<?php

$web = '_web_stub.php';

if (in_array('phar', stream_get_wrappers()) && class_exists('Phar', 0)) {
Phar::interceptFileFuncs();
set_include_path('phar://' . __FILE__ . PATH_SEPARATOR . get_include_path());
Phar::webPhar(null, $web);
include 'phar://' . __FILE__ . '/' . Extract_Phar::START;
return;
}

if (@(isset($_SERVER['REQUEST_URI']) && isset($_SERVER['REQUEST_METHOD']) && ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'POST'))) {
Extract_Phar::go(true);
$mimes = array(
'phps' => 2,
'c' => 'text/plain',
'cc' => 'text/plain',
'cpp' => 'text/plain',
'c++' => 'text/plain',
'dtd' => 'text/plain',
'h' => 'text/plain',
'log' => 'text/plain',
'rng' => 'text/plain',
'txt' => 'text/plain',
'xsd' => 'text/plain',
'php' => 1,
'inc' => 1,
'avi' => 'video/avi',
'bmp' => 'image/bmp',
'css' => 'text/css',
'gif' => 'image/gif',
'htm' => 'text/html',
'html' => 'text/html',
'htmls' => 'text/html',
'ico' => 'image/x-ico',
'jpe' => 'image/jpeg',
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'js' => 'application/x-javascript',
'midi' => 'audio/midi',
'mid' => 'audio/midi',
'mod' => 'audio/mod',
'mov' => 'movie/quicktime',
'mp3' => 'audio/mp3',
'mpg' => 'video/mpeg',
'mpeg' => 'video/mpeg',
'pdf' => 'application/pdf',
'png' => 'image/png',
'swf' => 'application/shockwave-flash',
'tif' => 'image/tiff',
'tiff' => 'image/tiff',
'wav' => 'audio/wav',
'xbm' => 'image/xbm',
'xml' => 'text/xml',
);

header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");

$basename = basename(__FILE__);
if (!strpos($_SERVER['REQUEST_URI'], $basename)) {
chdir(Extract_Phar::$temp);
include $web;
return;
}
$pt = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], $basename) + strlen($basename));
if (!$pt || $pt == '/') {
$pt = $web;
header('HTTP/1.1 301 Moved Permanently');
header('Location: ' . $_SERVER['REQUEST_URI'] . '/' . $pt);
exit;
}
$a = realpath(Extract_Phar::$temp . DIRECTORY_SEPARATOR . $pt);
if (!$a || strlen(dirname($a)) < strlen(Extract_Phar::$temp)) {
header('HTTP/1.0 404 Not Found');
echo "<html>\n <head>\n  <title>File Not Found<title>\n </head>\n <body>\n  <h1>404 - File ", $pt, " Not Found</h1>\n </body>\n</html>";
exit;
}
$b = pathinfo($a);
if (!isset($b['extension'])) {
header('Content-Type: text/plain');
header('Content-Length: ' . filesize($a));
readfile($a);
exit;
}
if (isset($mimes[$b['extension']])) {
if ($mimes[$b['extension']] === 1) {
include $a;
exit;
}
if ($mimes[$b['extension']] === 2) {
highlight_file($a);
exit;
}
header('Content-Type: ' .$mimes[$b['extension']]);
header('Content-Length: ' . filesize($a));
readfile($a);
exit;
}
}

class Extract_Phar
{
static $temp;
static $origdir;
const GZ = 0x1000;
const BZ2 = 0x2000;
const MASK = 0x3000;
const START = '_cli_stub.php';
const LEN = 6693;

static function go($return = false)
{
$fp = fopen(__FILE__, 'rb');
fseek($fp, self::LEN);
$L = unpack('V', $a = (binary)fread($fp, 4));
$m = (binary)'';

do {
$read = 8192;
if ($L[1] - strlen($m) < 8192) {
$read = $L[1] - strlen($m);
}
$last = (binary)fread($fp, $read);
$m .= $last;
} while (strlen($last) && strlen($m) < $L[1]);

if (strlen($m) < $L[1]) {
die('ERROR: manifest length read was "' .
strlen($m) .'" should be "' .
$L[1] . '"');
}

$info = self::_unpack($m);
$f = $info['c'];

if ($f & self::GZ) {
if (!function_exists('gzinflate')) {
die('Error: zlib extension is not enabled -' .
' gzinflate() function needed for zlib-compressed .phars');
}
}

if ($f & self::BZ2) {
if (!function_exists('bzdecompress')) {
die('Error: bzip2 extension is not enabled -' .
' bzdecompress() function needed for bz2-compressed .phars');
}
}

$temp = self::tmpdir();

if (!$temp || !is_writable($temp)) {
$sessionpath = session_save_path();
if (strpos ($sessionpath, ";") !== false)
$sessionpath = substr ($sessionpath, strpos ($sessionpath, ";")+1);
if (!file_exists($sessionpath) || !is_dir($sessionpath)) {
die('Could not locate temporary directory to extract phar');
}
$temp = $sessionpath;
}

$temp .= '/pharextract/'.basename(__FILE__, '.phar');
self::$temp = $temp;
self::$origdir = getcwd();
@mkdir($temp, 0777, true);
$temp = realpath($temp);

if (!file_exists($temp . DIRECTORY_SEPARATOR . md5_file(__FILE__))) {
self::_removeTmpFiles($temp, getcwd());
@mkdir($temp, 0777, true);
@file_put_contents($temp . '/' . md5_file(__FILE__), '');

foreach ($info['m'] as $path => $file) {
$a = !file_exists(dirname($temp . '/' . $path));
@mkdir(dirname($temp . '/' . $path), 0777, true);
clearstatcache();

if ($path[strlen($path) - 1] == '/') {
@mkdir($temp . '/' . $path, 0777);
} else {
file_put_contents($temp . '/' . $path, self::extractFile($path, $file, $fp));
@chmod($temp . '/' . $path, 0666);
}
}
}

chdir($temp);

if (!$return) {
include self::START;
}
}

static function tmpdir()
{
if (strpos(PHP_OS, 'WIN') !== false) {
if ($var = getenv('TMP') ? getenv('TMP') : getenv('TEMP')) {
return $var;
}
if (is_dir('/temp') || mkdir('/temp')) {
return realpath('/temp');
}
return false;
}
if ($var = getenv('TMPDIR')) {
return $var;
}
return realpath('/tmp');
}

static function _unpack($m)
{
$info = unpack('V', substr($m, 0, 4));
 $l = unpack('V', substr($m, 10, 4));
$m = substr($m, 14 + $l[1]);
$s = unpack('V', substr($m, 0, 4));
$o = 0;
$start = 4 + $s[1];
$ret['c'] = 0;

for ($i = 0; $i < $info[1]; $i++) {
 $len = unpack('V', substr($m, $start, 4));
$start += 4;
 $savepath = substr($m, $start, $len[1]);
$start += $len[1];
   $ret['m'][$savepath] = array_values(unpack('Va/Vb/Vc/Vd/Ve/Vf', substr($m, $start, 24)));
$ret['m'][$savepath][3] = sprintf('%u', $ret['m'][$savepath][3]
& 0xffffffff);
$ret['m'][$savepath][7] = $o;
$o += $ret['m'][$savepath][2];
$start += 24 + $ret['m'][$savepath][5];
$ret['c'] |= $ret['m'][$savepath][4] & self::MASK;
}
return $ret;
}

static function extractFile($path, $entry, $fp)
{
$data = '';
$c = $entry[2];

while ($c) {
if ($c < 8192) {
$data .= @fread($fp, $c);
$c = 0;
} else {
$c -= 8192;
$data .= @fread($fp, 8192);
}
}

if ($entry[4] & self::GZ) {
$data = gzinflate($data);
} elseif ($entry[4] & self::BZ2) {
$data = bzdecompress($data);
}

if (strlen($data) != $entry[0]) {
die("Invalid internal .phar file (size error " . strlen($data) . " != " .
$stat[7] . ")");
}

if ($entry[3] != sprintf("%u", crc32((binary)$data) & 0xffffffff)) {
die("Invalid internal .phar file (checksum error)");
}

return $data;
}

static function _removeTmpFiles($temp, $origdir)
{
chdir($temp);

foreach (glob('*') as $f) {
if (file_exists($f)) {
is_dir($f) ? @rmdir($f) : @unlink($f);
if (file_exists($f) && is_dir($f)) {
self::_removeTmpFiles($f, getcwd());
}
}
}

@rmdir($temp);
clearstatcache();
chdir($origdir);
}
}

Extract_Phar::go();
__HALT_COMPILER(); ?>
          phpDocumentor       LICENSE   gR   VD      	   README.md'  gR'  K1ﭶ         VERSION   gR   MѶ         bin/phpunit  gR  N          bin/compile}   gR}   ƶ         bin/phpdoc.bat   gR   T#         bin/phpdoc.php  gR  #         bin/utils/mem.shu  gRu           bin/utils/package.php  gR  W/      	   bin/behat  gR  :Z      	   bin/phpcs  gR  vHj      $   data/templates/new-black/sidebar.xsl  gR  U      &   data/templates/new-black/composer.json  gR  PӶ      $   data/templates/new-black/package.xml  gR  
.      '   data/templates/new-black/js/template.js  gR  /0      0   data/templates/new-black/css/jquery.treeview.css%  gR%  -~G      (   data/templates/new-black/css/default.css  gR  U<      +   data/templates/new-black/css/navigation.css@  gR@        S   data/templates/new-black/css/phpdoc/images/ui-bg_highlight-soft_40_aaaaaa_1x100.pngm   gRm   8      S   data/templates/new-black/css/phpdoc/images/ui-bg_highlight-soft_50_aaaaaa_1x100.pngf   gRf   K      S   data/templates/new-black/css/phpdoc/images/ui-bg_highlight-hard_65_232325_1x100.png{   gR{   Lশ      J   data/templates/new-black/css/phpdoc/images/ui-bg_glass_55_1c1c1c_1x400.png   gR   )ζ      F   data/templates/new-black/css/phpdoc/images/ui-icons_ededed_256x240.png  gR  <      F   data/templates/new-black/css/phpdoc/images/ui-icons_ffffff_256x240.png  gR  \      :   data/templates/new-black/css/phpdoc/images/icons/files.pngO  gRO  Aw7      >   data/templates/new-black/css/phpdoc/images/icons/dashboard.png  gR        <   data/templates/new-black/css/phpdoc/images/icons/reports.png   gR   @      ?   data/templates/new-black/css/phpdoc/images/icons/namespaces.png  gR  9!      :   data/templates/new-black/css/phpdoc/images/icons/chart.png-  gR-  #s      ?   data/templates/new-black/css/phpdoc/images/icons/chart15x12.png}  gR}  ]      9   data/templates/new-black/css/phpdoc/images/icons/book.png  gR  yIh      @   data/templates/new-black/css/phpdoc/images/icons/reports9x12.png-  gR-        =   data/templates/new-black/css/phpdoc/images/icons/packages.png  gR  /      F   data/templates/new-black/css/phpdoc/images/ui-icons_4ca300_256x240.png  gR  K      O   data/templates/new-black/css/phpdoc/images/ui-bg_inset-hard_55_ffeb80_1x100.pngq   gRq   /@      S   data/templates/new-black/css/phpdoc/images/ui-bg_highlight-hard_40_232325_1x100.pngw   gRw   {3      F   data/templates/new-black/css/phpdoc/images/ui-icons_bbbbbb_256x240.png  gR  ]Ҷ      F   data/templates/new-black/css/phpdoc/images/ui-icons_ffcf29_256x240.png  gR  &޶      T   data/templates/new-black/css/phpdoc/images/ui-bg_highlight-hard_100_f9f9f9_1x100.pngV   gRV   N5      O   data/templates/new-black/css/phpdoc/images/ui-bg_inset-hard_45_cd0a0a_1x100.png{   gR{   ;o      F   data/templates/new-black/css/phpdoc/images/ui-icons_222222_256x240.png  gR  7       L   data/templates/new-black/css/phpdoc/images/ui-bg_hexagon_15_232325_12x10.png   gR   ^Q      ?   data/templates/new-black/css/phpdoc/jquery-ui-1.8.16.custom.cssJ  gRJ  y>      ,   data/templates/new-black/css/images/plus.gifI  gRI  \M9      ,   data/templates/new-black/css/images/file.gifn   gRn   G~N      ?   data/templates/new-black/css/images/treeview-famfamfam-line.gif'  gR'  [〶      :   data/templates/new-black/css/images/treeview-gray-line.gifU  gRU  :h84      .   data/templates/new-black/css/images/folder.gifj   gRj   Zr      8   data/templates/new-black/css/images/treeview-default.gif  gR  k7      :   data/templates/new-black/css/images/treeview-famfamfam.gif   gR   t3      5   data/templates/new-black/css/images/folder-closed.gifi   gRi   ϶      -   data/templates/new-black/css/images/minus.gifE  gRE  N:      .   data/templates/new-black/css/images/search.gif   gR   Yb      ;   data/templates/new-black/css/images/treeview-black-line.gifU  gRU   3      6   data/templates/new-black/css/images/treeview-black.gif  gR  2      4   data/templates/new-black/css/images/treeview-red.gif  gR  &v      =   data/templates/new-black/css/images/treeview-default-line.gif  gR  9J      9   data/templates/new-black/css/images/treeview-red-line.gifU  gRU  5      3   data/templates/new-black/css/images/ajax-loader.gifO  gRO  =s      5   data/templates/new-black/css/images/treeview-gray.gif  gR  3      ,   data/templates/new-black/css/api-content.css  gR  D<ζ      )   data/templates/new-black/css/template.css  gR        *   data/templates/new-black/css/jquery-ui.css  gR  pg|      %   data/templates/new-black/template.xml
  gR
  =[      &   data/templates/new-black/composer.lock  gR  ?JK      (   data/templates/new-black/ajax_search.php  gR  qdŶ      *   data/templates/new-black/search/simple.xsl	  gR	  Y+      (   data/templates/new-black/search/ajax.xslw  gRw  }@      #   data/templates/abstract/sidebar.xsli  gRi  .Ƕ      #   data/templates/abstract/api-doc.xsll  gRl  Ը      %   data/templates/abstract/composer.jsonw  gRw  {Nz      #   data/templates/abstract/package.xml  gR  ն      -   data/templates/abstract/report_deprecated.xslZ
  gRZ
  ~/Z      !   data/templates/abstract/index.xslX  gRX  ځd      .   data/templates/abstract/js/jquery-1.7.1.min.js gR G      &   data/templates/abstract/js/template.js  gR  cd=      +   data/templates/abstract/js/bootstrap.min.jsdl  gRdl  p?      0   data/templates/abstract/css/font-awesome.min.csstE  gRtE  ~i      (   data/templates/abstract/css/abstract.cssk  gRk  ݶ      (   data/templates/abstract/css/template.css   gR   Nd      -   data/templates/abstract/css/bootstrap.min.css gR 0      '   data/templates/abstract/graph_class.xsln  gRn  ._         data/templates/abstract/README3  gR3  0ߚ      #   data/templates/abstract/content.xsl  gR  1ʶ      ,   data/templates/abstract/api-doc/function.xslR  gRR  ֶ      ,   data/templates/abstract/api-doc/docblock.xsl]!  gR]!  ob      ,   data/templates/abstract/api-doc/property.xsl  gR  Ov      (   data/templates/abstract/api-doc/file.xsl  gR  qx&"      ,   data/templates/abstract/api-doc/constant.xsl  gR        )   data/templates/abstract/api-doc/class.xsl  gR  cU5      0   data/templates/abstract/report_parse_markers.xsl
  gR
  VfW      $   data/templates/abstract/template.xml	  gR	  LB      %   data/templates/abstract/composer.lock  gR  8pC      /   data/templates/abstract/images/collapse_all.png  gR  ѫ>      '   data/templates/abstract/images/logo.png  gR  9      1   data/templates/abstract/images/icons/function.png  gR  p      3   data/templates/abstract/images/icons/arrow_down.png^  gR^  8V      1   data/templates/abstract/images/icons/constant.pngW  gRW  IH`      4   data/templates/abstract/images/icons/view_source.png[  gR[  EQ      -   data/templates/abstract/images/icons/file.gifn   gRn   G~N      =   data/templates/abstract/images/icons/visibility_protected.png  gR  m      4   data/templates/abstract/images/icons/arrow_right.pngt  gRt  tF      :   data/templates/abstract/images/icons/visibility_public.png{  gR{  /s      /   data/templates/abstract/images/icons/folder.gifj   gRj   Zr      0   data/templates/abstract/images/icons/favicon.ico~  gR~        .   data/templates/abstract/images/icons/class.png  gR  Å      /   data/templates/abstract/images/icons/search.gif   gR   >      2   data/templates/abstract/images/icons/interface.png  gR  ǛL      ;   data/templates/abstract/images/icons/visibility_private.pngi  gRi        1   data/templates/abstract/images/icons/variable.png=  gR=  &      /   data/templates/abstract/images/icons/method.png  gR  k      +   data/templates/abstract/images/icons/ok.pnge  gRe  "      1   data/templates/abstract/images/icons/property.pngB  gRB  {w~      1   data/templates/abstract/images/icons/file-php.png  gR  	.      -   data/templates/abstract/images/expand_all.png  gR  ZU      )   data/templates/abstract/images/search.gif   gR   Yb      -   data/templates/abstract/fonts/FontAwesome.otf  gR  Ƕ      6   data/templates/abstract/fonts/fontawesome-webfont.woff  gR  Ue      5   data/templates/abstract/fonts/fontawesome-webfont.svg gR 
H      5   data/templates/abstract/fonts/fontawesome-webfont.ttf; gR; ꃹ      5   data/templates/abstract/fonts/fontawesome-webfont.eot=  gR=  jz      *   data/templates/abstract/report_markers.xsl  gR  áI      #   data/templates/abstract/helpers.xsl  gR        *   data/templates/abstract/sidebar/header.xsl?  gR?  i`      *   data/templates/abstract/sidebar/footer.xsl  gR  o5      5   data/templates/abstract/sidebar/sections/packages.xsl+  gR+  :}      2   data/templates/abstract/sidebar/sections/files.xslI  gRI  _      7   data/templates/abstract/sidebar/sections/namespaces.xsl}	  gR}	  6      0   data/templates/abstract/sidebar/sections/api.xsl7  gR7  sfy      3   data/templates/abstract/sidebar/sections/charts.xsll  gRl  s      4   data/templates/abstract/sidebar/sections/reports.xsl3  gR3        )   data/templates/abstract/chrome/header.xsl/  gR/  Q      )   data/templates/abstract/chrome/footer.xsl  gR  E`      "   data/templates/abstract/chrome.xslR  gRR  ߯c      &   data/templates/old-ocean/composer.json  gR  H'X      $   data/templates/old-ocean/package.xml  gR  ތ?      *   data/templates/old-ocean/parse_markers.xsl
  gR
  (      $   data/templates/old-ocean/markers.xsl7  gR7  ζ      "   data/templates/old-ocean/index.xsl  gR  FNs      /   data/templates/old-ocean/js/jquery-1.7.1.min.js gR G      &   data/templates/old-ocean/js/sidebar.js  gR        9   data/templates/old-ocean/js/jquery-ui-1.8.2.custom.min.js( gR(        -   data/templates/old-ocean/js/jquery.panzoom.js9  gR9  [      /   data/templates/old-ocean/js/jquery.tools.min.jsõ  gRõ  t*ݶ      .   data/templates/old-ocean/js/jquery.treeview.jsH   gRH   nY      /   data/templates/old-ocean/js/jquery-1.4.2.min.js gR 4       .   data/templates/old-ocean/js/jquery.splitter.js-  gR-  U      %   data/templates/old-ocean/js/SVGPan.js  gR  @      ,   data/templates/old-ocean/js/jquery.cookie.js  gR  +B      #   data/templates/old-ocean/js/menu.js  gR  E<F      0   data/templates/old-ocean/css/jquery.treeview.css  gR  Ƕ      (   data/templates/old-ocean/css/default.cssm  gRm  _zU      ,   data/templates/old-ocean/css/images/plus.gifI  gRI  \M9      ,   data/templates/old-ocean/css/images/file.gifn   gRn   G~N      ?   data/templates/old-ocean/css/images/treeview-famfamfam-line.gif'  gR'  [〶      :   data/templates/old-ocean/css/images/treeview-gray-line.gifU  gRU  :h84      .   data/templates/old-ocean/css/images/folder.gifj   gRj   Zr      8   data/templates/old-ocean/css/images/treeview-default.gif  gR  k7      :   data/templates/old-ocean/css/images/treeview-famfamfam.gif   gR   t3      5   data/templates/old-ocean/css/images/folder-closed.gifi   gRi   ϶      -   data/templates/old-ocean/css/images/minus.gifE  gRE  N:      ;   data/templates/old-ocean/css/images/treeview-black-line.gifU  gRU   3      6   data/templates/old-ocean/css/images/treeview-black.gif  gR  2      4   data/templates/old-ocean/css/images/treeview-red.gif  gR  &v      =   data/templates/old-ocean/css/images/treeview-default-line.gif  gR  9J      9   data/templates/old-ocean/css/images/treeview-red-line.gifU  gRU  5      3   data/templates/old-ocean/css/images/ajax-loader.gifO  gRO  =s      5   data/templates/old-ocean/css/images/treeview-gray.gif  gR  3      V   data/templates/old-ocean/css/black-tie/images/ui-bg_diagonals-thick_8_333333_40x40.png   gR   j      V   data/templates/old-ocean/css/black-tie/images/ui-bg_highlight-soft_50_aaaaaa_1x100.pngf   gRf   K      M   data/templates/old-ocean/css/black-tie/images/ui-bg_glass_55_1c1c1c_1x400.png   gR   b'      M   data/templates/old-ocean/css/black-tie/images/ui-bg_flat_65_ffffff_40x100.png   gR   Yo      M   data/templates/old-ocean/css/black-tie/images/ui-bg_glass_40_111111_1x400.png|   gR|   yZ6      I   data/templates/old-ocean/css/black-tie/images/ui-icons_ededed_256x240.png  gR  uz      I   data/templates/old-ocean/css/black-tie/images/ui-icons_ffffff_256x240.png  gR  \      V   data/templates/old-ocean/css/black-tie/images/ui-bg_highlight-hard_40_aaaaaa_1x100.pngd   gRd   ̶      I   data/templates/old-ocean/css/black-tie/images/ui-icons_4ca300_256x240.png  gR  K      R   data/templates/old-ocean/css/black-tie/images/ui-bg_inset-hard_55_ffeb80_1x100.pngq   gRq   /@      I   data/templates/old-ocean/css/black-tie/images/ui-icons_bbbbbb_256x240.png  gR  ]Ҷ      I   data/templates/old-ocean/css/black-tie/images/ui-icons_ffcf29_256x240.png  gR  RJ      E   data/templates/old-ocean/css/black-tie/images/ui-anim_basic_16x16.gif  gR  {0      W   data/templates/old-ocean/css/black-tie/images/ui-bg_highlight-hard_100_f9f9f9_1x100.pngV   gRV   N5      R   data/templates/old-ocean/css/black-tie/images/ui-bg_inset-hard_45_cd0a0a_1x100.png{   gR{   ;o      I   data/templates/old-ocean/css/black-tie/images/ui-icons_222222_256x240.png  gR  7       A   data/templates/old-ocean/css/black-tie/jquery-ui-1.8.2.custom.cssl{  gRl{  WN         data/templates/old-ocean/README    gR              !   data/templates/old-ocean/file.xsl   gR   
|i      %   data/templates/old-ocean/template.xml  gR  G5      4   data/templates/old-ocean/preprocess/object-index.xsl  gR  U|Ŷ      &   data/templates/old-ocean/composer.lock  gR  IMnȶ      '   data/templates/old-ocean/images/top.png  gR  $      2   data/templates/old-ocean/images/icons/function.png  gR  p      4   data/templates/old-ocean/images/icons/arrow_down.png^  gR^  8V      2   data/templates/old-ocean/images/icons/constant.pngW  gRW  IH`      5   data/templates/old-ocean/images/icons/view_source.png[  gR[  EQ      .   data/templates/old-ocean/images/icons/file.gifn   gRn   G~N      >   data/templates/old-ocean/images/icons/visibility_protected.png  gR  m      5   data/templates/old-ocean/images/icons/arrow_right.pngt  gRt  tF      ;   data/templates/old-ocean/images/icons/visibility_public.png{  gR{  /s      0   data/templates/old-ocean/images/icons/folder.gifj   gRj   Zr      1   data/templates/old-ocean/images/icons/favicon.ico~  gR~        /   data/templates/old-ocean/images/icons/class.png  gR  Å      0   data/templates/old-ocean/images/icons/search.gif   gR   >      3   data/templates/old-ocean/images/icons/interface.png  gR  ǛL      <   data/templates/old-ocean/images/icons/visibility_private.pngi  gRi        2   data/templates/old-ocean/images/icons/variable.png=  gR=  &      0   data/templates/old-ocean/images/icons/method.png  gR  k      ,   data/templates/old-ocean/images/icons/ok.pnge  gRe  "      2   data/templates/old-ocean/images/icons/property.pngB  gRB  {w~      2   data/templates/old-ocean/images/icons/file-php.png  gR  	.      /   data/templates/old-ocean/images/top-stopper.png  gR  m$      3   data/templates/old-ocean/images/menu-background.png   gR   o      .   data/templates/old-ocean/images/background.png:  gR:  l      2   data/templates/old-ocean/images/top-background.png   gR   8      !   data/templates/old-ocean/menu.xsl-  gR-  2׶      '   data/templates/old-ocean/classgraph.xsl  gR  O      "   data/templates/old-ocean/class.xsl-  gR-  "      #   data/templates/old-ocean/search.xsl  gR  LԐ      #   data/templates/old-ocean/chrome.xsl  gR            data/templates/xml/composer.jsonl  gRl  J){[         data/templates/xml/template.xmlb  gRb  ˠ          data/templates/xml/composer.lock  gR  h      #   data/templates/clean/file.html.twig&  gR&  ]@߶      "   data/templates/clean/composer.json  gR  9k      (   data/templates/clean/namespace.html.twigB  gRB  A˥      .   data/templates/clean/reports/markers.html.twig
  gR
  1      -   data/templates/clean/reports/errors.html.twig
  gR
        1   data/templates/clean/reports/deprecated.html.twig  gR  &q      -   data/templates/clean/js/jquery.iviewer.min.jsCF  gRCF  vb      )   data/templates/clean/js/jquery.iviewer.js9  gR9        /   data/templates/clean/js/jquery.smooth-scroll.js9  gR9  c^      5   data/templates/clean/js/jquery.dotdotdot-1.5.9.min.js  gR  "$      $   data/templates/clean/js/prism.min.js.  gR.        1   data/templates/clean/js/jquery.dotdotdot-1.5.9.js*  gR*  	      <   data/templates/clean/css/phpdocumentor-clean-icons/style.css?  gR?  DE      V   data/templates/clean/css/phpdocumentor-clean-icons/fonts/phpdocumentor-clean-icons.ttf   gR   @f      V   data/templates/clean/css/phpdocumentor-clean-icons/fonts/phpdocumentor-clean-icons.svgN  gRN  =      V   data/templates/clean/css/phpdocumentor-clean-icons/fonts/phpdocumentor-clean-icons.eot	  gR	  ˲      Z   data/templates/clean/css/phpdocumentor-clean-icons/fonts/phpdocumentor-clean-icons.dev.svg  gR  ٩Ո      W   data/templates/clean/css/phpdocumentor-clean-icons/fonts/phpdocumentor-clean-icons.woff(  gR(        >   data/templates/clean/css/phpdocumentor-clean-icons/Read Me.txtV  gRV  o      =   data/templates/clean/css/phpdocumentor-clean-icons/lte-ie7.js  gR  ;O;      "   data/templates/clean/css/prism.css  gR  Cy      +   data/templates/clean/css/jquery.iviewer.css  gR  ,~be      %   data/templates/clean/css/template.cssW   gRW   1Ƕ      !   data/templates/clean/template.xmlG  gRG  |      "   data/templates/clean/composer.lock  gR  c蒶      +   data/templates/clean/graphs/class.html.twig  gR  /S      .   data/templates/clean/images/icon-interface.svg  gR  Ʉ"      0   data/templates/clean/images/icon-trait-13x13.pngT  gRT   a      .   data/templates/clean/images/hierarchy-item.png   gR   vĶ      8   data/templates/clean/images/apple-touch-icon-114x114.pngn  gRn  l      0   data/templates/clean/images/apple-touch-icon.png   gR   u      4   data/templates/clean/images/icon-interface-13x13.png4  gR4         *   data/templates/clean/images/icon-trait.svg  gR  Ŷ      '   data/templates/clean/images/favicon.ico~  gR~  \W      *   data/templates/clean/images/icon-class.svg  gR  "<      ,   data/templates/clean/images/custom-icons.svgE  gRE  }}2      ;   data/templates/clean/images/iviewer/iviewer.rotate_left.png  gR  tm      8   data/templates/clean/images/iviewer/iviewer.zoom_fit.png  gR  2ж      7   data/templates/clean/images/iviewer/iviewer.zoom_in.png  gR  M ז      8   data/templates/clean/images/iviewer/iviewer.zoom_out.png  gR  ^      ,   data/templates/clean/images/iviewer/grab.cur~  gR~  '2      ,   data/templates/clean/images/iviewer/hand.cur~  gR~  hګ      9   data/templates/clean/images/iviewer/iviewer.zoom_zero.pngC  gRC        <   data/templates/clean/images/iviewer/iviewer.rotate_right.png  gR  -Ģ϶      6   data/templates/clean/images/apple-touch-icon-72x72.png1  gR1  C      0   data/templates/clean/images/icon-class-13x13.png  gR  c      $   data/templates/clean/class.html.twig|=  gR|=  <UN      %   data/templates/clean/layout.html.twig0  gR0  ik0      )   data/templates/clean/file.source.txt.twig   gR   If`      (   data/templates/clean/interface.html.twig'  gR'  Զ      :   data/templates/clean/elements/namespaces.sidebar.html.twig  gR  Zg      0   data/templates/clean/elements/property.html.twig  gR  9+      .   data/templates/clean/elements/method.html.twig  gR  E
t      0   data/templates/clean/elements/constant.html.twigB  gRB  'Q      !   data/templates/zend/composer.json  gR  A         data/templates/zend/package.xmlJ
  gRJ
  ؿ         data/templates/zend/index.xsl  gR  _z      "   data/templates/zend/js/template.js  gR  cd=      "   data/templates/zend/css/manual.css  gR  (]h      $   data/templates/zend/css/template.cssp  gRp           data/templates/zend/READMEU   gRU   Q          data/templates/zend/template.xml
  gR
  ^      !   data/templates/zend/composer.lock  gR  ]]x      .   data/templates/zend/images/behind-the-site.gif  gR  <      #   data/templates/zend/page_header.xsl  gR  UY      '   data/templates/checkstyle/composer.json  gR        %   data/templates/checkstyle/package.xml+  gR+  |-Ӷ          data/templates/checkstyle/README    gR              &   data/templates/checkstyle/template.xmlL  gRL  XF      '   data/templates/checkstyle/composer.lock  gR  ?{      '   data/templates/responsive/composer.json}  gR}  m      $   data/templates/responsive/layout.xsl,  gR,  ;4~      %   data/templates/responsive/package.xml  gR  +-f?      &   data/templates/responsive/packages.xsl  gR  E=      -   data/templates/responsive/reports/markers.xsln  gRn  {g      ,   data/templates/responsive/reports/errors.xsl  gR  x}:      0   data/templates/responsive/reports/deprecated.xsl  gR  Ē      )   data/templates/responsive/search.json.xsl  gR  ]\G      #   data/templates/responsive/index.xsl  gR  ,)      :   data/templates/responsive/img/apple-touch-icon-114x114.pngn  gRn  l      2   data/templates/responsive/img/apple-touch-icon.png   gR   u      <   data/templates/responsive/img/glyphicons-halflings-white.png   gR   2zǶ      0   data/templates/responsive/img/icons/function.pngR  gRR  K+H      3   data/templates/responsive/img/icons/icon-th-big.pngj   gRj   s̶      2   data/templates/responsive/img/icons/arrow_down.png^  gR^  8V      0   data/templates/responsive/img/icons/constant.png  gR  0A׶      3   data/templates/responsive/img/icons/view_source.png[  gR[  EQ      ,   data/templates/responsive/img/icons/file.gifn   gRn   G~N      <   data/templates/responsive/img/icons/visibility_protected.png  gR  m      3   data/templates/responsive/img/icons/arrow_right.pngt  gRt  tF      5   data/templates/responsive/img/icons/icon_template.svgX  gRX   /      9   data/templates/responsive/img/icons/visibility_public.png{  gR{  /s      .   data/templates/responsive/img/icons/folder.gifj   gRj   Zr      /   data/templates/responsive/img/icons/favicon.ico~  gR~        -   data/templates/responsive/img/icons/class.png  gR  JX      .   data/templates/responsive/img/icons/search.gif   gR   >      1   data/templates/responsive/img/icons/interface.png  gR  WG      :   data/templates/responsive/img/icons/visibility_private.pngi  gRi        0   data/templates/responsive/img/icons/variable.png=  gR=  &      .   data/templates/responsive/img/icons/method.pngy  gRy  ?`0Ƕ      *   data/templates/responsive/img/icons/ok.pnge  gRe  "      0   data/templates/responsive/img/icons/property.pngh  gRh        0   data/templates/responsive/img/icons/file-php.png  gR  	.      <   data/templates/responsive/img/icons/icon-folder-open-big.png   gR         )   data/templates/responsive/img/favicon.ico~  gR~  \W      6   data/templates/responsive/img/glyphicons-halflings.png   gR   !˶      ;   data/templates/responsive/img/iviewer/iviewer.zoom_fit2.gif_   gR_   &      =   data/templates/responsive/img/iviewer/iviewer.rotate_left.png  gR  tm      :   data/templates/responsive/img/iviewer/iviewer.zoom_fit.png  gR  2ж      9   data/templates/responsive/img/iviewer/iviewer.zoom_in.png  gR  M ז      :   data/templates/responsive/img/iviewer/iviewer.zoom_in2.gifZ   gRZ   *      :   data/templates/responsive/img/iviewer/iviewer.zoom_out.png  gR  ^      .   data/templates/responsive/img/iviewer/grab.cur~  gR~  '2      <   data/templates/responsive/img/iviewer/iviewer.zoom_zero2.gifb   gRb   L7      .   data/templates/responsive/img/iviewer/hand.cur~  gR~  hګ      ;   data/templates/responsive/img/iviewer/iviewer.zoom_out2.gifE   gRE   t      ;   data/templates/responsive/img/iviewer/iviewer.zoom_zero.pngC  gRC        >   data/templates/responsive/img/iviewer/iviewer.rotate_right.png  gR  -Ģ϶      8   data/templates/responsive/img/apple-touch-icon-72x72.png1  gR1  C      (   data/templates/responsive/img/loader.gifv  gRv   z      2   data/templates/responsive/js/jquery.iviewer.min.jsR=  gRR=  9      0   data/templates/responsive/js/jquery-1.7.1.min.js gR G      '   data/templates/responsive/js/sidebar.js  gR        :   data/templates/responsive/js/jquery-ui-1.8.2.custom.min.js( gR(        .   data/templates/responsive/js/jquery.panzoom.js9  gR9  [      (   data/templates/responsive/js/template.js
  gR
        .   data/templates/responsive/js/jquery.iviewer.js:  gR:  `YĶ      0   data/templates/responsive/js/jquery.tools.min.jsõ  gRõ  t*ݶ      /   data/templates/responsive/js/jquery.treeview.jsH   gRH   nY      -   data/templates/responsive/js/bootstrap.min.jsP  gRP  @h}-      )   data/templates/responsive/js/bootstrap.js#  gR#  -#3      0   data/templates/responsive/js/jquery-1.4.2.min.js gR 4       2   data/templates/responsive/js/prettify/lang-yaml.js  gR  ,I      0   data/templates/responsive/js/prettify/lang-go.js  gR  ZO      3   data/templates/responsive/js/prettify/lang-scala.js  gR  (      1   data/templates/responsive/js/prettify/lang-clj.js  gR  ޤ      5   data/templates/responsive/js/prettify/prettify.min.js@5  gR@5  ;J      /   data/templates/responsive/js/prettify/lang-n.jsx  gRx  V7e      0   data/templates/responsive/js/prettify/lang-hs.js9  gR9  uk3V      2   data/templates/responsive/js/prettify/lang-wiki.js  gR        0   data/templates/responsive/js/prettify/lang-vb.js  gR  .+      2   data/templates/responsive/js/prettify/lang-vhdl.js  gR  ն      1   data/templates/responsive/js/prettify/lang-lua.js(  gR(  ʥҥ      1   data/templates/responsive/js/prettify/lang-tex.js  gR  Cٶ      1   data/templates/responsive/js/prettify/lang-sql.js  gR  7h      1   data/templates/responsive/js/prettify/lang-css.js]  gR]  ,z      3   data/templates/responsive/js/prettify/lang-proto.js.  gR.         4   data/templates/responsive/js/prettify/lang-apollo.js  gR  E      0   data/templates/responsive/js/prettify/lang-xq.jsZ  gRZ  ċO      0   data/templates/responsive/js/prettify/lang-ml.jsQ  gRQ  S      2   data/templates/responsive/js/prettify/lang-lisp.js  gR  9׶      5   data/templates/responsive/js/jquery.mousewheel.min.jsh  gRh  7!x      /   data/templates/responsive/js/jquery.splitter.js-  gR-  U      &   data/templates/responsive/js/SVGPan.js  gR  @      -   data/templates/responsive/js/jquery.cookie.js  gR  +B      $   data/templates/responsive/js/menu.js  gR  E<F      0   data/templates/responsive/css/jquery.iviewer.css3  gR3  Զ      :   data/templates/responsive/css/bootstrap-responsive.min.css   gR   p       6   data/templates/responsive/css/bootstrap-responsive.css/)  gR/)  6      *   data/templates/responsive/css/template.css$  gR$  nIt      /   data/templates/responsive/css/bootstrap.min.cssU gRU 1      +   data/templates/responsive/css/bootstrap.cssZ> gRZ> I~      *   data/templates/responsive/css/prettify.css  gR  l Զ      $   data/templates/responsive/graph.html  gR  t`V      (   data/templates/responsive/namespaces.xsl  gR  h>      &   data/templates/responsive/template.xml@  gR@  z      '   data/templates/responsive/composer.lock  gR  3      *   data/templates/responsive/graphs/class.xsl  gR  ko      #   data/templates/responsive/class.xslH  gRH  H      /   data/templates/responsive/elements/function.xslq  gRq  38^i      .   data/templates/responsive/elements/package.xsl  gR  ]Je      /   data/templates/responsive/elements/property.xsl  gR  %      0   data/templates/responsive/elements/namespace.xsl  gR  B      /   data/templates/responsive/elements/constant.xsl  gR  cÌ      -   data/templates/responsive/elements/common.xsl-#  gR-#  v      ,   data/templates/responsive/elements/class.xsl/&  gR/&  NS      4   data/templates/responsive-twig/base/macros.html.twig   gR         5   data/templates/responsive-twig/base/sidebar.html.twig   gR   K      ;   data/templates/responsive-twig/base/class.sidebar.html.twig(  gR(  ̃      ,   data/templates/responsive-twig/composer.jsons  gRs  B      2   data/templates/responsive-twig/namespace.html.twig  gR  0      8   data/templates/responsive-twig/reports/markers.html.twigk
  gRk
   y      7   data/templates/responsive-twig/reports/errors.html.twigM  gRM  N      ;   data/templates/responsive-twig/reports/deprecated.html.twige  gRe  ٹ      0   data/templates/responsive-twig/package.html.twig  gR  &_      .   data/templates/responsive-twig/index.html.twig  gR  q      +   data/templates/responsive-twig/template.xmlJ  gRJ  h)      5   data/templates/responsive-twig/graphs/class.html.twig  gR  aE      .   data/templates/responsive-twig/class.html.twig0  gR0  0      /   data/templates/responsive-twig/layout.html.twig  gR  oȶ         data/phpdoc.tpl.xmlO  gRO  -)      0   src/Cilex/Providers/ValidatorServiceProvider.php  gR        &   src/phpDocumentor/Event/Dispatcher.php
  gR
  U.!J      &   src/phpDocumentor/Event/DebugEvent.php  gR  kG/      )   src/phpDocumentor/Event/EventAbstract.php  gR  l      $   src/phpDocumentor/Event/LogEvent.php\  gR\  /9Ͷ      1   src/phpDocumentor/Command/ConfigurableCommand.php  gR   lJ      %   src/phpDocumentor/Command/Command.php	  gR	        0   src/phpDocumentor/Command/Project/RunCommand.php(  gR(  o϶      1   src/phpDocumentor/Command/Helper/LoggerHelper.php  gR  r/      !   src/phpDocumentor/Application.php.  gR.  6      &   src/phpDocumentor/Partials/Partial.php  gR  b'l      )   src/phpDocumentor/Partials/Collection.php_  gR_  SRƶ         src/phpDocumentor/Bootstrap.php  gR  (~      ,   src/phpDocumentor/Compiler/Linker/Linker.php  gR  "*      4   src/phpDocumentor/Compiler/CompilerPassInterface.php  gR  Oh      8   src/phpDocumentor/Compiler/Pass/NamespaceTreeBuilder.php8  gR8  T      )   src/phpDocumentor/Compiler/Pass/Debug.php  gR  Cɶ      ;   src/phpDocumentor/Compiler/Pass/MarkerFromTagsExtractor.php  gR  oy"      8   src/phpDocumentor/Compiler/Pass/ElementsIndexBuilder.phpt  gRt  >      6   src/phpDocumentor/Compiler/Pass/PackageTreeBuilder.php1  gR1  aM      '   src/phpDocumentor/Compiler/Compiler.php  gR  93          src/phpDocumentor/Translator.php  gR  i?      9   src/phpDocumentor/Descriptor/ProjectDescriptorBuilder.php  gR  Tlo      2   src/phpDocumentor/Descriptor/ProjectDescriptor.php  gR  `IV      3   src/phpDocumentor/Descriptor/DescriptorAbstract.php,  gR,  X^      0   src/phpDocumentor/Descriptor/TraitDescriptor.php  gR  h      >   src/phpDocumentor/Descriptor/Cache/ProjectDescriptorMapper.php  gR  ':      +   src/phpDocumentor/Descriptor/Collection.php  gR  ,揶      A   src/phpDocumentor/Descriptor/Builder/Reflector/ClassAssembler.php;  gR;  \      D   src/phpDocumentor/Descriptor/Builder/Reflector/ConstantAssembler.php  gR  qw      E   src/phpDocumentor/Descriptor/Builder/Reflector/InterfaceAssembler.php  gR  *      D   src/phpDocumentor/Descriptor/Builder/Reflector/PropertyAssembler.php  gR  Ɓ      B   src/phpDocumentor/Descriptor/Builder/Reflector/MethodAssembler.php  gR  1@X      A   src/phpDocumentor/Descriptor/Builder/Reflector/TraitAssembler.php  gR  >      @   src/phpDocumentor/Descriptor/Builder/Reflector/FileAssembler.php  gR  >      K   src/phpDocumentor/Descriptor/Builder/Reflector/Tags/DeprecatedAssembler.php  gR        G   src/phpDocumentor/Descriptor/Builder/Reflector/Tags/ReturnAssembler.php  gR  _v      E   src/phpDocumentor/Descriptor/Builder/Reflector/Tags/UsesAssembler.php  gR  j      G   src/phpDocumentor/Descriptor/Builder/Reflector/Tags/AuthorAssembler.php_  gR_  vk϶      G   src/phpDocumentor/Descriptor/Builder/Reflector/Tags/ThrowsAssembler.php  gR  8fd      F   src/phpDocumentor/Descriptor/Builder/Reflector/Tags/ParamAssembler.php  gR  x      D   src/phpDocumentor/Descriptor/Builder/Reflector/Tags/SeeAssembler.phpQ  gRQ  -1      I   src/phpDocumentor/Descriptor/Builder/Reflector/Tags/PropertyAssembler.php  gR  +ܶ      G   src/phpDocumentor/Descriptor/Builder/Reflector/Tags/MethodAssembler.php  gR  u{t      H   src/phpDocumentor/Descriptor/Builder/Reflector/Tags/VersionAssembler.php  gR  9_i      K   src/phpDocumentor/Descriptor/Builder/Reflector/Tags/GenericTagAssembler.phpF  gRF  Mb;      E   src/phpDocumentor/Descriptor/Builder/Reflector/Tags/LinkAssembler.php  gR  s      D   src/phpDocumentor/Descriptor/Builder/Reflector/Tags/VarAssembler.php  gR  Ϝf      F   src/phpDocumentor/Descriptor/Builder/Reflector/Tags/SinceAssembler.php  gR  'A賶      D   src/phpDocumentor/Descriptor/Builder/Reflector/AssemblerAbstract.php
  gR
  U%      D   src/phpDocumentor/Descriptor/Builder/Reflector/ArgumentAssembler.phpD  gRD  ʶ      D   src/phpDocumentor/Descriptor/Builder/Reflector/FunctionAssembler.php  gR  Ð      ;   src/phpDocumentor/Descriptor/Builder/AssemblerInterface.php  gR  N      :   src/phpDocumentor/Descriptor/Builder/AssemblerAbstract.php|  gR|  ^϶      9   src/phpDocumentor/Descriptor/Builder/AssemblerFactory.php(	  gR(	  ~      0   src/phpDocumentor/Descriptor/ClassDescriptor.phpI   gRI   k      0   src/phpDocumentor/Descriptor/Validator/Error.php  gR  v      0   src/phpDocumentor/Descriptor/ProjectAnalyzer.php
  gR
  !n      4   src/phpDocumentor/Descriptor/InterfaceDescriptor.phpf  gRf  G'9      3   src/phpDocumentor/Descriptor/Filter/StripIgnore.php  gR  $      5   src/phpDocumentor/Descriptor/Filter/StripInternal.php#	  gR#	  *      .   src/phpDocumentor/Descriptor/Filter/Filter.php  gR  Gж      4   src/phpDocumentor/Descriptor/Filter/ClassFactory.phpA  gRA        2   src/phpDocumentor/Descriptor/Filter/Filterable.php  gR  ㊠%      4   src/phpDocumentor/Descriptor/NamespaceDescriptor.php  gR  ;W      /   src/phpDocumentor/Descriptor/FileDescriptor.php%  gR%  ?hWS      0   src/phpDocumentor/Descriptor/ServiceProvider.phpC  gRC  J8      9   src/phpDocumentor/Descriptor/Interfaces/BaseInterface.php	  gR	  &      =   src/phpDocumentor/Descriptor/Interfaces/ConstantInterface.php!  gR!  {      9   src/phpDocumentor/Descriptor/Interfaces/FileInterface.php(  gR(  o      =   src/phpDocumentor/Descriptor/Interfaces/FunctionInterface.php  gR  ?zٶ      >   src/phpDocumentor/Descriptor/Interfaces/InterfaceInterface.php%  gR%  c'      :   src/phpDocumentor/Descriptor/Interfaces/TraitInterface.php  gR  rp      >   src/phpDocumentor/Descriptor/Interfaces/ContainerInterface.phpO  gRO  Cک      =   src/phpDocumentor/Descriptor/Interfaces/ArgumentInterface.php
  gR
        ;   src/phpDocumentor/Descriptor/Interfaces/MethodInterface.php  gR  Hw      :   src/phpDocumentor/Descriptor/Interfaces/ClassInterface.php  gR  殮o      :   src/phpDocumentor/Descriptor/Interfaces/ChildInterface.php  gR   PZl      =   src/phpDocumentor/Descriptor/Interfaces/PropertyInterface.php  gR  W      <   src/phpDocumentor/Descriptor/Interfaces/ProjectInterface.php0  gR0  ݶ      <   src/phpDocumentor/Descriptor/Interfaces/PackageInterface.php  gR  WĒB      >   src/phpDocumentor/Descriptor/Interfaces/NamespaceInterface.php7  gR7  ;      3   src/phpDocumentor/Descriptor/ArgumentDescriptor.php  gR  (      ;   src/phpDocumentor/Descriptor/ProjectDescriptor/Settings.php@  gR@  `~յ      3   src/phpDocumentor/Descriptor/FunctionDescriptor.php  gR  N      2   src/phpDocumentor/Descriptor/PackageDescriptor.php  gR        3   src/phpDocumentor/Descriptor/PropertyDescriptor.php  gR  Hz      E   src/phpDocumentor/Descriptor/Exception/MissingDependencyException.php  gR  Z      .   src/phpDocumentor/Descriptor/TagDescriptor.phpO  gRO  -N      1   src/phpDocumentor/Descriptor/MethodDescriptor.php  gR  f      3   src/phpDocumentor/Descriptor/ConstantDescriptor.php  gR  a{      5   src/phpDocumentor/Descriptor/Tag/ReturnDescriptor.php  gR  w      2   src/phpDocumentor/Descriptor/Tag/SeeDescriptor.php  gR  ބp      5   src/phpDocumentor/Descriptor/Tag/ThrowsDescriptor.php  gR  ,"      4   src/phpDocumentor/Descriptor/Tag/SinceDescriptor.php  gR  |ꥶ      9   src/phpDocumentor/Descriptor/Tag/DeprecatedDescriptor.php  gR  p<      4   src/phpDocumentor/Descriptor/Tag/ParamDescriptor.php  gR  IC      6   src/phpDocumentor/Descriptor/Tag/VersionDescriptor.php  gR  qt0      7   src/phpDocumentor/Descriptor/Tag/PropertyDescriptor.php  gR  ɠ      5   src/phpDocumentor/Descriptor/Tag/AuthorDescriptor.php  gR  SgĽ      2   src/phpDocumentor/Descriptor/Tag/VarDescriptor.php  gR  -      5   src/phpDocumentor/Descriptor/Tag/MethodDescriptor.php  gR  hK      <   src/phpDocumentor/Descriptor/Tag/BaseTypes/TypedAbstract.php  gR  6P      D   src/phpDocumentor/Descriptor/Tag/BaseTypes/TypedVariableAbstract.php  gR  o珶      3   src/phpDocumentor/Descriptor/Tag/UsesDescriptor.php  gR  >y      3   src/phpDocumentor/Descriptor/Tag/LinkDescriptor.phpq  gRq  [,      +   src/phpDocumentor/Console/Output/Output.php@  gR@  %      -   src/phpDocumentor/Console/Input/ArgvInput.php  gR  b      #   src/phpDocumentor/Configuration.php  gR  :ƶ      &   src/phpDocumentor/Parser/Exception.php]  gR]  \FjW      #   src/phpDocumentor/Parser/Parser.phpY9  gRY9  LH^      /   src/phpDocumentor/Parser/Event/PreFileEvent.php  gR  !      9   src/phpDocumentor/Parser/Command/Project/ParseCommand.php.  gR.  t      (   src/phpDocumentor/Parser/Messages/en.php  gR  O      ,   src/phpDocumentor/Parser/ServiceProvider.php  gR  w~N      A   src/phpDocumentor/Parser/Exception/MissingDependencyException.php  gR  
      E   src/phpDocumentor/Parser/Exception/MissingNameForPartialException.php  gR  B      =   src/phpDocumentor/Parser/Exception/FilesNotFoundException.php  gR  d?!      A   src/phpDocumentor/Transformer/Router/Matcher/MatcherInterface.php  gR  B      7   src/phpDocumentor/Transformer/Router/StandardRouter.php  gR  W[      K   src/phpDocumentor/Transformer/Router/UrlGenerator/UrlGeneratorInterface.php  gR  I      N   src/phpDocumentor/Transformer/Router/UrlGenerator/Standard/ClassDescriptor.php;  gR;  @Ƈ      R   src/phpDocumentor/Transformer/Router/UrlGenerator/Standard/NamespaceDescriptor.php  gR  s      M   src/phpDocumentor/Transformer/Router/UrlGenerator/Standard/FileDescriptor.php0  gR0        Q   src/phpDocumentor/Transformer/Router/UrlGenerator/Standard/FunctionDescriptor.php  gR  VƟɶ      P   src/phpDocumentor/Transformer/Router/UrlGenerator/Standard/PackageDescriptor.php  gR        Q   src/phpDocumentor/Transformer/Router/UrlGenerator/Standard/PropertyDescriptor.php  gR  ž      O   src/phpDocumentor/Transformer/Router/UrlGenerator/Standard/MethodDescriptor.php  gR  L2Ŷ      Q   src/phpDocumentor/Transformer/Router/UrlGenerator/Standard/ConstantDescriptor.php  gR  4x      -   src/phpDocumentor/Transformer/Router/Rule.php	  gR	  _7Ҷ      .   src/phpDocumentor/Transformer/Router/Queue.php  gR  ˕h      7   src/phpDocumentor/Transformer/Router/ExternalRouter.php   gR   X#      5   src/phpDocumentor/Transformer/Router/ForFileProxy.php  gR  GpI@      7   src/phpDocumentor/Transformer/Router/RouterAbstract.php}  gR}  uw2      +   src/phpDocumentor/Transformer/Exception.phpt  gRt  :      9   src/phpDocumentor/Transformer/Event/PreTransformEvent.phpA  gRA  эl      ?   src/phpDocumentor/Transformer/Event/PostTransformationEvent.php  gR  8ק'      9   src/phpDocumentor/Transformer/Event/PreXslWriterEvent.php  gR  1o      :   src/phpDocumentor/Transformer/Event/PostTransformEvent.php  gR        >   src/phpDocumentor/Transformer/Event/PreTransformationEvent.php  gR  {      B   src/phpDocumentor/Transformer/Command/Project/TransformCommand.php'  gR'  %l      >   src/phpDocumentor/Transformer/Command/Template/ListCommand.phpX
  gRX
  ƶ      -   src/phpDocumentor/Transformer/Transformer.php  gR  l      0   src/phpDocumentor/Transformer/Transformation.php   gR   \Ƕ      1   src/phpDocumentor/Transformer/ServiceProvider.php  gR        *   src/phpDocumentor/Transformer/Template.php  gR  6      5   src/phpDocumentor/Transformer/Template/Collection.php5  gR5  h      4   src/phpDocumentor/Transformer/Template/Parameter.php  gR  ^      F   src/phpDocumentor/Transformer/Exception/MissingDependencyException.php  gR  9      9   src/phpDocumentor/Transformer/Exception/UnknownWriter.php  gR  ec      3   src/phpDocumentor/Transformer/Writer/Collection.php
  gR
  :      7   src/phpDocumentor/Transformer/Writer/WriterAbstract.php  gR  	7t      5   src/phpDocumentor/Transformer/Writer/Translatable.php.  gR.  Ѷ      E   src/phpDocumentor/Transformer/Writer/Exception/RequirementMissing.php  gR  gpo      1   src/phpDocumentor/Transformer/Writer/Routable.php  gR         6   src/phpDocumentor/Transformer/Behaviour/Collection.php2  gR2  @      =   src/phpDocumentor/Transformer/Behaviour/BehaviourAbstract.php
  gR
  3      "   src/phpDocumentor/PharCompiler.php  gR  ,u9      +   src/phpDocumentor/Plugin/Core/Exception.phpe  gRe  p4      -   src/phpDocumentor/Plugin/Core/Messages/de.php  gR        -   src/phpDocumentor/Plugin/Core/Messages/en.php  gR  1      *   src/phpDocumentor/Plugin/Core/Listener.phpk  gRk  樶      H   src/phpDocumentor/Plugin/Core/Descriptor/Validator/RequiredValidator.php  gR  *s      q   src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/IsReturnTypeNotAnIdeDefaultValidator.php  gR  T      j   src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/IsArgumentInDocBlockValidator.php  gR        p   src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/IsParamTypeNotAnIdeDefaultValidator.php<  gR<  凶      h   src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/IsReturnTypeNotAnIdeDefault.phpn  gRn  wux      a   src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/IsArgumentInDocBlock.php\  gR\  ⽶      g   src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Functions/IsParamTypeNotAnIdeDefault.phpl  gRl  H      V   src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Property/HasSummary.phpY  gRY  +=¶      _   src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Property/HasSummaryValidator.php  gR  y|      ^   src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Classes/HasSingleSubpackage.phpm  gRm  ?׶      c   src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Classes/HasPackageWithSubpackage.php  gR  V	2      d   src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Classes/HasSinglePackageValidator.php  gR  j      l   src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Classes/HasPackageWithSubpackageValidator.php  gR        g   src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Classes/HasSingleSubpackageValidator.php  gR  |$p      [   src/phpDocumentor/Plugin/Core/Descriptor/Validator/Constraints/Classes/HasSinglePackage.phpg  gRg  1V      U   src/phpDocumentor/Plugin/Core/Descriptor/Validator/Functions/AreAllArgumentsValid.php  gR  l      H   src/phpDocumentor/Plugin/Core/Descriptor/Validator/ValidatorAbstract.php  gR  &*      J   src/phpDocumentor/Plugin/Core/Descriptor/Validator/DeprecatedValidator.phpv  gRv         9   src/phpDocumentor/Plugin/Core/Twig/ExtensionInterface.php  gR  i&n      0   src/phpDocumentor/Plugin/Core/Twig/Extension.phpR  gRR  pF	      1   src/phpDocumentor/Plugin/Core/ServiceProvider.phpk  gRk  /y      8   src/phpDocumentor/Plugin/Core/Transformer/Writer/Xsl.php$  gR$  qIb      ;   src/phpDocumentor/Plugin/Core/Transformer/Writer/FileIo.php;  gR;  dU/      :   src/phpDocumentor/Plugin/Core/Transformer/Writer/Graph.php"  gR"  ٶ      ?   src/phpDocumentor/Plugin/Core/Transformer/Writer/Checkstyle.php  gR  w"r      ?   src/phpDocumentor/Plugin/Core/Transformer/Writer/Sourcecode.php  gR  \      9   src/phpDocumentor/Plugin/Core/Transformer/Writer/Twig.php;  gR;  ,      8   src/phpDocumentor/Plugin/Core/Transformer/Writer/Xml.php}  gR}  c      E   src/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/CoversTag.php  gR  G      D   src/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/ParamTag.php  gR  и@      G   src/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/PropertyTag.phpJ  gRJ  I$      E   src/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/ReturnTag.phpq  gRq  O*H      G   src/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/InternalTag.php  gR  4a      C   src/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/UsesTag.php  gR  N      E   src/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/AuthorTag.phpb  gRb        F   src/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/LicenseTag.php  gR  z̶      E   src/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/MethodTag.php
  gR
        B   src/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/VarTag.php  gR  ;_ж      E   src/phpDocumentor/Plugin/Core/Transformer/Behaviour/Tag/IgnoreTag.php  gR  j      *   src/phpDocumentor/Configuration/Parser.php  gR  amٶ      /   src/phpDocumentor/Configuration/Transformer.php  gR  gx*      )   src/phpDocumentor/Configuration/Files.php  gR  l7      #   vendor/jms/parser-lib/composer.json  gR  ;ƭ      7   vendor/jms/parser-lib/src/JMS/Parser/AbstractParser.phpJ  gRJ  .^      =   vendor/jms/parser-lib/src/JMS/Parser/SyntaxErrorException.phpd  gRd        6   vendor/jms/parser-lib/src/JMS/Parser/AbstractLexer.php  gR  #8      4   vendor/jms/parser-lib/src/JMS/Parser/SimpleLexer.php&  gR&  qs         vendor/jms/parser-lib/LICENSE\,  gR\,  bE      B   vendor/jms/parser-lib/tests/JMS/Parser/Tests/AbstractLexerTest.php  gR        C   vendor/jms/parser-lib/tests/JMS/Parser/Tests/AbstractParserTest.php  gR  '{eH      )   vendor/jms/parser-lib/tests/bootstrap.php   gR   ?      #   vendor/jms/parser-lib/composer.locks  gRs  K"Gݶ      &   vendor/jms/parser-lib/phpunit.xml.dist  gR  ö      !   vendor/jms/parser-lib/doc/LICENSE?  gR?  FD      #   vendor/jms/serializer/composer.json  gR  j      U   vendor/jms/serializer/src/JMS/Serializer/EventDispatcher/EventSubscriberInterface.php  gR        P   vendor/jms/serializer/src/JMS/Serializer/EventDispatcher/LazyEventDispatcher.php  gR        P   vendor/jms/serializer/src/JMS/Serializer/EventDispatcher/PreDeserializeEvent.php  gR  {Ͷ      N   vendor/jms/serializer/src/JMS/Serializer/EventDispatcher/PreSerializeEvent.php  gR  oD      C   vendor/jms/serializer/src/JMS/Serializer/EventDispatcher/Events.php  gR  YkĶ      U   vendor/jms/serializer/src/JMS/Serializer/EventDispatcher/EventDispatcherInterface.php'  gR'  gǾ      L   vendor/jms/serializer/src/JMS/Serializer/EventDispatcher/EventDispatcher.php  gR  Н      B   vendor/jms/serializer/src/JMS/Serializer/EventDispatcher/Event.php{  gR{  4겶      H   vendor/jms/serializer/src/JMS/Serializer/EventDispatcher/ObjectEvent.php  gR  $      _   vendor/jms/serializer/src/JMS/Serializer/EventDispatcher/Subscriber/DoctrineProxySubscriber.php8  gR8  y      b   vendor/jms/serializer/src/JMS/Serializer/EventDispatcher/Subscriber/SymfonyValidatorSubscriber.phpN  gRN  yk-      7   vendor/jms/serializer/src/JMS/Serializer/TypeParser.php  gR  Ѷ      T   vendor/jms/serializer/src/JMS/Serializer/Naming/SerializedNameAnnotationStrategy.phpZ  gRZ  q       K   vendor/jms/serializer/src/JMS/Serializer/Naming/CamelCaseNamingStrategy.php  gR  {"h      G   vendor/jms/serializer/src/JMS/Serializer/Naming/CacheNamingStrategy.php  gR  OF޶      S   vendor/jms/serializer/src/JMS/Serializer/Naming/IdenticalPropertyNamingStrategy.php  gR  :O      S   vendor/jms/serializer/src/JMS/Serializer/Naming/PropertyNamingStrategyInterface.php  gR  _"\      H   vendor/jms/serializer/src/JMS/Serializer/GenericSerializationVisitor.php  gR  -      4   vendor/jms/serializer/src/JMS/Serializer/Context.php  gR  ʁ      Q   vendor/jms/serializer/src/JMS/Serializer/Exclusion/ExclusionStrategyInterface.php  gR  ~/ܶ      P   vendor/jms/serializer/src/JMS/Serializer/Exclusion/DisjunctExclusionStrategy.php
  gR
  E#      O   vendor/jms/serializer/src/JMS/Serializer/Exclusion/VersionExclusionStrategy.php=  gR=  ʾR      N   vendor/jms/serializer/src/JMS/Serializer/Exclusion/GroupsExclusionStrategy.php  gR  tG~      M   vendor/jms/serializer/src/JMS/Serializer/Exclusion/DepthExclusionStrategy.php  gR  _U      D   vendor/jms/serializer/src/JMS/Serializer/Annotation/PreSerialize.php  gR  m;      >   vendor/jms/serializer/src/JMS/Serializer/Annotation/Expose.php  gR  rF      @   vendor/jms/serializer/src/JMS/Serializer/Annotation/MaxDepth.php6  gR6  rf#      E   vendor/jms/serializer/src/JMS/Serializer/Annotation/PostSerialize.php  gR  +k      @   vendor/jms/serializer/src/JMS/Serializer/Annotation/ReadOnly.php  gR  [~      @   vendor/jms/serializer/src/JMS/Serializer/Annotation/XmlValue.php  gR  Kt      E   vendor/jms/serializer/src/JMS/Serializer/Annotation/XmlCollection.phpE  gRE  L      =   vendor/jms/serializer/src/JMS/Serializer/Annotation/Since.php  gR  {      E   vendor/jms/serializer/src/JMS/Serializer/Annotation/AccessorOrder.php  gR  zW      =   vendor/jms/serializer/src/JMS/Serializer/Annotation/Until.php  gR  ߋ      ?   vendor/jms/serializer/src/JMS/Serializer/Annotation/XmlList.php
  gR
        ?   vendor/jms/serializer/src/JMS/Serializer/Annotation/XmlRoot.php,  gR,  T۳      G   vendor/jms/serializer/src/JMS/Serializer/Annotation/ExclusionPolicy.php  gR  "t=      @   vendor/jms/serializer/src/JMS/Serializer/Annotation/Accessor.php  gR  6      <   vendor/jms/serializer/src/JMS/Serializer/Annotation/Type.php8  gR8  cG      >   vendor/jms/serializer/src/JMS/Serializer/Annotation/XmlMap.phpO  gRO  ͅ      G   vendor/jms/serializer/src/JMS/Serializer/Annotation/VirtualProperty.php'  gR'  $֋)      >   vendor/jms/serializer/src/JMS/Serializer/Annotation/Inline.php  gR  07'      >   vendor/jms/serializer/src/JMS/Serializer/Annotation/Groups.php/  gR/  yy      G   vendor/jms/serializer/src/JMS/Serializer/Annotation/XmlAttributeMap.php  gR  A }@      ?   vendor/jms/serializer/src/JMS/Serializer/Annotation/Version.php  gR  ,      D   vendor/jms/serializer/src/JMS/Serializer/Annotation/XmlAttribute.php  gR  >      B   vendor/jms/serializer/src/JMS/Serializer/Annotation/AccessType.phpv  gRv  LQ=      G   vendor/jms/serializer/src/JMS/Serializer/Annotation/PostDeserialize.php  gR  |      F   vendor/jms/serializer/src/JMS/Serializer/Annotation/SerializedName.php&  gR&  
(      H   vendor/jms/serializer/src/JMS/Serializer/Annotation/XmlKeyValuePairs.php  gR  @A\n      G   vendor/jms/serializer/src/JMS/Serializer/Annotation/HandlerCallback.php  gR  |TR      ?   vendor/jms/serializer/src/JMS/Serializer/Annotation/Exclude.php  gR  }\      E   vendor/jms/serializer/src/JMS/Serializer/Annotation/Discriminator.php  gR  QĖ>      A   vendor/jms/serializer/src/JMS/Serializer/SerializationContext.php=  gR=  RМ      V   vendor/jms/serializer/src/JMS/Serializer/Construction/UnserializeObjectConstructor.php  gR  5t      S   vendor/jms/serializer/src/JMS/Serializer/Construction/DoctrineObjectConstructor.php  gR        T   vendor/jms/serializer/src/JMS/Serializer/Construction/ObjectConstructorInterface.php  gR  Yl      J   vendor/jms/serializer/src/JMS/Serializer/GenericDeserializationVisitor.phpe  gRe  <      F   vendor/jms/serializer/src/JMS/Serializer/XmlDeserializationVisitor.php]%  gR]%  ն      E   vendor/jms/serializer/src/JMS/Serializer/YamlSerializationVisitor.php  gR        <   vendor/jms/serializer/src/JMS/Serializer/AbstractVisitor.phpb  gRb  +      8   vendor/jms/serializer/src/JMS/Serializer/Util/Writer.phpl  gRl  bF6      @   vendor/jms/serializer/src/JMS/Serializer/SerializerInterface.php  gR  S"      E   vendor/jms/serializer/src/JMS/Serializer/Twig/SerializerExtension.php  gR  pl      >   vendor/jms/serializer/src/JMS/Serializer/SerializerBuilder.php1  gR1  +      C   vendor/jms/serializer/src/JMS/Serializer/DeserializationContext.php  gR  s      G   vendor/jms/serializer/src/JMS/Serializer/JsonDeserializationVisitor.php  gR  Cm      =   vendor/jms/serializer/src/JMS/Serializer/VisitorInterface.php  gR  ^      D   vendor/jms/serializer/src/JMS/Serializer/XmlSerializationVisitor.php+  gR+  G_$      F   vendor/jms/serializer/src/JMS/Serializer/Metadata/PropertyMetadata.php  gR  tX      M   vendor/jms/serializer/src/JMS/Serializer/Metadata/VirtualPropertyMetadata.php7
  gR7
  H6׶      C   vendor/jms/serializer/src/JMS/Serializer/Metadata/ClassMetadata.php#  gR#  Z!      O   vendor/jms/serializer/src/JMS/Serializer/Metadata/Driver/DoctrineTypeDriver.php-  gR-        F   vendor/jms/serializer/src/JMS/Serializer/Metadata/Driver/PhpDriver.php  gR  XѶ      G   vendor/jms/serializer/src/JMS/Serializer/Metadata/Driver/YamlDriver.php)  gR)        M   vendor/jms/serializer/src/JMS/Serializer/Metadata/Driver/AnnotationDriver.php%  gR%  nf      F   vendor/jms/serializer/src/JMS/Serializer/Metadata/Driver/XmlDriver.php(.  gR(.  V      L   vendor/jms/serializer/src/JMS/Serializer/Metadata/StaticPropertyMetadata.php0
  gR0
  ([      E   vendor/jms/serializer/src/JMS/Serializer/JsonSerializationVisitor.php  gR  7i      7   vendor/jms/serializer/src/JMS/Serializer/Serializer.phpl  gRl  تs      P   vendor/jms/serializer/src/JMS/Serializer/Exception/ValidationFailedException.phpJ  gRJ  t5      @   vendor/jms/serializer/src/JMS/Serializer/Exception/Exception.php!  gR!  Ǫ      O   vendor/jms/serializer/src/JMS/Serializer/Exception/InvalidArgumentException.phpm  gRm  FQ      G   vendor/jms/serializer/src/JMS/Serializer/Exception/RuntimeException.phpU  gRU  eV      E   vendor/jms/serializer/src/JMS/Serializer/Exception/LogicException.phpO  gRO  [,      H   vendor/jms/serializer/src/JMS/Serializer/Exception/XmlErrorException.php  gR  Ր      Q   vendor/jms/serializer/src/JMS/Serializer/Exception/UnsupportedFormatException.php  gR  țK0      ;   vendor/jms/serializer/src/JMS/Serializer/GraphNavigator.phpE3  gRE3  oT      H   vendor/jms/serializer/src/JMS/Serializer/Handler/LazyHandlerRegistry.php  gR  &0      D   vendor/jms/serializer/src/JMS/Serializer/Handler/HandlerRegistry.php  gR  %      E   vendor/jms/serializer/src/JMS/Serializer/Handler/FormErrorHandler.phpo  gRo  VoԦ      O   vendor/jms/serializer/src/JMS/Serializer/Handler/ConstraintViolationHandler.phpT  gRT  "3      M   vendor/jms/serializer/src/JMS/Serializer/Handler/HandlerRegistryInterface.phpz  gRz  qOkܶ      P   vendor/jms/serializer/src/JMS/Serializer/Handler/SubscribingHandlerInterface.php  gR  Ի6z      I   vendor/jms/serializer/src/JMS/Serializer/Handler/PhpCollectionHandler.php/  gR/  yJl      @   vendor/jms/serializer/src/JMS/Serializer/Handler/DateHandler.php  gR  lc      K   vendor/jms/serializer/src/JMS/Serializer/Handler/ArrayCollectionHandler.php
  gR
  ޘ         vendor/jms/serializer/LICENSE\,  gR\,  bE      \   vendor/jms/serializer/tests/JMS/Serializer/Tests/Exclusion/DisjunctExclusionStrategyTest.php)  gR)  1      M   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/VersionedObject.phpG  gRG  7      F   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/BlogPost.php
  gR
        I   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/InlineChild.php  gR  1U7      Q   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/AccessorOrderMethod.php  gR  2̶      J   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/GroupsObject.php  gR        O   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/Discriminator/Car.php  gR  )      Q   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/Discriminator/Moped.php  gR  '%@      S   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/Discriminator/Vehicle.phpP  gRP  k}/      P   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/CurrencyAwareOrder.php
  gR
  {w+      E   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/Article.php	  gR	  ko      B   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/Node.php  gR  db      O   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/Doctrine/BlogPost.phpC
  gRC
  ^j      N   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/Doctrine/Comment.phps  gRs  P"Gl      M   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/Doctrine/Author.php  gR  3HB      P   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/CurrencyAwarePrice.phpq  gRq  :i      U   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/IndexedCommentsBlogPost.php  gR  +      Q   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/AccessorOrderParent.phpC  gRC  vζ      C   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/Price.php  gR  
:      Z   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/ObjectWithLifecycleCallbacks.php  gR  yG      L   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/AuthorReadOnly.phpf  gRf  VQ۶      U   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/CircularReferenceParent.php  gR  u      Z   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/InitializedObjectConstructor.php  gR  :      Q   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/InvalidGroupsObject.phpe  gRe  s:      L   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/PersonLocation.php  gR        O   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/SimpleObjectProxy.php[  gR[  g톶      B   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/Tree.phpt  gRt  Zx      E   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/Comment.phpF  gRF  N7      X   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/ObjectWithXmlKeyValuePairs.php  gR  a[      T   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/CircularReferenceChild.php  gR  ])&      N   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/PersonCollection.php  gR  ސ      C   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/Order.php  gR  W]K      T   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/ObjectWithNullProperty.php0  gR0  D       \   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/ObjectWithVirtualXmlProperties.php	  gR	  W      f   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/ObjectWithVirtualPropertiesAndExcludeAll.php  gR  kf[      Q   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/ObjectWithEmptyHash.phpP  gRP  q~6<      H   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/AuthorList.php5  gR5  {߶      A   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/Log.phpa  gRa  nYZ      O   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/AllExcludedObject.php  gR  .Ӷ      P   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/AccessorOrderChild.phpw  gRw  D      D   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/Author.php   gR   A?q      Y   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/CustomDeserializationObject.php  gR  C]      D   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/Person.php  gR  r]?      C   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/Input.php9  gR9  i:      J   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/SimpleObject.php  gR  cF'V      J   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/GetSetObject.php}  gR}  %Z      b   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/ObjectWithVersionedVirtualProperties.php  gR  kLJ      J   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/InlineParent.php  gR  \      T   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/InvalidUsageOfXmlValue.phpM  gRM  ^v`      Y   vendor/jms/serializer/tests/JMS/Serializer/Tests/Fixtures/ObjectWithVirtualProperties.php  gR  Ev      Q   vendor/jms/serializer/tests/JMS/Serializer/Tests/Twig/SerializerExtensionTest.php3  gR3  R	      J   vendor/jms/serializer/tests/JMS/Serializer/Tests/SerializerBuilderTest.php  gR  u'      O   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/ClassMetadataTest.php|	  gR|	  #}      Q   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/php/BlogPost.php  gR  1      M   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/php/Node.phpU  gRU  k9      N   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/php/Price.phpu  gRu  9|O      W   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/php/AuthorReadOnly.php   gR   z]n}      Z   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/php/Discriminator.Car.php   gR   #-      ^   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/php/Discriminator.Vehicle.php  gR  Nn      c   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/php/ObjectWithXmlKeyValuePairs.phpr  gRr  Y      q   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/php/ObjectWithVirtualPropertiesAndExcludeAll.php  gR  (      \   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/php/Discriminator.Moped.php   gR   YmS      d   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/php/ObjectWithVirtualProperties.php  gR  ("      Z   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/yml/Discriminator.Car.yml4   gR4   rJȶ      q   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/yml/ObjectWithVirtualPropertiesAndExcludeAll.yml   gR   Op5      ^   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/yml/exclude_none/BlogPost.yml   gR   oR[      c   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/yml/ObjectWithXmlKeyValuePairs.yml   gR    uʶ      ]   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/yml/exclude_all/BlogPost.yml   gR   3NQ      d   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/yml/ObjectWithVirtualProperties.yml+  gR+  {|E      ^   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/yml/Discriminator.Vehicle.yml*  gR*  ޶      N   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/yml/Price.ymlx   gRx   axk      Q   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/yml/BlogPost.yml  gR  L      V   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/yml/case/BlogPost.yml   gR   ob      \   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/yml/Discriminator.Moped.yml6   gR6   A5      M   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/yml/Node.yml_   gR_   ~2      Z   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/yml/accessor/BlogPost.yml   gR   XLض      W   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/yml/AuthorReadOnly.yml+  gR+  q      S   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/BaseDriverTest.php  gR  Jo      d   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/xml/ObjectWithVirtualProperties.xml  gR  N      ^   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/xml/exclude_none/BlogPost.xml   gR   8!      q   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/xml/ObjectWithVirtualPropertiesAndExcludeAll.xml   gR   .ض      P   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/xml/invalid.xml"   gR"   T#      W   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/xml/AuthorReadOnly.xmlW  gRW  n      U   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/xml/GetSetObject.xmlb  gRb        M   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/xml/Node.xml   gR   %`      Q   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/xml/BlogPost.xml  gR  ٶ      \   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/xml/Discriminator.Moped.xml   gR   %Ė      N   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/xml/Price.xml   gR   f]      ]   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/xml/exclude_all/BlogPost.xml   gR   HQ      ^   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/xml/Discriminator.Vehicle.xml  gR  S      c   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/xml/ObjectWithXmlKeyValuePairs.xml   gR   r      V   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/xml/case/BlogPost.xml   gR         Z   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/xml/Discriminator.Car.xml   gR   u      R   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/XmlDriverTest.php
  gR
  LtѶ      S   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/YamlDriverTest.phpL  gRL  {,      Y   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/AnnotationDriverTest.php  gR        R   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/PhpDriverTest.php  gR  &'      W   vendor/jms/serializer/tests/JMS/Serializer/Tests/Metadata/Driver/DoctrineDriverTest.phpa  gRa  R      c   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/EventDispatcher/EventDispatcherTest.php  gR  y      v   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/EventDispatcher/Subscriber/DoctrineProxySubscriberTest.php  gR  C!      y   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/EventDispatcher/Subscriber/SymfonyValidatorSubscriberTest.php@  gR@  2WC      U   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/YamlSerializationTest.php  gR  ׄ5:      Q   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/array_objects.yml`   gR`   &\ƈ      X   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/blog_post_unauthored.yml~   gR~   p      Q   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/array_strings.yml   gR   Zֶ      R   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/groups_default.yml   gR   <ӗ      X   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/accessor_order_child.yml   gR   _=&      c   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/order_with_currency_aware_price.yml)   gR)   Gl      Z   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/virtual_properties_all.yml   gR   _&IV      Q   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/boolean_false.yml   gR   W%      Z   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/accessor_order_methods.yml   gR   ~      I   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/input.ymlA   gRA   R|*b      Q   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/groups_foobar.yml!   gR!   5       N   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/hash_empty.yml	   gR	   M      H   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/tree.yml   gR   zDL      W   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/lifecycle_callbacks.yml   gR         M   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/date_time.yml   gR   hl      N   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/groups_all.yml,   gR,   6T      P   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/boolean_true.yml   gR   B#      I   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/order.yml   gR         S   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/custom_accessor.yml   gR   #C      Z   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/virtual_properties_low.yml   gR   6y      Q   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/simple_object.yml"   gR"   Ƕ      G   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/log.ymlB  gRB  7oV϶      R   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/array_booleans.yml   gR          V   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/virtual_properties.ymlS   gRS   b      V   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/mixed_access_types.yml,   gR,   َĶ      H   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/null.yml   gR   nԶ      P   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/array_floats.yml   gR   owJ      J   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/string.yml   gR   e2~      M   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/blog_post.yml9  gR9  Ȼܑ      c   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/object_when_null_and_serialized.yml   gR   [      K   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/integer.yml   gR   SQg      R   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/array_integers.yml   gR   e=      N   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/groups_foo.yml   gR   Cܶ      Q   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/date_interval.yml   gR   P4      [   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/virtual_properties_high.yml   gR   e       L   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/nullable.yml   gR   {+      G   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/car.yml   gR   +      O   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/array_mixed.yml^   gR^   |      T   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/car_without_type.yml   gR   KlW      K   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/article.yml   gR   [O'      L   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/readonly.yml#   gR#   )}/      M   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/orm_proxy.yml(   gR(   G      Z   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/simple_object_nullable.yml6   gR6   .E^      X   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/currency_aware_price.yml   gR    e)      T   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/object_when_null.yml
   gR
   FV      J   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/inline.yml   gR   |.      Y   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/accessor_order_parent.yml
   gR
   &ѫ      I   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/float.yml   gR   	      V   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/circular_reference.yml   gR   ѷ      I   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/price.yml	   gR	   b&      W   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/yml/float_trailing_zero.yml   gR   SQg      N   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/TypeParserTest.phpn  gRn  :.      j   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/Naming/IdenticalPropertyNamingStrategyTest.php  gR  QZ]      T   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/XmlSerializationTest.phpB  gRB  ?V      V   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/DateIntervalFormatTest.php3  gR3   T      Q   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/simple_object.xml   gR   ]e      K   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/integer.xml:   gR:   V      I   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/order.xmlM   gRM   SYض      W   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/lifecycle_callbacks.xml]   gR]   }¶      X   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/accessor_order_child.xml   gR   
8\      X   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/currency_aware_price.xmlJ   gRJ   O      Z   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/virtual_properties_low.xmlI   gRI   8      M   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/orm_proxy.xml   gR   㙈^      V   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/virtual_properties.xml   gR   8      H   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/tree.xml  gR  .g      [   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/virtual_properties_high.xmlK   gRK   Mܮ      U   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/person_collection.xml   gR   Ͷ      Q   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/array_objects.xml:  gR:  |      Q   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/boolean_false.xml>   gR>   ia@      S   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/custom_accessor.xml  gR  1Ɠ      K   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/article.xmlC   gRC   lT      V   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/nested_form_errors.xml   gR   Ͷ      Z   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/accessor_order_methods.xml   gR   |5      ]   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/constraint_violation_list.xml  gR  q~Ƕ      Y   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/accessor_order_parent.xmlh   gRh         O   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/form_errors.xml   gR   be      R   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/groups_default.xmlw   gRw   ǉ9      Z   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/simple_object_nullable.xml   gR   >      Q   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/groups_foobar.xml   gR   Yö      M   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/blog_post.xmlJ  gRJ  ~q      G   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/log.xml  gR  X      I   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/float.xml>   gR>   _      R   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/virtual_values.xmlN   gRN         L   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/nullable.xml   gR   )ܶ      V   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/mixed_access_types.xml   gR   !      R   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/array_booleans.xmlg   gRg   :      W   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/float_trailing_zero.xml:   gR:   V      S   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/person_location.xml   gR   |+4      P   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/boolean_true.xml=   gR=   V<ض      Z   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/virtual_properties_all.xmlZ   gRZ   G=;      X   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/blog_post_unauthored.xml   gR   "*p      O   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/array_mixed.xml[  gR[  bͦ      R   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/array_integers.xmls   gRs   ,H1      M   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/date_time.xml]   gR]   }      V   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/circular_reference.xml  gR  B㚹      T   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/car_without_type.xmlG   gRG   N      N   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/hash_empty.xmlD   gRD   ubm      N   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/groups_foo.xml}   gR}   r      J   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/string.xmlH   gRH   o      J   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/inline.xml   gR         c   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/order_with_currency_aware_price.xml[   gR[   1/      P   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/array_floats.xmly   gRy   '      I   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/price.xml8   gR8   Sc      G   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/car.xmlf   gRf   g       L   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/readonly.xml|   gR|   qQ      N   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/groups_all.xml   gR         I   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/input.xml\   gR\   RE	      X   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/constraint_violation.xml   gR   dG͚      H   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/null.xmlv   gRv   A&      T   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/object_when_null.xmlY   gRY   OY      T   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/array_key_values.xml  gR  |#      Q   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/date_interval.xmlJ   gRJ   o銶      c   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/object_when_null_and_serialized.xml   gR   Li      [   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/virtual_properties_list.xmlt   gRt   :f@      Q   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/array_strings.xml|   gR|   Wr      V   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/virtual_attributes.xml;   gR;   >!      Z   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/xml/virtual_properties_map.xml   gR   5![9      U   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/BaseSerializationTest.phpy  gRy  o_      R   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/GraphNavigatorTest.php(  gR(  C>      U   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/JsonSerializationTest.php%  gR%  YZ      K   vendor/jms/serializer/tests/JMS/Serializer/Tests/Serializer/ContextTest.php  gR  9í      )   vendor/jms/serializer/tests/benchmark.php=  gR=  fж      )   vendor/jms/serializer/tests/bootstrap.php:  gR:  g\      #   vendor/jms/serializer/composer.lockr  gRr  Xi8      &   vendor/jms/serializer/phpunit.xml.dist  gR  qo̶      !   vendor/jms/serializer/doc/LICENSE?  gR?  FD      !   vendor/jms/metadata/composer.jsone  gRe  j      4   vendor/jms/metadata/src/Metadata/MetadataFactory.phpw  gRw  9?      5   vendor/jms/metadata/src/Metadata/PropertyMetadata.php  gR        1   vendor/jms/metadata/src/Metadata/NullMetadata.phph  gRh  ж      ?   vendor/jms/metadata/src/Metadata/Cache/DoctrineCacheAdapter.php  gR  4޶      4   vendor/jms/metadata/src/Metadata/Cache/FileCache.phpm  gRm        9   vendor/jms/metadata/src/Metadata/Cache/CacheInterface.php  gR  dxm;      ;   vendor/jms/metadata/src/Metadata/ClassHierarchyMetadata.php  gR  *      ;   vendor/jms/metadata/src/Metadata/MergeableClassMetadata.phpE  gRE  Qt      7   vendor/jms/metadata/src/Metadata/MergeableInterface.php   gR   ʶ      3   vendor/jms/metadata/src/Metadata/MethodMetadata.php  gR  o      2   vendor/jms/metadata/src/Metadata/ClassMetadata.php	  gR	  	O      ,   vendor/jms/metadata/src/Metadata/Version.php  gR        E   vendor/jms/metadata/src/Metadata/AdvancedMetadataFactoryInterface.php?  gR?  BK)<      ;   vendor/jms/metadata/src/Metadata/Driver/DriverInterface.phpW  gRW  sgA      =   vendor/jms/metadata/src/Metadata/Driver/LazyLoadingDriver.phpH  gRH  1˶      7   vendor/jms/metadata/src/Metadata/Driver/DriverChain.php  gR  R      H   vendor/jms/metadata/src/Metadata/Driver/AdvancedFileLocatorInterface.php  gR  ?      @   vendor/jms/metadata/src/Metadata/Driver/FileLocatorInterface.php  gR  ځ      >   vendor/jms/metadata/src/Metadata/Driver/AbstractFileDriver.php  gR  Il      7   vendor/jms/metadata/src/Metadata/Driver/FileLocator.php  gR  6      C   vendor/jms/metadata/src/Metadata/Driver/AdvancedDriverInterface.php  gR  T      =   vendor/jms/metadata/src/Metadata/MetadataFactoryInterface.phpB  gRB  ڌT         vendor/jms/metadata/LICENSE\,  gR\,  bE      @   vendor/jms/metadata/tests/Metadata/Tests/Cache/FileCacheTest.php  gR  ㆶ      K   vendor/jms/metadata/tests/Metadata/Tests/Cache/DoctrineCacheAdapterTest.php  gR  X*      @   vendor/jms/metadata/tests/Metadata/Tests/Fixtures/TestParent.phpR   gRR   P`-      P   vendor/jms/metadata/tests/Metadata/Tests/Fixtures/ComplexHierarchy/SubClassB.phps   gRs   Nls      P   vendor/jms/metadata/tests/Metadata/Tests/Fixtures/ComplexHierarchy/SubClassA.php   gR   -Q      Q   vendor/jms/metadata/tests/Metadata/Tests/Fixtures/ComplexHierarchy/InterfaceA.phpU   gRU   .       Q   vendor/jms/metadata/tests/Metadata/Tests/Fixtures/ComplexHierarchy/InterfaceB.phpU   gRU   8\      P   vendor/jms/metadata/tests/Metadata/Tests/Fixtures/ComplexHierarchy/BaseClass.php   gR   ܾ?      @   vendor/jms/metadata/tests/Metadata/Tests/Fixtures/TestObject.php   gR   eH,Q      >   vendor/jms/metadata/tests/Metadata/Tests/ClassMetadataTest.phpm  gRm  Ù      A   vendor/jms/metadata/tests/Metadata/Tests/PropertyMetadataTest.phpe  gRe  ȦZw      ?   vendor/jms/metadata/tests/Metadata/Tests/MethodMetadataTest.phpR  gRR  !      J   vendor/jms/metadata/tests/Metadata/Tests/Driver/AbstractFileDriverTest.php  gR  	D      ?   vendor/jms/metadata/tests/Metadata/Tests/Driver/Fixture/B/B.yml    gR              ?   vendor/jms/metadata/tests/Metadata/Tests/Driver/Fixture/B/B.php>   gR>         F   vendor/jms/metadata/tests/Metadata/Tests/Driver/Fixture/C/SubDir.C.yml    gR              F   vendor/jms/metadata/tests/Metadata/Tests/Driver/Fixture/C/SubDir/C.phpE   gRE   Y      ?   vendor/jms/metadata/tests/Metadata/Tests/Driver/Fixture/D/D.php   gR         ?   vendor/jms/metadata/tests/Metadata/Tests/Driver/Fixture/D/D.yml    gR              ?   vendor/jms/metadata/tests/Metadata/Tests/Driver/Fixture/T/T.xml    gR              ?   vendor/jms/metadata/tests/Metadata/Tests/Driver/Fixture/T/T.php>   gR>   j 4      ?   vendor/jms/metadata/tests/Metadata/Tests/Driver/Fixture/A/A.xml    gR              ?   vendor/jms/metadata/tests/Metadata/Tests/Driver/Fixture/A/A.php>   gR>   "jS}      C   vendor/jms/metadata/tests/Metadata/Tests/Driver/DriverChainTest.php  gR  x      C   vendor/jms/metadata/tests/Metadata/Tests/Driver/FileLocatorTest.php
  gR
  [      @   vendor/jms/metadata/tests/Metadata/Tests/MetadataFactoryTest.php<+  gR<+  9j.      G   vendor/jms/metadata/tests/Metadata/Tests/MergeableClassMetadataTest.php  gR  O`m      '   vendor/jms/metadata/tests/bootstrap.php  gR  =      $   vendor/jms/metadata/phpunit.xml.dist  gR  eѶ      -   vendor/phpunit/php-token-stream/composer.jsonu  gRu  !F      +   vendor/phpunit/php-token-stream/package.xml  gR  >      /   vendor/phpunit/php-token-stream/build/phpmd.xml  gR  <dy      ^   vendor/phpunit/php-token-stream/build/PHPCS/Sniffs/ControlStructures/ControlSignatureSniff.php  gR  Aȶ      [   vendor/phpunit/php-token-stream/build/PHPCS/Sniffs/Whitespace/ConcatenationSpacingSniff.phpU  gRU  CN      7   vendor/phpunit/php-token-stream/build/PHPCS/ruleset.xml-  gR-  K      '   vendor/phpunit/php-token-stream/LICENSE  gR  Q)[      )   vendor/phpunit/php-token-stream/build.xml
  gR
  FIԶ      0   vendor/phpunit/php-token-stream/phpunit.xml.dist`  gR`  O      =   vendor/phpunit/php-token-stream/PHP/Token/Stream/Autoload.phpB)  gRB)  %ia      C   vendor/phpunit/php-token-stream/PHP/Token/Stream/CachingFactory.php  gR  Ӓն      @   vendor/phpunit/php-token-stream/PHP/Token/Stream/Autoload.php.inz	  gRz	  *n      4   vendor/phpunit/php-token-stream/PHP/Token/Stream.phpuD  gRuD  rSͶ      -   vendor/phpunit/php-token-stream/PHP/Token.php[  gR[  @@ն      <   vendor/phpunit/php-token-stream/Tests/Token/FunctionTest.php  gR  +      ;   vendor/phpunit/php-token-stream/Tests/Token/ClosureTest.php  gR  7      9   vendor/phpunit/php-token-stream/Tests/Token/ClassTest.php  gR  p      =   vendor/phpunit/php-token-stream/Tests/Token/InterfaceTest.php  gR  F      =   vendor/phpunit/php-token-stream/Tests/Token/NamespaceTest.php  gR        ;   vendor/phpunit/php-token-stream/Tests/Token/IncludeTest.php  gR  8v      3   vendor/phpunit/php-token-stream/Tests/TokenTest.php  gR  15/      A   vendor/phpunit/php-token-stream/Tests/_files/classInNamespace.php.   gR.   s3      8   vendor/phpunit/php-token-stream/Tests/_files/closure.php  gR  aٶ      Z   vendor/phpunit/php-token-stream/Tests/_files/multipleNamespacesWithOneClassUsingBraces.phpa   gRa   Z      8   vendor/phpunit/php-token-stream/Tests/_files/source3.php1  gR1  g$q      8   vendor/phpunit/php-token-stream/Tests/_files/source2.phpm   gRm   oZ      L   vendor/phpunit/php-token-stream/Tests/_files/classExtendsNamespacedClass.phpi   gRi   Zh`      b   vendor/phpunit/php-token-stream/Tests/_files/multipleNamespacesWithOneClassUsingNonBraceSyntax.php}   gR}         8   vendor/phpunit/php-token-stream/Tests/_files/source5.php  gR  	>۶      8   vendor/phpunit/php-token-stream/Tests/_files/issue30.phpU   gRU         G   vendor/phpunit/php-token-stream/Tests/_files/classInScopedNamespace.phpB   gRB   :B      7   vendor/phpunit/php-token-stream/Tests/_files/source.php  gR  DMɠ      8   vendor/phpunit/php-token-stream/Tests/_files/issue19.php   gR   4      8   vendor/phpunit/php-token-stream/Tests/_files/source4.php  gR        $   vendor/phpunit/phpunit/composer.jsonS  gRS  X:      "   vendor/phpunit/phpunit/package.xml1  gR1  PY      "   vendor/phpunit/phpunit/phpunit.xsd.  gR.  ՞      &   vendor/phpunit/phpunit/build/phpmd.xml  gR  <dy      1   vendor/phpunit/phpunit/build/phar-autoload.php.in  gR  	      +   vendor/phpunit/phpunit/build/assertions.phpr  gRr        *   vendor/phpunit/phpunit/build/travis-ci.xml  gR  @Ѯ      U   vendor/phpunit/phpunit/build/PHPCS/Sniffs/ControlStructures/ControlSignatureSniff.phpM  gRM  Sg      R   vendor/phpunit/phpunit/build/PHPCS/Sniffs/Whitespace/ConcatenationSpacingSniff.phpU  gRU  CN      .   vendor/phpunit/phpunit/build/PHPCS/ruleset.xml-  gR-  K      "   vendor/phpunit/phpunit/phpunit.bat  gR  nhH         vendor/phpunit/phpunit/LICENSE  gR  8iX      :   vendor/phpunit/phpunit/PHPUnit/Extensions/PhptTestCase.phpj"  gRj"  rOfȶ      :   vendor/phpunit/phpunit/PHPUnit/Extensions/RepeatedTest.php  gR  뾶      ;   vendor/phpunit/phpunit/PHPUnit/Extensions/PhptTestSuite.php  gR  7q      ;   vendor/phpunit/phpunit/PHPUnit/Extensions/TestDecorator.phpk  gRk  J},      <   vendor/phpunit/phpunit/PHPUnit/Extensions/TicketListener.php  gR  `k      A   vendor/phpunit/phpunit/PHPUnit/Extensions/PhptTestCase/Logger.php	  gR	  bն      <   vendor/phpunit/phpunit/PHPUnit/Extensions/GroupTestSuite.php  gR  'e      4   vendor/phpunit/phpunit/PHPUnit/TextUI/TestRunner.php)  gR)        7   vendor/phpunit/phpunit/PHPUnit/TextUI/ResultPrinter.phpE  gRE  ex      1   vendor/phpunit/phpunit/PHPUnit/TextUI/Command.phpq  gRq  \M      .   vendor/phpunit/phpunit/PHPUnit/Util/String.php  gR  |&      0   vendor/phpunit/phpunit/PHPUnit/Util/Log/JSON.php  gR  ĚP      1   vendor/phpunit/phpunit/PHPUnit/Util/Log/JUnit.php#<  gR#<  Z!      /   vendor/phpunit/phpunit/PHPUnit/Util/Log/TAP.php  gR  12      2   vendor/phpunit/phpunit/PHPUnit/Util/Filesystem.php  gR  G      2   vendor/phpunit/phpunit/PHPUnit/Util/Fileloader.php  gR  {      @   vendor/phpunit/phpunit/PHPUnit/Util/DeprecatedFeature/Logger.phpT  gRT  b      =   vendor/phpunit/phpunit/PHPUnit/Util/TestDox/ResultPrinter.phps&  gRs&  Ƕ      B   vendor/phpunit/phpunit/PHPUnit/Util/TestDox/ResultPrinter/HTML.php  gR         B   vendor/phpunit/phpunit/PHPUnit/Util/TestDox/ResultPrinter/Text.php  gR  4ٶ      >   vendor/phpunit/phpunit/PHPUnit/Util/TestDox/NamePrettifier.php"  gR"  f yY      9   vendor/phpunit/phpunit/PHPUnit/Util/DeprecatedFeature.php  gR        /   vendor/phpunit/phpunit/PHPUnit/Util/Printer.phpH  gRH        ,   vendor/phpunit/phpunit/PHPUnit/Util/Diff.php5!  gR5!  ɶ      -   vendor/phpunit/phpunit/PHPUnit/Util/Class.php*  gR*  _      ,   vendor/phpunit/phpunit/PHPUnit/Util/Type.php&  gR&  Cٶ      5   vendor/phpunit/phpunit/PHPUnit/Util/Configuration.php  gR  W<K      .   vendor/phpunit/phpunit/PHPUnit/Util/Filter.php  gR  </      .   vendor/phpunit/phpunit/PHPUnit/Util/Getopt.php  gR  -u!j      +   vendor/phpunit/phpunit/PHPUnit/Util/PHP.phpP-  gRP-  s޻      ,   vendor/phpunit/phpunit/PHPUnit/Util/Test.phpM  gRM  Jٶ      4   vendor/phpunit/phpunit/PHPUnit/Util/ErrorHandler.php	  gR	  D      +   vendor/phpunit/phpunit/PHPUnit/Util/XML.phpu  gRu  M-       3   vendor/phpunit/phpunit/PHPUnit/Util/PHP/Windows.php  gR  d      3   vendor/phpunit/phpunit/PHPUnit/Util/PHP/Default.phpX
  gRX
  v⋶      3   vendor/phpunit/phpunit/PHPUnit/Util/GlobalState.php7  gR7  z      =   vendor/phpunit/phpunit/PHPUnit/Util/InvalidArgumentHelper.php  gR  K      9   vendor/phpunit/phpunit/PHPUnit/Util/TestSuiteIterator.phpi  gRi  |č      6   vendor/phpunit/phpunit/PHPUnit/Framework/Exception.php	  gR	  /`?      5   vendor/phpunit/phpunit/PHPUnit/Framework/TestCase.php  gR  *Ͷ      =   vendor/phpunit/phpunit/PHPUnit/Framework/Comparator/Array.phpx  gRx         >   vendor/phpunit/phpunit/PHPUnit/Framework/Comparator/Double.php
  gR
  $Xu      A   vendor/phpunit/phpunit/PHPUnit/Framework/Comparator/Exception.php  gR  7      B   vendor/phpunit/phpunit/PHPUnit/Framework/Comparator/MockObject.php  gR  e"      H   vendor/phpunit/phpunit/PHPUnit/Framework/Comparator/SplObjectStorage.php  gR        >   vendor/phpunit/phpunit/PHPUnit/Framework/Comparator/Scalar.php   gR   j_      >   vendor/phpunit/phpunit/PHPUnit/Framework/Comparator/Object.php  gR  5      <   vendor/phpunit/phpunit/PHPUnit/Framework/Comparator/Type.phpr  gRr        @   vendor/phpunit/phpunit/PHPUnit/Framework/Comparator/Resource.php  gR  @      ?   vendor/phpunit/phpunit/PHPUnit/Framework/Comparator/Numeric.php  gR        C   vendor/phpunit/phpunit/PHPUnit/Framework/Comparator/DOMDocument.php  gR  7      2   vendor/phpunit/phpunit/PHPUnit/Framework/Error.phpB  gRB  x`      =   vendor/phpunit/phpunit/PHPUnit/Framework/SkippedTestError.php/
  gR/
  a,*      @   vendor/phpunit/phpunit/PHPUnit/Framework/Assert/Functions.php.in  gR  dx      =   vendor/phpunit/phpunit/PHPUnit/Framework/Assert/Functions.php   gR   ƭ8      4   vendor/phpunit/phpunit/PHPUnit/Framework/Warning.php5  gR5  e       @   vendor/phpunit/phpunit/PHPUnit/Framework/IncompleteTestError.php9
  gR9
  do      B   vendor/phpunit/phpunit/PHPUnit/Framework/SkippedTestSuiteError.php:
  gR:
  c      C   vendor/phpunit/phpunit/PHPUnit/Framework/TestSuite/DataProvider.php
  gR
  :ö      7   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint.php  gR  <E      >   vendor/phpunit/phpunit/PHPUnit/Framework/ComparatorFactory.phpI  gRI  Z\      8   vendor/phpunit/phpunit/PHPUnit/Framework/SkippedTest.php	  gR	  arr      7   vendor/phpunit/phpunit/PHPUnit/Framework/Comparator.php  gR  ):      K   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/TraversableContains.php  gR        A   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/Attribute.php  gR  	       E   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/StringMatches.php;  gR;  $n:      O   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/ClassHasStaticAttribute.php)  gR)  i      A   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/Exception.phpD  gRD  -xDɶ      ;   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/Not.phpc  gRc  `:      F   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/StringEndsWith.phpg  gRg  qR      C   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/JsonMatches.php  gR  $      ?   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/IsEmpty.phpj  gRj  طE      J   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/ObjectHasAttribute.phpL  gRL  ;2      >   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/IsNull.php   gR   8$      @   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/LessThan.phpP  gRP  >      @   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/Callback.php{  gR{  Qc      A   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/Composite.php  gR  G$a|      ;   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/Xor.phpy  gRy  %(      F   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/StringContains.php  gR  dj      ;   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/And.php  gR  Q      C   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/GreaterThan.phpY  gRY  c׆      =   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/Count.php  gR  )      C   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/ArrayHasKey.php  gR  'Fٶ      >   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/IsJson.php  gR  xVZP      :   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/Or.php  gR  +      D   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/IsInstanceOf.php  gR  c      H   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/ExceptionMessage.php[  gR[  h9      ?   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/IsEqual.php  gR  Zȶ      I   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/ClassHasAttribute.phpC  gRC        B   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/IsAnything.php  gR  ZM      A   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/PCREMatch.phpJ  gRJ  em      E   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/ExceptionCode.phpy  gRy  )V      H   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/StringStartsWith.phpV  gRV  u/<      >   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/IsTrue.php   gR   ,+Ͷ      B   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/FileExists.phpY  gRY  CŔ      O   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/TraversableContainsOnly.phpI  gRI  L      X   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/JsonMatches/ErrorMessageProvider.php  gR  nY      >   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/IsType.php  gR  Z-      @   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/SameSize.php  gR  !n+      C   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/IsIdentical.phpI  gRI  ݢ      ?   vendor/phpunit/phpunit/PHPUnit/Framework/Constraint/IsFalse.php$  gR$  c{R      9   vendor/phpunit/phpunit/PHPUnit/Framework/TestListener.phpR  gRR  }      6   vendor/phpunit/phpunit/PHPUnit/Framework/TestSuite.php^o  gR^o  ۃS      1   vendor/phpunit/phpunit/PHPUnit/Framework/Test.php
  gR
  `1      ;   vendor/phpunit/phpunit/PHPUnit/Framework/SyntheticError.phpA  gRA  fSj      8   vendor/phpunit/phpunit/PHPUnit/Framework/OutputError.php
  gR
  Cg      ;   vendor/phpunit/phpunit/PHPUnit/Framework/IncompleteTest.php
  gR
  ,9      A   vendor/phpunit/phpunit/PHPUnit/Framework/AssertionFailedError.php
  gR
  k!      ;   vendor/phpunit/phpunit/PHPUnit/Framework/SelfDescribing.php<
  gR<
  En      :   vendor/phpunit/phpunit/PHPUnit/Framework/Error/Warning.phpe
  gRe
  O	Ķ      =   vendor/phpunit/phpunit/PHPUnit/Framework/Error/Deprecated.phpx
  gRx
  fܶ      9   vendor/phpunit/phpunit/PHPUnit/Framework/Error/Notice.phpb
  gRb
  c9      7   vendor/phpunit/phpunit/PHPUnit/Framework/TestResult.php,_  gR,_  Z      >   vendor/phpunit/phpunit/PHPUnit/Framework/ComparisonFailure.php  gR  M      H   vendor/phpunit/phpunit/PHPUnit/Framework/Process/TestCaseMethod.tpl.dist  gR  Eޙ      8   vendor/phpunit/phpunit/PHPUnit/Framework/TestFailure.php  gR  yx˶      3   vendor/phpunit/phpunit/PHPUnit/Framework/Assert.phpJe gRJe $z      G   vendor/phpunit/phpunit/PHPUnit/Framework/ExpectationFailedException.php  gR  Lu!      +   vendor/phpunit/phpunit/PHPUnit/Autoload.phpu7  gRu7  N@}      .   vendor/phpunit/phpunit/PHPUnit/Autoload.php.in=  gR=         9   vendor/phpunit/phpunit/PHPUnit/Runner/TestSuiteLoader.php
  gR
  	ܳ      1   vendor/phpunit/phpunit/PHPUnit/Runner/Version.phpK  gRK  O[zh      A   vendor/phpunit/phpunit/PHPUnit/Runner/StandardTestSuiteLoader.php  gR  Ka|      8   vendor/phpunit/phpunit/PHPUnit/Runner/BaseTestRunner.php  gR  B      "   vendor/phpunit/phpunit/phpunit.php  gR            vendor/phpunit/phpunit/build.xml4$  gR4$  Ƕ      '   vendor/phpunit/phpunit/phpunit.xml.dist  gR  *      +   vendor/phpunit/phpunit/composer/bin/phpunit  gR  N       &   vendor/phpunit/phpunit/phpdox.xml.dist  gR  C֋      <   vendor/phpunit/phpunit/Tests/Extensions/RepeatedTestTest.php  gR  ]ÿ_      @   vendor/phpunit/phpunit/Tests/TextUI/exclude-group-isolation.phpt  gR  S      5   vendor/phpunit/phpunit/Tests/TextUI/filter-class.phptL  gRL  }[      ,   vendor/phpunit/phpunit/Tests/TextUI/tap.phptj  gRj  Wi      0   vendor/phpunit/phpunit/Tests/TextUI/failure.phpt3	  gR3	  cֶ      ?   vendor/phpunit/phpunit/Tests/TextUI/filter-class-isolation.phpt  gR  Ƕ      :   vendor/phpunit/phpunit/Tests/TextUI/failure-isolation.phpts	  gRs	  X#      8   vendor/phpunit/phpunit/Tests/TextUI/fatal-isolation.phpt  gR  ӄٶ      -   vendor/phpunit/phpunit/Tests/TextUI/help.phptb  gRb  ,      4   vendor/phpunit/phpunit/Tests/TextUI/list-groups.phptu  gRu  8Gu      6   vendor/phpunit/phpunit/Tests/TextUI/filter-method.phpt^  gR^  jĶ      0   vendor/phpunit/phpunit/Tests/TextUI/testdox.phpt:  gR:  w2      0   vendor/phpunit/phpunit/Tests/TextUI/default.phpt  gR  *      :   vendor/phpunit/phpunit/Tests/TextUI/filter-no-results.phptI  gRI        6   vendor/phpunit/phpunit/Tests/TextUI/dependencies2.phpt  gR  N      =   vendor/phpunit/phpunit/Tests/TextUI/test-suffix-multiple.phpt  gR  D-o      .   vendor/phpunit/phpunit/Tests/TextUI/help2.phpt  gR  Ӑ      6   vendor/phpunit/phpunit/Tests/TextUI/exclude-group.phptg  gRg  zE      @   vendor/phpunit/phpunit/Tests/TextUI/filter-method-isolation.phpt  gR  C?      .   vendor/phpunit/phpunit/Tests/TextUI/fatal.phpt  gR        .   vendor/phpunit/phpunit/Tests/TextUI/debug.phpt  gR  es      ;   vendor/phpunit/phpunit/Tests/TextUI/test-suffix-single.phpt  gR  8P      =   vendor/phpunit/phpunit/Tests/TextUI/dataprovider-testdox.phpt  gR  MSp      :   vendor/phpunit/phpunit/Tests/TextUI/default-isolation.phpt)  gR)  `ٶ      9   vendor/phpunit/phpunit/Tests/TextUI/strict-isolation.phpt  gR  S拶      <   vendor/phpunit/phpunit/Tests/TextUI/concrete-test-class.phpt  gR  x      @   vendor/phpunit/phpunit/Tests/TextUI/dependencies2-isolation.phpt  gR  @S      ?   vendor/phpunit/phpunit/Tests/TextUI/dependencies-isolation.phpt  gR  jV#˶      0   vendor/phpunit/phpunit/Tests/TextUI/log-xml.phpt  gR  r      =   vendor/phpunit/phpunit/Tests/TextUI/dataprovider-log-xml.phpt?  gR?  ՗Jd      8   vendor/phpunit/phpunit/Tests/TextUI/group-isolation.phpt  gR         1   vendor/phpunit/phpunit/Tests/TextUI/log-json.phpt  gR  #      7   vendor/phpunit/phpunit/Tests/TextUI/empty-testcase.phpta  gRa  qL      :   vendor/phpunit/phpunit/Tests/TextUI/strict-incomplete.phptG  gRG        <   vendor/phpunit/phpunit/Tests/TextUI/abstract-test-class.phptJ  gRJ  |F      5   vendor/phpunit/phpunit/Tests/TextUI/testdox-text.phpt  gR  բ       5   vendor/phpunit/phpunit/Tests/TextUI/dependencies.phpt  gR  ʹ      6   vendor/phpunit/phpunit/Tests/TextUI/dependencies3.phpt   gR   F      @   vendor/phpunit/phpunit/Tests/TextUI/dependencies3-isolation.phptB  gRB  ,w      0   vendor/phpunit/phpunit/Tests/TextUI/log-tap.phpt   gR   @m      /   vendor/phpunit/phpunit/Tests/TextUI/strict.phpt;  gR;  M̶      5   vendor/phpunit/phpunit/Tests/TextUI/testdox-html.phpt  gR  8~      G   vendor/phpunit/phpunit/Tests/TextUI/dataprovider-log-xml-isolation.phptt  gRt  {      .   vendor/phpunit/phpunit/Tests/TextUI/group.phptT  gRT  q      8   vendor/phpunit/phpunit/Tests/TextUI/exception-stack.phpt}  gR}  囂      -   vendor/phpunit/phpunit/Tests/Util/XMLTest.php/  gR/  Q}      .   vendor/phpunit/phpunit/Tests/Util/TestTest.php;&  gR;&  g>2      @   vendor/phpunit/phpunit/Tests/Util/TestDox/NamePrettifierTest.php  gR  5      /   vendor/phpunit/phpunit/Tests/Util/ClassTest.php  gR  H!1      7   vendor/phpunit/phpunit/Tests/Util/ConfigurationTest.php3  gR3  R:      .   vendor/phpunit/phpunit/Tests/Util/TypeTest.php  gR  <      .   vendor/phpunit/phpunit/Tests/Util/DiffTest.phpq  gRq  ^      0   vendor/phpunit/phpunit/Tests/Regression/783.phpt  gR  j      <   vendor/phpunit/phpunit/Tests/Regression/684/Issue684Test.phpH   gRH   J      <   vendor/phpunit/phpunit/Tests/Regression/523/Issue523Test.php  gR  G7      0   vendor/phpunit/phpunit/Tests/Regression/684.phpt$  gR$  q      >   vendor/phpunit/phpunit/Tests/Regression/1021/Issue1021Test.phpx  gRx  K      0   vendor/phpunit/phpunit/Tests/Regression/578.phpt?  gR?  k+      1   vendor/phpunit/phpunit/Tests/Regression/1021.phpt  gR  *      C   vendor/phpunit/phpunit/Tests/Regression/GitHub/581/Issue581Test.php   gR   /       C   vendor/phpunit/phpunit/Tests/Regression/GitHub/765/Issue765Test.php  gR  :/      7   vendor/phpunit/phpunit/Tests/Regression/GitHub/445.phpt  gR  j)      C   vendor/phpunit/phpunit/Tests/Regression/GitHub/445/Issue445Test.php  gR  i0ݜ      7   vendor/phpunit/phpunit/Tests/Regression/GitHub/322.phpt  gR        7   vendor/phpunit/phpunit/Tests/Regression/GitHub/498.phpt  gR  Ŷ      7   vendor/phpunit/phpunit/Tests/Regression/GitHub/244.phpt  gR  ((      A   vendor/phpunit/phpunit/Tests/Regression/GitHub/74/Issue74Test.php   gR   i      B   vendor/phpunit/phpunit/Tests/Regression/GitHub/74/NewException.php.   gR.   }/۶      C   vendor/phpunit/phpunit/Tests/Regression/GitHub/244/Issue244Test.php\  gR\  ѐfo      C   vendor/phpunit/phpunit/Tests/Regression/GitHub/503/Issue503Test.php   gR   !-      C   vendor/phpunit/phpunit/Tests/Regression/GitHub/498/Issue498Test.phpO  gRO  ?V      7   vendor/phpunit/phpunit/Tests/Regression/GitHub/581.phpt  gR  H      A   vendor/phpunit/phpunit/Tests/Regression/GitHub/322/phpunit322.xml   gR   ʶ      C   vendor/phpunit/phpunit/Tests/Regression/GitHub/322/Issue322Test.php   gR          C   vendor/phpunit/phpunit/Tests/Regression/GitHub/433/Issue433Test.php  gR  C      7   vendor/phpunit/phpunit/Tests/Regression/GitHub/863.phpt  gR        6   vendor/phpunit/phpunit/Tests/Regression/GitHub/74.phpt  gR  %lx      7   vendor/phpunit/phpunit/Tests/Regression/GitHub/503.phpt  gR        7   vendor/phpunit/phpunit/Tests/Regression/GitHub/433.phptx  gRx  !􃋶      7   vendor/phpunit/phpunit/Tests/Regression/GitHub/765.phpt{  gR{  =z      <   vendor/phpunit/phpunit/Tests/Regression/578/Issue578Test.php=  gR=  "޴      0   vendor/phpunit/phpunit/Tests/Regression/523.phpt  gR  ˚Z      7   vendor/phpunit/phpunit/Tests/Regression/783/TwoTest.php   gR   z      ;   vendor/phpunit/phpunit/Tests/Regression/783/ParentSuite.php   gR    r      7   vendor/phpunit/phpunit/Tests/Regression/783/OneTest.php   gR   |Ŷ      :   vendor/phpunit/phpunit/Tests/Regression/783/ChildSuite.php(  gR(  nY7      9   vendor/phpunit/phpunit/Tests/_files/InheritedTestCase.php   gR   ¹(      >   vendor/phpunit/phpunit/Tests/_files/configuration_xinclude.xmlZ  gRZ  ϝr      1   vendor/phpunit/phpunit/Tests/_files/NonStatic.phpW   gRW   ն      >   vendor/phpunit/phpunit/Tests/_files/ThrowExceptionTestCase.php   gR         I   vendor/phpunit/phpunit/Tests/_files/ChangeCurrentWorkingDirectoryTest.php   gR   4Aܣ      .   vendor/phpunit/phpunit/Tests/_files/Struct.phpv   gRv   f      @   vendor/phpunit/phpunit/Tests/_files/ThrowNoExceptionTestCase.phps   gRs   ʪc      ;   vendor/phpunit/phpunit/Tests/_files/JsonData/arrayObject.js"   gR"   P	      =   vendor/phpunit/phpunit/Tests/_files/JsonData/simpleObject2.js   gR   uٶ      <   vendor/phpunit/phpunit/Tests/_files/JsonData/simpleObject.js   gR   uٶ      B   vendor/phpunit/phpunit/Tests/_files/SelectorAssertionsFixture.html  gR        -   vendor/phpunit/phpunit/Tests/_files/Error.php   gR   m      E   vendor/phpunit/phpunit/Tests/_files/RequirementsClassDocBlockTest.phpv  gRv  @r      2   vendor/phpunit/phpunit/Tests/_files/MockRunner.phpx   gRx   L'z      ;   vendor/phpunit/phpunit/Tests/_files/TemplateMethodsTest.php  gR        C   vendor/phpunit/phpunit/Tests/_files/structureIsSameButDataIsNot.xml^  gR^  tG      D   vendor/phpunit/phpunit/Tests/_files/ClassWithNonPublicAttributes.phpx  gRx  z@^      ;   vendor/phpunit/phpunit/Tests/_files/DependencyTestSuite.phpv  gRv  o䚶      9   vendor/phpunit/phpunit/Tests/_files/ClassWithToString.php	  gR	  VUrm      7   vendor/phpunit/phpunit/Tests/_files/NotVoidTestCase.phpC   gRC   烶      8   vendor/phpunit/phpunit/Tests/_files/RequirementsTest.phpu  gRu  7      5   vendor/phpunit/phpunit/Tests/_files/ExceptionTest.php  gR  ^׶      Q   vendor/phpunit/phpunit/Tests/_files/structureAttributesAreSameButValuesAreNot.xml  gR         >   vendor/phpunit/phpunit/Tests/_files/ExceptionNamespaceTest.phpN  gRN  ָ      .   vendor/phpunit/phpunit/Tests/_files/WasRun.php   gR   /?kn      6   vendor/phpunit/phpunit/Tests/_files/DoubleTestCase.php  gR  j      /   vendor/phpunit/phpunit/Tests/_files/Success.phph   gRh   87      5   vendor/phpunit/phpunit/Tests/_files/configuration.xml  gR  й=      H   vendor/phpunit/phpunit/Tests/_files/structureWrongNumberOfAttributes.xml   gR   o.      ?   vendor/phpunit/phpunit/Tests/_files/ExceptionInTearDownTest.php  gR  v      9   vendor/phpunit/phpunit/Tests/_files/NoArgTestCaseTest.phps   gRs         <   vendor/phpunit/phpunit/Tests/_files/BankAccountTest.test.phpo  gRo  yͶ      @   vendor/phpunit/phpunit/Tests/_files/structureIgnoreTextNodes.xmly  gRy  +o      +   vendor/phpunit/phpunit/Tests/_files/bar.xml   gR   ]{@      <   vendor/phpunit/phpunit/Tests/_files/ExceptionInSetUpTest.php  gR  }      ;   vendor/phpunit/phpunit/Tests/_files/MultiDependencyTest.php  gR  yc      3   vendor/phpunit/phpunit/Tests/_files/NoTestCases.phpl   gRl   K      3   vendor/phpunit/phpunit/Tests/_files/SampleClass.php   gR   `ע      :   vendor/phpunit/phpunit/Tests/_files/expectedFileFormat.txt   gR   Ԩs      9   vendor/phpunit/phpunit/Tests/_files/EmptyTestCaseTest.phpE   gRE   [">      4   vendor/phpunit/phpunit/Tests/_files/AbstractTest.phps   gRs   $      K   vendor/phpunit/phpunit/Tests/_files/ExceptionInAssertPostConditionsTest.php  gR  5|      7   vendor/phpunit/phpunit/Tests/_files/ExceptionInTest.php  gR  ¾p      6   vendor/phpunit/phpunit/Tests/_files/ExceptionStack.php"  gR"        7   vendor/phpunit/phpunit/Tests/_files/NoTestCaseClass.php    gR    3      =   vendor/phpunit/phpunit/Tests/_files/DependencyFailureTest.php2  gR2  ̑      3   vendor/phpunit/phpunit/Tests/_files/BankAccount.php  gR  m      4   vendor/phpunit/phpunit/Tests/_files/ConcreteTest.php~   gR~   [O2      ,   vendor/phpunit/phpunit/Tests/_files/Book.php	  gR	  ;      3   vendor/phpunit/phpunit/Tests/_files/FailureTest.php)  gR)  bʖ      C   vendor/phpunit/phpunit/Tests/_files/structureWrongNumberOfNodes.xmlD  gRD  \W      1   vendor/phpunit/phpunit/Tests/_files/Singleton.phpq  gRq  9k.ж      8   vendor/phpunit/phpunit/Tests/_files/OverrideTestCase.php   gR   'ζ      4   vendor/phpunit/phpunit/Tests/_files/TestIterator.phpG  gRG  b      9   vendor/phpunit/phpunit/Tests/_files/structureExpected.xmlN  gRN  1?      6   vendor/phpunit/phpunit/Tests/_files/IncompleteTest.php   gR   쓶      1   vendor/phpunit/phpunit/Tests/_files/StackTest.php  gR        +   vendor/phpunit/phpunit/Tests/_files/foo.xml   gR   h$ƶ      8   vendor/phpunit/phpunit/Tests/_files/DataProviderTest.php  gR        /   vendor/phpunit/phpunit/Tests/_files/Failure.php   gR   >t      J   vendor/phpunit/phpunit/Tests/_files/ExceptionInAssertPreConditionsTest.php  gR        .   vendor/phpunit/phpunit/Tests/_files/Author.php
  gR
  S      7   vendor/phpunit/phpunit/Tests/_files/BankAccountTest.php\  gR\  ̈      2   vendor/phpunit/phpunit/Tests/_files/Calculator.php   gR   oP      1   vendor/phpunit/phpunit/Tests/_files/FatalTest.php   gR   T      9   vendor/phpunit/phpunit/Tests/_files/NotPublicTestCase.php   gR   @7/      6   vendor/phpunit/phpunit/Tests/_files/OutputTestCase.phpU  gRU  Yx      =   vendor/phpunit/phpunit/Tests/_files/DependencySuccessTest.php2  gR2  ӻ      3   vendor/phpunit/phpunit/Tests/_files/NothingTest.phpm   gRm   43z      7   vendor/phpunit/phpunit/Tests/_files/ConcreteTest.my.php   gR   8*      3   vendor/phpunit/phpunit/Tests/_files/OneTestCase.php   gR   rs      9   vendor/phpunit/phpunit/Tests/Framework/ComparatorTest.phpq  gRq  'aB      7   vendor/phpunit/phpunit/Tests/Framework/TestCaseTest.php;  gR;        ?   vendor/phpunit/phpunit/Tests/Framework/Assert/FunctionsTest.php  gR  2n      :   vendor/phpunit/phpunit/Tests/Framework/TestFailureTest.php
  gR
  Ҷ      ;   vendor/phpunit/phpunit/Tests/Framework/TestListenerTest.php  gR  2      E   vendor/phpunit/phpunit/Tests/Framework/Constraint/JsonMatchesTest.php  gR  
{      Z   vendor/phpunit/phpunit/Tests/Framework/Constraint/JsonMatches/ErrorMessageProviderTest.php  gR  !      9   vendor/phpunit/phpunit/Tests/Framework/ConstraintTest.phpZ gRZ ӗ      5   vendor/phpunit/phpunit/Tests/Framework/AssertTest.php gR jﷶ      4   vendor/phpunit/phpunit/Tests/Framework/SuiteTest.phpa  gRa  ޾      >   vendor/phpunit/phpunit/Tests/Framework/TestImplementorTest.php  gR  ?      :   vendor/phpunit/phpunit/Tests/Runner/BaseTestRunnerTest.php
  gR
        1   vendor/phpunit/phpunit-mock-objects/composer.jsonr  gRr  eO.ж      /   vendor/phpunit/phpunit-mock-objects/package.xml	"  gR	"         3   vendor/phpunit/phpunit-mock-objects/build/phpmd.xml  gR  <dy      7   vendor/phpunit/phpunit-mock-objects/build/travis-ci.xml  gR  hM      b   vendor/phpunit/phpunit-mock-objects/build/PHPCS/Sniffs/ControlStructures/ControlSignatureSniff.php  gR  Aȶ      _   vendor/phpunit/phpunit-mock-objects/build/PHPCS/Sniffs/Whitespace/ConcatenationSpacingSniff.phpU  gRU  CN      ;   vendor/phpunit/phpunit-mock-objects/build/PHPCS/ruleset.xml-  gR-  K      +   vendor/phpunit/phpunit-mock-objects/LICENSE  gR  BҶ      Y   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Matcher/InvokedCount.php  gR  `;      W   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Matcher/MethodName.phpV  gRV  %iҶ      W   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Matcher/Invocation.php  gR  T      W   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Matcher/Parameters.php  gR  (?      Z   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Matcher/AnyParameters.php  gR  -      \   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Matcher/InvokedRecorder.php  gR  䶶      [   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Matcher/InvokedAtIndex.php  gR        \   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Matcher/AnyInvokedCount.phpU  gRU  @9Ӷ      `   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Matcher/StatelessInvocation.php  gR  Cֶ      _   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Matcher/InvokedAtLeastOnce.phpC  gRC  ΰhU      N   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Invokable.phpI  gRI        L   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Matcher.php&  gR&  wq      O   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/MockObject.php  gR  ?R      U   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Builder/Identity.php	  gR	  oӶ      \   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Builder/ParametersMatch.phpu  gRu  I      V   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Builder/Namespace.php  gR  >Ͷ      ]   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Builder/InvocationMocker.php  gR  [6      R   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Builder/Match.php  gR  DR:      Q   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Builder/Stub.php  gR  Vmö      \   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Builder/MethodNameMatch.php  gR  (0      Z   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Stub/ConsecutiveCalls.php"  gR"  MmԶ      X   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Stub/ReturnValueMap.php  gR  z%Xu      S   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Stub/Exception.phpn  gRn  l1      T   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Stub/ReturnSelf.php  gR        X   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Stub/ReturnArgument.phpy  gRy  :      [   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Stub/MatcherCollection.phpv  gRv  <      X   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Stub/ReturnCallback.php  gR  q^      P   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Stub/Return.php  gR  6      O   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Invocation.php
  gR
  #ޢ      V   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Invocation/Object.php  gR  Z      V   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Invocation/Static.phpR  gRR  k#      U   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/InvocationMocker.php  gR  720      P   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/MockBuilder.php  gR  q      _   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Generator/wsdl_method.tpl.dist<   gR<   i      `   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Generator/mocked_clone.tpl.dist   gR   aT      `   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Generator/mocked_class.tpl.dist  gR  b)      ^   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Generator/wsdl_class.tpl.dist   gR         _   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Generator/trait_class.tpl.dist-   gR-   1,      h   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Generator/mocked_object_method.tpl.dist  gR  bV      b   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Generator/unmocked_clone.tpl.dist   gR   8W}ض      h   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Generator/mocked_static_method.tpl.dist  gR  >K      M   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Autoload.php  gR  xy      N   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Generator.php1i  gR1i  ZI      I   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Stub.phpi  gRi  6)/      O   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Verifiable.php'  gR'  %      P   vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Autoload.php.in	  gR	  W      6   vendor/phpunit/phpunit-mock-objects/ChangeLog.markdown  gR  Uz      -   vendor/phpunit/phpunit-mock-objects/build.xmlM  gRM  #ե      4   vendor/phpunit/phpunit-mock-objects/phpunit.xml.dist  gR  <2      ;   vendor/phpunit/phpunit-mock-objects/Tests/GeneratorTest.php  gR  [H      N   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/namespaced_interface.phpt
  gR
        r   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/nonexistent_class_with_namespace_starting_with_separator.phpt  gR  JЏ      Q   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/class_call_parent_clone.phpt  gR  D      g   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/namespaced_class_dont_call_parent_constructor.phpt  gR        \   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/class_dont_call_parent_constructor.phpt  gR  Hd      a   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/namespaced_class_dont_call_parent_clone.phpt  gR  <!#B      \   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/namespaced_class_call_parent_clone.phpt  gR  n      ?   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/class.phpt  gR  _߶      b   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/namespaced_class_call_parent_constructor.phpt  gR        G   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/class_partial.phpt
  gR
  cu      J   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/namespaced_class.phpt  gR  VQ      N   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/Invocation/ObjectTest.php	  gR	  ÷      N   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/Invocation/StaticTest.php  gR  ]+n      n   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/class_implementing_interface_call_parent_constructor.phpt  gR  Rö      ~   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/namespaced_class_implementing_interface_dont_call_parent_constructor.phpt  gR  ~uR      X   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/invocation_object_clone_object.phpt  gR  ~03      N   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/wsdl_class_namespace.phpt  gR  |      s   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/class_implementing_interface_dont_call_parent_constructor.phpt  gR  Rö      Z   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/nonexistent_class_with_namespace.phpt  gR  '      L   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/wsdl_class_partial.phpt#  gR#        V   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/class_dont_call_parent_clone.phpt  gR  ݂       C   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/interface.phpt
  gR
  _t      W   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/class_call_parent_constructor.phpt  gR  Hd      D   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/wsdl_class.phptq  gRq  
      K   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/nonexistent_class.phptm  gRm  Z2      y   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/namespaced_class_implementing_interface_call_parent_constructor.phpt  gR  ~uR      R   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/namespaced_class_partial.phpt
  gR
  դa      X   vendor/phpunit/phpunit-mock-objects/Tests/MockObject/invocation_static_clone_object.phpt  gR  C      C   vendor/phpunit/phpunit-mock-objects/Tests/_files/MethodCallback.phpr  gRr  |ܶ      >   vendor/phpunit/phpunit-mock-objects/Tests/_files/SomeClass.php   gR   ?A      =   vendor/phpunit/phpunit-mock-objects/Tests/_files/Mockable.php  gR  ^w%      J   vendor/phpunit/phpunit-mock-objects/Tests/_files/AbstractMockTestClass.php[   gR[   Ĕ      N   vendor/phpunit/phpunit-mock-objects/Tests/_files/MethodCallbackByReference.php   gR   \
      E   vendor/phpunit/phpunit-mock-objects/Tests/_files/FunctionCallback.php   gR         I   vendor/phpunit/phpunit-mock-objects/Tests/_files/PartialMockTestClass.php  gR  :Bڶ      @   vendor/phpunit/phpunit-mock-objects/Tests/_files/AnInterface.phpC   gRC   !L      H   vendor/phpunit/phpunit-mock-objects/Tests/_files/StaticMockTestClass.php   gR   8      B   vendor/phpunit/phpunit-mock-objects/Tests/_files/GoogleSearch.wsdl   gR   M0$      <   vendor/phpunit/phpunit-mock-objects/Tests/MockObjectTest.phpcW  gRcW  |Ns<      =   vendor/phpunit/phpunit-mock-objects/Tests/MockBuilderTest.php  gR  B      .   vendor/phpunit/php-code-coverage/composer.json  gR  @^      ,   vendor/phpunit/php-code-coverage/package.xml  gR  J3ƶ      8   vendor/phpunit/php-code-coverage/scripts/auto_append.phpt   gRt   s      9   vendor/phpunit/php-code-coverage/scripts/auto_prepend.php  gR        0   vendor/phpunit/php-code-coverage/build/phpmd.xml  gR  <dy      4   vendor/phpunit/php-code-coverage/build/travis-ci.xml^  gR^        _   vendor/phpunit/php-code-coverage/build/PHPCS/Sniffs/ControlStructures/ControlSignatureSniff.php  gR  Aȶ      \   vendor/phpunit/php-code-coverage/build/PHPCS/Sniffs/Whitespace/ConcatenationSpacingSniff.phpU  gRU  CN      8   vendor/phpunit/php-code-coverage/build/PHPCS/ruleset.xml-  gR-  K      (   vendor/phpunit/php-code-coverage/LICENSE  gR  w!      0   vendor/phpunit/php-code-coverage/README.markdown  gR  u      *   vendor/phpunit/php-code-coverage/build.xml  gR  |D      1   vendor/phpunit/php-code-coverage/phpunit.xml.dist  gR  dlħ      <   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Driver.php
  gR
  n      ?   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Exception.php	  gR	  
u:      :   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Util.php'  gR'  j      P   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Util/InvalidArgumentHelper.phpW  gRW  Y)      <   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Filter.php'  gR'  [      =   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Version.php<  gR<  ˃      A   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/Node.php*%  gR*%  B      A   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/HTML.php  gR  z      O   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/HTML/Renderer/File.phpKT  gRKT  ckV      T   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/HTML/Renderer/Dashboard.php  gR  /MKU      e   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/HTML/Renderer/Template/method_item.html.distX  gRX  %J      r   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/HTML/Renderer/Template/img/glyphicons-halflings-white.pngI"  gRI"  C      l   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/HTML/Renderer/Template/img/glyphicons-halflings.png1  gR1  V(F      _   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/HTML/Renderer/Template/js/html5shiv.jsH	  gRH	  ߶      c   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/HTML/Renderer/Template/js/bootstrap.min.jsl{  gRl{        `   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/HTML/Renderer/Template/js/jquery.min.jsi gRi v      `   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/HTML/Renderer/Template/js/highcharts.js gR ~K&      ]   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/HTML/Renderer/Template/css/style.cssq  gRq  
*      p   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/HTML/Renderer/Template/css/bootstrap-responsive.min.css@  gR@  T      e   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/HTML/Renderer/Template/css/bootstrap.min.css gR ak      h   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/HTML/Renderer/Template/directory_item.html.dist  gR  -,      c   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/HTML/Renderer/Template/file_item.html.dist;  gR;  rS      c   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/HTML/Renderer/Template/dashboard.html.dist>  gR>  I      c   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/HTML/Renderer/Template/directory.html.dist  gR  pW      ^   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/HTML/Renderer/Template/file.html.dist  gR  `      f   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/HTML/Renderer/Template/coverage_bar.html.dist   gR         T   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/HTML/Renderer/Directory.php  gR  [J      J   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/HTML/Renderer.php#  gR#  ^Q      A   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/Text.php6+  gR6+   8R      C   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/Clover.php2  gR2  )ֶ      @   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/PHP.php{  gR{  =      D   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/Factory.php2  gR2  [      F   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/Node/File.phpR  gRR  \-Ƕ      J   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/Node/Iterator.php  gR  u      K   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Report/Node/Directory.php#0  gR#0  3      >   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Autoload.php-  gR-  GG6      C   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Driver/Xdebug.php  gR  ei      A   vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Autoload.php.inA
  gRA
        5   vendor/phpunit/php-code-coverage/PHP/CodeCoverage.php*Y  gR*Y  0:*U      3   vendor/phpunit/php-code-coverage/Tests/TestCase.phpL$  gRL$  9kѶ      G   vendor/phpunit/php-code-coverage/Tests/_files/source_without_ignore.php,   gR,   [6p      H   vendor/phpunit/php-code-coverage/Tests/_files/CoverageNotPrivateTest.php   gR         Y   vendor/phpunit/php-code-coverage/Tests/_files/CoverageMethodParenthesesWhitespaceTest.php  gR  i>      L   vendor/phpunit/php-code-coverage/Tests/_files/NamespaceCoverageClassTest.php   gR   Qd      >   vendor/phpunit/php-code-coverage/Tests/_files/CoveredClass.phpK  gRK  o      A   vendor/phpunit/php-code-coverage/Tests/_files/CoveredFunction.php$   gR$   Y      P   vendor/phpunit/php-code-coverage/Tests/_files/NamespaceCoverageNotPublicTest.php   gR         D   vendor/phpunit/php-code-coverage/Tests/_files/CoveragePublicTest.php   gR   ʶ      K   vendor/phpunit/php-code-coverage/Tests/_files/CoverageClassExtendedTest.php   gR         O   vendor/phpunit/php-code-coverage/Tests/_files/NotExistingCoveredElementTest.php  gR  ;HV      G   vendor/phpunit/php-code-coverage/Tests/_files/CoverageNotPublicTest.php   gR         N   vendor/phpunit/php-code-coverage/Tests/_files/NamespaceCoveragePrivateTest.php   gR   ^[      S   vendor/phpunit/php-code-coverage/Tests/_files/NamespaceCoverageNotProtectedTest.php  gR        [   vendor/phpunit/php-code-coverage/Tests/_files/CoverageFunctionParenthesesWhitespaceTest.php   gR   i      Q   vendor/phpunit/php-code-coverage/Tests/_files/CoverageFunctionParenthesesTest.php   gR   U ض      G   vendor/phpunit/php-code-coverage/Tests/_files/NamespaceCoveredClass.php[  gR[  F
      J   vendor/phpunit/php-code-coverage/Tests/_files/CoverageNotProtectedTest.php   gR   #%      O   vendor/phpunit/php-code-coverage/Tests/_files/CoverageMethodParenthesesTest.php   gR   p      T   vendor/phpunit/php-code-coverage/Tests/_files/CoverageTwoDefaultClassAnnotations.phpL  gRL  qö      X   vendor/phpunit/php-code-coverage/Tests/_files/NamespaceCoverageCoversClassPublicTest.php)  gR)  Ha༶      Q   vendor/phpunit/php-code-coverage/Tests/_files/NamespaceCoverageNotPrivateTest.php   gR   C׶      U   vendor/phpunit/php-code-coverage/Tests/_files/CoverageMethodOneLineAnnotationTest.php   gR   i      M   vendor/phpunit/php-code-coverage/Tests/_files/NamespaceCoverageMethodTest.php   gR   ݶ      G   vendor/phpunit/php-code-coverage/Tests/_files/CoverageProtectedTest.php   gR   չZ      G   vendor/phpunit/php-code-coverage/Tests/_files/source_with_namespace.php   gR         M   vendor/phpunit/php-code-coverage/Tests/_files/NamespaceCoveragePublicTest.php   gR   E%P      =   vendor/phpunit/php-code-coverage/Tests/_files/BankAccount.phpv  gRv  wi      T   vendor/phpunit/php-code-coverage/Tests/_files/NamespaceCoverageClassExtendedTest.php   gR   }`      F   vendor/phpunit/php-code-coverage/Tests/_files/ignored-lines-clover.xmlC  gRC  H2ж      R   vendor/phpunit/php-code-coverage/Tests/_files/NamespaceCoverageCoversClassTest.php  gR  \yr]      C   vendor/phpunit/php-code-coverage/Tests/_files/CoverageClassTest.php   gR   
Xl      Z   vendor/phpunit/php-code-coverage/Tests/_files/source_with_class_and_anonymous_function.php  gR  #e      E   vendor/phpunit/php-code-coverage/Tests/_files/CoverageNothingTest.php  gR  Զ      J   vendor/phpunit/php-code-coverage/Tests/_files/source_without_namespace.php   gR   (      V   vendor/phpunit/php-code-coverage/Tests/_files/class-with-anonymous-function-clover.xml]  gR]  ڈ      E   vendor/phpunit/php-code-coverage/Tests/_files/CoveragePrivateTest.php   gR   ܶ      F   vendor/phpunit/php-code-coverage/Tests/_files/CoverageFunctionTest.php   gR         B   vendor/phpunit/php-code-coverage/Tests/_files/CoverageNoneTest.php   gR   Bζ      P   vendor/phpunit/php-code-coverage/Tests/_files/NamespaceCoverageProtectedTest.php   gR   pr      Q   vendor/phpunit/php-code-coverage/Tests/_files/source_with_oneline_annotations.php  gR  =G      D   vendor/phpunit/php-code-coverage/Tests/_files/CoverageMethodTest.php   gR   D7      A   vendor/phpunit/php-code-coverage/Tests/_files/BankAccountTest.php  gR  뻊      D   vendor/phpunit/php-code-coverage/Tests/_files/source_with_ignore.php  gR  %`P      D   vendor/phpunit/php-code-coverage/Tests/_files/BankAccount-clover.xml  gR  _?      F   vendor/phpunit/php-code-coverage/Tests/PHP/CodeCoverage/FilterTest.php+  gR+  
D2T      D   vendor/phpunit/php-code-coverage/Tests/PHP/CodeCoverage/UtilTest.php  gR  h<C:      M   vendor/phpunit/php-code-coverage/Tests/PHP/CodeCoverage/Report/CloverTest.php  gR  9Ƕ      N   vendor/phpunit/php-code-coverage/Tests/PHP/CodeCoverage/Report/FactoryTest.php$  gR$  e}      ?   vendor/phpunit/php-code-coverage/Tests/PHP/CodeCoverageTest.phpA  gRA  f      2   vendor/phpunit/php-file-iterator/File/Iterator.phpc  gRc  ~ԃ      9   vendor/phpunit/php-file-iterator/File/Iterator/Facade.php  gR  l      :   vendor/phpunit/php-file-iterator/File/Iterator/Factory.phph  gRh  ڶ      ;   vendor/phpunit/php-file-iterator/File/Iterator/Autoload.php	  gR	        >   vendor/phpunit/php-file-iterator/File/Iterator/Autoload.php.in*	  gR*	  N ۶      .   vendor/phpunit/php-file-iterator/composer.json6  gR6  \      ,   vendor/phpunit/php-file-iterator/package.xml  gR  eR      0   vendor/phpunit/php-file-iterator/build/phpmd.xml  gR  <dy      _   vendor/phpunit/php-file-iterator/build/PHPCS/Sniffs/ControlStructures/ControlSignatureSniff.php  gR  Aȶ      \   vendor/phpunit/php-file-iterator/build/PHPCS/Sniffs/Whitespace/ConcatenationSpacingSniff.phpU  gRU  CN      8   vendor/phpunit/php-file-iterator/build/PHPCS/ruleset.xml-  gR-  K      (   vendor/phpunit/php-file-iterator/LICENSE  gR  |      0   vendor/phpunit/php-file-iterator/README.markdownF  gRF  _h'      3   vendor/phpunit/php-file-iterator/ChangeLog.markdown  gR  $      *   vendor/phpunit/php-file-iterator/build.xml  gR  D      .   vendor/phpunit/php-text-template/composer.json  gR  (       2   vendor/phpunit/php-text-template/Text/Template.php  gR  Py      ;   vendor/phpunit/php-text-template/Text/Template/Autoload.php	  gR	  Ƕ      >   vendor/phpunit/php-text-template/Text/Template/Autoload.php.in	  gR	  j      ,   vendor/phpunit/php-text-template/package.xmlB  gRB  j(侶      0   vendor/phpunit/php-text-template/build/phpmd.xml  gR  <dy      _   vendor/phpunit/php-text-template/build/PHPCS/Sniffs/ControlStructures/ControlSignatureSniff.php  gR  Aȶ      \   vendor/phpunit/php-text-template/build/PHPCS/Sniffs/Whitespace/ConcatenationSpacingSniff.phpU  gRU  CN      8   vendor/phpunit/php-text-template/build/PHPCS/ruleset.xml-  gR-  K      (   vendor/phpunit/php-text-template/LICENSE  gR  rȶ      0   vendor/phpunit/php-text-template/README.markdownF  gRF  Q      3   vendor/phpunit/php-text-template/ChangeLog.markdown  gR        *   vendor/phpunit/php-text-template/build.xml  gR  RG      &   vendor/phpunit/php-timer/composer.json  gR  o      $   vendor/phpunit/php-timer/package.xml  gR  0T      (   vendor/phpunit/php-timer/build/phpmd.xml  gR  <dy      W   vendor/phpunit/php-timer/build/PHPCS/Sniffs/ControlStructures/ControlSignatureSniff.php  gR  Aȶ      T   vendor/phpunit/php-timer/build/PHPCS/Sniffs/Whitespace/ConcatenationSpacingSniff.phpU  gRU  CN      0   vendor/phpunit/php-timer/build/PHPCS/ruleset.xml-  gR-  K          vendor/phpunit/php-timer/LICENSE  gR  N>      "   vendor/phpunit/php-timer/build.xml  gR  (T      )   vendor/phpunit/php-timer/phpunit.xml.dist  gR  -      /   vendor/phpunit/php-timer/PHP/Timer/Autoload.phpx	  gRx	        2   vendor/phpunit/php-timer/PHP/Timer/Autoload.php.inl	  gRl	  Ԩ      &   vendor/phpunit/php-timer/PHP/Timer.php6  gR6  #X6      ,   vendor/phpunit/php-timer/Tests/TimerTest.php  gR  ̽      6   vendor/zendframework/zend-json/Zend/Json/composer.json  gR  h      4   vendor/zendframework/zend-json/Zend/Json/Encoder.phpIH  gRIH  Z      1   vendor/zendframework/zend-json/Zend/Json/Expr.php1  gR1  xk      O   vendor/zendframework/zend-json/Zend/Json/Exception/InvalidArgumentException.php  gR  Q      G   vendor/zendframework/zend-json/Zend/Json/Exception/RuntimeException.php  gR  @5k`      I   vendor/zendframework/zend-json/Zend/Json/Exception/ExceptionInterface.phpv  gRv  Ҷ      M   vendor/zendframework/zend-json/Zend/Json/Exception/BadMethodCallException.php  gR  bR      I   vendor/zendframework/zend-json/Zend/Json/Exception/RecursionException.php  gR  w      1   vendor/zendframework/zend-json/Zend/Json/Json.php:  gR:  =      4   vendor/zendframework/zend-json/Zend/Json/Decoder.php.F  gR.F  	oƶ      @   vendor/zendframework/zend-json/Zend/Json/Server/Request/Http.php  gR  ѳ      9   vendor/zendframework/zend-json/Zend/Json/Server/Error.php  gR  ɿ      9   vendor/zendframework/zend-json/Zend/Json/Server/Cache.php  gR  Z      7   vendor/zendframework/zend-json/Zend/Json/Server/Smd.php'  gR'  H L      ?   vendor/zendframework/zend-json/Zend/Json/Server/Smd/Service.php"+  gR"+  l      :   vendor/zendframework/zend-json/Zend/Json/Server/Server.phpi;  gRi;  dA:      V   vendor/zendframework/zend-json/Zend/Json/Server/Exception/InvalidArgumentException.php  gR  	      N   vendor/zendframework/zend-json/Zend/Json/Server/Exception/RuntimeException.php  gR  fQ      P   vendor/zendframework/zend-json/Zend/Json/Server/Exception/ExceptionInterface.php  gR  {6      L   vendor/zendframework/zend-json/Zend/Json/Server/Exception/ErrorException.php4  gR4  Mp      K   vendor/zendframework/zend-json/Zend/Json/Server/Exception/HttpException.php  gR  y      ;   vendor/zendframework/zend-json/Zend/Json/Server/Request.php  gR  /<*      A   vendor/zendframework/zend-json/Zend/Json/Server/Response/Http.php  gR  s      <   vendor/zendframework/zend-json/Zend/Json/Server/Response.php  gR  )$      :   vendor/zendframework/zend-json/Zend/Json/Server/Client.php[  gR[  h
R      K   vendor/zendframework/zend-stdlib/Zend/Stdlib/ArraySerializableInterface.php  gR        D   vendor/zendframework/zend-stdlib/Zend/Stdlib/ParametersInterface.php<  gR<  wIC      :   vendor/zendframework/zend-stdlib/Zend/Stdlib/composer.json  gR  g|      8   vendor/zendframework/zend-stdlib/Zend/Stdlib/Message.phpb  gRb  $      D   vendor/zendframework/zend-stdlib/Zend/Stdlib/StringWrapper/Iconv.php  gR  U{      T   vendor/zendframework/zend-stdlib/Zend/Stdlib/StringWrapper/AbstractStringWrapper.php!  gR!  {e      U   vendor/zendframework/zend-stdlib/Zend/Stdlib/StringWrapper/StringWrapperInterface.php  gR  L`      C   vendor/zendframework/zend-stdlib/Zend/Stdlib/StringWrapper/Intl.php  gR  	Y      E   vendor/zendframework/zend-stdlib/Zend/Stdlib/StringWrapper/Native.php  gR  ˫Z\      G   vendor/zendframework/zend-stdlib/Zend/Stdlib/StringWrapper/MbString.php  gR  b      B   vendor/zendframework/zend-stdlib/Zend/Stdlib/ResponseInterface.php  gR  Pj@      A   vendor/zendframework/zend-stdlib/Zend/Stdlib/SplPriorityQueue.phpa  gRa  Dy      ;   vendor/zendframework/zend-stdlib/Zend/Stdlib/Parameters.phpn	  gRn	  ԭض      I   vendor/zendframework/zend-stdlib/Zend/Stdlib/ParameterObjectInterface.php  gR  J      9   vendor/zendframework/zend-stdlib/Zend/Stdlib/SplQueue.phpI  gRI  3      A   vendor/zendframework/zend-stdlib/Zend/Stdlib/RequestInterface.php  gR  '      G   vendor/zendframework/zend-stdlib/Zend/Stdlib/compatibility/autoload.php`  gR`  U      @   vendor/zendframework/zend-stdlib/Zend/Stdlib/AbstractOptions.php  gR  =X%      <   vendor/zendframework/zend-stdlib/Zend/Stdlib/StringUtils.phpj  gRj  f      5   vendor/zendframework/zend-stdlib/Zend/Stdlib/Glob.php  gR  yIn      A   vendor/zendframework/zend-stdlib/Zend/Stdlib/MessageInterface.php  gR  L9      9   vendor/zendframework/zend-stdlib/Zend/Stdlib/SplStack.phpR  gRR  /      >   vendor/zendframework/zend-stdlib/Zend/Stdlib/PriorityQueue.php  gR  0N      ;   vendor/zendframework/zend-stdlib/Zend/Stdlib/ArrayStack.phpW  gRW  x      V   vendor/zendframework/zend-stdlib/Zend/Stdlib/ArrayObject/PhpReferenceCompatibility.php&  gR&  `      S   vendor/zendframework/zend-stdlib/Zend/Stdlib/ArrayObject/PhpLegacyCompatibility.php  gR  ^oܶ      J   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/AbstractHydrator.php  gR  ٶ      P   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Aggregate/ExtractEvent.php\  gR\  kL      P   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Aggregate/HydrateEvent.phpH  gRH  C`F      U   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Aggregate/AggregateHydrator.php	  gR	   O\      T   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Aggregate/HydratorListener.php	  gR	  ζ      H   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/ObjectProperty.php?  gR?  EZ~      K   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/ArraySerializable.php	  gR	  6z;      O   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/HydratorPluginManager.php!  gR!  5      D   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Reflection.php
  gR
  -"}      R   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/StrategyEnabledInterface.phph  gRh  #h      R   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/MethodMatchFilter.php  gR  wC      I   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/IsFilter.php  gR  .cŶ      X   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/NumberOfParameterFilter.php  gR   UVA      P   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/FilterComposite.php3  gR3  Z4      Y   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/OptionalParametersFilter.php\  gR\  ^]      X   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/FilterProviderInterface.php  gR  zxN      J   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/HasFilter.php  gR  i      P   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/FilterInterface.phpY  gRY  :zͶ      J   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Filter/GetFilter.php  gR  N$      F   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/ClassMethods.phpZ  gRZ        P   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/HydratorAwareInterface.php  gR  P      R   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/HydratorOptionsInterface.php  gR  @      K   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/HydratorInterface.php  gR  9O      T   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Strategy/StrategyInterface.phpE  gRE  ⪶      R   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Strategy/ClosureStrategy.php
  gR
  a      W   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Strategy/SerializableStrategy.php  gR  x      R   vendor/zendframework/zend-stdlib/Zend/Stdlib/Hydrator/Strategy/DefaultStrategy.php  gR        =   vendor/zendframework/zend-stdlib/Zend/Stdlib/ErrorHandler.php#
  gR#
  ~@%      V   vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/ExtensionNotLoadedException.php  gR  }/R      S   vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/InvalidArgumentException.php  gR  ;~Ƕ      K   vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/RuntimeException.php  gR  :      S   vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/InvalidCallbackException.php  gR  F      I   vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/LogicException.php  gR  yt&      J   vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/DomainException.php  gR  gݥb      M   vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/ExceptionInterface.php  gR  YtA      Q   vendor/zendframework/zend-stdlib/Zend/Stdlib/Exception/BadMethodCallException.php  gR  2      F   vendor/zendframework/zend-stdlib/Zend/Stdlib/DispatchableInterface.php  gR  xUU      <   vendor/zendframework/zend-stdlib/Zend/Stdlib/ArrayObject.php  gR  D      @   vendor/zendframework/zend-stdlib/Zend/Stdlib/CallbackHandler.php  gR  w      G   vendor/zendframework/zend-stdlib/Zend/Stdlib/InitializableInterface.php  gR  \*޶      8   vendor/zendframework/zend-stdlib/Zend/Stdlib/Request.php  gR  a]      9   vendor/zendframework/zend-stdlib/Zend/Stdlib/Response.php  gR  *N      ;   vendor/zendframework/zend-stdlib/Zend/Stdlib/ArrayUtils.php  gR  %5      9   vendor/zendframework/zend-stdlib/Zend/Stdlib/DateTime.php9  gR9  dx      :   vendor/zendframework/zend-config/Zend/Config/composer.jsono  gRo  P.      D   vendor/zendframework/zend-config/Zend/Config/WriterPluginManager.phph  gRh  ̝^ն      M   vendor/zendframework/zend-config/Zend/Config/Processor/ProcessorInterface.php  gR  ؆      E   vendor/zendframework/zend-config/Zend/Config/Processor/Translator.phpI  gRI  ނ       C   vendor/zendframework/zend-config/Zend/Config/Processor/Constant.php`  gR`  \х      @   vendor/zendframework/zend-config/Zend/Config/Processor/Token.php  gR  >      A   vendor/zendframework/zend-config/Zend/Config/Processor/Filter.php  gR  G4=      @   vendor/zendframework/zend-config/Zend/Config/Processor/Queue.php[  gR[  3Q      7   vendor/zendframework/zend-config/Zend/Config/Config.php$  gR$  *ڶ      8   vendor/zendframework/zend-config/Zend/Config/Factory.phpp  gRp  Z      D   vendor/zendframework/zend-config/Zend/Config/ReaderPluginManager.php  gR  tYp      S   vendor/zendframework/zend-config/Zend/Config/Exception/InvalidArgumentException.php  gR  n      K   vendor/zendframework/zend-config/Zend/Config/Exception/RuntimeException.php  gR  s3      M   vendor/zendframework/zend-config/Zend/Config/Exception/ExceptionInterface.phpx  gRx  $      G   vendor/zendframework/zend-config/Zend/Config/Writer/WriterInterface.php  gR  0y      <   vendor/zendframework/zend-config/Zend/Config/Writer/Yaml.phpa  gRa  M4      ;   vendor/zendframework/zend-config/Zend/Config/Writer/Ini.phpM  gRM  mh      F   vendor/zendframework/zend-config/Zend/Config/Writer/AbstractWriter.php?	  gR?	  6϶      @   vendor/zendframework/zend-config/Zend/Config/Writer/PhpArray.php  gR  Z      <   vendor/zendframework/zend-config/Zend/Config/Writer/Json.php  gR  ڝ~      ;   vendor/zendframework/zend-config/Zend/Config/Writer/Xml.php
  gR
  u<      <   vendor/zendframework/zend-config/Zend/Config/Reader/Yaml.phpn  gRn  M      ;   vendor/zendframework/zend-config/Zend/Config/Reader/Ini.php  gR  &}'      G   vendor/zendframework/zend-config/Zend/Config/Reader/ReaderInterface.php  gR  =      <   vendor/zendframework/zend-config/Zend/Config/Reader/Json.phpI  gRI  G~iq      ;   vendor/zendframework/zend-config/Zend/Config/Reader/Xml.php  gR  Y      J   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/composer.json7  gR7  70G      Y   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/ServiceLocatorAwareTrait.php  gR  {X      `   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/MutableCreationOptionsInterface.php!  gR!  nj`      O   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/ServiceManager.phph  gRh  p      P   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/ConfigInterface.php:  gR:  A嗥      ]   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/ServiceLocatorAwareInterface.php  gR  E9[C      Y   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/Proxy/LazyServiceFactory.php
  gR
  O=v      `   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/Proxy/LazyServiceFactoryFactory.php
  gR
  4{      U   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/InitializerInterface.php  gR  ȓ      Y   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/AbstractFactoryInterface.php  gR  ٺ0      G   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/Config.php<  gR<  C%      X   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/ServiceLocatorInterface.php  gR  |ƶ      ]   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/ServiceManagerAwareInterface.php'  gR'  @`      Z   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/DelegatorFactoryInterface.php'  gR'  /:,      c   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/Exception/InvalidArgumentException.php  gR  9>J      [   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/Exception/RuntimeException.php  gR  bѶ      c   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/Exception/ServiceNotFoundException.php  gR  Pa[E      ]   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/Exception/ExceptionInterface.php  gR  4O      e   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/Exception/CircularReferenceException.php  gR  \-      f   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/Exception/InvalidServiceNameException.php  gR  Drb      e   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/Exception/ServiceNotCreatedException.php  gR         k   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/Exception/CircularDependencyFoundException.php  gR  !      \   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/Di/DiAbstractServiceFactory.php  gR  r_      Z   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/Di/DiInstanceManagerProxy.phpV  gRV  9      T   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/Di/DiServiceFactory.php  gR  ;      X   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/Di/DiServiceInitializer.php  gR  ʤ      Q   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/FactoryInterface.php9  gR9  f      V   vendor/zendframework/zend-servicemanager/Zend/ServiceManager/AbstractPluginManager.php(  gR(  O'      F   vendor/zendframework/zend-eventmanager/Zend/EventManager/composer.json  gR  ~#      S   vendor/zendframework/zend-eventmanager/Zend/EventManager/EventsCapableInterface.php  gR  <+Ƕ      H   vendor/zendframework/zend-eventmanager/Zend/EventManager/FilterChain.php  gR  r2cx      ]   vendor/zendframework/zend-eventmanager/Zend/EventManager/SharedEventManagerAwareInterface.php  gR  M      S   vendor/zendframework/zend-eventmanager/Zend/EventManager/ListenerAggregateTrait.phpg  gRg  QSL      I   vendor/zendframework/zend-eventmanager/Zend/EventManager/EventManager.phpF  gRF  ܢ޶      W   vendor/zendframework/zend-eventmanager/Zend/EventManager/EventManagerAwareInterface.php  gR  }z7N      ]   vendor/zendframework/zend-eventmanager/Zend/EventManager/SharedListenerAggregateInterface.php  gR  i      V   vendor/zendframework/zend-eventmanager/Zend/EventManager/AbstractListenerAggregate.phpM  gRM  E      O   vendor/zendframework/zend-eventmanager/Zend/EventManager/GlobalEventManager.phpJ  gRJ  92      X   vendor/zendframework/zend-eventmanager/Zend/EventManager/SharedEventManagerInterface.phpY  gRY  "s      R   vendor/zendframework/zend-eventmanager/Zend/EventManager/Filter/FilterIterator.php	  gR	  Kʶ      S   vendor/zendframework/zend-eventmanager/Zend/EventManager/Filter/FilterInterface.phpp  gRp  A n      K   vendor/zendframework/zend-eventmanager/Zend/EventManager/ProvidesEvents.php  gR        R   vendor/zendframework/zend-eventmanager/Zend/EventManager/EventManagerInterface.php  gR  ).,      O   vendor/zendframework/zend-eventmanager/Zend/EventManager/SharedEventManager.phph  gRh  ~      B   vendor/zendframework/zend-eventmanager/Zend/EventManager/Event.php  gR  \Ln      O   vendor/zendframework/zend-eventmanager/Zend/EventManager/ResponseCollection.phpk  gRk  0{<      K   vendor/zendframework/zend-eventmanager/Zend/EventManager/EventInterface.php  gR  
      _   vendor/zendframework/zend-eventmanager/Zend/EventManager/Exception/InvalidArgumentException.php  gR  _Qn      _   vendor/zendframework/zend-eventmanager/Zend/EventManager/Exception/InvalidCallbackException.php  gR        V   vendor/zendframework/zend-eventmanager/Zend/EventManager/Exception/DomainException.php  gR  @v      Y   vendor/zendframework/zend-eventmanager/Zend/EventManager/Exception/ExceptionInterface.php  gR  '      S   vendor/zendframework/zend-eventmanager/Zend/EventManager/EventManagerAwareTrait.php  gR  4MA      W   vendor/zendframework/zend-eventmanager/Zend/EventManager/ListenerAggregateInterface.php  gR  2      O   vendor/zendframework/zend-eventmanager/Zend/EventManager/StaticEventManager.phpx  gRx  e      _   vendor/zendframework/zend-eventmanager/Zend/EventManager/SharedEventAggregateAwareInterface.php  gR  Zϐ6      B   vendor/zendframework/zend-serializer/Zend/Serializer/composer.json\  gR\  ^$G      C   vendor/zendframework/zend-serializer/Zend/Serializer/Serializer.php  gR  R7      ^   vendor/zendframework/zend-serializer/Zend/Serializer/Exception/ExtensionNotLoadedException.php  gR  fZ&      [   vendor/zendframework/zend-serializer/Zend/Serializer/Exception/InvalidArgumentException.php  gR  PF      S   vendor/zendframework/zend-serializer/Zend/Serializer/Exception/RuntimeException.php  gR  ̶      U   vendor/zendframework/zend-serializer/Zend/Serializer/Exception/ExceptionInterface.php|  gR|  /      M   vendor/zendframework/zend-serializer/Zend/Serializer/AdapterPluginManager.phpg  gRg  ¶      O   vendor/zendframework/zend-serializer/Zend/Serializer/Adapter/AdapterOptions.php  gR  HY}      L   vendor/zendframework/zend-serializer/Zend/Serializer/Adapter/JsonOptions.phpJ  gRJ  BS      H   vendor/zendframework/zend-serializer/Zend/Serializer/Adapter/PhpCode.php?  gR?  Wz      M   vendor/zendframework/zend-serializer/Zend/Serializer/Adapter/PythonPickle.php  gR  I˧      L   vendor/zendframework/zend-serializer/Zend/Serializer/Adapter/WddxOptions.phpr  gRr  G      M   vendor/zendframework/zend-serializer/Zend/Serializer/Adapter/PhpSerialize.phpa	  gRa	         Q   vendor/zendframework/zend-serializer/Zend/Serializer/Adapter/AdapterInterface.phpt  gRt  7\      E   vendor/zendframework/zend-serializer/Zend/Serializer/Adapter/Wddx.php  gR  c<;      I   vendor/zendframework/zend-serializer/Zend/Serializer/Adapter/IgBinary.php  gR  R,      H   vendor/zendframework/zend-serializer/Zend/Serializer/Adapter/MsgPack.phpl  gRl  z2      T   vendor/zendframework/zend-serializer/Zend/Serializer/Adapter/PythonPickleOptions.php"  gR"  .      P   vendor/zendframework/zend-serializer/Zend/Serializer/Adapter/AbstractAdapter.phpF  gRF  Gf9      E   vendor/zendframework/zend-serializer/Zend/Serializer/Adapter/Json.php
  gR
  F6      6   vendor/zendframework/zend-i18n/Zend/I18n/composer.jsonX  gRX  -_      P   vendor/zendframework/zend-i18n/Zend/I18n/Translator/TranslatorAwareInterface.php  gR  Ğ      E   vendor/zendframework/zend-i18n/Zend/I18n/Translator/Plural/Parser.phpI%  gRI%  f0f      C   vendor/zendframework/zend-i18n/Zend/I18n/Translator/Plural/Rule.phpy  gRy  N_ٲ      E   vendor/zendframework/zend-i18n/Zend/I18n/Translator/Plural/Symbol.phpi  gRi  !@      L   vendor/zendframework/zend-i18n/Zend/I18n/Translator/TranslatorAwareTrait.php1	  gR1	  n      B   vendor/zendframework/zend-i18n/Zend/I18n/Translator/Translator.phpT  gRT  xJ+      T   vendor/zendframework/zend-i18n/Zend/I18n/Translator/Loader/RemoteLoaderInterface.php  gR  TH      F   vendor/zendframework/zend-i18n/Zend/I18n/Translator/Loader/Gettext.php  gR        B   vendor/zendframework/zend-i18n/Zend/I18n/Translator/Loader/Ini.php
  gR
  m      G   vendor/zendframework/zend-i18n/Zend/I18n/Translator/Loader/PhpArray.php  gR        R   vendor/zendframework/zend-i18n/Zend/I18n/Translator/Loader/FileLoaderInterface.php  gR  bض      K   vendor/zendframework/zend-i18n/Zend/I18n/Translator/LoaderPluginManager.php!  gR!  fG      P   vendor/zendframework/zend-i18n/Zend/I18n/Translator/TranslatorServiceFactory.php\  gR\  ~,8      B   vendor/zendframework/zend-i18n/Zend/I18n/Translator/TextDomain.php3  gR3  {      :   vendor/zendframework/zend-i18n/Zend/I18n/Validator/Int.php  gR  1t      <   vendor/zendframework/zend-i18n/Zend/I18n/Validator/Float.php5  gR5        <   vendor/zendframework/zend-i18n/Zend/I18n/Validator/Alnum.php  gR  	ίڶ      ?   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PostCode.php$,  gR$,  K0      B   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber.php  gR  +.      <   vendor/zendframework/zend-i18n/Zend/I18n/Validator/Alpha.php5  gR5  ˾      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/BZ.php  gR  }
      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/GT.phpB  gRB        E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/ST.php  gR  L      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/GB.php  gR  {s      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/PE.php  gR  ^      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/CF.php  gR  T      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/CL.phpe  gRe  Ӆ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/TL.php  gR  K      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/JE.php  gR  nD^      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/PH.php  gR        E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/MT.php  gR  W      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/BF.phpI  gRI  JAc      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/ID.php  gR  Sܶ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/NL.php  gR        E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/BW.phpx  gRx  s(      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/ZW.php  gR  N      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/SM.php  gR  |       E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/SO.php  gR  (ڌ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/LU.phpu  gRu  t      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/OM.php  gR  E      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/PT.phpO  gRO  idö      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/ML.php:  gR:  'd      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/FR.php  gR  Z}      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/FO.php  gR  s^      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/NE.php  gR  #w      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/SX.phpN  gRN  ~&4      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/GM.php<  gR<  ž5      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/KI.phpV  gRV  {      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/GR.php  gR  O      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/CZ.php  gR  `ζ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/FJ.php2  gR2  |      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/IR.php  gR  -ߕڶ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/KM.php  gR  4S׶      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/PY.php  gR  `Q      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/EC.php  gR  c彶      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/MK.php  gR  }      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/SZ.php]  gR]  ]       E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/PA.php  gR  G      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/YE.phpZ  gRZ  -ֵ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/PS.php  gR  h޶      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/MV.phpo  gRo  T\      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/UG.php  gR        E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/DE.php  gR  x<l      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/RO.php  gR  ?      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/ER.php  gR  h{Ӷ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/TO.php  gR        E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/CI.php?  gR?  i      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/BO.php  gR  {      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/NG.php  gR        E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/KE.php  gR  hpgͶ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/DJ.php  gR  J      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/BL.php  gR  m϶      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/MS.php$  gR$  @NT      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/AI.php?  gR?  =(k      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/VG.php  gR  S      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/TD.php  gR  l      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/BB.php;  gR;  pF      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/SY.phpQ  gRQ  $쁶      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/TT.php  gR  ݶ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/CD.php  gR  åG      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/KG.php;  gR;  8Np      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/GP.php4  gR4  
F      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/TR.php
  gR
  ]      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/HR.php  gR  93s׶      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/GH.php  gR  7      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/RW.php  gR  w1E      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/MH.php  gR        E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/NP.php  gR  @      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/BN.php  gR  /      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/SH.php>  gR>  S      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/IE.phpe  gRe  L       E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/ET.php  gR  .Ӷ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/CR.php  gR  шd      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/MX.php
  gR
  S      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/BG.php  gR  G      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/GN.phpu  gRu  o      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/NC.php  gR  wE      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/VN.php  gR  F*M      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/SK.php  gR  ɶ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/SJ.php  gR  ض      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/NZ.php  gR  MoRs      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/CK.php  gR  O      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/MZ.php  gR  9      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/IO.phpj  gRj        E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/HN.php  gR  ~[wR      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/ME.php  gR  ö      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/RU.php  gR  yܐ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/LB.php  gR        E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/MP.php  gR  wh      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/KP.php  gR  >I϶      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/PL.php  gR  # x      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/ES.php  gR        E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/SV.php  gR  j      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/WF.php  gR        E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/AX.php  gR        E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/CX.php  gR  DF      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/KR.php  gR  &3      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/MU.php  gR  $      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/GD.php  gR  eX      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/JO.php)  gR)  &      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/CN.phpC  gRC  Wv      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/CY.php  gR  aȶ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/GU.php  gR  	      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/MQ.php  gR  eҶ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/AT.php$  gR$  u      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/AC.php  gR  \O      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/SI.phpm  gRm  i}Z      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/DM.phpr  gRr  Z Q      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/KY.php  gR  TU      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/TK.phpp  gRp  rɶ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/MG.php?  gR?  ĸo      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/TV.php  gR  ,      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/GW.php  gR  f      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/VU.php  gR  /]}      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/AU.php  gR  శ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/GL.php<  gR<  Oy      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/RE.php  gR  Y       E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/NA.phpA  gRA  ^d`S      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/PK.php  gR  v      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/LS.php  gR  &G`      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/CV.php  gR  Ad^      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/JM.php6  gR6  y c      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/HU.phpI  gRI  )      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/QA.php  gR  |Ӷ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/SB.php  gR  q       E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/BS.php  gR  <
      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/CG.php  gR  ;嫶      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/BD.php
  gR
  ,i      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/SN.php9  gR9  Pr      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/LK.php$  gR$  pJ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/VC.php  gR  jؙR      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/TH.php  gR  '      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/EG.php  gR  쫶      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/GQ.php
  gR
  BŶ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/PM.php  gR  g@      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/GG.php_  gR_  4A      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/VI.php  gR  Q      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/CC.php  gR  2      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/HT.php  gR  O"      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/CO.php  gR  e      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/AD.php  gR  0f      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/TJ.php<  gR<  LSb      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/AG.php  gR  +o      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/LV.phpE  gRE  2      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/CU.php  gR  ѷ1      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/SA.phpy  gRy  7Ͷ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/CA.php  gR  c9      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/AE.phpz  gRz  ɡ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/GI.php  gR  5L      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/SG.php  gR  cֶ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/FK.php  gR  [8      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/PG.php  gR  ̕Ͷ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/BA.phpz  gRz  (IG      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/JP.phpv  gRv  \      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/BE.phpi  gRi   _      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/NU.php  gR  ]9      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/TG.php  gR  Ŷ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/SS.phpy  gRy  g2      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/AL.php  gR        E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/CM.php"  gR"  X7      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/SE.php  gR  {냹      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/MW.php-  gR-  Y d      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/FI.php  gR        E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/LC.php  gR  SC      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/IL.phpB  gRB  H      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/TM.php,  gR,  e;      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/MY.php  gR  (۶      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/SC.php  gR         E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/NF.php  gR  V      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/VE.php  gR  q`      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/VA.php  gR  @x9      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/KN.phpc  gRc  ښ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/MA.php  gR        E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/CW.php  gR  FB      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/UZ.php  gR  tt      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/AM.php  gR  h;      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/BR.phpp  gRp  Hz      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/BJ.php*  gR*  W]      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/LY.php  gR  Ra8      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/AR.php  gR  Drq      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/YT.php  gR  Hᬶ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/ZA.php  gR  z      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/LA.phpT  gRT  B=      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/GY.php  gR  M      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/IN.phpv
  gRv
        E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/AF.php  gR  |      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/KH.php  gR  %      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/BH.php   gR   hO      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/LI.php  gR  %
      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/LR.php  gR  [Y=      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/AO.php  gR        E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/DO.phpO  gRO  Q>C      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/MC.php\  gR\  F      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/EE.php  gR  g      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/AZ.php  gR  l      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/EH.phpO  gRO  n.b      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/NI.php  gR        E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/AW.php  gR  Vv      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/BI.php  gR  7y      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/KZ.phpL  gRL  #e      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/KW.php  gR  g      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/SL.php  gR  %ֶ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/GE.php  gR  T      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/MM.php  gR  Ż      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/PW.php  gR  ӎṶ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/TW.php  gR  -       E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/MN.php  gR  {      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/NR.php%  gR%  P      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/MF.php  gR  #x      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/DZ.php  gR  9[]      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/SR.php  gR  <Q      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/TC.php  gR  h,      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/US.phpK  gRK  +.      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/ZM.php  gR  M%      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/DK.phpG  gRG  T&      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/IQ.php  gR  T      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/MD.php  gR  =      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/CH.php  gR  [h      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/NO.php  gR  ',      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/IT.php  gR  #o      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/UY.php  gR  ~      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/PF.php   gR         E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/BY.php  gR  GIn      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/AS.php-  gR-  n      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/TZ.phpj  gRj  {      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/RS.phpL  gRL  ̶      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/MO.php  gR  җǶ      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/FM.php  gR  #*      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/PR.php  gR  $      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/LT.php  gR  hikx      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/GA.php  gR  !:      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/BT.phpD  gRD  Ob      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/GF.php  gR  U8      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/IS.phpY  gRY        E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/SD.php  gR  6      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/BQ.php  gR  ,      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/TN.php  gR  ;,      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/BM.php`  gR`  qq      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/HK.php  gR  Rz      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/IM.php  gR  c      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/UA.php  gR  <`n      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/MR.phpH  gRH  ,      E   vendor/zendframework/zend-i18n/Zend/I18n/Validator/PhoneNumber/WS.php  gR  ۂ~~      ?   vendor/zendframework/zend-i18n/Zend/I18n/Validator/DateTime.phpE  gRE  ~¶      >   vendor/zendframework/zend-i18n/Zend/I18n/View/HelperConfig.php  gR  !.      E   vendor/zendframework/zend-i18n/Zend/I18n/View/Helper/NumberFormat.php  gR        G   vendor/zendframework/zend-i18n/Zend/I18n/View/Helper/CurrencyFormat.php9  gR9  ?s      H   vendor/zendframework/zend-i18n/Zend/I18n/View/Helper/TranslatePlural.php  gR  ߶      C   vendor/zendframework/zend-i18n/Zend/I18n/View/Helper/DateFormat.php  gR  -dP      ?   vendor/zendframework/zend-i18n/Zend/I18n/View/Helper/Plural.php|  gR|  φ      Q   vendor/zendframework/zend-i18n/Zend/I18n/View/Helper/AbstractTranslatorHelper.php  gR  Q      B   vendor/zendframework/zend-i18n/Zend/I18n/View/Helper/Translate.php_  gR_  XD      B   vendor/zendframework/zend-i18n/Zend/I18n/Filter/AbstractLocale.phpT  gRT  Q;rH      @   vendor/zendframework/zend-i18n/Zend/I18n/Filter/NumberFormat.php  gR  WC      9   vendor/zendframework/zend-i18n/Zend/I18n/Filter/Alnum.php@
  gR@
  JC      9   vendor/zendframework/zend-i18n/Zend/I18n/Filter/Alpha.php.  gR.  +ɩi      R   vendor/zendframework/zend-i18n/Zend/I18n/Exception/ExtensionNotLoadedException.php  gR  T{ֶ      K   vendor/zendframework/zend-i18n/Zend/I18n/Exception/OutOfBoundsException.php  gR  '      O   vendor/zendframework/zend-i18n/Zend/I18n/Exception/InvalidArgumentException.php  gR  a!<H      G   vendor/zendframework/zend-i18n/Zend/I18n/Exception/RuntimeException.php  gR  O&e      I   vendor/zendframework/zend-i18n/Zend/I18n/Exception/ExceptionInterface.phpv  gRv        E   vendor/zendframework/zend-i18n/Zend/I18n/Exception/ParseException.php  gR  k      E   vendor/zendframework/zend-i18n/Zend/I18n/Exception/RangeException.php  gR  @      ?   vendor/zendframework/zend-filter/Zend/Filter/File/LowerCase.php(  gR(  L	      <   vendor/zendframework/zend-filter/Zend/Filter/File/Rename.phpu%  gRu%  1      B   vendor/zendframework/zend-filter/Zend/Filter/File/RenameUpload.phpz!  gRz!  іD      ?   vendor/zendframework/zend-filter/Zend/Filter/File/UpperCase.php9  gR9        =   vendor/zendframework/zend-filter/Zend/Filter/File/Encrypt.php
  gR
  &$Q      =   vendor/zendframework/zend-filter/Zend/Filter/File/Decrypt.php
  gR
  ң	      :   vendor/zendframework/zend-filter/Zend/Filter/composer.json  gR  Q      ;   vendor/zendframework/zend-filter/Zend/Filter/Decompress.php-  gR-        :   vendor/zendframework/zend-filter/Zend/Filter/StripTags.php'  gR'  _l      <   vendor/zendframework/zend-filter/Zend/Filter/PregReplace.php  gR  5g%#      4   vendor/zendframework/zend-filter/Zend/Filter/Int.php  gR  ?       <   vendor/zendframework/zend-filter/Zend/Filter/FilterChain.phpY  gRY  M¶      =   vendor/zendframework/zend-filter/Zend/Filter/Compress/Rar.php  gR  $       =   vendor/zendframework/zend-filter/Zend/Filter/Compress/Lzf.php8  gR8  Hz<      @   vendor/zendframework/zend-filter/Zend/Filter/Compress/Snappy.php  gR  '      V   vendor/zendframework/zend-filter/Zend/Filter/Compress/AbstractCompressionAlgorithm.php  gR  z3a      =   vendor/zendframework/zend-filter/Zend/Filter/Compress/Tar.php  gR  y      W   vendor/zendframework/zend-filter/Zend/Filter/Compress/CompressionAlgorithmInterface.php  gR  ݌      =   vendor/zendframework/zend-filter/Zend/Filter/Compress/Zip.php$  gR$  O       =   vendor/zendframework/zend-filter/Zend/Filter/Compress/Bz2.php  gR  X찶      <   vendor/zendframework/zend-filter/Zend/Filter/Compress/Gz.php>  gR>  L<      >   vendor/zendframework/zend-filter/Zend/Filter/StripNewlines.php  gR  KƷ      :   vendor/zendframework/zend-filter/Zend/Filter/Inflector.phpj1  gRj1  -w      ?   vendor/zendframework/zend-filter/Zend/Filter/AbstractFilter.php
  gR
  @      @   vendor/zendframework/zend-filter/Zend/Filter/AbstractUnicode.php   gR   sR      K   vendor/zendframework/zend-filter/Zend/Filter/Word/UnderscoreToCamelCase.php
  gR
  Ƕ      F   vendor/zendframework/zend-filter/Zend/Filter/Word/DashToUnderscore.php  gR  Wg      E   vendor/zendframework/zend-filter/Zend/Filter/Word/CamelCaseToDash.php  gR  j/      J   vendor/zendframework/zend-filter/Zend/Filter/Word/CamelCaseToSeparator.phpU  gRU  gZ      K   vendor/zendframework/zend-filter/Zend/Filter/Word/CamelCaseToUnderscore.php
  gR
  +d      J   vendor/zendframework/zend-filter/Zend/Filter/Word/SeparatorToCamelCase.php  gR  x      F   vendor/zendframework/zend-filter/Zend/Filter/Word/UnderscoreToDash.php
  gR
  ob      K   vendor/zendframework/zend-filter/Zend/Filter/Word/UnderscoreToSeparator.phpy  gRy  ,      E   vendor/zendframework/zend-filter/Zend/Filter/Word/DashToCamelCase.php  gR  !\      G   vendor/zendframework/zend-filter/Zend/Filter/Word/AbstractSeparator.php  gR  Ӓ      J   vendor/zendframework/zend-filter/Zend/Filter/Word/SeparatorToSeparator.php	  gR	  zJݶ      E   vendor/zendframework/zend-filter/Zend/Filter/Word/SeparatorToDash.phpq  gRq  ̶      E   vendor/zendframework/zend-filter/Zend/Filter/Word/DashToSeparator.phpc  gRc  edX      4   vendor/zendframework/zend-filter/Zend/Filter/Dir.phpi  gRi  UL      =   vendor/zendframework/zend-filter/Zend/Filter/StaticFilter.php  gR  ja      @   vendor/zendframework/zend-filter/Zend/Filter/Encrypt/Openssl.php0  gR0  n       U   vendor/zendframework/zend-filter/Zend/Filter/Encrypt/EncryptionAlgorithmInterface.php  gR  rC      D   vendor/zendframework/zend-filter/Zend/Filter/Encrypt/BlockCipher.phpl  gRl  y      9   vendor/zendframework/zend-filter/Zend/Filter/Compress.php  gR  	W      9   vendor/zendframework/zend-filter/Zend/Filter/Callback.php	  gR	  <L      D   vendor/zendframework/zend-filter/Zend/Filter/FilterPluginManager.php  gR  ?˶      9   vendor/zendframework/zend-filter/Zend/Filter/BaseName.php  gR  A      7   vendor/zendframework/zend-filter/Zend/Filter/Digits.php  gR  7      >   vendor/zendframework/zend-filter/Zend/Filter/StringToLower.php  gR  D      5   vendor/zendframework/zend-filter/Zend/Filter/Null.php_  gR_  W.      9   vendor/zendframework/zend-filter/Zend/Filter/RealPath.phpv  gRv        ;   vendor/zendframework/zend-filter/Zend/Filter/StringTrim.php.
  gR.
  x      =   vendor/zendframework/zend-filter/Zend/Filter/UriNormalize.phpZ  gRZ  3=      =   vendor/zendframework/zend-filter/Zend/Filter/HtmlEntities.php  gR  [cж      8   vendor/zendframework/zend-filter/Zend/Filter/Encrypt.phpU  gRU  5l      V   vendor/zendframework/zend-filter/Zend/Filter/Exception/ExtensionNotLoadedException.php  gR  V(e      S   vendor/zendframework/zend-filter/Zend/Filter/Exception/InvalidArgumentException.php  gR  ت      K   vendor/zendframework/zend-filter/Zend/Filter/Exception/RuntimeException.php  gR  i2      J   vendor/zendframework/zend-filter/Zend/Filter/Exception/DomainException.php  gR  C      M   vendor/zendframework/zend-filter/Zend/Filter/Exception/ExceptionInterface.phpy  gRy  <}      Q   vendor/zendframework/zend-filter/Zend/Filter/Exception/BadMethodCallException.php  gR  7/e      8   vendor/zendframework/zend-filter/Zend/Filter/Decrypt.php  gR  ;-      B   vendor/zendframework/zend-filter/Zend/Filter/DateTimeFormatter.phpG  gRG  g       8   vendor/zendframework/zend-filter/Zend/Filter/Boolean.phpq   gRq   ^      >   vendor/zendframework/zend-filter/Zend/Filter/StringToUpper.php  gR  9M      @   vendor/zendframework/zend-filter/Zend/Filter/FilterInterface.phpR  gRR  wje      6   vendor/zendframework/zend-math/Zend/Math/composer.json\  gR\  !f      >   vendor/zendframework/zend-math/Zend/Math/Source/HashTiming.phpv  gRv  >      B   vendor/zendframework/zend-math/Zend/Math/BigInteger/BigInteger.phpN  gRN  Nl6      Z   vendor/zendframework/zend-math/Zend/Math/BigInteger/Exception/InvalidArgumentException.php  gR  '-&      R   vendor/zendframework/zend-math/Zend/Math/BigInteger/Exception/RuntimeException.php  gR        T   vendor/zendframework/zend-math/Zend/Math/BigInteger/Exception/ExceptionInterface.php  gR        Y   vendor/zendframework/zend-math/Zend/Math/BigInteger/Exception/DivisionByZeroException.php  gR  T_      L   vendor/zendframework/zend-math/Zend/Math/BigInteger/AdapterPluginManager.php(  gR(  Ĳm      F   vendor/zendframework/zend-math/Zend/Math/BigInteger/Adapter/Bcmath.php"  gR"  Dն      P   vendor/zendframework/zend-math/Zend/Math/BigInteger/Adapter/AdapterInterface.php  gR  N      C   vendor/zendframework/zend-math/Zend/Math/BigInteger/Adapter/Gmp.php   gR   Kr      1   vendor/zendframework/zend-math/Zend/Math/Rand.php  gR   v      O   vendor/zendframework/zend-math/Zend/Math/Exception/InvalidArgumentException.php  gR  km      G   vendor/zendframework/zend-math/Zend/Math/Exception/RuntimeException.php  gR  	[      F   vendor/zendframework/zend-math/Zend/Math/Exception/DomainException.php  gR  9      I   vendor/zendframework/zend-math/Zend/Math/Exception/ExceptionInterface.phpv  gRv  ,hsb      8   vendor/zendframework/zend-cache/Zend/Cache/composer.json  gR  pX      L   vendor/zendframework/zend-cache/Zend/Cache/Storage/ClearExpiredInterface.php  gR  %      E   vendor/zendframework/zend-cache/Zend/Cache/Storage/ExceptionEvent.php  gR  "      P   vendor/zendframework/zend-cache/Zend/Cache/Storage/ClearByNamespaceInterface.php!  gR!  H?      H   vendor/zendframework/zend-cache/Zend/Cache/Storage/IterableInterface.php  gR  3      U   vendor/zendframework/zend-cache/Zend/Cache/Storage/AvailableSpaceCapableInterface.php  gR   
      H   vendor/zendframework/zend-cache/Zend/Cache/Storage/TaggableInterface.php<  gR<  Vc      D   vendor/zendframework/zend-cache/Zend/Cache/Storage/PluginManager.php  gR  $      I   vendor/zendframework/zend-cache/Zend/Cache/Storage/FlushableInterface.php  gR  }h      K   vendor/zendframework/zend-cache/Zend/Cache/Storage/OptimizableInterface.php  gR  ö      @   vendor/zendframework/zend-cache/Zend/Cache/Storage/PostEvent.php$  gR$  Rxڕ      M   vendor/zendframework/zend-cache/Zend/Cache/Storage/ClearByPrefixInterface.php  gR  Pƶ      H   vendor/zendframework/zend-cache/Zend/Cache/Storage/IteratorInterface.php  gR  Ski      <   vendor/zendframework/zend-cache/Zend/Cache/Storage/Event.php  gR  O(8      G   vendor/zendframework/zend-cache/Zend/Cache/Storage/StorageInterface.php  gR  m      Q   vendor/zendframework/zend-cache/Zend/Cache/Storage/TotalSpaceCapableInterface.php  gR  T      K   vendor/zendframework/zend-cache/Zend/Cache/Storage/AdapterPluginManager.php  gR  U      L   vendor/zendframework/zend-cache/Zend/Cache/Storage/Plugin/AbstractPlugin.php'  gR'  z	b      N   vendor/zendframework/zend-cache/Zend/Cache/Storage/Plugin/OptimizeByFactor.phpm  gRm  ڴI      N   vendor/zendframework/zend-cache/Zend/Cache/Storage/Plugin/ExceptionHandler.php;  gR;        M   vendor/zendframework/zend-cache/Zend/Cache/Storage/Plugin/IgnoreUserAbort.php  gR  [׶      R   vendor/zendframework/zend-cache/Zend/Cache/Storage/Plugin/ClearExpiredByFactor.php(  gR(  }      H   vendor/zendframework/zend-cache/Zend/Cache/Storage/Plugin/Serializer.php,   gR,   ǻQ!      M   vendor/zendframework/zend-cache/Zend/Cache/Storage/Plugin/PluginInterface.php  gR  `0      K   vendor/zendframework/zend-cache/Zend/Cache/Storage/Plugin/PluginOptions.php@  gR@        C   vendor/zendframework/zend-cache/Zend/Cache/Storage/Capabilities.php5  gR5  d?      M   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/AdapterOptions.php  gR  ,       B   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/Apc.php&Y  gR&Y  fܶ      N   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/KeyListIterator.php  gR  	c      I   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/Filesystem.php~  gR~  m#      Q   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/AbstractZendServer.php   gR    &      S   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/RedisResourceManager.phpWC  gRWC  V޻      D   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/Redis.php4  gR4        Q   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/FilesystemIterator.php  gR  Pم޶      W   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/MemcachedResourceManager.php->  gR->  }A~      B   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/Dba.php;  gR;  }ض      M   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/SessionOptions.php  gR        L   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/ZendServerShm.php  gR  1>      E   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/XCache.php;  gR;  $      H   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/Memcached.phpR  gRR  @g      J   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/DbaIterator.phpE  gRE  @㠀      P   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/FilesystemOptions.php,  gR,  +j1      M   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/ZendServerDisk.php  gR  ψ      N   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/AbstractAdapter.php  gR  %8      N   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/WinCacheOptions.php  gR  H|ֶ      L   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/XCacheOptions.php  gR  v      K   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/RedisOptions.php  gR  t      O   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/MemcachedOptions.php!  gR!  o      J   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/ApcIterator.phpb  gRb  gI      F   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/Session.php9  gR9  !`R      I   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/ApcOptions.php  gR  <      L   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/MemoryOptions.php  gR  n      E   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/Memory.phpN  gRN  vT      I   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/DbaOptions.php  gR  8K2      G   vendor/zendframework/zend-cache/Zend/Cache/Storage/Adapter/WinCache.phpW@  gRW@  gq      =   vendor/zendframework/zend-cache/Zend/Cache/StorageFactory.php  gR  Pj      C   vendor/zendframework/zend-cache/Zend/Cache/Pattern/CaptureCache.phpd-  gRd-  eon      F   vendor/zendframework/zend-cache/Zend/Cache/Pattern/AbstractPattern.php  gR  L      B   vendor/zendframework/zend-cache/Zend/Cache/Pattern/OutputCache.php	  gR	  <q      G   vendor/zendframework/zend-cache/Zend/Cache/Pattern/PatternInterface.php  gR  Moƶ      D   vendor/zendframework/zend-cache/Zend/Cache/Pattern/CallbackCache.php-  gR-  |      B   vendor/zendframework/zend-cache/Zend/Cache/Pattern/ObjectCache.php#  gR#  b      A   vendor/zendframework/zend-cache/Zend/Cache/Pattern/ClassCache.php  gR  5      E   vendor/zendframework/zend-cache/Zend/Cache/Pattern/PatternOptions.phpC  gRC  Ud[      C   vendor/zendframework/zend-cache/Zend/Cache/PatternPluginManager.phpt  gRt  &      T   vendor/zendframework/zend-cache/Zend/Cache/Exception/ExtensionNotLoadedException.php  gR  `WL      Q   vendor/zendframework/zend-cache/Zend/Cache/Exception/InvalidArgumentException.php  gR        I   vendor/zendframework/zend-cache/Zend/Cache/Exception/RuntimeException.php  gR  .#      L   vendor/zendframework/zend-cache/Zend/Cache/Exception/OutOfSpaceException.php  gR        W   vendor/zendframework/zend-cache/Zend/Cache/Exception/UnsupportedMethodCallException.php  gR   G#      G   vendor/zendframework/zend-cache/Zend/Cache/Exception/LogicException.php  gR  fg      L   vendor/zendframework/zend-cache/Zend/Cache/Exception/MissingKeyException.php  gR        K   vendor/zendframework/zend-cache/Zend/Cache/Exception/ExceptionInterface.phpx  gRx   n      S   vendor/zendframework/zend-cache/Zend/Cache/Exception/MissingDependencyException.php  gR  Νֶ      O   vendor/zendframework/zend-cache/Zend/Cache/Exception/BadMethodCallException.php  gR  m1      Q   vendor/zendframework/zend-cache/Zend/Cache/Exception/UnexpectedValueException.php  gR  e~<ٶ      Y   vendor/zendframework/zend-cache/Zend/Cache/Service/StorageCacheAbstractServiceFactory.php	  gR	  =+      J   vendor/zendframework/zend-cache/Zend/Cache/Service/StorageCacheFactory.phpq  gRq  pϨ      =   vendor/zendframework/zend-cache/Zend/Cache/PatternFactory.php	  gR	  PG         vendor/autoload.php   gR   K>      (   vendor/phpoption/phpoption/composer.json  gR  ԗ%b      3   vendor/phpoption/phpoption/src/PhpOption/Option.php  gR  X      1   vendor/phpoption/phpoption/src/PhpOption/None.phpc  gRc  =      7   vendor/phpoption/phpoption/src/PhpOption/LazyOption.php  gR   E      1   vendor/phpoption/phpoption/src/PhpOption/Some.php
  gR
  Up      "   vendor/phpoption/phpoption/LICENSE\,  gR\,  bE      =   vendor/phpoption/phpoption/tests/PhpOption/Tests/SomeTest.php  gR  o۶      ?   vendor/phpoption/phpoption/tests/PhpOption/Tests/OptionTest.phpL	  gRL	  3      =   vendor/phpoption/phpoption/tests/PhpOption/Tests/NoneTest.phpQ
  gRQ
  S      D   vendor/phpoption/phpoption/tests/PhpOption/Tests/PerformanceTest.php|  gR|  Qd      C   vendor/phpoption/phpoption/tests/PhpOption/Tests/LazyOptionTest.php-  gR-  gĶ      .   vendor/phpoption/phpoption/tests/bootstrap.php   gR   ?      +   vendor/phpoption/phpoption/phpunit.xml.dist  gR  3ն      )   vendor/doctrine/annotations/composer.json  gR  M䲳      =   vendor/doctrine/annotations/tests/Doctrine/Tests/TestInit.php  gR        Z   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/TopLevelAnnotation.phpw   gRw   wI      [   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Ticket/DCOM58Entity.phpa   gRa         Y   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Ticket/DCOM55Test.phpB  gRB  Pۦ      Y   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Ticket/DCOM58Test.php"  gR"  WR      W   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/PerformanceTest.php=  gR=  k$:      {   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithInvalidAnnotationTargetAtProperty.php  gR  +	@      g   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationTargetMethod.php   gR         k   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationTargetAnnotation.php   gR   AĶ      i   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationWithAttributes.php	  gR	  iD         vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationWithRequiredAttributesWithoutContructor.phpx  gRx  K6      y   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithInvalidAnnotationTargetAtMethod.php[  gR[  ?4      h   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationWithConstants.php  gR  nH˶      m   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationEnumLiteralInvalid.php-  gR-        c   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/NonNamespacedClass.php   gR   $      a   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithRequire.php,  gR,  %      h   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithAnnotationEnum.php  gR  vt߶      b   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/Secure.phpS  gRS  ׯt      a   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/Route.php   gR   ({϶      q   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/AnnotWithDefaultValue.php   gR   nGW      d   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/Template.php  gR  Aض      c   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/Version.php   gR   Э      d   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/Annotation/Autoload.phpr   gRr   ,<      o   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithValidAnnotationTarget.phpZ  gRZ  0      l   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/InvalidAnnotationUsageClass.php|   gR|   R7      x   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithInvalidAnnotationTargetAtClass.phpG  gRG  et      f   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/MultipleClassesInFile.php   gR   =      {   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/DifferentNamespacesPerFileWithClassAsFirst.php  gR         ]   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/NoAnnotation.phpS   gRS   U      [   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/Controller.php)  gR)  r      d   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationTargetAll.php   gR   E|H      p   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationWithTargetSyntaxError.php   gR   F      v   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/InvalidAnnotationUsageButIgnoredClass.php   gR   PP      a   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithClosure.php  gR   V      n   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/NamespaceAndClassCommentedOut.phpR  gRR  Ef      y   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithAnnotationWithTargetSyntaxError.php  gR  ֗      p   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/NamespaceWithClosureDeclaration.phpU  gRU  \&      T   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/Api.phpp   gRp   s      f   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/IntefaceWithConstants.php   gR         m   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/NamespacedSingleClassLOC1000.phpg  gRg  )0      f   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationTargetClass.php   gR   K/      c   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithConstants.php   gR         ]   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassDDC1660.php  gR  9*#      w   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/EqualNamespacesPerFileWithClassAsFirst.phpn  gRn  g      q   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationWithRequiredAttributes.php  gR  &      f   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationEnumLiteral.php  gR  =m      ^   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/TestInterface.php   gR   j      c   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/SingleClassLOC1000.phpf  gRf  E[K      n   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/MultipleImportsInUseStatement.php   gR   W)      z   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/DifferentNamespacesPerFileWithClassAsLast.php  gR  !\      f   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationEnumInvalid.php   gR   j޶      o   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationTargetPropertyMethod.php   gR          w   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/GlobalNamespacesPerFileWithClassAsLast.php  gR  r=J      _   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationEnum.php3  gR3  hj      f   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/AnnotationWithVarType.phpO  gRO  1      u   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithFullyQualifiedUseStatements.php;  gR;  椶      v   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/EqualNamespacesPerFileWithClassAsLast.phpl  gRl  O      o   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/ClassWithAnnotationWithVarType.php  gR  Ӎa0      x   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/Fixtures/GlobalNamespacesPerFileWithClassAsFirst.php   gR   d˶      U   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/DocParserTest.php5  gR5  :      \   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/AnnotationReaderTest.php   gR   '      [   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/FileCacheReaderTest.php  gR        U   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/PhpParserTest.php  gR  BV
<      Z   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/AbstractReaderTest.phpY  gRY        R   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/DummyClass.phpp  gRp  y      b   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/SimpleAnnotationReaderTest.php[  gR[  8H      T   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/DocLexerTest.php  gR  o<_      X   vendor/doctrine/annotations/tests/Doctrine/Tests/Common/Annotations/CachedReaderTest.php  gR  iж      E   vendor/doctrine/annotations/tests/Doctrine/Tests/DoctrineTestCase.php   gR   xOy      ,   vendor/doctrine/annotations/phpunit.xml.dist7  gR7  _P(      O   vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/FileCacheReader.php!  gR!  w      F   vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Reader.phpp  gRp  b      I   vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php<  gR<  M      T   vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.php  gR        S   vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Required.php  gR  M      O   vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.php$
  gR$
  A}`ݶ      [   vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.phpI  gRI  @·      U   vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attributes.phpj  gRj  6      Q   vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Target.php  gR  _vbU      V   vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/SimpleAnnotationReader.phpW  gRW        J   vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation.php	  gR	  oc      S   vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php)  gR)  9L      I   vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/PhpParser.phpq  gRq        M   vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.phpf  gRf  T@l      P   vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php#+  gR#+  L      K   vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/TokenParser.php  gR  >      R   vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php  gR  cy[      L   vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/CachedReader.php  gR  2      H   vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocLexer.php  gR  )B      #   vendor/doctrine/lexer/composer.json  gR  ɅĶ      A   vendor/doctrine/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.phpK  gRK  Ok      '   vendor/mikey179/vfsStream/composer.json   gR   \Q,      R   vendor/mikey179/vfsStream/src/main/php/org/bovigo/vfs/vfsStreamAbstractContent.php]"  gR]"  VmU      T   vendor/mikey179/vfsStream/src/main/php/org/bovigo/vfs/vfsStreamContainerIterator.php  gR  R      Z   vendor/mikey179/vfsStream/src/main/php/org/bovigo/vfs/visitor/vfsStreamAbstractVisitor.php  gR  ?XC      W   vendor/mikey179/vfsStream/src/main/php/org/bovigo/vfs/visitor/vfsStreamPrintVisitor.php  gR  08      [   vendor/mikey179/vfsStream/src/main/php/org/bovigo/vfs/visitor/vfsStreamStructureVisitor.php`  gR`  X.c      R   vendor/mikey179/vfsStream/src/main/php/org/bovigo/vfs/visitor/vfsStreamVisitor.php[  gR[  ?"qu      J   vendor/mikey179/vfsStream/src/main/php/org/bovigo/vfs/vfsStreamContent.phpj  gRj  N'      L   vendor/mikey179/vfsStream/src/main/php/org/bovigo/vfs/vfsStreamContainer.phpG  gRG  "=*      ?   vendor/mikey179/vfsStream/src/main/php/org/bovigo/vfs/Quota.php  gR  dF      L   vendor/mikey179/vfsStream/src/main/php/org/bovigo/vfs/vfsStreamException.phpo  gRo  `      J   vendor/mikey179/vfsStream/src/main/php/org/bovigo/vfs/vfsStreamWrapper.phpm  gRm        C   vendor/mikey179/vfsStream/src/main/php/org/bovigo/vfs/vfsStream.phpU2  gRU2  k>      L   vendor/mikey179/vfsStream/src/main/php/org/bovigo/vfs/vfsStreamDirectory.phpk  gRk  Я      G   vendor/mikey179/vfsStream/src/main/php/org/bovigo/vfs/vfsStreamFile.php~'  gR~'  %      ]   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/vfsStreamResolveIncludePathTestCase.php  gR  Rk      V   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/vfsStreamWrapperBaseTestCase.php	  gR	  ]      T   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/vfsStreamDirectoryTestCase.php+  gR+  ;+o      W   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/vfsStreamWrapperQuotaTestCase.php  gR  *}      ^   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/vfsStreamWrapperDirSeparatorTestCase.php7  gR7         b   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/visitor/vfsStreamAbstractVisitorTestCase.phpZ	  gRZ	  ܡ      _   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/visitor/vfsStreamPrintVisitorTestCase.php  gR  O      c   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/visitor/vfsStreamStructureVisitorTestCase.phpQ
  gRQ
  i4      O   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/vfsStreamFileTestCase.php$  gR$        W   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/vfsStreamWrapperFlockTestCase.php8  gR8  oR      ^   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/proxy/vfsStreamWrapperRecordingProxy.php  gR  ݰ      H   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/UnlinkTestCase.php?  gR?  1׶      R   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/vfsStreamWrapperTestCase.phpi  gRi  >4/      Z   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/vfsStreamAbstractContentTestCase.php  gR  ]i      U   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/vfsStreamWrapperDirTestCase.phpK  gRK  I>      P   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/vfsStreamUmaskTestCase.php  gR  FtP      Q   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/vfsStreamExLockTestCase.php  gR  L<      [   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/vfsStreamDirectoryIssue18TestCase.php  gR  wvZ      \   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/vfsStreamContainerIteratorTestCase.php~  gR~  o      ^   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/vfsStreamWrapperStreamSelectTestCase.phpv  gRv        G   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/QuotaTestCase.php  gR  V˶      [   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/vfsStreamWrapperSetOptionTestCase.php  gR        N   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/vfsStreamZipTestCase.php*  gR*  A`      V   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/vfsStreamWrapperFileTestCase.php4  gR4  ]#	      M   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/PermissionsTestCase.php

  gR

  dzҶ      [   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/vfsStreamWrapperFileTimesTestCase.php,  gR,  VO      K   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/vfsStreamTestCase.phpW[  gRW[  @      ]   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/vfsStreamWrapperWithoutRootTestCase.php  gR  M      O   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/vfsStreamGlobTestCase.php  gR  4Vȶ      c   vendor/mikey179/vfsStream/src/test/php/org/bovigo/vfs/vfsStreamWrapperAlreadyRegisteredTestCase.php  gR  (j      T   vendor/mikey179/vfsStream/src/test/resources/filesystemcopy/withSubfolders/aFile.txt   gR   !es      _   vendor/mikey179/vfsStream/src/test/resources/filesystemcopy/withSubfolders/subfolder1/file1.txt   gR         !   vendor/mikey179/vfsStream/LICENSE  gR  G      *   vendor/mikey179/vfsStream/phpunit.xml.dist  gR  u      !   vendor/mikey179/vfsStream/CHANGES  gR        )   vendor/mikey179/vfsStream/phpdoc.dist.xmlN  gRN  d2۶      6   vendor/mikey179/vfsStream/examples/FilemodeExample.php  gR  .a      D   vendor/mikey179/vfsStream/examples/FileModeExampleTestCaseOldWay.phpN  gRN  =      =   vendor/mikey179/vfsStream/examples/FilePermissionsExample.php  gR  i"54      K   vendor/mikey179/vfsStream/examples/FilemodeExampleTestCaseWithVfsStream.php@  gR@  
      =   vendor/mikey179/vfsStream/examples/FailureExampleTestCase.phpW  gRW  	S      5   vendor/mikey179/vfsStream/examples/FailureExample.php  gR  5      .   vendor/mikey179/vfsStream/examples/Example.php  gR  mD=      C   vendor/mikey179/vfsStream/examples/ExampleTestCaseWithVfsStream.php  gR  B}      E   vendor/mikey179/vfsStream/examples/FilePermissionsExampleTestCase.phpE  gRE  ˑ      <   vendor/mikey179/vfsStream/examples/ExampleTestCaseOldWay.php  gR  Q1      0   vendor/mikey179/vfsStream/examples/bootstrap.php?   gR?            vendor/twig/twig/composer.json  gR  (         vendor/twig/twig/LICENSE  gR  ۫c[          vendor/twig/twig/README.markdown  gR  1ζ         vendor/twig/twig/AUTHORS  gR  5ɶ      !   vendor/twig/twig/phpunit.xml.dist  gR        #   vendor/twig/twig/ext/twig/config.m4   gR         $   vendor/twig/twig/ext/twig/config.w32   gR   (      !   vendor/twig/twig/ext/twig/LICENSE  gR  ۫c[          vendor/twig/twig/ext/twig/twig.c>q  gR>q  EI      $   vendor/twig/twig/ext/twig/php_twig.hY  gRY  ߻b      1   vendor/twig/twig/lib/Twig/Extension/Optimizer.php  gR  D      -   vendor/twig/twig/lib/Twig/Extension/Debug.php  gR  rI      ,   vendor/twig/twig/lib/Twig/Extension/Core.php̽  gR̽  iN      /   vendor/twig/twig/lib/Twig/Extension/Staging.php0  gR0  NR      /   vendor/twig/twig/lib/Twig/Extension/Escaper.php
  gR
  жԥ      /   vendor/twig/twig/lib/Twig/Extension/Sandbox.php6
  gR6
  3      4   vendor/twig/twig/lib/Twig/Extension/StringLoader.php  gR  ٷ      -   vendor/twig/twig/lib/Twig/LoaderInterface.php6  gR6  s\P      )   vendor/twig/twig/lib/Twig/Environment.phps  gRs  	      ,   vendor/twig/twig/lib/Twig/SimpleFunction.phpP  gRP  SFv      $   vendor/twig/twig/lib/Twig/Parser.php-  gR-  N      (   vendor/twig/twig/lib/Twig/SimpleTest.php  gR  XӶ      #   vendor/twig/twig/lib/Twig/Error.phpH  gRH  Gn       (   vendor/twig/twig/lib/Twig/Autoloader.php  gR  k      "   vendor/twig/twig/lib/Twig/Node.php  gR  T7^      0   vendor/twig/twig/lib/Twig/ExtensionInterface.php  gR  I۶      .   vendor/twig/twig/lib/Twig/ExpressionParser.php9^  gR9^  A      2   vendor/twig/twig/lib/Twig/NodeVisitorInterface.php0  gR0  CĶ      /   vendor/twig/twig/lib/Twig/FunctionInterface.php$  gR$  x      /   vendor/twig/twig/lib/Twig/CompilerInterface.php  gR  Ey      3   vendor/twig/twig/lib/Twig/NodeVisitor/Optimizer.php  gR  ;ض      6   vendor/twig/twig/lib/Twig/NodeVisitor/SafeAnalysis.php  gR  @      1   vendor/twig/twig/lib/Twig/NodeVisitor/Escaper.php  gR  S$Ҷ      1   vendor/twig/twig/lib/Twig/NodeVisitor/Sandbox.php(
  gR(
  |      )   vendor/twig/twig/lib/Twig/Filter/Node.php  gR         -   vendor/twig/twig/lib/Twig/Filter/Function.php  gR  ̶      +   vendor/twig/twig/lib/Twig/Filter/Method.php  gR  &      #   vendor/twig/twig/lib/Twig/Token.phpR  gRR  )K      /   vendor/twig/twig/lib/Twig/TokenParserBroker.php'  gR'  H      4   vendor/twig/twig/lib/Twig/Sandbox/SecurityPolicy.php|  gR|  f      =   vendor/twig/twig/lib/Twig/Sandbox/SecurityPolicyInterface.php0  gR0  {/      3   vendor/twig/twig/lib/Twig/Sandbox/SecurityError.php  gR  =      '   vendor/twig/twig/lib/Twig/Test/Node.php  gR  f0      6   vendor/twig/twig/lib/Twig/Test/IntegrationTestCase.php  gR  c      +   vendor/twig/twig/lib/Twig/Test/Function.php  gR  q      )   vendor/twig/twig/lib/Twig/Test/Method.phpw  gRw  ޛ      /   vendor/twig/twig/lib/Twig/Test/NodeTestCase.php9  gR9  	      +   vendor/twig/twig/lib/Twig/NodeInterface.php  gR  c;'      '   vendor/twig/twig/lib/Twig/Extension.php>  gR>  1      &   vendor/twig/twig/lib/Twig/Function.php\  gR\  C/w      1   vendor/twig/twig/lib/Twig/NodeOutputInterface.php_  gR_  '      2   vendor/twig/twig/lib/Twig/TokenParserInterface.php  gR  bC      $   vendor/twig/twig/lib/Twig/Filter.phpM  gRM  G.8Զ      )   vendor/twig/twig/lib/Twig/TokenStream.php  gR  bO      &   vendor/twig/twig/lib/Twig/Template.php;  gR;  ӧ      +   vendor/twig/twig/lib/Twig/Loader/String.php6  gR6  6:I      *   vendor/twig/twig/lib/Twig/Loader/Array.php<	  gR<	  }lT      /   vendor/twig/twig/lib/Twig/Loader/Filesystem.phpW  gRW  Tk      *   vendor/twig/twig/lib/Twig/Loader/Chain.php4  gR4  fn      3   vendor/twig/twig/lib/Twig/TestCallableInterface.php  gR  +F      3   vendor/twig/twig/lib/Twig/ExistsLoaderInterface.php  gR  w      )   vendor/twig/twig/lib/Twig/TokenParser.php  gR  3      *   vendor/twig/twig/lib/Twig/SimpleFilter.phpE  gRE  _ֶ      "   vendor/twig/twig/lib/Twig/Test.php  gR  {)      7   vendor/twig/twig/lib/Twig/FunctionCallableInterface.php  gR  .Qȶ      .   vendor/twig/twig/lib/Twig/TokenParser/From.php=  gR=  ܱͶ      3   vendor/twig/twig/lib/Twig/TokenParser/Spaceless.phpp  gRp  )P      1   vendor/twig/twig/lib/Twig/TokenParser/Extends.phpK  gRK  3      0   vendor/twig/twig/lib/Twig/TokenParser/Import.php  gR  8      ,   vendor/twig/twig/lib/Twig/TokenParser/If.php
  gR
  sJ)      4   vendor/twig/twig/lib/Twig/TokenParser/AutoEscape.php3
  gR3
  Ŷ      -   vendor/twig/twig/lib/Twig/TokenParser/Use.php  gR  KU      1   vendor/twig/twig/lib/Twig/TokenParser/Include.php  gR        -   vendor/twig/twig/lib/Twig/TokenParser/For.php  gR  (δ      ,   vendor/twig/twig/lib/Twig/TokenParser/Do.php  gR  Z       0   vendor/twig/twig/lib/Twig/TokenParser/Filter.php  gR  K      -   vendor/twig/twig/lib/Twig/TokenParser/Set.php		  gR		  me      /   vendor/twig/twig/lib/Twig/TokenParser/Block.phpX
  gRX
  ~      /   vendor/twig/twig/lib/Twig/TokenParser/Macro.php  gR  r"      1   vendor/twig/twig/lib/Twig/TokenParser/Sandbox.php  gR  +`      /   vendor/twig/twig/lib/Twig/TokenParser/Embed.php  gR  <Ⴖ      /   vendor/twig/twig/lib/Twig/TokenParser/Flush.php  gR  Gd޶      +   vendor/twig/twig/lib/Twig/NodeTraverser.php	  gR	  }-      +   vendor/twig/twig/lib/Twig/TestInterface.php  gR  N_      +   vendor/twig/twig/lib/Twig/Function/Node.php  gR        /   vendor/twig/twig/lib/Twig/Function/Function.php  gR  d+      -   vendor/twig/twig/lib/Twig/Function/Method.php  gR  !S      5   vendor/twig/twig/lib/Twig/FilterCallableInterface.php  gR  ݶ      *   vendor/twig/twig/lib/Twig/Error/Loader.php  gR  H@$      +   vendor/twig/twig/lib/Twig/Error/Runtime.php  gR  }ܶ      *   vendor/twig/twig/lib/Twig/Error/Syntax.php  gR   :      *   vendor/twig/twig/lib/Twig/Node/ForLoop.phpW  gRW  J)      ,   vendor/twig/twig/lib/Twig/Node/Spaceless.php  gR        1   vendor/twig/twig/lib/Twig/Node/BlockReference.php  gR  '      )   vendor/twig/twig/lib/Twig/Node/Module.phpi-  gRi-  W-0      '   vendor/twig/twig/lib/Twig/Node/Text.phph  gRh  !      )   vendor/twig/twig/lib/Twig/Node/Import.php	  gR	  %^]      %   vendor/twig/twig/lib/Twig/Node/If.php  gR  Ŷ      2   vendor/twig/twig/lib/Twig/Node/SandboxedModule.php  gR  ,m      (   vendor/twig/twig/lib/Twig/Node/Print.php  gR  W      -   vendor/twig/twig/lib/Twig/Node/AutoEscape.php  gR  g	      *   vendor/twig/twig/lib/Twig/Node/Include.phpQ  gRQ  \      &   vendor/twig/twig/lib/Twig/Node/For.php  gR  Wz      '   vendor/twig/twig/lib/Twig/Node/Body.phpQ  gRQ  3      %   vendor/twig/twig/lib/Twig/Node/Do.phpG  gRG  u0Q      *   vendor/twig/twig/lib/Twig/Node/SetTemp.phpH  gRH  !ݶ      &   vendor/twig/twig/lib/Twig/Node/Set.php  gR  ?rR      (   vendor/twig/twig/lib/Twig/Node/Block.php8  gR8  ж      1   vendor/twig/twig/lib/Twig/Node/SandboxedPrint.php=  gR=  q      (   vendor/twig/twig/lib/Twig/Node/Macro.php_
  gR_
  cu      3   vendor/twig/twig/lib/Twig/Node/Expression/Array.php.	  gR.	  Ҕ      <   vendor/twig/twig/lib/Twig/Node/Expression/BlockReference.phpn  gRn  z      4   vendor/twig/twig/lib/Twig/Node/Expression/Parent.php  gR  3      4   vendor/twig/twig/lib/Twig/Node/Expression/Binary.php  gR  w      6   vendor/twig/twig/lib/Twig/Node/Expression/Constant.php-  gR-  Dȶ      <   vendor/twig/twig/lib/Twig/Node/Expression/Filter/Default.php/  gR/  "      6   vendor/twig/twig/lib/Twig/Node/Expression/Test/Odd.phpy  gRy  |      ;   vendor/twig/twig/lib/Twig/Node/Expression/Test/Constant.phpj  gRj  P϶      >   vendor/twig/twig/lib/Twig/Node/Expression/Test/Divisibleby.php  gR  Y(      7   vendor/twig/twig/lib/Twig/Node/Expression/Test/Null.phpj  gRj        7   vendor/twig/twig/lib/Twig/Node/Expression/Test/Even.php|  gR|  ^u      9   vendor/twig/twig/lib/Twig/Node/Expression/Test/Sameas.php  gR  (I      :   vendor/twig/twig/lib/Twig/Node/Expression/Test/Defined.phpG  gRG  Dl      ?   vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseXor.php  gR  Il      >   vendor/twig/twig/lib/Twig/Node/Expression/Binary/LessEqual.php  gR  $_      :   vendor/twig/twig/lib/Twig/Node/Expression/Binary/Power.php  gR  b      8   vendor/twig/twig/lib/Twig/Node/Expression/Binary/Mod.php  gR  c      :   vendor/twig/twig/lib/Twig/Node/Expression/Binary/NotIn.php  gR  >      =   vendor/twig/twig/lib/Twig/Node/Expression/Binary/FloorDiv.php  gR  3Ӷ      <   vendor/twig/twig/lib/Twig/Node/Expression/Binary/Matches.php  gR  hP      8   vendor/twig/twig/lib/Twig/Node/Expression/Binary/Div.php  gR  	      8   vendor/twig/twig/lib/Twig/Node/Expression/Binary/Mul.php  gR  ]      :   vendor/twig/twig/lib/Twig/Node/Expression/Binary/Equal.php  gR  -      8   vendor/twig/twig/lib/Twig/Node/Expression/Binary/And.php  gR  gP      8   vendor/twig/twig/lib/Twig/Node/Expression/Binary/Add.php  gR  (H      7   vendor/twig/twig/lib/Twig/Node/Expression/Binary/Or.php  gR  Q      7   vendor/twig/twig/lib/Twig/Node/Expression/Binary/In.php  gR  1h      A   vendor/twig/twig/lib/Twig/Node/Expression/Binary/GreaterEqual.php  gR  Jf¶      <   vendor/twig/twig/lib/Twig/Node/Expression/Binary/Greater.php  gR  ī      8   vendor/twig/twig/lib/Twig/Node/Expression/Binary/Sub.php  gR  
b      ;   vendor/twig/twig/lib/Twig/Node/Expression/Binary/Concat.php  gR  eO      =   vendor/twig/twig/lib/Twig/Node/Expression/Binary/EndsWith.php  gR  B      ?   vendor/twig/twig/lib/Twig/Node/Expression/Binary/StartsWith.php  gR  )0      >   vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseOr.php  gR  VT      ?   vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseAnd.php  gR  )I      9   vendor/twig/twig/lib/Twig/Node/Expression/Binary/Less.php  gR  iض      =   vendor/twig/twig/lib/Twig/Node/Expression/Binary/NotEqual.php  gR  Z      :   vendor/twig/twig/lib/Twig/Node/Expression/Binary/Range.php  gR  GL      6   vendor/twig/twig/lib/Twig/Node/Expression/Function.php  gR  <      5   vendor/twig/twig/lib/Twig/Node/Expression/GetAttr.php  gR  ݎ޶      2   vendor/twig/twig/lib/Twig/Node/Expression/Name.php8  gR8  X|      4   vendor/twig/twig/lib/Twig/Node/Expression/Filter.phpb  gRb  #      2   vendor/twig/twig/lib/Twig/Node/Expression/Call.php  gR  	38      9   vendor/twig/twig/lib/Twig/Node/Expression/Conditional.php  gR  %٠      3   vendor/twig/twig/lib/Twig/Node/Expression/Unary.php  gR  OàQ      2   vendor/twig/twig/lib/Twig/Node/Expression/Test.php  gR  ?      8   vendor/twig/twig/lib/Twig/Node/Expression/AssignName.phph  gRh  4      7   vendor/twig/twig/lib/Twig/Node/Expression/Unary/Not.php  gR  5A      7   vendor/twig/twig/lib/Twig/Node/Expression/Unary/Pos.php  gR  `      7   vendor/twig/twig/lib/Twig/Node/Expression/Unary/Neg.php  gR  d       @   vendor/twig/twig/lib/Twig/Node/Expression/ExtensionReference.php&  gR&  *      6   vendor/twig/twig/lib/Twig/Node/Expression/TempName.phpR  gRR        8   vendor/twig/twig/lib/Twig/Node/Expression/MethodCall.php  gR  &P      *   vendor/twig/twig/lib/Twig/Node/Sandbox.php  gR  J      (   vendor/twig/twig/lib/Twig/Node/Embed.php  gR  p}ض      -   vendor/twig/twig/lib/Twig/Node/Expression.php  gR  AW      (   vendor/twig/twig/lib/Twig/Node/Flush.php  gR  !s@      $   vendor/twig/twig/lib/Twig/Markup.php  gR  E	      8   vendor/twig/twig/lib/Twig/TokenParserBrokerInterface.php  gR  ^Ʀ\      #   vendor/twig/twig/lib/Twig/Lexer.php,?  gR,?  i@c      /   vendor/twig/twig/lib/Twig/TemplateInterface.php  gR  v      -   vendor/twig/twig/lib/Twig/ParserInterface.php  gR  Wg      &   vendor/twig/twig/lib/Twig/Compiler.php  gR  fL1      -   vendor/twig/twig/lib/Twig/FilterInterface.phpN  gRN  S      ,   vendor/twig/twig/lib/Twig/LexerInterface.php  gR  q\         vendor/twig/twig/CHANGELOG|{  gR|{  Z~      0   vendor/phpcollection/phpcollection/composer.json   gR   r      D   vendor/phpcollection/phpcollection/src/PhpCollection/AbstractMap.phpU  gRU   Ȱ      J   vendor/phpcollection/phpcollection/src/PhpCollection/SortableInterface.phpD  gRD  hK-J      A   vendor/phpcollection/phpcollection/src/PhpCollection/Sequence.php^  gR^  iU      G   vendor/phpcollection/phpcollection/src/PhpCollection/SortedSequence.php  gR  =?      I   vendor/phpcollection/phpcollection/src/PhpCollection/AbstractSequence.php  gR  R׶      <   vendor/phpcollection/phpcollection/src/PhpCollection/Map.php2  gR2  #b      E   vendor/phpcollection/phpcollection/src/PhpCollection/MapInterface.phpv  gRv  XZWg      J   vendor/phpcollection/phpcollection/src/PhpCollection/SequenceInterface.phpd  gRd        K   vendor/phpcollection/phpcollection/src/PhpCollection/AbstractCollection.php=  gR=  O      L   vendor/phpcollection/phpcollection/src/PhpCollection/CollectionInterface.php  gR        *   vendor/phpcollection/phpcollection/LICENSE\,  gR\,  bE      6   vendor/phpcollection/phpcollection/tests/bootstrap.php   gR   ?      S   vendor/phpcollection/phpcollection/tests/PhpCollection/Tests/SortedSequenceTest.php  gR  z+	J      H   vendor/phpcollection/phpcollection/tests/PhpCollection/Tests/MapTest.php  gR  p      M   vendor/phpcollection/phpcollection/tests/PhpCollection/Tests/SequenceTest.php  gR         0   vendor/phpcollection/phpcollection/composer.lock  gR  1(޶      3   vendor/phpcollection/phpcollection/phpunit.xml.dist  gR  x      .   vendor/phpcollection/phpcollection/doc/LICENSE?  gR?  FD      3   vendor/cilex/console-service-provider/composer.json	  gR	  R       _   vendor/cilex/console-service-provider/src/Cilex/Provider/Console/BaseConsoleServiceProvider.php  gR  ee      ^   vendor/cilex/console-service-provider/src/Cilex/Provider/Console/ContainerAwareApplication.php  gR  Q      [   vendor/cilex/console-service-provider/src/Cilex/Provider/Console/ConsoleServiceProvider.php  gR  l7      i   vendor/cilex/console-service-provider/src/Cilex/Provider/Console/Adapter/Silex/ConsoleServiceProvider.php]  gR]  e      3   vendor/cilex/console-service-provider/composer.lock  gR  |Us         vendor/cilex/cilex/Vagrantfilek  gRk  "9>          vendor/cilex/cilex/composer.json  gR  D      0   vendor/cilex/cilex/src/Cilex/Command/Command.php  gR  >G      5   vendor/cilex/cilex/src/Cilex/Command/GreetCommand.php  gR  ^      8   vendor/cilex/cilex/src/Cilex/Command/DemoInfoCommand.php  gR  sCY      ,   vendor/cilex/cilex/src/Cilex/Application.php  gR  D      9   vendor/cilex/cilex/src/Cilex/ServiceProviderInterface.phpQ  gRQ  4u      A   vendor/cilex/cilex/src/Cilex/Provider/DoctrineServiceProvider.phpj  gRj  ]*'      ?   vendor/cilex/cilex/src/Cilex/Provider/ConfigServiceProvider.php	  gR	  D귶      B   vendor/cilex/cilex/src/Cilex/Provider/ValidatorServiceProvider.php  gR  `      @   vendor/cilex/cilex/src/Cilex/Provider/MonologServiceProvider.php  gR  f\cI      )   vendor/cilex/cilex/src/Cilex/Compiler.phpp  gRp  :W-G         vendor/cilex/cilex/bin/compile
  gR
  o+         vendor/cilex/cilex/docs/conf.py  gR  
;          vendor/cilex/cilex/docs/Makefile  gR  ~         vendor/cilex/cilex/LICENSE   gR            vendor/cilex/cilex/example.php   gR   z          vendor/cilex/cilex/composer.lockTd  gRTd  X/      #   vendor/cilex/cilex/phpunit.xml.dist  gR  Զ      *   vendor/phpdocumentor/fileset/composer.json  gR  /X9[      E   vendor/phpdocumentor/fileset/src/phpDocumentor/Fileset/Collection.php"  gR"  |iY      ?   vendor/phpdocumentor/fileset/src/phpDocumentor/Fileset/File.php  gR  KͶ      T   vendor/phpdocumentor/fileset/src/phpDocumentor/Fileset/Collection/IgnorePatterns.php7  gR7  UP      $   vendor/phpdocumentor/fileset/LICENSE   gR   VD      *   vendor/phpdocumentor/fileset/composer.lock;  gR;  9      -   vendor/phpdocumentor/fileset/phpunit.xml.dist"  gR"  H      -   vendor/phpdocumentor/reflection/composer.json  gR  b      J   vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Traverser.php	  gR	  /      J   vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Exception.phpR  gRR  :      S   vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/InterfaceReflector.php
  gR
  [˶      N   vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/PrettyPrinter.php  gR  {r      b   vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Event/PostDocBlockExtractionEvent.phpB  gRB  S!'      ]   vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Event/ExportDocBlockTagEvent.php  gR  UQ      Q   vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/IncludeReflector.php  gR  94      R   vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/FunctionReflector.php  gR  BD      N   vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/BaseReflector.php  gR  =      N   vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/FileReflector.php@  gR@  h      O   vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/TraitReflector.php  gR  |
R      d   vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/FunctionReflector/ArgumentReflector.php;  gR;  /nO      S   vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/ReflectionAbstract.php  gR  Ze      Y   vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Exception/UnparsableFile.php  gR  n      Y   vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Exception/UnreadableFile.php  gR  0!      _   vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/ClassReflector/MethodReflector.phpb  gRb  X}-      a   vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/ClassReflector/PropertyReflector.php  gR  bhD      a   vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/ClassReflector/ConstantReflector.php  gR  V.϶      O   vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/ClassReflector.php	  gR	  w?      R   vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/ConstantReflector.php  gR        F   vendor/phpdocumentor/reflection/src/phpDocumentor/Reflection/Lexer.phpR  gRR  [۶      Z   vendor/phpdocumentor/reflection/tests/unit/phpDocumentor/Reflection/ClassReflectorTest.phpJ  gRJ  qҷ      Y   vendor/phpdocumentor/reflection/tests/unit/phpDocumentor/Reflection/PrettyPrinterTest.php  gR  .      Y   vendor/phpdocumentor/reflection/tests/unit/phpDocumentor/Reflection/BaseReflectorTest.php@  gR@  Z޶      [   vendor/phpdocumentor/reflection/tests/mocks/phpDocumentor/Reflection/ClassReflectorMock.php=  gR=  %      V   vendor/phpdocumentor/reflection/tests/mocks/phpDocumentor/Reflection/NodeStmtMock2.phpf  gRf  sA      Z   vendor/phpdocumentor/reflection/tests/mocks/phpDocumentor/Reflection/BaseReflectorMock.php  gR  ]      U   vendor/phpdocumentor/reflection/tests/mocks/phpDocumentor/Reflection/NodeExprMock.php  gR  k      U   vendor/phpdocumentor/reflection/tests/mocks/phpDocumentor/Reflection/NodeStmtMock.php  gR  _n      -   vendor/phpdocumentor/reflection/composer.lockĎ  gRĎ  jʴʶ      0   vendor/phpdocumentor/reflection/phpunit.xml.distY  gRY  X-      +   vendor/phpdocumentor/graphviz/composer.json~  gR~  j      F   vendor/phpdocumentor/graphviz/src/phpDocumentor/GraphViz/Attribute.php
  gR
  #my      F   vendor/phpdocumentor/graphviz/src/phpDocumentor/GraphViz/Exception.php  gR  m      A   vendor/phpdocumentor/graphviz/src/phpDocumentor/GraphViz/Node.php  gR  Lȶ      B   vendor/phpdocumentor/graphviz/src/phpDocumentor/GraphViz/Graph.php	'  gR	'  x'      A   vendor/phpdocumentor/graphviz/src/phpDocumentor/GraphViz/Edge.php  gR  lw      +   vendor/phpdocumentor/graphviz/composer.lock6  gR6  ͎      .   vendor/phpdocumentor/graphviz/phpunit.xml.disto  gRo  bߛ      6   vendor/phpdocumentor/reflection-docblock/composer.jsonC  gRC        Z   vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Context.php5  gR5  l.%      ]   vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Serializer.php  gR  rж      ^   vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Description.php  gR  Բض      b   vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Type/Collection.php  gR  +=4      [   vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Location.phpq  gRq  u/      `   vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/CoversTag.phpI  gRI  9{      _   vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/ParamTag.phpU	  gRU	  W9"5      b   vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/PropertyTag.phpO  gRO  #m      `   vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/ReturnTag.php  gR  pS      d   vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/DeprecatedTag.php  gR  K      ]   vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/SeeTag.php  gR  i?$      ^   vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/UsesTag.phpE  gRE  .˶      `   vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/SourceTag.php  gR  n*      `   vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/AuthorTag.phpM  gRM  1      f   vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/PropertyReadTag.php[  gR[  <=      `   vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/ThrowsTag.phpL  gRL  "      a   vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/ExampleTag.php  gR  N:x      ^   vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/LinkTag.phpL  gRL  F      `   vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/MethodTag.php	  gR	  &7	      g   vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/PropertyWriteTag.php]  gR]  Rp      _   vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/SinceTag.php|  gR|  tR      a   vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/VersionTag.phpx
  gRx
  Eƶ      ]   vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag/VarTag.phpE  gRE  Ͷ      V   vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock/Tag.php(  gR(  E6      R   vendor/phpdocumentor/reflection-docblock/src/phpDocumentor/Reflection/DocBlock.php,  gR,  u      6   vendor/phpdocumentor/reflection-docblock/composer.lock:  gR:   ۶      9   vendor/phpdocumentor/reflection-docblock/phpunit.xml.distt  gRt  ¬P      :   vendor/phpdocumentor/unified-asset-installer/composer.jsonr  gRr  S;ç      a   vendor/phpdocumentor/unified-asset-installer/src/phpDocumentor/Composer/UnifiedAssetInstaller.php  gR  cj;      l   vendor/phpdocumentor/unified-asset-installer/tests/unit/phpDocumentor/Composer/UnifiedAssetInstallerTest.phpx  gRx  d1      @   vendor/phpdocumentor/unified-asset-installer/tests/bootstrap.php  gR  M      :   vendor/phpdocumentor/unified-asset-installer/composer.lockWb  gRWb  Ypն      =   vendor/phpdocumentor/unified-asset-installer/phpunit.xml.dist  gR  `P[      .   vendor/squizlabs/php_codesniffer/composer.json  gR  :      ,   vendor/squizlabs/php_codesniffer/package.xml(3 gR(3 ¿"      2   vendor/squizlabs/php_codesniffer/scripts/phpcs.bat  gR  Q!ֶ      =   vendor/squizlabs/php_codesniffer/scripts/phpcs-svn-pre-commiti  gRi  c      .   vendor/squizlabs/php_codesniffer/scripts/phpcs  gR  vHj      0   vendor/squizlabs/php_codesniffer/README.markdown  gR  Jv      L   vendor/squizlabs/php_codesniffer/tests/Core/File/GetMethodParametersTest.php  gR  8B      ?   vendor/squizlabs/php_codesniffer/tests/Core/IsCamelCapsTest.php  gR  ހ      D   vendor/squizlabs/php_codesniffer/tests/Core/ErrorSuppressionTest.php  gR  a      8   vendor/squizlabs/php_codesniffer/tests/Core/AllTests.php  gR  NN-      4   vendor/squizlabs/php_codesniffer/tests/TestSuite.php  gR  nWӶ      3   vendor/squizlabs/php_codesniffer/tests/AllTests.phpk
  gRk
  ޠ      >   vendor/squizlabs/php_codesniffer/tests/Standards/AllSniffs.php  gR        J   vendor/squizlabs/php_codesniffer/tests/Standards/AbstractSniffUnitTest.php1  gR1  Ͼ:      0   vendor/squizlabs/php_codesniffer/CodeSniffer.phpM gRM ,_%      :   vendor/squizlabs/php_codesniffer/CodeSniffer/Exception.php  gR  
      7   vendor/squizlabs/php_codesniffer/CodeSniffer/Report.php	  gR	  dp      =   vendor/squizlabs/php_codesniffer/CodeSniffer/Reports/Full.phpj  gRj  u:      <   vendor/squizlabs/php_codesniffer/CodeSniffer/Reports/Csv.php  gR  ^:      C   vendor/squizlabs/php_codesniffer/CodeSniffer/Reports/Notifysend.php  gR  m      @   vendor/squizlabs/php_codesniffer/CodeSniffer/Reports/Summary.php"  gR"  Ӷ      @   vendor/squizlabs/php_codesniffer/CodeSniffer/Reports/Hgblame.php_  gR_  W1      G   vendor/squizlabs/php_codesniffer/CodeSniffer/Reports/VersionControl.php!  gR!        >   vendor/squizlabs/php_codesniffer/CodeSniffer/Reports/Emacs.php3  gR3  cV      A   vendor/squizlabs/php_codesniffer/CodeSniffer/Reports/Gitblame.php9  gR9  &}j      C   vendor/squizlabs/php_codesniffer/CodeSniffer/Reports/Checkstyle.phph  gRh  p      >   vendor/squizlabs/php_codesniffer/CodeSniffer/Reports/Junit.phpQ  gRQ  `      =   vendor/squizlabs/php_codesniffer/CodeSniffer/Reports/Json.php  gR  f~s,      ?   vendor/squizlabs/php_codesniffer/CodeSniffer/Reports/Source.php  gR  KW      A   vendor/squizlabs/php_codesniffer/CodeSniffer/Reports/Svnblame.php	  gR	  <      <   vendor/squizlabs/php_codesniffer/CodeSniffer/Reports/Xml.php  gR  r^=      :   vendor/squizlabs/php_codesniffer/CodeSniffer/Reporting.php%  gR%  =[/      L   vendor/squizlabs/php_codesniffer/CodeSniffer/CommentParser/SingleElement.php  gR  L      M   vendor/squizlabs/php_codesniffer/CodeSniffer/CommentParser/CommentElement.phpm  gRm  ||      I   vendor/squizlabs/php_codesniffer/CodeSniffer/CommentParser/DocElement.php	  gR	  %&U      M   vendor/squizlabs/php_codesniffer/CodeSniffer/CommentParser/AbstractParser.phpN  gRN  Ҷ      R   vendor/squizlabs/php_codesniffer/CodeSniffer/CommentParser/MemberCommentParser.php  gR  u      Q   vendor/squizlabs/php_codesniffer/CodeSniffer/CommentParser/AbstractDocElement.phpX&  gRX&  wh      Q   vendor/squizlabs/php_codesniffer/CodeSniffer/CommentParser/ClassCommentParser.php  gR  _ض      T   vendor/squizlabs/php_codesniffer/CodeSniffer/CommentParser/FunctionCommentParser.php'  gR'  &      N   vendor/squizlabs/php_codesniffer/CodeSniffer/CommentParser/ParserException.php  gR  u      J   vendor/squizlabs/php_codesniffer/CodeSniffer/CommentParser/PairElement.phpg  gRg  U      O   vendor/squizlabs/php_codesniffer/CodeSniffer/CommentParser/ParameterElement.php/&  gR/&  쿝      4   vendor/squizlabs/php_codesniffer/CodeSniffer/CLI.phpy  gRy  i	+      >   vendor/squizlabs/php_codesniffer/CodeSniffer/Tokenizers/JS.phpU  gRU  ի\      ?   vendor/squizlabs/php_codesniffer/CodeSniffer/Tokenizers/PHP.php̎  gR̎  B      ?   vendor/squizlabs/php_codesniffer/CodeSniffer/Tokenizers/CSS.php|A  gR|A  6      5   vendor/squizlabs/php_codesniffer/CodeSniffer/File.php1 gR1       7   vendor/squizlabs/php_codesniffer/CodeSniffer/Tokens.phpaA  gRaA  #      6   vendor/squizlabs/php_codesniffer/CodeSniffer/Sniff.php)  gR)   ̶      C   vendor/squizlabs/php_codesniffer/CodeSniffer/DocGenerators/HTML.php$  gR$  FFƶ      C   vendor/squizlabs/php_codesniffer/CodeSniffer/DocGenerators/Text.php"  gR"  4h{      H   vendor/squizlabs/php_codesniffer/CodeSniffer/DocGenerators/Generator.php  gR  (      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Debug/FirebugConsoleSniff.php  gR  \      _   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Debug/DebugCodeSniff.php  gR  gfb      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Channels/ChannelExceptionSniff.php(	  gR(	  +R      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Channels/UnusedSystemSniff.php/  gR/  &϶      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Channels/IncludeSystemSniff.php6  gR6  )1}ֶ      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Channels/IncludeOwnSystemSniff.php_  gR_  Aw      l   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Channels/DisallowSelfActionsSniff.php~  gR~  u#      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/CSS/BrowserSpecificStylesSniff.php  gR  @3      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Objects/DisallowNewWidgetSniff.php  gR  3ж      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Objects/CreateWidgetTypeCallbackSniff.php!  gR!  0鍶      b   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Objects/AssignThisSniff.phpJ  gRJ  !q      j   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Commenting/FunctionCommentSniff.php  gR  ޶      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Strings/JoinStringsSniff.php
  gR
  (*      b   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/PHP/GetRequestDataSniff.php  gR  x      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/PHP/EvalObjectFactorySniff.php  gR  Y$      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/PHP/AjaxNullComparisonSniff.php  gR        g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/PHP/ReturnFunctionValueSniff.phpQ	  gRQ	  5۶      a   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/Debug/DebugCodeUnitTest.inc7   gR7   V      a   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/Debug/DebugCodeUnitTest.phpD  gRD  1      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/Debug/FirebugConsoleUnitTest.php  gR  Lƶ      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/Debug/FirebugConsoleUnitTest.js{   gR{   Z|      h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/Channels/IncludeSystemUnitTest.incu  gRu  'e      n   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/Channels/DisallowSelfActionsUnitTest.inc  gR  *<
      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/Channels/UnusedSystemUnitTest.php  gR        h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/Channels/IncludeSystemUnitTest.php6  gR6  yi      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/Channels/UnusedSystemUnitTest.inc   gR   R/|      n   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/Channels/DisallowSelfActionsUnitTest.php  gR  S-      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/CSS/BrowserSpecificStylesUnitTest.css  gR  [z      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/CSS/BrowserSpecificStylesUnitTest.php<  gR<  5      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/Objects/DisallowNewWidgetUnitTest.inc   gR   pጶ      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/Objects/AssignThisUnitTest.js%  gR%  ˁ!      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/Objects/DisallowNewWidgetUnitTest.phpF  gRF  p      r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/Objects/CreateWidgetTypeCallbackUnitTest.php  gR   B_      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/Objects/CreateWidgetTypeCallbackUnitTest.js  gR        d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/Objects/AssignThisUnitTest.php*  gR*  1I      l   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/Commenting/FunctionCommentUnitTest.inc,  gR,  _6s      l   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/Commenting/FunctionCommentUnitTest.php=  gR=  6"`      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/Strings/JoinStringsUnitTest.php  gR  qj}      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/Strings/JoinStringsUnitTest.js  gR  l      h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/PHP/AjaxNullComparisonUnitTest.inc7  gR7        g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/PHP/EvalObjectFactoryUnitTest.inc  gR  =G      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/PHP/ReturnFunctionValueUnitTest.inc   gR   rz      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/PHP/EvalObjectFactoryUnitTest.phpu  gRu  >      h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/PHP/AjaxNullComparisonUnitTest.php  gR        d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/PHP/GetRequestDataUnitTest.php  gR        i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/PHP/ReturnFunctionValueUnitTest.phpx  gRx  'C      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Tests/PHP/GetRequestDataUnitTest.incH  gRH  kR      K   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/ruleset.xml  gR  y      O   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/AbstractPatternSniff.php7  gR7  iٶ      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Namespaces/NamespaceDeclarationSniff.php	  gR	  k      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Namespaces/UseDeclarationSniff.phpb  gRb  S,<      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/ControlStructures/SwitchDeclarationSniff.phpb  gRb  &zh      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/ControlStructures/ElseIfDeclarationSniff.php  gR  @      u   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/ControlStructures/ControlStructureSpacingSniff.php  gR  	M      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Methods/MethodDeclarationSniff.php  gR  |      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Methods/FunctionCallSignatureSniff.php
  gR
  Y[      `   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Files/EndFileNewlineSniff.php  gR  vŶ      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Classes/ClassDeclarationSniff.php 5  gR 5  [      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Classes/PropertyDeclarationSniff.phpD  gRD  `J-      l   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Docs/Namespaces/NamespaceDeclarationStandard.xml#  gR#  1Au      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Docs/Namespaces/UseDeclarationStandard.xml  gR  ˛R      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Docs/ControlStructures/ElseIfDeclarationStandard.xmlE  gRE        p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Docs/ControlStructures/SwitchDeclarationStandard.xml	  gR	  x      v   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Docs/ControlStructures/ControlStructureSpacingStandard.xmlE  gRE  5mo      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Docs/Methods/MethodDeclarationStandard.xml  gR  j      a   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Docs/Files/EndFileNewlineStandard.xml   gR   ܬ      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Docs/Classes/ClassDeclarationStandard.xml  gR  З      h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Docs/Classes/PropertyDeclarationStandard.xml  gR  e9凶      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.3.inc   gR   ,      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/Namespaces/NamespaceDeclarationUnitTest.incc   gRc   b]      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.php)
  gR)
  jN]      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/Namespaces/NamespaceDeclarationUnitTest.php=  gR=  }Զ      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.2.inc   gR   +      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/Namespaces/UseDeclarationUnitTest.1.incz  gRz  ݓX      w   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.inc%  gR%  Ͱ]      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.inc  gR  -2      w   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/ControlStructures/ControlStructureSpacingUnitTest.php  gR  4       q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/ControlStructures/SwitchDeclarationUnitTest.php  gR  &F      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc   gR   K2      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/ControlStructures/ElseIfDeclarationUnitTest.phpT  gRT  D      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/Methods/MethodDeclarationUnitTest.php  gR        g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/Methods/MethodDeclarationUnitTest.inc  gR  )      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.incF  gRF  gʶ      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/Methods/FunctionCallSignatureUnitTest.php  gR  #Z~      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.4.inc   gR   n      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.7.inc#   gR#   c-      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.2.inc   gR   z8      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.6.inc   gR   S.6      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.3.inc   gR   e      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.1.inc   gR         d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.5.inc/   gR/   0      b   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/Files/EndFileNewlineUnitTest.php	  gR	  bٶ      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.php  gR  g}       i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/Classes/PropertyDeclarationUnitTest.inc  gR  g      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/Classes/ClassDeclarationUnitTest.inc;  gR;  oo      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Tests/Classes/PropertyDeclarationUnitTest.php  gR  5      G   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/ruleset.xml$  gR$  K      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR1/Sniffs/Methods/CamelCapsMethodNameSniff.php  gR  e      ]   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR1/Sniffs/Files/SideEffectsSniff.php  gR  T      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR1/Sniffs/Classes/ClassDeclarationSniff.php	  gR	  nD      ^   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR1/Docs/Files/SideEffectsStandard.xml^  gR^  ƾ      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR1/Docs/Classes/ClassDeclarationStandard.xml  gR  OS      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR1/Tests/Methods/CamelCapsMethodNameUnitTest.php  gR  d3      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR1/Tests/Methods/CamelCapsMethodNameUnitTest.inc  gR  Z[      a   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR1/Tests/Files/SideEffectsUnitTest.3.inck   gRk   Ll      a   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR1/Tests/Files/SideEffectsUnitTest.1.inc  gR  ])      a   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR1/Tests/Files/SideEffectsUnitTest.4.incg   gRg   zՠ)      a   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR1/Tests/Files/SideEffectsUnitTest.2.inc   gR   9mն      _   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR1/Tests/Files/SideEffectsUnitTest.php  gR  x$      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR1/Tests/Classes/ClassDeclarationUnitTest.php  gR  ߰g      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR1/Tests/Classes/ClassDeclarationUnitTest.inc#   gR#   x      G   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR1/ruleset.xml  gR  Ir      [   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Debug/JSHintSniff.php  gR  nl2      \   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Debug/CSSLintSniff.php  gR  BNܶ      b   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Debug/ClosureLinterSniff.php  gR        r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/VersionControl/SubversionPropertiesSniff.php  gR  ϣJn      t   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/UnconditionalIfStatementSniff.phpX  gRX  ~T      s   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/UnusedFunctionParameterSniff.php$  gR$  W'      n   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/JumbledIncrementerSniff.php  gR  ˍ      s   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/UselessOverridingMethodSniff.php  gR  Ò}      t   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/UnnecessaryFinalModifierSniff.php
  gR
  bj      w   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/ForLoopWithTestFunctionCallSniff.php  gR        t   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/ForLoopShouldBeWhileLoopSniff.phpH  gRH  ,      j   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/EmptyStatementSniff.php  gR  '      v   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/NamingConventions/CamelCapsFunctionNameSniff.phpG  gRG  =Sd      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/NamingConventions/ConstructorNameSniff.phpv  gRv  Jyȶ      v   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/NamingConventions/UpperCaseConstantNameSniff.phpz  gRz  LA      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/WhiteSpace/DisallowTabIndentSniff.php	  gR	  S#e      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/WhiteSpace/ScopeIndentSniff.phpD  gRD  ?۶      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/WhiteSpace/DisallowSpaceIndentSniff.php
  gR
  κ      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Functions/CallTimePassByReferenceSniff.php  gR  Rv      v   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceBsdAllmanSniff.php  gR  _      t   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Functions/FunctionCallArgumentSpacingSniff.php  gR  lZ      }   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceKernighanRitchieSniff.php  gR  ]R      w   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php  gR        _   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Commenting/FixmeSniff.php
  gR
  sH      ^   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Commenting/TodoSniff.phpg
  gRg
        k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Metrics/CyclomaticComplexitySniff.php  gR  V      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Metrics/NestingLevelSniff.phpi  gRi  P      _   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/InlineHTMLSniff.php  gR  Kܶ      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/OneClassPerFileSniff.php  gR  l6Զ      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/LowercasedFilenameSniff.php  gR  ?L{۶      `   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/LineEndingsSniff.php  gR  Yq      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/EndFileNewlineSniff.php
  gR
  WI      b   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/ByteOrderMarkSniff.php  gR  <      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/EndFileNoNewlineSniff.php
  gR
  .      _   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/LineLengthSniff.php  gR  Tᆶ      h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/OneInterfacePerFileSniff.php
  gR
  N      n   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Strings/UnnecessaryStringConcatSniff.php  gR   \      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/UpperCaseConstantSniff.phpD  gRD        f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/DeprecatedFunctionsSniff.phpM  gRM  ڵ      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/LowerCaseConstantSniff.php?  gR?        \   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/SAPIUsageSniff.php	  gR	  Ϗs      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/ForbiddenFunctionsSniff.php  gR  ڊ      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/DisallowShortOpenTagSniff.php
  gR
  PX@4      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/LowerCaseKeywordSniff.php  gR  X      `   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/ClosingPHPTagSniff.php  gR  X      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/CharacterBeforePHPOpeningTagSniff.php  gR  ڶ      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/NoSilencedErrorsSniff.php7  gR7  -M      h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Formatting/SpaceAfterCastSniff.php  gR  .      t   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Formatting/DisallowMultipleStatementsSniff.phpq
  gRq
  {      j   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Formatting/NoSpaceAfterCastSniff.php  gR  >      t   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Formatting/MultipleStatementAlignmentSniff.php,  gR,  ,]#      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.phpS  gRS  U      ]   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/Debug/CSSLintStandard.xml  gR  Q      \   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/Debug/JSHintStandard.xml  gR        c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/Debug/ClosureLinterStandard.xml  gR  .S¶      s   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/VersionControl/SubversionPropertiesStandard.xml  gR  .tҶ      t   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/CodeAnalysis/UselessOverridingMethodStandard.xml  gR  Zr      u   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/CodeAnalysis/UnnecessaryFinalModifierStandard.xmlw  gRw  YC      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/CodeAnalysis/EmptyStatementStandard.xml$  gR$  %"      u   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/CodeAnalysis/ForLoopShouldBeWhileLoopStandard.xml  gR  ꃶ      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/CodeAnalysis/JumbledIncrementerStandard.xml  gR  ?b      x   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/CodeAnalysis/ForLoopWithTestFunctionCallStandard.xml  gR  ?6      u   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/CodeAnalysis/UnconditionalIfStatementStandard.xml  gR  x˶      t   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/CodeAnalysis/UnusedFunctionParameterStandard.xmlY  gRY   ȴy      w   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/NamingConventions/UpperCaseConstantNameStandard.xmlj  gRj  G8      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/NamingConventions/ConstructorNameStandard.xmlA  gRA  Y      w   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/NamingConventions/CamelCapsFunctionNameStandard.xmlC  gRC  F~ݶ      n   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/WhiteSpace/DisallowSpaceIndentStandard.xml   gR         f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/WhiteSpace/ScopeIndentStandard.xmlF  gRF  
!<      l   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/WhiteSpace/DisallowTabIndentStandard.xml   gR   g      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/Functions/CallTimePassByReferenceStandard.xml  gR  F!      ~   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/Functions/OpeningFunctionBraceKernighanRitchieStandard.xml  gR  D      w   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/Functions/OpeningFunctionBraceBsdAllmanStandard.xml  gR  
$q      u   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/Functions/FunctionCallArgumentSpacingStandard.xml  gR  W      x   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/ControlStructures/InlineControlStructureStandard.xml  gR  LJ      _   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/Commenting/TodoStandard.xml  gR  ߶      `   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/Commenting/FixmeStandard.xml  gR  F=c      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/Metrics/NestingLevelStandard.xml   gR   }~      l   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/Metrics/CyclomaticComplexityStandard.xml   gR   qض      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/Files/OneInterfacePerFileStandard.xml  gR  K      `   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/Files/InlineHTMLStandard.xmlS  gRS  w/=      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/Files/OneClassPerFileStandard.xml  gR  $׿      a   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/Files/LineEndingsStandard.xml   gR   f      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/Files/EndFileNoNewlineStandard.xml   gR   Ev      `   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/Files/LineLengthStandard.xml   gR   z/$      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/Files/EndFileNewlineStandard.xml   gR   c      h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/Files/LowercasedFilenameStandard.xml   gR   U<-      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/Files/ByteOrderMarkStandard.xml  gR  Lٻ      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/Strings/UnnecessaryStringConcatStandard.xml  gR  6Wֶ      ]   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/PHP/SAPIUsageStandard.xml+  gR+  Xݶ      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/PHP/DeprecatedFunctionsStandard.xml  gR  q_.      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/PHP/CharacterBeforePHPOpeningTagStandard.xml!  gR!  v꒶      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/PHP/UpperCaseConstantStandard.xmla  gRa  %1      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/PHP/ForbiddenFunctionsStandard.xml  gR  [      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/PHP/NoSilencedErrorsStandard.xml!  gR!  w      h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/PHP/DisallowShortOpenTagStandard.xml  gR        d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/PHP/LowerCaseKeywordStandard.xml  gR  T      a   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/PHP/ClosingPHPTagStandard.xml  gR  ޶      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/PHP/LowerCaseConstantStandard.xmla  gRa        u   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/Formatting/MultipleStatementAlignmentStandard.xml  gR  O      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/Formatting/SpaceAfterCastStandard.xml  gR  '      u   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/Formatting/DisallowMultipleStatementsStandard.xml  gR  ԫ޶      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/Formatting/NoSpaceAfterCastStandard.xml  gR  M5      j   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Docs/Classes/DuplicateClassNameStandard.xml+  gR+  !+Y      l   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/CodeAnalysis/EmptyStatementUnitTest.php  gR  2      u   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/CodeAnalysis/UnusedFunctionParameterUnitTest.inc  gR  [      v   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/CodeAnalysis/UnconditionalIfStatementUnitTest.incs   gRs   p      l   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/CodeAnalysis/EmptyStatementUnitTest.inc  gR  "&Ƿ      v   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/CodeAnalysis/UnnecessaryFinalModifierUnitTest.php  gR         v   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/CodeAnalysis/ForLoopShouldBeWhileLoopUnitTest.inc   gR   M      v   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/CodeAnalysis/UnnecessaryFinalModifierUnitTest.inc  gR  t]D      y   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/CodeAnalysis/ForLoopWithTestFunctionCallUnitTest.php  gR  ?k      v   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/CodeAnalysis/ForLoopShouldBeWhileLoopUnitTest.php  gR        u   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/CodeAnalysis/UnusedFunctionParameterUnitTest.php{  gR{  Ëp      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/CodeAnalysis/JumbledIncrementerUnitTest.inc  gR  >`      u   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/CodeAnalysis/UselessOverridingMethodUnitTest.php}  gR}  t      u   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/CodeAnalysis/UselessOverridingMethodUnitTest.inc  gR   ;s      y   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/CodeAnalysis/ForLoopWithTestFunctionCallUnitTest.inc  gR  v)      v   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/CodeAnalysis/UnconditionalIfStatementUnitTest.php  gR  h!*      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/CodeAnalysis/JumbledIncrementerUnitTest.php  gR        x   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/NamingConventions/UpperCaseConstantNameUnitTest.php  gR  
䨶      x   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/NamingConventions/UpperCaseConstantNameUnitTest.inc
  gR
        x   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/NamingConventions/CamelCapsFunctionNameUnitTest.inc	  gR	  r&      x   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/NamingConventions/CamelCapsFunctionNameUnitTest.php  gR  M      r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/NamingConventions/ConstructorNameUnitTest.inc  gR  HV      r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/NamingConventions/ConstructorNameUnitTest.php  gR        m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.inc   gR   Uu      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.phpZ
  gRZ
  V      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.css=   gR=   Qo      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.css>   gR>   d,      n   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.jsH   gRH   fԶ      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/WhiteSpace/DisallowSpaceIndentUnitTest.inc  gR  U~      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.php<
  gR<
  Y      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.incT!  gRT!  _yY      l   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/WhiteSpace/DisallowTabIndentUnitTest.jsJ   gRJ   њ      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/WhiteSpace/ScopeIndentUnitTest.php.
  gR.
  ֶ      r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Functions/CallTimePassByReferenceUnitTest.incs  gRs  DK      r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Functions/CallTimePassByReferenceUnitTest.php  gR  	fl      v   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Functions/FunctionCallArgumentSpacingUnitTest.incA  gRA  5yӶ         vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Functions/OpeningFunctionBraceKernighanRitchieUnitTest.php	  gR	  ;.          vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Functions/OpeningFunctionBraceKernighanRitchieUnitTest.inc3  gR3  1t      v   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Functions/FunctionCallArgumentSpacingUnitTest.php  gR  vj      x   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Functions/OpeningFunctionBraceBsdAllmanUnitTest.php	  gR	  M?      x   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Functions/OpeningFunctionBraceBsdAllmanUnitTest.incP	  gRP	        y   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.php
  gR
  <@      x   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.js  gR  2)d      y   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/ControlStructures/InlineControlStructureUnitTest.inc"  gR"  >/      _   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Commenting/TodoUnitTest.jsO  gRO  ö      `   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Commenting/FixmeUnitTest.jsY  gRY  8ҁ      `   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Commenting/TodoUnitTest.php
  gR
  I~      `   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Commenting/TodoUnitTest.incX  gRX  '      a   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Commenting/FixmeUnitTest.inc  gR  h      a   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Commenting/FixmeUnitTest.phpZ  gRZ  7	Զ      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Metrics/CyclomaticComplexityUnitTest.php  gR        e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Metrics/NestingLevelUnitTest.inc	  gR	  Z`      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Metrics/NestingLevelUnitTest.php  gR  iJ      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Metrics/CyclomaticComplexityUnitTest.inc  gR  
ߧʶ      b   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/LineEndingsUnitTest.css1   gR1   lH      a   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/LineEndingsUnitTest.js   gR   [      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.2.js   gR         i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.1.css   gR   F؇      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/LowercasedFilenameUnitTest.php  gR  h
      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.3.css   gR   aT      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/OneClassPerFileUnitTest.inc7   gR7   Bi      h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.2.js   gR         g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.2.css   gR   ;߶      a   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/LineLengthUnitTest.phpY  gRY  a      b   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/LineEndingsUnitTest.php  gR  Z      j   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/OneInterfacePerFileUnitTest.php#  gR#  `]      a   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/InlineHTMLUnitTest.php		  gR		  @(O      a   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/LineLengthUnitTest.inc  gR  eLU      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.2.inc   gR   z8      b   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/LineEndingsUnitTest.inc0   gR0   ne`      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/LowercasedFilenameUnitTest.inc   gR   xж      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.3.js   gR         d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/ByteOrderMarkUnitTest.inc   gR   7V      h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.3.js   gR         g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.3.inc   gR   e      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/OneClassPerFileUnitTest.php  gR  ۶      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.2.css   gR   ;߶      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.1.css   gR   F؇      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.2.inc   gR   `u      h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.1.js   gR   q<      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/InlineHTMLUnitTest.4.inc,   gR,   ＾      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.1.inc   gR         c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/InlineHTMLUnitTest.2.inc   gR   `u      j   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/OneInterfacePerFileUnitTest.incF   gRF   F3dj      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.4.inc   gR   c      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/ByteOrderMarkUnitTest.php%  gR%  8˱      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/InlineHTMLUnitTest.3.inc.   gR.   V͉      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/InlineHTMLUnitTest.1.inc   gR         i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.1.inc   gR         f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.1.js   gR   q<      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.3.css   gR   aT      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.3.inc   gR   e      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/EndFileNoNewlineUnitTest.php	  gR	  M;      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Files/EndFileNewlineUnitTest.php  gR        p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.php	  gR	        p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.incZ  gRZ  ?8ض      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Strings/UnnecessaryStringConcatUnitTest.js  gR  q      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/PHP/ForbiddenFunctionsUnitTest.php  gR  unm      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.php  gR  F۶      b   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/PHP/ClosingPHPTagUnitTest.php  gR  6&      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/PHP/CharacterBeforePHPOpeningTagUnitTest.php:  gR:  K<      ^   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/PHP/SAPIUsageUnitTest.incm   gRm   f      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/PHP/ForbiddenFunctionsUnitTest.incR  gRR  0$-      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/PHP/NoSilencedErrorsUnitTest.php,  gR,  o1      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.inc  gR  C*      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.incR   gRR   ]E      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/PHP/NoSilencedErrorsUnitTest.incU   gRU   
u,      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.inc  gR  B0      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/PHP/LowerCaseConstantUnitTest.js,  gR,  T      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.php  gR  ׆      ^   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/PHP/SAPIUsageUnitTest.php  gR  [A/      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/PHP/UpperCaseConstantUnitTest.inc  gR  	      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/PHP/LowerCaseKeywordUnitTest.php  gR  x,$      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/PHP/CharacterBeforePHPOpeningTagUnitTest.inc2   gR2   ot{      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/PHP/DisallowShortOpenTagUnitTest.phph	  gRh	  Y+      b   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/PHP/ClosingPHPTagUnitTest.inc_   gR_   3      v   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Formatting/MultipleStatementAlignmentUnitTest.php|  gR|  _ H      j   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Formatting/SpaceAfterCastUnitTest.inc  gR        v   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Formatting/DisallowMultipleStatementsUnitTest.php  gR  eA      l   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Formatting/NoSpaceAfterCastUnitTest.inc  gR        v   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Formatting/DisallowMultipleStatementsUnitTest.inc   gR   M(      v   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Formatting/MultipleStatementAlignmentUnitTest.inc  gR  Ȉ      j   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Formatting/SpaceAfterCastUnitTest.php	  gR	  =      l   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Formatting/NoSpaceAfterCastUnitTest.php	  gR	  φ&      u   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Formatting/MultipleStatementAlignmentUnitTest.js  gR  G`ն      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.php
  gR
  [      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.2.inc2   gR2   0      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.3.incr   gRr   7      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.6.incv   gRv   }	      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.5.inc`   gR`   憆      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.4.inc?   gR?   H      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Tests/Classes/DuplicateClassNameUnitTest.1.inc   gR   _ф      J   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/ruleset.xml   gR   Hp      a   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Debug/JavaScriptLintSniff.php(  gR(        Y   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Debug/JSLintSniff.php,  gR,  2      ^   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Scope/MethodScopeSniff.php	  gR	  dJH      a   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Scope/MemberVarScopeSniff.php  gR  !      b   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Scope/StaticThisUsageSniff.php  gR  ֶ      h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CodeAnalysis/EmptyStatementSniff.php*  gR*        p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/NamingConventions/ValidFunctionNameSniff.php@
  gR@
  0Ex      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/NamingConventions/ConstantCaseSniff.phpY  gRY  V      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/NamingConventions/ValidVariableNameSniff.phpu%  gRu%  #E      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Arrays/ArrayDeclarationSniff.php\  gR\  uưƶ      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Arrays/ArrayBracketSpacingSniff.php{  gR{  Um      h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/SemicolonSpacingSniff.php
  gR
  t      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/ObjectOperatorSpacingSniff.php	  gR	  G      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/CastSpacingSniff.php  gR  =      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php  gR  	      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/LanguageConstructSpacingSniff.phpM  gRM  `      h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/MemberVarSpacingSniff.php  gR  љٶ      n   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/LogicalOperatorSpacingSniff.php  gR  !ö      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/ScopeKeywordSpacingSniff.php
  gR
  O$      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/ScopeClosingBraceSniff.phpi  gRi  g      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/SuperfluousWhitespaceSniff.php$!  gR$!  ?D      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/FunctionClosingBraceSpaceSniff.php  gR  %      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/FunctionSpacingSniff.php  gR  
      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/OperatorSpacingSniff.php#  gR#  =Q      l   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/PropertyLabelSpacingSniff.php	  gR	  :      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/FunctionOpeningBraceSpaceSniff.php,  gR,  a;B      a   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/ColourDefinitionSniff.php
  gR
  k0Ѷ      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/ClassDefinitionOpeningBraceSpaceSniff.php  gR  v      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/LowercaseStyleDefinitionSniff.php  gR  zHZ      \   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/IndentationSniff.phpt  gRt  u      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/ClassDefinitionNameSpacingSniff.php}  gR}  "Ob      a   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/SemicolonSpacingSniff.php	  gR	  ;      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/EmptyClassDefinitionSniff.php@  gR@  ηZ      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/ClassDefinitionClosingBraceSpaceSniff.phpY  gRY  Ֆ      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/DuplicateClassDefinitionSniff.phpc  gRc  0n      ]   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/MissingColonSniff.php  gR   \      ]   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/ColonSpacingSniff.php  gR  B'      ]   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/NamedColoursSniff.php  gR  i<      ^   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/ShorthandSizeSniff.php?  gR?   |      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/DisallowMultipleStyleDefinitionsSniff.php  gR  iT      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/DuplicateStyleDefinitionSniff.php
  gR
  r8      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/EmptyStyleDefinitionSniff.phpZ  gRZ  E"      `   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/ForbiddenStylesSniff.php7  gR7  J9      X   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/OpacitySniff.phpy  gRy  Qww      s   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Functions/MultiLineFunctionDeclarationSniff.php  gR  Z~      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Functions/FunctionDuplicateArgumentSniff.php
  gR
  M@      j   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Functions/FunctionDeclarationSniff.php4  gR4  }FX      y   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Functions/FunctionDeclarationArgumentSpacingSniff.phpJ3  gRJ3  i5      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Functions/LowercaseFunctionKeywordsSniff.php@	  gR@	  z      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Functions/GlobalFunctionSniff.php	  gR	  b      s   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/ControlStructures/LowercaseDeclarationSniff.php	  gR	  Ԃ      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/ControlStructures/SwitchDeclarationSniff.php-  gR-  ЅF¶      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/ControlStructures/ControlSignatureSniff.php:  gR:  R7p      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/ControlStructures/ElseIfDeclarationSniff.php  gR  iI      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/ControlStructures/ForLoopDeclarationSniff.php  gR  /       r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/ControlStructures/InlineIfDeclarationSniff.php  gR  d{޶      u   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/ControlStructures/ForEachLoopDeclarationSniff.php}  gR}  K      l   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Operators/ValidLogicalOperatorsSniff.php	  gR	  <      n   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Operators/IncrementDecrementUsageSniff.php_   gR_   H޶      n   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Operators/ComparisonOperatorUsageSniff.php  gR  y      h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Objects/ObjectInstantiationSniff.php	  gR	  >z      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Objects/ObjectMemberCommaSniff.php	  gR	  *qö      n   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Objects/DisallowObjectStringIndexSniff.php  gR  O[      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/InlineCommentSniff.php$  gR$  7'Zܶ      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/EmptyCatchCommentSniff.php  gR  j      l   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/PostStatementCommentSniff.php  gR  ]2      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/FunctionCommentThrowTagSniff.php   gR   CyP      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/ClosingDeclarationCommentSniff.php  gR  VT^      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/VariableCommentSniff.php6  gR6  C      s   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/LongConditionClosingCommentSniff.php  gR  _      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/FunctionCommentSniff.php  gR  {      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/BlockCommentSniff.php%  gR%  %r,      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/ClassCommentSniff.php$+  gR$+  3      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/DocCommentAlignmentSniff.php  gR  ¶      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/FileCommentSniff.phpW  gRW  qR7V      `   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Files/FileExtensionSniff.php
  gR
  [ȶ      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Strings/ConcatenationSpacingSniff.phpL  gRL  A      b   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Strings/EchoedStringsSniff.php
  gR
  D      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Strings/DoubleQuoteUsageSniff.php  gR  |ٞ      l   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/DisallowMultipleAssignmentsSniff.php2  gR2  ض      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/LowercasePHPFunctionsSniff.php  gR  Ѓ      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/DisallowObEndFlushSniff.php  gR  a       a   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/DisallowInlineIfSniff.php
  gR
  #Έ      ^   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/GlobalKeywordSniff.php  gR        c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/ForbiddenFunctionsSniff.php  gR  *      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/DisallowComparisonAssignmentSniff.php  gR  z0      \   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/EmbeddedPhpSniff.php%  gR%  !      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/DiscouragedFunctionsSniff.php  gR  oVt      X   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/HeredocSniff.php  gR  
      U   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/EvalSniff.php  gR        m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/DisallowSizeFunctionsInLoopsSniff.php  gR  1      _   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/InnerFunctionsSniff.php  gR  +%|      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/DisallowBooleanStatementSniff.php  gR  &'w      a   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/CommentedOutCodeSniff.php  gR        b   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/NonExecutableCodeSniff.phpK(  gRK(  zW      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Formatting/OperatorBracketSniff.php%)  gR%)  'v      h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Classes/SelfMemberReferenceSniff.php@  gR@        b   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Classes/ClassFileNameSniff.php
  gR
  oA      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Classes/ValidClassNameSniff.phpR  gRR  ħ      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Classes/ClassDeclarationSniff.phpF  gRF  =G      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Classes/DuplicatePropertySniff.php   gR   +ٶ      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Classes/LowercaseClassKeywordsSniff.php	  gR	  ,}E)      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Docs/Scope/StaticThisUsageStandard.xmlt  gRt  Z      h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Docs/Arrays/ArrayBracketSpacingStandard.xml-  gR-  z)      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Docs/Arrays/ArrayDeclarationStandard.xml  gR  cul      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Docs/WhiteSpace/SemicolonSpacingStandard.xml  gR        l   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Docs/WhiteSpace/ScopeKeywordSpacingStandard.xml@  gR@  b˳      n   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Docs/WhiteSpace/ObjectOperatorSpacingStandard.xml  gR  @w      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Docs/WhiteSpace/CastSpacingStandard.xml  gR  ̶      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Docs/WhiteSpace/LanguageConstructSpacingStandard.xml2  gR2  ʀ      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Docs/WhiteSpace/FunctionOpeningBraceStandard.xml  gR  |l      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Docs/Functions/LowercaseFunctionKeywordsStandard.xml  gR  ꭶ      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Docs/Functions/FunctionDuplicateArgumentStandard.xml  gR  zF      r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Docs/ControlStructures/ForLoopDeclarationStandard.xmlZ  gRZ  &m#      t   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Docs/ControlStructures/LowercaseDeclarationStandard.xml"  gR"  &      v   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Docs/ControlStructures/ForEachLoopDeclarationStandard.xml  gR  Z$C      l   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Docs/Commenting/DocCommentAlignmentStandard.xmlM  gRM   ]      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Docs/Commenting/FunctionCommentThrowTagStandard.xml  gR  oxk      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Docs/Strings/EchoedStringsStandard.xml  gR  .k      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Docs/Classes/SelfMemberReferenceStandard.xml:  gR:  v._      l   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Docs/Classes/LowercaseClassKeywordsStandard.xml`  gR`   U!      [   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Debug/JSLintUnitTest.php8  gR8  球      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Debug/JavaScriptLintUnitTest.php5  gR5  h      b   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Debug/JavaScriptLintUnitTest.js   gR   I      Z   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Debug/JSLintUnitTest.js   gR   I      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Scope/MemberVarScopeUnitTest.php  gR  :L?A      `   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Scope/MethodScopeUnitTest.php  gR  ~MŶ      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Scope/MemberVarScopeUnitTest.inc   gR   3      `   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Scope/MethodScopeUnitTest.incJ  gRJ  ׶      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Scope/StaticThisUsageUnitTest.php  gR  dʶ      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Scope/StaticThisUsageUnitTest.inc_  gR_        j   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CodeAnalysis/EmptyStatementUnitTest.php8  gR8  }V      j   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CodeAnalysis/EmptyStatementUnitTest.inc  gR        m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/NamingConventions/ConstantCaseUnitTest.phpG  gRG  f9      r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/NamingConventions/ValidVariableNameUnitTest.phpE
  gRE
  ưj      r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/NamingConventions/ValidVariableNameUnitTest.inc  gR  q      l   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/NamingConventions/ConstantCaseUnitTest.js,  gR,  T      r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/NamingConventions/ValidFunctionNameUnitTest.incz  gRz  @      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/NamingConventions/ConstantCaseUnitTest.inc  gR  :pv      r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/NamingConventions/ValidFunctionNameUnitTest.php  gR  ي      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.php  gR  5      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.incV  gRV  =	      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Arrays/ArrayBracketSpacingUnitTest.php  gR  k!oG      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Arrays/ArrayDeclarationUnitTest.incu  gRu  0      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.inc   gR   O4      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/CastSpacingUnitTest.incr   gRr   V      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.css2   gR2   h      r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.inc  gR  vv2      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.js   gR   +	      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.2.js   gR          q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.inc  gR  F\      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.js>  gR>  {ֶ      s   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/FunctionOpeningBraceSpaceUnitTest.php\
  gR\
  n      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.css  gR  
(      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.phpJ  gRJ  V      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.inc  gR  K      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.php%  gR%  =V      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/ControlStructureSpacingUnitTest.js  gR   ö      h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.js  gR  .e      r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/FunctionOpeningBraceSpaceUnitTest.jsr  gRr  3!      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/ScopeKeywordSpacingUnitTest.php  gR  i1      r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/LanguageConstructSpacingUnitTest.php	  gR	  G֙      s   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/FunctionOpeningBraceSpaceUnitTest.inc  gR  paܶ      j   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.inc   gR   æ      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.inc  gR  /!      j   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.inc~  gR~  ?߶      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/LogicalOperatorSpacingUnitTest.inc  gR  (      s   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/FunctionClosingBraceSpaceUnitTest.phpS
  gRS
  {      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/CastSpacingUnitTest.php  gR  zs8      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.inc
  gR
        i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.php	  gR	        p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/LogicalOperatorSpacingUnitTest.php  gR  q      j   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/MemberVarSpacingUnitTest.php^  gR^  ~      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/ScopeClosingBraceUnitTest.php  gR  88      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.js   gR   0      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.inc{  gR{  ~Ӌ      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.3.css3   gR3   ']      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/SuperfluousWhitespaceUnitTest.1.js  gR  /z=      r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/FunctionClosingBraceSpaceUnitTest.jsF  gRF  ;{      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/LogicalOperatorSpacingUnitTest.js   gR   9ζ      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.php  gR  ,      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/ObjectOperatorSpacingUnitTest.php  gR  H~"      j   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/SemicolonSpacingUnitTest.phpn
  gRn
  mf      s   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/FunctionClosingBraceSpaceUnitTest.incS  gRS  5      n   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/PropertyLabelSpacingUnitTest.php  gR        k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc  gR  W/y      _   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.cssH  gRH        s   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.php  gR  p      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/LowercaseStyleDefinitionUnitTest.css  gR  Ae*      _   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/MissingColonUnitTest.phpi  gRi  .V      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/EmptyClassDefinitionUnitTest.css   gR   ˶N      s   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/ClassDefinitionOpeningBraceSpaceUnitTest.css  gR        s   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.php  gR  Q      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/EmptyStyleDefinitionUnitTest.cssb   gRb   dԻ      s   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.php  gR  ^׶      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/DuplicateClassDefinitionUnitTest.css  gR  `9      _   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/NamedColoursUnitTest.css   gR   AO      _   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/NamedColoursUnitTest.php  gR  ⇛      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/DuplicateStyleDefinitionUnitTest.phpB  gRB        s   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/DisallowMultipleStyleDefinitionsUnitTest.cssD  gRD  Ζ      ^   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/IndentationUnitTest.css  gR  S      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/DuplicateClassDefinitionUnitTest.php\  gR\  sN	      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/LowercaseStyleDefinitionUnitTest.php  gR  )      Z   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/OpacityUnitTest.php  gR  MU      b   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.php  gR  yY      b   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/ForbiddenStylesUnitTest.css  gR  m      `   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.php  gR  HͶ      _   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/MissingColonUnitTest.css   gR   ×      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.phpY  gRY  ~      `   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/ShorthandSizeUnitTest.css	  gR	  _v      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/ClassDefinitionNameSpacingUnitTest.css|  gR|  @v      ^   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/IndentationUnitTest.php  gR  \޶      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/DuplicateStyleDefinitionUnitTest.css  gR        Z   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/OpacityUnitTest.css   gR   Uz      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/ClassDefinitionNameSpacingUnitTest.phpb  gRb  RM"      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/EmptyStyleDefinitionUnitTest.phpM  gRM  	      _   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/ColonSpacingUnitTest.php  gR  (Fɶ      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.phpA  gRA  bҶ      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/EmptyClassDefinitionUnitTest.php  gR  =      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/ColourDefinitionUnitTest.css   gR   Z      s   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/ClassDefinitionClosingBraceSpaceUnitTest.css  gR  Ҷ      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/CSS/SemicolonSpacingUnitTest.css6  gR6  c      l   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Functions/FunctionDeclarationUnitTest.php  gR  .@0      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Functions/GlobalFunctionUnitTest.inc
  gR
  ~4m      {   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.phpB	  gRB	  ffȶ      r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Functions/FunctionDuplicateArgumentUnitTest.php  gR  -PV      {   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Functions/FunctionDeclarationArgumentSpacingUnitTest.inc  gR  F(      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Functions/GlobalFunctionUnitTest.php  gR  l      r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Functions/FunctionDuplicateArgumentUnitTest.inc   gR   2      r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.inc   gR   L¶      u   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Functions/MultiLineFunctionDeclarationUnitTest.php  gR  Γ      r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Functions/LowercaseFunctionKeywordsUnitTest.php  gR  P      u   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Functions/MultiLineFunctionDeclarationUnitTest.inc  gR  z      l   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Functions/FunctionDeclarationUnitTest.inc  gR        u   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/ControlStructures/LowercaseDeclarationUnitTest.php  gR  K5      s   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.inci  gRi        q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.php  gR  DJԶ      r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.js  gR  fiS      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.js  gR  Z;      r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/ControlStructures/SwitchDeclarationUnitTest.inc  gR  M      t   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.php  gR  %Ƕ      t   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/ControlStructures/InlineIfDeclarationUnitTest.inc  gR  8      r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/ControlStructures/SwitchDeclarationUnitTest.php  gR  ڠ      s   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/ControlStructures/ForLoopDeclarationUnitTest.php
  gR
  jL϶      w   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.incJ  gRJ  (n      w   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/ControlStructures/ForEachLoopDeclarationUnitTest.php  gR  w      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/ControlStructures/SwitchDeclarationUnitTest.js;  gR;  Vƶ      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/ControlStructures/ControlSignatureUnitTest.incj  gRj  Ica      u   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/ControlStructures/LowercaseDeclarationUnitTest.inc   gR   B      r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/ControlStructures/ElseIfDeclarationUnitTest.inc   gR   Kk      r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/ControlStructures/ElseIfDeclarationUnitTest.php  gR  ;fc      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Operators/IncrementDecrementUsageUnitTest.phpr  gRr  ݣ      n   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.incx  gRx  {E "      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.php  gR  
      n   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.php  gR  @      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.jsK  gRK  ¶      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Operators/IncrementDecrementUsageUnitTest.inc  gR  Gm      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Operators/ComparisonOperatorUsageUnitTest.incj  gRj  .ƶ      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.js  gR  u/      j   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.inc  gR  	{      h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Objects/ObjectMemberCommaUnitTest.php8  gR8  I*      j   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.php  gR        p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Objects/DisallowObjectStringIndexUnitTest.phpz  gRz  4\4      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Objects/DisallowObjectStringIndexUnitTest.js  gR  v      n   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.php	  gR	  ж      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/ClassCommentUnitTest.inc2  gR2  ѳ      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/ClassCommentUnitTest.php  gR  >ж      n   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.inc   gR   ^      t   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.js  gR  d      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.php	  gR	  Ƕ      s   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.phpp  gRp  Ro¶      u   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.php  gR  d      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/FunctionCommentThrowTagUnitTest.incz  gRz  k      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/PostStatementCommentUnitTest.js  gR        e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.php	  gR	  w7      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.inc  gR  V      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/BlockCommentUnitTest.inc  gR  %      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc$  gR$  ޚM      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.php  gR  9R      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.php  gR   Z      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/EmptyCatchCommentUnitTest.php  gR  5a      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.js  gR  I      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/VariableCommentUnitTest.inc  gR  M8Ͷ      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/EmptyCatchCommentUnitTest.inca  gRa  >W      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.php  gR  Z9      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/DocCommentAlignmentUnitTest.incx  gRx  ~A      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/FunctionCommentThrowTagUnitTest.php  gR  譩      s   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/ClosingDeclarationCommentUnitTest.inc  gR  A      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/InlineCommentUnitTest.inc  gR  1NC      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/FileCommentUnitTest.js  gR  JUr      u   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/LongConditionClosingCommentUnitTest.inc.  gR.  ٶ      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Commenting/BlockCommentUnitTest.php  gR  0ڶ      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Files/FileExtensionUnitTest.4.inc   gR   ԡ0      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Files/FileExtensionUnitTest.1.inc"   gR"   Ȅ      b   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Files/FileExtensionUnitTest.phpy	  gRy	  P޶      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Files/FileExtensionUnitTest.3.inc"   gR"   z9      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Files/FileExtensionUnitTest.2.inc   gR   "r      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.php  gR  )N7      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.incs   gRs   Hf      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.inc  gR        g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Strings/DoubleQuoteUsageUnitTest.phpB  gRB  /q      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Strings/ConcatenationSpacingUnitTest.inc   gR   %Dd      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Strings/EchoedStringsUnitTest.php  gR  sM      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/ForbiddenFunctionsUnitTest.php  gR  _Ӏ      a   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/InnerFunctionsUnitTest.inc  gR  T      W   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/EvalUnitTest.incB   gRB   {7G      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/DisallowObEndFlushUnitTest.inc   gR   N      n   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/DisallowMultipleAssignmentsUnitTest.php-  gR-  x      n   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/DisallowMultipleAssignmentsUnitTest.inc  gR        Z   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/HeredocUnitTest.php  gR  .d      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/DisallowBooleanStatementUnitTest.php  gR  d[      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.phpQ
  gRQ
  !      Z   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/HeredocUnitTest.inc   gR         c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.incQ  gRQ  ?=      W   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/EvalUnitTest.php  gR  6      `   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/GlobalKeywordUnitTest.php  gR  <      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/ForbiddenFunctionsUnitTest.inc   gR   ?/      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.php	  gR	  T_      ^   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.php  gR  ~ +      a   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/InnerFunctionsUnitTest.php  gR  UH      n   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.js   gR   oZO      h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.incY  gRY  
;      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/DisallowObEndFlushUnitTest.php  gR  swc      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.inc_   gR_   ݨ*      h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/LowercasePHPFunctionsUnitTest.php  gR  ,N      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.php
  gR
  Qe      b   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/DisallowInlineIfUnitTest.js.   gR.   {3d      ^   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/EmbeddedPhpUnitTest.inc  gR  g      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/DisallowSizeFunctionsInLoopsUnitTest.inc  gR  P4~      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.css  gR  OA      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/CommentedOutCodeUnitTest.phpw	  gRw	  έ      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/DisallowComparisonAssignmentUnitTest.php0  gR0  D?6      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/DisallowComparisonAssignmentUnitTest.inc  gR  >ʎ      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/DiscouragedFunctionsUnitTest.inc-   gR-   w       `   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/GlobalKeywordUnitTest.inc   gR   g      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/DisallowBooleanStatementUnitTest.inca  gRa  /ֶ      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/NonExecutableCodeUnitTest.inc;  gR;  63Ex      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/PHP/DiscouragedFunctionsUnitTest.phpN  gRN  =      h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.js  gR  Z'      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.php  gR  6      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Formatting/OperatorBracketUnitTest.inc  gR  g       h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Classes/DuplicatePropertyUnitTest.phpd  gRd  Scw      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Classes/LowercaseClassKeywordsUnitTest.php  gR  	W      j   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.inc  gR  xj      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Classes/ClassFileNameUnitTest.php   gR   hY      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Classes/ValidClassNameUnitTest.inc  gR        g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Classes/DuplicatePropertyUnitTest.js  gR  ]A,      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Classes/ClassFileNameUnitTest.inc  gR        g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Classes/ClassDeclarationUnitTest.phpl
  gRl
        e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Classes/ValidClassNameUnitTest.php#  gR#  y      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Classes/ClassDeclarationUnitTest.inc  gR  {q      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Classes/LowercaseClassKeywordsUnitTest.inc   gR   5x      j   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Tests/Classes/SelfMemberReferenceUnitTest.php  gR  -(ɶ      H   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/ruleset.xml
  gR
        M   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/AbstractScopeSniff.php_  gR_  Ƒ      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/NamingConventions/ValidFunctionNameSniff.php)  gR)  3R      l   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/NamingConventions/ValidClassNameSniff.php  gR  ϗS      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/NamingConventions/ValidVariableNameSniff.php!  gR!  R      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/WhiteSpace/ObjectOperatorIndentSniff.phpU  gRU        h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php  gR        b   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/WhiteSpace/ScopeIndentSniff.php  gR        g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Functions/ValidDefaultValueSniff.phpo  gRo  h^      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Functions/FunctionDeclarationSniff.php3  gR3  {Lv      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Functions/FunctionCallSignatureSniff.php75  gR75  t04d      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/ControlStructures/MultiLineConditionSniff.php  gR  'Xˡ      n   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/ControlStructures/ControlSignatureSniff.php  gR  6      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Commenting/InlineCommentSniff.php  gR        f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Commenting/FunctionCommentSniff.phpI  gRI  Ar      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Commenting/ClassCommentSniff.php#  gR#  ^[      b   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Commenting/FileCommentSniff.phpz  gRz  x1y      _   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Files/IncludingFileSniff.php?  gR?  D}      j   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Formatting/MultiLineAssignmentSniff.php~  gR~  ,߶      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Classes/ClassDeclarationSniff.php  gR  tߕ      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Docs/NamingConventions/ValidVariableNameStandard.xml  gR  w      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Docs/NamingConventions/ValidFunctionNameStandard.xml&  gR&  ol餶      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Docs/NamingConventions/ValidClassNameStandard.xml  gR  E      l   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Docs/WhiteSpace/ObjectOperatorIndentStandard.xml  gR  R      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Docs/WhiteSpace/ScopeClosingBraceStandard.xmlA  gRA  ¶      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Docs/WhiteSpace/ScopeIndentStandard.xml  gR  T      h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Docs/Functions/ValidDefaultValueStandard.xml{  gR{  %(      j   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Docs/Functions/FunctionDeclarationStandard.xml  gR  
U      l   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Docs/Functions/FunctionCallSignatureStandard.xml  gR  -0      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Docs/ControlStructures/ControlSignatureStandard.xml  gR  jp_ö      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Docs/ControlStructures/MultiLineConditionStandard.xml  gR  AYֶ      c   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Docs/Commenting/FileCommentStandard.xml|  gR|  F      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Docs/Commenting/InlineCommentStandard.xml  gR  n4w      g   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Docs/Commenting/FunctionCommentStandard.xml  gR        d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Docs/Commenting/ClassCommentStandard.xml  gR  LP1      `   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Docs/Files/IncludingFileStandard.xml6  gR6  YZ>      ]   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Docs/Files/LineLengthStandard.xml   gR   FAs      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Docs/Formatting/MultiLineAssignmentStandard.xml~  gR~  K/      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Docs/Classes/ClassDeclarationStandard.xml	  gR	  Q      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/NamingConventions/ValidVariableNameUnitTest.php  gR  {      n   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/NamingConventions/ValidClassNameUnitTest.inc  gR  %5̶      n   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/NamingConventions/ValidClassNameUnitTest.php  gR  am      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/NamingConventions/ValidVariableNameUnitTest.inc  gR  ya      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/NamingConventions/ValidFunctionNameUnitTest.inc  gR  ]y      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/NamingConventions/ValidFunctionNameUnitTest.php  gR  8
      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.php  gR  u      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/WhiteSpace/ObjectOperatorIndentUnitTest.inc  gR  oe      j   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.phpG  gRG  ҩ      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/WhiteSpace/ScopeIndentUnitTest.inc  gR  !?*      j   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/WhiteSpace/ScopeClosingBraceUnitTest.inc^  gR^  ,iL      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/WhiteSpace/ScopeIndentUnitTest.php  gR  쫦s      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/Functions/FunctionDeclarationUnitTest.php$	  gR$	  d\      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/Functions/ValidDefaultValueUnitTest.php  gR  }      i   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/Functions/ValidDefaultValueUnitTest.incD  gRD  ?ﷶ      k   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/Functions/FunctionDeclarationUnitTest.inc  gR  =rQ      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.inc  gR  I:      m   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/Functions/FunctionCallSignatureUnitTest.php.
  gR.
  Lc      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/ControlStructures/ControlSignatureUnitTest.php	  gR	  $      r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.phpC	  gRC	  2c      r   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/ControlStructures/MultiLineConditionUnitTest.inc  gR        p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/ControlStructures/ControlSignatureUnitTest.inc  gR  BU      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/Commenting/ClassCommentUnitTest.inc_  gR_  ;      e   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/Commenting/ClassCommentUnitTest.phpJ	  gRJ	  vyٶ      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.php
  gR
  ^O      d   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/Commenting/FileCommentUnitTest.inc/  gR/  B      h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc  gR  
      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/Commenting/InlineCommentUnitTest.php  gR  [1      h   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.phpy	  gRy	  Z~      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/Commenting/InlineCommentUnitTest.incS  gRS        a   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/Files/IncludingFileUnitTest.incJ  gRJ  S1      a   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/Files/IncludingFileUnitTest.php  gR  5'Z      l   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/Formatting/MultiLineAssignmentUnitTest.phpi  gRi  {do      l   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/Formatting/MultiLineAssignmentUnitTest.inc  gR  +zӶ      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.php(  gR(  U      f   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Tests/Classes/ClassDeclarationUnitTest.incw  gRw  zǶ      G   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/ruleset.xml  gR  e      ^   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Zend/Sniffs/Debug/CodeAnalyzerSniff.php2  gR2  VC      o   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Zend/Sniffs/NamingConventions/ValidVariableNameSniff.php/)  gR/)   ,      \   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Zend/Sniffs/Files/ClosingTagSniff.php	  gR	  r人      _   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Zend/Docs/Debug/CodeAnalyzerStandard.xml  gR  A8      p   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Zend/Docs/NamingConventions/ValidVariableNameStandard.xml  gR  |	      ]   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Zend/Docs/Files/ClosingTagStandard.xml  gR  9۶      `   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Zend/Tests/Debug/CodeAnalyzerUnitTest.php  gR  phD      `   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Zend/Tests/Debug/CodeAnalyzerUnitTest.incW   gRW   ;       q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Zend/Tests/NamingConventions/ValidVariableNameUnitTest.php~  gR~  aP9      q   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Zend/Tests/NamingConventions/ValidVariableNameUnitTest.incu  gRu  Hv      ^   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Zend/Tests/Files/ClosingTagUnitTest.inc/   gR/         ^   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Zend/Tests/Files/ClosingTagUnitTest.php~  gR~  #̍$      G   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/Zend/ruleset.xml  gR  eA      T   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/IncorrectPatternException.phpj  gRj  L      P   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/AbstractVariableSniff.phpQ  gRQ  Q      H   vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PHPCS/ruleset.xml  gR  40޶      ,   vendor/squizlabs/php_codesniffer/licence.txt  gR  K      6   vendor/squizlabs/php_codesniffer/CodeSniffer.conf.dist   gR   w	ֶ      M   vendor/symfony/property-access/Symfony/Component/PropertyAccess/composer.jsonf  gRf  Rڤ      T   vendor/symfony/property-access/Symfony/Component/PropertyAccess/PropertyAccessor.phpG  gRG  U;      P   vendor/symfony/property-access/Symfony/Component/PropertyAccess/PropertyPath.php  gR  ¾Ӷ      G   vendor/symfony/property-access/Symfony/Component/PropertyAccess/LICENSE)  gR)  NmQ      X   vendor/symfony/property-access/Symfony/Component/PropertyAccess/PropertyPathIterator.php  gR  2[      N   vendor/symfony/property-access/Symfony/Component/PropertyAccess/StringUtil.php  gR  A      [   vendor/symfony/property-access/Symfony/Component/PropertyAccess/PropertyAccessorBuilder.phpc	  gRc	  I1f      Y   vendor/symfony/property-access/Symfony/Component/PropertyAccess/PropertyPathInterface.php	  gR	  p.      ]   vendor/symfony/property-access/Symfony/Component/PropertyAccess/PropertyAccessorInterface.php  gR  m      R   vendor/symfony/property-access/Symfony/Component/PropertyAccess/PropertyAccess.php  gR        W   vendor/symfony/property-access/Symfony/Component/PropertyAccess/PropertyPathBuilder.php$'  gR$'  \      b   vendor/symfony/property-access/Symfony/Component/PropertyAccess/Exception/OutOfBoundsException.php  gR  sC&      ^   vendor/symfony/property-access/Symfony/Component/PropertyAccess/Exception/RuntimeException.php  gR  m>C      ]   vendor/symfony/property-access/Symfony/Component/PropertyAccess/Exception/AccessException.php  gR  @Q      j   vendor/symfony/property-access/Symfony/Component/PropertyAccess/Exception/InvalidPropertyPathException.php  gR  -d      `   vendor/symfony/property-access/Symfony/Component/PropertyAccess/Exception/ExceptionInterface.php  gR  (z       e   vendor/symfony/property-access/Symfony/Component/PropertyAccess/Exception/NoSuchPropertyException.php  gR        b   vendor/symfony/property-access/Symfony/Component/PropertyAccess/Exception/NoSuchIndexException.php  gR  D'      e   vendor/symfony/property-access/Symfony/Component/PropertyAccess/Exception/UnexpectedTypeException.php  gR  <޶      a   vendor/symfony/property-access/Symfony/Component/PropertyAccess/PropertyPathIteratorInterface.php  gR  (      D   vendor/symfony/filesystem/Symfony/Component/Filesystem/composer.json  gR  9	      E   vendor/symfony/filesystem/Symfony/Component/Filesystem/Filesystem.php	F  gR	F  :A      >   vendor/symfony/filesystem/Symfony/Component/Filesystem/LICENSE)  gR)  NmQ      G   vendor/symfony/filesystem/Symfony/Component/Filesystem/phpunit.xml.dist	  gR	  Ejc      P   vendor/symfony/filesystem/Symfony/Component/Filesystem/Exception/IOException.php  gR  ;{      Z   vendor/symfony/filesystem/Symfony/Component/Filesystem/Exception/FileNotFoundException.php  gR  dP      Y   vendor/symfony/filesystem/Symfony/Component/Filesystem/Exception/IOExceptionInterface.php  gR  oC~      W   vendor/symfony/filesystem/Symfony/Component/Filesystem/Exception/ExceptionInterface.php  gR  3{      N   vendor/symfony/filesystem/Symfony/Component/Filesystem/Tests/ExceptionTest.php  gR  i̶      S   vendor/symfony/filesystem/Symfony/Component/Filesystem/Tests/FilesystemTestCase.php  gR  ;      O   vendor/symfony/filesystem/Symfony/Component/Filesystem/Tests/FilesystemTest.phpk  gRk  w`
      X   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Definition.php89  gR89  c!      \   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/ScopeInterface.php  gR  _J      w   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Extension/ConfigurationExtensionInterface.php  gR  J      j   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Extension/ExtensionInterface.php  gR  DSض      q   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Extension/PrependExtensionInterface.phpM  gRM  Co      a   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Extension/Extension.php  gR  o      W   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/composer.jsonC  gRC  2$Z      f   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/TaggedContainerInterface.php  gR        _   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php:$  gR:$  A      ^   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php+  gR+  "1HŶ      d   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Dumper/DumperInterface.php  gR  }      [   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Dumper/Dumper.php+  gR+  N/      ^   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php*  gR*        c   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php%  gR%        Q   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/LICENSE)  gR)  NmQ      V   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Variable.php7  gR7  $      a   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/DefinitionDecorator.phpP  gRP  U穌      r   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.phpq	  gRq	  @      c   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/RepeatedPass.php#  gR#  0є      y   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.phpF  gRF  L׶      t   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/RemoveAbstractDefinitionsPass.php'  gR'  U*      r   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.php
  gR
  iZ         vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php6  gR6  b[_      a   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/PassConfig.php  gR  C\Z      u   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php  gR  ϒ      n   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/RepeatablePassInterface.php  gR  EŶ      s   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php  gR  .k      r   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.phpd  gRd        p   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphEdge.php  gR  x7۶      s   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php  gR  iJT      q   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.php  gR         v   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php\  gR\  X      l   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/CompilerPassInterface.php  gR  _9      w   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.phpn  gRn        s   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php  gR  ۻǶ      p   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphNode.php	  gR	  [׶      g   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/LoggingFormatter.php  gR        l   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraph.php)  gR)  V%      o   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/RemovePrivateAliasesPass.php  gR  !?      u   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.phpP  gRP        _   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Compiler/Compiler.phpt
  gRt
  {       a   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/ContainerAwareTrait.php  gR  H8      W   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Container.phpB  gRB  #x      `   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/ExpressionLanguage.php  gR  ;Yޯ      ^   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/ContainerBuilder.phpÂ  gRÂ  K      `   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/ContainerInterface.php  gR  E?      \   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/ContainerAware.phpi  gRi  u      Z   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/phpunit.xml.distu  gRu        _   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Loader/FileLoader.php-  gR-  Ua      u   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd  gR  @h!      b   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Loader/ClosureLoader.php  gR  
      b   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Loader/IniFileLoader.php  gR  ӸBj      b   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php(  gR(        b   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php7  gR7  n>>o      c   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php+  gR+  ƶ      S   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Alias.php  gR  l5      z   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/InstantiatorInterface.phpJ  gRJ  ܶ      |   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/LazyProxy/Instantiator/RealServiceInstantiator.phpn  gRn  iض      l   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/NullDumper.php  gR  ҳ      q   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php  gR  z>l      ^   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/SimpleXMLElement.phpI  gRI  %      W   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Reference.php,  gR,  -R]      W   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Parameter.php  gR  F"      p   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/ParameterBag/ParameterBagInterface.php	  gR	  ܮP8      g   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php"   gR"   U      m   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/ParameterBag/FrozenParameterBag.php   gR   ך      l   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/OutOfBoundsException.php  gR  {      p   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/InvalidArgumentException.php  gR         h   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/RuntimeException.php  gR  
+      p   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/ServiceNotFoundException.php  gR        f   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/LogicException.php  gR  l.      j   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/ExceptionInterface.php  gR  9      n   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/InactiveScopeException.php  gR  I_      {   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/ParameterCircularReferenceException.php  gR  qB      n   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/BadMethodCallException.php  gR  
O,      w   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/ScopeCrossingInjectionException.php  gR  = Զ      y   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/ServiceCircularReferenceException.php  gR  ]      w   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/ScopeWideningInjectionException.php  gR  z      r   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Exception/ParameterNotFoundException.php
  gR
  \      n   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/IntrospectableContainerInterface.phpB  gRB  Bt      e   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/ContainerAwareInterface.php  gR  q8I      k   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Extension/ExtensionTest.php	  gR	  `=      b   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/CrossCheckTest.php  gR        h   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php."  gR."  "ö      i   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php	  gR	  2+`      m   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Dumper/GraphvizDumperTest.php  gR  v      h   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php  gR  )׶      h   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.phpg  gRg  iƬ      a   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/ReferenceTest.php  gR        |   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/RemoveUnusedDefinitionsPassTest.php
  gR
  I         vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/ReplaceAliasByActualDefinitionPassTest.php@  gR@  }1H      }   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/AnalyzeServiceReferencesPassTest.php`  gR`  ~         vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveReferencesToAliasesPassTest.php?  gR?  
T^         vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php  gR  ]껶      |   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckCircularReferencesPassTest.php{  gR{  '      |   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckDefinitionValidityPassTest.php  gR  @w         vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckExceptionOnInvalidReferenceBehaviorPassTest.php  gR  @|޶      }   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInvalidReferencesPassTest.php	  gR	  '      {   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/CheckReferenceValidityPassTest.php  gR  >"      }   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.phpn  gRn  5      l   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php  gR  O      s   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container11.php3  gR3        s   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container14.php   gR   1v      s   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/interfaces2.php  gR  Fm      s   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container12.phpE  gRE  *      s   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container10.php;  gR;  Cݲ      s   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container13.phpO  gRO  Bre      s   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/interfaces1.php  gR  |      r   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.phpC  gRC  %2z      r   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container8.php  gR  4h      s   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php  gR  LR؉      g   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/simple.php/   gR/   ɶ      j   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php  gR  oTb      l   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php)  gR)  E      j   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php  gR  7/      k   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php  gR  G3G@      k   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services11.phpy  gRy  $o      j   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.phpE  gRE  nb      l   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters1.ini%   gR%   5l      l   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters2.ini(   gR(   pu      i   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/nonvalid.ini+   gR+   ۴)      k   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/ini/parameters.ini'   gR'   s4ж      k   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services3.ymlD   gRD   |      l   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services11.yml   gR   MuA      k   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services1.yml   gR   2      k   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml  gR  6e3      i   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag2.yml   gR   }>      k   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4.yml  gR  !9      k   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.ymlX  gRX  $q      k   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services7.yml'   gR'         k   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/nonvalid1.yml   gR   #&#      k   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services2.yml   gR   :Ʋ      i   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag1.ymln   gRn   zb      k   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/nonvalid2.yml   gR   W%      l   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services10.yml   gR   %/      k   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services8.yml   gR         l   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services13.ymlG   gRG         i   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/badtag3.yml   gR   *_6      v   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4_bad_import.yml?   gR?   y      t   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extension2/services.xml  gR  ]2
      j   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services3.xml  gR  \_      i   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/nonvalid.xml%   gR%   ˕n      u   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services3.xml  gR  >U      u   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services4.xml   gR   җ'y      u   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services2.xml  gR  }      u   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services5.xml  gR  Ń      u   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services7.xml  gR  	      u   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services6.xml  gR  ixC      u   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extensions/services1.xml  gR  ^      j   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4.xml  gR  u      j   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services2.xml  gR  	      u   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services4_bad_import.xmlg  gRg  P      j   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services5.xml  gR  ibĶ      l   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/withdoctype.xml1   gR1   x'	      j   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services7.xmlW  gRW  _+      k   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services13.xmli  gRi  <      j   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xml  gR  pԠ      j   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services1.xml  gR  (]      j   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml  gR        t   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/extension1/services.xml  gR  ʶ      j   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services8.xmlh  gRh  wz      r   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services10-1.dot,  gR,  Ձ1*      o   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot	  gR	  h	      p   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services10.dot3  gR3        p   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services14.dotB  gRB  8      o   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services1.dotW  gRW  &      p   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services13.dot;  gR;  ŏD      v   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectExtension.php  gR  .Y<Ҷ      p   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/createphar.php  gR  ]ζ      x   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/schema/project-1.0.xsd  gR  RK:      m   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.phpZ  gRZ  Aov:         vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectWithXsdExtensionInPhar.pharr  gRr  N{      i   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/foo.php  gR  
      }   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/ProjectWithXsdExtension.php[  gR[        m   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.phpd0  gRd0  t(/      l   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php  gR  SR      l   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Loader/ClosureLoaderTest.php`  gR`  ł      l   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.phpE]  gRE]  .      l   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Loader/IniFileLoaderTest.php
  gR
        k   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/DefinitionDecoratorTest.php  gR  +E         vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/LazyProxy/Instantiator/RealServiceInstantiatorTest.php  gR  I8i      v   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/NullDumperTest.php9  gR9  ~O      b   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php5  gR5  e      q   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.php9  gR9  $      w   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/ParameterBag/FrozenParameterBagTest.php  gR  
^      a   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/ContainerTest.phpV  gRV  3a      a   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/ParameterTest.php  gR  [      S   vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Scope.phpm  gRm  ,x      8   vendor/symfony/yaml/Symfony/Component/Yaml/composer.json  gR  @-      8   vendor/symfony/yaml/Symfony/Component/Yaml/Unescaper.php  gR  h      5   vendor/symfony/yaml/Symfony/Component/Yaml/Parser.phpY\  gRY\  S?y      2   vendor/symfony/yaml/Symfony/Component/Yaml/LICENSE)  gR)  NmQ      3   vendor/symfony/yaml/Symfony/Component/Yaml/Yaml.php  gR  7MӺ      6   vendor/symfony/yaml/Symfony/Component/Yaml/Escaper.phpj  gRj  k(=      ;   vendor/symfony/yaml/Symfony/Component/Yaml/phpunit.xml.dist3  gR3  >[      5   vendor/symfony/yaml/Symfony/Component/Yaml/Inline.php=  gR=  >j      I   vendor/symfony/yaml/Symfony/Component/Yaml/Exception/RuntimeException.php  gR  |-      K   vendor/symfony/yaml/Symfony/Component/Yaml/Exception/ExceptionInterface.php  gR  +l      G   vendor/symfony/yaml/Symfony/Component/Yaml/Exception/ParseException.php  gR        F   vendor/symfony/yaml/Symfony/Component/Yaml/Exception/DumpException.php  gR  ؙ՚      5   vendor/symfony/yaml/Symfony/Component/Yaml/Dumper.php	  gR	  8n      ?   vendor/symfony/yaml/Symfony/Component/Yaml/Tests/ParserTest.phpw2  gRw2  LZʶ      =   vendor/symfony/yaml/Symfony/Component/Yaml/Tests/YamlTest.phpe  gRe  `@      O   vendor/symfony/yaml/Symfony/Component/Yaml/Tests/Fixtures/escapedCharacters.yml  gR  *¶      G   vendor/symfony/yaml/Symfony/Component/Yaml/Tests/Fixtures/sfCompact.ymlU  gRU        N   vendor/symfony/yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsTypeTransfers.yml  gR  $R      K   vendor/symfony/yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsBasicTests.yml  gR  ֋O      H   vendor/symfony/yaml/Symfony/Component/Yaml/Tests/Fixtures/embededPhp.yml   gR   Zܶ      H   vendor/symfony/yaml/Symfony/Component/Yaml/Tests/Fixtures/sfMergeKey.ymlJ  gRJ  ;:Q      P   vendor/symfony/yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsFlowCollections.ymlX  gRX  Z{k      N   vendor/symfony/yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsFoldedScalars.ymlz  gRz  ګغ      V   vendor/symfony/yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml1  gR1  ܷU      R   vendor/symfony/yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsDocumentSeparator.yml  gR  %MC      G   vendor/symfony/yaml/Symfony/Component/Yaml/Tests/Fixtures/sfObjects.yml  gR  <ö      E   vendor/symfony/yaml/Symfony/Component/Yaml/Tests/Fixtures/sfTests.yml  gR  U      H   vendor/symfony/yaml/Symfony/Component/Yaml/Tests/Fixtures/sfComments.ymlU  gRU  @      S   vendor/symfony/yaml/Symfony/Component/Yaml/Tests/Fixtures/unindentedCollections.yml-  gR-  Ç¶      C   vendor/symfony/yaml/Symfony/Component/Yaml/Tests/Fixtures/index.yml8  gR8        L   vendor/symfony/yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsAnchorAlias.yml[  gR[  5R      F   vendor/symfony/yaml/Symfony/Component/Yaml/Tests/Fixtures/sfQuotes.yml  gR  섶      P   vendor/symfony/yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsNullsAndEmpties.yml  gR  >;      M   vendor/symfony/yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsBlockMapping.yml  gR        K   vendor/symfony/yaml/Symfony/Component/Yaml/Tests/Fixtures/YtsErrorTests.ymlq  gRq  tr      G   vendor/symfony/yaml/Symfony/Component/Yaml/Tests/ParseExceptionTest.php  gR  ?o      ?   vendor/symfony/yaml/Symfony/Component/Yaml/Tests/InlineTest.php[%  gR[%  =ao      ?   vendor/symfony/yaml/Symfony/Component/Yaml/Tests/DumperTest.php  gR  @e˶      ^   vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventSubscriberInterface.php1  gR1  cG      O   vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/composer.json  gR  l      m   vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php  gR  
      I   vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/LICENSE)  gR)  NmQ      ^   vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventDispatcherInterface.php  gR  UҶ      ^   vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/ImmutableEventDispatcher.php  gR  s      U   vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/EventDispatcher.php  gR  Y"      R   vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/phpunit.xml.distq  gRq  M      K   vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Event.php  gR  bk      c   vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php  gR  Nm      R   vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/GenericEvent.phpD  gRD  ,      \   vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Tests/GenericEventTest.php  gR  \2      U   vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Tests/EventTest.php  gR  nu      h   vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Tests/ImmutableEventDispatcherTest.php  gR  +̶      m   vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Tests/ContainerAwareEventDispatcherTest.php  gR  'm      _   vendor/symfony/event-dispatcher/Symfony/Component/EventDispatcher/Tests/EventDispatcherTest.phpp/  gRp/  o       <   vendor/symfony/config/Symfony/Component/Config/composer.json  gR  ˴Ѷ      6   vendor/symfony/config/Symfony/Component/Config/LICENSE)  gR)  NmQ      @   vendor/symfony/config/Symfony/Component/Config/Util/XmlUtils.php,  gR,  [f      H   vendor/symfony/config/Symfony/Component/Config/Resource/FileResource.php!  gR!  T      M   vendor/symfony/config/Symfony/Component/Config/Resource/DirectoryResource.php
  gR
  #      M   vendor/symfony/config/Symfony/Component/Config/Resource/ResourceInterface.phpD  gRD  fKE      ?   vendor/symfony/config/Symfony/Component/Config/phpunit.xml.disth  gRh  Y      >   vendor/symfony/config/Symfony/Component/Config/ConfigCache.php
  gR
  }Kж      I   vendor/symfony/config/Symfony/Component/Config/Loader/LoaderInterface.php9  gR9  4      Q   vendor/symfony/config/Symfony/Component/Config/Loader/LoaderResolverInterface.php  gR  ¶      D   vendor/symfony/config/Symfony/Component/Config/Loader/FileLoader.php8  gR8  (      @   vendor/symfony/config/Symfony/Component/Config/Loader/Loader.php  gR  =      J   vendor/symfony/config/Symfony/Component/Config/Loader/DelegatingLoader.php8  gR8  ;v7%      H   vendor/symfony/config/Symfony/Component/Config/Loader/LoaderResolver.php  gR  HPʶ      G   vendor/symfony/config/Symfony/Component/Config/FileLocatorInterface.phpl  gRl  C3k      T   vendor/symfony/config/Symfony/Component/Config/Exception/FileLoaderLoadException.php	  gR	  W      g   vendor/symfony/config/Symfony/Component/Config/Exception/FileLoaderImportCircularReferenceException.phpT  gRT  7      >   vendor/symfony/config/Symfony/Component/Config/FileLocator.php   gR   I      G   vendor/symfony/config/Symfony/Component/Config/Definition/Processor.php'  gR'  U      T   vendor/symfony/config/Symfony/Component/Config/Definition/PrototypeNodeInterface.phpw  gRw  e      I   vendor/symfony/config/Symfony/Component/Config/Definition/IntegerNode.phpk  gRk  j      I   vendor/symfony/config/Symfony/Component/Config/Definition/BooleanNode.php  gR        X   vendor/symfony/config/Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.phpZ  gRZ  05      W   vendor/symfony/config/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php&  gR&  2      X   vendor/symfony/config/Symfony/Component/Config/Definition/Builder/EnumNodeDefinition.php  gR  ~      [   vendor/symfony/config/Symfony/Component/Config/Definition/Builder/BooleanNodeDefinition.php  gR  P      T   vendor/symfony/config/Symfony/Component/Config/Definition/Builder/NodeDefinition.php  gR  K      Q   vendor/symfony/config/Symfony/Component/Config/Definition/Builder/NodeBuilder.php  gR   }      Y   vendor/symfony/config/Symfony/Component/Config/Definition/Builder/FloatNodeDefinition.php  gR  tp      Y   vendor/symfony/config/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php8  gR8  /      [   vendor/symfony/config/Symfony/Component/Config/Definition/Builder/IntegerNodeDefinition.php  gR  'nڭ      Z   vendor/symfony/config/Symfony/Component/Config/Definition/Builder/NormalizationBuilder.php4  gR4  #֕      R   vendor/symfony/config/Symfony/Component/Config/Definition/Builder/MergeBuilder.php{  gR{        Q   vendor/symfony/config/Symfony/Component/Config/Definition/Builder/ExprBuilder.php  gR        Y   vendor/symfony/config/Symfony/Component/Config/Definition/Builder/NodeParentInterface.php  gR  U=      \   vendor/symfony/config/Symfony/Component/Config/Definition/Builder/VariableNodeDefinition.php  gR  e@      Z   vendor/symfony/config/Symfony/Component/Config/Definition/Builder/ScalarNodeDefinition.php  gR  mc      [   vendor/symfony/config/Symfony/Component/Config/Definition/Builder/NumericNodeDefinition.phpX  gRX  ~G      c   vendor/symfony/config/Symfony/Component/Config/Definition/Builder/ParentNodeDefinitionInterface.php_  gR_  3d      W   vendor/symfony/config/Symfony/Component/Config/Definition/Builder/ValidationBuilder.php[  gR[  ,l      Q   vendor/symfony/config/Symfony/Component/Config/Definition/Builder/TreeBuilder.php  gR  VhU      F   vendor/symfony/config/Symfony/Component/Config/Definition/BaseNode.php"  gR"  B      G   vendor/symfony/config/Symfony/Component/Config/Definition/FloatNode.php  gR  m+      H   vendor/symfony/config/Symfony/Component/Config/Definition/ScalarNode.phpq  gRq  X      Q   vendor/symfony/config/Symfony/Component/Config/Definition/PrototypedArrayNode.php#'  gR#'  Un=      J   vendor/symfony/config/Symfony/Component/Config/Definition/VariableNode.php	  gR	  $¶      T   vendor/symfony/config/Symfony/Component/Config/Definition/ConfigurationInterface.phpd  gRd  *      K   vendor/symfony/config/Symfony/Component/Config/Definition/NodeInterface.php  gR  fJ      F   vendor/symfony/config/Symfony/Component/Config/Definition/EnumNode.php@  gR@  =      M   vendor/symfony/config/Symfony/Component/Config/Definition/ReferenceDumper.php0  gR0  0۶      I   vendor/symfony/config/Symfony/Component/Config/Definition/NumericNode.php-  gR-  -*ҹ      Q   vendor/symfony/config/Symfony/Component/Config/Definition/Exception/Exception.php  gR  Cж      ]   vendor/symfony/config/Symfony/Component/Config/Definition/Exception/DuplicateKeyException.phpE  gRE  |      \   vendor/symfony/config/Symfony/Component/Config/Definition/Exception/InvalidTypeException.php  gR  @      b   vendor/symfony/config/Symfony/Component/Config/Definition/Exception/InvalidDefinitionException.php  gR  ]F4      Y   vendor/symfony/config/Symfony/Component/Config/Definition/Exception/UnsetKeyException.php  gR        c   vendor/symfony/config/Symfony/Component/Config/Definition/Exception/ForbiddenOverwriteException.phpQ  gRQ  :2&      e   vendor/symfony/config/Symfony/Component/Config/Definition/Exception/InvalidConfigurationException.php  gR  5-      G   vendor/symfony/config/Symfony/Component/Config/Definition/ArrayNode.php*  gR*  ɶ      H   vendor/symfony/config/Symfony/Component/Config/Tests/ConfigCacheTest.phpY  gRY  Aw      K   vendor/symfony/config/Symfony/Component/Config/Tests/Fixtures/Again/foo.xml    gR              [   vendor/symfony/config/Symfony/Component/Config/Tests/Fixtures/Builder/BarNodeDefinition.php  gR  r_      U   vendor/symfony/config/Symfony/Component/Config/Tests/Fixtures/Builder/NodeBuilder.phps  gRs  u;      `   vendor/symfony/config/Symfony/Component/Config/Tests/Fixtures/Builder/VariableNodeDefinition.php  gR  @      T   vendor/symfony/config/Symfony/Component/Config/Tests/Fixtures/Util/document_type.xml   gR   c=      N   vendor/symfony/config/Symfony/Component/Config/Tests/Fixtures/Util/invalid.xml.   gR.   b      M   vendor/symfony/config/Symfony/Component/Config/Tests/Fixtures/Util/schema.xsd  gR  &Ƕ      L   vendor/symfony/config/Symfony/Component/Config/Tests/Fixtures/Util/valid.xmlX   gRX   \      U   vendor/symfony/config/Symfony/Component/Config/Tests/Fixtures/Util/invalid_schema.xmlS   gRS   Gɩ      E   vendor/symfony/config/Symfony/Component/Config/Tests/Fixtures/foo.xml    gR              d   vendor/symfony/config/Symfony/Component/Config/Tests/Fixtures/Configuration/ExampleConfiguration.php
  gR
        J   vendor/symfony/config/Symfony/Component/Config/Tests/Util/XmlUtilsTest.php  gR  xȖ;      W   vendor/symfony/config/Symfony/Component/Config/Tests/Resource/DirectoryResourceTest.php  gR  ȶ      R   vendor/symfony/config/Symfony/Component/Config/Tests/Resource/FileResourceTest.php  gR   D-      T   vendor/symfony/config/Symfony/Component/Config/Tests/Loader/DelegatingLoaderTest.php  gR  oq*,      R   vendor/symfony/config/Symfony/Component/Config/Tests/Loader/LoaderResolverTest.php  gR  Y      J   vendor/symfony/config/Symfony/Component/Config/Tests/Loader/LoaderTest.php@  gR@  5bcö      N   vendor/symfony/config/Symfony/Component/Config/Tests/Loader/FileLoaderTest.php  gR  2׶      H   vendor/symfony/config/Symfony/Component/Config/Tests/FileLocatorTest.phpC  gRC  KO      Q   vendor/symfony/config/Symfony/Component/Config/Tests/Definition/FloatNodeTest.php  gR  &]Ķ      a   vendor/symfony/config/Symfony/Component/Config/Tests/Definition/Dumper/XmlReferenceDumperTest.php  gR  ~P+      b   vendor/symfony/config/Symfony/Component/Config/Tests/Definition/Dumper/YamlReferenceDumperTest.php  gR  y      [   vendor/symfony/config/Symfony/Component/Config/Tests/Definition/Builder/NodeBuilderTest.php
  gR
  x(      e   vendor/symfony/config/Symfony/Component/Config/Tests/Definition/Builder/NumericNodeDefinitionTest.phpj  gRj  Ej~      c   vendor/symfony/config/Symfony/Component/Config/Tests/Definition/Builder/ArrayNodeDefinitionTest.php  gR  wX      b   vendor/symfony/config/Symfony/Component/Config/Tests/Definition/Builder/EnumNodeDefinitionTest.php  gR  <C      [   vendor/symfony/config/Symfony/Component/Config/Tests/Definition/Builder/TreeBuilderTest.php  gR        [   vendor/symfony/config/Symfony/Component/Config/Tests/Definition/Builder/ExprBuilderTest.php  gR  c,8̶      P   vendor/symfony/config/Symfony/Component/Config/Tests/Definition/EnumNodeTest.php  gR  iH      U   vendor/symfony/config/Symfony/Component/Config/Tests/Definition/NormalizationTest.php  gR  3      M   vendor/symfony/config/Symfony/Component/Config/Tests/Definition/MergeTest.php9  gR9  D      S   vendor/symfony/config/Symfony/Component/Config/Tests/Definition/IntegerNodeTest.php  gR        T   vendor/symfony/config/Symfony/Component/Config/Tests/Definition/FinalizationTest.phpR  gRR  A      [   vendor/symfony/config/Symfony/Component/Config/Tests/Definition/PrototypedArrayNodeTest.php  gR  %Jbx      S   vendor/symfony/config/Symfony/Component/Config/Tests/Definition/BooleanNodeTest.php  gR  {      R   vendor/symfony/config/Symfony/Component/Config/Tests/Definition/ScalarNodeTest.php  gR  jO灶      Q   vendor/symfony/config/Symfony/Component/Config/Tests/Definition/ArrayNodeTest.php:	  gR:	  ݼ      F   vendor/symfony/translation/Symfony/Component/Translation/composer.json  gR  >      L   vendor/symfony/translation/Symfony/Component/Translation/MessageSelector.phpN  gRN  <q      O   vendor/symfony/translation/Symfony/Component/Translation/IdentityTranslator.php<  gR<  d      Q   vendor/symfony/translation/Symfony/Component/Translation/Dumper/IniFileDumper.php  gR  &X      N   vendor/symfony/translation/Symfony/Component/Translation/Dumper/FileDumper.php[  gR[  B^      P   vendor/symfony/translation/Symfony/Component/Translation/Dumper/QtFileDumper.phpG  gRG  >{      T   vendor/symfony/translation/Symfony/Component/Translation/Dumper/IcuResFileDumper.php  gR  M
      S   vendor/symfony/translation/Symfony/Component/Translation/Dumper/XliffFileDumper.php  gR  <̧      Q   vendor/symfony/translation/Symfony/Component/Translation/Dumper/CsvFileDumper.php  gR  oBͶ      P   vendor/symfony/translation/Symfony/Component/Translation/Dumper/PoFileDumper.php  gR  ਪ(      Q   vendor/symfony/translation/Symfony/Component/Translation/Dumper/PhpFileDumper.phpL  gRL  !0      R   vendor/symfony/translation/Symfony/Component/Translation/Dumper/JsonFileDumper.php}  gR}  :$      S   vendor/symfony/translation/Symfony/Component/Translation/Dumper/DumperInterface.php*  gR*  <      P   vendor/symfony/translation/Symfony/Component/Translation/Dumper/MoFileDumper.phpA	  gRA	  ׶      R   vendor/symfony/translation/Symfony/Component/Translation/Dumper/YamlFileDumper.php6  gR6        @   vendor/symfony/translation/Symfony/Component/Translation/LICENSE)  gR)  NmQ      T   vendor/symfony/translation/Symfony/Component/Translation/Catalogue/DiffOperation.php  gR  Ӷ      X   vendor/symfony/translation/Symfony/Component/Translation/Catalogue/AbstractOperation.php  gR  fb      Y   vendor/symfony/translation/Symfony/Component/Translation/Catalogue/OperationInterface.php  gR  Y[      U   vendor/symfony/translation/Symfony/Component/Translation/Catalogue/MergeOperation.php  gR  س      S   vendor/symfony/translation/Symfony/Component/Translation/MetadataAwareInterface.php  gR  %Mt      G   vendor/symfony/translation/Symfony/Component/Translation/Translator.php  gR  eG      E   vendor/symfony/translation/Symfony/Component/Translation/Interval.php
  gR
  g?Z      O   vendor/symfony/translation/Symfony/Component/Translation/PluralizationRules.phpo  gRo  b*0      P   vendor/symfony/translation/Symfony/Component/Translation/TranslatorInterface.php  gR  3ݶ      I   vendor/symfony/translation/Symfony/Component/Translation/phpunit.xml.dist:  gR:  ^C	      U   vendor/symfony/translation/Symfony/Component/Translation/Extractor/ChainExtractor.php  gR        Y   vendor/symfony/translation/Symfony/Component/Translation/Extractor/ExtractorInterface.php  gR  ArP      S   vendor/symfony/translation/Symfony/Component/Translation/Loader/XliffFileLoader.phpA  gRA  8t      S   vendor/symfony/translation/Symfony/Component/Translation/Loader/LoaderInterface.phpt  gRt  l#      T   vendor/symfony/translation/Symfony/Component/Translation/Loader/IcuDatFileLoader.php  gR  Tö      ]   vendor/symfony/translation/Symfony/Component/Translation/Loader/schema/dic/xliff-core/xml.xsd"  gR"  :	Z      o   vendor/symfony/translation/Symfony/Component/Translation/Loader/schema/dic/xliff-core/xliff-core-1.2-strict.xsd gR xO      T   vendor/symfony/translation/Symfony/Component/Translation/Loader/IcuResFileLoader.phpz
  gRz
  CS      Q   vendor/symfony/translation/Symfony/Component/Translation/Loader/IniFileLoader.php  gR  N@      Q   vendor/symfony/translation/Symfony/Component/Translation/Loader/PhpFileLoader.php;  gR;  r      R   vendor/symfony/translation/Symfony/Component/Translation/Loader/JsonFileLoader.phpu	  gRu	  's¶      P   vendor/symfony/translation/Symfony/Component/Translation/Loader/MoFileLoader.php  gR  v      Q   vendor/symfony/translation/Symfony/Component/Translation/Loader/CsvFileLoader.php"
  gR"
  i3      O   vendor/symfony/translation/Symfony/Component/Translation/Loader/ArrayLoader.php  gR  R      P   vendor/symfony/translation/Symfony/Component/Translation/Loader/QtFileLoader.php  gR  r;(      R   vendor/symfony/translation/Symfony/Component/Translation/Loader/YamlFileLoader.php  gR  :޶      P   vendor/symfony/translation/Symfony/Component/Translation/Loader/PoFileLoader.php  gR  ʶ      `   vendor/symfony/translation/Symfony/Component/Translation/Exception/NotFoundResourceException.php  gR  2B      Y   vendor/symfony/translation/Symfony/Component/Translation/Exception/ExceptionInterface.php  gR  6"      _   vendor/symfony/translation/Symfony/Component/Translation/Exception/InvalidResourceException.php  gR  Ǆ      M   vendor/symfony/translation/Symfony/Component/Translation/MessageCatalogue.php  gR  y4      U   vendor/symfony/translation/Symfony/Component/Translation/Writer/TranslationWriter.php}  gR}  P?      O   vendor/symfony/translation/Symfony/Component/Translation/Tests/IntervalTest.php  gR  02      [   vendor/symfony/translation/Symfony/Component/Translation/Tests/Dumper/IniFileDumperTest.php  gR  V      ]   vendor/symfony/translation/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php  gR  `׶      \   vendor/symfony/translation/Symfony/Component/Translation/Tests/Dumper/YamlFileDumperTest.php  gR        Z   vendor/symfony/translation/Symfony/Component/Translation/Tests/Dumper/PoFileDumperTest.php  gR  &ݶ      Z   vendor/symfony/translation/Symfony/Component/Translation/Tests/Dumper/QtFileDumperTest.php  gR  BY      Z   vendor/symfony/translation/Symfony/Component/Translation/Tests/Dumper/MoFileDumperTest.php  gR        ^   vendor/symfony/translation/Symfony/Component/Translation/Tests/Dumper/IcuResFileDumperTest.php  gR  ub/      [   vendor/symfony/translation/Symfony/Component/Translation/Tests/Dumper/CsvFileDumperTest.php  gR  ׶      \   vendor/symfony/translation/Symfony/Component/Translation/Tests/Dumper/JsonFileDumperTest.phpI  gRI        [   vendor/symfony/translation/Symfony/Component/Translation/Tests/Dumper/PhpFileDumperTest.php  gR        ^   vendor/symfony/translation/Symfony/Component/Translation/Tests/Catalogue/DiffOperationTest.php  gR  D^      b   vendor/symfony/translation/Symfony/Component/Translation/Tests/Catalogue/AbstractOperationTest.php(  gR(  H7n9      _   vendor/symfony/translation/Symfony/Component/Translation/Tests/Catalogue/MergeOperationTest.php  gR  ވ߶      P   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/empty.mo    gR              T   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/resources.mo4   gR4   W      V   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/malformed.json   gR   ߞ      Q   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/empty.csv    gR              R   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/empty.json    gR              U   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/non-valid.yml   gR   e2~      U   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/resources.xlfz  gRz  .      \   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/empty-translation.po   gR   =Bs      W   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/withdoctype.xlfj  gRj        T   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/resources.ts   gR   C(      V   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/resources.json   gR         Q   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/empty.yml    gR              S   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/resname.xlf4  gR4  Yݶ      Q   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/empty.ini    gR              n   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/corrupted/resources.dat   gR   <      a   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/en.txt'   gR'   25ֶ      a   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/fr.res|   gR|   w˦(      a   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/fr.txt*   gR*   X      a   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/en.resx   gRx   MR      j   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/packagelist.txt   gR   g.      h   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/dat/resources.dat`  gR`  rQ槶      a   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/resourcebundle/res/en.resT   gRT   +L      a   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/invalid-xml-resources.xlf  gR  /
      U   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/resources.php+   gR+   :Ŷ      T   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/encoding.xlf  gR  ̉^2      R   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/plurals.moJ   gRJ   *֔      R   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/plurals.poB   gRB   ;.      T   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/resources.po   gR   !f      [   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/resources-clean.xlf  gR  YڸC      U   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/resources.csv`   gR`   D      Q   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/valid.csv$   gR$   B      P   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/empty.po    gR              U   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/resources.ini
   gR
   'F      U   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/resources.yml	   gR	         U   vendor/symfony/translation/Symfony/Component/Translation/Tests/fixtures/non-valid.xlfT  gRT         \   vendor/symfony/translation/Symfony/Component/Translation/Tests/Loader/YamlFileLoaderTest.php	  gR	  ~      [   vendor/symfony/translation/Symfony/Component/Translation/Tests/Loader/LocalizedTestCase.php  gR  3      ^   vendor/symfony/translation/Symfony/Component/Translation/Tests/Loader/IcuResFileLoaderTest.php  gR  j      [   vendor/symfony/translation/Symfony/Component/Translation/Tests/Loader/CsvFileLoaderTest.php  gR  [      Z   vendor/symfony/translation/Symfony/Component/Translation/Tests/Loader/MoFileLoaderTest.php  gR        [   vendor/symfony/translation/Symfony/Component/Translation/Tests/Loader/PhpFileLoaderTest.php  gR        Z   vendor/symfony/translation/Symfony/Component/Translation/Tests/Loader/QtFileLoaderTest.phpG  gRG  ܮ1      ]   vendor/symfony/translation/Symfony/Component/Translation/Tests/Loader/XliffFileLoaderTest.php-  gR-  5ȭ^      ^   vendor/symfony/translation/Symfony/Component/Translation/Tests/Loader/IcuDatFileLoaderTest.php	  gR	  )	      Z   vendor/symfony/translation/Symfony/Component/Translation/Tests/Loader/PoFileLoaderTest.php
  gR
  $X      \   vendor/symfony/translation/Symfony/Component/Translation/Tests/Loader/JsonFileLoaderTest.php  gR  Pe      [   vendor/symfony/translation/Symfony/Component/Translation/Tests/Loader/IniFileLoaderTest.php  gR  /ݶ      Y   vendor/symfony/translation/Symfony/Component/Translation/Tests/IdentityTranslatorTest.phpU  gRU  h9=      Y   vendor/symfony/translation/Symfony/Component/Translation/Tests/PluralizationRulesTest.php  gR  l.!      Q   vendor/symfony/translation/Symfony/Component/Translation/Tests/TranslatorTest.php|1  gR|1  *      W   vendor/symfony/translation/Symfony/Component/Translation/Tests/MessageCatalogueTest.php  gR  M϶      V   vendor/symfony/translation/Symfony/Component/Translation/Tests/MessageSelectorTest.php   gR         V   vendor/symfony/translation/Symfony/Component/Translation/MessageCatalogueInterface.php  gR  ֶ      <   vendor/symfony/finder/Symfony/Component/Finder/composer.json  gR  V:׶      H   vendor/symfony/finder/Symfony/Component/Finder/Comparator/Comparator.php
  gR
  |Fz      N   vendor/symfony/finder/Symfony/Component/Finder/Comparator/NumberComparator.php
  gR
  P      L   vendor/symfony/finder/Symfony/Component/Finder/Comparator/DateComparator.php  gR         9   vendor/symfony/finder/Symfony/Component/Finder/Finder.phpV  gRV        6   vendor/symfony/finder/Symfony/Component/Finder/LICENSE)  gR)  NmQ      >   vendor/symfony/finder/Symfony/Component/Finder/SplFileInfo.php  gR  59      ?   vendor/symfony/finder/Symfony/Component/Finder/phpunit.xml.dist5  gR5        7   vendor/symfony/finder/Symfony/Component/Finder/Glob.phpb  gRb  g@M      >   vendor/symfony/finder/Symfony/Component/Finder/Shell/Shell.php  gR  2      @   vendor/symfony/finder/Symfony/Component/Finder/Shell/Command.php  gR  p      Y   vendor/symfony/finder/Symfony/Component/Finder/Exception/ShellCommandFailureException.php9  gR9        Z   vendor/symfony/finder/Symfony/Component/Finder/Exception/OperationNotPermitedException.php  gR  P      R   vendor/symfony/finder/Symfony/Component/Finder/Exception/AccessDeniedException.php  gR  cW޶      O   vendor/symfony/finder/Symfony/Component/Finder/Exception/ExceptionInterface.php  gR  7      T   vendor/symfony/finder/Symfony/Component/Finder/Exception/AdapterFailureException.php  gR  >@      C   vendor/symfony/finder/Symfony/Component/Finder/Expression/Regex.php  gR  [ǐ      B   vendor/symfony/finder/Symfony/Component/Finder/Expression/Glob.php  gR  E      L   vendor/symfony/finder/Symfony/Component/Finder/Expression/ValueInterface.phpH  gRH  "      H   vendor/symfony/finder/Symfony/Component/Finder/Expression/Expression.php&
  gR&
  뇶      P   vendor/symfony/finder/Symfony/Component/Finder/Iterator/CustomFilterIterator.php  gR  z"      N   vendor/symfony/finder/Symfony/Component/Finder/Iterator/PathFilterIterator.php  gR  )      U   vendor/symfony/finder/Symfony/Component/Finder/Iterator/FilecontentFilterIterator.php  gR  ʽ      J   vendor/symfony/finder/Symfony/Component/Finder/Iterator/FilterIterator.php  gR  ,G      R   vendor/symfony/finder/Symfony/Component/Finder/Iterator/FilenameFilterIterator.php  gR  {^Ƕ      S   vendor/symfony/finder/Symfony/Component/Finder/Iterator/DateRangeFilterIterator.php  gR   U      V   vendor/symfony/finder/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php  gR  6s      M   vendor/symfony/finder/Symfony/Component/Finder/Iterator/FilePathsIterator.php
  gR
  ɔ      Z   vendor/symfony/finder/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php  gR  d      V   vendor/symfony/finder/Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.php  gR  

      L   vendor/symfony/finder/Symfony/Component/Finder/Iterator/SortableIterator.php	  gR	  j      T   vendor/symfony/finder/Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.php  gR  ils_      R   vendor/symfony/finder/Symfony/Component/Finder/Iterator/FileTypeFilterIterator.phpb  gRb  n       S   vendor/symfony/finder/Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.php  gR  xP      R   vendor/symfony/finder/Symfony/Component/Finder/Tests/Comparator/ComparatorTest.php  gR  Ŷ      V   vendor/symfony/finder/Symfony/Component/Finder/Tests/Comparator/DateComparatorTest.php	  gR	  ˟׶      X   vendor/symfony/finder/Symfony/Component/Finder/Tests/Comparator/NumberComparatorTest.php/  gR/  W.      Q   vendor/symfony/finder/Symfony/Component/Finder/Tests/FakeAdapter/NamedAdapter.php  gR  `2      W   vendor/symfony/finder/Symfony/Component/Finder/Tests/FakeAdapter/UnsupportedAdapter.php0  gR0  /      Q   vendor/symfony/finder/Symfony/Component/Finder/Tests/FakeAdapter/DummyAdapter.php  gR  I޶      S   vendor/symfony/finder/Symfony/Component/Finder/Tests/FakeAdapter/FailingAdapter.phpm  gRm        G   vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/lorem.txt5   gR5         G   vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/dolor.txt   gR   o5|      C   vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/one/a    gR              J   vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/one/b/d.neon    gR              J   vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/one/b/c.neon    gR              P   vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/with space/foo.txt    gR              H   vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/A/B/ab.dat    gR              K   vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/A/B/C/abc.dat    gR              E   vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/A/a.dat    gR              U   vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/copy/A/B/C/abc.dat.copy    gR              R   vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/copy/A/B/ab.dat.copy    gR              O   vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/copy/A/a.dat.copy    gR              G   vendor/symfony/finder/Symfony/Component/Finder/Tests/Fixtures/ipsum.txt)   gR)   '      C   vendor/symfony/finder/Symfony/Component/Finder/Tests/FinderTest.phpw  gRw  ꖾ      R   vendor/symfony/finder/Symfony/Component/Finder/Tests/Expression/ExpressionTest.php  gR        M   vendor/symfony/finder/Symfony/Component/Finder/Tests/Expression/RegexTest.php  gR         L   vendor/symfony/finder/Symfony/Component/Finder/Tests/Expression/GlobTest.phpi  gRi  "F      \   vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FileTypeFilterIteratorTest.phpM  gRM  Ybk      \   vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FilenameFilterIteratorTest.php  gR  7      ^   vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/DepthRangeFilterIteratorTest.php)  gR)  Zo*      ]   vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/DateRangeFilterIteratorTest.php=  gR=  (g      W   vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FilePathsIteratorTest.php
  gR
  :@      X   vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/PathFilterIteratorTest.php  gR  nI      `   vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/MultiplePcreFilterIteratorTest.php+  gR+  캶      V   vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/RealIteratorTestCase.php4  gR4  +드      ]   vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/SizeRangeFilterIteratorTest.php   gR   F      V   vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/MockFileListIterator.php&  gR&  u8      Z   vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/CustomFilterIteratorTest.php  gR  ߫Ӷ      d   vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/ExcludeDirectoryFilterIteratorTest.phpa  gRa  4/      V   vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.phpa	  gRa	  7W      J   vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/Iterator.php  gR  S䞶      Q   vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/MockSplFileInfo.php  gR  o      _   vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FilecontentFilterIteratorTest.php  gR  ٶ      `   vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/RecursiveDirectoryIteratorTest.php  gR  Ŷ      R   vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/IteratorTestCase.phpo	  gRo	  {)\      T   vendor/symfony/finder/Symfony/Component/Finder/Tests/Iterator/FilterIteratorTest.php6  gR6  -ڶ      E   vendor/symfony/finder/Symfony/Component/Finder/Adapter/PhpAdapter.php{
  gR{
  9!2      I   vendor/symfony/finder/Symfony/Component/Finder/Adapter/GnuFindAdapter.php
  gR
  }]      I   vendor/symfony/finder/Symfony/Component/Finder/Adapter/BsdFindAdapter.php
  gR
  kA      K   vendor/symfony/finder/Symfony/Component/Finder/Adapter/AdapterInterface.php  gR        J   vendor/symfony/finder/Symfony/Component/Finder/Adapter/AbstractAdapter.php  gR  	      N   vendor/symfony/finder/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php)  gR)  QJ      B   vendor/symfony/stopwatch/Symfony/Component/Stopwatch/composer.json  gR  Ј      <   vendor/symfony/stopwatch/Symfony/Component/Stopwatch/LICENSE)  gR)  NmQ      B   vendor/symfony/stopwatch/Symfony/Component/Stopwatch/Stopwatch.php  gR  ʒA      G   vendor/symfony/stopwatch/Symfony/Component/Stopwatch/StopwatchEvent.phpA  gRA        H   vendor/symfony/stopwatch/Symfony/Component/Stopwatch/StopwatchPeriod.php  gR  f      W   vendor/symfony/validator/Symfony/Component/Validator/GroupSequenceProviderInterface.phpU  gRU  S      \   vendor/symfony/validator/Symfony/Component/Validator/ConstraintValidatorFactoryInterface.php4  gR4  %      B   vendor/symfony/validator/Symfony/Component/Validator/composer.jsons  gRs  _϶      R   vendor/symfony/validator/Symfony/Component/Validator/ExecutionContextInterface.phpC0  gRC0        ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.lt.xlf3  gR3  B.w      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.mn.xlf#"  gR#"  D      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.no.xlf1  gR1  kCM      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.ca.xlf58  gR58   O      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.es.xlfq8  gRq8  VKN      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.ru.xlfYM  gRYM  mP      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.lb.xlf(7  gR(7  J`      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.sv.xlf!1  gR!1  a       ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.pl.xlfB  gRB  mw      b   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.sr_Latn.xlf4  gR4  1^      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.fa.xlfG  gRG         ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.he.xlf5  gR5  tö      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.eu.xlf?  gR?  18h      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.ro.xlfA  gRA  Zq`      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.sl.xlfC  gRC  n      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.it.xlf :  gR :  =^      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.uk.xlf|K  gR|K  p	      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.fr.xlfB  gRB  +      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.pt.xlf@  gR@  NB      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.hr.xlf7  gR7  Iᇶ      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.en.xlf?  gR?  D#      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.gl.xlf=A  gR=A  (      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.id.xlfY1  gRY1  >:h      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.da.xlf5  gR5  9>      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.hy.xlfw,  gRw,  v_      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.fi.xlf2  gR2  a      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.af.xlf4  gR4  @T\      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.cy.xlf1  gR1  PH      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.bg.xlf:  gR:  e϶      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.ar.xlfF  gRF  (U      b   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.sr_Cyrl.xlfA  gRA  e]߶      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.nb.xlfe  gRe  (⊶      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.el.xlfM  gRM        ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.nl.xlf@  gR@  ~u      `   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.pt_BR.xlf8  gR8  z      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.ja.xlfA  gRA        ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.de.xlfA  gRA  sE#      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.sq.xlf5  gR5  Y.3      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.cs.xlfB  gRB  
nֶ      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.hu.xlfoA  gRoA  93Xa      `   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.zh_CN.xlf/  gR/  Fwն      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.tr.xlfN1  gRN1        ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.sk.xlfuC  gRuC  -      ]   vendor/symfony/validator/Symfony/Component/Validator/Resources/translations/validators.et.xlf=  gR=  %N      <   vendor/symfony/validator/Symfony/Component/Validator/LICENSE)  gR)  NmQ      K   vendor/symfony/validator/Symfony/Component/Validator/ValidatorInterface.php)  gR)  5˶      U   vendor/symfony/validator/Symfony/Component/Validator/ConstraintViolationInterface.php  gR  R'      X   vendor/symfony/validator/Symfony/Component/Validator/Constraints/NotEqualToValidator.phpU  gRU  {      X   vendor/symfony/validator/Symfony/Component/Validator/Constraints/ExpressionValidator.php	  gR	  zet      Q   vendor/symfony/validator/Symfony/Component/Validator/Constraints/UrlValidator.phpE  gRE  >N      J   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Image.php  gR  _      S   vendor/symfony/validator/Symfony/Component/Validator/Constraints/FalseValidator.php  gR  ^T      M   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Optional.php  gR  rs+      I   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Issn.phpB  gRB  dXƶ      R   vendor/symfony/validator/Symfony/Component/Validator/Constraints/GroupSequence.phpv  gRv        S   vendor/symfony/validator/Symfony/Component/Validator/Constraints/RegexValidator.php  gR  <W      V   vendor/symfony/validator/Symfony/Component/Validator/Constraints/CallbackValidator.php	  gR	        R   vendor/symfony/validator/Symfony/Component/Validator/Constraints/NullValidator.php  gR  -      R   vendor/symfony/validator/Symfony/Component/Validator/Constraints/TypeValidator.php  gR  F      M   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Required.php  gR  tU׶      `   vendor/symfony/validator/Symfony/Component/Validator/Constraints/GreaterThanOrEqualValidator.phpw  gRw  (.      M   vendor/symfony/validator/Symfony/Component/Validator/Constraints/NotBlank.php  gR  U      K   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Length.php&  gR&  }      Z   vendor/symfony/validator/Symfony/Component/Validator/Constraints/GroupSequenceProvider.php  gR  ଶ      S   vendor/symfony/validator/Symfony/Component/Validator/Constraints/NotIdenticalTo.php  gR  e핶      I   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Date.php  gR  S탟      O   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Collection.phpW  gRW  H      R   vendor/symfony/validator/Symfony/Component/Validator/Constraints/LuhnValidator.php  gR  b+      J   vendor/symfony/validator/Symfony/Component/Validator/Constraints/False.php  gR  I7U      M   vendor/symfony/validator/Symfony/Component/Validator/Constraints/LessThan.php  gR  NHݶ      M   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Callback.phps  gRs  x.`      K   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Locale.php  gR  Hð      S   vendor/symfony/validator/Symfony/Component/Validator/Constraints/CountValidator.phpH  gRH  !x      L   vendor/symfony/validator/Symfony/Component/Validator/Constraints/NotNull.php  gR  w      S   vendor/symfony/validator/Symfony/Component/Validator/Constraints/ImageValidator.php  gR  <8S      Y   vendor/symfony/validator/Symfony/Component/Validator/Constraints/GreaterThanValidator.phpb  gRb  v      R   vendor/symfony/validator/Symfony/Component/Validator/Constraints/IssnValidator.php4  gR4        X   vendor/symfony/validator/Symfony/Component/Validator/Constraints/CollectionValidator.php  gR  6u      I   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Isbn.php,  gR,  ж      T   vendor/symfony/validator/Symfony/Component/Validator/Constraints/LocaleValidator.php  gR  `v      I   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Luhn.php  gR  &      V   vendor/symfony/validator/Symfony/Component/Validator/Constraints/LanguageValidator.php  gR  Qݶ      R   vendor/symfony/validator/Symfony/Component/Validator/Constraints/IbanValidator.php  gR  q      T   vendor/symfony/validator/Symfony/Component/Validator/Constraints/ChoiceValidator.php  gR  aHβ      H   vendor/symfony/validator/Symfony/Component/Validator/Constraints/All.php  gR        P   vendor/symfony/validator/Symfony/Component/Validator/Constraints/GreaterThan.php  gR  }a      J   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Count.php  gR  '      J   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Blank.php  gR  l      I   vendor/symfony/validator/Symfony/Component/Validator/Constraints/File.php"  gR"  qp      J   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Email.phpH  gRH  {      R   vendor/symfony/validator/Symfony/Component/Validator/Constraints/FileValidator.phpq  gRq  @v      X   vendor/symfony/validator/Symfony/Component/Validator/Constraints/CardSchemeValidator.php  gR  "      K   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Choice.phpS  gRS  D ~      S   vendor/symfony/validator/Symfony/Component/Validator/Constraints/BlankValidator.php  gR  y      P   vendor/symfony/validator/Symfony/Component/Validator/Constraints/IpValidator.php
  gR
  l˘      P   vendor/symfony/validator/Symfony/Component/Validator/Constraints/IdenticalTo.php  gR  '㔘      ]   vendor/symfony/validator/Symfony/Component/Validator/Constraints/LessThanOrEqualValidator.phpq  gRq  O      V   vendor/symfony/validator/Symfony/Component/Validator/Constraints/CurrencyValidator.php  gR  Z      J   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Regex.php	  gR	         W   vendor/symfony/validator/Symfony/Component/Validator/Constraints/AbstractComparison.phpF  gRF  뱶      H   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Url.php0  gR0  	Ƕ      U   vendor/symfony/validator/Symfony/Component/Validator/Constraints/EqualToValidator.phpL  gRL  CG^      I   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Type.php  gR  N3      U   vendor/symfony/validator/Symfony/Component/Validator/Constraints/NotNullValidator.php  gR  D      I   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Null.php  gR  Sn      `   vendor/symfony/validator/Symfony/Component/Validator/Constraints/AbstractComparisonValidator.php  gR  ^Ӷ      S   vendor/symfony/validator/Symfony/Component/Validator/Constraints/RangeValidator.php  gR  oo      U   vendor/symfony/validator/Symfony/Component/Validator/Constraints/CountryValidator.php  gR  EW^      I   vendor/symfony/validator/Symfony/Component/Validator/Constraints/True.php  gR  ٜ?      R   vendor/symfony/validator/Symfony/Component/Validator/Constraints/TimeValidator.php  gR  (      I   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Time.php  gR  7      T   vendor/symfony/validator/Symfony/Component/Validator/Constraints/LessThanOrEqual.php  gR  [A      L   vendor/symfony/validator/Symfony/Component/Validator/Constraints/EqualTo.php  gR  Ǧ      O   vendor/symfony/validator/Symfony/Component/Validator/Constraints/NotEqualTo.php  gR  +      V   vendor/symfony/validator/Symfony/Component/Validator/Constraints/NotBlankValidator.php  gR  &      M   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Currency.php
  gR
  ᤶ      \   vendor/symfony/validator/Symfony/Component/Validator/Constraints/NotIdenticalToValidator.php\  gR\  mԼ      R   vendor/symfony/validator/Symfony/Component/Validator/Constraints/DateValidator.php  gR  5ʟ      W   vendor/symfony/validator/Symfony/Component/Validator/Constraints/GreaterThanOrEqual.php  gR  Qヶ      L   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Country.php  gR  q;O      N   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Existence.php/  gR/  >
i      G   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Ip.php  gR  c      I   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Iban.php  gR  +      S   vendor/symfony/validator/Symfony/Component/Validator/Constraints/EmailValidator.php  gR  5      O   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Expression.phpK  gRK  Ŀ:      Y   vendor/symfony/validator/Symfony/Component/Validator/Constraints/IdenticalToValidator.phpV  gRV  ̢      O   vendor/symfony/validator/Symfony/Component/Validator/Constraints/CardScheme.php  gR  Lֶ      R   vendor/symfony/validator/Symfony/Component/Validator/Constraints/IsbnValidator.phpn  gRn  b=      J   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Range.phpB  gRB        R   vendor/symfony/validator/Symfony/Component/Validator/Constraints/TrueValidator.php5  gR5  ɑ      M   vendor/symfony/validator/Symfony/Component/Validator/Constraints/DateTime.php
  gR
  cy      X   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Collection/Optional.phpz  gRz  خ      X   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Collection/Required.phpz  gRz  \,y      Q   vendor/symfony/validator/Symfony/Component/Validator/Constraints/AllValidator.php  gR  Fn      V   vendor/symfony/validator/Symfony/Component/Validator/Constraints/DateTimeValidator.php  gR        V   vendor/symfony/validator/Symfony/Component/Validator/Constraints/LessThanValidator.php\  gR\        T   vendor/symfony/validator/Symfony/Component/Validator/Constraints/LengthValidator.php  gR  F;      J   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Valid.php  gR  ~%ɶ      M   vendor/symfony/validator/Symfony/Component/Validator/Constraints/Language.php
  gR
  ^r      R   vendor/symfony/validator/Symfony/Component/Validator/PropertyMetadataInterface.php  gR  }`煶      Y   vendor/symfony/validator/Symfony/Component/Validator/ConstraintViolationListInterface.php  gR  @V      Q   vendor/symfony/validator/Symfony/Component/Validator/Mapping/PropertyMetadata.php  gR  r      O   vendor/symfony/validator/Symfony/Component/Validator/Mapping/Cache/ApcCache.php  gR        U   vendor/symfony/validator/Symfony/Component/Validator/Mapping/Cache/CacheInterface.php%  gR%  +d      O   vendor/symfony/validator/Symfony/Component/Validator/Mapping/MemberMetadata.phpa  gRa  /;      Y   vendor/symfony/validator/Symfony/Component/Validator/Mapping/BlackholeMetadataFactory.php  gR  ۔      P   vendor/symfony/validator/Symfony/Component/Validator/Mapping/ElementMetadata.php"	  gR"	  !      N   vendor/symfony/validator/Symfony/Component/Validator/Mapping/ClassMetadata.php./  gR./  tڶ      W   vendor/symfony/validator/Symfony/Component/Validator/Mapping/Loader/LoaderInterface.php?  gR?  >      S   vendor/symfony/validator/Symfony/Component/Validator/Mapping/Loader/FilesLoader.php  gR  *      R   vendor/symfony/validator/Symfony/Component/Validator/Mapping/Loader/FileLoader.php  gR  ʚ      S   vendor/symfony/validator/Symfony/Component/Validator/Mapping/Loader/LoaderChain.php  gR        V   vendor/symfony/validator/Symfony/Component/Validator/Mapping/Loader/XmlFilesLoader.php  gR  Rᠯ      |   vendor/symfony/validator/Symfony/Component/Validator/Mapping/Loader/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd-  gR-  TOö      Z   vendor/symfony/validator/Symfony/Component/Validator/Mapping/Loader/StaticMethodLoader.php  gR  Tb      U   vendor/symfony/validator/Symfony/Component/Validator/Mapping/Loader/XmlFileLoader.php(  gR(  K)      V   vendor/symfony/validator/Symfony/Component/Validator/Mapping/Loader/AbstractLoader.php  gR  S`      X   vendor/symfony/validator/Symfony/Component/Validator/Mapping/Loader/AnnotationLoader.phpQ  gRQ  	lw#      V   vendor/symfony/validator/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.phpk  gRk  'p      W   vendor/symfony/validator/Symfony/Component/Validator/Mapping/Loader/YamlFilesLoader.php  gR  ?      U   vendor/symfony/validator/Symfony/Component/Validator/Mapping/ClassMetadataFactory.php  gR  d#[N      O   vendor/symfony/validator/Symfony/Component/Validator/Mapping/GetterMetadata.php  gR  |      C   vendor/symfony/validator/Symfony/Component/Validator/Constraint.php  gR  r߶      L   vendor/symfony/validator/Symfony/Component/Validator/ConstraintValidator.php  gR  Gk	      J   vendor/symfony/validator/Symfony/Component/Validator/MetadataInterface.phpK  gRK  Sq      R   vendor/symfony/validator/Symfony/Component/Validator/ValidatorBuilderInterface.php{  gR{  &      L   vendor/symfony/validator/Symfony/Component/Validator/ConstraintViolation.phpf  gRf  PX      E   vendor/symfony/validator/Symfony/Component/Validator/phpunit.xml.dist8  gR8  ,Q      P   vendor/symfony/validator/Symfony/Component/Validator/ConstraintViolationList.php  gR  ;5t      [   vendor/symfony/validator/Symfony/Component/Validator/PropertyMetadataContainerInterface.php  gR  bh      U   vendor/symfony/validator/Symfony/Component/Validator/ConstraintValidatorInterface.php  gR  ,'      I   vendor/symfony/validator/Symfony/Component/Validator/ExecutionContext.php/!  gR/!  ޽      S   vendor/symfony/validator/Symfony/Component/Validator/ObjectInitializerInterface.php1  gR1  z9      S   vendor/symfony/validator/Symfony/Component/Validator/ValidationVisitorInterface.php  gR  L8      J   vendor/symfony/validator/Symfony/Component/Validator/ValidationVisitor.php  gR  AbI̶      B   vendor/symfony/validator/Symfony/Component/Validator/Validator.php  gR  /ζ      J   vendor/symfony/validator/Symfony/Component/Validator/DefaultTranslator.php}  gR}  K      S   vendor/symfony/validator/Symfony/Component/Validator/Exception/MappingException.phpV  gRV  Q      [   vendor/symfony/validator/Symfony/Component/Validator/Exception/InvalidArgumentException.php  gR  \      S   vendor/symfony/validator/Symfony/Component/Validator/Exception/RuntimeException.php  gR  z      U   vendor/symfony/validator/Symfony/Component/Validator/Exception/ValidatorException.phpW  gRW  k1+      Z   vendor/symfony/validator/Symfony/Component/Validator/Exception/InvalidOptionsException.phpR  gRR  LЉ      Z   vendor/symfony/validator/Symfony/Component/Validator/Exception/NoSuchMetadataException.php  gR  x      Z   vendor/symfony/validator/Symfony/Component/Validator/Exception/MissingOptionsException.phpR  gRR  uն      [   vendor/symfony/validator/Symfony/Component/Validator/Exception/GroupDefinitionException.php^  gR^  M#      U   vendor/symfony/validator/Symfony/Component/Validator/Exception/ExceptionInterface.php  gR  T      Y   vendor/symfony/validator/Symfony/Component/Validator/Exception/BadMethodCallException.php  gR  yĶ      Z   vendor/symfony/validator/Symfony/Component/Validator/Exception/UnexpectedTypeException.php  gR  3      `   vendor/symfony/validator/Symfony/Component/Validator/Exception/ConstraintDefinitionException.phpc  gRc  1"      C   vendor/symfony/validator/Symfony/Component/Validator/Validation.phpJ  gRJ  xf첶      X   vendor/symfony/validator/Symfony/Component/Validator/GlobalExecutionContextInterface.php  gR  8Wc      b   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorTest.php+  gR+  \z?      ]   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/EmailValidatorTest.phpw
  gRw
  8      ]   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.php  gR  0h'      _   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/NotNullValidatorTest.php  gR  GRf      ]   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/BlankValidatorTest.phpw  gRw  ];X      ]   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CountValidatorTest.php  gR  ֆ      ^   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/ChoiceValidatorTest.php  gR  x      \   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/IssnValidatorTest.php3  gR3  -0cY      c   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.php.  gR.  $I      \   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/TimeValidatorTest.phpT  gRT   B      \   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LuhnValidatorTest.phpD  gRD  p)      b   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/FileValidatorObjectTest.php  gR  W      a   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/Fixtures/test_portrait.gif+   gR+   |      X   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/Fixtures/test.gif!  gR!  Ѝ      b   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/Fixtures/test_landscape.gif+   gR+   JĶ      `   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CurrencyValidatorTest.php  gR  A      \   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/TypeValidatorTest.php=  gR=  y7{      s   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorCustomArrayObjectTest.php  gR  rH      \   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/DateValidatorTest.phpH  gRH  @*V      ^   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LengthValidatorTest.php  gR  )mR      ]   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/FalseValidatorTest.phpK  gRK  i      `   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.phps(  gRs(  Q      ^   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LocaleValidatorTest.php
  gR
  Ͷ      \   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/NullValidatorTest.php  gR  ?τ      f   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CountValidatorCountableTest.php8  gR8  w      [   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.phpk  gRk  v      `   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/FileValidatorPathTest.phpk  gRk        m   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorArrayObjectTest.php  gR  |=      c   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.phpw  gRw  L      \   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/TrueValidatorTest.phpQ  gRQ  s{*p      \   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/IbanValidatorTest.php6   gR6   !      g   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.php  gR  Q      b   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.php,  gR,  ;      b   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CardSchemeValidatorTest.php  gR        \   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/FileValidatorTest.php(  gR(  2      R   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/AllTest.php  gR  BǶ      `   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/DateTimeValidatorTest.phpg  gRg  bڶ      f   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.php  gR  t      _   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CountryValidatorTest.php  gR  z0      `   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LanguageValidatorTest.php  gR  qC      j   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.php  gR  ׫      `   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.php6  gR6  qJf      ]   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.php  gR  Ͷ      \   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/IsbnValidatorTest.php  gR  {r>K      b   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.php  gR  WӶ      _   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.php  gR  29      g   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorArrayTest.php  gR  }mW      Z   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/IpValidatorTest.phpK1  gRK1        b   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CountValidatorArrayTest.php  gR  ϏR      Y   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/CollectionTest.php  gR  I      ]   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/RegexValidatorTest.phpD  gRD  Ā      `   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/NotBlankValidatorTest.php^
  gR^
  Zf      [   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/AllValidatorTest.php  gR        T   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/ValidTest.php  gR  (3      n   vendor/symfony/validator/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php  gR  3ê      \   vendor/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintAValidator.php  gR  ?>      N   vendor/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/Entity.php[  gR[  ߛ      S   vendor/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/FilesLoader.php  gR  j/      Y   vendor/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/FailingConstraint.php  gR  =2      U   vendor/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/CallbackClass.php  gR  Y/      c   vendor/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/GroupSequenceProviderEntity.php  gR  hҶ      d   vendor/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintWithValueAsDefault.php  gR  pTq      [   vendor/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/FakeMetadataFactory.php  gR  @w      b   vendor/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/InvalidConstraintValidator.phpI  gRI  X      [   vendor/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintWithValue.php  gR  5>      Z   vendor/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/PropertyConstraint.php  gR  G#i      Y   vendor/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/InvalidConstraint.php  gR  Cn      S   vendor/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintB.php  gR  5*      Q   vendor/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/Reference.php9  gR9  Ol      W   vendor/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/ClassConstraint.php  gR  ^t      S   vendor/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintA.php  gR  &      b   vendor/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/FailingConstraintValidator.phpg  gRg  pö      W   vendor/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/EntityInterface.phpC  gRC  a      S   vendor/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/ConstraintC.phpq  gRq  ]      T   vendor/symfony/validator/Symfony/Component/Validator/Tests/Fixtures/EntityParent.php8  gR8        c   vendor/symfony/validator/Symfony/Component/Validator/Tests/Mapping/BlackholeMetadataFactoryTest.phpe  gRe  os%      Y   vendor/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Cache/ApcCacheTest.php	  gR	  ",      X   vendor/symfony/validator/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php  gR  >      [   vendor/symfony/validator/Symfony/Component/Validator/Tests/Mapping/PropertyMetadataTest.php  gR  {d      `   vendor/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php  gR  N      d   vendor/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Loader/StaticMethodLoaderTest.php  gR  {%u      l   vendor/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping-non-strings.xml  gR  =      ]   vendor/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Loader/LoaderChainTest.php  gR  ug      `   vendor/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.yml  gR  -      h   vendor/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Loader/AbstractMethodStaticLoader.php   gR         _   vendor/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Loader/XmlFileLoaderTest.php  gR  Qi      b   vendor/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Loader/AnnotationLoaderTest.php  gR  m      ^   vendor/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Loader/nonvalid-mapping.yml   gR   e2~      `   vendor/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.xml  gR  Dk      [   vendor/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Loader/empty-mapping.yml    gR              ]   vendor/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Loader/FilesLoaderTest.php<  gR<  F      Y   vendor/symfony/validator/Symfony/Component/Validator/Tests/Mapping/Loader/withdoctype.xml  gR  N;      Y   vendor/symfony/validator/Symfony/Component/Validator/Tests/Mapping/GetterMetadataTest.php  gR  W_϶      Y   vendor/symfony/validator/Symfony/Component/Validator/Tests/Mapping/MemberMetadataTest.php  gR  D      Z   vendor/symfony/validator/Symfony/Component/Validator/Tests/Mapping/ElementMetadataTest.php  gR  y      _   vendor/symfony/validator/Symfony/Component/Validator/Tests/Mapping/ClassMetadataFactoryTest.php  gR  D      Z   vendor/symfony/validator/Symfony/Component/Validator/Tests/ConstraintViolationListTest.php  gR  zJ.4      M   vendor/symfony/validator/Symfony/Component/Validator/Tests/ConstraintTest.php.  gR.  d۶      L   vendor/symfony/validator/Symfony/Component/Validator/Tests/ValidatorTest.php'$  gR'$  Ky      S   vendor/symfony/validator/Symfony/Component/Validator/Tests/ExecutionContextTest.php)  gR)  P6      S   vendor/symfony/validator/Symfony/Component/Validator/Tests/ValidatorBuilderTest.php)  gR)  Ε_      V   vendor/symfony/validator/Symfony/Component/Validator/Tests/ConstraintViolationTest.php.  gR.  ,      T   vendor/symfony/validator/Symfony/Component/Validator/Tests/ValidationVisitorTest.phpF  gRF  ~6      S   vendor/symfony/validator/Symfony/Component/Validator/ConstraintValidatorFactory.php  gR  +s      L   vendor/symfony/validator/Symfony/Component/Validator/ClassBasedInterface.php<  gR<  U      I   vendor/symfony/validator/Symfony/Component/Validator/ValidatorBuilder.phpb'  gRb'  S      Q   vendor/symfony/validator/Symfony/Component/Validator/MetadataFactoryInterface.php  gR  YӶ      >   vendor/symfony/process/Symfony/Component/Process/composer.json  gR  dB      H   vendor/symfony/process/Symfony/Component/Process/PhpExecutableFinder.php  gR  ;      C   vendor/symfony/process/Symfony/Component/Process/ProcessBuilder.php  gR  !/      8   vendor/symfony/process/Symfony/Component/Process/LICENSE)  gR)  NmQ      A   vendor/symfony/process/Symfony/Component/Process/ProcessPipes.php!  gR!   Ӷ      ?   vendor/symfony/process/Symfony/Component/Process/PhpProcess.php  gR  @s      A   vendor/symfony/process/Symfony/Component/Process/phpunit.xml.dist  gR  p\H      <   vendor/symfony/process/Symfony/Component/Process/Process.php  gR  &!      W   vendor/symfony/process/Symfony/Component/Process/Exception/InvalidArgumentException.php  gR  ˅      O   vendor/symfony/process/Symfony/Component/Process/Exception/RuntimeException.php  gR  >H      M   vendor/symfony/process/Symfony/Component/Process/Exception/LogicException.php  gR  W      Q   vendor/symfony/process/Symfony/Component/Process/Exception/ExceptionInterface.php  gR  <      W   vendor/symfony/process/Symfony/Component/Process/Exception/ProcessTimedOutException.php{  gR{  2      U   vendor/symfony/process/Symfony/Component/Process/Exception/ProcessFailedException.php  gR  _      A   vendor/symfony/process/Symfony/Component/Process/ProcessUtils.php  gR  ¶      E   vendor/symfony/process/Symfony/Component/Process/ExecutableFinder.php
  gR
  !,$      N   vendor/symfony/process/Symfony/Component/Process/Tests/AbstractProcessTest.phpQX  gRQX  jZԶ      M   vendor/symfony/process/Symfony/Component/Process/Tests/ProcessBuilderTest.phpP  gRP  8ҍ      M   vendor/symfony/process/Symfony/Component/Process/Tests/NonStopableProcess.php*  gR*  .D϶      V   vendor/symfony/process/Symfony/Component/Process/Tests/SigchildDisabledProcessTest.phpD  gRD  +      R   vendor/symfony/process/Symfony/Component/Process/Tests/PhpExecutableFinderTest.phpM  gRM  D      I   vendor/symfony/process/Symfony/Component/Process/Tests/PhpProcessTest.php  gR  x[      I   vendor/symfony/process/Symfony/Component/Process/Tests/SignalListener.php   gR   O      K   vendor/symfony/process/Symfony/Component/Process/Tests/ProcessUtilsTest.phpf  gRf  7\      U   vendor/symfony/process/Symfony/Component/Process/Tests/ProcessFailedExceptionTest.php
  gR
  WKo      ^   vendor/symfony/process/Symfony/Component/Process/Tests/PipeStdinInStdoutStdErrStreamSelect.php  gR  #      W   vendor/symfony/process/Symfony/Component/Process/Tests/ProcessInSigchildEnvironment.php  gR  m      L   vendor/symfony/process/Symfony/Component/Process/Tests/SimpleProcessTest.php  gR  rD      U   vendor/symfony/process/Symfony/Component/Process/Tests/SigchildEnabledProcessTest.php  gR  (      >   vendor/symfony/console/Symfony/Component/Console/composer.jsone  gRe  Q&x      N   vendor/symfony/console/Symfony/Component/Console/Resources/bin/hiddeninput.exe $  gR $  v      P   vendor/symfony/console/Symfony/Component/Console/Event/ConsoleExceptionEvent.phpA  gRA  sK      N   vendor/symfony/console/Symfony/Component/Console/Event/ConsoleCommandEvent.php  gR  ||-&      P   vendor/symfony/console/Symfony/Component/Console/Event/ConsoleTerminateEvent.php&  gR&  Z      G   vendor/symfony/console/Symfony/Component/Console/Event/ConsoleEvent.php  gR  
      H   vendor/symfony/console/Symfony/Component/Console/Command/ListCommand.php
  gR
   x      D   vendor/symfony/console/Symfony/Component/Console/Command/Command.php7@  gR7@  Ƙ      H   vendor/symfony/console/Symfony/Component/Console/Command/HelpCommand.php_
  gR_
  m      :   vendor/symfony/console/Symfony/Component/Console/Shell.php%  gR%  ?OŶ      @   vendor/symfony/console/Symfony/Component/Console/Application.php  gR  PJ      8   vendor/symfony/console/Symfony/Component/Console/LICENSE)  gR)  NmQ      S   vendor/symfony/console/Symfony/Component/Console/Descriptor/DescriptorInterface.php  gR  JZ0<      N   vendor/symfony/console/Symfony/Component/Console/Descriptor/TextDescriptor.php  gR        J   vendor/symfony/console/Symfony/Component/Console/Descriptor/Descriptor.php  gR  m      R   vendor/symfony/console/Symfony/Component/Console/Descriptor/MarkdownDescriptor.php.  gR.  lP      V   vendor/symfony/console/Symfony/Component/Console/Descriptor/ApplicationDescription.php  gR  sX      M   vendor/symfony/console/Symfony/Component/Console/Descriptor/XmlDescriptor.php%  gR%  ﶲͶ      N   vendor/symfony/console/Symfony/Component/Console/Descriptor/JsonDescriptor.phpu  gRu  D      F   vendor/symfony/console/Symfony/Component/Console/Output/NullOutput.php  gR  F$_      K   vendor/symfony/console/Symfony/Component/Console/Output/OutputInterface.phpM  gRM  z      H   vendor/symfony/console/Symfony/Component/Console/Output/StreamOutput.phpM  gRM  Xz      B   vendor/symfony/console/Symfony/Component/Console/Output/Output.php;  gR;  sQ      J   vendor/symfony/console/Symfony/Component/Console/Output/BufferedOutput.phph  gRh  t|X4      R   vendor/symfony/console/Symfony/Component/Console/Output/ConsoleOutputInterface.php  gR  :2p      I   vendor/symfony/console/Symfony/Component/Console/Output/ConsoleOutput.php  gR  e      A   vendor/symfony/console/Symfony/Component/Console/phpunit.xml.disti  gRi  ?UH      F   vendor/symfony/console/Symfony/Component/Console/Input/InputOption.phpV  gRV  Oö      I   vendor/symfony/console/Symfony/Component/Console/Input/InputInterface.php&  gR&  o3޶      J   vendor/symfony/console/Symfony/Component/Console/Input/InputDefinition.php(0  gR(0  1E      F   vendor/symfony/console/Symfony/Component/Console/Input/StringInput.php
  gR
  ΂=      D   vendor/symfony/console/Symfony/Component/Console/Input/ArgvInput.php)  gR)  Q      @   vendor/symfony/console/Symfony/Component/Console/Input/Input.php  gR  QkT      E   vendor/symfony/console/Symfony/Component/Console/Input/ArrayInput.php%  gR%  p      H   vendor/symfony/console/Symfony/Component/Console/Input/InputArgument.php  gR  '      N   vendor/symfony/console/Symfony/Component/Console/Input/InputAwareInterface.php^  gR^  9Kh      M   vendor/symfony/console/Symfony/Component/Console/Tester/ApplicationTester.phpf  gRf  hr      I   vendor/symfony/console/Symfony/Component/Console/Tester/CommandTester.php  gR  ~H(R      K   vendor/symfony/console/Symfony/Component/Console/Helper/HelperInterface.php  gR  z׶      K   vendor/symfony/console/Symfony/Component/Console/Helper/FormatterHelper.php  gR  gse      J   vendor/symfony/console/Symfony/Component/Console/Helper/ProgressHelper.phpp.  gRp.  XT      L   vendor/symfony/console/Symfony/Component/Console/Helper/InputAwareHelper.php  gR  s H      H   vendor/symfony/console/Symfony/Component/Console/Helper/DialogHelper.php<@  gR<@  m      L   vendor/symfony/console/Symfony/Component/Console/Helper/DescriptorHelper.php
  gR
  "U1      G   vendor/symfony/console/Symfony/Component/Console/Helper/TableHelper.php.  gR.  Oe      B   vendor/symfony/console/Symfony/Component/Console/Helper/Helper.php  gR  Z\      E   vendor/symfony/console/Symfony/Component/Console/Helper/HelperSet.php	  gR	        W   vendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterInterface.php  gR  Jp˶      \   vendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyleInterface.php  gR  5      S   vendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyle.php&  gR&  oǌ      N   vendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatter.php   gR   	+<      X   vendor/symfony/console/Symfony/Component/Console/Formatter/OutputFormatterStyleStack.php
  gR
  v      N   vendor/symfony/console/Symfony/Component/Console/Tests/Command/CommandTest.phpZ9  gRZ9  o"      R   vendor/symfony/console/Symfony/Component/Console/Tests/Command/HelpCommandTest.php1  gR1  byζ      R   vendor/symfony/console/Symfony/Component/Console/Tests/Command/ListCommandTest.phpC	  gRC	  ˶      T   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/application_run4.txt   gR   8UT      S   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_option_3.json   gR   I      T   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_argument_3.xml   gR   : 8      T   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/application_run2.txt,  gR,  X       O   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/Foo5Command.php   gR   /""      N   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/FooCommand.php   gR   c      V   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_definition_4.txt~   gR~   .p      R   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/application_1.json  gR  oYֶ      W   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/application_astext1.txt  gR  ud      Q   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/BarBucCommand.php   gR         V   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_definition_2.xml   gR   3P߶      U   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_argument_3.json}   gR}   󚲱      V   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_definition_3.xml  gR  F:c      R   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_option_1.txt!   gR!   u$´      R   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/command_astext.txt  gR  ׶      R   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_option_1.xml   gR   G      T   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_argument_2.xml   gR   f      i   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/application_renderexception3decorated.txty  gRy  W      V   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_definition_3.txt=   gR=         T   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/application_run1.txt:  gR:  e      T   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/definition_asxml.txt  gR  ia      R   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_option_2.xml  gR  J2      V   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_definition_2.txt;   gR;   Ѹ      W   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_definition_4.json$  gR$        O   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/Foo4Command.php   gR   ed      U   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_argument_1.json]   gR]   <      R   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_option_4.xml   gR   I ƶ      Q   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/FoobarCommand.php/  gR/  1G~"      O   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/Foo3Command.phpA  gRA  6 _      O   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/Foo2Command.php  gR  	      T   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_argument_1.txt   gR   (?h      T   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_argument_1.xml   gR   _n      V   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/application_asxml1.txt  gR  ;`M      S   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_option_1.json   gR   X      Q   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/application_1.txt6  gR6  a      V   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_definition_1.txt    gR              R   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_option_3.xml   gR   XX      Q   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/command_asxml.txt  gR  S      W   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/application_astext2.txt$  gR$        V   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/application_asxml2.txt  gR  W'      S   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_option_2.json   gR   ۴2      N   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/command_1.json   gR   [%      W   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_definition_2.json   gR         `   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/application_renderexception1.txt   gR   &      S   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_option_4.json   gR    a      R   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_option_4.txta   gRa   t;      `   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/application_renderexception3.txt  gR  G u=      T   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/application_run3.txt  gR  !"      N   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/command_2.json  gR  #"      M   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/command_1.txt   gR   '̶      W   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_definition_3.json   gR   *q      O   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/TestCommand.php  gR  9*A      Q   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/application_2.xml]"  gR]"  @      V   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_definition_1.xml^   gR^   ^tݶ      V   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/DescriptorCommand1.php  gR  Y'A      V   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/DescriptorCommand2.php?  gR?  XzԶ      M   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/command_2.xmlf  gRf  A(      M   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/command_2.txt   gR   h      O   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/Foo1Command.phpU  gRU  <|4      `   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/application_renderexception2.txt   gR   ,Ǆ      Q   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/application_2.txt  gR  (      T   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_argument_2.txt1   gR1   g/      V   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_definition_4.xml  gR  CQu      `   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/application_renderexception4.txt   gR   Xl      R   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/application_2.json  gR  M      M   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/command_1.xmlO  gRO  E      U   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/definition_astext.txt  gR  ,ݶ      W   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/application_gethelp.txt  gR  #ɤb      Q   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/application_1.xml  gR  lT      R   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_option_3.txt4   gR4   x      Z   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/DescriptorApplication2.phpM  gRM  1"8      U   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_argument_2.jsono   gRo         T   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_argument_3.txt_   gR_   NY      Z   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/DescriptorApplication1.php  gR  q+      R   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_option_2.txtb   gRb   K@      W   vendor/symfony/console/Symfony/Component/Console/Tests/Fixtures/input_definition_1.json   gR         \   vendor/symfony/console/Symfony/Component/Console/Tests/Descriptor/AbstractDescriptorTest.php  gR  }      U   vendor/symfony/console/Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.phpJ  gRJ  _      X   vendor/symfony/console/Symfony/Component/Console/Tests/Descriptor/JsonDescriptorTest.php:  gR:  oW      X   vendor/symfony/console/Symfony/Component/Console/Tests/Descriptor/TextDescriptorTest.php9  gR9  K       W   vendor/symfony/console/Symfony/Component/Console/Tests/Descriptor/XmlDescriptorTest.php6  gR6  ₶      \   vendor/symfony/console/Symfony/Component/Console/Tests/Descriptor/MarkdownDescriptorTest.phpD  gRD  1HD      R   vendor/symfony/console/Symfony/Component/Console/Tests/Output/StreamOutputTest.php  gR        S   vendor/symfony/console/Symfony/Component/Console/Tests/Output/ConsoleOutputTest.php  gR  }R      P   vendor/symfony/console/Symfony/Component/Console/Tests/Output/NullOutputTest.php  gR  ;!      L   vendor/symfony/console/Symfony/Component/Console/Tests/Output/OutputTest.php  gR        N   vendor/symfony/console/Symfony/Component/Console/Tests/Input/ArgvInputTest.php ;  gR ;  9I      P   vendor/symfony/console/Symfony/Component/Console/Tests/Input/StringInputTest.php  gR        T   vendor/symfony/console/Symfony/Component/Console/Tests/Input/InputDefinitionTest.phpH  gRH  @      O   vendor/symfony/console/Symfony/Component/Console/Tests/Input/ArrayInputTest.php<  gR<  1E      J   vendor/symfony/console/Symfony/Component/Console/Tests/Input/InputTest.php  gR  p      P   vendor/symfony/console/Symfony/Component/Console/Tests/Input/InputOptionTest.php#  gR#  KUö      R   vendor/symfony/console/Symfony/Component/Console/Tests/Input/InputArgumentTest.php  gR  F5      S   vendor/symfony/console/Symfony/Component/Console/Tests/Tester/CommandTesterTest.phpB  gRB  x0m      W   vendor/symfony/console/Symfony/Component/Console/Tests/Tester/ApplicationTesterTest.phpd	  gRd	  Q      U   vendor/symfony/console/Symfony/Component/Console/Tests/Helper/FormatterHelperTest.php
  gR
  gO      O   vendor/symfony/console/Symfony/Component/Console/Tests/Helper/HelperSetTest.phpv  gRv  +      T   vendor/symfony/console/Symfony/Component/Console/Tests/Helper/ProgressHelperTest.php  gR  "
U      Q   vendor/symfony/console/Symfony/Component/Console/Tests/Helper/TableHelperTest.php$  gR$  z%?ȶ      R   vendor/symfony/console/Symfony/Component/Console/Tests/Helper/DialogHelperTest.php"  gR"  Ԧ      ]   vendor/symfony/console/Symfony/Component/Console/Tests/Formatter/OutputFormatterStyleTest.phpw  gRw  rH      b   vendor/symfony/console/Symfony/Component/Console/Tests/Formatter/OutputFormatterStyleStackTest.phpw  gRw   R      X   vendor/symfony/console/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php  gR        J   vendor/symfony/console/Symfony/Component/Console/Tests/ApplicationTest.phpQ  gRQ  Ķ      B   vendor/symfony/console/Symfony/Component/Console/ConsoleEvents.php  gR  \0E         vendor/psr/log/composer.jsonf  gRf  V         vendor/psr/log/LICENSE=  gR=  pO      )   vendor/psr/log/Psr/Log/AbstractLogger.php  gR  ,      3   vendor/psr/log/Psr/Log/InvalidArgumentException.php`   gR`    X1      &   vendor/psr/log/Psr/Log/LoggerTrait.php  gR  =      #   vendor/psr/log/Psr/Log/LogLevel.php8  gR8  l$ӥ      *   vendor/psr/log/Psr/Log/LoggerInterface.php  gR  b      +   vendor/psr/log/Psr/Log/LoggerAwareTrait.php_  gR_  b޶      %   vendor/psr/log/Psr/Log/NullLogger.php  gR  >      3   vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php"  gR"        /   vendor/psr/log/Psr/Log/LoggerAwareInterface.php   gR   SjT      %   vendor/erusev/parsedown/Parsedown.php%<  gR%<  Ga>      %   vendor/erusev/parsedown/composer.json  gR  xp      &   vendor/erusev/parsedown/tests/Test.php  gR        0   vendor/erusev/parsedown/tests/data/emphasis.html0  gR0  t5ζ      9   vendor/erusev/parsedown/tests/data/fenced_code_block.htmln   gRn   !E      2   vendor/erusev/parsedown/tests/data/code_block.html   gR   0ݶ      9   vendor/erusev/parsedown/tests/data/simple_blockquote.html   gR   1AVB      2   vendor/erusev/parsedown/tests/data/line_break.html   gR   T'L      0   vendor/erusev/parsedown/tests/data/escaping.html   gR   >Ƕ      7   vendor/erusev/parsedown/tests/data/span-level_html.htmlF   gRF   qA7      1   vendor/erusev/parsedown/tests/data/strong_em.html  gR  D6      5   vendor/erusev/parsedown/tests/data/compound_list.html{   gR{   ɺ      7   vendor/erusev/parsedown/tests/data/horizontal_rule.html&   gR&   u      3   vendor/erusev/parsedown/tests/data/atx_heading.html`   gR`   ]C      :   vendor/erusev/parsedown/tests/data/implicit_reference.html   gR   4lg      2   vendor/erusev/parsedown/tests/data/whitespace.html   gR   ؽP      7   vendor/erusev/parsedown/tests/data/lazy_blockquote.html6   gR6   Iʶ      1   vendor/erusev/parsedown/tests/data/em_strong.html   gR   )G      1   vendor/erusev/parsedown/tests/data/lazy_list.html%   gR%   n      6   vendor/erusev/parsedown/tests/data/text_reference.html*  gR*  ڎ'      8   vendor/erusev/parsedown/tests/data/block-level_html.htmlr   gRr   ~r      ;   vendor/erusev/parsedown/tests/data/compound_blockquote.htmlj   gRj   M8      1   vendor/erusev/parsedown/tests/data/code_span.html   gR   %      :   vendor/erusev/parsedown/tests/data/special_characters.html  gR  N      5   vendor/erusev/parsedown/tests/data/strikethrough.htmlw   gRw   2      6   vendor/erusev/parsedown/tests/data/automatic_link.html:   gR:         4   vendor/erusev/parsedown/tests/data/ordered_list.html   gR   Z      3   vendor/erusev/parsedown/tests/data/inline_link.html   gR   t      6   vendor/erusev/parsedown/tests/data/unordered_list.htmlg   gRg   a      7   vendor/erusev/parsedown/tests/data/image_reference.html.   gR.   P      3   vendor/erusev/parsedown/tests/data/sparse_list.htmlr   gRr   c|I#      5   vendor/erusev/parsedown/tests/data/setext_header.htmlP   gRP   ;vi      7   vendor/erusev/parsedown/tests/data/url_autolinking.htmlN   gRN   g      (   vendor/erusev/parsedown/phpunit.xml.dist   gR   ߂      #   vendor/erusev/parsedown/LICENSE.txtC  gRC  8E      %   vendor/nikic/php-parser/composer.json  gR  ґ>         vendor/nikic/php-parser/LICENSE  gR  EF      +   vendor/nikic/php-parser/grammar/analyze.php  gR        1   vendor/nikic/php-parser/grammar/kmyacc.php.parser'-  gR'-  JN      9   vendor/nikic/php-parser/grammar/zend_language_parser.phpy  gR  V      1   vendor/nikic/php-parser/grammar/rebuildParser.php  gR        (   vendor/nikic/php-parser/phpunit.xml.dist  gR  tGL      5   vendor/nikic/php-parser/lib/PHPParser/NodeVisitor.php<  gR<  5r˶      0   vendor/nikic/php-parser/lib/PHPParser/Parser.php gR T,      ?   vendor/nikic/php-parser/lib/PHPParser/PrettyPrinterAbstract.php&  gR&  oje      /   vendor/nikic/php-parser/lib/PHPParser/Error.php  gR  "ݶ      4   vendor/nikic/php-parser/lib/PHPParser/Autoloader.php  gR  {      .   vendor/nikic/php-parser/lib/PHPParser/Node.php  gR  
RF      9   vendor/nikic/php-parser/lib/PHPParser/BuilderAbstract.php  gR  m      :   vendor/nikic/php-parser/lib/PHPParser/Builder/Property.php  gR  J\      7   vendor/nikic/php-parser/lib/PHPParser/Builder/Class.php  gR  P&      :   vendor/nikic/php-parser/lib/PHPParser/Builder/Function.phpz
  gRz
  Os      8   vendor/nikic/php-parser/lib/PHPParser/Builder/Method.php  gR   (      7   vendor/nikic/php-parser/lib/PHPParser/Builder/Param.php  gR  (      ;   vendor/nikic/php-parser/lib/PHPParser/Builder/Interface.php	  gR	        @   vendor/nikic/php-parser/lib/PHPParser/NodeTraverserInterface.php  gR  Rf=      B   vendor/nikic/php-parser/lib/PHPParser/NodeVisitor/NameResolver.php  gR  w      5   vendor/nikic/php-parser/lib/PHPParser/Comment/Doc.php@   gR@   G      8   vendor/nikic/php-parser/lib/PHPParser/BuilderFactory.php	  gR	  ߘ8      4   vendor/nikic/php-parser/lib/PHPParser/NodeDumper.php  gR  ]V5      1   vendor/nikic/php-parser/lib/PHPParser/Comment.phpu  gRu  ]2      1   vendor/nikic/php-parser/lib/PHPParser/Builder.php   gR   zƶ      =   vendor/nikic/php-parser/lib/PHPParser/NodeVisitorAbstract.phpN  gRN  4      2   vendor/nikic/php-parser/lib/PHPParser/Template.php  gR  RN      6   vendor/nikic/php-parser/lib/PHPParser/NodeAbstract.phpI  gRI  7      :   vendor/nikic/php-parser/lib/PHPParser/Unserializer/XML.phpm  gRm  '?Ⓐ      4   vendor/nikic/php-parser/lib/PHPParser/Serializer.php   gR   m      7   vendor/nikic/php-parser/lib/PHPParser/NodeTraverser.php(  gR(  +߶      9   vendor/nikic/php-parser/lib/PHPParser/Lexer/Emulative.php!  gR!  ,B      4   vendor/nikic/php-parser/lib/PHPParser/Node/Const.php  gR  )᜶      3   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt.phpL   gRL   Bȶ      2   vendor/nikic/php-parser/lib/PHPParser/Node/Arg.php  gR  SY,      5   vendor/nikic/php-parser/lib/PHPParser/Node/Scalar.phpK   gRK   nW      9   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/Const.php5  gR5  N      :   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/ElseIf.php  gR  /r      <   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/Continue.phpQ  gRQ        :   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/Global.php'  gR'  ~"      9   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/While.php  gR  A$      ?   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/ClassMethod.php\	  gR\	  5^      <   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/Property.php   gR   >      8   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/Echo.php  gR  p      :   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/UseUse.php  gR  @R      >   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/ClassConst.php@  gR@  @p      B   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/DeclareDeclare.php  gR  ˬt      <   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/TryCatch.php  gR  t$      6   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/If.php  gR  
      :   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/Switch.php  gR  ?a      8   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/Case.php  gR  `      <   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/TraitUse.phpG  gRG  N{      >   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/InlineHTML.php  gR  dl      =   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/Namespace.php  gR  ׶      7   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/Use.php(  gR(  pCn߶      9   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/Break.phpE  gRE  =fI      7   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/For.phpV  gRV  ߖ      9   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/Label.php  gR  Sy      8   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/Else.php  gR   U      ;   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/Foreach.php  gR  ]9      L   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/TraitUseAdaptation/Alias.php  gR  $h      Q   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/TraitUseAdaptation/Precedence.php  gR  4I      9   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/Class.phpH  gRH  6      <   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/Function.phpQ  gRQ  uQP      8   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/Goto.php  gR  Ͷ      9   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/Throw.php  gR  ~+      6   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/Do.php  gR        9   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/Catch.php{  gR{  o      =   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/StaticVar.php  gR  Mt      D   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/PropertyProperty.php  gR  U[5      :   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/Static.phpR  gRR  ݪ	      @   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/HaltCompiler.phpG  gRG  A      9   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/Unset.php   gR   $      9   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/Trait.php  gR  1f      :   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/Return.php/  gR/  "8      ;   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/Declare.php!  gR!  7      F   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/TraitUseAdaptation.php\   gR\         =   vendor/nikic/php-parser/lib/PHPParser/Node/Stmt/Interface.php  gR  K淶      3   vendor/nikic/php-parser/lib/PHPParser/Node/Name.phpx  gRx        3   vendor/nikic/php-parser/lib/PHPParser/Node/Expr.phpL   gRL         4   vendor/nikic/php-parser/lib/PHPParser/Node/Param.php}  gR}  ?      >   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/BitwiseXor.php  gR  Gٶ      A   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/PropertyFetch.php  gR  2ȫ      =   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/AssignMod.php  gR  B      9   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Array.php>  gR>  9l      A   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/ArrayDimFetch.php  gR  7m2ƶ      ;   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Ternary.php  gR  {      >   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/StaticCall.php  gR  W      9   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Isset.php  gR  Q)      C   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/ClassConstFetch.php  gR  ͂2      7   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Mod.php  gR  U
      9   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Empty.php  gR  %-u`      =   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/AssignMul.php  gR  k      7   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/New.php  gR  "Go      :   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Assign.php  gR  8u-      =   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/ArrayItem.php  gR  \      ;   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/PostDec.php  gR  .      9   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Minus.php  gR  SN      =   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Identical.php(  gR(  XD      =   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/UnaryPlus.php  gR  h      :   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/PreDec.php  gR  p}D      <   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Variable.php  gR  ~u      9   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Yield.php	  gR	  2      ?   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/AssignMinus.php  gR  Fn      >   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/AssignPlus.php  gR  G'      @   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/AssignConcat.php  gR  d]M      9   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Print.php  gR  հ      B   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/SmallerOrEqual.php5  gR5  r*      7   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Div.php  gR  uXl      >   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/ConstFetch.php(  gR(  N      7   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Mul.php  gR  5      >   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/UnaryMinus.php!  gR!  Gg      >   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/ClosureUse.php  gR  nƶ      9   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Equal.php  gR  }      D   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/AssignBitwiseXor.php  gR  nؿG      ;   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/PostInc.php  gR  U      8   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Cast.php  gR  CM&ն      ;   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Include.php=  gR=  wݤ      C   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/AssignShiftLeft.php  gR  F(R      >   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/BooleanNot.php!  gR!  [e      D   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/AssignBitwiseAnd.php  gR  QӶ      ;   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Smaller.php%  gR%  B      8   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/List.php  gR  yV      8   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Plus.php  gR        <   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/FuncCall.php  gR  !ֶ      :   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/PreInc.php  gR  C"ٶ      A   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/ErrorSuppress.php(  gR(  !      C   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/AssignBitwiseOr.php  gR  ū      ;   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Greater.php%  gR%  |DĶ      >   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Instanceof.php  gR  d      ?   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Cast/String.phpQ   gRQ   m
      >   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Cast/Array.phpP   gRP   &NZ      ?   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Cast/Double.phpQ   gRQ   t      <   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Cast/Int.phpN   gRN   	ж      ?   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Cast/Object.phpQ   gRQ   P!¶      =   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Cast/Bool.phpO   gRO   %z      >   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Cast/Unset.phpP   gRP   Xp      :   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Concat.php  gR  l      G   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/StaticPropertyFetch.php#  gR#  0]Il      =   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/BitwiseOr.php  gR  R      D   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/AssignShiftRight.php  gR  w\      9   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Clone.php  gR  Ȏ      =   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/BooleanOr.php  gR  ]      ;   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Closure.php_  gR_  
u/      >   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/BitwiseAnd.php  gR  F      =   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/ShiftLeft.php  gR  u      >   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/BooleanAnd.php  gR  V.yl      >   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/LogicalAnd.php  gR  w(F      >   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/BitwiseNot.php!  gR!  Oy      >   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/ShiftRight.php  gR  iӶ      @   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/NotIdentical.php+  gR+  p1      8   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Exit.php-  gR-  V      =   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/LogicalOr.php  gR  0      =   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/AssignDiv.php  gR  4w      B   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/GreaterOrEqual.php*  gR*  Z\ٶ      >   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/LogicalXor.php  gR  6q      <   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/NotEqual.php#  gR#  %      =   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/AssignRef.php  gR  lo      8   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/Eval.php  gR  Ŷ      >   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/MethodCall.php  gR  8      =   vendor/nikic/php-parser/lib/PHPParser/Node/Expr/ShellExec.php  gR  k:Ŷ      B   vendor/nikic/php-parser/lib/PHPParser/Node/Name/FullyQualified.php  gR  !?      <   vendor/nikic/php-parser/lib/PHPParser/Node/Name/Relative.php  gR  tֶ      <   vendor/nikic/php-parser/lib/PHPParser/Node/Scalar/String.phpo  gRo        >   vendor/nikic/php-parser/lib/PHPParser/Node/Scalar/Encapsed.php   gR   rz      @   vendor/nikic/php-parser/lib/PHPParser/Node/Scalar/ClassConst.php=  gR=  uX      ?   vendor/nikic/php-parser/lib/PHPParser/Node/Scalar/LineConst.php;  gR;  1      =   vendor/nikic/php-parser/lib/PHPParser/Node/Scalar/DNumber.phpC  gRC        =   vendor/nikic/php-parser/lib/PHPParser/Node/Scalar/LNumber.phpn  gRn  1ж      ?   vendor/nikic/php-parser/lib/PHPParser/Node/Scalar/FuncConst.php?  gR?  t&      ?   vendor/nikic/php-parser/lib/PHPParser/Node/Scalar/FileConst.php;  gR;  *      >   vendor/nikic/php-parser/lib/PHPParser/Node/Scalar/DirConst.php9  gR9  N~f      @   vendor/nikic/php-parser/lib/PHPParser/Node/Scalar/TraitConst.php=  gR=  kϝ      =   vendor/nikic/php-parser/lib/PHPParser/Node/Scalar/NSConst.php>  gR>  k      A   vendor/nikic/php-parser/lib/PHPParser/Node/Scalar/MethodConst.php?  gR?  `R      6   vendor/nikic/php-parser/lib/PHPParser/Unserializer.php  gR  3,      8   vendor/nikic/php-parser/lib/PHPParser/Serializer/XML.php  gR         /   vendor/nikic/php-parser/lib/PHPParser/Lexer.php  gR  B      8   vendor/nikic/php-parser/lib/PHPParser/TemplateLoader.php  gR  v      ?   vendor/nikic/php-parser/lib/PHPParser/PrettyPrinter/Default.phpGn  gRGn        <   vendor/nikic/php-parser/lib/PHPParser/PrettyPrinter/Zend.php   gR   e      )   vendor/nikic/php-parser/lib/bootstrap.phpC  gRC  \      %   vendor/composer/autoload_classmap.php* gR* oX      !   vendor/composer/autoload_real.php  gR  D         vendor/composer/ClassLoader.php  gR  q      !   vendor/composer/include_paths.php  gR  Y         vendor/composer/installed.json gR ~      '   vendor/composer/autoload_namespaces.php  gR  UkR      $   vendor/monolog/monolog/composer.json  gR  ڈg      -   vendor/monolog/monolog/src/Monolog/Logger.php?  gR?  ɴS      =   vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.phpR  gRR  BU      G   vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php  gR  񀫶      E   vendor/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.phpk  gRk  %      =   vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.phpE  gRE  DsE      I   vendor/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php~  gR~  '      G   vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php%  gR%  m      @   vendor/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php  gR  0p      C   vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php>  gR>  )V+      3   vendor/monolog/monolog/src/Monolog/ErrorHandler.php  gR  M2      B   vendor/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php,  gR,   I      E   vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php  gR  Ė      D   vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php  gR  PUֶ      C   vendor/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php  gR  Wܑ      B   vendor/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.phpb  gRb  6$      C   vendor/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php  gR  lD      @   vendor/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php;  gR;  úB      B   vendor/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php  gR        >   vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php  gR  	      >   vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php  gR  e      =   vendor/monolog/monolog/src/Monolog/Handler/MongoDBHandler.phph  gRh  R.I      A   vendor/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php  gR  R޽      :   vendor/monolog/monolog/src/Monolog/Handler/NullHandler.php  gR   O      ;   vendor/monolog/monolog/src/Monolog/Handler/RavenHandler.php`  gR`  :Ƕ      :   vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php  gR  ~V͚      ?   vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php#  gR#  0      >   vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php  gR  D܅      ?   vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php	  gR	  g%|      >   vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php  gR  ¶      <   vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.phpd  gRd  g=(      >   vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.phpt  gRt  VF:<      B   vendor/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php;  gR;  z      >   vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php  gR  8߶      ;   vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php  gR  !      D   vendor/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php=  gR=  9ö      =   vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.phpN  gRN  '1ն      >   vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php?
  gR?
        ?   vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php  gR  x      :   vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php  gR  	Ja      B   vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php!  gR!  D      D   vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php3  gR3  <m      E   vendor/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php  gR  ~      Y   vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php  gR  S      Z   vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php  gR  JHi      \   vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php/  gR/  gD      :   vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.phpl  gRl  	̶      H   vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php  gR  o@      <   vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php  gR        :   vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php  gR  G      <   vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php  gR  N7^      <   vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php8  gR8   R      =   vendor/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php{  gR{  n      <   vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php6  gR6  .      B   vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php	  gR	  s      C   vendor/monolog/monolog/src/Monolog/Handler/ElasticSearchHandler.phpP  gRP  k      A   vendor/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php  gR  k      H   vendor/monolog/monolog/src/Monolog/Handler/MissingExtensionException.php  gR  8?      =   vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php~  gR~  k      ;   vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.phpa  gRa  e}ζ      :   vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.phpg  gRg  c         vendor/monolog/monolog/LICENSE  gR  8w      1   vendor/monolog/monolog/tests/Monolog/TestCase.phpk  gRk  Z      9   vendor/monolog/monolog/tests/Monolog/ErrorHandlerTest.php  gR  $=      9   vendor/monolog/monolog/tests/Monolog/PsrLogCompatTest.php  gR        3   vendor/monolog/monolog/tests/Monolog/LoggerTest.php/  gR/  z      I   vendor/monolog/monolog/tests/Monolog/Processor/ProcessIdProcessorTest.phpL  gRL   	      C   vendor/monolog/monolog/tests/Monolog/Processor/WebProcessorTest.php	  gR	  H      C   vendor/monolog/monolog/tests/Monolog/Processor/UidProcessorTest.php[  gR[  hv      K   vendor/monolog/monolog/tests/Monolog/Processor/MemoryUsageProcessorTest.php  gR  ]6R}      O   vendor/monolog/monolog/tests/Monolog/Processor/MemoryPeakUsageProcessorTest.php%  gR%  y̤t      M   vendor/monolog/monolog/tests/Monolog/Processor/IntrospectionProcessorTest.phpQ  gRQ  ek      D   vendor/monolog/monolog/tests/Monolog/Formatter/LineFormatterTest.phpa  gRa  ?      D   vendor/monolog/monolog/tests/Monolog/Formatter/JsonFormatterTest.php  gR  	4      H   vendor/monolog/monolog/tests/Monolog/Formatter/LogstashFormatterTest.phpx&  gRx&  )A      K   vendor/monolog/monolog/tests/Monolog/Formatter/GelfMessageFormatterTest.php  gR  3@_
      F   vendor/monolog/monolog/tests/Monolog/Formatter/ScalarFormatterTest.phpp  gRp  jG      J   vendor/monolog/monolog/tests/Monolog/Formatter/NormalizerFormatterTest.php  gR  7kض      H   vendor/monolog/monolog/tests/Monolog/Formatter/WildfireFormatterTest.phpj  gRj  Vnv      H   vendor/monolog/monolog/tests/Monolog/Formatter/ElasticaFormatterTest.phpU	  gRU	  #(      I   vendor/monolog/monolog/tests/Monolog/Formatter/ChromePHPFormatterTest.php  gR  1      N   vendor/monolog/monolog/tests/Monolog/Functional/Handler/FirePHPHandlerTest.php  gR  fyA      K   vendor/monolog/monolog/tests/Monolog/Handler/DoctrineCouchDBHandlerTest.php  gR        H   vendor/monolog/monolog/tests/Monolog/Handler/NativeMailerHandlerTest.php  gR  ޶      :   vendor/monolog/monolog/tests/Monolog/Handler/GelfMocks.php  gR  lȶ      E   vendor/monolog/monolog/tests/Monolog/Handler/ChromePHPHandlerTest.php7  gR7        @   vendor/monolog/monolog/tests/Monolog/Handler/TestHandlerTest.phpj  gRj  ׶      @   vendor/monolog/monolog/tests/Monolog/Handler/AmqpHandlerTest.phpm  gRm  ɶ      @   vendor/monolog/monolog/tests/Monolog/Handler/MockRavenClient.php  gR  fH      B   vendor/monolog/monolog/tests/Monolog/Handler/SyslogHandlerTest.php  gR  G      C   vendor/monolog/monolog/tests/Monolog/Handler/CouchDBHandlerTest.php_  gR_  q      B   vendor/monolog/monolog/tests/Monolog/Handler/BufferHandlerTest.php  gR  q*      B   vendor/monolog/monolog/tests/Monolog/Handler/SocketHandlerTest.php  gR  h      D   vendor/monolog/monolog/tests/Monolog/Handler/AbstractHandlerTest.php7  gR7  ʶ      G   vendor/monolog/monolog/tests/Monolog/Handler/ZendMonitorHandlerTest.php  gR  Zt4      C   vendor/monolog/monolog/tests/Monolog/Handler/MongoDBHandlerTest.php  gR  ad      A   vendor/monolog/monolog/tests/Monolog/Handler/AmqpExchangeMock.php  gR  /i      A   vendor/monolog/monolog/tests/Monolog/Handler/RedisHandlerTest.php  gR  옶      >   vendor/monolog/monolog/tests/Monolog/Handler/UdpSocketTest.phpc  gRc  bJ      C   vendor/monolog/monolog/tests/Monolog/Handler/FirePHPHandlerTest.php)  gR)  (      A   vendor/monolog/monolog/tests/Monolog/Handler/GroupHandlerTest.phpW  gRW  =+      E   vendor/monolog/monolog/tests/Monolog/Handler/SyslogUdpHandlerTest.php  gR        J   vendor/monolog/monolog/tests/Monolog/Handler/FingersCrossedHandlerTest.php  gR  J%      C   vendor/monolog/monolog/tests/Monolog/Handler/HipChatHandlerTest.php1  gR1  n      @   vendor/monolog/monolog/tests/Monolog/Handler/GelfHandlerTest.phpL  gRL  QN<      I   vendor/monolog/monolog/tests/Monolog/Handler/ElasticSearchHandlerTest.php$  gR$  .      D   vendor/monolog/monolog/tests/Monolog/Handler/ErrorLogHandlerTest.php'  gR'  M      A   vendor/monolog/monolog/tests/Monolog/Handler/RavenHandlerTest.php5  gR5  Ƕ      @   vendor/monolog/monolog/tests/Monolog/Handler/NullHandlerTest.php  gR        H   vendor/monolog/monolog/tests/Monolog/Handler/RotatingFileHandlerTest.php9  gR9  ly      @   vendor/monolog/monolog/tests/Monolog/Handler/MailHandlerTest.php  gR  |d      D   vendor/monolog/monolog/tests/Monolog/Handler/NewRelicHandlerTest.php	  gR	  Y%      D   vendor/monolog/monolog/tests/Monolog/Handler/DynamoDbHandlerTest.phpI  gRI  巓C      N   vendor/monolog/monolog/tests/Monolog/Handler/AbstractProcessingHandlerTest.php_
  gR_
  ^      D   vendor/monolog/monolog/tests/Monolog/Handler/PushoverHandlerTest.php  gR  J#      B   vendor/monolog/monolog/tests/Monolog/Handler/StreamHandlerTest.php
  gR
  04      *   vendor/monolog/monolog/tests/bootstrap.phpG  gRG  *s      '   vendor/monolog/monolog/phpunit.xml.dist  gR  Q'      #   vendor/monolog/monolog/README.mdown.  gR.  zA      &   vendor/monolog/monolog/CHANGELOG.mdowni  gRi        "   vendor/pimple/pimple/composer.jsonU  gRU  Ka _         vendor/pimple/pimple/LICENSE)  gR)  ˶      %   vendor/pimple/pimple/phpunit.xml.dist3  gR3  {Kö      #   vendor/pimple/pimple/lib/Pimple.php  gR  0񔤶      $   vendor/mockery/mockery/composer.json  gR  g      >   vendor/mockery/mockery/library/Mockery/ExpectationDirector.php  gR  汌϶      8   vendor/mockery/mockery/library/Mockery/MockInterface.php  gR  |      6   vendor/mockery/mockery/library/Mockery/Matcher/Not.php  gR  ^y      9   vendor/mockery/mockery/library/Mockery/Matcher/HasKey.php  gR  G<      ;   vendor/mockery/mockery/library/Mockery/Matcher/Contains.php  gR  V淶      6   vendor/mockery/mockery/library/Mockery/Matcher/Any.phpg  gRg  VqӶ      B   vendor/mockery/mockery/library/Mockery/Matcher/MatcherAbstract.php  gR  .(t*      7   vendor/mockery/mockery/library/Mockery/Matcher/Type.php  gR  1      8   vendor/mockery/mockery/library/Mockery/Matcher/AnyOf.php  gR  ж      9   vendor/mockery/mockery/library/Mockery/Matcher/Subset.php-  gR-  rK      :   vendor/mockery/mockery/library/Mockery/Matcher/Closure.php  gR        ;   vendor/mockery/mockery/library/Mockery/Matcher/HasValue.php  gR  Pʑ      9   vendor/mockery/mockery/library/Mockery/Matcher/MustBe.php  gR  K      ;   vendor/mockery/mockery/library/Mockery/Matcher/NotAnyOf.php   gR   1J-      ;   vendor/mockery/mockery/library/Mockery/Matcher/Ducktype.php{  gR{  GC9      4   vendor/mockery/mockery/library/Mockery/Undefined.php  gR   $!r      4   vendor/mockery/mockery/library/Mockery/Exception.php  gR  {      @   vendor/mockery/mockery/library/Mockery/CountValidator/AtMost.phpx  gRx  +i      C   vendor/mockery/mockery/library/Mockery/CountValidator/Exception.php  gR  EO      A   vendor/mockery/mockery/library/Mockery/CountValidator/AtLeast.php@  gR@  %9      P   vendor/mockery/mockery/library/Mockery/CountValidator/CountValidatorAbstract.php  gR  <k      ?   vendor/mockery/mockery/library/Mockery/CountValidator/Exact.phpy  gRy  G      ?   vendor/mockery/mockery/library/Mockery/CompositeExpectation.php  gR  a%      1   vendor/mockery/mockery/library/Mockery/Loader.php  gR  ?߶      6   vendor/mockery/mockery/library/Mockery/Expectation.php9  gR9  s(      4   vendor/mockery/mockery/library/Mockery/Container.php0  gR0  H      3   vendor/mockery/mockery/library/Mockery/Recorder.php  gR  !      /   vendor/mockery/mockery/library/Mockery/Mock.php@3  gR@3        8   vendor/mockery/mockery/library/Mockery/Configuration.php  gR  Sὶ      4   vendor/mockery/mockery/library/Mockery/Generator.phpCe  gRCe  -      S   vendor/mockery/mockery/library/Mockery/Exception/NoMatchingExpectationException.php-  gR-         J   vendor/mockery/mockery/library/Mockery/Exception/InvalidCountException.php  gR   ƽ:      J   vendor/mockery/mockery/library/Mockery/Exception/InvalidOrderException.php  gR  أ      G   vendor/mockery/mockery/library/Mockery/Adapter/Phpunit/TestListener.php
  gR
  ܏"      *   vendor/mockery/mockery/library/Mockery.php/  gR/  /C      "   vendor/mockery/mockery/package.xmlz  gRz  { V         vendor/mockery/mockery/LICENSE  gR  $c      &   vendor/mockery/mockery/README.markdown  gR  -¼      1   vendor/mockery/mockery/tests/Mockery/MockTest.php  gR  {tU      2   vendor/mockery/mockery/tests/Mockery/AdhocTest.php  gR  ?      4   vendor/mockery/mockery/tests/Mockery/_files/file.txt    gR              5   vendor/mockery/mockery/tests/Mockery/RecorderTest.php  gR  1"      3   vendor/mockery/mockery/tests/Mockery/LoaderTest.php]  gR]  @Ҷ      8   vendor/mockery/mockery/tests/Mockery/ExpectationTest.phpT  gRT  S      6   vendor/mockery/mockery/tests/Mockery/ContainerTest.php  gR  K      @   vendor/mockery/mockery/tests/Mockery/HamcrestExpectationTest.php  gR  v      E   vendor/mockery/mockery/tests/Mockery/WithFormatterExpectationTest.php#  gR#  90s      *   vendor/mockery/mockery/tests/Bootstrap.phpc
  gRc
  z      (   vendor/mockery/mockery/tests/phpunit.xml*  gR*        9   vendor/mockery/mockery/examples/starship/StarshipTest.php  gR  q      6   vendor/mockery/mockery/examples/starship/Bootstrap.php   gR   Tf޶      4   vendor/mockery/mockery/examples/starship/phpunit.xmlA  gRA        5   vendor/mockery/mockery/examples/starship/Starship.phpp  gRp  S         _cli_stub.phpS   gRS   >wb         _web_stub.phpx   gRx   ށ      Copyright (c) 2010 Mike van Riel

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.README
======

What is phpDocumentor?
----------------

phpDocumentor an application that is capable of analyzing your PHP source code and
DocBlock comments to generate a complete set of API Documentation.

Inspired by phpDocumentor 1 and JavaDoc it continues to innovate and is up to date
with the latest technologies and PHP language features.

Features
--------

phpDocumentor supports the following:

* *PHP 5.3 compatible*, full support for Namespaces, Closures and more is provided.
* *Shows any tag*, some tags add additional functionality to phpDocumentor (such as @link).
* *Processing speed*, Zend Framework experienced a significant reduction in processing time compared to phpDocumentor 1.
* *Low memory usage*, peak memory usage for small projects is less than 20MB, medium projects 40MB and large frameworks 100MB.
* *Incremental parsing*, if you kept the Structure file from a previous run you get an additional performance boost of up
  to 80% on top of the mentioned processing speed above.
* *Easy template building*, if you want to make a branding you only have to call 1 task and edit 3 files.
* *Command-line compatibility with phpDocumentor 1*, phpDocumentor 2 is an application in its own right but the
  basic phpDocumentor 1 arguments, such as --directory, --file and --target, have been adopted.
* *Two-step process*, phpDocumentor first generates a cache with your application structure before creating the output.
  If you'd like you can use that to power your own tools or formatters!

Requirements
------------

phpDocumentor requires the following:

* PHP 5.3.3 or higher
* ext/iconv, http://php.net/manual/en/book.iconv.php (is enabled by default since PHP 5.0.0)
* ext/intl, http://php.net/manual/en/book.intl.php
* The XSL extension, http://www.php.net/manual/en/book.xsl.php (optional, only used with XSL based templates)
* Graphviz (optional, used for generating Class diagrams)

**Note:**
If you do not want to install the Graphviz dependency you are encouraged to generate your own template and make sure
that it does not contain anything related to `Graph`.
An easier solution might be to edit `data/templates/responsive/template.xml` file and remove every line
containing the word `Graph` but this will be undone with every upgrade of phpDocumentor.

Please see the documentation about creating your own templates for more information.

Installation
------------

There are 3 ways to install phpDocumentor:

1. Via PEAR (recommended)
2. Via [Composer](https://getcomposer.org)
3. Using the PHAR

_*Please note* that it is required that the installation path of phpDocumentor does not
contain spaces. This is a requirement imposed by an external library (libxml)_

### PEAR (recommended)

1. phpDocumentor is hosted on its own PEAR channel which can be discovered using the following command:

        $ pear channel-discover pear.phpdoc.org

2. After that it is a simple matter of invoking PEAR to install the application

        $ pear install phpdoc/phpDocumentor

### Via Composer

1. phpDocumentor is available on [Packagist](https://packagist.org).
2. It can be installed as a dependency of your project by running

        $ composer require-dev phpdocumentor/phpdocumentor

### Using the PHAR

1. Download the phar file from http://phpdoc.org/phpDocumentor.phar
2. ???
3. Profit!

How to use phpDocumentor?
-------------------

The easiest way to run phpDocumentor is by running the following command:

    $ phpdoc run -d <SOURCE_DIRECTORY> -t <TARGET_DIRECTORY>

This command will parse the source code provided using the `-d` argument and
output it to the folder indicated by the `-t` argument.

phpDocumentor supports a whole range of options to configure the output of your documentation.
You can execute the following command, or check our website, for a more detailed listing of available command line options.

    $ phpdoc run -h

Configuration file(s)
---------------------

phpDocumentor also supports the use of configuration files (named phpdoc.xml or phpdoc.dist.xml by default).
Please consult the documentation to see the format and supported options.

Documentation
-------------

For more detailed information you can check our online documentation at [http://phpdoc.org/docs/](http://phpdoc.org/docs/).

Known issues
------------

1. phpDocumentor must be installed in a path without spaces due to restrictions in libxml. The XSL transformation
   will throw all kinds of odd warnings if the path contains spaces.

Donations
---------

If you would like to help out financially we accept donations using [gittip](https://www.gittip.com/mvriel/). All
donations will be used to cover the costs for hosting phpDocumentor's website and PEAR repository.

Contact
-------

To come in contact is actually dead simple and can be done in a variety of ways.

* Twitter: [@phpDocumentor](http://twitter.com/phpdocumentor)
* Website: [http://www.phpdoc.org](http://www.phpdoc.org)
* IRC:     Freenode, #phpdocumentor
* Github:  [http://www.github.com/phpdocumentor/phpdocumentor2](http://www.github.com/phpdocumentor/phpdocumentor2)
* E-mail:  [mike.vanriel@naenius.com](mailto:mike.vanriel@naenius.com)
2.2.0

<?php
/* PHPUnit
 *
 * Copyright (c) 2001-2012, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

define('PHPUnit_MAIN_METHOD', 'PHPUnit_TextUI_Command::main');

$files = array(
  __DIR__ . '/../../vendor/autoload.php',
  __DIR__ . '/../../../../autoload.php'
);

foreach ($files as $file) {
    if (file_exists($file)) {
        require $file;

        define('PHPUNIT_COMPOSER_INSTALL', $file);

        break;
    }
}

if (!defined('PHPUNIT_COMPOSER_INSTALL')) {
    die(
      'You need to set up the project dependencies using the following commands:' . PHP_EOL .
      'curl -s http://getcomposer.org/installer | php' . PHP_EOL .
      'php composer.phar install' . PHP_EOL
    );
}

PHPUnit_TextUI_Command::main();

<?php

require_once __DIR__.'/../vendor/autoload.php';

$compiler = new phpDocumentor\PharCompiler();
$compiler->compile();
@echo off
if "%PHPBIN%" == "" set PHPBIN=php.exe
if not exist "%PHPBIN%" if "%PHP_PEAR_PHP_BIN%" neq "" goto USE_PEAR_PATH
GOTO RUN
:USE_PEAR_PATH
set PHPBIN=%PHP_PEAR_PHP_BIN%
:RUN
"%PHPBIN%" "%PHP_PEAR_BIN_DIR%\phpdoc.php" %*
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

// check whether xhprof is loaded
$profile   = (bool)(getenv('PHPDOC_PROFILE') === 'on');
$xhguiPath = getenv('XHGUI_PATH');
if ($profile && $xhguiPath && extension_loaded('xhprof')) {
    echo 'PROFILING ENABLED' . PHP_EOL;
    include($xhguiPath . '/external/header.php');
}

// determine base include folder, if @php_dir@ contains @php_dir then
// we did not install via PEAR
$bootstrap_folder = (strpos('@php_dir@', '@php_dir') === 0)
    ? __DIR__ . '/../src'
    : '@php_dir@/phpDocumentor/src';

require_once $bootstrap_folder . '/phpDocumentor/Application.php';
$app = new phpDocumentor\Application();
$app->run();

// disable E_STRICT reporting on the end to prevent PEAR from throwing Strict warnings.
error_reporting(error_reporting() & ~E_STRICT);
#!/bin/bash

ppid=$$
maxmem=0

$@ &
pid=`pgrep -P ${ppid} -n -f $1` # $! may work here but not later
while [[ ${pid} -ne "" ]]; do
    #mem=`ps v | grep "^[ ]*${pid}" | awk '{print $8}'`
        #the previous does not work with MPI
        mem=`cat /proc/${pid}/status | grep VmRSS | awk '{print $2}'`
    if [[ ${mem} -gt ${maxmem} ]]; then
    	maxmem=${mem}
    fi
    sleep 1
    savedpid=${pid}
    pid=`pgrep -P ${ppid} -n -f $1`
done
wait ${savedpid} # don't wait, job is finished
exitstatus=$?   # catch the exit status of wait, the same of $@
echo -e "Memory usage for $@ is: ${maxmem} KB. Exit status: ${exitstatus}\n"
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5
 *
 * @category  phpDocumentor
 * @package   Core
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

error_reporting(E_ALL & ~E_STRICT & ~E_DEPRECATED);
require_once('PEAR/PackageFileManager2.php');
\PEAR::setErrorHandling(PEAR_ERROR_DIE);

/**
 * Creates a packager object with all basic options set.
 *
 * @param string   $original_file Path of the original package.xml.
 * @param string[] $options       Set of options to merge in.
 *
 * @return PEAR_Error|PEAR_PackageFileManager2
 */
function createPackager($original_file, $options = array())
{
    // merge the options with these defaults.
    $options = array_merge(
        array(
            'packagefile'       => 'package.xml',
            'filelistgenerator' => 'file',
            'simpleoutput'      => true,
            'baseinstalldir'    => '/phpDocumentor',
            'packagedirectory'  => dirname(__FILE__).'/../../',
            'clearcontents'     => true,
            'ignore'            => array(
                'build.properties',
                'build.xml',
                'build/*',
                'data/output/*',
                'data/log/*',
                'bin/utils/*',
                'src/XHProf/*',     // Profiling package
                'vendor/twig/twig/ext/*'
            ),
            'exceptions'        => array(
                'bin/phpdoc.php'   => 'script',
                'bin/phpdoc.bat'   => 'script',
                'phpdoc.dist.xml'  => 'php',
                'LICENSE'          => 'php',
                'phpunit.xml.dist' => 'php',
                'README'           => 'php',
                'VERSION'          => 'php',
                'vendor/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Autoload.php.in' => 'php',
                'vendor/phpunit/phpunit/PHPUnit/Framework/Assert/Functions.php.in' => 'php',
                'vendor/phpunit/phpunit/PHPUnit/Autoload.php.in' => 'php',
                'vendor/phpunit/php-token-stream/PHP/Token/Stream/Autoload.php.in' => 'php',
                'vendor/phpunit/php-timer/PHP/Timer/Autoload.php.in' => 'php',
                'vendor/phpunit/php-text-template/Text/Template/Autoload.php.in' => 'php',
                'vendor/phpunit/php-file-iterator/File/Iterator/Autoload.php.in' => 'php',
                'vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Autoload.php.in' => 'php',
            ),
            'installexceptions' => array(
                'bin/phpdoc.php' => '/',
                'bin/phpdoc.bat' => '/'
            ),
            'dir_roles'         => array(
                'bin'   => 'php',
                'docs'  => 'php',
                'data'  => 'php',
                'tests' => 'php',
                'src'   => 'php',
            ),
        ),
        $options
    );

    $packagexml = PEAR_PackageFileManager2::importOptions($original_file, $options);
    $packagexml->setPackageType('php');

    $packagexml->setPackage('phpDocumentor');
    $packagexml->setSummary(
        'PHP 5.3 compatible API Documentation generator aimed at projects of '
        .'all sizes and Continuous Integration'
    );
    $packagexml->setDescription(
<<<DESC
phpDocumentor is a Documentation Generation Application (DGA) for use with PHP applications.

It is capable of transforming the comments in your source code into a full API reference document.

phpDocumentor is build to be PHP 5.3 compatible, fast, having a low memory consumption and easily integratable into Continuous Integration.
DESC
    );
    $packagexml->setChannel('pear.phpdoc.org');
    $packagexml->setNotes(
        'Please see the CHANGELOG in the root of the application for the '
        .'latest changes'
    );

    $packagexml->setPhpDep('5.3.3');
    $packagexml->setPearinstallerDep('1.4.0');
    $packagexml->addReplacement(
        'bin/phpdoc.php',
        'pear-config',
        '/usr/bin/env php',
        'php_bin'
    );
    $packagexml->addGlobalReplacement('pear-config', '@php_bin@', 'php_bin');
    $packagexml->addReplacement(
        'bin/phpdoc.php',
        'pear-config',
        '@php_dir@',
        'php_dir'
    );

    $packagexml->addMaintainer(
        'lead',
        'mvriel',
        'Mike van Riel',
        'mike.vanriel@naenius.com'
    );
    $packagexml->addMaintainer(
        'lead',
        'ashnazg',
        'Chuck Burgess',
        'ashnazg@php.net'
    );
    $packagexml->setLicense(
        'MIT',
        'http://www.opensource.org/licenses/mit-license.html'
    );

    // Add this as a release, and generate XML content
    $packagexml->addRelease();
    $packagexml->setOSInstallCondition('windows');
    $packagexml->addInstallAs('bin/phpdoc.bat', 'phpdoc.bat');
    $packagexml->addInstallAs('bin/phpdoc.php', 'phpdoc.php');

    $packagexml->addRelease();
    $packagexml->addInstallAs('bin/phpdoc.php', 'phpdoc');
    $packagexml->addIgnoreToRelease('bin/phpdoc.bat');

    return $packagexml;
}


echo 'phpDocumentor PEAR Packager v1.0'.PHP_EOL;

if ($argc < 4) {
    echo <<<HELP

Usage:
  php package.php [version] [api-version] [stability] [make|nothing]

Description:
  The phpDocumentor packager generates a package.xml file and accompanying package.
  By specifying the version and stability you can tell the packager which version to package.

  A file will only be generated if the third parameter is the word 'make'; otherwise the output will be send to
  the command line.

HELP;
    exit(0);
}

$packager = createPackager('../../package.xml');

$packager->setReleaseVersion($argv[1]);
$packager->setAPIVersion($argv[2]);
$packager->setReleaseStability($argv[3]);
$packager->setAPIStability($argv[3]);

$packager->generateContents();
if (isset($argv[4]) && ($argv[4] == 'make')) {
    $packager->writePackageFile();
} else {
    $packager->debugPackageFile();
}

<?php

/*
 * This file is part of the Behat.
 * (c) Konstantin Kudryashov <ever.zet@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

define('BEHAT_PHP_BIN_PATH', getenv('PHP_PEAR_PHP_BIN') ?: '/usr/bin/env php');
define('BEHAT_BIN_PATH',     __FILE__);
define('BEHAT_VERSION',      'DEV');

function includeIfExists($file)
{
    if (file_exists($file)) {
        return include $file;
    }
}

if ((!$loader = includeIfExists(__DIR__.'/../vendor/autoload.php')) && (!$loader = includeIfExists(__DIR__.'/../../../autoload.php'))) {
    die(
        'You must set up the project dependencies, run the following commands:'.PHP_EOL.
        'curl -s http://getcomposer.org/installer | php'.PHP_EOL.
        'php composer.phar install'.PHP_EOL
    );
}

$app = new Behat\Behat\Console\BehatApplication(BEHAT_VERSION);
$app->run();

<?php
/**
 * PHP_CodeSniffer tokenises PHP code and detects violations of a
 * defined set of coding standards.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

error_reporting(E_ALL | E_STRICT);

// Optionally use PHP_Timer to print time/memory stats for the run.
// Note that the reports are the ones who actually print the data
// as they decide if it is ok to print this data to screen.
@include_once 'PHP/Timer.php';
if (class_exists('PHP_Timer', false) === true) {
    PHP_Timer::start();
}

if (is_file(dirname(__FILE__).'/../CodeSniffer/CLI.php') === true) {
    include_once dirname(__FILE__).'/../CodeSniffer/CLI.php';
} else {
    include_once 'PHP/CodeSniffer/CLI.php';
}

$phpcs = new PHP_CodeSniffer_CLI();
$phpcs->checkRequirements();

$numErrors = $phpcs->process();
if ($numErrors === 0) {
    exit(0);
} else {
    exit(1);
}

?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
    <xsl:import href="../abstract/sidebar.xsl" />
    <xsl:include href="../abstract/chrome.xsl" />
    <xsl:output indent="yes" method="html" />

    <xsl:param name="section.dashboard.show" />
    <xsl:template name="sidebar-header">
        <xsl:if test="not($title)">
            <img src="images/logo.png" id="sidebar-logo" alt="Logo" />
        </xsl:if>
        <h1>
            <xsl:if test="$title">
                <xsl:value-of select="$title" disable-output-escaping="yes" />
            </xsl:if>
        </h1>
        <div style="clear: both"></div>
        <xsl:if test="$section.dashboard.show != 'false'">
            <h3 id="sidebar-dashboard">
                <a href="{$root}content.html" target="content"
                   class="ui-state-default ui-helper-reset ui-accordion-header">Dashboard</a>
            </h3>
        </xsl:if>
    </xsl:template>

    <xsl:template name="content">
        <script type="text/javascript" src="{$root}js/jquery.cookie.js"></script>
        <script type="text/javascript" src="{$root}js/jquery.treeview.js"></script>
        <script type="text/javascript" src="{$root}js/sidebar.js"></script>

        <div id="sidebar">
            <div id="sidebar-header">
                <xsl:call-template name="sidebar-header" />
            </div>

            <div id="sidebar-nav">
                <xsl:call-template name="sidebar-sections" />
            </div>

            <div id="sidebar-footer">
                <xsl:call-template name="sidebar-footer" />
            </div>
        </div>
    </xsl:template>

</xsl:stylesheet>{
    "name": "phpdocumentor/template-new-black",
    "type": "phpdocumentor-template",
    "description": "Web 2.0 template with dark sidebar for phpDocumentor",
    "keywords": ["documentation", "template", "phpdoc"],
    "homepage": "http://www.phpdoc.org",
    "license": "MIT",
    "require": {
        "ext-xsl": "*",
        "phpdocumentor/template-abstract": "1.*",
        "phpdocumentor/unified-asset-installer": "~1.1"
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.9.4" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
    http://pear.php.net/dtd/tasks-1.0.xsd
    http://pear.php.net/dtd/package-2.0
    http://pear.php.net/dtd/package-2.0.xsd">
 <name>phpDocumentor_Template_new_black</name>
 <channel>pear.phpdoc.org</channel>
 <summary>The new_black template for phpDocumentor</summary>
 <description>This is the New Black look and feel for phpDocumentor</description>
 <lead>
  <name>Mike van Riel</name>
  <user />
  <email>mike.vanriel@naenius.com</email>
  <active>yes</active>
 </lead>
 <date>2012-04-01</date>
 <time>10:33:20</time>
 <version>
  <release>1.0.4</release>
  <api>1.0.4</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license uri="http://www.opensource.org/licenses/mit-license.html">MIT</license>
 <notes>
Automatically generated by the phpDocumentor packager
 </notes>
 <contents>
  <dir baseinstalldir="/phpDocumentor/data/templates/new_black" name="/">
   <dir name="css">
    <dir name="images">
     <file name="ajax-loader.gif" role="php" />
     <file name="file.gif" role="php" />
     <file name="folder-closed.gif" role="php" />
     <file name="folder.gif" role="php" />
     <file name="minus.gif" role="php" />
     <file name="plus.gif" role="php" />
     <file name="treeview-black-line.gif" role="php" />
     <file name="treeview-black.gif" role="php" />
     <file name="treeview-default-line.gif" role="php" />
     <file name="treeview-default.gif" role="php" />
     <file name="treeview-famfamfam-line.gif" role="php" />
     <file name="treeview-famfamfam.gif" role="php" />
     <file name="treeview-gray-line.gif" role="php" />
     <file name="treeview-gray.gif" role="php" />
     <file name="treeview-red-line.gif" role="php" />
     <file name="treeview-red.gif" role="php" />
    </dir> <!-- /css/images -->
    <dir name="phpdoc">
     <dir name="images">
      <dir name="icons">
       <file name="book.png" role="php" />
       <file name="chart.png" role="php" />
       <file name="chart15x12.png" role="php" />
       <file name="dashboard.png" role="php" />
       <file name="files.png" role="php" />
       <file name="namespaces.png" role="php" />
       <file name="packages.png" role="php" />
       <file name="reports.png" role="php" />
       <file name="reports9x12.png" role="php" />
      </dir> <!-- /css/phpdoc/images/icons -->
      <file name="ui-bg_glass_55_1c1c1c_1x400.png" role="php" />
      <file name="ui-bg_hexagon_15_232325_12x10.png" role="php" />
      <file name="ui-bg_highlight-hard_40_232325_1x100.png" role="php" />
      <file name="ui-bg_highlight-hard_65_232325_1x100.png" role="php" />
      <file name="ui-bg_highlight-hard_100_f9f9f9_1x100.png" role="php" />
      <file name="ui-bg_highlight-soft_40_aaaaaa_1x100.png" role="php" />
      <file name="ui-bg_highlight-soft_50_aaaaaa_1x100.png" role="php" />
      <file name="ui-bg_inset-hard_45_cd0a0a_1x100.png" role="php" />
      <file name="ui-bg_inset-hard_55_ffeb80_1x100.png" role="php" />
      <file name="ui-icons_4ca300_256x240.png" role="php" />
      <file name="ui-icons_222222_256x240.png" role="php" />
      <file name="ui-icons_bbbbbb_256x240.png" role="php" />
      <file name="ui-icons_ededed_256x240.png" role="php" />
      <file name="ui-icons_ffcf29_256x240.png" role="php" />
      <file name="ui-icons_ffffff_256x240.png" role="php" />
     </dir> <!-- /css/phpdoc/images -->
     <file name="jquery-ui-1.8.16.custom.css" role="php" />
    </dir> <!-- /css/phpdoc -->
    <file name="api-content.css" role="php" />
    <file name="default.css" role="php" />
    <file name="jquery-ui.css" role="php" />
    <file name="jquery.treeview.css" role="php" />
    <file name="navigation.css" role="php" />
    <file name="template.css" role="php" />
   </dir> <!-- /css -->
   <dir name="js">
    <file name="template.js" role="php" />
   </dir> <!-- /js -->
   <dir name="search">
    <file name="ajax.xsl" role="php" />
    <file name="simple.xsl" role="php" />
   </dir> <!-- /search -->
   <file name="README.md" role="php" />
   <file name="sidebar.xsl" role="php" />
   <file name="template.xml" role="php" />
  </dir> <!-- / -->
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.2.6</min>
   </php>
   <pearinstaller>
    <min>1.4.0</min>
   </pearinstaller>
   <package>
    <name>PEAR</name>
    <channel>pear.php.net</channel>
    <min>1.4.0</min>
   </package>
   <package>
    <name>phpDocumentor</name>
    <channel>pear.phpdoc.org</channel>
    <min>0.17.0</min>
   </package>
   <package>
    <name>phpDocumentor_Template_abstract</name>
    <channel>pear.phpdoc.org</channel>
    <min>1.0.3</min>
   </package>
  </required>
 </dependencies>
 <phprelease />
 <changelog>
  <release>
   <version>
    <release>1.0.4</release>
    <api>1.0.4</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2012-04-01</date>
   <license uri="http://www.opensource.org/licenses/mit-license.html">MIT</license>
   <notes>
Automatically generated by the phpDocumentor packager
   </notes>
  </release>
 </changelog>
</package>
function filterElements() {
    inherited = !$('#show-inherited').hasClass('deselected');
    public = !$('#show-public').hasClass('deselected');
    protected = !$('#show-protected').hasClass('deselected');
    private = !$('#show-private').hasClass('deselected');

    $('div.public').each(function(index, val) {
        $(val).toggle(public && !($(val).hasClass('inherited_from') && !inherited));
    });
    $('div.protected').each(function(index, val) {
        $(val).toggle(protected && !($(val).hasClass('inherited_from') && !inherited));
    });
    $('div.private').each(function(index, val) {
        $(val).toggle(private && !($(val).hasClass('inherited_from') && !inherited));
    });
}

$(document).ready(function() {
    $('#show-public, #show-protected, #show-private, #show-inherited')
            .css('cursor', 'pointer')
            .click(function() {
                $(this).toggleClass('deselected');
                if ($(this).hasClass('deselected')) {
                    $(this).fadeTo('fast', '0.4');
                } else {
                    $(this).fadeTo('fast', '1.0');
                }
                filterElements();
                return false;
            });
    $('#show-protected, #show-private').click();

    $('#file-nav-box').show();

    if ($(".filetree").treeview)
    {
        $(".filetree").treeview({
            collapsed:true,
            persist:"cookie"
        });
    }

    $("#accordion").accordion({
        collapsible:true,
        autoHeight:false,
        fillSpace:true
    });

    $("#marker-accordion").accordion({
        collapsible:true,
        autoHeight:false
    });

    $(".tabs").tabs();

    jQuery('.sidebar-nav-tree').before('<div class="search-bar"> \
    <a href="#"><img src="images/collapse_all.png" title="Collapse all" alt="Collapse all" /></a> \
    <a href="#"><img src="images/expand_all.png" title="Expand all" alt="Expand all" /></a> \
    <div><input type="search" /></div> \
</div>');

    jQuery('.search-bar').find('a:eq(0)').click(function() {
        jQuery(this).parent().next().find('.collapsable-hitarea').click();
        return false;
    });
    jQuery('.search-bar').find('a:eq(1)').click(function() {
        jQuery(this).parent().next().find('.expandable-hitarea').click();
        return false;
    });
    jQuery('.search-bar input').keyup(function() {
        tree_search(this);
    });

    $('div.code-tabs').hide();
    $('a.gripper').show();
    $('div.code-tabs:empty').prevAll('a.gripper').html('');

    $('a.gripper').click(function() {
        $(this).nextAll('div.code-tabs').slideToggle();
        $(this).children('img').toggle();
        return false;
    });

    $('code.title').click(function() {
        $(this).nextAll('div.code-tabs').slideToggle();
        $(this).prev().children('img').toggle();
    });

});.treeview, .treeview ul {
    padding: 0;
    margin: 0;
    list-style: none;
}

.treeview ul {
    margin-top: 4px;
}

.treeview .hitarea {
    background: url(images/treeview-default.gif) -64px -25px no-repeat;
    height: 16px;
    width: 16px;
    margin-left: -16px;
    float: left;
    cursor: pointer;
}

/* fix for IE6 */
* html .hitarea {
    display: inline;
    float:none;
}

.treeview li {
    margin: 0;
    padding: 3px 0pt 3px 16px;
}

.treeview a.selected {
    background-color: #eee;
}

#treecontrol { margin: 1em 0; display: none; }

.treeview .hover { color: red; cursor: pointer; }

.treeview li { background: url(images/treeview-default-line.gif) 0 0 no-repeat; }
.treeview li.collapsable, .treeview li.expandable { background-position: 0 -176px; }

.treeview .expandable-hitarea { background-position: -80px -3px; }

.treeview li.last { background-position: 0 -1766px }
.treeview li.lastCollapsable, .treeview li.lastExpandable { background-image: url(images/treeview-default.gif); }
.treeview li.lastCollapsable { background-position: 0 -111px }
.treeview li.lastExpandable { background-position: -32px -67px }

.treeview div.lastCollapsable-hitarea, .treeview div.lastExpandable-hitarea { background-position: 0; }

.treeview-red li { background-image: url(images/treeview-red-line.gif); }
.treeview-red .hitarea, .treeview-red li.lastCollapsable, .treeview-red li.lastExpandable { background-image: url(images/treeview-red.gif); }

.treeview-black li { background-image: url(images/treeview-black-line.gif); }
.treeview-black .hitarea, .treeview-black li.lastCollapsable, .treeview-black li.lastExpandable { background-image: url(images/treeview-black.gif); }

.treeview-gray li { background-image: url(images/treeview-gray-line.gif); }
.treeview-gray .hitarea, .treeview-gray li.lastCollapsable, .treeview-gray li.lastExpandable { background-image: url(images/treeview-gray.gif); }

.treeview-famfamfam li { background-image: url(images/treeview-famfamfam-line.gif); }
.treeview-famfamfam .hitarea, .treeview-famfamfam li.lastCollapsable, .treeview-famfamfam li.lastExpandable { background-image: url(images/treeview-famfamfam.gif); }

.treeview .placeholder {
    background: url(images/ajax-loader.gif) 0 0 no-repeat;
    height: 16px;
    width: 16px;
    display: block;
}

ul.deadtree
{
  padding:    0;
  margin:     0;
  list-style: none;
}
.filetree li, .deadtree li, .sidebar-nav-tree li { padding: 3px 0 2px 16px; }

.filetree span.folder, .filetree span.file,
.deadtree span.folder, .deadtree span.file,
.sidebar-nav-tree span.folder, .sidebar-nav-tree span.file
{
  padding: 1px 0 1px 16px; display: block;
}

.filetree span.class, .deadtree span.class,
.filetree span.function, .deadtree span.function,
.filetree span.method, .deadtree span.method,
.filetree span.constant, .deadtree span.constant,
.filetree span.property, .deadtree span.property,
.filetree span.interface, .deadtree span.interface,
.sidebar-nav-tree span.class,
.sidebar-nav-tree span.function,
.sidebar-nav-tree span.method,
.sidebar-nav-tree span.constant,
.sidebar-nav-tree span.property,
.sidebar-nav-tree span.interface
{
  padding: 1px 0 1px 18px; display: block;
}

.filetree span.folder, .deadtree span.folder, .sidebar-nav-tree span.folder { background: url(images/folder.gif) 0 0 no-repeat; }
.filetree li.expandable span.folder, .sidebar-nav-tree li.expandable span.folder { background: url(images/folder-closed.gif) 0 0 no-repeat; }
.filetree span.file, .sidebar-nav-tree span.file { background: url(images/file.gif) 0 0 no-repeat; }
.filetree span.class, .sidebar-nav-tree span.class { background: url(../images/icons/class.png) 0 0 no-repeat; }
.filetree span.interface, .sidebar-nav-tree span.interface { background: url(../images/icons/interface.png) 0 0 no-repeat; }
.filetree span.function, .sidebar-nav-tree span.function { background: url(../images/icons/function.png) 0 0 no-repeat; }
.filetree span.method, .sidebar-nav-tree span.method { background: url(../images/icons/function.png) 0 0 no-repeat; }
.filetree span.property, .sidebar-nav-tree span.property { background: url(../images/icons/property.png) 0 0 no-repeat; }
.filetree span.constant, .sidebar-nav-tree span.constant { background: url(../images/icons/constant.png) 0 0 no-repeat; }
html, body, #page
{
  height: 99.9%;
  width:  100%;
}

#frameset {
    overflow:hidden;
}

body
{
    font: 80% / 1.5em Arial, Helvetica, "DejaVu Sans", "Liberation sans", "Bitstream Vera Sans", sans-serif
}

#db-header, #menubar
{
  height: 1px;
}

#contents {
    margin-left: 260px;
}

#sidebar {
    height: 100%;
    width: 100%;
    background: #232325;
    overflow: auto;
    color: #f9f9ff
}

#sidebar-header {
    border-bottom: 1px solid #333333;
    padding: 10px;
    margin-bottom: 10px;
}

#sidebar-footer {
    position: relative;
    bottom: 0;
    font-size: 0.7em;
    color: gray;
    padding: 15px 5px 5px;
    border-top: 1px solid #333333;
    margin-top: 10px;
}

#sidebar-footer a {
    color: gray;
}

#sidebar-header h1 {
    font-size: 1.2em;
    padding: 0;
    margin: 0;
    display: inline;
}

#sidebar-logo {
    float: left;
    padding-right: 10px;
}

#sidebar-nav h3 {
    width: 100%;
}

#sidebar-nav h3 img {
    float: right;
    height: 22px;
    padding-top: 6px;
    padding-right: 7px;
}

#sidebar-nav h3#sidebar-files img {
    height: auto;
    margin-top: 2px;
}

#sidebar-nav {
    font-size: 1.1em;
}

.ui-accordion-header {
    background-image: none;
    border: none;
    font-size: 1.1em;
}

.ui-accordion .sidebar-section {
    overflow: auto;
    border-bottom-right-radius: 10px;
}

.ui-accordion .ui-accordion-content {
    padding: 0px;
    padding-bottom: 10px;
}

.sidebar-section div.search-bar {
    height: 19px;
    border-bottom: 1px solid silver;
    background: #f9f9f9;
    padding: 6px 3px 4px 3px;
}

.sidebar-section ul {
    margin: 10px 10px 0px 32px;
}

.sidebar-section ul ul, .sidebar-section ul.sidebar-nav-tree {
    margin: 0px;
}

.sidebar-section div.search-bar div {
    padding-right: 48px;
}

.sidebar-section div.search-bar a {
    float: right;
    margin-right: 5px;
}

.sidebar-section div.search-bar div input {
    border-radius: 3px;
    background: white url('images/search.gif') no-repeat right top;
}

#sidebar, #contents {
    height:100%;
}

#sidebar iframe, #contents iframe
{
  height: 100%;
  width:  100%;
  border: none;
}

.footer, #footer
{
  display: block;
  clear: both;
}

#accordion table, #marker-accordion table
{
    font-size: 0.95em;
}

#marker-accordion h3 a small
{
    display:        block;
    float:          right;
    background:     gray;
    height:         18px;
    line-height:    18px;
    padding:        0px 5px;
    border-radius:  3px;
    color:          white;
    font-weight:    bold;
}

ul#menu
{
  background:         black;
  display:            block;
  height:             34px;
  line-height:        22px;
  padding:            0px;
  margin:             0px;
  font-size:          0.8em;
}

ul#menu li
{
  padding:      0px 10px;
  margin:       5px 0px;
  border-right: 1px solid gray;
  display:      block;
  float:        left;
}

ul#menu li:last-of-type
{
  border: none;
}

ul#menu li a
{
  color:   white;
  display: block;
}

ul.filetree li a
{
  display: block;
}

ul.filetree li a small
{
  display: none;
}

ul.filetree li a:hover small
{
  display: inline;
  color:   gray;
}

.ui-resizable-helper
{
    border-right: 40px solid silver;
    margin-right: -40px;

    /* 20% opacity; zoom is required for IE */
    zoom: 1;
    filter: alpha(opacity = 20);
    opacity: 0.2;
}

.splitterMask {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;
    background: transparent;
    z-index: 20000;
}

.vsplitbar {
    width: 5px;
    background: #f0f0f0;
}

.resizable {
    margin: 0px;
    padding: 0px;
}

div.success_notification
{
    margin: 5px;
    padding: 5px;
    padding-left: 35px;
    background: #f9f9f9 url('../images/icons/ok.png') no-repeat 5px center;
    border: 1px solid silver;
}body.nav
{
  background: #d9d9d9;
}

.section h1
{
  font-size:      1.4em;
  padding-bottom: 5px;
}

img#search_box_icon
{
  display:    none;
  position:   absolute;
  top:        18px;
  right:      142px;
}

img#search_box_clear
{
  position:     absolute;
  display:      none;
  cursor:       pointer;
  top:          20px;
  right:        14px;
}

input#search_box
{
  float:              right;
  margin-top:         5px;
  display:            none;
  width:              150px;
  border:             1px solid silver;
  border-radius:      5px;
  -moz-border-radius: 5px;
  padding-right:      20px;
  font-size:          1em;
  line-height:        1em;
}

div.results
{
  border-radius:      10px;
  -moz-border-radius: 10px;
  background:         #f0f0f0;
  margin:             10px;
}

div.results a.result
{
  border-bottom:    1px solid silver;
  display:          block;
  padding:          7px 5px;
  color:            black;
  background:       transparent url('arrow_right.gif') right center no-repeat;
  text-decoration:  none;
}

div.results a.result:hover
{
  color: blue;
}

div.results a.result:last-of-type
{
  border: none;
}

div.results a.result img
{
  border: 0px;
}

#sidebar-nav h3
{
    padding: 10px 0;
}

.ui-accordion .ui-accordion-header .ui-icon
{
    position: static;
    margin-top: 0;
    float: left;
}PNG

   IHDR      d   G,Z`   4IDATcطo&!DF00000,Bh##`4 K<b    IENDB`PNG

   IHDR      d   G,Z`   -IDATc8|&!D`````~.N Bh,    IENDB`PNG

   IHDR      d   G,Z`   BIDATݏA
0Ä_]I]ca>1S Z(3mgcwGUB ,1e!U    IENDB`PNG

   IHDR        oX
   FIDAT8ϱ	@CQ%<\H@P
af6Wݛ$(	SUuG҃8c^ }n7Q    IENDB`PNG

   IHDR         IJ   PLTE&ha   NtRNS 2P."Tp@f` <BHJZ&0R,4j8D|($
blߝF>n~hhH  IDATx]b۶H儒-{iZK:glkn-tIqq?  E$dK>$>; PZ sVh!Sy0E0}H)-tkoܪKp\RϠ .E7
)*V;~PeBx*,=$zDؾ  JҸٻ 9{ ǸHpqW@"2'B[$ @TiH/b٥96!XHq`DE*R HV!%;"
i]dddddddd4y5 	Rb@(8CdŪݡ,@T@ibrq0alX!pe,	=4bW {
5Ƭhu~(Q^@3="b5XC@JCT76q_5@,r	šɩD)T|O@
ON-ՙ	[n@RXIm݋(F @?=0puL;g$@6η
K`>п @h գKVn"a"%l@.v$/U^G:#`` uTtK~ŋZ5T%kxk]\*Q,҇B44OXK|yg+_M(lоEO
 V$T1BXb-|?@ fBXr%'@ҹA\IJ,}BBc\V
rh(]tI^}oצoS3	";ʙb}"߰	){b$Gwwݾab")T@pF_er6JvШ"mޭM-d76x˰6ӥ;/`>KrP\_^u1%OTM.} Q3.Nس} )>-w`a+sy$t)NbFFFFBejnNVn4,A*X*5>PGa3	{oB&<L[Nc.öi=` Q@d
͆I.Il`\t[< Cit484-r+f쑱BCB MH	iy }>rxp|z;BǏ;burcK4tz1G~`ؚK|	̔>ۡO$~
Ao)0pzz
} i `;ADm8n:cfA@s7L  Z/..h8or?N93B~o_'` opO-:TG	L;7]`B%˛>*wTpM 0H}&t^1'Oqr'2P͡+z,tIW''|en=ǳgRm[NStK{҉mؓVt6ҲR`ζN&}B	U(r<qȁVyrrA**دzg6D#	YP`vs~(zMle|uQa*}+TRXc"+*NlNhcFt<N+;-}،Xtٕ$à^|uv*~'E_51qs*R`OΒ9#x449#WHۏZ)]0`p<ߝNoY{476ǹ>ۗ&1%Q''?l׸+&r{jN಻4)`N狌.߭ ǣ)q	2?n3Hb`} .`pqY1e_bu7e+N_F(DT,L}LLrmP5|x芥1cx DAb`M(7NED~<v\	%,ߚ/pR~/^lnp7t0_0l4_b0MWΦjmбɎl
|reȫ`B-v.iRox}
)%#`ЂR5CA2sua sYy3=jaeoI7~.plA΃
`O)	^>Mz	+4BXd.Mzv͈Pd8p<6?8N*x.6ڍ6G FZ)O	!lSshssNp8`'0/<s}.@Ǩs7ξO۟VDa5a v]m1+3 y6۠>@u50Ps51==p *KVҫ܂ݻc$N4(Xr2###c-賟Lδ>]5.sYs1f0;'̨Yg銛{@9	`aC(=%bo2=n1	jBoS$n#m =i0ci9}oI	qT] W%.(؅]z\x
f"]o'u䫵tk{v;A C3ֆwwR_#X(xҋ/q%Whpk_IX'b/fXKi"#####QCLi2t5L 0
QiH2;yTOok;עٶ`RNg{zy! Kxm?A(vU~mL(`o/!nmX-{v [ dw=n「sdwzn(}Oy~m
?XU;, V'+V&JRZ]᧭:zC'-߆@y4u`Vۓwъ#zP@QN>2/{\o) W~a3xLw:_Q;=pּdt\'8~3SRP6y+XQ*޺r
̗ѭ*޺r
gl/\U^u$|mbVnw\V|D͊NVNy7 k<;/E}?E*ǳgO ~g/96f
cD}%g$QG7o) UJo,O@0߾Q(;bw:5	NwRN5Iy'K?}:9mֽ*@f@jU9mҫÍ{$ ؗ}dFp|%!DdF>}G{@FFFFFFƦQܞH 
3
u	Mo~vy}mwz<7nP9rWku=|_nz쿳}@IXn?s<uP    IENDB`PNG

   IHDR         IJ   PLTE   NtRNS 2P."Tp@f` <BHJZ&0R,4j8D|($
blߝF>n~hhH  IDATx]b۶H儒-{iZK:glkn-tIqq?  E$dK>$>; PZ sVh!Sy0E0}H)-tkoܪKp\RϠ .E7
)*V;~PeBx*,=$zDؾ  JҸٻ 9{ ǸHpqW@"2'B[$ @TiH/b٥96!XHq`DE*R HV!%;"
i]dddddddd4y5 	Rb@(8CdŪݡ,@T@ibrq0alX!pe,	=4bW {
5Ƭhu~(Q^@3="b5XC@JCT76q_5@,r	šɩD)T|O@
ON-ՙ	[n@RXIm݋(F @?=0puL;g$@6η
K`>п @h գKVn"a"%l@.v$/U^G:#`` uTtK~ŋZ5T%kxk]\*Q,҇B44OXK|yg+_M(lоEO
 V$T1BXb-|?@ fBXr%'@ҹA\IJ,}BBc\V
rh(]tI^}oצoS3	";ʙb}"߰	){b$Gwwݾab")T@pF_er6JvШ"mޭM-d76x˰6ӥ;/`>KrP\_^u1%OTM.} Q3.Nس} )>-w`a+sy$t)NbFFFFBejnNVn4,A*X*5>PGa3	{oB&<L[Nc.öi=` Q@d
͆I.Il`\t[< Cit484-r+f쑱BCB MH	iy }>rxp|z;BǏ;burcK4tz1G~`ؚK|	̔>ۡO$~
Ao)0pzz
} i `;ADm8n:cfA@s7L  Z/..h8or?N93B~o_'` opO-:TG	L;7]`B%˛>*wTpM 0H}&t^1'Oqr'2P͡+z,tIW''|en=ǳgRm[NStK{҉mؓVt6ҲR`ζN&}B	U(r<qȁVyrrA**دzg6D#	YP`vs~(zMle|uQa*}+TRXc"+*NlNhcFt<N+;-}،Xtٕ$à^|uv*~'E_51qs*R`OΒ9#x449#WHۏZ)]0`p<ߝNoY{476ǹ>ۗ&1%Q''?l׸+&r{jN಻4)`N狌.߭ ǣ)q	2?n3Hb`} .`pqY1e_bu7e+N_F(DT,L}LLrmP5|x芥1cx DAb`M(7NED~<v\	%,ߚ/pR~/^lnp7t0_0l4_b0MWΦjmбɎl
|reȫ`B-v.iRox}
)%#`ЂR5CA2sua sYy3=jaeoI7~.plA΃
`O)	^>Mz	+4BXd.Mzv͈Pd8p<6?8N*x.6ڍ6G FZ)O	!lSshssNp8`'0/<s}.@Ǩs7ξO۟VDa5a v]m1+3 y6۠>@u50Ps51==p *KVҫ܂ݻc$N4(Xr2###c-賟Lδ>]5.sYs1f0;'̨Yg銛{@9	`aC(=%bo2=n1	jBoS$n#m =i0ci9}oI	qT] W%.(؅]z\x
f"]o'u䫵tk{v;A C3ֆwwR_#X(xҋ/q%Whpk_IX'b/fXKi"#####QCLi2t5L 0
QiH2;yTOok;עٶ`RNg{zy! Kxm?A(vU~mL(`o/!nmX-{v [ dw=n「sdwzn(}Oy~m
?XU;, V'+V&JRZ]᧭:zC'-߆@y4u`Vۓwъ#zP@QN>2/{\o) W~a3xLw:_Q;=pּdt\'8~3SRP6y+XQ*޺r
̗ѭ*޺r
gl/\U^u$|mbVnw\V|D͊NVNy7 k<;/E}?E*ǳgO ~g/96f
cD}%g$QG7o) UJo,O@0߾Q(;bw:5	NwRN5Iy'K?}:9mֽ*@f@jU9mҫÍ{$ ؗ}dFp|%!DdF>}G{@FFFFFFƦQܞH 
3
u	Mo~vy}mwz<7nP9rWku=|_nz쿳}@IXn?s<uP    IENDB`PNG

   IHDR         Í   	pHYs       
OiCCPPhotoshop ICC profile  xڝSgTS=BKKoR RB&*!	J!QEEȠQ,
!{kּ>H3Q5B.@
$p d!s# ~<<+" x M0B\t8K @zB @F&S  `cb P- `' { [!  eD h; VE X0 fK9 - 0IWfH    0Q) { `##x  FW<+*  x<$9E[-qWW.(I+6aa@.y24  x6_-"bbϫp@  t~,/;m%h^uf@ Wp~<<EJB[aW}g_Wl~<$2]GLϒ	bG"IbX*QqD2"B)%d,>5 j>{-]cK'Xt  o(hw?G% fIq  ^D$.Tʳ?  D*A,`6B$BB
dr`)B(Ͱ*`/@4Qhp.U=pa(	Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F; 2G1Q=C7Fdt1r=6Ыhڏ>C03l0.B8,	c˱"VcϱwE	6wB aAHXLXNH $4	7	Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![
b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGwǈg(gwLӋT071oUX**|
J&*/TުUUT^S}FU3S	ԖUPSSg;goT?~YYLOCQ_ cx,!ku5&|v*=9C3J3WRf?qtN	(~))4L1e\kXHQG6EYAJ'\'GgSSݧ
M=:.kDwn^Loy}/TmGX$<5qo</QC]@Caaᄑ<FFi\$mmƣ&&!&KMMRM);L;L֙͢5=12כ߷`ZxZ,eIZYnZ9YXUZ]F%ֻNNgðɶۮm}agbgŮ}}=Z~sr:V:ޚΜ?}/gX3)iSGggs󈋉K.>.ȽJtq]zۯ6iܟ4)Y3sCQ?0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz %gA[z|!?:eAAA!h쐭!ΑiP~aa~'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl{/]py.,:@LN8A*%w%
yg"/6шC\*NH*Mz쑼5y$3,幄'LLݛ:v m2=:1qB!Mggfvˬen/kY-
BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9<qy
+V<*mOW~&zMk^ʂkU
}]OX/Yߵa>(xoʿܔĹdff-[nڴVE/(ۻC<e;?TTTT6ݵan{4[>ɾUUMfeI?m]Nmq#׹=TR+Gw-6U#pDy	:v{vg/jBFS[b[O>zG4<YyJTiӓgό}~.`ۢ{cjotE;;\tWW:_mt<Oǻ\kz{f7y՞9=ݽzo~r'˻w'O_@AC݇?[jwGCˆ8>99?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-    cHRM  z%        u0  `  :  o_F   zIDATxA WbVzP8+Qm2CL%.JVpHyN!'
|QPOwu[$/3{7ͶlZ   MN    IENDB`PNG

   IHDR         rߔ   	pHYs       
OiCCPPhotoshop ICC profile  xڝSgTS=BKKoR RB&*!	J!QEEȠQ,
!{kּ>H3Q5B.@
$p d!s# ~<<+" x M0B\t8K @zB @F&S  `cb P- `' { [!  eD h; VE X0 fK9 - 0IWfH    0Q) { `##x  FW<+*  x<$9E[-qWW.(I+6aa@.y24  x6_-"bbϫp@  t~,/;m%h^uf@ Wp~<<EJB[aW}g_Wl~<$2]GLϒ	bG"IbX*QqD2"B)%d,>5 j>{-]cK'Xt  o(hw?G% fIq  ^D$.Tʳ?  D*A,`6B$BB
dr`)B(Ͱ*`/@4Qhp.U=pa(	Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F; 2G1Q=C7Fdt1r=6Ыhڏ>C03l0.B8,	c˱"VcϱwE	6wB aAHXLXNH $4	7	Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![
b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGwǈg(gwLӋT071oUX**|
J&*/TުUUT^S}FU3S	ԖUPSSg;goT?~YYLOCQ_ cx,!ku5&|v*=9C3J3WRf?qtN	(~))4L1e\kXHQG6EYAJ'\'GgSSݧ
M=:.kDwn^Loy}/TmGX$<5qo</QC]@Caaᄑ<FFi\$mmƣ&&!&KMMRM);L;L֙͢5=12כ߷`ZxZ,eIZYnZ9YXUZ]F%ֻNNgðɶۮm}agbgŮ}}=Z~sr:V:ޚΜ?}/gX3)iSGggs󈋉K.>.ȽJtq]zۯ6iܟ4)Y3sCQ?0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz %gA[z|!?:eAAA!h쐭!ΑiP~aa~'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl{/]py.,:@LN8A*%w%
yg"/6шC\*NH*Mz쑼5y$3,幄'LLݛ:v m2=:1qB!Mggfvˬen/kY-
BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9<qy
+V<*mOW~&zMk^ʂkU
}]OX/Yߵa>(xoʿܔĹdff-[nڴVE/(ۻC<e;?TTTT6ݵan{4[>ɾUUMfeI?m]Nmq#׹=TR+Gw-6U#pDy	:v{vg/jBFS[b[O>zG4<YyJTiӓgό}~.`ۢ{cjotE;;\tWW:_mt<Oǻ\kz{f7y՞9=ݽzo~r'˻w'O_@AC݇?[jwGCˆ8>99?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-    cHRM  z%        u0  `  :  o_F  >IDATxڴVm0uw6@nLd$   ޠ#<uVP<-"Ed>cD
   ^8W Z 8ɀMiϦ
Esa-}Kp`-~,U<VM:Gᰬǲͤ9YA`:לVaAY@L9[+%Zuz(
n >UwgV ׌gCE:6REp<yfKY;'Hzv6`$M(>2vt&ρ
$ᝧtһq7/ANIF9-RCB#epfv0ir0O>;!Q5#* 	 +чQ`ѷNYav#W9H Sx33ԝ|)ÓT]AR2$+v6gzWu# v9v
u5it-F4byCFTι暨e]E8dOܸ׻PA$%? $]    IENDB`PNG

   IHDR         e/O]   tEXtSoftware Adobe ImageReadyqe<   RIDATxbtqqaP|&Hlr1Ð2H%34Gx4Gx4GxHs ܣ슱a    IENDB`PNG

   IHDR         }\   	pHYs       
OiCCPPhotoshop ICC profile  xڝSgTS=BKKoR RB&*!	J!QEEȠQ,
!{kּ>H3Q5B.@
$p d!s# ~<<+" x M0B\t8K @zB @F&S  `cb P- `' { [!  eD h; VE X0 fK9 - 0IWfH    0Q) { `##x  FW<+*  x<$9E[-qWW.(I+6aa@.y24  x6_-"bbϫp@  t~,/;m%h^uf@ Wp~<<EJB[aW}g_Wl~<$2]GLϒ	bG"IbX*QqD2"B)%d,>5 j>{-]cK'Xt  o(hw?G% fIq  ^D$.Tʳ?  D*A,`6B$BB
dr`)B(Ͱ*`/@4Qhp.U=pa(	Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F; 2G1Q=C7Fdt1r=6Ыhڏ>C03l0.B8,	c˱"VcϱwE	6wB aAHXLXNH $4	7	Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![
b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGwǈg(gwLӋT071oUX**|
J&*/TުUUT^S}FU3S	ԖUPSSg;goT?~YYLOCQ_ cx,!ku5&|v*=9C3J3WRf?qtN	(~))4L1e\kXHQG6EYAJ'\'GgSSݧ
M=:.kDwn^Loy}/TmGX$<5qo</QC]@Caaᄑ<FFi\$mmƣ&&!&KMMRM);L;L֙͢5=12כ߷`ZxZ,eIZYnZ9YXUZ]F%ֻNNgðɶۮm}agbgŮ}}=Z~sr:V:ޚΜ?}/gX3)iSGggs󈋉K.>.ȽJtq]zۯ6iܟ4)Y3sCQ?0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz %gA[z|!?:eAAA!h쐭!ΑiP~aa~'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl{/]py.,:@LN8A*%w%
yg"/6шC\*NH*Mz쑼5y$3,幄'LLݛ:v m2=:1qB!Mggfvˬen/kY-
BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9<qy
+V<*mOW~&zMk^ʂkU
}]OX/Yߵa>(xoʿܔĹdff-[nڴVE/(ۻC<e;?TTTT6ݵan{4[>ɾUUMfeI?m]Nmq#׹=TR+Gw-6U#pDy	:v{vg/jBFS[b[O>zG4<YyJTiӓgό}~.`ۢ{cjotE;;\tWW:_mt<Oǻ\kz{f7y՞9=ݽzo~r'˻w'O_@AC݇?[jwGCˆ8>99?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-    cHRM  z%        u0  `  :  o_F  IDATx068IX:#lPR	/}6}ZC0L9PX2.-IfdΒg"	]n_Y+%`xn@%ڢ$ޏ͑ijn#	m#i-JK 6pƑ#< ^?m@b8)мH-[*M5	-o*E~hwF.{7|// SE_s    IENDB`PNG

   IHDR         ^   	pHYs       
OiCCPPhotoshop ICC profile  xڝSgTS=BKKoR RB&*!	J!QEEȠQ,
!{kּ>H3Q5B.@
$p d!s# ~<<+" x M0B\t8K @zB @F&S  `cb P- `' { [!  eD h; VE X0 fK9 - 0IWfH    0Q) { `##x  FW<+*  x<$9E[-qWW.(I+6aa@.y24  x6_-"bbϫp@  t~,/;m%h^uf@ Wp~<<EJB[aW}g_Wl~<$2]GLϒ	bG"IbX*QqD2"B)%d,>5 j>{-]cK'Xt  o(hw?G% fIq  ^D$.Tʳ?  D*A,`6B$BB
dr`)B(Ͱ*`/@4Qhp.U=pa(	Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F; 2G1Q=C7Fdt1r=6Ыhڏ>C03l0.B8,	c˱"VcϱwE	6wB aAHXLXNH $4	7	Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![
b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGwǈg(gwLӋT071oUX**|
J&*/TުUUT^S}FU3S	ԖUPSSg;goT?~YYLOCQ_ cx,!ku5&|v*=9C3J3WRf?qtN	(~))4L1e\kXHQG6EYAJ'\'GgSSݧ
M=:.kDwn^Loy}/TmGX$<5qo</QC]@Caaᄑ<FFi\$mmƣ&&!&KMMRM);L;L֙͢5=12כ߷`ZxZ,eIZYnZ9YXUZ]F%ֻNNgðɶۮm}agbgŮ}}=Z~sr:V:ޚΜ?}/gX3)iSGggs󈋉K.>.ȽJtq]zۯ6iܟ4)Y3sCQ?0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz %gA[z|!?:eAAA!h쐭!ΑiP~aa~'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl{/]py.,:@LN8A*%w%
yg"/6шC\*NH*Mz쑼5y$3,幄'LLݛ:v m2=:1qB!Mggfvˬen/kY-
BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9<qy
+V<*mOW~&zMk^ʂkU
}]OX/Yߵa>(xoʿܔĹdff-[nڴVE/(ۻC<e;?TTTT6ݵan{4[>ɾUUMfeI?m]Nmq#׹=TR+Gw-6U#pDy	:v{vg/jBFS[b[O>zG4<YyJTiӓgό}~.`ۢ{cjotE;;\tWW:_mt<Oǻ\kz{f7y՞9=ݽzo~r'˻w'O_@AC݇?[jwGCˆ8>99?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-    cHRM  z%        u0  `  :  o_F   XIDATxbtqq)`3`h c)ۏvV>%gZJ^Z)U|2ZZ:j)M#SzZ
    e
2fh    IENDB`PNG

   IHDR         B  
OiCCPPhotoshop ICC profile  xڝSgTS=BKKoR RB&*!	J!QEEȠQ,
!{kּ>H3Q5B.@
$p d!s# ~<<+" x M0B\t8K @zB @F&S  `cb P- `' { [!  eD h; VE X0 fK9 - 0IWfH    0Q) { `##x  FW<+*  x<$9E[-qWW.(I+6aa@.y24  x6_-"bbϫp@  t~,/;m%h^uf@ Wp~<<EJB[aW}g_Wl~<$2]GLϒ	bG"IbX*QqD2"B)%d,>5 j>{-]cK'Xt  o(hw?G% fIq  ^D$.Tʳ?  D*A,`6B$BB
dr`)B(Ͱ*`/@4Qhp.U=pa(	Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F; 2G1Q=C7Fdt1r=6Ыhڏ>C03l0.B8,	c˱"VcϱwE	6wB aAHXLXNH $4	7	Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![
b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGwǈg(gwLӋT071oUX**|
J&*/TުUUT^S}FU3S	ԖUPSSg;goT?~YYLOCQ_ cx,!ku5&|v*=9C3J3WRf?qtN	(~))4L1e\kXHQG6EYAJ'\'GgSSݧ
M=:.kDwn^Loy}/TmGX$<5qo</QC]@Caaᄑ<FFi\$mmƣ&&!&KMMRM);L;L֙͢5=12כ߷`ZxZ,eIZYnZ9YXUZ]F%ֻNNgðɶۮm}agbgŮ}}=Z~sr:V:ޚΜ?}/gX3)iSGggs󈋉K.>.ȽJtq]zۯ6iܟ4)Y3sCQ?0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz %gA[z|!?:eAAA!h쐭!ΑiP~aa~'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl{/]py.,:@LN8A*%w%
yg"/6шC\*NH*Mz쑼5y$3,幄'LLݛ:v m2=:1qB!Mggfvˬen/kY-
BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9<qy
+V<*mOW~&zMk^ʂkU
}]OX/Yߵa>(xoʿܔĹdff-[nڴVE/(ۻC<e;?TTTT6ݵan{4[>ɾUUMfeI?m]Nmq#׹=TR+Gw-6U#pDy	:v{vg/jBFS[b[O>zG4<YyJTiӓgό}~.`ۢ{cjotE;;\tWW:_mt<Oǻ\kz{f7y՞9=ݽzo~r'˻w'O_@AC݇?[jwGCˆ8>99?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-   bKGD      	pHYs        tIME	  \r   IDAT(ϥ=
@FAllx\^4&R)$$Fbk0kQ;3pCz׋M nmH* .@"i&Hoy쁧@-J	a.\W uaJ3;I2v&0#[+6    IENDB`PNG

   IHDR         :   	pHYs       
OiCCPPhotoshop ICC profile  xڝSgTS=BKKoR RB&*!	J!QEEȠQ,
!{kּ>H3Q5B.@
$p d!s# ~<<+" x M0B\t8K @zB @F&S  `cb P- `' { [!  eD h; VE X0 fK9 - 0IWfH    0Q) { `##x  FW<+*  x<$9E[-qWW.(I+6aa@.y24  x6_-"bbϫp@  t~,/;m%h^uf@ Wp~<<EJB[aW}g_Wl~<$2]GLϒ	bG"IbX*QqD2"B)%d,>5 j>{-]cK'Xt  o(hw?G% fIq  ^D$.Tʳ?  D*A,`6B$BB
dr`)B(Ͱ*`/@4Qhp.U=pa(	Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F; 2G1Q=C7Fdt1r=6Ыhڏ>C03l0.B8,	c˱"VcϱwE	6wB aAHXLXNH $4	7	Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![
b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGwǈg(gwLӋT071oUX**|
J&*/TުUUT^S}FU3S	ԖUPSSg;goT?~YYLOCQ_ cx,!ku5&|v*=9C3J3WRf?qtN	(~))4L1e\kXHQG6EYAJ'\'GgSSݧ
M=:.kDwn^Loy}/TmGX$<5qo</QC]@Caaᄑ<FFi\$mmƣ&&!&KMMRM);L;L֙͢5=12כ߷`ZxZ,eIZYnZ9YXUZ]F%ֻNNgðɶۮm}agbgŮ}}=Z~sr:V:ޚΜ?}/gX3)iSGggs󈋉K.>.ȽJtq]zۯ6iܟ4)Y3sCQ?0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz %gA[z|!?:eAAA!h쐭!ΑiP~aa~'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl{/]py.,:@LN8A*%w%
yg"/6шC\*NH*Mz쑼5y$3,幄'LLݛ:v m2=:1qB!Mggfvˬen/kY-
BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9<qy
+V<*mOW~&zMk^ʂkU
}]OX/Yߵa>(xoʿܔĹdff-[nڴVE/(ۻC<e;?TTTT6ݵan{4[>ɾUUMfeI?m]Nmq#׹=TR+Gw-6U#pDy	:v{vg/jBFS[b[O>zG4<YyJTiӓgό}~.`ۢ{cjotE;;\tWW:_mt<Oǻ\kz{f7y՞9=ݽzo~r'˻w'O_@AC݇?[jwGCˆ8>99?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-    cHRM  z%        u0  `  :  o_F  $IDATxտ+aE)L~N-`h0RFOpS-Ab0X\˹R%z<y9ϩd$j
qMUUxNЎ~S&Q
TXxE	CA5$I
84jTozq|TvqGE9-W\OWPZwX5P+Rq(T}ӈfbC[X?=O52jUU@?M"O\N}-4Fg`m_L,AgCH> ?    IENDB`PNG

   IHDR   	      \   sRGB    bKGD      	pHYs        tIME	e=   IDAT}ϱUBQEsp>~-edDlb
[PsC+aY)w)zM̝vkXl} gTxn*Is:hHR;S]TS1?dV<'ੀ1Ƀ:I~ձ}_vK%kS?:M/J    IENDB`PNG

   IHDR         ++]   	pHYs       
OiCCPPhotoshop ICC profile  xڝSgTS=BKKoR RB&*!	J!QEEȠQ,
!{kּ>H3Q5B.@
$p d!s# ~<<+" x M0B\t8K @zB @F&S  `cb P- `' { [!  eD h; VE X0 fK9 - 0IWfH    0Q) { `##x  FW<+*  x<$9E[-qWW.(I+6aa@.y24  x6_-"bbϫp@  t~,/;m%h^uf@ Wp~<<EJB[aW}g_Wl~<$2]GLϒ	bG"IbX*QqD2"B)%d,>5 j>{-]cK'Xt  o(hw?G% fIq  ^D$.Tʳ?  D*A,`6B$BB
dr`)B(Ͱ*`/@4Qhp.U=pa(	Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F; 2G1Q=C7Fdt1r=6Ыhڏ>C03l0.B8,	c˱"VcϱwE	6wB aAHXLXNH $4	7	Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![
b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGwǈg(gwLӋT071oUX**|
J&*/TުUUT^S}FU3S	ԖUPSSg;goT?~YYLOCQ_ cx,!ku5&|v*=9C3J3WRf?qtN	(~))4L1e\kXHQG6EYAJ'\'GgSSݧ
M=:.kDwn^Loy}/TmGX$<5qo</QC]@Caaᄑ<FFi\$mmƣ&&!&KMMRM);L;L֙͢5=12כ߷`ZxZ,eIZYnZ9YXUZ]F%ֻNNgðɶۮm}agbgŮ}}=Z~sr:V:ޚΜ?}/gX3)iSGggs󈋉K.>.ȽJtq]zۯ6iܟ4)Y3sCQ?0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz %gA[z|!?:eAAA!h쐭!ΑiP~aa~'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl{/]py.,:@LN8A*%w%
yg"/6шC\*NH*Mz쑼5y$3,幄'LLݛ:v m2=:1qB!Mggfvˬen/kY-
BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9<qy
+V<*mOW~&zMk^ʂkU
}]OX/Yߵa>(xoʿܔĹdff-[nڴVE/(ۻC<e;?TTTT6ݵan{4[>ɾUUMfeI?m]Nmq#׹=TR+Gw-6U#pDy	:v{vg/jBFS[b[O>zG4<YyJTiӓgό}~.`ۢ{cjotE;;\tWW:_mt<Oǻ\kz{f7y՞9=ݽzo~r'˻w'O_@AC݇?[jwGCˆ8>99?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-    cHRM  z%        u0  `  :  o_F  IDATxڬgVqמnҴRDbĈ覤.HY7ms#F,1ʓt=G{89~ȲLj"N|/# .cj\g0-\Dp
s\Ȓ xA<$La.`8C*Cf0pBx|/28X8Nn20Uh?X|ppKD;Ɔp/dYֳub/<F߅H倻!6fia$hdODy:/ѳ(ndoblfT)DxuIn~6d<JfU:nStv16ZbEVm`M=pq6/<Ut\I1OE_0Z忊:ZvtU; k4    IENDB`PNG

   IHDR         IJ   PLTELLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL/g0   NtRNS 2P."Tp@f` <BHJZ&0R,4j8D|($
blߝF>n~hhH  IDATx]b۶H儒-{iZK:glkn-tIqq?  E$dK>$>; PZ sVh!Sy0E0}H)-tkoܪKp\RϠ .E7
)*V;~PeBx*,=$zDؾ  JҸٻ 9{ ǸHpqW@"2'B[$ @TiH/b٥96!XHq`DE*R HV!%;"
i]dddddddd4y5 	Rb@(8CdŪݡ,@T@ibrq0alX!pe,	=4bW {
5Ƭhu~(Q^@3="b5XC@JCT76q_5@,r	šɩD)T|O@
ON-ՙ	[n@RXIm݋(F @?=0puL;g$@6η
K`>п @h գKVn"a"%l@.v$/U^G:#`` uTtK~ŋZ5T%kxk]\*Q,҇B44OXK|yg+_M(lоEO
 V$T1BXb-|?@ fBXr%'@ҹA\IJ,}BBc\V
rh(]tI^}oצoS3	";ʙb}"߰	){b$Gwwݾab")T@pF_er6JvШ"mޭM-d76x˰6ӥ;/`>KrP\_^u1%OTM.} Q3.Nس} )>-w`a+sy$t)NbFFFFBejnNVn4,A*X*5>PGa3	{oB&<L[Nc.öi=` Q@d
͆I.Il`\t[< Cit484-r+f쑱BCB MH	iy }>rxp|z;BǏ;burcK4tz1G~`ؚK|	̔>ۡO$~
Ao)0pzz
} i `;ADm8n:cfA@s7L  Z/..h8or?N93B~o_'` opO-:TG	L;7]`B%˛>*wTpM 0H}&t^1'Oqr'2P͡+z,tIW''|en=ǳgRm[NStK{҉mؓVt6ҲR`ζN&}B	U(r<qȁVyrrA**دzg6D#	YP`vs~(zMle|uQa*}+TRXc"+*NlNhcFt<N+;-}،Xtٕ$à^|uv*~'E_51qs*R`OΒ9#x449#WHۏZ)]0`p<ߝNoY{476ǹ>ۗ&1%Q''?l׸+&r{jN಻4)`N狌.߭ ǣ)q	2?n3Hb`} .`pqY1e_bu7e+N_F(DT,L}LLrmP5|x芥1cx DAb`M(7NED~<v\	%,ߚ/pR~/^lnp7t0_0l4_b0MWΦjmбɎl
|reȫ`B-v.iRox}
)%#`ЂR5CA2sua sYy3=jaeoI7~.plA΃
`O)	^>Mz	+4BXd.Mzv͈Pd8p<6?8N*x.6ڍ6G FZ)O	!lSshssNp8`'0/<s}.@Ǩs7ξO۟VDa5a v]m1+3 y6۠>@u50Ps51==p *KVҫ܂ݻc$N4(Xr2###c-賟Lδ>]5.sYs1f0;'̨Yg銛{@9	`aC(=%bo2=n1	jBoS$n#m =i0ci9}oI	qT] W%.(؅]z\x
f"]o'u䫵tk{v;A C3ֆwwR_#X(xҋ/q%Whpk_IX'b/fXKi"#####QCLi2t5L 0
QiH2;yTOok;עٶ`RNg{zy! Kxm?A(vU~mL(`o/!nmX-{v [ dw=n「sdwzn(}Oy~m
?XU;, V'+V&JRZ]᧭:zC'-߆@y4u`Vۓwъ#zP@QN>2/{\o) W~a3xLw:_Q;=pּdt\'8~3SRP6y+XQ*޺r
̗ѭ*޺r
gl/\U^u$|mbVnw\V|D͊NVNy7 k<;/E}?E*ǳgO ~g/96f
cD}%g$QG7o) UJo,O@0߾Q(;bw:5	NwRN5Iy'K?}:9mֽ*@f@jU9mҫÍ{$ ؗ}dFp|%!DdF>}G{@FFFFFFƦQܞH 
3
u	Mo~vy}mwz<7nP9rWku=|_nz쿳}@IXn?s<uP    IENDB`PNG

   IHDR      d   G,Z`   8IDATݏ  ÜP_(KؑXXBΑpjAWch~	^rB]    IENDB`PNG

   IHDR      d   G,Z`   >IDAT	@A*}wav>T8C ZmA۠znpf4,106    IENDB`PNG

   IHDR         IJ   PLTEi   NtRNS 2P."Tp@f` <BHJZ&0R,4j8D|($
blߝF>n~hhH  IDATx]b۶H儒-{iZK:glkn-tIqq?  E$dK>$>; PZ sVh!Sy0E0}H)-tkoܪKp\RϠ .E7
)*V;~PeBx*,=$zDؾ  JҸٻ 9{ ǸHpqW@"2'B[$ @TiH/b٥96!XHq`DE*R HV!%;"
i]dddddddd4y5 	Rb@(8CdŪݡ,@T@ibrq0alX!pe,	=4bW {
5Ƭhu~(Q^@3="b5XC@JCT76q_5@,r	šɩD)T|O@
ON-ՙ	[n@RXIm݋(F @?=0puL;g$@6η
K`>п @h գKVn"a"%l@.v$/U^G:#`` uTtK~ŋZ5T%kxk]\*Q,҇B44OXK|yg+_M(lоEO
 V$T1BXb-|?@ fBXr%'@ҹA\IJ,}BBc\V
rh(]tI^}oצoS3	";ʙb}"߰	){b$Gwwݾab")T@pF_er6JvШ"mޭM-d76x˰6ӥ;/`>KrP\_^u1%OTM.} Q3.Nس} )>-w`a+sy$t)NbFFFFBejnNVn4,A*X*5>PGa3	{oB&<L[Nc.öi=` Q@d
͆I.Il`\t[< Cit484-r+f쑱BCB MH	iy }>rxp|z;BǏ;burcK4tz1G~`ؚK|	̔>ۡO$~
Ao)0pzz
} i `;ADm8n:cfA@s7L  Z/..h8or?N93B~o_'` opO-:TG	L;7]`B%˛>*wTpM 0H}&t^1'Oqr'2P͡+z,tIW''|en=ǳgRm[NStK{҉mؓVt6ҲR`ζN&}B	U(r<qȁVyrrA**دzg6D#	YP`vs~(zMle|uQa*}+TRXc"+*NlNhcFt<N+;-}،Xtٕ$à^|uv*~'E_51qs*R`OΒ9#x449#WHۏZ)]0`p<ߝNoY{476ǹ>ۗ&1%Q''?l׸+&r{jN಻4)`N狌.߭ ǣ)q	2?n3Hb`} .`pqY1e_bu7e+N_F(DT,L}LLrmP5|x芥1cx DAb`M(7NED~<v\	%,ߚ/pR~/^lnp7t0_0l4_b0MWΦjmбɎl
|reȫ`B-v.iRox}
)%#`ЂR5CA2sua sYy3=jaeoI7~.plA΃
`O)	^>Mz	+4BXd.Mzv͈Pd8p<6?8N*x.6ڍ6G FZ)O	!lSshssNp8`'0/<s}.@Ǩs7ξO۟VDa5a v]m1+3 y6۠>@u50Ps51==p *KVҫ܂ݻc$N4(Xr2###c-賟Lδ>]5.sYs1f0;'̨Yg銛{@9	`aC(=%bo2=n1	jBoS$n#m =i0ci9}oI	qT] W%.(؅]z\x
f"]o'u䫵tk{v;A C3ֆwwR_#X(xҋ/q%Whpk_IX'b/fXKi"#####QCLi2t5L 0
QiH2;yTOok;עٶ`RNg{zy! Kxm?A(vU~mL(`o/!nmX-{v [ dw=n「sdwzn(}Oy~m
?XU;, V'+V&JRZ]᧭:zC'-߆@y4u`Vۓwъ#zP@QN>2/{\o) W~a3xLw:_Q;=pּdt\'8~3SRP6y+XQ*޺r
̗ѭ*޺r
gl/\U^u$|mbVnw\V|D͊NVNy7 k<;/E}?E*ǳgO ~g/96f
cD}%g$QG7o) UJo,O@0߾Q(;bw:5	NwRN5Iy'K?}:9mֽ*@f@jU9mҫÍ{$ ؗ}dFp|%!DdF>}G{@FFFFFFƦQܞH 
3
u	Mo~vy}mwz<7nP9rWku=|_nz쿳}@IXn?s<uP    IENDB`PNG

   IHDR         IJ   PLTE,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,E|   NtRNS 2P."Tp@f` <BHJZ&0R,4j8D|($
blߝF>n~hhH  IDATx]b۶H儒-{iZK:glkn-tIqq?  E$dK>$>; PZ sVh!Sy0E0}H)-tkoܪKp\RϠ .E7
)*V;~PeBx*,=$zDؾ  JҸٻ 9{ ǸHpqW@"2'B[$ @TiH/b٥96!XHq`DE*R HV!%;"
i]dddddddd4y5 	Rb@(8CdŪݡ,@T@ibrq0alX!pe,	=4bW {
5Ƭhu~(Q^@3="b5XC@JCT76q_5@,r	šɩD)T|O@
ON-ՙ	[n@RXIm݋(F @?=0puL;g$@6η
K`>п @h գKVn"a"%l@.v$/U^G:#`` uTtK~ŋZ5T%kxk]\*Q,҇B44OXK|yg+_M(lоEO
 V$T1BXb-|?@ fBXr%'@ҹA\IJ,}BBc\V
rh(]tI^}oצoS3	";ʙb}"߰	){b$Gwwݾab")T@pF_er6JvШ"mޭM-d76x˰6ӥ;/`>KrP\_^u1%OTM.} Q3.Nس} )>-w`a+sy$t)NbFFFFBejnNVn4,A*X*5>PGa3	{oB&<L[Nc.öi=` Q@d
͆I.Il`\t[< Cit484-r+f쑱BCB MH	iy }>rxp|z;BǏ;burcK4tz1G~`ؚK|	̔>ۡO$~
Ao)0pzz
} i `;ADm8n:cfA@s7L  Z/..h8or?N93B~o_'` opO-:TG	L;7]`B%˛>*wTpM 0H}&t^1'Oqr'2P͡+z,tIW''|en=ǳgRm[NStK{҉mؓVt6ҲR`ζN&}B	U(r<qȁVyrrA**دzg6D#	YP`vs~(zMle|uQa*}+TRXc"+*NlNhcFt<N+;-}،Xtٕ$à^|uv*~'E_51qs*R`OΒ9#x449#WHۏZ)]0`p<ߝNoY{476ǹ>ۗ&1%Q''?l׸+&r{jN಻4)`N狌.߭ ǣ)q	2?n3Hb`} .`pqY1e_bu7e+N_F(DT,L}LLrmP5|x芥1cx DAb`M(7NED~<v\	%,ߚ/pR~/^lnp7t0_0l4_b0MWΦjmбɎl
|reȫ`B-v.iRox}
)%#`ЂR5CA2sua sYy3=jaeoI7~.plA΃
`O)	^>Mz	+4BXd.Mzv͈Pd8p<6?8N*x.6ڍ6G FZ)O	!lSshssNp8`'0/<s}.@Ǩs7ξO۟VDa5a v]m1+3 y6۠>@u50Ps51==p *KVҫ܂ݻc$N4(Xr2###c-賟Lδ>]5.sYs1f0;'̨Yg銛{@9	`aC(=%bo2=n1	jBoS$n#m =i0ci9}oI	qT] W%.(؅]z\x
f"]o'u䫵tk{v;A C3ֆwwR_#X(xҋ/q%Whpk_IX'b/fXKi"#####QCLi2t5L 0
QiH2;yTOok;עٶ`RNg{zy! Kxm?A(vU~mL(`o/!nmX-{v [ dw=n「sdwzn(}Oy~m
?XU;, V'+V&JRZ]᧭:zC'-߆@y4u`Vۓwъ#zP@QN>2/{\o) W~a3xLw:_Q;=pּdt\'8~3SRP6y+XQ*޺r
̗ѭ*޺r
gl/\U^u$|mbVnw\V|D͊NVNy7 k<;/E}?E*ǳgO ~g/96f
cD}%g$QG7o) UJo,O@0߾Q(;bw:5	NwRN5Iy'K?}:9mֽ*@f@jU9mҫÍ{$ ؗ}dFp|%!DdF>}G{@FFFFFFƦQܞH 
3
u	Mo~vy}mwz<7nP9rWku=|_nz쿳}@IXn?s<uP    IENDB`PNG

   IHDR      d   G,Z`   IDATc&JlI  M"tg    IENDB`PNG

   IHDR      d   G,Z`   BIDATݏ	@2;{peMDyc ՍN0	ZX3X	̣wM0UXU_/g6>>    IENDB`PNG

   IHDR         IJ   PLTE$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$È   NtRNS 2P."Tp@f` <BHJZ&0R,4j8D|($
blߝF>n~hhH  IDATx]b۶H儒-{iZK:glkn-tIqq?  E$dK>$>; PZ sVh!Sy0E0}H)-tkoܪKp\RϠ .E7
)*V;~PeBx*,=$zDؾ  JҸٻ 9{ ǸHpqW@"2'B[$ @TiH/b٥96!XHq`DE*R HV!%;"
i]dddddddd4y5 	Rb@(8CdŪݡ,@T@ibrq0alX!pe,	=4bW {
5Ƭhu~(Q^@3="b5XC@JCT76q_5@,r	šɩD)T|O@
ON-ՙ	[n@RXIm݋(F @?=0puL;g$@6η
K`>п @h գKVn"a"%l@.v$/U^G:#`` uTtK~ŋZ5T%kxk]\*Q,҇B44OXK|yg+_M(lоEO
 V$T1BXb-|?@ fBXr%'@ҹA\IJ,}BBc\V
rh(]tI^}oצoS3	";ʙb}"߰	){b$Gwwݾab")T@pF_er6JvШ"mޭM-d76x˰6ӥ;/`>KrP\_^u1%OTM.} Q3.Nس} )>-w`a+sy$t)NbFFFFBejnNVn4,A*X*5>PGa3	{oB&<L[Nc.öi=` Q@d
͆I.Il`\t[< Cit484-r+f쑱BCB MH	iy }>rxp|z;BǏ;burcK4tz1G~`ؚK|	̔>ۡO$~
Ao)0pzz
} i `;ADm8n:cfA@s7L  Z/..h8or?N93B~o_'` opO-:TG	L;7]`B%˛>*wTpM 0H}&t^1'Oqr'2P͡+z,tIW''|en=ǳgRm[NStK{҉mؓVt6ҲR`ζN&}B	U(r<qȁVyrrA**دzg6D#	YP`vs~(zMle|uQa*}+TRXc"+*NlNhcFt<N+;-}،Xtٕ$à^|uv*~'E_51qs*R`OΒ9#x449#WHۏZ)]0`p<ߝNoY{476ǹ>ۗ&1%Q''?l׸+&r{jN಻4)`N狌.߭ ǣ)q	2?n3Hb`} .`pqY1e_bu7e+N_F(DT,L}LLrmP5|x芥1cx DAb`M(7NED~<v\	%,ߚ/pR~/^lnp7t0_0l4_b0MWΦjmбɎl
|reȫ`B-v.iRox}
)%#`ЂR5CA2sua sYy3=jaeoI7~.plA΃
`O)	^>Mz	+4BXd.Mzv͈Pd8p<6?8N*x.6ڍ6G FZ)O	!lSshssNp8`'0/<s}.@Ǩs7ξO۟VDa5a v]m1+3 y6۠>@u50Ps51==p *KVҫ܂ݻc$N4(Xr2###c-賟Lδ>]5.sYs1f0;'̨Yg銛{@9	`aC(=%bo2=n1	jBoS$n#m =i0ci9}oI	qT] W%.(؅]z\x
f"]o'u䫵tk{v;A C3ֆwwR_#X(xҋ/q%Whpk_IX'b/fXKi"#####QCLi2t5L 0
QiH2;yTOok;עٶ`RNg{zy! Kxm?A(vU~mL(`o/!nmX-{v [ dw=n「sdwzn(}Oy~m
?XU;, V'+V&JRZ]᧭:zC'-߆@y4u`Vۓwъ#zP@QN>2/{\o) W~a3xLw:_Q;=pּdt\'8~3SRP6y+XQ*޺r
̗ѭ*޺r
gl/\U^u$|mbVnw\V|D͊NVNy7 k<;/E}?E*ǳgO ~g/96f
cD}%g$QG7o) UJo,O@0߾Q(;bw:5	NwRN5Iy'K?}:9mֽ*@f@jU9mҫÍ{$ ؗ}dFp|%!DdF>}G{@FFFFFFƦQܞH 
3
u	Mo~vy}mwz<7nP9rWku=|_nz쿳}@IXn?s<uP    IENDB`PNG

   IHDR      
   ,   IDAT
 D_5^__ {=$йvǶ=_rwJ~?@Up|w*5 RJ늙!" 1~N1s{ԟ68k fFu}í5BT7H@^"    IENDB`/*
 * jQuery UI CSS Framework 1.8.16
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Theming/API
 */

/* Layout helpers
----------------------------------*/
.ui-helper-hidden { display: none; }
.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
.ui-helper-clearfix { display: inline-block; }
/* required comment for clearfix to work in Opera \*/
* html .ui-helper-clearfix { height:1%; }
.ui-helper-clearfix { display:block; }
/* end clearfix */
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }


/* Interaction Cues
----------------------------------*/
.ui-state-disabled { cursor: default !important; }


/* Icons
----------------------------------*/

/* states and images */
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }


/* Misc visuals
----------------------------------*/

/* Overlays */
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }


/*
 * jQuery UI CSS Framework 1.8.16
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Theming/API
 *
 * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Helvetica,%20Verdana,%20Arial,%20sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=0px&bgColorHeader=232325&bgTextureHeader=18_hexagon.png&bgImgOpacityHeader=15&borderColorHeader=a3a3a3&fcHeader=eeeeee&iconColorHeader=bbbbbb&bgColorContent=f9f9f9&bgTextureContent=04_highlight_hard.png&bgImgOpacityContent=100&borderColorContent=cccccc&fcContent=222222&iconColorContent=222222&bgColorDefault=232325&bgTextureDefault=04_highlight_hard.png&bgImgOpacityDefault=40&borderColorDefault=777777&fcDefault=e3e3e3&iconColorDefault=ededed&bgColorHover=1c1c1c&bgTextureHover=02_glass.png&bgImgOpacityHover=55&borderColorHover=000000&fcHover=ffffff&iconColorHover=ffffff&bgColorActive=232325&bgTextureActive=04_highlight_hard.png&bgImgOpacityActive=65&borderColorActive=cccccc&fcActive=ffffff&iconColorActive=ffffff&bgColorHighlight=ffeb80&bgTextureHighlight=06_inset_hard.png&bgImgOpacityHighlight=55&borderColorHighlight=ffde2e&fcHighlight=363636&iconColorHighlight=4ca300&bgColorError=cd0a0a&bgTextureError=06_inset_hard.png&bgImgOpacityError=45&borderColorError=9e0505&fcError=ffffff&iconColorError=ffcf29&bgColorOverlay=aaaaaa&bgTextureOverlay=03_highlight_soft.png&bgImgOpacityOverlay=40&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=03_highlight_soft.png&bgImgOpacityShadow=50&opacityShadow=20&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
 */


/* Component containers
----------------------------------*/
.ui-widget { font-family: Helvetica, Verdana, Arial, sans-serif; font-size: 0.8em; }
.ui-widget .ui-widget { font-size: 1em; }
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Helvetica, Verdana, Arial, sans-serif; font-size: 1em; }
.ui-widget-content { border: 1px solid #cccccc; background: #f9f9f9 url(images/ui-bg_highlight-hard_100_f9f9f9_1x100.png) 50% top repeat-x; color: #222222; }
.ui-widget-content a { color: #222222; }
.ui-widget-header { border: 1px solid #a3a3a3; background: #232325 url(images/ui-bg_hexagon_15_232325_12x10.png) 50% 50% repeat; color: #eeeeee; font-weight: bold; }
.ui-widget-header a { color: #eeeeee; }

/* Interaction states
----------------------------------*/
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #777777; background: #232325 url(images/ui-bg_highlight-hard_40_232325_1x100.png) 50% 50% repeat-x; font-weight: normal; color: #e3e3e3; }
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #e3e3e3; text-decoration: none; }
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #000000; background: #1c1c1c url(images/ui-bg_glass_55_1c1c1c_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #ffffff; }
.ui-state-hover a, .ui-state-hover a:hover { color: #ffffff; text-decoration: none; }
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #cccccc; background: #232325 url(images/ui-bg_highlight-hard_65_232325_1x100.png) 50% 50% repeat-x; font-weight: normal; color: #ffffff; }
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #ffffff; text-decoration: none; }
.ui-widget :active { outline: none; }

/* Interaction Cues
----------------------------------*/
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight  {border: 1px solid #ffde2e; background: #ffeb80 url(images/ui-bg_inset-hard_55_ffeb80_1x100.png) 50% bottom repeat-x; color: #363636; }
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #9e0505; background: #cd0a0a url(images/ui-bg_inset-hard_45_cd0a0a_1x100.png) 50% bottom repeat-x; color: #ffffff; }
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #ffffff; }
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #ffffff; }
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary,  .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }

/* Icons
----------------------------------*/

/* states and images */
.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
.ui-widget-header .ui-icon {background-image: url(images/ui-icons_bbbbbb_256x240.png); }
.ui-state-default .ui-icon { background-image: url(images/ui-icons_ededed_256x240.png); }
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }
.ui-state-active .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }
.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_4ca300_256x240.png); }
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_ffcf29_256x240.png); }

/* positioning */
.ui-icon-carat-1-n { background-position: 0 0; }
.ui-icon-carat-1-ne { background-position: -16px 0; }
.ui-icon-carat-1-e { background-position: -32px 0; }
.ui-icon-carat-1-se { background-position: -48px 0; }
.ui-icon-carat-1-s { background-position: -64px 0; }
.ui-icon-carat-1-sw { background-position: -80px 0; }
.ui-icon-carat-1-w { background-position: -96px 0; }
.ui-icon-carat-1-nw { background-position: -112px 0; }
.ui-icon-carat-2-n-s { background-position: -128px 0; }
.ui-icon-carat-2-e-w { background-position: -144px 0; }
.ui-icon-triangle-1-n { background-position: 0 -16px; }
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
.ui-icon-triangle-1-e { background-position: -32px -16px; }
.ui-icon-triangle-1-se { background-position: -48px -16px; }
.ui-icon-triangle-1-s { background-position: -64px -16px; }
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
.ui-icon-triangle-1-w { background-position: -96px -16px; }
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
.ui-icon-arrow-1-n { background-position: 0 -32px; }
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
.ui-icon-arrow-1-e { background-position: -32px -32px; }
.ui-icon-arrow-1-se { background-position: -48px -32px; }
.ui-icon-arrow-1-s { background-position: -64px -32px; }
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
.ui-icon-arrow-1-w { background-position: -96px -32px; }
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
.ui-icon-arrow-4 { background-position: 0 -80px; }
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
.ui-icon-extlink { background-position: -32px -80px; }
.ui-icon-newwin { background-position: -48px -80px; }
.ui-icon-refresh { background-position: -64px -80px; }
.ui-icon-shuffle { background-position: -80px -80px; }
.ui-icon-transfer-e-w { background-position: -96px -80px; }
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
.ui-icon-folder-collapsed { background-position: 0 -96px; }
.ui-icon-folder-open { background-position: -16px -96px; }
.ui-icon-document { background-position: -32px -96px; }
.ui-icon-document-b { background-position: -48px -96px; }
.ui-icon-note { background-position: -64px -96px; }
.ui-icon-mail-closed { background-position: -80px -96px; }
.ui-icon-mail-open { background-position: -96px -96px; }
.ui-icon-suitcase { background-position: -112px -96px; }
.ui-icon-comment { background-position: -128px -96px; }
.ui-icon-person { background-position: -144px -96px; }
.ui-icon-print { background-position: -160px -96px; }
.ui-icon-trash { background-position: -176px -96px; }
.ui-icon-locked { background-position: -192px -96px; }
.ui-icon-unlocked { background-position: -208px -96px; }
.ui-icon-bookmark { background-position: -224px -96px; }
.ui-icon-tag { background-position: -240px -96px; }
.ui-icon-home { background-position: 0 -112px; }
.ui-icon-flag { background-position: -16px -112px; }
.ui-icon-calendar { background-position: -32px -112px; }
.ui-icon-cart { background-position: -48px -112px; }
.ui-icon-pencil { background-position: -64px -112px; }
.ui-icon-clock { background-position: -80px -112px; }
.ui-icon-disk { background-position: -96px -112px; }
.ui-icon-calculator { background-position: -112px -112px; }
.ui-icon-zoomin { background-position: -128px -112px; }
.ui-icon-zoomout { background-position: -144px -112px; }
.ui-icon-search { background-position: -160px -112px; }
.ui-icon-wrench { background-position: -176px -112px; }
.ui-icon-gear { background-position: -192px -112px; }
.ui-icon-heart { background-position: -208px -112px; }
.ui-icon-star { background-position: -224px -112px; }
.ui-icon-link { background-position: -240px -112px; }
.ui-icon-cancel { background-position: 0 -128px; }
.ui-icon-plus { background-position: -16px -128px; }
.ui-icon-plusthick { background-position: -32px -128px; }
.ui-icon-minus { background-position: -48px -128px; }
.ui-icon-minusthick { background-position: -64px -128px; }
.ui-icon-close { background-position: -80px -128px; }
.ui-icon-closethick { background-position: -96px -128px; }
.ui-icon-key { background-position: -112px -128px; }
.ui-icon-lightbulb { background-position: -128px -128px; }
.ui-icon-scissors { background-position: -144px -128px; }
.ui-icon-clipboard { background-position: -160px -128px; }
.ui-icon-copy { background-position: -176px -128px; }
.ui-icon-contact { background-position: -192px -128px; }
.ui-icon-image { background-position: -208px -128px; }
.ui-icon-video { background-position: -224px -128px; }
.ui-icon-script { background-position: -240px -128px; }
.ui-icon-alert { background-position: 0 -144px; }
.ui-icon-info { background-position: -16px -144px; }
.ui-icon-notice { background-position: -32px -144px; }
.ui-icon-help { background-position: -48px -144px; }
.ui-icon-check { background-position: -64px -144px; }
.ui-icon-bullet { background-position: -80px -144px; }
.ui-icon-radio-off { background-position: -96px -144px; }
.ui-icon-radio-on { background-position: -112px -144px; }
.ui-icon-pin-w { background-position: -128px -144px; }
.ui-icon-pin-s { background-position: -144px -144px; }
.ui-icon-play { background-position: 0 -160px; }
.ui-icon-pause { background-position: -16px -160px; }
.ui-icon-seek-next { background-position: -32px -160px; }
.ui-icon-seek-prev { background-position: -48px -160px; }
.ui-icon-seek-end { background-position: -64px -160px; }
.ui-icon-seek-start { background-position: -80px -160px; }
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
.ui-icon-seek-first { background-position: -80px -160px; }
.ui-icon-stop { background-position: -96px -160px; }
.ui-icon-eject { background-position: -112px -160px; }
.ui-icon-volume-off { background-position: -128px -160px; }
.ui-icon-volume-on { background-position: -144px -160px; }
.ui-icon-power { background-position: 0 -176px; }
.ui-icon-signal-diag { background-position: -16px -176px; }
.ui-icon-signal { background-position: -32px -176px; }
.ui-icon-battery-0 { background-position: -48px -176px; }
.ui-icon-battery-1 { background-position: -64px -176px; }
.ui-icon-battery-2 { background-position: -80px -176px; }
.ui-icon-battery-3 { background-position: -96px -176px; }
.ui-icon-circle-plus { background-position: 0 -192px; }
.ui-icon-circle-minus { background-position: -16px -192px; }
.ui-icon-circle-close { background-position: -32px -192px; }
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
.ui-icon-circle-zoomin { background-position: -176px -192px; }
.ui-icon-circle-zoomout { background-position: -192px -192px; }
.ui-icon-circle-check { background-position: -208px -192px; }
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
.ui-icon-circlesmall-close { background-position: -32px -208px; }
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
.ui-icon-squaresmall-close { background-position: -80px -208px; }
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }


/* Misc visuals
----------------------------------*/

/* Corner radius */
.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 0px; -webkit-border-top-left-radius: 0px; -khtml-border-top-left-radius: 0px; border-top-left-radius: 0px; }
.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 0px; -webkit-border-top-right-radius: 0px; -khtml-border-top-right-radius: 0px; border-top-right-radius: 0px; }
.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 0px; -webkit-border-bottom-left-radius: 0px; -khtml-border-bottom-left-radius: 0px; border-bottom-left-radius: 0px; }
.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 0px; -webkit-border-bottom-right-radius: 0px; -khtml-border-bottom-right-radius: 0px; border-bottom-right-radius: 0px; }

/* Overlays */
.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_highlight-soft_40_aaaaaa_1x100.png) 50% top repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_highlight-soft_50_aaaaaa_1x100.png) 50% top repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }GIF89a	 	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                !   ,    	 	  & HpPA81a/>̈0#A ;GIF89a   jlbAԽ|9tmp|_,      ;X%ܬPƤ7i4e'E j
dq 56p1tJU$  ;GIF89a                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    !   ,         ;GIF89a                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                !   ,       	/ "\XB	B(p"E1:0ǏR8r G%<0ʒ,$L6s	SgO#oVEnTڑ)ʟP=:5iեWf}*5*UVb,ׯ]Ӣ]Vm[cƅ[Vn]gꝻn߼|x[nUl2:;oegLqş=w~thҧ)skͯ9=Zumַ]熽[PڳEGtƇVn缡~Iܥسkν{W|s^y*:?_zrW ~*8B I^ZHx"f8%&c.(cc;bx@($A9$=vE"dOeSx$WJ%[ZiNvi#X\ejeyiҹfxΙg{ީ|gj}"*2zhbBڦv:j)br(U^
jNZj꣩zjnk~*ʚ+ڪd[+L[,˺zmRbkr묶Ւ{٢{»KJo;/[0+<C0J_[L"g<%'s.,sÌs;c|@,4A=4=wE#tOuS|4WK5[[mNwm3X\uje}iӽvxϝw{|wn}#.3~xbC޶v;n9cs8U_zO^z型髣~zo{:˞;ۮt_꿓;L_<˻~}Sc{sՓ٣ÿOK?_ #@Ѐ=	2pAr!'pCT?τ%L`+ ʰ!#CP@2iD"=`OXD$61O\a[8WbE+Ni ;GIF89a   Zx➭s-҃h$Ç4,      7H`KPl\:pL)e9@\ "l:+PB ;GIF89a`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 !   ,    `    	H*\ BlHŋ#bȱEC	rɓ(S<K+cp̛m:φ:AI!M\Z)<J}:PԫCfW`ÊU:Y[Ϫ];2-[oDIrѭުK!EP1㎎t,S#cys暞9nŦSDI֦^(vܻ	q3;pm8r"TcdcܣOy\9w]v5eU]9߀'xE('aHnq["$!ؠ)8e	_p3v<5"| aFF2dO"U.VfPWl[$`)d9[@ ;GIF89a`       1k9s!Bs!R1scB J ZZ!k!s {cc{Bs֔ƭҤޥ筌絔ﵔҵ                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      !   ,    `    	H*\ BlHŋ#bȱEC	rɓ(S\ɲ˗0cʜ)B&ܙB
x(A(tp@ѧH;HthjQ	PJ+O	`۷pʝK.͒v[[qć|7r0È+^̸	$c8DP2 0` !8Hi	"0X 1$ e!Kȓ+~FֳkνU8ur	,wJ:ujXr]XѪe뽿 8vDM1A(^NݑP%TW)wmb}aa~iU0xX|)h >(D$d]fmhݦ]j]l&ev[!YdR=!`ұip)県IvJjٕVwTJefw]%wv裐F* ;GIF89a   Zx➭s-҃h$Ç4,       6H`KPl\
2jLEkuÅalV ;GIF89a	 	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                !   ,    	 	  " H"<pa  HaE   ;GIF89a       遁YYY'''!!!ܰfff333                                          !   ,       I `Q@*@+@Bn9DĐnB1ȵ
 xXI=޲m[Ր  ;GIF89a                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   !   ,       	 "\XB	B(p"E1:ǏR8r G%<0ʒ,$L6s	SgO#oVEnTڑ)ʟP=:5iեWf}*5*UVb,ׯ]Ӣ]Vm[cƅ[Vn]gꝻn߼|x[nUl2:;oegLqş=w~thҧ)skͯ9=Zumַ]熽[PڳEGtƇVn缡~Iܥسkν{W|s^y*:?_zrW ~*8B I^ZHx"f8%&c.(cc;bx@($A9$=vE"dOeSx$WJ%[ZiNvi#X\ejeyiҹfxΙg{ީ|gj}"*2zhbBڦv:j)br(U^
jNZj꣩zjnk~*ʚ+ڪd[+L[,˺zmRbkr묶Ւ{٢{»KJo;/[0+<C0J_[L"g<%'s.,sÌs;c|@,4A=4=wE#tOuS|4WK5[[mNwm3X\uje}iӽvxϝw{|wn}#.3~xbC޶v;n9cs8U_zO^z型髣~zo{:˞;ۮt_꿓;L_<˻~}Sc{sՓ٣ÿOK?_ #@Ѐ=	2pAr!'pCT?τ%L`+ ʰ!#CP@2iD"=`OXD$61O\a[8WbE+Ni ;GIF89a`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    !   ,    `    	H*\ BlHŋ#bȱEC	rɓ(S<	Õ0I,ǁ iܹ0'N@FteУ
ԉϥMB5TNFZ)׮A)vͲfcMZ8QKs/E7o߼`r#x1211希/c~r῝99z$ҢQs<Zik_0߻Y5o7ds6ix%gSO͎3Ëg{6|qcPɷu]~G߂6`}ؙcaH=
7|#
EM~%x'݇4hcmr؜~֣(d:-&p2K+*1"9%3ި\v` ;GIF89a`       vv                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          !   ,    `    	H*\ BlHŋ#bȱEC	rɓ(S<K+cp̛m:φ:AI!MZhPM|*T5j]Rת_Â*YgUfImeDIރs
L8-WGZ3BxҮ/>q3g?;>X4Ҧ)N}u_הaw\;0m׶SMMUI#\wjJ(TzsZ4w뾙'ӫ7}{Ӗy-|}_}=ym7Pu}W vi'18x)߄VhNq6qgaXB"R)"ȹ8th<uX7RXqK$lO߁8>XWfIGu_za>ih ;GIF89a                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                !   ,       	HA*\x0!ÇBHP"E	3xaǋ?2)R!ɒOrdˈ/M8ʗ7[\eϒ?E8cQ5m&eaSOb|ԉW!f}eT`mإeeM&ٰol.Zl;R}4ỀƹXgc}F:Yhej̹3H34dӒQSVm5fFAOp^ڳmōUvoZ}W݁EXZ棡~zj뫱{ln{-FpW\r?tx!~ᝧ yFރIXaq8yx8x	¸6V昡١"#Y'2+B٢/R3"Y#7ȥ^y?CYK٤OSYW♥I~	mq":u2zyBgeRzib顟&ꢣ6Z꣧Fꤜ
j*j⪪**lZlllFkR>,Nm^nn;n+k.+o;okoVڪܬ"\2\B/Kc\sܰ[\1gܱ#\'2+1=5#}93=CAK=t/[]5Es}IMQ=*Tt]vj_}owց]݇8߃w׏ؓ]ٗڋw>#3^:{C^Sc޻s^x3<œͣӳ^ϋ~ٛ=^㞾޾o<<H=Zπ=s$>
ςà4?σ`
?3P@Ѕe@.qANЇA"nЈDBp pfJyN*C2R%4cјB5損-tcxC9>*aE>vQ?d9DBѐGDdDF6яtFI~m5YFNqAYGQ{4QHVҕ!eHZ.)H@  ;GIF89a      vv                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          !   ,       	/ "\XB	B(p"E1:0ǏR8r G%<0ʒ,$L6s	SgO#oVEnTڑ)ʟP=:5iեWf}*5*UVb,ׯ]Ӣ]Vm[cƅ[Vn]gꝻn߼|x[nUl2:;oegLqş=w~thҧ)skͯ9=Zumַ]熽[PڳEGtƇVn缡~Iܥسkν{W|s^y*:?_zrW ~*8B I^ZHx"f8%&c.(cc;bx@($A9$=vE"dOeSx$WJ%[ZiNvi#X\ejeyiҹfxΙg{ީ|gj}"*2zhbBڦv:j)br(U^
jNZj꣩zjnk~*ʚ+ڪd[+L[,˺zmRbkr묶Ւ{٢{»KJo;/[0+<C0J_[L"g<%'s.,sÌs;c|@,4A=4=wE#tOuS|4WK5[[mNwm3X\uje}iӽvxϝw{|wn}#.3~xbC޶v;n9cs8U_zO^z型髣~zo{:˞;ۮt_꿓;L_<˻~}Sc{sՓ٣ÿOK?_ #@Ѐ=	2pAr!'pCT?τ%L`+ ʰ!#CP@2iD"=`OXD$61O\a[8WbE+Ni ;GIF89a       888&&&֨vvvfff䘘HHHVVV                                             !Created with ajaxload.info ! 
   !NETSCAPE2.0   ,       P  di0l!*`Ƒ5و[<iP),IZ$bH85&x5k <yB ! 
  ,       h  GҌh*ਨ@$E}eh @
LcQGBP5 <5UdQ+"g0Ak#A <P70<	0Y8*	#! ! 
  ,       `  #(H*
P	-13
:C1KHH.$ٱy j.WD@Y 0H	,0B
kJU?5w|$k\)! ! 
  ,       R  di 1@Ck!B`? #E8zBQXcmv" £``UFrp)f! ! 
  ,       `  di@E1m]ǹHІ(4 (,F!aH XSm5bDH ab,
%p3c#'"467P&*X/($! ! 
  ,       _  diH@@4 ²A"I`>nI0$K7H,-t*E-``1@C7h/1f\)&! ;         GIF89a`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 !   ,    `    	H*\ BlHŋ#bȱEC	rɓ(S<K+cp̛m:φ:AI!MZhPM|*T5j]Rת_Â*YgUfImeDIރs
L8-WGZ3BxҮ/>q3g?;>X4Ҧ)N}u_הaw\;0m׶SMMUI#\wjJ(TzsZ4w뾙'ӫ7}{Ӗy-|}_}=ym7Pu}W vi'18x)߄VhNq6qgaXB"R)"ȹ8th<uX7RXqK$lO߁8>XWfIGu_za>ih ;th {
    text-align: left;
}

h1, h2, h3, h4, h5, h6 {
    padding-top: 20px;
    padding-bottom: 5px;
    clear: left;
    margin-bottom: 5px;
    margin-top: 0px;
}

h1 {
    padding-top: 10px;
    padding-bottom: 10px;
}

h1.file {
    position: fixed;
    width: 100%;
    background: #f0f0f0 url('../images/icons/file-php.png') no-repeat left 2px;
    padding: 10px;
    padding-left: 34px;
    margin: 0px;
    border-bottom: 1px solid silver;
}

#file-nav-box
{
    position:         fixed;
    width:            100%;
    top:              39px;
    display:          none;
}

#file-nav {
    margin:  0px;
    padding: 0px;
}

#file-nav-options {
    float: right;
    border-bottom: 1px solid #e9e9e9;
    border-left: 1px solid #e9e9e9;
    border-bottom-left-radius: 5px;
    padding: 5px;
    padding-right: 20px;
    background: #f7f7f7;
}

#file-nav li {
    list-style-type: square;
}

#file-nav > li {
    float: left;
    list-style: none;
}

#file-nav > li > a {
    font-weight: bold;
}

#file-nav li a {
    display: block;
    padding: 0px 5px;
    text-decoration: none;
    color: black;
    white-space: nowrap;
}

#file-nav li a:hover {
    background: #f6f6f6;
}

#file-nav-container {
    background: #f9f9f9;
    display: none;
}

#file-nav-tab {
    margin: 0px auto;
    width: 200px;
    text-align: center;
    font-weight: bold;
    border-bottom-right-radius: 5px;
    border-bottom-left-radius: 5px;
    border-left: 1px solid #e9e9e9;
    border-right: 1px solid #e9e9e9;
    border-bottom: 1px solid #e9e9e9;
    background: #f9f9f9;
}

#file-description
{
    padding-top: 60px;
}

h2 {
    color: navy;
    padding-top: 30px;
}

h2.class, h2.interface {
    clear: both;
}

h4 {
    font-style: italic;
    margin-bottom: 5px;
    margin-top: 20px;
    padding-top: 0px;
}

h4.method, h4.function {
    margin: 0px;
    font-size: 1.15em;
    color: teal;
}

h4.info {
    margin-top: 0px;
    margin-left: 10px;
}

.file_menu {
    background-color: #f0f0f0;
    -moz-border-radius: 5px;
    border-radius: 5px;
    padding: 3px;
    margin-bottom: 5px;
}

.file_menu a {
    border-right: 1px solid silver;
    padding: 0px 10px;
}

.file_menu a:last-of-type {
    border: none;
}

.file-info, .class-info {
    border-left: 1px solid #5f9ea0;
    padding: 5px 0px 5px 7px;
}

dl.function-info, dl.constant-info {
    width: 100%;
}

dt {
    float: left;
    clear: left;
}

dd {
    display: block;
    margin-bottom: 0em;
    margin-left: 150px;
}

dd, dt {
    background: transparent;
}

dd pre {
    margin: 0px;
    background: #f9f9f9;
}

p, div dl, h4.arguments, div.arguments {
    margin-left: 10px;
}

table.argument-info {
    font-size: 1.0em;
}

table.argument-info tr.odd {
    background-color: #f0f0f0;
}

table.argument-info thead {
    background-color: #f9f9f9;
    border-bottom: 1px dashed gray;
    color: gray;
}

code {
    background:   #f9f9f9;
    color:        #707079;
    font-weight:  bold;
}

code span.highlight {
    color: navy;
    font-size: 1.1em;
    font-family: helvetica sans-serif;
    padding-right: 5px;
}

code a {
    color: silver;
}

div.class code, div.function code, div.property code,
div.method code, div.constant code
{
    display: block;
    border-bottom: 1px solid #e0e0e0;
    padding: 5px 10px;
    margin-right: 5px;
}

div.long-description {
    font-size: 1.0em;
    padding: 5px;
    background: #f9f9f9;
}

div.long-description p {
    margin-bottom: 0em;
}

div.long-description code {
    display:       inline;
    margin-left:   0px;
    background:    gray;
    white-space:   pre;
    color:         white;
    border-bottom: none;
    padding:       3px 10px;
}

div.long-description pre code {
    padding: 0px;
    font-size: 0.8em;
}

div.long-description pre {
    background: gray;
    color: white;
    padding: 5px 10px;
    margin-right: 5px;
}

div.constant dd, div.constant dt,
div.property dd, div.property dt,
.function-info dd, .function-info dt,
.return-info dd, .return-info dt {
    float: left;
}

div.constant dt, div.property dt, .function-info dt, .return-info dt {
    width: 150px;
    clear: left;
    word-wrap: break-word;
}

.file-info dd, .class-info dd {
    border-bottom: 1px solid #f0f0f0;
}

.file-info dd a.class {
    background: transparent url('../images/icons/class.png') no-repeat 0px 0px;
    padding-left: 20px;
    margin-left: -10px;
}

.file-info dd a.interface {
    background: transparent url('../images/icons/interface.png') no-repeat 0px 0px;
    padding-left: 20px;
    margin-left: -10px;
}

.file-info dd a.function {
    background: transparent url('../images/icons/function.png') no-repeat 0px 0px;
    padding-left: 20px;
    margin-left: -10px;
}

.file-info dd a.constant, .class-info dd a.constant {
    background: transparent url('../images/icons/constant.png') no-repeat 0px 0px;
    padding-left: 20px;
    margin-left: -10px;
}

.class-info dd a.property {
    background: transparent url('../images/icons/property.png') no-repeat 0px 0px;
    padding-left: 20px;
    margin-left: -10px;
}

.class-info dd a.method {
    background: transparent url('../images/icons/method.png') no-repeat 0px 0px;
    padding-left: 20px;
    margin-left: -10px;
}

h3.constant, h4.constant {
    background: transparent url('../images/icons/constant.png') no-repeat 0px 20px;
    padding-left: 20px;
}

h3.function {
    background: transparent url('../images/icons/function.png') no-repeat 0px 20px;
    padding-left: 20px;
}

h4.method {
    background: transparent url('../images/icons/method.png') no-repeat 0px 0px;
    padding-left: 20px;
}

h4.property {
    background: transparent url('../images/icons/property.png') no-repeat 0px 0px;
    padding-left: 20px;
}

h2.class {
    background: transparent url('../images/icons/class.png') no-repeat left 31px;
    padding-left: 20px;
}

h2.interface {
    background: transparent url('../images/icons/interface.png') no-repeat left 31px;
    padding-left: 20px;
}

h4.constant {
    background-position: 0px 0px;
}

div.api-section {
    background: #fbfbfb;
    border: 1px solid #eee;
    margin-top: 5px;
    padding: 5px;
}

div.api-section h4, div.api-section h5 {
    font-size: 1em;
    font-style: italic;
    margin-top: 3px;
    padding-top: 0px;
}

div.clear {
    clear: left;
}

div.class {
    padding-left: 20px;
}

div.constant, div.function, div.method, div.property {
    border: 1px solid silver;
    border-bottom: none;
}

div.method div.description {
    padding: 10px;
    padding-top: 0px;
}

div.method div.description small {
    color: silver;
    display: block;
}

div.method div.description small a {
    color: gray;
}

div.class h3 {
    color: navy;
}

div.to-top {
    float: right;
    text-align: right;
    width: 100px;
    font-size: 11px;
    font-variant: small-caps;
    font-style: normal;
}

div.to-top a {
    color: silver;
    padding-right: 10px;
}

span.attribute {
    padding: 2px 5px;
    border-radius: 5px;
    -moz-border-radius: 5px;
    background: gray;
    font-weight: bold;
    font-variant: small-caps;
    color: white;
    font-size: 0.92em;
}

div.method span.attribute, div.property span.attribute {
    float: right;
}

div.code-tabs {
    margin-left: 24px;
}

a.gripper {
    display: none;
    float: left;
    background-color: #f0f0f0;
    height: 50px;
    width: 13px;
    margin: 5px 10px 5px 0px;
    border-top-right-radius: 5px;
    border-bottom-right-radius: 5px;
    border: 1px solid silver;
    border-left: none;
}

a.gripper img {
    margin-top: 6px;
    width: 12px;
}

div.inherited_from code span.highlight {
    color: gray;
}

small.package {
    margin-top: -10px;
    display: block;
}

.argument-info p
{
    margin: 0px;
}

a.anchor {
    position: absolute;
    margin-top: -60px;
    left: -1000px;
}@import url('sen.full.min.css');
@import url('jquery-ui.css');
@import url('phpdoc/jquery-ui-1.8.16.custom.css');
@import url('jquery.treeview.css');
@import url('navigation.css');
@import url('api-content.css');
@import url('default.css');

#page
{
  background: white;
}

#db-header, #db-menu
{
  height: 1px;
  background: black;
  padding: 0px;
}

#db-header *, #db-menu * {
    display: none !important;
}

table#overview th
{
  text-align: left;
}

table#overview td
{
  border: none;
}

td#sidebar
{
  width: 200px;
  padding: 0px;
}/*
 * jQuery UI CSS Framework 1.8.16
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Theming/API
 */

/* Layout helpers
----------------------------------*/
.ui-helper-hidden { display: none; }
.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
.ui-helper-clearfix { display: inline-block; }
/* required comment for clearfix to work in Opera \*/
* html .ui-helper-clearfix { height:1%; }
.ui-helper-clearfix { display:block; }
/* end clearfix */
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }


/* Interaction Cues
----------------------------------*/
.ui-state-disabled { cursor: default !important; }


/* Icons
----------------------------------*/

/* states and images */
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }


/* Misc visuals
----------------------------------*/

/* Overlays */
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
/*
 * jQuery UI Accordion 1.8.16
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Accordion#theming
 */
/* IE/Win - Fix animation bug - #4615 */
.ui-accordion { width: 100%; }
.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
.ui-accordion .ui-accordion-li-fix { display: inline; }
.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
.ui-accordion .ui-accordion-content-active { display: block; }
/*
 * jQuery UI Autocomplete 1.8.16
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Autocomplete#theming
 */
.ui-autocomplete { position: absolute; cursor: default; }   

/* workarounds */
* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */

/*
 * jQuery UI Menu 1.8.16
 *
 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Menu#theming
 */
.ui-menu {
    list-style:none;
    padding: 2px;
    margin: 0;
    display:block;
    float: left;
}
.ui-menu .ui-menu {
    margin-top: -3px;
}
.ui-menu .ui-menu-item {
    margin:0;
    padding: 0;
    zoom: 1;
    float: left;
    clear: left;
    width: 100%;
}
.ui-menu .ui-menu-item a {
    text-decoration:none;
    display:block;
    padding:.2em .4em;
    line-height:1.5;
    zoom:1;
}
.ui-menu .ui-menu-item a.ui-state-hover,
.ui-menu .ui-menu-item a.ui-state-active {
    font-weight: normal;
    margin: -1px;
}
/*
 * jQuery UI Button 1.8.16
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Button#theming
 */
.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
.ui-button-icons-only { width: 3.4em; } 
button.ui-button-icons-only { width: 3.7em; } 

/*button text element */
.ui-button .ui-button-text { display: block; line-height: 1.4;  }
.ui-button-text-only .ui-button-text { padding: .4em 1em; }
.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
/* no icon support for input elements, provide padding by default */
input.ui-button { padding: .4em 1em; }

/*button icon element(s) */
.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }

/*button sets*/
.ui-buttonset { margin-right: 7px; }
.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }

/* workarounds */
button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
/*
 * jQuery UI Datepicker 1.8.16
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Datepicker#theming
 */
.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
.ui-datepicker .ui-datepicker-prev { left:2px; }
.ui-datepicker .ui-datepicker-next { right:2px; }
.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
.ui-datepicker .ui-datepicker-next-hover { right:1px; }
.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px;  }
.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
.ui-datepicker select.ui-datepicker-month, 
.ui-datepicker select.ui-datepicker-year { width: 49%;}
.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }
.ui-datepicker td { border: 0; padding: 1px; }
.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }

/* with multiple calendars */
.ui-datepicker.ui-datepicker-multi { width:auto; }
.ui-datepicker-multi .ui-datepicker-group { float:left; }
.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }

/* RTL support */
.ui-datepicker-rtl { direction: rtl; }
.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
.ui-datepicker-rtl .ui-datepicker-group { float:right; }
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }

/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
.ui-datepicker-cover {
    display: none; /*sorry for IE5*/
    display/**/: block; /*sorry for IE5*/
    position: absolute; /*must have*/
    z-index: -1; /*must have*/
    filter: mask(); /*must have*/
    top: -4px; /*must have*/
    left: -4px; /*must have*/
    width: 200px; /*must have*/
    height: 200px; /*must have*/
}/*
 * jQuery UI Dialog 1.8.16
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Dialog#theming
 */
.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative;  }
.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; } 
.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
.ui-draggable .ui-dialog-titlebar { cursor: move; }
/*
 * jQuery UI Progressbar 1.8.16
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Progressbar#theming
 */
.ui-progressbar { height:2em; text-align: left; }
.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }/*
 * jQuery UI Resizable 1.8.16
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Resizable#theming
 */
.ui-resizable { position: relative;}
.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block; }
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*
 * jQuery UI Selectable 1.8.16
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Selectable#theming
 */
.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
/*
 * jQuery UI Slider 1.8.16
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Slider#theming
 */
.ui-slider { position: relative; text-align: left; }
.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }

.ui-slider-horizontal { height: .8em; }
.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
.ui-slider-horizontal .ui-slider-range-min { left: 0; }
.ui-slider-horizontal .ui-slider-range-max { right: 0; }

.ui-slider-vertical { width: .8em; height: 100px; }
.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
.ui-slider-vertical .ui-slider-range-max { top: 0; }/*
 * jQuery UI Tabs 1.8.16
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Tabs#theming
 */
.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
.ui-tabs .ui-tabs-hide { display: none !important; }
/*
 * jQuery UI CSS Framework 1.8.16
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Theming/API
 *
 * To view and modify this theme, visit http://jqueryui.com/themeroller/
 */


/* Component containers
----------------------------------*/
.ui-widget { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1.1em/*{fsDefault}*/; }
.ui-widget .ui-widget { font-size: 1em; }
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1em; }
.ui-widget-content { border: 1px solid #aaaaaa/*{borderColorContent}*/; background: #ffffff/*{bgColorContent}*/ url(images/ui-bg_flat_75_ffffff_40x100.png)/*{bgImgUrlContent}*/ 50%/*{bgContentXPos}*/ 50%/*{bgContentYPos}*/ repeat-x/*{bgContentRepeat}*/; color: #222222/*{fcContent}*/; }
.ui-widget-content a { color: #222222/*{fcContent}*/; }
.ui-widget-header { border: 1px solid #aaaaaa/*{borderColorHeader}*/; background: #cccccc/*{bgColorHeader}*/ url(images/ui-bg_highlight-soft_75_cccccc_1x100.png)/*{bgImgUrlHeader}*/ 50%/*{bgHeaderXPos}*/ 50%/*{bgHeaderYPos}*/ repeat-x/*{bgHeaderRepeat}*/; color: #222222/*{fcHeader}*/; font-weight: bold; }
.ui-widget-header a { color: #222222/*{fcHeader}*/; }

/* Interaction states
----------------------------------*/
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(images/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; }
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555/*{fcDefault}*/; text-decoration: none; }
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999/*{borderColorHover}*/; background: #dadada/*{bgColorHover}*/ url(images/ui-bg_glass_75_dadada_1x400.png)/*{bgImgUrlHover}*/ 50%/*{bgHoverXPos}*/ 50%/*{bgHoverYPos}*/ repeat-x/*{bgHoverRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcHover}*/; }
.ui-state-hover a, .ui-state-hover a:hover { color: #212121/*{fcHover}*/; text-decoration: none; }
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa/*{borderColorActive}*/; background: #ffffff/*{bgColorActive}*/ url(images/ui-bg_glass_65_ffffff_1x400.png)/*{bgImgUrlActive}*/ 50%/*{bgActiveXPos}*/ 50%/*{bgActiveYPos}*/ repeat-x/*{bgActiveRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcActive}*/; }
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121/*{fcActive}*/; text-decoration: none; }
.ui-widget :active { outline: none; }

/* Interaction Cues
----------------------------------*/
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight  {border: 1px solid #fcefa1/*{borderColorHighlight}*/; background: #fbf9ee/*{bgColorHighlight}*/ url(images/ui-bg_glass_55_fbf9ee_1x400.png)/*{bgImgUrlHighlight}*/ 50%/*{bgHighlightXPos}*/ 50%/*{bgHighlightYPos}*/ repeat-x/*{bgHighlightRepeat}*/; color: #363636/*{fcHighlight}*/; }
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636/*{fcHighlight}*/; }
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a/*{borderColorError}*/; background: #fef1ec/*{bgColorError}*/ url(images/ui-bg_glass_95_fef1ec_1x400.png)/*{bgImgUrlError}*/ 50%/*{bgErrorXPos}*/ 50%/*{bgErrorYPos}*/ repeat-x/*{bgErrorRepeat}*/; color: #cd0a0a/*{fcError}*/; }
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a/*{fcError}*/; }
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a/*{fcError}*/; }
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary,  .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }

/* Icons
----------------------------------*/

/* states and images */
.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; }
.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; }
.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsHeader}*/; }
.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png)/*{iconsDefault}*/; }
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsHover}*/; }
.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsActive}*/; }
.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png)/*{iconsHighlight}*/; }
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png)/*{iconsError}*/; }

/* positioning */
.ui-icon-carat-1-n { background-position: 0 0; }
.ui-icon-carat-1-ne { background-position: -16px 0; }
.ui-icon-carat-1-e { background-position: -32px 0; }
.ui-icon-carat-1-se { background-position: -48px 0; }
.ui-icon-carat-1-s { background-position: -64px 0; }
.ui-icon-carat-1-sw { background-position: -80px 0; }
.ui-icon-carat-1-w { background-position: -96px 0; }
.ui-icon-carat-1-nw { background-position: -112px 0; }
.ui-icon-carat-2-n-s { background-position: -128px 0; }
.ui-icon-carat-2-e-w { background-position: -144px 0; }
.ui-icon-triangle-1-n { background-position: 0 -16px; }
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
.ui-icon-triangle-1-e { background-position: -32px -16px; }
.ui-icon-triangle-1-se { background-position: -48px -16px; }
.ui-icon-triangle-1-s { background-position: -64px -16px; }
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
.ui-icon-triangle-1-w { background-position: -96px -16px; }
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
.ui-icon-arrow-1-n { background-position: 0 -32px; }
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
.ui-icon-arrow-1-e { background-position: -32px -32px; }
.ui-icon-arrow-1-se { background-position: -48px -32px; }
.ui-icon-arrow-1-s { background-position: -64px -32px; }
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
.ui-icon-arrow-1-w { background-position: -96px -32px; }
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
.ui-icon-arrow-4 { background-position: 0 -80px; }
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
.ui-icon-extlink { background-position: -32px -80px; }
.ui-icon-newwin { background-position: -48px -80px; }
.ui-icon-refresh { background-position: -64px -80px; }
.ui-icon-shuffle { background-position: -80px -80px; }
.ui-icon-transfer-e-w { background-position: -96px -80px; }
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
.ui-icon-folder-collapsed { background-position: 0 -96px; }
.ui-icon-folder-open { background-position: -16px -96px; }
.ui-icon-document { background-position: -32px -96px; }
.ui-icon-document-b { background-position: -48px -96px; }
.ui-icon-note { background-position: -64px -96px; }
.ui-icon-mail-closed { background-position: -80px -96px; }
.ui-icon-mail-open { background-position: -96px -96px; }
.ui-icon-suitcase { background-position: -112px -96px; }
.ui-icon-comment { background-position: -128px -96px; }
.ui-icon-person { background-position: -144px -96px; }
.ui-icon-print { background-position: -160px -96px; }
.ui-icon-trash { background-position: -176px -96px; }
.ui-icon-locked { background-position: -192px -96px; }
.ui-icon-unlocked { background-position: -208px -96px; }
.ui-icon-bookmark { background-position: -224px -96px; }
.ui-icon-tag { background-position: -240px -96px; }
.ui-icon-home { background-position: 0 -112px; }
.ui-icon-flag { background-position: -16px -112px; }
.ui-icon-calendar { background-position: -32px -112px; }
.ui-icon-cart { background-position: -48px -112px; }
.ui-icon-pencil { background-position: -64px -112px; }
.ui-icon-clock { background-position: -80px -112px; }
.ui-icon-disk { background-position: -96px -112px; }
.ui-icon-calculator { background-position: -112px -112px; }
.ui-icon-zoomin { background-position: -128px -112px; }
.ui-icon-zoomout { background-position: -144px -112px; }
.ui-icon-search { background-position: -160px -112px; }
.ui-icon-wrench { background-position: -176px -112px; }
.ui-icon-gear { background-position: -192px -112px; }
.ui-icon-heart { background-position: -208px -112px; }
.ui-icon-star { background-position: -224px -112px; }
.ui-icon-link { background-position: -240px -112px; }
.ui-icon-cancel { background-position: 0 -128px; }
.ui-icon-plus { background-position: -16px -128px; }
.ui-icon-plusthick { background-position: -32px -128px; }
.ui-icon-minus { background-position: -48px -128px; }
.ui-icon-minusthick { background-position: -64px -128px; }
.ui-icon-close { background-position: -80px -128px; }
.ui-icon-closethick { background-position: -96px -128px; }
.ui-icon-key { background-position: -112px -128px; }
.ui-icon-lightbulb { background-position: -128px -128px; }
.ui-icon-scissors { background-position: -144px -128px; }
.ui-icon-clipboard { background-position: -160px -128px; }
.ui-icon-copy { background-position: -176px -128px; }
.ui-icon-contact { background-position: -192px -128px; }
.ui-icon-image { background-position: -208px -128px; }
.ui-icon-video { background-position: -224px -128px; }
.ui-icon-script { background-position: -240px -128px; }
.ui-icon-alert { background-position: 0 -144px; }
.ui-icon-info { background-position: -16px -144px; }
.ui-icon-notice { background-position: -32px -144px; }
.ui-icon-help { background-position: -48px -144px; }
.ui-icon-check { background-position: -64px -144px; }
.ui-icon-bullet { background-position: -80px -144px; }
.ui-icon-radio-off { background-position: -96px -144px; }
.ui-icon-radio-on { background-position: -112px -144px; }
.ui-icon-pin-w { background-position: -128px -144px; }
.ui-icon-pin-s { background-position: -144px -144px; }
.ui-icon-play { background-position: 0 -160px; }
.ui-icon-pause { background-position: -16px -160px; }
.ui-icon-seek-next { background-position: -32px -160px; }
.ui-icon-seek-prev { background-position: -48px -160px; }
.ui-icon-seek-end { background-position: -64px -160px; }
.ui-icon-seek-start { background-position: -80px -160px; }
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
.ui-icon-seek-first { background-position: -80px -160px; }
.ui-icon-stop { background-position: -96px -160px; }
.ui-icon-eject { background-position: -112px -160px; }
.ui-icon-volume-off { background-position: -128px -160px; }
.ui-icon-volume-on { background-position: -144px -160px; }
.ui-icon-power { background-position: 0 -176px; }
.ui-icon-signal-diag { background-position: -16px -176px; }
.ui-icon-signal { background-position: -32px -176px; }
.ui-icon-battery-0 { background-position: -48px -176px; }
.ui-icon-battery-1 { background-position: -64px -176px; }
.ui-icon-battery-2 { background-position: -80px -176px; }
.ui-icon-battery-3 { background-position: -96px -176px; }
.ui-icon-circle-plus { background-position: 0 -192px; }
.ui-icon-circle-minus { background-position: -16px -192px; }
.ui-icon-circle-close { background-position: -32px -192px; }
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
.ui-icon-circle-zoomin { background-position: -176px -192px; }
.ui-icon-circle-zoomout { background-position: -192px -192px; }
.ui-icon-circle-check { background-position: -208px -192px; }
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
.ui-icon-circlesmall-close { background-position: -32px -208px; }
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
.ui-icon-squaresmall-close { background-position: -80px -208px; }
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }


/* Misc visuals
----------------------------------*/

/* Corner radius */
.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; -khtml-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; }
.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; -khtml-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; }
.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; -khtml-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; }
.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; -khtml-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; }

/* Overlays */
.ui-widget-overlay { background: #aaaaaa/*{bgColorOverlay}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlOverlay}*/ 50%/*{bgOverlayXPos}*/ 50%/*{bgOverlayYPos}*/ repeat-x/*{bgOverlayRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityOverlay}*/; }
.ui-widget-shadow { margin: -8px/*{offsetTopShadow}*/ 0 0 -8px/*{offsetLeftShadow}*/; padding: 8px/*{thicknessShadow}*/; background: #aaaaaa/*{bgColorShadow}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlShadow}*/ 50%/*{bgShadowXPos}*/ 50%/*{bgShadowYPos}*/ repeat-x/*{bgShadowRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityShadow}*/; -moz-border-radius: 8px/*{cornerRadiusShadow}*/; -khtml-border-radius: 8px/*{cornerRadiusShadow}*/; -webkit-border-radius: 8px/*{cornerRadiusShadow}*/; border-radius: 8px/*{cornerRadiusShadow}*/; }<?xml version="1.0" encoding="utf-8"?>
<template>
  <author>Mike van Riel</author>
  <email>mike.vanriel@naenius.com</email>
  <version>1.1.0</version>
  <copyright>Mike van Riel / Naenius 2012</copyright>
  <description>This is the New Black look and feel for phpDocumentor</description>
  <dependencies>
      <template name="abstract" version="1.0.3" />
  </dependencies>
  <transformations>
    <transformation writer="xml" artifact="structure.xml"/>
    <transformation query="copy" writer="FileIo" source="templates/new-black/ajax_search.php" artifact="ajax_search.php"/>
    <transformation query="copy" writer="FileIo" source="templates/abstract/js" artifact="js"/>
    <transformation query="copy" writer="FileIo" source="templates/abstract/images" artifact="images"/>
    <transformation query="copy" writer="FileIo" source="templates/abstract/css" artifact="css"/>
    <transformation query="copy" writer="FileIo" source="templates/new-black/css" artifact="css"/>
    <transformation query="copy" writer="FileIo" source="templates/new-black/js" artifact="js"/>
    <transformation writer="xml" artifact="structure.xml" />
    <!--<transformation query="" writer="Search" source="" artifact="."/>-->
    <transformation writer="xsl" source="templates/abstract/index.xsl" artifact="index.html"/>
    <transformation writer="xsl" source="templates/abstract/content.xsl" artifact="content.html"/>
    <transformation writer="xsl" source="templates/new-black/sidebar.xsl" artifact="nav.html">
        <parameters>
            <variables>
                <section.dashboard.show>false</section.dashboard.show>
                <section.api.show/>
                <section.namespaces.show/>
                <section.packages.show/>
                <section.files.show/>
                <section.files.show-elements/>
                <section.reports.show />
                <section.charts.show />
            </variables>
        </parameters>
    </transformation>
    <transformation query="/project/file/@path" writer="xsl" source="templates/abstract/api-doc.xsl" artifact="files/{$path}"/>
    <transformation writer="xsl" source="templates/abstract/report_markers.xsl" artifact="report_markers.html"/>
    <transformation writer="xsl" source="templates/abstract/report_parse_markers.xsl" artifact="report_parse_markers.html"/>
    <transformation writer="xsl" source="templates/abstract/report_deprecated.xsl" artifact="report_deprecated.html"/>
    <transformation writer="sourcecode" />
    <transformation writer="xsl" source="templates/abstract/graph_class.xsl" artifact="graph.html"/>
    <transformation writer="Graph" source="Class" artifact="classes.svg" />
  </transformations>
</template>
{
    "_readme": [
        "This file locks the dependencies of your project to a known state",
        "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
    ],
    "hash": "c4da9c0dc166887cf90e4eab8ec63cd2",
    "packages": [
        {
            "name": "phpdocumentor/template-abstract",
            "version": "1.2",
            "source": {
                "type": "git",
                "url": "https://github.com/phpDocumentor/template.abstract.git",
                "reference": "1.2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phpDocumentor/template.abstract/zipball/1.2",
                "reference": "1.2",
                "shasum": ""
            },
            "require": {
                "ext-xsl": "*",
                "phpdocumentor/unified-asset-installer": "~1.1"
            },
            "type": "phpdocumentor-template",
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "description": "Simple bright template for phpDocumentor",
            "homepage": "http://www.phpdoc.org",
            "keywords": [
                "documentation",
                "phpdoc",
                "template"
            ],
            "time": "2013-08-01 19:38:43"
        },
        {
            "name": "phpdocumentor/unified-asset-installer",
            "version": "1.1",
            "source": {
                "type": "git",
                "url": "https://github.com/phpDocumentor/UnifiedAssetInstaller.git",
                "reference": "1.1"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phpDocumentor/UnifiedAssetInstaller/zipball/1.1",
                "reference": "1.1",
                "shasum": ""
            },
            "require-dev": {
                "composer/composer": "~1.0@dev",
                "phpunit/phpunit": "~3.7"
            },
            "type": "composer-installer",
            "extra": {
                "class": "\\phpDocumentor\\Composer\\UnifiedAssetInstaller"
            },
            "autoload": {
                "psr-0": {
                    "phpDocumentor\\Composer": [
                        "src/",
                        "test/unit/"
                    ]
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "description": "Asset installer for phpDocumentor",
            "homepage": "http://www.phpdoc.org",
            "keywords": [
                "assets",
                "installer",
                "plugins",
                "templates"
            ],
            "time": "2013-08-01 19:35:55"
        }
    ],
    "packages-dev": [

    ],
    "aliases": [

    ],
    "minimum-stability": "stable",
    "stability-flags": [

    ],
    "platform": {
        "ext-xsl": "*"
    },
    "platform-dev": [

    ]
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5
 *
 * @category  phpDocumentor
 * @package   Search
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

// get search term
$term = strtolower($_GET['term']);

// find term in XML document
$xml = new DOMDocument();
$xml->load('search_index.xml');
$xpath = new DOMXPath($xml);

$qry = $xpath->query(
    "//value[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', "
    . "'abcdefghijklmnopqrstuvwxyz'), '$term')]/.."
);
$results = array();

/** @var DOMElement $element */
foreach ($qry as $element) {
    /** @var DomNodeList $value  */
    $value     = $element->getElementsByTagName('value');
    $id        = $element->getElementsByTagName('id');
    $type      = $element->getElementsByTagName('type');
    $results[] = '{ "value": "' . addslashes($value->item(0)->nodeValue)
    . '", "id": "' . addslashes($id->item(0)->nodeValue)
    . '", "type": "' . addslashes($type->item(0)->nodeValue) . '" }';
}

echo '[' . implode(', ', $results) . ']';
<?xml version="1.0"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes" method="html" />

  <xsl:template name="search">
    <xsl:param name="root" />

    <script type="text/javascript">
      $(function() {

        var is_chrome = /chrome/.test( navigator.userAgent.toLowerCase() );
        var is_local = /file:\/\//.test(document.location.href);
        if (is_chrome &amp;&amp; is_local)
        {
          // search is disabled on chrome with local files due to http://code.google.com/p/chromium/issues/detail?id=40787
          return;
        }

        $("#search_box").show();
        $("#search_box_icon").show();
        $("#search_box_clear").show();
        var search_index = {};
        $.ajax({
          url: "<xsl:value-of select="$root" />search_index.xml",
          dataType: ($.browser.msie) ? "text" : "xml",
          error: function(data) {
            alert('An error occurred using the search data');
          },
          success: function( data ) {
            var xml;
            if (typeof data == "string") {
              xml = new ActiveXObject("Microsoft.XMLDOM");
              xml.async = false;
              xml.loadXML(data);
            } else {
              xml = data;
            }

            search_index = $("node", xml).map(function() {
              type = $("type", this).text();
              return {
                value: $("value", this).text(),
                label: '<img src="{$root}images/icons/'+type+'.png" align="absmiddle" />'+$("value", this).text(),
                id: $("id", this).text(),
              };
            }).get();

            $("#search_box").autocomplete({
              source: search_index,
              select: function(event, ui) {
                // redirect to the documentation
                if ((parent) &amp;&amp; (parent.content))
                {
                  parent.content.document.location = '<xsl:value-of select="$root" />'+ui.item.id;
                }
                else
                {
                  jQuery(document).location = '<xsl:value-of select="$root" />'+ui.item.id;
                }
              }
            });
          }
        });
      });
    </script>

    <img src="{$root}images/search.gif" id="search_box_icon" border="0" onclick="$('#search_box').focus()"/>
    <input id="search_box" />
    <img src="{$root}images/clear_left.png" id="search_box_clear" border="0" onclick="$('#search_box').val('')"/>
  </xsl:template>

</xsl:stylesheet><?xml version="1.0"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes" method="html" />

  <xsl:template name="search">
    <xsl:param name="root" />

    <script type="text/javascript">
        $(function() {
            $("#search_box_icon, #search_box_clear").show();
            $("#search_box").show().autocomplete({
                source: "<xsl:value-of select="$root"/>ajax_search.php",
                minLength: 2,
                select: function (event, ui) {
                    if ((parent) &amp;&amp; (parent.content)) {
                        parent.content.document.location = '' + ui.item.id;
                    } else {
                        jQuery(document).location = '' + ui.item.id;
                    }
                }
            });
        });
    </script>

    <img src="{$root}images/search.gif" id="search_box_icon" border="0" onclick="$('#search_box').focus()" />
    <input id="search_box" />
    <img src="{$root}images/clear_left.png" id="search_box_clear" border="0" onclick="$('#search_box').val('')" />
  </xsl:template>

</xsl:stylesheet><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
    <xsl:output indent="yes" method="html" />
    <xsl:include href="chrome.xsl" />
    <xsl:include href="sidebar/header.xsl" />
    <xsl:include href="sidebar/footer.xsl" />
    <xsl:include href="sidebar/sections/api.xsl"/>
    <xsl:include href="sidebar/sections/charts.xsl"/>
    <xsl:include href="sidebar/sections/files.xsl"/>
    <xsl:include href="sidebar/sections/namespaces.xsl"/>
    <xsl:include href="sidebar/sections/packages.xsl"/>
    <xsl:include href="sidebar/sections/reports.xsl"/>

    <xsl:param name="section.api.show" />
    <xsl:param name="section.packages.show" />
    <xsl:param name="section.namespaces.show" />
    <xsl:param name="section.files.show" />
    <xsl:param name="section.files.show-elements" />
    <xsl:param name="section.charts.show" />
    <xsl:param name="section.reports.show" />

    <xsl:template name="content">
        <div id="sidebar">
            <div id="sidebar-header">
                <xsl:call-template name="sidebar-header"/>
            </div>

            <div id="sidebar-nav">
                <xsl:if test="$section.api.show != 'false'">
                    <xsl:if test="count(/project/file/*/docblock/tag[@name='api']|/project/file/class/*/docblock/tag[@name='api']|/project/file/interface/*/docblock/tag[@name='api']) > 0">
                    <h3 data-toggle="collapse" data-target="#sidebar-api-menu" id="sidebar-api">API</h3>
                    <div class="collapse" id="sidebar-api-menu">
                        <xsl:call-template name="sidebar-section-api"/>
                    </div>
                    </xsl:if>
                </xsl:if>

                <xsl:if test="$section.packages.show != 'false'">
                    <xsl:if test="count(/project/package[@name != 'Default']) > 0">
                    <h3 data-toggle="collapse" data-target="#sidebar-packages-menu" id="sidebar-packages" class="collapsed">Packages</h3>
                    <div class="collapse" id="sidebar-packages-menu">
                        <xsl:call-template name="sidebar-section-packages"/>
                    </div>
                    </xsl:if>
                </xsl:if>


                <xsl:if test="$section.namespaces.show != 'false'">
                    <xsl:if test="count(/project/namespace[@name != 'default']) > 0">
                    <h3 data-toggle="collapse" data-target="#sidebar-namespaces-menu" id="sidebar-namespaces" class="collapsed">Namespaces</h3>
                    <div class="collapse" id="sidebar-namespaces-menu">
                        <xsl:call-template name="sidebar-section-namespaces"/>
                    </div>
                    </xsl:if>
                </xsl:if>

                <xsl:if test="$section.files.show != 'false'">
                <h3 data-toggle="collapse" data-target="#sidebar-files-menu" id="sidebar-files" class="collapsed">Files</h3>
                <div class="collapse" id="sidebar-files-menu">
                    <xsl:call-template name="sidebar-section-files"/>
                </div>
                </xsl:if>

                <xsl:if test="$section.charts.show != 'false'">
                <h3 id="sidebar-charts">Charts</h3>
                <div class="sidebar-section">
                    <ul style="list-style-image: url('css/phpdoc/images/icons/chart15x12.png');">
                        <xsl:call-template name="sidebar-section-charts"/>
                    </ul>
                </div>
                </xsl:if>

                <xsl:if test="$section.reports.show != 'false'">
                    <h3 id="sidebar-reports">Reports</h3>
                    <div class="sidebar-section">
                        <ul style="list-style-image: url('css/phpdoc/images/icons/reports9x12.png');">
                            <xsl:call-template name="sidebar-section-reports"/>
                        </ul>
                    </div>
                </xsl:if>
            </div>

            <div id="sidebar-footer">
                <xsl:call-template name="sidebar-footer"/>
            </div>
        </div>
    </xsl:template>

</xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
    <xsl:output indent="yes" method="html"/>

    <xsl:include href="chrome.xsl"/>

    <xsl:include href="api-doc/property.xsl"/>
    <xsl:include href="api-doc/class.xsl"/>
    <xsl:include href="api-doc/constant.xsl"/>
    <xsl:include href="api-doc/function.xsl"/>
    <xsl:include href="api-doc/docblock.xsl"/>
    <xsl:include href="api-doc/file.xsl"/>

    <xsl:template name="content">
        <div id="content">
            <xsl:apply-templates select="/project/file[@path=$path]"/>
        </div>

        <small class="footer">
            Documentation was generated by
            <a href="http://phpdoc.org">phpDocumentor
                <xsl:value-of select="$version"/>
            </a>.
        </small>
    </xsl:template>

</xsl:stylesheet>{
    "name": "phpdocumentor/template-abstract",
    "type": "phpdocumentor-template",
    "description": "Simple bright template for phpDocumentor",
    "keywords": ["documentation", "template", "phpdoc"],
    "homepage": "http://www.phpdoc.org",
    "license": "MIT",
    "require": {
        "ext-xsl": "*",
        "phpdocumentor/unified-asset-installer": "~1.1"
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.9.4" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
    http://pear.php.net/dtd/tasks-1.0.xsd
    http://pear.php.net/dtd/package-2.0
    http://pear.php.net/dtd/package-2.0.xsd">
 <name>phpDocumentor_Template_abstract</name>
 <channel>pear.phpdoc.org</channel>
 <summary>The abstract template for phpDocumentor</summary>
 <description>This is a light theme for phpDocumentor that can be used as basis for other themes</description>
 <lead>
  <name>Mike van Riel</name>
  <user />
  <email>mike.vanriel@naenius.com</email>
  <active>yes</active>
 </lead>
 <date>2012-04-01</date>
 <time>10:31:10</time>
 <version>
  <release>1.0.3</release>
  <api>1.0.3</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license uri="http://www.opensource.org/licenses/mit-license.html">MIT</license>
 <notes>
Automatically generated by the phpDocumentor packager
 </notes>
 <contents>
  <dir baseinstalldir="/phpDocumentor/data/templates/abstract" name="/">
   <dir name="api-doc">
    <file name="class.xsl" role="php" />
    <file name="constant.xsl" role="php" />
    <file name="docblock.xsl" role="php" />
    <file name="file.xsl" role="php" />
    <file name="function.xsl" role="php" />
    <file name="property.xsl" role="php" />
   </dir> <!-- /api-doc -->
   <dir name="chrome">
    <file name="footer.xsl" role="php" />
    <file name="head.xsl" role="php" />
    <file name="header.xsl" role="php" />
    <file name="menu.xsl" role="php" />
   </dir> <!-- /chrome -->
   <dir name="css">
    <file name="abstract.css" role="php" />
    <file name="sen.full.min.css" role="php" />
    <file name="template.css" role="php" />
   </dir> <!-- /css -->
   <dir name="images">
    <file name="collapse_all.png" role="php" />
    <file name="expand_all.png" role="php" />
    <file name="logo.png" role="php" />
    <file name="search.gif" role="php" />
   </dir> <!-- /images -->
   <dir name="js">
    <file name="template.js" role="php" />
   </dir> <!-- /js -->
   <dir name="sidebar">
    <dir name="sections">
     <file name="api.xsl" role="php" />
     <file name="charts.xsl" role="php" />
     <file name="files.xsl" role="php" />
     <file name="namespaces.xsl" role="php" />
     <file name="packages.xsl" role="php" />
     <file name="reports.xsl" role="php" />
    </dir> <!-- /sidebar/sections -->
    <file name="footer.xsl" role="php" />
    <file name="header.xsl" role="php" />
    <file name="sections.xsl" role="php" />
   </dir> <!-- /sidebar -->
   <file name="api-doc.xsl" role="php" />
   <file name="chrome.xsl" role="php" />
   <file name="content.xsl" role="php" />
   <file name="graph_class.xsl" role="php" />
   <file name="helpers.xsl" role="php" />
   <file name="index.xsl" role="php" />
   <file name="README" role="php" />
   <file name="report_deprecated.xsl" role="php" />
   <file name="report_markers.xsl" role="php" />
   <file name="report_parse_markers.xsl" role="php" />
   <file name="sidebar.xsl" role="php" />
   <file name="template.xml" role="php" />
  </dir> <!-- / -->
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.2.6</min>
   </php>
   <pearinstaller>
    <min>1.4.0</min>
   </pearinstaller>
   <package>
    <name>PEAR</name>
    <channel>pear.php.net</channel>
    <min>1.4.0</min>
   </package>
   <package>
    <name>phpDocumentor</name>
    <channel>pear.phpdoc.org</channel>
    <min>0.17.0</min>
   </package>
  </required>
 </dependencies>
 <phprelease />
 <changelog>
  <release>
   <version>
    <release>1.0.3</release>
    <api>1.0.3</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2012-04-01</date>
   <license uri="http://www.opensource.org/licenses/mit-license.html">MIT</license>
   <notes>
Automatically generated by the phpDocumentor packager
   </notes>
  </release>
 </changelog>
</package>
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
  <xsl:output indent="yes" method="html" />
  <xsl:include href="chrome.xsl" />

  <xsl:template name="content">

      <div id="content">

          <h1>Deprecated elements</h1>
          <xsl:if test="count(//docblock/tag[@name='deprecated']) &lt; 1">
              <div class="alert alert-success">No deprecated elements have been found in this project.</div>
          </xsl:if>
          <div id="marker-accordion">
            <xsl:for-each select="/project/file">
                <xsl:if test=".//docblock/tag[@name='deprecated']">
                    <h3>
                        <a href="#">
                            <xsl:value-of select="@path"/>
                            <small><xsl:value-of select="count(.//docblock/tag[@name='deprecated'])"/></small>
                        </a>
                    </h3>
                    <div>
                        <table class="table">
                            <tr><th>Type</th><th>Line</th><th>Description</th></tr>
                            <xsl:for-each select=".//docblock/tag[@name='deprecated']">
                                <xsl:sort select="line"/>
                                <tr>
                                    <xsl:if test="name() = 'tag'">
                                        <td><xsl:value-of select="@name"/></td>
                                    </xsl:if>
                                    <xsl:if test="name() != 'tag'">
                                        <td><xsl:value-of select="name()"/></td>
                                    </xsl:if>
                                    <td><xsl:value-of select="@line"/></td>
                                    <xsl:if test="name() = 'tag'">
                                        <td>
                                            <xsl:value-of select="@description" disable-output-escaping="yes"/>
                                        </td>
                                    </xsl:if>
                                    <xsl:if test="name() != 'tag'">
                                        <td>
                                            <xsl:value-of select="." disable-output-escaping="yes"/>
                                        </td>
                                    </xsl:if>
                                </tr>
                            </xsl:for-each>
                        </table>
                    </div>
                </xsl:if>
            </xsl:for-each>
        </div>

    </div>
  </xsl:template>

</xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
    <xsl:output indent="yes" method="html"/>
    <xsl:include href="chrome.xsl"/>
    <xsl:include href="chrome/header.xsl"/>
    <xsl:include href="sidebar/sections/charts.xsl"/>
    <xsl:include href="sidebar/sections/reports.xsl"/>

    <xsl:template match="/">
        <xsl:call-template name="root">
            <xsl:with-param name="pageId" select="'frameset'" />
        </xsl:call-template>
    </xsl:template>

    <xsl:template name="content">
        <div class="container-fluid">
            <header class="row">
                <section class="col-sm-5">
                    <xsl:call-template name="page-header" />
                </section>
                <section class="col-sm-7">
                    <ul class="nav nav-tabs pull-right">
                        <xsl:call-template name="sidebar-section-charts"/>
                        <xsl:call-template name="sidebar-section-reports"/>
                    </ul>
                </section>
            </header>
            <div class="row">
                <section class="col-sm-3">
                    <iframe name="nav" id="nav" src="{$root}nav.html"/>
                </section>
                <section class="col-sm-9">
                    <iframe name="content" id="content" src="{$root}content.html"/>
                </section>
            </div>
            <footer class="row">
                <section class="col-sm-12">
                </section>
            </footer>
        </div>
    </xsl:template>

</xsl:stylesheet>
/*
 * Downloaded from http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js, 2012-02-04 23:26
 */

/*!
 * jQuery JavaScript Library v1.7.1
 * http://jquery.com/
 *
 * Copyright 2011, John Resig
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * Includes Sizzle.js
 * http://sizzlejs.com/
 * Copyright 2011, The Dojo Foundation
 * Released under the MIT, BSD, and GPL Licenses.
 *
 * Date: Mon Nov 21 21:11:03 2011 -0500
 */
(function( window, undefined ) {

// Use the correct document accordingly with window argument (sandbox)
var document = window.document,
	navigator = window.navigator,
	location = window.location;
var jQuery = (function() {

// Define a local copy of jQuery
var jQuery = function( selector, context ) {
		// The jQuery object is actually just the init constructor 'enhanced'
		return new jQuery.fn.init( selector, context, rootjQuery );
	},

	// Map over jQuery in case of overwrite
	_jQuery = window.jQuery,

	// Map over the $ in case of overwrite
	_$ = window.$,

	// A central reference to the root jQuery(document)
	rootjQuery,

	// A simple way to check for HTML strings or ID strings
	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
	quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,

	// Check if a string has a non-whitespace character in it
	rnotwhite = /\S/,

	// Used for trimming whitespace
	trimLeft = /^\s+/,
	trimRight = /\s+$/,

	// Match a standalone tag
	rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,

	// JSON RegExp
	rvalidchars = /^[\],:{}\s]*$/,
	rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
	rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
	rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,

	// Useragent RegExp
	rwebkit = /(webkit)[ \/]([\w.]+)/,
	ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
	rmsie = /(msie) ([\w.]+)/,
	rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,

	// Matches dashed string for camelizing
	rdashAlpha = /-([a-z]|[0-9])/ig,
	rmsPrefix = /^-ms-/,

	// Used by jQuery.camelCase as callback to replace()
	fcamelCase = function( all, letter ) {
		return ( letter + "" ).toUpperCase();
	},

	// Keep a UserAgent string for use with jQuery.browser
	userAgent = navigator.userAgent,

	// For matching the engine and version of the browser
	browserMatch,

	// The deferred used on DOM ready
	readyList,

	// The ready event handler
	DOMContentLoaded,

	// Save a reference to some core methods
	toString = Object.prototype.toString,
	hasOwn = Object.prototype.hasOwnProperty,
	push = Array.prototype.push,
	slice = Array.prototype.slice,
	trim = String.prototype.trim,
	indexOf = Array.prototype.indexOf,

	// [[Class]] -> type pairs
	class2type = {};

jQuery.fn = jQuery.prototype = {
	constructor: jQuery,
	init: function( selector, context, rootjQuery ) {
		var match, elem, ret, doc;

		// Handle $(""), $(null), or $(undefined)
		if ( !selector ) {
			return this;
		}

		// Handle $(DOMElement)
		if ( selector.nodeType ) {
			this.context = this[0] = selector;
			this.length = 1;
			return this;
		}

		// The body element only exists once, optimize finding it
		if ( selector === "body" && !context && document.body ) {
			this.context = document;
			this[0] = document.body;
			this.selector = selector;
			this.length = 1;
			return this;
		}

		// Handle HTML strings
		if ( typeof selector === "string" ) {
			// Are we dealing with HTML string or an ID?
			if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
				// Assume that strings that start and end with <> are HTML and skip the regex check
				match = [ null, selector, null ];

			} else {
				match = quickExpr.exec( selector );
			}

			// Verify a match, and that no context was specified for #id
			if ( match && (match[1] || !context) ) {

				// HANDLE: $(html) -> $(array)
				if ( match[1] ) {
					context = context instanceof jQuery ? context[0] : context;
					doc = ( context ? context.ownerDocument || context : document );

					// If a single string is passed in and it's a single tag
					// just do a createElement and skip the rest
					ret = rsingleTag.exec( selector );

					if ( ret ) {
						if ( jQuery.isPlainObject( context ) ) {
							selector = [ document.createElement( ret[1] ) ];
							jQuery.fn.attr.call( selector, context, true );

						} else {
							selector = [ doc.createElement( ret[1] ) ];
						}

					} else {
						ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
						selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;
					}

					return jQuery.merge( this, selector );

				// HANDLE: $("#id")
				} else {
					elem = document.getElementById( match[2] );

					// Check parentNode to catch when Blackberry 4.6 returns
					// nodes that are no longer in the document #6963
					if ( elem && elem.parentNode ) {
						// Handle the case where IE and Opera return items
						// by name instead of ID
						if ( elem.id !== match[2] ) {
							return rootjQuery.find( selector );
						}

						// Otherwise, we inject the element directly into the jQuery object
						this.length = 1;
						this[0] = elem;
					}

					this.context = document;
					this.selector = selector;
					return this;
				}

			// HANDLE: $(expr, $(...))
			} else if ( !context || context.jquery ) {
				return ( context || rootjQuery ).find( selector );

			// HANDLE: $(expr, context)
			// (which is just equivalent to: $(context).find(expr)
			} else {
				return this.constructor( context ).find( selector );
			}

		// HANDLE: $(function)
		// Shortcut for document ready
		} else if ( jQuery.isFunction( selector ) ) {
			return rootjQuery.ready( selector );
		}

		if ( selector.selector !== undefined ) {
			this.selector = selector.selector;
			this.context = selector.context;
		}

		return jQuery.makeArray( selector, this );
	},

	// Start with an empty selector
	selector: "",

	// The current version of jQuery being used
	jquery: "1.7.1",

	// The default length of a jQuery object is 0
	length: 0,

	// The number of elements contained in the matched element set
	size: function() {
		return this.length;
	},

	toArray: function() {
		return slice.call( this, 0 );
	},

	// Get the Nth element in the matched element set OR
	// Get the whole matched element set as a clean array
	get: function( num ) {
		return num == null ?

			// Return a 'clean' array
			this.toArray() :

			// Return just the object
			( num < 0 ? this[ this.length + num ] : this[ num ] );
	},

	// Take an array of elements and push it onto the stack
	// (returning the new matched element set)
	pushStack: function( elems, name, selector ) {
		// Build a new jQuery matched element set
		var ret = this.constructor();

		if ( jQuery.isArray( elems ) ) {
			push.apply( ret, elems );

		} else {
			jQuery.merge( ret, elems );
		}

		// Add the old object onto the stack (as a reference)
		ret.prevObject = this;

		ret.context = this.context;

		if ( name === "find" ) {
			ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
		} else if ( name ) {
			ret.selector = this.selector + "." + name + "(" + selector + ")";
		}

		// Return the newly-formed element set
		return ret;
	},

	// Execute a callback for every element in the matched set.
	// (You can seed the arguments with an array of args, but this is
	// only used internally.)
	each: function( callback, args ) {
		return jQuery.each( this, callback, args );
	},

	ready: function( fn ) {
		// Attach the listeners
		jQuery.bindReady();

		// Add the callback
		readyList.add( fn );

		return this;
	},

	eq: function( i ) {
		i = +i;
		return i === -1 ?
			this.slice( i ) :
			this.slice( i, i + 1 );
	},

	first: function() {
		return this.eq( 0 );
	},

	last: function() {
		return this.eq( -1 );
	},

	slice: function() {
		return this.pushStack( slice.apply( this, arguments ),
			"slice", slice.call(arguments).join(",") );
	},

	map: function( callback ) {
		return this.pushStack( jQuery.map(this, function( elem, i ) {
			return callback.call( elem, i, elem );
		}));
	},

	end: function() {
		return this.prevObject || this.constructor(null);
	},

	// For internal use only.
	// Behaves like an Array's method, not like a jQuery method.
	push: push,
	sort: [].sort,
	splice: [].splice
};

// Give the init function the jQuery prototype for later instantiation
jQuery.fn.init.prototype = jQuery.fn;

jQuery.extend = jQuery.fn.extend = function() {
	var options, name, src, copy, copyIsArray, clone,
		target = arguments[0] || {},
		i = 1,
		length = arguments.length,
		deep = false;

	// Handle a deep copy situation
	if ( typeof target === "boolean" ) {
		deep = target;
		target = arguments[1] || {};
		// skip the boolean and the target
		i = 2;
	}

	// Handle case when target is a string or something (possible in deep copy)
	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
		target = {};
	}

	// extend jQuery itself if only one argument is passed
	if ( length === i ) {
		target = this;
		--i;
	}

	for ( ; i < length; i++ ) {
		// Only deal with non-null/undefined values
		if ( (options = arguments[ i ]) != null ) {
			// Extend the base object
			for ( name in options ) {
				src = target[ name ];
				copy = options[ name ];

				// Prevent never-ending loop
				if ( target === copy ) {
					continue;
				}

				// Recurse if we're merging plain objects or arrays
				if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
					if ( copyIsArray ) {
						copyIsArray = false;
						clone = src && jQuery.isArray(src) ? src : [];

					} else {
						clone = src && jQuery.isPlainObject(src) ? src : {};
					}

					// Never move original objects, clone them
					target[ name ] = jQuery.extend( deep, clone, copy );

				// Don't bring in undefined values
				} else if ( copy !== undefined ) {
					target[ name ] = copy;
				}
			}
		}
	}

	// Return the modified object
	return target;
};

jQuery.extend({
	noConflict: function( deep ) {
		if ( window.$ === jQuery ) {
			window.$ = _$;
		}

		if ( deep && window.jQuery === jQuery ) {
			window.jQuery = _jQuery;
		}

		return jQuery;
	},

	// Is the DOM ready to be used? Set to true once it occurs.
	isReady: false,

	// A counter to track how many items to wait for before
	// the ready event fires. See #6781
	readyWait: 1,

	// Hold (or release) the ready event
	holdReady: function( hold ) {
		if ( hold ) {
			jQuery.readyWait++;
		} else {
			jQuery.ready( true );
		}
	},

	// Handle when the DOM is ready
	ready: function( wait ) {
		// Either a released hold or an DOMready/load event and not yet ready
		if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {
			// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
			if ( !document.body ) {
				return setTimeout( jQuery.ready, 1 );
			}

			// Remember that the DOM is ready
			jQuery.isReady = true;

			// If a normal DOM Ready event fired, decrement, and wait if need be
			if ( wait !== true && --jQuery.readyWait > 0 ) {
				return;
			}

			// If there are functions bound, to execute
			readyList.fireWith( document, [ jQuery ] );

			// Trigger any bound ready events
			if ( jQuery.fn.trigger ) {
				jQuery( document ).trigger( "ready" ).off( "ready" );
			}
		}
	},

	bindReady: function() {
		if ( readyList ) {
			return;
		}

		readyList = jQuery.Callbacks( "once memory" );

		// Catch cases where $(document).ready() is called after the
		// browser event has already occurred.
		if ( document.readyState === "complete" ) {
			// Handle it asynchronously to allow scripts the opportunity to delay ready
			return setTimeout( jQuery.ready, 1 );
		}

		// Mozilla, Opera and webkit nightlies currently support this event
		if ( document.addEventListener ) {
			// Use the handy event callback
			document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );

			// A fallback to window.onload, that will always work
			window.addEventListener( "load", jQuery.ready, false );

		// If IE event model is used
		} else if ( document.attachEvent ) {
			// ensure firing before onload,
			// maybe late but safe also for iframes
			document.attachEvent( "onreadystatechange", DOMContentLoaded );

			// A fallback to window.onload, that will always work
			window.attachEvent( "onload", jQuery.ready );

			// If IE and not a frame
			// continually check to see if the document is ready
			var toplevel = false;

			try {
				toplevel = window.frameElement == null;
			} catch(e) {}

			if ( document.documentElement.doScroll && toplevel ) {
				doScrollCheck();
			}
		}
	},

	// See test/unit/core.js for details concerning isFunction.
	// Since version 1.3, DOM methods and functions like alert
	// aren't supported. They return false on IE (#2968).
	isFunction: function( obj ) {
		return jQuery.type(obj) === "function";
	},

	isArray: Array.isArray || function( obj ) {
		return jQuery.type(obj) === "array";
	},

	// A crude way of determining if an object is a window
	isWindow: function( obj ) {
		return obj && typeof obj === "object" && "setInterval" in obj;
	},

	isNumeric: function( obj ) {
		return !isNaN( parseFloat(obj) ) && isFinite( obj );
	},

	type: function( obj ) {
		return obj == null ?
			String( obj ) :
			class2type[ toString.call(obj) ] || "object";
	},

	isPlainObject: function( obj ) {
		// Must be an Object.
		// Because of IE, we also have to check the presence of the constructor property.
		// Make sure that DOM nodes and window objects don't pass through, as well
		if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
			return false;
		}

		try {
			// Not own constructor property must be Object
			if ( obj.constructor &&
				!hasOwn.call(obj, "constructor") &&
				!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
				return false;
			}
		} catch ( e ) {
			// IE8,9 Will throw exceptions on certain host objects #9897
			return false;
		}

		// Own properties are enumerated firstly, so to speed up,
		// if last one is own, then all properties are own.

		var key;
		for ( key in obj ) {}

		return key === undefined || hasOwn.call( obj, key );
	},

	isEmptyObject: function( obj ) {
		for ( var name in obj ) {
			return false;
		}
		return true;
	},

	error: function( msg ) {
		throw new Error( msg );
	},

	parseJSON: function( data ) {
		if ( typeof data !== "string" || !data ) {
			return null;
		}

		// Make sure leading/trailing whitespace is removed (IE can't handle it)
		data = jQuery.trim( data );

		// Attempt to parse using the native JSON parser first
		if ( window.JSON && window.JSON.parse ) {
			return window.JSON.parse( data );
		}

		// Make sure the incoming data is actual JSON
		// Logic borrowed from http://json.org/json2.js
		if ( rvalidchars.test( data.replace( rvalidescape, "@" )
			.replace( rvalidtokens, "]" )
			.replace( rvalidbraces, "")) ) {

			return ( new Function( "return " + data ) )();

		}
		jQuery.error( "Invalid JSON: " + data );
	},

	// Cross-browser xml parsing
	parseXML: function( data ) {
		var xml, tmp;
		try {
			if ( window.DOMParser ) { // Standard
				tmp = new DOMParser();
				xml = tmp.parseFromString( data , "text/xml" );
			} else { // IE
				xml = new ActiveXObject( "Microsoft.XMLDOM" );
				xml.async = "false";
				xml.loadXML( data );
			}
		} catch( e ) {
			xml = undefined;
		}
		if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
			jQuery.error( "Invalid XML: " + data );
		}
		return xml;
	},

	noop: function() {},

	// Evaluates a script in a global context
	// Workarounds based on findings by Jim Driscoll
	// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
	globalEval: function( data ) {
		if ( data && rnotwhite.test( data ) ) {
			// We use execScript on Internet Explorer
			// We use an anonymous function so that context is window
			// rather than jQuery in Firefox
			( window.execScript || function( data ) {
				window[ "eval" ].call( window, data );
			} )( data );
		}
	},

	// Convert dashed to camelCase; used by the css and data modules
	// Microsoft forgot to hump their vendor prefix (#9572)
	camelCase: function( string ) {
		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
	},

	nodeName: function( elem, name ) {
		return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
	},

	// args is for internal usage only
	each: function( object, callback, args ) {
		var name, i = 0,
			length = object.length,
			isObj = length === undefined || jQuery.isFunction( object );

		if ( args ) {
			if ( isObj ) {
				for ( name in object ) {
					if ( callback.apply( object[ name ], args ) === false ) {
						break;
					}
				}
			} else {
				for ( ; i < length; ) {
					if ( callback.apply( object[ i++ ], args ) === false ) {
						break;
					}
				}
			}

		// A special, fast, case for the most common use of each
		} else {
			if ( isObj ) {
				for ( name in object ) {
					if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
						break;
					}
				}
			} else {
				for ( ; i < length; ) {
					if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
						break;
					}
				}
			}
		}

		return object;
	},

	// Use native String.trim function wherever possible
	trim: trim ?
		function( text ) {
			return text == null ?
				"" :
				trim.call( text );
		} :

		// Otherwise use our own trimming functionality
		function( text ) {
			return text == null ?
				"" :
				text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
		},

	// results is for internal usage only
	makeArray: function( array, results ) {
		var ret = results || [];

		if ( array != null ) {
			// The window, strings (and functions) also have 'length'
			// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
			var type = jQuery.type( array );

			if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
				push.call( ret, array );
			} else {
				jQuery.merge( ret, array );
			}
		}

		return ret;
	},

	inArray: function( elem, array, i ) {
		var len;

		if ( array ) {
			if ( indexOf ) {
				return indexOf.call( array, elem, i );
			}

			len = array.length;
			i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;

			for ( ; i < len; i++ ) {
				// Skip accessing in sparse arrays
				if ( i in array && array[ i ] === elem ) {
					return i;
				}
			}
		}

		return -1;
	},

	merge: function( first, second ) {
		var i = first.length,
			j = 0;

		if ( typeof second.length === "number" ) {
			for ( var l = second.length; j < l; j++ ) {
				first[ i++ ] = second[ j ];
			}

		} else {
			while ( second[j] !== undefined ) {
				first[ i++ ] = second[ j++ ];
			}
		}

		first.length = i;

		return first;
	},

	grep: function( elems, callback, inv ) {
		var ret = [], retVal;
		inv = !!inv;

		// Go through the array, only saving the items
		// that pass the validator function
		for ( var i = 0, length = elems.length; i < length; i++ ) {
			retVal = !!callback( elems[ i ], i );
			if ( inv !== retVal ) {
				ret.push( elems[ i ] );
			}
		}

		return ret;
	},

	// arg is for internal usage only
	map: function( elems, callback, arg ) {
		var value, key, ret = [],
			i = 0,
			length = elems.length,
			// jquery objects are treated as arrays
			isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;

		// Go through the array, translating each of the items to their
		if ( isArray ) {
			for ( ; i < length; i++ ) {
				value = callback( elems[ i ], i, arg );

				if ( value != null ) {
					ret[ ret.length ] = value;
				}
			}

		// Go through every key on the object,
		} else {
			for ( key in elems ) {
				value = callback( elems[ key ], key, arg );

				if ( value != null ) {
					ret[ ret.length ] = value;
				}
			}
		}

		// Flatten any nested arrays
		return ret.concat.apply( [], ret );
	},

	// A global GUID counter for objects
	guid: 1,

	// Bind a function to a context, optionally partially applying any
	// arguments.
	proxy: function( fn, context ) {
		if ( typeof context === "string" ) {
			var tmp = fn[ context ];
			context = fn;
			fn = tmp;
		}

		// Quick check to determine if target is callable, in the spec
		// this throws a TypeError, but we will just return undefined.
		if ( !jQuery.isFunction( fn ) ) {
			return undefined;
		}

		// Simulated bind
		var args = slice.call( arguments, 2 ),
			proxy = function() {
				return fn.apply( context, args.concat( slice.call( arguments ) ) );
			};

		// Set the guid of unique handler to the same of original handler, so it can be removed
		proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;

		return proxy;
	},

	// Mutifunctional method to get and set values to a collection
	// The value/s can optionally be executed if it's a function
	access: function( elems, key, value, exec, fn, pass ) {
		var length = elems.length;

		// Setting many attributes
		if ( typeof key === "object" ) {
			for ( var k in key ) {
				jQuery.access( elems, k, key[k], exec, fn, value );
			}
			return elems;
		}

		// Setting one attribute
		if ( value !== undefined ) {
			// Optionally, function values get executed if exec is true
			exec = !pass && exec && jQuery.isFunction(value);

			for ( var i = 0; i < length; i++ ) {
				fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
			}

			return elems;
		}

		// Getting an attribute
		return length ? fn( elems[0], key ) : undefined;
	},

	now: function() {
		return ( new Date() ).getTime();
	},

	// Use of jQuery.browser is frowned upon.
	// More details: http://docs.jquery.com/Utilities/jQuery.browser
	uaMatch: function( ua ) {
		ua = ua.toLowerCase();

		var match = rwebkit.exec( ua ) ||
			ropera.exec( ua ) ||
			rmsie.exec( ua ) ||
			ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
			[];

		return { browser: match[1] || "", version: match[2] || "0" };
	},

	sub: function() {
		function jQuerySub( selector, context ) {
			return new jQuerySub.fn.init( selector, context );
		}
		jQuery.extend( true, jQuerySub, this );
		jQuerySub.superclass = this;
		jQuerySub.fn = jQuerySub.prototype = this();
		jQuerySub.fn.constructor = jQuerySub;
		jQuerySub.sub = this.sub;
		jQuerySub.fn.init = function init( selector, context ) {
			if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
				context = jQuerySub( context );
			}

			return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
		};
		jQuerySub.fn.init.prototype = jQuerySub.fn;
		var rootjQuerySub = jQuerySub(document);
		return jQuerySub;
	},

	browser: {}
});

// Populate the class2type map
jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
	class2type[ "[object " + name + "]" ] = name.toLowerCase();
});

browserMatch = jQuery.uaMatch( userAgent );
if ( browserMatch.browser ) {
	jQuery.browser[ browserMatch.browser ] = true;
	jQuery.browser.version = browserMatch.version;
}

// Deprecated, use jQuery.browser.webkit instead
if ( jQuery.browser.webkit ) {
	jQuery.browser.safari = true;
}

// IE doesn't match non-breaking spaces with \s
if ( rnotwhite.test( "\xA0" ) ) {
	trimLeft = /^[\s\xA0]+/;
	trimRight = /[\s\xA0]+$/;
}

// All jQuery objects should point back to these
rootjQuery = jQuery(document);

// Cleanup functions for the document ready method
if ( document.addEventListener ) {
	DOMContentLoaded = function() {
		document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
		jQuery.ready();
	};

} else if ( document.attachEvent ) {
	DOMContentLoaded = function() {
		// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
		if ( document.readyState === "complete" ) {
			document.detachEvent( "onreadystatechange", DOMContentLoaded );
			jQuery.ready();
		}
	};
}

// The DOM ready check for Internet Explorer
function doScrollCheck() {
	if ( jQuery.isReady ) {
		return;
	}

	try {
		// If IE is used, use the trick by Diego Perini
		// http://javascript.nwbox.com/IEContentLoaded/
		document.documentElement.doScroll("left");
	} catch(e) {
		setTimeout( doScrollCheck, 1 );
		return;
	}

	// and execute any waiting functions
	jQuery.ready();
}

return jQuery;

})();


// String to Object flags format cache
var flagsCache = {};

// Convert String-formatted flags into Object-formatted ones and store in cache
function createFlags( flags ) {
	var object = flagsCache[ flags ] = {},
		i, length;
	flags = flags.split( /\s+/ );
	for ( i = 0, length = flags.length; i < length; i++ ) {
		object[ flags[i] ] = true;
	}
	return object;
}

/*
 * Create a callback list using the following parameters:
 *
 *	flags:	an optional list of space-separated flags that will change how
 *			the callback list behaves
 *
 * By default a callback list will act like an event callback list and can be
 * "fired" multiple times.
 *
 * Possible flags:
 *
 *	once:			will ensure the callback list can only be fired once (like a Deferred)
 *
 *	memory:			will keep track of previous values and will call any callback added
 *					after the list has been fired right away with the latest "memorized"
 *					values (like a Deferred)
 *
 *	unique:			will ensure a callback can only be added once (no duplicate in the list)
 *
 *	stopOnFalse:	interrupt callings when a callback returns false
 *
 */
jQuery.Callbacks = function( flags ) {

	// Convert flags from String-formatted to Object-formatted
	// (we check in cache first)
	flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};

	var // Actual callback list
		list = [],
		// Stack of fire calls for repeatable lists
		stack = [],
		// Last fire value (for non-forgettable lists)
		memory,
		// Flag to know if list is currently firing
		firing,
		// First callback to fire (used internally by add and fireWith)
		firingStart,
		// End of the loop when firing
		firingLength,
		// Index of currently firing callback (modified by remove if needed)
		firingIndex,
		// Add one or several callbacks to the list
		add = function( args ) {
			var i,
				length,
				elem,
				type,
				actual;
			for ( i = 0, length = args.length; i < length; i++ ) {
				elem = args[ i ];
				type = jQuery.type( elem );
				if ( type === "array" ) {
					// Inspect recursively
					add( elem );
				} else if ( type === "function" ) {
					// Add if not in unique mode and callback is not in
					if ( !flags.unique || !self.has( elem ) ) {
						list.push( elem );
					}
				}
			}
		},
		// Fire callbacks
		fire = function( context, args ) {
			args = args || [];
			memory = !flags.memory || [ context, args ];
			firing = true;
			firingIndex = firingStart || 0;
			firingStart = 0;
			firingLength = list.length;
			for ( ; list && firingIndex < firingLength; firingIndex++ ) {
				if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {
					memory = true; // Mark as halted
					break;
				}
			}
			firing = false;
			if ( list ) {
				if ( !flags.once ) {
					if ( stack && stack.length ) {
						memory = stack.shift();
						self.fireWith( memory[ 0 ], memory[ 1 ] );
					}
				} else if ( memory === true ) {
					self.disable();
				} else {
					list = [];
				}
			}
		},
		// Actual Callbacks object
		self = {
			// Add a callback or a collection of callbacks to the list
			add: function() {
				if ( list ) {
					var length = list.length;
					add( arguments );
					// Do we need to add the callbacks to the
					// current firing batch?
					if ( firing ) {
						firingLength = list.length;
					// With memory, if we're not firing then
					// we should call right away, unless previous
					// firing was halted (stopOnFalse)
					} else if ( memory && memory !== true ) {
						firingStart = length;
						fire( memory[ 0 ], memory[ 1 ] );
					}
				}
				return this;
			},
			// Remove a callback from the list
			remove: function() {
				if ( list ) {
					var args = arguments,
						argIndex = 0,
						argLength = args.length;
					for ( ; argIndex < argLength ; argIndex++ ) {
						for ( var i = 0; i < list.length; i++ ) {
							if ( args[ argIndex ] === list[ i ] ) {
								// Handle firingIndex and firingLength
								if ( firing ) {
									if ( i <= firingLength ) {
										firingLength--;
										if ( i <= firingIndex ) {
											firingIndex--;
										}
									}
								}
								// Remove the element
								list.splice( i--, 1 );
								// If we have some unicity property then
								// we only need to do this once
								if ( flags.unique ) {
									break;
								}
							}
						}
					}
				}
				return this;
			},
			// Control if a given callback is in the list
			has: function( fn ) {
				if ( list ) {
					var i = 0,
						length = list.length;
					for ( ; i < length; i++ ) {
						if ( fn === list[ i ] ) {
							return true;
						}
					}
				}
				return false;
			},
			// Remove all callbacks from the list
			empty: function() {
				list = [];
				return this;
			},
			// Have the list do nothing anymore
			disable: function() {
				list = stack = memory = undefined;
				return this;
			},
			// Is it disabled?
			disabled: function() {
				return !list;
			},
			// Lock the list in its current state
			lock: function() {
				stack = undefined;
				if ( !memory || memory === true ) {
					self.disable();
				}
				return this;
			},
			// Is it locked?
			locked: function() {
				return !stack;
			},
			// Call all callbacks with the given context and arguments
			fireWith: function( context, args ) {
				if ( stack ) {
					if ( firing ) {
						if ( !flags.once ) {
							stack.push( [ context, args ] );
						}
					} else if ( !( flags.once && memory ) ) {
						fire( context, args );
					}
				}
				return this;
			},
			// Call all the callbacks with the given arguments
			fire: function() {
				self.fireWith( this, arguments );
				return this;
			},
			// To know if the callbacks have already been called at least once
			fired: function() {
				return !!memory;
			}
		};

	return self;
};




var // Static reference to slice
	sliceDeferred = [].slice;

jQuery.extend({

	Deferred: function( func ) {
		var doneList = jQuery.Callbacks( "once memory" ),
			failList = jQuery.Callbacks( "once memory" ),
			progressList = jQuery.Callbacks( "memory" ),
			state = "pending",
			lists = {
				resolve: doneList,
				reject: failList,
				notify: progressList
			},
			promise = {
				done: doneList.add,
				fail: failList.add,
				progress: progressList.add,

				state: function() {
					return state;
				},

				// Deprecated
				isResolved: doneList.fired,
				isRejected: failList.fired,

				then: function( doneCallbacks, failCallbacks, progressCallbacks ) {
					deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );
					return this;
				},
				always: function() {
					deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );
					return this;
				},
				pipe: function( fnDone, fnFail, fnProgress ) {
					return jQuery.Deferred(function( newDefer ) {
						jQuery.each( {
							done: [ fnDone, "resolve" ],
							fail: [ fnFail, "reject" ],
							progress: [ fnProgress, "notify" ]
						}, function( handler, data ) {
							var fn = data[ 0 ],
								action = data[ 1 ],
								returned;
							if ( jQuery.isFunction( fn ) ) {
								deferred[ handler ](function() {
									returned = fn.apply( this, arguments );
									if ( returned && jQuery.isFunction( returned.promise ) ) {
										returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );
									} else {
										newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
									}
								});
							} else {
								deferred[ handler ]( newDefer[ action ] );
							}
						});
					}).promise();
				},
				// Get a promise for this deferred
				// If obj is provided, the promise aspect is added to the object
				promise: function( obj ) {
					if ( obj == null ) {
						obj = promise;
					} else {
						for ( var key in promise ) {
							obj[ key ] = promise[ key ];
						}
					}
					return obj;
				}
			},
			deferred = promise.promise({}),
			key;

		for ( key in lists ) {
			deferred[ key ] = lists[ key ].fire;
			deferred[ key + "With" ] = lists[ key ].fireWith;
		}

		// Handle state
		deferred.done( function() {
			state = "resolved";
		}, failList.disable, progressList.lock ).fail( function() {
			state = "rejected";
		}, doneList.disable, progressList.lock );

		// Call given func if any
		if ( func ) {
			func.call( deferred, deferred );
		}

		// All done!
		return deferred;
	},

	// Deferred helper
	when: function( firstParam ) {
		var args = sliceDeferred.call( arguments, 0 ),
			i = 0,
			length = args.length,
			pValues = new Array( length ),
			count = length,
			pCount = length,
			deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?
				firstParam :
				jQuery.Deferred(),
			promise = deferred.promise();
		function resolveFunc( i ) {
			return function( value ) {
				args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
				if ( !( --count ) ) {
					deferred.resolveWith( deferred, args );
				}
			};
		}
		function progressFunc( i ) {
			return function( value ) {
				pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
				deferred.notifyWith( promise, pValues );
			};
		}
		if ( length > 1 ) {
			for ( ; i < length; i++ ) {
				if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {
					args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );
				} else {
					--count;
				}
			}
			if ( !count ) {
				deferred.resolveWith( deferred, args );
			}
		} else if ( deferred !== firstParam ) {
			deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
		}
		return promise;
	}
});




jQuery.support = (function() {

	var support,
		all,
		a,
		select,
		opt,
		input,
		marginDiv,
		fragment,
		tds,
		events,
		eventName,
		i,
		isSupported,
		div = document.createElement( "div" ),
		documentElement = document.documentElement;

	// Preliminary tests
	div.setAttribute("className", "t");
	div.innerHTML = "   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";

	all = div.getElementsByTagName( "*" );
	a = div.getElementsByTagName( "a" )[ 0 ];

	// Can't get basic test support
	if ( !all || !all.length || !a ) {
		return {};
	}

	// First batch of supports tests
	select = document.createElement( "select" );
	opt = select.appendChild( document.createElement("option") );
	input = div.getElementsByTagName( "input" )[ 0 ];

	support = {
		// IE strips leading whitespace when .innerHTML is used
		leadingWhitespace: ( div.firstChild.nodeType === 3 ),

		// Make sure that tbody elements aren't automatically inserted
		// IE will insert them into empty tables
		tbody: !div.getElementsByTagName("tbody").length,

		// Make sure that link elements get serialized correctly by innerHTML
		// This requires a wrapper element in IE
		htmlSerialize: !!div.getElementsByTagName("link").length,

		// Get the style information from getAttribute
		// (IE uses .cssText instead)
		style: /top/.test( a.getAttribute("style") ),

		// Make sure that URLs aren't manipulated
		// (IE normalizes it by default)
		hrefNormalized: ( a.getAttribute("href") === "/a" ),

		// Make sure that element opacity exists
		// (IE uses filter instead)
		// Use a regex to work around a WebKit issue. See #5145
		opacity: /^0.55/.test( a.style.opacity ),

		// Verify style float existence
		// (IE uses styleFloat instead of cssFloat)
		cssFloat: !!a.style.cssFloat,

		// Make sure that if no value is specified for a checkbox
		// that it defaults to "on".
		// (WebKit defaults to "" instead)
		checkOn: ( input.value === "on" ),

		// Make sure that a selected-by-default option has a working selected property.
		// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
		optSelected: opt.selected,

		// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
		getSetAttribute: div.className !== "t",

		// Tests for enctype support on a form(#6743)
		enctype: !!document.createElement("form").enctype,

		// Makes sure cloning an html5 element does not cause problems
		// Where outerHTML is undefined, this still works
		html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",

		// Will be defined later
		submitBubbles: true,
		changeBubbles: true,
		focusinBubbles: false,
		deleteExpando: true,
		noCloneEvent: true,
		inlineBlockNeedsLayout: false,
		shrinkWrapBlocks: false,
		reliableMarginRight: true
	};

	// Make sure checked status is properly cloned
	input.checked = true;
	support.noCloneChecked = input.cloneNode( true ).checked;

	// Make sure that the options inside disabled selects aren't marked as disabled
	// (WebKit marks them as disabled)
	select.disabled = true;
	support.optDisabled = !opt.disabled;

	// Test to see if it's possible to delete an expando from an element
	// Fails in Internet Explorer
	try {
		delete div.test;
	} catch( e ) {
		support.deleteExpando = false;
	}

	if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
		div.attachEvent( "onclick", function() {
			// Cloning a node shouldn't copy over any
			// bound event handlers (IE does this)
			support.noCloneEvent = false;
		});
		div.cloneNode( true ).fireEvent( "onclick" );
	}

	// Check if a radio maintains its value
	// after being appended to the DOM
	input = document.createElement("input");
	input.value = "t";
	input.setAttribute("type", "radio");
	support.radioValue = input.value === "t";

	input.setAttribute("checked", "checked");
	div.appendChild( input );
	fragment = document.createDocumentFragment();
	fragment.appendChild( div.lastChild );

	// WebKit doesn't clone checked state correctly in fragments
	support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;

	// Check if a disconnected checkbox will retain its checked
	// value of true after appended to the DOM (IE6/7)
	support.appendChecked = input.checked;

	fragment.removeChild( input );
	fragment.appendChild( div );

	div.innerHTML = "";

	// Check if div with explicit width and no margin-right incorrectly
	// gets computed margin-right based on width of container. For more
	// info see bug #3333
	// Fails in WebKit before Feb 2011 nightlies
	// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
	if ( window.getComputedStyle ) {
		marginDiv = document.createElement( "div" );
		marginDiv.style.width = "0";
		marginDiv.style.marginRight = "0";
		div.style.width = "2px";
		div.appendChild( marginDiv );
		support.reliableMarginRight =
			( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;
	}

	// Technique from Juriy Zaytsev
	// http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
	// We only care about the case where non-standard event systems
	// are used, namely in IE. Short-circuiting here helps us to
	// avoid an eval call (in setAttribute) which can cause CSP
	// to go haywire. See: https://developer.mozilla.org/en/Security/CSP
	if ( div.attachEvent ) {
		for( i in {
			submit: 1,
			change: 1,
			focusin: 1
		}) {
			eventName = "on" + i;
			isSupported = ( eventName in div );
			if ( !isSupported ) {
				div.setAttribute( eventName, "return;" );
				isSupported = ( typeof div[ eventName ] === "function" );
			}
			support[ i + "Bubbles" ] = isSupported;
		}
	}

	fragment.removeChild( div );

	// Null elements to avoid leaks in IE
	fragment = select = opt = marginDiv = div = input = null;

	// Run tests that need a body at doc ready
	jQuery(function() {
		var container, outer, inner, table, td, offsetSupport,
			conMarginTop, ptlm, vb, style, html,
			body = document.getElementsByTagName("body")[0];

		if ( !body ) {
			// Return for frameset docs that don't have a body
			return;
		}

		conMarginTop = 1;
		ptlm = "position:absolute;top:0;left:0;width:1px;height:1px;margin:0;";
		vb = "visibility:hidden;border:0;";
		style = "style='" + ptlm + "border:5px solid #000;padding:0;'";
		html = "<div " + style + "><div></div></div>" +
			"<table " + style + " cellpadding='0' cellspacing='0'>" +
			"<tr><td></td></tr></table>";

		container = document.createElement("div");
		container.style.cssText = vb + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px";
		body.insertBefore( container, body.firstChild );

		// Construct the test element
		div = document.createElement("div");
		container.appendChild( div );

		// Check if table cells still have offsetWidth/Height when they are set
		// to display:none and there are still other visible table cells in a
		// table row; if so, offsetWidth/Height are not reliable for use when
		// determining if an element has been hidden directly using
		// display:none (it is still safe to use offsets if a parent element is
		// hidden; don safety goggles and see bug #4512 for more information).
		// (only IE 8 fails this test)
		div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
		tds = div.getElementsByTagName( "td" );
		isSupported = ( tds[ 0 ].offsetHeight === 0 );

		tds[ 0 ].style.display = "";
		tds[ 1 ].style.display = "none";

		// Check if empty table cells still have offsetWidth/Height
		// (IE <= 8 fail this test)
		support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );

		// Figure out if the W3C box model works as expected
		div.innerHTML = "";
		div.style.width = div.style.paddingLeft = "1px";
		jQuery.boxModel = support.boxModel = div.offsetWidth === 2;

		if ( typeof div.style.zoom !== "undefined" ) {
			// Check if natively block-level elements act like inline-block
			// elements when setting their display to 'inline' and giving
			// them layout
			// (IE < 8 does this)
			div.style.display = "inline";
			div.style.zoom = 1;
			support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );

			// Check if elements with layout shrink-wrap their children
			// (IE 6 does this)
			div.style.display = "";
			div.innerHTML = "<div style='width:4px;'></div>";
			support.shrinkWrapBlocks = ( div.offsetWidth !== 2 );
		}

		div.style.cssText = ptlm + vb;
		div.innerHTML = html;

		outer = div.firstChild;
		inner = outer.firstChild;
		td = outer.nextSibling.firstChild.firstChild;

		offsetSupport = {
			doesNotAddBorder: ( inner.offsetTop !== 5 ),
			doesAddBorderForTableAndCells: ( td.offsetTop === 5 )
		};

		inner.style.position = "fixed";
		inner.style.top = "20px";

		// safari subtracts parent border width here which is 5px
		offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );
		inner.style.position = inner.style.top = "";

		outer.style.overflow = "hidden";
		outer.style.position = "relative";

		offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );
		offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );

		body.removeChild( container );
		div  = container = null;

		jQuery.extend( support, offsetSupport );
	});

	return support;
})();




var rbrace = /^(?:\{.*\}|\[.*\])$/,
	rmultiDash = /([A-Z])/g;

jQuery.extend({
	cache: {},

	// Please use with caution
	uuid: 0,

	// Unique for each copy of jQuery on the page
	// Non-digits removed to match rinlinejQuery
	expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),

	// The following elements throw uncatchable exceptions if you
	// attempt to add expando properties to them.
	noData: {
		"embed": true,
		// Ban all objects except for Flash (which handle expandos)
		"object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
		"applet": true
	},

	hasData: function( elem ) {
		elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
		return !!elem && !isEmptyDataObject( elem );
	},

	data: function( elem, name, data, pvt /* Internal Use Only */ ) {
		if ( !jQuery.acceptData( elem ) ) {
			return;
		}

		var privateCache, thisCache, ret,
			internalKey = jQuery.expando,
			getByName = typeof name === "string",

			// We have to handle DOM nodes and JS objects differently because IE6-7
			// can't GC object references properly across the DOM-JS boundary
			isNode = elem.nodeType,

			// Only DOM nodes need the global jQuery cache; JS object data is
			// attached directly to the object so GC can occur automatically
			cache = isNode ? jQuery.cache : elem,

			// Only defining an ID for JS objects if its cache already exists allows
			// the code to shortcut on the same path as a DOM node with no cache
			id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,
			isEvents = name === "events";

		// Avoid doing any more work than we need to when trying to get data on an
		// object that has no data at all
		if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {
			return;
		}

		if ( !id ) {
			// Only DOM nodes need a new unique ID for each element since their data
			// ends up in the global cache
			if ( isNode ) {
				elem[ internalKey ] = id = ++jQuery.uuid;
			} else {
				id = internalKey;
			}
		}

		if ( !cache[ id ] ) {
			cache[ id ] = {};

			// Avoids exposing jQuery metadata on plain JS objects when the object
			// is serialized using JSON.stringify
			if ( !isNode ) {
				cache[ id ].toJSON = jQuery.noop;
			}
		}

		// An object can be passed to jQuery.data instead of a key/value pair; this gets
		// shallow copied over onto the existing cache
		if ( typeof name === "object" || typeof name === "function" ) {
			if ( pvt ) {
				cache[ id ] = jQuery.extend( cache[ id ], name );
			} else {
				cache[ id ].data = jQuery.extend( cache[ id ].data, name );
			}
		}

		privateCache = thisCache = cache[ id ];

		// jQuery data() is stored in a separate object inside the object's internal data
		// cache in order to avoid key collisions between internal data and user-defined
		// data.
		if ( !pvt ) {
			if ( !thisCache.data ) {
				thisCache.data = {};
			}

			thisCache = thisCache.data;
		}

		if ( data !== undefined ) {
			thisCache[ jQuery.camelCase( name ) ] = data;
		}

		// Users should not attempt to inspect the internal events object using jQuery.data,
		// it is undocumented and subject to change. But does anyone listen? No.
		if ( isEvents && !thisCache[ name ] ) {
			return privateCache.events;
		}

		// Check for both converted-to-camel and non-converted data property names
		// If a data property was specified
		if ( getByName ) {

			// First Try to find as-is property data
			ret = thisCache[ name ];

			// Test for null|undefined property data
			if ( ret == null ) {

				// Try to find the camelCased property
				ret = thisCache[ jQuery.camelCase( name ) ];
			}
		} else {
			ret = thisCache;
		}

		return ret;
	},

	removeData: function( elem, name, pvt /* Internal Use Only */ ) {
		if ( !jQuery.acceptData( elem ) ) {
			return;
		}

		var thisCache, i, l,

			// Reference to internal data cache key
			internalKey = jQuery.expando,

			isNode = elem.nodeType,

			// See jQuery.data for more information
			cache = isNode ? jQuery.cache : elem,

			// See jQuery.data for more information
			id = isNode ? elem[ internalKey ] : internalKey;

		// If there is already no cache entry for this object, there is no
		// purpose in continuing
		if ( !cache[ id ] ) {
			return;
		}

		if ( name ) {

			thisCache = pvt ? cache[ id ] : cache[ id ].data;

			if ( thisCache ) {

				// Support array or space separated string names for data keys
				if ( !jQuery.isArray( name ) ) {

					// try the string as a key before any manipulation
					if ( name in thisCache ) {
						name = [ name ];
					} else {

						// split the camel cased version by spaces unless a key with the spaces exists
						name = jQuery.camelCase( name );
						if ( name in thisCache ) {
							name = [ name ];
						} else {
							name = name.split( " " );
						}
					}
				}

				for ( i = 0, l = name.length; i < l; i++ ) {
					delete thisCache[ name[i] ];
				}

				// If there is no data left in the cache, we want to continue
				// and let the cache object itself get destroyed
				if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
					return;
				}
			}
		}

		// See jQuery.data for more information
		if ( !pvt ) {
			delete cache[ id ].data;

			// Don't destroy the parent cache unless the internal data object
			// had been the only thing left in it
			if ( !isEmptyDataObject(cache[ id ]) ) {
				return;
			}
		}

		// Browsers that fail expando deletion also refuse to delete expandos on
		// the window, but it will allow it on all other JS objects; other browsers
		// don't care
		// Ensure that `cache` is not a window object #10080
		if ( jQuery.support.deleteExpando || !cache.setInterval ) {
			delete cache[ id ];
		} else {
			cache[ id ] = null;
		}

		// We destroyed the cache and need to eliminate the expando on the node to avoid
		// false lookups in the cache for entries that no longer exist
		if ( isNode ) {
			// IE does not allow us to delete expando properties from nodes,
			// nor does it have a removeAttribute function on Document nodes;
			// we must handle all of these cases
			if ( jQuery.support.deleteExpando ) {
				delete elem[ internalKey ];
			} else if ( elem.removeAttribute ) {
				elem.removeAttribute( internalKey );
			} else {
				elem[ internalKey ] = null;
			}
		}
	},

	// For internal use only.
	_data: function( elem, name, data ) {
		return jQuery.data( elem, name, data, true );
	},

	// A method for determining if a DOM node can handle the data expando
	acceptData: function( elem ) {
		if ( elem.nodeName ) {
			var match = jQuery.noData[ elem.nodeName.toLowerCase() ];

			if ( match ) {
				return !(match === true || elem.getAttribute("classid") !== match);
			}
		}

		return true;
	}
});

jQuery.fn.extend({
	data: function( key, value ) {
		var parts, attr, name,
			data = null;

		if ( typeof key === "undefined" ) {
			if ( this.length ) {
				data = jQuery.data( this[0] );

				if ( this[0].nodeType === 1 && !jQuery._data( this[0], "parsedAttrs" ) ) {
					attr = this[0].attributes;
					for ( var i = 0, l = attr.length; i < l; i++ ) {
						name = attr[i].name;

						if ( name.indexOf( "data-" ) === 0 ) {
							name = jQuery.camelCase( name.substring(5) );

							dataAttr( this[0], name, data[ name ] );
						}
					}
					jQuery._data( this[0], "parsedAttrs", true );
				}
			}

			return data;

		} else if ( typeof key === "object" ) {
			return this.each(function() {
				jQuery.data( this, key );
			});
		}

		parts = key.split(".");
		parts[1] = parts[1] ? "." + parts[1] : "";

		if ( value === undefined ) {
			data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);

			// Try to fetch any internally stored data first
			if ( data === undefined && this.length ) {
				data = jQuery.data( this[0], key );
				data = dataAttr( this[0], key, data );
			}

			return data === undefined && parts[1] ?
				this.data( parts[0] ) :
				data;

		} else {
			return this.each(function() {
				var self = jQuery( this ),
					args = [ parts[0], value ];

				self.triggerHandler( "setData" + parts[1] + "!", args );
				jQuery.data( this, key, value );
				self.triggerHandler( "changeData" + parts[1] + "!", args );
			});
		}
	},

	removeData: function( key ) {
		return this.each(function() {
			jQuery.removeData( this, key );
		});
	}
});

function dataAttr( elem, key, data ) {
	// If nothing was found internally, try to fetch any
	// data from the HTML5 data-* attribute
	if ( data === undefined && elem.nodeType === 1 ) {

		var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();

		data = elem.getAttribute( name );

		if ( typeof data === "string" ) {
			try {
				data = data === "true" ? true :
				data === "false" ? false :
				data === "null" ? null :
				jQuery.isNumeric( data ) ? parseFloat( data ) :
					rbrace.test( data ) ? jQuery.parseJSON( data ) :
					data;
			} catch( e ) {}

			// Make sure we set the data so it isn't changed later
			jQuery.data( elem, key, data );

		} else {
			data = undefined;
		}
	}

	return data;
}

// checks a cache object for emptiness
function isEmptyDataObject( obj ) {
	for ( var name in obj ) {

		// if the public data object is empty, the private is still empty
		if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
			continue;
		}
		if ( name !== "toJSON" ) {
			return false;
		}
	}

	return true;
}




function handleQueueMarkDefer( elem, type, src ) {
	var deferDataKey = type + "defer",
		queueDataKey = type + "queue",
		markDataKey = type + "mark",
		defer = jQuery._data( elem, deferDataKey );
	if ( defer &&
		( src === "queue" || !jQuery._data(elem, queueDataKey) ) &&
		( src === "mark" || !jQuery._data(elem, markDataKey) ) ) {
		// Give room for hard-coded callbacks to fire first
		// and eventually mark/queue something else on the element
		setTimeout( function() {
			if ( !jQuery._data( elem, queueDataKey ) &&
				!jQuery._data( elem, markDataKey ) ) {
				jQuery.removeData( elem, deferDataKey, true );
				defer.fire();
			}
		}, 0 );
	}
}

jQuery.extend({

	_mark: function( elem, type ) {
		if ( elem ) {
			type = ( type || "fx" ) + "mark";
			jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );
		}
	},

	_unmark: function( force, elem, type ) {
		if ( force !== true ) {
			type = elem;
			elem = force;
			force = false;
		}
		if ( elem ) {
			type = type || "fx";
			var key = type + "mark",
				count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );
			if ( count ) {
				jQuery._data( elem, key, count );
			} else {
				jQuery.removeData( elem, key, true );
				handleQueueMarkDefer( elem, type, "mark" );
			}
		}
	},

	queue: function( elem, type, data ) {
		var q;
		if ( elem ) {
			type = ( type || "fx" ) + "queue";
			q = jQuery._data( elem, type );

			// Speed up dequeue by getting out quickly if this is just a lookup
			if ( data ) {
				if ( !q || jQuery.isArray(data) ) {
					q = jQuery._data( elem, type, jQuery.makeArray(data) );
				} else {
					q.push( data );
				}
			}
			return q || [];
		}
	},

	dequeue: function( elem, type ) {
		type = type || "fx";

		var queue = jQuery.queue( elem, type ),
			fn = queue.shift(),
			hooks = {};

		// If the fx queue is dequeued, always remove the progress sentinel
		if ( fn === "inprogress" ) {
			fn = queue.shift();
		}

		if ( fn ) {
			// Add a progress sentinel to prevent the fx queue from being
			// automatically dequeued
			if ( type === "fx" ) {
				queue.unshift( "inprogress" );
			}

			jQuery._data( elem, type + ".run", hooks );
			fn.call( elem, function() {
				jQuery.dequeue( elem, type );
			}, hooks );
		}

		if ( !queue.length ) {
			jQuery.removeData( elem, type + "queue " + type + ".run", true );
			handleQueueMarkDefer( elem, type, "queue" );
		}
	}
});

jQuery.fn.extend({
	queue: function( type, data ) {
		if ( typeof type !== "string" ) {
			data = type;
			type = "fx";
		}

		if ( data === undefined ) {
			return jQuery.queue( this[0], type );
		}
		return this.each(function() {
			var queue = jQuery.queue( this, type, data );

			if ( type === "fx" && queue[0] !== "inprogress" ) {
				jQuery.dequeue( this, type );
			}
		});
	},
	dequeue: function( type ) {
		return this.each(function() {
			jQuery.dequeue( this, type );
		});
	},
	// Based off of the plugin by Clint Helfers, with permission.
	// http://blindsignals.com/index.php/2009/07/jquery-delay/
	delay: function( time, type ) {
		time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
		type = type || "fx";

		return this.queue( type, function( next, hooks ) {
			var timeout = setTimeout( next, time );
			hooks.stop = function() {
				clearTimeout( timeout );
			};
		});
	},
	clearQueue: function( type ) {
		return this.queue( type || "fx", [] );
	},
	// Get a promise resolved when queues of a certain type
	// are emptied (fx is the type by default)
	promise: function( type, object ) {
		if ( typeof type !== "string" ) {
			object = type;
			type = undefined;
		}
		type = type || "fx";
		var defer = jQuery.Deferred(),
			elements = this,
			i = elements.length,
			count = 1,
			deferDataKey = type + "defer",
			queueDataKey = type + "queue",
			markDataKey = type + "mark",
			tmp;
		function resolve() {
			if ( !( --count ) ) {
				defer.resolveWith( elements, [ elements ] );
			}
		}
		while( i-- ) {
			if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
					( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||
						jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
					jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) {
				count++;
				tmp.add( resolve );
			}
		}
		resolve();
		return defer.promise();
	}
});




var rclass = /[\n\t\r]/g,
	rspace = /\s+/,
	rreturn = /\r/g,
	rtype = /^(?:button|input)$/i,
	rfocusable = /^(?:button|input|object|select|textarea)$/i,
	rclickable = /^a(?:rea)?$/i,
	rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
	getSetAttribute = jQuery.support.getSetAttribute,
	nodeHook, boolHook, fixSpecified;

jQuery.fn.extend({
	attr: function( name, value ) {
		return jQuery.access( this, name, value, true, jQuery.attr );
	},

	removeAttr: function( name ) {
		return this.each(function() {
			jQuery.removeAttr( this, name );
		});
	},

	prop: function( name, value ) {
		return jQuery.access( this, name, value, true, jQuery.prop );
	},

	removeProp: function( name ) {
		name = jQuery.propFix[ name ] || name;
		return this.each(function() {
			// try/catch handles cases where IE balks (such as removing a property on window)
			try {
				this[ name ] = undefined;
				delete this[ name ];
			} catch( e ) {}
		});
	},

	addClass: function( value ) {
		var classNames, i, l, elem,
			setClass, c, cl;

		if ( jQuery.isFunction( value ) ) {
			return this.each(function( j ) {
				jQuery( this ).addClass( value.call(this, j, this.className) );
			});
		}

		if ( value && typeof value === "string" ) {
			classNames = value.split( rspace );

			for ( i = 0, l = this.length; i < l; i++ ) {
				elem = this[ i ];

				if ( elem.nodeType === 1 ) {
					if ( !elem.className && classNames.length === 1 ) {
						elem.className = value;

					} else {
						setClass = " " + elem.className + " ";

						for ( c = 0, cl = classNames.length; c < cl; c++ ) {
							if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
								setClass += classNames[ c ] + " ";
							}
						}
						elem.className = jQuery.trim( setClass );
					}
				}
			}
		}

		return this;
	},

	removeClass: function( value ) {
		var classNames, i, l, elem, className, c, cl;

		if ( jQuery.isFunction( value ) ) {
			return this.each(function( j ) {
				jQuery( this ).removeClass( value.call(this, j, this.className) );
			});
		}

		if ( (value && typeof value === "string") || value === undefined ) {
			classNames = ( value || "" ).split( rspace );

			for ( i = 0, l = this.length; i < l; i++ ) {
				elem = this[ i ];

				if ( elem.nodeType === 1 && elem.className ) {
					if ( value ) {
						className = (" " + elem.className + " ").replace( rclass, " " );
						for ( c = 0, cl = classNames.length; c < cl; c++ ) {
							className = className.replace(" " + classNames[ c ] + " ", " ");
						}
						elem.className = jQuery.trim( className );

					} else {
						elem.className = "";
					}
				}
			}
		}

		return this;
	},

	toggleClass: function( value, stateVal ) {
		var type = typeof value,
			isBool = typeof stateVal === "boolean";

		if ( jQuery.isFunction( value ) ) {
			return this.each(function( i ) {
				jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
			});
		}

		return this.each(function() {
			if ( type === "string" ) {
				// toggle individual class names
				var className,
					i = 0,
					self = jQuery( this ),
					state = stateVal,
					classNames = value.split( rspace );

				while ( (className = classNames[ i++ ]) ) {
					// check each className given, space seperated list
					state = isBool ? state : !self.hasClass( className );
					self[ state ? "addClass" : "removeClass" ]( className );
				}

			} else if ( type === "undefined" || type === "boolean" ) {
				if ( this.className ) {
					// store className if set
					jQuery._data( this, "__className__", this.className );
				}

				// toggle whole className
				this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
			}
		});
	},

	hasClass: function( selector ) {
		var className = " " + selector + " ",
			i = 0,
			l = this.length;
		for ( ; i < l; i++ ) {
			if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
				return true;
			}
		}

		return false;
	},

	val: function( value ) {
		var hooks, ret, isFunction,
			elem = this[0];

		if ( !arguments.length ) {
			if ( elem ) {
				hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];

				if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
					return ret;
				}

				ret = elem.value;

				return typeof ret === "string" ?
					// handle most common string cases
					ret.replace(rreturn, "") :
					// handle cases where value is null/undef or number
					ret == null ? "" : ret;
			}

			return;
		}

		isFunction = jQuery.isFunction( value );

		return this.each(function( i ) {
			var self = jQuery(this), val;

			if ( this.nodeType !== 1 ) {
				return;
			}

			if ( isFunction ) {
				val = value.call( this, i, self.val() );
			} else {
				val = value;
			}

			// Treat null/undefined as ""; convert numbers to string
			if ( val == null ) {
				val = "";
			} else if ( typeof val === "number" ) {
				val += "";
			} else if ( jQuery.isArray( val ) ) {
				val = jQuery.map(val, function ( value ) {
					return value == null ? "" : value + "";
				});
			}

			hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];

			// If set returns undefined, fall back to normal setting
			if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
				this.value = val;
			}
		});
	}
});

jQuery.extend({
	valHooks: {
		option: {
			get: function( elem ) {
				// attributes.value is undefined in Blackberry 4.7 but
				// uses .value. See #6932
				var val = elem.attributes.value;
				return !val || val.specified ? elem.value : elem.text;
			}
		},
		select: {
			get: function( elem ) {
				var value, i, max, option,
					index = elem.selectedIndex,
					values = [],
					options = elem.options,
					one = elem.type === "select-one";

				// Nothing was selected
				if ( index < 0 ) {
					return null;
				}

				// Loop through all the selected options
				i = one ? index : 0;
				max = one ? index + 1 : options.length;
				for ( ; i < max; i++ ) {
					option = options[ i ];

					// Don't return options that are disabled or in a disabled optgroup
					if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
							(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {

						// Get the specific value for the option
						value = jQuery( option ).val();

						// We don't need an array for one selects
						if ( one ) {
							return value;
						}

						// Multi-Selects return an array
						values.push( value );
					}
				}

				// Fixes Bug #2551 -- select.val() broken in IE after form.reset()
				if ( one && !values.length && options.length ) {
					return jQuery( options[ index ] ).val();
				}

				return values;
			},

			set: function( elem, value ) {
				var values = jQuery.makeArray( value );

				jQuery(elem).find("option").each(function() {
					this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
				});

				if ( !values.length ) {
					elem.selectedIndex = -1;
				}
				return values;
			}
		}
	},

	attrFn: {
		val: true,
		css: true,
		html: true,
		text: true,
		data: true,
		width: true,
		height: true,
		offset: true
	},

	attr: function( elem, name, value, pass ) {
		var ret, hooks, notxml,
			nType = elem.nodeType;

		// don't get/set attributes on text, comment and attribute nodes
		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
			return;
		}

		if ( pass && name in jQuery.attrFn ) {
			return jQuery( elem )[ name ]( value );
		}

		// Fallback to prop when attributes are not supported
		if ( typeof elem.getAttribute === "undefined" ) {
			return jQuery.prop( elem, name, value );
		}

		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );

		// All attributes are lowercase
		// Grab necessary hook if one is defined
		if ( notxml ) {
			name = name.toLowerCase();
			hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
		}

		if ( value !== undefined ) {

			if ( value === null ) {
				jQuery.removeAttr( elem, name );
				return;

			} else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
				return ret;

			} else {
				elem.setAttribute( name, "" + value );
				return value;
			}

		} else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
			return ret;

		} else {

			ret = elem.getAttribute( name );

			// Non-existent attributes return null, we normalize to undefined
			return ret === null ?
				undefined :
				ret;
		}
	},

	removeAttr: function( elem, value ) {
		var propName, attrNames, name, l,
			i = 0;

		if ( value && elem.nodeType === 1 ) {
			attrNames = value.toLowerCase().split( rspace );
			l = attrNames.length;

			for ( ; i < l; i++ ) {
				name = attrNames[ i ];

				if ( name ) {
					propName = jQuery.propFix[ name ] || name;

					// See #9699 for explanation of this approach (setting first, then removal)
					jQuery.attr( elem, name, "" );
					elem.removeAttribute( getSetAttribute ? name : propName );

					// Set corresponding property to false for boolean attributes
					if ( rboolean.test( name ) && propName in elem ) {
						elem[ propName ] = false;
					}
				}
			}
		}
	},

	attrHooks: {
		type: {
			set: function( elem, value ) {
				// We can't allow the type property to be changed (since it causes problems in IE)
				if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
					jQuery.error( "type property can't be changed" );
				} else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
					// Setting the type on a radio button after the value resets the value in IE6-9
					// Reset value to it's default in case type is set after value
					// This is for element creation
					var val = elem.value;
					elem.setAttribute( "type", value );
					if ( val ) {
						elem.value = val;
					}
					return value;
				}
			}
		},
		// Use the value property for back compat
		// Use the nodeHook for button elements in IE6/7 (#1954)
		value: {
			get: function( elem, name ) {
				if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
					return nodeHook.get( elem, name );
				}
				return name in elem ?
					elem.value :
					null;
			},
			set: function( elem, value, name ) {
				if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
					return nodeHook.set( elem, value, name );
				}
				// Does not return so that setAttribute is also used
				elem.value = value;
			}
		}
	},

	propFix: {
		tabindex: "tabIndex",
		readonly: "readOnly",
		"for": "htmlFor",
		"class": "className",
		maxlength: "maxLength",
		cellspacing: "cellSpacing",
		cellpadding: "cellPadding",
		rowspan: "rowSpan",
		colspan: "colSpan",
		usemap: "useMap",
		frameborder: "frameBorder",
		contenteditable: "contentEditable"
	},

	prop: function( elem, name, value ) {
		var ret, hooks, notxml,
			nType = elem.nodeType;

		// don't get/set properties on text, comment and attribute nodes
		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
			return;
		}

		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );

		if ( notxml ) {
			// Fix name and attach hooks
			name = jQuery.propFix[ name ] || name;
			hooks = jQuery.propHooks[ name ];
		}

		if ( value !== undefined ) {
			if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
				return ret;

			} else {
				return ( elem[ name ] = value );
			}

		} else {
			if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
				return ret;

			} else {
				return elem[ name ];
			}
		}
	},

	propHooks: {
		tabIndex: {
			get: function( elem ) {
				// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
				var attributeNode = elem.getAttributeNode("tabindex");

				return attributeNode && attributeNode.specified ?
					parseInt( attributeNode.value, 10 ) :
					rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
						0 :
						undefined;
			}
		}
	}
});

// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)
jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;

// Hook for boolean attributes
boolHook = {
	get: function( elem, name ) {
		// Align boolean attributes with corresponding properties
		// Fall back to attribute presence where some booleans are not supported
		var attrNode,
			property = jQuery.prop( elem, name );
		return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
			name.toLowerCase() :
			undefined;
	},
	set: function( elem, value, name ) {
		var propName;
		if ( value === false ) {
			// Remove boolean attributes when set to false
			jQuery.removeAttr( elem, name );
		} else {
			// value is true since we know at this point it's type boolean and not false
			// Set boolean attributes to the same name and set the DOM property
			propName = jQuery.propFix[ name ] || name;
			if ( propName in elem ) {
				// Only set the IDL specifically if it already exists on the element
				elem[ propName ] = true;
			}

			elem.setAttribute( name, name.toLowerCase() );
		}
		return name;
	}
};

// IE6/7 do not support getting/setting some attributes with get/setAttribute
if ( !getSetAttribute ) {

	fixSpecified = {
		name: true,
		id: true
	};

	// Use this for any attribute in IE6/7
	// This fixes almost every IE6/7 issue
	nodeHook = jQuery.valHooks.button = {
		get: function( elem, name ) {
			var ret;
			ret = elem.getAttributeNode( name );
			return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ?
				ret.nodeValue :
				undefined;
		},
		set: function( elem, value, name ) {
			// Set the existing or create a new attribute node
			var ret = elem.getAttributeNode( name );
			if ( !ret ) {
				ret = document.createAttribute( name );
				elem.setAttributeNode( ret );
			}
			return ( ret.nodeValue = value + "" );
		}
	};

	// Apply the nodeHook to tabindex
	jQuery.attrHooks.tabindex.set = nodeHook.set;

	// Set width and height to auto instead of 0 on empty string( Bug #8150 )
	// This is for removals
	jQuery.each([ "width", "height" ], function( i, name ) {
		jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
			set: function( elem, value ) {
				if ( value === "" ) {
					elem.setAttribute( name, "auto" );
					return value;
				}
			}
		});
	});

	// Set contenteditable to false on removals(#10429)
	// Setting to empty string throws an error as an invalid value
	jQuery.attrHooks.contenteditable = {
		get: nodeHook.get,
		set: function( elem, value, name ) {
			if ( value === "" ) {
				value = "false";
			}
			nodeHook.set( elem, value, name );
		}
	};
}


// Some attributes require a special call on IE
if ( !jQuery.support.hrefNormalized ) {
	jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
		jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
			get: function( elem ) {
				var ret = elem.getAttribute( name, 2 );
				return ret === null ? undefined : ret;
			}
		});
	});
}

if ( !jQuery.support.style ) {
	jQuery.attrHooks.style = {
		get: function( elem ) {
			// Return undefined in the case of empty string
			// Normalize to lowercase since IE uppercases css property names
			return elem.style.cssText.toLowerCase() || undefined;
		},
		set: function( elem, value ) {
			return ( elem.style.cssText = "" + value );
		}
	};
}

// Safari mis-reports the default selected property of an option
// Accessing the parent's selectedIndex property fixes it
if ( !jQuery.support.optSelected ) {
	jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
		get: function( elem ) {
			var parent = elem.parentNode;

			if ( parent ) {
				parent.selectedIndex;

				// Make sure that it also works with optgroups, see #5701
				if ( parent.parentNode ) {
					parent.parentNode.selectedIndex;
				}
			}
			return null;
		}
	});
}

// IE6/7 call enctype encoding
if ( !jQuery.support.enctype ) {
	jQuery.propFix.enctype = "encoding";
}

// Radios and checkboxes getter/setter
if ( !jQuery.support.checkOn ) {
	jQuery.each([ "radio", "checkbox" ], function() {
		jQuery.valHooks[ this ] = {
			get: function( elem ) {
				// Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
				return elem.getAttribute("value") === null ? "on" : elem.value;
			}
		};
	});
}
jQuery.each([ "radio", "checkbox" ], function() {
	jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
		set: function( elem, value ) {
			if ( jQuery.isArray( value ) ) {
				return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
			}
		}
	});
});




var rformElems = /^(?:textarea|input|select)$/i,
	rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/,
	rhoverHack = /\bhover(\.\S+)?\b/,
	rkeyEvent = /^key/,
	rmouseEvent = /^(?:mouse|contextmenu)|click/,
	rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
	rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,
	quickParse = function( selector ) {
		var quick = rquickIs.exec( selector );
		if ( quick ) {
			//   0  1    2   3
			// [ _, tag, id, class ]
			quick[1] = ( quick[1] || "" ).toLowerCase();
			quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" );
		}
		return quick;
	},
	quickIs = function( elem, m ) {
		var attrs = elem.attributes || {};
		return (
			(!m[1] || elem.nodeName.toLowerCase() === m[1]) &&
			(!m[2] || (attrs.id || {}).value === m[2]) &&
			(!m[3] || m[3].test( (attrs[ "class" ] || {}).value ))
		);
	},
	hoverHack = function( events ) {
		return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
	};

/*
 * Helper functions for managing events -- not part of the public interface.
 * Props to Dean Edwards' addEvent library for many of the ideas.
 */
jQuery.event = {

	add: function( elem, types, handler, data, selector ) {

		var elemData, eventHandle, events,
			t, tns, type, namespaces, handleObj,
			handleObjIn, quick, handlers, special;

		// Don't attach events to noData or text/comment nodes (allow plain objects tho)
		if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {
			return;
		}

		// Caller can pass in an object of custom data in lieu of the handler
		if ( handler.handler ) {
			handleObjIn = handler;
			handler = handleObjIn.handler;
		}

		// Make sure that the handler has a unique ID, used to find/remove it later
		if ( !handler.guid ) {
			handler.guid = jQuery.guid++;
		}

		// Init the element's event structure and main handler, if this is the first
		events = elemData.events;
		if ( !events ) {
			elemData.events = events = {};
		}
		eventHandle = elemData.handle;
		if ( !eventHandle ) {
			elemData.handle = eventHandle = function( e ) {
				// Discard the second event of a jQuery.event.trigger() and
				// when an event is called after a page has unloaded
				return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
					jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
					undefined;
			};
			// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
			eventHandle.elem = elem;
		}

		// Handle multiple events separated by a space
		// jQuery(...).bind("mouseover mouseout", fn);
		types = jQuery.trim( hoverHack(types) ).split( " " );
		for ( t = 0; t < types.length; t++ ) {

			tns = rtypenamespace.exec( types[t] ) || [];
			type = tns[1];
			namespaces = ( tns[2] || "" ).split( "." ).sort();

			// If event changes its type, use the special event handlers for the changed type
			special = jQuery.event.special[ type ] || {};

			// If selector defined, determine special event api type, otherwise given type
			type = ( selector ? special.delegateType : special.bindType ) || type;

			// Update special based on newly reset type
			special = jQuery.event.special[ type ] || {};

			// handleObj is passed to all event handlers
			handleObj = jQuery.extend({
				type: type,
				origType: tns[1],
				data: data,
				handler: handler,
				guid: handler.guid,
				selector: selector,
				quick: quickParse( selector ),
				namespace: namespaces.join(".")
			}, handleObjIn );

			// Init the event handler queue if we're the first
			handlers = events[ type ];
			if ( !handlers ) {
				handlers = events[ type ] = [];
				handlers.delegateCount = 0;

				// Only use addEventListener/attachEvent if the special events handler returns false
				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
					// Bind the global event handler to the element
					if ( elem.addEventListener ) {
						elem.addEventListener( type, eventHandle, false );

					} else if ( elem.attachEvent ) {
						elem.attachEvent( "on" + type, eventHandle );
					}
				}
			}

			if ( special.add ) {
				special.add.call( elem, handleObj );

				if ( !handleObj.handler.guid ) {
					handleObj.handler.guid = handler.guid;
				}
			}

			// Add to the element's handler list, delegates in front
			if ( selector ) {
				handlers.splice( handlers.delegateCount++, 0, handleObj );
			} else {
				handlers.push( handleObj );
			}

			// Keep track of which events have ever been used, for event optimization
			jQuery.event.global[ type ] = true;
		}

		// Nullify elem to prevent memory leaks in IE
		elem = null;
	},

	global: {},

	// Detach an event or set of events from an element
	remove: function( elem, types, handler, selector, mappedTypes ) {

		var elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
			t, tns, type, origType, namespaces, origCount,
			j, events, special, handle, eventType, handleObj;

		if ( !elemData || !(events = elemData.events) ) {
			return;
		}

		// Once for each type.namespace in types; type may be omitted
		types = jQuery.trim( hoverHack( types || "" ) ).split(" ");
		for ( t = 0; t < types.length; t++ ) {
			tns = rtypenamespace.exec( types[t] ) || [];
			type = origType = tns[1];
			namespaces = tns[2];

			// Unbind all events (on this namespace, if provided) for the element
			if ( !type ) {
				for ( type in events ) {
					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
				}
				continue;
			}

			special = jQuery.event.special[ type ] || {};
			type = ( selector? special.delegateType : special.bindType ) || type;
			eventType = events[ type ] || [];
			origCount = eventType.length;
			namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null;

			// Remove matching events
			for ( j = 0; j < eventType.length; j++ ) {
				handleObj = eventType[ j ];

				if ( ( mappedTypes || origType === handleObj.origType ) &&
					 ( !handler || handler.guid === handleObj.guid ) &&
					 ( !namespaces || namespaces.test( handleObj.namespace ) ) &&
					 ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
					eventType.splice( j--, 1 );

					if ( handleObj.selector ) {
						eventType.delegateCount--;
					}
					if ( special.remove ) {
						special.remove.call( elem, handleObj );
					}
				}
			}

			// Remove generic event handler if we removed something and no more handlers exist
			// (avoids potential for endless recursion during removal of special event handlers)
			if ( eventType.length === 0 && origCount !== eventType.length ) {
				if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
					jQuery.removeEvent( elem, type, elemData.handle );
				}

				delete events[ type ];
			}
		}

		// Remove the expando if it's no longer used
		if ( jQuery.isEmptyObject( events ) ) {
			handle = elemData.handle;
			if ( handle ) {
				handle.elem = null;
			}

			// removeData also checks for emptiness and clears the expando if empty
			// so use it instead of delete
			jQuery.removeData( elem, [ "events", "handle" ], true );
		}
	},

	// Events that are safe to short-circuit if no handlers are attached.
	// Native DOM events should not be added, they may have inline handlers.
	customEvent: {
		"getData": true,
		"setData": true,
		"changeData": true
	},

	trigger: function( event, data, elem, onlyHandlers ) {
		// Don't do events on text and comment nodes
		if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {
			return;
		}

		// Event object or event type
		var type = event.type || event,
			namespaces = [],
			cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;

		// focus/blur morphs to focusin/out; ensure we're not firing them right now
		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
			return;
		}

		if ( type.indexOf( "!" ) >= 0 ) {
			// Exclusive events trigger only for the exact event (no namespaces)
			type = type.slice(0, -1);
			exclusive = true;
		}

		if ( type.indexOf( "." ) >= 0 ) {
			// Namespaced trigger; create a regexp to match event type in handle()
			namespaces = type.split(".");
			type = namespaces.shift();
			namespaces.sort();
		}

		if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
			// No jQuery handlers for this event type, and it can't have inline handlers
			return;
		}

		// Caller can pass in an Event, Object, or just an event type string
		event = typeof event === "object" ?
			// jQuery.Event object
			event[ jQuery.expando ] ? event :
			// Object literal
			new jQuery.Event( type, event ) :
			// Just the event type (string)
			new jQuery.Event( type );

		event.type = type;
		event.isTrigger = true;
		event.exclusive = exclusive;
		event.namespace = namespaces.join( "." );
		event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
		ontype = type.indexOf( ":" ) < 0 ? "on" + type : "";

		// Handle a global trigger
		if ( !elem ) {

			// TODO: Stop taunting the data cache; remove global events and always attach to document
			cache = jQuery.cache;
			for ( i in cache ) {
				if ( cache[ i ].events && cache[ i ].events[ type ] ) {
					jQuery.event.trigger( event, data, cache[ i ].handle.elem, true );
				}
			}
			return;
		}

		// Clean up the event in case it is being reused
		event.result = undefined;
		if ( !event.target ) {
			event.target = elem;
		}

		// Clone any incoming data and prepend the event, creating the handler arg list
		data = data != null ? jQuery.makeArray( data ) : [];
		data.unshift( event );

		// Allow special events to draw outside the lines
		special = jQuery.event.special[ type ] || {};
		if ( special.trigger && special.trigger.apply( elem, data ) === false ) {
			return;
		}

		// Determine event propagation path in advance, per W3C events spec (#9951)
		// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
		eventPath = [[ elem, special.bindType || type ]];
		if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {

			bubbleType = special.delegateType || type;
			cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;
			old = null;
			for ( ; cur; cur = cur.parentNode ) {
				eventPath.push([ cur, bubbleType ]);
				old = cur;
			}

			// Only add window if we got to document (e.g., not plain obj or detached DOM)
			if ( old && old === elem.ownerDocument ) {
				eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);
			}
		}

		// Fire handlers on the event path
		for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {

			cur = eventPath[i][0];
			event.type = eventPath[i][1];

			handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
			if ( handle ) {
				handle.apply( cur, data );
			}
			// Note that this is a bare JS function and not a jQuery handler
			handle = ontype && cur[ ontype ];
			if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {
				event.preventDefault();
			}
		}
		event.type = type;

		// If nobody prevented the default action, do it now
		if ( !onlyHandlers && !event.isDefaultPrevented() ) {

			if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
				!(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {

				// Call a native DOM method on the target with the same name name as the event.
				// Can't use an .isFunction() check here because IE6/7 fails that test.
				// Don't do default actions on window, that's where global variables be (#6170)
				// IE<9 dies on focus/blur to hidden element (#1486)
				if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {

					// Don't re-trigger an onFOO event when we call its FOO() method
					old = elem[ ontype ];

					if ( old ) {
						elem[ ontype ] = null;
					}

					// Prevent re-triggering of the same event, since we already bubbled it above
					jQuery.event.triggered = type;
					elem[ type ]();
					jQuery.event.triggered = undefined;

					if ( old ) {
						elem[ ontype ] = old;
					}
				}
			}
		}

		return event.result;
	},

	dispatch: function( event ) {

		// Make a writable jQuery.Event from the native event object
		event = jQuery.event.fix( event || window.event );

		var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []),
			delegateCount = handlers.delegateCount,
			args = [].slice.call( arguments, 0 ),
			run_all = !event.exclusive && !event.namespace,
			handlerQueue = [],
			i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;

		// Use the fix-ed jQuery.Event rather than the (read-only) native event
		args[0] = event;
		event.delegateTarget = this;

		// Determine handlers that should run if there are delegated events
		// Avoid disabled elements in IE (#6911) and non-left-click bubbling in Firefox (#3861)
		if ( delegateCount && !event.target.disabled && !(event.button && event.type === "click") ) {

			// Pregenerate a single jQuery object for reuse with .is()
			jqcur = jQuery(this);
			jqcur.context = this.ownerDocument || this;

			for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {
				selMatch = {};
				matches = [];
				jqcur[0] = cur;
				for ( i = 0; i < delegateCount; i++ ) {
					handleObj = handlers[ i ];
					sel = handleObj.selector;

					if ( selMatch[ sel ] === undefined ) {
						selMatch[ sel ] = (
							handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )
						);
					}
					if ( selMatch[ sel ] ) {
						matches.push( handleObj );
					}
				}
				if ( matches.length ) {
					handlerQueue.push({ elem: cur, matches: matches });
				}
			}
		}

		// Add the remaining (directly-bound) handlers
		if ( handlers.length > delegateCount ) {
			handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });
		}

		// Run delegates first; they may want to stop propagation beneath us
		for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {
			matched = handlerQueue[ i ];
			event.currentTarget = matched.elem;

			for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {
				handleObj = matched.matches[ j ];

				// Triggered event must either 1) be non-exclusive and have no namespace, or
				// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
				if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {

					event.data = handleObj.data;
					event.handleObj = handleObj;

					ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
							.apply( matched.elem, args );

					if ( ret !== undefined ) {
						event.result = ret;
						if ( ret === false ) {
							event.preventDefault();
							event.stopPropagation();
						}
					}
				}
			}
		}

		return event.result;
	},

	// Includes some event props shared by KeyEvent and MouseEvent
	// *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***
	props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),

	fixHooks: {},

	keyHooks: {
		props: "char charCode key keyCode".split(" "),
		filter: function( event, original ) {

			// Add which for key events
			if ( event.which == null ) {
				event.which = original.charCode != null ? original.charCode : original.keyCode;
			}

			return event;
		}
	},

	mouseHooks: {
		props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
		filter: function( event, original ) {
			var eventDoc, doc, body,
				button = original.button,
				fromElement = original.fromElement;

			// Calculate pageX/Y if missing and clientX/Y available
			if ( event.pageX == null && original.clientX != null ) {
				eventDoc = event.target.ownerDocument || document;
				doc = eventDoc.documentElement;
				body = eventDoc.body;

				event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
				event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
			}

			// Add relatedTarget, if necessary
			if ( !event.relatedTarget && fromElement ) {
				event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
			}

			// Add which for click: 1 === left; 2 === middle; 3 === right
			// Note: button is not normalized, so don't use it
			if ( !event.which && button !== undefined ) {
				event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
			}

			return event;
		}
	},

	fix: function( event ) {
		if ( event[ jQuery.expando ] ) {
			return event;
		}

		// Create a writable copy of the event object and normalize some properties
		var i, prop,
			originalEvent = event,
			fixHook = jQuery.event.fixHooks[ event.type ] || {},
			copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;

		event = jQuery.Event( originalEvent );

		for ( i = copy.length; i; ) {
			prop = copy[ --i ];
			event[ prop ] = originalEvent[ prop ];
		}

		// Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)
		if ( !event.target ) {
			event.target = originalEvent.srcElement || document;
		}

		// Target should not be a text node (#504, Safari)
		if ( event.target.nodeType === 3 ) {
			event.target = event.target.parentNode;
		}

		// For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)
		if ( event.metaKey === undefined ) {
			event.metaKey = event.ctrlKey;
		}

		return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
	},

	special: {
		ready: {
			// Make sure the ready event is setup
			setup: jQuery.bindReady
		},

		load: {
			// Prevent triggered image.load events from bubbling to window.load
			noBubble: true
		},

		focus: {
			delegateType: "focusin"
		},
		blur: {
			delegateType: "focusout"
		},

		beforeunload: {
			setup: function( data, namespaces, eventHandle ) {
				// We only want to do this special case on windows
				if ( jQuery.isWindow( this ) ) {
					this.onbeforeunload = eventHandle;
				}
			},

			teardown: function( namespaces, eventHandle ) {
				if ( this.onbeforeunload === eventHandle ) {
					this.onbeforeunload = null;
				}
			}
		}
	},

	simulate: function( type, elem, event, bubble ) {
		// Piggyback on a donor event to simulate a different one.
		// Fake originalEvent to avoid donor's stopPropagation, but if the
		// simulated event prevents default then we do the same on the donor.
		var e = jQuery.extend(
			new jQuery.Event(),
			event,
			{ type: type,
				isSimulated: true,
				originalEvent: {}
			}
		);
		if ( bubble ) {
			jQuery.event.trigger( e, null, elem );
		} else {
			jQuery.event.dispatch.call( elem, e );
		}
		if ( e.isDefaultPrevented() ) {
			event.preventDefault();
		}
	}
};

// Some plugins are using, but it's undocumented/deprecated and will be removed.
// The 1.7 special event interface should provide all the hooks needed now.
jQuery.event.handle = jQuery.event.dispatch;

jQuery.removeEvent = document.removeEventListener ?
	function( elem, type, handle ) {
		if ( elem.removeEventListener ) {
			elem.removeEventListener( type, handle, false );
		}
	} :
	function( elem, type, handle ) {
		if ( elem.detachEvent ) {
			elem.detachEvent( "on" + type, handle );
		}
	};

jQuery.Event = function( src, props ) {
	// Allow instantiation without the 'new' keyword
	if ( !(this instanceof jQuery.Event) ) {
		return new jQuery.Event( src, props );
	}

	// Event object
	if ( src && src.type ) {
		this.originalEvent = src;
		this.type = src.type;

		// Events bubbling up the document may have been marked as prevented
		// by a handler lower down the tree; reflect the correct value.
		this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
			src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;

	// Event type
	} else {
		this.type = src;
	}

	// Put explicitly provided properties onto the event object
	if ( props ) {
		jQuery.extend( this, props );
	}

	// Create a timestamp if incoming event doesn't have one
	this.timeStamp = src && src.timeStamp || jQuery.now();

	// Mark it as fixed
	this[ jQuery.expando ] = true;
};

function returnFalse() {
	return false;
}
function returnTrue() {
	return true;
}

// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
jQuery.Event.prototype = {
	preventDefault: function() {
		this.isDefaultPrevented = returnTrue;

		var e = this.originalEvent;
		if ( !e ) {
			return;
		}

		// if preventDefault exists run it on the original event
		if ( e.preventDefault ) {
			e.preventDefault();

		// otherwise set the returnValue property of the original event to false (IE)
		} else {
			e.returnValue = false;
		}
	},
	stopPropagation: function() {
		this.isPropagationStopped = returnTrue;

		var e = this.originalEvent;
		if ( !e ) {
			return;
		}
		// if stopPropagation exists run it on the original event
		if ( e.stopPropagation ) {
			e.stopPropagation();
		}
		// otherwise set the cancelBubble property of the original event to true (IE)
		e.cancelBubble = true;
	},
	stopImmediatePropagation: function() {
		this.isImmediatePropagationStopped = returnTrue;
		this.stopPropagation();
	},
	isDefaultPrevented: returnFalse,
	isPropagationStopped: returnFalse,
	isImmediatePropagationStopped: returnFalse
};

// Create mouseenter/leave events using mouseover/out and event-time checks
jQuery.each({
	mouseenter: "mouseover",
	mouseleave: "mouseout"
}, function( orig, fix ) {
	jQuery.event.special[ orig ] = {
		delegateType: fix,
		bindType: fix,

		handle: function( event ) {
			var target = this,
				related = event.relatedTarget,
				handleObj = event.handleObj,
				selector = handleObj.selector,
				ret;

			// For mousenter/leave call the handler if related is outside the target.
			// NB: No relatedTarget if the mouse left/entered the browser window
			if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
				event.type = handleObj.origType;
				ret = handleObj.handler.apply( this, arguments );
				event.type = fix;
			}
			return ret;
		}
	};
});

// IE submit delegation
if ( !jQuery.support.submitBubbles ) {

	jQuery.event.special.submit = {
		setup: function() {
			// Only need this for delegated form submit events
			if ( jQuery.nodeName( this, "form" ) ) {
				return false;
			}

			// Lazy-add a submit handler when a descendant form may potentially be submitted
			jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
				// Node name check avoids a VML-related crash in IE (#9807)
				var elem = e.target,
					form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
				if ( form && !form._submit_attached ) {
					jQuery.event.add( form, "submit._submit", function( event ) {
						// If form was submitted by the user, bubble the event up the tree
						if ( this.parentNode && !event.isTrigger ) {
							jQuery.event.simulate( "submit", this.parentNode, event, true );
						}
					});
					form._submit_attached = true;
				}
			});
			// return undefined since we don't need an event listener
		},

		teardown: function() {
			// Only need this for delegated form submit events
			if ( jQuery.nodeName( this, "form" ) ) {
				return false;
			}

			// Remove delegated handlers; cleanData eventually reaps submit handlers attached above
			jQuery.event.remove( this, "._submit" );
		}
	};
}

// IE change delegation and checkbox/radio fix
if ( !jQuery.support.changeBubbles ) {

	jQuery.event.special.change = {

		setup: function() {

			if ( rformElems.test( this.nodeName ) ) {
				// IE doesn't fire change on a check/radio until blur; trigger it on click
				// after a propertychange. Eat the blur-change in special.change.handle.
				// This still fires onchange a second time for check/radio after blur.
				if ( this.type === "checkbox" || this.type === "radio" ) {
					jQuery.event.add( this, "propertychange._change", function( event ) {
						if ( event.originalEvent.propertyName === "checked" ) {
							this._just_changed = true;
						}
					});
					jQuery.event.add( this, "click._change", function( event ) {
						if ( this._just_changed && !event.isTrigger ) {
							this._just_changed = false;
							jQuery.event.simulate( "change", this, event, true );
						}
					});
				}
				return false;
			}
			// Delegated event; lazy-add a change handler on descendant inputs
			jQuery.event.add( this, "beforeactivate._change", function( e ) {
				var elem = e.target;

				if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {
					jQuery.event.add( elem, "change._change", function( event ) {
						if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
							jQuery.event.simulate( "change", this.parentNode, event, true );
						}
					});
					elem._change_attached = true;
				}
			});
		},

		handle: function( event ) {
			var elem = event.target;

			// Swallow native change events from checkbox/radio, we already triggered them above
			if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
				return event.handleObj.handler.apply( this, arguments );
			}
		},

		teardown: function() {
			jQuery.event.remove( this, "._change" );

			return rformElems.test( this.nodeName );
		}
	};
}

// Create "bubbling" focus and blur events
if ( !jQuery.support.focusinBubbles ) {
	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {

		// Attach a single capturing handler while someone wants focusin/focusout
		var attaches = 0,
			handler = function( event ) {
				jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
			};

		jQuery.event.special[ fix ] = {
			setup: function() {
				if ( attaches++ === 0 ) {
					document.addEventListener( orig, handler, true );
				}
			},
			teardown: function() {
				if ( --attaches === 0 ) {
					document.removeEventListener( orig, handler, true );
				}
			}
		};
	});
}

jQuery.fn.extend({

	on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
		var origFn, type;

		// Types can be a map of types/handlers
		if ( typeof types === "object" ) {
			// ( types-Object, selector, data )
			if ( typeof selector !== "string" ) {
				// ( types-Object, data )
				data = selector;
				selector = undefined;
			}
			for ( type in types ) {
				this.on( type, selector, data, types[ type ], one );
			}
			return this;
		}

		if ( data == null && fn == null ) {
			// ( types, fn )
			fn = selector;
			data = selector = undefined;
		} else if ( fn == null ) {
			if ( typeof selector === "string" ) {
				// ( types, selector, fn )
				fn = data;
				data = undefined;
			} else {
				// ( types, data, fn )
				fn = data;
				data = selector;
				selector = undefined;
			}
		}
		if ( fn === false ) {
			fn = returnFalse;
		} else if ( !fn ) {
			return this;
		}

		if ( one === 1 ) {
			origFn = fn;
			fn = function( event ) {
				// Can use an empty set, since event contains the info
				jQuery().off( event );
				return origFn.apply( this, arguments );
			};
			// Use same guid so caller can remove using origFn
			fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
		}
		return this.each( function() {
			jQuery.event.add( this, types, fn, data, selector );
		});
	},
	one: function( types, selector, data, fn ) {
		return this.on.call( this, types, selector, data, fn, 1 );
	},
	off: function( types, selector, fn ) {
		if ( types && types.preventDefault && types.handleObj ) {
			// ( event )  dispatched jQuery.Event
			var handleObj = types.handleObj;
			jQuery( types.delegateTarget ).off(
				handleObj.namespace? handleObj.type + "." + handleObj.namespace : handleObj.type,
				handleObj.selector,
				handleObj.handler
			);
			return this;
		}
		if ( typeof types === "object" ) {
			// ( types-object [, selector] )
			for ( var type in types ) {
				this.off( type, selector, types[ type ] );
			}
			return this;
		}
		if ( selector === false || typeof selector === "function" ) {
			// ( types [, fn] )
			fn = selector;
			selector = undefined;
		}
		if ( fn === false ) {
			fn = returnFalse;
		}
		return this.each(function() {
			jQuery.event.remove( this, types, fn, selector );
		});
	},

	bind: function( types, data, fn ) {
		return this.on( types, null, data, fn );
	},
	unbind: function( types, fn ) {
		return this.off( types, null, fn );
	},

	live: function( types, data, fn ) {
		jQuery( this.context ).on( types, this.selector, data, fn );
		return this;
	},
	die: function( types, fn ) {
		jQuery( this.context ).off( types, this.selector || "**", fn );
		return this;
	},

	delegate: function( selector, types, data, fn ) {
		return this.on( types, selector, data, fn );
	},
	undelegate: function( selector, types, fn ) {
		// ( namespace ) or ( selector, types [, fn] )
		return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn );
	},

	trigger: function( type, data ) {
		return this.each(function() {
			jQuery.event.trigger( type, data, this );
		});
	},
	triggerHandler: function( type, data ) {
		if ( this[0] ) {
			return jQuery.event.trigger( type, data, this[0], true );
		}
	},

	toggle: function( fn ) {
		// Save reference to arguments for access in closure
		var args = arguments,
			guid = fn.guid || jQuery.guid++,
			i = 0,
			toggler = function( event ) {
				// Figure out which function to execute
				var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
				jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );

				// Make sure that clicks stop
				event.preventDefault();

				// and execute the function
				return args[ lastToggle ].apply( this, arguments ) || false;
			};

		// link all the functions, so any of them can unbind this click handler
		toggler.guid = guid;
		while ( i < args.length ) {
			args[ i++ ].guid = guid;
		}

		return this.click( toggler );
	},

	hover: function( fnOver, fnOut ) {
		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
	}
});

jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
	"change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {

	// Handle event binding
	jQuery.fn[ name ] = function( data, fn ) {
		if ( fn == null ) {
			fn = data;
			data = null;
		}

		return arguments.length > 0 ?
			this.on( name, null, data, fn ) :
			this.trigger( name );
	};

	if ( jQuery.attrFn ) {
		jQuery.attrFn[ name ] = true;
	}

	if ( rkeyEvent.test( name ) ) {
		jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;
	}

	if ( rmouseEvent.test( name ) ) {
		jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;
	}
});



/*!
 * Sizzle CSS Selector Engine
 *  Copyright 2011, The Dojo Foundation
 *  Released under the MIT, BSD, and GPL Licenses.
 *  More information: http://sizzlejs.com/
 */
(function(){

var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
	expando = "sizcache" + (Math.random() + '').replace('.', ''),
	done = 0,
	toString = Object.prototype.toString,
	hasDuplicate = false,
	baseHasDuplicate = true,
	rBackslash = /\\/g,
	rReturn = /\r\n/g,
	rNonWord = /\W/;

// Here we check if the JavaScript engine is using some sort of
// optimization where it does not always call our comparision
// function. If that is the case, discard the hasDuplicate value.
//   Thus far that includes Google Chrome.
[0, 0].sort(function() {
	baseHasDuplicate = false;
	return 0;
});

var Sizzle = function( selector, context, results, seed ) {
	results = results || [];
	context = context || document;

	var origContext = context;

	if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
		return [];
	}
	
	if ( !selector || typeof selector !== "string" ) {
		return results;
	}

	var m, set, checkSet, extra, ret, cur, pop, i,
		prune = true,
		contextXML = Sizzle.isXML( context ),
		parts = [],
		soFar = selector;
	
	// Reset the position of the chunker regexp (start from head)
	do {
		chunker.exec( "" );
		m = chunker.exec( soFar );

		if ( m ) {
			soFar = m[3];
		
			parts.push( m[1] );
		
			if ( m[2] ) {
				extra = m[3];
				break;
			}
		}
	} while ( m );

	if ( parts.length > 1 && origPOS.exec( selector ) ) {

		if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
			set = posProcess( parts[0] + parts[1], context, seed );

		} else {
			set = Expr.relative[ parts[0] ] ?
				[ context ] :
				Sizzle( parts.shift(), context );

			while ( parts.length ) {
				selector = parts.shift();

				if ( Expr.relative[ selector ] ) {
					selector += parts.shift();
				}
				
				set = posProcess( selector, set, seed );
			}
		}

	} else {
		// Take a shortcut and set the context if the root selector is an ID
		// (but not if it'll be faster if the inner selector is an ID)
		if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
				Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {

			ret = Sizzle.find( parts.shift(), context, contextXML );
			context = ret.expr ?
				Sizzle.filter( ret.expr, ret.set )[0] :
				ret.set[0];
		}

		if ( context ) {
			ret = seed ?
				{ expr: parts.pop(), set: makeArray(seed) } :
				Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );

			set = ret.expr ?
				Sizzle.filter( ret.expr, ret.set ) :
				ret.set;

			if ( parts.length > 0 ) {
				checkSet = makeArray( set );

			} else {
				prune = false;
			}

			while ( parts.length ) {
				cur = parts.pop();
				pop = cur;

				if ( !Expr.relative[ cur ] ) {
					cur = "";
				} else {
					pop = parts.pop();
				}

				if ( pop == null ) {
					pop = context;
				}

				Expr.relative[ cur ]( checkSet, pop, contextXML );
			}

		} else {
			checkSet = parts = [];
		}
	}

	if ( !checkSet ) {
		checkSet = set;
	}

	if ( !checkSet ) {
		Sizzle.error( cur || selector );
	}

	if ( toString.call(checkSet) === "[object Array]" ) {
		if ( !prune ) {
			results.push.apply( results, checkSet );

		} else if ( context && context.nodeType === 1 ) {
			for ( i = 0; checkSet[i] != null; i++ ) {
				if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
					results.push( set[i] );
				}
			}

		} else {
			for ( i = 0; checkSet[i] != null; i++ ) {
				if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
					results.push( set[i] );
				}
			}
		}

	} else {
		makeArray( checkSet, results );
	}

	if ( extra ) {
		Sizzle( extra, origContext, results, seed );
		Sizzle.uniqueSort( results );
	}

	return results;
};

Sizzle.uniqueSort = function( results ) {
	if ( sortOrder ) {
		hasDuplicate = baseHasDuplicate;
		results.sort( sortOrder );

		if ( hasDuplicate ) {
			for ( var i = 1; i < results.length; i++ ) {
				if ( results[i] === results[ i - 1 ] ) {
					results.splice( i--, 1 );
				}
			}
		}
	}

	return results;
};

Sizzle.matches = function( expr, set ) {
	return Sizzle( expr, null, null, set );
};

Sizzle.matchesSelector = function( node, expr ) {
	return Sizzle( expr, null, null, [node] ).length > 0;
};

Sizzle.find = function( expr, context, isXML ) {
	var set, i, len, match, type, left;

	if ( !expr ) {
		return [];
	}

	for ( i = 0, len = Expr.order.length; i < len; i++ ) {
		type = Expr.order[i];
		
		if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
			left = match[1];
			match.splice( 1, 1 );

			if ( left.substr( left.length - 1 ) !== "\\" ) {
				match[1] = (match[1] || "").replace( rBackslash, "" );
				set = Expr.find[ type ]( match, context, isXML );

				if ( set != null ) {
					expr = expr.replace( Expr.match[ type ], "" );
					break;
				}
			}
		}
	}

	if ( !set ) {
		set = typeof context.getElementsByTagName !== "undefined" ?
			context.getElementsByTagName( "*" ) :
			[];
	}

	return { set: set, expr: expr };
};

Sizzle.filter = function( expr, set, inplace, not ) {
	var match, anyFound,
		type, found, item, filter, left,
		i, pass,
		old = expr,
		result = [],
		curLoop = set,
		isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );

	while ( expr && set.length ) {
		for ( type in Expr.filter ) {
			if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
				filter = Expr.filter[ type ];
				left = match[1];

				anyFound = false;

				match.splice(1,1);

				if ( left.substr( left.length - 1 ) === "\\" ) {
					continue;
				}

				if ( curLoop === result ) {
					result = [];
				}

				if ( Expr.preFilter[ type ] ) {
					match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );

					if ( !match ) {
						anyFound = found = true;

					} else if ( match === true ) {
						continue;
					}
				}

				if ( match ) {
					for ( i = 0; (item = curLoop[i]) != null; i++ ) {
						if ( item ) {
							found = filter( item, match, i, curLoop );
							pass = not ^ found;

							if ( inplace && found != null ) {
								if ( pass ) {
									anyFound = true;

								} else {
									curLoop[i] = false;
								}

							} else if ( pass ) {
								result.push( item );
								anyFound = true;
							}
						}
					}
				}

				if ( found !== undefined ) {
					if ( !inplace ) {
						curLoop = result;
					}

					expr = expr.replace( Expr.match[ type ], "" );

					if ( !anyFound ) {
						return [];
					}

					break;
				}
			}
		}

		// Improper expression
		if ( expr === old ) {
			if ( anyFound == null ) {
				Sizzle.error( expr );

			} else {
				break;
			}
		}

		old = expr;
	}

	return curLoop;
};

Sizzle.error = function( msg ) {
	throw new Error( "Syntax error, unrecognized expression: " + msg );
};

/**
 * Utility function for retreiving the text value of an array of DOM nodes
 * @param {Array|Element} elem
 */
var getText = Sizzle.getText = function( elem ) {
    var i, node,
		nodeType = elem.nodeType,
		ret = "";

	if ( nodeType ) {
		if ( nodeType === 1 || nodeType === 9 ) {
			// Use textContent || innerText for elements
			if ( typeof elem.textContent === 'string' ) {
				return elem.textContent;
			} else if ( typeof elem.innerText === 'string' ) {
				// Replace IE's carriage returns
				return elem.innerText.replace( rReturn, '' );
			} else {
				// Traverse it's children
				for ( elem = elem.firstChild; elem; elem = elem.nextSibling) {
					ret += getText( elem );
				}
			}
		} else if ( nodeType === 3 || nodeType === 4 ) {
			return elem.nodeValue;
		}
	} else {

		// If no nodeType, this is expected to be an array
		for ( i = 0; (node = elem[i]); i++ ) {
			// Do not traverse comment nodes
			if ( node.nodeType !== 8 ) {
				ret += getText( node );
			}
		}
	}
	return ret;
};

var Expr = Sizzle.selectors = {
	order: [ "ID", "NAME", "TAG" ],

	match: {
		ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
		CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
		NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
		ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
		TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
		CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
		POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
		PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
	},

	leftMatch: {},

	attrMap: {
		"class": "className",
		"for": "htmlFor"
	},

	attrHandle: {
		href: function( elem ) {
			return elem.getAttribute( "href" );
		},
		type: function( elem ) {
			return elem.getAttribute( "type" );
		}
	},

	relative: {
		"+": function(checkSet, part){
			var isPartStr = typeof part === "string",
				isTag = isPartStr && !rNonWord.test( part ),
				isPartStrNotTag = isPartStr && !isTag;

			if ( isTag ) {
				part = part.toLowerCase();
			}

			for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
				if ( (elem = checkSet[i]) ) {
					while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}

					checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
						elem || false :
						elem === part;
				}
			}

			if ( isPartStrNotTag ) {
				Sizzle.filter( part, checkSet, true );
			}
		},

		">": function( checkSet, part ) {
			var elem,
				isPartStr = typeof part === "string",
				i = 0,
				l = checkSet.length;

			if ( isPartStr && !rNonWord.test( part ) ) {
				part = part.toLowerCase();

				for ( ; i < l; i++ ) {
					elem = checkSet[i];

					if ( elem ) {
						var parent = elem.parentNode;
						checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
					}
				}

			} else {
				for ( ; i < l; i++ ) {
					elem = checkSet[i];

					if ( elem ) {
						checkSet[i] = isPartStr ?
							elem.parentNode :
							elem.parentNode === part;
					}
				}

				if ( isPartStr ) {
					Sizzle.filter( part, checkSet, true );
				}
			}
		},

		"": function(checkSet, part, isXML){
			var nodeCheck,
				doneName = done++,
				checkFn = dirCheck;

			if ( typeof part === "string" && !rNonWord.test( part ) ) {
				part = part.toLowerCase();
				nodeCheck = part;
				checkFn = dirNodeCheck;
			}

			checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
		},

		"~": function( checkSet, part, isXML ) {
			var nodeCheck,
				doneName = done++,
				checkFn = dirCheck;

			if ( typeof part === "string" && !rNonWord.test( part ) ) {
				part = part.toLowerCase();
				nodeCheck = part;
				checkFn = dirNodeCheck;
			}

			checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
		}
	},

	find: {
		ID: function( match, context, isXML ) {
			if ( typeof context.getElementById !== "undefined" && !isXML ) {
				var m = context.getElementById(match[1]);
				// Check parentNode to catch when Blackberry 4.6 returns
				// nodes that are no longer in the document #6963
				return m && m.parentNode ? [m] : [];
			}
		},

		NAME: function( match, context ) {
			if ( typeof context.getElementsByName !== "undefined" ) {
				var ret = [],
					results = context.getElementsByName( match[1] );

				for ( var i = 0, l = results.length; i < l; i++ ) {
					if ( results[i].getAttribute("name") === match[1] ) {
						ret.push( results[i] );
					}
				}

				return ret.length === 0 ? null : ret;
			}
		},

		TAG: function( match, context ) {
			if ( typeof context.getElementsByTagName !== "undefined" ) {
				return context.getElementsByTagName( match[1] );
			}
		}
	},
	preFilter: {
		CLASS: function( match, curLoop, inplace, result, not, isXML ) {
			match = " " + match[1].replace( rBackslash, "" ) + " ";

			if ( isXML ) {
				return match;
			}

			for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
				if ( elem ) {
					if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) {
						if ( !inplace ) {
							result.push( elem );
						}

					} else if ( inplace ) {
						curLoop[i] = false;
					}
				}
			}

			return false;
		},

		ID: function( match ) {
			return match[1].replace( rBackslash, "" );
		},

		TAG: function( match, curLoop ) {
			return match[1].replace( rBackslash, "" ).toLowerCase();
		},

		CHILD: function( match ) {
			if ( match[1] === "nth" ) {
				if ( !match[2] ) {
					Sizzle.error( match[0] );
				}

				match[2] = match[2].replace(/^\+|\s*/g, '');

				// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
				var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec(
					match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
					!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);

				// calculate the numbers (first)n+(last) including if they are negative
				match[2] = (test[1] + (test[2] || 1)) - 0;
				match[3] = test[3] - 0;
			}
			else if ( match[2] ) {
				Sizzle.error( match[0] );
			}

			// TODO: Move to normal caching system
			match[0] = done++;

			return match;
		},

		ATTR: function( match, curLoop, inplace, result, not, isXML ) {
			var name = match[1] = match[1].replace( rBackslash, "" );
			
			if ( !isXML && Expr.attrMap[name] ) {
				match[1] = Expr.attrMap[name];
			}

			// Handle if an un-quoted value was used
			match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" );

			if ( match[2] === "~=" ) {
				match[4] = " " + match[4] + " ";
			}

			return match;
		},

		PSEUDO: function( match, curLoop, inplace, result, not ) {
			if ( match[1] === "not" ) {
				// If we're dealing with a complex expression, or a simple one
				if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
					match[3] = Sizzle(match[3], null, null, curLoop);

				} else {
					var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);

					if ( !inplace ) {
						result.push.apply( result, ret );
					}

					return false;
				}

			} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
				return true;
			}
			
			return match;
		},

		POS: function( match ) {
			match.unshift( true );

			return match;
		}
	},
	
	filters: {
		enabled: function( elem ) {
			return elem.disabled === false && elem.type !== "hidden";
		},

		disabled: function( elem ) {
			return elem.disabled === true;
		},

		checked: function( elem ) {
			return elem.checked === true;
		},
		
		selected: function( elem ) {
			// Accessing this property makes selected-by-default
			// options in Safari work properly
			if ( elem.parentNode ) {
				elem.parentNode.selectedIndex;
			}
			
			return elem.selected === true;
		},

		parent: function( elem ) {
			return !!elem.firstChild;
		},

		empty: function( elem ) {
			return !elem.firstChild;
		},

		has: function( elem, i, match ) {
			return !!Sizzle( match[3], elem ).length;
		},

		header: function( elem ) {
			return (/h\d/i).test( elem.nodeName );
		},

		text: function( elem ) {
			var attr = elem.getAttribute( "type" ), type = elem.type;
			// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) 
			// use getAttribute instead to test this case
			return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null );
		},

		radio: function( elem ) {
			return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type;
		},

		checkbox: function( elem ) {
			return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type;
		},

		file: function( elem ) {
			return elem.nodeName.toLowerCase() === "input" && "file" === elem.type;
		},

		password: function( elem ) {
			return elem.nodeName.toLowerCase() === "input" && "password" === elem.type;
		},

		submit: function( elem ) {
			var name = elem.nodeName.toLowerCase();
			return (name === "input" || name === "button") && "submit" === elem.type;
		},

		image: function( elem ) {
			return elem.nodeName.toLowerCase() === "input" && "image" === elem.type;
		},

		reset: function( elem ) {
			var name = elem.nodeName.toLowerCase();
			return (name === "input" || name === "button") && "reset" === elem.type;
		},

		button: function( elem ) {
			var name = elem.nodeName.toLowerCase();
			return name === "input" && "button" === elem.type || name === "button";
		},

		input: function( elem ) {
			return (/input|select|textarea|button/i).test( elem.nodeName );
		},

		focus: function( elem ) {
			return elem === elem.ownerDocument.activeElement;
		}
	},
	setFilters: {
		first: function( elem, i ) {
			return i === 0;
		},

		last: function( elem, i, match, array ) {
			return i === array.length - 1;
		},

		even: function( elem, i ) {
			return i % 2 === 0;
		},

		odd: function( elem, i ) {
			return i % 2 === 1;
		},

		lt: function( elem, i, match ) {
			return i < match[3] - 0;
		},

		gt: function( elem, i, match ) {
			return i > match[3] - 0;
		},

		nth: function( elem, i, match ) {
			return match[3] - 0 === i;
		},

		eq: function( elem, i, match ) {
			return match[3] - 0 === i;
		}
	},
	filter: {
		PSEUDO: function( elem, match, i, array ) {
			var name = match[1],
				filter = Expr.filters[ name ];

			if ( filter ) {
				return filter( elem, i, match, array );

			} else if ( name === "contains" ) {
				return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;

			} else if ( name === "not" ) {
				var not = match[3];

				for ( var j = 0, l = not.length; j < l; j++ ) {
					if ( not[j] === elem ) {
						return false;
					}
				}

				return true;

			} else {
				Sizzle.error( name );
			}
		},

		CHILD: function( elem, match ) {
			var first, last,
				doneName, parent, cache,
				count, diff,
				type = match[1],
				node = elem;

			switch ( type ) {
				case "only":
				case "first":
					while ( (node = node.previousSibling) )	 {
						if ( node.nodeType === 1 ) { 
							return false; 
						}
					}

					if ( type === "first" ) { 
						return true; 
					}

					node = elem;

				case "last":
					while ( (node = node.nextSibling) )	 {
						if ( node.nodeType === 1 ) { 
							return false; 
						}
					}

					return true;

				case "nth":
					first = match[2];
					last = match[3];

					if ( first === 1 && last === 0 ) {
						return true;
					}
					
					doneName = match[0];
					parent = elem.parentNode;
	
					if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {
						count = 0;
						
						for ( node = parent.firstChild; node; node = node.nextSibling ) {
							if ( node.nodeType === 1 ) {
								node.nodeIndex = ++count;
							}
						} 

						parent[ expando ] = doneName;
					}
					
					diff = elem.nodeIndex - last;

					if ( first === 0 ) {
						return diff === 0;

					} else {
						return ( diff % first === 0 && diff / first >= 0 );
					}
			}
		},

		ID: function( elem, match ) {
			return elem.nodeType === 1 && elem.getAttribute("id") === match;
		},

		TAG: function( elem, match ) {
			return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;
		},
		
		CLASS: function( elem, match ) {
			return (" " + (elem.className || elem.getAttribute("class")) + " ")
				.indexOf( match ) > -1;
		},

		ATTR: function( elem, match ) {
			var name = match[1],
				result = Sizzle.attr ?
					Sizzle.attr( elem, name ) :
					Expr.attrHandle[ name ] ?
					Expr.attrHandle[ name ]( elem ) :
					elem[ name ] != null ?
						elem[ name ] :
						elem.getAttribute( name ),
				value = result + "",
				type = match[2],
				check = match[4];

			return result == null ?
				type === "!=" :
				!type && Sizzle.attr ?
				result != null :
				type === "=" ?
				value === check :
				type === "*=" ?
				value.indexOf(check) >= 0 :
				type === "~=" ?
				(" " + value + " ").indexOf(check) >= 0 :
				!check ?
				value && result !== false :
				type === "!=" ?
				value !== check :
				type === "^=" ?
				value.indexOf(check) === 0 :
				type === "$=" ?
				value.substr(value.length - check.length) === check :
				type === "|=" ?
				value === check || value.substr(0, check.length + 1) === check + "-" :
				false;
		},

		POS: function( elem, match, i, array ) {
			var name = match[2],
				filter = Expr.setFilters[ name ];

			if ( filter ) {
				return filter( elem, i, match, array );
			}
		}
	}
};

var origPOS = Expr.match.POS,
	fescape = function(all, num){
		return "\\" + (num - 0 + 1);
	};

for ( var type in Expr.match ) {
	Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
	Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
}

var makeArray = function( array, results ) {
	array = Array.prototype.slice.call( array, 0 );

	if ( results ) {
		results.push.apply( results, array );
		return results;
	}
	
	return array;
};

// Perform a simple check to determine if the browser is capable of
// converting a NodeList to an array using builtin methods.
// Also verifies that the returned array holds DOM nodes
// (which is not the case in the Blackberry browser)
try {
	Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;

// Provide a fallback method if it does not work
} catch( e ) {
	makeArray = function( array, results ) {
		var i = 0,
			ret = results || [];

		if ( toString.call(array) === "[object Array]" ) {
			Array.prototype.push.apply( ret, array );

		} else {
			if ( typeof array.length === "number" ) {
				for ( var l = array.length; i < l; i++ ) {
					ret.push( array[i] );
				}

			} else {
				for ( ; array[i]; i++ ) {
					ret.push( array[i] );
				}
			}
		}

		return ret;
	};
}

var sortOrder, siblingCheck;

if ( document.documentElement.compareDocumentPosition ) {
	sortOrder = function( a, b ) {
		if ( a === b ) {
			hasDuplicate = true;
			return 0;
		}

		if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
			return a.compareDocumentPosition ? -1 : 1;
		}

		return a.compareDocumentPosition(b) & 4 ? -1 : 1;
	};

} else {
	sortOrder = function( a, b ) {
		// The nodes are identical, we can exit early
		if ( a === b ) {
			hasDuplicate = true;
			return 0;

		// Fallback to using sourceIndex (in IE) if it's available on both nodes
		} else if ( a.sourceIndex && b.sourceIndex ) {
			return a.sourceIndex - b.sourceIndex;
		}

		var al, bl,
			ap = [],
			bp = [],
			aup = a.parentNode,
			bup = b.parentNode,
			cur = aup;

		// If the nodes are siblings (or identical) we can do a quick check
		if ( aup === bup ) {
			return siblingCheck( a, b );

		// If no parents were found then the nodes are disconnected
		} else if ( !aup ) {
			return -1;

		} else if ( !bup ) {
			return 1;
		}

		// Otherwise they're somewhere else in the tree so we need
		// to build up a full list of the parentNodes for comparison
		while ( cur ) {
			ap.unshift( cur );
			cur = cur.parentNode;
		}

		cur = bup;

		while ( cur ) {
			bp.unshift( cur );
			cur = cur.parentNode;
		}

		al = ap.length;
		bl = bp.length;

		// Start walking down the tree looking for a discrepancy
		for ( var i = 0; i < al && i < bl; i++ ) {
			if ( ap[i] !== bp[i] ) {
				return siblingCheck( ap[i], bp[i] );
			}
		}

		// We ended someplace up the tree so do a sibling check
		return i === al ?
			siblingCheck( a, bp[i], -1 ) :
			siblingCheck( ap[i], b, 1 );
	};

	siblingCheck = function( a, b, ret ) {
		if ( a === b ) {
			return ret;
		}

		var cur = a.nextSibling;

		while ( cur ) {
			if ( cur === b ) {
				return -1;
			}

			cur = cur.nextSibling;
		}

		return 1;
	};
}

// Check to see if the browser returns elements by name when
// querying by getElementById (and provide a workaround)
(function(){
	// We're going to inject a fake input element with a specified name
	var form = document.createElement("div"),
		id = "script" + (new Date()).getTime(),
		root = document.documentElement;

	form.innerHTML = "<a name='" + id + "'/>";

	// Inject it into the root element, check its status, and remove it quickly
	root.insertBefore( form, root.firstChild );

	// The workaround has to do additional checks after a getElementById
	// Which slows things down for other browsers (hence the branching)
	if ( document.getElementById( id ) ) {
		Expr.find.ID = function( match, context, isXML ) {
			if ( typeof context.getElementById !== "undefined" && !isXML ) {
				var m = context.getElementById(match[1]);

				return m ?
					m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
						[m] :
						undefined :
					[];
			}
		};

		Expr.filter.ID = function( elem, match ) {
			var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");

			return elem.nodeType === 1 && node && node.nodeValue === match;
		};
	}

	root.removeChild( form );

	// release memory in IE
	root = form = null;
})();

(function(){
	// Check to see if the browser returns only elements
	// when doing getElementsByTagName("*")

	// Create a fake element
	var div = document.createElement("div");
	div.appendChild( document.createComment("") );

	// Make sure no comments are found
	if ( div.getElementsByTagName("*").length > 0 ) {
		Expr.find.TAG = function( match, context ) {
			var results = context.getElementsByTagName( match[1] );

			// Filter out possible comments
			if ( match[1] === "*" ) {
				var tmp = [];

				for ( var i = 0; results[i]; i++ ) {
					if ( results[i].nodeType === 1 ) {
						tmp.push( results[i] );
					}
				}

				results = tmp;
			}

			return results;
		};
	}

	// Check to see if an attribute returns normalized href attributes
	div.innerHTML = "<a href='#'></a>";

	if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
			div.firstChild.getAttribute("href") !== "#" ) {

		Expr.attrHandle.href = function( elem ) {
			return elem.getAttribute( "href", 2 );
		};
	}

	// release memory in IE
	div = null;
})();

if ( document.querySelectorAll ) {
	(function(){
		var oldSizzle = Sizzle,
			div = document.createElement("div"),
			id = "__sizzle__";

		div.innerHTML = "<p class='TEST'></p>";

		// Safari can't handle uppercase or unicode characters when
		// in quirks mode.
		if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
			return;
		}
	
		Sizzle = function( query, context, extra, seed ) {
			context = context || document;

			// Only use querySelectorAll on non-XML documents
			// (ID selectors don't work in non-HTML documents)
			if ( !seed && !Sizzle.isXML(context) ) {
				// See if we find a selector to speed up
				var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query );
				
				if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
					// Speed-up: Sizzle("TAG")
					if ( match[1] ) {
						return makeArray( context.getElementsByTagName( query ), extra );
					
					// Speed-up: Sizzle(".CLASS")
					} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
						return makeArray( context.getElementsByClassName( match[2] ), extra );
					}
				}
				
				if ( context.nodeType === 9 ) {
					// Speed-up: Sizzle("body")
					// The body element only exists once, optimize finding it
					if ( query === "body" && context.body ) {
						return makeArray( [ context.body ], extra );
						
					// Speed-up: Sizzle("#ID")
					} else if ( match && match[3] ) {
						var elem = context.getElementById( match[3] );

						// Check parentNode to catch when Blackberry 4.6 returns
						// nodes that are no longer in the document #6963
						if ( elem && elem.parentNode ) {
							// Handle the case where IE and Opera return items
							// by name instead of ID
							if ( elem.id === match[3] ) {
								return makeArray( [ elem ], extra );
							}
							
						} else {
							return makeArray( [], extra );
						}
					}
					
					try {
						return makeArray( context.querySelectorAll(query), extra );
					} catch(qsaError) {}

				// qSA works strangely on Element-rooted queries
				// We can work around this by specifying an extra ID on the root
				// and working up from there (Thanks to Andrew Dupont for the technique)
				// IE 8 doesn't work on object elements
				} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
					var oldContext = context,
						old = context.getAttribute( "id" ),
						nid = old || id,
						hasParent = context.parentNode,
						relativeHierarchySelector = /^\s*[+~]/.test( query );

					if ( !old ) {
						context.setAttribute( "id", nid );
					} else {
						nid = nid.replace( /'/g, "\\$&" );
					}
					if ( relativeHierarchySelector && hasParent ) {
						context = context.parentNode;
					}

					try {
						if ( !relativeHierarchySelector || hasParent ) {
							return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra );
						}

					} catch(pseudoError) {
					} finally {
						if ( !old ) {
							oldContext.removeAttribute( "id" );
						}
					}
				}
			}
		
			return oldSizzle(query, context, extra, seed);
		};

		for ( var prop in oldSizzle ) {
			Sizzle[ prop ] = oldSizzle[ prop ];
		}

		// release memory in IE
		div = null;
	})();
}

(function(){
	var html = document.documentElement,
		matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;

	if ( matches ) {
		// Check to see if it's possible to do matchesSelector
		// on a disconnected node (IE 9 fails this)
		var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ),
			pseudoWorks = false;

		try {
			// This should fail with an exception
			// Gecko does not error, returns false instead
			matches.call( document.documentElement, "[test!='']:sizzle" );
	
		} catch( pseudoError ) {
			pseudoWorks = true;
		}

		Sizzle.matchesSelector = function( node, expr ) {
			// Make sure that attribute selectors are quoted
			expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");

			if ( !Sizzle.isXML( node ) ) {
				try { 
					if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
						var ret = matches.call( node, expr );

						// IE 9's matchesSelector returns false on disconnected nodes
						if ( ret || !disconnectedMatch ||
								// As well, disconnected nodes are said to be in a document
								// fragment in IE 9, so check for that
								node.document && node.document.nodeType !== 11 ) {
							return ret;
						}
					}
				} catch(e) {}
			}

			return Sizzle(expr, null, null, [node]).length > 0;
		};
	}
})();

(function(){
	var div = document.createElement("div");

	div.innerHTML = "<div class='test e'></div><div class='test'></div>";

	// Opera can't find a second classname (in 9.6)
	// Also, make sure that getElementsByClassName actually exists
	if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
		return;
	}

	// Safari caches class attributes, doesn't catch changes (in 3.2)
	div.lastChild.className = "e";

	if ( div.getElementsByClassName("e").length === 1 ) {
		return;
	}
	
	Expr.order.splice(1, 0, "CLASS");
	Expr.find.CLASS = function( match, context, isXML ) {
		if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
			return context.getElementsByClassName(match[1]);
		}
	};

	// release memory in IE
	div = null;
})();

function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
		var elem = checkSet[i];

		if ( elem ) {
			var match = false;

			elem = elem[dir];

			while ( elem ) {
				if ( elem[ expando ] === doneName ) {
					match = checkSet[elem.sizset];
					break;
				}

				if ( elem.nodeType === 1 && !isXML ){
					elem[ expando ] = doneName;
					elem.sizset = i;
				}

				if ( elem.nodeName.toLowerCase() === cur ) {
					match = elem;
					break;
				}

				elem = elem[dir];
			}

			checkSet[i] = match;
		}
	}
}

function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
		var elem = checkSet[i];

		if ( elem ) {
			var match = false;
			
			elem = elem[dir];

			while ( elem ) {
				if ( elem[ expando ] === doneName ) {
					match = checkSet[elem.sizset];
					break;
				}

				if ( elem.nodeType === 1 ) {
					if ( !isXML ) {
						elem[ expando ] = doneName;
						elem.sizset = i;
					}

					if ( typeof cur !== "string" ) {
						if ( elem === cur ) {
							match = true;
							break;
						}

					} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
						match = elem;
						break;
					}
				}

				elem = elem[dir];
			}

			checkSet[i] = match;
		}
	}
}

if ( document.documentElement.contains ) {
	Sizzle.contains = function( a, b ) {
		return a !== b && (a.contains ? a.contains(b) : true);
	};

} else if ( document.documentElement.compareDocumentPosition ) {
	Sizzle.contains = function( a, b ) {
		return !!(a.compareDocumentPosition(b) & 16);
	};

} else {
	Sizzle.contains = function() {
		return false;
	};
}

Sizzle.isXML = function( elem ) {
	// documentElement is verified for cases where it doesn't yet exist
	// (such as loading iframes in IE - #4833) 
	var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;

	return documentElement ? documentElement.nodeName !== "HTML" : false;
};

var posProcess = function( selector, context, seed ) {
	var match,
		tmpSet = [],
		later = "",
		root = context.nodeType ? [context] : context;

	// Position selectors must be done after the filter
	// And so must :not(positional) so we move all PSEUDOs to the end
	while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
		later += match[0];
		selector = selector.replace( Expr.match.PSEUDO, "" );
	}

	selector = Expr.relative[selector] ? selector + "*" : selector;

	for ( var i = 0, l = root.length; i < l; i++ ) {
		Sizzle( selector, root[i], tmpSet, seed );
	}

	return Sizzle.filter( later, tmpSet );
};

// EXPOSE
// Override sizzle attribute retrieval
Sizzle.attr = jQuery.attr;
Sizzle.selectors.attrMap = {};
jQuery.find = Sizzle;
jQuery.expr = Sizzle.selectors;
jQuery.expr[":"] = jQuery.expr.filters;
jQuery.unique = Sizzle.uniqueSort;
jQuery.text = Sizzle.getText;
jQuery.isXMLDoc = Sizzle.isXML;
jQuery.contains = Sizzle.contains;


})();


var runtil = /Until$/,
	rparentsprev = /^(?:parents|prevUntil|prevAll)/,
	// Note: This RegExp should be improved, or likely pulled from Sizzle
	rmultiselector = /,/,
	isSimple = /^.[^:#\[\.,]*$/,
	slice = Array.prototype.slice,
	POS = jQuery.expr.match.POS,
	// methods guaranteed to produce a unique set when starting from a unique set
	guaranteedUnique = {
		children: true,
		contents: true,
		next: true,
		prev: true
	};

jQuery.fn.extend({
	find: function( selector ) {
		var self = this,
			i, l;

		if ( typeof selector !== "string" ) {
			return jQuery( selector ).filter(function() {
				for ( i = 0, l = self.length; i < l; i++ ) {
					if ( jQuery.contains( self[ i ], this ) ) {
						return true;
					}
				}
			});
		}

		var ret = this.pushStack( "", "find", selector ),
			length, n, r;

		for ( i = 0, l = this.length; i < l; i++ ) {
			length = ret.length;
			jQuery.find( selector, this[i], ret );

			if ( i > 0 ) {
				// Make sure that the results are unique
				for ( n = length; n < ret.length; n++ ) {
					for ( r = 0; r < length; r++ ) {
						if ( ret[r] === ret[n] ) {
							ret.splice(n--, 1);
							break;
						}
					}
				}
			}
		}

		return ret;
	},

	has: function( target ) {
		var targets = jQuery( target );
		return this.filter(function() {
			for ( var i = 0, l = targets.length; i < l; i++ ) {
				if ( jQuery.contains( this, targets[i] ) ) {
					return true;
				}
			}
		});
	},

	not: function( selector ) {
		return this.pushStack( winnow(this, selector, false), "not", selector);
	},

	filter: function( selector ) {
		return this.pushStack( winnow(this, selector, true), "filter", selector );
	},

	is: function( selector ) {
		return !!selector && ( 
			typeof selector === "string" ?
				// If this is a positional selector, check membership in the returned set
				// so $("p:first").is("p:last") won't return true for a doc with two "p".
				POS.test( selector ) ? 
					jQuery( selector, this.context ).index( this[0] ) >= 0 :
					jQuery.filter( selector, this ).length > 0 :
				this.filter( selector ).length > 0 );
	},

	closest: function( selectors, context ) {
		var ret = [], i, l, cur = this[0];
		
		// Array (deprecated as of jQuery 1.7)
		if ( jQuery.isArray( selectors ) ) {
			var level = 1;

			while ( cur && cur.ownerDocument && cur !== context ) {
				for ( i = 0; i < selectors.length; i++ ) {

					if ( jQuery( cur ).is( selectors[ i ] ) ) {
						ret.push({ selector: selectors[ i ], elem: cur, level: level });
					}
				}

				cur = cur.parentNode;
				level++;
			}

			return ret;
		}

		// String
		var pos = POS.test( selectors ) || typeof selectors !== "string" ?
				jQuery( selectors, context || this.context ) :
				0;

		for ( i = 0, l = this.length; i < l; i++ ) {
			cur = this[i];

			while ( cur ) {
				if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
					ret.push( cur );
					break;

				} else {
					cur = cur.parentNode;
					if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {
						break;
					}
				}
			}
		}

		ret = ret.length > 1 ? jQuery.unique( ret ) : ret;

		return this.pushStack( ret, "closest", selectors );
	},

	// Determine the position of an element within
	// the matched set of elements
	index: function( elem ) {

		// No argument, return index in parent
		if ( !elem ) {
			return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;
		}

		// index in selector
		if ( typeof elem === "string" ) {
			return jQuery.inArray( this[0], jQuery( elem ) );
		}

		// Locate the position of the desired element
		return jQuery.inArray(
			// If it receives a jQuery object, the first element is used
			elem.jquery ? elem[0] : elem, this );
	},

	add: function( selector, context ) {
		var set = typeof selector === "string" ?
				jQuery( selector, context ) :
				jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
			all = jQuery.merge( this.get(), set );

		return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
			all :
			jQuery.unique( all ) );
	},

	andSelf: function() {
		return this.add( this.prevObject );
	}
});

// A painfully simple check to see if an element is disconnected
// from a document (should be improved, where feasible).
function isDisconnected( node ) {
	return !node || !node.parentNode || node.parentNode.nodeType === 11;
}

jQuery.each({
	parent: function( elem ) {
		var parent = elem.parentNode;
		return parent && parent.nodeType !== 11 ? parent : null;
	},
	parents: function( elem ) {
		return jQuery.dir( elem, "parentNode" );
	},
	parentsUntil: function( elem, i, until ) {
		return jQuery.dir( elem, "parentNode", until );
	},
	next: function( elem ) {
		return jQuery.nth( elem, 2, "nextSibling" );
	},
	prev: function( elem ) {
		return jQuery.nth( elem, 2, "previousSibling" );
	},
	nextAll: function( elem ) {
		return jQuery.dir( elem, "nextSibling" );
	},
	prevAll: function( elem ) {
		return jQuery.dir( elem, "previousSibling" );
	},
	nextUntil: function( elem, i, until ) {
		return jQuery.dir( elem, "nextSibling", until );
	},
	prevUntil: function( elem, i, until ) {
		return jQuery.dir( elem, "previousSibling", until );
	},
	siblings: function( elem ) {
		return jQuery.sibling( elem.parentNode.firstChild, elem );
	},
	children: function( elem ) {
		return jQuery.sibling( elem.firstChild );
	},
	contents: function( elem ) {
		return jQuery.nodeName( elem, "iframe" ) ?
			elem.contentDocument || elem.contentWindow.document :
			jQuery.makeArray( elem.childNodes );
	}
}, function( name, fn ) {
	jQuery.fn[ name ] = function( until, selector ) {
		var ret = jQuery.map( this, fn, until );

		if ( !runtil.test( name ) ) {
			selector = until;
		}

		if ( selector && typeof selector === "string" ) {
			ret = jQuery.filter( selector, ret );
		}

		ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;

		if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
			ret = ret.reverse();
		}

		return this.pushStack( ret, name, slice.call( arguments ).join(",") );
	};
});

jQuery.extend({
	filter: function( expr, elems, not ) {
		if ( not ) {
			expr = ":not(" + expr + ")";
		}

		return elems.length === 1 ?
			jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
			jQuery.find.matches(expr, elems);
	},

	dir: function( elem, dir, until ) {
		var matched = [],
			cur = elem[ dir ];

		while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
			if ( cur.nodeType === 1 ) {
				matched.push( cur );
			}
			cur = cur[dir];
		}
		return matched;
	},

	nth: function( cur, result, dir, elem ) {
		result = result || 1;
		var num = 0;

		for ( ; cur; cur = cur[dir] ) {
			if ( cur.nodeType === 1 && ++num === result ) {
				break;
			}
		}

		return cur;
	},

	sibling: function( n, elem ) {
		var r = [];

		for ( ; n; n = n.nextSibling ) {
			if ( n.nodeType === 1 && n !== elem ) {
				r.push( n );
			}
		}

		return r;
	}
});

// Implement the identical functionality for filter and not
function winnow( elements, qualifier, keep ) {

	// Can't pass null or undefined to indexOf in Firefox 4
	// Set to 0 to skip string check
	qualifier = qualifier || 0;

	if ( jQuery.isFunction( qualifier ) ) {
		return jQuery.grep(elements, function( elem, i ) {
			var retVal = !!qualifier.call( elem, i, elem );
			return retVal === keep;
		});

	} else if ( qualifier.nodeType ) {
		return jQuery.grep(elements, function( elem, i ) {
			return ( elem === qualifier ) === keep;
		});

	} else if ( typeof qualifier === "string" ) {
		var filtered = jQuery.grep(elements, function( elem ) {
			return elem.nodeType === 1;
		});

		if ( isSimple.test( qualifier ) ) {
			return jQuery.filter(qualifier, filtered, !keep);
		} else {
			qualifier = jQuery.filter( qualifier, filtered );
		}
	}

	return jQuery.grep(elements, function( elem, i ) {
		return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
	});
}




function createSafeFragment( document ) {
	var list = nodeNames.split( "|" ),
	safeFrag = document.createDocumentFragment();

	if ( safeFrag.createElement ) {
		while ( list.length ) {
			safeFrag.createElement(
				list.pop()
			);
		}
	}
	return safeFrag;
}

var nodeNames = "abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|" +
		"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
	rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
	rleadingWhitespace = /^\s+/,
	rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
	rtagName = /<([\w:]+)/,
	rtbody = /<tbody/i,
	rhtml = /<|&#?\w+;/,
	rnoInnerhtml = /<(?:script|style)/i,
	rnocache = /<(?:script|object|embed|option|style)/i,
	rnoshimcache = new RegExp("<(?:" + nodeNames + ")", "i"),
	// checked="checked" or checked
	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
	rscriptType = /\/(java|ecma)script/i,
	rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)/,
	wrapMap = {
		option: [ 1, "<select multiple='multiple'>", "</select>" ],
		legend: [ 1, "<fieldset>", "</fieldset>" ],
		thead: [ 1, "<table>", "</table>" ],
		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
		col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
		area: [ 1, "<map>", "</map>" ],
		_default: [ 0, "", "" ]
	},
	safeFragment = createSafeFragment( document );

wrapMap.optgroup = wrapMap.option;
wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
wrapMap.th = wrapMap.td;

// IE can't serialize <link> and <script> tags normally
if ( !jQuery.support.htmlSerialize ) {
	wrapMap._default = [ 1, "div<div>", "</div>" ];
}

jQuery.fn.extend({
	text: function( text ) {
		if ( jQuery.isFunction(text) ) {
			return this.each(function(i) {
				var self = jQuery( this );

				self.text( text.call(this, i, self.text()) );
			});
		}

		if ( typeof text !== "object" && text !== undefined ) {
			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
		}

		return jQuery.text( this );
	},

	wrapAll: function( html ) {
		if ( jQuery.isFunction( html ) ) {
			return this.each(function(i) {
				jQuery(this).wrapAll( html.call(this, i) );
			});
		}

		if ( this[0] ) {
			// The elements to wrap the target around
			var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);

			if ( this[0].parentNode ) {
				wrap.insertBefore( this[0] );
			}

			wrap.map(function() {
				var elem = this;

				while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
					elem = elem.firstChild;
				}

				return elem;
			}).append( this );
		}

		return this;
	},

	wrapInner: function( html ) {
		if ( jQuery.isFunction( html ) ) {
			return this.each(function(i) {
				jQuery(this).wrapInner( html.call(this, i) );
			});
		}

		return this.each(function() {
			var self = jQuery( this ),
				contents = self.contents();

			if ( contents.length ) {
				contents.wrapAll( html );

			} else {
				self.append( html );
			}
		});
	},

	wrap: function( html ) {
		var isFunction = jQuery.isFunction( html );

		return this.each(function(i) {
			jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
		});
	},

	unwrap: function() {
		return this.parent().each(function() {
			if ( !jQuery.nodeName( this, "body" ) ) {
				jQuery( this ).replaceWith( this.childNodes );
			}
		}).end();
	},

	append: function() {
		return this.domManip(arguments, true, function( elem ) {
			if ( this.nodeType === 1 ) {
				this.appendChild( elem );
			}
		});
	},

	prepend: function() {
		return this.domManip(arguments, true, function( elem ) {
			if ( this.nodeType === 1 ) {
				this.insertBefore( elem, this.firstChild );
			}
		});
	},

	before: function() {
		if ( this[0] && this[0].parentNode ) {
			return this.domManip(arguments, false, function( elem ) {
				this.parentNode.insertBefore( elem, this );
			});
		} else if ( arguments.length ) {
			var set = jQuery.clean( arguments );
			set.push.apply( set, this.toArray() );
			return this.pushStack( set, "before", arguments );
		}
	},

	after: function() {
		if ( this[0] && this[0].parentNode ) {
			return this.domManip(arguments, false, function( elem ) {
				this.parentNode.insertBefore( elem, this.nextSibling );
			});
		} else if ( arguments.length ) {
			var set = this.pushStack( this, "after", arguments );
			set.push.apply( set, jQuery.clean(arguments) );
			return set;
		}
	},

	// keepData is for internal use only--do not document
	remove: function( selector, keepData ) {
		for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
			if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
				if ( !keepData && elem.nodeType === 1 ) {
					jQuery.cleanData( elem.getElementsByTagName("*") );
					jQuery.cleanData( [ elem ] );
				}

				if ( elem.parentNode ) {
					elem.parentNode.removeChild( elem );
				}
			}
		}

		return this;
	},

	empty: function() {
		for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
			// Remove element nodes and prevent memory leaks
			if ( elem.nodeType === 1 ) {
				jQuery.cleanData( elem.getElementsByTagName("*") );
			}

			// Remove any remaining nodes
			while ( elem.firstChild ) {
				elem.removeChild( elem.firstChild );
			}
		}

		return this;
	},

	clone: function( dataAndEvents, deepDataAndEvents ) {
		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;

		return this.map( function () {
			return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
		});
	},

	html: function( value ) {
		if ( value === undefined ) {
			return this[0] && this[0].nodeType === 1 ?
				this[0].innerHTML.replace(rinlinejQuery, "") :
				null;

		// See if we can take a shortcut and just use innerHTML
		} else if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
			(jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
			!wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {

			value = value.replace(rxhtmlTag, "<$1></$2>");

			try {
				for ( var i = 0, l = this.length; i < l; i++ ) {
					// Remove element nodes and prevent memory leaks
					if ( this[i].nodeType === 1 ) {
						jQuery.cleanData( this[i].getElementsByTagName("*") );
						this[i].innerHTML = value;
					}
				}

			// If using innerHTML throws an exception, use the fallback method
			} catch(e) {
				this.empty().append( value );
			}

		} else if ( jQuery.isFunction( value ) ) {
			this.each(function(i){
				var self = jQuery( this );

				self.html( value.call(this, i, self.html()) );
			});

		} else {
			this.empty().append( value );
		}

		return this;
	},

	replaceWith: function( value ) {
		if ( this[0] && this[0].parentNode ) {
			// Make sure that the elements are removed from the DOM before they are inserted
			// this can help fix replacing a parent with child elements
			if ( jQuery.isFunction( value ) ) {
				return this.each(function(i) {
					var self = jQuery(this), old = self.html();
					self.replaceWith( value.call( this, i, old ) );
				});
			}

			if ( typeof value !== "string" ) {
				value = jQuery( value ).detach();
			}

			return this.each(function() {
				var next = this.nextSibling,
					parent = this.parentNode;

				jQuery( this ).remove();

				if ( next ) {
					jQuery(next).before( value );
				} else {
					jQuery(parent).append( value );
				}
			});
		} else {
			return this.length ?
				this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) :
				this;
		}
	},

	detach: function( selector ) {
		return this.remove( selector, true );
	},

	domManip: function( args, table, callback ) {
		var results, first, fragment, parent,
			value = args[0],
			scripts = [];

		// We can't cloneNode fragments that contain checked, in WebKit
		if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
			return this.each(function() {
				jQuery(this).domManip( args, table, callback, true );
			});
		}

		if ( jQuery.isFunction(value) ) {
			return this.each(function(i) {
				var self = jQuery(this);
				args[0] = value.call(this, i, table ? self.html() : undefined);
				self.domManip( args, table, callback );
			});
		}

		if ( this[0] ) {
			parent = value && value.parentNode;

			// If we're in a fragment, just use that instead of building a new one
			if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
				results = { fragment: parent };

			} else {
				results = jQuery.buildFragment( args, this, scripts );
			}

			fragment = results.fragment;

			if ( fragment.childNodes.length === 1 ) {
				first = fragment = fragment.firstChild;
			} else {
				first = fragment.firstChild;
			}

			if ( first ) {
				table = table && jQuery.nodeName( first, "tr" );

				for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {
					callback.call(
						table ?
							root(this[i], first) :
							this[i],
						// Make sure that we do not leak memory by inadvertently discarding
						// the original fragment (which might have attached data) instead of
						// using it; in addition, use the original fragment object for the last
						// item instead of first because it can end up being emptied incorrectly
						// in certain situations (Bug #8070).
						// Fragments from the fragment cache must always be cloned and never used
						// in place.
						results.cacheable || ( l > 1 && i < lastIndex ) ?
							jQuery.clone( fragment, true, true ) :
							fragment
					);
				}
			}

			if ( scripts.length ) {
				jQuery.each( scripts, evalScript );
			}
		}

		return this;
	}
});

function root( elem, cur ) {
	return jQuery.nodeName(elem, "table") ?
		(elem.getElementsByTagName("tbody")[0] ||
		elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
		elem;
}

function cloneCopyEvent( src, dest ) {

	if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
		return;
	}

	var type, i, l,
		oldData = jQuery._data( src ),
		curData = jQuery._data( dest, oldData ),
		events = oldData.events;

	if ( events ) {
		delete curData.handle;
		curData.events = {};

		for ( type in events ) {
			for ( i = 0, l = events[ type ].length; i < l; i++ ) {
				jQuery.event.add( dest, type + ( events[ type ][ i ].namespace ? "." : "" ) + events[ type ][ i ].namespace, events[ type ][ i ], events[ type ][ i ].data );
			}
		}
	}

	// make the cloned public data object a copy from the original
	if ( curData.data ) {
		curData.data = jQuery.extend( {}, curData.data );
	}
}

function cloneFixAttributes( src, dest ) {
	var nodeName;

	// We do not need to do anything for non-Elements
	if ( dest.nodeType !== 1 ) {
		return;
	}

	// clearAttributes removes the attributes, which we don't want,
	// but also removes the attachEvent events, which we *do* want
	if ( dest.clearAttributes ) {
		dest.clearAttributes();
	}

	// mergeAttributes, in contrast, only merges back on the
	// original attributes, not the events
	if ( dest.mergeAttributes ) {
		dest.mergeAttributes( src );
	}

	nodeName = dest.nodeName.toLowerCase();

	// IE6-8 fail to clone children inside object elements that use
	// the proprietary classid attribute value (rather than the type
	// attribute) to identify the type of content to display
	if ( nodeName === "object" ) {
		dest.outerHTML = src.outerHTML;

	} else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) {
		// IE6-8 fails to persist the checked state of a cloned checkbox
		// or radio button. Worse, IE6-7 fail to give the cloned element
		// a checked appearance if the defaultChecked value isn't also set
		if ( src.checked ) {
			dest.defaultChecked = dest.checked = src.checked;
		}

		// IE6-7 get confused and end up setting the value of a cloned
		// checkbox/radio button to an empty string instead of "on"
		if ( dest.value !== src.value ) {
			dest.value = src.value;
		}

	// IE6-8 fails to return the selected option to the default selected
	// state when cloning options
	} else if ( nodeName === "option" ) {
		dest.selected = src.defaultSelected;

	// IE6-8 fails to set the defaultValue to the correct value when
	// cloning other types of input fields
	} else if ( nodeName === "input" || nodeName === "textarea" ) {
		dest.defaultValue = src.defaultValue;
	}

	// Event data gets referenced instead of copied if the expando
	// gets copied too
	dest.removeAttribute( jQuery.expando );
}

jQuery.buildFragment = function( args, nodes, scripts ) {
	var fragment, cacheable, cacheresults, doc,
	first = args[ 0 ];

	// nodes may contain either an explicit document object,
	// a jQuery collection or context object.
	// If nodes[0] contains a valid object to assign to doc
	if ( nodes && nodes[0] ) {
		doc = nodes[0].ownerDocument || nodes[0];
	}

	// Ensure that an attr object doesn't incorrectly stand in as a document object
	// Chrome and Firefox seem to allow this to occur and will throw exception
	// Fixes #8950
	if ( !doc.createDocumentFragment ) {
		doc = document;
	}

	// Only cache "small" (1/2 KB) HTML strings that are associated with the main document
	// Cloning options loses the selected state, so don't cache them
	// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
	// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
	// Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501
	if ( args.length === 1 && typeof first === "string" && first.length < 512 && doc === document &&
		first.charAt(0) === "<" && !rnocache.test( first ) &&
		(jQuery.support.checkClone || !rchecked.test( first )) &&
		(jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {

		cacheable = true;

		cacheresults = jQuery.fragments[ first ];
		if ( cacheresults && cacheresults !== 1 ) {
			fragment = cacheresults;
		}
	}

	if ( !fragment ) {
		fragment = doc.createDocumentFragment();
		jQuery.clean( args, doc, fragment, scripts );
	}

	if ( cacheable ) {
		jQuery.fragments[ first ] = cacheresults ? fragment : 1;
	}

	return { fragment: fragment, cacheable: cacheable };
};

jQuery.fragments = {};

jQuery.each({
	appendTo: "append",
	prependTo: "prepend",
	insertBefore: "before",
	insertAfter: "after",
	replaceAll: "replaceWith"
}, function( name, original ) {
	jQuery.fn[ name ] = function( selector ) {
		var ret = [],
			insert = jQuery( selector ),
			parent = this.length === 1 && this[0].parentNode;

		if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
			insert[ original ]( this[0] );
			return this;

		} else {
			for ( var i = 0, l = insert.length; i < l; i++ ) {
				var elems = ( i > 0 ? this.clone(true) : this ).get();
				jQuery( insert[i] )[ original ]( elems );
				ret = ret.concat( elems );
			}

			return this.pushStack( ret, name, insert.selector );
		}
	};
});

function getAll( elem ) {
	if ( typeof elem.getElementsByTagName !== "undefined" ) {
		return elem.getElementsByTagName( "*" );

	} else if ( typeof elem.querySelectorAll !== "undefined" ) {
		return elem.querySelectorAll( "*" );

	} else {
		return [];
	}
}

// Used in clean, fixes the defaultChecked property
function fixDefaultChecked( elem ) {
	if ( elem.type === "checkbox" || elem.type === "radio" ) {
		elem.defaultChecked = elem.checked;
	}
}
// Finds all inputs and passes them to fixDefaultChecked
function findInputs( elem ) {
	var nodeName = ( elem.nodeName || "" ).toLowerCase();
	if ( nodeName === "input" ) {
		fixDefaultChecked( elem );
	// Skip scripts, get other children
	} else if ( nodeName !== "script" && typeof elem.getElementsByTagName !== "undefined" ) {
		jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
	}
}

// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js
function shimCloneNode( elem ) {
	var div = document.createElement( "div" );
	safeFragment.appendChild( div );

	div.innerHTML = elem.outerHTML;
	return div.firstChild;
}

jQuery.extend({
	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
		var srcElements,
			destElements,
			i,
			// IE<=8 does not properly clone detached, unknown element nodes
			clone = jQuery.support.html5Clone || !rnoshimcache.test( "<" + elem.nodeName ) ?
				elem.cloneNode( true ) :
				shimCloneNode( elem );

		if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
				(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
			// IE copies events bound via attachEvent when using cloneNode.
			// Calling detachEvent on the clone will also remove the events
			// from the original. In order to get around this, we use some
			// proprietary methods to clear the events. Thanks to MooTools
			// guys for this hotness.

			cloneFixAttributes( elem, clone );

			// Using Sizzle here is crazy slow, so we use getElementsByTagName instead
			srcElements = getAll( elem );
			destElements = getAll( clone );

			// Weird iteration because IE will replace the length property
			// with an element if you are cloning the body and one of the
			// elements on the page has a name or id of "length"
			for ( i = 0; srcElements[i]; ++i ) {
				// Ensure that the destination node is not null; Fixes #9587
				if ( destElements[i] ) {
					cloneFixAttributes( srcElements[i], destElements[i] );
				}
			}
		}

		// Copy the events from the original to the clone
		if ( dataAndEvents ) {
			cloneCopyEvent( elem, clone );

			if ( deepDataAndEvents ) {
				srcElements = getAll( elem );
				destElements = getAll( clone );

				for ( i = 0; srcElements[i]; ++i ) {
					cloneCopyEvent( srcElements[i], destElements[i] );
				}
			}
		}

		srcElements = destElements = null;

		// Return the cloned set
		return clone;
	},

	clean: function( elems, context, fragment, scripts ) {
		var checkScriptType;

		context = context || document;

		// !context.createElement fails in IE with an error but returns typeof 'object'
		if ( typeof context.createElement === "undefined" ) {
			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
		}

		var ret = [], j;

		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
			if ( typeof elem === "number" ) {
				elem += "";
			}

			if ( !elem ) {
				continue;
			}

			// Convert html string into DOM nodes
			if ( typeof elem === "string" ) {
				if ( !rhtml.test( elem ) ) {
					elem = context.createTextNode( elem );
				} else {
					// Fix "XHTML"-style tags in all browsers
					elem = elem.replace(rxhtmlTag, "<$1></$2>");

					// Trim whitespace, otherwise indexOf won't work as expected
					var tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(),
						wrap = wrapMap[ tag ] || wrapMap._default,
						depth = wrap[0],
						div = context.createElement("div");

					// Append wrapper element to unknown element safe doc fragment
					if ( context === document ) {
						// Use the fragment we've already created for this document
						safeFragment.appendChild( div );
					} else {
						// Use a fragment created with the owner document
						createSafeFragment( context ).appendChild( div );
					}

					// Go to html and back, then peel off extra wrappers
					div.innerHTML = wrap[1] + elem + wrap[2];

					// Move to the right depth
					while ( depth-- ) {
						div = div.lastChild;
					}

					// Remove IE's autoinserted <tbody> from table fragments
					if ( !jQuery.support.tbody ) {

						// String was a <table>, *may* have spurious <tbody>
						var hasBody = rtbody.test(elem),
							tbody = tag === "table" && !hasBody ?
								div.firstChild && div.firstChild.childNodes :

								// String was a bare <thead> or <tfoot>
								wrap[1] === "<table>" && !hasBody ?
									div.childNodes :
									[];

						for ( j = tbody.length - 1; j >= 0 ; --j ) {
							if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
								tbody[ j ].parentNode.removeChild( tbody[ j ] );
							}
						}
					}

					// IE completely kills leading whitespace when innerHTML is used
					if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
						div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
					}

					elem = div.childNodes;
				}
			}

			// Resets defaultChecked for any radios and checkboxes
			// about to be appended to the DOM in IE 6/7 (#8060)
			var len;
			if ( !jQuery.support.appendChecked ) {
				if ( elem[0] && typeof (len = elem.length) === "number" ) {
					for ( j = 0; j < len; j++ ) {
						findInputs( elem[j] );
					}
				} else {
					findInputs( elem );
				}
			}

			if ( elem.nodeType ) {
				ret.push( elem );
			} else {
				ret = jQuery.merge( ret, elem );
			}
		}

		if ( fragment ) {
			checkScriptType = function( elem ) {
				return !elem.type || rscriptType.test( elem.type );
			};
			for ( i = 0; ret[i]; i++ ) {
				if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
					scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );

				} else {
					if ( ret[i].nodeType === 1 ) {
						var jsTags = jQuery.grep( ret[i].getElementsByTagName( "script" ), checkScriptType );

						ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
					}
					fragment.appendChild( ret[i] );
				}
			}
		}

		return ret;
	},

	cleanData: function( elems ) {
		var data, id,
			cache = jQuery.cache,
			special = jQuery.event.special,
			deleteExpando = jQuery.support.deleteExpando;

		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
			if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
				continue;
			}

			id = elem[ jQuery.expando ];

			if ( id ) {
				data = cache[ id ];

				if ( data && data.events ) {
					for ( var type in data.events ) {
						if ( special[ type ] ) {
							jQuery.event.remove( elem, type );

						// This is a shortcut to avoid jQuery.event.remove's overhead
						} else {
							jQuery.removeEvent( elem, type, data.handle );
						}
					}

					// Null the DOM reference to avoid IE6/7/8 leak (#7054)
					if ( data.handle ) {
						data.handle.elem = null;
					}
				}

				if ( deleteExpando ) {
					delete elem[ jQuery.expando ];

				} else if ( elem.removeAttribute ) {
					elem.removeAttribute( jQuery.expando );
				}

				delete cache[ id ];
			}
		}
	}
});

function evalScript( i, elem ) {
	if ( elem.src ) {
		jQuery.ajax({
			url: elem.src,
			async: false,
			dataType: "script"
		});
	} else {
		jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "/*$0*/" ) );
	}

	if ( elem.parentNode ) {
		elem.parentNode.removeChild( elem );
	}
}




var ralpha = /alpha\([^)]*\)/i,
	ropacity = /opacity=([^)]*)/,
	// fixed for IE9, see #8346
	rupper = /([A-Z]|^ms)/g,
	rnumpx = /^-?\d+(?:px)?$/i,
	rnum = /^-?\d/,
	rrelNum = /^([\-+])=([\-+.\de]+)/,

	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
	cssWidth = [ "Left", "Right" ],
	cssHeight = [ "Top", "Bottom" ],
	curCSS,

	getComputedStyle,
	currentStyle;

jQuery.fn.css = function( name, value ) {
	// Setting 'undefined' is a no-op
	if ( arguments.length === 2 && value === undefined ) {
		return this;
	}

	return jQuery.access( this, name, value, true, function( elem, name, value ) {
		return value !== undefined ?
			jQuery.style( elem, name, value ) :
			jQuery.css( elem, name );
	});
};

jQuery.extend({
	// Add in style property hooks for overriding the default
	// behavior of getting and setting a style property
	cssHooks: {
		opacity: {
			get: function( elem, computed ) {
				if ( computed ) {
					// We should always get a number back from opacity
					var ret = curCSS( elem, "opacity", "opacity" );
					return ret === "" ? "1" : ret;

				} else {
					return elem.style.opacity;
				}
			}
		}
	},

	// Exclude the following css properties to add px
	cssNumber: {
		"fillOpacity": true,
		"fontWeight": true,
		"lineHeight": true,
		"opacity": true,
		"orphans": true,
		"widows": true,
		"zIndex": true,
		"zoom": true
	},

	// Add in properties whose names you wish to fix before
	// setting or getting the value
	cssProps: {
		// normalize float css property
		"float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
	},

	// Get and set the style property on a DOM Node
	style: function( elem, name, value, extra ) {
		// Don't set styles on text and comment nodes
		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
			return;
		}

		// Make sure that we're working with the right name
		var ret, type, origName = jQuery.camelCase( name ),
			style = elem.style, hooks = jQuery.cssHooks[ origName ];

		name = jQuery.cssProps[ origName ] || origName;

		// Check if we're setting a value
		if ( value !== undefined ) {
			type = typeof value;

			// convert relative number strings (+= or -=) to relative numbers. #7345
			if ( type === "string" && (ret = rrelNum.exec( value )) ) {
				value = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );
				// Fixes bug #9237
				type = "number";
			}

			// Make sure that NaN and null values aren't set. See: #7116
			if ( value == null || type === "number" && isNaN( value ) ) {
				return;
			}

			// If a number was passed in, add 'px' to the (except for certain CSS properties)
			if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
				value += "px";
			}

			// If a hook was provided, use that value, otherwise just set the specified value
			if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
				// Wrapped to prevent IE from throwing errors when 'invalid' values are provided
				// Fixes bug #5509
				try {
					style[ name ] = value;
				} catch(e) {}
			}

		} else {
			// If a hook was provided get the non-computed value from there
			if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
				return ret;
			}

			// Otherwise just get the value from the style object
			return style[ name ];
		}
	},

	css: function( elem, name, extra ) {
		var ret, hooks;

		// Make sure that we're working with the right name
		name = jQuery.camelCase( name );
		hooks = jQuery.cssHooks[ name ];
		name = jQuery.cssProps[ name ] || name;

		// cssFloat needs a special treatment
		if ( name === "cssFloat" ) {
			name = "float";
		}

		// If a hook was provided get the computed value from there
		if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {
			return ret;

		// Otherwise, if a way to get the computed value exists, use that
		} else if ( curCSS ) {
			return curCSS( elem, name );
		}
	},

	// A method for quickly swapping in/out CSS properties to get correct calculations
	swap: function( elem, options, callback ) {
		var old = {};

		// Remember the old values, and insert the new ones
		for ( var name in options ) {
			old[ name ] = elem.style[ name ];
			elem.style[ name ] = options[ name ];
		}

		callback.call( elem );

		// Revert the old values
		for ( name in options ) {
			elem.style[ name ] = old[ name ];
		}
	}
});

// DEPRECATED, Use jQuery.css() instead
jQuery.curCSS = jQuery.css;

jQuery.each(["height", "width"], function( i, name ) {
	jQuery.cssHooks[ name ] = {
		get: function( elem, computed, extra ) {
			var val;

			if ( computed ) {
				if ( elem.offsetWidth !== 0 ) {
					return getWH( elem, name, extra );
				} else {
					jQuery.swap( elem, cssShow, function() {
						val = getWH( elem, name, extra );
					});
				}

				return val;
			}
		},

		set: function( elem, value ) {
			if ( rnumpx.test( value ) ) {
				// ignore negative width and height values #1599
				value = parseFloat( value );

				if ( value >= 0 ) {
					return value + "px";
				}

			} else {
				return value;
			}
		}
	};
});

if ( !jQuery.support.opacity ) {
	jQuery.cssHooks.opacity = {
		get: function( elem, computed ) {
			// IE uses filters for opacity
			return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
				( parseFloat( RegExp.$1 ) / 100 ) + "" :
				computed ? "1" : "";
		},

		set: function( elem, value ) {
			var style = elem.style,
				currentStyle = elem.currentStyle,
				opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
				filter = currentStyle && currentStyle.filter || style.filter || "";

			// IE has trouble with opacity if it does not have layout
			// Force it by setting the zoom level
			style.zoom = 1;

			// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
			if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" ) {

				// Setting style.filter to null, "" & " " still leave "filter:" in the cssText
				// if "filter:" is present at all, clearType is disabled, we want to avoid this
				// style.removeAttribute is IE Only, but so apparently is this code path...
				style.removeAttribute( "filter" );

				// if there there is no filter style applied in a css rule, we are done
				if ( currentStyle && !currentStyle.filter ) {
					return;
				}
			}

			// otherwise, set new filter values
			style.filter = ralpha.test( filter ) ?
				filter.replace( ralpha, opacity ) :
				filter + " " + opacity;
		}
	};
}

jQuery(function() {
	// This hook cannot be added until DOM ready because the support test
	// for it is not run until after DOM ready
	if ( !jQuery.support.reliableMarginRight ) {
		jQuery.cssHooks.marginRight = {
			get: function( elem, computed ) {
				// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
				// Work around by temporarily setting element display to inline-block
				var ret;
				jQuery.swap( elem, { "display": "inline-block" }, function() {
					if ( computed ) {
						ret = curCSS( elem, "margin-right", "marginRight" );
					} else {
						ret = elem.style.marginRight;
					}
				});
				return ret;
			}
		};
	}
});

if ( document.defaultView && document.defaultView.getComputedStyle ) {
	getComputedStyle = function( elem, name ) {
		var ret, defaultView, computedStyle;

		name = name.replace( rupper, "-$1" ).toLowerCase();

		if ( (defaultView = elem.ownerDocument.defaultView) &&
				(computedStyle = defaultView.getComputedStyle( elem, null )) ) {
			ret = computedStyle.getPropertyValue( name );
			if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
				ret = jQuery.style( elem, name );
			}
		}

		return ret;
	};
}

if ( document.documentElement.currentStyle ) {
	currentStyle = function( elem, name ) {
		var left, rsLeft, uncomputed,
			ret = elem.currentStyle && elem.currentStyle[ name ],
			style = elem.style;

		// Avoid setting ret to empty string here
		// so we don't default to auto
		if ( ret === null && style && (uncomputed = style[ name ]) ) {
			ret = uncomputed;
		}

		// From the awesome hack by Dean Edwards
		// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291

		// If we're not dealing with a regular pixel number
		// but a number that has a weird ending, we need to convert it to pixels
		if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {

			// Remember the original values
			left = style.left;
			rsLeft = elem.runtimeStyle && elem.runtimeStyle.left;

			// Put in the new values to get a computed value out
			if ( rsLeft ) {
				elem.runtimeStyle.left = elem.currentStyle.left;
			}
			style.left = name === "fontSize" ? "1em" : ( ret || 0 );
			ret = style.pixelLeft + "px";

			// Revert the changed values
			style.left = left;
			if ( rsLeft ) {
				elem.runtimeStyle.left = rsLeft;
			}
		}

		return ret === "" ? "auto" : ret;
	};
}

curCSS = getComputedStyle || currentStyle;

function getWH( elem, name, extra ) {

	// Start with offset property
	var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
		which = name === "width" ? cssWidth : cssHeight,
		i = 0,
		len = which.length;

	if ( val > 0 ) {
		if ( extra !== "border" ) {
			for ( ; i < len; i++ ) {
				if ( !extra ) {
					val -= parseFloat( jQuery.css( elem, "padding" + which[ i ] ) ) || 0;
				}
				if ( extra === "margin" ) {
					val += parseFloat( jQuery.css( elem, extra + which[ i ] ) ) || 0;
				} else {
					val -= parseFloat( jQuery.css( elem, "border" + which[ i ] + "Width" ) ) || 0;
				}
			}
		}

		return val + "px";
	}

	// Fall back to computed then uncomputed css if necessary
	val = curCSS( elem, name, name );
	if ( val < 0 || val == null ) {
		val = elem.style[ name ] || 0;
	}
	// Normalize "", auto, and prepare for extra
	val = parseFloat( val ) || 0;

	// Add padding, border, margin
	if ( extra ) {
		for ( ; i < len; i++ ) {
			val += parseFloat( jQuery.css( elem, "padding" + which[ i ] ) ) || 0;
			if ( extra !== "padding" ) {
				val += parseFloat( jQuery.css( elem, "border" + which[ i ] + "Width" ) ) || 0;
			}
			if ( extra === "margin" ) {
				val += parseFloat( jQuery.css( elem, extra + which[ i ] ) ) || 0;
			}
		}
	}

	return val + "px";
}

if ( jQuery.expr && jQuery.expr.filters ) {
	jQuery.expr.filters.hidden = function( elem ) {
		var width = elem.offsetWidth,
			height = elem.offsetHeight;

		return ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
	};

	jQuery.expr.filters.visible = function( elem ) {
		return !jQuery.expr.filters.hidden( elem );
	};
}




var r20 = /%20/g,
	rbracket = /\[\]$/,
	rCRLF = /\r?\n/g,
	rhash = /#.*$/,
	rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
	rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
	// #7653, #8125, #8152: local protocol detection
	rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,
	rnoContent = /^(?:GET|HEAD)$/,
	rprotocol = /^\/\//,
	rquery = /\?/,
	rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
	rselectTextarea = /^(?:select|textarea)/i,
	rspacesAjax = /\s+/,
	rts = /([?&])_=[^&]*/,
	rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,

	// Keep a copy of the old load method
	_load = jQuery.fn.load,

	/* Prefilters
	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
	 * 2) These are called:
	 *    - BEFORE asking for a transport
	 *    - AFTER param serialization (s.data is a string if s.processData is true)
	 * 3) key is the dataType
	 * 4) the catchall symbol "*" can be used
	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
	 */
	prefilters = {},

	/* Transports bindings
	 * 1) key is the dataType
	 * 2) the catchall symbol "*" can be used
	 * 3) selection will start with transport dataType and THEN go to "*" if needed
	 */
	transports = {},

	// Document location
	ajaxLocation,

	// Document location segments
	ajaxLocParts,

	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
	allTypes = ["*/"] + ["*"];

// #8138, IE may throw an exception when accessing
// a field from window.location if document.domain has been set
try {
	ajaxLocation = location.href;
} catch( e ) {
	// Use the href attribute of an A element
	// since IE will modify it given document.location
	ajaxLocation = document.createElement( "a" );
	ajaxLocation.href = "";
	ajaxLocation = ajaxLocation.href;
}

// Segment location into parts
ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];

// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
function addToPrefiltersOrTransports( structure ) {

	// dataTypeExpression is optional and defaults to "*"
	return function( dataTypeExpression, func ) {

		if ( typeof dataTypeExpression !== "string" ) {
			func = dataTypeExpression;
			dataTypeExpression = "*";
		}

		if ( jQuery.isFunction( func ) ) {
			var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),
				i = 0,
				length = dataTypes.length,
				dataType,
				list,
				placeBefore;

			// For each dataType in the dataTypeExpression
			for ( ; i < length; i++ ) {
				dataType = dataTypes[ i ];
				// We control if we're asked to add before
				// any existing element
				placeBefore = /^\+/.test( dataType );
				if ( placeBefore ) {
					dataType = dataType.substr( 1 ) || "*";
				}
				list = structure[ dataType ] = structure[ dataType ] || [];
				// then we add to the structure accordingly
				list[ placeBefore ? "unshift" : "push" ]( func );
			}
		}
	};
}

// Base inspection function for prefilters and transports
function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,
		dataType /* internal */, inspected /* internal */ ) {

	dataType = dataType || options.dataTypes[ 0 ];
	inspected = inspected || {};

	inspected[ dataType ] = true;

	var list = structure[ dataType ],
		i = 0,
		length = list ? list.length : 0,
		executeOnly = ( structure === prefilters ),
		selection;

	for ( ; i < length && ( executeOnly || !selection ); i++ ) {
		selection = list[ i ]( options, originalOptions, jqXHR );
		// If we got redirected to another dataType
		// we try there if executing only and not done already
		if ( typeof selection === "string" ) {
			if ( !executeOnly || inspected[ selection ] ) {
				selection = undefined;
			} else {
				options.dataTypes.unshift( selection );
				selection = inspectPrefiltersOrTransports(
						structure, options, originalOptions, jqXHR, selection, inspected );
			}
		}
	}
	// If we're only executing or nothing was selected
	// we try the catchall dataType if not done already
	if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) {
		selection = inspectPrefiltersOrTransports(
				structure, options, originalOptions, jqXHR, "*", inspected );
	}
	// unnecessary when only executing (prefilters)
	// but it'll be ignored by the caller in that case
	return selection;
}

// A special extend for ajax options
// that takes "flat" options (not to be deep extended)
// Fixes #9887
function ajaxExtend( target, src ) {
	var key, deep,
		flatOptions = jQuery.ajaxSettings.flatOptions || {};
	for ( key in src ) {
		if ( src[ key ] !== undefined ) {
			( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
		}
	}
	if ( deep ) {
		jQuery.extend( true, target, deep );
	}
}

jQuery.fn.extend({
	load: function( url, params, callback ) {
		if ( typeof url !== "string" && _load ) {
			return _load.apply( this, arguments );

		// Don't do a request if no elements are being requested
		} else if ( !this.length ) {
			return this;
		}

		var off = url.indexOf( " " );
		if ( off >= 0 ) {
			var selector = url.slice( off, url.length );
			url = url.slice( 0, off );
		}

		// Default to a GET request
		var type = "GET";

		// If the second parameter was provided
		if ( params ) {
			// If it's a function
			if ( jQuery.isFunction( params ) ) {
				// We assume that it's the callback
				callback = params;
				params = undefined;

			// Otherwise, build a param string
			} else if ( typeof params === "object" ) {
				params = jQuery.param( params, jQuery.ajaxSettings.traditional );
				type = "POST";
			}
		}

		var self = this;

		// Request the remote document
		jQuery.ajax({
			url: url,
			type: type,
			dataType: "html",
			data: params,
			// Complete callback (responseText is used internally)
			complete: function( jqXHR, status, responseText ) {
				// Store the response as specified by the jqXHR object
				responseText = jqXHR.responseText;
				// If successful, inject the HTML into all the matched elements
				if ( jqXHR.isResolved() ) {
					// #4825: Get the actual response in case
					// a dataFilter is present in ajaxSettings
					jqXHR.done(function( r ) {
						responseText = r;
					});
					// See if a selector was specified
					self.html( selector ?
						// Create a dummy div to hold the results
						jQuery("<div>")
							// inject the contents of the document in, removing the scripts
							// to avoid any 'Permission Denied' errors in IE
							.append(responseText.replace(rscript, ""))

							// Locate the specified elements
							.find(selector) :

						// If not, just inject the full result
						responseText );
				}

				if ( callback ) {
					self.each( callback, [ responseText, status, jqXHR ] );
				}
			}
		});

		return this;
	},

	serialize: function() {
		return jQuery.param( this.serializeArray() );
	},

	serializeArray: function() {
		return this.map(function(){
			return this.elements ? jQuery.makeArray( this.elements ) : this;
		})
		.filter(function(){
			return this.name && !this.disabled &&
				( this.checked || rselectTextarea.test( this.nodeName ) ||
					rinput.test( this.type ) );
		})
		.map(function( i, elem ){
			var val = jQuery( this ).val();

			return val == null ?
				null :
				jQuery.isArray( val ) ?
					jQuery.map( val, function( val, i ){
						return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
					}) :
					{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
		}).get();
	}
});

// Attach a bunch of functions for handling common AJAX events
jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){
	jQuery.fn[ o ] = function( f ){
		return this.on( o, f );
	};
});

jQuery.each( [ "get", "post" ], function( i, method ) {
	jQuery[ method ] = function( url, data, callback, type ) {
		// shift arguments if data argument was omitted
		if ( jQuery.isFunction( data ) ) {
			type = type || callback;
			callback = data;
			data = undefined;
		}

		return jQuery.ajax({
			type: method,
			url: url,
			data: data,
			success: callback,
			dataType: type
		});
	};
});

jQuery.extend({

	getScript: function( url, callback ) {
		return jQuery.get( url, undefined, callback, "script" );
	},

	getJSON: function( url, data, callback ) {
		return jQuery.get( url, data, callback, "json" );
	},

	// Creates a full fledged settings object into target
	// with both ajaxSettings and settings fields.
	// If target is omitted, writes into ajaxSettings.
	ajaxSetup: function( target, settings ) {
		if ( settings ) {
			// Building a settings object
			ajaxExtend( target, jQuery.ajaxSettings );
		} else {
			// Extending ajaxSettings
			settings = target;
			target = jQuery.ajaxSettings;
		}
		ajaxExtend( target, settings );
		return target;
	},

	ajaxSettings: {
		url: ajaxLocation,
		isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
		global: true,
		type: "GET",
		contentType: "application/x-www-form-urlencoded",
		processData: true,
		async: true,
		/*
		timeout: 0,
		data: null,
		dataType: null,
		username: null,
		password: null,
		cache: null,
		traditional: false,
		headers: {},
		*/

		accepts: {
			xml: "application/xml, text/xml",
			html: "text/html",
			text: "text/plain",
			json: "application/json, text/javascript",
			"*": allTypes
		},

		contents: {
			xml: /xml/,
			html: /html/,
			json: /json/
		},

		responseFields: {
			xml: "responseXML",
			text: "responseText"
		},

		// List of data converters
		// 1) key format is "source_type destination_type" (a single space in-between)
		// 2) the catchall symbol "*" can be used for source_type
		converters: {

			// Convert anything to text
			"* text": window.String,

			// Text to html (true = no transformation)
			"text html": true,

			// Evaluate text as a json expression
			"text json": jQuery.parseJSON,

			// Parse text as xml
			"text xml": jQuery.parseXML
		},

		// For options that shouldn't be deep extended:
		// you can add your own custom options here if
		// and when you create one that shouldn't be
		// deep extended (see ajaxExtend)
		flatOptions: {
			context: true,
			url: true
		}
	},

	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
	ajaxTransport: addToPrefiltersOrTransports( transports ),

	// Main method
	ajax: function( url, options ) {

		// If url is an object, simulate pre-1.5 signature
		if ( typeof url === "object" ) {
			options = url;
			url = undefined;
		}

		// Force options to be an object
		options = options || {};

		var // Create the final options object
			s = jQuery.ajaxSetup( {}, options ),
			// Callbacks context
			callbackContext = s.context || s,
			// Context for global events
			// It's the callbackContext if one was provided in the options
			// and if it's a DOM node or a jQuery collection
			globalEventContext = callbackContext !== s &&
				( callbackContext.nodeType || callbackContext instanceof jQuery ) ?
						jQuery( callbackContext ) : jQuery.event,
			// Deferreds
			deferred = jQuery.Deferred(),
			completeDeferred = jQuery.Callbacks( "once memory" ),
			// Status-dependent callbacks
			statusCode = s.statusCode || {},
			// ifModified key
			ifModifiedKey,
			// Headers (they are sent all at once)
			requestHeaders = {},
			requestHeadersNames = {},
			// Response headers
			responseHeadersString,
			responseHeaders,
			// transport
			transport,
			// timeout handle
			timeoutTimer,
			// Cross-domain detection vars
			parts,
			// The jqXHR state
			state = 0,
			// To know if global events are to be dispatched
			fireGlobals,
			// Loop variable
			i,
			// Fake xhr
			jqXHR = {

				readyState: 0,

				// Caches the header
				setRequestHeader: function( name, value ) {
					if ( !state ) {
						var lname = name.toLowerCase();
						name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
						requestHeaders[ name ] = value;
					}
					return this;
				},

				// Raw string
				getAllResponseHeaders: function() {
					return state === 2 ? responseHeadersString : null;
				},

				// Builds headers hashtable if needed
				getResponseHeader: function( key ) {
					var match;
					if ( state === 2 ) {
						if ( !responseHeaders ) {
							responseHeaders = {};
							while( ( match = rheaders.exec( responseHeadersString ) ) ) {
								responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
							}
						}
						match = responseHeaders[ key.toLowerCase() ];
					}
					return match === undefined ? null : match;
				},

				// Overrides response content-type header
				overrideMimeType: function( type ) {
					if ( !state ) {
						s.mimeType = type;
					}
					return this;
				},

				// Cancel the request
				abort: function( statusText ) {
					statusText = statusText || "abort";
					if ( transport ) {
						transport.abort( statusText );
					}
					done( 0, statusText );
					return this;
				}
			};

		// Callback for when everything is done
		// It is defined here because jslint complains if it is declared
		// at the end of the function (which would be more logical and readable)
		function done( status, nativeStatusText, responses, headers ) {

			// Called once
			if ( state === 2 ) {
				return;
			}

			// State is "done" now
			state = 2;

			// Clear timeout if it exists
			if ( timeoutTimer ) {
				clearTimeout( timeoutTimer );
			}

			// Dereference transport for early garbage collection
			// (no matter how long the jqXHR object will be used)
			transport = undefined;

			// Cache response headers
			responseHeadersString = headers || "";

			// Set readyState
			jqXHR.readyState = status > 0 ? 4 : 0;

			var isSuccess,
				success,
				error,
				statusText = nativeStatusText,
				response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,
				lastModified,
				etag;

			// If successful, handle type chaining
			if ( status >= 200 && status < 300 || status === 304 ) {

				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
				if ( s.ifModified ) {

					if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) {
						jQuery.lastModified[ ifModifiedKey ] = lastModified;
					}
					if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) {
						jQuery.etag[ ifModifiedKey ] = etag;
					}
				}

				// If not modified
				if ( status === 304 ) {

					statusText = "notmodified";
					isSuccess = true;

				// If we have data
				} else {

					try {
						success = ajaxConvert( s, response );
						statusText = "success";
						isSuccess = true;
					} catch(e) {
						// We have a parsererror
						statusText = "parsererror";
						error = e;
					}
				}
			} else {
				// We extract error from statusText
				// then normalize statusText and status for non-aborts
				error = statusText;
				if ( !statusText || status ) {
					statusText = "error";
					if ( status < 0 ) {
						status = 0;
					}
				}
			}

			// Set data for the fake xhr object
			jqXHR.status = status;
			jqXHR.statusText = "" + ( nativeStatusText || statusText );

			// Success/Error
			if ( isSuccess ) {
				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
			} else {
				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
			}

			// Status-dependent callbacks
			jqXHR.statusCode( statusCode );
			statusCode = undefined;

			if ( fireGlobals ) {
				globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
						[ jqXHR, s, isSuccess ? success : error ] );
			}

			// Complete
			completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );

			if ( fireGlobals ) {
				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
				// Handle the global AJAX counter
				if ( !( --jQuery.active ) ) {
					jQuery.event.trigger( "ajaxStop" );
				}
			}
		}

		// Attach deferreds
		deferred.promise( jqXHR );
		jqXHR.success = jqXHR.done;
		jqXHR.error = jqXHR.fail;
		jqXHR.complete = completeDeferred.add;

		// Status-dependent callbacks
		jqXHR.statusCode = function( map ) {
			if ( map ) {
				var tmp;
				if ( state < 2 ) {
					for ( tmp in map ) {
						statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
					}
				} else {
					tmp = map[ jqXHR.status ];
					jqXHR.then( tmp, tmp );
				}
			}
			return this;
		};

		// Remove hash character (#7531: and string promotion)
		// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
		// We also use the url parameter if available
		s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );

		// Extract dataTypes list
		s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax );

		// Determine if a cross-domain request is in order
		if ( s.crossDomain == null ) {
			parts = rurl.exec( s.url.toLowerCase() );
			s.crossDomain = !!( parts &&
				( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||
					( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
						( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
			);
		}

		// Convert data if not already a string
		if ( s.data && s.processData && typeof s.data !== "string" ) {
			s.data = jQuery.param( s.data, s.traditional );
		}

		// Apply prefilters
		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );

		// If request was aborted inside a prefiler, stop there
		if ( state === 2 ) {
			return false;
		}

		// We can fire global events as of now if asked to
		fireGlobals = s.global;

		// Uppercase the type
		s.type = s.type.toUpperCase();

		// Determine if request has content
		s.hasContent = !rnoContent.test( s.type );

		// Watch for a new set of requests
		if ( fireGlobals && jQuery.active++ === 0 ) {
			jQuery.event.trigger( "ajaxStart" );
		}

		// More options handling for requests with no content
		if ( !s.hasContent ) {

			// If data is available, append data to url
			if ( s.data ) {
				s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
				// #9682: remove data so that it's not used in an eventual retry
				delete s.data;
			}

			// Get ifModifiedKey before adding the anti-cache parameter
			ifModifiedKey = s.url;

			// Add anti-cache in url if needed
			if ( s.cache === false ) {

				var ts = jQuery.now(),
					// try replacing _= if it is there
					ret = s.url.replace( rts, "$1_=" + ts );

				// if nothing was replaced, add timestamp to the end
				s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );
			}
		}

		// Set the correct header, if data is being sent
		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
			jqXHR.setRequestHeader( "Content-Type", s.contentType );
		}

		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
		if ( s.ifModified ) {
			ifModifiedKey = ifModifiedKey || s.url;
			if ( jQuery.lastModified[ ifModifiedKey ] ) {
				jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] );
			}
			if ( jQuery.etag[ ifModifiedKey ] ) {
				jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] );
			}
		}

		// Set the Accepts header for the server, depending on the dataType
		jqXHR.setRequestHeader(
			"Accept",
			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
				s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
				s.accepts[ "*" ]
		);

		// Check for headers option
		for ( i in s.headers ) {
			jqXHR.setRequestHeader( i, s.headers[ i ] );
		}

		// Allow custom headers/mimetypes and early abort
		if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
				// Abort if not done already
				jqXHR.abort();
				return false;

		}

		// Install callbacks on deferreds
		for ( i in { success: 1, error: 1, complete: 1 } ) {
			jqXHR[ i ]( s[ i ] );
		}

		// Get transport
		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );

		// If no transport, we auto-abort
		if ( !transport ) {
			done( -1, "No Transport" );
		} else {
			jqXHR.readyState = 1;
			// Send global event
			if ( fireGlobals ) {
				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
			}
			// Timeout
			if ( s.async && s.timeout > 0 ) {
				timeoutTimer = setTimeout( function(){
					jqXHR.abort( "timeout" );
				}, s.timeout );
			}

			try {
				state = 1;
				transport.send( requestHeaders, done );
			} catch (e) {
				// Propagate exception as error if not done
				if ( state < 2 ) {
					done( -1, e );
				// Simply rethrow otherwise
				} else {
					throw e;
				}
			}
		}

		return jqXHR;
	},

	// Serialize an array of form elements or a set of
	// key/values into a query string
	param: function( a, traditional ) {
		var s = [],
			add = function( key, value ) {
				// If value is a function, invoke it and return its value
				value = jQuery.isFunction( value ) ? value() : value;
				s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
			};

		// Set traditional to true for jQuery <= 1.3.2 behavior.
		if ( traditional === undefined ) {
			traditional = jQuery.ajaxSettings.traditional;
		}

		// If an array was passed in, assume that it is an array of form elements.
		if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
			// Serialize the form elements
			jQuery.each( a, function() {
				add( this.name, this.value );
			});

		} else {
			// If traditional, encode the "old" way (the way 1.3.2 or older
			// did it), otherwise encode params recursively.
			for ( var prefix in a ) {
				buildParams( prefix, a[ prefix ], traditional, add );
			}
		}

		// Return the resulting serialization
		return s.join( "&" ).replace( r20, "+" );
	}
});

function buildParams( prefix, obj, traditional, add ) {
	if ( jQuery.isArray( obj ) ) {
		// Serialize array item.
		jQuery.each( obj, function( i, v ) {
			if ( traditional || rbracket.test( prefix ) ) {
				// Treat each array item as a scalar.
				add( prefix, v );

			} else {
				// If array item is non-scalar (array or object), encode its
				// numeric index to resolve deserialization ambiguity issues.
				// Note that rack (as of 1.0.0) can't currently deserialize
				// nested arrays properly, and attempting to do so may cause
				// a server error. Possible fixes are to modify rack's
				// deserialization algorithm or to provide an option or flag
				// to force array serialization to be shallow.
				buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add );
			}
		});

	} else if ( !traditional && obj != null && typeof obj === "object" ) {
		// Serialize object item.
		for ( var name in obj ) {
			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
		}

	} else {
		// Serialize scalar item.
		add( prefix, obj );
	}
}

// This is still on the jQuery object... for now
// Want to move this to jQuery.ajax some day
jQuery.extend({

	// Counter for holding the number of active queries
	active: 0,

	// Last-Modified header cache for next request
	lastModified: {},
	etag: {}

});

/* Handles responses to an ajax request:
 * - sets all responseXXX fields accordingly
 * - finds the right dataType (mediates between content-type and expected dataType)
 * - returns the corresponding response
 */
function ajaxHandleResponses( s, jqXHR, responses ) {

	var contents = s.contents,
		dataTypes = s.dataTypes,
		responseFields = s.responseFields,
		ct,
		type,
		finalDataType,
		firstDataType;

	// Fill responseXXX fields
	for ( type in responseFields ) {
		if ( type in responses ) {
			jqXHR[ responseFields[type] ] = responses[ type ];
		}
	}

	// Remove auto dataType and get content-type in the process
	while( dataTypes[ 0 ] === "*" ) {
		dataTypes.shift();
		if ( ct === undefined ) {
			ct = s.mimeType || jqXHR.getResponseHeader( "content-type" );
		}
	}

	// Check if we're dealing with a known content-type
	if ( ct ) {
		for ( type in contents ) {
			if ( contents[ type ] && contents[ type ].test( ct ) ) {
				dataTypes.unshift( type );
				break;
			}
		}
	}

	// Check to see if we have a response for the expected dataType
	if ( dataTypes[ 0 ] in responses ) {
		finalDataType = dataTypes[ 0 ];
	} else {
		// Try convertible dataTypes
		for ( type in responses ) {
			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
				finalDataType = type;
				break;
			}
			if ( !firstDataType ) {
				firstDataType = type;
			}
		}
		// Or just use first one
		finalDataType = finalDataType || firstDataType;
	}

	// If we found a dataType
	// We add the dataType to the list if needed
	// and return the corresponding response
	if ( finalDataType ) {
		if ( finalDataType !== dataTypes[ 0 ] ) {
			dataTypes.unshift( finalDataType );
		}
		return responses[ finalDataType ];
	}
}

// Chain conversions given the request and the original response
function ajaxConvert( s, response ) {

	// Apply the dataFilter if provided
	if ( s.dataFilter ) {
		response = s.dataFilter( response, s.dataType );
	}

	var dataTypes = s.dataTypes,
		converters = {},
		i,
		key,
		length = dataTypes.length,
		tmp,
		// Current and previous dataTypes
		current = dataTypes[ 0 ],
		prev,
		// Conversion expression
		conversion,
		// Conversion function
		conv,
		// Conversion functions (transitive conversion)
		conv1,
		conv2;

	// For each dataType in the chain
	for ( i = 1; i < length; i++ ) {

		// Create converters map
		// with lowercased keys
		if ( i === 1 ) {
			for ( key in s.converters ) {
				if ( typeof key === "string" ) {
					converters[ key.toLowerCase() ] = s.converters[ key ];
				}
			}
		}

		// Get the dataTypes
		prev = current;
		current = dataTypes[ i ];

		// If current is auto dataType, update it to prev
		if ( current === "*" ) {
			current = prev;
		// If no auto and dataTypes are actually different
		} else if ( prev !== "*" && prev !== current ) {

			// Get the converter
			conversion = prev + " " + current;
			conv = converters[ conversion ] || converters[ "* " + current ];

			// If there is no direct converter, search transitively
			if ( !conv ) {
				conv2 = undefined;
				for ( conv1 in converters ) {
					tmp = conv1.split( " " );
					if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) {
						conv2 = converters[ tmp[1] + " " + current ];
						if ( conv2 ) {
							conv1 = converters[ conv1 ];
							if ( conv1 === true ) {
								conv = conv2;
							} else if ( conv2 === true ) {
								conv = conv1;
							}
							break;
						}
					}
				}
			}
			// If we found no converter, dispatch an error
			if ( !( conv || conv2 ) ) {
				jQuery.error( "No conversion from " + conversion.replace(" "," to ") );
			}
			// If found converter is not an equivalence
			if ( conv !== true ) {
				// Convert with 1 or 2 converters accordingly
				response = conv ? conv( response ) : conv2( conv1(response) );
			}
		}
	}
	return response;
}




var jsc = jQuery.now(),
	jsre = /(\=)\?(&|$)|\?\?/i;

// Default jsonp settings
jQuery.ajaxSetup({
	jsonp: "callback",
	jsonpCallback: function() {
		return jQuery.expando + "_" + ( jsc++ );
	}
});

// Detect, normalize options and install callbacks for jsonp requests
jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {

	var inspectData = s.contentType === "application/x-www-form-urlencoded" &&
		( typeof s.data === "string" );

	if ( s.dataTypes[ 0 ] === "jsonp" ||
		s.jsonp !== false && ( jsre.test( s.url ) ||
				inspectData && jsre.test( s.data ) ) ) {

		var responseContainer,
			jsonpCallback = s.jsonpCallback =
				jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
			previous = window[ jsonpCallback ],
			url = s.url,
			data = s.data,
			replace = "$1" + jsonpCallback + "$2";

		if ( s.jsonp !== false ) {
			url = url.replace( jsre, replace );
			if ( s.url === url ) {
				if ( inspectData ) {
					data = data.replace( jsre, replace );
				}
				if ( s.data === data ) {
					// Add callback manually
					url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback;
				}
			}
		}

		s.url = url;
		s.data = data;

		// Install callback
		window[ jsonpCallback ] = function( response ) {
			responseContainer = [ response ];
		};

		// Clean-up function
		jqXHR.always(function() {
			// Set callback back to previous value
			window[ jsonpCallback ] = previous;
			// Call if it was a function and we have a response
			if ( responseContainer && jQuery.isFunction( previous ) ) {
				window[ jsonpCallback ]( responseContainer[ 0 ] );
			}
		});

		// Use data converter to retrieve json after script execution
		s.converters["script json"] = function() {
			if ( !responseContainer ) {
				jQuery.error( jsonpCallback + " was not called" );
			}
			return responseContainer[ 0 ];
		};

		// force json dataType
		s.dataTypes[ 0 ] = "json";

		// Delegate to script
		return "script";
	}
});




// Install script dataType
jQuery.ajaxSetup({
	accepts: {
		script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
	},
	contents: {
		script: /javascript|ecmascript/
	},
	converters: {
		"text script": function( text ) {
			jQuery.globalEval( text );
			return text;
		}
	}
});

// Handle cache's special case and global
jQuery.ajaxPrefilter( "script", function( s ) {
	if ( s.cache === undefined ) {
		s.cache = false;
	}
	if ( s.crossDomain ) {
		s.type = "GET";
		s.global = false;
	}
});

// Bind script tag hack transport
jQuery.ajaxTransport( "script", function(s) {

	// This transport only deals with cross domain requests
	if ( s.crossDomain ) {

		var script,
			head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;

		return {

			send: function( _, callback ) {

				script = document.createElement( "script" );

				script.async = "async";

				if ( s.scriptCharset ) {
					script.charset = s.scriptCharset;
				}

				script.src = s.url;

				// Attach handlers for all browsers
				script.onload = script.onreadystatechange = function( _, isAbort ) {

					if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {

						// Handle memory leak in IE
						script.onload = script.onreadystatechange = null;

						// Remove the script
						if ( head && script.parentNode ) {
							head.removeChild( script );
						}

						// Dereference the script
						script = undefined;

						// Callback if not abort
						if ( !isAbort ) {
							callback( 200, "success" );
						}
					}
				};
				// Use insertBefore instead of appendChild  to circumvent an IE6 bug.
				// This arises when a base node is used (#2709 and #4378).
				head.insertBefore( script, head.firstChild );
			},

			abort: function() {
				if ( script ) {
					script.onload( 0, 1 );
				}
			}
		};
	}
});




var // #5280: Internet Explorer will keep connections alive if we don't abort on unload
	xhrOnUnloadAbort = window.ActiveXObject ? function() {
		// Abort all pending requests
		for ( var key in xhrCallbacks ) {
			xhrCallbacks[ key ]( 0, 1 );
		}
	} : false,
	xhrId = 0,
	xhrCallbacks;

// Functions to create xhrs
function createStandardXHR() {
	try {
		return new window.XMLHttpRequest();
	} catch( e ) {}
}

function createActiveXHR() {
	try {
		return new window.ActiveXObject( "Microsoft.XMLHTTP" );
	} catch( e ) {}
}

// Create the request object
// (This is still attached to ajaxSettings for backward compatibility)
jQuery.ajaxSettings.xhr = window.ActiveXObject ?
	/* Microsoft failed to properly
	 * implement the XMLHttpRequest in IE7 (can't request local files),
	 * so we use the ActiveXObject when it is available
	 * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
	 * we need a fallback.
	 */
	function() {
		return !this.isLocal && createStandardXHR() || createActiveXHR();
	} :
	// For all other browsers, use the standard XMLHttpRequest object
	createStandardXHR;

// Determine support properties
(function( xhr ) {
	jQuery.extend( jQuery.support, {
		ajax: !!xhr,
		cors: !!xhr && ( "withCredentials" in xhr )
	});
})( jQuery.ajaxSettings.xhr() );

// Create transport if the browser can provide an xhr
if ( jQuery.support.ajax ) {

	jQuery.ajaxTransport(function( s ) {
		// Cross domain only allowed if supported through XMLHttpRequest
		if ( !s.crossDomain || jQuery.support.cors ) {

			var callback;

			return {
				send: function( headers, complete ) {

					// Get a new xhr
					var xhr = s.xhr(),
						handle,
						i;

					// Open the socket
					// Passing null username, generates a login popup on Opera (#2865)
					if ( s.username ) {
						xhr.open( s.type, s.url, s.async, s.username, s.password );
					} else {
						xhr.open( s.type, s.url, s.async );
					}

					// Apply custom fields if provided
					if ( s.xhrFields ) {
						for ( i in s.xhrFields ) {
							xhr[ i ] = s.xhrFields[ i ];
						}
					}

					// Override mime type if needed
					if ( s.mimeType && xhr.overrideMimeType ) {
						xhr.overrideMimeType( s.mimeType );
					}

					// X-Requested-With header
					// For cross-domain requests, seeing as conditions for a preflight are
					// akin to a jigsaw puzzle, we simply never set it to be sure.
					// (it can always be set on a per-request basis or even using ajaxSetup)
					// For same-domain requests, won't change header if already provided.
					if ( !s.crossDomain && !headers["X-Requested-With"] ) {
						headers[ "X-Requested-With" ] = "XMLHttpRequest";
					}

					// Need an extra try/catch for cross domain requests in Firefox 3
					try {
						for ( i in headers ) {
							xhr.setRequestHeader( i, headers[ i ] );
						}
					} catch( _ ) {}

					// Do send the request
					// This may raise an exception which is actually
					// handled in jQuery.ajax (so no try/catch here)
					xhr.send( ( s.hasContent && s.data ) || null );

					// Listener
					callback = function( _, isAbort ) {

						var status,
							statusText,
							responseHeaders,
							responses,
							xml;

						// Firefox throws exceptions when accessing properties
						// of an xhr when a network error occured
						// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
						try {

							// Was never called and is aborted or complete
							if ( callback && ( isAbort || xhr.readyState === 4 ) ) {

								// Only called once
								callback = undefined;

								// Do not keep as active anymore
								if ( handle ) {
									xhr.onreadystatechange = jQuery.noop;
									if ( xhrOnUnloadAbort ) {
										delete xhrCallbacks[ handle ];
									}
								}

								// If it's an abort
								if ( isAbort ) {
									// Abort it manually if needed
									if ( xhr.readyState !== 4 ) {
										xhr.abort();
									}
								} else {
									status = xhr.status;
									responseHeaders = xhr.getAllResponseHeaders();
									responses = {};
									xml = xhr.responseXML;

									// Construct response list
									if ( xml && xml.documentElement /* #4958 */ ) {
										responses.xml = xml;
									}
									responses.text = xhr.responseText;

									// Firefox throws an exception when accessing
									// statusText for faulty cross-domain requests
									try {
										statusText = xhr.statusText;
									} catch( e ) {
										// We normalize with Webkit giving an empty statusText
										statusText = "";
									}

									// Filter status for non standard behaviors

									// If the request is local and we have data: assume a success
									// (success with no data won't get notified, that's the best we
									// can do given current implementations)
									if ( !status && s.isLocal && !s.crossDomain ) {
										status = responses.text ? 200 : 404;
									// IE - #1450: sometimes returns 1223 when it should be 204
									} else if ( status === 1223 ) {
										status = 204;
									}
								}
							}
						} catch( firefoxAccessException ) {
							if ( !isAbort ) {
								complete( -1, firefoxAccessException );
							}
						}

						// Call complete if needed
						if ( responses ) {
							complete( status, statusText, responses, responseHeaders );
						}
					};

					// if we're in sync mode or it's in cache
					// and has been retrieved directly (IE6 & IE7)
					// we need to manually fire the callback
					if ( !s.async || xhr.readyState === 4 ) {
						callback();
					} else {
						handle = ++xhrId;
						if ( xhrOnUnloadAbort ) {
							// Create the active xhrs callbacks list if needed
							// and attach the unload handler
							if ( !xhrCallbacks ) {
								xhrCallbacks = {};
								jQuery( window ).unload( xhrOnUnloadAbort );
							}
							// Add to list of active xhrs callbacks
							xhrCallbacks[ handle ] = callback;
						}
						xhr.onreadystatechange = callback;
					}
				},

				abort: function() {
					if ( callback ) {
						callback(0,1);
					}
				}
			};
		}
	});
}




var elemdisplay = {},
	iframe, iframeDoc,
	rfxtypes = /^(?:toggle|show|hide)$/,
	rfxnum = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,
	timerId,
	fxAttrs = [
		// height animations
		[ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
		// width animations
		[ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
		// opacity animations
		[ "opacity" ]
	],
	fxNow;

jQuery.fn.extend({
	show: function( speed, easing, callback ) {
		var elem, display;

		if ( speed || speed === 0 ) {
			return this.animate( genFx("show", 3), speed, easing, callback );

		} else {
			for ( var i = 0, j = this.length; i < j; i++ ) {
				elem = this[ i ];

				if ( elem.style ) {
					display = elem.style.display;

					// Reset the inline display of this element to learn if it is
					// being hidden by cascaded rules or not
					if ( !jQuery._data(elem, "olddisplay") && display === "none" ) {
						display = elem.style.display = "";
					}

					// Set elements which have been overridden with display: none
					// in a stylesheet to whatever the default browser style is
					// for such an element
					if ( display === "" && jQuery.css(elem, "display") === "none" ) {
						jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) );
					}
				}
			}

			// Set the display of most of the elements in a second loop
			// to avoid the constant reflow
			for ( i = 0; i < j; i++ ) {
				elem = this[ i ];

				if ( elem.style ) {
					display = elem.style.display;

					if ( display === "" || display === "none" ) {
						elem.style.display = jQuery._data( elem, "olddisplay" ) || "";
					}
				}
			}

			return this;
		}
	},

	hide: function( speed, easing, callback ) {
		if ( speed || speed === 0 ) {
			return this.animate( genFx("hide", 3), speed, easing, callback);

		} else {
			var elem, display,
				i = 0,
				j = this.length;

			for ( ; i < j; i++ ) {
				elem = this[i];
				if ( elem.style ) {
					display = jQuery.css( elem, "display" );

					if ( display !== "none" && !jQuery._data( elem, "olddisplay" ) ) {
						jQuery._data( elem, "olddisplay", display );
					}
				}
			}

			// Set the display of the elements in a second loop
			// to avoid the constant reflow
			for ( i = 0; i < j; i++ ) {
				if ( this[i].style ) {
					this[i].style.display = "none";
				}
			}

			return this;
		}
	},

	// Save the old toggle function
	_toggle: jQuery.fn.toggle,

	toggle: function( fn, fn2, callback ) {
		var bool = typeof fn === "boolean";

		if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
			this._toggle.apply( this, arguments );

		} else if ( fn == null || bool ) {
			this.each(function() {
				var state = bool ? fn : jQuery(this).is(":hidden");
				jQuery(this)[ state ? "show" : "hide" ]();
			});

		} else {
			this.animate(genFx("toggle", 3), fn, fn2, callback);
		}

		return this;
	},

	fadeTo: function( speed, to, easing, callback ) {
		return this.filter(":hidden").css("opacity", 0).show().end()
					.animate({opacity: to}, speed, easing, callback);
	},

	animate: function( prop, speed, easing, callback ) {
		var optall = jQuery.speed( speed, easing, callback );

		if ( jQuery.isEmptyObject( prop ) ) {
			return this.each( optall.complete, [ false ] );
		}

		// Do not change referenced properties as per-property easing will be lost
		prop = jQuery.extend( {}, prop );

		function doAnimation() {
			// XXX 'this' does not always have a nodeName when running the
			// test suite

			if ( optall.queue === false ) {
				jQuery._mark( this );
			}

			var opt = jQuery.extend( {}, optall ),
				isElement = this.nodeType === 1,
				hidden = isElement && jQuery(this).is(":hidden"),
				name, val, p, e,
				parts, start, end, unit,
				method;

			// will store per property easing and be used to determine when an animation is complete
			opt.animatedProperties = {};

			for ( p in prop ) {

				// property name normalization
				name = jQuery.camelCase( p );
				if ( p !== name ) {
					prop[ name ] = prop[ p ];
					delete prop[ p ];
				}

				val = prop[ name ];

				// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)
				if ( jQuery.isArray( val ) ) {
					opt.animatedProperties[ name ] = val[ 1 ];
					val = prop[ name ] = val[ 0 ];
				} else {
					opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';
				}

				if ( val === "hide" && hidden || val === "show" && !hidden ) {
					return opt.complete.call( this );
				}

				if ( isElement && ( name === "height" || name === "width" ) ) {
					// Make sure that nothing sneaks out
					// Record all 3 overflow attributes because IE does not
					// change the overflow attribute when overflowX and
					// overflowY are set to the same value
					opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];

					// Set display property to inline-block for height/width
					// animations on inline elements that are having width/height animated
					if ( jQuery.css( this, "display" ) === "inline" &&
							jQuery.css( this, "float" ) === "none" ) {

						// inline-level elements accept inline-block;
						// block-level elements need to be inline with layout
						if ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === "inline" ) {
							this.style.display = "inline-block";

						} else {
							this.style.zoom = 1;
						}
					}
				}
			}

			if ( opt.overflow != null ) {
				this.style.overflow = "hidden";
			}

			for ( p in prop ) {
				e = new jQuery.fx( this, opt, p );
				val = prop[ p ];

				if ( rfxtypes.test( val ) ) {

					// Tracks whether to show or hide based on private
					// data attached to the element
					method = jQuery._data( this, "toggle" + p ) || ( val === "toggle" ? hidden ? "show" : "hide" : 0 );
					if ( method ) {
						jQuery._data( this, "toggle" + p, method === "show" ? "hide" : "show" );
						e[ method ]();
					} else {
						e[ val ]();
					}

				} else {
					parts = rfxnum.exec( val );
					start = e.cur();

					if ( parts ) {
						end = parseFloat( parts[2] );
						unit = parts[3] || ( jQuery.cssNumber[ p ] ? "" : "px" );

						// We need to compute starting value
						if ( unit !== "px" ) {
							jQuery.style( this, p, (end || 1) + unit);
							start = ( (end || 1) / e.cur() ) * start;
							jQuery.style( this, p, start + unit);
						}

						// If a +=/-= token was provided, we're doing a relative animation
						if ( parts[1] ) {
							end = ( (parts[ 1 ] === "-=" ? -1 : 1) * end ) + start;
						}

						e.custom( start, end, unit );

					} else {
						e.custom( start, val, "" );
					}
				}
			}

			// For JS strict compliance
			return true;
		}

		return optall.queue === false ?
			this.each( doAnimation ) :
			this.queue( optall.queue, doAnimation );
	},

	stop: function( type, clearQueue, gotoEnd ) {
		if ( typeof type !== "string" ) {
			gotoEnd = clearQueue;
			clearQueue = type;
			type = undefined;
		}
		if ( clearQueue && type !== false ) {
			this.queue( type || "fx", [] );
		}

		return this.each(function() {
			var index,
				hadTimers = false,
				timers = jQuery.timers,
				data = jQuery._data( this );

			// clear marker counters if we know they won't be
			if ( !gotoEnd ) {
				jQuery._unmark( true, this );
			}

			function stopQueue( elem, data, index ) {
				var hooks = data[ index ];
				jQuery.removeData( elem, index, true );
				hooks.stop( gotoEnd );
			}

			if ( type == null ) {
				for ( index in data ) {
					if ( data[ index ] && data[ index ].stop && index.indexOf(".run") === index.length - 4 ) {
						stopQueue( this, data, index );
					}
				}
			} else if ( data[ index = type + ".run" ] && data[ index ].stop ){
				stopQueue( this, data, index );
			}

			for ( index = timers.length; index--; ) {
				if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
					if ( gotoEnd ) {

						// force the next step to be the last
						timers[ index ]( true );
					} else {
						timers[ index ].saveState();
					}
					hadTimers = true;
					timers.splice( index, 1 );
				}
			}

			// start the next in the queue if the last step wasn't forced
			// timers currently will call their complete callbacks, which will dequeue
			// but only if they were gotoEnd
			if ( !( gotoEnd && hadTimers ) ) {
				jQuery.dequeue( this, type );
			}
		});
	}

});

// Animations created synchronously will run synchronously
function createFxNow() {
	setTimeout( clearFxNow, 0 );
	return ( fxNow = jQuery.now() );
}

function clearFxNow() {
	fxNow = undefined;
}

// Generate parameters to create a standard animation
function genFx( type, num ) {
	var obj = {};

	jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {
		obj[ this ] = type;
	});

	return obj;
}

// Generate shortcuts for custom animations
jQuery.each({
	slideDown: genFx( "show", 1 ),
	slideUp: genFx( "hide", 1 ),
	slideToggle: genFx( "toggle", 1 ),
	fadeIn: { opacity: "show" },
	fadeOut: { opacity: "hide" },
	fadeToggle: { opacity: "toggle" }
}, function( name, props ) {
	jQuery.fn[ name ] = function( speed, easing, callback ) {
		return this.animate( props, speed, easing, callback );
	};
});

jQuery.extend({
	speed: function( speed, easing, fn ) {
		var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
			complete: fn || !fn && easing ||
				jQuery.isFunction( speed ) && speed,
			duration: speed,
			easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
		};

		opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
			opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;

		// normalize opt.queue - true/undefined/null -> "fx"
		if ( opt.queue == null || opt.queue === true ) {
			opt.queue = "fx";
		}

		// Queueing
		opt.old = opt.complete;

		opt.complete = function( noUnmark ) {
			if ( jQuery.isFunction( opt.old ) ) {
				opt.old.call( this );
			}

			if ( opt.queue ) {
				jQuery.dequeue( this, opt.queue );
			} else if ( noUnmark !== false ) {
				jQuery._unmark( this );
			}
		};

		return opt;
	},

	easing: {
		linear: function( p, n, firstNum, diff ) {
			return firstNum + diff * p;
		},
		swing: function( p, n, firstNum, diff ) {
			return ( ( -Math.cos( p*Math.PI ) / 2 ) + 0.5 ) * diff + firstNum;
		}
	},

	timers: [],

	fx: function( elem, options, prop ) {
		this.options = options;
		this.elem = elem;
		this.prop = prop;

		options.orig = options.orig || {};
	}

});

jQuery.fx.prototype = {
	// Simple function for setting a style value
	update: function() {
		if ( this.options.step ) {
			this.options.step.call( this.elem, this.now, this );
		}

		( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );
	},

	// Get the current size
	cur: function() {
		if ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {
			return this.elem[ this.prop ];
		}

		var parsed,
			r = jQuery.css( this.elem, this.prop );
		// Empty strings, null, undefined and "auto" are converted to 0,
		// complex values such as "rotate(1rad)" are returned as is,
		// simple values such as "10px" are parsed to Float.
		return isNaN( parsed = parseFloat( r ) ) ? !r || r === "auto" ? 0 : r : parsed;
	},

	// Start an animation from one number to another
	custom: function( from, to, unit ) {
		var self = this,
			fx = jQuery.fx;

		this.startTime = fxNow || createFxNow();
		this.end = to;
		this.now = this.start = from;
		this.pos = this.state = 0;
		this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" );

		function t( gotoEnd ) {
			return self.step( gotoEnd );
		}

		t.queue = this.options.queue;
		t.elem = this.elem;
		t.saveState = function() {
			if ( self.options.hide && jQuery._data( self.elem, "fxshow" + self.prop ) === undefined ) {
				jQuery._data( self.elem, "fxshow" + self.prop, self.start );
			}
		};

		if ( t() && jQuery.timers.push(t) && !timerId ) {
			timerId = setInterval( fx.tick, fx.interval );
		}
	},

	// Simple 'show' function
	show: function() {
		var dataShow = jQuery._data( this.elem, "fxshow" + this.prop );

		// Remember where we started, so that we can go back to it later
		this.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );
		this.options.show = true;

		// Begin the animation
		// Make sure that we start at a small width/height to avoid any flash of content
		if ( dataShow !== undefined ) {
			// This show is picking up where a previous hide or show left off
			this.custom( this.cur(), dataShow );
		} else {
			this.custom( this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur() );
		}

		// Start by showing the element
		jQuery( this.elem ).show();
	},

	// Simple 'hide' function
	hide: function() {
		// Remember where we started, so that we can go back to it later
		this.options.orig[ this.prop ] = jQuery._data( this.elem, "fxshow" + this.prop ) || jQuery.style( this.elem, this.prop );
		this.options.hide = true;

		// Begin the animation
		this.custom( this.cur(), 0 );
	},

	// Each step of an animation
	step: function( gotoEnd ) {
		var p, n, complete,
			t = fxNow || createFxNow(),
			done = true,
			elem = this.elem,
			options = this.options;

		if ( gotoEnd || t >= options.duration + this.startTime ) {
			this.now = this.end;
			this.pos = this.state = 1;
			this.update();

			options.animatedProperties[ this.prop ] = true;

			for ( p in options.animatedProperties ) {
				if ( options.animatedProperties[ p ] !== true ) {
					done = false;
				}
			}

			if ( done ) {
				// Reset the overflow
				if ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {

					jQuery.each( [ "", "X", "Y" ], function( index, value ) {
						elem.style[ "overflow" + value ] = options.overflow[ index ];
					});
				}

				// Hide the element if the "hide" operation was done
				if ( options.hide ) {
					jQuery( elem ).hide();
				}

				// Reset the properties, if the item has been hidden or shown
				if ( options.hide || options.show ) {
					for ( p in options.animatedProperties ) {
						jQuery.style( elem, p, options.orig[ p ] );
						jQuery.removeData( elem, "fxshow" + p, true );
						// Toggle data is no longer needed
						jQuery.removeData( elem, "toggle" + p, true );
					}
				}

				// Execute the complete function
				// in the event that the complete function throws an exception
				// we must ensure it won't be called twice. #5684

				complete = options.complete;
				if ( complete ) {

					options.complete = false;
					complete.call( elem );
				}
			}

			return false;

		} else {
			// classical easing cannot be used with an Infinity duration
			if ( options.duration == Infinity ) {
				this.now = t;
			} else {
				n = t - this.startTime;
				this.state = n / options.duration;

				// Perform the easing function, defaults to swing
				this.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );
				this.now = this.start + ( (this.end - this.start) * this.pos );
			}
			// Perform the next step of the animation
			this.update();
		}

		return true;
	}
};

jQuery.extend( jQuery.fx, {
	tick: function() {
		var timer,
			timers = jQuery.timers,
			i = 0;

		for ( ; i < timers.length; i++ ) {
			timer = timers[ i ];
			// Checks the timer has not already been removed
			if ( !timer() && timers[ i ] === timer ) {
				timers.splice( i--, 1 );
			}
		}

		if ( !timers.length ) {
			jQuery.fx.stop();
		}
	},

	interval: 13,

	stop: function() {
		clearInterval( timerId );
		timerId = null;
	},

	speeds: {
		slow: 600,
		fast: 200,
		// Default speed
		_default: 400
	},

	step: {
		opacity: function( fx ) {
			jQuery.style( fx.elem, "opacity", fx.now );
		},

		_default: function( fx ) {
			if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
				fx.elem.style[ fx.prop ] = fx.now + fx.unit;
			} else {
				fx.elem[ fx.prop ] = fx.now;
			}
		}
	}
});

// Adds width/height step functions
// Do not set anything below 0
jQuery.each([ "width", "height" ], function( i, prop ) {
	jQuery.fx.step[ prop ] = function( fx ) {
		jQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit );
	};
});

if ( jQuery.expr && jQuery.expr.filters ) {
	jQuery.expr.filters.animated = function( elem ) {
		return jQuery.grep(jQuery.timers, function( fn ) {
			return elem === fn.elem;
		}).length;
	};
}

// Try to restore the default display value of an element
function defaultDisplay( nodeName ) {

	if ( !elemdisplay[ nodeName ] ) {

		var body = document.body,
			elem = jQuery( "<" + nodeName + ">" ).appendTo( body ),
			display = elem.css( "display" );
		elem.remove();

		// If the simple way fails,
		// get element's real default display by attaching it to a temp iframe
		if ( display === "none" || display === "" ) {
			// No iframe to use yet, so create it
			if ( !iframe ) {
				iframe = document.createElement( "iframe" );
				iframe.frameBorder = iframe.width = iframe.height = 0;
			}

			body.appendChild( iframe );

			// Create a cacheable copy of the iframe document on first call.
			// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML
			// document to it; WebKit & Firefox won't allow reusing the iframe document.
			if ( !iframeDoc || !iframe.createElement ) {
				iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;
				iframeDoc.write( ( document.compatMode === "CSS1Compat" ? "<!doctype html>" : "" ) + "<html><body>" );
				iframeDoc.close();
			}

			elem = iframeDoc.createElement( nodeName );

			iframeDoc.body.appendChild( elem );

			display = jQuery.css( elem, "display" );
			body.removeChild( iframe );
		}

		// Store the correct default display
		elemdisplay[ nodeName ] = display;
	}

	return elemdisplay[ nodeName ];
}




var rtable = /^t(?:able|d|h)$/i,
	rroot = /^(?:body|html)$/i;

if ( "getBoundingClientRect" in document.documentElement ) {
	jQuery.fn.offset = function( options ) {
		var elem = this[0], box;

		if ( options ) {
			return this.each(function( i ) {
				jQuery.offset.setOffset( this, options, i );
			});
		}

		if ( !elem || !elem.ownerDocument ) {
			return null;
		}

		if ( elem === elem.ownerDocument.body ) {
			return jQuery.offset.bodyOffset( elem );
		}

		try {
			box = elem.getBoundingClientRect();
		} catch(e) {}

		var doc = elem.ownerDocument,
			docElem = doc.documentElement;

		// Make sure we're not dealing with a disconnected DOM node
		if ( !box || !jQuery.contains( docElem, elem ) ) {
			return box ? { top: box.top, left: box.left } : { top: 0, left: 0 };
		}

		var body = doc.body,
			win = getWindow(doc),
			clientTop  = docElem.clientTop  || body.clientTop  || 0,
			clientLeft = docElem.clientLeft || body.clientLeft || 0,
			scrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,
			scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,
			top  = box.top  + scrollTop  - clientTop,
			left = box.left + scrollLeft - clientLeft;

		return { top: top, left: left };
	};

} else {
	jQuery.fn.offset = function( options ) {
		var elem = this[0];

		if ( options ) {
			return this.each(function( i ) {
				jQuery.offset.setOffset( this, options, i );
			});
		}

		if ( !elem || !elem.ownerDocument ) {
			return null;
		}

		if ( elem === elem.ownerDocument.body ) {
			return jQuery.offset.bodyOffset( elem );
		}

		var computedStyle,
			offsetParent = elem.offsetParent,
			prevOffsetParent = elem,
			doc = elem.ownerDocument,
			docElem = doc.documentElement,
			body = doc.body,
			defaultView = doc.defaultView,
			prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
			top = elem.offsetTop,
			left = elem.offsetLeft;

		while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
			if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) {
				break;
			}

			computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
			top  -= elem.scrollTop;
			left -= elem.scrollLeft;

			if ( elem === offsetParent ) {
				top  += elem.offsetTop;
				left += elem.offsetLeft;

				if ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {
					top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
					left += parseFloat( computedStyle.borderLeftWidth ) || 0;
				}

				prevOffsetParent = offsetParent;
				offsetParent = elem.offsetParent;
			}

			if ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
				top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
				left += parseFloat( computedStyle.borderLeftWidth ) || 0;
			}

			prevComputedStyle = computedStyle;
		}

		if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
			top  += body.offsetTop;
			left += body.offsetLeft;
		}

		if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) {
			top  += Math.max( docElem.scrollTop, body.scrollTop );
			left += Math.max( docElem.scrollLeft, body.scrollLeft );
		}

		return { top: top, left: left };
	};
}

jQuery.offset = {

	bodyOffset: function( body ) {
		var top = body.offsetTop,
			left = body.offsetLeft;

		if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {
			top  += parseFloat( jQuery.css(body, "marginTop") ) || 0;
			left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
		}

		return { top: top, left: left };
	},

	setOffset: function( elem, options, i ) {
		var position = jQuery.css( elem, "position" );

		// set position first, in-case top/left are set even on static elem
		if ( position === "static" ) {
			elem.style.position = "relative";
		}

		var curElem = jQuery( elem ),
			curOffset = curElem.offset(),
			curCSSTop = jQuery.css( elem, "top" ),
			curCSSLeft = jQuery.css( elem, "left" ),
			calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
			props = {}, curPosition = {}, curTop, curLeft;

		// need to be able to calculate position if either top or left is auto and position is either absolute or fixed
		if ( calculatePosition ) {
			curPosition = curElem.position();
			curTop = curPosition.top;
			curLeft = curPosition.left;
		} else {
			curTop = parseFloat( curCSSTop ) || 0;
			curLeft = parseFloat( curCSSLeft ) || 0;
		}

		if ( jQuery.isFunction( options ) ) {
			options = options.call( elem, i, curOffset );
		}

		if ( options.top != null ) {
			props.top = ( options.top - curOffset.top ) + curTop;
		}
		if ( options.left != null ) {
			props.left = ( options.left - curOffset.left ) + curLeft;
		}

		if ( "using" in options ) {
			options.using.call( elem, props );
		} else {
			curElem.css( props );
		}
	}
};


jQuery.fn.extend({

	position: function() {
		if ( !this[0] ) {
			return null;
		}

		var elem = this[0],

		// Get *real* offsetParent
		offsetParent = this.offsetParent(),

		// Get correct offsets
		offset       = this.offset(),
		parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();

		// Subtract element margins
		// note: when an element has margin: auto the offsetLeft and marginLeft
		// are the same in Safari causing offset.left to incorrectly be 0
		offset.top  -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
		offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;

		// Add offsetParent borders
		parentOffset.top  += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
		parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;

		// Subtract the two offsets
		return {
			top:  offset.top  - parentOffset.top,
			left: offset.left - parentOffset.left
		};
	},

	offsetParent: function() {
		return this.map(function() {
			var offsetParent = this.offsetParent || document.body;
			while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
				offsetParent = offsetParent.offsetParent;
			}
			return offsetParent;
		});
	}
});


// Create scrollLeft and scrollTop methods
jQuery.each( ["Left", "Top"], function( i, name ) {
	var method = "scroll" + name;

	jQuery.fn[ method ] = function( val ) {
		var elem, win;

		if ( val === undefined ) {
			elem = this[ 0 ];

			if ( !elem ) {
				return null;
			}

			win = getWindow( elem );

			// Return the scroll offset
			return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
				jQuery.support.boxModel && win.document.documentElement[ method ] ||
					win.document.body[ method ] :
				elem[ method ];
		}

		// Set the scroll offset
		return this.each(function() {
			win = getWindow( this );

			if ( win ) {
				win.scrollTo(
					!i ? val : jQuery( win ).scrollLeft(),
					 i ? val : jQuery( win ).scrollTop()
				);

			} else {
				this[ method ] = val;
			}
		});
	};
});

function getWindow( elem ) {
	return jQuery.isWindow( elem ) ?
		elem :
		elem.nodeType === 9 ?
			elem.defaultView || elem.parentWindow :
			false;
}




// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods
jQuery.each([ "Height", "Width" ], function( i, name ) {

	var type = name.toLowerCase();

	// innerHeight and innerWidth
	jQuery.fn[ "inner" + name ] = function() {
		var elem = this[0];
		return elem ?
			elem.style ?
			parseFloat( jQuery.css( elem, type, "padding" ) ) :
			this[ type ]() :
			null;
	};

	// outerHeight and outerWidth
	jQuery.fn[ "outer" + name ] = function( margin ) {
		var elem = this[0];
		return elem ?
			elem.style ?
			parseFloat( jQuery.css( elem, type, margin ? "margin" : "border" ) ) :
			this[ type ]() :
			null;
	};

	jQuery.fn[ type ] = function( size ) {
		// Get window width or height
		var elem = this[0];
		if ( !elem ) {
			return size == null ? null : this;
		}

		if ( jQuery.isFunction( size ) ) {
			return this.each(function( i ) {
				var self = jQuery( this );
				self[ type ]( size.call( this, i, self[ type ]() ) );
			});
		}

		if ( jQuery.isWindow( elem ) ) {
			// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
			// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat
			var docElemProp = elem.document.documentElement[ "client" + name ],
				body = elem.document.body;
			return elem.document.compatMode === "CSS1Compat" && docElemProp ||
				body && body[ "client" + name ] || docElemProp;

		// Get document width or height
		} else if ( elem.nodeType === 9 ) {
			// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
			return Math.max(
				elem.documentElement["client" + name],
				elem.body["scroll" + name], elem.documentElement["scroll" + name],
				elem.body["offset" + name], elem.documentElement["offset" + name]
			);

		// Get or set width or height on the element
		} else if ( size === undefined ) {
			var orig = jQuery.css( elem, type ),
				ret = parseFloat( orig );

			return jQuery.isNumeric( ret ) ? ret : orig;

		// Set the width or height on the element (default to pixels if value is unitless)
		} else {
			return this.css( type, typeof size === "string" ? size : size + "px" );
		}
	};

});




// Expose jQuery to the global object
window.jQuery = window.$ = jQuery;

// Expose jQuery as an AMD module, but only for AMD loaders that
// understand the issues with loading multiple versions of jQuery
// in a page that all might call define(). The loader will indicate
// they have special allowances for multiple jQuery versions by
// specifying define.amd.jQuery = true. Register as a named module,
// since jQuery can be concatenated with other files that may use define,
// but not use a proper concatenation script that understands anonymous
// AMD modules. A named AMD is safest and most robust way to register.
// Lowercase jquery is used because AMD module names are derived from
// file names, and jQuery is normally delivered in a lowercase file name.
// Do this after creating the global so that if an AMD module wants to call
// noConflict to hide this version of jQuery, it will work.
if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
	define( "jquery", [], function () { return jQuery; } );
}



})( window );
function filterElements() {
    inherited = !$('#show-inherited').hasClass('deselected');
    public = !$('#show-public').hasClass('deselected');
    protected = !$('#show-protected').hasClass('deselected');
    private = !$('#show-private').hasClass('deselected');

    $('div.public').each(function(index, val) {
        $(val).toggle(public && !($(val).hasClass('inherited_from') && !inherited));
    });
    $('div.protected').each(function(index, val) {
        $(val).toggle(protected && !($(val).hasClass('inherited_from') && !inherited));
    });
    $('div.private').each(function(index, val) {
        $(val).toggle(private && !($(val).hasClass('inherited_from') && !inherited));
    });
}

$(document).ready(function() {
    $('#show-public, #show-protected, #show-private, #show-inherited')
            .css('cursor', 'pointer')
            .click(function() {
                $(this).toggleClass('deselected');
                if ($(this).hasClass('deselected')) {
                    $(this).fadeTo('fast', '0.4');
                } else {
                    $(this).fadeTo('fast', '1.0');
                }
                filterElements();
                return false;
            });
    $('#show-protected, #show-private').click();
});/*!
 * Bootstrap v3.0.2 by @fat and @mdo
 * Copyright 2013 Twitter, Inc.
 * Licensed under http://www.apache.org/licenses/LICENSE-2.0
 *
 * Designed and built with all the love in the world by @mdo and @fat.
 */

if("undefined"==typeof jQuery)throw new Error("Bootstrap requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]}}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d)};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.is("input")?"val":"html",e=c.data();a+="Text",e.resetText||c.data("resetText",c[d]()),c[d](e[a]||this.options[a]),setTimeout(function(){"loadingText"==a?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons"]');if(a.length){var b=this.$element.find("input").prop("checked",!this.$element.hasClass("active")).trigger("change");"radio"===b.prop("type")&&a.find(".active").removeClass("active")}this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}this.sliding=!0,f&&this.pause();var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});if(!e.hasClass("active")){if(this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")){if(this.$element.trigger(j),j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid")},0)}).emulateTransitionEnd(600)}else{if(this.$element.trigger(j),j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return f&&this.cycle(),this}};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?(this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350),void 0):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(jQuery),+function(a){"use strict";function b(){a(d).remove(),a(e).each(function(b){var d=c(a(this));d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown")),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown"))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){if("ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('<div class="dropdown-backdrop"/>').insertAfter(a(this)).on("click",b),f.trigger(d=a.Event("show.bs.dropdown")),d.isDefaultPrevented())return;f.toggleClass("open").trigger("shown.bs.dropdown"),e.focus()}return!1}},f.prototype.keydown=function(b){if(/(38|40|27)/.test(b.keyCode)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var f=c(d),g=f.hasClass("open");if(!g||g&&27==b.keyCode)return 27==b.which&&f.find(e).focus(),d.click();var h=a("[role=menu] li:not(.divider):visible a",f);if(h.length){var i=h.index(h.filter(":focus"));38==b.keyCode&&i>0&&i--,40==b.keyCode&&i<h.length-1&&i++,~i||(i=0),h.eq(i).focus()}}}};var g=a.fn.dropdown;a.fn.dropdown=function(b){return this.each(function(){var c=a(this),d=c.data("dropdown");d||c.data("dropdown",d=new f(this)),"string"==typeof b&&d[b].call(c)})},a.fn.dropdown.Constructor=f,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=g,this},a(document).on("click.bs.dropdown.data-api",b).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",e,f.prototype.toggle).on("keydown.bs.dropdown.data-api",e+", [role=menu]",f.prototype.keydown)}(jQuery),+function(a){"use strict";var b=function(b,c){this.options=c,this.$element=a(b),this.$backdrop=this.isShown=null,this.options.remote&&this.$element.load(this.options.remote)};b.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},b.prototype.toggle=function(a){return this[this.isShown?"hide":"show"](a)},b.prototype.show=function(b){var c=this,d=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(d),this.isShown||d.isDefaultPrevented()||(this.isShown=!0,this.escape(),this.$element.on("click.dismiss.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.backdrop(function(){var d=a.support.transition&&c.$element.hasClass("fade");c.$element.parent().length||c.$element.appendTo(document.body),c.$element.show(),d&&c.$element[0].offsetWidth,c.$element.addClass("in").attr("aria-hidden",!1),c.enforceFocus();var e=a.Event("shown.bs.modal",{relatedTarget:b});d?c.$element.find(".modal-dialog").one(a.support.transition.end,function(){c.$element.focus().trigger(e)}).emulateTransitionEnd(300):c.$element.focus().trigger(e)}))},b.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.escape(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").attr("aria-hidden",!0).off("click.dismiss.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one(a.support.transition.end,a.proxy(this.hideModal,this)).emulateTransitionEnd(300):this.hideModal())},b.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.focus()},this))},b.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.bs.modal",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off("keyup.dismiss.bs.modal")},b.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.removeBackdrop(),a.$element.trigger("hidden.bs.modal")})},b.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},b.prototype.backdrop=function(b){var c=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var d=a.support.transition&&c;if(this.$backdrop=a('<div class="modal-backdrop '+c+'" />').appendTo(document.body),this.$element.on("click.dismiss.modal",a.proxy(function(a){a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus.call(this.$element[0]):this.hide.call(this))},this)),d&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;d?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()):b&&b()};var c=a.fn.modal;a.fn.modal=function(c,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},b.DEFAULTS,e.data(),"object"==typeof c&&c);f||e.data("bs.modal",f=new b(this,g)),"string"==typeof c?f[c](d):g.show&&f.show(d)})},a.fn.modal.Constructor=b,a.fn.modal.noConflict=function(){return a.fn.modal=c,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(b){var c=a(this),d=c.attr("href"),e=a(c.attr("data-target")||d&&d.replace(/.*(?=#[^\s]+$)/,"")),f=e.data("modal")?"toggle":a.extend({remote:!/#/.test(d)&&d},e.data(),c.data());b.preventDefault(),e.modal(f,this).one("hide",function(){c.is(":visible")&&c.focus()})}),a(document).on("show.bs.modal",".modal",function(){a(document.body).addClass("modal-open")}).on("hidden.bs.modal",".modal",function(){a(document.body).removeClass("modal-open")})}(jQuery),+function(a){"use strict";var b=function(a,b){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null,this.init("tooltip",a,b)};b.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},b.prototype.init=function(b,c,d){this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d);for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focus",i="hover"==g?"mouseleave":"blur";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},b.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},b.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show),void 0):c.show()},b.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide),void 0):c.hide()},b.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){if(this.$element.trigger(b),b.isDefaultPrevented())return;var c=this.tip();this.setContent(),this.options.animation&&c.addClass("fade");var d="function"==typeof this.options.placement?this.options.placement.call(this,c[0],this.$element[0]):this.options.placement,e=/\s?auto?\s?/i,f=e.test(d);f&&(d=d.replace(e,"")||"top"),c.detach().css({top:0,left:0,display:"block"}).addClass(d),this.options.container?c.appendTo(this.options.container):c.insertAfter(this.$element);var g=this.getPosition(),h=c[0].offsetWidth,i=c[0].offsetHeight;if(f){var j=this.$element.parent(),k=d,l=document.documentElement.scrollTop||document.body.scrollTop,m="body"==this.options.container?window.innerWidth:j.outerWidth(),n="body"==this.options.container?window.innerHeight:j.outerHeight(),o="body"==this.options.container?0:j.offset().left;d="bottom"==d&&g.top+g.height+i-l>n?"top":"top"==d&&g.top-l-i<0?"bottom":"right"==d&&g.right+h>m?"left":"left"==d&&g.left-h<o?"right":d,c.removeClass(k).addClass(d)}var p=this.getCalculatedOffset(d,g,h,i);this.applyPlacement(p,d),this.$element.trigger("shown.bs."+this.type)}},b.prototype.applyPlacement=function(a,b){var c,d=this.tip(),e=d[0].offsetWidth,f=d[0].offsetHeight,g=parseInt(d.css("margin-top"),10),h=parseInt(d.css("margin-left"),10);isNaN(g)&&(g=0),isNaN(h)&&(h=0),a.top=a.top+g,a.left=a.left+h,d.offset(a).addClass("in");var i=d[0].offsetWidth,j=d[0].offsetHeight;if("top"==b&&j!=f&&(c=!0,a.top=a.top+f-j),/bottom|top/.test(b)){var k=0;a.left<0&&(k=-2*a.left,a.left=0,d.offset(a),i=d[0].offsetWidth,j=d[0].offsetHeight),this.replaceArrow(k-e+i,i,"left")}else this.replaceArrow(j-f,j,"top");c&&d.offset(a)},b.prototype.replaceArrow=function(a,b,c){this.arrow().css(c,a?50*(1-a/b)+"%":"")},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},b.prototype.hide=function(){function b(){"in"!=c.hoverState&&d.detach()}var c=this,d=this.tip(),e=a.Event("hide.bs."+this.type);return this.$element.trigger(e),e.isDefaultPrevented()?void 0:(d.removeClass("in"),a.support.transition&&this.$tip.hasClass("fade")?d.one(a.support.transition.end,b).emulateTransitionEnd(150):b(),this.$element.trigger("hidden.bs."+this.type),this)},b.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"string"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},b.prototype.hasContent=function(){return this.getTitle()},b.prototype.getPosition=function(){var b=this.$element[0];return a.extend({},"function"==typeof b.getBoundingClientRect?b.getBoundingClientRect():{width:b.offsetWidth,height:b.offsetHeight},this.$element.offset())},b.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},b.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},b.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},b.prototype.validate=function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},b.prototype.enable=function(){this.enabled=!0},b.prototype.disable=function(){this.enabled=!1},b.prototype.toggleEnabled=function(){this.enabled=!this.enabled},b.prototype.toggle=function(b){var c=b?a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type):this;c.tip().hasClass("in")?c.leave(c):c.enter(c)},b.prototype.destroy=function(){this.hide().$element.off("."+this.type).removeData("bs."+this.type)};var c=a.fn.tooltip;a.fn.tooltip=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof c&&c;e||d.data("bs.tooltip",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.tooltip.Constructor=b,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=c,this}}(jQuery),+function(a){"use strict";var b=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");b.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(c).is("body")?a(window):a(c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#\w/.test(e)&&a(e);return f&&f.length&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parents(".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top()),"function"==typeof h&&(h=f.bottom());var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;this.affixed!==i&&(this.unpin&&this.$element.css("top",""),this.affixed=i,this.unpin="bottom"==i?e.top-d:null,this.$element.removeClass(b.RESET).addClass("affix"+(i?"-"+i:"")),"bottom"==i&&this.$element.offset({top:document.body.offsetHeight-h-this.$element.height()}))}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(jQuery);/*!
 *  Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome
 *  License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
 */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.0.3');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.0.3') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff?v=4.0.3') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.0.3') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.0.3#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.3333333333333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.2857142857142858em;text-align:center}.fa-ul{padding-left:0;margin-left:2.142857142857143em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.142857142857143em;width:2.142857142857143em;top:.14285714285714285em;text-align:center}.fa-li.fa-lg{left:-1.8571428571428572em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:spin 2s infinite linear;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg)}100%{-ms-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0,mirror=1);-webkit-transform:scale(-1,1);-moz-transform:scale(-1,1);-ms-transform:scale(-1,1);-o-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2,mirror=1);-webkit-transform:scale(1,-1);-moz-transform:scale(1,-1);-ms-transform:scale(1,-1);-o-transform:scale(1,-1);transform:scale(1,-1)}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-asc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-desc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-reply-all:before{content:"\f122"}.fa-mail-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}@import url('bootstrap.min.css');
/*@import url('font-awesome.min.css');*/

iframe {
    width: 100%;
    border: 0;
    min-height: 580px;
}
header .nav {
    margin-top: 27px;
}


#sidebar-nav h3 {
    position:relative;
    margin-left: 10px;
    padding-left: 10px;
}
#sidebar-nav h3[data-toggle="collapse"] {
    cursor: pointer;
}
#sidebar-nav h3[data-toggle="collapse"]:before {
    position:absolute;
    font-family: FontAwesome;
    top:0;
    left:-5px;
    content: "\F0D7";
}
#sidebar-nav h3[data-toggle="collapse"].collapsed:before {
    content: "\F0DA";
}

div.sidebar-section ul span {
    background: transparent no-repeat top left;
    padding-left: 20px;
}
div#sidebar .list-group-item {
    padding-right: 0;
    border-right: none;
    border-left: none;
}
div.sidebar-section ul span.method    { background-image: url('../images/icons/method.png'); }
div.sidebar-section ul span.function  { background-image: url('../images/icons/function.png'); }
div.sidebar-section ul span.class     { background-image: url('../images/icons/class.png'); }
div.sidebar-section ul span.interface { background-image: url('../images/icons/interface.png'); }
div.sidebar-section ul span.constant  { background-image: url('../images/icons/constant.png'); }
div.sidebar-section ul span.property  { background-image: url('../images/icons/property.png'); }
div.sidebar-section ul span.package   { background-image: url('../images/icons/folder.gif'); }
div.sidebar-section ul span.namespace { background-image: url('../images/icons/namespace.png'); }
div.sidebar-section ul span.file      { background-image: url('../images/icons/file.gif'); }
@import url('abstract.css');
/*!
 * Bootstrap v3.0.2 by @fat and @mdo
 * Copyright 2013 Twitter, Inc.
 * Licensed under http://www.apache.org/licenses/LICENSE-2.0
 *
 * Designed and built with all the love in the world by @mdo and @fat.
 */

/*! normalize.css v2.1.3 | MIT License | git.io/normalize */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}[hidden],template{display:none}html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a{background:transparent}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{margin:.67em 0;font-size:2em}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}hr{height:0;-moz-box-sizing:content-box;box-sizing:content-box}mark{color:#000;background:#ff0}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:0}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid #c0c0c0}legend{padding:0;border:0}button,input,select,textarea{margin:0;font-family:inherit;font-size:100%}button,input{line-height:normal}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}button[disabled],html input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{padding:0;box-sizing:border-box}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:2cm .5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.table td,.table th{background-color:#fff!important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}*,*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}img{vertical-align:middle}.img-responsive{display:block;height:auto;max-width:100%}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;height:auto;max-width:100%;padding:4px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}@media(min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}cite{font-style:normal}.text-muted{color:#999}.text-primary{color:#428bca}.text-primary:hover{color:#3071a9}.text-warning{color:#c09853}.text-warning:hover{color:#a47e3c}.text-danger{color:#b94a48}.text-danger:hover{color:#953b39}.text-success{color:#468847}.text-success:hover{color:#356635}.text-info{color:#3a87ad}.text-info:hover{color:#2d6987}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#999}h1,h2,h3{margin-top:20px;margin-bottom:10px}h1 small,h2 small,h3 small,h1 .small,h2 .small,h3 .small{font-size:65%}h4,h5,h6{margin-top:10px;margin-bottom:10px}h4 small,h5 small,h6 small,h4 .small,h5 .small,h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}.list-inline>li:first-child{padding-left:0}dl{margin-bottom:20px}dt,dd{line-height:1.428571429}dt{font-weight:bold}dd{margin-left:0}@media(min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}.dl-horizontal dd:before,.dl-horizontal dd:after{display:table;content:" "}.dl-horizontal dd:after{clear:both}.dl-horizontal dd:before,.dl-horizontal dd:after{display:table;content:" "}.dl-horizontal dd:after{clear:both}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{font-size:17.5px;font-weight:300;line-height:1.25}blockquote p:last-child{margin-bottom:0}blockquote small{display:block;line-height:1.428571429;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small,blockquote.pull-right .small{text-align:right}blockquote.pull-right small:before,blockquote.pull-right .small:before{content:''}blockquote.pull-right small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}blockquote:before,blockquote:after{content:""}address{margin-bottom:20px;font-style:normal;line-height:1.428571429}code,kbd,pre,samp{font-family:Monaco,Menlo,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;white-space:nowrap;background-color:#f9f2f4;border-radius:4px}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.428571429;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.container:before,.container:after{display:table;content:" "}.container:after{clear:both}.container:before,.container:after{display:table;content:" "}.container:after{clear:both}.row{margin-right:-15px;margin-left:-15px}.row:before,.row:after{display:table;content:" "}.row:after{clear:both}.row:before,.row:after{display:table;content:" "}.row:after{clear:both}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666666666666%}.col-xs-10{width:83.33333333333334%}.col-xs-9{width:75%}.col-xs-8{width:66.66666666666666%}.col-xs-7{width:58.333333333333336%}.col-xs-6{width:50%}.col-xs-5{width:41.66666666666667%}.col-xs-4{width:33.33333333333333%}.col-xs-3{width:25%}.col-xs-2{width:16.666666666666664%}.col-xs-1{width:8.333333333333332%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666666666666%}.col-xs-pull-10{right:83.33333333333334%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666666666666%}.col-xs-pull-7{right:58.333333333333336%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666666666667%}.col-xs-pull-4{right:33.33333333333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.666666666666664%}.col-xs-pull-1{right:8.333333333333332%}.col-xs-pull-0{right:0}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666666666666%}.col-xs-push-10{left:83.33333333333334%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666666666666%}.col-xs-push-7{left:58.333333333333336%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666666666667%}.col-xs-push-4{left:33.33333333333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.666666666666664%}.col-xs-push-1{left:8.333333333333332%}.col-xs-push-0{left:0}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666666666666%}.col-xs-offset-10{margin-left:83.33333333333334%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666666666666%}.col-xs-offset-7{margin-left:58.333333333333336%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666666666667%}.col-xs-offset-4{margin-left:33.33333333333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.666666666666664%}.col-xs-offset-1{margin-left:8.333333333333332%}.col-xs-offset-0{margin-left:0}@media(min-width:768px){.container{width:750px}.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666666666666%}.col-sm-10{width:83.33333333333334%}.col-sm-9{width:75%}.col-sm-8{width:66.66666666666666%}.col-sm-7{width:58.333333333333336%}.col-sm-6{width:50%}.col-sm-5{width:41.66666666666667%}.col-sm-4{width:33.33333333333333%}.col-sm-3{width:25%}.col-sm-2{width:16.666666666666664%}.col-sm-1{width:8.333333333333332%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666666666666%}.col-sm-pull-10{right:83.33333333333334%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666666666666%}.col-sm-pull-7{right:58.333333333333336%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666666666667%}.col-sm-pull-4{right:33.33333333333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.666666666666664%}.col-sm-pull-1{right:8.333333333333332%}.col-sm-pull-0{right:0}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666666666666%}.col-sm-push-10{left:83.33333333333334%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666666666666%}.col-sm-push-7{left:58.333333333333336%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666666666667%}.col-sm-push-4{left:33.33333333333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.666666666666664%}.col-sm-push-1{left:8.333333333333332%}.col-sm-push-0{left:0}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666666666666%}.col-sm-offset-10{margin-left:83.33333333333334%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666666666666%}.col-sm-offset-7{margin-left:58.333333333333336%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666666666667%}.col-sm-offset-4{margin-left:33.33333333333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.666666666666664%}.col-sm-offset-1{margin-left:8.333333333333332%}.col-sm-offset-0{margin-left:0}}@media(min-width:992px){.container{width:970px}.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666666666666%}.col-md-10{width:83.33333333333334%}.col-md-9{width:75%}.col-md-8{width:66.66666666666666%}.col-md-7{width:58.333333333333336%}.col-md-6{width:50%}.col-md-5{width:41.66666666666667%}.col-md-4{width:33.33333333333333%}.col-md-3{width:25%}.col-md-2{width:16.666666666666664%}.col-md-1{width:8.333333333333332%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666666666666%}.col-md-pull-10{right:83.33333333333334%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666666666666%}.col-md-pull-7{right:58.333333333333336%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666666666667%}.col-md-pull-4{right:33.33333333333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.666666666666664%}.col-md-pull-1{right:8.333333333333332%}.col-md-pull-0{right:0}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666666666666%}.col-md-push-10{left:83.33333333333334%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666666666666%}.col-md-push-7{left:58.333333333333336%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666666666667%}.col-md-push-4{left:33.33333333333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.666666666666664%}.col-md-push-1{left:8.333333333333332%}.col-md-push-0{left:0}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666666666666%}.col-md-offset-10{margin-left:83.33333333333334%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666666666666%}.col-md-offset-7{margin-left:58.333333333333336%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666666666667%}.col-md-offset-4{margin-left:33.33333333333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.666666666666664%}.col-md-offset-1{margin-left:8.333333333333332%}.col-md-offset-0{margin-left:0}}@media(min-width:1200px){.container{width:1170px}.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666666666666%}.col-lg-10{width:83.33333333333334%}.col-lg-9{width:75%}.col-lg-8{width:66.66666666666666%}.col-lg-7{width:58.333333333333336%}.col-lg-6{width:50%}.col-lg-5{width:41.66666666666667%}.col-lg-4{width:33.33333333333333%}.col-lg-3{width:25%}.col-lg-2{width:16.666666666666664%}.col-lg-1{width:8.333333333333332%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666666666666%}.col-lg-pull-10{right:83.33333333333334%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666666666666%}.col-lg-pull-7{right:58.333333333333336%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666666666667%}.col-lg-pull-4{right:33.33333333333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.666666666666664%}.col-lg-pull-1{right:8.333333333333332%}.col-lg-pull-0{right:0}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666666666666%}.col-lg-push-10{left:83.33333333333334%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666666666666%}.col-lg-push-7{left:58.333333333333336%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666666666667%}.col-lg-push-4{left:33.33333333333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.666666666666664%}.col-lg-push-1{left:8.333333333333332%}.col-lg-push-0{left:0}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666666666666%}.col-lg-offset-10{margin-left:83.33333333333334%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666666666666%}.col-lg-offset-7{margin-left:58.333333333333336%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666666666667%}.col-lg-offset-4{margin-left:33.33333333333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.666666666666664%}.col-lg-offset-1{margin-left:8.333333333333332%}.col-lg-offset-0{margin-left:0}}table{max-width:100%;background-color:transparent}th{text-align:left}.table{width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.428571429;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5}table col[class*="col-"]{display:table-column;float:none}table td[class*="col-"],table th[class*="col-"]{display:table-cell;float:none}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}@media(max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-x:scroll;overflow-y:hidden;border:1px solid #ddd;-ms-overflow-style:-ms-autohiding-scrollbar;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}select[multiple],select[size]{height:auto}select optgroup{font-family:inherit;font-size:inherit;font-style:inherit}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}input[type="number"]::-webkit-outer-spin-button,input[type="number"]::-webkit-inner-spin-button{height:auto}output{display:block;padding-top:7px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.form-control:-moz-placeholder{color:#999}.form-control::-moz-placeholder{color:#999}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee}textarea.form-control{height:auto}.form-group{margin-bottom:15px}.radio,.checkbox{display:block;min-height:20px;padding-left:20px;margin-top:10px;margin-bottom:10px;vertical-align:middle}.radio label,.checkbox label{display:inline;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{float:left;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;font-weight:normal;vertical-align:middle;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm{height:auto}.input-lg{height:45px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:45px;line-height:45px}textarea.input-lg{height:auto}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#c09853}.has-warning .form-control{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e}.has-warning .input-group-addon{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#b94a48}.has-error .form-control{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392}.has-error .input-group-addon{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#468847}.has-success .form-control{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b}.has-success .input-group-addon{color:#468847;background-color:#dff0d8;border-color:#468847}.form-control-static{margin-bottom:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media(min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block}.form-inline .radio,.form-inline .checkbox{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:none;margin-left:0}}.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}.form-horizontal .form-group:before,.form-horizontal .form-group:after{display:table;content:" "}.form-horizontal .form-group:after{clear:both}.form-horizontal .form-group:before,.form-horizontal .form-group:after{display:table;content:" "}.form-horizontal .form-group:after{clear:both}.form-horizontal .form-control-static{padding-top:7px}@media(min-width:768px){.form-horizontal .control-label{text-align:right}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:normal;line-height:1.428571429;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{pointer-events:none;cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-link{font-weight:normal;color:#428bca;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999;text-decoration:none}.btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm,.btn-xs{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs{padding:1px 5px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}@font-face{font-family:'Glyphicons Halflings';src:url('../fonts/glyphicons-halflings-regular.eot');src:url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('../fonts/glyphicons-halflings-regular.woff') format('woff'),url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';-webkit-font-smoothing:antialiased;font-style:normal;font-weight:normal;line-height:1;-moz-osx-font-smoothing:grayscale}.glyphicon:empty{width:1em}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid #000;border-right:4px solid transparent;border-bottom:0 dotted;border-left:4px solid transparent}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.428571429;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#428bca;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.428571429;color:#999}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0 dotted;border-bottom:4px solid #000;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media(min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}}.btn-default .caret{border-top-color:#333}.btn-primary .caret,.btn-success .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret{border-top-color:#fff}.dropup .btn-default .caret{border-bottom-color:#333}.dropup .btn-primary .caret,.dropup .btn-success .caret,.dropup .btn-warning .caret,.dropup .btn-danger .caret,.dropup .btn-info .caret{border-bottom-color:#fff}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:0}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar:before,.btn-toolbar:after{display:table;content:" "}.btn-toolbar:after{clear:both}.btn-toolbar:before,.btn-toolbar:after{display:table;content:" "}.btn-toolbar:after{clear:both}.btn-toolbar .btn-group{float:left}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group,.btn-toolbar>.btn-group+.btn-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group-xs>.btn{padding:5px 10px;padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after{display:table;content:" "}.btn-group-vertical>.btn-group:after{clear:both}.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after{display:table;content:" "}.btn-group-vertical>.btn-group:after{clear:both}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-bottom-left-radius:4px;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child>.btn:last-child,.btn-group-vertical>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;border-collapse:separate;table-layout:fixed}.btn-group-justified .btn{display:table-cell;float:none;width:1%}[data-toggle="buttons"]>.btn>input[type="radio"],[data-toggle="buttons"]>.btn>input[type="checkbox"]{display:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group.col{float:none;padding-right:0;padding-left:0}.input-group .form-control{width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:45px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:45px;line-height:45px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:normal;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;white-space:nowrap}.input-group-btn:first-child>.btn{margin-right:-1px}.input-group-btn:last-child>.btn{margin-left:-1px}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-4px}.input-group-btn>.btn:hover,.input-group-btn>.btn:active{z-index:2}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav:before,.nav:after{display:table;content:" "}.nav:after{clear:both}.nav:before,.nav:after{display:table;content:" "}.nav:after{clear:both}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#428bca}.nav .open>a .caret,.nav .open>a:hover .caret,.nav .open>a:focus .caret{border-top-color:#2a6496;border-bottom-color:#2a6496}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.428571429;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media(min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media(min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#428bca}.nav-pills>li.active>a .caret,.nav-pills>li.active>a:hover .caret,.nav-pills>li.active>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media(min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media(min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav .caret{border-top-color:#428bca;border-bottom-color:#428bca}.nav a:hover .caret{border-top-color:#2a6496;border-bottom-color:#2a6496}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}.navbar:before,.navbar:after{display:table;content:" "}.navbar:after{clear:both}.navbar:before,.navbar:after{display:table;content:" "}.navbar:after{clear:both}@media(min-width:768px){.navbar{border-radius:4px}}.navbar-header:before,.navbar-header:after{display:table;content:" "}.navbar-header:after{clear:both}.navbar-header:before,.navbar-header:after{display:table;content:" "}.navbar-header:after{clear:both}@media(min-width:768px){.navbar-header{float:left}}.navbar-collapse{max-height:340px;padding-right:15px;padding-left:15px;overflow-x:visible;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse:before,.navbar-collapse:after{display:table;content:" "}.navbar-collapse:after{clear:both}.navbar-collapse:before,.navbar-collapse:after{display:table;content:" "}.navbar-collapse:after{clear:both}.navbar-collapse.in{overflow-y:auto}@media(min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:auto}.navbar-collapse .navbar-nav.navbar-left:first-child{margin-left:-15px}.navbar-collapse .navbar-nav.navbar-right:last-child{margin-right:-15px}.navbar-collapse .navbar-text:last-child{margin-right:0}}.container>.navbar-header,.container>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media(min-width:768px){.container>.navbar-header,.container>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media(min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media(min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}@media(min-width:768px){.navbar>.container .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;border:1px solid transparent;border-radius:4px}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media(min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media(max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media(min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}@media(min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}@media(min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{float:none;margin-left:0}}@media(max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media(min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-nav.pull-right>li>.dropdown-menu,.navbar-nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-text{float:left;margin-top:15px;margin-bottom:15px}@media(min-width:768px){.navbar-text{margin-right:15px;margin-left:15px}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#ccc}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.dropdown>a:hover .caret,.navbar-default .navbar-nav>.dropdown>a:focus .caret{border-top-color:#333;border-bottom-color:#333}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.open>a .caret,.navbar-default .navbar-nav>.open>a:hover .caret,.navbar-default .navbar-nav>.open>a:focus .caret{border-top-color:#555;border-bottom-color:#555}.navbar-default .navbar-nav>.dropdown>a .caret{border-top-color:#777;border-bottom-color:#777}@media(max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#999}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .navbar-nav>li>a{color:#999}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.dropdown>a:hover .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-nav>.dropdown>a .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .navbar-nav>.open>a .caret,.navbar-inverse .navbar-nav>.open>a:hover .caret,.navbar-inverse .navbar-nav>.open>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}@media(max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#999}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.428571429;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{background-color:#eee}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;cursor:default;background-color:#428bca;border-color:#428bca}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager:before,.pager:after{display:table;content:" "}.pager:after{clear:both}.pager:before,.pager:after{display:table;content:" "}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.label[href]:hover,.label[href]:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.label-default{background-color:#999}.label-default[href]:hover,.label-default[href]:focus{background-color:#808080}.label-primary{background-color:#428bca}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;background-color:#999;border-radius:10px}.badge:empty{display:none}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.btn .badge{position:relative;top:-1px}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px;margin-bottom:30px;font-size:21px;font-weight:200;line-height:2.1428571435;color:inherit;background-color:#eee}.jumbotron h1{line-height:1;color:inherit}.jumbotron p{line-height:1.4}.container .jumbotron{border-radius:6px}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-right:60px;padding-left:60px}.jumbotron h1{font-size:63px}}.thumbnail{display:inline-block;display:block;height:auto;max-width:100%;padding:4px;margin-bottom:20px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.thumbnail>img{display:block;height:auto;max-width:100%;margin-right:auto;margin-left:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#428bca}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#356635}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#2d6987}.alert-warning{color:#c09853;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#a47e3c}.alert-danger{color:#b94a48;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#953b39}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-size:40px 40px}.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.media,.media-body{overflow:hidden;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{text-decoration:none;background-color:#f5f5f5}a.list-group-item.active,a.list-group-item.active:hover,a.list-group-item.active:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}a.list-group-item.active .list-group-item-heading,a.list-group-item.active:hover .list-group-item-heading,a.list-group-item.active:focus .list-group-item-heading{color:inherit}a.list-group-item.active .list-group-item-text,a.list-group-item.active:hover .list-group-item-text,a.list-group-item.active:focus .list-group-item-text{color:#e1edf7}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-body:before,.panel-body:after{display:table;content:" "}.panel-body:after{clear:both}.panel-body:before,.panel-body:after{display:table;content:" "}.panel-body:after{clear:both}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0}.panel>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.panel>.list-group .list-group-item:last-child{border-bottom:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.panel>.table,.panel>.table-responsive{margin-bottom:0}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive{border-top:1px solid #ddd}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:last-child>th,.panel>.table-responsive>.table-bordered>thead>tr:last-child>th,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th,.panel>.table-bordered>thead>tr:last-child>td,.panel>.table-responsive>.table-bordered>thead>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-group .panel{margin-bottom:0;overflow:hidden;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse .panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse .panel-body{border-top-color:#ddd}.panel-default>.panel-heading>.dropdown .caret{border-color:#333 transparent}.panel-default>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.panel-heading+.panel-collapse .panel-body{border-top-color:#428bca}.panel-primary>.panel-heading>.dropdown .caret{border-color:#fff transparent}.panel-primary>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse .panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading>.dropdown .caret{border-color:#468847 transparent}.panel-success>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#d6e9c6}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#c09853;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse .panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading>.dropdown .caret{border-color:#c09853 transparent}.panel-warning>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#b94a48;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse .panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading>.dropdown .caret{border-color:#b94a48 transparent}.panel-danger>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ebccd1}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse .panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading>.dropdown .caret{border-color:#3a87ad transparent}.panel-info>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#bce8f1}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:bold;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;display:none;overflow:auto;overflow-y:scroll}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.modal-dialog{position:relative;z-index:1050;width:auto;padding:10px;margin-right:auto;margin-left:auto}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);background-clip:padding-box}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1030;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{min-height:16.428571429px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.428571429}.modal-body{position:relative;padding:20px}.modal-footer{padding:19px 20px 20px;margin-top:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer:before,.modal-footer:after{display:table;content:" "}.modal-footer:after{clear:both}.modal-footer:before,.modal-footer:after{display:table;content:" "}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}@media screen and (min-width:768px){.modal-dialog{width:600px;padding-top:30px;padding-bottom:30px}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}}.tooltip{position:absolute;z-index:1030;display:block;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.top-right .tooltip-arrow{right:5px;bottom:0;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-bottom-color:#000;border-width:0 5px 5px}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);background-clip:padding-box}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{border-width:10px;content:""}.popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);border-bottom-width:0}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0;content:" "}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,0.25);border-left-width:0}.popover.right .arrow:after{bottom:-10px;left:1px;border-right-color:#fff;border-left-width:0;content:" "}.popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);border-top-width:0}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0;content:" "}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-left-color:#999;border-left-color:rgba(0,0,0,0.25);border-right-width:0}.popover.left .arrow:after{right:1px;bottom:-10px;border-left-color:#fff;border-right-width:0;content:" "}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;height:auto;max-width:100%;line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6);opacity:.5;filter:alpha(opacity=50)}.carousel-control.left{background-image:-webkit-gradient(linear,0 top,100% top,from(rgba(0,0,0,0.5)),to(rgba(0,0,0,0.0001)));background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,0.5) 0),color-stop(rgba(0,0,0,0.0001) 100%));background-image:-moz-linear-gradient(left,rgba(0,0,0,0.5) 0,rgba(0,0,0,0.0001) 100%);background-image:linear-gradient(to right,rgba(0,0,0,0.5) 0,rgba(0,0,0,0.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000',endColorstr='#00000000',GradientType=1)}.carousel-control.right{right:0;left:auto;background-image:-webkit-gradient(linear,0 top,100% top,from(rgba(0,0,0,0.0001)),to(rgba(0,0,0,0.5)));background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,0.0001) 0),color-stop(rgba(0,0,0,0.5) 100%));background-image:-moz-linear-gradient(left,rgba(0,0,0,0.0001) 0,rgba(0,0,0,0.5) 100%);background-image:linear-gradient(to right,rgba(0,0,0,0.0001) 0,rgba(0,0,0,0.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000',endColorstr='#80000000',GradientType=1)}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;margin-top:-10px;margin-left:-10px;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicons-chevron-left,.carousel-control .glyphicons-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-15px;margin-left:-15px;font-size:30px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after{display:table;content:" "}.clearfix:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important;visibility:hidden!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,tr.visible-xs,th.visible-xs,td.visible-xs{display:none!important}@media(max-width:767px){.visible-xs{display:block!important}tr.visible-xs{display:table-row!important}th.visible-xs,td.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-xs.visible-sm{display:block!important}tr.visible-xs.visible-sm{display:table-row!important}th.visible-xs.visible-sm,td.visible-xs.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-xs.visible-md{display:block!important}tr.visible-xs.visible-md{display:table-row!important}th.visible-xs.visible-md,td.visible-xs.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-xs.visible-lg{display:block!important}tr.visible-xs.visible-lg{display:table-row!important}th.visible-xs.visible-lg,td.visible-xs.visible-lg{display:table-cell!important}}.visible-sm,tr.visible-sm,th.visible-sm,td.visible-sm{display:none!important}@media(max-width:767px){.visible-sm.visible-xs{display:block!important}tr.visible-sm.visible-xs{display:table-row!important}th.visible-sm.visible-xs,td.visible-sm.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-sm{display:block!important}tr.visible-sm{display:table-row!important}th.visible-sm,td.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-sm.visible-md{display:block!important}tr.visible-sm.visible-md{display:table-row!important}th.visible-sm.visible-md,td.visible-sm.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-sm.visible-lg{display:block!important}tr.visible-sm.visible-lg{display:table-row!important}th.visible-sm.visible-lg,td.visible-sm.visible-lg{display:table-cell!important}}.visible-md,tr.visible-md,th.visible-md,td.visible-md{display:none!important}@media(max-width:767px){.visible-md.visible-xs{display:block!important}tr.visible-md.visible-xs{display:table-row!important}th.visible-md.visible-xs,td.visible-md.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-md.visible-sm{display:block!important}tr.visible-md.visible-sm{display:table-row!important}th.visible-md.visible-sm,td.visible-md.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-md{display:block!important}tr.visible-md{display:table-row!important}th.visible-md,td.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-md.visible-lg{display:block!important}tr.visible-md.visible-lg{display:table-row!important}th.visible-md.visible-lg,td.visible-md.visible-lg{display:table-cell!important}}.visible-lg,tr.visible-lg,th.visible-lg,td.visible-lg{display:none!important}@media(max-width:767px){.visible-lg.visible-xs{display:block!important}tr.visible-lg.visible-xs{display:table-row!important}th.visible-lg.visible-xs,td.visible-lg.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-lg.visible-sm{display:block!important}tr.visible-lg.visible-sm{display:table-row!important}th.visible-lg.visible-sm,td.visible-lg.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-lg.visible-md{display:block!important}tr.visible-lg.visible-md{display:table-row!important}th.visible-lg.visible-md,td.visible-lg.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-lg{display:block!important}tr.visible-lg{display:table-row!important}th.visible-lg,td.visible-lg{display:table-cell!important}}.hidden-xs{display:block!important}tr.hidden-xs{display:table-row!important}th.hidden-xs,td.hidden-xs{display:table-cell!important}@media(max-width:767px){.hidden-xs,tr.hidden-xs,th.hidden-xs,td.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-xs.hidden-sm,tr.hidden-xs.hidden-sm,th.hidden-xs.hidden-sm,td.hidden-xs.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-xs.hidden-md,tr.hidden-xs.hidden-md,th.hidden-xs.hidden-md,td.hidden-xs.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-xs.hidden-lg,tr.hidden-xs.hidden-lg,th.hidden-xs.hidden-lg,td.hidden-xs.hidden-lg{display:none!important}}.hidden-sm{display:block!important}tr.hidden-sm{display:table-row!important}th.hidden-sm,td.hidden-sm{display:table-cell!important}@media(max-width:767px){.hidden-sm.hidden-xs,tr.hidden-sm.hidden-xs,th.hidden-sm.hidden-xs,td.hidden-sm.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-sm,tr.hidden-sm,th.hidden-sm,td.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-sm.hidden-md,tr.hidden-sm.hidden-md,th.hidden-sm.hidden-md,td.hidden-sm.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-sm.hidden-lg,tr.hidden-sm.hidden-lg,th.hidden-sm.hidden-lg,td.hidden-sm.hidden-lg{display:none!important}}.hidden-md{display:block!important}tr.hidden-md{display:table-row!important}th.hidden-md,td.hidden-md{display:table-cell!important}@media(max-width:767px){.hidden-md.hidden-xs,tr.hidden-md.hidden-xs,th.hidden-md.hidden-xs,td.hidden-md.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-md.hidden-sm,tr.hidden-md.hidden-sm,th.hidden-md.hidden-sm,td.hidden-md.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-md,tr.hidden-md,th.hidden-md,td.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-md.hidden-lg,tr.hidden-md.hidden-lg,th.hidden-md.hidden-lg,td.hidden-md.hidden-lg{display:none!important}}.hidden-lg{display:block!important}tr.hidden-lg{display:table-row!important}th.hidden-lg,td.hidden-lg{display:table-cell!important}@media(max-width:767px){.hidden-lg.hidden-xs,tr.hidden-lg.hidden-xs,th.hidden-lg.hidden-xs,td.hidden-lg.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-lg.hidden-sm,tr.hidden-lg.hidden-sm,th.hidden-lg.hidden-sm,td.hidden-lg.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-lg.hidden-md,tr.hidden-lg.hidden-md,th.hidden-lg.hidden-md,td.hidden-lg.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-lg,tr.hidden-lg,th.hidden-lg,td.hidden-lg{display:none!important}}.visible-print,tr.visible-print,th.visible-print,td.visible-print{display:none!important}@media print{.visible-print{display:block!important}tr.visible-print{display:table-row!important}th.visible-print,td.visible-print{display:table-cell!important}.hidden-print,tr.hidden-print,th.hidden-print,td.hidden-print{display:none!important}}<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
    <xsl:output indent="yes" method="html"/>
    <xsl:include href="chrome.xsl"/>

    <xsl:template name="content">
        <script type="text/javascript" src="{$root}js/jquery.panzoom.js"></script>
        <script>
            $(document).ready(function () {
                $('#pan').css('width', jQuery(document).width() - 15);
                $('#pan').css('height', jQuery(document).height() - jQuery('#intro').height() - 15);
                $('#pan img').panZoom({
                    'directedit': true,
                    'debug':      false,
                    'zoom_step':  9
                });
                $('#pan img').panZoom('fit');
            });

            $(window).resize(function () {
                $('#pan').css('width', jQuery(document).width() - 15);
                $('#pan').css('height', jQuery(document).height() - jQuery('#intro').height() - 15);
                $('#pan img').css('width', jQuery('#pan').width());
                $('#pan img').css('height', jQuery('#pan').height());
            });
        </script>

        <div id="content">
            <div id="intro" style="font-size: 10px; white-space: normal;">
                The following actions are supported in this diagram:
                <ul>
                    <li>
                        <b>Zoom</b>, you can use the scrollwheel, or double-click,
                        to zoom in or out
                    </li>
                    <li>
                        <b>Move</b>, you can move around by dragging
                        the Diagram
                    </li>
                </ul>
            </div>

            <div id="pan" style="overflow: hidden"><img src="classes.svg" /></div>
        </div>
    </xsl:template>

</xsl:stylesheet>Abstract

Known issues
- Class inheritance diagram complains; should use new style
- Errors do not show
- File preview does not work
- Arrays do not have their array sign stripped when generating a url
- Linking to files in subdirectories does not work
- Inherited does not show
- design should be improved
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
  <xsl:output indent="yes" method="html" />
  <xsl:include href="chrome.xsl" />

  <xsl:template name="content">

    <div class="content">
      <h2>Welcome!</h2>
      This documentation was generated by <a href="http://www.phpdoc.org">phpDocumentor <xsl:value-of select="$version" /></a>.
    </div>
  </xsl:template>

</xsl:stylesheet>
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml"
    xmlns:dbx="http://phpdoc.org/xsl/functions"
    exclude-result-prefixes="dbx">
  <xsl:output indent="yes" method="html" />

  <xsl:template match="method/name">
    <h4 class="method {../@visibility}">
      <img src="{$root}images/icons/visibility_{../@visibility}.png" style="margin-right: 10px" alt="{@visibility}" title="{@visibility}"/>
      <xsl:value-of select="." />
      <div class="to-top"><a href="#{../../name}">jump to class</a></div>
    </h4>
  </xsl:template>

  <xsl:template match="function/name">
    <h3 class="function {../@visibility}">
      <img src="{$root}images/icons/visibility_{../@visibility}.png" style="margin-right: 10px" alt="{@visibility}" title="{@visibility}"/>
      <xsl:value-of select="." />
      <div class="to-top"><a href="#top">jump to top</a></div>
    </h3>
  </xsl:template>

    <xsl:template match="argument">
        <xsl:variable name="name" select="name"/>
        <tr>
            <th>
                <xsl:value-of select="$name"/>
            </th>
            <td>
                <xsl:if test="../docblock/tag[@name='param' and @variable=$name]/type">
                    <xsl:call-template name="implodeTypes">
                        <xsl:with-param name="items" select="../docblock/tag[@name='param' and @variable=$name]/type"/>
                    </xsl:call-template>
                </xsl:if>
            </td>
            <td>
                <em>
                    <xsl:value-of select="../docblock/tag[@name='param' and @variable=$name]/@description" disable-output-escaping="yes"/>
                </em>
            </td>
        </tr>
    </xsl:template>

  <xsl:template match="function|method">
    <a id="{../full_name}::{name}()" class="anchor" />
    <div>
        <xsl:attribute name="class">
            <xsl:value-of select="concat(name(), ' ', @visibility)" />
            <xsl:if test="inherited_from"> inherited_from </xsl:if>
        </xsl:attribute>

        <a href="#" class="gripper">
            <img src="{$root}images/icons/arrow_right.png" />
            <img src="{$root}images/icons/arrow_down.png" style="display: none;"/>
        </a>

        <code class="title"><img src="{$root}images/icons/{name()}.png" alt="{name()}" title="{name()}" /><xsl:if test="@visibility"><img src="{$root}images/icons/visibility_{@visibility}.png" style="margin-right: 5px" alt="{@visibility}"/></xsl:if><span class="highlight"><xsl:value-of select="name" /></span>
            <span class="nb-faded-text">(<xsl:for-each select="argument"><xsl:if test="position() &gt; 1">, </xsl:if><xsl:variable name="variable_name" select="name" /><xsl:call-template name="implodeTypes"><xsl:with-param name="items" select="../docblock/tag[@name='param' and @variable=$variable_name]/type" /></xsl:call-template>&#160;<xsl:value-of select="$variable_name" /><xsl:if test="default != ''"> = <xsl:value-of select="default" disable-output-escaping="yes" /></xsl:if></xsl:for-each>)</span> : <xsl:if test="not(docblock/tag[@name='return'])">void</xsl:if><xsl:apply-templates select="docblock/tag[@name='return']" />
        </code>

        <div class="description">
            <xsl:if test="@static='true'">
                <span class="attribute">static</span>
            </xsl:if>

            <xsl:if test="@final='true'">
                <span class="attribute">final</span>
            </xsl:if>

            <xsl:if test="@abstract='true'">
                <span class="attribute">abstract</span>
            </xsl:if>

            <xsl:if test="inherited_from">
                <span class="attribute">inherited</span>
            </xsl:if>

            <p class="short_description">
                <xsl:value-of select="docblock/description" disable-output-escaping="yes" />
            </p>

            <xsl:if test="inherited_from">
                <small class="inherited_from">Inherited from:
                    <xsl:if test="docblock/tag[@name='inherited_from']/@link">
                        <xsl:apply-templates select="docblock/tag[@name='inherited_from']/@link"/>
                    </xsl:if>

                    <xsl:if test="not(docblock/tag[@name='inherited_from']/@link)">
                        <xsl:value-of select="docblock/tag[@name='inherited_from']/@description" />
                    </xsl:if>
                </small>
            </xsl:if>
        </div>

        <div class="code-tabs">
            <xsl:apply-templates select="docblock/long-description"/>

            <xsl:if test="count(argument) > 0">
                <strong>Parameters</strong>
                <table class="argument-info">
                    <thead>
                        <tr>
                            <th>Name</th>
                            <th>Type</th>
                            <th>Description</th>
                        </tr>
                    </thead>
                    <xsl:apply-templates select="argument"/>
                </table>
            </xsl:if>

            <xsl:if test="docblock/tag[@name = 'return'] != '' and docblock/tag[@name = 'return']/@type != 'void'">
                <strong>Returns</strong>
                <table class="argument-info">
                    <thead>
                        <tr><th>Type</th><th>Description</th></tr>
                    </thead>
                    <tr>
                        <td>
                            <xsl:apply-templates select="docblock/tag[@name='return']"/>
                        </td>
                        <td>
                            <xsl:apply-templates select="docblock/tag[@name='return']/@description"/>
                        </td>
                    </tr>
                </table>
            </xsl:if>

            <xsl:if test="count(docblock/tag[@name = 'throws'])">
                <strong>Throws</strong>
                <table class="argument-info">
                    <thead>
                        <tr>
                            <th>Exception</th>
                            <th>Description</th>
                        </tr>
                    </thead>
                    <xsl:apply-templates select="docblock/tag[@name='throws']"/>
                </table>
            </xsl:if>

            <xsl:call-template name="doctrine" />

            <xsl:if test="docblock/tag[@name != 'param' and @name != 'return' and @name !='inherited_from' and @name != 'throws']">
                <strong>Details</strong>
                <dl class="function-info">
                    <xsl:apply-templates select="docblock/tag[@name != 'param' and @name != 'return' and @name !='inherited_from' and @name != 'throws']">
                        <xsl:sort select="dbx:ucfirst(@name)"/>
                    </xsl:apply-templates>
                </dl>
            </xsl:if>
        </div>
      <div class="clear"></div>
    </div>

  </xsl:template>

</xsl:stylesheet><?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml"
    xmlns:dbx="http://phpdoc.org/xsl/functions"
    xmlns:func="http://exslt.org/functions"
    extension-element-prefixes="func"
    exclude-result-prefixes="dbx">

    <!-- https://fosswiki.liip.ch/display/BLOG/How+to+define+your+own+XSLT+functions+with+EXSLT -->
    <func:function name="dbx:ucfirst">
        <xsl:param name="str"/>
        <xsl:param name="strLen" select="string-length($str)"/>
        <xsl:variable name="firstLetter" select="substring($str,1,1)"/>
        <xsl:variable name="restString" select="substring($str,2,$strLen)"/>
        <xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'"/>
        <xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
        <xsl:variable name="translate"
                      select="translate($firstLetter,$lower,$upper)"/>
        <func:result select="concat($translate,$restString)"/>
    </func:function>

    <xsl:template name="ucfirst">
        <xsl:param name="str"/>
        <xsl:param name="strLen" select="string-length($str)"/>
        <xsl:variable name="firstLetter" select="substring($str,1,1)"/>
        <xsl:variable name="restString" select="substring($str,2,$strLen)"/>
        <xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'"/>
        <xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
        <xsl:variable name="translate"
                      select="translate($firstLetter,$lower,$upper)"/>
        <xsl:value-of select="concat($translate,$restString)"/>
    </xsl:template>

        <!-- Concatenate items with links with a given separator, based on: http://symphony-cms.com/download/xslt-utilities/view/22517/-->
  <xsl:template name="implodeTypes">
    <xsl:param name="items" />
    <xsl:param name="separator" select="' | '" />

    <xsl:for-each select="$items">
      <xsl:if test="position() &gt; 1">
        <xsl:value-of select="$separator" />
      </xsl:if>

      <xsl:if test="@link">
        <a href="{$root}files/{@link}">
          <xsl:value-of select="." />
        </a>
      </xsl:if>
      <xsl:if test="not(@link)">
        <xsl:value-of select="." />
      </xsl:if>
    </xsl:for-each>
  </xsl:template>

    <xsl:template name="doctrine">
        <xsl:if test="count(docblock/tag[@plugin = 'doctrine']) > 0">
            <strong>Doctrine</strong>
            <table class="argument-info" style="font-size: 1.0em;">
                <thead>
                    <tr>
                        <th>Annotation</th>
                        <th>Field name</th>
                        <th>Value</th>
                    </tr>
                </thead>
                <xsl:for-each select="docblock/tag[@plugin='doctrine']">
                    <xsl:variable name="doctrine_row_class">
                        <xsl:if test="position() mod 2 = 0">odd</xsl:if>
                        <xsl:if test="position() mod 2 = 1">even</xsl:if>
                    </xsl:variable>

                    <xsl:if test="count(argument) = 0">
                        <tr class="{$doctrine_row_class}">
                            <td style="vertical-align: top; font-variant: small-caps; text-transform: lowercase; font-size: 1.3em">
                                <xsl:apply-templates select="@link"/>
                            </td>
                            <td></td>
                            <td></td>
                        </tr>
                    </xsl:if>

                    <xsl:for-each select="argument">
                        <tr class="{$doctrine_row_class}">
                            <xsl:if test="position() = 1">
                                <td rowspan="{count(../argument)}"
                                    style="vertical-align: top; font-variant: small-caps; text-transform: lowercase; font-size: 1.3em">
                                    <xsl:apply-templates select="../@link"/>
                                </td>
                            </xsl:if>
                            <td>
                                <xsl:value-of select="@field-name"/>
                            </td>
                            <td>
                                <xsl:value-of select="."/>
                            </td>
                        </tr>
                    </xsl:for-each>
                </xsl:for-each>
            </table>
        </xsl:if>
    </xsl:template>


  <xsl:template match="docblock/description[.!='']|docblock[description[.='']]/tag[@name='var']/@description">
    <div class="short-description">
      <xsl:value-of select="." disable-output-escaping="yes" />
    </div>
  </xsl:template>

  <xsl:template match="docblock/long-description">
    <div class="long-description">
      <xsl:value-of select="." disable-output-escaping="yes" />
    </div>
  </xsl:template>

  <xsl:template match="docblock/tag">
    <dt>
      <xsl:call-template name="ucfirst">
        <xsl:with-param name="str" select="@name" />
      </xsl:call-template>
    </dt>
    <dd>
        <xsl:choose>
            <xsl:when test="@link">
                <a>
                    <xsl:attribute name="href">
                         <xsl:if test="not(@name = 'license' or @name = 'link' or @name = 'author')">
                             <xsl:value-of select="$root"/>files/
                         </xsl:if>
                         <xsl:value-of select="@link" />
                    </xsl:attribute>
                    <xsl:value-of select="@description" disable-output-escaping="yes"/>
                </a>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="@description" disable-output-escaping="yes"/>
            </xsl:otherwise>
        </xsl:choose>
        &#160;
    </dd>
  </xsl:template>

    <!-- Any Doctrine related tag must not be shown in the details listing but
     is shown as a separate table -->
    <xsl:template match="docblock/tag[@plugin='doctrine']"/>

  <xsl:template match="docblock/tag[@name='var']|docblock/tag[@name='param']">
    <dt>
      <xsl:if test="@variable">
        <xsl:value-of select="@variable" />
      </xsl:if>
      <xsl:if test="@variable = ''">
        <xsl:value-of select="../../name" />
      </xsl:if>
    </dt>
    <dd>
      <xsl:if test="@type != ''">
        <xsl:apply-templates select="@type" /><br />
      </xsl:if>
      <em><xsl:value-of select="@description" disable-output-escaping="yes" /></em>
    </dd>
  </xsl:template>

  <xsl:template match="docblock/tag[@name='return']">
      <xsl:if test="type = ''">void</xsl:if>
      <xsl:if test="type != ''">
          <xsl:call-template name="implodeTypes">
              <xsl:with-param name="items" select="type" />
          </xsl:call-template>
      </xsl:if>
  </xsl:template>

  <xsl:template match="docblock/tag[@name='throws']">
      <tr>
        <td>
            <xsl:if test="type != ''">
                <xsl:call-template name="implodeTypes">
                    <xsl:with-param name="items" select="type" />
                </xsl:call-template>
            </xsl:if>
        </td>
        <td>
            <em><xsl:value-of select="@description" disable-output-escaping="yes" /></em>
        </td>
    </tr>
  </xsl:template>

  <xsl:template match="docblock/tag/@type">
    <xsl:if test="not(.)">n/a</xsl:if>
    <xsl:if test=".">
      <xsl:if test="../@link">
        <a href="{$root}files/{../@link}">
          <xsl:value-of select="." />
        </a>
      </xsl:if>
      <xsl:if test="not(../@link)">
        <xsl:if test=". = ''">void</xsl:if>
        <xsl:if test=". != ''"><xsl:value-of select="." /></xsl:if>
      </xsl:if>
    </xsl:if>
  </xsl:template>

  <xsl:template match="docblock/tag/type">
    <xsl:if test="not(.)">n/a</xsl:if>
    <xsl:if test=".">
        <xsl:call-template name="implodeTypes">
            <xsl:with-param name="items" select="."/>
        </xsl:call-template>
    </xsl:if>
  </xsl:template>

  <xsl:template match="docblock/tag/@link">
    <xsl:if test="not(../@description)">n/a</xsl:if>
    <xsl:if test="../@description">
      <xsl:if test="../@link">
        <a href="{$root}files/{../@link}">
          <xsl:value-of select="../@description" disable-output-escaping="yes"/>
        </a>
      </xsl:if>
      <xsl:if test="not(../@link)">
        <xsl:value-of select="../@description" disable-output-escaping="yes" />
      </xsl:if>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet><?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml"
    xmlns:dbx="http://phpdoc.org/xsl/functions"
    exclude-result-prefixes="dbx">

    <xsl:template match="property">
        <a id="{../full_name}::{name}" class="anchor"/>

        <div>
            <xsl:attribute name="class">
                <xsl:value-of select="concat(name(), ' ', @visibility)"/>
                <xsl:if test="inherited_from"> inherited_from </xsl:if>
                <xsl:if test="docblock/tag[@name='magic']"> magic </xsl:if>
            </xsl:attribute>

            <a href="#" class="gripper">
                <img src="{$root}images/icons/arrow_right.png" alt="&gt;"/>
                <img src="{$root}images/icons/arrow_down.png" alt="V" style="display: none;"/>
            </a>

            <code class="title">
                <img src="{$root}images/icons/property.png" alt="Property"/>
                <xsl:if test="@visibility"><img src="{$root}images/icons/visibility_{@visibility}.png" style="margin-right: 5px" alt="{@visibility}"/></xsl:if><xsl:if test="docblock/tag[@name='var']/@type"><xsl:apply-templates select="docblock/tag[@name='var']/@type"/>&#160;</xsl:if><span class="highlight"><xsl:value-of select="name"/></span><xsl:if test="default[.!='']"> = <xsl:value-of select="default"/></xsl:if>
            </code>

            <div class="description">
                <xsl:if test="@static='true'">
                    <span class="attribute">static</span>
                </xsl:if>

                <xsl:if test="@final='true'">
                    <span class="attribute">final</span>
                </xsl:if>

                <xsl:if test="inherited_from">
                    <span class="attribute">inherited</span>
                </xsl:if>

                <xsl:apply-templates select="docblock/description[.!='']|docblock[description[.='']]/tag[@name='var']/@description"/>
                <xsl:if test="inherited_from">
                    <small class="inherited_from">Inherited from:
                        <xsl:apply-templates
                                select="docblock/tag[@name='inherited_from']/@link"/>
                    </small>
                </xsl:if>
            </div>

            <div class="code-tabs">
                <xsl:apply-templates select="docblock/long-description"/>

                <xsl:if test="default != ''">
                <strong>Default value</strong>
                    <code>
                        <xsl:value-of select="default"/>
                    </code>
                </xsl:if>

                <strong>Details</strong>
                <dl class="property-info">
                    <dt>Type</dt>
                    <dd>
                        <xsl:if test="not(docblock/tag[@name='var']/type)">n/a</xsl:if>
                        <xsl:if test="docblock/tag[@name='var']/type">
                            <xsl:call-template name="implodeTypes">
                                <xsl:with-param name="items" select="docblock/tag[@name='var']/type"/>
                            </xsl:call-template>
                        </xsl:if>
                    </dd>
                    <xsl:apply-templates select="docblock/tag[@name!='var']">
                        <xsl:sort select="dbx:ucfirst(@name)"/>
                    </xsl:apply-templates>
                </dl>
            </div>
            <div class="clear"></div>
        </div>
    </xsl:template>

</xsl:stylesheet><?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml"
    xmlns:dbx="http://phpdoc.org/xsl/functions"
    exclude-result-prefixes="dbx">
  <xsl:output indent="yes" method="html" />

  <xsl:template match="file">
      <h1 class="file">
          <xsl:value-of select="@path" />
          <xsl:if test="source">
              <a href="{$root}source/{@path}.html" role="button" class="pull-right btn btn-default"><i class="fa fa-2x fa-code"></i></a>
          </xsl:if>
      </h1>

      <div id="file-nav-box">
          <div id="file-nav-options">
              Show:
              <img src="{$root}images/icons/visibility_public.png" alt="Public" id="show-public"/>
              <img src="{$root}images/icons/visibility_protected.png" alt="Protected" id="show-protected"/>
              <img src="{$root}images/icons/visibility_private.png" alt="Private" id="show-private"/>
              <span class="attribute" id="show-inherited">inherited</span>
          </div>

          <div id="file-nav-container">
              <ul id="file-nav">
                  <xsl:if test="constant">
                  <li>
                      <a href="#constants">
                          <img src="{$root}images/icons/constant.png" height="14" />
                          Constants
                      </a>
                      <ul>
                      <xsl:for-each select="constant">
                          <xsl:sort select="name" />
                          <li><a href="#::{name}"><xsl:value-of select="name"/></a></li>
                      </xsl:for-each>
                      </ul>
                  </li>
                  </xsl:if>

                  <xsl:if test="constant">
                  <li>
                      <a href="#functions">
                          <img src="{$root}images/icons/function.png" alt="Function" height="14"/>
                          Functions
                      </a>
                      <ul>
                      <xsl:for-each select="function">
                          <xsl:sort select="name"/>
                          <li><a href="#::{name}()"><xsl:value-of select="name"/></a></li>
                      </xsl:for-each>
                      </ul>
                  </li>
                  </xsl:if>

                  <xsl:if test="class">
                  <li>
                      <a href="#classes">
                          <img src="{$root}images/icons/class.png" alt="Class" height="14"/>
                          Classes
                      </a>
                      <ul>
                      <xsl:for-each select="class">
                          <xsl:sort select="full_name"/>
                          <li><a href="#{full_name}"><xsl:value-of select="full_name"/></a></li>
                      </xsl:for-each>
                      </ul>
                  </li>
                  </xsl:if>
              </ul>
              <div style="clear: left;"></div>
          </div>

          <div id="file-nav-tab">
              Table of Contents
          </div>
      </div>

      <a name="top" class="anchor"/>
      <xsl:if test="docblock/description|docblock/long-description">
          <div id="file-description">
              <xsl:apply-templates select="docblock/description"/>
              <xsl:apply-templates select="docblock/long-description"/>
          </div>
      </xsl:if>

      <xsl:if test="count(docblock/tag) > 0">
      <dl class="file-info">
          <xsl:apply-templates select="docblock/tag">
            <xsl:sort select="dbx:ucfirst(@name)" />
          </xsl:apply-templates>
      </dl>
      </xsl:if>

    <xsl:if test="count(constant) > 0">
    <a name="constants" class="anchor" />
    <h2>Constants</h2>
    <div>
      <xsl:apply-templates select="constant"/>
    </div>
    </xsl:if>

    <xsl:if test="count(function) > 0">
    <a name="functions" class="anchor" />
    <h2>Functions</h2>
    <div>
      <xsl:apply-templates select="function">
        <xsl:sort select="name" />
      </xsl:apply-templates>
    </div>
    </xsl:if>

    <xsl:if test="count(class) > 0">
    <a name="classes" class="anchor" />
    <xsl:apply-templates select="class">
      <xsl:sort select="name" />
    </xsl:apply-templates>
    </xsl:if>

    <xsl:if test="count(interface) > 0">
    <a name="interfaces" class="anchor" />
    <xsl:apply-templates select="interface">
      <xsl:sort select="name" />
    </xsl:apply-templates>
    </xsl:if>

  </xsl:template>

</xsl:stylesheet>
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml"
    xmlns:dbx="http://phpdoc.org/xsl/functions"
    exclude-result-prefixes="dbx">
    <xsl:output indent="yes" method="html"/>

    <xsl:template match="constant">
        <a id="{../full_name}::{name}" class="anchor"/>

        <div class="constant">
            <xsl:attribute name="class">
                <xsl:value-of select="concat(name(), ' publicC')"/>
                <xsl:if test="inherited_from"> inherited_from </xsl:if>
            </xsl:attribute>

            <a href="#" class="gripper">
                <img src="{$root}images/icons/arrow_right.png" alt="&gt;"/>
                <img src="{$root}images/icons/arrow_down.png" alt="V" style="display: none;"/>
            </a>

            <code class="title">
                <img src="{$root}images/icons/constant.png" alt="Constant"/>
                <xsl:value-of select="docblock/tag[@name='var']/type"/>&#160;
                <span class="highlight">
                    <xsl:value-of select="name"/>
                </span>
                = <xsl:value-of select="value"/>
            </code>

            <div class="description">
                <xsl:if test="inherited_from">
                    <span class="attribute">inherited</span>
                </xsl:if>

                <xsl:apply-templates select="docblock/description"/>
                <xsl:if test="inherited_from">
                    <small class="inherited_from">Inherited from:
                        <xsl:apply-templates select="docblock/tag[@name='inherited_from']/@link"/>
                    </small>
                </xsl:if>
            </div>

            <div class="code-tabs">
                <xsl:apply-templates select="docblock/long-description"/>

                <xsl:if test="docblock/tag">
                    <dl class="constant-info">
                        <xsl:apply-templates select="docblock/tag">
                            <xsl:sort select="dbx:ucfirst(@name)"/>
                        </xsl:apply-templates>
                    </dl>
                </xsl:if>
            </div>
            <div class="clear"></div>
        </div>
    </xsl:template>

</xsl:stylesheet><?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml"
    xmlns:dbx="http://phpdoc.org/xsl/functions"
    exclude-result-prefixes="dbx">
    <xsl:output indent="yes" method="html"/>


    <xsl:template match="class/extends|interface/extends">
        <xsl:if test="not(.)">n/a</xsl:if>
        <xsl:if test=".">
            <xsl:if test="@link">
                <a href="{$root}files/{@link}"><xsl:value-of select="."/></a>
            </xsl:if>
            <xsl:if test="not(@link)">
                <xsl:if test=". = ''">?</xsl:if>
                <xsl:if test=". != ''">
                    <xsl:value-of select="."/>
                </xsl:if>
            </xsl:if>
        </xsl:if>
    </xsl:template>

    <xsl:template name="class_inherit">
        <xsl:param name="class"/>
        <xsl:param name="depth"/>

        <a href="{concat($root, 'files/', $class/../@generated-path, '#', $class/full_name)}">
            <xsl:if test="$depth != 0">
                <xsl:attribute name="style">color: gray; font-size: 0.8em
                </xsl:attribute>
            </xsl:if>
            <xsl:value-of select="$class/full_name"/>
        </a>

        <xsl:variable name="parent" select="$class/extends"/>
        <xsl:if test="/project/file/*[full_name=$parent]">
            &lt;
            <xsl:call-template name="class_inherit">
                <xsl:with-param name="class"
                                select="/project/file/*[full_name=$parent]"/>
                <xsl:with-param name="depth" select="$depth+1"/>
            </xsl:call-template>
        </xsl:if>

        <xsl:if test="$parent != '' and not(/project/file/*[full_name=$parent])">
            &lt;
            <xsl:apply-templates select="$parent"/>
        </xsl:if>

    </xsl:template>

    <xsl:template match="class|interface">
        <a id="{full_name}" class="anchor"/>
        <h2 class="{name()}">
            <xsl:value-of select="full_name"/>
            <div class="to-top">
                <a href="#top">jump to top</a>
            </div>
        </h2>

        <div class="class">
            <small class="package"><b>Package: </b><xsl:value-of select="@package"/></small>
            <xsl:if test="docblock/description|docblock/long-description">
                <xsl:apply-templates select="docblock/description"/>
                <xsl:apply-templates select="docblock/long-description"/>
            </xsl:if>

            <dl class="class-info">

                <xsl:if test="implements">
                    <dt>Implements</dt>
                    <xsl:for-each select="implements">
                        <dd>
                            <xsl:if test="@link = ''">
                                <xsl:value-of select="."/>
                            </xsl:if>
                            <xsl:if test="@link != ''">
                                <a href="{$root}files/{@link}">
                                    <xsl:value-of select="."/>
                                </a>
                            </xsl:if>
                        </dd>
                    </xsl:for-each>
                </xsl:if>

                <xsl:if test="extends != ''">
                    <dt>Parent(s)</dt>
                    <dd>
                        <xsl:variable name="parent" select="extends"/>
                        <xsl:if test="/project/file/*[full_name=$parent]">
                            <xsl:call-template name="class_inherit">
                                <xsl:with-param name="class"
                                                select="/project/file/*[full_name=$parent]"/>
                                <xsl:with-param name="depth" select="0"/>
                            </xsl:call-template>
                        </xsl:if>
                        <xsl:if test="not(/project/file/*[full_name=$parent])">
                            <xsl:apply-templates select="$parent"/>
                        </xsl:if>
                    </dd>
                </xsl:if>

                <xsl:variable name="full_name" select="full_name"/>

                <xsl:if test="/project/file/*[extends=$full_name]">
                    <dt>Children</dt>
                    <xsl:for-each select="/project/file/*[extends=$full_name]">
                        <dd>
                            <a href="{concat($root, 'files/', ../@generated-path, '#', full_name)}">
                                <xsl:value-of select="full_name"/>
                            </a>
                        </dd>
                    </xsl:for-each>
                </xsl:if>

                <xsl:apply-templates select="docblock/tag[@name='see']"/>
                <xsl:apply-templates select="docblock/tag[@name != 'see' and @name != 'package' and @name != 'subpackage']">
                    <xsl:sort select="dbx:ucfirst(@name)"/>
                </xsl:apply-templates>
            </dl>

            <xsl:call-template name="doctrine"/>

            <xsl:if test="count(constant) > 0">
                <h3>Constants</h3>
                <div>
                    <xsl:apply-templates select="constant"/>
                </div>
            </xsl:if>

            <xsl:if test="count(property) > 0">
                <h3>Properties</h3>
                <div>
                    <xsl:apply-templates select="property">
                        <xsl:sort select="name"/>
                    </xsl:apply-templates>
                </div>
            </xsl:if>

            <xsl:if test="count(method) > 0">
                <h3>Methods</h3>
                <div>
                    <xsl:apply-templates select="method">
                        <xsl:sort select="name"/>
                    </xsl:apply-templates>
                </div>
            </xsl:if>
        </div>

    </xsl:template>

</xsl:stylesheet>
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
  <xsl:output indent="yes" method="html" />
  <xsl:include href="chrome.xsl" />

  <xsl:template name="content">
      <div id="content">

          <h1>Parsing errors</h1>
          <xsl:if test="count(/project/file/parse_markers) &lt; 1">
              <div class="alert alert-success">No errors have been found in this project.</div>
          </xsl:if>
        <div id="marker-accordion">
            <xsl:for-each select="/project/file">
                <xsl:if test="parse_markers">
                    <h3>
                        <a href="#{@path}">
                            <xsl:value-of select="@path"/>
                            <small><xsl:value-of select="count(parse_markers/*)"/></small>
                        </a>
                    </h3>
                    <div>
                        <table class="table">
                            <tr><th>Type</th><th>Line</th><th>Description</th></tr>
                            <xsl:for-each select="parse_markers/*">
                                <xsl:sort select="line"/>
                                <tr>
                                    <xsl:if test="name() = 'tag'">
                                        <td><xsl:value-of select="@name"/></td>
                                    </xsl:if>
                                    <xsl:if test="name() != 'tag'">
                                        <td><xsl:value-of select="name()"/></td>
                                    </xsl:if>
                                    <td><xsl:value-of select="@line"/></td>
                                    <xsl:if test="name() = 'tag'">
                                        <td>
                                            <xsl:value-of select="@description" disable-output-escaping="yes"/>
                                        </td>
                                    </xsl:if>
                                    <xsl:if test="name() != 'tag'">
                                        <td>
                                            <xsl:value-of select="." disable-output-escaping="yes"/>
                                        </td>
                                    </xsl:if>
                                </tr>
                            </xsl:for-each>
                        </table>
                    </div>
                </xsl:if>
            </xsl:for-each>
        </div>

    </div>
  </xsl:template>

</xsl:stylesheet>
<?xml version="1.0" encoding="utf-8"?>

<template>
  <author>Mike van Riel</author>
  <email>mike.vanriel@naenius.com</email>
  <description>This is a light theme for phpDocumentor that can be used as basis for other themes</description>
  <version>1.0.3</version>
  <transformations>
    <transformation writer="xml" artifact="structure.xml"/>
    <transformation query="copy" writer="FileIo" source="templates/abstract/images" artifact="images"/>
    <transformation query="copy" writer="FileIo" source="templates/abstract/css" artifact="css"/>
    <transformation query="copy" writer="FileIo" source="templates/abstract/js" artifact="js"/>
    <transformation query="" writer="xsl" source="templates/abstract/index.xsl" artifact="index.html"/>
    <transformation query="" writer="xsl" source="templates/abstract/sidebar.xsl" artifact="nav.html">
        <parameters>
            <variables>
                <section.dashboard.show>false</section.dashboard.show>
                <section.api.show/>
                <section.namespaces.show/>
                <section.packages.show/>
                <section.files.show/>
                <section.files.show-elements>false</section.files.show-elements>
                <section.reports.show>false</section.reports.show>
                <section.charts.show>false</section.charts.show>
            </variables>
        </parameters>
    </transformation>
    <transformation query="" writer="xsl" source="templates/abstract/report_markers.xsl" artifact="report_markers.html"/>
    <transformation query="" writer="xsl" source="templates/abstract/report_parse_markers.xsl" artifact="report_parse_markers.html"/>
    <transformation query="" writer="xsl" source="templates/abstract/report_deprecated.xsl" artifact="report_deprecated.html"/>
    <transformation query="" writer="xsl" source="templates/abstract/content.xsl" artifact="content.html"/>
    <transformation query="/project/file/@path" writer="xsl" source="templates/abstract/api-doc.xsl" artifact="files/{$path}"/>
    <!--<transformation query="" writer="sourcecode" source="" artifact=""/>-->
    <transformation query="" writer="xsl" source="templates/abstract/graph_class.xsl" artifact="graph.html"/>
    <transformation query="" writer="Graph" source="Class" artifact="classes.svg" />
  </transformations>
</template>
{
    "_readme": [
        "This file locks the dependencies of your project to a known state",
        "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
    ],
    "hash": "6496cbc6eea67b1407c0332a92bfedf3",
    "packages": [
        {
            "name": "phpdocumentor/unified-asset-installer",
            "version": "1.1",
            "source": {
                "type": "git",
                "url": "https://github.com/phpDocumentor/UnifiedAssetInstaller.git",
                "reference": "1.1"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phpDocumentor/UnifiedAssetInstaller/zipball/1.1",
                "reference": "1.1",
                "shasum": ""
            },
            "require-dev": {
                "composer/composer": "~1.0@dev",
                "phpunit/phpunit": "~3.7"
            },
            "type": "composer-installer",
            "extra": {
                "class": "\\phpDocumentor\\Composer\\UnifiedAssetInstaller"
            },
            "autoload": {
                "psr-0": {
                    "phpDocumentor\\Composer": [
                        "src/",
                        "test/unit/"
                    ]
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "description": "Asset installer for phpDocumentor",
            "homepage": "http://www.phpdoc.org",
            "keywords": [
                "assets",
                "installer",
                "plugins",
                "templates"
            ],
            "time": "2013-08-01 19:35:55"
        }
    ],
    "packages-dev": [

    ],
    "aliases": [

    ],
    "minimum-stability": "stable",
    "stability-flags": [

    ],
    "platform": {
        "ext-xsl": "*"
    },
    "platform-dev": [

    ]
}
PNG

   IHDR         a   bKGD   G   	pHYs        tIME.   AIDAT8˕NPkqn,I+u>!#n,1h%,SaVs5 d2d,w[}ֶk :2	A$@"MUGr]dF˱ArgVr4!D|,κIB i&`M ်MHHQlm	I &v>,QmON7(IpT0NSOPv~vf;2(	=k;D uSCH!=SP[
]L`YVw6fvjg:q    IENDB`PNG

   IHDR   d   <   ?   sRGB    bKGD      	pHYs        tIME5vt  pIDATx|y]Uop[d B@Pldlyؾ[?g?|Si'422URTJR|{[$AUsN9gZ5#.XoK'\۱d*p^8swΜpNڡAz/T"  # wޗ׀k	~%ݚu "{REt3 400_fd2Iַ~cO'8 ӀDQwOt3>-sQ;2ʮbKIh;u_{;tp?C  `T܉
Dt%US_+I~?+(H꿻 Zl pxH@G g0lcy.G	DUDXY<  ̆+2tޅn}/ Чy qKq$>3L8T8
f*x1	r9|#׊;vu<̳ 6
`Tpo+ d=	 *e̸bj(!t"GEe͞T۾; pTJV	pTTƸ	w*Ⓨ%ҙĎ
3a+p>? TPf.o]xk_^z1<hضGbgF*Ce:Vm[<p  JBJd\It {*tEG8M0b6| LݩUX&4KI@A{e@0x@>R	H! 0FGӻUup<e@T$绖JWWأj(p3}1â$$ (!%PWWRBz{ O:Ւu7COco>?6AV3HZAF˒uxČU^v0G3E/+$APE TJRJ	XJAJQiY}f3= 6=ꍀ l6<//gPԱh\.Nc*Ce*2IuA@CCY$2A}2S2DP J)(%,	$,e$lK!!./YּsgM%Pw% ?]u73!b4wnA_P	\
F Ϊc;d(Cf![SD@DK"RB+%?J`(JBY
`[^4al{_ w|T-Q@8)^¶nGy^haYr2bF,!T& .C0K0SLp#
l+KI%[JV
Җ,vUQǶ9۶7w/_+ .0 2 q)S4++jRLh)c=JoãTX	8	PkƇB\gB8
A1ʂXld	Ph%ɲ,H	Xn'N=7S%#C93aE4]n	Z5tŘ!5	i[YC7`h\g	*EH<R@|I-hP֊`?{Pt1SR܋_\ӵ|;JyGǩA@Rq6æ>LČʥb(f	 ?.-PN#IؘI/OeGCQ1ҔMY1syKUqjl'mʺ҇Rw_3VVC}=FgCшuUQi*ū8ݡm^എD{1AEs"Bq|/
ya4>ՇYёEI^h/#jh@MzT,yb=n *R%<
8guБ IMtm59GJv|leL:겴tk\"De謝h;`a-EH$paa4̄)I&qLbzw*ʌMd .XK׍3]U뵷ю?+5Ec~r\NX"FTb9x,ʸ	5m"m(1".&WI!Si0)B" EL&H!R*kQY]b\?~2jNF4^īO=ںu)Ն?#|-z]yYnߴ~-	@CqH%TpwL.c(hrx<dY!}d"v#PF#Pb7q#`EcLtwKZpmQ0A0-$|C/
%xӸc  };=ϛDD8β.":!BcL'^|a䂋ɧZ.V4>x̘"/V*4J%ah. hrA*괲lz!c3׉@dPH7MkDBDvAȱSyG> 
زeg	иL6gIB
c m?{&N0ٶ()08bbNCM"NPEET"Z(T5˴D0 E=!^Qg YU_aocr_D葞~t:Gwj^hV?pd+"[75`n xjɼ *׍([`<{y1Vϯ>G~vt׶-U[lSK{B̝8[v1̚ߵl[a'1;lesHcBfz;}w5#n%9c&p7pO6>*ѐ_Rto
mIV袋^|@RU^zd|o׮ǬZjQPx8sY=wgK8y fQ^1cKk֬/ZömL0wXɓ'v/7?M`4 _J2{~~~s.`fە d,z.{O=uj὿ܾ}ە!>F\}Zys)Ĵm7j/1b_tYa,%0(! C_lWjFv=Cn׆kJJh-<8hZq\b|~L.K137q/-XGyǃgzc
8*++^r%?3/ݻBBy!DMMMn޼5;e.޽{[
B"\ׅeY]vݥ.)!(~/~v掫e͟?U/[~0	±|O+:zzA I @؍+1Xnwh"18Lvp^<  Æ'k;^5b> W1[(VXaYΖeQPB@===3֯_\." Z\.k׮9 .F6Lٹse}}} "&"BbŊo566>?44= B >~ 7J9#c6!4}  a.櫮	Ð Ğ=[Do_/XxGM4}<'o2RH<	gѦ$Y[JIgmM%IR)/_ʂFc:;;gg2D"Ú3WJi\QQA7tӷD; rwΝ 8hѢ{n1@Dŋo>}c|\kh>{k}}s#Ѭ OfMpr`.R`L -K/l8,5!İ\#<XFDl0b 
|t
tPFvC"NDA@E撛 ^,#GF.q#af&.3q50;!`9y^ps0~p`X,",<re! 9!)hمY(+u %pH01Im{ɀGŵR
-ʑ)צB䑙1h	3SمcS)8y0ygg9h#1ðsuk@cLx+^*@JaGc(8xE-0`L`KeZk./\uuuE>,q{RPJ1B}}Y0[`*Nڀke@"Y`Р0F}KDI'KyI)qOம.y(`:,y뭿/ʞ0 cq)
)1FZZH%!B0w
0Ch#A <AlX(jCh$,B</W#Ȑo9"DB GȺu?9ctH bf)TT܏j$hܱVh45.bRu|  N[۷oP(@)5xA+̌H,h*]KDyd)4|?KTyc1 e*Ə8x lmv_ǻbı\IL@rQr[C1\||.7<B)ߠk#sb,K'KGX_uhY_3{{{g#!`)e!umRtXJxSA-g`GrCDU5cR#Cw~Yvɏ	<!s^\(uÃ> 3/	`{}'c۷ol[[Xck;vkjj}'!$EֿHRJZsEg3fx˲xk6Zy- Le8 c٪v4}d`fa`/v744+Ֆ֬Ys{PjkkWkO(j}8aڿ͛</d0I<( (N̼D=B̬FuY0xfΜysĒ%힦f͚Ry<@5UtԳn3u̴pi, @h_=Io[bƍcuX TƄPJ	$-`d P;RSL|SSӫX3S,:^.p9`766?k֬x<NUfͺ (&MK~w tY/#DB4_ȶ}'l9 <7Yn[[weMjTW79XfH(!k9ǡ !hZD
 }M<oi?%KW[anB L,àz	@2sK6]hx۶kkk;?ϧ7n܊?xťD)qcGm۾$pb3䪲ZZ~uyg+3dgw3;vСCSamm>+W^T<3f\gӦ{0gΧ8 'g;3?Yu?7iLvDcQ|/0С&m dG*S/|s,	z2#k>'[PJK?}+V=K'|7#S Fx58&t*$$FjP#aaؼ.s9̘݈>tEG .OQ?Z9h(e1C^ٺˍΙyM084y^ ?E+)
lC9/zɧW ?A! xeAgڦke"Tְm3{,AǊM[w8=޴w
m?=L<#?E\S@m4***pt7;ӿΞ;_wQy:}k!H:(#< bGwo,^T#qVRj)Q6☨>IXIu˞_{XIgCTv_GSjZq~ [Ĝdri۶ڗ=򁃽oM:#?8$F2(ؿ !${/i@N>ENy_xޜyawPB.P|xo #8C>qփ_?gɅ{1,i@dNqcU"B~RT)^1JӧyڱWrwOzf0;)BJ
-^V@ -<˾oAwO/ǂ跈 )qo-휥Ti5L+.m\S:kE)@z/yoo<ѓ_GWS9[)</ynw((˾+|]C/]r(^ 3/O    IENDB`PNG

   IHDR         a   tEXtSoftware Adobe ImageReadyqe<  IDATxڤKLQ<vhK1@D0X,H	qc\pgtڕF!nl`HѦTlyZ*#t:B;0Kdns{.eYkҙZ:BΘD4K4E+N(Po`XX`JwoJ'V㡛#ѱgO:p\Dݸ0;P{(((j[ZػcCFR?#%0|=ub`!Dl[[V]@wS${<v4Tu\9'@nގ=`}'!	V u UM^MІ	(	HCG9Mv!h,LLVA
&?HL)ą
/3ɢ &%R1ـ WĦL9۹:YZi9LD`AuɆqŶCHi
ӱ%_ MrS_'&M/xy8mn e&Tȩή`i	+ EF
*YEbb"k`6hkyi>>oAQPs嬴O˛OD޼Au^? 9r    IENDB`PNG

   IHDR         a   sRGB    bKGD      	pHYs        tIME_.  IDAT8˥S=`~|$`F?С?PނSKNRGtE$^PP]P @d#oN7೜p<C88H\aYpΑ$	$Is؝oT*\.XӴ'bq1$IfA)(Ps(]Ki^P( E8nR
QA)  nl6τj48i,ː$)$Q(.Z Ze^XI@IBe,,N\ïRA IEab2s4V@&Is9h4EJN}y,+,˘N mPH\A~ò,Ȳ0fhu4Mx0Wz$iڋlnG]uvRR<eFѽۜ    IENDB`PNG

   IHDR         a   gAMA  7   tEXtSoftware Adobe ImageReadyqe<   IDATxb?%  ( D ĂK%1H#	]3: y@M&@) P b	ga @}s., @ ȦƟfx{ ~u 9 g ~!NŪ p?J?U@ tϿO_0: gpV8  FJ@ Qb b  Mte |    IENDB`PNG

   IHDR         a   gAMA  7   tEXtSoftware Adobe ImageReadyqe<  IDAT8ˍ=OP)C0[!k_@ @

&~@[%C
*UAVJ;dB,@l_رo}nqHP=<>. ]D\cn?/ 8FNq$ɷAIP0Hɦi²,0iDQdAJ|mTU&2t]$ILPT@IMIP[5AJ(Je%6O(~0[dāa(*yUtOлM̾_
^I
P%4UUoVNcc_E{v_B|NuXתA"*kfB"_0-K?6љc.oal7.`Z:g|)bbܬ*āG
å2Da.a<gɏ^f$VuZAm{ToY7AA{:;r{ЁK_p-pdQ>2A$tC ʘ?    IENDB`GIF89a   jlbAԽ|9tmp|_,      ;X%ܬPƤ7i4e'E j
dq 56p1tJU$  ;PNG

   IHDR         a   sRGB    bKGD      	pHYs        tIME&s"  |IDAT8˅OlLQΛԤLjCkJYV]  $D,!DN$,6AXI"HFjռk˂ι!AWkYӴ!=?pSr7N'Gj.ZVsYoGxL]Yï;9*d6x;<[*Z 1`Cp.9VtY~K@BTydkO'

ن !H NyhkH574~_*ZPL:O0XUjã<y}lCjteiXD|Aʑ<,)AGZ-$fL	eMTب|1b݄ʸه6mm3I4q߱H;L+7(6D&A%,]
CcHaP)3p8bQkq*7OzGW		qR`+ 9+Ր{Q '(7<*΂SҞvwA;xxz^;pͳ+qs6uRUԉ/M\0=6v4MfJTXY,b:xL#D[V-aNmj	CcQ{j~J,ϔ    IENDB`PNG

   IHDR         a   sRGB    bKGD      	pHYs        tIME\s  IDAT8˕˫RQ-# H"AA"Ms05# ΤfgR"&MAc}IO#wM6k>ZD4"pn?T*դlCҌ[!Fb$Ih4.L
gA4pX/WշT*<@~p\D"!t:l9%f(wçD"qf J)TUjzzsx^||r6E(c2R`0PӴL1 ctlA;^J)L&Ǜk 5UUJ't:Aj$It:p\.ZÎ(`AE8VzodY~' f3v;-~V}nNZx<vh4Yohnhf=+:&Ji>v:
9G ȴ    IENDB`PNG

   IHDR         a  
MiCCPPhotoshop ICC profile  xڝSwX>eVBl "#Y a@Ņ
VHUĂ
H(gAZU\8ܧ}zy&j 9R<:OHɽH g  yx~t?o  p.$P&W   "R .T  Sd
   ly|B"  I> ة آ  (G$@ `UR, @".Y2G vX@` B,  8 C L0ҿ_pH ˕͗K3w!lBa)f	"#HL  8?flŢko">! N_puk[ V h]3	Z
zy8@P<
%b0>3o~@z q@qanvRB1n#ǅ)4\,XP"MyRD!ɕ2	w ONl~Xv @~- g42y  @+ ͗  \L  D*AaD@$<B
AT:18\p`	Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut }c1fa\E`X&cX5V5cX7va$^lGXLXC%#W	1'"O%zxb:XF&!!%^'_H$ɒN
!%2IIkHH-S>iL&m O:ňL	$RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t	݃EЗkwHb(k{/LӗT02goUX**|:V~TUsU?yTU^V}FUP	թU6RwRPQ__cFHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ!{--?-jf~7zھbrup@,:m:u	6Qu>cy	Gm7046l18c̐ckihhI'&g5x>fob4ek<abi2ۤĤ)͔kfѴt,ܬج9՜kaټEJ6ǖږ|MV>VyVV׬I\,mWlPW:˶vm))Sn1
9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/>B	Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$	=sl3Ttcܢ˞w<Y5Y|8? BP/OnM򄛅OEQJ<V8;}ChOFu3	OR+y#MVDެq-9Ri+0(Of++ym#slLѣRPL/+x[[xHHZ3f#|PظxY"E#Sw.1]Rdxi}h˲PXRUjyRҥC+W4nZcadUj[V*_pFWN_|ymJHnYJjAІ_mJtzjʹ5a5[̶6z]V&ֿw{;켵+xWkE}nݏb~ݸGwOŞ{{Ejtolܯ	mR6H:p囀oڛwpZ*A'ߦ|{PߙHy+:u-m=茣^G~1cu5W(=䂓dN?=ԙyLk]Q]gCϞ?tL_]p"b%K==G~pH[oeW<tM;js.]yn&%vw
L]zxem``Y	ӇGG#F#dΓ᧲~VysKXϿyr﫩:#y=}ǽ(@PcǧO>|/%ҟ3   bKGD      	pHYs        tIME&z;n7  IDAT8}Oh\UΛLf$iJ@Oc)PE4)hB.qeE((,?(DM6ЖhH$޻{\$.z79s8<}@p+HNո8Sᩱ[bv{iOqo}776jf;<S۾5\oˊAFs)r1nˉ7Ym3p@Q*#.{.~ʅnC'iyqO'̐d:AQA~Bׯ w?}XHfHGF##nlp{ Y3뻳{͕(u1QQD!Fn./5`pk Q(#h:3-G_>WϜ=!
"F"D1b!(PI>s"RWe=Q H\Q+h_ZX[΋fP=G@ Y3Wz8OMBLr4"Q༫7VfsKso[\#I̼X1ɻ"u+ձ'CuZ:-TA5Uj4⫞ol)齯&95^:3M`prJ2{W-f=F3%8<ZP)ϲȗ~b    IENDB`GIF89a   Zx➭s-҃h$Ç4,      7H`KPl\:pL)e9@\ "l:+PB ;         h     (                                    ǷZpGc6c6c6c6c6c6c6c6c6c6c6c6pGǷZpGc6c6c6c6c6c6c6c6c6c6c6c6c6c6pGnDЬӱѮΩŘ{}Xc6c6rIʡj?wPЬuNc6c6mCog;wPΨ˼\c6g}XЫƛ~c6c6c6c6lc6c6c6~YxQc6ƛ~c6c6c6c6c6lc6c6c6c6ɺf:ʻǜc6c6c6c6c6lc6c6c6c6Ьӱ\gүh<c6c6c6lc6c6c6c6׷]c6e9h<d7c6c6c6lc6c6c6d7غc6c6c6c6c6c6c6c6lc6c6j?׷h<c6c6c6c6c6c6c6c6ʺѭǛˣүkd7c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6i>ˣc6c6c6c6c6c6c6c6c6c6c6c6c6c6i>ėyc6c6c6c6c6c6c6pGc6c6c6c6c6c6tKic6c6c6c6c6c6pGǷZpGc6c6c6c6c6c6c6c6c6c6c6c6pGǷZ                                                            PNG

   IHDR         a   gAMA  7   tEXtSoftware Adobe ImageReadyqe<  IDATxb?%  X@jtd1- b V3@|^ @,hYh8Hq0}_:~܍խi  d
"lդYf`̌\:r|;_:u* b9R_B POAFF2U &Yπ{_0,Y鳗lNN._10p
pk>yN f//m?,ZP-W`Lmdh25ffa		^h  *l h.fSN+`af@ ;&P Pe@_A0 @@Ͽ @ :/@3ATZ;(4i `͗o@[``c% ޶Hh/MX /eud4yW/X`P5?~~T @0]p kH 
w?|tWϞτ%i BN]mM1I	^^n6Px|׳/>_tKfxR g7 Hiv0 dG32    IENDB`GIF89a   𵵶ݺ         !   ,       EI8[s/f,^	W\߄xh%@[1	J 3@hHW" ;PNG

   IHDR         a   gAMA  7   tEXtSoftware Adobe ImageReadyqe<  IDATxb?%  X@Ld1 b օ]@ @,hȨTI
3001|<?{N˷f4 遺vTxظW& U$8x޺[! sj??~o o@l*B|P2 >r<`;CE\ /C?.2|BVʟ. AOhw߀tq_ _ɉ~cd-9P 3 ,@?;+0>/=>3|ҿ1\\=  d`蒿@#~c🁑/x_xp	H'@Fg?X`  n}WW>mh+(:A_hb  [Nܾq7wM%W@A՗GBS%@ ̓7o:ߺ:AMI?k0]`|>%i BN3o=zӇRIY.e^&v`_@߅j'e B3?|~L  @fg  4    IENDB`PNG

   IHDR         a  
MiCCPPhotoshop ICC profile  xڝSwX>eVBl "#Y a@Ņ
VHUĂ
H(gAZU\8ܧ}zy&j 9R<:OHɽH g  yx~t?o  p.$P&W   "R .T  Sd
   ly|B"  I> ة آ  (G$@ `UR, @".Y2G vX@` B,  8 C L0ҿ_pH ˕͗K3w!lBa)f	"#HL  8?flŢko">! N_puk[ V h]3	Z
zy8@P<
%b0>3o~@z q@qanvRB1n#ǅ)4\,XP"MyRD!ɕ2	w ONl~Xv @~- g42y  @+ ͗  \L  D*AaD@$<B
AT:18\p`	Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut }c1fa\E`X&cX5V5cX7va$^lGXLXC%#W	1'"O%zxb:XF&!!%^'_H$ɒN
!%2IIkHH-S>iL&m O:ňL	$RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t	݃EЗkwHb(k{/LӗT02goUX**|:V~TUsU?yTU^V}FUP	թU6RwRPQ__cFHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ!{--?-jf~7zھbrup@,:m:u	6Qu>cy	Gm7046l18c̐ckihhI'&g5x>fob4ek<abi2ۤĤ)͔kfѴt,ܬج9՜kaټEJ6ǖږ|MV>VyVV׬I\,mWlPW:˶vm))Sn1
9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/>B	Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$	=sl3Ttcܢ˞w<Y5Y|8? BP/OnM򄛅OEQJ<V8;}ChOFu3	OR+y#MVDެq-9Ri+0(Of++ym#slLѣRPL/+x[[xHHZ3f#|PظxY"E#Sw.1]Rdxi}h˲PXRUjyRҥC+W4nZcadUj[V*_pFWN_|ymJHnYJjAІ_mJtzjʹ5a5[̶6z]V&ֿw{;켵+xWkE}nݏb~ݸGwOŞ{{Ejtolܯ	mR6H:p囀oڛwpZ*A'ߦ|{PߙHy+:u-m=茣^G~1cu5W(=䂓dN?=ԙyLk]Q]gCϞ?tL_]p"b%K==G~pH[oeW<tM;js.]yn&%vw
L]zxem``Y	ӇGG#F#dΓ᧲~VysKXϿyr﫩:#y=}ǽ(@PcǧO>|/%ҟ3   bKGD      	pHYs        tIME&P  IDAT8}kG3{ssosMjBRTP[Zčv#bݸu!..tU V;7I͇Ixg9]܏.ss0f}	^}5_\>r򞝚XXK۩_>x]߇*;3ڊRiqw޻pqu?=?S6é|>yb[	zWb8DE^gnN G?|bDu؊V\cخ =izYs!"FJl!F=et/ifD=5A !L͡=i;;rT#Ah )	w7bZ&.+݂@nkjFkRCiKn66-Iܟ	rKsK%QC+{yOTTg75+pACTQ3>D%O2&0SOoXơFVoq=ʮҍƧ7~厙~>usqu_ј5Otu[\t|GۍsM~ԕ$HRk/I    IENDB`PNG

   IHDR         a   gAMA  7   tEXtSoftware Adobe ImageReadyqe<  IDATxb?%  X@ĄPFd1U 6b] =@|o @,hzF%X
Iq0˟]~n/T pMSPadeOCV@R@㼰̹` ny*,c/? /ÿ_@WGJKVQ)U `h	tO&o00#ßL|zpb  "<3Ue8s)X~ABW 3@WL%^4ÙKOL4|G88a1@L !&ZB>õo4ϯ `</~f0Q`Ã~`#3>6 f7|`O}`0Vegа^m??^z fVW&зafx`͠ӧ7oJ %w- ,$geȫ!aa>ßw| 3>|t̵+Ϟ=_ K wٽ[F"|,Woo޸y9D3<)z^ͻ@LTf b4; -)oyp    IENDB`PNG

   IHDR         a   gAMA  7   tEXtSoftware Adobe ImageReadyqe<  IDATxb?%  X@27md1- b V3@|F @,h)9{pKp001+wwn:ܳwխi  dٸ8wFV66~AVI-A~~^kKݾpf@ 1b\/?@B3on^n=]1QtW fw''3ß303ӷO0/!4 n	i2pa֣\b(pdؾg|,X8D8y< `.Pafaeb>2$X1dh3-kÐm)0i1qi.F66X<};x1h2p )  `_gThwbATǏ_д @0μ{Ïo CA6} %7&, b%e`JԒМlf@|OpՇwx `.vk
oP@__~>PLX 䔸֩<PVT0͏_o޿|ރ5Ó2@ u/=De&  FJ3@ A    IENDB`PNG

   IHDR         Ĵl;   	pHYs       
OiCCPPhotoshop ICC profile  xڝSgTS=BKKoR RB&*!	J!QEEȠQ,
!{kּ>H3Q5B.@
$p d!s# ~<<+" x M0B\t8K @zB @F&S  `cb P- `' { [!  eD h; VE X0 fK9 - 0IWfH    0Q) { `##x  FW<+*  x<$9E[-qWW.(I+6aa@.y24  x6_-"bbϫp@  t~,/;m%h^uf@ Wp~<<EJB[aW}g_Wl~<$2]GLϒ	bG"IbX*QqD2"B)%d,>5 j>{-]cK'Xt  o(hw?G% fIq  ^D$.Tʳ?  D*A,`6B$BB
dr`)B(Ͱ*`/@4Qhp.U=pa(	Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F; 2G1Q=C7Fdt1r=6Ыhڏ>C03l0.B8,	c˱"VcϱwE	6wB aAHXLXNH $4	7	Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![
b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGwǈg(gwLӋT071oUX**|
J&*/TުUUT^S}FU3S	ԖUPSSg;goT?~YYLOCQ_ cx,!ku5&|v*=9C3J3WRf?qtN	(~))4L1e\kXHQG6EYAJ'\'GgSSݧ
M=:.kDwn^Loy}/TmGX$<5qo</QC]@Caaᄑ<FFi\$mmƣ&&!&KMMRM);L;L֙͢5=12כ߷`ZxZ,eIZYnZ9YXUZ]F%ֻNNgðɶۮm}agbgŮ}}=Z~sr:V:ޚΜ?}/gX3)iSGggs󈋉K.>.ȽJtq]zۯ6iܟ4)Y3sCQ?0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz %gA[z|!?:eAAA!h쐭!ΑiP~aa~'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl{/]py.,:@LN8A*%w%
yg"/6шC\*NH*Mz쑼5y$3,幄'LLݛ:v m2=:1qB!Mggfvˬen/kY-
BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9<qy
+V<*mOW~&zMk^ʂkU
}]OX/Yߵa>(xoʿܔĹdff-[nڴVE/(ۻC<e;?TTTT6ݵan{4[>ɾUUMfeI?m]Nmq#׹=TR+Gw-6U#pDy	:v{vg/jBFS[b[O>zG4<YyJTiӓgό}~.`ۢ{cjotE;;\tWW:_mt<Oǻ\kz{f7y՞9=ݽzo~r'˻w'O_@AC݇?[jwGCˆ8>99?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-   gAMA  |Q    cHRM  z%        u0  `  :  o_F  IDATxԕLu<y?,=%0[МDY`nYV+[Y1q,Aiz(T;A{q`q24}~2D{Q2ܣb70U>E$Q^㥵u7Lw9;ޮY3"KY|   ;gڲH/XEm
v2^N%(B-sB>w}3Ύ0N; dH3)Amu=8TJR@umЬ'tLuG:_j n/B3S&/#) Rr252C
WOeV4ƺs$Dc'7C܎/!) ҖTt2'uۖN	U*Ǭ,byw$D:xlzja&"O`ܿHowAeb2ө"J'蜺;Vfsc$k:q\ik6ug CCH9/8m,gsBP%<N@+clտse	h?ܬjNAOD0D]9<nYU}9'0jE&0Bz	.Mto
'١T(Dg4+:wCE᷌:kE։"nV"~llC_v˒e7*؝B&0[SJ>hZ8q}r贵9\l2nv^;z>z
;3c2p+vcƨgQyͳNl0U_Yyr2~>IvĺdS's5=3  Qp\{    IENDB`PNG

   IHDR         a   gAMA  7   tEXtSoftware Adobe ImageReadyqe<  IDATxb?%  X@D}- 	@  >`
lf  4l<-8X٘|7w>|ܝ{wխi  d}u99b`U]MEP[cR.1 `ζ3.Гec/߿?@4 Nc-sIQtW gov~gbHmfPgq!  Cqx\\Ljr_?5 DTBo?3 -,05A]\a²e߿gc2@ Paaee詨3|yUax%##Ï!  O!?o31|?y Oop`=}ԅ_=dHgxs7/_~A@ 8P5UE1	goO0gd
t?`ghb  :p~`d##~{ы硩 `.v歩<RF
|?_c
O<מә$@)qɳ'>y*o !Ïzk}z69)z^X@LTf b4; B
,f7    IENDB`PNG

   IHDR           szz   	pHYs       
OiCCPPhotoshop ICC profile  xڝSgTS=BKKoR RB&*!	J!QEEȠQ,
!{kּ>H3Q5B.@
$p d!s# ~<<+" x M0B\t8K @zB @F&S  `cb P- `' { [!  eD h; VE X0 fK9 - 0IWfH    0Q) { `##x  FW<+*  x<$9E[-qWW.(I+6aa@.y24  x6_-"bbϫp@  t~,/;m%h^uf@ Wp~<<EJB[aW}g_Wl~<$2]GLϒ	bG"IbX*QqD2"B)%d,>5 j>{-]cK'Xt  o(hw?G% fIq  ^D$.Tʳ?  D*A,`6B$BB
dr`)B(Ͱ*`/@4Qhp.U=pa(	Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F; 2G1Q=C7Fdt1r=6Ыhڏ>C03l0.B8,	c˱"VcϱwE	6wB aAHXLXNH $4	7	Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![
b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGwǈg(gwLӋT071oUX**|
J&*/TުUUT^S}FU3S	ԖUPSSg;goT?~YYLOCQ_ cx,!ku5&|v*=9C3J3WRf?qtN	(~))4L1e\kXHQG6EYAJ'\'GgSSݧ
M=:.kDwn^Loy}/TmGX$<5qo</QC]@Caaᄑ<FFi\$mmƣ&&!&KMMRM);L;L֙͢5=12כ߷`ZxZ,eIZYnZ9YXUZ]F%ֻNNgðɶۮm}agbgŮ}}=Z~sr:V:ޚΜ?}/gX3)iSGggs󈋉K.>.ȽJtq]zۯ6iܟ4)Y3sCQ?0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz %gA[z|!?:eAAA!h쐭!ΑiP~aa~'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl{/]py.,:@LN8A*%w%
yg"/6шC\*NH*Mz쑼5y$3,幄'LLݛ:v m2=:1qB!Mggfvˬen/kY-
BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9<qy
+V<*mOW~&zMk^ʂkU
}]OX/Yߵa>(xoʿܔĹdff-[nڴVE/(ۻC<e;?TTTT6ݵan{4[>ɾUUMfeI?m]Nmq#׹=TR+Gw-6U#pDy	:v{vg/jBFS[b[O>zG4<YyJTiӓgό}~.`ۢ{cjotE;;\tWW:_mt<Oǻ\kz{f7y՞9=ݽzo~r'˻w'O_@AC݇?[jwGCˆ8>99?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-   gAMA  |Q    cHRM  z%        u0  `  :  o_F  IDATx̗mlE{Σ/^/GE[
	F(񃆐cŨQD>Q%& Q	Fmy	+zngٖQqg?B),"Z7nzܟS`"!Q&hlml >(IJ;MO֚@h潮"Y+0BIRa$ 0]1"M.#(	JP*yom29C C-Oh@wa( 2؀YeD0>dB[y ͠aáHVr8ㅰbb9԰^Bo5D>7^i>5*&?eؐ*94tӡKK	TυxB}fVzv;*)@P=8Gfͪ ~\]KjJ5>r
[MLcB8Ƣ۶-\6@BqrlYb\킜|E)p; 7-567";>22a(N̊gtVa;tm"}YsY\/w)԰$>ıG	ijϊGVSMy`	J~̧ŷmԀgwx4iQͿ@B$͑1H%,:?g[Ntx yyلC9+;г_)#Jy3e%s'ct*d9.]
S3{9W``};:>Ƭy.AvM5lq<?YC7㤝E7k61x}=uDrXd#Es#arl%.4]/
ӯSqs_IeW[ RESYN2ByT"t\ZgIu1oq#鸑`4LR5.:JIvInJ&n(
{ 2)4M|n=%ӆR}0HɸqoDZTfT
0zgeAKK2!F80=̈́ZGM0\")S({0%J)&˃iԕ_!4Q<.X5LXZ1OK։)SHÆ$۾㦝 vvf    IENDB`PNG

   IHDR         a   bKGD   G   	pHYs        tIME^  @IDAT8˕JA	>Iԏz ?YD>T#$~-+{ϙswX,ow σ rUKB` Hq<e=uwyq8o)r!dW~;FD%(-C@* b<
@BQ|S	ٌ f0Cp'yjVޒy6n@g<g8Ph67Z:PCJRb@vc_G&rF0Xkcr\X 
DkTjʶ1&)8il"PI5    IENDB`GIF89a       遁YYY'''!!!ܰfff333                                          !   ,       I `Q@*@+@Bn9DĐnB1ȵ
 xXI=޲m[Ր  ;OTTO 	   CFF  A  X  .OS/2n      `cmap8M:    thead       6hhea      $hmtxl  0  maxpP       nameSo  `  Ypost} Z  8           &]_<      T0    Ν#                                ~  P      3   3  s Z3                            pyrs @                                                   $                5               Q G              	 
           	   2   	     	    	  "  	     	  $;  	     	  _  	    	 	   	  *-SIL Open Font License 1.1FontAwesomeFONTLAB:OTFEXPORTVersion 4.0.2 2013Please refer to the Copyright section for the font trademark attribution notices.Fort AwesomeDave Gandyhttp://fontawesome.io S I L   O p e n   F o n t   L i c e n s e   1 . 1 F o n t A w e s o m e R e g u l a r F O N T L A B : O T F E X P O R T V e r s i o n   4 . 0 . 2   2 0 1 3 P l e a s e   r e f e r   t o   t h e   C o p y r i g h t   s e c t i o n   f o r   t h e   f o n t   t r a d e m a r k   a t t r i b u t i o n   n o t i c e s . F o r t   A w e s o m e D a v e   G a n d y h t t p : / / f o n t a w e s o m e . i o           "          "                                                                                                                                                                         	                                                                                 R   N @        !"""`>N^fin~'(.>N^n~         !"""` !@P`gjp  ()0@P`p   [QAޔQ	       L                         6                                                    
  p   v    _                      ]                             y n                       2                           @                                                                                              z                 5 u                                @    5 5                                          5 5          @                                                                   ,                                                                           f                                @                    @                        (                                                  @      @        -   M M -  M M                                                    @  @  -                 b                                                           5                                           -            8                                   @                  N           @                               *     @                                                           z Z                      FontAwesome D G U6 U6    T{       " , 0 4 < > E G M T \ _ e h m q y }                  #)4>HT_lp{
'4=GRYfoy&,39COVcoz"/5;FPUZes}&+16<EOW_hmqv|)04=DPX\aju(,26GYhy%16;>EMUckox				$	5	G	V	g	l	p	v													




&
*
-
0
3
6
9
<
?
B
F
O
_
c
u












 &5BQafmty !%)-159=AZeglassmusicsearchenvelopeheartstarstar_emptyuserfilmth_largethth_listokremovezoom_inzoom_outoffsignalcogtrashhomefile_alttimeroaddownload_altdownloaduploadinboxplay_circlerepeatrefreshlist_altlockflagheadphonesvolume_offvolume_downvolume_upqrcodebarcodetagtagsbookbookmarkprintcamerafontbolditalictext_heighttext_widthalign_leftalign_centeralign_rightalign_justifylistindent_leftindent_rightfacetime_videopicturepencilmap_markeradjusttinteditsharecheckmovestep_backwardfast_backwardbackwardplaypausestopforwardfast_forwardstep_forwardejectchevron_leftchevron_rightplus_signminus_signremove_signok_signquestion_signinfo_signscreenshotremove_circleok_circleban_circlearrow_leftarrow_rightarrow_uparrow_downshare_altresize_fullresize_smallexclamation_signgiftleaffireeye_openeye_closewarning_signplanecalendarrandomcommentmagnetchevron_upchevron_downretweetshopping_cartfolder_closefolder_openresize_verticalresize_horizontalbar_charttwitter_signfacebook_signcamera_retrokeycogscommentsthumbs_up_altthumbs_down_altstar_halfheart_emptysignoutlinkedin_signpushpinexternal_linksignintrophygithub_signupload_altlemonphonecheck_emptybookmark_emptyphone_signtwitterfacebookgithubunlockcredit_cardrsshddbullhornbellcertificatehand_righthand_lefthand_uphand_downcircle_arrow_leftcircle_arrow_rightcircle_arrow_upcircle_arrow_downglobewrenchtasksfilterbriefcasefullscreennotequalinfinitylessequalgrouplinkcloudbeakercutcopypaper_clipsavesign_blankreorderulolstrikethroughunderlinetablemagictruckpinterestpinterest_signgoogle_plus_signgoogle_plusmoneycaret_downcaret_upcaret_leftcaret_rightcolumnssortsort_downsort_upenvelope_altlinkedinundolegaldashboardcomment_altcomments_altboltsitemapumbrellapastelight_bulbexchangecloud_downloadcloud_uploaduser_mdstethoscopesuitcasebell_altcoffeefoodfile_text_altbuildinghospitalambulancemedkitfighter_jetbeerh_signf0fedouble_angle_leftdouble_angle_rightdouble_angle_updouble_angle_downangle_leftangle_rightangle_upangle_downdesktoplaptoptabletmobile_phonecircle_blankquote_leftquote_rightspinnercirclereplygithub_altfolder_close_altfolder_open_altexpand_altcollapse_altsmilefrownmehgamepadkeyboardflag_altflag_checkeredterminalcodereply_allstar_half_emptylocation_arrowcropcode_forkunlink_279exclamationsuperscriptsubscript_283puzzle_piecemicrophonemicrophone_offshieldcalendar_emptyfire_extinguisherrocketmaxcdnchevron_sign_leftchevron_sign_rightchevron_sign_upchevron_sign_downhtml5css3anchorunlock_altbullseyeellipsis_horizontalellipsis_vertical_303play_signticketminus_sign_altcheck_minuslevel_uplevel_downcheck_signedit_sign_312share_signcompasscollapsecollapse_top_317eurgbpusdinrjpyrubkrwbtcfilefile_textsort_by_alphabet_329sort_by_attributessort_by_attributes_altsort_by_ordersort_by_order_alt_334_335youtube_signyoutubexingxing_signyoutube_playdropboxstackexchangeinstagramflickradnf171bitbucket_signtumblrtumblr_signlong_arrow_downlong_arrow_uplong_arrow_leftlong_arrow_rightapplewindowsandroidlinuxdribbleskypefoursquaretrellofemalemalegittipsun_366archivebugvkweiborenren_372stack_exchange_374arrow_circle_alt_left_376dot_circle_alt_378vimeo_square_380plus_square_o_382_383_384_385_386_387_388_389SIL Open Font License 1.1FontAwesome#  	  ' V a h s      PTZaeinUY^ahlyIM#IOX\ 49goy$+/6[ckp"-48FKex}$(+/5:?eimr			%	F	P	]	f	k	p									

%
2
>
O
X
_
t











 -CT\bhou|.4BIRYbhnv{'2:>MPWer
+5=BJOTY^it{
"T
0
K\KFPT33T$

`^
~~33T4
B
%8
6
T3
T6
0
K\KF<<RDRyRDRy
#
\TFhnnh
nh
1

]
]
(
}t	 "" 	88}yy}%
Qy}}y++>ff
Y
33$
$%
hnCg
nhB
T%T8
V``V|z@z||zTz||zz||zTz|Ԋ
@*8:(
!SS


T2
j]^hYE֊ׅB
?Gߩмqٴ̟'(͔͂z'w!q=wVF7HJ?x>
e,*

tzuxu[Brlmyz~ 5qsUT
TTT7

_^X*D4EQQE4D*Y_`tw
3CC
3C&
.hnG
1
TTb
TTv
hV
F/B	NPuc]T<Od}}|1B&2B]]xPr
YYJ
ff]
v

t`|;$$T*
TE$$Y
4
:
K0;
/K:
09
}yK<<<<<<(\
e
Ԉׇ}zxaQpW'
.
Tz|:

!5t`Vkw
K'
zz++V

w
!V`24
8
4qmmU[hn,SS`nŊڊ~asjki<
<

&&2
{z3C
ff
YY
J
Yff}h@)
i8_dd_~~xzƅyGCC8=<<8CGCp]
z|r%

0@B:t

rrcr~(<<<<d

|ff;!9"TM5Ř{~~D;i2>
3CC3c
p
D;`L< xraB5,;
}8nh}yvKyx}zy
T:m_+c!%|yy}}
A0%ssjnt
+h@@hh@)
xh@@h}D}}
TTr{zz{yy
440
@*Pn\n4*<씒<Jڔ

0
*TPE!'''',
&
x
l

@
ZZt44
~M
T8
4
T8
yots{tqT*
TBrcrr
}=tvyyrrrryy<
G
j1
(<<}yy}C @$$@!quuqqu;;uq`VK4
d
V
>
>trrcrJ
}ry'&p]\;COLD|yz|r44 83
$Kwh(~Ez*6z*E!\xcikvss]tRat
&&%
!!~t
*
tD12
<]]?
	_$cX9
TTF
9
QEsu}
|
Eq
}
@zu
z{.
'*
3!w1]
4d
/K:


tE
`M`M
z}D$$D;;4%
h/t0
DRV
p˒&
~-
4@|z&
s}Tjiirsyy'&OGv
_Ib	Vv6>
>\
nhE@t       }          x  5 9  +B"vgVOb		4	
K

@~JlybbelT+w?(@n"] * L !?!""##P#$$$%$%%%&&''()*:*+,V,~,--@-.r../+/J/0D0113o346	6"6w67C778=89:e;<3<a<===>E>x>?@%@A>BAC(D>ERFFGAGGLM
MFMMNNNNO<PPQASSTU,U4UMUVWYAYZ7Z[r\-]^.^^^__"_e_v__`#`a*bbccddpe'effgBghAhi:iijBjqkkl^lmjmmn nUnlnnnnnooPoppkpyppqZqdqrrsssst8tTtuvwwx2xy*y{yz{{|!||};~#~|go^ɂ 3ÃCa|9/"xZ})o+꒱jocp8Р*(tJիܬkroQȱFYOQSUWY[]_Tt TT4V
4  T
z..ȮhKh<Nh-
-N<vhNKhN<h..Nhv<NNvȮ-
-hڠvNv44B
T442T4
44M
T8
44=
0Tyuuyyuuyy?j`,4G yu~8գYSKkj>h3c#^uiƭR@%
8
3FMffMZnnw
2G
v;
V
 `Vc~ofa[
Y
 ~T-u

@l
suw#$L>$#69JX"!!`V+/EE+V1R8>_r
@|
L
{ksu[ztKU
q9[[9:QQ:Mqksu[ztKU
LttvVlXXlD *33 6k
);KK

~t
K
4u@ v
W
~W
W
~W
v
<
T&<

`VV``VTV`p
pT&v
<
T&y
$
TV``VT 
<
y
$
TV``VTTB
TV``VT^y
$%
hh9
vjy9
y

9
 

&tt0
K\tt\KFtthPtt.-y 
&\KFP-yp1
tW&S:aR`S:a))6zzzz6)õ`a;R`W&t";;EQQEEQѥ
}yTy}}yTԜԜTT@L
lzK}zaEV" nmloL{yry}{{OJNll~n|i&js^^[{m~mkNo|y|rz{Kpijki\f_i]QM[!|Lz~rǑ̒Ȫ 'fgiMu

___([popHH4		tkF
E;wOVVOcZwE;]L1H
 v~tnnt*
(
s~oJ,^W`aGahc~v~AHHu
;


Q
t4tt4tttK09
4"
)vT
{||||:N8
g|5pp8
Ty~}y:y~T:ppur5|gccn_Tz}:8
y}}zT y
y
Tdgf[wXX[fe
8
tqT5,T.
TT.TTY44t8
^
~~
)
Y44t8(y}TT)
vT,T,ThXhYm}}chhcqj}}iVgvYtwxrwwvt"
V
3

!SY;;"ylD&)'C3zzzzY4
TD)t}
|}zcesd,.9/F-v
5T,TЄ
"Q>W"SX5z|[,9FZ3
TDd
y
!
!!~T{
{
{

@l
}
6
@|
v
TTTT
+
kT^^^^TkT3
RDp
]btFPKG
_=1lno1"-SKq~n}s{x}zsz2;3n L v
TT
T/WW/!(ZMj:k09
ԝ
K:
k+8V=_GxɁHKxMG_8+_M
J
JN-hnog??go Gw+JN-hnog??go_QP6
ox}yCQ(Csyrp}t{xoQPQ_K6
n{}|zx8S``*S8qxozo||{}s}|{n2K

u
u
;
u
u
 0u
 8~vvʪʪꪫʪ骫kihvvvijiʌ[
P
X
1X
w
X
X
X
  1XY1XXXXQ]
kllP
 ]
P
F? ijivvviijM)M
_^X*DtcX_^s=}jttjjhs
 u
;g|vtywxog`vf/TFw.qra\zzzaM{tswxyzzVc,sj|wut{tv\h2p]yx}xzuxWi:mY{pvzs~{sww}e_^#:/r8"y
U
 
;44
4K4"Kme,,eBV4K"44"4Ft44t.)
T333333/
T4tXr=EE=UIrXtw
tHq
T
]
]
]?
 (
ie[E./;Fnj L#Ï~LZpXiy%朱Vxtdorqpō\ʉˈfikkt}|mv}pu{qjfg__atVsrqhxg{u~~fOep|<A56slA$݁uvaL^O@BOq[rZbfSppSD}2`\Yl}~rYYM@!m@P`_O3vagl)厬߉Y͑ϟÕlNN2	ٯ}}unnidcksFLPAiw"^~8ȃ}gPnW6J_{zyk~bYpux-vؒŐZႼfugc`2˚ҡ}hT(D_sdљx$χ|yYu{Ln1p=m1KSp`}ixsq~e~W~hq{z6/S*اr	@Z$0
f,.㎨ok
I;p6p_ph6hpo;_}oh6h6}_Hڦاqr	_Z$0
fW,ڊ㎨ތSoR
Z6ho}_;ohp6hp_p6p;_}6hG '
y
(
 '
V
(
'
~DG'
(
T
'
DG5 '
y
(
5 '
V
(
5'
~DG2
2
2
S
tk @k

S

tC
.tTAS

T
\StAv

{tz{~'&9,
T33T$
T$:''~)TTd
T
4444Tt~|z@4k
@u@d
 D~~UT44
~sst:944::
~'
lyyNLT_p Y= 
v
PRϠHGwwsrPmXXj:bkkcv`~:jX;`Y;l-&P
4d
S+,,||~KK
fcc7+4444400f,,fMff// +
gt}{|y~wj
|z("7
{zt{tqT4 7\3ulz* p4qt JwtKK3CC
3Cfcc7{kkYkkkYkkkkYkBBk'
E


%


b
v
5
v

gsn


Z
n
Z 
SZ
ZZrrcrZZrZhlvlr|h@h|L
V
@G
,*
(
G
,*
DL
V
@
 
 
ZZZ
ZZrwhZ

V
 
Zo
Z

o
@}=
rrw>rZZ
+
5,*
@jzfY݋ZzyzzZ@Y9ZZ ZY9Z@	jT}t tst?@t"
szyzzt"
s@tE
 

I


I
 
L

hn

 
L
}2zz11zzz{IIII{zzz1IIII<
IIII1zzz{IIII{zv 
V

9zz{z
vv,+
1zz6

T4T
T4,#Q?`\pnZtҫȧPKgjzx}wy\O~#7@TKT 

ttt44/
T4Z
+4Z
Z`44
44 
'
`$$`$`$(

$$
$`$'
#
#Zk==k##kZ==Zk#'
#k==kZ#
#k==k#DYt]

&&

&&

&&&&kK"
Ytg
%
''
%%rrcrr::!8"
t
 %56&{SjjQh[=<<=><<>Kw1
^CT}s@sksstsjt }sTӸKw~ssjiik}ss@@s"
tTC^OG
GOTs@t} @w

sjJ
~stssks@swTC^ǸTsw @
T
@sttT
T
 tw 
@j
t,Qa! KtkvqCt
v
L
t[^
^
[
4a!y}|zy|RT|y.}|yMx|zp;
T4HhnzhhnhTԡ
hS\V`y~5V``VV5`VF
L'HMoZd99dMH'''L:
04M
8
4
v߫
y
%
/J7I[^_[Z_~}yhn{x(Zf7p\XTHaG-whhiwVQZ:#vz]l`L{l{,+\^˒3)vt40
\KF@PCN.ETiCkhT$T$?LL?'0cGv=<]]
]vc0;'dquuq--LaaLvtrrtvLa`Lv$T$]D'#5'0cGv=<#7quuq-.Sv-yU*PNO_Z~wrsrswH7*V3ziU{QgegSA:NT~=L=&0ErAuX

5y}|
R|yR
~|yMx|z]pkou`\\`qbuud[ddsV
u=
z``K4K++44-3V+*QQ듔VV땓4L554K 3˫44˫

44Tt

Tt

Tt44
Kl
}
|zt4

t
Kl
}
|za

."&FtD
t+g+KQc-b.T5MKTz|gsRrQnS SL0tD
tĤŨ y}v

%%Cs{L
V
T
Ki``iK
,QQ,G
,*
(
G
,*
D 	j
}ssttt@swzyzysw֯
 j

@sttzzzz
sw
)-y
4TT>
yxxy}||0T44rdTP4G
T44fT4
4TT1||} 
; pRDRyRDDRRD'yG
OG`E}n\>l0G
,h v
4
4q&
H
)=
WWXg3
UGQ {y|ss^
 
q /
&
T

1

b
v
5D'
 


v
)u
y
d
+|z@
@u@y
2o`gfbnh./>p+>|Ri/8Crb{Zja_qV Yo/1cCoGfCo:lRZb 44T3V``V3y}㝙}ytA
V


T
RD p
 V
yTTTT
noqqon
!55!Tft//tq:v++n+*mm*+n33yäyppv-)u
vv
~>lERQDEQҥQEERQDEQҥQE9},~
 q
2srqt-}}N}}~ZTYprr~npwefc~rrq/s~|~M}~,soppndmfnen
 s
-}N1kmo/@
,>aB@
,aNv
ty
zO
6$7u

dI.3WWT\
hn~fo1\s\koyxx<^
U/SkW?Ÿj-@	
+6	@o
	Dɝ·lZ'#ik}ts')2OKebh`i_mdG1dqp
Wm]a"W
3

eG.3O׈\
7hn~GNOH	6
	t@K̬-*osr^?<kO篞
OY	OxxytR]׈ssvkc\k}\vsO1fOzkO~rvdO J.eY$n:moOp
q1d_`cJl2)t}ǏymD׈
	83Ky
@KM>M>KR4)<5Mnɿ<5)4RP{ !
dr3CT~ϧC
33T$
~ϧ4h
J{{{J{J IYU:=YϿڼWG j8Ke`bz|vw{	̋{&,(i"z ~4t43y}Tm
}yT480EQQEEQ082(y{wAD
tF
K:

T9
˝
T7G
1
DD  1
9  DDth

^GofC3T^Goh
 
d
8^!Y1/)Yb1+

|
+2
Rzf|Xm}[YKKkK+++K+K09
+++k˙̚zfRhơ|w_L<L@aNi%ʆŕXP
"tHs]C$r[t
 y
y
ˈ?ApDU88Dp?
8
\xTTz{{z~TT
T-
(
T1!8 2 ZZ.n82Y\uZQ m{r^-Ʒ֫Ϧ [@{wx^^]Up[c\ˀt bdee	@$fb% <l6fGWG4 9<:]ua\Q ,2n{AtZwRQSqklN2IUphsJ&J}rIm{jlkāuvgE{|jZvkSr^kPxOH.76NPT>aa>"ipuleǞëѯ
3
C3
4
3$

y
d
~3
&;*226;*U
R
y
qXsIm[FHNMo;otpлͩ&oxtt_Jdwry0Ayu{&Ay  v(TQrLyJγʣMfEpB}P7.G$%Frrs3Xo[{TO(QVY`1(mpnnvww."4X+prq/#>VK?ʹķL>h"Ւ"w+{?>>w1'Ahpp%Hs]C$8rwsp v
TTTT T4B
+T*
DF
!
y
K|
@u@}

@|ztt
 l
x
 
AT
zi.],++,]i{{}zyjpnjry''{{~{y#joicciq#4d
44

4
@l
}

	
2t1v~z1vF4YtHAAHZEtYrtpu
V

4Ttt|
TuEuFF6!1=۴n_F(yRD\\ D~
Ttͼ-tY%CC%PYtKqu"nB
V``V~~B
q
TT
L
`wrPNxyprNV[Pwrqqyxyprrwwr[PNrpyxxyprNP[rwwrrpyxyprrwP[VNrpyxNPrw}PNVVNPx
1.oT:wtFPPFs\koyxx>\V?Ckwk++JL@
	
=3`?.Qm\ibgbjnG5[p
ofuel
= 	 
.Gc1n8`XC>[B
natĹo8ixFPv8+֫ঽtttuV]]B1˚RDo8[GngimQ`?34=_`b

	 	 =acfn}|}KKYXS#Ln8y31.`y
KPV?Ck1B]]Vvuut+`PF`xiPta?MQYKK}|}Pfca= 	 	

b`_=43?`Qmig`nG['yʰ3.Gc1tZB
xxyatRt]ssvikcx\j_qFPPFGOLJ++kϰkpC>[%
hn>
kfufRDp
[5Gjnbgbi\m.Q?`3<
	
 	 p=ϰˠSL
Hy

QQ{zH00
0
{zz{QQ 

X900{zXz{0QQQQ0{z 


900{zz{QQI
QQ

{z

P900

QQIQQ
{z
%Q4.&E݂v'a'~'|iyzr|x|~t}uz~}tyzrjhv~|'{|~oz|'r}spwhjhy~|}}|x}owuxzp}o~vqyv}}{oy~tcuyuu~xr}|~gwɛ|cx||v'݀t|$|~d+|~vrys~݇uw}{~|G|}}xzutl݇|~|rk|'|}y~z{|}{x|sv~vzyzzy'7}r~ww/*Gs kiB8"W==t >>Gww|&xjUt=N,B
]]Q?F



s
s
s
t{tq .
z

~zv;
3

44\
ԫ44tt

4B
ԇ4
L
w$$T5Tqt{stoy$$$$tqT,Tqt$$$$-
$$$$
T(
T
$$)
Wn|`_]#v:[vVi\\iD*446A
Tk
u܎v#6]_`uuu0n1W@^;A
 UU`4U5TTTT`4S2SB  ?zyrrrrybcyjd=
 djyddysqSUmtvwjoXV``VXojvwtnrryB ddybcyrrUnTddUA?<AkST3«nUbc,UB>?BnUU'&UVlA?>CTddUmի3STk@< ?BUbcTm,Ԩ'&)=
J,>	KQtd_O>Kj}|},D!/G]]x y
*
##@*!~!@i##flA\4v4443T3o@T%
2K"~xF͇F6)-1?pWSRWn?=%(EUmþB B_XS-(mU6EF(%=?VXpO 򎬇F˞y\&sqb] NEN ewd G&NS6}dNDwO]bqNñ џsSe& GF\}w~vt:4+q4CKtېE,b

~4dYztdPB
4VAlff,,fflAV44

B
i?fflAV4=
4440=
4|+fLdUS55TTd..Ġ..||eWT6LL6UVe[o!"m\àB)%h;=h&)CMe00u

d

4B
ԇ4y
44
8
4{}~bx4
Tl
}
T	
kmeeBV4
@8
L
V
 

V
TT
T
T

w


_
t40
I*
8
t40
I*
8Tr
I*
8')h	$J7_H,  `djXg]SˈScfzhebpR3 ^v" Om(;.?GdFjPyi7voMyyy4
 (!?::: @(t
Tr
@

z|
.$
@]9
˝
{pkgGR[".__ušȟmNgG&߅ȂAP_ATeAa6226^%OLJnpsosxZWS]{`lcmcbnXzyY\a\^cbhnnpszf%_whY+W~ cv͉ΒИ15hv9U!݉}t{D$<T;JYYbll|ԡǩ+}yLJGa75t|m`PvG#?}Zhzdqcwuvltlsj{hxPKGQPObktl{·}yُˌ|na`ZUTSR{S-deh}~~3U/
@t
Z
Z b
4Oe
y}}yy}T}yTdd&

|
u@ &eeO  .ZZ{zz{{zz{ZZ<
R
OXOXXOXOXXXr6
v2


*

WW2
G
,T4g[wrrZZTT<D
Aٕف1;))PQ̙rԋѭVLE^"t*9xI&Oq=b}%BVH\fzw}i~w{z Y
nL Uiw<u8=q^Ei{PjPn]vӀ
)9((NK"KsӋЬWMF_#t+:xI$Mo;`z$?TH]f{x}i~x{z!YlJSfu:s9>p_Civ9U:j\i$T,
T9-:R %z{{KlG8jmtst4AEA,:MK
,Ff3,
T>
9 ,;IKmxK0suXT~VqZh
 zEM?MuZMJ!` C:O)4lTd8D= \(F',
M,oLL~NJc'6R]<#V`lujSY`G]2Hva{]\|;O(1`tY(`
)4
{r|sv>(T+J~ff~JJ~ff~Jw
q
E~G
 ,*

D
R
N
TT{z
TT%

TTv
 u
~84
~

|
@u@@w
TRN
K
TR@w
N
t

mjingr;<7
M7#?#77<:fimB4@ V7)0[/ 1 /^//1 0 6;$p#sEAA*,?m6"mpF=(G`$.ƣ0y
1
;;YS<!-
zzzz3')x~D&l&y;;
sjiel{ppmoy,,yrrUg[giyxtq]um~~~~mu]qtyxgi[gUrry,,yom
pp{leijt tw 
u
7
TT7
@u^9v:p%"M$%Mڑhi7
7
TT7
T&&&&@;$yz%:@~4~~4`_`R`e9C/R&aҦ4A'")~4%%Cu{vd
T~DddDWXYV_lw}v~v*AdD
zyo6$7O
	^~ )?cwrvy~x]͈}|*YvvT
p

+T
T8
B
ԃ
TEQQET+24
8
B
+TT+
8
B
+TT+
8
 u
 4
XvvuuvvHNNHHN>%
				1j
j/h



eU.k>\
)$3)v
~44
4
Tl
}
T|zK4ime,,~B

44#x:4tT.4
hpFh84KqHaZxuuvwtD6O'xODwuxaq\_II_\DD$2??  nzykjstz{ztsjmy}z{JlQeűťž̛{yn׭

|z<|
T`.tg*`z|)ty
t8T|zt`tU)y
4z}|ytx
Tl
ty}U
tT4T>%
2>
N[cG=B^60
EQQE
uI7#e  #7upjj_pB:
!5ܾئ_Wc[7+447k
u
;w y
Ԛ5!
7Ep
m;4U>ua[RҢ&
&yRD[apdu %
U;4mph]@
)
֦y
t
t~
K3
4B
ԇ4 
K H
 qu"n`VV``V~~B
q
TT
)
TTT
K5!y
Hh@@h,t%
T%x
+>\
#n4F#n4F:Bp
צG
!Ft




F
T]T9
/T]T9
Q


t!
!6
T|zKz||zKz|3
T|zKz||zKz||zKz||zKz|'8
V
~ @G
 ,*
y
D

Ut!
!'D.
~k4
T8

Kl
+x
Kl
}
|z+}

T	
EG
pB
T
 *
y
DF


*
7
WW27
4


5,4hZwrrZZrrwZh#n!"""TD
44y
4


t
k3
44B
ԇ44 
k H
)TkkTtKG+4Kk44Tt+kkTkTs
Tskk
kTt44Kk4GFtˋ v|g>DRTT˫kTTktkKh@@hTT~R
y
TI
I
II4 R
y

I

԰I zZ4|Y
E
|Y
E
zZWW!Zt66AZ45
5
ztE
|Y
zYYJYf
65
)td


l
@6u4KGf0(
K)+TK;
^4}T
|
Tuk8|zTx
l
`t4+V`@Ӷ+!
;*
B4
l
T}
|z2
TC3|
uԝ4d_gg__gg_d4
l
T}
|zTT
EQQE

Yt)
 v~i
i
 '

iTi_
[tT44dtT4TzTJ<;KK;;KDTRDDRRD'DyC33CTYMMYYM
<**<<**<!dT
`VV``VM
=
dT
L
  
@*j
4a,t{z

tC8qbbb{y{x{K  t44t

4\<-7ʗ7-tD&c+zi0&H.0,-##s&&2iGz@@RQT+c&&t
 ;
;
V
tV``VIV`TT`VTT
4q&
H
)
|~aiEjVulѬo70 XDQ`V47mGGT4
q&u
TTnaxjigxi j(C(jgjixhi5' ==' 5G)u
TTn5Y' ==' 5YihC ix)u

~TG
(
T))TK4TTT/
Txc
T
t
Z
TZTT`
K7
xRyRDxyyyy
p<
Zyy)

4t+t44!  +4r@ 40 44p% 40 ++t$4RDp
4yq^jMPdioo '.<WN2XVu5^RDp
~\bu09


^
xvuz~^
ޠ0$]UM'
6"W
NQ(YcjMPimpP~~~+r+UQtb3L?0X3>X5QRDp
\bu09
J


xvuzJ
 sv]F
T]T)\&

Y
ff
ffzM{yz	zyz	%v@tJjZ!!
!"Њ~$yf+/YkzX,Hn|}1dZ\I<PW3֩ÓWW}Ou[}zyyy}p~u[BO}a` 5_qUU5tyw{z q~}mnnwmry
 -4F
t~w~t;
ttH
t0
t
tt

TTV``V
~V``V
V``V
5!
DMje!_NPZ|UzXrĬ5!
DMjRjdMD!5dR쿣3>ێĬ TPv4TTTTT{K
=btF
3y}9
mUzxwyysq?ggKgywxz{TmӨ'&h ~zUB>>CnUU'&TUmC>>CTz~{y7F
3y}9
+=
T#
K
2K'
(
 G
,T*
DvPG
,t*
(
3
ohhonhhn;mg<&S3
<~
;|#&%6Nkj
hWC
x}p;F&<U3
<~
Y;|$&%6Nli
hWC
y|p);9Iv]Yfh{osjeV]]nw vvKuKpJQT*FhltnݖݘƎqDA5%!*QTFhulstnl_a99:Pp~݀*Pk9okթd


p~>c

]F
tk
D$$D!D$$DD$$Du


8F
?CI
9
..
9`n
F

AEND$$D^
!
TT% 7;L9\XpqTTG
,9$9 3t
/
KZ
Zc
KZ
}ya
4@BT+}~|C3knr]J'V{ke{ohc-#*
(
/&|~T+ t``V``V
t{yS;RQPIODwt{K6KtqvMn;<-=vvkhF8!!ZZ
ZZ%! 
a!%
Ǫ
ZZ 
L!%
ZZZZ! 
LZZ
%X 
FIC?6IY(uC XVYx\b66SKPeSGQGz5:5'DN5TT(TKKT(T B4F
~~'1A3ZpT+

T7׷	w
,9_7T,
-
TZA1~.
~Q1Q1.ꗐv@TTTt-
>
 kB


A
yy
#
?T?T?=
?T?T?
ss'
7
- |a99az~ 
z |33z} 
z99S L
awvttvw_+
sZ@@@@֋Y9ZYhYY9Z@@@@Z݋ L/y

 d
~tF
]9
NC3
7'
9{sYsn{xput}T4T~T9
T'
3
}4Tru|utpxnurT}yLnnA
gggg% 
TT(@WWS+}}F簰ɋf,,fMff zzy
q{ttz{$$%
$$xtet 4
44G{zs{4O!mFNB9x*}}~5W]4xG YtTc'
#"
R
yussu~uvqxTzTQ
Tl
T}
T|z2
T R
y7}TxvvxzT}xqvu~
Tl
T}
T|z2
T R
zTxqvu~ussuTTt/
TTZ
TZTT xEFvdyDs4>$0K_|h)!<z35#N2):
0hekI
z|P諌jjnW{2v|#F
6.
I2|

kG\L9xs,0*
*0P
[fdL"* & _D
z|}yHec$,Lt1HDU
\+!W)E $z ~jCy}9
Ch&5`v8:$:F
?vk}9

:
z|% e@1:
%0?nPD
Q](E5UW+M3T)3w'T<|v;<#

9
}ykאSS8x_uaz`{{sk=Vj
#06:
$00
@vtT
iTi{_,1!T!1NH	t)0t
t:
0tT0
;9
T


NHv*

@3uk1@:6zi4F
G%9
˝
쎔|~}.)|}~}*1~|]"C]d4}3;e:}38iOJK.J?71..KzJ1Z.Scbb.KjjlhM8ʟgk&wl`lKK\.K.H̢W/&~kSڡ#ڨZDpA4ILy
y
m
4

m $
#
7
}
|
@ $
#
127
}
@|
t#
F
D
D
TD
TD

kF
D
9
t#
4F
TD
T9
TTF
D
9
TTF
D
>
iw
s
#
`
ma">


#
d`
 d
4Tgnohgo4,*
(
3#؋Gt
`aMPQOddlli`g]_Q+fjoojhovuf \#ͥȅ֤ ;Tnhgooghn>
4\
>
e)|mxrze`I3}y?z#\f LuOvhimohjoQ]`ldOQPMastGmqvi Ǿn4^ːΆ̀Ən԰+}j{xtzj1"Lzii|E;;]SHv|~}Iqzxcypst}qv5Hίp}Gq|z{t}ypjip~rx}xoddnyr~Wvuyi0izx`60w7~Q[`R|R[~wߋƻő|ą`P805]A]|s|z|WW[dm}yrxq~jiqy}~rxndImpr|rv| {H X?A܅wlDzك{цԨ_~q|||||f|mm|t^]Z'X"-Ibgiwknv v}(]jvgrxhklm[2+* mxfwj]Ynwwy{hsfy\\hqxAzireV$G4]t~%]~smn}ft]fcqyJ>LNMMNwK=KQx<r<Q؃vLNMMNLؓŞzGD!MLM.EZ#xrh]^hzirxrdVCVdqiz0nwx}y0gs|rT v7yg}}~5T~~K}g|ut~$zmvs:u
y
ssA~Tz}xpMXlLy{q-gpLn}t"VOw( v
y
uvxw~~vu#,lu=-rutturr->Cu)k,##,)CrrutturӠ,#
˖&~'+' }~~}}+44W+W4tl4}*UJ*d&?K&>G5#p)qM)EH2D??==BRippiip!~b^^jcjc~9?>99>?9elleBel9Ble9Bd 2  22  2 v  L< <pK"T$T,


L
&]&8t#4#4-_G_G 
C3uXr 9*Hb=gh`̀,ް5-"MM/8(x,(90KǲіɕOTOm̀ցQ\Y5Yy{))+)jxYhmG{IUsV7=o{vu! z'f@o&d1caaPEb4"f|aunO鿦ɯ˱nnoI7J!I5.OB\WQĦdRۛ~-aOpbKI2C@lU[s^Yoc`̄ƃ ~ƒΑ~vD,@aD1"@3byЀѐl"k"rbsIr3p1o1]_qewG1('$:er)n'y*ԧӥؘؒ6;2]zt[uns oK<yJqWqXi_`f`gWoOwm>EUffhjkqzyɂőơͪX>>r=_diry  T~TZt^zcc`]V\cchnow(78IH`xx|{ŞI1u T7~t;
 t~~(7(~t 
t'

tF
 t~򕃘t
'
~~t H
t~qqPV]]tסжihhMD;ZQuItI[nt]FEQZ-[+@@*e-8;@@4uvǹߤp7ZYCYCq5( v
>>>-r>->j7)1
;auabtavzyvvzyu:uzyvvzyvLR]]SBR]ĸB]Sx*.NZwR]ĹwwR]ĹwǼ|CNGCCG|pNC!C,313, q|]RS]^RBR]Ĺ_wη}|w$䔻kiᦿůI7J+kt}n~x?z}}}b;u{{~(  0YP
K  S{TSm  {qiTAsFGKiwzw 0 o_ewkj	"˒lshztu|Цy(  0u"5 @B '\ϊ؊sqٱ 0@.&7e}|_g͗|qD|unlaK]~d  iqqquzw|wʎó^=~Şv}M,7QupzTS(pzKYN  GJ b/ѓcctup4K6gp1zy@ yr7Y}{w\    wxFis}txyoGqtsp^)X  )iz=J<I
ԑyʂXjeˈP  𫐠{yM9<  IbquҏБZ=Z>Fdf|oL{1$+#~[G0`SQRne*wXjsIx[Ͽ^d7,vX9<DBcr~}\{zeugwTqtmqFXec_ddyq]ŉm]nr╠Ĩ  @԰={ j<5x03%\QMG#K.<(؃fff h8z_=K8^@mK#2'(hU5hKQy%."/b7$:,M%sysvnX}||,#/ 
K={)@m_X-PuPª.MĲT2&&<_]AQS@QdXJ*13SsVQ~ys"k=OBmmYXX[J:3h@@h3:J[XXYmx V
j`ҋD҉pqg}fortx*,p|{qPP"#DDDDDDD>~~}~}~~xxkw+,`nnx4448TT/
tZ
tZ4/
tZ
tZ4
y
y
tcMAAM[Pc|xxM
w/0TMY4ɽT>
/wp{=
4TttT:

4M
$
dd
$M
L
~mpk`YyuݶSHkpf1H 
x~HH-Ho{H遏+HH+HH-pu
td
}%I3URH!f_xxoriB?z<."to2|3"CT˖T\
hn+
e#
,T*
t(
G
 ,*
V
D v@`G
tAA

AAAA
rrcrAAI'tt2F^wtpcsKcI;>ZY.
deҦt(
tE##EE##E)vo}}4u{zu\O#nWvZh,lt:$4Zsj{rglb1XldvG'bQ^{yqa|x|{jjs}.Ӣѡ?IYKk.#4)sV
1|5Gc%1 A XRf
7n]Mw]^}ǟxwVo]ytyywyB A'!3EMM!#]([B4WtIm@nxWxWtIWȇ$rzӎlQ3J>Rq_(%vv==)G/H{uAR6=z@kwlkkwllaelj{RI7
A5ifsgffsh./gge0lF
miE#=[Z\Z#=EOiNQ@QyQ@QpzE&}9ً܉{H[1N[GCJۋz"q*g2EKa"81&*a/rwxrrwT(v]*I0  D
D
3  30Hg*z|4"
&T|
<T.4"
R
T>~~TzwwvxT+
4
Tl
T}
T|z2
T YtA
)
 3)vd
dp
]F47zw8,lr7RZ(x[ts[{+;fC3DK^Fxukrlqv}~b~F61fH1:4%Oft@oZ)i<oz|v|sdSLPrkŪV_WMY2E= ¤ W)A8ӻǔቴWf[\q u`vtTtp~TF
43Zdz{I
4:
k.pk04
~tF
K00
9

NC3
7p@
 "    " % 0 5 B I M w {            
#).3 ,38Gei}$TX\clu~"*.?EJRZ_chw|+7=D\`ejn	%.>JX^biov	-;Mlt					3	L	P	W	^	i	w	}									





$
(
/
D
Y
\
p











	"(38@QVYiqw#,26>FTY^chqw|	#(.9DOU]aejo<<!
=
t#
 
33hnnhTZ
z
,*
+


=(<<<<
-
>
/
2333C
5'
(
|zKz||zKz|6
M

J
fff
?
!
RyRD=
<.
}
}y&!
 ʆiimdod$@~ Kz&w{yyw}| |}xz{wa&zK$|'q
w
`V|zH
Y;ff1
ff9Y
/5.
T0cbhnnhhnnhjL V`
TT
D;(=ZXWG/9;/_Mknmn9:YIƑP`q~d_iiiiy
44
4zzklffAV
8
$/J
5'
t(
lnl||}_zob^^bzM<M<v	o_}|| 
EQQE
]
P
m
jih%
[
G
T1
$$1
9$$
5!
!5m3'!%Ơ#xM'nqwdo^

K|
+
K|
+
EQQE 
t
s3&
O9ffY
T%
*
T
v
:
tV`5
(

KzzT!5>
h@@hh@@hh@@hxC:
:

:
t:
DRRD!*!0
5,*
(
y}!4
 Z
0
T\KFTPMY;/a3b
+
{z0ZZrZZrwh4
2
(
x
C3/
ttttt
TZ
ttV*VvvP
tt{z



 ~w~~w~
%
2G
tz{|Y;*
(
V
/z{TF
TYY1


G
,yrrrryyEQ_
r
]\

tx}r|GzIydq{}uq
|z@:

z|A
c
TZ
TZKg__gg__gV``V{tsoyx>!55!10
*@PttsA@tKxxtw~
@OIIgX!!gXg!mm))mm)5,
1
Y9Uf@u


0ZZ	,,		,				,	<<}t.+ݭ2yqpV``VV`,
~~w~}t
tt`xyots{nj
<
\

y}&MQN5ye11eBBt0
\tKB
<~STdJ,]շ49arwwvyr/$x&
F Bwrr)!$DD$EQQEEQѥQE;fveKxe`Z=+


~w~~yyyyt
I

y6%6-J
z4

0P@zyzMYɽ|z%

rcrrry}|zy3]
EQQE0
fM@
jmq;
>
er



CTZd
tjTG

&]@hd

xqt{tsoyc
y}V
Ty
z||z%
}y5!v-


Pnq"u%t~*w)%iij  wOFF         ;                       FFTM  D      f/WGDEF  `        OS/2     >   `zcmap    $  rkgasp           glyf     ;ehead     1   6hhea        $hmtx      Hloca      .8bmaxp         name    e  ;epost  8  
M  ]Pwebf        Rw       =    T0    ΝjWxc`d``b	`b`d`d
$Y< 
  xc`f}8ŘB33D8AAeQ1W6@>2bDR i	  x͑Ja\ kbe>AX[X'y6&R|\@3EDAF,<0g8p"Q4kB'u&O%ɡSI9^um7ҰQ@%QEMq+pŖu)HQJRԥ9$cBxA/D#>TPC- BȦxK IcB47fmm7쎺'ǫ,gxxx9+&mXGI?}?{]oUVhBdf:2C_q /x   xڼ	|T0~s;Yd2d$d YĈ. (.*jԪ]jjW}mkWm^?[!sܙ$$}{}=ssxNl!v2].q83H(Oe!өH: =Rrx7Oon6zż1*.`ts䊖`cubтJ­$C^8ޛd!Hܼ-;<|M`Mq7sf{c<>ܱnYz./
pB'GXa\ N >qbwfAt0xvp)/2Q^S;~K^r5L X˧Վ״#1:;܉̉㺹A9$YG X<pyp3.HnIGd{ ''Ӄƴ<]~Q.XP
d6Y{4+muZYɜw,׷qcXh}-3f{)-rU0(jÏ3|13!>v[esL'
ilaGx{xP:)g.%2զ\ɲht%ho;:CsڿZQ^qF*G-&4R0LWqL|}RZ֋&{k;.ux̲]o~ms[?`S;f\ojf.6%B*u)!f©cbS7CںGuб}֮E\j7hRnfǇ!ǾK T $#++ rv)gb<(}+o>c[
kϽ:[HouYs[-8swmǿq&dZknzӸK;/sN[ ,Ճ3OG*Π`bL&.&}lg!pq_XXSW:U?`ID9>
S?>䫓hE
R|z;E<4.50"9Sn)O*Obeɰȁ[oU7rLb}l
17W>zj7>gqOzU!M:GUcFYaǹX
<MW9̐p@<xJ Mⴛ7k~8(Ͱ~7nbxGt
E]6	#в㩬q|lJ~V/	*RWJ}8OA%lܖ<yqSa^ZFT-#9c12rRN|
I{jkHZulk?	j?ZZ+}V~䖖}.&.M1#"	AlM:f<^$[/
?z=Ng;4ųQǗ<|傆yӶ}-˷mj6|2$irK7_^c-WrIk"Y6h6h'Vpı}UECMS9`u?{p^1'^	uåeiwyDFc\T<,<p}8#.QIո\2xcP+-&qgg="jE cP +BR]E.z˴6EM+6ڄl-rYn7=mm}w{,0,,φp.CXZOak|f4]Q,f{}mǌ:ⶰ3͊%z:;iΎ.ln.wTϲx
+@nHEi%R^YF3ies[m<meE"8CFb^`[JO:`YpG1a.#!0xt`啻Vd?KbO8;O95x	JE@!AaRJ⦂?8⪤1Xx8P0-Qƫ
!A-H[ d#ɜ(uwiߴ-ߠ| Ft}pvJP<+a"6E6ةq$W(fzzg,7ckz34+ږ<,ok?u½{f;%= g'֎;;#0|ccpKCF^8*pCaa/񥥸=:9H@wK: u`JȼN7KFw6\-.f'y8ڻkÆVbC$6L+]Q<#~ɤݎjLRE7-<vO(hb\7b(VʹKWxd@<KYO:Q*Al<Ɛ4M>=fxGsfZh$̀_\)=ws'GSSU(7%\pQ*ۑ,=`U")wL5&`3<p'9x$!Cfrvƪ;IG=	t&i雡Ζ L֍U-T9>a9f3Z|HS		XʇP+$WACVwcO@J|AY#Cq1ܨjQ>>K+Ԓf'fRxD0{Icm8\[uwٸ:!x8;ti)0,v{0j ]%N`41NU+V=TڔEx/#a+A-Az˒PA2qR[abn50"G_Cu"|D%oY
1bUMSB'_sqU3Qn![mHy1QAN;źRsɅX-;n^MXyѢa(v}: ݀`D$?]|^D<[tås*r="kjaJ~0))zJ'z?<<#3&wccC9x0T)$ܣ>a	ָO]}SZ_J	zp9Sϕ `;<WzVm]&}I2W#\ee.cn%Λ̈2'Ckϱں_}͆[wv_=om{xG3WZ|q[?nދ/J*u֝R>fkbl9/߳0:FwQ""ԬcH#U]oyF^W+گ|Xo@
 53B+ǐ.Yӟ֎ݻ,sRܶ24?5/g_AFdŃYj_ӎ}XA\qaC(9A
/A!ʚ>yi>ͧZyvȟ@5p}6e$k{b]mZﺘX@o-dYm8m#if8vy%G,xӵd%Dg~nA0Mrk[n*ڊN>
Y%8[z[o>ջcL+XZzCjb=	wVۀ'~st#i!U(?t@)itq4I|I/Jv	yٻE FR>K|f$,!?φZJ}MɈ#7~/ \ſkޣ7dbu֏΋~'*E	#B
b@71͝Hct<=t>N~L4_˥c+#?0HǋD7OV+}D=@i\$Zym/c4.K@fȏi< s%yw.!i+p9gSvq>':0JʬK|e<	(1w/dc\_:ѣEl;5	L$ffEyw  DM !VdpXTW(ᇸ|dG{'OՙLJ3&f+
ntѱ!<s5ۖZ:SJV}ↈ̱Poܾdm>UO-Zs?! w
|`pJ$Bjm{D[-~W-cwZA6D^Ȍ45	ʠuX:)%7 wQӻ!eD]F,!ÍCi;{NgpQ=sڐE0ç Aʜ8j<(4skP1ģKUaWv~;Gs(ӱ<}$i¥7cd~MJ:y3n>o[#IBّ2\?l@";%#	fRm$ˤ:'?<hvnuM/N%j<O[[˶9tZf	{;fmSuywO{}9S;&6{l!{nuU	$Wb"C~b8.#Ӝ6	8ZYr1n3<"N{(e0~\PL'<!AO8(Ɍ#" 2XieO,}|j)$ӽHD09Upt)Bk[3Okʺ%oXUق+-ҾrlE[<etF#oVj7]fVJ .`gkf[o8'(	\IDz	ǹq5#{4#FX6"g4֛:$=
݉p߽@Yfr1(Lt[̄edkFU\{:+̹iӍnxG"|+TzjfNߚ.l(7(@xB,1܍zqR{z2"v  p>RO'%I9RJuA<H&`/քT~Gy=3AW[l%$k6X7C
<F\"ou]<w{g2"bFA2/nnqLR<,ru3lYGNR	 sgUrz`Bĳk5Q++vLqU>c7#zvl"Hu&cy!W瀦IbWv/WsHsHMeuHۦ_"	4n[xzԴq9X9DBtZR׫#}jcC bCW'pt8	\JJ4ǙȘq1擸RK)0&r)ڭFRO,K1hcǷz'm>cCxoO7Z
=Cc#"}*f*H4l2+Naɳ;Tw.MȠSQ1!hZTJ)SMtGStǠ$Ci&G>nK~Z..13r?vvT&7KsSbn#IaYg$(3!p#mCr$2Huǽ$}xaa<	b~Ht$4bAXR0K8cl$o8	Z	P6!nH!H f$>* e7#ֿ>O.(r2>I@hAߊ==ͤo0ն<?졩M#mh d${+Q?];b;3;vwQM'0/pp-=CW`8Jٝظp^z;kH7]o'QX܌ϛJVLS(AGC8{d?Bk?W+˥g\7vg쐖C>Pk{EOa^㣷@887>jN_ҿL[g\zm0ڨE.Mlep&k_!#6.?{A9x<zFbƜq!mDذA_?!,s*YGje$]dcߵ,N^FXo?2>[7QwFGU=ף	ʒaJ&I!a|	T9>gX;z 39"#^rS[q𩸓V,SԉP/URc75-EsaI	C:gZrάm0$Uu8mLB1ٴ22उ;neF/S"I?F[QSs1A&7Q{nT*2N[_bj0+-s(9XZMUT`,,JOY93WYBQ=Opj
qTD>1B9U؅Nh?^zu|mU|a.*4Ad>Zeew,3R\Wƹ^g2T馴L,jXLVvrwRͳh&6X[j%Uy^AOUIk+j:q0"Jc/{C!%gO,\tEq	?P'q%m01a\IH(qV-Pfttp`ё阚́#+Wj4Uj!kGcDWՍ&Ʒeb#*W;	$%:SMT:cL/.s>Lc>TGgܔ0y3#Ŷc1oб-Fn̣Vte:ЏezrYmLHz756/^ZH!(R	ow<a 6Q$U܎79t塴OqBu6'8ahBRyd٩*Rʭ9UGZ}[&C,jSm@mTOӓ/{o5SO:G:t{'xiʱ22ZDdmVR9ɪs=\tVZipNXvj	C*MdBfqsjI[ +S9DN+2%{'t(jol｀EY0;C+~Q<W2ϫIQvN%aOUc#.0֡ .?EV`/'p)6kT=iDb9I!:+i1_Vb>,CEt!]|B.|881 .0>VN?!pSˁF<+ɺFP/.~gPRlr]T|ʁ8з2IB'T~8ɲ*,JȔBh{@y9Q!R,4ﱏ9#dɩ02q"Pat\SW֒bpϋhBV%tBd3{j/hgE܉4Gl`Is=ɭ**sH>~ ;p-VLЯ%iPOq13bXw%Rb.5gNWx*21v$cOc٩q/>;V~*BKZVeE`QH6C
ж񖧰|Y߼<nUpbi|H1">ʧ NǯtLGt(b:űsY^UCUwo%	}u2ݦQJjdӧ>cSOD6Y6ҏ E83_2ޜ'E6Ó{(&qigK//?&eC̷+Ru].E)nԭ(0pWIbc+B4=&_diLcR̠MՎ&i&IBYZ`
 Qʊ1}QBX;d,}.u:-5_L=jBRNR:j_bLNtUx+e$Z|9ҵ[G]+(ԣ@Rއ71b"SN~//@iX>(2I:;D^M%h ⨪B-哯:-˅'q*58\oYUq"rZUYKEf`{|ǅq΃T%9!]剦ԪutJY[asR7ᇵB_G^k#ll]\#<xcS<s3uۨiu~^)iuu:u_+Ô齃=6//c4bІLGR%NWP%TVW4Y(DDr=ju]@][r[l@A<߳Ok>Eٯ%+I|<?M\s5իt֦.lr_`,rd03K)e?{hwi㍉pxmjět^q&S/;8mhsXwہuYኴ.wE' Mv^M名7BJwʴaxw}/.v6:ÜIstnyRݺWou=]۴D=-quX7ۻ\-+zſlZGټț[y#2/xzTr\tl+:'3FYb
*L[`Zׯ"-T;cCxRGDmҲt&X/&@۰u4Ook]O`9c}Fqh c 5(i~˞=3x{oaǺW|h>z}?lYuDo}ޟoA8s]=ճ.)$<rE襇PugRڕ,<9fqَX]ƍIeIjYb<멸pC4Z:./z}@-sF`jTmCF^84-7fIъi2d訉n<&Xyb[q(UxHI[`T+>il6BxvS">4<'	die-I&_aޔt	q	Z*%r/Te6C
D7a<}+-8	11ؗCz9-($A&eK~%
UǙCaH\R1Yn![*q]v7 Q*%2ـD(%lt *]@2?m%VR}YuKIuY&9/j	7^s2&s	]TXV?- /[ę_gTQ sQߺ+NXq!z{)j	(I=,H3qzYj̽/hfq	
1T0=7[hsq`lEgt膿|aI9v1|;zvJ"uMͭ+t/5xJƐ|SOAucj %(|bn/g@U(;+u:u
R&.!-G),c妱\k93Vo1MxSNՑ[˔ΣNTU<1j廠ivBL|Ao.2"Iz'rT`rj
9[W 9qX&yVpriV,0W΁k^P$aFyG;j`C5-`4eцIyQMmRBMe1@.b1Bz;c0`Ak̎ Otַfd⋧4&k{;Y>NUv#o܆}6 >}p}&ݬC~N 95|yMd˧X.!NkGF_־,B 5DɅ@Cn7>kSBUc(o#p&^].	׷UׯoStV
\2V 's|A|<y}O-l|zb:-r},ݗ~T
lLg]5yQLHt)X-3ةAVGnW<n,!%ȜrsΙ߽aU?~}[Ͻmλ}5~in<i#G_}8]^wyi7Ԓ]VлԑUNt ckʸuҌmq'Ohd΋|x޽ ![_hFջnjFr_]\eۇkTS)QU@,J8{<(=ACnr) ݀ҨTh}4L|NT9\j)ߟ>ƥ>W΍}Gh40 =ko珳"}1[$߅%*:͌gJ2-1tI3Zt->}xԼl{wØC67g?yG_&E:c&˚96̍K䡽/>:Ͼ'<9ipźZZ{gȁrw;^%7{樸?`7WTeQI?Mòǩ?beQUm/9X^٢?);)ݪI,h2ާMN.-&.Y{͇k%
4R`I]6	}fgRCVe0=Bi>#)=d$\!$>nIG %v׷j"Ms,vTm56哊pcQ.L׀TIj2uN녭<a/qGnjw
nBzlvQ筷;*{0ñcedޯHҘ	EĵK}[{?VhoR	D%zr߆p-']w\Q$w\W[퇳Ck{?ߪkH$	2OBܱƚE?}\E51w\$Ivku6/+<. LeBT {JIWWCYo"]leB tQRTZ7#<CjbMmJ؃AK.|1q]`K~1Xn9U;=?<kF7ޒHڿ-u;$ٛ6.;O#Qg1/6,~/^_3sݞ̓><?M+5ܲsse;}j7]%\SEΈ>`"U#^T'"U]IRSa`2j	\ig$ nZsVDStZm\zb5>OX?Hdd"hQgoj1zv柽`m_.>n!躢 %+&Kż3I;yޖ/m4ǳ;?|Ιϛ?'ڴrcpo>jӦ=x@qv:j1hX9f%Io>[yFQ[y<2ʖp	|ܡ[ؼY-<CyοQ9h˯^jO{<I{⫗ˤ۟Ƣ>Hqc%xP6g _$oHhhLZ*y)ԢCR~X-P!Gf/
*.8$>.Zgc_⧂l")Kv0Gʺ̺=jO+q٤#;,d:aD/`3a"Oy1IuM	Tc{{7~7/?	wm+Ȍeո3/&*:*`m o<2IG>Dw LB_s*#S<@0jڗ7;	ۧԸ+4G0mW+T,INv8&KXl33FZ,ԯmO$
e!_,ˌJ+$ni>z9f'Kt
4V#S҄	E< 0eGvSe|z`"$*%r:XWxT-wi =t%vˤ<.lK6QJ̪te?Zr;*|9ۿi)?>n+;!-`c'-C?}/޵41Lf[ə~I&9nʈkaSv`}+sIv?D'<Dzӗ+"SIjKR=#˭8.^\K'Lmô E`iP-h0;FhL/)F{.EοpdQR3ן=tDδ/;)wFw{:r%3-bY4xFFɀY|&,bDhe Mb"b	m׳K5~wkj|>SpqzaYF"lx*Jo o=^B<5Ȍfty=Z_+릲6y9u3TpJm!6(83N(4ħ08عhQg'j,/FFT<6;Ty9*Y'5(8]B:.%Ӳ5.mlj2+ERWןg?fzj<5g|}S_F?ufoFW/=]/Q I^vk]?]9df,?qɻfZ!:W1i,Ym|_9+WyyCH:bѽB([bpH:>	 NB5=ļ޼qC]2װ̸i009dgG:쌘A_o9w"a{HZgtvvtBƺ5Ii
d\֐KmظmrY+4[]]Nc5L|o ܲe[y[0n8yUy˝JM31UGD|иmHEd~(Oq<a
w<N?]*p{,cGQԻ$$SDdYFDf|dӢߣ8gueϹ3K,4Iq|ΫӭD";IlgFt5&]ʜ>Y*[-63}L{.}F~qQךgVvǂXA)Rzew[Fiܳ`S~oGZ^B[ڷtڕ]4La˦VZu-䚳E+8?펕k?z{eJYw97>B-8tsT쌸@?/<;mnENh#AVl^W5D¿{Q.ZPpJjsWgղ&.k?Oxg8w.Jčg:Nv{(F1u܇W}l 1[f{/u mBgcoQ<^Q[GMtP니_S=dԞZ-Ag[T)Z,.Xƾ1.8Xj!CaJͦuY-*]$3
R B)Vb33{.NTgMQўy6va&b!.N__]ڈA3]W{rj߀tG\H`/;ذ򙧵PI+q5pM{&sy'~c&T6Zm}mm}^U+>Pc}Z#_GcCf78}z6.Y΂-xmv龾tex+b@)+q1+-V
d+Vσhx':)Oy),m׬>!3}Ucs/-p%g| %Bs:ꚽw]jGfc5HF5i5W6TÄ;OW&PAthg
 gDm{]2Yv'>Eg+c؃,-xg:-<dv)xQ_ӒO"H=\N5z1V&i5"ؓLYff鳗<f>icvgdq薀bnvPtd\7onRڟno0hVLHTMMӐlCƲ5ݤn5`Rƥ|4e"	Qt@iU4|,iՖOj~CpǗvh5}5E}~>q!ĸ71xku2'biƯyW3]3+[v:͝[vf1U3sfF%Y\dy].qRIvZv˅(jn{Jr=0az/:Ξ?$9]ɢFkN۰bc@
uNpU/<[t?̳$@7\[rϣ{Rcsx$_y,yŽs[Vg
+&x\.^"M8sw۳?Y.q«e|m[By$V;U١:^fώ2ؖNVDd2˰2	N!O8?vUT#@hIq]M;VA"t0/Wܛ$v?%zhP-ªP.Wdn'֙cs/Qĥ̡sYrM暭I!qQ	p`ѡfC[j@pP-xaAL/d*j _!$LU;a+:qާiNizL\8Ẕm\~$b*,d5D7FSF~u=X&6msXC16d]	]WBE}!:^oW*VZ뜢/SWEHSWty5kM9IϝlTNn׹c<	p'>L&5 w>zR<Sq)Q&l)gdL<dQ2@n=!hP3sL鏦4x=LRH޸haZdȰ=5\'ydJcRB+ؒTdEf=8DG,f($3CdqKJ@";XP-Btgqd3i)j%QazioNRZX(xPAăʦYOUmg JcV3ё#nY6ʤ؄d"4}COd$RD^pԩV%@o&	?$" ٭xy'fHF+Q	 ϋA^Õ76"yY7-/>^e(&U^Iֆ$I67Y#6"UFQ6ND0)bEEAEq `[%IAJ2vH&jKϐEQ/:;,ixxky D|6Hv#!!rT%I&OĄ.)F" yDLfUzE-*|76&DkE{&*d@dECpK 8FYEY^&!wZ;o6b8t7N	d'`d:U6l4I"$6U;:"p<8@1l$J<`Akx$"xB p\	 ]"ɨU]0%"1=Z`X"Xmk36RJN#E
fl1P Up	b`A &*vKY8Ι	y dĈ$<\+ndC:bJER},N/9%A4#5 # `*o3<v%Oi
Q2Y!9yGE҈.I6ީA4݈5x;1+,KGU4I 4 $$փȂրL!
pYID(p嚈^48jmA30-	t-TKTn4`D8;ǾAEWZWS89yRάګhsc2Y#>%Bg"6~BW-N]ֲOH!(N׉~QQ.jB#Yfdo4WfsQ3oNU"xbv*oDuW94Y;J?$ro5c8o_cv)Q9616"HB	okkQX>Yv0ԷQENaڵa ۨXmg!	eǾdd'Pє9rE+%Yk9wa
K{@{.:@ `3}K`&/,r<_ 1!5Esn-";Ln[ϸ@܄,"B0׫KܸW	&n1/) 9WKW̞'
?w-e}Jsף<~uIm_G}sg_/]Ko֢uOcLOk(}!Wny[a+,%mB\$#ې3rX,N{3%m	}ItKJ\e.I 4rggnCs//5ML_w=+rK+׮]U/\#̾Z[c:A?3:u	LT0>QwW\ykb%\.臰+M9 rpc'i<0{CM{W3~+0;zmpY{ZwgP%K)-A"8?;o=:+rڻڻ3,	q혧/6NmGLv$(sKV
n?wۘq9:ٓL4ٷc.öPmi)1׎fˢ>j%J[f&ѝ:.~^-vb8y:iž+-{XVܷb,6~}+7ɘp1a"?cs$WĒs7/xxүԼUC⿾BLD?$}ڥhĞCoo 3oOZꪁ;ҫ,ŋU;f_8mU ^G[%gG8;9dx)2x;E$Ӗ2A>÷~\qIEq.%vd2R!R4g*SHOAPy]yRdA,*,}s3c7|^袺<k5K>NfV]e(݂FI /ҋW?sG㵇t-Jzp7ȭ->k~nVz/]?<7\~bw+C[/g܊^2&^ø^R,l8y8+=_cߍӯw$,$! ]'ݦqyn-_aφ>JPVqsU樣CU_'v񪯩}*i|\KM宲dNvdjAOKpYє5ǜ[	sSl7kV_f.pŰ1!*tXmL\ W rWvVAV_rda)>`1~gaLl<N()ɉlqA[fΘYr0#طY.k[#ל5kV̇iJ6 7o߮U6^:MN k/3/!T4omݬə+vlviT9F#6pvvM%b¸UBi} ӕI2Va| 
~śY][F%$0ocW%*WY;k\:on_/o{>%7yc-^vեoi3P<[&F^޶<LcEu9_vUi:Ϟvܹ=V	.dsvF6@<63cQ=o*9IiY:-qƣVq>d6@zc=glO^O/3𖺮Ծ; ].`GמeMgK#p6p˹VŁ+֟X,xUr|%.:Į]V\}>]Gߚ3k[ڟ^:;wY?}ڦ{VϞ W+-rL'7T^4:g```۵c7qJEfc;t}wLb}'<1)*:vSrTb[81'o,	
_p݉OBLZ@e+%1/)zxCl*iv;8_p:ExӦ@ pՅ?w%͋Y34Yd`6u}B%=*n٩mfJUX."N!"SLLn򞉿k?w.2'xJRJ6'!j@jyAdty"ļBayF
K ozmԶ!ic!?,C%J3S}YKKtEvDo~zɶ٪qkkn;.u[L$GG>q%VC̛Y]{CxI+[\3yCYC쟻9(K^WO3{?ΚȮ3osGq̶eS=Y:ݝNŖ*wYƖcaM3i 1'&$y @"^ P[gf&}uwgfgg~i0Zꝰz!(W)yrvVNr:[2O	Nϱ*++Nm¶'Wq^Z3b9cͫ|߾UMrHu)|K@e=@fyiw}߶+ڗbU
Ul/yMϚX--Yv,=R%VׄX1.Nձ:㉯\\9SO2aBűpGFeeӍp#wy\FX)*oY+`dEq緯jqo<EVtL"՜Af&xk;qOS8JVyth<FOiǗKkgWJgʵ4:}	TNxlB>
y(*!CD-M,(8g&tv,?DD+՜_7;ڵqgquolyu˭N5-rG#7^J}Ӕ8é`~zu/&J]WGaWԹYlڷs恾YwϟqBc^iZZ?pS:'ϯY`wMVW1nXђ	+o%=!Z[Fyti@fws&64LmeSw9L^UO%$K1<=NIۧM~P^HeH䗎縍i~6uC0P1JQ4.b'<.X%G*5Ekes9 $AHG"ʁq*166[V܃x}tƙ2`V p:OsQTMD#s1 R	(}2xV`;e$#9F0q`D1%hCsa7J_KS2#Mcn2V'l$.fc!I^wJv"TԃU.	A0|It"U[ysԊDhsyjYSdbaokiYUuuUٶ?ҩ8_U_QVvc^EcGXFܰa8x;H,;UmMp$XV̆32zs[SH%TֵkCn/{ɒI\0n(2>׃/ƍ;WW\ D^ݾ` C	Eʏp`BQ"Co/bJo3<ۿ	W;@+t+ݰWU8U]_WPKNǸXa8a6!լ5݅Bٴ]Mǐ6y3x&\7OS;u%:hf.j`זJJE2r&ӁEc
qN@cjĿkXгtġ @mQ*Qnv*==kTc4Ux rl5f^ɹ<+FC gēX̯qF&Zx'f cBQ/l5zn;`2T%HJV~wW#n5`i)J.f6M=P3iN>E,N]=orqABB,1l>}QCa(az/9l#7:#mľ wLO{qRMkOɯsbfbc9ض,:[8"8;+ҿ\wSX6V0s 5:&Gfbp'm8͹m}4EoGc[QΙʎtb %h?͂:Q*F!h7 &vFoMS
 [hK.j	FJ^yJ#m$sqj{}#q4tSu%rbDk[SjMK F,O{L&3gU;%MNMd$SrQ&5\M#M28Q
]OnG'v$PlvZz~Cr̨1[B6#0Z֊:RTYE~.uȑ~,LV;
&5|TMC!eSxUύ= K \R&sRP6$AŐnLQ$w6'y8lH>	)$S(ނTUW 5	 ųM]Ο"|@va`V惾\IxkT	mIWɘhJe&⹴3,֚Iys?k!]\SUt[;SUJh&в3*(ԶL==Pij\~hbՠN>rNWWo[b0w8EV[&d}S߾/I>1f2%	%1agr2ĚQH?W*AZaF A".ABav8F;hIYn!Q\w,dY|,%ɍ1qf&\O5`OnZp`N }6@:Pk$Ĝ7A[R2IPwQ&XF
w
{2pMNH>QS󩾜Ʊ1 gzb7$Ѱ@ǧ:lЋgrHiin`]W}^0aoî:ה)d9 Fod:Ľ.yxB}m狦e=4/3R_?jAQˊ`VL/xx'tK6]n9I/q0Jޥ+*){pJY>B$lJGWq};;26yqJ$P,vuoQ܃ww֡倌x{kA!)N.&C9!2;{^j4i^R猵Y7 ܑΆqÙh1i M2CTBEqI` h~
[rTPr^+˒|r;G35\p<OvI[訓zoëNQ.¨r7NJь#n#8rT,[nb[3]+gPd?Nšl2@Wjq@'\py@4bӮ'r.+ؼ,A0F|&RJL&>\2̭*kMO	PWX/kC4y)Q?ȋOxL<~GQR>GJ<3;2b#l]Gqc&tVF3͊]9p*~:o>χg? q*F|lM9yRc?(%FH:(dyآxo)OWI/Uy d8U lvg5#XE#2ʓH/7A{'G$\xvJ~E'e Yugn4x׌x&חefh+ٷYOtTCgXbF^!KɨH&n}?14nĸ}@ʤMrHc/5q5>x;'8dp3d Un9cU^RцƨbJDa9υvkYǞNx,Rӑ{0"^/F(5e>d˕H&.W_oAg<1k0B^S+R6ZkvqW2\<ká^HXl5#1Ҟ;F=9 !8^]tǹ%d)L&;
D"ӊVr#b<e8
9,JT3fZc-/
nd|Rx@p#0GǎU.))-)?K.U|ddٸ\8TLIqXCՃ1ˌnTը*)R7JJ%m1w'kdO"mQ[rCL\2C5N8?\~rS*XTdk?؟.qH5n\ԵL5yAFdL\QEukc~{`ډuꎱr`cc_p#yTv\oB)}~C:vc8+{	=-g7^ L߳sc߳34gگ,ˍU2h3m׶HMxR.Lr.C$z*h1DȅtIv>ۆ{ i1ԢـS!?Ćj^g0Eet\/gfs,X̞sbHcZ(ZZn~rb-CÂ &b#tH7 '4(RGM0 M(ٲP;e	E@S].90q[l2Kߔ%=th.3GX9MF!WRS}M=˞fUJ{щ3q{]LbW?B¯|1˭yj<OthjT.0T|d)SyIJI'XFlvۙ\IŜƦٳ!+޻w/sqE)Њ`Lg;H$:u쭳z;7
^/ZG*>$r{|LF"6:0\`1\D!ưKD.Z5e-KzL+Q"swH++&u.<'Z4^bR;_<!PK֭2j'HbJ4Z4:	1gK{c8qDAoͮ>sۺ:R~ɁCWμ敇nEj*Gx=o+Yv\{fwv}f|{&Wt ūۧk*9eY۶>=:sg{]3-4oȊBz_YG[	ީx}iG2Br,Gdi27+3@ȇZY096r}9,Yh(DxɢN]m2#.4*!:N%F\2zEK7ފb@*@cd[#sY4P"y^HZ8D\DcP8HB.48!|"~WU}+PI*9FTr̧>I7t)Mҥ=v
GΕesAvY$s7ꦰՌKתnSJn*CZ
tTUMMʱ>GR"`O&R߫'§:):E3P^O:.蒂.l*+^Ho<ΡқM:&H IGh)͗L$@`t}b/.jZMmKǉ	`::7j?9u6ݘ]mq6.0aЀ0Dϐ'0ff)Qv[4N|Kp@1(XG"7Ũ] 9πsk1ye:Y2j.2=0e2p(EƈL6ٺ|u2vX~멋E	VE}MzUo?0>a]rz`p{]{O_/;iQخB6Ope46`XfWvoP*D?k27Zb:kL8)Sw2@m!Ǜ"E*9̤RV3:jj:~ŗͷ~Id5b^᭰XESYttQ[A[p3}<V{zS 9/rjQr'v2!-	%^yaH,ˀb*x*j"Ue>\yF~)y~=Q4IftLA0ń+ǲxjƪijY^׎Yc[w_U˪TؕŶ2c `@
aLNgi
ۍ8ɌDY#EAi(rZOyS8 O> ~5#Ǥeo=^ڀ#6ܲcGvpޮS#Γ+qYVs;AJE:TV*Hi	3 E1E	hwm-Mt\b5ZV-,\&P	W ;U5v~ i~'hn̝:TcYlrn2{i*a,aUG*iKiA3?<Ey!D+b+Ѥ+[ezt\戮ca	ZR	wId\C<T~M9?<oݗZDgk踐9cda99g7F|!38xCb1I .ӲZ[;%fU"".M)ɦ\<Mo_]XQGܺeM;3:(;@zJj3Do9mjrP+	X		l6 Шc|Y$ +y\ i[["}(x4jJ%2}Y(H͟cB3k=S|.}'=ۤon9Mmi@dArVA@܌5
@H	I}aFE{	@yL#EaǄ>[f3ۍG4]^&)	n!F~@Sq"XC[zi57{'j- z=2hocb]`,n:E;TN-Pߒѷ![+CLff#gl6ZIȼ52Z$ΰT2,'$9RKЏ3O2!"-A:QϿf?k?"'Z+)!ܑH{#nBK&LekЗsԦiJ$%f?0]h(O?NI4S;iβ⫪'ϟ?ﾡ2l}w3F){~+WB|UGkEm[667{blgz7ӄS'ug>II=N=k.jesT8*h obe<ʏ-Bz@]: =)JzJ.JRTՀiNuD<RZ2h)!gE1>렌fͥ&Y<AOĈ1?p3	؄2	Șc@H)X0XԞ]R/q!JR ~dNtUe[Qi)<9<d;+K/X8RYAB jĥG#ŘYu4H+g\&!V1mc ?`D+7'q,O+=c+Gw!Bƣ$?%jɓ{!HHbT;ln-ȑ<jB@p@uqZRX5ϐώ%4T7R,uɽ/\V@:[{O}tEêTJ;^;^m<r,.EI,:[zXΈAS1DvnڿCjq8u}뤧GSlm9wܾ灹@;O]xxhuGdjQ4|>dM1awq1ێYڃ$$pP"O;EP,!yn4s7%OTC8=Iʔ;e蠟@9Fah)֝ Ov;u5cAk5jXme]A^ I3*V~}RҠA˭n"SZsmU$kjl*BYX->+q|]{c5axVF$BEv?a Nfl0Au\Α	qfPe zNـՙYJo铮0%~i&P0(	$tдaOD:b4:Z&xH=-t=K[TOX:^ru?5gc]CcZUe9Aޡ]. ,˱ Wb-r%Z|y"A>}Fx4U>|=N-K/F>
M.<|ŹbL|ڼڈJ YXh\1ڀ42#Az/a9S#_2FIYb+_tf*5Up紏X*ImKul"iGR\#},}7鿚qӘxn%<+cn Iz'5:OMl`	,,Pt[xdN޷*CUC<U9O43lcew<*-7)-zVZ|QЈgQ(:Y&~y:
	dl,
<|%Dò;Lp<G<N!ّԴc2hQa8fu{W̕te976>gpӥpi%pq2P3AdH^`I+$b'&pvҊszs	:6JCd/+!QcӮژ?ٸ)U91ȕ~|l rPiƷ`N">JA[A>0aA:Q{;j hZ.G{*AX:OԠ8?Q|&j	۴F6Pя@"{ץ{^
*%ȘȜ1уlXaTn`0G1n&	 .
?
%zEDCRf<Hf(j[>j1!E)X	Wsq{_YnnO_6v~Iz.cUl|U-^?ɏ.X[EhcvuicīAtbU٤0<"wZ5E[(9D<LJ^!t|jT4N߱BK]r8ۛJ8ʬPhOF;-;{J*I5L aH	ːA&f5pALht	1!^CJJI=RJZD]\/H0NLpY'`Nӳ{,-iY #|H_>s>FvsZyxN H)i#H3Gt3J:#S%Ģ#=0ևՁKtZ|I*] } [8RXL}MV\q)d.wXnh9(84n,-瑖C牬$W?oVf"ѱ"BLn,o,)C/e,=ԹU<g+VDzF>".¦JXjʍYr
0#A:p$0` !Q+/pT!H&`zNSH#"g#FLclj#Vb.RRlU0D#XN-M>[,,zSa#Ưe q2KR`EDg.-ICKe"Ȳ7j,S+?O4M}B\A_&"DeC#過z`VĲQx#HY!ᨠU^ņfŴb#֨YF+Kw.\%J.-Zћ
ź/Ԁ7Jmcz$!ؠv{q+.4Vƌig8ewEzX?Nm	o ʊ=]fh&i4vF_oO3B YOj\pK̂8Ew٘C;u`1a"Pj*rN?&bы^yu]vN˱?PvT)o=ZQYG.b&8r[`HsY[NW#͎7~}Tӊz:X~o+~mNOm4X94T`|NQO'ԯh8fBX˼[eɡH]_l(+*6}*p]1wzaj6^GEi}9׏rwLVт:^txEd
O蝵ddp-i ǲL #-bޙ݂~|:KRzs{ECljwh4>2C`rp	cmAЀ/)ܙX/jY"DY41AZ$d#F#U$h\g9L\$蘭)*mѯ*0̨R*_MܟG^InV#"l74/06:cYQۯ:AzR+>/V;ꈮ;>~/Y3><1U8skXzAz|K/zۥ8Kߗ^C;nFe߬I;h+ZLڨs[@JCich/-3aC:^Ⱕጣ ;.p	贻g=k{xQCK:hRxN\t>koP؅k)7xGcPg3=H$RHBhDziѯN-[|Vc~'`4|1LM$8ALcx7	FbH
2^#J"as4~4]b<8hj@-spMZ><mӮ&L_(^[0p*픵oݷ,meͯ;+LW(mjUk.oFO{Ec'Љ'k̈́*sN ŝ 05j/n uW0Y	oaU Z#ahr1b7Hgր`3`HkjdY-9Qsbg cj f]n3svpGS3Q;1G12j<mń\VpDf[ H0#"fRz0^a5I}~$%I\
aL=kM#|Ƥ9Z448U&|pL	x4@&hbp]<hJ BPCЗZuUpjɯw-?Wo#jFGV;񌭐Uki(W=fר&P!j=i3oSW<@pp*3|VO'Ȇ$B$il߾jQ9Vi,S}#k?˫a963kր#<5rVeXM6Hg_I'{?st4ae̋Әhǁ7mXY3!3T3{]-!yFŪ+^T~BhU6Lα-ͬ6(<<Zx+=6l 6֠
sImF=F"su?87zٚ{,+j?4lx`8E.b[cd@腉;bhT(MlDa=th+|Sw̛k
l՝nTBhuWJ S0<mƠ{BG6mpMik?; ?B,Xd5%MN[`Jt,{9Ҙٗ7R3[D˅VB1I1Mۣ\o7!ViPU!h*TJ]pwV
|wyw7(z1DәHMn4ϟAgq,*e&=/B(SƯףʩf˨]5Ǩ_GcWÜ EXv΅fy#A`[̦I@kMh-^	5])4D"|K)aLJb$01]osc{&M?J ZyMjS8"EfSr
84OOhSL0MG)\W=	EaWOtthN7|tgap8AZ S KCR2"E(	8/otSv1;;jSgU4z=X1˛zSlElP5	lVl6`@164^ZJSS#w"ضư{גyy;"#^aAxԋa&ڬ!L<"]w^"=itwd3}OgAb7԰Zza2Zh@	Jc|qQ\`Gg(8~"R@`j`\]7Z;Zo|
~@և/]Ow
`HMHXh찀JKg(y7ktev5ҥ6sR+bYڰ7~ފp?8ZD%7ƏcBjǛ{8i\^M&3:it`l	@Wz7)ic-~[npCK9!Fb~Q"Ě`F^s sT_;M wiJ%vjuУV,٤XiRȃ9++2y<dW]u9><6#b;iΊb@Ap(NsӂWxNT)oS.Dj+UagQkҏt:Pr{?WƛdqAw[I&2 ތQUqzR	zê?sjNIF7	B 
N{@57)K-O1s }L&=(Y
ɂte`. `^j+	l̔`HzXfU鯠Uz'_
13>{k@'})C9(wJ?=$tli8" #ov1Yۨ_d~T38u\J&֙X05n_zn/*`0\5pxCOϥ#A?x98T>c11(4ULoZ.c.=Sf3%Z,IH:qbW^RpQ	yxӌSfl4dƦU;VGyxoaiiOso^bd|I8 TGrmtGd1{x_w	ѬyE7Vp=,t1J)UH4C+P=Vo{9C$̂,\Dd#"I"#)L$(lHpN6f8VRl
ZݯN-}Ċj]P\p.5Nkd\^[+B]3'͜}[QnެeyJSs8	ۛ :e9(h7T^:~aB8/sxj^z|QBvtUF=gPt穣O9k;uRGmMW:zuHM1O])(ڀt]n TI&"n,bIbm4DCܰQrNg zfAyp$hp`T:ڐ7ܾ:5K[Uw~ǩߧ4􏽽08}V\̌%ü_,5~fQG|SL`s&#R4,`V4pm#աM㜝֚<SB)`jP3b|Դt
*-S<!c?&6Xӱy)SVΘ`<0ل%W)_3p4:ƦNI?%BX2_9l45GΟ@>G]TT=sXV2|ߤNYΥ xxϫ/+PZ37tZ&8Ln,c+V[թ;
)$P@ fP0&=YX:
1,2xB3@74yN{f3Vxp	F
Ag{Q&0TpjU@k_3@2
^#igaܡ ù*YMv}psۚgSdyז޶{EhAO(ݶcs.ۃ6/?tx|pb.k<5*׬.4cќْFd^SsڌC+J]#-C7} $Ib7U%^&wr$#6c(AkI8JGp d͓/$X.e']:tqnS3=^9inӁ&0)N-M5Z~7OǛʛ"+զ2ifySS9xIL-*C6ps͛foY^kS7g*olDŷoBOy LA`x1QR EKzH`nX,b̀h|4Đ:vsV71&0xHdp$L4h<U y@*Na	0kgX)='Kb'4Gărt1Ɂ7#~(-H1[5<TM\#FHgjXEzi7'ąԄ&?R@t7'͛=qؾ zZY3L``nd-j%Ê"F)hvai9 $"1W	T6<:XjYjS`a:o_RH0X,-Qȫ8F0ٌ& ,JEhY΢rXbbjVjL
{AT-t\fH+X+ f9e|!1ݯ4NE.dM+*jD̴B#}cZ.Z)!i5~FUueRJCxuz!PAQ16P㬘+N1UtEŸƪ< [ktWأ
P2C^۲6ky9-TT3ho	.iXlՏg4@DzAK@0DUy%ݑqu@̅@
j-'
#*TTn(&C×.6ZTBbAZf:}sGA;t{8,1+iNfv ŐV+Ahq2i@ggV@#(JJBsŌ aV 4Qde恮ɮQ+iu\gw\a3mPbP	o:d|A?1B" nrW.~.3!T@oZ bF  f?V1ZQ4Vh
8aeuc
] 4iQyj8OaT6V_4SgTr
Υڶ񧵓<JRG;M׮y͠Qvs+_WUǏ]!jXnvl.]-@*P'uiNZÁKP:ʅdUCPsqd?@{skс 3UF#	&\l#QhA|KZ@FE-iU^m6Hla.yJ44|3e/jҿOJSD}S't6EʝFf>|%g:ﺩy,S޺[>o*/{ߴ6%χMA0RYQ-L_Ջu]0smى!)-of|-P&B>L90juL,,Uث=יX4yWO[xFuYMQMrm;XSN=Г , m<o0؍Smn-^[*n]ݼɯYt`UYj\?a>뻧7Sx#dBUI 	ͻMU4FI1@?싩DR'"89r8҆e[a+l
0{N
M4JRmn D'J/-il(ÌL)\MG2}*Pt[!تf Q~_"#G45G\,M2ğ:DrH<_Jr',FfBĈN3i\.kʀ='ו-
 ս$Vt ={ԕ9{= }!`ұ"H^-%lt`\VO"X­KͲXfT]O]}Q;Cz`g4HJC%oh)k8J[^Ε#crl"0A$FY|CzƢ6_S<4Td40G*?X&ۑRRRI*>&{nlC%dhi~4&$XIl-#%V\x[uBy2^'ʥzBzGJVJ1 :|O(='A-"zOzŠRqhr*zotG5
:j~&E	R~<ᡌ2OX	dGDcn|{R9اI2+]1xS<n0
}w%PmO&m~{ǖoPxǭO{uM
źK}?btC`t;rÜO?!AG9
w:=IH2ʑGBtvIzB*C3
҄G1AI 7NDQ
bM%uL6Qma1Z8=Xڥ	O'-(>J]vW!b\||鏐'?Aw0]ԕ$֎u7k"	 "hFL`5/bEPfgFkb-A] *+H1lخt$@-q[4rµ5HQNSo*<ލ]ןo+Py_ьZ(Z^RTPsMZḧɁdz$sFB$CΤ`GYV\ZbnFs8֤ј环R _/XfJ:l6Uu`a9ɘ6׬.,j_]](ET!аbwC킀SU|aK*=Mz̍ 5;RQCv/2c\Nk5?|Hc,#]8/U@X	t0F.Q(6HI?GvB+ؽ:l:glR("9OT3^_v1Ӈ"I _&>W' &U2NqW.TY	YJSsQQnE3o15Qмqm_y&uvgqjmU.yY|"Gщ&謟u^cSk6&74֍Zpq:tT>-zNKmt؅':GOn	+ү1k	<,F`.:st{9Rq;a%ǐtҷ'`Re҇o/Gߜ~F8Z-4Q9'h<AJ u 	HgtHACU2ӛD]<ʗ&_2w{6D켥s̹Jn®%snhZ] }QLGz*:0<m)FMٲ:M.Z,Pޗ@xNPh+&UeNRg А6M8(6Vus֭&DzvFuڮN}?WP V#Ō䗿6$"e9F7goQ/>ݩ}@eN;p:&k::foْ'k i:[3&mQL"Mܙ!;8[ncgKNu8h>pƲbN\(f8kaE	Tf NdxN+&8WrʖфOϒܕKtʕ&0Kţo8.Q?^v6\tf:p^?x>TgQKd1+]0Ld4eЭ!mvL)>Az'wH_omӔPb\*>͍w}Ju}pKv(kH~׾!{n6í/ॿ$^~nH ,DRVMl5c%6dBك(_8U"5U	{KQmT˚g{l?kGSfŲ؜j>4v4+dѶtW IB^ჴ	1mCv<uja(dd.
"T($!5gVQ*}I<+ـNxTJRС`n'CϤ
:p*Cª:?POlbMx3+R~rs49#W&;e=j3'qLK>9ڣ'w:[6*Kj  xc`d```a`h+J f37L 
 7\   xc`d``cw?70 Ec ]} xڅTN1].	8х.b`h~ H@HN_G}qV=Ng;.WD@p@kdTľwA}[ϺпM>4Cwe[k{sNkƦ1cXJr~[S8סs#wkˍyy1pۜۂs?hxH5Rci,GegẎBE'"?Ħ){	84{c##𦺦7!gŅJ)F :;~Y{L.i^okD+3`_;O;}^tUW}z@:jѣ'HWh=܃zw{vSYNby`?u7{feUe   xc``#10LbXɆYŃ/VeB؎Ӄs? 	\ugT5]·_߇@@#A-UB.Bۄ+D,D|]"'v@H<M|7	 }?&H]fV.^"JFJGLfY:rZrML{)))PxXxL񏒄Re5ʏT,T
)QޣGCKIcM%5Z<ZNZ˴ttVYMߡ`a#BAgLLL|30c`f\|ESVbVIVlM{`d!aMNNN]׹DsVv}:O7E<yj[;{	_-}?2
)]QPVЉ`3aa~WX%!2+rJQQuQ{Y͢'E	)k[%$$KlJ<ԓt+%9"Xʴw)>;oJᗱ''**sW,I<.˲_ʹ RSC޴[:y;

|
+b+(VU|$J_23^*B*SbUT}ƪ&fAK:u՗kPi<EHTk\6B7:Vu<ӵYC*L ( xc`d``$  L@`>  xuN@ƿC7DQ(V7>Vh6of
Jg 1+d<UkNaMil^<6yo_5/RSՃԣeloȪ0p2T1D}R	ڐTD,专|wzu+|ީ
G^C\FKIg֓؁mmjTP#銖9)b̌Ǻ]wMJgB!.I׌9?&*}PO4Jv~@9">BWRߙyJTLTPFr&-rs&3kjh   xmW_ôpff[8󙙙dAH7Z'X2SqffpYxɾRCu_%*ǗKWQMJeP=KDTQC4Bt1ҽJ`؀=v	;cݰ;{c?8p88
؈ILa1Ya318x'dSqN8glsqb\Kq.Wj\kq\l8b BHDV)=V"F汀E,a7F܄qnmwN܅'xq}A<xO#x:gYx6yx>^Ex1^ex9^WUx5^ux=ހ7Mx3ނmx;ށw]x7ރ}x?>C0>c8>OS4>s</Q|	_WU|_7M|w]|C?OS?/K
o[<?T*ըNjRԡ.(8mh{ځvJδJI{޴Kt HtJtIGmIM4M34KscX:DB't
JtIgtKt]Ht	]Jt]IWt]KבAדIVQ!A=KmPH"F1%RF@DtH7tJtIwg71eB~cOTo*颟)٢+E%'OiݟT$ K<3݆/#QuYO+Ij-"ҥJo}A[W$Xr^ԗ/l^fiYz뇦_efV\&O+J,MȅgACEz%ۑo.۾=#aXb^З~DEҚ~iڠYYTu}95K*j3TӚm"6+=wj^jNbjiK-_N."LEΕX,IRE;3mf{ȳ,H32"Z#~
KkƢj#."2,,¡
jd22d=|
*
;>O*Cxa!si.n)=OKX0qe-h\jYf88ڏv.j/Ew"#v'|SI`X}30WܪN=ΑX4oۗpTB/Ug(1ZlZ`Cʢ8*iEjIc8߬](ʅy8^讌e7E/e\W SZ'Gǲ<KQtS7}U-4қH\5RW2Et}/08P֣,qX]3m곦/摻{ gMgppU5Fɛ-= ߬8pcxZr-b4*N9NpR08xa߶UX{T\ZThk)r
xHcYLY~Z9\ZsλLIӴbOl3-<OXfQEŲɜ%Lf|GŌ4~cX#Nƌ'|>3FD}1/ż`,_T4ك&_#;"鰏iV8P;K-HII:sQǊ)<L*jy%NaeEe
-0}ƿ%ɒ|jdgm]QSk*[dFdk	aa5bDVNHRjN禮L8d^n@v\
#UD<OoH՝fhZ {%e`7DO;2BquLu:Wku~{pFkuhɀF7#i@Z\:;5Z2Kb~|0c\VAih*%#Fj#VX[3E`Ӹh9M-f1ebhjx?w1Bofk)\0*+N2HN_/bXgV.񰹩N-/y\@Ղ*#^'|gdXhroU2MK\hd'TY&$Gˆu֚A5AiOW$162[9 ff݋/YSWlâU1&֯Y}9rS66|I`wдS8K֪ YE
CW-,.%NhgVy/Vd\1CFg15yÊ5e:T$;I;4k_in26f4Je8|zQ;~T3KoH^bAoA\6G,/2	w4KhJuY=O~ʅiKϩrbdgڒ".j2m?*cZEE5^TN2u33uύ7/V֧AuAxB#ʶiܥa>͌82]A:W-sݼi!iR5SQw57̪fN5&F    Rw  <?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata></metadata>
<defs>
<font id="fontawesomeregular" horiz-adv-x="1536" >
<font-face units-per-em="1792" ascent="1536" descent="-256" />
<missing-glyph horiz-adv-x="448" />
<glyph unicode=" "  horiz-adv-x="448" />
<glyph unicode="&#x09;" horiz-adv-x="448" />
<glyph unicode="&#xa0;" horiz-adv-x="448" />
<glyph unicode="&#xa8;" horiz-adv-x="1792" />
<glyph unicode="&#xa9;" horiz-adv-x="1792" />
<glyph unicode="&#xae;" horiz-adv-x="1792" />
<glyph unicode="&#xb4;" horiz-adv-x="1792" />
<glyph unicode="&#xc6;" horiz-adv-x="1792" />
<glyph unicode="&#x2000;" horiz-adv-x="768" />
<glyph unicode="&#x2001;" />
<glyph unicode="&#x2002;" horiz-adv-x="768" />
<glyph unicode="&#x2003;" />
<glyph unicode="&#x2004;" horiz-adv-x="512" />
<glyph unicode="&#x2005;" horiz-adv-x="384" />
<glyph unicode="&#x2006;" horiz-adv-x="256" />
<glyph unicode="&#x2007;" horiz-adv-x="256" />
<glyph unicode="&#x2008;" horiz-adv-x="192" />
<glyph unicode="&#x2009;" horiz-adv-x="307" />
<glyph unicode="&#x200a;" horiz-adv-x="85" />
<glyph unicode="&#x202f;" horiz-adv-x="307" />
<glyph unicode="&#x205f;" horiz-adv-x="384" />
<glyph unicode="&#x2122;" horiz-adv-x="1792" />
<glyph unicode="&#x221e;" horiz-adv-x="1792" />
<glyph unicode="&#x2260;" horiz-adv-x="1792" />
<glyph unicode="&#xe000;" horiz-adv-x="500" d="M0 0z" />
<glyph unicode="&#xf000;" horiz-adv-x="1792" d="M1699 1350q0 -35 -43 -78l-632 -632v-768h320q26 0 45 -19t19 -45t-19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45t45 19h320v768l-632 632q-43 43 -43 78q0 23 18 36.5t38 17.5t43 4h1408q23 0 43 -4t38 -17.5t18 -36.5z" />
<glyph unicode="&#xf001;" d="M1536 1312v-1120q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v537l-768 -237v-709q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89 t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v967q0 31 19 56.5t49 35.5l832 256q12 4 28 4q40 0 68 -28t28 -68z" />
<glyph unicode="&#xf002;" horiz-adv-x="1664" d="M1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -52 -38 -90t-90 -38q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5 t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" />
<glyph unicode="&#xf003;" horiz-adv-x="1792" d="M1664 32v768q-32 -36 -69 -66q-268 -206 -426 -338q-51 -43 -83 -67t-86.5 -48.5t-102.5 -24.5h-1h-1q-48 0 -102.5 24.5t-86.5 48.5t-83 67q-158 132 -426 338q-37 30 -69 66v-768q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1664 1083v11v13.5t-0.5 13 t-3 12.5t-5.5 9t-9 7.5t-14 2.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5q0 -168 147 -284q193 -152 401 -317q6 -5 35 -29.5t46 -37.5t44.5 -31.5t50.5 -27.5t43 -9h1h1q20 0 43 9t50.5 27.5t44.5 31.5t46 37.5t35 29.5q208 165 401 317q54 43 100.5 115.5t46.5 131.5z M1792 1120v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
<glyph unicode="&#xf004;" horiz-adv-x="1792" d="M896 -128q-26 0 -44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124t127 -344q0 -221 -229 -450l-623 -600 q-18 -18 -44 -18z" />
<glyph unicode="&#xf005;" horiz-adv-x="1664" d="M1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -21 -10.5 -35.5t-30.5 -14.5q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455 l502 -73q56 -9 56 -46z" />
<glyph unicode="&#xf006;" horiz-adv-x="1664" d="M1137 532l306 297l-422 62l-189 382l-189 -382l-422 -62l306 -297l-73 -421l378 199l377 -199zM1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -50 -41 -50q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500 l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455l502 -73q56 -9 56 -46z" />
<glyph unicode="&#xf007;" horiz-adv-x="1408" d="M1408 131q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5t43 97.5t62 81t85.5 53.5t111.5 20q9 0 42 -21.5t74.5 -48t108 -48t133.5 -21.5t133.5 21.5t108 48t74.5 48t42 21.5q61 0 111.5 -20t85.5 -53.5t62 -81 t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5z" />
<glyph unicode="&#xf008;" horiz-adv-x="1920" d="M384 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 320v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 704v128q0 26 -19 45t-45 19h-128 q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 -64v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM384 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45 t45 -19h128q26 0 45 19t19 45zM1792 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 704v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1792 320v128 q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 704v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19 t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1920 1248v-1344q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1344q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
<glyph unicode="&#xf009;" horiz-adv-x="1664" d="M768 512v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM768 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 512v-384q0 -52 -38 -90t-90 -38 h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" />
<glyph unicode="&#xf00a;" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 288v-192q0 -40 -28 -68t-68 -28h-320 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28 h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192 q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68z" />
<glyph unicode="&#xf00b;" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-960 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28 h960q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68z" />
<glyph unicode="&#xf00c;" horiz-adv-x="1792" d="M1671 970q0 -40 -28 -68l-724 -724l-136 -136q-28 -28 -68 -28t-68 28l-136 136l-362 362q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -295l656 657q28 28 68 28t68 -28l136 -136q28 -28 28 -68z" />
<glyph unicode="&#xf00d;" horiz-adv-x="1408" d="M1298 214q0 -40 -28 -68l-136 -136q-28 -28 -68 -28t-68 28l-294 294l-294 -294q-28 -28 -68 -28t-68 28l-136 136q-28 28 -28 68t28 68l294 294l-294 294q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -294l294 294q28 28 68 28t68 -28l136 -136q28 -28 28 -68 t-28 -68l-294 -294l294 -294q28 -28 28 -68z" />
<glyph unicode="&#xf00e;" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-224q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v224h-224q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h224v224q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-224h224 q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5 t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" />
<glyph unicode="&#xf010;" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-576q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h576q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5z M1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z " />
<glyph unicode="&#xf011;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61t-298 61t-245 164t-164 245t-61 298q0 182 80.5 343t226.5 270q43 32 95.5 25t83.5 -50q32 -42 24.5 -94.5t-49.5 -84.5q-98 -74 -151.5 -181t-53.5 -228q0 -104 40.5 -198.5t109.5 -163.5t163.5 -109.5 t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5q0 121 -53.5 228t-151.5 181q-42 32 -49.5 84.5t24.5 94.5q31 43 84 50t95 -25q146 -109 226.5 -270t80.5 -343zM896 1408v-640q0 -52 -38 -90t-90 -38t-90 38t-38 90v640q0 52 38 90t90 38t90 -38t38 -90z" />
<glyph unicode="&#xf012;" horiz-adv-x="1792" d="M256 96v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 224v-320q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1024 480v-576q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23 v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1408 864v-960q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 1376v-1472q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1472q0 14 9 23t23 9h192q14 0 23 -9t9 -23z" />
<glyph unicode="&#xf013;" d="M1024 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1536 749v-222q0 -12 -8 -23t-20 -13l-185 -28q-19 -54 -39 -91q35 -50 107 -138q10 -12 10 -25t-9 -23q-27 -37 -99 -108t-94 -71q-12 0 -26 9l-138 108q-44 -23 -91 -38 q-16 -136 -29 -186q-7 -28 -36 -28h-222q-14 0 -24.5 8.5t-11.5 21.5l-28 184q-49 16 -90 37l-141 -107q-10 -9 -25 -9q-14 0 -25 11q-126 114 -165 168q-7 10 -7 23q0 12 8 23q15 21 51 66.5t54 70.5q-27 50 -41 99l-183 27q-13 2 -21 12.5t-8 23.5v222q0 12 8 23t19 13 l186 28q14 46 39 92q-40 57 -107 138q-10 12 -10 24q0 10 9 23q26 36 98.5 107.5t94.5 71.5q13 0 26 -10l138 -107q44 23 91 38q16 136 29 186q7 28 36 28h222q14 0 24.5 -8.5t11.5 -21.5l28 -184q49 -16 90 -37l142 107q9 9 24 9q13 0 25 -10q129 -119 165 -170q7 -8 7 -22 q0 -12 -8 -23q-15 -21 -51 -66.5t-54 -70.5q26 -50 41 -98l183 -28q13 -2 21 -12.5t8 -23.5z" />
<glyph unicode="&#xf014;" horiz-adv-x="1408" d="M512 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM768 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1024 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1152 76v948h-896v-948q0 -22 7 -40.5t14.5 -27t10.5 -8.5h832q3 0 10.5 8.5t14.5 27t7 40.5zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832 q-66 0 -113 58.5t-47 141.5v952h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h309l70 167q15 37 54 63t79 26h320q40 0 79 -26t54 -63l70 -167h309q14 0 23 -9t9 -23z" />
<glyph unicode="&#xf015;" horiz-adv-x="1664" d="M1408 544v-480q0 -26 -19 -45t-45 -19h-384v384h-256v-384h-384q-26 0 -45 19t-19 45v480q0 1 0.5 3t0.5 3l575 474l575 -474q1 -2 1 -6zM1631 613l-62 -74q-8 -9 -21 -11h-3q-13 0 -21 7l-692 577l-692 -577q-12 -8 -24 -7q-13 2 -21 11l-62 74q-8 10 -7 23.5t11 21.5 l719 599q32 26 76 26t76 -26l244 -204v195q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-408l219 -182q10 -8 11 -21.5t-7 -23.5z" />
<glyph unicode="&#xf016;" horiz-adv-x="1280" d="M128 0h1024v768h-416q-40 0 -68 28t-28 68v416h-512v-1280zM768 896h376q-10 29 -22 41l-313 313q-12 12 -41 22v-376zM1280 864v-896q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h640q40 0 88 -20t76 -48l312 -312q28 -28 48 -76t20 -88z " />
<glyph unicode="&#xf017;" d="M896 992v-448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf018;" horiz-adv-x="1920" d="M1111 540v4l-24 320q-1 13 -11 22.5t-23 9.5h-186q-13 0 -23 -9.5t-11 -22.5l-24 -320v-4q-1 -12 8 -20t21 -8h244q12 0 21 8t8 20zM1870 73q0 -73 -46 -73h-704q13 0 22 9.5t8 22.5l-20 256q-1 13 -11 22.5t-23 9.5h-272q-13 0 -23 -9.5t-11 -22.5l-20 -256 q-1 -13 8 -22.5t22 -9.5h-704q-46 0 -46 73q0 54 26 116l417 1044q8 19 26 33t38 14h339q-13 0 -23 -9.5t-11 -22.5l-15 -192q-1 -14 8 -23t22 -9h166q13 0 22 9t8 23l-15 192q-1 13 -11 22.5t-23 9.5h339q20 0 38 -14t26 -33l417 -1044q26 -62 26 -116z" />
<glyph unicode="&#xf019;" horiz-adv-x="1664" d="M1280 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 416v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h465l135 -136 q58 -56 136 -56t136 56l136 136h464q40 0 68 -28t28 -68zM1339 985q17 -41 -14 -70l-448 -448q-18 -19 -45 -19t-45 19l-448 448q-31 29 -14 70q17 39 59 39h256v448q0 26 19 45t45 19h256q26 0 45 -19t19 -45v-448h256q42 0 59 -39z" />
<glyph unicode="&#xf01a;" d="M1120 608q0 -12 -10 -24l-319 -319q-11 -9 -23 -9t-23 9l-320 320q-15 16 -7 35q8 20 30 20h192v352q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-352h192q14 0 23 -9t9 -23zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273 t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf01b;" d="M1118 660q-8 -20 -30 -20h-192v-352q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v352h-192q-14 0 -23 9t-9 23q0 12 10 24l319 319q11 9 23 9t23 -9l320 -320q15 -16 7 -35zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198 t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf01c;" d="M1023 576h316q-1 3 -2.5 8t-2.5 8l-212 496h-708l-212 -496q-1 -2 -2.5 -8t-2.5 -8h316l95 -192h320zM1536 546v-482q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v482q0 62 25 123l238 552q10 25 36.5 42t52.5 17h832q26 0 52.5 -17t36.5 -42l238 -552 q25 -61 25 -123z" />
<glyph unicode="&#xf01d;" d="M1184 640q0 -37 -32 -55l-544 -320q-15 -9 -32 -9q-16 0 -32 8q-32 19 -32 56v640q0 37 32 56q33 18 64 -1l544 -320q32 -18 32 -55zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf01e;" d="M1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l138 138q-148 137 -349 137q-104 0 -198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5q119 0 225 52t179 147q7 10 23 12q14 0 25 -9 l137 -138q9 -8 9.5 -20.5t-7.5 -22.5q-109 -132 -264 -204.5t-327 -72.5q-156 0 -298 61t-245 164t-164 245t-61 298t61 298t164 245t245 164t298 61q147 0 284.5 -55.5t244.5 -156.5l130 129q29 31 70 14q39 -17 39 -59z" />
<glyph unicode="&#xf021;" d="M1511 480q0 -5 -1 -7q-64 -268 -268 -434.5t-478 -166.5q-146 0 -282.5 55t-243.5 157l-129 -129q-19 -19 -45 -19t-45 19t-19 45v448q0 26 19 45t45 19h448q26 0 45 -19t19 -45t-19 -45l-137 -137q71 -66 161 -102t187 -36q134 0 250 65t186 179q11 17 53 117 q8 23 30 23h192q13 0 22.5 -9.5t9.5 -22.5zM1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-26 0 -45 19t-19 45t19 45l138 138q-148 137 -349 137q-134 0 -250 -65t-186 -179q-11 -17 -53 -117q-8 -23 -30 -23h-199q-13 0 -22.5 9.5t-9.5 22.5v7q65 268 270 434.5t480 166.5 q146 0 284 -55.5t245 -156.5l130 129q19 19 45 19t45 -19t19 -45z" />
<glyph unicode="&#xf022;" horiz-adv-x="1792" d="M384 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M384 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1536 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5z M1536 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5zM1536 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5 t9.5 -22.5zM1664 160v832q0 13 -9.5 22.5t-22.5 9.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1792 1248v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47 t47 -113z" />
<glyph unicode="&#xf023;" horiz-adv-x="1152" d="M320 768h512v192q0 106 -75 181t-181 75t-181 -75t-75 -181v-192zM1152 672v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v192q0 184 132 316t316 132t316 -132t132 -316v-192h32q40 0 68 -28t28 -68z" />
<glyph unicode="&#xf024;" horiz-adv-x="1792" d="M320 1280q0 -72 -64 -110v-1266q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v1266q-64 38 -64 110q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -25 -12.5 -38.5t-39.5 -27.5q-215 -116 -369 -116q-61 0 -123.5 22t-108.5 48 t-115.5 48t-142.5 22q-192 0 -464 -146q-17 -9 -33 -9q-26 0 -45 19t-19 45v742q0 32 31 55q21 14 79 43q236 120 421 120q107 0 200 -29t219 -88q38 -19 88 -19q54 0 117.5 21t110 47t88 47t54.5 21q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf025;" horiz-adv-x="1664" d="M1664 650q0 -166 -60 -314l-20 -49l-185 -33q-22 -83 -90.5 -136.5t-156.5 -53.5v-32q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-32q71 0 130 -35.5t93 -95.5l68 12q29 95 29 193q0 148 -88 279t-236.5 209t-315.5 78 t-315.5 -78t-236.5 -209t-88 -279q0 -98 29 -193l68 -12q34 60 93 95.5t130 35.5v32q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v32q-88 0 -156.5 53.5t-90.5 136.5l-185 33l-20 49q-60 148 -60 314q0 151 67 291t179 242.5 t266 163.5t320 61t320 -61t266 -163.5t179 -242.5t67 -291z" />
<glyph unicode="&#xf026;" horiz-adv-x="768" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45z" />
<glyph unicode="&#xf027;" horiz-adv-x="1152" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142z" />
<glyph unicode="&#xf028;" horiz-adv-x="1664" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142zM1408 640q0 -153 -85 -282.5t-225 -188.5q-13 -5 -25 -5q-27 0 -46 19t-19 45q0 39 39 59q56 29 76 44q74 54 115.5 135.5t41.5 173.5t-41.5 173.5 t-115.5 135.5q-20 15 -76 44q-39 20 -39 59q0 26 19 45t45 19q13 0 26 -5q140 -59 225 -188.5t85 -282.5zM1664 640q0 -230 -127 -422.5t-338 -283.5q-13 -5 -26 -5q-26 0 -45 19t-19 45q0 36 39 59q7 4 22.5 10.5t22.5 10.5q46 25 82 51q123 91 192 227t69 289t-69 289 t-192 227q-36 26 -82 51q-7 4 -22.5 10.5t-22.5 10.5q-39 23 -39 59q0 26 19 45t45 19q13 0 26 -5q211 -91 338 -283.5t127 -422.5z" />
<glyph unicode="&#xf029;" horiz-adv-x="1408" d="M384 384v-128h-128v128h128zM384 1152v-128h-128v128h128zM1152 1152v-128h-128v128h128zM128 129h384v383h-384v-383zM128 896h384v384h-384v-384zM896 896h384v384h-384v-384zM640 640v-640h-640v640h640zM1152 128v-128h-128v128h128zM1408 128v-128h-128v128h128z M1408 640v-384h-384v128h-128v-384h-128v640h384v-128h128v128h128zM640 1408v-640h-640v640h640zM1408 1408v-640h-640v640h640z" />
<glyph unicode="&#xf02a;" horiz-adv-x="1792" d="M63 0h-63v1408h63v-1408zM126 1h-32v1407h32v-1407zM220 1h-31v1407h31v-1407zM377 1h-31v1407h31v-1407zM534 1h-62v1407h62v-1407zM660 1h-31v1407h31v-1407zM723 1h-31v1407h31v-1407zM786 1h-31v1407h31v-1407zM943 1h-63v1407h63v-1407zM1100 1h-63v1407h63v-1407z M1226 1h-63v1407h63v-1407zM1352 1h-63v1407h63v-1407zM1446 1h-63v1407h63v-1407zM1635 1h-94v1407h94v-1407zM1698 1h-32v1407h32v-1407zM1792 0h-63v1408h63v-1408z" />
<glyph unicode="&#xf02b;" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91z" />
<glyph unicode="&#xf02c;" horiz-adv-x="1920" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91zM1899 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-36 0 -59 14t-53 45l470 470q37 37 37 90q0 52 -37 91l-715 714q-38 38 -102 64.5t-117 26.5h224q53 0 117 -26.5t102 -64.5l715 -714q37 -39 37 -91z" />
<glyph unicode="&#xf02d;" horiz-adv-x="1664" d="M1639 1058q40 -57 18 -129l-275 -906q-19 -64 -76.5 -107.5t-122.5 -43.5h-923q-77 0 -148.5 53.5t-99.5 131.5q-24 67 -2 127q0 4 3 27t4 37q1 8 -3 21.5t-3 19.5q2 11 8 21t16.5 23.5t16.5 23.5q23 38 45 91.5t30 91.5q3 10 0.5 30t-0.5 28q3 11 17 28t17 23 q21 36 42 92t25 90q1 9 -2.5 32t0.5 28q4 13 22 30.5t22 22.5q19 26 42.5 84.5t27.5 96.5q1 8 -3 25.5t-2 26.5q2 8 9 18t18 23t17 21q8 12 16.5 30.5t15 35t16 36t19.5 32t26.5 23.5t36 11.5t47.5 -5.5l-1 -3q38 9 51 9h761q74 0 114 -56t18 -130l-274 -906 q-36 -119 -71.5 -153.5t-128.5 -34.5h-869q-27 0 -38 -15q-11 -16 -1 -43q24 -70 144 -70h923q29 0 56 15.5t35 41.5l300 987q7 22 5 57q38 -15 59 -43zM575 1056q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5 t-16.5 -22.5zM492 800q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5t-16.5 -22.5z" />
<glyph unicode="&#xf02e;" horiz-adv-x="1280" d="M1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289q0 34 19.5 62t52.5 41q21 9 44 9h1048z" />
<glyph unicode="&#xf02f;" horiz-adv-x="1664" d="M384 0h896v256h-896v-256zM384 640h896v384h-160q-40 0 -68 28t-28 68v160h-640v-640zM1536 576q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 576v-416q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-160q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68 v160h-224q-13 0 -22.5 9.5t-9.5 22.5v416q0 79 56.5 135.5t135.5 56.5h64v544q0 40 28 68t68 28h672q40 0 88 -20t76 -48l152 -152q28 -28 48 -76t20 -88v-256h64q79 0 135.5 -56.5t56.5 -135.5z" />
<glyph unicode="&#xf030;" horiz-adv-x="1920" d="M960 864q119 0 203.5 -84.5t84.5 -203.5t-84.5 -203.5t-203.5 -84.5t-203.5 84.5t-84.5 203.5t84.5 203.5t203.5 84.5zM1664 1280q106 0 181 -75t75 -181v-896q0 -106 -75 -181t-181 -75h-1408q-106 0 -181 75t-75 181v896q0 106 75 181t181 75h224l51 136 q19 49 69.5 84.5t103.5 35.5h512q53 0 103.5 -35.5t69.5 -84.5l51 -136h224zM960 128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
<glyph unicode="&#xf031;" horiz-adv-x="1664" d="M725 977l-170 -450q73 -1 153.5 -2t119 -1.5t52.5 -0.5l29 2q-32 95 -92 241q-53 132 -92 211zM21 -128h-21l2 79q22 7 80 18q89 16 110 31q20 16 48 68l237 616l280 724h75h53l11 -21l205 -480q103 -242 124 -297q39 -102 96 -235q26 -58 65 -164q24 -67 65 -149 q22 -49 35 -57q22 -19 69 -23q47 -6 103 -27q6 -39 6 -57q0 -14 -1 -26q-80 0 -192 8q-93 8 -189 8q-79 0 -135 -2l-200 -11l-58 -2q0 45 4 78l131 28q56 13 68 23q12 12 12 27t-6 32l-47 114l-92 228l-450 2q-29 -65 -104 -274q-23 -64 -23 -84q0 -31 17 -43 q26 -21 103 -32q3 0 13.5 -2t30 -5t40.5 -6q1 -28 1 -58q0 -17 -2 -27q-66 0 -349 20l-48 -8q-81 -14 -167 -14z" />
<glyph unicode="&#xf032;" horiz-adv-x="1408" d="M555 15q76 -32 140 -32q131 0 216 41t122 113q38 70 38 181q0 114 -41 180q-58 94 -141 126q-80 32 -247 32q-74 0 -101 -10v-144l-1 -173l3 -270q0 -15 12 -44zM541 761q43 -7 109 -7q175 0 264 65t89 224q0 112 -85 187q-84 75 -255 75q-52 0 -130 -13q0 -44 2 -77 q7 -122 6 -279l-1 -98q0 -43 1 -77zM0 -128l2 94q45 9 68 12q77 12 123 31q17 27 21 51q9 66 9 194l-2 497q-5 256 -9 404q-1 87 -11 109q-1 4 -12 12q-18 12 -69 15q-30 2 -114 13l-4 83l260 6l380 13l45 1q5 0 14 0.5t14 0.5q1 0 21.5 -0.5t40.5 -0.5h74q88 0 191 -27 q43 -13 96 -39q57 -29 102 -76q44 -47 65 -104t21 -122q0 -70 -32 -128t-95 -105q-26 -20 -150 -77q177 -41 267 -146q92 -106 92 -236q0 -76 -29 -161q-21 -62 -71 -117q-66 -72 -140 -108q-73 -36 -203 -60q-82 -15 -198 -11l-197 4q-84 2 -298 -11q-33 -3 -272 -11z" />
<glyph unicode="&#xf033;" horiz-adv-x="1024" d="M0 -126l17 85q4 1 77 20q76 19 116 39q29 37 41 101l27 139l56 268l12 64q8 44 17 84.5t16 67t12.5 46.5t9 30.5t3.5 11.5l29 157l16 63l22 135l8 50v38q-41 22 -144 28q-28 2 -38 4l19 103l317 -14q39 -2 73 -2q66 0 214 9q33 2 68 4.5t36 2.5q-2 -19 -6 -38 q-7 -29 -13 -51q-55 -19 -109 -31q-64 -16 -101 -31q-12 -31 -24 -88q-9 -44 -13 -82q-44 -199 -66 -306l-61 -311l-38 -158l-43 -235l-12 -45q-2 -7 1 -27q64 -15 119 -21q36 -5 66 -10q-1 -29 -7 -58q-7 -31 -9 -41q-18 0 -23 -1q-24 -2 -42 -2q-9 0 -28 3q-19 4 -145 17 l-198 2q-41 1 -174 -11q-74 -7 -98 -9z" />
<glyph unicode="&#xf034;" horiz-adv-x="1792" d="M81 1407l54 -27q20 -5 211 -5h130l19 3l115 1l215 -1h293l34 -2q14 -1 28 7t21 16l7 8l42 1q15 0 28 -1v-104.5t1 -131.5l1 -100l-1 -58q0 -32 -4 -51q-39 -15 -68 -18q-25 43 -54 128q-8 24 -15.5 62.5t-11.5 65.5t-6 29q-13 15 -27 19q-7 2 -42.5 2t-103.5 -1t-111 -1 q-34 0 -67 -5q-10 -97 -8 -136l1 -152v-332l3 -359l-1 -147q-1 -46 11 -85q49 -25 89 -32q2 0 18 -5t44 -13t43 -12q30 -8 50 -18q5 -45 5 -50q0 -10 -3 -29q-14 -1 -34 -1q-110 0 -187 10q-72 8 -238 8q-88 0 -233 -14q-48 -4 -70 -4q-2 22 -2 26l-1 26v9q21 33 79 49 q139 38 159 50q9 21 12 56q8 192 6 433l-5 428q-1 62 -0.5 118.5t0.5 102.5t-2 57t-6 15q-6 5 -14 6q-38 6 -148 6q-43 0 -100 -13.5t-73 -24.5q-13 -9 -22 -33t-22 -75t-24 -84q-6 -19 -19.5 -32t-20.5 -13q-44 27 -56 44v297v86zM1744 128q33 0 42 -18.5t-11 -44.5 l-126 -162q-20 -26 -49 -26t-49 26l-126 162q-20 26 -11 44.5t42 18.5h80v1024h-80q-33 0 -42 18.5t11 44.5l126 162q20 26 49 26t49 -26l126 -162q20 -26 11 -44.5t-42 -18.5h-80v-1024h80z" />
<glyph unicode="&#xf035;" d="M81 1407l54 -27q20 -5 211 -5h130l19 3l115 1l446 -1h318l34 -2q14 -1 28 7t21 16l7 8l42 1q15 0 28 -1v-104.5t1 -131.5l1 -100l-1 -58q0 -32 -4 -51q-39 -15 -68 -18q-25 43 -54 128q-8 24 -15.5 62.5t-11.5 65.5t-6 29q-13 15 -27 19q-7 2 -58.5 2t-138.5 -1t-128 -1 q-94 0 -127 -5q-10 -97 -8 -136l1 -152v52l3 -359l-1 -147q-1 -46 11 -85q49 -25 89 -32q2 0 18 -5t44 -13t43 -12q30 -8 50 -18q5 -45 5 -50q0 -10 -3 -29q-14 -1 -34 -1q-110 0 -187 10q-72 8 -238 8q-82 0 -233 -13q-45 -5 -70 -5q-2 22 -2 26l-1 26v9q21 33 79 49 q139 38 159 50q9 21 12 56q6 137 6 433l-5 44q0 265 -2 278q-2 11 -6 15q-6 5 -14 6q-38 6 -148 6q-50 0 -168.5 -14t-132.5 -24q-13 -9 -22 -33t-22 -75t-24 -84q-6 -19 -19.5 -32t-20.5 -13q-44 27 -56 44v297v86zM1505 113q26 -20 26 -49t-26 -49l-162 -126 q-26 -20 -44.5 -11t-18.5 42v80h-1024v-80q0 -33 -18.5 -42t-44.5 11l-162 126q-26 20 -26 49t26 49l162 126q26 20 44.5 11t18.5 -42v-80h1024v80q0 33 18.5 42t44.5 -11z" />
<glyph unicode="&#xf036;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf037;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h896q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45t-45 -19 h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h640q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf038;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf039;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf03a;" horiz-adv-x="1792" d="M256 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM256 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5 t9.5 -22.5zM256 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344 q13 0 22.5 -9.5t9.5 -22.5zM256 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5 t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192 q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5z" />
<glyph unicode="&#xf03b;" horiz-adv-x="1792" d="M384 992v-576q0 -13 -9.5 -22.5t-22.5 -9.5q-14 0 -23 9l-288 288q-9 9 -9 23t9 23l288 288q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088 q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" />
<glyph unicode="&#xf03c;" horiz-adv-x="1792" d="M352 704q0 -14 -9 -23l-288 -288q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v576q0 13 9.5 22.5t22.5 9.5q14 0 23 -9l288 -288q9 -9 9 -23zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088 q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" />
<glyph unicode="&#xf03d;" horiz-adv-x="1792" d="M1792 1184v-1088q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-403 403v-166q0 -119 -84.5 -203.5t-203.5 -84.5h-704q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h704q119 0 203.5 -84.5t84.5 -203.5v-165l403 402q18 19 45 19q12 0 25 -5 q39 -17 39 -59z" />
<glyph unicode="&#xf03e;" horiz-adv-x="1920" d="M640 960q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 576v-448h-1408v192l320 320l160 -160l512 512zM1760 1280h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5v1216 q0 13 -9.5 22.5t-22.5 9.5zM1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
<glyph unicode="&#xf040;" d="M363 0l91 91l-235 235l-91 -91v-107h128v-128h107zM886 928q0 22 -22 22q-10 0 -17 -7l-542 -542q-7 -7 -7 -17q0 -22 22 -22q10 0 17 7l542 542q7 7 7 17zM832 1120l416 -416l-832 -832h-416v416zM1515 1024q0 -53 -37 -90l-166 -166l-416 416l166 165q36 38 90 38 q53 0 91 -38l235 -234q37 -39 37 -91z" />
<glyph unicode="&#xf041;" horiz-adv-x="1024" d="M768 896q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1024 896q0 -109 -33 -179l-364 -774q-16 -33 -47.5 -52t-67.5 -19t-67.5 19t-46.5 52l-365 774q-33 70 -33 179q0 212 150 362t362 150t362 -150t150 -362z" />
<glyph unicode="&#xf042;" d="M768 96v1088q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf043;" horiz-adv-x="1024" d="M512 384q0 36 -20 69q-1 1 -15.5 22.5t-25.5 38t-25 44t-21 50.5q-4 16 -21 16t-21 -16q-7 -23 -21 -50.5t-25 -44t-25.5 -38t-15.5 -22.5q-20 -33 -20 -69q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 512q0 -212 -150 -362t-362 -150t-362 150t-150 362 q0 145 81 275q6 9 62.5 90.5t101 151t99.5 178t83 201.5q9 30 34 47t51 17t51.5 -17t33.5 -47q28 -93 83 -201.5t99.5 -178t101 -151t62.5 -90.5q81 -127 81 -275z" />
<glyph unicode="&#xf044;" horiz-adv-x="1792" d="M888 352l116 116l-152 152l-116 -116v-56h96v-96h56zM1328 1072q-16 16 -33 -1l-350 -350q-17 -17 -1 -33t33 1l350 350q17 17 1 33zM1408 478v-190q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-14 -14 -32 -8q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v126q0 13 9 22l64 64q15 15 35 7t20 -29zM1312 1216l288 -288l-672 -672h-288v288zM1756 1084l-92 -92 l-288 288l92 92q28 28 68 28t68 -28l152 -152q28 -28 28 -68t-28 -68z" />
<glyph unicode="&#xf045;" horiz-adv-x="1664" d="M1408 547v-259q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h255v0q13 0 22.5 -9.5t9.5 -22.5q0 -27 -26 -32q-77 -26 -133 -60q-10 -4 -16 -4h-112q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832 q66 0 113 47t47 113v214q0 19 18 29q28 13 54 37q16 16 35 8q21 -9 21 -29zM1645 1043l-384 -384q-18 -19 -45 -19q-12 0 -25 5q-39 17 -39 59v192h-160q-323 0 -438 -131q-119 -137 -74 -473q3 -23 -20 -34q-8 -2 -12 -2q-16 0 -26 13q-10 14 -21 31t-39.5 68.5t-49.5 99.5 t-38.5 114t-17.5 122q0 49 3.5 91t14 90t28 88t47 81.5t68.5 74t94.5 61.5t124.5 48.5t159.5 30.5t196.5 11h160v192q0 42 39 59q13 5 25 5q26 0 45 -19l384 -384q19 -19 19 -45t-19 -45z" />
<glyph unicode="&#xf046;" horiz-adv-x="1664" d="M1408 606v-318q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-10 -10 -23 -10q-3 0 -9 2q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832 q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v254q0 13 9 22l64 64q10 10 23 10q6 0 12 -3q20 -8 20 -29zM1639 1095l-814 -814q-24 -24 -57 -24t-57 24l-430 430q-24 24 -24 57t24 57l110 110q24 24 57 24t57 -24l263 -263l647 647q24 24 57 24t57 -24l110 -110 q24 -24 24 -57t-24 -57z" />
<glyph unicode="&#xf047;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-384v-384h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v384h-384v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45 t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h384v384h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45t-19 -45t-45 -19h-128v-384h384v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" />
<glyph unicode="&#xf048;" horiz-adv-x="1024" d="M979 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19z" />
<glyph unicode="&#xf049;" horiz-adv-x="1792" d="M1747 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19l710 710 q19 19 32 13t13 -32v-710q4 11 13 19z" />
<glyph unicode="&#xf04a;" horiz-adv-x="1664" d="M1619 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-8 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-19 19 -19 45t19 45l710 710q19 19 32 13t13 -32v-710q5 11 13 19z" />
<glyph unicode="&#xf04b;" horiz-adv-x="1408" d="M1384 609l-1328 -738q-23 -13 -39.5 -3t-16.5 36v1472q0 26 16.5 36t39.5 -3l1328 -738q23 -13 23 -31t-23 -31z" />
<glyph unicode="&#xf04c;" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45zM640 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf04d;" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf04e;" horiz-adv-x="1664" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q19 -19 19 -45t-19 -45l-710 -710q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" />
<glyph unicode="&#xf050;" horiz-adv-x="1792" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19l-710 -710 q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" />
<glyph unicode="&#xf051;" horiz-adv-x="1024" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19z" />
<glyph unicode="&#xf052;" horiz-adv-x="1538" d="M14 557l710 710q19 19 45 19t45 -19l710 -710q19 -19 13 -32t-32 -13h-1472q-26 0 -32 13t13 32zM1473 0h-1408q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1408q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19z" />
<glyph unicode="&#xf053;" horiz-adv-x="1152" d="M742 -37l-652 651q-37 37 -37 90.5t37 90.5l652 651q37 37 90.5 37t90.5 -37l75 -75q37 -37 37 -90.5t-37 -90.5l-486 -486l486 -485q37 -38 37 -91t-37 -90l-75 -75q-37 -37 -90.5 -37t-90.5 37z" />
<glyph unicode="&#xf054;" horiz-adv-x="1152" d="M1099 704q0 -52 -37 -91l-652 -651q-37 -37 -90 -37t-90 37l-76 75q-37 39 -37 91q0 53 37 90l486 486l-486 485q-37 39 -37 91q0 53 37 90l76 75q36 38 90 38t90 -38l652 -651q37 -37 37 -90z" />
<glyph unicode="&#xf055;" d="M1216 576v128q0 26 -19 45t-45 19h-256v256q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-256h-256q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h256v-256q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v256h256q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5 t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf056;" d="M1216 576v128q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5 t103 -385.5z" />
<glyph unicode="&#xf057;" d="M1149 414q0 26 -19 45l-181 181l181 181q19 19 19 45q0 27 -19 46l-90 90q-19 19 -46 19q-26 0 -45 -19l-181 -181l-181 181q-19 19 -45 19q-27 0 -46 -19l-90 -90q-19 -19 -19 -46q0 -26 19 -45l181 -181l-181 -181q-19 -19 -19 -45q0 -27 19 -46l90 -90q19 -19 46 -19 q26 0 45 19l181 181l181 -181q19 -19 45 -19q27 0 46 19l90 90q19 19 19 46zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf058;" d="M1284 802q0 28 -18 46l-91 90q-19 19 -45 19t-45 -19l-408 -407l-226 226q-19 19 -45 19t-45 -19l-91 -90q-18 -18 -18 -46q0 -27 18 -45l362 -362q19 -19 45 -19q27 0 46 19l543 543q18 18 18 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf059;" d="M896 160v192q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h192q14 0 23 9t9 23zM1152 832q0 88 -55.5 163t-138.5 116t-170 41q-243 0 -371 -213q-15 -24 8 -42l132 -100q7 -6 19 -6q16 0 25 12q53 68 86 92q34 24 86 24q48 0 85.5 -26t37.5 -59 q0 -38 -20 -61t-68 -45q-63 -28 -115.5 -86.5t-52.5 -125.5v-36q0 -14 9 -23t23 -9h192q14 0 23 9t9 23q0 19 21.5 49.5t54.5 49.5q32 18 49 28.5t46 35t44.5 48t28 60.5t12.5 81zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf05a;" d="M1024 160v160q0 14 -9 23t-23 9h-96v512q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h96v-320h-96q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h448q14 0 23 9t9 23zM896 1056v160q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23 t23 -9h192q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf05b;" d="M1197 512h-109q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h109q-32 108 -112.5 188.5t-188.5 112.5v-109q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v109q-108 -32 -188.5 -112.5t-112.5 -188.5h109q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-109 q32 -108 112.5 -188.5t188.5 -112.5v109q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-109q108 32 188.5 112.5t112.5 188.5zM1536 704v-128q0 -26 -19 -45t-45 -19h-143q-37 -161 -154.5 -278.5t-278.5 -154.5v-143q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v143 q-161 37 -278.5 154.5t-154.5 278.5h-143q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h143q37 161 154.5 278.5t278.5 154.5v143q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-143q161 -37 278.5 -154.5t154.5 -278.5h143q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf05c;" d="M1097 457l-146 -146q-10 -10 -23 -10t-23 10l-137 137l-137 -137q-10 -10 -23 -10t-23 10l-146 146q-10 10 -10 23t10 23l137 137l-137 137q-10 10 -10 23t10 23l146 146q10 10 23 10t23 -10l137 -137l137 137q10 10 23 10t23 -10l146 -146q10 -10 10 -23t-10 -23 l-137 -137l137 -137q10 -10 10 -23t-10 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5 t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf05d;" d="M1171 723l-422 -422q-19 -19 -45 -19t-45 19l-294 294q-19 19 -19 45t19 45l102 102q19 19 45 19t45 -19l147 -147l275 275q19 19 45 19t45 -19l102 -102q19 -19 19 -45t-19 -45zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198 t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf05e;" d="M1312 643q0 161 -87 295l-754 -753q137 -89 297 -89q111 0 211.5 43.5t173.5 116.5t116 174.5t43 212.5zM313 344l755 754q-135 91 -300 91q-148 0 -273 -73t-198 -199t-73 -274q0 -162 89 -299zM1536 643q0 -157 -61 -300t-163.5 -246t-245 -164t-298.5 -61t-298.5 61 t-245 164t-163.5 246t-61 300t61 299.5t163.5 245.5t245 164t298.5 61t298.5 -61t245 -164t163.5 -245.5t61 -299.5z" />
<glyph unicode="&#xf060;" d="M1536 640v-128q0 -53 -32.5 -90.5t-84.5 -37.5h-704l293 -294q38 -36 38 -90t-38 -90l-75 -76q-37 -37 -90 -37q-52 0 -91 37l-651 652q-37 37 -37 90q0 52 37 91l651 650q38 38 91 38q52 0 90 -38l75 -74q38 -38 38 -91t-38 -91l-293 -293h704q52 0 84.5 -37.5 t32.5 -90.5z" />
<glyph unicode="&#xf061;" d="M1472 576q0 -54 -37 -91l-651 -651q-39 -37 -91 -37q-51 0 -90 37l-75 75q-38 38 -38 91t38 91l293 293h-704q-52 0 -84.5 37.5t-32.5 90.5v128q0 53 32.5 90.5t84.5 37.5h704l-293 294q-38 36 -38 90t38 90l75 75q38 38 90 38q53 0 91 -38l651 -651q37 -35 37 -90z" />
<glyph unicode="&#xf062;" horiz-adv-x="1664" d="M1611 565q0 -51 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-294 293v-704q0 -52 -37.5 -84.5t-90.5 -32.5h-128q-53 0 -90.5 32.5t-37.5 84.5v704l-294 -293q-36 -38 -90 -38t-90 38l-75 75q-38 38 -38 90q0 53 38 91l651 651q35 37 90 37q54 0 91 -37l651 -651 q37 -39 37 -91z" />
<glyph unicode="&#xf063;" horiz-adv-x="1664" d="M1611 704q0 -53 -37 -90l-651 -652q-39 -37 -91 -37q-53 0 -90 37l-651 652q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l294 -294v704q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-704l294 294q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" />
<glyph unicode="&#xf064;" horiz-adv-x="1792" d="M1792 896q0 -26 -19 -45l-512 -512q-19 -19 -45 -19t-45 19t-19 45v256h-224q-98 0 -175.5 -6t-154 -21.5t-133 -42.5t-105.5 -69.5t-80 -101t-48.5 -138.5t-17.5 -181q0 -55 5 -123q0 -6 2.5 -23.5t2.5 -26.5q0 -15 -8.5 -25t-23.5 -10q-16 0 -28 17q-7 9 -13 22 t-13.5 30t-10.5 24q-127 285 -127 451q0 199 53 333q162 403 875 403h224v256q0 26 19 45t45 19t45 -19l512 -512q19 -19 19 -45z" />
<glyph unicode="&#xf065;" d="M755 480q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23zM1536 1344v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332 q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf066;" d="M768 576v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45zM1523 1248q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45 t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23z" />
<glyph unicode="&#xf067;" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-416v-416q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v416h-416q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h416v416q0 40 28 68t68 28h192q40 0 68 -28t28 -68v-416h416q40 0 68 -28t28 -68z" />
<glyph unicode="&#xf068;" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-1216q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h1216q40 0 68 -28t28 -68z" />
<glyph unicode="&#xf069;" horiz-adv-x="1664" d="M1482 486q46 -26 59.5 -77.5t-12.5 -97.5l-64 -110q-26 -46 -77.5 -59.5t-97.5 12.5l-266 153v-307q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v307l-266 -153q-46 -26 -97.5 -12.5t-77.5 59.5l-64 110q-26 46 -12.5 97.5t59.5 77.5l266 154l-266 154 q-46 26 -59.5 77.5t12.5 97.5l64 110q26 46 77.5 59.5t97.5 -12.5l266 -153v307q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-307l266 153q46 26 97.5 12.5t77.5 -59.5l64 -110q26 -46 12.5 -97.5t-59.5 -77.5l-266 -154z" />
<glyph unicode="&#xf06a;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM896 161v190q0 14 -9 23.5t-22 9.5h-192q-13 0 -23 -10t-10 -23v-190q0 -13 10 -23t23 -10h192 q13 0 22 9.5t9 23.5zM894 505l18 621q0 12 -10 18q-10 8 -24 8h-220q-14 0 -24 -8q-10 -6 -10 -18l17 -621q0 -10 10 -17.5t24 -7.5h185q14 0 23.5 7.5t10.5 17.5z" />
<glyph unicode="&#xf06b;" d="M928 180v56v468v192h-320v-192v-468v-56q0 -25 18 -38.5t46 -13.5h192q28 0 46 13.5t18 38.5zM472 1024h195l-126 161q-26 31 -69 31q-40 0 -68 -28t-28 -68t28 -68t68 -28zM1160 1120q0 40 -28 68t-68 28q-43 0 -69 -31l-125 -161h194q40 0 68 28t28 68zM1536 864v-320 q0 -14 -9 -23t-23 -9h-96v-416q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v416h-96q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h440q-93 0 -158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5q107 0 168 -77l128 -165l128 165q61 77 168 77q93 0 158.5 -65.5t65.5 -158.5 t-65.5 -158.5t-158.5 -65.5h440q14 0 23 -9t9 -23z" />
<glyph unicode="&#xf06c;" horiz-adv-x="1792" d="M1280 832q0 26 -19 45t-45 19q-172 0 -318 -49.5t-259.5 -134t-235.5 -219.5q-19 -21 -19 -45q0 -26 19 -45t45 -19q24 0 45 19q27 24 74 71t67 66q137 124 268.5 176t313.5 52q26 0 45 19t19 45zM1792 1030q0 -95 -20 -193q-46 -224 -184.5 -383t-357.5 -268 q-214 -108 -438 -108q-148 0 -286 47q-15 5 -88 42t-96 37q-16 0 -39.5 -32t-45 -70t-52.5 -70t-60 -32q-30 0 -51 11t-31 24t-27 42q-2 4 -6 11t-5.5 10t-3 9.5t-1.5 13.5q0 35 31 73.5t68 65.5t68 56t31 48q0 4 -14 38t-16 44q-9 51 -9 104q0 115 43.5 220t119 184.5 t170.5 139t204 95.5q55 18 145 25.5t179.5 9t178.5 6t163.5 24t113.5 56.5l29.5 29.5t29.5 28t27 20t36.5 16t43.5 4.5q39 0 70.5 -46t47.5 -112t24 -124t8 -96z" />
<glyph unicode="&#xf06d;" horiz-adv-x="1408" d="M1408 -160v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1152 896q0 -78 -24.5 -144t-64 -112.5t-87.5 -88t-96 -77.5t-87.5 -72t-64 -81.5t-24.5 -96.5q0 -96 67 -224l-4 1l1 -1 q-90 41 -160 83t-138.5 100t-113.5 122.5t-72.5 150.5t-27.5 184q0 78 24.5 144t64 112.5t87.5 88t96 77.5t87.5 72t64 81.5t24.5 96.5q0 94 -66 224l3 -1l-1 1q90 -41 160 -83t138.5 -100t113.5 -122.5t72.5 -150.5t27.5 -184z" />
<glyph unicode="&#xf06e;" horiz-adv-x="1792" d="M1664 576q-152 236 -381 353q61 -104 61 -225q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 121 61 225q-229 -117 -381 -353q133 -205 333.5 -326.5t434.5 -121.5t434.5 121.5t333.5 326.5zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5 t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1792 576q0 -34 -20 -69q-140 -230 -376.5 -368.5t-499.5 -138.5t-499.5 139t-376.5 368q-20 35 -20 69t20 69q140 229 376.5 368t499.5 139t499.5 -139t376.5 -368q20 -35 20 -69z" />
<glyph unicode="&#xf070;" horiz-adv-x="1792" d="M555 201l78 141q-87 63 -136 159t-49 203q0 121 61 225q-229 -117 -381 -353q167 -258 427 -375zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1307 1151q0 -7 -1 -9 q-105 -188 -315 -566t-316 -567l-49 -89q-10 -16 -28 -16q-12 0 -134 70q-16 10 -16 28q0 12 44 87q-143 65 -263.5 173t-208.5 245q-20 31 -20 69t20 69q153 235 380 371t496 136q89 0 180 -17l54 97q10 16 28 16q5 0 18 -6t31 -15.5t33 -18.5t31.5 -18.5t19.5 -11.5 q16 -10 16 -27zM1344 704q0 -139 -79 -253.5t-209 -164.5l280 502q8 -45 8 -84zM1792 576q0 -35 -20 -69q-39 -64 -109 -145q-150 -172 -347.5 -267t-419.5 -95l74 132q212 18 392.5 137t301.5 307q-115 179 -282 294l63 112q95 -64 182.5 -153t144.5 -184q20 -34 20 -69z " />
<glyph unicode="&#xf071;" horiz-adv-x="1792" d="M1024 161v190q0 14 -9.5 23.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -23.5v-190q0 -14 9.5 -23.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 23.5zM1022 535l18 459q0 12 -10 19q-13 11 -24 11h-220q-11 0 -24 -11q-10 -7 -10 -21l17 -457q0 -10 10 -16.5t24 -6.5h185 q14 0 23.5 6.5t10.5 16.5zM1008 1469l768 -1408q35 -63 -2 -126q-17 -29 -46.5 -46t-63.5 -17h-1536q-34 0 -63.5 17t-46.5 46q-37 63 -2 126l768 1408q17 31 47 49t65 18t65 -18t47 -49z" />
<glyph unicode="&#xf072;" horiz-adv-x="1408" d="M1376 1376q44 -52 12 -148t-108 -172l-161 -161l160 -696q5 -19 -12 -33l-128 -96q-7 -6 -19 -6q-4 0 -7 1q-15 3 -21 16l-279 508l-259 -259l53 -194q5 -17 -8 -31l-96 -96q-9 -9 -23 -9h-2q-15 2 -24 13l-189 252l-252 189q-11 7 -13 23q-1 13 9 25l96 97q9 9 23 9 q6 0 8 -1l194 -53l259 259l-508 279q-14 8 -17 24q-2 16 9 27l128 128q14 13 30 8l665 -159l160 160q76 76 172 108t148 -12z" />
<glyph unicode="&#xf073;" horiz-adv-x="1664" d="M128 -128h288v288h-288v-288zM480 -128h320v288h-320v-288zM128 224h288v320h-288v-320zM480 224h320v320h-320v-320zM128 608h288v288h-288v-288zM864 -128h320v288h-320v-288zM480 608h320v288h-320v-288zM1248 -128h288v288h-288v-288zM864 224h320v320h-320v-320z M512 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1248 224h288v320h-288v-320zM864 608h320v288h-320v-288zM1248 608h288v288h-288v-288zM1280 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64 q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47 h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
<glyph unicode="&#xf074;" horiz-adv-x="1792" d="M666 1055q-60 -92 -137 -273q-22 45 -37 72.5t-40.5 63.5t-51 56.5t-63 35t-81.5 14.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q250 0 410 -225zM1792 256q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192q-32 0 -85 -0.5t-81 -1t-73 1 t-71 5t-64 10.5t-63 18.5t-58 28.5t-59 40t-55 53.5t-56 69.5q59 93 136 273q22 -45 37 -72.5t40.5 -63.5t51 -56.5t63 -35t81.5 -14.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1792 1152q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5 v192h-256q-48 0 -87 -15t-69 -45t-51 -61.5t-45 -77.5q-32 -62 -78 -171q-29 -66 -49.5 -111t-54 -105t-64 -100t-74 -83t-90 -68.5t-106.5 -42t-128 -16.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q48 0 87 15t69 45t51 61.5t45 77.5q32 62 78 171q29 66 49.5 111 t54 105t64 100t74 83t90 68.5t106.5 42t128 16.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" />
<glyph unicode="&#xf075;" horiz-adv-x="1792" d="M1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22q-17 -2 -30.5 9t-17.5 29v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281 q0 130 71 248.5t191 204.5t286 136.5t348 50.5q244 0 450 -85.5t326 -233t120 -321.5z" />
<glyph unicode="&#xf076;" d="M1536 704v-128q0 -201 -98.5 -362t-274 -251.5t-395.5 -90.5t-395.5 90.5t-274 251.5t-98.5 362v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-128q0 -52 23.5 -90t53.5 -57t71 -30t64 -13t44 -2t44 2t64 13t71 30t53.5 57t23.5 90v128q0 26 19 45t45 19h384 q26 0 45 -19t19 -45zM512 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45zM1536 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf077;" horiz-adv-x="1664" d="M1611 320q0 -53 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-486 485l-486 -485q-36 -38 -90 -38t-90 38l-75 75q-38 36 -38 90q0 53 38 91l651 651q37 37 90 37q52 0 91 -37l650 -651q38 -38 38 -91z" />
<glyph unicode="&#xf078;" horiz-adv-x="1664" d="M1611 832q0 -53 -37 -90l-651 -651q-38 -38 -91 -38q-54 0 -90 38l-651 651q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l486 -486l486 486q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" />
<glyph unicode="&#xf079;" horiz-adv-x="1920" d="M1280 32q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-8 0 -13.5 2t-9 7t-5.5 8t-3 11.5t-1 11.5v13v11v160v416h-192q-26 0 -45 19t-19 45q0 24 15 41l320 384q19 22 49 22t49 -22l320 -384q15 -17 15 -41q0 -26 -19 -45t-45 -19h-192v-384h576q16 0 25 -11l160 -192q7 -11 7 -21 zM1920 448q0 -24 -15 -41l-320 -384q-20 -23 -49 -23t-49 23l-320 384q-15 17 -15 41q0 26 19 45t45 19h192v384h-576q-16 0 -25 12l-160 192q-7 9 -7 20q0 13 9.5 22.5t22.5 9.5h960q8 0 13.5 -2t9 -7t5.5 -8t3 -11.5t1 -11.5v-13v-11v-160v-416h192q26 0 45 -19t19 -45z " />
<glyph unicode="&#xf07a;" horiz-adv-x="1664" d="M640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5 l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5 t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf07b;" horiz-adv-x="1664" d="M1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" />
<glyph unicode="&#xf07c;" horiz-adv-x="1920" d="M1879 584q0 -31 -31 -66l-336 -396q-43 -51 -120.5 -86.5t-143.5 -35.5h-1088q-34 0 -60.5 13t-26.5 43q0 31 31 66l336 396q43 51 120.5 86.5t143.5 35.5h1088q34 0 60.5 -13t26.5 -43zM1536 928v-160h-832q-94 0 -197 -47.5t-164 -119.5l-337 -396l-5 -6q0 4 -0.5 12.5 t-0.5 12.5v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158z" />
<glyph unicode="&#xf07d;" horiz-adv-x="768" d="M704 1216q0 -26 -19 -45t-45 -19h-128v-1024h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v1024h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45z" />
<glyph unicode="&#xf07e;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-1024v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h1024v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" />
<glyph unicode="&#xf080;" horiz-adv-x="1920" d="M512 512v-384h-256v384h256zM896 1024v-896h-256v896h256zM1280 768v-640h-256v640h256zM1664 1152v-1024h-256v1024h256zM1792 32v1216q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5z M1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
<glyph unicode="&#xf081;" d="M1280 926q-56 -25 -121 -34q68 40 93 117q-65 -38 -134 -51q-61 66 -153 66q-87 0 -148.5 -61.5t-61.5 -148.5q0 -29 5 -48q-129 7 -242 65t-192 155q-29 -50 -29 -106q0 -114 91 -175q-47 1 -100 26v-2q0 -75 50 -133.5t123 -72.5q-29 -8 -51 -8q-13 0 -39 4 q21 -63 74.5 -104t121.5 -42q-116 -90 -261 -90q-26 0 -50 3q148 -94 322 -94q112 0 210 35.5t168 95t120.5 137t75 162t24.5 168.5q0 18 -1 27q63 45 105 109zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5 t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf082;" d="M1307 618l23 219h-198v109q0 49 15.5 68.5t71.5 19.5h110v219h-175q-152 0 -218 -72t-66 -213v-131h-131v-219h131v-635h262v635h175zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960 q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf083;" horiz-adv-x="1792" d="M928 704q0 14 -9 23t-23 9q-66 0 -113 -47t-47 -113q0 -14 9 -23t23 -9t23 9t9 23q0 40 28 68t68 28q14 0 23 9t9 23zM1152 574q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM128 0h1536v128h-1536v-128zM1280 574q0 159 -112.5 271.5 t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM256 1216h384v128h-384v-128zM128 1024h1536v118v138h-828l-64 -128h-644v-128zM1792 1280v-1280q0 -53 -37.5 -90.5t-90.5 -37.5h-1536q-53 0 -90.5 37.5t-37.5 90.5v1280 q0 53 37.5 90.5t90.5 37.5h1536q53 0 90.5 -37.5t37.5 -90.5z" />
<glyph unicode="&#xf084;" horiz-adv-x="1792" d="M832 1024q0 80 -56 136t-136 56t-136 -56t-56 -136q0 -42 19 -83q-41 19 -83 19q-80 0 -136 -56t-56 -136t56 -136t136 -56t136 56t56 136q0 42 -19 83q41 -19 83 -19q80 0 136 56t56 136zM1683 320q0 -17 -49 -66t-66 -49q-9 0 -28.5 16t-36.5 33t-38.5 40t-24.5 26 l-96 -96l220 -220q28 -28 28 -68q0 -42 -39 -81t-81 -39q-40 0 -68 28l-671 671q-176 -131 -365 -131q-163 0 -265.5 102.5t-102.5 265.5q0 160 95 313t248 248t313 95q163 0 265.5 -102.5t102.5 -265.5q0 -189 -131 -365l355 -355l96 96q-3 3 -26 24.5t-40 38.5t-33 36.5 t-16 28.5q0 17 49 66t66 49q13 0 23 -10q6 -6 46 -44.5t82 -79.5t86.5 -86t73 -78t28.5 -41z" />
<glyph unicode="&#xf085;" horiz-adv-x="1920" d="M896 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1664 128q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1152q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1280 731v-185q0 -10 -7 -19.5t-16 -10.5l-155 -24q-11 -35 -32 -76q34 -48 90 -115q7 -10 7 -20q0 -12 -7 -19q-23 -30 -82.5 -89.5t-78.5 -59.5q-11 0 -21 7l-115 90q-37 -19 -77 -31q-11 -108 -23 -155q-7 -24 -30 -24h-186q-11 0 -20 7.5t-10 17.5 l-23 153q-34 10 -75 31l-118 -89q-7 -7 -20 -7q-11 0 -21 8q-144 133 -144 160q0 9 7 19q10 14 41 53t47 61q-23 44 -35 82l-152 24q-10 1 -17 9.5t-7 19.5v185q0 10 7 19.5t16 10.5l155 24q11 35 32 76q-34 48 -90 115q-7 11 -7 20q0 12 7 20q22 30 82 89t79 59q11 0 21 -7 l115 -90q34 18 77 32q11 108 23 154q7 24 30 24h186q11 0 20 -7.5t10 -17.5l23 -153q34 -10 75 -31l118 89q8 7 20 7q11 0 21 -8q144 -133 144 -160q0 -9 -7 -19q-12 -16 -42 -54t-45 -60q23 -48 34 -82l152 -23q10 -2 17 -10.5t7 -19.5zM1920 198v-140q0 -16 -149 -31 q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20 t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31zM1920 1222v-140q0 -16 -149 -31q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68 q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70 q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31z" />
<glyph unicode="&#xf086;" horiz-adv-x="1792" d="M1408 768q0 -139 -94 -257t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224 q0 139 94 257t256.5 186.5t353.5 68.5t353.5 -68.5t256.5 -186.5t94 -257zM1792 512q0 -120 -71 -224.5t-195 -176.5q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7 q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230z" />
<glyph unicode="&#xf087;" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 768q0 51 -39 89.5t-89 38.5h-352q0 58 48 159.5t48 160.5q0 98 -32 145t-128 47q-26 -26 -38 -85t-30.5 -125.5t-59.5 -109.5q-22 -23 -77 -91q-4 -5 -23 -30t-31.5 -41t-34.5 -42.5 t-40 -44t-38.5 -35.5t-40 -27t-35.5 -9h-32v-640h32q13 0 31.5 -3t33 -6.5t38 -11t35 -11.5t35.5 -12.5t29 -10.5q211 -73 342 -73h121q192 0 192 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5q32 1 53.5 47t21.5 81zM1536 769 q0 -89 -49 -163q9 -33 9 -69q0 -77 -38 -144q3 -21 3 -43q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5h-36h-93q-96 0 -189.5 22.5t-216.5 65.5q-116 40 -138 40h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h274q36 24 137 155q58 75 107 128 q24 25 35.5 85.5t30.5 126.5t62 108q39 37 90 37q84 0 151 -32.5t102 -101.5t35 -186q0 -93 -48 -192h176q104 0 180 -76t76 -179z" />
<glyph unicode="&#xf088;" d="M256 1088q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 512q0 35 -21.5 81t-53.5 47q15 17 25 47.5t10 55.5q0 69 -53 119q18 32 18 69t-17.5 73.5t-47.5 52.5q5 30 5 56q0 85 -49 126t-136 41h-128q-131 0 -342 -73q-5 -2 -29 -10.5 t-35.5 -12.5t-35 -11.5t-38 -11t-33 -6.5t-31.5 -3h-32v-640h32q16 0 35.5 -9t40 -27t38.5 -35.5t40 -44t34.5 -42.5t31.5 -41t23 -30q55 -68 77 -91q41 -43 59.5 -109.5t30.5 -125.5t38 -85q96 0 128 47t32 145q0 59 -48 160.5t-48 159.5h352q50 0 89 38.5t39 89.5z M1536 511q0 -103 -76 -179t-180 -76h-176q48 -99 48 -192q0 -118 -35 -186q-35 -69 -102 -101.5t-151 -32.5q-51 0 -90 37q-34 33 -54 82t-25.5 90.5t-17.5 84.5t-31 64q-48 50 -107 127q-101 131 -137 155h-274q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5 h288q22 0 138 40q128 44 223 66t200 22h112q140 0 226.5 -79t85.5 -216v-5q60 -77 60 -178q0 -22 -3 -43q38 -67 38 -144q0 -36 -9 -69q49 -74 49 -163z" />
<glyph unicode="&#xf089;" horiz-adv-x="896" d="M832 1504v-1339l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41z" />
<glyph unicode="&#xf08a;" horiz-adv-x="1792" d="M1664 940q0 81 -21.5 143t-55 98.5t-81.5 59.5t-94 31t-98 8t-112 -25.5t-110.5 -64t-86.5 -72t-60 -61.5q-18 -22 -49 -22t-49 22q-24 28 -60 61.5t-86.5 72t-110.5 64t-112 25.5t-98 -8t-94 -31t-81.5 -59.5t-55 -98.5t-21.5 -143q0 -168 187 -355l581 -560l580 559 q188 188 188 356zM1792 940q0 -221 -229 -450l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5 q224 0 351 -124t127 -344z" />
<glyph unicode="&#xf08b;" horiz-adv-x="1664" d="M640 96q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h320q13 0 22.5 -9.5t9.5 -22.5q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-66 0 -113 -47t-47 -113v-704 q0 -66 47 -113t113 -47h288h11h13t11.5 -1t11.5 -3t8 -5.5t7 -9t2 -13.5zM1568 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45z" />
<glyph unicode="&#xf08c;" d="M237 122h231v694h-231v-694zM483 1030q-1 52 -36 86t-93 34t-94.5 -34t-36.5 -86q0 -51 35.5 -85.5t92.5 -34.5h1q59 0 95 34.5t36 85.5zM1068 122h231v398q0 154 -73 233t-193 79q-136 0 -209 -117h2v101h-231q3 -66 0 -694h231v388q0 38 7 56q15 35 45 59.5t74 24.5 q116 0 116 -157v-371zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf08d;" horiz-adv-x="1152" d="M480 672v448q0 14 -9 23t-23 9t-23 -9t-9 -23v-448q0 -14 9 -23t23 -9t23 9t9 23zM1152 320q0 -26 -19 -45t-45 -19h-429l-51 -483q-2 -12 -10.5 -20.5t-20.5 -8.5h-1q-27 0 -32 27l-76 485h-404q-26 0 -45 19t-19 45q0 123 78.5 221.5t177.5 98.5v512q-52 0 -90 38 t-38 90t38 90t90 38h640q52 0 90 -38t38 -90t-38 -90t-90 -38v-512q99 0 177.5 -98.5t78.5 -221.5z" />
<glyph unicode="&#xf08e;" horiz-adv-x="1792" d="M1408 608v-320q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v320 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1792 1472v-512q0 -26 -19 -45t-45 -19t-45 19l-176 176l-652 -652q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l652 652l-176 176q-19 19 -19 45t19 45t45 19h512q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf090;" d="M1184 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45zM1536 992v-704q0 -119 -84.5 -203.5t-203.5 -84.5h-320q-13 0 -22.5 9.5t-9.5 22.5 q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q66 0 113 47t47 113v704q0 66 -47 113t-113 47h-288h-11h-13t-11.5 1t-11.5 3t-8 5.5t-7 9t-2 13.5q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf091;" horiz-adv-x="1664" d="M458 653q-74 162 -74 371h-256v-96q0 -78 94.5 -162t235.5 -113zM1536 928v96h-256q0 -209 -74 -371q141 29 235.5 113t94.5 162zM1664 1056v-128q0 -71 -41.5 -143t-112 -130t-173 -97.5t-215.5 -44.5q-42 -54 -95 -95q-38 -34 -52.5 -72.5t-14.5 -89.5q0 -54 30.5 -91 t97.5 -37q75 0 133.5 -45.5t58.5 -114.5v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 69 58.5 114.5t133.5 45.5q67 0 97.5 37t30.5 91q0 51 -14.5 89.5t-52.5 72.5q-53 41 -95 95q-113 5 -215.5 44.5t-173 97.5t-112 130t-41.5 143v128q0 40 28 68t68 28h288v96 q0 66 47 113t113 47h576q66 0 113 -47t47 -113v-96h288q40 0 68 -28t28 -68z" />
<glyph unicode="&#xf092;" d="M394 184q-8 -9 -20 3q-13 11 -4 19q8 9 20 -3q12 -11 4 -19zM352 245q9 -12 0 -19q-8 -6 -17 7t0 18q9 7 17 -6zM291 305q-5 -7 -13 -2q-10 5 -7 12q3 5 13 2q10 -5 7 -12zM322 271q-6 -7 -16 3q-9 11 -2 16q6 6 16 -3q9 -11 2 -16zM451 159q-4 -12 -19 -6q-17 4 -13 15 t19 7q16 -5 13 -16zM514 154q0 -11 -16 -11q-17 -2 -17 11q0 11 16 11q17 2 17 -11zM572 164q2 -10 -14 -14t-18 8t14 15q16 2 18 -9zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-224q-16 0 -24.5 1t-19.5 5t-16 14.5t-5 27.5v239q0 97 -52 142q57 6 102.5 18t94 39 t81 66.5t53 105t20.5 150.5q0 121 -79 206q37 91 -8 204q-28 9 -81 -11t-92 -44l-38 -24q-93 26 -192 26t-192 -26q-16 11 -42.5 27t-83.5 38.5t-86 13.5q-44 -113 -7 -204q-79 -85 -79 -206q0 -85 20.5 -150t52.5 -105t80.5 -67t94 -39t102.5 -18q-40 -36 -49 -103 q-21 -10 -45 -15t-57 -5t-65.5 21.5t-55.5 62.5q-19 32 -48.5 52t-49.5 24l-20 3q-21 0 -29 -4.5t-5 -11.5t9 -14t13 -12l7 -5q22 -10 43.5 -38t31.5 -51l10 -23q13 -38 44 -61.5t67 -30t69.5 -7t55.5 3.5l23 4q0 -38 0.5 -103t0.5 -68q0 -22 -11 -33.5t-22 -13t-33 -1.5 h-224q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf093;" horiz-adv-x="1664" d="M1280 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 288v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h427q21 -56 70.5 -92 t110.5 -36h256q61 0 110.5 36t70.5 92h427q40 0 68 -28t28 -68zM1339 936q-17 -40 -59 -40h-256v-448q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v448h-256q-42 0 -59 40q-17 39 14 69l448 448q18 19 45 19t45 -19l448 -448q31 -30 14 -69z" />
<glyph unicode="&#xf094;" d="M1407 710q0 44 -7 113.5t-18 96.5q-12 30 -17 44t-9 36.5t-4 48.5q0 23 5 68.5t5 67.5q0 37 -10 55q-4 1 -13 1q-19 0 -58 -4.5t-59 -4.5q-60 0 -176 24t-175 24q-43 0 -94.5 -11.5t-85 -23.5t-89.5 -34q-137 -54 -202 -103q-96 -73 -159.5 -189.5t-88 -236t-24.5 -248.5 q0 -40 12.5 -120t12.5 -121q0 -23 -11 -66.5t-11 -65.5t12 -36.5t34 -14.5q24 0 72.5 11t73.5 11q57 0 169.5 -15.5t169.5 -15.5q181 0 284 36q129 45 235.5 152.5t166 245.5t59.5 275zM1535 712q0 -165 -70 -327.5t-196 -288t-281 -180.5q-124 -44 -326 -44 q-57 0 -170 14.5t-169 14.5q-24 0 -72.5 -14.5t-73.5 -14.5q-73 0 -123.5 55.5t-50.5 128.5q0 24 11 68t11 67q0 40 -12.5 120.5t-12.5 121.5q0 111 18 217.5t54.5 209.5t100.5 194t150 156q78 59 232 120q194 78 316 78q60 0 175.5 -24t173.5 -24q19 0 57 5t58 5 q81 0 118 -50.5t37 -134.5q0 -23 -5 -68t-5 -68q0 -10 1 -18.5t3 -17t4 -13.5t6.5 -16t6.5 -17q16 -40 25 -118.5t9 -136.5z" />
<glyph unicode="&#xf095;" horiz-adv-x="1408" d="M1408 296q0 -27 -10 -70.5t-21 -68.5q-21 -50 -122 -106q-94 -51 -186 -51q-27 0 -52.5 3.5t-57.5 12.5t-47.5 14.5t-55.5 20.5t-49 18q-98 35 -175 83q-128 79 -264.5 215.5t-215.5 264.5q-48 77 -83 175q-3 9 -18 49t-20.5 55.5t-14.5 47.5t-12.5 57.5t-3.5 52.5 q0 92 51 186q56 101 106 122q25 11 68.5 21t70.5 10q14 0 21 -3q18 -6 53 -76q11 -19 30 -54t35 -63.5t31 -53.5q3 -4 17.5 -25t21.5 -35.5t7 -28.5q0 -20 -28.5 -50t-62 -55t-62 -53t-28.5 -46q0 -9 5 -22.5t8.5 -20.5t14 -24t11.5 -19q76 -137 174 -235t235 -174 q2 -1 19 -11.5t24 -14t20.5 -8.5t22.5 -5q18 0 46 28.5t53 62t55 62t50 28.5q14 0 28.5 -7t35.5 -21.5t25 -17.5q25 -15 53.5 -31t63.5 -35t54 -30q70 -35 76 -53q3 -7 3 -21z" />
<glyph unicode="&#xf096;" horiz-adv-x="1408" d="M1120 1280h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v832q0 66 -47 113t-113 47zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf097;" horiz-adv-x="1280" d="M1152 1280h-1024v-1242l423 406l89 85l89 -85l423 -406v1242zM1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289 q0 34 19.5 62t52.5 41q21 9 44 9h1048z" />
<glyph unicode="&#xf098;" d="M1280 343q0 11 -2 16q-3 8 -38.5 29.5t-88.5 49.5l-53 29q-5 3 -19 13t-25 15t-21 5q-18 0 -47 -32.5t-57 -65.5t-44 -33q-7 0 -16.5 3.5t-15.5 6.5t-17 9.5t-14 8.5q-99 55 -170.5 126.5t-126.5 170.5q-2 3 -8.5 14t-9.5 17t-6.5 15.5t-3.5 16.5q0 13 20.5 33.5t45 38.5 t45 39.5t20.5 36.5q0 10 -5 21t-15 25t-13 19q-3 6 -15 28.5t-25 45.5t-26.5 47.5t-25 40.5t-16.5 18t-16 2q-48 0 -101 -22q-46 -21 -80 -94.5t-34 -130.5q0 -16 2.5 -34t5 -30.5t9 -33t10 -29.5t12.5 -33t11 -30q60 -164 216.5 -320.5t320.5 -216.5q6 -2 30 -11t33 -12.5 t29.5 -10t33 -9t30.5 -5t34 -2.5q57 0 130.5 34t94.5 80q22 53 22 101zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf099;" horiz-adv-x="1664" d="M1620 1128q-67 -98 -162 -167q1 -14 1 -42q0 -130 -38 -259.5t-115.5 -248.5t-184.5 -210.5t-258 -146t-323 -54.5q-271 0 -496 145q35 -4 78 -4q225 0 401 138q-105 2 -188 64.5t-114 159.5q33 -5 61 -5q43 0 85 11q-112 23 -185.5 111.5t-73.5 205.5v4q68 -38 146 -41 q-66 44 -105 115t-39 154q0 88 44 163q121 -149 294.5 -238.5t371.5 -99.5q-8 38 -8 74q0 134 94.5 228.5t228.5 94.5q140 0 236 -102q109 21 205 78q-37 -115 -142 -178q93 10 186 50z" />
<glyph unicode="&#xf09a;" horiz-adv-x="768" d="M511 980h257l-30 -284h-227v-824h-341v824h-170v284h170v171q0 182 86 275.5t283 93.5h227v-284h-142q-39 0 -62.5 -6.5t-34 -23.5t-13.5 -34.5t-3 -49.5v-142z" />
<glyph unicode="&#xf09b;" d="M1536 640q0 -251 -146.5 -451.5t-378.5 -277.5q-27 -5 -39.5 7t-12.5 30v211q0 97 -52 142q57 6 102.5 18t94 39t81 66.5t53 105t20.5 150.5q0 121 -79 206q37 91 -8 204q-28 9 -81 -11t-92 -44l-38 -24q-93 26 -192 26t-192 -26q-16 11 -42.5 27t-83.5 38.5t-86 13.5 q-44 -113 -7 -204q-79 -85 -79 -206q0 -85 20.5 -150t52.5 -105t80.5 -67t94 -39t102.5 -18q-40 -36 -49 -103q-21 -10 -45 -15t-57 -5t-65.5 21.5t-55.5 62.5q-19 32 -48.5 52t-49.5 24l-20 3q-21 0 -29 -4.5t-5 -11.5t9 -14t13 -12l7 -5q22 -10 43.5 -38t31.5 -51l10 -23 q13 -38 44 -61.5t67 -30t69.5 -7t55.5 3.5l23 4q0 -38 0.5 -89t0.5 -54q0 -18 -13 -30t-40 -7q-232 77 -378.5 277.5t-146.5 451.5q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf09c;" horiz-adv-x="1664" d="M1664 960v-256q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-192h96q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h672v192q0 185 131.5 316.5t316.5 131.5 t316.5 -131.5t131.5 -316.5z" />
<glyph unicode="&#xf09d;" horiz-adv-x="1920" d="M1760 1408q66 0 113 -47t47 -113v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600zM160 1280q-13 0 -22.5 -9.5t-9.5 -22.5v-224h1664v224q0 13 -9.5 22.5t-22.5 9.5h-1600zM1760 0q13 0 22.5 9.5t9.5 22.5v608h-1664v-608 q0 -13 9.5 -22.5t22.5 -9.5h1600zM256 128v128h256v-128h-256zM640 128v128h384v-128h-384z" />
<glyph unicode="&#xf09e;" horiz-adv-x="1408" d="M384 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 69q2 -28 -17 -48q-18 -21 -47 -21h-135q-25 0 -43 16.5t-20 41.5q-22 229 -184.5 391.5t-391.5 184.5q-25 2 -41.5 20t-16.5 43v135q0 29 21 47q17 17 43 17h5q160 -13 306 -80.5 t259 -181.5q114 -113 181.5 -259t80.5 -306zM1408 67q2 -27 -18 -47q-18 -20 -46 -20h-143q-26 0 -44.5 17.5t-19.5 42.5q-12 215 -101 408.5t-231.5 336t-336 231.5t-408.5 102q-25 1 -42.5 19.5t-17.5 43.5v143q0 28 20 46q18 18 44 18h3q262 -13 501.5 -120t425.5 -294 q187 -186 294 -425.5t120 -501.5z" />
<glyph unicode="&#xf0a0;" d="M1040 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1296 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1408 160v320q0 13 -9.5 22.5t-22.5 9.5 h-1216q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h1216q13 0 22.5 9.5t9.5 22.5zM178 640h1180l-157 482q-4 13 -16 21.5t-26 8.5h-782q-14 0 -26 -8.5t-16 -21.5zM1536 480v-320q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113v320q0 25 16 75 l197 606q17 53 63 86t101 33h782q55 0 101 -33t63 -86l197 -606q16 -50 16 -75z" />
<glyph unicode="&#xf0a1;" horiz-adv-x="1792" d="M1664 896q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5v-384q0 -52 -38 -90t-90 -38q-417 347 -812 380q-58 -19 -91 -66t-31 -100.5t40 -92.5q-20 -33 -23 -65.5t6 -58t33.5 -55t48 -50t61.5 -50.5q-29 -58 -111.5 -83t-168.5 -11.5t-132 55.5q-7 23 -29.5 87.5 t-32 94.5t-23 89t-15 101t3.5 98.5t22 110.5h-122q-66 0 -113 47t-47 113v192q0 66 47 113t113 47h480q435 0 896 384q52 0 90 -38t38 -90v-384zM1536 292v954q-394 -302 -768 -343v-270q377 -42 768 -341z" />
<glyph unicode="&#xf0a2;" horiz-adv-x="1664" d="M848 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM183 128h1298q-164 181 -246.5 411.5t-82.5 484.5q0 256 -320 256t-320 -256q0 -254 -82.5 -484.5t-246.5 -411.5zM1664 128q0 -52 -38 -90t-90 -38 h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q190 161 287 397.5t97 498.5q0 165 96 262t264 117q-8 18 -8 37q0 40 28 68t68 28t68 -28t28 -68q0 -19 -8 -37q168 -20 264 -117t96 -262q0 -262 97 -498.5t287 -397.5z" />
<glyph unicode="&#xf0a3;" d="M1376 640l138 -135q30 -28 20 -70q-12 -41 -52 -51l-188 -48l53 -186q12 -41 -19 -70q-29 -31 -70 -19l-186 53l-48 -188q-10 -40 -51 -52q-12 -2 -19 -2q-31 0 -51 22l-135 138l-135 -138q-28 -30 -70 -20q-41 11 -51 52l-48 188l-186 -53q-41 -12 -70 19q-31 29 -19 70 l53 186l-188 48q-40 10 -52 51q-10 42 20 70l138 135l-138 135q-30 28 -20 70q12 41 52 51l188 48l-53 186q-12 41 19 70q29 31 70 19l186 -53l48 188q10 41 51 51q41 12 70 -19l135 -139l135 139q29 30 70 19q41 -10 51 -51l48 -188l186 53q41 12 70 -19q31 -29 19 -70 l-53 -186l188 -48q40 -10 52 -51q10 -42 -20 -70z" />
<glyph unicode="&#xf0a4;" horiz-adv-x="1792" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 768q0 51 -39 89.5t-89 38.5h-576q0 20 15 48.5t33 55t33 68t15 84.5q0 67 -44.5 97.5t-115.5 30.5q-24 0 -90 -139q-24 -44 -37 -65q-40 -64 -112 -145q-71 -81 -101 -106 q-69 -57 -140 -57h-32v-640h32q72 0 167 -32t193.5 -64t179.5 -32q189 0 189 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5h331q52 0 90 38t38 90zM1792 769q0 -105 -75.5 -181t-180.5 -76h-169q-4 -62 -37 -119q3 -21 3 -43 q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5q-133 0 -322 69q-164 59 -223 59h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h288q10 0 21.5 4.5t23.5 14t22.5 18t24 22.5t20.5 21.5t19 21.5t14 17q65 74 100 129q13 21 33 62t37 72t40.5 63t55 49.5 t69.5 17.5q125 0 206.5 -67t81.5 -189q0 -68 -22 -128h374q104 0 180 -76t76 -179z" />
<glyph unicode="&#xf0a5;" horiz-adv-x="1792" d="M1376 128h32v640h-32q-35 0 -67.5 12t-62.5 37t-50 46t-49 54q-2 3 -3.5 4.5t-4 4.5t-4.5 5q-72 81 -112 145q-14 22 -38 68q-1 3 -10.5 22.5t-18.5 36t-20 35.5t-21.5 30.5t-18.5 11.5q-71 0 -115.5 -30.5t-44.5 -97.5q0 -43 15 -84.5t33 -68t33 -55t15 -48.5h-576 q-50 0 -89 -38.5t-39 -89.5q0 -52 38 -90t90 -38h331q-15 -17 -25 -47.5t-10 -55.5q0 -69 53 -119q-18 -32 -18 -69t17.5 -73.5t47.5 -52.5q-4 -24 -4 -56q0 -85 48.5 -126t135.5 -41q84 0 183 32t194 64t167 32zM1664 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45 t45 -19t45 19t19 45zM1792 768v-640q0 -53 -37.5 -90.5t-90.5 -37.5h-288q-59 0 -223 -59q-190 -69 -317 -69q-142 0 -230 77.5t-87 217.5l1 5q-61 76 -61 178q0 22 3 43q-33 57 -37 119h-169q-105 0 -180.5 76t-75.5 181q0 103 76 179t180 76h374q-22 60 -22 128 q0 122 81.5 189t206.5 67q38 0 69.5 -17.5t55 -49.5t40.5 -63t37 -72t33 -62q35 -55 100 -129q2 -3 14 -17t19 -21.5t20.5 -21.5t24 -22.5t22.5 -18t23.5 -14t21.5 -4.5h288q53 0 90.5 -37.5t37.5 -90.5z" />
<glyph unicode="&#xf0a6;" d="M1280 -64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 700q0 189 -167 189q-26 0 -56 -5q-16 30 -52.5 47.5t-73.5 17.5t-69 -18q-50 53 -119 53q-25 0 -55.5 -10t-47.5 -25v331q0 52 -38 90t-90 38q-51 0 -89.5 -39t-38.5 -89v-576 q-20 0 -48.5 15t-55 33t-68 33t-84.5 15q-67 0 -97.5 -44.5t-30.5 -115.5q0 -24 139 -90q44 -24 65 -37q64 -40 145 -112q81 -71 106 -101q57 -69 57 -140v-32h640v32q0 72 32 167t64 193.5t32 179.5zM1536 705q0 -133 -69 -322q-59 -164 -59 -223v-288q0 -53 -37.5 -90.5 t-90.5 -37.5h-640q-53 0 -90.5 37.5t-37.5 90.5v288q0 10 -4.5 21.5t-14 23.5t-18 22.5t-22.5 24t-21.5 20.5t-21.5 19t-17 14q-74 65 -129 100q-21 13 -62 33t-72 37t-63 40.5t-49.5 55t-17.5 69.5q0 125 67 206.5t189 81.5q68 0 128 -22v374q0 104 76 180t179 76 q105 0 181 -75.5t76 -180.5v-169q62 -4 119 -37q21 3 43 3q101 0 178 -60q139 1 219.5 -85t80.5 -227z" />
<glyph unicode="&#xf0a7;" d="M1408 576q0 84 -32 183t-64 194t-32 167v32h-640v-32q0 -35 -12 -67.5t-37 -62.5t-46 -50t-54 -49q-9 -8 -14 -12q-81 -72 -145 -112q-22 -14 -68 -38q-3 -1 -22.5 -10.5t-36 -18.5t-35.5 -20t-30.5 -21.5t-11.5 -18.5q0 -71 30.5 -115.5t97.5 -44.5q43 0 84.5 15t68 33 t55 33t48.5 15v-576q0 -50 38.5 -89t89.5 -39q52 0 90 38t38 90v331q46 -35 103 -35q69 0 119 53q32 -18 69 -18t73.5 17.5t52.5 47.5q24 -4 56 -4q85 0 126 48.5t41 135.5zM1280 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 580 q0 -142 -77.5 -230t-217.5 -87l-5 1q-76 -61 -178 -61q-22 0 -43 3q-54 -30 -119 -37v-169q0 -105 -76 -180.5t-181 -75.5q-103 0 -179 76t-76 180v374q-54 -22 -128 -22q-121 0 -188.5 81.5t-67.5 206.5q0 38 17.5 69.5t49.5 55t63 40.5t72 37t62 33q55 35 129 100 q3 2 17 14t21.5 19t21.5 20.5t22.5 24t18 22.5t14 23.5t4.5 21.5v288q0 53 37.5 90.5t90.5 37.5h640q53 0 90.5 -37.5t37.5 -90.5v-288q0 -59 59 -223q69 -190 69 -317z" />
<glyph unicode="&#xf0a8;" d="M1280 576v128q0 26 -19 45t-45 19h-502l189 189q19 19 19 45t-19 45l-91 91q-18 18 -45 18t-45 -18l-362 -362l-91 -91q-18 -18 -18 -45t18 -45l91 -91l362 -362q18 -18 45 -18t45 18l91 91q18 18 18 45t-18 45l-189 189h502q26 0 45 19t19 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf0a9;" d="M1285 640q0 27 -18 45l-91 91l-362 362q-18 18 -45 18t-45 -18l-91 -91q-18 -18 -18 -45t18 -45l189 -189h-502q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h502l-189 -189q-19 -19 -19 -45t19 -45l91 -91q18 -18 45 -18t45 18l362 362l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf0aa;" d="M1284 641q0 27 -18 45l-362 362l-91 91q-18 18 -45 18t-45 -18l-91 -91l-362 -362q-18 -18 -18 -45t18 -45l91 -91q18 -18 45 -18t45 18l189 189v-502q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v502l189 -189q19 -19 45 -19t45 19l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf0ab;" d="M1284 639q0 27 -18 45l-91 91q-18 18 -45 18t-45 -18l-189 -189v502q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-502l-189 189q-19 19 -45 19t-45 -19l-91 -91q-18 -18 -18 -45t18 -45l362 -362l91 -91q18 -18 45 -18t45 18l91 91l362 362q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf0ac;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1042 887q-2 -1 -9.5 -9.5t-13.5 -9.5q2 0 4.5 5t5 11t3.5 7q6 7 22 15q14 6 52 12q34 8 51 -11 q-2 2 9.5 13t14.5 12q3 2 15 4.5t15 7.5l2 22q-12 -1 -17.5 7t-6.5 21q0 -2 -6 -8q0 7 -4.5 8t-11.5 -1t-9 -1q-10 3 -15 7.5t-8 16.5t-4 15q-2 5 -9.5 10.5t-9.5 10.5q-1 2 -2.5 5.5t-3 6.5t-4 5.5t-5.5 2.5t-7 -5t-7.5 -10t-4.5 -5q-3 2 -6 1.5t-4.5 -1t-4.5 -3t-5 -3.5 q-3 -2 -8.5 -3t-8.5 -2q15 5 -1 11q-10 4 -16 3q9 4 7.5 12t-8.5 14h5q-1 4 -8.5 8.5t-17.5 8.5t-13 6q-8 5 -34 9.5t-33 0.5q-5 -6 -4.5 -10.5t4 -14t3.5 -12.5q1 -6 -5.5 -13t-6.5 -12q0 -7 14 -15.5t10 -21.5q-3 -8 -16 -16t-16 -12q-5 -8 -1.5 -18.5t10.5 -16.5 q2 -2 1.5 -4t-3.5 -4.5t-5.5 -4t-6.5 -3.5l-3 -2q-11 -5 -20.5 6t-13.5 26q-7 25 -16 30q-23 8 -29 -1q-5 13 -41 26q-25 9 -58 4q6 1 0 15q-7 15 -19 12q3 6 4 17.5t1 13.5q3 13 12 23q1 1 7 8.5t9.5 13.5t0.5 6q35 -4 50 11q5 5 11.5 17t10.5 17q9 6 14 5.5t14.5 -5.5 t14.5 -5q14 -1 15.5 11t-7.5 20q12 -1 3 17q-5 7 -8 9q-12 4 -27 -5q-8 -4 2 -8q-1 1 -9.5 -10.5t-16.5 -17.5t-16 5q-1 1 -5.5 13.5t-9.5 13.5q-8 0 -16 -15q3 8 -11 15t-24 8q19 12 -8 27q-7 4 -20.5 5t-19.5 -4q-5 -7 -5.5 -11.5t5 -8t10.5 -5.5t11.5 -4t8.5 -3 q14 -10 8 -14q-2 -1 -8.5 -3.5t-11.5 -4.5t-6 -4q-3 -4 0 -14t-2 -14q-5 5 -9 17.5t-7 16.5q7 -9 -25 -6l-10 1q-4 0 -16 -2t-20.5 -1t-13.5 8q-4 8 0 20q1 4 4 2q-4 3 -11 9.5t-10 8.5q-46 -15 -94 -41q6 -1 12 1q5 2 13 6.5t10 5.5q34 14 42 7l5 5q14 -16 20 -25 q-7 4 -30 1q-20 -6 -22 -12q7 -12 5 -18q-4 3 -11.5 10t-14.5 11t-15 5q-16 0 -22 -1q-146 -80 -235 -222q7 -7 12 -8q4 -1 5 -9t2.5 -11t11.5 3q9 -8 3 -19q1 1 44 -27q19 -17 21 -21q3 -11 -10 -18q-1 2 -9 9t-9 4q-3 -5 0.5 -18.5t10.5 -12.5q-7 0 -9.5 -16t-2.5 -35.5 t-1 -23.5l2 -1q-3 -12 5.5 -34.5t21.5 -19.5q-13 -3 20 -43q6 -8 8 -9q3 -2 12 -7.5t15 -10t10 -10.5q4 -5 10 -22.5t14 -23.5q-2 -6 9.5 -20t10.5 -23q-1 0 -2.5 -1t-2.5 -1q3 -7 15.5 -14t15.5 -13q1 -3 2 -10t3 -11t8 -2q2 20 -24 62q-15 25 -17 29q-3 5 -5.5 15.5 t-4.5 14.5q2 0 6 -1.5t8.5 -3.5t7.5 -4t2 -3q-3 -7 2 -17.5t12 -18.5t17 -19t12 -13q6 -6 14 -19.5t0 -13.5q9 0 20 -10t17 -20q5 -8 8 -26t5 -24q2 -7 8.5 -13.5t12.5 -9.5l16 -8t13 -7q5 -2 18.5 -10.5t21.5 -11.5q10 -4 16 -4t14.5 2.5t13.5 3.5q15 2 29 -15t21 -21 q36 -19 55 -11q-2 -1 0.5 -7.5t8 -15.5t9 -14.5t5.5 -8.5q5 -6 18 -15t18 -15q6 4 7 9q-3 -8 7 -20t18 -10q14 3 14 32q-31 -15 -49 18q0 1 -2.5 5.5t-4 8.5t-2.5 8.5t0 7.5t5 3q9 0 10 3.5t-2 12.5t-4 13q-1 8 -11 20t-12 15q-5 -9 -16 -8t-16 9q0 -1 -1.5 -5.5t-1.5 -6.5 q-13 0 -15 1q1 3 2.5 17.5t3.5 22.5q1 4 5.5 12t7.5 14.5t4 12.5t-4.5 9.5t-17.5 2.5q-19 -1 -26 -20q-1 -3 -3 -10.5t-5 -11.5t-9 -7q-7 -3 -24 -2t-24 5q-13 8 -22.5 29t-9.5 37q0 10 2.5 26.5t3 25t-5.5 24.5q3 2 9 9.5t10 10.5q2 1 4.5 1.5t4.5 0t4 1.5t3 6q-1 1 -4 3 q-3 3 -4 3q7 -3 28.5 1.5t27.5 -1.5q15 -11 22 2q0 1 -2.5 9.5t-0.5 13.5q5 -27 29 -9q3 -3 15.5 -5t17.5 -5q3 -2 7 -5.5t5.5 -4.5t5 0.5t8.5 6.5q10 -14 12 -24q11 -40 19 -44q7 -3 11 -2t4.5 9.5t0 14t-1.5 12.5l-1 8v18l-1 8q-15 3 -18.5 12t1.5 18.5t15 18.5q1 1 8 3.5 t15.5 6.5t12.5 8q21 19 15 35q7 0 11 9q-1 0 -5 3t-7.5 5t-4.5 2q9 5 2 16q5 3 7.5 11t7.5 10q9 -12 21 -2q7 8 1 16q5 7 20.5 10.5t18.5 9.5q7 -2 8 2t1 12t3 12q4 5 15 9t13 5l17 11q3 4 0 4q18 -2 31 11q10 11 -6 20q3 6 -3 9.5t-15 5.5q3 1 11.5 0.5t10.5 1.5 q15 10 -7 16q-17 5 -43 -12zM879 10q206 36 351 189q-3 3 -12.5 4.5t-12.5 3.5q-18 7 -24 8q1 7 -2.5 13t-8 9t-12.5 8t-11 7q-2 2 -7 6t-7 5.5t-7.5 4.5t-8.5 2t-10 -1l-3 -1q-3 -1 -5.5 -2.5t-5.5 -3t-4 -3t0 -2.5q-21 17 -36 22q-5 1 -11 5.5t-10.5 7t-10 1.5t-11.5 -7 q-5 -5 -6 -15t-2 -13q-7 5 0 17.5t2 18.5q-3 6 -10.5 4.5t-12 -4.5t-11.5 -8.5t-9 -6.5t-8.5 -5.5t-8.5 -7.5q-3 -4 -6 -12t-5 -11q-2 4 -11.5 6.5t-9.5 5.5q2 -10 4 -35t5 -38q7 -31 -12 -48q-27 -25 -29 -40q-4 -22 12 -26q0 -7 -8 -20.5t-7 -21.5q0 -6 2 -16z" />
<glyph unicode="&#xf0ad;" horiz-adv-x="1664" d="M384 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1028 484l-682 -682q-37 -37 -90 -37q-52 0 -91 37l-106 108q-38 36 -38 90q0 53 38 91l681 681q39 -98 114.5 -173.5t173.5 -114.5zM1662 919q0 -39 -23 -106q-47 -134 -164.5 -217.5 t-258.5 -83.5q-185 0 -316.5 131.5t-131.5 316.5t131.5 316.5t316.5 131.5q58 0 121.5 -16.5t107.5 -46.5q16 -11 16 -28t-16 -28l-293 -169v-224l193 -107q5 3 79 48.5t135.5 81t70.5 35.5q15 0 23.5 -10t8.5 -25z" />
<glyph unicode="&#xf0ae;" horiz-adv-x="1792" d="M1024 128h640v128h-640v-128zM640 640h1024v128h-1024v-128zM1280 1152h384v128h-384v-128zM1792 320v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 832v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19 t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf0b0;" horiz-adv-x="1408" d="M1403 1241q17 -41 -14 -70l-493 -493v-742q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-256 256q-19 19 -19 45v486l-493 493q-31 29 -14 70q17 39 59 39h1280q42 0 59 -39z" />
<glyph unicode="&#xf0b1;" horiz-adv-x="1792" d="M640 1280h512v128h-512v-128zM1792 640v-480q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v480h672v-160q0 -26 19 -45t45 -19h320q26 0 45 19t19 45v160h672zM1024 640v-128h-256v128h256zM1792 1120v-384h-1792v384q0 66 47 113t113 47h352v160q0 40 28 68 t68 28h576q40 0 68 -28t28 -68v-160h352q66 0 113 -47t47 -113z" />
<glyph unicode="&#xf0b2;" d="M1283 995l-355 -355l355 -355l144 144q29 31 70 14q39 -17 39 -59v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l144 144l-355 355l-355 -355l144 -144q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l144 -144 l355 355l-355 355l-144 -144q-19 -19 -45 -19q-12 0 -24 5q-40 17 -40 59v448q0 26 19 45t45 19h448q42 0 59 -40q17 -39 -14 -69l-144 -144l355 -355l355 355l-144 144q-31 30 -14 69q17 40 59 40h448q26 0 45 -19t19 -45v-448q0 -42 -39 -59q-13 -5 -25 -5q-26 0 -45 19z " />
<glyph unicode="&#xf0c0;" horiz-adv-x="1920" d="M593 640q-162 -5 -265 -128h-134q-82 0 -138 40.5t-56 118.5q0 353 124 353q6 0 43.5 -21t97.5 -42.5t119 -21.5q67 0 133 23q-5 -37 -5 -66q0 -139 81 -256zM1664 3q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5 t43 97.5t62 81t85.5 53.5t111.5 20q10 0 43 -21.5t73 -48t107 -48t135 -21.5t135 21.5t107 48t73 48t43 21.5q61 0 111.5 -20t85.5 -53.5t62 -81t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM640 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75 t75 -181zM1344 896q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5zM1920 671q0 -78 -56 -118.5t-138 -40.5h-134q-103 123 -265 128q81 117 81 256q0 29 -5 66q66 -23 133 -23q59 0 119 21.5t97.5 42.5 t43.5 21q124 0 124 -353zM1792 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181z" />
<glyph unicode="&#xf0c1;" horiz-adv-x="1664" d="M1456 320q0 40 -28 68l-208 208q-28 28 -68 28q-42 0 -72 -32q3 -3 19 -18.5t21.5 -21.5t15 -19t13 -25.5t3.5 -27.5q0 -40 -28 -68t-68 -28q-15 0 -27.5 3.5t-25.5 13t-19 15t-21.5 21.5t-18.5 19q-33 -31 -33 -73q0 -40 28 -68l206 -207q27 -27 68 -27q40 0 68 26 l147 146q28 28 28 67zM753 1025q0 40 -28 68l-206 207q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l208 -208q27 -27 68 -27q42 0 72 31q-3 3 -19 18.5t-21.5 21.5t-15 19t-13 25.5t-3.5 27.5q0 40 28 68t68 28q15 0 27.5 -3.5t25.5 -13t19 -15 t21.5 -21.5t18.5 -19q33 31 33 73zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-206 207q-83 83 -83 203q0 123 88 209l-88 88q-86 -88 -208 -88q-120 0 -204 84l-208 208q-84 84 -84 204t85 203l147 146q83 83 203 83q121 0 204 -85l206 -207 q83 -83 83 -203q0 -123 -88 -209l88 -88q86 88 208 88q120 0 204 -84l208 -208q84 -84 84 -204z" />
<glyph unicode="&#xf0c2;" horiz-adv-x="1920" d="M1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088q-185 0 -316.5 131.5t-131.5 316.5q0 132 71 241.5t187 163.5q-2 28 -2 43q0 212 150 362t362 150q158 0 286.5 -88t187.5 -230q70 62 166 62q106 0 181 -75t75 -181q0 -75 -41 -138q129 -30 213 -134.5t84 -239.5z " />
<glyph unicode="&#xf0c3;" horiz-adv-x="1664" d="M1527 88q56 -89 21.5 -152.5t-140.5 -63.5h-1152q-106 0 -140.5 63.5t21.5 152.5l503 793v399h-64q-26 0 -45 19t-19 45t19 45t45 19h512q26 0 45 -19t19 -45t-19 -45t-45 -19h-64v-399zM748 813l-272 -429h712l-272 429l-20 31v37v399h-128v-399v-37z" />
<glyph unicode="&#xf0c4;" horiz-adv-x="1792" d="M960 640q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1260 576l507 -398q28 -20 25 -56q-5 -35 -35 -51l-128 -64q-13 -7 -29 -7q-17 0 -31 8l-690 387l-110 -66q-8 -4 -12 -5q14 -49 10 -97q-7 -77 -56 -147.5t-132 -123.5q-132 -84 -277 -84 q-136 0 -222 78q-90 84 -79 207q7 76 56 147t131 124q132 84 278 84q83 0 151 -31q9 13 22 22l122 73l-122 73q-13 9 -22 22q-68 -31 -151 -31q-146 0 -278 84q-82 53 -131 124t-56 147q-5 59 15.5 113t63.5 93q85 79 222 79q145 0 277 -84q83 -52 132 -123t56 -148 q4 -48 -10 -97q4 -1 12 -5l110 -66l690 387q14 8 31 8q16 0 29 -7l128 -64q30 -16 35 -51q3 -36 -25 -56zM579 836q46 42 21 108t-106 117q-92 59 -192 59q-74 0 -113 -36q-46 -42 -21 -108t106 -117q92 -59 192 -59q74 0 113 36zM494 91q81 51 106 117t-21 108 q-39 36 -113 36q-100 0 -192 -59q-81 -51 -106 -117t21 -108q39 -36 113 -36q100 0 192 59zM672 704l96 -58v11q0 36 33 56l14 8l-79 47l-26 -26q-3 -3 -10 -11t-12 -12q-2 -2 -4 -3.5t-3 -2.5zM896 480l96 -32l736 576l-128 64l-768 -431v-113l-160 -96l9 -8q2 -2 7 -6 q4 -4 11 -12t11 -12l26 -26zM1600 64l128 64l-520 408l-177 -138q-2 -3 -13 -7z" />
<glyph unicode="&#xf0c5;" horiz-adv-x="1792" d="M1696 1152q40 0 68 -28t28 -68v-1216q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v288h-544q-40 0 -68 28t-28 68v672q0 40 20 88t48 76l408 408q28 28 76 48t88 20h416q40 0 68 -28t28 -68v-328q68 40 128 40h416zM1152 939l-299 -299h299v299zM512 1323l-299 -299 h299v299zM708 676l316 316v416h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h512v256q0 40 20 88t48 76zM1664 -128v1152h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h896z" />
<glyph unicode="&#xf0c6;" horiz-adv-x="1408" d="M1404 151q0 -117 -79 -196t-196 -79q-135 0 -235 100l-777 776q-113 115 -113 271q0 159 110 270t269 111q158 0 273 -113l605 -606q10 -10 10 -22q0 -16 -30.5 -46.5t-46.5 -30.5q-13 0 -23 10l-606 607q-79 77 -181 77q-106 0 -179 -75t-73 -181q0 -105 76 -181 l776 -777q63 -63 145 -63q64 0 106 42t42 106q0 82 -63 145l-581 581q-26 24 -60 24q-29 0 -48 -19t-19 -48q0 -32 25 -59l410 -410q10 -10 10 -22q0 -16 -31 -47t-47 -31q-12 0 -22 10l-410 410q-63 61 -63 149q0 82 57 139t139 57q88 0 149 -63l581 -581q100 -98 100 -235 z" />
<glyph unicode="&#xf0c7;" d="M384 0h768v384h-768v-384zM1280 0h128v896q0 14 -10 38.5t-20 34.5l-281 281q-10 10 -34 20t-39 10v-416q0 -40 -28 -68t-68 -28h-576q-40 0 -68 28t-28 68v416h-128v-1280h128v416q0 40 28 68t68 28h832q40 0 68 -28t28 -68v-416zM896 928v320q0 13 -9.5 22.5t-22.5 9.5 h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM1536 896v-928q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h928q40 0 88 -20t76 -48l280 -280q28 -28 48 -76t20 -88z" />
<glyph unicode="&#xf0c8;" d="M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf0c9;" d="M1536 192v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 704v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 1216v-128q0 -26 -19 -45 t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf0ca;" horiz-adv-x="1792" d="M384 128q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM384 640q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5 t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1152q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z M1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" />
<glyph unicode="&#xf0cb;" horiz-adv-x="1792" d="M381 -84q0 -80 -54.5 -126t-135.5 -46q-106 0 -172 66l57 88q49 -45 106 -45q29 0 50.5 14.5t21.5 42.5q0 64 -105 56l-26 56q8 10 32.5 43.5t42.5 54t37 38.5v1q-16 0 -48.5 -1t-48.5 -1v-53h-106v152h333v-88l-95 -115q51 -12 81 -49t30 -88zM383 543v-159h-362 q-6 36 -6 54q0 51 23.5 93t56.5 68t66 47.5t56.5 43.5t23.5 45q0 25 -14.5 38.5t-39.5 13.5q-46 0 -81 -58l-85 59q24 51 71.5 79.5t105.5 28.5q73 0 123 -41.5t50 -112.5q0 -50 -34 -91.5t-75 -64.5t-75.5 -50.5t-35.5 -52.5h127v60h105zM1792 224v-192q0 -13 -9.5 -22.5 t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1123v-99h-335v99h107q0 41 0.5 122t0.5 121v12h-2q-8 -17 -50 -54l-71 76l136 127h106v-404h108zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5 t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" />
<glyph unicode="&#xf0cc;" horiz-adv-x="1792" d="M1760 640q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1728q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h1728zM483 704q-28 35 -51 80q-48 97 -48 188q0 181 134 309q133 127 393 127q50 0 167 -19q66 -12 177 -48q10 -38 21 -118q14 -123 14 -183q0 -18 -5 -45l-12 -3l-84 6 l-14 2q-50 149 -103 205q-88 91 -210 91q-114 0 -182 -59q-67 -58 -67 -146q0 -73 66 -140t279 -129q69 -20 173 -66q58 -28 95 -52h-743zM990 448h411q7 -39 7 -92q0 -111 -41 -212q-23 -55 -71 -104q-37 -35 -109 -81q-80 -48 -153 -66q-80 -21 -203 -21q-114 0 -195 23 l-140 40q-57 16 -72 28q-8 8 -8 22v13q0 108 -2 156q-1 30 0 68l2 37v44l102 2q15 -34 30 -71t22.5 -56t12.5 -27q35 -57 80 -94q43 -36 105 -57q59 -22 132 -22q64 0 139 27q77 26 122 86q47 61 47 129q0 84 -81 157q-34 29 -137 71z" />
<glyph unicode="&#xf0cd;" d="M48 1313q-37 2 -45 4l-3 88q13 1 40 1q60 0 112 -4q132 -7 166 -7q86 0 168 3q116 4 146 5q56 0 86 2l-1 -14l2 -64v-9q-60 -9 -124 -9q-60 0 -79 -25q-13 -14 -13 -132q0 -13 0.5 -32.5t0.5 -25.5l1 -229l14 -280q6 -124 51 -202q35 -59 96 -92q88 -47 177 -47 q104 0 191 28q56 18 99 51q48 36 65 64q36 56 53 114q21 73 21 229q0 79 -3.5 128t-11 122.5t-13.5 159.5l-4 59q-5 67 -24 88q-34 35 -77 34l-100 -2l-14 3l2 86h84l205 -10q76 -3 196 10l18 -2q6 -38 6 -51q0 -7 -4 -31q-45 -12 -84 -13q-73 -11 -79 -17q-15 -15 -15 -41 q0 -7 1.5 -27t1.5 -31q8 -19 22 -396q6 -195 -15 -304q-15 -76 -41 -122q-38 -65 -112 -123q-75 -57 -182 -89q-109 -33 -255 -33q-167 0 -284 46q-119 47 -179 122q-61 76 -83 195q-16 80 -16 237v333q0 188 -17 213q-25 36 -147 39zM1536 -96v64q0 14 -9 23t-23 9h-1472 q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h1472q14 0 23 9t9 23z" />
<glyph unicode="&#xf0ce;" horiz-adv-x="1664" d="M512 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23 v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 160v192 q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192 q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1664 1248v-1088q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1344q66 0 113 -47t47 -113 z" />
<glyph unicode="&#xf0d0;" horiz-adv-x="1664" d="M1190 955l293 293l-107 107l-293 -293zM1637 1248q0 -27 -18 -45l-1286 -1286q-18 -18 -45 -18t-45 18l-198 198q-18 18 -18 45t18 45l1286 1286q18 18 45 18t45 -18l198 -198q18 -18 18 -45zM286 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM636 1276 l196 -60l-196 -60l-60 -196l-60 196l-196 60l196 60l60 196zM1566 798l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM926 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98z" />
<glyph unicode="&#xf0d1;" horiz-adv-x="1792" d="M640 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM256 640h384v256h-158q-13 0 -22 -9l-195 -195q-9 -9 -9 -22v-30zM1536 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1792 1216v-1024q0 -15 -4 -26.5t-13.5 -18.5 t-16.5 -11.5t-23.5 -6t-22.5 -2t-25.5 0t-22.5 0.5q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-64q-3 0 -22.5 -0.5t-25.5 0t-22.5 2t-23.5 6t-16.5 11.5t-13.5 18.5t-4 26.5q0 26 19 45t45 19v320q0 8 -0.5 35t0 38 t2.5 34.5t6.5 37t14 30.5t22.5 30l198 198q19 19 50.5 32t58.5 13h160v192q0 26 19 45t45 19h1024q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf0d2;" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103q-111 0 -218 32q59 93 78 164q9 34 54 211q20 -39 73 -67.5t114 -28.5q121 0 216 68.5t147 188.5t52 270q0 114 -59.5 214t-172.5 163t-255 63q-105 0 -196 -29t-154.5 -77t-109 -110.5t-67 -129.5t-21.5 -134 q0 -104 40 -183t117 -111q30 -12 38 20q2 7 8 31t8 30q6 23 -11 43q-51 61 -51 151q0 151 104.5 259.5t273.5 108.5q151 0 235.5 -82t84.5 -213q0 -170 -68.5 -289t-175.5 -119q-61 0 -98 43.5t-23 104.5q8 35 26.5 93.5t30 103t11.5 75.5q0 50 -27 83t-77 33 q-62 0 -105 -57t-43 -142q0 -73 25 -122l-99 -418q-17 -70 -13 -177q-206 91 -333 281t-127 423q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf0d3;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-725q85 122 108 210q9 34 53 209q21 -39 73.5 -67t112.5 -28q181 0 295.5 147.5t114.5 373.5q0 84 -35 162.5t-96.5 139t-152.5 97t-197 36.5q-104 0 -194.5 -28.5t-153 -76.5 t-107.5 -109.5t-66.5 -128t-21.5 -132.5q0 -102 39.5 -180t116.5 -110q13 -5 23.5 0t14.5 19q10 44 15 61q6 23 -11 42q-50 62 -50 150q0 150 103.5 256.5t270.5 106.5q149 0 232.5 -81t83.5 -210q0 -168 -67.5 -286t-173.5 -118q-60 0 -97 43.5t-23 103.5q8 34 26.5 92.5 t29.5 102t11 74.5q0 49 -26.5 81.5t-75.5 32.5q-61 0 -103.5 -56.5t-42.5 -139.5q0 -72 24 -121l-98 -414q-24 -100 -7 -254h-183q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960z" />
<glyph unicode="&#xf0d4;" d="M678 -57q0 -38 -10 -71h-380q-95 0 -171.5 56.5t-103.5 147.5q24 45 69 77.5t100 49.5t107 24t107 7q32 0 49 -2q6 -4 30.5 -21t33 -23t31 -23t32 -25.5t27.5 -25.5t26.5 -29.5t21 -30.5t17.5 -34.5t9.5 -36t4.5 -40.5zM385 294q-234 -7 -385 -85v433q103 -118 273 -118 q32 0 70 5q-21 -61 -21 -86q0 -67 63 -149zM558 805q0 -100 -43.5 -160.5t-140.5 -60.5q-51 0 -97 26t-78 67.5t-56 93.5t-35.5 104t-11.5 99q0 96 51.5 165t144.5 69q66 0 119 -41t84 -104t47 -130t16 -128zM1536 896v-736q0 -119 -84.5 -203.5t-203.5 -84.5h-468 q39 73 39 157q0 66 -22 122.5t-55.5 93t-72 71t-72 59.5t-55.5 54.5t-22 59.5q0 36 23 68t56 61.5t65.5 64.5t55.5 93t23 131t-26.5 145.5t-75.5 118.5q-6 6 -14 11t-12.5 7.5t-10 9.5t-10.5 17h135l135 64h-437q-138 0 -244.5 -38.5t-182.5 -133.5q0 126 81 213t207 87h960 q119 0 203.5 -84.5t84.5 -203.5v-96h-256v256h-128v-256h-256v-128h256v-256h128v256h256z" />
<glyph unicode="&#xf0d5;" horiz-adv-x="1664" d="M876 71q0 21 -4.5 40.5t-9.5 36t-17.5 34.5t-21 30.5t-26.5 29.5t-27.5 25.5t-32 25.5t-31 23t-33 23t-30.5 21q-17 2 -50 2q-54 0 -106 -7t-108 -25t-98 -46t-69 -75t-27 -107q0 -68 35.5 -121.5t93 -84t120.5 -45.5t127 -15q59 0 112.5 12.5t100.5 39t74.5 73.5 t27.5 110zM756 933q0 60 -16.5 127.5t-47 130.5t-84 104t-119.5 41q-93 0 -144 -69t-51 -165q0 -47 11.5 -99t35.5 -104t56 -93.5t78 -67.5t97 -26q97 0 140.5 60.5t43.5 160.5zM625 1408h437l-135 -79h-135q71 -45 110 -126t39 -169q0 -74 -23 -131.5t-56 -92.5t-66 -64.5 t-56 -61t-23 -67.5q0 -26 16.5 -51t43 -48t58.5 -48t64 -55.5t58.5 -66t43 -85t16.5 -106.5q0 -160 -140 -282q-152 -131 -420 -131q-59 0 -119.5 10t-122 33.5t-108.5 58t-77 89t-30 121.5q0 61 37 135q32 64 96 110.5t145 71t155 36t150 13.5q-64 83 -64 149q0 12 2 23.5 t5 19.5t8 21.5t7 21.5q-40 -5 -70 -5q-149 0 -255.5 98t-106.5 246q0 140 95 250.5t234 141.5q94 20 187 20zM1664 1152v-128h-256v-256h-128v256h-256v128h256v256h128v-256h256z" />
<glyph unicode="&#xf0d6;" horiz-adv-x="1920" d="M768 384h384v96h-128v448h-114l-148 -137l77 -80q42 37 55 57h2v-288h-128v-96zM1280 640q0 -70 -21 -142t-59.5 -134t-101.5 -101t-138 -39t-138 39t-101.5 101t-59.5 134t-21 142t21 142t59.5 134t101.5 101t138 39t138 -39t101.5 -101t59.5 -134t21 -142zM1792 384 v512q-106 0 -181 75t-75 181h-1152q0 -106 -75 -181t-181 -75v-512q106 0 181 -75t75 -181h1152q0 106 75 181t181 75zM1920 1216v-1152q0 -26 -19 -45t-45 -19h-1792q-26 0 -45 19t-19 45v1152q0 26 19 45t45 19h1792q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf0d7;" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf0d8;" horiz-adv-x="1024" d="M1024 320q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
<glyph unicode="&#xf0d9;" horiz-adv-x="640" d="M640 1088v-896q0 -26 -19 -45t-45 -19t-45 19l-448 448q-19 19 -19 45t19 45l448 448q19 19 45 19t45 -19t19 -45z" />
<glyph unicode="&#xf0da;" horiz-adv-x="640" d="M576 640q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19t-19 45v896q0 26 19 45t45 19t45 -19l448 -448q19 -19 19 -45z" />
<glyph unicode="&#xf0db;" horiz-adv-x="1664" d="M160 0h608v1152h-640v-1120q0 -13 9.5 -22.5t22.5 -9.5zM1536 32v1120h-640v-1152h608q13 0 22.5 9.5t9.5 22.5zM1664 1248v-1216q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1344q66 0 113 -47t47 -113z" />
<glyph unicode="&#xf0dc;" horiz-adv-x="1024" d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45zM1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
<glyph unicode="&#xf0dd;" horiz-adv-x="1024" d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf0de;" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
<glyph unicode="&#xf0e0;" horiz-adv-x="1792" d="M1792 826v-794q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v794q44 -49 101 -87q362 -246 497 -345q57 -42 92.5 -65.5t94.5 -48t110 -24.5h1h1q51 0 110 24.5t94.5 48t92.5 65.5q170 123 498 345q57 39 100 87zM1792 1120q0 -79 -49 -151t-122 -123 q-376 -261 -468 -325q-10 -7 -42.5 -30.5t-54 -38t-52 -32.5t-57.5 -27t-50 -9h-1h-1q-23 0 -50 9t-57.5 27t-52 32.5t-54 38t-42.5 30.5q-91 64 -262 182.5t-205 142.5q-62 42 -117 115.5t-55 136.5q0 78 41.5 130t118.5 52h1472q65 0 112.5 -47t47.5 -113z" />
<glyph unicode="&#xf0e1;" d="M349 911v-991h-330v991h330zM370 1217q1 -73 -50.5 -122t-135.5 -49h-2q-82 0 -132 49t-50 122q0 74 51.5 122.5t134.5 48.5t133 -48.5t51 -122.5zM1536 488v-568h-329v530q0 105 -40.5 164.5t-126.5 59.5q-63 0 -105.5 -34.5t-63.5 -85.5q-11 -30 -11 -81v-553h-329 q2 399 2 647t-1 296l-1 48h329v-144h-2q20 32 41 56t56.5 52t87 43.5t114.5 15.5q171 0 275 -113.5t104 -332.5z" />
<glyph unicode="&#xf0e2;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61q-172 0 -327 72.5t-264 204.5q-7 10 -6.5 22.5t8.5 20.5l137 138q10 9 25 9q16 -2 23 -12q73 -95 179 -147t225 -52q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5 t-163.5 109.5t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 -298z" />
<glyph unicode="&#xf0e3;" horiz-adv-x="1792" d="M1771 0q0 -53 -37 -90l-107 -108q-39 -37 -91 -37q-53 0 -90 37l-363 364q-38 36 -38 90q0 53 43 96l-256 256l-126 -126q-14 -14 -34 -14t-34 14q2 -2 12.5 -12t12.5 -13t10 -11.5t10 -13.5t6 -13.5t5.5 -16.5t1.5 -18q0 -38 -28 -68q-3 -3 -16.5 -18t-19 -20.5 t-18.5 -16.5t-22 -15.5t-22 -9t-26 -4.5q-40 0 -68 28l-408 408q-28 28 -28 68q0 13 4.5 26t9 22t15.5 22t16.5 18.5t20.5 19t18 16.5q30 28 68 28q10 0 18 -1.5t16.5 -5.5t13.5 -6t13.5 -10t11.5 -10t13 -12.5t12 -12.5q-14 14 -14 34t14 34l348 348q14 14 34 14t34 -14 q-2 2 -12.5 12t-12.5 13t-10 11.5t-10 13.5t-6 13.5t-5.5 16.5t-1.5 18q0 38 28 68q3 3 16.5 18t19 20.5t18.5 16.5t22 15.5t22 9t26 4.5q40 0 68 -28l408 -408q28 -28 28 -68q0 -13 -4.5 -26t-9 -22t-15.5 -22t-16.5 -18.5t-20.5 -19t-18 -16.5q-30 -28 -68 -28 q-10 0 -18 1.5t-16.5 5.5t-13.5 6t-13.5 10t-11.5 10t-13 12.5t-12 12.5q14 -14 14 -34t-14 -34l-126 -126l256 -256q43 43 96 43q52 0 91 -37l363 -363q37 -39 37 -91z" />
<glyph unicode="&#xf0e4;" horiz-adv-x="1792" d="M384 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM576 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1004 351l101 382q6 26 -7.5 48.5t-38.5 29.5 t-48 -6.5t-30 -39.5l-101 -382q-60 -5 -107 -43.5t-63 -98.5q-20 -77 20 -146t117 -89t146 20t89 117q16 60 -6 117t-72 91zM1664 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 1024q0 53 -37.5 90.5 t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1472 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1792 384q0 -261 -141 -483q-19 -29 -54 -29h-1402q-35 0 -54 29 q-141 221 -141 483q0 182 71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
<glyph unicode="&#xf0e5;" horiz-adv-x="1792" d="M896 1152q-204 0 -381.5 -69.5t-282 -187.5t-104.5 -255q0 -112 71.5 -213.5t201.5 -175.5l87 -50l-27 -96q-24 -91 -70 -172q152 63 275 171l43 38l57 -6q69 -8 130 -8q204 0 381.5 69.5t282 187.5t104.5 255t-104.5 255t-282 187.5t-381.5 69.5zM1792 640 q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22h-5q-15 0 -27 10.5t-16 27.5v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281q0 174 120 321.5 t326 233t450 85.5t450 -85.5t326 -233t120 -321.5z" />
<glyph unicode="&#xf0e6;" horiz-adv-x="1792" d="M704 1152q-153 0 -286 -52t-211.5 -141t-78.5 -191q0 -82 53 -158t149 -132l97 -56l-35 -84q34 20 62 39l44 31l53 -10q78 -14 153 -14q153 0 286 52t211.5 141t78.5 191t-78.5 191t-211.5 141t-286 52zM704 1280q191 0 353.5 -68.5t256.5 -186.5t94 -257t-94 -257 t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224q0 139 94 257t256.5 186.5 t353.5 68.5zM1526 111q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129 q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230q0 -120 -71 -224.5t-195 -176.5z" />
<glyph unicode="&#xf0e7;" horiz-adv-x="896" d="M885 970q18 -20 7 -44l-540 -1157q-13 -25 -42 -25q-4 0 -14 2q-17 5 -25.5 19t-4.5 30l197 808l-406 -101q-4 -1 -12 -1q-18 0 -31 11q-18 15 -13 39l201 825q4 14 16 23t28 9h328q19 0 32 -12.5t13 -29.5q0 -8 -5 -18l-171 -463l396 98q8 2 12 2q19 0 34 -15z" />
<glyph unicode="&#xf0e8;" horiz-adv-x="1792" d="M1792 288v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320 q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192q0 52 38 90t90 38h512v192h-96q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-96v-192h512q52 0 90 -38t38 -90v-192h96q40 0 68 -28t28 -68 z" />
<glyph unicode="&#xf0e9;" horiz-adv-x="1664" d="M896 708v-580q0 -104 -76 -180t-180 -76t-180 76t-76 180q0 26 19 45t45 19t45 -19t19 -45q0 -50 39 -89t89 -39t89 39t39 89v580q33 11 64 11t64 -11zM1664 681q0 -13 -9.5 -22.5t-22.5 -9.5q-11 0 -23 10q-49 46 -93 69t-102 23q-68 0 -128 -37t-103 -97 q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -28 -17q-18 0 -29 17q-4 6 -14.5 24t-17.5 28q-43 60 -102.5 97t-127.5 37t-127.5 -37t-102.5 -97q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -29 -17q-17 0 -28 17q-4 6 -14.5 24t-17.5 28q-43 60 -103 97t-128 37q-58 0 -102 -23t-93 -69 q-12 -10 -23 -10q-13 0 -22.5 9.5t-9.5 22.5q0 5 1 7q45 183 172.5 319.5t298 204.5t360.5 68q140 0 274.5 -40t246.5 -113.5t194.5 -187t115.5 -251.5q1 -2 1 -7zM896 1408v-98q-42 2 -64 2t-64 -2v98q0 26 19 45t45 19t45 -19t19 -45z" />
<glyph unicode="&#xf0ea;" horiz-adv-x="1792" d="M768 -128h896v640h-416q-40 0 -68 28t-28 68v416h-384v-1152zM1024 1312v64q0 13 -9.5 22.5t-22.5 9.5h-704q-13 0 -22.5 -9.5t-9.5 -22.5v-64q0 -13 9.5 -22.5t22.5 -9.5h704q13 0 22.5 9.5t9.5 22.5zM1280 640h299l-299 299v-299zM1792 512v-672q0 -40 -28 -68t-68 -28 h-960q-40 0 -68 28t-28 68v160h-544q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1088q40 0 68 -28t28 -68v-328q21 -13 36 -28l408 -408q28 -28 48 -76t20 -88z" />
<glyph unicode="&#xf0eb;" horiz-adv-x="1024" d="M736 960q0 -13 -9.5 -22.5t-22.5 -9.5t-22.5 9.5t-9.5 22.5q0 46 -54 71t-106 25q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5q50 0 99.5 -16t87 -54t37.5 -90zM896 960q0 72 -34.5 134t-90 101.5t-123 62t-136.5 22.5t-136.5 -22.5t-123 -62t-90 -101.5t-34.5 -134 q0 -101 68 -180q10 -11 30.5 -33t30.5 -33q128 -153 141 -298h228q13 145 141 298q10 11 30.5 33t30.5 33q68 79 68 180zM1024 960q0 -155 -103 -268q-45 -49 -74.5 -87t-59.5 -95.5t-34 -107.5q47 -28 47 -82q0 -37 -25 -64q25 -27 25 -64q0 -52 -45 -81q13 -23 13 -47 q0 -46 -31.5 -71t-77.5 -25q-20 -44 -60 -70t-87 -26t-87 26t-60 70q-46 0 -77.5 25t-31.5 71q0 24 13 47q-45 29 -45 81q0 37 25 64q-25 27 -25 64q0 54 47 82q-4 50 -34 107.5t-59.5 95.5t-74.5 87q-103 113 -103 268q0 99 44.5 184.5t117 142t164 89t186.5 32.5 t186.5 -32.5t164 -89t117 -142t44.5 -184.5z" />
<glyph unicode="&#xf0ec;" horiz-adv-x="1792" d="M1792 352v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5q-12 0 -24 10l-319 320q-9 9 -9 22q0 14 9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h1376q13 0 22.5 -9.5t9.5 -22.5zM1792 896q0 -14 -9 -23l-320 -320q-9 -9 -23 -9 q-13 0 -22.5 9.5t-9.5 22.5v192h-1376q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1376v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" />
<glyph unicode="&#xf0ed;" horiz-adv-x="1920" d="M1280 608q0 14 -9 23t-23 9h-224v352q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-352h-224q-13 0 -22.5 -9.5t-9.5 -22.5q0 -14 9 -23l352 -352q9 -9 23 -9t23 9l351 351q10 12 10 24zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088 q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" />
<glyph unicode="&#xf0ee;" horiz-adv-x="1920" d="M1280 672q0 14 -9 23l-352 352q-9 9 -23 9t-23 -9l-351 -351q-10 -12 -10 -24q0 -14 9 -23t23 -9h224v-352q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5v352h224q13 0 22.5 9.5t9.5 22.5zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088 q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" />
<glyph unicode="&#xf0f0;" horiz-adv-x="1408" d="M384 192q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM1408 131q0 -121 -73 -190t-194 -69h-874q-121 0 -194 69t-73 190q0 68 5.5 131t24 138t47.5 132.5t81 103t120 60.5q-22 -52 -22 -120v-203q-58 -20 -93 -70t-35 -111q0 -80 56 -136t136 -56 t136 56t56 136q0 61 -35.5 111t-92.5 70v203q0 62 25 93q132 -104 295 -104t295 104q25 -31 25 -93v-64q-106 0 -181 -75t-75 -181v-89q-32 -29 -32 -71q0 -40 28 -68t68 -28t68 28t28 68q0 42 -32 71v89q0 52 38 90t90 38t90 -38t38 -90v-89q-32 -29 -32 -71q0 -40 28 -68 t68 -28t68 28t28 68q0 42 -32 71v89q0 68 -34.5 127.5t-93.5 93.5q0 10 0.5 42.5t0 48t-2.5 41.5t-7 47t-13 40q68 -15 120 -60.5t81 -103t47.5 -132.5t24 -138t5.5 -131zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5 t271.5 -112.5t112.5 -271.5z" />
<glyph unicode="&#xf0f1;" horiz-adv-x="1408" d="M1280 832q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 832q0 -62 -35.5 -111t-92.5 -70v-395q0 -159 -131.5 -271.5t-316.5 -112.5t-316.5 112.5t-131.5 271.5v132q-164 20 -274 128t-110 252v512q0 26 19 45t45 19q6 0 16 -2q17 30 47 48 t65 18q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5q-33 0 -64 18v-402q0 -106 94 -181t226 -75t226 75t94 181v402q-31 -18 -64 -18q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5q35 0 65 -18t47 -48q10 2 16 2q26 0 45 -19t19 -45v-512q0 -144 -110 -252 t-274 -128v-132q0 -106 94 -181t226 -75t226 75t94 181v395q-57 21 -92.5 70t-35.5 111q0 80 56 136t136 56t136 -56t56 -136z" />
<glyph unicode="&#xf0f2;" horiz-adv-x="1792" d="M640 1152h512v128h-512v-128zM288 1152v-1280h-64q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h64zM1408 1152v-1280h-1024v1280h128v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h128zM1792 928v-832q0 -92 -66 -158t-158 -66h-64v1280h64q92 0 158 -66 t66 -158z" />
<glyph unicode="&#xf0f3;" horiz-adv-x="1664" d="M848 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM1664 128q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q190 161 287 397.5t97 498.5 q0 165 96 262t264 117q-8 18 -8 37q0 40 28 68t68 28t68 -28t28 -68q0 -19 -8 -37q168 -20 264 -117t96 -262q0 -262 97 -498.5t287 -397.5z" />
<glyph unicode="&#xf0f4;" horiz-adv-x="1920" d="M1664 896q0 80 -56 136t-136 56h-64v-384h64q80 0 136 56t56 136zM0 128h1792q0 -106 -75 -181t-181 -75h-1280q-106 0 -181 75t-75 181zM1856 896q0 -159 -112.5 -271.5t-271.5 -112.5h-64v-32q0 -92 -66 -158t-158 -66h-704q-92 0 -158 66t-66 158v736q0 26 19 45 t45 19h1152q159 0 271.5 -112.5t112.5 -271.5z" />
<glyph unicode="&#xf0f5;" horiz-adv-x="1408" d="M640 1472v-640q0 -61 -35.5 -111t-92.5 -70v-779q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v779q-57 20 -92.5 70t-35.5 111v640q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45 t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45zM1408 1472v-1600q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v512h-224q-13 0 -22.5 9.5t-9.5 22.5v800q0 132 94 226t226 94h256q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf0f6;" horiz-adv-x="1280" d="M1024 352v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704q14 0 23 -9t9 -23zM1024 608v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704q14 0 23 -9t9 -23zM128 0h1024v768h-416q-40 0 -68 28t-28 68v416h-512v-1280z M768 896h376q-10 29 -22 41l-313 313q-12 12 -41 22v-376zM1280 864v-896q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h640q40 0 88 -20t76 -48l312 -312q28 -28 48 -76t20 -88z" />
<glyph unicode="&#xf0f7;" horiz-adv-x="1408" d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 -128h384v1536h-1152v-1536h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM1408 1472v-1664q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h1280q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf0f8;" horiz-adv-x="1408" d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 -128h384v1152h-256v-32q0 -40 -28 -68t-68 -28h-448q-40 0 -68 28t-28 68v32h-256v-1152h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM896 1056v320q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-96h-128v96q0 13 -9.5 22.5 t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5v96h128v-96q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1408 1088v-1280q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1280q0 26 19 45t45 19h320 v288q0 40 28 68t68 28h448q40 0 68 -28t28 -68v-288h320q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf0f9;" horiz-adv-x="1920" d="M640 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM256 640h384v256h-158q-14 -2 -22 -9l-195 -195q-7 -12 -9 -22v-30zM1536 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1664 800v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM1920 1344v-1152 q0 -26 -19 -45t-45 -19h-192q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-128q-26 0 -45 19t-19 45t19 45t45 19v416q0 26 13 58t32 51l198 198q19 19 51 32t58 13h160v320q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf0fa;" horiz-adv-x="1792" d="M1280 416v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM640 1152h512v128h-512v-128zM256 1152v-1280h-32 q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h32zM1440 1152v-1280h-1088v1280h160v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h160zM1792 928v-832q0 -92 -66 -158t-158 -66h-32v1280h32q92 0 158 -66t66 -158z" />
<glyph unicode="&#xf0fb;" horiz-adv-x="1920" d="M1920 576q-1 -32 -288 -96l-352 -32l-224 -64h-64l-293 -352h69q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-96h-160h-64v32h64v416h-160l-192 -224h-96l-32 32v192h32v32h128v8l-192 24v128l192 24v8h-128v32h-32v192l32 32h96l192 -224h160v416h-64v32h64h160h96 q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-69l293 -352h64l224 -64l352 -32q261 -58 287 -93z" />
<glyph unicode="&#xf0fc;" horiz-adv-x="1664" d="M640 640v384h-256v-256q0 -53 37.5 -90.5t90.5 -37.5h128zM1664 192v-192h-1152v192l128 192h-128q-159 0 -271.5 112.5t-112.5 271.5v320l-64 64l32 128h480l32 128h960l32 -192l-64 -32v-800z" />
<glyph unicode="&#xf0fd;" d="M1280 192v896q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-512v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-896q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h512v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf0fe;" d="M1280 576v128q0 26 -19 45t-45 19h-320v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-320q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h320v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h320q26 0 45 19t19 45zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf100;" horiz-adv-x="1024" d="M627 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23zM1011 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23 t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23z" />
<glyph unicode="&#xf101;" horiz-adv-x="1024" d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM979 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23 l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
<glyph unicode="&#xf102;" horiz-adv-x="1152" d="M1075 224q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM1075 608q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393 q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
<glyph unicode="&#xf103;" horiz-adv-x="1152" d="M1075 672q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23zM1075 1056q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23 t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
<glyph unicode="&#xf104;" horiz-adv-x="640" d="M627 992q0 -13 -10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
<glyph unicode="&#xf105;" horiz-adv-x="640" d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
<glyph unicode="&#xf106;" horiz-adv-x="1152" d="M1075 352q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
<glyph unicode="&#xf107;" horiz-adv-x="1152" d="M1075 800q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
<glyph unicode="&#xf108;" horiz-adv-x="1920" d="M1792 544v832q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5zM1920 1376v-1088q0 -66 -47 -113t-113 -47h-544q0 -37 16 -77.5t32 -71t16 -43.5q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19 t-19 45q0 14 16 44t32 70t16 78h-544q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
<glyph unicode="&#xf109;" horiz-adv-x="1920" d="M416 256q-66 0 -113 47t-47 113v704q0 66 47 113t113 47h1088q66 0 113 -47t47 -113v-704q0 -66 -47 -113t-113 -47h-1088zM384 1120v-704q0 -13 9.5 -22.5t22.5 -9.5h1088q13 0 22.5 9.5t9.5 22.5v704q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5z M1760 192h160v-96q0 -40 -47 -68t-113 -28h-1600q-66 0 -113 28t-47 68v96h160h1600zM1040 96q16 0 16 16t-16 16h-160q-16 0 -16 -16t16 -16h160z" />
<glyph unicode="&#xf10a;" horiz-adv-x="1152" d="M640 128q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1024 288v960q0 13 -9.5 22.5t-22.5 9.5h-832q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h832q13 0 22.5 9.5t9.5 22.5zM1152 1248v-1088q0 -66 -47 -113t-113 -47h-832 q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h832q66 0 113 -47t47 -113z" />
<glyph unicode="&#xf10b;" horiz-adv-x="768" d="M464 128q0 33 -23.5 56.5t-56.5 23.5t-56.5 -23.5t-23.5 -56.5t23.5 -56.5t56.5 -23.5t56.5 23.5t23.5 56.5zM672 288v704q0 13 -9.5 22.5t-22.5 9.5h-512q-13 0 -22.5 -9.5t-9.5 -22.5v-704q0 -13 9.5 -22.5t22.5 -9.5h512q13 0 22.5 9.5t9.5 22.5zM480 1136 q0 16 -16 16h-160q-16 0 -16 -16t16 -16h160q16 0 16 16zM768 1152v-1024q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v1024q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" />
<glyph unicode="&#xf10c;" d="M768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103 t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf10d;" horiz-adv-x="1664" d="M768 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z M1664 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z" />
<glyph unicode="&#xf10e;" horiz-adv-x="1664" d="M768 1216v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136zM1664 1216 v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136z" />
<glyph unicode="&#xf110;" horiz-adv-x="1568" d="M496 192q0 -60 -42.5 -102t-101.5 -42q-60 0 -102 42t-42 102t42 102t102 42q59 0 101.5 -42t42.5 -102zM928 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM320 640q0 -66 -47 -113t-113 -47t-113 47t-47 113 t47 113t113 47t113 -47t47 -113zM1360 192q0 -46 -33 -79t-79 -33t-79 33t-33 79t33 79t79 33t79 -33t33 -79zM528 1088q0 -73 -51.5 -124.5t-124.5 -51.5t-124.5 51.5t-51.5 124.5t51.5 124.5t124.5 51.5t124.5 -51.5t51.5 -124.5zM992 1280q0 -80 -56 -136t-136 -56 t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1536 640q0 -40 -28 -68t-68 -28t-68 28t-28 68t28 68t68 28t68 -28t28 -68zM1328 1088q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5z" />
<glyph unicode="&#xf111;" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf112;" horiz-adv-x="1792" d="M1792 416q0 -166 -127 -451q-3 -7 -10.5 -24t-13.5 -30t-13 -22q-12 -17 -28 -17q-15 0 -23.5 10t-8.5 25q0 9 2.5 26.5t2.5 23.5q5 68 5 123q0 101 -17.5 181t-48.5 138.5t-80 101t-105.5 69.5t-133 42.5t-154 21.5t-175.5 6h-224v-256q0 -26 -19 -45t-45 -19t-45 19 l-512 512q-19 19 -19 45t19 45l512 512q19 19 45 19t45 -19t19 -45v-256h224q713 0 875 -403q53 -134 53 -333z" />
<glyph unicode="&#xf113;" horiz-adv-x="1664" d="M640 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1280 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1440 320 q0 120 -69 204t-187 84q-41 0 -195 -21q-71 -11 -157 -11t-157 11q-152 21 -195 21q-118 0 -187 -84t-69 -204q0 -88 32 -153.5t81 -103t122 -60t140 -29.5t149 -7h168q82 0 149 7t140 29.5t122 60t81 103t32 153.5zM1664 496q0 -207 -61 -331q-38 -77 -105.5 -133t-141 -86 t-170 -47.5t-171.5 -22t-167 -4.5q-78 0 -142 3t-147.5 12.5t-152.5 30t-137 51.5t-121 81t-86 115q-62 123 -62 331q0 237 136 396q-27 82 -27 170q0 116 51 218q108 0 190 -39.5t189 -123.5q147 35 309 35q148 0 280 -32q105 82 187 121t189 39q51 -102 51 -218 q0 -87 -27 -168q136 -160 136 -398z" />
<glyph unicode="&#xf114;" horiz-adv-x="1664" d="M1536 224v704q0 40 -28 68t-68 28h-704q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68v-960q0 -40 28 -68t68 -28h1216q40 0 68 28t28 68zM1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320 q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" />
<glyph unicode="&#xf115;" horiz-adv-x="1920" d="M1781 605q0 35 -53 35h-1088q-40 0 -85.5 -21.5t-71.5 -52.5l-294 -363q-18 -24 -18 -40q0 -35 53 -35h1088q40 0 86 22t71 53l294 363q18 22 18 39zM640 768h768v160q0 40 -28 68t-68 28h-576q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68 v-853l256 315q44 53 116 87.5t140 34.5zM1909 605q0 -62 -46 -120l-295 -363q-43 -53 -116 -87.5t-140 -34.5h-1088q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158v-160h192q54 0 99 -24.5t67 -70.5q15 -32 15 -68z " />
<glyph unicode="&#xf116;" horiz-adv-x="1792" />
<glyph unicode="&#xf117;" horiz-adv-x="1792" />
<glyph unicode="&#xf118;" d="M1134 461q-37 -121 -138 -195t-228 -74t-228 74t-138 195q-8 25 4 48.5t38 31.5q25 8 48.5 -4t31.5 -38q25 -80 92.5 -129.5t151.5 -49.5t151.5 49.5t92.5 129.5q8 26 32 38t49 4t37 -31.5t4 -48.5zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5 t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5 t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf119;" d="M1134 307q8 -25 -4 -48.5t-37 -31.5t-49 4t-32 38q-25 80 -92.5 129.5t-151.5 49.5t-151.5 -49.5t-92.5 -129.5q-8 -26 -31.5 -38t-48.5 -4q-26 8 -38 31.5t-4 48.5q37 121 138 195t228 74t228 -74t138 -195zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5 t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204 t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf11a;" d="M1152 448q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h640q26 0 45 -19t19 -45zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5 t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf11b;" horiz-adv-x="1920" d="M832 448v128q0 14 -9 23t-23 9h-192v192q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-192h-192q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h192v-192q0 -14 9 -23t23 -9h128q14 0 23 9t9 23v192h192q14 0 23 9t9 23zM1408 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5 t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1920 512q0 -212 -150 -362t-362 -150q-192 0 -338 128h-220q-146 -128 -338 -128q-212 0 -362 150 t-150 362t150 362t362 150h896q212 0 362 -150t150 -362z" />
<glyph unicode="&#xf11c;" horiz-adv-x="1920" d="M384 368v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM512 624v-96q0 -16 -16 -16h-224q-16 0 -16 16v96q0 16 16 16h224q16 0 16 -16zM384 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1408 368v-96q0 -16 -16 -16 h-864q-16 0 -16 16v96q0 16 16 16h864q16 0 16 -16zM768 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM640 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1024 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16 h96q16 0 16 -16zM896 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1280 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1664 368v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1152 880v-96 q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1408 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1664 880v-352q0 -16 -16 -16h-224q-16 0 -16 16v96q0 16 16 16h112v240q0 16 16 16h96q16 0 16 -16zM1792 128v896h-1664v-896 h1664zM1920 1024v-896q0 -53 -37.5 -90.5t-90.5 -37.5h-1664q-53 0 -90.5 37.5t-37.5 90.5v896q0 53 37.5 90.5t90.5 37.5h1664q53 0 90.5 -37.5t37.5 -90.5z" />
<glyph unicode="&#xf11d;" horiz-adv-x="1792" d="M1664 491v616q-169 -91 -306 -91q-82 0 -145 32q-100 49 -184 76.5t-178 27.5q-173 0 -403 -127v-599q245 113 433 113q55 0 103.5 -7.5t98 -26t77 -31t82.5 -39.5l28 -14q44 -22 101 -22q120 0 293 92zM320 1280q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9 h-64q-14 0 -23 9t-9 23v1266q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -99 48t-91 29t-114 14q-102 0 -235.5 -44t-228.5 -102 q-15 -9 -33 -9q-16 0 -32 8q-32 19 -32 56v742q0 35 31 55q35 21 78.5 42.5t114 52t152.5 49.5t155 19q112 0 209 -31t209 -86q38 -19 89 -19q122 0 310 112q22 12 31 17q31 16 62 -2q31 -20 31 -55z" />
<glyph unicode="&#xf11e;" horiz-adv-x="1792" d="M832 536v192q-181 -16 -384 -117v-185q205 96 384 110zM832 954v197q-172 -8 -384 -126v-189q215 111 384 118zM1664 491v184q-235 -116 -384 -71v224q-20 6 -39 15q-5 3 -33 17t-34.5 17t-31.5 15t-34.5 15.5t-32.5 13t-36 12.5t-35 8.5t-39.5 7.5t-39.5 4t-44 2 q-23 0 -49 -3v-222h19q102 0 192.5 -29t197.5 -82q19 -9 39 -15v-188q42 -17 91 -17q120 0 293 92zM1664 918v189q-169 -91 -306 -91q-45 0 -78 8v-196q148 -42 384 90zM320 1280q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v1266 q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -99 48t-91 29t-114 14q-102 0 -235.5 -44t-228.5 -102q-15 -9 -33 -9q-16 0 -32 8 q-32 19 -32 56v742q0 35 31 55q35 21 78.5 42.5t114 52t152.5 49.5t155 19q112 0 209 -31t209 -86q38 -19 89 -19q122 0 310 112q22 12 31 17q31 16 62 -2q31 -20 31 -55z" />
<glyph unicode="&#xf120;" horiz-adv-x="1664" d="M585 553l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23zM1664 96v-64q0 -14 -9 -23t-23 -9h-960q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h960q14 0 23 -9 t9 -23z" />
<glyph unicode="&#xf121;" horiz-adv-x="1920" d="M617 137l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23zM1208 1204l-373 -1291q-4 -13 -15.5 -19.5t-23.5 -2.5l-62 17q-13 4 -19.5 15.5t-2.5 24.5 l373 1291q4 13 15.5 19.5t23.5 2.5l62 -17q13 -4 19.5 -15.5t2.5 -24.5zM1865 553l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23z" />
<glyph unicode="&#xf122;" horiz-adv-x="1792" d="M640 454v-70q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45t19 45l512 512q29 31 70 14q39 -17 39 -59v-69l-397 -398q-19 -19 -19 -45t19 -45zM1792 416q0 -58 -17 -133.5t-38.5 -138t-48 -125t-40.5 -90.5l-20 -40q-8 -17 -28 -17q-6 0 -9 1 q-25 8 -23 34q43 400 -106 565q-64 71 -170.5 110.5t-267.5 52.5v-251q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45t19 45l512 512q29 31 70 14q39 -17 39 -59v-262q411 -28 599 -221q169 -173 169 -509z" />
<glyph unicode="&#xf123;" horiz-adv-x="1664" d="M1186 579l257 250l-356 52l-66 10l-30 60l-159 322v-963l59 -31l318 -168l-60 355l-12 66zM1638 841l-363 -354l86 -500q5 -33 -6 -51.5t-34 -18.5q-17 0 -40 12l-449 236l-449 -236q-23 -12 -40 -12q-23 0 -34 18.5t-6 51.5l86 500l-364 354q-32 32 -23 59.5t54 34.5 l502 73l225 455q20 41 49 41q28 0 49 -41l225 -455l502 -73q45 -7 54 -34.5t-24 -59.5z" />
<glyph unicode="&#xf124;" horiz-adv-x="1408" d="M1401 1187l-640 -1280q-17 -35 -57 -35q-5 0 -15 2q-22 5 -35.5 22.5t-13.5 39.5v576h-576q-22 0 -39.5 13.5t-22.5 35.5t4 42t29 30l1280 640q13 7 29 7q27 0 45 -19q15 -14 18.5 -34.5t-6.5 -39.5z" />
<glyph unicode="&#xf125;" horiz-adv-x="1664" d="M557 256h595v595zM512 301l595 595h-595v-595zM1664 224v-192q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v224h-864q-14 0 -23 9t-9 23v864h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224v224q0 14 9 23t23 9h192q14 0 23 -9t9 -23 v-224h851l246 247q10 9 23 9t23 -9q9 -10 9 -23t-9 -23l-247 -246v-851h224q14 0 23 -9t9 -23z" />
<glyph unicode="&#xf126;" horiz-adv-x="1024" d="M288 64q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM288 1216q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM928 1088q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1024 1088q0 -52 -26 -96.5t-70 -69.5 q-2 -287 -226 -414q-68 -38 -203 -81q-128 -40 -169.5 -71t-41.5 -100v-26q44 -25 70 -69.5t26 -96.5q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 52 26 96.5t70 69.5v820q-44 25 -70 69.5t-26 96.5q0 80 56 136t136 56t136 -56t56 -136q0 -52 -26 -96.5t-70 -69.5v-497 q54 26 154 57q55 17 87.5 29.5t70.5 31t59 39.5t40.5 51t28 69.5t8.5 91.5q-44 25 -70 69.5t-26 96.5q0 80 56 136t136 56t136 -56t56 -136z" />
<glyph unicode="&#xf127;" horiz-adv-x="1664" d="M439 265l-256 -256q-10 -9 -23 -9q-12 0 -23 9q-9 10 -9 23t9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23zM608 224v-320q0 -14 -9 -23t-23 -9t-23 9t-9 23v320q0 14 9 23t23 9t23 -9t9 -23zM384 448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23t9 23t23 9h320 q14 0 23 -9t9 -23zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-334 335q-21 21 -42 56l239 18l273 -274q27 -27 68 -27.5t68 26.5l147 146q28 28 28 67q0 40 -28 68l-274 275l18 239q35 -21 56 -42l336 -336q84 -86 84 -204zM1031 1044l-239 -18 l-273 274q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l274 -274l-18 -240q-35 21 -56 42l-336 336q-84 86 -84 204q0 120 85 203l147 146q83 83 203 83q121 0 204 -85l334 -335q21 -21 42 -56zM1664 960q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9 t-9 23t9 23t23 9h320q14 0 23 -9t9 -23zM1120 1504v-320q0 -14 -9 -23t-23 -9t-23 9t-9 23v320q0 14 9 23t23 9t23 -9t9 -23zM1527 1353l-256 -256q-11 -9 -23 -9t-23 9q-9 10 -9 23t9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23z" />
<glyph unicode="&#xf128;" horiz-adv-x="1024" d="M704 280v-240q0 -16 -12 -28t-28 -12h-240q-16 0 -28 12t-12 28v240q0 16 12 28t28 12h240q16 0 28 -12t12 -28zM1020 880q0 -54 -15.5 -101t-35 -76.5t-55 -59.5t-57.5 -43.5t-61 -35.5q-41 -23 -68.5 -65t-27.5 -67q0 -17 -12 -32.5t-28 -15.5h-240q-15 0 -25.5 18.5 t-10.5 37.5v45q0 83 65 156.5t143 108.5q59 27 84 56t25 76q0 42 -46.5 74t-107.5 32q-65 0 -108 -29q-35 -25 -107 -115q-13 -16 -31 -16q-12 0 -25 8l-164 125q-13 10 -15.5 25t5.5 28q160 266 464 266q80 0 161 -31t146 -83t106 -127.5t41 -158.5z" />
<glyph unicode="&#xf129;" horiz-adv-x="640" d="M640 192v-128q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64v384h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-576h64q26 0 45 -19t19 -45zM512 1344v-192q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v192 q0 26 19 45t45 19h256q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf12a;" horiz-adv-x="640" d="M512 288v-224q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v224q0 26 19 45t45 19h256q26 0 45 -19t19 -45zM542 1344l-28 -768q-1 -26 -20.5 -45t-45.5 -19h-256q-26 0 -45.5 19t-20.5 45l-28 768q-1 26 17.5 45t44.5 19h320q26 0 44.5 -19t17.5 -45z" />
<glyph unicode="&#xf12b;" d="M897 167v-167h-248l-159 252l-24 42q-8 9 -11 21h-3l-9 -21q-10 -20 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109zM1534 846v-206h-514l-3 27 q-4 28 -4 46q0 64 26 117t65 86.5t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q83 65 188 65q110 0 178 -59.5t68 -158.5q0 -56 -24.5 -103t-62 -76.5t-81.5 -58.5t-82 -50.5t-65.5 -51.5t-30.5 -63h232v80 h126z" />
<glyph unicode="&#xf12c;" d="M897 167v-167h-248l-159 252l-24 42q-8 9 -11 21h-3l-9 -21q-10 -20 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109zM1536 -50v-206h-514l-4 27 q-3 45 -3 46q0 64 26 117t65 86.5t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q80 65 188 65q110 0 178 -59.5t68 -158.5q0 -66 -34.5 -118.5t-84 -86t-99.5 -62.5t-87 -63t-41 -73h232v80h126z" />
<glyph unicode="&#xf12d;" horiz-adv-x="1920" d="M896 128l336 384h-768l-336 -384h768zM1909 1205q15 -34 9.5 -71.5t-30.5 -65.5l-896 -1024q-38 -44 -96 -44h-768q-38 0 -69.5 20.5t-47.5 54.5q-15 34 -9.5 71.5t30.5 65.5l896 1024q38 44 96 44h768q38 0 69.5 -20.5t47.5 -54.5z" />
<glyph unicode="&#xf12e;" horiz-adv-x="1664" d="M1664 438q0 -81 -44.5 -135t-123.5 -54q-41 0 -77.5 17.5t-59 38t-56.5 38t-71 17.5q-110 0 -110 -124q0 -39 16 -115t15 -115v-5q-22 0 -33 -1q-34 -3 -97.5 -11.5t-115.5 -13.5t-98 -5q-61 0 -103 26.5t-42 83.5q0 37 17.5 71t38 56.5t38 59t17.5 77.5q0 79 -54 123.5 t-135 44.5q-84 0 -143 -45.5t-59 -127.5q0 -43 15 -83t33.5 -64.5t33.5 -53t15 -50.5q0 -45 -46 -89q-37 -35 -117 -35q-95 0 -245 24q-9 2 -27.5 4t-27.5 4l-13 2q-1 0 -3 1q-2 0 -2 1v1024q2 -1 17.5 -3.5t34 -5t21.5 -3.5q150 -24 245 -24q80 0 117 35q46 44 46 89 q0 22 -15 50.5t-33.5 53t-33.5 64.5t-15 83q0 82 59 127.5t144 45.5q80 0 134 -44.5t54 -123.5q0 -41 -17.5 -77.5t-38 -59t-38 -56.5t-17.5 -71q0 -57 42 -83.5t103 -26.5q64 0 180 15t163 17v-2q-1 -2 -3.5 -17.5t-5 -34t-3.5 -21.5q-24 -150 -24 -245q0 -80 35 -117 q44 -46 89 -46q22 0 50.5 15t53 33.5t64.5 33.5t83 15q82 0 127.5 -59t45.5 -143z" />
<glyph unicode="&#xf130;" horiz-adv-x="1152" d="M1152 832v-128q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-217 24 -364.5 187.5t-147.5 384.5v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -185 131.5 -316.5t316.5 -131.5 t316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45zM896 1216v-512q0 -132 -94 -226t-226 -94t-226 94t-94 226v512q0 132 94 226t226 94t226 -94t94 -226z" />
<glyph unicode="&#xf131;" horiz-adv-x="1408" d="M271 591l-101 -101q-42 103 -42 214v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -53 15 -113zM1385 1193l-361 -361v-128q0 -132 -94 -226t-226 -94q-55 0 -109 19l-96 -96q97 -51 205 -51q185 0 316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45v-128 q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-125 13 -235 81l-254 -254q-10 -10 -23 -10t-23 10l-82 82q-10 10 -10 23t10 23l1234 1234q10 10 23 10t23 -10l82 -82q10 -10 10 -23 t-10 -23zM1005 1325l-621 -621v512q0 132 94 226t226 94q102 0 184.5 -59t116.5 -152z" />
<glyph unicode="&#xf132;" horiz-adv-x="1280" d="M1088 576v640h-448v-1137q119 63 213 137q235 184 235 360zM1280 1344v-768q0 -86 -33.5 -170.5t-83 -150t-118 -127.5t-126.5 -103t-121 -77.5t-89.5 -49.5t-42.5 -20q-12 -6 -26 -6t-26 6q-16 7 -42.5 20t-89.5 49.5t-121 77.5t-126.5 103t-118 127.5t-83 150 t-33.5 170.5v768q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf133;" horiz-adv-x="1664" d="M128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280 q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
<glyph unicode="&#xf134;" horiz-adv-x="1408" d="M512 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 1376v-320q0 -16 -12 -25q-8 -7 -20 -7q-4 0 -7 1l-448 96q-11 2 -18 11t-7 20h-256v-102q111 -23 183.5 -111t72.5 -203v-800q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v800 q0 106 62.5 190.5t161.5 114.5v111h-32q-59 0 -115 -23.5t-91.5 -53t-66 -66.5t-40.5 -53.5t-14 -24.5q-17 -35 -57 -35q-16 0 -29 7q-23 12 -31.5 37t3.5 49q5 10 14.5 26t37.5 53.5t60.5 70t85 67t108.5 52.5q-25 42 -25 86q0 66 47 113t113 47t113 -47t47 -113 q0 -33 -14 -64h302q0 11 7 20t18 11l448 96q3 1 7 1q12 0 20 -7q12 -9 12 -25z" />
<glyph unicode="&#xf135;" horiz-adv-x="1664" d="M1440 1088q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1664 1376q0 -249 -75.5 -430.5t-253.5 -360.5q-81 -80 -195 -176l-20 -379q-2 -16 -16 -26l-384 -224q-7 -4 -16 -4q-12 0 -23 9l-64 64q-13 14 -8 32l85 276l-281 281l-276 -85q-3 -1 -9 -1 q-14 0 -23 9l-64 64q-17 19 -5 39l224 384q10 14 26 16l379 20q96 114 176 195q188 187 358 258t431 71q14 0 24 -9.5t10 -22.5z" />
<glyph unicode="&#xf136;" horiz-adv-x="1792" d="M1745 763l-164 -763h-334l178 832q13 56 -15 88q-27 33 -83 33h-169l-204 -953h-334l204 953h-286l-204 -953h-334l204 953l-153 327h1276q101 0 189.5 -40.5t147.5 -113.5q60 -73 81 -168.5t0 -194.5z" />
<glyph unicode="&#xf137;" d="M909 141l102 102q19 19 19 45t-19 45l-307 307l307 307q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45t19 -45l454 -454q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf138;" d="M717 141l454 454q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l307 -307l-307 -307q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf139;" d="M1165 397l102 102q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19l307 307l307 -307q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf13a;" d="M813 237l454 454q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-307 -307l-307 307q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l454 -454q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf13b;" horiz-adv-x="1408" d="M1130 939l16 175h-884l47 -534h612l-22 -228l-197 -53l-196 53l-13 140h-175l22 -278l362 -100h4v1l359 99l50 544h-644l-15 181h674zM0 1408h1408l-128 -1438l-578 -162l-574 162z" />
<glyph unicode="&#xf13c;" horiz-adv-x="1792" d="M275 1408h1505l-266 -1333l-804 -267l-698 267l71 356h297l-29 -147l422 -161l486 161l68 339h-1208l58 297h1209l38 191h-1208z" />
<glyph unicode="&#xf13d;" horiz-adv-x="1792" d="M960 1280q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1792 352v-352q0 -22 -20 -30q-8 -2 -12 -2q-13 0 -23 9l-93 93q-119 -143 -318.5 -226.5t-429.5 -83.5t-429.5 83.5t-318.5 226.5l-93 -93q-9 -9 -23 -9q-4 0 -12 2q-20 8 -20 30v352 q0 14 9 23t23 9h352q22 0 30 -20q8 -19 -7 -35l-100 -100q67 -91 189.5 -153.5t271.5 -82.5v647h-192q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h192v163q-58 34 -93 92.5t-35 128.5q0 106 75 181t181 75t181 -75t75 -181q0 -70 -35 -128.5t-93 -92.5v-163h192q26 0 45 -19 t19 -45v-128q0 -26 -19 -45t-45 -19h-192v-647q149 20 271.5 82.5t189.5 153.5l-100 100q-15 16 -7 35q8 20 30 20h352q14 0 23 -9t9 -23z" />
<glyph unicode="&#xf13e;" horiz-adv-x="1152" d="M1056 768q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v320q0 185 131.5 316.5t316.5 131.5t316.5 -131.5t131.5 -316.5q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45q0 106 -75 181t-181 75t-181 -75t-75 -181 v-320h736z" />
<glyph unicode="&#xf140;" d="M1024 640q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM1152 640q0 159 -112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM1280 640q0 -212 -150 -362t-362 -150t-362 150 t-150 362t150 362t362 150t362 -150t150 -362zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf141;" horiz-adv-x="1408" d="M384 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM896 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM1408 800v-192q0 -40 -28 -68t-68 -28h-192 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68z" />
<glyph unicode="&#xf142;" horiz-adv-x="384" d="M384 288v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM384 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM384 1312v-192q0 -40 -28 -68t-68 -28h-192 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68z" />
<glyph unicode="&#xf143;" d="M512 256q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM863 162q-13 232 -177 396t-396 177q-14 1 -24 -9t-10 -23v-128q0 -13 8.5 -22t21.5 -10q154 -11 264 -121t121 -264q1 -13 10 -21.5t22 -8.5h128q13 0 23 10 t9 24zM1247 161q-5 154 -56 297.5t-139.5 260t-205 205t-260 139.5t-297.5 56q-14 1 -23 -9q-10 -10 -10 -23v-128q0 -13 9 -22t22 -10q204 -7 378 -111.5t278.5 -278.5t111.5 -378q1 -13 10 -22t22 -9h128q13 0 23 10q11 9 9 23zM1536 1120v-960q0 -119 -84.5 -203.5 t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf144;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1152 585q32 18 32 55t-32 55l-544 320q-31 19 -64 1q-32 -19 -32 -56v-640q0 -37 32 -56 q16 -8 32 -8q17 0 32 9z" />
<glyph unicode="&#xf145;" horiz-adv-x="1792" d="M1024 1084l316 -316l-572 -572l-316 316zM813 105l618 618q19 19 19 45t-19 45l-362 362q-18 18 -45 18t-45 -18l-618 -618q-19 -19 -19 -45t19 -45l362 -362q18 -18 45 -18t45 18zM1702 742l-907 -908q-37 -37 -90.5 -37t-90.5 37l-126 126q56 56 56 136t-56 136 t-136 56t-136 -56l-125 126q-37 37 -37 90.5t37 90.5l907 906q37 37 90.5 37t90.5 -37l125 -125q-56 -56 -56 -136t56 -136t136 -56t136 56l126 -125q37 -37 37 -90.5t-37 -90.5z" />
<glyph unicode="&#xf146;" d="M1280 576v128q0 26 -19 45t-45 19h-896q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h896q26 0 45 19t19 45zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5 t84.5 -203.5z" />
<glyph unicode="&#xf147;" horiz-adv-x="1408" d="M1152 736v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h832q14 0 23 -9t9 -23zM1280 288v832q0 66 -47 113t-113 47h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113zM1408 1120v-832q0 -119 -84.5 -203.5 t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf148;" horiz-adv-x="1024" d="M1018 933q-18 -37 -58 -37h-192v-864q0 -14 -9 -23t-23 -9h-704q-21 0 -29 18q-8 20 4 35l160 192q9 11 25 11h320v640h-192q-40 0 -58 37q-17 37 9 68l320 384q18 22 49 22t49 -22l320 -384q27 -32 9 -68z" />
<glyph unicode="&#xf149;" horiz-adv-x="1024" d="M32 1280h704q13 0 22.5 -9.5t9.5 -23.5v-863h192q40 0 58 -37t-9 -69l-320 -384q-18 -22 -49 -22t-49 22l-320 384q-26 31 -9 69q18 37 58 37h192v640h-320q-14 0 -25 11l-160 192q-13 14 -4 34q9 19 29 19z" />
<glyph unicode="&#xf14a;" d="M685 237l614 614q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-467 -467l-211 211q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l358 -358q19 -19 45 -19t45 19zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5 t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf14b;" d="M404 428l152 -152l-52 -52h-56v96h-96v56zM818 818q14 -13 -3 -30l-291 -291q-17 -17 -30 -3q-14 13 3 30l291 291q17 17 30 3zM544 128l544 544l-288 288l-544 -544v-288h288zM1152 736l92 92q28 28 28 68t-28 68l-152 152q-28 28 -68 28t-68 -28l-92 -92zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf14c;" d="M1280 608v480q0 26 -19 45t-45 19h-480q-42 0 -59 -39q-17 -41 14 -70l144 -144l-534 -534q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19l534 534l144 -144q18 -19 45 -19q12 0 25 5q39 17 39 59zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960 q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf14d;" d="M1005 435l352 352q19 19 19 45t-19 45l-352 352q-30 31 -69 14q-40 -17 -40 -59v-160q-119 0 -216 -19.5t-162.5 -51t-114 -79t-76.5 -95.5t-44.5 -109t-21.5 -111.5t-5 -110.5q0 -181 167 -404q10 -12 25 -12q7 0 13 3q22 9 19 33q-44 354 62 473q46 52 130 75.5 t224 23.5v-160q0 -42 40 -59q12 -5 24 -5q26 0 45 19zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf14e;" d="M640 448l256 128l-256 128v-256zM1024 1039v-542l-512 -256v542zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf150;" d="M1145 861q18 -35 -5 -66l-320 -448q-19 -27 -52 -27t-52 27l-320 448q-23 31 -5 66q17 35 57 35h640q40 0 57 -35zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf151;" d="M1145 419q-17 -35 -57 -35h-640q-40 0 -57 35q-18 35 5 66l320 448q19 27 52 27t52 -27l320 -448q23 -31 5 -66zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf152;" d="M1088 640q0 -33 -27 -52l-448 -320q-31 -23 -66 -5q-35 17 -35 57v640q0 40 35 57q35 18 66 -5l448 -320q27 -19 27 -52zM1280 160v960q0 14 -9 23t-23 9h-960q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h960q14 0 23 9t9 23zM1536 1120v-960q0 -119 -84.5 -203.5 t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf153;" horiz-adv-x="1024" d="M976 229l35 -159q3 -12 -3 -22.5t-17 -14.5l-5 -1q-4 -2 -10.5 -3.5t-16 -4.5t-21.5 -5.5t-25.5 -5t-30 -5t-33.5 -4.5t-36.5 -3t-38.5 -1q-234 0 -409 130.5t-238 351.5h-95q-13 0 -22.5 9.5t-9.5 22.5v113q0 13 9.5 22.5t22.5 9.5h66q-2 57 1 105h-67q-14 0 -23 9 t-9 23v114q0 14 9 23t23 9h98q67 210 243.5 338t400.5 128q102 0 194 -23q11 -3 20 -15q6 -11 3 -24l-43 -159q-3 -13 -14 -19.5t-24 -2.5l-4 1q-4 1 -11.5 2.5l-17.5 3.5t-22.5 3.5t-26 3t-29 2.5t-29.5 1q-126 0 -226 -64t-150 -176h468q16 0 25 -12q10 -12 7 -26 l-24 -114q-5 -26 -32 -26h-488q-3 -37 0 -105h459q15 0 25 -12q9 -12 6 -27l-24 -112q-2 -11 -11 -18.5t-20 -7.5h-387q48 -117 149.5 -185.5t228.5 -68.5q18 0 36 1.5t33.5 3.5t29.5 4.5t24.5 5t18.5 4.5l12 3l5 2q13 5 26 -2q12 -7 15 -21z" />
<glyph unicode="&#xf154;" horiz-adv-x="1024" d="M1020 399v-367q0 -14 -9 -23t-23 -9h-956q-14 0 -23 9t-9 23v150q0 13 9.5 22.5t22.5 9.5h97v383h-95q-14 0 -23 9.5t-9 22.5v131q0 14 9 23t23 9h95v223q0 171 123.5 282t314.5 111q185 0 335 -125q9 -8 10 -20.5t-7 -22.5l-103 -127q-9 -11 -22 -12q-13 -2 -23 7 q-5 5 -26 19t-69 32t-93 18q-85 0 -137 -47t-52 -123v-215h305q13 0 22.5 -9t9.5 -23v-131q0 -13 -9.5 -22.5t-22.5 -9.5h-305v-379h414v181q0 13 9 22.5t23 9.5h162q14 0 23 -9.5t9 -22.5z" />
<glyph unicode="&#xf155;" horiz-adv-x="1024" d="M978 351q0 -153 -99.5 -263.5t-258.5 -136.5v-175q0 -14 -9 -23t-23 -9h-135q-13 0 -22.5 9.5t-9.5 22.5v175q-66 9 -127.5 31t-101.5 44.5t-74 48t-46.5 37.5t-17.5 18q-17 21 -2 41l103 135q7 10 23 12q15 2 24 -9l2 -2q113 -99 243 -125q37 -8 74 -8q81 0 142.5 43 t61.5 122q0 28 -15 53t-33.5 42t-58.5 37.5t-66 32t-80 32.5q-39 16 -61.5 25t-61.5 26.5t-62.5 31t-56.5 35.5t-53.5 42.5t-43.5 49t-35.5 58t-21 66.5t-8.5 78q0 138 98 242t255 134v180q0 13 9.5 22.5t22.5 9.5h135q14 0 23 -9t9 -23v-176q57 -6 110.5 -23t87 -33.5 t63.5 -37.5t39 -29t15 -14q17 -18 5 -38l-81 -146q-8 -15 -23 -16q-14 -3 -27 7q-3 3 -14.5 12t-39 26.5t-58.5 32t-74.5 26t-85.5 11.5q-95 0 -155 -43t-60 -111q0 -26 8.5 -48t29.5 -41.5t39.5 -33t56 -31t60.5 -27t70 -27.5q53 -20 81 -31.5t76 -35t75.5 -42.5t62 -50 t53 -63.5t31.5 -76.5t13 -94z" />
<glyph unicode="&#xf156;" horiz-adv-x="898" d="M898 1066v-102q0 -14 -9 -23t-23 -9h-168q-23 -144 -129 -234t-276 -110q167 -178 459 -536q14 -16 4 -34q-8 -18 -29 -18h-195q-16 0 -25 12q-306 367 -498 571q-9 9 -9 22v127q0 13 9.5 22.5t22.5 9.5h112q132 0 212.5 43t102.5 125h-427q-14 0 -23 9t-9 23v102 q0 14 9 23t23 9h413q-57 113 -268 113h-145q-13 0 -22.5 9.5t-9.5 22.5v133q0 14 9 23t23 9h832q14 0 23 -9t9 -23v-102q0 -14 -9 -23t-23 -9h-233q47 -61 64 -144h171q14 0 23 -9t9 -23z" />
<glyph unicode="&#xf157;" horiz-adv-x="1027" d="M603 0h-172q-13 0 -22.5 9t-9.5 23v330h-288q-13 0 -22.5 9t-9.5 23v103q0 13 9.5 22.5t22.5 9.5h288v85h-288q-13 0 -22.5 9t-9.5 23v104q0 13 9.5 22.5t22.5 9.5h214l-321 578q-8 16 0 32q10 16 28 16h194q19 0 29 -18l215 -425q19 -38 56 -125q10 24 30.5 68t27.5 61 l191 420q8 19 29 19h191q17 0 27 -16q9 -14 1 -31l-313 -579h215q13 0 22.5 -9.5t9.5 -22.5v-104q0 -14 -9.5 -23t-22.5 -9h-290v-85h290q13 0 22.5 -9.5t9.5 -22.5v-103q0 -14 -9.5 -23t-22.5 -9h-290v-330q0 -13 -9.5 -22.5t-22.5 -9.5z" />
<glyph unicode="&#xf158;" horiz-adv-x="1280" d="M1043 971q0 100 -65 162t-171 62h-320v-448h320q106 0 171 62t65 162zM1280 971q0 -193 -126.5 -315t-326.5 -122h-340v-118h505q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9h-505v-192q0 -14 -9.5 -23t-22.5 -9h-167q-14 0 -23 9t-9 23v192h-224q-14 0 -23 9t-9 23v128 q0 14 9 23t23 9h224v118h-224q-14 0 -23 9t-9 23v149q0 13 9 22.5t23 9.5h224v629q0 14 9 23t23 9h539q200 0 326.5 -122t126.5 -315z" />
<glyph unicode="&#xf159;" horiz-adv-x="1792" d="M514 341l81 299h-159l75 -300q1 -1 1 -3t1 -3q0 1 0.5 3.5t0.5 3.5zM630 768l35 128h-292l32 -128h225zM822 768h139l-35 128h-70zM1271 340l78 300h-162l81 -299q0 -1 0.5 -3.5t1.5 -3.5q0 1 0.5 3t0.5 3zM1382 768l33 128h-297l34 -128h230zM1792 736v-64q0 -14 -9 -23 t-23 -9h-213l-164 -616q-7 -24 -31 -24h-159q-24 0 -31 24l-166 616h-209l-167 -616q-7 -24 -31 -24h-159q-11 0 -19.5 7t-10.5 17l-160 616h-208q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h175l-33 128h-142q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h109l-89 344q-5 15 5 28 q10 12 26 12h137q26 0 31 -24l90 -360h359l97 360q7 24 31 24h126q24 0 31 -24l98 -360h365l93 360q5 24 31 24h137q16 0 26 -12q10 -13 5 -28l-91 -344h111q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-145l-34 -128h179q14 0 23 -9t9 -23z" />
<glyph unicode="&#xf15a;" horiz-adv-x="1280" d="M1167 896q18 -182 -131 -258q117 -28 175 -103t45 -214q-7 -71 -32.5 -125t-64.5 -89t-97 -58.5t-121.5 -34.5t-145.5 -15v-255h-154v251q-80 0 -122 1v-252h-154v255q-18 0 -54 0.5t-55 0.5h-200l31 183h111q50 0 58 51v402h16q-6 1 -16 1v287q-13 68 -89 68h-111v164 l212 -1q64 0 97 1v252h154v-247q82 2 122 2v245h154v-252q79 -7 140 -22.5t113 -45t82.5 -78t36.5 -114.5zM952 351q0 36 -15 64t-37 46t-57.5 30.5t-65.5 18.5t-74 9t-69 3t-64.5 -1t-47.5 -1v-338q8 0 37 -0.5t48 -0.5t53 1.5t58.5 4t57 8.5t55.5 14t47.5 21t39.5 30 t24.5 40t9.5 51zM881 827q0 33 -12.5 58.5t-30.5 42t-48 28t-55 16.5t-61.5 8t-58 2.5t-54 -1t-39.5 -0.5v-307q5 0 34.5 -0.5t46.5 0t50 2t55 5.5t51.5 11t48.5 18.5t37 27t27 38.5t9 51z" />
<glyph unicode="&#xf15b;" horiz-adv-x="1280" d="M1280 768v-800q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h544v-544q0 -40 28 -68t68 -28h544zM1277 896h-509v509q82 -15 132 -65l312 -312q50 -50 65 -132z" />
<glyph unicode="&#xf15c;" horiz-adv-x="1280" d="M1024 160v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23zM1024 416v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23zM1280 768v-800q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28 t-28 68v1344q0 40 28 68t68 28h544v-544q0 -40 28 -68t68 -28h544zM1277 896h-509v509q82 -15 132 -65l312 -312q50 -50 65 -132z" />
<glyph unicode="&#xf15d;" horiz-adv-x="1664" d="M1191 1128h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1572 -23 v-233h-584v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -11v-2l14 2q9 2 30 2h248v119h121zM1661 874v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287v106h70l230 662h162 l230 -662h70z" />
<glyph unicode="&#xf15e;" horiz-adv-x="1664" d="M1191 104h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1661 -150 v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287v106h70l230 662h162l230 -662h70zM1572 1001v-233h-584v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -10v-3l14 3q9 1 30 1h248 v119h121z" />
<glyph unicode="&#xf160;" horiz-adv-x="1792" d="M736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1792 -32v-192q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h832 q14 0 23 -9t9 -23zM1600 480v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23zM1408 992v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23zM1216 1504v-192q0 -14 -9 -23t-23 -9h-256 q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h256q14 0 23 -9t9 -23z" />
<glyph unicode="&#xf161;" horiz-adv-x="1792" d="M1216 -32v-192q0 -14 -9 -23t-23 -9h-256q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h256q14 0 23 -9t9 -23zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192 q14 0 23 -9t9 -23zM1408 480v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23zM1600 992v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23zM1792 1504v-192q0 -14 -9 -23t-23 -9h-832 q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h832q14 0 23 -9t9 -23z" />
<glyph unicode="&#xf162;" d="M1346 223q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94t36.5 -95t104.5 -38q50 0 85 27t35 68zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23 zM1486 165q0 -62 -13 -121.5t-41 -114t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 172.5q0 105 72 178t181 73q123 0 205 -94.5 t82 -252.5zM1456 882v-114h-469v114h167v432q0 7 0.5 19t0.5 17v16h-2l-7 -12q-8 -13 -26 -31l-62 -58l-82 86l192 185h123v-654h165z" />
<glyph unicode="&#xf163;" d="M1346 1247q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94t36.5 -95t104.5 -38q50 0 85 27t35 68zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9 t9 -23zM1456 -142v-114h-469v114h167v432q0 7 0.5 19t0.5 17v16h-2l-7 -12q-8 -13 -26 -31l-62 -58l-82 86l192 185h123v-654h165zM1486 1189q0 -62 -13 -121.5t-41 -114t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13 q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 172.5q0 105 72 178t181 73q123 0 205 -94.5t82 -252.5z" />
<glyph unicode="&#xf164;" horiz-adv-x="1664" d="M256 192q0 26 -19 45t-45 19q-27 0 -45.5 -19t-18.5 -45q0 -27 18.5 -45.5t45.5 -18.5q26 0 45 18.5t19 45.5zM416 704v-640q0 -26 -19 -45t-45 -19h-288q-26 0 -45 19t-19 45v640q0 26 19 45t45 19h288q26 0 45 -19t19 -45zM1600 704q0 -86 -55 -149q15 -44 15 -76 q3 -76 -43 -137q17 -56 0 -117q-15 -57 -54 -94q9 -112 -49 -181q-64 -76 -197 -78h-36h-76h-17q-66 0 -144 15.5t-121.5 29t-120.5 39.5q-123 43 -158 44q-26 1 -45 19.5t-19 44.5v641q0 25 18 43.5t43 20.5q24 2 76 59t101 121q68 87 101 120q18 18 31 48t17.5 48.5 t13.5 60.5q7 39 12.5 61t19.5 52t34 50q19 19 45 19q46 0 82.5 -10.5t60 -26t40 -40.5t24 -45t12 -50t5 -45t0.5 -39q0 -38 -9.5 -76t-19 -60t-27.5 -56q-3 -6 -10 -18t-11 -22t-8 -24h277q78 0 135 -57t57 -135z" />
<glyph unicode="&#xf165;" horiz-adv-x="1664" d="M256 960q0 -26 -19 -45t-45 -19q-27 0 -45.5 19t-18.5 45q0 27 18.5 45.5t45.5 18.5q26 0 45 -18.5t19 -45.5zM416 448v640q0 26 -19 45t-45 19h-288q-26 0 -45 -19t-19 -45v-640q0 -26 19 -45t45 -19h288q26 0 45 19t19 45zM1545 597q55 -61 55 -149q-1 -78 -57.5 -135 t-134.5 -57h-277q4 -14 8 -24t11 -22t10 -18q18 -37 27 -57t19 -58.5t10 -76.5q0 -24 -0.5 -39t-5 -45t-12 -50t-24 -45t-40 -40.5t-60 -26t-82.5 -10.5q-26 0 -45 19q-20 20 -34 50t-19.5 52t-12.5 61q-9 42 -13.5 60.5t-17.5 48.5t-31 48q-33 33 -101 120q-49 64 -101 121 t-76 59q-25 2 -43 20.5t-18 43.5v641q0 26 19 44.5t45 19.5q35 1 158 44q77 26 120.5 39.5t121.5 29t144 15.5h17h76h36q133 -2 197 -78q58 -69 49 -181q39 -37 54 -94q17 -61 0 -117q46 -61 43 -137q0 -32 -15 -76z" />
<glyph unicode="&#xf166;" d="M919 233v157q0 50 -29 50q-17 0 -33 -16v-224q16 -16 33 -16q29 0 29 49zM1103 355h66v34q0 51 -33 51t-33 -51v-34zM532 621v-70h-80v-423h-74v423h-78v70h232zM733 495v-367h-67v40q-39 -45 -76 -45q-33 0 -42 28q-6 16 -6 54v290h66v-270q0 -24 1 -26q1 -15 15 -15 q20 0 42 31v280h67zM985 384v-146q0 -52 -7 -73q-12 -42 -53 -42q-35 0 -68 41v-36h-67v493h67v-161q32 40 68 40q41 0 53 -42q7 -21 7 -74zM1236 255v-9q0 -29 -2 -43q-3 -22 -15 -40q-27 -40 -80 -40q-52 0 -81 38q-21 27 -21 86v129q0 59 20 86q29 38 80 38t78 -38 q21 -28 21 -86v-76h-133v-65q0 -51 34 -51q24 0 30 26q0 1 0.5 7t0.5 16.5v21.5h68zM785 1079v-156q0 -51 -32 -51t-32 51v156q0 52 32 52t32 -52zM1318 366q0 177 -19 260q-10 44 -43 73.5t-76 34.5q-136 15 -412 15q-275 0 -411 -15q-44 -5 -76.5 -34.5t-42.5 -73.5 q-20 -87 -20 -260q0 -176 20 -260q10 -43 42.5 -73t75.5 -35q137 -15 412 -15t412 15q43 5 75.5 35t42.5 73q20 84 20 260zM563 1017l90 296h-75l-51 -195l-53 195h-78l24 -69t23 -69q35 -103 46 -158v-201h74v201zM852 936v130q0 58 -21 87q-29 38 -78 38q-51 0 -78 -38 q-21 -29 -21 -87v-130q0 -58 21 -87q27 -38 78 -38q49 0 78 38q21 27 21 87zM1033 816h67v370h-67v-283q-22 -31 -42 -31q-15 0 -16 16q-1 2 -1 26v272h-67v-293q0 -37 6 -55q11 -27 43 -27q36 0 77 45v-40zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960 q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf167;" d="M971 292v-211q0 -67 -39 -67q-23 0 -45 22v301q22 22 45 22q39 0 39 -67zM1309 291v-46h-90v46q0 68 45 68t45 -68zM343 509h107v94h-312v-94h105v-569h100v569zM631 -60h89v494h-89v-378q-30 -42 -57 -42q-18 0 -21 21q-1 3 -1 35v364h-89v-391q0 -49 8 -73 q12 -37 58 -37q48 0 102 61v-54zM1060 88v197q0 73 -9 99q-17 56 -71 56q-50 0 -93 -54v217h-89v-663h89v48q45 -55 93 -55q54 0 71 55q9 27 9 100zM1398 98v13h-91q0 -51 -2 -61q-7 -36 -40 -36q-46 0 -46 69v87h179v103q0 79 -27 116q-39 51 -106 51q-68 0 -107 -51 q-28 -37 -28 -116v-173q0 -79 29 -116q39 -51 108 -51q72 0 108 53q18 27 21 54q2 9 2 58zM790 1011v210q0 69 -43 69t-43 -69v-210q0 -70 43 -70t43 70zM1509 260q0 -234 -26 -350q-14 -59 -58 -99t-102 -46q-184 -21 -555 -21t-555 21q-58 6 -102.5 46t-57.5 99 q-26 112 -26 350q0 234 26 350q14 59 58 99t103 47q183 20 554 20t555 -20q58 -7 102.5 -47t57.5 -99q26 -112 26 -350zM511 1536h102l-121 -399v-271h-100v271q-14 74 -61 212q-37 103 -65 187h106l71 -263zM881 1203v-175q0 -81 -28 -118q-37 -51 -106 -51q-67 0 -105 51 q-28 38 -28 118v175q0 80 28 117q38 51 105 51q69 0 106 -51q28 -37 28 -117zM1216 1365v-499h-91v55q-53 -62 -103 -62q-46 0 -59 37q-8 24 -8 75v394h91v-367q0 -33 1 -35q3 -22 21 -22q27 0 57 43v381h91z" />
<glyph unicode="&#xf168;" horiz-adv-x="1408" d="M597 869q-10 -18 -257 -456q-27 -46 -65 -46h-239q-21 0 -31 17t0 36l253 448q1 0 0 1l-161 279q-12 22 -1 37q9 15 32 15h239q40 0 66 -45zM1403 1511q11 -16 0 -37l-528 -934v-1l336 -615q11 -20 1 -37q-10 -15 -32 -15h-239q-42 0 -66 45l-339 622q18 32 531 942 q25 45 64 45h241q22 0 31 -15z" />
<glyph unicode="&#xf169;" d="M685 771q0 1 -126 222q-21 34 -52 34h-184q-18 0 -26 -11q-7 -12 1 -29l125 -216v-1l-196 -346q-9 -14 0 -28q8 -13 24 -13h185q31 0 50 36zM1309 1268q-7 12 -24 12h-187q-30 0 -49 -35l-411 -729q1 -2 262 -481q20 -35 52 -35h184q18 0 25 12q8 13 -1 28l-260 476v1 l409 723q8 16 0 28zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf16a;" horiz-adv-x="1792" d="M1280 640q0 37 -30 54l-512 320q-31 20 -65 2q-33 -18 -33 -56v-640q0 -38 33 -56q16 -8 31 -8q20 0 34 10l512 320q30 17 30 54zM1792 640q0 -96 -1 -150t-8.5 -136.5t-22.5 -147.5q-16 -73 -69 -123t-124 -58q-222 -25 -671 -25t-671 25q-71 8 -124.5 58t-69.5 123 q-14 65 -21.5 147.5t-8.5 136.5t-1 150t1 150t8.5 136.5t22.5 147.5q16 73 69 123t124 58q222 25 671 25t671 -25q71 -8 124.5 -58t69.5 -123q14 -65 21.5 -147.5t8.5 -136.5t1 -150z" />
<glyph unicode="&#xf16b;" horiz-adv-x="1792" d="M402 829l494 -305l-342 -285l-490 319zM1388 274v-108l-490 -293v-1l-1 1l-1 -1v1l-489 293v108l147 -96l342 284v2l1 -1l1 1v-2l343 -284zM554 1418l342 -285l-494 -304l-338 270zM1390 829l338 -271l-489 -319l-343 285zM1239 1418l489 -319l-338 -270l-494 304z" />
<glyph unicode="&#xf16c;" horiz-adv-x="1408" d="M928 135v-151l-707 -1v151zM1169 481v-701l-1 -35v-1h-1132l-35 1h-1v736h121v-618h928v618h120zM241 393l704 -65l-13 -150l-705 65zM309 709l683 -183l-39 -146l-683 183zM472 1058l609 -360l-77 -130l-609 360zM832 1389l398 -585l-124 -85l-399 584zM1285 1536 l121 -697l-149 -26l-121 697z" />
<glyph unicode="&#xf16d;" d="M1362 110v648h-135q20 -63 20 -131q0 -126 -64 -232.5t-174 -168.5t-240 -62q-197 0 -337 135.5t-140 327.5q0 68 20 131h-141v-648q0 -26 17.5 -43.5t43.5 -17.5h1069q25 0 43 17.5t18 43.5zM1078 643q0 124 -90.5 211.5t-218.5 87.5q-127 0 -217.5 -87.5t-90.5 -211.5 t90.5 -211.5t217.5 -87.5q128 0 218.5 87.5t90.5 211.5zM1362 1003v165q0 28 -20 48.5t-49 20.5h-174q-29 0 -49 -20.5t-20 -48.5v-165q0 -29 20 -49t49 -20h174q29 0 49 20t20 49zM1536 1211v-1142q0 -81 -58 -139t-139 -58h-1142q-81 0 -139 58t-58 139v1142q0 81 58 139 t139 58h1142q81 0 139 -58t58 -139z" />
<glyph unicode="&#xf16e;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM698 640q0 88 -62 150t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150zM1262 640q0 88 -62 150 t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150z" />
<glyph unicode="&#xf170;" d="M768 914l201 -306h-402zM1133 384h94l-459 691l-459 -691h94l104 160h522zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf171;" horiz-adv-x="1408" d="M815 677q8 -63 -50.5 -101t-111.5 -6q-39 17 -53.5 58t-0.5 82t52 58q36 18 72.5 12t64 -35.5t27.5 -67.5zM926 698q-14 107 -113 164t-197 13q-63 -28 -100.5 -88.5t-34.5 -129.5q4 -91 77.5 -155t165.5 -56q91 8 152 84t50 168zM1165 1240q-20 27 -56 44.5t-58 22 t-71 12.5q-291 47 -566 -2q-43 -7 -66 -12t-55 -22t-50 -43q30 -28 76 -45.5t73.5 -22t87.5 -11.5q228 -29 448 -1q63 8 89.5 12t72.5 21.5t75 46.5zM1222 205q-8 -26 -15.5 -76.5t-14 -84t-28.5 -70t-58 -56.5q-86 -48 -189.5 -71.5t-202 -22t-201.5 18.5q-46 8 -81.5 18 t-76.5 27t-73 43.5t-52 61.5q-25 96 -57 292l6 16l18 9q223 -148 506.5 -148t507.5 148q21 -6 24 -23t-5 -45t-8 -37zM1403 1166q-26 -167 -111 -655q-5 -30 -27 -56t-43.5 -40t-54.5 -31q-252 -126 -610 -88q-248 27 -394 139q-15 12 -25.5 26.5t-17 35t-9 34t-6 39.5 t-5.5 35q-9 50 -26.5 150t-28 161.5t-23.5 147.5t-22 158q3 26 17.5 48.5t31.5 37.5t45 30t46 22.5t48 18.5q125 46 313 64q379 37 676 -50q155 -46 215 -122q16 -20 16.5 -51t-5.5 -54z" />
<glyph unicode="&#xf172;" d="M848 666q0 43 -41 66t-77 1q-43 -20 -42.5 -72.5t43.5 -70.5q39 -23 81 4t36 72zM928 682q8 -66 -36 -121t-110 -61t-119 40t-56 113q-2 49 25.5 93t72.5 64q70 31 141.5 -10t81.5 -118zM1100 1073q-20 -21 -53.5 -34t-53 -16t-63.5 -8q-155 -20 -324 0q-44 6 -63 9.5 t-52.5 16t-54.5 32.5q13 19 36 31t40 15.5t47 8.5q198 35 408 1q33 -5 51 -8.5t43 -16t39 -31.5zM1142 327q0 7 5.5 26.5t3 32t-17.5 16.5q-161 -106 -365 -106t-366 106l-12 -6l-5 -12q26 -154 41 -210q47 -81 204 -108q249 -46 428 53q34 19 49 51.5t22.5 85.5t12.5 71z M1272 1020q9 53 -8 75q-43 55 -155 88q-216 63 -487 36q-132 -12 -226 -46q-38 -15 -59.5 -25t-47 -34t-29.5 -54q8 -68 19 -138t29 -171t24 -137q1 -5 5 -31t7 -36t12 -27t22 -28q105 -80 284 -100q259 -28 440 63q24 13 39.5 23t31 29t19.5 40q48 267 80 473zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf173;" horiz-adv-x="1024" d="M390 1408h219v-388h364v-241h-364v-394q0 -136 14 -172q13 -37 52 -60q50 -31 117 -31q117 0 232 76v-242q-102 -48 -178 -65q-77 -19 -173 -19q-105 0 -186 27q-78 25 -138 75q-58 51 -79 105q-22 54 -22 161v539h-170v217q91 30 155 84q64 55 103 132q39 78 54 196z " />
<glyph unicode="&#xf174;" d="M1123 127v181q-88 -56 -174 -56q-51 0 -88 23q-29 17 -39 45q-11 30 -11 129v295h274v181h-274v291h-164q-11 -90 -40 -147t-78 -99q-48 -40 -116 -63v-163h127v-404q0 -78 17 -121q17 -42 59 -78q43 -37 104 -57q62 -20 140 -20q67 0 129 14q57 13 134 49zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf175;" horiz-adv-x="768" d="M765 237q8 -19 -5 -35l-350 -384q-10 -10 -23 -10q-14 0 -24 10l-355 384q-13 16 -5 35q9 19 29 19h224v1248q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1248h224q21 0 29 -19z" />
<glyph unicode="&#xf176;" horiz-adv-x="768" d="M765 1043q-9 -19 -29 -19h-224v-1248q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1248h-224q-21 0 -29 19t5 35l350 384q10 10 23 10q14 0 24 -10l355 -384q13 -16 5 -35z" />
<glyph unicode="&#xf177;" horiz-adv-x="1792" d="M1792 736v-192q0 -14 -9 -23t-23 -9h-1248v-224q0 -21 -19 -29t-35 5l-384 350q-10 10 -10 23q0 14 10 24l384 354q16 14 35 6q19 -9 19 -29v-224h1248q14 0 23 -9t9 -23z" />
<glyph unicode="&#xf178;" horiz-adv-x="1792" d="M1728 643q0 -14 -10 -24l-384 -354q-16 -14 -35 -6q-19 9 -19 29v224h-1248q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h1248v224q0 21 19 29t35 -5l384 -350q10 -10 10 -23z" />
<glyph unicode="&#xf179;" horiz-adv-x="1408" d="M1393 321q-39 -125 -123 -250q-129 -196 -257 -196q-49 0 -140 32q-86 32 -151 32q-61 0 -142 -33q-81 -34 -132 -34q-152 0 -301 259q-147 261 -147 503q0 228 113 374q112 144 284 144q72 0 177 -30q104 -30 138 -30q45 0 143 34q102 34 173 34q119 0 213 -65 q52 -36 104 -100q-79 -67 -114 -118q-65 -94 -65 -207q0 -124 69 -223t158 -126zM1017 1494q0 -61 -29 -136q-30 -75 -93 -138q-54 -54 -108 -72q-37 -11 -104 -17q3 149 78 257q74 107 250 148q1 -3 2.5 -11t2.5 -11q0 -4 0.5 -10t0.5 -10z" />
<glyph unicode="&#xf17a;" horiz-adv-x="1664" d="M682 530v-651l-682 94v557h682zM682 1273v-659h-682v565zM1664 530v-786l-907 125v661h907zM1664 1408v-794h-907v669z" />
<glyph unicode="&#xf17b;" horiz-adv-x="1408" d="M493 1053q16 0 27.5 11.5t11.5 27.5t-11.5 27.5t-27.5 11.5t-27 -11.5t-11 -27.5t11 -27.5t27 -11.5zM915 1053q16 0 27 11.5t11 27.5t-11 27.5t-27 11.5t-27.5 -11.5t-11.5 -27.5t11.5 -27.5t27.5 -11.5zM103 869q42 0 72 -30t30 -72v-430q0 -43 -29.5 -73t-72.5 -30 t-73 30t-30 73v430q0 42 30 72t73 30zM1163 850v-666q0 -46 -32 -78t-77 -32h-75v-227q0 -43 -30 -73t-73 -30t-73 30t-30 73v227h-138v-227q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73l-1 227h-74q-46 0 -78 32t-32 78v666h918zM931 1255q107 -55 171 -153.5t64 -215.5 h-925q0 117 64 215.5t172 153.5l-71 131q-7 13 5 20q13 6 20 -6l72 -132q95 42 201 42t201 -42l72 132q7 12 20 6q12 -7 5 -20zM1408 767v-430q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73v430q0 43 30 72.5t72 29.5q43 0 73 -29.5t30 -72.5z" />
<glyph unicode="&#xf17c;" d="M663 1125q-11 -1 -15.5 -10.5t-8.5 -9.5q-5 -1 -5 5q0 12 19 15h10zM750 1111q-4 -1 -11.5 6.5t-17.5 4.5q24 11 32 -2q3 -6 -3 -9zM399 684q-4 1 -6 -3t-4.5 -12.5t-5.5 -13.5t-10 -13q-7 -10 -1 -12q4 -1 12.5 7t12.5 18q1 3 2 7t2 6t1.5 4.5t0.5 4v3t-1 2.5t-3 2z M1254 325q0 18 -55 42q4 15 7.5 27.5t5 26t3 21.5t0.5 22.5t-1 19.5t-3.5 22t-4 20.5t-5 25t-5.5 26.5q-10 48 -47 103t-72 75q24 -20 57 -83q87 -162 54 -278q-11 -40 -50 -42q-31 -4 -38.5 18.5t-8 83.5t-11.5 107q-9 39 -19.5 69t-19.5 45.5t-15.5 24.5t-13 15t-7.5 7 q-14 62 -31 103t-29.5 56t-23.5 33t-15 40q-4 21 6 53.5t4.5 49.5t-44.5 25q-15 3 -44.5 18t-35.5 16q-8 1 -11 26t8 51t36 27q37 3 51 -30t4 -58q-11 -19 -2 -26.5t30 -0.5q13 4 13 36v37q-5 30 -13.5 50t-21 30.5t-23.5 15t-27 7.5q-107 -8 -89 -134q0 -15 -1 -15 q-9 9 -29.5 10.5t-33 -0.5t-15.5 5q1 57 -16 90t-45 34q-27 1 -41.5 -27.5t-16.5 -59.5q-1 -15 3.5 -37t13 -37.5t15.5 -13.5q10 3 16 14q4 9 -7 8q-7 0 -15.5 14.5t-9.5 33.5q-1 22 9 37t34 14q17 0 27 -21t9.5 -39t-1.5 -22q-22 -15 -31 -29q-8 -12 -27.5 -23.5 t-20.5 -12.5q-13 -14 -15.5 -27t7.5 -18q14 -8 25 -19.5t16 -19t18.5 -13t35.5 -6.5q47 -2 102 15q2 1 23 7t34.5 10.5t29.5 13t21 17.5q9 14 20 8q5 -3 6.5 -8.5t-3 -12t-16.5 -9.5q-20 -6 -56.5 -21.5t-45.5 -19.5q-44 -19 -70 -23q-25 -5 -79 2q-10 2 -9 -2t17 -19 q25 -23 67 -22q17 1 36 7t36 14t33.5 17.5t30 17t24.5 12t17.5 2.5t8.5 -11q0 -2 -1 -4.5t-4 -5t-6 -4.5t-8.5 -5t-9 -4.5t-10 -5t-9.5 -4.5q-28 -14 -67.5 -44t-66.5 -43t-49 -1q-21 11 -63 73q-22 31 -25 22q-1 -3 -1 -10q0 -25 -15 -56.5t-29.5 -55.5t-21 -58t11.5 -63 q-23 -6 -62.5 -90t-47.5 -141q-2 -18 -1.5 -69t-5.5 -59q-8 -24 -29 -3q-32 31 -36 94q-2 28 4 56q4 19 -1 18l-4 -5q-36 -65 10 -166q5 -12 25 -28t24 -20q20 -23 104 -90.5t93 -76.5q16 -15 17.5 -38t-14 -43t-45.5 -23q8 -15 29 -44.5t28 -54t7 -70.5q46 24 7 92 q-4 8 -10.5 16t-9.5 12t-2 6q3 5 13 9.5t20 -2.5q46 -52 166 -36q133 15 177 87q23 38 34 30q12 -6 10 -52q-1 -25 -23 -92q-9 -23 -6 -37.5t24 -15.5q3 19 14.5 77t13.5 90q2 21 -6.5 73.5t-7.5 97t23 70.5q15 18 51 18q1 37 34.5 53t72.5 10.5t60 -22.5zM626 1152 q3 17 -2.5 30t-11.5 15q-9 2 -9 -7q2 -5 5 -6q10 0 7 -15q-3 -20 8 -20q3 0 3 3zM1045 955q-2 8 -6.5 11.5t-13 5t-14.5 5.5q-5 3 -9.5 8t-7 8t-5.5 6.5t-4 4t-4 -1.5q-14 -16 7 -43.5t39 -31.5q9 -1 14.5 8t3.5 20zM867 1168q0 11 -5 19.5t-11 12.5t-9 3q-14 -1 -7 -7l4 -2 q14 -4 18 -31q0 -3 8 2zM921 1401q0 2 -2.5 5t-9 7t-9.5 6q-15 15 -24 15q-9 -1 -11.5 -7.5t-1 -13t-0.5 -12.5q-1 -4 -6 -10.5t-6 -9t3 -8.5q4 -3 8 0t11 9t15 9q1 1 9 1t15 2t9 7zM1486 60q20 -12 31 -24.5t12 -24t-2.5 -22.5t-15.5 -22t-23.5 -19.5t-30 -18.5 t-31.5 -16.5t-32 -15.5t-27 -13q-38 -19 -85.5 -56t-75.5 -64q-17 -16 -68 -19.5t-89 14.5q-18 9 -29.5 23.5t-16.5 25.5t-22 19.5t-47 9.5q-44 1 -130 1q-19 0 -57 -1.5t-58 -2.5q-44 -1 -79.5 -15t-53.5 -30t-43.5 -28.5t-53.5 -11.5q-29 1 -111 31t-146 43q-19 4 -51 9.5 t-50 9t-39.5 9.5t-33.5 14.5t-17 19.5q-10 23 7 66.5t18 54.5q1 16 -4 40t-10 42.5t-4.5 36.5t10.5 27q14 12 57 14t60 12q30 18 42 35t12 51q21 -73 -32 -106q-32 -20 -83 -15q-34 3 -43 -10q-13 -15 5 -57q2 -6 8 -18t8.5 -18t4.5 -17t1 -22q0 -15 -17 -49t-14 -48 q3 -17 37 -26q20 -6 84.5 -18.5t99.5 -20.5q24 -6 74 -22t82.5 -23t55.5 -4q43 6 64.5 28t23 48t-7.5 58.5t-19 52t-20 36.5q-121 190 -169 242q-68 74 -113 40q-11 -9 -15 15q-3 16 -2 38q1 29 10 52t24 47t22 42q8 21 26.5 72t29.5 78t30 61t39 54q110 143 124 195 q-12 112 -16 310q-2 90 24 151.5t106 104.5q39 21 104 21q53 1 106 -13.5t89 -41.5q57 -42 91.5 -121.5t29.5 -147.5q-5 -95 30 -214q34 -113 133 -218q55 -59 99.5 -163t59.5 -191q8 -49 5 -84.5t-12 -55.5t-20 -22q-10 -2 -23.5 -19t-27 -35.5t-40.5 -33.5t-61 -14 q-18 1 -31.5 5t-22.5 13.5t-13.5 15.5t-11.5 20.5t-9 19.5q-22 37 -41 30t-28 -49t7 -97q20 -70 1 -195q-10 -65 18 -100.5t73 -33t85 35.5q59 49 89.5 66.5t103.5 42.5q53 18 77 36.5t18.5 34.5t-25 28.5t-51.5 23.5q-33 11 -49.5 48t-15 72.5t15.5 47.5q1 -31 8 -56.5 t14.5 -40.5t20.5 -28.5t21 -19t21.5 -13t16.5 -9.5z" />
<glyph unicode="&#xf17d;" d="M1024 36q-42 241 -140 498h-2l-2 -1q-16 -6 -43 -16.5t-101 -49t-137 -82t-131 -114.5t-103 -148l-15 11q184 -150 418 -150q132 0 256 52zM839 643q-21 49 -53 111q-311 -93 -673 -93q-1 -7 -1 -21q0 -124 44 -236.5t124 -201.5q50 89 123.5 166.5t142.5 124.5t130.5 81 t99.5 48l37 13q4 1 13 3.5t13 4.5zM732 855q-120 213 -244 378q-138 -65 -234 -186t-128 -272q302 0 606 80zM1416 536q-210 60 -409 29q87 -239 128 -469q111 75 185 189.5t96 250.5zM611 1277q-1 0 -2 -1q1 1 2 1zM1201 1132q-185 164 -433 164q-76 0 -155 -19 q131 -170 246 -382q69 26 130 60.5t96.5 61.5t65.5 57t37.5 40.5zM1424 647q-3 232 -149 410l-1 -1q-9 -12 -19 -24.5t-43.5 -44.5t-71 -60.5t-100 -65t-131.5 -64.5q25 -53 44 -95q2 -6 6.5 -17.5t7.5 -16.5q36 5 74.5 7t73.5 2t69 -1.5t64 -4t56.5 -5.5t48 -6.5t36.5 -6 t25 -4.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf17e;" d="M1173 473q0 50 -19.5 91.5t-48.5 68.5t-73 49t-82.5 34t-87.5 23l-104 24q-30 7 -44 10.5t-35 11.5t-30 16t-16.5 21t-7.5 30q0 77 144 77q43 0 77 -12t54 -28.5t38 -33.5t40 -29t48 -12q47 0 75.5 32t28.5 77q0 55 -56 99.5t-142 67.5t-182 23q-68 0 -132 -15.5 t-119.5 -47t-89 -87t-33.5 -128.5q0 -61 19 -106.5t56 -75.5t80 -48.5t103 -32.5l146 -36q90 -22 112 -36q32 -20 32 -60q0 -39 -40 -64.5t-105 -25.5q-51 0 -91.5 16t-65 38.5t-45.5 45t-46 38.5t-54 16q-50 0 -75.5 -30t-25.5 -75q0 -92 122 -157.5t291 -65.5 q73 0 140 18.5t122.5 53.5t88.5 93.5t33 131.5zM1536 256q0 -159 -112.5 -271.5t-271.5 -112.5q-130 0 -234 80q-77 -16 -150 -16q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5q0 73 16 150q-80 104 -80 234q0 159 112.5 271.5t271.5 112.5q130 0 234 -80 q77 16 150 16q143 0 273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -73 -16 -150q80 -104 80 -234z" />
<glyph unicode="&#xf180;" horiz-adv-x="1664" d="M1483 512l-587 -587q-52 -53 -127.5 -53t-128.5 53l-587 587q-53 53 -53 128t53 128l587 587q53 53 128 53t128 -53l265 -265l-398 -399l-188 188q-42 42 -99 42q-59 0 -100 -41l-120 -121q-42 -40 -42 -99q0 -58 42 -100l406 -408q30 -28 67 -37l6 -4h28q60 0 99 41 l619 619l2 -3q53 -53 53 -128t-53 -128zM1406 1138l120 -120q14 -15 14 -36t-14 -36l-730 -730q-17 -15 -37 -15v0q-4 0 -6 1q-18 2 -30 14l-407 408q-14 15 -14 36t14 35l121 120q13 15 35 15t36 -15l252 -252l574 575q15 15 36 15t36 -15z" />
<glyph unicode="&#xf181;" d="M704 192v1024q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-1024q0 -14 9 -23t23 -9h480q14 0 23 9t9 23zM1376 576v640q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-640q0 -14 9 -23t23 -9h480q14 0 23 9t9 23zM1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408 q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf182;" horiz-adv-x="1280" d="M1280 480q0 -40 -28 -68t-68 -28q-51 0 -80 43l-227 341h-45v-132l247 -411q9 -15 9 -33q0 -26 -19 -45t-45 -19h-192v-272q0 -46 -33 -79t-79 -33h-160q-46 0 -79 33t-33 79v272h-192q-26 0 -45 19t-19 45q0 18 9 33l247 411v132h-45l-227 -341q-29 -43 -80 -43 q-40 0 -68 28t-28 68q0 29 16 53l256 384q73 107 176 107h384q103 0 176 -107l256 -384q16 -24 16 -53zM864 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" />
<glyph unicode="&#xf183;" horiz-adv-x="1024" d="M1024 832v-416q0 -40 -28 -68t-68 -28t-68 28t-28 68v352h-64v-912q0 -46 -33 -79t-79 -33t-79 33t-33 79v464h-64v-464q0 -46 -33 -79t-79 -33t-79 33t-33 79v912h-64v-352q0 -40 -28 -68t-68 -28t-68 28t-28 68v416q0 80 56 136t136 56h640q80 0 136 -56t56 -136z M736 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" />
<glyph unicode="&#xf184;" d="M773 234l350 473q16 22 24.5 59t-6 85t-61.5 79q-40 26 -83 25.5t-73.5 -17.5t-54.5 -45q-36 -40 -96 -40q-59 0 -95 40q-24 28 -54.5 45t-73.5 17.5t-84 -25.5q-46 -31 -60.5 -79t-6 -85t24.5 -59zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf185;" horiz-adv-x="1792" d="M1472 640q0 117 -45.5 223.5t-123 184t-184 123t-223.5 45.5t-223.5 -45.5t-184 -123t-123 -184t-45.5 -223.5t45.5 -223.5t123 -184t184 -123t223.5 -45.5t223.5 45.5t184 123t123 184t45.5 223.5zM1748 363q-4 -15 -20 -20l-292 -96v-306q0 -16 -13 -26q-15 -10 -29 -4 l-292 94l-180 -248q-10 -13 -26 -13t-26 13l-180 248l-292 -94q-14 -6 -29 4q-13 10 -13 26v306l-292 96q-16 5 -20 20q-5 17 4 29l180 248l-180 248q-9 13 -4 29q4 15 20 20l292 96v306q0 16 13 26q15 10 29 4l292 -94l180 248q9 12 26 12t26 -12l180 -248l292 94 q14 6 29 -4q13 -10 13 -26v-306l292 -96q16 -5 20 -20q5 -16 -4 -29l-180 -248l180 -248q9 -12 4 -29z" />
<glyph unicode="&#xf186;" d="M1262 233q-54 -9 -110 -9q-182 0 -337 90t-245 245t-90 337q0 192 104 357q-201 -60 -328.5 -229t-127.5 -384q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51q144 0 273.5 61.5t220.5 171.5zM1465 318q-94 -203 -283.5 -324.5t-413.5 -121.5q-156 0 -298 61 t-245 164t-164 245t-61 298q0 153 57.5 292.5t156 241.5t235.5 164.5t290 68.5q44 2 61 -39q18 -41 -15 -72q-86 -78 -131.5 -181.5t-45.5 -218.5q0 -148 73 -273t198 -198t273 -73q118 0 228 51q41 18 72 -13q14 -14 17.5 -34t-4.5 -38z" />
<glyph unicode="&#xf187;" horiz-adv-x="1792" d="M1088 704q0 26 -19 45t-45 19h-256q-26 0 -45 -19t-19 -45t19 -45t45 -19h256q26 0 45 19t19 45zM1664 896v-960q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v960q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1728 1344v-256q0 -26 -19 -45t-45 -19h-1536 q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1536q26 0 45 -19t19 -45z" />
<glyph unicode="&#xf188;" horiz-adv-x="1664" d="M1632 576q0 -26 -19 -45t-45 -19h-224q0 -171 -67 -290l208 -209q19 -19 19 -45t-19 -45q-18 -19 -45 -19t-45 19l-198 197q-5 -5 -15 -13t-42 -28.5t-65 -36.5t-82 -29t-97 -13v896h-128v-896q-51 0 -101.5 13.5t-87 33t-66 39t-43.5 32.5l-15 14l-183 -207 q-20 -21 -48 -21q-24 0 -43 16q-19 18 -20.5 44.5t15.5 46.5l202 227q-58 114 -58 274h-224q-26 0 -45 19t-19 45t19 45t45 19h224v294l-173 173q-19 19 -19 45t19 45t45 19t45 -19l173 -173h844l173 173q19 19 45 19t45 -19t19 -45t-19 -45l-173 -173v-294h224q26 0 45 -19 t19 -45zM1152 1152h-640q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5z" />
<glyph unicode="&#xf189;" horiz-adv-x="1920" d="M1917 1016q23 -64 -150 -294q-24 -32 -65 -85q-78 -100 -90 -131q-17 -41 14 -81q17 -21 81 -82h1l1 -1l1 -1l2 -2q141 -131 191 -221q3 -5 6.5 -12.5t7 -26.5t-0.5 -34t-25 -27.5t-59 -12.5l-256 -4q-24 -5 -56 5t-52 22l-20 12q-30 21 -70 64t-68.5 77.5t-61 58 t-56.5 15.5q-3 -1 -8 -3.5t-17 -14.5t-21.5 -29.5t-17 -52t-6.5 -77.5q0 -15 -3.5 -27.5t-7.5 -18.5l-4 -5q-18 -19 -53 -22h-115q-71 -4 -146 16.5t-131.5 53t-103 66t-70.5 57.5l-25 24q-10 10 -27.5 30t-71.5 91t-106 151t-122.5 211t-130.5 272q-6 16 -6 27t3 16l4 6 q15 19 57 19l274 2q12 -2 23 -6.5t16 -8.5l5 -3q16 -11 24 -32q20 -50 46 -103.5t41 -81.5l16 -29q29 -60 56 -104t48.5 -68.5t41.5 -38.5t34 -14t27 5q2 1 5 5t12 22t13.5 47t9.5 81t0 125q-2 40 -9 73t-14 46l-6 12q-25 34 -85 43q-13 2 5 24q17 19 38 30q53 26 239 24 q82 -1 135 -13q20 -5 33.5 -13.5t20.5 -24t10.5 -32t3.5 -45.5t-1 -55t-2.5 -70.5t-1.5 -82.5q0 -11 -1 -42t-0.5 -48t3.5 -40.5t11.5 -39t22.5 -24.5q8 -2 17 -4t26 11t38 34.5t52 67t68 107.5q60 104 107 225q4 10 10 17.5t11 10.5l4 3l5 2.5t13 3t20 0.5l288 2 q39 5 64 -2.5t31 -16.5z" />
<glyph unicode="&#xf18a;" horiz-adv-x="1792" d="M675 252q21 34 11 69t-45 50q-34 14 -73 1t-60 -46q-22 -34 -13 -68.5t43 -50.5t74.5 -2.5t62.5 47.5zM769 373q8 13 3.5 26.5t-17.5 18.5q-14 5 -28.5 -0.5t-21.5 -18.5q-17 -31 13 -45q14 -5 29 0.5t22 18.5zM943 266q-45 -102 -158 -150t-224 -12 q-107 34 -147.5 126.5t6.5 187.5q47 93 151.5 139t210.5 19q111 -29 158.5 -119.5t2.5 -190.5zM1255 426q-9 96 -89 170t-208.5 109t-274.5 21q-223 -23 -369.5 -141.5t-132.5 -264.5q9 -96 89 -170t208.5 -109t274.5 -21q223 23 369.5 141.5t132.5 264.5zM1563 422 q0 -68 -37 -139.5t-109 -137t-168.5 -117.5t-226 -83t-270.5 -31t-275 33.5t-240.5 93t-171.5 151t-65 199.5q0 115 69.5 245t197.5 258q169 169 341.5 236t246.5 -7q65 -64 20 -209q-4 -14 -1 -20t10 -7t14.5 0.5t13.5 3.5l6 2q139 59 246 59t153 -61q45 -63 0 -178 q-2 -13 -4.5 -20t4.5 -12.5t12 -7.5t17 -6q57 -18 103 -47t80 -81.5t34 -116.5zM1489 1046q42 -47 54.5 -108.5t-6.5 -117.5q-8 -23 -29.5 -34t-44.5 -4q-23 8 -34 29.5t-4 44.5q20 63 -24 111t-107 35q-24 -5 -45 8t-25 37q-5 24 8 44.5t37 25.5q60 13 119 -5.5t101 -65.5z M1670 1209q87 -96 112.5 -222.5t-13.5 -241.5q-9 -27 -34 -40t-52 -4t-40 34t-5 52q28 82 10 172t-80 158q-62 69 -148 95.5t-173 8.5q-28 -6 -52 9.5t-30 43.5t9.5 51.5t43.5 29.5q123 26 244 -11.5t208 -134.5z" />
<glyph unicode="&#xf18b;" d="M1133 -34q-171 -94 -368 -94q-196 0 -367 94q138 87 235.5 211t131.5 268q35 -144 132.5 -268t235.5 -211zM638 1394v-485q0 -252 -126.5 -459.5t-330.5 -306.5q-181 215 -181 495q0 187 83.5 349.5t229.5 269.5t325 137zM1536 638q0 -280 -181 -495 q-204 99 -330.5 306.5t-126.5 459.5v485q179 -30 325 -137t229.5 -269.5t83.5 -349.5z" />
<glyph unicode="&#xf18c;" horiz-adv-x="1408" d="M1402 433q-32 -80 -76 -138t-91 -88.5t-99 -46.5t-101.5 -14.5t-96.5 8.5t-86.5 22t-69.5 27.5t-46 22.5l-17 10q-113 -228 -289.5 -359.5t-384.5 -132.5q-19 0 -32 13t-13 32t13 31.5t32 12.5q173 1 322.5 107.5t251.5 294.5q-36 -14 -72 -23t-83 -13t-91 2.5t-93 28.5 t-92 59t-84.5 100t-74.5 146q114 47 214 57t167.5 -7.5t124.5 -56.5t88.5 -77t56.5 -82q53 131 79 291q-7 -1 -18 -2.5t-46.5 -2.5t-69.5 0.5t-81.5 10t-88.5 23t-84 42.5t-75 65t-54.5 94.5t-28.5 127.5q70 28 133.5 36.5t112.5 -1t92 -30t73.5 -50t56 -61t42 -63t27.5 -56 t16 -39.5l4 -16q12 122 12 195q-8 6 -21.5 16t-49 44.5t-63.5 71.5t-54 93t-33 112.5t12 127t70 138.5q73 -25 127.5 -61.5t84.5 -76.5t48 -85t20.5 -89t-0.5 -85.5t-13 -76.5t-19 -62t-17 -42l-7 -15q1 -5 1 -50.5t-1 -71.5q3 7 10 18.5t30.5 43t50.5 58t71 55.5t91.5 44.5 t112 14.5t132.5 -24q-2 -78 -21.5 -141.5t-50 -104.5t-69.5 -71.5t-81.5 -45.5t-84.5 -24t-80 -9.5t-67.5 1t-46.5 4.5l-17 3q-23 -147 -73 -283q6 7 18 18.5t49.5 41t77.5 52.5t99.5 42t117.5 20t129 -23.5t137 -77.5z" />
<glyph unicode="&#xf18d;" horiz-adv-x="1280" d="M1259 283v-66q0 -85 -57.5 -144.5t-138.5 -59.5h-57l-260 -269v269h-529q-81 0 -138.5 59.5t-57.5 144.5v66h1238zM1259 609v-255h-1238v255h1238zM1259 937v-255h-1238v255h1238zM1259 1077v-67h-1238v67q0 84 57.5 143.5t138.5 59.5h846q81 0 138.5 -59.5t57.5 -143.5z " />
<glyph unicode="&#xf18e;" d="M1152 640q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192h-352q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h352v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198 t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf190;" d="M1152 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-352v-192q0 -14 -9 -23t-23 -9q-12 0 -24 10l-319 319q-9 9 -9 23t9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h352q13 0 22.5 -9.5t9.5 -22.5zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198 t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf191;" d="M1024 960v-640q0 -26 -19 -45t-45 -19q-20 0 -37 12l-448 320q-27 19 -27 52t27 52l448 320q17 12 37 12q26 0 45 -19t19 -45zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5z M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf192;" d="M1024 640q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5 t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
<glyph unicode="&#xf193;" horiz-adv-x="1664" d="M1023 349l102 -204q-58 -179 -210 -290t-339 -111q-156 0 -288.5 77.5t-210 210t-77.5 288.5q0 181 104.5 330t274.5 211l17 -131q-122 -54 -195 -165.5t-73 -244.5q0 -185 131.5 -316.5t316.5 -131.5q126 0 232.5 65t165 175.5t49.5 236.5zM1571 249l58 -114l-256 -128 q-13 -7 -29 -7q-40 0 -57 35l-239 477h-472q-24 0 -42.5 16.5t-21.5 40.5l-96 779q-2 16 6 42q14 51 57 82.5t97 31.5q66 0 113 -47t47 -113q0 -69 -52 -117.5t-120 -41.5l37 -289h423v-128h-407l16 -128h455q40 0 57 -35l228 -455z" />
<glyph unicode="&#xf194;" d="M1254 899q16 85 -21 132q-52 65 -187 45q-17 -3 -41 -12.5t-57.5 -30.5t-64.5 -48.5t-59.5 -70t-44.5 -91.5q80 7 113.5 -16t26.5 -99q-5 -52 -52 -143q-43 -78 -71 -99q-44 -32 -87 14q-23 24 -37.5 64.5t-19 73t-10 84t-8.5 71.5q-23 129 -34 164q-12 37 -35.5 69 t-50.5 40q-57 16 -127 -25q-54 -32 -136.5 -106t-122.5 -102v-7q16 -8 25.5 -26t21.5 -20q21 -3 54.5 8.5t58 10.5t41.5 -30q11 -18 18.5 -38.5t15 -48t12.5 -40.5q17 -46 53 -187q36 -146 57 -197q42 -99 103 -125q43 -12 85 -1.5t76 31.5q131 77 250 237 q104 139 172.5 292.5t82.5 226.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf195;" horiz-adv-x="1152" d="M1152 704q0 -191 -94.5 -353t-256.5 -256.5t-353 -94.5h-160q-14 0 -23 9t-9 23v611l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v93l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v250q0 14 9 23t23 9h160 q14 0 23 -9t9 -23v-181l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-93l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-487q188 13 318 151t130 328q0 14 9 23t23 9h160q14 0 23 -9t9 -23z" />
<glyph unicode="&#xf196;" horiz-adv-x="1408" d="M1152 736v-64q0 -14 -9 -23t-23 -9h-352v-352q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v352h-352q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h352v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-352h352q14 0 23 -9t9 -23zM1280 288v832q0 66 -47 113t-113 47h-832 q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5z" />
<glyph unicode="&#xf197;" horiz-adv-x="1792" />
<glyph unicode="&#xf198;" horiz-adv-x="1792" />
<glyph unicode="&#xf199;" horiz-adv-x="1792" />
<glyph unicode="&#xf19a;" horiz-adv-x="1792" />
<glyph unicode="&#xf19b;" horiz-adv-x="1792" />
<glyph unicode="&#xf19c;" horiz-adv-x="1792" />
<glyph unicode="&#xf19d;" horiz-adv-x="1792" />
<glyph unicode="&#xf19e;" horiz-adv-x="1792" />
<glyph unicode="&#xf500;" horiz-adv-x="1792" />
</font>
</defs></svg>        `FFTMf/W      GDEF       OS/2z  (   `cmapk    rgasp        glyf;e   head    6hhea 0   $hmtx T  Hloca8b #  .maxp &    name;e &  postP )  ]webfRw ;          =    T0    ΝjW                        3   3  s Z3                            pyrs @        #                              l      P   P @          
 / _!"""` >N^n~.>N^n~             / _!"""`  !@P`p  0@P`p d]YTC
߷ݹ                                                                                                                                                                                                                                                         	                                                                                      p       7!!!@pp p                  1   ]    !2#!"&463!&54>3!2+@&&&&@+$(($F#+ &4&&4& x+#       +  ".4>32".4>32467632 DhgZghDDhg-iW DhgZghDDhg-iW&@(8 2N++NdN+';2N++NdN+'3
 8      !        #"'#"$&6$ rL46$܏ooo|W%r4L&V|oooܳ%        = M  %+".'&%&'3!26<.#!";2>767>7#!"&5463!2 %3@m00m@3% @:"7..7":6]^B@B^^BB^  $΄+0110+$ (	
t1%%1+`B^^B@B^^        "'.54632>324
#L</>oP$$Po>Z$_dC+I@$$@I+     "  #"'%#"&547&547%62V??V8<8yb%	I))9I	       	 +  	%%#"'%#"&547&547%62q2ZZ2IzyV)??V8<8)>~>[
2b%	I))9I	      '  %#!"&54>322>32  &6 yy 6Fe=	BSSB	=eF6 >xx5eud_C(+5++5+(C_due>        / ? O _ o      54&+";2654&+";2654&+";264&#!"3!2654&+";2654&+";264&#!"3!2654&+";2654&+";2654&+";267#!"&5463!2&&&&&&&&&&&& & && & &&&&&&&&& && &&&&&&&&&&&&&^BB^^B@B^@&&&&&&&&&&&& && &&&&&&&&&& && &&&&&&&&&&&&&&B^^B@B^^        / ?  #!"&5463!2#!"&5463!2#!"&5463!2#!"&5463!2 L4 4LL4 4LL4 4LL4 4LL4 4LL4 4LL4 4LL4 4L 4LL44LL4LL44LL4LL44LL4LL44LL 	        / ? O _ o    #!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2 8((88(@(88((88(@(88((88(@(88((88(@(88((88(@(88((88(@(88((88(@(88((88(@(88((88(@(8 (88((88(88((88(88((88(88((88(88((88(88((88(88((88(88((88(88((88          / ? O _  #!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2 8((88(@(88((88(@(8 8(@(88((8 8((88(@(8 8(@(88((88(@(88((8 (88((88(88((88(88((88(88((88(88((88(88((88    y     "/&4?62	62,PP&PP,jP  n #  $"'	"/&47	&4?62	62	PP&P&&P&P&P&&P&P      # + D  ++"&=#"&=46;546;232      #"'#"$&6$  @@rK56$܏ooo|W@@rjK&V|oooܳ        0  #!"&=463!2      #"'#"$&6$  @rK56$܏ooo|W@@rjK&V|oooܳ         ) 5   $&54762>54&'.7>"&5462 zz+i *bkQнQkb* j*LhLLhLzzBm +*i JyhQQhyJ i*+ mJ4LL44LL          / ? O  %+"&=46;2%+"&546;2%+"&546;2+"&546;2+"&546;2 `r@@r@@        n   4&"2#"/+"&/&'#"'&'&547>7&/.=46?67&'&547>3267676;27632 Ԗ#H
	,/1)
~'H(C
	,/1)	$HԖԖm6%2X
%	l2k	r6
[21..9Q
$
k2k	
w3[20       / ; C g  +"&546;2+"&546;2+"&546;2!3!2>!'&'!+#!"&5#"&=463!7>3!2!2 @@ @@ @@@`0

o`^BB^`5FN(@(NF5 @@@L%%Ju		@LSyuS@%44%       f  5  #!!!"&5465	7#"'	'&/&6762546;2& &??>LL>
 X 
  &&&AJ	A	J
Wh        #  3!!"&5!!&'&'#!"&5463!2 `(8 x
 8((88((`8( 8(9
h(88(@(8(`        ,  #!"&=46;46;2 .  6  $$ @(r^aa@@`(_^aa    2  N   C  5.+";26#!26'.#!"3!"547>3!";26/.#!2W.@@.$SS$@9I  I6>>         % =  $4&"2$4&"2#!"&5463!2?!2"'&763!463!2!2 &4&&4&&4&&48(@(88(ч::(8@6@* & & *4&&4&&4&&4& (88(@(8888)@)'&&@      $ 0  "'&76;46;232  >& $$ `
(r^aa`		@`2(^aa         $ 0  ++"&5#"&54762  >& $$ ^
?@(r^aa`?		(^aa         #  !.'!!!%#!"&547>3!2<<<_@`&&
5@5
@
&&>=(""=       '   #"'&5476.  6  $$    ! (r^aaJ	%%(_^aa     3  #!"'&?&#"3267672#"$&6$3276 &@*hQQhwI	mʬzzk)' @&('QнQh_
	
z8zoe      $ G   !"$'"&5463!23267676;2#!"&4?&#"+"&= !2762@hk4&&&GaF*&@&ɆF*Ak4&nf&&&4BHrd@&&4rdMoe&            / ? O _ o   +"&=46;25+"&=46;25+"&=46;2#!"&=463!25#!"&=463!25#!"&=463!24&#!"3!26#!"&5463!2@@@@@@@@@@^B@B^^BB^`@@@@@@@@@@@@3@MB^^B@B^^         !54&"#!"&546;54   32@ Ԗ@8(@(88( p (8 jj(88(@(88   @   7  +"&5&5462#".#"#"&5476763232>32@@@@KjKך=}\I&:k~&26]S& H&&H5KKut,4,	& x:;*4*&        K  #+"&546;227654$ >3546;2+"&="&/&546$ <X@@Gv"DװD"vG@@X<4L41!Sk @ G<_bb_<G  kS!1zz          "'!"&5463!62 &4&&M4&&M&&M&          -  "'!"&5463!62 #"&54>4.54632 &4&&M4&UF
&""""&
F&M&&M&%.D.%      G  - I k  "'!"&5463!62 #"&54>4.54632#"&54767>4&'&'&54632#"&547>7676'&'.'&54632 &4&&M4&UF
&""""&
FU&'8JSSJ8'&&'.${{$.'&&M&&M&%.D.%7;&'66'&;4[&$[2[$&[              # / 3 7  #5#5!#5!!!!!!!#5!#5!5##!35!!!                        # ' + / 3 7 ; ?  3#3#3#3#3#3#3#3#3#3#3#3#3#3#3#3#3????  ^>>~??????~??~??^??^^?  ^??          4&"2#"'.5463!2KjKKjv%'45%5&5L45&%jKKjK@5%%%%54L5&6'      k   5   4&"2#"'.5463!2#"&'654'.#32KjKKjv%'45%5&5L45&%%'4$.%%5&55&%jKKjK@5%%%%54L5&6'45%%%54'&55&6'  
y T d t  #!"&'&74676&7>7>76&7>7>76&7>7>76&7>7>63!2#!"3!2676'3!26?6&#!"3!26?6&#!"g(sAeM,*$/!'&JP$G]
x6,&`h`"9Hv@WkNC<.
&k&
("$p"	.#u&#	%!'	pJvwEF#@@        2#"'	#"'.546763!''!0#GG$/!''!	8""8 X!	8"	"8	          <  )!!#"&=! 4&"27+#!"&=#"&546;463!232(8&4&&48(@(8qO@8((`(@Oq 8(&4&&4&@`(88(Oq (8(`( q      ! )   2"&42#!"&546;7>3!2      Ijjjj3e5 5e3gr`Ijjjj1GG1r       	 Q  37&'&#7676767;"'&#"4?6764/%2"%ժIM <5:YK5g'9')//8Pp]`O8:8/\>KM'B0Q>_O4h 7f:jCR1'-!
rA@
        % e  %3267654'&'&#"32654'&#"767676765'&'&'&'&/-72632;2/&+L@%&):SPJ+BUT4N-M.	
3T|-)JXg+59-,*@?|Z\2BJIRtT! RHForB^  
pKK,!zb+e^	B WS//rAFt/9)ijLU>7H$$       J  767676?7>5?5&'&'7327>3"#"'&/&IL(8)g
='"B!F76@%	,=&+@7$	~)J~U%@@,Q5(?2&g	9,&kɞ-
     i   ;?!6?2&'.'&'&"#"2#"'&#"#&5'56767676'&64&'&'&#"#&'52"/&6;#"&?62+Q6s%"*'G+"!
1( 8nMHX0:	&n+r,!~:~!PP!~:~!P5d: +UM6a'.'

-

	!&#>q\	0f!)V%% %%       h   ;?!6?2&'.'&'&"#"52#"'&#"#&5'56767676''&'&'&#"#&'5&=!/&4?6!546Q6s>"*'g)^!
1( 8nMHR-:	&n2,% %% %5d: +UM6a'4.'

-

	!&#(,	
	0f!)V:~!PP!~:~!PP!          / ?  %#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2 &&&&& && & & && &&&&&&&&&f&&&&f&&&&f&&&&          / ?  %#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2 &&&&&&&& &&&&&&&&&&&&f&&&&f&&&&f&&&&          / ?  %#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2 &&&&& && && && &&&&&&&&&f&&&&f&&&&f&&&&            / ?  %#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2 &&&&&&&&&&&&&&&&&&&&f&&&&f&&&&f&&&&            / ? O _ o   %+"&=46;2+"&=46;2+"&=46;2#!"&=463!2+"&=46;2#!"&=463!2#!"&=463!2#!"&=463!2  @  @@@sssss          / ? O  #"'&47632#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2			 	@@@@	 		 	sss         / ? O   #"&54632	#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2`			 @@@@		@		sss           #"'#!"&5463!2632 'mw@www'*wwww          .   "&462!5	!"3!2654&#!"&5463!2pppp@  @^BB^^B@B^ppp@@  @ @B^^BB^^   k    %  !7'34#"3276'	!7632k[[v

6`%`$65&%[[k
`5%&&'          4&"2"&'&54    Ԗ!?H?!,,ԖԖ mF!&&!Fm,        %"  $$  ^aa`@^aa           -  4'.'&"26%   547>7>2 "KjK XQqYn	243nYqQ$!+!77!+!$5KK,ԑ	]""]ً	        9 > H  7'3 &7#!"&5463!2'&#!"3!26=4?6	!762xtt`   ^Qwww@?61B^^B@B^	@(` `\\\P`tt8`  ^Ͼww@w1^BB^^B~	@` \ \P          + Z  #!"&5463!12+"3!26=47676#"'&=# #"'.54>;547632www M8
pB^^B@B^'sw-

9*##;Noj'#ww@w"^BB^^B
	*"g`81T`PSA:'*4       / D  #!"&5463!2#"'&#!"3!26=4?632"'&4?62	62www@?61
B^^B@B^	@
BRnBBn^ww@w1
^BB^^B	@
BnnB          C   "&=!32"'&46;!"'&4762!#"&4762+!5462  4&& 4 &&4  4&& 4 &&4 4 &&4  4&& 4 &&4  4&&        6'&'+"&546;267:	&&&&	s@	
Z&&&&Z     +  6'&''&'+"&546;267667:	:	&&&&		s@	
:	
Z&&&&Z:  z   6'&''&47667S::s@	
:4:    |   	&546h!!0a$           #!"&5463!2#!"&5463!2 & && && && &@&&&&&&&&          #!"&5463!2 &&&&@&&&&         &54646&5-:s::4:
	        +  &5464646;2+"&5&5-&&&&:s::&&&&
	:
	         &54646;2+"&5-&&&&s:&&&&
	          62#!"&!"&5463!24@&&&&-:& && &     5   &4762	"t%%%k%K%%%%K%k%%k%%%K%k%&j%K%     uK   "/&547	&54?62K%t%j%L%%%%L$l$%4'u%%K'45%'45%K&&u%        # /  54&#!4&+"!"3!;265!26  $$ & && && && &@^aa@& && && && &+^aa        54&#!"3!26  $$ & && &@^aa@&&&&+^aa       + 7  4/7654/&#"'&#"32?32?6  $$ }ZZZZ^aaZZZZ^aa      #  4/&"'&"327> $$ [4h4[j^aa"ZiZJ^aa      : F  %54&+";264.#"32767632;265467>$ $$  oW	5!"40K(0?i+! ":^aaXRdD4!&.uC$=1/J=^aa       . :  %54&+4&#!";#"3!2654&+";26 $$  ```^aa ^aa      / _  #"&=46;.'+"&=32+546;2>++"&=.'#"&=46;>7546;232m&&m l&&l m&&m l&&ls&%&&%&&%&&%& &&l m&&m l&&l m&&m ,&%&&%&&%&&%&        # / ;  "/"/&4?'&4?627626.  6  $$ I














͒(r^aaɒ














(_^aa           ,  	"'&4?6262.  6  $$ Z4f44fz(r^aaZ&4ff4(_^aa        	  "  4'32>&#"  $&6$  WoɒV󇥔 zzz8YW˼[?zz:zz   @5 K    #!#"'&547632!2 A4@%&&K%54'u%%&54&K&&4A5K$l$L%%%54'&&J&j&K    5K    #"/&47!"&=463!&4?632%u'43'K&&%@4AA4&&K&45&%@6%u%%K&j&%K55K&$l$K&&u#   5K@ !  #"'+"&5"/&547632K%K&56$K55K$l$K&&#76%%53'K&&%@4AA4&&K&45&%%u'     5K "  #"'&54?63246;2632K%u'45%u&&J'45%&L44L&%54'K%5%t%%$65&K%%4LL4@&%%K'      ,   "&5#"#"'.'547!3462  4&bqb>#5&4 4 & 6Uue7D#		"ǆ &        /   #!"&546262"/"/&47'&463!2
&@&&4L

r&4

r

L&&
4&&&L

rI@&

r

L4&&     s  /  "/"/&47'&463!2 #!"&546262 &4

r

L&&
&@&&4L

r@@&

r

L4&&
4&&&L

r         #  #!+"&5!"&=463!46;2!28(`8((8`(88(8((8(8 (8`(88(8((8(88(`8          #!"&=463!28(@(88((8 (88((88   z 5  '%+"&5&/&67-.?>46;2%6.@g.L44L.g@.
.@g.
L44L
.g@.g.n.4LL43.n.gg.n.34LL4͙.n.g        -     $54&+";264'&+";26/a^



^aafm
        @    J  %55!;263'&#"$4&#"32+#!"&5#"&5463!"&46327632#!2$$8~+(888(+}(`8((8`]]k==k]]8,8e8P88P8`(88(@MM        O   4&#"327>76$32 #"'.#"#".'.54>54&'&54>7>7>32 &z&^&./+>*>J>	Wm7'
'"''? &4&c&^|h_bml/J@L@#M6:D
35sҟw$	'%
'	\t       3  #!"&=463!2'.54>54''@ 1O``O1CZZ71O``O1BZZ7@@N]SHH[3`)TtbN]SHH[3^)Tt           ! 1  &'   547 $ 4&#"2654632    '&476   ==嘅}(zVl''ٌ@uhyyhu9(}VzD##D#     	  = C U  %7.547 4&#"2654632% #"'&547.'&476 !27632#76$7&'7+NWb=嘧}(zVi\j1
z,XY[6
$!%'FuJiys?_9ɍ?kyhun(}VzYF
KA؉La
02-F"@Qsp@_        ! 3  %54&+";264'&+";26#!"&'&7>2 

 #%;" ";%# <F<7
??""??$$     ll 2  #"'&'	+&/&'&?632	&'&?67>`,@L5`		
`	L`4LH``	a	5L@              # 3 7 ; ? O s  !!!!%!!!!%!!!!!!!!%!!4&+";26!!%!!!!74&+";26%#!"&546;546;2!546;232 `@ `@ @@  @@@ @  @@L44LL4^B@B^^B@B^4L  @@@@      @@  @@   M 4LL4 4L`B^^B``B^^B`L        7 q  .+"&=46;2 #"&=".'673!54632#"&=!"+"&=46;2>767>3!54632<M33K,		 j8Z4L2B4:;M33K, ?			 0N<* .)C=W]xD0N<* .)C=W]xD ?\-7H)		".=']-7H)
w		<?.>mBZxPV3!<?.>mBZxPV3!
         &   #"'&'5&6&>7>7&54>$32 dFK1A
0)L.٫C58.H(Ye      # 3 C   $=463!22>=463!2#!"&5463!2#!"&5463!2 H&&/<R.*.R</&& &&&& &&&&Bɀ&&4L&&L4&&f&&&&&&&&     5 uKK    #"'	"/&547632K%K&56$$l$K&&%54'uj%K&&&&K$65&%%u  5 5K   #"'&54?632	632K%u&56$u&&J'45%%54'K%@5%u&&$65&K%%%%K'         % K  %#!".<=#"&54762+!2"'&546;!"/&5463!232 @&@<@&@	:&	& 
&&&	
`&          ;  $"&462"&462!2#!"&54>7#"&463!2!2KjKKjKjKKj && &%&& &5jKKjKKjKKjK %z
0&4&&3D7&4&%&        #!"&5463!2!2\@\\@\\@\\\\         W  *  #!"&547>3!2!"4&5463!2!2W+B"5P+B@"5^=\@\ \H#t3G#3G:_Ht\\     @      +32"'&46;#"&4762&& 4 && 4 4& &4  4& &4       @     "&=!"'&4762!5462  4& &4  4& &4 4 && 4 &&            /  !!!!4&#!"3!26#!"&5463!2     @^BB^^B@B^     @@B^^BB^^        0 @  67&#".'&'#"'#"'32>54'6#!"&5463!2 8ADAE=\W{O[/5dIkDtpČe1?*w@www	(M&B{Wta28r=Ku?RZ^GwT	-@www        #  7#546;5#"#3!#!"&5463!28nw@wwwjm1'ې{@www        # ' . >   4&#"26546326"&462!5! &  !5!!=!!%#!"&5463!2B^8(Ԗ  > @|K5 5KK5 5K^B(8ԖԖ>v 5KK5 5KK   H  G   4&"&#"2654'32#".'#"'#"&54$327.54632@pp)*Pppp)*Pb	'"+`N*(a;2̓c`." b
PTY9ppP*)pppP*) b ".`(*Nͣ2ͣ`+"'	b
MRZB               4&"24&"264&"26#"/+"&/&'#"'&547>7&/.=46?67&'&547>3267676;27632#"&'"'#"'&547&'&=4767&547>32626?2#"&'"'#"'&547&'&=4767&547>32626?2ԖLhLKjKLhLKjK	"8w
s%(")v

>
	"8x
s"+")v
<
3zLLz33>8L3)x33zLLz33>8L3)x3ԖԖ 4LL45KK54LL45KK
#)0C

wZl/

Y	
N,&
#)0C	vZl.

Y	
L0"qG^^Gqq$ ]G)FqqG^^Gqq$ ]G)Fq         % O   #"'#"&'&4>7>7.546$ '&'&'# '32$7>54'VZ|$2$
|E~E<|
$2$|ZV:(t}X(	&%(Hw쉉xH(%&	(XZT\MKG        < m  $4&"24&#!4654&#+32;254'>4'654&'>7+"&'&#!"&5463!6767>763232 &4&&4N2`@`%)7&,$)'  %/0Ӄy#5 +1	&<$]`{t5KK5$e:1&+'3TF0h4&&4&3M:;b^v+D2 5#$IIJ 2E=\$YJ!$MCeM-+(K55KK5y*%Au]c         = p   4&"24&'>54'64&'654&+"+322654&5!267+#"'.'&'&'!"&5463!27>;2 &4&&4+ 5#bW0/%  ')$,&7)%`@``2Nh0##T3'"(0;e$5KK5 tip<&	1&4&&4& #\=E2 JIURI$#5 2D+v^b;:M2gc]vDEA%!bSV2MK55K(,,MeCM$!J   @   #"&547&547%6@?V8b%	I)         9  4.""'."	67"'.54632>32+C`\hxeH>Hexh\`C+ED4
#L</>oP$$Po>Q|I.3MCCM3.I|Q/Z$_dC+I@$$@I+           ( @  %#!"&5463!2#!"3!: "&5!"&5463!462ww@B^^B 
4&@&&&4 ` ww ^B@B^24& && &        % 5  73#7.";2634&#"35#347>32#!"&5463!2FtIG9;HIxI<,tԩw@wwwz4DD43EEueB&#1s@www      .  4&"26#!+"'!"&5463"&463!2#2&S3Ll&c4LL44LL4c@&&{ LhLLhL           ' ?  #!"&5463!2#!"3!26546;2"/"/&47'&463!2www@B^^B@B^@&4t

r

& &`ww@w@^BB^^B@R &t

r

4&&         @   "&5!"&5463!462	#!"&54&>3!2654&#!*.54&>3!24&@&&&4 sw@B^^B
@w4& && &3@w ^BB^       I  &5!%5!>732#!"&=4632654&'&'.=463!5463!2!2J  JSq*5&=CKuuKC=&5*q͍S8( ^B@B^ (8`N`Ѣ΀GtO6)"M36J[E@@E[J63M")6OtG(8`B^^B`8           % - 3   %'&76'&76''&76'&76'&6#5436&76+".=4'>54'6'&&"."&'./"?+"&5463!2	2				5



	
	z<: Ʃw
49[aA)O%-j'&]]5r,%O)@a[9(	0BA;+

>HCwww		5/)
	u
@wa-6OUyU[q	( -	q[UyUP6$C

+) (	
8&/&ww       ' ?  $4&"2$4&"2#!"&5463!3!267!2#!#!"&5!"'&762 &4&&4&&4&&48(@(88(c= =c(8* & & *6&4&&4&&4&&4& (88(@(88HH88`(@&&('@       1 d  4&'.54654'&#"#"&#"32632327>7#"&#"#"&54654&54>76763232632


	N<;+gC8A`1a99gw|98aIe$IVNz<:LQJ
	,-[%	061I()W,$-7,oIX()oζA;=N0
eTZ

(         O  #".'&'& '&'.54767>3232>32e^\3@P	bMO0#382W#& 9C9
Lĉ"	82<*9FF(W283#0OMb	P@3\^eFF9*<28	"L
9C9 &#           !"3!2654&#!"&5463!2`B^^B@B^^ީwww@w ^BB^^B@B^ww@w      #  !72#"'	#"'.546763 YY!''!0#GG$/!''! &UUjZ	8""8 X!	8"	"8	        E U  4'./.#"#".'.'.54>54.'.#" 32676#!"&5463!2 G55
:8c7)1)

05.D<90)$9 w@wwwW+
AB7c)$+
-.1 9$)0<D.59@www    ,  T  1  # '327.'327.=.547&54632676TC_LҬ#+i!+*pDNBN,y[`m`%i]hbEm}au&,SXK
&$f9s?
         !#!#3546;#"'/8"#      R   &=4'>54'6'&&"."&'./"?'& 54$  49[aA)O%-j'&]]5r,%O)@a[9(	0BA;+

>HCaaoMa-6OUyU[q	( -	q[UyUP6$C

+) (	
8&/&fMa         %  +"&54&"32#!"&5463!54   &@&Ԗ`(88(@(88(r && jj8((88(@(8        # ' +  2#!"&5463"!54&#265!375!35!B^^BB^^B` ^B@B^^BB^ `       ! =   "&462+"&'& '.=476;+"&'& $'.=476;pppp$!$qr%}#ߺppp!E$rqܢ#%ֻ!           ) ?   "&462"&4624&#!"3!26!.#!"#!"&547>3!2/B//B//B//B@2^B@B^\77\aB//B//B//B/@~B^^B@2^5BB52     . 4  2## %&'.67#"&=463! 2 5KK5L4_u:B&1/&.-
zB^^B4LvyKjK4L[!^k'!A3;):2*<vTq6^BB^L4$)*          7  4#"&54"3!&5 #!"&5!"&56467&5462P;U gIw%L4@Ԗ@4L8P8° U;Ig0  34LjjL4(88(¥'     } I  /#"/'&/'&?'&'&?'&76?'&7676767676`
(5)0
)*)
0)5(

(5)0
))))
0)5(
*)
0)5(
)5)0
)**)
0)5)

)5)0
)*      5 h  $4&"24&#!4>54&#"+323254'>4'654&'!267+#"'&#!"&5463!2>767>32!2 &4&&4N2$YGB(HGEG  HQ#5K4Li!<;5KK5 
A#("/?&}vh4&&4&3M95S+C=,@QQ9@@IJ 2E=L5i>9eME;K55K	J7R>@#zD<      7 ? s  %3#".'.'&'&'.#"!"3!32>$4&"2#!"#"&?&547&'#"&5463!&546323!2`  #A<(H(GY$2NL4K5#aWTƾh&4&&4K5;=!ihv}&?/"(#A
 5K2*!Q@.'!&=C+S59M34L=E2 JI UR@@&4&&4&5K;ELf9>ig<Dz#@>R7J	K         5 h  4&"24#"."&#"4&#"".#"!54>7#!"&54.'&'.5463246326326 &4&&4IJ 2E=L43M95S+C=,@QQ9@@E;K55K	J7R>@#zD<gi>9eMZ4&&4&<#5K4LN2$YGB(HGEG  HV;5KK5 
A#("/?&}vhi!<         4 < p  4.=!32>332653272673264&"2/#"'#"&5#"&54>767>5463!2@@2*!	Q@.'!&=C+S59M34L.9E2 JI UR&4&&4&Lf6Aig6Jy#@>R7J	K55K;E@TƾH  #A<(H(GY$2NL4K#5#a=4&&4&D=ihv}&?/"(#A
 5KK5;         +  54&#!764/&"2?64/!26  $$  &
[6[[j6[& ^aa@&4[[6[[6&+^aa        +   4/&"!"3!277$ $$ [6[
&&[6j[^aae6[j[6&&4[j[^aa      +   4''&"2?;2652?$ $$ [6[[6&&4[^aaf6j[[6[
&&[^aa      +   4/&"4&+"'&"2?  $$ [6&&4[j[6[j^aad6[&&
[6[[j ^aa             $2>767676&67>?&'4&'.'.'."#&6'&6&'3.'.&'&'&&'&6'&>567>#7>7636''&'&&'.'"6&'6'..'/"&'&76.'7>767&.'"76.7"7"#76'&'.'2#22676767765'4.6326&'.'&'"'>7>&&'.54>'>7>67&'&#674&7767>&/45'.67>76'27".#6'>776'>7647>?6#76'6&'676'&67.'&'6.'.#&'.&6'&.5/a^D&"	


	4	$!	#	
		
	


 
.0"Y
	+!	
	
$		"+


		
	Α	
		^aa
	

					

		
			P '-(	#	*
$
"!				*
!	
(				
	
$
		
2   ~   /  $4&"2	#"/&547#"  32>32&4&&4V%54'j&&'/덹:,{	&4&&4&V%%l$65&b'Cr!"k[G             + ;  %!5!!5!!5!#!"&5463!2#!"&5463!2#!"&5463!2    &&&&&&&&&&&&@ && && && && && &&   {    #"'&5&763!2{' * *)* )'             /  !5!#!"&5!3!26=#!5!463!5463!2!2  ^B@B^&@&`   ^B`8(@(8`B^   B^^B&&B^(88(^      G  	76#!"'&?	#!"&5476	#"'&5463!2	'&763!2#"'c)'&@**@&('c(&*cc*&'*@&('c'(&*cc*&('c'(&@*        1 9 A S [  #"&532327#!"&54>322>32 "&462  &6 +&'654'32>32"&462QgRp|Kx;CByy 6Fe=
BPPB
=eF6  ԖV>!pRgQBC;xK|Ԗ{QNa*+%xx5eud_C(+5++5+(C_due2ԖԖ>NQ{u%+*jԖԖ     p ! C i  4/&#"#".'32?64/&#"327.546326 #"/&547'#"/&4?632632(* 8(!)(A(')* 8(!USxySSXXVzxTTUSxySSXXVzxT@( (8 *(('((8 SSUSx{VXXTTSSUSx{VXXT        #!" 5467&54 32632t,Ԟ;F`j)6,>jK?  s  !  %#!"&7#"&463!2+!'5#8EjjE8@&& &&@XYY&4&&4&qDS%q%         N \ j x     2"&4#"'#"'&7>76326?'&'#"'.'&676326326&'&#"32>'&#"3254?''74&&4&lNnbSVZbRSD	zz	DSRb)+USbn\.2Q\dJ'.2Q\dJ.Q2.'Jd\Q2.'Jd`!O` 	`&4&&4r$#@B10M5TNT{L5T	II	T5L;l'OT4M01B@#$*3;$*3;;3*$;3*$:$/ @@Qq`@         " % 3 <  2#!"&5!"&5467>3!263!	!!#!!46!#!(88(@(8(8(`((8D<++<8(` (8(`8(@(88( 8((`(8((<`(8 (``(8    || ?  %#"'&54632#"'&#"32654'&#"#"'&54632|udqܟs]
=
OfjL?R@T?"&
>
f?rRX=Edudsq
=
_MjiL?T@R?E& f
>
=XRr?b      ! 1 E  )!34&'.##!"&5#3463!24&+";26#!"&5463!2  

08((88(@(88((88((`(1

`(88( (88( @`(88(@(8(`         #!"&5463!2 w@www`@www             /  %#!"&=463!2#!"&=463!2#!"&=463!2 &&&&&&&&&&&&&&&&&&&&&&&&    @    ' 7 G  $"&462"&462#!"&=463!2 "&462#!"&=463!2#!"&=463!2ppppppp@ppp@@Рppppppppp         < L \ l |  #"'732654'>75"##5!!&54>54&#"'>3235#!"&=463!2!5346=#'73#!"&=463!2#!"&=463!2}mQjB919+i1$AjM_3</BB/.#U_:IdDRE@k*Gj@@TP\BX-@8
C)5XsJ@$3T4+,:;39SG2S.7<vcc)(%Ll}         5 e  2#!"&=463%&'&5476!2/&'&#"!#"/&'&=4'&?5732767654'&@02uBo
T25XzrDCBBEh:%)0%HPIP{rQ9f#-+>;I@KM-/Q"@@@#-a[$&P{<8[;:XICC>. '5oe71#.0(l0&%,"J&9%$<=DTI     c s  &/6323276727#"327676767654./&'&'737#"'&'&'&54'&54&#!"3!260%<4"VRt8<@<-#=XYhW8+0$"+dTLx-'I&JKkmuw<=V@!X@		v'|N;!/!$8:IObV;C#V
&(mL.A:9 !./KLwPM$@@  
       / ? O _ o     %54&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!26#!"&5463!2 @@ @ @ @ @ @ @@^BB^^B@B^NB^^B@B^^         # + 3  	'$"/&4762%/?/?/?/?%k*66bbbb|<<<bbbbbbbb%k66Ƒbbb<<<<^bbbbbb    @      M  $4&"2!#" 4&"2&#"&5!"&5#".54634&>?>;5463!2LhLLh		 LhLLhL!'ԖԖ@'!&	?& &LhLLhL 		hLLhL 	jjjj	&@6/"&&       J   #"'676732>54.#"7>76'&54632#"&7>54&#"&54$  ok;	-j=yhwi[+PM3ѩk=J%62>VcaaQ^ ]G"'9r~:`}Ch  0=Z٤W=#uY2BrUI1^Fk[|a      L  2#!67673254.#"67676'&54632#"&7>54&#"#"&5463ww+U	,i<F{jh}Z+OM
2ϧj<J%51=Ubwww@wzX"'8'TyI9`{Bf 
,>XբW<"uW1AqSH1bdww        " 3 g  !"&'>32	327#".54632%#!654.54>4&'.'37!"463!2!#!!3
_Znh7 1-$
	g &Wa3\@0g]Bj> ҩw,',CMC,.BA.51	KL~w   9&!q[-A""""$!'JNv=Cdy4Shh/`R~ wITBqIE2;$@;Ft.

@M_~w`             - c o  %4.'&#"32>4.#"326!#!".547>7&54>7#"&54676!#!5!3l	
$-1!6hpT6Gs~@;k^7x!=kB]f0@\3aWGN.BB.!5@@5!;y{^<% L@
(վ^l   G'!$"""$8^<Dk=5^<~R`/hhS4y?O-XJsF;?$2.2=Gc9z/EmC=J@]1SBĔ                , <  !5##673#$".4>2"&5!#2!46#!"&5463!2 rM* *M~~M**M~~M*jjj& && &`P%挐|NN||NN|* jj jj@&&&&    @     "'&463!2 @4@&Z4@4&        @    #!"&4762 &&4Z4&&4@     @    "'&4762&4@4&@&4&      @    "&5462@@4&&44@&&@           3!!%!!26#!"&5463!2`m`^BB^^B@B^ `@B^^BB^^    @     "'&463!2#!"&4762 @4@&&&&44@4&Z4&&4@            "'&463!2 @4@&4@4&        @    #!"&4762 &&4Z4&&4@          :  #!"&5;2>76%6 +".'&$'.5463!2 ^B@B^,9j9Gv33vG9H9+bI\
A+=66=+A
[">nSMA_:B^^B1&c*/11/*{'VO3@/$$/@*?Nh^    l   +  !+"&5462!4&#"!/!#>32]_gTRdgdQV?UI*Gg?!2IbbIJaaiwE3300 08        4   #"$'&6?6332>4.#"#!"&54766$32 z䜬m
IwhQQhbF*@&('kz
	
_hQнQGB'(&*eoz  ( q  !#"'&547"'#"'&54>7632&4762.547>32#".'632%k'45%&+ ~((h		&

\((		&

~ +54'k%5%l%%l$65+ ~

&		((\

&		h((~ +%'         ! ) 1 9 K   4&"2 4&"26.676&$4&"2 4&"24&"2#!"'&46$ KjKKjKjKKje2.e<^P,bKjKKjKjKKjKjKKj##LlLKjKKjKjKKjK~-M<M(PM<rjKKjKjKKjKujKKjKL           <    6?32$6&#"'#"&'5&6&>7>7&54$ LhяW.{+9E=cQdFK1A
0)pJ2`[Q?l&٫C58.H(Y'        : d    6?32$64&$ #"'#"&'&4>7>7.546'&'&'# '32$7>54'Yj`a#",5NK
~EVZ|$2$
|:
$2$|ZV:(t}hfR88T
h̲X(	&%(Hw(%&	(XZT\MKG{x   | !  #"'.7#"'&7>3!2%632u
jH{(e9
1b      U  #!"&546;5!32#!"&546;5!32#!"&546;5463!5#"&5463!2+!232 8((88(` `(88((88(` `(88((88(`L4 `(88(@(88(` 4L`(8 (88(@(88((88(@(88((88(@(84L8(@(88((8L48      O Y  "&546226562#"'.#"#"'.'."#"'.'.#"#"&5476 $32&"5462И&4&NdN!>!1X:Dx++ww++xD:X1- U! *,*&4&hh&&2NN2D&
..J<
$$
<JJ<
$$
<J..
Pbb&&          7  !!"&5!54&#!"3!26!	#!"&=!"&5463!2 `(8 @ + 8(@(8(88(@(8(8( @@m+U`(88(8(@(88(h`         ( \  "&54&#"&46324."367>767#"&'"&547&547&547.'&54>2l42cKEooED
)

)
Dg-;</-?.P^P.?-/<;-gYY.2 L4H|O--O|HeO,,Oeq1Ls26%%4.2,44,2.4%%62sL1qcqAAq      4  #!#"'&547632!2#"&=!"&=463!54632 		@	`		`?`
@		@	!		
          5  4&+4&+"#"276#!" 5467&54 32632 	`		_
v,Ԝ;G_j)``			_ԟ7,>jL>       5  4'&";;265326#!" 5467&54 32632 			
v,Ԝ;G_j)	`		`7,>jL>        X `  $"&462#!"&54>72654&'547 7"2654'54622654'54&'46.'  &6 &4&&4&yy%:hD:FppG9Fj 8P8 LhL 8P8 E;
Dh:%>4&&4&}yyD~s[4Dd=PppP=d>hh>@jY*(88(*Y4LL4Y*(88(*YDw"
A4*[s~>       M   4&"27 $=.54632>32#"' 65#"&4632632 65.5462 &4&&4G9&
<#5KK5!!5KK5#<
&ܤ9Gpp&4&&4&@>buោؐ &$KjKnjjKjK$& jjb>Ppp        %  !5!#"&5463!!35463!2+32  @\\ 8(@(8 \@@\ \@\  (88(\        -  4#"&54"3#!"&5!"&56467&5462P;U gI@L4@Ԗ@4L8P8° U;Ig04LjjL4(88(¥'   @    "   4&+32!#!"& +#!"&5463!2pP@@P j j@@\@\&0pj	 \\&       - B  +"&5.5462265462265462+"&5#"&5463!2G9L44L9G&4&&4&&4&&4&&4& L44L &=d4LL4d=&&`&&&&`&&&&4LL4  &       ( / C  #!"&=463!25#!"&=463!2!!"&5!!&'&'#!"&5463!2 @@ `(8 x
 8((88((`8(`@@@@ 8(9
h(88(@(8(`          / ? O _ o         -=  %+"&=46;25+"&=46;2+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2%+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2%+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2+"&=46;2!!!5463!2#!"&5463!2@@@@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @ & && &@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  `&&&&        / ? O _ o        %+"&=46;25+"&=46;2+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2+"&=46;2!!#!"&=!!5463!24&+"#54&+";26=3;26%#!"&5463!463!2!2@@@@ @@ @@ @@ @@ @@ @@ @@ @@  8(@(8 @@@@@ & &&@8((8@&@@@@@@@@@@@@@@@@@@@@ (88( @````- && & (88(&  @    < c  $4&"2!# 4&"254&+54&+"#";;26=326+"&5!"&5#"&46346?>;463!2KjKKj KjKKj &ԖԖ&&@&&KjKKjK 
jKKjK .&jjjj&4&@@&&      # ' 1 ? I  54&+54&+"#";;26=326!5!#"&5463!!35463!2+32    \\8(@(8 \  \ \@\  (88(\          :  #32+53##'53535'575#5#5733#5;2+3@E&&`@@`    `@@`&&E%@`@ @ @		      		@ :#   @      !3!57#"&5'7!7! K5@   @ 5K@@@      # 3  %4&+"!4&+";265!;26#!"&5463!2 && &&&& && w@www&&@&&&&@&&@www        # 3  54&#!4&+"!"3!;265!26#!"&5463!2 &&&&&@&&@& w@www@&@&&&&&&@&:@www    - M3  )  $"'&4762	"'&4762	s
2

.



2

w
2

.



2

w
2





2

ww

2





2

ww     M3  )   "/&47	&4?62"/&47	&4?62S
.

2

w

2


.

2

w

2

M
.

2



2

.

.

2



2

.   M 3S  )  $"'	"/&4762"'	"/&47623
2

ww

2





2

ww

2




2

w

2



.v
2

w

2



.    M 3s  )   "'&4?62	62"'&4?62	623
.

.

2



2

.

.

2



2
.



2

w

2v
.



2

w

2   - Ms3    	"'&4762s
w

2

.



2
ww

2





2     MS3    "/&47	&4?62S
.

2

w

2

M
.

2



2

.    M3S    "'	"/&47623
2

ww

2



m
2

w

2



.    M-3s    "'&4?62	623
.

.

2



2-
.



2

w

2        /  4&#!"3!26#!#!"&54>5!"&5463!2 @^B  & &  B^^B@B^ @MB^%Q=&&<P&^B@B^^            + 3  "&5463!2#3!2654&#!"3#!"&=324+"3B^^B@B^^B@`^BB^p ^BB^^B@B^`@S`(88(``             '  $4&"2%4&#!"3!26#!"&5463!2&4&&4@^BB^^B@B^f4&&4&@B^^B@B^^            /  $4&"2%4&#!"3!264+";%#!"&5463!2/B//B   0L4 4LL4 4L_B//B/@M    4LL4 4LL            >& $$ (r^aa(^aa        ! C  #!"&54>;2+";2#!"&54>;2+";2 pPPpQh@&&@j8(PppPPpQh@&&@j8(Pp@PppPhQ&&j (8pPPppPhQ&&j (8p         ! C  +"&=46;26=4&+"&5463!2+"&=46;26=4&+"&5463!2 Qh@&&@j8(PppPPpQh@&&@j8(PppPPp@hQ&&j (8pPPppP@hQ&&j (8pPPpp        	   ! ) 1 9 A  $#"&4632 "&462 "&462 "&462 "&462$"&462 "&462"&462U;<TT<;KjKKj^^^nB\BB\ggg7ppp8P88P/B//BxTTxTjKKjKB^^^\BB\BYggg`pppP88P8B//B/            $$  ^aaQ^aa      ,  #"&5465654.+"'&47623  #>bqb&4  4&ɢ5"		#D7euU6 & 4 & m       1 X   ".4>2".4>24&#""'&#";2>#".'&547&5472632>3=T==T==T==T=v)GG+v@bRRb@=&\Nj!>3lkik3hPTDDTPTDDTPTDDTPTDD|xxXK--K|Mp<#	)>dA{RXtfOT# RNftWQ          ,  %4&#!"&=4&#!"3!26#!"&5463!2!2 8(@(88((88((8\@\\@\\(88(@(88(@(88@\\\\       u  ' E  4#!"3!2676%!54&#!"&=4&#!">#!"&5463!2!2325([5@(\& 8((88((8 ,9.+C\\@\ \6Z]#+#,k(88(@(88(;5E>:5E\\\ \1.           $ 4 @  "&'&676267> "&462"&462 .  > $$ n%%/02
KjKKjKKjKKjKfff^aayy/PccP/jKKjKKjKKjKffff@^aa        $ 4 @  &'."'.7>2 "&462"&462 .  > $$ n20/%7KjKKjKKjKKjKfff^aa3/PccP/y	jKKjKKjKKjKffff@^aa         + 7   #!"&463!2 "&462"&462 .  > $$ &&&&KjKKjKKjKKjKfff^aa4&&4&jKKjKKjKKjKffff@^aa       # + 3 C  54&+54&+"#";;26=3264&"2 4&"2$ #"'##"  3!2@@KjKKjKKjKKjKܒ,gjKKjKKjKKjKXԀ,,          # / ; G S _ k w       +"=4;27+"=4;2'+"=4;2#!"=43!2%+"=4;2'+"=4;2+"=4;2'+"=4;2+"=4;2+"=4;2+"=4;2+"=4;2+"=4;54;2!#!"&5463!2```` ````````````` `` `` p` K55KK55Kp````````````````````````` 5KK55KK     @   * V  #"'.#"63232+"&5.5462#"/.#"#"'&547>32327676R?d^7ac77,9xm#@#KjK#
ڗXF@Fp:f_ #WIpp&3z	h[ 17q%q#::#5KKu't#!X:	%#+=&>7p   @    * 2 F r  56565'5&'.	#"32325#"'+"&5.5462#"/.#"#"'&547>32327676@ͳ82.,#,fk*1x-!#@#KjK#
ڗXF@Fp:f_ #WIpp&3z	e`vo8t-	:5	[*#::#5KKu't#!X:	%#+=&>7p    3  $  	"/&47	&4?62#!"&=463!2I.

2

w

2


-@).

2



2

.
-@@     -S  $ 9  %"'&4762		/.7>	"/&47	&4?62i2

.



2

w
E>u>.

2

w

2


2





2

ww
!h.

2



2

.
       ;  #"'&476#"'&7'.'#"'&476'  )'s"+5+@ա'  )'F* 4 *Er4M:}}8GO* 4 *     ~ 
 (  -/'	#"'%#"&7&67%632B;><V??V --C4
<B=cB5!%%!b 7I))9I7        	#"'.5!".67632y(
#
  ##@,(
)        8  !	!++"&=!"&5#"&=46;546;2!76232-SSS

		 SS``		

          K  $4&"24&"24&"27"&5467.546267>5.5462 8P88P88P88P8P88P4,DS,4pp4,,4pp4,6d7AL*',4ppP88P8P88P8HP88P8`4Y&+(>EY4PppP4Y4Y4PppP4Y%*<O4Y4Ppp        & A ] i u   	#"'&4762"&5462&#!"&463!2#"'&'7?654'7&#"&'&54?632#!"&463!2"&5462"'&4762 
		 

	@USxySR#PT('#TUSxySN@ 		 

		 		

 		
3@xSSUO#'(V^'(PVvxSSUi @ 		

 		
     `     <  +"&=46;2+"&=467>54&#"#"/.7!2<'G,')7N;2]=A+#H0PRH6^;<T%-S#:/*@Z}

>h         .  %#!"&=46;#"&=463!232#!"&=463!2& &&@@&&&@&& && &&&&&&&&f&&&&   b      #!"&=463!2#!"&'&63!2 & && &' '%@% &&&& && &&    k " G  %#/&'#!53#5!36?!#!'&54>54&#"'6763235	
Ź}4NZN4;)3.i%Sin1KXL7觧*	#&		*@jC?.>!&1'\%Awc8^;:+<!P        " F  %#/&'#!53#5!36?!#!'&54>54&#"'6763235	
Ź}4NZN4;)3.i%PlnEcdJ觧*	#&		*-@jC?.>!&1'\%AwcBiC:D'P           %!	#!"&'&6763!2P &: &?&: &?5"K ,)""K ,)      h  #".#""#"&54>54&#"#"'./"'"5327654.54632326732>32YO)I-D%n "h.=T#)#lQTv%.%P_	%	%_P%.%vUPl#)#T=@/#,-91P+R[Ql#)#|''
59%D-I)OY[R+P19-,# #,-91P+R[YO)I-D%95%_P%.%v      ' 3   !2#!"&463!5& =462   =462 &546  &&&& &4&r&4& @&4&&4&G݀&&&&f    s   C K  &=462	#"'32 =462 !2#!"&463!5&'"/&4762%4632e*&4&i76`al&4& &&&& }n

R



R
zfOego&&5`3&&&4&&4&D

R



R
z v        "  !676"'.5463!2@@w^Cct~55~tcC&&@?J V|RIIR|V &&           # G  !!%4&+";26%4&+";26%#!"&546;546;2!546;232@@ @@L44LL4^B@B^^B@B^4L   N 4LL4 4L`B^^B``B^^B`L      L   4&"2%#"'%.5!#!"&54675#"#"'.7>7&5462!467%632 &4&&4@ o& &}c ;pG=(8Ai8^^.&4&&4&`	`fs&& jo/;J!#2
 KAE*,B^^B!`	   $   -   4&"2#"/&7#"/&767%676$!28P88PQr	@U	@
{`PTP88P8P`
	@U	@rQ           !6'&+!!!!2Ѥ8̙e;<*@8 !GGGQII            %764'	64/&"2  $$ f3f4:4^aaf4334f:4:^aa         %64'&"	2  $$ :4f3f4F^aa4f44f^aa         764'&"27	2  $$ f:4:f4334^aaf4:4f3^aa            %64/&"	&"2  $$ -f44f4^aa4f3f4:w^aa   @    7!!/#35%!'!%j/djg2|855dc b    @   !	!%!!7!FG)DH:&HdS)         U   4&"2#"/ $'#"'&5463!2#"&=46;5.546232+>7'&763!2&4&&4f
]wq4qw]	`dC&&:FԖF:&&Cd`4&&4&	]]	`d[}&&"uFjjFu"&&y}[d       #  2#!"&546;4   +"&54&" (88(@(88( r&@&Ԗ 8((88(@(8@&&jj           ' 3   "&462 &         .  > $$  Ԗ>aX,fff^aaԖԖa>TX,,~ffff@^aa          /  +"&=46;2+"&=46;2+"&=46;28((88((8 8((88((8 8((88((8 (88((88((88((88((88((88           /  +"&=46;2+"&=46;2+"&=46;28((88((88((88((88((88((8 (88((88(88((88(88((88        5 E  $4&"2%& '&;26%&.$'&;276#!"&5463!2 KjKKjf	
\
w@wwwjKKjK"Hܚf


	@www             $64'&327/a^  !  ^aaJ@%%	  65   /  	64'&"2	"/64&"'&476227 <ij6j6u%k%~8p8}%%%k%}8p8~%<<ij4j4t%%~8p8~%k%%%}8p8}%k          54&#!"3!26#!"&5463!2 &&&& w@www@&&&&:@www        /  #!"&=463!24&#!"3!26#!"&5463!2@^BB^^B@B^www@w@@2@B^^BB^^ww@w        +#!"'&?63!#"'&762(@	@(@>@%%%         !232"'&76;!"/&76 ($>(		 J &%       $  %64/&"'&"2#!"&5463!2ff4-4ff4fw@wwwf4f-f4@www         /  #5#5'&76	764/&"%#!"&5463!248`# \P\w@www4`8#@  `\P\`@www        )  4&#!"273276#!"&5463!2 & *f4' w@www`&')4f*@www     % 5  	64'&"3276'7>332#!"&5463!2`'(wa8!

,j.(&w@www`4`*'?_`ze<	bw4/*@www           - .  6  $$     (r^aaO (_^aa       -  "'&763!24&#!"3!26#!"&5463!2yB((@ w@www]#@## @@www       -  #!"'&7624&#!"3!26#!"&5463!2y((@B@u@ w@www###@@@www       -   '&54764&#!"3!26#!"&5463!2@@####@ w@wwwB((@@www      `  %#" '#"&=46;&7#"&=46;6 32/.#"!2#!!2#!32>?6#!"'?_BCbCaf\	+~2	

	}0$q90r pr%Dpu       ?  #!"&=46;#"&=46;54632'.#"!2#!!546;2Da__	g	
*`-Uh1߫}
	$^L    4   b  +"&=.'&?676032654.'.5467546;2'.#"ǟB{PDg	q%%Q{%P46'-N/B).ĝ9kC<Q7>W*_x*%K./58`7E%_	,-3
cVO2")#,)9;J)"!*
#VD,'#/&>AX      >  ++"' '&=46;267!"&=463!&+"&=463!2+32Ԫ$
		pU9ӑ@/*fo	VRfqf=S     E  !#"&5!"&=463!5!"&=46;&76;2>76;232#!!2#![ 

%
)
	"JgUhBW&WXhUg        8   4&#!!2 #!!2#!+"&=#"&=46;5#"&=46;463!2j@jog|@~vvu            n  #467!!3'##467!++"'#+"&'#"&=46;'#"&=46;&76;2!6;2!6;232+32QKt# #FNQo!"դѧ!mY

Zga~bm]

[o"U+, @h
h@@Xhh@   8  3 H \  #5"'#"&+73273&#&+5275363534."#22>4.#2>ut3NtRP*Ho2
Lo@!R(Ozh=,G<X2O:&D1A.1G$<2I+A;"B,;&$LGlF/ 3D;a$8$".!3!
.        #!"&5463!3%! 8((88( 8(R282 (88(@(8(822       1 8  %54&#!"3!2654&#!"3!26#!"&5463!3%! @@ 8((88( 8(R282@@@@n(88(@(8(822   " }  
 $ B R  3/&5##"'&76;46;232!56?5"#+#5!76;5!53'#3!533H

Dq		x7	K//KFh/"		@`Z		sYwjjjjj     " }  
 $ 4 R  %3/&5##"'&76;46;232!53'#3!533!56?5"#+#5!76;5H

K//KFq		x7	h/"		@`jjjjjZ		sY
w  "     ) 9 I Y  %#"'&76;46;232#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2

 @@  `		@`     "     ) 9 I Y  #!"&=463!2%#"'&76;46;232#!"&=463!2#!"&=463!2#!"&=463!2   

@@ r		@`r    "   
 $ C V  %4&#"326#"'&76;46;232%#"'&'73267##"&54632!5346=#'73BX;4>ID2F

8PuE>.'%&TeQ,jm{+>R{?jJrL6V		@`7>wmR1quWei/rr:Vr     "   
 $ 7 V  4&#"326#"'&76;46;232!5346=#'73#"'&'73267##"&54632BX;4>ID2F

+>R{8PuE>.'%&TeQ,jm{?jJrL6		@`rr:Vr3>wmR1quWei    @   \  %4&#"326#!"&5463!2+".'&'.5467>767>7>7632!2 &%%&&&& &7.'	:@$LBWM{#&$h1D!		.I/!	Nr&&%%&&&&V?, L=8=9%pEL+%%r@W!<%*',<2(<&L,"r       @    \  #"&546324&#!"3!26%#!#"'.'.'&'.'.546767>; &%%&&&& &i7qN	!/I.		!D1h$&#{MWBL$@:	'.&&%%&&&&=XNr%(M&<(2<,'*%<!W@r%%+LEp%9=8=L       	   + = \ d       %54#"327354"%###5#5#"'&53327#"'#3632#"'&=4762#3274645"=424'.'&!  7>76#'#3%54'&#"32763##"'&5#327#!"&5463!2BBPJNC'%!	B?)#!CC $)54f"@@
B+,A

A+&+A
ZK35N #J!1331CCC $)w@www2"33FYF~(-&"o4*)$(*	(&;;&&:LA38334S,;;,WT+<<+T;(\g7x:&&::&&<r%-@www       	   + = [ c }     #"'632#542%35!33!3##"'&5#327%54'&#"5#353276%5##"=354'&#"32767654"2 '.'&547>76 3#&'&'3#"'&=47632%#5#"'&53327''RZZ:kid YYY.06	62+YY-06	R[!.'CD''EH$VVX::YX;:Yfyd/%jG%EC&&CE%O[52.[$C-D..D^^* ly1%=^I86i077S3
$EWgO%33%OO%35	EEFWt;PP;pt;PP;pqJgTFQ%33&PP%33%R7>%3!+}   {  '  +"&72'&76;2+"'66;2U
&
	(P

*'eJ."-dZ-n -         ' 7  4'&+";27&+";276'56#!"&5463!2~}		7e 	۩w@www"$Q#'!#@www            /   4'&327$ '.'.4>7>76   "!! jG~GkjGGk[J@&&
@lAIddIAllAIddIA   @       	'5557	,VWQV.RW=?l%l`~0    ~        #  %5!'#3!%%	%=#y?R'UaM|qByy[C#jXAAҷhUHG       / ?  %##" 547#3!26 4&#"3254&+";267#!"&5463!2R܂#-$䵀((((tQQttQvQtn?D~|D?x##))((QttQvQtt         2#!"&5463 4&"2$4&"2ww@ww||||||w@www|||||||       	   !3	37!  $$  n6^55^h
^aaM1^aa    P 
  * C g  '.676.7>.'$7>&'.'&'? 7%&'.'.'>767$/u5'&$I7ob?K\[zH,1+.@\7<?5\V,$Vg.GR@ 7U,+!	#	"8$}{)<?L RR;kr,yE[z#	/1
"#	#eCI0/"5#`	"84~&p)4	2{H-.%W.L>       ' : Y i  4&67&'&676'.'>7646&' '7>6'&'&7>7#!"&5463!2PR$++'TJXj7-FC',,&C."!$28h/"	+p^&+3$i0(w@www+.i6=Bn\C1XR:#"'jj8Q.cAj57!?"0D$4"P[&2@www     N  #  3!!327#"'&'&'&5#567676l'2CusfLM`iQN<:[@@''|v$%L02366k67MN        # 3  %5#"'&'&5!5!#33276#!"&5463!2cXV3%
10D*+=>NC>9w@www8c'#Z99*(lN+*$%@www     @     #"'&76;46;23

	 &

         ++"&5#"&7632	^

c &

     @    #!'&5476!2  &

^

b	        '&=!"&=463!546
 &

	
     q  & 8  #"'&#"#"5476323276326767q'T1[VA=QQ3qpHih"-bfGw^44O#A?66%CKJA}}  !"䒐""A$@C3^q|z=KK?6lk)           %!%!VVuuu^-m5w}n      ~    7 M [   264&"264&"2"&546+"&=##"&5'#"&5!467'&766276#"&54632    *<;V<<O@-K<V<<+*<J.@kclGH__H<+*<<*+<    <*R+<<+*<f.@+<<++<<+@.7uu7**R+<<++;; 	      "$1G  #5472&6&67><&4'>&4.'.'.'.'.'&6&'.'.6767645.'#.'6&'&7676"&'&627>76'&7>'&'&'&'&766'.7>7676>76&6763>6&'&232.'.6'4.?4.'&#>7626'.'&#"'.'.'&676.67>7>5'&7>.'&'&'&7>7>767&'&67636'.'&67>7>.'.67	\
U7	
J#!W!'	"';%
k	)"	
	'

/7* 		I	,6
*&"!O6*O $.(	*.'
.x,	$CN	
		*	
8		
7%&&_f&
",VL,G$3@@$+
"


V5 3"	""#dA++
y0D-%&n4P'A5j$9E#"c7Y
6"	&
8Z(;=I50' !!eR


"+0n?t(-z.'<>R$A"24B@(	~	9B9,	*$				<>	?0D9f?Ae 	.(;1.D	4H&.Ct iY% *	
7J	 <W0%$	
""I!*D	 ,4A'4J"	.0f6D4pZ{+*D_wqi;W1G("%%T7F}AG!1#% JG3         ' . 2 > V b  %&#'32&'!>?>'&' &>"6&#">&'>26 $$  *b6~#= XP2{&%gx| .W)oOLOsEzG<	CK}E	$MFD<5+
z^aa$MWM1>]|YY^DեA<KmE6<"@9I5*^aa       > ^  4./.543232654.#"#".#"32>#"'#"$&547&54632632':XM1h*+D($,/9p`DoC&JV<Z PA3Q1*223IoBkែhMIoPែhMIoP2S6,M!"@-7Y.?oI=[<%$('3 -- <-\%FuPoIMhPoIMh      # <  	"'&4762	'&#"327#1"'&'&4?62624555K55	r*9;)x**%<'k5x&iy,>* 55K55K55q*)y(;:*h	)k5=x*&*x?       /  %4&#!"3!264&#!"3!26#!"&5463!2  &&&&  &&&&         1 9  #"'#++"&5#"&5475##"&54763!2 "&462 8(3-	&B..B&	-3(8 IggI `(8+Ue&.BB.&+8(kk`      % -  "&5#"&5#"&5#"&5463!2 "&462 8P8@B\B@B\B@8P8pPPp@`(88(`p.BB.0.BB.(88(Pppͺ      !  %>&'&#"'.$ $$ ^/(V=$<;$=V).X^aaJ`"(("`J^aa    ,   I   4."2>%'%"/'&5%&'&?'&767%476762%6[՛[[՛oܴ
 
		$$	"	$$		՛[[՛[[5`

^^

2``2

^^

`     1  %#"$54732$%#"$&546$76327668ʴhf킐&^zs,!V[vn)	6<ׂf{z}))Ns3(  @   +   4&#!"3!2#!"&5463!2#!"&5463!2@& && f&&&&@& && &4&&4& @&&&& && &&    ` B H   +"/##"./#"'.?&5#"&46;'&462!76232!46 `&C6@Bb03eI;:&&&4L4&F
Z4&w4) ''5r&4&&4&&4    }G   3#&/.#./.'&4?63%27>'./&'&7676>767>?>%6})N@2*& @P9A
#sGq]
#lh<*46+(	
<5R5"*>%</
 '2@ 5d)(=Z&VE/#E+)AC
(	2k<X1$:hI(B"	!:4Y&>"/	+[>hy
	    K 
  ! / U i   %6&'&676&'&6'.7>%.$76$% $.5476$6?62'.76&&'&676%.76&'..676#"NDQt	-okQ//jo_		%&JՂYJA-.--
9\DtT+X?*<UW3'	26$>>W0{"F!"E ^f`$"_]\<`F`FDh>CwlsJ@;=?s:i_^{8+?`)O`s2RDE58/K       r 	    #"'>7&4$&5mī"#̵$5$"^^W=acE*c      z  k  ./ "&4636$7.'>67.'>65.67>&/>z X^hc^O<q+f$H^XbVS!rȇr?5GD_RV@-FbV=3!G84&3Im<$/6X_D'=NUTL;2KPwtPt= 

&ռ,J~S/#NL,8JsF);??1zIEJpqDIPZXSF6[?5:NR=;.&1          +!"&=!!%!5463!2sQ9Qs***sQNQsBUwwUBF H CCTww      % 1   #"&=!"&=463!54632.  6  $$ 		`?(r^aa		
(_^aa         % 1  #!#"'&47632!2.  6  $$ 		@	`(r^aa
?		@	(_^aa        /  #"'&476324&#!"3!26#!"&5463!2 &@& @ w@www&@B@&@@www          "&462  >& $$  Ԗ*(r^aaԖԖ (^aa       ]  6  #"$547 32>%#"'!"&'&7>32'!!!2f:лѪz~u: ((%`V6B^hD%i(]̳ޛ	*>6߅r#!3?^BEa߀#9       ; K  6'&6'.'&'.'&667676#!"&5463!2%40C>9PC/+,+	/9F6(C1$$*=+T"wh(w@wwwU/A*7U1.L4[N .QAg#%@) $)7.3cM3&@www       D  +"&5#"'&=4?5#"'&=4?546;2%6%66 546;2
	
	wwwwcB
G]B
Gty]ty      # 3 C  #!+"&5!"&=463!46;2!24&#!"3!26#!"&5463!2@`@`^BB^^B@B^www@w@`@`2@B^^BB^^ww@w         ^rg_<      ΝjW    ΝjW                                  p    U                                               3   U  3                 ]                             y n                       2                           @                    
                                                                           z                  5 u                                @    5 5             z                                 5 5          @                                                                   ,                                                                  s                               @                    @                        (                                                 @      @        -   M M -  M M                                                    @  @  -              `   b                 $                                       6                                         4           8       " "  "  "  "  "                  @                  N         @                                 ,     @                                                                                  P  Bp <$H<TfT	H		
R

,Dx6\DLX*Dx8JN2f$P`"VtLv$~*h 6 n  !&!v!!""p"#&##$8$%%f& &&'`''(*((()")X)**B*+,n,-z..:../@//0D01~12l233R344>445856 6V67"78P89|9::b:=>>l>>?R?@l@@ABBxBC CDCDZDEFrFGDGHHIFIIIIJJLJJJKK\KLJLM*MMNhNOFOPPjPQDQQR2RjRS2TVVVWLWxWXX\XXY@YjYYYZ0Z~Z[[6[[\V\t\]6]x]]]^P^__~```aab*bbccXcdde0edef6fffg@gghNhii:iziij<jljkkDkkl,llm&mXmmnn@nno,onoppLpq,qrrhrsZsttXtuNuvNvwJwxTydz\zz{L{{|:|n|}D}~&~v~~~v$򃒄zą^d؈z\@zzzzzzzzzz                  @            	   2    	   2  	   H  	  " V  	  & x  	  $   	     	     	  z  	 	   	  *  	    	  0 S I L   O p e n   F o n t   L i c e n s e   1 . 1 F o n t A w e s o m e R e g u l a r F O N T L A B : O T F E X P O R T F o n t A w e s o m e   R e g u l a r V e r s i o n   4 . 0 . 2   2 0 1 3 F o n t A w e s o m e P l e a s e   r e f e r   t o   t h e   C o p y r i g h t   s e c t i o n   f o r   t h e   f o n t   t r a d e m a r k   a t t r i b u t i o n   n o t i c e s . F o r t   A w e s o m e D a v e   G a n d y h t t p : / / f o n t a w e s o m e . i o W e b f o n t   1 . 0 M o n   N o v     4   1 0 : 1 4 : 3 1   2 0 1 3       z Z                              	
    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopq   rstuvwxyz{|}~ 	
 " !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab cdefghijklmnopqrstuvwxyz{|}~ uni00A0uni2000uni2001uni2002uni2003uni2004uni2005uni2006uni2007uni2008uni2009uni200Auni202Funi205FuniE000glassmusicsearchenvelopeheartstar
star_emptyuserfilmth_largethth_listokremovezoom_inzoom_outoffsignalcogtrashhomefile_alttimeroaddownload_altdownloaduploadinboxplay_circlerepeatrefreshlist_altlockflag
headphones
volume_offvolume_down	volume_upqrcodebarcodetagtagsbookbookmarkprintcamerafontbolditalictext_height
text_width
align_leftalign_centeralign_rightalign_justifylistindent_leftindent_rightfacetime_videopicturepencil
map_markeradjusttinteditsharecheckmovestep_backwardfast_backwardbackwardplaypausestopforwardfast_forwardstep_forwardejectchevron_leftchevron_right	plus_sign
minus_signremove_signok_signquestion_sign	info_sign
screenshotremove_circle	ok_circle
ban_circle
arrow_leftarrow_rightarrow_up
arrow_down	share_altresize_fullresize_smallexclamation_signgiftleaffireeye_open	eye_closewarning_signplanecalendarrandomcommentmagnet
chevron_upchevron_downretweetshopping_cartfolder_closefolder_openresize_verticalresize_horizontal	bar_charttwitter_signfacebook_signcamera_retrokeycogscommentsthumbs_up_altthumbs_down_alt	star_halfheart_emptysignoutlinkedin_signpushpinexternal_linksignintrophygithub_sign
upload_altlemonphonecheck_emptybookmark_empty
phone_signtwitterfacebookgithubunlockcredit_cardrsshddbullhornbellcertificate
hand_right	hand_lefthand_up	hand_downcircle_arrow_leftcircle_arrow_rightcircle_arrow_upcircle_arrow_downglobewrenchtasksfilter	briefcase
fullscreengrouplinkcloudbeakercutcopy
paper_clipsave
sign_blankreorderulolstrikethrough	underlinetablemagictruck	pinterestpinterest_signgoogle_plus_signgoogle_plusmoney
caret_downcaret_up
caret_leftcaret_rightcolumnssort	sort_downsort_upenvelope_altlinkedinundolegal	dashboardcomment_altcomments_altboltsitemapumbrellapaste
light_bulbexchangecloud_downloadcloud_uploaduser_mdstethoscopesuitcasebell_altcoffeefoodfile_text_altbuildinghospital	ambulancemedkitfighter_jetbeerh_signf0fedouble_angle_leftdouble_angle_rightdouble_angle_updouble_angle_down
angle_leftangle_rightangle_up
angle_downdesktoplaptoptabletmobile_phonecircle_blank
quote_leftquote_rightspinnercirclereply
github_altfolder_close_altfolder_open_alt
expand_altcollapse_altsmilefrownmehgamepadkeyboardflag_altflag_checkeredterminalcode	reply_allstar_half_emptylocation_arrowcrop	code_forkunlink_279exclamationsuperscript	subscript_283puzzle_piece
microphonemicrophone_offshieldcalendar_emptyfire_extinguisherrocketmaxcdnchevron_sign_leftchevron_sign_rightchevron_sign_upchevron_sign_downhtml5css3anchor
unlock_altbullseyeellipsis_horizontalellipsis_vertical_303	play_signticketminus_sign_altcheck_minuslevel_up
level_down
check_sign	edit_sign_312
share_signcompasscollapsecollapse_top_317eurgbpusdinrjpyrubkrwbtcfile	file_textsort_by_alphabet_329sort_by_attributessort_by_attributes_altsort_by_ordersort_by_order_alt_334_335youtube_signyoutubexing	xing_signyoutube_playdropboxstackexchange	instagramflickradnf171bitbucket_signtumblrtumblr_signlong_arrow_downlong_arrow_uplong_arrow_leftlong_arrow_rightwindowsandroidlinuxdribbleskype
foursquaretrellofemalemalegittipsun_366archivebugvkweiborenren_372stack_exchange_374arrow_circle_alt_left_376dot_circle_alt_378vimeo_square_380plus_square_o_382_383_384_385_386_387_388_389    Rw  =  W                     LP                       gr^                   F o n t A w e s o m e    R e g u l a r   $ V e r s i o n   4 . 0 . 2   2 0 1 3   & F o n t A w e s o m e   R e g u l a r     BSGP                 O S ~lYD
MF x>ޝ Ə)[1ɵH-A)Fٜ1./
dU'&a-nb$%J[`_)qVlihu-ĳyxMqyS0E2zr0igئ=?hkƕ2[V0q0w\0Qa)F.[>dؑ%[GV 4lGG99q80};w	m=7Cw"k?3eYtd`]Tѐc4+`*`[G*LR:. a	Q(a]]$1?3eqm䎤$RY%E@KHS Saվ m|.5 @_PL	lB0fj(42xyt	0:T<ɷ¹
]FUkcD6$Ǒqz{?j_f\6 X)FPN>pud_-0!#SI`FWdʝCGZMδ4Z@&Xe%[	bxGamBKB(%\زKʆOG5	4aB5PKeE1fY!yQ/,0]U,JAy\I֍c-W,}F=n'~ji3c4y]E%+rg'*2*'/0kaZ#g2\62I)C	U!"C|eVx0Pڏ@n.mUUvfBGiL%YUt~YHlɊfh8Y9ņx	 ~jbY=: #+|&V]\ՋӺ͒Ķb WMۜ.x@@BD`xV$e#ln|Q燊,sR,:5DS'v:%AP`K"[X^S\("Te&qʌl-+.3.o&	~g=*JVCeDh4~F)hz{H=UWɀ8"]ӓL23e+m?Py7B\tJ-/Dm9K3adz4]J+Bю@"WU+@D
>K"ZWJ遟@L1:
&P|ŞXtԦ5+1{=JK|F)Y^#[d
NK>N%K( ݘiکt!/J:!D>.h)~_
9
qlFFXN0a	BXZ?wLUk`ɗF!;~i[ %0'4 9>* [AIo
0P|]
鮘eǔ*"*sƐYaC@CuTmAնpV8[57ձ!]:ZѬ-kیܮꂮ~UE
%
EPyoJ3rWoZyRʉQ#lΔND~M6J	\-/V߽mYD|ݟ34 ֧d$!P.P҆_=U suK(PP7pTp1o"ġ`
8M*"@~ZU@YA(RLޢ[#P=@>ChQ QCy;f r@q"8`%4St2ݽ,R>\s*	 0?89j;k'7A&v	`Ŷ~7SAV"dXՐށ]<,P0t1psHeXvd+w8!#Rh/_bhج+waz=r=g d];4"OxxGA~L"rg@͗Z9 bUE׵	d)14NA0IprpEI_IFv x0,YXt0շo)[a|xsZ3ӯ,9{V9&pEoJ2q*H >HsB $rFk[@`দ4d,1o vc[JC6IQB7&(z]\a$q
qwJyKxII/.i1^:F#+qqй+\5zIȅ(:3(ڷ_e5x0M0*Tw0"<nĹ6\BI#S=@BoU]("~iTor/,8'e5R{@mvxL䨏@%z)4r@M޾{nyaRC5Y^y8YDM'c\x<|$̷˪LeS@bcVJ\9J2oƉ6)/ɹ+&k-{͜/y>#=c69R-/Vfe^'W(5A/^.N.U39bTCҰM!1PzE>*,%R\DJ$KT,ИAAgߵEd~y?b"Z	c0&+e*Bڒ27çC\\0E*EiKLwiMCAY;S6Q.9zuB8#ÿI7<-zzeUrHl@|$`|Y"#G@WG*wh#vSi4͔sZIYjb>娵;P+?וdia0$:22b?䁬M,7=~`myڼrBFj`=Vv2 CyvRXDA&j. 7|3	a&ؓI6vl &ϫ-F"ʏL˄ RF^
زҭKf7Pը]ˁwb)In]'9-P&	
Ք?P$ճCCJs׷ԯ#p c-V-FC=q2'"-֋7qJ颫1EыA [.I۾ ۈIh,G
"JU~#6d-LWB؀[2S%ť	85W6\W |o&ETNIQ&YIs vfT+3+sN>gA6]\2dfKh2P@,|Q/kvGpzVX8e[2?aۃr制9-0`=-C	^K	U>'yk\V;{Q2+
P:%}h:)MCk5-$Y('J0d+lSsLZ1OͷsyJg@AJ^&3HENI״ܱ萰W@3kmdHvRsvf|,DH|<_tRHFTV/38௠c"b1[0Oժ"n~"rx8(&<X"t]/n Px } JPOSC[Q#!(y98"u_aX	ldQ:/57!~{Ք*d?SO@U
اYbp):'Y)r/sj8?:/  18	`Ц,te&3`7Yz$2A,#w+/"/	-xMXc{b@BYVgnbPf]A\ gVq,\ku@uzސo=
ιWrRoIqȪJ5}ng"Mg?edr6L4C`A0xI]]0ɫ=х@YG2%bc*HRҠ^,wKJ'OׅxnTD98SǡO$Po5 %#T9ꃷ'A.	hk]"cxcBpc1M0f]]:(G$P1K	SHH	%Gpٰ}+wPݷo]ϥS߆/@9곮9:?c*Mժ)Sձ	ߍ$LI
&.㧰8:!n%\Ä}_/&W1*;LGz6lPnLG¡EE8䞊Ŝ_lę:LݻyɕeibO~>'8).}ERs1ҍJx{\nO(c{NvS0րe1Ϭ$*Qݚ:+çXn48ruP?o\:kN6󞊦g!-2 bXb?A!' xXËu`R{82:哿D%x>o"7L>0Q"f9:Y\@Ԓ\
[j׽5_W/+0aZ #'^8aN:(rfD3H%)x~u@%ZA&CT#3 rMT%v"7!kkRmr]Kwè᏾BЌ_5~;lE½i.?pĎ`ak`y=N$hftxJ6	0J5twt؆ݨV_%U^i} ,q8(פ̫¦	 .8M}	yԀzCHKx#&B"yӔjEZDn)F$ͪa_=H9sF0 `${[	XtROTs )t>ZBbKr7SL+bc*Ȼf4ڠ\mL5rT4WB'FbHmУd
&.P`Gu9FH ĥ*´Kbaz2ZY4ŷ^Z(r?lR	2Y7CA?6͸
]80m	À75m.2tF@pMQ.TơQ

#x]H|N).DAù`P O>fMa>SYCPBT;% E-s<*S!c&rш, &9p*YQ6 ]ÃH "p{	ƃlk`?Ц%Gn(:壐{_6 \ONҹ$x.L:>fI bH(8DA
cWL!f҅ɡ[TBZw "p2)k@uAVcrL/./7RNk2rhV?VWIP\Ĝ2mL'&d!`nbNxnQCPZ\><Eob`L((\')K
	Dt	QRg]iM}4Yhs놰\ib"Pv
\xrL(y@($FWnjʈaG× NG1
?L0i8xfm!8
̓DEmD4WzmiHW];ӥO>Ŷp>k-܉.:.{_Ԋz<13gY[J- ]p%.=@4`U#
i*ȨذLa@HHs*d<(l9_taE$.!̋CvNJ"KY9\e]#*ܵؤ	 D%9I@s/"Q`	S65G#.
&,Y(W1C[P^TjMK5vנ
YB/T)
RpEFG<=c󶈘P%v6vp\**GjDQyᶤXJ&)We( m.ѡf61=I\JӥlUU͖U	:xh~ST5%I<vrwq02j1Vᦩ!9/#.,\LIPr^Jhث .xBŲ,($D8q@\ w24< ]<'B@AE1|l(U(o.lGk4ntx{ 9vc.z[D^E2ӈ{y>pi!jx]\e,k ۳y_hFrGbFFZY!LCGRFpKS/5
'?X-ffXLF,&"eWLI#ɯ&L>5 p*+JMBٵHpEucsm#R|GB^PG&oqűlx\5In_<Fዜntw}|Jψ
j()dӫ5^k#KUD2; Lym>@lB<DD#
6Q[5JBHD\@['*?*` Ty)t`ze&ZQ(q;"X1$8,_u{F25MO;B:Q߈KBU&Tކ`Rpj;MP2^K܂{vx_&G,"`h[g29o1.9_(2#	g}KֺQ~ȆQ=aoug30P#Cm'S#b:2Z\v~`t}ʤZYɿĹ?[H1(a؅(٣D-hCd*"|3e~ZABZc>mG jQ6jj<}ijm0Vc(Ho$Iz"6~7)ί.ex M&2(9i,D4ZF_viC8gPDW=qagE?Xľ	f=N'~V ɭ<GKqYUF,Be2Ob>ϣu(Dĥ9Gy-^-)tn65ψOtڈ9OIJb@zlpTŚ**^a9rV!aS-wzMJϮٜ7/d)쐕TRX$C|)	if@ށ3ug'f'Ac1JEF:BȽ%.Odp$DpӰ ,$kڈ90yMMզ$Pb&Q)Iq
zL  1ppj42 Q1g	i5AيB?VcFFp>̖ڑ4\xCtF-yӰ4UWT|4`|
Zh"hV,Zx `ogC;c\JeG˯6Xas3ȼsK#Ɠt!+h'γu	Rz3;t;o6.-),]ٺ[:4pU7P[87"3(;O2E,E0[%Â{=CR
50HS;+sO'j9ҘIHЂFlODc{D`*i WhmI$fB" (4F4c/Ł1<M=iBcw+>tWT:g	%~0܇UVq&#Z9k]I#;#wIz<:(k@7XP4,wdK<Zo+f,j6y_b0dDԉoi(릋Laf#NzFP;1aF( &bnhk5P,=䖖Hͤ7#A8hVJPV+]*FdE @ȃp`#Of.dtT`kx70+[+^A01dKJq73f.7	YoճT	u,E7m6y/;[X/+0{Rez!엺c)"8lf3=k6yχXG`WZX'!Ȱ҇һO4#_x.q}WRX& ?Xɹg+SC=EIp`ئ]~*A+jÃ6Y2FD&׸@UUJ[Xp8+B>8SE] :8ȡ8d_7!8>|1c!O\.\0Hv5m&nD&H6:A8HTTaOEC\
'Q9MWlBl	3PPހhB(;2u;Ɠ|eP`O($,iQ"`#Fl=h|D8NV Μ]:BIu+za?˝μ8dBa-	S&9gR p)偂0%l BN8(H@uo`}ui%l751h`q?a$&9,<uP!Tյd }Q*E]2,a]v=_;b^RU6*}4YHk<-s)hL.PHsm`0a
, ZG8rG@TQX'zǁ;$5+-CjJjĒ
چ51Y+!,k4M_7e>[fMS)muEV<JP]D4PZaߡKXr'Q&$bHx #4!O`c>42^ehW&<i`(zGZ,~8.Zx'jy6G>MK#T!TEem=GGK%({DBԠhj_PĘ'|!!	BT=WR=!y'@8/*vz;6K'"K(@H9ΤQĬ`S1]dP[;<ԴtTDjǪ}TG>f'$Uv{J[\Yzn$ԶH cC\2s%o	Ѝ{rHgM*X:Y~5ЉP@Nבd`݂O?˗[%
U"<ߴ6)fbmٞ|;Nz<p8?zv،:|&ro%0;LɟPPSe#Q3#[:)ɵpF#E_Q	B6|[c/֬988LH!'XGRF9+9v0w,l=3a>*Xvlj^ =\?醄AjSqR鱦
ؼKA RsAfY\A>7^=FzTh
;(RbF"tRP: _G49s)/F!˖%:
nDT^e OO*)MT\D{,<I$QD{x)CB=~fr,;yKDXkIA6D#%Zs&b׊$Tnf LYD1@di^)lA|nʾXw01e$M#W|n;B+lQUG.P}2]ACxnܚ 6jJr=7gPB:b&
@8`jjS9&EIʎ=`yۚcc99 (,h=1;yI	  D~=7."
b8ٞ~6r
p	`hnk@m,H^YK3#}Xi>#eL|$BӄBl\y5>{`T1L8<Sd`_GuxAmjEC}BpuàJ6?i;f(@`0αtBM~|PzE/bZ2{ȝ;'+w(cA8iW\A71qEZBf': 2?<{		j6T
?!bAz\6VPg>{., 5g=TMxe!|`}ٸ^|oí<C)Z0)Lʚ\"4nИb%mN[01G`qR@%5eyfq
EŔ& UWY*񶑩[8Juq^Ef4j`9FHN
Lmd264TF̄n߄@ÜfMԶ<,Hiۯ Á!Ե́ϤeÁm
uh蝌L. t>vܡehp#5{q
_LD6HJ
	#UxĴһMIAcq8-u{	NkAH),Mw}+"8cx7qM4N4hT((2=ߦӫPj~Jϋ,5VVնжcxqHR :VwcAtc0/j|ҸOM^˕Q-,_!yΦ]+ ]tDcR	C		u/@	Պɲr7dt$F#i5W/_om q_[n4`ׅ'D*F 8;(V`'k&dB)9M '@ѕ\ Spfx[6f?WT9f/,=WP,4m/Ȭd2JhEdnJ8ì@Ч@$SVwk*[fb׼X`a׫
K/e3XC@Nbł	I~8x'C)
ǽ@lsVOm$X<o߂ \eUo/J_l-dҀ?eeE6i<x*t&кpff+j+& ڃ~>X^4Jjb.m~q2m|O
	Mzޤ-W	DS۞z
eE'kqm~ }ܥ'}ݸq&{~X<?Bp_S5ִ*Mʤhܘ#W(3Oּ]T/?,ŖEb AZT~cImH2Rv9^I12Ha$bD:b	eࣁ#fju%*ˋNXug'J'G@ {0u3SG 8<dǁpE>FH D@?踳 [fP7sdz/{HCUu(]Yga$E%fv
 镤w5̲`>nj1b:WC;KH;
ǃ3%yGe/s";R7m\'R 2JOUihÍ9O2juV"xN!8|΂k(,6;F';HXf{dT;	3c%"IB"vܭ5O4x
bISϫ`ꍐG g:j 9	Q@ɔ,	 ATDcxpQsU#V0Aj@"\ SVR]ѻAKʵ9FB~8kل-?Ocacaj	~q[6!Fҥ:9J$x/KD4C8
hs<[z9ĒdZ8i.hdF;>֝$[2 T.'a*},Ԧg7AD{ˤ{(+Q4U.jmb&1+R {pu^khA}$ʷaT 2mgQAq+Uc펊VY RNZHxO9	!}bJ^b"k1Hڋ6ude UxwWoLY Ħh&c]wa4Ϣjz`#r2
l{"=_2TAǝ5QU( +w,&r9D7$E{%Jw<xȈ'Q ,	SgJ;)J1x>~EQأ5&<zHb8b"JŅ 0Lz[ ~0|Dpn+w4,Cܱw)SذouDHC;yjn1Qu-Š"!AO͡ENjV9T*[mZDM&|A?@PL8ƣY )@Oqȏő'_o2_ʣ\?6)TßG[ZnЄi3#QAsº\UFUth5=aZp}\R>SDsP1|t/g'A"ìava¨j7DC&{5:	A
fƝF2=CרkeLcS?f]6s_Gu2! ?okNbØC' &@BG$K1!hN)/ȼZLrqO2#S2ʩHP Ar:@uvK:&!omƓsF:Uj̀]sf(&h+~paPsqY7h@jw(c2/}֚4Cw22fu88@y^"	Wq`,11`Wc,	?Pb:MُqIaǴK˞W
.eqԮCќܼB}ϙ'"t-2p1,s@\aZI2@4δf#c4C`HH-#fŃ
,MWsF	h+7@5HiO
K'13&Dᲅ14ꌷD
}fk Ŋ48r=G9tXeɚn	US	f
x*DNzY]Dȏ%FP",e`U=*IxQ^`p/k23QP}YXВ=2
JLC8o'DhߏnsDy^Yd"~P#PYO?t #E$_)8DHR؉ˎ%SH /;IJ-Clh4k9ՙ|#.%uXáISa/QDEĝzV7k)e6Π~ȝpӨ񯈩oDGSHyHRWkjNep7d @V /%V';!N3Eh1bd . 7Wsc☯6(!8M](-&/C *GZO^$XB l
2c0.ExhLP^}%RU8s/̬
x^5Y;K Q!s"
#۠8)wxH>Ȣ>버Qc"3jOzCt-$! O$)'_$Ȭ9Pcp}vz8YfF?LԷBV4VC5pKk2x+,$=Ru%>j%,Iu+i1d9C/Ł`WB&'ͿKVaWkc5)W 4	C.8?$LπjEphe=3CE^ʖˏ#X稒)KnM7|KM<Ie8#]8%	;^ds[~ɳm=܈wq!mQn[){GqgB5w` ŬBej.pC{q1p6[y0#8)"`XIFl-,aD;YFh?4F1d%{SNv56mBq H6 Ɇ:%Oj(v%+ ;-6Q2|θٰz@
r(	}e$=%S	Gf	
@ydm 
DQ
 hґX`?[SKH`#wŚ.(DJ5k\`zNrq] WG\CÐQTkf&	n\"h2;J;rNs,~V/3`PL\͏#א@<$Gr<x(Eo+d||٪y1OQdbOIEX, ~-Ԟ'.kt ;^n-=tS#jS6PF^\|S
]Җ9^;N0!VPGC5b (/!nsE-Zn?C#;T	XK?	ZIf|m+?Wz#xo,y	`u{qh`uHoeBV)@lU֔{IEy3׏r~_Ēfzhu@H%nTF3|
gOv*p8P+_'<#x6nsNЬ2)WЕ6bz 
 YH1heD.A+@#F0#ꟁnavG-d	n8y:o'ګ(ʧ~Vcos7yCXN!MR7 ;fHw5A1A4P%$Vbxi^0oZA-$1EX|FA:lq@gnRShq7kqX0!*B	,g6_RdcL 'd\Oq9.eP8g1FgdЛ#լ.kBGH*>p`0yQ+nlJnjNMAxM!)lM?;bjۧ}a&n?[HH}	Il)E˃H#h9Cs܍ZC2;'M[qJ}H*?"¹T!OT] ZhowBvß6$zS/-!.it<d2ͧdѢƓkwΰ 0̚B-/[3F4G><w\L|A8Dj/&CKV\vG]>{zpk(_ך<!yW\8EѫtWP|AGHlQNVb.PVR|Xb0G֪BQ"C|[߅p0GDDqjfi% D n.ycjS8[%'QnR<2BS|R9F#81w"!pԞa-!'hr(qm8<;f$6t2mϋY.wX&еB
*#RKb@v~	Qe̱gYk<ӫ5낲.vfiJp10+@\LRXK@r`I?v757̇5>5S<"7'OOWjfͪenz<r`߾IrgRCԉƵ`QG3.7Pg&Լ/{ afi!ꠦb=盆cH
8M'0Iԁ$%&D0TĲ:215#.#OS4& {!@CmĈ(_21V.F
=֠͑ %
7yXxM^cAr/J(Gس-\8
t%$)
/<,QlTD/j]G6Zmt1(ja}K@3,"	mD)O6huڛ/hv<T@ĞMN^_Z&ƈpc*5 VX0ƣV%Q$$|(y>)&78~z@Tȋ-E`@_8v | _b!
ۭ=:>Iezp;,	T3!J:XxjA{M@Rיg^۸ ~>;vLb%4/[&+a9[s⻂$++gv0XtMD^G]e2K"x4DG`9-(Ez{(Ƴ0:N{+jyU:@h/_OhT ]Nv<}i-LoP;^h(`d2F&$pџF]\_jQwK>@C-"V=+ ՠTyE;[I}ǼYTkTk0z1AC>Tu1J<6.,GWiITŧRm1ecvSt6ҖVbSjU.x,]t~aÐ! GEx?ٻ')ߍ561I֫?g [?h5,E~K@ܿa6[dױBENfPdvڢ8a v$?ڄȁ&Hӑ%"ځDuTd1/%ir#~av H#w9VaiiVcp$F{(k(TCYpљ@" b(d*(pAZ;}(%W 3]>$
JQ3'nJ+ 6
Q"SR^V7ن"(uqw 0#V=Ԛ/ƘdyGL>$V]Pם69 ȩbnДjM$hGs>㳘?ufzPOQ0lNơ΅^ +	Ħ>P&B2)8S;yMGȀsȍBHB3,Lwq\f0F-sQA
(G.ψ)T9_{]wP;*$Pې@Arq=j.Bih)cR/Ui׽n``oKA6XFmW#<]ύn0$<AtdK dbx' e I`>x(\~qPf22)<'0RUb)C4HMqZ!9KSnB+x<ag6&eR!Hqy
PF]$S5g?Qs#Kn@.I{i_Vm4
QZ_iW|xV_j!fÀi۵F~ ?nqO7L1+1 -U~.g<\6e4U\dH F.Y{&Vn&n,G],bd26:x	׭hl,AR8٨Z	?~@R(\}nK|!ÐT:_*=R^,ZX8ʅ[ё"YFK0A>H&v/2F+:$bԀBR	x6ߧS񪶦28qF<
GLOU29/Շ(SUHc:"&e2鞶yvQL};L-Q@\s{"<ؠ<>2t= QFHb8$s	gzzA)jOT`)\Xyu,"F2IK+a[ C 2$1ڧ_͗픐jW`"{d* j5d,qD3eloHDKڇ5T~tm)S$PJםh|f, UtrHNX?1:0&$Pq蝶(r[	3]M1_ALS(QHa8HN53c3}>L۷p<6R7ؐ2T,289ͫ{XQ7>j*UQ\G< }"Jx	L;b{vr3dfBFd(" l-@* !WBb+j$ y܌8D&)m⢽j=
Q6Q(2j<`=άv?CTdLC4o>xLghbESIXg&4)`Y!f޵mi"AAG$4K(0 ċZ׵b7w72PR$!iw 7EKw*b	Z&c E6chDtfG'j5cJo7*<-̨i!3b"a @HO?̯OD].q;FĤ+,ey;N)sbf~6Nll/n(|$]3H'HK$#F~ <)e
kqD ֢K͇B<hEjQ*Cυ!\)4/((}/曼H1&h ݣٙbEآPb?(Bv,.gB<_֍
: ##DvǚffԘ: *.Y[+h>^nW7E
Ѳ'ȿk(6Dyx6P>]W$	Sp<^P&{VjyzU<;|o#o_F/"dx jt-oNxXR832H^Gl_dFcM[Ê,6@Eyz(0uE5>iHYAjIt;B"gU?Vۮm
m:=:7^Ng{ӑe`]bzW|,*𦞣}3e{,q4w'28 4t1=D<0@<WSTYzGF:
QxUPXmY%!;kgis$p܉SwPO"P&DAjJH p.lN
9=ʥ ϛV:OMd\Q$DT@K<^bDƎE'r7}V {GA?`RR>_ER9"v\F_-+ec=cֳ:3ơ#.,Z5g7p\ԧlSܶ.2t(+$Pe<2&gCe,v3g}yn0_碞P_ `ZN܄a3B)2'Z9g*2_C񞁲DhTR	)Kxp)lRDD	,8ƈv1'Lazoh0-mQ=2a\g!F-rw.*t[Zl4Icrs'@	bEq5G|wWmEܻ|ң7Dby1JG=EHҋb(ER߅a_5$| ZBQj 3E ,6Gk{1Nyape(l(8EĔ)>HEE''⟑OmreI3şE/P|2LW8O(hmFcMpA`DP])nϕ㢿'ݴL|Xzr8(}JzCh+,+bq	(-cC;+,q=0uT3ۣqllb[:EV=2Xl^xHlhb
ָBG@ LZuAVJێW+A%=A.!
b_JdG2cGwQ	NlhV7x! #57$rUQ՜x` __!F6l{tL{NXl䕌pޢ"u6uHR A'Ш&З]RkلR+J(Qy hҭ3@H4X "(qWxDa)#Eu䜴w!ʈB?ak\
D>q(GXt m*᝘xω;>t,%y73h1u|Qn(G-7!%t:>ߠ.u%8K4*bOdkh#l^툅-My5	L  M-K%rD^?TCA
H4LaF&.J?mfTc'"FBj):+Q:P&(Hfl(.(4AzPxb"gJC"TG&sFQM%4#th^2g?wթ௿LswȤS1uՇM/p:ٛYOE&/KΟSqĎ%n*#člBCVj0<+s@< Lr0He~,	lU:,xp[{m
P0@N>]r l7@qv$ߙ:	.jԝpH?g@šEiy<B!xQ)Hr8/ Do$P3`PGW!흎\ÉӍc]XGjN{#X=$_s(qV6 #'T`[%Kq,q?be-*0C3̽?6೥;S%&6*6b [.,8[8ݾ.	/b@)Q
4s! P3 Imh.sUU8}jzm%Nkx0-߸5^ÿjU@h̠:6@3f͟Q0~р/2k@ tw0?x4tT/˟63oN9#!?N"ͻ`ԠuxT@,, :3a1%!)}!j!a\XH`LYN1p$` zN	AX@!s`ˋm; T	8D4MR}vMOR:r^x	0gn鶁HcR5懤郇f"H-Q+2tX_4`k OH1=bCH蓑J֙s9|IEݢ,0QTrmBCwMn4.eE4ئI+ף8z`aK!%TjAD(-apOYAe K*a$hJh=ˡ/cd cr:K'㞗S_7Y
da0o@$Ga!Lv]9yk\r}̚ASFĿQh܈V*JXҶ,_os#HQH ^Ń ]5c1B3Ib#!I5 J:YiGK3
QuHq<7_M3R5AOT*^(T|14TOY~R\EMz&~u?HiW8*0A͍%KAɶ:D-# w49yV.3㟪aZ%u E %'d#~ucfid@Rl`CKh˲hCkb:Kl˖t4>mё?F9Bf0G
syGk{W	o\
cTT4}ϸGbRKN$0ټb$[KCɿf5o*d}K ӏ\ #z-|
wJA-Dlaf7륍NI,YHѬ^L oV6{IOT'-,t3ABM5,v]e} Rm _*bs+u_>*1:ed9IX̔K$lrͶ^UqՄZ`.:]M
ЈV"<u'M垙qT[́(uRAoS(AM6%H)ʄN%/s#OszA2I$> Iai)ʕ_Żnq²{g^}VsyԞ]r%ZbeGKx7êWUXke #SJFBVHHQ6a
hSXZ¡J.eJ׿=uUQSP(LV Z2zim7ZݐSȞK`XO5Wz\['Vѣ3QПØGmVrL0
ZW= 2bf!wbBw//p	/BÝr,BK#qQ^Tre3K^qUK`p9NVh-0BjB `cCҌ͋UFU6_]I7x~ECLza$pro^[HOFAsCa<.-/quuD%rlfq>md&m)MğeV yvSh!=QB&8#&c(QZ+q۔|˘r$z#5o\OTv{z"bN{wao0b%v<`_rv(IZu{9Iy);R|?	hJ87.-(8=`?Y<=LfjgwQ,aϱYrm?eqLPvC@ 0  zXYJs}<jDѤv'-YoOO^1̓ڝ/\*8zor
FgfH#S<
F)ܪ&CYfw|``@i Q<&dd
hKCY"n^+~: 3,\h&uIYP6_yuabH:YH1l1Bٌg"QD$(ư`=c(51d1oDH=yBeQk9b*QXݽ9%lxl'OZj)p CU6@xPn^datr r[ *+(qaP'y}b@j=;0"*(۞aA @N=iA1'-#V(xҨQv!\ dAva>e_!	zVicDۯ1C~e7HpDk+aOi4v/JvG
Nx!	aZEHq.*h X	a܀gPo$Zagg$
UR~4`bI,G(s0XiC,:	jfZ5͘ƶJ#zF_(uf8iF_ͤ x\Ac@@YSx,)KF%c"E z4,t yR,CǶ,)	2[1,>n*q;K\Eǳ,ɗzىй:p["86~a^IDRh&²Sw\'= έk-WsBG,(6U[V.:`]@mi3uB$>,y'9ftH:K<13=KzI .]oxEzp`v<K|"| pM;Vǅf-.l1a/S@Oɯ*!PHVRRoEq*ʈ|SKiJt58mk<_ Pkyy=򲥴@OdK<>?E$b\ !
+;
;Vl1"eY+kYDLwZeMx($c|L.
 =ؗA5R]YU2%1։ 	OQ%&Bɠdw#\O 	sZ?~پ_XD)͘A4?b;\/}lwgԻz}-0d
}(<K<G\dI(¿X+RCXlGӸ2	B^Ȁ㚯`.8EMHނ!RaL-2,c/a|o-LU"0l t~YjȪqF%BŵBJ ^DFaz 5t[wcW!HU>!	Q.l:ަ{}"0@pI8eRb%Zͨ1-[C5Mhj%l(zh@aPbtqM%WPG^b{0V{]hmnW$>?2(QBu=o::Cݡ3ߎA
JJG8r$Xü%얏uiʡi]SXP=b^7dPJ0ȄJ}͒M)nHX0kv`,LA"2-qwSyX"Tt0d`,1m2DKBizHɉ	s(^fz|r&c@Ι@tN]օ2Z|XV[ON*D?8cff(
WjYF dEv16/]K%ZPN5&P2P fLօDQAr1'zj+Bbi"N/(T)Ү]¨RJ: 	">YK`J襮7Fԥ;w; 	4Ϣc۴5<''
Tw8B")*q0iŵ'2:XCiTe.Ud-Bb\f??TޞP_%(Sm.;<=<~xֳޣ.45/d Pa>E
ѪLۦ >Q&v@JI#ãbZ!:@s]-3)dJ}Q<Xw<aAP[yEhWLp:,?,p <bl'ؔ+j:mŤdm{ȧ0މN,V¼E櫙q>)Vq|u/rˋ7jehi҅`n/qX1B#yTHiI@l{n#	x#E(:9+PF}ѻTdd,w@%\"E$969tݳ'DRD@Gr@$׶$;A1=}gյ1}%a_En'hx8"r]͎98)K.1وeQwjeȯJOׁ-.tѱkMr* Zm14ٕ49HX`:$.88u!U!F SF	2bZ~%Bh ~*༢E$pŖl4AO*V)JMSwU֒T;%^K[{9M zgȋ<M.[(>D׶+20ߍijI@30u'2$>ГyFF;'>뱁e+*%cLq ?P'φ,'X֘%ibp*HWŧgH[;=.߮ BHןVNcfָD2A;c		{!dG|`kAUjU!%EI 'R6;9| |Wgc4"y1D˗҃+T"mBcu,WIBmi*:-4#vEN#c9%g7-_šnGk	JTkhT0)L%pr%1GȘ,yHℵP; >8c:[" kSqNބ"aFА11ymϲùPpٱ!f4'2u\=Y"l\ʰTBquIh 5z
6DpR>Sԡ8"[c $'W}%5+@Wư@nV?q3
#ۤAH?%ֹnS:=4	S!!TPV]đ({0LwP{0?O־}ECr1G>g]xϩ# qEBf]id0R(M+.%lC
CRJx;Yhc<2!31$@2HX"xKCb}6w^ejt9oR'1Ba4&E%l4CGyNd台2YdJK"
9\JN,?>:/ ±Lk0h7ecUH!Fs.u6	]$3
'#*kRE9G⧴<÷yH]$;J>,HƖ B$Z>MVWV(8F)0VS^ ,JҞиX.^t.3Em`]k^h[;؈,D]}r`	5\J] @yY u
	&`f jH刲a.>LH!8?F!q0orz׀2PeB	}BAV;7Cfᜢ-ARPƌ7`9^QwiAxm-P
$pRj_숽zPc&$0 ܛfsxT"~z)Zߠ
@G6HW# i܂9ixlFN~Uv;GqpeqlZP],XQBV]n`PMxGWP'Uy0o	rRQU+o:2+2Rk9 [" >>|]Y	+PEu2F2_y:gkc>宲RHᝢ<Ƥ:9-:SfH	i{r0\eTㆉɖW]q Td'@~"E8 PZT#+H\~|;;Wȧ,du/ءhۼ|'SH2Sء^2T`/$ Rڱn`h?ad-mR}x\s¶m:e%ųd{5fv%)60գ&%MX,eqáhMKDg5fu#P@ =<) 8׎8u6<,0ЋRA{DH{&IA 	D'm
9
	AJT6+5a
Mv|r I`wBQ|:*`40erG8(ksy\BZ:2[M|ƄE;@:"'Q^tK@
j
#T
&jJ/wY k>F/:d6a:- 9^pTi넌zq+߲_vF~ojQZ!R;3E`f^B!ё&OWѐB8-pE%YH0Mh">.H`X49V֙wR7F *:$s̢<*	$鰪H{7_3wJwqLq˝m`Pz' 7̵;5ӶAN`չBͻIP0]fH5lO-r]i.^ܲ?Vҹ@X"t )!MpC5Q]hY@iOÒ]8	/5A0R7Fs TyjYHp%-4ab5TzD/+ْZdINrv_>e_vS6YU$/ڟ^j]+cxʘ|f2z?]\.e3&[5^u}ŗ8Hy;daD3V&wjt鍒FC<̅EI,pMҋå؟_+>z7C3MbLRfi`u}R
n/7UAma5pN4dGH6&i,!|~;AfJ(B9-춝s}8]F.},̏Ex\ؚD7}˿ǃLNBd(rR&<b(7
DR/MFFiys|N1H_eY`삇u+Ǝ/	qhMBqut# %H@>zTh"`$<s7R70kzU9PR]yiF>  ,nڹbѹp%	W[IW%S%/{T ś獾0@<PU/x*%Tj-P,R)A1BzjpɍJєѪՠB#OH9$'I)Xc=޽ @-Ceɾ=QkU; nnnyL,2e&$qKGQwoP2x|*zܷk2^PV:Q>8"$9#e׵S|K&U]65aAaP|'ר]",f*_/sR?{,,RMԆ~@h?d"H fMu>a@p+a]FPٳVv1[93I\;bPXM
@
 Iue3ЂRʦ˸wQIB̠H{ɮ?$miEm(l61!Q1v0Pn'f!Ƽ5th|n\f	8P
@ijbgs|pf]d)43 1m.yDOMS)ia@ `#y~2{a\<&eW=`3),Ńhp`q㗏=`4y
1x[`)c	\ek) f@IE*1!Uce8L.w;Ef++pikP {X#RYH٠mz݇@fN>:P*!+.f1Y@c?!_ʃ9fBq͍>qį8< rTaܢ$װ8D>"XclY3S@.M{G.4HxHi. )`rԬCM$UhԻm<wHh prsrPp[ ]q*m0G-lf|U钵Ƭ/Tf0}ۚW]"Pvĺh!v~&\*FM ׆`	qEL*ˣ$ WZ99㌱[TCm!=G }#eiM,6`6Rɦ!j Q?g$:.q)5m.TI }!`8+.DAԬ[_Y"$PPodҸX4РDCȎV$6!)]<%'[2!X9&|m7݈ b7  s¼C$`j=^+$QTJ&;fC@sAqNJuyYjI	Q1=0'/ea-77~NP6$cEoy@G@6RWf^eEͼnBK(φKn֮p3⢓1*5NSF8lf	U>9O)x?!V|j,O)@?xa[k]әHZkn@e!c
^"ƛ"x3`:Շ=*Ioy`JѡO,ʩ7¼6x IDMH58 nM#Rhr&5,uN0
tIf`wsV2סLcI: 3H߰H悁niwBBq&Q7n5 f;ܦqg>]Hr$ՑxlLmN'K@[$Q~Ʃֱ<RD|+ǂgt4/	ӥX>҃:-. e?%aY})evUt5%
(әWj;Xunt;<;MGør'<#A7ӢV̶pRPy!sㅇ"5JjWWri# }}(ySxar-4Rz7EN:l]ʗt7@fB??lu\vme~8Wr$
\Ĭ1"=u4?(r&M0ap7'NuweȈt¤%=MHs:/&ac$ndneG륣0Z5A+9LP:oF0qуg~ݨ)hJ
ɜ+EEf;wLQuXݹHCC#$(vo.H9CZai tbJ\C-݇< XLȨZ

p!ۯkiքk$ҪAP u%&(C䯄*U
0+̧`VCEUΡq]a=?x bA>nFNHLD:j+b8}JTdd0@eiFr}*d<R(d~F
WCR*ǑGc1`țbcR3%<+@tGjw=sqBUo7Țf UU*w}`&o3
85a:	WZ5)IuA _*
&)8g]5׶5h1BvhRKO?d]qU&26h>; *nZF4$$<8e.GGǿPEcpB#:XI 
$eڭi4wS368Q4^ky9"B EYK' #.et_P̜]D8G9X>M	42ơPW2D)o&?= STƹrx#0Ru&AJ<=Eִ9I<Q
AO
iFsc'J`A/rja;!)DMSi\j쎸5TJwΛލVbuAK`!ԪCN4BvAԉSO&BRxnc~X6X_0 XB~w(}09O0Sя>eZ-`IYeΩuJJ;RdA+]KH:Ycz6oQ@kjrNfpZɕpe%sG$duj8C
* YQp14]< Q/{(܃^Q ź^!M,E#F\$*+Ntt4Y/&d2!
NY$:4Pæ7CU	9IiCuX_m!*)R#b	]9i:\El}4f@'؎˃BaEKA.&1"y|FO3=u=pe MCqMTv4_ضdrwXk0DxqKy후6#(uZ-[m#38G3A+_Ⱦ.,
GYk	.y¹0:3
zB}XhqgMIG+;ԾRp
lӈI$~>a
4
0P݀,N ICjC(Ĕ^e_5={,Qr8|3jdλf~(땏dŞ1#_ԉx$iN꒙_$cMZDzIW4MgOPОt*rLVP4CҾ=:\/5
	 Lトiw&Liѐ54Ck?7Tx-bVaif7A0,v6Gy.HA 2tLaAxh#GXxd-kOhLw$7TCmIh BRѭ(3R2ȵ޴J"Aw07	8S$Ju%!8dd܉-Ɩ<Ć@`\tI5>j7%-s$b1+?_6f\p;NWAt$BL$M}?wVwQq噩:!fB24ңPe
{؜BNqP '̜U0>#+"oF&T)|Uп?9a^G#xџe1>'I]Z>wIWw@g=_gNG
_N@
ftV,x2CleybMЌ5]>R& ZG[Y6{k,ēIa#Z>nmQ3GzW2f@^=wm0XsϷQȹ% y|a
m1ޜ.PĝnCtR6/1r 2mւ:
dДDV,#*5iN1̡3Gt3. 8)!ٲňknwR'D<D"zP2hyšm@0(C	qC}X&vaqeDG|jh}e#ZvG'G";G#Dpzq%cMqIU_4uu_jnaMksȧ%e_hmϖ0@;.2LˍR	M P@[jp!`]jH!Me_ `5PMAc9I\Do[WBrsZaa]NlaB(ܫe~U^x@4WBNJލ}kdJJz 5Ȕ6!Crxdio:
5,e 1ds
:7g'әYFhYHn'OcUeF(u|YASX0OաW9'm?UdBE{9D\xAN' App/
}fσ]ׂr7}AE{r]IkRW'&{\4hZ\U0ix`ܮ/n.vťl1?
\ET[of&TXdxS[)6 ?\\)霭3g	I"f7E>ZCl@]D;W7*ᎨjxHE[Ig)ʉ4	>:'ZBOf1|$]w˛Rn@#"I)a=9WLd"]dFl9n(w#:a0Z󀌎7."!.1]R:M>{
52?5YB>"$Hb@penh7oev %0,{p(:/W_Jn'=:'A^f5,dD[V#7WcnL0gB1g@B5PMs0 L#̡ "yIlcƷ|m;xo
`G+^w3LiyoŊ9bYYS};12&嗦Є^tR^|dƓ݁()xUD!F*dPV+$D5U%0í8`0
)ZM4V>ZSZ
ak D&
#ڼ+a.74hOЫ!O?ıi$4B$xkDb[@&gSQ^slns8ku&'3^{; i xZ5岠Qʹ{޼=u&h'.aDQqKrvSLPQR~U+$N&q	D%Ka;C8Ə$zKȐ 2/8"d` tdX<pyP#.f`Mr4e]q.$Cp5\3Hd`C"'t~C0	B(PAf
-`| j
5)@k |>R}QM_|1[嗨~hR6z{Ƨ_t
WF΍:R	K6n	w'nz `%e;v-zgi^4QWz 嵑AYɶm6ѳ`,l/gRZ->)^)!rnCfJ8m㢸e<04oz\Pf4xj>-xvC^JzqU_/6KHIe@cTVMʊi)MgwA
Ib޻cvZMDVDXBBb8j>M$fT$8't8
ـ !.yp5%YgLH/4m:B&	6~ gv{j{C M=O`{_%Lghڌ*[G(dɀ	 \T{<NfTQ%rz ;$>Ԣc|z ˑz2_wR_t1KS;9\AQ0&qtK+X$& Bura3v^%d9 8f91!)Hh/vЊ|zBB;r&+լUϷۑ:EΔJ<W,¾ZqFv5-쒐%-uΖuN3Zt:<bA̍Eru2~sgV1~r+B~*FN/뵦qR)ܪSҤ'f4%P|$;=f+Ž-bgX0`9bb< L!7iЬ~Yif$l){,ZpA@3#_A*a@ ! nf ?C`@FT}Ĭ)9$Y)dl,o%d@9ᷓ4`T 1Њ 7<ywжǙ\Bq/O)$-Q-:/SUeҌ<AM6}ږG~qgh0Iyzb}4B;]WQɏŉ=E&'YݖQ.L/$	_qUqG1!`TNUhԹvLn.7M[bfa-PsA+82q#Q,tF6PFzs*z*ZaxDl<)wh1mX*) TUv?ߑС=s.ELz(phRBNDX2b)e*e	1njqޙ.lfH S{Ҹ	2'H g yF9әVܐr Ihg뗴_aHR{Ӹ>ꦱlyҧpپÄlR6.B~%lG.PdP<\Լ(Z<Nygt2x
'ŉ[V#K)v5d{[vBXG *a)ܱ)?23k\Y#v"m!)YCI"tY
Ɉ%h7?P1<1@gLC1ⳆYAI9FWelHΧU_%.Q+W^AIm2LR#njT!ďQL>FAX"~w'8Ȑڢ%mlY(I$XN<ݷ+;sJ2?8ln|_'΀&T,T:1zrPw(WDA9(N,%&VވĐ4e'!#7;q5]2$;#o`.Gl#y+Gl*X@'Me)rCtx;,Cbdѻ"6sPWY
%/͠J(j9)!>XdؤNx~	iEh P8,9]b9inhhNkS ܆'K>e/HgC$FG)C221eJ9/W-pLy4Vg70*]E/r5R6GUW ؏.:6c"_%TIFD,KPadٌM&*pKP\	5~BD@A=XdmYcљ]4!?&7&vLH /)z& aa޾k        <?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
  <xsl:output indent="yes" method="html" />
  <xsl:include href="chrome.xsl" />

  <xsl:template name="content">

      <div id="content">

          <h1>Markers</h1>
          <xsl:if test="count(/project/file/markers) &lt; 1">
            <div class="alert alert-success">No markers have been found in this project.</div>
          </xsl:if>
          <div id="marker-accordion">
            <xsl:for-each select="/project/file">
                <xsl:if test="markers">
                    <h3>
                        <a href="#">
                            <xsl:value-of select="@path"/>
                            &#160;
                            <span class="badge"><xsl:value-of select="count(markers/*)"/></span>
                        </a>
                    </h3>
                    <div>
                        <table class="table">
                            <tr><th>Type</th><th>Line</th><th>Description</th></tr>
                            <xsl:for-each select="markers/*">
                                <xsl:sort select="line"/>
                                <tr>
                                    <td><xsl:value-of select="name()"/></td>
                                    <td><xsl:value-of select="@line"/></td>
                                    <td><xsl:value-of select="." disable-output-escaping="yes"/></td>
                                </tr>
                            </xsl:for-each>
                        </table>
                    </div>
                </xsl:if>
            </xsl:for-each>
        </div>

    </div>
  </xsl:template>

</xsl:stylesheet>
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
    <xsl:output indent="yes" method="html"/>

    <!-- Concatenate items with a given separator: http://symphony-cms.com/download/xslt-utilities/view/22517/-->
    <xsl:template name="implode">
        <xsl:param name="items"/>
        <xsl:param name="separator" select="', '"/>

        <xsl:for-each select="$items">
            <xsl:if test="position() &gt; 1">
                <xsl:value-of select="$separator"/>
            </xsl:if>

            <xsl:value-of select="."/>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet><?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
    <xsl:output indent="yes" method="html"/>

    <xsl:param name="section.dashboard.show" />
    <xsl:template name="sidebar-header">
        <xsl:if test="$section.dashboard.show != 'false'">
            <h3 id="sidebar-dashboard">
                <a href="{$root}content.html" target="content">Dashboard</a>
            </h3>
            <div class="sidebar-dashboard"> </div>
        </xsl:if>
    </xsl:template>

</xsl:stylesheet><?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
    <xsl:output indent="yes" method="html" />

    <xsl:template name="sidebar-footer">
        Documentation is generated by <a href="http://www.phpdoc.org" target="_top">
        phpDocumentor <xsl:value-of select="$version" />
        </a>
    </xsl:template>

</xsl:stylesheet>
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
    <xsl:output indent="yes" method="html"/>

    <xsl:template name="sidebar-section-packages">
        <ul class="list-group">
            <xsl:apply-templates select="/project/package">
                <xsl:sort select="@name"/>
                <xsl:with-param name="parent_name" select="''"/>
            </xsl:apply-templates>
        </ul>
    </xsl:template>

    <xsl:template match="subpackage">
        <xsl:variable name="package" select="../@name" />
        <li class="list-group-item">
          <xsl:variable name="subpackage" select="." />
          <span class="package folder">
            <xsl:if test="$subpackage=''">Default</xsl:if>
            <xsl:if test="not($subpackage='')">
              <xsl:value-of select="$subpackage" />
            </xsl:if>
          </span>
          <ul id="packages_{$package}_{$subpackage}" class="list-group">

            <!-- List all functions whose file has a package which matches @name but no subpackage OR which have no package and $package is empty -->
            <xsl:for-each select="/project/file[docblock/tag[@name='package'][@description=$package] and docblock/tag[@name='subpackage'][@description=$subpackage]]/function">
              <xsl:sort select="name" />
              <li class="lit-group-item">
                <span class="{name()}">
                  <a href="{$root}files/{../@generated-path}#::{name}()" target="content">
                    <xsl:value-of select="name" />
                  </a>
                </span>
              </li>
            </xsl:for-each>

            <xsl:for-each select="/project/file/class[docblock/tag[@name='package'][@description=$package] and docblock/tag[@name='subpackage'][@description=$subpackage]]|/project/file/interface[docblock/tag[@name='package'][@description=$package] and docblock/tag[@name='subpackage'][@description=$subpackage]]">
              <xsl:sort select="name" />
              <li class="list-group-item">
                <span class="{name()}">
                  <a href="{$root}files/{../@generated-path}#{full_name}" target="content">
                    <xsl:value-of select="name" />
                  </a>
                </span>
              </li>
            </xsl:for-each>

          </ul>
        </li>
    </xsl:template>

  <xsl:template name="package-content">
      <xsl:param name="package"/>

      <!-- List all subpackages and their classes -->
      <xsl:for-each select="subpackage">
          <xsl:sort select="."/>
          <xsl:apply-templates select="."/>
      </xsl:for-each>

      <!-- List all functions whose file has a package which matches @name but no subpackage OR which have no package and $package is empty -->
      <xsl:for-each select="
          /project/file[docblock/tag[@name='package'][@description=$package] and not(docblock/tag[@name='subpackage'])]/function
          |/project/file[not(docblock/tag[@name='package']) and $package='']/function">
          <xsl:sort select="name"/>
          <li class="closed">
              <span class="{name()}">
                  <a href="{$root}files/{../@generated-path}#::{name}()"
                     target="content">
                      <xsl:value-of select="name"/>
                      <br/>
                      <small>
                          <xsl:value-of select="docblock/description"/>
                      </small>
                  </a>
              </span>
          </li>
      </xsl:for-each>

      <!-- List all classes that have a package which matches @name but no subpackage OR which have no package and $package is empty -->
      <xsl:for-each select="
            /project/file/class[docblock/tag[@name='package'][@description=$package] and not(docblock/tag[@name='subpackage'])]
            |/project/file/interface[docblock/tag[@name='package'][@description=$package] and not(docblock/tag[@name='subpackage'])]
            |/project/file/class[not(docblock/tag[@name='package']) and $package='']
            |/project/file/interface[not(docblock/tag[@name='package']) and $package='']">
          <xsl:sort select="name"/>
          <li class="closed">
              <span class="{name()}">
                  <a href="{$root}files/{../@generated-path}#{full_name}"
                     target="content">
                      <xsl:value-of select="name"/>
                  </a>
              </span>
          </li>
      </xsl:for-each>
  </xsl:template>

  <xsl:template match="package">
    <xsl:param name="parent_name" />
    <xsl:variable name="full_name" select="concat($parent_name, @name)" />

      <xsl:if test="((count(/project/file/class[contains(@package, $full_name)]) > 0)
        or (count(/project/file/interface[contains(@package, $full_name)]) > 0)
        or (count(/project/file/function[contains(@package, $full_name)]) > 0))
      ">
      <li class="closed">
        <span class="package folder">
          <xsl:if test="@name=''">\</xsl:if>
          <xsl:if test="not(@name='')">
            <xsl:value-of select="@name" />
          </xsl:if>
        </span>
        <ul class="list-group">
          <!-- process child packages -->
          <xsl:apply-templates select="package">
            <xsl:sort select="@name" />
            <xsl:with-param name="parent_name" select="concat($full_name, '\')" />
          </xsl:apply-templates>

          <xsl:for-each select="/project/file/function[@package=$full_name]">
            <xsl:sort select="name" />
            <li class="list-group-item">
              <span class="{name()}">
                <a href="{$root}files/{../@generated-path}#::{name}()" target="content">
                  <xsl:value-of select="name" />
                </a>
              </span>
            </li>
          </xsl:for-each>

          <xsl:for-each select="/project/file/class[@package=$full_name]|/project/file/interface[@package=$full_name]">
            <xsl:sort select="name" />
            <li class="list-group-item">
              <span class="{name()}">
                <a href="{$root}files/{../@generated-path}#{full_name}" target="content">
                  <xsl:value-of select="name" />
                </a>
              </span>
            </li>
          </xsl:for-each>
        </ul>
      </li>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
    <xsl:output indent="yes" method="html"/>

    <xsl:template name="sidebar-section-files">
        <ul class="list-group">
            <xsl:apply-templates select="/project/file">
                <xsl:sort select="@path"/>
            </xsl:apply-templates>
        </ul>
    </xsl:template>

    <xsl:template match="/project/file">
      <li class="list-group-item">
        <span class="file">
            <a href="{$root}files/{@generated-path}" target="content">
                <xsl:value-of select="@path" />
            </a>
        </span>
        <xsl:if test="$section.files.show-elements != false">
            <xsl:variable name="file" select="@hash" />
            <ul id="files_{$file}" class="list-group">
              <xsl:for-each select="constant">
                <li class="list-group-item">
                  <span class="constant">
                    <a href="{$root}files/{../@generated-path}#::{name}" target="content">
                      <xsl:value-of select="name" /><br/>
                    </a>
                  </span>
                </li>
              </xsl:for-each>
              <xsl:for-each select="function">
                <li class="list-group-item">
                  <span class="function">
                    <a href="{$root}files/{../@generated-path}#::{name}()" target="content">
                      <xsl:value-of select="name" /><br/>
                    </a>
                  </span>
                </li>
              </xsl:for-each>
              <xsl:for-each select="class|interface">
                <li class="list-group-item">
                  <span class="{name()}">
                    <a href="{$root}files/{../@generated-path}#{full_name}" target="content">
                      <xsl:value-of select="name" /><br/>
                    </a>
                  </span>
                </li>
              </xsl:for-each>
            </ul>
        </xsl:if>
      </li>
    </xsl:template>

</xsl:stylesheet>
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
    <xsl:output indent="yes" method="html"/>

    <xsl:template name="sidebar-section-namespaces">
        <ul class="list-group">
            <xsl:apply-templates select="/project/namespace">
                <xsl:sort select="@name"/>
                <xsl:with-param name="parent_name" select="''"/>
            </xsl:apply-templates>
        </ul>
    </xsl:template>

  <xsl:template match="namespace">
    <xsl:param name="parent_name" />
    <xsl:variable name="full_name" select="concat($parent_name, @name)" />

    <xsl:if test="(count(namespace) > 0) or (count(/project/file/function[@namespace=$full_name]) > 0) or (count(/project/file/class[@namespace=$full_name]) > 0) or (count(/project/file/interface[@namespace=$full_name]) > 0)">
      <li class="list-group-item">
        <h4 data-toggle="collapse" data-target="+ ul.list-group" class="collapsed">
          <xsl:if test="@name=''">\</xsl:if>
          <xsl:if test="not(@name='')">
            <xsl:value-of select="@name" />
          </xsl:if>
        </h4>
        <ul class="list-group collapse">
          <!-- process child namespaces -->
          <xsl:apply-templates select="namespace">
            <xsl:sort select="@name" />
            <xsl:with-param name="parent_name" select="concat($full_name, '\')" />
          </xsl:apply-templates>

          <xsl:for-each select="/project/file/function[@namespace=$full_name]">
            <xsl:sort select="name" />
            <li class="list-group-item">
              <span class="{name()}">
                <a href="{$root}files/{../@generated-path}#::{name}()" target="content">
                  <xsl:value-of select="name" />
                </a>
              </span>
            </li>
          </xsl:for-each>

          <xsl:for-each select="/project/file/class[@namespace=$full_name]|/project/file/interface[@namespace=$full_name]">
            <xsl:sort select="name" />
            <li class="list-group-item">
              <span class="{name()}">
                <a href="{$root}files/{../@generated-path}#{full_name}" target="content">
                  <xsl:value-of select="name" />
                </a>
              </span>
            </li>
          </xsl:for-each>
        </ul>
      </li>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
    <xsl:output indent="yes" method="html"/>

    <xsl:template name="sidebar-section-api">
        <div style="padding: 0px;">
            <ul id="api-" class="filetree sidebar-nav-tree">
            <xsl:for-each select="/project/file/*">
                <xsl:sort select="./name" />

                <xsl:if test="count(./*/docblock/tag[@name='api']) > 0">
                    <xsl:comment>Class|Interface level</xsl:comment>
                    <li class="closed">
                        <span class="{name()}">
                            <a href="{$root}files/{../@generated-path}#{./full_name}" target="content">
                                <xsl:value-of select="./full_name" />
                            </a>
                        </span>

                        <ul class="filetree">
                        <xsl:for-each select="./*/docblock/tag[@name='api']">
                            <xsl:sort select="../../name" />
                            <xsl:variable name="className" select="name(../..)" />
                            <li>
                            <span class="{$className}">
                            <xsl:choose>
                                <xsl:when test="name(../..) = 'method'">
                                    <a class="{../../@visibility}" href="{$root}files/{../../../../@generated-path}#{../../../full_name}::{../../name}()" target="content">
                                    <xsl:value-of select="../../name" />
                                    </a>
                                </xsl:when>
                                <xsl:when test="name(../..) = 'constant'">
                                    <a class="{../../@visibility}" href="{$root}files/{../../../../@generated-path}#{../../../full_name}::{../../name}" target="content">
                                    <xsl:value-of select="../../name" />
                                    </a>
                                </xsl:when>
                                <xsl:when test="name(../..) = 'property'">
                                    <a class="{../../@visibility}" href="{$root}files/{../../../../@generated-path}#{../../../full_name}::{../../name}" target="content">
                                    <xsl:value-of select="../../name" />
                                    </a>
                                </xsl:when>
                                <xsl:otherwise>
                                    <xsl:value-of select="../../name" />
                                </xsl:otherwise>
                            </xsl:choose>
                            </span>
                            </li>
                        </xsl:for-each>
                        </ul>
                    </li>
                </xsl:if>

                <xsl:if test="count(./docblock/tag[@name='api']) > 0">
                    <xsl:comment>File level</xsl:comment>
                    <xsl:if test="
                    not(((name() = 'class') and count(./*/docblock/tag[@name='api']) > 0))
                    and
                    not(((name() = 'interface') and count(./*/docblock/tag[@name='api']) > 0))">
                    <li class="closed">
                        <span class="{name()}">
                        <xsl:choose>
                            <xsl:when test="name() = 'file'">
                                <a href="{$root}files/{../@generated-path}" target="content">
                                    <xsl:value-of select="./name" />
                                </a>
                            </xsl:when>
                            <xsl:when test="name() = 'function'">
                                <a href="{$root}files/{../@generated-path}#{./full_name}::{./name}()" target="content">
                                    <xsl:value-of select="./name" />
                                </a>
                            </xsl:when>
                            <xsl:when test="name() = 'class'">
                                <a href="{$root}files/{../@generated-path}#{./full_name}" target="content">
                                    <xsl:value-of select="./full_name" />
                                </a>
                            </xsl:when>
                            <xsl:when test="name() = 'constant'">
                                <a href="{$root}files/{../@generated-path}#{./full_name}::{./name}" target="content">
                                    <xsl:value-of select="./name" />
                                </a>
                            </xsl:when>
                            <xsl:when test="name() = 'property'">
                                <a href="{$root}files/{../@generated-path}#{./full_name}::{./name}" target="content">
                                    <xsl:value-of select="./name" />
                                </a>
                            </xsl:when>
                            <xsl:otherwise>
                                <xsl:value-of select="./name" />
                            </xsl:otherwise>
                        </xsl:choose>
                        </span>
                    </li>
                    </xsl:if>
                </xsl:if>
            </xsl:for-each>
            </ul>
        </div>
    </xsl:template>

</xsl:stylesheet>
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
    <xsl:output indent="yes" method="html"/>

    <xsl:template name="sidebar-section-charts">
        <li><a href="{$root}graph.html" target="content">Class Inheritance Diagram</a></li>
    </xsl:template>

</xsl:stylesheet><?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
    <xsl:output indent="yes" method="html"/>

    <xsl:template name="sidebar-section-reports">
        <li><a href="{$root}report_markers.html" target="content">Markers (TODO/FIXME)</a></li>
        <li><a href="{$root}report_parse_markers.html" target="content">Parsing errors</a></li>
        <li><a href="{$root}report_deprecated.html" target="content">Deprecated elements</a></li>
    </xsl:template>

</xsl:stylesheet><?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
    <xsl:output indent="yes" method="html"/>

    <xsl:template name="page-header">
        <h1>
            <xsl:if test="not($title)">
                <img src="images/logo.png" id="sidebar-logo" alt="Logo"/>
            </xsl:if>
            <xsl:if test="$title">
                <xsl:value-of select="$title" disable-output-escaping="yes"/>
            </xsl:if>
        </h1>
    </xsl:template>

</xsl:stylesheet><?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
    <xsl:output indent="yes" method="html"/>

    <xsl:template name="page-footer">
    </xsl:template>

</xsl:stylesheet><?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
    <xsl:include href="helpers.xsl"/>

    <xsl:output indent="yes" method="xml" omit-xml-declaration="yes" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>

    <xsl:template match="/" name="root">
        <xsl:param name="pageId" select="''"/>
        <html>
            <xsl:if test="$pageId!=''">
                <xsl:attribute name="id"><xsl:value-of select="$pageId" /></xsl:attribute>
            </xsl:if>
            <head>
                <title><xsl:value-of select="$title"/></title>
                <link href="http://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet"/>
                <link rel="stylesheet" href="{$root}css/template.css" type="text/css" />
                <script type="text/javascript" src="{$root}js/jquery-1.7.1.min.js"> </script>
                <script type="text/javascript" src="{$root}js/bootstrap.min.js"> </script>
                <script type="text/javascript" src="{$root}js/template.js"> </script>
            </head>
            <body>
                <xsl:call-template name="content"/>
            </body>
        </html>
    </xsl:template>

</xsl:stylesheet>
{
    "name": "phpdocumentor/template-old-ocean",
    "type": "phpdocumentor-template",
    "description": "Blue template with high contrast for the foreground",
    "keywords": ["documentation", "template", "phpdoc"],
    "homepage": "http://www.phpdoc.org",
    "license": "MIT",
    "require": {
        "ext-xsl": "*",
        "phpdocumentor/unified-asset-installer": "~1.1"
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.9.4" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
    http://pear.php.net/dtd/tasks-1.0.xsd
    http://pear.php.net/dtd/package-2.0
    http://pear.php.net/dtd/package-2.0.xsd">
 <name>phpDocumentor_Template_old_ocean</name>
 <channel>pear.phpdoc.org</channel>
 <summary>The old_ocean template for phpDocumentor</summary>
 <description>This is the Old Ocean theme; the old default for phpDocumentor.</description>
 <lead>
  <name>Mike van Riel</name>
  <user />
  <email>mike.vanriel@naenius.com</email>
  <active>yes</active>
 </lead>
 <date>2012-04-01</date>
 <time>10:34:05</time>
 <version>
  <release>1.0.2</release>
  <api>1.0.2</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license uri="http://www.opensource.org/licenses/mit-license.html">MIT</license>
 <notes>
Automatically generated by the phpDocumentor packager
 </notes>
 <contents>
  <dir baseinstalldir="/phpDocumentor/data/templates/old_ocean" name="/">
   <dir name="css">
    <dir name="black-tie">
     <dir name="images">
      <file name="ui-anim_basic_16x16.gif" role="php" />
      <file name="ui-bg_diagonals-thick_8_333333_40x40.png" role="php" />
      <file name="ui-bg_flat_65_ffffff_40x100.png" role="php" />
      <file name="ui-bg_glass_40_111111_1x400.png" role="php" />
      <file name="ui-bg_glass_55_1c1c1c_1x400.png" role="php" />
      <file name="ui-bg_highlight-hard_40_aaaaaa_1x100.png" role="php" />
      <file name="ui-bg_highlight-hard_100_f9f9f9_1x100.png" role="php" />
      <file name="ui-bg_highlight-soft_50_aaaaaa_1x100.png" role="php" />
      <file name="ui-bg_inset-hard_45_cd0a0a_1x100.png" role="php" />
      <file name="ui-bg_inset-hard_55_ffeb80_1x100.png" role="php" />
      <file name="ui-icons_4ca300_256x240.png" role="php" />
      <file name="ui-icons_222222_256x240.png" role="php" />
      <file name="ui-icons_bbbbbb_256x240.png" role="php" />
      <file name="ui-icons_ededed_256x240.png" role="php" />
      <file name="ui-icons_ffcf29_256x240.png" role="php" />
      <file name="ui-icons_ffffff_256x240.png" role="php" />
     </dir> <!-- /css/black-tie/images -->
     <file name="jquery-ui-1.8.2.custom.css" role="php" />
    </dir> <!-- /css/black-tie -->
    <dir name="images">
     <file name="ajax-loader.gif" role="php" />
     <file name="file.gif" role="php" />
     <file name="folder-closed.gif" role="php" />
     <file name="folder.gif" role="php" />
     <file name="minus.gif" role="php" />
     <file name="plus.gif" role="php" />
     <file name="treeview-black-line.gif" role="php" />
     <file name="treeview-black.gif" role="php" />
     <file name="treeview-default-line.gif" role="php" />
     <file name="treeview-default.gif" role="php" />
     <file name="treeview-famfamfam-line.gif" role="php" />
     <file name="treeview-famfamfam.gif" role="php" />
     <file name="treeview-gray-line.gif" role="php" />
     <file name="treeview-gray.gif" role="php" />
     <file name="treeview-red-line.gif" role="php" />
     <file name="treeview-red.gif" role="php" />
    </dir> <!-- /css/images -->
    <file name="default.css" role="php" />
    <file name="jquery.treeview.css" role="php" />
   </dir> <!-- /css -->
   <dir name="images">
    <file name="background.png" role="php" />
    <file name="menu-background.png" role="php" />
    <file name="top-background.png" role="php" />
    <file name="top-stopper.png" role="php" />
    <file name="top.png" role="php" />
   </dir> <!-- /images -->
   <dir name="preprocess">
    <file name="object-index.xsl" role="php" />
   </dir> <!-- /preprocess -->
   <file name="chrome.xsl" role="php" />
   <file name="class.xsl" role="php" />
   <file name="classgraph.xsl" role="php" />
   <file name="file.xsl" role="php" />
   <file name="index.xsl" role="php" />
   <file name="markers.xsl" role="php" />
   <file name="menu.xsl" role="php" />
   <file name="parse_markers.xsl" role="php" />
   <file name="README" role="php" />
   <file name="search.xsl" role="php" />
   <file name="template.xml" role="php" />
  </dir> <!-- / -->
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.2.6</min>
   </php>
   <pearinstaller>
    <min>1.4.0</min>
   </pearinstaller>
   <package>
    <name>PEAR</name>
    <channel>pear.php.net</channel>
    <min>1.4.0</min>
   </package>
   <package>
    <name>phpDocumentor</name>
    <channel>pear.phpdoc.org</channel>
    <min>0.17.0</min>
   </package>
  </required>
 </dependencies>
 <phprelease />
 <changelog>
  <release>
   <version>
    <release>1.0.2</release>
    <api>1.0.2</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2012-04-01</date>
   <license uri="http://www.opensource.org/licenses/mit-license.html">MIT</license>
   <notes>
Automatically generated by the phpDocumentor packager
   </notes>
  </release>
 </changelog>
</package>
<?xml version="1.0"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes" method="html" />
  <xsl:include href="chrome.xsl" />

  <xsl:template match="/project">
    <script type="text/javascript">
        $(document).ready(function() {
            $("#marker-accordion").accordion({
                collapsible: true,
                autoHeight:  false
            });
        });
    </script>


    <div id="content">

          <h1>Compilation Errors</h1>
        <xsl:if test="count(/project/file/parse_markers) &lt; 1">
            <div class="success_notification">No errors have been found in this project.</div>
        </xsl:if>
        <div id="marker-accordion">
            <xsl:for-each select="/project/file">
                <xsl:if test="parse_markers">
                    <h3>
                        <a href="#">
                            <xsl:value-of select="@path"/>
                            <small><xsl:value-of select="count(parse_markers/*)"/></small>
                        </a>
                    </h3>
                    <div>
                        <table>
                            <tr><th>Type</th><th>Line</th><th>Description</th></tr>
                            <xsl:for-each select="parse_markers/*">
                                <xsl:sort select="line"/>
                                <tr>
                                    <xsl:if test="name() = 'tag'">
                                        <td><xsl:value-of select="@name"/></td>
                                    </xsl:if>
                                    <xsl:if test="name() != 'tag'">
                                        <td><xsl:value-of select="name()"/></td>
                                    </xsl:if>
                                    <td><xsl:value-of select="@line"/></td>
                                    <xsl:if test="name() = 'tag'">
                                        <td>
                                            <xsl:value-of select="@description" disable-output-escaping="yes"/>
                                        </td>
                                    </xsl:if>
                                    <xsl:if test="name() != 'tag'">
                                        <td>
                                            <xsl:value-of select="." disable-output-escaping="yes"/>
                                        </td>
                                    </xsl:if>
                                </tr>
                            </xsl:for-each>
                        </table>
                    </div>
                </xsl:if>
            </xsl:for-each>
        </div>

    </div>
  </xsl:template>

</xsl:stylesheet><?xml version="1.0"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes" method="html" />
  <xsl:include href="chrome.xsl" />

  <xsl:template match="/project">
    <div id="content">

      <div class="tabs">
        <ul>
        <xsl:for-each select="marker">
          <xsl:variable name="marker" select="." />
          <li><a href="#{$marker}"><xsl:value-of select="$marker" /> (
            <xsl:if test="$marker='todo'">
            <xsl:value-of select="count(../file/markers/*[name()=$marker]|//tag[@name='todo'])" />
            </xsl:if>
            <xsl:if test="not($marker='todo')">
              <xsl:value-of select="count(../file/markers/*[name()=$marker])" />
            </xsl:if>
            )</a></li>
        </xsl:for-each>
        </ul>

        <xsl:for-each select="marker">
        <xsl:variable name="marker" select="." />
        <div id="{$marker}">
          <table>
            <tr>
                <th>Path</th>
                <th>Description</th>
            </tr>
          <xsl:if test="$marker='todo'">
            <xsl:for-each select="//tag[@name='todo']">
              <tr>
                <td><xsl:value-of select="../../../../@path|../../@path|../../../@path" />:<xsl:value-of select="./@line" /></td>
                <td><xsl:value-of select="./@description" /></td>
              </tr>
            </xsl:for-each>
          </xsl:if>
          <xsl:for-each select="../file/markers/*[name()=$marker]">
            <tr>
                <td><xsl:value-of select="../../@path" />:<xsl:value-of select="./@line" /></td>
                <td><xsl:value-of select="./@description" /></td>
            </tr>
          </xsl:for-each>
          </table>
        </div>
        </xsl:for-each>
      </div>
    </div>
  </xsl:template>

</xsl:stylesheet><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes" method="html" />
  <xsl:include href="chrome.xsl" />

  <xsl:template match="/project">
    <div id="content">
      <h2>Welcome!</h2>
      This documentation was generated by <a href="http://www.phpdoc.org">phpDocumentor <xsl:value-of select="$version" /></a>.
    </div>
  </xsl:template>

</xsl:stylesheet>/*
 * Downloaded from http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js, 2012-02-04 23:26
 */

/*!
 * jQuery JavaScript Library v1.7.1
 * http://jquery.com/
 *
 * Copyright 2011, John Resig
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * Includes Sizzle.js
 * http://sizzlejs.com/
 * Copyright 2011, The Dojo Foundation
 * Released under the MIT, BSD, and GPL Licenses.
 *
 * Date: Mon Nov 21 21:11:03 2011 -0500
 */
(function( window, undefined ) {

// Use the correct document accordingly with window argument (sandbox)
var document = window.document,
	navigator = window.navigator,
	location = window.location;
var jQuery = (function() {

// Define a local copy of jQuery
var jQuery = function( selector, context ) {
		// The jQuery object is actually just the init constructor 'enhanced'
		return new jQuery.fn.init( selector, context, rootjQuery );
	},

	// Map over jQuery in case of overwrite
	_jQuery = window.jQuery,

	// Map over the $ in case of overwrite
	_$ = window.$,

	// A central reference to the root jQuery(document)
	rootjQuery,

	// A simple way to check for HTML strings or ID strings
	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
	quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,

	// Check if a string has a non-whitespace character in it
	rnotwhite = /\S/,

	// Used for trimming whitespace
	trimLeft = /^\s+/,
	trimRight = /\s+$/,

	// Match a standalone tag
	rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,

	// JSON RegExp
	rvalidchars = /^[\],:{}\s]*$/,
	rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
	rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
	rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,

	// Useragent RegExp
	rwebkit = /(webkit)[ \/]([\w.]+)/,
	ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
	rmsie = /(msie) ([\w.]+)/,
	rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,

	// Matches dashed string for camelizing
	rdashAlpha = /-([a-z]|[0-9])/ig,
	rmsPrefix = /^-ms-/,

	// Used by jQuery.camelCase as callback to replace()
	fcamelCase = function( all, letter ) {
		return ( letter + "" ).toUpperCase();
	},

	// Keep a UserAgent string for use with jQuery.browser
	userAgent = navigator.userAgent,

	// For matching the engine and version of the browser
	browserMatch,

	// The deferred used on DOM ready
	readyList,

	// The ready event handler
	DOMContentLoaded,

	// Save a reference to some core methods
	toString = Object.prototype.toString,
	hasOwn = Object.prototype.hasOwnProperty,
	push = Array.prototype.push,
	slice = Array.prototype.slice,
	trim = String.prototype.trim,
	indexOf = Array.prototype.indexOf,

	// [[Class]] -> type pairs
	class2type = {};

jQuery.fn = jQuery.prototype = {
	constructor: jQuery,
	init: function( selector, context, rootjQuery ) {
		var match, elem, ret, doc;

		// Handle $(""), $(null), or $(undefined)
		if ( !selector ) {
			return this;
		}

		// Handle $(DOMElement)
		if ( selector.nodeType ) {
			this.context = this[0] = selector;
			this.length = 1;
			return this;
		}

		// The body element only exists once, optimize finding it
		if ( selector === "body" && !context && document.body ) {
			this.context = document;
			this[0] = document.body;
			this.selector = selector;
			this.length = 1;
			return this;
		}

		// Handle HTML strings
		if ( typeof selector === "string" ) {
			// Are we dealing with HTML string or an ID?
			if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
				// Assume that strings that start and end with <> are HTML and skip the regex check
				match = [ null, selector, null ];

			} else {
				match = quickExpr.exec( selector );
			}

			// Verify a match, and that no context was specified for #id
			if ( match && (match[1] || !context) ) {

				// HANDLE: $(html) -> $(array)
				if ( match[1] ) {
					context = context instanceof jQuery ? context[0] : context;
					doc = ( context ? context.ownerDocument || context : document );

					// If a single string is passed in and it's a single tag
					// just do a createElement and skip the rest
					ret = rsingleTag.exec( selector );

					if ( ret ) {
						if ( jQuery.isPlainObject( context ) ) {
							selector = [ document.createElement( ret[1] ) ];
							jQuery.fn.attr.call( selector, context, true );

						} else {
							selector = [ doc.createElement( ret[1] ) ];
						}

					} else {
						ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
						selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;
					}

					return jQuery.merge( this, selector );

				// HANDLE: $("#id")
				} else {
					elem = document.getElementById( match[2] );

					// Check parentNode to catch when Blackberry 4.6 returns
					// nodes that are no longer in the document #6963
					if ( elem && elem.parentNode ) {
						// Handle the case where IE and Opera return items
						// by name instead of ID
						if ( elem.id !== match[2] ) {
							return rootjQuery.find( selector );
						}

						// Otherwise, we inject the element directly into the jQuery object
						this.length = 1;
						this[0] = elem;
					}

					this.context = document;
					this.selector = selector;
					return this;
				}

			// HANDLE: $(expr, $(...))
			} else if ( !context || context.jquery ) {
				return ( context || rootjQuery ).find( selector );

			// HANDLE: $(expr, context)
			// (which is just equivalent to: $(context).find(expr)
			} else {
				return this.constructor( context ).find( selector );
			}

		// HANDLE: $(function)
		// Shortcut for document ready
		} else if ( jQuery.isFunction( selector ) ) {
			return rootjQuery.ready( selector );
		}

		if ( selector.selector !== undefined ) {
			this.selector = selector.selector;
			this.context = selector.context;
		}

		return jQuery.makeArray( selector, this );
	},

	// Start with an empty selector
	selector: "",

	// The current version of jQuery being used
	jquery: "1.7.1",

	// The default length of a jQuery object is 0
	length: 0,

	// The number of elements contained in the matched element set
	size: function() {
		return this.length;
	},

	toArray: function() {
		return slice.call( this, 0 );
	},

	// Get the Nth element in the matched element set OR
	// Get the whole matched element set as a clean array
	get: function( num ) {
		return num == null ?

			// Return a 'clean' array
			this.toArray() :

			// Return just the object
			( num < 0 ? this[ this.length + num ] : this[ num ] );
	},

	// Take an array of elements and push it onto the stack
	// (returning the new matched element set)
	pushStack: function( elems, name, selector ) {
		// Build a new jQuery matched element set
		var ret = this.constructor();

		if ( jQuery.isArray( elems ) ) {
			push.apply( ret, elems );

		} else {
			jQuery.merge( ret, elems );
		}

		// Add the old object onto the stack (as a reference)
		ret.prevObject = this;

		ret.context = this.context;

		if ( name === "find" ) {
			ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
		} else if ( name ) {
			ret.selector = this.selector + "." + name + "(" + selector + ")";
		}

		// Return the newly-formed element set
		return ret;
	},

	// Execute a callback for every element in the matched set.
	// (You can seed the arguments with an array of args, but this is
	// only used internally.)
	each: function( callback, args ) {
		return jQuery.each( this, callback, args );
	},

	ready: function( fn ) {
		// Attach the listeners
		jQuery.bindReady();

		// Add the callback
		readyList.add( fn );

		return this;
	},

	eq: function( i ) {
		i = +i;
		return i === -1 ?
			this.slice( i ) :
			this.slice( i, i + 1 );
	},

	first: function() {
		return this.eq( 0 );
	},

	last: function() {
		return this.eq( -1 );
	},

	slice: function() {
		return this.pushStack( slice.apply( this, arguments ),
			"slice", slice.call(arguments).join(",") );
	},

	map: function( callback ) {
		return this.pushStack( jQuery.map(this, function( elem, i ) {
			return callback.call( elem, i, elem );
		}));
	},

	end: function() {
		return this.prevObject || this.constructor(null);
	},

	// For internal use only.
	// Behaves like an Array's method, not like a jQuery method.
	push: push,
	sort: [].sort,
	splice: [].splice
};

// Give the init function the jQuery prototype for later instantiation
jQuery.fn.init.prototype = jQuery.fn;

jQuery.extend = jQuery.fn.extend = function() {
	var options, name, src, copy, copyIsArray, clone,
		target = arguments[0] || {},
		i = 1,
		length = arguments.length,
		deep = false;

	// Handle a deep copy situation
	if ( typeof target === "boolean" ) {
		deep = target;
		target = arguments[1] || {};
		// skip the boolean and the target
		i = 2;
	}

	// Handle case when target is a string or something (possible in deep copy)
	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
		target = {};
	}

	// extend jQuery itself if only one argument is passed
	if ( length === i ) {
		target = this;
		--i;
	}

	for ( ; i < length; i++ ) {
		// Only deal with non-null/undefined values
		if ( (options = arguments[ i ]) != null ) {
			// Extend the base object
			for ( name in options ) {
				src = target[ name ];
				copy = options[ name ];

				// Prevent never-ending loop
				if ( target === copy ) {
					continue;
				}

				// Recurse if we're merging plain objects or arrays
				if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
					if ( copyIsArray ) {
						copyIsArray = false;
						clone = src && jQuery.isArray(src) ? src : [];

					} else {
						clone = src && jQuery.isPlainObject(src) ? src : {};
					}

					// Never move original objects, clone them
					target[ name ] = jQuery.extend( deep, clone, copy );

				// Don't bring in undefined values
				} else if ( copy !== undefined ) {
					target[ name ] = copy;
				}
			}
		}
	}

	// Return the modified object
	return target;
};

jQuery.extend({
	noConflict: function( deep ) {
		if ( window.$ === jQuery ) {
			window.$ = _$;
		}

		if ( deep && window.jQuery === jQuery ) {
			window.jQuery = _jQuery;
		}

		return jQuery;
	},

	// Is the DOM ready to be used? Set to true once it occurs.
	isReady: false,

	// A counter to track how many items to wait for before
	// the ready event fires. See #6781
	readyWait: 1,

	// Hold (or release) the ready event
	holdReady: function( hold ) {
		if ( hold ) {
			jQuery.readyWait++;
		} else {
			jQuery.ready( true );
		}
	},

	// Handle when the DOM is ready
	ready: function( wait ) {
		// Either a released hold or an DOMready/load event and not yet ready
		if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {
			// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
			if ( !document.body ) {
				return setTimeout( jQuery.ready, 1 );
			}

			// Remember that the DOM is ready
			jQuery.isReady = true;

			// If a normal DOM Ready event fired, decrement, and wait if need be
			if ( wait !== true && --jQuery.readyWait > 0 ) {
				return;
			}

			// If there are functions bound, to execute
			readyList.fireWith( document, [ jQuery ] );

			// Trigger any bound ready events
			if ( jQuery.fn.trigger ) {
				jQuery( document ).trigger( "ready" ).off( "ready" );
			}
		}
	},

	bindReady: function() {
		if ( readyList ) {
			return;
		}

		readyList = jQuery.Callbacks( "once memory" );

		// Catch cases where $(document).ready() is called after the
		// browser event has already occurred.
		if ( document.readyState === "complete" ) {
			// Handle it asynchronously to allow scripts the opportunity to delay ready
			return setTimeout( jQuery.ready, 1 );
		}

		// Mozilla, Opera and webkit nightlies currently support this event
		if ( document.addEventListener ) {
			// Use the handy event callback
			document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );

			// A fallback to window.onload, that will always work
			window.addEventListener( "load", jQuery.ready, false );

		// If IE event model is used
		} else if ( document.attachEvent ) {
			// ensure firing before onload,
			// maybe late but safe also for iframes
			document.attachEvent( "onreadystatechange", DOMContentLoaded );

			// A fallback to window.onload, that will always work
			window.attachEvent( "onload", jQuery.ready );

			// If IE and not a frame
			// continually check to see if the document is ready
			var toplevel = false;

			try {
				toplevel = window.frameElement == null;
			} catch(e) {}

			if ( document.documentElement.doScroll && toplevel ) {
				doScrollCheck();
			}
		}
	},

	// See test/unit/core.js for details concerning isFunction.
	// Since version 1.3, DOM methods and functions like alert
	// aren't supported. They return false on IE (#2968).
	isFunction: function( obj ) {
		return jQuery.type(obj) === "function";
	},

	isArray: Array.isArray || function( obj ) {
		return jQuery.type(obj) === "array";
	},

	// A crude way of determining if an object is a window
	isWindow: function( obj ) {
		return obj && typeof obj === "object" && "setInterval" in obj;
	},

	isNumeric: function( obj ) {
		return !isNaN( parseFloat(obj) ) && isFinite( obj );
	},

	type: function( obj ) {
		return obj == null ?
			String( obj ) :
			class2type[ toString.call(obj) ] || "object";
	},

	isPlainObject: function( obj ) {
		// Must be an Object.
		// Because of IE, we also have to check the presence of the constructor property.
		// Make sure that DOM nodes and window objects don't pass through, as well
		if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
			return false;
		}

		try {
			// Not own constructor property must be Object
			if ( obj.constructor &&
				!hasOwn.call(obj, "constructor") &&
				!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
				return false;
			}
		} catch ( e ) {
			// IE8,9 Will throw exceptions on certain host objects #9897
			return false;
		}

		// Own properties are enumerated firstly, so to speed up,
		// if last one is own, then all properties are own.

		var key;
		for ( key in obj ) {}

		return key === undefined || hasOwn.call( obj, key );
	},

	isEmptyObject: function( obj ) {
		for ( var name in obj ) {
			return false;
		}
		return true;
	},

	error: function( msg ) {
		throw new Error( msg );
	},

	parseJSON: function( data ) {
		if ( typeof data !== "string" || !data ) {
			return null;
		}

		// Make sure leading/trailing whitespace is removed (IE can't handle it)
		data = jQuery.trim( data );

		// Attempt to parse using the native JSON parser first
		if ( window.JSON && window.JSON.parse ) {
			return window.JSON.parse( data );
		}

		// Make sure the incoming data is actual JSON
		// Logic borrowed from http://json.org/json2.js
		if ( rvalidchars.test( data.replace( rvalidescape, "@" )
			.replace( rvalidtokens, "]" )
			.replace( rvalidbraces, "")) ) {

			return ( new Function( "return " + data ) )();

		}
		jQuery.error( "Invalid JSON: " + data );
	},

	// Cross-browser xml parsing
	parseXML: function( data ) {
		var xml, tmp;
		try {
			if ( window.DOMParser ) { // Standard
				tmp = new DOMParser();
				xml = tmp.parseFromString( data , "text/xml" );
			} else { // IE
				xml = new ActiveXObject( "Microsoft.XMLDOM" );
				xml.async = "false";
				xml.loadXML( data );
			}
		} catch( e ) {
			xml = undefined;
		}
		if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
			jQuery.error( "Invalid XML: " + data );
		}
		return xml;
	},

	noop: function() {},

	// Evaluates a script in a global context
	// Workarounds based on findings by Jim Driscoll
	// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
	globalEval: function( data ) {
		if ( data && rnotwhite.test( data ) ) {
			// We use execScript on Internet Explorer
			// We use an anonymous function so that context is window
			// rather than jQuery in Firefox
			( window.execScript || function( data ) {
				window[ "eval" ].call( window, data );
			} )( data );
		}
	},

	// Convert dashed to camelCase; used by the css and data modules
	// Microsoft forgot to hump their vendor prefix (#9572)
	camelCase: function( string ) {
		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
	},

	nodeName: function( elem, name ) {
		return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
	},

	// args is for internal usage only
	each: function( object, callback, args ) {
		var name, i = 0,
			length = object.length,
			isObj = length === undefined || jQuery.isFunction( object );

		if ( args ) {
			if ( isObj ) {
				for ( name in object ) {
					if ( callback.apply( object[ name ], args ) === false ) {
						break;
					}
				}
			} else {
				for ( ; i < length; ) {
					if ( callback.apply( object[ i++ ], args ) === false ) {
						break;
					}
				}
			}

		// A special, fast, case for the most common use of each
		} else {
			if ( isObj ) {
				for ( name in object ) {
					if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
						break;
					}
				}
			} else {
				for ( ; i < length; ) {
					if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
						break;
					}
				}
			}
		}

		return object;
	},

	// Use native String.trim function wherever possible
	trim: trim ?
		function( text ) {
			return text == null ?
				"" :
				trim.call( text );
		} :

		// Otherwise use our own trimming functionality
		function( text ) {
			return text == null ?
				"" :
				text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
		},

	// results is for internal usage only
	makeArray: function( array, results ) {
		var ret = results || [];

		if ( array != null ) {
			// The window, strings (and functions) also have 'length'
			// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
			var type = jQuery.type( array );

			if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
				push.call( ret, array );
			} else {
				jQuery.merge( ret, array );
			}
		}

		return ret;
	},

	inArray: function( elem, array, i ) {
		var len;

		if ( array ) {
			if ( indexOf ) {
				return indexOf.call( array, elem, i );
			}

			len = array.length;
			i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;

			for ( ; i < len; i++ ) {
				// Skip accessing in sparse arrays
				if ( i in array && array[ i ] === elem ) {
					return i;
				}
			}
		}

		return -1;
	},

	merge: function( first, second ) {
		var i = first.length,
			j = 0;

		if ( typeof second.length === "number" ) {
			for ( var l = second.length; j < l; j++ ) {
				first[ i++ ] = second[ j ];
			}

		} else {
			while ( second[j] !== undefined ) {
				first[ i++ ] = second[ j++ ];
			}
		}

		first.length = i;

		return first;
	},

	grep: function( elems, callback, inv ) {
		var ret = [], retVal;
		inv = !!inv;

		// Go through the array, only saving the items
		// that pass the validator function
		for ( var i = 0, length = elems.length; i < length; i++ ) {
			retVal = !!callback( elems[ i ], i );
			if ( inv !== retVal ) {
				ret.push( elems[ i ] );
			}
		}

		return ret;
	},

	// arg is for internal usage only
	map: function( elems, callback, arg ) {
		var value, key, ret = [],
			i = 0,
			length = elems.length,
			// jquery objects are treated as arrays
			isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;

		// Go through the array, translating each of the items to their
		if ( isArray ) {
			for ( ; i < length; i++ ) {
				value = callback( elems[ i ], i, arg );

				if ( value != null ) {
					ret[ ret.length ] = value;
				}
			}

		// Go through every key on the object,
		} else {
			for ( key in elems ) {
				value = callback( elems[ key ], key, arg );

				if ( value != null ) {
					ret[ ret.length ] = value;
				}
			}
		}

		// Flatten any nested arrays
		return ret.concat.apply( [], ret );
	},

	// A global GUID counter for objects
	guid: 1,

	// Bind a function to a context, optionally partially applying any
	// arguments.
	proxy: function( fn, context ) {
		if ( typeof context === "string" ) {
			var tmp = fn[ context ];
			context = fn;
			fn = tmp;
		}

		// Quick check to determine if target is callable, in the spec
		// this throws a TypeError, but we will just return undefined.
		if ( !jQuery.isFunction( fn ) ) {
			return undefined;
		}

		// Simulated bind
		var args = slice.call( arguments, 2 ),
			proxy = function() {
				return fn.apply( context, args.concat( slice.call( arguments ) ) );
			};

		// Set the guid of unique handler to the same of original handler, so it can be removed
		proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;

		return proxy;
	},

	// Mutifunctional method to get and set values to a collection
	// The value/s can optionally be executed if it's a function
	access: function( elems, key, value, exec, fn, pass ) {
		var length = elems.length;

		// Setting many attributes
		if ( typeof key === "object" ) {
			for ( var k in key ) {
				jQuery.access( elems, k, key[k], exec, fn, value );
			}
			return elems;
		}

		// Setting one attribute
		if ( value !== undefined ) {
			// Optionally, function values get executed if exec is true
			exec = !pass && exec && jQuery.isFunction(value);

			for ( var i = 0; i < length; i++ ) {
				fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
			}

			return elems;
		}

		// Getting an attribute
		return length ? fn( elems[0], key ) : undefined;
	},

	now: function() {
		return ( new Date() ).getTime();
	},

	// Use of jQuery.browser is frowned upon.
	// More details: http://docs.jquery.com/Utilities/jQuery.browser
	uaMatch: function( ua ) {
		ua = ua.toLowerCase();

		var match = rwebkit.exec( ua ) ||
			ropera.exec( ua ) ||
			rmsie.exec( ua ) ||
			ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
			[];

		return { browser: match[1] || "", version: match[2] || "0" };
	},

	sub: function() {
		function jQuerySub( selector, context ) {
			return new jQuerySub.fn.init( selector, context );
		}
		jQuery.extend( true, jQuerySub, this );
		jQuerySub.superclass = this;
		jQuerySub.fn = jQuerySub.prototype = this();
		jQuerySub.fn.constructor = jQuerySub;
		jQuerySub.sub = this.sub;
		jQuerySub.fn.init = function init( selector, context ) {
			if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
				context = jQuerySub( context );
			}

			return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
		};
		jQuerySub.fn.init.prototype = jQuerySub.fn;
		var rootjQuerySub = jQuerySub(document);
		return jQuerySub;
	},

	browser: {}
});

// Populate the class2type map
jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
	class2type[ "[object " + name + "]" ] = name.toLowerCase();
});

browserMatch = jQuery.uaMatch( userAgent );
if ( browserMatch.browser ) {
	jQuery.browser[ browserMatch.browser ] = true;
	jQuery.browser.version = browserMatch.version;
}

// Deprecated, use jQuery.browser.webkit instead
if ( jQuery.browser.webkit ) {
	jQuery.browser.safari = true;
}

// IE doesn't match non-breaking spaces with \s
if ( rnotwhite.test( "\xA0" ) ) {
	trimLeft = /^[\s\xA0]+/;
	trimRight = /[\s\xA0]+$/;
}

// All jQuery objects should point back to these
rootjQuery = jQuery(document);

// Cleanup functions for the document ready method
if ( document.addEventListener ) {
	DOMContentLoaded = function() {
		document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
		jQuery.ready();
	};

} else if ( document.attachEvent ) {
	DOMContentLoaded = function() {
		// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
		if ( document.readyState === "complete" ) {
			document.detachEvent( "onreadystatechange", DOMContentLoaded );
			jQuery.ready();
		}
	};
}

// The DOM ready check for Internet Explorer
function doScrollCheck() {
	if ( jQuery.isReady ) {
		return;
	}

	try {
		// If IE is used, use the trick by Diego Perini
		// http://javascript.nwbox.com/IEContentLoaded/
		document.documentElement.doScroll("left");
	} catch(e) {
		setTimeout( doScrollCheck, 1 );
		return;
	}

	// and execute any waiting functions
	jQuery.ready();
}

return jQuery;

})();


// String to Object flags format cache
var flagsCache = {};

// Convert String-formatted flags into Object-formatted ones and store in cache
function createFlags( flags ) {
	var object = flagsCache[ flags ] = {},
		i, length;
	flags = flags.split( /\s+/ );
	for ( i = 0, length = flags.length; i < length; i++ ) {
		object[ flags[i] ] = true;
	}
	return object;
}

/*
 * Create a callback list using the following parameters:
 *
 *	flags:	an optional list of space-separated flags that will change how
 *			the callback list behaves
 *
 * By default a callback list will act like an event callback list and can be
 * "fired" multiple times.
 *
 * Possible flags:
 *
 *	once:			will ensure the callback list can only be fired once (like a Deferred)
 *
 *	memory:			will keep track of previous values and will call any callback added
 *					after the list has been fired right away with the latest "memorized"
 *					values (like a Deferred)
 *
 *	unique:			will ensure a callback can only be added once (no duplicate in the list)
 *
 *	stopOnFalse:	interrupt callings when a callback returns false
 *
 */
jQuery.Callbacks = function( flags ) {

	// Convert flags from String-formatted to Object-formatted
	// (we check in cache first)
	flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};

	var // Actual callback list
		list = [],
		// Stack of fire calls for repeatable lists
		stack = [],
		// Last fire value (for non-forgettable lists)
		memory,
		// Flag to know if list is currently firing
		firing,
		// First callback to fire (used internally by add and fireWith)
		firingStart,
		// End of the loop when firing
		firingLength,
		// Index of currently firing callback (modified by remove if needed)
		firingIndex,
		// Add one or several callbacks to the list
		add = function( args ) {
			var i,
				length,
				elem,
				type,
				actual;
			for ( i = 0, length = args.length; i < length; i++ ) {
				elem = args[ i ];
				type = jQuery.type( elem );
				if ( type === "array" ) {
					// Inspect recursively
					add( elem );
				} else if ( type === "function" ) {
					// Add if not in unique mode and callback is not in
					if ( !flags.unique || !self.has( elem ) ) {
						list.push( elem );
					}
				}
			}
		},
		// Fire callbacks
		fire = function( context, args ) {
			args = args || [];
			memory = !flags.memory || [ context, args ];
			firing = true;
			firingIndex = firingStart || 0;
			firingStart = 0;
			firingLength = list.length;
			for ( ; list && firingIndex < firingLength; firingIndex++ ) {
				if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {
					memory = true; // Mark as halted
					break;
				}
			}
			firing = false;
			if ( list ) {
				if ( !flags.once ) {
					if ( stack && stack.length ) {
						memory = stack.shift();
						self.fireWith( memory[ 0 ], memory[ 1 ] );
					}
				} else if ( memory === true ) {
					self.disable();
				} else {
					list = [];
				}
			}
		},
		// Actual Callbacks object
		self = {
			// Add a callback or a collection of callbacks to the list
			add: function() {
				if ( list ) {
					var length = list.length;
					add( arguments );
					// Do we need to add the callbacks to the
					// current firing batch?
					if ( firing ) {
						firingLength = list.length;
					// With memory, if we're not firing then
					// we should call right away, unless previous
					// firing was halted (stopOnFalse)
					} else if ( memory && memory !== true ) {
						firingStart = length;
						fire( memory[ 0 ], memory[ 1 ] );
					}
				}
				return this;
			},
			// Remove a callback from the list
			remove: function() {
				if ( list ) {
					var args = arguments,
						argIndex = 0,
						argLength = args.length;
					for ( ; argIndex < argLength ; argIndex++ ) {
						for ( var i = 0; i < list.length; i++ ) {
							if ( args[ argIndex ] === list[ i ] ) {
								// Handle firingIndex and firingLength
								if ( firing ) {
									if ( i <= firingLength ) {
										firingLength--;
										if ( i <= firingIndex ) {
											firingIndex--;
										}
									}
								}
								// Remove the element
								list.splice( i--, 1 );
								// If we have some unicity property then
								// we only need to do this once
								if ( flags.unique ) {
									break;
								}
							}
						}
					}
				}
				return this;
			},
			// Control if a given callback is in the list
			has: function( fn ) {
				if ( list ) {
					var i = 0,
						length = list.length;
					for ( ; i < length; i++ ) {
						if ( fn === list[ i ] ) {
							return true;
						}
					}
				}
				return false;
			},
			// Remove all callbacks from the list
			empty: function() {
				list = [];
				return this;
			},
			// Have the list do nothing anymore
			disable: function() {
				list = stack = memory = undefined;
				return this;
			},
			// Is it disabled?
			disabled: function() {
				return !list;
			},
			// Lock the list in its current state
			lock: function() {
				stack = undefined;
				if ( !memory || memory === true ) {
					self.disable();
				}
				return this;
			},
			// Is it locked?
			locked: function() {
				return !stack;
			},
			// Call all callbacks with the given context and arguments
			fireWith: function( context, args ) {
				if ( stack ) {
					if ( firing ) {
						if ( !flags.once ) {
							stack.push( [ context, args ] );
						}
					} else if ( !( flags.once && memory ) ) {
						fire( context, args );
					}
				}
				return this;
			},
			// Call all the callbacks with the given arguments
			fire: function() {
				self.fireWith( this, arguments );
				return this;
			},
			// To know if the callbacks have already been called at least once
			fired: function() {
				return !!memory;
			}
		};

	return self;
};




var // Static reference to slice
	sliceDeferred = [].slice;

jQuery.extend({

	Deferred: function( func ) {
		var doneList = jQuery.Callbacks( "once memory" ),
			failList = jQuery.Callbacks( "once memory" ),
			progressList = jQuery.Callbacks( "memory" ),
			state = "pending",
			lists = {
				resolve: doneList,
				reject: failList,
				notify: progressList
			},
			promise = {
				done: doneList.add,
				fail: failList.add,
				progress: progressList.add,

				state: function() {
					return state;
				},

				// Deprecated
				isResolved: doneList.fired,
				isRejected: failList.fired,

				then: function( doneCallbacks, failCallbacks, progressCallbacks ) {
					deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );
					return this;
				},
				always: function() {
					deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );
					return this;
				},
				pipe: function( fnDone, fnFail, fnProgress ) {
					return jQuery.Deferred(function( newDefer ) {
						jQuery.each( {
							done: [ fnDone, "resolve" ],
							fail: [ fnFail, "reject" ],
							progress: [ fnProgress, "notify" ]
						}, function( handler, data ) {
							var fn = data[ 0 ],
								action = data[ 1 ],
								returned;
							if ( jQuery.isFunction( fn ) ) {
								deferred[ handler ](function() {
									returned = fn.apply( this, arguments );
									if ( returned && jQuery.isFunction( returned.promise ) ) {
										returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );
									} else {
										newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
									}
								});
							} else {
								deferred[ handler ]( newDefer[ action ] );
							}
						});
					}).promise();
				},
				// Get a promise for this deferred
				// If obj is provided, the promise aspect is added to the object
				promise: function( obj ) {
					if ( obj == null ) {
						obj = promise;
					} else {
						for ( var key in promise ) {
							obj[ key ] = promise[ key ];
						}
					}
					return obj;
				}
			},
			deferred = promise.promise({}),
			key;

		for ( key in lists ) {
			deferred[ key ] = lists[ key ].fire;
			deferred[ key + "With" ] = lists[ key ].fireWith;
		}

		// Handle state
		deferred.done( function() {
			state = "resolved";
		}, failList.disable, progressList.lock ).fail( function() {
			state = "rejected";
		}, doneList.disable, progressList.lock );

		// Call given func if any
		if ( func ) {
			func.call( deferred, deferred );
		}

		// All done!
		return deferred;
	},

	// Deferred helper
	when: function( firstParam ) {
		var args = sliceDeferred.call( arguments, 0 ),
			i = 0,
			length = args.length,
			pValues = new Array( length ),
			count = length,
			pCount = length,
			deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?
				firstParam :
				jQuery.Deferred(),
			promise = deferred.promise();
		function resolveFunc( i ) {
			return function( value ) {
				args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
				if ( !( --count ) ) {
					deferred.resolveWith( deferred, args );
				}
			};
		}
		function progressFunc( i ) {
			return function( value ) {
				pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
				deferred.notifyWith( promise, pValues );
			};
		}
		if ( length > 1 ) {
			for ( ; i < length; i++ ) {
				if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {
					args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );
				} else {
					--count;
				}
			}
			if ( !count ) {
				deferred.resolveWith( deferred, args );
			}
		} else if ( deferred !== firstParam ) {
			deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
		}
		return promise;
	}
});




jQuery.support = (function() {

	var support,
		all,
		a,
		select,
		opt,
		input,
		marginDiv,
		fragment,
		tds,
		events,
		eventName,
		i,
		isSupported,
		div = document.createElement( "div" ),
		documentElement = document.documentElement;

	// Preliminary tests
	div.setAttribute("className", "t");
	div.innerHTML = "   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";

	all = div.getElementsByTagName( "*" );
	a = div.getElementsByTagName( "a" )[ 0 ];

	// Can't get basic test support
	if ( !all || !all.length || !a ) {
		return {};
	}

	// First batch of supports tests
	select = document.createElement( "select" );
	opt = select.appendChild( document.createElement("option") );
	input = div.getElementsByTagName( "input" )[ 0 ];

	support = {
		// IE strips leading whitespace when .innerHTML is used
		leadingWhitespace: ( div.firstChild.nodeType === 3 ),

		// Make sure that tbody elements aren't automatically inserted
		// IE will insert them into empty tables
		tbody: !div.getElementsByTagName("tbody").length,

		// Make sure that link elements get serialized correctly by innerHTML
		// This requires a wrapper element in IE
		htmlSerialize: !!div.getElementsByTagName("link").length,

		// Get the style information from getAttribute
		// (IE uses .cssText instead)
		style: /top/.test( a.getAttribute("style") ),

		// Make sure that URLs aren't manipulated
		// (IE normalizes it by default)
		hrefNormalized: ( a.getAttribute("href") === "/a" ),

		// Make sure that element opacity exists
		// (IE uses filter instead)
		// Use a regex to work around a WebKit issue. See #5145
		opacity: /^0.55/.test( a.style.opacity ),

		// Verify style float existence
		// (IE uses styleFloat instead of cssFloat)
		cssFloat: !!a.style.cssFloat,

		// Make sure that if no value is specified for a checkbox
		// that it defaults to "on".
		// (WebKit defaults to "" instead)
		checkOn: ( input.value === "on" ),

		// Make sure that a selected-by-default option has a working selected property.
		// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
		optSelected: opt.selected,

		// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
		getSetAttribute: div.className !== "t",

		// Tests for enctype support on a form(#6743)
		enctype: !!document.createElement("form").enctype,

		// Makes sure cloning an html5 element does not cause problems
		// Where outerHTML is undefined, this still works
		html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",

		// Will be defined later
		submitBubbles: true,
		changeBubbles: true,
		focusinBubbles: false,
		deleteExpando: true,
		noCloneEvent: true,
		inlineBlockNeedsLayout: false,
		shrinkWrapBlocks: false,
		reliableMarginRight: true
	};

	// Make sure checked status is properly cloned
	input.checked = true;
	support.noCloneChecked = input.cloneNode( true ).checked;

	// Make sure that the options inside disabled selects aren't marked as disabled
	// (WebKit marks them as disabled)
	select.disabled = true;
	support.optDisabled = !opt.disabled;

	// Test to see if it's possible to delete an expando from an element
	// Fails in Internet Explorer
	try {
		delete div.test;
	} catch( e ) {
		support.deleteExpando = false;
	}

	if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
		div.attachEvent( "onclick", function() {
			// Cloning a node shouldn't copy over any
			// bound event handlers (IE does this)
			support.noCloneEvent = false;
		});
		div.cloneNode( true ).fireEvent( "onclick" );
	}

	// Check if a radio maintains its value
	// after being appended to the DOM
	input = document.createElement("input");
	input.value = "t";
	input.setAttribute("type", "radio");
	support.radioValue = input.value === "t";

	input.setAttribute("checked", "checked");
	div.appendChild( input );
	fragment = document.createDocumentFragment();
	fragment.appendChild( div.lastChild );

	// WebKit doesn't clone checked state correctly in fragments
	support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;

	// Check if a disconnected checkbox will retain its checked
	// value of true after appended to the DOM (IE6/7)
	support.appendChecked = input.checked;

	fragment.removeChild( input );
	fragment.appendChild( div );

	div.innerHTML = "";

	// Check if div with explicit width and no margin-right incorrectly
	// gets computed margin-right based on width of container. For more
	// info see bug #3333
	// Fails in WebKit before Feb 2011 nightlies
	// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
	if ( window.getComputedStyle ) {
		marginDiv = document.createElement( "div" );
		marginDiv.style.width = "0";
		marginDiv.style.marginRight = "0";
		div.style.width = "2px";
		div.appendChild( marginDiv );
		support.reliableMarginRight =
			( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;
	}

	// Technique from Juriy Zaytsev
	// http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
	// We only care about the case where non-standard event systems
	// are used, namely in IE. Short-circuiting here helps us to
	// avoid an eval call (in setAttribute) which can cause CSP
	// to go haywire. See: https://developer.mozilla.org/en/Security/CSP
	if ( div.attachEvent ) {
		for( i in {
			submit: 1,
			change: 1,
			focusin: 1
		}) {
			eventName = "on" + i;
			isSupported = ( eventName in div );
			if ( !isSupported ) {
				div.setAttribute( eventName, "return;" );
				isSupported = ( typeof div[ eventName ] === "function" );
			}
			support[ i + "Bubbles" ] = isSupported;
		}
	}

	fragment.removeChild( div );

	// Null elements to avoid leaks in IE
	fragment = select = opt = marginDiv = div = input = null;

	// Run tests that need a body at doc ready
	jQuery(function() {
		var container, outer, inner, table, td, offsetSupport,
			conMarginTop, ptlm, vb, style, html,
			body = document.getElementsByTagName("body")[0];

		if ( !body ) {
			// Return for frameset docs that don't have a body
			return;
		}

		conMarginTop = 1;
		ptlm = "position:absolute;top:0;left:0;width:1px;height:1px;margin:0;";
		vb = "visibility:hidden;border:0;";
		style = "style='" + ptlm + "border:5px solid #000;padding:0;'";
		html = "<div " + style + "><div></div></div>" +
			"<table " + style + " cellpadding='0' cellspacing='0'>" +
			"<tr><td></td></tr></table>";

		container = document.createElement("div");
		container.style.cssText = vb + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px";
		body.insertBefore( container, body.firstChild );

		// Construct the test element
		div = document.createElement("div");
		container.appendChild( div );

		// Check if table cells still have offsetWidth/Height when they are set
		// to display:none and there are still other visible table cells in a
		// table row; if so, offsetWidth/Height are not reliable for use when
		// determining if an element has been hidden directly using
		// display:none (it is still safe to use offsets if a parent element is
		// hidden; don safety goggles and see bug #4512 for more information).
		// (only IE 8 fails this test)
		div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
		tds = div.getElementsByTagName( "td" );
		isSupported = ( tds[ 0 ].offsetHeight === 0 );

		tds[ 0 ].style.display = "";
		tds[ 1 ].style.display = "none";

		// Check if empty table cells still have offsetWidth/Height
		// (IE <= 8 fail this test)
		support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );

		// Figure out if the W3C box model works as expected
		div.innerHTML = "";
		div.style.width = div.style.paddingLeft = "1px";
		jQuery.boxModel = support.boxModel = div.offsetWidth === 2;

		if ( typeof div.style.zoom !== "undefined" ) {
			// Check if natively block-level elements act like inline-block
			// elements when setting their display to 'inline' and giving
			// them layout
			// (IE < 8 does this)
			div.style.display = "inline";
			div.style.zoom = 1;
			support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );

			// Check if elements with layout shrink-wrap their children
			// (IE 6 does this)
			div.style.display = "";
			div.innerHTML = "<div style='width:4px;'></div>";
			support.shrinkWrapBlocks = ( div.offsetWidth !== 2 );
		}

		div.style.cssText = ptlm + vb;
		div.innerHTML = html;

		outer = div.firstChild;
		inner = outer.firstChild;
		td = outer.nextSibling.firstChild.firstChild;

		offsetSupport = {
			doesNotAddBorder: ( inner.offsetTop !== 5 ),
			doesAddBorderForTableAndCells: ( td.offsetTop === 5 )
		};

		inner.style.position = "fixed";
		inner.style.top = "20px";

		// safari subtracts parent border width here which is 5px
		offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );
		inner.style.position = inner.style.top = "";

		outer.style.overflow = "hidden";
		outer.style.position = "relative";

		offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );
		offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );

		body.removeChild( container );
		div  = container = null;

		jQuery.extend( support, offsetSupport );
	});

	return support;
})();




var rbrace = /^(?:\{.*\}|\[.*\])$/,
	rmultiDash = /([A-Z])/g;

jQuery.extend({
	cache: {},

	// Please use with caution
	uuid: 0,

	// Unique for each copy of jQuery on the page
	// Non-digits removed to match rinlinejQuery
	expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),

	// The following elements throw uncatchable exceptions if you
	// attempt to add expando properties to them.
	noData: {
		"embed": true,
		// Ban all objects except for Flash (which handle expandos)
		"object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
		"applet": true
	},

	hasData: function( elem ) {
		elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
		return !!elem && !isEmptyDataObject( elem );
	},

	data: function( elem, name, data, pvt /* Internal Use Only */ ) {
		if ( !jQuery.acceptData( elem ) ) {
			return;
		}

		var privateCache, thisCache, ret,
			internalKey = jQuery.expando,
			getByName = typeof name === "string",

			// We have to handle DOM nodes and JS objects differently because IE6-7
			// can't GC object references properly across the DOM-JS boundary
			isNode = elem.nodeType,

			// Only DOM nodes need the global jQuery cache; JS object data is
			// attached directly to the object so GC can occur automatically
			cache = isNode ? jQuery.cache : elem,

			// Only defining an ID for JS objects if its cache already exists allows
			// the code to shortcut on the same path as a DOM node with no cache
			id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,
			isEvents = name === "events";

		// Avoid doing any more work than we need to when trying to get data on an
		// object that has no data at all
		if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {
			return;
		}

		if ( !id ) {
			// Only DOM nodes need a new unique ID for each element since their data
			// ends up in the global cache
			if ( isNode ) {
				elem[ internalKey ] = id = ++jQuery.uuid;
			} else {
				id = internalKey;
			}
		}

		if ( !cache[ id ] ) {
			cache[ id ] = {};

			// Avoids exposing jQuery metadata on plain JS objects when the object
			// is serialized using JSON.stringify
			if ( !isNode ) {
				cache[ id ].toJSON = jQuery.noop;
			}
		}

		// An object can be passed to jQuery.data instead of a key/value pair; this gets
		// shallow copied over onto the existing cache
		if ( typeof name === "object" || typeof name === "function" ) {
			if ( pvt ) {
				cache[ id ] = jQuery.extend( cache[ id ], name );
			} else {
				cache[ id ].data = jQuery.extend( cache[ id ].data, name );
			}
		}

		privateCache = thisCache = cache[ id ];

		// jQuery data() is stored in a separate object inside the object's internal data
		// cache in order to avoid key collisions between internal data and user-defined
		// data.
		if ( !pvt ) {
			if ( !thisCache.data ) {
				thisCache.data = {};
			}

			thisCache = thisCache.data;
		}

		if ( data !== undefined ) {
			thisCache[ jQuery.camelCase( name ) ] = data;
		}

		// Users should not attempt to inspect the internal events object using jQuery.data,
		// it is undocumented and subject to change. But does anyone listen? No.
		if ( isEvents && !thisCache[ name ] ) {
			return privateCache.events;
		}

		// Check for both converted-to-camel and non-converted data property names
		// If a data property was specified
		if ( getByName ) {

			// First Try to find as-is property data
			ret = thisCache[ name ];

			// Test for null|undefined property data
			if ( ret == null ) {

				// Try to find the camelCased property
				ret = thisCache[ jQuery.camelCase( name ) ];
			}
		} else {
			ret = thisCache;
		}

		return ret;
	},

	removeData: function( elem, name, pvt /* Internal Use Only */ ) {
		if ( !jQuery.acceptData( elem ) ) {
			return;
		}

		var thisCache, i, l,

			// Reference to internal data cache key
			internalKey = jQuery.expando,

			isNode = elem.nodeType,

			// See jQuery.data for more information
			cache = isNode ? jQuery.cache : elem,

			// See jQuery.data for more information
			id = isNode ? elem[ internalKey ] : internalKey;

		// If there is already no cache entry for this object, there is no
		// purpose in continuing
		if ( !cache[ id ] ) {
			return;
		}

		if ( name ) {

			thisCache = pvt ? cache[ id ] : cache[ id ].data;

			if ( thisCache ) {

				// Support array or space separated string names for data keys
				if ( !jQuery.isArray( name ) ) {

					// try the string as a key before any manipulation
					if ( name in thisCache ) {
						name = [ name ];
					} else {

						// split the camel cased version by spaces unless a key with the spaces exists
						name = jQuery.camelCase( name );
						if ( name in thisCache ) {
							name = [ name ];
						} else {
							name = name.split( " " );
						}
					}
				}

				for ( i = 0, l = name.length; i < l; i++ ) {
					delete thisCache[ name[i] ];
				}

				// If there is no data left in the cache, we want to continue
				// and let the cache object itself get destroyed
				if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
					return;
				}
			}
		}

		// See jQuery.data for more information
		if ( !pvt ) {
			delete cache[ id ].data;

			// Don't destroy the parent cache unless the internal data object
			// had been the only thing left in it
			if ( !isEmptyDataObject(cache[ id ]) ) {
				return;
			}
		}

		// Browsers that fail expando deletion also refuse to delete expandos on
		// the window, but it will allow it on all other JS objects; other browsers
		// don't care
		// Ensure that `cache` is not a window object #10080
		if ( jQuery.support.deleteExpando || !cache.setInterval ) {
			delete cache[ id ];
		} else {
			cache[ id ] = null;
		}

		// We destroyed the cache and need to eliminate the expando on the node to avoid
		// false lookups in the cache for entries that no longer exist
		if ( isNode ) {
			// IE does not allow us to delete expando properties from nodes,
			// nor does it have a removeAttribute function on Document nodes;
			// we must handle all of these cases
			if ( jQuery.support.deleteExpando ) {
				delete elem[ internalKey ];
			} else if ( elem.removeAttribute ) {
				elem.removeAttribute( internalKey );
			} else {
				elem[ internalKey ] = null;
			}
		}
	},

	// For internal use only.
	_data: function( elem, name, data ) {
		return jQuery.data( elem, name, data, true );
	},

	// A method for determining if a DOM node can handle the data expando
	acceptData: function( elem ) {
		if ( elem.nodeName ) {
			var match = jQuery.noData[ elem.nodeName.toLowerCase() ];

			if ( match ) {
				return !(match === true || elem.getAttribute("classid") !== match);
			}
		}

		return true;
	}
});

jQuery.fn.extend({
	data: function( key, value ) {
		var parts, attr, name,
			data = null;

		if ( typeof key === "undefined" ) {
			if ( this.length ) {
				data = jQuery.data( this[0] );

				if ( this[0].nodeType === 1 && !jQuery._data( this[0], "parsedAttrs" ) ) {
					attr = this[0].attributes;
					for ( var i = 0, l = attr.length; i < l; i++ ) {
						name = attr[i].name;

						if ( name.indexOf( "data-" ) === 0 ) {
							name = jQuery.camelCase( name.substring(5) );

							dataAttr( this[0], name, data[ name ] );
						}
					}
					jQuery._data( this[0], "parsedAttrs", true );
				}
			}

			return data;

		} else if ( typeof key === "object" ) {
			return this.each(function() {
				jQuery.data( this, key );
			});
		}

		parts = key.split(".");
		parts[1] = parts[1] ? "." + parts[1] : "";

		if ( value === undefined ) {
			data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);

			// Try to fetch any internally stored data first
			if ( data === undefined && this.length ) {
				data = jQuery.data( this[0], key );
				data = dataAttr( this[0], key, data );
			}

			return data === undefined && parts[1] ?
				this.data( parts[0] ) :
				data;

		} else {
			return this.each(function() {
				var self = jQuery( this ),
					args = [ parts[0], value ];

				self.triggerHandler( "setData" + parts[1] + "!", args );
				jQuery.data( this, key, value );
				self.triggerHandler( "changeData" + parts[1] + "!", args );
			});
		}
	},

	removeData: function( key ) {
		return this.each(function() {
			jQuery.removeData( this, key );
		});
	}
});

function dataAttr( elem, key, data ) {
	// If nothing was found internally, try to fetch any
	// data from the HTML5 data-* attribute
	if ( data === undefined && elem.nodeType === 1 ) {

		var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();

		data = elem.getAttribute( name );

		if ( typeof data === "string" ) {
			try {
				data = data === "true" ? true :
				data === "false" ? false :
				data === "null" ? null :
				jQuery.isNumeric( data ) ? parseFloat( data ) :
					rbrace.test( data ) ? jQuery.parseJSON( data ) :
					data;
			} catch( e ) {}

			// Make sure we set the data so it isn't changed later
			jQuery.data( elem, key, data );

		} else {
			data = undefined;
		}
	}

	return data;
}

// checks a cache object for emptiness
function isEmptyDataObject( obj ) {
	for ( var name in obj ) {

		// if the public data object is empty, the private is still empty
		if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
			continue;
		}
		if ( name !== "toJSON" ) {
			return false;
		}
	}

	return true;
}




function handleQueueMarkDefer( elem, type, src ) {
	var deferDataKey = type + "defer",
		queueDataKey = type + "queue",
		markDataKey = type + "mark",
		defer = jQuery._data( elem, deferDataKey );
	if ( defer &&
		( src === "queue" || !jQuery._data(elem, queueDataKey) ) &&
		( src === "mark" || !jQuery._data(elem, markDataKey) ) ) {
		// Give room for hard-coded callbacks to fire first
		// and eventually mark/queue something else on the element
		setTimeout( function() {
			if ( !jQuery._data( elem, queueDataKey ) &&
				!jQuery._data( elem, markDataKey ) ) {
				jQuery.removeData( elem, deferDataKey, true );
				defer.fire();
			}
		}, 0 );
	}
}

jQuery.extend({

	_mark: function( elem, type ) {
		if ( elem ) {
			type = ( type || "fx" ) + "mark";
			jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );
		}
	},

	_unmark: function( force, elem, type ) {
		if ( force !== true ) {
			type = elem;
			elem = force;
			force = false;
		}
		if ( elem ) {
			type = type || "fx";
			var key = type + "mark",
				count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );
			if ( count ) {
				jQuery._data( elem, key, count );
			} else {
				jQuery.removeData( elem, key, true );
				handleQueueMarkDefer( elem, type, "mark" );
			}
		}
	},

	queue: function( elem, type, data ) {
		var q;
		if ( elem ) {
			type = ( type || "fx" ) + "queue";
			q = jQuery._data( elem, type );

			// Speed up dequeue by getting out quickly if this is just a lookup
			if ( data ) {
				if ( !q || jQuery.isArray(data) ) {
					q = jQuery._data( elem, type, jQuery.makeArray(data) );
				} else {
					q.push( data );
				}
			}
			return q || [];
		}
	},

	dequeue: function( elem, type ) {
		type = type || "fx";

		var queue = jQuery.queue( elem, type ),
			fn = queue.shift(),
			hooks = {};

		// If the fx queue is dequeued, always remove the progress sentinel
		if ( fn === "inprogress" ) {
			fn = queue.shift();
		}

		if ( fn ) {
			// Add a progress sentinel to prevent the fx queue from being
			// automatically dequeued
			if ( type === "fx" ) {
				queue.unshift( "inprogress" );
			}

			jQuery._data( elem, type + ".run", hooks );
			fn.call( elem, function() {
				jQuery.dequeue( elem, type );
			}, hooks );
		}

		if ( !queue.length ) {
			jQuery.removeData( elem, type + "queue " + type + ".run", true );
			handleQueueMarkDefer( elem, type, "queue" );
		}
	}
});

jQuery.fn.extend({
	queue: function( type, data ) {
		if ( typeof type !== "string" ) {
			data = type;
			type = "fx";
		}

		if ( data === undefined ) {
			return jQuery.queue( this[0], type );
		}
		return this.each(function() {
			var queue = jQuery.queue( this, type, data );

			if ( type === "fx" && queue[0] !== "inprogress" ) {
				jQuery.dequeue( this, type );
			}
		});
	},
	dequeue: function( type ) {
		return this.each(function() {
			jQuery.dequeue( this, type );
		});
	},
	// Based off of the plugin by Clint Helfers, with permission.
	// http://blindsignals.com/index.php/2009/07/jquery-delay/
	delay: function( time, type ) {
		time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
		type = type || "fx";

		return this.queue( type, function( next, hooks ) {
			var timeout = setTimeout( next, time );
			hooks.stop = function() {
				clearTimeout( timeout );
			};
		});
	},
	clearQueue: function( type ) {
		return this.queue( type || "fx", [] );
	},
	// Get a promise resolved when queues of a certain type
	// are emptied (fx is the type by default)
	promise: function( type, object ) {
		if ( typeof type !== "string" ) {
			object = type;
			type = undefined;
		}
		type = type || "fx";
		var defer = jQuery.Deferred(),
			elements = this,
			i = elements.length,
			count = 1,
			deferDataKey = type + "defer",
			queueDataKey = type + "queue",
			markDataKey = type + "mark",
			tmp;
		function resolve() {
			if ( !( --count ) ) {
				defer.resolveWith( elements, [ elements ] );
			}
		}
		while( i-- ) {
			if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
					( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||
						jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
					jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) {
				count++;
				tmp.add( resolve );
			}
		}
		resolve();
		return defer.promise();
	}
});




var rclass = /[\n\t\r]/g,
	rspace = /\s+/,
	rreturn = /\r/g,
	rtype = /^(?:button|input)$/i,
	rfocusable = /^(?:button|input|object|select|textarea)$/i,
	rclickable = /^a(?:rea)?$/i,
	rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
	getSetAttribute = jQuery.support.getSetAttribute,
	nodeHook, boolHook, fixSpecified;

jQuery.fn.extend({
	attr: function( name, value ) {
		return jQuery.access( this, name, value, true, jQuery.attr );
	},

	removeAttr: function( name ) {
		return this.each(function() {
			jQuery.removeAttr( this, name );
		});
	},

	prop: function( name, value ) {
		return jQuery.access( this, name, value, true, jQuery.prop );
	},

	removeProp: function( name ) {
		name = jQuery.propFix[ name ] || name;
		return this.each(function() {
			// try/catch handles cases where IE balks (such as removing a property on window)
			try {
				this[ name ] = undefined;
				delete this[ name ];
			} catch( e ) {}
		});
	},

	addClass: function( value ) {
		var classNames, i, l, elem,
			setClass, c, cl;

		if ( jQuery.isFunction( value ) ) {
			return this.each(function( j ) {
				jQuery( this ).addClass( value.call(this, j, this.className) );
			});
		}

		if ( value && typeof value === "string" ) {
			classNames = value.split( rspace );

			for ( i = 0, l = this.length; i < l; i++ ) {
				elem = this[ i ];

				if ( elem.nodeType === 1 ) {
					if ( !elem.className && classNames.length === 1 ) {
						elem.className = value;

					} else {
						setClass = " " + elem.className + " ";

						for ( c = 0, cl = classNames.length; c < cl; c++ ) {
							if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
								setClass += classNames[ c ] + " ";
							}
						}
						elem.className = jQuery.trim( setClass );
					}
				}
			}
		}

		return this;
	},

	removeClass: function( value ) {
		var classNames, i, l, elem, className, c, cl;

		if ( jQuery.isFunction( value ) ) {
			return this.each(function( j ) {
				jQuery( this ).removeClass( value.call(this, j, this.className) );
			});
		}

		if ( (value && typeof value === "string") || value === undefined ) {
			classNames = ( value || "" ).split( rspace );

			for ( i = 0, l = this.length; i < l; i++ ) {
				elem = this[ i ];

				if ( elem.nodeType === 1 && elem.className ) {
					if ( value ) {
						className = (" " + elem.className + " ").replace( rclass, " " );
						for ( c = 0, cl = classNames.length; c < cl; c++ ) {
							className = className.replace(" " + classNames[ c ] + " ", " ");
						}
						elem.className = jQuery.trim( className );

					} else {
						elem.className = "";
					}
				}
			}
		}

		return this;
	},

	toggleClass: function( value, stateVal ) {
		var type = typeof value,
			isBool = typeof stateVal === "boolean";

		if ( jQuery.isFunction( value ) ) {
			return this.each(function( i ) {
				jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
			});
		}

		return this.each(function() {
			if ( type === "string" ) {
				// toggle individual class names
				var className,
					i = 0,
					self = jQuery( this ),
					state = stateVal,
					classNames = value.split( rspace );

				while ( (className = classNames[ i++ ]) ) {
					// check each className given, space seperated list
					state = isBool ? state : !self.hasClass( className );
					self[ state ? "addClass" : "removeClass" ]( className );
				}

			} else if ( type === "undefined" || type === "boolean" ) {
				if ( this.className ) {
					// store className if set
					jQuery._data( this, "__className__", this.className );
				}

				// toggle whole className
				this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
			}
		});
	},

	hasClass: function( selector ) {
		var className = " " + selector + " ",
			i = 0,
			l = this.length;
		for ( ; i < l; i++ ) {
			if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
				return true;
			}
		}

		return false;
	},

	val: function( value ) {
		var hooks, ret, isFunction,
			elem = this[0];

		if ( !arguments.length ) {
			if ( elem ) {
				hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];

				if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
					return ret;
				}

				ret = elem.value;

				return typeof ret === "string" ?
					// handle most common string cases
					ret.replace(rreturn, "") :
					// handle cases where value is null/undef or number
					ret == null ? "" : ret;
			}

			return;
		}

		isFunction = jQuery.isFunction( value );

		return this.each(function( i ) {
			var self = jQuery(this), val;

			if ( this.nodeType !== 1 ) {
				return;
			}

			if ( isFunction ) {
				val = value.call( this, i, self.val() );
			} else {
				val = value;
			}

			// Treat null/undefined as ""; convert numbers to string
			if ( val == null ) {
				val = "";
			} else if ( typeof val === "number" ) {
				val += "";
			} else if ( jQuery.isArray( val ) ) {
				val = jQuery.map(val, function ( value ) {
					return value == null ? "" : value + "";
				});
			}

			hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];

			// If set returns undefined, fall back to normal setting
			if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
				this.value = val;
			}
		});
	}
});

jQuery.extend({
	valHooks: {
		option: {
			get: function( elem ) {
				// attributes.value is undefined in Blackberry 4.7 but
				// uses .value. See #6932
				var val = elem.attributes.value;
				return !val || val.specified ? elem.value : elem.text;
			}
		},
		select: {
			get: function( elem ) {
				var value, i, max, option,
					index = elem.selectedIndex,
					values = [],
					options = elem.options,
					one = elem.type === "select-one";

				// Nothing was selected
				if ( index < 0 ) {
					return null;
				}

				// Loop through all the selected options
				i = one ? index : 0;
				max = one ? index + 1 : options.length;
				for ( ; i < max; i++ ) {
					option = options[ i ];

					// Don't return options that are disabled or in a disabled optgroup
					if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
							(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {

						// Get the specific value for the option
						value = jQuery( option ).val();

						// We don't need an array for one selects
						if ( one ) {
							return value;
						}

						// Multi-Selects return an array
						values.push( value );
					}
				}

				// Fixes Bug #2551 -- select.val() broken in IE after form.reset()
				if ( one && !values.length && options.length ) {
					return jQuery( options[ index ] ).val();
				}

				return values;
			},

			set: function( elem, value ) {
				var values = jQuery.makeArray( value );

				jQuery(elem).find("option").each(function() {
					this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
				});

				if ( !values.length ) {
					elem.selectedIndex = -1;
				}
				return values;
			}
		}
	},

	attrFn: {
		val: true,
		css: true,
		html: true,
		text: true,
		data: true,
		width: true,
		height: true,
		offset: true
	},

	attr: function( elem, name, value, pass ) {
		var ret, hooks, notxml,
			nType = elem.nodeType;

		// don't get/set attributes on text, comment and attribute nodes
		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
			return;
		}

		if ( pass && name in jQuery.attrFn ) {
			return jQuery( elem )[ name ]( value );
		}

		// Fallback to prop when attributes are not supported
		if ( typeof elem.getAttribute === "undefined" ) {
			return jQuery.prop( elem, name, value );
		}

		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );

		// All attributes are lowercase
		// Grab necessary hook if one is defined
		if ( notxml ) {
			name = name.toLowerCase();
			hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
		}

		if ( value !== undefined ) {

			if ( value === null ) {
				jQuery.removeAttr( elem, name );
				return;

			} else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
				return ret;

			} else {
				elem.setAttribute( name, "" + value );
				return value;
			}

		} else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
			return ret;

		} else {

			ret = elem.getAttribute( name );

			// Non-existent attributes return null, we normalize to undefined
			return ret === null ?
				undefined :
				ret;
		}
	},

	removeAttr: function( elem, value ) {
		var propName, attrNames, name, l,
			i = 0;

		if ( value && elem.nodeType === 1 ) {
			attrNames = value.toLowerCase().split( rspace );
			l = attrNames.length;

			for ( ; i < l; i++ ) {
				name = attrNames[ i ];

				if ( name ) {
					propName = jQuery.propFix[ name ] || name;

					// See #9699 for explanation of this approach (setting first, then removal)
					jQuery.attr( elem, name, "" );
					elem.removeAttribute( getSetAttribute ? name : propName );

					// Set corresponding property to false for boolean attributes
					if ( rboolean.test( name ) && propName in elem ) {
						elem[ propName ] = false;
					}
				}
			}
		}
	},

	attrHooks: {
		type: {
			set: function( elem, value ) {
				// We can't allow the type property to be changed (since it causes problems in IE)
				if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
					jQuery.error( "type property can't be changed" );
				} else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
					// Setting the type on a radio button after the value resets the value in IE6-9
					// Reset value to it's default in case type is set after value
					// This is for element creation
					var val = elem.value;
					elem.setAttribute( "type", value );
					if ( val ) {
						elem.value = val;
					}
					return value;
				}
			}
		},
		// Use the value property for back compat
		// Use the nodeHook for button elements in IE6/7 (#1954)
		value: {
			get: function( elem, name ) {
				if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
					return nodeHook.get( elem, name );
				}
				return name in elem ?
					elem.value :
					null;
			},
			set: function( elem, value, name ) {
				if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
					return nodeHook.set( elem, value, name );
				}
				// Does not return so that setAttribute is also used
				elem.value = value;
			}
		}
	},

	propFix: {
		tabindex: "tabIndex",
		readonly: "readOnly",
		"for": "htmlFor",
		"class": "className",
		maxlength: "maxLength",
		cellspacing: "cellSpacing",
		cellpadding: "cellPadding",
		rowspan: "rowSpan",
		colspan: "colSpan",
		usemap: "useMap",
		frameborder: "frameBorder",
		contenteditable: "contentEditable"
	},

	prop: function( elem, name, value ) {
		var ret, hooks, notxml,
			nType = elem.nodeType;

		// don't get/set properties on text, comment and attribute nodes
		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
			return;
		}

		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );

		if ( notxml ) {
			// Fix name and attach hooks
			name = jQuery.propFix[ name ] || name;
			hooks = jQuery.propHooks[ name ];
		}

		if ( value !== undefined ) {
			if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
				return ret;

			} else {
				return ( elem[ name ] = value );
			}

		} else {
			if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
				return ret;

			} else {
				return elem[ name ];
			}
		}
	},

	propHooks: {
		tabIndex: {
			get: function( elem ) {
				// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
				var attributeNode = elem.getAttributeNode("tabindex");

				return attributeNode && attributeNode.specified ?
					parseInt( attributeNode.value, 10 ) :
					rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
						0 :
						undefined;
			}
		}
	}
});

// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)
jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;

// Hook for boolean attributes
boolHook = {
	get: function( elem, name ) {
		// Align boolean attributes with corresponding properties
		// Fall back to attribute presence where some booleans are not supported
		var attrNode,
			property = jQuery.prop( elem, name );
		return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
			name.toLowerCase() :
			undefined;
	},
	set: function( elem, value, name ) {
		var propName;
		if ( value === false ) {
			// Remove boolean attributes when set to false
			jQuery.removeAttr( elem, name );
		} else {
			// value is true since we know at this point it's type boolean and not false
			// Set boolean attributes to the same name and set the DOM property
			propName = jQuery.propFix[ name ] || name;
			if ( propName in elem ) {
				// Only set the IDL specifically if it already exists on the element
				elem[ propName ] = true;
			}

			elem.setAttribute( name, name.toLowerCase() );
		}
		return name;
	}
};

// IE6/7 do not support getting/setting some attributes with get/setAttribute
if ( !getSetAttribute ) {

	fixSpecified = {
		name: true,
		id: true
	};

	// Use this for any attribute in IE6/7
	// This fixes almost every IE6/7 issue
	nodeHook = jQuery.valHooks.button = {
		get: function( elem, name ) {
			var ret;
			ret = elem.getAttributeNode( name );
			return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ?
				ret.nodeValue :
				undefined;
		},
		set: function( elem, value, name ) {
			// Set the existing or create a new attribute node
			var ret = elem.getAttributeNode( name );
			if ( !ret ) {
				ret = document.createAttribute( name );
				elem.setAttributeNode( ret );
			}
			return ( ret.nodeValue = value + "" );
		}
	};

	// Apply the nodeHook to tabindex
	jQuery.attrHooks.tabindex.set = nodeHook.set;

	// Set width and height to auto instead of 0 on empty string( Bug #8150 )
	// This is for removals
	jQuery.each([ "width", "height" ], function( i, name ) {
		jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
			set: function( elem, value ) {
				if ( value === "" ) {
					elem.setAttribute( name, "auto" );
					return value;
				}
			}
		});
	});

	// Set contenteditable to false on removals(#10429)
	// Setting to empty string throws an error as an invalid value
	jQuery.attrHooks.contenteditable = {
		get: nodeHook.get,
		set: function( elem, value, name ) {
			if ( value === "" ) {
				value = "false";
			}
			nodeHook.set( elem, value, name );
		}
	};
}


// Some attributes require a special call on IE
if ( !jQuery.support.hrefNormalized ) {
	jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
		jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
			get: function( elem ) {
				var ret = elem.getAttribute( name, 2 );
				return ret === null ? undefined : ret;
			}
		});
	});
}

if ( !jQuery.support.style ) {
	jQuery.attrHooks.style = {
		get: function( elem ) {
			// Return undefined in the case of empty string
			// Normalize to lowercase since IE uppercases css property names
			return elem.style.cssText.toLowerCase() || undefined;
		},
		set: function( elem, value ) {
			return ( elem.style.cssText = "" + value );
		}
	};
}

// Safari mis-reports the default selected property of an option
// Accessing the parent's selectedIndex property fixes it
if ( !jQuery.support.optSelected ) {
	jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
		get: function( elem ) {
			var parent = elem.parentNode;

			if ( parent ) {
				parent.selectedIndex;

				// Make sure that it also works with optgroups, see #5701
				if ( parent.parentNode ) {
					parent.parentNode.selectedIndex;
				}
			}
			return null;
		}
	});
}

// IE6/7 call enctype encoding
if ( !jQuery.support.enctype ) {
	jQuery.propFix.enctype = "encoding";
}

// Radios and checkboxes getter/setter
if ( !jQuery.support.checkOn ) {
	jQuery.each([ "radio", "checkbox" ], function() {
		jQuery.valHooks[ this ] = {
			get: function( elem ) {
				// Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
				return elem.getAttribute("value") === null ? "on" : elem.value;
			}
		};
	});
}
jQuery.each([ "radio", "checkbox" ], function() {
	jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
		set: function( elem, value ) {
			if ( jQuery.isArray( value ) ) {
				return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
			}
		}
	});
});




var rformElems = /^(?:textarea|input|select)$/i,
	rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/,
	rhoverHack = /\bhover(\.\S+)?\b/,
	rkeyEvent = /^key/,
	rmouseEvent = /^(?:mouse|contextmenu)|click/,
	rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
	rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,
	quickParse = function( selector ) {
		var quick = rquickIs.exec( selector );
		if ( quick ) {
			//   0  1    2   3
			// [ _, tag, id, class ]
			quick[1] = ( quick[1] || "" ).toLowerCase();
			quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" );
		}
		return quick;
	},
	quickIs = function( elem, m ) {
		var attrs = elem.attributes || {};
		return (
			(!m[1] || elem.nodeName.toLowerCase() === m[1]) &&
			(!m[2] || (attrs.id || {}).value === m[2]) &&
			(!m[3] || m[3].test( (attrs[ "class" ] || {}).value ))
		);
	},
	hoverHack = function( events ) {
		return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
	};

/*
 * Helper functions for managing events -- not part of the public interface.
 * Props to Dean Edwards' addEvent library for many of the ideas.
 */
jQuery.event = {

	add: function( elem, types, handler, data, selector ) {

		var elemData, eventHandle, events,
			t, tns, type, namespaces, handleObj,
			handleObjIn, quick, handlers, special;

		// Don't attach events to noData or text/comment nodes (allow plain objects tho)
		if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {
			return;
		}

		// Caller can pass in an object of custom data in lieu of the handler
		if ( handler.handler ) {
			handleObjIn = handler;
			handler = handleObjIn.handler;
		}

		// Make sure that the handler has a unique ID, used to find/remove it later
		if ( !handler.guid ) {
			handler.guid = jQuery.guid++;
		}

		// Init the element's event structure and main handler, if this is the first
		events = elemData.events;
		if ( !events ) {
			elemData.events = events = {};
		}
		eventHandle = elemData.handle;
		if ( !eventHandle ) {
			elemData.handle = eventHandle = function( e ) {
				// Discard the second event of a jQuery.event.trigger() and
				// when an event is called after a page has unloaded
				return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
					jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
					undefined;
			};
			// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
			eventHandle.elem = elem;
		}

		// Handle multiple events separated by a space
		// jQuery(...).bind("mouseover mouseout", fn);
		types = jQuery.trim( hoverHack(types) ).split( " " );
		for ( t = 0; t < types.length; t++ ) {

			tns = rtypenamespace.exec( types[t] ) || [];
			type = tns[1];
			namespaces = ( tns[2] || "" ).split( "." ).sort();

			// If event changes its type, use the special event handlers for the changed type
			special = jQuery.event.special[ type ] || {};

			// If selector defined, determine special event api type, otherwise given type
			type = ( selector ? special.delegateType : special.bindType ) || type;

			// Update special based on newly reset type
			special = jQuery.event.special[ type ] || {};

			// handleObj is passed to all event handlers
			handleObj = jQuery.extend({
				type: type,
				origType: tns[1],
				data: data,
				handler: handler,
				guid: handler.guid,
				selector: selector,
				quick: quickParse( selector ),
				namespace: namespaces.join(".")
			}, handleObjIn );

			// Init the event handler queue if we're the first
			handlers = events[ type ];
			if ( !handlers ) {
				handlers = events[ type ] = [];
				handlers.delegateCount = 0;

				// Only use addEventListener/attachEvent if the special events handler returns false
				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
					// Bind the global event handler to the element
					if ( elem.addEventListener ) {
						elem.addEventListener( type, eventHandle, false );

					} else if ( elem.attachEvent ) {
						elem.attachEvent( "on" + type, eventHandle );
					}
				}
			}

			if ( special.add ) {
				special.add.call( elem, handleObj );

				if ( !handleObj.handler.guid ) {
					handleObj.handler.guid = handler.guid;
				}
			}

			// Add to the element's handler list, delegates in front
			if ( selector ) {
				handlers.splice( handlers.delegateCount++, 0, handleObj );
			} else {
				handlers.push( handleObj );
			}

			// Keep track of which events have ever been used, for event optimization
			jQuery.event.global[ type ] = true;
		}

		// Nullify elem to prevent memory leaks in IE
		elem = null;
	},

	global: {},

	// Detach an event or set of events from an element
	remove: function( elem, types, handler, selector, mappedTypes ) {

		var elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
			t, tns, type, origType, namespaces, origCount,
			j, events, special, handle, eventType, handleObj;

		if ( !elemData || !(events = elemData.events) ) {
			return;
		}

		// Once for each type.namespace in types; type may be omitted
		types = jQuery.trim( hoverHack( types || "" ) ).split(" ");
		for ( t = 0; t < types.length; t++ ) {
			tns = rtypenamespace.exec( types[t] ) || [];
			type = origType = tns[1];
			namespaces = tns[2];

			// Unbind all events (on this namespace, if provided) for the element
			if ( !type ) {
				for ( type in events ) {
					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
				}
				continue;
			}

			special = jQuery.event.special[ type ] || {};
			type = ( selector? special.delegateType : special.bindType ) || type;
			eventType = events[ type ] || [];
			origCount = eventType.length;
			namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null;

			// Remove matching events
			for ( j = 0; j < eventType.length; j++ ) {
				handleObj = eventType[ j ];

				if ( ( mappedTypes || origType === handleObj.origType ) &&
					 ( !handler || handler.guid === handleObj.guid ) &&
					 ( !namespaces || namespaces.test( handleObj.namespace ) ) &&
					 ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
					eventType.splice( j--, 1 );

					if ( handleObj.selector ) {
						eventType.delegateCount--;
					}
					if ( special.remove ) {
						special.remove.call( elem, handleObj );
					}
				}
			}

			// Remove generic event handler if we removed something and no more handlers exist
			// (avoids potential for endless recursion during removal of special event handlers)
			if ( eventType.length === 0 && origCount !== eventType.length ) {
				if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
					jQuery.removeEvent( elem, type, elemData.handle );
				}

				delete events[ type ];
			}
		}

		// Remove the expando if it's no longer used
		if ( jQuery.isEmptyObject( events ) ) {
			handle = elemData.handle;
			if ( handle ) {
				handle.elem = null;
			}

			// removeData also checks for emptiness and clears the expando if empty
			// so use it instead of delete
			jQuery.removeData( elem, [ "events", "handle" ], true );
		}
	},

	// Events that are safe to short-circuit if no handlers are attached.
	// Native DOM events should not be added, they may have inline handlers.
	customEvent: {
		"getData": true,
		"setData": true,
		"changeData": true
	},

	trigger: function( event, data, elem, onlyHandlers ) {
		// Don't do events on text and comment nodes
		if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {
			return;
		}

		// Event object or event type
		var type = event.type || event,
			namespaces = [],
			cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;

		// focus/blur morphs to focusin/out; ensure we're not firing them right now
		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
			return;
		}

		if ( type.indexOf( "!" ) >= 0 ) {
			// Exclusive events trigger only for the exact event (no namespaces)
			type = type.slice(0, -1);
			exclusive = true;
		}

		if ( type.indexOf( "." ) >= 0 ) {
			// Namespaced trigger; create a regexp to match event type in handle()
			namespaces = type.split(".");
			type = namespaces.shift();
			namespaces.sort();
		}

		if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
			// No jQuery handlers for this event type, and it can't have inline handlers
			return;
		}

		// Caller can pass in an Event, Object, or just an event type string
		event = typeof event === "object" ?
			// jQuery.Event object
			event[ jQuery.expando ] ? event :
			// Object literal
			new jQuery.Event( type, event ) :
			// Just the event type (string)
			new jQuery.Event( type );

		event.type = type;
		event.isTrigger = true;
		event.exclusive = exclusive;
		event.namespace = namespaces.join( "." );
		event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
		ontype = type.indexOf( ":" ) < 0 ? "on" + type : "";

		// Handle a global trigger
		if ( !elem ) {

			// TODO: Stop taunting the data cache; remove global events and always attach to document
			cache = jQuery.cache;
			for ( i in cache ) {
				if ( cache[ i ].events && cache[ i ].events[ type ] ) {
					jQuery.event.trigger( event, data, cache[ i ].handle.elem, true );
				}
			}
			return;
		}

		// Clean up the event in case it is being reused
		event.result = undefined;
		if ( !event.target ) {
			event.target = elem;
		}

		// Clone any incoming data and prepend the event, creating the handler arg list
		data = data != null ? jQuery.makeArray( data ) : [];
		data.unshift( event );

		// Allow special events to draw outside the lines
		special = jQuery.event.special[ type ] || {};
		if ( special.trigger && special.trigger.apply( elem, data ) === false ) {
			return;
		}

		// Determine event propagation path in advance, per W3C events spec (#9951)
		// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
		eventPath = [[ elem, special.bindType || type ]];
		if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {

			bubbleType = special.delegateType || type;
			cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;
			old = null;
			for ( ; cur; cur = cur.parentNode ) {
				eventPath.push([ cur, bubbleType ]);
				old = cur;
			}

			// Only add window if we got to document (e.g., not plain obj or detached DOM)
			if ( old && old === elem.ownerDocument ) {
				eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);
			}
		}

		// Fire handlers on the event path
		for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {

			cur = eventPath[i][0];
			event.type = eventPath[i][1];

			handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
			if ( handle ) {
				handle.apply( cur, data );
			}
			// Note that this is a bare JS function and not a jQuery handler
			handle = ontype && cur[ ontype ];
			if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {
				event.preventDefault();
			}
		}
		event.type = type;

		// If nobody prevented the default action, do it now
		if ( !onlyHandlers && !event.isDefaultPrevented() ) {

			if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
				!(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {

				// Call a native DOM method on the target with the same name name as the event.
				// Can't use an .isFunction() check here because IE6/7 fails that test.
				// Don't do default actions on window, that's where global variables be (#6170)
				// IE<9 dies on focus/blur to hidden element (#1486)
				if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {

					// Don't re-trigger an onFOO event when we call its FOO() method
					old = elem[ ontype ];

					if ( old ) {
						elem[ ontype ] = null;
					}

					// Prevent re-triggering of the same event, since we already bubbled it above
					jQuery.event.triggered = type;
					elem[ type ]();
					jQuery.event.triggered = undefined;

					if ( old ) {
						elem[ ontype ] = old;
					}
				}
			}
		}

		return event.result;
	},

	dispatch: function( event ) {

		// Make a writable jQuery.Event from the native event object
		event = jQuery.event.fix( event || window.event );

		var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []),
			delegateCount = handlers.delegateCount,
			args = [].slice.call( arguments, 0 ),
			run_all = !event.exclusive && !event.namespace,
			handlerQueue = [],
			i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;

		// Use the fix-ed jQuery.Event rather than the (read-only) native event
		args[0] = event;
		event.delegateTarget = this;

		// Determine handlers that should run if there are delegated events
		// Avoid disabled elements in IE (#6911) and non-left-click bubbling in Firefox (#3861)
		if ( delegateCount && !event.target.disabled && !(event.button && event.type === "click") ) {

			// Pregenerate a single jQuery object for reuse with .is()
			jqcur = jQuery(this);
			jqcur.context = this.ownerDocument || this;

			for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {
				selMatch = {};
				matches = [];
				jqcur[0] = cur;
				for ( i = 0; i < delegateCount; i++ ) {
					handleObj = handlers[ i ];
					sel = handleObj.selector;

					if ( selMatch[ sel ] === undefined ) {
						selMatch[ sel ] = (
							handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )
						);
					}
					if ( selMatch[ sel ] ) {
						matches.push( handleObj );
					}
				}
				if ( matches.length ) {
					handlerQueue.push({ elem: cur, matches: matches });
				}
			}
		}

		// Add the remaining (directly-bound) handlers
		if ( handlers.length > delegateCount ) {
			handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });
		}

		// Run delegates first; they may want to stop propagation beneath us
		for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {
			matched = handlerQueue[ i ];
			event.currentTarget = matched.elem;

			for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {
				handleObj = matched.matches[ j ];

				// Triggered event must either 1) be non-exclusive and have no namespace, or
				// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
				if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {

					event.data = handleObj.data;
					event.handleObj = handleObj;

					ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
							.apply( matched.elem, args );

					if ( ret !== undefined ) {
						event.result = ret;
						if ( ret === false ) {
							event.preventDefault();
							event.stopPropagation();
						}
					}
				}
			}
		}

		return event.result;
	},

	// Includes some event props shared by KeyEvent and MouseEvent
	// *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***
	props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),

	fixHooks: {},

	keyHooks: {
		props: "char charCode key keyCode".split(" "),
		filter: function( event, original ) {

			// Add which for key events
			if ( event.which == null ) {
				event.which = original.charCode != null ? original.charCode : original.keyCode;
			}

			return event;
		}
	},

	mouseHooks: {
		props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
		filter: function( event, original ) {
			var eventDoc, doc, body,
				button = original.button,
				fromElement = original.fromElement;

			// Calculate pageX/Y if missing and clientX/Y available
			if ( event.pageX == null && original.clientX != null ) {
				eventDoc = event.target.ownerDocument || document;
				doc = eventDoc.documentElement;
				body = eventDoc.body;

				event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
				event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
			}

			// Add relatedTarget, if necessary
			if ( !event.relatedTarget && fromElement ) {
				event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
			}

			// Add which for click: 1 === left; 2 === middle; 3 === right
			// Note: button is not normalized, so don't use it
			if ( !event.which && button !== undefined ) {
				event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
			}

			return event;
		}
	},

	fix: function( event ) {
		if ( event[ jQuery.expando ] ) {
			return event;
		}

		// Create a writable copy of the event object and normalize some properties
		var i, prop,
			originalEvent = event,
			fixHook = jQuery.event.fixHooks[ event.type ] || {},
			copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;

		event = jQuery.Event( originalEvent );

		for ( i = copy.length; i; ) {
			prop = copy[ --i ];
			event[ prop ] = originalEvent[ prop ];
		}

		// Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)
		if ( !event.target ) {
			event.target = originalEvent.srcElement || document;
		}

		// Target should not be a text node (#504, Safari)
		if ( event.target.nodeType === 3 ) {
			event.target = event.target.parentNode;
		}

		// For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)
		if ( event.metaKey === undefined ) {
			event.metaKey = event.ctrlKey;
		}

		return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
	},

	special: {
		ready: {
			// Make sure the ready event is setup
			setup: jQuery.bindReady
		},

		load: {
			// Prevent triggered image.load events from bubbling to window.load
			noBubble: true
		},

		focus: {
			delegateType: "focusin"
		},
		blur: {
			delegateType: "focusout"
		},

		beforeunload: {
			setup: function( data, namespaces, eventHandle ) {
				// We only want to do this special case on windows
				if ( jQuery.isWindow( this ) ) {
					this.onbeforeunload = eventHandle;
				}
			},

			teardown: function( namespaces, eventHandle ) {
				if ( this.onbeforeunload === eventHandle ) {
					this.onbeforeunload = null;
				}
			}
		}
	},

	simulate: function( type, elem, event, bubble ) {
		// Piggyback on a donor event to simulate a different one.
		// Fake originalEvent to avoid donor's stopPropagation, but if the
		// simulated event prevents default then we do the same on the donor.
		var e = jQuery.extend(
			new jQuery.Event(),
			event,
			{ type: type,
				isSimulated: true,
				originalEvent: {}
			}
		);
		if ( bubble ) {
			jQuery.event.trigger( e, null, elem );
		} else {
			jQuery.event.dispatch.call( elem, e );
		}
		if ( e.isDefaultPrevented() ) {
			event.preventDefault();
		}
	}
};

// Some plugins are using, but it's undocumented/deprecated and will be removed.
// The 1.7 special event interface should provide all the hooks needed now.
jQuery.event.handle = jQuery.event.dispatch;

jQuery.removeEvent = document.removeEventListener ?
	function( elem, type, handle ) {
		if ( elem.removeEventListener ) {
			elem.removeEventListener( type, handle, false );
		}
	} :
	function( elem, type, handle ) {
		if ( elem.detachEvent ) {
			elem.detachEvent( "on" + type, handle );
		}
	};

jQuery.Event = function( src, props ) {
	// Allow instantiation without the 'new' keyword
	if ( !(this instanceof jQuery.Event) ) {
		return new jQuery.Event( src, props );
	}

	// Event object
	if ( src && src.type ) {
		this.originalEvent = src;
		this.type = src.type;

		// Events bubbling up the document may have been marked as prevented
		// by a handler lower down the tree; reflect the correct value.
		this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
			src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;

	// Event type
	} else {
		this.type = src;
	}

	// Put explicitly provided properties onto the event object
	if ( props ) {
		jQuery.extend( this, props );
	}

	// Create a timestamp if incoming event doesn't have one
	this.timeStamp = src && src.timeStamp || jQuery.now();

	// Mark it as fixed
	this[ jQuery.expando ] = true;
};

function returnFalse() {
	return false;
}
function returnTrue() {
	return true;
}

// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
jQuery.Event.prototype = {
	preventDefault: function() {
		this.isDefaultPrevented = returnTrue;

		var e = this.originalEvent;
		if ( !e ) {
			return;
		}

		// if preventDefault exists run it on the original event
		if ( e.preventDefault ) {
			e.preventDefault();

		// otherwise set the returnValue property of the original event to false (IE)
		} else {
			e.returnValue = false;
		}
	},
	stopPropagation: function() {
		this.isPropagationStopped = returnTrue;

		var e = this.originalEvent;
		if ( !e ) {
			return;
		}
		// if stopPropagation exists run it on the original event
		if ( e.stopPropagation ) {
			e.stopPropagation();
		}
		// otherwise set the cancelBubble property of the original event to true (IE)
		e.cancelBubble = true;
	},
	stopImmediatePropagation: function() {
		this.isImmediatePropagationStopped = returnTrue;
		this.stopPropagation();
	},
	isDefaultPrevented: returnFalse,
	isPropagationStopped: returnFalse,
	isImmediatePropagationStopped: returnFalse
};

// Create mouseenter/leave events using mouseover/out and event-time checks
jQuery.each({
	mouseenter: "mouseover",
	mouseleave: "mouseout"
}, function( orig, fix ) {
	jQuery.event.special[ orig ] = {
		delegateType: fix,
		bindType: fix,

		handle: function( event ) {
			var target = this,
				related = event.relatedTarget,
				handleObj = event.handleObj,
				selector = handleObj.selector,
				ret;

			// For mousenter/leave call the handler if related is outside the target.
			// NB: No relatedTarget if the mouse left/entered the browser window
			if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
				event.type = handleObj.origType;
				ret = handleObj.handler.apply( this, arguments );
				event.type = fix;
			}
			return ret;
		}
	};
});

// IE submit delegation
if ( !jQuery.support.submitBubbles ) {

	jQuery.event.special.submit = {
		setup: function() {
			// Only need this for delegated form submit events
			if ( jQuery.nodeName( this, "form" ) ) {
				return false;
			}

			// Lazy-add a submit handler when a descendant form may potentially be submitted
			jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
				// Node name check avoids a VML-related crash in IE (#9807)
				var elem = e.target,
					form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
				if ( form && !form._submit_attached ) {
					jQuery.event.add( form, "submit._submit", function( event ) {
						// If form was submitted by the user, bubble the event up the tree
						if ( this.parentNode && !event.isTrigger ) {
							jQuery.event.simulate( "submit", this.parentNode, event, true );
						}
					});
					form._submit_attached = true;
				}
			});
			// return undefined since we don't need an event listener
		},

		teardown: function() {
			// Only need this for delegated form submit events
			if ( jQuery.nodeName( this, "form" ) ) {
				return false;
			}

			// Remove delegated handlers; cleanData eventually reaps submit handlers attached above
			jQuery.event.remove( this, "._submit" );
		}
	};
}

// IE change delegation and checkbox/radio fix
if ( !jQuery.support.changeBubbles ) {

	jQuery.event.special.change = {

		setup: function() {

			if ( rformElems.test( this.nodeName ) ) {
				// IE doesn't fire change on a check/radio until blur; trigger it on click
				// after a propertychange. Eat the blur-change in special.change.handle.
				// This still fires onchange a second time for check/radio after blur.
				if ( this.type === "checkbox" || this.type === "radio" ) {
					jQuery.event.add( this, "propertychange._change", function( event ) {
						if ( event.originalEvent.propertyName === "checked" ) {
							this._just_changed = true;
						}
					});
					jQuery.event.add( this, "click._change", function( event ) {
						if ( this._just_changed && !event.isTrigger ) {
							this._just_changed = false;
							jQuery.event.simulate( "change", this, event, true );
						}
					});
				}
				return false;
			}
			// Delegated event; lazy-add a change handler on descendant inputs
			jQuery.event.add( this, "beforeactivate._change", function( e ) {
				var elem = e.target;

				if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {
					jQuery.event.add( elem, "change._change", function( event ) {
						if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
							jQuery.event.simulate( "change", this.parentNode, event, true );
						}
					});
					elem._change_attached = true;
				}
			});
		},

		handle: function( event ) {
			var elem = event.target;

			// Swallow native change events from checkbox/radio, we already triggered them above
			if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
				return event.handleObj.handler.apply( this, arguments );
			}
		},

		teardown: function() {
			jQuery.event.remove( this, "._change" );

			return rformElems.test( this.nodeName );
		}
	};
}

// Create "bubbling" focus and blur events
if ( !jQuery.support.focusinBubbles ) {
	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {

		// Attach a single capturing handler while someone wants focusin/focusout
		var attaches = 0,
			handler = function( event ) {
				jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
			};

		jQuery.event.special[ fix ] = {
			setup: function() {
				if ( attaches++ === 0 ) {
					document.addEventListener( orig, handler, true );
				}
			},
			teardown: function() {
				if ( --attaches === 0 ) {
					document.removeEventListener( orig, handler, true );
				}
			}
		};
	});
}

jQuery.fn.extend({

	on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
		var origFn, type;

		// Types can be a map of types/handlers
		if ( typeof types === "object" ) {
			// ( types-Object, selector, data )
			if ( typeof selector !== "string" ) {
				// ( types-Object, data )
				data = selector;
				selector = undefined;
			}
			for ( type in types ) {
				this.on( type, selector, data, types[ type ], one );
			}
			return this;
		}

		if ( data == null && fn == null ) {
			// ( types, fn )
			fn = selector;
			data = selector = undefined;
		} else if ( fn == null ) {
			if ( typeof selector === "string" ) {
				// ( types, selector, fn )
				fn = data;
				data = undefined;
			} else {
				// ( types, data, fn )
				fn = data;
				data = selector;
				selector = undefined;
			}
		}
		if ( fn === false ) {
			fn = returnFalse;
		} else if ( !fn ) {
			return this;
		}

		if ( one === 1 ) {
			origFn = fn;
			fn = function( event ) {
				// Can use an empty set, since event contains the info
				jQuery().off( event );
				return origFn.apply( this, arguments );
			};
			// Use same guid so caller can remove using origFn
			fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
		}
		return this.each( function() {
			jQuery.event.add( this, types, fn, data, selector );
		});
	},
	one: function( types, selector, data, fn ) {
		return this.on.call( this, types, selector, data, fn, 1 );
	},
	off: function( types, selector, fn ) {
		if ( types && types.preventDefault && types.handleObj ) {
			// ( event )  dispatched jQuery.Event
			var handleObj = types.handleObj;
			jQuery( types.delegateTarget ).off(
				handleObj.namespace? handleObj.type + "." + handleObj.namespace : handleObj.type,
				handleObj.selector,
				handleObj.handler
			);
			return this;
		}
		if ( typeof types === "object" ) {
			// ( types-object [, selector] )
			for ( var type in types ) {
				this.off( type, selector, types[ type ] );
			}
			return this;
		}
		if ( selector === false || typeof selector === "function" ) {
			// ( types [, fn] )
			fn = selector;
			selector = undefined;
		}
		if ( fn === false ) {
			fn = returnFalse;
		}
		return this.each(function() {
			jQuery.event.remove( this, types, fn, selector );
		});
	},

	bind: function( types, data, fn ) {
		return this.on( types, null, data, fn );
	},
	unbind: function( types, fn ) {
		return this.off( types, null, fn );
	},

	live: function( types, data, fn ) {
		jQuery( this.context ).on( types, this.selector, data, fn );
		return this;
	},
	die: function( types, fn ) {
		jQuery( this.context ).off( types, this.selector || "**", fn );
		return this;
	},

	delegate: function( selector, types, data, fn ) {
		return this.on( types, selector, data, fn );
	},
	undelegate: function( selector, types, fn ) {
		// ( namespace ) or ( selector, types [, fn] )
		return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn );
	},

	trigger: function( type, data ) {
		return this.each(function() {
			jQuery.event.trigger( type, data, this );
		});
	},
	triggerHandler: function( type, data ) {
		if ( this[0] ) {
			return jQuery.event.trigger( type, data, this[0], true );
		}
	},

	toggle: function( fn ) {
		// Save reference to arguments for access in closure
		var args = arguments,
			guid = fn.guid || jQuery.guid++,
			i = 0,
			toggler = function( event ) {
				// Figure out which function to execute
				var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
				jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );

				// Make sure that clicks stop
				event.preventDefault();

				// and execute the function
				return args[ lastToggle ].apply( this, arguments ) || false;
			};

		// link all the functions, so any of them can unbind this click handler
		toggler.guid = guid;
		while ( i < args.length ) {
			args[ i++ ].guid = guid;
		}

		return this.click( toggler );
	},

	hover: function( fnOver, fnOut ) {
		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
	}
});

jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
	"change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {

	// Handle event binding
	jQuery.fn[ name ] = function( data, fn ) {
		if ( fn == null ) {
			fn = data;
			data = null;
		}

		return arguments.length > 0 ?
			this.on( name, null, data, fn ) :
			this.trigger( name );
	};

	if ( jQuery.attrFn ) {
		jQuery.attrFn[ name ] = true;
	}

	if ( rkeyEvent.test( name ) ) {
		jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;
	}

	if ( rmouseEvent.test( name ) ) {
		jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;
	}
});



/*!
 * Sizzle CSS Selector Engine
 *  Copyright 2011, The Dojo Foundation
 *  Released under the MIT, BSD, and GPL Licenses.
 *  More information: http://sizzlejs.com/
 */
(function(){

var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
	expando = "sizcache" + (Math.random() + '').replace('.', ''),
	done = 0,
	toString = Object.prototype.toString,
	hasDuplicate = false,
	baseHasDuplicate = true,
	rBackslash = /\\/g,
	rReturn = /\r\n/g,
	rNonWord = /\W/;

// Here we check if the JavaScript engine is using some sort of
// optimization where it does not always call our comparision
// function. If that is the case, discard the hasDuplicate value.
//   Thus far that includes Google Chrome.
[0, 0].sort(function() {
	baseHasDuplicate = false;
	return 0;
});

var Sizzle = function( selector, context, results, seed ) {
	results = results || [];
	context = context || document;

	var origContext = context;

	if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
		return [];
	}
	
	if ( !selector || typeof selector !== "string" ) {
		return results;
	}

	var m, set, checkSet, extra, ret, cur, pop, i,
		prune = true,
		contextXML = Sizzle.isXML( context ),
		parts = [],
		soFar = selector;
	
	// Reset the position of the chunker regexp (start from head)
	do {
		chunker.exec( "" );
		m = chunker.exec( soFar );

		if ( m ) {
			soFar = m[3];
		
			parts.push( m[1] );
		
			if ( m[2] ) {
				extra = m[3];
				break;
			}
		}
	} while ( m );

	if ( parts.length > 1 && origPOS.exec( selector ) ) {

		if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
			set = posProcess( parts[0] + parts[1], context, seed );

		} else {
			set = Expr.relative[ parts[0] ] ?
				[ context ] :
				Sizzle( parts.shift(), context );

			while ( parts.length ) {
				selector = parts.shift();

				if ( Expr.relative[ selector ] ) {
					selector += parts.shift();
				}
				
				set = posProcess( selector, set, seed );
			}
		}

	} else {
		// Take a shortcut and set the context if the root selector is an ID
		// (but not if it'll be faster if the inner selector is an ID)
		if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
				Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {

			ret = Sizzle.find( parts.shift(), context, contextXML );
			context = ret.expr ?
				Sizzle.filter( ret.expr, ret.set )[0] :
				ret.set[0];
		}

		if ( context ) {
			ret = seed ?
				{ expr: parts.pop(), set: makeArray(seed) } :
				Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );

			set = ret.expr ?
				Sizzle.filter( ret.expr, ret.set ) :
				ret.set;

			if ( parts.length > 0 ) {
				checkSet = makeArray( set );

			} else {
				prune = false;
			}

			while ( parts.length ) {
				cur = parts.pop();
				pop = cur;

				if ( !Expr.relative[ cur ] ) {
					cur = "";
				} else {
					pop = parts.pop();
				}

				if ( pop == null ) {
					pop = context;
				}

				Expr.relative[ cur ]( checkSet, pop, contextXML );
			}

		} else {
			checkSet = parts = [];
		}
	}

	if ( !checkSet ) {
		checkSet = set;
	}

	if ( !checkSet ) {
		Sizzle.error( cur || selector );
	}

	if ( toString.call(checkSet) === "[object Array]" ) {
		if ( !prune ) {
			results.push.apply( results, checkSet );

		} else if ( context && context.nodeType === 1 ) {
			for ( i = 0; checkSet[i] != null; i++ ) {
				if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
					results.push( set[i] );
				}
			}

		} else {
			for ( i = 0; checkSet[i] != null; i++ ) {
				if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
					results.push( set[i] );
				}
			}
		}

	} else {
		makeArray( checkSet, results );
	}

	if ( extra ) {
		Sizzle( extra, origContext, results, seed );
		Sizzle.uniqueSort( results );
	}

	return results;
};

Sizzle.uniqueSort = function( results ) {
	if ( sortOrder ) {
		hasDuplicate = baseHasDuplicate;
		results.sort( sortOrder );

		if ( hasDuplicate ) {
			for ( var i = 1; i < results.length; i++ ) {
				if ( results[i] === results[ i - 1 ] ) {
					results.splice( i--, 1 );
				}
			}
		}
	}

	return results;
};

Sizzle.matches = function( expr, set ) {
	return Sizzle( expr, null, null, set );
};

Sizzle.matchesSelector = function( node, expr ) {
	return Sizzle( expr, null, null, [node] ).length > 0;
};

Sizzle.find = function( expr, context, isXML ) {
	var set, i, len, match, type, left;

	if ( !expr ) {
		return [];
	}

	for ( i = 0, len = Expr.order.length; i < len; i++ ) {
		type = Expr.order[i];
		
		if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
			left = match[1];
			match.splice( 1, 1 );

			if ( left.substr( left.length - 1 ) !== "\\" ) {
				match[1] = (match[1] || "").replace( rBackslash, "" );
				set = Expr.find[ type ]( match, context, isXML );

				if ( set != null ) {
					expr = expr.replace( Expr.match[ type ], "" );
					break;
				}
			}
		}
	}

	if ( !set ) {
		set = typeof context.getElementsByTagName !== "undefined" ?
			context.getElementsByTagName( "*" ) :
			[];
	}

	return { set: set, expr: expr };
};

Sizzle.filter = function( expr, set, inplace, not ) {
	var match, anyFound,
		type, found, item, filter, left,
		i, pass,
		old = expr,
		result = [],
		curLoop = set,
		isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );

	while ( expr && set.length ) {
		for ( type in Expr.filter ) {
			if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
				filter = Expr.filter[ type ];
				left = match[1];

				anyFound = false;

				match.splice(1,1);

				if ( left.substr( left.length - 1 ) === "\\" ) {
					continue;
				}

				if ( curLoop === result ) {
					result = [];
				}

				if ( Expr.preFilter[ type ] ) {
					match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );

					if ( !match ) {
						anyFound = found = true;

					} else if ( match === true ) {
						continue;
					}
				}

				if ( match ) {
					for ( i = 0; (item = curLoop[i]) != null; i++ ) {
						if ( item ) {
							found = filter( item, match, i, curLoop );
							pass = not ^ found;

							if ( inplace && found != null ) {
								if ( pass ) {
									anyFound = true;

								} else {
									curLoop[i] = false;
								}

							} else if ( pass ) {
								result.push( item );
								anyFound = true;
							}
						}
					}
				}

				if ( found !== undefined ) {
					if ( !inplace ) {
						curLoop = result;
					}

					expr = expr.replace( Expr.match[ type ], "" );

					if ( !anyFound ) {
						return [];
					}

					break;
				}
			}
		}

		// Improper expression
		if ( expr === old ) {
			if ( anyFound == null ) {
				Sizzle.error( expr );

			} else {
				break;
			}
		}

		old = expr;
	}

	return curLoop;
};

Sizzle.error = function( msg ) {
	throw new Error( "Syntax error, unrecognized expression: " + msg );
};

/**
 * Utility function for retreiving the text value of an array of DOM nodes
 * @param {Array|Element} elem
 */
var getText = Sizzle.getText = function( elem ) {
    var i, node,
		nodeType = elem.nodeType,
		ret = "";

	if ( nodeType ) {
		if ( nodeType === 1 || nodeType === 9 ) {
			// Use textContent || innerText for elements
			if ( typeof elem.textContent === 'string' ) {
				return elem.textContent;
			} else if ( typeof elem.innerText === 'string' ) {
				// Replace IE's carriage returns
				return elem.innerText.replace( rReturn, '' );
			} else {
				// Traverse it's children
				for ( elem = elem.firstChild; elem; elem = elem.nextSibling) {
					ret += getText( elem );
				}
			}
		} else if ( nodeType === 3 || nodeType === 4 ) {
			return elem.nodeValue;
		}
	} else {

		// If no nodeType, this is expected to be an array
		for ( i = 0; (node = elem[i]); i++ ) {
			// Do not traverse comment nodes
			if ( node.nodeType !== 8 ) {
				ret += getText( node );
			}
		}
	}
	return ret;
};

var Expr = Sizzle.selectors = {
	order: [ "ID", "NAME", "TAG" ],

	match: {
		ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
		CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
		NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
		ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
		TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
		CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
		POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
		PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
	},

	leftMatch: {},

	attrMap: {
		"class": "className",
		"for": "htmlFor"
	},

	attrHandle: {
		href: function( elem ) {
			return elem.getAttribute( "href" );
		},
		type: function( elem ) {
			return elem.getAttribute( "type" );
		}
	},

	relative: {
		"+": function(checkSet, part){
			var isPartStr = typeof part === "string",
				isTag = isPartStr && !rNonWord.test( part ),
				isPartStrNotTag = isPartStr && !isTag;

			if ( isTag ) {
				part = part.toLowerCase();
			}

			for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
				if ( (elem = checkSet[i]) ) {
					while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}

					checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
						elem || false :
						elem === part;
				}
			}

			if ( isPartStrNotTag ) {
				Sizzle.filter( part, checkSet, true );
			}
		},

		">": function( checkSet, part ) {
			var elem,
				isPartStr = typeof part === "string",
				i = 0,
				l = checkSet.length;

			if ( isPartStr && !rNonWord.test( part ) ) {
				part = part.toLowerCase();

				for ( ; i < l; i++ ) {
					elem = checkSet[i];

					if ( elem ) {
						var parent = elem.parentNode;
						checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
					}
				}

			} else {
				for ( ; i < l; i++ ) {
					elem = checkSet[i];

					if ( elem ) {
						checkSet[i] = isPartStr ?
							elem.parentNode :
							elem.parentNode === part;
					}
				}

				if ( isPartStr ) {
					Sizzle.filter( part, checkSet, true );
				}
			}
		},

		"": function(checkSet, part, isXML){
			var nodeCheck,
				doneName = done++,
				checkFn = dirCheck;

			if ( typeof part === "string" && !rNonWord.test( part ) ) {
				part = part.toLowerCase();
				nodeCheck = part;
				checkFn = dirNodeCheck;
			}

			checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
		},

		"~": function( checkSet, part, isXML ) {
			var nodeCheck,
				doneName = done++,
				checkFn = dirCheck;

			if ( typeof part === "string" && !rNonWord.test( part ) ) {
				part = part.toLowerCase();
				nodeCheck = part;
				checkFn = dirNodeCheck;
			}

			checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
		}
	},

	find: {
		ID: function( match, context, isXML ) {
			if ( typeof context.getElementById !== "undefined" && !isXML ) {
				var m = context.getElementById(match[1]);
				// Check parentNode to catch when Blackberry 4.6 returns
				// nodes that are no longer in the document #6963
				return m && m.parentNode ? [m] : [];
			}
		},

		NAME: function( match, context ) {
			if ( typeof context.getElementsByName !== "undefined" ) {
				var ret = [],
					results = context.getElementsByName( match[1] );

				for ( var i = 0, l = results.length; i < l; i++ ) {
					if ( results[i].getAttribute("name") === match[1] ) {
						ret.push( results[i] );
					}
				}

				return ret.length === 0 ? null : ret;
			}
		},

		TAG: function( match, context ) {
			if ( typeof context.getElementsByTagName !== "undefined" ) {
				return context.getElementsByTagName( match[1] );
			}
		}
	},
	preFilter: {
		CLASS: function( match, curLoop, inplace, result, not, isXML ) {
			match = " " + match[1].replace( rBackslash, "" ) + " ";

			if ( isXML ) {
				return match;
			}

			for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
				if ( elem ) {
					if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) {
						if ( !inplace ) {
							result.push( elem );
						}

					} else if ( inplace ) {
						curLoop[i] = false;
					}
				}
			}

			return false;
		},

		ID: function( match ) {
			return match[1].replace( rBackslash, "" );
		},

		TAG: function( match, curLoop ) {
			return match[1].replace( rBackslash, "" ).toLowerCase();
		},

		CHILD: function( match ) {
			if ( match[1] === "nth" ) {
				if ( !match[2] ) {
					Sizzle.error( match[0] );
				}

				match[2] = match[2].replace(/^\+|\s*/g, '');

				// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
				var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec(
					match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
					!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);

				// calculate the numbers (first)n+(last) including if they are negative
				match[2] = (test[1] + (test[2] || 1)) - 0;
				match[3] = test[3] - 0;
			}
			else if ( match[2] ) {
				Sizzle.error( match[0] );
			}

			// TODO: Move to normal caching system
			match[0] = done++;

			return match;
		},

		ATTR: function( match, curLoop, inplace, result, not, isXML ) {
			var name = match[1] = match[1].replace( rBackslash, "" );
			
			if ( !isXML && Expr.attrMap[name] ) {
				match[1] = Expr.attrMap[name];
			}

			// Handle if an un-quoted value was used
			match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" );

			if ( match[2] === "~=" ) {
				match[4] = " " + match[4] + " ";
			}

			return match;
		},

		PSEUDO: function( match, curLoop, inplace, result, not ) {
			if ( match[1] === "not" ) {
				// If we're dealing with a complex expression, or a simple one
				if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
					match[3] = Sizzle(match[3], null, null, curLoop);

				} else {
					var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);

					if ( !inplace ) {
						result.push.apply( result, ret );
					}

					return false;
				}

			} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
				return true;
			}
			
			return match;
		},

		POS: function( match ) {
			match.unshift( true );

			return match;
		}
	},
	
	filters: {
		enabled: function( elem ) {
			return elem.disabled === false && elem.type !== "hidden";
		},

		disabled: function( elem ) {
			return elem.disabled === true;
		},

		checked: function( elem ) {
			return elem.checked === true;
		},
		
		selected: function( elem ) {
			// Accessing this property makes selected-by-default
			// options in Safari work properly
			if ( elem.parentNode ) {
				elem.parentNode.selectedIndex;
			}
			
			return elem.selected === true;
		},

		parent: function( elem ) {
			return !!elem.firstChild;
		},

		empty: function( elem ) {
			return !elem.firstChild;
		},

		has: function( elem, i, match ) {
			return !!Sizzle( match[3], elem ).length;
		},

		header: function( elem ) {
			return (/h\d/i).test( elem.nodeName );
		},

		text: function( elem ) {
			var attr = elem.getAttribute( "type" ), type = elem.type;
			// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) 
			// use getAttribute instead to test this case
			return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null );
		},

		radio: function( elem ) {
			return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type;
		},

		checkbox: function( elem ) {
			return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type;
		},

		file: function( elem ) {
			return elem.nodeName.toLowerCase() === "input" && "file" === elem.type;
		},

		password: function( elem ) {
			return elem.nodeName.toLowerCase() === "input" && "password" === elem.type;
		},

		submit: function( elem ) {
			var name = elem.nodeName.toLowerCase();
			return (name === "input" || name === "button") && "submit" === elem.type;
		},

		image: function( elem ) {
			return elem.nodeName.toLowerCase() === "input" && "image" === elem.type;
		},

		reset: function( elem ) {
			var name = elem.nodeName.toLowerCase();
			return (name === "input" || name === "button") && "reset" === elem.type;
		},

		button: function( elem ) {
			var name = elem.nodeName.toLowerCase();
			return name === "input" && "button" === elem.type || name === "button";
		},

		input: function( elem ) {
			return (/input|select|textarea|button/i).test( elem.nodeName );
		},

		focus: function( elem ) {
			return elem === elem.ownerDocument.activeElement;
		}
	},
	setFilters: {
		first: function( elem, i ) {
			return i === 0;
		},

		last: function( elem, i, match, array ) {
			return i === array.length - 1;
		},

		even: function( elem, i ) {
			return i % 2 === 0;
		},

		odd: function( elem, i ) {
			return i % 2 === 1;
		},

		lt: function( elem, i, match ) {
			return i < match[3] - 0;
		},

		gt: function( elem, i, match ) {
			return i > match[3] - 0;
		},

		nth: function( elem, i, match ) {
			return match[3] - 0 === i;
		},

		eq: function( elem, i, match ) {
			return match[3] - 0 === i;
		}
	},
	filter: {
		PSEUDO: function( elem, match, i, array ) {
			var name = match[1],
				filter = Expr.filters[ name ];

			if ( filter ) {
				return filter( elem, i, match, array );

			} else if ( name === "contains" ) {
				return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;

			} else if ( name === "not" ) {
				var not = match[3];

				for ( var j = 0, l = not.length; j < l; j++ ) {
					if ( not[j] === elem ) {
						return false;
					}
				}

				return true;

			} else {
				Sizzle.error( name );
			}
		},

		CHILD: function( elem, match ) {
			var first, last,
				doneName, parent, cache,
				count, diff,
				type = match[1],
				node = elem;

			switch ( type ) {
				case "only":
				case "first":
					while ( (node = node.previousSibling) )	 {
						if ( node.nodeType === 1 ) { 
							return false; 
						}
					}

					if ( type === "first" ) { 
						return true; 
					}

					node = elem;

				case "last":
					while ( (node = node.nextSibling) )	 {
						if ( node.nodeType === 1 ) { 
							return false; 
						}
					}

					return true;

				case "nth":
					first = match[2];
					last = match[3];

					if ( first === 1 && last === 0 ) {
						return true;
					}
					
					doneName = match[0];
					parent = elem.parentNode;
	
					if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {
						count = 0;
						
						for ( node = parent.firstChild; node; node = node.nextSibling ) {
							if ( node.nodeType === 1 ) {
								node.nodeIndex = ++count;
							}
						} 

						parent[ expando ] = doneName;
					}
					
					diff = elem.nodeIndex - last;

					if ( first === 0 ) {
						return diff === 0;

					} else {
						return ( diff % first === 0 && diff / first >= 0 );
					}
			}
		},

		ID: function( elem, match ) {
			return elem.nodeType === 1 && elem.getAttribute("id") === match;
		},

		TAG: function( elem, match ) {
			return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;
		},
		
		CLASS: function( elem, match ) {
			return (" " + (elem.className || elem.getAttribute("class")) + " ")
				.indexOf( match ) > -1;
		},

		ATTR: function( elem, match ) {
			var name = match[1],
				result = Sizzle.attr ?
					Sizzle.attr( elem, name ) :
					Expr.attrHandle[ name ] ?
					Expr.attrHandle[ name ]( elem ) :
					elem[ name ] != null ?
						elem[ name ] :
						elem.getAttribute( name ),
				value = result + "",
				type = match[2],
				check = match[4];

			return result == null ?
				type === "!=" :
				!type && Sizzle.attr ?
				result != null :
				type === "=" ?
				value === check :
				type === "*=" ?
				value.indexOf(check) >= 0 :
				type === "~=" ?
				(" " + value + " ").indexOf(check) >= 0 :
				!check ?
				value && result !== false :
				type === "!=" ?
				value !== check :
				type === "^=" ?
				value.indexOf(check) === 0 :
				type === "$=" ?
				value.substr(value.length - check.length) === check :
				type === "|=" ?
				value === check || value.substr(0, check.length + 1) === check + "-" :
				false;
		},

		POS: function( elem, match, i, array ) {
			var name = match[2],
				filter = Expr.setFilters[ name ];

			if ( filter ) {
				return filter( elem, i, match, array );
			}
		}
	}
};

var origPOS = Expr.match.POS,
	fescape = function(all, num){
		return "\\" + (num - 0 + 1);
	};

for ( var type in Expr.match ) {
	Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
	Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
}

var makeArray = function( array, results ) {
	array = Array.prototype.slice.call( array, 0 );

	if ( results ) {
		results.push.apply( results, array );
		return results;
	}
	
	return array;
};

// Perform a simple check to determine if the browser is capable of
// converting a NodeList to an array using builtin methods.
// Also verifies that the returned array holds DOM nodes
// (which is not the case in the Blackberry browser)
try {
	Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;

// Provide a fallback method if it does not work
} catch( e ) {
	makeArray = function( array, results ) {
		var i = 0,
			ret = results || [];

		if ( toString.call(array) === "[object Array]" ) {
			Array.prototype.push.apply( ret, array );

		} else {
			if ( typeof array.length === "number" ) {
				for ( var l = array.length; i < l; i++ ) {
					ret.push( array[i] );
				}

			} else {
				for ( ; array[i]; i++ ) {
					ret.push( array[i] );
				}
			}
		}

		return ret;
	};
}

var sortOrder, siblingCheck;

if ( document.documentElement.compareDocumentPosition ) {
	sortOrder = function( a, b ) {
		if ( a === b ) {
			hasDuplicate = true;
			return 0;
		}

		if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
			return a.compareDocumentPosition ? -1 : 1;
		}

		return a.compareDocumentPosition(b) & 4 ? -1 : 1;
	};

} else {
	sortOrder = function( a, b ) {
		// The nodes are identical, we can exit early
		if ( a === b ) {
			hasDuplicate = true;
			return 0;

		// Fallback to using sourceIndex (in IE) if it's available on both nodes
		} else if ( a.sourceIndex && b.sourceIndex ) {
			return a.sourceIndex - b.sourceIndex;
		}

		var al, bl,
			ap = [],
			bp = [],
			aup = a.parentNode,
			bup = b.parentNode,
			cur = aup;

		// If the nodes are siblings (or identical) we can do a quick check
		if ( aup === bup ) {
			return siblingCheck( a, b );

		// If no parents were found then the nodes are disconnected
		} else if ( !aup ) {
			return -1;

		} else if ( !bup ) {
			return 1;
		}

		// Otherwise they're somewhere else in the tree so we need
		// to build up a full list of the parentNodes for comparison
		while ( cur ) {
			ap.unshift( cur );
			cur = cur.parentNode;
		}

		cur = bup;

		while ( cur ) {
			bp.unshift( cur );
			cur = cur.parentNode;
		}

		al = ap.length;
		bl = bp.length;

		// Start walking down the tree looking for a discrepancy
		for ( var i = 0; i < al && i < bl; i++ ) {
			if ( ap[i] !== bp[i] ) {
				return siblingCheck( ap[i], bp[i] );
			}
		}

		// We ended someplace up the tree so do a sibling check
		return i === al ?
			siblingCheck( a, bp[i], -1 ) :
			siblingCheck( ap[i], b, 1 );
	};

	siblingCheck = function( a, b, ret ) {
		if ( a === b ) {
			return ret;
		}

		var cur = a.nextSibling;

		while ( cur ) {
			if ( cur === b ) {
				return -1;
			}

			cur = cur.nextSibling;
		}

		return 1;
	};
}

// Check to see if the browser returns elements by name when
// querying by getElementById (and provide a workaround)
(function(){
	// We're going to inject a fake input element with a specified name
	var form = document.createElement("div"),
		id = "script" + (new Date()).getTime(),
		root = document.documentElement;

	form.innerHTML = "<a name='" + id + "'/>";

	// Inject it into the root element, check its status, and remove it quickly
	root.insertBefore( form, root.firstChild );

	// The workaround has to do additional checks after a getElementById
	// Which slows things down for other browsers (hence the branching)
	if ( document.getElementById( id ) ) {
		Expr.find.ID = function( match, context, isXML ) {
			if ( typeof context.getElementById !== "undefined" && !isXML ) {
				var m = context.getElementById(match[1]);

				return m ?
					m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
						[m] :
						undefined :
					[];
			}
		};

		Expr.filter.ID = function( elem, match ) {
			var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");

			return elem.nodeType === 1 && node && node.nodeValue === match;
		};
	}

	root.removeChild( form );

	// release memory in IE
	root = form = null;
})();

(function(){
	// Check to see if the browser returns only elements
	// when doing getElementsByTagName("*")

	// Create a fake element
	var div = document.createElement("div");
	div.appendChild( document.createComment("") );

	// Make sure no comments are found
	if ( div.getElementsByTagName("*").length > 0 ) {
		Expr.find.TAG = function( match, context ) {
			var results = context.getElementsByTagName( match[1] );

			// Filter out possible comments
			if ( match[1] === "*" ) {
				var tmp = [];

				for ( var i = 0; results[i]; i++ ) {
					if ( results[i].nodeType === 1 ) {
						tmp.push( results[i] );
					}
				}

				results = tmp;
			}

			return results;
		};
	}

	// Check to see if an attribute returns normalized href attributes
	div.innerHTML = "<a href='#'></a>";

	if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
			div.firstChild.getAttribute("href") !== "#" ) {

		Expr.attrHandle.href = function( elem ) {
			return elem.getAttribute( "href", 2 );
		};
	}

	// release memory in IE
	div = null;
})();

if ( document.querySelectorAll ) {
	(function(){
		var oldSizzle = Sizzle,
			div = document.createElement("div"),
			id = "__sizzle__";

		div.innerHTML = "<p class='TEST'></p>";

		// Safari can't handle uppercase or unicode characters when
		// in quirks mode.
		if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
			return;
		}
	
		Sizzle = function( query, context, extra, seed ) {
			context = context || document;

			// Only use querySelectorAll on non-XML documents
			// (ID selectors don't work in non-HTML documents)
			if ( !seed && !Sizzle.isXML(context) ) {
				// See if we find a selector to speed up
				var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query );
				
				if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
					// Speed-up: Sizzle("TAG")
					if ( match[1] ) {
						return makeArray( context.getElementsByTagName( query ), extra );
					
					// Speed-up: Sizzle(".CLASS")
					} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
						return makeArray( context.getElementsByClassName( match[2] ), extra );
					}
				}
				
				if ( context.nodeType === 9 ) {
					// Speed-up: Sizzle("body")
					// The body element only exists once, optimize finding it
					if ( query === "body" && context.body ) {
						return makeArray( [ context.body ], extra );
						
					// Speed-up: Sizzle("#ID")
					} else if ( match && match[3] ) {
						var elem = context.getElementById( match[3] );

						// Check parentNode to catch when Blackberry 4.6 returns
						// nodes that are no longer in the document #6963
						if ( elem && elem.parentNode ) {
							// Handle the case where IE and Opera return items
							// by name instead of ID
							if ( elem.id === match[3] ) {
								return makeArray( [ elem ], extra );
							}
							
						} else {
							return makeArray( [], extra );
						}
					}
					
					try {
						return makeArray( context.querySelectorAll(query), extra );
					} catch(qsaError) {}

				// qSA works strangely on Element-rooted queries
				// We can work around this by specifying an extra ID on the root
				// and working up from there (Thanks to Andrew Dupont for the technique)
				// IE 8 doesn't work on object elements
				} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
					var oldContext = context,
						old = context.getAttribute( "id" ),
						nid = old || id,
						hasParent = context.parentNode,
						relativeHierarchySelector = /^\s*[+~]/.test( query );

					if ( !old ) {
						context.setAttribute( "id", nid );
					} else {
						nid = nid.replace( /'/g, "\\$&" );
					}
					if ( relativeHierarchySelector && hasParent ) {
						context = context.parentNode;
					}

					try {
						if ( !relativeHierarchySelector || hasParent ) {
							return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra );
						}

					} catch(pseudoError) {
					} finally {
						if ( !old ) {
							oldContext.removeAttribute( "id" );
						}
					}
				}
			}
		
			return oldSizzle(query, context, extra, seed);
		};

		for ( var prop in oldSizzle ) {
			Sizzle[ prop ] = oldSizzle[ prop ];
		}

		// release memory in IE
		div = null;
	})();
}

(function(){
	var html = document.documentElement,
		matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;

	if ( matches ) {
		// Check to see if it's possible to do matchesSelector
		// on a disconnected node (IE 9 fails this)
		var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ),
			pseudoWorks = false;

		try {
			// This should fail with an exception
			// Gecko does not error, returns false instead
			matches.call( document.documentElement, "[test!='']:sizzle" );
	
		} catch( pseudoError ) {
			pseudoWorks = true;
		}

		Sizzle.matchesSelector = function( node, expr ) {
			// Make sure that attribute selectors are quoted
			expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");

			if ( !Sizzle.isXML( node ) ) {
				try { 
					if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
						var ret = matches.call( node, expr );

						// IE 9's matchesSelector returns false on disconnected nodes
						if ( ret || !disconnectedMatch ||
								// As well, disconnected nodes are said to be in a document
								// fragment in IE 9, so check for that
								node.document && node.document.nodeType !== 11 ) {
							return ret;
						}
					}
				} catch(e) {}
			}

			return Sizzle(expr, null, null, [node]).length > 0;
		};
	}
})();

(function(){
	var div = document.createElement("div");

	div.innerHTML = "<div class='test e'></div><div class='test'></div>";

	// Opera can't find a second classname (in 9.6)
	// Also, make sure that getElementsByClassName actually exists
	if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
		return;
	}

	// Safari caches class attributes, doesn't catch changes (in 3.2)
	div.lastChild.className = "e";

	if ( div.getElementsByClassName("e").length === 1 ) {
		return;
	}
	
	Expr.order.splice(1, 0, "CLASS");
	Expr.find.CLASS = function( match, context, isXML ) {
		if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
			return context.getElementsByClassName(match[1]);
		}
	};

	// release memory in IE
	div = null;
})();

function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
		var elem = checkSet[i];

		if ( elem ) {
			var match = false;

			elem = elem[dir];

			while ( elem ) {
				if ( elem[ expando ] === doneName ) {
					match = checkSet[elem.sizset];
					break;
				}

				if ( elem.nodeType === 1 && !isXML ){
					elem[ expando ] = doneName;
					elem.sizset = i;
				}

				if ( elem.nodeName.toLowerCase() === cur ) {
					match = elem;
					break;
				}

				elem = elem[dir];
			}

			checkSet[i] = match;
		}
	}
}

function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
		var elem = checkSet[i];

		if ( elem ) {
			var match = false;
			
			elem = elem[dir];

			while ( elem ) {
				if ( elem[ expando ] === doneName ) {
					match = checkSet[elem.sizset];
					break;
				}

				if ( elem.nodeType === 1 ) {
					if ( !isXML ) {
						elem[ expando ] = doneName;
						elem.sizset = i;
					}

					if ( typeof cur !== "string" ) {
						if ( elem === cur ) {
							match = true;
							break;
						}

					} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
						match = elem;
						break;
					}
				}

				elem = elem[dir];
			}

			checkSet[i] = match;
		}
	}
}

if ( document.documentElement.contains ) {
	Sizzle.contains = function( a, b ) {
		return a !== b && (a.contains ? a.contains(b) : true);
	};

} else if ( document.documentElement.compareDocumentPosition ) {
	Sizzle.contains = function( a, b ) {
		return !!(a.compareDocumentPosition(b) & 16);
	};

} else {
	Sizzle.contains = function() {
		return false;
	};
}

Sizzle.isXML = function( elem ) {
	// documentElement is verified for cases where it doesn't yet exist
	// (such as loading iframes in IE - #4833) 
	var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;

	return documentElement ? documentElement.nodeName !== "HTML" : false;
};

var posProcess = function( selector, context, seed ) {
	var match,
		tmpSet = [],
		later = "",
		root = context.nodeType ? [context] : context;

	// Position selectors must be done after the filter
	// And so must :not(positional) so we move all PSEUDOs to the end
	while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
		later += match[0];
		selector = selector.replace( Expr.match.PSEUDO, "" );
	}

	selector = Expr.relative[selector] ? selector + "*" : selector;

	for ( var i = 0, l = root.length; i < l; i++ ) {
		Sizzle( selector, root[i], tmpSet, seed );
	}

	return Sizzle.filter( later, tmpSet );
};

// EXPOSE
// Override sizzle attribute retrieval
Sizzle.attr = jQuery.attr;
Sizzle.selectors.attrMap = {};
jQuery.find = Sizzle;
jQuery.expr = Sizzle.selectors;
jQuery.expr[":"] = jQuery.expr.filters;
jQuery.unique = Sizzle.uniqueSort;
jQuery.text = Sizzle.getText;
jQuery.isXMLDoc = Sizzle.isXML;
jQuery.contains = Sizzle.contains;


})();


var runtil = /Until$/,
	rparentsprev = /^(?:parents|prevUntil|prevAll)/,
	// Note: This RegExp should be improved, or likely pulled from Sizzle
	rmultiselector = /,/,
	isSimple = /^.[^:#\[\.,]*$/,
	slice = Array.prototype.slice,
	POS = jQuery.expr.match.POS,
	// methods guaranteed to produce a unique set when starting from a unique set
	guaranteedUnique = {
		children: true,
		contents: true,
		next: true,
		prev: true
	};

jQuery.fn.extend({
	find: function( selector ) {
		var self = this,
			i, l;

		if ( typeof selector !== "string" ) {
			return jQuery( selector ).filter(function() {
				for ( i = 0, l = self.length; i < l; i++ ) {
					if ( jQuery.contains( self[ i ], this ) ) {
						return true;
					}
				}
			});
		}

		var ret = this.pushStack( "", "find", selector ),
			length, n, r;

		for ( i = 0, l = this.length; i < l; i++ ) {
			length = ret.length;
			jQuery.find( selector, this[i], ret );

			if ( i > 0 ) {
				// Make sure that the results are unique
				for ( n = length; n < ret.length; n++ ) {
					for ( r = 0; r < length; r++ ) {
						if ( ret[r] === ret[n] ) {
							ret.splice(n--, 1);
							break;
						}
					}
				}
			}
		}

		return ret;
	},

	has: function( target ) {
		var targets = jQuery( target );
		return this.filter(function() {
			for ( var i = 0, l = targets.length; i < l; i++ ) {
				if ( jQuery.contains( this, targets[i] ) ) {
					return true;
				}
			}
		});
	},

	not: function( selector ) {
		return this.pushStack( winnow(this, selector, false), "not", selector);
	},

	filter: function( selector ) {
		return this.pushStack( winnow(this, selector, true), "filter", selector );
	},

	is: function( selector ) {
		return !!selector && ( 
			typeof selector === "string" ?
				// If this is a positional selector, check membership in the returned set
				// so $("p:first").is("p:last") won't return true for a doc with two "p".
				POS.test( selector ) ? 
					jQuery( selector, this.context ).index( this[0] ) >= 0 :
					jQuery.filter( selector, this ).length > 0 :
				this.filter( selector ).length > 0 );
	},

	closest: function( selectors, context ) {
		var ret = [], i, l, cur = this[0];
		
		// Array (deprecated as of jQuery 1.7)
		if ( jQuery.isArray( selectors ) ) {
			var level = 1;

			while ( cur && cur.ownerDocument && cur !== context ) {
				for ( i = 0; i < selectors.length; i++ ) {

					if ( jQuery( cur ).is( selectors[ i ] ) ) {
						ret.push({ selector: selectors[ i ], elem: cur, level: level });
					}
				}

				cur = cur.parentNode;
				level++;
			}

			return ret;
		}

		// String
		var pos = POS.test( selectors ) || typeof selectors !== "string" ?
				jQuery( selectors, context || this.context ) :
				0;

		for ( i = 0, l = this.length; i < l; i++ ) {
			cur = this[i];

			while ( cur ) {
				if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
					ret.push( cur );
					break;

				} else {
					cur = cur.parentNode;
					if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {
						break;
					}
				}
			}
		}

		ret = ret.length > 1 ? jQuery.unique( ret ) : ret;

		return this.pushStack( ret, "closest", selectors );
	},

	// Determine the position of an element within
	// the matched set of elements
	index: function( elem ) {

		// No argument, return index in parent
		if ( !elem ) {
			return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;
		}

		// index in selector
		if ( typeof elem === "string" ) {
			return jQuery.inArray( this[0], jQuery( elem ) );
		}

		// Locate the position of the desired element
		return jQuery.inArray(
			// If it receives a jQuery object, the first element is used
			elem.jquery ? elem[0] : elem, this );
	},

	add: function( selector, context ) {
		var set = typeof selector === "string" ?
				jQuery( selector, context ) :
				jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
			all = jQuery.merge( this.get(), set );

		return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
			all :
			jQuery.unique( all ) );
	},

	andSelf: function() {
		return this.add( this.prevObject );
	}
});

// A painfully simple check to see if an element is disconnected
// from a document (should be improved, where feasible).
function isDisconnected( node ) {
	return !node || !node.parentNode || node.parentNode.nodeType === 11;
}

jQuery.each({
	parent: function( elem ) {
		var parent = elem.parentNode;
		return parent && parent.nodeType !== 11 ? parent : null;
	},
	parents: function( elem ) {
		return jQuery.dir( elem, "parentNode" );
	},
	parentsUntil: function( elem, i, until ) {
		return jQuery.dir( elem, "parentNode", until );
	},
	next: function( elem ) {
		return jQuery.nth( elem, 2, "nextSibling" );
	},
	prev: function( elem ) {
		return jQuery.nth( elem, 2, "previousSibling" );
	},
	nextAll: function( elem ) {
		return jQuery.dir( elem, "nextSibling" );
	},
	prevAll: function( elem ) {
		return jQuery.dir( elem, "previousSibling" );
	},
	nextUntil: function( elem, i, until ) {
		return jQuery.dir( elem, "nextSibling", until );
	},
	prevUntil: function( elem, i, until ) {
		return jQuery.dir( elem, "previousSibling", until );
	},
	siblings: function( elem ) {
		return jQuery.sibling( elem.parentNode.firstChild, elem );
	},
	children: function( elem ) {
		return jQuery.sibling( elem.firstChild );
	},
	contents: function( elem ) {
		return jQuery.nodeName( elem, "iframe" ) ?
			elem.contentDocument || elem.contentWindow.document :
			jQuery.makeArray( elem.childNodes );
	}
}, function( name, fn ) {
	jQuery.fn[ name ] = function( until, selector ) {
		var ret = jQuery.map( this, fn, until );

		if ( !runtil.test( name ) ) {
			selector = until;
		}

		if ( selector && typeof selector === "string" ) {
			ret = jQuery.filter( selector, ret );
		}

		ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;

		if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
			ret = ret.reverse();
		}

		return this.pushStack( ret, name, slice.call( arguments ).join(",") );
	};
});

jQuery.extend({
	filter: function( expr, elems, not ) {
		if ( not ) {
			expr = ":not(" + expr + ")";
		}

		return elems.length === 1 ?
			jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
			jQuery.find.matches(expr, elems);
	},

	dir: function( elem, dir, until ) {
		var matched = [],
			cur = elem[ dir ];

		while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
			if ( cur.nodeType === 1 ) {
				matched.push( cur );
			}
			cur = cur[dir];
		}
		return matched;
	},

	nth: function( cur, result, dir, elem ) {
		result = result || 1;
		var num = 0;

		for ( ; cur; cur = cur[dir] ) {
			if ( cur.nodeType === 1 && ++num === result ) {
				break;
			}
		}

		return cur;
	},

	sibling: function( n, elem ) {
		var r = [];

		for ( ; n; n = n.nextSibling ) {
			if ( n.nodeType === 1 && n !== elem ) {
				r.push( n );
			}
		}

		return r;
	}
});

// Implement the identical functionality for filter and not
function winnow( elements, qualifier, keep ) {

	// Can't pass null or undefined to indexOf in Firefox 4
	// Set to 0 to skip string check
	qualifier = qualifier || 0;

	if ( jQuery.isFunction( qualifier ) ) {
		return jQuery.grep(elements, function( elem, i ) {
			var retVal = !!qualifier.call( elem, i, elem );
			return retVal === keep;
		});

	} else if ( qualifier.nodeType ) {
		return jQuery.grep(elements, function( elem, i ) {
			return ( elem === qualifier ) === keep;
		});

	} else if ( typeof qualifier === "string" ) {
		var filtered = jQuery.grep(elements, function( elem ) {
			return elem.nodeType === 1;
		});

		if ( isSimple.test( qualifier ) ) {
			return jQuery.filter(qualifier, filtered, !keep);
		} else {
			qualifier = jQuery.filter( qualifier, filtered );
		}
	}

	return jQuery.grep(elements, function( elem, i ) {
		return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
	});
}




function createSafeFragment( document ) {
	var list = nodeNames.split( "|" ),
	safeFrag = document.createDocumentFragment();

	if ( safeFrag.createElement ) {
		while ( list.length ) {
			safeFrag.createElement(
				list.pop()
			);
		}
	}
	return safeFrag;
}

var nodeNames = "abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|" +
		"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
	rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
	rleadingWhitespace = /^\s+/,
	rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
	rtagName = /<([\w:]+)/,
	rtbody = /<tbody/i,
	rhtml = /<|&#?\w+;/,
	rnoInnerhtml = /<(?:script|style)/i,
	rnocache = /<(?:script|object|embed|option|style)/i,
	rnoshimcache = new RegExp("<(?:" + nodeNames + ")", "i"),
	// checked="checked" or checked
	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
	rscriptType = /\/(java|ecma)script/i,
	rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)/,
	wrapMap = {
		option: [ 1, "<select multiple='multiple'>", "</select>" ],
		legend: [ 1, "<fieldset>", "</fieldset>" ],
		thead: [ 1, "<table>", "</table>" ],
		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
		col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
		area: [ 1, "<map>", "</map>" ],
		_default: [ 0, "", "" ]
	},
	safeFragment = createSafeFragment( document );

wrapMap.optgroup = wrapMap.option;
wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
wrapMap.th = wrapMap.td;

// IE can't serialize <link> and <script> tags normally
if ( !jQuery.support.htmlSerialize ) {
	wrapMap._default = [ 1, "div<div>", "</div>" ];
}

jQuery.fn.extend({
	text: function( text ) {
		if ( jQuery.isFunction(text) ) {
			return this.each(function(i) {
				var self = jQuery( this );

				self.text( text.call(this, i, self.text()) );
			});
		}

		if ( typeof text !== "object" && text !== undefined ) {
			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
		}

		return jQuery.text( this );
	},

	wrapAll: function( html ) {
		if ( jQuery.isFunction( html ) ) {
			return this.each(function(i) {
				jQuery(this).wrapAll( html.call(this, i) );
			});
		}

		if ( this[0] ) {
			// The elements to wrap the target around
			var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);

			if ( this[0].parentNode ) {
				wrap.insertBefore( this[0] );
			}

			wrap.map(function() {
				var elem = this;

				while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
					elem = elem.firstChild;
				}

				return elem;
			}).append( this );
		}

		return this;
	},

	wrapInner: function( html ) {
		if ( jQuery.isFunction( html ) ) {
			return this.each(function(i) {
				jQuery(this).wrapInner( html.call(this, i) );
			});
		}

		return this.each(function() {
			var self = jQuery( this ),
				contents = self.contents();

			if ( contents.length ) {
				contents.wrapAll( html );

			} else {
				self.append( html );
			}
		});
	},

	wrap: function( html ) {
		var isFunction = jQuery.isFunction( html );

		return this.each(function(i) {
			jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
		});
	},

	unwrap: function() {
		return this.parent().each(function() {
			if ( !jQuery.nodeName( this, "body" ) ) {
				jQuery( this ).replaceWith( this.childNodes );
			}
		}).end();
	},

	append: function() {
		return this.domManip(arguments, true, function( elem ) {
			if ( this.nodeType === 1 ) {
				this.appendChild( elem );
			}
		});
	},

	prepend: function() {
		return this.domManip(arguments, true, function( elem ) {
			if ( this.nodeType === 1 ) {
				this.insertBefore( elem, this.firstChild );
			}
		});
	},

	before: function() {
		if ( this[0] && this[0].parentNode ) {
			return this.domManip(arguments, false, function( elem ) {
				this.parentNode.insertBefore( elem, this );
			});
		} else if ( arguments.length ) {
			var set = jQuery.clean( arguments );
			set.push.apply( set, this.toArray() );
			return this.pushStack( set, "before", arguments );
		}
	},

	after: function() {
		if ( this[0] && this[0].parentNode ) {
			return this.domManip(arguments, false, function( elem ) {
				this.parentNode.insertBefore( elem, this.nextSibling );
			});
		} else if ( arguments.length ) {
			var set = this.pushStack( this, "after", arguments );
			set.push.apply( set, jQuery.clean(arguments) );
			return set;
		}
	},

	// keepData is for internal use only--do not document
	remove: function( selector, keepData ) {
		for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
			if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
				if ( !keepData && elem.nodeType === 1 ) {
					jQuery.cleanData( elem.getElementsByTagName("*") );
					jQuery.cleanData( [ elem ] );
				}

				if ( elem.parentNode ) {
					elem.parentNode.removeChild( elem );
				}
			}
		}

		return this;
	},

	empty: function() {
		for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
			// Remove element nodes and prevent memory leaks
			if ( elem.nodeType === 1 ) {
				jQuery.cleanData( elem.getElementsByTagName("*") );
			}

			// Remove any remaining nodes
			while ( elem.firstChild ) {
				elem.removeChild( elem.firstChild );
			}
		}

		return this;
	},

	clone: function( dataAndEvents, deepDataAndEvents ) {
		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;

		return this.map( function () {
			return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
		});
	},

	html: function( value ) {
		if ( value === undefined ) {
			return this[0] && this[0].nodeType === 1 ?
				this[0].innerHTML.replace(rinlinejQuery, "") :
				null;

		// See if we can take a shortcut and just use innerHTML
		} else if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
			(jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
			!wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {

			value = value.replace(rxhtmlTag, "<$1></$2>");

			try {
				for ( var i = 0, l = this.length; i < l; i++ ) {
					// Remove element nodes and prevent memory leaks
					if ( this[i].nodeType === 1 ) {
						jQuery.cleanData( this[i].getElementsByTagName("*") );
						this[i].innerHTML = value;
					}
				}

			// If using innerHTML throws an exception, use the fallback method
			} catch(e) {
				this.empty().append( value );
			}

		} else if ( jQuery.isFunction( value ) ) {
			this.each(function(i){
				var self = jQuery( this );

				self.html( value.call(this, i, self.html()) );
			});

		} else {
			this.empty().append( value );
		}

		return this;
	},

	replaceWith: function( value ) {
		if ( this[0] && this[0].parentNode ) {
			// Make sure that the elements are removed from the DOM before they are inserted
			// this can help fix replacing a parent with child elements
			if ( jQuery.isFunction( value ) ) {
				return this.each(function(i) {
					var self = jQuery(this), old = self.html();
					self.replaceWith( value.call( this, i, old ) );
				});
			}

			if ( typeof value !== "string" ) {
				value = jQuery( value ).detach();
			}

			return this.each(function() {
				var next = this.nextSibling,
					parent = this.parentNode;

				jQuery( this ).remove();

				if ( next ) {
					jQuery(next).before( value );
				} else {
					jQuery(parent).append( value );
				}
			});
		} else {
			return this.length ?
				this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) :
				this;
		}
	},

	detach: function( selector ) {
		return this.remove( selector, true );
	},

	domManip: function( args, table, callback ) {
		var results, first, fragment, parent,
			value = args[0],
			scripts = [];

		// We can't cloneNode fragments that contain checked, in WebKit
		if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
			return this.each(function() {
				jQuery(this).domManip( args, table, callback, true );
			});
		}

		if ( jQuery.isFunction(value) ) {
			return this.each(function(i) {
				var self = jQuery(this);
				args[0] = value.call(this, i, table ? self.html() : undefined);
				self.domManip( args, table, callback );
			});
		}

		if ( this[0] ) {
			parent = value && value.parentNode;

			// If we're in a fragment, just use that instead of building a new one
			if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
				results = { fragment: parent };

			} else {
				results = jQuery.buildFragment( args, this, scripts );
			}

			fragment = results.fragment;

			if ( fragment.childNodes.length === 1 ) {
				first = fragment = fragment.firstChild;
			} else {
				first = fragment.firstChild;
			}

			if ( first ) {
				table = table && jQuery.nodeName( first, "tr" );

				for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {
					callback.call(
						table ?
							root(this[i], first) :
							this[i],
						// Make sure that we do not leak memory by inadvertently discarding
						// the original fragment (which might have attached data) instead of
						// using it; in addition, use the original fragment object for the last
						// item instead of first because it can end up being emptied incorrectly
						// in certain situations (Bug #8070).
						// Fragments from the fragment cache must always be cloned and never used
						// in place.
						results.cacheable || ( l > 1 && i < lastIndex ) ?
							jQuery.clone( fragment, true, true ) :
							fragment
					);
				}
			}

			if ( scripts.length ) {
				jQuery.each( scripts, evalScript );
			}
		}

		return this;
	}
});

function root( elem, cur ) {
	return jQuery.nodeName(elem, "table") ?
		(elem.getElementsByTagName("tbody")[0] ||
		elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
		elem;
}

function cloneCopyEvent( src, dest ) {

	if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
		return;
	}

	var type, i, l,
		oldData = jQuery._data( src ),
		curData = jQuery._data( dest, oldData ),
		events = oldData.events;

	if ( events ) {
		delete curData.handle;
		curData.events = {};

		for ( type in events ) {
			for ( i = 0, l = events[ type ].length; i < l; i++ ) {
				jQuery.event.add( dest, type + ( events[ type ][ i ].namespace ? "." : "" ) + events[ type ][ i ].namespace, events[ type ][ i ], events[ type ][ i ].data );
			}
		}
	}

	// make the cloned public data object a copy from the original
	if ( curData.data ) {
		curData.data = jQuery.extend( {}, curData.data );
	}
}

function cloneFixAttributes( src, dest ) {
	var nodeName;

	// We do not need to do anything for non-Elements
	if ( dest.nodeType !== 1 ) {
		return;
	}

	// clearAttributes removes the attributes, which we don't want,
	// but also removes the attachEvent events, which we *do* want
	if ( dest.clearAttributes ) {
		dest.clearAttributes();
	}

	// mergeAttributes, in contrast, only merges back on the
	// original attributes, not the events
	if ( dest.mergeAttributes ) {
		dest.mergeAttributes( src );
	}

	nodeName = dest.nodeName.toLowerCase();

	// IE6-8 fail to clone children inside object elements that use
	// the proprietary classid attribute value (rather than the type
	// attribute) to identify the type of content to display
	if ( nodeName === "object" ) {
		dest.outerHTML = src.outerHTML;

	} else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) {
		// IE6-8 fails to persist the checked state of a cloned checkbox
		// or radio button. Worse, IE6-7 fail to give the cloned element
		// a checked appearance if the defaultChecked value isn't also set
		if ( src.checked ) {
			dest.defaultChecked = dest.checked = src.checked;
		}

		// IE6-7 get confused and end up setting the value of a cloned
		// checkbox/radio button to an empty string instead of "on"
		if ( dest.value !== src.value ) {
			dest.value = src.value;
		}

	// IE6-8 fails to return the selected option to the default selected
	// state when cloning options
	} else if ( nodeName === "option" ) {
		dest.selected = src.defaultSelected;

	// IE6-8 fails to set the defaultValue to the correct value when
	// cloning other types of input fields
	} else if ( nodeName === "input" || nodeName === "textarea" ) {
		dest.defaultValue = src.defaultValue;
	}

	// Event data gets referenced instead of copied if the expando
	// gets copied too
	dest.removeAttribute( jQuery.expando );
}

jQuery.buildFragment = function( args, nodes, scripts ) {
	var fragment, cacheable, cacheresults, doc,
	first = args[ 0 ];

	// nodes may contain either an explicit document object,
	// a jQuery collection or context object.
	// If nodes[0] contains a valid object to assign to doc
	if ( nodes && nodes[0] ) {
		doc = nodes[0].ownerDocument || nodes[0];
	}

	// Ensure that an attr object doesn't incorrectly stand in as a document object
	// Chrome and Firefox seem to allow this to occur and will throw exception
	// Fixes #8950
	if ( !doc.createDocumentFragment ) {
		doc = document;
	}

	// Only cache "small" (1/2 KB) HTML strings that are associated with the main document
	// Cloning options loses the selected state, so don't cache them
	// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
	// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
	// Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501
	if ( args.length === 1 && typeof first === "string" && first.length < 512 && doc === document &&
		first.charAt(0) === "<" && !rnocache.test( first ) &&
		(jQuery.support.checkClone || !rchecked.test( first )) &&
		(jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {

		cacheable = true;

		cacheresults = jQuery.fragments[ first ];
		if ( cacheresults && cacheresults !== 1 ) {
			fragment = cacheresults;
		}
	}

	if ( !fragment ) {
		fragment = doc.createDocumentFragment();
		jQuery.clean( args, doc, fragment, scripts );
	}

	if ( cacheable ) {
		jQuery.fragments[ first ] = cacheresults ? fragment : 1;
	}

	return { fragment: fragment, cacheable: cacheable };
};

jQuery.fragments = {};

jQuery.each({
	appendTo: "append",
	prependTo: "prepend",
	insertBefore: "before",
	insertAfter: "after",
	replaceAll: "replaceWith"
}, function( name, original ) {
	jQuery.fn[ name ] = function( selector ) {
		var ret = [],
			insert = jQuery( selector ),
			parent = this.length === 1 && this[0].parentNode;

		if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
			insert[ original ]( this[0] );
			return this;

		} else {
			for ( var i = 0, l = insert.length; i < l; i++ ) {
				var elems = ( i > 0 ? this.clone(true) : this ).get();
				jQuery( insert[i] )[ original ]( elems );
				ret = ret.concat( elems );
			}

			return this.pushStack( ret, name, insert.selector );
		}
	};
});

function getAll( elem ) {
	if ( typeof elem.getElementsByTagName !== "undefined" ) {
		return elem.getElementsByTagName( "*" );

	} else if ( typeof elem.querySelectorAll !== "undefined" ) {
		return elem.querySelectorAll( "*" );

	} else {
		return [];
	}
}

// Used in clean, fixes the defaultChecked property
function fixDefaultChecked( elem ) {
	if ( elem.type === "checkbox" || elem.type === "radio" ) {
		elem.defaultChecked = elem.checked;
	}
}
// Finds all inputs and passes them to fixDefaultChecked
function findInputs( elem ) {
	var nodeName = ( elem.nodeName || "" ).toLowerCase();
	if ( nodeName === "input" ) {
		fixDefaultChecked( elem );
	// Skip scripts, get other children
	} else if ( nodeName !== "script" && typeof elem.getElementsByTagName !== "undefined" ) {
		jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
	}
}

// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js
function shimCloneNode( elem ) {
	var div = document.createElement( "div" );
	safeFragment.appendChild( div );

	div.innerHTML = elem.outerHTML;
	return div.firstChild;
}

jQuery.extend({
	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
		var srcElements,
			destElements,
			i,
			// IE<=8 does not properly clone detached, unknown element nodes
			clone = jQuery.support.html5Clone || !rnoshimcache.test( "<" + elem.nodeName ) ?
				elem.cloneNode( true ) :
				shimCloneNode( elem );

		if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
				(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
			// IE copies events bound via attachEvent when using cloneNode.
			// Calling detachEvent on the clone will also remove the events
			// from the original. In order to get around this, we use some
			// proprietary methods to clear the events. Thanks to MooTools
			// guys for this hotness.

			cloneFixAttributes( elem, clone );

			// Using Sizzle here is crazy slow, so we use getElementsByTagName instead
			srcElements = getAll( elem );
			destElements = getAll( clone );

			// Weird iteration because IE will replace the length property
			// with an element if you are cloning the body and one of the
			// elements on the page has a name or id of "length"
			for ( i = 0; srcElements[i]; ++i ) {
				// Ensure that the destination node is not null; Fixes #9587
				if ( destElements[i] ) {
					cloneFixAttributes( srcElements[i], destElements[i] );
				}
			}
		}

		// Copy the events from the original to the clone
		if ( dataAndEvents ) {
			cloneCopyEvent( elem, clone );

			if ( deepDataAndEvents ) {
				srcElements = getAll( elem );
				destElements = getAll( clone );

				for ( i = 0; srcElements[i]; ++i ) {
					cloneCopyEvent( srcElements[i], destElements[i] );
				}
			}
		}

		srcElements = destElements = null;

		// Return the cloned set
		return clone;
	},

	clean: function( elems, context, fragment, scripts ) {
		var checkScriptType;

		context = context || document;

		// !context.createElement fails in IE with an error but returns typeof 'object'
		if ( typeof context.createElement === "undefined" ) {
			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
		}

		var ret = [], j;

		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
			if ( typeof elem === "number" ) {
				elem += "";
			}

			if ( !elem ) {
				continue;
			}

			// Convert html string into DOM nodes
			if ( typeof elem === "string" ) {
				if ( !rhtml.test( elem ) ) {
					elem = context.createTextNode( elem );
				} else {
					// Fix "XHTML"-style tags in all browsers
					elem = elem.replace(rxhtmlTag, "<$1></$2>");

					// Trim whitespace, otherwise indexOf won't work as expected
					var tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(),
						wrap = wrapMap[ tag ] || wrapMap._default,
						depth = wrap[0],
						div = context.createElement("div");

					// Append wrapper element to unknown element safe doc fragment
					if ( context === document ) {
						// Use the fragment we've already created for this document
						safeFragment.appendChild( div );
					} else {
						// Use a fragment created with the owner document
						createSafeFragment( context ).appendChild( div );
					}

					// Go to html and back, then peel off extra wrappers
					div.innerHTML = wrap[1] + elem + wrap[2];

					// Move to the right depth
					while ( depth-- ) {
						div = div.lastChild;
					}

					// Remove IE's autoinserted <tbody> from table fragments
					if ( !jQuery.support.tbody ) {

						// String was a <table>, *may* have spurious <tbody>
						var hasBody = rtbody.test(elem),
							tbody = tag === "table" && !hasBody ?
								div.firstChild && div.firstChild.childNodes :

								// String was a bare <thead> or <tfoot>
								wrap[1] === "<table>" && !hasBody ?
									div.childNodes :
									[];

						for ( j = tbody.length - 1; j >= 0 ; --j ) {
							if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
								tbody[ j ].parentNode.removeChild( tbody[ j ] );
							}
						}
					}

					// IE completely kills leading whitespace when innerHTML is used
					if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
						div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
					}

					elem = div.childNodes;
				}
			}

			// Resets defaultChecked for any radios and checkboxes
			// about to be appended to the DOM in IE 6/7 (#8060)
			var len;
			if ( !jQuery.support.appendChecked ) {
				if ( elem[0] && typeof (len = elem.length) === "number" ) {
					for ( j = 0; j < len; j++ ) {
						findInputs( elem[j] );
					}
				} else {
					findInputs( elem );
				}
			}

			if ( elem.nodeType ) {
				ret.push( elem );
			} else {
				ret = jQuery.merge( ret, elem );
			}
		}

		if ( fragment ) {
			checkScriptType = function( elem ) {
				return !elem.type || rscriptType.test( elem.type );
			};
			for ( i = 0; ret[i]; i++ ) {
				if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
					scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );

				} else {
					if ( ret[i].nodeType === 1 ) {
						var jsTags = jQuery.grep( ret[i].getElementsByTagName( "script" ), checkScriptType );

						ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
					}
					fragment.appendChild( ret[i] );
				}
			}
		}

		return ret;
	},

	cleanData: function( elems ) {
		var data, id,
			cache = jQuery.cache,
			special = jQuery.event.special,
			deleteExpando = jQuery.support.deleteExpando;

		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
			if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
				continue;
			}

			id = elem[ jQuery.expando ];

			if ( id ) {
				data = cache[ id ];

				if ( data && data.events ) {
					for ( var type in data.events ) {
						if ( special[ type ] ) {
							jQuery.event.remove( elem, type );

						// This is a shortcut to avoid jQuery.event.remove's overhead
						} else {
							jQuery.removeEvent( elem, type, data.handle );
						}
					}

					// Null the DOM reference to avoid IE6/7/8 leak (#7054)
					if ( data.handle ) {
						data.handle.elem = null;
					}
				}

				if ( deleteExpando ) {
					delete elem[ jQuery.expando ];

				} else if ( elem.removeAttribute ) {
					elem.removeAttribute( jQuery.expando );
				}

				delete cache[ id ];
			}
		}
	}
});

function evalScript( i, elem ) {
	if ( elem.src ) {
		jQuery.ajax({
			url: elem.src,
			async: false,
			dataType: "script"
		});
	} else {
		jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "/*$0*/" ) );
	}

	if ( elem.parentNode ) {
		elem.parentNode.removeChild( elem );
	}
}




var ralpha = /alpha\([^)]*\)/i,
	ropacity = /opacity=([^)]*)/,
	// fixed for IE9, see #8346
	rupper = /([A-Z]|^ms)/g,
	rnumpx = /^-?\d+(?:px)?$/i,
	rnum = /^-?\d/,
	rrelNum = /^([\-+])=([\-+.\de]+)/,

	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
	cssWidth = [ "Left", "Right" ],
	cssHeight = [ "Top", "Bottom" ],
	curCSS,

	getComputedStyle,
	currentStyle;

jQuery.fn.css = function( name, value ) {
	// Setting 'undefined' is a no-op
	if ( arguments.length === 2 && value === undefined ) {
		return this;
	}

	return jQuery.access( this, name, value, true, function( elem, name, value ) {
		return value !== undefined ?
			jQuery.style( elem, name, value ) :
			jQuery.css( elem, name );
	});
};

jQuery.extend({
	// Add in style property hooks for overriding the default
	// behavior of getting and setting a style property
	cssHooks: {
		opacity: {
			get: function( elem, computed ) {
				if ( computed ) {
					// We should always get a number back from opacity
					var ret = curCSS( elem, "opacity", "opacity" );
					return ret === "" ? "1" : ret;

				} else {
					return elem.style.opacity;
				}
			}
		}
	},

	// Exclude the following css properties to add px
	cssNumber: {
		"fillOpacity": true,
		"fontWeight": true,
		"lineHeight": true,
		"opacity": true,
		"orphans": true,
		"widows": true,
		"zIndex": true,
		"zoom": true
	},

	// Add in properties whose names you wish to fix before
	// setting or getting the value
	cssProps: {
		// normalize float css property
		"float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
	},

	// Get and set the style property on a DOM Node
	style: function( elem, name, value, extra ) {
		// Don't set styles on text and comment nodes
		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
			return;
		}

		// Make sure that we're working with the right name
		var ret, type, origName = jQuery.camelCase( name ),
			style = elem.style, hooks = jQuery.cssHooks[ origName ];

		name = jQuery.cssProps[ origName ] || origName;

		// Check if we're setting a value
		if ( value !== undefined ) {
			type = typeof value;

			// convert relative number strings (+= or -=) to relative numbers. #7345
			if ( type === "string" && (ret = rrelNum.exec( value )) ) {
				value = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );
				// Fixes bug #9237
				type = "number";
			}

			// Make sure that NaN and null values aren't set. See: #7116
			if ( value == null || type === "number" && isNaN( value ) ) {
				return;
			}

			// If a number was passed in, add 'px' to the (except for certain CSS properties)
			if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
				value += "px";
			}

			// If a hook was provided, use that value, otherwise just set the specified value
			if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
				// Wrapped to prevent IE from throwing errors when 'invalid' values are provided
				// Fixes bug #5509
				try {
					style[ name ] = value;
				} catch(e) {}
			}

		} else {
			// If a hook was provided get the non-computed value from there
			if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
				return ret;
			}

			// Otherwise just get the value from the style object
			return style[ name ];
		}
	},

	css: function( elem, name, extra ) {
		var ret, hooks;

		// Make sure that we're working with the right name
		name = jQuery.camelCase( name );
		hooks = jQuery.cssHooks[ name ];
		name = jQuery.cssProps[ name ] || name;

		// cssFloat needs a special treatment
		if ( name === "cssFloat" ) {
			name = "float";
		}

		// If a hook was provided get the computed value from there
		if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {
			return ret;

		// Otherwise, if a way to get the computed value exists, use that
		} else if ( curCSS ) {
			return curCSS( elem, name );
		}
	},

	// A method for quickly swapping in/out CSS properties to get correct calculations
	swap: function( elem, options, callback ) {
		var old = {};

		// Remember the old values, and insert the new ones
		for ( var name in options ) {
			old[ name ] = elem.style[ name ];
			elem.style[ name ] = options[ name ];
		}

		callback.call( elem );

		// Revert the old values
		for ( name in options ) {
			elem.style[ name ] = old[ name ];
		}
	}
});

// DEPRECATED, Use jQuery.css() instead
jQuery.curCSS = jQuery.css;

jQuery.each(["height", "width"], function( i, name ) {
	jQuery.cssHooks[ name ] = {
		get: function( elem, computed, extra ) {
			var val;

			if ( computed ) {
				if ( elem.offsetWidth !== 0 ) {
					return getWH( elem, name, extra );
				} else {
					jQuery.swap( elem, cssShow, function() {
						val = getWH( elem, name, extra );
					});
				}

				return val;
			}
		},

		set: function( elem, value ) {
			if ( rnumpx.test( value ) ) {
				// ignore negative width and height values #1599
				value = parseFloat( value );

				if ( value >= 0 ) {
					return value + "px";
				}

			} else {
				return value;
			}
		}
	};
});

if ( !jQuery.support.opacity ) {
	jQuery.cssHooks.opacity = {
		get: function( elem, computed ) {
			// IE uses filters for opacity
			return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
				( parseFloat( RegExp.$1 ) / 100 ) + "" :
				computed ? "1" : "";
		},

		set: function( elem, value ) {
			var style = elem.style,
				currentStyle = elem.currentStyle,
				opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
				filter = currentStyle && currentStyle.filter || style.filter || "";

			// IE has trouble with opacity if it does not have layout
			// Force it by setting the zoom level
			style.zoom = 1;

			// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
			if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" ) {

				// Setting style.filter to null, "" & " " still leave "filter:" in the cssText
				// if "filter:" is present at all, clearType is disabled, we want to avoid this
				// style.removeAttribute is IE Only, but so apparently is this code path...
				style.removeAttribute( "filter" );

				// if there there is no filter style applied in a css rule, we are done
				if ( currentStyle && !currentStyle.filter ) {
					return;
				}
			}

			// otherwise, set new filter values
			style.filter = ralpha.test( filter ) ?
				filter.replace( ralpha, opacity ) :
				filter + " " + opacity;
		}
	};
}

jQuery(function() {
	// This hook cannot be added until DOM ready because the support test
	// for it is not run until after DOM ready
	if ( !jQuery.support.reliableMarginRight ) {
		jQuery.cssHooks.marginRight = {
			get: function( elem, computed ) {
				// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
				// Work around by temporarily setting element display to inline-block
				var ret;
				jQuery.swap( elem, { "display": "inline-block" }, function() {
					if ( computed ) {
						ret = curCSS( elem, "margin-right", "marginRight" );
					} else {
						ret = elem.style.marginRight;
					}
				});
				return ret;
			}
		};
	}
});

if ( document.defaultView && document.defaultView.getComputedStyle ) {
	getComputedStyle = function( elem, name ) {
		var ret, defaultView, computedStyle;

		name = name.replace( rupper, "-$1" ).toLowerCase();

		if ( (defaultView = elem.ownerDocument.defaultView) &&
				(computedStyle = defaultView.getComputedStyle( elem, null )) ) {
			ret = computedStyle.getPropertyValue( name );
			if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
				ret = jQuery.style( elem, name );
			}
		}

		return ret;
	};
}

if ( document.documentElement.currentStyle ) {
	currentStyle = function( elem, name ) {
		var left, rsLeft, uncomputed,
			ret = elem.currentStyle && elem.currentStyle[ name ],
			style = elem.style;

		// Avoid setting ret to empty string here
		// so we don't default to auto
		if ( ret === null && style && (uncomputed = style[ name ]) ) {
			ret = uncomputed;
		}

		// From the awesome hack by Dean Edwards
		// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291

		// If we're not dealing with a regular pixel number
		// but a number that has a weird ending, we need to convert it to pixels
		if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {

			// Remember the original values
			left = style.left;
			rsLeft = elem.runtimeStyle && elem.runtimeStyle.left;

			// Put in the new values to get a computed value out
			if ( rsLeft ) {
				elem.runtimeStyle.left = elem.currentStyle.left;
			}
			style.left = name === "fontSize" ? "1em" : ( ret || 0 );
			ret = style.pixelLeft + "px";

			// Revert the changed values
			style.left = left;
			if ( rsLeft ) {
				elem.runtimeStyle.left = rsLeft;
			}
		}

		return ret === "" ? "auto" : ret;
	};
}

curCSS = getComputedStyle || currentStyle;

function getWH( elem, name, extra ) {

	// Start with offset property
	var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
		which = name === "width" ? cssWidth : cssHeight,
		i = 0,
		len = which.length;

	if ( val > 0 ) {
		if ( extra !== "border" ) {
			for ( ; i < len; i++ ) {
				if ( !extra ) {
					val -= parseFloat( jQuery.css( elem, "padding" + which[ i ] ) ) || 0;
				}
				if ( extra === "margin" ) {
					val += parseFloat( jQuery.css( elem, extra + which[ i ] ) ) || 0;
				} else {
					val -= parseFloat( jQuery.css( elem, "border" + which[ i ] + "Width" ) ) || 0;
				}
			}
		}

		return val + "px";
	}

	// Fall back to computed then uncomputed css if necessary
	val = curCSS( elem, name, name );
	if ( val < 0 || val == null ) {
		val = elem.style[ name ] || 0;
	}
	// Normalize "", auto, and prepare for extra
	val = parseFloat( val ) || 0;

	// Add padding, border, margin
	if ( extra ) {
		for ( ; i < len; i++ ) {
			val += parseFloat( jQuery.css( elem, "padding" + which[ i ] ) ) || 0;
			if ( extra !== "padding" ) {
				val += parseFloat( jQuery.css( elem, "border" + which[ i ] + "Width" ) ) || 0;
			}
			if ( extra === "margin" ) {
				val += parseFloat( jQuery.css( elem, extra + which[ i ] ) ) || 0;
			}
		}
	}

	return val + "px";
}

if ( jQuery.expr && jQuery.expr.filters ) {
	jQuery.expr.filters.hidden = function( elem ) {
		var width = elem.offsetWidth,
			height = elem.offsetHeight;

		return ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
	};

	jQuery.expr.filters.visible = function( elem ) {
		return !jQuery.expr.filters.hidden( elem );
	};
}




var r20 = /%20/g,
	rbracket = /\[\]$/,
	rCRLF = /\r?\n/g,
	rhash = /#.*$/,
	rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
	rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
	// #7653, #8125, #8152: local protocol detection
	rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,
	rnoContent = /^(?:GET|HEAD)$/,
	rprotocol = /^\/\//,
	rquery = /\?/,
	rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
	rselectTextarea = /^(?:select|textarea)/i,
	rspacesAjax = /\s+/,
	rts = /([?&])_=[^&]*/,
	rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,

	// Keep a copy of the old load method
	_load = jQuery.fn.load,

	/* Prefilters
	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
	 * 2) These are called:
	 *    - BEFORE asking for a transport
	 *    - AFTER param serialization (s.data is a string if s.processData is true)
	 * 3) key is the dataType
	 * 4) the catchall symbol "*" can be used
	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
	 */
	prefilters = {},

	/* Transports bindings
	 * 1) key is the dataType
	 * 2) the catchall symbol "*" can be used
	 * 3) selection will start with transport dataType and THEN go to "*" if needed
	 */
	transports = {},

	// Document location
	ajaxLocation,

	// Document location segments
	ajaxLocParts,

	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
	allTypes = ["*/"] + ["*"];

// #8138, IE may throw an exception when accessing
// a field from window.location if document.domain has been set
try {
	ajaxLocation = location.href;
} catch( e ) {
	// Use the href attribute of an A element
	// since IE will modify it given document.location
	ajaxLocation = document.createElement( "a" );
	ajaxLocation.href = "";
	ajaxLocation = ajaxLocation.href;
}

// Segment location into parts
ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];

// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
function addToPrefiltersOrTransports( structure ) {

	// dataTypeExpression is optional and defaults to "*"
	return function( dataTypeExpression, func ) {

		if ( typeof dataTypeExpression !== "string" ) {
			func = dataTypeExpression;
			dataTypeExpression = "*";
		}

		if ( jQuery.isFunction( func ) ) {
			var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),
				i = 0,
				length = dataTypes.length,
				dataType,
				list,
				placeBefore;

			// For each dataType in the dataTypeExpression
			for ( ; i < length; i++ ) {
				dataType = dataTypes[ i ];
				// We control if we're asked to add before
				// any existing element
				placeBefore = /^\+/.test( dataType );
				if ( placeBefore ) {
					dataType = dataType.substr( 1 ) || "*";
				}
				list = structure[ dataType ] = structure[ dataType ] || [];
				// then we add to the structure accordingly
				list[ placeBefore ? "unshift" : "push" ]( func );
			}
		}
	};
}

// Base inspection function for prefilters and transports
function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,
		dataType /* internal */, inspected /* internal */ ) {

	dataType = dataType || options.dataTypes[ 0 ];
	inspected = inspected || {};

	inspected[ dataType ] = true;

	var list = structure[ dataType ],
		i = 0,
		length = list ? list.length : 0,
		executeOnly = ( structure === prefilters ),
		selection;

	for ( ; i < length && ( executeOnly || !selection ); i++ ) {
		selection = list[ i ]( options, originalOptions, jqXHR );
		// If we got redirected to another dataType
		// we try there if executing only and not done already
		if ( typeof selection === "string" ) {
			if ( !executeOnly || inspected[ selection ] ) {
				selection = undefined;
			} else {
				options.dataTypes.unshift( selection );
				selection = inspectPrefiltersOrTransports(
						structure, options, originalOptions, jqXHR, selection, inspected );
			}
		}
	}
	// If we're only executing or nothing was selected
	// we try the catchall dataType if not done already
	if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) {
		selection = inspectPrefiltersOrTransports(
				structure, options, originalOptions, jqXHR, "*", inspected );
	}
	// unnecessary when only executing (prefilters)
	// but it'll be ignored by the caller in that case
	return selection;
}

// A special extend for ajax options
// that takes "flat" options (not to be deep extended)
// Fixes #9887
function ajaxExtend( target, src ) {
	var key, deep,
		flatOptions = jQuery.ajaxSettings.flatOptions || {};
	for ( key in src ) {
		if ( src[ key ] !== undefined ) {
			( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
		}
	}
	if ( deep ) {
		jQuery.extend( true, target, deep );
	}
}

jQuery.fn.extend({
	load: function( url, params, callback ) {
		if ( typeof url !== "string" && _load ) {
			return _load.apply( this, arguments );

		// Don't do a request if no elements are being requested
		} else if ( !this.length ) {
			return this;
		}

		var off = url.indexOf( " " );
		if ( off >= 0 ) {
			var selector = url.slice( off, url.length );
			url = url.slice( 0, off );
		}

		// Default to a GET request
		var type = "GET";

		// If the second parameter was provided
		if ( params ) {
			// If it's a function
			if ( jQuery.isFunction( params ) ) {
				// We assume that it's the callback
				callback = params;
				params = undefined;

			// Otherwise, build a param string
			} else if ( typeof params === "object" ) {
				params = jQuery.param( params, jQuery.ajaxSettings.traditional );
				type = "POST";
			}
		}

		var self = this;

		// Request the remote document
		jQuery.ajax({
			url: url,
			type: type,
			dataType: "html",
			data: params,
			// Complete callback (responseText is used internally)
			complete: function( jqXHR, status, responseText ) {
				// Store the response as specified by the jqXHR object
				responseText = jqXHR.responseText;
				// If successful, inject the HTML into all the matched elements
				if ( jqXHR.isResolved() ) {
					// #4825: Get the actual response in case
					// a dataFilter is present in ajaxSettings
					jqXHR.done(function( r ) {
						responseText = r;
					});
					// See if a selector was specified
					self.html( selector ?
						// Create a dummy div to hold the results
						jQuery("<div>")
							// inject the contents of the document in, removing the scripts
							// to avoid any 'Permission Denied' errors in IE
							.append(responseText.replace(rscript, ""))

							// Locate the specified elements
							.find(selector) :

						// If not, just inject the full result
						responseText );
				}

				if ( callback ) {
					self.each( callback, [ responseText, status, jqXHR ] );
				}
			}
		});

		return this;
	},

	serialize: function() {
		return jQuery.param( this.serializeArray() );
	},

	serializeArray: function() {
		return this.map(function(){
			return this.elements ? jQuery.makeArray( this.elements ) : this;
		})
		.filter(function(){
			return this.name && !this.disabled &&
				( this.checked || rselectTextarea.test( this.nodeName ) ||
					rinput.test( this.type ) );
		})
		.map(function( i, elem ){
			var val = jQuery( this ).val();

			return val == null ?
				null :
				jQuery.isArray( val ) ?
					jQuery.map( val, function( val, i ){
						return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
					}) :
					{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
		}).get();
	}
});

// Attach a bunch of functions for handling common AJAX events
jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){
	jQuery.fn[ o ] = function( f ){
		return this.on( o, f );
	};
});

jQuery.each( [ "get", "post" ], function( i, method ) {
	jQuery[ method ] = function( url, data, callback, type ) {
		// shift arguments if data argument was omitted
		if ( jQuery.isFunction( data ) ) {
			type = type || callback;
			callback = data;
			data = undefined;
		}

		return jQuery.ajax({
			type: method,
			url: url,
			data: data,
			success: callback,
			dataType: type
		});
	};
});

jQuery.extend({

	getScript: function( url, callback ) {
		return jQuery.get( url, undefined, callback, "script" );
	},

	getJSON: function( url, data, callback ) {
		return jQuery.get( url, data, callback, "json" );
	},

	// Creates a full fledged settings object into target
	// with both ajaxSettings and settings fields.
	// If target is omitted, writes into ajaxSettings.
	ajaxSetup: function( target, settings ) {
		if ( settings ) {
			// Building a settings object
			ajaxExtend( target, jQuery.ajaxSettings );
		} else {
			// Extending ajaxSettings
			settings = target;
			target = jQuery.ajaxSettings;
		}
		ajaxExtend( target, settings );
		return target;
	},

	ajaxSettings: {
		url: ajaxLocation,
		isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
		global: true,
		type: "GET",
		contentType: "application/x-www-form-urlencoded",
		processData: true,
		async: true,
		/*
		timeout: 0,
		data: null,
		dataType: null,
		username: null,
		password: null,
		cache: null,
		traditional: false,
		headers: {},
		*/

		accepts: {
			xml: "application/xml, text/xml",
			html: "text/html",
			text: "text/plain",
			json: "application/json, text/javascript",
			"*": allTypes
		},

		contents: {
			xml: /xml/,
			html: /html/,
			json: /json/
		},

		responseFields: {
			xml: "responseXML",
			text: "responseText"
		},

		// List of data converters
		// 1) key format is "source_type destination_type" (a single space in-between)
		// 2) the catchall symbol "*" can be used for source_type
		converters: {

			// Convert anything to text
			"* text": window.String,

			// Text to html (true = no transformation)
			"text html": true,

			// Evaluate text as a json expression
			"text json": jQuery.parseJSON,

			// Parse text as xml
			"text xml": jQuery.parseXML
		},

		// For options that shouldn't be deep extended:
		// you can add your own custom options here if
		// and when you create one that shouldn't be
		// deep extended (see ajaxExtend)
		flatOptions: {
			context: true,
			url: true
		}
	},

	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
	ajaxTransport: addToPrefiltersOrTransports( transports ),

	// Main method
	ajax: function( url, options ) {

		// If url is an object, simulate pre-1.5 signature
		if ( typeof url === "object" ) {
			options = url;
			url = undefined;
		}

		// Force options to be an object
		options = options || {};

		var // Create the final options object
			s = jQuery.ajaxSetup( {}, options ),
			// Callbacks context
			callbackContext = s.context || s,
			// Context for global events
			// It's the callbackContext if one was provided in the options
			// and if it's a DOM node or a jQuery collection
			globalEventContext = callbackContext !== s &&
				( callbackContext.nodeType || callbackContext instanceof jQuery ) ?
						jQuery( callbackContext ) : jQuery.event,
			// Deferreds
			deferred = jQuery.Deferred(),
			completeDeferred = jQuery.Callbacks( "once memory" ),
			// Status-dependent callbacks
			statusCode = s.statusCode || {},
			// ifModified key
			ifModifiedKey,
			// Headers (they are sent all at once)
			requestHeaders = {},
			requestHeadersNames = {},
			// Response headers
			responseHeadersString,
			responseHeaders,
			// transport
			transport,
			// timeout handle
			timeoutTimer,
			// Cross-domain detection vars
			parts,
			// The jqXHR state
			state = 0,
			// To know if global events are to be dispatched
			fireGlobals,
			// Loop variable
			i,
			// Fake xhr
			jqXHR = {

				readyState: 0,

				// Caches the header
				setRequestHeader: function( name, value ) {
					if ( !state ) {
						var lname = name.toLowerCase();
						name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
						requestHeaders[ name ] = value;
					}
					return this;
				},

				// Raw string
				getAllResponseHeaders: function() {
					return state === 2 ? responseHeadersString : null;
				},

				// Builds headers hashtable if needed
				getResponseHeader: function( key ) {
					var match;
					if ( state === 2 ) {
						if ( !responseHeaders ) {
							responseHeaders = {};
							while( ( match = rheaders.exec( responseHeadersString ) ) ) {
								responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
							}
						}
						match = responseHeaders[ key.toLowerCase() ];
					}
					return match === undefined ? null : match;
				},

				// Overrides response content-type header
				overrideMimeType: function( type ) {
					if ( !state ) {
						s.mimeType = type;
					}
					return this;
				},

				// Cancel the request
				abort: function( statusText ) {
					statusText = statusText || "abort";
					if ( transport ) {
						transport.abort( statusText );
					}
					done( 0, statusText );
					return this;
				}
			};

		// Callback for when everything is done
		// It is defined here because jslint complains if it is declared
		// at the end of the function (which would be more logical and readable)
		function done( status, nativeStatusText, responses, headers ) {

			// Called once
			if ( state === 2 ) {
				return;
			}

			// State is "done" now
			state = 2;

			// Clear timeout if it exists
			if ( timeoutTimer ) {
				clearTimeout( timeoutTimer );
			}

			// Dereference transport for early garbage collection
			// (no matter how long the jqXHR object will be used)
			transport = undefined;

			// Cache response headers
			responseHeadersString = headers || "";

			// Set readyState
			jqXHR.readyState = status > 0 ? 4 : 0;

			var isSuccess,
				success,
				error,
				statusText = nativeStatusText,
				response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,
				lastModified,
				etag;

			// If successful, handle type chaining
			if ( status >= 200 && status < 300 || status === 304 ) {

				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
				if ( s.ifModified ) {

					if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) {
						jQuery.lastModified[ ifModifiedKey ] = lastModified;
					}
					if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) {
						jQuery.etag[ ifModifiedKey ] = etag;
					}
				}

				// If not modified
				if ( status === 304 ) {

					statusText = "notmodified";
					isSuccess = true;

				// If we have data
				} else {

					try {
						success = ajaxConvert( s, response );
						statusText = "success";
						isSuccess = true;
					} catch(e) {
						// We have a parsererror
						statusText = "parsererror";
						error = e;
					}
				}
			} else {
				// We extract error from statusText
				// then normalize statusText and status for non-aborts
				error = statusText;
				if ( !statusText || status ) {
					statusText = "error";
					if ( status < 0 ) {
						status = 0;
					}
				}
			}

			// Set data for the fake xhr object
			jqXHR.status = status;
			jqXHR.statusText = "" + ( nativeStatusText || statusText );

			// Success/Error
			if ( isSuccess ) {
				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
			} else {
				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
			}

			// Status-dependent callbacks
			jqXHR.statusCode( statusCode );
			statusCode = undefined;

			if ( fireGlobals ) {
				globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
						[ jqXHR, s, isSuccess ? success : error ] );
			}

			// Complete
			completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );

			if ( fireGlobals ) {
				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
				// Handle the global AJAX counter
				if ( !( --jQuery.active ) ) {
					jQuery.event.trigger( "ajaxStop" );
				}
			}
		}

		// Attach deferreds
		deferred.promise( jqXHR );
		jqXHR.success = jqXHR.done;
		jqXHR.error = jqXHR.fail;
		jqXHR.complete = completeDeferred.add;

		// Status-dependent callbacks
		jqXHR.statusCode = function( map ) {
			if ( map ) {
				var tmp;
				if ( state < 2 ) {
					for ( tmp in map ) {
						statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
					}
				} else {
					tmp = map[ jqXHR.status ];
					jqXHR.then( tmp, tmp );
				}
			}
			return this;
		};

		// Remove hash character (#7531: and string promotion)
		// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
		// We also use the url parameter if available
		s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );

		// Extract dataTypes list
		s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax );

		// Determine if a cross-domain request is in order
		if ( s.crossDomain == null ) {
			parts = rurl.exec( s.url.toLowerCase() );
			s.crossDomain = !!( parts &&
				( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||
					( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
						( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
			);
		}

		// Convert data if not already a string
		if ( s.data && s.processData && typeof s.data !== "string" ) {
			s.data = jQuery.param( s.data, s.traditional );
		}

		// Apply prefilters
		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );

		// If request was aborted inside a prefiler, stop there
		if ( state === 2 ) {
			return false;
		}

		// We can fire global events as of now if asked to
		fireGlobals = s.global;

		// Uppercase the type
		s.type = s.type.toUpperCase();

		// Determine if request has content
		s.hasContent = !rnoContent.test( s.type );

		// Watch for a new set of requests
		if ( fireGlobals && jQuery.active++ === 0 ) {
			jQuery.event.trigger( "ajaxStart" );
		}

		// More options handling for requests with no content
		if ( !s.hasContent ) {

			// If data is available, append data to url
			if ( s.data ) {
				s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
				// #9682: remove data so that it's not used in an eventual retry
				delete s.data;
			}

			// Get ifModifiedKey before adding the anti-cache parameter
			ifModifiedKey = s.url;

			// Add anti-cache in url if needed
			if ( s.cache === false ) {

				var ts = jQuery.now(),
					// try replacing _= if it is there
					ret = s.url.replace( rts, "$1_=" + ts );

				// if nothing was replaced, add timestamp to the end
				s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );
			}
		}

		// Set the correct header, if data is being sent
		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
			jqXHR.setRequestHeader( "Content-Type", s.contentType );
		}

		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
		if ( s.ifModified ) {
			ifModifiedKey = ifModifiedKey || s.url;
			if ( jQuery.lastModified[ ifModifiedKey ] ) {
				jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] );
			}
			if ( jQuery.etag[ ifModifiedKey ] ) {
				jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] );
			}
		}

		// Set the Accepts header for the server, depending on the dataType
		jqXHR.setRequestHeader(
			"Accept",
			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
				s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
				s.accepts[ "*" ]
		);

		// Check for headers option
		for ( i in s.headers ) {
			jqXHR.setRequestHeader( i, s.headers[ i ] );
		}

		// Allow custom headers/mimetypes and early abort
		if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
				// Abort if not done already
				jqXHR.abort();
				return false;

		}

		// Install callbacks on deferreds
		for ( i in { success: 1, error: 1, complete: 1 } ) {
			jqXHR[ i ]( s[ i ] );
		}

		// Get transport
		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );

		// If no transport, we auto-abort
		if ( !transport ) {
			done( -1, "No Transport" );
		} else {
			jqXHR.readyState = 1;
			// Send global event
			if ( fireGlobals ) {
				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
			}
			// Timeout
			if ( s.async && s.timeout > 0 ) {
				timeoutTimer = setTimeout( function(){
					jqXHR.abort( "timeout" );
				}, s.timeout );
			}

			try {
				state = 1;
				transport.send( requestHeaders, done );
			} catch (e) {
				// Propagate exception as error if not done
				if ( state < 2 ) {
					done( -1, e );
				// Simply rethrow otherwise
				} else {
					throw e;
				}
			}
		}

		return jqXHR;
	},

	// Serialize an array of form elements or a set of
	// key/values into a query string
	param: function( a, traditional ) {
		var s = [],
			add = function( key, value ) {
				// If value is a function, invoke it and return its value
				value = jQuery.isFunction( value ) ? value() : value;
				s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
			};

		// Set traditional to true for jQuery <= 1.3.2 behavior.
		if ( traditional === undefined ) {
			traditional = jQuery.ajaxSettings.traditional;
		}

		// If an array was passed in, assume that it is an array of form elements.
		if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
			// Serialize the form elements
			jQuery.each( a, function() {
				add( this.name, this.value );
			});

		} else {
			// If traditional, encode the "old" way (the way 1.3.2 or older
			// did it), otherwise encode params recursively.
			for ( var prefix in a ) {
				buildParams( prefix, a[ prefix ], traditional, add );
			}
		}

		// Return the resulting serialization
		return s.join( "&" ).replace( r20, "+" );
	}
});

function buildParams( prefix, obj, traditional, add ) {
	if ( jQuery.isArray( obj ) ) {
		// Serialize array item.
		jQuery.each( obj, function( i, v ) {
			if ( traditional || rbracket.test( prefix ) ) {
				// Treat each array item as a scalar.
				add( prefix, v );

			} else {
				// If array item is non-scalar (array or object), encode its
				// numeric index to resolve deserialization ambiguity issues.
				// Note that rack (as of 1.0.0) can't currently deserialize
				// nested arrays properly, and attempting to do so may cause
				// a server error. Possible fixes are to modify rack's
				// deserialization algorithm or to provide an option or flag
				// to force array serialization to be shallow.
				buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add );
			}
		});

	} else if ( !traditional && obj != null && typeof obj === "object" ) {
		// Serialize object item.
		for ( var name in obj ) {
			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
		}

	} else {
		// Serialize scalar item.
		add( prefix, obj );
	}
}

// This is still on the jQuery object... for now
// Want to move this to jQuery.ajax some day
jQuery.extend({

	// Counter for holding the number of active queries
	active: 0,

	// Last-Modified header cache for next request
	lastModified: {},
	etag: {}

});

/* Handles responses to an ajax request:
 * - sets all responseXXX fields accordingly
 * - finds the right dataType (mediates between content-type and expected dataType)
 * - returns the corresponding response
 */
function ajaxHandleResponses( s, jqXHR, responses ) {

	var contents = s.contents,
		dataTypes = s.dataTypes,
		responseFields = s.responseFields,
		ct,
		type,
		finalDataType,
		firstDataType;

	// Fill responseXXX fields
	for ( type in responseFields ) {
		if ( type in responses ) {
			jqXHR[ responseFields[type] ] = responses[ type ];
		}
	}

	// Remove auto dataType and get content-type in the process
	while( dataTypes[ 0 ] === "*" ) {
		dataTypes.shift();
		if ( ct === undefined ) {
			ct = s.mimeType || jqXHR.getResponseHeader( "content-type" );
		}
	}

	// Check if we're dealing with a known content-type
	if ( ct ) {
		for ( type in contents ) {
			if ( contents[ type ] && contents[ type ].test( ct ) ) {
				dataTypes.unshift( type );
				break;
			}
		}
	}

	// Check to see if we have a response for the expected dataType
	if ( dataTypes[ 0 ] in responses ) {
		finalDataType = dataTypes[ 0 ];
	} else {
		// Try convertible dataTypes
		for ( type in responses ) {
			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
				finalDataType = type;
				break;
			}
			if ( !firstDataType ) {
				firstDataType = type;
			}
		}
		// Or just use first one
		finalDataType = finalDataType || firstDataType;
	}

	// If we found a dataType
	// We add the dataType to the list if needed
	// and return the corresponding response
	if ( finalDataType ) {
		if ( finalDataType !== dataTypes[ 0 ] ) {
			dataTypes.unshift( finalDataType );
		}
		return responses[ finalDataType ];
	}
}

// Chain conversions given the request and the original response
function ajaxConvert( s, response ) {

	// Apply the dataFilter if provided
	if ( s.dataFilter ) {
		response = s.dataFilter( response, s.dataType );
	}

	var dataTypes = s.dataTypes,
		converters = {},
		i,
		key,
		length = dataTypes.length,
		tmp,
		// Current and previous dataTypes
		current = dataTypes[ 0 ],
		prev,
		// Conversion expression
		conversion,
		// Conversion function
		conv,
		// Conversion functions (transitive conversion)
		conv1,
		conv2;

	// For each dataType in the chain
	for ( i = 1; i < length; i++ ) {

		// Create converters map
		// with lowercased keys
		if ( i === 1 ) {
			for ( key in s.converters ) {
				if ( typeof key === "string" ) {
					converters[ key.toLowerCase() ] = s.converters[ key ];
				}
			}
		}

		// Get the dataTypes
		prev = current;
		current = dataTypes[ i ];

		// If current is auto dataType, update it to prev
		if ( current === "*" ) {
			current = prev;
		// If no auto and dataTypes are actually different
		} else if ( prev !== "*" && prev !== current ) {

			// Get the converter
			conversion = prev + " " + current;
			conv = converters[ conversion ] || converters[ "* " + current ];

			// If there is no direct converter, search transitively
			if ( !conv ) {
				conv2 = undefined;
				for ( conv1 in converters ) {
					tmp = conv1.split( " " );
					if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) {
						conv2 = converters[ tmp[1] + " " + current ];
						if ( conv2 ) {
							conv1 = converters[ conv1 ];
							if ( conv1 === true ) {
								conv = conv2;
							} else if ( conv2 === true ) {
								conv = conv1;
							}
							break;
						}
					}
				}
			}
			// If we found no converter, dispatch an error
			if ( !( conv || conv2 ) ) {
				jQuery.error( "No conversion from " + conversion.replace(" "," to ") );
			}
			// If found converter is not an equivalence
			if ( conv !== true ) {
				// Convert with 1 or 2 converters accordingly
				response = conv ? conv( response ) : conv2( conv1(response) );
			}
		}
	}
	return response;
}




var jsc = jQuery.now(),
	jsre = /(\=)\?(&|$)|\?\?/i;

// Default jsonp settings
jQuery.ajaxSetup({
	jsonp: "callback",
	jsonpCallback: function() {
		return jQuery.expando + "_" + ( jsc++ );
	}
});

// Detect, normalize options and install callbacks for jsonp requests
jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {

	var inspectData = s.contentType === "application/x-www-form-urlencoded" &&
		( typeof s.data === "string" );

	if ( s.dataTypes[ 0 ] === "jsonp" ||
		s.jsonp !== false && ( jsre.test( s.url ) ||
				inspectData && jsre.test( s.data ) ) ) {

		var responseContainer,
			jsonpCallback = s.jsonpCallback =
				jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
			previous = window[ jsonpCallback ],
			url = s.url,
			data = s.data,
			replace = "$1" + jsonpCallback + "$2";

		if ( s.jsonp !== false ) {
			url = url.replace( jsre, replace );
			if ( s.url === url ) {
				if ( inspectData ) {
					data = data.replace( jsre, replace );
				}
				if ( s.data === data ) {
					// Add callback manually
					url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback;
				}
			}
		}

		s.url = url;
		s.data = data;

		// Install callback
		window[ jsonpCallback ] = function( response ) {
			responseContainer = [ response ];
		};

		// Clean-up function
		jqXHR.always(function() {
			// Set callback back to previous value
			window[ jsonpCallback ] = previous;
			// Call if it was a function and we have a response
			if ( responseContainer && jQuery.isFunction( previous ) ) {
				window[ jsonpCallback ]( responseContainer[ 0 ] );
			}
		});

		// Use data converter to retrieve json after script execution
		s.converters["script json"] = function() {
			if ( !responseContainer ) {
				jQuery.error( jsonpCallback + " was not called" );
			}
			return responseContainer[ 0 ];
		};

		// force json dataType
		s.dataTypes[ 0 ] = "json";

		// Delegate to script
		return "script";
	}
});




// Install script dataType
jQuery.ajaxSetup({
	accepts: {
		script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
	},
	contents: {
		script: /javascript|ecmascript/
	},
	converters: {
		"text script": function( text ) {
			jQuery.globalEval( text );
			return text;
		}
	}
});

// Handle cache's special case and global
jQuery.ajaxPrefilter( "script", function( s ) {
	if ( s.cache === undefined ) {
		s.cache = false;
	}
	if ( s.crossDomain ) {
		s.type = "GET";
		s.global = false;
	}
});

// Bind script tag hack transport
jQuery.ajaxTransport( "script", function(s) {

	// This transport only deals with cross domain requests
	if ( s.crossDomain ) {

		var script,
			head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;

		return {

			send: function( _, callback ) {

				script = document.createElement( "script" );

				script.async = "async";

				if ( s.scriptCharset ) {
					script.charset = s.scriptCharset;
				}

				script.src = s.url;

				// Attach handlers for all browsers
				script.onload = script.onreadystatechange = function( _, isAbort ) {

					if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {

						// Handle memory leak in IE
						script.onload = script.onreadystatechange = null;

						// Remove the script
						if ( head && script.parentNode ) {
							head.removeChild( script );
						}

						// Dereference the script
						script = undefined;

						// Callback if not abort
						if ( !isAbort ) {
							callback( 200, "success" );
						}
					}
				};
				// Use insertBefore instead of appendChild  to circumvent an IE6 bug.
				// This arises when a base node is used (#2709 and #4378).
				head.insertBefore( script, head.firstChild );
			},

			abort: function() {
				if ( script ) {
					script.onload( 0, 1 );
				}
			}
		};
	}
});




var // #5280: Internet Explorer will keep connections alive if we don't abort on unload
	xhrOnUnloadAbort = window.ActiveXObject ? function() {
		// Abort all pending requests
		for ( var key in xhrCallbacks ) {
			xhrCallbacks[ key ]( 0, 1 );
		}
	} : false,
	xhrId = 0,
	xhrCallbacks;

// Functions to create xhrs
function createStandardXHR() {
	try {
		return new window.XMLHttpRequest();
	} catch( e ) {}
}

function createActiveXHR() {
	try {
		return new window.ActiveXObject( "Microsoft.XMLHTTP" );
	} catch( e ) {}
}

// Create the request object
// (This is still attached to ajaxSettings for backward compatibility)
jQuery.ajaxSettings.xhr = window.ActiveXObject ?
	/* Microsoft failed to properly
	 * implement the XMLHttpRequest in IE7 (can't request local files),
	 * so we use the ActiveXObject when it is available
	 * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
	 * we need a fallback.
	 */
	function() {
		return !this.isLocal && createStandardXHR() || createActiveXHR();
	} :
	// For all other browsers, use the standard XMLHttpRequest object
	createStandardXHR;

// Determine support properties
(function( xhr ) {
	jQuery.extend( jQuery.support, {
		ajax: !!xhr,
		cors: !!xhr && ( "withCredentials" in xhr )
	});
})( jQuery.ajaxSettings.xhr() );

// Create transport if the browser can provide an xhr
if ( jQuery.support.ajax ) {

	jQuery.ajaxTransport(function( s ) {
		// Cross domain only allowed if supported through XMLHttpRequest
		if ( !s.crossDomain || jQuery.support.cors ) {

			var callback;

			return {
				send: function( headers, complete ) {

					// Get a new xhr
					var xhr = s.xhr(),
						handle,
						i;

					// Open the socket
					// Passing null username, generates a login popup on Opera (#2865)
					if ( s.username ) {
						xhr.open( s.type, s.url, s.async, s.username, s.password );
					} else {
						xhr.open( s.type, s.url, s.async );
					}

					// Apply custom fields if provided
					if ( s.xhrFields ) {
						for ( i in s.xhrFields ) {
							xhr[ i ] = s.xhrFields[ i ];
						}
					}

					// Override mime type if needed
					if ( s.mimeType && xhr.overrideMimeType ) {
						xhr.overrideMimeType( s.mimeType );
					}

					// X-Requested-With header
					// For cross-domain requests, seeing as conditions for a preflight are
					// akin to a jigsaw puzzle, we simply never set it to be sure.
					// (it can always be set on a per-request basis or even using ajaxSetup)
					// For same-domain requests, won't change header if already provided.
					if ( !s.crossDomain && !headers["X-Requested-With"] ) {
						headers[ "X-Requested-With" ] = "XMLHttpRequest";
					}

					// Need an extra try/catch for cross domain requests in Firefox 3
					try {
						for ( i in headers ) {
							xhr.setRequestHeader( i, headers[ i ] );
						}
					} catch( _ ) {}

					// Do send the request
					// This may raise an exception which is actually
					// handled in jQuery.ajax (so no try/catch here)
					xhr.send( ( s.hasContent && s.data ) || null );

					// Listener
					callback = function( _, isAbort ) {

						var status,
							statusText,
							responseHeaders,
							responses,
							xml;

						// Firefox throws exceptions when accessing properties
						// of an xhr when a network error occured
						// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
						try {

							// Was never called and is aborted or complete
							if ( callback && ( isAbort || xhr.readyState === 4 ) ) {

								// Only called once
								callback = undefined;

								// Do not keep as active anymore
								if ( handle ) {
									xhr.onreadystatechange = jQuery.noop;
									if ( xhrOnUnloadAbort ) {
										delete xhrCallbacks[ handle ];
									}
								}

								// If it's an abort
								if ( isAbort ) {
									// Abort it manually if needed
									if ( xhr.readyState !== 4 ) {
										xhr.abort();
									}
								} else {
									status = xhr.status;
									responseHeaders = xhr.getAllResponseHeaders();
									responses = {};
									xml = xhr.responseXML;

									// Construct response list
									if ( xml && xml.documentElement /* #4958 */ ) {
										responses.xml = xml;
									}
									responses.text = xhr.responseText;

									// Firefox throws an exception when accessing
									// statusText for faulty cross-domain requests
									try {
										statusText = xhr.statusText;
									} catch( e ) {
										// We normalize with Webkit giving an empty statusText
										statusText = "";
									}

									// Filter status for non standard behaviors

									// If the request is local and we have data: assume a success
									// (success with no data won't get notified, that's the best we
									// can do given current implementations)
									if ( !status && s.isLocal && !s.crossDomain ) {
										status = responses.text ? 200 : 404;
									// IE - #1450: sometimes returns 1223 when it should be 204
									} else if ( status === 1223 ) {
										status = 204;
									}
								}
							}
						} catch( firefoxAccessException ) {
							if ( !isAbort ) {
								complete( -1, firefoxAccessException );
							}
						}

						// Call complete if needed
						if ( responses ) {
							complete( status, statusText, responses, responseHeaders );
						}
					};

					// if we're in sync mode or it's in cache
					// and has been retrieved directly (IE6 & IE7)
					// we need to manually fire the callback
					if ( !s.async || xhr.readyState === 4 ) {
						callback();
					} else {
						handle = ++xhrId;
						if ( xhrOnUnloadAbort ) {
							// Create the active xhrs callbacks list if needed
							// and attach the unload handler
							if ( !xhrCallbacks ) {
								xhrCallbacks = {};
								jQuery( window ).unload( xhrOnUnloadAbort );
							}
							// Add to list of active xhrs callbacks
							xhrCallbacks[ handle ] = callback;
						}
						xhr.onreadystatechange = callback;
					}
				},

				abort: function() {
					if ( callback ) {
						callback(0,1);
					}
				}
			};
		}
	});
}




var elemdisplay = {},
	iframe, iframeDoc,
	rfxtypes = /^(?:toggle|show|hide)$/,
	rfxnum = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,
	timerId,
	fxAttrs = [
		// height animations
		[ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
		// width animations
		[ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
		// opacity animations
		[ "opacity" ]
	],
	fxNow;

jQuery.fn.extend({
	show: function( speed, easing, callback ) {
		var elem, display;

		if ( speed || speed === 0 ) {
			return this.animate( genFx("show", 3), speed, easing, callback );

		} else {
			for ( var i = 0, j = this.length; i < j; i++ ) {
				elem = this[ i ];

				if ( elem.style ) {
					display = elem.style.display;

					// Reset the inline display of this element to learn if it is
					// being hidden by cascaded rules or not
					if ( !jQuery._data(elem, "olddisplay") && display === "none" ) {
						display = elem.style.display = "";
					}

					// Set elements which have been overridden with display: none
					// in a stylesheet to whatever the default browser style is
					// for such an element
					if ( display === "" && jQuery.css(elem, "display") === "none" ) {
						jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) );
					}
				}
			}

			// Set the display of most of the elements in a second loop
			// to avoid the constant reflow
			for ( i = 0; i < j; i++ ) {
				elem = this[ i ];

				if ( elem.style ) {
					display = elem.style.display;

					if ( display === "" || display === "none" ) {
						elem.style.display = jQuery._data( elem, "olddisplay" ) || "";
					}
				}
			}

			return this;
		}
	},

	hide: function( speed, easing, callback ) {
		if ( speed || speed === 0 ) {
			return this.animate( genFx("hide", 3), speed, easing, callback);

		} else {
			var elem, display,
				i = 0,
				j = this.length;

			for ( ; i < j; i++ ) {
				elem = this[i];
				if ( elem.style ) {
					display = jQuery.css( elem, "display" );

					if ( display !== "none" && !jQuery._data( elem, "olddisplay" ) ) {
						jQuery._data( elem, "olddisplay", display );
					}
				}
			}

			// Set the display of the elements in a second loop
			// to avoid the constant reflow
			for ( i = 0; i < j; i++ ) {
				if ( this[i].style ) {
					this[i].style.display = "none";
				}
			}

			return this;
		}
	},

	// Save the old toggle function
	_toggle: jQuery.fn.toggle,

	toggle: function( fn, fn2, callback ) {
		var bool = typeof fn === "boolean";

		if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
			this._toggle.apply( this, arguments );

		} else if ( fn == null || bool ) {
			this.each(function() {
				var state = bool ? fn : jQuery(this).is(":hidden");
				jQuery(this)[ state ? "show" : "hide" ]();
			});

		} else {
			this.animate(genFx("toggle", 3), fn, fn2, callback);
		}

		return this;
	},

	fadeTo: function( speed, to, easing, callback ) {
		return this.filter(":hidden").css("opacity", 0).show().end()
					.animate({opacity: to}, speed, easing, callback);
	},

	animate: function( prop, speed, easing, callback ) {
		var optall = jQuery.speed( speed, easing, callback );

		if ( jQuery.isEmptyObject( prop ) ) {
			return this.each( optall.complete, [ false ] );
		}

		// Do not change referenced properties as per-property easing will be lost
		prop = jQuery.extend( {}, prop );

		function doAnimation() {
			// XXX 'this' does not always have a nodeName when running the
			// test suite

			if ( optall.queue === false ) {
				jQuery._mark( this );
			}

			var opt = jQuery.extend( {}, optall ),
				isElement = this.nodeType === 1,
				hidden = isElement && jQuery(this).is(":hidden"),
				name, val, p, e,
				parts, start, end, unit,
				method;

			// will store per property easing and be used to determine when an animation is complete
			opt.animatedProperties = {};

			for ( p in prop ) {

				// property name normalization
				name = jQuery.camelCase( p );
				if ( p !== name ) {
					prop[ name ] = prop[ p ];
					delete prop[ p ];
				}

				val = prop[ name ];

				// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)
				if ( jQuery.isArray( val ) ) {
					opt.animatedProperties[ name ] = val[ 1 ];
					val = prop[ name ] = val[ 0 ];
				} else {
					opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';
				}

				if ( val === "hide" && hidden || val === "show" && !hidden ) {
					return opt.complete.call( this );
				}

				if ( isElement && ( name === "height" || name === "width" ) ) {
					// Make sure that nothing sneaks out
					// Record all 3 overflow attributes because IE does not
					// change the overflow attribute when overflowX and
					// overflowY are set to the same value
					opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];

					// Set display property to inline-block for height/width
					// animations on inline elements that are having width/height animated
					if ( jQuery.css( this, "display" ) === "inline" &&
							jQuery.css( this, "float" ) === "none" ) {

						// inline-level elements accept inline-block;
						// block-level elements need to be inline with layout
						if ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === "inline" ) {
							this.style.display = "inline-block";

						} else {
							this.style.zoom = 1;
						}
					}
				}
			}

			if ( opt.overflow != null ) {
				this.style.overflow = "hidden";
			}

			for ( p in prop ) {
				e = new jQuery.fx( this, opt, p );
				val = prop[ p ];

				if ( rfxtypes.test( val ) ) {

					// Tracks whether to show or hide based on private
					// data attached to the element
					method = jQuery._data( this, "toggle" + p ) || ( val === "toggle" ? hidden ? "show" : "hide" : 0 );
					if ( method ) {
						jQuery._data( this, "toggle" + p, method === "show" ? "hide" : "show" );
						e[ method ]();
					} else {
						e[ val ]();
					}

				} else {
					parts = rfxnum.exec( val );
					start = e.cur();

					if ( parts ) {
						end = parseFloat( parts[2] );
						unit = parts[3] || ( jQuery.cssNumber[ p ] ? "" : "px" );

						// We need to compute starting value
						if ( unit !== "px" ) {
							jQuery.style( this, p, (end || 1) + unit);
							start = ( (end || 1) / e.cur() ) * start;
							jQuery.style( this, p, start + unit);
						}

						// If a +=/-= token was provided, we're doing a relative animation
						if ( parts[1] ) {
							end = ( (parts[ 1 ] === "-=" ? -1 : 1) * end ) + start;
						}

						e.custom( start, end, unit );

					} else {
						e.custom( start, val, "" );
					}
				}
			}

			// For JS strict compliance
			return true;
		}

		return optall.queue === false ?
			this.each( doAnimation ) :
			this.queue( optall.queue, doAnimation );
	},

	stop: function( type, clearQueue, gotoEnd ) {
		if ( typeof type !== "string" ) {
			gotoEnd = clearQueue;
			clearQueue = type;
			type = undefined;
		}
		if ( clearQueue && type !== false ) {
			this.queue( type || "fx", [] );
		}

		return this.each(function() {
			var index,
				hadTimers = false,
				timers = jQuery.timers,
				data = jQuery._data( this );

			// clear marker counters if we know they won't be
			if ( !gotoEnd ) {
				jQuery._unmark( true, this );
			}

			function stopQueue( elem, data, index ) {
				var hooks = data[ index ];
				jQuery.removeData( elem, index, true );
				hooks.stop( gotoEnd );
			}

			if ( type == null ) {
				for ( index in data ) {
					if ( data[ index ] && data[ index ].stop && index.indexOf(".run") === index.length - 4 ) {
						stopQueue( this, data, index );
					}
				}
			} else if ( data[ index = type + ".run" ] && data[ index ].stop ){
				stopQueue( this, data, index );
			}

			for ( index = timers.length; index--; ) {
				if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
					if ( gotoEnd ) {

						// force the next step to be the last
						timers[ index ]( true );
					} else {
						timers[ index ].saveState();
					}
					hadTimers = true;
					timers.splice( index, 1 );
				}
			}

			// start the next in the queue if the last step wasn't forced
			// timers currently will call their complete callbacks, which will dequeue
			// but only if they were gotoEnd
			if ( !( gotoEnd && hadTimers ) ) {
				jQuery.dequeue( this, type );
			}
		});
	}

});

// Animations created synchronously will run synchronously
function createFxNow() {
	setTimeout( clearFxNow, 0 );
	return ( fxNow = jQuery.now() );
}

function clearFxNow() {
	fxNow = undefined;
}

// Generate parameters to create a standard animation
function genFx( type, num ) {
	var obj = {};

	jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {
		obj[ this ] = type;
	});

	return obj;
}

// Generate shortcuts for custom animations
jQuery.each({
	slideDown: genFx( "show", 1 ),
	slideUp: genFx( "hide", 1 ),
	slideToggle: genFx( "toggle", 1 ),
	fadeIn: { opacity: "show" },
	fadeOut: { opacity: "hide" },
	fadeToggle: { opacity: "toggle" }
}, function( name, props ) {
	jQuery.fn[ name ] = function( speed, easing, callback ) {
		return this.animate( props, speed, easing, callback );
	};
});

jQuery.extend({
	speed: function( speed, easing, fn ) {
		var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
			complete: fn || !fn && easing ||
				jQuery.isFunction( speed ) && speed,
			duration: speed,
			easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
		};

		opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
			opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;

		// normalize opt.queue - true/undefined/null -> "fx"
		if ( opt.queue == null || opt.queue === true ) {
			opt.queue = "fx";
		}

		// Queueing
		opt.old = opt.complete;

		opt.complete = function( noUnmark ) {
			if ( jQuery.isFunction( opt.old ) ) {
				opt.old.call( this );
			}

			if ( opt.queue ) {
				jQuery.dequeue( this, opt.queue );
			} else if ( noUnmark !== false ) {
				jQuery._unmark( this );
			}
		};

		return opt;
	},

	easing: {
		linear: function( p, n, firstNum, diff ) {
			return firstNum + diff * p;
		},
		swing: function( p, n, firstNum, diff ) {
			return ( ( -Math.cos( p*Math.PI ) / 2 ) + 0.5 ) * diff + firstNum;
		}
	},

	timers: [],

	fx: function( elem, options, prop ) {
		this.options = options;
		this.elem = elem;
		this.prop = prop;

		options.orig = options.orig || {};
	}

});

jQuery.fx.prototype = {
	// Simple function for setting a style value
	update: function() {
		if ( this.options.step ) {
			this.options.step.call( this.elem, this.now, this );
		}

		( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );
	},

	// Get the current size
	cur: function() {
		if ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {
			return this.elem[ this.prop ];
		}

		var parsed,
			r = jQuery.css( this.elem, this.prop );
		// Empty strings, null, undefined and "auto" are converted to 0,
		// complex values such as "rotate(1rad)" are returned as is,
		// simple values such as "10px" are parsed to Float.
		return isNaN( parsed = parseFloat( r ) ) ? !r || r === "auto" ? 0 : r : parsed;
	},

	// Start an animation from one number to another
	custom: function( from, to, unit ) {
		var self = this,
			fx = jQuery.fx;

		this.startTime = fxNow || createFxNow();
		this.end = to;
		this.now = this.start = from;
		this.pos = this.state = 0;
		this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" );

		function t( gotoEnd ) {
			return self.step( gotoEnd );
		}

		t.queue = this.options.queue;
		t.elem = this.elem;
		t.saveState = function() {
			if ( self.options.hide && jQuery._data( self.elem, "fxshow" + self.prop ) === undefined ) {
				jQuery._data( self.elem, "fxshow" + self.prop, self.start );
			}
		};

		if ( t() && jQuery.timers.push(t) && !timerId ) {
			timerId = setInterval( fx.tick, fx.interval );
		}
	},

	// Simple 'show' function
	show: function() {
		var dataShow = jQuery._data( this.elem, "fxshow" + this.prop );

		// Remember where we started, so that we can go back to it later
		this.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );
		this.options.show = true;

		// Begin the animation
		// Make sure that we start at a small width/height to avoid any flash of content
		if ( dataShow !== undefined ) {
			// This show is picking up where a previous hide or show left off
			this.custom( this.cur(), dataShow );
		} else {
			this.custom( this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur() );
		}

		// Start by showing the element
		jQuery( this.elem ).show();
	},

	// Simple 'hide' function
	hide: function() {
		// Remember where we started, so that we can go back to it later
		this.options.orig[ this.prop ] = jQuery._data( this.elem, "fxshow" + this.prop ) || jQuery.style( this.elem, this.prop );
		this.options.hide = true;

		// Begin the animation
		this.custom( this.cur(), 0 );
	},

	// Each step of an animation
	step: function( gotoEnd ) {
		var p, n, complete,
			t = fxNow || createFxNow(),
			done = true,
			elem = this.elem,
			options = this.options;

		if ( gotoEnd || t >= options.duration + this.startTime ) {
			this.now = this.end;
			this.pos = this.state = 1;
			this.update();

			options.animatedProperties[ this.prop ] = true;

			for ( p in options.animatedProperties ) {
				if ( options.animatedProperties[ p ] !== true ) {
					done = false;
				}
			}

			if ( done ) {
				// Reset the overflow
				if ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {

					jQuery.each( [ "", "X", "Y" ], function( index, value ) {
						elem.style[ "overflow" + value ] = options.overflow[ index ];
					});
				}

				// Hide the element if the "hide" operation was done
				if ( options.hide ) {
					jQuery( elem ).hide();
				}

				// Reset the properties, if the item has been hidden or shown
				if ( options.hide || options.show ) {
					for ( p in options.animatedProperties ) {
						jQuery.style( elem, p, options.orig[ p ] );
						jQuery.removeData( elem, "fxshow" + p, true );
						// Toggle data is no longer needed
						jQuery.removeData( elem, "toggle" + p, true );
					}
				}

				// Execute the complete function
				// in the event that the complete function throws an exception
				// we must ensure it won't be called twice. #5684

				complete = options.complete;
				if ( complete ) {

					options.complete = false;
					complete.call( elem );
				}
			}

			return false;

		} else {
			// classical easing cannot be used with an Infinity duration
			if ( options.duration == Infinity ) {
				this.now = t;
			} else {
				n = t - this.startTime;
				this.state = n / options.duration;

				// Perform the easing function, defaults to swing
				this.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );
				this.now = this.start + ( (this.end - this.start) * this.pos );
			}
			// Perform the next step of the animation
			this.update();
		}

		return true;
	}
};

jQuery.extend( jQuery.fx, {
	tick: function() {
		var timer,
			timers = jQuery.timers,
			i = 0;

		for ( ; i < timers.length; i++ ) {
			timer = timers[ i ];
			// Checks the timer has not already been removed
			if ( !timer() && timers[ i ] === timer ) {
				timers.splice( i--, 1 );
			}
		}

		if ( !timers.length ) {
			jQuery.fx.stop();
		}
	},

	interval: 13,

	stop: function() {
		clearInterval( timerId );
		timerId = null;
	},

	speeds: {
		slow: 600,
		fast: 200,
		// Default speed
		_default: 400
	},

	step: {
		opacity: function( fx ) {
			jQuery.style( fx.elem, "opacity", fx.now );
		},

		_default: function( fx ) {
			if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
				fx.elem.style[ fx.prop ] = fx.now + fx.unit;
			} else {
				fx.elem[ fx.prop ] = fx.now;
			}
		}
	}
});

// Adds width/height step functions
// Do not set anything below 0
jQuery.each([ "width", "height" ], function( i, prop ) {
	jQuery.fx.step[ prop ] = function( fx ) {
		jQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit );
	};
});

if ( jQuery.expr && jQuery.expr.filters ) {
	jQuery.expr.filters.animated = function( elem ) {
		return jQuery.grep(jQuery.timers, function( fn ) {
			return elem === fn.elem;
		}).length;
	};
}

// Try to restore the default display value of an element
function defaultDisplay( nodeName ) {

	if ( !elemdisplay[ nodeName ] ) {

		var body = document.body,
			elem = jQuery( "<" + nodeName + ">" ).appendTo( body ),
			display = elem.css( "display" );
		elem.remove();

		// If the simple way fails,
		// get element's real default display by attaching it to a temp iframe
		if ( display === "none" || display === "" ) {
			// No iframe to use yet, so create it
			if ( !iframe ) {
				iframe = document.createElement( "iframe" );
				iframe.frameBorder = iframe.width = iframe.height = 0;
			}

			body.appendChild( iframe );

			// Create a cacheable copy of the iframe document on first call.
			// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML
			// document to it; WebKit & Firefox won't allow reusing the iframe document.
			if ( !iframeDoc || !iframe.createElement ) {
				iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;
				iframeDoc.write( ( document.compatMode === "CSS1Compat" ? "<!doctype html>" : "" ) + "<html><body>" );
				iframeDoc.close();
			}

			elem = iframeDoc.createElement( nodeName );

			iframeDoc.body.appendChild( elem );

			display = jQuery.css( elem, "display" );
			body.removeChild( iframe );
		}

		// Store the correct default display
		elemdisplay[ nodeName ] = display;
	}

	return elemdisplay[ nodeName ];
}




var rtable = /^t(?:able|d|h)$/i,
	rroot = /^(?:body|html)$/i;

if ( "getBoundingClientRect" in document.documentElement ) {
	jQuery.fn.offset = function( options ) {
		var elem = this[0], box;

		if ( options ) {
			return this.each(function( i ) {
				jQuery.offset.setOffset( this, options, i );
			});
		}

		if ( !elem || !elem.ownerDocument ) {
			return null;
		}

		if ( elem === elem.ownerDocument.body ) {
			return jQuery.offset.bodyOffset( elem );
		}

		try {
			box = elem.getBoundingClientRect();
		} catch(e) {}

		var doc = elem.ownerDocument,
			docElem = doc.documentElement;

		// Make sure we're not dealing with a disconnected DOM node
		if ( !box || !jQuery.contains( docElem, elem ) ) {
			return box ? { top: box.top, left: box.left } : { top: 0, left: 0 };
		}

		var body = doc.body,
			win = getWindow(doc),
			clientTop  = docElem.clientTop  || body.clientTop  || 0,
			clientLeft = docElem.clientLeft || body.clientLeft || 0,
			scrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,
			scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,
			top  = box.top  + scrollTop  - clientTop,
			left = box.left + scrollLeft - clientLeft;

		return { top: top, left: left };
	};

} else {
	jQuery.fn.offset = function( options ) {
		var elem = this[0];

		if ( options ) {
			return this.each(function( i ) {
				jQuery.offset.setOffset( this, options, i );
			});
		}

		if ( !elem || !elem.ownerDocument ) {
			return null;
		}

		if ( elem === elem.ownerDocument.body ) {
			return jQuery.offset.bodyOffset( elem );
		}

		var computedStyle,
			offsetParent = elem.offsetParent,
			prevOffsetParent = elem,
			doc = elem.ownerDocument,
			docElem = doc.documentElement,
			body = doc.body,
			defaultView = doc.defaultView,
			prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
			top = elem.offsetTop,
			left = elem.offsetLeft;

		while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
			if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) {
				break;
			}

			computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
			top  -= elem.scrollTop;
			left -= elem.scrollLeft;

			if ( elem === offsetParent ) {
				top  += elem.offsetTop;
				left += elem.offsetLeft;

				if ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {
					top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
					left += parseFloat( computedStyle.borderLeftWidth ) || 0;
				}

				prevOffsetParent = offsetParent;
				offsetParent = elem.offsetParent;
			}

			if ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
				top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
				left += parseFloat( computedStyle.borderLeftWidth ) || 0;
			}

			prevComputedStyle = computedStyle;
		}

		if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
			top  += body.offsetTop;
			left += body.offsetLeft;
		}

		if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) {
			top  += Math.max( docElem.scrollTop, body.scrollTop );
			left += Math.max( docElem.scrollLeft, body.scrollLeft );
		}

		return { top: top, left: left };
	};
}

jQuery.offset = {

	bodyOffset: function( body ) {
		var top = body.offsetTop,
			left = body.offsetLeft;

		if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {
			top  += parseFloat( jQuery.css(body, "marginTop") ) || 0;
			left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
		}

		return { top: top, left: left };
	},

	setOffset: function( elem, options, i ) {
		var position = jQuery.css( elem, "position" );

		// set position first, in-case top/left are set even on static elem
		if ( position === "static" ) {
			elem.style.position = "relative";
		}

		var curElem = jQuery( elem ),
			curOffset = curElem.offset(),
			curCSSTop = jQuery.css( elem, "top" ),
			curCSSLeft = jQuery.css( elem, "left" ),
			calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
			props = {}, curPosition = {}, curTop, curLeft;

		// need to be able to calculate position if either top or left is auto and position is either absolute or fixed
		if ( calculatePosition ) {
			curPosition = curElem.position();
			curTop = curPosition.top;
			curLeft = curPosition.left;
		} else {
			curTop = parseFloat( curCSSTop ) || 0;
			curLeft = parseFloat( curCSSLeft ) || 0;
		}

		if ( jQuery.isFunction( options ) ) {
			options = options.call( elem, i, curOffset );
		}

		if ( options.top != null ) {
			props.top = ( options.top - curOffset.top ) + curTop;
		}
		if ( options.left != null ) {
			props.left = ( options.left - curOffset.left ) + curLeft;
		}

		if ( "using" in options ) {
			options.using.call( elem, props );
		} else {
			curElem.css( props );
		}
	}
};


jQuery.fn.extend({

	position: function() {
		if ( !this[0] ) {
			return null;
		}

		var elem = this[0],

		// Get *real* offsetParent
		offsetParent = this.offsetParent(),

		// Get correct offsets
		offset       = this.offset(),
		parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();

		// Subtract element margins
		// note: when an element has margin: auto the offsetLeft and marginLeft
		// are the same in Safari causing offset.left to incorrectly be 0
		offset.top  -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
		offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;

		// Add offsetParent borders
		parentOffset.top  += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
		parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;

		// Subtract the two offsets
		return {
			top:  offset.top  - parentOffset.top,
			left: offset.left - parentOffset.left
		};
	},

	offsetParent: function() {
		return this.map(function() {
			var offsetParent = this.offsetParent || document.body;
			while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
				offsetParent = offsetParent.offsetParent;
			}
			return offsetParent;
		});
	}
});


// Create scrollLeft and scrollTop methods
jQuery.each( ["Left", "Top"], function( i, name ) {
	var method = "scroll" + name;

	jQuery.fn[ method ] = function( val ) {
		var elem, win;

		if ( val === undefined ) {
			elem = this[ 0 ];

			if ( !elem ) {
				return null;
			}

			win = getWindow( elem );

			// Return the scroll offset
			return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
				jQuery.support.boxModel && win.document.documentElement[ method ] ||
					win.document.body[ method ] :
				elem[ method ];
		}

		// Set the scroll offset
		return this.each(function() {
			win = getWindow( this );

			if ( win ) {
				win.scrollTo(
					!i ? val : jQuery( win ).scrollLeft(),
					 i ? val : jQuery( win ).scrollTop()
				);

			} else {
				this[ method ] = val;
			}
		});
	};
});

function getWindow( elem ) {
	return jQuery.isWindow( elem ) ?
		elem :
		elem.nodeType === 9 ?
			elem.defaultView || elem.parentWindow :
			false;
}




// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods
jQuery.each([ "Height", "Width" ], function( i, name ) {

	var type = name.toLowerCase();

	// innerHeight and innerWidth
	jQuery.fn[ "inner" + name ] = function() {
		var elem = this[0];
		return elem ?
			elem.style ?
			parseFloat( jQuery.css( elem, type, "padding" ) ) :
			this[ type ]() :
			null;
	};

	// outerHeight and outerWidth
	jQuery.fn[ "outer" + name ] = function( margin ) {
		var elem = this[0];
		return elem ?
			elem.style ?
			parseFloat( jQuery.css( elem, type, margin ? "margin" : "border" ) ) :
			this[ type ]() :
			null;
	};

	jQuery.fn[ type ] = function( size ) {
		// Get window width or height
		var elem = this[0];
		if ( !elem ) {
			return size == null ? null : this;
		}

		if ( jQuery.isFunction( size ) ) {
			return this.each(function( i ) {
				var self = jQuery( this );
				self[ type ]( size.call( this, i, self[ type ]() ) );
			});
		}

		if ( jQuery.isWindow( elem ) ) {
			// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
			// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat
			var docElemProp = elem.document.documentElement[ "client" + name ],
				body = elem.document.body;
			return elem.document.compatMode === "CSS1Compat" && docElemProp ||
				body && body[ "client" + name ] || docElemProp;

		// Get document width or height
		} else if ( elem.nodeType === 9 ) {
			// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
			return Math.max(
				elem.documentElement["client" + name],
				elem.body["scroll" + name], elem.documentElement["scroll" + name],
				elem.body["offset" + name], elem.documentElement["offset" + name]
			);

		// Get or set width or height on the element
		} else if ( size === undefined ) {
			var orig = jQuery.css( elem, type ),
				ret = parseFloat( orig );

			return jQuery.isNumeric( ret ) ? ret : orig;

		// Set the width or height on the element (default to pixels if value is unitless)
		} else {
			return this.css( type, typeof size === "string" ? size : size + "px" );
		}
	};

});




// Expose jQuery to the global object
window.jQuery = window.$ = jQuery;

// Expose jQuery as an AMD module, but only for AMD loaders that
// understand the issues with loading multiple versions of jQuery
// in a page that all might call define(). The loader will indicate
// they have special allowances for multiple jQuery versions by
// specifying define.amd.jQuery = true. Register as a named module,
// since jQuery can be concatenated with other files that may use define,
// but not use a proper concatenation script that understands anonymous
// AMD modules. A named AMD is safest and most robust way to register.
// Lowercase jquery is used because AMD module names are derived from
// file names, and jQuery is normally delivered in a lowercase file name.
// Do this after creating the global so that if an AMD module wants to call
// noConflict to hide this version of jQuery, it will work.
if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
	define( "jquery", [], function () { return jQuery; } );
}



})( window );
jQuery.expr[':'].Contains = function(a, i, m) {
    return jQuery(a).text().toUpperCase().indexOf(m[3].toUpperCase()) >= 0;
};

$(function() {
    $("#sidebar-nav").accordion({
        autoHeight: false,
        navigation: true,
        collapsible: true
    }).accordion("activate", false)
            .find('a.link').unbind('click').click(
            function(ev) {
                ev.cancelBubble = true; // IE
                if (ev.stopPropagation) {
                    ev.stopPropagation(); // the rest
                }

                return true;
            }).prev().prev().remove();

    $("#sidebar-nav>h3").click(function() {
        if ($(this).attr('initialized') == 'true') return;

        $(this).next().find(".sidebar-nav-tree").treeview({
            collapsed: true,
            persist: "cookie"
        });
        $(this).attr('initialized', true);
    });
});

function tree_search(input) {
    treeview = $(input).parent().parent().next();

    // Expand all items
    treeview.find('.expandable-hitarea').click();

    // make all items visible again
    treeview.find('li:hidden').show();

    // hide all items that do not match the given search criteria
    if ($(input).val()) {
        treeview.find('li').not(':has(a:Contains(' + $(input).val() + '))').hide();
    }
}
/*!
 * jQuery UI 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI
 */
(function(c){c.ui=c.ui||{};if(!c.ui.version){c.extend(c.ui,{version:"1.8.2",plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&&a.element[0].parentNode)for(var e=0;e<b.length;e++)a.options[b[e][0]]&&b[e][1].apply(a.element,d)}},contains:function(a,b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScroll:function(a,b){if(c(a).css("overflow")==
"hidden")return false;b=b&&b=="left"?"scrollLeft":"scrollTop";var d=false;if(a[b]>0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a<b+d},isOver:function(a,b,d,e,f,g){return c.ui.isOverAxis(a,d,f)&&c.ui.isOverAxis(b,e,g)},keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,
NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});c.fn.extend({_focus:c.fn.focus,focus:function(a,b){return typeof a==="number"?this.each(function(){var d=this;setTimeout(function(){c(d).focus();b&&b.call(d)},a)}):this._focus.apply(this,arguments)},enableSelection:function(){return this.attr("unselectable","off").css("MozUserSelect","")},disableSelection:function(){return this.attr("unselectable","on").css("MozUserSelect",
"none")},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this,"position",1))&&/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",
1))}).eq(0);return/fixed/.test(this.css("position"))||!a.length?c(document):a},zIndex:function(a){if(a!==undefined)return this.css("zIndex",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css("position");if(b=="absolute"||b=="relative"||b=="fixed"){b=parseInt(a.css("zIndex"));if(!isNaN(b)&&b!=0)return b}a=a.parent()}}return 0}});c.extend(c.expr[":"],{data:function(a,b,d){return!!c.data(a,d[3])},focusable:function(a){var b=a.nodeName.toLowerCase(),d=c.attr(a,"tabindex");return(/input|select|textarea|button|object/.test(b)?
!a.disabled:"a"==b||"area"==b?a.href||!isNaN(d):!isNaN(d))&&!c(a)["area"==b?"parents":"closest"](":hidden").length},tabbable:function(a){var b=c.attr(a,"tabindex");return(isNaN(b)||b>=0)&&c(a).is(":focusable")}})}})(jQuery);
;/*!
 * jQuery UI Widget 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Widget
 */
(function(b){var j=b.fn.remove;b.fn.remove=function(a,c){return this.each(function(){if(!c)if(!a||b.filter(a,[this]).length)b("*",this).add(this).each(function(){b(this).triggerHandler("remove")});return j.call(b(this),a,c)})};b.widget=function(a,c,d){var e=a.split(".")[0],f;a=a.split(".")[1];f=e+"-"+a;if(!d){d=c;c=b.Widget}b.expr[":"][f]=function(h){return!!b.data(h,a)};b[e]=b[e]||{};b[e][a]=function(h,g){arguments.length&&this._createWidget(h,g)};c=new c;c.options=b.extend({},c.options);b[e][a].prototype=
b.extend(true,c,{namespace:e,widgetName:a,widgetEventPrefix:b[e][a].prototype.widgetEventPrefix||a,widgetBaseClass:f},d);b.widget.bridge(a,b[e][a])};b.widget.bridge=function(a,c){b.fn[a]=function(d){var e=typeof d==="string",f=Array.prototype.slice.call(arguments,1),h=this;d=!e&&f.length?b.extend.apply(null,[true,d].concat(f)):d;if(e&&d.substring(0,1)==="_")return h;e?this.each(function(){var g=b.data(this,a),i=g&&b.isFunction(g[d])?g[d].apply(g,f):g;if(i!==g&&i!==undefined){h=i;return false}}):this.each(function(){var g=
b.data(this,a);if(g){d&&g.option(d);g._init()}else b.data(this,a,new c(d,this))});return h}};b.Widget=function(a,c){arguments.length&&this._createWidget(a,c)};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(a,c){this.element=b(c).data(this.widgetName,this);this.options=b.extend(true,{},this.options,b.metadata&&b.metadata.get(c)[this.widgetName],a);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()});this._create();
this._init()},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},widget:function(){return this.element},option:function(a,c){var d=a,e=this;if(arguments.length===0)return b.extend({},e.options);if(typeof a==="string"){if(c===undefined)return this.options[a];d={};d[a]=c}b.each(d,function(f,
h){e._setOption(f,h)});return e},_setOption:function(a,c){this.options[a]=c;if(a==="disabled")this.widget()[c?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",c);return this},enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(a,c,d){var e=this.options[a];c=b.Event(c);c.type=(a===this.widgetEventPrefix?a:this.widgetEventPrefix+a).toLowerCase();d=d||{};if(c.originalEvent){a=
b.event.props.length;for(var f;a;){f=b.event.props[--a];c[f]=c.originalEvent[f]}}this.element.trigger(c,d);return!(b.isFunction(e)&&e.call(this.element[0],c,d)===false||c.isDefaultPrevented())}}})(jQuery);
;/*!
 * jQuery UI Mouse 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Mouse
 *
 * Depends:
 *	jquery.ui.widget.js
 */
(function(c){c.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var a=this;this.element.bind("mousedown."+this.widgetName,function(b){return a._mouseDown(b)}).bind("click."+this.widgetName,function(b){if(a._preventClickEvent){a._preventClickEvent=false;b.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(a){a.originalEvent=a.originalEvent||{};if(!a.originalEvent.mouseHandled){this._mouseStarted&&
this._mouseUp(a);this._mouseDownEvent=a;var b=this,e=a.which==1,f=typeof this.options.cancel=="string"?c(a.target).parents().add(a.target).filter(this.options.cancel).length:false;if(!e||f||!this._mouseCapture(a))return true;this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet)this._mouseDelayTimer=setTimeout(function(){b.mouseDelayMet=true},this.options.delay);if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a)){this._mouseStarted=this._mouseStart(a)!==false;if(!this._mouseStarted){a.preventDefault();
return true}}this._mouseMoveDelegate=function(d){return b._mouseMove(d)};this._mouseUpDelegate=function(d){return b._mouseUp(d)};c(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);c.browser.safari||a.preventDefault();return a.originalEvent.mouseHandled=true}},_mouseMove:function(a){if(c.browser.msie&&!a.button)return this._mouseUp(a);if(this._mouseStarted){this._mouseDrag(a);return a.preventDefault()}if(this._mouseDistanceMet(a)&&
this._mouseDelayMet(a))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,a)!==false)?this._mouseDrag(a):this._mouseUp(a);return!this._mouseStarted},_mouseUp:function(a){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=a.target==this._mouseDownEvent.target;this._mouseStop(a)}return false},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-
a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery);
;/*
 * jQuery UI Position 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Position
 */
(function(c){c.ui=c.ui||{};var m=/left|center|right/,n=/top|center|bottom/,p=c.fn.position,q=c.fn.offset;c.fn.position=function(a){if(!a||!a.of)return p.apply(this,arguments);a=c.extend({},a);var b=c(a.of),d=(a.collision||"flip").split(" "),e=a.offset?a.offset.split(" "):[0,0],g,h,i;if(a.of.nodeType===9){g=b.width();h=b.height();i={top:0,left:0}}else if(a.of.scrollTo&&a.of.document){g=b.width();h=b.height();i={top:b.scrollTop(),left:b.scrollLeft()}}else if(a.of.preventDefault){a.at="left top";g=h=
0;i={top:a.of.pageY,left:a.of.pageX}}else{g=b.outerWidth();h=b.outerHeight();i=b.offset()}c.each(["my","at"],function(){var f=(a[this]||"").split(" ");if(f.length===1)f=m.test(f[0])?f.concat(["center"]):n.test(f[0])?["center"].concat(f):["center","center"];f[0]=m.test(f[0])?f[0]:"center";f[1]=n.test(f[1])?f[1]:"center";a[this]=f});if(d.length===1)d[1]=d[0];e[0]=parseInt(e[0],10)||0;if(e.length===1)e[1]=e[0];e[1]=parseInt(e[1],10)||0;if(a.at[0]==="right")i.left+=g;else if(a.at[0]==="center")i.left+=
g/2;if(a.at[1]==="bottom")i.top+=h;else if(a.at[1]==="center")i.top+=h/2;i.left+=e[0];i.top+=e[1];return this.each(function(){var f=c(this),k=f.outerWidth(),l=f.outerHeight(),j=c.extend({},i);if(a.my[0]==="right")j.left-=k;else if(a.my[0]==="center")j.left-=k/2;if(a.my[1]==="bottom")j.top-=l;else if(a.my[1]==="center")j.top-=l/2;j.left=parseInt(j.left);j.top=parseInt(j.top);c.each(["left","top"],function(o,r){c.ui.position[d[o]]&&c.ui.position[d[o]][r](j,{targetWidth:g,targetHeight:h,elemWidth:k,
elemHeight:l,offset:e,my:a.my,at:a.at})});c.fn.bgiframe&&f.bgiframe();f.offset(c.extend(j,{using:a.using}))})};c.ui.position={fit:{left:function(a,b){var d=c(window);b=a.left+b.elemWidth-d.width()-d.scrollLeft();a.left=b>0?a.left-b:Math.max(0,a.left)},top:function(a,b){var d=c(window);b=a.top+b.elemHeight-d.height()-d.scrollTop();a.top=b>0?a.top-b:Math.max(0,a.top)}},flip:{left:function(a,b){if(b.at[0]!=="center"){var d=c(window);d=a.left+b.elemWidth-d.width()-d.scrollLeft();var e=b.my[0]==="left"?
-b.elemWidth:b.my[0]==="right"?b.elemWidth:0,g=-2*b.offset[0];a.left+=a.left<0?e+b.targetWidth+g:d>0?e-b.targetWidth+g:0}},top:function(a,b){if(b.at[1]!=="center"){var d=c(window);d=a.top+b.elemHeight-d.height()-d.scrollTop();var e=b.my[1]==="top"?-b.elemHeight:b.my[1]==="bottom"?b.elemHeight:0,g=b.at[1]==="top"?b.targetHeight:-b.targetHeight,h=-2*b.offset[1];a.top+=a.top<0?e+b.targetHeight+h:d>0?e+g+h:0}}}};if(!c.offset.setOffset){c.offset.setOffset=function(a,b){if(/static/.test(c.curCSS(a,"position")))a.style.position=
"relative";var d=c(a),e=d.offset(),g=parseInt(c.curCSS(a,"top",true),10)||0,h=parseInt(c.curCSS(a,"left",true),10)||0;e={top:b.top-e.top+g,left:b.left-e.left+h};"using"in b?b.using.call(a,e):d.css(e)};c.fn.offset=function(a){var b=this[0];if(!b||!b.ownerDocument)return null;if(a)return this.each(function(){c.offset.setOffset(this,a)});return q.call(this)}}})(jQuery);
;/*
 * jQuery UI Draggable 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Draggables
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.mouse.js
 *	jquery.ui.widget.js
 */
(function(d){d.widget("ui.draggable",d.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:true,appendTo:"parent",axis:false,connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false},_create:function(){if(this.options.helper==
"original"&&!/^(?:r|a|f)/.test(this.element.css("position")))this.element[0].style.position="relative";this.options.addClasses&&this.element.addClass("ui-draggable");this.options.disabled&&this.element.addClass("ui-draggable-disabled");this._mouseInit()},destroy:function(){if(this.element.data("draggable")){this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._mouseDestroy();return this}},_mouseCapture:function(a){var b=
this.options;if(this.helper||b.disabled||d(a.target).is(".ui-resizable-handle"))return false;this.handle=this._getHandle(a);if(!this.handle)return false;return true},_mouseStart:function(a){var b=this.options;this.helper=this._createHelper(a);this._cacheHelperProportions();if(d.ui.ddmanager)d.ui.ddmanager.current=this;this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.positionAbs=this.element.offset();this.offset={top:this.offset.top-
this.margins.top,left:this.offset.left-this.margins.left};d.extend(this.offset,{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this.position=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);b.containment&&this._setContainment();if(this._trigger("start",a)===false){this._clear();return false}this._cacheHelperProportions();
d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.helper.addClass("ui-draggable-dragging");this._mouseDrag(a,true);return true},_mouseDrag:function(a,b){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");if(!b){b=this._uiHash();if(this._trigger("drag",a,b)===false){this._mouseUp({});return false}this.position=b.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||
this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);return false},_mouseStop:function(a){var b=false;if(d.ui.ddmanager&&!this.options.dropBehaviour)b=d.ui.ddmanager.drop(this,a);if(this.dropped){b=this.dropped;this.dropped=false}if(!this.element[0]||!this.element[0].parentNode)return false;if(this.options.revert=="invalid"&&!b||this.options.revert=="valid"&&b||this.options.revert===true||d.isFunction(this.options.revert)&&this.options.revert.call(this.element,
b)){var c=this;d(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){c._trigger("stop",a)!==false&&c._clear()})}else this._trigger("stop",a)!==false&&this._clear();return false},cancel:function(){this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear();return this},_getHandle:function(a){var b=!this.options.handle||!d(this.options.handle,this.element).length?true:false;d(this.options.handle,this.element).find("*").andSelf().each(function(){if(this==
a.target)b=true});return b},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a])):b.helper=="clone"?this.element.clone():this.element;a.parents("body").length||a.appendTo(b.appendTo=="parent"?this.element[0].parentNode:b.appendTo);a[0]!=this.element[0]&&!/(fixed|absolute)/.test(a.css("position"))&&a.css("position","absolute");return a},_adjustOffsetFromHelper:function(a){if(typeof a=="string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]||
0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],
this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.element.position();return{top:a.top-
(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;if(a.containment==
"parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)&&
a.containment.constructor!=Array){var b=d(a.containment)[0];if(b){a=d(a.containment).offset();var c=d(b).css("overflow")!="hidden";this.containment=[a.left+(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0)-this.margins.left,a.top+(parseInt(d(b).css("borderTopWidth"),10)||0)+(parseInt(d(b).css("paddingTop"),10)||0)-this.margins.top,a.left+(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"),
10)||0)-this.helperProportions.width-this.margins.left,a.top+(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"),10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}}else if(a.containment.constructor==Array)this.containment=a.containment},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],
this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName);return{top:b.top+this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():
f?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName),e=a.pageX,g=a.pageY;if(this.originalPosition){if(this.containment){if(a.pageX-this.offset.click.left<this.containment[0])e=this.containment[0]+this.offset.click.left;if(a.pageY-this.offset.click.top<this.containment[1])g=this.containment[1]+
this.offset.click.top;if(a.pageX-this.offset.click.left>this.containment[2])e=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?g:!(g-this.offset.click.top<this.containment[1])?g-b.grid[1]:g+b.grid[1]:g;e=this.originalPageX+
Math.round((e-this.originalPageX)/b.grid[0])*b.grid[0];e=this.containment?!(e-this.offset.click.left<this.containment[0]||e-this.offset.click.left>this.containment[2])?e:!(e-this.offset.click.left<this.containment[0])?e-b.grid[0]:e+b.grid[0]:e}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop()),left:e-this.offset.click.left-
this.offset.relative.left-this.offset.parent.left+(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():f?0:c.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging");this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove();this.helper=null;this.cancelHelperRemoval=false},_trigger:function(a,b,c){c=c||this._uiHash();d.ui.plugin.call(this,a,[b,c]);if(a=="drag")this.positionAbs=
this._convertPositionTo("absolute");return d.Widget.prototype._trigger.call(this,a,b,c)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}});d.extend(d.ui.draggable,{version:"1.8.2"});d.ui.plugin.add("draggable","connectToSortable",{start:function(a,b){var c=d(this).data("draggable"),f=c.options,e=d.extend({},b,{item:c.element});c.sortables=[];d(f.connectToSortable).each(function(){var g=d.data(this,"sortable");
if(g&&!g.options.disabled){c.sortables.push({instance:g,shouldRevert:g.options.revert});g._refreshItems();g._trigger("activate",a,e)}})},stop:function(a,b){var c=d(this).data("draggable"),f=d.extend({},b,{item:c.element});d.each(c.sortables,function(){if(this.instance.isOver){this.instance.isOver=0;c.cancelHelperRemoval=true;this.instance.cancelHelperRemoval=false;if(this.shouldRevert)this.instance.options.revert=true;this.instance._mouseStop(a);this.instance.options.helper=this.instance.options._helper;
c.options.helper=="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})}else{this.instance.cancelHelperRemoval=false;this.instance._trigger("deactivate",a,f)}})},drag:function(a,b){var c=d(this).data("draggable"),f=this;d.each(c.sortables,function(){this.instance.positionAbs=c.positionAbs;this.instance.helperProportions=c.helperProportions;this.instance.offset.click=c.offset.click;if(this.instance._intersectsWith(this.instance.containerCache)){if(!this.instance.isOver){this.instance.isOver=
1;this.instance.currentItem=d(f).clone().appendTo(this.instance.element).data("sortable-item",true);this.instance.options._helper=this.instance.options.helper;this.instance.options.helper=function(){return b.helper[0]};a.target=this.instance.currentItem[0];this.instance._mouseCapture(a,true);this.instance._mouseStart(a,true,true);this.instance.offset.click.top=c.offset.click.top;this.instance.offset.click.left=c.offset.click.left;this.instance.offset.parent.left-=c.offset.parent.left-this.instance.offset.parent.left;
this.instance.offset.parent.top-=c.offset.parent.top-this.instance.offset.parent.top;c._trigger("toSortable",a);c.dropped=this.instance.element;c.currentItem=c.element;this.instance.fromOutside=c}this.instance.currentItem&&this.instance._mouseDrag(a)}else if(this.instance.isOver){this.instance.isOver=0;this.instance.cancelHelperRemoval=true;this.instance.options.revert=false;this.instance._trigger("out",a,this.instance._uiHash(this.instance));this.instance._mouseStop(a,true);this.instance.options.helper=
this.instance.options._helper;this.instance.currentItem.remove();this.instance.placeholder&&this.instance.placeholder.remove();c._trigger("fromSortable",a);c.dropped=false}})}});d.ui.plugin.add("draggable","cursor",{start:function(){var a=d("body"),b=d(this).data("draggable").options;if(a.css("cursor"))b._cursor=a.css("cursor");a.css("cursor",b.cursor)},stop:function(){var a=d(this).data("draggable").options;a._cursor&&d("body").css("cursor",a._cursor)}});d.ui.plugin.add("draggable","iframeFix",{start:function(){var a=
d(this).data("draggable").options;d(a.iframeFix===true?"iframe":a.iframeFix).each(function(){d('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1E3}).css(d(this).offset()).appendTo("body")})},stop:function(){d("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)})}});d.ui.plugin.add("draggable","opacity",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options;
if(a.css("opacity"))b._opacity=a.css("opacity");a.css("opacity",b.opacity)},stop:function(a,b){a=d(this).data("draggable").options;a._opacity&&d(b.helper).css("opacity",a._opacity)}});d.ui.plugin.add("draggable","scroll",{start:function(){var a=d(this).data("draggable");if(a.scrollParent[0]!=document&&a.scrollParent[0].tagName!="HTML")a.overflowOffset=a.scrollParent.offset()},drag:function(a){var b=d(this).data("draggable"),c=b.options,f=false;if(b.scrollParent[0]!=document&&b.scrollParent[0].tagName!=
"HTML"){if(!c.axis||c.axis!="x")if(b.overflowOffset.top+b.scrollParent[0].offsetHeight-a.pageY<c.scrollSensitivity)b.scrollParent[0].scrollTop=f=b.scrollParent[0].scrollTop+c.scrollSpeed;else if(a.pageY-b.overflowOffset.top<c.scrollSensitivity)b.scrollParent[0].scrollTop=f=b.scrollParent[0].scrollTop-c.scrollSpeed;if(!c.axis||c.axis!="y")if(b.overflowOffset.left+b.scrollParent[0].offsetWidth-a.pageX<c.scrollSensitivity)b.scrollParent[0].scrollLeft=f=b.scrollParent[0].scrollLeft+c.scrollSpeed;else if(a.pageX-
b.overflowOffset.left<c.scrollSensitivity)b.scrollParent[0].scrollLeft=f=b.scrollParent[0].scrollLeft-c.scrollSpeed}else{if(!c.axis||c.axis!="x")if(a.pageY-d(document).scrollTop()<c.scrollSensitivity)f=d(document).scrollTop(d(document).scrollTop()-c.scrollSpeed);else if(d(window).height()-(a.pageY-d(document).scrollTop())<c.scrollSensitivity)f=d(document).scrollTop(d(document).scrollTop()+c.scrollSpeed);if(!c.axis||c.axis!="y")if(a.pageX-d(document).scrollLeft()<c.scrollSensitivity)f=d(document).scrollLeft(d(document).scrollLeft()-
c.scrollSpeed);else if(d(window).width()-(a.pageX-d(document).scrollLeft())<c.scrollSensitivity)f=d(document).scrollLeft(d(document).scrollLeft()+c.scrollSpeed)}f!==false&&d.ui.ddmanager&&!c.dropBehaviour&&d.ui.ddmanager.prepareOffsets(b,a)}});d.ui.plugin.add("draggable","snap",{start:function(){var a=d(this).data("draggable"),b=a.options;a.snapElements=[];d(b.snap.constructor!=String?b.snap.items||":data(draggable)":b.snap).each(function(){var c=d(this),f=c.offset();this!=a.element[0]&&a.snapElements.push({item:this,
width:c.outerWidth(),height:c.outerHeight(),top:f.top,left:f.left})})},drag:function(a,b){for(var c=d(this).data("draggable"),f=c.options,e=f.snapTolerance,g=b.offset.left,n=g+c.helperProportions.width,m=b.offset.top,o=m+c.helperProportions.height,h=c.snapElements.length-1;h>=0;h--){var i=c.snapElements[h].left,k=i+c.snapElements[h].width,j=c.snapElements[h].top,l=j+c.snapElements[h].height;if(i-e<g&&g<k+e&&j-e<m&&m<l+e||i-e<g&&g<k+e&&j-e<o&&o<l+e||i-e<n&&n<k+e&&j-e<m&&m<l+e||i-e<n&&n<k+e&&j-e<o&&
o<l+e){if(f.snapMode!="inner"){var p=Math.abs(j-o)<=e,q=Math.abs(l-m)<=e,r=Math.abs(i-n)<=e,s=Math.abs(k-g)<=e;if(p)b.position.top=c._convertPositionTo("relative",{top:j-c.helperProportions.height,left:0}).top-c.margins.top;if(q)b.position.top=c._convertPositionTo("relative",{top:l,left:0}).top-c.margins.top;if(r)b.position.left=c._convertPositionTo("relative",{top:0,left:i-c.helperProportions.width}).left-c.margins.left;if(s)b.position.left=c._convertPositionTo("relative",{top:0,left:k}).left-c.margins.left}var t=
p||q||r||s;if(f.snapMode!="outer"){p=Math.abs(j-m)<=e;q=Math.abs(l-o)<=e;r=Math.abs(i-g)<=e;s=Math.abs(k-n)<=e;if(p)b.position.top=c._convertPositionTo("relative",{top:j,left:0}).top-c.margins.top;if(q)b.position.top=c._convertPositionTo("relative",{top:l-c.helperProportions.height,left:0}).top-c.margins.top;if(r)b.position.left=c._convertPositionTo("relative",{top:0,left:i}).left-c.margins.left;if(s)b.position.left=c._convertPositionTo("relative",{top:0,left:k-c.helperProportions.width}).left-c.margins.left}if(!c.snapElements[h].snapping&&
(p||q||r||s||t))c.options.snap.snap&&c.options.snap.snap.call(c.element,a,d.extend(c._uiHash(),{snapItem:c.snapElements[h].item}));c.snapElements[h].snapping=p||q||r||s||t}else{c.snapElements[h].snapping&&c.options.snap.release&&c.options.snap.release.call(c.element,a,d.extend(c._uiHash(),{snapItem:c.snapElements[h].item}));c.snapElements[h].snapping=false}}}});d.ui.plugin.add("draggable","stack",{start:function(){var a=d(this).data("draggable").options;a=d.makeArray(d(a.stack)).sort(function(c,f){return(parseInt(d(c).css("zIndex"),
10)||0)-(parseInt(d(f).css("zIndex"),10)||0)});if(a.length){var b=parseInt(a[0].style.zIndex)||0;d(a).each(function(c){this.style.zIndex=b+c});this[0].style.zIndex=b+a.length}}});d.ui.plugin.add("draggable","zIndex",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options;if(a.css("zIndex"))b._zIndex=a.css("zIndex");a.css("zIndex",b.zIndex)},stop:function(a,b){a=d(this).data("draggable").options;a._zIndex&&d(b.helper).css("zIndex",a._zIndex)}})})(jQuery);
;/*
 * jQuery UI Droppable 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Droppables
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 *	jquery.ui.mouse.js
 *	jquery.ui.draggable.js
 */
(function(d){d.widget("ui.droppable",{widgetEventPrefix:"drop",options:{accept:"*",activeClass:false,addClasses:true,greedy:false,hoverClass:false,scope:"default",tolerance:"intersect"},_create:function(){var a=this.options,b=a.accept;this.isover=0;this.isout=1;this.accept=d.isFunction(b)?b:function(c){return c.is(b)};this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight};d.ui.ddmanager.droppables[a.scope]=d.ui.ddmanager.droppables[a.scope]||[];d.ui.ddmanager.droppables[a.scope].push(this);
a.addClasses&&this.element.addClass("ui-droppable")},destroy:function(){for(var a=d.ui.ddmanager.droppables[this.options.scope],b=0;b<a.length;b++)a[b]==this&&a.splice(b,1);this.element.removeClass("ui-droppable ui-droppable-disabled").removeData("droppable").unbind(".droppable");return this},_setOption:function(a,b){if(a=="accept")this.accept=d.isFunction(b)?b:function(c){return c.is(b)};d.Widget.prototype._setOption.apply(this,arguments)},_activate:function(a){var b=d.ui.ddmanager.current;this.options.activeClass&&
this.element.addClass(this.options.activeClass);b&&this._trigger("activate",a,this.ui(b))},_deactivate:function(a){var b=d.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass);b&&this._trigger("deactivate",a,this.ui(b))},_over:function(a){var b=d.ui.ddmanager.current;if(!(!b||(b.currentItem||b.element)[0]==this.element[0]))if(this.accept.call(this.element[0],b.currentItem||b.element)){this.options.hoverClass&&this.element.addClass(this.options.hoverClass);
this._trigger("over",a,this.ui(b))}},_out:function(a){var b=d.ui.ddmanager.current;if(!(!b||(b.currentItem||b.element)[0]==this.element[0]))if(this.accept.call(this.element[0],b.currentItem||b.element)){this.options.hoverClass&&this.element.removeClass(this.options.hoverClass);this._trigger("out",a,this.ui(b))}},_drop:function(a,b){var c=b||d.ui.ddmanager.current;if(!c||(c.currentItem||c.element)[0]==this.element[0])return false;var e=false;this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var g=
d.data(this,"droppable");if(g.options.greedy&&!g.options.disabled&&g.options.scope==c.options.scope&&g.accept.call(g.element[0],c.currentItem||c.element)&&d.ui.intersect(c,d.extend(g,{offset:g.element.offset()}),g.options.tolerance)){e=true;return false}});if(e)return false;if(this.accept.call(this.element[0],c.currentItem||c.element)){this.options.activeClass&&this.element.removeClass(this.options.activeClass);this.options.hoverClass&&this.element.removeClass(this.options.hoverClass);this._trigger("drop",
a,this.ui(c));return this.element}return false},ui:function(a){return{draggable:a.currentItem||a.element,helper:a.helper,position:a.position,offset:a.positionAbs}}});d.extend(d.ui.droppable,{version:"1.8.2"});d.ui.intersect=function(a,b,c){if(!b.offset)return false;var e=(a.positionAbs||a.position.absolute).left,g=e+a.helperProportions.width,f=(a.positionAbs||a.position.absolute).top,h=f+a.helperProportions.height,i=b.offset.left,k=i+b.proportions.width,j=b.offset.top,l=j+b.proportions.height;
switch(c){case "fit":return i<e&&g<k&&j<f&&h<l;case "intersect":return i<e+a.helperProportions.width/2&&g-a.helperProportions.width/2<k&&j<f+a.helperProportions.height/2&&h-a.helperProportions.height/2<l;case "pointer":return d.ui.isOver((a.positionAbs||a.position.absolute).top+(a.clickOffset||a.offset.click).top,(a.positionAbs||a.position.absolute).left+(a.clickOffset||a.offset.click).left,j,i,b.proportions.height,b.proportions.width);case "touch":return(f>=j&&f<=l||h>=j&&h<=l||f<j&&h>l)&&(e>=i&&
e<=k||g>=i&&g<=k||e<i&&g>k);default:return false}};d.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(a,b){var c=d.ui.ddmanager.droppables[a.options.scope]||[],e=b?b.type:null,g=(a.currentItem||a.element).find(":data(droppable)").andSelf(),f=0;a:for(;f<c.length;f++)if(!(c[f].options.disabled||a&&!c[f].accept.call(c[f].element[0],a.currentItem||a.element))){for(var h=0;h<g.length;h++)if(g[h]==c[f].element[0]){c[f].proportions.height=0;continue a}c[f].visible=c[f].element.css("display")!=
"none";if(c[f].visible){c[f].offset=c[f].element.offset();c[f].proportions={width:c[f].element[0].offsetWidth,height:c[f].element[0].offsetHeight};e=="mousedown"&&c[f]._activate.call(c[f],b)}}},drop:function(a,b){var c=false;d.each(d.ui.ddmanager.droppables[a.options.scope]||[],function(){if(this.options){if(!this.options.disabled&&this.visible&&d.ui.intersect(a,this,this.options.tolerance))c=c||this._drop.call(this,b);if(!this.options.disabled&&this.visible&&this.accept.call(this.element[0],a.currentItem||
a.element)){this.isout=1;this.isover=0;this._deactivate.call(this,b)}}});return c},drag:function(a,b){a.options.refreshPositions&&d.ui.ddmanager.prepareOffsets(a,b);d.each(d.ui.ddmanager.droppables[a.options.scope]||[],function(){if(!(this.options.disabled||this.greedyChild||!this.visible)){var c=d.ui.intersect(a,this,this.options.tolerance);if(c=!c&&this.isover==1?"isout":c&&this.isover==0?"isover":null){var e;if(this.options.greedy){var g=this.element.parents(":data(droppable):eq(0)");if(g.length){e=
d.data(g[0],"droppable");e.greedyChild=c=="isover"?1:0}}if(e&&c=="isover"){e.isover=0;e.isout=1;e._out.call(e,b)}this[c]=1;this[c=="isout"?"isover":"isout"]=0;this[c=="isover"?"_over":"_out"].call(this,b);if(e&&c=="isout"){e.isout=0;e.isover=1;e._over.call(e,b)}}}})}}})(jQuery);
;/*
 * jQuery UI Resizable 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Resizables
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.mouse.js
 *	jquery.ui.widget.js
 */
(function(d){d.widget("ui.resizable",d.ui.mouse,{widgetEventPrefix:"resize",options:{alsoResize:false,animate:false,animateDuration:"slow",animateEasing:"swing",aspectRatio:false,autoHide:false,containment:false,ghost:false,grid:false,handles:"e,s,se",helper:false,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1E3},_create:function(){var b=this,a=this.options;this.element.addClass("ui-resizable");d.extend(this,{_aspectRatio:!!a.aspectRatio,aspectRatio:a.aspectRatio,originalElement:this.element,
_proportionallyResizeElements:[],_helper:a.helper||a.ghost||a.animate?a.helper||"ui-resizable-helper":null});if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)){/relative/.test(this.element.css("position"))&&d.browser.opera&&this.element.css({position:"relative",top:"auto",left:"auto"});this.element.wrap(d('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),
top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle=
this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=a.handles||(!d(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",
nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all")this.handles="n,e,s,w,se,sw,ne,nw";var c=this.handles.split(",");this.handles={};for(var e=0;e<c.length;e++){var g=d.trim(c[e]),f=d('<div class="ui-resizable-handle '+("ui-resizable-"+g)+'"></div>');/sw|se|ne|nw/.test(g)&&f.css({zIndex:++a.zIndex});"se"==g&&f.addClass("ui-icon ui-icon-gripsmall-diagonal-se");this.handles[g]=".ui-resizable-"+g;this.element.append(f)}}this._renderAxis=function(h){h=h||this.element;for(var i in this.handles){if(this.handles[i].constructor==
String)this.handles[i]=d(this.handles[i],this.element).show();if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var j=d(this.handles[i],this.element),l=0;l=/sw|ne|nw|se|n|s/.test(i)?j.outerHeight():j.outerWidth();j=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join("");h.css(j,l);this._proportionallyResize()}d(this.handles[i])}};this._renderAxis(this.element);this._handles=d(".ui-resizable-handle",this.element).disableSelection();
this._handles.mouseover(function(){if(!b.resizing){if(this.className)var h=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);b.axis=h&&h[1]?h[1]:"se"}});if(a.autoHide){this._handles.hide();d(this.element).addClass("ui-resizable-autohide").hover(function(){d(this).removeClass("ui-resizable-autohide");b._handles.show()},function(){if(!b.resizing){d(this).addClass("ui-resizable-autohide");b._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var b=function(c){d(c).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};
if(this.elementIsWrapper){b(this.element);var a=this.element;a.after(this.originalElement.css({position:a.css("position"),width:a.outerWidth(),height:a.outerHeight(),top:a.css("top"),left:a.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle);b(this.originalElement);return this},_mouseCapture:function(b){var a=false;for(var c in this.handles)if(d(this.handles[c])[0]==b.target)a=true;return!this.options.disabled&&a},_mouseStart:function(b){var a=this.options,c=this.element.position(),
e=this.element;this.resizing=true;this.documentScroll={top:d(document).scrollTop(),left:d(document).scrollLeft()};if(e.is(".ui-draggable")||/absolute/.test(e.css("position")))e.css({position:"absolute",top:c.top,left:c.left});d.browser.opera&&/relative/.test(e.css("position"))&&e.css({position:"relative",top:"auto",left:"auto"});this._renderProxy();c=m(this.helper.css("left"));var g=m(this.helper.css("top"));if(a.containment){c+=d(a.containment).scrollLeft()||0;g+=d(a.containment).scrollTop()||0}this.offset=
this.helper.offset();this.position={left:c,top:g};this.size=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalSize=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalPosition={left:c,top:g};this.sizeDiff={width:e.outerWidth()-e.width(),height:e.outerHeight()-e.height()};this.originalMousePosition={left:b.pageX,top:b.pageY};this.aspectRatio=typeof a.aspectRatio=="number"?a.aspectRatio:
this.originalSize.width/this.originalSize.height||1;a=d(".ui-resizable-"+this.axis).css("cursor");d("body").css("cursor",a=="auto"?this.axis+"-resize":a);e.addClass("ui-resizable-resizing");this._propagate("start",b);return true},_mouseDrag:function(b){var a=this.helper,c=this.originalMousePosition,e=this._change[this.axis];if(!e)return false;c=e.apply(this,[b,b.pageX-c.left||0,b.pageY-c.top||0]);if(this._aspectRatio||b.shiftKey)c=this._updateRatio(c,b);c=this._respectSize(c,b);this._propagate("resize",
b);a.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize();this._updateCache(c);this._trigger("resize",b,this.ui());return false},_mouseStop:function(b){this.resizing=false;var a=this.options,c=this;if(this._helper){var e=this._proportionallyResizeElements,g=e.length&&/textarea/i.test(e[0].nodeName);e=g&&d.ui.hasScroll(e[0],"left")?0:c.sizeDiff.height;
g={width:c.size.width-(g?0:c.sizeDiff.width),height:c.size.height-e};e=parseInt(c.element.css("left"),10)+(c.position.left-c.originalPosition.left)||null;var f=parseInt(c.element.css("top"),10)+(c.position.top-c.originalPosition.top)||null;a.animate||this.element.css(d.extend(g,{top:f,left:e}));c.helper.height(c.size.height);c.helper.width(c.size.width);this._helper&&!a.animate&&this._proportionallyResize()}d("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",
b);this._helper&&this.helper.remove();return false},_updateCache:function(b){this.offset=this.helper.offset();if(k(b.left))this.position.left=b.left;if(k(b.top))this.position.top=b.top;if(k(b.height))this.size.height=b.height;if(k(b.width))this.size.width=b.width},_updateRatio:function(b){var a=this.position,c=this.size,e=this.axis;if(b.height)b.width=c.height*this.aspectRatio;else if(b.width)b.height=c.width/this.aspectRatio;if(e=="sw"){b.left=a.left+(c.width-b.width);b.top=null}if(e=="nw"){b.top=
a.top+(c.height-b.height);b.left=a.left+(c.width-b.width)}return b},_respectSize:function(b){var a=this.options,c=this.axis,e=k(b.width)&&a.maxWidth&&a.maxWidth<b.width,g=k(b.height)&&a.maxHeight&&a.maxHeight<b.height,f=k(b.width)&&a.minWidth&&a.minWidth>b.width,h=k(b.height)&&a.minHeight&&a.minHeight>b.height;if(f)b.width=a.minWidth;if(h)b.height=a.minHeight;if(e)b.width=a.maxWidth;if(g)b.height=a.maxHeight;var i=this.originalPosition.left+this.originalSize.width,j=this.position.top+this.size.height,
l=/sw|nw|w/.test(c);c=/nw|ne|n/.test(c);if(f&&l)b.left=i-a.minWidth;if(e&&l)b.left=i-a.maxWidth;if(h&&c)b.top=j-a.minHeight;if(g&&c)b.top=j-a.maxHeight;if((a=!b.width&&!b.height)&&!b.left&&b.top)b.top=null;else if(a&&!b.top&&b.left)b.left=null;return b},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var b=this.helper||this.element,a=0;a<this._proportionallyResizeElements.length;a++){var c=this._proportionallyResizeElements[a];if(!this.borderDif){var e=[c.css("borderTopWidth"),
c.css("borderRightWidth"),c.css("borderBottomWidth"),c.css("borderLeftWidth")],g=[c.css("paddingTop"),c.css("paddingRight"),c.css("paddingBottom"),c.css("paddingLeft")];this.borderDif=d.map(e,function(f,h){f=parseInt(f,10)||0;h=parseInt(g[h],10)||0;return f+h})}d.browser.msie&&(d(b).is(":hidden")||d(b).parents(":hidden").length)||c.css({height:b.height()-this.borderDif[0]-this.borderDif[2]||0,width:b.width()-this.borderDif[1]-this.borderDif[3]||0})}},_renderProxy:function(){var b=this.options;this.elementOffset=
this.element.offset();if(this._helper){this.helper=this.helper||d('<div style="overflow:hidden;"></div>');var a=d.browser.msie&&d.browser.version<7,c=a?1:0;a=a?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+a,height:this.element.outerHeight()+a,position:"absolute",left:this.elementOffset.left-c+"px",top:this.elementOffset.top-c+"px",zIndex:++b.zIndex});this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(b,a){return{width:this.originalSize.width+
a}},w:function(b,a){return{left:this.originalPosition.left+a,width:this.originalSize.width-a}},n:function(b,a,c){return{top:this.originalPosition.top+c,height:this.originalSize.height-c}},s:function(b,a,c){return{height:this.originalSize.height+c}},se:function(b,a,c){return d.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[b,a,c]))},sw:function(b,a,c){return d.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[b,a,c]))},ne:function(b,a,c){return d.extend(this._change.n.apply(this,
arguments),this._change.e.apply(this,[b,a,c]))},nw:function(b,a,c){return d.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[b,a,c]))}},_propagate:function(b,a){d.ui.plugin.call(this,b,[a,this.ui()]);b!="resize"&&this._trigger(b,a,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}});d.extend(d.ui.resizable,
{version:"1.8.2"});d.ui.plugin.add("resizable","alsoResize",{start:function(){var b=d(this).data("resizable").options,a=function(c){d(c).each(function(){d(this).data("resizable-alsoresize",{width:parseInt(d(this).width(),10),height:parseInt(d(this).height(),10),left:parseInt(d(this).css("left"),10),top:parseInt(d(this).css("top"),10)})})};if(typeof b.alsoResize=="object"&&!b.alsoResize.parentNode)if(b.alsoResize.length){b.alsoResize=b.alsoResize[0];a(b.alsoResize)}else d.each(b.alsoResize,function(c){a(c)});
else a(b.alsoResize)},resize:function(){var b=d(this).data("resizable"),a=b.options,c=b.originalSize,e=b.originalPosition,g={height:b.size.height-c.height||0,width:b.size.width-c.width||0,top:b.position.top-e.top||0,left:b.position.left-e.left||0},f=function(h,i){d(h).each(function(){var j=d(this),l=d(this).data("resizable-alsoresize"),p={};d.each((i&&i.length?i:["width","height","top","left"])||["width","height","top","left"],function(n,o){if((n=(l[o]||0)+(g[o]||0))&&n>=0)p[o]=n||null});if(/relative/.test(j.css("position"))&&
d.browser.opera){b._revertToRelativePosition=true;j.css({position:"absolute",top:"auto",left:"auto"})}j.css(p)})};typeof a.alsoResize=="object"&&!a.alsoResize.nodeType?d.each(a.alsoResize,function(h,i){f(h,i)}):f(a.alsoResize)},stop:function(){var b=d(this).data("resizable");if(b._revertToRelativePosition&&d.browser.opera){b._revertToRelativePosition=false;el.css({position:"relative"})}d(this).removeData("resizable-alsoresize-start")}});d.ui.plugin.add("resizable","animate",{stop:function(b){var a=
d(this).data("resizable"),c=a.options,e=a._proportionallyResizeElements,g=e.length&&/textarea/i.test(e[0].nodeName),f=g&&d.ui.hasScroll(e[0],"left")?0:a.sizeDiff.height;g={width:a.size.width-(g?0:a.sizeDiff.width),height:a.size.height-f};f=parseInt(a.element.css("left"),10)+(a.position.left-a.originalPosition.left)||null;var h=parseInt(a.element.css("top"),10)+(a.position.top-a.originalPosition.top)||null;a.element.animate(d.extend(g,h&&f?{top:h,left:f}:{}),{duration:c.animateDuration,easing:c.animateEasing,
step:function(){var i={width:parseInt(a.element.css("width"),10),height:parseInt(a.element.css("height"),10),top:parseInt(a.element.css("top"),10),left:parseInt(a.element.css("left"),10)};e&&e.length&&d(e[0]).css({width:i.width,height:i.height});a._updateCache(i);a._propagate("resize",b)}})}});d.ui.plugin.add("resizable","containment",{start:function(){var b=d(this).data("resizable"),a=b.element,c=b.options.containment;if(a=c instanceof d?c.get(0):/parent/.test(c)?a.parent().get(0):c){b.containerElement=
d(a);if(/document/.test(c)||c==document){b.containerOffset={left:0,top:0};b.containerPosition={left:0,top:0};b.parentData={element:d(document),left:0,top:0,width:d(document).width(),height:d(document).height()||document.body.parentNode.scrollHeight}}else{var e=d(a),g=[];d(["Top","Right","Left","Bottom"]).each(function(i,j){g[i]=m(e.css("padding"+j))});b.containerOffset=e.offset();b.containerPosition=e.position();b.containerSize={height:e.innerHeight()-g[3],width:e.innerWidth()-g[1]};c=b.containerOffset;
var f=b.containerSize.height,h=b.containerSize.width;h=d.ui.hasScroll(a,"left")?a.scrollWidth:h;f=d.ui.hasScroll(a)?a.scrollHeight:f;b.parentData={element:a,left:c.left,top:c.top,width:h,height:f}}}},resize:function(b){var a=d(this).data("resizable"),c=a.options,e=a.containerOffset,g=a.position;b=a._aspectRatio||b.shiftKey;var f={top:0,left:0},h=a.containerElement;if(h[0]!=document&&/static/.test(h.css("position")))f=e;if(g.left<(a._helper?e.left:0)){a.size.width+=a._helper?a.position.left-e.left:
a.position.left-f.left;if(b)a.size.height=a.size.width/c.aspectRatio;a.position.left=c.helper?e.left:0}if(g.top<(a._helper?e.top:0)){a.size.height+=a._helper?a.position.top-e.top:a.position.top;if(b)a.size.width=a.size.height*c.aspectRatio;a.position.top=a._helper?e.top:0}a.offset.left=a.parentData.left+a.position.left;a.offset.top=a.parentData.top+a.position.top;c=Math.abs((a._helper?a.offset.left-f.left:a.offset.left-f.left)+a.sizeDiff.width);e=Math.abs((a._helper?a.offset.top-f.top:a.offset.top-
e.top)+a.sizeDiff.height);g=a.containerElement.get(0)==a.element.parent().get(0);f=/relative|absolute/.test(a.containerElement.css("position"));if(g&&f)c-=a.parentData.left;if(c+a.size.width>=a.parentData.width){a.size.width=a.parentData.width-c;if(b)a.size.height=a.size.width/a.aspectRatio}if(e+a.size.height>=a.parentData.height){a.size.height=a.parentData.height-e;if(b)a.size.width=a.size.height*a.aspectRatio}},stop:function(){var b=d(this).data("resizable"),a=b.options,c=b.containerOffset,e=b.containerPosition,
g=b.containerElement,f=d(b.helper),h=f.offset(),i=f.outerWidth()-b.sizeDiff.width;f=f.outerHeight()-b.sizeDiff.height;b._helper&&!a.animate&&/relative/.test(g.css("position"))&&d(this).css({left:h.left-e.left-c.left,width:i,height:f});b._helper&&!a.animate&&/static/.test(g.css("position"))&&d(this).css({left:h.left-e.left-c.left,width:i,height:f})}});d.ui.plugin.add("resizable","ghost",{start:function(){var b=d(this).data("resizable"),a=b.options,c=b.size;b.ghost=b.originalElement.clone();b.ghost.css({opacity:0.25,
display:"block",position:"relative",height:c.height,width:c.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof a.ghost=="string"?a.ghost:"");b.ghost.appendTo(b.helper)},resize:function(){var b=d(this).data("resizable");b.ghost&&b.ghost.css({position:"relative",height:b.size.height,width:b.size.width})},stop:function(){var b=d(this).data("resizable");b.ghost&&b.helper&&b.helper.get(0).removeChild(b.ghost.get(0))}});d.ui.plugin.add("resizable","grid",{resize:function(){var b=
d(this).data("resizable"),a=b.options,c=b.size,e=b.originalSize,g=b.originalPosition,f=b.axis;a.grid=typeof a.grid=="number"?[a.grid,a.grid]:a.grid;var h=Math.round((c.width-e.width)/(a.grid[0]||1))*(a.grid[0]||1);a=Math.round((c.height-e.height)/(a.grid[1]||1))*(a.grid[1]||1);if(/^(se|s|e)$/.test(f)){b.size.width=e.width+h;b.size.height=e.height+a}else if(/^(ne)$/.test(f)){b.size.width=e.width+h;b.size.height=e.height+a;b.position.top=g.top-a}else{if(/^(sw)$/.test(f)){b.size.width=e.width+h;b.size.height=
e.height+a}else{b.size.width=e.width+h;b.size.height=e.height+a;b.position.top=g.top-a}b.position.left=g.left-h}}});var m=function(b){return parseInt(b,10)||0},k=function(b){return!isNaN(parseInt(b,10))}})(jQuery);
;
/*
 * jQuery UI Selectable 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Selectables
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.mouse.js
 *	jquery.ui.widget.js
 */
(function($) {

$.widget("ui.selectable", $.ui.mouse, {
	options: {
		appendTo: 'body',
		autoRefresh: true,
		distance: 0,
		filter: '*',
		tolerance: 'touch'
	},
	_create: function() {
		var self = this;

		this.element.addClass("ui-selectable");

		this.dragged = false;

		// cache selectee children based on filter
		var selectees;
		this.refresh = function() {
			selectees = $(self.options.filter, self.element[0]);
			selectees.each(function() {
				var $this = $(this);
				var pos = $this.offset();
				$.data(this, "selectable-item", {
					element: this,
					$element: $this,
					left: pos.left,
					top: pos.top,
					right: pos.left + $this.outerWidth(),
					bottom: pos.top + $this.outerHeight(),
					startselected: false,
					selected: $this.hasClass('ui-selected'),
					selecting: $this.hasClass('ui-selecting'),
					unselecting: $this.hasClass('ui-unselecting')
				});
			});
		};
		this.refresh();

		this.selectees = selectees.addClass("ui-selectee");

		this._mouseInit();

		this.helper = $("<div class='ui-selectable-helper'></div>");
	},

	destroy: function() {
		this.selectees
			.removeClass("ui-selectee")
			.removeData("selectable-item");
		this.element
			.removeClass("ui-selectable ui-selectable-disabled")
			.removeData("selectable")
			.unbind(".selectable");
		this._mouseDestroy();

		return this;
	},

	_mouseStart: function(event) {
		var self = this;

		this.opos = [event.pageX, event.pageY];

		if (this.options.disabled)
			return;

		var options = this.options;

		this.selectees = $(options.filter, this.element[0]);

		this._trigger("start", event);

		$(options.appendTo).append(this.helper);
		// position helper (lasso)
		this.helper.css({
			"z-index": 100,
			"position": "absolute",
			"left": event.clientX,
			"top": event.clientY,
			"width": 0,
			"height": 0
		});

		if (options.autoRefresh) {
			this.refresh();
		}

		this.selectees.filter('.ui-selected').each(function() {
			var selectee = $.data(this, "selectable-item");
			selectee.startselected = true;
			if (!event.metaKey) {
				selectee.$element.removeClass('ui-selected');
				selectee.selected = false;
				selectee.$element.addClass('ui-unselecting');
				selectee.unselecting = true;
				// selectable UNSELECTING callback
				self._trigger("unselecting", event, {
					unselecting: selectee.element
				});
			}
		});

		$(event.target).parents().andSelf().each(function() {
			var selectee = $.data(this, "selectable-item");
			if (selectee) {
				var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected');
				selectee.$element
					.removeClass(doSelect ? "ui-unselecting" : "ui-selected")
					.addClass(doSelect ? "ui-selecting" : "ui-unselecting");
				selectee.unselecting = !doSelect;
				selectee.selecting = doSelect;
				selectee.selected = doSelect;
				// selectable (UN)SELECTING callback
				if (doSelect) {
					self._trigger("selecting", event, {
						selecting: selectee.element
					});
				} else {
					self._trigger("unselecting", event, {
						unselecting: selectee.element
					});
				}
				return false;
			}
		});

	},

	_mouseDrag: function(event) {
		var self = this;
		this.dragged = true;

		if (this.options.disabled)
			return;

		var options = this.options;

		var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
		if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
		if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
		this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});

		this.selectees.each(function() {
			var selectee = $.data(this, "selectable-item");
			//prevent helper from being selected if appendTo: selectable
			if (!selectee || selectee.element == self.element[0])
				return;
			var hit = false;
			if (options.tolerance == 'touch') {
				hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
			} else if (options.tolerance == 'fit') {
				hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
			}

			if (hit) {
				// SELECT
				if (selectee.selected) {
					selectee.$element.removeClass('ui-selected');
					selectee.selected = false;
				}
				if (selectee.unselecting) {
					selectee.$element.removeClass('ui-unselecting');
					selectee.unselecting = false;
				}
				if (!selectee.selecting) {
					selectee.$element.addClass('ui-selecting');
					selectee.selecting = true;
					// selectable SELECTING callback
					self._trigger("selecting", event, {
						selecting: selectee.element
					});
				}
			} else {
				// UNSELECT
				if (selectee.selecting) {
					if (event.metaKey && selectee.startselected) {
						selectee.$element.removeClass('ui-selecting');
						selectee.selecting = false;
						selectee.$element.addClass('ui-selected');
						selectee.selected = true;
					} else {
						selectee.$element.removeClass('ui-selecting');
						selectee.selecting = false;
						if (selectee.startselected) {
							selectee.$element.addClass('ui-unselecting');
							selectee.unselecting = true;
						}
						// selectable UNSELECTING callback
						self._trigger("unselecting", event, {
							unselecting: selectee.element
						});
					}
				}
				if (selectee.selected) {
					if (!event.metaKey && !selectee.startselected) {
						selectee.$element.removeClass('ui-selected');
						selectee.selected = false;

						selectee.$element.addClass('ui-unselecting');
						selectee.unselecting = true;
						// selectable UNSELECTING callback
						self._trigger("unselecting", event, {
							unselecting: selectee.element
						});
					}
				}
			}
		});

		return false;
	},

	_mouseStop: function(event) {
		var self = this;

		this.dragged = false;

		var options = this.options;

		$('.ui-unselecting', this.element[0]).each(function() {
			var selectee = $.data(this, "selectable-item");
			selectee.$element.removeClass('ui-unselecting');
			selectee.unselecting = false;
			selectee.startselected = false;
			self._trigger("unselected", event, {
				unselected: selectee.element
			});
		});
		$('.ui-selecting', this.element[0]).each(function() {
			var selectee = $.data(this, "selectable-item");
			selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
			selectee.selecting = false;
			selectee.selected = true;
			selectee.startselected = true;
			self._trigger("selected", event, {
				selected: selectee.element
			});
		});
		this._trigger("stop", event);

		this.helper.remove();

		return false;
	}

});

$.extend($.ui.selectable, {
	version: "1.8.2"
});

})(jQuery);
(function(e){e.widget("ui.selectable",e.ui.mouse,{options:{appendTo:"body",autoRefresh:true,distance:0,filter:"*",tolerance:"touch"},_create:function(){var c=this;this.element.addClass("ui-selectable");this.dragged=false;var f;this.refresh=function(){f=e(c.options.filter,c.element[0]);f.each(function(){var d=e(this),b=d.offset();e.data(this,"selectable-item",{element:this,$element:d,left:b.left,top:b.top,right:b.left+d.outerWidth(),bottom:b.top+d.outerHeight(),startselected:false,selected:d.hasClass("ui-selected"),
selecting:d.hasClass("ui-selecting"),unselecting:d.hasClass("ui-unselecting")})})};this.refresh();this.selectees=f.addClass("ui-selectee");this._mouseInit();this.helper=e("<div class='ui-selectable-helper'></div>")},destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item");this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable");this._mouseDestroy();return this},_mouseStart:function(c){var f=this;this.opos=[c.pageX,
c.pageY];if(!this.options.disabled){var d=this.options;this.selectees=e(d.filter,this.element[0]);this._trigger("start",c);e(d.appendTo).append(this.helper);this.helper.css({"z-index":100,position:"absolute",left:c.clientX,top:c.clientY,width:0,height:0});d.autoRefresh&&this.refresh();this.selectees.filter(".ui-selected").each(function(){var b=e.data(this,"selectable-item");b.startselected=true;if(!c.metaKey){b.$element.removeClass("ui-selected");b.selected=false;b.$element.addClass("ui-unselecting");
b.unselecting=true;f._trigger("unselecting",c,{unselecting:b.element})}});e(c.target).parents().andSelf().each(function(){var b=e.data(this,"selectable-item");if(b){var g=!c.metaKey||!b.$element.hasClass("ui-selected");b.$element.removeClass(g?"ui-unselecting":"ui-selected").addClass(g?"ui-selecting":"ui-unselecting");b.unselecting=!g;b.selecting=g;(b.selected=g)?f._trigger("selecting",c,{selecting:b.element}):f._trigger("unselecting",c,{unselecting:b.element});return false}})}},_mouseDrag:function(c){var f=
this;this.dragged=true;if(!this.options.disabled){var d=this.options,b=this.opos[0],g=this.opos[1],h=c.pageX,i=c.pageY;if(b>h){var j=h;h=b;b=j}if(g>i){j=i;i=g;g=j}this.helper.css({left:b,top:g,width:h-b,height:i-g});this.selectees.each(function(){var a=e.data(this,"selectable-item");if(!(!a||a.element==f.element[0])){var k=false;if(d.tolerance=="touch")k=!(a.left>h||a.right<b||a.top>i||a.bottom<g);else if(d.tolerance=="fit")k=a.left>b&&a.right<h&&a.top>g&&a.bottom<i;if(k){if(a.selected){a.$element.removeClass("ui-selected");
a.selected=false}if(a.unselecting){a.$element.removeClass("ui-unselecting");a.unselecting=false}if(!a.selecting){a.$element.addClass("ui-selecting");a.selecting=true;f._trigger("selecting",c,{selecting:a.element})}}else{if(a.selecting)if(c.metaKey&&a.startselected){a.$element.removeClass("ui-selecting");a.selecting=false;a.$element.addClass("ui-selected");a.selected=true}else{a.$element.removeClass("ui-selecting");a.selecting=false;if(a.startselected){a.$element.addClass("ui-unselecting");a.unselecting=
true}f._trigger("unselecting",c,{unselecting:a.element})}if(a.selected)if(!c.metaKey&&!a.startselected){a.$element.removeClass("ui-selected");a.selected=false;a.$element.addClass("ui-unselecting");a.unselecting=true;f._trigger("unselecting",c,{unselecting:a.element})}}}});return false}},_mouseStop:function(c){var f=this;this.dragged=false;e(".ui-unselecting",this.element[0]).each(function(){var d=e.data(this,"selectable-item");d.$element.removeClass("ui-unselecting");d.unselecting=false;d.startselected=
false;f._trigger("unselected",c,{unselected:d.element})});e(".ui-selecting",this.element[0]).each(function(){var d=e.data(this,"selectable-item");d.$element.removeClass("ui-selecting").addClass("ui-selected");d.selecting=false;d.selected=true;d.startselected=true;f._trigger("selected",c,{selected:d.element})});this._trigger("stop",c);this.helper.remove();return false}});e.extend(e.ui.selectable,{version:"1.8.2"})})(jQuery);
;/*
 * jQuery UI Sortable 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Sortables
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.mouse.js
 *	jquery.ui.widget.js
 */
(function(d){d.widget("ui.sortable",d.ui.mouse,{widgetEventPrefix:"sort",options:{appendTo:"parent",axis:false,connectWith:false,containment:false,cursor:"auto",cursorAt:false,dropOnEmpty:true,forcePlaceholderSize:false,forceHelperSize:false,grid:false,handle:false,helper:"original",items:"> *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1E3},_create:function(){this.containerCache={};this.element.addClass("ui-sortable");
this.refresh();this.floating=this.items.length?/left|right/.test(this.items[0].item.css("float")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var a=this.items.length-1;a>=0;a--)this.items[a].item.removeData("sortable-item");return this},_setOption:function(a,b){if(a==="disabled"){this.options[a]=b;this.widget()[b?"addClass":"removeClass"]("ui-sortable-disabled")}else d.Widget.prototype._setOption.apply(this,
arguments)},_mouseCapture:function(a,b){if(this.reverting)return false;if(this.options.disabled||this.options.type=="static")return false;this._refreshItems(a);var c=null,e=this;d(a.target).parents().each(function(){if(d.data(this,"sortable-item")==e){c=d(this);return false}});if(d.data(a.target,"sortable-item")==e)c=d(a.target);if(!c)return false;if(this.options.handle&&!b){var f=false;d(this.options.handle,c).find("*").andSelf().each(function(){if(this==a.target)f=true});if(!f)return false}this.currentItem=
c;this._removeCurrentsFromItems();return true},_mouseStart:function(a,b,c){b=this.options;var e=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(a);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");d.extend(this.offset,
{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};this.helper[0]!=this.currentItem[0]&&this.currentItem.hide();this._createPlaceholder();b.containment&&this._setContainment();
if(b.cursor){if(d("body").css("cursor"))this._storedCursor=d("body").css("cursor");d("body").css("cursor",b.cursor)}if(b.opacity){if(this.helper.css("opacity"))this._storedOpacity=this.helper.css("opacity");this.helper.css("opacity",b.opacity)}if(b.zIndex){if(this.helper.css("zIndex"))this._storedZIndex=this.helper.css("zIndex");this.helper.css("zIndex",b.zIndex)}if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML")this.overflowOffset=this.scrollParent.offset();this._trigger("start",
a,this._uiHash());this._preserveHelperProportions||this._cacheHelperProportions();if(!c)for(c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("activate",a,e._uiHash(this));if(d.ui.ddmanager)d.ui.ddmanager.current=this;d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(a);return true},_mouseDrag:function(a){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");
if(!this.lastPositionAbs)this.lastPositionAbs=this.positionAbs;if(this.options.scroll){var b=this.options,c=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if(this.overflowOffset.top+this.scrollParent[0].offsetHeight-a.pageY<b.scrollSensitivity)this.scrollParent[0].scrollTop=c=this.scrollParent[0].scrollTop+b.scrollSpeed;else if(a.pageY-this.overflowOffset.top<b.scrollSensitivity)this.scrollParent[0].scrollTop=c=this.scrollParent[0].scrollTop-b.scrollSpeed;if(this.overflowOffset.left+
this.scrollParent[0].offsetWidth-a.pageX<b.scrollSensitivity)this.scrollParent[0].scrollLeft=c=this.scrollParent[0].scrollLeft+b.scrollSpeed;else if(a.pageX-this.overflowOffset.left<b.scrollSensitivity)this.scrollParent[0].scrollLeft=c=this.scrollParent[0].scrollLeft-b.scrollSpeed}else{if(a.pageY-d(document).scrollTop()<b.scrollSensitivity)c=d(document).scrollTop(d(document).scrollTop()-b.scrollSpeed);else if(d(window).height()-(a.pageY-d(document).scrollTop())<b.scrollSensitivity)c=d(document).scrollTop(d(document).scrollTop()+
b.scrollSpeed);if(a.pageX-d(document).scrollLeft()<b.scrollSensitivity)c=d(document).scrollLeft(d(document).scrollLeft()-b.scrollSpeed);else if(d(window).width()-(a.pageX-d(document).scrollLeft())<b.scrollSensitivity)c=d(document).scrollLeft(d(document).scrollLeft()+b.scrollSpeed)}c!==false&&d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a)}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+
"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";for(b=this.items.length-1;b>=0;b--){c=this.items[b];var e=c.item[0],f=this._intersectsWithPointer(c);if(f)if(e!=this.currentItem[0]&&this.placeholder[f==1?"next":"prev"]()[0]!=e&&!d.ui.contains(this.placeholder[0],e)&&(this.options.type=="semi-dynamic"?!d.ui.contains(this.element[0],e):true)){this.direction=f==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(c))this._rearrange(a,
c);else break;this._trigger("change",a,this._uiHash());break}}this._contactContainers(a);d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);this._trigger("sort",a,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(a,b){if(a){d.ui.ddmanager&&!this.options.dropBehaviour&&d.ui.ddmanager.drop(this,a);if(this.options.revert){var c=this;b=c.placeholder.offset();c.reverting=true;d(this.helper).animate({left:b.left-this.offset.parent.left-c.margins.left+(this.offsetParent[0]==
document.body?0:this.offsetParent[0].scrollLeft),top:b.top-this.offset.parent.top-c.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){c._clear(a)})}else this._clear(a,b);return false}},cancel:function(){var a=this;if(this.dragging){this._mouseUp();this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var b=this.containers.length-1;b>=0;b--){this.containers[b]._trigger("deactivate",
null,a._uiHash(this));if(this.containers[b].containerCache.over){this.containers[b]._trigger("out",null,a._uiHash(this));this.containers[b].containerCache.over=0}}}this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove();d.extend(this,{helper:null,dragging:false,reverting:false,_noFinalSort:null});this.domPosition.prev?d(this.domPosition.prev).after(this.currentItem):
d(this.domPosition.parent).prepend(this.currentItem);return this},serialize:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};d(b).each(function(){var e=(d(a.item||this).attr(a.attribute||"id")||"").match(a.expression||/(.+)[-=_](.+)/);if(e)c.push((a.key||e[1]+"[]")+"="+(a.key&&a.expression?e[1]:e[2]))});return c.join("&")},toArray:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};b.each(function(){c.push(d(a.item||this).attr(a.attribute||"id")||"")});return c},
_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,e=this.positionAbs.top,f=e+this.helperProportions.height,g=a.left,h=g+a.width,i=a.top,k=i+a.height,j=this.offset.click.top,l=this.offset.click.left;j=e+j>i&&e+j<k&&b+l>g&&b+l<h;return this.options.tolerance=="pointer"||this.options.forcePointerForContainers||this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>a[this.floating?"width":"height"]?j:g<b+this.helperProportions.width/
2&&c-this.helperProportions.width/2<h&&i<e+this.helperProportions.height/2&&f-this.helperProportions.height/2<k},_intersectsWithPointer:function(a){var b=d.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,a.top,a.height);a=d.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,a.left,a.width);b=b&&a;a=this._getDragVerticalDirection();var c=this._getDragHorizontalDirection();if(!b)return false;return this.floating?c&&c=="right"||a=="down"?2:1:a&&(a=="down"?2:1)},_intersectsWithSides:function(a){var b=
d.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,a.top+a.height/2,a.height);a=d.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,a.left+a.width/2,a.width);var c=this._getDragVerticalDirection(),e=this._getDragHorizontalDirection();return this.floating&&e?e=="right"&&a||e=="left"&&!a:c&&(c=="down"&&b||c=="up"&&!b)},_getDragVerticalDirection:function(){var a=this.positionAbs.top-this.lastPositionAbs.top;return a!=0&&(a>0?"down":"up")},_getDragHorizontalDirection:function(){var a=
this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){this._refreshItems(a);this.refreshPositions();return this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(a){var b=[],c=[],e=this._connectWith();if(e&&a)for(a=e.length-1;a>=0;a--)for(var f=d(e[a]),g=f.length-1;g>=0;g--){var h=d.data(f[g],"sortable");if(h&&h!=this&&!h.options.disabled)c.push([d.isFunction(h.options.items)?
h.options.items.call(h.element):d(h.options.items,h.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),h])}c.push([d.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):d(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(a=c.length-1;a>=0;a--)c[a][0].each(function(){b.push(this)});return d(b)},_removeCurrentsFromItems:function(){for(var a=this.currentItem.find(":data(sortable-item)"),
b=0;b<this.items.length;b++)for(var c=0;c<a.length;c++)a[c]==this.items[b].item[0]&&this.items.splice(b,1)},_refreshItems:function(a){this.items=[];this.containers=[this];var b=this.items,c=[[d.isFunction(this.options.items)?this.options.items.call(this.element[0],a,{item:this.currentItem}):d(this.options.items,this.element),this]],e=this._connectWith();if(e)for(var f=e.length-1;f>=0;f--)for(var g=d(e[f]),h=g.length-1;h>=0;h--){var i=d.data(g[h],"sortable");if(i&&i!=this&&!i.options.disabled){c.push([d.isFunction(i.options.items)?
i.options.items.call(i.element[0],a,{item:this.currentItem}):d(i.options.items,i.element),i]);this.containers.push(i)}}for(f=c.length-1;f>=0;f--){a=c[f][1];e=c[f][0];h=0;for(g=e.length;h<g;h++){i=d(e[h]);i.data("sortable-item",a);b.push({item:i,instance:a,width:0,height:0,left:0,top:0})}}},refreshPositions:function(a){if(this.offsetParent&&this.helper)this.offset.parent=this._getParentOffset();for(var b=this.items.length-1;b>=0;b--){var c=this.items[b],e=this.options.toleranceElement?d(this.options.toleranceElement,
c.item):c.item;if(!a){c.width=e.outerWidth();c.height=e.outerHeight()}e=e.offset();c.left=e.left;c.top=e.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(b=this.containers.length-1;b>=0;b--){e=this.containers[b].element.offset();this.containers[b].containerCache.left=e.left;this.containers[b].containerCache.top=e.top;this.containers[b].containerCache.width=this.containers[b].element.outerWidth();this.containers[b].containerCache.height=
this.containers[b].element.outerHeight()}return this},_createPlaceholder:function(a){var b=a||this,c=b.options;if(!c.placeholder||c.placeholder.constructor==String){var e=c.placeholder;c.placeholder={element:function(){var f=d(document.createElement(b.currentItem[0].nodeName)).addClass(e||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!e)f.style.visibility="hidden";return f},update:function(f,g){if(!(e&&!c.forcePlaceholderSize)){g.height()||g.height(b.currentItem.innerHeight()-
parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10));g.width()||g.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")||0,10))}}}}b.placeholder=d(c.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);c.placeholder.update(b,b.placeholder)},_contactContainers:function(a){for(var b=null,c=null,e=this.containers.length-1;e>=0;e--)if(!d.ui.contains(this.currentItem[0],
this.containers[e].element[0]))if(this._intersectsWith(this.containers[e].containerCache)){if(!(b&&d.ui.contains(this.containers[e].element[0],b.element[0]))){b=this.containers[e];c=e}}else if(this.containers[e].containerCache.over){this.containers[e]._trigger("out",a,this._uiHash(this));this.containers[e].containerCache.over=0}if(b)if(this.containers.length===1){this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}else if(this.currentContainer!=this.containers[c]){b=
1E4;e=null;for(var f=this.positionAbs[this.containers[c].floating?"left":"top"],g=this.items.length-1;g>=0;g--)if(d.ui.contains(this.containers[c].element[0],this.items[g].item[0])){var h=this.items[g][this.containers[c].floating?"left":"top"];if(Math.abs(h-f)<b){b=Math.abs(h-f);e=this.items[g]}}if(e||this.options.dropOnEmpty){this.currentContainer=this.containers[c];e?this._rearrange(a,e,null,true):this._rearrange(a,null,this.containers[c].element,true);this._trigger("change",a,this._uiHash());this.containers[c]._trigger("change",
a,this._uiHash(this));this.options.placeholder.update(this.currentContainer,this.placeholder);this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}}},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a,this.currentItem])):b.helper=="clone"?this.currentItem.clone():this.currentItem;a.parents("body").length||d(b.appendTo!="parent"?b.appendTo:this.currentItem[0].parentNode)[0].appendChild(a[0]);if(a[0]==
this.currentItem[0])this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")};if(a[0].style.width==""||b.forceHelperSize)a.width(this.currentItem.width());if(a[0].style.height==""||b.forceHelperSize)a.height(this.currentItem.height());return a},_adjustOffsetFromHelper:function(a){if(typeof a=="string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]||
0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],
this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.currentItem.position();return{top:a.top-
(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;
if(a.containment=="parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)){var b=
d(a.containment)[0];a=d(a.containment).offset();var c=d(b).css("overflow")!="hidden";this.containment=[a.left+(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0)-this.margins.left,a.top+(parseInt(d(b).css("borderTopWidth"),10)||0)+(parseInt(d(b).css("paddingTop"),10)||0)-this.margins.top,a.left+(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"),10)||0)-this.helperProportions.width-
this.margins.left,a.top+(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"),10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(c[0].tagName);return{top:b.top+
this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],
this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(c[0].tagName);if(this.cssPosition=="relative"&&!(this.scrollParent[0]!=document&&this.scrollParent[0]!=this.offsetParent[0]))this.offset.relative=this._getRelativeOffset();var f=a.pageX,g=a.pageY;if(this.originalPosition){if(this.containment){if(a.pageX-this.offset.click.left<this.containment[0])f=this.containment[0]+this.offset.click.left;if(a.pageY-this.offset.click.top<this.containment[1])g=this.containment[1]+this.offset.click.top;
if(a.pageX-this.offset.click.left>this.containment[2])f=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?g:!(g-this.offset.click.top<this.containment[1])?g-b.grid[1]:g+b.grid[1]:g;f=this.originalPageX+Math.round((f-
this.originalPageX)/b.grid[0])*b.grid[0];f=this.containment?!(f-this.offset.click.left<this.containment[0]||f-this.offset.click.left>this.containment[2])?f:!(f-this.offset.click.left<this.containment[0])?f-b.grid[0]:f+b.grid[0]:f}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(d.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:c.scrollTop()),left:f-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+
(d.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:c.scrollLeft())}},_rearrange:function(a,b,c,e){c?c[0].appendChild(this.placeholder[0]):b.item[0].parentNode.insertBefore(this.placeholder[0],this.direction=="down"?b.item[0]:b.item[0].nextSibling);this.counter=this.counter?++this.counter:1;var f=this,g=this.counter;window.setTimeout(function(){g==f.counter&&f.refreshPositions(!e)},0)},_clear:function(a,b){this.reverting=false;var c=[];!this._noFinalSort&&
this.currentItem[0].parentNode&&this.placeholder.before(this.currentItem);this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var e in this._storedCSS)if(this._storedCSS[e]=="auto"||this._storedCSS[e]=="static")this._storedCSS[e]="";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();this.fromOutside&&!b&&c.push(function(f){this._trigger("receive",f,this._uiHash(this.fromOutside))});if((this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||
this.domPosition.parent!=this.currentItem.parent()[0])&&!b)c.push(function(f){this._trigger("update",f,this._uiHash())});if(!d.ui.contains(this.element[0],this.currentItem[0])){b||c.push(function(f){this._trigger("remove",f,this._uiHash())});for(e=this.containers.length-1;e>=0;e--)if(d.ui.contains(this.containers[e].element[0],this.currentItem[0])&&!b){c.push(function(f){return function(g){f._trigger("receive",g,this._uiHash(this))}}.call(this,this.containers[e]));c.push(function(f){return function(g){f._trigger("update",
g,this._uiHash(this))}}.call(this,this.containers[e]))}}for(e=this.containers.length-1;e>=0;e--){b||c.push(function(f){return function(g){f._trigger("deactivate",g,this._uiHash(this))}}.call(this,this.containers[e]));if(this.containers[e].containerCache.over){c.push(function(f){return function(g){f._trigger("out",g,this._uiHash(this))}}.call(this,this.containers[e]));this.containers[e].containerCache.over=0}}this._storedCursor&&d("body").css("cursor",this._storedCursor);this._storedOpacity&&this.helper.css("opacity",
this._storedOpacity);if(this._storedZIndex)this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex);this.dragging=false;if(this.cancelHelperRemoval){if(!b){this._trigger("beforeStop",a,this._uiHash());for(e=0;e<c.length;e++)c[e].call(this,a);this._trigger("stop",a,this._uiHash())}return false}b||this._trigger("beforeStop",a,this._uiHash());this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.helper[0]!=this.currentItem[0]&&this.helper.remove();this.helper=null;if(!b){for(e=
0;e<c.length;e++)c[e].call(this,a);this._trigger("stop",a,this._uiHash())}this.fromOutside=false;return true},_trigger:function(){d.Widget.prototype._trigger.apply(this,arguments)===false&&this.cancel()},_uiHash:function(a){var b=a||this;return{helper:b.helper,placeholder:b.placeholder||d([]),position:b.position,originalPosition:b.originalPosition,offset:b.positionAbs,item:b.currentItem,sender:a?a.element:null}}});d.extend(d.ui.sortable,{version:"1.8.2"})})(jQuery);
;/*
 * jQuery UI Accordion 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Accordion
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 */
(function(c){c.widget("ui.accordion",{options:{active:0,animated:"slide",autoHeight:true,clearStyle:false,collapsible:false,event:"click",fillSpace:false,header:"> li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:false,navigationFilter:function(){return this.href.toLowerCase()==location.href.toLowerCase()}},_create:function(){var a=this.options,b=this;this.running=0;this.element.addClass("ui-accordion ui-widget ui-helper-reset");
this.element.children("li").addClass("ui-accordion-li-fix");this.headers=this.element.find(a.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){c(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){c(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){c(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){c(this).removeClass("ui-state-focus")});this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");
if(a.navigation){var d=this.element.find("a").filter(a.navigationFilter);if(d.length){var f=d.closest(".ui-accordion-header");this.active=f.length?f:d.closest(".ui-accordion-content").prev()}}this.active=this._findActive(this.active||a.active).toggleClass("ui-state-default").toggleClass("ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");this.active.next().addClass("ui-accordion-content-active");this._createIcons();this.resize();this.element.attr("role","tablist");this.headers.attr("role",
"tab").bind("keydown",function(g){return b._keydown(g)}).next().attr("role","tabpanel");this.headers.not(this.active||"").attr("aria-expanded","false").attr("tabIndex","-1").next().hide();this.active.length?this.active.attr("aria-expanded","true").attr("tabIndex","0"):this.headers.eq(0).attr("tabIndex","0");c.browser.safari||this.headers.find("a").attr("tabIndex","-1");a.event&&this.headers.bind(a.event+".accordion",function(g){b._clickHandler.call(b,g,this);g.preventDefault()})},_createIcons:function(){var a=
this.options;if(a.icons){c("<span/>").addClass("ui-icon "+a.icons.header).prependTo(this.headers);this.active.find(".ui-icon").toggleClass(a.icons.header).toggleClass(a.icons.headerSelected);this.element.addClass("ui-accordion-icons")}},_destroyIcons:function(){this.headers.children(".ui-icon").remove();this.element.removeClass("ui-accordion-icons")},destroy:function(){var a=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role").unbind(".accordion").removeData("accordion");
this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("tabIndex");this.headers.find("a").removeAttr("tabIndex");this._destroyIcons();var b=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active");if(a.autoHeight||a.fillHeight)b.css("height",
"");return this},_setOption:function(a,b){c.Widget.prototype._setOption.apply(this,arguments);a=="active"&&this.activate(b);if(a=="icons"){this._destroyIcons();b&&this._createIcons()}},_keydown:function(a){var b=c.ui.keyCode;if(!(this.options.disabled||a.altKey||a.ctrlKey)){var d=this.headers.length,f=this.headers.index(a.target),g=false;switch(a.keyCode){case b.RIGHT:case b.DOWN:g=this.headers[(f+1)%d];break;case b.LEFT:case b.UP:g=this.headers[(f-1+d)%d];break;case b.SPACE:case b.ENTER:this._clickHandler({target:a.target},
a.target);a.preventDefault()}if(g){c(a.target).attr("tabIndex","-1");c(g).attr("tabIndex","0");g.focus();return false}return true}},resize:function(){var a=this.options,b;if(a.fillSpace){if(c.browser.msie){var d=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}b=this.element.parent().height();c.browser.msie&&this.element.parent().css("overflow",d);this.headers.each(function(){b-=c(this).outerHeight(true)});this.headers.next().each(function(){c(this).height(Math.max(0,
b-c(this).innerHeight()+c(this).height()))}).css("overflow","auto")}else if(a.autoHeight){b=0;this.headers.next().each(function(){b=Math.max(b,c(this).height())}).height(b)}return this},activate:function(a){this.options.active=a;a=this._findActive(a)[0];this._clickHandler({target:a},a);return this},_findActive:function(a){return a?typeof a=="number"?this.headers.filter(":eq("+a+")"):this.headers.not(this.headers.not(a)):a===false?c([]):this.headers.filter(":eq(0)")},_clickHandler:function(a,b){var d=
this.options;if(!d.disabled)if(a.target){a=c(a.currentTarget||b);b=a[0]==this.active[0];d.active=d.collapsible&&b?false:c(".ui-accordion-header",this.element).index(a);if(!(this.running||!d.collapsible&&b)){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").find(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);if(!b){a.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").find(".ui-icon").removeClass(d.icons.header).addClass(d.icons.headerSelected);
a.next().addClass("ui-accordion-content-active")}e=a.next();f=this.active.next();g={options:d,newHeader:b&&d.collapsible?c([]):a,oldHeader:this.active,newContent:b&&d.collapsible?c([]):e,oldContent:f};d=this.headers.index(this.active[0])>this.headers.index(a[0]);this.active=b?c([]):a;this._toggle(e,f,g,b,d)}}else if(d.collapsible){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").find(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);
this.active.next().addClass("ui-accordion-content-active");var f=this.active.next(),g={options:d,newHeader:c([]),oldHeader:d.active,newContent:c([]),oldContent:f},e=this.active=c([]);this._toggle(e,f,g)}},_toggle:function(a,b,d,f,g){var e=this.options,k=this;this.toShow=a;this.toHide=b;this.data=d;var i=function(){if(k)return k._completed.apply(k,arguments)};this._trigger("changestart",null,this.data);this.running=b.size()===0?a.size():b.size();if(e.animated){d={};d=e.collapsible&&f?{toShow:c([]),
toHide:b,complete:i,down:g,autoHeight:e.autoHeight||e.fillSpace}:{toShow:a,toHide:b,complete:i,down:g,autoHeight:e.autoHeight||e.fillSpace};if(!e.proxied)e.proxied=e.animated;if(!e.proxiedDuration)e.proxiedDuration=e.duration;e.animated=c.isFunction(e.proxied)?e.proxied(d):e.proxied;e.duration=c.isFunction(e.proxiedDuration)?e.proxiedDuration(d):e.proxiedDuration;f=c.ui.accordion.animations;var h=e.duration,j=e.animated;if(j&&!f[j]&&!c.easing[j])j="slide";f[j]||(f[j]=function(l){this.slide(l,{easing:j,
duration:h||700})});f[j](d)}else{if(e.collapsible&&f)a.toggle();else{b.hide();a.show()}i(true)}b.prev().attr("aria-expanded","false").attr("tabIndex","-1").blur();a.prev().attr("aria-expanded","true").attr("tabIndex","0").focus()},_completed:function(a){var b=this.options;this.running=a?0:--this.running;if(!this.running){b.clearStyle&&this.toShow.add(this.toHide).css({height:"",overflow:""});this.toHide.removeClass("ui-accordion-content-active");this._trigger("change",null,this.data)}}});c.extend(c.ui.accordion,
{version:"1.8.2",animations:{slide:function(a,b){a=c.extend({easing:"swing",duration:300},a,b);if(a.toHide.size())if(a.toShow.size()){var d=a.toShow.css("overflow"),f=0,g={},e={},k;b=a.toShow;k=b[0].style.width;b.width(parseInt(b.parent().width(),10)-parseInt(b.css("paddingLeft"),10)-parseInt(b.css("paddingRight"),10)-(parseInt(b.css("borderLeftWidth"),10)||0)-(parseInt(b.css("borderRightWidth"),10)||0));c.each(["height","paddingTop","paddingBottom"],function(i,h){e[h]="hide";i=(""+c.css(a.toShow[0],
h)).match(/^([\d+-.]+)(.*)$/);g[h]={value:i[1],unit:i[2]||"px"}});a.toShow.css({height:0,overflow:"hidden"}).show();a.toHide.filter(":hidden").each(a.complete).end().filter(":visible").animate(e,{step:function(i,h){if(h.prop=="height")f=h.end-h.start===0?0:(h.now-h.start)/(h.end-h.start);a.toShow[0].style[h.prop]=f*g[h.prop].value+g[h.prop].unit},duration:a.duration,easing:a.easing,complete:function(){a.autoHeight||a.toShow.css("height","");a.toShow.css("width",k);a.toShow.css({overflow:d});a.complete()}})}else a.toHide.animate({height:"hide"},
a);else a.toShow.animate({height:"show"},a)},bounceslide:function(a){this.slide(a,{easing:a.down?"easeOutBounce":"swing",duration:a.down?1E3:200})}}})})(jQuery);
;/*
 * jQuery UI Autocomplete 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Autocomplete
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 *	jquery.ui.position.js
 */
(function(e){e.widget("ui.autocomplete",{options:{minLength:1,delay:300},_create:function(){var a=this,c=this.element[0].ownerDocument;this.element.addClass("ui-autocomplete-input").attr("autocomplete","off").attr({role:"textbox","aria-autocomplete":"list","aria-haspopup":"true"}).bind("keydown.autocomplete",function(d){var b=e.ui.keyCode;switch(d.keyCode){case b.PAGE_UP:a._move("previousPage",d);break;case b.PAGE_DOWN:a._move("nextPage",d);break;case b.UP:a._move("previous",d);d.preventDefault();
break;case b.DOWN:a._move("next",d);d.preventDefault();break;case b.ENTER:case b.NUMPAD_ENTER:a.menu.active&&d.preventDefault();case b.TAB:if(!a.menu.active)return;a.menu.select(d);break;case b.ESCAPE:a.element.val(a.term);a.close(d);break;case b.LEFT:case b.RIGHT:case b.SHIFT:case b.CONTROL:case b.ALT:case b.COMMAND:case b.COMMAND_RIGHT:case b.INSERT:case b.CAPS_LOCK:case b.END:case b.HOME:break;default:clearTimeout(a.searching);a.searching=setTimeout(function(){a.search(null,d)},a.options.delay);
break}}).bind("focus.autocomplete",function(){a.selectedItem=null;a.previous=a.element.val()}).bind("blur.autocomplete",function(d){clearTimeout(a.searching);a.closing=setTimeout(function(){a.close(d);a._change(d)},150)});this._initSource();this.response=function(){return a._response.apply(a,arguments)};this.menu=e("<ul></ul>").addClass("ui-autocomplete").appendTo("body",c).mousedown(function(){setTimeout(function(){clearTimeout(a.closing)},13)}).menu({focus:function(d,b){b=b.item.data("item.autocomplete");
false!==a._trigger("focus",null,{item:b})&&/^key/.test(d.originalEvent.type)&&a.element.val(b.value)},selected:function(d,b){b=b.item.data("item.autocomplete");false!==a._trigger("select",d,{item:b})&&a.element.val(b.value);a.close(d);d=a.previous;if(a.element[0]!==c.activeElement){a.element.focus();a.previous=d}a.selectedItem=b},blur:function(){a.menu.element.is(":visible")&&a.element.val(a.term)}}).zIndex(this.element.zIndex()+1).css({top:0,left:0}).hide().data("menu");e.fn.bgiframe&&this.menu.element.bgiframe()},
destroy:function(){this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete").removeAttr("role").removeAttr("aria-autocomplete").removeAttr("aria-haspopup");this.menu.element.remove();e.Widget.prototype.destroy.call(this)},_setOption:function(a){e.Widget.prototype._setOption.apply(this,arguments);a==="source"&&this._initSource()},_initSource:function(){var a,c;if(e.isArray(this.options.source)){a=this.options.source;this.source=function(d,b){b(e.ui.autocomplete.filter(a,d.term))}}else if(typeof this.options.source===
"string"){c=this.options.source;this.source=function(d,b){e.getJSON(c,d,b)}}else this.source=this.options.source},search:function(a,c){a=a!=null?a:this.element.val();if(a.length<this.options.minLength)return this.close(c);clearTimeout(this.closing);if(this._trigger("search")!==false)return this._search(a)},_search:function(a){this.term=this.element.addClass("ui-autocomplete-loading").val();this.source({term:a},this.response)},_response:function(a){if(a.length){a=this._normalize(a);this._suggest(a);
this._trigger("open")}else this.close();this.element.removeClass("ui-autocomplete-loading")},close:function(a){clearTimeout(this.closing);if(this.menu.element.is(":visible")){this._trigger("close",a);this.menu.element.hide();this.menu.deactivate()}},_change:function(a){this.previous!==this.element.val()&&this._trigger("change",a,{item:this.selectedItem})},_normalize:function(a){if(a.length&&a[0].label&&a[0].value)return a;return e.map(a,function(c){if(typeof c==="string")return{label:c,value:c};return e.extend({label:c.label||
c.value,value:c.value||c.label},c)})},_suggest:function(a){var c=this.menu.element.empty().zIndex(this.element.zIndex()+1),d;this._renderMenu(c,a);this.menu.deactivate();this.menu.refresh();this.menu.element.show().position({my:"left top",at:"left bottom",of:this.element,collision:"none"});a=c.width("").width();d=this.element.width();c.width(Math.max(a,d))},_renderMenu:function(a,c){var d=this;e.each(c,function(b,f){d._renderItem(a,f)})},_renderItem:function(a,c){return e("<li></li>").data("item.autocomplete",
c).append("<a>"+c.label+"</a>").appendTo(a)},_move:function(a,c){if(this.menu.element.is(":visible"))if(this.menu.first()&&/^previous/.test(a)||this.menu.last()&&/^next/.test(a)){this.element.val(this.term);this.menu.deactivate()}else this.menu[a](c);else this.search(null,c)},widget:function(){return this.menu.element}});e.extend(e.ui.autocomplete,{escapeRegex:function(a){return a.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi,"\\$1")},filter:function(a,c){var d=new RegExp(e.ui.autocomplete.escapeRegex(c),
"i");return e.grep(a,function(b){return d.test(b.label||b.value||b)})}})})(jQuery);
(function(e){e.widget("ui.menu",{_create:function(){var a=this;this.element.addClass("ui-menu ui-widget ui-widget-content ui-corner-all").attr({role:"listbox","aria-activedescendant":"ui-active-menuitem"}).click(function(c){if(e(c.target).closest(".ui-menu-item a").length){c.preventDefault();a.select(c)}});this.refresh()},refresh:function(){var a=this;this.element.children("li:not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","menuitem").children("a").addClass("ui-corner-all").attr("tabindex",
-1).mouseenter(function(c){a.activate(c,e(this).parent())}).mouseleave(function(){a.deactivate()})},activate:function(a,c){this.deactivate();if(this.hasScroll()){var d=c.offset().top-this.element.offset().top,b=this.element.attr("scrollTop"),f=this.element.height();if(d<0)this.element.attr("scrollTop",b+d);else d>f&&this.element.attr("scrollTop",b+d-f+c.height())}this.active=c.eq(0).children("a").addClass("ui-state-hover").attr("id","ui-active-menuitem").end();this._trigger("focus",a,{item:c})},deactivate:function(){if(this.active){this.active.children("a").removeClass("ui-state-hover").removeAttr("id");
this._trigger("blur");this.active=null}},next:function(a){this.move("next",".ui-menu-item:first",a)},previous:function(a){this.move("prev",".ui-menu-item:last",a)},first:function(){return this.active&&!this.active.prev().length},last:function(){return this.active&&!this.active.next().length},move:function(a,c,d){if(this.active){a=this.active[a+"All"](".ui-menu-item").eq(0);a.length?this.activate(d,a):this.activate(d,this.element.children(c))}else this.activate(d,this.element.children(c))},nextPage:function(a){if(this.hasScroll())if(!this.active||
this.last())this.activate(a,this.element.children(":first"));else{var c=this.active.offset().top,d=this.element.height(),b=this.element.children("li").filter(function(){var f=e(this).offset().top-c-d+e(this).height();return f<10&&f>-10});b.length||(b=this.element.children(":last"));this.activate(a,b)}else this.activate(a,this.element.children(!this.active||this.last()?":first":":last"))},previousPage:function(a){if(this.hasScroll())if(!this.active||this.first())this.activate(a,this.element.children(":last"));
else{var c=this.active.offset().top,d=this.element.height();result=this.element.children("li").filter(function(){var b=e(this).offset().top-c+d-e(this).height();return b<10&&b>-10});result.length||(result=this.element.children(":first"));this.activate(a,result)}else this.activate(a,this.element.children(!this.active||this.first()?":last":":first"))},hasScroll:function(){return this.element.height()<this.element.attr("scrollHeight")},select:function(a){this._trigger("selected",a,{item:this.active})}})})(jQuery);
;/*
 * jQuery UI Button 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Button
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 */
(function(a){var g,i=function(b){a(":ui-button",b.target.form).each(function(){var c=a(this).data("button");setTimeout(function(){c.refresh()},1)})},h=function(b){var c=b.name,d=b.form,e=a([]);if(c)e=d?a(d).find("[name='"+c+"']"):a("[name='"+c+"']",b.ownerDocument).filter(function(){return!this.form});return e};a.widget("ui.button",{options:{text:true,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset.button").bind("reset.button",i);this._determineButtonType();
this.hasTitle=!!this.buttonElement.attr("title");var b=this,c=this.options,d=this.type==="checkbox"||this.type==="radio",e="ui-state-hover"+(!d?" ui-state-active":"");if(c.label===null)c.label=this.buttonElement.html();if(this.element.is(":disabled"))c.disabled=true;this.buttonElement.addClass("ui-button ui-widget ui-state-default ui-corner-all").attr("role","button").bind("mouseenter.button",function(){if(!c.disabled){a(this).addClass("ui-state-hover");this===g&&a(this).addClass("ui-state-active")}}).bind("mouseleave.button",
function(){c.disabled||a(this).removeClass(e)}).bind("focus.button",function(){a(this).addClass("ui-state-focus")}).bind("blur.button",function(){a(this).removeClass("ui-state-focus")});d&&this.element.bind("change.button",function(){b.refresh()});if(this.type==="checkbox")this.buttonElement.bind("click.button",function(){if(c.disabled)return false;a(this).toggleClass("ui-state-active");b.buttonElement.attr("aria-pressed",b.element[0].checked)});else if(this.type==="radio")this.buttonElement.bind("click.button",
function(){if(c.disabled)return false;a(this).addClass("ui-state-active");b.buttonElement.attr("aria-pressed",true);var f=b.element[0];h(f).not(f).map(function(){return a(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed",false)});else{this.buttonElement.bind("mousedown.button",function(){if(c.disabled)return false;a(this).addClass("ui-state-active");g=this;a(document).one("mouseup",function(){g=null})}).bind("mouseup.button",function(){if(c.disabled)return false;a(this).removeClass("ui-state-active")}).bind("keydown.button",
function(f){if(c.disabled)return false;if(f.keyCode==a.ui.keyCode.SPACE||f.keyCode==a.ui.keyCode.ENTER)a(this).addClass("ui-state-active")}).bind("keyup.button",function(){a(this).removeClass("ui-state-active")});this.buttonElement.is("a")&&this.buttonElement.keyup(function(f){f.keyCode===a.ui.keyCode.SPACE&&a(this).click()})}this._setOption("disabled",c.disabled)},_determineButtonType:function(){this.type=this.element.is(":checkbox")?"checkbox":this.element.is(":radio")?"radio":this.element.is("input")?
"input":"button";if(this.type==="checkbox"||this.type==="radio"){this.buttonElement=this.element.parents().last().find("[for="+this.element.attr("id")+"]");this.element.addClass("ui-helper-hidden-accessible");var b=this.element.is(":checked");b&&this.buttonElement.addClass("ui-state-active");this.buttonElement.attr("aria-pressed",b)}else this.buttonElement=this.element},widget:function(){return this.buttonElement},destroy:function(){this.element.removeClass("ui-helper-hidden-accessible");this.buttonElement.removeClass("ui-button ui-widget ui-state-default ui-corner-all ui-state-hover ui-state-active  ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon ui-button-text-only").removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html());
this.hasTitle||this.buttonElement.removeAttr("title");a.Widget.prototype.destroy.call(this)},_setOption:function(b,c){a.Widget.prototype._setOption.apply(this,arguments);if(b==="disabled")c?this.element.attr("disabled",true):this.element.removeAttr("disabled");this._resetButton()},refresh:function(){var b=this.element.is(":disabled");b!==this.options.disabled&&this._setOption("disabled",b);if(this.type==="radio")h(this.element[0]).each(function(){a(this).is(":checked")?a(this).button("widget").addClass("ui-state-active").attr("aria-pressed",
true):a(this).button("widget").removeClass("ui-state-active").attr("aria-pressed",false)});else if(this.type==="checkbox")this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed",true):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed",false)},_resetButton:function(){if(this.type==="input")this.options.label&&this.element.val(this.options.label);else{var b=this.buttonElement.removeClass("ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon ui-button-text-only"),
c=a("<span></span>").addClass("ui-button-text").html(this.options.label).appendTo(b.empty()).text(),d=this.options.icons,e=d.primary&&d.secondary;if(d.primary||d.secondary){b.addClass("ui-button-text-icon"+(e?"s":""));d.primary&&b.prepend("<span class='ui-button-icon-primary ui-icon "+d.primary+"'></span>");d.secondary&&b.append("<span class='ui-button-icon-secondary ui-icon "+d.secondary+"'></span>");if(!this.options.text){b.addClass(e?"ui-button-icons-only":"ui-button-icon-only").removeClass("ui-button-text-icons ui-button-text-icon");
this.hasTitle||b.attr("title",c)}}else b.addClass("ui-button-text-only")}}});a.widget("ui.buttonset",{_create:function(){this.element.addClass("ui-buttonset");this._init()},_init:function(){this.refresh()},_setOption:function(b,c){b==="disabled"&&this.buttons.button("option",b,c);a.Widget.prototype._setOption.apply(this,arguments)},refresh:function(){this.buttons=this.element.find(":button, :submit, :reset, :checkbox, :radio, a, :data(button)").filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass("ui-corner-left").end().filter(":last").addClass("ui-corner-right").end().end()},
destroy:function(){this.element.removeClass("ui-buttonset");this.buttons.map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy");a.Widget.prototype.destroy.call(this)}})})(jQuery);
;/*
 * jQuery UI Dialog 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Dialog
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 *  jquery.ui.button.js
 *	jquery.ui.draggable.js
 *	jquery.ui.mouse.js
 *	jquery.ui.position.js
 *	jquery.ui.resizable.js
 */
(function(c){c.widget("ui.dialog",{options:{autoOpen:true,buttons:{},closeOnEscape:true,closeText:"close",dialogClass:"",draggable:true,hide:null,height:"auto",maxHeight:false,maxWidth:false,minHeight:150,minWidth:150,modal:false,position:"center",resizable:true,show:null,stack:true,title:"",width:300,zIndex:1E3},_create:function(){this.originalTitle=this.element.attr("title");var a=this,b=a.options,d=b.title||a.originalTitle||"&#160;",e=c.ui.dialog.getTitleId(a.element),g=(a.uiDialog=c("<div></div>")).appendTo(document.body).hide().addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+
b.dialogClass).css({zIndex:b.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(i){if(b.closeOnEscape&&i.keyCode&&i.keyCode===c.ui.keyCode.ESCAPE){a.close(i);i.preventDefault()}}).attr({role:"dialog","aria-labelledby":e}).mousedown(function(i){a.moveToTop(false,i)});a.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(g);var f=(a.uiDialogTitlebar=c("<div></div>")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(g),
h=c('<a href="#"></a>').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){h.addClass("ui-state-hover")},function(){h.removeClass("ui-state-hover")}).focus(function(){h.addClass("ui-state-focus")}).blur(function(){h.removeClass("ui-state-focus")}).click(function(i){a.close(i);return false}).appendTo(f);(a.uiDialogTitlebarCloseText=c("<span></span>")).addClass("ui-icon ui-icon-closethick").text(b.closeText).appendTo(h);c("<span></span>").addClass("ui-dialog-title").attr("id",
e).html(d).prependTo(f);if(c.isFunction(b.beforeclose)&&!c.isFunction(b.beforeClose))b.beforeClose=b.beforeclose;f.find("*").add(f).disableSelection();b.draggable&&c.fn.draggable&&a._makeDraggable();b.resizable&&c.fn.resizable&&a._makeResizable();a._createButtons(b.buttons);a._isOpen=false;c.fn.bgiframe&&g.bgiframe()},_init:function(){this.options.autoOpen&&this.open()},destroy:function(){var a=this;a.overlay&&a.overlay.destroy();a.uiDialog.hide();a.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body");
a.uiDialog.remove();a.originalTitle&&a.element.attr("title",a.originalTitle);return a},widget:function(){return this.uiDialog},close:function(a){var b=this,d;if(false!==b._trigger("beforeClose",a)){b.overlay&&b.overlay.destroy();b.uiDialog.unbind("keypress.ui-dialog");b._isOpen=false;if(b.options.hide)b.uiDialog.hide(b.options.hide,function(){b._trigger("close",a)});else{b.uiDialog.hide();b._trigger("close",a)}c.ui.dialog.overlay.resize();if(b.options.modal){d=0;c(".ui-dialog").each(function(){if(this!==
b.uiDialog[0])d=Math.max(d,c(this).css("z-index"))});c.ui.dialog.maxZ=d}return b}},isOpen:function(){return this._isOpen},moveToTop:function(a,b){var d=this,e=d.options;if(e.modal&&!a||!e.stack&&!e.modal)return d._trigger("focus",b);if(e.zIndex>c.ui.dialog.maxZ)c.ui.dialog.maxZ=e.zIndex;if(d.overlay){c.ui.dialog.maxZ+=1;d.overlay.$el.css("z-index",c.ui.dialog.overlay.maxZ=c.ui.dialog.maxZ)}a={scrollTop:d.element.attr("scrollTop"),scrollLeft:d.element.attr("scrollLeft")};c.ui.dialog.maxZ+=1;d.uiDialog.css("z-index",
c.ui.dialog.maxZ);d.element.attr(a);d._trigger("focus",b);return d},open:function(){if(!this._isOpen){var a=this,b=a.options,d=a.uiDialog;a.overlay=b.modal?new c.ui.dialog.overlay(a):null;d.next().length&&d.appendTo("body");a._size();a._position(b.position);d.show(b.show);a.moveToTop(true);b.modal&&d.bind("keypress.ui-dialog",function(e){if(e.keyCode===c.ui.keyCode.TAB){var g=c(":tabbable",this),f=g.filter(":first");g=g.filter(":last");if(e.target===g[0]&&!e.shiftKey){f.focus(1);return false}else if(e.target===
f[0]&&e.shiftKey){g.focus(1);return false}}});c([]).add(d.find(".ui-dialog-content :tabbable:first")).add(d.find(".ui-dialog-buttonpane :tabbable:first")).add(d).filter(":first").focus();a._trigger("open");a._isOpen=true;return a}},_createButtons:function(a){var b=this,d=false,e=c("<div></div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix");b.uiDialog.find(".ui-dialog-buttonpane").remove();typeof a==="object"&&a!==null&&c.each(a,function(){return!(d=true)});if(d){c.each(a,
function(g,f){g=c('<button type="button"></button>').text(g).click(function(){f.apply(b.element[0],arguments)}).appendTo(e);c.fn.button&&g.button()});e.appendTo(b.uiDialog)}},_makeDraggable:function(){function a(f){return{position:f.position,offset:f.offset}}var b=this,d=b.options,e=c(document),g;b.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(f,h){g=d.height==="auto"?"auto":c(this).height();c(this).height(c(this).height()).addClass("ui-dialog-dragging");
b._trigger("dragStart",f,a(h))},drag:function(f,h){b._trigger("drag",f,a(h))},stop:function(f,h){d.position=[h.position.left-e.scrollLeft(),h.position.top-e.scrollTop()];c(this).removeClass("ui-dialog-dragging").height(g);b._trigger("dragStop",f,a(h));c.ui.dialog.overlay.resize()}})},_makeResizable:function(a){function b(f){return{originalPosition:f.originalPosition,originalSize:f.originalSize,position:f.position,size:f.size}}a=a===undefined?this.options.resizable:a;var d=this,e=d.options,g=d.uiDialog.css("position");
a=typeof a==="string"?a:"n,e,s,w,se,sw,ne,nw";d.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:d.element,maxWidth:e.maxWidth,maxHeight:e.maxHeight,minWidth:e.minWidth,minHeight:d._minHeight(),handles:a,start:function(f,h){c(this).addClass("ui-dialog-resizing");d._trigger("resizeStart",f,b(h))},resize:function(f,h){d._trigger("resize",f,b(h))},stop:function(f,h){c(this).removeClass("ui-dialog-resizing");e.height=c(this).height();e.width=c(this).width();d._trigger("resizeStop",
f,b(h));c.ui.dialog.overlay.resize()}}).css("position",g).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var a=this.options;return a.height==="auto"?a.minHeight:Math.min(a.minHeight,a.height)},_position:function(a){var b=[],d=[0,0];a=a||c.ui.dialog.prototype.options.position;if(typeof a==="string"||typeof a==="object"&&"0"in a){b=a.split?a.split(" "):[a[0],a[1]];if(b.length===1)b[1]=b[0];c.each(["left","top"],function(e,g){if(+b[e]===b[e]){d[e]=b[e];b[e]=
g}})}else if(typeof a==="object"){if("left"in a){b[0]="left";d[0]=a.left}else if("right"in a){b[0]="right";d[0]=-a.right}if("top"in a){b[1]="top";d[1]=a.top}else if("bottom"in a){b[1]="bottom";d[1]=-a.bottom}}(a=this.uiDialog.is(":visible"))||this.uiDialog.show();this.uiDialog.css({top:0,left:0}).position({my:b.join(" "),at:b.join(" "),offset:d.join(" "),of:window,collision:"fit",using:function(e){var g=c(this).css(e).offset().top;g<0&&c(this).css("top",e.top-g)}});a||this.uiDialog.hide()},_setOption:function(a,
b){var d=this,e=d.uiDialog,g=e.is(":data(resizable)"),f=false;switch(a){case "beforeclose":a="beforeClose";break;case "buttons":d._createButtons(b);break;case "closeText":d.uiDialogTitlebarCloseText.text(""+b);break;case "dialogClass":e.removeClass(d.options.dialogClass).addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+b);break;case "disabled":b?e.addClass("ui-dialog-disabled"):e.removeClass("ui-dialog-disabled");break;case "draggable":b?d._makeDraggable():e.draggable("destroy");break;
case "height":f=true;break;case "maxHeight":g&&e.resizable("option","maxHeight",b);f=true;break;case "maxWidth":g&&e.resizable("option","maxWidth",b);f=true;break;case "minHeight":g&&e.resizable("option","minHeight",b);f=true;break;case "minWidth":g&&e.resizable("option","minWidth",b);f=true;break;case "position":d._position(b);break;case "resizable":g&&!b&&e.resizable("destroy");g&&typeof b==="string"&&e.resizable("option","handles",b);!g&&b!==false&&d._makeResizable(b);break;case "title":c(".ui-dialog-title",
d.uiDialogTitlebar).html(""+(b||"&#160;"));break;case "width":f=true;break}c.Widget.prototype._setOption.apply(d,arguments);f&&d._size()},_size:function(){var a=this.options,b;this.element.css({width:"auto",minHeight:0,height:0});b=this.uiDialog.css({height:"auto",width:a.width}).height();this.element.css(a.height==="auto"?{minHeight:Math.max(a.minHeight-b,0),height:"auto"}:{minHeight:0,height:Math.max(a.height-b,0)}).show();this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",
this._minHeight())}});c.extend(c.ui.dialog,{version:"1.8.2",uuid:0,maxZ:0,getTitleId:function(a){a=a.attr("id");if(!a){this.uuid+=1;a=this.uuid}return"ui-dialog-title-"+a},overlay:function(a){this.$el=c.ui.dialog.overlay.create(a)}});c.extend(c.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:c.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(a){return a+".dialog-overlay"}).join(" "),create:function(a){if(this.instances.length===0){setTimeout(function(){c.ui.dialog.overlay.instances.length&&
c(document).bind(c.ui.dialog.overlay.events,function(d){return c(d.target).zIndex()>=c.ui.dialog.overlay.maxZ})},1);c(document).bind("keydown.dialog-overlay",function(d){if(a.options.closeOnEscape&&d.keyCode&&d.keyCode===c.ui.keyCode.ESCAPE){a.close(d);d.preventDefault()}});c(window).bind("resize.dialog-overlay",c.ui.dialog.overlay.resize)}var b=(this.oldInstances.pop()||c("<div></div>").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),height:this.height()});c.fn.bgiframe&&
b.bgiframe();this.instances.push(b);return b},destroy:function(a){this.oldInstances.push(this.instances.splice(c.inArray(a,this.instances),1)[0]);this.instances.length===0&&c([document,window]).unbind(".dialog-overlay");a.remove();var b=0;c.each(this.instances,function(){b=Math.max(b,this.css("z-index"))});this.maxZ=b},height:function(){var a,b;if(c.browser.msie&&c.browser.version<7){a=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);b=Math.max(document.documentElement.offsetHeight,
document.body.offsetHeight);return a<b?c(window).height()+"px":a+"px"}else return c(document).height()+"px"},width:function(){var a,b;if(c.browser.msie&&c.browser.version<7){a=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth);b=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth);return a<b?c(window).width()+"px":a+"px"}else return c(document).width()+"px"},resize:function(){var a=c([]);c.each(c.ui.dialog.overlay.instances,function(){a=a.add(this)});a.css({width:0,
height:0}).css({width:c.ui.dialog.overlay.width(),height:c.ui.dialog.overlay.height()})}});c.extend(c.ui.dialog.overlay.prototype,{destroy:function(){c.ui.dialog.overlay.destroy(this.$el)}})})(jQuery);
;/*
 * jQuery UI Slider 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Slider
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.mouse.js
 *	jquery.ui.widget.js
 */
(function(d){d.widget("ui.slider",d.ui.mouse,{widgetEventPrefix:"slide",options:{animate:false,distance:0,max:100,min:0,orientation:"horizontal",range:false,step:1,value:0,values:null},_create:function(){var a=this,b=this.options;this._mouseSliding=this._keySliding=false;this._animateOff=true;this._handleIndex=null;this._detectOrientation();this._mouseInit();this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget ui-widget-content ui-corner-all");b.disabled&&this.element.addClass("ui-slider-disabled ui-disabled");
this.range=d([]);if(b.range){if(b.range===true){this.range=d("<div></div>");if(!b.values)b.values=[this._valueMin(),this._valueMin()];if(b.values.length&&b.values.length!==2)b.values=[b.values[0],b.values[0]]}else this.range=d("<div></div>");this.range.appendTo(this.element).addClass("ui-slider-range");if(b.range==="min"||b.range==="max")this.range.addClass("ui-slider-range-"+b.range);this.range.addClass("ui-widget-header")}d(".ui-slider-handle",this.element).length===0&&d("<a href='#'></a>").appendTo(this.element).addClass("ui-slider-handle");
if(b.values&&b.values.length)for(;d(".ui-slider-handle",this.element).length<b.values.length;)d("<a href='#'></a>").appendTo(this.element).addClass("ui-slider-handle");this.handles=d(".ui-slider-handle",this.element).addClass("ui-state-default ui-corner-all");this.handle=this.handles.eq(0);this.handles.add(this.range).filter("a").click(function(c){c.preventDefault()}).hover(function(){b.disabled||d(this).addClass("ui-state-hover")},function(){d(this).removeClass("ui-state-hover")}).focus(function(){if(b.disabled)d(this).blur();
else{d(".ui-slider .ui-state-focus").removeClass("ui-state-focus");d(this).addClass("ui-state-focus")}}).blur(function(){d(this).removeClass("ui-state-focus")});this.handles.each(function(c){d(this).data("index.ui-slider-handle",c)});this.handles.keydown(function(c){var e=true,f=d(this).data("index.ui-slider-handle"),g,h,i;if(!a.options.disabled){switch(c.keyCode){case d.ui.keyCode.HOME:case d.ui.keyCode.END:case d.ui.keyCode.PAGE_UP:case d.ui.keyCode.PAGE_DOWN:case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:e=
false;if(!a._keySliding){a._keySliding=true;d(this).addClass("ui-state-active");g=a._start(c,f);if(g===false)return}break}i=a.options.step;g=a.options.values&&a.options.values.length?(h=a.values(f)):(h=a.value());switch(c.keyCode){case d.ui.keyCode.HOME:h=a._valueMin();break;case d.ui.keyCode.END:h=a._valueMax();break;case d.ui.keyCode.PAGE_UP:h=a._trimAlignValue(g+(a._valueMax()-a._valueMin())/5);break;case d.ui.keyCode.PAGE_DOWN:h=a._trimAlignValue(g-(a._valueMax()-a._valueMin())/5);break;case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:if(g===
a._valueMax())return;h=a._trimAlignValue(g+i);break;case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:if(g===a._valueMin())return;h=a._trimAlignValue(g-i);break}a._slide(c,f,h);return e}}).keyup(function(c){var e=d(this).data("index.ui-slider-handle");if(a._keySliding){a._keySliding=false;a._stop(c,e);a._change(c,e);d(this).removeClass("ui-state-active")}});this._refreshValue();this._animateOff=false},destroy:function(){this.handles.remove();this.range.remove();this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all").removeData("slider").unbind(".slider");
this._mouseDestroy();return this},_mouseCapture:function(a){var b=this.options,c,e,f,g,h,i;if(b.disabled)return false;this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()};this.elementOffset=this.element.offset();c={x:a.pageX,y:a.pageY};e=this._normValueFromMouse(c);f=this._valueMax()-this._valueMin()+1;h=this;this.handles.each(function(j){var k=Math.abs(e-h.values(j));if(f>k){f=k;g=d(this);i=j}});if(b.range===true&&this.values(1)===b.min){i+=1;g=d(this.handles[i])}if(this._start(a,
i)===false)return false;this._mouseSliding=true;h._handleIndex=i;g.addClass("ui-state-active").focus();b=g.offset();this._clickOffset=!d(a.target).parents().andSelf().is(".ui-slider-handle")?{left:0,top:0}:{left:a.pageX-b.left-g.width()/2,top:a.pageY-b.top-g.height()/2-(parseInt(g.css("borderTopWidth"),10)||0)-(parseInt(g.css("borderBottomWidth"),10)||0)+(parseInt(g.css("marginTop"),10)||0)};e=this._normValueFromMouse(c);this._slide(a,i,e);return this._animateOff=true},_mouseStart:function(){return true},
_mouseDrag:function(a){var b=this._normValueFromMouse({x:a.pageX,y:a.pageY});this._slide(a,this._handleIndex,b);return false},_mouseStop:function(a){this.handles.removeClass("ui-state-active");this._mouseSliding=false;this._stop(a,this._handleIndex);this._change(a,this._handleIndex);this._clickOffset=this._handleIndex=null;return this._animateOff=false},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(a){var b;
if(this.orientation==="horizontal"){b=this.elementSize.width;a=a.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)}else{b=this.elementSize.height;a=a.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)}b=a/b;if(b>1)b=1;if(b<0)b=0;if(this.orientation==="vertical")b=1-b;a=this._valueMax()-this._valueMin();return this._trimAlignValue(this._valueMin()+b*a)},_start:function(a,b){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=
this.values(b);c.values=this.values()}return this._trigger("start",a,c)},_slide:function(a,b,c){var e;if(this.options.values&&this.options.values.length){e=this.values(b?0:1);if(this.options.values.length===2&&this.options.range===true&&(b===0&&c>e||b===1&&c<e))c=e;if(c!==this.values(b)){e=this.values();e[b]=c;a=this._trigger("slide",a,{handle:this.handles[b],value:c,values:e});this.values(b?0:1);a!==false&&this.values(b,c,true)}}else if(c!==this.value()){a=this._trigger("slide",a,{handle:this.handles[b],
value:c});a!==false&&this.value(c)}},_stop:function(a,b){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=this.values(b);c.values=this.values()}this._trigger("stop",a,c)},_change:function(a,b){if(!this._keySliding&&!this._mouseSliding){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=this.values(b);c.values=this.values()}this._trigger("change",a,c)}},value:function(a){if(arguments.length){this.options.value=
this._trimAlignValue(a);this._refreshValue();this._change(null,0)}return this._value()},values:function(a,b){var c,e,f;if(arguments.length>1){this.options.values[a]=this._trimAlignValue(b);this._refreshValue();this._change(null,a)}if(arguments.length)if(d.isArray(arguments[0])){c=this.options.values;e=arguments[0];for(f=0;f<c.length;f+=1){c[f]=this._trimAlignValue(e[f]);this._change(null,f)}this._refreshValue()}else return this.options.values&&this.options.values.length?this._values(a):this.value();
else return this._values()},_setOption:function(a,b){var c,e=0;if(d.isArray(this.options.values))e=this.options.values.length;d.Widget.prototype._setOption.apply(this,arguments);switch(a){case "disabled":if(b){this.handles.filter(".ui-state-focus").blur();this.handles.removeClass("ui-state-hover");this.handles.attr("disabled","disabled");this.element.addClass("ui-disabled")}else{this.handles.removeAttr("disabled");this.element.removeClass("ui-disabled")}break;case "orientation":this._detectOrientation();
this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation);this._refreshValue();break;case "value":this._animateOff=true;this._refreshValue();this._change(null,0);this._animateOff=false;break;case "values":this._animateOff=true;this._refreshValue();for(c=0;c<e;c+=1)this._change(null,c);this._animateOff=false;break}},_value:function(){var a=this.options.value;return a=this._trimAlignValue(a)},_values:function(a){var b,c;if(arguments.length){b=this.options.values[a];
return b=this._trimAlignValue(b)}else{b=this.options.values.slice();for(c=0;c<b.length;c+=1)b[c]=this._trimAlignValue(b[c]);return b}},_trimAlignValue:function(a){if(a<this._valueMin())return this._valueMin();if(a>this._valueMax())return this._valueMax();var b=this.options.step>0?this.options.step:1,c=a%b;a=a-c;if(Math.abs(c)*2>=b)a+=c>0?b:-b;return parseFloat(a.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var a=
this.options.range,b=this.options,c=this,e=!this._animateOff?b.animate:false,f,g={},h,i,j,k;if(this.options.values&&this.options.values.length)this.handles.each(function(l){f=(c.values(l)-c._valueMin())/(c._valueMax()-c._valueMin())*100;g[c.orientation==="horizontal"?"left":"bottom"]=f+"%";d(this).stop(1,1)[e?"animate":"css"](g,b.animate);if(c.options.range===true)if(c.orientation==="horizontal"){if(l===0)c.range.stop(1,1)[e?"animate":"css"]({left:f+"%"},b.animate);if(l===1)c.range[e?"animate":"css"]({width:f-
h+"%"},{queue:false,duration:b.animate})}else{if(l===0)c.range.stop(1,1)[e?"animate":"css"]({bottom:f+"%"},b.animate);if(l===1)c.range[e?"animate":"css"]({height:f-h+"%"},{queue:false,duration:b.animate})}h=f});else{i=this.value();j=this._valueMin();k=this._valueMax();f=k!==j?(i-j)/(k-j)*100:0;g[c.orientation==="horizontal"?"left":"bottom"]=f+"%";this.handle.stop(1,1)[e?"animate":"css"](g,b.animate);if(a==="min"&&this.orientation==="horizontal")this.range.stop(1,1)[e?"animate":"css"]({width:f+"%"},
b.animate);if(a==="max"&&this.orientation==="horizontal")this.range[e?"animate":"css"]({width:100-f+"%"},{queue:false,duration:b.animate});if(a==="min"&&this.orientation==="vertical")this.range.stop(1,1)[e?"animate":"css"]({height:f+"%"},b.animate);if(a==="max"&&this.orientation==="vertical")this.range[e?"animate":"css"]({height:100-f+"%"},{queue:false,duration:b.animate})}}});d.extend(d.ui.slider,{version:"1.8.2"})})(jQuery);
;/*
 * jQuery UI Tabs 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Tabs
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 */
(function(d){function s(){return++u}function v(){return++w}var u=0,w=0;d.widget("ui.tabs",{options:{add:null,ajaxOptions:null,cache:false,cookie:null,collapsible:false,disable:null,disabled:[],enable:null,event:"click",fx:null,idPrefix:"ui-tabs-",load:null,panelTemplate:"<div></div>",remove:null,select:null,show:null,spinner:"<em>Loading&#8230;</em>",tabTemplate:'<li><a href="#{href}"><span>#{label}</span></a></li>'},_create:function(){this._tabify(true)},_setOption:function(c,e){if(c=="selected")this.options.collapsible&&
e==this.options.selected||this.select(e);else{this.options[c]=e;this._tabify()}},_tabId:function(c){return c.title&&c.title.replace(/\s/g,"_").replace(/[^A-Za-z0-9\-_:\.]/g,"")||this.options.idPrefix+s()},_sanitizeSelector:function(c){return c.replace(/:/g,"\\:")},_cookie:function(){var c=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+v());return d.cookie.apply(null,[c].concat(d.makeArray(arguments)))},_ui:function(c,e){return{tab:c,panel:e,index:this.anchors.index(c)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var c=
d(this);c.html(c.data("label.tabs")).removeData("label.tabs")})},_tabify:function(c){function e(g,f){g.css({display:""});!d.support.opacity&&f.opacity&&g[0].style.removeAttribute("filter")}this.list=this.element.find("ol,ul").eq(0);this.lis=d("li:has(a[href])",this.list);this.anchors=this.lis.map(function(){return d("a",this)[0]});this.panels=d([]);var a=this,b=this.options,h=/^#.+/;this.anchors.each(function(g,f){var j=d(f).attr("href"),l=j.split("#")[0],p;if(l&&(l===location.toString().split("#")[0]||
(p=d("base")[0])&&l===p.href)){j=f.hash;f.href=j}if(h.test(j))a.panels=a.panels.add(a._sanitizeSelector(j));else if(j!="#"){d.data(f,"href.tabs",j);d.data(f,"load.tabs",j.replace(/#.*$/,""));j=a._tabId(f);f.href="#"+j;f=d("#"+j);if(!f.length){f=d(b.panelTemplate).attr("id",j).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(a.panels[g-1]||a.list);f.data("destroy.tabs",true)}a.panels=a.panels.add(f)}else b.disabled.push(g)});if(c){this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all");
this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.lis.addClass("ui-state-default ui-corner-top");this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom");if(b.selected===undefined){location.hash&&this.anchors.each(function(g,f){if(f.hash==location.hash){b.selected=g;return false}});if(typeof b.selected!="number"&&b.cookie)b.selected=parseInt(a._cookie(),10);if(typeof b.selected!="number"&&this.lis.filter(".ui-tabs-selected").length)b.selected=
this.lis.index(this.lis.filter(".ui-tabs-selected"));b.selected=b.selected||(this.lis.length?0:-1)}else if(b.selected===null)b.selected=-1;b.selected=b.selected>=0&&this.anchors[b.selected]||b.selected<0?b.selected:0;b.disabled=d.unique(b.disabled.concat(d.map(this.lis.filter(".ui-state-disabled"),function(g){return a.lis.index(g)}))).sort();d.inArray(b.selected,b.disabled)!=-1&&b.disabled.splice(d.inArray(b.selected,b.disabled),1);this.panels.addClass("ui-tabs-hide");this.lis.removeClass("ui-tabs-selected ui-state-active");
if(b.selected>=0&&this.anchors.length){this.panels.eq(b.selected).removeClass("ui-tabs-hide");this.lis.eq(b.selected).addClass("ui-tabs-selected ui-state-active");a.element.queue("tabs",function(){a._trigger("show",null,a._ui(a.anchors[b.selected],a.panels[b.selected]))});this.load(b.selected)}d(window).bind("unload",function(){a.lis.add(a.anchors).unbind(".tabs");a.lis=a.anchors=a.panels=null})}else b.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"));this.element[b.collapsible?"addClass":
"removeClass"]("ui-tabs-collapsible");b.cookie&&this._cookie(b.selected,b.cookie);c=0;for(var i;i=this.lis[c];c++)d(i)[d.inArray(c,b.disabled)!=-1&&!d(i).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled");b.cache===false&&this.anchors.removeData("cache.tabs");this.lis.add(this.anchors).unbind(".tabs");if(b.event!="mouseover"){var k=function(g,f){f.is(":not(.ui-state-disabled)")&&f.addClass("ui-state-"+g)},n=function(g,f){f.removeClass("ui-state-"+g)};this.lis.bind("mouseover.tabs",
function(){k("hover",d(this))});this.lis.bind("mouseout.tabs",function(){n("hover",d(this))});this.anchors.bind("focus.tabs",function(){k("focus",d(this).closest("li"))});this.anchors.bind("blur.tabs",function(){n("focus",d(this).closest("li"))})}var m,o;if(b.fx)if(d.isArray(b.fx)){m=b.fx[0];o=b.fx[1]}else m=o=b.fx;var q=o?function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.hide().removeClass("ui-tabs-hide").animate(o,o.duration||"normal",function(){e(f,o);a._trigger("show",
null,a._ui(g,f[0]))})}:function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.removeClass("ui-tabs-hide");a._trigger("show",null,a._ui(g,f[0]))},r=m?function(g,f){f.animate(m,m.duration||"normal",function(){a.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");e(f,m);a.element.dequeue("tabs")})}:function(g,f){a.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");a.element.dequeue("tabs")};this.anchors.bind(b.event+".tabs",
function(){var g=this,f=d(this).closest("li"),j=a.panels.filter(":not(.ui-tabs-hide)"),l=d(a._sanitizeSelector(this.hash));if(f.hasClass("ui-tabs-selected")&&!b.collapsible||f.hasClass("ui-state-disabled")||f.hasClass("ui-state-processing")||a._trigger("select",null,a._ui(this,l[0]))===false){this.blur();return false}b.selected=a.anchors.index(this);a.abort();if(b.collapsible)if(f.hasClass("ui-tabs-selected")){b.selected=-1;b.cookie&&a._cookie(b.selected,b.cookie);a.element.queue("tabs",function(){r(g,
j)}).dequeue("tabs");this.blur();return false}else if(!j.length){b.cookie&&a._cookie(b.selected,b.cookie);a.element.queue("tabs",function(){q(g,l)});a.load(a.anchors.index(this));this.blur();return false}b.cookie&&a._cookie(b.selected,b.cookie);if(l.length){j.length&&a.element.queue("tabs",function(){r(g,j)});a.element.queue("tabs",function(){q(g,l)});a.load(a.anchors.index(this))}else throw"jQuery UI Tabs: Mismatching fragment identifier.";d.browser.msie&&this.blur()});this.anchors.bind("click.tabs",
function(){return false})},destroy:function(){var c=this.options;this.abort();this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs");this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.anchors.each(function(){var e=d.data(this,"href.tabs");if(e)this.href=e;var a=d(this).unbind(".tabs");d.each(["href","load","cache"],function(b,h){a.removeData(h+".tabs")})});this.lis.unbind(".tabs").add(this.panels).each(function(){d.data(this,
"destroy.tabs")?d(this).remove():d(this).removeClass("ui-state-default ui-corner-top ui-tabs-selected ui-state-active ui-state-hover ui-state-focus ui-state-disabled ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide")});c.cookie&&this._cookie(null,c.cookie);return this},add:function(c,e,a){if(a===undefined)a=this.anchors.length;var b=this,h=this.options;e=d(h.tabTemplate.replace(/#\{href\}/g,c).replace(/#\{label\}/g,e));c=!c.indexOf("#")?c.replace("#",""):this._tabId(d("a",e)[0]);e.addClass("ui-state-default ui-corner-top").data("destroy.tabs",
true);var i=d("#"+c);i.length||(i=d(h.panelTemplate).attr("id",c).data("destroy.tabs",true));i.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide");if(a>=this.lis.length){e.appendTo(this.list);i.appendTo(this.list[0].parentNode)}else{e.insertBefore(this.lis[a]);i.insertBefore(this.panels[a])}h.disabled=d.map(h.disabled,function(k){return k>=a?++k:k});this._tabify();if(this.anchors.length==1){h.selected=0;e.addClass("ui-tabs-selected ui-state-active");i.removeClass("ui-tabs-hide");
this.element.queue("tabs",function(){b._trigger("show",null,b._ui(b.anchors[0],b.panels[0]))});this.load(0)}this._trigger("add",null,this._ui(this.anchors[a],this.panels[a]));return this},remove:function(c){var e=this.options,a=this.lis.eq(c).remove(),b=this.panels.eq(c).remove();if(a.hasClass("ui-tabs-selected")&&this.anchors.length>1)this.select(c+(c+1<this.anchors.length?1:-1));e.disabled=d.map(d.grep(e.disabled,function(h){return h!=c}),function(h){return h>=c?--h:h});this._tabify();this._trigger("remove",
null,this._ui(a.find("a")[0],b[0]));return this},enable:function(c){var e=this.options;if(d.inArray(c,e.disabled)!=-1){this.lis.eq(c).removeClass("ui-state-disabled");e.disabled=d.grep(e.disabled,function(a){return a!=c});this._trigger("enable",null,this._ui(this.anchors[c],this.panels[c]));return this}},disable:function(c){var e=this.options;if(c!=e.selected){this.lis.eq(c).addClass("ui-state-disabled");e.disabled.push(c);e.disabled.sort();this._trigger("disable",null,this._ui(this.anchors[c],this.panels[c]))}return this},
select:function(c){if(typeof c=="string")c=this.anchors.index(this.anchors.filter("[href$="+c+"]"));else if(c===null)c=-1;if(c==-1&&this.options.collapsible)c=this.options.selected;this.anchors.eq(c).trigger(this.options.event+".tabs");return this},load:function(c){var e=this,a=this.options,b=this.anchors.eq(c)[0],h=d.data(b,"load.tabs");this.abort();if(!h||this.element.queue("tabs").length!==0&&d.data(b,"cache.tabs"))this.element.dequeue("tabs");else{this.lis.eq(c).addClass("ui-state-processing");
if(a.spinner){var i=d("span",b);i.data("label.tabs",i.html()).html(a.spinner)}this.xhr=d.ajax(d.extend({},a.ajaxOptions,{url:h,success:function(k,n){d(e._sanitizeSelector(b.hash)).html(k);e._cleanup();a.cache&&d.data(b,"cache.tabs",true);e._trigger("load",null,e._ui(e.anchors[c],e.panels[c]));try{a.ajaxOptions.success(k,n)}catch(m){}},error:function(k,n){e._cleanup();e._trigger("load",null,e._ui(e.anchors[c],e.panels[c]));try{a.ajaxOptions.error(k,n,c,b)}catch(m){}}}));e.element.dequeue("tabs");return this}},
abort:function(){this.element.queue([]);this.panels.stop(false,true);this.element.queue("tabs",this.element.queue("tabs").splice(-2,2));if(this.xhr){this.xhr.abort();delete this.xhr}this._cleanup();return this},url:function(c,e){this.anchors.eq(c).removeData("cache.tabs").data("load.tabs",e);return this},length:function(){return this.anchors.length}});d.extend(d.ui.tabs,{version:"1.8.2"});d.extend(d.ui.tabs.prototype,{rotation:null,rotate:function(c,e){var a=this,b=this.options,h=a._rotate||(a._rotate=
function(i){clearTimeout(a.rotation);a.rotation=setTimeout(function(){var k=b.selected;a.select(++k<a.anchors.length?k:0)},c);i&&i.stopPropagation()});e=a._unrotate||(a._unrotate=!e?function(i){i.clientX&&a.rotate(null)}:function(){t=b.selected;h()});if(c){this.element.bind("tabsshow",h);this.anchors.bind(b.event+".tabs",e);h()}else{clearTimeout(a.rotation);this.element.unbind("tabsshow",h);this.anchors.unbind(b.event+".tabs",e);delete this._rotate;delete this._unrotate}return this}})})(jQuery);
;/*
 * jQuery UI Datepicker 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Datepicker
 *
 * Depends:
 *	jquery.ui.core.js
 */
(function(d){function J(){this.debug=false;this._curInst=null;this._keyEvent=false;this._disabledInputs=[];this._inDialog=this._datepickerShowing=false;this._mainDivId="ui-datepicker-div";this._inlineClass="ui-datepicker-inline";this._appendClass="ui-datepicker-append";this._triggerClass="ui-datepicker-trigger";this._dialogClass="ui-datepicker-dialog";this._disableClass="ui-datepicker-disabled";this._unselectableClass="ui-datepicker-unselectable";this._currentClass="ui-datepicker-current-day";this._dayOverClass=
"ui-datepicker-days-cell-over";this.regional=[];this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su",
"Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:false,showMonthAfterYear:false,yearSuffix:""};this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:false,hideIfNoPrevNext:false,navigationAsDateFormat:false,gotoCurrent:false,changeMonth:false,changeYear:false,yearRange:"c-10:c+10",showOtherMonths:false,selectOtherMonths:false,showWeek:false,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",
minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:true,showButtonPanel:false,autoSize:false};d.extend(this._defaults,this.regional[""]);this.dpDiv=d('<div id="'+this._mainDivId+'" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>')}function E(a,b){d.extend(a,
b);for(var c in b)if(b[c]==null||b[c]==undefined)a[c]=b[c];return a}d.extend(d.ui,{datepicker:{version:"1.8.2"}});var y=(new Date).getTime();d.extend(J.prototype,{markerClassName:"hasDatepicker",log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(a){E(this._defaults,a||{});return this},_attachDatepicker:function(a,b){var c=null;for(var e in this._defaults){var f=a.getAttribute("date:"+e);if(f){c=c||{};try{c[e]=eval(f)}catch(h){c[e]=
f}}}e=a.nodeName.toLowerCase();f=e=="div"||e=="span";if(!a.id){this.uuid+=1;a.id="dp"+this.uuid}var i=this._newInst(d(a),f);i.settings=d.extend({},b||{},c||{});if(e=="input")this._connectDatepicker(a,i);else f&&this._inlineDatepicker(a,i)},_newInst:function(a,b){return{id:a[0].id.replace(/([^A-Za-z0-9_])/g,"\\\\$1"),input:a,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:b,dpDiv:!b?this.dpDiv:d('<div class="'+this._inlineClass+' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')}},
_connectDatepicker:function(a,b){var c=d(a);b.append=d([]);b.trigger=d([]);if(!c.hasClass(this.markerClassName)){this._attachments(c,b);c.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});this._autoSize(b);d.data(a,"datepicker",b)}},_attachments:function(a,b){var c=this._get(b,"appendText"),e=this._get(b,"isRTL");b.append&&
b.append.remove();if(c){b.append=d('<span class="'+this._appendClass+'">'+c+"</span>");a[e?"before":"after"](b.append)}a.unbind("focus",this._showDatepicker);b.trigger&&b.trigger.remove();c=this._get(b,"showOn");if(c=="focus"||c=="both")a.focus(this._showDatepicker);if(c=="button"||c=="both"){c=this._get(b,"buttonText");var f=this._get(b,"buttonImage");b.trigger=d(this._get(b,"buttonImageOnly")?d("<img/>").addClass(this._triggerClass).attr({src:f,alt:c,title:c}):d('<button type="button"></button>').addClass(this._triggerClass).html(f==
""?c:d("<img/>").attr({src:f,alt:c,title:c})));a[e?"before":"after"](b.trigger);b.trigger.click(function(){d.datepicker._datepickerShowing&&d.datepicker._lastInput==a[0]?d.datepicker._hideDatepicker():d.datepicker._showDatepicker(a[0]);return false})}},_autoSize:function(a){if(this._get(a,"autoSize")&&!a.inline){var b=new Date(2009,11,20),c=this._get(a,"dateFormat");if(c.match(/[DM]/)){var e=function(f){for(var h=0,i=0,g=0;g<f.length;g++)if(f[g].length>h){h=f[g].length;i=g}return i};b.setMonth(e(this._get(a,
c.match(/MM/)?"monthNames":"monthNamesShort")));b.setDate(e(this._get(a,c.match(/DD/)?"dayNames":"dayNamesShort"))+20-b.getDay())}a.input.attr("size",this._formatDate(a,b).length)}},_inlineDatepicker:function(a,b){var c=d(a);if(!c.hasClass(this.markerClassName)){c.addClass(this.markerClassName).append(b.dpDiv).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});d.data(a,"datepicker",b);this._setDate(b,this._getDefaultDate(b),
true);this._updateDatepicker(b);this._updateAlternate(b)}},_dialogDatepicker:function(a,b,c,e,f){a=this._dialogInst;if(!a){this.uuid+=1;this._dialogInput=d('<input type="text" id="'+("dp"+this.uuid)+'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');this._dialogInput.keydown(this._doKeyDown);d("body").append(this._dialogInput);a=this._dialogInst=this._newInst(this._dialogInput,false);a.settings={};d.data(this._dialogInput[0],"datepicker",a)}E(a.settings,e||{});b=b&&b.constructor==
Date?this._formatDate(a,b):b;this._dialogInput.val(b);this._pos=f?f.length?f:[f.pageX,f.pageY]:null;if(!this._pos)this._pos=[document.documentElement.clientWidth/2-100+(document.documentElement.scrollLeft||document.body.scrollLeft),document.documentElement.clientHeight/2-150+(document.documentElement.scrollTop||document.body.scrollTop)];this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px");a.settings.onSelect=c;this._inDialog=true;this.dpDiv.addClass(this._dialogClass);this._showDatepicker(this._dialogInput[0]);
d.blockUI&&d.blockUI(this.dpDiv);d.data(this._dialogInput[0],"datepicker",a);return this},_destroyDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();d.removeData(a,"datepicker");if(e=="input"){c.append.remove();c.trigger.remove();b.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)}else if(e=="div"||e=="span")b.removeClass(this.markerClassName).empty()}},
_enableDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=false;c.trigger.filter("button").each(function(){this.disabled=false}).end().filter("img").css({opacity:"1.0",cursor:""})}else if(e=="div"||e=="span")b.children("."+this._inlineClass).children().removeClass("ui-state-disabled");this._disabledInputs=d.map(this._disabledInputs,function(f){return f==a?null:f})}},_disableDatepicker:function(a){var b=
d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=true;c.trigger.filter("button").each(function(){this.disabled=true}).end().filter("img").css({opacity:"0.5",cursor:"default"})}else if(e=="div"||e=="span")b.children("."+this._inlineClass).children().addClass("ui-state-disabled");this._disabledInputs=d.map(this._disabledInputs,function(f){return f==a?null:f});this._disabledInputs[this._disabledInputs.length]=a}},_isDisabledDatepicker:function(a){if(!a)return false;
for(var b=0;b<this._disabledInputs.length;b++)if(this._disabledInputs[b]==a)return true;return false},_getInst:function(a){try{return d.data(a,"datepicker")}catch(b){throw"Missing instance data for this datepicker";}},_optionDatepicker:function(a,b,c){var e=this._getInst(a);if(arguments.length==2&&typeof b=="string")return b=="defaults"?d.extend({},d.datepicker._defaults):e?b=="all"?d.extend({},e.settings):this._get(e,b):null;var f=b||{};if(typeof b=="string"){f={};f[b]=c}if(e){this._curInst==e&&
this._hideDatepicker();var h=this._getDateDatepicker(a,true);E(e.settings,f);this._attachments(d(a),e);this._autoSize(e);this._setDateDatepicker(a,h);this._updateDatepicker(e)}},_changeDatepicker:function(a,b,c){this._optionDatepicker(a,b,c)},_refreshDatepicker:function(a){(a=this._getInst(a))&&this._updateDatepicker(a)},_setDateDatepicker:function(a,b){if(a=this._getInst(a)){this._setDate(a,b);this._updateDatepicker(a);this._updateAlternate(a)}},_getDateDatepicker:function(a,b){(a=this._getInst(a))&&
!a.inline&&this._setDateFromField(a,b);return a?this._getDate(a):null},_doKeyDown:function(a){var b=d.datepicker._getInst(a.target),c=true,e=b.dpDiv.is(".ui-datepicker-rtl");b._keyEvent=true;if(d.datepicker._datepickerShowing)switch(a.keyCode){case 9:d.datepicker._hideDatepicker();c=false;break;case 13:c=d("td."+d.datepicker._dayOverClass,b.dpDiv).add(d("td."+d.datepicker._currentClass,b.dpDiv));c[0]?d.datepicker._selectDay(a.target,b.selectedMonth,b.selectedYear,c[0]):d.datepicker._hideDatepicker();
return false;case 27:d.datepicker._hideDatepicker();break;case 33:d.datepicker._adjustDate(a.target,a.ctrlKey?-d.datepicker._get(b,"stepBigMonths"):-d.datepicker._get(b,"stepMonths"),"M");break;case 34:d.datepicker._adjustDate(a.target,a.ctrlKey?+d.datepicker._get(b,"stepBigMonths"):+d.datepicker._get(b,"stepMonths"),"M");break;case 35:if(a.ctrlKey||a.metaKey)d.datepicker._clearDate(a.target);c=a.ctrlKey||a.metaKey;break;case 36:if(a.ctrlKey||a.metaKey)d.datepicker._gotoToday(a.target);c=a.ctrlKey||
a.metaKey;break;case 37:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,e?+1:-1,"D");c=a.ctrlKey||a.metaKey;if(a.originalEvent.altKey)d.datepicker._adjustDate(a.target,a.ctrlKey?-d.datepicker._get(b,"stepBigMonths"):-d.datepicker._get(b,"stepMonths"),"M");break;case 38:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,-7,"D");c=a.ctrlKey||a.metaKey;break;case 39:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,e?-1:+1,"D");c=a.ctrlKey||a.metaKey;if(a.originalEvent.altKey)d.datepicker._adjustDate(a.target,
a.ctrlKey?+d.datepicker._get(b,"stepBigMonths"):+d.datepicker._get(b,"stepMonths"),"M");break;case 40:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,+7,"D");c=a.ctrlKey||a.metaKey;break;default:c=false}else if(a.keyCode==36&&a.ctrlKey)d.datepicker._showDatepicker(this);else c=false;if(c){a.preventDefault();a.stopPropagation()}},_doKeyPress:function(a){var b=d.datepicker._getInst(a.target);if(d.datepicker._get(b,"constrainInput")){b=d.datepicker._possibleChars(d.datepicker._get(b,"dateFormat"));
var c=String.fromCharCode(a.charCode==undefined?a.keyCode:a.charCode);return a.ctrlKey||c<" "||!b||b.indexOf(c)>-1}},_doKeyUp:function(a){a=d.datepicker._getInst(a.target);if(a.input.val()!=a.lastVal)try{if(d.datepicker.parseDate(d.datepicker._get(a,"dateFormat"),a.input?a.input.val():null,d.datepicker._getFormatConfig(a))){d.datepicker._setDateFromField(a);d.datepicker._updateAlternate(a);d.datepicker._updateDatepicker(a)}}catch(b){d.datepicker.log(b)}return true},_showDatepicker:function(a){a=a.target||
a;if(a.nodeName.toLowerCase()!="input")a=d("input",a.parentNode)[0];if(!(d.datepicker._isDisabledDatepicker(a)||d.datepicker._lastInput==a)){var b=d.datepicker._getInst(a);d.datepicker._curInst&&d.datepicker._curInst!=b&&d.datepicker._curInst.dpDiv.stop(true,true);var c=d.datepicker._get(b,"beforeShow");E(b.settings,c?c.apply(a,[a,b]):{});b.lastVal=null;d.datepicker._lastInput=a;d.datepicker._setDateFromField(b);if(d.datepicker._inDialog)a.value="";if(!d.datepicker._pos){d.datepicker._pos=d.datepicker._findPos(a);
d.datepicker._pos[1]+=a.offsetHeight}var e=false;d(a).parents().each(function(){e|=d(this).css("position")=="fixed";return!e});if(e&&d.browser.opera){d.datepicker._pos[0]-=document.documentElement.scrollLeft;d.datepicker._pos[1]-=document.documentElement.scrollTop}c={left:d.datepicker._pos[0],top:d.datepicker._pos[1]};d.datepicker._pos=null;b.dpDiv.css({position:"absolute",display:"block",top:"-1000px"});d.datepicker._updateDatepicker(b);c=d.datepicker._checkOffset(b,c,e);b.dpDiv.css({position:d.datepicker._inDialog&&
d.blockUI?"static":e?"fixed":"absolute",display:"none",left:c.left+"px",top:c.top+"px"});if(!b.inline){c=d.datepicker._get(b,"showAnim");var f=d.datepicker._get(b,"duration"),h=function(){d.datepicker._datepickerShowing=true;var i=d.datepicker._getBorders(b.dpDiv);b.dpDiv.find("iframe.ui-datepicker-cover").css({left:-i[0],top:-i[1],width:b.dpDiv.outerWidth(),height:b.dpDiv.outerHeight()})};b.dpDiv.zIndex(d(a).zIndex()+1);d.effects&&d.effects[c]?b.dpDiv.show(c,d.datepicker._get(b,"showOptions"),f,
h):b.dpDiv[c||"show"](c?f:null,h);if(!c||!f)h();b.input.is(":visible")&&!b.input.is(":disabled")&&b.input.focus();d.datepicker._curInst=b}}},_updateDatepicker:function(a){var b=this,c=d.datepicker._getBorders(a.dpDiv);a.dpDiv.empty().append(this._generateHTML(a)).find("iframe.ui-datepicker-cover").css({left:-c[0],top:-c[1],width:a.dpDiv.outerWidth(),height:a.dpDiv.outerHeight()}).end().find("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a").bind("mouseout",function(){d(this).removeClass("ui-state-hover");
this.className.indexOf("ui-datepicker-prev")!=-1&&d(this).removeClass("ui-datepicker-prev-hover");this.className.indexOf("ui-datepicker-next")!=-1&&d(this).removeClass("ui-datepicker-next-hover")}).bind("mouseover",function(){if(!b._isDisabledDatepicker(a.inline?a.dpDiv.parent()[0]:a.input[0])){d(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");d(this).addClass("ui-state-hover");this.className.indexOf("ui-datepicker-prev")!=-1&&d(this).addClass("ui-datepicker-prev-hover");
this.className.indexOf("ui-datepicker-next")!=-1&&d(this).addClass("ui-datepicker-next-hover")}}).end().find("."+this._dayOverClass+" a").trigger("mouseover").end();c=this._getNumberOfMonths(a);var e=c[1];e>1?a.dpDiv.addClass("ui-datepicker-multi-"+e).css("width",17*e+"em"):a.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");a.dpDiv[(c[0]!=1||c[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi");a.dpDiv[(this._get(a,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl");
a==d.datepicker._curInst&&d.datepicker._datepickerShowing&&a.input&&a.input.is(":visible")&&!a.input.is(":disabled")&&a.input.focus()},_getBorders:function(a){var b=function(c){return{thin:1,medium:2,thick:3}[c]||c};return[parseFloat(b(a.css("border-left-width"))),parseFloat(b(a.css("border-top-width")))]},_checkOffset:function(a,b,c){var e=a.dpDiv.outerWidth(),f=a.dpDiv.outerHeight(),h=a.input?a.input.outerWidth():0,i=a.input?a.input.outerHeight():0,g=document.documentElement.clientWidth+d(document).scrollLeft(),
k=document.documentElement.clientHeight+d(document).scrollTop();b.left-=this._get(a,"isRTL")?e-h:0;b.left-=c&&b.left==a.input.offset().left?d(document).scrollLeft():0;b.top-=c&&b.top==a.input.offset().top+i?d(document).scrollTop():0;b.left-=Math.min(b.left,b.left+e>g&&g>e?Math.abs(b.left+e-g):0);b.top-=Math.min(b.top,b.top+f>k&&k>f?Math.abs(f+i):0);return b},_findPos:function(a){for(var b=this._get(this._getInst(a),"isRTL");a&&(a.type=="hidden"||a.nodeType!=1);)a=a[b?"previousSibling":"nextSibling"];
a=d(a).offset();return[a.left,a.top]},_hideDatepicker:function(a){var b=this._curInst;if(!(!b||a&&b!=d.data(a,"datepicker")))if(this._datepickerShowing){a=this._get(b,"showAnim");var c=this._get(b,"duration"),e=function(){d.datepicker._tidyDialog(b);this._curInst=null};d.effects&&d.effects[a]?b.dpDiv.hide(a,d.datepicker._get(b,"showOptions"),c,e):b.dpDiv[a=="slideDown"?"slideUp":a=="fadeIn"?"fadeOut":"hide"](a?c:null,e);a||e();if(a=this._get(b,"onClose"))a.apply(b.input?b.input[0]:null,[b.input?b.input.val():
"",b]);this._datepickerShowing=false;this._lastInput=null;if(this._inDialog){this._dialogInput.css({position:"absolute",left:"0",top:"-100px"});if(d.blockUI){d.unblockUI();d("body").append(this.dpDiv)}}this._inDialog=false}},_tidyDialog:function(a){a.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(a){if(d.datepicker._curInst){a=d(a.target);a[0].id!=d.datepicker._mainDivId&&a.parents("#"+d.datepicker._mainDivId).length==0&&!a.hasClass(d.datepicker.markerClassName)&&
!a.hasClass(d.datepicker._triggerClass)&&d.datepicker._datepickerShowing&&!(d.datepicker._inDialog&&d.blockUI)&&d.datepicker._hideDatepicker()}},_adjustDate:function(a,b,c){a=d(a);var e=this._getInst(a[0]);if(!this._isDisabledDatepicker(a[0])){this._adjustInstDate(e,b+(c=="M"?this._get(e,"showCurrentAtPos"):0),c);this._updateDatepicker(e)}},_gotoToday:function(a){a=d(a);var b=this._getInst(a[0]);if(this._get(b,"gotoCurrent")&&b.currentDay){b.selectedDay=b.currentDay;b.drawMonth=b.selectedMonth=b.currentMonth;
b.drawYear=b.selectedYear=b.currentYear}else{var c=new Date;b.selectedDay=c.getDate();b.drawMonth=b.selectedMonth=c.getMonth();b.drawYear=b.selectedYear=c.getFullYear()}this._notifyChange(b);this._adjustDate(a)},_selectMonthYear:function(a,b,c){a=d(a);var e=this._getInst(a[0]);e._selectingMonthYear=false;e["selected"+(c=="M"?"Month":"Year")]=e["draw"+(c=="M"?"Month":"Year")]=parseInt(b.options[b.selectedIndex].value,10);this._notifyChange(e);this._adjustDate(a)},_clickMonthYear:function(a){a=this._getInst(d(a)[0]);
a.input&&a._selectingMonthYear&&!d.browser.msie&&a.input.focus();a._selectingMonthYear=!a._selectingMonthYear},_selectDay:function(a,b,c,e){var f=d(a);if(!(d(e).hasClass(this._unselectableClass)||this._isDisabledDatepicker(f[0]))){f=this._getInst(f[0]);f.selectedDay=f.currentDay=d("a",e).html();f.selectedMonth=f.currentMonth=b;f.selectedYear=f.currentYear=c;this._selectDate(a,this._formatDate(f,f.currentDay,f.currentMonth,f.currentYear))}},_clearDate:function(a){a=d(a);this._getInst(a[0]);this._selectDate(a,
"")},_selectDate:function(a,b){a=this._getInst(d(a)[0]);b=b!=null?b:this._formatDate(a);a.input&&a.input.val(b);this._updateAlternate(a);var c=this._get(a,"onSelect");if(c)c.apply(a.input?a.input[0]:null,[b,a]);else a.input&&a.input.trigger("change");if(a.inline)this._updateDatepicker(a);else{this._hideDatepicker();this._lastInput=a.input[0];typeof a.input[0]!="object"&&a.input.focus();this._lastInput=null}},_updateAlternate:function(a){var b=this._get(a,"altField");if(b){var c=this._get(a,"altFormat")||
this._get(a,"dateFormat"),e=this._getDate(a),f=this.formatDate(c,e,this._getFormatConfig(a));d(b).each(function(){d(this).val(f)})}},noWeekends:function(a){a=a.getDay();return[a>0&&a<6,""]},iso8601Week:function(a){a=new Date(a.getTime());a.setDate(a.getDate()+4-(a.getDay()||7));var b=a.getTime();a.setMonth(0);a.setDate(1);return Math.floor(Math.round((b-a)/864E5)/7)+1},parseDate:function(a,b,c){if(a==null||b==null)throw"Invalid arguments";b=typeof b=="object"?b.toString():b+"";if(b=="")return null;
for(var e=(c?c.shortYearCutoff:null)||this._defaults.shortYearCutoff,f=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,h=(c?c.dayNames:null)||this._defaults.dayNames,i=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,g=(c?c.monthNames:null)||this._defaults.monthNames,k=c=-1,l=-1,u=-1,j=false,o=function(p){(p=z+1<a.length&&a.charAt(z+1)==p)&&z++;return p},m=function(p){o(p);p=new RegExp("^\\d{1,"+(p=="@"?14:p=="!"?20:p=="y"?4:p=="o"?3:2)+"}");p=b.substring(s).match(p);if(!p)throw"Missing number at position "+
s;s+=p[0].length;return parseInt(p[0],10)},n=function(p,w,G){p=o(p)?G:w;for(w=0;w<p.length;w++)if(b.substr(s,p[w].length)==p[w]){s+=p[w].length;return w+1}throw"Unknown name at position "+s;},r=function(){if(b.charAt(s)!=a.charAt(z))throw"Unexpected literal at position "+s;s++},s=0,z=0;z<a.length;z++)if(j)if(a.charAt(z)=="'"&&!o("'"))j=false;else r();else switch(a.charAt(z)){case "d":l=m("d");break;case "D":n("D",f,h);break;case "o":u=m("o");break;case "m":k=m("m");break;case "M":k=n("M",i,g);break;
case "y":c=m("y");break;case "@":var v=new Date(m("@"));c=v.getFullYear();k=v.getMonth()+1;l=v.getDate();break;case "!":v=new Date((m("!")-this._ticksTo1970)/1E4);c=v.getFullYear();k=v.getMonth()+1;l=v.getDate();break;case "'":if(o("'"))r();else j=true;break;default:r()}if(c==-1)c=(new Date).getFullYear();else if(c<100)c+=(new Date).getFullYear()-(new Date).getFullYear()%100+(c<=e?0:-100);if(u>-1){k=1;l=u;do{e=this._getDaysInMonth(c,k-1);if(l<=e)break;k++;l-=e}while(1)}v=this._daylightSavingAdjust(new Date(c,
k-1,l));if(v.getFullYear()!=c||v.getMonth()+1!=k||v.getDate()!=l)throw"Invalid date";return v},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1E7,formatDate:function(a,b,c){if(!b)return"";var e=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,f=(c?
c.dayNames:null)||this._defaults.dayNames,h=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort;c=(c?c.monthNames:null)||this._defaults.monthNames;var i=function(o){(o=j+1<a.length&&a.charAt(j+1)==o)&&j++;return o},g=function(o,m,n){m=""+m;if(i(o))for(;m.length<n;)m="0"+m;return m},k=function(o,m,n,r){return i(o)?r[m]:n[m]},l="",u=false;if(b)for(var j=0;j<a.length;j++)if(u)if(a.charAt(j)=="'"&&!i("'"))u=false;else l+=a.charAt(j);else switch(a.charAt(j)){case "d":l+=g("d",b.getDate(),2);break;
case "D":l+=k("D",b.getDay(),e,f);break;case "o":l+=g("o",(b.getTime()-(new Date(b.getFullYear(),0,0)).getTime())/864E5,3);break;case "m":l+=g("m",b.getMonth()+1,2);break;case "M":l+=k("M",b.getMonth(),h,c);break;case "y":l+=i("y")?b.getFullYear():(b.getYear()%100<10?"0":"")+b.getYear()%100;break;case "@":l+=b.getTime();break;case "!":l+=b.getTime()*1E4+this._ticksTo1970;break;case "'":if(i("'"))l+="'";else u=true;break;default:l+=a.charAt(j)}return l},_possibleChars:function(a){for(var b="",c=false,
e=function(h){(h=f+1<a.length&&a.charAt(f+1)==h)&&f++;return h},f=0;f<a.length;f++)if(c)if(a.charAt(f)=="'"&&!e("'"))c=false;else b+=a.charAt(f);else switch(a.charAt(f)){case "d":case "m":case "y":case "@":b+="0123456789";break;case "D":case "M":return null;case "'":if(e("'"))b+="'";else c=true;break;default:b+=a.charAt(f)}return b},_get:function(a,b){return a.settings[b]!==undefined?a.settings[b]:this._defaults[b]},_setDateFromField:function(a,b){if(a.input.val()!=a.lastVal){var c=this._get(a,"dateFormat"),
e=a.lastVal=a.input?a.input.val():null,f,h;f=h=this._getDefaultDate(a);var i=this._getFormatConfig(a);try{f=this.parseDate(c,e,i)||h}catch(g){this.log(g);e=b?"":e}a.selectedDay=f.getDate();a.drawMonth=a.selectedMonth=f.getMonth();a.drawYear=a.selectedYear=f.getFullYear();a.currentDay=e?f.getDate():0;a.currentMonth=e?f.getMonth():0;a.currentYear=e?f.getFullYear():0;this._adjustInstDate(a)}},_getDefaultDate:function(a){return this._restrictMinMax(a,this._determineDate(a,this._get(a,"defaultDate"),new Date))},
_determineDate:function(a,b,c){var e=function(h){var i=new Date;i.setDate(i.getDate()+h);return i},f=function(h){try{return d.datepicker.parseDate(d.datepicker._get(a,"dateFormat"),h,d.datepicker._getFormatConfig(a))}catch(i){}var g=(h.toLowerCase().match(/^c/)?d.datepicker._getDate(a):null)||new Date,k=g.getFullYear(),l=g.getMonth();g=g.getDate();for(var u=/([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,j=u.exec(h);j;){switch(j[2]||"d"){case "d":case "D":g+=parseInt(j[1],10);break;case "w":case "W":g+=parseInt(j[1],
10)*7;break;case "m":case "M":l+=parseInt(j[1],10);g=Math.min(g,d.datepicker._getDaysInMonth(k,l));break;case "y":case "Y":k+=parseInt(j[1],10);g=Math.min(g,d.datepicker._getDaysInMonth(k,l));break}j=u.exec(h)}return new Date(k,l,g)};if(b=(b=b==null?c:typeof b=="string"?f(b):typeof b=="number"?isNaN(b)?c:e(b):b)&&b.toString()=="Invalid Date"?c:b){b.setHours(0);b.setMinutes(0);b.setSeconds(0);b.setMilliseconds(0)}return this._daylightSavingAdjust(b)},_daylightSavingAdjust:function(a){if(!a)return null;
a.setHours(a.getHours()>12?a.getHours()+2:0);return a},_setDate:function(a,b,c){var e=!b,f=a.selectedMonth,h=a.selectedYear;b=this._restrictMinMax(a,this._determineDate(a,b,new Date));a.selectedDay=a.currentDay=b.getDate();a.drawMonth=a.selectedMonth=a.currentMonth=b.getMonth();a.drawYear=a.selectedYear=a.currentYear=b.getFullYear();if((f!=a.selectedMonth||h!=a.selectedYear)&&!c)this._notifyChange(a);this._adjustInstDate(a);if(a.input)a.input.val(e?"":this._formatDate(a))},_getDate:function(a){return!a.currentYear||
a.input&&a.input.val()==""?null:this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay))},_generateHTML:function(a){var b=new Date;b=this._daylightSavingAdjust(new Date(b.getFullYear(),b.getMonth(),b.getDate()));var c=this._get(a,"isRTL"),e=this._get(a,"showButtonPanel"),f=this._get(a,"hideIfNoPrevNext"),h=this._get(a,"navigationAsDateFormat"),i=this._getNumberOfMonths(a),g=this._get(a,"showCurrentAtPos"),k=this._get(a,"stepMonths"),l=i[0]!=1||i[1]!=1,u=this._daylightSavingAdjust(!a.currentDay?
new Date(9999,9,9):new Date(a.currentYear,a.currentMonth,a.currentDay)),j=this._getMinMaxDate(a,"min"),o=this._getMinMaxDate(a,"max");g=a.drawMonth-g;var m=a.drawYear;if(g<0){g+=12;m--}if(o){var n=this._daylightSavingAdjust(new Date(o.getFullYear(),o.getMonth()-i[0]*i[1]+1,o.getDate()));for(n=j&&n<j?j:n;this._daylightSavingAdjust(new Date(m,g,1))>n;){g--;if(g<0){g=11;m--}}}a.drawMonth=g;a.drawYear=m;n=this._get(a,"prevText");n=!h?n:this.formatDate(n,this._daylightSavingAdjust(new Date(m,g-k,1)),this._getFormatConfig(a));
n=this._canAdjustMonth(a,-1,m,g)?'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_'+y+".datepicker._adjustDate('#"+a.id+"', -"+k+", 'M');\" title=\""+n+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"e":"w")+'">'+n+"</span></a>":f?"":'<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+n+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"e":"w")+'">'+n+"</span></a>";var r=this._get(a,"nextText");r=!h?r:this.formatDate(r,this._daylightSavingAdjust(new Date(m,
g+k,1)),this._getFormatConfig(a));f=this._canAdjustMonth(a,+1,m,g)?'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_'+y+".datepicker._adjustDate('#"+a.id+"', +"+k+", 'M');\" title=\""+r+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"w":"e")+'">'+r+"</span></a>":f?"":'<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+r+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"w":"e")+'">'+r+"</span></a>";k=this._get(a,"currentText");r=this._get(a,"gotoCurrent")&&
a.currentDay?u:b;k=!h?k:this.formatDate(k,r,this._getFormatConfig(a));h=!a.inline?'<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_'+y+'.datepicker._hideDatepicker();">'+this._get(a,"closeText")+"</button>":"";e=e?'<div class="ui-datepicker-buttonpane ui-widget-content">'+(c?h:"")+(this._isInRange(a,r)?'<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_'+
y+".datepicker._gotoToday('#"+a.id+"');\">"+k+"</button>":"")+(c?"":h)+"</div>":"";h=parseInt(this._get(a,"firstDay"),10);h=isNaN(h)?0:h;k=this._get(a,"showWeek");r=this._get(a,"dayNames");this._get(a,"dayNamesShort");var s=this._get(a,"dayNamesMin"),z=this._get(a,"monthNames"),v=this._get(a,"monthNamesShort"),p=this._get(a,"beforeShowDay"),w=this._get(a,"showOtherMonths"),G=this._get(a,"selectOtherMonths");this._get(a,"calculateWeek");for(var K=this._getDefaultDate(a),H="",C=0;C<i[0];C++){for(var L=
"",D=0;D<i[1];D++){var M=this._daylightSavingAdjust(new Date(m,g,a.selectedDay)),t=" ui-corner-all",x="";if(l){x+='<div class="ui-datepicker-group';if(i[1]>1)switch(D){case 0:x+=" ui-datepicker-group-first";t=" ui-corner-"+(c?"right":"left");break;case i[1]-1:x+=" ui-datepicker-group-last";t=" ui-corner-"+(c?"left":"right");break;default:x+=" ui-datepicker-group-middle";t="";break}x+='">'}x+='<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix'+t+'">'+(/all|left/.test(t)&&C==0?c?
f:n:"")+(/all|right/.test(t)&&C==0?c?n:f:"")+this._generateMonthYearHeader(a,g,m,j,o,C>0||D>0,z,v)+'</div><table class="ui-datepicker-calendar"><thead><tr>';var A=k?'<th class="ui-datepicker-week-col">'+this._get(a,"weekHeader")+"</th>":"";for(t=0;t<7;t++){var q=(t+h)%7;A+="<th"+((t+h+6)%7>=5?' class="ui-datepicker-week-end"':"")+'><span title="'+r[q]+'">'+s[q]+"</span></th>"}x+=A+"</tr></thead><tbody>";A=this._getDaysInMonth(m,g);if(m==a.selectedYear&&g==a.selectedMonth)a.selectedDay=Math.min(a.selectedDay,
A);t=(this._getFirstDayOfMonth(m,g)-h+7)%7;A=l?6:Math.ceil((t+A)/7);q=this._daylightSavingAdjust(new Date(m,g,1-t));for(var N=0;N<A;N++){x+="<tr>";var O=!k?"":'<td class="ui-datepicker-week-col">'+this._get(a,"calculateWeek")(q)+"</td>";for(t=0;t<7;t++){var F=p?p.apply(a.input?a.input[0]:null,[q]):[true,""],B=q.getMonth()!=g,I=B&&!G||!F[0]||j&&q<j||o&&q>o;O+='<td class="'+((t+h+6)%7>=5?" ui-datepicker-week-end":"")+(B?" ui-datepicker-other-month":"")+(q.getTime()==M.getTime()&&g==a.selectedMonth&&
a._keyEvent||K.getTime()==q.getTime()&&K.getTime()==M.getTime()?" "+this._dayOverClass:"")+(I?" "+this._unselectableClass+" ui-state-disabled":"")+(B&&!w?"":" "+F[1]+(q.getTime()==u.getTime()?" "+this._currentClass:"")+(q.getTime()==b.getTime()?" ui-datepicker-today":""))+'"'+((!B||w)&&F[2]?' title="'+F[2]+'"':"")+(I?"":' onclick="DP_jQuery_'+y+".datepicker._selectDay('#"+a.id+"',"+q.getMonth()+","+q.getFullYear()+', this);return false;"')+">"+(B&&!w?"&#xa0;":I?'<span class="ui-state-default">'+q.getDate()+
"</span>":'<a class="ui-state-default'+(q.getTime()==b.getTime()?" ui-state-highlight":"")+(q.getTime()==u.getTime()?" ui-state-active":"")+(B?" ui-priority-secondary":"")+'" href="#">'+q.getDate()+"</a>")+"</td>";q.setDate(q.getDate()+1);q=this._daylightSavingAdjust(q)}x+=O+"</tr>"}g++;if(g>11){g=0;m++}x+="</tbody></table>"+(l?"</div>"+(i[0]>0&&D==i[1]-1?'<div class="ui-datepicker-row-break"></div>':""):"");L+=x}H+=L}H+=e+(d.browser.msie&&parseInt(d.browser.version,10)<7&&!a.inline?'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>':
"");a._keyEvent=false;return H},_generateMonthYearHeader:function(a,b,c,e,f,h,i,g){var k=this._get(a,"changeMonth"),l=this._get(a,"changeYear"),u=this._get(a,"showMonthAfterYear"),j='<div class="ui-datepicker-title">',o="";if(h||!k)o+='<span class="ui-datepicker-month">'+i[b]+"</span>";else{i=e&&e.getFullYear()==c;var m=f&&f.getFullYear()==c;o+='<select class="ui-datepicker-month" onchange="DP_jQuery_'+y+".datepicker._selectMonthYear('#"+a.id+"', this, 'M');\" onclick=\"DP_jQuery_"+y+".datepicker._clickMonthYear('#"+
a.id+"');\">";for(var n=0;n<12;n++)if((!i||n>=e.getMonth())&&(!m||n<=f.getMonth()))o+='<option value="'+n+'"'+(n==b?' selected="selected"':"")+">"+g[n]+"</option>";o+="</select>"}u||(j+=o+(h||!(k&&l)?"&#xa0;":""));if(h||!l)j+='<span class="ui-datepicker-year">'+c+"</span>";else{g=this._get(a,"yearRange").split(":");var r=(new Date).getFullYear();i=function(s){s=s.match(/c[+-].*/)?c+parseInt(s.substring(1),10):s.match(/[+-].*/)?r+parseInt(s,10):parseInt(s,10);return isNaN(s)?r:s};b=i(g[0]);g=Math.max(b,
i(g[1]||""));b=e?Math.max(b,e.getFullYear()):b;g=f?Math.min(g,f.getFullYear()):g;for(j+='<select class="ui-datepicker-year" onchange="DP_jQuery_'+y+".datepicker._selectMonthYear('#"+a.id+"', this, 'Y');\" onclick=\"DP_jQuery_"+y+".datepicker._clickMonthYear('#"+a.id+"');\">";b<=g;b++)j+='<option value="'+b+'"'+(b==c?' selected="selected"':"")+">"+b+"</option>";j+="</select>"}j+=this._get(a,"yearSuffix");if(u)j+=(h||!(k&&l)?"&#xa0;":"")+o;j+="</div>";return j},_adjustInstDate:function(a,b,c){var e=
a.drawYear+(c=="Y"?b:0),f=a.drawMonth+(c=="M"?b:0);b=Math.min(a.selectedDay,this._getDaysInMonth(e,f))+(c=="D"?b:0);e=this._restrictMinMax(a,this._daylightSavingAdjust(new Date(e,f,b)));a.selectedDay=e.getDate();a.drawMonth=a.selectedMonth=e.getMonth();a.drawYear=a.selectedYear=e.getFullYear();if(c=="M"||c=="Y")this._notifyChange(a)},_restrictMinMax:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");b=c&&b<c?c:b;return b=a&&b>a?a:b},_notifyChange:function(a){var b=this._get(a,
"onChangeMonthYear");if(b)b.apply(a.input?a.input[0]:null,[a.selectedYear,a.selectedMonth+1,a])},_getNumberOfMonths:function(a){a=this._get(a,"numberOfMonths");return a==null?[1,1]:typeof a=="number"?[1,a]:a},_getMinMaxDate:function(a,b){return this._determineDate(a,this._get(a,b+"Date"),null)},_getDaysInMonth:function(a,b){return 32-(new Date(a,b,32)).getDate()},_getFirstDayOfMonth:function(a,b){return(new Date(a,b,1)).getDay()},_canAdjustMonth:function(a,b,c,e){var f=this._getNumberOfMonths(a);
c=this._daylightSavingAdjust(new Date(c,e+(b<0?b:f[0]*f[1]),1));b<0&&c.setDate(this._getDaysInMonth(c.getFullYear(),c.getMonth()));return this._isInRange(a,c)},_isInRange:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");return(!c||b.getTime()>=c.getTime())&&(!a||b.getTime()<=a.getTime())},_getFormatConfig:function(a){var b=this._get(a,"shortYearCutoff");b=typeof b!="string"?b:(new Date).getFullYear()%100+parseInt(b,10);return{shortYearCutoff:b,dayNamesShort:this._get(a,
"dayNamesShort"),dayNames:this._get(a,"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,b,c,e){if(!b){a.currentDay=a.selectedDay;a.currentMonth=a.selectedMonth;a.currentYear=a.selectedYear}b=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(e,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),b,this._getFormatConfig(a))}});d.fn.datepicker=
function(a){if(!d.datepicker.initialized){d(document).mousedown(d.datepicker._checkExternalClick).find("body").append(d.datepicker.dpDiv);d.datepicker.initialized=true}var b=Array.prototype.slice.call(arguments,1);if(typeof a=="string"&&(a=="isDisabled"||a=="getDate"||a=="widget"))return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));if(a=="option"&&arguments.length==2&&typeof arguments[1]=="string")return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));
return this.each(function(){typeof a=="string"?d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this].concat(b)):d.datepicker._attachDatepicker(this,a)})};d.datepicker=new J;d.datepicker.initialized=false;d.datepicker.uuid=(new Date).getTime();d.datepicker.version="1.8.2";window["DP_jQuery_"+y]=d})(jQuery);
;/*
 * jQuery UI Progressbar 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Progressbar
 *
 * Depends:
 *   jquery.ui.core.js
 *   jquery.ui.widget.js
 */
(function(b){b.widget("ui.progressbar",{options:{value:0},_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this._valueMin(),"aria-valuemax":this._valueMax(),"aria-valuenow":this._value()});this.valueDiv=b("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element);this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow");
this.valueDiv.remove();b.Widget.prototype.destroy.apply(this,arguments)},value:function(a){if(a===undefined)return this._value();this._setOption("value",a);return this},_setOption:function(a,c){switch(a){case "value":this.options.value=c;this._refreshValue();this._trigger("change");break}b.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;if(typeof a!=="number")a=0;if(a<this._valueMin())a=this._valueMin();if(a>this._valueMax())a=this._valueMax();return a},
_valueMin:function(){return 0},_valueMax:function(){return 100},_refreshValue:function(){var a=this.value();this.valueDiv[a===this._valueMax()?"addClass":"removeClass"]("ui-corner-right").width(a+"%");this.element.attr("aria-valuenow",a)}});b.extend(b.ui.progressbar,{version:"1.8.2"})})(jQuery);
;/*
 * jQuery UI Effects 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/
 */
jQuery.effects||function(f){function k(c){var a;if(c&&c.constructor==Array&&c.length==3)return c;if(a=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(c))return[parseInt(a[1],10),parseInt(a[2],10),parseInt(a[3],10)];if(a=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(c))return[parseFloat(a[1])*2.55,parseFloat(a[2])*2.55,parseFloat(a[3])*2.55];if(a=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(c))return[parseInt(a[1],
16),parseInt(a[2],16),parseInt(a[3],16)];if(a=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(c))return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16)];if(/rgba\(0, 0, 0, 0\)/.exec(c))return l.transparent;return l[f.trim(c).toLowerCase()]}function q(c,a){var b;do{b=f.curCSS(c,a);if(b!=""&&b!="transparent"||f.nodeName(c,"body"))break;a="backgroundColor"}while(c=c.parentNode);return k(b)}function m(){var c=document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle,
a={},b,d;if(c&&c.length&&c[0]&&c[c[0]])for(var e=c.length;e--;){b=c[e];if(typeof c[b]=="string"){d=b.replace(/\-(\w)/g,function(g,h){return h.toUpperCase()});a[d]=c[b]}}else for(b in c)if(typeof c[b]==="string")a[b]=c[b];return a}function n(c){var a,b;for(a in c){b=c[a];if(b==null||f.isFunction(b)||a in r||/scrollbar/.test(a)||!/color/i.test(a)&&isNaN(parseFloat(b)))delete c[a]}return c}function s(c,a){var b={_:0},d;for(d in a)if(c[d]!=a[d])b[d]=a[d];return b}function j(c,a,b,d){if(typeof c=="object"){d=
a;b=null;a=c;c=a.effect}if(f.isFunction(a)){d=a;b=null;a={}}if(f.isFunction(b)){d=b;b=null}if(typeof a=="number"||f.fx.speeds[a]){d=b;b=a;a={}}a=a||{};b=b||a.duration;b=f.fx.off?0:typeof b=="number"?b:f.fx.speeds[b]||f.fx.speeds._default;d=d||a.complete;return[c,a,b,d]}f.effects={};f.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","color","outlineColor"],function(c,a){f.fx.step[a]=function(b){if(!b.colorInit){b.start=q(b.elem,a);b.end=k(b.end);b.colorInit=
true}b.elem.style[a]="rgb("+Math.max(Math.min(parseInt(b.pos*(b.end[0]-b.start[0])+b.start[0],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[1]-b.start[1])+b.start[1],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[2]-b.start[2])+b.start[2],10),255),0)+")"}});var l={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,
183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,
165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]},o=["add","remove","toggle"],r={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};f.effects.animateClass=function(c,a,b,d){if(f.isFunction(b)){d=b;b=null}return this.each(function(){var e=f(this),g=e.attr("style")||" ",h=n(m.call(this)),p,t=e.attr("className");f.each(o,function(u,
i){c[i]&&e[i+"Class"](c[i])});p=n(m.call(this));e.attr("className",t);e.animate(s(h,p),a,b,function(){f.each(o,function(u,i){c[i]&&e[i+"Class"](c[i])});if(typeof e.attr("style")=="object"){e.attr("style").cssText="";e.attr("style").cssText=g}else e.attr("style",g);d&&d.apply(this,arguments)})})};f.fn.extend({_addClass:f.fn.addClass,addClass:function(c,a,b,d){return a?f.effects.animateClass.apply(this,[{add:c},a,b,d]):this._addClass(c)},_removeClass:f.fn.removeClass,removeClass:function(c,a,b,d){return a?
f.effects.animateClass.apply(this,[{remove:c},a,b,d]):this._removeClass(c)},_toggleClass:f.fn.toggleClass,toggleClass:function(c,a,b,d,e){return typeof a=="boolean"||a===undefined?b?f.effects.animateClass.apply(this,[a?{add:c}:{remove:c},b,d,e]):this._toggleClass(c,a):f.effects.animateClass.apply(this,[{toggle:c},a,b,d])},switchClass:function(c,a,b,d,e){return f.effects.animateClass.apply(this,[{add:a,remove:c},b,d,e])}});f.extend(f.effects,{version:"1.8.2",save:function(c,a){for(var b=0;b<a.length;b++)a[b]!==
null&&c.data("ec.storage."+a[b],c[0].style[a[b]])},restore:function(c,a){for(var b=0;b<a.length;b++)a[b]!==null&&c.css(a[b],c.data("ec.storage."+a[b]))},setMode:function(c,a){if(a=="toggle")a=c.is(":hidden")?"show":"hide";return a},getBaseline:function(c,a){var b;switch(c[0]){case "top":b=0;break;case "middle":b=0.5;break;case "bottom":b=1;break;default:b=c[0]/a.height}switch(c[1]){case "left":c=0;break;case "center":c=0.5;break;case "right":c=1;break;default:c=c[1]/a.width}return{x:c,y:b}},createWrapper:function(c){if(c.parent().is(".ui-effects-wrapper"))return c.parent();
var a={width:c.outerWidth(true),height:c.outerHeight(true),"float":c.css("float")},b=f("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0});c.wrap(b);b=c.parent();if(c.css("position")=="static"){b.css({position:"relative"});c.css({position:"relative"})}else{f.extend(a,{position:c.css("position"),zIndex:c.css("z-index")});f.each(["top","left","bottom","right"],function(d,e){a[e]=c.css(e);if(isNaN(parseInt(a[e],10)))a[e]="auto"});
c.css({position:"relative",top:0,left:0})}return b.css(a).show()},removeWrapper:function(c){if(c.parent().is(".ui-effects-wrapper"))return c.parent().replaceWith(c);return c},setTransition:function(c,a,b,d){d=d||{};f.each(a,function(e,g){unit=c.cssUnit(g);if(unit[0]>0)d[g]=unit[0]*b+unit[1]});return d}});f.fn.extend({effect:function(c){var a=j.apply(this,arguments);a={options:a[1],duration:a[2],callback:a[3]};var b=f.effects[c];return b&&!f.fx.off?b.call(this,a):this},_show:f.fn.show,show:function(c){if(!c||
typeof c=="number"||f.fx.speeds[c])return this._show.apply(this,arguments);else{var a=j.apply(this,arguments);a[1].mode="show";return this.effect.apply(this,a)}},_hide:f.fn.hide,hide:function(c){if(!c||typeof c=="number"||f.fx.speeds[c])return this._hide.apply(this,arguments);else{var a=j.apply(this,arguments);a[1].mode="hide";return this.effect.apply(this,a)}},__toggle:f.fn.toggle,toggle:function(c){if(!c||typeof c=="number"||f.fx.speeds[c]||typeof c=="boolean"||f.isFunction(c))return this.__toggle.apply(this,
arguments);else{var a=j.apply(this,arguments);a[1].mode="toggle";return this.effect.apply(this,a)}},cssUnit:function(c){var a=this.css(c),b=[];f.each(["em","px","%","pt"],function(d,e){if(a.indexOf(e)>0)b=[parseFloat(a),e]});return b}});f.easing.jswing=f.easing.swing;f.extend(f.easing,{def:"easeOutQuad",swing:function(c,a,b,d,e){return f.easing[f.easing.def](c,a,b,d,e)},easeInQuad:function(c,a,b,d,e){return d*(a/=e)*a+b},easeOutQuad:function(c,a,b,d,e){return-d*(a/=e)*(a-2)+b},easeInOutQuad:function(c,
a,b,d,e){if((a/=e/2)<1)return d/2*a*a+b;return-d/2*(--a*(a-2)-1)+b},easeInCubic:function(c,a,b,d,e){return d*(a/=e)*a*a+b},easeOutCubic:function(c,a,b,d,e){return d*((a=a/e-1)*a*a+1)+b},easeInOutCubic:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a+b;return d/2*((a-=2)*a*a+2)+b},easeInQuart:function(c,a,b,d,e){return d*(a/=e)*a*a*a+b},easeOutQuart:function(c,a,b,d,e){return-d*((a=a/e-1)*a*a*a-1)+b},easeInOutQuart:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a+b;return-d/2*((a-=2)*a*a*a-2)+
b},easeInQuint:function(c,a,b,d,e){return d*(a/=e)*a*a*a*a+b},easeOutQuint:function(c,a,b,d,e){return d*((a=a/e-1)*a*a*a*a+1)+b},easeInOutQuint:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a*a+b;return d/2*((a-=2)*a*a*a*a+2)+b},easeInSine:function(c,a,b,d,e){return-d*Math.cos(a/e*(Math.PI/2))+d+b},easeOutSine:function(c,a,b,d,e){return d*Math.sin(a/e*(Math.PI/2))+b},easeInOutSine:function(c,a,b,d,e){return-d/2*(Math.cos(Math.PI*a/e)-1)+b},easeInExpo:function(c,a,b,d,e){return a==0?b:d*Math.pow(2,
10*(a/e-1))+b},easeOutExpo:function(c,a,b,d,e){return a==e?b+d:d*(-Math.pow(2,-10*a/e)+1)+b},easeInOutExpo:function(c,a,b,d,e){if(a==0)return b;if(a==e)return b+d;if((a/=e/2)<1)return d/2*Math.pow(2,10*(a-1))+b;return d/2*(-Math.pow(2,-10*--a)+2)+b},easeInCirc:function(c,a,b,d,e){return-d*(Math.sqrt(1-(a/=e)*a)-1)+b},easeOutCirc:function(c,a,b,d,e){return d*Math.sqrt(1-(a=a/e-1)*a)+b},easeInOutCirc:function(c,a,b,d,e){if((a/=e/2)<1)return-d/2*(Math.sqrt(1-a*a)-1)+b;return d/2*(Math.sqrt(1-(a-=2)*
a)+1)+b},easeInElastic:function(c,a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e)==1)return b+d;g||(g=e*0.3);if(h<Math.abs(d)){h=d;c=g/4}else c=g/(2*Math.PI)*Math.asin(d/h);return-(h*Math.pow(2,10*(a-=1))*Math.sin((a*e-c)*2*Math.PI/g))+b},easeOutElastic:function(c,a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e)==1)return b+d;g||(g=e*0.3);if(h<Math.abs(d)){h=d;c=g/4}else c=g/(2*Math.PI)*Math.asin(d/h);return h*Math.pow(2,-10*a)*Math.sin((a*e-c)*2*Math.PI/g)+d+b},easeInOutElastic:function(c,
a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e/2)==2)return b+d;g||(g=e*0.3*1.5);if(h<Math.abs(d)){h=d;c=g/4}else c=g/(2*Math.PI)*Math.asin(d/h);if(a<1)return-0.5*h*Math.pow(2,10*(a-=1))*Math.sin((a*e-c)*2*Math.PI/g)+b;return h*Math.pow(2,-10*(a-=1))*Math.sin((a*e-c)*2*Math.PI/g)*0.5+d+b},easeInBack:function(c,a,b,d,e,g){if(g==undefined)g=1.70158;return d*(a/=e)*a*((g+1)*a-g)+b},easeOutBack:function(c,a,b,d,e,g){if(g==undefined)g=1.70158;return d*((a=a/e-1)*a*((g+1)*a+g)+1)+b},easeInOutBack:function(c,
a,b,d,e,g){if(g==undefined)g=1.70158;if((a/=e/2)<1)return d/2*a*a*(((g*=1.525)+1)*a-g)+b;return d/2*((a-=2)*a*(((g*=1.525)+1)*a+g)+2)+b},easeInBounce:function(c,a,b,d,e){return d-f.easing.easeOutBounce(c,e-a,0,d,e)+b},easeOutBounce:function(c,a,b,d,e){return(a/=e)<1/2.75?d*7.5625*a*a+b:a<2/2.75?d*(7.5625*(a-=1.5/2.75)*a+0.75)+b:a<2.5/2.75?d*(7.5625*(a-=2.25/2.75)*a+0.9375)+b:d*(7.5625*(a-=2.625/2.75)*a+0.984375)+b},easeInOutBounce:function(c,a,b,d,e){if(a<e/2)return f.easing.easeInBounce(c,a*2,0,
d,e)*0.5+b;return f.easing.easeOutBounce(c,a*2-e,0,d,e)*0.5+d*0.5+b}})}(jQuery);
;/*
 * jQuery UI Effects Blind 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Blind
 *
 * Depends:
 *	jquery.effects.core.js
 */
(function(b){b.effects.blind=function(c){return this.queue(function(){var a=b(this),g=["position","top","left"],f=b.effects.setMode(a,c.options.mode||"hide"),d=c.options.direction||"vertical";b.effects.save(a,g);a.show();var e=b.effects.createWrapper(a).css({overflow:"hidden"}),h=d=="vertical"?"height":"width";d=d=="vertical"?e.height():e.width();f=="show"&&e.css(h,0);var i={};i[h]=f=="show"?d:0;e.animate(i,c.duration,c.options.easing,function(){f=="hide"&&a.hide();b.effects.restore(a,g);b.effects.removeWrapper(a);
c.callback&&c.callback.apply(a[0],arguments);a.dequeue()})})}})(jQuery);
;/*
 * jQuery UI Effects Bounce 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Bounce
 *
 * Depends:
 *	jquery.effects.core.js
 */
(function(e){e.effects.bounce=function(b){return this.queue(function(){var a=e(this),l=["position","top","left"],h=e.effects.setMode(a,b.options.mode||"effect"),d=b.options.direction||"up",c=b.options.distance||20,m=b.options.times||5,i=b.duration||250;/show|hide/.test(h)&&l.push("opacity");e.effects.save(a,l);a.show();e.effects.createWrapper(a);var f=d=="up"||d=="down"?"top":"left";d=d=="up"||d=="left"?"pos":"neg";c=b.options.distance||(f=="top"?a.outerHeight({margin:true})/3:a.outerWidth({margin:true})/
3);if(h=="show")a.css("opacity",0).css(f,d=="pos"?-c:c);if(h=="hide")c/=m*2;h!="hide"&&m--;if(h=="show"){var g={opacity:1};g[f]=(d=="pos"?"+=":"-=")+c;a.animate(g,i/2,b.options.easing);c/=2;m--}for(g=0;g<m;g++){var j={},k={};j[f]=(d=="pos"?"-=":"+=")+c;k[f]=(d=="pos"?"+=":"-=")+c;a.animate(j,i/2,b.options.easing).animate(k,i/2,b.options.easing);c=h=="hide"?c*2:c/2}if(h=="hide"){g={opacity:0};g[f]=(d=="pos"?"-=":"+=")+c;a.animate(g,i/2,b.options.easing,function(){a.hide();e.effects.restore(a,l);e.effects.removeWrapper(a);
b.callback&&b.callback.apply(this,arguments)})}else{j={};k={};j[f]=(d=="pos"?"-=":"+=")+c;k[f]=(d=="pos"?"+=":"-=")+c;a.animate(j,i/2,b.options.easing).animate(k,i/2,b.options.easing,function(){e.effects.restore(a,l);e.effects.removeWrapper(a);b.callback&&b.callback.apply(this,arguments)})}a.queue("fx",function(){a.dequeue()});a.dequeue()})}})(jQuery);
;/*
 * jQuery UI Effects Clip 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Clip
 *
 * Depends:
 *	jquery.effects.core.js
 */
(function(b){b.effects.clip=function(e){return this.queue(function(){var a=b(this),i=["position","top","left","height","width"],f=b.effects.setMode(a,e.options.mode||"hide"),c=e.options.direction||"vertical";b.effects.save(a,i);a.show();var d=b.effects.createWrapper(a).css({overflow:"hidden"});d=a[0].tagName=="IMG"?d:a;var g={size:c=="vertical"?"height":"width",position:c=="vertical"?"top":"left"};c=c=="vertical"?d.height():d.width();if(f=="show"){d.css(g.size,0);d.css(g.position,c/2)}var h={};h[g.size]=
f=="show"?c:0;h[g.position]=f=="show"?0:c/2;d.animate(h,{queue:false,duration:e.duration,easing:e.options.easing,complete:function(){f=="hide"&&a.hide();b.effects.restore(a,i);b.effects.removeWrapper(a);e.callback&&e.callback.apply(a[0],arguments);a.dequeue()}})})}})(jQuery);
;/*
 * jQuery UI Effects Drop 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Drop
 *
 * Depends:
 *	jquery.effects.core.js
 */
(function(c){c.effects.drop=function(d){return this.queue(function(){var a=c(this),h=["position","top","left","opacity"],e=c.effects.setMode(a,d.options.mode||"hide"),b=d.options.direction||"left";c.effects.save(a,h);a.show();c.effects.createWrapper(a);var f=b=="up"||b=="down"?"top":"left";b=b=="up"||b=="left"?"pos":"neg";var g=d.options.distance||(f=="top"?a.outerHeight({margin:true})/2:a.outerWidth({margin:true})/2);if(e=="show")a.css("opacity",0).css(f,b=="pos"?-g:g);var i={opacity:e=="show"?1:
0};i[f]=(e=="show"?b=="pos"?"+=":"-=":b=="pos"?"-=":"+=")+g;a.animate(i,{queue:false,duration:d.duration,easing:d.options.easing,complete:function(){e=="hide"&&a.hide();c.effects.restore(a,h);c.effects.removeWrapper(a);d.callback&&d.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery);
;/*
 * jQuery UI Effects Explode 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Explode
 *
 * Depends:
 *	jquery.effects.core.js
 */
(function(j){j.effects.explode=function(a){return this.queue(function(){var c=a.options.pieces?Math.round(Math.sqrt(a.options.pieces)):3,d=a.options.pieces?Math.round(Math.sqrt(a.options.pieces)):3;a.options.mode=a.options.mode=="toggle"?j(this).is(":visible")?"hide":"show":a.options.mode;var b=j(this).show().css("visibility","hidden"),g=b.offset();g.top-=parseInt(b.css("marginTop"),10)||0;g.left-=parseInt(b.css("marginLeft"),10)||0;for(var h=b.outerWidth(true),i=b.outerHeight(true),e=0;e<c;e++)for(var f=
0;f<d;f++)b.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-f*(h/d),top:-e*(i/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:h/d,height:i/c,left:g.left+f*(h/d)+(a.options.mode=="show"?(f-Math.floor(d/2))*(h/d):0),top:g.top+e*(i/c)+(a.options.mode=="show"?(e-Math.floor(c/2))*(i/c):0),opacity:a.options.mode=="show"?0:1}).animate({left:g.left+f*(h/d)+(a.options.mode=="show"?0:(f-Math.floor(d/2))*(h/d)),top:g.top+
e*(i/c)+(a.options.mode=="show"?0:(e-Math.floor(c/2))*(i/c)),opacity:a.options.mode=="show"?1:0},a.duration||500);setTimeout(function(){a.options.mode=="show"?b.css({visibility:"visible"}):b.css({visibility:"visible"}).hide();a.callback&&a.callback.apply(b[0]);b.dequeue();j("div.ui-effects-explode").remove()},a.duration||500)})}})(jQuery);
;/*
 * jQuery UI Effects Fold 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Fold
 *
 * Depends:
 *	jquery.effects.core.js
 */
(function(c){c.effects.fold=function(a){return this.queue(function(){var b=c(this),j=["position","top","left"],d=c.effects.setMode(b,a.options.mode||"hide"),g=a.options.size||15,h=!!a.options.horizFirst,k=a.duration?a.duration/2:c.fx.speeds._default/2;c.effects.save(b,j);b.show();var e=c.effects.createWrapper(b).css({overflow:"hidden"}),f=d=="show"!=h,l=f?["width","height"]:["height","width"];f=f?[e.width(),e.height()]:[e.height(),e.width()];var i=/([0-9]+)%/.exec(g);if(i)g=parseInt(i[1],10)/100*
f[d=="hide"?0:1];if(d=="show")e.css(h?{height:0,width:g}:{height:g,width:0});h={};i={};h[l[0]]=d=="show"?f[0]:g;i[l[1]]=d=="show"?f[1]:0;e.animate(h,k,a.options.easing).animate(i,k,a.options.easing,function(){d=="hide"&&b.hide();c.effects.restore(b,j);c.effects.removeWrapper(b);a.callback&&a.callback.apply(b[0],arguments);b.dequeue()})})}})(jQuery);
;/*
 * jQuery UI Effects Highlight 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Highlight
 *
 * Depends:
 *	jquery.effects.core.js
 */
(function(b){b.effects.highlight=function(c){return this.queue(function(){var a=b(this),e=["backgroundImage","backgroundColor","opacity"],d=b.effects.setMode(a,c.options.mode||"show"),f={backgroundColor:a.css("backgroundColor")};if(d=="hide")f.opacity=0;b.effects.save(a,e);a.show().css({backgroundImage:"none",backgroundColor:c.options.color||"#ffff99"}).animate(f,{queue:false,duration:c.duration,easing:c.options.easing,complete:function(){d=="hide"&&a.hide();b.effects.restore(a,e);d=="show"&&!b.support.opacity&&
this.style.removeAttribute("filter");c.callback&&c.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery);
;/*
 * jQuery UI Effects Pulsate 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Pulsate
 *
 * Depends:
 *	jquery.effects.core.js
 */
(function(d){d.effects.pulsate=function(a){return this.queue(function(){var b=d(this),c=d.effects.setMode(b,a.options.mode||"show");times=(a.options.times||5)*2-1;duration=a.duration?a.duration/2:d.fx.speeds._default/2;isVisible=b.is(":visible");animateTo=0;if(!isVisible){b.css("opacity",0).show();animateTo=1}if(c=="hide"&&isVisible||c=="show"&&!isVisible)times--;for(c=0;c<times;c++){b.animate({opacity:animateTo},duration,a.options.easing);animateTo=(animateTo+1)%2}b.animate({opacity:animateTo},duration,
a.options.easing,function(){animateTo==0&&b.hide();a.callback&&a.callback.apply(this,arguments)});b.queue("fx",function(){b.dequeue()}).dequeue()})}})(jQuery);
;/*
 * jQuery UI Effects Scale 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Scale
 *
 * Depends:
 *	jquery.effects.core.js
 */
(function(c){c.effects.puff=function(b){return this.queue(function(){var a=c(this),e=c.effects.setMode(a,b.options.mode||"hide"),g=parseInt(b.options.percent,10)||150,h=g/100,i={height:a.height(),width:a.width()};c.extend(b.options,{fade:true,mode:e,percent:e=="hide"?g:100,from:e=="hide"?i:{height:i.height*h,width:i.width*h}});a.effect("scale",b.options,b.duration,b.callback);a.dequeue()})};c.effects.scale=function(b){return this.queue(function(){var a=c(this),e=c.extend(true,{},b.options),g=c.effects.setMode(a,
b.options.mode||"effect"),h=parseInt(b.options.percent,10)||(parseInt(b.options.percent,10)==0?0:g=="hide"?0:100),i=b.options.direction||"both",f=b.options.origin;if(g!="effect"){e.origin=f||["middle","center"];e.restore=true}f={height:a.height(),width:a.width()};a.from=b.options.from||(g=="show"?{height:0,width:0}:f);h={y:i!="horizontal"?h/100:1,x:i!="vertical"?h/100:1};a.to={height:f.height*h.y,width:f.width*h.x};if(b.options.fade){if(g=="show"){a.from.opacity=0;a.to.opacity=1}if(g=="hide"){a.from.opacity=
1;a.to.opacity=0}}e.from=a.from;e.to=a.to;e.mode=g;a.effect("size",e,b.duration,b.callback);a.dequeue()})};c.effects.size=function(b){return this.queue(function(){var a=c(this),e=["position","top","left","width","height","overflow","opacity"],g=["position","top","left","overflow","opacity"],h=["width","height","overflow"],i=["fontSize"],f=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],k=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],p=c.effects.setMode(a,
b.options.mode||"effect"),n=b.options.restore||false,m=b.options.scale||"both",l=b.options.origin,j={height:a.height(),width:a.width()};a.from=b.options.from||j;a.to=b.options.to||j;if(l){l=c.effects.getBaseline(l,j);a.from.top=(j.height-a.from.height)*l.y;a.from.left=(j.width-a.from.width)*l.x;a.to.top=(j.height-a.to.height)*l.y;a.to.left=(j.width-a.to.width)*l.x}var d={from:{y:a.from.height/j.height,x:a.from.width/j.width},to:{y:a.to.height/j.height,x:a.to.width/j.width}};if(m=="box"||m=="both"){if(d.from.y!=
d.to.y){e=e.concat(f);a.from=c.effects.setTransition(a,f,d.from.y,a.from);a.to=c.effects.setTransition(a,f,d.to.y,a.to)}if(d.from.x!=d.to.x){e=e.concat(k);a.from=c.effects.setTransition(a,k,d.from.x,a.from);a.to=c.effects.setTransition(a,k,d.to.x,a.to)}}if(m=="content"||m=="both")if(d.from.y!=d.to.y){e=e.concat(i);a.from=c.effects.setTransition(a,i,d.from.y,a.from);a.to=c.effects.setTransition(a,i,d.to.y,a.to)}c.effects.save(a,n?e:g);a.show();c.effects.createWrapper(a);a.css("overflow","hidden").css(a.from);
if(m=="content"||m=="both"){f=f.concat(["marginTop","marginBottom"]).concat(i);k=k.concat(["marginLeft","marginRight"]);h=e.concat(f).concat(k);a.find("*[width]").each(function(){child=c(this);n&&c.effects.save(child,h);var o={height:child.height(),width:child.width()};child.from={height:o.height*d.from.y,width:o.width*d.from.x};child.to={height:o.height*d.to.y,width:o.width*d.to.x};if(d.from.y!=d.to.y){child.from=c.effects.setTransition(child,f,d.from.y,child.from);child.to=c.effects.setTransition(child,
f,d.to.y,child.to)}if(d.from.x!=d.to.x){child.from=c.effects.setTransition(child,k,d.from.x,child.from);child.to=c.effects.setTransition(child,k,d.to.x,child.to)}child.css(child.from);child.animate(child.to,b.duration,b.options.easing,function(){n&&c.effects.restore(child,h)})})}a.animate(a.to,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){a.to.opacity===0&&a.css("opacity",a.from.opacity);p=="hide"&&a.hide();c.effects.restore(a,n?e:g);c.effects.removeWrapper(a);b.callback&&
b.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery);
;/*
 * jQuery UI Effects Shake 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Shake
 *
 * Depends:
 *	jquery.effects.core.js
 */
(function(d){d.effects.shake=function(a){return this.queue(function(){var b=d(this),j=["position","top","left"];d.effects.setMode(b,a.options.mode||"effect");var c=a.options.direction||"left",e=a.options.distance||20,l=a.options.times||3,f=a.duration||a.options.duration||140;d.effects.save(b,j);b.show();d.effects.createWrapper(b);var g=c=="up"||c=="down"?"top":"left",h=c=="up"||c=="left"?"pos":"neg";c={};var i={},k={};c[g]=(h=="pos"?"-=":"+=")+e;i[g]=(h=="pos"?"+=":"-=")+e*2;k[g]=(h=="pos"?"-=":"+=")+
e*2;b.animate(c,f,a.options.easing);for(e=1;e<l;e++)b.animate(i,f,a.options.easing).animate(k,f,a.options.easing);b.animate(i,f,a.options.easing).animate(c,f/2,a.options.easing,function(){d.effects.restore(b,j);d.effects.removeWrapper(b);a.callback&&a.callback.apply(this,arguments)});b.queue("fx",function(){b.dequeue()});b.dequeue()})}})(jQuery);
;/*
 * jQuery UI Effects Slide 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Slide
 *
 * Depends:
 *	jquery.effects.core.js
 */
(function(c){c.effects.slide=function(d){return this.queue(function(){var a=c(this),h=["position","top","left"],e=c.effects.setMode(a,d.options.mode||"show"),b=d.options.direction||"left";c.effects.save(a,h);a.show();c.effects.createWrapper(a).css({overflow:"hidden"});var f=b=="up"||b=="down"?"top":"left";b=b=="up"||b=="left"?"pos":"neg";var g=d.options.distance||(f=="top"?a.outerHeight({margin:true}):a.outerWidth({margin:true}));if(e=="show")a.css(f,b=="pos"?-g:g);var i={};i[f]=(e=="show"?b=="pos"?
"+=":"-=":b=="pos"?"-=":"+=")+g;a.animate(i,{queue:false,duration:d.duration,easing:d.options.easing,complete:function(){e=="hide"&&a.hide();c.effects.restore(a,h);c.effects.removeWrapper(a);d.callback&&d.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery);
;/*
 * jQuery UI Effects Transfer 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Transfer
 *
 * Depends:
 *	jquery.effects.core.js
 */
(function(e){e.effects.transfer=function(a){return this.queue(function(){var b=e(this),c=e(a.options.to),d=c.offset();c={top:d.top,left:d.left,height:c.innerHeight(),width:c.innerWidth()};d=b.offset();var f=e('<div class="ui-effects-transfer"></div>').appendTo(document.body).addClass(a.options.className).css({top:d.top,left:d.left,height:b.innerHeight(),width:b.innerWidth(),position:"absolute"}).animate(c,a.duration,a.options.easing,function(){f.remove();a.callback&&a.callback.apply(b[0],arguments);
b.dequeue()})})}})(jQuery);
;/*
 * jQuery PanZoom Plugin
 * Pan and zoom an image within a parent div.
 *
 * version: 0.9.0
 * @requires jQuery v1.4.2 or later (earlier probably work, but untested so far)
 *
 * Copyright (c) 2011 Ben Lumley
 * Examples and documentation at: https://github.com/benlumley/jQuery-PanZoom
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
*/

(function( $ ){

  $.fn.panZoom = function(method) {

    if ( methods[method] ) {
      return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
      return methods.init.apply( this, arguments );
    } else {
      $.error( 'Method ' +  method + ' does not exist' );
    }

  };

	$.fn.panZoom.defaults = {
      zoomIn   					: 	false,
      zoomOut 					: 	false,
		  panUp							:		false,
		  panDown						:		false,
		  panLeft						:		false,
		  panRight					:		false,
			fit								: 	false,
		  out_x1						:		false,
		  out_y1						:		false,
		  out_x2						:		false,
		  out_y2						:		false,
			min_width					:   20,
			min_height 				:   20,
			zoom_step					:   3,
			pan_step  				:   3,
			debug							: 	false,
			directedit				:   false,
      aspect    				:   true,
      factor    				:   1,
		  animate   				:   true,
			animate_duration	: 	200,
		 	animate_easing		: 	'linear',
			double_click	 		: 	true,
			mousewheel				: 	true,
			mousewheel_delta	: 	1,
			draggable					:   true,
			clickandhold			: 	true
  };

	var settings = {}

  var methods = {
		'init': function (options) {
			$.extend(settings, $.fn.panZoom.defaults, options);
  		setupCSS.apply(this);
			setupData.apply(this);
			setupBindings.apply(this);
			methods.readPosition.apply(this);
		},

		'destroy': function () {
			$(window).unbind('.panZoom');
			this.removeData('panZoom');
		},

		'loadImage': function () {
			var data = this.data('panZoom');
      loadTargetDimensions.apply(this);
			methods.updatePosition.apply(this);
			if (data.last_image != null && data.last_image != this.attr('src')) {
        methods.fit.apply(this);
			}
			data.last_image = this.attr('src');
			data.loaded = true;
		},

	  'readPosition': function () {
				var data = this.data('panZoom');
		 		if (settings.out_x1) { data.position.x1 = settings.out_x1.val()*settings.factor }
		 		if (settings.out_y1) { data.position.y1 = settings.out_y1.val()*settings.factor }
		 		if (settings.out_x2) { data.position.x2 = settings.out_x2.val()*settings.factor }
		 		if (settings.out_y2) { data.position.y2 = settings.out_y2.val()*settings.factor }
				methods.updatePosition.apply(this);
		 },

		'updatePosition': function() {
			validatePosition.apply(this);
			writePosition.apply(this);
			applyPosition.apply(this);
		},

	  'fit': function () {
			var data = this.data('panZoom');
			data.position.x1 = 0;
			data.position.y1 = 0;
			data.position.x2 = data.viewport_dimensions.x;
			data.position.y2 = data.viewport_dimensions.y;
			methods.updatePosition.apply(this);
		},

		'zoomIn': function (steps) {
			var data = this.data('panZoom');
			if (typeof(steps) == 'undefined') {
				var steps = getStepDimensions.apply(this);
			}
            console.debug(data.position);
			console.debug(data.viewport_dimensions);
			data.position.x1 = data.position.x1*1 - steps.zoom.x;
			data.position.x2 = data.position.x2*1 + steps.zoom.x;
			data.position.y1 = data.position.y1*1 - steps.zoom.y;
			data.position.y2 = data.position.y2*1 + steps.zoom.y;
			methods.updatePosition.apply(this);
		 },

		'zoomOut': function (steps) {
			var data = this.data('panZoom');
			if (typeof(steps) == 'undefined') {
				var steps = getStepDimensions.apply(this);
			}
			data.position.x1 = data.position.x1*1 + steps.zoom.x;
			data.position.x2 = data.position.x2*1 - steps.zoom.x;
			data.position.y1 = data.position.y1*1 + steps.zoom.y;
			data.position.y2 = data.position.y2*1 - steps.zoom.y;
			methods.updatePosition.apply(this);
		 },

		'panUp': function () {
			var data = this.data('panZoom');
			var steps = getStepDimensions.apply(this);
			data.position.y1 -= steps.pan.y;
			data.position.y2 -= steps.pan.y;
			methods.updatePosition.apply(this);
		},

		'panDown': function () {
			var data = this.data('panZoom');
			var steps = getStepDimensions.apply(this);
			data.position.y1 = data.position.y1*1 + steps.pan.y;
			data.position.y2 = data.position.y2*1 + steps.pan.y;
			methods.updatePosition.apply(this);
		},

		'panLeft': function () {
			var data = this.data('panZoom');
			var steps = getStepDimensions.apply(this);
			data.position.x1 -= steps.pan.x;
			data.position.x2 -= steps.pan.x;
			methods.updatePosition.apply(this);
		},

		'panRight': function () {
			var data = this.data('panZoom');
			var steps = getStepDimensions.apply(this);
			data.position.x1 = data.position.x1*1 + steps.pan.x;
			data.position.x2 = data.position.x2*1 + steps.pan.x;
			methods.updatePosition.apply(this);
		},

		'mouseWheel': function (delta) {
			// first calculate how much to zoom in/out
			var steps = getStepDimensions.apply(this);
			steps.zoom.x = steps.zoom.x * (Math.abs(delta) / settings.mousewheel_delta);
			steps.zoom.y = steps.zoom.y * (Math.abs(delta) / settings.mousewheel_delta);

			// then do it
			if (delta > 0) {
				methods.zoomIn.apply(this, [steps]);
			} else if (delta < 0) {
				methods.zoomOut.apply(this, [steps]);
			}
		},

		'dragComplete': function() {
			var data = this.data('panZoom');
			data.position.x1 = this.position().left;
			data.position.y1 = this.position().top;
			data.position.x2 = this.position().left*1 + this.width();
			data.position.y2 = this.position().top*1 + this.height();
			methods.updatePosition.apply(this);
		},

		'mouseDown': function (action) {
			methods[action].apply(this);

			if (settings.clickandhold) {
				var data = this.data('panZoom');
				methods.mouseUp.apply(this);
				data.mousedown_interval = window.setInterval(function (that, action) {
					that.panZoom(action);
				}, settings.animate_duration, this, action);
			}
		},

		'mouseUp': function() {
			var data = this.data('panZoom');
			window.clearInterval(data.mousedown_interval);
		}

  }

	function setupBindings() {

		eventData = { target: this }

		// bind up controls
		if (settings.zoomIn) {
			settings.zoomIn.bind('mousedown.panZoom', eventData, function(event) {
				event.preventDefault(); event.data.target.panZoom('mouseDown', 'zoomIn');
			}).bind('mouseleave.panZoom mouseup.panZoom', eventData, function(event) {
				event.preventDefault(); event.data.target.panZoom('mouseUp');
			});
		}

		if (settings.zoomOut) {
			settings.zoomOut.bind('mousedown.panZoom', eventData, function(event) {
				event.preventDefault(); event.data.target.panZoom('mouseDown', 'zoomOut');
			}).bind('mouseleave.panZoom mouseup.panZoom', eventData, function(event) {
				event.preventDefault(); event.data.target.panZoom('mouseUp');
			});
		}

		if (settings.panUp) {
			settings.panUp.bind('mousedown.panZoom', eventData, function(event) {
				event.preventDefault(); event.data.target.panZoom('mouseDown', 'panUp');
			}).bind('mouseleave.panZoom mouseup.panZoom', eventData, function(event) {
				event.preventDefault(); event.data.target.panZoom('mouseUp');
			});
		}

		if (settings.panDown) {
			settings.panDown.bind('mousedown.panZoom', eventData, function(event) {
				event.preventDefault(); event.data.target.panZoom('mouseDown', 'panDown');
			}).bind('mouseleave.panZoom mouseup.panZoom', eventData, function(event) {
				event.preventDefault(); event.data.target.panZoom('mouseUp');
			});
		}

		if (settings.panLeft) {
			settings.panLeft.bind('mousedown.panZoom', eventData, function(event) {
				event.preventDefault(); event.data.target.panZoom('mouseDown', 'panLeft');
			}).bind('mouseleave.panZoom mouseup.panZoom', eventData, function(event) {
				event.preventDefault(); event.data.target.panZoom('mouseUp');
			});
		}

		if (settings.panRight) {
			settings.panRight.bind('mousedown.panZoom', eventData, function(event) {
				event.preventDefault(); event.data.target.panZoom('mouseDown', 'panRight');
			}).bind('mouseleave.panZoom mouseup.panZoom', eventData, function(event) {
				event.preventDefault(); event.data.target.panZoom('mouseUp');
			});
		}

		if (settings.fit) { settings.fit.bind('click.panZoom', eventData, function(event) { event.preventDefault(); event.data.target.panZoom('fit'); } ); }

		// double click
		if (settings.double_click) {
			this.bind('dblclick.panZoom', eventData, function(event, delta) { event.data.target.panZoom('zoomIn') } );
		}

		// mousewheel
		if (settings.mousewheel && typeof(this.mousewheel) == 'function') {
			this.parent().mousewheel(function(event, delta) { event.preventDefault(); $(this).find('img').panZoom('mouseWheel', delta) } );
		} else if (settings.mousewheel) {
			alert('Mousewheel requires mousewheel from jQuery tools - please include jQuery tools or disable mousewheel to remove this warning.')
		}

		// direct form input
		if (settings.directedit) {
			$(settings.out_x1).add(settings.out_y1).add(settings.out_x2).add(settings.out_y2).bind('change.panZoom blur.panZoom', eventData, function(event) { event.data.target.panZoom('readPosition') } );
		}

		if (settings.draggable && typeof(this.draggable) == 'function') {
			this.draggable({
				stop: function () { $(this).panZoom('dragComplete');	}
			});
		}	else if (settings.draggable) {
				alert('Draggable requires jQuery UI - please include jQuery UI or disable draggable to remove this warning.')
		}

		// image load
		$(this).bind('load.panZoom', eventData, function (event) { event.data.target.panZoom('loadImage') })

	}

	function setupData() {
		this.data('panZoom', {
			target_element: this,
			target_dimensions: { x: null, y: null },
			viewport_element: this.parent(),
			viewport_dimensions: { x: this.parent().width(), y: this.parent().height() },
			position: { x1: null, y1: null, x2: null, y2: null },
			last_image: null,
			loaded: false,
			mousewheel_delta: 0,
			mousedown_interval: false
		});
		if (settings.debug) {
			console.log(this.data('panZoom'));
		}
	}

	function setupCSS() {
		if (this.parent().css('position') == 'static') {
			this.parent().css('position', 'relative');
		}
		this.css({
			'position': 'absolute',
			'top': 0,
			'left': 0
		});
		if (settings.draggable) {
			this.css({
				'cursor': 'move'
			});
		}
	}

	function validatePosition() {
		var data = this.data('panZoom');
		// if dimensions are too small...
		if ( data.position.x2 - data.position.x1 < settings.min_width/settings.factor || data.position.y2 - data.position.y1 < settings.min_height/settings.factor ) {
			// and second co-ords are zero (IE: no dims set), fit image
			if (data.position.x2 == 0 || data.position.y2 == 0) {
				methods.fit.apply(this);
			}
			// otherwise, backout a bit
			else {
				if (data.position.x2 - data.position.x1 < settings.min_width/settings.factor) {
					data.position.x2 = data.position.x1*1+settings.min_width/settings.factor;
				}
				if (data.position.y2 - data.position.y1 < settings.min_height/settings.factor) {
	  			data.position.y2 = data.position.y1*1+settings.min_height/settings.factor;
				}
			}
		}

		if (settings.aspect) {
			target = data.target_dimensions.ratio;
			current = getCurrentAspectRatio.apply(this)
			if (current > target) {
				new_width = getHeight.apply(this) * target;
				diff = getWidth.apply(this) - new_width;
				data.position.x1 = data.position.x1*1 + (diff/2);
				data.position.x2 = data.position.x2*1 - (diff/2);
			} else if (current < target) {
				new_height = getWidth.apply(this) / target;
				diff = getHeight.apply(this) - new_height;
				data.position.y1 = data.position.y1*1 + (diff/2);
				data.position.y2 = data.position.y2*1 - (diff/2);
			}
		}


	}

  function applyPosition() {
		var data = this.data('panZoom');

    width = getWidth.apply(this);
    height = getHeight.apply(this);
    left_offset = getLeftOffset.apply(this);
    top_offset = getTopOffset.apply(this);

		properties = {
			'top': Math.round(top_offset),
			'left': Math.round(left_offset),
			'width': Math.round(width),
			'height': Math.round(height)
		}

		if (data.loaded && settings.animate) {
			applyAnimate.apply(this, [ properties ]);
		} else {
			applyCSS.apply(this, [ properties ]);
		}

		if (settings.debug) {
			console.log('--');
			console.log('width:' + width);
			console.log('height:' + height);
			console.log('left:' + left_offset);
			console.log('top:' + top_offset);
		}
	}

	function applyCSS() {
		this.css(	properties );
	}

	function applyAnimate() {
		this.stop().animate(	properties , settings.animate_duration, settings.animate_easing);
	}

  function getWidth() {
		var data = this.data('panZoom');
    width = (data.position.x2 - data.position.x1);
    return width;
  }

  function getLeftOffset() {
		var data = this.data('panZoom');
    return data.position.x1;
  }

  function getHeight() {
		var data = this.data('panZoom');
		height = (data.position.y2 - data.position.y1);
    return height;
  }

  function getTopOffset() {
		var data = this.data('panZoom');
		top_offset = data.position.y1;
    return top_offset;
  }

	function getCurrentAspectRatio() {
		return (getWidth.apply(this) / getHeight.apply(this));
	}

	function writePosition() {
		var data = this.data('panZoom');
 		if (settings.out_x1) { settings.out_x1.val(Math.round(data.position.x1 / settings.factor)) }
 		if (settings.out_y1) { settings.out_y1.val(Math.round(data.position.y1 / settings.factor)) }
 		if (settings.out_x2) { settings.out_x2.val(Math.round(data.position.x2 / settings.factor)) }
 		if (settings.out_y2) { settings.out_y2.val(Math.round(data.position.y2 / settings.factor)) }
	}

	function getStepDimensions() {
		var data = this.data('panZoom');
		ret = {
			zoom: {
				x: (settings.zoom_step/100 * data.viewport_dimensions.x),
				y: (settings.zoom_step/100 * data.viewport_dimensions.y)
			},
			pan: {
				x: (settings.pan_step/100 * data.viewport_dimensions.x),
				y: (settings.pan_step/100 * data.viewport_dimensions.y)
			}
		}
		return ret;
	}

	function loadTargetDimensions() {
		var data = this.data('panZoom');
		var img = document.createElement('img');
    img.src = this.attr('src');
    img.id = "jqpz-temp";
    $('body').append(img);
    data.target_dimensions.x = $('#jqpz-temp').width();
		data.target_dimensions.y = $('#jqpz-temp').height();
    $('#jqpz-temp').remove();
    data.target_dimensions.ratio = data.target_dimensions.x / data.target_dimensions.y;
	}

})( jQuery );/*
 * jQuery Tools 1.2.5 - The missing UI library for the Web
 *
 * [toolbox.flashembed, toolbox.history, toolbox.expose, toolbox.mousewheel, tabs, tabs.slideshow, tooltip, tooltip.slide, tooltip.dynamic, scrollable, scrollable.autoscroll, scrollable.navigator, overlay, overlay.apple, dateinput, rangeinput, validator]
 *
 * NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
 *
 * http://flowplayer.org/tools/
 *
 * jquery.event.wheel.js - rev 1
 * Copyright (c) 2008, Three Dub Media (http://threedubmedia.com)
 * Liscensed under the MIT License (MIT-LICENSE.txt)
 * http://www.opensource.org/licenses/mit-license.php
 * Created: 2008-07-01 | Updated: 2008-07-14
 *
 * -----
 *
 * File generated: Wed Sep 22 06:12:53 GMT 2010
 */
(function(){function f(a,b){if(b)for(var c in b)if(b.hasOwnProperty(c))a[c]=b[c];return a}function l(a,b){var c=[];for(var d in a)if(a.hasOwnProperty(d))c[d]=b(a[d]);return c}function m(a,b,c){if(e.isSupported(b.version))a.innerHTML=e.getHTML(b,c);else if(b.expressInstall&&e.isSupported([6,65]))a.innerHTML=e.getHTML(f(b,{src:b.expressInstall}),{MMredirectURL:location.href,MMplayerType:"PlugIn",MMdoctitle:document.title});else{if(!a.innerHTML.replace(/\s/g,"")){a.innerHTML="<h2>Flash version "+b.version+
" or greater is required</h2><h3>"+(g[0]>0?"Your version is "+g:"You have no flash plugin installed")+"</h3>"+(a.tagName=="A"?"<p>Click here to download latest version</p>":"<p>Download latest version from <a href='"+k+"'>here</a></p>");if(a.tagName=="A")a.onclick=function(){location.href=k}}if(b.onFail){var d=b.onFail.call(this);if(typeof d=="string")a.innerHTML=d}}if(i)window[b.id]=document.getElementById(b.id);f(this,{getRoot:function(){return a},getOptions:function(){return b},getConf:function(){return c},
getApi:function(){return a.firstChild}})}var i=document.all,k="http://www.adobe.com/go/getflashplayer",n=typeof jQuery=="function",o=/(\d+)[^\d]+(\d+)[^\d]*(\d*)/,j={width:"100%",height:"100%",id:"_"+(""+Math.random()).slice(9),allowfullscreen:true,allowscriptaccess:"always",quality:"high",version:[3,0],onFail:null,expressInstall:null,w3c:false,cachebusting:false};window.attachEvent&&window.attachEvent("onbeforeunload",function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){}});
window.flashembed=function(a,b,c){if(typeof a=="string")a=document.getElementById(a.replace("#",""));if(a){if(typeof b=="string")b={src:b};return new m(a,f(f({},j),b),c)}};var e=f(window.flashembed,{conf:j,getVersion:function(){var a,b;try{b=navigator.plugins["Shockwave Flash"].description.slice(16)}catch(c){try{b=(a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7"))&&a.GetVariable("$version")}catch(d){try{b=(a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6"))&&a.GetVariable("$version")}catch(h){}}}return(b=
o.exec(b))?[b[1],b[3]]:[0,0]},asString:function(a){if(a===null||a===undefined)return null;var b=typeof a;if(b=="object"&&a.push)b="array";switch(b){case "string":a=a.replace(new RegExp('(["\\\\])',"g"),"\\$1");a=a.replace(/^\s?(\d+\.?\d+)%/,"$1pct");return'"'+a+'"';case "array":return"["+l(a,function(d){return e.asString(d)}).join(",")+"]";case "function":return'"function()"';case "object":b=[];for(var c in a)a.hasOwnProperty(c)&&b.push('"'+c+'":'+e.asString(a[c]));return"{"+b.join(",")+"}"}return String(a).replace(/\s/g,
" ").replace(/\'/g,'"')},getHTML:function(a,b){a=f({},a);var c='<object width="'+a.width+'" height="'+a.height+'" id="'+a.id+'" name="'+a.id+'"';if(a.cachebusting)a.src+=(a.src.indexOf("?")!=-1?"&":"?")+Math.random();c+=a.w3c||!i?' data="'+a.src+'" type="application/x-shockwave-flash"':' classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"';c+=">";if(a.w3c||i)c+='<param name="movie" value="'+a.src+'" />';a.width=a.height=a.id=a.w3c=a.src=null;a.onFail=a.version=a.expressInstall=null;for(var d in a)if(a[d])c+=
'<param name="'+d+'" value="'+a[d]+'" />';a="";if(b){for(var h in b)if(b[h]){d=b[h];a+=h+"="+(/function|object/.test(typeof d)?e.asString(d):d)+"&"}a=a.slice(0,-1);c+='<param name="flashvars" value=\''+a+"' />"}c+="</object>";return c},isSupported:function(a){return g[0]>a[0]||g[0]==a[0]&&g[1]>=a[1]}}),g=e.getVersion();if(n){jQuery.tools=jQuery.tools||{version:"1.2.5"};jQuery.tools.flashembed={conf:j};jQuery.fn.flashembed=function(a,b){return this.each(function(){$(this).data("flashembed",flashembed(this,
a,b))})}}})();
(function(b){function h(c){if(c){var a=d.contentWindow.document;a.open().close();a.location.hash=c}}var g,d,f,i;b.tools=b.tools||{version:"1.2.5"};b.tools.history={init:function(c){if(!i){if(b.browser.msie&&b.browser.version<"8"){if(!d){d=b("<iframe/>").attr("src","javascript:false;").hide().get(0);b("body").append(d);setInterval(function(){var a=d.contentWindow.document;a=a.location.hash;g!==a&&b.event.trigger("hash",a)},100);h(location.hash||"#")}}else setInterval(function(){var a=location.hash;
a!==g&&b.event.trigger("hash",a)},100);f=!f?c:f.add(c);c.click(function(a){var e=b(this).attr("href");d&&h(e);if(e.slice(0,1)!="#"){location.href="#"+e;return a.preventDefault()}});i=true}}};b(window).bind("hash",function(c,a){a?f.filter(function(){var e=b(this).attr("href");return e==a||e==a.replace("#","")}).trigger("history",[a]):f.eq(0).trigger("history",[a]);g=a});b.fn.history=function(c){b.tools.history.init(this);return this.bind("history",c)}})(jQuery);
(function(b){function k(){if(b.browser.msie){var a=b(document).height(),d=b(window).height();return[window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth,a-d<20?d:a]}return[b(document).width(),b(document).height()]}function h(a){if(a)return a.call(b.mask)}b.tools=b.tools||{version:"1.2.5"};var l;l=b.tools.expose={conf:{maskId:"exposeMask",loadSpeed:"slow",closeSpeed:"fast",closeOnClick:true,closeOnEsc:true,zIndex:9998,opacity:0.8,startOpacity:0,color:"#fff",onLoad:null,
onClose:null}};var c,i,e,g,j;b.mask={load:function(a,d){if(e)return this;if(typeof a=="string")a={color:a};a=a||g;g=a=b.extend(b.extend({},l.conf),a);c=b("#"+a.maskId);if(!c.length){c=b("<div/>").attr("id",a.maskId);b("body").append(c)}var m=k();c.css({position:"absolute",top:0,left:0,width:m[0],height:m[1],display:"none",opacity:a.startOpacity,zIndex:a.zIndex});a.color&&c.css("backgroundColor",a.color);if(h(a.onBeforeLoad)===false)return this;a.closeOnEsc&&b(document).bind("keydown.mask",function(f){f.keyCode==
27&&b.mask.close(f)});a.closeOnClick&&c.bind("click.mask",function(f){b.mask.close(f)});b(window).bind("resize.mask",function(){b.mask.fit()});if(d&&d.length){j=d.eq(0).css("zIndex");b.each(d,function(){var f=b(this);/relative|absolute|fixed/i.test(f.css("position"))||f.css("position","relative")});i=d.css({zIndex:Math.max(a.zIndex+1,j=="auto"?0:j)})}c.css({display:"block"}).fadeTo(a.loadSpeed,a.opacity,function(){b.mask.fit();h(a.onLoad);e="full"});e=true;return this},close:function(){if(e){if(h(g.onBeforeClose)===
false)return this;c.fadeOut(g.closeSpeed,function(){h(g.onClose);i&&i.css({zIndex:j});e=false});b(document).unbind("keydown.mask");c.unbind("click.mask");b(window).unbind("resize.mask")}return this},fit:function(){if(e){var a=k();c.css({width:a[0],height:a[1]})}},getMask:function(){return c},isLoaded:function(a){return a?e=="full":e},getConf:function(){return g},getExposed:function(){return i}};b.fn.mask=function(a){b.mask.load(a);return this};b.fn.expose=function(a){b.mask.load(a,this);return this}})(jQuery);
(function(b){function c(a){switch(a.type){case "mousemove":return b.extend(a.data,{clientX:a.clientX,clientY:a.clientY,pageX:a.pageX,pageY:a.pageY});case "DOMMouseScroll":b.extend(a,a.data);a.delta=-a.detail/3;break;case "mousewheel":a.delta=a.wheelDelta/120;break}a.type="wheel";return b.event.handle.call(this,a,a.delta)}b.fn.mousewheel=function(a){return this[a?"bind":"trigger"]("wheel",a)};b.event.special.wheel={setup:function(){b.event.add(this,d,c,{})},teardown:function(){b.event.remove(this,
d,c)}};var d=!b.browser.mozilla?"mousewheel":"DOMMouseScroll"+(b.browser.version<"1.9"?" mousemove":"")})(jQuery);
(function(c){function p(d,b,a){var e=this,l=d.add(this),h=d.find(a.tabs),i=b.jquery?b:d.children(b),j;h.length||(h=d.children());i.length||(i=d.parent().find(b));i.length||(i=c(b));c.extend(this,{click:function(f,g){var k=h.eq(f);if(typeof f=="string"&&f.replace("#","")){k=h.filter("[href*="+f.replace("#","")+"]");f=Math.max(h.index(k),0)}if(a.rotate){var n=h.length-1;if(f<0)return e.click(n,g);if(f>n)return e.click(0,g)}if(!k.length){if(j>=0)return e;f=a.initialIndex;k=h.eq(f)}if(f===j)return e;
g=g||c.Event();g.type="onBeforeClick";l.trigger(g,[f]);if(!g.isDefaultPrevented()){o[a.effect].call(e,f,function(){g.type="onClick";l.trigger(g,[f])});j=f;h.removeClass(a.current);k.addClass(a.current);return e}},getConf:function(){return a},getTabs:function(){return h},getPanes:function(){return i},getCurrentPane:function(){return i.eq(j)},getCurrentTab:function(){return h.eq(j)},getIndex:function(){return j},next:function(){return e.click(j+1)},prev:function(){return e.click(j-1)},destroy:function(){h.unbind(a.event).removeClass(a.current);
i.find("a[href^=#]").unbind("click.T");return e}});c.each("onBeforeClick,onClick".split(","),function(f,g){c.isFunction(a[g])&&c(e).bind(g,a[g]);e[g]=function(k){k&&c(e).bind(g,k);return e}});if(a.history&&c.fn.history){c.tools.history.init(h);a.event="history"}h.each(function(f){c(this).bind(a.event,function(g){e.click(f,g);return g.preventDefault()})});i.find("a[href^=#]").bind("click.T",function(f){e.click(c(this).attr("href"),f)});if(location.hash&&a.tabs=="a"&&d.find("[href="+location.hash+"]").length)e.click(location.hash);
else if(a.initialIndex===0||a.initialIndex>0)e.click(a.initialIndex)}c.tools=c.tools||{version:"1.2.5"};c.tools.tabs={conf:{tabs:"a",current:"current",onBeforeClick:null,onClick:null,effect:"default",initialIndex:0,event:"click",rotate:false,history:false},addEffect:function(d,b){o[d]=b}};var o={"default":function(d,b){this.getPanes().hide().eq(d).show();b.call()},fade:function(d,b){var a=this.getConf(),e=a.fadeOutSpeed,l=this.getPanes();e?l.fadeOut(e):l.hide();l.eq(d).fadeIn(a.fadeInSpeed,b)},slide:function(d,
b){this.getPanes().slideUp(200);this.getPanes().eq(d).slideDown(400,b)},ajax:function(d,b){this.getPanes().eq(0).load(this.getTabs().eq(d).attr("href"),b)}},m;c.tools.tabs.addEffect("horizontal",function(d,b){m||(m=this.getPanes().eq(0).width());this.getCurrentPane().animate({width:0},function(){c(this).hide()});this.getPanes().eq(d).animate({width:m},function(){c(this).show();b.call()})});c.fn.tabs=function(d,b){var a=this.data("tabs");if(a){a.destroy();this.removeData("tabs")}if(c.isFunction(b))b=
{onBeforeClick:b};b=c.extend({},c.tools.tabs.conf,b);this.each(function(){a=new p(c(this),d,b);c(this).data("tabs",a)});return b.api?a:this}})(jQuery);
(function(c){function p(g,a){function m(f){var e=c(f);return e.length<2?e:g.parent().find(f)}var b=this,i=g.add(this),d=g.data("tabs"),h,j=true,n=m(a.next).click(function(){d.next()}),k=m(a.prev).click(function(){d.prev()});c.extend(b,{getTabs:function(){return d},getConf:function(){return a},play:function(){if(h)return b;var f=c.Event("onBeforePlay");i.trigger(f);if(f.isDefaultPrevented())return b;h=setInterval(d.next,a.interval);j=false;i.trigger("onPlay");return b},pause:function(){if(!h)return b;
var f=c.Event("onBeforePause");i.trigger(f);if(f.isDefaultPrevented())return b;h=clearInterval(h);i.trigger("onPause");return b},stop:function(){b.pause();j=true}});c.each("onBeforePlay,onPlay,onBeforePause,onPause".split(","),function(f,e){c.isFunction(a[e])&&c(b).bind(e,a[e]);b[e]=function(q){return c(b).bind(e,q)}});a.autopause&&d.getTabs().add(n).add(k).add(d.getPanes()).hover(b.pause,function(){j||b.play()});a.autoplay&&b.play();a.clickable&&d.getPanes().click(function(){d.next()});if(!d.getConf().rotate){var l=
a.disabledClass;d.getIndex()||k.addClass(l);d.onBeforeClick(function(f,e){k.toggleClass(l,!e);n.toggleClass(l,e==d.getTabs().length-1)})}}var o;o=c.tools.tabs.slideshow={conf:{next:".forward",prev:".backward",disabledClass:"disabled",autoplay:false,autopause:true,interval:3E3,clickable:true,api:false}};c.fn.slideshow=function(g){var a=this.data("slideshow");if(a)return a;g=c.extend({},o.conf,g);this.each(function(){a=new p(c(this),g);c(this).data("slideshow",a)});return g.api?a:this}})(jQuery);
(function(f){function p(a,b,c){var h=c.relative?a.position().top:a.offset().top,d=c.relative?a.position().left:a.offset().left,i=c.position[0];h-=b.outerHeight()-c.offset[0];d+=a.outerWidth()+c.offset[1];if(/iPad/i.test(navigator.userAgent))h-=f(window).scrollTop();var j=b.outerHeight()+a.outerHeight();if(i=="center")h+=j/2;if(i=="bottom")h+=j;i=c.position[1];a=b.outerWidth()+a.outerWidth();if(i=="center")d-=a/2;if(i=="left")d-=a;return{top:h,left:d}}function u(a,b){var c=this,h=a.add(c),d,i=0,j=
0,m=a.attr("title"),q=a.attr("data-tooltip"),r=o[b.effect],l,s=a.is(":input"),v=s&&a.is(":checkbox, :radio, select, :button, :submit"),t=a.attr("type"),k=b.events[t]||b.events[s?v?"widget":"input":"def"];if(!r)throw'Nonexistent effect "'+b.effect+'"';k=k.split(/,\s*/);if(k.length!=2)throw"Tooltip: bad events configuration for "+t;a.bind(k[0],function(e){clearTimeout(i);if(b.predelay)j=setTimeout(function(){c.show(e)},b.predelay);else c.show(e)}).bind(k[1],function(e){clearTimeout(j);if(b.delay)i=
setTimeout(function(){c.hide(e)},b.delay);else c.hide(e)});if(m&&b.cancelDefault){a.removeAttr("title");a.data("title",m)}f.extend(c,{show:function(e){if(!d){if(q)d=f(q);else if(b.tip)d=f(b.tip).eq(0);else if(m)d=f(b.layout).addClass(b.tipClass).appendTo(document.body).hide().append(m);else{d=a.next();d.length||(d=a.parent().next())}if(!d.length)throw"Cannot find tooltip for "+a;}if(c.isShown())return c;d.stop(true,true);var g=p(a,d,b);b.tip&&d.html(a.data("title"));e=e||f.Event();e.type="onBeforeShow";
h.trigger(e,[g]);if(e.isDefaultPrevented())return c;g=p(a,d,b);d.css({position:"absolute",top:g.top,left:g.left});l=true;r[0].call(c,function(){e.type="onShow";l="full";h.trigger(e)});g=b.events.tooltip.split(/,\s*/);if(!d.data("__set")){d.bind(g[0],function(){clearTimeout(i);clearTimeout(j)});g[1]&&!a.is("input:not(:checkbox, :radio), textarea")&&d.bind(g[1],function(n){n.relatedTarget!=a[0]&&a.trigger(k[1].split(" ")[0])});d.data("__set",true)}return c},hide:function(e){if(!d||!c.isShown())return c;
e=e||f.Event();e.type="onBeforeHide";h.trigger(e);if(!e.isDefaultPrevented()){l=false;o[b.effect][1].call(c,function(){e.type="onHide";h.trigger(e)});return c}},isShown:function(e){return e?l=="full":l},getConf:function(){return b},getTip:function(){return d},getTrigger:function(){return a}});f.each("onHide,onBeforeShow,onShow,onBeforeHide".split(","),function(e,g){f.isFunction(b[g])&&f(c).bind(g,b[g]);c[g]=function(n){n&&f(c).bind(g,n);return c}})}f.tools=f.tools||{version:"1.2.5"};f.tools.tooltip=
{conf:{effect:"toggle",fadeOutSpeed:"fast",predelay:0,delay:30,opacity:1,tip:0,position:["top","center"],offset:[0,0],relative:false,cancelDefault:true,events:{def:"mouseenter,mouseleave",input:"focus,blur",widget:"focus mouseenter,blur mouseleave",tooltip:"mouseenter,mouseleave"},layout:"<div/>",tipClass:"tooltip"},addEffect:function(a,b,c){o[a]=[b,c]}};var o={toggle:[function(a){var b=this.getConf(),c=this.getTip();b=b.opacity;b<1&&c.css({opacity:b});c.show();a.call()},function(a){this.getTip().hide();
a.call()}],fade:[function(a){var b=this.getConf();this.getTip().fadeTo(b.fadeInSpeed,b.opacity,a)},function(a){this.getTip().fadeOut(this.getConf().fadeOutSpeed,a)}]};f.fn.tooltip=function(a){var b=this.data("tooltip");if(b)return b;a=f.extend(true,{},f.tools.tooltip.conf,a);if(typeof a.position=="string")a.position=a.position.split(/,?\s/);this.each(function(){b=new u(f(this),a);f(this).data("tooltip",b)});return a.api?b:this}})(jQuery);
(function(d){var i=d.tools.tooltip;d.extend(i.conf,{direction:"up",bounce:false,slideOffset:10,slideInSpeed:200,slideOutSpeed:200,slideFade:!d.browser.msie});var e={up:["-","top"],down:["+","top"],left:["-","left"],right:["+","left"]};i.addEffect("slide",function(g){var a=this.getConf(),f=this.getTip(),b=a.slideFade?{opacity:a.opacity}:{},c=e[a.direction]||e.up;b[c[1]]=c[0]+"="+a.slideOffset;a.slideFade&&f.css({opacity:0});f.show().animate(b,a.slideInSpeed,g)},function(g){var a=this.getConf(),f=a.slideOffset,
b=a.slideFade?{opacity:0}:{},c=e[a.direction]||e.up,h=""+c[0];if(a.bounce)h=h=="+"?"-":"+";b[c[1]]=h+"="+f;this.getTip().animate(b,a.slideOutSpeed,function(){d(this).hide();g.call()})})})(jQuery);
(function(g){function j(a){var c=g(window),d=c.width()+c.scrollLeft(),h=c.height()+c.scrollTop();return[a.offset().top<=c.scrollTop(),d<=a.offset().left+a.width(),h<=a.offset().top+a.height(),c.scrollLeft()>=a.offset().left]}function k(a){for(var c=a.length;c--;)if(a[c])return false;return true}var i=g.tools.tooltip;i.dynamic={conf:{classNames:"top right bottom left"}};g.fn.dynamic=function(a){if(typeof a=="number")a={speed:a};a=g.extend({},i.dynamic.conf,a);var c=a.classNames.split(/\s/),d;this.each(function(){var h=
g(this).tooltip().onBeforeShow(function(e,f){e=this.getTip();var b=this.getConf();d||(d=[b.position[0],b.position[1],b.offset[0],b.offset[1],g.extend({},b)]);g.extend(b,d[4]);b.position=[d[0],d[1]];b.offset=[d[2],d[3]];e.css({visibility:"hidden",position:"absolute",top:f.top,left:f.left}).show();f=j(e);if(!k(f)){if(f[2]){g.extend(b,a.top);b.position[0]="top";e.addClass(c[0])}if(f[3]){g.extend(b,a.right);b.position[1]="right";e.addClass(c[1])}if(f[0]){g.extend(b,a.bottom);b.position[0]="bottom";e.addClass(c[2])}if(f[1]){g.extend(b,
a.left);b.position[1]="left";e.addClass(c[3])}if(f[0]||f[2])b.offset[0]*=-1;if(f[1]||f[3])b.offset[1]*=-1}e.css({visibility:"visible"}).hide()});h.onBeforeShow(function(){var e=this.getConf();this.getTip();setTimeout(function(){e.position=[d[0],d[1]];e.offset=[d[2],d[3]]},0)});h.onHide(function(){var e=this.getTip();e.removeClass(a.classNames)});ret=h});return a.api?ret:this}})(jQuery);
(function(e){function p(f,c){var b=e(c);return b.length<2?b:f.parent().find(c)}function u(f,c){var b=this,n=f.add(b),g=f.children(),l=0,j=c.vertical;k||(k=b);if(g.length>1)g=e(c.items,f);e.extend(b,{getConf:function(){return c},getIndex:function(){return l},getSize:function(){return b.getItems().size()},getNaviButtons:function(){return o.add(q)},getRoot:function(){return f},getItemWrap:function(){return g},getItems:function(){return g.children(c.item).not("."+c.clonedClass)},move:function(a,d){return b.seekTo(l+
a,d)},next:function(a){return b.move(1,a)},prev:function(a){return b.move(-1,a)},begin:function(a){return b.seekTo(0,a)},end:function(a){return b.seekTo(b.getSize()-1,a)},focus:function(){return k=b},addItem:function(a){a=e(a);if(c.circular){g.children("."+c.clonedClass+":last").before(a);g.children("."+c.clonedClass+":first").replaceWith(a.clone().addClass(c.clonedClass))}else g.append(a);n.trigger("onAddItem",[a]);return b},seekTo:function(a,d,h){a.jquery||(a*=1);if(c.circular&&a===0&&l==-1&&d!==
0)return b;if(!c.circular&&a<0||a>b.getSize()||a<-1)return b;var i=a;if(a.jquery)a=b.getItems().index(a);else i=b.getItems().eq(a);var r=e.Event("onBeforeSeek");if(!h){n.trigger(r,[a,d]);if(r.isDefaultPrevented()||!i.length)return b}i=j?{top:-i.position().top}:{left:-i.position().left};l=a;k=b;if(d===undefined)d=c.speed;g.animate(i,d,c.easing,h||function(){n.trigger("onSeek",[a])});return b}});e.each(["onBeforeSeek","onSeek","onAddItem"],function(a,d){e.isFunction(c[d])&&e(b).bind(d,c[d]);b[d]=function(h){h&&
e(b).bind(d,h);return b}});if(c.circular){var s=b.getItems().slice(-1).clone().prependTo(g),t=b.getItems().eq(1).clone().appendTo(g);s.add(t).addClass(c.clonedClass);b.onBeforeSeek(function(a,d,h){if(!a.isDefaultPrevented())if(d==-1){b.seekTo(s,h,function(){b.end(0)});return a.preventDefault()}else d==b.getSize()&&b.seekTo(t,h,function(){b.begin(0)})});b.seekTo(0,0,function(){})}var o=p(f,c.prev).click(function(){b.prev()}),q=p(f,c.next).click(function(){b.next()});if(!c.circular&&b.getSize()>1){b.onBeforeSeek(function(a,
d){setTimeout(function(){if(!a.isDefaultPrevented()){o.toggleClass(c.disabledClass,d<=0);q.toggleClass(c.disabledClass,d>=b.getSize()-1)}},1)});c.initialIndex||o.addClass(c.disabledClass)}c.mousewheel&&e.fn.mousewheel&&f.mousewheel(function(a,d){if(c.mousewheel){b.move(d<0?1:-1,c.wheelSpeed||50);return false}});if(c.touch){var m={};g[0].ontouchstart=function(a){a=a.touches[0];m.x=a.clientX;m.y=a.clientY};g[0].ontouchmove=function(a){if(a.touches.length==1&&!g.is(":animated")){var d=a.touches[0],h=
m.x-d.clientX;d=m.y-d.clientY;b[j&&d>0||!j&&h>0?"next":"prev"]();a.preventDefault()}}}c.keyboard&&e(document).bind("keydown.scrollable",function(a){if(!(!c.keyboard||a.altKey||a.ctrlKey||e(a.target).is(":input")))if(!(c.keyboard!="static"&&k!=b)){var d=a.keyCode;if(j&&(d==38||d==40)){b.move(d==38?-1:1);return a.preventDefault()}if(!j&&(d==37||d==39)){b.move(d==37?-1:1);return a.preventDefault()}}});c.initialIndex&&b.seekTo(c.initialIndex,0,function(){})}e.tools=e.tools||{version:"1.2.5"};e.tools.scrollable=
{conf:{activeClass:"active",circular:false,clonedClass:"cloned",disabledClass:"disabled",easing:"swing",initialIndex:0,item:null,items:".items",keyboard:true,mousewheel:false,next:".next",prev:".prev",speed:400,vertical:false,touch:true,wheelSpeed:0}};var k;e.fn.scrollable=function(f){var c=this.data("scrollable");if(c)return c;f=e.extend({},e.tools.scrollable.conf,f);this.each(function(){c=new u(e(this),f);e(this).data("scrollable",c)});return f.api?c:this}})(jQuery);
(function(b){var f=b.tools.scrollable;f.autoscroll={conf:{autoplay:true,interval:3E3,autopause:true}};b.fn.autoscroll=function(c){if(typeof c=="number")c={interval:c};var d=b.extend({},f.autoscroll.conf,c),g;this.each(function(){var a=b(this).data("scrollable");if(a)g=a;var e,h=true;a.play=function(){if(!e){h=false;e=setInterval(function(){a.next()},d.interval)}};a.pause=function(){e=clearInterval(e)};a.stop=function(){a.pause();h=true};d.autopause&&a.getRoot().add(a.getNaviButtons()).hover(a.pause,
a.play);d.autoplay&&a.play()});return d.api?g:this}})(jQuery);
(function(d){function p(b,g){var h=d(g);return h.length<2?h:b.parent().find(g)}var m=d.tools.scrollable;m.navigator={conf:{navi:".navi",naviItem:null,activeClass:"active",indexed:false,idPrefix:null,history:false}};d.fn.navigator=function(b){if(typeof b=="string")b={navi:b};b=d.extend({},m.navigator.conf,b);var g;this.each(function(){function h(a,c,i){e.seekTo(c);if(j){if(location.hash)location.hash=a.attr("href").replace("#","")}else return i.preventDefault()}function f(){return k.find(b.naviItem||
"> *")}function n(a){var c=d("<"+(b.naviItem||"a")+"/>").click(function(i){h(d(this),a,i)}).attr("href","#"+a);a===0&&c.addClass(l);b.indexed&&c.text(a+1);b.idPrefix&&c.attr("id",b.idPrefix+a);return c.appendTo(k)}function o(a,c){a=f().eq(c.replace("#",""));a.length||(a=f().filter("[href="+c+"]"));a.click()}var e=d(this).data("scrollable"),k=b.navi.jquery?b.navi:p(e.getRoot(),b.navi),q=e.getNaviButtons(),l=b.activeClass,j=b.history&&d.fn.history;if(e)g=e;e.getNaviButtons=function(){return q.add(k)};
f().length?f().each(function(a){d(this).click(function(c){h(d(this),a,c)})}):d.each(e.getItems(),function(a){n(a)});e.onBeforeSeek(function(a,c){setTimeout(function(){if(!a.isDefaultPrevented()){var i=f().eq(c);!a.isDefaultPrevented()&&i.length&&f().removeClass(l).eq(c).addClass(l)}},1)});e.onAddItem(function(a,c){c=n(e.getItems().index(c));j&&c.history(o)});j&&f().history(o)});return b.api?g:this}})(jQuery);
(function(a){function t(d,b){var c=this,j=d.add(c),o=a(window),k,f,m,g=a.tools.expose&&(b.mask||b.expose),n=Math.random().toString().slice(10);if(g){if(typeof g=="string")g={color:g};g.closeOnClick=g.closeOnEsc=false}var p=b.target||d.attr("rel");f=p?a(p):d;if(!f.length)throw"Could not find Overlay: "+p;d&&d.index(f)==-1&&d.click(function(e){c.load(e);return e.preventDefault()});a.extend(c,{load:function(e){if(c.isOpened())return c;var h=q[b.effect];if(!h)throw'Overlay: cannot find effect : "'+b.effect+
'"';b.oneInstance&&a.each(s,function(){this.close(e)});e=e||a.Event();e.type="onBeforeLoad";j.trigger(e);if(e.isDefaultPrevented())return c;m=true;g&&a(f).expose(g);var i=b.top,r=b.left,u=f.outerWidth({margin:true}),v=f.outerHeight({margin:true});if(typeof i=="string")i=i=="center"?Math.max((o.height()-v)/2,0):parseInt(i,10)/100*o.height();if(r=="center")r=Math.max((o.width()-u)/2,0);h[0].call(c,{top:i,left:r},function(){if(m){e.type="onLoad";j.trigger(e)}});g&&b.closeOnClick&&a.mask.getMask().one("click",
c.close);b.closeOnClick&&a(document).bind("click."+n,function(l){a(l.target).parents(f).length||c.close(l)});b.closeOnEsc&&a(document).bind("keydown."+n,function(l){l.keyCode==27&&c.close(l)});return c},close:function(e){if(!c.isOpened())return c;e=e||a.Event();e.type="onBeforeClose";j.trigger(e);if(!e.isDefaultPrevented()){m=false;q[b.effect][1].call(c,function(){e.type="onClose";j.trigger(e)});a(document).unbind("click."+n).unbind("keydown."+n);g&&a.mask.close();return c}},getOverlay:function(){return f},
getTrigger:function(){return d},getClosers:function(){return k},isOpened:function(){return m},getConf:function(){return b}});a.each("onBeforeLoad,onStart,onLoad,onBeforeClose,onClose".split(","),function(e,h){a.isFunction(b[h])&&a(c).bind(h,b[h]);c[h]=function(i){i&&a(c).bind(h,i);return c}});k=f.find(b.close||".close");if(!k.length&&!b.close){k=a('<a class="close"></a>');f.prepend(k)}k.click(function(e){c.close(e)});b.load&&c.load()}a.tools=a.tools||{version:"1.2.5"};a.tools.overlay={addEffect:function(d,
b,c){q[d]=[b,c]},conf:{close:null,closeOnClick:true,closeOnEsc:true,closeSpeed:"fast",effect:"default",fixed:!a.browser.msie||a.browser.version>6,left:"center",load:false,mask:null,oneInstance:true,speed:"normal",target:null,top:"10%"}};var s=[],q={};a.tools.overlay.addEffect("default",function(d,b){var c=this.getConf(),j=a(window);if(!c.fixed){d.top+=j.scrollTop();d.left+=j.scrollLeft()}d.position=c.fixed?"fixed":"absolute";this.getOverlay().css(d).fadeIn(c.speed,b)},function(d){this.getOverlay().fadeOut(this.getConf().closeSpeed,
d)});a.fn.overlay=function(d){var b=this.data("overlay");if(b)return b;if(a.isFunction(d))d={onBeforeLoad:d};d=a.extend(true,{},a.tools.overlay.conf,d);this.each(function(){b=new t(a(this),d);s.push(b);a(this).data("overlay",b)});return d.api?b:this}})(jQuery);
(function(h){function k(d){var e=d.offset();return{top:e.top+d.height()/2,left:e.left+d.width()/2}}var l=h.tools.overlay,f=h(window);h.extend(l.conf,{start:{top:null,left:null},fadeInSpeed:"fast",zIndex:9999});function o(d,e){var a=this.getOverlay(),c=this.getConf(),g=this.getTrigger(),p=this,m=a.outerWidth({margin:true}),b=a.data("img"),n=c.fixed?"fixed":"absolute";if(!b){b=a.css("backgroundImage");if(!b)throw"background-image CSS property not set for overlay";b=b.slice(b.indexOf("(")+1,b.indexOf(")")).replace(/\"/g,
"");a.css("backgroundImage","none");b=h('<img src="'+b+'"/>');b.css({border:0,display:"none"}).width(m);h("body").append(b);a.data("img",b)}var i=c.start.top||Math.round(f.height()/2),j=c.start.left||Math.round(f.width()/2);if(g){g=k(g);i=g.top;j=g.left}if(c.fixed){i-=f.scrollTop();j-=f.scrollLeft()}else{d.top+=f.scrollTop();d.left+=f.scrollLeft()}b.css({position:"absolute",top:i,left:j,width:0,zIndex:c.zIndex}).show();d.position=n;a.css(d);b.animate({top:a.css("top"),left:a.css("left"),width:m},
c.speed,function(){a.css("zIndex",c.zIndex+1).fadeIn(c.fadeInSpeed,function(){p.isOpened()&&!h(this).index(a)?e.call():a.hide()})}).css("position",n)}function q(d){var e=this.getOverlay().hide(),a=this.getConf(),c=this.getTrigger();e=e.data("img");var g={top:a.start.top,left:a.start.left,width:0};c&&h.extend(g,k(c));a.fixed&&e.css({position:"absolute"}).animate({top:"+="+f.scrollTop(),left:"+="+f.scrollLeft()},0);e.animate(g,a.closeSpeed,d)}l.addEffect("apple",o,q)})(jQuery);
(function(d){function R(a,c){return 32-(new Date(a,c,32)).getDate()}function S(a,c){a=""+a;for(c=c||2;a.length<c;)a="0"+a;return a}function T(a,c,j){var q=a.getDate(),h=a.getDay(),r=a.getMonth();a=a.getFullYear();var f={d:q,dd:S(q),ddd:B[j].shortDays[h],dddd:B[j].days[h],m:r+1,mm:S(r+1),mmm:B[j].shortMonths[r],mmmm:B[j].months[r],yy:String(a).slice(2),yyyy:a};c=c.replace(X,function(s){return s in f?f[s]:s.slice(1,s.length-1)});return Y.html(c).html()}function v(a){return parseInt(a,10)}function U(a,
c){return a.getFullYear()===c.getFullYear()&&a.getMonth()==c.getMonth()&&a.getDate()==c.getDate()}function C(a){if(a){if(a.constructor==Date)return a;if(typeof a=="string"){var c=a.split("-");if(c.length==3)return new Date(v(c[0]),v(c[1])-1,v(c[2]));if(!/^-?\d+$/.test(a))return;a=v(a)}c=new Date;c.setDate(c.getDate()+a);return c}}function Z(a,c){function j(b,e,g){n=b;D=b.getFullYear();E=b.getMonth();G=b.getDate();g=g||d.Event("api");g.type="change";H.trigger(g,[b]);if(!g.isDefaultPrevented()){a.val(T(b,
e.format,e.lang));a.data("date",b);h.hide(g)}}function q(b){b.type="onShow";H.trigger(b);d(document).bind("keydown.d",function(e){if(e.ctrlKey)return true;var g=e.keyCode;if(g==8){a.val("");return h.hide(e)}if(g==27)return h.hide(e);if(d(V).index(g)>=0){if(!w){h.show(e);return e.preventDefault()}var i=d("#"+f.weeks+" a"),t=d("."+f.focus),o=i.index(t);t.removeClass(f.focus);if(g==74||g==40)o+=7;else if(g==75||g==38)o-=7;else if(g==76||g==39)o+=1;else if(g==72||g==37)o-=1;if(o>41){h.addMonth();t=d("#"+
f.weeks+" a:eq("+(o-42)+")")}else if(o<0){h.addMonth(-1);t=d("#"+f.weeks+" a:eq("+(o+42)+")")}else t=i.eq(o);t.addClass(f.focus);return e.preventDefault()}if(g==34)return h.addMonth();if(g==33)return h.addMonth(-1);if(g==36)return h.today();if(g==13)d(e.target).is("select")||d("."+f.focus).click();return d([16,17,18,9]).index(g)>=0});d(document).bind("click.d",function(e){var g=e.target;if(!d(g).parents("#"+f.root).length&&g!=a[0]&&(!L||g!=L[0]))h.hide(e)})}var h=this,r=new Date,f=c.css,s=B[c.lang],
k=d("#"+f.root),M=k.find("#"+f.title),L,I,J,D,E,G,n=a.attr("data-value")||c.value||a.val(),m=a.attr("min")||c.min,p=a.attr("max")||c.max,w;if(m===0)m="0";n=C(n)||r;m=C(m||c.yearRange[0]*365);p=C(p||c.yearRange[1]*365);if(!s)throw"Dateinput: invalid language: "+c.lang;if(a.attr("type")=="date"){var N=d("<input/>");d.each("class,disabled,id,maxlength,name,readonly,required,size,style,tabindex,title,value".split(","),function(b,e){N.attr(e,a.attr(e))});a.replaceWith(N);a=N}a.addClass(f.input);var H=
a.add(h);if(!k.length){k=d("<div><div><a/><div/><a/></div><div><div/><div/></div></div>").hide().css({position:"absolute"}).attr("id",f.root);k.children().eq(0).attr("id",f.head).end().eq(1).attr("id",f.body).children().eq(0).attr("id",f.days).end().eq(1).attr("id",f.weeks).end().end().end().find("a").eq(0).attr("id",f.prev).end().eq(1).attr("id",f.next);M=k.find("#"+f.head).find("div").attr("id",f.title);if(c.selectors){var z=d("<select/>").attr("id",f.month),A=d("<select/>").attr("id",f.year);M.html(z.add(A))}for(var $=
k.find("#"+f.days),O=0;O<7;O++)$.append(d("<span/>").text(s.shortDays[(O+c.firstDay)%7]));d("body").append(k)}if(c.trigger)L=d("<a/>").attr("href","#").addClass(f.trigger).click(function(b){h.show();return b.preventDefault()}).insertAfter(a);var K=k.find("#"+f.weeks);A=k.find("#"+f.year);z=k.find("#"+f.month);d.extend(h,{show:function(b){if(!(a.attr("readonly")||a.attr("disabled")||w)){b=b||d.Event();b.type="onBeforeShow";H.trigger(b);if(!b.isDefaultPrevented()){d.each(W,function(){this.hide()});
w=true;z.unbind("change").change(function(){h.setValue(A.val(),d(this).val())});A.unbind("change").change(function(){h.setValue(d(this).val(),z.val())});I=k.find("#"+f.prev).unbind("click").click(function(){I.hasClass(f.disabled)||h.addMonth(-1);return false});J=k.find("#"+f.next).unbind("click").click(function(){J.hasClass(f.disabled)||h.addMonth();return false});h.setValue(n);var e=a.offset();if(/iPad/i.test(navigator.userAgent))e.top-=d(window).scrollTop();k.css({top:e.top+a.outerHeight({margins:true})+
c.offset[0],left:e.left+c.offset[1]});if(c.speed)k.show(c.speed,function(){q(b)});else{k.show();q(b)}return h}}},setValue:function(b,e,g){var i=v(e)>=-1?new Date(v(b),v(e),v(g||1)):b||n;if(i<m)i=m;else if(i>p)i=p;b=i.getFullYear();e=i.getMonth();g=i.getDate();if(e==-1){e=11;b--}else if(e==12){e=0;b++}if(!w){j(i,c);return h}E=e;D=b;g=new Date(b,e,1-c.firstDay);g=g.getDay();var t=R(b,e),o=R(b,e-1),P;if(c.selectors){z.empty();d.each(s.months,function(x,F){m<new Date(b,x+1,-1)&&p>new Date(b,x,0)&&z.append(d("<option/>").html(F).attr("value",
x))});A.empty();i=r.getFullYear();for(var l=i+c.yearRange[0];l<i+c.yearRange[1];l++)m<=new Date(l+1,-1,1)&&p>new Date(l,0,0)&&A.append(d("<option/>").text(l));z.val(e);A.val(b)}else M.html(s.months[e]+" "+b);K.empty();I.add(J).removeClass(f.disabled);l=!g?-7:0;for(var u,y;l<(!g?35:42);l++){u=d("<a/>");if(l%7===0){P=d("<div/>").addClass(f.week);K.append(P)}if(l<g){u.addClass(f.off);y=o-g+l+1;i=new Date(b,e-1,y)}else if(l>=g+t){u.addClass(f.off);y=l-t-g+1;i=new Date(b,e+1,y)}else{y=l-g+1;i=new Date(b,
e,y);if(U(n,i))u.attr("id",f.current).addClass(f.focus);else U(r,i)&&u.attr("id",f.today)}m&&i<m&&u.add(I).addClass(f.disabled);p&&i>p&&u.add(J).addClass(f.disabled);u.attr("href","#"+y).text(y).data("date",i);P.append(u)}K.find("a").click(function(x){var F=d(this);if(!F.hasClass(f.disabled)){d("#"+f.current).removeAttr("id");F.attr("id",f.current);j(F.data("date"),c,x)}return false});f.sunday&&K.find(f.week).each(function(){var x=c.firstDay?7-c.firstDay:0;d(this).children().slice(x,x+1).addClass(f.sunday)});
return h},setMin:function(b,e){m=C(b);e&&n<m&&h.setValue(m);return h},setMax:function(b,e){p=C(b);e&&n>p&&h.setValue(p);return h},today:function(){return h.setValue(r)},addDay:function(b){return this.setValue(D,E,G+(b||1))},addMonth:function(b){return this.setValue(D,E+(b||1),G)},addYear:function(b){return this.setValue(D+(b||1),E,G)},hide:function(b){if(w){b=d.Event();b.type="onHide";H.trigger(b);d(document).unbind("click.d").unbind("keydown.d");if(b.isDefaultPrevented())return;k.hide();w=false}return h},
getConf:function(){return c},getInput:function(){return a},getCalendar:function(){return k},getValue:function(b){return b?T(n,b,c.lang):n},isOpen:function(){return w}});d.each(["onBeforeShow","onShow","change","onHide"],function(b,e){d.isFunction(c[e])&&d(h).bind(e,c[e]);h[e]=function(g){g&&d(h).bind(e,g);return h}});a.bind("focus click",h.show).keydown(function(b){var e=b.keyCode;if(!w&&d(V).index(e)>=0){h.show(b);return b.preventDefault()}return b.shiftKey||b.ctrlKey||b.altKey||e==9?true:b.preventDefault()});
C(a.val())&&j(n,c)}d.tools=d.tools||{version:"1.2.5"};var W=[],Q,V=[75,76,38,39,74,72,40,37],B={};Q=d.tools.dateinput={conf:{format:"mm/dd/yy",selectors:false,yearRange:[-5,5],lang:"en",offset:[0,0],speed:0,firstDay:0,min:undefined,max:undefined,trigger:false,css:{prefix:"cal",input:"date",root:0,head:0,title:0,prev:0,next:0,month:0,year:0,days:0,body:0,weeks:0,today:0,current:0,week:0,off:0,sunday:0,focus:0,disabled:0,trigger:0}},localize:function(a,c){d.each(c,function(j,q){c[j]=q.split(",")});
B[a]=c}};Q.localize("en",{months:"January,February,March,April,May,June,July,August,September,October,November,December",shortMonths:"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",days:"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday",shortDays:"Sun,Mon,Tue,Wed,Thu,Fri,Sat"});var X=/d{1,4}|m{1,4}|yy(?:yy)?|"[^"]*"|'[^']*'/g,Y=d("<a/>");d.expr[":"].date=function(a){var c=a.getAttribute("type");return c&&c=="date"||!!d(a).data("dateinput")};d.fn.dateinput=function(a){if(this.data("dateinput"))return this;
a=d.extend(true,{},Q.conf,a);d.each(a.css,function(j,q){if(!q&&j!="prefix")a.css[j]=(a.css.prefix||"")+(q||j)});var c;this.each(function(){var j=new Z(d(this),a);W.push(j);j=j.getInput().data("dateinput",j);c=c?c.add(j):j});return c?c:this}})(jQuery);
(function(e){function F(d,a){a=Math.pow(10,a);return Math.round(d*a)/a}function q(d,a){if(a=parseInt(d.css(a),10))return a;return(d=d[0].currentStyle)&&d.width&&parseInt(d.width,10)}function C(d){return(d=d.data("events"))&&d.onSlide}function G(d,a){function h(c,b,f,j){if(f===undefined)f=b/k*z;else if(j)f-=a.min;if(s)f=Math.round(f/s)*s;if(b===undefined||s)b=f*k/z;if(isNaN(f))return g;b=Math.max(0,Math.min(b,k));f=b/k*z;if(j||!n)f+=a.min;if(n)if(j)b=k-b;else f=a.max-f;f=F(f,t);var r=c.type=="click";
if(D&&l!==undefined&&!r){c.type="onSlide";A.trigger(c,[f,b]);if(c.isDefaultPrevented())return g}j=r?a.speed:0;r=r?function(){c.type="change";A.trigger(c,[f])}:null;if(n){m.animate({top:b},j,r);a.progress&&B.animate({height:k-b+m.width()/2},j)}else{m.animate({left:b},j,r);a.progress&&B.animate({width:b+m.width()/2},j)}l=f;H=b;d.val(f);return g}function o(){if(n=a.vertical||q(i,"height")>q(i,"width")){k=q(i,"height")-q(m,"height");u=i.offset().top+k}else{k=q(i,"width")-q(m,"width");u=i.offset().left}}
function v(){o();g.setValue(a.value!==undefined?a.value:a.min)}var g=this,p=a.css,i=e("<div><div/><a href='#'/></div>").data("rangeinput",g),n,l,u,k,H;d.before(i);var m=i.addClass(p.slider).find("a").addClass(p.handle),B=i.find("div").addClass(p.progress);e.each("min,max,step,value".split(","),function(c,b){c=d.attr(b);if(parseFloat(c))a[b]=parseFloat(c,10)});var z=a.max-a.min,s=a.step=="any"?0:a.step,t=a.precision;if(t===undefined)try{t=s.toString().split(".")[1].length}catch(I){t=0}if(d.attr("type")==
"range"){var w=e("<input/>");e.each("class,disabled,id,maxlength,name,readonly,required,size,style,tabindex,title,value".split(","),function(c,b){w.attr(b,d.attr(b))});w.val(a.value);d.replaceWith(w);d=w}d.addClass(p.input);var A=e(g).add(d),D=true;e.extend(g,{getValue:function(){return l},setValue:function(c,b){o();return h(b||e.Event("api"),undefined,c,true)},getConf:function(){return a},getProgress:function(){return B},getHandle:function(){return m},getInput:function(){return d},step:function(c,
b){b=b||e.Event();var f=a.step=="any"?1:a.step;g.setValue(l+f*(c||1),b)},stepUp:function(c){return g.step(c||1)},stepDown:function(c){return g.step(-c||-1)}});e.each("onSlide,change".split(","),function(c,b){e.isFunction(a[b])&&e(g).bind(b,a[b]);g[b]=function(f){f&&e(g).bind(b,f);return g}});m.drag({drag:false}).bind("dragStart",function(){o();D=C(e(g))||C(d)}).bind("drag",function(c,b,f){if(d.is(":disabled"))return false;h(c,n?b:f)}).bind("dragEnd",function(c){if(!c.isDefaultPrevented()){c.type=
"change";A.trigger(c,[l])}}).click(function(c){return c.preventDefault()});i.click(function(c){if(d.is(":disabled")||c.target==m[0])return c.preventDefault();o();var b=m.width()/2;h(c,n?k-u-b+c.pageY:c.pageX-u-b)});a.keyboard&&d.keydown(function(c){if(!d.attr("readonly")){var b=c.keyCode,f=e([75,76,38,33,39]).index(b)!=-1,j=e([74,72,40,34,37]).index(b)!=-1;if((f||j)&&!(c.shiftKey||c.altKey||c.ctrlKey)){if(f)g.step(b==33?10:1,c);else if(j)g.step(b==34?-10:-1,c);return c.preventDefault()}}});d.blur(function(c){var b=
e(this).val();b!==l&&g.setValue(b,c)});e.extend(d[0],{stepUp:g.stepUp,stepDown:g.stepDown});v();k||e(window).load(v)}e.tools=e.tools||{version:"1.2.5"};var E;E=e.tools.rangeinput={conf:{min:0,max:100,step:"any",steps:0,value:0,precision:undefined,vertical:0,keyboard:true,progress:false,speed:100,css:{input:"range",slider:"slider",progress:"progress",handle:"handle"}}};var x,y;e.fn.drag=function(d){document.ondragstart=function(){return false};d=e.extend({x:true,y:true,drag:true},d);x=x||e(document).bind("mousedown mouseup",
function(a){var h=e(a.target);if(a.type=="mousedown"&&h.data("drag")){var o=h.position(),v=a.pageX-o.left,g=a.pageY-o.top,p=true;x.bind("mousemove.drag",function(i){var n=i.pageX-v;i=i.pageY-g;var l={};if(d.x)l.left=n;if(d.y)l.top=i;if(p){h.trigger("dragStart");p=false}d.drag&&h.css(l);h.trigger("drag",[i,n]);y=h});a.preventDefault()}else try{y&&y.trigger("dragEnd")}finally{x.unbind("mousemove.drag");y=null}});return this.data("drag",true)};e.expr[":"].range=function(d){var a=d.getAttribute("type");
return a&&a=="range"||!!e(d).filter("input").data("rangeinput")};e.fn.rangeinput=function(d){if(this.data("rangeinput"))return this;d=e.extend(true,{},E.conf,d);var a;this.each(function(){var h=new G(e(this),e.extend(true,{},d));h=h.getInput().data("rangeinput",h);a=a?a.add(h):h});return a?a:this}})(jQuery);
(function(e){function t(a,b,c){var k=a.offset().top,f=a.offset().left,l=c.position.split(/,?\s+/),p=l[0];l=l[1];k-=b.outerHeight()-c.offset[0];f+=a.outerWidth()+c.offset[1];if(/iPad/i.test(navigator.userAgent))k-=e(window).scrollTop();c=b.outerHeight()+a.outerHeight();if(p=="center")k+=c/2;if(p=="bottom")k+=c;a=a.outerWidth();if(l=="center")f-=(a+b.outerWidth())/2;if(l=="left")f-=a;return{top:k,left:f}}function y(a){function b(){return this.getAttribute("type")==a}b.key="[type="+a+"]";return b}function u(a,
b,c){function k(g,d,i){if(!(!c.grouped&&g.length)){var j;if(i===false||e.isArray(i)){j=h.messages[d.key||d]||h.messages["*"];j=j[c.lang]||h.messages["*"].en;(d=j.match(/\$\d/g))&&e.isArray(i)&&e.each(d,function(m){j=j.replace(this,i[m])})}else j=i[c.lang]||i;g.push(j)}}var f=this,l=b.add(f);a=a.not(":button, :image, :reset, :submit");e.extend(f,{getConf:function(){return c},getForm:function(){return b},getInputs:function(){return a},reflow:function(){a.each(function(){var g=e(this),d=g.data("msg.el");
if(d){g=t(g,d,c);d.css({top:g.top,left:g.left})}});return f},invalidate:function(g,d){if(!d){var i=[];e.each(g,function(j,m){j=a.filter("[name='"+j+"']");if(j.length){j.trigger("OI",[m]);i.push({input:j,messages:[m]})}});g=i;d=e.Event()}d.type="onFail";l.trigger(d,[g]);d.isDefaultPrevented()||q[c.effect][0].call(f,g,d);return f},reset:function(g){g=g||a;g.removeClass(c.errorClass).each(function(){var d=e(this).data("msg.el");if(d){d.remove();e(this).data("msg.el",null)}}).unbind(c.errorInputEvent||
"");return f},destroy:function(){b.unbind(c.formEvent+".V").unbind("reset.V");a.unbind(c.inputEvent+".V").unbind("change.V");return f.reset()},checkValidity:function(g,d){g=g||a;g=g.not(":disabled");if(!g.length)return true;d=d||e.Event();d.type="onBeforeValidate";l.trigger(d,[g]);if(d.isDefaultPrevented())return d.result;var i=[];g.not(":radio:not(:checked)").each(function(){var m=[],n=e(this).data("messages",m),v=r&&n.is(":date")?"onHide.v":c.errorInputEvent+".v";n.unbind(v);e.each(w,function(){var o=
this,s=o[0];if(n.filter(s).length){o=o[1].call(f,n,n.val());if(o!==true){d.type="onBeforeFail";l.trigger(d,[n,s]);if(d.isDefaultPrevented())return false;var x=n.attr(c.messageAttr);if(x){m=[x];return false}else k(m,s,o)}}});if(m.length){i.push({input:n,messages:m});n.trigger("OI",[m]);c.errorInputEvent&&n.bind(v,function(o){f.checkValidity(n,o)})}if(c.singleError&&i.length)return false});var j=q[c.effect];if(!j)throw'Validator: cannot find effect "'+c.effect+'"';if(i.length){f.invalidate(i,d);return false}else{j[1].call(f,
g,d);d.type="onSuccess";l.trigger(d,[g]);g.unbind(c.errorInputEvent+".v")}return true}});e.each("onBeforeValidate,onBeforeFail,onFail,onSuccess".split(","),function(g,d){e.isFunction(c[d])&&e(f).bind(d,c[d]);f[d]=function(i){i&&e(f).bind(d,i);return f}});c.formEvent&&b.bind(c.formEvent+".V",function(g){if(!f.checkValidity(null,g))return g.preventDefault()});b.bind("reset.V",function(){f.reset()});a[0]&&a[0].validity&&a.each(function(){this.oninvalid=function(){return false}});if(b[0])b[0].checkValidity=
f.checkValidity;c.inputEvent&&a.bind(c.inputEvent+".V",function(g){f.checkValidity(e(this),g)});a.filter(":checkbox, select").filter("[required]").bind("change.V",function(g){var d=e(this);if(this.checked||d.is("select")&&e(this).val())q[c.effect][1].call(f,d,g)});var p=a.filter(":radio").change(function(g){f.checkValidity(p,g)});e(window).resize(function(){f.reflow()})}e.tools=e.tools||{version:"1.2.5"};var z=/\[type=([a-z]+)\]/,A=/^-?[0-9]*(\.[0-9]+)?$/,r=e.tools.dateinput,B=/^([a-z0-9_\.\-\+]+)@([\da-z\.\-]+)\.([a-z\.]{2,6})$/i,
C=/^(https?:\/\/)?[\da-z\.\-]+\.[a-z\.]{2,6}[#&+_\?\/\w \.\-=]*$/i,h;h=e.tools.validator={conf:{grouped:false,effect:"default",errorClass:"invalid",inputEvent:null,errorInputEvent:"keyup",formEvent:"submit",lang:"en",message:"<div/>",messageAttr:"data-message",messageClass:"error",offset:[0,0],position:"center right",singleError:false,speed:"normal"},messages:{"*":{en:"Please correct this value"}},localize:function(a,b){e.each(b,function(c,k){h.messages[c]=h.messages[c]||{};h.messages[c][a]=k})},
localizeFn:function(a,b){h.messages[a]=h.messages[a]||{};e.extend(h.messages[a],b)},fn:function(a,b,c){if(e.isFunction(b))c=b;else{if(typeof b=="string")b={en:b};this.messages[a.key||a]=b}if(b=z.exec(a))a=y(b[1]);w.push([a,c])},addEffect:function(a,b,c){q[a]=[b,c]}};var w=[],q={"default":[function(a){var b=this.getConf();e.each(a,function(c,k){c=k.input;c.addClass(b.errorClass);var f=c.data("msg.el");if(!f){f=e(b.message).addClass(b.messageClass).appendTo(document.body);c.data("msg.el",f)}f.css({visibility:"hidden"}).find("p").remove();
e.each(k.messages,function(l,p){e("<p/>").html(p).appendTo(f)});f.outerWidth()==f.parent().width()&&f.add(f.find("p")).css({display:"inline"});k=t(c,f,b);f.css({visibility:"visible",position:"absolute",top:k.top,left:k.left}).fadeIn(b.speed)})},function(a){var b=this.getConf();a.removeClass(b.errorClass).each(function(){var c=e(this).data("msg.el");c&&c.css({visibility:"hidden"})})}]};e.each("email,url,number".split(","),function(a,b){e.expr[":"][b]=function(c){return c.getAttribute("type")===b}});
e.fn.oninvalid=function(a){return this[a?"bind":"trigger"]("OI",a)};h.fn(":email","Please enter a valid email address",function(a,b){return!b||B.test(b)});h.fn(":url","Please enter a valid URL",function(a,b){return!b||C.test(b)});h.fn(":number","Please enter a numeric value.",function(a,b){return A.test(b)});h.fn("[max]","Please enter a value smaller than $1",function(a,b){if(b===""||r&&a.is(":date"))return true;a=a.attr("max");return parseFloat(b)<=parseFloat(a)?true:[a]});h.fn("[min]","Please enter a value larger than $1",
function(a,b){if(b===""||r&&a.is(":date"))return true;a=a.attr("min");return parseFloat(b)>=parseFloat(a)?true:[a]});h.fn("[required]","Please complete this mandatory field.",function(a,b){if(a.is(":checkbox"))return a.is(":checked");return!!b});h.fn("[pattern]",function(a){var b=new RegExp("^"+a.attr("pattern")+"$");return b.test(a.val())});e.fn.validator=function(a){var b=this.data("validator");if(b){b.destroy();this.removeData("validator")}a=e.extend(true,{},h.conf,a);if(this.is("form"))return this.each(function(){var c=
e(this);b=new u(c.find(":input"),c,a);c.data("validator",b)});else{b=new u(this,this.eq(0).closest("form"),a);return this.data("validator",b)}}})(jQuery);/*
 * Treeview 1.5pre - jQuery plugin to hide and show branches of a tree
 * 
 * http://bassistance.de/jquery-plugins/jquery-plugin-treeview/
 * http://docs.jquery.com/Plugins/Treeview
 *
 * Copyright (c) 2007 Jörn Zaefferer
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id: jquery.treeview.js 5759 2008-07-01 07:50:28Z joern.zaefferer $
 *
 */

;(function($) {

	// TODO rewrite as a widget, removing all the extra plugins
	$.extend($.fn, {
		swapClass: function(c1, c2) {
			var c1Elements = this.filter('.' + c1);
			this.filter('.' + c2).removeClass(c2).addClass(c1);
			c1Elements.removeClass(c1).addClass(c2);
			return this;
		},
		replaceClass: function(c1, c2) {
			return this.filter('.' + c1).removeClass(c1).addClass(c2).end();
		},
		hoverClass: function(className) {
			className = className || "hover";
			return this.hover(function() {
				$(this).addClass(className);
			}, function() {
				$(this).removeClass(className);
			});
		},
		heightToggle: function(animated, callback) {
			animated ?
				this.animate({ height: "toggle" }, animated, callback) :
				this.each(function(){
					jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
					if(callback)
						callback.apply(this, arguments);
				});
		},
		heightHide: function(animated, callback) {
			if (animated) {
				this.animate({ height: "hide" }, animated, callback);
			} else {
				this.hide();
				if (callback)
					this.each(callback);				
			}
		},
		prepareBranches: function(settings) {
			if (!settings.prerendered) {
				// mark last tree items
				this.filter(":last-child:not(ul)").addClass(CLASSES.last);
				// collapse whole tree, or only those marked as closed, anyway except those marked as open
				this.filter((settings.collapsed ? "" : "." + CLASSES.closed) + ":not(." + CLASSES.open + ")").find(">ul").hide();
			}
			// return all items with sublists
			return this.filter(":has(>ul)");
		},
		applyClasses: function(settings, toggler) {
			// TODO use event delegation
			this.filter(":has(>ul):not(:has(>a))").find(">span").unbind("click.treeview").bind("click.treeview", function(event) {
				// don't handle click events on children, eg. checkboxes
				if ( this == event.target )
					toggler.apply($(this).next());
			}).add( $("a", this) ).hoverClass();
			
			if (!settings.prerendered) {
				// handle closed ones first
				this.filter(":has(>ul:hidden)")
						.addClass(CLASSES.expandable)
						.replaceClass(CLASSES.last, CLASSES.lastExpandable);
						
				// handle open ones
				this.not(":has(>ul:hidden)")
						.addClass(CLASSES.collapsable)
						.replaceClass(CLASSES.last, CLASSES.lastCollapsable);
						
	            // create hitarea if not present
				var hitarea = this.find("div." + CLASSES.hitarea);
				if (!hitarea.length)
					hitarea = this.prepend("<div class=\"" + CLASSES.hitarea + "\"/>").find("div." + CLASSES.hitarea);
				hitarea.removeClass().addClass(CLASSES.hitarea).each(function() {
					var classes = "";
					$.each($(this).parent().attr("class").split(" "), function() {
						classes += this + "-hitarea ";
					});
					$(this).addClass( classes );
				})
			}
			
			// apply event to hitarea
			this.find("div." + CLASSES.hitarea).click( toggler );
		},
		treeview: function(settings) {
			
			settings = $.extend({
				cookieId: "treeview"
			}, settings);
			
			if ( settings.toggle ) {
				var callback = settings.toggle;
				settings.toggle = function() {
					return callback.apply($(this).parent()[0], arguments);
				};
			}
		
			// factory for treecontroller
			function treeController(tree, control) {
				// factory for click handlers
				function handler(filter) {
					return function() {
						// reuse toggle event handler, applying the elements to toggle
						// start searching for all hitareas
						toggler.apply( $("div." + CLASSES.hitarea, tree).filter(function() {
							// for plain toggle, no filter is provided, otherwise we need to check the parent element
							return filter ? $(this).parent("." + filter).length : true;
						}) );
						return false;
					};
				}
				// click on first element to collapse tree
				$("a:eq(0)", control).click( handler(CLASSES.collapsable) );
				// click on second to expand tree
				$("a:eq(1)", control).click( handler(CLASSES.expandable) );
				// click on third to toggle tree
				$("a:eq(2)", control).click( handler() ); 
			}
		
			// handle toggle event
			function toggler() {
				$(this)
					.parent()
					// swap classes for hitarea
					.find(">.hitarea")
						.swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
						.swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
					.end()
					// swap classes for parent li
					.swapClass( CLASSES.collapsable, CLASSES.expandable )
					.swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
					// find child lists
					.find( ">ul" )
					// toggle them
					.heightToggle( settings.animated, settings.toggle );
				if ( settings.unique ) {
					$(this).parent()
						.siblings()
						// swap classes for hitarea
						.find(">.hitarea")
							.replaceClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
							.replaceClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
						.end()
						.replaceClass( CLASSES.collapsable, CLASSES.expandable )
						.replaceClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
						.find( ">ul" )
						.heightHide( settings.animated, settings.toggle );
				}
			}
			this.data("toggler", toggler);
			
			function serialize() {
				function binary(arg) {
					return arg ? 1 : 0;
				}
				var data = [];
				branches.each(function(i, e) {
					data[i] = $(e).is(":has(>ul:visible)") ? 1 : 0;
				});
				$.cookie(settings.cookieId, data.join(""), settings.cookieOptions );
			}
			
			function deserialize() {
				var stored = $.cookie(settings.cookieId);
				if ( stored ) {
					var data = stored.split("");
					branches.each(function(i, e) {
						$(e).find(">ul")[ parseInt(data[i]) ? "show" : "hide" ]();
					});
				}
			}
			
			// add treeview class to activate styles
			this.addClass("treeview");
			
			// prepare branches and find all tree items with child lists
			var branches = this.find("li").prepareBranches(settings);
			
			switch(settings.persist) {
			case "cookie":
				var toggleCallback = settings.toggle;
				settings.toggle = function() {
					serialize();
					if (toggleCallback) {
						toggleCallback.apply(this, arguments);
					}
				};
				deserialize();
				break;
			case "location":
				var current = this.find("a").filter(function() {
					return this.href.toLowerCase() == location.href.toLowerCase();
				});
				if ( current.length ) {
					// TODO update the open/closed classes
					var items = current.addClass("selected").parents("ul, li").add( current.next() ).show();
					if (settings.prerendered) {
						// if prerendered is on, replicate the basic class swapping
						items.filter("li")
							.swapClass( CLASSES.collapsable, CLASSES.expandable )
							.swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
							.find(">.hitarea")
								.swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
								.swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea );
					}
				}
				break;
			}
			
			branches.applyClasses(settings, toggler);
				
			// if control option is set, create the treecontroller and show it
			if ( settings.control ) {
				treeController(this, settings.control);
				$(settings.control).show();
			}
			
			return this;
		}
	});
	
	// classes used by the plugin
	// need to be styled via external stylesheet, see first example
	$.treeview = {};
	var CLASSES = ($.treeview.classes = {
		open: "open",
		closed: "closed",
		expandable: "expandable",
		expandableHitarea: "expandable-hitarea",
		lastExpandableHitarea: "lastExpandable-hitarea",
		collapsable: "collapsable",
		collapsableHitarea: "collapsable-hitarea",
		lastCollapsableHitarea: "lastCollapsable-hitarea",
		lastCollapsable: "lastCollapsable",
		lastExpandable: "lastExpandable",
		last: "last",
		hitarea: "hitarea"
	});
	
})(jQuery);/*!
 * jQuery JavaScript Library v1.4.2
 * http://jquery.com/
 *
 * Copyright 2010, John Resig
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * Includes Sizzle.js
 * http://sizzlejs.com/
 * Copyright 2010, The Dojo Foundation
 * Released under the MIT, BSD, and GPL Licenses.
 *
 * Date: Sat Feb 13 22:33:48 2010 -0500
 */
(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML="   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);
/*
 * jQuery.splitter.js - two-pane splitter window plugin
 *
 * version 1.51 (2009/01/09)
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */

/**
 * The splitter() plugin implements a two-pane resizable splitter window.
 * The selected elements in the jQuery object are converted to a splitter;
 * each selected element should have two child elements, used for the panes
 * of the splitter. The plugin adds a third child element for the splitbar.
 *
 * For more details see: http://methvin.com/splitter/
 *
 *
 * @example $('#MySplitter').splitter();
 * @desc Create a vertical splitter with default settings
 *
 * @example $('#MySplitter').splitter({type: 'h', accessKey: 'M'});
 * @desc Create a horizontal splitter resizable via Alt+Shift+M
 *
 * @name splitter
 * @type jQuery
 * @param Object options Options for the splitter (not required)
 * @cat Plugins/Splitter
 * @return jQuery
 * @author Dave Methvin (dave.methvin@gmail.com)
 */
;
(function($) {

    $.fn.splitter = function(args) {
        args = args || {};
        return this.each(function() {
            var zombie;      // left-behind splitbar for outline resizes
            function startSplitMouse(evt) {
                if (opts.outline)
                    zombie = zombie || bar.clone(false).insertAfter(A);
                panes.css("-webkit-user-select", "none");   // Safari selects A/B text on a move
                bar.addClass(opts.activeClass);
                $('<div class="splitterMask"></div>').insertAfter(bar);
                A._posSplit = A[0][opts.pxSplit] - evt[opts.eventPos];
                $(document)
                        .bind("mousemove", doSplitMouse)
                        .bind("mouseup", endSplitMouse);
            }

            function doSplitMouse(evt) {
                var newPos = A._posSplit + evt[opts.eventPos];
                if (opts.outline) {
                    newPos = Math.max(0, Math.min(newPos, splitter._DA - bar._DA));
                    bar.css(opts.origin, newPos);
                } else
                    resplit(newPos);
            }

            function endSplitMouse(evt) {
                $('div.splitterMask').remove();
                bar.removeClass(opts.activeClass);
                var newPos = A._posSplit + evt[opts.eventPos];
                if (opts.outline) {
                    zombie.remove();
                    zombie = null;
                    resplit(newPos);
                }
                panes.css("-webkit-user-select", "text");   // let Safari select text again
                $(document)
                        .unbind("mousemove", doSplitMouse)
                        .unbind("mouseup", endSplitMouse);
            }

            function resplit(newPos) {
                // Constrain new splitbar position to fit pane size limits
                newPos = Math.max(A._min, splitter._DA - B._max,
                        Math.min(newPos, A._max, splitter._DA - bar._DA - B._min));
                // Resize/position the two panes
                bar._DA = bar[0][opts.pxSplit];      // bar size may change during dock
                bar.css(opts.origin, newPos).css(opts.fixed, splitter._DF);
                A.css(opts.origin, 0).css(opts.split, newPos).css(opts.fixed, splitter._DF);
                B.css(opts.origin, newPos + bar._DA)
                        .css(opts.split, splitter._DA - bar._DA - newPos).css(opts.fixed, splitter._DF);
                // IE fires resize for us; all others pay cash
                if (!$.browser.msie)
                    panes.trigger("resize");
            }

            function dimSum(jq, dims) {
                // Opera returns -1 for missing min/max width, turn into 0
                var sum = 0;
                for (var i = 1; i < arguments.length; i++)
                    sum += Math.max(parseInt(jq.css(arguments[i])) || 0, 0);
                return sum;
            }

            // Determine settings based on incoming opts, element classes, and defaults
            var vh = (args.splitHorizontal ? 'h' : args.splitVertical ? 'v' : args.type) || 'v';
            var opts = $.extend({
                activeClass: 'active',   // class name for active splitter
                pxPerKey: 8,         // splitter px moved per keypress
                tabIndex: 0,         // tab order indicator
                accessKey: ''         // accessKey for splitbar
            }, {
                v: {               // Vertical splitters:
                    keyLeft: 39, keyRight: 37, cursor: "e-resize",
                    splitbarClass: "vsplitbar", outlineClass: "voutline",
                    type: 'v', eventPos: "pageX", origin: "left",
                    split: "width",  pxSplit: "offsetWidth",  side1: "Left", side2: "Right",
                    fixed: "height", pxFixed: "offsetHeight", side3: "Top",  side4: "Bottom"
                },
                h: {               // Horizontal splitters:
                    keyTop: 40, keyBottom: 38,  cursor: "n-resize",
                    splitbarClass: "hsplitbar", outlineClass: "houtline",
                    type: 'h', eventPos: "pageY", origin: "top",
                    split: "height", pxSplit: "offsetHeight", side1: "Top",  side2: "Bottom",
                    fixed: "width",  pxFixed: "offsetWidth",  side3: "Left", side4: "Right"
                }
            }[vh], args);

            // Create jQuery object closures for splitter and both panes
            var splitter = $(this).css({position: "relative"});
            var panes = $(">*", splitter[0]).css({
                position: "absolute",          // positioned inside splitter container
                "z-index": "1",               // splitbar is positioned above
                "-moz-outline-style": "none"   // don't show dotted outline
            });
            var A = $(panes[0]);      // left  or top
            var B = $(panes[1]);      // right or bottom

            // Focuser element, provides keyboard support; title is shown by Opera accessKeys
            var focuser = $('<a href="javascript:void(0)"></a>')
                    .attr({accessKey: opts.accessKey, tabIndex: opts.tabIndex, title: opts.splitbarClass})
                    .bind($.browser.opera ? "click" : "focus", function() {
                        this.focus();
                        bar.addClass(opts.activeClass)
                    })
                    .bind("keydown", function(e) {
                        var key = e.which || e.keyCode;
                        var dir = key == opts["key" + opts.side1] ? 1 : key == opts["key" + opts.side2] ? -1 : 0;
                        if (dir)
                            resplit(A[0][opts.pxSplit] + dir * opts.pxPerKey, false);
                    })
                    .bind("blur", function() {
                        bar.removeClass(opts.activeClass)
                    });

            // Splitbar element, can be already in the doc or we create one
            var bar = $(panes[2] || '<div></div>')
                    .insertAfter(A).css("z-index", "100").append(focuser)
                    .attr({"class": opts.splitbarClass, unselectable: "on"})
                    .css({position: "absolute",   "user-select": "none", "-webkit-user-select": "none",
                        "-khtml-user-select": "none", "-moz-user-select": "none", "top": "0px"})
                    .bind("mousedown", startSplitMouse);
            // Use our cursor unless the style specifies a non-default cursor
            if (/^(auto|default|)$/.test(bar.css("cursor")))
                bar.css("cursor", opts.cursor);

            // Cache several dimensions for speed, rather than re-querying constantly
            bar._DA = bar[0][opts.pxSplit];
            splitter._PBF = $.boxModel ? dimSum(splitter, "border" + opts.side3 + "Width", "border" + opts.side4 + "Width") : 0;
            splitter._PBA = $.boxModel ? dimSum(splitter, "border" + opts.side1 + "Width", "border" + opts.side2 + "Width") : 0;
            A._pane = opts.side1;
            B._pane = opts.side2;
            $.each([A,B], function() {
                this._min = opts["min" + this._pane] || dimSum(this, "min-" + opts.split);
                this._max = opts["max" + this._pane] || dimSum(this, "max-" + opts.split) || 9999;
                this._init = opts["size" + this._pane] === true ?
                        parseInt($.curCSS(this[0], opts.split)) : opts["size" + this._pane];
            });

            // Determine initial position, get from cookie if specified
            var initPos = A._init;
            if (!isNaN(B._init))   // recalc initial B size as an offset from the top or left side
                initPos = splitter[0][opts.pxSplit] - splitter._PBA - B._init - bar._DA;
            if (opts.cookie) {
                if (!$.cookie)
                    alert('jQuery.splitter(): jQuery cookie plugin required');
                var ckpos = parseInt($.cookie(opts.cookie));
                if (!isNaN(ckpos))
                    initPos = ckpos;
                $(window).bind("unload", function() {
                    var state = String(bar.css(opts.origin));   // current location of splitbar
                    $.cookie(opts.cookie, state, {expires: opts.cookieExpires || 365,
                        path: opts.cookiePath || document.location.pathname});
                });
            }
            if (isNaN(initPos))   // King Solomon's algorithm
                initPos = Math.round((splitter[0][opts.pxSplit] - splitter._PBA - bar._DA) / 2);

            // Resize event propagation and splitter sizing
            if (opts.anchorToWindow) {
                // Account for margin or border on the splitter container and enforce min height
                splitter._hadjust = dimSum(splitter, "borderTopWidth", "borderBottomWidth", "marginBottom");
                splitter._hmin = Math.max(dimSum(splitter, "minHeight"), 20);
                $(window).bind("resize",
                        function() {
                            var top = splitter.offset().top;
                            var wh = $(window).height();
                            splitter.css("height", Math.max(wh - top - splitter._hadjust, splitter._hmin) + "px");
                            if (!$.browser.msie) splitter.trigger("resize");
                        }).trigger("resize");
            }
            else if (opts.resizeToWidth && !$.browser.msie)
                $(window).bind("resize", function() {
                    splitter.trigger("resize");
                });

            // Resize event handler; triggered immediately to set initial position
            splitter.bind("resize",
                    function(e, size) {
                        // Custom events bubble in jQuery 1.3; don't Yo Dawg
                        if (e.target != this) return;
                        // Determine new width/height of splitter container
                        splitter._DF = splitter[0][opts.pxFixed] - splitter._PBF;
                        splitter._DA = splitter[0][opts.pxSplit] - splitter._PBA;
                        // Bail if splitter isn't visible or content isn't there yet
                        if (splitter._DF <= 0 || splitter._DA <= 0) return;
                        // Re-divvy the adjustable dimension; maintain size of the preferred pane
                        resplit(!isNaN(size) ? size : (!(opts.sizeRight || opts.sizeBottom) ? A[0][opts.pxSplit] :
                                splitter._DA - B[0][opts.pxSplit] - bar._DA));
                    }).trigger("resize", [initPos]);
        });
    };

})(jQuery);/**
 *  SVGPan library 1.2 - phpDocumentor1
 * ====================
 *
 * Given an unique existing element with id "viewport", including the
 * the library into any SVG adds the following capabilities:
 *
 *  - Mouse panning
 *  - Mouse zooming (using the wheel)
 *  - Object dargging
 *
 * Known issues:
 *
 *  - Zooming (while panning) on Safari has still some issues
 *
 * Releases:
 *
 * 1.2 - phpDocumentor1, Fri Apr 08 19:19:00 CET 2011, Mike van Riel
 *            Increased zoom speed with 20%
 *            Disabled element moving functionality
 *
 * 1.2, Sat Mar 20 08:42:50 GMT 2010, Zeng Xiaohui
 *	Fixed a bug with browser mouse handler interaction
 *
 * 1.1, Wed Feb  3 17:39:33 GMT 2010, Zeng Xiaohui
 *	Updated the zoom code to support the mouse wheel on Safari/Chrome
 *
 * 1.0, Andrea Leofreddi
 *	First release
 *
 * This code is licensed under the following BSD license:
 *
 * Copyright 2009-2010 Andrea Leofreddi <a.leofreddi@itcharm.com>. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are
 * permitted provided that the following conditions are met:
 *
 *    1. Redistributions of source code must retain the above copyright notice, this list of
 *       conditions and the following disclaimer.
 *
 *    2. Redistributions in binary form must reproduce the above copyright notice, this list
 *       of conditions and the following disclaimer in the documentation and/or other materials
 *       provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY Andrea Leofreddi ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Andrea Leofreddi OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * The views and conclusions contained in the software and documentation are those of the
 * authors and should not be interpreted as representing official policies, either expressed
 * or implied, of Andrea Leofreddi.
 */

var root = document.documentElement;

var state = 'none', stateTarget, stateOrigin, stateTf;

setupHandlers(root);

/**
 * Register handlers
 */
function setupHandlers(root){
	setAttributes(root, {
		"onmouseup" : "add(evt)",
		"onmousedown" : "handleMouseDown(evt)",
		"onmousemove" : "handleMouseMove(evt)",
		"onmouseup" : "handleMouseUp(evt)",
//		"onmouseout" : "handleMouseUp(evt)" // Decomment this to stop the pan functionality when dragging out of the SVG element
	});

	if(navigator.userAgent.toLowerCase().indexOf('webkit') >= 0)
		window.addEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari
	else
		window.addEventListener('DOMMouseScroll', handleMouseWheel, false); // Others
}

/**
 * Instance an SVGPoint object with given event coordinates.
 */
function getEventPoint(evt) {
	var p = root.createSVGPoint();

	p.x = evt.clientX;
	p.y = evt.clientY;

	return p;
}

/**
 * Sets the current transform matrix of an element.
 */
function setCTM(element, matrix) {
	var s = "matrix(" + matrix.a + "," + matrix.b + "," + matrix.c + "," + matrix.d + "," + matrix.e + "," + matrix.f + ")";

	element.setAttribute("transform", s);
}

/**
 * Dumps a matrix to a string (useful for debug).
 */
function dumpMatrix(matrix) {
	var s = "[ " + matrix.a + ", " + matrix.c + ", " + matrix.e + "\n  " + matrix.b + ", " + matrix.d + ", " + matrix.f + "\n  0, 0, 1 ]";

	return s;
}

/**
 * Sets attributes of an element.
 */
function setAttributes(element, attributes){
	for (i in attributes)
		element.setAttributeNS(null, i, attributes[i]);
}

/**
 * Handle mouse move event.
 */
function handleMouseWheel(evt) {
	if(evt.preventDefault)
		evt.preventDefault();

	evt.returnValue = false;

	var svgDoc = evt.target.ownerDocument;

	var delta;

	if(evt.wheelDelta)
		delta = evt.wheelDelta / 3600; // Chrome/Safari
	else
		delta = evt.detail / -90; // Mozilla

	var z = 1 + (delta * 1.2); // Zoom factor: 0.9/1.1

	var g = svgDoc.getElementById("viewport");

	var p = getEventPoint(evt);

	p = p.matrixTransform(g.getCTM().inverse());

	// Compute new scale matrix in current mouse position
	var k = root.createSVGMatrix().translate(p.x, p.y).scale(z).translate(-p.x, -p.y);

        setCTM(g, g.getCTM().multiply(k));

	stateTf = stateTf.multiply(k.inverse());
}

/**
 * Handle mouse move event.
 */
function handleMouseMove(evt) {
	if(evt.preventDefault)
		evt.preventDefault();

	evt.returnValue = false;

	var svgDoc = evt.target.ownerDocument;

	var g = svgDoc.getElementById("viewport");

	if(state == 'pan') {
		// Pan mode
		var p = getEventPoint(evt).matrixTransform(stateTf);

		setCTM(g, stateTf.inverse().translate(p.x - stateOrigin.x, p.y - stateOrigin.y));
	} else if(state == 'move') {
		// Move mode
		var p = getEventPoint(evt).matrixTransform(g.getCTM().inverse());

		setCTM(stateTarget, root.createSVGMatrix().translate(p.x - stateOrigin.x, p.y - stateOrigin.y).multiply(g.getCTM().inverse()).multiply(stateTarget.getCTM()));

		stateOrigin = p;
	}
}

/**
 * Handle click event.
 */
function handleMouseDown(evt) {
	if(evt.preventDefault)
		evt.preventDefault();

	evt.returnValue = false;

	var svgDoc = evt.target.ownerDocument;

	var g = svgDoc.getElementById("viewport");

//	if(evt.target.tagName == "svg") {
		// Pan mode
		state = 'pan';

		stateTf = g.getCTM().inverse();

		stateOrigin = getEventPoint(evt).matrixTransform(stateTf);
//	} else {
		// Move mode
//		state = 'move';
//
//		stateTarget = evt.target;
//
//		stateTf = g.getCTM().inverse();
//
//		stateOrigin = getEventPoint(evt).matrixTransform(stateTf);
//	}
}

/**
 * Handle mouse button release event.
 */
function handleMouseUp(evt) {
	if(evt.preventDefault)
		evt.preventDefault();

	evt.returnValue = false;

	var svgDoc = evt.target.ownerDocument;

	if(state == 'pan' || state == 'move') {
		// Quit pan mode
		state = '';
	}
}

/**
 * Cookie plugin
 *
 * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 */

/**
 * Create a cookie with the given name and value and other optional parameters.
 *
 * @example $.cookie('the_cookie', 'the_value');
 * @desc Set the value of a cookie.
 * @example $.cookie('the_cookie', 'the_value', {expires: 7, path: '/', domain: 'jquery.com', secure: true});
 * @desc Create a cookie with all available options.
 * @example $.cookie('the_cookie', 'the_value');
 * @desc Create a session cookie.
 * @example $.cookie('the_cookie', null);
 * @desc Delete a cookie by passing null as value.
 *
 * @param String name The name of the cookie.
 * @param String value The value of the cookie.
 * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
 * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
 *                             If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
 *                             If set to null or omitted, the cookie will be a session cookie and will not be retained
 *                             when the the browser exits.
 * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
 * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
 * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
 *                        require a secure protocol (like HTTPS).
 * @type undefined
 *
 * @name $.cookie
 * @cat Plugins/Cookie
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */

/**
 * Get the value of a cookie with the given name.
 *
 * @example $.cookie('the_cookie');
 * @desc Get the value of a cookie.
 *
 * @param String name The name of the cookie.
 * @return The value of the cookie.
 * @type String
 *
 * @name $.cookie
 * @cat Plugins/Cookie
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */
jQuery.cookie = function(name, value, options)
{
  if (typeof value != 'undefined')
  { // name and value given, set cookie
    options = options || {};
    if (value === null)
    {
      value = '';
      options.expires = -1;
    }
    var expires = '';
    if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString))
    {
      var date;
      if (typeof options.expires == 'number')
      {
        date = new Date();
        date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
      }
      else
      {
        date = options.expires;
      }
      expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
    }
    var path = options.path ? '; path=' + options.path : '';
    var domain = options.domain ? '; domain=' + options.domain : '';
    var secure = options.secure ? '; secure' : '';
    document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
  }
  else
  { // only name given, get cookie
    var cookieValue = null;
    if (document.cookie && document.cookie != '')
    {
      var cookies = document.cookie.split(';');
      for (var i = 0; i < cookies.length; i++)
      {
        var cookie = jQuery.trim(cookies[i]);
        // Does this cookie string begin with the name we want?
        if (cookie.substring(0, name.length + 1) == (name + '='))
        {
          cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
          break;
        }
      }
    }
    return cookieValue;
  }
};var timeout    = 500;
var closetimer = 0;
var ddmenuitem = 0;

function menu_open() {
    menu_canceltimer();
    menu_close();
    ddmenuitem = $(this).find('ul').css('visibility', 'visible');
}

function menu_close() {
    if (ddmenuitem) ddmenuitem.css('visibility', 'hidden');
}

function menu_timer() {
    closetimer = window.setTimeout(menu_close, timeout);
}

function menu_canceltimer() {
    if (closetimer) {
        window.clearTimeout(closetimer);
        closetimer = null;
    }
}

$(document).ready(function() {
    $('#file-nav > li').bind('mouseover', menu_open);
    $('#file-nav > li').bind('mouseout', menu_timer);
});

document.onclick = menu_close;.treeview, .treeview ul {
	padding: 0;
	margin: 0;
	list-style: none;
}

.treeview ul {
	margin-top: 4px;
}

.treeview .hitarea {
	background: url(images/treeview-default.gif) -64px -25px no-repeat;
	height: 16px;
	width: 16px;
	margin-left: -16px;
	float: left;
	cursor: pointer;
}

/* fix for IE6 */
* html .hitarea {
	display: inline;
	float:none;
}

.treeview li {
	margin: 0;
	padding: 3px 0pt 3px 16px;
}

.treeview a.selected {
	background-color: #eee;
}

#treecontrol { margin: 1em 0; display: none; }

.treeview .hover { color: red; cursor: pointer; }

.treeview li { background: url(images/treeview-default-line.gif) 0 0 no-repeat; }
.treeview li.collapsable, .treeview li.expandable { background-position: 0 -176px; }

.treeview .expandable-hitarea { background-position: -80px -3px; }

.treeview li.last { background-position: 0 -1766px }
.treeview li.lastCollapsable, .treeview li.lastExpandable { background-image: url(images/treeview-default.gif); }
.treeview li.lastCollapsable { background-position: 0 -111px }
.treeview li.lastExpandable { background-position: -32px -67px }

.treeview div.lastCollapsable-hitarea, .treeview div.lastExpandable-hitarea { background-position: 0; }

.treeview-red li { background-image: url(images/treeview-red-line.gif); }
.treeview-red .hitarea, .treeview-red li.lastCollapsable, .treeview-red li.lastExpandable { background-image: url(images/treeview-red.gif); }

.treeview-black li { background-image: url(images/treeview-black-line.gif); }
.treeview-black .hitarea, .treeview-black li.lastCollapsable, .treeview-black li.lastExpandable { background-image: url(images/treeview-black.gif); }

.treeview-gray li { background-image: url(images/treeview-gray-line.gif); }
.treeview-gray .hitarea, .treeview-gray li.lastCollapsable, .treeview-gray li.lastExpandable { background-image: url(images/treeview-gray.gif); }

.treeview-famfamfam li { background-image: url(images/treeview-famfamfam-line.gif); }
.treeview-famfamfam .hitarea, .treeview-famfamfam li.lastCollapsable, .treeview-famfamfam li.lastExpandable { background-image: url(images/treeview-famfamfam.gif); }

.treeview .placeholder {
	background: url(images/ajax-loader.gif) 0 0 no-repeat;
	height: 16px;
	width: 16px;
	display: block;
}

ul.deadtree
{
  padding:    0;
  margin:     0;
  list-style: none;
}
.filetree li, .deadtree li { padding: 3px 0 2px 16px; }

.filetree span.folder, .filetree span.file,
.deadtree span.folder, .deadtree span.file
{
  padding: 1px 0 1px 16px; display: block;
}

.filetree span.class, .deadtree span.class,
.filetree span.function, .deadtree span.function,
.filetree span.interface, .deadtree span.interface
{
  padding: 1px 0 1px 18px; display: block;
}

.filetree span.folder, .deadtree span.folder { background: url(images/folder.gif) 0 0 no-repeat; }
.filetree li.expandable span.folder { background: url(images/folder-closed.gif) 0 0 no-repeat; }
.filetree span.file { background: url(images/file.gif) 0 0 no-repeat; }
.filetree span.class { background: url(../images/icons/class.png) 0 0 no-repeat; }
.filetree span.interface { background: url(../images/icons/interface.png) 0 0 no-repeat; }
.filetree span.function { background: url(../images/icons/function.png) 0 0 no-repeat; }
.treeview ul
{
  background:          transparent;
}

body
{
  margin:              0px;
  padding:             0px;
  line-height:         1.5em;
  font-family:         Verdana, Helvetica, sans-serif;
  font-size:           0.8em;
  color:               black;
  background:          black url('../images/background.png') repeat-x top left;
}

table
{
  border-collapse:     collapse;
}

thead th
{
  color:               gray;
  font-size:           0.8em;
  border-bottom:       1px solid silver;
}

th, td
{
  padding-right:       8px;
}

#maincontainer
{
  margin: 0 auto;
  background: white url('../images/top.png') top left no-repeat;
  width: 980px;
}

#header
{
  height: 70px;
}

#header h1
{
  display: inline;
  margin-left: 10px;
  background: white url('../images/top-background.png') repeat-x top left;
  padding-top: 35px;
}

#footer
{
  clear:both;
}

#content_container
{
  float:               right;
  width:               100%;
  margin-left:         -250px; /*Set left margin to -(leftColumnWidth + RightColumnWidth)*/
}

#content
{
  margin-left:         250px; /*Set left margin to (leftColumnWidth + RightColumnWidth)*/
}

ul#menu
{
  float:              left;
  margin:             0px 10px;
  -moz-border-radius: 5px;
  border-radius:      5px;
  background:         #f0f0f0;
  display:            block;
  width:              960px;
  height:             32px;
  line-height:        22px;
  padding:            0px;
}

ul#menu li
{
  padding:      0px 10px;
  margin:       5px 0px;
  border-right: 1px solid gray;
  display:      block;
  float:        left;
}

ul#menu li a
{
  color:   black;
  display: block;
}

div.section
{
  margin: 5px;
  padding: 5px;
  padding-top: 0px;
  margin-bottom: 15px;
  border: 1px solid silver;
  -moz-border-radius: 6px;
  border-radius: 6px;
  width: 218px;
  word-wrap: break-word;
}

div.section h1
{
  border-bottom: 1px solid #5E8CDF;
  text-align: center;
  font-size: 1.1em;
  padding-bottom: 5px;
  /*font-variant: small-caps;*/
  color: #5E8CDF;
}

#index
{
  float:               left;
  width:               250px; /*Width of right column in pixels*/
}

#index h2
{
  font-size:           1.1em;
  margin-bottom:       5px;
  border-bottom:       1px dashed gray;
}

.padder
{
  margin:              10px; /*Margins for inner DIV inside each column (to provide padding)*/
  margin-top:          0px;
}

#index .padder
{
  margin-left:         5px;
  margin-right:        5px;
}

#menu h1
{
  text-align:          center;
  margin-top:          15px;
  margin-bottom:       10px;
  color:               #6495ed;
}

#menu h4
{
  margin-bottom:       0px;
  border-bottom:       1px solid #5E8CDF;
}

#search_box
{
  display: none;
  width: 95%;
  margin: 5px;
  text-align:         center;
  border:             1px solid #5E8CDF;
  -moz-border-radius: 5px;
  border-radius:      5px;
}

#content .properties
{
  float:               right;
  width:               200px;
  border:              1px solid gray;
  -moz-border-radius:  5px;
  padding:             5px;
  background:          white;
  word-wrap:           break-word;
  border-radius:       5px;
}

#content .properties div.property-value
{
  margin-left:         80px;
  word-wrap:           break-word;
  font-size:           0.8em;
  width:               120px;
}

#content .properties label.property-key
{
  float:               left;
  width:               80px;
  word-wrap:           break-word;
  font-size:           0.8em;
  font-weight:         bold;
}

#content .properties h1
{
  font-size:           1.1em;
  margin-top:          3px;
  margin-bottom:       0px;
  border-bottom:       1px solid #5E8CDF;
}

#content .properties table
{
  font-size:           0.8em;
  width:               200px;
}

#content table
{
  font-size:           1.0em;
}

#content .properties th, #content .properties td, #content th, #content td
{
  text-align:          left;
  vertical-align:      top;
  word-wrap:           break-word;
  overflow:            hidden;
  white-space:         pre-wrap;
}

#content .class, #content .interface
{
  clear: right;
}

#content h1
{
  border-bottom:       1px solid #5E8CDF;
  padding-bottom:      10px;
  font-size:           1.6em;
}

#content h2
{
  color: #5E8CDF;
  border-bottom:       1px dashed #5E8CDF;
  padding: 10px 0px;
}

#content h5
{
  margin-bottom:       0px;
  margin-top:          12px;
}

.file_menu
{
  background-color:   #f0f0f0;
  -moz-border-radius: 5px;
  border-radius:      5px;
  text-align:         center;
  margin-top:         -5px;
  padding:            3px;
}

#content .method, #content .constant, #content .property, #content .class, #content .interface
{
  border:              1px solid silver;
  background:          #f9fdf9;
  margin:              8px 0px;
  padding:             5px;
}

#content .method h4, #content .constant h4, #content .property h4, #content .class h4, #content .interface h4
{
  margin-top:          10px;
  margin-bottom:       3px;
}

#content .method small p, #content .method small ul
{
  margin: 0px;
}

#content .class
{
  margin:        5px 0px;
  margin-bottom: 15px;
}

small.footer
{
  display: block;
  text-align: right;
  color: silver;
}

small.footer a
{
  color: gray;
}GIF89a	 	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                !   ,    	 	  & HpPA81a/>̈0#A ;GIF89a   jlbAԽ|9tmp|_,      ;X%ܬPƤ7i4e'E j
dq 56p1tJU$  ;GIF89a                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    !   ,         ;GIF89a                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                !   ,       	/ "\XB	B(p"E1:0ǏR8r G%<0ʒ,$L6s	SgO#oVEnTڑ)ʟP=:5iեWf}*5*UVb,ׯ]Ӣ]Vm[cƅ[Vn]gꝻn߼|x[nUl2:;oegLqş=w~thҧ)skͯ9=Zumַ]熽[PڳEGtƇVn缡~Iܥسkν{W|s^y*:?_zrW ~*8B I^ZHx"f8%&c.(cc;bx@($A9$=vE"dOeSx$WJ%[ZiNvi#X\ejeyiҹfxΙg{ީ|gj}"*2zhbBڦv:j)br(U^
jNZj꣩zjnk~*ʚ+ڪd[+L[,˺zmRbkr묶Ւ{٢{»KJo;/[0+<C0J_[L"g<%'s.,sÌs;c|@,4A=4=wE#tOuS|4WK5[[mNwm3X\uje}iӽvxϝw{|wn}#.3~xbC޶v;n9cs8U_zO^z型髣~zo{:˞;ۮt_꿓;L_<˻~}Sc{sՓ٣ÿOK?_ #@Ѐ=	2pAr!'pCT?τ%L`+ ʰ!#CP@2iD"=`OXD$61O\a[8WbE+Ni ;GIF89a   Zx➭s-҃h$Ç4,      7H`KPl\:pL)e9@\ "l:+PB ;GIF89a`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 !   ,    `    	H*\ BlHŋ#bȱEC	rɓ(S<K+cp̛m:φ:AI!M\Z)<J}:PԫCfW`ÊU:Y[Ϫ];2-[oDIrѭުK!EP1㎎t,S#cys暞9nŦSDI֦^(vܻ	q3;pm8r"TcdcܣOy\9w]v5eU]9߀'xE('aHnq["$!ؠ)8e	_p3v<5"| aFF2dO"U.VfPWl[$`)d9[@ ;GIF89a`       1k9s!Bs!R1scB J ZZ!k!s {cc{Bs֔ƭҤޥ筌絔ﵔҵ                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      !   ,    `    	H*\ BlHŋ#bȱEC	rɓ(S\ɲ˗0cʜ)B&ܙB
x(A(tp@ѧH;HthjQ	PJ+O	`۷pʝK.͒v[[qć|7r0È+^̸	$c8DP2 0` !8Hi	"0X 1$ e!Kȓ+~FֳkνU8ur	,wJ:ujXr]XѪe뽿 8vDM1A(^NݑP%TW)wmb}aa~iU0xX|)h >(D$d]fmhݦ]j]l&ev[!YdR=!`ұip)県IvJjٕVwTJefw]%wv裐F* ;GIF89a   Zx➭s-҃h$Ç4,       6H`KPl\
2jLEkuÅalV ;GIF89a	 	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                !   ,    	 	  " H"<pa  HaE   ;GIF89a                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   !   ,       	 "\XB	B(p"E1:ǏR8r G%<0ʒ,$L6s	SgO#oVEnTڑ)ʟP=:5iեWf}*5*UVb,ׯ]Ӣ]Vm[cƅ[Vn]gꝻn߼|x[nUl2:;oegLqş=w~thҧ)skͯ9=Zumַ]熽[PڳEGtƇVn缡~Iܥسkν{W|s^y*:?_zrW ~*8B I^ZHx"f8%&c.(cc;bx@($A9$=vE"dOeSx$WJ%[ZiNvi#X\ejeyiҹfxΙg{ީ|gj}"*2zhbBڦv:j)br(U^
jNZj꣩zjnk~*ʚ+ڪd[+L[,˺zmRbkr묶Ւ{٢{»KJo;/[0+<C0J_[L"g<%'s.,sÌs;c|@,4A=4=wE#tOuS|4WK5[[mNwm3X\uje}iӽvxϝw{|wn}#.3~xbC޶v;n9cs8U_zO^z型髣~zo{:˞;ۮt_꿓;L_<˻~}Sc{sՓ٣ÿOK?_ #@Ѐ=	2pAr!'pCT?τ%L`+ ʰ!#CP@2iD"=`OXD$61O\a[8WbE+Ni ;GIF89a`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    !   ,    `    	H*\ BlHŋ#bȱEC	rɓ(S<	Õ0I,ǁ iܹ0'N@FteУ
ԉϥMB5TNFZ)׮A)vͲfcMZ8QKs/E7o߼`r#x1211希/c~r῝99z$ҢQs<Zik_0߻Y5o7ds6ix%gSO͎3Ëg{6|qcPɷu]~G߂6`}ؙcaH=
7|#
EM~%x'݇4hcmr؜~֣(d:-&p2K+*1"9%3ި\v` ;GIF89a`       vv                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          !   ,    `    	H*\ BlHŋ#bȱEC	rɓ(S<K+cp̛m:φ:AI!MZhPM|*T5j]Rת_Â*YgUfImeDIރs
L8-WGZ3BxҮ/>q3g?;>X4Ҧ)N}u_הaw\;0m׶SMMUI#\wjJ(TzsZ4w뾙'ӫ7}{Ӗy-|}_}=ym7Pu}W vi'18x)߄VhNq6qgaXB"R)"ȹ8th<uX7RXqK$lO߁8>XWfIGu_za>ih ;GIF89a                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                !   ,       	HA*\x0!ÇBHP"E	3xaǋ?2)R!ɒOrdˈ/M8ʗ7[\eϒ?E8cQ5m&eaSOb|ԉW!f}eT`mإeeM&ٰol.Zl;R}4ỀƹXgc}F:Yhej̹3H34dӒQSVm5fFAOp^ڳmōUvoZ}W݁EXZ棡~zj뫱{ln{-FpW\r?tx!~ᝧ yFރIXaq8yx8x	¸6V昡١"#Y'2+B٢/R3"Y#7ȥ^y?CYK٤OSYW♥I~	mq":u2zyBgeRzib顟&ꢣ6Z꣧Fꤜ
j*j⪪**lZlllFkR>,Nm^nn;n+k.+o;okoVڪܬ"\2\B/Kc\sܰ[\1gܱ#\'2+1=5#}93=CAK=t/[]5Es}IMQ=*Tt]vj_}owց]݇8߃w׏ؓ]ٗڋw>#3^:{C^Sc޻s^x3<œͣӳ^ϋ~ٛ=^㞾޾o<<H=Zπ=s$>
ςà4?σ`
?3P@Ѕe@.qANЇA"nЈDBp pfJyN*C2R%4cјB5損-tcxC9>*aE>vQ?d9DBѐGDdDF6яtFI~m5YFNqAYGQ{4QHVҕ!eHZ.)H@  ;GIF89a      vv                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          !   ,       	/ "\XB	B(p"E1:0ǏR8r G%<0ʒ,$L6s	SgO#oVEnTڑ)ʟP=:5iեWf}*5*UVb,ׯ]Ӣ]Vm[cƅ[Vn]gꝻn߼|x[nUl2:;oegLqş=w~thҧ)skͯ9=Zumַ]熽[PڳEGtƇVn缡~Iܥسkν{W|s^y*:?_zrW ~*8B I^ZHx"f8%&c.(cc;bx@($A9$=vE"dOeSx$WJ%[ZiNvi#X\ejeyiҹfxΙg{ީ|gj}"*2zhbBڦv:j)br(U^
jNZj꣩zjnk~*ʚ+ڪd[+L[,˺zmRbkr묶Ւ{٢{»KJo;/[0+<C0J_[L"g<%'s.,sÌs;c|@,4A=4=wE#tOuS|4WK5[[mNwm3X\uje}iӽvxϝw{|wn}#.3~xbC޶v;n9cs8U_zO^z型髣~zo{:˞;ۮt_꿓;L_<˻~}Sc{sՓ٣ÿOK?_ #@Ѐ=	2pAr!'pCT?τ%L`+ ʰ!#CP@2iD"=`OXD$61O\a[8WbE+Ni ;GIF89a       888&&&֨vvvfff䘘HHHVVV                                             !Created with ajaxload.info ! 
   !NETSCAPE2.0   ,       P  di0l!*`Ƒ5و[<iP),IZ$bH85&x5k <yB ! 
  ,       h  GҌh*ਨ@$E}eh @
LcQGBP5 <5UdQ+"g0Ak#A <P70<	0Y8*	#! ! 
  ,       `  #(H*
P	-13
:C1KHH.$ٱy j.WD@Y 0H	,0B
kJU?5w|$k\)! ! 
  ,       R  di 1@Ck!B`? #E8zBQXcmv" £``UFrp)f! ! 
  ,       `  di@E1m]ǹHІ(4 (,F!aH XSm5bDH ab,
%p3c#'"467P&*X/($! ! 
  ,       _  diH@@4 ²A"I`>nI0$K7H,-t*E-``1@C7h/1f\)&! ;         GIF89a`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 !   ,    `    	H*\ BlHŋ#bȱEC	rɓ(S<K+cp̛m:φ:AI!MZhPM|*T5j]Rת_Â*YgUfImeDIރs
L8-WGZ3BxҮ/>q3g?;>X4Ҧ)N}u_הaw\;0m׶SMMUI#\wjJ(TzsZ4w뾙'ӫ7}{Ӗy-|}_}=ym7Pu}W vi'18x)߄VhNq6qgaXB"R)"ȹ8th<uX7RXqK$lO߁8>XWfIGu_za>ih ;PNG

   IHDR   (   (   m   IDATXM
0YNi_d(,EGAüBoK?w﹣YVjP	P'PqPHVʞx&p7oP

@%d@5$@E@USz쉇<gu*@&M2WmeIVZM2RVm4Im& a0 v-P    IENDB`PNG

   IHDR      d   G,Z`   -IDATc8|&!D`````~.N Bh,    IENDB`PNG

   IHDR       _:M   rIDAT8;
! ؈bm=UKk$sM 8 rΛw˹򯖟#RC/hu?|R6R1ރ9ZjA!^>*     IENDB`PNG

   IHDR   (   d   drz   yIDATh1  R	7(ȚV`%X	V`%X	V`%X	V`%X	V`%X	V`%X	V`%X	V`%X	V`%X	V`%X	V`%X	V`%X	Vj)2N    IENDB`PNG

   IHDR        oX
   CIDAT8ϱ0Dуzaƅd(  +f'yU<fl>S    IENDB`PNG

   IHDR        Nzo   PLTE&ha   NtRNS 2P."Tp@f` <BHJZ&0R,4j8D|($
blߝF>n~hhH  _IDATx]c۶JZgv,ٲ&{?:-[3Ү3q JOp tB	}6x9sSmCXȸR<QήF ?SHf+&ytSE-G8>Am٪d ~Z#sկ6'аfN(0%#r(DXXKQL^J*KʱzTA~yd-TLieSS(Kň< bۜE%NS~._c$QUb=+C5>W-Z8BHؗ+$~ǫ+e9*9J*VDoq@.i
ovR~SH6w_vcU˂5y@~Rת#J9"!ꎾJ:d$.3@nVew%w>#vSvᤵ#,e]Tq/|cթbfppߋbH1F S sL(?"#YP)C6C\$V-A$bߏ3R4m`G\~
c:C.UasuC]7<e7,4	ʯUW-Cv7uT{%*9"VzOFU8ь) Y~+%X4STaWDSWeju^ѓIMg/_Moe"&~m '
sOW7-;3xf7yr#C+9ckM].8qYd#R` kaU^k#/P?*u$~HY52֟^|b{|a,?kE/vkL? o=;dxlE{A:?aM2$GqB+hC>te_O8d0wPlE`AAɂ[.zda VĀ#O4&k?V
`]ْP#NJ7Ybe7,H[F24eYS ۉ|B&]KR˥ŶATS6?h{9"\vr9U{qvk/0W+?q"GW˨`wͤWAF-`a e]n"bMB]p+5޿3G]SÎ.1Yax)Ã[<+>smT؆*sɴ,K۶\ij`erY 9yaЩ
L|Ϟ)L[T7GRPP$/0*vStWFCE /2:htL?8;>l<Q7FvA@lˠUlF(t6? sS\ VOøvW"OУ3u&Xzxv3\w?w?=2V\@%q@F[;U(
R^8k?tKwJ(料͋t3TK`k"B=(Y{"N|XH=P 22  }pw=l<]T-cH̍s&I	d<x1nͷp?5Q/^O<k-Ed:z/'<I=jZPs'AV-fT}G2v{,|XA6ANYɸBzٺr"VS@(|?@0:㊏;q;ճv
.8of%zSROFFx&\8 wO(_G
ؽ-?qwǏYG4T+N[>fYd 6ɩ}{ZiukDJӟS\^zL,uFtKyh}jdrf$3<A10ǟ{q>:Cd.Uٽ{AojRN	簐џQ	S /]VTq _G9sE$Zw a͏FUH#	e G1ZwV7>naO[+ʀ4HF^׆ONfTpzaƀV@O//S]SύwxTnځZG#N"a]s՜X7
`G{v´?VW_FYͩi+U'4V7%yT`뇪rXfOo@Ao>Wn2K*fǦMh:7 5M+ЏyN<ÊP	Lon>h:ǙvI~9畺K 5fdķ c=8983K4jvyi|@v0cNv+̩1WrJ<=Qm[=(A3LJLX	H˦6:խziJc'f&Lt v}15|%۶%2oCm _x\c)VaF3<nF|wa,~s Kp=Bb֊v91n%cNX8;T!C	7Ǎ0=vwOӡO?a1sx22az2p#O|@UTǝ`SM\7f~7!`YQP2 Ac% TY {mWnA%D(q Qݤ]^JD`A0( xzA{,+z+
`x<xޕ<>p[<o'
av}fPK	@tâxfj8~?|hpP'222:^v2`v{'`	^}9@#p=,'@HC~XHU0|bO∀|cp	=kcw*##㡣7K>oǽ$\FFO"vp30Fz8L&2pG>0V~XQO~!E
0t${

F0{F「{bZ),\(<`0o%JVA=#J֟߆L4  lO/ܫbĪ(X &ܮ`XZw222>*Dg)	0ݱ*ouJ(=M^ 8IV },f >+! >? @ejBD8pOagd|PTqg$Ǐ8i)s0,C~\:UV6U
\`77`V1c@fN/ɪǿfPʃV]*hw. 藢{7iHu}Jn3@ veb d?wPyW˂ ErٵyI*RV 2~ET~=N8e!	*{,F-:.Yg (^!.j4^6Ե5o	B}|~[ ];CU
[R)aT>7/{Ky&Ϥ{QOy)#ârύ~a!&WzZ졽Tץ<vhA'^ٕg"ӖzT@zS2Z9}T Ua-HMN7*g1;nI
fpBk%y!է#]@	X5BW@_aEW&u@ѨeCN絷6! dYGF'sÀrA/X&fӂXtV_B_Wo^-9m)K-}Xl:}oBU;M8N)S_N]rdɕ/Nt3_B
gZz>Rҥ_s]4"oEDAwUT 8Hvo%sn\Hy$ȴ hz4qR;yu5:??@V'.vlcl77^WQgZ-&5_D ?1EBTNN	ٞqJ/{^b!#{ ~M{x/-Jn)Qljk=%46}t
yX3KȊ7D:m{μ0-2TULPĆX@ ׎|M#D/vzXp< %#_%=/9(@C@	YMkf#-r@Cʭd8aG@ƌ< @޻@Fƃǃ~?llǆ/wlTLǆRnFWbA%Igש½'39R^MRV֡ UuC+0i=YS}!uۖ,V/B5,.C|r	Z^;0p&h"?ȏo7~olap,lr_UaFH\zh+G_mB[޶ CշjSz322`t裇:{GC@{E
:\^	 
?* ;ۢ9/BAo_
@[@] Qlu f;s    IENDB`PNG

   IHDR         IJ   PLTE   NtRNS 2P."Tp@f` <BHJZ&0R,4j8D|($
blߝF>n~hhH  IDATx]b۶H儒-{iZK:glkn-tIqq?  E$dK>$>; PZ sVh!Sy0E0}H)-tkoܪKp\RϠ .E7
)*V;~PeBx*,=$zDؾ  JҸٻ 9{ ǸHpqW@"2'B[$ @TiH/b٥96!XHq`DE*R HV!%;"
i]dddddddd4y5 	Rb@(8CdŪݡ,@T@ibrq0alX!pe,	=4bW {
5Ƭhu~(Q^@3="b5XC@JCT76q_5@,r	šɩD)T|O@
ON-ՙ	[n@RXIm݋(F @?=0puL;g$@6η
K`>п @h գKVn"a"%l@.v$/U^G:#`` uTtK~ŋZ5T%kxk]\*Q,҇B44OXK|yg+_M(lоEO
 V$T1BXb-|?@ fBXr%'@ҹA\IJ,}BBc\V
rh(]tI^}oצoS3	";ʙb}"߰	){b$Gwwݾab")T@pF_er6JvШ"mޭM-d76x˰6ӥ;/`>KrP\_^u1%OTM.} Q3.Nس} )>-w`a+sy$t)NbFFFFBejnNVn4,A*X*5>PGa3	{oB&<L[Nc.öi=` Q@d
͆I.Il`\t[< Cit484-r+f쑱BCB MH	iy }>rxp|z;BǏ;burcK4tz1G~`ؚK|	̔>ۡO$~
Ao)0pzz
} i `;ADm8n:cfA@s7L  Z/..h8or?N93B~o_'` opO-:TG	L;7]`B%˛>*wTpM 0H}&t^1'Oqr'2P͡+z,tIW''|en=ǳgRm[NStK{҉mؓVt6ҲR`ζN&}B	U(r<qȁVyrrA**دzg6D#	YP`vs~(zMle|uQa*}+TRXc"+*NlNhcFt<N+;-}،Xtٕ$à^|uv*~'E_51qs*R`OΒ9#x449#WHۏZ)]0`p<ߝNoY{476ǹ>ۗ&1%Q''?l׸+&r{jN಻4)`N狌.߭ ǣ)q	2?n3Hb`} .`pqY1e_bu7e+N_F(DT,L}LLrmP5|x芥1cx DAb`M(7NED~<v\	%,ߚ/pR~/^lnp7t0_0l4_b0MWΦjmбɎl
|reȫ`B-v.iRox}
)%#`ЂR5CA2sua sYy3=jaeoI7~.plA΃
`O)	^>Mz	+4BXd.Mzv͈Pd8p<6?8N*x.6ڍ6G FZ)O	!lSshssNp8`'0/<s}.@Ǩs7ξO۟VDa5a v]m1+3 y6۠>@u50Ps51==p *KVҫ܂ݻc$N4(Xr2###c-賟Lδ>]5.sYs1f0;'̨Yg銛{@9	`aC(=%bo2=n1	jBoS$n#m =i0ci9}oI	qT] W%.(؅]z\x
f"]o'u䫵tk{v;A C3ֆwwR_#X(xҋ/q%Whpk_IX'b/fXKi"#####QCLi2t5L 0
QiH2;yTOok;עٶ`RNg{zy! Kxm?A(vU~mL(`o/!nmX-{v [ dw=n「sdwzn(}Oy~m
?XU;, V'+V&JRZ]᧭:zC'-߆@y4u`Vۓwъ#zP@QN>2/{\o) W~a3xLw:_Q;=pּdt\'8~3SRP6y+XQ*޺r
̗ѭ*޺r
gl/\U^u$|mbVnw\V|D͊NVNy7 k<;/E}?E*ǳgO ~g/96f
cD}%g$QG7o) UJo,O@0߾Q(;bw:5	NwRN5Iy'K?}:9mֽ*@f@jU9mҫÍ{$ ؗ}dFp|%!DdF>}G{@FFFFFFƦQܞH 
3
u	Mo~vy}mwz<7nP9rWku=|_nz쿳}@IXn?s<uP    IENDB`PNG

   IHDR      d   G,Z`   +IDATcطo&EJJ"?@3 X*L    IENDB`PNG

   IHDR         IJ   PLTELLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL/g0   NtRNS 2P."Tp@f` <BHJZ&0R,4j8D|($
blߝF>n~hhH  IDATx]b۶H儒-{iZK:glkn-tIqq?  E$dK>$>; PZ sVh!Sy0E0}H)-tkoܪKp\RϠ .E7
)*V;~PeBx*,=$zDؾ  JҸٻ 9{ ǸHpqW@"2'B[$ @TiH/b٥96!XHq`DE*R HV!%;"
i]dddddddd4y5 	Rb@(8CdŪݡ,@T@ibrq0alX!pe,	=4bW {
5Ƭhu~(Q^@3="b5XC@JCT76q_5@,r	šɩD)T|O@
ON-ՙ	[n@RXIm݋(F @?=0puL;g$@6η
K`>п @h գKVn"a"%l@.v$/U^G:#`` uTtK~ŋZ5T%kxk]\*Q,҇B44OXK|yg+_M(lоEO
 V$T1BXb-|?@ fBXr%'@ҹA\IJ,}BBc\V
rh(]tI^}oצoS3	";ʙb}"߰	){b$Gwwݾab")T@pF_er6JvШ"mޭM-d76x˰6ӥ;/`>KrP\_^u1%OTM.} Q3.Nس} )>-w`a+sy$t)NbFFFFBejnNVn4,A*X*5>PGa3	{oB&<L[Nc.öi=` Q@d
͆I.Il`\t[< Cit484-r+f쑱BCB MH	iy }>rxp|z;BǏ;burcK4tz1G~`ؚK|	̔>ۡO$~
Ao)0pzz
} i `;ADm8n:cfA@s7L  Z/..h8or?N93B~o_'` opO-:TG	L;7]`B%˛>*wTpM 0H}&t^1'Oqr'2P͡+z,tIW''|en=ǳgRm[NStK{҉mؓVt6ҲR`ζN&}B	U(r<qȁVyrrA**دzg6D#	YP`vs~(zMle|uQa*}+TRXc"+*NlNhcFt<N+;-}،Xtٕ$à^|uv*~'E_51qs*R`OΒ9#x449#WHۏZ)]0`p<ߝNoY{476ǹ>ۗ&1%Q''?l׸+&r{jN಻4)`N狌.߭ ǣ)q	2?n3Hb`} .`pqY1e_bu7e+N_F(DT,L}LLrmP5|x芥1cx DAb`M(7NED~<v\	%,ߚ/pR~/^lnp7t0_0l4_b0MWΦjmбɎl
|reȫ`B-v.iRox}
)%#`ЂR5CA2sua sYy3=jaeoI7~.plA΃
`O)	^>Mz	+4BXd.Mzv͈Pd8p<6?8N*x.6ڍ6G FZ)O	!lSshssNp8`'0/<s}.@Ǩs7ξO۟VDa5a v]m1+3 y6۠>@u50Ps51==p *KVҫ܂ݻc$N4(Xr2###c-賟Lδ>]5.sYs1f0;'̨Yg銛{@9	`aC(=%bo2=n1	jBoS$n#m =i0ci9}oI	qT] W%.(؅]z\x
f"]o'u䫵tk{v;A C3ֆwwR_#X(xҋ/q%Whpk_IX'b/fXKi"#####QCLi2t5L 0
QiH2;yTOok;עٶ`RNg{zy! Kxm?A(vU~mL(`o/!nmX-{v [ dw=n「sdwzn(}Oy~m
?XU;, V'+V&JRZ]᧭:zC'-߆@y4u`Vۓwъ#zP@QN>2/{\o) W~a3xLw:_Q;=pּdt\'8~3SRP6y+XQ*޺r
̗ѭ*޺r
gl/\U^u$|mbVnw\V|D͊NVNy7 k<;/E}?E*ǳgO ~g/96f
cD}%g$QG7o) UJo,O@0߾Q(;bw:5	NwRN5Iy'K?}:9mֽ*@f@jU9mҫÍ{$ ؗ}dFp|%!DdF>}G{@FFFFFFƦQܞH 
3
u	Mo~vy}mwz<7nP9rWku=|_nz쿳}@IXn?s<uP    IENDB`PNG

   IHDR      d   G,Z`   8IDATݏ  ÜP_(KؑXXBΑpjAWch~	^rB]    IENDB`PNG

   IHDR         IJ   PLTEi   NtRNS 2P."Tp@f` <BHJZ&0R,4j8D|($
blߝF>n~hhH  IDATx]b۶H儒-{iZK:glkn-tIqq?  E$dK>$>; PZ sVh!Sy0E0}H)-tkoܪKp\RϠ .E7
)*V;~PeBx*,=$zDؾ  JҸٻ 9{ ǸHpqW@"2'B[$ @TiH/b٥96!XHq`DE*R HV!%;"
i]dddddddd4y5 	Rb@(8CdŪݡ,@T@ibrq0alX!pe,	=4bW {
5Ƭhu~(Q^@3="b5XC@JCT76q_5@,r	šɩD)T|O@
ON-ՙ	[n@RXIm݋(F @?=0puL;g$@6η
K`>п @h գKVn"a"%l@.v$/U^G:#`` uTtK~ŋZ5T%kxk]\*Q,҇B44OXK|yg+_M(lоEO
 V$T1BXb-|?@ fBXr%'@ҹA\IJ,}BBc\V
rh(]tI^}oצoS3	";ʙb}"߰	){b$Gwwݾab")T@pF_er6JvШ"mޭM-d76x˰6ӥ;/`>KrP\_^u1%OTM.} Q3.Nس} )>-w`a+sy$t)NbFFFFBejnNVn4,A*X*5>PGa3	{oB&<L[Nc.öi=` Q@d
͆I.Il`\t[< Cit484-r+f쑱BCB MH	iy }>rxp|z;BǏ;burcK4tz1G~`ؚK|	̔>ۡO$~
Ao)0pzz
} i `;ADm8n:cfA@s7L  Z/..h8or?N93B~o_'` opO-:TG	L;7]`B%˛>*wTpM 0H}&t^1'Oqr'2P͡+z,tIW''|en=ǳgRm[NStK{҉mؓVt6ҲR`ζN&}B	U(r<qȁVyrrA**دzg6D#	YP`vs~(zMle|uQa*}+TRXc"+*NlNhcFt<N+;-}،Xtٕ$à^|uv*~'E_51qs*R`OΒ9#x449#WHۏZ)]0`p<ߝNoY{476ǹ>ۗ&1%Q''?l׸+&r{jN಻4)`N狌.߭ ǣ)q	2?n3Hb`} .`pqY1e_bu7e+N_F(DT,L}LLrmP5|x芥1cx DAb`M(7NED~<v\	%,ߚ/pR~/^lnp7t0_0l4_b0MWΦjmбɎl
|reȫ`B-v.iRox}
)%#`ЂR5CA2sua sYy3=jaeoI7~.plA΃
`O)	^>Mz	+4BXd.Mzv͈Pd8p<6?8N*x.6ڍ6G FZ)O	!lSshssNp8`'0/<s}.@Ǩs7ξO۟VDa5a v]m1+3 y6۠>@u50Ps51==p *KVҫ܂ݻc$N4(Xr2###c-賟Lδ>]5.sYs1f0;'̨Yg銛{@9	`aC(=%bo2=n1	jBoS$n#m =i0ci9}oI	qT] W%.(؅]z\x
f"]o'u䫵tk{v;A C3ֆwwR_#X(xҋ/q%Whpk_IX'b/fXKi"#####QCLi2t5L 0
QiH2;yTOok;עٶ`RNg{zy! Kxm?A(vU~mL(`o/!nmX-{v [ dw=n「sdwzn(}Oy~m
?XU;, V'+V&JRZ]᧭:zC'-߆@y4u`Vۓwъ#zP@QN>2/{\o) W~a3xLw:_Q;=pּdt\'8~3SRP6y+XQ*޺r
̗ѭ*޺r
gl/\U^u$|mbVnw\V|D͊NVNy7 k<;/E}?E*ǳgO ~g/96f
cD}%g$QG7o) UJo,O@0߾Q(;bw:5	NwRN5Iy'K?}:9mֽ*@f@jU9mҫÍ{$ ؗ}dFp|%!DdF>}G{@FFFFFFƦQܞH 
3
u	Mo~vy}mwz<7nP9rWku=|_nz쿳}@IXn?s<uP    IENDB`PNG

   IHDR        Nzo   PLTE,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,E|   NtRNS 2P."Tp@f` <BHJZ&0R,4j8D|($
blߝF>n~hhH  _IDATx]c۶JZgv,ٲ&{?:-[3Ү3q JOp tB	}6x9sSmCXȸR<QήF ?SHf+&ytSE-G8>Am٪d ~Z#sկ6'аfN(0%#r(DXXKQL^J*KʱzTA~yd-TLieSS(Kň< bۜE%NS~._c$QUb=+C5>W-Z8BHؗ+$~ǫ+e9*9J*VDoq@.i
ovR~SH6w_vcU˂5y@~Rת#J9"!ꎾJ:d$.3@nVew%w>#vSvᤵ#,e]Tq/|cթbfppߋbH1F S sL(?"#YP)C6C\$V-A$bߏ3R4m`G\~
c:C.UasuC]7<e7,4	ʯUW-Cv7uT{%*9"VzOFU8ь) Y~+%X4STaWDSWeju^ѓIMg/_Moe"&~m '
sOW7-;3xf7yr#C+9ckM].8qYd#R` kaU^k#/P?*u$~HY52֟^|b{|a,?kE/vkL? o=;dxlE{A:?aM2$GqB+hC>te_O8d0wPlE`AAɂ[.zda VĀ#O4&k?V
`]ْP#NJ7Ybe7,H[F24eYS ۉ|B&]KR˥ŶATS6?h{9"\vr9U{qvk/0W+?q"GW˨`wͤWAF-`a e]n"bMB]p+5޿3G]SÎ.1Yax)Ã[<+>smT؆*sɴ,K۶\ij`erY 9yaЩ
L|Ϟ)L[T7GRPP$/0*vStWFCE /2:htL?8;>l<Q7FvA@lˠUlF(t6? sS\ VOøvW"OУ3u&Xzxv3\w?w?=2V\@%q@F[;U(
R^8k?tKwJ(料͋t3TK`k"B=(Y{"N|XH=P 22  }pw=l<]T-cH̍s&I	d<x1nͷp?5Q/^O<k-Ed:z/'<I=jZPs'AV-fT}G2v{,|XA6ANYɸBzٺr"VS@(|?@0:㊏;q;ճv
.8of%zSROFFx&\8 wO(_G
ؽ-?qwǏYG4T+N[>fYd 6ɩ}{ZiukDJӟS\^zL,uFtKyh}jdrf$3<A10ǟ{q>:Cd.Uٽ{AojRN	簐џQ	S /]VTq _G9sE$Zw a͏FUH#	e G1ZwV7>naO[+ʀ4HF^׆ONfTpzaƀV@O//S]SύwxTnځZG#N"a]s՜X7
`G{v´?VW_FYͩi+U'4V7%yT`뇪rXfOo@Ao>Wn2K*fǦMh:7 5M+ЏyN<ÊP	Lon>h:ǙvI~9畺K 5fdķ c=8983K4jvyi|@v0cNv+̩1WrJ<=Qm[=(A3LJLX	H˦6:խziJc'f&Lt v}15|%۶%2oCm _x\c)VaF3<nF|wa,~s Kp=Bb֊v91n%cNX8;T!C	7Ǎ0=vwOӡO?a1sx22az2p#O|@UTǝ`SM\7f~7!`YQP2 Ac% TY {mWnA%D(q Qݤ]^JD`A0( xzA{,+z+
`x<xޕ<>p[<o'
av}fPK	@tâxfj8~?|hpP'222:^v2`v{'`	^}9@#p=,'@HC~XHU0|bO∀|cp	=kcw*##㡣7K>oǽ$\FFO"vp30Fz8L&2pG>0V~XQO~!E
0t${

F0{F「{bZ),\(<`0o%JVA=#J֟߆L4  lO/ܫbĪ(X &ܮ`XZw222>*Dg)	0ݱ*ouJ(=M^ 8IV },f >+! >? @ejBD8pOagd|PTqg$Ǐ8i)s0,C~\:UV6U
\`77`V1c@fN/ɪǿfPʃV]*hw. 藢{7iHu}Jn3@ veb d?wPyW˂ ErٵyI*RV 2~ET~=N8e!	*{,F-:.Yg (^!.j4^6Ե5o	B}|~[ ];CU
[R)aT>7/{Ky&Ϥ{QOy)#ârύ~a!&WzZ졽Tץ<vhA'^ٕg"ӖzT@zS2Z9}T Ua-HMN7*g1;nI
fpBk%y!է#]@	X5BW@_aEW&u@ѨeCN絷6! dYGF'sÀrA/X&fӂXtV_B_Wo^-9m)K-}Xl:}oBU;M8N)S_N]rdɕ/Nt3_B
gZz>Rҥ_s]4"oEDAwUT 8Hvo%sn\Hy$ȴ hz4qR;yu5:??@V'.vlcl77^WQgZ-&5_D ?1EBTNN	ٞqJ/{^b!#{ ~M{x/-Jn)Qljk=%46}t
yX3KȊ7D:m{μ0-2TULPĆX@ ׎|M#D/vzXp< %#_%=/9(@C@	YMkf#-r@Cʭd8aG@ƌ< @޻@Fƃǃ~?llǆ/wlTLǆRnFWbA%Igש½'39R^MRV֡ UuC+0i=YS}!uۖ,V/B5,.C|r	Z^;0p&h"?ȏo7~olap,lr_UaFH\zh+G_mB[޶ CշjSz322`t裇:{GC@{E
:\^	 
?* ;ۢ9/BAo_
@[@] Qlu f;s    IENDB`GIF89a    ݻwwwfffUUUDDD333"""                                                  !NETSCAPE2.0   !  ,       w $B$B##(<L
3ðDH$^@Pd"UP#a\;̓1

o::0
v@$|,3_#	d53"s5e! !  ,       c $Ё9*"#
83b4k BJ`4<q8첐B_sDP@UӠdZf*i"()VY#! !  ,       ` $Pa
K*:	u#@tX 
!&0<U#'hm'@Y^ha-k(.N|$Cf)@f|! !  ,       b $bA@"&
-"*6CȀ*+`j42` 5Xp	h/H`.	hR"]SWB]~(! !  ,       I $qæB,n[h*G
UܑH )8GtJ^S@-*Dm˦ؤT  !  ,       q $0(qkȩ7AGd(10d	X`U	eR!PTh (v!_"PQVeYi)Z`x#'3y|)! !  ,       ` $ 8EIF0C
T@F`B4	AbZbq 	 )/azSS&V	p$! !  ,      ^ $B8"1ڢ®0B	R0
v"BlpXbݤFaAA&*Xǁ(@3,(}Q+>	R! !  ,       c $PxB +*-[dඁ+i@
)`L
?'I`JGbPhXB)0׸XQ#}	No"tI+ZI! !  ,      \ $P`8*1h0rx8BQaV 
!MDl!4%BBe
PDY00! !  ,      ] $$I>Q] d"28	GqH9	 A2ȀB", DH('4C
\0`UL"r(! !	  ,       d $dI`ìkBB 
m
A72,
(PX鲪	8@R%a	K*D2E{$ft5C%! ;PNG

   IHDR      d   G,Z`   IDATc&JlI  M"tg    IENDB`PNG

   IHDR      d   G,Z`   BIDATݏ	@2;{peMDyc ՍN0	ZX3X	̣wM0UXU_/g6>>    IENDB`PNG

   IHDR         IJ   PLTE$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$$"$È   NtRNS 2P."Tp@f` <BHJZ&0R,4j8D|($
blߝF>n~hhH  IDATx]b۶H儒-{iZK:glkn-tIqq?  E$dK>$>; PZ sVh!Sy0E0}H)-tkoܪKp\RϠ .E7
)*V;~PeBx*,=$zDؾ  JҸٻ 9{ ǸHpqW@"2'B[$ @TiH/b٥96!XHq`DE*R HV!%;"
i]dddddddd4y5 	Rb@(8CdŪݡ,@T@ibrq0alX!pe,	=4bW {
5Ƭhu~(Q^@3="b5XC@JCT76q_5@,r	šɩD)T|O@
ON-ՙ	[n@RXIm݋(F @?=0puL;g$@6η
K`>п @h գKVn"a"%l@.v$/U^G:#`` uTtK~ŋZ5T%kxk]\*Q,҇B44OXK|yg+_M(lоEO
 V$T1BXb-|?@ fBXr%'@ҹA\IJ,}BBc\V
rh(]tI^}oצoS3	";ʙb}"߰	){b$Gwwݾab")T@pF_er6JvШ"mޭM-d76x˰6ӥ;/`>KrP\_^u1%OTM.} Q3.Nس} )>-w`a+sy$t)NbFFFFBejnNVn4,A*X*5>PGa3	{oB&<L[Nc.öi=` Q@d
͆I.Il`\t[< Cit484-r+f쑱BCB MH	iy }>rxp|z;BǏ;burcK4tz1G~`ؚK|	̔>ۡO$~
Ao)0pzz
} i `;ADm8n:cfA@s7L  Z/..h8or?N93B~o_'` opO-:TG	L;7]`B%˛>*wTpM 0H}&t^1'Oqr'2P͡+z,tIW''|en=ǳgRm[NStK{҉mؓVt6ҲR`ζN&}B	U(r<qȁVyrrA**دzg6D#	YP`vs~(zMle|uQa*}+TRXc"+*NlNhcFt<N+;-}،Xtٕ$à^|uv*~'E_51qs*R`OΒ9#x449#WHۏZ)]0`p<ߝNoY{476ǹ>ۗ&1%Q''?l׸+&r{jN಻4)`N狌.߭ ǣ)q	2?n3Hb`} .`pqY1e_bu7e+N_F(DT,L}LLrmP5|x芥1cx DAb`M(7NED~<v\	%,ߚ/pR~/^lnp7t0_0l4_b0MWΦjmбɎl
|reȫ`B-v.iRox}
)%#`ЂR5CA2sua sYy3=jaeoI7~.plA΃
`O)	^>Mz	+4BXd.Mzv͈Pd8p<6?8N*x.6ڍ6G FZ)O	!lSshssNp8`'0/<s}.@Ǩs7ξO۟VDa5a v]m1+3 y6۠>@u50Ps51==p *KVҫ܂ݻc$N4(Xr2###c-賟Lδ>]5.sYs1f0;'̨Yg銛{@9	`aC(=%bo2=n1	jBoS$n#m =i0ci9}oI	qT] W%.(؅]z\x
f"]o'u䫵tk{v;A C3ֆwwR_#X(xҋ/q%Whpk_IX'b/fXKi"#####QCLi2t5L 0
QiH2;yTOok;עٶ`RNg{zy! Kxm?A(vU~mL(`o/!nmX-{v [ dw=n「sdwzn(}Oy~m
?XU;, V'+V&JRZ]᧭:zC'-߆@y4u`Vۓwъ#zP@QN>2/{\o) W~a3xLw:_Q;=pּdt\'8~3SRP6y+XQ*޺r
̗ѭ*޺r
gl/\U^u$|mbVnw\V|D͊NVNy7 k<;/E}?E*ǳgO ~g/96f
cD}%g$QG7o) UJo,O@0߾Q(;bw:5	NwRN5Iy'K?}:9mֽ*@f@jU9mҫÍ{$ ؗ}dFp|%!DdF>}G{@FFFFFFƦQܞH 
3
u	Mo~vy}mwz<7nP9rWku=|_nz쿳}@IXn?s<uP    IENDB`/*
* jQuery UI CSS Framework
* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
*/

/* Layout helpers
----------------------------------*/
.ui-helper-hidden { display: none; }
.ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
.ui-helper-clearfix { display: inline-block; }
/* required comment for clearfix to work in Opera \*/
* html .ui-helper-clearfix { height:1%; }
.ui-helper-clearfix { display:block; }
/* end clearfix */
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }


/* Interaction Cues
----------------------------------*/
.ui-state-disabled { cursor: default !important; }


/* Icons
----------------------------------*/

/* states and images */
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }


/* Misc visuals
----------------------------------*/

/* Overlays */
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }


/*
* jQuery UI CSS Framework
* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,%20Arial,%20sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=333333&bgTextureHeader=08_diagonals_thick.png&bgImgOpacityHeader=8&borderColorHeader=a3a3a3&fcHeader=eeeeee&iconColorHeader=bbbbbb&bgColorContent=f9f9f9&bgTextureContent=04_highlight_hard.png&bgImgOpacityContent=100&borderColorContent=cccccc&fcContent=222222&iconColorContent=222222&bgColorDefault=111111&bgTextureDefault=02_glass.png&bgImgOpacityDefault=40&borderColorDefault=777777&fcDefault=e3e3e3&iconColorDefault=ededed&bgColorHover=1c1c1c&bgTextureHover=02_glass.png&bgImgOpacityHover=55&borderColorHover=000000&fcHover=ffffff&iconColorHover=ffffff&bgColorActive=ffffff&bgTextureActive=01_flat.png&bgImgOpacityActive=65&borderColorActive=cccccc&fcActive=222222&iconColorActive=222222&bgColorHighlight=ffeb80&bgTextureHighlight=06_inset_hard.png&bgImgOpacityHighlight=55&borderColorHighlight=ffde2e&fcHighlight=363636&iconColorHighlight=4ca300&bgColorError=cd0a0a&bgTextureError=06_inset_hard.png&bgImgOpacityError=45&borderColorError=9e0505&fcError=ffffff&iconColorError=ffcf29&bgColorOverlay=aaaaaa&bgTextureOverlay=04_highlight_hard.png&bgImgOpacityOverlay=40&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=03_highlight_soft.png&bgImgOpacityShadow=50&opacityShadow=20&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
*/


/* Component containers
----------------------------------*/
.ui-widget { font-family: Verdana, Arial, sans-serif; font-size: 1.1em; }
.ui-widget .ui-widget { font-size: 1em; }
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana, Arial, sans-serif; font-size: 1em; }
.ui-widget-content { border: 1px solid #cccccc; background: #f9f9f9 url(images/ui-bg_highlight-hard_100_f9f9f9_1x100.png) 50% top repeat-x; color: #222222; }
.ui-widget-content a { color: #222222; }
.ui-widget-header { border: 1px solid #a3a3a3; background: #333333 url(images/ui-bg_diagonals-thick_8_333333_40x40.png) 50% 50% repeat; color: #eeeeee; font-weight: bold; }
.ui-widget-header a { color: #eeeeee; }

/* Interaction states
----------------------------------*/
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #777777; background: #111111 url(images/ui-bg_glass_40_111111_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #e3e3e3; }
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #e3e3e3; text-decoration: none; }
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #000000; background: #1c1c1c url(images/ui-bg_glass_55_1c1c1c_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #ffffff; }
.ui-state-hover a, .ui-state-hover a:hover { color: #ffffff; text-decoration: none; }
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #cccccc; background: #ffffff url(images/ui-bg_flat_65_ffffff_40x100.png) 50% 50% repeat-x; font-weight: normal; color: #222222; }
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #222222; text-decoration: none; }
.ui-widget :active { outline: none; }

/* Interaction Cues
----------------------------------*/
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight  {border: 1px solid #ffde2e; background: #ffeb80 url(images/ui-bg_inset-hard_55_ffeb80_1x100.png) 50% bottom repeat-x; color: #363636; }
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #9e0505; background: #cd0a0a url(images/ui-bg_inset-hard_45_cd0a0a_1x100.png) 50% bottom repeat-x; color: #ffffff; }
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #ffffff; }
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #ffffff; }
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary,  .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }

/* Icons
----------------------------------*/

/* states and images */
.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
.ui-widget-header .ui-icon {background-image: url(images/ui-icons_bbbbbb_256x240.png); }
.ui-state-default .ui-icon { background-image: url(images/ui-icons_ededed_256x240.png); }
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }
.ui-state-active .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_4ca300_256x240.png); }
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_ffcf29_256x240.png); }

/* positioning */
.ui-icon-carat-1-n { background-position: 0 0; }
.ui-icon-carat-1-ne { background-position: -16px 0; }
.ui-icon-carat-1-e { background-position: -32px 0; }
.ui-icon-carat-1-se { background-position: -48px 0; }
.ui-icon-carat-1-s { background-position: -64px 0; }
.ui-icon-carat-1-sw { background-position: -80px 0; }
.ui-icon-carat-1-w { background-position: -96px 0; }
.ui-icon-carat-1-nw { background-position: -112px 0; }
.ui-icon-carat-2-n-s { background-position: -128px 0; }
.ui-icon-carat-2-e-w { background-position: -144px 0; }
.ui-icon-triangle-1-n { background-position: 0 -16px; }
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
.ui-icon-triangle-1-e { background-position: -32px -16px; }
.ui-icon-triangle-1-se { background-position: -48px -16px; }
.ui-icon-triangle-1-s { background-position: -64px -16px; }
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
.ui-icon-triangle-1-w { background-position: -96px -16px; }
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
.ui-icon-arrow-1-n { background-position: 0 -32px; }
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
.ui-icon-arrow-1-e { background-position: -32px -32px; }
.ui-icon-arrow-1-se { background-position: -48px -32px; }
.ui-icon-arrow-1-s { background-position: -64px -32px; }
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
.ui-icon-arrow-1-w { background-position: -96px -32px; }
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
.ui-icon-arrow-4 { background-position: 0 -80px; }
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
.ui-icon-extlink { background-position: -32px -80px; }
.ui-icon-newwin { background-position: -48px -80px; }
.ui-icon-refresh { background-position: -64px -80px; }
.ui-icon-shuffle { background-position: -80px -80px; }
.ui-icon-transfer-e-w { background-position: -96px -80px; }
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
.ui-icon-folder-collapsed { background-position: 0 -96px; }
.ui-icon-folder-open { background-position: -16px -96px; }
.ui-icon-document { background-position: -32px -96px; }
.ui-icon-document-b { background-position: -48px -96px; }
.ui-icon-note { background-position: -64px -96px; }
.ui-icon-mail-closed { background-position: -80px -96px; }
.ui-icon-mail-open { background-position: -96px -96px; }
.ui-icon-suitcase { background-position: -112px -96px; }
.ui-icon-comment { background-position: -128px -96px; }
.ui-icon-person { background-position: -144px -96px; }
.ui-icon-print { background-position: -160px -96px; }
.ui-icon-trash { background-position: -176px -96px; }
.ui-icon-locked { background-position: -192px -96px; }
.ui-icon-unlocked { background-position: -208px -96px; }
.ui-icon-bookmark { background-position: -224px -96px; }
.ui-icon-tag { background-position: -240px -96px; }
.ui-icon-home { background-position: 0 -112px; }
.ui-icon-flag { background-position: -16px -112px; }
.ui-icon-calendar { background-position: -32px -112px; }
.ui-icon-cart { background-position: -48px -112px; }
.ui-icon-pencil { background-position: -64px -112px; }
.ui-icon-clock { background-position: -80px -112px; }
.ui-icon-disk { background-position: -96px -112px; }
.ui-icon-calculator { background-position: -112px -112px; }
.ui-icon-zoomin { background-position: -128px -112px; }
.ui-icon-zoomout { background-position: -144px -112px; }
.ui-icon-search { background-position: -160px -112px; }
.ui-icon-wrench { background-position: -176px -112px; }
.ui-icon-gear { background-position: -192px -112px; }
.ui-icon-heart { background-position: -208px -112px; }
.ui-icon-star { background-position: -224px -112px; }
.ui-icon-link { background-position: -240px -112px; }
.ui-icon-cancel { background-position: 0 -128px; }
.ui-icon-plus { background-position: -16px -128px; }
.ui-icon-plusthick { background-position: -32px -128px; }
.ui-icon-minus { background-position: -48px -128px; }
.ui-icon-minusthick { background-position: -64px -128px; }
.ui-icon-close { background-position: -80px -128px; }
.ui-icon-closethick { background-position: -96px -128px; }
.ui-icon-key { background-position: -112px -128px; }
.ui-icon-lightbulb { background-position: -128px -128px; }
.ui-icon-scissors { background-position: -144px -128px; }
.ui-icon-clipboard { background-position: -160px -128px; }
.ui-icon-copy { background-position: -176px -128px; }
.ui-icon-contact { background-position: -192px -128px; }
.ui-icon-image { background-position: -208px -128px; }
.ui-icon-video { background-position: -224px -128px; }
.ui-icon-script { background-position: -240px -128px; }
.ui-icon-alert { background-position: 0 -144px; }
.ui-icon-info { background-position: -16px -144px; }
.ui-icon-notice { background-position: -32px -144px; }
.ui-icon-help { background-position: -48px -144px; }
.ui-icon-check { background-position: -64px -144px; }
.ui-icon-bullet { background-position: -80px -144px; }
.ui-icon-radio-off { background-position: -96px -144px; }
.ui-icon-radio-on { background-position: -112px -144px; }
.ui-icon-pin-w { background-position: -128px -144px; }
.ui-icon-pin-s { background-position: -144px -144px; }
.ui-icon-play { background-position: 0 -160px; }
.ui-icon-pause { background-position: -16px -160px; }
.ui-icon-seek-next { background-position: -32px -160px; }
.ui-icon-seek-prev { background-position: -48px -160px; }
.ui-icon-seek-end { background-position: -64px -160px; }
.ui-icon-seek-start { background-position: -80px -160px; }
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
.ui-icon-seek-first { background-position: -80px -160px; }
.ui-icon-stop { background-position: -96px -160px; }
.ui-icon-eject { background-position: -112px -160px; }
.ui-icon-volume-off { background-position: -128px -160px; }
.ui-icon-volume-on { background-position: -144px -160px; }
.ui-icon-power { background-position: 0 -176px; }
.ui-icon-signal-diag { background-position: -16px -176px; }
.ui-icon-signal { background-position: -32px -176px; }
.ui-icon-battery-0 { background-position: -48px -176px; }
.ui-icon-battery-1 { background-position: -64px -176px; }
.ui-icon-battery-2 { background-position: -80px -176px; }
.ui-icon-battery-3 { background-position: -96px -176px; }
.ui-icon-circle-plus { background-position: 0 -192px; }
.ui-icon-circle-minus { background-position: -16px -192px; }
.ui-icon-circle-close { background-position: -32px -192px; }
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
.ui-icon-circle-zoomin { background-position: -176px -192px; }
.ui-icon-circle-zoomout { background-position: -192px -192px; }
.ui-icon-circle-check { background-position: -208px -192px; }
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
.ui-icon-circlesmall-close { background-position: -32px -208px; }
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
.ui-icon-squaresmall-close { background-position: -80px -208px; }
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }


/* Misc visuals
----------------------------------*/

/* Corner radius */
.ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; }
.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; }
.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; }
.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
.ui-corner-right {  -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; }

/* Overlays */
.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_highlight-hard_40_aaaaaa_1x100.png) 50% top repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_highlight-soft_50_aaaaaa_1x100.png) 50% top repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/* Resizable
----------------------------------*/
.ui-resizable { position: relative;}
.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Selectable
----------------------------------*/
.ui-selectable-helper { border:1px dotted black }
/* Accordion
----------------------------------*/
.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
.ui-accordion .ui-accordion-li-fix { display: inline; }
.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
/* IE7-/Win - Fix extra vertical space in lists */
.ui-accordion a { zoom: 1; }
.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
.ui-accordion .ui-accordion-content-active { display: block; }/* Autocomplete
----------------------------------*/
.ui-autocomplete { position: absolute; cursor: default; }	
.ui-autocomplete-loading { background: white url('images/ui-anim_basic_16x16.gif') right center no-repeat; }

/* workarounds */
* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */

/* Menu
----------------------------------*/
.ui-menu {
	list-style:none;
	padding: 2px;
	margin: 0;
	display:block;
}
.ui-menu .ui-menu {
	margin-top: -3px;
}
.ui-menu .ui-menu-item {
	margin:0;
	padding: 0;
	zoom: 1;
	float: left;
	clear: left;
	width: 100%;
}
.ui-menu .ui-menu-item a {
	text-decoration:none;
	display:block;
	padding:.2em .4em;
	line-height:1.5;
	zoom:1;
}
.ui-menu .ui-menu-item a.ui-state-hover,
.ui-menu .ui-menu-item a.ui-state-active {
	font-weight: normal;
	margin: -1px;
}
/* Button
----------------------------------*/

.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
.ui-button-icons-only { width: 3.4em; } 
button.ui-button-icons-only { width: 3.7em; } 

/*button text element */
.ui-button .ui-button-text { display: block; line-height: 1.4;  }
.ui-button-text-only .ui-button-text { padding: .4em 1em; }
.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
.ui-button-text-icon .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
/* no icon support for input elements, provide padding by default */
input.ui-button { padding: .4em 1em; }

/*button icon element(s) */
.ui-button-icon-only .ui-icon, .ui-button-text-icon .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
.ui-button-text-icon .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }

/*button sets*/
.ui-buttonset { margin-right: 7px; }
.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }

/* workarounds */
button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */





/* Dialog
----------------------------------*/
.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
.ui-dialog .ui-dialog-titlebar { padding: .5em 1em .3em; position: relative;  }
.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .2em 0; } 
.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; }
.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
.ui-draggable .ui-dialog-titlebar { cursor: move; }
/* Slider
----------------------------------*/
.ui-slider { position: relative; text-align: left; }
.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }

.ui-slider-horizontal { height: .8em; }
.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
.ui-slider-horizontal .ui-slider-range-min { left: 0; }
.ui-slider-horizontal .ui-slider-range-max { right: 0; }

.ui-slider-vertical { width: .8em; height: 100px; }
.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
.ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs
----------------------------------*/
.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
.ui-tabs .ui-tabs-hide { display: none !important; }
/* Datepicker
----------------------------------*/
.ui-datepicker { width: 17em; padding: .2em .2em 0; }
.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
.ui-datepicker .ui-datepicker-prev { left:2px; }
.ui-datepicker .ui-datepicker-next { right:2px; }
.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
.ui-datepicker .ui-datepicker-next-hover { right:1px; }
.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px;  }
.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
.ui-datepicker select.ui-datepicker-month, 
.ui-datepicker select.ui-datepicker-year { width: 49%;}
.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }
.ui-datepicker td { border: 0; padding: 1px; }
.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }

/* with multiple calendars */
.ui-datepicker.ui-datepicker-multi { width:auto; }
.ui-datepicker-multi .ui-datepicker-group { float:left; }
.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
.ui-datepicker-row-break { clear:both; width:100%; }

/* RTL support */
.ui-datepicker-rtl { direction: rtl; }
.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
.ui-datepicker-rtl .ui-datepicker-group { float:right; }
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }

/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
.ui-datepicker-cover {
    display: none; /*sorry for IE5*/
    display/**/: block; /*sorry for IE5*/
    position: absolute; /*must have*/
    z-index: -1; /*must have*/
    filter: mask(); /*must have*/
    top: -4px; /*must have*/
    left: -4px; /*must have*/
    width: 200px; /*must have*/
    height: 200px; /*must have*/
}/* Progressbar
----------------------------------*/
.ui-progressbar { height:2em; text-align: left; }
.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }<?xml version="1.0"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes" method="html" />
  <xsl:include href="chrome.xsl" />
  <xsl:include href="class.xsl" />

  <xsl:template match="/project" name="file">
    <div id="content">
      <xsl:apply-templates select="/project/file[@path=$path]" />
    </div>
    <small class="footer">Documentation was generated by <a href="http://www.phpdoc.org">phpDocumentor <xsl:value-of select="$version" /></a>.</small>
  </xsl:template>

  <xsl:template match="/project/file">
    <h1><xsl:value-of select="@path" /></h1>
    <div class="file_menu">
      <xsl:if test="count(include) > 0"><a href="#includes">Includes</a> |</xsl:if>
      <xsl:if test="count(function) > 0"><a href="#functions">Functions</a> |</xsl:if>
      <xsl:if test="count(constant) > 0"><a href="#constants">Constants</a> |</xsl:if>
      <xsl:if test="count(class) > 0"><a href="#classes">Classes</a> |</xsl:if>
      <xsl:if test="count(interface) > 0"><a href="#interfaces">Interfaces</a></xsl:if>
    </div>

    <xsl:if test="docblock/tag">
    <div class="properties">
      <h1>Properties</h1>
      <xsl:for-each select="docblock/tag">
        <xsl:sort select="@name" />
        <label class="property-key"><xsl:value-of select="@name" /></label>
        <div class="property-value"><xsl:value-of select="." /></div>
      </xsl:for-each>
    </div>
    </xsl:if>

    <xsl:if test="docblock/description != '' or docblock/long-description != ''">
      <h2>Description</h2>
    </xsl:if>
    <xsl:if test="docblock/description != ''">
      <xsl:value-of select="docblock/description" disable-output-escaping="yes" /><br />
      <br />
    </xsl:if>
    <xsl:if test="docblock/long-description != ''">
      <xsl:value-of select="docblock/long-description" disable-output-escaping="yes"/><br />
    </xsl:if>

    <xsl:if test="include">
      <a name="includes"/>
      <h2>Includes</h2>
      <xsl:for-each select="include">
        <xsl:value-of select="name" />&#160;<span class="nb-faded-text">(<xsl:value-of select="@type" />)</span><br />
      </xsl:for-each>
    </xsl:if>

    <xsl:if test="function">
      <a name="functions" />
      <h2>Functions</h2>
      <xsl:for-each select="function">
        <xsl:apply-templates select="." />
      </xsl:for-each>
    </xsl:if>

    <xsl:if test="constant">
      <a name="constants" />
      <h2>Constants</h2>
      <xsl:for-each select="constant"><xsl:apply-templates select="." /></xsl:for-each>
    </xsl:if>

    <xsl:if test="class">
      <a name="classes" />
      <h2>Classes</h2>
      <xsl:for-each select="class">
        <div id="{name}" class="class">
          <xsl:apply-templates select="." />
        </div>
      </xsl:for-each>
    </xsl:if>

    <xsl:if test="interface">
      <a name="interfaces" />
      <h2>Interfaces</h2>
      <xsl:for-each select="interface">
        <div id="{name}" class="interface">
          <xsl:apply-templates select="." />
        </div>
      </xsl:for-each>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet><?xml version="1.0" encoding="utf-8"?>
<template>
  <author>Mike van Riel</author>
  <email>mike.vanriel@naenius.com</email>
  <version>1.1.2</version>
  <copyright>Mike van Riel / Naenius 2011</copyright>
  <description>This is the Old Ocean theme; the old default for phpDocumentor.</description>
  <transformations>
    <transformation query="copy" writer="FileIo" source="templates/old-ocean/js" artifact="js"/>
    <transformation query="copy" writer="FileIo" source="templates/old-ocean/css" artifact="css"/>
    <transformation query="copy" writer="FileIo" source="templates/old-ocean/images" artifact="images"/>
    <transformation writer="xml" artifact="structure.xml" />
    <transformation writer="xsl" source="templates/old-ocean/preprocess/object-index.xsl" artifact="$object-index" />
    <transformation writer="xsl" source="templates/old-ocean/index.xsl" artifact="index.html">
      <parameters><variables><title>Class Diagram</title></variables></parameters>
    </transformation>
    <transformation writer="xsl" source="templates/old-ocean/classgraph.xsl" artifact="graph.html">
      <parameters><variables><title>phpDocumentor</title></variables></parameters>
    </transformation>
    <transformation query="/project/file/@path" writer="xsl" source="templates/old-ocean/file.xsl" artifact="{$path}">
      <parameters><variables><title>File</title></variables></parameters>
    </transformation>
    <transformation writer="xsl" source="templates/old-ocean/markers.xsl" artifact="markers.html">
      <parameters><variables><title>Markers</title></variables></parameters>
    </transformation>
    <transformation writer="xsl" source="templates/old-ocean/parse_markers.xsl" artifact="parse_markers.html">
      <parameters><variables><title>Errors</title></variables></parameters>
    </transformation>
    <transformation writer="Graph" source="Class" artifact="classes.svg" />
  </transformations>
</template>
<?xml version="1.0"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes" method="html" />

  <xsl:template match="/">
    <xsl:if test="count(/project/namespace[@name != 'default']) > 0">
      <div class="section">
        <h1>Namespaces</h1>
        <!--<input type="checkbox" onclick="$('.treeview-phpdoc small').toggle(!this.checked);" checked="">Compact view<br />-->
        <ul id="namespaces-" class="filetree">
          <xsl:apply-templates select="/project/namespace">
            <xsl:sort select="@name" />
            <xsl:with-param name="parent_name" select="''" />
          </xsl:apply-templates>
        </ul>
      </div>
    </xsl:if>

    <xsl:if test="count(/project/package) > 0">
      <div class="section">
        <h1>Packages</h1>

        <xsl:if test="count(/project/package) &lt; 2">
        <ul id="packages-" class="deadtree">
          <xsl:apply-templates select="/project/package">
            <xsl:sort select="@name" />
          </xsl:apply-templates>
        </ul>
        </xsl:if>

        <xsl:if test="count(/project/package) > 1">
        <ul id="packages-" class="filetree">
          <xsl:apply-templates select="/project/package">
            <xsl:sort select="@name" />
          </xsl:apply-templates>
        </ul>
        </xsl:if>
      </div>
    </xsl:if>

    <!--<h1>Files</h1>-->
    <!--<div id="file">-->
    <!--<xsl:apply-templates select="file">-->
    <!--<xsl:sort select="@path" />-->
    <!--</xsl:apply-templates>-->
    <!--</div>-->
  </xsl:template>

  <xsl:template match="file">
    <h2>
      <xsl:value-of select="@path" />
    </h2>
    <xsl:variable name="file" select="@hash" />
    <ul id="files_{$file}" class="treeview-phpdoc">
      <xsl:for-each select="class">
        <li>
          <span>
            <a href="{$root}/{../@generated-path}#{name}">
              <xsl:value-of select="name" />
            </a>
          </span>
          <small>
            <xsl:value-of select="docblock/description" />
          </small>
        </li>
      </xsl:for-each>
    </ul>
  </xsl:template>

  <xsl:template match="package">
    <li class="closed">
      <span class="folder">
        <xsl:if test="@name=''">Default</xsl:if>
        <xsl:if test="not(@name='')">
          <xsl:value-of select="@name" />
        </xsl:if>
      </span>
      <xsl:variable name="package" select="@name" />
      <ul id="packages_{$package}" class="filetree">

        <!-- List all classes that have a package which matches @name but no subpackage OR which have no package and $package is empty -->
        <xsl:for-each select="/project/file/class[docblock/tag[@name='package'][@description=$package] and not(docblock/tag[@name='subpackage'])]|/project/file/interface[docblock/tag[@name='package'][@description=$package] and not(docblock/tag[@name='subpackage'])]|/project/file/class[not(docblock/package) and $package='']|/project/file/interface[not(docblock/package) and $package='']">
          <xsl:sort select="name"/>
          <li class="closed">
            <span class="{name()}">
              <a href="{$root}{../@generated-path}#{name}">
                <xsl:value-of select="name" />
              </a>
              <br />
              <small>
                <xsl:value-of select="docblock/description" />
              </small>
            </span>
          </li>
        </xsl:for-each>

        <!-- List all subpackages and their classes -->
        <xsl:for-each select="subpackage">
          <xsl:sort select="." />
          <li class="closed">
            <xsl:variable name="subpackage" select="." />
            <span class="folder">
              <xsl:if test="$subpackage=''">Default</xsl:if>
              <xsl:if test="not($subpackage='')">
                <xsl:value-of select="$subpackage" />
              </xsl:if>
            </span>
            <ul id="packages_{$package}_{$subpackage}" class="filetree">
              <xsl:for-each select="/project/file/class[docblock/tag[@name='package'][@description=$package] and docblock/tag[@name='subpackage'][@description=$subpackage]]|/project/file/class[docblock/tag[@name='package'][@description=$package] and docblock/tag[@name='subpackage'][@description=$subpackage]]">
                <xsl:sort select="name" />
                <li class="{name()}">
                  <span>
                    <a href="{$root}{../@generated-path}#{name}">
                      <xsl:value-of select="name" />
                    </a>
                    <br />
                    <small>
                      <xsl:value-of select="docblock/description" />
                    </small>
                  </span>
                </li>
              </xsl:for-each>
            </ul>
          </li>
        </xsl:for-each>
      </ul>
    </li>
  </xsl:template>

  <xsl:template match="namespace">
    <xsl:param name="parent_name" />
    <xsl:variable name="full_name" select="concat($parent_name, @name)" />

    <li class="closed">
      <span class="folder">
        <xsl:if test="@name=''">Default</xsl:if>
        <xsl:if test="not(@name='')">
          <xsl:value-of select="@name" />
        </xsl:if>
      </span>
      <ul>
        <xsl:for-each select="/project/file/class[@namespace=$full_name]|/project/file/interface[@namespace=$full_name]">
          <xsl:sort select="name" />
          <li>
            <span class="{name()}">
              <a href="{$root}{../@generated-path}#{name}">
                <xsl:value-of select="name" />
              </a>
              <br />
              <small>
                <xsl:value-of select="docblock/description" />
              </small>
            </span>
          </li>
        </xsl:for-each>
        <xsl:apply-templates select="namespace">
          <xsl:sort select="@name" />
          <xsl:with-param name="parent_name" select="concat($full_name, '\')" />
        </xsl:apply-templates>
      </ul>
    </li>
  </xsl:template>

</xsl:stylesheet>{
    "_readme": [
        "This file locks the dependencies of your project to a known state",
        "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
    ],
    "hash": "4d017c55893ea23fc1c87c8ab76fba1f",
    "packages": [
        {
            "name": "phpdocumentor/unified-asset-installer",
            "version": "1.1",
            "source": {
                "type": "git",
                "url": "https://github.com/phpDocumentor/UnifiedAssetInstaller.git",
                "reference": "1.1"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phpDocumentor/UnifiedAssetInstaller/zipball/1.1",
                "reference": "1.1",
                "shasum": ""
            },
            "require-dev": {
                "composer/composer": "~1.0@dev",
                "phpunit/phpunit": "~3.7"
            },
            "type": "composer-installer",
            "extra": {
                "class": "\\phpDocumentor\\Composer\\UnifiedAssetInstaller"
            },
            "autoload": {
                "psr-0": {
                    "phpDocumentor\\Composer": [
                        "src/",
                        "test/unit/"
                    ]
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "description": "Asset installer for phpDocumentor",
            "homepage": "http://www.phpdoc.org",
            "keywords": [
                "assets",
                "installer",
                "plugins",
                "templates"
            ],
            "time": "2013-08-01 19:35:55"
        }
    ],
    "packages-dev": [

    ],
    "aliases": [

    ],
    "minimum-stability": "stable",
    "stability-flags": [

    ],
    "platform": {
        "ext-xsl": "*"
    },
    "platform-dev": [

    ]
}
PNG

   IHDR     K   Ϗ   sRGB    bKGD      	pHYs    B(x   tIME	<  IDATx?Kqs]j$QCjޤ?BTs
BAMa-&54IA{hhlСV_IMJex!%|y[   PL   J:,  8m  @P  uj   (rC   AmC   vC   O  <m  @P    @"m   $چ   A   AmC   vC     DP  TPo~hch@_}{vP>   `w1}J4vTl  Ok~!zvP<  cPoc'Fbe  sPWUG䍋J  NAݨGϼ,jj   :h?l  SP7   vC  5   w^STԂ  AmiA  N    {چ   A(jA  .iA  j   um  ԉ   DQ{  N5   :QԂ   A]ӂ   A	j7   DQP   {ZP   3E-  =   A)jj   uyOj   u    A]6   jA  ޙ   vC  5   5   :SԂ   A]n  ԙ  `k:   6,Zisxc\]   PbnK}0%A   %하~2^~-A   l<FP  @v{%.ߊRԍ   ;f>FnC   ݞ  RgN   PIO     2<   A      5   O~
m%    IENDB`PNG

   IHDR         a   tEXtSoftware Adobe ImageReadyqe<  IDATxڤKLQ<vhK1@D0X,H	qc\pgtڕF!nl`HѦTlyZ*#t:B;0Kdns{.eYkҙZ:BΘD4K4E+N(Po`XX`JwoJ'V㡛#ѱgO:p\Dݸ0;P{(((j[ZػcCFR?#%0|=ub`!Dl[[V]@wS${<v4Tu\9'@nގ=`}'!	V u UM^MІ	(	HCG9Mv!h,LLVA
&?HL)ą
/3ɢ &%R1ـ WĦL9۹:YZi9LD`AuɆqŶCHi
ӱ%_ MrS_'&M/xy8mn e&Tȩή`i	+ EF
*YEbb"k`6hkyi>>oAQPs嬴O˛OD޼Au^? 9r    IENDB`PNG

   IHDR         a   sRGB    bKGD      	pHYs        tIME_.  IDAT8˥S=`~|$`F?С?PނSKNRGtE$^PP]P @d#oN7೜p<C88H\aYpΑ$	$Is؝oT*\.XӴ'bq1$IfA)(Ps(]Ki^P( E8nR
QA)  nl6τj48i,ː$)$Q(.Z Ze^XI@IBe,,N\ïRA IEab2s4V@&Is9h4EJN}y,+,˘N mPH\A~ò,Ȳ0fhu4Mx0Wz$iڋlnG]uvRR<eFѽۜ    IENDB`PNG

   IHDR         a   gAMA  7   tEXtSoftware Adobe ImageReadyqe<   IDATxb?%  ( D ĂK%1H#	]3: y@M&@) P b	ga @}s., @ ȦƟfx{ ~u 9 g ~!NŪ p?J?U@ tϿO_0: gpV8  FJ@ Qb b  Mte |    IENDB`PNG

   IHDR         a   gAMA  7   tEXtSoftware Adobe ImageReadyqe<  IDAT8ˍ=OP)C0[!k_@ @

&~@[%C
*UAVJ;dB,@l_رo}nqHP=<>. ]D\cn?/ 8FNq$ɷAIP0Hɦi²,0iDQdAJ|mTU&2t]$ILPT@IMIP[5AJ(Je%6O(~0[dāa(*yUtOлM̾_
^I
P%4UUoVNcc_E{v_B|NuXתA"*kfB"_0-K?6љc.oal7.`Z:g|)bbܬ*āG
å2Da.a<gɏ^f$VuZAm{ToY7AA{:;r{ЁK_p-pdQ>2A$tC ʘ?    IENDB`GIF89a   jlbAԽ|9tmp|_,      ;X%ܬPƤ7i4e'E j
dq 56p1tJU$  ;PNG

   IHDR         a   sRGB    bKGD      	pHYs        tIME&s"  |IDAT8˅OlLQΛԤLjCkJYV]  $D,!DN$,6AXI"HFjռk˂ι!AWkYӴ!=?pSr7N'Gj.ZVsYoGxL]Yï;9*d6x;<[*Z 1`Cp.9VtY~K@BTydkO'

ن !H NyhkH574~_*ZPL:O0XUjã<y}lCjteiXD|Aʑ<,)AGZ-$fL	eMTب|1b݄ʸه6mm3I4q߱H;L+7(6D&A%,]
CcHaP)3p8bQkq*7OzGW		qR`+ 9+Ր{Q '(7<*΂SҞvwA;xxz^;pͳ+qs6uRUԉ/M\0=6v4MfJTXY,b:xL#D[V-aNmj	CcQ{j~J,ϔ    IENDB`PNG

   IHDR         a   sRGB    bKGD      	pHYs        tIME\s  IDAT8˕˫RQ-# H"AA"Ms05# ΤfgR"&MAc}IO#wM6k>ZD4"pn?T*դlCҌ[!Fb$Ih4.L
gA4pX/WշT*<@~p\D"!t:l9%f(wçD"qf J)TUjzzsx^||r6E(c2R`0PӴL1 ctlA;^J)L&Ǜk 5UUJ't:Aj$It:p\.ZÎ(`AE8VzodY~' f3v;-~V}nNZx<vh4Yohnhf=+:&Ji>v:
9G ȴ    IENDB`PNG

   IHDR         a  
MiCCPPhotoshop ICC profile  xڝSwX>eVBl "#Y a@Ņ
VHUĂ
H(gAZU\8ܧ}zy&j 9R<:OHɽH g  yx~t?o  p.$P&W   "R .T  Sd
   ly|B"  I> ة آ  (G$@ `UR, @".Y2G vX@` B,  8 C L0ҿ_pH ˕͗K3w!lBa)f	"#HL  8?flŢko">! N_puk[ V h]3	Z
zy8@P<
%b0>3o~@z q@qanvRB1n#ǅ)4\,XP"MyRD!ɕ2	w ONl~Xv @~- g42y  @+ ͗  \L  D*AaD@$<B
AT:18\p`	Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut }c1fa\E`X&cX5V5cX7va$^lGXLXC%#W	1'"O%zxb:XF&!!%^'_H$ɒN
!%2IIkHH-S>iL&m O:ňL	$RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t	݃EЗkwHb(k{/LӗT02goUX**|:V~TUsU?yTU^V}FUP	թU6RwRPQ__cFHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ!{--?-jf~7zھbrup@,:m:u	6Qu>cy	Gm7046l18c̐ckihhI'&g5x>fob4ek<abi2ۤĤ)͔kfѴt,ܬج9՜kaټEJ6ǖږ|MV>VyVV׬I\,mWlPW:˶vm))Sn1
9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/>B	Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$	=sl3Ttcܢ˞w<Y5Y|8? BP/OnM򄛅OEQJ<V8;}ChOFu3	OR+y#MVDެq-9Ri+0(Of++ym#slLѣRPL/+x[[xHHZ3f#|PظxY"E#Sw.1]Rdxi}h˲PXRUjyRҥC+W4nZcadUj[V*_pFWN_|ymJHnYJjAІ_mJtzjʹ5a5[̶6z]V&ֿw{;켵+xWkE}nݏb~ݸGwOŞ{{Ejtolܯ	mR6H:p囀oڛwpZ*A'ߦ|{PߙHy+:u-m=茣^G~1cu5W(=䂓dN?=ԙyLk]Q]gCϞ?tL_]p"b%K==G~pH[oeW<tM;js.]yn&%vw
L]zxem``Y	ӇGG#F#dΓ᧲~VysKXϿyr﫩:#y=}ǽ(@PcǧO>|/%ҟ3   bKGD      	pHYs        tIME&z;n7  IDAT8}Oh\UΛLf$iJ@Oc)PE4)hB.qeE((,?(DM6ЖhH$޻{\$.z79s8<}@p+HNո8Sᩱ[bv{iOqo}776jf;<S۾5\oˊAFs)r1nˉ7Ym3p@Q*#.{.~ʅnC'iyqO'̐d:AQA~Bׯ w?}XHfHGF##nlp{ Y3뻳{͕(u1QQD!Fn./5`pk Q(#h:3-G_>WϜ=!
"F"D1b!(PI>s"RWe=Q H\Q+h_ZX[΋fP=G@ Y3Wz8OMBLr4"Q༫7VfsKso[\#I̼X1ɻ"u+ձ'CuZ:-TA5Uj4⫞ol)齯&95^:3M`prJ2{W-f=F3%8<ZP)ϲȗ~b    IENDB`GIF89a   Zx➭s-҃h$Ç4,      7H`KPl\:pL)e9@\ "l:+PB ;         h     (                                    ǷZpGc6c6c6c6c6c6c6c6c6c6c6c6pGǷZpGc6c6c6c6c6c6c6c6c6c6c6c6c6c6pGnDЬӱѮΩŘ{}Xc6c6rIʡj?wPЬuNc6c6mCog;wPΨ˼\c6g}XЫƛ~c6c6c6c6lc6c6c6~YxQc6ƛ~c6c6c6c6c6lc6c6c6c6ɺf:ʻǜc6c6c6c6c6lc6c6c6c6Ьӱ\gүh<c6c6c6lc6c6c6c6׷]c6e9h<d7c6c6c6lc6c6c6d7غc6c6c6c6c6c6c6c6lc6c6j?׷h<c6c6c6c6c6c6c6c6ʺѭǛˣүkd7c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6i>ˣc6c6c6c6c6c6c6c6c6c6c6c6c6c6i>ėyc6c6c6c6c6c6c6pGc6c6c6c6c6c6tKic6c6c6c6c6c6pGǷZpGc6c6c6c6c6c6c6c6c6c6c6c6pGǷZ                                                            PNG

   IHDR         a   gAMA  7   tEXtSoftware Adobe ImageReadyqe<  IDATxb?%  X@jtd1- b V3@|^ @,hYh8Hq0}_:~܍խi  d
"lդYf`̌\:r|;_:u* b9R_B POAFF2U &Yπ{_0,Y鳗lNN._10p
pk>yN f//m?,ZP-W`Lmdh25ffa		^h  *l h.fSN+`af@ ;&P Pe@_A0 @@Ͽ @ :/@3ATZ;(4i `͗o@[``c% ޶Hh/MX /eud4yW/X`P5?~~T @0]p kH 
w?|tWϞτ%i BN]mM1I	^^n6Px|׳/>_tKfxR g7 Hiv0 dG32    IENDB`GIF89a   𵵶ݺ         !   ,       EI8[s/f,^	W\߄xh%@[1	J 3@hHW" ;PNG

   IHDR         a   gAMA  7   tEXtSoftware Adobe ImageReadyqe<  IDATxb?%  X@Ld1 b օ]@ @,hȨTI
3001|<?{N˷f4 遺vTxظW& U$8x޺[! sj??~o o@l*B|P2 >r<`;CE\ /C?.2|BVʟ. AOhw߀tq_ _ɉ~cd-9P 3 ,@?;+0>/=>3|ҿ1\\=  d`蒿@#~c🁑/x_xp	H'@Fg?X`  n}WW>mh+(:A_hb  [Nܾq7wM%W@A՗GBS%@ ̓7o:ߺ:AMI?k0]`|>%i BN3o=zӇRIY.e^&v`_@߅j'e B3?|~L  @fg  4    IENDB`PNG

   IHDR         a  
MiCCPPhotoshop ICC profile  xڝSwX>eVBl "#Y a@Ņ
VHUĂ
H(gAZU\8ܧ}zy&j 9R<:OHɽH g  yx~t?o  p.$P&W   "R .T  Sd
   ly|B"  I> ة آ  (G$@ `UR, @".Y2G vX@` B,  8 C L0ҿ_pH ˕͗K3w!lBa)f	"#HL  8?flŢko">! N_puk[ V h]3	Z
zy8@P<
%b0>3o~@z q@qanvRB1n#ǅ)4\,XP"MyRD!ɕ2	w ONl~Xv @~- g42y  @+ ͗  \L  D*AaD@$<B
AT:18\p`	Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut }c1fa\E`X&cX5V5cX7va$^lGXLXC%#W	1'"O%zxb:XF&!!%^'_H$ɒN
!%2IIkHH-S>iL&m O:ňL	$RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t	݃EЗkwHb(k{/LӗT02goUX**|:V~TUsU?yTU^V}FUP	թU6RwRPQ__cFHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ!{--?-jf~7zھbrup@,:m:u	6Qu>cy	Gm7046l18c̐ckihhI'&g5x>fob4ek<abi2ۤĤ)͔kfѴt,ܬج9՜kaټEJ6ǖږ|MV>VyVV׬I\,mWlPW:˶vm))Sn1
9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/>B	Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$	=sl3Ttcܢ˞w<Y5Y|8? BP/OnM򄛅OEQJ<V8;}ChOFu3	OR+y#MVDެq-9Ri+0(Of++ym#slLѣRPL/+x[[xHHZ3f#|PظxY"E#Sw.1]Rdxi}h˲PXRUjyRҥC+W4nZcadUj[V*_pFWN_|ymJHnYJjAІ_mJtzjʹ5a5[̶6z]V&ֿw{;켵+xWkE}nݏb~ݸGwOŞ{{Ejtolܯ	mR6H:p囀oڛwpZ*A'ߦ|{PߙHy+:u-m=茣^G~1cu5W(=䂓dN?=ԙyLk]Q]gCϞ?tL_]p"b%K==G~pH[oeW<tM;js.]yn&%vw
L]zxem``Y	ӇGG#F#dΓ᧲~VysKXϿyr﫩:#y=}ǽ(@PcǧO>|/%ҟ3   bKGD      	pHYs        tIME&P  IDAT8}kG3{ssosMjBRTP[Zčv#bݸu!..tU V;7I͇Ixg9]܏.ss0f}	^}5_\>r򞝚XXK۩_>x]߇*;3ڊRiqw޻pqu?=?S6é|>yb[	zWb8DE^gnN G?|bDu؊V\cخ =izYs!"FJl!F=et/ifD=5A !L͡=i;;rT#Ah )	w7bZ&.+݂@nkjFkRCiKn66-Iܟ	rKsK%QC+{yOTTg75+pACTQ3>D%O2&0SOoXơFVoq=ʮҍƧ7~厙~>usqu_ј5Otu[\t|GۍsM~ԕ$HRk/I    IENDB`PNG

   IHDR         a   gAMA  7   tEXtSoftware Adobe ImageReadyqe<  IDATxb?%  X@ĄPFd1U 6b] =@|o @,hzF%X
Iq0˟]~n/T pMSPadeOCV@R@㼰̹` ny*,c/? /ÿ_@WGJKVQ)U `h	tO&o00#ßL|zpb  "<3Ue8s)X~ABW 3@WL%^4ÙKOL4|G88a1@L !&ZB>õo4ϯ `</~f0Q`Ã~`#3>6 f7|`O}`0Vegа^m??^z fVW&зafx`͠ӧ7oJ %w- ,$geȫ!aa>ßw| 3>|t̵+Ϟ=_ K wٽ[F"|,Woo޸y9D3<)z^ͻ@LTf b4; -)oyp    IENDB`PNG

   IHDR         a   gAMA  7   tEXtSoftware Adobe ImageReadyqe<  IDATxb?%  X@27md1- b V3@|F @,h)9{pKp001+wwn:ܳwխi  dٸ8wFV66~AVI-A~~^kKݾpf@ 1b\/?@B3on^n=]1QtW fw''3ß303ӷO0/!4 n	i2pa֣\b(pdؾg|,X8D8y< `.Pafaeb>2$X1dh3-kÐm)0i1qi.F66X<};x1h2p )  `_gThwbATǏ_д @0μ{Ïo CA6} %7&, b%e`JԒМlf@|OpՇwx `.vk
oP@__~>PLX 䔸֩<PVT0͏_o޿|ރ5Ó2@ u/=De&  FJ3@ A    IENDB`PNG

   IHDR         Ĵl;   	pHYs       
OiCCPPhotoshop ICC profile  xڝSgTS=BKKoR RB&*!	J!QEEȠQ,
!{kּ>H3Q5B.@
$p d!s# ~<<+" x M0B\t8K @zB @F&S  `cb P- `' { [!  eD h; VE X0 fK9 - 0IWfH    0Q) { `##x  FW<+*  x<$9E[-qWW.(I+6aa@.y24  x6_-"bbϫp@  t~,/;m%h^uf@ Wp~<<EJB[aW}g_Wl~<$2]GLϒ	bG"IbX*QqD2"B)%d,>5 j>{-]cK'Xt  o(hw?G% fIq  ^D$.Tʳ?  D*A,`6B$BB
dr`)B(Ͱ*`/@4Qhp.U=pa(	Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F; 2G1Q=C7Fdt1r=6Ыhڏ>C03l0.B8,	c˱"VcϱwE	6wB aAHXLXNH $4	7	Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![
b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGwǈg(gwLӋT071oUX**|
J&*/TުUUT^S}FU3S	ԖUPSSg;goT?~YYLOCQ_ cx,!ku5&|v*=9C3J3WRf?qtN	(~))4L1e\kXHQG6EYAJ'\'GgSSݧ
M=:.kDwn^Loy}/TmGX$<5qo</QC]@Caaᄑ<FFi\$mmƣ&&!&KMMRM);L;L֙͢5=12כ߷`ZxZ,eIZYnZ9YXUZ]F%ֻNNgðɶۮm}agbgŮ}}=Z~sr:V:ޚΜ?}/gX3)iSGggs󈋉K.>.ȽJtq]zۯ6iܟ4)Y3sCQ?0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz %gA[z|!?:eAAA!h쐭!ΑiP~aa~'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl{/]py.,:@LN8A*%w%
yg"/6шC\*NH*Mz쑼5y$3,幄'LLݛ:v m2=:1qB!Mggfvˬen/kY-
BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9<qy
+V<*mOW~&zMk^ʂkU
}]OX/Yߵa>(xoʿܔĹdff-[nڴVE/(ۻC<e;?TTTT6ݵan{4[>ɾUUMfeI?m]Nmq#׹=TR+Gw-6U#pDy	:v{vg/jBFS[b[O>zG4<YyJTiӓgό}~.`ۢ{cjotE;;\tWW:_mt<Oǻ\kz{f7y՞9=ݽzo~r'˻w'O_@AC݇?[jwGCˆ8>99?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-   gAMA  |Q    cHRM  z%        u0  `  :  o_F  IDATxԕLu<y?,=%0[МDY`nYV+[Y1q,Aiz(T;A{q`q24}~2D{Q2ܣb70U>E$Q^㥵u7Lw9;ޮY3"KY|   ;gڲH/XEm
v2^N%(B-sB>w}3Ύ0N; dH3)Amu=8TJR@umЬ'tLuG:_j n/B3S&/#) Rr252C
WOeV4ƺs$Dc'7C܎/!) ҖTt2'uۖN	U*Ǭ,byw$D:xlzja&"O`ܿHowAeb2ө"J'蜺;Vfsc$k:q\ik6ug CCH9/8m,gsBP%<N@+clտse	h?ܬjNAOD0D]9<nYU}9'0jE&0Bz	.Mto
'١T(Dg4+:wCE᷌:kE։"nV"~llC_v˒e7*؝B&0[SJ>hZ8q}r贵9\l2nv^;z>z
;3c2p+vcƨgQyͳNl0U_Yyr2~>IvĺdS's5=3  Qp\{    IENDB`PNG

   IHDR         a   gAMA  7   tEXtSoftware Adobe ImageReadyqe<  IDATxb?%  X@D}- 	@  >`
lf  4l<-8X٘|7w>|ܝ{wխi  d}u99b`U]MEP[cR.1 `ζ3.Гec/߿?@4 Nc-sIQtW gov~gbHmfPgq!  Cqx\\Ljr_?5 DTBo?3 -,05A]\a²e߿gc2@ Paaee詨3|yUax%##Ï!  O!?o31|?y Oop`=}ԅ_=dHgxs7/_~A@ 8P5UE1	goO0gd
t?`ghb  :p~`d##~{ы硩 `.v歩<RF
|?_c
O<מә$@)qɳ'>y*o !Ïzk}z69)z^X@LTf b4; B
,f7    IENDB`PNG

   IHDR           szz   	pHYs       
OiCCPPhotoshop ICC profile  xڝSgTS=BKKoR RB&*!	J!QEEȠQ,
!{kּ>H3Q5B.@
$p d!s# ~<<+" x M0B\t8K @zB @F&S  `cb P- `' { [!  eD h; VE X0 fK9 - 0IWfH    0Q) { `##x  FW<+*  x<$9E[-qWW.(I+6aa@.y24  x6_-"bbϫp@  t~,/;m%h^uf@ Wp~<<EJB[aW}g_Wl~<$2]GLϒ	bG"IbX*QqD2"B)%d,>5 j>{-]cK'Xt  o(hw?G% fIq  ^D$.Tʳ?  D*A,`6B$BB
dr`)B(Ͱ*`/@4Qhp.U=pa(	Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F; 2G1Q=C7Fdt1r=6Ыhڏ>C03l0.B8,	c˱"VcϱwE	6wB aAHXLXNH $4	7	Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![
b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGwǈg(gwLӋT071oUX**|
J&*/TުUUT^S}FU3S	ԖUPSSg;goT?~YYLOCQ_ cx,!ku5&|v*=9C3J3WRf?qtN	(~))4L1e\kXHQG6EYAJ'\'GgSSݧ
M=:.kDwn^Loy}/TmGX$<5qo</QC]@Caaᄑ<FFi\$mmƣ&&!&KMMRM);L;L֙͢5=12כ߷`ZxZ,eIZYnZ9YXUZ]F%ֻNNgðɶۮm}agbgŮ}}=Z~sr:V:ޚΜ?}/gX3)iSGggs󈋉K.>.ȽJtq]zۯ6iܟ4)Y3sCQ?0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz %gA[z|!?:eAAA!h쐭!ΑiP~aa~'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl{/]py.,:@LN8A*%w%
yg"/6шC\*NH*Mz쑼5y$3,幄'LLݛ:v m2=:1qB!Mggfvˬen/kY-
BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9<qy
+V<*mOW~&zMk^ʂkU
}]OX/Yߵa>(xoʿܔĹdff-[nڴVE/(ۻC<e;?TTTT6ݵan{4[>ɾUUMfeI?m]Nmq#׹=TR+Gw-6U#pDy	:v{vg/jBFS[b[O>zG4<YyJTiӓgό}~.`ۢ{cjotE;;\tWW:_mt<Oǻ\kz{f7y՞9=ݽzo~r'˻w'O_@AC݇?[jwGCˆ8>99?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-   gAMA  |Q    cHRM  z%        u0  `  :  o_F  IDATx̗mlE{Σ/^/GE[
	F(񃆐cŨQD>Q%& Q	Fmy	+zngٖQqg?B),"Z7nzܟS`"!Q&hlml >(IJ;MO֚@h潮"Y+0BIRa$ 0]1"M.#(	JP*yom29C C-Oh@wa( 2؀YeD0>dB[y ͠aáHVr8ㅰbb9԰^Bo5D>7^i>5*&?eؐ*94tӡKK	TυxB}fVzv;*)@P=8Gfͪ ~\]KjJ5>r
[MLcB8Ƣ۶-\6@BqrlYb\킜|E)p; 7-567";>22a(N̊gtVa;tm"}YsY\/w)԰$>ıG	ijϊGVSMy`	J~̧ŷmԀgwx4iQͿ@B$͑1H%,:?g[Ntx yyلC9+;г_)#Jy3e%s'ct*d9.]
S3{9W``};:>Ƭy.AvM5lq<?YC7㤝E7k61x}=uDrXd#Es#arl%.4]/
ӯSqs_IeW[ RESYN2ByT"t\ZgIu1oq#鸑`4LR5.:JIvInJ&n(
{ 2)4M|n=%ӆR}0HɸqoDZTfT
0zgeAKK2!F80=̈́ZGM0\")S({0%J)&˃iԕ_!4Q<.X5LXZ1OK։)SHÆ$۾㦝 vvf    IENDB`PNG

   IHDR   x   >   eߣ   sRGB    bKGD      	pHYs    B(x   tIMEئ   tEXtComment Created with GIMPW  HIDATxmORa+]ò5̜,pMp{ ڪZwc<>s]tݸ9ae\09`F`vY	,}s`vi'?ќ`F`C5q`	8{0uUjh4ކjgzB%dreSl&lY@vnodqpEw/Mb-;_rPW*<be3!xx/VU,)Ewyp|nREU2T|15T ֢4Lc 4Œ<q#m1B'pqv13r	-.}X6)*nec6?.- ,˂ǿo+	l	w6'y+T7ޥ+ylc7#
%nlZ41jA$Ԋ9p{Cbq_i`n"Xjia|j=7J:V6ĘgNNjzc-C`Yw;0bJ`Mxz rN;K-uEÅK&oq\8"IKοP	,jzzM&dF^#ex>KK0.7B*?cBx\FD`u4bu]Fb2,_ҚbOM\RRkR}ju~l»%WP@u    IENDB`PNG

   IHDR        M   sBIT|d   	pHYs    B(x   tEXtSoftware www.inkscape.org<   :IDAT8c30000|b`~?N`  ~Tڂ|k    IENDB`PNG

   IHDR     d   gxl   sBIT|d   	pHYs    B(x   tEXtSoftware www.inkscape.org<  IDATxm@A9K9j`*}$5   r}   y   %     3   v  -	5   6   Q  5	5      )   f  @      	5   6   H     @   o   T   P  @`C      j   $   P  @   7   j   P     j   $   C   7      l   ~J   5   j     @   o   $   P  @      3*   &     ?%  ,   $   P  @      o   T   P  @pƆ   $   P  @l   j   l     ,   $   )   j   l   8P  7   *   H   p6   	5   j   S2   XS  @   o   $   P  @      	5   6   xP  @pƆ   $   )   f  @      gG     ?X    IENDB`PNG

   IHDR      K      sRGB    bKGD      	pHYs    B(x   tIMEy|D   tEXtComment Created with GIMPW   5IDAT튱 !ìL;)07coLE(i"p %7@    IENDB`<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes" method="html" />

  <xsl:template match="/project" name="menu">
    <ul id="menu">
      <li>
        <a href="{$root}graph.html">Class diagram</a>
      </li>
      <!--<li>Packages</li>-->
      <!--<li>Files</li>-->
      <li>
        <a href="{$root}markers.html">TODO / Markers</a>
      </li>
      <li>
        <a href="{$root}parse_markers.html">Errors</a>
      </li>
    </ul>
    <!--<h4>Charts</h4>-->
  </xsl:template>

</xsl:stylesheet><?xml version="1.0"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes" method="html" />
  <xsl:include href="chrome.xsl" />

  <xsl:template match="/project">
    <div id="content">
      <table width="100%" height="95%">
      <tr><td height="60px">
        <div style="font-size: 10px; white-space: normal;">
          The following actions are supported in this diagram:
          <ul>
            <li><b>Zoom</b>, you can use the scrollwheel to zoom in or out</li>
            <li><b>Move</b>, you can move around by dragging the Diagram</li>
            <li><b>Go to class</b>, you can view the details of a class by clicking on it</li>
          </ul>
        </div>
      </td></tr>
      <tr><td>
        <embed src="classes.svg" width="100%" height="100%" />
      </td></tr>
      </table>
    </div>
  </xsl:template>

</xsl:stylesheet><?xml version="1.0"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes" method="html" />

  <xsl:template match="/project">
    <xsl:apply-templates select="/project/class[name=$class]" />
  </xsl:template>

  <xsl:template match="class|interface">
    <h3><xsl:value-of select="name" /></h3>
    <div class="properties">
      <h1>Properties</h1>
      <label class="property-key">Extends</label>
      <div class="property-value">
        <xsl:if test="extends[@link = '']">
          <xsl:value-of select="extends" />
        </xsl:if>
        <xsl:if test="extends[@link != '']">
          <a href="{extends/@link}"><xsl:value-of select="extends" /></a>
        </xsl:if>
        &#160;</div>
      <label class="property-key">Implements</label>
      <div class="property-value">
        <xsl:for-each select="implements"><xsl:value-of select="." /><br /></xsl:for-each>&#160;
      </div>
      <xsl:for-each select="docblock/tag">
        <xsl:sort select="@name" />
        <label class="property-key"><xsl:value-of select="@name" /></label>
        <div class="property-value">
          <xsl:if test="@link and @link != ''"><a title="{.}" href="{@link}"><xsl:value-of select="@description" disable-output-escaping="yes" /></a></xsl:if>
          <xsl:if test="not(@link) or @link = ''"><a title="{.}"><xsl:value-of select="@description" disable-output-escaping="yes" /></a></xsl:if>
            &#160;
        </div>
      </xsl:for-each>
      <label class="property-key">Abstract</label>
      <div class="property-value">
        <xsl:if test="@abstract='true'">Yes</xsl:if>
        <xsl:if test="@abstract != 'true'">No</xsl:if>&#160;
      </div>
      <label class="property-key">Final</label>
      <div class="property-value">
        <xsl:if test="@final='true'">Yes</xsl:if>
        <xsl:if test="@final != 'true'">No</xsl:if>&#160;
      </div>
    </div>

    <h4>Description</h4>
    <xsl:if test="not(docblock/description) and not(docblock/long-description)">
      <strong><em>No description is available</em></strong>
    </xsl:if>
    <xsl:if test="docblock/description">
    <em><xsl:value-of select="docblock/description" disable-output-escaping="yes" /></em><br />
    </xsl:if>
    <xsl:if test="docblock/long-description">
    <xsl:value-of select="docblock/long-description" disable-output-escaping="yes" /><br />
    </xsl:if>

    <xsl:if test="count(method) > 0">
    <div id="methods_{name}">
      <h4>Methods</h4>
      <xsl:for-each select="method">
        <xsl:sort select="name" />
        <a style="font-style: italic;" href="#{../name}::{name}()"><xsl:value-of select="name" /></a>,
      </xsl:for-each>

      <xsl:for-each select="method">
        <xsl:sort select="name" />
        <xsl:apply-templates select="." />
      </xsl:for-each>
    </div>
    </xsl:if>

    <xsl:if test="count(property) > 0">
    <div id="properties_{name}">
      <h4>Properties</h4>
      <xsl:for-each select="property">
        <xsl:sort select="name" />
        <a href="#{../name}::{name}">
          <xsl:value-of select="name" />
        </a>,
      </xsl:for-each>

      <xsl:for-each select="property">
        <xsl:sort select="name" />
        <xsl:apply-templates select="." />
      </xsl:for-each>
    </div>
    </xsl:if>

    <xsl:if test="count(constant) > 0">
    <div id="constants_{name}">
      <h4>Constants</h4>
      <xsl:for-each select="constant">
        <xsl:sort select="name" />

        <xsl:apply-templates select="." />
      </xsl:for-each>
    </div>
    </xsl:if>
    <div style="clear: both"></div>
  </xsl:template>

  <!-- Concatenate items with links with a given separator, based on: http://symphony-cms.com/download/xslt-utilities/view/22517/-->
  <xsl:template name="implodeTypes">
    <xsl:param name="items" />
    <xsl:param name="separator" select="'|'" />

    <xsl:for-each select="$items">
      <xsl:if test="position() &gt; 1">
        <xsl:value-of select="$separator" />
      </xsl:if>

      <xsl:if test="@link">
        <a href="{$root}{@link}">
          <xsl:value-of select="." />
        </a>
      </xsl:if>
      <xsl:if test="not(@link)">
        <xsl:value-of select="." />
      </xsl:if>
    </xsl:for-each>
  </xsl:template>

  <xsl:template match="method|function">
    <div class="method">
      <a id="{../name}::{name}()" />
      <h3>
        <xsl:value-of select="name" />
        <span class="nb-faded-text">(
          <xsl:for-each select="argument">

            <xsl:variable name="variable_name" select="name" />

            <xsl:call-template name="implodeTypes">
              <xsl:with-param name="items" select="../docblock/tag[@name='param' and @variable=$variable_name]/type"/>
            </xsl:call-template>
            &#160;
            <xsl:value-of select="$variable_name" />

            <xsl:if test="default != ''">
            = <xsl:value-of select="default" disable-output-escaping="yes"/>
            </xsl:if>,
          </xsl:for-each>
          )
        </span>
        :
        <span class="nb-faded-text">
          <xsl:if test="not(docblock/tag[@name='return']/@type)">n/a</xsl:if>
          <xsl:if test="docblock/tag[@name='return']/@type">
            <xsl:if test="docblock/tag[@name='return']/@link">
              <a href="{$root}{docblock/tag[@name='return']/@link}">
                <xsl:value-of select="docblock/tag[@name='return']/@type" />
              </a>
            </xsl:if>
            <xsl:if test="not(docblock/tag[@name='return']/@link)">
              <xsl:value-of select="docblock/tag[@name='return']/@type" />
            </xsl:if>
          </xsl:if>
        </span>

      </h3>
      <xsl:if test="docblock/description != '' or docblock/long-description != ''">
        <h4>Description</h4>
      </xsl:if>
      <xsl:if test="docblock/description != ''">
        <em><xsl:value-of select="docblock/description" disable-output-escaping="yes" /></em><br />
      </xsl:if>
      <xsl:if test="docblock/long-description != ''">
        <small><xsl:value-of select="docblock/long-description" disable-output-escaping="yes" /></small><br />
      </xsl:if>
      <xsl:if test="count(argument) > 0">
      <h4>Arguments</h4>
      <table>
        <thead><tr><th>Name</th><th>Type</th><th>Description</th><th>Default</th></tr></thead>
        <tbody>
          <xsl:for-each select="argument">
            <xsl:variable name="variable_name" select="name" />
            <xsl:variable name="variable_description" select="../docblock/tag[@name='param' and @variable=$variable_name]/@description" />
            <tr>
              <td>
                <xsl:value-of select="$variable_name" />
              </td>
              <td style="white-space: normal;">
                <xsl:if test="not(../docblock/tag[@name='param' and @variable=$variable_name]/type)">n/a</xsl:if>
                <xsl:for-each select="../docblock/tag[@name='param' and @variable=$variable_name]/type">
                  <xsl:if test="position() &gt; 1">|</xsl:if>
                  <xsl:if test="@link"><a href="{$root}{@link}"><xsl:value-of select="." /></a></xsl:if>
                  <xsl:if test="not(@link)"><xsl:value-of select="." /></xsl:if>
                </xsl:for-each>
              </td>
              <td>
                <xsl:value-of select="$variable_description" disable-output-escaping="yes"/>
              </td>
              <td>
                <xsl:value-of select="default" disable-output-escaping="yes" />
              </td>
            </tr>
          </xsl:for-each>
        </tbody>
      </table>
      </xsl:if>

      <h4>Return value</h4>
      <table>
        <thead>
          <tr>
            <th>Type</th>
            <th>Description</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>
              <xsl:if test="not(docblock/tag[@name='return']/@type)">n/a</xsl:if>
              <xsl:if test="docblock/tag[@name='return']/@type">
                <xsl:if test="docblock/tag[@name='return']/@link">
                  <a href="{$root}{docblock/tag[@name='return']/@link}">
                    <xsl:value-of select="docblock/tag[@name='return']/@type" />
                  </a>
                </xsl:if>
                <xsl:if test="not(docblock/tag[@name='return']/@link)">
                  <xsl:value-of select="docblock/tag[@name='return']/@type" />
                </xsl:if>
              </xsl:if>
            </td>
            <td>
              <xsl:if test="not(docblock/tag[@name='return']/@description)">n/a</xsl:if>
              <xsl:value-of select="docblock/tag[@name='return']/@description" />
            </td>
          </tr>
        </tbody>
      </table>

      <xsl:if test="docblock/tag[@name != 'return' and @name != 'param']">
        <h4>Tags</h4>
        <table>
        <thead>
          <tr>
            <th>Name</th>
            <th>Description</th>
          </tr>
        </thead>
        <tbody>
        <xsl:for-each select="docblock/tag[@name != 'return' and @name != 'param']">
          <tr>
            <td>
              <xsl:value-of select="@name" />
            </td>
            <td>
                <xsl:if test="@link and @link != ''">
                  <a href="{$root}{@link}">
                    <xsl:if test="type">
                      <xsl:value-of select="type" /><br />
                    </xsl:if>
                    <small><xsl:value-of select="@description" /></small>
                  </a>
                </xsl:if>
                <xsl:if test="not(@link) or @link = ''"><xsl:value-of select="@description" /></xsl:if>
            </td>
          </tr>
        </xsl:for-each>
        </tbody>
        </table>
      </xsl:if>
    </div>

  </xsl:template>

  <xsl:template match="property">
    <div class="method">
      <a id="{../name}::{name}" />
      <h3>
        <span class="nb-faded-text">
          <xsl:value-of select="docblock/tag[@name='var']/@type" />&#160;
          <xsl:value-of select="@visibility" />&#160;
          <xsl:if test="@static='true'">static&#160;</xsl:if>
          <xsl:if test="@final='true'">final&#160;</xsl:if>
        </span>
        <xsl:value-of select="name" />
        <xsl:if test="default">
          =
          <xsl:value-of select="default" />
        </xsl:if>
      </h3>
      <em>
        <xsl:value-of select="docblock/description" disable-output-escaping="yes" />
        <xsl:value-of select="docblock/tag[@name='var']/@description" disable-output-escaping="yes" />
      </em>
      <xsl:if test="docblock/long-description">
        <br />
        <small>
          <xsl:value-of select="docblock/long-description" />
        </small>
        <br />
      </xsl:if>
      <br />
    </div>

  </xsl:template>

  <xsl:template match="constant">
    <a id="{../name}::{name}" />
    <div class="constant">
      <h3>
        <span class="nb-faded-text">
          <xsl:value-of select="docblock/tag[@name='var']/@description" />&#160;
        </span>
        <xsl:value-of select="name" />
        <span class="nb-faded-text">
         = <xsl:value-of select="value" />
        </span>
      </h3>
      <em>
        <xsl:value-of select="docblock/description" disable-output-escaping="yes" />
      </em>
      <br />
      <xsl:if test="docblock/long-description">
        <small>
          <xsl:value-of select="docblock/long-description" />
        </small>
        <br />
      </xsl:if>
      <br />
    </div>
  </xsl:template>
</xsl:stylesheet><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template name="search">
    <xsl:param name="search_template" />
    <xsl:param name="root" />

    <xsl:choose>
      <xsl:when test="$search_template='xmljs'">
        <xsl:call-template name="search_xmljs">
          <xsl:with-param name="root" select="$root" />
        </xsl:call-template>
      </xsl:when>
      <xsl:when test="$search_template='ajax'">
        <xsl:call-template name="search_ajax">
          <xsl:with-param name="root" select="$root" />
        </xsl:call-template>
      </xsl:when>
    </xsl:choose>
  </xsl:template>

  <xsl:template name="search_xmljs">
    <xsl:param name="root" />

    <script type="text/javascript">
      $(function() {

        var is_chrome = /chrome/.test( navigator.userAgent.toLowerCase() );
        var is_local = /file:\/\//.test(document.location.href);
        if (is_chrome &amp;&amp; is_local)
        {
          // search is disabled on chrome with local files due to http://code.google.com/p/chromium/issues/detail?id=40787
          return;
        }

        $("#search_box").show();
        var search_index = {};
        $.ajax({
          url: "<xsl:value-of select="$root" />search_index.xml",
          dataType: ($.browser.msie) ? "text" : "xml",
          error: function(data) {
            alert('An error occurred using the search data');
          },
          success: function( data ) {
            var xml;
            if (typeof data == "string") {
              xml = new ActiveXObject("Microsoft.XMLDOM");
              xml.async = false;
              xml.loadXML(data);
            } else {
              xml = data;
            }

            search_index = $("node", xml).map(function() {
              type = $("type", this).text();
              return {
                value: $("value", this).text(),
                label: '<img src="{$root}images/icons/'+type+'.png" align="absmiddle" />'+$("value", this).text(),
                id: $("id", this).text(),
              };
            }).get();

            $("#search_box").autocomplete({
              source: search_index,
              select: function(event, ui) {
                // redirect to the documentation
                if ((parent) &amp;&amp; (parent.content))
                {
                  parent.content.document.location = '<xsl:value-of select="$root" />'+ui.item.id;
                }
                else
                {
                  jQuery(document).location = '<xsl:value-of select="$root" />'+ui.item.id;
                }
                applySearchHash();
              }
            });
          }
        });
      });
    </script>
  </xsl:template>

  <xsl:template name="search_ajax">
    <xsl:param name="root" />

    <script type="text/javascript">
      $(function() {
        $("#search_box").show();
        $("#search_box").autocomplete({
          source: "<xsl:value-of select="$root" />ajax_search.php",
          minLength: 2,
          select: function(event, ui) {
            $(location).attr('href', '<xsl:value-of select="$root" />'+ui.item.id);
            applySearchHash();
          }
        });
      });
    </script>
  </xsl:template>

</xsl:stylesheet><?xml version="1.0"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes" method="html" />
  <xsl:include href="menu.xsl" />
  <xsl:include href="search.xsl" />

  <!-- Concatenate items with a given separator: http://symphony-cms.com/download/xslt-utilities/view/22517/-->
  <xsl:template name="implode">
    <xsl:param name="items" />
    <xsl:param name="separator" select="', '" />

    <xsl:for-each select="$items">
      <xsl:if test="position() &gt; 1">
        <xsl:value-of select="$separator" />
      </xsl:if>

      <xsl:value-of select="." />
    </xsl:for-each>
  </xsl:template>

  <xsl:template match="/">
    <html xmlns="http://www.w3.org/1999/xhtml">
      <head>
        <title><xsl:value-of select="$title" /></title>
        <meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
        <link rel="stylesheet" href="{$root}css/black-tie/jquery-ui-1.8.2.custom.css" type="text/css" />
        <link rel="stylesheet" href="{$root}css/jquery.treeview.css" type="text/css" />
        <link rel="stylesheet" href="{$root}css/default.css" type="text/css" />
        <script type="text/javascript" src="{$root}js/jquery-1.4.2.min.js"></script>
        <script type="text/javascript" src="{$root}js/jquery-ui-1.8.2.custom.min.js"></script>
        <script type="text/javascript" src="{$root}js/jquery.cookie.js"></script>
        <script type="text/javascript" src="{$root}js/jquery.treeview.js"></script>
      </head>
      <body>
        <script type="text/javascript">
          $(document).ready(function()
          {
            $(".filetree").treeview({
              animated: "fast",
              collapsed: true,
              persist: "cookie"
            });
          });

          function jq_escape(myid)
          {
            return '#' + myid.replace(/(#|\$|:|\.|\(|\))/g, '\\$1');
          }

          function applySearchHash()
          {
            hashes = document.location.hash.substr(1, document.location.hash.length);
            if (hashes != "")
            {
              hashes = hashes.split('/');
              $.each(hashes, function(index, hash)
              {
                node = $(jq_escape(hash));
                switch (node[0].nodeName)
                {
                  case 'DIV':
                    tabs = node.parents('.tabs');
                    $(tabs[0]).tabs('select', '#' + hash)
                    break;
                  case 'A':
                    window.scrollTo(0, node.offset().top);
                    break;
                }
              });
            }
          }

          jQuery(function()
          {
            jQuery(".tabs").tabs();
            applySearchHash();
          });
        </script>

        <div id="maincontainer">

          <div id="header">
            <h1>
              <xsl:if test="//@title != ''">
                <xsl:value-of select="//@title" disable-output-escaping="yes" />
              </xsl:if>
              <xsl:if test="//@title = ''">
                phpDocumentor
              </xsl:if>
              <img src="{$root}images/top-stopper.png" />
            </h1>
          </div>

          <xsl:call-template name="menu" />

          <div id="content_container">
            <xsl:apply-templates />
          </div>

          <div id="index">
            <div class="padder">
              <xsl:call-template name="search">
                <xsl:with-param name="root" select="$root" />
                <xsl:with-param name="search_template" select="$search_template" />
              </xsl:call-template>
              <input id="search_box" />
              <xsl:if test="$object-index">
              <xsl:value-of select="$object-index" disable-output-escaping="yes"/>
              </xsl:if>
            </div>
          </div>

          <div id="footer">
            <div class="padder"></div>
          </div>

        </div>

      </body>
    </html>
  </xsl:template>

</xsl:stylesheet>{
    "name": "phpdocumentor/template-xml",
    "type": "phpdocumentor-template",
    "description": "Generates an XML representation of the project's structure",
    "keywords": ["documentation", "template", "phpdoc"],
    "homepage": "http://www.phpdoc.org",
    "license": "MIT",
    "require": {
        "phpdocumentor/unified-asset-installer": "~1.1"
    }
}
<?xml version="1.0" encoding="utf-8"?>

<template>
  <author>Mike van Riel</author>
  <email>mike.vanriel@naenius.com</email>
  <description>Generates an XML representation of the project's structure</description>
  <version>1.0.0</version>
  <transformations>
    <transformation writer="xml" artifact="structure.xml"/>
  </transformations>
</template>
{
    "_readme": [
        "This file locks the dependencies of your project to a known state",
        "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
    ],
    "hash": "72418b2354d9f752ba74fd0b86c44f8e",
    "packages": [
        {
            "name": "phpdocumentor/unified-asset-installer",
            "version": "1.1",
            "source": {
                "type": "git",
                "url": "https://github.com/phpDocumentor/UnifiedAssetInstaller.git",
                "reference": "1.1"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phpDocumentor/UnifiedAssetInstaller/zipball/1.1",
                "reference": "1.1",
                "shasum": ""
            },
            "require-dev": {
                "composer/composer": "~1.0@dev",
                "phpunit/phpunit": "~3.7"
            },
            "type": "composer-installer",
            "extra": {
                "class": "\\phpDocumentor\\Composer\\UnifiedAssetInstaller"
            },
            "autoload": {
                "psr-0": {
                    "phpDocumentor\\Composer": [
                        "src/",
                        "test/unit/"
                    ]
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "description": "Asset installer for phpDocumentor",
            "homepage": "http://www.phpdoc.org",
            "keywords": [
                "assets",
                "installer",
                "plugins",
                "templates"
            ],
            "time": "2013-08-01 19:35:55"
        }
    ],
    "packages-dev": [

    ],
    "aliases": [

    ],
    "minimum-stability": "stable",
    "stability-flags": [

    ],
    "platform": [

    ],
    "platform-dev": [

    ]
}
{% extends 'layout.html.twig' %}

{% block javascripts %}
    <script type="text/javascript">
        function loadExternalCodeSnippets() {
            Array.prototype.slice.call(document.querySelectorAll('pre[data-src]')).forEach(function (pre) {
                var src = pre.getAttribute('data-src');
                var extension = (src.match(/\.(\w+)$/) || [, ''])[1];
                var language = 'php';

                var code = document.createElement('code');
                code.className = 'language-' + language;

                pre.textContent = '';

                code.textContent = 'Loading…';

                pre.appendChild(code);

                var xhr = new XMLHttpRequest();

                xhr.open('GET', src, true);

                xhr.onreadystatechange = function () {
                    if (xhr.readyState == 4) {

                        if (xhr.status < 400 && xhr.responseText) {
                            code.textContent = xhr.responseText;

                            Prism.highlightElement(code);
                        }
                        else if (xhr.status >= 400) {
                            code.textContent = '✖ Error ' + xhr.status + ' while fetching file: ' + xhr.statusText;
                        }
                        else {
                            code.textContent = '✖ Error: File does not exist or is empty';
                        }
                    }
                };

                xhr.send(null);
            });
        }

        $(document).ready(function(){
            loadExternalCodeSnippets();
        });
        $('#source-view').on('shown', function () {
            loadExternalCodeSnippets();
        })
    </script>
{% endblock %}

{% block content %}
    <section class="row-fluid">
        <div class="span2 sidebar">
            {% set namespace = project.namespace %}
            {{ block('sidebarNamespaces') }}
        </div>
    </section>
    <section class="row-fluid">
        <div class="span10 offset2">
            <div class="row-fluid">
                <div class="span8 content file">
                    <nav>
                        {#<a href="" class="pull-left">&laquo; NamespaceAssembler</a>#}
                        {#<a href="" class="pull-right">ClassAssembler &raquo;</a>#}
                    </nav>

                    <a href="#source-view" role="button" class="pull-right btn" data-toggle="modal"><i class="icon-code"></i></a>
                    <h1><small>{{ node.path|split('/')|slice(0,-1)|join('/') }}</small>{{ node.name }}</h1>
                    <p><em>{{ node.summary }}</em></p>
                    {{ node.description|markdown|raw }}

                    {% if node.traits|length > 0 %}
                    <h2>Traits</h2>
                    <table class="table table-hover">
                        {% for trait in node.traits %}
                            <tr>
                                <td>{{ trait|route('class:short')|raw }}</td>
                                <td><em>{{ trait.summary }}</em></td>
                            </tr>
                        {% endfor %}
                    </table>
                    {% endif %}

                    {% if node.interfaces|length > 0 %}
                    <h2>Interfaces</h2>
                    <table class="table table-hover">
                        {% for interface in node.interfaces %}
                            <tr>
                                <td>{{ interface|route('class:short')|raw }}</td>
                                <td><em>{{ interface.summary }}</em></td>
                            </tr>
                        {% endfor %}
                    </table>
                    {% endif %}

                    {% if node.classes|length > 0 %}
                    <h2>Classes</h2>
                    <table class="table table-hover">
                    {% for class in node.classes %}
                        <tr>
                            <td>{{ class|route('class:short')|raw }}</td>
                            <td><em>{{ class.summary }}</em></td>
                        </tr>
                    {% endfor %}
                    </table>
                    {% endif %}
                </div>

                <aside class="span4 detailsbar">
                    <dl>
                        {% if node.package is not empty and node.package != '\\' %}
                            <dt>Package</dt>
                            <dd><div class="namespace-wrapper">{{ node.subpackage ? (node.package ~ '\\' ~ node.subpackage) : node.package }}</div></dd>
                        {% endif %}

                        {% for tagName,tags in node.tags if tagName in ['link', 'see'] %}
                            {% if loop.first %}
                                <dt>See also</dt>
                            {% endif %}
                            {% for tag in tags %}
                                <dd><a href="{{ tag.link }}"><div class="namespace-wrapper">{{ tag.description }}</div></a></dd>
                            {% endfor %}
                        {% endfor %}

                    </dl>
                    <h2>Tags</h2>
                    <table class="table table-condensed">
                        {% for tagName,tags in node.tags if tagName not in ['link', 'see', 'package', 'subpackage'] %}
                            <tr>
                                <th>
                                    {{ tagName }}
                                </th>
                                <td>
                                    {% for tag in tags %}
                                        {{ tag.description|markdown|raw }}
                                    {% endfor %}
                                </td>
                            </tr>
                        {% else %}
                            <tr><td colspan="2"><em>None found</em></td></tr>
                        {% endfor %}
                    </table>

                </aside>
            </div>

            {% if node.constants|length > 0 %}
            <div class="row-fluid">
                <section class="span8 content file">
                    <h2>Constants</h2>
                </section>
                <aside class="span4 detailsbar"></aside>
            </div>

                {% for constant in node.constants %}
                    {{ block('constant') }}
                {% endfor %}
            {% endif %}

            {% if node.functions|length > 0 %}
            <div class="row-fluid">
                <section class="span8 content file">
                    <h2>Functions</h2>
                </section>
                <aside class="span4 detailsbar"></aside>
            </div>

                {% for method in node.functions %}
                    {{ block('method') }}
                {% endfor %}
            {% endif %}

        </div>
    </section>

    <div id="source-view" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="source-view-label" aria-hidden="true">
        <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
            <h3 id="source-view-label">{{ node.file.name }}</h3>
        </div>
        <div class="modal-body">
            <pre data-src="{{ path('files/' ~ node.path ~ '.txt') }}" class="language-php line-numbers"></pre>
        </div>
    </div>
{% endblock %}
{
    "name": "phpdocumentor/template-clean",
    "type": "phpdocumentor-template",
    "description": "A clean, responsive modern template for phpDocumentor for Twig aimed at usability",
    "keywords": ["documentation", "template", "phpdoc", "responsive"],
    "homepage": "http://www.phpdoc.org",
    "license": "MIT",
    "require": {
        "phpdocumentor/unified-asset-installer": "~1.1"
    }
}
{% extends 'layout.html.twig' %}

{% block content %}
    <section class="row-fluid">
        <div class="span2 sidebar">
            {% set namespace = project.namespace %}
            {{ block('sidebarNamespaces') }}
        </div>
    </section>
    <section class="row-fluid">
        <div class="span10 offset2">
            <div class="row-fluid">
                <div class="span8 content namespace">
                    <nav>
                        {#<a href="" class="pull-left">&laquo; NamespaceAssembler</a>#}
                        {{ node.parent|route|raw }}
                        {#<a href="" class="pull-right">ClassAssembler &raquo;</a>#}
                    </nav>
                    <h1><small>{{ node.parent.fullyQualifiedStructuralElementName }}</small>{{ node.name }}</h1>

                    {% if node.children|length > 0 %}
                    <h2>Namespaces</h2>
                    <table class="table table-hover">
                        {% for namespace in node.children %}
                            <tr>
                                <td>{{ namespace|route('class:short')|raw }}</td>
                            </tr>
                        {% endfor %}
                    </table>
                    {% endif %}

                    {% if node.traits|length > 0 %}
                    <h2>Traits</h2>
                    <table class="table table-hover">
                        {% for trait in node.traits %}
                            <tr>
                                <td>{{ trait|route('class:short')|raw }}</td>
                                <td><em>{{ trait.summary }}</em></td>
                            </tr>
                        {% endfor %}
                    </table>
                    {% endif %}

                    {% if node.interfaces|length > 0 %}
                    <h2>Interfaces</h2>
                    <table class="table table-hover">
                        {% for interface in node.interfaces %}
                            <tr>
                                <td>{{ interface|route('class:short')|raw }}</td>
                                <td><em>{{ interface.summary }}</em></td>
                            </tr>
                        {% endfor %}
                    </table>
                    {% endif %}

                    {% if node.classes|length > 0 %}
                    <h2>Classes</h2>
                    <table class="table table-hover">
                    {% for class in node.classes %}
                        <tr>
                            <td>{{ class|route('class:short')|raw }}</td>
                            <td><em>{{ class.summary }}</em></td>
                        </tr>
                    {% endfor %}
                    </table>
                    {% endif %}
                </div>

                <aside class="span4 detailsbar">
                    <dl>
                        <dt>Namespace hierarchy</dt>
                        <dd class="hierarchy">
                            {% set namespace = node.parent %}
                            {% block hierarchy_element %}
                                {% if namespace %}
                                    {% set child = namespace %}
                                    {% set namespace = namespace.parent %}
                                    {{ block('hierarchy_element') }}
                                    <div class="namespace-wrapper">{{ child|route|raw }}</div>
                                {% endif %}
                            {% endblock %}
                            <div class="namespace-wrapper">{{ node.fullyQualifiedStructuralElementName}}</div>
                        </dd>
                    </dl>
                </aside>
            </div>

            {% if node.constants|length > 0 %}
            <div class="row-fluid">
                <section class="span8 content namespace">
                    <h2>Constants</h2>
                </section>
                <aside class="span4 detailsbar"></aside>
            </div>

                {% for constant in node.constants %}
                    {{ block('constant') }}
                {% endfor %}
            {% endif %}

            {% if node.functions|length > 0 %}
            <div class="row-fluid">
                <section class="span8 content namespace">
                    <h2>Functions</h2>
                </section>
                <aside class="span4 detailsbar"></aside>
            </div>

                {% for method in node.functions %}
                    {{ block('method') }}
                {% endfor %}
            {% endif %}

        </div>
    </section>
{% endblock %}
{% extends 'layout.html.twig' %}

{% block title %}
    {{ project.title }} &raquo; Markers
{% endblock %}

{% block content %}
    <section class="row-fluid">
        <div class="span2 sidebar">
            <ul class="side-nav nav nav-list">
                <li class="nav-header">Navigation</li>
                {% set markerCount = 0 %}
                {% for file in project.files %}
                    {% if file.markers.count > 0 %}
                    <li><a href="#{{ file.path }}"><i class="icon-file"></i> {{ file.path }}</a></li>
                    {% endif %}
                    {% set markerCount = markerCount + file.markers.count %}
                {% endfor %}
            </ul>
        </div>

        <div class="span10 offset2">

            <ul class="breadcrumb">
                <li><a href="{{ path('/') }}"><i class="icon-map-marker"></i></a><span class="divider">\</span></li>
                <li>Markers</li>
            </ul>

            {% if markerCount <= 0 %}
                <div class="alert alert-info">No markers have been found in this project.</div>
            {% endif %}

            <div id="marker-accordion">
                {% for file in project.files %}
                    {% if file.markers.count > 0 %}
                        <div class="package-contents">
                            <a name="{{ file.path }}" id="{{ file.path }}"></a>
                            <h3>
                            <i class="icon-file"></i>
                                {{ file.path }}
                                <small style="float: right;padding-right: 10px;">{{ file.markers.count }}</small>
                            </h3>
                            <div>
                                <table class="table markers table-bordered">
                                    <tr>
                                        <th>Type</th>
                                        <th>Line</th>
                                        <th>Description</th>
                                    </tr>
                                    {% for marker in file.markers %}
                                        <tr>
                                            <td>{{ marker.type }}</td>
                                            <td>{{ marker.line }}</td>
                                            <td>{{ marker.message }}</td>
                                        </tr>
                                    {% endfor %}
                                </table>
                            </div>
                        </div>
                    {% endif %}
                {% endfor %}
            </div>
        </div>
    </section>
{% endblock %}
{% extends 'layout.html.twig' %}

{% block title %}
    {{ project.title }} &raquo; Compilation errors
{% endblock %}

{% block content %}
    <section class="row-fluid">
        <div class="span2 sidebar">

            <ul class="side-nav nav nav-list">
                <li class="nav-header">Navigation</li>
                {% set errorCount = 0 %}
                {% for file in project.files %}
                    {% if file.allerrors.count > 0 %}
                        <li><a href="#{{ file.path }}"><i class="icon-file"></i> {{ file.path }}</a></li>
                    {% endif %}
                    {% set errorCount = errorCount + file.allerrors.count %}
                {% endfor %}
            </ul>
        </div>

        <div class="span10 offset2">
            <ul class="breadcrumb">
                <li><a href="{{ path('/') }}"><i class="icon-remove-sign"></i></a><span class="divider">\</span></li>
                <li>Compilation Errors</li>
            </ul>

            {% if errorCount <= 0 %}
                <div class="alert alert-info">No errors have been found in this project.</div>
            {% endif %}

            {% for file in project.files %}
                <div class="package-contents">
                    {% if file.allerrors.count > 0 %}
                        <a name="{{ file.path }}" id="{{ file.path }}"></a>
                        <h3>
                            <i class="icon-file"></i>
                            {{ file.path }}
                            <small style="float: right;padding-right: 10px;">{{ file.allerrors.count }}</small>
                        </h3>
                        <div>
                            <table class="table markers table-bordered">
                                <thead>
                                <tr>
                                    <th>Type</th>
                                    <th>Line</th>
                                    <th>Description</th>
                                </tr>
                                </thead>
                                <tbody>
                                {% for error in file.allerrors %}
                                    <tr>
                                        <td>{{ error.severity }}</td>
                                        <td>{{ error.line }}</td>
                                        <td>{{ error.code|trans(error.context) }}</td>
                                    </tr>
                                {% endfor %}
                            </tbody>
                            </table>
                        </div>
                    {% endif %}
                </div>
            {% endfor %}
        </div>
    </section>
{% endblock %}
{% extends 'layout.html.twig' %}

{% block title %}
    {{ project.title }} &raquo; Deprecated elements
{% endblock %}

{% block content %}
    <div class="row-fluid">

        <div class="span2 sidebar">
            <ul class="side-nav nav nav-list">
                <li class="nav-header">Navigation</li>
                {% for file in project.files if file.tags.deprecated %}
                    <li><a href="#{{ file.path }}"><i class="icon-file"></i> {{ file.path }}</a></li>
                {% endfor %}
            </ul>
        </div>

        <div class="span10 offset2">
            <ul class="breadcrumb">
                <li><a href="{{ path('/') }}"><i class="icon-stop"></i></a><span class="divider">\</span></li>
                <li>Deprecated elements</li>
            </ul>

            <div id="marker-accordion">
                {% for element in project.indexes.elements if element.deprecated %}
                    <a name="{{ element.path }}" id="{{ element.path }}"></a>
                    <h3>
                        <i class="icon-file"></i> {{ element.path }}
                        <small style="float: right;padding-right: 10px;">{{ element.tags.deprecated.count }}</small>
                    </h3>
                    <div>
                        <table class="table markers table-bordered">
                            <tr>
                                <th>Type</th>
                                <th>Line</th>
                                <th>Description</th>
                            </tr>
                            {% for tag in element.tags.deprecated %}
                                <tr>
                                    <td>{{ tag.name }}</td>
                                    <td>{{ tag.line }}</td>
                                    <td>{{ tag.description }}</td>
                                </tr>
                            {% endfor %}
                        </table>
                    </div>
                {% else %}
                    <div class="alert alert-info">No deprecated elements have been found in this project.</div>
                {% endfor %}
            </div>
        </div>
    </div>
{% endblock %}
/*
 * iviewer Widget for jQuery UI
 * https://github.com/can3p/iviewer
 *
 * Copyright (c) 2009 - 2012 Dmitry Petrov
 * Dual licensed under the MIT and GPL licenses.
 *  - http://www.opensource.org/licenses/mit-license.php
 *  - http://www.gnu.org/copyleft/gpl.html
 *
 * Author: Dmitry Petrov
 * Version: 0.7.7
 */
(function($,undefined){var mouseEvents={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup"},gesturesSupport="ongesturestart"in document.createElement("div");function makeMouseEvent(event){var touch=event.originalEvent.changedTouches[0];return $.extend(event,{type:mouseEvents[event.type],which:1,pageX:touch.pageX,pageY:touch.pageY,screenX:touch.screenX,screenY:touch.screenY,clientX:touch.clientX,clientY:touch.clientY,isTouchEvent:true})}var mouseProto=$.ui.mouse.prototype,_mouseInit=$.ui.mouse.prototype._mouseInit;
mouseProto._mouseInit=function(){var self=this;self._touchActive=false;this.element.bind("touchstart."+this.widgetName,function(event){if(gesturesSupport&&event.originalEvent.touches.length>1)return;self._touchActive=true;return self._mouseDown(makeMouseEvent(event))});var self=this;this._mouseMoveDelegate=function(event){if(gesturesSupport&&event.originalEvent.touches&&event.originalEvent.touches.length>1)return;if(self._touchActive)return self._mouseMove(makeMouseEvent(event))};this._mouseUpDelegate=
function(event){if(self._touchActive){self._touchActive=false;return self._mouseUp(makeMouseEvent(event))}};$(document).bind("touchmove."+this.widgetName,this._mouseMoveDelegate).bind("touchend."+this.widgetName,this._mouseUpDelegate);_mouseInit.apply(this)};var setter=function(setter,getter){return function(val){if(arguments.length===0)return getter.apply(this);else setter.apply(this,arguments)}};var ieTransforms={"0":{marginLeft:0,marginTop:0,filter:'progid:DXImageTransform.Microsoft.Matrix(M11=1, M12=0, M21=0, M22=1, SizingMethod="auto expand")'},
90:{marginLeft:-1,marginTop:1,filter:'progid:DXImageTransform.Microsoft.Matrix(M11=0, M12=-1, M21=1, M22=0, SizingMethod="auto expand")'},180:{marginLeft:0,marginTop:0,filter:'progid:DXImageTransform.Microsoft.Matrix(M11=-1, M12=0, M21=0, M22=-1, SizingMethod="auto expand")'},270:{marginLeft:-1,marginTop:1,filter:'progid:DXImageTransform.Microsoft.Matrix(M11=0, M12=1, M21=-1, M22=0, SizingMethod="auto expand")'}},useIeTransforms=function(){var el=document.createElement("div");el.style.cssText=["-ms-",
"",""].join("filter:blur(2px); ");return!!el.style.cssText&&document.documentMode<9}();$.widget("ui.iviewer",$.ui.mouse,{widgetEventPrefix:"iviewer",options:{zoom:"fit",zoom_base:100,zoom_max:800,zoom_min:25,zoom_delta:1.4,zoom_animation:true,ui_disabled:false,mousewheel:true,update_on_resize:true,onZoom:jQuery.noop,onAfterZoom:jQuery.noop,onStartDrag:jQuery.noop,onDrag:jQuery.noop,onStopDrag:jQuery.noop,onMouseMove:jQuery.noop,onClick:jQuery.noop,onStartLoad:null,onFinishLoad:null,onErrorLoad:null},
_create:function(){var me=this;this.dx=0;this.dy=0;this.img_object={};this.zoom_object={};this._angle=0;this.current_zoom=this.options.zoom;if(this.options.src===null)return;this.container=this.element;this._updateContainerInfo();this.container.css("overflow","hidden");if(this.options.update_on_resize==true)$(window).resize(function(){me.update()});this.img_object=new $.ui.iviewer.ImageObject(this.options.zoom_animation);if(this.options.mousewheel){this.container.bind("mousewheel.iviewer",function(ev,
delta){var zoom=delta>0?1:-1,container_offset=me.container.offset(),mouse_pos={x:ev.pageX-container_offset.left,y:ev.pageY-container_offset.top};me.zoom_by(zoom,mouse_pos);return false});if(gesturesSupport){var gestureThrottle=+new Date;var originalScale,originalCenter;this.img_object.object().bind("touchstart",function(ev){originalScale=me.current_zoom;var touches=ev.originalEvent.touches,container_offset;if(touches.length==2){container_offset=me.container.offset();originalCenter={x:(touches[0].pageX+
touches[1].pageX)/2-container_offset.left,y:(touches[0].pageY+touches[1].pageY)/2-container_offset.top}}else originalCenter=null}).bind("gesturechange",function(ev){var d=+new Date;if(d-gestureThrottle<50)return;gestureThrottle=d;var zoom=originalScale*ev.originalEvent.scale;me.set_zoom(zoom,originalCenter);ev.preventDefault()}).bind("gestureend",function(ev){originalCenter=null})}}this.img_object.object().click(function(e){return me._click(e)}).prependTo(this.container);this.container.bind("mousemove",
function(ev){me._handleMouseMove(ev)});this.loadImage(this.options.src);if(!this.options.ui_disabled)this.createui();this._mouseInit()},destroy:function(){$.Widget.prototype.destroy.call(this);this._mouseDestroy();this.img_object.object().remove();this.container.off(".iviewer");this.container.css("overflow","")},_updateContainerInfo:function(){this.options.height=this.container.height();this.options.width=this.container.width()},update:function(){this._updateContainerInfo();this.setCoords(this.img_object.x(),
this.img_object.y())},loadImage:function(src){this.current_zoom=this.options.zoom;var me=this;this._trigger("onStartLoad",0,src);this.container.addClass("iviewer_loading");this.img_object.load(src,function(){me._imageLoaded(src)},function(){me._trigger("onErrorLoad",0,src)})},_imageLoaded:function(src){this.container.removeClass("iviewer_loading");this.container.addClass("iviewer_cursor");if(this.options.zoom=="fit")this.fit(true);else this.set_zoom(this.options.zoom,true);this._trigger("onFinishLoad",
0,src)},fit:function(skip_animation){var aspect_ratio=this.img_object.orig_width()/this.img_object.orig_height();var window_ratio=this.options.width/this.options.height;var choose_left=aspect_ratio>window_ratio;var new_zoom=0;if(choose_left)new_zoom=this.options.width/this.img_object.orig_width()*100;else new_zoom=this.options.height/this.img_object.orig_height()*100;this.set_zoom(new_zoom,skip_animation)},center:function(){this.setCoords(-Math.round((this.img_object.display_width()-this.options.width)/
2),-Math.round((this.img_object.display_height()-this.options.height)/2))},moveTo:function(x,y){var dx=x-Math.round(this.options.width/2);var dy=y-Math.round(this.options.height/2);var new_x=this.img_object.x()-dx;var new_y=this.img_object.y()-dy;this.setCoords(new_x,new_y)},getContainerOffset:function(){return jQuery.extend({},this.container.offset())},setCoords:function(x,y){if(!this.img_object.loaded())return;var coords=this._correctCoords(x,y);this.img_object.x(coords.x);this.img_object.y(coords.y)},
_correctCoords:function(x,y){x=parseInt(x,10);y=parseInt(y,10);if(y>0)y=0;if(x>0)x=0;if(y+this.img_object.display_height()<this.options.height)y=this.options.height-this.img_object.display_height();if(x+this.img_object.display_width()<this.options.width)x=this.options.width-this.img_object.display_width();if(this.img_object.display_width()<=this.options.width)x=-(this.img_object.display_width()-this.options.width)/2;if(this.img_object.display_height()<=this.options.height)y=-(this.img_object.display_height()-
this.options.height)/2;return{x:x,y:y}},containerToImage:function(x,y){var coords={x:x-this.img_object.x(),y:y-this.img_object.y()};coords=this.img_object.toOriginalCoords(coords);return{x:util.descaleValue(coords.x,this.current_zoom),y:util.descaleValue(coords.y,this.current_zoom)}},imageToContainer:function(x,y){var coords={x:util.scaleValue(x,this.current_zoom),y:util.scaleValue(y,this.current_zoom)};return this.img_object.toRealCoords(coords)},_getMouseCoords:function(e){var containerOffset=this.container.offset();
coords=this.containerToImage(e.pageX-containerOffset.left,e.pageY-containerOffset.top);return coords},set_zoom:function(new_zoom,skip_animation,zoom_center){if(this._trigger("onZoom",0,new_zoom)==false)return;if(!this.img_object.loaded())return;zoom_center=zoom_center||{x:Math.round(this.options.width/2),y:Math.round(this.options.height/2)};if(new_zoom<this.options.zoom_min)new_zoom=this.options.zoom_min;else if(new_zoom>this.options.zoom_max)new_zoom=this.options.zoom_max;if(this.current_zoom=="fit"){var old_x=
zoom_center.x+Math.round(this.img_object.orig_width()/2);var old_y=zoom_center.y+Math.round(this.img_object.orig_height()/2);this.current_zoom=100}else{var old_x=-this.img_object.x()+zoom_center.x;var old_y=-this.img_object.y()+zoom_center.y}var new_width=util.scaleValue(this.img_object.orig_width(),new_zoom);var new_height=util.scaleValue(this.img_object.orig_height(),new_zoom);var new_x=util.scaleValue(util.descaleValue(old_x,this.current_zoom),new_zoom);var new_y=util.scaleValue(util.descaleValue(old_y,
this.current_zoom),new_zoom);new_x=zoom_center.x-new_x;new_y=zoom_center.y-new_y;new_width=Math.floor(new_width);new_height=Math.floor(new_height);new_x=Math.floor(new_x);new_y=Math.floor(new_y);this.img_object.display_width(new_width);this.img_object.display_height(new_height);var coords=this._correctCoords(new_x,new_y),self=this;this.img_object.setImageProps(new_width,new_height,coords.x,coords.y,skip_animation,function(){self._trigger("onAfterZoom",0,new_zoom)});this.current_zoom=new_zoom;this.update_status()},
zoom_by:function(delta,zoom_center){var closest_rate=this.find_closest_zoom_rate(this.current_zoom);var next_rate=closest_rate+delta;var next_zoom=this.options.zoom_base*Math.pow(this.options.zoom_delta,next_rate);if(delta>0&&next_zoom<this.current_zoom)next_zoom*=this.options.zoom_delta;if(delta<0&&next_zoom>this.current_zoom)next_zoom/=this.options.zoom_delta;this.set_zoom(next_zoom,undefined,zoom_center)},angle:function(deg,abs){if(arguments.length===0)return this.img_object.angle();if(deg<-270||
deg>270||deg%90!==0)return;if(!abs)deg+=this.img_object.angle();if(deg<0)deg+=360;if(deg>=360)deg-=360;if(deg===this.img_object.angle())return;this.img_object.angle(deg);this.center();this._trigger("angle",0,{angle:this.img_object.angle()})},find_closest_zoom_rate:function(value){if(value==this.options.zoom_base)return 0;function div(val1,val2){return val1/val2}function mul(val1,val2){return val1*val2}var func=value>this.options.zoom_base?mul:div;var sgn=value>this.options.zoom_base?1:-1;var mltplr=
this.options.zoom_delta;var rate=1;while(Math.abs(func(this.options.zoom_base,Math.pow(mltplr,rate))-value)>Math.abs(func(this.options.zoom_base,Math.pow(mltplr,rate+1))-value))rate++;return sgn*rate},update_status:function(){if(!this.options.ui_disabled){var percent=Math.round(100*this.img_object.display_height()/this.img_object.orig_height());if(percent)this.zoom_object.html(percent+"%")}},info:function(param,withoutRotation){if(!param)return;switch(param){case "orig_width":case "orig_height":if(withoutRotation)return this.img_object.angle()%
180===0?this.img_object[param]():param==="orig_width"?this.img_object.orig_height():this.img_object.orig_width();else return this.img_object[param]();case "display_width":case "display_height":case "angle":return this.img_object[param]();case "zoom":return this.current_zoom;case "src":return this.img_object.object().attr("src");case "coords":return{x:this.img_object.x(),y:this.img_object.y()}}},_mouseStart:function(e){$.ui.mouse.prototype._mouseStart.call(this,e);if(this._trigger("onStartDrag",0,
this._getMouseCoords(e))===false)return false;this.container.addClass("iviewer_drag_cursor");this._dragInitialized=!(e.originalEvent.changedTouches&&e.originalEvent.changedTouches.length==1);this.dx=e.pageX-this.img_object.x();this.dy=e.pageY-this.img_object.y();return true},_mouseCapture:function(e){return true},_handleMouseMove:function(e){this._trigger("onMouseMove",e,this._getMouseCoords(e))},_mouseDrag:function(e){$.ui.mouse.prototype._mouseDrag.call(this,e);if(!this._dragInitialized){this.dx=
e.pageX-this.img_object.x();this.dy=e.pageY-this.img_object.y();this._dragInitialized=true}var ltop=e.pageY-this.dy;var lleft=e.pageX-this.dx;this.setCoords(lleft,ltop);this._trigger("onDrag",e,this._getMouseCoords(e));return false},_mouseStop:function(e){$.ui.mouse.prototype._mouseStop.call(this,e);this.container.removeClass("iviewer_drag_cursor");this._trigger("onStopDrag",0,this._getMouseCoords(e))},_click:function(e){this._trigger("onClick",0,this._getMouseCoords(e))},createui:function(){var me=
this;$("<div>",{"class":"iviewer_zoom_in iviewer_common iviewer_button"}).bind("mousedown touchstart",function(){me.zoom_by(1);return false}).appendTo(this.container);$("<div>",{"class":"iviewer_zoom_out iviewer_common iviewer_button"}).bind("mousedown touchstart",function(){me.zoom_by(-1);return false}).appendTo(this.container);$("<div>",{"class":"iviewer_zoom_zero iviewer_common iviewer_button"}).bind("mousedown touchstart",function(){me.set_zoom(100);return false}).appendTo(this.container);$("<div>",
{"class":"iviewer_zoom_fit iviewer_common iviewer_button"}).bind("mousedown touchstart",function(){me.fit(this);return false}).appendTo(this.container);this.zoom_object=$("<div>").addClass("iviewer_zoom_status iviewer_common").appendTo(this.container);$("<div>",{"class":"iviewer_rotate_left iviewer_common iviewer_button"}).bind("mousedown touchstart",function(){me.angle(-90);return false}).appendTo(this.container);$("<div>",{"class":"iviewer_rotate_right iviewer_common iviewer_button"}).bind("mousedown touchstart",
function(){me.angle(90);return false}).appendTo(this.container);this.update_status()}});$.ui.iviewer.ImageObject=function(do_anim){this._img=$("<img>").css({position:"absolute",top:"0px",left:"0px"});this._loaded=false;this._swapDimensions=false;this._do_anim=do_anim||false;this.x(0,true);this.y(0,true);this.angle(0)};(function(){this._reset=function(w,h){this._angle=0;this._swapDimensions=false;this.x(0);this.y(0);this.orig_width(w);this.orig_height(h);this.display_width(w);this.display_height(h)};
this.loaded=function(){return this._loaded};this.load=function(src,loaded,error){var self=this;loaded=loaded||jQuery.noop;this._loaded=false;var img=new Image;img.onload=function(){self._loaded=true;self._reset(this.width,this.height);self._img.removeAttr("width").removeAttr("height").removeAttr("style").css({position:"absolute",top:"0px",left:"0px",maxWidth:"none"});self._img[0].src=src;loaded()};img.onerror=error;setTimeout(function(){img.src=src},0);this.angle(0)};this._dimension=function(prefix,
name){var horiz="_"+prefix+"_"+name,vert="_"+prefix+"_"+(name==="height"?"width":"height");return setter(function(val){this[this._swapDimensions?horiz:vert]=val},function(){return this[this._swapDimensions?horiz:vert]})};this.display_width=this._dimension("display","width"),this.display_height=this._dimension("display","height"),this.display_diff=function(){return Math.floor(this.display_width()-this.display_height())};this.orig_width=this._dimension("orig","width"),this.orig_height=this._dimension("orig",
"height"),this.x=setter(function(val,skipCss){this._x=val;if(!skipCss){this._finishAnimation();this._img.css("left",this._x+(this._swapDimensions?this.display_diff()/2:0)+"px")}},function(){return this._x});this.y=setter(function(val,skipCss){this._y=val;if(!skipCss){this._finishAnimation();this._img.css("top",this._y-(this._swapDimensions?this.display_diff()/2:0)+"px")}},function(){return this._y});this.angle=setter(function(deg){var prevSwap=this._swapDimensions;this._angle=deg;this._swapDimensions=
deg%180!==0;if(prevSwap!==this._swapDimensions){var verticalMod=this._swapDimensions?-1:1;this.x(this.x()-verticalMod*this.display_diff()/2,true);this.y(this.y()+verticalMod*this.display_diff()/2,true)}var cssVal="rotate("+deg+"deg)",img=this._img;jQuery.each(["","-webkit-","-moz-","-o-","-ms-"],function(i,prefix){img.css(prefix+"transform",cssVal)});if(useIeTransforms){jQuery.each(["-ms-",""],function(i,prefix){img.css(prefix+"filter",ieTransforms[deg].filter)});img.css({marginLeft:ieTransforms[deg].marginLeft*
this.display_diff()/2,marginTop:ieTransforms[deg].marginTop*this.display_diff()/2})}},function(){return this._angle});this.toOriginalCoords=function(point){switch(this.angle()){case 0:return{x:point.x,y:point.y};case 90:return{x:point.y,y:this.display_width()-point.x};case 180:return{x:this.display_width()-point.x,y:this.display_height()-point.y};case 270:return{x:this.display_height()-point.y,y:point.x}}};this.toRealCoords=function(point){switch(this.angle()){case 0:return{x:this.x()+point.x,y:this.y()+
point.y};case 90:return{x:this.x()+this.display_width()-point.y,y:this.y()+point.x};case 180:return{x:this.x()+this.display_width()-point.x,y:this.y()+this.display_height()-point.y};case 270:return{x:this.x()+point.y,y:this.y()+this.display_height()-point.x}}};this.object=setter(jQuery.noop,function(){return this._img});this.setImageProps=function(disp_w,disp_h,x,y,skip_animation,complete){complete=complete||jQuery.noop;this.display_width(disp_w);this.display_height(disp_h);this.x(x,true);this.y(y,
true);var w=this._swapDimensions?disp_h:disp_w;var h=this._swapDimensions?disp_w:disp_h;var params={width:w,height:h,top:y-(this._swapDimensions?this.display_diff()/2:0)+"px",left:x+(this._swapDimensions?this.display_diff()/2:0)+"px"};if(useIeTransforms)jQuery.extend(params,{marginLeft:ieTransforms[this.angle()].marginLeft*this.display_diff()/2,marginTop:ieTransforms[this.angle()].marginTop*this.display_diff()/2});var swapDims=this._swapDimensions,img=this._img;if(useIeTransforms&&swapDims){var ieh=
this._img.width(),iew=this._img.height(),iedh=params.height-ieh;iedw=params.width-iew;delete params.width;delete params.height}if(this._do_anim&&!skip_animation)this._img.stop(true).animate(params,{duration:200,complete:complete,step:function(now,fx){if(useIeTransforms&&swapDims&&fx.prop==="top"){var percent=(now-fx.start)/(fx.end-fx.start);img.height(ieh+iedh*percent);img.width(iew+iedw*percent);img.css("top",now)}}});else{this._img.css(params);setTimeout(complete,0)}};this._finishAnimation=function(){this._img.stop(true,
true)}}).apply($.ui.iviewer.ImageObject.prototype);var util={scaleValue:function(value,toZoom){return value*toZoom/100},descaleValue:function(value,fromZoom){return value*100/fromZoom}}})(jQuery,undefined);
/*
 * iviewer Widget for jQuery UI
 * https://github.com/can3p/iviewer
 *
 * Copyright (c) 2009 - 2012 Dmitry Petrov
 * Dual licensed under the MIT and GPL licenses.
 *  - http://www.opensource.org/licenses/mit-license.php
 *  - http://www.gnu.org/copyleft/gpl.html
 *
 * Author: Dmitry Petrov
 * Version: 0.7.7
 */

( function( $, undefined ) {

//this code was taken from the https://github.com/furf/jquery-ui-touch-punch
var mouseEvents = {
        touchstart: 'mousedown',
        touchmove: 'mousemove',
        touchend: 'mouseup'
    },
    gesturesSupport = 'ongesturestart' in document.createElement('div');


/**
 * Convert a touch event to a mouse-like
 */
function makeMouseEvent (event) {
    var touch = event.originalEvent.changedTouches[0];

    return $.extend(event, {
        type:    mouseEvents[event.type],
        which:   1,
        pageX:   touch.pageX,
        pageY:   touch.pageY,
        screenX: touch.screenX,
        screenY: touch.screenY,
        clientX: touch.clientX,
        clientY: touch.clientY,
        isTouchEvent: true
    });
}

var mouseProto = $.ui.mouse.prototype,
    _mouseInit = $.ui.mouse.prototype._mouseInit;

mouseProto._mouseInit = function() {
    var self = this;
    self._touchActive = false;

    this.element.bind( 'touchstart.' + this.widgetName, function(event) {
        if (gesturesSupport && event.originalEvent.touches.length > 1) { return; }
        self._touchActive = true;
        return self._mouseDown(makeMouseEvent(event));
    })

    var self = this;
    // these delegates are required to keep context
    this._mouseMoveDelegate = function(event) {
        if (gesturesSupport && event.originalEvent.touches && event.originalEvent.touches.length > 1) { return; }
        if (self._touchActive) {
            return self._mouseMove(makeMouseEvent(event));
        }
    };
    this._mouseUpDelegate = function(event) {
        if (self._touchActive) {
            self._touchActive = false;
            return self._mouseUp(makeMouseEvent(event));
        }
    };

    $(document)
        .bind('touchmove.'+ this.widgetName, this._mouseMoveDelegate)
        .bind('touchend.' + this.widgetName, this._mouseUpDelegate);

    _mouseInit.apply(this);
}

/**
 * Simple implementation of jQuery like getters/setters
 * var val = something();
 * something(val);
 */
var setter = function(setter, getter) {
    return function(val) {
        if (arguments.length === 0) {
            return getter.apply(this);
        } else {
            setter.apply(this, arguments);
        }
    }
};

/**
 * Internet explorer rotates image relative left top corner, so we should
 * shift image when it's rotated.
 */
var ieTransforms = {
        '0': {
            marginLeft: 0,
            marginTop: 0,
            filter: 'progid:DXImageTransform.Microsoft.Matrix(M11=1, M12=0, M21=0, M22=1, SizingMethod="auto expand")'
        },

        '90': {
            marginLeft: -1,
            marginTop: 1,
            filter: 'progid:DXImageTransform.Microsoft.Matrix(M11=0, M12=-1, M21=1, M22=0, SizingMethod="auto expand")'
        },

        '180': {
            marginLeft: 0,
            marginTop: 0,
            filter: 'progid:DXImageTransform.Microsoft.Matrix(M11=-1, M12=0, M21=0, M22=-1, SizingMethod="auto expand")'
        },

        '270': {
            marginLeft: -1,
            marginTop: 1,
            filter: 'progid:DXImageTransform.Microsoft.Matrix(M11=0, M12=1, M21=-1, M22=0, SizingMethod="auto expand")'
        }
    },
    // this test is the inversion of the css filters test from the modernizr project
    useIeTransforms = function() {
        var modElem = document.createElement('modernizr'),
		mStyle = modElem.style,
		omPrefixes = 'Webkit Moz O ms',
		domPrefixes = omPrefixes.toLowerCase().split(' '),
        	props = ("transform" + ' ' + domPrefixes.join("Transform ") + "Transform").split(' ');
        for ( var i in props ) {
            var prop = props[i];
            if ( !$.contains(prop, "-") && mStyle[prop] !== undefined ) {
                return false;
            }
        }
        return true;
    }();

$.widget( "ui.iviewer", $.ui.mouse, {
    widgetEventPrefix: "iviewer",
    options : {
        /**
        * start zoom value for image, not used now
        * may be equal to "fit" to fit image into container or scale in %
        **/
        zoom: "fit",
        /**
        * base value to scale image
        **/
        zoom_base: 100,
        /**
        * maximum zoom
        **/
        zoom_max: 800,
        /**
        * minimum zoom
        **/
        zoom_min: 25,
        /**
        * base of rate multiplier.
        * zoom is calculated by formula: zoom_base * zoom_delta^rate
        **/
        zoom_delta: 1.4,
        /**
        * whether the zoom should be animated.
        */
        zoom_animation: true,
        /**
        * if true plugin doesn't add its own controls
        **/
        ui_disabled: false,
        /**
         * If false mousewheel will be disabled
         */
        mousewheel: true,
        /**
        * if false, plugin doesn't bind resize event on window and this must
        * be handled manually
        **/
        update_on_resize: true,
        /**
        * event is triggered when zoom value is changed
        * @param int new zoom value
        * @return boolean if false zoom action is aborted
        **/
        onZoom: jQuery.noop,
        /**
        * event is triggered when zoom value is changed after image is set to the new dimensions
        * @param int new zoom value
        * @return boolean if false zoom action is aborted
        **/
        onAfterZoom: jQuery.noop,
        /**
        * event is fired on drag begin
        * @param object coords mouse coordinates on the image
        * @return boolean if false is returned, drag action is aborted
        **/
        onStartDrag: jQuery.noop,
        /**
        * event is fired on drag action
        * @param object coords mouse coordinates on the image
        **/
        onDrag: jQuery.noop,
        /**
        * event is fired on drag stop
        * @param object coords mouse coordinates on the image
        **/
        onStopDrag: jQuery.noop,
        /**
        * event is fired when mouse moves over image
        * @param object coords mouse coordinates on the image
        **/
        onMouseMove: jQuery.noop,
        /**
        * mouse click event
        * @param object coords mouse coordinates on the image
        **/
        onClick: jQuery.noop,
        /**
        * event is fired when image starts to load
        */
        onStartLoad: null,
        /**
        * event is fired, when image is loaded and initially positioned
        */
        onFinishLoad: null,
        /**
        * event is fired when image load error occurs
        */
        onErrorLoad: null
    },

    _create: function() {
        var me = this;

        //drag variables
        this.dx = 0;
        this.dy = 0;

        /* object containing actual information about image
        *   @img_object.object - jquery img object
        *   @img_object.orig_{width|height} - original dimensions
        *   @img_object.display_{width|height} - actual dimensions
        */
        this.img_object = {};

        this.zoom_object = {}; //object to show zoom status

        this._angle = 0;

        this.current_zoom = this.options.zoom;

        if(this.options.src === null){
            return;
        }

        this.container = this.element;

        this._updateContainerInfo();

        //init container
        this.container.css("overflow","hidden");

        if (this.options.update_on_resize == true) {
            $(window).resize(function() {
                me.update();
            });
        }

        this.img_object = new $.ui.iviewer.ImageObject(this.options.zoom_animation);

        if (this.options.mousewheel) {
            this.container.bind('mousewheel.iviewer', function(ev, delta)
                {
                    //this event is there instead of containing div, because
                    //at opera it triggers many times on div
                    var zoom = (delta > 0)?1:-1,
                        container_offset = me.container.offset(),
                        mouse_pos = {
                            //jquery.mousewheel 3.1.0 uses strange MozMousePixelScroll event
                            //which is not being fixed by jQuery.Event
                            x: (ev.pageX || ev.originalEvent.pageX) - container_offset.left,
                            y: (ev.pageY || ev.originalEvent.pageX) - container_offset.top
                        };

                    me.zoom_by(zoom, mouse_pos);
                    return false;
                });

            if (gesturesSupport) {
                var gestureThrottle = +new Date();
                var originalScale, originalCenter;
                this.img_object.object()
                    // .bind('gesturestart', function(ev) {
                    .bind('touchstart', function(ev) {
                        originalScale = me.current_zoom;
                        var touches = ev.originalEvent.touches,
                            container_offset;
                        if (touches.length == 2) {
                            container_offset = me.container.offset();
                            originalCenter = {
                                x: (touches[0].pageX + touches[1].pageX) / 2  - container_offset.left,
                                y: (touches[0].pageY + touches[1].pageY) / 2 - container_offset.top
                            };
                        } else {
                            originalCenter = null;
                        }
                    }).bind('gesturechange', function(ev) {
                        //do not want to import throttle function from underscore
                        var d = +new Date();
                        if ((d - gestureThrottle) < 50) { return; }
                        gestureThrottle = d;
                        var zoom = originalScale * ev.originalEvent.scale;
                        me.set_zoom(zoom, originalCenter);
                        ev.preventDefault();
                    }).bind('gestureend', function(ev) {
                        originalCenter = null;
                    });
            }
        }

        //init object
        this.img_object.object()
            //bind mouse events
            .click(function(e){return me._click(e)})
                .prependTo(this.container);

        this.container.bind('mousemove', function(ev) { me._handleMouseMove(ev); });

        this.loadImage(this.options.src);

        if(!this.options.ui_disabled)
        {
            this.createui();
        }

        this._mouseInit();
    },

    destroy: function() {
        $.Widget.prototype.destroy.call( this );
        this._mouseDestroy();
        this.img_object.object().remove();
        this.container.off('.iviewer');
        this.container.css('overflow', ''); //cleanup styles on destroy
    },

    _updateContainerInfo: function()
    {
        this.options.height = this.container.height();
        this.options.width = this.container.width();
    },

    update: function()
    {
        this._updateContainerInfo()
        this.setCoords(this.img_object.x(), this.img_object.y());
    },

    loadImage: function( src )
    {
        this.current_zoom = this.options.zoom;
        var me = this;

        this._trigger('onStartLoad', 0, src);

        this.container.addClass("iviewer_loading");
        this.img_object.load(src, function() {
            me._imageLoaded(src);
        }, function() {
            me._trigger("onErrorLoad", 0, src);
        });
    },

    _imageLoaded: function(src) {
        this.container.removeClass("iviewer_loading");
        this.container.addClass("iviewer_cursor");

        if(this.options.zoom == "fit"){
            this.fit(true);
        }
        else {
            this.set_zoom(this.options.zoom, true);
        }

        this._trigger('onFinishLoad', 0, src);
    },

    /**
    * fits image in the container
    *
    * @param {boolean} skip_animation
    **/
    fit: function(skip_animation)
    {
        var aspect_ratio = this.img_object.orig_width() / this.img_object.orig_height();
        var window_ratio = this.options.width /  this.options.height;
        var choose_left = (aspect_ratio > window_ratio);
        var new_zoom = 0;

        if(choose_left){
            new_zoom = this.options.width / this.img_object.orig_width() * 100;
        }
        else {
            new_zoom = this.options.height / this.img_object.orig_height() * 100;
        }

      this.set_zoom(new_zoom, skip_animation);
    },

    /**
    * center image in container
    **/
    center: function()
    {
        this.setCoords(-Math.round((this.img_object.display_width() - this.options.width)/2),
                -Math.round((this.img_object.display_height() - this.options.height)/2));
    },

    /**
    *   move a point in container to the center of display area
    *   @param x a point in container
    *   @param y a point in container
    **/
    moveTo: function(x, y)
    {
        var dx = x-Math.round(this.options.width/2);
        var dy = y-Math.round(this.options.height/2);

        var new_x = this.img_object.x() - dx;
        var new_y = this.img_object.y() - dy;

        this.setCoords(new_x, new_y);
    },

    /**
     * Get container offset object.
     */
    getContainerOffset: function() {
        return jQuery.extend({}, this.container.offset());
    },

    /**
    * set coordinates of upper left corner of image object
    **/
    setCoords: function(x,y)
    {
        //do nothing while image is being loaded
        if(!this.img_object.loaded()) { return; }

        var coords = this._correctCoords(x,y);
        this.img_object.x(coords.x);
        this.img_object.y(coords.y);
    },

    _correctCoords: function( x, y )
    {
        x = parseInt(x, 10);
        y = parseInt(y, 10);

        //check new coordinates to be correct (to be in rect)
        if(y > 0){
            y = 0;
        }
        if(x > 0){
            x = 0;
        }
        if(y + this.img_object.display_height() < this.options.height){
            y = this.options.height - this.img_object.display_height();
        }
        if(x + this.img_object.display_width() < this.options.width){
            x = this.options.width - this.img_object.display_width();
        }
        if(this.img_object.display_width() <= this.options.width){
            x = -(this.img_object.display_width() - this.options.width)/2;
        }
        if(this.img_object.display_height() <= this.options.height){
            y = -(this.img_object.display_height() - this.options.height)/2;
        }

        return { x: x, y:y };
    },


    /**
    * convert coordinates on the container to the coordinates on the image (in original size)
    *
    * @return object with fields x,y according to coordinates or false
    * if initial coords are not inside image
    **/
    containerToImage : function (x,y)
    {
        var coords = { x : x - this.img_object.x(),
                 y :  y - this.img_object.y()
        };

        coords = this.img_object.toOriginalCoords(coords);

        return { x :  util.descaleValue(coords.x, this.current_zoom),
                 y :  util.descaleValue(coords.y, this.current_zoom)
        };
    },

    /**
    * convert coordinates on the image (in original size, and zero angle) to the coordinates on the container
    *
    * @return object with fields x,y according to coordinates
    **/
    imageToContainer : function (x,y)
    {
        var coords = {
                x : util.scaleValue(x, this.current_zoom),
                y : util.scaleValue(y, this.current_zoom)
            };

        return this.img_object.toRealCoords(coords);
    },

    /**
    * get mouse coordinates on the image
    * @param e - object containing pageX and pageY fields, e.g. mouse event object
    *
    * @return object with fields x,y according to coordinates or false
    * if initial coords are not inside image
    **/
    _getMouseCoords : function(e)
    {
        var containerOffset = this.container.offset();
            coords = this.containerToImage(e.pageX - containerOffset.left, e.pageY - containerOffset.top);

        return coords;
    },

    /**
    * set image scale to the new_zoom
    *
    * @param {number} new_zoom image scale in %
    * @param {boolean} skip_animation
    * @param {x: number, y: number} Coordinates of point the should not be moved on zoom. The default is the center of image.
    **/
    set_zoom: function(new_zoom, skip_animation, zoom_center)
    {
        if (this._trigger('onZoom', 0, new_zoom) == false) {
            return;
        }

        //do nothing while image is being loaded
        if(!this.img_object.loaded()) { return; }

        zoom_center = zoom_center || {
            x: Math.round(this.options.width/2),
            y: Math.round(this.options.height/2)
        }

        if(new_zoom <  this.options.zoom_min)
        {
            new_zoom = this.options.zoom_min;
        }
        else if(new_zoom > this.options.zoom_max)
        {
            new_zoom = this.options.zoom_max;
        }

        /* we fake these values to make fit zoom properly work */
        if(this.current_zoom == "fit")
        {
            var old_x = zoom_center.x + Math.round(this.img_object.orig_width()/2);
            var old_y = zoom_center.y + Math.round(this.img_object.orig_height()/2);
            this.current_zoom = 100;
        }
        else {
            var old_x = -this.img_object.x() + zoom_center.x;
            var old_y = -this.img_object.y() + zoom_center.y
        }

        var new_width = util.scaleValue(this.img_object.orig_width(), new_zoom);
        var new_height = util.scaleValue(this.img_object.orig_height(), new_zoom);
        var new_x = util.scaleValue( util.descaleValue(old_x, this.current_zoom), new_zoom);
        var new_y = util.scaleValue( util.descaleValue(old_y, this.current_zoom), new_zoom);

        new_x = zoom_center.x - new_x;
        new_y = zoom_center.y - new_y;

        new_width = Math.floor(new_width);
        new_height = Math.floor(new_height);
        new_x = Math.floor(new_x);
        new_y = Math.floor(new_y);

        this.img_object.display_width(new_width);
        this.img_object.display_height(new_height);

        var coords = this._correctCoords( new_x, new_y ),
            self = this;

        this.img_object.setImageProps(new_width, new_height, coords.x, coords.y,
                                        skip_animation, function() {
            self._trigger('onAfterZoom', 0, new_zoom );
        });
        this.current_zoom = new_zoom;

        this.update_status();
    },

    /**
    * changes zoom scale by delta
    * zoom is calculated by formula: zoom_base * zoom_delta^rate
    * @param Integer delta number to add to the current multiplier rate number
    * @param {x: number, y: number=} Coordinates of point the should not be moved on zoom.
    **/
    zoom_by: function(delta, zoom_center)
    {
        var closest_rate = this.find_closest_zoom_rate(this.current_zoom);

        var next_rate = closest_rate + delta;
        var next_zoom = this.options.zoom_base * Math.pow(this.options.zoom_delta, next_rate)
        if(delta > 0 && next_zoom < this.current_zoom)
        {
            next_zoom *= this.options.zoom_delta;
        }

        if(delta < 0 && next_zoom > this.current_zoom)
        {
            next_zoom /= this.options.zoom_delta;
        }

        this.set_zoom(next_zoom, undefined, zoom_center);
    },

    /**
    * Rotate image
    * @param {num} deg Degrees amount to rotate. Positive values rotate image clockwise.
    *     Currently 0, 90, 180, 270 and -90, -180, -270 values are supported
    *
    * @param {boolean} abs If the flag is true if, the deg parameter will be considered as
    *     a absolute value and relative otherwise.
    * @return {num|null} Method will return current image angle if called without any arguments.
    **/
    angle: function(deg, abs) {
        if (arguments.length === 0) { return this.img_object.angle(); }

        if (deg < -270 || deg > 270 || deg % 90 !== 0) { return; }
        if (!abs) { deg += this.img_object.angle(); }
        if (deg < 0) { deg += 360; }
        if (deg >= 360) { deg -= 360; }

        if (deg === this.img_object.angle()) { return; }

        this.img_object.angle(deg);
        //the rotate behavior is different in all editors. For now we  just center the
        //image. However, it will be better to try to keep the position.
        this.center();
        this._trigger('angle', 0, { angle: this.img_object.angle() });
    },

    /**
    * finds closest multiplier rate for value
    * basing on zoom_base and zoom_delta values from settings
    * @param Number value zoom value to examine
    **/
    find_closest_zoom_rate: function(value)
    {
        if(value == this.options.zoom_base)
        {
            return 0;
        }

        function div(val1,val2) { return val1 / val2 };
        function mul(val1,val2) { return val1 * val2 };

        var func = (value > this.options.zoom_base)?mul:div;
        var sgn = (value > this.options.zoom_base)?1:-1;

        var mltplr = this.options.zoom_delta;
        var rate = 1;

        while(Math.abs(func(this.options.zoom_base, Math.pow(mltplr,rate)) - value) >
              Math.abs(func(this.options.zoom_base, Math.pow(mltplr,rate+1)) - value))
        {
            rate++;
        }

        return sgn * rate;
    },

    /* update scale info in the container */
    update_status: function()
    {
        if(!this.options.ui_disabled)
        {
            var percent = Math.round(100*this.img_object.display_height()/this.img_object.orig_height());
            if(percent)
            {
                this.zoom_object.html(percent + "%");
            }
        }
    },

    /**
     * Get some information about the image.
     *     Currently orig_(width|height), display_(width|height), angle, zoom and src params are supported.
     *
     *  @param {string} parameter to check
     *  @param {boolean} withoutRotation if param is orig_width or orig_height and this flag is set to true,
     *      method will return original image width without considering rotation.
     *
     */
    info: function(param, withoutRotation) {
        if (!param) { return; }

        switch (param) {
            case 'orig_width':
            case 'orig_height':
                if (withoutRotation) {
                    return (this.img_object.angle() % 180 === 0 ? this.img_object[param]() :
                            param === 'orig_width' ? this.img_object.orig_height() :
                                                        this.img_object.orig_width());
                } else {
                    return this.img_object[param]();
                }
            case 'display_width':
            case 'display_height':
            case 'angle':
                return this.img_object[param]();
            case 'zoom':
                return this.current_zoom;
            case 'src':
                return this.img_object.object().attr('src');
            case 'coords':
                return {
                    x: this.img_object.x(),
                    y: this.img_object.y()
                };
        }
    },

    /**
    *   callback for handling mousdown event to start dragging image
    **/
    _mouseStart: function( e )
    {
        $.ui.mouse.prototype._mouseStart.call(this, e);
        if (this._trigger('onStartDrag', 0, this._getMouseCoords(e)) === false) {
            return false;
        }

        /* start drag event*/
        this.container.addClass("iviewer_drag_cursor");

        //#10: fix movement quirks for ipad
        this._dragInitialized = !(e.originalEvent.changedTouches && e.originalEvent.changedTouches.length==1);

        this.dx = e.pageX - this.img_object.x();
        this.dy = e.pageY - this.img_object.y();
        return true;
    },

    _mouseCapture: function( e ) {
        return true;
    },

    /**
     * Handle mouse move if needed. User can avoid using this callback, because
     *    he can get the same information through public methods.
     *  @param {jQuery.Event} e
     */
    _handleMouseMove: function(e) {
        this._trigger('onMouseMove', e, this._getMouseCoords(e));
    },

    /**
    *   callback for handling mousemove event to drag image
    **/
    _mouseDrag: function(e)
    {
        $.ui.mouse.prototype._mouseDrag.call(this, e);

        //#10: imitate mouseStart, because we can get here without it on iPad for some reason
        if (!this._dragInitialized) {
            this.dx = e.pageX - this.img_object.x();
            this.dy = e.pageY - this.img_object.y();
            this._dragInitialized = true;
        }

        var ltop =  e.pageY - this.dy;
        var lleft = e.pageX - this.dx;

        this.setCoords(lleft, ltop);
        this._trigger('onDrag', e, this._getMouseCoords(e));
        return false;
    },

    /**
    *   callback for handling stop drag
    **/
    _mouseStop: function(e)
    {
        $.ui.mouse.prototype._mouseStop.call(this, e);
        this.container.removeClass("iviewer_drag_cursor");
        this._trigger('onStopDrag', 0, this._getMouseCoords(e));
    },

    _click: function(e)
    {
        this._trigger('onClick', 0, this._getMouseCoords(e));
    },

    /**
    *   create zoom buttons info box
    **/
    createui: function()
    {
        var me=this;

        $("<div>", { 'class': "iviewer_zoom_in iviewer_common iviewer_button"})
                    .bind('mousedown touchstart',function(){me.zoom_by(1); return false;})
                    .appendTo(this.container);

        $("<div>", { 'class': "iviewer_zoom_out iviewer_common iviewer_button"})
                    .bind('mousedown touchstart',function(){me.zoom_by(- 1); return false;})
                    .appendTo(this.container);

        $("<div>", { 'class': "iviewer_zoom_zero iviewer_common iviewer_button"})
                    .bind('mousedown touchstart',function(){me.set_zoom(100); return false;})
                    .appendTo(this.container);

        $("<div>", { 'class': "iviewer_zoom_fit iviewer_common iviewer_button"})
                    .bind('mousedown touchstart',function(){me.fit(this); return false;})
                    .appendTo(this.container);

        this.zoom_object = $("<div>").addClass("iviewer_zoom_status iviewer_common")
                                    .appendTo(this.container);

        $("<div>", { 'class': "iviewer_rotate_left iviewer_common iviewer_button"})
                    .bind('mousedown touchstart',function(){me.angle(-90); return false;})
                    .appendTo(this.container);

        $("<div>", { 'class': "iviewer_rotate_right iviewer_common iviewer_button" })
                    .bind('mousedown touchstart',function(){me.angle(90); return false;})
                    .appendTo(this.container);

        this.update_status(); //initial status update
    }

} );

/**
 * @class $.ui.iviewer.ImageObject Class represents image and provides public api without
 *     extending image prototype.
 * @constructor
 * @param {boolean} do_anim Do we want to animate image on dimension changes?
 */
$.ui.iviewer.ImageObject = function(do_anim) {
    this._img = $("<img>")
            //this is needed, because chromium sets them auto otherwise
            .css({ position: "absolute", top :"0px", left: "0px"});

    this._loaded = false;
    this._swapDimensions = false;
    this._do_anim = do_anim || false;
    this.x(0, true);
    this.y(0, true);
    this.angle(0);
};


/** @lends $.ui.iviewer.ImageObject.prototype */
(function() {
    /**
     * Restore initial object state.
     *
     * @param {number} w Image width.
     * @param {number} h Image height.
     */
    this._reset = function(w, h) {
        this._angle = 0;
        this._swapDimensions = false;
        this.x(0);
        this.y(0);

        this.orig_width(w);
        this.orig_height(h);
        this.display_width(w);
        this.display_height(h);
    };

    /**
     * Check if image is loaded.
     *
     * @return {boolean}
     */
    this.loaded = function() { return this._loaded; };

    /**
     * Load image.
     *
     * @param {string} src Image url.
     * @param {Function=} loaded Function will be called on image load.
     */
    this.load = function(src, loaded, error) {
        var self = this;

        loaded = loaded || jQuery.noop;
        this._loaded = false;

        //If we assign new image url to the this._img IE9 fires onload event and image width and
        //height are set to zero. So, we create another image object and load image through it.
        var img = new Image();
        img.onload = function() {
            self._loaded = true;
            self._reset(this.width, this.height);

            self._img
                .removeAttr("width")
                .removeAttr("height")
                .removeAttr("style")
                //max-width is reset, because plugin breaks in the twitter bootstrap otherwise
                .css({ position: "absolute", top :"0px", left: "0px", maxWidth: "none"})

            self._img[0].src = src;
            loaded();
        };

        img.onerror = error;

        //we need this because sometimes internet explorer 8 fires onload event
        //right after assignment (synchronously)
        setTimeout(function() {
            img.src = src;
        }, 0);

        this.angle(0);
    };

    this._dimension = function(prefix, name) {
        var horiz = '_' + prefix + '_' + name,
            vert = '_' + prefix + '_' + (name === 'height' ? 'width' : 'height');
        return setter(function(val) {
                this[this._swapDimensions ? horiz: vert] = val;
            },
            function() {
                return this[this._swapDimensions ? horiz: vert];
            });
    };

    /**
     * Getters and setter for common image dimensions.
     *    display_ means real image tag dimensions
     *    orig_ means physical image dimensions.
     *  Note, that dimensions are swapped if image is rotated. It necessary,
     *  because as little as possible code should know about rotation.
     */
    this.display_width = this._dimension('display', 'width'),
    this.display_height = this._dimension('display', 'height'),
    this.display_diff = function() { return Math.floor( this.display_width() - this.display_height() ) };
    this.orig_width = this._dimension('orig', 'width'),
    this.orig_height = this._dimension('orig', 'height'),

    /**
     * Setter for  X coordinate. If image is rotated we need to additionaly shift an
     *     image to map image coordinate to the visual position.
     *
     * @param {number} val Coordinate value.
     * @param {boolean} skipCss If true, we only set the value and do not touch the dom.
     */
    this.x = setter(function(val, skipCss) {
            this._x = val;
            if (!skipCss) {
                this._finishAnimation();
                this._img.css("left",this._x + (this._swapDimensions ? this.display_diff() / 2 : 0) + "px");
            }
        },
        function() {
            return this._x;
        });

    /**
     * Setter for  Y coordinate. If image is rotated we need to additionaly shift an
     *     image to map image coordinate to the visual position.
     *
     * @param {number} val Coordinate value.
     * @param {boolean} skipCss If true, we only set the value and do not touch the dom.
     */
    this.y = setter(function(val, skipCss) {
            this._y = val;
            if (!skipCss) {
                this._finishAnimation();
                this._img.css("top",this._y - (this._swapDimensions ? this.display_diff() / 2 : 0) + "px");
            }
        },
       function() {
            return this._y;
       });

    /**
     * Perform image rotation.
     *
     * @param {number} deg Absolute image angle. The method will work with values 0, 90, 180, 270 degrees.
     */
    this.angle = setter(function(deg) {
            var prevSwap = this._swapDimensions;

            this._angle = deg;
            this._swapDimensions = deg % 180 !== 0;

            if (prevSwap !== this._swapDimensions) {
                var verticalMod = this._swapDimensions ? -1 : 1;
                this.x(this.x() - verticalMod * this.display_diff() / 2, true);
                this.y(this.y() + verticalMod * this.display_diff() / 2, true);
            };

            var cssVal = 'rotate(' + deg + 'deg)',
                img = this._img;

            jQuery.each(['', '-webkit-', '-moz-', '-o-', '-ms-'], function(i, prefix) {
                img.css(prefix + 'transform', cssVal);
            });

            if (useIeTransforms) {
                jQuery.each(['-ms-', ''], function(i, prefix) {
                    img.css(prefix + 'filter', ieTransforms[deg].filter);
                });

                img.css({
                    marginLeft: ieTransforms[deg].marginLeft * this.display_diff() / 2,
                    marginTop: ieTransforms[deg].marginTop * this.display_diff() / 2
                });
            }
        },
       function() { return this._angle; });

    /**
     * Map point in the container coordinates to the point in image coordinates.
     *     You will get coordinates of point on image with respect to rotation,
     *     but will be set as if image was not rotated.
     *     So, if image was rotated 90 degrees, it's (0,0) point will be on the
     *     top right corner.
     *
     * @param {{x: number, y: number}} point Point in container coordinates.
     * @return  {{x: number, y: number}}
     */
    this.toOriginalCoords = function(point) {
        switch (this.angle()) {
            case 0: return { x: point.x, y: point.y }
            case 90: return { x: point.y, y: this.display_width() - point.x }
            case 180: return { x: this.display_width() - point.x, y: this.display_height() - point.y }
            case 270: return { x: this.display_height() - point.y, y: point.x }
        }
    };

    /**
     * Map point in the image coordinates to the point in container coordinates.
     *     You will get coordinates of point on container with respect to rotation.
     *     Note, if image was rotated 90 degrees, it's (0,0) point will be on the
     *     top right corner.
     *
     * @param {{x: number, y: number}} point Point in container coordinates.
     * @return  {{x: number, y: number}}
     */
    this.toRealCoords = function(point) {
        switch (this.angle()) {
            case 0: return { x: this.x() + point.x, y: this.y() + point.y }
            case 90: return { x: this.x() + this.display_width() - point.y, y: this.y() + point.x}
            case 180: return { x: this.x() + this.display_width() - point.x, y: this.y() + this.display_height() - point.y}
            case 270: return { x: this.x() + point.y, y: this.y() + this.display_height() - point.x}
        }
    };

    /**
     * @return {jQuery} Return image node. this is needed to add event handlers.
     */
    this.object = setter(jQuery.noop,
                           function() { return this._img; });

    /**
     * Change image properties.
     *
     * @param {number} disp_w Display width;
     * @param {number} disp_h Display height;
     * @param {number} x
     * @param {number} y
     * @param {boolean} skip_animation If true, the animation will be skiped despite the
     *     value set in constructor.
     * @param {Function=} complete Call back will be fired when zoom will be complete.
     */
    this.setImageProps = function(disp_w, disp_h, x, y, skip_animation, complete) {
        complete = complete || jQuery.noop;

        this.display_width(disp_w);
        this.display_height(disp_h);
        this.x(x, true);
        this.y(y, true);

        var w = this._swapDimensions ? disp_h : disp_w;
        var h = this._swapDimensions ? disp_w : disp_h;

        var params = {
            width: w,
            height: h,
            top: y - (this._swapDimensions ? this.display_diff() / 2 : 0) + "px",
            left: x + (this._swapDimensions ? this.display_diff() / 2 : 0) + "px"
        };

        if (useIeTransforms) {
            jQuery.extend(params, {
                marginLeft: ieTransforms[this.angle()].marginLeft * this.display_diff() / 2,
                marginTop: ieTransforms[this.angle()].marginTop * this.display_diff() / 2
            });
        }

        var swapDims = this._swapDimensions,
            img = this._img;

        //here we come: another IE oddness. If image is rotated 90 degrees with a filter, than
        //width and height getters return real width and height of rotated image. The bad news
        //is that to set height you need to set a width and vice versa. Fuck IE.
        //So, in this case we have to animate width and height manually.
        if(useIeTransforms && swapDims) {
            var ieh = this._img.width(),
                iew = this._img.height(),
                iedh = params.height - ieh;
                iedw = params.width - iew;

            delete params.width;
            delete params.height;
        }

        if (this._do_anim && !skip_animation) {
            this._img.stop(true)
                .animate(params, {
                    duration: 200,
                    complete: complete,
                    step: function(now, fx) {
                        if(useIeTransforms && swapDims && (fx.prop === 'top')) {
                            var percent = (now - fx.start) / (fx.end - fx.start);

                            img.height(ieh + iedh * percent);
                            img.width(iew + iedw * percent);
                            img.css('top', now);
                        }
                    }
                });
        } else {
            this._img.css(params);
            setTimeout(complete, 0); //both if branches should behave equally.
        }
    };

    //if we set image coordinates we need to be sure that no animation is active atm
    this._finishAnimation = function() {
      this._img.stop(true, true);
    }

}).apply($.ui.iviewer.ImageObject.prototype);



var util = {
    scaleValue: function(value, toZoom)
    {
        return value * toZoom / 100;
    },

    descaleValue: function(value, fromZoom)
    {
        return value * 100 / fromZoom;
    }
};

 } )( jQuery, undefined );
$(document).ready(function() {
    function filterPath(string) {
        return string
            .replace(/^\//,'')
            .replace(/(index|default).[a-zA-Z]{3,4}$/,'')
            .replace(/\/$/,'');
    }
    var locationPath = filterPath(location.pathname);

    $('a[href*=#]').each(function() {
        var thisPath = filterPath(this.pathname) || locationPath;
        if (  locationPath == thisPath
            && (location.hostname == this.hostname || !this.hostname)
            && this.hash.replace(/#/,'') ) {
            var $target = $(this.hash), target = this.hash;
            if (target) {
                $(this).click(function(event) {
                    if (!$(this.hash).offset()) {
                        return;
                    }

                    event.preventDefault();
                    position = $(this.hash).offset().top;

                    $('html,body').animate({scrollTop: position}, 400, function() {
                        location.hash = target;
                    });
                });
            }
        }
    });
});
/*	
 *	jQuery dotdotdot 1.5.9
 *	
 *	Copyright (c) 2013 Fred Heusschen
 *	www.frebsite.nl
 *
 *	Plugin website:
 *	dotdotdot.frebsite.nl
 *
 *	Dual licensed under the MIT and GPL licenses.
 *	http://en.wikipedia.org/wiki/MIT_License
 *	http://en.wikipedia.org/wiki/GNU_General_Public_License
 */

(function(a){function c(a,b,c){var d=a.children(),e=!1;a.empty();for(var g=0,h=d.length;h>g;g++){var i=d.eq(g);if(a.append(i),c&&a.append(c),f(a,b)){i.remove(),e=!0;break}c&&c.remove()}return e}function d(b,c,g,h,i){var j=b.contents(),k=!1;b.empty();for(var l="table, thead, tbody, tfoot, tr, col, colgroup, object, embed, param, ol, ul, dl, select, optgroup, option, textarea, script, style",m=0,n=j.length;n>m&&!k;m++){var o=j[m],p=a(o);void 0!==o&&(b.append(p),i&&b[b.is(l)?"after":"append"](i),3==o.nodeType?f(g,h)&&(k=e(p,c,g,h,i)):k=d(p,c,g,h,i),k||i&&i.remove())}return k}function e(a,b,c,d,h){var k=!1,l=a[0];if(l===void 0)return!1;for(var m="letter"==d.wrap?"":" ",n=j(l).split(m),o=-1,p=-1,q=0,r=n.length-1;r>=q;){var s=Math.floor((q+r)/2);if(s==p)break;p=s,i(l,n.slice(0,p+1).join(m)+d.ellipsis),f(c,d)?r=p:(o=p,q=p)}if(-1==o||1==n.length&&0==n[0].length){var u=a.parent();a.remove();var v=h?h.length:0;if(u.contents().size()>v){var w=u.contents().eq(-1-v);k=e(w,b,c,d,h)}else{var x=u.prev(),l=x.contents().eq(-1)[0];if(l!==void 0){var t=g(j(l),d);i(l,t),h&&x.append(h),u.remove(),k=!0}}}else{var t=g(n.slice(0,o+1).join(m),d);k=!0,i(l,t)}return k}function f(a,b){return a.innerHeight()>b.maxHeight}function g(b,c){for(;a.inArray(b.slice(-1),c.lastCharacter.remove)>-1;)b=b.slice(0,-1);return 0>a.inArray(b.slice(-1),c.lastCharacter.noEllipsis)&&(b+=c.ellipsis),b}function h(a){return{width:a.innerWidth(),height:a.innerHeight()}}function i(a,b){a.innerText?a.innerText=b:a.nodeValue?a.nodeValue=b:a.textContent&&(a.textContent=b)}function j(a){return a.innerText?a.innerText:a.nodeValue?a.nodeValue:a.textContent?a.textContent:""}function k(b,c){return b===void 0?!1:b?"string"==typeof b?(b=a(b,c),b.length?b:!1):"object"==typeof b?b.jquery===void 0?!1:b:!1:!1}function l(a){for(var b=a.innerHeight(),c=["paddingTop","paddingBottom"],d=0,e=c.length;e>d;d++){var f=parseInt(a.css(c[d]),10);isNaN(f)&&(f=0),b-=f}return b}function m(a,b){return a?(b="string"==typeof b?"dotdotdot: "+b:["dotdotdot:",b],window.console!==void 0&&window.console.log!==void 0&&window.console.log(b),!1):!1}if(!a.fn.dotdotdot){a.fn.dotdotdot=function(e){if(0==this.length)return e&&e.debug===!1||m(!0,'No element found for "'+this.selector+'".'),this;if(this.length>1)return this.each(function(){a(this).dotdotdot(e)});var g=this;g.data("dotdotdot")&&g.trigger("destroy.dot"),g.data("dotdotdot-style",g.attr("style")),g.css("word-wrap","break-word"),g.bind_events=function(){return g.bind("update.dot",function(b,e){b.preventDefault(),b.stopPropagation(),j.maxHeight="number"==typeof j.height?j.height:l(g),j.maxHeight+=j.tolerance,e!==void 0&&(("string"==typeof e||e instanceof HTMLElement)&&(e=a("<div />").append(e).contents()),e instanceof a&&(i=e)),q=g.wrapInner('<div class="dotdotdot" />').children(),q.empty().append(i.clone(!0)).css({height:"auto",width:"auto",border:"none",padding:0,margin:0});var h=!1,k=!1;return n.afterElement&&(h=n.afterElement.clone(!0),n.afterElement.remove()),f(q,j)&&(k="children"==j.wrap?c(q,j,h):d(q,g,q,j,h)),q.replaceWith(q.contents()),q=null,a.isFunction(j.callback)&&j.callback.call(g[0],k,i),n.isTruncated=k,k}).bind("isTruncated.dot",function(a,b){return a.preventDefault(),a.stopPropagation(),"function"==typeof b&&b.call(g[0],n.isTruncated),n.isTruncated}).bind("originalContent.dot",function(a,b){return a.preventDefault(),a.stopPropagation(),"function"==typeof b&&b.call(g[0],i),i}).bind("destroy.dot",function(a){a.preventDefault(),a.stopPropagation(),g.unwatch().unbind_events().empty().append(i).attr("style",g.data("dotdotdot-style")).data("dotdotdot",!1)}),g},g.unbind_events=function(){return g.unbind(".dot"),g},g.watch=function(){if(g.unwatch(),"window"==j.watch){var b=a(window),c=b.width(),d=b.height();b.bind("resize.dot"+n.dotId,function(){c==b.width()&&d==b.height()&&j.windowResizeFix||(c=b.width(),d=b.height(),p&&clearInterval(p),p=setTimeout(function(){g.trigger("update.dot")},10))})}else o=h(g),p=setInterval(function(){var a=h(g);(o.width!=a.width||o.height!=a.height)&&(g.trigger("update.dot"),o=h(g))},100);return g},g.unwatch=function(){return a(window).unbind("resize.dot"+n.dotId),p&&clearInterval(p),g};var i=g.contents(),j=a.extend(!0,{},a.fn.dotdotdot.defaults,e),n={},o={},p=null,q=null;return n.afterElement=k(j.after,g),n.isTruncated=!1,n.dotId=b++,g.data("dotdotdot",!0).bind_events().trigger("update.dot"),j.watch&&g.watch(),g},a.fn.dotdotdot.defaults={ellipsis:"... ",wrap:"word",lastCharacter:{remove:[" ",",",";",".","!","?"],noEllipsis:[]},tolerance:0,callback:null,after:null,height:null,watch:!1,windowResizeFix:!0,debug:!1};var b=1,n=a.fn.html;a.fn.html=function(a){return a!==void 0?this.data("dotdotdot")&&"function"!=typeof a?this.trigger("update",[a]):n.call(this,a):n.call(this)};var o=a.fn.text;a.fn.text=function(b){if(b!==void 0){if(this.data("dotdotdot")){var c=a("<div />");return c.text(b),b=c.html(),c.remove(),this.trigger("update",[b])}return o.call(this,b)}return o.call(this)}}})(jQuery);/**
 * Prism: Lightweight, robust, elegant syntax highlighting
 * MIT license http://www.opensource.org/licenses/mit-license.php/
 * @author Lea Verou http://lea.verou.me
 */(function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={util:{type:function(e){return Object.prototype.toString.call(e).match(/\[object (\w+)\]/)[1]},clone:function(e){var n=t.util.type(e);switch(n){case"Object":var r={};for(var i in e)e.hasOwnProperty(i)&&(r[i]=t.util.clone(e[i]));return r;case"Array":return e.slice()}return e}},languages:{extend:function(e,n){var r=t.util.clone(t.languages[e]);for(var i in n)r[i]=n[i];return r},insertBefore:function(e,n,r,i){i=i||t.languages;var s=i[e],o={};for(var u in s)if(s.hasOwnProperty(u)){if(u==n)for(var a in r)r.hasOwnProperty(a)&&(o[a]=r[a]);o[u]=s[u]}return i[e]=o},DFS:function(e,n){for(var r in e){n.call(e,r,e[r]);t.util.type(e)==="Object"&&t.languages.DFS(e[r],n)}}},highlightAll:function(e,n){var r=document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code');for(var i=0,s;s=r[i++];)t.highlightElement(s,e===!0,n)},highlightElement:function(r,i,s){var o,u,a=r;while(a&&!e.test(a.className))a=a.parentNode;if(a){o=(a.className.match(e)||[,""])[1];u=t.languages[o]}if(!u)return;r.className=r.className.replace(e,"").replace(/\s+/g," ")+" language-"+o;a=r.parentNode;/pre/i.test(a.nodeName)&&(a.className=a.className.replace(e,"").replace(/\s+/g," ")+" language-"+o);var f=r.textContent;if(!f)return;f=f.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/\u00a0/g," ");var l={element:r,language:o,grammar:u,code:f};t.hooks.run("before-highlight",l);if(i&&self.Worker){var c=new Worker(t.filename);c.onmessage=function(e){l.highlightedCode=n.stringify(JSON.parse(e.data),o);t.hooks.run("before-insert",l);l.element.innerHTML=l.highlightedCode;s&&s.call(l.element);t.hooks.run("after-highlight",l)};c.postMessage(JSON.stringify({language:l.language,code:l.code}))}else{l.highlightedCode=t.highlight(l.code,l.grammar,l.language);t.hooks.run("before-insert",l);l.element.innerHTML=l.highlightedCode;s&&s.call(r);t.hooks.run("after-highlight",l)}},highlight:function(e,r,i){return n.stringify(t.tokenize(e,r),i)},tokenize:function(e,n,r){var i=t.Token,s=[e],o=n.rest;if(o){for(var u in o)n[u]=o[u];delete n.rest}e:for(var u in n){if(!n.hasOwnProperty(u)||!n[u])continue;var a=n[u],f=a.inside,l=!!a.lookbehind,c=0;a=a.pattern||a;for(var h=0;h<s.length;h++){var p=s[h];if(s.length>e.length)break e;if(p instanceof i)continue;a.lastIndex=0;var d=a.exec(p);if(d){l&&(c=d[1].length);var v=d.index-1+c,d=d[0].slice(c),m=d.length,g=v+m,y=p.slice(0,v+1),b=p.slice(g+1),w=[h,1];y&&w.push(y);var E=new i(u,f?t.tokenize(d,f):d);w.push(E);b&&w.push(b);Array.prototype.splice.apply(s,w)}}}return s},hooks:{all:{},add:function(e,n){var r=t.hooks.all;r[e]=r[e]||[];r[e].push(n)},run:function(e,n){var r=t.hooks.all[e];if(!r||!r.length)return;for(var i=0,s;s=r[i++];)s(n)}}},n=t.Token=function(e,t){this.type=e;this.content=t};n.stringify=function(e,r,i){if(typeof e=="string")return e;if(Object.prototype.toString.call(e)=="[object Array]")return e.map(function(t){return n.stringify(t,r,e)}).join("");var s={type:e.type,content:n.stringify(e.content,r,i),tag:"span",classes:["token",e.type],attributes:{},language:r,parent:i};s.type=="comment"&&(s.attributes.spellcheck="true");t.hooks.run("wrap",s);var o="";for(var u in s.attributes)o+=u+'="'+(s.attributes[u]||"")+'"';return"<"+s.tag+' class="'+s.classes.join(" ")+'" '+o+">"+s.content+"</"+s.tag+">"};if(!self.document){self.addEventListener("message",function(e){var n=JSON.parse(e.data),r=n.language,i=n.code;self.postMessage(JSON.stringify(t.tokenize(i,t.languages[r])));self.close()},!1);return}var r=document.getElementsByTagName("script");r=r[r.length-1];if(r){t.filename=r.src;document.addEventListener&&!r.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)}})();;
Prism.languages.markup={comment:/&lt;!--[\w\W]*?-->/g,prolog:/&lt;\?.+?\?>/,doctype:/&lt;!DOCTYPE.+?>/,cdata:/&lt;!\[CDATA\[[\w\W]*?]]>/i,tag:{pattern:/&lt;\/?[\w:-]+\s*(?:\s+[\w:-]+(?:=(?:("|')(\\?[\w\W])*?\1|\w+))?\s*)*\/?>/gi,inside:{tag:{pattern:/^&lt;\/?[\w:-]+/i,inside:{punctuation:/^&lt;\/?/,namespace:/^[\w-]+?:/}},"attr-value":{pattern:/=(?:('|")[\w\W]*?(\1)|[^\s>]+)/gi,inside:{punctuation:/=|>|"/g}},punctuation:/\/?>/g,"attr-name":{pattern:/[\w:-]+/g,inside:{namespace:/^[\w-]+?:/}}}},entity:/&amp;#?[\da-z]{1,8};/gi};Prism.hooks.add("wrap",function(e){e.type==="entity"&&(e.attributes.title=e.content.replace(/&amp;/,"&"))});;
Prism.languages.css={comment:/\/\*[\w\W]*?\*\//g,atrule:{pattern:/@[\w-]+?.*?(;|(?=\s*{))/gi,inside:{punctuation:/[;:]/g}},url:/url\((["']?).*?\1\)/gi,selector:/[^\{\}\s][^\{\};]*(?=\s*\{)/g,property:/(\b|\B)[\w-]+(?=\s*:)/ig,string:/("|')(\\?.)*?\1/g,important:/\B!important\b/gi,ignore:/&(lt|gt|amp);/gi,punctuation:/[\{\};:]/g};Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{style:{pattern:/(&lt;|<)style[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/style(>|&gt;)/ig,inside:{tag:{pattern:/(&lt;|<)style[\w\W]*?(>|&gt;)|(&lt;|<)\/style(>|&gt;)/ig,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.css}}});;
Prism.languages.css.selector={pattern:/[^\{\}\s][^\{\}]*(?=\s*\{)/g,inside:{"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/g,"pseudo-class":/:[-\w]+(?:\(.*\))?/g,"class":/\.[-:\.\w]+/g,id:/#[-:\.\w]+/g}};Prism.languages.insertBefore("css","ignore",{hexcode:/#[\da-f]{3,6}/gi,entity:/\\[\da-f]{1,8}/gi,number:/[\d%\.]+/g,"function":/(attr|calc|cross-fade|cycle|element|hsla?|image|lang|linear-gradient|matrix3d|matrix|perspective|radial-gradient|repeating-linear-gradient|repeating-radial-gradient|rgba?|rotatex|rotatey|rotatez|rotate3d|rotate|scalex|scaley|scalez|scale3d|scale|skewx|skewy|skew|steps|translatex|translatey|translatez|translate3d|translate|url|var)/ig});;
Prism.languages.clike={comment:{pattern:/(^|[^\\])(\/\*[\w\W]*?\*\/|(^|[^:])\/\/.*?(\r?\n|$))/g,lookbehind:!0},string:/("|')(\\?.)*?\1/g,"class-name":{pattern:/((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/ig,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|catch|finally|null|break|continue)\b/g,"boolean":/\b(true|false)\b/g,"function":{pattern:/[a-z0-9_]+\(/ig,inside:{punctuation:/\(/}}, number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g,operator:/[-+]{1,2}|!|&lt;=?|>=?|={1,3}|(&amp;){1,2}|\|?\||\?|\*|\/|\~|\^|\%/g,ignore:/&(lt|gt|amp);/gi,punctuation:/[{}[\];(),.:]/g};;
Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(var|let|if|else|while|do|for|return|in|instanceof|function|new|with|typeof|try|catch|finally|null|break|continue)\b/g,number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?|NaN|-?Infinity)\b/g});Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g,lookbehind:!0}});Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/(&lt;|<)script[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/script(>|&gt;)/ig,inside:{tag:{pattern:/(&lt;|<)script[\w\W]*?(>|&gt;)|(&lt;|<)\/script(>|&gt;)/ig,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.javascript}}});;
Prism.languages.php=Prism.languages.extend("clike",{keyword:/\b(and|or|xor|array|as|break|case|cfunction|class|const|continue|declare|default|die|do|else|elseif|enddeclare|endfor|endforeach|endif|endswitch|endwhile|extends|for|foreach|function|include|include_once|global|if|new|return|static|switch|use|require|require_once|var|while|abstract|interface|public|implements|extends|private|protected|parent|static|throw|null|echo|print|trait|namespace|use|final|yield|goto|instanceof|finally|try|catch)\b/ig, constant:/\b[A-Z0-9_]{2,}\b/g});Prism.languages.insertBefore("php","keyword",{delimiter:/(\?>|&lt;\?php|&lt;\?)/ig,variable:/(\$\w+)\b/ig,"package":{pattern:/(\\|namespace\s+|use\s+)[\w\\]+/g,lookbehind:!0,inside:{punctuation:/\\/}}});Prism.languages.insertBefore("php","operator",{property:{pattern:/(->)[\w]+/g,lookbehind:!0}}); Prism.languages.markup&&(Prism.hooks.add("before-highlight",function(a){"php"===a.language&&(a.tokenStack=[],a.code=a.code.replace(/(?:&lt;\?php|&lt;\?|<\?php|<\?)[\w\W]*?(?:\?&gt;|\?>)/ig,function(b){a.tokenStack.push(b);return"{{{PHP"+a.tokenStack.length+"}}}"}))}),Prism.hooks.add("after-highlight",function(a){if("php"===a.language){for(var b=0,c;c=a.tokenStack[b];b++)a.highlightedCode=a.highlightedCode.replace("{{{PHP"+(b+1)+"}}}",Prism.highlight(c,a.grammar,"php"));a.element.innerHTML=a.highlightedCode}}), Prism.hooks.add("wrap",function(a){"php"===a.language&&"markup"===a.type&&(a.content=a.content.replace(/(\{\{\{PHP[0-9]+\}\}\})/g,'<span class="token php">$1</span>'))}),Prism.languages.insertBefore("php","comment",{markup:{pattern:/(&lt;|<)[^?]\/?(.*?)(>|&gt;)/g,inside:Prism.languages.markup},php:/\{\{\{PHP[0-9]+\}\}\}/g}));;
Prism.languages.insertBefore("php","variable",{"this":/\$this/g,global:/\$_?(GLOBALS|SERVER|GET|POST|FILES|REQUEST|SESSION|ENV|COOKIE|HTTP_RAW_POST_DATA|argc|argv|php_errormsg|http_response_header)/g,scope:{pattern:/\b[\w\\]+::/g,inside:{keyword:/(static|self|parent)/,punctuation:/(::|\\)/}}});;
(function(){function e(e,t){return Array.prototype.slice.call((t||document).querySelectorAll(e))}function n(e,t,n){var r=t.replace(/\s+/g,"").split(","),i=+e.getAttribute("data-line-offset")||0,s=parseFloat(getComputedStyle(e).lineHeight);for(var o=0,u;u=r[o++];){u=u.split("-");var a=+u[0],f=+u[1]||a,l=document.createElement("div");l.textContent=Array(f-a+2).join(" \r\n");l.className=(n||"")+" line-highlight";l.setAttribute("data-start",a);f>a&&l.setAttribute("data-end",f);l.style.top=(a-i-1)*s+"px";(e.querySelector("code")||e).appendChild(l)}}function r(){var t=location.hash.slice(1);e(".temporary.line-highlight").forEach(function(e){e.parentNode.removeChild(e)});var r=(t.match(/\.([\d,-]+)$/)||[,""])[1];if(!r||document.getElementById(t))return;var i=t.slice(0,t.lastIndexOf(".")),s=document.getElementById(i);if(!s)return;s.hasAttribute("data-line")||s.setAttribute("data-line","");n(s,r,"temporary ");document.querySelector(".temporary.line-highlight").scrollIntoView()}if(!window.Prism)return;var t=crlf=/\r?\n|\r/g,i=0;Prism.hooks.add("after-highlight",function(t){var s=t.element.parentNode,o=s&&s.getAttribute("data-line");if(!s||!o||!/pre/i.test(s.nodeName))return;clearTimeout(i);e(".line-highlight",s).forEach(function(e){e.parentNode.removeChild(e)});n(s,o);i=setTimeout(r,1)});addEventListener("hashchange",r)})();;
Prism.hooks.add("after-highlight",function(e){var t=e.element.parentNode;if(!t||!/pre/i.test(t.nodeName)||t.className.indexOf("line-numbers")===-1){return}var n=1+e.code.split("\n").length;var r;lines=new Array(n);lines=lines.join("<span></span>");r=document.createElement("span");r.className="line-numbers-rows";r.innerHTML=lines;if(t.hasAttribute("data-start")){t.style.counterReset="linenumber "+(parseInt(t.getAttribute("data-start"),10)-1)}e.element.appendChild(r)})
;
(function(){if(!self.Prism||!self.document||!document.querySelector)return;var e={js:"javascript",html:"markup",svg:"markup"};Array.prototype.slice.call(document.querySelectorAll("pre[data-src]")).forEach(function(t){var n=t.getAttribute("data-src"),r=(n.match(/\.(\w+)$/)||[,""])[1],i=e[r]||r,s=document.createElement("code");s.className="language-"+i;t.textContent="";s.textContent="Loading…";t.appendChild(s);var o=new XMLHttpRequest;o.open("GET",n,!0);o.onreadystatechange=function(){if(o.readyState==4)if(o.status<400&&o.responseText){s.textContent=o.responseText;Prism.highlightElement(s)}else o.status>=400?s.textContent="✖ Error "+o.status+" while fetching file: "+o.statusText:s.textContent="✖ Error: File does not exist or is empty"};o.send(null)})})();;
/*	
 *	jQuery dotdotdot 1.5.9
 *	
 *	Copyright (c) 2013 Fred Heusschen
 *	www.frebsite.nl
 *
 *	Plugin website:
 *	dotdotdot.frebsite.nl
 *
 *	Dual licensed under the MIT and GPL licenses.
 *	http://en.wikipedia.org/wiki/MIT_License
 *	http://en.wikipedia.org/wiki/GNU_General_Public_License
 */

(function( $ )
{
	if ( $.fn.dotdotdot )
	{
		return;
	}

	$.fn.dotdotdot = function( o )
	{
		if ( this.length == 0 )
		{
			if ( !o || o.debug !== false )
			{
				debug( true, 'No element found for "' + this.selector + '".' );				
			}
			return this;
		}
		if ( this.length > 1 )
		{
			return this.each(
				function()
				{
					$(this).dotdotdot( o );
				}
			);
		}


		var $dot = this;

		if ( $dot.data( 'dotdotdot' ) )
		{
			$dot.trigger( 'destroy.dot' );
		}

		$dot.data( 'dotdotdot-style', $dot.attr( 'style' ) );
		$dot.css( 'word-wrap', 'break-word' );

		$dot.bind_events = function()
		{
			$dot.bind(
				'update.dot',
				function( e, c )
				{
					e.preventDefault();
					e.stopPropagation();

					opts.maxHeight = ( typeof opts.height == 'number' ) 
						? opts.height 
						: getTrueInnerHeight( $dot );

					opts.maxHeight += opts.tolerance;

					if ( typeof c != 'undefined' )
					{
						if ( typeof c == 'string' || c instanceof HTMLElement )
						{
					 		c = $('<div />').append( c ).contents();
						}
						if ( c instanceof $ )
						{
							orgContent = c;
						}
					}

					$inr = $dot.wrapInner( '<div class="dotdotdot" />' ).children();
					$inr.empty()
						.append( orgContent.clone( true ) )
						.css({
							'height'	: 'auto',
							'width'		: 'auto',
							'border'	: 'none',
							'padding'	: 0,
							'margin'	: 0
						});

					var after = false,
						trunc = false;

					if ( conf.afterElement )
					{
						after = conf.afterElement.clone( true );
						conf.afterElement.remove();
					}
					if ( test( $inr, opts ) )
					{
						if ( opts.wrap == 'children' )
						{
							trunc = children( $inr, opts, after );
						}
						else
						{
							trunc = ellipsis( $inr, $dot, $inr, opts, after );
						}
					}
					$inr.replaceWith( $inr.contents() );
					$inr = null;
					
					if ( $.isFunction( opts.callback ) )
					{
						opts.callback.call( $dot[ 0 ], trunc, orgContent );
					}

					conf.isTruncated = trunc;
					return trunc;
				}

			).bind(
				'isTruncated.dot',
				function( e, fn )
				{
					e.preventDefault();
					e.stopPropagation();

					if ( typeof fn == 'function' )
					{
						fn.call( $dot[ 0 ], conf.isTruncated );
					}
					return conf.isTruncated;
				}

			).bind(
				'originalContent.dot',
				function( e, fn )
				{
					e.preventDefault();
					e.stopPropagation();

					if ( typeof fn == 'function' )
					{
						fn.call( $dot[ 0 ], orgContent );
					}
					return orgContent;
				}

			).bind(
				'destroy.dot',
				function( e )
				{
					e.preventDefault();
					e.stopPropagation();

					$dot.unwatch()
						.unbind_events()
						.empty()
						.append( orgContent )
						.attr( 'style', $dot.data( 'dotdotdot-style' ) )
						.data( 'dotdotdot', false );
				}
			);
			return $dot;
		};	//	/bind_events

		$dot.unbind_events = function()
		{
			$dot.unbind('.dot');
			return $dot;
		};	//	/unbind_events

		$dot.watch = function()
		{
			$dot.unwatch();
			if ( opts.watch == 'window' )
			{
				var $window = $(window),
					_wWidth = $window.width(),
					_wHeight = $window.height(); 

				$window.bind(
					'resize.dot' + conf.dotId,
					function()
					{
						if ( _wWidth != $window.width() || _wHeight != $window.height() || !opts.windowResizeFix )
						{
							_wWidth = $window.width();
							_wHeight = $window.height();
	
							if ( watchInt )
							{
								clearInterval( watchInt );
							}
							watchInt = setTimeout(
								function()
								{
									$dot.trigger( 'update.dot' );
								}, 10
							);
						}
					}
				);
			}
			else
			{
				watchOrg = getSizes( $dot );
				watchInt = setInterval(
					function()
					{
						var watchNew = getSizes( $dot );
						if ( watchOrg.width  != watchNew.width ||
							 watchOrg.height != watchNew.height )
						{
							$dot.trigger( 'update.dot' );
							watchOrg = getSizes( $dot );
						}
					}, 100
				);
			}
			return $dot;
		};
		$dot.unwatch = function()
		{
			$(window).unbind( 'resize.dot' + conf.dotId );
			if ( watchInt )
			{
				clearInterval( watchInt );
			}
			return $dot;
		};

		var	orgContent	= $dot.contents(),
			opts 		= $.extend( true, {}, $.fn.dotdotdot.defaults, o ),
			conf		= {},
			watchOrg	= {},
			watchInt	= null,
			$inr		= null;

		conf.afterElement	= getElement( opts.after, $dot );
		conf.isTruncated	= false;
		conf.dotId			= dotId++;


		$dot.data( 'dotdotdot', true )
			.bind_events()
			.trigger( 'update.dot' );

		if ( opts.watch )
		{
			$dot.watch();
		}

		return $dot;
	};


	//	public
	$.fn.dotdotdot.defaults = {
		'ellipsis'	: '... ',
		'wrap'		: 'word',
		'lastCharacter': {
			'remove'		: [ ' ', ',', ';', '.', '!', '?' ],
			'noEllipsis'	: []
		},
		'tolerance'	: 0,
		'callback'	: null,
		'after'		: null,
		'height'	: null,
		'watch'		: false,
		'windowResizeFix': true,
		'debug'		: false
	};
	

	//	private
	var dotId = 1;

	function children( $elem, o, after )
	{
		var $elements 	= $elem.children(),
			isTruncated	= false;

		$elem.empty();

		for ( var a = 0, l = $elements.length; a < l; a++ )
		{
			var $e = $elements.eq( a );
			$elem.append( $e );
			if ( after )
			{
				$elem.append( after );
			}
			if ( test( $elem, o ) )
			{
				$e.remove();
				isTruncated = true;
				break;
			}
			else
			{
				if ( after )
				{
					after.remove();
				}
			}
		}
		return isTruncated;
	}
	function ellipsis( $elem, $d, $i, o, after )
	{
		var $elements 	= $elem.contents(),
			isTruncated	= false;

		$elem.empty();

		var notx = 'table, thead, tbody, tfoot, tr, col, colgroup, object, embed, param, ol, ul, dl, select, optgroup, option, textarea, script, style';
		for ( var a = 0, l = $elements.length; a < l; a++ )
		{

			if ( isTruncated )
			{
				break;
			}

			var e	= $elements[ a ],
				$e	= $(e);

			if ( typeof e == 'undefined' )
			{
				continue;
			}

			$elem.append( $e );
			if ( after )
			{
				$elem[ ( $elem.is( notx ) ) ? 'after' : 'append' ]( after );
			}
			if ( e.nodeType == 3 )
			{
				if ( test( $i, o ) )
				{
					isTruncated = ellipsisElement( $e, $d, $i, o, after );
				}
			}
			else
			{
				isTruncated = ellipsis( $e, $d, $i, o, after );
			}

			if ( !isTruncated )
			{
				if ( after )
				{
					after.remove();
				}
			}
		}
		return isTruncated;
	}
	function ellipsisElement( $e, $d, $i, o, after )
	{
		var isTruncated	= false,
			e = $e[ 0 ];

		if ( typeof e == 'undefined' )
		{
			return false;
		}

		var seporator	= ( o.wrap == 'letter' ) ? '' : ' ',
			textArr		= getTextContent( e ).split( seporator ),
			position 	= -1,
			midPos		= -1,
			startPos	= 0,
			endPos		= textArr.length - 1;

		while ( startPos <= endPos )
		{
			var m = Math.floor( ( startPos + endPos ) / 2 );
			if ( m == midPos ) 
			{
				break;
			}
			midPos = m;

			setTextContent( e, textArr.slice( 0, midPos + 1 ).join( seporator ) + o.ellipsis );

			if ( !test( $i, o ) )
			{
				position = midPos;
				startPos = midPos; 
			}
			else
			{
				endPos = midPos;
			}				
		}	
	
		if ( position != -1 && !( textArr.length == 1 && textArr[ 0 ].length == 0 ) )
		{
			var txt = addEllipsis( textArr.slice( 0, position + 1 ).join( seporator ), o );
			isTruncated = true;
			setTextContent( e, txt );
		}
		else
		{
			var $w = $e.parent();
			$e.remove();

			var afterLength = ( after ) ? after.length : 0 ;

			if ( $w.contents().size() > afterLength )
			{
				var $n = $w.contents().eq( -1 - afterLength );
				isTruncated = ellipsisElement( $n, $d, $i, o, after );
			}
			else
			{
				var $p = $w.prev()
				var e = $p.contents().eq( -1 )[ 0 ];

				if ( typeof e != 'undefined' )
				{
					var txt = addEllipsis( getTextContent( e ), o );
					setTextContent( e, txt );
					if ( after )
					{
						$p.append( after );
					}
					$w.remove();
					isTruncated = true;
				}

			}
		}

		return isTruncated;
	}
	function test( $i, o )
	{
		return $i.innerHeight() > o.maxHeight;
	}
	function addEllipsis( txt, o )
	{
		while( $.inArray( txt.slice( -1 ), o.lastCharacter.remove ) > -1 )
		{
			txt = txt.slice( 0, -1 );
		}
		if ( $.inArray( txt.slice( -1 ), o.lastCharacter.noEllipsis ) < 0 )
		{
			txt += o.ellipsis;
		}
		return txt;
	}
	function getSizes( $d )
	{
		return {
			'width'	: $d.innerWidth(),
			'height': $d.innerHeight()
		};
	}
	function setTextContent( e, content )
	{
		if ( e.innerText )
		{
			e.innerText = content;
		}
		else if ( e.nodeValue )
		{
			e.nodeValue = content;
		}
		else if (e.textContent)
		{
			e.textContent = content;
		}

	}
	function getTextContent( e )
	{
		if ( e.innerText )
		{
			return e.innerText;
		}
		else if ( e.nodeValue )
		{
			return e.nodeValue;
		}
		else if ( e.textContent )
		{
			return e.textContent;
		}
		else
		{
			return "";
		}
	}
	function getElement( e, $i )
	{
		if ( typeof e == 'undefined' )
		{
			return false;
		}
		if ( !e )
		{
			return false;
		}
		if ( typeof e == 'string' )
		{
			e = $(e, $i);
			return ( e.length )
				? e 
				: false;
		}
		if ( typeof e == 'object' )
		{
			return ( typeof e.jquery == 'undefined' )
				? false
				: e;
		}
		return false;
	}
	function getTrueInnerHeight( $el )
	{
		var h = $el.innerHeight(),
			a = [ 'paddingTop', 'paddingBottom' ];

		for ( var z = 0, l = a.length; z < l; z++ ) {
			var m = parseInt( $el.css( a[ z ] ), 10 );
			if ( isNaN( m ) )
			{
				m = 0;
			}
			h -= m;
		}
		return h;
	}
	function debug( d, m )
	{
		if ( !d )
		{
			return false;
		}
		if ( typeof m == 'string' )
		{
			m = 'dotdotdot: ' + m;
		}
		else
		{
			m = [ 'dotdotdot:', m ];
		}

		if ( typeof window.console != 'undefined' )
		{
			if ( typeof window.console.log != 'undefined' )
			{
				window.console.log( m );
			}
		}
		return false;
	}
	

	//	override jQuery.html
	var _orgHtml = $.fn.html;
    $.fn.html = function( str ) {
		if ( typeof str != 'undefined' )
		{
			if ( this.data( 'dotdotdot' ) )
			{
				if ( typeof str != 'function' )
				{
					return this.trigger( 'update', [ str ] );
				}
			}
			return _orgHtml.call( this, str );
		}
		return _orgHtml.call( this );
    };


	//	override jQuery.text
	var _orgText = $.fn.text;
    $.fn.text = function( str ) {
		if ( typeof str != 'undefined' )
		{
			if ( this.data( 'dotdotdot' ) )
			{
				var temp = $( '<div />' );
				temp.text( str );
				str = temp.html();
				temp.remove();
				return this.trigger( 'update', [ str ] );
			}
			return _orgText.call( this, str );
		}
        return _orgText.call( this );
    };


})( jQuery );
@font-face {
	font-family: 'phpdocumentor-clean-icons';
	src:url('fonts/phpdocumentor-clean-icons.eot');
	src:url('fonts/phpdocumentor-clean-icons.eot?#iefix') format('embedded-opentype'),
		url('fonts/phpdocumentor-clean-icons.woff') format('woff'),
		url('fonts/phpdocumentor-clean-icons.ttf') format('truetype'),
		url('fonts/phpdocumentor-clean-icons.svg#phpdocumentor-clean-icons') format('svg');
	font-weight: normal;
	font-style: normal;
}

/* Use the following CSS code if you want to use data attributes for inserting your icons */
[data-icon]:before {
	font-family: 'phpdocumentor-clean-icons';
	content: attr(data-icon);
	speak: none;
	font-weight: normal;
	font-variant: normal;
	text-transform: none;
	line-height: 1;
	-webkit-font-smoothing: antialiased;
}

/* Use the following CSS code if you want to have a class per icon */
/*
Instead of a list of all class selectors,
you can use the generic selector below, but it's slower:
[class*="icon-"] {
*/
.icon-trait, .icon-interface, .icon-class {
	font-family: 'phpdocumentor-clean-icons';
	speak: none;
	font-style: normal;
	font-weight: normal;
	font-variant: normal;
	text-transform: none;
	line-height: 1;
	-webkit-font-smoothing: antialiased;
}
.icon-trait:before {
	content: "\e000";
}
.icon-interface:before {
	content: "\e001";
}
.icon-class:before {
	content: "\e002";
}
       PFFTMh[<     GDEF 4       OS/2/  X   Vcmap    Rgasp      glyfuc  ,  head<)      6hhea     $hmtx .     loca B     maxp M X  8    name61     jpost5|q     P      DL_<                           .                          U             @          Lf   GLf                             PfEd @   .                                           L       0                                                                                                                                                                                                                                                                                                       H         !             )  ";26=4&#32+"&=461##5#531DD11DD1'88''88T3TD11DD11D*8''88''80++        %  ";26=4&#32+"&=4613#1DD11DD1'88''88n22D11DD11D*8''88''80          T  ";26=4&#32+"&=461"&'.4767>32&'&#"32767#1DD11DD1'88''881
1


		D11DD11D*8''88''85D)%(               4        f       5        H       z         	  2    	   N  	  j r  	  2  	  b  	  2 p h p d o c u m e n t o r - c l e a n - i c o n s  phpdocumentor-clean-icons  c l e a n - i c o n s  clean-icons  F o n t F o r g e   2 . 0   :   p h p d o c u m e n t o r - c l e a n - i c o n s   :   1 9 - 7 - 2 0 1 3  FontForge 2.0 : phpdocumentor-clean-icons : 19-7-2013  p h p d o c u m e n t o r - c l e a n - i c o n s  phpdocumentor-clean-icons  V e r s i o n   1 . 0  Version 1.0  p h p d o c u m e n t o r - c l e a n - i c o n s  phpdocumentor-clean-icons                                       uniF000uniE000uniE001uniE002                                 =        <?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>
This is a custom SVG font generated by IcoMoon.
<iconset id="phpdocumentor-clean-icons" name="phpdocumentor-clean-icons" href="http://www.phpdoc.org" grid="16"></iconset><author name="Mike van Riel" href="http://www.mikevanriel.com"></author><license name="SIL"></license>
</metadata>
<defs>
<font id="phpdocumentor-clean-icons" horiz-adv-x="512" >
<font-face units-per-em="512" ascent="480" descent="-32" />
<missing-glyph horiz-adv-x="512" />
<glyph class="hidden" unicode="&#xf000;" d="M0,480L 512 -32L0 -32 z" horiz-adv-x="0" />
<glyph unicode="&#xe000;" d="M 139.636,456.727 C 75.171,456.727 23.273,404.829 23.273,340.364 l 0-232.727 c 0-64.465 51.898-116.364 116.364-116.364 l 232.727,0 c 64.465,0 116.364,51.898 116.364,116.364 L 488.727,340.364 C 488.727,404.829 436.829,456.727 372.364,456.727 L 139.636,456.727 z m 20.727-41.381 191.274,0 c 53.001,0 95.709-42.708 95.709-95.709 l 0-191.274 c 0-53.001 -42.708-95.709 -95.709-95.709 l -191.274,0 c -53.001,0 -95.709,42.708 -95.709,95.709 l 0,191.274 c 0,53.001 42.708,95.709 95.709,95.709 zM 359.963,366.827  m0,0,0-43.124 -84.271,0 0-231.052 -50.246,0 0,231.052 -84.271,0 0,43.124 218.787,0"  />
<glyph unicode="&#xe001;" d="M 139.636,456.727 C 75.171,456.727 23.273,404.829 23.273,340.364 l 0-232.727 c 0-64.465 51.898-116.364 116.364-116.364 l 232.727,0 c 64.465,0 116.364,51.898 116.364,116.364 L 488.727,340.364 C 488.727,404.829 436.829,456.727 372.364,456.727 L 139.636,456.727 z m 20.727-41.381 191.274,0 c 53.001,0 95.709-42.708 95.709-95.709 l 0-191.274 c 0-53.001 -42.708-95.709 -95.709-95.709 l -191.274,0 c -53.001,0 -95.709,42.708 -95.709,95.709 l 0,191.274 c 0,53.001 42.708,95.709 95.709,95.709 zM 231.075,366.827  m0,0, 49.85,0 0-274.176 -49.85,0 0,274.176"  />
<glyph unicode="&#xe002;" d="M 139.636,456.727 C 75.171,456.727 23.273,404.829 23.273,340.364 l 0-232.727 c 0-64.465 51.898-116.364 116.364-116.364 l 232.727,0 c 64.465,0 116.364,51.898 116.364,116.364 L 488.727,340.364 C 488.727,404.829 436.829,456.727 372.364,456.727 L 139.636,456.727 z m 20.727-41.381 191.274,0 c 53.001,0 95.709-42.708 95.709-95.709 l 0-191.274 c 0-53.001 -42.708-95.709 -95.709-95.709 l -191.274,0 c -53.001,0 -95.709,42.708 -95.709,95.709 l 0,191.274 c 0,53.001 42.708,95.709 95.709,95.709 zM 278.749,86.717  m0,0,c -20.573,0 -39.036,3.165 -55.389,9.495 -16.353,6.33 -30.2,15.562 -41.542,27.695 -11.342,12.397 -20.046,27.431 -26.112,45.103 -6.066,17.672 -9.1,37.981 -9.1,60.928 0,22.947 3.429,43.256 10.287,60.928 7.121,17.672 16.749,32.574 28.881,44.707 12.133,12.396 26.376,21.76 42.729,28.090 16.353,6.33 33.893,9.495 52.62,9.495 11.341,0 21.628-0.923 30.86-2.769 9.231-1.583 17.276-3.429 24.134-5.539 6.857-2.11 12.528-4.352 17.012-6.726 4.484-2.374 7.649-4.089 9.495-5.143 l -14.639-40.751 c -6.33,3.956 -15.43,7.649 -27.299,11.078 -11.606,3.692 -24.266,5.539 -37.981,5.539 -11.869,0 -22.947-2.11 -33.233-6.33 -10.287-3.957 -19.254-10.023 -26.903-18.199 -7.385-8.177 -13.188-18.463 -17.408-30.86 -4.22-12.397 -6.33-26.772 -6.33-43.124 0-14.507 1.582-27.827 4.748-39.959 3.429-12.133 8.572-22.683 15.43-31.651 6.858-8.704 15.562-15.562 26.112-20.573 10.55-4.748 23.211-7.122 37.981-7.121 17.672,0 32.046,1.714 43.124,5.143 11.078,3.693 19.65,7.121 25.716,10.287 l 13.452-40.751 c -3.165-2.11 -7.517-4.22 -13.056-6.33 -5.275-2.11 -11.606-4.22 -18.991-6.33 -7.385-1.846 -15.694-3.297 -24.925-4.352 -9.232-1.319 -19.123-1.978 -29.673-1.978"  />
<glyph unicode="&#x20;" horiz-adv-x="256" />
</font></defs></svg>	                       LP                     LD                  2 p h p d o c u m e n t o r - c l e a n - i c o n s    c l e a n - i c o n s    V e r s i o n   1 . 0   2 p h p d o c u m e n t o r - c l e a n - i c o n s            PFFTMh[<     GDEF 4       OS/2/  X   Vcmap    Rgasp      glyfuc  ,  head<)      6hhea     $hmtx .     loca B     maxp M X  8    name61     jpost5|q     P      DL_<                           .                          U             @          Lf   GLf                             PfEd @   .                                           L       0                                                                                                                                                                                                                                                                                                       H         !             )  ";26=4&#32+"&=461##5#531DD11DD1'88''88T3TD11DD11D*8''88''80++        %  ";26=4&#32+"&=4613#1DD11DD1'88''88n22D11DD11D*8''88''80          T  ";26=4&#32+"&=461"&'.4767>32&'&#"32767#1DD11DD1'88''881
1


		D11DD11D*8''88''85D)%(               4        f       5        H       z         	  2    	   N  	  j r  	  2  	  b  	  2 p h p d o c u m e n t o r - c l e a n - i c o n s  phpdocumentor-clean-icons  c l e a n - i c o n s  clean-icons  F o n t F o r g e   2 . 0   :   p h p d o c u m e n t o r - c l e a n - i c o n s   :   1 9 - 7 - 2 0 1 3  FontForge 2.0 : phpdocumentor-clean-icons : 19-7-2013  p h p d o c u m e n t o r - c l e a n - i c o n s  phpdocumentor-clean-icons  V e r s i o n   1 . 0  Version 1.0  p h p d o c u m e n t o r - c l e a n - i c o n s  phpdocumentor-clean-icons                                       uniF000uniE000uniE001uniE002                                 =        <?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>
This is a custom SVG font generated by IcoMoon.
<iconset id="phpdocumentor-clean-icons" name="phpdocumentor-clean-icons" href="http://www.phpdoc.org" grid="16"></iconset><author name="Mike van Riel" href="http://www.mikevanriel.com"></author><license name="SIL"></license>
</metadata>
<defs>
<font id="phpdocumentor-clean-icons" horiz-adv-x="512" >
<font-face units-per-em="512" ascent="480" descent="-32" />
<missing-glyph horiz-adv-x="512" />
<glyph class="hidden" unicode="&#xf000;" d="M0,480L 512 -32L0 -32 z" horiz-adv-x="0" />
<glyph unicode="&#xe000;" d="M 139.636,456.727 C 75.171,456.727 23.273,404.829 23.273,340.364 l 0-232.727 c 0-64.465 51.898-116.364 116.364-116.364 l 232.727,0 c 64.465,0 116.364,51.898 116.364,116.364 L 488.727,340.364 C 488.727,404.829 436.829,456.727 372.364,456.727 L 139.636,456.727 z m 20.727-41.381 191.274,0 c 53.001,0 95.709-42.708 95.709-95.709 l 0-191.274 c 0-53.001 -42.708-95.709 -95.709-95.709 l -191.274,0 c -53.001,0 -95.709,42.708 -95.709,95.709 l 0,191.274 c 0,53.001 42.708,95.709 95.709,95.709 zM 359.963,366.827  m0,0,0-43.124 -84.271,0 0-231.052 -50.246,0 0,231.052 -84.271,0 0,43.124 218.787,0" data-tags="trait" />
<glyph unicode="&#xe001;" d="M 139.636,456.727 C 75.171,456.727 23.273,404.829 23.273,340.364 l 0-232.727 c 0-64.465 51.898-116.364 116.364-116.364 l 232.727,0 c 64.465,0 116.364,51.898 116.364,116.364 L 488.727,340.364 C 488.727,404.829 436.829,456.727 372.364,456.727 L 139.636,456.727 z m 20.727-41.381 191.274,0 c 53.001,0 95.709-42.708 95.709-95.709 l 0-191.274 c 0-53.001 -42.708-95.709 -95.709-95.709 l -191.274,0 c -53.001,0 -95.709,42.708 -95.709,95.709 l 0,191.274 c 0,53.001 42.708,95.709 95.709,95.709 zM 231.075,366.827  m0,0, 49.85,0 0-274.176 -49.85,0 0,274.176" data-tags="interface" />
<glyph unicode="&#xe002;" d="M 139.636,456.727 C 75.171,456.727 23.273,404.829 23.273,340.364 l 0-232.727 c 0-64.465 51.898-116.364 116.364-116.364 l 232.727,0 c 64.465,0 116.364,51.898 116.364,116.364 L 488.727,340.364 C 488.727,404.829 436.829,456.727 372.364,456.727 L 139.636,456.727 z m 20.727-41.381 191.274,0 c 53.001,0 95.709-42.708 95.709-95.709 l 0-191.274 c 0-53.001 -42.708-95.709 -95.709-95.709 l -191.274,0 c -53.001,0 -95.709,42.708 -95.709,95.709 l 0,191.274 c 0,53.001 42.708,95.709 95.709,95.709 zM 278.749,86.717  m0,0,c -20.573,0 -39.036,3.165 -55.389,9.495 -16.353,6.33 -30.2,15.562 -41.542,27.695 -11.342,12.397 -20.046,27.431 -26.112,45.103 -6.066,17.672 -9.1,37.981 -9.1,60.928 0,22.947 3.429,43.256 10.287,60.928 7.121,17.672 16.749,32.574 28.881,44.707 12.133,12.396 26.376,21.76 42.729,28.090 16.353,6.33 33.893,9.495 52.62,9.495 11.341,0 21.628-0.923 30.86-2.769 9.231-1.583 17.276-3.429 24.134-5.539 6.857-2.11 12.528-4.352 17.012-6.726 4.484-2.374 7.649-4.089 9.495-5.143 l -14.639-40.751 c -6.33,3.956 -15.43,7.649 -27.299,11.078 -11.606,3.692 -24.266,5.539 -37.981,5.539 -11.869,0 -22.947-2.11 -33.233-6.33 -10.287-3.957 -19.254-10.023 -26.903-18.199 -7.385-8.177 -13.188-18.463 -17.408-30.86 -4.22-12.397 -6.33-26.772 -6.33-43.124 0-14.507 1.582-27.827 4.748-39.959 3.429-12.133 8.572-22.683 15.43-31.651 6.858-8.704 15.562-15.562 26.112-20.573 10.55-4.748 23.211-7.122 37.981-7.121 17.672,0 32.046,1.714 43.124,5.143 11.078,3.693 19.65,7.121 25.716,10.287 l 13.452-40.751 c -3.165-2.11 -7.517-4.22 -13.056-6.33 -5.275-2.11 -11.606-4.22 -18.991-6.33 -7.385-1.846 -15.694-3.297 -24.925-4.352 -9.232-1.319 -19.123-1.978 -29.673-1.978" data-tags="class" />
<glyph unicode="&#x20;" horiz-adv-x="256" />
</font></defs></svg>wOFFOTTO  (                            CFF       `8FFTM        h[<GDEF          2 OS/2  ,   K   `/@cmap  x   =  Rhead     .   6<)hhea        $hmtx         .maxp         P name        j61post            x}T]leݟqwv[t6TI6$Ѥ&,V%?
j1fА
	
gADZ1I[6{=̴͙{9so%I@Mu-o6l75FIDzȦ/s횒)XҶqšy*QJgVIQW)8dG9O+hmktseII	s%c}+DR)> PB(aw4ŞqIKc~տ͔ݟWmmgYgrVt2TTS9wii?=p>;
'MpLK~b)+c>ԃې2R.Lݧ5"ГzIZ_B _6Y jner1ЅO-dS5GZ|͊9vVbťFLf]Ŵx <-2O]Ǟ_̢Xvw9^$j]ˢAɗ~ode|B99GAia-ZI>%+@3gN"*f1w5yR#16V9S1P^),2aLصH P݃r2Ŗd*mm6<u6h}nJ4jY=_
c.ۢ'0.,by}E[12y1>ewTa{vJس׬´LgvcBF>+ha8>׫0$s2֛G̷Iߝ E,D'1twC71q$C/'
3C":&3wރ*g@
IX}a(v(="jŕjOgk~Mqi>$i%'S[wp8
q>;C>Rq!I.jF9
"		Vo_5|1!kkLQ23E `eSr3e.HL$uxc```d 3΃s|;h K;  xc`d``b	`b`B0 v 7xc`fb`Ø2H2000123 0(4000( !# B xc```f`F| L L ,&F.0`dc@H  ˨   xc`d`` bEg|efb s|;! `i G  xc`d``|? 	A m               P    x1n1EaAH|NT)F`p 09KnIA	K##>.){]3LՋ #uRSeT\Wr
$ &<~E=cg0K0T7T*ft}C)~LU<Nm=aG+rܗO[g:g8eV14v^K}srمWXO'zپkNUŝ; wuYxc`f  } To modify your generated font, use the *dev.svg* file, located in the *fonts* folder in this package. You can import this dev.svg file to the IcoMoon app. All the tags (class names) and the Unicode points of your glyphs are saved in this file.

See the documentation for more info on how to use this package: http://icomoon.io/#docs/font-face/* Load this script using conditional IE comments if you need to support IE 7 and IE 6. */

window.onload = function() {
	function addIcon(el, entity) {
		var html = el.innerHTML;
		el.innerHTML = '<span style="font-family: \'phpdocumentor-clean-icons\'">' + entity + '</span>' + html;
	}
	var icons = {
			'icon-trait' : '&#xe000;',
			'icon-interface' : '&#xe001;',
			'icon-class' : '&#xe002;'
		},
		els = document.getElementsByTagName('*'),
		i, attr, html, c, el;
	for (i = 0; ; i += 1) {
		el = els[i];
		if(!el) {
			break;
		}
		attr = el.getAttribute('data-icon');
		if (attr) {
			addIcon(el, attr);
		}
		c = el.className;
		c = c.match(/icon-[^\s'"]+/);
		if (c && icons[c[0]]) {
			addIcon(el, icons[c[0]]);
		}
	}
};/**
 * prism.js default theme for JavaScript, CSS and HTML
 * Based on dabblet (http://dabblet.com)
 * @author Lea Verou
 */

code[class*="language-"],
pre[class*="language-"] {
	color: black;
	text-shadow: 0 1px white;
	font-family: Consolas, Monaco, 'Andale Mono', monospace;
	direction: ltr;
	text-align: left;
	white-space: pre;
	word-spacing: normal;

	-moz-tab-size: 4;
	-o-tab-size: 4;
	tab-size: 4;

	-webkit-hyphens: none;
	-moz-hyphens: none;
	-ms-hyphens: none;
	hyphens: none;
}

::-moz-selection {
	text-shadow: none;
	background: #b3d4fc;
}

::selection {
	text-shadow: none;
	background: #b3d4fc;
}

@media print {
	code[class*="language-"],
	pre[class*="language-"] {
		text-shadow: none;
	}
}

/* Code blocks */
pre[class*="language-"] {
	padding: 1em;
	margin: .5em 0;
	overflow: auto;
}

:not(pre) > code[class*="language-"],
pre[class*="language-"] {
	background: #f5f2f0;
}

/* Inline code */
:not(pre) > code[class*="language-"] {
	padding: .1em;
	border-radius: .3em;
}

.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
	color: slategray;
}

.token.punctuation {
	color: #999;
}

.namespace {
	opacity: .7;
}

.token.property,
.token.tag,
.token.boolean,
.token.number {
	color: #905;
}

.token.selector,
.token.attr-name,
.token.string {
	color: #690;
}

.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
	color: #a67f59;
	background: hsla(0,0%,100%,.5);
}

.token.atrule,
.token.attr-value,
.token.keyword {
	color: #07a;
}


.token.regex,
.token.important {
	color: #e90;
}

.token.important {
	font-weight: bold;
}

.token.entity {
	cursor: help;
}
pre[data-line] {
	position: relative;
	padding: 1em 0 1em 3em;
}

.line-highlight {
	position: absolute;
	left: 0;
	right: 0;
	padding: inherit 0;
	margin-top: 1em; /* Same as .prism’s padding-top */

	background: hsla(24, 20%, 50%,.08);
	background: -moz-linear-gradient(left, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0));
	background: -webkit-linear-gradient(left, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0));
	background: -o-linear-gradient(left, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0));
	background: linear-gradient(left, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0));
	
	pointer-events: none;
	
	line-height: inherit;
	white-space: pre;
}

	.line-highlight:before,
	.line-highlight[data-end]:after {
		content: attr(data-start);
		position: absolute;
		top: .4em;
		left: .6em;
		min-width: 1em;
		padding: 0 .5em;
		background-color: hsla(24, 20%, 50%,.4);
		color: hsl(24, 20%, 95%);
		font: bold 65%/1.5 sans-serif;
		text-align: center;
		vertical-align: .3em;
		border-radius: 999px;
		text-shadow: none;
		box-shadow: 0 1px white;
	}
	
	.line-highlight[data-end]:after {
		content: attr(data-end);
		top: auto;
		bottom: .4em;
	}
pre.line-numbers {
	position: relative;
	padding-left: 3.8em;
	counter-reset: linenumber;
}

pre.line-numbers > code {
	position: relative;
}

.line-numbers .line-numbers-rows {
	position: absolute;
	pointer-events: none;
	top: 0;
	font-size: 100%;
	left: -3.8em;
	width: 3em; /* works for line-numbers below 1000 lines */
	letter-spacing: -1px;
	border-right: 1px solid #999;

	-webkit-user-select: none;
	-moz-user-select: none;
	-ms-user-select: none;
	user-select: none;

}

	.line-numbers-rows > span {
		pointer-events: none;
		display: block;
		counter-increment: linenumber;
	}

		.line-numbers-rows > span:before {
			content: counter(linenumber);
			color: #999;
			display: block;
			padding-right: 0.8em;
			text-align: right;
		}
.viewer {
    -ms-touch-action: none;
}

.iviewer_common {
    position:absolute;
    bottom:10px;
    border: 1px  solid #000;
    height: 28px;
    z-index: 5000;
}

.iviewer_cursor {
    cursor: url(../images/iviewer/hand.cur) 6 8, pointer;
}

.iviewer_drag_cursor {
    cursor: url(../images/iviewer/grab.cur) 6 8, pointer;
}

.iviewer_button {
    width: 28px;
    cursor: pointer;
    background-position: center center;
    background-repeat: no-repeat;
}

.iviewer_zoom_in {
    left: 20px;
    background: url(../images/iviewer/iviewer.zoom_in.png);
}

.iviewer_zoom_out {
    left: 55px;
    background: url(../images/iviewer/iviewer.zoom_out.png);
}

.iviewer_zoom_zero {
    left: 90px;
    background: url(../images/iviewer/iviewer.zoom_zero.png);
}

.iviewer_zoom_fit {
    left: 125px;
    background: url(../images/iviewer/iviewer.zoom_fit.png);
}

.iviewer_zoom_status {
    left: 160px;
    font: 1em/28px Sans;
    color: #000;
    background-color: #fff;
    text-align: center;
    width: 60px;
}

.iviewer_rotate_left {
    left: 227px;
    background: #fff url(../images/iviewer/iviewer.rotate_left.png) center center no-repeat;
}

.iviewer_rotate_right {
    left: 262px;
    background: #fff url(../images/iviewer/iviewer.rotate_right.png) center center no-repeat;
}
@import url(https://fonts.googleapis.com/css?family=Source+Sans+Pro);
@import url('phpdocumentor-clean-icons/style.css');

body {
    padding-top:      40px;
    background-color: #333333;
}

a {
    color: #6495ed;
}
a.anchor {
    height: 40px;
    margin-top: -40px;
    display: block;
}

h1, h2, h3, h4, h5, h6, .brand {
    font-family:    'Source Sans Pro', sans-serif;
    font-weight:    normal;
    letter-spacing: 0.05em;
}

h2, h3, .detailsbar h1 {
    overflow:    hidden;
    white-space: nowrap;
    margin:      30px 0 20px 0;
}

h2:after, h3:after, .detailsbar h1:after {
    content:        '';
    display:        inline-block;
    vertical-align: middle;
    width:          100%;
    height:         2px;
    margin-left:    1em;
    background:     silver;
}

h3 {
    margin: 10px 0 20px 0;
}

h4 {
    margin:    20px 0 10px 0;
    color:     gray;
    font-size: 18.5px;
}

h3.public, h3.protected, h3.private {
    padding-left: 10px;
    text-overflow: ellipsis;
}

.table tr:first-of-type th, .table tr:first-of-type td {
    border-top: none;
}
.detailsbar {
    color:            #eeeeee;
    background-color: #333333;
    font-size:        0.9em;
    overflow:         hidden;
    border-left:      2px solid gray;
}

.detailsbar h1 {
    font-size:     1.5em;
    margin-bottom: 20px;
    margin-top:    0;
}

.detailsbar h2 {
    font-size: 1.2em;
    margin:    0;
    padding:   0;
}

.detailsbar h1:after {
    background: gray;
}
.detailsbar h2:after, .detailsbar h3:after {
    background: transparent;
}

.detailsbar dt {
    font-variant:   small-caps;
    text-transform: lowercase;
    font-size:      1.1em;
    letter-spacing: 0.1em;
    color:          silver;
}

.hierarchy div:nth-of-type(2) { margin-left: 11px; }
.hierarchy div:nth-of-type(3) { margin-left: 22px; }
.hierarchy div:nth-of-type(4) { margin-left: 33px; }
.hierarchy div:nth-of-type(5) { margin-left: 44px; }
.hierarchy div:nth-of-type(6) { margin-left: 55px; }
.hierarchy div:nth-of-type(7) { margin-left: 66px; }
.hierarchy div:nth-of-type(8) { margin-left: 77px; }
.hierarchy div:nth-of-type(9) { margin-left: 88px; }
.hierarchy div:before {
    content: "\f0da";
    font-family: FontAwesome;
    margin-right: 5px;
}

.row-fluid {
    background-color: white;
    overflow:         hidden;
}

footer.row-fluid, footer.row-fluid * {
    background-color: #333333;
    color:            white;
}

footer.row-fluid {
    border-top: 2px dashed #555;
    margin-top: 2px;
}

.footer-sections .span4 {
    border:        2px solid #555;
    text-align:    center;
    border-radius: 10px;
    margin-top:    70px;
    margin-bottom: 20px;
    background:    #373737;
}

.footer-sections .span4 h1 {
    background: transparent;
    margin-top: -30px;
    margin-bottom: 20px;
    font-size:  5em;
}

.footer-sections .span4 h1 * {
    background: transparent;
}

.footer-sections .span4 div {
    border-bottom-right-radius: 6px;
    border-bottom-left-radius: 6px;
    padding: 10px;
    min-height: 40px;
}
.footer-sections .span4 div, .footer-sections .span4 div * {
    background-color: #555;
}
.footer-sections .span4 ul {
    text-align: left;
    list-style: none;
    margin: 0;
    padding: 0;
}

.content {
    background-color: white;
    padding-right:    20px;
}

.content nav {
    text-align:     center;
    border-bottom:  1px solid silver;
    margin:         5px 0 20px 0;
    padding-bottom: 5px;
}

.content > h1 {
    padding-bottom: 15px;
}

.content > h1 small {
    display:        block;
    padding-bottom: 8px;
    font-size:      0.6em;
}

.deprecated {
    text-decoration: line-through;
}

.method {
    margin-bottom: 20px;
}

.method .signature .argument {
    color:       maroon;
    font-weight: bold;
}

.class #summary section.row-fluid {
    overflow: hidden
}

.class #summary .heading {
    font-weight: bold;
    text-align:  center;
}

.class #summary section .span4 {
    padding:        3px;
    overflow:       hidden;
    margin-bottom:  -9999px;
    padding-bottom: 9999px;
    white-space:    nowrap;
    text-overflow:  ellipsis;
    border-left:    5px solid transparent;
}

.class #summary section.public .span4:first-of-type:before,
.class #summary section.public .span6:first-of-type:before,
h3.public:before {
    font-family: FontAwesome;
    content:     "\f046";
    color:       green;
    display:     inline-block;
    width:       1.2em;
}

.class #summary section .span4:first-of-type,
.class #summary section .span6:first-of-type {
    padding-left: 21px;
}
.class #summary section .span4:first-of-type:before,
.class #summary section .span6:first-of-type:before {
    margin-left: -21px;
}
.class #summary section.protected .span4:first-of-type:before,
.class #summary section.protected .span6:first-of-type:before,
h3.protected:before {
    font-family: FontAwesome;
    content:     "\f132";
    color:       orange;
    display:     inline-block;
    width:       1.2em;
}

.class #summary section.private .span4:first-of-type:before,
.class #summary section.private .span6:first-of-type:before,
h3.private:before {
    font-family: FontAwesome;
    content:     "\f023";
    color:       red;
    display:     inline-block;
    width:       1.2em;
}

.class #summary section em {
    font-size: 0.9em;
    color: silver;
}
.class #summary .inherited {
    color:      gray;
    font-style: italic;
}

.accordion-group {
    border: none;
}

.accordion {
    margin-bottom: 0;
}

.accordion a:hover {
    text-decoration: none;
    background:      #333333;
    color:           #eeeeee;
}

.accordion-heading .accordion-toggle:before {
    content:      "\f078";
    font-family:  FontAwesome;
    margin-right: 5px;
}

.accordion-heading .accordion-toggle.collapsed:before {
    content: "\f054";
}
.accordion-heading .accordion-toggle {
    float: left;
    width: 16px;
    height: 16px;
    padding: 4px 2px 4px 12px;
}
.accordion-heading a {
    display: block;
    padding: 4px 12px;
}

.accordion-inner a {
    display: block;
    padding: 4px 12px;
}

.accordion-inner > ul a:before {
    font-family: 'phpdocumentor-clean-icons';
    content:      "\e001";
    margin-right: 5px;
}

.accordion-inner li.class a:before {
    content:      "\e002";
}

.accordion-inner li.interface a:before {
    content:      "\e001";
}

.accordion-inner li.trait a:before {
    content:      "\e000";
}

.accordion-inner {
    padding: 4px 0 4px 12px;
}
.accordion-inner ul {
    list-style: none;
    padding:    0;
    margin:     0;
}

.row-fluid .span2 {
    width: 16.5%;
}

body .modal {
    width: 90%; /* desired relative width */
    left: 5%; /* (100%-width)/2 */
    /* place center */
    margin-left:auto;
    margin-right:auto;
}

@media (min-width: 767px) {
    .sidebar {
        position:         fixed;
        top:              40px;
        bottom:           0;
        background-color: #f3f3f3;
        left:             0;
        border-right:     1px solid #e9e9e9;
        overflow-y:       scroll;
        overflow-x:       hidden;
        padding-top:      10px;
    }

    .sidebar::-webkit-scrollbar {
        width: 10px;
    }

    .sidebar::-webkit-scrollbar-thumb {
        background:      #cccccc;
        background-clip: padding-box;
        border:          3px solid #f3f3f3;
        border-radius:   5px;
    }

    .sidebar::-webkit-scrollbar-button {
        display: none;
    }

    .sidebar::-webkit-scrollbar-track {
        background: #f3f3f3;
    }
}

@media (max-width: 979px) {
    body {
        padding-top: 0;
    }
}

@media (max-width: 767px) {
    .class #summary .heading {
        display: none;
    }

    .detailsbar h1 {
        display: none;
    }

    body {
        background-color: white;
    }

    footer.row-fluid, footer.row-fluid * {
        background-color: white;
    }

    .footer-sections h1 {
        color: #ccccd9;
    }

    .detailsbar {
        background-color: white;
        color: #333;
        border: none;
    }
}

@media (min-width: 767px) {
    .detailsbar {
        min-height:     100%;
        margin-bottom:  -99999px;
        padding-bottom: 99999px;
        padding-left:   20px;
        padding-top:    10px;
    }
}

@media (min-width: 1200px) {
    .row-fluid .span2 {
        width: 16.5%;
    }
}
<?xml version="1.0" encoding="utf-8"?>
<template>
  <author>Mike van Riel</author>
  <email>mike@phpdoc.org</email>
  <version>1.0.0</version>
  <copyright>Mike van Riel 2013</copyright>
  <description><![CDATA[

      To improve performance you can add the following to your .htaccess:

      <ifModule mod_deflate.c>
          <filesMatch "\.(js|css|html)$">
              SetOutputFilter DEFLATE
          </filesMatch>
      </ifModule>
  ]]></description>
  <transformations>
    <transformation query="copy" writer="FileIo" source="templates/clean/images" artifact="images"/>
    <transformation query="copy" writer="FileIo" source="templates/clean/css" artifact="css"/>
    <transformation query="copy" writer="FileIo" source="templates/clean/js" artifact="js"/>
    <transformation writer="twig" query="namespace" source="templates/clean/namespace.html.twig" artifact="index.html"/>
    <transformation writer="twig" query="indexes.namespaces" source="templates/clean/namespace.html.twig" />
    <transformation writer="twig" query="indexes.classes" source="templates/clean/class.html.twig" />
    <transformation writer="twig" query="indexes.interfaces" source="templates/clean/interface.html.twig" />
    <transformation writer="twig" query="indexes.traits" source="templates/clean/class.html.twig" />
    <transformation writer="twig" query="files" source="templates/clean/file.html.twig" />
    <transformation writer="twig" query="files" source="templates/clean/file.source.txt.twig" artifact="files/{{path}}.txt"/>
    <transformation writer="twig" source="templates/clean/reports/markers.html.twig" artifact="reports/markers.html"/>
    <transformation writer="twig" source="templates/clean/reports/errors.html.twig" artifact="reports/errors.html"/>
    <transformation writer="twig" source="templates/clean/reports/deprecated.html.twig" artifact="reports/deprecated.html"/>
    <transformation writer="twig" source="templates/clean/graphs/class.html.twig" artifact="graphs/class.html"/>
    <transformation writer="Graph" source="Class" artifact="graphs/classes.svg" />
  </transformations>
</template>
{
    "_readme": [
        "This file locks the dependencies of your project to a known state",
        "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
    ],
    "hash": "f31d00a5e74fc89a3edb95389c580553",
    "packages": [
        {
            "name": "phpdocumentor/unified-asset-installer",
            "version": "1.1",
            "source": {
                "type": "git",
                "url": "https://github.com/phpDocumentor/UnifiedAssetInstaller.git",
                "reference": "1.1"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phpDocumentor/UnifiedAssetInstaller/zipball/1.1",
                "reference": "1.1",
                "shasum": ""
            },
            "require-dev": {
                "composer/composer": "~1.0@dev",
                "phpunit/phpunit": "~3.7"
            },
            "type": "composer-installer",
            "extra": {
                "class": "\\phpDocumentor\\Composer\\UnifiedAssetInstaller"
            },
            "autoload": {
                "psr-0": {
                    "phpDocumentor\\Composer": [
                        "src/",
                        "test/unit/"
                    ]
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "description": "Asset installer for phpDocumentor",
            "homepage": "http://www.phpdoc.org",
            "keywords": [
                "assets",
                "installer",
                "plugins",
                "templates"
            ],
            "time": "2013-08-01 19:35:55"
        }
    ],
    "packages-dev": [

    ],
    "aliases": [

    ],
    "minimum-stability": "stable",
    "stability-flags": [

    ],
    "platform": [

    ],
    "platform-dev": [

    ]
}
{% extends 'layout.html.twig' %}

{% block stylesheets %}
    <link href="{{ path('css/jquery.iviewer.css') }}" rel="stylesheet" media="all"/>
    <style>
        #viewer {
            position: relative;
            width: 100%;
        }
        .wrapper {
            overflow: hidden;
        }
    </style>
{% endblock %}

{% block javascripts %}
    <script src="{{ path('js/jquery.mousewheel.min.js') }}" type="text/javascript"></script>
    <script src="{{ path('js/jquery.iviewer.js') }}" type="text/javascript"></script>
    <script type="text/javascript">
        $(window).resize(function(){
            $("#viewer").height($(window).height() - 100);
        });

        $(document).ready(function() {
            $("#viewer").iviewer({src: '{{ path('graphs/classes.svg') }}', zoom_animation: false});
            $('#viewer img').bind('dragstart', function(event){
                event.preventDefault();
            });
            $(window).resize();
        });
    </script>
{% endblock %}

{% block content %}
    <div class="row-fluid">
        <div class="span12">
            <div class="wrapper">
                <div id="viewer" class="viewer"></div>
            </div>
        </div>
    </div>
{% endblock %}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   version="1.1"
   width="220"
   height="220"
   id="svg2">
  <defs
     id="defs4" />
  <metadata
     id="metadata7">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
        <dc:title></dc:title>
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <g
     transform="translate(7.0217361,8.0694962)"
     id="layer1">
    <path
       d="M 60,10 C 32.3,10 10,32.3 10,60 l 0,100 c 0,27.7 22.3,50 50,50 l 100,0 c 27.7,0 50,-22.3 50,-50 L 210,60 C 210,32.3 187.7,10 160,10 L 60,10 z m 8.90625,17.78125 82.1875,0 c 22.7744,0 41.125,18.350601 41.125,41.125 l 0,82.1875 c 0,22.7744 -18.3506,41.125 -41.125,41.125 l -82.1875,0 c -22.774399,0 -41.125,-18.3506 -41.125,-41.125 l 0,-82.1875 c 0,-22.774399 18.350601,-41.125 41.125,-41.125 z"
       transform="translate(-7.0217361,-8.0694962)"
       id="rect4991"
       style="fill:#333333;fill-opacity:1;stroke:none" />
  </g>
  <g
     id="layer2"
     style="display:none">
    <g
       id="text3761"
       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#333333;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu">
      <path
         d="m 119.775,168.98893 c -8.84006,0 -16.77338,-1.36 -23.8,-4.08 -7.026702,-2.71999 -12.976696,-6.68665 -17.85,-11.9 -4.873353,-5.32664 -8.613349,-11.78664 -11.22,-19.38 -2.606677,-7.59329 -3.910009,-16.31995 -3.91,-26.18 -9e-6,-9.859927 1.473322,-18.586585 4.42,-26.179996 3.059983,-7.59324 7.196646,-13.996567 12.41,-19.21 5.213302,-5.326557 11.333296,-9.349886 18.36,-12.07 7.02662,-2.719881 14.56327,-4.079879 22.61,-4.08 4.87326,1.21e-4 9.29326,0.396787 13.26,1.19 3.96658,0.680119 7.42325,1.473452 10.37,2.38 2.94657,0.906783 5.38324,1.870115 7.31,2.89 1.92657,1.020113 3.28657,1.756779 4.08,2.21 l -6.29,17.51 c -2.72009,-1.699904 -6.63009,-3.286569 -11.73,-4.76 -4.98675,-1.586566 -10.42674,-2.379898 -16.32,-2.38 -5.10006,1.02e-4 -9.86006,0.906768 -14.28,2.72 -4.42005,1.700097 -8.273379,4.306761 -11.56,7.82 -3.173372,3.513421 -5.666703,7.933417 -7.48,13.26 -1.813366,5.326739 -2.720032,11.503396 -2.72,18.529996 -3.2e-5,6.23339 0.679967,11.95672 2.04,17.17 1.473298,5.21337 3.683296,9.7467 6.63,13.6 2.946623,3.74003 6.68662,6.68669 11.22,8.84 4.53328,2.04002 9.97327,3.06002 16.32,3.06 7.59326,2e-5 13.76992,-0.73665 18.53,-2.21 4.75991,-1.58664 8.44324,-3.05997 11.05,-4.42 l 5.78,17.51 c -1.3601,0.90668 -3.2301,1.81334 -5.61,2.72 -2.26676,0.90667 -4.98676,1.81334 -8.16,2.72 -3.17342,0.79334 -6.74342,1.41667 -10.71,1.87 -3.96674,0.56667 -8.21674,0.85 -12.75,0.85"
         id="path5013"
         style="font-size:170px;font-weight:500;fill:#333333;-inkscape-font-specification:Ubuntu Medium" />
    </g>
  </g>
  <g
     id="layer3"
     style="display:inline">
    <g
       id="text3761-9"
       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#333333;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu">
      <path
         d="m 99.289993,48.628934 21.419997,0 0,117.809996 -21.419997,0 0,-117.809996"
         id="path5086"
         style="font-size:170px;font-weight:500;fill:#333333;-inkscape-font-specification:Ubuntu Medium" />
    </g>
  </g>
  <g
     id="layer4"
     style="display:none">
    <g
       id="text3761-7"
       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#333333;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu">
      <path
         d="m 154.67148,48.628934 0,18.53 -36.21,0 0,99.279996 -21.589995,0 0,-99.279996 -36.21,0 0,-18.53 94.009995,0"
         id="path5089"
         style="font-size:170px;font-weight:500;fill:#333333;-inkscape-font-specification:Ubuntu Medium" />
    </g>
  </g>
</svg>
PNG

   IHDR         r|   sBIT|d   	pHYs         tEXtSoftware www.inkscape.org<   IDAT(ݒMAD.H ADte9p-. d !2	Rnc~85#ХoC	23Nr34K˶mu( I~B8rxvIRbǜXٹZ0O;Q(B18qHj}dflp"б:iW@&Hk+    IENDB`PNG

   IHDR         ha   sBITO   tEXtSoftware Shutterc	   IDAT(c466f 01(Q*!MjV分XMAn$Gq۪zޒ7YVX];r~O5tB֍xG}qļCUO/twf&R<fĢq	 >&VZ-T    IENDB`PNG

   IHDR   r   r   ݅}   sRGB    bKGD      	pHYs        tIME$S     IDATxڜyeiU[߰91ϑC $LBBB (2%jRHW[N8C>e-*X(
	ɔ$9SpsV#s8}z׻wΌ{rr(NQ#`TP97rsIQP@E{sC^L}]Eȹ7ycdi#+dA1CLdڅ903'} =sF/W?p$ǈĀC*`C*n@Zb
XWR߼ȚX3R*981n`V 7*)3d$Pg,V&RXq宇u&D*9ҴSq9R
ԾВb@E12ڌit9W?ܗm5fؾ@UgHc]g_^}Ϯm8;ZΜ9xϜaueӧ0i;1Im-%ԕ;B֌A"ƠYI9s&4e@ȱŨXaPU
)Xjoq)V]XO:2
%%ĤdQsiCD43	<BkbTV) hC$eqfS^NĐT0?;baf׬L#حߺoǟ8pcR9֤|=̽⻞ww=m̙8!NdLBI1`|M0!dj_#ffĮ!f1aXOx[!V%t-XZGN`UpRUc+*K-J!DbLT-ODՃ>]A|t:%wwXc'kfv$+JЄ5!g541҄"X#BA.XvX>{?ǯh38kCL;~ #6<?CoW^Y?G{#&qΉ*ٲ4c "֐U1Ƙ1֐sQq)aP1lu"HI *9@!cT5JV\UZK9/I
w+rVtePJ5cC&Xޫw'#VrraT9ʞ]۞;v)FfwY-nw]}ɮ_uҺW=5*1X[1"gKaDVpޣ931<֕alADk=9#xWĀƊ1x_9a+ok5{k"TcE5ʣ)DTu7gޗZUWFP,"G7JH#xgQPA4Q9O F8c܎oO𱕕F sLMt9`[?0=u<^=$YT5Y1 
F/K	c}P-*%jNgeW&rʨ]C9%`
[k.헮g,h&|=K:4pNLΊXbga,3X+H*5P;urNRK|Ăf3G
Feu:Stfd-7\z]>ziƘ;rm'byڎ?yȓ}9=s%1A{nՋ)7HsZ@cPMMu1ҧrDCfKKزR,øGW90ƂxU#֡
)%+"vxobPUbK!
/.4 !&R)⌣PʌrC'N [-^{ջ?|~wv~ *̆wuo?t<Z8gp!b)bYk,A1F0=XshV*PkǠT!b]<ƔT$9/;H3Xףsmg-K9bD .RCfh[X8rk]A"XS;bK	TIY1YrDӵWa+Tsͳ k&D"1%9vVdǶ޽}u]yi֜^0{/9{'Tkcb\Y	9tJΡ3%8grr#bWVRnDsg`#ԧ@49l]mnfVQrĈi2BU0Ε֗ʽTx#ksV4QΖ]XRhK*#%-
%!JThOZZcrs%;c&c m}~ߢۧ ր8CDR>ߟfZ\UcAc`]EL)+ Jь80\UT_DJ R1.{-}pj
ؖSjrZjT%kN0dV25X`J
,We@}bsޢ3t9SF`g8qFSGtW>oݸn+Pp-ϼh<S'I8fA3pƕ 9+/XВrΈyWn
Y]]"dHGڷ"U[D\_}IXv(JN1W
RŠX)5ڲ+5wTԛK9V;p8)5, ߍ!pP3<
`EϼkŘ>v޺iWW#'OX+Ik=FrFz+ouL)5dUT!>a%=[;&2
b	10%a3Y0$Y3"NӂXŖO߳񊠱[1B
֣1S8S>ECbHX2"ЎQUb$G9+*jk	
]HԾ\*<uZg+Í/7_ܼ+MggbnhS+cjg®!
VZkHU:-@i!B K!89`.L3F,)&R+iZ4!֠oC4c4BS݀BI)t`	PUU=ȅp]ѹ0znDpo_ 
!4cP!TF\fHmےF<[,AN^8k63@]y}:rڻ>}w`WZ$ HQ;Ol .t%@͊1`rWj9vH˪)PbJ`ȸ&Ccm|?(8Kc
]u0"A3)	"6`v[S]PR|"ʙs[3%BJ<UUQUlmn{&V7ύDQ)-޴[Z&FxTR3b}1EG-$Nt]H1B`8,7`\M%ŨPe3#ѾI݄&WZ[R`%Aă PzF%HYjT˫I)G_s1EB.ƕC5(DUE	A盅UB^СqFRJw"LJ&V&cf7:kF_\t	&c9u6PUU$XL 1`IvLPʍAhB0ܜIќKےTu5cL:04@E4`Q$K;׈A	WHY39),'М1C
xNgUJ6ˉK+ԵS*ң֕-ԝXUTS$eGQ۴K9v@sAtDb0ph	!3XXVvqUr9D&FUWX1ҹFki'-ѐMqΕ2tU1h̨8v
!VΐaIbX 51dyf*IAMc@c$%à~jHZ]CXXҫ5m6✥I1V1ln"1QaV\ k<0e6H"^^"#ԃ!r1Xk5+lT
n0*;͔A]#еS~[-YrR2KKK;yC%egp5/§]O
_ٲ2s?|x{*֭_dm̍DÂBJdkr*lœRpCH-V6&R	]Csx[2LVhS	41%ymPõ@:U2*UԃXΖsfI)4h˼1!V	VcmXVѐv:E|,MXVkŔL+>xfŗ|wsU4yZ'lϬۼu 5׿,7ٵUs>éٹs;K"YsuZ7dc]WR#Y&LiS$,hlPc3T!9S6t!2Nib&Rac) ȁ.$(hg癛qh,XS1 C	qWh8f#UeB`b͊d(M,SdS񼛾z~e}2 N%/hmzjyoru/^;><]{yjkؾ};pHbi!0[Xؠlዳ9rWC$f6`Qg*.FR΄L¢9.c<l`D̸ׂtmUɩб<i*+|1cB(D/d^eUՠӦe41"1P{GQ^E3AְԱ79탧T=@20LEΛ	aW6|/~hWdM̯[ X蹬L&+j|=@u@҄hJQ	N[$sh$g%D"mRbXW%g&Zד$2ԨBJ3Yu=(s8cH126Ķav8b$2pb;?@r&IY]S!59}M̙ӧ8z[v֟\0FuH^jBdk+y`RZ&7JC2ުz7}ٺeK\]Hw@	&(I))54cFP.DJ=ꀞVT`z6S7(!{ҷ-On. &(,OrBe1qjzݎ%}x33ns*!+,-/qfvX,3!b{a>/	eBL 5MIצ4ˮQ|UatmߕРboz7k/bQFyCD)^SS5B̆6ٔj5Oxgv@JJ״t1E=Z522	r֓aNxd<e4*)oTI)H'*35b"ae0pѰ4Δ,Mi\Š2$U9ɎK>ص} 	nE")e&KLW8u'|GƧ:L̉'Iei.ndqv]⦭昙`ljsO_nC{AnY`EZc!du-LwbQUjkޡ#fG"O!^[+/%"kє	]kL*DӮ)CefFJL2h47Z E&GLC ,Yi37|{~
P=ZgO+1Y9{9z	NO<G#ՀŅyvotʅ6Gs榖&$L'+z ֱR_v.[w0wɨk/~O5nȜbEsp1%]"@+Lc-W/cBL6D-oۊ(F) )gڶ#Ls6̌P%@Nᠢo:T0X^3;3B]Ȫeq\:)a2:}-^/VQ 

d}|}w'gX~=;6o`i-duե\NrNu1Qeeủrxx~/O6^q%pH@T#_]ɧw9v)6ځ3ӦE1jCj_hm;b.zؔsڤO\MHIfB	h/;
mWRg6!d2%jxb %-gOf׾"#dfFC,t)56->׾yiv^4TOQkҌyR<~779Nٴq#skƌO5	"*52P~&1P1[®{v9yss5gN%6︀s^6mP5bpR)DHQhP\̤\zRcȰlS6VaJߺŷ:#m3MU(+h-2x""
ɡu{/_~vlD(<ox#lݸuLYZb:6M0Oh-RɔtZ!if]GcBb~~{#?pv)VGQy%yƳ9?uT/ +Z#&Ҵ-]W$/ʬU>DN5!3r㷜^?l֚zˤ\ƄZjP&E}V!H$RN%W-T$m(L"Dʉu7Ͼ~? 6=ݟqz+׭#+,,ĴiI(S4MCʹYrj)IPh .ZXY^&a&sj^? idp~* K,%W]}{ٸi9vԕ=JN麎6)mS%^8)y$ĞTbpXq㷜Y@zkv_wϬ\k\HJZTcua Xs^y{b?{}	_enqI!5t3Ǐq'~C}y2RnD҅@NzhQ-RWWD)mJԆP1躆iS^Jw/.+{?/g8/@m岫gwslߺkkYhHK?2^Vj`1)9b=Y7;'rfsvq.LA$edzU|:[ƥ1遵ESO:ݗ_mmQm{pwǇi>>}I3aڴ.
^jV}Dr&['-T׭j/eӶc-("$1As,<O<cKbva#"-eAJf~qKy=w|fh4] d)3Ϊm%碐o^Lh,[ά^y+Mx1JιwD&XwVhaT	V1)]3)1"G-qt'v>]P|>D^:Ǝ[)3LLеfz[cȥ~ 9F,b+uٞ}rJ<f)J_Rv],Ņy&_cEWa/%n.ߧԨ4EbRJSQjXkD ;	M;-J#.2]ITt?xW&mXO4o
zQr`S8?+{6AĞD'_9̦9uzǏN&FXB uXО5hRYBh%Ɔ:r$G.iVBa<pinH<
?[mRֱ55	gF3Bt8+0ROD65d
m:]    IDAT9E ,<#*)]Gϒ7*XAi8ᆿXax̙3LZ:>c$EQеHh,fg<b˔@2͕f*Ex:Kkt׊Y]%T)Rm WZ+ˌ稴3{j2L/Iycl᫵mqƣ)KSmu
2Hw5Y!H]}-kI]kK0#[8I]QC`2FkZqvHh[?h~׏u-׉cn#mضk;++LVəΑJzũhĎ%A"03d20[Gc.s)u33T^b0@b1oE
LǁUF3slټ#ߦDVBuӬ̎%H<2!Z|@]RCk[ROH,`|ouԘzV&a{38p[U\v!2m#m4m__a~1BU!p>?ԡ}ܵ*t
1c!ۦayy	LU
2BF*AsQ^JT|?}q/}џGdeyp iSG5xӫ{``iZEu+\rdpTlQXay=4PW.C	B̅d\sj/qɥb]E?YEGRzMbċ-W<1Wzu&v41?.`	mHJyΣk,J
=~)úb>]?Ȏ_=Wr8욫BU'.~ƳyߍYm~O`f0DlS麆AERQ5]5}F #0|`Ӆdӎ"&sVغB7>#S$#ghچ)teVxȔŎř;t|z͓ѰV{c{7VzԔzYK3;'>;l`CۤAĲ<1/pee4+g$S*KOe#)FNX⑇Fnx^=|2?_a.ǘUD, ૖Ky/PH$ao<p\JL2:.Tx+J=f 08_a'b1rB[,1^KE!ildaı8[sS_ZUU4bqjz({4ӆ,%1'G׽]{!a\ᚑ8E}6
[g2mе ]lƠ*KKK?yz?7~?Cߺw䐨ح:>H:f<o~om&}_|r1<pì.0i;fV*)vLCdi<a:fgss:*ATEk\Kq
s$E1HnlsH)5a\@qU	I3Oܩy]G׵$UF̱ kb#Г*8k8S,rmognvHh*O''>ƶmiVx)kWL# l:S\z/|RyAx_';	GCKʃ_?3??b$@Wԗx~#C{0O93r24m9#ض,sF>Α}zsϑ{Gi&T͈jTN$I	IRW#j)&-9oCiB?k/riIJLz_EGl}YN;EW>W]D)P_/nLv6fb"i8yf'۾7ʏor/p߭3l`{~Kx[~g<r7>h÷W?QNˋ_ֳzt̮+I=(f,^"n3ǎa0mڒbǠjy0|эHXW~
so\|/IzBp_ʴLrHV
"3>txړfƛ']Dmr֌cDJۣRQi\}=o7\
[O/sE[NL'Ł;:p
˝7~y杻9^ǿwXzjϿ8	Osl}\i<3#~tr'n"'q~mo S<ɉ/}p#6(?Eod*޻3+3`41겛rffn_&׼{:i{L~Klݺ"cs`rUS>f(qYx-˓Z}u7Y#yrv{=ӑqbΣ!,(zL~I:4lxջ~Ø;?w@DyˋlB̯_S0ZzDXܲg:UR4gs
9e>qo}|s\wP{7<,lfvq7XrnWL, 3.3=hH%ر%~hXElU S?sveR]m?N\##ܰ档v3Y;o^iuA'eTt?ɵRz>kǎ-ss^w%kT(O~WؽcuMc Pjṯ#Ǹ>͗O誫y;577xГ(g	/{;M+SsΎﾃZz+1ݟ's[_ClڹK}<}_,/1Zhg<&|$
))7i|UϽVѻbD9+1~ziGB	dx4w֛W&Sz+/ԩO{NS=z'Yj=/rsmܐ{z7l0G;g&ʗ|9IJe8aΜ:3^},nZ N *~kndfn{Yzbl;A\r-wpf^淲y*ו	]׿SOߢgذ2.wY\-.M N+V,+zv >߼!1ssU3)泵Tc#[w<iK4ҟza0Zek}h6л]|'vo.E>я0L
ʹLRGa0q})N=$x;.ĺJFPehŭ7r}~|cI9t>j{~ [`'
DX=$y.y_?ºٳejTIG1yHR	o|7ѵb.T$v̠~g3b.AŃGoY7棪ʴ,S4
[Ssi˫ly1CжC
QsѮY!ݮm+_P%Lv]?%x&߰|W앬ۺa>ejHY9l4T_ষ\=+DdO{ F<h7'>fDQiv;a=9 gˮgѵLEH=,3vTpi/)Ƣ@I;{Ў[S(xGZ.״9?, N*ʙU.|eR[;>$ĮFI)̀2X:q)׾7q>]qӹ_{>|O+n|9<^rQ:b<vW˷7}<1/x[8py˹e4{P<~8cj¦~E̮'Gb*TFiYiۖ$B
/'i?֭5L&*F\t٥g0CNOX-i\vcLqkG@$gtav$PH9F*3X|e'81hHlݵ*x/e]br.'S4,%(t#GOrz9})^23×|#ŋx%v+w}3xb/zkGh'xn*zq1;z8~p9:Q6Ɲp.ndE{v̮[ V
͑lFOv刳wFbuź! [/xWaٶs7}I9G|2dƗAyJZ\ݺ[֤Dhz}$Fz6UcyܱnN3`yqGՂH+4s	7yrơ?K|7C(3#^a6q!^7avԧG?<>F.~lb6_k0;q&VNp<peM̮!-?p3V?3/=)rHl QH41شcڑQyHPr14)t
)hVbJĐH>յN刕t -Xwl]p5G+an";h&=ず>N5I$1k81"^G(߸/}rAn~Ͽ	~	lt+oFX j>x짙.Un?Wen0~͟q5o3'/%߄yY7s5h[-dcY	l9!I{MtB!8$dh0xGlY5ZPg=%ݽ֪jiUoO<#׽s>+jJx?B+˩'4"OB9LYQlڒ($]DrzM9m)DRL4uE!'b82vaV4piXw>rݳ#>Mx
ȁFvpK>k?	Wexǭh}q{~l=W).;lsMfOrϟ|+o~9ooť]əO_F+RdEb9z`Iʐfuh;Sg,_$u[C*B6h"!?j#J<@HaY\I-Q*dJ6g-PQY\qT[ڶllL9З!ֻߍuEUN|=].</z͛8)_W#ibȫ57qM7q扇y'8~oʗ(FT3gSB!#k#|	bՊsgೠ@
?jJH)Qo"v2}!SD2kj_ޤČQ4vTuqTBv LgUˎOxooc茼^X<W|?~SnַΟyՅg;rR(5R5-eǸ/Kyϸ~2/c )UǕ78	cXn2[2ȂF{W2;H]qjJB)[/X*:YivR3v EngAə&>U=kX).5 j9Ka-E86c{1~'~wßصNPE?|w.xwny밮YGSҗov?o~wo3ZsqhQD^+I8g/Cơ'v<Rd$H1:ZM-N6b"G'
7mNE1R寿Gu閅TD=Rٺ BPZ(S,d鄔=U⣐uR"ʙ3n`,GbZ?3o{)9/`eE )YßiŒZ0ta9%c\EPq	v"}>0
3rN釕1"]|/)_L6I`	E=v|)c%`ٴ@BN)y95/B_rM\C_)hr<Gب >S+:L+>+ᶷ*fe_(8tɿ7~G=o[ߋk#~C|o#Ry
}i )>j/fiZeH3=)Ӛa_I\gUYkZ2Sľr3zi,E?;CȢ#-b1\E`3eU;Ֆ<@P`cA-9pp'esp!.
 CnZ( {q!.r|w~m^=oqNBUե7o{kWp;ln ;0!2uz"$uLU,x
E6lsf_dɇ+2lMR2:*U!eXvL+ۙq(<KKG?xRQމW.RMN0MF"CU>x)12\.S\v=u/}n4mn*tOU;rȔ/owo|`kF@҆k߃~h&m?I4hsV\(p:YqQK0)1hN?rO~YKbwR ҂b7rʌ̩9>$JB&F:ʂǈb~8?! ׏C/EsRteK6FT9(e6ۊqө Cϵ/>iudY@gzݳXSg9ƕӏ>ʟ_>6lqG]kto~7۸;OaIz~E1C,uY'T([A҄QA?avʪ:4=ec1r+"\yudyx~$i!j]8x@!XMJbd؊B|3]߳\vm.d>^!eM	 J[9!xpysZqՍ7WRbmTV1_xmsݻO?3(W9%׿q+^Y{!v,kt_ELUb`kgG>7~Y/.p쪫n^w)zE)EbC8'I6H~M3ibskNA0oV3,w>,WV*Ib!ff\!I!0atuUiqPC*$IMQH%llL̓}n<fTe`%ױ`}GZ	9d)
оHuL+]0luo}#GndgKy	1G=ˇwP1I)9I_>h.y{%ʺzEJgHS9/%K?B̎!$Ƙ5r#O7xpgN?hN<Od1JҾh?Qa?H)h[d7Vj$9s:gKLRNmE٥T16<҄{=YQ    IDATs/1A'ڠ	Z!⬨
/]..΋ %\!)yY/;^W9go}5	}~G?EvO>ŁK/%ov^;8|q!g])BT[2uOiP(Z|N,nmU/]Q:A QjOwW^~;#UՈ)Nu"xNYo0(j{"P+RBW,9ըKUfBdkPŊ'y<:0%eoV~|Wn
3'1KD}dGiKÀ_@XʞS"9`ц0iGȕ7i<q5o>i,y(1T΀>ܐ`8kVش#+é9o
\J
ݺA5Ś~g\($@QAZ臱=#!+6RLSW#A|9Q6lx+r7
,)Xy[_oKA_$7I~)[[aiEc6EEog) S~.:ț[W|;OP736^u+ǯ
؅"sTyITa4Yk-5Q!&1`sk	>귾V{xejỿʡPhɗTJ*y^I&gx?N mЌIc[(kŎmm=sSW>9:!+#װzL[K R7]\rElc|=x5䱓B:_*%TV9?|l]y5W%pS²IԂ+l\W$!XBuCHRbLr([wydXǶ!'vvW<|\qLӘҦDg xI_SaN6L\,`9fggoЂDJGu[΀C&}},W\rdR_ /Rq *E֙y Zrn2Xyczۛ:~mrH_Xf.*G!FAХ3??&2FԆ)9U	E;LN~8m1.!	(|J37'L'y'qqA2^&~BXg(kKLbf.a4>e1;*Hi>qr)kcpb+o~v&]k%|30XmBHUUcbFL
<.}u(+v_AVLI<,+6!.Q*rojsC@5B9{~8yWPd6)R>J*Qhvv\Wr'`9@5:c \}я>тK5Ƞ3_o="FQJ-k(cR7̚@mGK}'wEa"t}w?y𡓄a TFbRoSetb8tвؗ9>$(=-ZF cLRk=ENZAӠPOkѿx#?u?[ܠ2 13zd,O?zw5yaQ5<<~=6b`T6ɄiSQ)6z}fQ]SWu5}@BFˮ*eMSUX%)k*TF}+;i"=7v=x}Ӝ)zrLt^jdVΖab7gݏL&LBǳc>cWGŌbL:ȝ^&,:M`F>Y;LP}E^K\NLjK5@L;WW^]s	՚1)B*ɵh"	5M-	F!2ʗ*,U]]#X&eq.p38#)0F+W W30_c+?/o(?;IlM6[:HZ`МR9u}ّMgg-{DZHsȫ /ҟOY6LbS2c/hm]3?[?W}h"5|l{?qj|^p0EM̆@68ǁP金9Gqc/tgQMM[IbEVRsZbtm؜H9nzLdgQV#3[]_vE`*Ge-T1xֽĥRTZsX\8je7܂kp'>\%rPOOoSL5Ƒ"~޿U^&zྒྷ|	TKCΨeZ󳿊ϠufZ}v,wPb(ZW$cmV)>d5G~Om4ӥ(+ErEMg1#]?^E8XjС?+xMQ(>~|o牻kD9AB!E1ĮIu8_o?/:!.T ĺN=ˡ-]EN؜5a`FlRê08sN)5?8ݼ/=r)?Ie<rյ8wmHOF֝12]@iI/Tj*޺FWu'مb(UnĬQ"絢m[&YKKșٌc[-O5-ߊ!X=.;~PNdRX2UDeٛ/!P9C=clnM	A[]8pq^}3Wq_-ñC-cjխݣ=nM=}׋T2*qe>\T=u\~߱"'$	Y<;~#1z)\*
)˽=%6m&S,#o%rIgY^qE)DF8'd3C7Tsts!Ə=vF[bM=.ף^0ց1w?$A$-a=
)@S9+UR*t%ɇL85acS/~V|#L\vAډ؍ݚ9u!mH^cHc{I$(V>s~gV].vG4֒f񯽏',[EV@,-ATib=|%f*)XsHk@pGXRqc;p45s]sRTc2`)|c6)U%y6i>w5R=Gr%y[⚛_0l*iSA154C+,gUז+.?̥Grǈ(6&̗+vwwǨ֬YEXȔO<6z5:rgv${)~~^{9_ZP4PFb_,}1ϖ$+l4{@}Us(i!&ѳ^Vca:V5U]A[3#5l~[?zTO|۾@29yt5s^{FV"3kjJ{diJ!XwkIFp~,F?R5S[a6uj1R7T8U^ZMc$);wy=/:/{Mm6%mpn?8qIE=!KMuI^k%D<gR#9tสt]/}h3/˯9v9!$>mrlln0NحD<h6&u%9xBsCt{~7[0FN*s[7!B聆Z2m
),$4ۏe#+).j"ekD/JAa+KH9C)wx/gfom_Or/(E=j6c'IaQX/!KR#"f+B]$W(rdM뮓+FZy#QNw@ܵa2iM&"HI0 9:l&FI(b/uےBرM.<p%7cV17N@\rozS9^2&d*c1QW=]u9kP)2F躮'QT-cƙxr>EG?:0ȡH4մWy+\r!%(vߜPO)&$[ޯ22ݺǇU'ƏPRsc;}R&3	MS_}J¦nH;E%pnp-F =#w޷\u$vrHCW_mo}Nk=b4LIM_b8#X	Sx舘T~MFZj0P
j9}GF+$Fʙ%7NϿˮ؄՜lldT0{y檫KIYjș,5y񇡰/S̓k]%`*'3<15īol*F֫qiSŤ}$!*0ZªvU%+cL/^Pޓ'L/{먷NCOwa=I%BhjM]£S9Gڵ1RU[cIKK.R3Z|?bi|r7HqA+4SVu`|N^^<QZɐ6>Opz'TqdVX1l\>Gv; #ԎvE-Wܑ%>{O7$bdkDe4Wl:'vwg1->'B\'BdiGko@U?uݳٛa+GҝWɫ̺[1SWMYB~Ǧ>`vwUm;s-7P
Zj͛3΍|7+~6L~d#Y=U_'ҾYTI,U(a.(پ(Tۜs#V'n5DI٘Lu;ir1V]W1TrlLu;!釞#Ƕ8l
C`<x/p7={ۻF@U;1ߖLG裠~V2JKH6	fŊszoh/NX"G^gBY<z?dsһN
%ISsrQ
~Yd 3ڇ%e(	5Y=o :c;{MZd?9H$czIļQIV=I$*|#mS1T<<, G<rUW%no[o>p[BPst@TF\(T*Ւ~tr[9szu0Tҗ[қyۼ-NB(ba#uߦ!p{^rƏH2F֗:VJ\\UkQ'1Y_bj?Ȫ߯*ؘNjrJ,A!!HT)]K 鄦5ł=Dł={%:03V^Wq`}'~U"VKTsUx|'O<0O=0x'Oe9s~!&<sFRdzC<a9̵/usՋ^5/~d*
pAxc )ۧp)w}lNC5;;P4T>dF"5`P	PZb!z_"wCn(B
rMa#xޕ0tNҊHBbnT!=X&MY,x?Ng$˽=(QrlmcW}Qn|m|ӫ_P$4t9.j_"^[ 3'ٹCXnRqVRcduǏqaqK1bNKD	R3g.Q	WO>_CvzV{2sԌzTV`5˾kZmZq(jl9g,:s!)e(yY",1P]LoDXkpU[xuJo{9,U݂X.g2m%2!sq`CG/af<<y'|?xPn˅,>(eX%:n9^~5ua0=$--kr@+٫kRt|r?IC(e,zυ,KTS颐R/Iۈ;R叉L.C	BN֢TGiicKs4;8vc,>	\VkꚪrFe4Mba1_\.1RMfF)E3iKɉbz66t2Aw|+׼_~JڕZmFoQ1R&rH!SYLJUX4PD5Fg-JosC<I=/p,+{
"20&a2%rALeàhGq$^"9U WΏhrF%MB@ÕV"yi*ˤi)srJ-!%5)%I+IF3[q/W7=gq9rpنFmvC<gR^[U/gئNfjrDu'~.x\h(AW0~~<zi̅흲=)9tLdk?:Gk2Ȉt$wX0zϤjK4JVEx`"xw$aHMkk">8MDuU@rdog0Zh3rMUQ7r!!Tc1_03D?ҭTV4)*6՚p'O?>q5/x˹P\DfeYރ(B++hQ4@Gt7)52a{Z*%p钨Bn$VMe\'61{yAUnRL
51JulªsdZ:!(~ݕ~$bS6U5RIaGɔtFzMLl6^;)${mzѱZp] >9i0i$5oR؜I?{Ͼ79r\~	.:f^!c9t7@Ss_?(g9S}`65X8dq9ǁ&Tރ2tuLNRvRYsQ wLyP嬠ˌAQ&gr[8A|&0V+,>ni0h}qV2Mq`UZuUb%8vAjŭ#1y6f3n2!CKUUafBNrE"L&uUQCm`yk<~$E7DVNjtZѭ2ichlyÈ1wNrC"z.҅|d6XQ1'T\L8"	҆TgqVDn*.ٛYFOȓ}D%wcZ9gpqD*EjX,nZ&XV6,12L&3VXkkbfblceyrN\}*XMXiE#McZNClkcdV;bY[,0B6gZҍ	W9c3HS+񣠫SLbt255!&V00t='t6#e\Ɛ#|1kHA<HUR8Zea[%q[(I|Ѧn`+8۽]8PS[[c¬>0t+9{?\MN軞U/..Tq7dRԭcxD$t?GzI30iU/_QږZ=|$sTqde7bJT10kГF/gIbwbC04Uٺ^,y%'e#'D0z//Қ#>f3-wx(%hublE:6_  IDATu:s(pdmN\Q"w@SUTN2'z6~LfL66a0e2a"(\U]O]bLT1`$SZoq#'DH^	j#V5뾗8*gƮU0UXcH@Ӵ|9d2neB׌!3EoE	ࣔ}%Kh} -,?3Oɰ9_o׌à6Yj3<ŜrA[U41]kfı'M*ڟe>S]W$YYŇՄDGBe*$S9'nCGBd:KlMد%WaD;-Ƒls!ɄzUj%@FDl1ܸː 65Y/qR%E>*GIqY]s%HMOz t)}CLgχLlI3_v={Cc+'4mX,CG]5To_V*GNFTU]r1n1Lq\-I%gK1N\S%$)9WWED+/;=J;!ZV1a<pV5,1I95ǔцnDL
 qB̙ʈ;iUBk~!:|"ʔIn\XǓN^3OquKef#LI3dvEq4u[n'=UUՆ3FdcYukBNXcJ#S7"g-DqGIwE=x/2) u%k9+h'a3uC"ᇑ29KX/j?a +0cBk+W>~*b \|Gʒ8gHEd@F/8(wc5cJBTZczV@(cZi_zgƠKQr/gΞ^jΟgwoxꆔ2뮗T	C5dlʆKӹݘfZP4#@hƑr)KB[@8CZxyNEXℵ-\YLXi#9-|1UvUن}?oiVݪ$e~5$✣EiqrPdLJuKej$۹X@N>`I+zXv8N.Ù'ͿsH?k|w^-rL׶4R]%h'UþW/Cyu8XSZm)GʒB")#}?`̹$RFO#! ϠlZBX&'c')7)Kc
Sd);	Q.b8W/AʀuY֒霅R+y/"0c#J[%JVnA1O?rcOg&}F0!C._MR(%wCd2Qh&$w-[[&eJٲt@iLbQ@(yKCF(1CJvT(4 ~%Bk " JIaK{ǢpΡtjz*ѢY
Wt@6JRiOLA_E#i~.{d2G=[k8]By\*%&	 G~]L&]*GS	-OL0F,46ZNcF)DJTUE@Ӎ`E V¸	93 JSD(hQ-lK;Zs-}6hcA̽ҪY-W)gVuPMQs$f9BAɥ|4mc'eE*WFC#>r*p^59wvv|Ji5i[*)2v^UP[Y\rb{OUIG9$5)bJTW1F1XkBu݈A11Ƚ2Xr"躹XFba9dK[^O4ŵ0U6V$~BGb~-sŊTCV[mɅGNp+)`O{@ ǔԩuBirjY}'otU	qYI<maݓ{Қb(d礒S9%FKPf,qC)~$#KR>$qXQp`K\%1DⴤK"P*ZL!""F*^)Q-QQkIcZI"Oq@!HrXx(dFյO~3[=eIϏfe,5!ƧvV%gRR{9ڶEi|`Ft	PkQ9.^p}Kb,o֚bӇͤ`#Z,/"{U3#a eAyJ(ORf^ڂ,8wRrUb D	Ieʋ8Q}m]óZ%x}~'!<!67`/z ]!vֳ*E%2KiLuHR&F)5rS&x㆘:'Q:Fݱ2&i!r엁TrqI֡+UUޓ$)al9+Ƈ 8|ZRt]'_7R'NjsV
:rjƘZf26o X_LzY~B窪ȴQ1j8!K5z*TeOWoJn`=
<)FP}!ֽ'$001iO~=﫴cB*Ywޜ3^Ǖ6Ie -ƞuKgNaTuCÈqdE.0\vrIэbf[+WYuWO3_xfgqw̓e&nH8h_ZlHoՕ&%lN.d>ZѶ=0h{{{,mk0K4cmu
iYڇ{]2]}6p{sY5XcMI]{/!p8v8chonȯ.֕r3UIr
X51j=Ӣ{B+G#ΰ\.yDl[|Yr<HWX
&dCUs^cdw8UkXp	=#ڳ|l5M>SN.n}y|q~[@έT5߀3fz{YZcZ_ىY,5bC\4RNQ}dTaG!Vs("şR*.S#cʔojv):e#krBX
8k51Ž1V,6FG@f	URSrCL]?NSJp׃_&62:[~>}QG~`AWՎ
ؓrG#@^FP,7
G06y~@_~jJf&s`a߀wma	tVjK    IENDB`PNG

   IHDR   9   9      sRGB    bKGD      	pHYs        tIME 'w+(    IDATh͛ygY?;ɝr3s!B$L-jŪ*TV*HQZJIHad2sr;7S\mWZ^}vd?7~[^ZJV^'(%"9k!HHcDb@+Ae9)ukO
2@$DB@RjC!SBb6W899}1Eδn  fyg͌lll2DT",ۖ#*
J{\Ca,6ӈ("Bn#5>%1Jȵ9U@+Z4my1ymw_<ے`\դ?klgcgD41D~Fhں*CL=.E^EaIFC BS;Li !RuD%TuKY
kA%v3z[ǴVJ\ۦ2+d볲wp}Cnz˯2(t=zsk^[?\/>yEZ"OJ+IB-F	$eYbd9ܢ1y
-!2'5fX	1tgdGC/5JkOVcRgEVӴ/nx+=~ݷ߾q/}ݼgG}4
)wH<ˈ)CHh1FcIVi$J. (52BHhZ(f4mK(ȌYScAk#
Qc^:|\/z5ğW j~}ٹ+&ֈQDiф %B̐sSN-uV@(kIa"5{5DcEnR"&(&&hۖf"h@iiӦ^a:o痗ГG+ hΙ1%4-)
\̚	!3`lwmh!ALhcNKHX!ѓ$G5QZCJn"h! 	T&31Z#$TӔ1l>p@/>3ݷR}(%F+Ci!v@)oAYb 
I	  EOBKhMBA(Q݊fx	%EA	ڐ)RBSikj3+Y#((!){VnW-M'ILF	RIgR;ZI1:zJ	=T%mwh]$K<'E͘ԳiWyFkoBRV8QD$zB}ĘD5RBMgt:\sOXH}Y)P$ZOfef)rKV55Hk<gBVǁs.,,!dlGӏwXZ^!	(ijZP1>jFwAF	SlG2Z̦yBT/zTZV!dJB@jFk2IiՁBO;pKg(@×_
T5_3];9\@Jw- (I4.0mZ<((mHn=;q蹲du]~/Z`c{mSҌ&Akyf8>_~W&RuT,)9bT?#<JEDE(ʒgŁ_N'ÿ\nEIMBжyJkP$rĤrMx`WJZ-3(Wɳ"1%UK?fx/ĘfxsG9CLמc2`}rJ`aW2`nt3cJV$Lꚲ1ZQhMLh2c:Be6jD1A)TflF,1J@JB#M3ƼUidΘG>i֟~X	i _(I O
Csoa~)_|O]>zI(lF4(V5hm([e"ɴγ="Y'OnJ+BYK&~QS͏sHBd_yϰ+ɐtN FYS3<+вpsӏ~s~/7'7.o䢋Qx<ev%3GO	8CLzy<|{n*Z`MFBZi
	Dcry{I)=yR;4md:H!z$|DtiZ5s|{~Je7տ2&cJk34b@+M"2k(s7n+×:%Zy>pkoe|ŋI)PW4ш(M	%BtC/IP)chE#9ƣZd~_|?@C_hp-" "!vAKE[)D)MgiiMkXŃy&HR6c4p*dR7-VDJ9?m|9N{hR JnooQM{O~Z 1yȔh HBµ1Q7m1|4=)1(dZfu}/{|/a뙇!fuUB!Sؘpjfc_.~<5.[hӆD=(_3N2OZߦ3ZDh*]K:2QA`Ɛ	ʒhE׿$jS-Jmy\S:\{O^[c\|-a flL01b(EjZ*o FNG۸[I	3^wˋλs\5˜LVAn:k<M,#(yOc\RӸރ=gqMpƾw6go3_GƘ<e7Lv6}cClM߃2+t\|I+dQ9>'~@ϗYŭ.&Ȯ(ҡD}t<i.`
zmzYpk䵯Gș_p}#}?+9c_^.)<;Z}q%/Ax[3(EI|{!e[GDh}H=~>6M/+[Ch@R#
L~V,6||ѱ'IR^d<앯GsY9t!cl|n'y37\υW_ó~/Ɨq%/IJf78"p]w!yB#gǷc<a:(.]Iڀ-Y^"֏e2c%3Z	>L;AhɋX: x'^_sg{~k?·_*6Ngo=1	F?+{XY^C	"*
4	0Y4F"Fm4y=\(lV1X%mU3X9m:r"Gx\p%7>r;<..	xs,Ɉsrknm,/"g:
zYH=sg,wAXV8;bM")M:}`4R5UPHm#sP$b1V	̛緸z?¡.s6OK.~=2\׼s.#}\vL[|c=2H)ҳZtXʲdn
u눘ऄGt`Z|x'[K6slg(Ҿ,?@GhUWS/_'_Jzbg׿h/L^l}3/7o!hWZե CRL"%L_͐JI_B;OY\P=]g0WFZ^-WbϻO~o%ώ)Ko>sOY^3W^K|6mMR(cvPJ(<dɰHUw"(cd>:RI2	c[{?l׿'Y9s?x?_ݬ>c*:7haAF>TUR֤]s	Ѵ&Dwv"ňI	b+HhҬlr&vFLF#,-R~Ͻ\SoE>ͬٯw}99Iaѡl	ȗʷ\3~J]( ou1vwxO#&H]WĀ:Q(kq<Q4dl2?6!rz}kgs.xK8CLNv6+>_lyMfƀ2P[w|fsdLjVy/.@JmyAiO#XJ(JMjrkȴBIgufU\b90y[l>?/z;a1U7?y'bkl}z/_:_J$BL<H&3w%ӀEPt-#صNXY-enѻȮu#nU={`|
M'((+n@eY_~ei~rz0B@K'h}HHql[߰9d6$bbuJ^5η݃[<w8^z({-D7]ȉdZX{I֎9piPFhrͣ'X:XUjd9 D&6*&UC9X[	>*8zbTk;8O UնX[gsgx2m]y<g+ٷg{>1|'\{c{VEe<'I+hqyùc~)CK"DK99W&5g~@EK4S{OXYo5*FBP"(e4OĔP)J(eW7VBg?9,@?mz	Fd65?hBdI|DlsƉ1-9GrM ӪM~g~$ a P9L54ՔEv"L%r2y9pG፷P1xus>
[f.a{rُ8.vy讯ro&lO`m2ApV!ư8qc\#o7\	e?cs8%xҊ,/ֲ0g56tTL^~gS"ӊ̉gw-*&sב;~nzT4)DF
ZN}$p6O?> a$;;lGچ1Uͭ-q=7ߏWiIsǓ	Bٜݦs}VQ¬hRgP]*<.-^q)!۫sJcRrؚ\|
-kkՌd
)2zEF!ԉ`g◘YW{ɯ*6;;VuDQfǷ^v=[ǳm4sdF#7^.&uw5[W9J\q<''q"zceZLGCmJJGY۞?b.!*c+Z:	)&xT2ڼ@+u-n=wy+7>}/_*Y,3zg;am-!Aiѻ(FCk4;#&S孿0_*8&f
+z5M;VhmP6CH۩oӋy+['	sgtdk,hexB`]_˯a"{WǾ A%_d5!$,q-6ĔX`<n9UMy7_v.H76%׊PJ\v}Ϻ;Yz$}Z,zF$kayp侯S,elh)W^ͬ5o3TyN!ts>V"K\px'HQDwPږ-tS'Jb$DL6v "$dJqdM_{-sgZ80F[KnsEof)f(Ҡdei6X]R[8ha0^b{ud:e"Y/c̃,Y _u0&OZO|x{|x{"hSn#QZ
iږi0i|g܆3qo4>x"ȴ<4zLFC<g2RQI	_	sWonhX>&P\ø@Ahyg9l|N3acgB"n6WVSD445(EQûڤ;UU|R*Mi2g{{a:/T
\CaOK_9pޥY>c%}B1g󙓜|iN=k<rhc:0b(;ӉDJ鬦WX- Τfq-;cbXARƅuD,Ȍgdecs"Ec</{HЄ-J&;۔Z8yjc`}6ǾSpe8D:sqBGHJ|L􋜪n|1MfyK=m۰
$NAGB3SF=eyRa(Y=}m,(;yNBalp{Hy#mZǨB1.2M[3v`3ڦ4&Hx36Egk4+PHiy^dc>?i~vIWӧRVb-zE[ee-фHb)k t`ЄHI1kiLqR?&D rj76dv{b  !xOMoVI#(J꨹՝:i+l4-ǎKLh7R("@d0krkA񗘄=Ӻ;@imv-i}m[<'bk4B8CumJ\"I5Y"0:5l*ɳk/VlEl77Sserw0ڒ4">.Zn$"Z[|Hp13ALxI:6;eXs	URO	36&CO 0޵>:g6RY*7MsZmiBJRO{TTu~pBJi]k28ZSdR5 BQdh}dV7	eJֆJ"SuxS{Ut#eMz8!&Me"ƦM)tFPmm=6Pi5RW!
y.خ|	Һsu!yZqz/	f$4gԷOl70id=%qݨ6{Kw_fJ+|ՍMaw;rT:(X(MVkfń 1u$kiCi0m=n{GЄDTOokiJU]I䙍ι}F<rr?>~ugֆ=ƽ,]}xsN}HT5Z1#B۶Ѱ[$v nn\}H4$mC6(EIY^2*`4ܦjy*?~c۳o _A{K&XN)4p8._-   IDATzХߦΊ@D}XR    IENDB`PNG

   IHDR         r|   sBIT|d   	pHYs         tEXtSoftware www.inkscape.org<   IDAT(1
@E&JIgI;X tiz&jD8aP[Ƨ{󗭵N#P)yiA|K۶XV8\3NY-b<=S(d11tYԮ:)24<(d7ߛ3h1;    IENDB`<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   version="1.1"
   width="220"
   height="220"
   id="svg2">
  <defs
     id="defs4" />
  <metadata
     id="metadata7">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
        <dc:title></dc:title>
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <g
     transform="translate(7.0217361,8.0694962)"
     id="layer1">
    <path
       d="M 60,10 C 32.3,10 10,32.3 10,60 l 0,100 c 0,27.7 22.3,50 50,50 l 100,0 c 27.7,0 50,-22.3 50,-50 L 210,60 C 210,32.3 187.7,10 160,10 L 60,10 z m 8.90625,17.78125 82.1875,0 c 22.7744,0 41.125,18.350601 41.125,41.125 l 0,82.1875 c 0,22.7744 -18.3506,41.125 -41.125,41.125 l -82.1875,0 c -22.774399,0 -41.125,-18.3506 -41.125,-41.125 l 0,-82.1875 c 0,-22.774399 18.350601,-41.125 41.125,-41.125 z"
       transform="translate(-7.0217361,-8.0694962)"
       id="rect4991"
       style="fill:#333333;fill-opacity:1;stroke:none" />
  </g>
  <g
     id="layer2"
     style="display:none">
    <g
       id="text3761"
       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#333333;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu">
      <path
         d="m 119.775,168.98893 c -8.84006,0 -16.77338,-1.36 -23.8,-4.08 -7.026702,-2.71999 -12.976696,-6.68665 -17.85,-11.9 -4.873353,-5.32664 -8.613349,-11.78664 -11.22,-19.38 -2.606677,-7.59329 -3.910009,-16.31995 -3.91,-26.18 -9e-6,-9.859927 1.473322,-18.586585 4.42,-26.179996 3.059983,-7.59324 7.196646,-13.996567 12.41,-19.21 5.213302,-5.326557 11.333296,-9.349886 18.36,-12.07 7.02662,-2.719881 14.56327,-4.079879 22.61,-4.08 4.87326,1.21e-4 9.29326,0.396787 13.26,1.19 3.96658,0.680119 7.42325,1.473452 10.37,2.38 2.94657,0.906783 5.38324,1.870115 7.31,2.89 1.92657,1.020113 3.28657,1.756779 4.08,2.21 l -6.29,17.51 c -2.72009,-1.699904 -6.63009,-3.286569 -11.73,-4.76 -4.98675,-1.586566 -10.42674,-2.379898 -16.32,-2.38 -5.10006,1.02e-4 -9.86006,0.906768 -14.28,2.72 -4.42005,1.700097 -8.273379,4.306761 -11.56,7.82 -3.173372,3.513421 -5.666703,7.933417 -7.48,13.26 -1.813366,5.326739 -2.720032,11.503396 -2.72,18.529996 -3.2e-5,6.23339 0.679967,11.95672 2.04,17.17 1.473298,5.21337 3.683296,9.7467 6.63,13.6 2.946623,3.74003 6.68662,6.68669 11.22,8.84 4.53328,2.04002 9.97327,3.06002 16.32,3.06 7.59326,2e-5 13.76992,-0.73665 18.53,-2.21 4.75991,-1.58664 8.44324,-3.05997 11.05,-4.42 l 5.78,17.51 c -1.3601,0.90668 -3.2301,1.81334 -5.61,2.72 -2.26676,0.90667 -4.98676,1.81334 -8.16,2.72 -3.17342,0.79334 -6.74342,1.41667 -10.71,1.87 -3.96674,0.56667 -8.21674,0.85 -12.75,0.85"
         id="path5013"
         style="font-size:170px;font-weight:500;fill:#333333;-inkscape-font-specification:Ubuntu Medium" />
    </g>
  </g>
  <g
     id="layer3"
     style="display:none">
    <g
       id="text3761-9"
       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#333333;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu">
      <path
         d="m 99.289993,48.628934 21.419997,0 0,117.809996 -21.419997,0 0,-117.809996"
         id="path5086"
         style="font-size:170px;font-weight:500;fill:#333333;-inkscape-font-specification:Ubuntu Medium" />
    </g>
  </g>
  <g
     id="layer4"
     style="display:inline">
    <g
       id="text3761-7"
       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#333333;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu">
      <path
         d="m 154.67148,48.628934 0,18.53 -36.21,0 0,99.279996 -21.589995,0 0,-99.279996 -36.21,0 0,-18.53 94.009995,0"
         id="path5089"
         style="font-size:170px;font-weight:500;fill:#333333;-inkscape-font-specification:Ubuntu Medium" />
    </g>
  </g>
</svg>
          h     (                                    888       r                                 r          B4a)Ak(Bt-I{)Du.J}'D|*G.H'@n(?k4`.R   +Ae7d(U#@u9m/M+J9X3T'G9Y8V6f+Cr"8c+Ak/U!8a9R0a'ENgJ`&Cw-Fx6P3\"C%8[)Ao$>k6S2S7\3U1S1M!9f8g/P.S%>l3MymwPX.M8ZsH[<]7YP^Y\'Ao(>g0U*L0Y7e0N9Vv *`.K$?p!9d)I/P2\2Kx8W7Xr{)7m3R8Q~(?g!2R/Q*?h8Q|0MNZ8S=V(?h&8X3V)Cl5Ox>[!3cUfp8U*Fq+Bi$6X0Cb5Ov=UOiFd1@jC`Ok9Qy*Em+?]1Ea6QuD_=X~iLkMkMkIk`|GbA[>X8Lh(?a>UvEbHaQnztId;V|Li>Uv4IjF[}KdJdNjLgUsRm;a:aQmHiPkLfCZ~JdBUw   .D]ToRnLgOmSm[x[xNm\yPlKeNg?Vv   / #%*0KcG[IdGaD\PgOgNgG`LeJcF\#&+1                                                            <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   version="1.1"
   width="220"
   height="220"
   id="svg2">
  <defs
     id="defs4" />
  <metadata
     id="metadata7">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
        <dc:title></dc:title>
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <g
     transform="translate(7.0217361,8.0694962)"
     id="layer1">
    <path
       d="M 60,10 C 32.3,10 10,32.3 10,60 l 0,100 c 0,27.7 22.3,50 50,50 l 100,0 c 27.7,0 50,-22.3 50,-50 L 210,60 C 210,32.3 187.7,10 160,10 L 60,10 z m 8.90625,17.78125 82.1875,0 c 22.7744,0 41.125,18.350601 41.125,41.125 l 0,82.1875 c 0,22.7744 -18.3506,41.125 -41.125,41.125 l -82.1875,0 c -22.774399,0 -41.125,-18.3506 -41.125,-41.125 l 0,-82.1875 c 0,-22.774399 18.350601,-41.125 41.125,-41.125 z"
       transform="translate(-7.0217361,-8.0694962)"
       id="rect4991"
       style="fill:#333333;fill-opacity:1;stroke:none" />
  </g>
  <g
     id="layer2"
     style="display:inline">
    <g
       id="text3761"
       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#333333;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu">
      <path
         d="m 119.775,168.98893 c -8.84006,0 -16.77338,-1.36 -23.8,-4.08 -7.026702,-2.71999 -12.976696,-6.68665 -17.85,-11.9 -4.873353,-5.32664 -8.613349,-11.78664 -11.22,-19.38 -2.606677,-7.59329 -3.910009,-16.31995 -3.91,-26.18 -9e-6,-9.859927 1.473322,-18.586585 4.42,-26.179996 3.059983,-7.59324 7.196646,-13.996567 12.41,-19.21 5.213302,-5.326557 11.333296,-9.349886 18.36,-12.07 7.02662,-2.719881 14.56327,-4.079879 22.61,-4.08 4.87326,1.21e-4 9.29326,0.396787 13.26,1.19 3.96658,0.680119 7.42325,1.473452 10.37,2.38 2.94657,0.906783 5.38324,1.870115 7.31,2.89 1.92657,1.020113 3.28657,1.756779 4.08,2.21 l -6.29,17.51 c -2.72009,-1.699904 -6.63009,-3.286569 -11.73,-4.76 -4.98675,-1.586566 -10.42674,-2.379898 -16.32,-2.38 -5.10006,1.02e-4 -9.86006,0.906768 -14.28,2.72 -4.42005,1.700097 -8.273379,4.306761 -11.56,7.82 -3.173372,3.513421 -5.666703,7.933417 -7.48,13.26 -1.813366,5.326739 -2.720032,11.503396 -2.72,18.529996 -3.2e-5,6.23339 0.679967,11.95672 2.04,17.17 1.473298,5.21337 3.683296,9.7467 6.63,13.6 2.946623,3.74003 6.68662,6.68669 11.22,8.84 4.53328,2.04002 9.97327,3.06002 16.32,3.06 7.59326,2e-5 13.76992,-0.73665 18.53,-2.21 4.75991,-1.58664 8.44324,-3.05997 11.05,-4.42 l 5.78,17.51 c -1.3601,0.90668 -3.2301,1.81334 -5.61,2.72 -2.26676,0.90667 -4.98676,1.81334 -8.16,2.72 -3.17342,0.79334 -6.74342,1.41667 -10.71,1.87 -3.96674,0.56667 -8.21674,0.85 -12.75,0.85"
         id="path5013"
         style="font-size:170px;font-weight:500;fill:#333333;-inkscape-font-specification:Ubuntu Medium" />
    </g>
  </g>
  <g
     id="layer3"
     style="display:none">
    <text
       x="110.08234"
       y="166.43893"
       id="text3761-9"
       xml:space="preserve"
       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#333333;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"><tspan
         x="110.08234"
         y="166.43893"
         id="tspan3763-5"
         style="font-size:170px;font-weight:500;fill:#333333;-inkscape-font-specification:Ubuntu Medium">I</tspan></text>
  </g>
  <g
     id="layer4"
     style="display:none">
    <text
       x="107.59211"
       y="166.43893"
       id="text3761-7"
       xml:space="preserve"
       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#333333;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"><tspan
         x="107.59211"
         y="166.43893"
         id="tspan3763-8"
         style="font-size:170px;font-weight:500;fill:#333333;-inkscape-font-specification:Ubuntu Medium">T</tspan></text>
  </g>
</svg>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   width="220"
   height="220"
   id="svg2"
   version="1.1"
   inkscape:version="0.48.3.1 r9886"
   sodipodi:docname="custom-icons.svg">
  <defs
     id="defs4" />
  <sodipodi:namedview
     id="base"
     pagecolor="#ffffff"
     bordercolor="#666666"
     borderopacity="1.0"
     inkscape:pageopacity="0"
     inkscape:pageshadow="2"
     inkscape:zoom="2.4181818"
     inkscape:cx="60.37594"
     inkscape:cy="110"
     inkscape:document-units="px"
     inkscape:current-layer="layer4"
     showgrid="false"
     inkscape:window-width="1366"
     inkscape:window-height="718"
     inkscape:window-x="0"
     inkscape:window-y="0"
     inkscape:window-maximized="1"
     inkscape:showpageshadow="false"
     fit-margin-top="10"
     fit-margin-left="10"
     fit-margin-right="10"
     fit-margin-bottom="10" />
  <metadata
     id="metadata7">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
        <dc:title></dc:title>
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <g
     inkscape:label="Background"
     inkscape:groupmode="layer"
     id="layer1"
     transform="translate(7.0217361,8.0694962)"
     sodipodi:insensitive="true">
    <path
       style="fill:#333333;fill-opacity:1;stroke:none"
       d="M 60,10 C 32.3,10 10,32.3 10,60 l 0,100 c 0,27.7 22.3,50 50,50 l 100,0 c 27.7,0 50,-22.3 50,-50 L 210,60 C 210,32.3 187.7,10 160,10 L 60,10 z m 8.90625,17.78125 82.1875,0 c 22.7744,0 41.125,18.350601 41.125,41.125 l 0,82.1875 c 0,22.7744 -18.3506,41.125 -41.125,41.125 l -82.1875,0 c -22.774399,0 -41.125,-18.3506 -41.125,-41.125 l 0,-82.1875 c 0,-22.774399 18.350601,-41.125 41.125,-41.125 z"
       transform="translate(-7.0217361,-8.0694962)"
       id="rect4991"
       inkscape:connector-curvature="0" />
  </g>
  <g
     inkscape:groupmode="layer"
     id="layer2"
     inkscape:label="Class"
     style="display:none"
     sodipodi:insensitive="true">
    <g
       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#333333;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
       id="text3761">
      <path
         d="m 119.775,168.98893 c -8.84006,0 -16.77338,-1.36 -23.8,-4.08 -7.026702,-2.71999 -12.976696,-6.68665 -17.85,-11.9 -4.873353,-5.32664 -8.613349,-11.78664 -11.22,-19.38 -2.606677,-7.59329 -3.910009,-16.31995 -3.91,-26.18 -9e-6,-9.859927 1.473322,-18.586585 4.42,-26.179996 3.059983,-7.59324 7.196646,-13.996567 12.41,-19.21 5.213302,-5.326557 11.333296,-9.349886 18.36,-12.07 7.02662,-2.719881 14.56327,-4.079879 22.61,-4.08 4.87326,1.21e-4 9.29326,0.396787 13.26,1.19 3.96658,0.680119 7.42325,1.473452 10.37,2.38 2.94657,0.906783 5.38324,1.870115 7.31,2.89 1.92657,1.020113 3.28657,1.756779 4.08,2.21 l -6.29,17.51 c -2.72009,-1.699904 -6.63009,-3.286569 -11.73,-4.76 -4.98675,-1.586566 -10.42674,-2.379898 -16.32,-2.38 -5.10006,1.02e-4 -9.86006,0.906768 -14.28,2.72 -4.42005,1.700097 -8.273379,4.306761 -11.56,7.82 -3.173372,3.513421 -5.666703,7.933417 -7.48,13.26 -1.813366,5.326739 -2.720032,11.503396 -2.72,18.529996 -3.2e-5,6.23339 0.679967,11.95672 2.04,17.17 1.473298,5.21337 3.683296,9.7467 6.63,13.6 2.946623,3.74003 6.68662,6.68669 11.22,8.84 4.53328,2.04002 9.97327,3.06002 16.32,3.06 7.59326,2e-5 13.76992,-0.73665 18.53,-2.21 4.75991,-1.58664 8.44324,-3.05997 11.05,-4.42 l 5.78,17.51 c -1.3601,0.90668 -3.2301,1.81334 -5.61,2.72 -2.26676,0.90667 -4.98676,1.81334 -8.16,2.72 -3.17342,0.79334 -6.74342,1.41667 -10.71,1.87 -3.96674,0.56667 -8.21674,0.85 -12.75,0.85"
         style="font-size:170px;font-weight:500;fill:#333333;-inkscape-font-specification:Ubuntu Medium"
         id="path5013"
         inkscape:connector-curvature="0" />
    </g>
  </g>
  <g
     inkscape:groupmode="layer"
     id="layer3"
     inkscape:label="Interface"
     style="display:none"
     sodipodi:insensitive="true">
    <g
       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#333333;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
       id="text3761-9">
      <path
         d="m 99.289993,48.628934 21.419997,0 0,117.809996 -21.419997,0 0,-117.809996"
         style="font-size:170px;font-weight:500;fill:#333333;-inkscape-font-specification:Ubuntu Medium"
         id="path5086"
         inkscape:connector-curvature="0" />
    </g>
  </g>
  <g
     inkscape:groupmode="layer"
     id="layer4"
     inkscape:label="Trait"
     style="display:inline"
     sodipodi:insensitive="true">
    <g
       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#333333;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
       id="text3761-7">
      <path
         d="m 154.67148,48.628934 0,18.53 -36.21,0 0,99.279996 -21.589995,0 0,-99.279996 -36.21,0 0,-18.53 94.009995,0"
         style="font-size:170px;font-weight:500;fill:#333333;-inkscape-font-specification:Ubuntu Medium"
         id="path5089"
         inkscape:connector-curvature="0" />
    </g>
  </g>
</svg>
PNG

   IHDR           szz   tEXtSoftware Adobe ImageReadyqe<  wIDATXŖ{PUj:VDQ:IiS6854MJ!M "7@4P,yInˮEV	.+ {ݥEL^><1lq KZS<:mgqw
^~N1S Y{qW2ݨ;bYП%J%P݋׭2D2c*D[OoSsܒ(]{[.p~!Lp,c%̱9ow^
0\\G?!v<ci*_=Oʮ^dc \<9YM?	wuu"4+93BZԄ?j|x'KDF2!1,_̰8C ]M	:Fn3>8=j V~C9@UT\9.`1E&3P28`=n;XxBABNLB^HpOHj
6(b84H1oʢ+*&/Xv6:Ƣ)s]_,`4TVGo&_6%Y]Ah!f"=5bp,8=\ScOИ`11bU	G\þXBu%Aq5S.̩AL+Bjؚ۫{~E8M9GlEne'"UPf0[o #W{#ofP+"2JYS/_׉j7}ZH-@Hc25q2>R,y:4a	u'Zw'),z+WPTݮY)Y_>[t܂/?uz)2ڐxDTU0N-kHJ`MST=߀}(W4Wu*].źLO5+N\&(+ Մ!R¦>Gz$o29Ppꚅ1r%\O,;m37lxЅtV܇fp٣P\KMEh`&VB#//kreYƶ>T]xBR(O˸uUYn%u)dG
Gv^5Gv y	=bc'%C]ۂGoaޔ(cy*)mnFӌiƚP9?c4Ӗr-IBu?Ks'
O dX!=p0זoj?p)z%&֏00a{Mϰ/% 9>/_    IENDB`PNG

   IHDR         ;0   tEXtSoftware Adobe ImageReadyqe<  diTXtXML:com.adobe.xmp     <?xpacket begin="﻿" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.0-c060 61.134777, 2010/02/12-17:32:00        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmpMM:OriginalDocumentID="xmp.did:3F186DBFEB7BE01180DEBC3D1F6633B1" xmpMM:DocumentID="xmp.did:8FE521A7F35411E0A81FA4AF0F59BF4A" xmpMM:InstanceID="xmp.iid:8FE521A6F35411E0A81FA4AF0F59BF4A" xmp:CreatorTool="Adobe Photoshop CS5 Windows"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:817901DA62DDE011A7A1986CEF352AD3" stRef:documentID="xmp.did:3F186DBFEB7BE01180DEBC3D1F6633B1"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>T  IDATxW]
0^&C`[{l{u-ڴn!K.p̲3T  M+I^m[rUb3)GjGC!~JĦoɉK7[[AGq׆jczi$Xh3qXIafbt\feNMtfM"u>XyR1Ub !!PgKWi(qQsĵ%!Ֆr%I@}cٽ ,>-    IENDB`PNG

   IHDR         ;0   tEXtSoftware Adobe ImageReadyqe<  diTXtXML:com.adobe.xmp     <?xpacket begin="﻿" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.0-c060 61.134777, 2010/02/12-17:32:00        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmpMM:OriginalDocumentID="xmp.did:3F186DBFEB7BE01180DEBC3D1F6633B1" xmpMM:DocumentID="xmp.did:A78832A1F35411E0A4B4CD5BA28F5129" xmpMM:InstanceID="xmp.iid:A78832A0F35411E0A4B4CD5BA28F5129" xmp:CreatorTool="Adobe Photoshop CS5 Windows"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:67358F0068E0E011A127D534A854555F" stRef:documentID="xmp.did:3F186DBFEB7BE01180DEBC3D1F6633B1"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>'5r  IDATxڼJ@ȩPBO>'oP
PT]KWAxJB^^+82&qevgdv6^i匇hb֠GY4mpS9^*AO*i1oʂ	
4 5I%\N)W2/-O :=1\+OY+Ǣ&f6ŏH0憹DWgϲKخ̿7
$uطm00_TcP m|_J㴐'@x]:ϕ+y2K⹂Kb\+õy1p?fTC ri|&->}p!ZxTQYBpMYO\x`![X {V>L <f^`` 2 E9    IENDB`PNG

   IHDR         ;0   tEXtSoftware Adobe ImageReadyqe<  diTXtXML:com.adobe.xmp     <?xpacket begin="﻿" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.0-c060 61.134777, 2010/02/12-17:32:00        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmpMM:OriginalDocumentID="xmp.did:3F186DBFEB7BE01180DEBC3D1F6633B1" xmpMM:DocumentID="xmp.did:A7D198C4F35411E0BFB9A953AE02CB2D" xmpMM:InstanceID="xmp.iid:A7D198C3F35411E0BFB9A953AE02CB2D" xmp:CreatorTool="Adobe Photoshop CS5 Windows"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:65358F0068E0E011A127D534A854555F" stRef:documentID="xmp.did:3F186DBFEB7BE01180DEBC3D1F6633B1"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>  IDATxڼJ@ȩPBO>'oP
P]KWAxJB^^+8lvv82ٙ/;ٝ]UѲ,sC4@1_@#_J@[A[KUd]Г 
c`,盒0]F6iDT=[_0
fۀ%]c)8 }vDS	w)6sQ>	uqh$s\OW瓈zkIy+	.{?/ 	xYIP6~+ɛմ_`s
ex؃.Zs,l\L9mϱ\"ǋc4(,~l%YȒ5/^ٔdCᵂ~#`|4]q0p=#{u]W 	YWy     IENDB`         h     (                                                                                                                                                                                                                                                                                                         			                                                                                                                                                                                                                                                                                                                                                                                  O                     h     (                                                                                                                                                                                                                              !!!                                             			                                                                                                                                                                                                PNG

   IHDR         ;0   tEXtSoftware Adobe ImageReadyqe<  diTXtXML:com.adobe.xmp     <?xpacket begin="﻿" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.0-c060 61.134777, 2010/02/12-17:32:00        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmpMM:OriginalDocumentID="xmp.did:3F186DBFEB7BE01180DEBC3D1F6633B1" xmpMM:DocumentID="xmp.did:2B07A5B1F35411E0A619C903323F0D99" xmpMM:InstanceID="xmp.iid:2B07A5B0F35411E0A619C903323F0D99" xmp:CreatorTool="Adobe Photoshop CS5 Windows"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:60802ED7F2DFE011B39A9A21C2CA722A" stRef:documentID="xmp.did:3F186DBFEB7BE01180DEBC3D1F6633B1"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>se   uIDATxb?@ &322RĘ1`>f!4mP3TvbUYhd`nO2jCb`Vb(ţӿE?:^G$  $S`    IENDB`PNG

   IHDR           szz   tEXtSoftware Adobe ImageReadyqe<  lIDATXŖPUBN5Ze9YdiB%MSGeqFAŔU	54aE*
.*A	ewYXXe w~Ve'<s=OzR0mkGʀi1H<t蹍6blE8P/%'q`~3bg37U>G|9˥T!Lg#b{ R/a	}w]Zc(RqzG3KCUTu <a_<{*}yi.n#2w0B1지se<DS]C']@yPZ́C>|D5և~d}q$<M4+1LbLyඅ-Cl5,ڏ$u]{bA5p]]F_#O&}XhH)pxՍǶ~NpBK=Oh>p&=C`TOϗnwN+S^cqD3Zӻpb744.6%4uHT!B/'d|NTYL D:"aqQ&k	5h&YMpV@Pb	Be.cx7]`\Y
N+ިE;k֕:ߟU@pr)G߆G[+|<!v/ ~v,FdB*'*QPii.*b`^%^@Rq B˛w<~
[!֒OOrgTp*(%}ZLqeAzdIQ׬_O7obJ,VгƯDܟ̮ĩ:G-f/*G_PX̖dĤIhl@3	(ݬB
DZ,,&EFAW\@1	_݁W,ʒvI]	'e5fGބ4 x
f=$%Z0SJOB MU-ryO=	wj"/Cҝ,{UK!ZEZyD>O)E#)$ E.,;)?:OyCN'@5CȠi8,/k^s$1seӜW7vJq$\-i@lkFܾ̒ķ=+\Tǥb'9#@N#d;͡wAZX|32Ьp+-mX|t_ՒKB5)i*8Dqo3{7:={)vuvo)&`y''%l<ϧ`)5    IENDB`PNG

   IHDR   H   H   UG   sRGB    bKGD      	pHYs        tIME &[    IDATxdy%U}YcU3C7 Q@DA@gDBfrFɍQsohLH0I'EP"BMj<y_~vZW߱GJIJAh<zo|<~ۦFP2e!R(]TFJ R$)'rJH29zl#*ENRLҒ!ň-)r$I#DQJ#u5BrJbMșL916
>>>z70젟7F_J)b()EL y[_ǟZ}th9rGf4i(DPJPZ66R
T".g b&% YWhqMSjd!)QhM| %ubĈ1k*#LQ8OMZ	ރ-ya;A]+SRʐRJZJY$wL_3ͯ30\۾d2!p)T9 @E&5~$@ƔPRS$@V2TE)Z\LQ|$61xTB"DP7jMi-s@60WY"1fƭmB!<O-ۏ޷oWb8jAR
Rʙ{k5k^~]w%k(B(ZӸ/)9FC#r'iR'H!@DA**"Dii	!c
K@xa-m"i)e*kZ1|C"EQә51&jۆ1a!I1ĳqkwo  f{j}4ݻm
h#
kAkY2LJH3Ɩ3*T)B"@H1c4R	R%A˂[rUHk[liZc&FGB,RL8҆9g1n68pp4³/<__mCf:d߽Ťl(pޣZ	AwbJHRSB	>)g$3Fi	2d F(ItsE+
rBK $h%PRsBhMPV`R D(ʂh$f-3(E4@*qӈ=[f9M@K>q;B	!Fa7(mB7Od2JvwHkRsT1]hZ-H9R@K,
wHYs6 LCʙ*=!$[Zr-5JI*R)&mCDFxK'mއ~
9-O=u+rｹmJ
ȈJ*j)#%kB13BrĐ0Z!B)H	DN()DJ)R~YJ#-RRmIN$ZIxנ;Gi5Z
)s1/J}hqS%RwsO
` %PG]JkbJ0Zc
ڶ%#h"c$1cD	-XL&HJ!@"'
A.PRpPJ g)Մqsw 8ByF!Fkn^lvfx3LӄJH)QR"  $Z|;AA H)@<D-Jibp P(;*"')Y@y:!1D@aFɌ'
k%&AH<Z+( 2)ʲB9P0){"㏚9Ԣ)$
Zu;kG)"|RhL[Ȝ9DIm,"% C$DGhk0M:BtJ+lh[RJ!&9ՄAR@dROpVHN z-./f40cܸ9y'./mf91p0UEǈ)Kb]#[D$P4!:sѽr쉏'ñ'=mPY:(=?{`Q;8z	CueA5B"$$ }P2uX,J(\QŨlWZl7[ 28gT(!HA*M"1hB$#> x961}/yݻ97ߒ)'lc?_7&U#ʲGD D	MpA"@)$	r7w\)aB5IҴјG\LY$׀Iv ̸nYyQ<ZiN؁ĤgWcIt!#y_\I{"e;L!`a C!j s}	=qջ38(rJx	)	)bp@iM8&Q%AUƭctRR).5 [^) zJcdqeA5)ѸIw@_(RF	֛y^4ܐ@THi@cD!4Je]%9RV\pg;O4["&rBkK4!Q[4.2i=I!I)R B-3}4Ԯ%+-,yV*
V-q)8p`?>)7yY#{znFGPOY~tlޱ
{"G|:Gx*v!9%]ŗÞoSND
Pd1.0 cdSI2n>YktǷ?_ +pkc^U0(K2ZRuad~v@LZJ|H1Vo~	99b{C)T&Ye'l߁D? Wrǣ9'pSǒ"g9ބq:Rqv00h hT
#LH1|mYQƐW-;!Bkn?o2Ul1h'H	YaJ{f|oKxs/?Ws !=9:|O^EٌEA9&#u['Dy1#c7+`.\qduh{}J6#B(LO-d2yW
stf/}o_~yGVpgRLjRLR"Dx׶i[cakǞ	brd~s_'- 5&B@M" ֚"(I	P%N&,N9B$'@!IM3Yxҟ0h&/;x_dn`>Ĥi! Bc@_otkي~ԕ4ȁ?Oqhq~ZƵ<U"5(!H9(I[FHBbH@EAYBl)TBjzVSermGP7.~b}yEVɭG+CJIHx'R$Q3mq>G~ɨ4԰Y-7C:@H4H"M#%"'| D@@)~cu3ZH!3w<B(B(?+ᐃ@JBiw!ŌB*hquт!4()mGCdJx',/.}B_?y+>΂N>9@K2-KPin\b
U,k
JcJSCi4(Ƭ'ޓõ-!<wGdCFuKʙQVm5qʉX\ZǃWxG9#І,TɄ#geyulOo~-"\zfrL(2ZֆH*GRN4m> Ĕ8uI9!P#JRma,5o?; 7}8D=@ם4Y
ɏ~C&qdb	rWn5d{7mSBlB΄򬦍ƵV3ojn@
(ЉgYYZ*
\4ށ!!0iZ*R2s
} YJR@gD:LTJsJ
i['<M[*r@b{Pp~)$H	mh!w
e yu?KJVcNoxŕw=r?R@+ȵ}+G(9Mi\dBm;:"@DBXSt)b!okں&	RS)ɠ71H8IMKΉ#z	Lݳ[~gy}3w|K|CKrJV|_hopcNynVO&L	{)#rͥ|z7޷>t!4-*1ni ={t:@*:"y/}vT"{d abR)Excy*/{եq_KnZ1g=?췸.y,GQNoXF쾃;n2g>"|է7s{nga\ǯ\Crs=kslIϸ(J3)D&ǅ@B|Ke;<fi:CV)Nj.}}
+V4uVG\sѥ/dw^ɮǟ3^JθY|>N3N.|1_oykIg^{=OpK_o~zvzǝz4?2w3`Vb4k!}s -t-t^NLG">vAʉ``m'5Y!E")I̹9J*#ؓE(^۾'!#${6m}O:x?s?yۏ_j~318&y''^%_$GO8_yeu.vlJ!o;և* zNx1l8	:q?eȂD"N{$b;h|Fwʿ2N1&QF</%/|ѡh&$Ȝ(XY.ㄓQFLGo.qʹp5`q߃O~b)Zsۄ.oь7~Ĉ"Sh`b*N>a"&J[|՘:{Ik ~fJߺg(E
[XcJQ%QF+Kƫvι0F|;)+CiBb_̖m:O;k![gq^!MZ[lGcX|d|zVN{x\%q)8pwB#ǈYN94+2FfzE9S!Oe*Ԥܙ~i.(eZȸqI{I"W#c#rcݷeo|; 0w~//|<<tX=ǩO~&xorK_=<||cnf~s߶PGGaRORjhh\TvDNyi<rͳ)"$ EwJu	V	jBk!fimCn fzJ̝ZffJyG>)OBJ+}K{7/JyغDr ゗;zlnO˞X;Wz7W71=3epEh&+Aaǉ'1dqu.8Ў9S;O;(DΑ	@
:Yp,CA7FHAΎӟ$>W#<ocyߣڏb+)O9ߗ~n5d)9X=po]9/2җc_-m8B#qM9"Hz
AB@;S,k TJ)"s@BKHc6C@89#	ΑrbϼmqcZo N98.юVЫe>a)qv.ghMaN|y\+~OZ@23`ԓqK~a߃YVB	z/,QXAzl^I-:B	R2ZNQRQYFu.JAZeI!$>~ufs7R"#'u6v @͑f?~J
^7ir&H'=|((#2x
cm(Z "DDYLHh[b)c ؑbY D/Jv[0mXOpށE a&Db&%jDyMs_?A
dEUs;}/2'y#r79urvJ ?WlBFGD$L
/cp&4xDLt)r֏RqbbB"EhЦLBN	KAeN/s-,JTSX463#wϯ+|7UJn؇C\ku>9BaS@UdA=|33CیA$:mo\[\?(Qƒ|DKE	
]"ĀPk%:I%)Q
I(Buϑ},;oYش@L3;'UՌ_b>g?Gwdu|?rhaw)?YAA!5U<t=ﲲNbdƨ&bg1yZغ0@	AtURcM2E9u
QRe7ɕ,wn}۲.*)˲歷S=/z"?Vףti{VÃ|󪫹.ɲ^oxGwr?rNyR27~jfLi4u	1щxv@6L=w[F*ll	јnFlm'oL(@V)hr
#U߅_QOBl6`.i	Rnشm 9KD\T%5m97_m']z)%7X=|]Ƌl?q<9hAC,
.wȐK^yQL3	>ۑs	|Щs}	A)2eUc OG9vyIy*ZDR\$}kHD&ĄxO+(C"xLqPY9E/`ߏlu""˯A5ЌϸLgL..Җzx/C{A/sC:FuC:$%@EJmBYCk1MY)"%<.*WY?1޹aeoCnU(-q!Zɑt8ECn[Dj;+0cyl=D-ONэb"UX"0.2jyJMoB mo&QĔZT Y^]cc4n) uZ°yu|hMm]FT%A56'P.қHo~+uџ)BB]Л,lUH&b7ppk>ϿUl4S.i[Yɦ?*8,T#9E6_Pԙ7	,(2RDwsEɜVq0C: Q46PU~ppɗp^!KIRXHKH1".OSL2ҳ_7N@!K^\EOoHkcBR䄋ih떐Xb0S.XݝKAY\]g=叺,񖍃  CIDATgL PMD][ɼl߲|=|OWegEL
̐w`1t-ui3:3ֵꖵk4EB~<V93Pqdi	@[3-hкv-c&:(UAe,"tdX7j`p<fݷ'K^͒tx"G$El8M{\@`Ȫb|}ӯ}%]G?.Ɛť#<DjkDΓàŃmJ\}*B̙pMO]Vњ(PNPsrŸ֚.^[VBjyRuMe4;ĝ}<L*L[я?S,(Z)҂qhGgO3߿۾}1nk8l1Z^Y^]E:Dꦥ4"+Ov?uq\6o28 M-e)1i't-2 lU[YD'o_ᳲUev$V3cbC殗1/%zXҊ`m?*f˂E èvɈL~ٱi6,/Lli 4PD]ϬW~0O~o~>ٵPhU<*B*djL&5묯(Y)[Yby8.Fb-2z(ƎV%Jt1pҸCz<	X_̧Uv5Kq"'뚞5L*cf23\_HZ|x(f2`u	1>If<c§HL%$Z.%ɄhLLPhؿ-c6+,EkDVV1Zd
^d5Q@pNa	qg<@*U 4׭L_$/FuL&5Zv)6DJI)ck^gbk:kos)ӄk,:TLÞX@0Ԉ+'$6mJFm~.B>NX-%ѵty _^dOǱ껅
&2
ѵ1UB<|N|%S/?<bs݇&9(˒>Fvl%5YkFiNB-2~yzyvsܖ+ׇ6٪WX$&dBH"_TZ|0Y(n	5ǝy2!d_I^}bߞGmLU=-0ҴZ(4>xw_2lwPa&zZ("ƄHBeZE1iPNzW$]T9#Fk(%-KeLգMu6/8t9|`g>3y<شs3OyKyڙ^thC04Z|Lxر1Y_mfNxx^^6PXDc\K>y/1;gYYYa8 S@
T	)MkW,%J5S3[koxiX7%6	] hI-
"oE
Kk6sޯ_Y<"f2׌V7xY;h(mdabqǱП/;7e:~}f$e4&C㽲N7ƍn=1g|ue$6(wXN]D 'ŀ +(!)2?3%^JUuw?7̇ɜrI;P:xH&Qƚje% 'AAdH< ZE}<v5b#!Rk-Č]n}4bP(KH].7i1R wb\H2^Ea-JJfҟuffgӯ
,rH}3O?I++OFKd_#r #""YC/\ǃ߿z BeD&ҌGH)3jZ$L;kkz=FVBH^Id5:̍
ꎽk-(fmmsmsn4dvvAFx̊[P5§_ܱm蓎zAV(	yH2K{axYMX_eꡧ}ٔBv
ck,1wף4J@چ~?F\6޻,vYH:шم4^B(;c`hk̈́\,..#)ھ?z쿹.LMFsRea`0ZP-VD7dߒP˰N*mqӚ[XmpS='[T9-Y
|&&
 |LI4Mh<_voLjF1fgJI)&MjX-A27G}fL`ccmkV7Ơ5m`FQ'歏Z$ia212iHShaz.ZDΓ61Jk+-JHV&oJZ67*d2!T]IzUڻY	mh<]5eƱ*Dq=ѐdR7c6-LF U{~+deҴӸ$dRܹTuycr6>rRd[,8p ᐹ[iZZ'c(C3vkϳtm-R()A)|sוJuo^P@5	87h"k&;jژ Lf81RRUYdd<HR@[ĔXN	AȦ-lH`<weLOuߗldҰ]?QγA cμ-[)O_p>0i[RJx6HH-pm	CmK-X&{1Uŕ2ӦDLISsI
"Rk\yҸ<(xhqVa`({|5:L-дLQ`i&Q0OȺ{2ts4j)&BȘp!D:(&LRag!@j" 
{Rc$.x"]'	Ҳ6%%J*N)Y|ćX7wR/n_:jtUE̩;VU!zUEhkfiۖdvn%VftUU[GbA\?GB 	n{NDa	?mWS=s0)5#ijs;OBiR.)1R^G?Q/lH3ǀfO;E_'9(z!%jβ1`1*-).(Fc;GQ&D@!8WNe%uHc-$YJ\E{GL6xԽaccDl~$(s;IoOw2+F{	.!0lt.vr*Tｲ
I{ӍR0mV5bHqk%fJ|PTsEm
7!Zj{Vj]/֎(
Τn[UTv[YqжxP=5z0xz!| *z*@SPwyUrhZfy89,)Ke,'B	DDƨ8X-N/psx
|Ϋ@G[/|<XTβc+5+L\)#X9-D';TJo&, tExA+N<,zK呾S84L#Ǧa^81ړJt_~O/Q@}ó"wEX/x٬8G4͒f\.::U˲wl%<gsn=y6e,iUq-
zM;eI۶?1#1EW6o<vcpf0Gwt5?{-p 7:AJMTN&IT$QѨPA_#DBTQ#^BlΝ(:!%t}Qy?}@dzdBDv"\ρcHwӾ8㽌vIL#pI富"սs+7"u~yѧ!'$    IENDB`PNG

   IHDR         r|   sBIT|d   	pHYs         tEXtSoftware www.inkscape.org<  )IDAT(!KCaݫ 6Ad;aLVUҲMZiNKD]\7.ė灗{{4C6PW,˲"9){v8~z "'feo"rn}i٪L\E.p%"nr:WpR6Jf[VR s@\
@RYVR0sd2&IRs!@,zw("m`<?9?3]͒:)khk⏋>    IENDB`{% extends 'layout.html.twig' %}

{% block javascripts %}
<script type="text/javascript">
    function loadExternalCodeSnippets() {
        Array.prototype.slice.call(document.querySelectorAll('pre[data-src]')).forEach(function (pre) {
            var src = pre.getAttribute('data-src');
            var extension = (src.match(/\.(\w+)$/) || [, ''])[1];
            var language = 'php';

            var code = document.createElement('code');
            code.className = 'language-' + language;

            pre.textContent = '';

            code.textContent = 'Loading…';

            pre.appendChild(code);

            var xhr = new XMLHttpRequest();

            xhr.open('GET', src, true);

            xhr.onreadystatechange = function () {
                if (xhr.readyState == 4) {

                    if (xhr.status < 400 && xhr.responseText) {
                        code.textContent = xhr.responseText;

                        Prism.highlightElement(code);
                    }
                    else if (xhr.status >= 400) {
                        code.textContent = '✖ Error ' + xhr.status + ' while fetching file: ' + xhr.statusText;
                    }
                    else {
                        code.textContent = '✖ Error: File does not exist or is empty';
                    }
                }
            };

            xhr.send(null);
        });
    }

    $(document).ready(function(){
        loadExternalCodeSnippets();
    });
    $('#source-view').on('shown', function () {
        loadExternalCodeSnippets();
    })
</script>
{% endblock %}

{% block content %}
    <section class="row-fluid">
        <div class="span2 sidebar">
            {% set namespace = project.namespace %}
            {{ block('sidebarNamespaces') }}
        </div>
    </section>
    <section class="row-fluid">
        <div class="span10 offset2">
            <div class="row-fluid">
                <div class="span8 content class">
                    <nav>
                        {#<a href="" class="pull-left">&laquo; NamespaceAssembler</a>#}
                        {{ node.namespace|route|raw }} <i class="icon-level-up"></i>
                        {#<a href="" class="pull-right">ClassAssembler &raquo;</a>#}
                    </nav>
                    <a href="#source-view" role="button" class="pull-right btn" data-toggle="modal"><i class="icon-code"></i></a>

                    <h1><small>{{ node.namespace }}</small>{{ node.name }}</h1>
                    <p><em>{{ node.summary }}</em></p>
                    {{ node.description|markdown|raw }}

                    <section id="summary">
                        <h2>Summary</h2>
                        <section class="row-fluid heading">
                            <section class="span4">
                                <a href="#methods">Methods</a>
                            </section>
                            <section class="span4">
                                <a href="#properties">Properties</a>
                            </section>
                            <section class="span4">
                                <a href="#constants">Constants</a>
                            </section>
                        </section>
                        <section class="row-fluid public">
                            <section class="span4">
                                {% for method in node.methods.merge(node.inheritedMethods.merge(node.magicMethods)) if method.visibility == 'public' %}
                                    <a href="{{ method|route('url')}}" class="{{ method.deprecated ? 'deprecated' }}">{{ method.name }}()</a><br />
                                {% else %}
                                    <em>No public methods found</em>
                                {% endfor %}
                            </section>
                            <section class="span4">
                                {% for property in node.properties.merge(node.inheritedProperties.merge(node.magicProperties)) if property.visibility == 'public' %}
                                    <a href="{{ property|route('url')}}" class="{{ property.deprecated ? 'deprecated' }}">${{ property.name }}</a><br />
                                {% else %}
                                    <em>No public properties found</em>
                                {% endfor %}
                            </section>
                            <section class="span4">
                                {% for constant in node.constants.merge(node.inheritedConstants) %}
                                    <a href="{{ constant|route('url')}}" class="{{ constant.deprecated ? 'deprecated' }}">{{ constant.name }}</a><br />
                                {% else %}
                                    <em>No constants found</em>
                                {% endfor %}
                            </section>
                        </section>
                        <section class="row-fluid protected">
                            <section class="span4">
                                {% for method in node.methods.merge(node.inheritedMethods.merge(node.magicMethods)) if method.visibility == 'protected' %}
                                    <a href="{{ method|route('url')}}" class="{{ method.deprecated ? 'deprecated' }}">{{ method.name }}()</a><br />
                                {% else %}
                                    <em>No protected methods found</em>
                                {% endfor %}
                            </section>
                            <section class="span4">
                                {% for property in node.properties.merge(node.inheritedProperties.merge(node.magicProperties)) if property.visibility == 'protected' %}
                                    <a href="{{ property|route('url')}}" class="{{ property.deprecated ? 'deprecated' }}">${{ property.name }}</a><br />
                                {% else %}
                                    <em>No protected properties found</em>
                                {% endfor %}
                            </section>
                            <section class="span4">
                                <em>N/A</em>
                            </section>
                        </section>
                        <section class="row-fluid private">
                            <section class="span4">
                                {% for method in node.methods.merge(node.inheritedMethods.merge(node.magicMethods)) if method.visibility == 'private' %}
                                    <a href="{{ method|route('url')}}" class="{{ method.deprecated ? 'deprecated' }}">{{ method.name }}()</a><br />
                                {% else %}
                                    <em>No private methods found</em>
                                {% endfor %}
                            </section>
                            <section class="span4">
                                {% for property in node.properties.merge(node.inheritedProperties.merge(node.magicProperties)) if property.visibility == 'private' %}
                                    <a href="{{ property|route('url')}}" class="{{ property.deprecated ? 'deprecated' }}">${{ property.name }}</a><br />
                                {% else %}
                                    <em>No private properties found</em>
                                {% endfor %}
                            </section>
                            <section class="span4">
                                <em>N/A</em>
                            </section>
                        </section>
                    </section>
                </div>
                <aside class="span4 detailsbar">
                    {% if node.abstract %}
                        <span class="label label-info">abstract</span>
                    {% endif %}
                    {% if node.final %}
                        <span class="label label-info">final</span>
                    {% endif %}

                    {% if method.deprecated %}
                        <aside class="alert alert-block alert-error">
                            <h4>Deprecated</h4>
                            {{ method.tags.deprecated[0].description }}
                        </aside>
                    {% endif %}

                    <dl>
                        <dt>File</dt>
                            <dd><a href="{{ node.file|route('url') }}"><div class="path-wrapper">{{ node.path }}</div></a></dd>
                        {% if node.package is not empty and node.package != '\\' %}
                        <dt>Package</dt>
                            <dd><div class="namespace-wrapper">{{ node.subpackage ? (node.package ~ '\\' ~ node.subpackage) : node.package }}</div></dd>
                        {% endif %}
                        <dt>Class hierarchy</dt>
                            <dd class="hierarchy">
                                {% set class = node.parent %}
                                {% block hierarchy_element %}
                                    {% if class %}
                                        {% set child = class %}
                                        {% set class = class.parent %}
                                        {{ block('hierarchy_element') }}
                                        <div class="namespace-wrapper">{{ child|route|raw }}</div>
                                    {% endif %}
                                {% endblock %}
                                <div class="namespace-wrapper">{{ node.fullyQualifiedStructuralElementName}}</div>
                            </dd>

                        {% for interface in node.implements %}
                            {% if loop.first %}
                        <dt>Implements</dt>
                            {% endif %}
                            <dd><a href="{{ interface|route('url') }}"><div class="namespace-wrapper">{{ interface.fullyQualifiedStructuralElementName }}</div></a></dd>
                        {% endfor %}

                        {% for trait in node.usedTraits %}
                            {% if loop.first %}
                                <dt>Uses traits</dt>
                            {% endif %}
                            <dd>
                                {% if trait.fullyQualifiedStructuralElementName %}<a href="{{ trait|route('url') }}">{% endif %}
                                    <div class="namespace-wrapper">{{ trait.fullyQualifiedStructuralElementName ?: trait }}</div>
                                {% if trait.fullyQualifiedStructuralElementName %}</a>{% endif %}
                            </dd>
                        {% endfor %}

                        {# TODO: expensive action; replace with an index or precompiled list in descriptors #}
{#
                        {% for child in project.indexes.elements if child.parent.fullyQualifiedStructuralElementName == node.fullyQualifiedStructuralElementName %}
                            {% if loop.first %}
                        <dt>Children</dt>
                            {% endif %}
                            <dd><a href="{{ child|route('url') }}"><div class="namespace-wrapper">{{ child.fullyQualifiedStructuralElementName }}</div></a></dd>
                        {% endfor %}
#}

                        {% for tagName,tags in node.tags if tagName in ['link', 'see'] %}
                            {% if loop.first %}
                        <dt>See also</dt>
                            {% endif %}
                            {% for tag in tags %}
                            <dd><a href="{{ tag.link }}"><div class="namespace-wrapper">{{ tag.description }}</div></a></dd>
                            {% endfor %}
                        {% endfor %}

                        {#<dt>Categories</dt>#}
                            {#<dd><a href="">Assemblers</a></dd>#}
                    </dl>
                    <h2>Tags</h2>
                    <table class="table table-condensed">
                    {% for tagName,tags in node.tags if tagName not in ['link', 'see', 'abstract', 'method', 'property', 'property-read', 'property-write', 'package', 'subpackage'] %}
                        <tr>
                            <th>
                                {{ tagName }}
                            </th>
                            <td>
                                {% for tag in tags %}
                                    {{ tag.description|markdown|raw }}
                                {% endfor %}
                            </td>
                        </tr>
                    {% else %}
                        <tr><td colspan="2"><em>None found</em></td></tr>
                    {% endfor %}
                    </table>
                </aside>
            </div>

            {% set constants = node.constants.merge(node.inheritedConstants) %}
            {% if constants|length > 0 %}
            <a id="constants" name="constants"></a>
            <div class="row-fluid">
                <div class="span8 content class">
                    <h2>Constants</h2>
                </div>
                <aside class="span4 detailsbar"></aside>
            </div>

            {% for constant in constants %}
                {{ block('constant') }}
                {% endfor %}
            {% endif %}

            {% set properties = node.properties.merge(node.inheritedProperties.merge(node.magicProperties)) %}
            {% if properties|length > 0 %}
            <a id="properties" name="properties"></a>
            <div class="row-fluid">
                <div class="span8 content class">
                    <h2>Properties</h2>
                </div>
                <aside class="span4 detailsbar"></aside>
            </div>

                {% for property in properties if property.visibility == 'public' %}
                {{ block('property') }}
                {% endfor %}
                {% for property in properties if property.visibility == 'protected' %}
                {{ block('property') }}
                {% endfor %}
                {% for property in properties if property.visibility == 'private' %}
                {{ block('property') }}
                {% endfor %}
            {% endif %}

            {% set methods = node.methods.merge(node.inheritedMethods.merge(node.magicMethods)) %}
            {% if methods|length > 0 %}
            <a id="methods" name="methods"></a>
            <div class="row-fluid">
                <div class="span8 content class"><h2>Methods</h2></div>
                <aside class="span4 detailsbar"></aside>
            </div>

                {% for method in methods if method.visibility == 'public' %}
                {{ block('method') }}
                {% endfor %}
                {% for method in methods if method.visibility == 'protected' %}
                {{ block('method') }}
                {% endfor %}
                {% for method in methods if method.visibility == 'private' %}
                {{ block('method') }}
                {% endfor %}
            {% endif %}
        </div>
    </section>

    <div id="source-view" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="source-view-label" aria-hidden="true">
        <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
            <h3 id="source-view-label">{{ node.file.name }}</h3>
        </div>
        <div class="modal-body">
            <pre data-src="{{ path('files/' ~ node.path ~ '.txt') }}" class="language-php line-numbers"></pre>
        </div>
    </div>
{% endblock %}
{% use 'elements/constant.html.twig' %}
{% use 'elements/property.html.twig' %}
{% use 'elements/method.html.twig' %}
{% use 'elements/namespaces.sidebar.html.twig' %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
    <meta charset="utf-8"/>
    <title>{% block title %}{{ project.name }}{% endblock %}</title>
    <meta name="author" content=""/>
    <meta name="description" content=""/>

    <link href="https://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.no-icons.min.css" rel="stylesheet">
    <link href="https://netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.min.css" rel="stylesheet">
    <link href="{{ path('css/prism.css') }}" rel="stylesheet" media="all"/>
    <link href="{{ path('css/template.css') }}" rel="stylesheet" media="all"/>
    {% block stylesheets %}{% endblock %}

    <!--[if lt IE 9]>
    <script src="https://html5shim.googlecode.com/svn/trunk/html5.js" type="text/javascript"></script>
    <![endif]-->
    <script src="https://code.jquery.com/jquery-1.10.2.min.js" type="text/javascript"></script>
    <script src="https://code.jquery.com/ui/1.10.3/jquery-ui.min.js" type="text/javascript"></script>
    <script src="https://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
    <script src="{{ path('js/jquery.smooth-scroll.js') }}"></script>
    <script src="{{ path('js/prism.min.js') }}"></script>
    <!-- TODO: Add http://jscrollpane.kelvinluck.com/ to style the scrollbars for browsers not using webkit-->
    {% block javascripts %}{% endblock %}

    <link rel="shortcut icon" href="{{ path('images/favicon.ico') }}"/>
    <link rel="apple-touch-icon" href="{{ path('images/apple-touch-icon.png') }}"/>
    <link rel="apple-touch-icon" sizes="72x72" href="{{ path('images/apple-touch-icon-72x72.png') }}"/>
    <link rel="apple-touch-icon" sizes="114x114" href="{{ path('images/apple-touch-icon-114x114.png') }}"/>
</head>
<body>

<div class="navbar navbar-fixed-top">
    <div class="navbar-inner">
        <div class="container">
            <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
                <i class="icon-ellipsis-vertical"></i>
            </a>
            <a class="brand" href="{{  path('index.html') }}">{{ project.name }}</a>

            <div class="nav-collapse">
                <ul class="nav pull-right">
                    <li class="dropdown">
                        <a href="{{ path('index.html') }}" class="dropdown-toggle" data-toggle="dropdown">
                            API Documentation <b class="caret"></b>
                        </a>
                        <ul class="dropdown-menu">
                            {% for namespace in project.namespace.children %}
                            <li>{{ namespace|route|raw }}</li>
                            {% endfor %}
                        </ul>
                    </li>
                    <li class="dropdown" id="charts-menu">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown">
                            Charts <b class="caret"></b>
                        </a>
                        <ul class="dropdown-menu">
                            <li>
                                <a href="{{ path('graphs/class.html') }}">
                                    <i class="icon-list-alt"></i>&#160;Class hierarchy diagram
                                </a>
                            </li>
                        </ul>
                    </li>
                    <li class="dropdown" id="reports-menu">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown">
                            Reports <b class="caret"></b>
                        </a>
                        <ul class="dropdown-menu">
                            <li>
                                <a href="{{ path('reports/errors.html') }}">
                                    {% set errorCount = 0 %}
                                    {% for file in project.files %}
                                        {% set errorCount = errorCount + file.allerrors.count %}
                                    {% endfor %}
                                    <i class="icon-list-alt"></i>&#160;Errors <span class="label label-info pull-right">{{ errorCount }}</span>
                                </a>
                            </li>
                            <li>
                                <a href="{{ path('reports/markers.html') }}">
                                    {% set markerCount = 0 %}
                                    {% for file in project.files %}
                                        {% set markerCount = markerCount + file.markers.count %}
                                    {% endfor %}
                                    <i class="icon-list-alt"></i>&#160;Markers <span class="label label-info pull-right">{{ markerCount }}</span>
                                </a>
                            </li>
{#
                            <li>
                                <a href="{{ path('reports/deprecated.html') }}">
                                    <i class="icon-list-alt"></i>&#160;Deprecated
                                </a>
                            </li>
#}
                        </ul>
                    </li>
                </ul>
            </div>
        </div>
    </div>
    <!--<div class="go_to_top">-->
    <!--<a href="#___" style="color: inherit">Back to top&#160;&#160;<i class="icon-upload icon-white"></i></a>-->
    <!--</div>-->
</div>

<div id="___" class="container-fluid">
    {% block content %}{% endblock %}

    <footer class="row-fluid">
        <section class="span10 offset2">
            <section class="row-fluid">
                <section class="span10 offset1">
                    <section class="row-fluid footer-sections">
                        <section class="span4">
                            {#Doc#}
                            <h1><i class="icon-code"></i></h1>
                            <div>
                                <ul>
                                    {% for namespace in project.namespace.children %}
                                        <li>{{ namespace|route|raw }}</li>
                                    {% endfor %}
                                </ul>
                            </div>
                        </section>
                        <section class="span4">
                            {#Graphs#}
                            <h1><i class="icon-bar-chart"></i></h1>
                            <div>
                                <ul>
                                    <li><a href="{{ path('graphs/class.html') }}">Class Hierarchy Diagram</a></li>
                                </ul>
                            </div>
                        </section>
                        <section class="span4">
                            {#Reports#}
                            <h1><i class="icon-pushpin"></i></h1>
                            <div>
                                <ul>
                                    <li><a href="{{ path('reports/errors.html') }}">Errors</a></li>
                                    <li><a href="{{ path('reports/markers.html') }}">Markers</a></li>
                                </ul>
                            </div>
                        </section>
                    </section>
                </section>
            </section>
            <section class="row-fluid">
                <section class="span10 offset1">
                    <hr />
                    Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor </a> and authored
                    on {{ "now"|date('F jS, Y \\a\\t H:i') }}.
                </section>
            </section>
        </section>
    </footer>
</div>

</body>
</html>
{{ node.source|raw }}
{% extends 'layout.html.twig' %}

{% block javascripts %}
    <script type="text/javascript">
        function loadExternalCodeSnippets() {
            Array.prototype.slice.call(document.querySelectorAll('pre[data-src]')).forEach(function (pre) {
                var src = pre.getAttribute('data-src');
                var extension = (src.match(/\.(\w+)$/) || [, ''])[1];
                var language = 'php';

                var code = document.createElement('code');
                code.className = 'language-' + language;

                pre.textContent = '';

                code.textContent = 'Loading…';

                pre.appendChild(code);

                var xhr = new XMLHttpRequest();

                xhr.open('GET', src, true);

                xhr.onreadystatechange = function () {
                    if (xhr.readyState == 4) {

                        if (xhr.status < 400 && xhr.responseText) {
                            code.textContent = xhr.responseText;

                            Prism.highlightElement(code);
                        }
                        else if (xhr.status >= 400) {
                            code.textContent = '✖ Error ' + xhr.status + ' while fetching file: ' + xhr.statusText;
                        }
                        else {
                            code.textContent = '✖ Error: File does not exist or is empty';
                        }
                    }
                };

                xhr.send(null);
            });
        }

        $(document).ready(function(){
            loadExternalCodeSnippets();
        });
        $('#source-view').on('shown', function () {
            loadExternalCodeSnippets();
        })
    </script>
{% endblock %}

{% block content %}
    <section class="row-fluid">
        <div class="span2 sidebar">
            {% set namespace = project.namespace %}
            {{ block('sidebarNamespaces') }}
        </div>
    </section>
    <section class="row-fluid">
        <div class="span10 offset2">
            <div class="row-fluid">
                <div class="span8 content class">
                    <nav>
                        {#<a href="" class="pull-left">&laquo; NamespaceAssembler</a>#}
                        {{ node.namespace|route|raw }}
                        {#<a href="" class="pull-right">ClassAssembler &raquo;</a>#}
                    </nav>
                    <a href="#source-view" role="button" class="pull-right btn" data-toggle="modal"><i class="icon-code"></i></a>

                    <h1><small>{{ node.namespace }}</small>{{ node.name }}</h1>
                    <p><em>{{ node.summary }}</em></p>
                    {{ node.description|markdown|raw }}

                    <section id="summary">
                        <h2>Summary</h2>
                        <section class="row-fluid heading">
                            <section class="span6">
                                <a href="#methods">Methods</a>
                            </section>
                            <section class="span6">
                                <a href="#constants">Constants</a>
                            </section>
                        </section>
                        <section class="row-fluid public">
                            <section class="span6">
                                {% for method in node.methods.merge(node.inheritedMethods) if method.visibility == 'public' %}
                                    <a href="{{ method|route('url')}}">{{ method.name }}()</a><br />
                                {% else %}
                                    <em>No public methods found</em>
                                {% endfor %}
                            </section>
                            <section class="span6">
                                {% for constant in node.constants.merge(node.inheritedConstants) %}
                                    <a href="{{ constant|route('url')}}">{{ constant.name }}</a><br />
                                {% else %}
                                    <em>No constants found</em>
                                {% endfor %}
                            </section>
                        </section>
                        <section class="row-fluid protected">
                            <section class="span6">
                                {% for method in node.methods.merge(node.inheritedMethods) if method.visibility == 'protected' %}
                                    <a href="{{ method|route('url')}}">{{ method.name }}()</a><br />
                                {% else %}
                                    <em>No protected methods found</em>
                                {% endfor %}
                            </section>
                            <section class="span6">
                                <em>N/A</em>
                            </section>
                        </section>
                        <section class="row-fluid private">
                            <section class="span6">
                                {% for method in node.methods.merge(node.inheritedMethods) if method.visibility == 'private' %}
                                    <a href="{{ method|route('url')}}">{{ method.name }}()</a><br />
                                {% else %}
                                    <em>No private methods found</em>
                                {% endfor %}
                            </section>
                            <section class="span6">
                                <em>N/A</em>
                            </section>
                        </section>
                    </section>
                </div>
                <aside class="span4 detailsbar">
                    {% if method.deprecated %}
                        <aside class="alert alert-block alert-error">
                            <h4>Deprecated</h4>
                            {{ method.tags.deprecated[0].description }}
                        </aside>
                    {% endif %}
                    <dl>
                        <dt>File</dt>
                            <dd>
                                <a href="{{ node.file|route('url') }}"><div class="path-wrapper">{{ node.path }}</div></a>
                            </dd>
                        {% if node.package is not empty and node.package != '\\' %}
                        <dt>Package</dt>
                            <dd><div class="namespace-wrapper">{{ node.subpackage ? (node.package ~ '\\' ~ node.subpackage) : node.package }}</div></dd>
                        {% endif %}
                        {% for parent in node.parent %}
                            {% if loop.first %}
                        <dt>Parents</dt>
                            {% endif %}
                            <dd><a href="{{ parent|route('url') }}"><div class="namespace-wrapper">{{ parent.fullyQualifiedStructuralElementName }}</div></a></dd>
                        {% endfor %}

                        {% for tagName,tags in node.tags if tagName in ['link', 'see'] %}
                            {% if loop.first %}
                        <dt>See also</dt>
                            {% endif %}
                            {% for tag in tags %}
                            <dd><a href="{{ tag.link }}"><div class="namespace-wrapper">{{ tag.description }}</div></a></dd>
                            {% endfor %}
                        {% endfor %}
                    </dl>
                    <h2>Tags</h2>
                    <table class="table table-condensed">
                    {% for tagName,tags in node.tags if tagName not in ['link', 'see', 'abstract', 'method', 'package', 'subpackage'] %}
                        <tr>
                            <th>{{ tagName }}</th>
                            <td>
                                {% for tag in tags %}
                                    {{ tag.description|markdown|raw }}
                                {% endfor %}
                            </td>
                        </tr>
                    {% else %}
                        <tr><td colspan="2"><em>None found</em></td></tr>
                    {% endfor %}
                    </table>
                </aside>
            </div>

            {% if node.constants|length > 0 %}
                <a id="constants" name="constants"></a>
                <div class="row-fluid">
                <div class="span8 content class">
                    <h2>Constants</h2>
                </div>
                <aside class="span4 detailsbar"></aside>
            </div>

            {% for constant in node.constants.merge(node.inheritedConstants) %}
                {{ block('constant') }}
                {% endfor %}
            {% endif %}

            {% if node.methods.merge(node.inheritedMethods)|length > 0 %}
            <div class="row-fluid">
                <div class="span8 content class">
                    <h2>Methods</h2>
                </div>
                <aside class="span4 detailsbar"></aside>
            </div>

                {% for method in node.methods.merge(node.inheritedMethods) if method.visibility == 'public' %}
                {{ block('method') }}
                {% endfor %}
                {% for method in node.methods.merge(node.inheritedMethods) if method.visibility == 'protected' %}
                {{ block('method') }}
                {% endfor %}
                {% for method in node.methods.merge(node.inheritedMethods) if method.visibility == 'private' %}
                {{ block('method') }}
                {% endfor %}
            {% endif %}
        </div>
    </section>

    <div id="source-view" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="source-view-label" aria-hidden="true">
        <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
            <h3 id="source-view-label">{{ node.file.name }}</h3>
        </div>
        <div class="modal-body">
            <pre data-src="{{ path('files/' ~ node.path ~ '.txt') }}" class="language-php"></pre>
        </div>
    </div>
{% endblock %}
{% block sidebarNamespaces %}
    {% set code = random() %}
    <div class="accordion" style="margin-bottom: 0">
        <div class="accordion-group">
            <div class="accordion-heading">
                {% if namespace.children|length > 0 or namespace.classes|length > 0 or namespace.interfaces|length > 0 or namespace.traits|length > 0 %}
                    <a class="accordion-toggle {{ namespace.name != '\\' ? 'collapsed' }}" data-toggle="collapse" data-target="#namespace-{{ code }}"></a>
                {% endif %}
                <a href="{{ namespace|route("url")|raw }}" style="margin-left: 30px; padding-left: 0">{{ namespace.name }}</a>
            </div>
            <div id="namespace-{{ code }}" class="accordion-body collapse {{ namespace.name == '\\' ? 'in' }}">
                <div class="accordion-inner">

                    {% for namespace in namespace.children %}
                        {{ block('sidebarNamespaces') }}
                    {% endfor %}

                    <ul>
                        {% for class in namespace.interfaces %}
                            <li class="interface">{{ class|route('class:short')|raw }}</li>
                        {% endfor %}
                        {% for class in namespace.traits %}
                            <li class="trait">{{ class|route('class:short')|raw }}</li>
                        {% endfor %}
                        {% for class in namespace.classes %}
                            <li class="class">{{ class|route('class:short')|raw }}</li>
                        {% endfor %}
                    </ul>
                </div>
            </div>
        </div>
    </div>
{% endblock %}
{% block property %}
    <div class="row-fluid">
        <div class="span8 content class">
            <a id="property_{{ property.name }}" name="property_{{ property.name }}" class="anchor"></a>
            <article class="property">
                <h3 class="{{ property.visibility }} {% if property.deprecated %}deprecated{% endif %}">${{ property.name }}</h3>
                <pre class="signature">${{ property.name }}{% if property.types %} : {{ property.types|join('|') }}{% endif %}</pre>
                <p><em>{{ property.summary }}</em></p>
                {{ property.description|markdown|raw }}

                {% if property.types %}
                <h4>Type</h4>
                {{ property.types|route|join('|')|raw }}
                {% if property.var.0.description %}&mdash; {{ property.var.0.description }}{% endif %}
                {% endif %}
            </article>
        </div>
        <aside class="span4 detailsbar">
            <h1><i class="icon-arrow-down"></i></h1>
            {% if property.deprecated %}
                <aside class="alert alert-block alert-error">
                    <h4>Deprecated</h4>
                    {{ property.tags.deprecated[0].description }}
                </aside>
            {% endif %}
            <dl>
                {% if (node.parent is not null and property.parent.fullyQualifiedStructuralElementName != node.fullyQualifiedStructuralElementName) %}
                    <dt>Inherited from</dt>
                    <dd><a href="{{ property.parent|route('url') }}"><div class="path-wrapper">{{ property.parent.fullyQualifiedStructuralElementName }}</div></a></dd>
                {% endif %}
                {% for tagName,tags in property.tags if tagName in ['link', 'see'] %}
                    {% if loop.first %}
                        <dt>See also</dt>
                    {% endif %}
                    {% for tag in tags %}
                        <dd><a href="{{ tag.reference|route('url') }}"><span class="namespace-wrapper">{{ tag.description }}</span></a></dd>
                    {% endfor %}
                {% endfor %}
                {% for tagName,tags in method.tags if tagName in ['uses'] %}
                    {% if loop.first %}
                        <dt>Uses</dt>
                    {% endif %}
                    {% for tag in tags %}
                        <dd>{{ tag.reference|route|raw }}</dd>
                    {% endfor %}
                {% endfor %}
            </dl>
            <h2>Tags</h2>
            <table class="table table-condensed">
                {% for tagName,tags in property.tags if tagName not in ['link', 'see', 'access', 'var', 'deprecated', 'uses'] %}
                    <tr>
                        <th>
                            {{ tagName }}
                        </th>
                        <td>
                            {% for tag in tags %}
                                {{ tag.description|markdown|raw }}
                            {% endfor %}
                        </td>
                    </tr>
                {% else %}
                    <tr><td colspan="2"><em>None found</em></td></tr>
                {% endfor %}
            </table>
        </aside>
    </div>
{% endblock %}
{% block method %}
    <div class="row-fluid">
        <div class="span8 content class">
            <a id="method_{{ method.name }}" name="method_{{ method.name }}" class="anchor"></a>
            <article class="method">
                <h3 class="{{ method.visibility }} {% if method.deprecated %}deprecated{% endif %}">{{ method.name }}()</h3>
                <a href="#source-view" role="button" class="pull-right btn" data-toggle="modal" style="font-size: 1.1em; padding: 9px 14px"><i class="icon-code"></i></a>
                <pre class="signature" style="margin-right: 54px;">{{ method.name }}({% for argument in method.arguments %}{{ argument.types|join('|') }} <span class="argument">{{ argument.name }}</span>{% if not loop.last %}, {% endif %}{% endfor %}){% if method.response %} : {{ method.response.types|join('|') }}{% endif %}</pre>
                <p><em>{{ method.summary }}</em></p>
                {{ method.description|markdown|raw }}

                {% if method.arguments|length > 0 %}
                    <h4>Parameters</h4>
                    <table class="table table-condensed table-hover">
                        {% for argument in method.arguments %}
                            <tr>
                                <td>{{ argument.types|route|join('|')|raw }}</td>
                                <td>{{ argument.name }}</td>
                                <td>{{ argument.description|markdown|raw }}</td>
                            </tr>
                        {% endfor %}
                    </table>
                {% endif %}

                {% if method.tags.throws|length > 0 or method.tags.throw|length > 0 %}
                    <h4>Throws</h4>
                    <dl>
                        {% for exception in method.tags.throws %}
                            <dt>{{ exception.types|route|join('|')|raw }}</dt>
                            <dd>{{ exception.description|markdown|raw }}</dd>
                        {% endfor %}
                        {% for exception in method.tags.throw %}
                            <dt>{{ exception.types|route|join('|')|raw }}</dt>
                            <dd>{{ exception.description|markdown|raw }}</dd>
                        {% endfor %}
                    </dl>
                {% endif %}

                {% if method.response and method.response.types|join() != 'void' %}
                    <h4>Returns</h4>
                    {{ method.response.types|route|join('|')|raw }}
                    {% if method.response.description %}
                        &mdash; {{ method.response.description|markdown|raw }}
                    {% endif %}
                {% endif %}
            </article>
        </div>
        <aside class="span4 detailsbar">
            <h1><i class="icon-arrow-down"></i></h1>
            {% if method.static %}
                <span class="label label-info">static</span>
            {% endif %}
            {% if method.abstract %}
                <span class="label label-info">abstract</span>
            {% endif %}
            {% if method.final %}
                <span class="label label-info">final</span>
            {% endif %}
            {% if method.deprecated %}
                <aside class="alert alert-block alert-error">
                    <h4>Deprecated{% if method.tags.deprecated[0].version %} since {{ method.tags.deprecated[0].version }}{% endif %}</h4>
                    {{ method.tags.deprecated[0].description }}
                </aside>
            {% endif %}
            <dl>
                {% if (node.parent is null) %}
                    <dt>File</dt>
                    <dd><a href="{{ node.file|route('url') }}"><div class="path-wrapper">{{ node.path }}</div></a></dd>
                {% endif %}
                {% if (node.parent is not null and method.parent.fullyQualifiedStructuralElementName != node.fullyQualifiedStructuralElementName) %}
                    <dt>Inherited from</dt>
                    <dd><a href="{{ method.parent|route('url') }}"><div class="path-wrapper">{{ method.parent.fullyQualifiedStructuralElementName }}</div></a></dd>
                {% endif %}
                {% for tagName,tags in method.tags if tagName in ['link', 'see'] %}
                    {% if loop.first %}
                        <dt>See also</dt>
                    {% endif %}
                    {% for tag in tags %}
                        <dd><a href="{{ (tag.reference|route('url')) ?: tag.link }}"><span class="namespace-wrapper">{{ tag.description }}</span></a></dd>
                    {% endfor %}
                {% endfor %}
                {% for tagName,tags in method.tags if tagName in ['uses'] %}
                    {% if loop.first %}
                        <dt>Uses</dt>
                    {% endif %}
                    {% for tag in tags %}
                        <dd>{{ tag.reference|route|raw }}</dd>
                    {% endfor %}
                {% endfor %}
            </dl>
            <h2>Tags</h2>
            <table class="table table-condensed">
                {% for tagName,tags in method.tags if tagName not in ['link', 'see', 'abstract', 'param', 'return', 'access', 'deprecated', 'throws', 'throw', 'uses'] %}
                    <tr>
                        <th>
                            {{ tagName }}
                        </th>
                        <td>
                            {% for tag in tags %}
                                {% if tag.version %}{{ tag.version }}{% endif %}
                                {{ tag.description|markdown|raw }}
                            {% endfor %}
                        </td>
                    </tr>
                {% else %}
                    <tr><td colspan="2"><em>None found</em></td></tr>
                {% endfor %}
            </table>
        </aside>
    </div>
{% endblock %}
{% block constant %}
    <div class="row-fluid">
        <div class="span8 content class">
            <a id="constant_{{ constant.name }}" name="constant_{{ constant.name }}" class="anchor"></a>
            <article id="constant_{{ constant.name }}" class="constant">
                <h3 class="{% if constant.deprecated %}deprecated{% endif %}">{{ constant.name }}</h3>
                <pre class="signature">{{ constant.name }}</pre>
                <p><em>{{ constant.summary }}</em></p>
                {{ constant.description|markdown|raw }}
            </article>
        </div>
        <aside class="span4 detailsbar">
            <h1><i class="icon-arrow-down"></i></h1>
            {% if constant.deprecated %}
                <aside class="alert alert-block alert-error">
                    <h4>Deprecated</h4>
                    {{ constant.tags.deprecated[0].description }}
                </aside>
            {% endif %}
            <dl>
                {% if (node.parent is null) %}
                <dt>File</dt>
                <dd><a href="{{ node.file|route('url') }}"><div class="path-wrapper">{{ node.path }}</div></a></dd>
                {% endif %}
                {% if (node.parent is not null and constant.parent.fullyQualifiedStructuralElementName != node.fullyQualifiedStructuralElementName) %}
                    <dt>Inherited from</dt>
                    <dd><a href="{{ constant.parent|route('url') }}"><div class="path-wrapper">{{ constant.parent.fullyQualifiedStructuralElementName }}</div></a></dd>
                {% endif %}
                {% for tagName,tags in constant.tags if tagName in ['link', 'see'] %}
                    {% if loop.first %}
                        <dt>See also</dt>
                    {% endif %}
                    {% for tag in tags %}
                        <dd><a href="{{ tag.reference|route('url') }}"><span class="namespace-wrapper">{{ tag.description }}</span></a></dd>
                    {% endfor %}
                {% endfor %}
                {% for tagName,tags in method.tags if tagName in ['uses'] %}
                    {% if loop.first %}
                        <dt>Uses</dt>
                    {% endif %}
                    {% for tag in tags %}
                        <dd>{{ tag.reference|route|raw }}</dd>
                    {% endfor %}
                {% endfor %}
            </dl>
            <h2>Tags</h2>
            <table class="table table-condensed">
                {% for tagName,tags in constant.tags if tagName not in ['link', 'see', 'var', 'deprecated', 'uses'] %}
                    <tr>
                        <th>
                            {{ tagName }}
                        </th>
                        <td>
                            {% for tag in tags %}
                                {{ tag.description|markdown|raw }}
                            {% endfor %}
                        </td>
                    </tr>
                {% else %}
                    <tr><td colspan="2"><em>None found</em></td></tr>
                {% endfor %}
            </table>
        </aside>
    </div>
{% endblock %}
{
    "name": "phpdocumentor/template-zend",
    "type": "phpdocumentor-template",
    "description": "Official Zend Framework Template for phpDocumentor2",
    "keywords": ["documentation", "template", "phpdoc", "zf", "zend", "zendframework"],
    "homepage": "http://www.phpdoc.org",
    "license": "MIT",
    "require": {
        "ext-xsl": "*",
        "phpdocumentor/unified-asset-installer": "~1.1",
        "phpdocumentor/template-abstract": "1.*"
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.9.4" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
    http://pear.php.net/dtd/tasks-1.0.xsd
    http://pear.php.net/dtd/package-2.0
    http://pear.php.net/dtd/package-2.0.xsd">
 <name>phpDocumentor_Template_zend</name>
 <channel>pear.phpdoc.org</channel>
 <summary>The zend template for phpDocumentor</summary>
 <description>This is the look and feel for Zend Framework</description>
 <lead>
  <name>Mike van Riel</name>
  <user />
  <email>mike.vanriel@naenius.com</email>
  <active>yes</active>
 </lead>
 <date>2012-04-01</date>
 <time>10:35:34</time>
 <version>
  <release>1.0.2</release>
  <api>1.0.2</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license uri="http://www.opensource.org/licenses/mit-license.html">MIT</license>
 <notes>
Automatically generated by the phpDocumentor packager
 </notes>
 <contents>
  <dir baseinstalldir="/phpDocumentor/data/templates/zend" name="/">
   <dir name="css">
    <file name="manual.css" role="php" />
    <file name="template.css" role="php" />
   </dir> <!-- /css -->
   <dir name="images">
    <file name="behind-the-site.gif" role="php" />
   </dir> <!-- /images -->
   <dir name="js">
    <file name="template.js" role="php" />
   </dir> <!-- /js -->
   <file name="index.xsl" role="php" />
   <file name="page_header.xsl" role="php" />
   <file name="README" role="php" />
   <file name="template.xml" role="php" />
  </dir> <!-- / -->
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.2.6</min>
   </php>
   <pearinstaller>
    <min>1.4.0</min>
   </pearinstaller>
   <package>
    <name>PEAR</name>
    <channel>pear.php.net</channel>
    <min>1.4.0</min>
   </package>
   <package>
    <name>phpDocumentor</name>
    <channel>pear.phpdoc.org</channel>
    <min>0.17.0</min>
   </package>
   <package>
    <name>phpDocumentor_Template_abstract</name>
    <channel>pear.phpdoc.org</channel>
    <min>1.0.3</min>
   </package>
  </required>
 </dependencies>
 <phprelease />
 <changelog>
  <release>
   <version>
    <release>1.0.2</release>
    <api>1.0.2</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2012-04-01</date>
   <license uri="http://www.opensource.org/licenses/mit-license.html">MIT</license>
   <notes>
Automatically generated by the phpDocumentor packager
   </notes>
  </release>
 </changelog>
</package>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:import href="../abstract/index.xsl" />
    <xsl:output indent="yes" method="html" />

    <xsl:template name="page-header">
        <div id="top">
            <div class="top">
                <h1 class="logo">
                    <a href="http://framework.zend.com/" title="ZF Zend Framework">ZF Zend Framework</a>
                </h1>
                <ul id="top-nav" class="top-nav">
                    <li>
                        <a href="graph.html" target="content">Class diagram</a>
                    </li>
                    <li>
                        <a href="report_markers.html" target="content">Todo / Fixme</a>
                    </li>
                    <li>
                        <a href="report_parse_markers.html" target="content">Errors</a>
                    </li>
                    <li>
                        <a href="report_deprecated.html" target="content">Deprecated elements</a>
                    </li>
                </ul>
            </div>
        </div>
    </xsl:template>

    <xsl:template match="/blabla">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
      <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <meta http-equiv="Content-Language" content="en" />
        <title>Zend Framework: API Documentation</title>
        <link rel="stylesheet" href="{$root}css/black-tie/jquery-ui-1.8.2.custom.css" type="text/css" />
        <link rel="stylesheet" href="{$root}css/jquery.treeview.css" type="text/css" />
        <link rel="stylesheet" href="{$root}css/template.css" type="text/css" />
        <script type="text/javascript" src="{$root}js/jquery-1.4.2.min.js"></script>
        <script type="text/javascript" src="{$root}js/jquery-ui-1.8.2.custom.min.js"></script>
        <script type="text/javascript" src="{$root}js/jquery.cookie.js"></script>
        <script type="text/javascript" src="{$root}js/jquery.treeview.js"></script>
        <script type="text/javascript" src="{$root}js/jquery.splitter.js"></script>
      </head>
      <body>

        <table id="page">
          <tr><td height="51">
            <div id="top">
              <div class="top">
                <h1 class="logo">
                  <a href="http://framework.zend.com/" title="ZF Zend Framework">ZF Zend Framework</a>
                </h1>
                  <ul id="top-nav" class="top-nav">
                      <li><a href="graph.html" target="content">Class diagram</a></li>
                      <li><a href="markers.html" target="content">Todo / Fixme</a></li>
                      <li><a href="parse_markers.html" target="content">Errors</a></li>
                  </ul>
              </div>
            </div>
          </td></tr>
          <tr>
            <td class="resizable">
                <div id="sidebar">
                    <iframe name="nav" id="nav" src="{$root}nav.html" frameBorder="0"></iframe>
                </div>
                <div id="contents">
                    <iframe name="content" id="content" src="{$root}content.html" frameBorder="0"></iframe>
                </div>
            </td>
          </tr>
        </table>

      </body>
    </html>
  </xsl:template>

</xsl:stylesheet>
function filterElements() {
    inherited = !$('#show-inherited').hasClass('deselected');
    public = !$('#show-public').hasClass('deselected');
    protected = !$('#show-protected').hasClass('deselected');
    private = !$('#show-private').hasClass('deselected');

    $('div.public').each(function(index, val) {
        $(val).toggle(public && !($(val).hasClass('inherited_from') && !inherited));
    });
    $('div.protected').each(function(index, val) {
        $(val).toggle(protected && !($(val).hasClass('inherited_from') && !inherited));
    });
    $('div.private').each(function(index, val) {
        $(val).toggle(private && !($(val).hasClass('inherited_from') && !inherited));
    });
}

$(document).ready(function() {
    $('#show-public, #show-protected, #show-private, #show-inherited')
            .css('cursor', 'pointer')
            .click(function() {
                $(this).toggleClass('deselected');
                if ($(this).hasClass('deselected')) {
                    $(this).fadeTo('fast', '0.4');
                } else {
                    $(this).fadeTo('fast', '1.0');
                }
                filterElements();
                return false;
            });
    $('#show-protected, #show-private').click();
});/* doc styles */
div.important, div.warning, div.tip
{
  margin-left:      0.3in;
  margin-right:     0.5in;
  border:           solid 1px blue;
  background-color: #e0e0e0;
  padding:          0.1in;
}

div.important img, div.warning img, div.tip img
{
  margin-right: 0.1in;
  border:       solid 1px blue;
}

div.example
{
  background:  #f0f9fc;
  border-left: 2px solid #c2c9d1;
  padding:     1em;
  margin:      1em 0 1em 1em;
}

div.example p.title
{
  padding-top: 10px;
  font-size:   1.083em;
  font-weight: bold;
}

div.programlisting
{
  background:    #e2f1f8;
  padding:       0.5em 0.5em 0.5em 1.5em;
  margin-bottom: 1em;
  border-left:   1px solid #c2c9d1;
  font-family:   Consolas, Lucida Console, monospace;
}

pre.programlisting
{
  border:           solid 1px #444;
  background-color: #e0e0e0;
  padding:          0.1in;
  margin:           0.2in;
}

pre.screen
{
  border:           solid 1px #777;
  background-color: #ddd;
  padding:          0.1in;
  margin:           0.2in;
}

div.variablelist dl dt span.term
{
  font-weight: bold;
}

div.navheader
{
  padding-bottom: 0.1in;
  border-bottom:  solid 1px black;
  border-color:   #aaa;
}

div.navfooter
{
  margin-top:   0.1in;
  border-top:   solid 1px black;
  border-color: #aaa;
  padding-top:  0.1in;
}

div.figure-float
{
  float:         right;
  margin-left:   2em;
  margin-bottom: 2em;
}

div.revinfo
{
  text-align: center;
  font-size:  0.7em;
  font-style: italic;
}

div.rtl-language
{
  direction: rtl;
}

div.itemizedlist ul
{
  list-style: disc outside;
  padding:    0 0 1em 20px;
}

dl dt span.sect1
{
  margin-left: 2em;
}

dl dt span.sect2
{
  margin-left: 4em;
}

dl dt span.sect3
{
  margin-left: 6em;
}

dl dt span.sect4
{
  margin-left: 8em;
}

pre.programlisting
{
  direction:        ltr;
  border:           1px solid #D3E0EB;
  padding:          13px 23px;
  background-color: #EDF7FF;
  margin:           10px 0 15px 0;
  font-size:        1.2em; /* font-weight:bold; */
  font-family:      "Courier New", Courier, monospace;
  overflow:         auto;
}

code.code
{
  font-size: 1.1em;
}

p.note
{
  border:     1px solid #E4E7A7;
  background: #FFFDBD url(http://framework.zend.com/images/note.gif) 17px 12px no-repeat;
  color:      #232D30;
  padding:    15px 23px 25px 64px;
  margin:     1.75em 0;
}

div.note table th
{
  font-size:      1.083em;
  font-weight:    bold;
  padding-bottom: 4px;
}

div.note table td img
{
  margin-right: 1em;
}

#manual-container
{
  margin-right: 0 auto;
  text-align:   left;
}

#manual-container div.table th
{
  font-size:    larger;
  font-weight:  bold;
  padding-left: 4px;
}

#manual-container div.table td
{
  padding-left: 4px;
}

#manual-container ol
{
  list-style: decimal outside;
  padding:    0 0 1em 25px;
}

#manual-container ul
{
  list-style: disc outside;
  padding:    0 0 1em 20px;
}

#manual-container ul span
{
  font-weight: bold;
}

#manual-container div.info h1, #content h1
{
  font-size:     1.4em;
  color:         #0398ca;
  font-weight:   bold;
  border-bottom: 1px solid #0398ca;
  margin:        0.5em 0 0.5em 0;
}

#manual-container hr
{
  border:           none;
  width:            100%;
  color:            #0398ca;
  background-color: #0398ca;
  height:           1px;
  margin-top:       1em;
  margin-bottom:    1em;
}

ul.manual.toc li
{
  padding-left: 3em;
  text-indent:  -1em;
}

ul.manual.toc li.header.home
{
  padding-left:  0;
  text-indent:   0;
  border-bottom: 1px dotted #0398ca;
}

ul.manual.toc li.header.up
{
  padding-left:  2em;
  border-bottom: 1px dotted #0398ca;
}

.manual-version-sctr
{
  display:    none;
  visibility: hidden;
}

/* Comments */
.comments h3
{
  background-color: #0398ca;
  border-top:       1px solid #D3E0EB;
  margin-top:       2em;
  font-size:        1.25em;
  font-weight:      bold;
  padding-bottom:   4px;
  padding-left:     0.5em;
}

.comment-form h4
{
  background-color: #0398ca;
  border-top:       1px solid #D3E0EB;
  margin-top:       2em;
  font-size:        1.25em;
  font-weight:      bold;
  padding-bottom:   4px;
  padding-left:     0.5em;
}

.comment-form h4 span.expand
{
  float:        right;
  margin-right: 0.5em;
}

.comments .comment
{
  border-top:    3px solid #D3E0EB;
  margin-bottom: 1em;
}

.comments .comment:nth-child(odd)
{
  background-color: #EAF0F5;
}

.comment .admin form
{
  display: inline;
}

.comment .metadata
{
  border-bottom: 1px solid #D3E0EB;
  font-size:     0.8em;
  font-style:    oblique;
}

.comment .admin
{
  border-top: 1px solid #D3E0EB;
}

.comment .admin .status
{
  border-right: 1px solid #D3E0EB;
  margin-right: 1em;
}

.comment .admin form
{
  margin-left: 1em;
}

dl span.term, dl dt
{
  font-weight: bold;
}

dl dd
{
  margin-left: 6em;
}
@import url('abstract.css');
@import url('manual.css');

@charset
"utf-8"
;

h1.file {
    margin: 0px !important;
    top: 0px;
}

div#content {
    padding: 10px;
}

body, html {
    margin: 0px;
    padding: 0px;
}

#db-menu
{
    display: none;
}

div#file-description {
    padding-top: 0px;
}

.ui-widget {
    font-size: 0.8em;
}

div.section {
    margin: 5px;
    padding: 5px;
    padding-top: 0px;
    margin-bottom: 15px;
    border: 1px solid silver;
    -moz-border-radius: 6px;
    border-radius: 6px;
    width: 218px;
    word-wrap: break-word;
    font-size: 0.8em;
}

div.section h1 {
    border-bottom: 1px solid #5E8CDF;
    text-align: center;
    font-size: 1.1em;
    padding-bottom: 5px;
    color: #5E8CDF;
}

ul#menu {
    width: auto;
    height: auto;
    background: transparent;
    font-size: 1.0em;
}

ul#menu li {
    float: none;
    display: inherit;
    border: none;
}

ul#menu li a, .ui-widget-content a {
    color: #0087D5;
}

/* < general styles */
html, body {
    background: white;
}

table {
    border: 0;
    border-collapse: collapse;
    border-spacing: 0;
    font-size: 100%;
}

td, th {
    text-align: left;
    vertical-align: top;
    font-weight: normal;
}

img {
    border: 0;
    vertical-align: top;
}

ul, ol {
    list-style: none;
}

address {
    font-style: normal;
}

sup {
    vertical-align: top;
}

body {
    color: #444;
}

a {
    color: #0087d5;
    text-decoration: none;
    outline: 0;
}

a:hover {
    text-decoration: underline;
}

.left {
    float: left !important;
}

.right {
    float: right !important;
}

.clearer {
    clear: both;
    font-size: 1px;
    line-height: 0;
    height: 0;
    overflow: hidden;
}

.toleft {
    text-align: left !important;
}

.tocenter {
    text-align: center !important;
}

.toright {
    text-align: right !important;
}

/* < forms styles */
form dl {
    width: 80%;
    margin-left: 10%;
    margin-right: 10%;
}

form {
    display: inline;
}

fieldset {
    border: 0;
}

legend {
    display: none;
}

textarea {
    overflow: hidden;
}

input, select, textarea, button {
    font: 1em Tahoma;
    color: #444444;
    width: 100%;
    border-width: 1px;
    border-style: solid;
    border-color: #444;
}

.list-image {
    float: left;
    padding-left: 5px;
    padding-right: 10px;
    padding-top: 20px;
}

#contact-email, #contact-content, #query {
    padding-left: 3px;
}

form#searchForm dd {
    width: 100%;
    float: bottom;
}

input.btn_submit {
    cursor: pointer;
    height: 30px;
    margin-top: 10px;
    float: bottom;
    margin-left: 0px;
    background-color: #cce5ea;
    font: 1.1em Tahoma;
    text-transform: uppercase;
    color: #444;
    align: right;
}

label {
    display: block;
    vertical-align: bottom;
    color: #444;
}

label.required {
    background: url(http://framework.zend.com/images/req-asterisk.gif) left;
    background-repeat: no-repeat;
    padding-left: 26px;
}

.errors {
    color: #ff3333;
    font-weight: bold;
}

.field {
    border: 1px solid #d8d8d8;
    background-color: #fff;
    padding: 1px 3px 2px;
    overflow: hidden;
}

.field input, .field textarea {
    float: left;
    border: 0;
    background: transparent;
    width: 100%;
}

.chbr {
    width: 1.1em;
    height: 1.1em;
    margin-right: 5px;
    vertical-align: middle;
}

/* forms styles > */
/* general styles > */

#page {
    min-width: 1003px;
}

/* < top styles */
#top {
    background: #f2f2f2 url(http://framework.zend.com/images/bkg_top.gif) left top repeat-x;
    height: 51px;
}

#top .top {
    margin: 0 auto;
    width: 973px;
    text-align: left;
}

#top h1.logo {
    float: left;
    width: 123px;
    height: 23px;
    padding: 1px;
    background: url(http://framework.zend.com/images/logo_small.gif) left top no-repeat;
    margin: 10px 0 0;
    text-indent: -3000px;
    overflow: hidden;
}

#top h1.logo a {
    display: block;
    width: 123px;
    height: 23px;
}

#top-nav {
    float: left;
}

#top-nav li {
    float: left;
    height: 23px;
    font: bold small-caps 0.9em/1 Arial, Helvetica, sans-serif;
    color: #979797;
    position: relative;
    z-index: 20;
}

#top-nav li a {
    display: block;
    padding: 6px 10px;
    text-decoration: none;
    color: #6e6e6e;
}

#top-nav li a.level1:hover {
    background-color: #008ebe;
    color: #fff;
}

#top-nav li.current a.level1,
#top-nav li.over a.level1 {
    background-color: #008ebe;
    color: #fff;
}

#top-nav li ul {
    display: none;
    position: absolute;
    top: 23px;
    left: 0;
    width: 198px;
    background-color: #f9fbfc;
    border: 1px solid #b9c4c6;
    border-bottom: 2px solid #979797;
    padding-bottom: 3px;
}

#top-nav li li {
    float: none;
    height: auto;
    font-size: 1.09em;
    border-bottom: 1px solid #d4e0e3;
    margin: 0 10px;
}

#top-nav li li a {
    font-weight: normal;
    padding: 10px 0 8px;
    color: #008dbb;
}

#top-nav li li a:hover {
    font-weight: normal;
    background: none;
    color: #555;
}

#top-nav li li.last {
    border-bottom: 0;
}

#top-nav li.over ul {
    display: block;
}

#top-search {
    float: right;
    width: 339px;
    background: url(http://framework.zend.com/images/bkg_search.gif) left top repeat-x;
    height: 51px;
}

#top-search fieldset {
    padding: 8px 16px 0;
}

#top-search .field {
    float: left;
    border: 0;
    background: #fff url(http://framework.zend.com/images/bkg_search-field.gif) left top no-repeat;
    width: 253px;
    height: 30px;
    padding: 0 6px;
    margin-top: 2px;
    font-size: 1.2em;
}

#top-search .field input {
    margin: 8px 0;
}

#top-search .btn_go {
    float: left;
    margin-left: 9px;
    width: 33px;
    height: 33px;
    border: none;
}

#top .behind-the-site {
    position: absolute;
    right: 0pt;
    top: 0pt;
}

/* < header styles */
#header {
    background: url(http://framework.zend.com/images/bkg_header.jpg) left top repeat-x;
}

#header .banner {
    margin: 0 auto;
    width: 994px;
    height: 255px;
    background: url(http://framework.zend.com/images/bkg_header.jpg) left top no-repeat;
    position: relative;
}

#header .banner_zf_logo {
    margin: 0 auto;
    width: 429px;
    height: 255px;
    background: url(http://framework.zend.com/images/banner_zf_logo_v1_11.png) left top no-repeat;
    position: absolute;
    top: 0px;
    left: 0px;
}

#header .banner_announcement {
    margin: 0 auto;
    width: 557px;
    height: 170px;
    background: url(http://framework.zend.com/images/banner_announcement.jpg) left top no-repeat;
    position: absolute;
    top: 0px;
    left: 429px;
}

#header .banner_download {
    margin: 0 auto;
    width: 557px;
    height: 85px;
    background: url(http://framework.zend.com/images/banner_download.jpg) left top no-repeat;
    position: absolute;
    top: 170px;
    left: 429px;
}

/* #header .banner_announcement
#header .banner_download */
/* #header .announcement { width:478px; height:112px; position:absolute; top:29px; left:410px; background:url(http://framework.zend.com/images/dojo_announcement.jpg) left top no-repeat; text-indent:-50000px; overflow:hidden; } */
/* #header .download { width:576px; height:59px; position:absolute; right:4px; bottom:58px; } */
/* #header .download .btn_download { width:576px; height:59px; background:url(http://framework.zend.com/images/btn_download.jpg) left top no-repeat; }
#header .download .btn_download .link-download { display:block; text-indent:-5000px; width:576px; height:59px; overflow:hidden; }
#header .download .types { position:absolute; top:11px; left:308px; font-size:1.2em; font-weight:bold; line-height:1.17; color:#000; }
#header .download .types a { text-decoration:underline; color:#fff; }
#header .download .types a:hover { text-decoration:none; }
#header .download .version-seal { position:absolute; right:12px; top:-54px; width:136px; height:139px; background:url(http://framework.zend.com/images/version-seal.jpg) left top no-repeat; text-indent:-5000px; overflow:hidden; }*/
/* header styles > */

#main-holder {
    background: url(http://framework.zend.com/images/bkg_body.gif) left bottom repeat;
}

#main-holder .main-holder-bottom {
    background: url(http://framework.zend.com/images/bkg_body-bottom.gif) left bottom repeat-x;
    padding-bottom: 45px;
}

/* < Index page */
.box {
    margin: 0 auto;
    width: 968px;
    background: url(http://framework.zend.com/images/bkg_box-shadow.png) left top repeat-y;
    text-align: left;
}

.box .box-in {
    background: url(http://framework.zend.com/images/bkg_box.gif) left bottom no-repeat;
    padding: 0 6px 0 5px;
    min-height: 443px;
}

.box-bottom {
    margin: 0 auto;
    width: 968px;
    height: 19px;
    background: url(http://framework.zend.com/images/bkg_box-bottom.png) left top no-repeat;
}

.box .col {
    float: left;
    width: 319px;
}

.box .col-blue,
.box .col-green,
.box .col-yellow {
    padding: 9px 23px 0;
}

.box h2 {
    font-size: 2.6em;
    margin-bottom: 3px;
}

.box h3 {
    font-size: 1.4em;
    font-weight: bold;
    color: #0398ca;
}

.box h3 a {
    color: #0398ca;
}

.box p.tagline {
    font-size: 1.5em;
    line-height: 1.2;
}

.box .rss-box {
    padding: 6px 11px;
    font-size: 1.1em;
    line-height: 1.55;
    min-height: 7.5em;
    margin: 10px 0 17px;
}

.box .rss-box .rss-icon {
    float: right;
    width: 12px;
    height: 12px;
    margin-right: -5px;
    overflow: hidden;
}

.box .rss-box li {
    background: left .9em no-repeat;
    padding: 3px 0 4px 14px;
}

.box .rss-box li.last {
    border-bottom: 0 !important;
}

.box .col-blue h2 {
    color: #166e8b;
}

.box .col-blue p.tagline {
    color: #318ba8;
}

.box .col-blue .rss-box {
    border: 2px solid #cfdae4;
    background-color: #f4f9fc;
    color: #00769e;
}

.box .col-blue .rss-box .rss-icon {
    background: url(http://framework.zend.com/images/icon_rss-blue.gif) left top no-repeat;
}

.box .col-blue .rss-box li {
    background-image: url(http://framework.zend.com/images/icon_arrow-blue.gif);
    border-bottom: 1px solid #d9e3e9;
}

.box .col-blue .rss-box a {
    color: #00769e;
}

.box .col-green h2 {
    color: #619400;
}

.box .col-green p.tagline {
    color: #5c7b23;
}

.box .col-green .rss-box {
    border: 2px solid #d3e4cf;
    background-color: #f4fff2;
    color: #537e01;
}

.box .col-green .rss-box .rss-icon {
    background: url(http://framework.zend.com/images/icon_rss-green.gif) left top no-repeat;
}

.box .col-green .rss-box li {
    background-image: url(http://framework.zend.com/images/icon_arrow-green.gif);
    border-bottom: 1px solid #d7e9d4;
}

.box .col-green .rss-box a {
    color: #537e01;
}

.box .col-yellow h2 {
    color: #f29300;
}

.box .col-yellow p.tagline {
    color: #a65200;
}

.box .col-yellow .rss-box {
    border: 2px solid #e7dac5;
    background-color: #fdf9f1;
    color: #c26400;
}

.box .col-yellow .rss-box .rss-icon {
    background: url(http://framework.zend.com/images/icon_rss-yellow.gif) left top no-repeat;
}

.box .col-yellow .rss-box li {
    background-image: url(http://framework.zend.com/images/icon_arrow-yellow.gif);
    border-bottom: 1px solid #e0d5c2;
}

.box .col-yellow .rss-box a {
    color: #c26400;
}

.box .items li {
    padding: 0 0 13px 70px;
    margin-bottom: 14px;
    background: left top no-repeat;
    border-bottom: 1px solid #d5d5d5;
    min-height: 53px;
}

.box .items li.last {
    border-bottom: 0;
}

.box .items li p {
    font-size: 1.2em;
    line-height: 1.5;
    padding-top: 3px;
}

.box .items li.item1 {
    background-image: url(http://framework.zend.com/images/icon_whyzf.png);
}

.box .items li.item2 {
    background-image: url(http://framework.zend.com/images/icon_case-studies.gif);
}

.box .items li.item3 {
    background-image: url(http://framework.zend.com/images/icon_support.png);
}

.box .items li.item4 {
    background-image: url(http://framework.zend.com/images/icon_partners.png);
}

.box .items li.item5 {
    background-image: url(http://framework.zend.com/images/icon_quickstart.png);
}

.box .items li.item6 {
    background-image: url(http://framework.zend.com/images/icon_videos.png);
}

.box .items li.item7 {
    background-image: url(http://framework.zend.com/images/icon_documentation.png);
}

.box .items li.item8 {
    background-image: url(http://framework.zend.com/images/icon_training.png);
}

.box .items li.item9 {
    background-image: url(http://framework.zend.com/images/icon_contributors-guide.png);
}

.box .items li.item10 {
    background-image: url(http://framework.zend.com/images/icon_issue.gif);
}

.box .items li.item11 {
    background-image: url(http://framework.zend.com/images/icon_wiki.png);
}

.box .items li.item12 {
    background-image: url(http://framework.zend.com/images/icon_continuous_integration.png);
}

.box .items li.item13 {
    background-image: url(http://framework.zend.com/images/win-ipod-touch-survey-icon.png);
}

/* Index page > */

/* < Internal pages styles */
.internal-page #main-holder {
    background: #fff;
}

.internal-page #top-search {
    width: 280px;
}

.internal-page #top-search .field {
    width: 194px;
}

.content {
    padding: 10px;
    line-height: 1.5;
    text-align: left;
}

.content .content-in {
    padding: 35px 0 120px;
}

.content .heading {
    padding-bottom: 10px;
}

.content h2.heading-internal {
    clear: both;
    font-size: 2.5em;
    color: #008dbb;
}

.content h2 {
    font-size: 1.5em;
    font-weight: bold;
    padding-bottom: 4px;
}

.content h3 {
    font-size: 1.25em;
    font-weight: bold;
    padding-bottom: 4px;
}

.content h4 {
    font-size: 1.083em;
    font-weight: bold;
    padding-bottom: 4px;
}

.content h5 {
    font-size: 1em;
    font-weight: bold;
    padding-bottom: 4px;
}

.content p {
    padding-bottom: 1em;
}

.content p.first {
    font-size: 1.17em;
    font-family: Georgia, "Times New Roman", Times, serif;
}

.content .ol {
    list-style: decimal outside;
    padding: 0 0 1em 25px;
}

.content .ul {
    list-style: disc outside;
    padding: 0 0 1em 20px;
}

.content .ul span {
    font-weight: bold;
}

.content .highlight1 {
    font-weight: bold;
    font-style: italic;
}

.content .dotted-line {
    font-size: 1px;
    line-height: 0;
    height: 7px;
    background: url(http://framework.zend.com/images/bkg_dotted-line.gif) left top repeat-x;
}

.content .left-side {
    float: left;
    width: 646px;
}

.content .sub-nav ul {
    float: left;
    width: 100%;
    background-color: #f4f4f4;
    margin-bottom: 25px;
}

.content .sub-nav li {
    float: left;
    font-weight: bold;
    padding: 4px 0 4px 10px;
    position: relative;
    z-index: 19;
}

.content .sub-nav li .arrow {
    display: none;
    width: 10px;
    height: 8px;
    background: url(http://framework.zend.com/images/bkg_sub-nav.gif) left top no-repeat;
    position: absolute;
    bottom: -8px;
    left: 50%;
    margin-left: -7px;
    font-size: 0;
    line-height: 0;
}

.content .sub-nav li .divider {
    color: #b7b7b7;
    margin: 0 0 0 0px;
}

.content .sub-nav a {
    margin-right: 10px;
    color: #008dbb;
}

.content .sub-nav .current .arrow {
    display: block;
}

.content .sub-nav .current a {
    text-decoration: none;
    color: #749b2a;
    cursor: default;
}

.content table.dl-packages {
    border-collapse: separate;
    border-spacing: 20px;
}

.content td.dl-package-title {
    width: 100px;
    height: 60px;
    align: center;
    text-align: center;
    vertical-align: middle;
    font-size: 1.17em;
    font-family: Georgia, "Times New Roman", Times, serif;
}

.content td.dl-package-def {
    vertical-align: middle;
}

.content .list-features {
    border: 1px solid #ebf1e0;
    background-color: #f4f8ed;
    padding: 12px 10px;
    margin-bottom: 1em;
    overflow: hidden;
}

.content .list-features li {
    float: left;
    font-size: 1.083em;
    font-weight: bold;
    line-height: 1.31;
    color: #3b5901;
}

.content .list-features li img {
    float: left;
    margin-right: 13px;
}

.content .list-features li.feature1 {
    width: 230px;
}

.content .list-features li.feature2 {
    width: 155px;
}

.content .list-features li.feature3 {
    width: 190px;
}

.content .right-nav {
    float: right;
    width: 280px;
}

.content .right-nav .block {
    border: 1px solid #dde8ed;
    margin-bottom: 17px;
}

.content .right-nav .block h2 {
    font-size: .92em;
    font-weight: bold;
    line-height: 1;
    background-color: #e3eaed;
    border-bottom: 1px solid #f6fbfd;
    padding: 5px 10px 6px;
    text-transform: uppercase;
    color: #222;
}

.content .right-nav .block .block-in {
    background: #f0f6f8;
    padding: 10px;
}

.content .right-nav .block .nav li {
    padding-bottom: 3px;
}

.content .right-nav .block a {
    color: #0088b5;
}

/* Internal pages styles > */

/* < Search styles */
div#site-search-form {
    padding: 5px 0px 5px 0px;
    background: url(http://framework.zend.com/images/req-legend.gif) top right;
    background-repeat: no-repeat;
}

div.search ul.ul li {
    background: url(http://framework.zend.com/images/icon_arrow-blue.gif) left .9em no-repeat;
    padding: 3px 0 1em 14px;
}

.searchForm li.element {
    width: 100%;
}

#searchForm input#manual-search {
    vertical-align: middle;
}

#searchForm div.clearer {
    font-size: 12px;
    line-height: 1em;
    height: 1em;
}

ul.pager {
    list-style-image: none;
    list-style-position: outside;
    list-style-type: none;
    margin: 15px 0px 0px 25px;
}

ul.pager li {
    float: left;
    margin-left: 3px;
    border: 1px solid #ced2d2;
}

ul.pager li a {
    text-decoration: none;
    padding: 2px 6px;
}

ul.pager li a:hover {
    color: #fff;
    border-color: #2B55AF;
    background: #37464f none repeat scroll 0%;
}

ul.pager li.current {
    font-size: 107%;
    font-weight: bold;
    border: 0pt none;
    color: #37464f;
    padding: 1px 6px;
}

/* Search styles > */

/* < Contact form styles */
textarea#contact-content {
    overflow: auto;
}

dl.zend_form {
    width: 80%;
    background: url(http://framework.zend.com/images/req-legend.gif) top right;
    background-repeat: no-repeat;
}

/* Contact form styles */

/* < Error page styles */
pre.error {
    overflow: auto;
}

/* Error page styles > */

/* < footer styles */
#footer {
    background: #f2f2f2 url(http://framework.zend.com/images/bkg_footer.gif) left top repeat-x;
    min-height: 73px;
}

#footer .footer {
    margin: 0 auto;
    width: 956px;
    padding: 15px 0 0;
    text-align: left;
}

#footer .footer-nav li {
    float: left;
    font-size: 1.2em;
    line-height: 1.5;
    color: #008dbb;
}

#footer .footer-nav li .divider {
    color: #868686;
    margin: 0 8px;
}

#footer .footer-nav li a {
    color: #008dbb;
}

#footer address {
    float: right;
    font-size: 1.1em;
    line-height: 1.64;
    text-align: right;
    color: #444;
}

#footer address .logo_zend {
    width: 100px;
    height: 38px;
    background: url(http://framework.zend.com/images/logo_zend.gif) left top no-repeat;
    text-align: center;
}

#footer address .logo_varien {
    width: 14px;
    height: 15px;
    background: url(http://framework.zend.com/images/logo_varien.gif) left top no-repeat;
}

#footer address a {
    color: #444;
}

#footer address a:hover {
    color: #008dbb;
    text-decoration: none;
}

#footer address a:hover .logo_varien {
    background-position: left -15px;
}

/* footer styles > */

#release-notes {
    margin-bottom: 1em;
}

/* Hide nodes */
.hidden {
    visibility: hidden;
    display: none;
}

.sub-page-main-header-latest-release-of-zf {
    background-image: url(http://framework.zend.com/images/header/sub-page-main-header-latest-release-of-zf.png);
    background-repeat: no-repeat;
    height: 28px;
    width: 351px;
    margin-bottom: 5px;
    padding-bottom: 0.5em;
    clear: both;
}

.sub-page-main-header-latest-release-of-zf h1, .sub-page-main-header-latest-release-of-zf h2, .sub-page-main-header-latest-release-of-zf h3, .sub-page-main-header-latest-release-of-zf h4 {
    display: none
}

.front-page-left-header-make-the-choice {
    background-image: url(http://framework.zend.com/images/header/front-page-left-header-make-the-choice.png);
    background-repeat: no-repeat;
    height: 23px;
    width: 247px;
    margin-bottom: 5px;
    padding-bottom: 0.5em;
    clear: both;
}

.front-page-left-header-make-the-choice h1, .front-page-left-header-make-the-choice h2, .front-page-left-header-make-the-choice h3, .front-page-left-header-make-the-choice h4 {
    display: none
}

.sub-page-main-header-search-the-manual {
    background-image: url(http://framework.zend.com/images/header/sub-page-main-header-search-the-manual.png);
    background-repeat: no-repeat;
    height: 28px;
    width: 334px;
    margin-bottom: 5px;
    padding-bottom: 0.5em;
    clear: both;
}

.sub-page-main-header-search-the-manual h1, .sub-page-main-header-search-the-manual h2, .sub-page-main-header-search-the-manual h3, .sub-page-main-header-search-the-manual h4 {
    display: none
}

.sub-page-main-header-application-error {
    background-image: url(http://framework.zend.com/images/header/sub-page-main-header-application-error.png);
    background-repeat: no-repeat;
    height: 37px;
    width: 304px;
    margin-bottom: 5px;
    padding-bottom: 0.5em;
    clear: both;
}

.sub-page-main-header-application-error h1, .sub-page-main-header-application-error h2, .sub-page-main-header-application-error h3, .sub-page-main-header-application-error h4 {
    display: none
}

.sub-page-main-header-api-documentation {
    background-image: url(http://framework.zend.com/images/header/sub-page-main-header-api-documentation.png);
    background-repeat: no-repeat;
    height: 28px;
    width: 345px;
    margin-bottom: 5px;
    padding-bottom: 0.5em;
    clear: both;
    margin-top: 80px;
}

.sub-page-main-header-api-documentation h1, .sub-page-main-header-api-documentation h2, .sub-page-main-header-api-documentation h3, .sub-page-main-header-api-documentation h4 {
    display: none
}

.sub-page-main-header-zend-framework-user-groups {
    background-image: url(http://framework.zend.com/images/header/sub-page-main-header-zend-framework-user-groups.png);
    background-repeat: no-repeat;
    height: 37px;
    width: 535px;
    margin-bottom: 5px;
    padding-bottom: 0.5em;
    clear: both;
}

.sub-page-main-header-zend-framework-user-groups h1, .sub-page-main-header-zend-framework-user-groups h2, .sub-page-main-header-zend-framework-user-groups h3, .sub-page-main-header-zend-framework-user-groups h4 {
    display: none
}

.front-page-middle-sub-header-what-you-need-to-get-up-to-speed {
    background-image: url(http://framework.zend.com/images/header/front-page-middle-sub-header-what-you-need-to-get-up-to-speed.png);
    background-repeat: no-repeat;
    height: 17px;
    width: 269px;
    margin-bottom: 5px;
    padding-bottom: 0.5em;
    clear: both;
}

.front-page-middle-sub-header-what-you-need-to-get-up-to-speed h1, .front-page-middle-sub-header-what-you-need-to-get-up-to-speed h2, .front-page-middle-sub-header-what-you-need-to-get-up-to-speed h3, .front-page-middle-sub-header-what-you-need-to-get-up-to-speed h4 {
    display: none
}

.sub-page-main-header-programmers-reference-guide {
    background-image: url(http://framework.zend.com/images/header/sub-page-main-header-programmers-reference-guide.png);
    background-repeat: no-repeat;
    height: 37px;
    width: 552px;
    margin-bottom: 5px;
    padding-bottom: 0.5em;
    clear: both;
}

.sub-page-main-header-programmers-reference-guide h1, .sub-page-main-header-programmers-reference-guide h2, .sub-page-main-header-programmers-reference-guide h3, .sub-page-main-header-programmers-reference-guide h4 {
    display: none
}

.sub-page-main-header-zend-amf-downloads {
    background-image: url(http://framework.zend.com/images/header/sub-page-main-header-zend-amf-downloads.png);
    background-repeat: no-repeat;
    height: 28px;
    width: 391px;
    margin-bottom: 5px;
    padding-bottom: 0.5em;
    clear: both;
}

.sub-page-main-header-zend-amf-downloads h1, .sub-page-main-header-zend-amf-downloads h2, .sub-page-main-header-zend-amf-downloads h3, .sub-page-main-header-zend-amf-downloads h4 {
    display: none
}

.front-page-left-sub-header-standardize-your-php-practices {
    background-image: url(http://framework.zend.com/images/header/front-page-left-sub-header-standardize-your-php-practices.png);
    background-repeat: no-repeat;
    height: 17px;
    width: 241px;
    margin-bottom: 5px;
    padding-bottom: 0.5em;
    clear: both;
}

.front-page-left-sub-header-standardize-your-php-practices h1, .front-page-left-sub-header-standardize-your-php-practices h2, .front-page-left-sub-header-standardize-your-php-practices h3, .front-page-left-sub-header-standardize-your-php-practices h4 {
    display: none
}

.front-page-middle-header-get-started {
    background-image: url(http://framework.zend.com/images/header/front-page-middle-header-get-started.png);
    background-repeat: no-repeat;
    height: 23px;
    width: 166px;
    margin-bottom: 5px;
    padding-bottom: 0.5em;
    clear: both;
}

.front-page-middle-header-get-started h1, .front-page-middle-header-get-started h2, .front-page-middle-header-get-started h3, .front-page-middle-header-get-started h4 {
    display: none
}

.front-page-right-header-give-back {
    background-image: url(http://framework.zend.com/images/header/front-page-right-header-give-back.png);
    background-repeat: no-repeat;
    height: 23px;
    width: 139px;
    margin-bottom: 5px;
    padding-bottom: 0.5em;
    clear: both;
}

.front-page-right-header-give-back h1, .front-page-right-header-give-back h2, .front-page-right-header-give-back h3, .front-page-right-header-give-back h4 {
    display: none
}

.sub-page-main-header-page-not-found {
    background-image: url(http://framework.zend.com/images/header/sub-page-main-header-page-not-found.png);
    background-repeat: no-repeat;
    height: 37px;
    width: 265px;
    margin-bottom: 5px;
    padding-bottom: 0.5em;
    clear: both;
}

.sub-page-main-header-page-not-found h1, .sub-page-main-header-page-not-found h2, .sub-page-main-header-page-not-found h3, .sub-page-main-header-page-not-found h4 {
    display: none
}

.sub-page-main-header-zend-info-card-downloads {
    background-image: url(http://framework.zend.com/images/header/sub-page-main-header-zend-info-card-downloads.png);
    background-repeat: no-repeat;
    height: 28px;
    width: 464px;
    margin-bottom: 5px;
    padding-bottom: 0.5em;
    clear: both;
}

.sub-page-main-header-zend-info-card-downloads h1, .sub-page-main-header-zend-info-card-downloads h2, .sub-page-main-header-zend-info-card-downloads h3, .sub-page-main-header-zend-info-card-downloads h4 {
    display: none
}

.sub-page-main-header-simple-cloud-api-downloads {
    background-image: url(http://framework.zend.com/images/header/sub-page-main-header-simple-cloud-api-downloads.png);
    background-repeat: no-repeat;
    height: 37px;
    width: 511px;
    margin-bottom: 5px;
    padding-bottom: 0.5em;
    clear: both;
}

.sub-page-main-header-simple-cloud-api-downloads h1, .sub-page-main-header-simple-cloud-api-downloads h2, .sub-page-main-header-simple-cloud-api-downloads h3, .sub-page-main-header-simple-cloud-api-downloads h4 {
    display: none
}

.sub-page-main-header-zend-gdata-downloads {
    background-image: url(http://framework.zend.com/images/header/sub-page-main-header-zend-gdata-downloads.png);
    background-repeat: no-repeat;
    height: 28px;
    width: 411px;
    margin-bottom: 5px;
    padding-bottom: 0.5em;
    clear: both;
}

.sub-page-main-header-zend-gdata-downloads h1, .sub-page-main-header-zend-gdata-downloads h2, .sub-page-main-header-zend-gdata-downloads h3, .sub-page-main-header-zend-gdata-downloads h4 {
    display: none
}

.front-page-right-sub-header-because-it-just-feels-good {
    background-image: url(http://framework.zend.com/images/header/front-page-right-sub-header-because-it-just-feels-good.png);
    background-repeat: no-repeat;
    height: 17px;
    width: 200px;
    margin-bottom: 5px;
    padding-bottom: 0.5em;
    clear: both;
}

.front-page-right-sub-header-because-it-just-feels-good h1, .front-page-right-sub-header-because-it-just-feels-good h2, .front-page-right-sub-header-because-it-just-feels-good h3, .front-page-right-sub-header-because-it-just-feels-good h4 {
    display: none
}

div.section {
    margin: 0px;
    margin-bottom: 10px;
    padding: 0px;
    width: auto;
}

div.section h1 {
    border-bottom: 1px solid #F6FBFD;
    color: #222;
    font-size: 0.92em;
    font-weight: bold;
    line-height: 1;
    padding: 5px 10px 6px;
    text-transform: uppercase;
    margin: 0 0px;
    margin-bottom: 10px;
}

td#sidebar
{
    padding-top: 0px;
}

#sidebar ul li span
{
    display: inline-block;
    height: 16px;
}Zend Framework Template for phpDocumentor2
==========================================<?xml version="1.0" encoding="utf-8"?>
<template>
    <author>Mike van Riel</author>
    <email>mike.vanriel@naenius.com</email>
    <version>1.1.0</version>
    <copyright>Mike van Riel / Naenius 2011</copyright>
    <description>This is the look and feel for Zend Framework</description>
    <dependencies>
      <template name="abstract" version="1.0.3" />
    </dependencies>
    <transformations>
        <transformation query="copy" writer="FileIo" source="templates/abstract/images" artifact="images" />
        <transformation query="copy" writer="FileIo" source="templates/abstract/css" artifact="css" />
        <transformation query="copy" writer="FileIo" source="templates/abstract/js" artifact="js" />
        <transformation query="copy" writer="FileIo" source="templates/zend/images" artifact="images" />
        <transformation query="copy" writer="FileIo" source="templates/zend/css" artifact="css" />
        <transformation query="copy" writer="FileIo" source="templates/zend/js" artifact="js" />
        <transformation writer="xml" artifact="structure.xml" />
        <transformation writer="xsl" source="templates/zend/index.xsl" artifact="index.html" />
        <transformation writer="xsl" source="templates/abstract/sidebar.xsl" artifact="nav.html">
            <parameters>
                <variables>
                    <section.dashboard.show>false</section.dashboard.show>
                    <section.api.show />
                    <section.namespaces.show />
                    <section.packages.show />
                    <section.files.show />
                    <section.files.show-elements>false</section.files.show-elements>
                    <section.reports.show>false</section.reports.show>
                    <section.charts.show>false</section.charts.show>
                </variables>
            </parameters>
        </transformation>
        <transformation writer="xsl" source="templates/abstract/report_markers.xsl" artifact="report_markers.html" />
        <transformation writer="xsl" source="templates/abstract/report_parse_markers.xsl" artifact="report_parse_markers.html" />
        <transformation writer="xsl" source="templates/abstract/report_deprecated.xsl" artifact="report_deprecated.html" />
        <transformation writer="xsl" source="templates/abstract/content.xsl" artifact="content.html" />
        <transformation query="/project/file/@path" writer="xsl" source="templates/abstract/api-doc.xsl" artifact="files/{$path}" />
        <transformation writer="sourcecode" />
        <transformation writer="xsl" source="templates/abstract/graph_class.xsl" artifact="graph.html" />
        <transformation writer="Graph" source="Class" artifact="classes.svg" />
    </transformations>
</template>
{
    "_readme": [
        "This file locks the dependencies of your project to a known state",
        "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
    ],
    "hash": "34afa50ce1382956842ceaa8705898e1",
    "packages": [
        {
            "name": "phpdocumentor/template-abstract",
            "version": "1.2",
            "source": {
                "type": "git",
                "url": "https://github.com/phpDocumentor/template.abstract.git",
                "reference": "1.2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phpDocumentor/template.abstract/zipball/1.2",
                "reference": "1.2",
                "shasum": ""
            },
            "require": {
                "ext-xsl": "*",
                "phpdocumentor/unified-asset-installer": "~1.1"
            },
            "type": "phpdocumentor-template",
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "description": "Simple bright template for phpDocumentor",
            "homepage": "http://www.phpdoc.org",
            "keywords": [
                "documentation",
                "phpdoc",
                "template"
            ],
            "time": "2013-08-01 19:38:43"
        },
        {
            "name": "phpdocumentor/unified-asset-installer",
            "version": "1.1",
            "source": {
                "type": "git",
                "url": "https://github.com/phpDocumentor/UnifiedAssetInstaller.git",
                "reference": "1.1"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phpDocumentor/UnifiedAssetInstaller/zipball/1.1",
                "reference": "1.1",
                "shasum": ""
            },
            "require-dev": {
                "composer/composer": "~1.0@dev",
                "phpunit/phpunit": "~3.7"
            },
            "type": "composer-installer",
            "extra": {
                "class": "\\phpDocumentor\\Composer\\UnifiedAssetInstaller"
            },
            "autoload": {
                "psr-0": {
                    "phpDocumentor\\Composer": [
                        "src/",
                        "test/unit/"
                    ]
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "description": "Asset installer for phpDocumentor",
            "homepage": "http://www.phpdoc.org",
            "keywords": [
                "assets",
                "installer",
                "plugins",
                "templates"
            ],
            "time": "2013-08-01 19:35:55"
        }
    ],
    "packages-dev": [

    ],
    "aliases": [

    ],
    "minimum-stability": "stable",
    "stability-flags": [

    ],
    "platform": {
        "ext-xsl": "*"
    },
    "platform-dev": [

    ]
}
GIF87a3 3  ٶ㥦ԧܻ̘ժݯׯ׭ѥܔ^ktȷ𸸸꿿Ӧҥ᾿ӿըҦ񼼼ǖ§˲Ⱦ׵ϣӫ͹Ĵ񼾾帹峴£Уݶѧ,    3 3   KmP*\ȰC@J 3j>~<!
O.
?~tMUԨ3!K/gUIҟʞ;QdDPU$ɣFOܪ&RAzlHKfUvkZ
,7ٮYݶMϹuEARkJ~_ek7i80f*-	d3~~+JN?~	z(ͅ}G#2Aߔ) 6ܺy31gŻά3QOm?TN5qu`ϗiԳ.x]l	MF@=PyR#nDQxpa\xܓO9Zᶠx@#ay18c%enx(
"sAZD W.pNXpTHUXD*JD)>"Z,UW9D*Pq?BI`~xX>O=H#1+]4u9QZ$vwH>CC*ng'? "B=MHwh~9l>c1C=JʨZQJ>-0ܪN%PHGת:gLw1+0¨f{/bgLJqc@'+">+zXnGK@4PuJrܧ5p4p 
Bܪ,?.35k4
!tBA=( 6pfAK@;0Ax9P+pN:j7F-q'Ҁ
"鶼mThsCW\a7	#@͝8U)?]7Fu/c8I4o0E#)5qE #xb&{|4a4đ;$p =R9;37D8Xjغ'e;/L
8ͯ	C\1=ÈG>AH#lA%jb¬4E"qv `Cbql |xQHG`vQm8@/a
tPcaZB$(a
SŠ Xa$C8iXBUp Q	 ;<?xml version="1.0"?>
<!DOCTYPE xsl:stylesheet [<!ENTITY nbsp "&#160;">]>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template name="page_header">
    <div class="content">
      <div class="sub-page-main-header-api-documentation">
        <h2>API Documentation</h2>
      </div>

      <div class="dotted-line" />
    </div>
  </xsl:template>

</xsl:stylesheet>{
    "name": "phpdocumentor/template-checkstyle",
    "type": "phpdocumentor-template",
    "description": "Checkstyle XML output template for phpDocumentor2",
    "keywords": ["documentation", "template", "phpdoc"],
    "homepage": "http://www.phpdoc.org",
    "license": "MIT",
    "require": {
        "ext-xsl": "*",
        "phpdocumentor/unified-asset-installer": "~1.1"
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.9.4" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
    http://pear.php.net/dtd/tasks-1.0.xsd
    http://pear.php.net/dtd/package-2.0
    http://pear.php.net/dtd/package-2.0.xsd">
 <name>phpDocumentor_Template_checkstyle</name>
 <channel>pear.phpdoc.org</channel>
 <summary>The checkstyle template for phpDocumentor</summary>
 <description>This template allows users to produce checkstyle output</description>
 <lead>
  <name>Ben Selby</name>
  <user />
  <email />
  <active>yes</active>
 </lead>
 <date>2012-04-01</date>
 <time>10:32:36</time>
 <version>
  <release>1.0.0</release>
  <api>1.0.0</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license uri="http://www.opensource.org/licenses/mit-license.html">MIT</license>
 <notes>
Automatically generated by the phpDocumentor packager
 </notes>
 <contents>
  <dir baseinstalldir="/phpDocumentor/data/templates/checkstyle" name="/">
   <file name="README" role="php" />
   <file name="template.xml" role="php" />
  </dir> <!-- / -->
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.2.6</min>
   </php>
   <pearinstaller>
    <min>1.4.0</min>
   </pearinstaller>
   <package>
    <name>PEAR</name>
    <channel>pear.php.net</channel>
    <min>1.4.0</min>
   </package>
   <package>
    <name>phpDocumentor</name>
    <channel>pear.phpdoc.org</channel>
    <min>0.17.0</min>
   </package>
  </required>
 </dependencies>
 <phprelease />
 <changelog>
  <release>
   <version>
    <release>1.0.0</release>
    <api>1.0.0</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2012-04-01</date>
   <license uri="http://www.opensource.org/licenses/mit-license.html">MIT</license>
   <notes>
Automatically generated by the phpDocumentor packager
   </notes>
  </release>
 </changelog>
</package>
<?xml version="1.0" encoding="utf-8"?>
<template>
  <author>Ben Selby</author>
  <version>1.0.0</version>
  <description>This template allows users to produce checkstyle output</description>
  <transformations>
    <transformation query="" writer="checkstyle" source="" artifact="checkstyle.xml" />
  </transformations>
</template>
{
    "_readme": [
        "This file locks the dependencies of your project to a known state",
        "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
    ],
    "hash": "8fb3b5cfd9bb2a97534d51b90f5e82e7",
    "packages": [
        {
            "name": "phpdocumentor/unified-asset-installer",
            "version": "1.1",
            "source": {
                "type": "git",
                "url": "https://github.com/phpDocumentor/UnifiedAssetInstaller.git",
                "reference": "1.1"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phpDocumentor/UnifiedAssetInstaller/zipball/1.1",
                "reference": "1.1",
                "shasum": ""
            },
            "require-dev": {
                "composer/composer": "~1.0@dev",
                "phpunit/phpunit": "~3.7"
            },
            "type": "composer-installer",
            "extra": {
                "class": "\\phpDocumentor\\Composer\\UnifiedAssetInstaller"
            },
            "autoload": {
                "psr-0": {
                    "phpDocumentor\\Composer": [
                        "src/",
                        "test/unit/"
                    ]
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "description": "Asset installer for phpDocumentor",
            "homepage": "http://www.phpdoc.org",
            "keywords": [
                "assets",
                "installer",
                "plugins",
                "templates"
            ],
            "time": "2013-08-01 19:35:55"
        }
    ],
    "packages-dev": [

    ],
    "aliases": [

    ],
    "minimum-stability": "stable",
    "stability-flags": [

    ],
    "platform": {
        "ext-xsl": "*"
    },
    "platform-dev": [

    ]
}
{
    "name": "phpdocumentor/template-responsive",
    "type": "phpdocumentor-template",
    "description": "Responsive modern template for phpDocumentor",
    "keywords": ["documentation", "template", "phpdoc"],
    "homepage": "http://www.phpdoc.org",
    "license": "MIT",
    "require": {
        "ext-xsl": "*",
        "phpdocumentor/unified-asset-installer": "~1.1"
    }
}
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:date="http://exslt.org/dates-and-times"
    extension-element-prefixes="date">
    <xsl:output indent="yes" method="html" />

    <xsl:template name="string-replace-all">
        <xsl:param name="text" />
        <xsl:param name="replace" />
        <xsl:param name="by" />
        <xsl:choose>
            <xsl:when test="contains($text, $replace)">
                <xsl:value-of select="substring-before($text,$replace)" />
                <xsl:value-of select="$by" />
                <xsl:call-template name="string-replace-all">
                    <xsl:with-param name="text"
                        select="substring-after($text,$replace)" />
                    <xsl:with-param name="replace" select="$replace" />
                    <xsl:with-param name="by" select="$by" />
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$text" />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template name="createLink">
        <xsl:param name="value"/>

        <xsl:variable name="stage1">
            <xsl:call-template name="string-replace-all">
                <xsl:with-param name="text" select="$value"/>
                <xsl:with-param name="replace" select="'\'"/>
                <xsl:with-param name="by" select="'.'"/>
            </xsl:call-template>
        </xsl:variable>

        <xsl:call-template name="string-replace-all">
            <xsl:with-param name="text" select="$stage1" />
            <xsl:with-param name="replace" select="'/'" />
            <xsl:with-param name="by" select="'.'" />
        </xsl:call-template>
    </xsl:template>

    <xsl:template match="/project/namespace" mode="menu">
        <xsl:variable name="link">
            <xsl:call-template name="createLink">
                <xsl:with-param name="value" select="@full_name"/>
            </xsl:call-template>
        </xsl:variable>

        <li>
            <a href="{$root}namespaces/{$link}.html">
                <i class="icon-th"></i>&#160;<xsl:value-of select="@full_name" />
            </a>
        </li>
    </xsl:template>

    <xsl:template match="/project/package" mode="menu">
        <xsl:variable name="name" select="@name"/>

        <xsl:variable name="link">
            <xsl:call-template name="createLink">
                <xsl:with-param name="value" select="@full_name"/>
            </xsl:call-template>
        </xsl:variable>

        <!-- only show those packages that actually have visible contents -->
        <xsl:if test="/project/package[@name=$name]/package|/project/file/constant[@package=$name]|/project/file/function[@package=$name]|/project/file/class[@package=$name]|/project/file/interface[@package=$name]">
            <li>
                <a href="{$root}packages/{$link}.html">
                    <i class="icon-folder-open"></i>&#160;<xsl:value-of select="@full_name" />
                </a>
            </li>
        </xsl:if>
    </xsl:template>

    <xsl:template match="/" mode="header">
        <div class="navbar navbar-fixed-top">
            <div class="navbar-inner">
                <div class="container">
                    <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
                        <span class="icon-bar"></span> <span class="icon-bar"></span>
                        <span class="icon-bar"></span> </a>
                    <a class="brand" href="{$root}index.html">
                        <xsl:value-of select="$title" disable-output-escaping="yes"/>
                        <xsl:if test="$title = ''">phpDocumentor</xsl:if>
                    </a>

                    <div class="nav-collapse">
                        <ul class="nav">
                            <li class="dropdown">
                                <a href="#api" class="dropdown-toggle" data-toggle="dropdown">
                                    API Documentation <b class="caret"></b>
                                </a>
                                <ul class="dropdown-menu">
                                    <xsl:if test="/project/namespace/namespace">
                                        <li><a>Namespaces</a></li>
                                        <xsl:apply-templates select="/project/namespace" mode="menu">
                                            <xsl:sort select="@full_name" />
                                        </xsl:apply-templates>
                                    </xsl:if>
                                    <xsl:if test="/project/package/package or count(/project/package[@name != '']) > 1">
                                        <li><a>Packages</a></li>
                                        <xsl:apply-templates select="/project/package" mode="menu">
                                            <xsl:sort select="@name" />
                                        </xsl:apply-templates>
                                    </xsl:if>
                                </ul>
                            </li>
                            <li class="dropdown" id="charts-menu">
                                <a href="#charts" class="dropdown-toggle" data-toggle="dropdown">
                                    Charts <b class="caret"></b>
                                </a>
                                <ul class="dropdown-menu">
                                    <li><a href="{$root}graph_class.html">
                                        <i class="icon-list-alt"></i>&#160;Class hierarchy diagram</a></li>
                                </ul>
                            </li>
                            <li class="dropdown" id="reports-menu">
                                <a href="#reports" class="dropdown-toggle" data-toggle="dropdown">
                                    Reports <b class="caret"></b>
                                </a>
                                <ul class="dropdown-menu">
                                    <xsl:apply-templates select="/" mode="report-overview" />
                                </ul>
                            </li>
                        </ul>
                    </div>
                    <!--<form class="navbar-search pull-right" onsubmit="$('.element:parent').show(); $('.element h1:not(:contains('+$('#search-query').val()+'))').parent().hide();return false;">-->
                        <!--<input type="text" id="search-query" class="search-query" placeholder="Search" />-->
                    <!--</form>-->
                    <!--/.nav-collapse -->
                </div>
            </div>
            <div class="go_to_top">
                <a href="#___" style="color: inherit">Back to top&#160;&#160;<i class="icon-upload icon-white"></i></a>
            </div>
        </div>
    </xsl:template>

    <xsl:template match="/" mode="footer"></xsl:template>

    <xsl:template match="/" mode="content-footer">
        <footer class="span12">
            Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by <a href="http://glyphicons.com/">Glyphicons</a>.<br />
            Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor <xsl:value-of select="$version"/></a> and<br />
            generated on <xsl:value-of select="date:date-time()" />.<br />
        </footer>
    </xsl:template>

    <xsl:template match="/" mode="title"></xsl:template>

    <xsl:template match="/" mode="head">
        <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;" />
        <meta charset="utf-8" />
        <title>
            <xsl:value-of select="$title" disable-output-escaping="yes" />
            <xsl:if test="$title = ''">phpDocumentor</xsl:if>
            <xsl:apply-templates select="." mode="title"/>
        </title>
        <meta name="author" content="Mike van Riel" />
        <meta name="description" content="" />

        <!--[if lt IE 9]>
        <script src="http://html5shim.googlecode.com/svn/trunk/html5.js" type="text/javascript"></script>
        <![endif]-->

        <link href="{$root}css/template.css" rel="stylesheet" media="all" />
        <script src="{$root}js/jquery-1.7.1.min.js" type="text/javascript"></script>
        <script src="{$root}js/jquery-ui-1.8.2.custom.min.js" type="text/javascript"></script>
        <script src="{$root}js/jquery.mousewheel.min.js" type="text/javascript"></script>
        <script src="{$root}js/bootstrap.js" type="text/javascript"></script>
        <script src="{$root}js/template.js" type="text/javascript"></script>
        <script src="{$root}js/prettify/prettify.min.js" type="text/javascript"></script>

        <link rel="shortcut icon" href="{$root}img/favicon.ico" />
        <link rel="apple-touch-icon" href="{$root}img/apple-touch-icon.png" />
        <link rel="apple-touch-icon" sizes="72x72" href="{$root}img/apple-touch-icon-72x72.png" />
        <link rel="apple-touch-icon" sizes="114x114" href="{$root}img/apple-touch-icon-114x114.png" />
    </xsl:template>

    <xsl:template match="/">
        <xsl:text disable-output-escaping='yes'>&lt;!DOCTYPE html></xsl:text>
        <html lang="en">
            <head><xsl:apply-templates select="." mode="head"/></head>
            <body>
                <xsl:apply-templates select="." mode="header"/>
                <div id="___" class="container">
                    <noscript>
                        <div class="alert alert-warning">
                            Javascript is disabled; several features are only available
                            if Javascript is enabled.
                        </div>
                    </noscript>

                    <xsl:apply-templates select="/project" mode="contents" />
                    <div class="row">
                        <xsl:apply-templates select="." mode="content-footer" />
                    </div>
                </div>
                <xsl:apply-templates select="." mode="footer" />
            </body>
        </html>
    </xsl:template>

    <xsl:template match="/" mode="report-overview">
        <li>
            <a href="{$root}errors.html">
                <i class="icon-remove-sign"></i>&#160;Errors&#160;
                <span class="label label-info"><xsl:value-of select="count(/project/file/parse_markers/*)" /></span>
            </a>
        </li>
        <li>
            <a href="{$root}markers.html">
                <i class="icon-map-marker"></i>&#160;Markers&#160;
                <ul>
                    <xsl:apply-templates select="/project/marker" mode="report-overview" />
                </ul>
            </a>
        </li>
        <li>
            <a href="{$root}deprecated.html">
                <i class="icon-stop"></i>&#160;Deprecated elements&#160;
                <span class="label label-info"><xsl:value-of select="/project/deprecated/@count" /></span>
            </a>
        </li>
    </xsl:template>

    <xsl:template match="/project/marker" mode="report-overview">
        <xsl:variable name="marker" select="."/>
        <xsl:if test="./@count > 0">
            <li>
                <xsl:value-of select="$marker" />&#160;
                <span class="label label-info"><xsl:value-of select="./@count" /></span>
            </li>
        </xsl:if>
    </xsl:template>

</xsl:stylesheet><?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.9.4" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
    http://pear.php.net/dtd/tasks-1.0.xsd
    http://pear.php.net/dtd/package-2.0
    http://pear.php.net/dtd/package-2.0.xsd">
 <name>phpDocumentor_Template_responsive</name>
 <channel>pear.phpdoc.org</channel>
 <summary>The responsive template for phpDocumentor</summary>
 <description>
      This is the &apos;Responsive&apos; look and feel for phpDocumentor.

      This is a responsive template that is optimized to make the user&apos;s
      experience paramount.

      To improve performance you can add the following to your .htaccess:

      &lt;ifModule mod_deflate.c&gt;
          &lt;filesMatch &quot;\.(js|css|html)$&quot;&gt;
              SetOutputFilter DEFLATE
          &lt;/filesMatch&gt;
      &lt;/ifModule&gt;
  </description>
 <lead>
  <name>Mike van Riel</name>
  <user />
  <email>mike.vanriel@naenius.com</email>
  <active>yes</active>
 </lead>
 <date>2012-04-01</date>
 <time>10:34:36</time>
 <version>
  <release>1.0.1</release>
  <api>1.0.1</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license uri="http://www.opensource.org/licenses/mit-license.html">MIT</license>
 <notes>
Automatically generated by the phpDocumentor packager
 </notes>
 <contents>
  <dir baseinstalldir="/phpDocumentor/data/templates/responsive" name="/">
   <dir name="css">
    <file name="bootstrap-responsive.css" role="php" />
    <file name="bootstrap-responsive.min.css" role="php" />
    <file name="bootstrap.css" role="php" />
    <file name="bootstrap.min.css" role="php" />
    <file name="jquery.iviewer.css" role="php" />
    <file name="prettify.css" role="php" />
    <file name="template.css" role="php" />
   </dir> <!-- /css -->
   <dir name="elements">
    <file name="class.xsl" role="php" />
    <file name="common.xsl" role="php" />
    <file name="constant.xsl" role="php" />
    <file name="function.xsl" role="php" />
    <file name="namespace.xsl" role="php" />
    <file name="package.xsl" role="php" />
    <file name="property.xsl" role="php" />
   </dir> <!-- /elements -->
   <dir name="graphs">
    <file name="class.xsl" role="php" />
   </dir> <!-- /graphs -->
   <dir name="img">
    <dir name="icons">
     <file name="class.png" role="php" />
     <file name="constant.png" role="php" />
     <file name="function.png" role="php" />
     <file name="icon-folder-open-big.png" role="php" />
     <file name="icon-th-big.png" role="php" />
     <file name="icon_template.svg" role="php" />
     <file name="interface.png" role="php" />
     <file name="method.png" role="php" />
     <file name="property.png" role="php" />
    </dir> <!-- /img/icons -->
    <dir name="iviewer">
     <file name="grab.cur" role="php" />
     <file name="hand.cur" role="php" />
     <file name="iviewer.rotate_left.png" role="php" />
     <file name="iviewer.rotate_right.png" role="php" />
     <file name="iviewer.zoom_fit.png" role="php" />
     <file name="iviewer.zoom_fit2.gif" role="php" />
     <file name="iviewer.zoom_in.png" role="php" />
     <file name="iviewer.zoom_in2.gif" role="php" />
     <file name="iviewer.zoom_out.png" role="php" />
     <file name="iviewer.zoom_out2.gif" role="php" />
     <file name="iviewer.zoom_zero.png" role="php" />
     <file name="iviewer.zoom_zero2.gif" role="php" />
    </dir> <!-- /img/iviewer -->
    <file name="apple-touch-icon-72x72.png" role="php" />
    <file name="apple-touch-icon-114x114.png" role="php" />
    <file name="apple-touch-icon.png" role="php" />
    <file name="favicon.ico" role="php" />
    <file name="glyphicons-halflings-white.png" role="php" />
    <file name="glyphicons-halflings.png" role="php" />
    <file name="loader.gif" role="php" />
   </dir> <!-- /img -->
   <dir name="js">
    <dir name="prettify">
     <file name="lang-apollo.js" role="php" />
     <file name="lang-clj.js" role="php" />
     <file name="lang-css.js" role="php" />
     <file name="lang-go.js" role="php" />
     <file name="lang-hs.js" role="php" />
     <file name="lang-lisp.js" role="php" />
     <file name="lang-lua.js" role="php" />
     <file name="lang-ml.js" role="php" />
     <file name="lang-n.js" role="php" />
     <file name="lang-proto.js" role="php" />
     <file name="lang-scala.js" role="php" />
     <file name="lang-sql.js" role="php" />
     <file name="lang-tex.js" role="php" />
     <file name="lang-vb.js" role="php" />
     <file name="lang-vhdl.js" role="php" />
     <file name="lang-wiki.js" role="php" />
     <file name="lang-xq.js" role="php" />
     <file name="lang-yaml.js" role="php" />
     <file name="prettify.min.js" role="php" />
    </dir> <!-- /js/prettify -->
    <file name="bootstrap.js" role="php" />
    <file name="bootstrap.min.js" role="php" />
    <file name="jquery.iviewer.js" role="php" />
    <file name="jquery.iviewer.min.js" role="php" />
    <file name="jquery.mousewheel.min.js" role="php" />
    <file name="template.js" role="php" />
   </dir> <!-- /js -->
   <dir name="reports">
    <file name="deprecated.xsl" role="php" />
    <file name="errors.xsl" role="php" />
    <file name="markers.xsl" role="php" />
   </dir> <!-- /reports -->
   <file name="class.xsl" role="php" />
   <file name="graph.html" role="php" />
   <file name="index.xsl" role="php" />
   <file name="layout.xsl" role="php" />
   <file name="namespaces.xsl" role="php" />
   <file name="packages.xsl" role="php" />
   <file name="README.md" role="php" />
   <file name="search.json.xsl" role="php" />
   <file name="template.xml" role="php" />
  </dir> <!-- / -->
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.2.6</min>
   </php>
   <pearinstaller>
    <min>1.4.0</min>
   </pearinstaller>
   <package>
    <name>PEAR</name>
    <channel>pear.php.net</channel>
    <min>1.4.0</min>
   </package>
   <package>
    <name>phpDocumentor</name>
    <channel>pear.phpdoc.org</channel>
    <min>0.17.0</min>
   </package>
  </required>
 </dependencies>
 <phprelease />
 <changelog>
  <release>
   <version>
    <release>1.0.1</release>
    <api>1.0.1</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2012-04-01</date>
   <license uri="http://www.opensource.org/licenses/mit-license.html">MIT</license>
   <notes>
Automatically generated by the phpDocumentor packager
   </notes>
  </release>
 </changelog>
</package>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" method="html" />
    <xsl:include href="layout.xsl" />
    <xsl:include href="elements/common.xsl" />
    <xsl:include href="elements/package.xsl" />
    <xsl:include href="elements/class.xsl" />
    <xsl:include href="elements/function.xsl" />
    <xsl:include href="elements/constant.xsl" />

    <xsl:template match="/project" mode="contents">
        <xsl:variable name="element" select="//package[@full_name = $full_name]"/>

        <xsl:variable name="parent_name">
            <xsl:if test="local-name($element/..) = 'package'">
                <xsl:value-of select="concat($element/../@full_name, '\')"/>
            </xsl:if>
        </xsl:variable>

        <div class="row">
            <div class="span4">
                <xsl:apply-templates select="$element" mode="sidebar-nav">
                    <xsl:with-param name="parent_name" select="$parent_name"/>
                </xsl:apply-templates>
            </div>
            <div class="span8 package-contents">
                <xsl:apply-templates select="$element" mode="contents">
                    <xsl:with-param name="parent_name" select="$parent_name"/>
                </xsl:apply-templates>
            </div>

        </div>
    </xsl:template>

    <xsl:template match="/" mode="title">
        <xsl:text> &#187; </xsl:text>
        <xsl:value-of select="$full_name" />
    </xsl:template>

</xsl:stylesheet><?xml version="1.0"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" method="html" />
    <xsl:include href="../layout.xsl" />

    <xsl:template match="/project" mode="contents">

        <div class="row">
            <div class="span4">
                <ul class="side-nav nav nav-list">
                    <li class="nav-header">Navigation</li>
                    <xsl:for-each select="/project/file">
                        <xsl:if test="markers">
                        <li>
                            <a href="#{@path}">
                                <i class="icon-file"></i> <xsl:value-of select="@path"/>
                            </a>
                        </li>
                        </xsl:if>
                    </xsl:for-each>
                </ul>
            </div>

            <div class="span8">

                <ul class="breadcrumb">
                    <li><a href="{$root}"><i class="icon-map-marker"></i></a><span class="divider">\</span></li>
                    <li>Markers</li>
                </ul>

                <xsl:if test="count(/project/file/markers) &lt; 1">
                    <div class="alert alert-info">No markers have been found in this project.</div>
                </xsl:if>

                <xsl:if test="count(/project/marker) > 0">
                    <div class="alert alert-info">
                        The following markers were found:
                        <ul>
                            <xsl:apply-templates select="/project/marker" mode="report-overview" />
                        </ul>
                    </div>
                </xsl:if>

                <div id="marker-accordion">
                    <xsl:for-each select="/project/file">
                        <xsl:if test="markers">
                            <div class="package-contents">
                                <a name="{@path}" id="{@path}"></a>
                                <h3>
                                <i class="icon-file"></i>
                                    <xsl:value-of select="@path" />
                                    <small style="float: right;padding-right: 10px;">
                                        <xsl:value-of select="count(markers/*)" />
                                    </small>
                                </h3>
                                <div>
                                    <table class="table markers table-bordered">
                                        <tr>
                                            <th>Type</th>
                                            <th>Line</th>
                                            <th>Description</th>
                                        </tr>
                                        <xsl:for-each select="markers/*">
                                            <xsl:sort select="line" />
                                            <tr>
                                                <td>
                                                    <xsl:value-of select="name()" />
                                                </td>
                                                <td>
                                                    <xsl:value-of select="@line" />
                                                </td>
                                                <td>
                                                    <xsl:value-of select="." disable-output-escaping="yes" />
                                                </td>
                                            </tr>
                                        </xsl:for-each>
                                    </table>
                                </div>
                            </div>
                        </xsl:if>
                    </xsl:for-each>
                </div>
            </div>

        </div>
    </xsl:template>

</xsl:stylesheet>
<?xml version="1.0"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" method="html" />
    <xsl:include href="../layout.xsl" />

    <xsl:template match="/project" mode="contents">
        <div class="row">
            <div class="span4">

                <ul class="side-nav nav nav-list">
                    <li class="nav-header">Filter type</li>
                    <li>
                        <div class="btn-group type-filter" data-toggle="buttons-checkbox">
                            <button class="btn critical">Critical</button>
                            <button class="btn error">Error</button>
                            <button class="btn notice">Notice</button>
                        </div>
                    </li>
                    <li class="nav-header">Navigation</li>
                    <xsl:for-each select="/project/file[count(parse_markers) > 0]">
                        <li>
                            <a href="#{@path}">
                                <i class="icon-file"></i> <xsl:value-of select="@path"/>
                            </a>
                        </li>
                    </xsl:for-each>
                </ul>
            </div>

            <div class="span8">
                <ul class="breadcrumb">
                    <li><a href="{$root}"><i class="icon-remove-sign"></i></a><span class="divider">\</span></li>
                    <li>Compilation Errors</li>
                </ul>

                <xsl:if test="count(/project/file/parse_markers) &lt; 1">
                    <div class="alert alert-info">No errors have been found in this project.</div>
                </xsl:if>

                <xsl:for-each select="/project/file">
                    <div class="package-contents">
                        <xsl:if test="parse_markers">
                            <a name="{@path}" id="{@path}"></a>
                            <h3>
                                <i class="icon-file"></i>
                                <xsl:value-of select="@path" />
                                <small style="float: right;padding-right: 10px;">
                                    <xsl:value-of select="count(parse_markers/*)" />
                                </small>
                            </h3>
                            <div>
                                <table class="table markers table-bordered">
                                    <thead>
                                    <tr>
                                        <th>Type</th>
                                        <th>Line</th>
                                        <th>Description</th>
                                    </tr>
                                    </thead>
                                    <tbody>
                                    <xsl:for-each select="parse_markers/*">
                                        <xsl:sort select="@line" data-type="number"/>
                                        <tr>
                                            <xsl:if test="name() = 'tag'">
                                                <xsl:attribute name="class">
                                                    <xsl:value-of select="@name"/>
                                                </xsl:attribute>
                                                <td>
                                                    <xsl:value-of select="@name" />
                                                </td>
                                            </xsl:if>
                                            <xsl:if test="name() != 'tag'">
                                                <xsl:attribute name="class">
                                                    <xsl:value-of select="name()" />
                                                </xsl:attribute>
                                                <td>
                                                    <xsl:value-of select="name()" />
                                                </td>
                                            </xsl:if>
                                            <td>
                                                <xsl:value-of select="@line" />
                                            </td>
                                            <xsl:if test="name() = 'tag'">
                                                <td>
                                                    <xsl:value-of select="@description" disable-output-escaping="yes" />
                                                </td>
                                            </xsl:if>
                                            <xsl:if test="name() != 'tag'">
                                                <td>
                                                    <xsl:value-of select="." disable-output-escaping="yes" />
                                                </td>
                                            </xsl:if>
                                        </tr>
                                    </xsl:for-each>
                                </tbody>
                                </table>
                            </div>
                        </xsl:if>
                    </div>
                </xsl:for-each>
            </div>
        </div>
    </xsl:template>

</xsl:stylesheet><?xml version="1.0"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" method="html" />
    <xsl:include href="../layout.xsl" />

    <xsl:template match="/project" mode="contents">

        <div class="row">

            <div class="span4">
                <ul class="side-nav nav nav-list">
                    <li class="nav-header">Navigation</li>
                    <xsl:for-each select="/project/file">
                        <xsl:if test=".//docblock/tag[@name='deprecated']">
                            <li>
                                <a href="#{@path}">
                                    <i class="icon-file"></i>
                                    <xsl:value-of select="@path" />
                                </a>
                            </li>
                        </xsl:if>
                    </xsl:for-each>
                </ul>
            </div>
            <div class="span8">
                <ul class="breadcrumb">
                    <li><a href="{$root}"><i class="icon-stop"></i></a><span class="divider">\</span></li>
                    <li>Deprecated elements</li>
                </ul>
                <xsl:if test="count(//docblock/tag[@name='deprecated']) &lt; 1">
                    <div class="alert alert-info">No deprecated elements have been
                        found in this project.
                    </div>
                </xsl:if>
                <div id="marker-accordion">
                    <xsl:for-each select="/project/file">
                        <xsl:if test=".//docblock/tag[@name='deprecated']">
                            <a name="{@path}" id="{@path}"></a>
                            <h3>
                                <i class="icon-file"></i>
                                <xsl:value-of select="@path" />
                                <small style="float: right;padding-right: 10px;">
                                    <xsl:value-of select="count(.//docblock/tag[@name='deprecated'])" />
                                </small>
                            </h3>
                            <div>
                                <table class="table markers table-bordered">
                                    <tr>
                                        <th>Type</th>
                                        <th>Line</th>
                                        <th>Description</th>
                                    </tr>
                                    <xsl:for-each select=".//docblock/tag[@name='deprecated']">
                                        <xsl:sort select="@line" />
                                        <tr>
                                            <xsl:if test="name() = 'tag'">
                                                <td>
                                                    <xsl:value-of select="@name" />
                                                </td>
                                            </xsl:if>
                                            <xsl:if test="name() != 'tag'">
                                                <td>
                                                    <xsl:value-of select="name()" />
                                                </td>
                                            </xsl:if>
                                            <td>
                                                <xsl:value-of select="@line" />
                                            </td>
                                            <xsl:if test="name() = 'tag'">
                                                <td>
                                                    <xsl:value-of select="@description" disable-output-escaping="yes" />
                                                </td>
                                            </xsl:if>
                                            <xsl:if test="name() != 'tag'">
                                                <td>
                                                    <xsl:value-of select="." disable-output-escaping="yes" />
                                                </td>
                                            </xsl:if>
                                        </tr>
                                    </xsl:for-each>
                                </table>
                            </div>
                        </xsl:if>
                    </xsl:for-each>
                </div>
            </div>

        </div>
    </xsl:template>

</xsl:stylesheet><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template name="output-tokens">
        <xsl:param name="list" />
        <xsl:variable name="newlist" select="concat(normalize-space($list), ' ')" />
        <xsl:variable name="first" select="substring-before($newlist, ' ')" />
        <xsl:variable name="remaining" select="substring-after($newlist, ' ')" />

        <id>
            <xsl:value-of select="$first" />
        </id>

        <xsl:if test="$remaining">
            <xsl:call-template name="output-tokens">
                    <xsl:with-param name="list" select="$remaining" />
            </xsl:call-template>
        </xsl:if>
    </xsl:template>

    <xsl:template match="/">
        <xsl:call-template name="output-tokens">
            <xsl:with-param name="list" select="//description"/>
        </xsl:call-template>
    </xsl:template>

</xsl:stylesheet><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" method="html" />
    <xsl:include href="layout.xsl" />

    <xsl:template match="/project" mode="contents">

        <div class="hero-unit">
            <h1>
                <xsl:value-of select="$title" disable-output-escaping="yes"/>
                <xsl:if test="$title = ''">phpDocumentor</xsl:if>
            </h1>
            <h2>Documentation</h2>
        </div>

        <div class="row">
            <div class="span7">
                <xsl:if test="count(/project/namespace[@name != 'default' and @name != '']) > 0">
                <div class="well">
                    <ul class="nav nav-list">
                        <li class="nav-header">Namespaces</li>
                        <xsl:apply-templates select="/project/namespace" mode="menu">
                            <xsl:sort select="@full_name" />
                        </xsl:apply-templates>
                    </ul>
                </div>
                </xsl:if>

                <xsl:if test="count(/project/package[@name != '' and @name != 'default']) > 0">
                <div class="well">
                    <ul class="nav nav-list">
                        <li class="nav-header">Packages</li>
                        <xsl:apply-templates select="/project/package" mode="menu">
                            <xsl:sort select="@name"/>
                        </xsl:apply-templates>
                    </ul>
                </div>
                </xsl:if>

                <xsl:if test="count(/project/file/class[docblock/tag[@name='api']]) + count(/project/file/class[docblock/tag[@name='api']]/method[@visibility='public' and substring(name,1,2)!='__']) + count(/project/file/class/method[@visibility='public' and docblock/tag[@name='api']]) > 0">
                <div class="well">
                    <ul class="nav nav-list">
                        <li class="nav-header">Api</li>

    		            <xsl:variable name="classes" select="/project/file/class[docblock/tag[@name='api']]"/>
                            <xsl:if test="count($classes) > 0">
                                <li class="nav-header"><i class="icon-custom icon-class"></i> Public API Classes</li>
                                <xsl:for-each select="$classes">
                                    <li><a href="classes/{name}.html" title="{docblock/description}"><xsl:value-of select="name" /></a></li>
                                </xsl:for-each>
                            </xsl:if>

                            <xsl:variable name="methods" select="/project/file/class[docblock/tag[@name='api']]/method[@visibility='public' and substring(name,1,2)!='__']|/project/file/class/method[@visibility='public' and docblock/tag[@name='api']]"/>
                            <xsl:if test="count($methods) > 0">
                                <li class="nav-header"><i class="icon-custom icon-method"></i> Public API Methods</li>
                                <xsl:for-each select="$methods">
                                    <li><a href="classes/{../name}.html#{name}" title="{docblock/description}"><xsl:value-of select="../name" />.<xsl:value-of select="name" /></a></li>
                                </xsl:for-each>
                            </xsl:if>
                    </ul>
                </div>
                </xsl:if>

            </div>
            <div class="span5">
                <div class="well">
                    <ul class="nav nav-list">
                        <li class="nav-header">Charts</li>
                        <li>
                            <a href="{$root}graph_class.html">
                                <i class="icon-list-alt"></i> Class inheritance diagram
                            </a>
                        </li>
                    </ul>
                </div>
                <div class="well">
                    <ul class="nav nav-list">
                        <li class="nav-header">Reports</li>
                        <xsl:apply-templates select="/" mode="report-overview" />
                    </ul>
                </div>
            </div>
        </div>
    </xsl:template>

</xsl:stylesheet>PNG

   IHDR   r   r   ݅}   sRGB    bKGD      	pHYs        tIME$S     IDATxڜyeiU[߰91ϑC $LBBB (2%jRHW[N8C>e-*X(
	ɔ$9SpsV#s8}z׻wΌ{rr(NQ#`TP97rsIQP@E{sC^L}]Eȹ7ycdi#+dA1CLdڅ903'} =sF/W?p$ǈĀC*`C*n@Zb
XWR߼ȚX3R*981n`V 7*)3d$Pg,V&RXq宇u&D*9ҴSq9R
ԾВb@E12ڌit9W?ܗm5fؾ@UgHc]g_^}Ϯm8;ZΜ9xϜaueӧ0i;1Im-%ԕ;B֌A"ƠYI9s&4e@ȱŨXaPU
)Xjoq)V]XO:2
%%ĤdQsiCD43	<BkbTV) hC$eqfS^NĐT0?;baf׬L#حߺoǟ8pcR9֤|=̽⻞ww=m̙8!NdLBI1`|M0!dj_#ffĮ!f1aXOx[!V%t-XZGN`UpRUc+*K-J!DbLT-ODՃ>]A|t:%wwXc'kfv$+JЄ5!g541҄"X#BA.XvX>{?ǯh38kCL;~ #6<?CoW^Y?G{#&qΉ*ٲ4c "֐U1Ƙ1֐sQq)aP1lu"HI *9@!cT5JV\UZK9/I
w+rVtePJ5cC&Xޫw'#VrraT9ʞ]۞;v)FfwY-nw]}ɮ_uҺW=5*1X[1"gKaDVpޣ931<֕alADk=9#xWĀƊ1x_9a+ok5{k"TcE5ʣ)DTu7gޗZUWFP,"G7JH#xgQPA4Q9O F8c܎oO𱕕F sLMt9`[?0=u<^=$YT5Y1 
F/K	c}P-*%jNgeW&rʨ]C9%`
[k.헮g,h&|=K:4pNLΊXbga,3X+H*5P;urNRK|Ăf3G
Feu:Stfd-7\z]>ziƘ;rm'byڎ?yȓ}9=s%1A{nՋ)7HsZ@cPMMu1ҧrDCfKKزR,øGW90ƂxU#֡
)%+"vxobPUbK!
/.4 !&R)⌣PʌrC'N [-^{ջ?|~wv~ *̆wuo?t<Z8gp!b)bYk,A1F0=XshV*PkǠT!b]<ƔT$9/;H3Xףsmg-K9bD .RCfh[X8rk]A"XS;bK	TIY1YrDӵWa+Tsͳ k&D"1%9vVdǶ޽}u]yi֜^0{/9{'Tkcb\Y	9tJΡ3%8grr#bWVRnDsg`#ԧ@49l]mnfVQrĈi2BU0Ε֗ʽTx#ksV4QΖ]XRhK*#%-
%!JThOZZcrs%;c&c m}~ߢۧ ր8CDR>ߟfZ\UcAc`]EL)+ Jь80\UT_DJ R1.{-}pj
ؖSjrZjT%kN0dV25X`J
,We@}bsޢ3t9SF`g8qFSGtW>oݸn+Pp-ϼh<S'I8fA3pƕ 9+/XВrΈyWn
Y]]"dHGڷ"U[D\_}IXv(JN1W
RŠX)5ڲ+5wTԛK9V;p8)5, ߍ!pP3<
`EϼkŘ>v޺iWW#'OX+Ik=FrFz+ouL)5dUT!>a%=[;&2
b	10%a3Y0$Y3"NӂXŖO߳񊠱[1B
֣1S8S>ECbHX2"ЎQUb$G9+*jk	
]HԾ\*<uZg+Í/7_ܼ+MggbnhS+cjg®!
VZkHU:-@i!B K!89`.L3F,)&R+iZ4!֠oC4c4BS݀BI)t`	PUU=ȅp]ѹ0znDpo_ 
!4cP!TF\fHmےF<[,AN^8k63@]y}:rڻ>}w`WZ$ HQ;Ol .t%@͊1`rWj9vH˪)PbJ`ȸ&Ccm|?(8Kc
]u0"A3)	"6`v[S]PR|"ʙs[3%BJ<UUQUlmn{&V7ύDQ)-޴[Z&FxTR3b}1EG-$Nt]H1B`8,7`\M%ŨPe3#ѾI݄&WZ[R`%Aă PzF%HYjT˫I)G_s1EB.ƕC5(DUE	A盅UB^СqFRJw"LJ&V&cf7:kF_\t	&c9u6PUU$XL 1`IvLPʍAhB0ܜIќKےTu5cL:04@E4`Q$K;׈A	WHY39),'М1C
xNgUJ6ˉK+ԵS*ң֕-ԝXUTS$eGQ۴K9v@sAtDb0ph	!3XXVvqUr9D&FUWX1ҹFki'-ѐMqΕ2tU1h̨8v
!VΐaIbX 51dyf*IAMc@c$%à~jHZ]CXXҫ5m6✥I1V1ln"1QaV\ k<0e6H"^^"#ԃ!r1Xk5+lT
n0*;͔A]#еS~[-YrR2KKK;yC%egp5/§]O
_ٲ2s?|x{*֭_dm̍DÂBJdkr*lœRpCH-V6&R	]Csx[2LVhS	41%ymPõ@:U2*UԃXΖsfI)4h˼1!V	VcmXVѐv:E|,MXVkŔL+>xfŗ|wsU4yZ'lϬۼu 5׿,7ٵUs>éٹs;K"YsuZ7dc]WR#Y&LiS$,hlPc3T!9S6t!2Nib&Rac) ȁ.$(hg癛qh,XS1 C	qWh8f#UeB`b͊d(M,SdS񼛾z~e}2 N%/hmzjyoru/^;><]{yjkؾ};pHbi!0[Xؠlዳ9rWC$f6`Qg*.FR΄L¢9.c<l`D̸ׂtmUɩб<i*+|1cB(D/d^eUՠӦe41"1P{GQ^E3AְԱ79탧T=@20LEΛ	aW6|/~hWdM̯[ X蹬L&+j|=@u@҄hJQ	N[$sh$g%D"mRbXW%g&Zד$2ԨBJ3Yu=(s8cH126Ķav8b$2pb;?@r&IY]S!59}M̙ӧ8z[v֟\0FuH^jBdk+y`RZ&7JC2ުz7}ٺeK\]Hw@	&(I))54cFP.DJ=ꀞVT`z6S7(!{ҷ-On. &(,OrBe1qjzݎ%}x33ns*!+,-/qfvX,3!b{a>/	eBL 5MIצ4ˮQ|UatmߕРboz7k/bQFyCD)^SS5B̆6ٔj5Oxgv@JJ״t1E=Z522	r֓aNxd<e4*)oTI)H'*35b"ae0pѰ4Δ,Mi\Š2$U9ɎK>ص} 	nE")e&KLW8u'|GƧ:L̉'Iei.ndqv]⦭昙`ljsO_nC{AnY`EZc!du-LwbQUjkޡ#fG"O!^[+/%"kє	]kL*DӮ)CefFJL2h47Z E&GLC ,Yi37|{~
P=ZgO+1Y9{9z	NO<G#ՀŅyvotʅ6Gs榖&$L'+z ֱR_v.[w0wɨk/~O5nȜbEsp1%]"@+Lc-W/cBL6D-oۊ(F) )gڶ#Ls6̌P%@Nᠢo:T0X^3;3B]Ȫeq\:)a2:}-^/VQ 

d}|}w'gX~=;6o`i-duե\NrNu1Qeeủrxx~/O6^q%pH@T#_]ɧw9v)6ځ3ӦE1jCj_hm;b.zؔsڤO\MHIfB	h/;
mWRg6!d2%jxb %-gOf׾"#dfFC,t)56->׾yiv^4TOQkҌyR<~779Nٴq#skƌO5	"*52P~&1P1[®{v9yss5gN%6︀s^6mP5bpR)DHQhP\̤\zRcȰlS6VaJߺŷ:#m3MU(+h-2x""
ɡu{/_~vlD(<ox#lݸuLYZb:6M0Oh-RɔtZ!if]GcBb~~{#?pv)VGQy%yƳ9?uT/ +Z#&Ҵ-]W$/ʬU>DN5!3r㷜^?l֚zˤ\ƄZjP&E}V!H$RN%W-T$m(L"Dʉu7Ͼ~? 6=ݟqz+׭#+,,ĴiI(S4MCʹYrj)IPh .ZXY^&a&sj^? idp~* K,%W]}{ٸi9vԕ=JN麎6)mS%^8)y$ĞTbpXq㷜Y@zkv_wϬ\k\HJZTcua Xs^y{b?{}	_enqI!5t3Ǐq'~C}y2RnD҅@NzhQ-RWWD)mJԆP1躆iS^Jw/.+{?/g8/@m岫gwslߺkkYhHK?2^Vj`1)9b=Y7;'rfsvq.LA$edzU|:[ƥ1遵ESO:ݗ_mmQm{pwǇi>>}I3aڴ.
^jV}Dr&['-T׭j/eӶc-("$1As,<O<cKbva#"-eAJf~qKy=w|fh4] d)3Ϊm%碐o^Lh,[ά^y+Mx1JιwD&XwVhaT	V1)]3)1"G-qt'v>]P|>D^:Ǝ[)3LLеfz[cȥ~ 9F,b+uٞ}rJ<f)J_Rv],Ņy&_cEWa/%n.ߧԨ4EbRJSQjXkD ;	M;-J#.2]ITt?xW&mXO4o
zQr`S8?+{6AĞD'_9̦9uzǏN&FXB uXО5hRYBh%Ɔ:r$G.iVBa<pinH<
?[mRֱ55	gF3Bt8+0ROD65d
m:]    IDAT9E ,<#*)]Gϒ7*XAi8ᆿXax̙3LZ:>c$EQеHh,fg<b˔@2͕f*Ex:Kkt׊Y]%T)Rm WZ+ˌ稴3{j2L/Iycl᫵mqƣ)KSmu
2Hw5Y!H]}-kI]kK0#[8I]QC`2FkZqvHh[?h~׏u-׉cn#mضk;++LVəΑJzũhĎ%A"03d20[Gc.s)u33T^b0@b1oE
LǁUF3slټ#ߦDVBuӬ̎%H<2!Z|@]RCk[ROH,`|ouԘzV&a{38p[U\v!2m#m4m__a~1BU!p>?ԡ}ܵ*t
1c!ۦayy	LU
2BF*AsQ^JT|?}q/}џGdeyp iSG5xӫ{``iZEu+\rdpTlQXay=4PW.C	B̅d\sj/qɥb]E?YEGRzMbċ-W<1Wzu&v41?.`	mHJyΣk,J
=~)úb>]?Ȏ_=Wr8욫BU'.~ƳyߍYm~O`f0DlS麆AERQ5]5}F #0|`Ӆdӎ"&sVغB7>#S$#ghچ)teVxȔŎř;t|z͓ѰV{c{7VzԔzYK3;'>;l`CۤAĲ<1/pee4+g$S*KOe#)FNX⑇Fnx^=|2?_a.ǘUD, ૖Ky/PH$ao<p\JL2:.Tx+J=f 08_a'b1rB[,1^KE!ildaı8[sS_ZUU4bqjz({4ӆ,%1'G׽]{!a\ᚑ8E}6
[g2mе ]lƠ*KKK?yz?7~?Cߺw䐨ح:>H:f<o~om&}_|r1<pì.0i;fV*)vLCdi<a:fgss:*ATEk\Kq
s$E1HnlsH)5a\@qU	I3Oܩy]G׵$UF̱ kb#Г*8k8S,rmognvHh*O''>ƶmiVx)kWL# l:S\z/|RyAx_';	GCKʃ_?3??b$@Wԗx~#C{0O93r24m9#ض,sF>Α}zsϑ{Gi&T͈jTN$I	IRW#j)&-9oCiB?k/riIJLz_EGl}YN;EW>W]D)P_/nLv6fb"i8yf'۾7ʏor/p߭3l`{~Kx[~g<r7>h÷W?QNˋ_ֳzt̮+I=(f,^"n3ǎa0mڒbǠjy0|эHXW~
so\|/IzBp_ʴLrHV
"3>txړfƛ']Dmr֌cDJۣRQi\}=o7\
[O/sE[NL'Ł;:p
˝7~y杻9^ǿwXzjϿ8	Osl}\i<3#~tr'n"'q~mo S<ɉ/}p#6(?Eod*޻3+3`41겛rffn_&׼{:i{L~Klݺ"cs`rUS>f(qYx-˓Z}u7Y#yrv{=ӑqbΣ!,(zL~I:4lxջ~Ø;?w@DyˋlB̯_S0ZzDXܲg:UR4gs
9e>qo}|s\wP{7<,lfvq7XrnWL, 3.3=hH%ر%~hXElU S?sveR]m?N\##ܰ档v3Y;o^iuA'eTt?ɵRz>kǎ-ss^w%kT(O~WؽcuMc Pjṯ#Ǹ>͗O誫y;577xГ(g	/{;M+SsΎﾃZz+1ݟ's[_ClڹK}<}_,/1Zhg<&|$
))7i|UϽVѻbD9+1~ziGB	dx4w֛W&Sz+/ԩO{NS=z'Yj=/rsmܐ{z7l0G;g&ʗ|9IJe8aΜ:3^},nZ N *~kndfn{Yzbl;A\r-wpf^淲y*ו	]׿SOߢgذ2.wY\-.M N+V,+zv >߼!1ssU3)泵Tc#[w<iK4ҟza0Zek}h6л]|'vo.E>я0L
ʹLRGa0q})N=$x;.ĺJFPehŭ7r}~|cI9t>j{~ [`'
DX=$y.y_?ºٳejTIG1yHR	o|7ѵb.T$v̠~g3b.AŃGoY7棪ʴ,S4
[Ssi˫ly1CжC
QsѮY!ݮm+_P%Lv]?%x&߰|W앬ۺa>ejHY9l4T_ষ\=+DdO{ F<h7'>fDQiv;a=9 gˮgѵLEH=,3vTpi/)Ƣ@I;{Ў[S(xGZ.״9?, N*ʙU.|eR[;>$ĮFI)̀2X:q)׾7q>]qӹ_{>|O+n|9<^rQ:b<vW˷7}<1/x[8py˹e4{P<~8cj¦~E̮'Gb*TFiYiۖ$B
/'i?֭5L&*F\t٥g0CNOX-i\vcLqkG@$gtav$PH9F*3X|e'81hHlݵ*x/e]br.'S4,%(t#GOrz9})^23×|#ŋx%v+w}3xb/zkGh'xn*zq1;z8~p9:Q6Ɲp.ndE{v̮[ V
͑lFOv刳wFbuź! [/xWaٶs7}I9G|2dƗAyJZ\ݺ[֤Dhz}$Fz6UcyܱnN3`yqGՂH+4s	7yrơ?K|7C(3#^a6q!^7avԧG?<>F.~lb6_k0;q&VNp<peM̮!-?p3V?3/=)rHl QH41شcڑQyHPr14)t
)hVbJĐH>յN刕t -Xwl]p5G+an";h&=ず>N5I$1k81"^G(߸/}rAn~Ͽ	~	lt+oFX j>x짙.Un?Wen0~͟q5o3'/%߄yY7s5h[-dcY	l9!I{MtB!8$dh0xGlY5ZPg=%ݽ֪jiUoO<#׽s>+jJx?B+˩'4"OB9LYQlڒ($]DrzM9m)DRL4uE!'b82vaV4piXw>rݳ#>Mx
ȁFvpK>k?	Wexǭh}q{~l=W).;lsMfOrϟ|+o~9ooť]əO_F+RdEb9z`Iʐfuh;Sg,_$u[C*B6h"!?j#J<@HaY\I-Q*dJ6g-PQY\qT[ڶllL9З!ֻߍuEUN|=].</z͛8)_W#ibȫ57qM7q扇y'8~oʗ(FT3gSB!#k#|	bՊsgೠ@
?jJH)Qo"v2}!SD2kj_ޤČQ4vTuqTBv LgUˎOxooc茼^X<W|?~SnַΟyՅg;rR(5R5-eǸ/Kyϸ~2/c )UǕ78	cXn2[2ȂF{W2;H]qjJB)[/X*:YivR3v EngAə&>U=kX).5 j9Ka-E86c{1~'~wßصNPE?|w.xwny밮YGSҗov?o~wo3ZsqhQD^+I8g/Cơ'v<Rd$H1:ZM-N6b"G'
7mNE1R寿Gu閅TD=Rٺ BPZ(S,d鄔=U⣐uR"ʙ3n`,GbZ?3o{)9/`eE )YßiŒZ0ta9%c\EPq	v"}>0
3rN釕1"]|/)_L6I`	E=v|)c%`ٴ@BN)y95/B_rM\C_)hr<Gب >S+:L+>+ᶷ*fe_(8tɿ7~G=o[ߋk#~C|o#Ry
}i )>j/fiZeH3=)Ӛa_I\gUYkZ2Sľr3zi,E?;CȢ#-b1\E`3eU;Ֆ<@P`cA-9pp'esp!.
 CnZ( {q!.r|w~m^=oqNBUե7o{kWp;ln ;0!2uz"$uLU,x
E6lsf_dɇ+2lMR2:*U!eXvL+ۙq(<KKG?xRQމW.RMN0MF"CU>x)12\.S\v=u/}n4mn*tOU;rȔ/owo|`kF@҆k߃~h&m?I4hsV\(p:YqQK0)1hN?rO~YKbwR ҂b7rʌ̩9>$JB&F:ʂǈb~8?! ׏C/EsRteK6FT9(e6ۊqө Cϵ/>iudY@gzݳXSg9ƕӏ>ʟ_>6lqG]kto~7۸;OaIz~E1C,uY'T([A҄QA?avʪ:4=ec1r+"\yudyx~$i!j]8x@!XMJbd؊B|3]߳\vm.d>^!eM	 J[9!xpysZqՍ7WRbmTV1_xmsݻO?3(W9%׿q+^Y{!v,kt_ELUb`kgG>7~Y/.p쪫n^w)zE)EbC8'I6H~M3ibskNA0oV3,w>,WV*Ib!ff\!I!0atuUiqPC*$IMQH%llL̓}n<fTe`%ױ`}GZ	9d)
оHuL+]0luo}#GndgKy	1G=ˇwP1I)9I_>h.y{%ʺzEJgHS9/%K?B̎!$Ƙ5r#O7xpgN?hN<Od1JҾh?Qa?H)h[d7Vj$9s:gKLRNmE٥T16<҄{=YQ    IDATs/1A'ڠ	Z!⬨
/]..΋ %\!)yY/;^W9go}5	}~G?EvO>ŁK/%ov^;8|q!g])BT[2uOiP(Z|N,nmU/]Q:A QjOwW^~;#UՈ)Nu"xNYo0(j{"P+RBW,9ըKUfBdkPŊ'y<:0%eoV~|Wn
3'1KD}dGiKÀ_@XʞS"9`ц0iGȕ7i<q5o>i,y(1T΀>ܐ`8kVش#+é9o
\J
ݺA5Ś~g\($@QAZ臱=#!+6RLSW#A|9Q6lx+r7
,)Xy[_oKA_$7I~)[[aiEc6EEog) S~.:ț[W|;OP736^u+ǯ
؅"sTyITa4Yk-5Q!&1`sk	>귾V{xejỿʡPhɗTJ*y^I&gx?N mЌIc[(kŎmm=sSW>9:!+#װzL[K R7]\rElc|=x5䱓B:_*%TV9?|l]y5W%pS²IԂ+l\W$!XBuCHRbLr([wydXǶ!'vvW<|\qLӘҦDg xI_SaN6L\,`9fggoЂDJGu[΀C&}},W\rdR_ /Rq *E֙y Zrn2Xyczۛ:~mrH_Xf.*G!FAХ3??&2FԆ)9U	E;LN~8m1.!	(|J37'L'y'qqA2^&~BXg(kKLbf.a4>e1;*Hi>qr)kcpb+o~v&]k%|30XmBHUUcbFL
<.}u(+v_AVLI<,+6!.Q*rojsC@5B9{~8yWPd6)R>J*Qhvv\Wr'`9@5:c \}я>тK5Ƞ3_o="FQJ-k(cR7̚@mGK}'wEa"t}w?y𡓄a TFbRoSetb8tвؗ9>$(=-ZF cLRk=ENZAӠPOkѿx#?u?[ܠ2 13zd,O?zw5yaQ5<<~=6b`T6ɄiSQ)6z}fQ]SWu5}@BFˮ*eMSUX%)k*TF}+;i"=7v=x}Ӝ)zrLt^jdVΖab7gݏL&LBǳc>cWGŌbL:ȝ^&,:M`F>Y;LP}E^K\NLjK5@L;WW^]s	՚1)B*ɵh"	5M-	F!2ʗ*,U]]#X&eq.p38#)0F+W W30_c+?/o(?;IlM6[:HZ`МR9u}ّMgg-{DZHsȫ /ҟOY6LbS2c/hm]3?[?W}h"5|l{?qj|^p0EM̆@68ǁP金9Gqc/tgQMM[IbEVRsZbtm؜H9nzLdgQV#3[]_vE`*Ge-T1xֽĥRTZsX\8je7܂kp'>\%rPOOoSL5Ƒ"~޿U^&zྒྷ|	TKCΨeZ󳿊ϠufZ}v,wPb(ZW$cmV)>d5G~Om4ӥ(+ErEMg1#]?^E8XjС?+xMQ(>~|o牻kD9AB!E1ĮIu8_o?/:!.T ĺN=ˡ-]EN؜5a`FlRê08sN)5?8ݼ/=r)?Ie<rյ8wmHOF֝12]@iI/Tj*޺FWu'مb(UnĬQ"絢m[&YKKșٌc[-O5-ߊ!X=.;~PNdRX2UDeٛ/!P9C=clnM	A[]8pq^}3Wq_-ñC-cjխݣ=nM=}׋T2*qe>\T=u\~߱"'$	Y<;~#1z)\*
)˽=%6m&S,#o%rIgY^qE)DF8'd3C7Tsts!Ə=vF[bM=.ף^0ց1w?$A$-a=
)@S9+UR*t%ɇL85acS/~V|#L\vAډ؍ݚ9u!mH^cHc{I$(V>s~gV].vG4֒f񯽏',[EV@,-ATib=|%f*)XsHk@pGXRqc;p45s]sRTc2`)|c6)U%y6i>w5R=Gr%y[⚛_0l*iSA154C+,gUז+.?̥Grǈ(6&̗+vwwǨ֬YEXȔO<6z5:rgv${)~~^{9_ZP4PFb_,}1ϖ$+l4{@}Us(i!&ѳ^Vca:V5U]A[3#5l~[?zTO|۾@29yt5s^{FV"3kjJ{diJ!XwkIFp~,F?R5S[a6uj1R7T8U^ZMc$);wy=/:/{Mm6%mpn?8qIE=!KMuI^k%D<gR#9tสt]/}h3/˯9v9!$>mrlln0NحD<h6&u%9xBsCt{~7[0FN*s[7!B聆Z2m
),$4ۏe#+).j"ekD/JAa+KH9C)wx/gfom_Or/(E=j6c'IaQX/!KR#"f+B]$W(rdM뮓+FZy#QNw@ܵa2iM&"HI0 9:l&FI(b/uےBرM.<p%7cV17N@\rozS9^2&d*c1QW=]u9kP)2F躮'QT-cƙxr>EG?:0ȡH4մWy+\r!%(vߜPO)&$[ޯ22ݺǇU'ƏPRsc;}R&3	MS_}J¦nH;E%pnp-F =#w޷\u$vrHCW_mo}Nk=b4LIM_b8#X	Sx舘T~MFZj0P
j9}GF+$Fʙ%7NϿˮ؄՜lldT0{y檫KIYjș,5y񇡰/S̓k]%`*'3<15īol*F֫qiSŤ}$!*0ZªvU%+cL/^Pޓ'L/{먷NCOwa=I%BhjM]£S9Gڵ1RU[cIKK.R3Z|?bi|r7HqA+4SVu`|N^^<QZɐ6>Opz'TqdVX1l\>Gv; #ԎvE-Wܑ%>{O7$bdkDe4Wl:'vwg1->'B\'BdiGko@U?uݳٛa+GҝWɫ̺[1SWMYB~Ǧ>`vwUm;s-7P
Zj͛3΍|7+~6L~d#Y=U_'ҾYTI,U(a.(پ(Tۜs#V'n5DI٘Lu;ir1V]W1TrlLu;!釞#Ƕ8l
C`<x/p7={ۻF@U;1ߖLG裠~V2JKH6	fŊszoh/NX"G^gBY<z?dsһN
%ISsrQ
~Yd 3ڇ%e(	5Y=o :c;{MZd?9H$czIļQIV=I$*|#mS1T<<, G<rUW%no[o>p[BPst@TF\(T*Ւ~tr[9szu0Tҗ[қyۼ-NB(ba#uߦ!p{^rƏH2F֗:VJ\\UkQ'1Y_bj?Ȫ߯*ؘNjrJ,A!!HT)]K 鄦5ł=Dł={%:03V^Wq`}'~U"VKTsUx|'O<0O=0x'Oe9s~!&<sFRdzC<a9̵/usՋ^5/~d*
pAxc )ۧp)w}lNC5;;P4T>dF"5`P	PZb!z_"wCn(B
rMa#xޕ0tNҊHBbnT!=X&MY,x?Ng$˽=(QrlmcW}Qn|m|ӫ_P$4t9.j_"^[ 3'ٹCXnRqVRcduǏqaqK1bNKD	R3g.Q	WO>_CvzV{2sԌzTV`5˾kZmZq(jl9g,:s!)e(yY",1P]LoDXkpU[xuJo{9,U݂X.g2m%2!sq`CG/af<<y'|?xPn˅,>(eX%:n9^~5ua0=$--kr@+٫kRt|r?IC(e,zυ,KTS颐R/Iۈ;R叉L.C	BN֢TGiicKs4;8vc,>	\VkꚪrFe4Mba1_\.1RMfF)E3iKɉbz66t2Aw|+׼_~JڕZmFoQ1R&rH!SYLJUX4PD5Fg-JosC<I=/p,+{
"20&a2%rALeàhGq$^"9U WΏhrF%MB@ÕV"yi*ˤi)srJ-!%5)%I+IF3[q/W7=gq9rpنFmvC<gR^[U/gئNfjrDu'~.x\h(AW0~~<zi̅흲=)9tLdk?:Gk2Ȉt$wX0zϤjK4JVEx`"xw$aHMkk">8MDuU@rdog0Zh3rMUQ7r!!Tc1_03D?ҭTV4)*6՚p'O?>q5/x˹P\DfeYރ(B++hQ4@Gt7)52a{Z*%p钨Bn$VMe\'61{yAUnRL
51JulªsdZ:!(~ݕ~$bS6U5RIaGɔtFzMLl6^;)${mzѱZp] >9i0i$5oR؜I?{Ͼ79r\~	.:f^!c9t7@Ss_?(g9S}`65X8dq9ǁ&Tރ2tuLNRvRYsQ wLyP嬠ˌAQ&gr[8A|&0V+,>ni0h}qV2Mq`UZuUb%8vAjŭ#1y6f3n2!CKUUafBNrE"L&uUQCm`yk<~$E7DVNjtZѭ2ichlyÈ1wNrC"z.҅|d6XQ1'T\L8"	҆TgqVDn*.ٛYFOȓ}D%wcZ9gpqD*EjX,nZ&XV6,12L&3VXkkbfblceyrN\}*XMXiE#McZNClkcdV;bY[,0B6gZҍ	W9c3HS+񣠫SLbt255!&V00t='t6#e\Ɛ#|1kHA<HUR8Zea[%q[(I|Ѧn`+8۽]8PS[[c¬>0t+9{?\MN軞U/..Tq7dRԭcxD$t?GzI30iU/_QږZ=|$sTqde7bJT10kГF/gIbwbC04Uٺ^,y%'e#'D0z//Қ#>f3-wx(%hublE:6_  IDATu:s(pdmN\Q"w@SUTN2'z6~LfL66a0e2a"(\U]O]bLT1`$SZoq#'DH^	j#V5뾗8*gƮU0UXcH@Ӵ|9d2neB׌!3EoE	ࣔ}%Kh} -,?3Oɰ9_o׌à6Yj3<ŜrA[U41]kfı'M*ڟe>S]W$YYŇՄDGBe*$S9'nCGBd:KlMد%WaD;-Ƒls!ɄzUj%@FDl1ܸː 65Y/qR%E>*GIqY]s%HMOz t)}CLgχLlI3_v={Cc+'4mX,CG]5To_V*GNFTU]r1n1Lq\-I%gK1N\S%$)9WWED+/;=J;!ZV1a<pV5,1I95ǔцnDL
 qB̙ʈ;iUBk~!:|"ʔIn\XǓN^3OquKef#LI3dvEq4u[n'=UUՆ3FdcYukBNXcJ#S7"g-DqGIwE=x/2) u%k9+h'a3uC"ᇑ29KX/j?a +0cBk+W>~*b \|Gʒ8gHEd@F/8(wc5cJBTZczV@(cZi_zgƠKQr/gΞ^jΟgwoxꆔ2뮗T	C5dlʆKӹݘfZP4#@hƑr)KB[@8CZxyNEXℵ-\YLXi#9-|1UvUن}?oiVݪ$e~5$✣EiqrPdLJuKej$۹X@N>`I+zXv8N.Ù'ͿsH?k|w^-rL׶4R]%h'UþW/Cyu8XSZm)GʒB")#}?`̹$RFO#! ϠlZBX&'c')7)Kc
Sd);	Q.b8W/AʀuY֒霅R+y/"0c#J[%JVnA1O?rcOg&}F0!C._MR(%wCd2Qh&$w-[[&eJٲt@iLbQ@(yKCF(1CJvT(4 ~%Bk " JIaK{ǢpΡtjz*ѢY
Wt@6JRiOLA_E#i~.{d2G=[k8]By\*%&	 G~]L&]*GS	-OL0F,46ZNcF)DJTUE@Ӎ`E V¸	93 JSD(hQ-lK;Zs-}6hcA̽ҪY-W)gVuPMQs$f9BAɥ|4mc'eE*WFC#>r*p^59wvv|Ji5i[*)2v^UP[Y\rb{OUIG9$5)bJTW1F1XkBu݈A11Ƚ2Xr"躹XFba9dK[^O4ŵ0U6V$~BGb~-sŊTCV[mɅGNp+)`O{@ ǔԩuBirjY}'otU	qYI<maݓ{Қb(d礒S9%FKPf,qC)~$#KR>$qXQp`K\%1DⴤK"P*ZL!""F*^)Q-QQkIcZI"Oq@!HrXx(dFյO~3[=eIϏfe,5!ƧvV%gRR{9ڶEi|`Ft	PkQ9.^p}Kb,o֚bӇͤ`#Z,/"{U3#a eAyJ(ORf^ڂ,8wRrUb D	Ieʋ8Q}m]óZ%x}~'!<!67`/z ]!vֳ*E%2KiLuHR&F)5rS&x㆘:'Q:Fݱ2&i!r엁TrqI֡+UUޓ$)al9+Ƈ 8|ZRt]'_7R'NjsV
:rjƘZf26o X_LzY~B窪ȴQ1j8!K5z*TeOWoJn`=
<)FP}!ֽ'$001iO~=﫴cB*Ywޜ3^Ǖ6Ie -ƞuKgNaTuCÈqdE.0\vrIэbf[+WYuWO3_xfgqw̓e&nH8h_ZlHoՕ&%lN.d>ZѶ=0h{{{,mk0K4cmu
iYڇ{]2]}6p{sY5XcMI]{/!p8v8chonȯ.֕r3UIr
X51j=Ӣ{B+G#ΰ\.yDl[|Yr<HWX
&dCUs^cdw8UkXp	=#ڳ|l5M>SN.n}y|q~[@έT5߀3fz{YZcZ_ىY,5bC\4RNQ}dTaG!Vs("şR*.S#cʔojv):e#krBX
8k51Ž1V,6FG@f	URSrCL]?NSJp׃_&62:[~>}QG~`AWՎ
ؓrG#@^FP,7
G06y~@_~jJf&s`a߀wma	tVjK    IENDB`PNG

   IHDR   9   9      sRGB    bKGD      	pHYs        tIME 'w+(    IDATh͛ygY?;ɝr3s!B$L-jŪ*TV*HQZJIHad2sr;7S\mWZ^}vd?7~[^ZJV^'(%"9k!HHcDb@+Ae9)ukO
2@$DB@RjC!SBb6W899}1Eδn  fyg͌lll2DT",ۖ#*
J{\Ca,6ӈ("Bn#5>%1Jȵ9U@+Z4my1ymw_<ے`\դ?klgcgD41D~Fhں*CL=.E^EaIFC BS;Li !RuD%TuKY
kA%v3z[ǴVJ\ۦ2+d볲wp}Cnz˯2(t=zsk^[?\/>yEZ"OJ+IB-F	$eYbd9ܢ1y
-!2'5fX	1tgdGC/5JkOVcRgEVӴ/nx+=~ݷ߾q/}ݼgG}4
)wH<ˈ)CHh1FcIVi$J. (52BHhZ(f4mK(ȌYScAk#
Qc^:|\/z5ğW j~}ٹ+&ֈQDiф %B̐sSN-uV@(kIa"5{5DcEnR"&(&&hۖf"h@iiӦ^a:o痗ГG+ hΙ1%4-)
\̚	!3`lwmh!ALhcNKHX!ѓ$G5QZCJn"h! 	T&31Z#$TӔ1l>p@/>3ݷR}(%F+Ci!v@)oAYb 
I	  EOBKhMBA(Q݊fx	%EA	ڐ)RBSikj3+Y#((!){VnW-M'ILF	RIgR;ZI1:zJ	=T%mwh]$K<'E͘ԳiWyFkoBRV8QD$zB}ĘD5RBMgt:\sOXH}Y)P$ZOfef)rKV55Hk<gBVǁs.,,!dlGӏwXZ^!	(ijZP1>jFwAF	SlG2Z̦yBT/zTZV!dJB@jFk2IiՁBO;pKg(@×_
T5_3];9\@Jw- (I4.0mZ<((mHn=;q蹲du]~/Z`c{mSҌ&Akyf8>_~W&RuT,)9bT?#<JEDE(ʒgŁ_N'ÿ\nEIMBжyJkP$rĤrMx`WJZ-3(Wɳ"1%UK?fx/ĘfxsG9CLמc2`}rJ`aW2`nt3cJV$Lꚲ1ZQhMLh2c:Be6jD1A)TflF,1J@JB#M3ƼUidΘG>i֟~X	i _(I O
Csoa~)_|O]>zI(lF4(V5hm([e"ɴγ="Y'OnJ+BYK&~QS͏sHBd_yϰ+ɐtN FYS3<+вpsӏ~s~/7'7.o䢋Qx<ev%3GO	8CLzy<|{n*Z`MFBZi
	Dcry{I)=yR;4md:H!z$|DtiZ5s|{~Je7տ2&cJk34b@+M"2k(s7n+×:%Zy>pkoe|ŋI)PW4ш(M	%BtC/IP)chE#9ƣZd~_|?@C_hp-" "!vAKE[)D)MgiiMkXŃy&HR6c4p*dR7-VDJ9?m|9N{hR JnooQM{O~Z 1yȔh HBµ1Q7m1|4=)1(dZfu}/{|/a뙇!fuUB!Sؘpjfc_.~<5.[hӆD=(_3N2OZߦ3ZDh*]K:2QA`Ɛ	ʒhE׿$jS-Jmy\S:\{O^[c\|-a flL01b(EjZ*o FNG۸[I	3^wˋλs\5˜LVAn:k<M,#(yOc\RӸރ=gqMpƾw6go3_GƘ<e7Lv6}cClM߃2+t\|I+dQ9>'~@ϗYŭ.&Ȯ(ҡD}t<i.`
zmzYpk䵯Gș_p}#}?+9c_^.)<;Z}q%/Ax[3(EI|{!e[GDh}H=~>6M/+[Ch@R#
L~V,6||ѱ'IR^d<앯GsY9t!cl|n'y37\υW_ó~/Ɨq%/IJf78"p]w!yB#gǷc<a:(.]Iڀ-Y^"֏e2c%3Z	>L;AhɋX: x'^_sg{~k?·_*6Ngo=1	F?+{XY^C	"*
4	0Y4F"Fm4y=\(lV1X%mU3X9m:r"Gx\p%7>r;<..	xs,Ɉsrknm,/"g:
zYH=sg,wAXV8;bM")M:}`4R5UPHm#sP$b1V	̛緸z?¡.s6OK.~=2\׼s.#}\vL[|c=2H)ҳZtXʲdn
u눘ऄGt`Z|x'[K6slg(Ҿ,?@GhUWS/_'_Jzbg׿h/L^l}3/7o!hWZե CRL"%L_͐JI_B;OY\P=]g0WFZ^-WbϻO~o%ώ)Ko>sOY^3W^K|6mMR(cvPJ(<dɰHUw"(cd>:RI2	c[{?l׿'Y9s?x?_ݬ>c*:7haAF>TUR֤]s	Ѵ&Dwv"ňI	b+HhҬlr&vFLF#,-R~Ͻ\SoE>ͬٯw}99Iaѡl	ȗʷ\3~J]( ou1vwxO#&H]WĀ:Q(kq<Q4dl2?6!rz}kgs.xK8CLNv6+>_lyMfƀ2P[w|fsdLjVy/.@JmyAiO#XJ(JMjrkȴBIgufU\b90y[l>?/z;a1U7?y'bkl}z/_:_J$BL<H&3w%ӀEPt-#صNXY-enѻȮu#nU={`|
M'((+n@eY_~ei~rz0B@K'h}HHql[߰9d6$bbuJ^5η݃[<w8^z({-D7]ȉdZX{I֎9piPFhrͣ'X:XUjd9 D&6*&UC9X[	>*8zbTk;8O UնX[gsgx2m]y<g+ٷg{>1|'\{c{VEe<'I+hqyùc~)CK"DK99W&5g~@EK4S{OXYo5*FBP"(e4OĔP)J(eW7VBg?9,@?mz	Fd65?hBdI|DlsƉ1-9GrM ӪM~g~$ a P9L54ՔEv"L%r2y9pG፷P1xus>
[f.a{rُ8.vy讯ro&lO`m2ApV!ư8qc\#o7\	e?cs8%xҊ,/ֲ0g56tTL^~gS"ӊ̉gw-*&sב;~nzT4)DF
ZN}$p6O?> a$;;lGچ1Uͭ-q=7ߏWiIsǓ	Bٜݦs}VQ¬hRgP]*<.-^q)!۫sJcRrؚ\|
-kkՌd
)2zEF!ԉ`g◘YW{ɯ*6;;VuDQfǷ^v=[ǳm4sdF#7^.&uw5[W9J\q<''q"zceZLGCmJJGY۞?b.!*c+Z:	)&xT2ڼ@+u-n=wy+7>}/_*Y,3zg;am-!Aiѻ(FCk4;#&S孿0_*8&f
+z5M;VhmP6CH۩oӋy+['	sgtdk,hexB`]_˯a"{WǾ A%_d5!$,q-6ĔX`<n9UMy7_v.H76%׊PJ\v}Ϻ;Yz$}Z,zF$kayp侯S,elh)W^ͬ5o3TyN!ts>V"K\px'HQDwPږ-tS'Jb$DL6v "$dJqdM_{-sgZ80F[KnsEof)f(Ҡdei6X]R[8ha0^b{ud:e"Y/c̃,Y _u0&OZO|x{|x{"hSn#QZ
iږi0i|g܆3qo4>x"ȴ<4zLFC<g2RQI	_	sWonhX>&P\ø@Ahyg9l|N3acgB"n6WVSD445(EQûڤ;UU|R*Mi2g{{a:/T
\CaOK_9pޥY>c%}B1g󙓜|iN=k<rhc:0b(;ӉDJ鬦WX- Τfq-;cbXARƅuD,Ȍgdecs"Ec</{HЄ-J&;۔Z8yjc`}6ǾSpe8D:sqBGHJ|L􋜪n|1MfyK=m۰
$NAGB3SF=eyRa(Y=}m,(;yNBalp{Hy#mZǨB1.2M[3v`3ڦ4&Hx36Egk4+PHiy^dc>?i~vIWӧRVb-zE[ee-фHb)k t`ЄHI1kiLqR?&D rj76dv{b  !xOMoVI#(J꨹՝:i+l4-ǎKLh7R("@d0krkA񗘄=Ӻ;@imv-i}m[<'bk4B8CumJ\"I5Y"0:5l*ɳk/VlEl77Sserw0ڒ4">.Zn$"Z[|Hp13ALxI:6;eXs	URO	36&CO 0޵>:g6RY*7MsZmiBJRO{TTu~pBJi]k28ZSdR5 BQdh}dV7	eJֆJ"SuxS{Ut#eMz8!&Me"ƦM)tFPmm=6Pi5RW!
y.خ|	Һsu!yZqz/	f$4gԷOl70id=%qݨ6{Kw_fJ+|ՍMaw;rT:(X(MVkfń 1u$kiCi0m=n{GЄDTOokiJU]I䙍ι}F<rr?>~ugֆ=ƽ,]}xsN}HT5Z1#B۶Ѱ[$v nn\}H4$mC6(EIY^2*`4ܦjy*?~c۳o _A{K&XN)4p8._-   IDATzХߦΊ@D}XR    IENDB`PNG

   IHDR        :   PLTEaY   +tRNS /_?MOo	ثKHuÓ'*zǽ̎s   IDATx^흉r8h_fMp+̹J`pjt**qo
}H)B~uY-o2Jl!aOpŷVcqJH R`f(WQY&)A^ 蜫/dկqX+bF cOS!paTUJwpIdt;f X^d|M/ LUZk!k[s#v[n'//j3Ǡw_	_/UOT=S^QooR;U|*Ug i[YsTfgXq}ہx?]R5j*IrH;z]Xȕ~(O+AEjSJ ۿ͈@DZTTHUBGHl;??_v8
ށdg(_S@RXcx}Ș{<HWM[#pt0BըR >vˎ+N5=ƥM^{sgcq#<g}ܟ-T}ڇ|Wށ#pFKT=5xxt*TxwtzU>ϖsw*͖S}Tɒ+6L1ogl~ryenc e`5u9!C0T
5j\]r.q_9p*߅hSm%a%T-JS>pʿO*)<$TerXK]ՕSgBv!miGzkdͫKJX |7ˑj:q36kqt8GՒ
2NSϹNeȽk[1_y T9NFKqpίňjQ `(TDʤ4D\-/-	6~T=Vy*	AJFFҤq!/b3C}@طf-5jמ)$'@ހc|*䠯z@Z+
>#)[~OcDq_ux;E5{3)/Ry!"_T=MZ* F Gf F8qo3a>8>NvʑF(4zQ}7T[~^i`>^CQF80KO\s%t5TUi:7Mq"@,\G y幞jã<([omխsk>*"Tg'@q,ƙ#\gْk̖:[uKWt l)%8UG W[߫JuV6TϻTUTӸuUG̾*귻28^_uu1U1U.|'K<CU"G-y?&馳1p	QfQ/r=OMW3Vj(HY7Ow1_&riOR}ΕQP+ڟ VbiqS"z88Q#1K6w%TAvMA=ob7HNXZG	}H,1U/ҁu R'E'JF>H!ʋ,ozj^TS)I9gG=]k#|Du֩z5pru7(f?<-#e՚zW߉EYE1m2oӳrgʸҚOv*VlS=YlP$!<.QM@OU>g6K PVlɬԷ>["vm0	?>=Vhoٱnw!̰heK\@ҧKO<7z\Sgρ8mTR?7 mkޅ5m UۄPz?Sݩ|ϓCWY]]]]]]]]]]]]]]]]]]]m]n_C{.[THR#k0]bF>RˇZ~d@=xd~S0@RvZA4-SO.a*U֠$910v{Oȥo%9+f.@@AN3<0X~WT.o|p}0v}'~Tac1Zv^Lgu|K	?Gj1',UU_dTalL]~:C=CP4J`°Qݠ2	& nz&C  DuJۻTa*ŧPe26T0}Q' PD[Ne@:|*Ws|q]irQZ#pcZ.俩H"?:xIpU[
5ӈjLqSIPig*O{U׿W
=[`O7|Z|9%):d+'Bl=EZnziՐlʺ^-0O+-\[|^Oi˷-oyoɾD%]dxg.z|f=>*8mq~_e2ɛ25]A5:"#Jyp>X=4+~"4VR?C0<.ޢj@tK/ٶM5zyDs7yKYFkݏAW%#Z$zjqkosEDB:HoiM39_, tt#Ύ޲6b=O;sG9Mu|qXO\ԍ|6yDG>G/"Pn?bO3v~1G{UT'W(|؃X+='Um*e`"N+U %JqDlߌ瓳T!>Syc%q oa/IB~ZxWJ<RTyQ>ydFGj5fKlz+.
bUoU͇	9 Hqx˳Ϛ-}IW6H/J|ڜ ]^+kF ]=}N	48E5r2ryVSe]oD/E8T3E
&./g믿ַo|>ɭ?l2 :cE0?EA kA쬣fsy??'u`D!h?*bƅQ,UmxO)zk{71LY&/7:rJt!PPC|39  \YRea7r7ztyj}}sGy*{e]d o}fX \3Uj{^`)z/7^V 9.$ `, LIu0SeM{xFydQ=JnߴJ&zLot*&Yli%r*;ݢ)K5,U%{Lut)z|d?[QAF8g4 vXQA5.
{>LK9iDʥuG TngKȴg")is յ[o& ~ZS(DMʀ*i+ʔ `\; s敍eh+k!~ J.l<mJؔ0aJQ-xeeyT)"1
d$]|*h]N}Uծ*Tu
rKXh9s9ʳ=j_=h&y͈t)Wq^t{KVegʷ:TwՇ^g    IENDB`PNG

   IHDR         a   sBIT|d   	pHYs    B(x   tEXtSoftware www.inkscape.org<   IDAT8œ1
PDFH[zxmRi !c7$`$?'x K뵤8zQ(j">W`{~THtʪmC`fr98vikLI6)UUEe E1z<ǬcaGs`d|S>:&ӻ9gO~    IENDB`PNG

   IHDR         Ĵl;   1IDATx1
  8A&:=`c c^oZ!
r(T    IENDB`PNG

   IHDR         a   sRGB    bKGD      	pHYs        tIME_.  IDAT8˥S=`~|$`F?С?PނSKNRGtE$^PP]P @d#oN7೜p<C88H\aYpΑ$	$Is؝oT*\.XӴ'bq1$IfA)(Ps(]Ki^P( E8nR
QA)  nl6τj48i,ː$)$Q(.Z Ze^XI@IBe,,N\ïRA IEab2s4V@&Is9h4EJN}y,+,˘N mPH\A~ò,Ȳ0fhu4Mx0Wz$iڋlnG]uvRR<eFѽۜ    IENDB`PNG

   IHDR         a   sBIT|d   	pHYs    B(x   tEXtSoftware www.inkscape.org<  mIDAT8œ"Qkz@N&A| #&ML|IhHA`lM1Seofe=PpOpVSgKT#O
%}#cXm⧤~Ie9 ˅nGP#y!I$I6Fiu2aPpvm=IUV ȋnqjbxqC0"d$:  HyÁVeY4M,zM:s:bƂ$Jٌv%STNy5L$ER5~=-A(Hǣ$0I Q
=л    IENDB`PNG

   IHDR         a   gAMA  7   tEXtSoftware Adobe ImageReadyqe<  IDAT8ˍ=OP)C0[!k_@ @

&~@[%C
*UAVJ;dB,@l_رo}nqHP=<>. ]D\cn?/ 8FNq$ɷAIP0Hɦi²,0iDQdAJ|mTU&2t]$ILPT@IMIP[5AJ(Je%6O(~0[dāa(*yUtOлM̾_
^I
P%4UUoVNcc_E{v_B|NuXתA"*kfB"_0-K?6љc.oal7.`Z:g|)bbܬ*āG
å2Da.a<gɏ^f$VuZAm{ToY7AA{:;r{ЁK_p-pdQ>2A$tC ʘ?    IENDB`GIF89a   jlbAԽ|9tmp|_,      ;X%ܬPƤ7i4e'E j
dq 56p1tJU$  ;PNG

   IHDR         a   sRGB    bKGD      	pHYs        tIME&s"  |IDAT8˅OlLQΛԤLjCkJYV]  $D,!DN$,6AXI"HFjռk˂ι!AWkYӴ!=?pSr7N'Gj.ZVsYoGxL]Yï;9*d6x;<[*Z 1`Cp.9VtY~K@BTydkO'

ن !H NyhkH574~_*ZPL:O0XUjã<y}lCjteiXD|Aʑ<,)AGZ-$fL	eMTب|1b݄ʸه6mm3I4q߱H;L+7(6D&A%,]
CcHaP)3p8bQkq*7OzGW		qR`+ 9+Ր{Q '(7<*΂SҞvwA;xxz^;pͳ+qs6uRUԉ/M\0=6v4MfJTXY,b:xL#D[V-aNmj	CcQ{j~J,ϔ    IENDB`PNG

   IHDR         a   sRGB    bKGD      	pHYs        tIME\s  IDAT8˕˫RQ-# H"AA"Ms05# ΤfgR"&MAc}IO#wM6k>ZD4"pn?T*դlCҌ[!Fb$Ih4.L
gA4pX/WշT*<@~p\D"!t:l9%f(wçD"qf J)TUjzzsx^||r6E(c2R`0PӴL1 ctlA;^J)L&Ǜk 5UUJ't:Aj$It:p\.ZÎ(`AE8VzodY~' f3v;-~V}nNZx<vh4Yohnhf=+:&Ji>v:
9G ȴ    IENDB`<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   width="16"
   height="16"
   id="svg2"
   version="1.1"
   inkscape:version="0.48.2 r9819"
   inkscape:export-filename="/home/mvriel/Dropbox/Projects/phpDocumentor/Template/responsive/img/icons/constant.png"
   inkscape:export-xdpi="90"
   inkscape:export-ydpi="90"
   sodipodi:docname="icon_template.svg">
  <defs
     id="defs4" />
  <sodipodi:namedview
     id="base"
     pagecolor="#ffffff"
     bordercolor="#666666"
     borderopacity="1.0"
     inkscape:pageopacity="0.0"
     inkscape:pageshadow="2"
     inkscape:zoom="38.375"
     inkscape:cx="8"
     inkscape:cy="8"
     inkscape:document-units="px"
     inkscape:current-layer="layer1"
     showgrid="true"
     inkscape:showpageshadow="false"
     inkscape:window-width="1440"
     inkscape:window-height="846"
     inkscape:window-x="0"
     inkscape:window-y="0"
     inkscape:window-maximized="1">
    <inkscape:grid
       type="xygrid"
       id="grid2990"
       empspacing="5"
       visible="true"
       enabled="true"
       snapvisiblegridlinesonly="true" />
  </sodipodi:namedview>
  <metadata
     id="metadata7">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
        <dc:title></dc:title>
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <g
     inkscape:label="Layer 1"
     inkscape:groupmode="layer"
     id="layer1"
     transform="translate(0,-1036.3622)">
    <path
       style="stroke:none"
       d="m 0,1038.3622 10.909091,0 2.090909,6 -2.090909,6 -10.909091,0 z"
       id="rect3764"
       inkscape:connector-curvature="0"
       sodipodi:nodetypes="cccccc" />
    <path
       style="stroke:none"
       d="m 12,1038.3622 2,0 2,6 -2,6 -2,0 2,-6 z"
       id="rect3764-6"
       inkscape:connector-curvature="0"
       sodipodi:nodetypes="ccccccc" />
    <text
       xml:space="preserve"
       style="font-size:8.49677849px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans"
       x="1.2488016"
       y="1074.2206"
       id="text3785"
       sodipodi:linespacing="125%"
       transform="scale(1.0256589,0.974983)"><tspan
         sodipodi:role="line"
         id="tspan3787"
         x="1.2488016"
         y="1074.2206"
         style="font-weight:bold">Co</tspan></text>
  </g>
</svg>
PNG

   IHDR         a  
MiCCPPhotoshop ICC profile  xڝSwX>eVBl "#Y a@Ņ
VHUĂ
H(gAZU\8ܧ}zy&j 9R<:OHɽH g  yx~t?o  p.$P&W   "R .T  Sd
   ly|B"  I> ة آ  (G$@ `UR, @".Y2G vX@` B,  8 C L0ҿ_pH ˕͗K3w!lBa)f	"#HL  8?flŢko">! N_puk[ V h]3	Z
zy8@P<
%b0>3o~@z q@qanvRB1n#ǅ)4\,XP"MyRD!ɕ2	w ONl~Xv @~- g42y  @+ ͗  \L  D*AaD@$<B
AT:18\p`	Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut }c1fa\E`X&cX5V5cX7va$^lGXLXC%#W	1'"O%zxb:XF&!!%^'_H$ɒN
!%2IIkHH-S>iL&m O:ňL	$RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t	݃EЗkwHb(k{/LӗT02goUX**|:V~TUsU?yTU^V}FUP	թU6RwRPQ__cFHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ!{--?-jf~7zھbrup@,:m:u	6Qu>cy	Gm7046l18c̐ckihhI'&g5x>fob4ek<abi2ۤĤ)͔kfѴt,ܬج9՜kaټEJ6ǖږ|MV>VyVV׬I\,mWlPW:˶vm))Sn1
9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/>B	Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$	=sl3Ttcܢ˞w<Y5Y|8? BP/OnM򄛅OEQJ<V8;}ChOFu3	OR+y#MVDެq-9Ri+0(Of++ym#slLѣRPL/+x[[xHHZ3f#|PظxY"E#Sw.1]Rdxi}h˲PXRUjyRҥC+W4nZcadUj[V*_pFWN_|ymJHnYJjAІ_mJtzjʹ5a5[̶6z]V&ֿw{;켵+xWkE}nݏb~ݸGwOŞ{{Ejtolܯ	mR6H:p囀oڛwpZ*A'ߦ|{PߙHy+:u-m=茣^G~1cu5W(=䂓dN?=ԙyLk]Q]gCϞ?tL_]p"b%K==G~pH[oeW<tM;js.]yn&%vw
L]zxem``Y	ӇGG#F#dΓ᧲~VysKXϿyr﫩:#y=}ǽ(@PcǧO>|/%ҟ3   bKGD      	pHYs        tIME&z;n7  IDAT8}Oh\UΛLf$iJ@Oc)PE4)hB.qeE((,?(DM6ЖhH$޻{\$.z79s8<}@p+HNո8Sᩱ[bv{iOqo}776jf;<S۾5\oˊAFs)r1nˉ7Ym3p@Q*#.{.~ʅnC'iyqO'̐d:AQA~Bׯ w?}XHfHGF##nlp{ Y3뻳{͕(u1QQD!Fn./5`pk Q(#h:3-G_>WϜ=!
"F"D1b!(PI>s"RWe=Q H\Q+h_ZX[΋fP=G@ Y3Wz8OMBLr4"Q༫7VfsKso[\#I̼X1ɻ"u+ձ'CuZ:-TA5Uj4⫞ol)齯&95^:3M`prJ2{W-f=F3%8<ZP)ϲȗ~b    IENDB`GIF89a   Zx➭s-҃h$Ç4,      7H`KPl\:pL)e9@\ "l:+PB ;         h     (                                    ǷZpGc6c6c6c6c6c6c6c6c6c6c6c6pGǷZpGc6c6c6c6c6c6c6c6c6c6c6c6c6c6pGnDЬӱѮΩŘ{}Xc6c6rIʡj?wPЬuNc6c6mCog;wPΨ˼\c6g}XЫƛ~c6c6c6c6lc6c6c6~YxQc6ƛ~c6c6c6c6c6lc6c6c6c6ɺf:ʻǜc6c6c6c6c6lc6c6c6c6Ьӱ\gүh<c6c6c6lc6c6c6c6׷]c6e9h<d7c6c6c6lc6c6c6d7غc6c6c6c6c6c6c6c6lc6c6j?׷h<c6c6c6c6c6c6c6c6ʺѭǛˣүkd7c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6c6i>ˣc6c6c6c6c6c6c6c6c6c6c6c6c6c6i>ėyc6c6c6c6c6c6c6pGc6c6c6c6c6c6tKic6c6c6c6c6c6pGǷZpGc6c6c6c6c6c6c6c6c6c6c6c6pGǷZ                                                            PNG

   IHDR         a   sBIT|d   	pHYs    B(x   tEXtSoftware www.inkscape.org<  IDAT8œN`hM .nMnewqg!%tjB <s&4<IsνgDI%pIfTyslS"i׻Dl[ UUEؐIu]kV4w^H<ϧ:#D˲N8~i,<5lI,6]P%aNqHcAgmm}1IW9zֿww*^19<    IENDB`GIF89a   𵵶ݺ         !   ,       EI8[s/f,^	W\߄xh%@[1	J 3@hHW" ;PNG

   IHDR         a   sBIT|d   	pHYs    B(x   tEXtSoftware www.inkscape.org<   IDAT8œA
0D!Gڭ
9BOra\
Bc@??$JRJgnd}+锂N^ι_*>@kxZ'@1FR4[9C|lm<pWco 5H_Z_/Vo\ cez&    IENDB`PNG

   IHDR         a  
MiCCPPhotoshop ICC profile  xڝSwX>eVBl "#Y a@Ņ
VHUĂ
H(gAZU\8ܧ}zy&j 9R<:OHɽH g  yx~t?o  p.$P&W   "R .T  Sd
   ly|B"  I> ة آ  (G$@ `UR, @".Y2G vX@` B,  8 C L0ҿ_pH ˕͗K3w!lBa)f	"#HL  8?flŢko">! N_puk[ V h]3	Z
zy8@P<
%b0>3o~@z q@qanvRB1n#ǅ)4\,XP"MyRD!ɕ2	w ONl~Xv @~- g42y  @+ ͗  \L  D*AaD@$<B
AT:18\p`	Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut }c1fa\E`X&cX5V5cX7va$^lGXLXC%#W	1'"O%zxb:XF&!!%^'_H$ɒN
!%2IIkHH-S>iL&m O:ňL	$RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t	݃EЗkwHb(k{/LӗT02goUX**|:V~TUsU?yTU^V}FUP	թU6RwRPQ__cFHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ!{--?-jf~7zھbrup@,:m:u	6Qu>cy	Gm7046l18c̐ckihhI'&g5x>fob4ek<abi2ۤĤ)͔kfѴt,ܬج9՜kaټEJ6ǖږ|MV>VyVV׬I\,mWlPW:˶vm))Sn1
9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/>B	Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$	=sl3Ttcܢ˞w<Y5Y|8? BP/OnM򄛅OEQJ<V8;}ChOFu3	OR+y#MVDެq-9Ri+0(Of++ym#slLѣRPL/+x[[xHHZ3f#|PظxY"E#Sw.1]Rdxi}h˲PXRUjyRҥC+W4nZcadUj[V*_pFWN_|ymJHnYJjAІ_mJtzjʹ5a5[̶6z]V&ֿw{;켵+xWkE}nݏb~ݸGwOŞ{{Ejtolܯ	mR6H:p囀oڛwpZ*A'ߦ|{PߙHy+:u-m=茣^G~1cu5W(=䂓dN?=ԙyLk]Q]gCϞ?tL_]p"b%K==G~pH[oeW<tM;js.]yn&%vw
L]zxem``Y	ӇGG#F#dΓ᧲~VysKXϿyr﫩:#y=}ǽ(@PcǧO>|/%ҟ3   bKGD      	pHYs        tIME&P  IDAT8}kG3{ssosMjBRTP[Zčv#bݸu!..tU V;7I͇Ixg9]܏.ss0f}	^}5_\>r򞝚XXK۩_>x]߇*;3ڊRiqw޻pqu?=?S6é|>yb[	zWb8DE^gnN G?|bDu؊V\cخ =izYs!"FJl!F=et/ifD=5A !L͡=i;;rT#Ah )	w7bZ&.+݂@nkjFkRCiKn66-Iܟ	rKsK%QC+{yOTTg75+pACTQ3>D%O2&0SOoXơFVoq=ʮҍƧ7~厙~>usqu_ј5Otu[\t|GۍsM~ԕ$HRk/I    IENDB`PNG

   IHDR         a   gAMA  7   tEXtSoftware Adobe ImageReadyqe<  IDATxb?%  X@ĄPFd1U 6b] =@|o @,hzF%X
Iq0˟]~n/T pMSPadeOCV@R@㼰̹` ny*,c/? /ÿ_@WGJKVQ)U `h	tO&o00#ßL|zpb  "<3Ue8s)X~ABW 3@WL%^4ÙKOL4|G88a1@L !&ZB>õo4ϯ `</~f0Q`Ã~`#3>6 f7|`O}`0Vegа^m??^z fVW&зafx`͠ӧ7oJ %w- ,$geȫ!aa>ßw| 3>|t̵+Ϟ=_ K wٽ[F"|,Woo޸y9D3<)z^ͻ@LTf b4; -)oyp    IENDB`PNG

   IHDR         a   sBIT|d   	pHYs    B(x   tEXtSoftware www.inkscape.org<   IDAT8œAj@E_'AA8	SA67pxҳ,A'&E>4TUSU$jSyށ[0;I1/8#ue/W`7Ƈi~Զ$)"
P|ߟKXH֒)$Z&T,8xTQk2a(
<*s߶9MӐeO=O|n9  <ogepVx&+]ӺS    IENDB`PNG

   IHDR         Ĵl;   	pHYs       
OiCCPPhotoshop ICC profile  xڝSgTS=BKKoR RB&*!	J!QEEȠQ,
!{kּ>H3Q5B.@
$p d!s# ~<<+" x M0B\t8K @zB @F&S  `cb P- `' { [!  eD h; VE X0 fK9 - 0IWfH    0Q) { `##x  FW<+*  x<$9E[-qWW.(I+6aa@.y24  x6_-"bbϫp@  t~,/;m%h^uf@ Wp~<<EJB[aW}g_Wl~<$2]GLϒ	bG"IbX*QqD2"B)%d,>5 j>{-]cK'Xt  o(hw?G% fIq  ^D$.Tʳ?  D*A,`6B$BB
dr`)B(Ͱ*`/@4Qhp.U=pa(	Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F; 2G1Q=C7Fdt1r=6Ыhڏ>C03l0.B8,	c˱"VcϱwE	6wB aAHXLXNH $4	7	Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![
b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGwǈg(gwLӋT071oUX**|
J&*/TުUUT^S}FU3S	ԖUPSSg;goT?~YYLOCQ_ cx,!ku5&|v*=9C3J3WRf?qtN	(~))4L1e\kXHQG6EYAJ'\'GgSSݧ
M=:.kDwn^Loy}/TmGX$<5qo</QC]@Caaᄑ<FFi\$mmƣ&&!&KMMRM);L;L֙͢5=12כ߷`ZxZ,eIZYnZ9YXUZ]F%ֻNNgðɶۮm}agbgŮ}}=Z~sr:V:ޚΜ?}/gX3)iSGggs󈋉K.>.ȽJtq]zۯ6iܟ4)Y3sCQ?0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz %gA[z|!?:eAAA!h쐭!ΑiP~aa~'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl{/]py.,:@LN8A*%w%
yg"/6шC\*NH*Mz쑼5y$3,幄'LLݛ:v m2=:1qB!Mggfvˬen/kY-
BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9<qy
+V<*mOW~&zMk^ʂkU
}]OX/Yߵa>(xoʿܔĹdff-[nڴVE/(ۻC<e;?TTTT6ݵan{4[>ɾUUMfeI?m]Nmq#׹=TR+Gw-6U#pDy	:v{vg/jBFS[b[O>zG4<YyJTiӓgό}~.`ۢ{cjotE;;\tWW:_mt<Oǻ\kz{f7y՞9=ݽzo~r'˻w'O_@AC݇?[jwGCˆ8>99?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-   gAMA  |Q    cHRM  z%        u0  `  :  o_F  IDATxԕLu<y?,=%0[МDY`nYV+[Y1q,Aiz(T;A{q`q24}~2D{Q2ܣb70U>E$Q^㥵u7Lw9;ޮY3"KY|   ;gڲH/XEm
v2^N%(B-sB>w}3Ύ0N; dH3)Amu=8TJR@umЬ'tLuG:_j n/B3S&/#) Rr252C
WOeV4ƺs$Dc'7C܎/!) ҖTt2'uۖN	U*Ǭ,byw$D:xlzja&"O`ܿHowAeb2ө"J'蜺;Vfsc$k:q\ik6ug CCH9/8m,gsBP%<N@+clտse	h?ܬjNAOD0D]9<nYU}9'0jE&0Bz	.Mto
'١T(Dg4+:wCE᷌:kE։"nV"~llC_v˒e7*؝B&0[SJ>hZ8q}r贵9\l2nv^;z>z
;3c2p+vcƨgQyͳNl0U_Yyr2~>IvĺdS's5=3  Qp\{    IENDB`PNG

   IHDR         a   sBIT|d   	pHYs    B(x   tEXtSoftware www.inkscape.org<   IDAT8œ=0?O*i)s 
"TU nH9Br4;y={S0tA>\XWWE+`\\a(QI\kǯC~H۶2i)1F4Z+Z1= c$IǲgǷ@euR(m0Ɛ;G 8W':~iߎg؜4ʳ7GΏ    IENDB`PNG

   IHDR           szz   	pHYs       
OiCCPPhotoshop ICC profile  xڝSgTS=BKKoR RB&*!	J!QEEȠQ,
!{kּ>H3Q5B.@
$p d!s# ~<<+" x M0B\t8K @zB @F&S  `cb P- `' { [!  eD h; VE X0 fK9 - 0IWfH    0Q) { `##x  FW<+*  x<$9E[-qWW.(I+6aa@.y24  x6_-"bbϫp@  t~,/;m%h^uf@ Wp~<<EJB[aW}g_Wl~<$2]GLϒ	bG"IbX*QqD2"B)%d,>5 j>{-]cK'Xt  o(hw?G% fIq  ^D$.Tʳ?  D*A,`6B$BB
dr`)B(Ͱ*`/@4Qhp.U=pa(	Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F; 2G1Q=C7Fdt1r=6Ыhڏ>C03l0.B8,	c˱"VcϱwE	6wB aAHXLXNH $4	7	Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![
b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGwǈg(gwLӋT071oUX**|
J&*/TުUUT^S}FU3S	ԖUPSSg;goT?~YYLOCQ_ cx,!ku5&|v*=9C3J3WRf?qtN	(~))4L1e\kXHQG6EYAJ'\'GgSSݧ
M=:.kDwn^Loy}/TmGX$<5qo</QC]@Caaᄑ<FFi\$mmƣ&&!&KMMRM);L;L֙͢5=12כ߷`ZxZ,eIZYnZ9YXUZ]F%ֻNNgðɶۮm}agbgŮ}}=Z~sr:V:ޚΜ?}/gX3)iSGggs󈋉K.>.ȽJtq]zۯ6iܟ4)Y3sCQ?0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz %gA[z|!?:eAAA!h쐭!ΑiP~aa~'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl{/]py.,:@LN8A*%w%
yg"/6шC\*NH*Mz쑼5y$3,幄'LLݛ:v m2=:1qB!Mggfvˬen/kY-
BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9<qy
+V<*mOW~&zMk^ʂkU
}]OX/Yߵa>(xoʿܔĹdff-[nڴVE/(ۻC<e;?TTTT6ݵan{4[>ɾUUMfeI?m]Nmq#׹=TR+Gw-6U#pDy	:v{vg/jBFS[b[O>zG4<YyJTiӓgό}~.`ۢ{cjotE;;\tWW:_mt<Oǻ\kz{f7y՞9=ݽzo~r'˻w'O_@AC݇?[jwGCˆ8>99?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3-   gAMA  |Q    cHRM  z%        u0  `  :  o_F  IDATx̗mlE{Σ/^/GE[
	F(񃆐cŨQD>Q%& Q	Fmy	+zngٖQqg?B),"Z7nzܟS`"!Q&hlml >(IJ;MO֚@h潮"Y+0BIRa$ 0]1"M.#(	JP*yom29C C-Oh@wa( 2؀YeD0>dB[y ͠aáHVr8ㅰbb9԰^Bo5D>7^i>5*&?eؐ*94tӡKK	TυxB}fVzv;*)@P=8Gfͪ ~\]KjJ5>r
[MLcB8Ƣ۶-\6@BqrlYb\킜|E)p; 7-567";>22a(N̊gtVa;tm"}YsY\/w)԰$>ıG	ijϊGVSMy`	J~̧ŷmԀgwx4iQͿ@B$͑1H%,:?g[Ntx yyلC9+;г_)#Jy3e%s'ct*d9.]
S3{9W``};:>Ƭy.AvM5lq<?YC7㤝E7k61x}=uDrXd#Es#arl%.4]/
ӯSqs_IeW[ RESYN2ByT"t\ZgIu1oq#鸑`4LR5.:JIvInJ&n(
{ 2)4M|n=%ӆR}0HɸqoDZTfT
0zgeAKK2!F80=̈́ZGM0\")S({0%J)&˃iԕ_!4Q<.X5LXZ1OK։)SHÆ$۾㦝 vvf    IENDB`PNG

   IHDR         c,   IDATx Ez	ۯ$n	h<("N#Ũ@W/*.J@G_k"y%8Y,V 'K|nT8ZqdiU&vU'PY1=&
U#U݊QCM*n=fג}*    IENDB`          h     (                                    888       r                                 r          B4a)Ak(Bt-I{)Du.J}'D|*G.H'@n(?k4`.R   +Ae7d(U#@u9m/M+J9X3T'G9Y8V6f+Cr"8c+Ak/U!8a9R0a'ENgJ`&Cw-Fx6P3\"C%8[)Ao$>k6S2S7\3U1S1M!9f8g/P.S%>l3MymwPX.M8ZsH[<]7YP^Y\'Ao(>g0U*L0Y7e0N9Vv *`.K$?p!9d)I/P2\2Kx8W7Xr{)7m3R8Q~(?g!2R/Q*?h8Q|0MNZ8S=V(?h&8X3V)Cl5Ox>[!3cUfp8U*Fq+Bi$6X0Cb5Ov=UOiFd1@jC`Ok9Qy*Em+?]1Ea6QuD_=X~iLkMkMkIk`|GbA[>X8Lh(?a>UvEbHaQnztId;V|Li>Uv4IjF[}KdJdNjLgUsRm;a:aQmHiPkLfCZ~JdBUw   .D]ToRnLgOmSm[x[xNm\yPlKeNg?Vv   / #%*0KcG[IdGaD\PgOgNgG`LeJcF\#&+1                                                            PNG

   IHDR        :   PLTE333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333gT   +tRNS /_?MOo	ثKHuÓ'*zǽ̎s   IDATx^흉r8h_fMp+̹J`pjt**qo
}H)B~uY-o2Jl!aOpŷVcqJH R`f(WQY&)A^ 蜫/dկqX+bF cOS!paTUJwpIdt;f X^d|M/ LUZk!k[s#v[n'//j3Ǡw_	_/UOT=S^QooR;U|*Ug i[YsTfgXq}ہx?]R5j*IrH;z]Xȕ~(O+AEjSJ ۿ͈@DZTTHUBGHl;??_v8
ށdg(_S@RXcx}Ș{<HWM[#pt0BըR >vˎ+N5=ƥM^{sgcq#<g}ܟ-T}ڇ|Wށ#pFKT=5xxt*TxwtzU>ϖsw*͖S}Tɒ+6L1ogl~ryenc e`5u9!C0T
5j\]r.q_9p*߅hSm%a%T-JS>pʿO*)<$TerXK]ՕSgBv!miGzkdͫKJX |7ˑj:q36kqt8GՒ
2NSϹNeȽk[1_y T9NFKqpίňjQ `(TDʤ4D\-/-	6~T=Vy*	AJFFҤq!/b3C}@طf-5jמ)$'@ހc|*䠯z@Z+
>#)[~OcDq_ux;E5{3)/Ry!"_T=MZ* F Gf F8qo3a>8>NvʑF(4zQ}7T[~^i`>^CQF80KO\s%t5TUi:7Mq"@,\G y幞jã<([omխsk>*"Tg'@q,ƙ#\gْk̖:[uKWt l)%8UG W[߫JuV6TϻTUTӸuUG̾*귻28^_uu1U1U.|'K<CU"G-y?&馳1p	QfQ/r=OMW3Vj(HY7Ow1_&riOR}ΕQP+ڟ VbiqS"z88Q#1K6w%TAvMA=ob7HNXZG	}H,1U/ҁu R'E'JF>H!ʋ,ozj^TS)I9gG=]k#|Du֩z5pru7(f?<-#e՚zW߉EYE1m2oӳrgʸҚOv*VlS=YlP$!<.QM@OU>g6K PVlɬԷ>["vm0	?>=Vhoٱnw!̰heK\@ҧKO<7z\Sgρ8mTR?7 mkޅ5m UۄPz?Sݩ|ϓCWY]]]]]]]]]]]]]]]]]]]m]n_C{.[THR#k0]bF>RˇZ~d@=xd~S0@RvZA4-SO.a*U֠$910v{Oȥo%9+f.@@AN3<0X~WT.o|p}0v}'~Tac1Zv^Lgu|K	?Gj1',UU_dTalL]~:C=CP4J`°Qݠ2	& nz&C  DuJۻTa*ŧPe26T0}Q' PD[Ne@:|*Ws|q]irQZ#pcZ.俩H"?:xIpU[
5ӈjLqSIPig*O{U׿W
=[`O7|Z|9%):d+'Bl=EZnziՐlʺ^-0O+-\[|^Oi˷-oyoɾD%]dxg.z|f=>*8mq~_e2ɛ25]A5:"#Jyp>X=4+~"4VR?C0<.ޢj@tK/ٶM5zyDs7yKYFkݏAW%#Z$zjqkosEDB:HoiM39_, tt#Ύ޲6b=O;sG9Mu|qXO\ԍ|6yDG>G/"Pn?bO3v~1G{UT'W(|؃X+='Um*e`"N+U %JqDlߌ瓳T!>Syc%q oa/IB~ZxWJ<RTyQ>ydFGj5fKlz+.
bUoU͇	9 Hqx˳Ϛ-}IW6H/J|ڜ ]^+kF ]=}N	48E5r2ryVSe]oD/E8T3E
&./g믿ַo|>ɭ?l2 :cE0?EA kA쬣fsy??'u`D!h?*bƅQ,UmxO)zk{71LY&/7:rJt!PPC|39  \YRea7r7ztyj}}sGy*{e]d o}fX \3Uj{^`)z/7^V 9.$ `, LIu0SeM{xFydQ=JnߴJ&zLot*&Yli%r*;ݢ)K5,U%{Lut)z|d?[QAF8g4 vXQA5.
{>LK9iDʥuG TngKȴg")is յ[o& ~ZS(DMʀ*i+ʔ `\; s敍eh+k!~ J.l<mJؔ0aJQ-xeeyT)"1
d$]|*h]N}Uծ*Tu
rKXh9s9ʳ=j_=h&y͈t)Wq^t{KVegʷ:TwՇ^g    IENDB`GIF89a      ,       >Aqy[|I(J)(^]Cax4!\Q  ;PNG

   IHDR           szz   tEXtSoftware Adobe ImageReadyqe<  wIDATXŖ{PUj:VDQ:IiS6854MJ!M "7@4P,yInˮEV	.+ {ݥEL^><1lq KZS<:mgqw
^~N1S Y{qW2ݨ;bYП%J%P݋׭2D2c*D[OoSsܒ(]{[.p~!Lp,c%̱9ow^
0\\G?!v<ci*_=Oʮ^dc \<9YM?	wuu"4+93BZԄ?j|x'KDF2!1,_̰8C ]M	:Fn3>8=j V~C9@UT\9.`1E&3P28`=n;XxBABNLB^HpOHj
6(b84H1oʢ+*&/Xv6:Ƣ)s]_,`4TVGo&_6%Y]Ah!f"=5bp,8=\ScOИ`11bU	G\þXBu%Aq5S.̩AL+Bjؚ۫{~E8M9GlEne'"UPf0[o #W{#ofP+"2JYS/_׉j7}ZH-@Hc25q2>R,y:4a	u'Zw'),z+WPTݮY)Y_>[t܂/?uz)2ڐxDTU0N-kHJ`MST=߀}(W4Wu*].źLO5+N\&(+ Մ!R¦>Gz$o29Ppꚅ1r%\O,;m37lxЅtV܇fp٣P\KMEh`&VB#//kreYƶ>T]xBR(O˸uUYn%u)dG
Gv^5Gv y	=bc'%C]ۂGoaޔ(cy*)mnFӌiƚP9?c4Ӗr-IBu?Ks'
O dX!=p0זoj?p)z%&֏00a{Mϰ/% 9>/_    IENDB`PNG

   IHDR         ;0   tEXtSoftware Adobe ImageReadyqe<  diTXtXML:com.adobe.xmp     <?xpacket begin="﻿" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.0-c060 61.134777, 2010/02/12-17:32:00        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmpMM:OriginalDocumentID="xmp.did:3F186DBFEB7BE01180DEBC3D1F6633B1" xmpMM:DocumentID="xmp.did:8FE521A7F35411E0A81FA4AF0F59BF4A" xmpMM:InstanceID="xmp.iid:8FE521A6F35411E0A81FA4AF0F59BF4A" xmp:CreatorTool="Adobe Photoshop CS5 Windows"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:817901DA62DDE011A7A1986CEF352AD3" stRef:documentID="xmp.did:3F186DBFEB7BE01180DEBC3D1F6633B1"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>T  IDATxW]
0^&C`[{l{u-ڴn!K.p̲3T  M+I^m[rUb3)GjGC!~JĦoɉK7[[AGq׆jczi$Xh3qXIafbt\feNMtfM"u>XyR1Ub !!PgKWi(qQsĵ%!Ֆr%I@}cٽ ,>-    IENDB`PNG

   IHDR         ;0   tEXtSoftware Adobe ImageReadyqe<  diTXtXML:com.adobe.xmp     <?xpacket begin="﻿" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.0-c060 61.134777, 2010/02/12-17:32:00        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmpMM:OriginalDocumentID="xmp.did:3F186DBFEB7BE01180DEBC3D1F6633B1" xmpMM:DocumentID="xmp.did:A78832A1F35411E0A4B4CD5BA28F5129" xmpMM:InstanceID="xmp.iid:A78832A0F35411E0A4B4CD5BA28F5129" xmp:CreatorTool="Adobe Photoshop CS5 Windows"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:67358F0068E0E011A127D534A854555F" stRef:documentID="xmp.did:3F186DBFEB7BE01180DEBC3D1F6633B1"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>'5r  IDATxڼJ@ȩPBO>'oP
PT]KWAxJB^^+82&qevgdv6^i匇hb֠GY4mpS9^*AO*i1oʂ	
4 5I%\N)W2/-O :=1\+OY+Ǣ&f6ŏH0憹DWgϲKخ̿7
$uطm00_TcP m|_J㴐'@x]:ϕ+y2K⹂Kb\+õy1p?fTC ri|&->}p!ZxTQYBpMYO\x`![X {V>L <f^`` 2 E9    IENDB`GIF89a      ,       9X,L}I(d*2\%RbJ!QH3	B
 ;PNG

   IHDR         ;0   tEXtSoftware Adobe ImageReadyqe<  diTXtXML:com.adobe.xmp     <?xpacket begin="﻿" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.0-c060 61.134777, 2010/02/12-17:32:00        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmpMM:OriginalDocumentID="xmp.did:3F186DBFEB7BE01180DEBC3D1F6633B1" xmpMM:DocumentID="xmp.did:A7D198C4F35411E0BFB9A953AE02CB2D" xmpMM:InstanceID="xmp.iid:A7D198C3F35411E0BFB9A953AE02CB2D" xmp:CreatorTool="Adobe Photoshop CS5 Windows"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:65358F0068E0E011A127D534A854555F" stRef:documentID="xmp.did:3F186DBFEB7BE01180DEBC3D1F6633B1"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>  IDATxڼJ@ȩPBO>'oP
P]KWAxJB^^+8lvv82ٙ/;ٝ]UѲ,sC4@1_@#_J@[A[KUd]Г 
c`,盒0]F6iDT=[_0
fۀ%]c)8 }vDS	w)6sQ>	uqh$s\OW瓈zkIy+	.{?/ 	xYIP6~+ɛմ_`s
ex؃.Zs,l\L9mϱ\"ǋc4(,~l%YȒ5/^ٔdCᵂ~#`|4]q0p=#{u]W 	YWy     IENDB`         h     (                                                                                                                                                                                                                                                                                                         			                                                                                                                                                                                                                                                                                                                                                                                  O            GIF89a      ,       Aڋ1 q=`xpz33屯?ut%iɝPXD3Ԫj ;         h     (                                                                                                                                                                                                                              !!!                                             			                                                                                                                                                                                                GIF89a      ,       $ڋ޼{
Hb&Ls ;PNG

   IHDR         ;0   tEXtSoftware Adobe ImageReadyqe<  diTXtXML:com.adobe.xmp     <?xpacket begin="﻿" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.0-c060 61.134777, 2010/02/12-17:32:00        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmpMM:OriginalDocumentID="xmp.did:3F186DBFEB7BE01180DEBC3D1F6633B1" xmpMM:DocumentID="xmp.did:2B07A5B1F35411E0A619C903323F0D99" xmpMM:InstanceID="xmp.iid:2B07A5B0F35411E0A619C903323F0D99" xmp:CreatorTool="Adobe Photoshop CS5 Windows"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:60802ED7F2DFE011B39A9A21C2CA722A" stRef:documentID="xmp.did:3F186DBFEB7BE01180DEBC3D1F6633B1"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>se   uIDATxb?@ &322RĘ1`>f!4mP3TvbUYhd`nO2jCb`Vb(ţӿE?:^G$  $S`    IENDB`PNG

   IHDR           szz   tEXtSoftware Adobe ImageReadyqe<  lIDATXŖPUBN5Ze9YdiB%MSGeqFAŔU	54aE*
.*A	ewYXXe w~Ve'<s=OzR0mkGʀi1H<t蹍6blE8P/%'q`~3bg37U>G|9˥T!Lg#b{ R/a	}w]Zc(RqzG3KCUTu <a_<{*}yi.n#2w0B1지se<DS]C']@yPZ́C>|D5և~d}q$<M4+1LbLyඅ-Cl5,ڏ$u]{bA5p]]F_#O&}XhH)pxՍǶ~NpBK=Oh>p&=C`TOϗnwN+S^cqD3Zӻpb744.6%4uHT!B/'d|NTYL D:"aqQ&k	5h&YMpV@Pb	Be.cx7]`\Y
N+ިE;k֕:ߟU@pr)G߆G[+|<!v/ ~v,FdB*'*QPii.*b`^%^@Rq B˛w<~
[!֒OOrgTp*(%}ZLqeAzdIQ׬_O7obJ,VгƯDܟ̮ĩ:G-f/*G_PX̖dĤIhl@3	(ݬB
DZ,,&EFAW\@1	_݁W,ʒvI]	'e5fGބ4 x
f=$%Z0SJOB MU-ryO=	wj"/Cҝ,{UK!ZEZyD>O)E#)$ E.,;)?:OyCN'@5CȠi8,/k^s$1seӜW7vJq$\-i@lkFܾ̒ķ=+\Tǥb'9#@N#d;͡wAZX|32Ьp+-mX|t_ՒKB5)i*8Dqo3{7:={)vuvo)&`y''%l<ϧ`)5    IENDB`PNG

   IHDR   H   H   UG   sRGB    bKGD      	pHYs        tIME &[    IDATxdy%U}YcU3C7 Q@DA@gDBfrFɍQsohLH0I'EP"BMj<y_~vZW߱GJIJAh<zo|<~ۦFP2e!R(]TFJ R$)'rJH29zl#*ENRLҒ!ň-)r$I#DQJ#u5BrJbMșL916
>>>z70젟7F_J)b()EL y[_ǟZ}th9rGf4i(DPJPZ66R
T".g b&% YWhqMSjd!)QhM| %ubĈ1k*#LQ8OMZ	ރ-ya;A]+SRʐRJZJY$wL_3ͯ30\۾d2!p)T9 @E&5~$@ƔPRS$@V2TE)Z\LQ|$61xTB"DP7jMi-s@60WY"1fƭmB!<O-ۏ޷oWb8jAR
Rʙ{k5k^~]w%k(B(ZӸ/)9FC#r'iR'H!@DA**"Dii	!c
K@xa-m"i)e*kZ1|C"EQә51&jۆ1a!I1ĳqkwo  f{j}4ݻm
h#
kAkY2LJH3Ɩ3*T)B"@H1c4R	R%A˂[rUHk[liZc&FGB,RL8҆9g1n68pp4³/<__mCf:d߽Ťl(pޣZ	AwbJHRSB	>)g$3Fi	2d F(ItsE+
rBK $h%PRsBhMPV`R D(ʂh$f-3(E4@*qӈ=[f9M@K>q;B	!Fa7(mB7Od2JvwHkRsT1]hZ-H9R@K,
wHYs6 LCʙ*=!$[Zr-5JI*R)&mCDFxK'mއ~
9-O=u+rｹmJ
ȈJ*j)#%kB13BrĐ0Z!B)H	DN()DJ)R~YJ#-RRmIN$ZIxנ;Gi5Z
)s1/J}hqS%RwsO
` %PG]JkbJ0Zc
ڶ%#h"c$1cD	-XL&HJ!@"'
A.PRpPJ g)Մqsw 8ByF!Fkn^lvfx3LӄJH)QR"  $Z|;AA H)@<D-Jibp P(;*"')Y@y:!1D@aFɌ'
k%&AH<Z+( 2)ʲB9P0){"㏚9Ԣ)$
Zu;kG)"|RhL[Ȝ9DIm,"% C$DGhk0M:BtJ+lh[RJ!&9ՄAR@dROpVHN z-./f40cܸ9y'./mf91p0UEǈ)Kb]#[D$P4!:sѽr쉏'ñ'=mPY:(=?{`Q;8z	CueA5B"$$ }P2uX,J(\QŨlWZl7[ 28gT(!HA*M"1hB$#> x961}/yݻ97ߒ)'lc?_7&U#ʲGD D	MpA"@)$	r7w\)aB5IҴјG\LY$׀Iv ̸nYyQ<ZiN؁ĤgWcIt!#y_\I{"e;L!`a C!j s}	=qջ38(rJx	)	)bp@iM8&Q%AUƭctRR).5 [^) zJcdqeA5)ѸIw@_(RF	֛y^4ܐ@THi@cD!4Je]%9RV\pg;O4["&rBkK4!Q[4.2i=I!I)R B-3}4Ԯ%+-,yV*
V-q)8p`?>)7yY#{znFGPOY~tlޱ
{"G|:Gx*v!9%]ŗÞoSND
Pd1.0 cdSI2n>YktǷ?_ +pkc^U0(K2ZRuad~v@LZJ|H1Vo~	99b{C)T&Ye'l߁D? Wrǣ9'pSǒ"g9ބq:Rqv00h hT
#LH1|mYQƐW-;!Bkn?o2Ul1h'H	YaJ{f|oKxs/?Ws !=9:|O^EٌEA9&#u['Dy1#c7+`.\qduh{}J6#B(LO-d2yW
stf/}o_~yGVpgRLjRLR"Dx׶i[cakǞ	brd~s_'- 5&B@M" ֚"(I	P%N&,N9B$'@!IM3Yxҟ0h&/;x_dn`>Ĥi! Bc@_otkي~ԕ4ȁ?Oqhq~ZƵ<U"5(!H9(I[FHBbH@EAYBl)TBjzVSermGP7.~b}yEVɭG+CJIHx'R$Q3mq>G~ɨ4԰Y-7C:@H4H"M#%"'| D@@)~cu3ZH!3w<B(B(?+ᐃ@JBiw!ŌB*hquт!4()mGCdJx',/.}B_?y+>΂N>9@K2-KPin\b
U,k
JcJSCi4(Ƭ'ޓõ-!<wGdCFuKʙQVm5qʉX\ZǃWxG9#І,TɄ#geyulOo~-"\zfrL(2ZֆH*GRN4m> Ĕ8uI9!P#JRma,5o?; 7}8D=@ם4Y
ɏ~C&qdb	rWn5d{7mSBlB΄򬦍ƵV3ojn@
(ЉgYYZ*
\4ށ!!0iZ*R2s
} YJR@gD:LTJsJ
i['<M[*r@b{Pp~)$H	mh!w
e yu?KJVcNoxŕw=r?R@+ȵ}+G(9Mi\dBm;:"@DBXSt)b!okں&	RS)ɠ71H8IMKΉ#z	Lݳ[~gy}3w|K|CKrJV|_hopcNynVO&L	{)#rͥ|z7޷>t!4-*1ni ={t:@*:"y/}vT"{d abR)Excy*/{եq_KnZ1g=?췸.y,GQNoXF쾃;n2g>"|է7s{nga\ǯ\Crs=kslIϸ(J3)D&ǅ@B|Ke;<fi:CV)Nj.}}
+V4uVG\sѥ/dw^ɮǟ3^JθY|>N3N.|1_oykIg^{=OpK_o~zvzǝz4?2w3`Vb4k!}s -t-t^NLG">vAʉ``m'5Y!E")I̹9J*#ؓE(^۾'!#${6m}O:x?s?yۏ_j~318&y''^%_$GO8_yeu.vlJ!o;և* zNx1l8	:q?eȂD"N{$b;h|Fwʿ2N1&QF</%/|ѡh&$Ȝ(XY.ㄓQFLGo.qʹp5`q߃O~b)Zsۄ.oь7~Ĉ"Sh`b*N>a"&J[|՘:{Ik ~fJߺg(E
[XcJQ%QF+Kƫvι0F|;)+CiBb_̖m:O;k![gq^!MZ[lGcX|d|zVN{x\%q)8pwB#ǈYN94+2FfzE9S!Oe*Ԥܙ~i.(eZȸqI{I"W#c#rcݷeo|; 0w~//|<<tX=ǩO~&xorK_=<||cnf~s߶PGGaRORjhh\TvDNyi<rͳ)"$ EwJu	V	jBk!fimCn fzJ̝ZffJyG>)OBJ+}K{7/JyغDr ゗;zlnO˞X;Wz7W71=3epEh&+Aaǉ'1dqu.8Ў9S;O;(DΑ	@
:Yp,CA7FHAΎӟ$>W#<ocyߣڏb+)O9ߗ~n5d)9X=po]9/2җc_-m8B#qM9"Hz
AB@;S,k TJ)"s@BKHc6C@89#	ΑrbϼmqcZo N98.юVЫe>a)qv.ghMaN|y\+~OZ@23`ԓqK~a߃YVB	z/,QXAzl^I-:B	R2ZNQRQYFu.JAZeI!$>~ufs7R"#'u6v @͑f?~J
^7ir&H'=|((#2x
cm(Z "DDYLHh[b)c ؑbY D/Jv[0mXOpށE a&Db&%jDyMs_?A
dEUs;}/2'y#r79urvJ ?WlBFGD$L
/cp&4xDLt)r֏RqbbB"EhЦLBN	KAeN/s-,JTSX463#wϯ+|7UJn؇C\ku>9BaS@UdA=|33CیA$:mo\[\?(Qƒ|DKE	
]"ĀPk%:I%)Q
I(Buϑ},;oYش@L3;'UՌ_b>g?Gwdu|?rhaw)?YAA!5U<t=ﲲNbdƨ&bg1yZغ0@	AtURcM2E9u
QRe7ɕ,wn}۲.*)˲歷S=/z"?Vףti{VÃ|󪫹.ɲ^oxGwr?rNyR27~jfLi4u	1щxv@6L=w[F*ll	јnFlm'oL(@V)hr
#U߅_QOBl6`.i	Rnشm 9KD\T%5m97_m']z)%7X=|]Ƌl?q<9hAC,
.wȐK^yQL3	>ۑs	|Щs}	A)2eUc OG9vyIy*ZDR\$}kHD&ĄxO+(C"xLqPY9E/`ߏlu""˯A5ЌϸLgL..Җzx/C{A/sC:FuC:$%@EJmBYCk1MY)"%<.*WY?1޹aeoCnU(-q!Zɑt8ECn[Dj;+0cyl=D-ONэb"UX"0.2jyJMoB mo&QĔZT Y^]cc4n) uZ°yu|hMm]FT%A56'P.қHo~+uџ)BB]Л,lUH&b7ppk>ϿUl4S.i[Yɦ?*8,T#9E6_Pԙ7	,(2RDwsEɜVq0C: Q46PU~ppɗp^!KIRXHKH1".OSL2ҳ_7N@!K^\EOoHkcBR䄋ih떐Xb0S.XݝKAY\]g=叺,񖍃  CIDATgL PMD][ɼl߲|=|OWegEL
̐w`1t-ui3:3ֵꖵk4EB~<V93Pqdi	@[3-hкv-c&:(UAe,"tdX7j`p<fݷ'K^͒tx"G$El8M{\@`Ȫb|}ӯ}%]G?.Ɛť#<DjkDΓàŃmJ\}*B̙pMO]Vњ(PNPsrŸ֚.^[VBjyRuMe4;ĝ}<L*L[я?S,(Z)҂qhGgO3߿۾}1nk8l1Z^Y^]E:Dꦥ4"+Ov?uq\6o28 M-e)1i't-2 lU[YD'o_ᳲUev$V3cbC殗1/%zXҊ`m?*f˂E èvɈL~ٱi6,/Lli 4PD]ϬW~0O~o~>ٵPhU<*B*djL&5묯(Y)[Yby8.Fb-2z(ƎV%Jt1pҸCz<	X_̧Uv5Kq"'뚞5L*cf23\_HZ|x(f2`u	1>If<c§HL%$Z.%ɄhLLPhؿ-c6+,EkDVV1Zd
^d5Q@pNa	qg<@*U 4׭L_$/FuL&5Zv)6DJI)ck^gbk:kos)ӄk,:TLÞX@0Ԉ+'$6mJFm~.B>NX-%ѵty _^dOǱ껅
&2
ѵ1UB<|N|%S/?<bs݇&9(˒>Fvl%5YkFiNB-2~yzyvsܖ+ׇ6٪WX$&dBH"_TZ|0Y(n	5ǝy2!d_I^}bߞGmLU=-0ҴZ(4>xw_2lwPa&zZ("ƄHBeZE1iPNzW$]T9#Fk(%-KeLգMu6/8t9|`g>3y<شs3OyKyڙ^thC04Z|Lxر1Y_mfNxx^^6PXDc\K>y/1;gYYYa8 S@
T	)MkW,%J5S3[koxiX7%6	] hI-
"oE
Kk6sޯ_Y<"f2׌V7xY;h(mdabqǱП/;7e:~}f$e4&C㽲N7ƍn=1g|ue$6(wXN]D 'ŀ +(!)2?3%^JUuw?7̇ɜrI;P:xH&Qƚje% 'AAdH< ZE}<v5b#!Rk-Č]n}4bP(KH].7i1R wb\H2^Ea-JJfҟuffgӯ
,rH}3O?I++OFKd_#r #""YC/\ǃ߿z BeD&ҌGH)3jZ$L;kkz=FVBH^Id5:̍
ꎽk-(fmmsmsn4dvvAFx̊[P5§_ܱm蓎zAV(	yH2K{axYMX_eꡧ}ٔBv
ck,1wף4J@چ~?F\6޻,vYH:шم4^B(;c`hk̈́\,..#)ھ?z쿹.LMFsRea`0ZP-VD7dߒP˰N*mqӚ[XmpS='[T9-Y
|&&
 |LI4Mh<_voLjF1fgJI)&MjX-A27G}fL`ccmkV7Ơ5m`FQ'歏Z$ia212iHShaz.ZDΓ61Jk+-JHV&oJZ67*d2!T]IzUڻY	mh<]5eƱ*Dq=ѐdR7c6-LF U{~+deҴӸ$dRܹTuycr6>rRd[,8p ᐹ[iZZ'c(C3vkϳtm-R()A)|sוJuo^P@5	87h"k&;jژ Lf81RRUYdd<HR@[ĔXN	AȦ-lH`<weLOuߗldҰ]?QγA cμ-[)O_p>0i[RJx6HH-pm	CmK-X&{1Uŕ2ӦDLISsI
"Rk\yҸ<(xhqVa`({|5:L-дLQ`i&Q0OȺ{2ts4j)&BȘp!D:(&LRag!@j" 
{Rc$.x"]'	Ҳ6%%J*N)Y|ćX7wR/n_:jtUE̩;VU!zUEhkfiۖdvn%VftUU[GbA\?GB 	n{NDa	?mWS=s0)5#ijs;OBiR.)1R^G?Q/lH3ǀfO;E_'9(z!%jβ1`1*-).(Fc;GQ&D@!8WNe%uHc-$YJ\E{GL6xԽaccDl~$(s;IoOw2+F{	.!0lt.vr*Tｲ
I{ӍR0mV5bHqk%fJ|PTsEm
7!Zj{Vj]/֎(
Τn[UTv[YqжxP=5z0xz!| *z*@SPwyUrhZfy89,)Ke,'B	DDƨ8X-N/psx
|Ϋ@G[/|<XTβc+5+L\)#X9-D';TJo&, tExA+N<,zK呾S84L#Ǧa^81ړJt_~O/Q@}ó"wEX/x٬8G4͒f\.::U˲wl%<gsn=y6e,iUq-
zM;eI۶?1#1EW6o<vcpf0Gwt5?{-p 7:AJMTN&IT$QѨPA_#DBTQ#^BlΝ(:!%t}Qy?}@dzdBDv"\ρcHwӾ8㽌vIL#pI富"սs+7"u~yѧ!'$    IENDB`GIF89a\ \   z\yӗߴ      !NETSCAPE2.0   !"Created with Chimply.com" !	
  ,    \ \  h0I8ͻ`h	dih)VCp<<imKD<@F4z/lcrJX6O-BZB6&`Xv}4p6<ܨx9h{3b~mwq/t{~xruoilf`c]WZ^Nv;MPSLdz}UD+х$

n@0#J^C)jh7vdH#I3y;%#Ԙf>3ԴPfNx&h;piSiK0RjH$|Ϣ:vJS,R(
E;G{O.rޭw߿ È+@Ǉ;Lyd3YsE)se?E.m2Ꜫn	6jܿw[6p'xʗM3S;; SÆn|+7|7_Ya7`Z}6l j܁mg g
Wjȡa(A !	
  ,    \ \  h0I8ͻ`(8hCIp,s,U|PhO:a#.\6è47VXvz}lLF@is%_zN`y{s~mpjdga[^XR_r|kuve]yLPn;OGVFJNSY-t.17Ák0 
\0Zb;YdWōc=ܘ.䭏MA	Q%]I84kޤkHA t
M=tիXj
ׯ`Êݺ@ٳ_X˶۷n;Vܻxʥ˷ڼKoD5 Ἁ-f<㻑	N|巙n\g&d@ӘS~ڬgzegtP4n6"j6򓣗7?|et?Wywg*_8K[nk?~uY~ٷA5P/~_k!VM[ `T݀iY (S	  !	
  ,    \ \  h0I8ͻ`(di%lVE,ϴL8=<0UaMId6:#PʴYv>2ꍁѫqS=?te~lm}p|^hAfXwxkmnvDu8{aK~(H$ײW3T_ݴHM>YHp"C],~)Hlɖ^I͛8ɳϟ@sJ H*]tiP*hJ*jʵVQ<jR^Ӧ+6,YfѪA[Se@ w[UߵvK0j+jUÐJse3wy,ϠJ4 Ϩ^]런ccݺtnԻWsp'|<sr7<ptW{]ovvox<ʱS+`>m'-O}'e7PxlX~ `di=%N9eF  !	
  ,    \ \  h0I8ͻ`(diYl+l[=sӕ'\"l42ISyFSdl?0歹xpWjsdn9sl:oun=kztv|{r2xC@~-) ºǾ̹̩ҨɧpG `COa=Nb:,8O_@{ZӸc;yeJ &Lh59xY}*t(ϢH*]Z,ӧPJʴԫX6ׯ`J*h>۷p@(K7ִxܺdͻa >;Ç**1J,e3z֜tgƨA^=kӰcn@ۯZs7ۧu}uW7/ut9W|=s-w]q#~~pzw̻u}?]+jfb }_eb&(V*>UՆvᇲ$  !	
  ,    \ \  h0I8ͻ`xudhi+pγWpHC:NrijFkB:	x꒬B6=5su~@9]5yb|} p{x}ZztWQOlwsejuRn;ƾͬ50*ڽSo
:0&h0D :)te1=Kkɓ+42̕(IXC9[|ϋE;x/KMA<*b*իXjʵWKد̪]`۷pm]m߿N{p޽B̘1v'۷e!<˖3k.˹3ʠGցiʟSמVҸQK7(^Ùvn飩O.f퉹<btlW˾[5h1ր}f ( x~gAڀާ ($  !	
  ,    \ \  h0IͻXdi}la*Ѽ+lېh!GaJZU:`kV;{v=ҰzLNϜnwN\yh{|b~w X%orSuypgv]|mPsdIkGBUZAaM@} WF8K5ӿ޽x^ 
H0?z*<8OÁ=(0G(>x9^2Ha$K<ʕ:ztR KQ4k*N|JKK24cʥHUL|ȩ%^R!X#úS8ʝKݻx˷L+6ǐ#Gfƒ3Kue˘5&٩ϋC\ԩ!i؅Uφ\kܹe,ou']q䁕9t黩lA|Qɏ64?f/=lv>z|4E`}VAП 8~هAQH?؇ ($h]	  !	
  ,    \ \  h0I8ͻ`&di蹀l9B,t-7i0PM:o4\OgqZ[,1*-h`c%8xN/9pzj}1m%L|4Ty}ztwqknhbe_Y\VOSKuHP<ǍʐvͿJCRiGWF.~
͊"/{ 
H*\XpÇ#Jċ+FBIR$?\I$J*Yt2F3'ԼgI;!9hPC4z4RASO5RkN	G#zeؕeSTZTgXk.ub\i9IǆuLÈ+^̸ǐ#K쀀˘3g\Ag-@Ϩ-Mi
S;ؠ%n]6ͺ{~
S_-nϿJh<dS'mw_ޒ|gm~4z箧~{mk~7*G\h\	oBp݃qffv	  !	
  ,    \ \  h0I8`(]Bl6e,`xPTur(ϱ
TjLZz.-hzm"w+L6yzW|}$zswqnh}e_t\VkRUbfTr!GKY]{uHv7JNxƾcհBǿ
')Z4  
ȏ!Jŋ3f7qbE 5rcȓFLh%H+t_L3i^y3`N)mS'ϡ<TKCSI7SKH)> *lX ^;p,Y\WmRo-%9ٰ#E`;Na1ǐ#KL˘3kPϠ=SMҨ-N=auӮMW6ζo-5oܾwnÍ׽ǖ:9s	У78vW[w{㹗Wgy_wg<0~푗iWz֠l ~6ev ($  ;/*
 * iviewer Widget for jQuery UI
 * https://github.com/can3p/iviewer
 *
 * Copyright (c) 2009 - 2012 Dmitry Petrov
 * Dual licensed under the MIT and GPL licenses.
 *  - http://www.opensource.org/licenses/mit-license.php
 *  - http://www.gnu.org/copyleft/gpl.html
 *
 * Author: Dmitry Petrov
 * Version: 0.7
 */
(function($,undefined){var mouseEvents={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup"};function makeMouseEvent(event){var touch=event.originalEvent.changedTouches[0];return $.extend(event,{type:mouseEvents[event.type],which:1,pageX:touch.pageX,pageY:touch.pageY,screenX:touch.screenX,screenY:touch.screenY,clientX:touch.clientX,clientY:touch.clientY,isTouchEvent:true})}var mouseProto=$.ui.mouse.prototype,_mouseInit=$.ui.mouse.prototype._mouseInit;mouseProto._mouseInit=function(){var self=
this;self._touchActive=false;this.element.bind("touchstart."+this.widgetName,function(event){self._touchActive=true;return self._mouseDown(makeMouseEvent(event))});var self=this;this._mouseMoveDelegate=function(event){if(self._touchActive)return self._mouseMove(makeMouseEvent(event))};this._mouseUpDelegate=function(event){if(self._touchActive){self._touchActive=false;return self._mouseUp(makeMouseEvent(event))}};$(document).bind("touchmove."+this.widgetName,this._mouseMoveDelegate).bind("touchend."+
this.widgetName,this._mouseUpDelegate);_mouseInit.apply(this)};var setter=function(setter,getter){return function(val){if(arguments.length===0)return getter.apply(this);else setter.apply(this,arguments)}};var ieTransforms={"0":{marginLeft:0,marginTop:0,filter:'progid:DXImageTransform.Microsoft.Matrix(M11=1, M12=0, M21=0, M22=1, SizingMethod="auto expand")'},"90":{marginLeft:-1,marginTop:1,filter:'progid:DXImageTransform.Microsoft.Matrix(M11=0, M12=-1, M21=1, M22=0, SizingMethod="auto expand")'},"180":{marginLeft:0,
marginTop:0,filter:'progid:DXImageTransform.Microsoft.Matrix(M11=-1, M12=0, M21=0, M22=-1, SizingMethod="auto expand")'},"270":{marginLeft:-1,marginTop:1,filter:'progid:DXImageTransform.Microsoft.Matrix(M11=0, M12=1, M21=-1, M22=0, SizingMethod="auto expand")'}},useIeTransforms=jQuery.browser.msie&&parseInt(jQuery.browser.version,10)<=8;$.widget("ui.iviewer",$.ui.mouse,{widgetEventPrefix:"iviewer",options:{zoom:"fit",zoom_base:100,zoom_max:800,zoom_min:25,zoom_delta:1.4,zoom_animation:true,ui_disabled:false,
update_on_resize:true,onZoom:jQuery.noop,onAfterZoom:jQuery.noop,onStartDrag:jQuery.noop,onDrag:jQuery.noop,onStopDrag:jQuery.noop,onMouseMove:jQuery.noop,onClick:jQuery.noop,onStartLoad:null,onFinishLoad:null},_create:function(){var me=this;this.dx=0;this.dy=0;this.img_object={};this.zoom_object={};this._angle=0;this.current_zoom=this.options.zoom;if(this.options.src===null)return;this.container=this.element;this._updateContainerInfo();this.container.css("overflow","hidden");if(this.options.update_on_resize==
true)$(window).resize(function(){me._updateContainerInfo()});this.img_object=new $.ui.iviewer.ImageObject(this.options.zoom_animation);this.img_object.object().click(function(e){return me._click(e)}).mousewheel(function(ev,delta){var zoom=delta>0?1:-1;me.zoom_by(zoom);return false}).prependTo(this.container);this.container.bind("mousemove",function(ev){me._handleMouseMove(ev)});this.loadImage(this.options.src);if(!this.options.ui_disabled)this.createui();this._mouseInit()},destroy:function(){this._mouseDestroy()},
_updateContainerInfo:function(){this.options.height=this.container.height();this.options.width=this.container.width()},loadImage:function(src){this.current_zoom=this.options.zoom;var me=this;this._trigger("onStartLoad",0,src);this.img_object.load(src,function(){me.container.addClass("iviewer_cursor");if(me.options.zoom=="fit")me.fit(true);else me.set_zoom(me.options.zoom,true);if(me.options.onFinishLoad)me._trigger("onFinishLoad",0,src)})},fit:function(skip_animation){var aspect_ratio=this.img_object.orig_width()/
this.img_object.orig_height();var window_ratio=this.options.width/this.options.height;var choose_left=aspect_ratio>window_ratio;var new_zoom=0;if(choose_left)new_zoom=this.options.width/this.img_object.orig_width()*100;else new_zoom=this.options.height/this.img_object.orig_height()*100;this.set_zoom(new_zoom,skip_animation)},center:function(){this.setCoords(-Math.round((this.img_object.display_width()-this.options.width)/2),-Math.round((this.img_object.display_height()-this.options.height)/2))},moveTo:function(x,
y){var dx=x-Math.round(this.options.width/2);var dy=y-Math.round(this.options.height/2);var new_x=this.img_object.x()-dx;var new_y=this.img_object.y()-dy;this.setCoords(new_x,new_y)},getContainerOffset:function(){return jQuery.extend({},this.container.offset())},setCoords:function(x,y){if(!this.img_object.loaded())return;var coords=this._correctCoords(x,y);this.img_object.x(coords.x);this.img_object.y(coords.y)},_correctCoords:function(x,y){x=parseInt(x,10);y=parseInt(y,10);if(y>0)y=0;if(x>0)x=0;
if(y+this.img_object.display_height()<this.options.height)y=this.options.height-this.img_object.display_height();if(x+this.img_object.display_width()<this.options.width)x=this.options.width-this.img_object.display_width();if(this.img_object.display_width()<=this.options.width)x=-(this.img_object.display_width()-this.options.width)/2;if(this.img_object.display_height()<=this.options.height)y=-(this.img_object.display_height()-this.options.height)/2;return{x:x,y:y}},containerToImage:function(x,y){var coords=
{x:x-this.img_object.x(),y:y-this.img_object.y()};coords=this.img_object.toOriginalCoords(coords);return{x:util.descaleValue(coords.x,this.current_zoom),y:util.descaleValue(coords.y,this.current_zoom)}},imageToContainer:function(x,y){var coords={x:util.scaleValue(x,this.current_zoom),y:util.scaleValue(y,this.current_zoom)};return this.img_object.toRealCoords(coords)},_getMouseCoords:function(e){var containerOffset=this.container.offset();coords=this.containerToImage(e.pageX-containerOffset.left,e.pageY-
containerOffset.top);return coords},set_zoom:function(new_zoom,skip_animation){if(this._trigger("onZoom",0,new_zoom)==false)return;if(!this.img_object.loaded())return;if(new_zoom<this.options.zoom_min)new_zoom=this.options.zoom_min;else if(new_zoom>this.options.zoom_max)new_zoom=this.options.zoom_max;if(this.current_zoom=="fit"){var old_x=Math.round(this.options.width/2+this.img_object.orig_width()/2);var old_y=Math.round(this.options.height/2+this.img_object.orig_height()/2);this.current_zoom=100}else{var old_x=
-this.img_object.x()+Math.round(this.options.width/2);var old_y=-this.img_object.y()+Math.round(this.options.height/2)}var new_width=util.scaleValue(this.img_object.orig_width(),new_zoom);var new_height=util.scaleValue(this.img_object.orig_height(),new_zoom);var new_x=util.scaleValue(util.descaleValue(old_x,this.current_zoom),new_zoom);var new_y=util.scaleValue(util.descaleValue(old_y,this.current_zoom),new_zoom);new_x=this.options.width/2-new_x;new_y=this.options.height/2-new_y;this.img_object.display_width(new_width);
this.img_object.display_height(new_height);var coords=this._correctCoords(new_x,new_y),self=this;this.img_object.setImageProps(new_width,new_height,coords.x,coords.y,skip_animation,function(){self._trigger("onAfterZoom",0,new_zoom)});this.current_zoom=new_zoom;this.update_status()},zoom_by:function(delta){var closest_rate=this.find_closest_zoom_rate(this.current_zoom);var next_rate=closest_rate+delta;var next_zoom=this.options.zoom_base*Math.pow(this.options.zoom_delta,next_rate);if(delta>0&&next_zoom<
this.current_zoom)next_zoom*=this.options.zoom_delta;if(delta<0&&next_zoom>this.current_zoom)next_zoom/=this.options.zoom_delta;this.set_zoom(next_zoom)},angle:function(deg,abs){if(arguments.length===0)return this.img_object.angle();if(deg<-270||deg>270||deg%90!==0)return;if(!abs)deg+=this.img_object.angle();if(deg<0)deg+=360;if(deg>=360)deg-=360;if(deg===this.img_object.angle())return;this.img_object.angle(deg);this.center();this._trigger("angle",0,{angle:this.img_object.angle()})},find_closest_zoom_rate:function(value){if(value==
this.options.zoom_base)return 0;function div(val1,val2){return val1/val2}function mul(val1,val2){return val1*val2}var func=value>this.options.zoom_base?mul:div;var sgn=value>this.options.zoom_base?1:-1;var mltplr=this.options.zoom_delta;var rate=1;while(Math.abs(func(this.options.zoom_base,Math.pow(mltplr,rate))-value)>Math.abs(func(this.options.zoom_base,Math.pow(mltplr,rate+1))-value))rate++;return sgn*rate},update_status:function(){if(!this.options.ui_disabled){var percent=Math.round(100*this.img_object.display_height()/
this.img_object.orig_height());if(percent)this.zoom_object.html(percent+"%")}},info:function(param,withoutRotation){if(!param)return;switch(param){case "orig_width":case "orig_height":if(withoutRotation)return this.img_object.angle()%180===0?this.img_object[param]():param==="orig_width"?this.img_object.orig_height():this.img_object.orig_width();else return this.img_object[param]();case "display_width":case "display_height":case "angle":return this.img_object[param]();case "zoom":return this.current_zoom;
case "src":return this.img_object.object().attr("src")}},_mouseStart:function(e){$.ui.mouse.prototype._mouseStart.call(this,e);if(this._trigger("onStartDrag",0,this._getMouseCoords(e))===false)return false;this.container.addClass("iviewer_drag_cursor");this.dx=e.pageX-this.img_object.x();this.dy=e.pageY-this.img_object.y();return true},_mouseCapture:function(e){return true},_handleMouseMove:function(e){this._trigger("onMouseMove",e,this._getMouseCoords(e))},_mouseDrag:function(e){$.ui.mouse.prototype._mouseDrag.call(this,
e);var ltop=e.pageY-this.dy;var lleft=e.pageX-this.dx;this.setCoords(lleft,ltop);this._trigger("onDrag",e,this._getMouseCoords(e));return false},_mouseStop:function(e){$.ui.mouse.prototype._mouseStop.call(this,e);this.container.removeClass("iviewer_drag_cursor");this._trigger("onStopDrag",0,this._getMouseCoords(e))},_click:function(e){this._trigger("onClick",0,this._getMouseCoords(e))},createui:function(){var me=this;$("<div>",{"class":"iviewer_zoom_in iviewer_common iviewer_button"}).bind("mousedown touchstart",
function(){me.zoom_by(1);return false}).appendTo(this.container);$("<div>",{"class":"iviewer_zoom_out iviewer_common iviewer_button"}).bind("mousedown touchstart",function(){me.zoom_by(-1);return false}).appendTo(this.container);$("<div>",{"class":"iviewer_zoom_zero iviewer_common iviewer_button"}).bind("mousedown touchstart",function(){me.set_zoom(100);return false}).appendTo(this.container);$("<div>",{"class":"iviewer_zoom_fit iviewer_common iviewer_button"}).bind("mousedown touchstart",function(){me.fit(this);
return false}).appendTo(this.container);this.zoom_object=$("<div>").addClass("iviewer_zoom_status iviewer_common").appendTo(this.container);$("<div>",{"class":"iviewer_rotate_left iviewer_common iviewer_button"}).bind("mousedown touchstart",function(){me.angle(-90);return false}).appendTo(this.container);$("<div>",{"class":"iviewer_rotate_right iviewer_common iviewer_button"}).bind("mousedown touchstart",function(){me.angle(90);return false}).appendTo(this.container);this.update_status()}});$.ui.iviewer.ImageObject=
function(do_anim){this._img=$("<img>").css({position:"absolute",top:"0px",left:"0px"});this._loaded=false;this._swapDimensions=false;this._do_anim=do_anim||false;this.x(0,true);this.y(0,true);this.angle(0)};(function(){this._reset=function(w,h){this._angle=0;this._swapDimensions=false;this.x(0);this.y(0);this.orig_width(w);this.orig_height(h);this.display_width(w);this.display_height(h)};this.loaded=function(){return this._loaded};this.load=function(src,loaded){var self=this;loaded=loaded||jQuery.noop;
this._loaded=false;var img=new Image;img.onload=function(){self._loaded=true;self._reset(this.width,this.height);self._img[0].src=src;loaded()};img.src=src;this._img.removeAttr("src").removeAttr("width").removeAttr("height").removeAttr("style").css({position:"absolute",top:"0px",left:"0px"});this.angle(0)};this._dimension=function(prefix,name){var horiz="_"+prefix+"_"+name,vert="_"+prefix+"_"+(name==="height"?"width":"height");return setter(function(val){this[this._swapDimensions?horiz:vert]=val},
function(){return this[this._swapDimensions?horiz:vert]})};this.display_width=this._dimension("display","width"),this.display_height=this._dimension("display","height"),this.display_diff=function(){return Math.floor(this.display_width()-this.display_height())};this.orig_width=this._dimension("orig","width"),this.orig_height=this._dimension("orig","height"),this.x=setter(function(val,skipCss){this._x=val;if(!skipCss)this._img.css("left",this._x+(this._swapDimensions?this.display_diff()/2:0)+"px")},
function(){return this._x});this.y=setter(function(val,skipCss){this._y=val;if(!skipCss)this._img.css("top",this._y-(this._swapDimensions?this.display_diff()/2:0)+"px")},function(){return this._y});this.angle=setter(function(deg){var prevSwap=this._swapDimensions;this._angle=deg;this._swapDimensions=deg%180!==0;if(prevSwap!==this._swapDimensions){var verticalMod=this._swapDimensions?-1:1;this.x(this.x()-verticalMod*this.display_diff()/2,true);this.y(this.y()+verticalMod*this.display_diff()/2,true)}var cssVal=
"rotate("+deg+"deg)",img=this._img;jQuery.each(["","-webkit-","-moz-","-o-","-ms-"],function(i,prefix){img.css(prefix+"transform",cssVal)});if(useIeTransforms){jQuery.each(["-ms-",""],function(i,prefix){img.css(prefix+"filter",ieTransforms[deg].filter)});img.css({marginLeft:ieTransforms[deg].marginLeft*this.display_diff()/2,marginTop:ieTransforms[deg].marginTop*this.display_diff()/2})}},function(){return this._angle});this.toOriginalCoords=function(point){switch(this.angle()){case 0:return{x:point.x,
y:point.y};case 90:return{x:point.y,y:this.display_width()-point.x};case 180:return{x:this.display_width()-point.x,y:this.display_height()-point.y};case 270:return{x:this.display_height()-point.y,y:point.x}}};this.toRealCoords=function(point){switch(this.angle()){case 0:return{x:this.x()+point.x,y:this.y()+point.y};case 90:return{x:this.x()+this.display_width()-point.y,y:this.y()+point.x};case 180:return{x:this.x()+this.display_width()-point.x,y:this.y()+this.display_height()-point.y};case 270:return{x:this.x()+
point.y,y:this.y()+this.display_height()-point.x}}};this.object=setter(jQuery.noop,function(){return this._img});this.setImageProps=function(disp_w,disp_h,x,y,skip_animation,complete){complete=complete||jQuery.noop;this.display_width(disp_w);this.display_height(disp_h);this.x(x,true);this.y(y,true);var w=this._swapDimensions?disp_h:disp_w;var h=this._swapDimensions?disp_w:disp_h;var params={width:w,height:h,top:y-(this._swapDimensions?this.display_diff()/2:0)+"px",left:x+(this._swapDimensions?this.display_diff()/
2:0)+"px"};if(useIeTransforms)jQuery.extend(params,{marginLeft:ieTransforms[this.angle()].marginLeft*this.display_diff()/2,marginTop:ieTransforms[this.angle()].marginTop*this.display_diff()/2});var swapDims=this._swapDimensions,img=this._img;if(useIeTransforms&&swapDims){var ieh=this._img.width(),iew=this._img.height(),iedh=params.height-ieh;iedw=params.width-iew;delete params.width;delete params.height}if(this._do_anim&&!skip_animation)this._img.animate(params,{duration:200,complete:complete,step:function(now,
fx){if(useIeTransforms&&swapDims&&fx.prop==="top"){var percent=(now-fx.start)/(fx.end-fx.start);img.height(ieh+iedh*percent);img.width(iew+iedw*percent);img.css("top",now)}}});else{this._img.css(params);setTimeout(complete,0)}}}).apply($.ui.iviewer.ImageObject.prototype);var util={scaleValue:function(value,toZoom){return value*toZoom/100},descaleValue:function(value,fromZoom){return value*100/fromZoom}}})(jQuery,undefined);
/*
 * Downloaded from http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js, 2012-02-04 23:26
 */

/*!
 * jQuery JavaScript Library v1.7.1
 * http://jquery.com/
 *
 * Copyright 2011, John Resig
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * Includes Sizzle.js
 * http://sizzlejs.com/
 * Copyright 2011, The Dojo Foundation
 * Released under the MIT, BSD, and GPL Licenses.
 *
 * Date: Mon Nov 21 21:11:03 2011 -0500
 */
(function( window, undefined ) {

// Use the correct document accordingly with window argument (sandbox)
var document = window.document,
	navigator = window.navigator,
	location = window.location;
var jQuery = (function() {

// Define a local copy of jQuery
var jQuery = function( selector, context ) {
		// The jQuery object is actually just the init constructor 'enhanced'
		return new jQuery.fn.init( selector, context, rootjQuery );
	},

	// Map over jQuery in case of overwrite
	_jQuery = window.jQuery,

	// Map over the $ in case of overwrite
	_$ = window.$,

	// A central reference to the root jQuery(document)
	rootjQuery,

	// A simple way to check for HTML strings or ID strings
	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
	quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,

	// Check if a string has a non-whitespace character in it
	rnotwhite = /\S/,

	// Used for trimming whitespace
	trimLeft = /^\s+/,
	trimRight = /\s+$/,

	// Match a standalone tag
	rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,

	// JSON RegExp
	rvalidchars = /^[\],:{}\s]*$/,
	rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
	rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
	rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,

	// Useragent RegExp
	rwebkit = /(webkit)[ \/]([\w.]+)/,
	ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
	rmsie = /(msie) ([\w.]+)/,
	rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,

	// Matches dashed string for camelizing
	rdashAlpha = /-([a-z]|[0-9])/ig,
	rmsPrefix = /^-ms-/,

	// Used by jQuery.camelCase as callback to replace()
	fcamelCase = function( all, letter ) {
		return ( letter + "" ).toUpperCase();
	},

	// Keep a UserAgent string for use with jQuery.browser
	userAgent = navigator.userAgent,

	// For matching the engine and version of the browser
	browserMatch,

	// The deferred used on DOM ready
	readyList,

	// The ready event handler
	DOMContentLoaded,

	// Save a reference to some core methods
	toString = Object.prototype.toString,
	hasOwn = Object.prototype.hasOwnProperty,
	push = Array.prototype.push,
	slice = Array.prototype.slice,
	trim = String.prototype.trim,
	indexOf = Array.prototype.indexOf,

	// [[Class]] -> type pairs
	class2type = {};

jQuery.fn = jQuery.prototype = {
	constructor: jQuery,
	init: function( selector, context, rootjQuery ) {
		var match, elem, ret, doc;

		// Handle $(""), $(null), or $(undefined)
		if ( !selector ) {
			return this;
		}

		// Handle $(DOMElement)
		if ( selector.nodeType ) {
			this.context = this[0] = selector;
			this.length = 1;
			return this;
		}

		// The body element only exists once, optimize finding it
		if ( selector === "body" && !context && document.body ) {
			this.context = document;
			this[0] = document.body;
			this.selector = selector;
			this.length = 1;
			return this;
		}

		// Handle HTML strings
		if ( typeof selector === "string" ) {
			// Are we dealing with HTML string or an ID?
			if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
				// Assume that strings that start and end with <> are HTML and skip the regex check
				match = [ null, selector, null ];

			} else {
				match = quickExpr.exec( selector );
			}

			// Verify a match, and that no context was specified for #id
			if ( match && (match[1] || !context) ) {

				// HANDLE: $(html) -> $(array)
				if ( match[1] ) {
					context = context instanceof jQuery ? context[0] : context;
					doc = ( context ? context.ownerDocument || context : document );

					// If a single string is passed in and it's a single tag
					// just do a createElement and skip the rest
					ret = rsingleTag.exec( selector );

					if ( ret ) {
						if ( jQuery.isPlainObject( context ) ) {
							selector = [ document.createElement( ret[1] ) ];
							jQuery.fn.attr.call( selector, context, true );

						} else {
							selector = [ doc.createElement( ret[1] ) ];
						}

					} else {
						ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
						selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;
					}

					return jQuery.merge( this, selector );

				// HANDLE: $("#id")
				} else {
					elem = document.getElementById( match[2] );

					// Check parentNode to catch when Blackberry 4.6 returns
					// nodes that are no longer in the document #6963
					if ( elem && elem.parentNode ) {
						// Handle the case where IE and Opera return items
						// by name instead of ID
						if ( elem.id !== match[2] ) {
							return rootjQuery.find( selector );
						}

						// Otherwise, we inject the element directly into the jQuery object
						this.length = 1;
						this[0] = elem;
					}

					this.context = document;
					this.selector = selector;
					return this;
				}

			// HANDLE: $(expr, $(...))
			} else if ( !context || context.jquery ) {
				return ( context || rootjQuery ).find( selector );

			// HANDLE: $(expr, context)
			// (which is just equivalent to: $(context).find(expr)
			} else {
				return this.constructor( context ).find( selector );
			}

		// HANDLE: $(function)
		// Shortcut for document ready
		} else if ( jQuery.isFunction( selector ) ) {
			return rootjQuery.ready( selector );
		}

		if ( selector.selector !== undefined ) {
			this.selector = selector.selector;
			this.context = selector.context;
		}

		return jQuery.makeArray( selector, this );
	},

	// Start with an empty selector
	selector: "",

	// The current version of jQuery being used
	jquery: "1.7.1",

	// The default length of a jQuery object is 0
	length: 0,

	// The number of elements contained in the matched element set
	size: function() {
		return this.length;
	},

	toArray: function() {
		return slice.call( this, 0 );
	},

	// Get the Nth element in the matched element set OR
	// Get the whole matched element set as a clean array
	get: function( num ) {
		return num == null ?

			// Return a 'clean' array
			this.toArray() :

			// Return just the object
			( num < 0 ? this[ this.length + num ] : this[ num ] );
	},

	// Take an array of elements and push it onto the stack
	// (returning the new matched element set)
	pushStack: function( elems, name, selector ) {
		// Build a new jQuery matched element set
		var ret = this.constructor();

		if ( jQuery.isArray( elems ) ) {
			push.apply( ret, elems );

		} else {
			jQuery.merge( ret, elems );
		}

		// Add the old object onto the stack (as a reference)
		ret.prevObject = this;

		ret.context = this.context;

		if ( name === "find" ) {
			ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
		} else if ( name ) {
			ret.selector = this.selector + "." + name + "(" + selector + ")";
		}

		// Return the newly-formed element set
		return ret;
	},

	// Execute a callback for every element in the matched set.
	// (You can seed the arguments with an array of args, but this is
	// only used internally.)
	each: function( callback, args ) {
		return jQuery.each( this, callback, args );
	},

	ready: function( fn ) {
		// Attach the listeners
		jQuery.bindReady();

		// Add the callback
		readyList.add( fn );

		return this;
	},

	eq: function( i ) {
		i = +i;
		return i === -1 ?
			this.slice( i ) :
			this.slice( i, i + 1 );
	},

	first: function() {
		return this.eq( 0 );
	},

	last: function() {
		return this.eq( -1 );
	},

	slice: function() {
		return this.pushStack( slice.apply( this, arguments ),
			"slice", slice.call(arguments).join(",") );
	},

	map: function( callback ) {
		return this.pushStack( jQuery.map(this, function( elem, i ) {
			return callback.call( elem, i, elem );
		}));
	},

	end: function() {
		return this.prevObject || this.constructor(null);
	},

	// For internal use only.
	// Behaves like an Array's method, not like a jQuery method.
	push: push,
	sort: [].sort,
	splice: [].splice
};

// Give the init function the jQuery prototype for later instantiation
jQuery.fn.init.prototype = jQuery.fn;

jQuery.extend = jQuery.fn.extend = function() {
	var options, name, src, copy, copyIsArray, clone,
		target = arguments[0] || {},
		i = 1,
		length = arguments.length,
		deep = false;

	// Handle a deep copy situation
	if ( typeof target === "boolean" ) {
		deep = target;
		target = arguments[1] || {};
		// skip the boolean and the target
		i = 2;
	}

	// Handle case when target is a string or something (possible in deep copy)
	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
		target = {};
	}

	// extend jQuery itself if only one argument is passed
	if ( length === i ) {
		target = this;
		--i;
	}

	for ( ; i < length; i++ ) {
		// Only deal with non-null/undefined values
		if ( (options = arguments[ i ]) != null ) {
			// Extend the base object
			for ( name in options ) {
				src = target[ name ];
				copy = options[ name ];

				// Prevent never-ending loop
				if ( target === copy ) {
					continue;
				}

				// Recurse if we're merging plain objects or arrays
				if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
					if ( copyIsArray ) {
						copyIsArray = false;
						clone = src && jQuery.isArray(src) ? src : [];

					} else {
						clone = src && jQuery.isPlainObject(src) ? src : {};
					}

					// Never move original objects, clone them
					target[ name ] = jQuery.extend( deep, clone, copy );

				// Don't bring in undefined values
				} else if ( copy !== undefined ) {
					target[ name ] = copy;
				}
			}
		}
	}

	// Return the modified object
	return target;
};

jQuery.extend({
	noConflict: function( deep ) {
		if ( window.$ === jQuery ) {
			window.$ = _$;
		}

		if ( deep && window.jQuery === jQuery ) {
			window.jQuery = _jQuery;
		}

		return jQuery;
	},

	// Is the DOM ready to be used? Set to true once it occurs.
	isReady: false,

	// A counter to track how many items to wait for before
	// the ready event fires. See #6781
	readyWait: 1,

	// Hold (or release) the ready event
	holdReady: function( hold ) {
		if ( hold ) {
			jQuery.readyWait++;
		} else {
			jQuery.ready( true );
		}
	},

	// Handle when the DOM is ready
	ready: function( wait ) {
		// Either a released hold or an DOMready/load event and not yet ready
		if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {
			// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
			if ( !document.body ) {
				return setTimeout( jQuery.ready, 1 );
			}

			// Remember that the DOM is ready
			jQuery.isReady = true;

			// If a normal DOM Ready event fired, decrement, and wait if need be
			if ( wait !== true && --jQuery.readyWait > 0 ) {
				return;
			}

			// If there are functions bound, to execute
			readyList.fireWith( document, [ jQuery ] );

			// Trigger any bound ready events
			if ( jQuery.fn.trigger ) {
				jQuery( document ).trigger( "ready" ).off( "ready" );
			}
		}
	},

	bindReady: function() {
		if ( readyList ) {
			return;
		}

		readyList = jQuery.Callbacks( "once memory" );

		// Catch cases where $(document).ready() is called after the
		// browser event has already occurred.
		if ( document.readyState === "complete" ) {
			// Handle it asynchronously to allow scripts the opportunity to delay ready
			return setTimeout( jQuery.ready, 1 );
		}

		// Mozilla, Opera and webkit nightlies currently support this event
		if ( document.addEventListener ) {
			// Use the handy event callback
			document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );

			// A fallback to window.onload, that will always work
			window.addEventListener( "load", jQuery.ready, false );

		// If IE event model is used
		} else if ( document.attachEvent ) {
			// ensure firing before onload,
			// maybe late but safe also for iframes
			document.attachEvent( "onreadystatechange", DOMContentLoaded );

			// A fallback to window.onload, that will always work
			window.attachEvent( "onload", jQuery.ready );

			// If IE and not a frame
			// continually check to see if the document is ready
			var toplevel = false;

			try {
				toplevel = window.frameElement == null;
			} catch(e) {}

			if ( document.documentElement.doScroll && toplevel ) {
				doScrollCheck();
			}
		}
	},

	// See test/unit/core.js for details concerning isFunction.
	// Since version 1.3, DOM methods and functions like alert
	// aren't supported. They return false on IE (#2968).
	isFunction: function( obj ) {
		return jQuery.type(obj) === "function";
	},

	isArray: Array.isArray || function( obj ) {
		return jQuery.type(obj) === "array";
	},

	// A crude way of determining if an object is a window
	isWindow: function( obj ) {
		return obj && typeof obj === "object" && "setInterval" in obj;
	},

	isNumeric: function( obj ) {
		return !isNaN( parseFloat(obj) ) && isFinite( obj );
	},

	type: function( obj ) {
		return obj == null ?
			String( obj ) :
			class2type[ toString.call(obj) ] || "object";
	},

	isPlainObject: function( obj ) {
		// Must be an Object.
		// Because of IE, we also have to check the presence of the constructor property.
		// Make sure that DOM nodes and window objects don't pass through, as well
		if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
			return false;
		}

		try {
			// Not own constructor property must be Object
			if ( obj.constructor &&
				!hasOwn.call(obj, "constructor") &&
				!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
				return false;
			}
		} catch ( e ) {
			// IE8,9 Will throw exceptions on certain host objects #9897
			return false;
		}

		// Own properties are enumerated firstly, so to speed up,
		// if last one is own, then all properties are own.

		var key;
		for ( key in obj ) {}

		return key === undefined || hasOwn.call( obj, key );
	},

	isEmptyObject: function( obj ) {
		for ( var name in obj ) {
			return false;
		}
		return true;
	},

	error: function( msg ) {
		throw new Error( msg );
	},

	parseJSON: function( data ) {
		if ( typeof data !== "string" || !data ) {
			return null;
		}

		// Make sure leading/trailing whitespace is removed (IE can't handle it)
		data = jQuery.trim( data );

		// Attempt to parse using the native JSON parser first
		if ( window.JSON && window.JSON.parse ) {
			return window.JSON.parse( data );
		}

		// Make sure the incoming data is actual JSON
		// Logic borrowed from http://json.org/json2.js
		if ( rvalidchars.test( data.replace( rvalidescape, "@" )
			.replace( rvalidtokens, "]" )
			.replace( rvalidbraces, "")) ) {

			return ( new Function( "return " + data ) )();

		}
		jQuery.error( "Invalid JSON: " + data );
	},

	// Cross-browser xml parsing
	parseXML: function( data ) {
		var xml, tmp;
		try {
			if ( window.DOMParser ) { // Standard
				tmp = new DOMParser();
				xml = tmp.parseFromString( data , "text/xml" );
			} else { // IE
				xml = new ActiveXObject( "Microsoft.XMLDOM" );
				xml.async = "false";
				xml.loadXML( data );
			}
		} catch( e ) {
			xml = undefined;
		}
		if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
			jQuery.error( "Invalid XML: " + data );
		}
		return xml;
	},

	noop: function() {},

	// Evaluates a script in a global context
	// Workarounds based on findings by Jim Driscoll
	// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
	globalEval: function( data ) {
		if ( data && rnotwhite.test( data ) ) {
			// We use execScript on Internet Explorer
			// We use an anonymous function so that context is window
			// rather than jQuery in Firefox
			( window.execScript || function( data ) {
				window[ "eval" ].call( window, data );
			} )( data );
		}
	},

	// Convert dashed to camelCase; used by the css and data modules
	// Microsoft forgot to hump their vendor prefix (#9572)
	camelCase: function( string ) {
		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
	},

	nodeName: function( elem, name ) {
		return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
	},

	// args is for internal usage only
	each: function( object, callback, args ) {
		var name, i = 0,
			length = object.length,
			isObj = length === undefined || jQuery.isFunction( object );

		if ( args ) {
			if ( isObj ) {
				for ( name in object ) {
					if ( callback.apply( object[ name ], args ) === false ) {
						break;
					}
				}
			} else {
				for ( ; i < length; ) {
					if ( callback.apply( object[ i++ ], args ) === false ) {
						break;
					}
				}
			}

		// A special, fast, case for the most common use of each
		} else {
			if ( isObj ) {
				for ( name in object ) {
					if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
						break;
					}
				}
			} else {
				for ( ; i < length; ) {
					if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
						break;
					}
				}
			}
		}

		return object;
	},

	// Use native String.trim function wherever possible
	trim: trim ?
		function( text ) {
			return text == null ?
				"" :
				trim.call( text );
		} :

		// Otherwise use our own trimming functionality
		function( text ) {
			return text == null ?
				"" :
				text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
		},

	// results is for internal usage only
	makeArray: function( array, results ) {
		var ret = results || [];

		if ( array != null ) {
			// The window, strings (and functions) also have 'length'
			// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
			var type = jQuery.type( array );

			if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
				push.call( ret, array );
			} else {
				jQuery.merge( ret, array );
			}
		}

		return ret;
	},

	inArray: function( elem, array, i ) {
		var len;

		if ( array ) {
			if ( indexOf ) {
				return indexOf.call( array, elem, i );
			}

			len = array.length;
			i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;

			for ( ; i < len; i++ ) {
				// Skip accessing in sparse arrays
				if ( i in array && array[ i ] === elem ) {
					return i;
				}
			}
		}

		return -1;
	},

	merge: function( first, second ) {
		var i = first.length,
			j = 0;

		if ( typeof second.length === "number" ) {
			for ( var l = second.length; j < l; j++ ) {
				first[ i++ ] = second[ j ];
			}

		} else {
			while ( second[j] !== undefined ) {
				first[ i++ ] = second[ j++ ];
			}
		}

		first.length = i;

		return first;
	},

	grep: function( elems, callback, inv ) {
		var ret = [], retVal;
		inv = !!inv;

		// Go through the array, only saving the items
		// that pass the validator function
		for ( var i = 0, length = elems.length; i < length; i++ ) {
			retVal = !!callback( elems[ i ], i );
			if ( inv !== retVal ) {
				ret.push( elems[ i ] );
			}
		}

		return ret;
	},

	// arg is for internal usage only
	map: function( elems, callback, arg ) {
		var value, key, ret = [],
			i = 0,
			length = elems.length,
			// jquery objects are treated as arrays
			isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;

		// Go through the array, translating each of the items to their
		if ( isArray ) {
			for ( ; i < length; i++ ) {
				value = callback( elems[ i ], i, arg );

				if ( value != null ) {
					ret[ ret.length ] = value;
				}
			}

		// Go through every key on the object,
		} else {
			for ( key in elems ) {
				value = callback( elems[ key ], key, arg );

				if ( value != null ) {
					ret[ ret.length ] = value;
				}
			}
		}

		// Flatten any nested arrays
		return ret.concat.apply( [], ret );
	},

	// A global GUID counter for objects
	guid: 1,

	// Bind a function to a context, optionally partially applying any
	// arguments.
	proxy: function( fn, context ) {
		if ( typeof context === "string" ) {
			var tmp = fn[ context ];
			context = fn;
			fn = tmp;
		}

		// Quick check to determine if target is callable, in the spec
		// this throws a TypeError, but we will just return undefined.
		if ( !jQuery.isFunction( fn ) ) {
			return undefined;
		}

		// Simulated bind
		var args = slice.call( arguments, 2 ),
			proxy = function() {
				return fn.apply( context, args.concat( slice.call( arguments ) ) );
			};

		// Set the guid of unique handler to the same of original handler, so it can be removed
		proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;

		return proxy;
	},

	// Mutifunctional method to get and set values to a collection
	// The value/s can optionally be executed if it's a function
	access: function( elems, key, value, exec, fn, pass ) {
		var length = elems.length;

		// Setting many attributes
		if ( typeof key === "object" ) {
			for ( var k in key ) {
				jQuery.access( elems, k, key[k], exec, fn, value );
			}
			return elems;
		}

		// Setting one attribute
		if ( value !== undefined ) {
			// Optionally, function values get executed if exec is true
			exec = !pass && exec && jQuery.isFunction(value);

			for ( var i = 0; i < length; i++ ) {
				fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
			}

			return elems;
		}

		// Getting an attribute
		return length ? fn( elems[0], key ) : undefined;
	},

	now: function() {
		return ( new Date() ).getTime();
	},

	// Use of jQuery.browser is frowned upon.
	// More details: http://docs.jquery.com/Utilities/jQuery.browser
	uaMatch: function( ua ) {
		ua = ua.toLowerCase();

		var match = rwebkit.exec( ua ) ||
			ropera.exec( ua ) ||
			rmsie.exec( ua ) ||
			ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
			[];

		return { browser: match[1] || "", version: match[2] || "0" };
	},

	sub: function() {
		function jQuerySub( selector, context ) {
			return new jQuerySub.fn.init( selector, context );
		}
		jQuery.extend( true, jQuerySub, this );
		jQuerySub.superclass = this;
		jQuerySub.fn = jQuerySub.prototype = this();
		jQuerySub.fn.constructor = jQuerySub;
		jQuerySub.sub = this.sub;
		jQuerySub.fn.init = function init( selector, context ) {
			if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
				context = jQuerySub( context );
			}

			return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
		};
		jQuerySub.fn.init.prototype = jQuerySub.fn;
		var rootjQuerySub = jQuerySub(document);
		return jQuerySub;
	},

	browser: {}
});

// Populate the class2type map
jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
	class2type[ "[object " + name + "]" ] = name.toLowerCase();
});

browserMatch = jQuery.uaMatch( userAgent );
if ( browserMatch.browser ) {
	jQuery.browser[ browserMatch.browser ] = true;
	jQuery.browser.version = browserMatch.version;
}

// Deprecated, use jQuery.browser.webkit instead
if ( jQuery.browser.webkit ) {
	jQuery.browser.safari = true;
}

// IE doesn't match non-breaking spaces with \s
if ( rnotwhite.test( "\xA0" ) ) {
	trimLeft = /^[\s\xA0]+/;
	trimRight = /[\s\xA0]+$/;
}

// All jQuery objects should point back to these
rootjQuery = jQuery(document);

// Cleanup functions for the document ready method
if ( document.addEventListener ) {
	DOMContentLoaded = function() {
		document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
		jQuery.ready();
	};

} else if ( document.attachEvent ) {
	DOMContentLoaded = function() {
		// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
		if ( document.readyState === "complete" ) {
			document.detachEvent( "onreadystatechange", DOMContentLoaded );
			jQuery.ready();
		}
	};
}

// The DOM ready check for Internet Explorer
function doScrollCheck() {
	if ( jQuery.isReady ) {
		return;
	}

	try {
		// If IE is used, use the trick by Diego Perini
		// http://javascript.nwbox.com/IEContentLoaded/
		document.documentElement.doScroll("left");
	} catch(e) {
		setTimeout( doScrollCheck, 1 );
		return;
	}

	// and execute any waiting functions
	jQuery.ready();
}

return jQuery;

})();


// String to Object flags format cache
var flagsCache = {};

// Convert String-formatted flags into Object-formatted ones and store in cache
function createFlags( flags ) {
	var object = flagsCache[ flags ] = {},
		i, length;
	flags = flags.split( /\s+/ );
	for ( i = 0, length = flags.length; i < length; i++ ) {
		object[ flags[i] ] = true;
	}
	return object;
}

/*
 * Create a callback list using the following parameters:
 *
 *	flags:	an optional list of space-separated flags that will change how
 *			the callback list behaves
 *
 * By default a callback list will act like an event callback list and can be
 * "fired" multiple times.
 *
 * Possible flags:
 *
 *	once:			will ensure the callback list can only be fired once (like a Deferred)
 *
 *	memory:			will keep track of previous values and will call any callback added
 *					after the list has been fired right away with the latest "memorized"
 *					values (like a Deferred)
 *
 *	unique:			will ensure a callback can only be added once (no duplicate in the list)
 *
 *	stopOnFalse:	interrupt callings when a callback returns false
 *
 */
jQuery.Callbacks = function( flags ) {

	// Convert flags from String-formatted to Object-formatted
	// (we check in cache first)
	flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};

	var // Actual callback list
		list = [],
		// Stack of fire calls for repeatable lists
		stack = [],
		// Last fire value (for non-forgettable lists)
		memory,
		// Flag to know if list is currently firing
		firing,
		// First callback to fire (used internally by add and fireWith)
		firingStart,
		// End of the loop when firing
		firingLength,
		// Index of currently firing callback (modified by remove if needed)
		firingIndex,
		// Add one or several callbacks to the list
		add = function( args ) {
			var i,
				length,
				elem,
				type,
				actual;
			for ( i = 0, length = args.length; i < length; i++ ) {
				elem = args[ i ];
				type = jQuery.type( elem );
				if ( type === "array" ) {
					// Inspect recursively
					add( elem );
				} else if ( type === "function" ) {
					// Add if not in unique mode and callback is not in
					if ( !flags.unique || !self.has( elem ) ) {
						list.push( elem );
					}
				}
			}
		},
		// Fire callbacks
		fire = function( context, args ) {
			args = args || [];
			memory = !flags.memory || [ context, args ];
			firing = true;
			firingIndex = firingStart || 0;
			firingStart = 0;
			firingLength = list.length;
			for ( ; list && firingIndex < firingLength; firingIndex++ ) {
				if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {
					memory = true; // Mark as halted
					break;
				}
			}
			firing = false;
			if ( list ) {
				if ( !flags.once ) {
					if ( stack && stack.length ) {
						memory = stack.shift();
						self.fireWith( memory[ 0 ], memory[ 1 ] );
					}
				} else if ( memory === true ) {
					self.disable();
				} else {
					list = [];
				}
			}
		},
		// Actual Callbacks object
		self = {
			// Add a callback or a collection of callbacks to the list
			add: function() {
				if ( list ) {
					var length = list.length;
					add( arguments );
					// Do we need to add the callbacks to the
					// current firing batch?
					if ( firing ) {
						firingLength = list.length;
					// With memory, if we're not firing then
					// we should call right away, unless previous
					// firing was halted (stopOnFalse)
					} else if ( memory && memory !== true ) {
						firingStart = length;
						fire( memory[ 0 ], memory[ 1 ] );
					}
				}
				return this;
			},
			// Remove a callback from the list
			remove: function() {
				if ( list ) {
					var args = arguments,
						argIndex = 0,
						argLength = args.length;
					for ( ; argIndex < argLength ; argIndex++ ) {
						for ( var i = 0; i < list.length; i++ ) {
							if ( args[ argIndex ] === list[ i ] ) {
								// Handle firingIndex and firingLength
								if ( firing ) {
									if ( i <= firingLength ) {
										firingLength--;
										if ( i <= firingIndex ) {
											firingIndex--;
										}
									}
								}
								// Remove the element
								list.splice( i--, 1 );
								// If we have some unicity property then
								// we only need to do this once
								if ( flags.unique ) {
									break;
								}
							}
						}
					}
				}
				return this;
			},
			// Control if a given callback is in the list
			has: function( fn ) {
				if ( list ) {
					var i = 0,
						length = list.length;
					for ( ; i < length; i++ ) {
						if ( fn === list[ i ] ) {
							return true;
						}
					}
				}
				return false;
			},
			// Remove all callbacks from the list
			empty: function() {
				list = [];
				return this;
			},
			// Have the list do nothing anymore
			disable: function() {
				list = stack = memory = undefined;
				return this;
			},
			// Is it disabled?
			disabled: function() {
				return !list;
			},
			// Lock the list in its current state
			lock: function() {
				stack = undefined;
				if ( !memory || memory === true ) {
					self.disable();
				}
				return this;
			},
			// Is it locked?
			locked: function() {
				return !stack;
			},
			// Call all callbacks with the given context and arguments
			fireWith: function( context, args ) {
				if ( stack ) {
					if ( firing ) {
						if ( !flags.once ) {
							stack.push( [ context, args ] );
						}
					} else if ( !( flags.once && memory ) ) {
						fire( context, args );
					}
				}
				return this;
			},
			// Call all the callbacks with the given arguments
			fire: function() {
				self.fireWith( this, arguments );
				return this;
			},
			// To know if the callbacks have already been called at least once
			fired: function() {
				return !!memory;
			}
		};

	return self;
};




var // Static reference to slice
	sliceDeferred = [].slice;

jQuery.extend({

	Deferred: function( func ) {
		var doneList = jQuery.Callbacks( "once memory" ),
			failList = jQuery.Callbacks( "once memory" ),
			progressList = jQuery.Callbacks( "memory" ),
			state = "pending",
			lists = {
				resolve: doneList,
				reject: failList,
				notify: progressList
			},
			promise = {
				done: doneList.add,
				fail: failList.add,
				progress: progressList.add,

				state: function() {
					return state;
				},

				// Deprecated
				isResolved: doneList.fired,
				isRejected: failList.fired,

				then: function( doneCallbacks, failCallbacks, progressCallbacks ) {
					deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );
					return this;
				},
				always: function() {
					deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );
					return this;
				},
				pipe: function( fnDone, fnFail, fnProgress ) {
					return jQuery.Deferred(function( newDefer ) {
						jQuery.each( {
							done: [ fnDone, "resolve" ],
							fail: [ fnFail, "reject" ],
							progress: [ fnProgress, "notify" ]
						}, function( handler, data ) {
							var fn = data[ 0 ],
								action = data[ 1 ],
								returned;
							if ( jQuery.isFunction( fn ) ) {
								deferred[ handler ](function() {
									returned = fn.apply( this, arguments );
									if ( returned && jQuery.isFunction( returned.promise ) ) {
										returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );
									} else {
										newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
									}
								});
							} else {
								deferred[ handler ]( newDefer[ action ] );
							}
						});
					}).promise();
				},
				// Get a promise for this deferred
				// If obj is provided, the promise aspect is added to the object
				promise: function( obj ) {
					if ( obj == null ) {
						obj = promise;
					} else {
						for ( var key in promise ) {
							obj[ key ] = promise[ key ];
						}
					}
					return obj;
				}
			},
			deferred = promise.promise({}),
			key;

		for ( key in lists ) {
			deferred[ key ] = lists[ key ].fire;
			deferred[ key + "With" ] = lists[ key ].fireWith;
		}

		// Handle state
		deferred.done( function() {
			state = "resolved";
		}, failList.disable, progressList.lock ).fail( function() {
			state = "rejected";
		}, doneList.disable, progressList.lock );

		// Call given func if any
		if ( func ) {
			func.call( deferred, deferred );
		}

		// All done!
		return deferred;
	},

	// Deferred helper
	when: function( firstParam ) {
		var args = sliceDeferred.call( arguments, 0 ),
			i = 0,
			length = args.length,
			pValues = new Array( length ),
			count = length,
			pCount = length,
			deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?
				firstParam :
				jQuery.Deferred(),
			promise = deferred.promise();
		function resolveFunc( i ) {
			return function( value ) {
				args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
				if ( !( --count ) ) {
					deferred.resolveWith( deferred, args );
				}
			};
		}
		function progressFunc( i ) {
			return function( value ) {
				pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
				deferred.notifyWith( promise, pValues );
			};
		}
		if ( length > 1 ) {
			for ( ; i < length; i++ ) {
				if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {
					args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );
				} else {
					--count;
				}
			}
			if ( !count ) {
				deferred.resolveWith( deferred, args );
			}
		} else if ( deferred !== firstParam ) {
			deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
		}
		return promise;
	}
});




jQuery.support = (function() {

	var support,
		all,
		a,
		select,
		opt,
		input,
		marginDiv,
		fragment,
		tds,
		events,
		eventName,
		i,
		isSupported,
		div = document.createElement( "div" ),
		documentElement = document.documentElement;

	// Preliminary tests
	div.setAttribute("className", "t");
	div.innerHTML = "   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";

	all = div.getElementsByTagName( "*" );
	a = div.getElementsByTagName( "a" )[ 0 ];

	// Can't get basic test support
	if ( !all || !all.length || !a ) {
		return {};
	}

	// First batch of supports tests
	select = document.createElement( "select" );
	opt = select.appendChild( document.createElement("option") );
	input = div.getElementsByTagName( "input" )[ 0 ];

	support = {
		// IE strips leading whitespace when .innerHTML is used
		leadingWhitespace: ( div.firstChild.nodeType === 3 ),

		// Make sure that tbody elements aren't automatically inserted
		// IE will insert them into empty tables
		tbody: !div.getElementsByTagName("tbody").length,

		// Make sure that link elements get serialized correctly by innerHTML
		// This requires a wrapper element in IE
		htmlSerialize: !!div.getElementsByTagName("link").length,

		// Get the style information from getAttribute
		// (IE uses .cssText instead)
		style: /top/.test( a.getAttribute("style") ),

		// Make sure that URLs aren't manipulated
		// (IE normalizes it by default)
		hrefNormalized: ( a.getAttribute("href") === "/a" ),

		// Make sure that element opacity exists
		// (IE uses filter instead)
		// Use a regex to work around a WebKit issue. See #5145
		opacity: /^0.55/.test( a.style.opacity ),

		// Verify style float existence
		// (IE uses styleFloat instead of cssFloat)
		cssFloat: !!a.style.cssFloat,

		// Make sure that if no value is specified for a checkbox
		// that it defaults to "on".
		// (WebKit defaults to "" instead)
		checkOn: ( input.value === "on" ),

		// Make sure that a selected-by-default option has a working selected property.
		// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
		optSelected: opt.selected,

		// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
		getSetAttribute: div.className !== "t",

		// Tests for enctype support on a form(#6743)
		enctype: !!document.createElement("form").enctype,

		// Makes sure cloning an html5 element does not cause problems
		// Where outerHTML is undefined, this still works
		html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",

		// Will be defined later
		submitBubbles: true,
		changeBubbles: true,
		focusinBubbles: false,
		deleteExpando: true,
		noCloneEvent: true,
		inlineBlockNeedsLayout: false,
		shrinkWrapBlocks: false,
		reliableMarginRight: true
	};

	// Make sure checked status is properly cloned
	input.checked = true;
	support.noCloneChecked = input.cloneNode( true ).checked;

	// Make sure that the options inside disabled selects aren't marked as disabled
	// (WebKit marks them as disabled)
	select.disabled = true;
	support.optDisabled = !opt.disabled;

	// Test to see if it's possible to delete an expando from an element
	// Fails in Internet Explorer
	try {
		delete div.test;
	} catch( e ) {
		support.deleteExpando = false;
	}

	if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
		div.attachEvent( "onclick", function() {
			// Cloning a node shouldn't copy over any
			// bound event handlers (IE does this)
			support.noCloneEvent = false;
		});
		div.cloneNode( true ).fireEvent( "onclick" );
	}

	// Check if a radio maintains its value
	// after being appended to the DOM
	input = document.createElement("input");
	input.value = "t";
	input.setAttribute("type", "radio");
	support.radioValue = input.value === "t";

	input.setAttribute("checked", "checked");
	div.appendChild( input );
	fragment = document.createDocumentFragment();
	fragment.appendChild( div.lastChild );

	// WebKit doesn't clone checked state correctly in fragments
	support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;

	// Check if a disconnected checkbox will retain its checked
	// value of true after appended to the DOM (IE6/7)
	support.appendChecked = input.checked;

	fragment.removeChild( input );
	fragment.appendChild( div );

	div.innerHTML = "";

	// Check if div with explicit width and no margin-right incorrectly
	// gets computed margin-right based on width of container. For more
	// info see bug #3333
	// Fails in WebKit before Feb 2011 nightlies
	// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
	if ( window.getComputedStyle ) {
		marginDiv = document.createElement( "div" );
		marginDiv.style.width = "0";
		marginDiv.style.marginRight = "0";
		div.style.width = "2px";
		div.appendChild( marginDiv );
		support.reliableMarginRight =
			( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;
	}

	// Technique from Juriy Zaytsev
	// http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
	// We only care about the case where non-standard event systems
	// are used, namely in IE. Short-circuiting here helps us to
	// avoid an eval call (in setAttribute) which can cause CSP
	// to go haywire. See: https://developer.mozilla.org/en/Security/CSP
	if ( div.attachEvent ) {
		for( i in {
			submit: 1,
			change: 1,
			focusin: 1
		}) {
			eventName = "on" + i;
			isSupported = ( eventName in div );
			if ( !isSupported ) {
				div.setAttribute( eventName, "return;" );
				isSupported = ( typeof div[ eventName ] === "function" );
			}
			support[ i + "Bubbles" ] = isSupported;
		}
	}

	fragment.removeChild( div );

	// Null elements to avoid leaks in IE
	fragment = select = opt = marginDiv = div = input = null;

	// Run tests that need a body at doc ready
	jQuery(function() {
		var container, outer, inner, table, td, offsetSupport,
			conMarginTop, ptlm, vb, style, html,
			body = document.getElementsByTagName("body")[0];

		if ( !body ) {
			// Return for frameset docs that don't have a body
			return;
		}

		conMarginTop = 1;
		ptlm = "position:absolute;top:0;left:0;width:1px;height:1px;margin:0;";
		vb = "visibility:hidden;border:0;";
		style = "style='" + ptlm + "border:5px solid #000;padding:0;'";
		html = "<div " + style + "><div></div></div>" +
			"<table " + style + " cellpadding='0' cellspacing='0'>" +
			"<tr><td></td></tr></table>";

		container = document.createElement("div");
		container.style.cssText = vb + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px";
		body.insertBefore( container, body.firstChild );

		// Construct the test element
		div = document.createElement("div");
		container.appendChild( div );

		// Check if table cells still have offsetWidth/Height when they are set
		// to display:none and there are still other visible table cells in a
		// table row; if so, offsetWidth/Height are not reliable for use when
		// determining if an element has been hidden directly using
		// display:none (it is still safe to use offsets if a parent element is
		// hidden; don safety goggles and see bug #4512 for more information).
		// (only IE 8 fails this test)
		div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
		tds = div.getElementsByTagName( "td" );
		isSupported = ( tds[ 0 ].offsetHeight === 0 );

		tds[ 0 ].style.display = "";
		tds[ 1 ].style.display = "none";

		// Check if empty table cells still have offsetWidth/Height
		// (IE <= 8 fail this test)
		support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );

		// Figure out if the W3C box model works as expected
		div.innerHTML = "";
		div.style.width = div.style.paddingLeft = "1px";
		jQuery.boxModel = support.boxModel = div.offsetWidth === 2;

		if ( typeof div.style.zoom !== "undefined" ) {
			// Check if natively block-level elements act like inline-block
			// elements when setting their display to 'inline' and giving
			// them layout
			// (IE < 8 does this)
			div.style.display = "inline";
			div.style.zoom = 1;
			support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );

			// Check if elements with layout shrink-wrap their children
			// (IE 6 does this)
			div.style.display = "";
			div.innerHTML = "<div style='width:4px;'></div>";
			support.shrinkWrapBlocks = ( div.offsetWidth !== 2 );
		}

		div.style.cssText = ptlm + vb;
		div.innerHTML = html;

		outer = div.firstChild;
		inner = outer.firstChild;
		td = outer.nextSibling.firstChild.firstChild;

		offsetSupport = {
			doesNotAddBorder: ( inner.offsetTop !== 5 ),
			doesAddBorderForTableAndCells: ( td.offsetTop === 5 )
		};

		inner.style.position = "fixed";
		inner.style.top = "20px";

		// safari subtracts parent border width here which is 5px
		offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );
		inner.style.position = inner.style.top = "";

		outer.style.overflow = "hidden";
		outer.style.position = "relative";

		offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );
		offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );

		body.removeChild( container );
		div  = container = null;

		jQuery.extend( support, offsetSupport );
	});

	return support;
})();




var rbrace = /^(?:\{.*\}|\[.*\])$/,
	rmultiDash = /([A-Z])/g;

jQuery.extend({
	cache: {},

	// Please use with caution
	uuid: 0,

	// Unique for each copy of jQuery on the page
	// Non-digits removed to match rinlinejQuery
	expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),

	// The following elements throw uncatchable exceptions if you
	// attempt to add expando properties to them.
	noData: {
		"embed": true,
		// Ban all objects except for Flash (which handle expandos)
		"object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
		"applet": true
	},

	hasData: function( elem ) {
		elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
		return !!elem && !isEmptyDataObject( elem );
	},

	data: function( elem, name, data, pvt /* Internal Use Only */ ) {
		if ( !jQuery.acceptData( elem ) ) {
			return;
		}

		var privateCache, thisCache, ret,
			internalKey = jQuery.expando,
			getByName = typeof name === "string",

			// We have to handle DOM nodes and JS objects differently because IE6-7
			// can't GC object references properly across the DOM-JS boundary
			isNode = elem.nodeType,

			// Only DOM nodes need the global jQuery cache; JS object data is
			// attached directly to the object so GC can occur automatically
			cache = isNode ? jQuery.cache : elem,

			// Only defining an ID for JS objects if its cache already exists allows
			// the code to shortcut on the same path as a DOM node with no cache
			id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,
			isEvents = name === "events";

		// Avoid doing any more work than we need to when trying to get data on an
		// object that has no data at all
		if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {
			return;
		}

		if ( !id ) {
			// Only DOM nodes need a new unique ID for each element since their data
			// ends up in the global cache
			if ( isNode ) {
				elem[ internalKey ] = id = ++jQuery.uuid;
			} else {
				id = internalKey;
			}
		}

		if ( !cache[ id ] ) {
			cache[ id ] = {};

			// Avoids exposing jQuery metadata on plain JS objects when the object
			// is serialized using JSON.stringify
			if ( !isNode ) {
				cache[ id ].toJSON = jQuery.noop;
			}
		}

		// An object can be passed to jQuery.data instead of a key/value pair; this gets
		// shallow copied over onto the existing cache
		if ( typeof name === "object" || typeof name === "function" ) {
			if ( pvt ) {
				cache[ id ] = jQuery.extend( cache[ id ], name );
			} else {
				cache[ id ].data = jQuery.extend( cache[ id ].data, name );
			}
		}

		privateCache = thisCache = cache[ id ];

		// jQuery data() is stored in a separate object inside the object's internal data
		// cache in order to avoid key collisions between internal data and user-defined
		// data.
		if ( !pvt ) {
			if ( !thisCache.data ) {
				thisCache.data = {};
			}

			thisCache = thisCache.data;
		}

		if ( data !== undefined ) {
			thisCache[ jQuery.camelCase( name ) ] = data;
		}

		// Users should not attempt to inspect the internal events object using jQuery.data,
		// it is undocumented and subject to change. But does anyone listen? No.
		if ( isEvents && !thisCache[ name ] ) {
			return privateCache.events;
		}

		// Check for both converted-to-camel and non-converted data property names
		// If a data property was specified
		if ( getByName ) {

			// First Try to find as-is property data
			ret = thisCache[ name ];

			// Test for null|undefined property data
			if ( ret == null ) {

				// Try to find the camelCased property
				ret = thisCache[ jQuery.camelCase( name ) ];
			}
		} else {
			ret = thisCache;
		}

		return ret;
	},

	removeData: function( elem, name, pvt /* Internal Use Only */ ) {
		if ( !jQuery.acceptData( elem ) ) {
			return;
		}

		var thisCache, i, l,

			// Reference to internal data cache key
			internalKey = jQuery.expando,

			isNode = elem.nodeType,

			// See jQuery.data for more information
			cache = isNode ? jQuery.cache : elem,

			// See jQuery.data for more information
			id = isNode ? elem[ internalKey ] : internalKey;

		// If there is already no cache entry for this object, there is no
		// purpose in continuing
		if ( !cache[ id ] ) {
			return;
		}

		if ( name ) {

			thisCache = pvt ? cache[ id ] : cache[ id ].data;

			if ( thisCache ) {

				// Support array or space separated string names for data keys
				if ( !jQuery.isArray( name ) ) {

					// try the string as a key before any manipulation
					if ( name in thisCache ) {
						name = [ name ];
					} else {

						// split the camel cased version by spaces unless a key with the spaces exists
						name = jQuery.camelCase( name );
						if ( name in thisCache ) {
							name = [ name ];
						} else {
							name = name.split( " " );
						}
					}
				}

				for ( i = 0, l = name.length; i < l; i++ ) {
					delete thisCache[ name[i] ];
				}

				// If there is no data left in the cache, we want to continue
				// and let the cache object itself get destroyed
				if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
					return;
				}
			}
		}

		// See jQuery.data for more information
		if ( !pvt ) {
			delete cache[ id ].data;

			// Don't destroy the parent cache unless the internal data object
			// had been the only thing left in it
			if ( !isEmptyDataObject(cache[ id ]) ) {
				return;
			}
		}

		// Browsers that fail expando deletion also refuse to delete expandos on
		// the window, but it will allow it on all other JS objects; other browsers
		// don't care
		// Ensure that `cache` is not a window object #10080
		if ( jQuery.support.deleteExpando || !cache.setInterval ) {
			delete cache[ id ];
		} else {
			cache[ id ] = null;
		}

		// We destroyed the cache and need to eliminate the expando on the node to avoid
		// false lookups in the cache for entries that no longer exist
		if ( isNode ) {
			// IE does not allow us to delete expando properties from nodes,
			// nor does it have a removeAttribute function on Document nodes;
			// we must handle all of these cases
			if ( jQuery.support.deleteExpando ) {
				delete elem[ internalKey ];
			} else if ( elem.removeAttribute ) {
				elem.removeAttribute( internalKey );
			} else {
				elem[ internalKey ] = null;
			}
		}
	},

	// For internal use only.
	_data: function( elem, name, data ) {
		return jQuery.data( elem, name, data, true );
	},

	// A method for determining if a DOM node can handle the data expando
	acceptData: function( elem ) {
		if ( elem.nodeName ) {
			var match = jQuery.noData[ elem.nodeName.toLowerCase() ];

			if ( match ) {
				return !(match === true || elem.getAttribute("classid") !== match);
			}
		}

		return true;
	}
});

jQuery.fn.extend({
	data: function( key, value ) {
		var parts, attr, name,
			data = null;

		if ( typeof key === "undefined" ) {
			if ( this.length ) {
				data = jQuery.data( this[0] );

				if ( this[0].nodeType === 1 && !jQuery._data( this[0], "parsedAttrs" ) ) {
					attr = this[0].attributes;
					for ( var i = 0, l = attr.length; i < l; i++ ) {
						name = attr[i].name;

						if ( name.indexOf( "data-" ) === 0 ) {
							name = jQuery.camelCase( name.substring(5) );

							dataAttr( this[0], name, data[ name ] );
						}
					}
					jQuery._data( this[0], "parsedAttrs", true );
				}
			}

			return data;

		} else if ( typeof key === "object" ) {
			return this.each(function() {
				jQuery.data( this, key );
			});
		}

		parts = key.split(".");
		parts[1] = parts[1] ? "." + parts[1] : "";

		if ( value === undefined ) {
			data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);

			// Try to fetch any internally stored data first
			if ( data === undefined && this.length ) {
				data = jQuery.data( this[0], key );
				data = dataAttr( this[0], key, data );
			}

			return data === undefined && parts[1] ?
				this.data( parts[0] ) :
				data;

		} else {
			return this.each(function() {
				var self = jQuery( this ),
					args = [ parts[0], value ];

				self.triggerHandler( "setData" + parts[1] + "!", args );
				jQuery.data( this, key, value );
				self.triggerHandler( "changeData" + parts[1] + "!", args );
			});
		}
	},

	removeData: function( key ) {
		return this.each(function() {
			jQuery.removeData( this, key );
		});
	}
});

function dataAttr( elem, key, data ) {
	// If nothing was found internally, try to fetch any
	// data from the HTML5 data-* attribute
	if ( data === undefined && elem.nodeType === 1 ) {

		var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();

		data = elem.getAttribute( name );

		if ( typeof data === "string" ) {
			try {
				data = data === "true" ? true :
				data === "false" ? false :
				data === "null" ? null :
				jQuery.isNumeric( data ) ? parseFloat( data ) :
					rbrace.test( data ) ? jQuery.parseJSON( data ) :
					data;
			} catch( e ) {}

			// Make sure we set the data so it isn't changed later
			jQuery.data( elem, key, data );

		} else {
			data = undefined;
		}
	}

	return data;
}

// checks a cache object for emptiness
function isEmptyDataObject( obj ) {
	for ( var name in obj ) {

		// if the public data object is empty, the private is still empty
		if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
			continue;
		}
		if ( name !== "toJSON" ) {
			return false;
		}
	}

	return true;
}




function handleQueueMarkDefer( elem, type, src ) {
	var deferDataKey = type + "defer",
		queueDataKey = type + "queue",
		markDataKey = type + "mark",
		defer = jQuery._data( elem, deferDataKey );
	if ( defer &&
		( src === "queue" || !jQuery._data(elem, queueDataKey) ) &&
		( src === "mark" || !jQuery._data(elem, markDataKey) ) ) {
		// Give room for hard-coded callbacks to fire first
		// and eventually mark/queue something else on the element
		setTimeout( function() {
			if ( !jQuery._data( elem, queueDataKey ) &&
				!jQuery._data( elem, markDataKey ) ) {
				jQuery.removeData( elem, deferDataKey, true );
				defer.fire();
			}
		}, 0 );
	}
}

jQuery.extend({

	_mark: function( elem, type ) {
		if ( elem ) {
			type = ( type || "fx" ) + "mark";
			jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );
		}
	},

	_unmark: function( force, elem, type ) {
		if ( force !== true ) {
			type = elem;
			elem = force;
			force = false;
		}
		if ( elem ) {
			type = type || "fx";
			var key = type + "mark",
				count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );
			if ( count ) {
				jQuery._data( elem, key, count );
			} else {
				jQuery.removeData( elem, key, true );
				handleQueueMarkDefer( elem, type, "mark" );
			}
		}
	},

	queue: function( elem, type, data ) {
		var q;
		if ( elem ) {
			type = ( type || "fx" ) + "queue";
			q = jQuery._data( elem, type );

			// Speed up dequeue by getting out quickly if this is just a lookup
			if ( data ) {
				if ( !q || jQuery.isArray(data) ) {
					q = jQuery._data( elem, type, jQuery.makeArray(data) );
				} else {
					q.push( data );
				}
			}
			return q || [];
		}
	},

	dequeue: function( elem, type ) {
		type = type || "fx";

		var queue = jQuery.queue( elem, type ),
			fn = queue.shift(),
			hooks = {};

		// If the fx queue is dequeued, always remove the progress sentinel
		if ( fn === "inprogress" ) {
			fn = queue.shift();
		}

		if ( fn ) {
			// Add a progress sentinel to prevent the fx queue from being
			// automatically dequeued
			if ( type === "fx" ) {
				queue.unshift( "inprogress" );
			}

			jQuery._data( elem, type + ".run", hooks );
			fn.call( elem, function() {
				jQuery.dequeue( elem, type );
			}, hooks );
		}

		if ( !queue.length ) {
			jQuery.removeData( elem, type + "queue " + type + ".run", true );
			handleQueueMarkDefer( elem, type, "queue" );
		}
	}
});

jQuery.fn.extend({
	queue: function( type, data ) {
		if ( typeof type !== "string" ) {
			data = type;
			type = "fx";
		}

		if ( data === undefined ) {
			return jQuery.queue( this[0], type );
		}
		return this.each(function() {
			var queue = jQuery.queue( this, type, data );

			if ( type === "fx" && queue[0] !== "inprogress" ) {
				jQuery.dequeue( this, type );
			}
		});
	},
	dequeue: function( type ) {
		return this.each(function() {
			jQuery.dequeue( this, type );
		});
	},
	// Based off of the plugin by Clint Helfers, with permission.
	// http://blindsignals.com/index.php/2009/07/jquery-delay/
	delay: function( time, type ) {
		time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
		type = type || "fx";

		return this.queue( type, function( next, hooks ) {
			var timeout = setTimeout( next, time );
			hooks.stop = function() {
				clearTimeout( timeout );
			};
		});
	},
	clearQueue: function( type ) {
		return this.queue( type || "fx", [] );
	},
	// Get a promise resolved when queues of a certain type
	// are emptied (fx is the type by default)
	promise: function( type, object ) {
		if ( typeof type !== "string" ) {
			object = type;
			type = undefined;
		}
		type = type || "fx";
		var defer = jQuery.Deferred(),
			elements = this,
			i = elements.length,
			count = 1,
			deferDataKey = type + "defer",
			queueDataKey = type + "queue",
			markDataKey = type + "mark",
			tmp;
		function resolve() {
			if ( !( --count ) ) {
				defer.resolveWith( elements, [ elements ] );
			}
		}
		while( i-- ) {
			if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
					( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||
						jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
					jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) {
				count++;
				tmp.add( resolve );
			}
		}
		resolve();
		return defer.promise();
	}
});




var rclass = /[\n\t\r]/g,
	rspace = /\s+/,
	rreturn = /\r/g,
	rtype = /^(?:button|input)$/i,
	rfocusable = /^(?:button|input|object|select|textarea)$/i,
	rclickable = /^a(?:rea)?$/i,
	rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
	getSetAttribute = jQuery.support.getSetAttribute,
	nodeHook, boolHook, fixSpecified;

jQuery.fn.extend({
	attr: function( name, value ) {
		return jQuery.access( this, name, value, true, jQuery.attr );
	},

	removeAttr: function( name ) {
		return this.each(function() {
			jQuery.removeAttr( this, name );
		});
	},

	prop: function( name, value ) {
		return jQuery.access( this, name, value, true, jQuery.prop );
	},

	removeProp: function( name ) {
		name = jQuery.propFix[ name ] || name;
		return this.each(function() {
			// try/catch handles cases where IE balks (such as removing a property on window)
			try {
				this[ name ] = undefined;
				delete this[ name ];
			} catch( e ) {}
		});
	},

	addClass: function( value ) {
		var classNames, i, l, elem,
			setClass, c, cl;

		if ( jQuery.isFunction( value ) ) {
			return this.each(function( j ) {
				jQuery( this ).addClass( value.call(this, j, this.className) );
			});
		}

		if ( value && typeof value === "string" ) {
			classNames = value.split( rspace );

			for ( i = 0, l = this.length; i < l; i++ ) {
				elem = this[ i ];

				if ( elem.nodeType === 1 ) {
					if ( !elem.className && classNames.length === 1 ) {
						elem.className = value;

					} else {
						setClass = " " + elem.className + " ";

						for ( c = 0, cl = classNames.length; c < cl; c++ ) {
							if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
								setClass += classNames[ c ] + " ";
							}
						}
						elem.className = jQuery.trim( setClass );
					}
				}
			}
		}

		return this;
	},

	removeClass: function( value ) {
		var classNames, i, l, elem, className, c, cl;

		if ( jQuery.isFunction( value ) ) {
			return this.each(function( j ) {
				jQuery( this ).removeClass( value.call(this, j, this.className) );
			});
		}

		if ( (value && typeof value === "string") || value === undefined ) {
			classNames = ( value || "" ).split( rspace );

			for ( i = 0, l = this.length; i < l; i++ ) {
				elem = this[ i ];

				if ( elem.nodeType === 1 && elem.className ) {
					if ( value ) {
						className = (" " + elem.className + " ").replace( rclass, " " );
						for ( c = 0, cl = classNames.length; c < cl; c++ ) {
							className = className.replace(" " + classNames[ c ] + " ", " ");
						}
						elem.className = jQuery.trim( className );

					} else {
						elem.className = "";
					}
				}
			}
		}

		return this;
	},

	toggleClass: function( value, stateVal ) {
		var type = typeof value,
			isBool = typeof stateVal === "boolean";

		if ( jQuery.isFunction( value ) ) {
			return this.each(function( i ) {
				jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
			});
		}

		return this.each(function() {
			if ( type === "string" ) {
				// toggle individual class names
				var className,
					i = 0,
					self = jQuery( this ),
					state = stateVal,
					classNames = value.split( rspace );

				while ( (className = classNames[ i++ ]) ) {
					// check each className given, space seperated list
					state = isBool ? state : !self.hasClass( className );
					self[ state ? "addClass" : "removeClass" ]( className );
				}

			} else if ( type === "undefined" || type === "boolean" ) {
				if ( this.className ) {
					// store className if set
					jQuery._data( this, "__className__", this.className );
				}

				// toggle whole className
				this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
			}
		});
	},

	hasClass: function( selector ) {
		var className = " " + selector + " ",
			i = 0,
			l = this.length;
		for ( ; i < l; i++ ) {
			if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
				return true;
			}
		}

		return false;
	},

	val: function( value ) {
		var hooks, ret, isFunction,
			elem = this[0];

		if ( !arguments.length ) {
			if ( elem ) {
				hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];

				if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
					return ret;
				}

				ret = elem.value;

				return typeof ret === "string" ?
					// handle most common string cases
					ret.replace(rreturn, "") :
					// handle cases where value is null/undef or number
					ret == null ? "" : ret;
			}

			return;
		}

		isFunction = jQuery.isFunction( value );

		return this.each(function( i ) {
			var self = jQuery(this), val;

			if ( this.nodeType !== 1 ) {
				return;
			}

			if ( isFunction ) {
				val = value.call( this, i, self.val() );
			} else {
				val = value;
			}

			// Treat null/undefined as ""; convert numbers to string
			if ( val == null ) {
				val = "";
			} else if ( typeof val === "number" ) {
				val += "";
			} else if ( jQuery.isArray( val ) ) {
				val = jQuery.map(val, function ( value ) {
					return value == null ? "" : value + "";
				});
			}

			hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];

			// If set returns undefined, fall back to normal setting
			if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
				this.value = val;
			}
		});
	}
});

jQuery.extend({
	valHooks: {
		option: {
			get: function( elem ) {
				// attributes.value is undefined in Blackberry 4.7 but
				// uses .value. See #6932
				var val = elem.attributes.value;
				return !val || val.specified ? elem.value : elem.text;
			}
		},
		select: {
			get: function( elem ) {
				var value, i, max, option,
					index = elem.selectedIndex,
					values = [],
					options = elem.options,
					one = elem.type === "select-one";

				// Nothing was selected
				if ( index < 0 ) {
					return null;
				}

				// Loop through all the selected options
				i = one ? index : 0;
				max = one ? index + 1 : options.length;
				for ( ; i < max; i++ ) {
					option = options[ i ];

					// Don't return options that are disabled or in a disabled optgroup
					if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
							(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {

						// Get the specific value for the option
						value = jQuery( option ).val();

						// We don't need an array for one selects
						if ( one ) {
							return value;
						}

						// Multi-Selects return an array
						values.push( value );
					}
				}

				// Fixes Bug #2551 -- select.val() broken in IE after form.reset()
				if ( one && !values.length && options.length ) {
					return jQuery( options[ index ] ).val();
				}

				return values;
			},

			set: function( elem, value ) {
				var values = jQuery.makeArray( value );

				jQuery(elem).find("option").each(function() {
					this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
				});

				if ( !values.length ) {
					elem.selectedIndex = -1;
				}
				return values;
			}
		}
	},

	attrFn: {
		val: true,
		css: true,
		html: true,
		text: true,
		data: true,
		width: true,
		height: true,
		offset: true
	},

	attr: function( elem, name, value, pass ) {
		var ret, hooks, notxml,
			nType = elem.nodeType;

		// don't get/set attributes on text, comment and attribute nodes
		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
			return;
		}

		if ( pass && name in jQuery.attrFn ) {
			return jQuery( elem )[ name ]( value );
		}

		// Fallback to prop when attributes are not supported
		if ( typeof elem.getAttribute === "undefined" ) {
			return jQuery.prop( elem, name, value );
		}

		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );

		// All attributes are lowercase
		// Grab necessary hook if one is defined
		if ( notxml ) {
			name = name.toLowerCase();
			hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
		}

		if ( value !== undefined ) {

			if ( value === null ) {
				jQuery.removeAttr( elem, name );
				return;

			} else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
				return ret;

			} else {
				elem.setAttribute( name, "" + value );
				return value;
			}

		} else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
			return ret;

		} else {

			ret = elem.getAttribute( name );

			// Non-existent attributes return null, we normalize to undefined
			return ret === null ?
				undefined :
				ret;
		}
	},

	removeAttr: function( elem, value ) {
		var propName, attrNames, name, l,
			i = 0;

		if ( value && elem.nodeType === 1 ) {
			attrNames = value.toLowerCase().split( rspace );
			l = attrNames.length;

			for ( ; i < l; i++ ) {
				name = attrNames[ i ];

				if ( name ) {
					propName = jQuery.propFix[ name ] || name;

					// See #9699 for explanation of this approach (setting first, then removal)
					jQuery.attr( elem, name, "" );
					elem.removeAttribute( getSetAttribute ? name : propName );

					// Set corresponding property to false for boolean attributes
					if ( rboolean.test( name ) && propName in elem ) {
						elem[ propName ] = false;
					}
				}
			}
		}
	},

	attrHooks: {
		type: {
			set: function( elem, value ) {
				// We can't allow the type property to be changed (since it causes problems in IE)
				if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
					jQuery.error( "type property can't be changed" );
				} else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
					// Setting the type on a radio button after the value resets the value in IE6-9
					// Reset value to it's default in case type is set after value
					// This is for element creation
					var val = elem.value;
					elem.setAttribute( "type", value );
					if ( val ) {
						elem.value = val;
					}
					return value;
				}
			}
		},
		// Use the value property for back compat
		// Use the nodeHook for button elements in IE6/7 (#1954)
		value: {
			get: function( elem, name ) {
				if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
					return nodeHook.get( elem, name );
				}
				return name in elem ?
					elem.value :
					null;
			},
			set: function( elem, value, name ) {
				if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
					return nodeHook.set( elem, value, name );
				}
				// Does not return so that setAttribute is also used
				elem.value = value;
			}
		}
	},

	propFix: {
		tabindex: "tabIndex",
		readonly: "readOnly",
		"for": "htmlFor",
		"class": "className",
		maxlength: "maxLength",
		cellspacing: "cellSpacing",
		cellpadding: "cellPadding",
		rowspan: "rowSpan",
		colspan: "colSpan",
		usemap: "useMap",
		frameborder: "frameBorder",
		contenteditable: "contentEditable"
	},

	prop: function( elem, name, value ) {
		var ret, hooks, notxml,
			nType = elem.nodeType;

		// don't get/set properties on text, comment and attribute nodes
		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
			return;
		}

		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );

		if ( notxml ) {
			// Fix name and attach hooks
			name = jQuery.propFix[ name ] || name;
			hooks = jQuery.propHooks[ name ];
		}

		if ( value !== undefined ) {
			if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
				return ret;

			} else {
				return ( elem[ name ] = value );
			}

		} else {
			if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
				return ret;

			} else {
				return elem[ name ];
			}
		}
	},

	propHooks: {
		tabIndex: {
			get: function( elem ) {
				// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
				var attributeNode = elem.getAttributeNode("tabindex");

				return attributeNode && attributeNode.specified ?
					parseInt( attributeNode.value, 10 ) :
					rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
						0 :
						undefined;
			}
		}
	}
});

// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)
jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;

// Hook for boolean attributes
boolHook = {
	get: function( elem, name ) {
		// Align boolean attributes with corresponding properties
		// Fall back to attribute presence where some booleans are not supported
		var attrNode,
			property = jQuery.prop( elem, name );
		return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
			name.toLowerCase() :
			undefined;
	},
	set: function( elem, value, name ) {
		var propName;
		if ( value === false ) {
			// Remove boolean attributes when set to false
			jQuery.removeAttr( elem, name );
		} else {
			// value is true since we know at this point it's type boolean and not false
			// Set boolean attributes to the same name and set the DOM property
			propName = jQuery.propFix[ name ] || name;
			if ( propName in elem ) {
				// Only set the IDL specifically if it already exists on the element
				elem[ propName ] = true;
			}

			elem.setAttribute( name, name.toLowerCase() );
		}
		return name;
	}
};

// IE6/7 do not support getting/setting some attributes with get/setAttribute
if ( !getSetAttribute ) {

	fixSpecified = {
		name: true,
		id: true
	};

	// Use this for any attribute in IE6/7
	// This fixes almost every IE6/7 issue
	nodeHook = jQuery.valHooks.button = {
		get: function( elem, name ) {
			var ret;
			ret = elem.getAttributeNode( name );
			return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ?
				ret.nodeValue :
				undefined;
		},
		set: function( elem, value, name ) {
			// Set the existing or create a new attribute node
			var ret = elem.getAttributeNode( name );
			if ( !ret ) {
				ret = document.createAttribute( name );
				elem.setAttributeNode( ret );
			}
			return ( ret.nodeValue = value + "" );
		}
	};

	// Apply the nodeHook to tabindex
	jQuery.attrHooks.tabindex.set = nodeHook.set;

	// Set width and height to auto instead of 0 on empty string( Bug #8150 )
	// This is for removals
	jQuery.each([ "width", "height" ], function( i, name ) {
		jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
			set: function( elem, value ) {
				if ( value === "" ) {
					elem.setAttribute( name, "auto" );
					return value;
				}
			}
		});
	});

	// Set contenteditable to false on removals(#10429)
	// Setting to empty string throws an error as an invalid value
	jQuery.attrHooks.contenteditable = {
		get: nodeHook.get,
		set: function( elem, value, name ) {
			if ( value === "" ) {
				value = "false";
			}
			nodeHook.set( elem, value, name );
		}
	};
}


// Some attributes require a special call on IE
if ( !jQuery.support.hrefNormalized ) {
	jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
		jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
			get: function( elem ) {
				var ret = elem.getAttribute( name, 2 );
				return ret === null ? undefined : ret;
			}
		});
	});
}

if ( !jQuery.support.style ) {
	jQuery.attrHooks.style = {
		get: function( elem ) {
			// Return undefined in the case of empty string
			// Normalize to lowercase since IE uppercases css property names
			return elem.style.cssText.toLowerCase() || undefined;
		},
		set: function( elem, value ) {
			return ( elem.style.cssText = "" + value );
		}
	};
}

// Safari mis-reports the default selected property of an option
// Accessing the parent's selectedIndex property fixes it
if ( !jQuery.support.optSelected ) {
	jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
		get: function( elem ) {
			var parent = elem.parentNode;

			if ( parent ) {
				parent.selectedIndex;

				// Make sure that it also works with optgroups, see #5701
				if ( parent.parentNode ) {
					parent.parentNode.selectedIndex;
				}
			}
			return null;
		}
	});
}

// IE6/7 call enctype encoding
if ( !jQuery.support.enctype ) {
	jQuery.propFix.enctype = "encoding";
}

// Radios and checkboxes getter/setter
if ( !jQuery.support.checkOn ) {
	jQuery.each([ "radio", "checkbox" ], function() {
		jQuery.valHooks[ this ] = {
			get: function( elem ) {
				// Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
				return elem.getAttribute("value") === null ? "on" : elem.value;
			}
		};
	});
}
jQuery.each([ "radio", "checkbox" ], function() {
	jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
		set: function( elem, value ) {
			if ( jQuery.isArray( value ) ) {
				return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
			}
		}
	});
});




var rformElems = /^(?:textarea|input|select)$/i,
	rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/,
	rhoverHack = /\bhover(\.\S+)?\b/,
	rkeyEvent = /^key/,
	rmouseEvent = /^(?:mouse|contextmenu)|click/,
	rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
	rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,
	quickParse = function( selector ) {
		var quick = rquickIs.exec( selector );
		if ( quick ) {
			//   0  1    2   3
			// [ _, tag, id, class ]
			quick[1] = ( quick[1] || "" ).toLowerCase();
			quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" );
		}
		return quick;
	},
	quickIs = function( elem, m ) {
		var attrs = elem.attributes || {};
		return (
			(!m[1] || elem.nodeName.toLowerCase() === m[1]) &&
			(!m[2] || (attrs.id || {}).value === m[2]) &&
			(!m[3] || m[3].test( (attrs[ "class" ] || {}).value ))
		);
	},
	hoverHack = function( events ) {
		return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
	};

/*
 * Helper functions for managing events -- not part of the public interface.
 * Props to Dean Edwards' addEvent library for many of the ideas.
 */
jQuery.event = {

	add: function( elem, types, handler, data, selector ) {

		var elemData, eventHandle, events,
			t, tns, type, namespaces, handleObj,
			handleObjIn, quick, handlers, special;

		// Don't attach events to noData or text/comment nodes (allow plain objects tho)
		if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {
			return;
		}

		// Caller can pass in an object of custom data in lieu of the handler
		if ( handler.handler ) {
			handleObjIn = handler;
			handler = handleObjIn.handler;
		}

		// Make sure that the handler has a unique ID, used to find/remove it later
		if ( !handler.guid ) {
			handler.guid = jQuery.guid++;
		}

		// Init the element's event structure and main handler, if this is the first
		events = elemData.events;
		if ( !events ) {
			elemData.events = events = {};
		}
		eventHandle = elemData.handle;
		if ( !eventHandle ) {
			elemData.handle = eventHandle = function( e ) {
				// Discard the second event of a jQuery.event.trigger() and
				// when an event is called after a page has unloaded
				return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
					jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
					undefined;
			};
			// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
			eventHandle.elem = elem;
		}

		// Handle multiple events separated by a space
		// jQuery(...).bind("mouseover mouseout", fn);
		types = jQuery.trim( hoverHack(types) ).split( " " );
		for ( t = 0; t < types.length; t++ ) {

			tns = rtypenamespace.exec( types[t] ) || [];
			type = tns[1];
			namespaces = ( tns[2] || "" ).split( "." ).sort();

			// If event changes its type, use the special event handlers for the changed type
			special = jQuery.event.special[ type ] || {};

			// If selector defined, determine special event api type, otherwise given type
			type = ( selector ? special.delegateType : special.bindType ) || type;

			// Update special based on newly reset type
			special = jQuery.event.special[ type ] || {};

			// handleObj is passed to all event handlers
			handleObj = jQuery.extend({
				type: type,
				origType: tns[1],
				data: data,
				handler: handler,
				guid: handler.guid,
				selector: selector,
				quick: quickParse( selector ),
				namespace: namespaces.join(".")
			}, handleObjIn );

			// Init the event handler queue if we're the first
			handlers = events[ type ];
			if ( !handlers ) {
				handlers = events[ type ] = [];
				handlers.delegateCount = 0;

				// Only use addEventListener/attachEvent if the special events handler returns false
				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
					// Bind the global event handler to the element
					if ( elem.addEventListener ) {
						elem.addEventListener( type, eventHandle, false );

					} else if ( elem.attachEvent ) {
						elem.attachEvent( "on" + type, eventHandle );
					}
				}
			}

			if ( special.add ) {
				special.add.call( elem, handleObj );

				if ( !handleObj.handler.guid ) {
					handleObj.handler.guid = handler.guid;
				}
			}

			// Add to the element's handler list, delegates in front
			if ( selector ) {
				handlers.splice( handlers.delegateCount++, 0, handleObj );
			} else {
				handlers.push( handleObj );
			}

			// Keep track of which events have ever been used, for event optimization
			jQuery.event.global[ type ] = true;
		}

		// Nullify elem to prevent memory leaks in IE
		elem = null;
	},

	global: {},

	// Detach an event or set of events from an element
	remove: function( elem, types, handler, selector, mappedTypes ) {

		var elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
			t, tns, type, origType, namespaces, origCount,
			j, events, special, handle, eventType, handleObj;

		if ( !elemData || !(events = elemData.events) ) {
			return;
		}

		// Once for each type.namespace in types; type may be omitted
		types = jQuery.trim( hoverHack( types || "" ) ).split(" ");
		for ( t = 0; t < types.length; t++ ) {
			tns = rtypenamespace.exec( types[t] ) || [];
			type = origType = tns[1];
			namespaces = tns[2];

			// Unbind all events (on this namespace, if provided) for the element
			if ( !type ) {
				for ( type in events ) {
					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
				}
				continue;
			}

			special = jQuery.event.special[ type ] || {};
			type = ( selector? special.delegateType : special.bindType ) || type;
			eventType = events[ type ] || [];
			origCount = eventType.length;
			namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null;

			// Remove matching events
			for ( j = 0; j < eventType.length; j++ ) {
				handleObj = eventType[ j ];

				if ( ( mappedTypes || origType === handleObj.origType ) &&
					 ( !handler || handler.guid === handleObj.guid ) &&
					 ( !namespaces || namespaces.test( handleObj.namespace ) ) &&
					 ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
					eventType.splice( j--, 1 );

					if ( handleObj.selector ) {
						eventType.delegateCount--;
					}
					if ( special.remove ) {
						special.remove.call( elem, handleObj );
					}
				}
			}

			// Remove generic event handler if we removed something and no more handlers exist
			// (avoids potential for endless recursion during removal of special event handlers)
			if ( eventType.length === 0 && origCount !== eventType.length ) {
				if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
					jQuery.removeEvent( elem, type, elemData.handle );
				}

				delete events[ type ];
			}
		}

		// Remove the expando if it's no longer used
		if ( jQuery.isEmptyObject( events ) ) {
			handle = elemData.handle;
			if ( handle ) {
				handle.elem = null;
			}

			// removeData also checks for emptiness and clears the expando if empty
			// so use it instead of delete
			jQuery.removeData( elem, [ "events", "handle" ], true );
		}
	},

	// Events that are safe to short-circuit if no handlers are attached.
	// Native DOM events should not be added, they may have inline handlers.
	customEvent: {
		"getData": true,
		"setData": true,
		"changeData": true
	},

	trigger: function( event, data, elem, onlyHandlers ) {
		// Don't do events on text and comment nodes
		if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {
			return;
		}

		// Event object or event type
		var type = event.type || event,
			namespaces = [],
			cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;

		// focus/blur morphs to focusin/out; ensure we're not firing them right now
		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
			return;
		}

		if ( type.indexOf( "!" ) >= 0 ) {
			// Exclusive events trigger only for the exact event (no namespaces)
			type = type.slice(0, -1);
			exclusive = true;
		}

		if ( type.indexOf( "." ) >= 0 ) {
			// Namespaced trigger; create a regexp to match event type in handle()
			namespaces = type.split(".");
			type = namespaces.shift();
			namespaces.sort();
		}

		if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
			// No jQuery handlers for this event type, and it can't have inline handlers
			return;
		}

		// Caller can pass in an Event, Object, or just an event type string
		event = typeof event === "object" ?
			// jQuery.Event object
			event[ jQuery.expando ] ? event :
			// Object literal
			new jQuery.Event( type, event ) :
			// Just the event type (string)
			new jQuery.Event( type );

		event.type = type;
		event.isTrigger = true;
		event.exclusive = exclusive;
		event.namespace = namespaces.join( "." );
		event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
		ontype = type.indexOf( ":" ) < 0 ? "on" + type : "";

		// Handle a global trigger
		if ( !elem ) {

			// TODO: Stop taunting the data cache; remove global events and always attach to document
			cache = jQuery.cache;
			for ( i in cache ) {
				if ( cache[ i ].events && cache[ i ].events[ type ] ) {
					jQuery.event.trigger( event, data, cache[ i ].handle.elem, true );
				}
			}
			return;
		}

		// Clean up the event in case it is being reused
		event.result = undefined;
		if ( !event.target ) {
			event.target = elem;
		}

		// Clone any incoming data and prepend the event, creating the handler arg list
		data = data != null ? jQuery.makeArray( data ) : [];
		data.unshift( event );

		// Allow special events to draw outside the lines
		special = jQuery.event.special[ type ] || {};
		if ( special.trigger && special.trigger.apply( elem, data ) === false ) {
			return;
		}

		// Determine event propagation path in advance, per W3C events spec (#9951)
		// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
		eventPath = [[ elem, special.bindType || type ]];
		if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {

			bubbleType = special.delegateType || type;
			cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;
			old = null;
			for ( ; cur; cur = cur.parentNode ) {
				eventPath.push([ cur, bubbleType ]);
				old = cur;
			}

			// Only add window if we got to document (e.g., not plain obj or detached DOM)
			if ( old && old === elem.ownerDocument ) {
				eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);
			}
		}

		// Fire handlers on the event path
		for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {

			cur = eventPath[i][0];
			event.type = eventPath[i][1];

			handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
			if ( handle ) {
				handle.apply( cur, data );
			}
			// Note that this is a bare JS function and not a jQuery handler
			handle = ontype && cur[ ontype ];
			if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {
				event.preventDefault();
			}
		}
		event.type = type;

		// If nobody prevented the default action, do it now
		if ( !onlyHandlers && !event.isDefaultPrevented() ) {

			if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
				!(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {

				// Call a native DOM method on the target with the same name name as the event.
				// Can't use an .isFunction() check here because IE6/7 fails that test.
				// Don't do default actions on window, that's where global variables be (#6170)
				// IE<9 dies on focus/blur to hidden element (#1486)
				if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {

					// Don't re-trigger an onFOO event when we call its FOO() method
					old = elem[ ontype ];

					if ( old ) {
						elem[ ontype ] = null;
					}

					// Prevent re-triggering of the same event, since we already bubbled it above
					jQuery.event.triggered = type;
					elem[ type ]();
					jQuery.event.triggered = undefined;

					if ( old ) {
						elem[ ontype ] = old;
					}
				}
			}
		}

		return event.result;
	},

	dispatch: function( event ) {

		// Make a writable jQuery.Event from the native event object
		event = jQuery.event.fix( event || window.event );

		var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []),
			delegateCount = handlers.delegateCount,
			args = [].slice.call( arguments, 0 ),
			run_all = !event.exclusive && !event.namespace,
			handlerQueue = [],
			i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;

		// Use the fix-ed jQuery.Event rather than the (read-only) native event
		args[0] = event;
		event.delegateTarget = this;

		// Determine handlers that should run if there are delegated events
		// Avoid disabled elements in IE (#6911) and non-left-click bubbling in Firefox (#3861)
		if ( delegateCount && !event.target.disabled && !(event.button && event.type === "click") ) {

			// Pregenerate a single jQuery object for reuse with .is()
			jqcur = jQuery(this);
			jqcur.context = this.ownerDocument || this;

			for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {
				selMatch = {};
				matches = [];
				jqcur[0] = cur;
				for ( i = 0; i < delegateCount; i++ ) {
					handleObj = handlers[ i ];
					sel = handleObj.selector;

					if ( selMatch[ sel ] === undefined ) {
						selMatch[ sel ] = (
							handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )
						);
					}
					if ( selMatch[ sel ] ) {
						matches.push( handleObj );
					}
				}
				if ( matches.length ) {
					handlerQueue.push({ elem: cur, matches: matches });
				}
			}
		}

		// Add the remaining (directly-bound) handlers
		if ( handlers.length > delegateCount ) {
			handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });
		}

		// Run delegates first; they may want to stop propagation beneath us
		for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {
			matched = handlerQueue[ i ];
			event.currentTarget = matched.elem;

			for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {
				handleObj = matched.matches[ j ];

				// Triggered event must either 1) be non-exclusive and have no namespace, or
				// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
				if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {

					event.data = handleObj.data;
					event.handleObj = handleObj;

					ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
							.apply( matched.elem, args );

					if ( ret !== undefined ) {
						event.result = ret;
						if ( ret === false ) {
							event.preventDefault();
							event.stopPropagation();
						}
					}
				}
			}
		}

		return event.result;
	},

	// Includes some event props shared by KeyEvent and MouseEvent
	// *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***
	props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),

	fixHooks: {},

	keyHooks: {
		props: "char charCode key keyCode".split(" "),
		filter: function( event, original ) {

			// Add which for key events
			if ( event.which == null ) {
				event.which = original.charCode != null ? original.charCode : original.keyCode;
			}

			return event;
		}
	},

	mouseHooks: {
		props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
		filter: function( event, original ) {
			var eventDoc, doc, body,
				button = original.button,
				fromElement = original.fromElement;

			// Calculate pageX/Y if missing and clientX/Y available
			if ( event.pageX == null && original.clientX != null ) {
				eventDoc = event.target.ownerDocument || document;
				doc = eventDoc.documentElement;
				body = eventDoc.body;

				event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
				event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
			}

			// Add relatedTarget, if necessary
			if ( !event.relatedTarget && fromElement ) {
				event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
			}

			// Add which for click: 1 === left; 2 === middle; 3 === right
			// Note: button is not normalized, so don't use it
			if ( !event.which && button !== undefined ) {
				event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
			}

			return event;
		}
	},

	fix: function( event ) {
		if ( event[ jQuery.expando ] ) {
			return event;
		}

		// Create a writable copy of the event object and normalize some properties
		var i, prop,
			originalEvent = event,
			fixHook = jQuery.event.fixHooks[ event.type ] || {},
			copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;

		event = jQuery.Event( originalEvent );

		for ( i = copy.length; i; ) {
			prop = copy[ --i ];
			event[ prop ] = originalEvent[ prop ];
		}

		// Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)
		if ( !event.target ) {
			event.target = originalEvent.srcElement || document;
		}

		// Target should not be a text node (#504, Safari)
		if ( event.target.nodeType === 3 ) {
			event.target = event.target.parentNode;
		}

		// For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)
		if ( event.metaKey === undefined ) {
			event.metaKey = event.ctrlKey;
		}

		return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
	},

	special: {
		ready: {
			// Make sure the ready event is setup
			setup: jQuery.bindReady
		},

		load: {
			// Prevent triggered image.load events from bubbling to window.load
			noBubble: true
		},

		focus: {
			delegateType: "focusin"
		},
		blur: {
			delegateType: "focusout"
		},

		beforeunload: {
			setup: function( data, namespaces, eventHandle ) {
				// We only want to do this special case on windows
				if ( jQuery.isWindow( this ) ) {
					this.onbeforeunload = eventHandle;
				}
			},

			teardown: function( namespaces, eventHandle ) {
				if ( this.onbeforeunload === eventHandle ) {
					this.onbeforeunload = null;
				}
			}
		}
	},

	simulate: function( type, elem, event, bubble ) {
		// Piggyback on a donor event to simulate a different one.
		// Fake originalEvent to avoid donor's stopPropagation, but if the
		// simulated event prevents default then we do the same on the donor.
		var e = jQuery.extend(
			new jQuery.Event(),
			event,
			{ type: type,
				isSimulated: true,
				originalEvent: {}
			}
		);
		if ( bubble ) {
			jQuery.event.trigger( e, null, elem );
		} else {
			jQuery.event.dispatch.call( elem, e );
		}
		if ( e.isDefaultPrevented() ) {
			event.preventDefault();
		}
	}
};

// Some plugins are using, but it's undocumented/deprecated and will be removed.
// The 1.7 special event interface should provide all the hooks needed now.
jQuery.event.handle = jQuery.event.dispatch;

jQuery.removeEvent = document.removeEventListener ?
	function( elem, type, handle ) {
		if ( elem.removeEventListener ) {
			elem.removeEventListener( type, handle, false );
		}
	} :
	function( elem, type, handle ) {
		if ( elem.detachEvent ) {
			elem.detachEvent( "on" + type, handle );
		}
	};

jQuery.Event = function( src, props ) {
	// Allow instantiation without the 'new' keyword
	if ( !(this instanceof jQuery.Event) ) {
		return new jQuery.Event( src, props );
	}

	// Event object
	if ( src && src.type ) {
		this.originalEvent = src;
		this.type = src.type;

		// Events bubbling up the document may have been marked as prevented
		// by a handler lower down the tree; reflect the correct value.
		this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
			src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;

	// Event type
	} else {
		this.type = src;
	}

	// Put explicitly provided properties onto the event object
	if ( props ) {
		jQuery.extend( this, props );
	}

	// Create a timestamp if incoming event doesn't have one
	this.timeStamp = src && src.timeStamp || jQuery.now();

	// Mark it as fixed
	this[ jQuery.expando ] = true;
};

function returnFalse() {
	return false;
}
function returnTrue() {
	return true;
}

// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
jQuery.Event.prototype = {
	preventDefault: function() {
		this.isDefaultPrevented = returnTrue;

		var e = this.originalEvent;
		if ( !e ) {
			return;
		}

		// if preventDefault exists run it on the original event
		if ( e.preventDefault ) {
			e.preventDefault();

		// otherwise set the returnValue property of the original event to false (IE)
		} else {
			e.returnValue = false;
		}
	},
	stopPropagation: function() {
		this.isPropagationStopped = returnTrue;

		var e = this.originalEvent;
		if ( !e ) {
			return;
		}
		// if stopPropagation exists run it on the original event
		if ( e.stopPropagation ) {
			e.stopPropagation();
		}
		// otherwise set the cancelBubble property of the original event to true (IE)
		e.cancelBubble = true;
	},
	stopImmediatePropagation: function() {
		this.isImmediatePropagationStopped = returnTrue;
		this.stopPropagation();
	},
	isDefaultPrevented: returnFalse,
	isPropagationStopped: returnFalse,
	isImmediatePropagationStopped: returnFalse
};

// Create mouseenter/leave events using mouseover/out and event-time checks
jQuery.each({
	mouseenter: "mouseover",
	mouseleave: "mouseout"
}, function( orig, fix ) {
	jQuery.event.special[ orig ] = {
		delegateType: fix,
		bindType: fix,

		handle: function( event ) {
			var target = this,
				related = event.relatedTarget,
				handleObj = event.handleObj,
				selector = handleObj.selector,
				ret;

			// For mousenter/leave call the handler if related is outside the target.
			// NB: No relatedTarget if the mouse left/entered the browser window
			if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
				event.type = handleObj.origType;
				ret = handleObj.handler.apply( this, arguments );
				event.type = fix;
			}
			return ret;
		}
	};
});

// IE submit delegation
if ( !jQuery.support.submitBubbles ) {

	jQuery.event.special.submit = {
		setup: function() {
			// Only need this for delegated form submit events
			if ( jQuery.nodeName( this, "form" ) ) {
				return false;
			}

			// Lazy-add a submit handler when a descendant form may potentially be submitted
			jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
				// Node name check avoids a VML-related crash in IE (#9807)
				var elem = e.target,
					form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
				if ( form && !form._submit_attached ) {
					jQuery.event.add( form, "submit._submit", function( event ) {
						// If form was submitted by the user, bubble the event up the tree
						if ( this.parentNode && !event.isTrigger ) {
							jQuery.event.simulate( "submit", this.parentNode, event, true );
						}
					});
					form._submit_attached = true;
				}
			});
			// return undefined since we don't need an event listener
		},

		teardown: function() {
			// Only need this for delegated form submit events
			if ( jQuery.nodeName( this, "form" ) ) {
				return false;
			}

			// Remove delegated handlers; cleanData eventually reaps submit handlers attached above
			jQuery.event.remove( this, "._submit" );
		}
	};
}

// IE change delegation and checkbox/radio fix
if ( !jQuery.support.changeBubbles ) {

	jQuery.event.special.change = {

		setup: function() {

			if ( rformElems.test( this.nodeName ) ) {
				// IE doesn't fire change on a check/radio until blur; trigger it on click
				// after a propertychange. Eat the blur-change in special.change.handle.
				// This still fires onchange a second time for check/radio after blur.
				if ( this.type === "checkbox" || this.type === "radio" ) {
					jQuery.event.add( this, "propertychange._change", function( event ) {
						if ( event.originalEvent.propertyName === "checked" ) {
							this._just_changed = true;
						}
					});
					jQuery.event.add( this, "click._change", function( event ) {
						if ( this._just_changed && !event.isTrigger ) {
							this._just_changed = false;
							jQuery.event.simulate( "change", this, event, true );
						}
					});
				}
				return false;
			}
			// Delegated event; lazy-add a change handler on descendant inputs
			jQuery.event.add( this, "beforeactivate._change", function( e ) {
				var elem = e.target;

				if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {
					jQuery.event.add( elem, "change._change", function( event ) {
						if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
							jQuery.event.simulate( "change", this.parentNode, event, true );
						}
					});
					elem._change_attached = true;
				}
			});
		},

		handle: function( event ) {
			var elem = event.target;

			// Swallow native change events from checkbox/radio, we already triggered them above
			if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
				return event.handleObj.handler.apply( this, arguments );
			}
		},

		teardown: function() {
			jQuery.event.remove( this, "._change" );

			return rformElems.test( this.nodeName );
		}
	};
}

// Create "bubbling" focus and blur events
if ( !jQuery.support.focusinBubbles ) {
	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {

		// Attach a single capturing handler while someone wants focusin/focusout
		var attaches = 0,
			handler = function( event ) {
				jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
			};

		jQuery.event.special[ fix ] = {
			setup: function() {
				if ( attaches++ === 0 ) {
					document.addEventListener( orig, handler, true );
				}
			},
			teardown: function() {
				if ( --attaches === 0 ) {
					document.removeEventListener( orig, handler, true );
				}
			}
		};
	});
}

jQuery.fn.extend({

	on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
		var origFn, type;

		// Types can be a map of types/handlers
		if ( typeof types === "object" ) {
			// ( types-Object, selector, data )
			if ( typeof selector !== "string" ) {
				// ( types-Object, data )
				data = selector;
				selector = undefined;
			}
			for ( type in types ) {
				this.on( type, selector, data, types[ type ], one );
			}
			return this;
		}

		if ( data == null && fn == null ) {
			// ( types, fn )
			fn = selector;
			data = selector = undefined;
		} else if ( fn == null ) {
			if ( typeof selector === "string" ) {
				// ( types, selector, fn )
				fn = data;
				data = undefined;
			} else {
				// ( types, data, fn )
				fn = data;
				data = selector;
				selector = undefined;
			}
		}
		if ( fn === false ) {
			fn = returnFalse;
		} else if ( !fn ) {
			return this;
		}

		if ( one === 1 ) {
			origFn = fn;
			fn = function( event ) {
				// Can use an empty set, since event contains the info
				jQuery().off( event );
				return origFn.apply( this, arguments );
			};
			// Use same guid so caller can remove using origFn
			fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
		}
		return this.each( function() {
			jQuery.event.add( this, types, fn, data, selector );
		});
	},
	one: function( types, selector, data, fn ) {
		return this.on.call( this, types, selector, data, fn, 1 );
	},
	off: function( types, selector, fn ) {
		if ( types && types.preventDefault && types.handleObj ) {
			// ( event )  dispatched jQuery.Event
			var handleObj = types.handleObj;
			jQuery( types.delegateTarget ).off(
				handleObj.namespace? handleObj.type + "." + handleObj.namespace : handleObj.type,
				handleObj.selector,
				handleObj.handler
			);
			return this;
		}
		if ( typeof types === "object" ) {
			// ( types-object [, selector] )
			for ( var type in types ) {
				this.off( type, selector, types[ type ] );
			}
			return this;
		}
		if ( selector === false || typeof selector === "function" ) {
			// ( types [, fn] )
			fn = selector;
			selector = undefined;
		}
		if ( fn === false ) {
			fn = returnFalse;
		}
		return this.each(function() {
			jQuery.event.remove( this, types, fn, selector );
		});
	},

	bind: function( types, data, fn ) {
		return this.on( types, null, data, fn );
	},
	unbind: function( types, fn ) {
		return this.off( types, null, fn );
	},

	live: function( types, data, fn ) {
		jQuery( this.context ).on( types, this.selector, data, fn );
		return this;
	},
	die: function( types, fn ) {
		jQuery( this.context ).off( types, this.selector || "**", fn );
		return this;
	},

	delegate: function( selector, types, data, fn ) {
		return this.on( types, selector, data, fn );
	},
	undelegate: function( selector, types, fn ) {
		// ( namespace ) or ( selector, types [, fn] )
		return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn );
	},

	trigger: function( type, data ) {
		return this.each(function() {
			jQuery.event.trigger( type, data, this );
		});
	},
	triggerHandler: function( type, data ) {
		if ( this[0] ) {
			return jQuery.event.trigger( type, data, this[0], true );
		}
	},

	toggle: function( fn ) {
		// Save reference to arguments for access in closure
		var args = arguments,
			guid = fn.guid || jQuery.guid++,
			i = 0,
			toggler = function( event ) {
				// Figure out which function to execute
				var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
				jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );

				// Make sure that clicks stop
				event.preventDefault();

				// and execute the function
				return args[ lastToggle ].apply( this, arguments ) || false;
			};

		// link all the functions, so any of them can unbind this click handler
		toggler.guid = guid;
		while ( i < args.length ) {
			args[ i++ ].guid = guid;
		}

		return this.click( toggler );
	},

	hover: function( fnOver, fnOut ) {
		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
	}
});

jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
	"change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {

	// Handle event binding
	jQuery.fn[ name ] = function( data, fn ) {
		if ( fn == null ) {
			fn = data;
			data = null;
		}

		return arguments.length > 0 ?
			this.on( name, null, data, fn ) :
			this.trigger( name );
	};

	if ( jQuery.attrFn ) {
		jQuery.attrFn[ name ] = true;
	}

	if ( rkeyEvent.test( name ) ) {
		jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;
	}

	if ( rmouseEvent.test( name ) ) {
		jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;
	}
});



/*!
 * Sizzle CSS Selector Engine
 *  Copyright 2011, The Dojo Foundation
 *  Released under the MIT, BSD, and GPL Licenses.
 *  More information: http://sizzlejs.com/
 */
(function(){

var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
	expando = "sizcache" + (Math.random() + '').replace('.', ''),
	done = 0,
	toString = Object.prototype.toString,
	hasDuplicate = false,
	baseHasDuplicate = true,
	rBackslash = /\\/g,
	rReturn = /\r\n/g,
	rNonWord = /\W/;

// Here we check if the JavaScript engine is using some sort of
// optimization where it does not always call our comparision
// function. If that is the case, discard the hasDuplicate value.
//   Thus far that includes Google Chrome.
[0, 0].sort(function() {
	baseHasDuplicate = false;
	return 0;
});

var Sizzle = function( selector, context, results, seed ) {
	results = results || [];
	context = context || document;

	var origContext = context;

	if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
		return [];
	}
	
	if ( !selector || typeof selector !== "string" ) {
		return results;
	}

	var m, set, checkSet, extra, ret, cur, pop, i,
		prune = true,
		contextXML = Sizzle.isXML( context ),
		parts = [],
		soFar = selector;
	
	// Reset the position of the chunker regexp (start from head)
	do {
		chunker.exec( "" );
		m = chunker.exec( soFar );

		if ( m ) {
			soFar = m[3];
		
			parts.push( m[1] );
		
			if ( m[2] ) {
				extra = m[3];
				break;
			}
		}
	} while ( m );

	if ( parts.length > 1 && origPOS.exec( selector ) ) {

		if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
			set = posProcess( parts[0] + parts[1], context, seed );

		} else {
			set = Expr.relative[ parts[0] ] ?
				[ context ] :
				Sizzle( parts.shift(), context );

			while ( parts.length ) {
				selector = parts.shift();

				if ( Expr.relative[ selector ] ) {
					selector += parts.shift();
				}
				
				set = posProcess( selector, set, seed );
			}
		}

	} else {
		// Take a shortcut and set the context if the root selector is an ID
		// (but not if it'll be faster if the inner selector is an ID)
		if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
				Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {

			ret = Sizzle.find( parts.shift(), context, contextXML );
			context = ret.expr ?
				Sizzle.filter( ret.expr, ret.set )[0] :
				ret.set[0];
		}

		if ( context ) {
			ret = seed ?
				{ expr: parts.pop(), set: makeArray(seed) } :
				Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );

			set = ret.expr ?
				Sizzle.filter( ret.expr, ret.set ) :
				ret.set;

			if ( parts.length > 0 ) {
				checkSet = makeArray( set );

			} else {
				prune = false;
			}

			while ( parts.length ) {
				cur = parts.pop();
				pop = cur;

				if ( !Expr.relative[ cur ] ) {
					cur = "";
				} else {
					pop = parts.pop();
				}

				if ( pop == null ) {
					pop = context;
				}

				Expr.relative[ cur ]( checkSet, pop, contextXML );
			}

		} else {
			checkSet = parts = [];
		}
	}

	if ( !checkSet ) {
		checkSet = set;
	}

	if ( !checkSet ) {
		Sizzle.error( cur || selector );
	}

	if ( toString.call(checkSet) === "[object Array]" ) {
		if ( !prune ) {
			results.push.apply( results, checkSet );

		} else if ( context && context.nodeType === 1 ) {
			for ( i = 0; checkSet[i] != null; i++ ) {
				if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
					results.push( set[i] );
				}
			}

		} else {
			for ( i = 0; checkSet[i] != null; i++ ) {
				if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
					results.push( set[i] );
				}
			}
		}

	} else {
		makeArray( checkSet, results );
	}

	if ( extra ) {
		Sizzle( extra, origContext, results, seed );
		Sizzle.uniqueSort( results );
	}

	return results;
};

Sizzle.uniqueSort = function( results ) {
	if ( sortOrder ) {
		hasDuplicate = baseHasDuplicate;
		results.sort( sortOrder );

		if ( hasDuplicate ) {
			for ( var i = 1; i < results.length; i++ ) {
				if ( results[i] === results[ i - 1 ] ) {
					results.splice( i--, 1 );
				}
			}
		}
	}

	return results;
};

Sizzle.matches = function( expr, set ) {
	return Sizzle( expr, null, null, set );
};

Sizzle.matchesSelector = function( node, expr ) {
	return Sizzle( expr, null, null, [node] ).length > 0;
};

Sizzle.find = function( expr, context, isXML ) {
	var set, i, len, match, type, left;

	if ( !expr ) {
		return [];
	}

	for ( i = 0, len = Expr.order.length; i < len; i++ ) {
		type = Expr.order[i];
		
		if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
			left = match[1];
			match.splice( 1, 1 );

			if ( left.substr( left.length - 1 ) !== "\\" ) {
				match[1] = (match[1] || "").replace( rBackslash, "" );
				set = Expr.find[ type ]( match, context, isXML );

				if ( set != null ) {
					expr = expr.replace( Expr.match[ type ], "" );
					break;
				}
			}
		}
	}

	if ( !set ) {
		set = typeof context.getElementsByTagName !== "undefined" ?
			context.getElementsByTagName( "*" ) :
			[];
	}

	return { set: set, expr: expr };
};

Sizzle.filter = function( expr, set, inplace, not ) {
	var match, anyFound,
		type, found, item, filter, left,
		i, pass,
		old = expr,
		result = [],
		curLoop = set,
		isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );

	while ( expr && set.length ) {
		for ( type in Expr.filter ) {
			if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
				filter = Expr.filter[ type ];
				left = match[1];

				anyFound = false;

				match.splice(1,1);

				if ( left.substr( left.length - 1 ) === "\\" ) {
					continue;
				}

				if ( curLoop === result ) {
					result = [];
				}

				if ( Expr.preFilter[ type ] ) {
					match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );

					if ( !match ) {
						anyFound = found = true;

					} else if ( match === true ) {
						continue;
					}
				}

				if ( match ) {
					for ( i = 0; (item = curLoop[i]) != null; i++ ) {
						if ( item ) {
							found = filter( item, match, i, curLoop );
							pass = not ^ found;

							if ( inplace && found != null ) {
								if ( pass ) {
									anyFound = true;

								} else {
									curLoop[i] = false;
								}

							} else if ( pass ) {
								result.push( item );
								anyFound = true;
							}
						}
					}
				}

				if ( found !== undefined ) {
					if ( !inplace ) {
						curLoop = result;
					}

					expr = expr.replace( Expr.match[ type ], "" );

					if ( !anyFound ) {
						return [];
					}

					break;
				}
			}
		}

		// Improper expression
		if ( expr === old ) {
			if ( anyFound == null ) {
				Sizzle.error( expr );

			} else {
				break;
			}
		}

		old = expr;
	}

	return curLoop;
};

Sizzle.error = function( msg ) {
	throw new Error( "Syntax error, unrecognized expression: " + msg );
};

/**
 * Utility function for retreiving the text value of an array of DOM nodes
 * @param {Array|Element} elem
 */
var getText = Sizzle.getText = function( elem ) {
    var i, node,
		nodeType = elem.nodeType,
		ret = "";

	if ( nodeType ) {
		if ( nodeType === 1 || nodeType === 9 ) {
			// Use textContent || innerText for elements
			if ( typeof elem.textContent === 'string' ) {
				return elem.textContent;
			} else if ( typeof elem.innerText === 'string' ) {
				// Replace IE's carriage returns
				return elem.innerText.replace( rReturn, '' );
			} else {
				// Traverse it's children
				for ( elem = elem.firstChild; elem; elem = elem.nextSibling) {
					ret += getText( elem );
				}
			}
		} else if ( nodeType === 3 || nodeType === 4 ) {
			return elem.nodeValue;
		}
	} else {

		// If no nodeType, this is expected to be an array
		for ( i = 0; (node = elem[i]); i++ ) {
			// Do not traverse comment nodes
			if ( node.nodeType !== 8 ) {
				ret += getText( node );
			}
		}
	}
	return ret;
};

var Expr = Sizzle.selectors = {
	order: [ "ID", "NAME", "TAG" ],

	match: {
		ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
		CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
		NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
		ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
		TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
		CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
		POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
		PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
	},

	leftMatch: {},

	attrMap: {
		"class": "className",
		"for": "htmlFor"
	},

	attrHandle: {
		href: function( elem ) {
			return elem.getAttribute( "href" );
		},
		type: function( elem ) {
			return elem.getAttribute( "type" );
		}
	},

	relative: {
		"+": function(checkSet, part){
			var isPartStr = typeof part === "string",
				isTag = isPartStr && !rNonWord.test( part ),
				isPartStrNotTag = isPartStr && !isTag;

			if ( isTag ) {
				part = part.toLowerCase();
			}

			for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
				if ( (elem = checkSet[i]) ) {
					while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}

					checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
						elem || false :
						elem === part;
				}
			}

			if ( isPartStrNotTag ) {
				Sizzle.filter( part, checkSet, true );
			}
		},

		">": function( checkSet, part ) {
			var elem,
				isPartStr = typeof part === "string",
				i = 0,
				l = checkSet.length;

			if ( isPartStr && !rNonWord.test( part ) ) {
				part = part.toLowerCase();

				for ( ; i < l; i++ ) {
					elem = checkSet[i];

					if ( elem ) {
						var parent = elem.parentNode;
						checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
					}
				}

			} else {
				for ( ; i < l; i++ ) {
					elem = checkSet[i];

					if ( elem ) {
						checkSet[i] = isPartStr ?
							elem.parentNode :
							elem.parentNode === part;
					}
				}

				if ( isPartStr ) {
					Sizzle.filter( part, checkSet, true );
				}
			}
		},

		"": function(checkSet, part, isXML){
			var nodeCheck,
				doneName = done++,
				checkFn = dirCheck;

			if ( typeof part === "string" && !rNonWord.test( part ) ) {
				part = part.toLowerCase();
				nodeCheck = part;
				checkFn = dirNodeCheck;
			}

			checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
		},

		"~": function( checkSet, part, isXML ) {
			var nodeCheck,
				doneName = done++,
				checkFn = dirCheck;

			if ( typeof part === "string" && !rNonWord.test( part ) ) {
				part = part.toLowerCase();
				nodeCheck = part;
				checkFn = dirNodeCheck;
			}

			checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
		}
	},

	find: {
		ID: function( match, context, isXML ) {
			if ( typeof context.getElementById !== "undefined" && !isXML ) {
				var m = context.getElementById(match[1]);
				// Check parentNode to catch when Blackberry 4.6 returns
				// nodes that are no longer in the document #6963
				return m && m.parentNode ? [m] : [];
			}
		},

		NAME: function( match, context ) {
			if ( typeof context.getElementsByName !== "undefined" ) {
				var ret = [],
					results = context.getElementsByName( match[1] );

				for ( var i = 0, l = results.length; i < l; i++ ) {
					if ( results[i].getAttribute("name") === match[1] ) {
						ret.push( results[i] );
					}
				}

				return ret.length === 0 ? null : ret;
			}
		},

		TAG: function( match, context ) {
			if ( typeof context.getElementsByTagName !== "undefined" ) {
				return context.getElementsByTagName( match[1] );
			}
		}
	},
	preFilter: {
		CLASS: function( match, curLoop, inplace, result, not, isXML ) {
			match = " " + match[1].replace( rBackslash, "" ) + " ";

			if ( isXML ) {
				return match;
			}

			for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
				if ( elem ) {
					if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) {
						if ( !inplace ) {
							result.push( elem );
						}

					} else if ( inplace ) {
						curLoop[i] = false;
					}
				}
			}

			return false;
		},

		ID: function( match ) {
			return match[1].replace( rBackslash, "" );
		},

		TAG: function( match, curLoop ) {
			return match[1].replace( rBackslash, "" ).toLowerCase();
		},

		CHILD: function( match ) {
			if ( match[1] === "nth" ) {
				if ( !match[2] ) {
					Sizzle.error( match[0] );
				}

				match[2] = match[2].replace(/^\+|\s*/g, '');

				// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
				var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec(
					match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
					!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);

				// calculate the numbers (first)n+(last) including if they are negative
				match[2] = (test[1] + (test[2] || 1)) - 0;
				match[3] = test[3] - 0;
			}
			else if ( match[2] ) {
				Sizzle.error( match[0] );
			}

			// TODO: Move to normal caching system
			match[0] = done++;

			return match;
		},

		ATTR: function( match, curLoop, inplace, result, not, isXML ) {
			var name = match[1] = match[1].replace( rBackslash, "" );
			
			if ( !isXML && Expr.attrMap[name] ) {
				match[1] = Expr.attrMap[name];
			}

			// Handle if an un-quoted value was used
			match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" );

			if ( match[2] === "~=" ) {
				match[4] = " " + match[4] + " ";
			}

			return match;
		},

		PSEUDO: function( match, curLoop, inplace, result, not ) {
			if ( match[1] === "not" ) {
				// If we're dealing with a complex expression, or a simple one
				if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
					match[3] = Sizzle(match[3], null, null, curLoop);

				} else {
					var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);

					if ( !inplace ) {
						result.push.apply( result, ret );
					}

					return false;
				}

			} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
				return true;
			}
			
			return match;
		},

		POS: function( match ) {
			match.unshift( true );

			return match;
		}
	},
	
	filters: {
		enabled: function( elem ) {
			return elem.disabled === false && elem.type !== "hidden";
		},

		disabled: function( elem ) {
			return elem.disabled === true;
		},

		checked: function( elem ) {
			return elem.checked === true;
		},
		
		selected: function( elem ) {
			// Accessing this property makes selected-by-default
			// options in Safari work properly
			if ( elem.parentNode ) {
				elem.parentNode.selectedIndex;
			}
			
			return elem.selected === true;
		},

		parent: function( elem ) {
			return !!elem.firstChild;
		},

		empty: function( elem ) {
			return !elem.firstChild;
		},

		has: function( elem, i, match ) {
			return !!Sizzle( match[3], elem ).length;
		},

		header: function( elem ) {
			return (/h\d/i).test( elem.nodeName );
		},

		text: function( elem ) {
			var attr = elem.getAttribute( "type" ), type = elem.type;
			// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) 
			// use getAttribute instead to test this case
			return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null );
		},

		radio: function( elem ) {
			return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type;
		},

		checkbox: function( elem ) {
			return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type;
		},

		file: function( elem ) {
			return elem.nodeName.toLowerCase() === "input" && "file" === elem.type;
		},

		password: function( elem ) {
			return elem.nodeName.toLowerCase() === "input" && "password" === elem.type;
		},

		submit: function( elem ) {
			var name = elem.nodeName.toLowerCase();
			return (name === "input" || name === "button") && "submit" === elem.type;
		},

		image: function( elem ) {
			return elem.nodeName.toLowerCase() === "input" && "image" === elem.type;
		},

		reset: function( elem ) {
			var name = elem.nodeName.toLowerCase();
			return (name === "input" || name === "button") && "reset" === elem.type;
		},

		button: function( elem ) {
			var name = elem.nodeName.toLowerCase();
			return name === "input" && "button" === elem.type || name === "button";
		},

		input: function( elem ) {
			return (/input|select|textarea|button/i).test( elem.nodeName );
		},

		focus: function( elem ) {
			return elem === elem.ownerDocument.activeElement;
		}
	},
	setFilters: {
		first: function( elem, i ) {
			return i === 0;
		},

		last: function( elem, i, match, array ) {
			return i === array.length - 1;
		},

		even: function( elem, i ) {
			return i % 2 === 0;
		},

		odd: function( elem, i ) {
			return i % 2 === 1;
		},

		lt: function( elem, i, match ) {
			return i < match[3] - 0;
		},

		gt: function( elem, i, match ) {
			return i > match[3] - 0;
		},

		nth: function( elem, i, match ) {
			return match[3] - 0 === i;
		},

		eq: function( elem, i, match ) {
			return match[3] - 0 === i;
		}
	},
	filter: {
		PSEUDO: function( elem, match, i, array ) {
			var name = match[1],
				filter = Expr.filters[ name ];

			if ( filter ) {
				return filter( elem, i, match, array );

			} else if ( name === "contains" ) {
				return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;

			} else if ( name === "not" ) {
				var not = match[3];

				for ( var j = 0, l = not.length; j < l; j++ ) {
					if ( not[j] === elem ) {
						return false;
					}
				}

				return true;

			} else {
				Sizzle.error( name );
			}
		},

		CHILD: function( elem, match ) {
			var first, last,
				doneName, parent, cache,
				count, diff,
				type = match[1],
				node = elem;

			switch ( type ) {
				case "only":
				case "first":
					while ( (node = node.previousSibling) )	 {
						if ( node.nodeType === 1 ) { 
							return false; 
						}
					}

					if ( type === "first" ) { 
						return true; 
					}

					node = elem;

				case "last":
					while ( (node = node.nextSibling) )	 {
						if ( node.nodeType === 1 ) { 
							return false; 
						}
					}

					return true;

				case "nth":
					first = match[2];
					last = match[3];

					if ( first === 1 && last === 0 ) {
						return true;
					}
					
					doneName = match[0];
					parent = elem.parentNode;
	
					if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {
						count = 0;
						
						for ( node = parent.firstChild; node; node = node.nextSibling ) {
							if ( node.nodeType === 1 ) {
								node.nodeIndex = ++count;
							}
						} 

						parent[ expando ] = doneName;
					}
					
					diff = elem.nodeIndex - last;

					if ( first === 0 ) {
						return diff === 0;

					} else {
						return ( diff % first === 0 && diff / first >= 0 );
					}
			}
		},

		ID: function( elem, match ) {
			return elem.nodeType === 1 && elem.getAttribute("id") === match;
		},

		TAG: function( elem, match ) {
			return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;
		},
		
		CLASS: function( elem, match ) {
			return (" " + (elem.className || elem.getAttribute("class")) + " ")
				.indexOf( match ) > -1;
		},

		ATTR: function( elem, match ) {
			var name = match[1],
				result = Sizzle.attr ?
					Sizzle.attr( elem, name ) :
					Expr.attrHandle[ name ] ?
					Expr.attrHandle[ name ]( elem ) :
					elem[ name ] != null ?
						elem[ name ] :
						elem.getAttribute( name ),
				value = result + "",
				type = match[2],
				check = match[4];

			return result == null ?
				type === "!=" :
				!type && Sizzle.attr ?
				result != null :
				type === "=" ?
				value === check :
				type === "*=" ?
				value.indexOf(check) >= 0 :
				type === "~=" ?
				(" " + value + " ").indexOf(check) >= 0 :
				!check ?
				value && result !== false :
				type === "!=" ?
				value !== check :
				type === "^=" ?
				value.indexOf(check) === 0 :
				type === "$=" ?
				value.substr(value.length - check.length) === check :
				type === "|=" ?
				value === check || value.substr(0, check.length + 1) === check + "-" :
				false;
		},

		POS: function( elem, match, i, array ) {
			var name = match[2],
				filter = Expr.setFilters[ name ];

			if ( filter ) {
				return filter( elem, i, match, array );
			}
		}
	}
};

var origPOS = Expr.match.POS,
	fescape = function(all, num){
		return "\\" + (num - 0 + 1);
	};

for ( var type in Expr.match ) {
	Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
	Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
}

var makeArray = function( array, results ) {
	array = Array.prototype.slice.call( array, 0 );

	if ( results ) {
		results.push.apply( results, array );
		return results;
	}
	
	return array;
};

// Perform a simple check to determine if the browser is capable of
// converting a NodeList to an array using builtin methods.
// Also verifies that the returned array holds DOM nodes
// (which is not the case in the Blackberry browser)
try {
	Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;

// Provide a fallback method if it does not work
} catch( e ) {
	makeArray = function( array, results ) {
		var i = 0,
			ret = results || [];

		if ( toString.call(array) === "[object Array]" ) {
			Array.prototype.push.apply( ret, array );

		} else {
			if ( typeof array.length === "number" ) {
				for ( var l = array.length; i < l; i++ ) {
					ret.push( array[i] );
				}

			} else {
				for ( ; array[i]; i++ ) {
					ret.push( array[i] );
				}
			}
		}

		return ret;
	};
}

var sortOrder, siblingCheck;

if ( document.documentElement.compareDocumentPosition ) {
	sortOrder = function( a, b ) {
		if ( a === b ) {
			hasDuplicate = true;
			return 0;
		}

		if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
			return a.compareDocumentPosition ? -1 : 1;
		}

		return a.compareDocumentPosition(b) & 4 ? -1 : 1;
	};

} else {
	sortOrder = function( a, b ) {
		// The nodes are identical, we can exit early
		if ( a === b ) {
			hasDuplicate = true;
			return 0;

		// Fallback to using sourceIndex (in IE) if it's available on both nodes
		} else if ( a.sourceIndex && b.sourceIndex ) {
			return a.sourceIndex - b.sourceIndex;
		}

		var al, bl,
			ap = [],
			bp = [],
			aup = a.parentNode,
			bup = b.parentNode,
			cur = aup;

		// If the nodes are siblings (or identical) we can do a quick check
		if ( aup === bup ) {
			return siblingCheck( a, b );

		// If no parents were found then the nodes are disconnected
		} else if ( !aup ) {
			return -1;

		} else if ( !bup ) {
			return 1;
		}

		// Otherwise they're somewhere else in the tree so we need
		// to build up a full list of the parentNodes for comparison
		while ( cur ) {
			ap.unshift( cur );
			cur = cur.parentNode;
		}

		cur = bup;

		while ( cur ) {
			bp.unshift( cur );
			cur = cur.parentNode;
		}

		al = ap.length;
		bl = bp.length;

		// Start walking down the tree looking for a discrepancy
		for ( var i = 0; i < al && i < bl; i++ ) {
			if ( ap[i] !== bp[i] ) {
				return siblingCheck( ap[i], bp[i] );
			}
		}

		// We ended someplace up the tree so do a sibling check
		return i === al ?
			siblingCheck( a, bp[i], -1 ) :
			siblingCheck( ap[i], b, 1 );
	};

	siblingCheck = function( a, b, ret ) {
		if ( a === b ) {
			return ret;
		}

		var cur = a.nextSibling;

		while ( cur ) {
			if ( cur === b ) {
				return -1;
			}

			cur = cur.nextSibling;
		}

		return 1;
	};
}

// Check to see if the browser returns elements by name when
// querying by getElementById (and provide a workaround)
(function(){
	// We're going to inject a fake input element with a specified name
	var form = document.createElement("div"),
		id = "script" + (new Date()).getTime(),
		root = document.documentElement;

	form.innerHTML = "<a name='" + id + "'/>";

	// Inject it into the root element, check its status, and remove it quickly
	root.insertBefore( form, root.firstChild );

	// The workaround has to do additional checks after a getElementById
	// Which slows things down for other browsers (hence the branching)
	if ( document.getElementById( id ) ) {
		Expr.find.ID = function( match, context, isXML ) {
			if ( typeof context.getElementById !== "undefined" && !isXML ) {
				var m = context.getElementById(match[1]);

				return m ?
					m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
						[m] :
						undefined :
					[];
			}
		};

		Expr.filter.ID = function( elem, match ) {
			var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");

			return elem.nodeType === 1 && node && node.nodeValue === match;
		};
	}

	root.removeChild( form );

	// release memory in IE
	root = form = null;
})();

(function(){
	// Check to see if the browser returns only elements
	// when doing getElementsByTagName("*")

	// Create a fake element
	var div = document.createElement("div");
	div.appendChild( document.createComment("") );

	// Make sure no comments are found
	if ( div.getElementsByTagName("*").length > 0 ) {
		Expr.find.TAG = function( match, context ) {
			var results = context.getElementsByTagName( match[1] );

			// Filter out possible comments
			if ( match[1] === "*" ) {
				var tmp = [];

				for ( var i = 0; results[i]; i++ ) {
					if ( results[i].nodeType === 1 ) {
						tmp.push( results[i] );
					}
				}

				results = tmp;
			}

			return results;
		};
	}

	// Check to see if an attribute returns normalized href attributes
	div.innerHTML = "<a href='#'></a>";

	if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
			div.firstChild.getAttribute("href") !== "#" ) {

		Expr.attrHandle.href = function( elem ) {
			return elem.getAttribute( "href", 2 );
		};
	}

	// release memory in IE
	div = null;
})();

if ( document.querySelectorAll ) {
	(function(){
		var oldSizzle = Sizzle,
			div = document.createElement("div"),
			id = "__sizzle__";

		div.innerHTML = "<p class='TEST'></p>";

		// Safari can't handle uppercase or unicode characters when
		// in quirks mode.
		if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
			return;
		}
	
		Sizzle = function( query, context, extra, seed ) {
			context = context || document;

			// Only use querySelectorAll on non-XML documents
			// (ID selectors don't work in non-HTML documents)
			if ( !seed && !Sizzle.isXML(context) ) {
				// See if we find a selector to speed up
				var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query );
				
				if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
					// Speed-up: Sizzle("TAG")
					if ( match[1] ) {
						return makeArray( context.getElementsByTagName( query ), extra );
					
					// Speed-up: Sizzle(".CLASS")
					} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
						return makeArray( context.getElementsByClassName( match[2] ), extra );
					}
				}
				
				if ( context.nodeType === 9 ) {
					// Speed-up: Sizzle("body")
					// The body element only exists once, optimize finding it
					if ( query === "body" && context.body ) {
						return makeArray( [ context.body ], extra );
						
					// Speed-up: Sizzle("#ID")
					} else if ( match && match[3] ) {
						var elem = context.getElementById( match[3] );

						// Check parentNode to catch when Blackberry 4.6 returns
						// nodes that are no longer in the document #6963
						if ( elem && elem.parentNode ) {
							// Handle the case where IE and Opera return items
							// by name instead of ID
							if ( elem.id === match[3] ) {
								return makeArray( [ elem ], extra );
							}
							
						} else {
							return makeArray( [], extra );
						}
					}
					
					try {
						return makeArray( context.querySelectorAll(query), extra );
					} catch(qsaError) {}

				// qSA works strangely on Element-rooted queries
				// We can work around this by specifying an extra ID on the root
				// and working up from there (Thanks to Andrew Dupont for the technique)
				// IE 8 doesn't work on object elements
				} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
					var oldContext = context,
						old = context.getAttribute( "id" ),
						nid = old || id,
						hasParent = context.parentNode,
						relativeHierarchySelector = /^\s*[+~]/.test( query );

					if ( !old ) {
						context.setAttribute( "id", nid );
					} else {
						nid = nid.replace( /'/g, "\\$&" );
					}
					if ( relativeHierarchySelector && hasParent ) {
						context = context.parentNode;
					}

					try {
						if ( !relativeHierarchySelector || hasParent ) {
							return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra );
						}

					} catch(pseudoError) {
					} finally {
						if ( !old ) {
							oldContext.removeAttribute( "id" );
						}
					}
				}
			}
		
			return oldSizzle(query, context, extra, seed);
		};

		for ( var prop in oldSizzle ) {
			Sizzle[ prop ] = oldSizzle[ prop ];
		}

		// release memory in IE
		div = null;
	})();
}

(function(){
	var html = document.documentElement,
		matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;

	if ( matches ) {
		// Check to see if it's possible to do matchesSelector
		// on a disconnected node (IE 9 fails this)
		var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ),
			pseudoWorks = false;

		try {
			// This should fail with an exception
			// Gecko does not error, returns false instead
			matches.call( document.documentElement, "[test!='']:sizzle" );
	
		} catch( pseudoError ) {
			pseudoWorks = true;
		}

		Sizzle.matchesSelector = function( node, expr ) {
			// Make sure that attribute selectors are quoted
			expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");

			if ( !Sizzle.isXML( node ) ) {
				try { 
					if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
						var ret = matches.call( node, expr );

						// IE 9's matchesSelector returns false on disconnected nodes
						if ( ret || !disconnectedMatch ||
								// As well, disconnected nodes are said to be in a document
								// fragment in IE 9, so check for that
								node.document && node.document.nodeType !== 11 ) {
							return ret;
						}
					}
				} catch(e) {}
			}

			return Sizzle(expr, null, null, [node]).length > 0;
		};
	}
})();

(function(){
	var div = document.createElement("div");

	div.innerHTML = "<div class='test e'></div><div class='test'></div>";

	// Opera can't find a second classname (in 9.6)
	// Also, make sure that getElementsByClassName actually exists
	if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
		return;
	}

	// Safari caches class attributes, doesn't catch changes (in 3.2)
	div.lastChild.className = "e";

	if ( div.getElementsByClassName("e").length === 1 ) {
		return;
	}
	
	Expr.order.splice(1, 0, "CLASS");
	Expr.find.CLASS = function( match, context, isXML ) {
		if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
			return context.getElementsByClassName(match[1]);
		}
	};

	// release memory in IE
	div = null;
})();

function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
		var elem = checkSet[i];

		if ( elem ) {
			var match = false;

			elem = elem[dir];

			while ( elem ) {
				if ( elem[ expando ] === doneName ) {
					match = checkSet[elem.sizset];
					break;
				}

				if ( elem.nodeType === 1 && !isXML ){
					elem[ expando ] = doneName;
					elem.sizset = i;
				}

				if ( elem.nodeName.toLowerCase() === cur ) {
					match = elem;
					break;
				}

				elem = elem[dir];
			}

			checkSet[i] = match;
		}
	}
}

function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
		var elem = checkSet[i];

		if ( elem ) {
			var match = false;
			
			elem = elem[dir];

			while ( elem ) {
				if ( elem[ expando ] === doneName ) {
					match = checkSet[elem.sizset];
					break;
				}

				if ( elem.nodeType === 1 ) {
					if ( !isXML ) {
						elem[ expando ] = doneName;
						elem.sizset = i;
					}

					if ( typeof cur !== "string" ) {
						if ( elem === cur ) {
							match = true;
							break;
						}

					} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
						match = elem;
						break;
					}
				}

				elem = elem[dir];
			}

			checkSet[i] = match;
		}
	}
}

if ( document.documentElement.contains ) {
	Sizzle.contains = function( a, b ) {
		return a !== b && (a.contains ? a.contains(b) : true);
	};

} else if ( document.documentElement.compareDocumentPosition ) {
	Sizzle.contains = function( a, b ) {
		return !!(a.compareDocumentPosition(b) & 16);
	};

} else {
	Sizzle.contains = function() {
		return false;
	};
}

Sizzle.isXML = function( elem ) {
	// documentElement is verified for cases where it doesn't yet exist
	// (such as loading iframes in IE - #4833) 
	var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;

	return documentElement ? documentElement.nodeName !== "HTML" : false;
};

var posProcess = function( selector, context, seed ) {
	var match,
		tmpSet = [],
		later = "",
		root = context.nodeType ? [context] : context;

	// Position selectors must be done after the filter
	// And so must :not(positional) so we move all PSEUDOs to the end
	while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
		later += match[0];
		selector = selector.replace( Expr.match.PSEUDO, "" );
	}

	selector = Expr.relative[selector] ? selector + "*" : selector;

	for ( var i = 0, l = root.length; i < l; i++ ) {
		Sizzle( selector, root[i], tmpSet, seed );
	}

	return Sizzle.filter( later, tmpSet );
};

// EXPOSE
// Override sizzle attribute retrieval
Sizzle.attr = jQuery.attr;
Sizzle.selectors.attrMap = {};
jQuery.find = Sizzle;
jQuery.expr = Sizzle.selectors;
jQuery.expr[":"] = jQuery.expr.filters;
jQuery.unique = Sizzle.uniqueSort;
jQuery.text = Sizzle.getText;
jQuery.isXMLDoc = Sizzle.isXML;
jQuery.contains = Sizzle.contains;


})();


var runtil = /Until$/,
	rparentsprev = /^(?:parents|prevUntil|prevAll)/,
	// Note: This RegExp should be improved, or likely pulled from Sizzle
	rmultiselector = /,/,
	isSimple = /^.[^:#\[\.,]*$/,
	slice = Array.prototype.slice,
	POS = jQuery.expr.match.POS,
	// methods guaranteed to produce a unique set when starting from a unique set
	guaranteedUnique = {
		children: true,
		contents: true,
		next: true,
		prev: true
	};

jQuery.fn.extend({
	find: function( selector ) {
		var self = this,
			i, l;

		if ( typeof selector !== "string" ) {
			return jQuery( selector ).filter(function() {
				for ( i = 0, l = self.length; i < l; i++ ) {
					if ( jQuery.contains( self[ i ], this ) ) {
						return true;
					}
				}
			});
		}

		var ret = this.pushStack( "", "find", selector ),
			length, n, r;

		for ( i = 0, l = this.length; i < l; i++ ) {
			length = ret.length;
			jQuery.find( selector, this[i], ret );

			if ( i > 0 ) {
				// Make sure that the results are unique
				for ( n = length; n < ret.length; n++ ) {
					for ( r = 0; r < length; r++ ) {
						if ( ret[r] === ret[n] ) {
							ret.splice(n--, 1);
							break;
						}
					}
				}
			}
		}

		return ret;
	},

	has: function( target ) {
		var targets = jQuery( target );
		return this.filter(function() {
			for ( var i = 0, l = targets.length; i < l; i++ ) {
				if ( jQuery.contains( this, targets[i] ) ) {
					return true;
				}
			}
		});
	},

	not: function( selector ) {
		return this.pushStack( winnow(this, selector, false), "not", selector);
	},

	filter: function( selector ) {
		return this.pushStack( winnow(this, selector, true), "filter", selector );
	},

	is: function( selector ) {
		return !!selector && ( 
			typeof selector === "string" ?
				// If this is a positional selector, check membership in the returned set
				// so $("p:first").is("p:last") won't return true for a doc with two "p".
				POS.test( selector ) ? 
					jQuery( selector, this.context ).index( this[0] ) >= 0 :
					jQuery.filter( selector, this ).length > 0 :
				this.filter( selector ).length > 0 );
	},

	closest: function( selectors, context ) {
		var ret = [], i, l, cur = this[0];
		
		// Array (deprecated as of jQuery 1.7)
		if ( jQuery.isArray( selectors ) ) {
			var level = 1;

			while ( cur && cur.ownerDocument && cur !== context ) {
				for ( i = 0; i < selectors.length; i++ ) {

					if ( jQuery( cur ).is( selectors[ i ] ) ) {
						ret.push({ selector: selectors[ i ], elem: cur, level: level });
					}
				}

				cur = cur.parentNode;
				level++;
			}

			return ret;
		}

		// String
		var pos = POS.test( selectors ) || typeof selectors !== "string" ?
				jQuery( selectors, context || this.context ) :
				0;

		for ( i = 0, l = this.length; i < l; i++ ) {
			cur = this[i];

			while ( cur ) {
				if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
					ret.push( cur );
					break;

				} else {
					cur = cur.parentNode;
					if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {
						break;
					}
				}
			}
		}

		ret = ret.length > 1 ? jQuery.unique( ret ) : ret;

		return this.pushStack( ret, "closest", selectors );
	},

	// Determine the position of an element within
	// the matched set of elements
	index: function( elem ) {

		// No argument, return index in parent
		if ( !elem ) {
			return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;
		}

		// index in selector
		if ( typeof elem === "string" ) {
			return jQuery.inArray( this[0], jQuery( elem ) );
		}

		// Locate the position of the desired element
		return jQuery.inArray(
			// If it receives a jQuery object, the first element is used
			elem.jquery ? elem[0] : elem, this );
	},

	add: function( selector, context ) {
		var set = typeof selector === "string" ?
				jQuery( selector, context ) :
				jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
			all = jQuery.merge( this.get(), set );

		return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
			all :
			jQuery.unique( all ) );
	},

	andSelf: function() {
		return this.add( this.prevObject );
	}
});

// A painfully simple check to see if an element is disconnected
// from a document (should be improved, where feasible).
function isDisconnected( node ) {
	return !node || !node.parentNode || node.parentNode.nodeType === 11;
}

jQuery.each({
	parent: function( elem ) {
		var parent = elem.parentNode;
		return parent && parent.nodeType !== 11 ? parent : null;
	},
	parents: function( elem ) {
		return jQuery.dir( elem, "parentNode" );
	},
	parentsUntil: function( elem, i, until ) {
		return jQuery.dir( elem, "parentNode", until );
	},
	next: function( elem ) {
		return jQuery.nth( elem, 2, "nextSibling" );
	},
	prev: function( elem ) {
		return jQuery.nth( elem, 2, "previousSibling" );
	},
	nextAll: function( elem ) {
		return jQuery.dir( elem, "nextSibling" );
	},
	prevAll: function( elem ) {
		return jQuery.dir( elem, "previousSibling" );
	},
	nextUntil: function( elem, i, until ) {
		return jQuery.dir( elem, "nextSibling", until );
	},
	prevUntil: function( elem, i, until ) {
		return jQuery.dir( elem, "previousSibling", until );
	},
	siblings: function( elem ) {
		return jQuery.sibling( elem.parentNode.firstChild, elem );
	},
	children: function( elem ) {
		return jQuery.sibling( elem.firstChild );
	},
	contents: function( elem ) {
		return jQuery.nodeName( elem, "iframe" ) ?
			elem.contentDocument || elem.contentWindow.document :
			jQuery.makeArray( elem.childNodes );
	}
}, function( name, fn ) {
	jQuery.fn[ name ] = function( until, selector ) {
		var ret = jQuery.map( this, fn, until );

		if ( !runtil.test( name ) ) {
			selector = until;
		}

		if ( selector && typeof selector === "string" ) {
			ret = jQuery.filter( selector, ret );
		}

		ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;

		if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
			ret = ret.reverse();
		}

		return this.pushStack( ret, name, slice.call( arguments ).join(",") );
	};
});

jQuery.extend({
	filter: function( expr, elems, not ) {
		if ( not ) {
			expr = ":not(" + expr + ")";
		}

		return elems.length === 1 ?
			jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
			jQuery.find.matches(expr, elems);
	},

	dir: function( elem, dir, until ) {
		var matched = [],
			cur = elem[ dir ];

		while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
			if ( cur.nodeType === 1 ) {
				matched.push( cur );
			}
			cur = cur[dir];
		}
		return matched;
	},

	nth: function( cur, result, dir, elem ) {
		result = result || 1;
		var num = 0;

		for ( ; cur; cur = cur[dir] ) {
			if ( cur.nodeType === 1 && ++num === result ) {
				break;
			}
		}

		return cur;
	},

	sibling: function( n, elem ) {
		var r = [];

		for ( ; n; n = n.nextSibling ) {
			if ( n.nodeType === 1 && n !== elem ) {
				r.push( n );
			}
		}

		return r;
	}
});

// Implement the identical functionality for filter and not
function winnow( elements, qualifier, keep ) {

	// Can't pass null or undefined to indexOf in Firefox 4
	// Set to 0 to skip string check
	qualifier = qualifier || 0;

	if ( jQuery.isFunction( qualifier ) ) {
		return jQuery.grep(elements, function( elem, i ) {
			var retVal = !!qualifier.call( elem, i, elem );
			return retVal === keep;
		});

	} else if ( qualifier.nodeType ) {
		return jQuery.grep(elements, function( elem, i ) {
			return ( elem === qualifier ) === keep;
		});

	} else if ( typeof qualifier === "string" ) {
		var filtered = jQuery.grep(elements, function( elem ) {
			return elem.nodeType === 1;
		});

		if ( isSimple.test( qualifier ) ) {
			return jQuery.filter(qualifier, filtered, !keep);
		} else {
			qualifier = jQuery.filter( qualifier, filtered );
		}
	}

	return jQuery.grep(elements, function( elem, i ) {
		return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
	});
}




function createSafeFragment( document ) {
	var list = nodeNames.split( "|" ),
	safeFrag = document.createDocumentFragment();

	if ( safeFrag.createElement ) {
		while ( list.length ) {
			safeFrag.createElement(
				list.pop()
			);
		}
	}
	return safeFrag;
}

var nodeNames = "abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|" +
		"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
	rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
	rleadingWhitespace = /^\s+/,
	rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
	rtagName = /<([\w:]+)/,
	rtbody = /<tbody/i,
	rhtml = /<|&#?\w+;/,
	rnoInnerhtml = /<(?:script|style)/i,
	rnocache = /<(?:script|object|embed|option|style)/i,
	rnoshimcache = new RegExp("<(?:" + nodeNames + ")", "i"),
	// checked="checked" or checked
	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
	rscriptType = /\/(java|ecma)script/i,
	rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)/,
	wrapMap = {
		option: [ 1, "<select multiple='multiple'>", "</select>" ],
		legend: [ 1, "<fieldset>", "</fieldset>" ],
		thead: [ 1, "<table>", "</table>" ],
		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
		col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
		area: [ 1, "<map>", "</map>" ],
		_default: [ 0, "", "" ]
	},
	safeFragment = createSafeFragment( document );

wrapMap.optgroup = wrapMap.option;
wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
wrapMap.th = wrapMap.td;

// IE can't serialize <link> and <script> tags normally
if ( !jQuery.support.htmlSerialize ) {
	wrapMap._default = [ 1, "div<div>", "</div>" ];
}

jQuery.fn.extend({
	text: function( text ) {
		if ( jQuery.isFunction(text) ) {
			return this.each(function(i) {
				var self = jQuery( this );

				self.text( text.call(this, i, self.text()) );
			});
		}

		if ( typeof text !== "object" && text !== undefined ) {
			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
		}

		return jQuery.text( this );
	},

	wrapAll: function( html ) {
		if ( jQuery.isFunction( html ) ) {
			return this.each(function(i) {
				jQuery(this).wrapAll( html.call(this, i) );
			});
		}

		if ( this[0] ) {
			// The elements to wrap the target around
			var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);

			if ( this[0].parentNode ) {
				wrap.insertBefore( this[0] );
			}

			wrap.map(function() {
				var elem = this;

				while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
					elem = elem.firstChild;
				}

				return elem;
			}).append( this );
		}

		return this;
	},

	wrapInner: function( html ) {
		if ( jQuery.isFunction( html ) ) {
			return this.each(function(i) {
				jQuery(this).wrapInner( html.call(this, i) );
			});
		}

		return this.each(function() {
			var self = jQuery( this ),
				contents = self.contents();

			if ( contents.length ) {
				contents.wrapAll( html );

			} else {
				self.append( html );
			}
		});
	},

	wrap: function( html ) {
		var isFunction = jQuery.isFunction( html );

		return this.each(function(i) {
			jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
		});
	},

	unwrap: function() {
		return this.parent().each(function() {
			if ( !jQuery.nodeName( this, "body" ) ) {
				jQuery( this ).replaceWith( this.childNodes );
			}
		}).end();
	},

	append: function() {
		return this.domManip(arguments, true, function( elem ) {
			if ( this.nodeType === 1 ) {
				this.appendChild( elem );
			}
		});
	},

	prepend: function() {
		return this.domManip(arguments, true, function( elem ) {
			if ( this.nodeType === 1 ) {
				this.insertBefore( elem, this.firstChild );
			}
		});
	},

	before: function() {
		if ( this[0] && this[0].parentNode ) {
			return this.domManip(arguments, false, function( elem ) {
				this.parentNode.insertBefore( elem, this );
			});
		} else if ( arguments.length ) {
			var set = jQuery.clean( arguments );
			set.push.apply( set, this.toArray() );
			return this.pushStack( set, "before", arguments );
		}
	},

	after: function() {
		if ( this[0] && this[0].parentNode ) {
			return this.domManip(arguments, false, function( elem ) {
				this.parentNode.insertBefore( elem, this.nextSibling );
			});
		} else if ( arguments.length ) {
			var set = this.pushStack( this, "after", arguments );
			set.push.apply( set, jQuery.clean(arguments) );
			return set;
		}
	},

	// keepData is for internal use only--do not document
	remove: function( selector, keepData ) {
		for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
			if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
				if ( !keepData && elem.nodeType === 1 ) {
					jQuery.cleanData( elem.getElementsByTagName("*") );
					jQuery.cleanData( [ elem ] );
				}

				if ( elem.parentNode ) {
					elem.parentNode.removeChild( elem );
				}
			}
		}

		return this;
	},

	empty: function() {
		for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
			// Remove element nodes and prevent memory leaks
			if ( elem.nodeType === 1 ) {
				jQuery.cleanData( elem.getElementsByTagName("*") );
			}

			// Remove any remaining nodes
			while ( elem.firstChild ) {
				elem.removeChild( elem.firstChild );
			}
		}

		return this;
	},

	clone: function( dataAndEvents, deepDataAndEvents ) {
		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;

		return this.map( function () {
			return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
		});
	},

	html: function( value ) {
		if ( value === undefined ) {
			return this[0] && this[0].nodeType === 1 ?
				this[0].innerHTML.replace(rinlinejQuery, "") :
				null;

		// See if we can take a shortcut and just use innerHTML
		} else if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
			(jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
			!wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {

			value = value.replace(rxhtmlTag, "<$1></$2>");

			try {
				for ( var i = 0, l = this.length; i < l; i++ ) {
					// Remove element nodes and prevent memory leaks
					if ( this[i].nodeType === 1 ) {
						jQuery.cleanData( this[i].getElementsByTagName("*") );
						this[i].innerHTML = value;
					}
				}

			// If using innerHTML throws an exception, use the fallback method
			} catch(e) {
				this.empty().append( value );
			}

		} else if ( jQuery.isFunction( value ) ) {
			this.each(function(i){
				var self = jQuery( this );

				self.html( value.call(this, i, self.html()) );
			});

		} else {
			this.empty().append( value );
		}

		return this;
	},

	replaceWith: function( value ) {
		if ( this[0] && this[0].parentNode ) {
			// Make sure that the elements are removed from the DOM before they are inserted
			// this can help fix replacing a parent with child elements
			if ( jQuery.isFunction( value ) ) {
				return this.each(function(i) {
					var self = jQuery(this), old = self.html();
					self.replaceWith( value.call( this, i, old ) );
				});
			}

			if ( typeof value !== "string" ) {
				value = jQuery( value ).detach();
			}

			return this.each(function() {
				var next = this.nextSibling,
					parent = this.parentNode;

				jQuery( this ).remove();

				if ( next ) {
					jQuery(next).before( value );
				} else {
					jQuery(parent).append( value );
				}
			});
		} else {
			return this.length ?
				this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) :
				this;
		}
	},

	detach: function( selector ) {
		return this.remove( selector, true );
	},

	domManip: function( args, table, callback ) {
		var results, first, fragment, parent,
			value = args[0],
			scripts = [];

		// We can't cloneNode fragments that contain checked, in WebKit
		if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
			return this.each(function() {
				jQuery(this).domManip( args, table, callback, true );
			});
		}

		if ( jQuery.isFunction(value) ) {
			return this.each(function(i) {
				var self = jQuery(this);
				args[0] = value.call(this, i, table ? self.html() : undefined);
				self.domManip( args, table, callback );
			});
		}

		if ( this[0] ) {
			parent = value && value.parentNode;

			// If we're in a fragment, just use that instead of building a new one
			if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
				results = { fragment: parent };

			} else {
				results = jQuery.buildFragment( args, this, scripts );
			}

			fragment = results.fragment;

			if ( fragment.childNodes.length === 1 ) {
				first = fragment = fragment.firstChild;
			} else {
				first = fragment.firstChild;
			}

			if ( first ) {
				table = table && jQuery.nodeName( first, "tr" );

				for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {
					callback.call(
						table ?
							root(this[i], first) :
							this[i],
						// Make sure that we do not leak memory by inadvertently discarding
						// the original fragment (which might have attached data) instead of
						// using it; in addition, use the original fragment object for the last
						// item instead of first because it can end up being emptied incorrectly
						// in certain situations (Bug #8070).
						// Fragments from the fragment cache must always be cloned and never used
						// in place.
						results.cacheable || ( l > 1 && i < lastIndex ) ?
							jQuery.clone( fragment, true, true ) :
							fragment
					);
				}
			}

			if ( scripts.length ) {
				jQuery.each( scripts, evalScript );
			}
		}

		return this;
	}
});

function root( elem, cur ) {
	return jQuery.nodeName(elem, "table") ?
		(elem.getElementsByTagName("tbody")[0] ||
		elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
		elem;
}

function cloneCopyEvent( src, dest ) {

	if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
		return;
	}

	var type, i, l,
		oldData = jQuery._data( src ),
		curData = jQuery._data( dest, oldData ),
		events = oldData.events;

	if ( events ) {
		delete curData.handle;
		curData.events = {};

		for ( type in events ) {
			for ( i = 0, l = events[ type ].length; i < l; i++ ) {
				jQuery.event.add( dest, type + ( events[ type ][ i ].namespace ? "." : "" ) + events[ type ][ i ].namespace, events[ type ][ i ], events[ type ][ i ].data );
			}
		}
	}

	// make the cloned public data object a copy from the original
	if ( curData.data ) {
		curData.data = jQuery.extend( {}, curData.data );
	}
}

function cloneFixAttributes( src, dest ) {
	var nodeName;

	// We do not need to do anything for non-Elements
	if ( dest.nodeType !== 1 ) {
		return;
	}

	// clearAttributes removes the attributes, which we don't want,
	// but also removes the attachEvent events, which we *do* want
	if ( dest.clearAttributes ) {
		dest.clearAttributes();
	}

	// mergeAttributes, in contrast, only merges back on the
	// original attributes, not the events
	if ( dest.mergeAttributes ) {
		dest.mergeAttributes( src );
	}

	nodeName = dest.nodeName.toLowerCase();

	// IE6-8 fail to clone children inside object elements that use
	// the proprietary classid attribute value (rather than the type
	// attribute) to identify the type of content to display
	if ( nodeName === "object" ) {
		dest.outerHTML = src.outerHTML;

	} else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) {
		// IE6-8 fails to persist the checked state of a cloned checkbox
		// or radio button. Worse, IE6-7 fail to give the cloned element
		// a checked appearance if the defaultChecked value isn't also set
		if ( src.checked ) {
			dest.defaultChecked = dest.checked = src.checked;
		}

		// IE6-7 get confused and end up setting the value of a cloned
		// checkbox/radio button to an empty string instead of "on"
		if ( dest.value !== src.value ) {
			dest.value = src.value;
		}

	// IE6-8 fails to return the selected option to the default selected
	// state when cloning options
	} else if ( nodeName === "option" ) {
		dest.selected = src.defaultSelected;

	// IE6-8 fails to set the defaultValue to the correct value when
	// cloning other types of input fields
	} else if ( nodeName === "input" || nodeName === "textarea" ) {
		dest.defaultValue = src.defaultValue;
	}

	// Event data gets referenced instead of copied if the expando
	// gets copied too
	dest.removeAttribute( jQuery.expando );
}

jQuery.buildFragment = function( args, nodes, scripts ) {
	var fragment, cacheable, cacheresults, doc,
	first = args[ 0 ];

	// nodes may contain either an explicit document object,
	// a jQuery collection or context object.
	// If nodes[0] contains a valid object to assign to doc
	if ( nodes && nodes[0] ) {
		doc = nodes[0].ownerDocument || nodes[0];
	}

	// Ensure that an attr object doesn't incorrectly stand in as a document object
	// Chrome and Firefox seem to allow this to occur and will throw exception
	// Fixes #8950
	if ( !doc.createDocumentFragment ) {
		doc = document;
	}

	// Only cache "small" (1/2 KB) HTML strings that are associated with the main document
	// Cloning options loses the selected state, so don't cache them
	// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
	// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
	// Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501
	if ( args.length === 1 && typeof first === "string" && first.length < 512 && doc === document &&
		first.charAt(0) === "<" && !rnocache.test( first ) &&
		(jQuery.support.checkClone || !rchecked.test( first )) &&
		(jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {

		cacheable = true;

		cacheresults = jQuery.fragments[ first ];
		if ( cacheresults && cacheresults !== 1 ) {
			fragment = cacheresults;
		}
	}

	if ( !fragment ) {
		fragment = doc.createDocumentFragment();
		jQuery.clean( args, doc, fragment, scripts );
	}

	if ( cacheable ) {
		jQuery.fragments[ first ] = cacheresults ? fragment : 1;
	}

	return { fragment: fragment, cacheable: cacheable };
};

jQuery.fragments = {};

jQuery.each({
	appendTo: "append",
	prependTo: "prepend",
	insertBefore: "before",
	insertAfter: "after",
	replaceAll: "replaceWith"
}, function( name, original ) {
	jQuery.fn[ name ] = function( selector ) {
		var ret = [],
			insert = jQuery( selector ),
			parent = this.length === 1 && this[0].parentNode;

		if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
			insert[ original ]( this[0] );
			return this;

		} else {
			for ( var i = 0, l = insert.length; i < l; i++ ) {
				var elems = ( i > 0 ? this.clone(true) : this ).get();
				jQuery( insert[i] )[ original ]( elems );
				ret = ret.concat( elems );
			}

			return this.pushStack( ret, name, insert.selector );
		}
	};
});

function getAll( elem ) {
	if ( typeof elem.getElementsByTagName !== "undefined" ) {
		return elem.getElementsByTagName( "*" );

	} else if ( typeof elem.querySelectorAll !== "undefined" ) {
		return elem.querySelectorAll( "*" );

	} else {
		return [];
	}
}

// Used in clean, fixes the defaultChecked property
function fixDefaultChecked( elem ) {
	if ( elem.type === "checkbox" || elem.type === "radio" ) {
		elem.defaultChecked = elem.checked;
	}
}
// Finds all inputs and passes them to fixDefaultChecked
function findInputs( elem ) {
	var nodeName = ( elem.nodeName || "" ).toLowerCase();
	if ( nodeName === "input" ) {
		fixDefaultChecked( elem );
	// Skip scripts, get other children
	} else if ( nodeName !== "script" && typeof elem.getElementsByTagName !== "undefined" ) {
		jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
	}
}

// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js
function shimCloneNode( elem ) {
	var div = document.createElement( "div" );
	safeFragment.appendChild( div );

	div.innerHTML = elem.outerHTML;
	return div.firstChild;
}

jQuery.extend({
	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
		var srcElements,
			destElements,
			i,
			// IE<=8 does not properly clone detached, unknown element nodes
			clone = jQuery.support.html5Clone || !rnoshimcache.test( "<" + elem.nodeName ) ?
				elem.cloneNode( true ) :
				shimCloneNode( elem );

		if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
				(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
			// IE copies events bound via attachEvent when using cloneNode.
			// Calling detachEvent on the clone will also remove the events
			// from the original. In order to get around this, we use some
			// proprietary methods to clear the events. Thanks to MooTools
			// guys for this hotness.

			cloneFixAttributes( elem, clone );

			// Using Sizzle here is crazy slow, so we use getElementsByTagName instead
			srcElements = getAll( elem );
			destElements = getAll( clone );

			// Weird iteration because IE will replace the length property
			// with an element if you are cloning the body and one of the
			// elements on the page has a name or id of "length"
			for ( i = 0; srcElements[i]; ++i ) {
				// Ensure that the destination node is not null; Fixes #9587
				if ( destElements[i] ) {
					cloneFixAttributes( srcElements[i], destElements[i] );
				}
			}
		}

		// Copy the events from the original to the clone
		if ( dataAndEvents ) {
			cloneCopyEvent( elem, clone );

			if ( deepDataAndEvents ) {
				srcElements = getAll( elem );
				destElements = getAll( clone );

				for ( i = 0; srcElements[i]; ++i ) {
					cloneCopyEvent( srcElements[i], destElements[i] );
				}
			}
		}

		srcElements = destElements = null;

		// Return the cloned set
		return clone;
	},

	clean: function( elems, context, fragment, scripts ) {
		var checkScriptType;

		context = context || document;

		// !context.createElement fails in IE with an error but returns typeof 'object'
		if ( typeof context.createElement === "undefined" ) {
			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
		}

		var ret = [], j;

		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
			if ( typeof elem === "number" ) {
				elem += "";
			}

			if ( !elem ) {
				continue;
			}

			// Convert html string into DOM nodes
			if ( typeof elem === "string" ) {
				if ( !rhtml.test( elem ) ) {
					elem = context.createTextNode( elem );
				} else {
					// Fix "XHTML"-style tags in all browsers
					elem = elem.replace(rxhtmlTag, "<$1></$2>");

					// Trim whitespace, otherwise indexOf won't work as expected
					var tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(),
						wrap = wrapMap[ tag ] || wrapMap._default,
						depth = wrap[0],
						div = context.createElement("div");

					// Append wrapper element to unknown element safe doc fragment
					if ( context === document ) {
						// Use the fragment we've already created for this document
						safeFragment.appendChild( div );
					} else {
						// Use a fragment created with the owner document
						createSafeFragment( context ).appendChild( div );
					}

					// Go to html and back, then peel off extra wrappers
					div.innerHTML = wrap[1] + elem + wrap[2];

					// Move to the right depth
					while ( depth-- ) {
						div = div.lastChild;
					}

					// Remove IE's autoinserted <tbody> from table fragments
					if ( !jQuery.support.tbody ) {

						// String was a <table>, *may* have spurious <tbody>
						var hasBody = rtbody.test(elem),
							tbody = tag === "table" && !hasBody ?
								div.firstChild && div.firstChild.childNodes :

								// String was a bare <thead> or <tfoot>
								wrap[1] === "<table>" && !hasBody ?
									div.childNodes :
									[];

						for ( j = tbody.length - 1; j >= 0 ; --j ) {
							if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
								tbody[ j ].parentNode.removeChild( tbody[ j ] );
							}
						}
					}

					// IE completely kills leading whitespace when innerHTML is used
					if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
						div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
					}

					elem = div.childNodes;
				}
			}

			// Resets defaultChecked for any radios and checkboxes
			// about to be appended to the DOM in IE 6/7 (#8060)
			var len;
			if ( !jQuery.support.appendChecked ) {
				if ( elem[0] && typeof (len = elem.length) === "number" ) {
					for ( j = 0; j < len; j++ ) {
						findInputs( elem[j] );
					}
				} else {
					findInputs( elem );
				}
			}

			if ( elem.nodeType ) {
				ret.push( elem );
			} else {
				ret = jQuery.merge( ret, elem );
			}
		}

		if ( fragment ) {
			checkScriptType = function( elem ) {
				return !elem.type || rscriptType.test( elem.type );
			};
			for ( i = 0; ret[i]; i++ ) {
				if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
					scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );

				} else {
					if ( ret[i].nodeType === 1 ) {
						var jsTags = jQuery.grep( ret[i].getElementsByTagName( "script" ), checkScriptType );

						ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
					}
					fragment.appendChild( ret[i] );
				}
			}
		}

		return ret;
	},

	cleanData: function( elems ) {
		var data, id,
			cache = jQuery.cache,
			special = jQuery.event.special,
			deleteExpando = jQuery.support.deleteExpando;

		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
			if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
				continue;
			}

			id = elem[ jQuery.expando ];

			if ( id ) {
				data = cache[ id ];

				if ( data && data.events ) {
					for ( var type in data.events ) {
						if ( special[ type ] ) {
							jQuery.event.remove( elem, type );

						// This is a shortcut to avoid jQuery.event.remove's overhead
						} else {
							jQuery.removeEvent( elem, type, data.handle );
						}
					}

					// Null the DOM reference to avoid IE6/7/8 leak (#7054)
					if ( data.handle ) {
						data.handle.elem = null;
					}
				}

				if ( deleteExpando ) {
					delete elem[ jQuery.expando ];

				} else if ( elem.removeAttribute ) {
					elem.removeAttribute( jQuery.expando );
				}

				delete cache[ id ];
			}
		}
	}
});

function evalScript( i, elem ) {
	if ( elem.src ) {
		jQuery.ajax({
			url: elem.src,
			async: false,
			dataType: "script"
		});
	} else {
		jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "/*$0*/" ) );
	}

	if ( elem.parentNode ) {
		elem.parentNode.removeChild( elem );
	}
}




var ralpha = /alpha\([^)]*\)/i,
	ropacity = /opacity=([^)]*)/,
	// fixed for IE9, see #8346
	rupper = /([A-Z]|^ms)/g,
	rnumpx = /^-?\d+(?:px)?$/i,
	rnum = /^-?\d/,
	rrelNum = /^([\-+])=([\-+.\de]+)/,

	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
	cssWidth = [ "Left", "Right" ],
	cssHeight = [ "Top", "Bottom" ],
	curCSS,

	getComputedStyle,
	currentStyle;

jQuery.fn.css = function( name, value ) {
	// Setting 'undefined' is a no-op
	if ( arguments.length === 2 && value === undefined ) {
		return this;
	}

	return jQuery.access( this, name, value, true, function( elem, name, value ) {
		return value !== undefined ?
			jQuery.style( elem, name, value ) :
			jQuery.css( elem, name );
	});
};

jQuery.extend({
	// Add in style property hooks for overriding the default
	// behavior of getting and setting a style property
	cssHooks: {
		opacity: {
			get: function( elem, computed ) {
				if ( computed ) {
					// We should always get a number back from opacity
					var ret = curCSS( elem, "opacity", "opacity" );
					return ret === "" ? "1" : ret;

				} else {
					return elem.style.opacity;
				}
			}
		}
	},

	// Exclude the following css properties to add px
	cssNumber: {
		"fillOpacity": true,
		"fontWeight": true,
		"lineHeight": true,
		"opacity": true,
		"orphans": true,
		"widows": true,
		"zIndex": true,
		"zoom": true
	},

	// Add in properties whose names you wish to fix before
	// setting or getting the value
	cssProps: {
		// normalize float css property
		"float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
	},

	// Get and set the style property on a DOM Node
	style: function( elem, name, value, extra ) {
		// Don't set styles on text and comment nodes
		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
			return;
		}

		// Make sure that we're working with the right name
		var ret, type, origName = jQuery.camelCase( name ),
			style = elem.style, hooks = jQuery.cssHooks[ origName ];

		name = jQuery.cssProps[ origName ] || origName;

		// Check if we're setting a value
		if ( value !== undefined ) {
			type = typeof value;

			// convert relative number strings (+= or -=) to relative numbers. #7345
			if ( type === "string" && (ret = rrelNum.exec( value )) ) {
				value = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );
				// Fixes bug #9237
				type = "number";
			}

			// Make sure that NaN and null values aren't set. See: #7116
			if ( value == null || type === "number" && isNaN( value ) ) {
				return;
			}

			// If a number was passed in, add 'px' to the (except for certain CSS properties)
			if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
				value += "px";
			}

			// If a hook was provided, use that value, otherwise just set the specified value
			if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
				// Wrapped to prevent IE from throwing errors when 'invalid' values are provided
				// Fixes bug #5509
				try {
					style[ name ] = value;
				} catch(e) {}
			}

		} else {
			// If a hook was provided get the non-computed value from there
			if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
				return ret;
			}

			// Otherwise just get the value from the style object
			return style[ name ];
		}
	},

	css: function( elem, name, extra ) {
		var ret, hooks;

		// Make sure that we're working with the right name
		name = jQuery.camelCase( name );
		hooks = jQuery.cssHooks[ name ];
		name = jQuery.cssProps[ name ] || name;

		// cssFloat needs a special treatment
		if ( name === "cssFloat" ) {
			name = "float";
		}

		// If a hook was provided get the computed value from there
		if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {
			return ret;

		// Otherwise, if a way to get the computed value exists, use that
		} else if ( curCSS ) {
			return curCSS( elem, name );
		}
	},

	// A method for quickly swapping in/out CSS properties to get correct calculations
	swap: function( elem, options, callback ) {
		var old = {};

		// Remember the old values, and insert the new ones
		for ( var name in options ) {
			old[ name ] = elem.style[ name ];
			elem.style[ name ] = options[ name ];
		}

		callback.call( elem );

		// Revert the old values
		for ( name in options ) {
			elem.style[ name ] = old[ name ];
		}
	}
});

// DEPRECATED, Use jQuery.css() instead
jQuery.curCSS = jQuery.css;

jQuery.each(["height", "width"], function( i, name ) {
	jQuery.cssHooks[ name ] = {
		get: function( elem, computed, extra ) {
			var val;

			if ( computed ) {
				if ( elem.offsetWidth !== 0 ) {
					return getWH( elem, name, extra );
				} else {
					jQuery.swap( elem, cssShow, function() {
						val = getWH( elem, name, extra );
					});
				}

				return val;
			}
		},

		set: function( elem, value ) {
			if ( rnumpx.test( value ) ) {
				// ignore negative width and height values #1599
				value = parseFloat( value );

				if ( value >= 0 ) {
					return value + "px";
				}

			} else {
				return value;
			}
		}
	};
});

if ( !jQuery.support.opacity ) {
	jQuery.cssHooks.opacity = {
		get: function( elem, computed ) {
			// IE uses filters for opacity
			return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
				( parseFloat( RegExp.$1 ) / 100 ) + "" :
				computed ? "1" : "";
		},

		set: function( elem, value ) {
			var style = elem.style,
				currentStyle = elem.currentStyle,
				opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
				filter = currentStyle && currentStyle.filter || style.filter || "";

			// IE has trouble with opacity if it does not have layout
			// Force it by setting the zoom level
			style.zoom = 1;

			// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
			if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" ) {

				// Setting style.filter to null, "" & " " still leave "filter:" in the cssText
				// if "filter:" is present at all, clearType is disabled, we want to avoid this
				// style.removeAttribute is IE Only, but so apparently is this code path...
				style.removeAttribute( "filter" );

				// if there there is no filter style applied in a css rule, we are done
				if ( currentStyle && !currentStyle.filter ) {
					return;
				}
			}

			// otherwise, set new filter values
			style.filter = ralpha.test( filter ) ?
				filter.replace( ralpha, opacity ) :
				filter + " " + opacity;
		}
	};
}

jQuery(function() {
	// This hook cannot be added until DOM ready because the support test
	// for it is not run until after DOM ready
	if ( !jQuery.support.reliableMarginRight ) {
		jQuery.cssHooks.marginRight = {
			get: function( elem, computed ) {
				// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
				// Work around by temporarily setting element display to inline-block
				var ret;
				jQuery.swap( elem, { "display": "inline-block" }, function() {
					if ( computed ) {
						ret = curCSS( elem, "margin-right", "marginRight" );
					} else {
						ret = elem.style.marginRight;
					}
				});
				return ret;
			}
		};
	}
});

if ( document.defaultView && document.defaultView.getComputedStyle ) {
	getComputedStyle = function( elem, name ) {
		var ret, defaultView, computedStyle;

		name = name.replace( rupper, "-$1" ).toLowerCase();

		if ( (defaultView = elem.ownerDocument.defaultView) &&
				(computedStyle = defaultView.getComputedStyle( elem, null )) ) {
			ret = computedStyle.getPropertyValue( name );
			if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
				ret = jQuery.style( elem, name );
			}
		}

		return ret;
	};
}

if ( document.documentElement.currentStyle ) {
	currentStyle = function( elem, name ) {
		var left, rsLeft, uncomputed,
			ret = elem.currentStyle && elem.currentStyle[ name ],
			style = elem.style;

		// Avoid setting ret to empty string here
		// so we don't default to auto
		if ( ret === null && style && (uncomputed = style[ name ]) ) {
			ret = uncomputed;
		}

		// From the awesome hack by Dean Edwards
		// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291

		// If we're not dealing with a regular pixel number
		// but a number that has a weird ending, we need to convert it to pixels
		if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {

			// Remember the original values
			left = style.left;
			rsLeft = elem.runtimeStyle && elem.runtimeStyle.left;

			// Put in the new values to get a computed value out
			if ( rsLeft ) {
				elem.runtimeStyle.left = elem.currentStyle.left;
			}
			style.left = name === "fontSize" ? "1em" : ( ret || 0 );
			ret = style.pixelLeft + "px";

			// Revert the changed values
			style.left = left;
			if ( rsLeft ) {
				elem.runtimeStyle.left = rsLeft;
			}
		}

		return ret === "" ? "auto" : ret;
	};
}

curCSS = getComputedStyle || currentStyle;

function getWH( elem, name, extra ) {

	// Start with offset property
	var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
		which = name === "width" ? cssWidth : cssHeight,
		i = 0,
		len = which.length;

	if ( val > 0 ) {
		if ( extra !== "border" ) {
			for ( ; i < len; i++ ) {
				if ( !extra ) {
					val -= parseFloat( jQuery.css( elem, "padding" + which[ i ] ) ) || 0;
				}
				if ( extra === "margin" ) {
					val += parseFloat( jQuery.css( elem, extra + which[ i ] ) ) || 0;
				} else {
					val -= parseFloat( jQuery.css( elem, "border" + which[ i ] + "Width" ) ) || 0;
				}
			}
		}

		return val + "px";
	}

	// Fall back to computed then uncomputed css if necessary
	val = curCSS( elem, name, name );
	if ( val < 0 || val == null ) {
		val = elem.style[ name ] || 0;
	}
	// Normalize "", auto, and prepare for extra
	val = parseFloat( val ) || 0;

	// Add padding, border, margin
	if ( extra ) {
		for ( ; i < len; i++ ) {
			val += parseFloat( jQuery.css( elem, "padding" + which[ i ] ) ) || 0;
			if ( extra !== "padding" ) {
				val += parseFloat( jQuery.css( elem, "border" + which[ i ] + "Width" ) ) || 0;
			}
			if ( extra === "margin" ) {
				val += parseFloat( jQuery.css( elem, extra + which[ i ] ) ) || 0;
			}
		}
	}

	return val + "px";
}

if ( jQuery.expr && jQuery.expr.filters ) {
	jQuery.expr.filters.hidden = function( elem ) {
		var width = elem.offsetWidth,
			height = elem.offsetHeight;

		return ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
	};

	jQuery.expr.filters.visible = function( elem ) {
		return !jQuery.expr.filters.hidden( elem );
	};
}




var r20 = /%20/g,
	rbracket = /\[\]$/,
	rCRLF = /\r?\n/g,
	rhash = /#.*$/,
	rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
	rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
	// #7653, #8125, #8152: local protocol detection
	rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,
	rnoContent = /^(?:GET|HEAD)$/,
	rprotocol = /^\/\//,
	rquery = /\?/,
	rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
	rselectTextarea = /^(?:select|textarea)/i,
	rspacesAjax = /\s+/,
	rts = /([?&])_=[^&]*/,
	rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,

	// Keep a copy of the old load method
	_load = jQuery.fn.load,

	/* Prefilters
	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
	 * 2) These are called:
	 *    - BEFORE asking for a transport
	 *    - AFTER param serialization (s.data is a string if s.processData is true)
	 * 3) key is the dataType
	 * 4) the catchall symbol "*" can be used
	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
	 */
	prefilters = {},

	/* Transports bindings
	 * 1) key is the dataType
	 * 2) the catchall symbol "*" can be used
	 * 3) selection will start with transport dataType and THEN go to "*" if needed
	 */
	transports = {},

	// Document location
	ajaxLocation,

	// Document location segments
	ajaxLocParts,

	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
	allTypes = ["*/"] + ["*"];

// #8138, IE may throw an exception when accessing
// a field from window.location if document.domain has been set
try {
	ajaxLocation = location.href;
} catch( e ) {
	// Use the href attribute of an A element
	// since IE will modify it given document.location
	ajaxLocation = document.createElement( "a" );
	ajaxLocation.href = "";
	ajaxLocation = ajaxLocation.href;
}

// Segment location into parts
ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];

// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
function addToPrefiltersOrTransports( structure ) {

	// dataTypeExpression is optional and defaults to "*"
	return function( dataTypeExpression, func ) {

		if ( typeof dataTypeExpression !== "string" ) {
			func = dataTypeExpression;
			dataTypeExpression = "*";
		}

		if ( jQuery.isFunction( func ) ) {
			var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),
				i = 0,
				length = dataTypes.length,
				dataType,
				list,
				placeBefore;

			// For each dataType in the dataTypeExpression
			for ( ; i < length; i++ ) {
				dataType = dataTypes[ i ];
				// We control if we're asked to add before
				// any existing element
				placeBefore = /^\+/.test( dataType );
				if ( placeBefore ) {
					dataType = dataType.substr( 1 ) || "*";
				}
				list = structure[ dataType ] = structure[ dataType ] || [];
				// then we add to the structure accordingly
				list[ placeBefore ? "unshift" : "push" ]( func );
			}
		}
	};
}

// Base inspection function for prefilters and transports
function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,
		dataType /* internal */, inspected /* internal */ ) {

	dataType = dataType || options.dataTypes[ 0 ];
	inspected = inspected || {};

	inspected[ dataType ] = true;

	var list = structure[ dataType ],
		i = 0,
		length = list ? list.length : 0,
		executeOnly = ( structure === prefilters ),
		selection;

	for ( ; i < length && ( executeOnly || !selection ); i++ ) {
		selection = list[ i ]( options, originalOptions, jqXHR );
		// If we got redirected to another dataType
		// we try there if executing only and not done already
		if ( typeof selection === "string" ) {
			if ( !executeOnly || inspected[ selection ] ) {
				selection = undefined;
			} else {
				options.dataTypes.unshift( selection );
				selection = inspectPrefiltersOrTransports(
						structure, options, originalOptions, jqXHR, selection, inspected );
			}
		}
	}
	// If we're only executing or nothing was selected
	// we try the catchall dataType if not done already
	if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) {
		selection = inspectPrefiltersOrTransports(
				structure, options, originalOptions, jqXHR, "*", inspected );
	}
	// unnecessary when only executing (prefilters)
	// but it'll be ignored by the caller in that case
	return selection;
}

// A special extend for ajax options
// that takes "flat" options (not to be deep extended)
// Fixes #9887
function ajaxExtend( target, src ) {
	var key, deep,
		flatOptions = jQuery.ajaxSettings.flatOptions || {};
	for ( key in src ) {
		if ( src[ key ] !== undefined ) {
			( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
		}
	}
	if ( deep ) {
		jQuery.extend( true, target, deep );
	}
}

jQuery.fn.extend({
	load: function( url, params, callback ) {
		if ( typeof url !== "string" && _load ) {
			return _load.apply( this, arguments );

		// Don't do a request if no elements are being requested
		} else if ( !this.length ) {
			return this;
		}

		var off = url.indexOf( " " );
		if ( off >= 0 ) {
			var selector = url.slice( off, url.length );
			url = url.slice( 0, off );
		}

		// Default to a GET request
		var type = "GET";

		// If the second parameter was provided
		if ( params ) {
			// If it's a function
			if ( jQuery.isFunction( params ) ) {
				// We assume that it's the callback
				callback = params;
				params = undefined;

			// Otherwise, build a param string
			} else if ( typeof params === "object" ) {
				params = jQuery.param( params, jQuery.ajaxSettings.traditional );
				type = "POST";
			}
		}

		var self = this;

		// Request the remote document
		jQuery.ajax({
			url: url,
			type: type,
			dataType: "html",
			data: params,
			// Complete callback (responseText is used internally)
			complete: function( jqXHR, status, responseText ) {
				// Store the response as specified by the jqXHR object
				responseText = jqXHR.responseText;
				// If successful, inject the HTML into all the matched elements
				if ( jqXHR.isResolved() ) {
					// #4825: Get the actual response in case
					// a dataFilter is present in ajaxSettings
					jqXHR.done(function( r ) {
						responseText = r;
					});
					// See if a selector was specified
					self.html( selector ?
						// Create a dummy div to hold the results
						jQuery("<div>")
							// inject the contents of the document in, removing the scripts
							// to avoid any 'Permission Denied' errors in IE
							.append(responseText.replace(rscript, ""))

							// Locate the specified elements
							.find(selector) :

						// If not, just inject the full result
						responseText );
				}

				if ( callback ) {
					self.each( callback, [ responseText, status, jqXHR ] );
				}
			}
		});

		return this;
	},

	serialize: function() {
		return jQuery.param( this.serializeArray() );
	},

	serializeArray: function() {
		return this.map(function(){
			return this.elements ? jQuery.makeArray( this.elements ) : this;
		})
		.filter(function(){
			return this.name && !this.disabled &&
				( this.checked || rselectTextarea.test( this.nodeName ) ||
					rinput.test( this.type ) );
		})
		.map(function( i, elem ){
			var val = jQuery( this ).val();

			return val == null ?
				null :
				jQuery.isArray( val ) ?
					jQuery.map( val, function( val, i ){
						return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
					}) :
					{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
		}).get();
	}
});

// Attach a bunch of functions for handling common AJAX events
jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){
	jQuery.fn[ o ] = function( f ){
		return this.on( o, f );
	};
});

jQuery.each( [ "get", "post" ], function( i, method ) {
	jQuery[ method ] = function( url, data, callback, type ) {
		// shift arguments if data argument was omitted
		if ( jQuery.isFunction( data ) ) {
			type = type || callback;
			callback = data;
			data = undefined;
		}

		return jQuery.ajax({
			type: method,
			url: url,
			data: data,
			success: callback,
			dataType: type
		});
	};
});

jQuery.extend({

	getScript: function( url, callback ) {
		return jQuery.get( url, undefined, callback, "script" );
	},

	getJSON: function( url, data, callback ) {
		return jQuery.get( url, data, callback, "json" );
	},

	// Creates a full fledged settings object into target
	// with both ajaxSettings and settings fields.
	// If target is omitted, writes into ajaxSettings.
	ajaxSetup: function( target, settings ) {
		if ( settings ) {
			// Building a settings object
			ajaxExtend( target, jQuery.ajaxSettings );
		} else {
			// Extending ajaxSettings
			settings = target;
			target = jQuery.ajaxSettings;
		}
		ajaxExtend( target, settings );
		return target;
	},

	ajaxSettings: {
		url: ajaxLocation,
		isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
		global: true,
		type: "GET",
		contentType: "application/x-www-form-urlencoded",
		processData: true,
		async: true,
		/*
		timeout: 0,
		data: null,
		dataType: null,
		username: null,
		password: null,
		cache: null,
		traditional: false,
		headers: {},
		*/

		accepts: {
			xml: "application/xml, text/xml",
			html: "text/html",
			text: "text/plain",
			json: "application/json, text/javascript",
			"*": allTypes
		},

		contents: {
			xml: /xml/,
			html: /html/,
			json: /json/
		},

		responseFields: {
			xml: "responseXML",
			text: "responseText"
		},

		// List of data converters
		// 1) key format is "source_type destination_type" (a single space in-between)
		// 2) the catchall symbol "*" can be used for source_type
		converters: {

			// Convert anything to text
			"* text": window.String,

			// Text to html (true = no transformation)
			"text html": true,

			// Evaluate text as a json expression
			"text json": jQuery.parseJSON,

			// Parse text as xml
			"text xml": jQuery.parseXML
		},

		// For options that shouldn't be deep extended:
		// you can add your own custom options here if
		// and when you create one that shouldn't be
		// deep extended (see ajaxExtend)
		flatOptions: {
			context: true,
			url: true
		}
	},

	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
	ajaxTransport: addToPrefiltersOrTransports( transports ),

	// Main method
	ajax: function( url, options ) {

		// If url is an object, simulate pre-1.5 signature
		if ( typeof url === "object" ) {
			options = url;
			url = undefined;
		}

		// Force options to be an object
		options = options || {};

		var // Create the final options object
			s = jQuery.ajaxSetup( {}, options ),
			// Callbacks context
			callbackContext = s.context || s,
			// Context for global events
			// It's the callbackContext if one was provided in the options
			// and if it's a DOM node or a jQuery collection
			globalEventContext = callbackContext !== s &&
				( callbackContext.nodeType || callbackContext instanceof jQuery ) ?
						jQuery( callbackContext ) : jQuery.event,
			// Deferreds
			deferred = jQuery.Deferred(),
			completeDeferred = jQuery.Callbacks( "once memory" ),
			// Status-dependent callbacks
			statusCode = s.statusCode || {},
			// ifModified key
			ifModifiedKey,
			// Headers (they are sent all at once)
			requestHeaders = {},
			requestHeadersNames = {},
			// Response headers
			responseHeadersString,
			responseHeaders,
			// transport
			transport,
			// timeout handle
			timeoutTimer,
			// Cross-domain detection vars
			parts,
			// The jqXHR state
			state = 0,
			// To know if global events are to be dispatched
			fireGlobals,
			// Loop variable
			i,
			// Fake xhr
			jqXHR = {

				readyState: 0,

				// Caches the header
				setRequestHeader: function( name, value ) {
					if ( !state ) {
						var lname = name.toLowerCase();
						name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
						requestHeaders[ name ] = value;
					}
					return this;
				},

				// Raw string
				getAllResponseHeaders: function() {
					return state === 2 ? responseHeadersString : null;
				},

				// Builds headers hashtable if needed
				getResponseHeader: function( key ) {
					var match;
					if ( state === 2 ) {
						if ( !responseHeaders ) {
							responseHeaders = {};
							while( ( match = rheaders.exec( responseHeadersString ) ) ) {
								responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
							}
						}
						match = responseHeaders[ key.toLowerCase() ];
					}
					return match === undefined ? null : match;
				},

				// Overrides response content-type header
				overrideMimeType: function( type ) {
					if ( !state ) {
						s.mimeType = type;
					}
					return this;
				},

				// Cancel the request
				abort: function( statusText ) {
					statusText = statusText || "abort";
					if ( transport ) {
						transport.abort( statusText );
					}
					done( 0, statusText );
					return this;
				}
			};

		// Callback for when everything is done
		// It is defined here because jslint complains if it is declared
		// at the end of the function (which would be more logical and readable)
		function done( status, nativeStatusText, responses, headers ) {

			// Called once
			if ( state === 2 ) {
				return;
			}

			// State is "done" now
			state = 2;

			// Clear timeout if it exists
			if ( timeoutTimer ) {
				clearTimeout( timeoutTimer );
			}

			// Dereference transport for early garbage collection
			// (no matter how long the jqXHR object will be used)
			transport = undefined;

			// Cache response headers
			responseHeadersString = headers || "";

			// Set readyState
			jqXHR.readyState = status > 0 ? 4 : 0;

			var isSuccess,
				success,
				error,
				statusText = nativeStatusText,
				response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,
				lastModified,
				etag;

			// If successful, handle type chaining
			if ( status >= 200 && status < 300 || status === 304 ) {

				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
				if ( s.ifModified ) {

					if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) {
						jQuery.lastModified[ ifModifiedKey ] = lastModified;
					}
					if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) {
						jQuery.etag[ ifModifiedKey ] = etag;
					}
				}

				// If not modified
				if ( status === 304 ) {

					statusText = "notmodified";
					isSuccess = true;

				// If we have data
				} else {

					try {
						success = ajaxConvert( s, response );
						statusText = "success";
						isSuccess = true;
					} catch(e) {
						// We have a parsererror
						statusText = "parsererror";
						error = e;
					}
				}
			} else {
				// We extract error from statusText
				// then normalize statusText and status for non-aborts
				error = statusText;
				if ( !statusText || status ) {
					statusText = "error";
					if ( status < 0 ) {
						status = 0;
					}
				}
			}

			// Set data for the fake xhr object
			jqXHR.status = status;
			jqXHR.statusText = "" + ( nativeStatusText || statusText );

			// Success/Error
			if ( isSuccess ) {
				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
			} else {
				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
			}

			// Status-dependent callbacks
			jqXHR.statusCode( statusCode );
			statusCode = undefined;

			if ( fireGlobals ) {
				globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
						[ jqXHR, s, isSuccess ? success : error ] );
			}

			// Complete
			completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );

			if ( fireGlobals ) {
				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
				// Handle the global AJAX counter
				if ( !( --jQuery.active ) ) {
					jQuery.event.trigger( "ajaxStop" );
				}
			}
		}

		// Attach deferreds
		deferred.promise( jqXHR );
		jqXHR.success = jqXHR.done;
		jqXHR.error = jqXHR.fail;
		jqXHR.complete = completeDeferred.add;

		// Status-dependent callbacks
		jqXHR.statusCode = function( map ) {
			if ( map ) {
				var tmp;
				if ( state < 2 ) {
					for ( tmp in map ) {
						statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
					}
				} else {
					tmp = map[ jqXHR.status ];
					jqXHR.then( tmp, tmp );
				}
			}
			return this;
		};

		// Remove hash character (#7531: and string promotion)
		// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
		// We also use the url parameter if available
		s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );

		// Extract dataTypes list
		s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax );

		// Determine if a cross-domain request is in order
		if ( s.crossDomain == null ) {
			parts = rurl.exec( s.url.toLowerCase() );
			s.crossDomain = !!( parts &&
				( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||
					( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
						( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
			);
		}

		// Convert data if not already a string
		if ( s.data && s.processData && typeof s.data !== "string" ) {
			s.data = jQuery.param( s.data, s.traditional );
		}

		// Apply prefilters
		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );

		// If request was aborted inside a prefiler, stop there
		if ( state === 2 ) {
			return false;
		}

		// We can fire global events as of now if asked to
		fireGlobals = s.global;

		// Uppercase the type
		s.type = s.type.toUpperCase();

		// Determine if request has content
		s.hasContent = !rnoContent.test( s.type );

		// Watch for a new set of requests
		if ( fireGlobals && jQuery.active++ === 0 ) {
			jQuery.event.trigger( "ajaxStart" );
		}

		// More options handling for requests with no content
		if ( !s.hasContent ) {

			// If data is available, append data to url
			if ( s.data ) {
				s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
				// #9682: remove data so that it's not used in an eventual retry
				delete s.data;
			}

			// Get ifModifiedKey before adding the anti-cache parameter
			ifModifiedKey = s.url;

			// Add anti-cache in url if needed
			if ( s.cache === false ) {

				var ts = jQuery.now(),
					// try replacing _= if it is there
					ret = s.url.replace( rts, "$1_=" + ts );

				// if nothing was replaced, add timestamp to the end
				s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );
			}
		}

		// Set the correct header, if data is being sent
		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
			jqXHR.setRequestHeader( "Content-Type", s.contentType );
		}

		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
		if ( s.ifModified ) {
			ifModifiedKey = ifModifiedKey || s.url;
			if ( jQuery.lastModified[ ifModifiedKey ] ) {
				jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] );
			}
			if ( jQuery.etag[ ifModifiedKey ] ) {
				jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] );
			}
		}

		// Set the Accepts header for the server, depending on the dataType
		jqXHR.setRequestHeader(
			"Accept",
			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
				s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
				s.accepts[ "*" ]
		);

		// Check for headers option
		for ( i in s.headers ) {
			jqXHR.setRequestHeader( i, s.headers[ i ] );
		}

		// Allow custom headers/mimetypes and early abort
		if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
				// Abort if not done already
				jqXHR.abort();
				return false;

		}

		// Install callbacks on deferreds
		for ( i in { success: 1, error: 1, complete: 1 } ) {
			jqXHR[ i ]( s[ i ] );
		}

		// Get transport
		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );

		// If no transport, we auto-abort
		if ( !transport ) {
			done( -1, "No Transport" );
		} else {
			jqXHR.readyState = 1;
			// Send global event
			if ( fireGlobals ) {
				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
			}
			// Timeout
			if ( s.async && s.timeout > 0 ) {
				timeoutTimer = setTimeout( function(){
					jqXHR.abort( "timeout" );
				}, s.timeout );
			}

			try {
				state = 1;
				transport.send( requestHeaders, done );
			} catch (e) {
				// Propagate exception as error if not done
				if ( state < 2 ) {
					done( -1, e );
				// Simply rethrow otherwise
				} else {
					throw e;
				}
			}
		}

		return jqXHR;
	},

	// Serialize an array of form elements or a set of
	// key/values into a query string
	param: function( a, traditional ) {
		var s = [],
			add = function( key, value ) {
				// If value is a function, invoke it and return its value
				value = jQuery.isFunction( value ) ? value() : value;
				s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
			};

		// Set traditional to true for jQuery <= 1.3.2 behavior.
		if ( traditional === undefined ) {
			traditional = jQuery.ajaxSettings.traditional;
		}

		// If an array was passed in, assume that it is an array of form elements.
		if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
			// Serialize the form elements
			jQuery.each( a, function() {
				add( this.name, this.value );
			});

		} else {
			// If traditional, encode the "old" way (the way 1.3.2 or older
			// did it), otherwise encode params recursively.
			for ( var prefix in a ) {
				buildParams( prefix, a[ prefix ], traditional, add );
			}
		}

		// Return the resulting serialization
		return s.join( "&" ).replace( r20, "+" );
	}
});

function buildParams( prefix, obj, traditional, add ) {
	if ( jQuery.isArray( obj ) ) {
		// Serialize array item.
		jQuery.each( obj, function( i, v ) {
			if ( traditional || rbracket.test( prefix ) ) {
				// Treat each array item as a scalar.
				add( prefix, v );

			} else {
				// If array item is non-scalar (array or object), encode its
				// numeric index to resolve deserialization ambiguity issues.
				// Note that rack (as of 1.0.0) can't currently deserialize
				// nested arrays properly, and attempting to do so may cause
				// a server error. Possible fixes are to modify rack's
				// deserialization algorithm or to provide an option or flag
				// to force array serialization to be shallow.
				buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add );
			}
		});

	} else if ( !traditional && obj != null && typeof obj === "object" ) {
		// Serialize object item.
		for ( var name in obj ) {
			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
		}

	} else {
		// Serialize scalar item.
		add( prefix, obj );
	}
}

// This is still on the jQuery object... for now
// Want to move this to jQuery.ajax some day
jQuery.extend({

	// Counter for holding the number of active queries
	active: 0,

	// Last-Modified header cache for next request
	lastModified: {},
	etag: {}

});

/* Handles responses to an ajax request:
 * - sets all responseXXX fields accordingly
 * - finds the right dataType (mediates between content-type and expected dataType)
 * - returns the corresponding response
 */
function ajaxHandleResponses( s, jqXHR, responses ) {

	var contents = s.contents,
		dataTypes = s.dataTypes,
		responseFields = s.responseFields,
		ct,
		type,
		finalDataType,
		firstDataType;

	// Fill responseXXX fields
	for ( type in responseFields ) {
		if ( type in responses ) {
			jqXHR[ responseFields[type] ] = responses[ type ];
		}
	}

	// Remove auto dataType and get content-type in the process
	while( dataTypes[ 0 ] === "*" ) {
		dataTypes.shift();
		if ( ct === undefined ) {
			ct = s.mimeType || jqXHR.getResponseHeader( "content-type" );
		}
	}

	// Check if we're dealing with a known content-type
	if ( ct ) {
		for ( type in contents ) {
			if ( contents[ type ] && contents[ type ].test( ct ) ) {
				dataTypes.unshift( type );
				break;
			}
		}
	}

	// Check to see if we have a response for the expected dataType
	if ( dataTypes[ 0 ] in responses ) {
		finalDataType = dataTypes[ 0 ];
	} else {
		// Try convertible dataTypes
		for ( type in responses ) {
			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
				finalDataType = type;
				break;
			}
			if ( !firstDataType ) {
				firstDataType = type;
			}
		}
		// Or just use first one
		finalDataType = finalDataType || firstDataType;
	}

	// If we found a dataType
	// We add the dataType to the list if needed
	// and return the corresponding response
	if ( finalDataType ) {
		if ( finalDataType !== dataTypes[ 0 ] ) {
			dataTypes.unshift( finalDataType );
		}
		return responses[ finalDataType ];
	}
}

// Chain conversions given the request and the original response
function ajaxConvert( s, response ) {

	// Apply the dataFilter if provided
	if ( s.dataFilter ) {
		response = s.dataFilter( response, s.dataType );
	}

	var dataTypes = s.dataTypes,
		converters = {},
		i,
		key,
		length = dataTypes.length,
		tmp,
		// Current and previous dataTypes
		current = dataTypes[ 0 ],
		prev,
		// Conversion expression
		conversion,
		// Conversion function
		conv,
		// Conversion functions (transitive conversion)
		conv1,
		conv2;

	// For each dataType in the chain
	for ( i = 1; i < length; i++ ) {

		// Create converters map
		// with lowercased keys
		if ( i === 1 ) {
			for ( key in s.converters ) {
				if ( typeof key === "string" ) {
					converters[ key.toLowerCase() ] = s.converters[ key ];
				}
			}
		}

		// Get the dataTypes
		prev = current;
		current = dataTypes[ i ];

		// If current is auto dataType, update it to prev
		if ( current === "*" ) {
			current = prev;
		// If no auto and dataTypes are actually different
		} else if ( prev !== "*" && prev !== current ) {

			// Get the converter
			conversion = prev + " " + current;
			conv = converters[ conversion ] || converters[ "* " + current ];

			// If there is no direct converter, search transitively
			if ( !conv ) {
				conv2 = undefined;
				for ( conv1 in converters ) {
					tmp = conv1.split( " " );
					if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) {
						conv2 = converters[ tmp[1] + " " + current ];
						if ( conv2 ) {
							conv1 = converters[ conv1 ];
							if ( conv1 === true ) {
								conv = conv2;
							} else if ( conv2 === true ) {
								conv = conv1;
							}
							break;
						}
					}
				}
			}
			// If we found no converter, dispatch an error
			if ( !( conv || conv2 ) ) {
				jQuery.error( "No conversion from " + conversion.replace(" "," to ") );
			}
			// If found converter is not an equivalence
			if ( conv !== true ) {
				// Convert with 1 or 2 converters accordingly
				response = conv ? conv( response ) : conv2( conv1(response) );
			}
		}
	}
	return response;
}




var jsc = jQuery.now(),
	jsre = /(\=)\?(&|$)|\?\?/i;

// Default jsonp settings
jQuery.ajaxSetup({
	jsonp: "callback",
	jsonpCallback: function() {
		return jQuery.expando + "_" + ( jsc++ );
	}
});

// Detect, normalize options and install callbacks for jsonp requests
jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {

	var inspectData = s.contentType === "application/x-www-form-urlencoded" &&
		( typeof s.data === "string" );

	if ( s.dataTypes[ 0 ] === "jsonp" ||
		s.jsonp !== false && ( jsre.test( s.url ) ||
				inspectData && jsre.test( s.data ) ) ) {

		var responseContainer,
			jsonpCallback = s.jsonpCallback =
				jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
			previous = window[ jsonpCallback ],
			url = s.url,
			data = s.data,
			replace = "$1" + jsonpCallback + "$2";

		if ( s.jsonp !== false ) {
			url = url.replace( jsre, replace );
			if ( s.url === url ) {
				if ( inspectData ) {
					data = data.replace( jsre, replace );
				}
				if ( s.data === data ) {
					// Add callback manually
					url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback;
				}
			}
		}

		s.url = url;
		s.data = data;

		// Install callback
		window[ jsonpCallback ] = function( response ) {
			responseContainer = [ response ];
		};

		// Clean-up function
		jqXHR.always(function() {
			// Set callback back to previous value
			window[ jsonpCallback ] = previous;
			// Call if it was a function and we have a response
			if ( responseContainer && jQuery.isFunction( previous ) ) {
				window[ jsonpCallback ]( responseContainer[ 0 ] );
			}
		});

		// Use data converter to retrieve json after script execution
		s.converters["script json"] = function() {
			if ( !responseContainer ) {
				jQuery.error( jsonpCallback + " was not called" );
			}
			return responseContainer[ 0 ];
		};

		// force json dataType
		s.dataTypes[ 0 ] = "json";

		// Delegate to script
		return "script";
	}
});




// Install script dataType
jQuery.ajaxSetup({
	accepts: {
		script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
	},
	contents: {
		script: /javascript|ecmascript/
	},
	converters: {
		"text script": function( text ) {
			jQuery.globalEval( text );
			return text;
		}
	}
});

// Handle cache's special case and global
jQuery.ajaxPrefilter( "script", function( s ) {
	if ( s.cache === undefined ) {
		s.cache = false;
	}
	if ( s.crossDomain ) {
		s.type = "GET";
		s.global = false;
	}
});

// Bind script tag hack transport
jQuery.ajaxTransport( "script", function(s) {

	// This transport only deals with cross domain requests
	if ( s.crossDomain ) {

		var script,
			head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;

		return {

			send: function( _, callback ) {

				script = document.createElement( "script" );

				script.async = "async";

				if ( s.scriptCharset ) {
					script.charset = s.scriptCharset;
				}

				script.src = s.url;

				// Attach handlers for all browsers
				script.onload = script.onreadystatechange = function( _, isAbort ) {

					if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {

						// Handle memory leak in IE
						script.onload = script.onreadystatechange = null;

						// Remove the script
						if ( head && script.parentNode ) {
							head.removeChild( script );
						}

						// Dereference the script
						script = undefined;

						// Callback if not abort
						if ( !isAbort ) {
							callback( 200, "success" );
						}
					}
				};
				// Use insertBefore instead of appendChild  to circumvent an IE6 bug.
				// This arises when a base node is used (#2709 and #4378).
				head.insertBefore( script, head.firstChild );
			},

			abort: function() {
				if ( script ) {
					script.onload( 0, 1 );
				}
			}
		};
	}
});




var // #5280: Internet Explorer will keep connections alive if we don't abort on unload
	xhrOnUnloadAbort = window.ActiveXObject ? function() {
		// Abort all pending requests
		for ( var key in xhrCallbacks ) {
			xhrCallbacks[ key ]( 0, 1 );
		}
	} : false,
	xhrId = 0,
	xhrCallbacks;

// Functions to create xhrs
function createStandardXHR() {
	try {
		return new window.XMLHttpRequest();
	} catch( e ) {}
}

function createActiveXHR() {
	try {
		return new window.ActiveXObject( "Microsoft.XMLHTTP" );
	} catch( e ) {}
}

// Create the request object
// (This is still attached to ajaxSettings for backward compatibility)
jQuery.ajaxSettings.xhr = window.ActiveXObject ?
	/* Microsoft failed to properly
	 * implement the XMLHttpRequest in IE7 (can't request local files),
	 * so we use the ActiveXObject when it is available
	 * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
	 * we need a fallback.
	 */
	function() {
		return !this.isLocal && createStandardXHR() || createActiveXHR();
	} :
	// For all other browsers, use the standard XMLHttpRequest object
	createStandardXHR;

// Determine support properties
(function( xhr ) {
	jQuery.extend( jQuery.support, {
		ajax: !!xhr,
		cors: !!xhr && ( "withCredentials" in xhr )
	});
})( jQuery.ajaxSettings.xhr() );

// Create transport if the browser can provide an xhr
if ( jQuery.support.ajax ) {

	jQuery.ajaxTransport(function( s ) {
		// Cross domain only allowed if supported through XMLHttpRequest
		if ( !s.crossDomain || jQuery.support.cors ) {

			var callback;

			return {
				send: function( headers, complete ) {

					// Get a new xhr
					var xhr = s.xhr(),
						handle,
						i;

					// Open the socket
					// Passing null username, generates a login popup on Opera (#2865)
					if ( s.username ) {
						xhr.open( s.type, s.url, s.async, s.username, s.password );
					} else {
						xhr.open( s.type, s.url, s.async );
					}

					// Apply custom fields if provided
					if ( s.xhrFields ) {
						for ( i in s.xhrFields ) {
							xhr[ i ] = s.xhrFields[ i ];
						}
					}

					// Override mime type if needed
					if ( s.mimeType && xhr.overrideMimeType ) {
						xhr.overrideMimeType( s.mimeType );
					}

					// X-Requested-With header
					// For cross-domain requests, seeing as conditions for a preflight are
					// akin to a jigsaw puzzle, we simply never set it to be sure.
					// (it can always be set on a per-request basis or even using ajaxSetup)
					// For same-domain requests, won't change header if already provided.
					if ( !s.crossDomain && !headers["X-Requested-With"] ) {
						headers[ "X-Requested-With" ] = "XMLHttpRequest";
					}

					// Need an extra try/catch for cross domain requests in Firefox 3
					try {
						for ( i in headers ) {
							xhr.setRequestHeader( i, headers[ i ] );
						}
					} catch( _ ) {}

					// Do send the request
					// This may raise an exception which is actually
					// handled in jQuery.ajax (so no try/catch here)
					xhr.send( ( s.hasContent && s.data ) || null );

					// Listener
					callback = function( _, isAbort ) {

						var status,
							statusText,
							responseHeaders,
							responses,
							xml;

						// Firefox throws exceptions when accessing properties
						// of an xhr when a network error occured
						// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
						try {

							// Was never called and is aborted or complete
							if ( callback && ( isAbort || xhr.readyState === 4 ) ) {

								// Only called once
								callback = undefined;

								// Do not keep as active anymore
								if ( handle ) {
									xhr.onreadystatechange = jQuery.noop;
									if ( xhrOnUnloadAbort ) {
										delete xhrCallbacks[ handle ];
									}
								}

								// If it's an abort
								if ( isAbort ) {
									// Abort it manually if needed
									if ( xhr.readyState !== 4 ) {
										xhr.abort();
									}
								} else {
									status = xhr.status;
									responseHeaders = xhr.getAllResponseHeaders();
									responses = {};
									xml = xhr.responseXML;

									// Construct response list
									if ( xml && xml.documentElement /* #4958 */ ) {
										responses.xml = xml;
									}
									responses.text = xhr.responseText;

									// Firefox throws an exception when accessing
									// statusText for faulty cross-domain requests
									try {
										statusText = xhr.statusText;
									} catch( e ) {
										// We normalize with Webkit giving an empty statusText
										statusText = "";
									}

									// Filter status for non standard behaviors

									// If the request is local and we have data: assume a success
									// (success with no data won't get notified, that's the best we
									// can do given current implementations)
									if ( !status && s.isLocal && !s.crossDomain ) {
										status = responses.text ? 200 : 404;
									// IE - #1450: sometimes returns 1223 when it should be 204
									} else if ( status === 1223 ) {
										status = 204;
									}
								}
							}
						} catch( firefoxAccessException ) {
							if ( !isAbort ) {
								complete( -1, firefoxAccessException );
							}
						}

						// Call complete if needed
						if ( responses ) {
							complete( status, statusText, responses, responseHeaders );
						}
					};

					// if we're in sync mode or it's in cache
					// and has been retrieved directly (IE6 & IE7)
					// we need to manually fire the callback
					if ( !s.async || xhr.readyState === 4 ) {
						callback();
					} else {
						handle = ++xhrId;
						if ( xhrOnUnloadAbort ) {
							// Create the active xhrs callbacks list if needed
							// and attach the unload handler
							if ( !xhrCallbacks ) {
								xhrCallbacks = {};
								jQuery( window ).unload( xhrOnUnloadAbort );
							}
							// Add to list of active xhrs callbacks
							xhrCallbacks[ handle ] = callback;
						}
						xhr.onreadystatechange = callback;
					}
				},

				abort: function() {
					if ( callback ) {
						callback(0,1);
					}
				}
			};
		}
	});
}




var elemdisplay = {},
	iframe, iframeDoc,
	rfxtypes = /^(?:toggle|show|hide)$/,
	rfxnum = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,
	timerId,
	fxAttrs = [
		// height animations
		[ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
		// width animations
		[ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
		// opacity animations
		[ "opacity" ]
	],
	fxNow;

jQuery.fn.extend({
	show: function( speed, easing, callback ) {
		var elem, display;

		if ( speed || speed === 0 ) {
			return this.animate( genFx("show", 3), speed, easing, callback );

		} else {
			for ( var i = 0, j = this.length; i < j; i++ ) {
				elem = this[ i ];

				if ( elem.style ) {
					display = elem.style.display;

					// Reset the inline display of this element to learn if it is
					// being hidden by cascaded rules or not
					if ( !jQuery._data(elem, "olddisplay") && display === "none" ) {
						display = elem.style.display = "";
					}

					// Set elements which have been overridden with display: none
					// in a stylesheet to whatever the default browser style is
					// for such an element
					if ( display === "" && jQuery.css(elem, "display") === "none" ) {
						jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) );
					}
				}
			}

			// Set the display of most of the elements in a second loop
			// to avoid the constant reflow
			for ( i = 0; i < j; i++ ) {
				elem = this[ i ];

				if ( elem.style ) {
					display = elem.style.display;

					if ( display === "" || display === "none" ) {
						elem.style.display = jQuery._data( elem, "olddisplay" ) || "";
					}
				}
			}

			return this;
		}
	},

	hide: function( speed, easing, callback ) {
		if ( speed || speed === 0 ) {
			return this.animate( genFx("hide", 3), speed, easing, callback);

		} else {
			var elem, display,
				i = 0,
				j = this.length;

			for ( ; i < j; i++ ) {
				elem = this[i];
				if ( elem.style ) {
					display = jQuery.css( elem, "display" );

					if ( display !== "none" && !jQuery._data( elem, "olddisplay" ) ) {
						jQuery._data( elem, "olddisplay", display );
					}
				}
			}

			// Set the display of the elements in a second loop
			// to avoid the constant reflow
			for ( i = 0; i < j; i++ ) {
				if ( this[i].style ) {
					this[i].style.display = "none";
				}
			}

			return this;
		}
	},

	// Save the old toggle function
	_toggle: jQuery.fn.toggle,

	toggle: function( fn, fn2, callback ) {
		var bool = typeof fn === "boolean";

		if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
			this._toggle.apply( this, arguments );

		} else if ( fn == null || bool ) {
			this.each(function() {
				var state = bool ? fn : jQuery(this).is(":hidden");
				jQuery(this)[ state ? "show" : "hide" ]();
			});

		} else {
			this.animate(genFx("toggle", 3), fn, fn2, callback);
		}

		return this;
	},

	fadeTo: function( speed, to, easing, callback ) {
		return this.filter(":hidden").css("opacity", 0).show().end()
					.animate({opacity: to}, speed, easing, callback);
	},

	animate: function( prop, speed, easing, callback ) {
		var optall = jQuery.speed( speed, easing, callback );

		if ( jQuery.isEmptyObject( prop ) ) {
			return this.each( optall.complete, [ false ] );
		}

		// Do not change referenced properties as per-property easing will be lost
		prop = jQuery.extend( {}, prop );

		function doAnimation() {
			// XXX 'this' does not always have a nodeName when running the
			// test suite

			if ( optall.queue === false ) {
				jQuery._mark( this );
			}

			var opt = jQuery.extend( {}, optall ),
				isElement = this.nodeType === 1,
				hidden = isElement && jQuery(this).is(":hidden"),
				name, val, p, e,
				parts, start, end, unit,
				method;

			// will store per property easing and be used to determine when an animation is complete
			opt.animatedProperties = {};

			for ( p in prop ) {

				// property name normalization
				name = jQuery.camelCase( p );
				if ( p !== name ) {
					prop[ name ] = prop[ p ];
					delete prop[ p ];
				}

				val = prop[ name ];

				// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)
				if ( jQuery.isArray( val ) ) {
					opt.animatedProperties[ name ] = val[ 1 ];
					val = prop[ name ] = val[ 0 ];
				} else {
					opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';
				}

				if ( val === "hide" && hidden || val === "show" && !hidden ) {
					return opt.complete.call( this );
				}

				if ( isElement && ( name === "height" || name === "width" ) ) {
					// Make sure that nothing sneaks out
					// Record all 3 overflow attributes because IE does not
					// change the overflow attribute when overflowX and
					// overflowY are set to the same value
					opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];

					// Set display property to inline-block for height/width
					// animations on inline elements that are having width/height animated
					if ( jQuery.css( this, "display" ) === "inline" &&
							jQuery.css( this, "float" ) === "none" ) {

						// inline-level elements accept inline-block;
						// block-level elements need to be inline with layout
						if ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === "inline" ) {
							this.style.display = "inline-block";

						} else {
							this.style.zoom = 1;
						}
					}
				}
			}

			if ( opt.overflow != null ) {
				this.style.overflow = "hidden";
			}

			for ( p in prop ) {
				e = new jQuery.fx( this, opt, p );
				val = prop[ p ];

				if ( rfxtypes.test( val ) ) {

					// Tracks whether to show or hide based on private
					// data attached to the element
					method = jQuery._data( this, "toggle" + p ) || ( val === "toggle" ? hidden ? "show" : "hide" : 0 );
					if ( method ) {
						jQuery._data( this, "toggle" + p, method === "show" ? "hide" : "show" );
						e[ method ]();
					} else {
						e[ val ]();
					}

				} else {
					parts = rfxnum.exec( val );
					start = e.cur();

					if ( parts ) {
						end = parseFloat( parts[2] );
						unit = parts[3] || ( jQuery.cssNumber[ p ] ? "" : "px" );

						// We need to compute starting value
						if ( unit !== "px" ) {
							jQuery.style( this, p, (end || 1) + unit);
							start = ( (end || 1) / e.cur() ) * start;
							jQuery.style( this, p, start + unit);
						}

						// If a +=/-= token was provided, we're doing a relative animation
						if ( parts[1] ) {
							end = ( (parts[ 1 ] === "-=" ? -1 : 1) * end ) + start;
						}

						e.custom( start, end, unit );

					} else {
						e.custom( start, val, "" );
					}
				}
			}

			// For JS strict compliance
			return true;
		}

		return optall.queue === false ?
			this.each( doAnimation ) :
			this.queue( optall.queue, doAnimation );
	},

	stop: function( type, clearQueue, gotoEnd ) {
		if ( typeof type !== "string" ) {
			gotoEnd = clearQueue;
			clearQueue = type;
			type = undefined;
		}
		if ( clearQueue && type !== false ) {
			this.queue( type || "fx", [] );
		}

		return this.each(function() {
			var index,
				hadTimers = false,
				timers = jQuery.timers,
				data = jQuery._data( this );

			// clear marker counters if we know they won't be
			if ( !gotoEnd ) {
				jQuery._unmark( true, this );
			}

			function stopQueue( elem, data, index ) {
				var hooks = data[ index ];
				jQuery.removeData( elem, index, true );
				hooks.stop( gotoEnd );
			}

			if ( type == null ) {
				for ( index in data ) {
					if ( data[ index ] && data[ index ].stop && index.indexOf(".run") === index.length - 4 ) {
						stopQueue( this, data, index );
					}
				}
			} else if ( data[ index = type + ".run" ] && data[ index ].stop ){
				stopQueue( this, data, index );
			}

			for ( index = timers.length; index--; ) {
				if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
					if ( gotoEnd ) {

						// force the next step to be the last
						timers[ index ]( true );
					} else {
						timers[ index ].saveState();
					}
					hadTimers = true;
					timers.splice( index, 1 );
				}
			}

			// start the next in the queue if the last step wasn't forced
			// timers currently will call their complete callbacks, which will dequeue
			// but only if they were gotoEnd
			if ( !( gotoEnd && hadTimers ) ) {
				jQuery.dequeue( this, type );
			}
		});
	}

});

// Animations created synchronously will run synchronously
function createFxNow() {
	setTimeout( clearFxNow, 0 );
	return ( fxNow = jQuery.now() );
}

function clearFxNow() {
	fxNow = undefined;
}

// Generate parameters to create a standard animation
function genFx( type, num ) {
	var obj = {};

	jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {
		obj[ this ] = type;
	});

	return obj;
}

// Generate shortcuts for custom animations
jQuery.each({
	slideDown: genFx( "show", 1 ),
	slideUp: genFx( "hide", 1 ),
	slideToggle: genFx( "toggle", 1 ),
	fadeIn: { opacity: "show" },
	fadeOut: { opacity: "hide" },
	fadeToggle: { opacity: "toggle" }
}, function( name, props ) {
	jQuery.fn[ name ] = function( speed, easing, callback ) {
		return this.animate( props, speed, easing, callback );
	};
});

jQuery.extend({
	speed: function( speed, easing, fn ) {
		var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
			complete: fn || !fn && easing ||
				jQuery.isFunction( speed ) && speed,
			duration: speed,
			easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
		};

		opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
			opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;

		// normalize opt.queue - true/undefined/null -> "fx"
		if ( opt.queue == null || opt.queue === true ) {
			opt.queue = "fx";
		}

		// Queueing
		opt.old = opt.complete;

		opt.complete = function( noUnmark ) {
			if ( jQuery.isFunction( opt.old ) ) {
				opt.old.call( this );
			}

			if ( opt.queue ) {
				jQuery.dequeue( this, opt.queue );
			} else if ( noUnmark !== false ) {
				jQuery._unmark( this );
			}
		};

		return opt;
	},

	easing: {
		linear: function( p, n, firstNum, diff ) {
			return firstNum + diff * p;
		},
		swing: function( p, n, firstNum, diff ) {
			return ( ( -Math.cos( p*Math.PI ) / 2 ) + 0.5 ) * diff + firstNum;
		}
	},

	timers: [],

	fx: function( elem, options, prop ) {
		this.options = options;
		this.elem = elem;
		this.prop = prop;

		options.orig = options.orig || {};
	}

});

jQuery.fx.prototype = {
	// Simple function for setting a style value
	update: function() {
		if ( this.options.step ) {
			this.options.step.call( this.elem, this.now, this );
		}

		( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );
	},

	// Get the current size
	cur: function() {
		if ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {
			return this.elem[ this.prop ];
		}

		var parsed,
			r = jQuery.css( this.elem, this.prop );
		// Empty strings, null, undefined and "auto" are converted to 0,
		// complex values such as "rotate(1rad)" are returned as is,
		// simple values such as "10px" are parsed to Float.
		return isNaN( parsed = parseFloat( r ) ) ? !r || r === "auto" ? 0 : r : parsed;
	},

	// Start an animation from one number to another
	custom: function( from, to, unit ) {
		var self = this,
			fx = jQuery.fx;

		this.startTime = fxNow || createFxNow();
		this.end = to;
		this.now = this.start = from;
		this.pos = this.state = 0;
		this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" );

		function t( gotoEnd ) {
			return self.step( gotoEnd );
		}

		t.queue = this.options.queue;
		t.elem = this.elem;
		t.saveState = function() {
			if ( self.options.hide && jQuery._data( self.elem, "fxshow" + self.prop ) === undefined ) {
				jQuery._data( self.elem, "fxshow" + self.prop, self.start );
			}
		};

		if ( t() && jQuery.timers.push(t) && !timerId ) {
			timerId = setInterval( fx.tick, fx.interval );
		}
	},

	// Simple 'show' function
	show: function() {
		var dataShow = jQuery._data( this.elem, "fxshow" + this.prop );

		// Remember where we started, so that we can go back to it later
		this.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );
		this.options.show = true;

		// Begin the animation
		// Make sure that we start at a small width/height to avoid any flash of content
		if ( dataShow !== undefined ) {
			// This show is picking up where a previous hide or show left off
			this.custom( this.cur(), dataShow );
		} else {
			this.custom( this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur() );
		}

		// Start by showing the element
		jQuery( this.elem ).show();
	},

	// Simple 'hide' function
	hide: function() {
		// Remember where we started, so that we can go back to it later
		this.options.orig[ this.prop ] = jQuery._data( this.elem, "fxshow" + this.prop ) || jQuery.style( this.elem, this.prop );
		this.options.hide = true;

		// Begin the animation
		this.custom( this.cur(), 0 );
	},

	// Each step of an animation
	step: function( gotoEnd ) {
		var p, n, complete,
			t = fxNow || createFxNow(),
			done = true,
			elem = this.elem,
			options = this.options;

		if ( gotoEnd || t >= options.duration + this.startTime ) {
			this.now = this.end;
			this.pos = this.state = 1;
			this.update();

			options.animatedProperties[ this.prop ] = true;

			for ( p in options.animatedProperties ) {
				if ( options.animatedProperties[ p ] !== true ) {
					done = false;
				}
			}

			if ( done ) {
				// Reset the overflow
				if ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {

					jQuery.each( [ "", "X", "Y" ], function( index, value ) {
						elem.style[ "overflow" + value ] = options.overflow[ index ];
					});
				}

				// Hide the element if the "hide" operation was done
				if ( options.hide ) {
					jQuery( elem ).hide();
				}

				// Reset the properties, if the item has been hidden or shown
				if ( options.hide || options.show ) {
					for ( p in options.animatedProperties ) {
						jQuery.style( elem, p, options.orig[ p ] );
						jQuery.removeData( elem, "fxshow" + p, true );
						// Toggle data is no longer needed
						jQuery.removeData( elem, "toggle" + p, true );
					}
				}

				// Execute the complete function
				// in the event that the complete function throws an exception
				// we must ensure it won't be called twice. #5684

				complete = options.complete;
				if ( complete ) {

					options.complete = false;
					complete.call( elem );
				}
			}

			return false;

		} else {
			// classical easing cannot be used with an Infinity duration
			if ( options.duration == Infinity ) {
				this.now = t;
			} else {
				n = t - this.startTime;
				this.state = n / options.duration;

				// Perform the easing function, defaults to swing
				this.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );
				this.now = this.start + ( (this.end - this.start) * this.pos );
			}
			// Perform the next step of the animation
			this.update();
		}

		return true;
	}
};

jQuery.extend( jQuery.fx, {
	tick: function() {
		var timer,
			timers = jQuery.timers,
			i = 0;

		for ( ; i < timers.length; i++ ) {
			timer = timers[ i ];
			// Checks the timer has not already been removed
			if ( !timer() && timers[ i ] === timer ) {
				timers.splice( i--, 1 );
			}
		}

		if ( !timers.length ) {
			jQuery.fx.stop();
		}
	},

	interval: 13,

	stop: function() {
		clearInterval( timerId );
		timerId = null;
	},

	speeds: {
		slow: 600,
		fast: 200,
		// Default speed
		_default: 400
	},

	step: {
		opacity: function( fx ) {
			jQuery.style( fx.elem, "opacity", fx.now );
		},

		_default: function( fx ) {
			if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
				fx.elem.style[ fx.prop ] = fx.now + fx.unit;
			} else {
				fx.elem[ fx.prop ] = fx.now;
			}
		}
	}
});

// Adds width/height step functions
// Do not set anything below 0
jQuery.each([ "width", "height" ], function( i, prop ) {
	jQuery.fx.step[ prop ] = function( fx ) {
		jQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit );
	};
});

if ( jQuery.expr && jQuery.expr.filters ) {
	jQuery.expr.filters.animated = function( elem ) {
		return jQuery.grep(jQuery.timers, function( fn ) {
			return elem === fn.elem;
		}).length;
	};
}

// Try to restore the default display value of an element
function defaultDisplay( nodeName ) {

	if ( !elemdisplay[ nodeName ] ) {

		var body = document.body,
			elem = jQuery( "<" + nodeName + ">" ).appendTo( body ),
			display = elem.css( "display" );
		elem.remove();

		// If the simple way fails,
		// get element's real default display by attaching it to a temp iframe
		if ( display === "none" || display === "" ) {
			// No iframe to use yet, so create it
			if ( !iframe ) {
				iframe = document.createElement( "iframe" );
				iframe.frameBorder = iframe.width = iframe.height = 0;
			}

			body.appendChild( iframe );

			// Create a cacheable copy of the iframe document on first call.
			// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML
			// document to it; WebKit & Firefox won't allow reusing the iframe document.
			if ( !iframeDoc || !iframe.createElement ) {
				iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;
				iframeDoc.write( ( document.compatMode === "CSS1Compat" ? "<!doctype html>" : "" ) + "<html><body>" );
				iframeDoc.close();
			}

			elem = iframeDoc.createElement( nodeName );

			iframeDoc.body.appendChild( elem );

			display = jQuery.css( elem, "display" );
			body.removeChild( iframe );
		}

		// Store the correct default display
		elemdisplay[ nodeName ] = display;
	}

	return elemdisplay[ nodeName ];
}




var rtable = /^t(?:able|d|h)$/i,
	rroot = /^(?:body|html)$/i;

if ( "getBoundingClientRect" in document.documentElement ) {
	jQuery.fn.offset = function( options ) {
		var elem = this[0], box;

		if ( options ) {
			return this.each(function( i ) {
				jQuery.offset.setOffset( this, options, i );
			});
		}

		if ( !elem || !elem.ownerDocument ) {
			return null;
		}

		if ( elem === elem.ownerDocument.body ) {
			return jQuery.offset.bodyOffset( elem );
		}

		try {
			box = elem.getBoundingClientRect();
		} catch(e) {}

		var doc = elem.ownerDocument,
			docElem = doc.documentElement;

		// Make sure we're not dealing with a disconnected DOM node
		if ( !box || !jQuery.contains( docElem, elem ) ) {
			return box ? { top: box.top, left: box.left } : { top: 0, left: 0 };
		}

		var body = doc.body,
			win = getWindow(doc),
			clientTop  = docElem.clientTop  || body.clientTop  || 0,
			clientLeft = docElem.clientLeft || body.clientLeft || 0,
			scrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,
			scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,
			top  = box.top  + scrollTop  - clientTop,
			left = box.left + scrollLeft - clientLeft;

		return { top: top, left: left };
	};

} else {
	jQuery.fn.offset = function( options ) {
		var elem = this[0];

		if ( options ) {
			return this.each(function( i ) {
				jQuery.offset.setOffset( this, options, i );
			});
		}

		if ( !elem || !elem.ownerDocument ) {
			return null;
		}

		if ( elem === elem.ownerDocument.body ) {
			return jQuery.offset.bodyOffset( elem );
		}

		var computedStyle,
			offsetParent = elem.offsetParent,
			prevOffsetParent = elem,
			doc = elem.ownerDocument,
			docElem = doc.documentElement,
			body = doc.body,
			defaultView = doc.defaultView,
			prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
			top = elem.offsetTop,
			left = elem.offsetLeft;

		while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
			if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) {
				break;
			}

			computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
			top  -= elem.scrollTop;
			left -= elem.scrollLeft;

			if ( elem === offsetParent ) {
				top  += elem.offsetTop;
				left += elem.offsetLeft;

				if ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {
					top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
					left += parseFloat( computedStyle.borderLeftWidth ) || 0;
				}

				prevOffsetParent = offsetParent;
				offsetParent = elem.offsetParent;
			}

			if ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
				top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
				left += parseFloat( computedStyle.borderLeftWidth ) || 0;
			}

			prevComputedStyle = computedStyle;
		}

		if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
			top  += body.offsetTop;
			left += body.offsetLeft;
		}

		if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) {
			top  += Math.max( docElem.scrollTop, body.scrollTop );
			left += Math.max( docElem.scrollLeft, body.scrollLeft );
		}

		return { top: top, left: left };
	};
}

jQuery.offset = {

	bodyOffset: function( body ) {
		var top = body.offsetTop,
			left = body.offsetLeft;

		if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {
			top  += parseFloat( jQuery.css(body, "marginTop") ) || 0;
			left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
		}

		return { top: top, left: left };
	},

	setOffset: function( elem, options, i ) {
		var position = jQuery.css( elem, "position" );

		// set position first, in-case top/left are set even on static elem
		if ( position === "static" ) {
			elem.style.position = "relative";
		}

		var curElem = jQuery( elem ),
			curOffset = curElem.offset(),
			curCSSTop = jQuery.css( elem, "top" ),
			curCSSLeft = jQuery.css( elem, "left" ),
			calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
			props = {}, curPosition = {}, curTop, curLeft;

		// need to be able to calculate position if either top or left is auto and position is either absolute or fixed
		if ( calculatePosition ) {
			curPosition = curElem.position();
			curTop = curPosition.top;
			curLeft = curPosition.left;
		} else {
			curTop = parseFloat( curCSSTop ) || 0;
			curLeft = parseFloat( curCSSLeft ) || 0;
		}

		if ( jQuery.isFunction( options ) ) {
			options = options.call( elem, i, curOffset );
		}

		if ( options.top != null ) {
			props.top = ( options.top - curOffset.top ) + curTop;
		}
		if ( options.left != null ) {
			props.left = ( options.left - curOffset.left ) + curLeft;
		}

		if ( "using" in options ) {
			options.using.call( elem, props );
		} else {
			curElem.css( props );
		}
	}
};


jQuery.fn.extend({

	position: function() {
		if ( !this[0] ) {
			return null;
		}

		var elem = this[0],

		// Get *real* offsetParent
		offsetParent = this.offsetParent(),

		// Get correct offsets
		offset       = this.offset(),
		parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();

		// Subtract element margins
		// note: when an element has margin: auto the offsetLeft and marginLeft
		// are the same in Safari causing offset.left to incorrectly be 0
		offset.top  -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
		offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;

		// Add offsetParent borders
		parentOffset.top  += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
		parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;

		// Subtract the two offsets
		return {
			top:  offset.top  - parentOffset.top,
			left: offset.left - parentOffset.left
		};
	},

	offsetParent: function() {
		return this.map(function() {
			var offsetParent = this.offsetParent || document.body;
			while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
				offsetParent = offsetParent.offsetParent;
			}
			return offsetParent;
		});
	}
});


// Create scrollLeft and scrollTop methods
jQuery.each( ["Left", "Top"], function( i, name ) {
	var method = "scroll" + name;

	jQuery.fn[ method ] = function( val ) {
		var elem, win;

		if ( val === undefined ) {
			elem = this[ 0 ];

			if ( !elem ) {
				return null;
			}

			win = getWindow( elem );

			// Return the scroll offset
			return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
				jQuery.support.boxModel && win.document.documentElement[ method ] ||
					win.document.body[ method ] :
				elem[ method ];
		}

		// Set the scroll offset
		return this.each(function() {
			win = getWindow( this );

			if ( win ) {
				win.scrollTo(
					!i ? val : jQuery( win ).scrollLeft(),
					 i ? val : jQuery( win ).scrollTop()
				);

			} else {
				this[ method ] = val;
			}
		});
	};
});

function getWindow( elem ) {
	return jQuery.isWindow( elem ) ?
		elem :
		elem.nodeType === 9 ?
			elem.defaultView || elem.parentWindow :
			false;
}




// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods
jQuery.each([ "Height", "Width" ], function( i, name ) {

	var type = name.toLowerCase();

	// innerHeight and innerWidth
	jQuery.fn[ "inner" + name ] = function() {
		var elem = this[0];
		return elem ?
			elem.style ?
			parseFloat( jQuery.css( elem, type, "padding" ) ) :
			this[ type ]() :
			null;
	};

	// outerHeight and outerWidth
	jQuery.fn[ "outer" + name ] = function( margin ) {
		var elem = this[0];
		return elem ?
			elem.style ?
			parseFloat( jQuery.css( elem, type, margin ? "margin" : "border" ) ) :
			this[ type ]() :
			null;
	};

	jQuery.fn[ type ] = function( size ) {
		// Get window width or height
		var elem = this[0];
		if ( !elem ) {
			return size == null ? null : this;
		}

		if ( jQuery.isFunction( size ) ) {
			return this.each(function( i ) {
				var self = jQuery( this );
				self[ type ]( size.call( this, i, self[ type ]() ) );
			});
		}

		if ( jQuery.isWindow( elem ) ) {
			// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
			// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat
			var docElemProp = elem.document.documentElement[ "client" + name ],
				body = elem.document.body;
			return elem.document.compatMode === "CSS1Compat" && docElemProp ||
				body && body[ "client" + name ] || docElemProp;

		// Get document width or height
		} else if ( elem.nodeType === 9 ) {
			// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
			return Math.max(
				elem.documentElement["client" + name],
				elem.body["scroll" + name], elem.documentElement["scroll" + name],
				elem.body["offset" + name], elem.documentElement["offset" + name]
			);

		// Get or set width or height on the element
		} else if ( size === undefined ) {
			var orig = jQuery.css( elem, type ),
				ret = parseFloat( orig );

			return jQuery.isNumeric( ret ) ? ret : orig;

		// Set the width or height on the element (default to pixels if value is unitless)
		} else {
			return this.css( type, typeof size === "string" ? size : size + "px" );
		}
	};

});




// Expose jQuery to the global object
window.jQuery = window.$ = jQuery;

// Expose jQuery as an AMD module, but only for AMD loaders that
// understand the issues with loading multiple versions of jQuery
// in a page that all might call define(). The loader will indicate
// they have special allowances for multiple jQuery versions by
// specifying define.amd.jQuery = true. Register as a named module,
// since jQuery can be concatenated with other files that may use define,
// but not use a proper concatenation script that understands anonymous
// AMD modules. A named AMD is safest and most robust way to register.
// Lowercase jquery is used because AMD module names are derived from
// file names, and jQuery is normally delivered in a lowercase file name.
// Do this after creating the global so that if an AMD module wants to call
// noConflict to hide this version of jQuery, it will work.
if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
	define( "jquery", [], function () { return jQuery; } );
}



})( window );
jQuery.expr[':'].Contains = function(a, i, m) {
    return jQuery(a).text().toUpperCase().indexOf(m[3].toUpperCase()) >= 0;
};

$(function() {
    $("#sidebar-nav").accordion({
        autoHeight: false,
        navigation: true,
        collapsible: true
    }).accordion("activate", false)
            .find('a.link').unbind('click').click(
            function(ev) {
                ev.cancelBubble = true; // IE
                if (ev.stopPropagation) {
                    ev.stopPropagation(); // the rest
                }

                return true;
            }).prev().prev().remove();

    $("#sidebar-nav>h3").click(function() {
        if ($(this).attr('initialized') == 'true') return;

        $(this).next().find(".sidebar-nav-tree").treeview({
            collapsed: true,
            persist: "cookie"
        });
        $(this).attr('initialized', true);
    });
});

function tree_search(input) {
    treeview = $(input).parent().parent().next();

    // Expand all items
    treeview.find('.expandable-hitarea').click();

    // make all items visible again
    treeview.find('li:hidden').show();

    // hide all items that do not match the given search criteria
    if ($(input).val()) {
        treeview.find('li').not(':has(a:Contains(' + $(input).val() + '))').hide();
    }
}
/*!
 * jQuery UI 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI
 */
(function(c){c.ui=c.ui||{};if(!c.ui.version){c.extend(c.ui,{version:"1.8.2",plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&&a.element[0].parentNode)for(var e=0;e<b.length;e++)a.options[b[e][0]]&&b[e][1].apply(a.element,d)}},contains:function(a,b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScroll:function(a,b){if(c(a).css("overflow")==
"hidden")return false;b=b&&b=="left"?"scrollLeft":"scrollTop";var d=false;if(a[b]>0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a<b+d},isOver:function(a,b,d,e,f,g){return c.ui.isOverAxis(a,d,f)&&c.ui.isOverAxis(b,e,g)},keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,
NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});c.fn.extend({_focus:c.fn.focus,focus:function(a,b){return typeof a==="number"?this.each(function(){var d=this;setTimeout(function(){c(d).focus();b&&b.call(d)},a)}):this._focus.apply(this,arguments)},enableSelection:function(){return this.attr("unselectable","off").css("MozUserSelect","")},disableSelection:function(){return this.attr("unselectable","on").css("MozUserSelect",
"none")},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this,"position",1))&&/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",
1))}).eq(0);return/fixed/.test(this.css("position"))||!a.length?c(document):a},zIndex:function(a){if(a!==undefined)return this.css("zIndex",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css("position");if(b=="absolute"||b=="relative"||b=="fixed"){b=parseInt(a.css("zIndex"));if(!isNaN(b)&&b!=0)return b}a=a.parent()}}return 0}});c.extend(c.expr[":"],{data:function(a,b,d){return!!c.data(a,d[3])},focusable:function(a){var b=a.nodeName.toLowerCase(),d=c.attr(a,"tabindex");return(/input|select|textarea|button|object/.test(b)?
!a.disabled:"a"==b||"area"==b?a.href||!isNaN(d):!isNaN(d))&&!c(a)["area"==b?"parents":"closest"](":hidden").length},tabbable:function(a){var b=c.attr(a,"tabindex");return(isNaN(b)||b>=0)&&c(a).is(":focusable")}})}})(jQuery);
;/*!
 * jQuery UI Widget 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Widget
 */
(function(b){var j=b.fn.remove;b.fn.remove=function(a,c){return this.each(function(){if(!c)if(!a||b.filter(a,[this]).length)b("*",this).add(this).each(function(){b(this).triggerHandler("remove")});return j.call(b(this),a,c)})};b.widget=function(a,c,d){var e=a.split(".")[0],f;a=a.split(".")[1];f=e+"-"+a;if(!d){d=c;c=b.Widget}b.expr[":"][f]=function(h){return!!b.data(h,a)};b[e]=b[e]||{};b[e][a]=function(h,g){arguments.length&&this._createWidget(h,g)};c=new c;c.options=b.extend({},c.options);b[e][a].prototype=
b.extend(true,c,{namespace:e,widgetName:a,widgetEventPrefix:b[e][a].prototype.widgetEventPrefix||a,widgetBaseClass:f},d);b.widget.bridge(a,b[e][a])};b.widget.bridge=function(a,c){b.fn[a]=function(d){var e=typeof d==="string",f=Array.prototype.slice.call(arguments,1),h=this;d=!e&&f.length?b.extend.apply(null,[true,d].concat(f)):d;if(e&&d.substring(0,1)==="_")return h;e?this.each(function(){var g=b.data(this,a),i=g&&b.isFunction(g[d])?g[d].apply(g,f):g;if(i!==g&&i!==undefined){h=i;return false}}):this.each(function(){var g=
b.data(this,a);if(g){d&&g.option(d);g._init()}else b.data(this,a,new c(d,this))});return h}};b.Widget=function(a,c){arguments.length&&this._createWidget(a,c)};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(a,c){this.element=b(c).data(this.widgetName,this);this.options=b.extend(true,{},this.options,b.metadata&&b.metadata.get(c)[this.widgetName],a);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()});this._create();
this._init()},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},widget:function(){return this.element},option:function(a,c){var d=a,e=this;if(arguments.length===0)return b.extend({},e.options);if(typeof a==="string"){if(c===undefined)return this.options[a];d={};d[a]=c}b.each(d,function(f,
h){e._setOption(f,h)});return e},_setOption:function(a,c){this.options[a]=c;if(a==="disabled")this.widget()[c?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",c);return this},enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(a,c,d){var e=this.options[a];c=b.Event(c);c.type=(a===this.widgetEventPrefix?a:this.widgetEventPrefix+a).toLowerCase();d=d||{};if(c.originalEvent){a=
b.event.props.length;for(var f;a;){f=b.event.props[--a];c[f]=c.originalEvent[f]}}this.element.trigger(c,d);return!(b.isFunction(e)&&e.call(this.element[0],c,d)===false||c.isDefaultPrevented())}}})(jQuery);
;/*!
 * jQuery UI Mouse 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Mouse
 *
 * Depends:
 *	jquery.ui.widget.js
 */
(function(c){c.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var a=this;this.element.bind("mousedown."+this.widgetName,function(b){return a._mouseDown(b)}).bind("click."+this.widgetName,function(b){if(a._preventClickEvent){a._preventClickEvent=false;b.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(a){a.originalEvent=a.originalEvent||{};if(!a.originalEvent.mouseHandled){this._mouseStarted&&
this._mouseUp(a);this._mouseDownEvent=a;var b=this,e=a.which==1,f=typeof this.options.cancel=="string"?c(a.target).parents().add(a.target).filter(this.options.cancel).length:false;if(!e||f||!this._mouseCapture(a))return true;this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet)this._mouseDelayTimer=setTimeout(function(){b.mouseDelayMet=true},this.options.delay);if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a)){this._mouseStarted=this._mouseStart(a)!==false;if(!this._mouseStarted){a.preventDefault();
return true}}this._mouseMoveDelegate=function(d){return b._mouseMove(d)};this._mouseUpDelegate=function(d){return b._mouseUp(d)};c(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);c.browser.safari||a.preventDefault();return a.originalEvent.mouseHandled=true}},_mouseMove:function(a){if(c.browser.msie&&!a.button)return this._mouseUp(a);if(this._mouseStarted){this._mouseDrag(a);return a.preventDefault()}if(this._mouseDistanceMet(a)&&
this._mouseDelayMet(a))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,a)!==false)?this._mouseDrag(a):this._mouseUp(a);return!this._mouseStarted},_mouseUp:function(a){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=a.target==this._mouseDownEvent.target;this._mouseStop(a)}return false},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-
a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery);
;/*
 * jQuery UI Position 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Position
 */
(function(c){c.ui=c.ui||{};var m=/left|center|right/,n=/top|center|bottom/,p=c.fn.position,q=c.fn.offset;c.fn.position=function(a){if(!a||!a.of)return p.apply(this,arguments);a=c.extend({},a);var b=c(a.of),d=(a.collision||"flip").split(" "),e=a.offset?a.offset.split(" "):[0,0],g,h,i;if(a.of.nodeType===9){g=b.width();h=b.height();i={top:0,left:0}}else if(a.of.scrollTo&&a.of.document){g=b.width();h=b.height();i={top:b.scrollTop(),left:b.scrollLeft()}}else if(a.of.preventDefault){a.at="left top";g=h=
0;i={top:a.of.pageY,left:a.of.pageX}}else{g=b.outerWidth();h=b.outerHeight();i=b.offset()}c.each(["my","at"],function(){var f=(a[this]||"").split(" ");if(f.length===1)f=m.test(f[0])?f.concat(["center"]):n.test(f[0])?["center"].concat(f):["center","center"];f[0]=m.test(f[0])?f[0]:"center";f[1]=n.test(f[1])?f[1]:"center";a[this]=f});if(d.length===1)d[1]=d[0];e[0]=parseInt(e[0],10)||0;if(e.length===1)e[1]=e[0];e[1]=parseInt(e[1],10)||0;if(a.at[0]==="right")i.left+=g;else if(a.at[0]==="center")i.left+=
g/2;if(a.at[1]==="bottom")i.top+=h;else if(a.at[1]==="center")i.top+=h/2;i.left+=e[0];i.top+=e[1];return this.each(function(){var f=c(this),k=f.outerWidth(),l=f.outerHeight(),j=c.extend({},i);if(a.my[0]==="right")j.left-=k;else if(a.my[0]==="center")j.left-=k/2;if(a.my[1]==="bottom")j.top-=l;else if(a.my[1]==="center")j.top-=l/2;j.left=parseInt(j.left);j.top=parseInt(j.top);c.each(["left","top"],function(o,r){c.ui.position[d[o]]&&c.ui.position[d[o]][r](j,{targetWidth:g,targetHeight:h,elemWidth:k,
elemHeight:l,offset:e,my:a.my,at:a.at})});c.fn.bgiframe&&f.bgiframe();f.offset(c.extend(j,{using:a.using}))})};c.ui.position={fit:{left:function(a,b){var d=c(window);b=a.left+b.elemWidth-d.width()-d.scrollLeft();a.left=b>0?a.left-b:Math.max(0,a.left)},top:function(a,b){var d=c(window);b=a.top+b.elemHeight-d.height()-d.scrollTop();a.top=b>0?a.top-b:Math.max(0,a.top)}},flip:{left:function(a,b){if(b.at[0]!=="center"){var d=c(window);d=a.left+b.elemWidth-d.width()-d.scrollLeft();var e=b.my[0]==="left"?
-b.elemWidth:b.my[0]==="right"?b.elemWidth:0,g=-2*b.offset[0];a.left+=a.left<0?e+b.targetWidth+g:d>0?e-b.targetWidth+g:0}},top:function(a,b){if(b.at[1]!=="center"){var d=c(window);d=a.top+b.elemHeight-d.height()-d.scrollTop();var e=b.my[1]==="top"?-b.elemHeight:b.my[1]==="bottom"?b.elemHeight:0,g=b.at[1]==="top"?b.targetHeight:-b.targetHeight,h=-2*b.offset[1];a.top+=a.top<0?e+b.targetHeight+h:d>0?e+g+h:0}}}};if(!c.offset.setOffset){c.offset.setOffset=function(a,b){if(/static/.test(c.curCSS(a,"position")))a.style.position=
"relative";var d=c(a),e=d.offset(),g=parseInt(c.curCSS(a,"top",true),10)||0,h=parseInt(c.curCSS(a,"left",true),10)||0;e={top:b.top-e.top+g,left:b.left-e.left+h};"using"in b?b.using.call(a,e):d.css(e)};c.fn.offset=function(a){var b=this[0];if(!b||!b.ownerDocument)return null;if(a)return this.each(function(){c.offset.setOffset(this,a)});return q.call(this)}}})(jQuery);
;/*
 * jQuery UI Draggable 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Draggables
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.mouse.js
 *	jquery.ui.widget.js
 */
(function(d){d.widget("ui.draggable",d.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:true,appendTo:"parent",axis:false,connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false},_create:function(){if(this.options.helper==
"original"&&!/^(?:r|a|f)/.test(this.element.css("position")))this.element[0].style.position="relative";this.options.addClasses&&this.element.addClass("ui-draggable");this.options.disabled&&this.element.addClass("ui-draggable-disabled");this._mouseInit()},destroy:function(){if(this.element.data("draggable")){this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._mouseDestroy();return this}},_mouseCapture:function(a){var b=
this.options;if(this.helper||b.disabled||d(a.target).is(".ui-resizable-handle"))return false;this.handle=this._getHandle(a);if(!this.handle)return false;return true},_mouseStart:function(a){var b=this.options;this.helper=this._createHelper(a);this._cacheHelperProportions();if(d.ui.ddmanager)d.ui.ddmanager.current=this;this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.positionAbs=this.element.offset();this.offset={top:this.offset.top-
this.margins.top,left:this.offset.left-this.margins.left};d.extend(this.offset,{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this.position=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);b.containment&&this._setContainment();if(this._trigger("start",a)===false){this._clear();return false}this._cacheHelperProportions();
d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.helper.addClass("ui-draggable-dragging");this._mouseDrag(a,true);return true},_mouseDrag:function(a,b){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");if(!b){b=this._uiHash();if(this._trigger("drag",a,b)===false){this._mouseUp({});return false}this.position=b.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||
this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);return false},_mouseStop:function(a){var b=false;if(d.ui.ddmanager&&!this.options.dropBehaviour)b=d.ui.ddmanager.drop(this,a);if(this.dropped){b=this.dropped;this.dropped=false}if(!this.element[0]||!this.element[0].parentNode)return false;if(this.options.revert=="invalid"&&!b||this.options.revert=="valid"&&b||this.options.revert===true||d.isFunction(this.options.revert)&&this.options.revert.call(this.element,
b)){var c=this;d(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){c._trigger("stop",a)!==false&&c._clear()})}else this._trigger("stop",a)!==false&&this._clear();return false},cancel:function(){this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear();return this},_getHandle:function(a){var b=!this.options.handle||!d(this.options.handle,this.element).length?true:false;d(this.options.handle,this.element).find("*").andSelf().each(function(){if(this==
a.target)b=true});return b},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a])):b.helper=="clone"?this.element.clone():this.element;a.parents("body").length||a.appendTo(b.appendTo=="parent"?this.element[0].parentNode:b.appendTo);a[0]!=this.element[0]&&!/(fixed|absolute)/.test(a.css("position"))&&a.css("position","absolute");return a},_adjustOffsetFromHelper:function(a){if(typeof a=="string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]||
0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],
this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.element.position();return{top:a.top-
(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;if(a.containment==
"parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)&&
a.containment.constructor!=Array){var b=d(a.containment)[0];if(b){a=d(a.containment).offset();var c=d(b).css("overflow")!="hidden";this.containment=[a.left+(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0)-this.margins.left,a.top+(parseInt(d(b).css("borderTopWidth"),10)||0)+(parseInt(d(b).css("paddingTop"),10)||0)-this.margins.top,a.left+(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"),
10)||0)-this.helperProportions.width-this.margins.left,a.top+(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"),10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}}else if(a.containment.constructor==Array)this.containment=a.containment},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],
this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName);return{top:b.top+this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():
f?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName),e=a.pageX,g=a.pageY;if(this.originalPosition){if(this.containment){if(a.pageX-this.offset.click.left<this.containment[0])e=this.containment[0]+this.offset.click.left;if(a.pageY-this.offset.click.top<this.containment[1])g=this.containment[1]+
this.offset.click.top;if(a.pageX-this.offset.click.left>this.containment[2])e=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?g:!(g-this.offset.click.top<this.containment[1])?g-b.grid[1]:g+b.grid[1]:g;e=this.originalPageX+
Math.round((e-this.originalPageX)/b.grid[0])*b.grid[0];e=this.containment?!(e-this.offset.click.left<this.containment[0]||e-this.offset.click.left>this.containment[2])?e:!(e-this.offset.click.left<this.containment[0])?e-b.grid[0]:e+b.grid[0]:e}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop()),left:e-this.offset.click.left-
this.offset.relative.left-this.offset.parent.left+(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():f?0:c.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging");this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove();this.helper=null;this.cancelHelperRemoval=false},_trigger:function(a,b,c){c=c||this._uiHash();d.ui.plugin.call(this,a,[b,c]);if(a=="drag")this.positionAbs=
this._convertPositionTo("absolute");return d.Widget.prototype._trigger.call(this,a,b,c)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}});d.extend(d.ui.draggable,{version:"1.8.2"});d.ui.plugin.add("draggable","connectToSortable",{start:function(a,b){var c=d(this).data("draggable"),f=c.options,e=d.extend({},b,{item:c.element});c.sortables=[];d(f.connectToSortable).each(function(){var g=d.data(this,"sortable");
if(g&&!g.options.disabled){c.sortables.push({instance:g,shouldRevert:g.options.revert});g._refreshItems();g._trigger("activate",a,e)}})},stop:function(a,b){var c=d(this).data("draggable"),f=d.extend({},b,{item:c.element});d.each(c.sortables,function(){if(this.instance.isOver){this.instance.isOver=0;c.cancelHelperRemoval=true;this.instance.cancelHelperRemoval=false;if(this.shouldRevert)this.instance.options.revert=true;this.instance._mouseStop(a);this.instance.options.helper=this.instance.options._helper;
c.options.helper=="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})}else{this.instance.cancelHelperRemoval=false;this.instance._trigger("deactivate",a,f)}})},drag:function(a,b){var c=d(this).data("draggable"),f=this;d.each(c.sortables,function(){this.instance.positionAbs=c.positionAbs;this.instance.helperProportions=c.helperProportions;this.instance.offset.click=c.offset.click;if(this.instance._intersectsWith(this.instance.containerCache)){if(!this.instance.isOver){this.instance.isOver=
1;this.instance.currentItem=d(f).clone().appendTo(this.instance.element).data("sortable-item",true);this.instance.options._helper=this.instance.options.helper;this.instance.options.helper=function(){return b.helper[0]};a.target=this.instance.currentItem[0];this.instance._mouseCapture(a,true);this.instance._mouseStart(a,true,true);this.instance.offset.click.top=c.offset.click.top;this.instance.offset.click.left=c.offset.click.left;this.instance.offset.parent.left-=c.offset.parent.left-this.instance.offset.parent.left;
this.instance.offset.parent.top-=c.offset.parent.top-this.instance.offset.parent.top;c._trigger("toSortable",a);c.dropped=this.instance.element;c.currentItem=c.element;this.instance.fromOutside=c}this.instance.currentItem&&this.instance._mouseDrag(a)}else if(this.instance.isOver){this.instance.isOver=0;this.instance.cancelHelperRemoval=true;this.instance.options.revert=false;this.instance._trigger("out",a,this.instance._uiHash(this.instance));this.instance._mouseStop(a,true);this.instance.options.helper=
this.instance.options._helper;this.instance.currentItem.remove();this.instance.placeholder&&this.instance.placeholder.remove();c._trigger("fromSortable",a);c.dropped=false}})}});d.ui.plugin.add("draggable","cursor",{start:function(){var a=d("body"),b=d(this).data("draggable").options;if(a.css("cursor"))b._cursor=a.css("cursor");a.css("cursor",b.cursor)},stop:function(){var a=d(this).data("draggable").options;a._cursor&&d("body").css("cursor",a._cursor)}});d.ui.plugin.add("draggable","iframeFix",{start:function(){var a=
d(this).data("draggable").options;d(a.iframeFix===true?"iframe":a.iframeFix).each(function(){d('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1E3}).css(d(this).offset()).appendTo("body")})},stop:function(){d("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)})}});d.ui.plugin.add("draggable","opacity",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options;
if(a.css("opacity"))b._opacity=a.css("opacity");a.css("opacity",b.opacity)},stop:function(a,b){a=d(this).data("draggable").options;a._opacity&&d(b.helper).css("opacity",a._opacity)}});d.ui.plugin.add("draggable","scroll",{start:function(){var a=d(this).data("draggable");if(a.scrollParent[0]!=document&&a.scrollParent[0].tagName!="HTML")a.overflowOffset=a.scrollParent.offset()},drag:function(a){var b=d(this).data("draggable"),c=b.options,f=false;if(b.scrollParent[0]!=document&&b.scrollParent[0].tagName!=
"HTML"){if(!c.axis||c.axis!="x")if(b.overflowOffset.top+b.scrollParent[0].offsetHeight-a.pageY<c.scrollSensitivity)b.scrollParent[0].scrollTop=f=b.scrollParent[0].scrollTop+c.scrollSpeed;else if(a.pageY-b.overflowOffset.top<c.scrollSensitivity)b.scrollParent[0].scrollTop=f=b.scrollParent[0].scrollTop-c.scrollSpeed;if(!c.axis||c.axis!="y")if(b.overflowOffset.left+b.scrollParent[0].offsetWidth-a.pageX<c.scrollSensitivity)b.scrollParent[0].scrollLeft=f=b.scrollParent[0].scrollLeft+c.scrollSpeed;else if(a.pageX-
b.overflowOffset.left<c.scrollSensitivity)b.scrollParent[0].scrollLeft=f=b.scrollParent[0].scrollLeft-c.scrollSpeed}else{if(!c.axis||c.axis!="x")if(a.pageY-d(document).scrollTop()<c.scrollSensitivity)f=d(document).scrollTop(d(document).scrollTop()-c.scrollSpeed);else if(d(window).height()-(a.pageY-d(document).scrollTop())<c.scrollSensitivity)f=d(document).scrollTop(d(document).scrollTop()+c.scrollSpeed);if(!c.axis||c.axis!="y")if(a.pageX-d(document).scrollLeft()<c.scrollSensitivity)f=d(document).scrollLeft(d(document).scrollLeft()-
c.scrollSpeed);else if(d(window).width()-(a.pageX-d(document).scrollLeft())<c.scrollSensitivity)f=d(document).scrollLeft(d(document).scrollLeft()+c.scrollSpeed)}f!==false&&d.ui.ddmanager&&!c.dropBehaviour&&d.ui.ddmanager.prepareOffsets(b,a)}});d.ui.plugin.add("draggable","snap",{start:function(){var a=d(this).data("draggable"),b=a.options;a.snapElements=[];d(b.snap.constructor!=String?b.snap.items||":data(draggable)":b.snap).each(function(){var c=d(this),f=c.offset();this!=a.element[0]&&a.snapElements.push({item:this,
width:c.outerWidth(),height:c.outerHeight(),top:f.top,left:f.left})})},drag:function(a,b){for(var c=d(this).data("draggable"),f=c.options,e=f.snapTolerance,g=b.offset.left,n=g+c.helperProportions.width,m=b.offset.top,o=m+c.helperProportions.height,h=c.snapElements.length-1;h>=0;h--){var i=c.snapElements[h].left,k=i+c.snapElements[h].width,j=c.snapElements[h].top,l=j+c.snapElements[h].height;if(i-e<g&&g<k+e&&j-e<m&&m<l+e||i-e<g&&g<k+e&&j-e<o&&o<l+e||i-e<n&&n<k+e&&j-e<m&&m<l+e||i-e<n&&n<k+e&&j-e<o&&
o<l+e){if(f.snapMode!="inner"){var p=Math.abs(j-o)<=e,q=Math.abs(l-m)<=e,r=Math.abs(i-n)<=e,s=Math.abs(k-g)<=e;if(p)b.position.top=c._convertPositionTo("relative",{top:j-c.helperProportions.height,left:0}).top-c.margins.top;if(q)b.position.top=c._convertPositionTo("relative",{top:l,left:0}).top-c.margins.top;if(r)b.position.left=c._convertPositionTo("relative",{top:0,left:i-c.helperProportions.width}).left-c.margins.left;if(s)b.position.left=c._convertPositionTo("relative",{top:0,left:k}).left-c.margins.left}var t=
p||q||r||s;if(f.snapMode!="outer"){p=Math.abs(j-m)<=e;q=Math.abs(l-o)<=e;r=Math.abs(i-g)<=e;s=Math.abs(k-n)<=e;if(p)b.position.top=c._convertPositionTo("relative",{top:j,left:0}).top-c.margins.top;if(q)b.position.top=c._convertPositionTo("relative",{top:l-c.helperProportions.height,left:0}).top-c.margins.top;if(r)b.position.left=c._convertPositionTo("relative",{top:0,left:i}).left-c.margins.left;if(s)b.position.left=c._convertPositionTo("relative",{top:0,left:k-c.helperProportions.width}).left-c.margins.left}if(!c.snapElements[h].snapping&&
(p||q||r||s||t))c.options.snap.snap&&c.options.snap.snap.call(c.element,a,d.extend(c._uiHash(),{snapItem:c.snapElements[h].item}));c.snapElements[h].snapping=p||q||r||s||t}else{c.snapElements[h].snapping&&c.options.snap.release&&c.options.snap.release.call(c.element,a,d.extend(c._uiHash(),{snapItem:c.snapElements[h].item}));c.snapElements[h].snapping=false}}}});d.ui.plugin.add("draggable","stack",{start:function(){var a=d(this).data("draggable").options;a=d.makeArray(d(a.stack)).sort(function(c,f){return(parseInt(d(c).css("zIndex"),
10)||0)-(parseInt(d(f).css("zIndex"),10)||0)});if(a.length){var b=parseInt(a[0].style.zIndex)||0;d(a).each(function(c){this.style.zIndex=b+c});this[0].style.zIndex=b+a.length}}});d.ui.plugin.add("draggable","zIndex",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options;if(a.css("zIndex"))b._zIndex=a.css("zIndex");a.css("zIndex",b.zIndex)},stop:function(a,b){a=d(this).data("draggable").options;a._zIndex&&d(b.helper).css("zIndex",a._zIndex)}})})(jQuery);
;/*
 * jQuery UI Droppable 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Droppables
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 *	jquery.ui.mouse.js
 *	jquery.ui.draggable.js
 */
(function(d){d.widget("ui.droppable",{widgetEventPrefix:"drop",options:{accept:"*",activeClass:false,addClasses:true,greedy:false,hoverClass:false,scope:"default",tolerance:"intersect"},_create:function(){var a=this.options,b=a.accept;this.isover=0;this.isout=1;this.accept=d.isFunction(b)?b:function(c){return c.is(b)};this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight};d.ui.ddmanager.droppables[a.scope]=d.ui.ddmanager.droppables[a.scope]||[];d.ui.ddmanager.droppables[a.scope].push(this);
a.addClasses&&this.element.addClass("ui-droppable")},destroy:function(){for(var a=d.ui.ddmanager.droppables[this.options.scope],b=0;b<a.length;b++)a[b]==this&&a.splice(b,1);this.element.removeClass("ui-droppable ui-droppable-disabled").removeData("droppable").unbind(".droppable");return this},_setOption:function(a,b){if(a=="accept")this.accept=d.isFunction(b)?b:function(c){return c.is(b)};d.Widget.prototype._setOption.apply(this,arguments)},_activate:function(a){var b=d.ui.ddmanager.current;this.options.activeClass&&
this.element.addClass(this.options.activeClass);b&&this._trigger("activate",a,this.ui(b))},_deactivate:function(a){var b=d.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass);b&&this._trigger("deactivate",a,this.ui(b))},_over:function(a){var b=d.ui.ddmanager.current;if(!(!b||(b.currentItem||b.element)[0]==this.element[0]))if(this.accept.call(this.element[0],b.currentItem||b.element)){this.options.hoverClass&&this.element.addClass(this.options.hoverClass);
this._trigger("over",a,this.ui(b))}},_out:function(a){var b=d.ui.ddmanager.current;if(!(!b||(b.currentItem||b.element)[0]==this.element[0]))if(this.accept.call(this.element[0],b.currentItem||b.element)){this.options.hoverClass&&this.element.removeClass(this.options.hoverClass);this._trigger("out",a,this.ui(b))}},_drop:function(a,b){var c=b||d.ui.ddmanager.current;if(!c||(c.currentItem||c.element)[0]==this.element[0])return false;var e=false;this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var g=
d.data(this,"droppable");if(g.options.greedy&&!g.options.disabled&&g.options.scope==c.options.scope&&g.accept.call(g.element[0],c.currentItem||c.element)&&d.ui.intersect(c,d.extend(g,{offset:g.element.offset()}),g.options.tolerance)){e=true;return false}});if(e)return false;if(this.accept.call(this.element[0],c.currentItem||c.element)){this.options.activeClass&&this.element.removeClass(this.options.activeClass);this.options.hoverClass&&this.element.removeClass(this.options.hoverClass);this._trigger("drop",
a,this.ui(c));return this.element}return false},ui:function(a){return{draggable:a.currentItem||a.element,helper:a.helper,position:a.position,offset:a.positionAbs}}});d.extend(d.ui.droppable,{version:"1.8.2"});d.ui.intersect=function(a,b,c){if(!b.offset)return false;var e=(a.positionAbs||a.position.absolute).left,g=e+a.helperProportions.width,f=(a.positionAbs||a.position.absolute).top,h=f+a.helperProportions.height,i=b.offset.left,k=i+b.proportions.width,j=b.offset.top,l=j+b.proportions.height;
switch(c){case "fit":return i<e&&g<k&&j<f&&h<l;case "intersect":return i<e+a.helperProportions.width/2&&g-a.helperProportions.width/2<k&&j<f+a.helperProportions.height/2&&h-a.helperProportions.height/2<l;case "pointer":return d.ui.isOver((a.positionAbs||a.position.absolute).top+(a.clickOffset||a.offset.click).top,(a.positionAbs||a.position.absolute).left+(a.clickOffset||a.offset.click).left,j,i,b.proportions.height,b.proportions.width);case "touch":return(f>=j&&f<=l||h>=j&&h<=l||f<j&&h>l)&&(e>=i&&
e<=k||g>=i&&g<=k||e<i&&g>k);default:return false}};d.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(a,b){var c=d.ui.ddmanager.droppables[a.options.scope]||[],e=b?b.type:null,g=(a.currentItem||a.element).find(":data(droppable)").andSelf(),f=0;a:for(;f<c.length;f++)if(!(c[f].options.disabled||a&&!c[f].accept.call(c[f].element[0],a.currentItem||a.element))){for(var h=0;h<g.length;h++)if(g[h]==c[f].element[0]){c[f].proportions.height=0;continue a}c[f].visible=c[f].element.css("display")!=
"none";if(c[f].visible){c[f].offset=c[f].element.offset();c[f].proportions={width:c[f].element[0].offsetWidth,height:c[f].element[0].offsetHeight};e=="mousedown"&&c[f]._activate.call(c[f],b)}}},drop:function(a,b){var c=false;d.each(d.ui.ddmanager.droppables[a.options.scope]||[],function(){if(this.options){if(!this.options.disabled&&this.visible&&d.ui.intersect(a,this,this.options.tolerance))c=c||this._drop.call(this,b);if(!this.options.disabled&&this.visible&&this.accept.call(this.element[0],a.currentItem||
a.element)){this.isout=1;this.isover=0;this._deactivate.call(this,b)}}});return c},drag:function(a,b){a.options.refreshPositions&&d.ui.ddmanager.prepareOffsets(a,b);d.each(d.ui.ddmanager.droppables[a.options.scope]||[],function(){if(!(this.options.disabled||this.greedyChild||!this.visible)){var c=d.ui.intersect(a,this,this.options.tolerance);if(c=!c&&this.isover==1?"isout":c&&this.isover==0?"isover":null){var e;if(this.options.greedy){var g=this.element.parents(":data(droppable):eq(0)");if(g.length){e=
d.data(g[0],"droppable");e.greedyChild=c=="isover"?1:0}}if(e&&c=="isover"){e.isover=0;e.isout=1;e._out.call(e,b)}this[c]=1;this[c=="isout"?"isover":"isout"]=0;this[c=="isover"?"_over":"_out"].call(this,b);if(e&&c=="isout"){e.isout=0;e.isover=1;e._over.call(e,b)}}}})}}})(jQuery);
;/*
 * jQuery UI Resizable 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Resizables
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.mouse.js
 *	jquery.ui.widget.js
 */
(function(d){d.widget("ui.resizable",d.ui.mouse,{widgetEventPrefix:"resize",options:{alsoResize:false,animate:false,animateDuration:"slow",animateEasing:"swing",aspectRatio:false,autoHide:false,containment:false,ghost:false,grid:false,handles:"e,s,se",helper:false,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1E3},_create:function(){var b=this,a=this.options;this.element.addClass("ui-resizable");d.extend(this,{_aspectRatio:!!a.aspectRatio,aspectRatio:a.aspectRatio,originalElement:this.element,
_proportionallyResizeElements:[],_helper:a.helper||a.ghost||a.animate?a.helper||"ui-resizable-helper":null});if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)){/relative/.test(this.element.css("position"))&&d.browser.opera&&this.element.css({position:"relative",top:"auto",left:"auto"});this.element.wrap(d('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),
top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle=
this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=a.handles||(!d(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",
nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all")this.handles="n,e,s,w,se,sw,ne,nw";var c=this.handles.split(",");this.handles={};for(var e=0;e<c.length;e++){var g=d.trim(c[e]),f=d('<div class="ui-resizable-handle '+("ui-resizable-"+g)+'"></div>');/sw|se|ne|nw/.test(g)&&f.css({zIndex:++a.zIndex});"se"==g&&f.addClass("ui-icon ui-icon-gripsmall-diagonal-se");this.handles[g]=".ui-resizable-"+g;this.element.append(f)}}this._renderAxis=function(h){h=h||this.element;for(var i in this.handles){if(this.handles[i].constructor==
String)this.handles[i]=d(this.handles[i],this.element).show();if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var j=d(this.handles[i],this.element),l=0;l=/sw|ne|nw|se|n|s/.test(i)?j.outerHeight():j.outerWidth();j=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join("");h.css(j,l);this._proportionallyResize()}d(this.handles[i])}};this._renderAxis(this.element);this._handles=d(".ui-resizable-handle",this.element).disableSelection();
this._handles.mouseover(function(){if(!b.resizing){if(this.className)var h=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);b.axis=h&&h[1]?h[1]:"se"}});if(a.autoHide){this._handles.hide();d(this.element).addClass("ui-resizable-autohide").hover(function(){d(this).removeClass("ui-resizable-autohide");b._handles.show()},function(){if(!b.resizing){d(this).addClass("ui-resizable-autohide");b._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var b=function(c){d(c).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};
if(this.elementIsWrapper){b(this.element);var a=this.element;a.after(this.originalElement.css({position:a.css("position"),width:a.outerWidth(),height:a.outerHeight(),top:a.css("top"),left:a.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle);b(this.originalElement);return this},_mouseCapture:function(b){var a=false;for(var c in this.handles)if(d(this.handles[c])[0]==b.target)a=true;return!this.options.disabled&&a},_mouseStart:function(b){var a=this.options,c=this.element.position(),
e=this.element;this.resizing=true;this.documentScroll={top:d(document).scrollTop(),left:d(document).scrollLeft()};if(e.is(".ui-draggable")||/absolute/.test(e.css("position")))e.css({position:"absolute",top:c.top,left:c.left});d.browser.opera&&/relative/.test(e.css("position"))&&e.css({position:"relative",top:"auto",left:"auto"});this._renderProxy();c=m(this.helper.css("left"));var g=m(this.helper.css("top"));if(a.containment){c+=d(a.containment).scrollLeft()||0;g+=d(a.containment).scrollTop()||0}this.offset=
this.helper.offset();this.position={left:c,top:g};this.size=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalSize=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalPosition={left:c,top:g};this.sizeDiff={width:e.outerWidth()-e.width(),height:e.outerHeight()-e.height()};this.originalMousePosition={left:b.pageX,top:b.pageY};this.aspectRatio=typeof a.aspectRatio=="number"?a.aspectRatio:
this.originalSize.width/this.originalSize.height||1;a=d(".ui-resizable-"+this.axis).css("cursor");d("body").css("cursor",a=="auto"?this.axis+"-resize":a);e.addClass("ui-resizable-resizing");this._propagate("start",b);return true},_mouseDrag:function(b){var a=this.helper,c=this.originalMousePosition,e=this._change[this.axis];if(!e)return false;c=e.apply(this,[b,b.pageX-c.left||0,b.pageY-c.top||0]);if(this._aspectRatio||b.shiftKey)c=this._updateRatio(c,b);c=this._respectSize(c,b);this._propagate("resize",
b);a.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize();this._updateCache(c);this._trigger("resize",b,this.ui());return false},_mouseStop:function(b){this.resizing=false;var a=this.options,c=this;if(this._helper){var e=this._proportionallyResizeElements,g=e.length&&/textarea/i.test(e[0].nodeName);e=g&&d.ui.hasScroll(e[0],"left")?0:c.sizeDiff.height;
g={width:c.size.width-(g?0:c.sizeDiff.width),height:c.size.height-e};e=parseInt(c.element.css("left"),10)+(c.position.left-c.originalPosition.left)||null;var f=parseInt(c.element.css("top"),10)+(c.position.top-c.originalPosition.top)||null;a.animate||this.element.css(d.extend(g,{top:f,left:e}));c.helper.height(c.size.height);c.helper.width(c.size.width);this._helper&&!a.animate&&this._proportionallyResize()}d("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",
b);this._helper&&this.helper.remove();return false},_updateCache:function(b){this.offset=this.helper.offset();if(k(b.left))this.position.left=b.left;if(k(b.top))this.position.top=b.top;if(k(b.height))this.size.height=b.height;if(k(b.width))this.size.width=b.width},_updateRatio:function(b){var a=this.position,c=this.size,e=this.axis;if(b.height)b.width=c.height*this.aspectRatio;else if(b.width)b.height=c.width/this.aspectRatio;if(e=="sw"){b.left=a.left+(c.width-b.width);b.top=null}if(e=="nw"){b.top=
a.top+(c.height-b.height);b.left=a.left+(c.width-b.width)}return b},_respectSize:function(b){var a=this.options,c=this.axis,e=k(b.width)&&a.maxWidth&&a.maxWidth<b.width,g=k(b.height)&&a.maxHeight&&a.maxHeight<b.height,f=k(b.width)&&a.minWidth&&a.minWidth>b.width,h=k(b.height)&&a.minHeight&&a.minHeight>b.height;if(f)b.width=a.minWidth;if(h)b.height=a.minHeight;if(e)b.width=a.maxWidth;if(g)b.height=a.maxHeight;var i=this.originalPosition.left+this.originalSize.width,j=this.position.top+this.size.height,
l=/sw|nw|w/.test(c);c=/nw|ne|n/.test(c);if(f&&l)b.left=i-a.minWidth;if(e&&l)b.left=i-a.maxWidth;if(h&&c)b.top=j-a.minHeight;if(g&&c)b.top=j-a.maxHeight;if((a=!b.width&&!b.height)&&!b.left&&b.top)b.top=null;else if(a&&!b.top&&b.left)b.left=null;return b},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var b=this.helper||this.element,a=0;a<this._proportionallyResizeElements.length;a++){var c=this._proportionallyResizeElements[a];if(!this.borderDif){var e=[c.css("borderTopWidth"),
c.css("borderRightWidth"),c.css("borderBottomWidth"),c.css("borderLeftWidth")],g=[c.css("paddingTop"),c.css("paddingRight"),c.css("paddingBottom"),c.css("paddingLeft")];this.borderDif=d.map(e,function(f,h){f=parseInt(f,10)||0;h=parseInt(g[h],10)||0;return f+h})}d.browser.msie&&(d(b).is(":hidden")||d(b).parents(":hidden").length)||c.css({height:b.height()-this.borderDif[0]-this.borderDif[2]||0,width:b.width()-this.borderDif[1]-this.borderDif[3]||0})}},_renderProxy:function(){var b=this.options;this.elementOffset=
this.element.offset();if(this._helper){this.helper=this.helper||d('<div style="overflow:hidden;"></div>');var a=d.browser.msie&&d.browser.version<7,c=a?1:0;a=a?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+a,height:this.element.outerHeight()+a,position:"absolute",left:this.elementOffset.left-c+"px",top:this.elementOffset.top-c+"px",zIndex:++b.zIndex});this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(b,a){return{width:this.originalSize.width+
a}},w:function(b,a){return{left:this.originalPosition.left+a,width:this.originalSize.width-a}},n:function(b,a,c){return{top:this.originalPosition.top+c,height:this.originalSize.height-c}},s:function(b,a,c){return{height:this.originalSize.height+c}},se:function(b,a,c){return d.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[b,a,c]))},sw:function(b,a,c){return d.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[b,a,c]))},ne:function(b,a,c){return d.extend(this._change.n.apply(this,
arguments),this._change.e.apply(this,[b,a,c]))},nw:function(b,a,c){return d.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[b,a,c]))}},_propagate:function(b,a){d.ui.plugin.call(this,b,[a,this.ui()]);b!="resize"&&this._trigger(b,a,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}});d.extend(d.ui.resizable,
{version:"1.8.2"});d.ui.plugin.add("resizable","alsoResize",{start:function(){var b=d(this).data("resizable").options,a=function(c){d(c).each(function(){d(this).data("resizable-alsoresize",{width:parseInt(d(this).width(),10),height:parseInt(d(this).height(),10),left:parseInt(d(this).css("left"),10),top:parseInt(d(this).css("top"),10)})})};if(typeof b.alsoResize=="object"&&!b.alsoResize.parentNode)if(b.alsoResize.length){b.alsoResize=b.alsoResize[0];a(b.alsoResize)}else d.each(b.alsoResize,function(c){a(c)});
else a(b.alsoResize)},resize:function(){var b=d(this).data("resizable"),a=b.options,c=b.originalSize,e=b.originalPosition,g={height:b.size.height-c.height||0,width:b.size.width-c.width||0,top:b.position.top-e.top||0,left:b.position.left-e.left||0},f=function(h,i){d(h).each(function(){var j=d(this),l=d(this).data("resizable-alsoresize"),p={};d.each((i&&i.length?i:["width","height","top","left"])||["width","height","top","left"],function(n,o){if((n=(l[o]||0)+(g[o]||0))&&n>=0)p[o]=n||null});if(/relative/.test(j.css("position"))&&
d.browser.opera){b._revertToRelativePosition=true;j.css({position:"absolute",top:"auto",left:"auto"})}j.css(p)})};typeof a.alsoResize=="object"&&!a.alsoResize.nodeType?d.each(a.alsoResize,function(h,i){f(h,i)}):f(a.alsoResize)},stop:function(){var b=d(this).data("resizable");if(b._revertToRelativePosition&&d.browser.opera){b._revertToRelativePosition=false;el.css({position:"relative"})}d(this).removeData("resizable-alsoresize-start")}});d.ui.plugin.add("resizable","animate",{stop:function(b){var a=
d(this).data("resizable"),c=a.options,e=a._proportionallyResizeElements,g=e.length&&/textarea/i.test(e[0].nodeName),f=g&&d.ui.hasScroll(e[0],"left")?0:a.sizeDiff.height;g={width:a.size.width-(g?0:a.sizeDiff.width),height:a.size.height-f};f=parseInt(a.element.css("left"),10)+(a.position.left-a.originalPosition.left)||null;var h=parseInt(a.element.css("top"),10)+(a.position.top-a.originalPosition.top)||null;a.element.animate(d.extend(g,h&&f?{top:h,left:f}:{}),{duration:c.animateDuration,easing:c.animateEasing,
step:function(){var i={width:parseInt(a.element.css("width"),10),height:parseInt(a.element.css("height"),10),top:parseInt(a.element.css("top"),10),left:parseInt(a.element.css("left"),10)};e&&e.length&&d(e[0]).css({width:i.width,height:i.height});a._updateCache(i);a._propagate("resize",b)}})}});d.ui.plugin.add("resizable","containment",{start:function(){var b=d(this).data("resizable"),a=b.element,c=b.options.containment;if(a=c instanceof d?c.get(0):/parent/.test(c)?a.parent().get(0):c){b.containerElement=
d(a);if(/document/.test(c)||c==document){b.containerOffset={left:0,top:0};b.containerPosition={left:0,top:0};b.parentData={element:d(document),left:0,top:0,width:d(document).width(),height:d(document).height()||document.body.parentNode.scrollHeight}}else{var e=d(a),g=[];d(["Top","Right","Left","Bottom"]).each(function(i,j){g[i]=m(e.css("padding"+j))});b.containerOffset=e.offset();b.containerPosition=e.position();b.containerSize={height:e.innerHeight()-g[3],width:e.innerWidth()-g[1]};c=b.containerOffset;
var f=b.containerSize.height,h=b.containerSize.width;h=d.ui.hasScroll(a,"left")?a.scrollWidth:h;f=d.ui.hasScroll(a)?a.scrollHeight:f;b.parentData={element:a,left:c.left,top:c.top,width:h,height:f}}}},resize:function(b){var a=d(this).data("resizable"),c=a.options,e=a.containerOffset,g=a.position;b=a._aspectRatio||b.shiftKey;var f={top:0,left:0},h=a.containerElement;if(h[0]!=document&&/static/.test(h.css("position")))f=e;if(g.left<(a._helper?e.left:0)){a.size.width+=a._helper?a.position.left-e.left:
a.position.left-f.left;if(b)a.size.height=a.size.width/c.aspectRatio;a.position.left=c.helper?e.left:0}if(g.top<(a._helper?e.top:0)){a.size.height+=a._helper?a.position.top-e.top:a.position.top;if(b)a.size.width=a.size.height*c.aspectRatio;a.position.top=a._helper?e.top:0}a.offset.left=a.parentData.left+a.position.left;a.offset.top=a.parentData.top+a.position.top;c=Math.abs((a._helper?a.offset.left-f.left:a.offset.left-f.left)+a.sizeDiff.width);e=Math.abs((a._helper?a.offset.top-f.top:a.offset.top-
e.top)+a.sizeDiff.height);g=a.containerElement.get(0)==a.element.parent().get(0);f=/relative|absolute/.test(a.containerElement.css("position"));if(g&&f)c-=a.parentData.left;if(c+a.size.width>=a.parentData.width){a.size.width=a.parentData.width-c;if(b)a.size.height=a.size.width/a.aspectRatio}if(e+a.size.height>=a.parentData.height){a.size.height=a.parentData.height-e;if(b)a.size.width=a.size.height*a.aspectRatio}},stop:function(){var b=d(this).data("resizable"),a=b.options,c=b.containerOffset,e=b.containerPosition,
g=b.containerElement,f=d(b.helper),h=f.offset(),i=f.outerWidth()-b.sizeDiff.width;f=f.outerHeight()-b.sizeDiff.height;b._helper&&!a.animate&&/relative/.test(g.css("position"))&&d(this).css({left:h.left-e.left-c.left,width:i,height:f});b._helper&&!a.animate&&/static/.test(g.css("position"))&&d(this).css({left:h.left-e.left-c.left,width:i,height:f})}});d.ui.plugin.add("resizable","ghost",{start:function(){var b=d(this).data("resizable"),a=b.options,c=b.size;b.ghost=b.originalElement.clone();b.ghost.css({opacity:0.25,
display:"block",position:"relative",height:c.height,width:c.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof a.ghost=="string"?a.ghost:"");b.ghost.appendTo(b.helper)},resize:function(){var b=d(this).data("resizable");b.ghost&&b.ghost.css({position:"relative",height:b.size.height,width:b.size.width})},stop:function(){var b=d(this).data("resizable");b.ghost&&b.helper&&b.helper.get(0).removeChild(b.ghost.get(0))}});d.ui.plugin.add("resizable","grid",{resize:function(){var b=
d(this).data("resizable"),a=b.options,c=b.size,e=b.originalSize,g=b.originalPosition,f=b.axis;a.grid=typeof a.grid=="number"?[a.grid,a.grid]:a.grid;var h=Math.round((c.width-e.width)/(a.grid[0]||1))*(a.grid[0]||1);a=Math.round((c.height-e.height)/(a.grid[1]||1))*(a.grid[1]||1);if(/^(se|s|e)$/.test(f)){b.size.width=e.width+h;b.size.height=e.height+a}else if(/^(ne)$/.test(f)){b.size.width=e.width+h;b.size.height=e.height+a;b.position.top=g.top-a}else{if(/^(sw)$/.test(f)){b.size.width=e.width+h;b.size.height=
e.height+a}else{b.size.width=e.width+h;b.size.height=e.height+a;b.position.top=g.top-a}b.position.left=g.left-h}}});var m=function(b){return parseInt(b,10)||0},k=function(b){return!isNaN(parseInt(b,10))}})(jQuery);
;
/*
 * jQuery UI Selectable 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Selectables
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.mouse.js
 *	jquery.ui.widget.js
 */
(function($) {

$.widget("ui.selectable", $.ui.mouse, {
	options: {
		appendTo: 'body',
		autoRefresh: true,
		distance: 0,
		filter: '*',
		tolerance: 'touch'
	},
	_create: function() {
		var self = this;

		this.element.addClass("ui-selectable");

		this.dragged = false;

		// cache selectee children based on filter
		var selectees;
		this.refresh = function() {
			selectees = $(self.options.filter, self.element[0]);
			selectees.each(function() {
				var $this = $(this);
				var pos = $this.offset();
				$.data(this, "selectable-item", {
					element: this,
					$element: $this,
					left: pos.left,
					top: pos.top,
					right: pos.left + $this.outerWidth(),
					bottom: pos.top + $this.outerHeight(),
					startselected: false,
					selected: $this.hasClass('ui-selected'),
					selecting: $this.hasClass('ui-selecting'),
					unselecting: $this.hasClass('ui-unselecting')
				});
			});
		};
		this.refresh();

		this.selectees = selectees.addClass("ui-selectee");

		this._mouseInit();

		this.helper = $("<div class='ui-selectable-helper'></div>");
	},

	destroy: function() {
		this.selectees
			.removeClass("ui-selectee")
			.removeData("selectable-item");
		this.element
			.removeClass("ui-selectable ui-selectable-disabled")
			.removeData("selectable")
			.unbind(".selectable");
		this._mouseDestroy();

		return this;
	},

	_mouseStart: function(event) {
		var self = this;

		this.opos = [event.pageX, event.pageY];

		if (this.options.disabled)
			return;

		var options = this.options;

		this.selectees = $(options.filter, this.element[0]);

		this._trigger("start", event);

		$(options.appendTo).append(this.helper);
		// position helper (lasso)
		this.helper.css({
			"z-index": 100,
			"position": "absolute",
			"left": event.clientX,
			"top": event.clientY,
			"width": 0,
			"height": 0
		});

		if (options.autoRefresh) {
			this.refresh();
		}

		this.selectees.filter('.ui-selected').each(function() {
			var selectee = $.data(this, "selectable-item");
			selectee.startselected = true;
			if (!event.metaKey) {
				selectee.$element.removeClass('ui-selected');
				selectee.selected = false;
				selectee.$element.addClass('ui-unselecting');
				selectee.unselecting = true;
				// selectable UNSELECTING callback
				self._trigger("unselecting", event, {
					unselecting: selectee.element
				});
			}
		});

		$(event.target).parents().andSelf().each(function() {
			var selectee = $.data(this, "selectable-item");
			if (selectee) {
				var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected');
				selectee.$element
					.removeClass(doSelect ? "ui-unselecting" : "ui-selected")
					.addClass(doSelect ? "ui-selecting" : "ui-unselecting");
				selectee.unselecting = !doSelect;
				selectee.selecting = doSelect;
				selectee.selected = doSelect;
				// selectable (UN)SELECTING callback
				if (doSelect) {
					self._trigger("selecting", event, {
						selecting: selectee.element
					});
				} else {
					self._trigger("unselecting", event, {
						unselecting: selectee.element
					});
				}
				return false;
			}
		});

	},

	_mouseDrag: function(event) {
		var self = this;
		this.dragged = true;

		if (this.options.disabled)
			return;

		var options = this.options;

		var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
		if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
		if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
		this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});

		this.selectees.each(function() {
			var selectee = $.data(this, "selectable-item");
			//prevent helper from being selected if appendTo: selectable
			if (!selectee || selectee.element == self.element[0])
				return;
			var hit = false;
			if (options.tolerance == 'touch') {
				hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
			} else if (options.tolerance == 'fit') {
				hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
			}

			if (hit) {
				// SELECT
				if (selectee.selected) {
					selectee.$element.removeClass('ui-selected');
					selectee.selected = false;
				}
				if (selectee.unselecting) {
					selectee.$element.removeClass('ui-unselecting');
					selectee.unselecting = false;
				}
				if (!selectee.selecting) {
					selectee.$element.addClass('ui-selecting');
					selectee.selecting = true;
					// selectable SELECTING callback
					self._trigger("selecting", event, {
						selecting: selectee.element
					});
				}
			} else {
				// UNSELECT
				if (selectee.selecting) {
					if (event.metaKey && selectee.startselected) {
						selectee.$element.removeClass('ui-selecting');
						selectee.selecting = false;
						selectee.$element.addClass('ui-selected');
						selectee.selected = true;
					} else {
						selectee.$element.removeClass('ui-selecting');
						selectee.selecting = false;
						if (selectee.startselected) {
							selectee.$element.addClass('ui-unselecting');
							selectee.unselecting = true;
						}
						// selectable UNSELECTING callback
						self._trigger("unselecting", event, {
							unselecting: selectee.element
						});
					}
				}
				if (selectee.selected) {
					if (!event.metaKey && !selectee.startselected) {
						selectee.$element.removeClass('ui-selected');
						selectee.selected = false;

						selectee.$element.addClass('ui-unselecting');
						selectee.unselecting = true;
						// selectable UNSELECTING callback
						self._trigger("unselecting", event, {
							unselecting: selectee.element
						});
					}
				}
			}
		});

		return false;
	},

	_mouseStop: function(event) {
		var self = this;

		this.dragged = false;

		var options = this.options;

		$('.ui-unselecting', this.element[0]).each(function() {
			var selectee = $.data(this, "selectable-item");
			selectee.$element.removeClass('ui-unselecting');
			selectee.unselecting = false;
			selectee.startselected = false;
			self._trigger("unselected", event, {
				unselected: selectee.element
			});
		});
		$('.ui-selecting', this.element[0]).each(function() {
			var selectee = $.data(this, "selectable-item");
			selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
			selectee.selecting = false;
			selectee.selected = true;
			selectee.startselected = true;
			self._trigger("selected", event, {
				selected: selectee.element
			});
		});
		this._trigger("stop", event);

		this.helper.remove();

		return false;
	}

});

$.extend($.ui.selectable, {
	version: "1.8.2"
});

})(jQuery);
(function(e){e.widget("ui.selectable",e.ui.mouse,{options:{appendTo:"body",autoRefresh:true,distance:0,filter:"*",tolerance:"touch"},_create:function(){var c=this;this.element.addClass("ui-selectable");this.dragged=false;var f;this.refresh=function(){f=e(c.options.filter,c.element[0]);f.each(function(){var d=e(this),b=d.offset();e.data(this,"selectable-item",{element:this,$element:d,left:b.left,top:b.top,right:b.left+d.outerWidth(),bottom:b.top+d.outerHeight(),startselected:false,selected:d.hasClass("ui-selected"),
selecting:d.hasClass("ui-selecting"),unselecting:d.hasClass("ui-unselecting")})})};this.refresh();this.selectees=f.addClass("ui-selectee");this._mouseInit();this.helper=e("<div class='ui-selectable-helper'></div>")},destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item");this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable");this._mouseDestroy();return this},_mouseStart:function(c){var f=this;this.opos=[c.pageX,
c.pageY];if(!this.options.disabled){var d=this.options;this.selectees=e(d.filter,this.element[0]);this._trigger("start",c);e(d.appendTo).append(this.helper);this.helper.css({"z-index":100,position:"absolute",left:c.clientX,top:c.clientY,width:0,height:0});d.autoRefresh&&this.refresh();this.selectees.filter(".ui-selected").each(function(){var b=e.data(this,"selectable-item");b.startselected=true;if(!c.metaKey){b.$element.removeClass("ui-selected");b.selected=false;b.$element.addClass("ui-unselecting");
b.unselecting=true;f._trigger("unselecting",c,{unselecting:b.element})}});e(c.target).parents().andSelf().each(function(){var b=e.data(this,"selectable-item");if(b){var g=!c.metaKey||!b.$element.hasClass("ui-selected");b.$element.removeClass(g?"ui-unselecting":"ui-selected").addClass(g?"ui-selecting":"ui-unselecting");b.unselecting=!g;b.selecting=g;(b.selected=g)?f._trigger("selecting",c,{selecting:b.element}):f._trigger("unselecting",c,{unselecting:b.element});return false}})}},_mouseDrag:function(c){var f=
this;this.dragged=true;if(!this.options.disabled){var d=this.options,b=this.opos[0],g=this.opos[1],h=c.pageX,i=c.pageY;if(b>h){var j=h;h=b;b=j}if(g>i){j=i;i=g;g=j}this.helper.css({left:b,top:g,width:h-b,height:i-g});this.selectees.each(function(){var a=e.data(this,"selectable-item");if(!(!a||a.element==f.element[0])){var k=false;if(d.tolerance=="touch")k=!(a.left>h||a.right<b||a.top>i||a.bottom<g);else if(d.tolerance=="fit")k=a.left>b&&a.right<h&&a.top>g&&a.bottom<i;if(k){if(a.selected){a.$element.removeClass("ui-selected");
a.selected=false}if(a.unselecting){a.$element.removeClass("ui-unselecting");a.unselecting=false}if(!a.selecting){a.$element.addClass("ui-selecting");a.selecting=true;f._trigger("selecting",c,{selecting:a.element})}}else{if(a.selecting)if(c.metaKey&&a.startselected){a.$element.removeClass("ui-selecting");a.selecting=false;a.$element.addClass("ui-selected");a.selected=true}else{a.$element.removeClass("ui-selecting");a.selecting=false;if(a.startselected){a.$element.addClass("ui-unselecting");a.unselecting=
true}f._trigger("unselecting",c,{unselecting:a.element})}if(a.selected)if(!c.metaKey&&!a.startselected){a.$element.removeClass("ui-selected");a.selected=false;a.$element.addClass("ui-unselecting");a.unselecting=true;f._trigger("unselecting",c,{unselecting:a.element})}}}});return false}},_mouseStop:function(c){var f=this;this.dragged=false;e(".ui-unselecting",this.element[0]).each(function(){var d=e.data(this,"selectable-item");d.$element.removeClass("ui-unselecting");d.unselecting=false;d.startselected=
false;f._trigger("unselected",c,{unselected:d.element})});e(".ui-selecting",this.element[0]).each(function(){var d=e.data(this,"selectable-item");d.$element.removeClass("ui-selecting").addClass("ui-selected");d.selecting=false;d.selected=true;d.startselected=true;f._trigger("selected",c,{selected:d.element})});this._trigger("stop",c);this.helper.remove();return false}});e.extend(e.ui.selectable,{version:"1.8.2"})})(jQuery);
;/*
 * jQuery UI Sortable 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Sortables
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.mouse.js
 *	jquery.ui.widget.js
 */
(function(d){d.widget("ui.sortable",d.ui.mouse,{widgetEventPrefix:"sort",options:{appendTo:"parent",axis:false,connectWith:false,containment:false,cursor:"auto",cursorAt:false,dropOnEmpty:true,forcePlaceholderSize:false,forceHelperSize:false,grid:false,handle:false,helper:"original",items:"> *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1E3},_create:function(){this.containerCache={};this.element.addClass("ui-sortable");
this.refresh();this.floating=this.items.length?/left|right/.test(this.items[0].item.css("float")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var a=this.items.length-1;a>=0;a--)this.items[a].item.removeData("sortable-item");return this},_setOption:function(a,b){if(a==="disabled"){this.options[a]=b;this.widget()[b?"addClass":"removeClass"]("ui-sortable-disabled")}else d.Widget.prototype._setOption.apply(this,
arguments)},_mouseCapture:function(a,b){if(this.reverting)return false;if(this.options.disabled||this.options.type=="static")return false;this._refreshItems(a);var c=null,e=this;d(a.target).parents().each(function(){if(d.data(this,"sortable-item")==e){c=d(this);return false}});if(d.data(a.target,"sortable-item")==e)c=d(a.target);if(!c)return false;if(this.options.handle&&!b){var f=false;d(this.options.handle,c).find("*").andSelf().each(function(){if(this==a.target)f=true});if(!f)return false}this.currentItem=
c;this._removeCurrentsFromItems();return true},_mouseStart:function(a,b,c){b=this.options;var e=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(a);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");d.extend(this.offset,
{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};this.helper[0]!=this.currentItem[0]&&this.currentItem.hide();this._createPlaceholder();b.containment&&this._setContainment();
if(b.cursor){if(d("body").css("cursor"))this._storedCursor=d("body").css("cursor");d("body").css("cursor",b.cursor)}if(b.opacity){if(this.helper.css("opacity"))this._storedOpacity=this.helper.css("opacity");this.helper.css("opacity",b.opacity)}if(b.zIndex){if(this.helper.css("zIndex"))this._storedZIndex=this.helper.css("zIndex");this.helper.css("zIndex",b.zIndex)}if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML")this.overflowOffset=this.scrollParent.offset();this._trigger("start",
a,this._uiHash());this._preserveHelperProportions||this._cacheHelperProportions();if(!c)for(c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("activate",a,e._uiHash(this));if(d.ui.ddmanager)d.ui.ddmanager.current=this;d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(a);return true},_mouseDrag:function(a){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");
if(!this.lastPositionAbs)this.lastPositionAbs=this.positionAbs;if(this.options.scroll){var b=this.options,c=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if(this.overflowOffset.top+this.scrollParent[0].offsetHeight-a.pageY<b.scrollSensitivity)this.scrollParent[0].scrollTop=c=this.scrollParent[0].scrollTop+b.scrollSpeed;else if(a.pageY-this.overflowOffset.top<b.scrollSensitivity)this.scrollParent[0].scrollTop=c=this.scrollParent[0].scrollTop-b.scrollSpeed;if(this.overflowOffset.left+
this.scrollParent[0].offsetWidth-a.pageX<b.scrollSensitivity)this.scrollParent[0].scrollLeft=c=this.scrollParent[0].scrollLeft+b.scrollSpeed;else if(a.pageX-this.overflowOffset.left<b.scrollSensitivity)this.scrollParent[0].scrollLeft=c=this.scrollParent[0].scrollLeft-b.scrollSpeed}else{if(a.pageY-d(document).scrollTop()<b.scrollSensitivity)c=d(document).scrollTop(d(document).scrollTop()-b.scrollSpeed);else if(d(window).height()-(a.pageY-d(document).scrollTop())<b.scrollSensitivity)c=d(document).scrollTop(d(document).scrollTop()+
b.scrollSpeed);if(a.pageX-d(document).scrollLeft()<b.scrollSensitivity)c=d(document).scrollLeft(d(document).scrollLeft()-b.scrollSpeed);else if(d(window).width()-(a.pageX-d(document).scrollLeft())<b.scrollSensitivity)c=d(document).scrollLeft(d(document).scrollLeft()+b.scrollSpeed)}c!==false&&d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a)}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+
"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";for(b=this.items.length-1;b>=0;b--){c=this.items[b];var e=c.item[0],f=this._intersectsWithPointer(c);if(f)if(e!=this.currentItem[0]&&this.placeholder[f==1?"next":"prev"]()[0]!=e&&!d.ui.contains(this.placeholder[0],e)&&(this.options.type=="semi-dynamic"?!d.ui.contains(this.element[0],e):true)){this.direction=f==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(c))this._rearrange(a,
c);else break;this._trigger("change",a,this._uiHash());break}}this._contactContainers(a);d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);this._trigger("sort",a,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(a,b){if(a){d.ui.ddmanager&&!this.options.dropBehaviour&&d.ui.ddmanager.drop(this,a);if(this.options.revert){var c=this;b=c.placeholder.offset();c.reverting=true;d(this.helper).animate({left:b.left-this.offset.parent.left-c.margins.left+(this.offsetParent[0]==
document.body?0:this.offsetParent[0].scrollLeft),top:b.top-this.offset.parent.top-c.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){c._clear(a)})}else this._clear(a,b);return false}},cancel:function(){var a=this;if(this.dragging){this._mouseUp();this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var b=this.containers.length-1;b>=0;b--){this.containers[b]._trigger("deactivate",
null,a._uiHash(this));if(this.containers[b].containerCache.over){this.containers[b]._trigger("out",null,a._uiHash(this));this.containers[b].containerCache.over=0}}}this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove();d.extend(this,{helper:null,dragging:false,reverting:false,_noFinalSort:null});this.domPosition.prev?d(this.domPosition.prev).after(this.currentItem):
d(this.domPosition.parent).prepend(this.currentItem);return this},serialize:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};d(b).each(function(){var e=(d(a.item||this).attr(a.attribute||"id")||"").match(a.expression||/(.+)[-=_](.+)/);if(e)c.push((a.key||e[1]+"[]")+"="+(a.key&&a.expression?e[1]:e[2]))});return c.join("&")},toArray:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};b.each(function(){c.push(d(a.item||this).attr(a.attribute||"id")||"")});return c},
_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,e=this.positionAbs.top,f=e+this.helperProportions.height,g=a.left,h=g+a.width,i=a.top,k=i+a.height,j=this.offset.click.top,l=this.offset.click.left;j=e+j>i&&e+j<k&&b+l>g&&b+l<h;return this.options.tolerance=="pointer"||this.options.forcePointerForContainers||this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>a[this.floating?"width":"height"]?j:g<b+this.helperProportions.width/
2&&c-this.helperProportions.width/2<h&&i<e+this.helperProportions.height/2&&f-this.helperProportions.height/2<k},_intersectsWithPointer:function(a){var b=d.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,a.top,a.height);a=d.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,a.left,a.width);b=b&&a;a=this._getDragVerticalDirection();var c=this._getDragHorizontalDirection();if(!b)return false;return this.floating?c&&c=="right"||a=="down"?2:1:a&&(a=="down"?2:1)},_intersectsWithSides:function(a){var b=
d.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,a.top+a.height/2,a.height);a=d.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,a.left+a.width/2,a.width);var c=this._getDragVerticalDirection(),e=this._getDragHorizontalDirection();return this.floating&&e?e=="right"&&a||e=="left"&&!a:c&&(c=="down"&&b||c=="up"&&!b)},_getDragVerticalDirection:function(){var a=this.positionAbs.top-this.lastPositionAbs.top;return a!=0&&(a>0?"down":"up")},_getDragHorizontalDirection:function(){var a=
this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){this._refreshItems(a);this.refreshPositions();return this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(a){var b=[],c=[],e=this._connectWith();if(e&&a)for(a=e.length-1;a>=0;a--)for(var f=d(e[a]),g=f.length-1;g>=0;g--){var h=d.data(f[g],"sortable");if(h&&h!=this&&!h.options.disabled)c.push([d.isFunction(h.options.items)?
h.options.items.call(h.element):d(h.options.items,h.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),h])}c.push([d.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):d(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(a=c.length-1;a>=0;a--)c[a][0].each(function(){b.push(this)});return d(b)},_removeCurrentsFromItems:function(){for(var a=this.currentItem.find(":data(sortable-item)"),
b=0;b<this.items.length;b++)for(var c=0;c<a.length;c++)a[c]==this.items[b].item[0]&&this.items.splice(b,1)},_refreshItems:function(a){this.items=[];this.containers=[this];var b=this.items,c=[[d.isFunction(this.options.items)?this.options.items.call(this.element[0],a,{item:this.currentItem}):d(this.options.items,this.element),this]],e=this._connectWith();if(e)for(var f=e.length-1;f>=0;f--)for(var g=d(e[f]),h=g.length-1;h>=0;h--){var i=d.data(g[h],"sortable");if(i&&i!=this&&!i.options.disabled){c.push([d.isFunction(i.options.items)?
i.options.items.call(i.element[0],a,{item:this.currentItem}):d(i.options.items,i.element),i]);this.containers.push(i)}}for(f=c.length-1;f>=0;f--){a=c[f][1];e=c[f][0];h=0;for(g=e.length;h<g;h++){i=d(e[h]);i.data("sortable-item",a);b.push({item:i,instance:a,width:0,height:0,left:0,top:0})}}},refreshPositions:function(a){if(this.offsetParent&&this.helper)this.offset.parent=this._getParentOffset();for(var b=this.items.length-1;b>=0;b--){var c=this.items[b],e=this.options.toleranceElement?d(this.options.toleranceElement,
c.item):c.item;if(!a){c.width=e.outerWidth();c.height=e.outerHeight()}e=e.offset();c.left=e.left;c.top=e.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(b=this.containers.length-1;b>=0;b--){e=this.containers[b].element.offset();this.containers[b].containerCache.left=e.left;this.containers[b].containerCache.top=e.top;this.containers[b].containerCache.width=this.containers[b].element.outerWidth();this.containers[b].containerCache.height=
this.containers[b].element.outerHeight()}return this},_createPlaceholder:function(a){var b=a||this,c=b.options;if(!c.placeholder||c.placeholder.constructor==String){var e=c.placeholder;c.placeholder={element:function(){var f=d(document.createElement(b.currentItem[0].nodeName)).addClass(e||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!e)f.style.visibility="hidden";return f},update:function(f,g){if(!(e&&!c.forcePlaceholderSize)){g.height()||g.height(b.currentItem.innerHeight()-
parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10));g.width()||g.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")||0,10))}}}}b.placeholder=d(c.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);c.placeholder.update(b,b.placeholder)},_contactContainers:function(a){for(var b=null,c=null,e=this.containers.length-1;e>=0;e--)if(!d.ui.contains(this.currentItem[0],
this.containers[e].element[0]))if(this._intersectsWith(this.containers[e].containerCache)){if(!(b&&d.ui.contains(this.containers[e].element[0],b.element[0]))){b=this.containers[e];c=e}}else if(this.containers[e].containerCache.over){this.containers[e]._trigger("out",a,this._uiHash(this));this.containers[e].containerCache.over=0}if(b)if(this.containers.length===1){this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}else if(this.currentContainer!=this.containers[c]){b=
1E4;e=null;for(var f=this.positionAbs[this.containers[c].floating?"left":"top"],g=this.items.length-1;g>=0;g--)if(d.ui.contains(this.containers[c].element[0],this.items[g].item[0])){var h=this.items[g][this.containers[c].floating?"left":"top"];if(Math.abs(h-f)<b){b=Math.abs(h-f);e=this.items[g]}}if(e||this.options.dropOnEmpty){this.currentContainer=this.containers[c];e?this._rearrange(a,e,null,true):this._rearrange(a,null,this.containers[c].element,true);this._trigger("change",a,this._uiHash());this.containers[c]._trigger("change",
a,this._uiHash(this));this.options.placeholder.update(this.currentContainer,this.placeholder);this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}}},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a,this.currentItem])):b.helper=="clone"?this.currentItem.clone():this.currentItem;a.parents("body").length||d(b.appendTo!="parent"?b.appendTo:this.currentItem[0].parentNode)[0].appendChild(a[0]);if(a[0]==
this.currentItem[0])this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")};if(a[0].style.width==""||b.forceHelperSize)a.width(this.currentItem.width());if(a[0].style.height==""||b.forceHelperSize)a.height(this.currentItem.height());return a},_adjustOffsetFromHelper:function(a){if(typeof a=="string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]||
0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],
this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.currentItem.position();return{top:a.top-
(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;
if(a.containment=="parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)){var b=
d(a.containment)[0];a=d(a.containment).offset();var c=d(b).css("overflow")!="hidden";this.containment=[a.left+(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0)-this.margins.left,a.top+(parseInt(d(b).css("borderTopWidth"),10)||0)+(parseInt(d(b).css("paddingTop"),10)||0)-this.margins.top,a.left+(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"),10)||0)-this.helperProportions.width-
this.margins.left,a.top+(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"),10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(c[0].tagName);return{top:b.top+
this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],
this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(c[0].tagName);if(this.cssPosition=="relative"&&!(this.scrollParent[0]!=document&&this.scrollParent[0]!=this.offsetParent[0]))this.offset.relative=this._getRelativeOffset();var f=a.pageX,g=a.pageY;if(this.originalPosition){if(this.containment){if(a.pageX-this.offset.click.left<this.containment[0])f=this.containment[0]+this.offset.click.left;if(a.pageY-this.offset.click.top<this.containment[1])g=this.containment[1]+this.offset.click.top;
if(a.pageX-this.offset.click.left>this.containment[2])f=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?g:!(g-this.offset.click.top<this.containment[1])?g-b.grid[1]:g+b.grid[1]:g;f=this.originalPageX+Math.round((f-
this.originalPageX)/b.grid[0])*b.grid[0];f=this.containment?!(f-this.offset.click.left<this.containment[0]||f-this.offset.click.left>this.containment[2])?f:!(f-this.offset.click.left<this.containment[0])?f-b.grid[0]:f+b.grid[0]:f}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(d.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:c.scrollTop()),left:f-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+
(d.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:c.scrollLeft())}},_rearrange:function(a,b,c,e){c?c[0].appendChild(this.placeholder[0]):b.item[0].parentNode.insertBefore(this.placeholder[0],this.direction=="down"?b.item[0]:b.item[0].nextSibling);this.counter=this.counter?++this.counter:1;var f=this,g=this.counter;window.setTimeout(function(){g==f.counter&&f.refreshPositions(!e)},0)},_clear:function(a,b){this.reverting=false;var c=[];!this._noFinalSort&&
this.currentItem[0].parentNode&&this.placeholder.before(this.currentItem);this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var e in this._storedCSS)if(this._storedCSS[e]=="auto"||this._storedCSS[e]=="static")this._storedCSS[e]="";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();this.fromOutside&&!b&&c.push(function(f){this._trigger("receive",f,this._uiHash(this.fromOutside))});if((this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||
this.domPosition.parent!=this.currentItem.parent()[0])&&!b)c.push(function(f){this._trigger("update",f,this._uiHash())});if(!d.ui.contains(this.element[0],this.currentItem[0])){b||c.push(function(f){this._trigger("remove",f,this._uiHash())});for(e=this.containers.length-1;e>=0;e--)if(d.ui.contains(this.containers[e].element[0],this.currentItem[0])&&!b){c.push(function(f){return function(g){f._trigger("receive",g,this._uiHash(this))}}.call(this,this.containers[e]));c.push(function(f){return function(g){f._trigger("update",
g,this._uiHash(this))}}.call(this,this.containers[e]))}}for(e=this.containers.length-1;e>=0;e--){b||c.push(function(f){return function(g){f._trigger("deactivate",g,this._uiHash(this))}}.call(this,this.containers[e]));if(this.containers[e].containerCache.over){c.push(function(f){return function(g){f._trigger("out",g,this._uiHash(this))}}.call(this,this.containers[e]));this.containers[e].containerCache.over=0}}this._storedCursor&&d("body").css("cursor",this._storedCursor);this._storedOpacity&&this.helper.css("opacity",
this._storedOpacity);if(this._storedZIndex)this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex);this.dragging=false;if(this.cancelHelperRemoval){if(!b){this._trigger("beforeStop",a,this._uiHash());for(e=0;e<c.length;e++)c[e].call(this,a);this._trigger("stop",a,this._uiHash())}return false}b||this._trigger("beforeStop",a,this._uiHash());this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.helper[0]!=this.currentItem[0]&&this.helper.remove();this.helper=null;if(!b){for(e=
0;e<c.length;e++)c[e].call(this,a);this._trigger("stop",a,this._uiHash())}this.fromOutside=false;return true},_trigger:function(){d.Widget.prototype._trigger.apply(this,arguments)===false&&this.cancel()},_uiHash:function(a){var b=a||this;return{helper:b.helper,placeholder:b.placeholder||d([]),position:b.position,originalPosition:b.originalPosition,offset:b.positionAbs,item:b.currentItem,sender:a?a.element:null}}});d.extend(d.ui.sortable,{version:"1.8.2"})})(jQuery);
;/*
 * jQuery UI Accordion 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Accordion
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 */
(function(c){c.widget("ui.accordion",{options:{active:0,animated:"slide",autoHeight:true,clearStyle:false,collapsible:false,event:"click",fillSpace:false,header:"> li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:false,navigationFilter:function(){return this.href.toLowerCase()==location.href.toLowerCase()}},_create:function(){var a=this.options,b=this;this.running=0;this.element.addClass("ui-accordion ui-widget ui-helper-reset");
this.element.children("li").addClass("ui-accordion-li-fix");this.headers=this.element.find(a.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){c(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){c(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){c(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){c(this).removeClass("ui-state-focus")});this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");
if(a.navigation){var d=this.element.find("a").filter(a.navigationFilter);if(d.length){var f=d.closest(".ui-accordion-header");this.active=f.length?f:d.closest(".ui-accordion-content").prev()}}this.active=this._findActive(this.active||a.active).toggleClass("ui-state-default").toggleClass("ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");this.active.next().addClass("ui-accordion-content-active");this._createIcons();this.resize();this.element.attr("role","tablist");this.headers.attr("role",
"tab").bind("keydown",function(g){return b._keydown(g)}).next().attr("role","tabpanel");this.headers.not(this.active||"").attr("aria-expanded","false").attr("tabIndex","-1").next().hide();this.active.length?this.active.attr("aria-expanded","true").attr("tabIndex","0"):this.headers.eq(0).attr("tabIndex","0");c.browser.safari||this.headers.find("a").attr("tabIndex","-1");a.event&&this.headers.bind(a.event+".accordion",function(g){b._clickHandler.call(b,g,this);g.preventDefault()})},_createIcons:function(){var a=
this.options;if(a.icons){c("<span/>").addClass("ui-icon "+a.icons.header).prependTo(this.headers);this.active.find(".ui-icon").toggleClass(a.icons.header).toggleClass(a.icons.headerSelected);this.element.addClass("ui-accordion-icons")}},_destroyIcons:function(){this.headers.children(".ui-icon").remove();this.element.removeClass("ui-accordion-icons")},destroy:function(){var a=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role").unbind(".accordion").removeData("accordion");
this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("tabIndex");this.headers.find("a").removeAttr("tabIndex");this._destroyIcons();var b=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active");if(a.autoHeight||a.fillHeight)b.css("height",
"");return this},_setOption:function(a,b){c.Widget.prototype._setOption.apply(this,arguments);a=="active"&&this.activate(b);if(a=="icons"){this._destroyIcons();b&&this._createIcons()}},_keydown:function(a){var b=c.ui.keyCode;if(!(this.options.disabled||a.altKey||a.ctrlKey)){var d=this.headers.length,f=this.headers.index(a.target),g=false;switch(a.keyCode){case b.RIGHT:case b.DOWN:g=this.headers[(f+1)%d];break;case b.LEFT:case b.UP:g=this.headers[(f-1+d)%d];break;case b.SPACE:case b.ENTER:this._clickHandler({target:a.target},
a.target);a.preventDefault()}if(g){c(a.target).attr("tabIndex","-1");c(g).attr("tabIndex","0");g.focus();return false}return true}},resize:function(){var a=this.options,b;if(a.fillSpace){if(c.browser.msie){var d=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}b=this.element.parent().height();c.browser.msie&&this.element.parent().css("overflow",d);this.headers.each(function(){b-=c(this).outerHeight(true)});this.headers.next().each(function(){c(this).height(Math.max(0,
b-c(this).innerHeight()+c(this).height()))}).css("overflow","auto")}else if(a.autoHeight){b=0;this.headers.next().each(function(){b=Math.max(b,c(this).height())}).height(b)}return this},activate:function(a){this.options.active=a;a=this._findActive(a)[0];this._clickHandler({target:a},a);return this},_findActive:function(a){return a?typeof a=="number"?this.headers.filter(":eq("+a+")"):this.headers.not(this.headers.not(a)):a===false?c([]):this.headers.filter(":eq(0)")},_clickHandler:function(a,b){var d=
this.options;if(!d.disabled)if(a.target){a=c(a.currentTarget||b);b=a[0]==this.active[0];d.active=d.collapsible&&b?false:c(".ui-accordion-header",this.element).index(a);if(!(this.running||!d.collapsible&&b)){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").find(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);if(!b){a.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").find(".ui-icon").removeClass(d.icons.header).addClass(d.icons.headerSelected);
a.next().addClass("ui-accordion-content-active")}e=a.next();f=this.active.next();g={options:d,newHeader:b&&d.collapsible?c([]):a,oldHeader:this.active,newContent:b&&d.collapsible?c([]):e,oldContent:f};d=this.headers.index(this.active[0])>this.headers.index(a[0]);this.active=b?c([]):a;this._toggle(e,f,g,b,d)}}else if(d.collapsible){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").find(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);
this.active.next().addClass("ui-accordion-content-active");var f=this.active.next(),g={options:d,newHeader:c([]),oldHeader:d.active,newContent:c([]),oldContent:f},e=this.active=c([]);this._toggle(e,f,g)}},_toggle:function(a,b,d,f,g){var e=this.options,k=this;this.toShow=a;this.toHide=b;this.data=d;var i=function(){if(k)return k._completed.apply(k,arguments)};this._trigger("changestart",null,this.data);this.running=b.size()===0?a.size():b.size();if(e.animated){d={};d=e.collapsible&&f?{toShow:c([]),
toHide:b,complete:i,down:g,autoHeight:e.autoHeight||e.fillSpace}:{toShow:a,toHide:b,complete:i,down:g,autoHeight:e.autoHeight||e.fillSpace};if(!e.proxied)e.proxied=e.animated;if(!e.proxiedDuration)e.proxiedDuration=e.duration;e.animated=c.isFunction(e.proxied)?e.proxied(d):e.proxied;e.duration=c.isFunction(e.proxiedDuration)?e.proxiedDuration(d):e.proxiedDuration;f=c.ui.accordion.animations;var h=e.duration,j=e.animated;if(j&&!f[j]&&!c.easing[j])j="slide";f[j]||(f[j]=function(l){this.slide(l,{easing:j,
duration:h||700})});f[j](d)}else{if(e.collapsible&&f)a.toggle();else{b.hide();a.show()}i(true)}b.prev().attr("aria-expanded","false").attr("tabIndex","-1").blur();a.prev().attr("aria-expanded","true").attr("tabIndex","0").focus()},_completed:function(a){var b=this.options;this.running=a?0:--this.running;if(!this.running){b.clearStyle&&this.toShow.add(this.toHide).css({height:"",overflow:""});this.toHide.removeClass("ui-accordion-content-active");this._trigger("change",null,this.data)}}});c.extend(c.ui.accordion,
{version:"1.8.2",animations:{slide:function(a,b){a=c.extend({easing:"swing",duration:300},a,b);if(a.toHide.size())if(a.toShow.size()){var d=a.toShow.css("overflow"),f=0,g={},e={},k;b=a.toShow;k=b[0].style.width;b.width(parseInt(b.parent().width(),10)-parseInt(b.css("paddingLeft"),10)-parseInt(b.css("paddingRight"),10)-(parseInt(b.css("borderLeftWidth"),10)||0)-(parseInt(b.css("borderRightWidth"),10)||0));c.each(["height","paddingTop","paddingBottom"],function(i,h){e[h]="hide";i=(""+c.css(a.toShow[0],
h)).match(/^([\d+-.]+)(.*)$/);g[h]={value:i[1],unit:i[2]||"px"}});a.toShow.css({height:0,overflow:"hidden"}).show();a.toHide.filter(":hidden").each(a.complete).end().filter(":visible").animate(e,{step:function(i,h){if(h.prop=="height")f=h.end-h.start===0?0:(h.now-h.start)/(h.end-h.start);a.toShow[0].style[h.prop]=f*g[h.prop].value+g[h.prop].unit},duration:a.duration,easing:a.easing,complete:function(){a.autoHeight||a.toShow.css("height","");a.toShow.css("width",k);a.toShow.css({overflow:d});a.complete()}})}else a.toHide.animate({height:"hide"},
a);else a.toShow.animate({height:"show"},a)},bounceslide:function(a){this.slide(a,{easing:a.down?"easeOutBounce":"swing",duration:a.down?1E3:200})}}})})(jQuery);
;/*
 * jQuery UI Autocomplete 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Autocomplete
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 *	jquery.ui.position.js
 */
(function(e){e.widget("ui.autocomplete",{options:{minLength:1,delay:300},_create:function(){var a=this,c=this.element[0].ownerDocument;this.element.addClass("ui-autocomplete-input").attr("autocomplete","off").attr({role:"textbox","aria-autocomplete":"list","aria-haspopup":"true"}).bind("keydown.autocomplete",function(d){var b=e.ui.keyCode;switch(d.keyCode){case b.PAGE_UP:a._move("previousPage",d);break;case b.PAGE_DOWN:a._move("nextPage",d);break;case b.UP:a._move("previous",d);d.preventDefault();
break;case b.DOWN:a._move("next",d);d.preventDefault();break;case b.ENTER:case b.NUMPAD_ENTER:a.menu.active&&d.preventDefault();case b.TAB:if(!a.menu.active)return;a.menu.select(d);break;case b.ESCAPE:a.element.val(a.term);a.close(d);break;case b.LEFT:case b.RIGHT:case b.SHIFT:case b.CONTROL:case b.ALT:case b.COMMAND:case b.COMMAND_RIGHT:case b.INSERT:case b.CAPS_LOCK:case b.END:case b.HOME:break;default:clearTimeout(a.searching);a.searching=setTimeout(function(){a.search(null,d)},a.options.delay);
break}}).bind("focus.autocomplete",function(){a.selectedItem=null;a.previous=a.element.val()}).bind("blur.autocomplete",function(d){clearTimeout(a.searching);a.closing=setTimeout(function(){a.close(d);a._change(d)},150)});this._initSource();this.response=function(){return a._response.apply(a,arguments)};this.menu=e("<ul></ul>").addClass("ui-autocomplete").appendTo("body",c).mousedown(function(){setTimeout(function(){clearTimeout(a.closing)},13)}).menu({focus:function(d,b){b=b.item.data("item.autocomplete");
false!==a._trigger("focus",null,{item:b})&&/^key/.test(d.originalEvent.type)&&a.element.val(b.value)},selected:function(d,b){b=b.item.data("item.autocomplete");false!==a._trigger("select",d,{item:b})&&a.element.val(b.value);a.close(d);d=a.previous;if(a.element[0]!==c.activeElement){a.element.focus();a.previous=d}a.selectedItem=b},blur:function(){a.menu.element.is(":visible")&&a.element.val(a.term)}}).zIndex(this.element.zIndex()+1).css({top:0,left:0}).hide().data("menu");e.fn.bgiframe&&this.menu.element.bgiframe()},
destroy:function(){this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete").removeAttr("role").removeAttr("aria-autocomplete").removeAttr("aria-haspopup");this.menu.element.remove();e.Widget.prototype.destroy.call(this)},_setOption:function(a){e.Widget.prototype._setOption.apply(this,arguments);a==="source"&&this._initSource()},_initSource:function(){var a,c;if(e.isArray(this.options.source)){a=this.options.source;this.source=function(d,b){b(e.ui.autocomplete.filter(a,d.term))}}else if(typeof this.options.source===
"string"){c=this.options.source;this.source=function(d,b){e.getJSON(c,d,b)}}else this.source=this.options.source},search:function(a,c){a=a!=null?a:this.element.val();if(a.length<this.options.minLength)return this.close(c);clearTimeout(this.closing);if(this._trigger("search")!==false)return this._search(a)},_search:function(a){this.term=this.element.addClass("ui-autocomplete-loading").val();this.source({term:a},this.response)},_response:function(a){if(a.length){a=this._normalize(a);this._suggest(a);
this._trigger("open")}else this.close();this.element.removeClass("ui-autocomplete-loading")},close:function(a){clearTimeout(this.closing);if(this.menu.element.is(":visible")){this._trigger("close",a);this.menu.element.hide();this.menu.deactivate()}},_change:function(a){this.previous!==this.element.val()&&this._trigger("change",a,{item:this.selectedItem})},_normalize:function(a){if(a.length&&a[0].label&&a[0].value)return a;return e.map(a,function(c){if(typeof c==="string")return{label:c,value:c};return e.extend({label:c.label||
c.value,value:c.value||c.label},c)})},_suggest:function(a){var c=this.menu.element.empty().zIndex(this.element.zIndex()+1),d;this._renderMenu(c,a);this.menu.deactivate();this.menu.refresh();this.menu.element.show().position({my:"left top",at:"left bottom",of:this.element,collision:"none"});a=c.width("").width();d=this.element.width();c.width(Math.max(a,d))},_renderMenu:function(a,c){var d=this;e.each(c,function(b,f){d._renderItem(a,f)})},_renderItem:function(a,c){return e("<li></li>").data("item.autocomplete",
c).append("<a>"+c.label+"</a>").appendTo(a)},_move:function(a,c){if(this.menu.element.is(":visible"))if(this.menu.first()&&/^previous/.test(a)||this.menu.last()&&/^next/.test(a)){this.element.val(this.term);this.menu.deactivate()}else this.menu[a](c);else this.search(null,c)},widget:function(){return this.menu.element}});e.extend(e.ui.autocomplete,{escapeRegex:function(a){return a.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi,"\\$1")},filter:function(a,c){var d=new RegExp(e.ui.autocomplete.escapeRegex(c),
"i");return e.grep(a,function(b){return d.test(b.label||b.value||b)})}})})(jQuery);
(function(e){e.widget("ui.menu",{_create:function(){var a=this;this.element.addClass("ui-menu ui-widget ui-widget-content ui-corner-all").attr({role:"listbox","aria-activedescendant":"ui-active-menuitem"}).click(function(c){if(e(c.target).closest(".ui-menu-item a").length){c.preventDefault();a.select(c)}});this.refresh()},refresh:function(){var a=this;this.element.children("li:not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","menuitem").children("a").addClass("ui-corner-all").attr("tabindex",
-1).mouseenter(function(c){a.activate(c,e(this).parent())}).mouseleave(function(){a.deactivate()})},activate:function(a,c){this.deactivate();if(this.hasScroll()){var d=c.offset().top-this.element.offset().top,b=this.element.attr("scrollTop"),f=this.element.height();if(d<0)this.element.attr("scrollTop",b+d);else d>f&&this.element.attr("scrollTop",b+d-f+c.height())}this.active=c.eq(0).children("a").addClass("ui-state-hover").attr("id","ui-active-menuitem").end();this._trigger("focus",a,{item:c})},deactivate:function(){if(this.active){this.active.children("a").removeClass("ui-state-hover").removeAttr("id");
this._trigger("blur");this.active=null}},next:function(a){this.move("next",".ui-menu-item:first",a)},previous:function(a){this.move("prev",".ui-menu-item:last",a)},first:function(){return this.active&&!this.active.prev().length},last:function(){return this.active&&!this.active.next().length},move:function(a,c,d){if(this.active){a=this.active[a+"All"](".ui-menu-item").eq(0);a.length?this.activate(d,a):this.activate(d,this.element.children(c))}else this.activate(d,this.element.children(c))},nextPage:function(a){if(this.hasScroll())if(!this.active||
this.last())this.activate(a,this.element.children(":first"));else{var c=this.active.offset().top,d=this.element.height(),b=this.element.children("li").filter(function(){var f=e(this).offset().top-c-d+e(this).height();return f<10&&f>-10});b.length||(b=this.element.children(":last"));this.activate(a,b)}else this.activate(a,this.element.children(!this.active||this.last()?":first":":last"))},previousPage:function(a){if(this.hasScroll())if(!this.active||this.first())this.activate(a,this.element.children(":last"));
else{var c=this.active.offset().top,d=this.element.height();result=this.element.children("li").filter(function(){var b=e(this).offset().top-c+d-e(this).height();return b<10&&b>-10});result.length||(result=this.element.children(":first"));this.activate(a,result)}else this.activate(a,this.element.children(!this.active||this.first()?":last":":first"))},hasScroll:function(){return this.element.height()<this.element.attr("scrollHeight")},select:function(a){this._trigger("selected",a,{item:this.active})}})})(jQuery);
;/*
 * jQuery UI Button 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Button
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 */
(function(a){var g,i=function(b){a(":ui-button",b.target.form).each(function(){var c=a(this).data("button");setTimeout(function(){c.refresh()},1)})},h=function(b){var c=b.name,d=b.form,e=a([]);if(c)e=d?a(d).find("[name='"+c+"']"):a("[name='"+c+"']",b.ownerDocument).filter(function(){return!this.form});return e};a.widget("ui.button",{options:{text:true,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset.button").bind("reset.button",i);this._determineButtonType();
this.hasTitle=!!this.buttonElement.attr("title");var b=this,c=this.options,d=this.type==="checkbox"||this.type==="radio",e="ui-state-hover"+(!d?" ui-state-active":"");if(c.label===null)c.label=this.buttonElement.html();if(this.element.is(":disabled"))c.disabled=true;this.buttonElement.addClass("ui-button ui-widget ui-state-default ui-corner-all").attr("role","button").bind("mouseenter.button",function(){if(!c.disabled){a(this).addClass("ui-state-hover");this===g&&a(this).addClass("ui-state-active")}}).bind("mouseleave.button",
function(){c.disabled||a(this).removeClass(e)}).bind("focus.button",function(){a(this).addClass("ui-state-focus")}).bind("blur.button",function(){a(this).removeClass("ui-state-focus")});d&&this.element.bind("change.button",function(){b.refresh()});if(this.type==="checkbox")this.buttonElement.bind("click.button",function(){if(c.disabled)return false;a(this).toggleClass("ui-state-active");b.buttonElement.attr("aria-pressed",b.element[0].checked)});else if(this.type==="radio")this.buttonElement.bind("click.button",
function(){if(c.disabled)return false;a(this).addClass("ui-state-active");b.buttonElement.attr("aria-pressed",true);var f=b.element[0];h(f).not(f).map(function(){return a(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed",false)});else{this.buttonElement.bind("mousedown.button",function(){if(c.disabled)return false;a(this).addClass("ui-state-active");g=this;a(document).one("mouseup",function(){g=null})}).bind("mouseup.button",function(){if(c.disabled)return false;a(this).removeClass("ui-state-active")}).bind("keydown.button",
function(f){if(c.disabled)return false;if(f.keyCode==a.ui.keyCode.SPACE||f.keyCode==a.ui.keyCode.ENTER)a(this).addClass("ui-state-active")}).bind("keyup.button",function(){a(this).removeClass("ui-state-active")});this.buttonElement.is("a")&&this.buttonElement.keyup(function(f){f.keyCode===a.ui.keyCode.SPACE&&a(this).click()})}this._setOption("disabled",c.disabled)},_determineButtonType:function(){this.type=this.element.is(":checkbox")?"checkbox":this.element.is(":radio")?"radio":this.element.is("input")?
"input":"button";if(this.type==="checkbox"||this.type==="radio"){this.buttonElement=this.element.parents().last().find("[for="+this.element.attr("id")+"]");this.element.addClass("ui-helper-hidden-accessible");var b=this.element.is(":checked");b&&this.buttonElement.addClass("ui-state-active");this.buttonElement.attr("aria-pressed",b)}else this.buttonElement=this.element},widget:function(){return this.buttonElement},destroy:function(){this.element.removeClass("ui-helper-hidden-accessible");this.buttonElement.removeClass("ui-button ui-widget ui-state-default ui-corner-all ui-state-hover ui-state-active  ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon ui-button-text-only").removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html());
this.hasTitle||this.buttonElement.removeAttr("title");a.Widget.prototype.destroy.call(this)},_setOption:function(b,c){a.Widget.prototype._setOption.apply(this,arguments);if(b==="disabled")c?this.element.attr("disabled",true):this.element.removeAttr("disabled");this._resetButton()},refresh:function(){var b=this.element.is(":disabled");b!==this.options.disabled&&this._setOption("disabled",b);if(this.type==="radio")h(this.element[0]).each(function(){a(this).is(":checked")?a(this).button("widget").addClass("ui-state-active").attr("aria-pressed",
true):a(this).button("widget").removeClass("ui-state-active").attr("aria-pressed",false)});else if(this.type==="checkbox")this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed",true):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed",false)},_resetButton:function(){if(this.type==="input")this.options.label&&this.element.val(this.options.label);else{var b=this.buttonElement.removeClass("ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon ui-button-text-only"),
c=a("<span></span>").addClass("ui-button-text").html(this.options.label).appendTo(b.empty()).text(),d=this.options.icons,e=d.primary&&d.secondary;if(d.primary||d.secondary){b.addClass("ui-button-text-icon"+(e?"s":""));d.primary&&b.prepend("<span class='ui-button-icon-primary ui-icon "+d.primary+"'></span>");d.secondary&&b.append("<span class='ui-button-icon-secondary ui-icon "+d.secondary+"'></span>");if(!this.options.text){b.addClass(e?"ui-button-icons-only":"ui-button-icon-only").removeClass("ui-button-text-icons ui-button-text-icon");
this.hasTitle||b.attr("title",c)}}else b.addClass("ui-button-text-only")}}});a.widget("ui.buttonset",{_create:function(){this.element.addClass("ui-buttonset");this._init()},_init:function(){this.refresh()},_setOption:function(b,c){b==="disabled"&&this.buttons.button("option",b,c);a.Widget.prototype._setOption.apply(this,arguments)},refresh:function(){this.buttons=this.element.find(":button, :submit, :reset, :checkbox, :radio, a, :data(button)").filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass("ui-corner-left").end().filter(":last").addClass("ui-corner-right").end().end()},
destroy:function(){this.element.removeClass("ui-buttonset");this.buttons.map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy");a.Widget.prototype.destroy.call(this)}})})(jQuery);
;/*
 * jQuery UI Dialog 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Dialog
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 *  jquery.ui.button.js
 *	jquery.ui.draggable.js
 *	jquery.ui.mouse.js
 *	jquery.ui.position.js
 *	jquery.ui.resizable.js
 */
(function(c){c.widget("ui.dialog",{options:{autoOpen:true,buttons:{},closeOnEscape:true,closeText:"close",dialogClass:"",draggable:true,hide:null,height:"auto",maxHeight:false,maxWidth:false,minHeight:150,minWidth:150,modal:false,position:"center",resizable:true,show:null,stack:true,title:"",width:300,zIndex:1E3},_create:function(){this.originalTitle=this.element.attr("title");var a=this,b=a.options,d=b.title||a.originalTitle||"&#160;",e=c.ui.dialog.getTitleId(a.element),g=(a.uiDialog=c("<div></div>")).appendTo(document.body).hide().addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+
b.dialogClass).css({zIndex:b.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(i){if(b.closeOnEscape&&i.keyCode&&i.keyCode===c.ui.keyCode.ESCAPE){a.close(i);i.preventDefault()}}).attr({role:"dialog","aria-labelledby":e}).mousedown(function(i){a.moveToTop(false,i)});a.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(g);var f=(a.uiDialogTitlebar=c("<div></div>")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(g),
h=c('<a href="#"></a>').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){h.addClass("ui-state-hover")},function(){h.removeClass("ui-state-hover")}).focus(function(){h.addClass("ui-state-focus")}).blur(function(){h.removeClass("ui-state-focus")}).click(function(i){a.close(i);return false}).appendTo(f);(a.uiDialogTitlebarCloseText=c("<span></span>")).addClass("ui-icon ui-icon-closethick").text(b.closeText).appendTo(h);c("<span></span>").addClass("ui-dialog-title").attr("id",
e).html(d).prependTo(f);if(c.isFunction(b.beforeclose)&&!c.isFunction(b.beforeClose))b.beforeClose=b.beforeclose;f.find("*").add(f).disableSelection();b.draggable&&c.fn.draggable&&a._makeDraggable();b.resizable&&c.fn.resizable&&a._makeResizable();a._createButtons(b.buttons);a._isOpen=false;c.fn.bgiframe&&g.bgiframe()},_init:function(){this.options.autoOpen&&this.open()},destroy:function(){var a=this;a.overlay&&a.overlay.destroy();a.uiDialog.hide();a.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body");
a.uiDialog.remove();a.originalTitle&&a.element.attr("title",a.originalTitle);return a},widget:function(){return this.uiDialog},close:function(a){var b=this,d;if(false!==b._trigger("beforeClose",a)){b.overlay&&b.overlay.destroy();b.uiDialog.unbind("keypress.ui-dialog");b._isOpen=false;if(b.options.hide)b.uiDialog.hide(b.options.hide,function(){b._trigger("close",a)});else{b.uiDialog.hide();b._trigger("close",a)}c.ui.dialog.overlay.resize();if(b.options.modal){d=0;c(".ui-dialog").each(function(){if(this!==
b.uiDialog[0])d=Math.max(d,c(this).css("z-index"))});c.ui.dialog.maxZ=d}return b}},isOpen:function(){return this._isOpen},moveToTop:function(a,b){var d=this,e=d.options;if(e.modal&&!a||!e.stack&&!e.modal)return d._trigger("focus",b);if(e.zIndex>c.ui.dialog.maxZ)c.ui.dialog.maxZ=e.zIndex;if(d.overlay){c.ui.dialog.maxZ+=1;d.overlay.$el.css("z-index",c.ui.dialog.overlay.maxZ=c.ui.dialog.maxZ)}a={scrollTop:d.element.attr("scrollTop"),scrollLeft:d.element.attr("scrollLeft")};c.ui.dialog.maxZ+=1;d.uiDialog.css("z-index",
c.ui.dialog.maxZ);d.element.attr(a);d._trigger("focus",b);return d},open:function(){if(!this._isOpen){var a=this,b=a.options,d=a.uiDialog;a.overlay=b.modal?new c.ui.dialog.overlay(a):null;d.next().length&&d.appendTo("body");a._size();a._position(b.position);d.show(b.show);a.moveToTop(true);b.modal&&d.bind("keypress.ui-dialog",function(e){if(e.keyCode===c.ui.keyCode.TAB){var g=c(":tabbable",this),f=g.filter(":first");g=g.filter(":last");if(e.target===g[0]&&!e.shiftKey){f.focus(1);return false}else if(e.target===
f[0]&&e.shiftKey){g.focus(1);return false}}});c([]).add(d.find(".ui-dialog-content :tabbable:first")).add(d.find(".ui-dialog-buttonpane :tabbable:first")).add(d).filter(":first").focus();a._trigger("open");a._isOpen=true;return a}},_createButtons:function(a){var b=this,d=false,e=c("<div></div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix");b.uiDialog.find(".ui-dialog-buttonpane").remove();typeof a==="object"&&a!==null&&c.each(a,function(){return!(d=true)});if(d){c.each(a,
function(g,f){g=c('<button type="button"></button>').text(g).click(function(){f.apply(b.element[0],arguments)}).appendTo(e);c.fn.button&&g.button()});e.appendTo(b.uiDialog)}},_makeDraggable:function(){function a(f){return{position:f.position,offset:f.offset}}var b=this,d=b.options,e=c(document),g;b.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(f,h){g=d.height==="auto"?"auto":c(this).height();c(this).height(c(this).height()).addClass("ui-dialog-dragging");
b._trigger("dragStart",f,a(h))},drag:function(f,h){b._trigger("drag",f,a(h))},stop:function(f,h){d.position=[h.position.left-e.scrollLeft(),h.position.top-e.scrollTop()];c(this).removeClass("ui-dialog-dragging").height(g);b._trigger("dragStop",f,a(h));c.ui.dialog.overlay.resize()}})},_makeResizable:function(a){function b(f){return{originalPosition:f.originalPosition,originalSize:f.originalSize,position:f.position,size:f.size}}a=a===undefined?this.options.resizable:a;var d=this,e=d.options,g=d.uiDialog.css("position");
a=typeof a==="string"?a:"n,e,s,w,se,sw,ne,nw";d.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:d.element,maxWidth:e.maxWidth,maxHeight:e.maxHeight,minWidth:e.minWidth,minHeight:d._minHeight(),handles:a,start:function(f,h){c(this).addClass("ui-dialog-resizing");d._trigger("resizeStart",f,b(h))},resize:function(f,h){d._trigger("resize",f,b(h))},stop:function(f,h){c(this).removeClass("ui-dialog-resizing");e.height=c(this).height();e.width=c(this).width();d._trigger("resizeStop",
f,b(h));c.ui.dialog.overlay.resize()}}).css("position",g).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var a=this.options;return a.height==="auto"?a.minHeight:Math.min(a.minHeight,a.height)},_position:function(a){var b=[],d=[0,0];a=a||c.ui.dialog.prototype.options.position;if(typeof a==="string"||typeof a==="object"&&"0"in a){b=a.split?a.split(" "):[a[0],a[1]];if(b.length===1)b[1]=b[0];c.each(["left","top"],function(e,g){if(+b[e]===b[e]){d[e]=b[e];b[e]=
g}})}else if(typeof a==="object"){if("left"in a){b[0]="left";d[0]=a.left}else if("right"in a){b[0]="right";d[0]=-a.right}if("top"in a){b[1]="top";d[1]=a.top}else if("bottom"in a){b[1]="bottom";d[1]=-a.bottom}}(a=this.uiDialog.is(":visible"))||this.uiDialog.show();this.uiDialog.css({top:0,left:0}).position({my:b.join(" "),at:b.join(" "),offset:d.join(" "),of:window,collision:"fit",using:function(e){var g=c(this).css(e).offset().top;g<0&&c(this).css("top",e.top-g)}});a||this.uiDialog.hide()},_setOption:function(a,
b){var d=this,e=d.uiDialog,g=e.is(":data(resizable)"),f=false;switch(a){case "beforeclose":a="beforeClose";break;case "buttons":d._createButtons(b);break;case "closeText":d.uiDialogTitlebarCloseText.text(""+b);break;case "dialogClass":e.removeClass(d.options.dialogClass).addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+b);break;case "disabled":b?e.addClass("ui-dialog-disabled"):e.removeClass("ui-dialog-disabled");break;case "draggable":b?d._makeDraggable():e.draggable("destroy");break;
case "height":f=true;break;case "maxHeight":g&&e.resizable("option","maxHeight",b);f=true;break;case "maxWidth":g&&e.resizable("option","maxWidth",b);f=true;break;case "minHeight":g&&e.resizable("option","minHeight",b);f=true;break;case "minWidth":g&&e.resizable("option","minWidth",b);f=true;break;case "position":d._position(b);break;case "resizable":g&&!b&&e.resizable("destroy");g&&typeof b==="string"&&e.resizable("option","handles",b);!g&&b!==false&&d._makeResizable(b);break;case "title":c(".ui-dialog-title",
d.uiDialogTitlebar).html(""+(b||"&#160;"));break;case "width":f=true;break}c.Widget.prototype._setOption.apply(d,arguments);f&&d._size()},_size:function(){var a=this.options,b;this.element.css({width:"auto",minHeight:0,height:0});b=this.uiDialog.css({height:"auto",width:a.width}).height();this.element.css(a.height==="auto"?{minHeight:Math.max(a.minHeight-b,0),height:"auto"}:{minHeight:0,height:Math.max(a.height-b,0)}).show();this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",
this._minHeight())}});c.extend(c.ui.dialog,{version:"1.8.2",uuid:0,maxZ:0,getTitleId:function(a){a=a.attr("id");if(!a){this.uuid+=1;a=this.uuid}return"ui-dialog-title-"+a},overlay:function(a){this.$el=c.ui.dialog.overlay.create(a)}});c.extend(c.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:c.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(a){return a+".dialog-overlay"}).join(" "),create:function(a){if(this.instances.length===0){setTimeout(function(){c.ui.dialog.overlay.instances.length&&
c(document).bind(c.ui.dialog.overlay.events,function(d){return c(d.target).zIndex()>=c.ui.dialog.overlay.maxZ})},1);c(document).bind("keydown.dialog-overlay",function(d){if(a.options.closeOnEscape&&d.keyCode&&d.keyCode===c.ui.keyCode.ESCAPE){a.close(d);d.preventDefault()}});c(window).bind("resize.dialog-overlay",c.ui.dialog.overlay.resize)}var b=(this.oldInstances.pop()||c("<div></div>").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),height:this.height()});c.fn.bgiframe&&
b.bgiframe();this.instances.push(b);return b},destroy:function(a){this.oldInstances.push(this.instances.splice(c.inArray(a,this.instances),1)[0]);this.instances.length===0&&c([document,window]).unbind(".dialog-overlay");a.remove();var b=0;c.each(this.instances,function(){b=Math.max(b,this.css("z-index"))});this.maxZ=b},height:function(){var a,b;if(c.browser.msie&&c.browser.version<7){a=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);b=Math.max(document.documentElement.offsetHeight,
document.body.offsetHeight);return a<b?c(window).height()+"px":a+"px"}else return c(document).height()+"px"},width:function(){var a,b;if(c.browser.msie&&c.browser.version<7){a=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth);b=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth);return a<b?c(window).width()+"px":a+"px"}else return c(document).width()+"px"},resize:function(){var a=c([]);c.each(c.ui.dialog.overlay.instances,function(){a=a.add(this)});a.css({width:0,
height:0}).css({width:c.ui.dialog.overlay.width(),height:c.ui.dialog.overlay.height()})}});c.extend(c.ui.dialog.overlay.prototype,{destroy:function(){c.ui.dialog.overlay.destroy(this.$el)}})})(jQuery);
;/*
 * jQuery UI Slider 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Slider
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.mouse.js
 *	jquery.ui.widget.js
 */
(function(d){d.widget("ui.slider",d.ui.mouse,{widgetEventPrefix:"slide",options:{animate:false,distance:0,max:100,min:0,orientation:"horizontal",range:false,step:1,value:0,values:null},_create:function(){var a=this,b=this.options;this._mouseSliding=this._keySliding=false;this._animateOff=true;this._handleIndex=null;this._detectOrientation();this._mouseInit();this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget ui-widget-content ui-corner-all");b.disabled&&this.element.addClass("ui-slider-disabled ui-disabled");
this.range=d([]);if(b.range){if(b.range===true){this.range=d("<div></div>");if(!b.values)b.values=[this._valueMin(),this._valueMin()];if(b.values.length&&b.values.length!==2)b.values=[b.values[0],b.values[0]]}else this.range=d("<div></div>");this.range.appendTo(this.element).addClass("ui-slider-range");if(b.range==="min"||b.range==="max")this.range.addClass("ui-slider-range-"+b.range);this.range.addClass("ui-widget-header")}d(".ui-slider-handle",this.element).length===0&&d("<a href='#'></a>").appendTo(this.element).addClass("ui-slider-handle");
if(b.values&&b.values.length)for(;d(".ui-slider-handle",this.element).length<b.values.length;)d("<a href='#'></a>").appendTo(this.element).addClass("ui-slider-handle");this.handles=d(".ui-slider-handle",this.element).addClass("ui-state-default ui-corner-all");this.handle=this.handles.eq(0);this.handles.add(this.range).filter("a").click(function(c){c.preventDefault()}).hover(function(){b.disabled||d(this).addClass("ui-state-hover")},function(){d(this).removeClass("ui-state-hover")}).focus(function(){if(b.disabled)d(this).blur();
else{d(".ui-slider .ui-state-focus").removeClass("ui-state-focus");d(this).addClass("ui-state-focus")}}).blur(function(){d(this).removeClass("ui-state-focus")});this.handles.each(function(c){d(this).data("index.ui-slider-handle",c)});this.handles.keydown(function(c){var e=true,f=d(this).data("index.ui-slider-handle"),g,h,i;if(!a.options.disabled){switch(c.keyCode){case d.ui.keyCode.HOME:case d.ui.keyCode.END:case d.ui.keyCode.PAGE_UP:case d.ui.keyCode.PAGE_DOWN:case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:e=
false;if(!a._keySliding){a._keySliding=true;d(this).addClass("ui-state-active");g=a._start(c,f);if(g===false)return}break}i=a.options.step;g=a.options.values&&a.options.values.length?(h=a.values(f)):(h=a.value());switch(c.keyCode){case d.ui.keyCode.HOME:h=a._valueMin();break;case d.ui.keyCode.END:h=a._valueMax();break;case d.ui.keyCode.PAGE_UP:h=a._trimAlignValue(g+(a._valueMax()-a._valueMin())/5);break;case d.ui.keyCode.PAGE_DOWN:h=a._trimAlignValue(g-(a._valueMax()-a._valueMin())/5);break;case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:if(g===
a._valueMax())return;h=a._trimAlignValue(g+i);break;case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:if(g===a._valueMin())return;h=a._trimAlignValue(g-i);break}a._slide(c,f,h);return e}}).keyup(function(c){var e=d(this).data("index.ui-slider-handle");if(a._keySliding){a._keySliding=false;a._stop(c,e);a._change(c,e);d(this).removeClass("ui-state-active")}});this._refreshValue();this._animateOff=false},destroy:function(){this.handles.remove();this.range.remove();this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all").removeData("slider").unbind(".slider");
this._mouseDestroy();return this},_mouseCapture:function(a){var b=this.options,c,e,f,g,h,i;if(b.disabled)return false;this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()};this.elementOffset=this.element.offset();c={x:a.pageX,y:a.pageY};e=this._normValueFromMouse(c);f=this._valueMax()-this._valueMin()+1;h=this;this.handles.each(function(j){var k=Math.abs(e-h.values(j));if(f>k){f=k;g=d(this);i=j}});if(b.range===true&&this.values(1)===b.min){i+=1;g=d(this.handles[i])}if(this._start(a,
i)===false)return false;this._mouseSliding=true;h._handleIndex=i;g.addClass("ui-state-active").focus();b=g.offset();this._clickOffset=!d(a.target).parents().andSelf().is(".ui-slider-handle")?{left:0,top:0}:{left:a.pageX-b.left-g.width()/2,top:a.pageY-b.top-g.height()/2-(parseInt(g.css("borderTopWidth"),10)||0)-(parseInt(g.css("borderBottomWidth"),10)||0)+(parseInt(g.css("marginTop"),10)||0)};e=this._normValueFromMouse(c);this._slide(a,i,e);return this._animateOff=true},_mouseStart:function(){return true},
_mouseDrag:function(a){var b=this._normValueFromMouse({x:a.pageX,y:a.pageY});this._slide(a,this._handleIndex,b);return false},_mouseStop:function(a){this.handles.removeClass("ui-state-active");this._mouseSliding=false;this._stop(a,this._handleIndex);this._change(a,this._handleIndex);this._clickOffset=this._handleIndex=null;return this._animateOff=false},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(a){var b;
if(this.orientation==="horizontal"){b=this.elementSize.width;a=a.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)}else{b=this.elementSize.height;a=a.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)}b=a/b;if(b>1)b=1;if(b<0)b=0;if(this.orientation==="vertical")b=1-b;a=this._valueMax()-this._valueMin();return this._trimAlignValue(this._valueMin()+b*a)},_start:function(a,b){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=
this.values(b);c.values=this.values()}return this._trigger("start",a,c)},_slide:function(a,b,c){var e;if(this.options.values&&this.options.values.length){e=this.values(b?0:1);if(this.options.values.length===2&&this.options.range===true&&(b===0&&c>e||b===1&&c<e))c=e;if(c!==this.values(b)){e=this.values();e[b]=c;a=this._trigger("slide",a,{handle:this.handles[b],value:c,values:e});this.values(b?0:1);a!==false&&this.values(b,c,true)}}else if(c!==this.value()){a=this._trigger("slide",a,{handle:this.handles[b],
value:c});a!==false&&this.value(c)}},_stop:function(a,b){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=this.values(b);c.values=this.values()}this._trigger("stop",a,c)},_change:function(a,b){if(!this._keySliding&&!this._mouseSliding){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=this.values(b);c.values=this.values()}this._trigger("change",a,c)}},value:function(a){if(arguments.length){this.options.value=
this._trimAlignValue(a);this._refreshValue();this._change(null,0)}return this._value()},values:function(a,b){var c,e,f;if(arguments.length>1){this.options.values[a]=this._trimAlignValue(b);this._refreshValue();this._change(null,a)}if(arguments.length)if(d.isArray(arguments[0])){c=this.options.values;e=arguments[0];for(f=0;f<c.length;f+=1){c[f]=this._trimAlignValue(e[f]);this._change(null,f)}this._refreshValue()}else return this.options.values&&this.options.values.length?this._values(a):this.value();
else return this._values()},_setOption:function(a,b){var c,e=0;if(d.isArray(this.options.values))e=this.options.values.length;d.Widget.prototype._setOption.apply(this,arguments);switch(a){case "disabled":if(b){this.handles.filter(".ui-state-focus").blur();this.handles.removeClass("ui-state-hover");this.handles.attr("disabled","disabled");this.element.addClass("ui-disabled")}else{this.handles.removeAttr("disabled");this.element.removeClass("ui-disabled")}break;case "orientation":this._detectOrientation();
this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation);this._refreshValue();break;case "value":this._animateOff=true;this._refreshValue();this._change(null,0);this._animateOff=false;break;case "values":this._animateOff=true;this._refreshValue();for(c=0;c<e;c+=1)this._change(null,c);this._animateOff=false;break}},_value:function(){var a=this.options.value;return a=this._trimAlignValue(a)},_values:function(a){var b,c;if(arguments.length){b=this.options.values[a];
return b=this._trimAlignValue(b)}else{b=this.options.values.slice();for(c=0;c<b.length;c+=1)b[c]=this._trimAlignValue(b[c]);return b}},_trimAlignValue:function(a){if(a<this._valueMin())return this._valueMin();if(a>this._valueMax())return this._valueMax();var b=this.options.step>0?this.options.step:1,c=a%b;a=a-c;if(Math.abs(c)*2>=b)a+=c>0?b:-b;return parseFloat(a.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var a=
this.options.range,b=this.options,c=this,e=!this._animateOff?b.animate:false,f,g={},h,i,j,k;if(this.options.values&&this.options.values.length)this.handles.each(function(l){f=(c.values(l)-c._valueMin())/(c._valueMax()-c._valueMin())*100;g[c.orientation==="horizontal"?"left":"bottom"]=f+"%";d(this).stop(1,1)[e?"animate":"css"](g,b.animate);if(c.options.range===true)if(c.orientation==="horizontal"){if(l===0)c.range.stop(1,1)[e?"animate":"css"]({left:f+"%"},b.animate);if(l===1)c.range[e?"animate":"css"]({width:f-
h+"%"},{queue:false,duration:b.animate})}else{if(l===0)c.range.stop(1,1)[e?"animate":"css"]({bottom:f+"%"},b.animate);if(l===1)c.range[e?"animate":"css"]({height:f-h+"%"},{queue:false,duration:b.animate})}h=f});else{i=this.value();j=this._valueMin();k=this._valueMax();f=k!==j?(i-j)/(k-j)*100:0;g[c.orientation==="horizontal"?"left":"bottom"]=f+"%";this.handle.stop(1,1)[e?"animate":"css"](g,b.animate);if(a==="min"&&this.orientation==="horizontal")this.range.stop(1,1)[e?"animate":"css"]({width:f+"%"},
b.animate);if(a==="max"&&this.orientation==="horizontal")this.range[e?"animate":"css"]({width:100-f+"%"},{queue:false,duration:b.animate});if(a==="min"&&this.orientation==="vertical")this.range.stop(1,1)[e?"animate":"css"]({height:f+"%"},b.animate);if(a==="max"&&this.orientation==="vertical")this.range[e?"animate":"css"]({height:100-f+"%"},{queue:false,duration:b.animate})}}});d.extend(d.ui.slider,{version:"1.8.2"})})(jQuery);
;/*
 * jQuery UI Tabs 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Tabs
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 */
(function(d){function s(){return++u}function v(){return++w}var u=0,w=0;d.widget("ui.tabs",{options:{add:null,ajaxOptions:null,cache:false,cookie:null,collapsible:false,disable:null,disabled:[],enable:null,event:"click",fx:null,idPrefix:"ui-tabs-",load:null,panelTemplate:"<div></div>",remove:null,select:null,show:null,spinner:"<em>Loading&#8230;</em>",tabTemplate:'<li><a href="#{href}"><span>#{label}</span></a></li>'},_create:function(){this._tabify(true)},_setOption:function(c,e){if(c=="selected")this.options.collapsible&&
e==this.options.selected||this.select(e);else{this.options[c]=e;this._tabify()}},_tabId:function(c){return c.title&&c.title.replace(/\s/g,"_").replace(/[^A-Za-z0-9\-_:\.]/g,"")||this.options.idPrefix+s()},_sanitizeSelector:function(c){return c.replace(/:/g,"\\:")},_cookie:function(){var c=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+v());return d.cookie.apply(null,[c].concat(d.makeArray(arguments)))},_ui:function(c,e){return{tab:c,panel:e,index:this.anchors.index(c)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var c=
d(this);c.html(c.data("label.tabs")).removeData("label.tabs")})},_tabify:function(c){function e(g,f){g.css({display:""});!d.support.opacity&&f.opacity&&g[0].style.removeAttribute("filter")}this.list=this.element.find("ol,ul").eq(0);this.lis=d("li:has(a[href])",this.list);this.anchors=this.lis.map(function(){return d("a",this)[0]});this.panels=d([]);var a=this,b=this.options,h=/^#.+/;this.anchors.each(function(g,f){var j=d(f).attr("href"),l=j.split("#")[0],p;if(l&&(l===location.toString().split("#")[0]||
(p=d("base")[0])&&l===p.href)){j=f.hash;f.href=j}if(h.test(j))a.panels=a.panels.add(a._sanitizeSelector(j));else if(j!="#"){d.data(f,"href.tabs",j);d.data(f,"load.tabs",j.replace(/#.*$/,""));j=a._tabId(f);f.href="#"+j;f=d("#"+j);if(!f.length){f=d(b.panelTemplate).attr("id",j).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(a.panels[g-1]||a.list);f.data("destroy.tabs",true)}a.panels=a.panels.add(f)}else b.disabled.push(g)});if(c){this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all");
this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.lis.addClass("ui-state-default ui-corner-top");this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom");if(b.selected===undefined){location.hash&&this.anchors.each(function(g,f){if(f.hash==location.hash){b.selected=g;return false}});if(typeof b.selected!="number"&&b.cookie)b.selected=parseInt(a._cookie(),10);if(typeof b.selected!="number"&&this.lis.filter(".ui-tabs-selected").length)b.selected=
this.lis.index(this.lis.filter(".ui-tabs-selected"));b.selected=b.selected||(this.lis.length?0:-1)}else if(b.selected===null)b.selected=-1;b.selected=b.selected>=0&&this.anchors[b.selected]||b.selected<0?b.selected:0;b.disabled=d.unique(b.disabled.concat(d.map(this.lis.filter(".ui-state-disabled"),function(g){return a.lis.index(g)}))).sort();d.inArray(b.selected,b.disabled)!=-1&&b.disabled.splice(d.inArray(b.selected,b.disabled),1);this.panels.addClass("ui-tabs-hide");this.lis.removeClass("ui-tabs-selected ui-state-active");
if(b.selected>=0&&this.anchors.length){this.panels.eq(b.selected).removeClass("ui-tabs-hide");this.lis.eq(b.selected).addClass("ui-tabs-selected ui-state-active");a.element.queue("tabs",function(){a._trigger("show",null,a._ui(a.anchors[b.selected],a.panels[b.selected]))});this.load(b.selected)}d(window).bind("unload",function(){a.lis.add(a.anchors).unbind(".tabs");a.lis=a.anchors=a.panels=null})}else b.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"));this.element[b.collapsible?"addClass":
"removeClass"]("ui-tabs-collapsible");b.cookie&&this._cookie(b.selected,b.cookie);c=0;for(var i;i=this.lis[c];c++)d(i)[d.inArray(c,b.disabled)!=-1&&!d(i).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled");b.cache===false&&this.anchors.removeData("cache.tabs");this.lis.add(this.anchors).unbind(".tabs");if(b.event!="mouseover"){var k=function(g,f){f.is(":not(.ui-state-disabled)")&&f.addClass("ui-state-"+g)},n=function(g,f){f.removeClass("ui-state-"+g)};this.lis.bind("mouseover.tabs",
function(){k("hover",d(this))});this.lis.bind("mouseout.tabs",function(){n("hover",d(this))});this.anchors.bind("focus.tabs",function(){k("focus",d(this).closest("li"))});this.anchors.bind("blur.tabs",function(){n("focus",d(this).closest("li"))})}var m,o;if(b.fx)if(d.isArray(b.fx)){m=b.fx[0];o=b.fx[1]}else m=o=b.fx;var q=o?function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.hide().removeClass("ui-tabs-hide").animate(o,o.duration||"normal",function(){e(f,o);a._trigger("show",
null,a._ui(g,f[0]))})}:function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.removeClass("ui-tabs-hide");a._trigger("show",null,a._ui(g,f[0]))},r=m?function(g,f){f.animate(m,m.duration||"normal",function(){a.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");e(f,m);a.element.dequeue("tabs")})}:function(g,f){a.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");a.element.dequeue("tabs")};this.anchors.bind(b.event+".tabs",
function(){var g=this,f=d(this).closest("li"),j=a.panels.filter(":not(.ui-tabs-hide)"),l=d(a._sanitizeSelector(this.hash));if(f.hasClass("ui-tabs-selected")&&!b.collapsible||f.hasClass("ui-state-disabled")||f.hasClass("ui-state-processing")||a._trigger("select",null,a._ui(this,l[0]))===false){this.blur();return false}b.selected=a.anchors.index(this);a.abort();if(b.collapsible)if(f.hasClass("ui-tabs-selected")){b.selected=-1;b.cookie&&a._cookie(b.selected,b.cookie);a.element.queue("tabs",function(){r(g,
j)}).dequeue("tabs");this.blur();return false}else if(!j.length){b.cookie&&a._cookie(b.selected,b.cookie);a.element.queue("tabs",function(){q(g,l)});a.load(a.anchors.index(this));this.blur();return false}b.cookie&&a._cookie(b.selected,b.cookie);if(l.length){j.length&&a.element.queue("tabs",function(){r(g,j)});a.element.queue("tabs",function(){q(g,l)});a.load(a.anchors.index(this))}else throw"jQuery UI Tabs: Mismatching fragment identifier.";d.browser.msie&&this.blur()});this.anchors.bind("click.tabs",
function(){return false})},destroy:function(){var c=this.options;this.abort();this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs");this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.anchors.each(function(){var e=d.data(this,"href.tabs");if(e)this.href=e;var a=d(this).unbind(".tabs");d.each(["href","load","cache"],function(b,h){a.removeData(h+".tabs")})});this.lis.unbind(".tabs").add(this.panels).each(function(){d.data(this,
"destroy.tabs")?d(this).remove():d(this).removeClass("ui-state-default ui-corner-top ui-tabs-selected ui-state-active ui-state-hover ui-state-focus ui-state-disabled ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide")});c.cookie&&this._cookie(null,c.cookie);return this},add:function(c,e,a){if(a===undefined)a=this.anchors.length;var b=this,h=this.options;e=d(h.tabTemplate.replace(/#\{href\}/g,c).replace(/#\{label\}/g,e));c=!c.indexOf("#")?c.replace("#",""):this._tabId(d("a",e)[0]);e.addClass("ui-state-default ui-corner-top").data("destroy.tabs",
true);var i=d("#"+c);i.length||(i=d(h.panelTemplate).attr("id",c).data("destroy.tabs",true));i.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide");if(a>=this.lis.length){e.appendTo(this.list);i.appendTo(this.list[0].parentNode)}else{e.insertBefore(this.lis[a]);i.insertBefore(this.panels[a])}h.disabled=d.map(h.disabled,function(k){return k>=a?++k:k});this._tabify();if(this.anchors.length==1){h.selected=0;e.addClass("ui-tabs-selected ui-state-active");i.removeClass("ui-tabs-hide");
this.element.queue("tabs",function(){b._trigger("show",null,b._ui(b.anchors[0],b.panels[0]))});this.load(0)}this._trigger("add",null,this._ui(this.anchors[a],this.panels[a]));return this},remove:function(c){var e=this.options,a=this.lis.eq(c).remove(),b=this.panels.eq(c).remove();if(a.hasClass("ui-tabs-selected")&&this.anchors.length>1)this.select(c+(c+1<this.anchors.length?1:-1));e.disabled=d.map(d.grep(e.disabled,function(h){return h!=c}),function(h){return h>=c?--h:h});this._tabify();this._trigger("remove",
null,this._ui(a.find("a")[0],b[0]));return this},enable:function(c){var e=this.options;if(d.inArray(c,e.disabled)!=-1){this.lis.eq(c).removeClass("ui-state-disabled");e.disabled=d.grep(e.disabled,function(a){return a!=c});this._trigger("enable",null,this._ui(this.anchors[c],this.panels[c]));return this}},disable:function(c){var e=this.options;if(c!=e.selected){this.lis.eq(c).addClass("ui-state-disabled");e.disabled.push(c);e.disabled.sort();this._trigger("disable",null,this._ui(this.anchors[c],this.panels[c]))}return this},
select:function(c){if(typeof c=="string")c=this.anchors.index(this.anchors.filter("[href$="+c+"]"));else if(c===null)c=-1;if(c==-1&&this.options.collapsible)c=this.options.selected;this.anchors.eq(c).trigger(this.options.event+".tabs");return this},load:function(c){var e=this,a=this.options,b=this.anchors.eq(c)[0],h=d.data(b,"load.tabs");this.abort();if(!h||this.element.queue("tabs").length!==0&&d.data(b,"cache.tabs"))this.element.dequeue("tabs");else{this.lis.eq(c).addClass("ui-state-processing");
if(a.spinner){var i=d("span",b);i.data("label.tabs",i.html()).html(a.spinner)}this.xhr=d.ajax(d.extend({},a.ajaxOptions,{url:h,success:function(k,n){d(e._sanitizeSelector(b.hash)).html(k);e._cleanup();a.cache&&d.data(b,"cache.tabs",true);e._trigger("load",null,e._ui(e.anchors[c],e.panels[c]));try{a.ajaxOptions.success(k,n)}catch(m){}},error:function(k,n){e._cleanup();e._trigger("load",null,e._ui(e.anchors[c],e.panels[c]));try{a.ajaxOptions.error(k,n,c,b)}catch(m){}}}));e.element.dequeue("tabs");return this}},
abort:function(){this.element.queue([]);this.panels.stop(false,true);this.element.queue("tabs",this.element.queue("tabs").splice(-2,2));if(this.xhr){this.xhr.abort();delete this.xhr}this._cleanup();return this},url:function(c,e){this.anchors.eq(c).removeData("cache.tabs").data("load.tabs",e);return this},length:function(){return this.anchors.length}});d.extend(d.ui.tabs,{version:"1.8.2"});d.extend(d.ui.tabs.prototype,{rotation:null,rotate:function(c,e){var a=this,b=this.options,h=a._rotate||(a._rotate=
function(i){clearTimeout(a.rotation);a.rotation=setTimeout(function(){var k=b.selected;a.select(++k<a.anchors.length?k:0)},c);i&&i.stopPropagation()});e=a._unrotate||(a._unrotate=!e?function(i){i.clientX&&a.rotate(null)}:function(){t=b.selected;h()});if(c){this.element.bind("tabsshow",h);this.anchors.bind(b.event+".tabs",e);h()}else{clearTimeout(a.rotation);this.element.unbind("tabsshow",h);this.anchors.unbind(b.event+".tabs",e);delete this._rotate;delete this._unrotate}return this}})})(jQuery);
;/*
 * jQuery UI Datepicker 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Datepicker
 *
 * Depends:
 *	jquery.ui.core.js
 */
(function(d){function J(){this.debug=false;this._curInst=null;this._keyEvent=false;this._disabledInputs=[];this._inDialog=this._datepickerShowing=false;this._mainDivId="ui-datepicker-div";this._inlineClass="ui-datepicker-inline";this._appendClass="ui-datepicker-append";this._triggerClass="ui-datepicker-trigger";this._dialogClass="ui-datepicker-dialog";this._disableClass="ui-datepicker-disabled";this._unselectableClass="ui-datepicker-unselectable";this._currentClass="ui-datepicker-current-day";this._dayOverClass=
"ui-datepicker-days-cell-over";this.regional=[];this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su",
"Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:false,showMonthAfterYear:false,yearSuffix:""};this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:false,hideIfNoPrevNext:false,navigationAsDateFormat:false,gotoCurrent:false,changeMonth:false,changeYear:false,yearRange:"c-10:c+10",showOtherMonths:false,selectOtherMonths:false,showWeek:false,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",
minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:true,showButtonPanel:false,autoSize:false};d.extend(this._defaults,this.regional[""]);this.dpDiv=d('<div id="'+this._mainDivId+'" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>')}function E(a,b){d.extend(a,
b);for(var c in b)if(b[c]==null||b[c]==undefined)a[c]=b[c];return a}d.extend(d.ui,{datepicker:{version:"1.8.2"}});var y=(new Date).getTime();d.extend(J.prototype,{markerClassName:"hasDatepicker",log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(a){E(this._defaults,a||{});return this},_attachDatepicker:function(a,b){var c=null;for(var e in this._defaults){var f=a.getAttribute("date:"+e);if(f){c=c||{};try{c[e]=eval(f)}catch(h){c[e]=
f}}}e=a.nodeName.toLowerCase();f=e=="div"||e=="span";if(!a.id){this.uuid+=1;a.id="dp"+this.uuid}var i=this._newInst(d(a),f);i.settings=d.extend({},b||{},c||{});if(e=="input")this._connectDatepicker(a,i);else f&&this._inlineDatepicker(a,i)},_newInst:function(a,b){return{id:a[0].id.replace(/([^A-Za-z0-9_])/g,"\\\\$1"),input:a,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:b,dpDiv:!b?this.dpDiv:d('<div class="'+this._inlineClass+' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')}},
_connectDatepicker:function(a,b){var c=d(a);b.append=d([]);b.trigger=d([]);if(!c.hasClass(this.markerClassName)){this._attachments(c,b);c.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});this._autoSize(b);d.data(a,"datepicker",b)}},_attachments:function(a,b){var c=this._get(b,"appendText"),e=this._get(b,"isRTL");b.append&&
b.append.remove();if(c){b.append=d('<span class="'+this._appendClass+'">'+c+"</span>");a[e?"before":"after"](b.append)}a.unbind("focus",this._showDatepicker);b.trigger&&b.trigger.remove();c=this._get(b,"showOn");if(c=="focus"||c=="both")a.focus(this._showDatepicker);if(c=="button"||c=="both"){c=this._get(b,"buttonText");var f=this._get(b,"buttonImage");b.trigger=d(this._get(b,"buttonImageOnly")?d("<img/>").addClass(this._triggerClass).attr({src:f,alt:c,title:c}):d('<button type="button"></button>').addClass(this._triggerClass).html(f==
""?c:d("<img/>").attr({src:f,alt:c,title:c})));a[e?"before":"after"](b.trigger);b.trigger.click(function(){d.datepicker._datepickerShowing&&d.datepicker._lastInput==a[0]?d.datepicker._hideDatepicker():d.datepicker._showDatepicker(a[0]);return false})}},_autoSize:function(a){if(this._get(a,"autoSize")&&!a.inline){var b=new Date(2009,11,20),c=this._get(a,"dateFormat");if(c.match(/[DM]/)){var e=function(f){for(var h=0,i=0,g=0;g<f.length;g++)if(f[g].length>h){h=f[g].length;i=g}return i};b.setMonth(e(this._get(a,
c.match(/MM/)?"monthNames":"monthNamesShort")));b.setDate(e(this._get(a,c.match(/DD/)?"dayNames":"dayNamesShort"))+20-b.getDay())}a.input.attr("size",this._formatDate(a,b).length)}},_inlineDatepicker:function(a,b){var c=d(a);if(!c.hasClass(this.markerClassName)){c.addClass(this.markerClassName).append(b.dpDiv).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});d.data(a,"datepicker",b);this._setDate(b,this._getDefaultDate(b),
true);this._updateDatepicker(b);this._updateAlternate(b)}},_dialogDatepicker:function(a,b,c,e,f){a=this._dialogInst;if(!a){this.uuid+=1;this._dialogInput=d('<input type="text" id="'+("dp"+this.uuid)+'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');this._dialogInput.keydown(this._doKeyDown);d("body").append(this._dialogInput);a=this._dialogInst=this._newInst(this._dialogInput,false);a.settings={};d.data(this._dialogInput[0],"datepicker",a)}E(a.settings,e||{});b=b&&b.constructor==
Date?this._formatDate(a,b):b;this._dialogInput.val(b);this._pos=f?f.length?f:[f.pageX,f.pageY]:null;if(!this._pos)this._pos=[document.documentElement.clientWidth/2-100+(document.documentElement.scrollLeft||document.body.scrollLeft),document.documentElement.clientHeight/2-150+(document.documentElement.scrollTop||document.body.scrollTop)];this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px");a.settings.onSelect=c;this._inDialog=true;this.dpDiv.addClass(this._dialogClass);this._showDatepicker(this._dialogInput[0]);
d.blockUI&&d.blockUI(this.dpDiv);d.data(this._dialogInput[0],"datepicker",a);return this},_destroyDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();d.removeData(a,"datepicker");if(e=="input"){c.append.remove();c.trigger.remove();b.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)}else if(e=="div"||e=="span")b.removeClass(this.markerClassName).empty()}},
_enableDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=false;c.trigger.filter("button").each(function(){this.disabled=false}).end().filter("img").css({opacity:"1.0",cursor:""})}else if(e=="div"||e=="span")b.children("."+this._inlineClass).children().removeClass("ui-state-disabled");this._disabledInputs=d.map(this._disabledInputs,function(f){return f==a?null:f})}},_disableDatepicker:function(a){var b=
d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=true;c.trigger.filter("button").each(function(){this.disabled=true}).end().filter("img").css({opacity:"0.5",cursor:"default"})}else if(e=="div"||e=="span")b.children("."+this._inlineClass).children().addClass("ui-state-disabled");this._disabledInputs=d.map(this._disabledInputs,function(f){return f==a?null:f});this._disabledInputs[this._disabledInputs.length]=a}},_isDisabledDatepicker:function(a){if(!a)return false;
for(var b=0;b<this._disabledInputs.length;b++)if(this._disabledInputs[b]==a)return true;return false},_getInst:function(a){try{return d.data(a,"datepicker")}catch(b){throw"Missing instance data for this datepicker";}},_optionDatepicker:function(a,b,c){var e=this._getInst(a);if(arguments.length==2&&typeof b=="string")return b=="defaults"?d.extend({},d.datepicker._defaults):e?b=="all"?d.extend({},e.settings):this._get(e,b):null;var f=b||{};if(typeof b=="string"){f={};f[b]=c}if(e){this._curInst==e&&
this._hideDatepicker();var h=this._getDateDatepicker(a,true);E(e.settings,f);this._attachments(d(a),e);this._autoSize(e);this._setDateDatepicker(a,h);this._updateDatepicker(e)}},_changeDatepicker:function(a,b,c){this._optionDatepicker(a,b,c)},_refreshDatepicker:function(a){(a=this._getInst(a))&&this._updateDatepicker(a)},_setDateDatepicker:function(a,b){if(a=this._getInst(a)){this._setDate(a,b);this._updateDatepicker(a);this._updateAlternate(a)}},_getDateDatepicker:function(a,b){(a=this._getInst(a))&&
!a.inline&&this._setDateFromField(a,b);return a?this._getDate(a):null},_doKeyDown:function(a){var b=d.datepicker._getInst(a.target),c=true,e=b.dpDiv.is(".ui-datepicker-rtl");b._keyEvent=true;if(d.datepicker._datepickerShowing)switch(a.keyCode){case 9:d.datepicker._hideDatepicker();c=false;break;case 13:c=d("td."+d.datepicker._dayOverClass,b.dpDiv).add(d("td."+d.datepicker._currentClass,b.dpDiv));c[0]?d.datepicker._selectDay(a.target,b.selectedMonth,b.selectedYear,c[0]):d.datepicker._hideDatepicker();
return false;case 27:d.datepicker._hideDatepicker();break;case 33:d.datepicker._adjustDate(a.target,a.ctrlKey?-d.datepicker._get(b,"stepBigMonths"):-d.datepicker._get(b,"stepMonths"),"M");break;case 34:d.datepicker._adjustDate(a.target,a.ctrlKey?+d.datepicker._get(b,"stepBigMonths"):+d.datepicker._get(b,"stepMonths"),"M");break;case 35:if(a.ctrlKey||a.metaKey)d.datepicker._clearDate(a.target);c=a.ctrlKey||a.metaKey;break;case 36:if(a.ctrlKey||a.metaKey)d.datepicker._gotoToday(a.target);c=a.ctrlKey||
a.metaKey;break;case 37:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,e?+1:-1,"D");c=a.ctrlKey||a.metaKey;if(a.originalEvent.altKey)d.datepicker._adjustDate(a.target,a.ctrlKey?-d.datepicker._get(b,"stepBigMonths"):-d.datepicker._get(b,"stepMonths"),"M");break;case 38:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,-7,"D");c=a.ctrlKey||a.metaKey;break;case 39:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,e?-1:+1,"D");c=a.ctrlKey||a.metaKey;if(a.originalEvent.altKey)d.datepicker._adjustDate(a.target,
a.ctrlKey?+d.datepicker._get(b,"stepBigMonths"):+d.datepicker._get(b,"stepMonths"),"M");break;case 40:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,+7,"D");c=a.ctrlKey||a.metaKey;break;default:c=false}else if(a.keyCode==36&&a.ctrlKey)d.datepicker._showDatepicker(this);else c=false;if(c){a.preventDefault();a.stopPropagation()}},_doKeyPress:function(a){var b=d.datepicker._getInst(a.target);if(d.datepicker._get(b,"constrainInput")){b=d.datepicker._possibleChars(d.datepicker._get(b,"dateFormat"));
var c=String.fromCharCode(a.charCode==undefined?a.keyCode:a.charCode);return a.ctrlKey||c<" "||!b||b.indexOf(c)>-1}},_doKeyUp:function(a){a=d.datepicker._getInst(a.target);if(a.input.val()!=a.lastVal)try{if(d.datepicker.parseDate(d.datepicker._get(a,"dateFormat"),a.input?a.input.val():null,d.datepicker._getFormatConfig(a))){d.datepicker._setDateFromField(a);d.datepicker._updateAlternate(a);d.datepicker._updateDatepicker(a)}}catch(b){d.datepicker.log(b)}return true},_showDatepicker:function(a){a=a.target||
a;if(a.nodeName.toLowerCase()!="input")a=d("input",a.parentNode)[0];if(!(d.datepicker._isDisabledDatepicker(a)||d.datepicker._lastInput==a)){var b=d.datepicker._getInst(a);d.datepicker._curInst&&d.datepicker._curInst!=b&&d.datepicker._curInst.dpDiv.stop(true,true);var c=d.datepicker._get(b,"beforeShow");E(b.settings,c?c.apply(a,[a,b]):{});b.lastVal=null;d.datepicker._lastInput=a;d.datepicker._setDateFromField(b);if(d.datepicker._inDialog)a.value="";if(!d.datepicker._pos){d.datepicker._pos=d.datepicker._findPos(a);
d.datepicker._pos[1]+=a.offsetHeight}var e=false;d(a).parents().each(function(){e|=d(this).css("position")=="fixed";return!e});if(e&&d.browser.opera){d.datepicker._pos[0]-=document.documentElement.scrollLeft;d.datepicker._pos[1]-=document.documentElement.scrollTop}c={left:d.datepicker._pos[0],top:d.datepicker._pos[1]};d.datepicker._pos=null;b.dpDiv.css({position:"absolute",display:"block",top:"-1000px"});d.datepicker._updateDatepicker(b);c=d.datepicker._checkOffset(b,c,e);b.dpDiv.css({position:d.datepicker._inDialog&&
d.blockUI?"static":e?"fixed":"absolute",display:"none",left:c.left+"px",top:c.top+"px"});if(!b.inline){c=d.datepicker._get(b,"showAnim");var f=d.datepicker._get(b,"duration"),h=function(){d.datepicker._datepickerShowing=true;var i=d.datepicker._getBorders(b.dpDiv);b.dpDiv.find("iframe.ui-datepicker-cover").css({left:-i[0],top:-i[1],width:b.dpDiv.outerWidth(),height:b.dpDiv.outerHeight()})};b.dpDiv.zIndex(d(a).zIndex()+1);d.effects&&d.effects[c]?b.dpDiv.show(c,d.datepicker._get(b,"showOptions"),f,
h):b.dpDiv[c||"show"](c?f:null,h);if(!c||!f)h();b.input.is(":visible")&&!b.input.is(":disabled")&&b.input.focus();d.datepicker._curInst=b}}},_updateDatepicker:function(a){var b=this,c=d.datepicker._getBorders(a.dpDiv);a.dpDiv.empty().append(this._generateHTML(a)).find("iframe.ui-datepicker-cover").css({left:-c[0],top:-c[1],width:a.dpDiv.outerWidth(),height:a.dpDiv.outerHeight()}).end().find("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a").bind("mouseout",function(){d(this).removeClass("ui-state-hover");
this.className.indexOf("ui-datepicker-prev")!=-1&&d(this).removeClass("ui-datepicker-prev-hover");this.className.indexOf("ui-datepicker-next")!=-1&&d(this).removeClass("ui-datepicker-next-hover")}).bind("mouseover",function(){if(!b._isDisabledDatepicker(a.inline?a.dpDiv.parent()[0]:a.input[0])){d(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");d(this).addClass("ui-state-hover");this.className.indexOf("ui-datepicker-prev")!=-1&&d(this).addClass("ui-datepicker-prev-hover");
this.className.indexOf("ui-datepicker-next")!=-1&&d(this).addClass("ui-datepicker-next-hover")}}).end().find("."+this._dayOverClass+" a").trigger("mouseover").end();c=this._getNumberOfMonths(a);var e=c[1];e>1?a.dpDiv.addClass("ui-datepicker-multi-"+e).css("width",17*e+"em"):a.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");a.dpDiv[(c[0]!=1||c[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi");a.dpDiv[(this._get(a,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl");
a==d.datepicker._curInst&&d.datepicker._datepickerShowing&&a.input&&a.input.is(":visible")&&!a.input.is(":disabled")&&a.input.focus()},_getBorders:function(a){var b=function(c){return{thin:1,medium:2,thick:3}[c]||c};return[parseFloat(b(a.css("border-left-width"))),parseFloat(b(a.css("border-top-width")))]},_checkOffset:function(a,b,c){var e=a.dpDiv.outerWidth(),f=a.dpDiv.outerHeight(),h=a.input?a.input.outerWidth():0,i=a.input?a.input.outerHeight():0,g=document.documentElement.clientWidth+d(document).scrollLeft(),
k=document.documentElement.clientHeight+d(document).scrollTop();b.left-=this._get(a,"isRTL")?e-h:0;b.left-=c&&b.left==a.input.offset().left?d(document).scrollLeft():0;b.top-=c&&b.top==a.input.offset().top+i?d(document).scrollTop():0;b.left-=Math.min(b.left,b.left+e>g&&g>e?Math.abs(b.left+e-g):0);b.top-=Math.min(b.top,b.top+f>k&&k>f?Math.abs(f+i):0);return b},_findPos:function(a){for(var b=this._get(this._getInst(a),"isRTL");a&&(a.type=="hidden"||a.nodeType!=1);)a=a[b?"previousSibling":"nextSibling"];
a=d(a).offset();return[a.left,a.top]},_hideDatepicker:function(a){var b=this._curInst;if(!(!b||a&&b!=d.data(a,"datepicker")))if(this._datepickerShowing){a=this._get(b,"showAnim");var c=this._get(b,"duration"),e=function(){d.datepicker._tidyDialog(b);this._curInst=null};d.effects&&d.effects[a]?b.dpDiv.hide(a,d.datepicker._get(b,"showOptions"),c,e):b.dpDiv[a=="slideDown"?"slideUp":a=="fadeIn"?"fadeOut":"hide"](a?c:null,e);a||e();if(a=this._get(b,"onClose"))a.apply(b.input?b.input[0]:null,[b.input?b.input.val():
"",b]);this._datepickerShowing=false;this._lastInput=null;if(this._inDialog){this._dialogInput.css({position:"absolute",left:"0",top:"-100px"});if(d.blockUI){d.unblockUI();d("body").append(this.dpDiv)}}this._inDialog=false}},_tidyDialog:function(a){a.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(a){if(d.datepicker._curInst){a=d(a.target);a[0].id!=d.datepicker._mainDivId&&a.parents("#"+d.datepicker._mainDivId).length==0&&!a.hasClass(d.datepicker.markerClassName)&&
!a.hasClass(d.datepicker._triggerClass)&&d.datepicker._datepickerShowing&&!(d.datepicker._inDialog&&d.blockUI)&&d.datepicker._hideDatepicker()}},_adjustDate:function(a,b,c){a=d(a);var e=this._getInst(a[0]);if(!this._isDisabledDatepicker(a[0])){this._adjustInstDate(e,b+(c=="M"?this._get(e,"showCurrentAtPos"):0),c);this._updateDatepicker(e)}},_gotoToday:function(a){a=d(a);var b=this._getInst(a[0]);if(this._get(b,"gotoCurrent")&&b.currentDay){b.selectedDay=b.currentDay;b.drawMonth=b.selectedMonth=b.currentMonth;
b.drawYear=b.selectedYear=b.currentYear}else{var c=new Date;b.selectedDay=c.getDate();b.drawMonth=b.selectedMonth=c.getMonth();b.drawYear=b.selectedYear=c.getFullYear()}this._notifyChange(b);this._adjustDate(a)},_selectMonthYear:function(a,b,c){a=d(a);var e=this._getInst(a[0]);e._selectingMonthYear=false;e["selected"+(c=="M"?"Month":"Year")]=e["draw"+(c=="M"?"Month":"Year")]=parseInt(b.options[b.selectedIndex].value,10);this._notifyChange(e);this._adjustDate(a)},_clickMonthYear:function(a){a=this._getInst(d(a)[0]);
a.input&&a._selectingMonthYear&&!d.browser.msie&&a.input.focus();a._selectingMonthYear=!a._selectingMonthYear},_selectDay:function(a,b,c,e){var f=d(a);if(!(d(e).hasClass(this._unselectableClass)||this._isDisabledDatepicker(f[0]))){f=this._getInst(f[0]);f.selectedDay=f.currentDay=d("a",e).html();f.selectedMonth=f.currentMonth=b;f.selectedYear=f.currentYear=c;this._selectDate(a,this._formatDate(f,f.currentDay,f.currentMonth,f.currentYear))}},_clearDate:function(a){a=d(a);this._getInst(a[0]);this._selectDate(a,
"")},_selectDate:function(a,b){a=this._getInst(d(a)[0]);b=b!=null?b:this._formatDate(a);a.input&&a.input.val(b);this._updateAlternate(a);var c=this._get(a,"onSelect");if(c)c.apply(a.input?a.input[0]:null,[b,a]);else a.input&&a.input.trigger("change");if(a.inline)this._updateDatepicker(a);else{this._hideDatepicker();this._lastInput=a.input[0];typeof a.input[0]!="object"&&a.input.focus();this._lastInput=null}},_updateAlternate:function(a){var b=this._get(a,"altField");if(b){var c=this._get(a,"altFormat")||
this._get(a,"dateFormat"),e=this._getDate(a),f=this.formatDate(c,e,this._getFormatConfig(a));d(b).each(function(){d(this).val(f)})}},noWeekends:function(a){a=a.getDay();return[a>0&&a<6,""]},iso8601Week:function(a){a=new Date(a.getTime());a.setDate(a.getDate()+4-(a.getDay()||7));var b=a.getTime();a.setMonth(0);a.setDate(1);return Math.floor(Math.round((b-a)/864E5)/7)+1},parseDate:function(a,b,c){if(a==null||b==null)throw"Invalid arguments";b=typeof b=="object"?b.toString():b+"";if(b=="")return null;
for(var e=(c?c.shortYearCutoff:null)||this._defaults.shortYearCutoff,f=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,h=(c?c.dayNames:null)||this._defaults.dayNames,i=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,g=(c?c.monthNames:null)||this._defaults.monthNames,k=c=-1,l=-1,u=-1,j=false,o=function(p){(p=z+1<a.length&&a.charAt(z+1)==p)&&z++;return p},m=function(p){o(p);p=new RegExp("^\\d{1,"+(p=="@"?14:p=="!"?20:p=="y"?4:p=="o"?3:2)+"}");p=b.substring(s).match(p);if(!p)throw"Missing number at position "+
s;s+=p[0].length;return parseInt(p[0],10)},n=function(p,w,G){p=o(p)?G:w;for(w=0;w<p.length;w++)if(b.substr(s,p[w].length)==p[w]){s+=p[w].length;return w+1}throw"Unknown name at position "+s;},r=function(){if(b.charAt(s)!=a.charAt(z))throw"Unexpected literal at position "+s;s++},s=0,z=0;z<a.length;z++)if(j)if(a.charAt(z)=="'"&&!o("'"))j=false;else r();else switch(a.charAt(z)){case "d":l=m("d");break;case "D":n("D",f,h);break;case "o":u=m("o");break;case "m":k=m("m");break;case "M":k=n("M",i,g);break;
case "y":c=m("y");break;case "@":var v=new Date(m("@"));c=v.getFullYear();k=v.getMonth()+1;l=v.getDate();break;case "!":v=new Date((m("!")-this._ticksTo1970)/1E4);c=v.getFullYear();k=v.getMonth()+1;l=v.getDate();break;case "'":if(o("'"))r();else j=true;break;default:r()}if(c==-1)c=(new Date).getFullYear();else if(c<100)c+=(new Date).getFullYear()-(new Date).getFullYear()%100+(c<=e?0:-100);if(u>-1){k=1;l=u;do{e=this._getDaysInMonth(c,k-1);if(l<=e)break;k++;l-=e}while(1)}v=this._daylightSavingAdjust(new Date(c,
k-1,l));if(v.getFullYear()!=c||v.getMonth()+1!=k||v.getDate()!=l)throw"Invalid date";return v},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1E7,formatDate:function(a,b,c){if(!b)return"";var e=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,f=(c?
c.dayNames:null)||this._defaults.dayNames,h=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort;c=(c?c.monthNames:null)||this._defaults.monthNames;var i=function(o){(o=j+1<a.length&&a.charAt(j+1)==o)&&j++;return o},g=function(o,m,n){m=""+m;if(i(o))for(;m.length<n;)m="0"+m;return m},k=function(o,m,n,r){return i(o)?r[m]:n[m]},l="",u=false;if(b)for(var j=0;j<a.length;j++)if(u)if(a.charAt(j)=="'"&&!i("'"))u=false;else l+=a.charAt(j);else switch(a.charAt(j)){case "d":l+=g("d",b.getDate(),2);break;
case "D":l+=k("D",b.getDay(),e,f);break;case "o":l+=g("o",(b.getTime()-(new Date(b.getFullYear(),0,0)).getTime())/864E5,3);break;case "m":l+=g("m",b.getMonth()+1,2);break;case "M":l+=k("M",b.getMonth(),h,c);break;case "y":l+=i("y")?b.getFullYear():(b.getYear()%100<10?"0":"")+b.getYear()%100;break;case "@":l+=b.getTime();break;case "!":l+=b.getTime()*1E4+this._ticksTo1970;break;case "'":if(i("'"))l+="'";else u=true;break;default:l+=a.charAt(j)}return l},_possibleChars:function(a){for(var b="",c=false,
e=function(h){(h=f+1<a.length&&a.charAt(f+1)==h)&&f++;return h},f=0;f<a.length;f++)if(c)if(a.charAt(f)=="'"&&!e("'"))c=false;else b+=a.charAt(f);else switch(a.charAt(f)){case "d":case "m":case "y":case "@":b+="0123456789";break;case "D":case "M":return null;case "'":if(e("'"))b+="'";else c=true;break;default:b+=a.charAt(f)}return b},_get:function(a,b){return a.settings[b]!==undefined?a.settings[b]:this._defaults[b]},_setDateFromField:function(a,b){if(a.input.val()!=a.lastVal){var c=this._get(a,"dateFormat"),
e=a.lastVal=a.input?a.input.val():null,f,h;f=h=this._getDefaultDate(a);var i=this._getFormatConfig(a);try{f=this.parseDate(c,e,i)||h}catch(g){this.log(g);e=b?"":e}a.selectedDay=f.getDate();a.drawMonth=a.selectedMonth=f.getMonth();a.drawYear=a.selectedYear=f.getFullYear();a.currentDay=e?f.getDate():0;a.currentMonth=e?f.getMonth():0;a.currentYear=e?f.getFullYear():0;this._adjustInstDate(a)}},_getDefaultDate:function(a){return this._restrictMinMax(a,this._determineDate(a,this._get(a,"defaultDate"),new Date))},
_determineDate:function(a,b,c){var e=function(h){var i=new Date;i.setDate(i.getDate()+h);return i},f=function(h){try{return d.datepicker.parseDate(d.datepicker._get(a,"dateFormat"),h,d.datepicker._getFormatConfig(a))}catch(i){}var g=(h.toLowerCase().match(/^c/)?d.datepicker._getDate(a):null)||new Date,k=g.getFullYear(),l=g.getMonth();g=g.getDate();for(var u=/([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,j=u.exec(h);j;){switch(j[2]||"d"){case "d":case "D":g+=parseInt(j[1],10);break;case "w":case "W":g+=parseInt(j[1],
10)*7;break;case "m":case "M":l+=parseInt(j[1],10);g=Math.min(g,d.datepicker._getDaysInMonth(k,l));break;case "y":case "Y":k+=parseInt(j[1],10);g=Math.min(g,d.datepicker._getDaysInMonth(k,l));break}j=u.exec(h)}return new Date(k,l,g)};if(b=(b=b==null?c:typeof b=="string"?f(b):typeof b=="number"?isNaN(b)?c:e(b):b)&&b.toString()=="Invalid Date"?c:b){b.setHours(0);b.setMinutes(0);b.setSeconds(0);b.setMilliseconds(0)}return this._daylightSavingAdjust(b)},_daylightSavingAdjust:function(a){if(!a)return null;
a.setHours(a.getHours()>12?a.getHours()+2:0);return a},_setDate:function(a,b,c){var e=!b,f=a.selectedMonth,h=a.selectedYear;b=this._restrictMinMax(a,this._determineDate(a,b,new Date));a.selectedDay=a.currentDay=b.getDate();a.drawMonth=a.selectedMonth=a.currentMonth=b.getMonth();a.drawYear=a.selectedYear=a.currentYear=b.getFullYear();if((f!=a.selectedMonth||h!=a.selectedYear)&&!c)this._notifyChange(a);this._adjustInstDate(a);if(a.input)a.input.val(e?"":this._formatDate(a))},_getDate:function(a){return!a.currentYear||
a.input&&a.input.val()==""?null:this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay))},_generateHTML:function(a){var b=new Date;b=this._daylightSavingAdjust(new Date(b.getFullYear(),b.getMonth(),b.getDate()));var c=this._get(a,"isRTL"),e=this._get(a,"showButtonPanel"),f=this._get(a,"hideIfNoPrevNext"),h=this._get(a,"navigationAsDateFormat"),i=this._getNumberOfMonths(a),g=this._get(a,"showCurrentAtPos"),k=this._get(a,"stepMonths"),l=i[0]!=1||i[1]!=1,u=this._daylightSavingAdjust(!a.currentDay?
new Date(9999,9,9):new Date(a.currentYear,a.currentMonth,a.currentDay)),j=this._getMinMaxDate(a,"min"),o=this._getMinMaxDate(a,"max");g=a.drawMonth-g;var m=a.drawYear;if(g<0){g+=12;m--}if(o){var n=this._daylightSavingAdjust(new Date(o.getFullYear(),o.getMonth()-i[0]*i[1]+1,o.getDate()));for(n=j&&n<j?j:n;this._daylightSavingAdjust(new Date(m,g,1))>n;){g--;if(g<0){g=11;m--}}}a.drawMonth=g;a.drawYear=m;n=this._get(a,"prevText");n=!h?n:this.formatDate(n,this._daylightSavingAdjust(new Date(m,g-k,1)),this._getFormatConfig(a));
n=this._canAdjustMonth(a,-1,m,g)?'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_'+y+".datepicker._adjustDate('#"+a.id+"', -"+k+", 'M');\" title=\""+n+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"e":"w")+'">'+n+"</span></a>":f?"":'<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+n+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"e":"w")+'">'+n+"</span></a>";var r=this._get(a,"nextText");r=!h?r:this.formatDate(r,this._daylightSavingAdjust(new Date(m,
g+k,1)),this._getFormatConfig(a));f=this._canAdjustMonth(a,+1,m,g)?'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_'+y+".datepicker._adjustDate('#"+a.id+"', +"+k+", 'M');\" title=\""+r+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"w":"e")+'">'+r+"</span></a>":f?"":'<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+r+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"w":"e")+'">'+r+"</span></a>";k=this._get(a,"currentText");r=this._get(a,"gotoCurrent")&&
a.currentDay?u:b;k=!h?k:this.formatDate(k,r,this._getFormatConfig(a));h=!a.inline?'<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_'+y+'.datepicker._hideDatepicker();">'+this._get(a,"closeText")+"</button>":"";e=e?'<div class="ui-datepicker-buttonpane ui-widget-content">'+(c?h:"")+(this._isInRange(a,r)?'<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_'+
y+".datepicker._gotoToday('#"+a.id+"');\">"+k+"</button>":"")+(c?"":h)+"</div>":"";h=parseInt(this._get(a,"firstDay"),10);h=isNaN(h)?0:h;k=this._get(a,"showWeek");r=this._get(a,"dayNames");this._get(a,"dayNamesShort");var s=this._get(a,"dayNamesMin"),z=this._get(a,"monthNames"),v=this._get(a,"monthNamesShort"),p=this._get(a,"beforeShowDay"),w=this._get(a,"showOtherMonths"),G=this._get(a,"selectOtherMonths");this._get(a,"calculateWeek");for(var K=this._getDefaultDate(a),H="",C=0;C<i[0];C++){for(var L=
"",D=0;D<i[1];D++){var M=this._daylightSavingAdjust(new Date(m,g,a.selectedDay)),t=" ui-corner-all",x="";if(l){x+='<div class="ui-datepicker-group';if(i[1]>1)switch(D){case 0:x+=" ui-datepicker-group-first";t=" ui-corner-"+(c?"right":"left");break;case i[1]-1:x+=" ui-datepicker-group-last";t=" ui-corner-"+(c?"left":"right");break;default:x+=" ui-datepicker-group-middle";t="";break}x+='">'}x+='<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix'+t+'">'+(/all|left/.test(t)&&C==0?c?
f:n:"")+(/all|right/.test(t)&&C==0?c?n:f:"")+this._generateMonthYearHeader(a,g,m,j,o,C>0||D>0,z,v)+'</div><table class="ui-datepicker-calendar"><thead><tr>';var A=k?'<th class="ui-datepicker-week-col">'+this._get(a,"weekHeader")+"</th>":"";for(t=0;t<7;t++){var q=(t+h)%7;A+="<th"+((t+h+6)%7>=5?' class="ui-datepicker-week-end"':"")+'><span title="'+r[q]+'">'+s[q]+"</span></th>"}x+=A+"</tr></thead><tbody>";A=this._getDaysInMonth(m,g);if(m==a.selectedYear&&g==a.selectedMonth)a.selectedDay=Math.min(a.selectedDay,
A);t=(this._getFirstDayOfMonth(m,g)-h+7)%7;A=l?6:Math.ceil((t+A)/7);q=this._daylightSavingAdjust(new Date(m,g,1-t));for(var N=0;N<A;N++){x+="<tr>";var O=!k?"":'<td class="ui-datepicker-week-col">'+this._get(a,"calculateWeek")(q)+"</td>";for(t=0;t<7;t++){var F=p?p.apply(a.input?a.input[0]:null,[q]):[true,""],B=q.getMonth()!=g,I=B&&!G||!F[0]||j&&q<j||o&&q>o;O+='<td class="'+((t+h+6)%7>=5?" ui-datepicker-week-end":"")+(B?" ui-datepicker-other-month":"")+(q.getTime()==M.getTime()&&g==a.selectedMonth&&
a._keyEvent||K.getTime()==q.getTime()&&K.getTime()==M.getTime()?" "+this._dayOverClass:"")+(I?" "+this._unselectableClass+" ui-state-disabled":"")+(B&&!w?"":" "+F[1]+(q.getTime()==u.getTime()?" "+this._currentClass:"")+(q.getTime()==b.getTime()?" ui-datepicker-today":""))+'"'+((!B||w)&&F[2]?' title="'+F[2]+'"':"")+(I?"":' onclick="DP_jQuery_'+y+".datepicker._selectDay('#"+a.id+"',"+q.getMonth()+","+q.getFullYear()+', this);return false;"')+">"+(B&&!w?"&#xa0;":I?'<span class="ui-state-default">'+q.getDate()+
"</span>":'<a class="ui-state-default'+(q.getTime()==b.getTime()?" ui-state-highlight":"")+(q.getTime()==u.getTime()?" ui-state-active":"")+(B?" ui-priority-secondary":"")+'" href="#">'+q.getDate()+"</a>")+"</td>";q.setDate(q.getDate()+1);q=this._daylightSavingAdjust(q)}x+=O+"</tr>"}g++;if(g>11){g=0;m++}x+="</tbody></table>"+(l?"</div>"+(i[0]>0&&D==i[1]-1?'<div class="ui-datepicker-row-break"></div>':""):"");L+=x}H+=L}H+=e+(d.browser.msie&&parseInt(d.browser.version,10)<7&&!a.inline?'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>':
"");a._keyEvent=false;return H},_generateMonthYearHeader:function(a,b,c,e,f,h,i,g){var k=this._get(a,"changeMonth"),l=this._get(a,"changeYear"),u=this._get(a,"showMonthAfterYear"),j='<div class="ui-datepicker-title">',o="";if(h||!k)o+='<span class="ui-datepicker-month">'+i[b]+"</span>";else{i=e&&e.getFullYear()==c;var m=f&&f.getFullYear()==c;o+='<select class="ui-datepicker-month" onchange="DP_jQuery_'+y+".datepicker._selectMonthYear('#"+a.id+"', this, 'M');\" onclick=\"DP_jQuery_"+y+".datepicker._clickMonthYear('#"+
a.id+"');\">";for(var n=0;n<12;n++)if((!i||n>=e.getMonth())&&(!m||n<=f.getMonth()))o+='<option value="'+n+'"'+(n==b?' selected="selected"':"")+">"+g[n]+"</option>";o+="</select>"}u||(j+=o+(h||!(k&&l)?"&#xa0;":""));if(h||!l)j+='<span class="ui-datepicker-year">'+c+"</span>";else{g=this._get(a,"yearRange").split(":");var r=(new Date).getFullYear();i=function(s){s=s.match(/c[+-].*/)?c+parseInt(s.substring(1),10):s.match(/[+-].*/)?r+parseInt(s,10):parseInt(s,10);return isNaN(s)?r:s};b=i(g[0]);g=Math.max(b,
i(g[1]||""));b=e?Math.max(b,e.getFullYear()):b;g=f?Math.min(g,f.getFullYear()):g;for(j+='<select class="ui-datepicker-year" onchange="DP_jQuery_'+y+".datepicker._selectMonthYear('#"+a.id+"', this, 'Y');\" onclick=\"DP_jQuery_"+y+".datepicker._clickMonthYear('#"+a.id+"');\">";b<=g;b++)j+='<option value="'+b+'"'+(b==c?' selected="selected"':"")+">"+b+"</option>";j+="</select>"}j+=this._get(a,"yearSuffix");if(u)j+=(h||!(k&&l)?"&#xa0;":"")+o;j+="</div>";return j},_adjustInstDate:function(a,b,c){var e=
a.drawYear+(c=="Y"?b:0),f=a.drawMonth+(c=="M"?b:0);b=Math.min(a.selectedDay,this._getDaysInMonth(e,f))+(c=="D"?b:0);e=this._restrictMinMax(a,this._daylightSavingAdjust(new Date(e,f,b)));a.selectedDay=e.getDate();a.drawMonth=a.selectedMonth=e.getMonth();a.drawYear=a.selectedYear=e.getFullYear();if(c=="M"||c=="Y")this._notifyChange(a)},_restrictMinMax:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");b=c&&b<c?c:b;return b=a&&b>a?a:b},_notifyChange:function(a){var b=this._get(a,
"onChangeMonthYear");if(b)b.apply(a.input?a.input[0]:null,[a.selectedYear,a.selectedMonth+1,a])},_getNumberOfMonths:function(a){a=this._get(a,"numberOfMonths");return a==null?[1,1]:typeof a=="number"?[1,a]:a},_getMinMaxDate:function(a,b){return this._determineDate(a,this._get(a,b+"Date"),null)},_getDaysInMonth:function(a,b){return 32-(new Date(a,b,32)).getDate()},_getFirstDayOfMonth:function(a,b){return(new Date(a,b,1)).getDay()},_canAdjustMonth:function(a,b,c,e){var f=this._getNumberOfMonths(a);
c=this._daylightSavingAdjust(new Date(c,e+(b<0?b:f[0]*f[1]),1));b<0&&c.setDate(this._getDaysInMonth(c.getFullYear(),c.getMonth()));return this._isInRange(a,c)},_isInRange:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");return(!c||b.getTime()>=c.getTime())&&(!a||b.getTime()<=a.getTime())},_getFormatConfig:function(a){var b=this._get(a,"shortYearCutoff");b=typeof b!="string"?b:(new Date).getFullYear()%100+parseInt(b,10);return{shortYearCutoff:b,dayNamesShort:this._get(a,
"dayNamesShort"),dayNames:this._get(a,"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,b,c,e){if(!b){a.currentDay=a.selectedDay;a.currentMonth=a.selectedMonth;a.currentYear=a.selectedYear}b=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(e,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),b,this._getFormatConfig(a))}});d.fn.datepicker=
function(a){if(!d.datepicker.initialized){d(document).mousedown(d.datepicker._checkExternalClick).find("body").append(d.datepicker.dpDiv);d.datepicker.initialized=true}var b=Array.prototype.slice.call(arguments,1);if(typeof a=="string"&&(a=="isDisabled"||a=="getDate"||a=="widget"))return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));if(a=="option"&&arguments.length==2&&typeof arguments[1]=="string")return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));
return this.each(function(){typeof a=="string"?d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this].concat(b)):d.datepicker._attachDatepicker(this,a)})};d.datepicker=new J;d.datepicker.initialized=false;d.datepicker.uuid=(new Date).getTime();d.datepicker.version="1.8.2";window["DP_jQuery_"+y]=d})(jQuery);
;/*
 * jQuery UI Progressbar 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Progressbar
 *
 * Depends:
 *   jquery.ui.core.js
 *   jquery.ui.widget.js
 */
(function(b){b.widget("ui.progressbar",{options:{value:0},_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this._valueMin(),"aria-valuemax":this._valueMax(),"aria-valuenow":this._value()});this.valueDiv=b("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element);this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow");
this.valueDiv.remove();b.Widget.prototype.destroy.apply(this,arguments)},value:function(a){if(a===undefined)return this._value();this._setOption("value",a);return this},_setOption:function(a,c){switch(a){case "value":this.options.value=c;this._refreshValue();this._trigger("change");break}b.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;if(typeof a!=="number")a=0;if(a<this._valueMin())a=this._valueMin();if(a>this._valueMax())a=this._valueMax();return a},
_valueMin:function(){return 0},_valueMax:function(){return 100},_refreshValue:function(){var a=this.value();this.valueDiv[a===this._valueMax()?"addClass":"removeClass"]("ui-corner-right").width(a+"%");this.element.attr("aria-valuenow",a)}});b.extend(b.ui.progressbar,{version:"1.8.2"})})(jQuery);
;/*
 * jQuery UI Effects 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/
 */
jQuery.effects||function(f){function k(c){var a;if(c&&c.constructor==Array&&c.length==3)return c;if(a=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(c))return[parseInt(a[1],10),parseInt(a[2],10),parseInt(a[3],10)];if(a=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(c))return[parseFloat(a[1])*2.55,parseFloat(a[2])*2.55,parseFloat(a[3])*2.55];if(a=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(c))return[parseInt(a[1],
16),parseInt(a[2],16),parseInt(a[3],16)];if(a=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(c))return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16)];if(/rgba\(0, 0, 0, 0\)/.exec(c))return l.transparent;return l[f.trim(c).toLowerCase()]}function q(c,a){var b;do{b=f.curCSS(c,a);if(b!=""&&b!="transparent"||f.nodeName(c,"body"))break;a="backgroundColor"}while(c=c.parentNode);return k(b)}function m(){var c=document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle,
a={},b,d;if(c&&c.length&&c[0]&&c[c[0]])for(var e=c.length;e--;){b=c[e];if(typeof c[b]=="string"){d=b.replace(/\-(\w)/g,function(g,h){return h.toUpperCase()});a[d]=c[b]}}else for(b in c)if(typeof c[b]==="string")a[b]=c[b];return a}function n(c){var a,b;for(a in c){b=c[a];if(b==null||f.isFunction(b)||a in r||/scrollbar/.test(a)||!/color/i.test(a)&&isNaN(parseFloat(b)))delete c[a]}return c}function s(c,a){var b={_:0},d;for(d in a)if(c[d]!=a[d])b[d]=a[d];return b}function j(c,a,b,d){if(typeof c=="object"){d=
a;b=null;a=c;c=a.effect}if(f.isFunction(a)){d=a;b=null;a={}}if(f.isFunction(b)){d=b;b=null}if(typeof a=="number"||f.fx.speeds[a]){d=b;b=a;a={}}a=a||{};b=b||a.duration;b=f.fx.off?0:typeof b=="number"?b:f.fx.speeds[b]||f.fx.speeds._default;d=d||a.complete;return[c,a,b,d]}f.effects={};f.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","color","outlineColor"],function(c,a){f.fx.step[a]=function(b){if(!b.colorInit){b.start=q(b.elem,a);b.end=k(b.end);b.colorInit=
true}b.elem.style[a]="rgb("+Math.max(Math.min(parseInt(b.pos*(b.end[0]-b.start[0])+b.start[0],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[1]-b.start[1])+b.start[1],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[2]-b.start[2])+b.start[2],10),255),0)+")"}});var l={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,
183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,
165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]},o=["add","remove","toggle"],r={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};f.effects.animateClass=function(c,a,b,d){if(f.isFunction(b)){d=b;b=null}return this.each(function(){var e=f(this),g=e.attr("style")||" ",h=n(m.call(this)),p,t=e.attr("className");f.each(o,function(u,
i){c[i]&&e[i+"Class"](c[i])});p=n(m.call(this));e.attr("className",t);e.animate(s(h,p),a,b,function(){f.each(o,function(u,i){c[i]&&e[i+"Class"](c[i])});if(typeof e.attr("style")=="object"){e.attr("style").cssText="";e.attr("style").cssText=g}else e.attr("style",g);d&&d.apply(this,arguments)})})};f.fn.extend({_addClass:f.fn.addClass,addClass:function(c,a,b,d){return a?f.effects.animateClass.apply(this,[{add:c},a,b,d]):this._addClass(c)},_removeClass:f.fn.removeClass,removeClass:function(c,a,b,d){return a?
f.effects.animateClass.apply(this,[{remove:c},a,b,d]):this._removeClass(c)},_toggleClass:f.fn.toggleClass,toggleClass:function(c,a,b,d,e){return typeof a=="boolean"||a===undefined?b?f.effects.animateClass.apply(this,[a?{add:c}:{remove:c},b,d,e]):this._toggleClass(c,a):f.effects.animateClass.apply(this,[{toggle:c},a,b,d])},switchClass:function(c,a,b,d,e){return f.effects.animateClass.apply(this,[{add:a,remove:c},b,d,e])}});f.extend(f.effects,{version:"1.8.2",save:function(c,a){for(var b=0;b<a.length;b++)a[b]!==
null&&c.data("ec.storage."+a[b],c[0].style[a[b]])},restore:function(c,a){for(var b=0;b<a.length;b++)a[b]!==null&&c.css(a[b],c.data("ec.storage."+a[b]))},setMode:function(c,a){if(a=="toggle")a=c.is(":hidden")?"show":"hide";return a},getBaseline:function(c,a){var b;switch(c[0]){case "top":b=0;break;case "middle":b=0.5;break;case "bottom":b=1;break;default:b=c[0]/a.height}switch(c[1]){case "left":c=0;break;case "center":c=0.5;break;case "right":c=1;break;default:c=c[1]/a.width}return{x:c,y:b}},createWrapper:function(c){if(c.parent().is(".ui-effects-wrapper"))return c.parent();
var a={width:c.outerWidth(true),height:c.outerHeight(true),"float":c.css("float")},b=f("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0});c.wrap(b);b=c.parent();if(c.css("position")=="static"){b.css({position:"relative"});c.css({position:"relative"})}else{f.extend(a,{position:c.css("position"),zIndex:c.css("z-index")});f.each(["top","left","bottom","right"],function(d,e){a[e]=c.css(e);if(isNaN(parseInt(a[e],10)))a[e]="auto"});
c.css({position:"relative",top:0,left:0})}return b.css(a).show()},removeWrapper:function(c){if(c.parent().is(".ui-effects-wrapper"))return c.parent().replaceWith(c);return c},setTransition:function(c,a,b,d){d=d||{};f.each(a,function(e,g){unit=c.cssUnit(g);if(unit[0]>0)d[g]=unit[0]*b+unit[1]});return d}});f.fn.extend({effect:function(c){var a=j.apply(this,arguments);a={options:a[1],duration:a[2],callback:a[3]};var b=f.effects[c];return b&&!f.fx.off?b.call(this,a):this},_show:f.fn.show,show:function(c){if(!c||
typeof c=="number"||f.fx.speeds[c])return this._show.apply(this,arguments);else{var a=j.apply(this,arguments);a[1].mode="show";return this.effect.apply(this,a)}},_hide:f.fn.hide,hide:function(c){if(!c||typeof c=="number"||f.fx.speeds[c])return this._hide.apply(this,arguments);else{var a=j.apply(this,arguments);a[1].mode="hide";return this.effect.apply(this,a)}},__toggle:f.fn.toggle,toggle:function(c){if(!c||typeof c=="number"||f.fx.speeds[c]||typeof c=="boolean"||f.isFunction(c))return this.__toggle.apply(this,
arguments);else{var a=j.apply(this,arguments);a[1].mode="toggle";return this.effect.apply(this,a)}},cssUnit:function(c){var a=this.css(c),b=[];f.each(["em","px","%","pt"],function(d,e){if(a.indexOf(e)>0)b=[parseFloat(a),e]});return b}});f.easing.jswing=f.easing.swing;f.extend(f.easing,{def:"easeOutQuad",swing:function(c,a,b,d,e){return f.easing[f.easing.def](c,a,b,d,e)},easeInQuad:function(c,a,b,d,e){return d*(a/=e)*a+b},easeOutQuad:function(c,a,b,d,e){return-d*(a/=e)*(a-2)+b},easeInOutQuad:function(c,
a,b,d,e){if((a/=e/2)<1)return d/2*a*a+b;return-d/2*(--a*(a-2)-1)+b},easeInCubic:function(c,a,b,d,e){return d*(a/=e)*a*a+b},easeOutCubic:function(c,a,b,d,e){return d*((a=a/e-1)*a*a+1)+b},easeInOutCubic:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a+b;return d/2*((a-=2)*a*a+2)+b},easeInQuart:function(c,a,b,d,e){return d*(a/=e)*a*a*a+b},easeOutQuart:function(c,a,b,d,e){return-d*((a=a/e-1)*a*a*a-1)+b},easeInOutQuart:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a+b;return-d/2*((a-=2)*a*a*a-2)+
b},easeInQuint:function(c,a,b,d,e){return d*(a/=e)*a*a*a*a+b},easeOutQuint:function(c,a,b,d,e){return d*((a=a/e-1)*a*a*a*a+1)+b},easeInOutQuint:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a*a+b;return d/2*((a-=2)*a*a*a*a+2)+b},easeInSine:function(c,a,b,d,e){return-d*Math.cos(a/e*(Math.PI/2))+d+b},easeOutSine:function(c,a,b,d,e){return d*Math.sin(a/e*(Math.PI/2))+b},easeInOutSine:function(c,a,b,d,e){return-d/2*(Math.cos(Math.PI*a/e)-1)+b},easeInExpo:function(c,a,b,d,e){return a==0?b:d*Math.pow(2,
10*(a/e-1))+b},easeOutExpo:function(c,a,b,d,e){return a==e?b+d:d*(-Math.pow(2,-10*a/e)+1)+b},easeInOutExpo:function(c,a,b,d,e){if(a==0)return b;if(a==e)return b+d;if((a/=e/2)<1)return d/2*Math.pow(2,10*(a-1))+b;return d/2*(-Math.pow(2,-10*--a)+2)+b},easeInCirc:function(c,a,b,d,e){return-d*(Math.sqrt(1-(a/=e)*a)-1)+b},easeOutCirc:function(c,a,b,d,e){return d*Math.sqrt(1-(a=a/e-1)*a)+b},easeInOutCirc:function(c,a,b,d,e){if((a/=e/2)<1)return-d/2*(Math.sqrt(1-a*a)-1)+b;return d/2*(Math.sqrt(1-(a-=2)*
a)+1)+b},easeInElastic:function(c,a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e)==1)return b+d;g||(g=e*0.3);if(h<Math.abs(d)){h=d;c=g/4}else c=g/(2*Math.PI)*Math.asin(d/h);return-(h*Math.pow(2,10*(a-=1))*Math.sin((a*e-c)*2*Math.PI/g))+b},easeOutElastic:function(c,a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e)==1)return b+d;g||(g=e*0.3);if(h<Math.abs(d)){h=d;c=g/4}else c=g/(2*Math.PI)*Math.asin(d/h);return h*Math.pow(2,-10*a)*Math.sin((a*e-c)*2*Math.PI/g)+d+b},easeInOutElastic:function(c,
a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e/2)==2)return b+d;g||(g=e*0.3*1.5);if(h<Math.abs(d)){h=d;c=g/4}else c=g/(2*Math.PI)*Math.asin(d/h);if(a<1)return-0.5*h*Math.pow(2,10*(a-=1))*Math.sin((a*e-c)*2*Math.PI/g)+b;return h*Math.pow(2,-10*(a-=1))*Math.sin((a*e-c)*2*Math.PI/g)*0.5+d+b},easeInBack:function(c,a,b,d,e,g){if(g==undefined)g=1.70158;return d*(a/=e)*a*((g+1)*a-g)+b},easeOutBack:function(c,a,b,d,e,g){if(g==undefined)g=1.70158;return d*((a=a/e-1)*a*((g+1)*a+g)+1)+b},easeInOutBack:function(c,
a,b,d,e,g){if(g==undefined)g=1.70158;if((a/=e/2)<1)return d/2*a*a*(((g*=1.525)+1)*a-g)+b;return d/2*((a-=2)*a*(((g*=1.525)+1)*a+g)+2)+b},easeInBounce:function(c,a,b,d,e){return d-f.easing.easeOutBounce(c,e-a,0,d,e)+b},easeOutBounce:function(c,a,b,d,e){return(a/=e)<1/2.75?d*7.5625*a*a+b:a<2/2.75?d*(7.5625*(a-=1.5/2.75)*a+0.75)+b:a<2.5/2.75?d*(7.5625*(a-=2.25/2.75)*a+0.9375)+b:d*(7.5625*(a-=2.625/2.75)*a+0.984375)+b},easeInOutBounce:function(c,a,b,d,e){if(a<e/2)return f.easing.easeInBounce(c,a*2,0,
d,e)*0.5+b;return f.easing.easeOutBounce(c,a*2-e,0,d,e)*0.5+d*0.5+b}})}(jQuery);
;/*
 * jQuery UI Effects Blind 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Blind
 *
 * Depends:
 *	jquery.effects.core.js
 */
(function(b){b.effects.blind=function(c){return this.queue(function(){var a=b(this),g=["position","top","left"],f=b.effects.setMode(a,c.options.mode||"hide"),d=c.options.direction||"vertical";b.effects.save(a,g);a.show();var e=b.effects.createWrapper(a).css({overflow:"hidden"}),h=d=="vertical"?"height":"width";d=d=="vertical"?e.height():e.width();f=="show"&&e.css(h,0);var i={};i[h]=f=="show"?d:0;e.animate(i,c.duration,c.options.easing,function(){f=="hide"&&a.hide();b.effects.restore(a,g);b.effects.removeWrapper(a);
c.callback&&c.callback.apply(a[0],arguments);a.dequeue()})})}})(jQuery);
;/*
 * jQuery UI Effects Bounce 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Bounce
 *
 * Depends:
 *	jquery.effects.core.js
 */
(function(e){e.effects.bounce=function(b){return this.queue(function(){var a=e(this),l=["position","top","left"],h=e.effects.setMode(a,b.options.mode||"effect"),d=b.options.direction||"up",c=b.options.distance||20,m=b.options.times||5,i=b.duration||250;/show|hide/.test(h)&&l.push("opacity");e.effects.save(a,l);a.show();e.effects.createWrapper(a);var f=d=="up"||d=="down"?"top":"left";d=d=="up"||d=="left"?"pos":"neg";c=b.options.distance||(f=="top"?a.outerHeight({margin:true})/3:a.outerWidth({margin:true})/
3);if(h=="show")a.css("opacity",0).css(f,d=="pos"?-c:c);if(h=="hide")c/=m*2;h!="hide"&&m--;if(h=="show"){var g={opacity:1};g[f]=(d=="pos"?"+=":"-=")+c;a.animate(g,i/2,b.options.easing);c/=2;m--}for(g=0;g<m;g++){var j={},k={};j[f]=(d=="pos"?"-=":"+=")+c;k[f]=(d=="pos"?"+=":"-=")+c;a.animate(j,i/2,b.options.easing).animate(k,i/2,b.options.easing);c=h=="hide"?c*2:c/2}if(h=="hide"){g={opacity:0};g[f]=(d=="pos"?"-=":"+=")+c;a.animate(g,i/2,b.options.easing,function(){a.hide();e.effects.restore(a,l);e.effects.removeWrapper(a);
b.callback&&b.callback.apply(this,arguments)})}else{j={};k={};j[f]=(d=="pos"?"-=":"+=")+c;k[f]=(d=="pos"?"+=":"-=")+c;a.animate(j,i/2,b.options.easing).animate(k,i/2,b.options.easing,function(){e.effects.restore(a,l);e.effects.removeWrapper(a);b.callback&&b.callback.apply(this,arguments)})}a.queue("fx",function(){a.dequeue()});a.dequeue()})}})(jQuery);
;/*
 * jQuery UI Effects Clip 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Clip
 *
 * Depends:
 *	jquery.effects.core.js
 */
(function(b){b.effects.clip=function(e){return this.queue(function(){var a=b(this),i=["position","top","left","height","width"],f=b.effects.setMode(a,e.options.mode||"hide"),c=e.options.direction||"vertical";b.effects.save(a,i);a.show();var d=b.effects.createWrapper(a).css({overflow:"hidden"});d=a[0].tagName=="IMG"?d:a;var g={size:c=="vertical"?"height":"width",position:c=="vertical"?"top":"left"};c=c=="vertical"?d.height():d.width();if(f=="show"){d.css(g.size,0);d.css(g.position,c/2)}var h={};h[g.size]=
f=="show"?c:0;h[g.position]=f=="show"?0:c/2;d.animate(h,{queue:false,duration:e.duration,easing:e.options.easing,complete:function(){f=="hide"&&a.hide();b.effects.restore(a,i);b.effects.removeWrapper(a);e.callback&&e.callback.apply(a[0],arguments);a.dequeue()}})})}})(jQuery);
;/*
 * jQuery UI Effects Drop 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Drop
 *
 * Depends:
 *	jquery.effects.core.js
 */
(function(c){c.effects.drop=function(d){return this.queue(function(){var a=c(this),h=["position","top","left","opacity"],e=c.effects.setMode(a,d.options.mode||"hide"),b=d.options.direction||"left";c.effects.save(a,h);a.show();c.effects.createWrapper(a);var f=b=="up"||b=="down"?"top":"left";b=b=="up"||b=="left"?"pos":"neg";var g=d.options.distance||(f=="top"?a.outerHeight({margin:true})/2:a.outerWidth({margin:true})/2);if(e=="show")a.css("opacity",0).css(f,b=="pos"?-g:g);var i={opacity:e=="show"?1:
0};i[f]=(e=="show"?b=="pos"?"+=":"-=":b=="pos"?"-=":"+=")+g;a.animate(i,{queue:false,duration:d.duration,easing:d.options.easing,complete:function(){e=="hide"&&a.hide();c.effects.restore(a,h);c.effects.removeWrapper(a);d.callback&&d.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery);
;/*
 * jQuery UI Effects Explode 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Explode
 *
 * Depends:
 *	jquery.effects.core.js
 */
(function(j){j.effects.explode=function(a){return this.queue(function(){var c=a.options.pieces?Math.round(Math.sqrt(a.options.pieces)):3,d=a.options.pieces?Math.round(Math.sqrt(a.options.pieces)):3;a.options.mode=a.options.mode=="toggle"?j(this).is(":visible")?"hide":"show":a.options.mode;var b=j(this).show().css("visibility","hidden"),g=b.offset();g.top-=parseInt(b.css("marginTop"),10)||0;g.left-=parseInt(b.css("marginLeft"),10)||0;for(var h=b.outerWidth(true),i=b.outerHeight(true),e=0;e<c;e++)for(var f=
0;f<d;f++)b.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-f*(h/d),top:-e*(i/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:h/d,height:i/c,left:g.left+f*(h/d)+(a.options.mode=="show"?(f-Math.floor(d/2))*(h/d):0),top:g.top+e*(i/c)+(a.options.mode=="show"?(e-Math.floor(c/2))*(i/c):0),opacity:a.options.mode=="show"?0:1}).animate({left:g.left+f*(h/d)+(a.options.mode=="show"?0:(f-Math.floor(d/2))*(h/d)),top:g.top+
e*(i/c)+(a.options.mode=="show"?0:(e-Math.floor(c/2))*(i/c)),opacity:a.options.mode=="show"?1:0},a.duration||500);setTimeout(function(){a.options.mode=="show"?b.css({visibility:"visible"}):b.css({visibility:"visible"}).hide();a.callback&&a.callback.apply(b[0]);b.dequeue();j("div.ui-effects-explode").remove()},a.duration||500)})}})(jQuery);
;/*
 * jQuery UI Effects Fold 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Fold
 *
 * Depends:
 *	jquery.effects.core.js
 */
(function(c){c.effects.fold=function(a){return this.queue(function(){var b=c(this),j=["position","top","left"],d=c.effects.setMode(b,a.options.mode||"hide"),g=a.options.size||15,h=!!a.options.horizFirst,k=a.duration?a.duration/2:c.fx.speeds._default/2;c.effects.save(b,j);b.show();var e=c.effects.createWrapper(b).css({overflow:"hidden"}),f=d=="show"!=h,l=f?["width","height"]:["height","width"];f=f?[e.width(),e.height()]:[e.height(),e.width()];var i=/([0-9]+)%/.exec(g);if(i)g=parseInt(i[1],10)/100*
f[d=="hide"?0:1];if(d=="show")e.css(h?{height:0,width:g}:{height:g,width:0});h={};i={};h[l[0]]=d=="show"?f[0]:g;i[l[1]]=d=="show"?f[1]:0;e.animate(h,k,a.options.easing).animate(i,k,a.options.easing,function(){d=="hide"&&b.hide();c.effects.restore(b,j);c.effects.removeWrapper(b);a.callback&&a.callback.apply(b[0],arguments);b.dequeue()})})}})(jQuery);
;/*
 * jQuery UI Effects Highlight 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Highlight
 *
 * Depends:
 *	jquery.effects.core.js
 */
(function(b){b.effects.highlight=function(c){return this.queue(function(){var a=b(this),e=["backgroundImage","backgroundColor","opacity"],d=b.effects.setMode(a,c.options.mode||"show"),f={backgroundColor:a.css("backgroundColor")};if(d=="hide")f.opacity=0;b.effects.save(a,e);a.show().css({backgroundImage:"none",backgroundColor:c.options.color||"#ffff99"}).animate(f,{queue:false,duration:c.duration,easing:c.options.easing,complete:function(){d=="hide"&&a.hide();b.effects.restore(a,e);d=="show"&&!b.support.opacity&&
this.style.removeAttribute("filter");c.callback&&c.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery);
;/*
 * jQuery UI Effects Pulsate 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Pulsate
 *
 * Depends:
 *	jquery.effects.core.js
 */
(function(d){d.effects.pulsate=function(a){return this.queue(function(){var b=d(this),c=d.effects.setMode(b,a.options.mode||"show");times=(a.options.times||5)*2-1;duration=a.duration?a.duration/2:d.fx.speeds._default/2;isVisible=b.is(":visible");animateTo=0;if(!isVisible){b.css("opacity",0).show();animateTo=1}if(c=="hide"&&isVisible||c=="show"&&!isVisible)times--;for(c=0;c<times;c++){b.animate({opacity:animateTo},duration,a.options.easing);animateTo=(animateTo+1)%2}b.animate({opacity:animateTo},duration,
a.options.easing,function(){animateTo==0&&b.hide();a.callback&&a.callback.apply(this,arguments)});b.queue("fx",function(){b.dequeue()}).dequeue()})}})(jQuery);
;/*
 * jQuery UI Effects Scale 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Scale
 *
 * Depends:
 *	jquery.effects.core.js
 */
(function(c){c.effects.puff=function(b){return this.queue(function(){var a=c(this),e=c.effects.setMode(a,b.options.mode||"hide"),g=parseInt(b.options.percent,10)||150,h=g/100,i={height:a.height(),width:a.width()};c.extend(b.options,{fade:true,mode:e,percent:e=="hide"?g:100,from:e=="hide"?i:{height:i.height*h,width:i.width*h}});a.effect("scale",b.options,b.duration,b.callback);a.dequeue()})};c.effects.scale=function(b){return this.queue(function(){var a=c(this),e=c.extend(true,{},b.options),g=c.effects.setMode(a,
b.options.mode||"effect"),h=parseInt(b.options.percent,10)||(parseInt(b.options.percent,10)==0?0:g=="hide"?0:100),i=b.options.direction||"both",f=b.options.origin;if(g!="effect"){e.origin=f||["middle","center"];e.restore=true}f={height:a.height(),width:a.width()};a.from=b.options.from||(g=="show"?{height:0,width:0}:f);h={y:i!="horizontal"?h/100:1,x:i!="vertical"?h/100:1};a.to={height:f.height*h.y,width:f.width*h.x};if(b.options.fade){if(g=="show"){a.from.opacity=0;a.to.opacity=1}if(g=="hide"){a.from.opacity=
1;a.to.opacity=0}}e.from=a.from;e.to=a.to;e.mode=g;a.effect("size",e,b.duration,b.callback);a.dequeue()})};c.effects.size=function(b){return this.queue(function(){var a=c(this),e=["position","top","left","width","height","overflow","opacity"],g=["position","top","left","overflow","opacity"],h=["width","height","overflow"],i=["fontSize"],f=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],k=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],p=c.effects.setMode(a,
b.options.mode||"effect"),n=b.options.restore||false,m=b.options.scale||"both",l=b.options.origin,j={height:a.height(),width:a.width()};a.from=b.options.from||j;a.to=b.options.to||j;if(l){l=c.effects.getBaseline(l,j);a.from.top=(j.height-a.from.height)*l.y;a.from.left=(j.width-a.from.width)*l.x;a.to.top=(j.height-a.to.height)*l.y;a.to.left=(j.width-a.to.width)*l.x}var d={from:{y:a.from.height/j.height,x:a.from.width/j.width},to:{y:a.to.height/j.height,x:a.to.width/j.width}};if(m=="box"||m=="both"){if(d.from.y!=
d.to.y){e=e.concat(f);a.from=c.effects.setTransition(a,f,d.from.y,a.from);a.to=c.effects.setTransition(a,f,d.to.y,a.to)}if(d.from.x!=d.to.x){e=e.concat(k);a.from=c.effects.setTransition(a,k,d.from.x,a.from);a.to=c.effects.setTransition(a,k,d.to.x,a.to)}}if(m=="content"||m=="both")if(d.from.y!=d.to.y){e=e.concat(i);a.from=c.effects.setTransition(a,i,d.from.y,a.from);a.to=c.effects.setTransition(a,i,d.to.y,a.to)}c.effects.save(a,n?e:g);a.show();c.effects.createWrapper(a);a.css("overflow","hidden").css(a.from);
if(m=="content"||m=="both"){f=f.concat(["marginTop","marginBottom"]).concat(i);k=k.concat(["marginLeft","marginRight"]);h=e.concat(f).concat(k);a.find("*[width]").each(function(){child=c(this);n&&c.effects.save(child,h);var o={height:child.height(),width:child.width()};child.from={height:o.height*d.from.y,width:o.width*d.from.x};child.to={height:o.height*d.to.y,width:o.width*d.to.x};if(d.from.y!=d.to.y){child.from=c.effects.setTransition(child,f,d.from.y,child.from);child.to=c.effects.setTransition(child,
f,d.to.y,child.to)}if(d.from.x!=d.to.x){child.from=c.effects.setTransition(child,k,d.from.x,child.from);child.to=c.effects.setTransition(child,k,d.to.x,child.to)}child.css(child.from);child.animate(child.to,b.duration,b.options.easing,function(){n&&c.effects.restore(child,h)})})}a.animate(a.to,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){a.to.opacity===0&&a.css("opacity",a.from.opacity);p=="hide"&&a.hide();c.effects.restore(a,n?e:g);c.effects.removeWrapper(a);b.callback&&
b.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery);
;/*
 * jQuery UI Effects Shake 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Shake
 *
 * Depends:
 *	jquery.effects.core.js
 */
(function(d){d.effects.shake=function(a){return this.queue(function(){var b=d(this),j=["position","top","left"];d.effects.setMode(b,a.options.mode||"effect");var c=a.options.direction||"left",e=a.options.distance||20,l=a.options.times||3,f=a.duration||a.options.duration||140;d.effects.save(b,j);b.show();d.effects.createWrapper(b);var g=c=="up"||c=="down"?"top":"left",h=c=="up"||c=="left"?"pos":"neg";c={};var i={},k={};c[g]=(h=="pos"?"-=":"+=")+e;i[g]=(h=="pos"?"+=":"-=")+e*2;k[g]=(h=="pos"?"-=":"+=")+
e*2;b.animate(c,f,a.options.easing);for(e=1;e<l;e++)b.animate(i,f,a.options.easing).animate(k,f,a.options.easing);b.animate(i,f,a.options.easing).animate(c,f/2,a.options.easing,function(){d.effects.restore(b,j);d.effects.removeWrapper(b);a.callback&&a.callback.apply(this,arguments)});b.queue("fx",function(){b.dequeue()});b.dequeue()})}})(jQuery);
;/*
 * jQuery UI Effects Slide 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Slide
 *
 * Depends:
 *	jquery.effects.core.js
 */
(function(c){c.effects.slide=function(d){return this.queue(function(){var a=c(this),h=["position","top","left"],e=c.effects.setMode(a,d.options.mode||"show"),b=d.options.direction||"left";c.effects.save(a,h);a.show();c.effects.createWrapper(a).css({overflow:"hidden"});var f=b=="up"||b=="down"?"top":"left";b=b=="up"||b=="left"?"pos":"neg";var g=d.options.distance||(f=="top"?a.outerHeight({margin:true}):a.outerWidth({margin:true}));if(e=="show")a.css(f,b=="pos"?-g:g);var i={};i[f]=(e=="show"?b=="pos"?
"+=":"-=":b=="pos"?"-=":"+=")+g;a.animate(i,{queue:false,duration:d.duration,easing:d.options.easing,complete:function(){e=="hide"&&a.hide();c.effects.restore(a,h);c.effects.removeWrapper(a);d.callback&&d.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery);
;/*
 * jQuery UI Effects Transfer 1.8.2
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Transfer
 *
 * Depends:
 *	jquery.effects.core.js
 */
(function(e){e.effects.transfer=function(a){return this.queue(function(){var b=e(this),c=e(a.options.to),d=c.offset();c={top:d.top,left:d.left,height:c.innerHeight(),width:c.innerWidth()};d=b.offset();var f=e('<div class="ui-effects-transfer"></div>').appendTo(document.body).addClass(a.options.className).css({top:d.top,left:d.left,height:b.innerHeight(),width:b.innerWidth(),position:"absolute"}).animate(c,a.duration,a.options.easing,function(){f.remove();a.callback&&a.callback.apply(b[0],arguments);
b.dequeue()})})}})(jQuery);
;/*
 * jQuery PanZoom Plugin
 * Pan and zoom an image within a parent div.
 *
 * version: 0.9.0
 * @requires jQuery v1.4.2 or later (earlier probably work, but untested so far)
 *
 * Copyright (c) 2011 Ben Lumley
 * Examples and documentation at: https://github.com/benlumley/jQuery-PanZoom
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
*/

(function( $ ){

  $.fn.panZoom = function(method) {

    if ( methods[method] ) {
      return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
      return methods.init.apply( this, arguments );
    } else {
      $.error( 'Method ' +  method + ' does not exist' );
    }

  };

	$.fn.panZoom.defaults = {
      zoomIn   					: 	false,
      zoomOut 					: 	false,
		  panUp							:		false,
		  panDown						:		false,
		  panLeft						:		false,
		  panRight					:		false,
			fit								: 	false,
		  out_x1						:		false,
		  out_y1						:		false,
		  out_x2						:		false,
		  out_y2						:		false,
			min_width					:   20,
			min_height 				:   20,
			zoom_step					:   3,
			pan_step  				:   3,
			debug							: 	false,
			directedit				:   false,
      aspect    				:   true,
      factor    				:   1,
		  animate   				:   true,
			animate_duration	: 	200,
		 	animate_easing		: 	'linear',
			double_click	 		: 	true,
			mousewheel				: 	true,
			mousewheel_delta	: 	1,
			draggable					:   true,
			clickandhold			: 	true
  };

	var settings = {}

  var methods = {
		'init': function (options) {
			$.extend(settings, $.fn.panZoom.defaults, options);
  		setupCSS.apply(this);
			setupData.apply(this);
			setupBindings.apply(this);
			methods.readPosition.apply(this);
		},

		'destroy': function () {
			$(window).unbind('.panZoom');
			this.removeData('panZoom');
		},

		'loadImage': function () {
			var data = this.data('panZoom');
      loadTargetDimensions.apply(this);
			methods.updatePosition.apply(this);
			if (data.last_image != null && data.last_image != this.attr('src')) {
        methods.fit.apply(this);
			}
			data.last_image = this.attr('src');
			data.loaded = true;
		},

	  'readPosition': function () {
				var data = this.data('panZoom');
		 		if (settings.out_x1) { data.position.x1 = settings.out_x1.val()*settings.factor }
		 		if (settings.out_y1) { data.position.y1 = settings.out_y1.val()*settings.factor }
		 		if (settings.out_x2) { data.position.x2 = settings.out_x2.val()*settings.factor }
		 		if (settings.out_y2) { data.position.y2 = settings.out_y2.val()*settings.factor }
				methods.updatePosition.apply(this);
		 },

		'updatePosition': function() {
			validatePosition.apply(this);
			writePosition.apply(this);
			applyPosition.apply(this);
		},

	  'fit': function () {
			var data = this.data('panZoom');
			data.position.x1 = 0;
			data.position.y1 = 0;
			data.position.x2 = data.viewport_dimensions.x;
			data.position.y2 = data.viewport_dimensions.y;
			methods.updatePosition.apply(this);
		},

		'zoomIn': function (steps) {
			var data = this.data('panZoom');
			if (typeof(steps) == 'undefined') {
				var steps = getStepDimensions.apply(this);
			}
            console.debug(data.position);
			console.debug(data.viewport_dimensions);
			data.position.x1 = data.position.x1*1 - steps.zoom.x;
			data.position.x2 = data.position.x2*1 + steps.zoom.x;
			data.position.y1 = data.position.y1*1 - steps.zoom.y;
			data.position.y2 = data.position.y2*1 + steps.zoom.y;
			methods.updatePosition.apply(this);
		 },

		'zoomOut': function (steps) {
			var data = this.data('panZoom');
			if (typeof(steps) == 'undefined') {
				var steps = getStepDimensions.apply(this);
			}
			data.position.x1 = data.position.x1*1 + steps.zoom.x;
			data.position.x2 = data.position.x2*1 - steps.zoom.x;
			data.position.y1 = data.position.y1*1 + steps.zoom.y;
			data.position.y2 = data.position.y2*1 - steps.zoom.y;
			methods.updatePosition.apply(this);
		 },

		'panUp': function () {
			var data = this.data('panZoom');
			var steps = getStepDimensions.apply(this);
			data.position.y1 -= steps.pan.y;
			data.position.y2 -= steps.pan.y;
			methods.updatePosition.apply(this);
		},

		'panDown': function () {
			var data = this.data('panZoom');
			var steps = getStepDimensions.apply(this);
			data.position.y1 = data.position.y1*1 + steps.pan.y;
			data.position.y2 = data.position.y2*1 + steps.pan.y;
			methods.updatePosition.apply(this);
		},

		'panLeft': function () {
			var data = this.data('panZoom');
			var steps = getStepDimensions.apply(this);
			data.position.x1 -= steps.pan.x;
			data.position.x2 -= steps.pan.x;
			methods.updatePosition.apply(this);
		},

		'panRight': function () {
			var data = this.data('panZoom');
			var steps = getStepDimensions.apply(this);
			data.position.x1 = data.position.x1*1 + steps.pan.x;
			data.position.x2 = data.position.x2*1 + steps.pan.x;
			methods.updatePosition.apply(this);
		},

		'mouseWheel': function (delta) {
			// first calculate how much to zoom in/out
			var steps = getStepDimensions.apply(this);
			steps.zoom.x = steps.zoom.x * (Math.abs(delta) / settings.mousewheel_delta);
			steps.zoom.y = steps.zoom.y * (Math.abs(delta) / settings.mousewheel_delta);

			// then do it
			if (delta > 0) {
				methods.zoomIn.apply(this, [steps]);
			} else if (delta < 0) {
				methods.zoomOut.apply(this, [steps]);
			}
		},

		'dragComplete': function() {
			var data = this.data('panZoom');
			data.position.x1 = this.position().left;
			data.position.y1 = this.position().top;
			data.position.x2 = this.position().left*1 + this.width();
			data.position.y2 = this.position().top*1 + this.height();
			methods.updatePosition.apply(this);
		},

		'mouseDown': function (action) {
			methods[action].apply(this);

			if (settings.clickandhold) {
				var data = this.data('panZoom');
				methods.mouseUp.apply(this);
				data.mousedown_interval = window.setInterval(function (that, action) {
					that.panZoom(action);
				}, settings.animate_duration, this, action);
			}
		},

		'mouseUp': function() {
			var data = this.data('panZoom');
			window.clearInterval(data.mousedown_interval);
		}

  }

	function setupBindings() {

		eventData = { target: this }

		// bind up controls
		if (settings.zoomIn) {
			settings.zoomIn.bind('mousedown.panZoom', eventData, function(event) {
				event.preventDefault(); event.data.target.panZoom('mouseDown', 'zoomIn');
			}).bind('mouseleave.panZoom mouseup.panZoom', eventData, function(event) {
				event.preventDefault(); event.data.target.panZoom('mouseUp');
			});
		}

		if (settings.zoomOut) {
			settings.zoomOut.bind('mousedown.panZoom', eventData, function(event) {
				event.preventDefault(); event.data.target.panZoom('mouseDown', 'zoomOut');
			}).bind('mouseleave.panZoom mouseup.panZoom', eventData, function(event) {
				event.preventDefault(); event.data.target.panZoom('mouseUp');
			});
		}

		if (settings.panUp) {
			settings.panUp.bind('mousedown.panZoom', eventData, function(event) {
				event.preventDefault(); event.data.target.panZoom('mouseDown', 'panUp');
			}).bind('mouseleave.panZoom mouseup.panZoom', eventData, function(event) {
				event.preventDefault(); event.data.target.panZoom('mouseUp');
			});
		}

		if (settings.panDown) {
			settings.panDown.bind('mousedown.panZoom', eventData, function(event) {
				event.preventDefault(); event.data.target.panZoom('mouseDown', 'panDown');
			}).bind('mouseleave.panZoom mouseup.panZoom', eventData, function(event) {
				event.preventDefault(); event.data.target.panZoom('mouseUp');
			});
		}

		if (settings.panLeft) {
			settings.panLeft.bind('mousedown.panZoom', eventData, function(event) {
				event.preventDefault(); event.data.target.panZoom('mouseDown', 'panLeft');
			}).bind('mouseleave.panZoom mouseup.panZoom', eventData, function(event) {
				event.preventDefault(); event.data.target.panZoom('mouseUp');
			});
		}

		if (settings.panRight) {
			settings.panRight.bind('mousedown.panZoom', eventData, function(event) {
				event.preventDefault(); event.data.target.panZoom('mouseDown', 'panRight');
			}).bind('mouseleave.panZoom mouseup.panZoom', eventData, function(event) {
				event.preventDefault(); event.data.target.panZoom('mouseUp');
			});
		}

		if (settings.fit) { settings.fit.bind('click.panZoom', eventData, function(event) { event.preventDefault(); event.data.target.panZoom('fit'); } ); }

		// double click
		if (settings.double_click) {
			this.bind('dblclick.panZoom', eventData, function(event, delta) { event.data.target.panZoom('zoomIn') } );
		}

		// mousewheel
		if (settings.mousewheel && typeof(this.mousewheel) == 'function') {
			this.parent().mousewheel(function(event, delta) { event.preventDefault(); $(this).find('img').panZoom('mouseWheel', delta) } );
		} else if (settings.mousewheel) {
			alert('Mousewheel requires mousewheel from jQuery tools - please include jQuery tools or disable mousewheel to remove this warning.')
		}

		// direct form input
		if (settings.directedit) {
			$(settings.out_x1).add(settings.out_y1).add(settings.out_x2).add(settings.out_y2).bind('change.panZoom blur.panZoom', eventData, function(event) { event.data.target.panZoom('readPosition') } );
		}

		if (settings.draggable && typeof(this.draggable) == 'function') {
			this.draggable({
				stop: function () { $(this).panZoom('dragComplete');	}
			});
		}	else if (settings.draggable) {
				alert('Draggable requires jQuery UI - please include jQuery UI or disable draggable to remove this warning.')
		}

		// image load
		$(this).bind('load.panZoom', eventData, function (event) { event.data.target.panZoom('loadImage') })

	}

	function setupData() {
		this.data('panZoom', {
			target_element: this,
			target_dimensions: { x: null, y: null },
			viewport_element: this.parent(),
			viewport_dimensions: { x: this.parent().width(), y: this.parent().height() },
			position: { x1: null, y1: null, x2: null, y2: null },
			last_image: null,
			loaded: false,
			mousewheel_delta: 0,
			mousedown_interval: false
		});
		if (settings.debug) {
			console.log(this.data('panZoom'));
		}
	}

	function setupCSS() {
		if (this.parent().css('position') == 'static') {
			this.parent().css('position', 'relative');
		}
		this.css({
			'position': 'absolute',
			'top': 0,
			'left': 0
		});
		if (settings.draggable) {
			this.css({
				'cursor': 'move'
			});
		}
	}

	function validatePosition() {
		var data = this.data('panZoom');
		// if dimensions are too small...
		if ( data.position.x2 - data.position.x1 < settings.min_width/settings.factor || data.position.y2 - data.position.y1 < settings.min_height/settings.factor ) {
			// and second co-ords are zero (IE: no dims set), fit image
			if (data.position.x2 == 0 || data.position.y2 == 0) {
				methods.fit.apply(this);
			}
			// otherwise, backout a bit
			else {
				if (data.position.x2 - data.position.x1 < settings.min_width/settings.factor) {
					data.position.x2 = data.position.x1*1+settings.min_width/settings.factor;
				}
				if (data.position.y2 - data.position.y1 < settings.min_height/settings.factor) {
	  			data.position.y2 = data.position.y1*1+settings.min_height/settings.factor;
				}
			}
		}

		if (settings.aspect) {
			target = data.target_dimensions.ratio;
			current = getCurrentAspectRatio.apply(this)
			if (current > target) {
				new_width = getHeight.apply(this) * target;
				diff = getWidth.apply(this) - new_width;
				data.position.x1 = data.position.x1*1 + (diff/2);
				data.position.x2 = data.position.x2*1 - (diff/2);
			} else if (current < target) {
				new_height = getWidth.apply(this) / target;
				diff = getHeight.apply(this) - new_height;
				data.position.y1 = data.position.y1*1 + (diff/2);
				data.position.y2 = data.position.y2*1 - (diff/2);
			}
		}


	}

  function applyPosition() {
		var data = this.data('panZoom');

    width = getWidth.apply(this);
    height = getHeight.apply(this);
    left_offset = getLeftOffset.apply(this);
    top_offset = getTopOffset.apply(this);

		properties = {
			'top': Math.round(top_offset),
			'left': Math.round(left_offset),
			'width': Math.round(width),
			'height': Math.round(height)
		}

		if (data.loaded && settings.animate) {
			applyAnimate.apply(this, [ properties ]);
		} else {
			applyCSS.apply(this, [ properties ]);
		}

		if (settings.debug) {
			console.log('--');
			console.log('width:' + width);
			console.log('height:' + height);
			console.log('left:' + left_offset);
			console.log('top:' + top_offset);
		}
	}

	function applyCSS() {
		this.css(	properties );
	}

	function applyAnimate() {
		this.stop().animate(	properties , settings.animate_duration, settings.animate_easing);
	}

  function getWidth() {
		var data = this.data('panZoom');
    width = (data.position.x2 - data.position.x1);
    return width;
  }

  function getLeftOffset() {
		var data = this.data('panZoom');
    return data.position.x1;
  }

  function getHeight() {
		var data = this.data('panZoom');
		height = (data.position.y2 - data.position.y1);
    return height;
  }

  function getTopOffset() {
		var data = this.data('panZoom');
		top_offset = data.position.y1;
    return top_offset;
  }

	function getCurrentAspectRatio() {
		return (getWidth.apply(this) / getHeight.apply(this));
	}

	function writePosition() {
		var data = this.data('panZoom');
 		if (settings.out_x1) { settings.out_x1.val(Math.round(data.position.x1 / settings.factor)) }
 		if (settings.out_y1) { settings.out_y1.val(Math.round(data.position.y1 / settings.factor)) }
 		if (settings.out_x2) { settings.out_x2.val(Math.round(data.position.x2 / settings.factor)) }
 		if (settings.out_y2) { settings.out_y2.val(Math.round(data.position.y2 / settings.factor)) }
	}

	function getStepDimensions() {
		var data = this.data('panZoom');
		ret = {
			zoom: {
				x: (settings.zoom_step/100 * data.viewport_dimensions.x),
				y: (settings.zoom_step/100 * data.viewport_dimensions.y)
			},
			pan: {
				x: (settings.pan_step/100 * data.viewport_dimensions.x),
				y: (settings.pan_step/100 * data.viewport_dimensions.y)
			}
		}
		return ret;
	}

	function loadTargetDimensions() {
		var data = this.data('panZoom');
		var img = document.createElement('img');
    img.src = this.attr('src');
    img.id = "jqpz-temp";
    $('body').append(img);
    data.target_dimensions.x = $('#jqpz-temp').width();
		data.target_dimensions.y = $('#jqpz-temp').height();
    $('#jqpz-temp').remove();
    data.target_dimensions.ratio = data.target_dimensions.x / data.target_dimensions.y;
	}

})( jQuery );$.browser.chrome = /chrome/.test(navigator.userAgent.toLowerCase());
$.browser.ipad   = /ipad/.test(navigator.userAgent.toLowerCase());

/**
 * Initializes page contents for progressive enhancement.
 */
function initializeContents()
{
    // hide all more buttons because they are not needed with JS
    $(".element a.more").hide();

    $(".clickable.class,.clickable.interface").click(function() {
        document.location = $("a.more", this).attr('href');
    });

    // change the cursor to a pointer to make it more explicit that this it clickable
    // do a background color change on hover to emphasize the clickability eveb more
    // we do not use CSS for this because when JS is disabled this behaviour does not
    // apply and we do not want the hover
    $(".element.method,.element.function,.element.class.clickable,.element.interface.clickable,.element.property.clickable")
        .css("cursor", "pointer")
        .hover(function() {
            $(this).css('backgroundColor', '#F8FDF6')
        }, function(){
            $(this).css('backgroundColor', 'white')}
        );

    $("ul.side-nav.nav.nav-list li.nav-header").contents()
        .filter(function(){return this.nodeType == 3 && $.trim($(this).text()).length > 0})
        .wrap('<span class="side-nav-header" />');

    $("ul.side-nav.nav.nav-list li.nav-header span.side-nav-header")
        .css("cursor", "pointer");

    // do not show tooltips on iPad; it will cause the user having to click twice
    if (!$.browser.ipad) {
        $('.btn-group.visibility,.btn-group.view,.btn-group.type-filter,.icon-custom')
            .tooltip({'placement':'bottom'});
        $('.element').tooltip({'placement':'left'});
    }

    $('.btn-group.visibility,.btn-group.view,.btn-group.type-filter')
        .show()
        .css('display', 'inline-block')
        .find('button')
        .find('i').click(function(){ $(this).parent().click(); });

    // set the events for the visibility buttons and enable by default.
    $('.visibility button.public').click(function(){
        $('.element.public,.side-nav li.public').toggle($(this).hasClass('active'));
    }).click();
    $('.visibility button.protected').click(function(){
        $('.element.protected,.side-nav li.protected').toggle($(this).hasClass('active'));
    }).click();
    $('.visibility button.private').click(function(){
        $('.element.private,.side-nav li.private').toggle($(this).hasClass('active'));
    }).click();
    $('.visibility button.inherited').click(function(){
        $('.element.inherited,.side-nav li.inherited').toggle($(this).hasClass('active'));
    }).click();

    $('.type-filter button.critical').click(function(){
        $('tr.critical').toggle($(this).hasClass('active'));
    });
    $('.type-filter button.error').click(function(){
        $('tr.error').toggle($(this).hasClass('active'));
    });
    $('.type-filter button.notice').click(function(){
        $('tr.notice').toggle($(this).hasClass('active'));
    });

    $('.view button.details').click(function(){
        $('.side-nav li.view-simple').removeClass('view-simple');
    }).button('toggle').click();

    $('.view button.simple').click(function(){
        $('.side-nav li').addClass('view-simple');
    });
    
    $('ul.side-nav.nav.nav-list li.nav-header span.side-nav-header').click(function(){
        $(this).siblings('ul').collapse('toggle');
    });

// sorting example
//    $('ol li').sort(
//        function(a, b) { return a.innerHTML.toLowerCase() > b.innerHTML.toLowerCase() ? 1 : -1; }
//    ).appendTo('ol');
}

$(document).ready(function() {
    prettyPrint();

    initializeContents();

    // do not show tooltips on iPad; it will cause the user having to click twice
    if(!$.browser.ipad) {
        $(".side-nav a").tooltip({'placement': 'top'});
    }

    // chrome cannot deal with certain situations; warn the user about reduced features
    if ($.browser.chrome && (window.location.protocol == 'file:')) {
        $("body > .container").prepend(
            '<div class="alert alert-error"><a class="close" data-dismiss="alert">×</a>' +
            'You are using Google Chrome in a local environment; AJAX interaction has been ' +
            'disabled because Chrome cannot <a href="http://code.google.com/p/chromium/issues/detail?id=40787">' +
            'retrieve files using Ajax</a>.</div>'
        );
    }

    $('ul.nav-namespaces li a, ul.nav-packages li a').click(function(){
        // Google Chrome does not do Ajax locally
        if ($.browser.chrome && (window.location.protocol == 'file:'))
        {
            return true;
        }

        $(this).parents('.side-nav').find('.active').removeClass('active');
        $(this).parent().addClass('active');
        $('div.namespace-contents').load(
            this.href + ' div.namespace-contents', function(){
                initializeContents();
                $(window).scrollTop($('div.namespace-contents').position().top);
            }
        );
        $('div.package-contents').load(
            this.href + ' div.package-contents', function(){
                initializeContents();
                $(window).scrollTop($('div.package-contents').position().top);
            }
        );

        return false;
    });

    function filterPath(string)
    {
        return string
            .replace(/^\//, '')
            .replace(/(index|default).[a-zA-Z]{3,4}$/, '')
            .replace(/\/$/, '');
    }

    var locationPath = filterPath(location.pathname);

    // the ipad already smoothly scrolls and does not detect the scrollable
    // element if top=0; as such we disable this behaviour for the iPad
    if (!$.browser.ipad) {
        $('a[href*=#]').each(function ()
        {
            var thisPath = filterPath(this.pathname) || locationPath;
            if (locationPath == thisPath && (location.hostname == this.hostname || !this.hostname) && this.hash.replace(/#/, ''))
            {
                var target = decodeURIComponent(this.hash.replace(/#/,''));
                // note: I'm using attribute selector, because id selector can't match elements with '$' 
                var $target = $('[id="'+target+'"]');

                if ($target.length > 0)
                {
                    $(this).click(function (event)
                    {
                        var scrollElem = scrollableElement('html', 'body');
                        var targetOffset = $target.offset().top;

                        event.preventDefault();
                        $(scrollElem).animate({scrollTop:targetOffset}, 400, function ()
                        {
                            location.hash = target;
                        });
                    });
                }
            }
        });
    }

    // use the first element that is "scrollable"
    function scrollableElement(els)
    {
        for (var i = 0, argLength = arguments.length; i < argLength; i++)
        {
            var el = arguments[i], $scrollElement = $(el);
            if ($scrollElement.scrollTop() > 0)
            {
                return el;
            }
            else
            {
                $scrollElement.scrollTop(1);
                var isScrollable = $scrollElement.scrollTop() > 0;
                $scrollElement.scrollTop(0);
                if (isScrollable)
                {
                    return el;
                }
            }
        }
        return [];
    }

    // Hide API Documentation menu if it's empty
    $('.nav .dropdown a[href=#api]').next().filter(function(el) {
        if ($(el).children().length == 0) {
            return true;
        }
    }).parent().hide();
});
/*
 * iviewer Widget for jQuery UI
 * https://github.com/can3p/iviewer
 *
 * Copyright (c) 2009 - 2012 Dmitry Petrov
 * Dual licensed under the MIT and GPL licenses.
 *  - http://www.opensource.org/licenses/mit-license.php
 *  - http://www.gnu.org/copyleft/gpl.html
 *
 * Author: Dmitry Petrov
 * Version: 0.7
 */

( function( $, undefined ) {

//this code was taken from the https://github.com/furf/jquery-ui-touch-punch
var mouseEvents = {
    touchstart: 'mousedown',
    touchmove: 'mousemove',
    touchend: 'mouseup'
};

/**
 * Convert a touch event to a mouse-like
 */
function makeMouseEvent (event) {
    var touch = event.originalEvent.changedTouches[0];

    return $.extend(event, {
        type:    mouseEvents[event.type],
        which:   1,
        pageX:   touch.pageX,
        pageY:   touch.pageY,
        screenX: touch.screenX,
        screenY: touch.screenY,
        clientX: touch.clientX,
        clientY: touch.clientY,
        isTouchEvent: true
    });
}

var mouseProto = $.ui.mouse.prototype,
    _mouseInit = $.ui.mouse.prototype._mouseInit;

mouseProto._mouseInit = function() {
    var self = this;
    self._touchActive = false;

    this.element.bind( 'touchstart.' + this.widgetName, function(event) {
        self._touchActive = true;
        return self._mouseDown(makeMouseEvent(event));
    })

    var self = this;
    // these delegates are required to keep context
    this._mouseMoveDelegate = function(event) {
        if (self._touchActive) {
            return self._mouseMove(makeMouseEvent(event));
        }
    };
    this._mouseUpDelegate = function(event) {
        if (self._touchActive) {
            self._touchActive = false;
            return self._mouseUp(makeMouseEvent(event));
        }
    };

    $(document)
        .bind('touchmove.'+ this.widgetName, this._mouseMoveDelegate)
        .bind('touchend.' + this.widgetName, this._mouseUpDelegate);

    _mouseInit.apply(this);
}

/**
 * Simple implementation of jQuery like getters/setters
 * var val = something();
 * something(val);
 */
var setter = function(setter, getter) {
    return function(val) {
        if (arguments.length === 0) {
            return getter.apply(this);
        } else {
            setter.apply(this, arguments);
        }
    }
};

/**
 * Internet explorer rotates image relative left top corner, so we should
 * shift image when it's rotated.
 */
var ieTransforms = {
        '0': {
            marginLeft: 0,
            marginTop: 0,
            filter: 'progid:DXImageTransform.Microsoft.Matrix(M11=1, M12=0, M21=0, M22=1, SizingMethod="auto expand")'
        },

        '90': {
            marginLeft: -1,
            marginTop: 1,
            filter: 'progid:DXImageTransform.Microsoft.Matrix(M11=0, M12=-1, M21=1, M22=0, SizingMethod="auto expand")'
        },

        '180': {
            marginLeft: 0,
            marginTop: 0,
            filter: 'progid:DXImageTransform.Microsoft.Matrix(M11=-1, M12=0, M21=0, M22=-1, SizingMethod="auto expand")'
        },

        '270': {
            marginLeft: -1,
            marginTop: 1,
            filter: 'progid:DXImageTransform.Microsoft.Matrix(M11=0, M12=1, M21=-1, M22=0, SizingMethod="auto expand")'
        }
    },
    useIeTransforms = (jQuery.browser.msie && parseInt(jQuery.browser.version, 10) <= 8);

$.widget( "ui.iviewer", $.ui.mouse, {
    widgetEventPrefix: "iviewer",
    options : {
        /**
        * start zoom value for image, not used now
        * may be equal to "fit" to fit image into container or scale in %
        **/
        zoom: "fit",
        /**
        * base value to scale image
        **/
        zoom_base: 100,
        /**
        * maximum zoom
        **/
        zoom_max: 800,
        /**
        * minimum zoom
        **/
        zoom_min: 25,
        /**
        * base of rate multiplier.
        * zoom is calculated by formula: zoom_base * zoom_delta^rate
        **/
        zoom_delta: 1.4,
        /**
        * whether the zoom should be animated.
        */
        zoom_animation: true,
        /**
        * if true plugin doesn't add its own controls
        **/
        ui_disabled: false,
        /**
        * if false, plugin doesn't bind resize event on window and this must
        * be handled manually
        **/
        update_on_resize: true,
        /**
        * event is triggered when zoom value is changed
        * @param int new zoom value
        * @return boolean if false zoom action is aborted
        **/
        onZoom: jQuery.noop,
        /**
        * event is triggered when zoom value is changed after image is set to the new dimensions
        * @param int new zoom value
        * @return boolean if false zoom action is aborted
        **/
        onAfterZoom: jQuery.noop,
        /**
        * event is fired on drag begin
        * @param object coords mouse coordinates on the image
        * @return boolean if false is returned, drag action is aborted
        **/
        onStartDrag: jQuery.noop,
        /**
        * event is fired on drag action
        * @param object coords mouse coordinates on the image
        **/
        onDrag: jQuery.noop,
        /**
        * event is fired on drag stop
        * @param object coords mouse coordinates on the image
        **/
        onStopDrag: jQuery.noop,
        /**
        * event is fired when mouse moves over image
        * @param object coords mouse coordinates on the image
        **/
        onMouseMove: jQuery.noop,
        /**
        * mouse click event
        * @param object coords mouse coordinates on the image
        **/
        onClick: jQuery.noop,
        /**
        * event is fired when image starts to load
        */
        onStartLoad: null,
        /**
        * event is fired, when image is loaded and initially positioned
        */
        onFinishLoad: null
    },

    _create: function() {
        var me = this;

        //drag variables
        this.dx = 0;
        this.dy = 0;

        /* object containing actual information about image
        *   @img_object.object - jquery img object
        *   @img_object.orig_{width|height} - original dimensions
        *   @img_object.display_{width|height} - actual dimensions
        */
        this.img_object = {};

        this.zoom_object = {}; //object to show zoom status

        this._angle = 0;

        this.current_zoom = this.options.zoom;

        if(this.options.src === null){
            return;
        }

        this.container = this.element;

        this._updateContainerInfo();

        //init container
        this.container.css("overflow","hidden");

        if(this.options.update_on_resize == true)
        {
            $(window).resize(function()
            {
                me._updateContainerInfo();
            });
        }

        this.img_object = new $.ui.iviewer.ImageObject(this.options.zoom_animation);

        //init object
        this.img_object.object()
            //bind mouse events
            .click(function(e){return me._click(e)})
            .mousewheel(function(ev, delta)
            {
                //this event is there instead of containing div, because
                //at opera it triggers many times on div
                var zoom = (delta > 0)?1:-1;
                me.zoom_by(zoom);
                return false;
            })
            .prependTo(this.container);

        this.container.bind('mousemove', function(ev) { me._handleMouseMove(ev); });

        this.loadImage(this.options.src);

        if(!this.options.ui_disabled)
        {
            this.createui();
        }

        this._mouseInit();
    },

    destroy: function() {
        this._mouseDestroy();
    },

    _updateContainerInfo: function()
    {
        this.options.height = this.container.height();
        this.options.width = this.container.width();
    },

    loadImage: function( src )
    {
        this.current_zoom = this.options.zoom;
        var me = this;

        this._trigger('onStartLoad', 0, src);

        this.img_object.load(src, function() {
                me.container.addClass("iviewer_cursor");

                if(me.options.zoom == "fit"){
                    me.fit(true);
                }
                else {
                    me.set_zoom(me.options.zoom, true);
                }

                if(me.options.onFinishLoad)
                {
                    me._trigger('onFinishLoad', 0, src);
                }
        });
    },

    /**
    * fits image in the container
    *
    * @param {boolean} skip_animation
    **/
    fit: function(skip_animation)
    {
        var aspect_ratio = this.img_object.orig_width() / this.img_object.orig_height();
        var window_ratio = this.options.width /  this.options.height;
        var choose_left = (aspect_ratio > window_ratio);
        var new_zoom = 0;

        if(choose_left){
            new_zoom = this.options.width / this.img_object.orig_width() * 100;
        }
        else {
            new_zoom = this.options.height / this.img_object.orig_height() * 100;
        }

      this.set_zoom(new_zoom, skip_animation);
    },

    /**
    * center image in container
    **/
    center: function()
    {
        this.setCoords(-Math.round((this.img_object.display_width() - this.options.width)/2),
                -Math.round((this.img_object.display_height() - this.options.height)/2));
    },

    /**
    *   move a point in container to the center of display area
    *   @param x a point in container
    *   @param y a point in container
    **/
    moveTo: function(x, y)
    {
        var dx = x-Math.round(this.options.width/2);
        var dy = y-Math.round(this.options.height/2);

        var new_x = this.img_object.x() - dx;
        var new_y = this.img_object.y() - dy;

        this.setCoords(new_x, new_y);
    },

    /**
     * Get container offset object.
     */
    getContainerOffset: function() {
        return jQuery.extend({}, this.container.offset());
    },

    /**
    * set coordinates of upper left corner of image object
    **/
    setCoords: function(x,y)
    {
        //do nothing while image is being loaded
        if(!this.img_object.loaded()) { return; }

        var coords = this._correctCoords(x,y);
        this.img_object.x(coords.x);
        this.img_object.y(coords.y);
    },

    _correctCoords: function( x, y )
    {
        x = parseInt(x, 10);
        y = parseInt(y, 10);

        //check new coordinates to be correct (to be in rect)
        if(y > 0){
            y = 0;
        }
        if(x > 0){
            x = 0;
        }
        if(y + this.img_object.display_height() < this.options.height){
            y = this.options.height - this.img_object.display_height();
        }
        if(x + this.img_object.display_width() < this.options.width){
            x = this.options.width - this.img_object.display_width();
        }
        if(this.img_object.display_width() <= this.options.width){
            x = -(this.img_object.display_width() - this.options.width)/2;
        }
        if(this.img_object.display_height() <= this.options.height){
            y = -(this.img_object.display_height() - this.options.height)/2;
        }

        return { x: x, y:y };
    },


    /**
    * convert coordinates on the container to the coordinates on the image (in original size)
    *
    * @return object with fields x,y according to coordinates or false
    * if initial coords are not inside image
    **/
    containerToImage : function (x,y)
    {
        var coords = { x : x - this.img_object.x(),
                 y :  y - this.img_object.y()
        };

        coords = this.img_object.toOriginalCoords(coords);

        return { x :  util.descaleValue(coords.x, this.current_zoom),
                 y :  util.descaleValue(coords.y, this.current_zoom)
        };
    },

    /**
    * convert coordinates on the image (in original size, and zero angle) to the coordinates on the container
    *
    * @return object with fields x,y according to coordinates
    **/
    imageToContainer : function (x,y)
    {
        var coords = {
                x : util.scaleValue(x, this.current_zoom),
                y : util.scaleValue(y, this.current_zoom)
            };

        return this.img_object.toRealCoords(coords);
    },

    /**
    * get mouse coordinates on the image
    * @param e - object containing pageX and pageY fields, e.g. mouse event object
    *
    * @return object with fields x,y according to coordinates or false
    * if initial coords are not inside image
    **/
    _getMouseCoords : function(e)
    {
        var containerOffset = this.container.offset();
            coords = this.containerToImage(e.pageX - containerOffset.left, e.pageY - containerOffset.top);

        return coords;
    },

    /**
    * set image scale to the new_zoom
    *
    * @param {number} new_zoom image scale in %
    * @param {boolean} skip_animation
    **/
    set_zoom: function(new_zoom, skip_animation)
    {
        if (this._trigger('onZoom', 0, new_zoom) == false) {
            return;
        }

        //do nothing while image is being loaded
        if(!this.img_object.loaded()) { return; }

        if(new_zoom <  this.options.zoom_min)
        {
            new_zoom = this.options.zoom_min;
        }
        else if(new_zoom > this.options.zoom_max)
        {
            new_zoom = this.options.zoom_max;
        }

        /* we fake these values to make fit zoom properly work */
        if(this.current_zoom == "fit")
        {
            var old_x = Math.round(this.options.width/2 + this.img_object.orig_width()/2);
            var old_y = Math.round(this.options.height/2 + this.img_object.orig_height()/2);
            this.current_zoom = 100;
        }
        else {
            var old_x = -this.img_object.x() + Math.round(this.options.width/2);
            var old_y = -this.img_object.y() + Math.round(this.options.height/2);
        }

        var new_width = util.scaleValue(this.img_object.orig_width(), new_zoom);
        var new_height = util.scaleValue(this.img_object.orig_height(), new_zoom);
        var new_x = util.scaleValue( util.descaleValue(old_x, this.current_zoom), new_zoom);
        var new_y = util.scaleValue( util.descaleValue(old_y, this.current_zoom), new_zoom);

        new_x = this.options.width/2 - new_x;
        new_y = this.options.height/2 - new_y;

        this.img_object.display_width(new_width);
        this.img_object.display_height(new_height);

        var coords = this._correctCoords( new_x, new_y ),
            self = this;

        this.img_object.setImageProps(new_width, new_height, coords.x, coords.y,
                                        skip_animation, function() {
            self._trigger('onAfterZoom', 0, new_zoom );
        });
        this.current_zoom = new_zoom;

        this.update_status();
    },

    /**
    * changes zoom scale by delta
    * zoom is calculated by formula: zoom_base * zoom_delta^rate
    * @param Integer delta number to add to the current multiplier rate number
    **/
    zoom_by: function(delta)
    {
        var closest_rate = this.find_closest_zoom_rate(this.current_zoom);

        var next_rate = closest_rate + delta;
        var next_zoom = this.options.zoom_base * Math.pow(this.options.zoom_delta, next_rate)
        if(delta > 0 && next_zoom < this.current_zoom)
        {
            next_zoom *= this.options.zoom_delta;
        }

        if(delta < 0 && next_zoom > this.current_zoom)
        {
            next_zoom /= this.options.zoom_delta;
        }

        this.set_zoom(next_zoom);
    },

    /**
    * Rotate image
    * @param {num} deg Degrees amount to rotate. Positive values rotate image clockwise.
    *     Currently 0, 90, 180, 270 and -90, -180, -270 values are supported
    *
    * @param {boolean} abs If the flag is true if, the deg parameter will be considered as
    *     a absolute value and relative otherwise.
    * @return {num|null} Method will return current image angle if called without any arguments.
    **/
    angle: function(deg, abs) {
        if (arguments.length === 0) { return this.img_object.angle(); }

        if (deg < -270 || deg > 270 || deg % 90 !== 0) { return; }
        if (!abs) { deg += this.img_object.angle(); }
        if (deg < 0) { deg += 360; }
        if (deg >= 360) { deg -= 360; }

        if (deg === this.img_object.angle()) { return; }

        this.img_object.angle(deg);
        //the rotate behavior is different in all editors. For now we  just center the
        //image. However, it will be better to try to keep the position.
        this.center();
        this._trigger('angle', 0, { angle: this.img_object.angle() });
    },

    /**
    * finds closest multiplier rate for value
    * basing on zoom_base and zoom_delta values from settings
    * @param Number value zoom value to examine
    **/
    find_closest_zoom_rate: function(value)
    {
        if(value == this.options.zoom_base)
        {
            return 0;
        }

        function div(val1,val2) { return val1 / val2 };
        function mul(val1,val2) { return val1 * val2 };

        var func = (value > this.options.zoom_base)?mul:div;
        var sgn = (value > this.options.zoom_base)?1:-1;

        var mltplr = this.options.zoom_delta;
        var rate = 1;

        while(Math.abs(func(this.options.zoom_base, Math.pow(mltplr,rate)) - value) >
              Math.abs(func(this.options.zoom_base, Math.pow(mltplr,rate+1)) - value))
        {
            rate++;
        }

        return sgn * rate;
    },

    /* update scale info in the container */
    update_status: function()
    {
        if(!this.options.ui_disabled)
        {
            var percent = Math.round(100*this.img_object.display_height()/this.img_object.orig_height());
            if(percent)
            {
                this.zoom_object.html(percent + "%");
            }
        }
    },

    /**
     * Get some information about the image.
     *     Currently orig_(width|height), display_(width|height), angle, zoom and src params are supported.
     *
     *  @param {string} parameter to check
     *  @param {boolean} withoutRotation if param is orig_width or orig_height and this flag is set to true,
     *      method will return original image width without considering rotation.
     *
     */
    info: function(param, withoutRotation) {
        if (!param) { return; }

        switch (param) {
            case 'orig_width':
            case 'orig_height':
                if (withoutRotation) {
                    return (this.img_object.angle() % 180 === 0 ? this.img_object[param]() :
                            param === 'orig_width' ? this.img_object.orig_height() : 
                                                        this.img_object.orig_width());
                } else {
                    return this.img_object[param]();
                }
            case 'display_width':
            case 'display_height':
            case 'angle':
                return this.img_object[param]();
            case 'zoom':
                return this.current_zoom;
            case 'src':
                return this.img_object.object().attr('src');
        }
    },

    /**
    *   callback for handling mousdown event to start dragging image
    **/
    _mouseStart: function( e )
    {
        $.ui.mouse.prototype._mouseStart.call(this, e);
        if (this._trigger('onStartDrag', 0, this._getMouseCoords(e)) === false) {
            return false;
        }

        /* start drag event*/
        this.container.addClass("iviewer_drag_cursor");

        this.dx = e.pageX - this.img_object.x();
        this.dy = e.pageY - this.img_object.y();
        return true;
    },

    _mouseCapture: function( e ) {
        return true;
    },

    /**
     * Handle mouse move if needed. User can avoid using this callback, because
     *    he can get the same information through public methods.
     *  @param {jQuery.Event} e
     */
    _handleMouseMove: function(e) {
        this._trigger('onMouseMove', e, this._getMouseCoords(e));
    },

    /**
    *   callback for handling mousemove event to drag image
    **/
    _mouseDrag: function(e)
    {
        $.ui.mouse.prototype._mouseDrag.call(this, e);
        var ltop =  e.pageY - this.dy;
        var lleft = e.pageX - this.dx;

        this.setCoords(lleft, ltop);
        this._trigger('onDrag', e, this._getMouseCoords(e));
        return false;
    },

    /**
    *   callback for handling stop drag
    **/
    _mouseStop: function(e)
    {
        $.ui.mouse.prototype._mouseStop.call(this, e);
        this.container.removeClass("iviewer_drag_cursor");
        this._trigger('onStopDrag', 0, this._getMouseCoords(e));
    },

    _click: function(e)
    {
        this._trigger('onClick', 0, this._getMouseCoords(e));
    },

    /**
    *   create zoom buttons info box
    **/
    createui: function()
    {
        var me=this;

        $("<div>", { 'class': "iviewer_zoom_in iviewer_common iviewer_button"})
                    .bind('mousedown touchstart',function(){me.zoom_by(1); return false;})
                    .appendTo(this.container);

        $("<div>", { 'class': "iviewer_zoom_out iviewer_common iviewer_button"})
                    .bind('mousedown touchstart',function(){me.zoom_by(- 1); return false;})
                    .appendTo(this.container);

        $("<div>", { 'class': "iviewer_zoom_zero iviewer_common iviewer_button"})
                    .bind('mousedown touchstart',function(){me.set_zoom(100); return false;})
                    .appendTo(this.container);

        $("<div>", { 'class': "iviewer_zoom_fit iviewer_common iviewer_button"})
                    .bind('mousedown touchstart',function(){me.fit(this); return false;})
                    .appendTo(this.container);

        this.zoom_object = $("<div>").addClass("iviewer_zoom_status iviewer_common")
                                    .appendTo(this.container);

        $("<div>", { 'class': "iviewer_rotate_left iviewer_common iviewer_button"})
                    .bind('mousedown touchstart',function(){me.angle(-90); return false;})
                    .appendTo(this.container);

        $("<div>", { 'class': "iviewer_rotate_right iviewer_common iviewer_button" })
                    .bind('mousedown touchstart',function(){me.angle(90); return false;})
                    .appendTo(this.container);

        this.update_status(); //initial status update
    }

} );

/**
 * @class $.ui.iviewer.ImageObject Class represents image and provides public api without
 *     extending image prototype.
 * @constructor
 * @param {boolean} do_anim Do we want to animate image on dimension changes?
 */
$.ui.iviewer.ImageObject = function(do_anim) {
    this._img = $("<img>")
            //this is needed, because chromium sets them auto otherwise
            .css({ position: "absolute", top :"0px", left: "0px"});

    this._loaded = false;
    this._swapDimensions = false;
    this._do_anim = do_anim || false;
    this.x(0, true);
    this.y(0, true);
    this.angle(0);
};


/** @lends $.ui.iviewer.ImageObject.prototype */
(function() {
    /**
     * Restore initial object state.
     *
     * @param {number} w Image width.
     * @param {number} h Image height.
     */
    this._reset = function(w, h) {
        this._angle = 0;
        this._swapDimensions = false;
        this.x(0);
        this.y(0);

        this.orig_width(w);
        this.orig_height(h);
        this.display_width(w);
        this.display_height(h);
    };

    /**
     * Check if image is loaded.
     *
     * @return {boolean}
     */
    this.loaded = function() { return this._loaded; };

    /**
     * Load image.
     *
     * @param {string} src Image url.
     * @param {Function=} loaded Function will be called on image load.
     */
    this.load = function(src, loaded) {
        var self = this;

        loaded = loaded || jQuery.noop;
        this._loaded = false;

        //If we assign new image url to the this._img IE9 fires onload event and image width and
        //height are set to zero. So, we create another image object and load image through it.
        var img = new Image();
        img.onload = function() {
            self._loaded = true;
            self._reset(this.width, this.height);

            self._img[0].src = src;
            loaded();
        };
        img.src = src;

        this._img
            .removeAttr("src")
            .removeAttr("width")
            .removeAttr("height")
            .removeAttr("style")
            .css({ position: "absolute", top :"0px", left: "0px"})

        this.angle(0);
    };

    this._dimension = function(prefix, name) {
        var horiz = '_' + prefix + '_' + name,
            vert = '_' + prefix + '_' + (name === 'height' ? 'width' : 'height');
        return setter(function(val) {
                this[this._swapDimensions ? horiz: vert] = val;
            },
            function() {
                return this[this._swapDimensions ? horiz: vert];
            });
    };

    /**
     * Getters and setter for common image dimensions.
     *    display_ means real image tag dimensions
     *    orig_ means physical image dimensions.
     *  Note, that dimensions are swapped if image is rotated. It necessary,
     *  because as little as possible code should know about rotation.
     */
    this.display_width = this._dimension('display', 'width'),
    this.display_height = this._dimension('display', 'height'),
    this.display_diff = function() { return Math.floor( this.display_width() - this.display_height() ) };
    this.orig_width = this._dimension('orig', 'width'),
    this.orig_height = this._dimension('orig', 'height'),

    /**
     * Setter for  X coordinate. If image is rotated we need to additionaly shift an
     *     image to map image coordinate to the visual position.
     *
     * @param {number} val Coordinate value.
     * @param {boolean} skipCss If true, we only set the value and do not touch the dom.
     */
    this.x = setter(function(val, skipCss) { 
            this._x = val;
            if (!skipCss) {
                this._img.css("left",this._x + (this._swapDimensions ? this.display_diff() / 2 : 0) + "px");
            }
        },
        function() {
            return this._x;
        });

    /**
     * Setter for  Y coordinate. If image is rotated we need to additionaly shift an
     *     image to map image coordinate to the visual position.
     *
     * @param {number} val Coordinate value.
     * @param {boolean} skipCss If true, we only set the value and do not touch the dom.
     */
    this.y = setter(function(val, skipCss) {
            this._y = val;
            if (!skipCss) {
                this._img.css("top",this._y - (this._swapDimensions ? this.display_diff() / 2 : 0) + "px");
            }
        },
       function() {
            return this._y;
       });

    /**
     * Perform image rotation.
     *
     * @param {number} deg Absolute image angle. The method will work with values 0, 90, 180, 270 degrees.
     */
    this.angle = setter(function(deg) {
            var prevSwap = this._swapDimensions;

            this._angle = deg;
            this._swapDimensions = deg % 180 !== 0;
            
            if (prevSwap !== this._swapDimensions) {
                var verticalMod = this._swapDimensions ? -1 : 1;
                this.x(this.x() - verticalMod * this.display_diff() / 2, true);
                this.y(this.y() + verticalMod * this.display_diff() / 2, true);
            };

            var cssVal = 'rotate(' + deg + 'deg)',
                img = this._img;

            jQuery.each(['', '-webkit-', '-moz-', '-o-', '-ms-'], function(i, prefix) {
                img.css(prefix + 'transform', cssVal);
            });

            if (useIeTransforms) {
                jQuery.each(['-ms-', ''], function(i, prefix) {
                    img.css(prefix + 'filter', ieTransforms[deg].filter);
                });

                img.css({
                    marginLeft: ieTransforms[deg].marginLeft * this.display_diff() / 2,
                    marginTop: ieTransforms[deg].marginTop * this.display_diff() / 2
                });
            }
        },
       function() { return this._angle; });

    /**
     * Map point in the container coordinates to the point in image coordinates.
     *     You will get coordinates of point on image with respect to rotation,
     *     but will be set as if image was not rotated.
     *     So, if image was rotated 90 degrees, it's (0,0) point will be on the
     *     top right corner.
     *
     * @param {{x: number, y: number}} point Point in container coordinates.
     * @return  {{x: number, y: number}}
     */
    this.toOriginalCoords = function(point) {
        switch (this.angle()) {
            case 0: return { x: point.x, y: point.y }
            case 90: return { x: point.y, y: this.display_width() - point.x }
            case 180: return { x: this.display_width() - point.x, y: this.display_height() - point.y }
            case 270: return { x: this.display_height() - point.y, y: point.x }
        }
    };

    /**
     * Map point in the image coordinates to the point in container coordinates.
     *     You will get coordinates of point on container with respect to rotation.
     *     Note, if image was rotated 90 degrees, it's (0,0) point will be on the
     *     top right corner.
     *
     * @param {{x: number, y: number}} point Point in container coordinates.
     * @return  {{x: number, y: number}}
     */
    this.toRealCoords = function(point) {
        switch (this.angle()) {
            case 0: return { x: this.x() + point.x, y: this.y() + point.y }
            case 90: return { x: this.x() + this.display_width() - point.y, y: this.y() + point.x}
            case 180: return { x: this.x() + this.display_width() - point.x, y: this.y() + this.display_height() - point.y}
            case 270: return { x: this.x() + point.y, y: this.y() + this.display_height() - point.x}
        }
    };

    /**
     * @return {jQuery} Return image node. this is needed to add event handlers.
     */
    this.object = setter(jQuery.noop,
                           function() { return this._img; });

    /**
     * Change image properties.
     *
     * @param {number} disp_w Display width;
     * @param {number} disp_h Display height;
     * @param {number} x
     * @param {number} y
     * @param {boolean} skip_animation If true, the animation will be skiped despite the
     *     value set in constructor.
     * @param {Function=} complete Call back will be fired when zoom will be complete.
     */
    this.setImageProps = function(disp_w, disp_h, x, y, skip_animation, complete) {
        complete = complete || jQuery.noop;

        this.display_width(disp_w);
        this.display_height(disp_h);
        this.x(x, true);
        this.y(y, true);

        var w = this._swapDimensions ? disp_h : disp_w;
        var h = this._swapDimensions ? disp_w : disp_h;

        var params = {
            width: w,
            height: h,
            top: y - (this._swapDimensions ? this.display_diff() / 2 : 0) + "px",
            left: x + (this._swapDimensions ? this.display_diff() / 2 : 0) + "px" 
        };

        if (useIeTransforms) {
            jQuery.extend(params, {
                marginLeft: ieTransforms[this.angle()].marginLeft * this.display_diff() / 2,
                marginTop: ieTransforms[this.angle()].marginTop * this.display_diff() / 2
            });
        }

        var swapDims = this._swapDimensions,
            img = this._img;

        //here we come: another IE oddness. If image is rotated 90 degrees with a filter, than
        //width and height getters return real width and height of rotated image. The bad news
        //is that to set height you need to set a width and vice versa. Fuck IE.
        //So, in this case we have to animate width and height manually.
        if(useIeTransforms && swapDims) {
            var ieh = this._img.width(),
                iew = this._img.height(),
                iedh = params.height - ieh;
                iedw = params.width - iew;

            delete params.width;
            delete params.height;
        }

        if (this._do_anim && !skip_animation) {
            this._img.animate(params, {
                duration: 200, 
                complete: complete,
                step: function(now, fx) {
                    if(useIeTransforms && swapDims && (fx.prop === 'top')) {
                        var percent = (now - fx.start) / (fx.end - fx.start);

                        img.height(ieh + iedh * percent);
                        img.width(iew + iedw * percent);
                        img.css('top', now);
                    }
                }
            });
        } else {
            this._img.css(params);
            setTimeout(complete, 0); //both if branches should behave equally.
        }
    };

}).apply($.ui.iviewer.ImageObject.prototype);



var util = {
    scaleValue: function(value, toZoom)
    {
        return value * toZoom / 100;
    },

    descaleValue: function(value, fromZoom)
    {
        return value * 100 / fromZoom;
    }
};

 } )( jQuery, undefined );
/*
 * jQuery Tools 1.2.5 - The missing UI library for the Web
 *
 * [toolbox.flashembed, toolbox.history, toolbox.expose, toolbox.mousewheel, tabs, tabs.slideshow, tooltip, tooltip.slide, tooltip.dynamic, scrollable, scrollable.autoscroll, scrollable.navigator, overlay, overlay.apple, dateinput, rangeinput, validator]
 *
 * NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
 *
 * http://flowplayer.org/tools/
 *
 * jquery.event.wheel.js - rev 1
 * Copyright (c) 2008, Three Dub Media (http://threedubmedia.com)
 * Liscensed under the MIT License (MIT-LICENSE.txt)
 * http://www.opensource.org/licenses/mit-license.php
 * Created: 2008-07-01 | Updated: 2008-07-14
 *
 * -----
 *
 * File generated: Wed Sep 22 06:12:53 GMT 2010
 */
(function(){function f(a,b){if(b)for(var c in b)if(b.hasOwnProperty(c))a[c]=b[c];return a}function l(a,b){var c=[];for(var d in a)if(a.hasOwnProperty(d))c[d]=b(a[d]);return c}function m(a,b,c){if(e.isSupported(b.version))a.innerHTML=e.getHTML(b,c);else if(b.expressInstall&&e.isSupported([6,65]))a.innerHTML=e.getHTML(f(b,{src:b.expressInstall}),{MMredirectURL:location.href,MMplayerType:"PlugIn",MMdoctitle:document.title});else{if(!a.innerHTML.replace(/\s/g,"")){a.innerHTML="<h2>Flash version "+b.version+
" or greater is required</h2><h3>"+(g[0]>0?"Your version is "+g:"You have no flash plugin installed")+"</h3>"+(a.tagName=="A"?"<p>Click here to download latest version</p>":"<p>Download latest version from <a href='"+k+"'>here</a></p>");if(a.tagName=="A")a.onclick=function(){location.href=k}}if(b.onFail){var d=b.onFail.call(this);if(typeof d=="string")a.innerHTML=d}}if(i)window[b.id]=document.getElementById(b.id);f(this,{getRoot:function(){return a},getOptions:function(){return b},getConf:function(){return c},
getApi:function(){return a.firstChild}})}var i=document.all,k="http://www.adobe.com/go/getflashplayer",n=typeof jQuery=="function",o=/(\d+)[^\d]+(\d+)[^\d]*(\d*)/,j={width:"100%",height:"100%",id:"_"+(""+Math.random()).slice(9),allowfullscreen:true,allowscriptaccess:"always",quality:"high",version:[3,0],onFail:null,expressInstall:null,w3c:false,cachebusting:false};window.attachEvent&&window.attachEvent("onbeforeunload",function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){}});
window.flashembed=function(a,b,c){if(typeof a=="string")a=document.getElementById(a.replace("#",""));if(a){if(typeof b=="string")b={src:b};return new m(a,f(f({},j),b),c)}};var e=f(window.flashembed,{conf:j,getVersion:function(){var a,b;try{b=navigator.plugins["Shockwave Flash"].description.slice(16)}catch(c){try{b=(a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7"))&&a.GetVariable("$version")}catch(d){try{b=(a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6"))&&a.GetVariable("$version")}catch(h){}}}return(b=
o.exec(b))?[b[1],b[3]]:[0,0]},asString:function(a){if(a===null||a===undefined)return null;var b=typeof a;if(b=="object"&&a.push)b="array";switch(b){case "string":a=a.replace(new RegExp('(["\\\\])',"g"),"\\$1");a=a.replace(/^\s?(\d+\.?\d+)%/,"$1pct");return'"'+a+'"';case "array":return"["+l(a,function(d){return e.asString(d)}).join(",")+"]";case "function":return'"function()"';case "object":b=[];for(var c in a)a.hasOwnProperty(c)&&b.push('"'+c+'":'+e.asString(a[c]));return"{"+b.join(",")+"}"}return String(a).replace(/\s/g,
" ").replace(/\'/g,'"')},getHTML:function(a,b){a=f({},a);var c='<object width="'+a.width+'" height="'+a.height+'" id="'+a.id+'" name="'+a.id+'"';if(a.cachebusting)a.src+=(a.src.indexOf("?")!=-1?"&":"?")+Math.random();c+=a.w3c||!i?' data="'+a.src+'" type="application/x-shockwave-flash"':' classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"';c+=">";if(a.w3c||i)c+='<param name="movie" value="'+a.src+'" />';a.width=a.height=a.id=a.w3c=a.src=null;a.onFail=a.version=a.expressInstall=null;for(var d in a)if(a[d])c+=
'<param name="'+d+'" value="'+a[d]+'" />';a="";if(b){for(var h in b)if(b[h]){d=b[h];a+=h+"="+(/function|object/.test(typeof d)?e.asString(d):d)+"&"}a=a.slice(0,-1);c+='<param name="flashvars" value=\''+a+"' />"}c+="</object>";return c},isSupported:function(a){return g[0]>a[0]||g[0]==a[0]&&g[1]>=a[1]}}),g=e.getVersion();if(n){jQuery.tools=jQuery.tools||{version:"1.2.5"};jQuery.tools.flashembed={conf:j};jQuery.fn.flashembed=function(a,b){return this.each(function(){$(this).data("flashembed",flashembed(this,
a,b))})}}})();
(function(b){function h(c){if(c){var a=d.contentWindow.document;a.open().close();a.location.hash=c}}var g,d,f,i;b.tools=b.tools||{version:"1.2.5"};b.tools.history={init:function(c){if(!i){if(b.browser.msie&&b.browser.version<"8"){if(!d){d=b("<iframe/>").attr("src","javascript:false;").hide().get(0);b("body").append(d);setInterval(function(){var a=d.contentWindow.document;a=a.location.hash;g!==a&&b.event.trigger("hash",a)},100);h(location.hash||"#")}}else setInterval(function(){var a=location.hash;
a!==g&&b.event.trigger("hash",a)},100);f=!f?c:f.add(c);c.click(function(a){var e=b(this).attr("href");d&&h(e);if(e.slice(0,1)!="#"){location.href="#"+e;return a.preventDefault()}});i=true}}};b(window).bind("hash",function(c,a){a?f.filter(function(){var e=b(this).attr("href");return e==a||e==a.replace("#","")}).trigger("history",[a]):f.eq(0).trigger("history",[a]);g=a});b.fn.history=function(c){b.tools.history.init(this);return this.bind("history",c)}})(jQuery);
(function(b){function k(){if(b.browser.msie){var a=b(document).height(),d=b(window).height();return[window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth,a-d<20?d:a]}return[b(document).width(),b(document).height()]}function h(a){if(a)return a.call(b.mask)}b.tools=b.tools||{version:"1.2.5"};var l;l=b.tools.expose={conf:{maskId:"exposeMask",loadSpeed:"slow",closeSpeed:"fast",closeOnClick:true,closeOnEsc:true,zIndex:9998,opacity:0.8,startOpacity:0,color:"#fff",onLoad:null,
onClose:null}};var c,i,e,g,j;b.mask={load:function(a,d){if(e)return this;if(typeof a=="string")a={color:a};a=a||g;g=a=b.extend(b.extend({},l.conf),a);c=b("#"+a.maskId);if(!c.length){c=b("<div/>").attr("id",a.maskId);b("body").append(c)}var m=k();c.css({position:"absolute",top:0,left:0,width:m[0],height:m[1],display:"none",opacity:a.startOpacity,zIndex:a.zIndex});a.color&&c.css("backgroundColor",a.color);if(h(a.onBeforeLoad)===false)return this;a.closeOnEsc&&b(document).bind("keydown.mask",function(f){f.keyCode==
27&&b.mask.close(f)});a.closeOnClick&&c.bind("click.mask",function(f){b.mask.close(f)});b(window).bind("resize.mask",function(){b.mask.fit()});if(d&&d.length){j=d.eq(0).css("zIndex");b.each(d,function(){var f=b(this);/relative|absolute|fixed/i.test(f.css("position"))||f.css("position","relative")});i=d.css({zIndex:Math.max(a.zIndex+1,j=="auto"?0:j)})}c.css({display:"block"}).fadeTo(a.loadSpeed,a.opacity,function(){b.mask.fit();h(a.onLoad);e="full"});e=true;return this},close:function(){if(e){if(h(g.onBeforeClose)===
false)return this;c.fadeOut(g.closeSpeed,function(){h(g.onClose);i&&i.css({zIndex:j});e=false});b(document).unbind("keydown.mask");c.unbind("click.mask");b(window).unbind("resize.mask")}return this},fit:function(){if(e){var a=k();c.css({width:a[0],height:a[1]})}},getMask:function(){return c},isLoaded:function(a){return a?e=="full":e},getConf:function(){return g},getExposed:function(){return i}};b.fn.mask=function(a){b.mask.load(a);return this};b.fn.expose=function(a){b.mask.load(a,this);return this}})(jQuery);
(function(b){function c(a){switch(a.type){case "mousemove":return b.extend(a.data,{clientX:a.clientX,clientY:a.clientY,pageX:a.pageX,pageY:a.pageY});case "DOMMouseScroll":b.extend(a,a.data);a.delta=-a.detail/3;break;case "mousewheel":a.delta=a.wheelDelta/120;break}a.type="wheel";return b.event.handle.call(this,a,a.delta)}b.fn.mousewheel=function(a){return this[a?"bind":"trigger"]("wheel",a)};b.event.special.wheel={setup:function(){b.event.add(this,d,c,{})},teardown:function(){b.event.remove(this,
d,c)}};var d=!b.browser.mozilla?"mousewheel":"DOMMouseScroll"+(b.browser.version<"1.9"?" mousemove":"")})(jQuery);
(function(c){function p(d,b,a){var e=this,l=d.add(this),h=d.find(a.tabs),i=b.jquery?b:d.children(b),j;h.length||(h=d.children());i.length||(i=d.parent().find(b));i.length||(i=c(b));c.extend(this,{click:function(f,g){var k=h.eq(f);if(typeof f=="string"&&f.replace("#","")){k=h.filter("[href*="+f.replace("#","")+"]");f=Math.max(h.index(k),0)}if(a.rotate){var n=h.length-1;if(f<0)return e.click(n,g);if(f>n)return e.click(0,g)}if(!k.length){if(j>=0)return e;f=a.initialIndex;k=h.eq(f)}if(f===j)return e;
g=g||c.Event();g.type="onBeforeClick";l.trigger(g,[f]);if(!g.isDefaultPrevented()){o[a.effect].call(e,f,function(){g.type="onClick";l.trigger(g,[f])});j=f;h.removeClass(a.current);k.addClass(a.current);return e}},getConf:function(){return a},getTabs:function(){return h},getPanes:function(){return i},getCurrentPane:function(){return i.eq(j)},getCurrentTab:function(){return h.eq(j)},getIndex:function(){return j},next:function(){return e.click(j+1)},prev:function(){return e.click(j-1)},destroy:function(){h.unbind(a.event).removeClass(a.current);
i.find("a[href^=#]").unbind("click.T");return e}});c.each("onBeforeClick,onClick".split(","),function(f,g){c.isFunction(a[g])&&c(e).bind(g,a[g]);e[g]=function(k){k&&c(e).bind(g,k);return e}});if(a.history&&c.fn.history){c.tools.history.init(h);a.event="history"}h.each(function(f){c(this).bind(a.event,function(g){e.click(f,g);return g.preventDefault()})});i.find("a[href^=#]").bind("click.T",function(f){e.click(c(this).attr("href"),f)});if(location.hash&&a.tabs=="a"&&d.find("[href="+location.hash+"]").length)e.click(location.hash);
else if(a.initialIndex===0||a.initialIndex>0)e.click(a.initialIndex)}c.tools=c.tools||{version:"1.2.5"};c.tools.tabs={conf:{tabs:"a",current:"current",onBeforeClick:null,onClick:null,effect:"default",initialIndex:0,event:"click",rotate:false,history:false},addEffect:function(d,b){o[d]=b}};var o={"default":function(d,b){this.getPanes().hide().eq(d).show();b.call()},fade:function(d,b){var a=this.getConf(),e=a.fadeOutSpeed,l=this.getPanes();e?l.fadeOut(e):l.hide();l.eq(d).fadeIn(a.fadeInSpeed,b)},slide:function(d,
b){this.getPanes().slideUp(200);this.getPanes().eq(d).slideDown(400,b)},ajax:function(d,b){this.getPanes().eq(0).load(this.getTabs().eq(d).attr("href"),b)}},m;c.tools.tabs.addEffect("horizontal",function(d,b){m||(m=this.getPanes().eq(0).width());this.getCurrentPane().animate({width:0},function(){c(this).hide()});this.getPanes().eq(d).animate({width:m},function(){c(this).show();b.call()})});c.fn.tabs=function(d,b){var a=this.data("tabs");if(a){a.destroy();this.removeData("tabs")}if(c.isFunction(b))b=
{onBeforeClick:b};b=c.extend({},c.tools.tabs.conf,b);this.each(function(){a=new p(c(this),d,b);c(this).data("tabs",a)});return b.api?a:this}})(jQuery);
(function(c){function p(g,a){function m(f){var e=c(f);return e.length<2?e:g.parent().find(f)}var b=this,i=g.add(this),d=g.data("tabs"),h,j=true,n=m(a.next).click(function(){d.next()}),k=m(a.prev).click(function(){d.prev()});c.extend(b,{getTabs:function(){return d},getConf:function(){return a},play:function(){if(h)return b;var f=c.Event("onBeforePlay");i.trigger(f);if(f.isDefaultPrevented())return b;h=setInterval(d.next,a.interval);j=false;i.trigger("onPlay");return b},pause:function(){if(!h)return b;
var f=c.Event("onBeforePause");i.trigger(f);if(f.isDefaultPrevented())return b;h=clearInterval(h);i.trigger("onPause");return b},stop:function(){b.pause();j=true}});c.each("onBeforePlay,onPlay,onBeforePause,onPause".split(","),function(f,e){c.isFunction(a[e])&&c(b).bind(e,a[e]);b[e]=function(q){return c(b).bind(e,q)}});a.autopause&&d.getTabs().add(n).add(k).add(d.getPanes()).hover(b.pause,function(){j||b.play()});a.autoplay&&b.play();a.clickable&&d.getPanes().click(function(){d.next()});if(!d.getConf().rotate){var l=
a.disabledClass;d.getIndex()||k.addClass(l);d.onBeforeClick(function(f,e){k.toggleClass(l,!e);n.toggleClass(l,e==d.getTabs().length-1)})}}var o;o=c.tools.tabs.slideshow={conf:{next:".forward",prev:".backward",disabledClass:"disabled",autoplay:false,autopause:true,interval:3E3,clickable:true,api:false}};c.fn.slideshow=function(g){var a=this.data("slideshow");if(a)return a;g=c.extend({},o.conf,g);this.each(function(){a=new p(c(this),g);c(this).data("slideshow",a)});return g.api?a:this}})(jQuery);
(function(f){function p(a,b,c){var h=c.relative?a.position().top:a.offset().top,d=c.relative?a.position().left:a.offset().left,i=c.position[0];h-=b.outerHeight()-c.offset[0];d+=a.outerWidth()+c.offset[1];if(/iPad/i.test(navigator.userAgent))h-=f(window).scrollTop();var j=b.outerHeight()+a.outerHeight();if(i=="center")h+=j/2;if(i=="bottom")h+=j;i=c.position[1];a=b.outerWidth()+a.outerWidth();if(i=="center")d-=a/2;if(i=="left")d-=a;return{top:h,left:d}}function u(a,b){var c=this,h=a.add(c),d,i=0,j=
0,m=a.attr("title"),q=a.attr("data-tooltip"),r=o[b.effect],l,s=a.is(":input"),v=s&&a.is(":checkbox, :radio, select, :button, :submit"),t=a.attr("type"),k=b.events[t]||b.events[s?v?"widget":"input":"def"];if(!r)throw'Nonexistent effect "'+b.effect+'"';k=k.split(/,\s*/);if(k.length!=2)throw"Tooltip: bad events configuration for "+t;a.bind(k[0],function(e){clearTimeout(i);if(b.predelay)j=setTimeout(function(){c.show(e)},b.predelay);else c.show(e)}).bind(k[1],function(e){clearTimeout(j);if(b.delay)i=
setTimeout(function(){c.hide(e)},b.delay);else c.hide(e)});if(m&&b.cancelDefault){a.removeAttr("title");a.data("title",m)}f.extend(c,{show:function(e){if(!d){if(q)d=f(q);else if(b.tip)d=f(b.tip).eq(0);else if(m)d=f(b.layout).addClass(b.tipClass).appendTo(document.body).hide().append(m);else{d=a.next();d.length||(d=a.parent().next())}if(!d.length)throw"Cannot find tooltip for "+a;}if(c.isShown())return c;d.stop(true,true);var g=p(a,d,b);b.tip&&d.html(a.data("title"));e=e||f.Event();e.type="onBeforeShow";
h.trigger(e,[g]);if(e.isDefaultPrevented())return c;g=p(a,d,b);d.css({position:"absolute",top:g.top,left:g.left});l=true;r[0].call(c,function(){e.type="onShow";l="full";h.trigger(e)});g=b.events.tooltip.split(/,\s*/);if(!d.data("__set")){d.bind(g[0],function(){clearTimeout(i);clearTimeout(j)});g[1]&&!a.is("input:not(:checkbox, :radio), textarea")&&d.bind(g[1],function(n){n.relatedTarget!=a[0]&&a.trigger(k[1].split(" ")[0])});d.data("__set",true)}return c},hide:function(e){if(!d||!c.isShown())return c;
e=e||f.Event();e.type="onBeforeHide";h.trigger(e);if(!e.isDefaultPrevented()){l=false;o[b.effect][1].call(c,function(){e.type="onHide";h.trigger(e)});return c}},isShown:function(e){return e?l=="full":l},getConf:function(){return b},getTip:function(){return d},getTrigger:function(){return a}});f.each("onHide,onBeforeShow,onShow,onBeforeHide".split(","),function(e,g){f.isFunction(b[g])&&f(c).bind(g,b[g]);c[g]=function(n){n&&f(c).bind(g,n);return c}})}f.tools=f.tools||{version:"1.2.5"};f.tools.tooltip=
{conf:{effect:"toggle",fadeOutSpeed:"fast",predelay:0,delay:30,opacity:1,tip:0,position:["top","center"],offset:[0,0],relative:false,cancelDefault:true,events:{def:"mouseenter,mouseleave",input:"focus,blur",widget:"focus mouseenter,blur mouseleave",tooltip:"mouseenter,mouseleave"},layout:"<div/>",tipClass:"tooltip"},addEffect:function(a,b,c){o[a]=[b,c]}};var o={toggle:[function(a){var b=this.getConf(),c=this.getTip();b=b.opacity;b<1&&c.css({opacity:b});c.show();a.call()},function(a){this.getTip().hide();
a.call()}],fade:[function(a){var b=this.getConf();this.getTip().fadeTo(b.fadeInSpeed,b.opacity,a)},function(a){this.getTip().fadeOut(this.getConf().fadeOutSpeed,a)}]};f.fn.tooltip=function(a){var b=this.data("tooltip");if(b)return b;a=f.extend(true,{},f.tools.tooltip.conf,a);if(typeof a.position=="string")a.position=a.position.split(/,?\s/);this.each(function(){b=new u(f(this),a);f(this).data("tooltip",b)});return a.api?b:this}})(jQuery);
(function(d){var i=d.tools.tooltip;d.extend(i.conf,{direction:"up",bounce:false,slideOffset:10,slideInSpeed:200,slideOutSpeed:200,slideFade:!d.browser.msie});var e={up:["-","top"],down:["+","top"],left:["-","left"],right:["+","left"]};i.addEffect("slide",function(g){var a=this.getConf(),f=this.getTip(),b=a.slideFade?{opacity:a.opacity}:{},c=e[a.direction]||e.up;b[c[1]]=c[0]+"="+a.slideOffset;a.slideFade&&f.css({opacity:0});f.show().animate(b,a.slideInSpeed,g)},function(g){var a=this.getConf(),f=a.slideOffset,
b=a.slideFade?{opacity:0}:{},c=e[a.direction]||e.up,h=""+c[0];if(a.bounce)h=h=="+"?"-":"+";b[c[1]]=h+"="+f;this.getTip().animate(b,a.slideOutSpeed,function(){d(this).hide();g.call()})})})(jQuery);
(function(g){function j(a){var c=g(window),d=c.width()+c.scrollLeft(),h=c.height()+c.scrollTop();return[a.offset().top<=c.scrollTop(),d<=a.offset().left+a.width(),h<=a.offset().top+a.height(),c.scrollLeft()>=a.offset().left]}function k(a){for(var c=a.length;c--;)if(a[c])return false;return true}var i=g.tools.tooltip;i.dynamic={conf:{classNames:"top right bottom left"}};g.fn.dynamic=function(a){if(typeof a=="number")a={speed:a};a=g.extend({},i.dynamic.conf,a);var c=a.classNames.split(/\s/),d;this.each(function(){var h=
g(this).tooltip().onBeforeShow(function(e,f){e=this.getTip();var b=this.getConf();d||(d=[b.position[0],b.position[1],b.offset[0],b.offset[1],g.extend({},b)]);g.extend(b,d[4]);b.position=[d[0],d[1]];b.offset=[d[2],d[3]];e.css({visibility:"hidden",position:"absolute",top:f.top,left:f.left}).show();f=j(e);if(!k(f)){if(f[2]){g.extend(b,a.top);b.position[0]="top";e.addClass(c[0])}if(f[3]){g.extend(b,a.right);b.position[1]="right";e.addClass(c[1])}if(f[0]){g.extend(b,a.bottom);b.position[0]="bottom";e.addClass(c[2])}if(f[1]){g.extend(b,
a.left);b.position[1]="left";e.addClass(c[3])}if(f[0]||f[2])b.offset[0]*=-1;if(f[1]||f[3])b.offset[1]*=-1}e.css({visibility:"visible"}).hide()});h.onBeforeShow(function(){var e=this.getConf();this.getTip();setTimeout(function(){e.position=[d[0],d[1]];e.offset=[d[2],d[3]]},0)});h.onHide(function(){var e=this.getTip();e.removeClass(a.classNames)});ret=h});return a.api?ret:this}})(jQuery);
(function(e){function p(f,c){var b=e(c);return b.length<2?b:f.parent().find(c)}function u(f,c){var b=this,n=f.add(b),g=f.children(),l=0,j=c.vertical;k||(k=b);if(g.length>1)g=e(c.items,f);e.extend(b,{getConf:function(){return c},getIndex:function(){return l},getSize:function(){return b.getItems().size()},getNaviButtons:function(){return o.add(q)},getRoot:function(){return f},getItemWrap:function(){return g},getItems:function(){return g.children(c.item).not("."+c.clonedClass)},move:function(a,d){return b.seekTo(l+
a,d)},next:function(a){return b.move(1,a)},prev:function(a){return b.move(-1,a)},begin:function(a){return b.seekTo(0,a)},end:function(a){return b.seekTo(b.getSize()-1,a)},focus:function(){return k=b},addItem:function(a){a=e(a);if(c.circular){g.children("."+c.clonedClass+":last").before(a);g.children("."+c.clonedClass+":first").replaceWith(a.clone().addClass(c.clonedClass))}else g.append(a);n.trigger("onAddItem",[a]);return b},seekTo:function(a,d,h){a.jquery||(a*=1);if(c.circular&&a===0&&l==-1&&d!==
0)return b;if(!c.circular&&a<0||a>b.getSize()||a<-1)return b;var i=a;if(a.jquery)a=b.getItems().index(a);else i=b.getItems().eq(a);var r=e.Event("onBeforeSeek");if(!h){n.trigger(r,[a,d]);if(r.isDefaultPrevented()||!i.length)return b}i=j?{top:-i.position().top}:{left:-i.position().left};l=a;k=b;if(d===undefined)d=c.speed;g.animate(i,d,c.easing,h||function(){n.trigger("onSeek",[a])});return b}});e.each(["onBeforeSeek","onSeek","onAddItem"],function(a,d){e.isFunction(c[d])&&e(b).bind(d,c[d]);b[d]=function(h){h&&
e(b).bind(d,h);return b}});if(c.circular){var s=b.getItems().slice(-1).clone().prependTo(g),t=b.getItems().eq(1).clone().appendTo(g);s.add(t).addClass(c.clonedClass);b.onBeforeSeek(function(a,d,h){if(!a.isDefaultPrevented())if(d==-1){b.seekTo(s,h,function(){b.end(0)});return a.preventDefault()}else d==b.getSize()&&b.seekTo(t,h,function(){b.begin(0)})});b.seekTo(0,0,function(){})}var o=p(f,c.prev).click(function(){b.prev()}),q=p(f,c.next).click(function(){b.next()});if(!c.circular&&b.getSize()>1){b.onBeforeSeek(function(a,
d){setTimeout(function(){if(!a.isDefaultPrevented()){o.toggleClass(c.disabledClass,d<=0);q.toggleClass(c.disabledClass,d>=b.getSize()-1)}},1)});c.initialIndex||o.addClass(c.disabledClass)}c.mousewheel&&e.fn.mousewheel&&f.mousewheel(function(a,d){if(c.mousewheel){b.move(d<0?1:-1,c.wheelSpeed||50);return false}});if(c.touch){var m={};g[0].ontouchstart=function(a){a=a.touches[0];m.x=a.clientX;m.y=a.clientY};g[0].ontouchmove=function(a){if(a.touches.length==1&&!g.is(":animated")){var d=a.touches[0],h=
m.x-d.clientX;d=m.y-d.clientY;b[j&&d>0||!j&&h>0?"next":"prev"]();a.preventDefault()}}}c.keyboard&&e(document).bind("keydown.scrollable",function(a){if(!(!c.keyboard||a.altKey||a.ctrlKey||e(a.target).is(":input")))if(!(c.keyboard!="static"&&k!=b)){var d=a.keyCode;if(j&&(d==38||d==40)){b.move(d==38?-1:1);return a.preventDefault()}if(!j&&(d==37||d==39)){b.move(d==37?-1:1);return a.preventDefault()}}});c.initialIndex&&b.seekTo(c.initialIndex,0,function(){})}e.tools=e.tools||{version:"1.2.5"};e.tools.scrollable=
{conf:{activeClass:"active",circular:false,clonedClass:"cloned",disabledClass:"disabled",easing:"swing",initialIndex:0,item:null,items:".items",keyboard:true,mousewheel:false,next:".next",prev:".prev",speed:400,vertical:false,touch:true,wheelSpeed:0}};var k;e.fn.scrollable=function(f){var c=this.data("scrollable");if(c)return c;f=e.extend({},e.tools.scrollable.conf,f);this.each(function(){c=new u(e(this),f);e(this).data("scrollable",c)});return f.api?c:this}})(jQuery);
(function(b){var f=b.tools.scrollable;f.autoscroll={conf:{autoplay:true,interval:3E3,autopause:true}};b.fn.autoscroll=function(c){if(typeof c=="number")c={interval:c};var d=b.extend({},f.autoscroll.conf,c),g;this.each(function(){var a=b(this).data("scrollable");if(a)g=a;var e,h=true;a.play=function(){if(!e){h=false;e=setInterval(function(){a.next()},d.interval)}};a.pause=function(){e=clearInterval(e)};a.stop=function(){a.pause();h=true};d.autopause&&a.getRoot().add(a.getNaviButtons()).hover(a.pause,
a.play);d.autoplay&&a.play()});return d.api?g:this}})(jQuery);
(function(d){function p(b,g){var h=d(g);return h.length<2?h:b.parent().find(g)}var m=d.tools.scrollable;m.navigator={conf:{navi:".navi",naviItem:null,activeClass:"active",indexed:false,idPrefix:null,history:false}};d.fn.navigator=function(b){if(typeof b=="string")b={navi:b};b=d.extend({},m.navigator.conf,b);var g;this.each(function(){function h(a,c,i){e.seekTo(c);if(j){if(location.hash)location.hash=a.attr("href").replace("#","")}else return i.preventDefault()}function f(){return k.find(b.naviItem||
"> *")}function n(a){var c=d("<"+(b.naviItem||"a")+"/>").click(function(i){h(d(this),a,i)}).attr("href","#"+a);a===0&&c.addClass(l);b.indexed&&c.text(a+1);b.idPrefix&&c.attr("id",b.idPrefix+a);return c.appendTo(k)}function o(a,c){a=f().eq(c.replace("#",""));a.length||(a=f().filter("[href="+c+"]"));a.click()}var e=d(this).data("scrollable"),k=b.navi.jquery?b.navi:p(e.getRoot(),b.navi),q=e.getNaviButtons(),l=b.activeClass,j=b.history&&d.fn.history;if(e)g=e;e.getNaviButtons=function(){return q.add(k)};
f().length?f().each(function(a){d(this).click(function(c){h(d(this),a,c)})}):d.each(e.getItems(),function(a){n(a)});e.onBeforeSeek(function(a,c){setTimeout(function(){if(!a.isDefaultPrevented()){var i=f().eq(c);!a.isDefaultPrevented()&&i.length&&f().removeClass(l).eq(c).addClass(l)}},1)});e.onAddItem(function(a,c){c=n(e.getItems().index(c));j&&c.history(o)});j&&f().history(o)});return b.api?g:this}})(jQuery);
(function(a){function t(d,b){var c=this,j=d.add(c),o=a(window),k,f,m,g=a.tools.expose&&(b.mask||b.expose),n=Math.random().toString().slice(10);if(g){if(typeof g=="string")g={color:g};g.closeOnClick=g.closeOnEsc=false}var p=b.target||d.attr("rel");f=p?a(p):d;if(!f.length)throw"Could not find Overlay: "+p;d&&d.index(f)==-1&&d.click(function(e){c.load(e);return e.preventDefault()});a.extend(c,{load:function(e){if(c.isOpened())return c;var h=q[b.effect];if(!h)throw'Overlay: cannot find effect : "'+b.effect+
'"';b.oneInstance&&a.each(s,function(){this.close(e)});e=e||a.Event();e.type="onBeforeLoad";j.trigger(e);if(e.isDefaultPrevented())return c;m=true;g&&a(f).expose(g);var i=b.top,r=b.left,u=f.outerWidth({margin:true}),v=f.outerHeight({margin:true});if(typeof i=="string")i=i=="center"?Math.max((o.height()-v)/2,0):parseInt(i,10)/100*o.height();if(r=="center")r=Math.max((o.width()-u)/2,0);h[0].call(c,{top:i,left:r},function(){if(m){e.type="onLoad";j.trigger(e)}});g&&b.closeOnClick&&a.mask.getMask().one("click",
c.close);b.closeOnClick&&a(document).bind("click."+n,function(l){a(l.target).parents(f).length||c.close(l)});b.closeOnEsc&&a(document).bind("keydown."+n,function(l){l.keyCode==27&&c.close(l)});return c},close:function(e){if(!c.isOpened())return c;e=e||a.Event();e.type="onBeforeClose";j.trigger(e);if(!e.isDefaultPrevented()){m=false;q[b.effect][1].call(c,function(){e.type="onClose";j.trigger(e)});a(document).unbind("click."+n).unbind("keydown."+n);g&&a.mask.close();return c}},getOverlay:function(){return f},
getTrigger:function(){return d},getClosers:function(){return k},isOpened:function(){return m},getConf:function(){return b}});a.each("onBeforeLoad,onStart,onLoad,onBeforeClose,onClose".split(","),function(e,h){a.isFunction(b[h])&&a(c).bind(h,b[h]);c[h]=function(i){i&&a(c).bind(h,i);return c}});k=f.find(b.close||".close");if(!k.length&&!b.close){k=a('<a class="close"></a>');f.prepend(k)}k.click(function(e){c.close(e)});b.load&&c.load()}a.tools=a.tools||{version:"1.2.5"};a.tools.overlay={addEffect:function(d,
b,c){q[d]=[b,c]},conf:{close:null,closeOnClick:true,closeOnEsc:true,closeSpeed:"fast",effect:"default",fixed:!a.browser.msie||a.browser.version>6,left:"center",load:false,mask:null,oneInstance:true,speed:"normal",target:null,top:"10%"}};var s=[],q={};a.tools.overlay.addEffect("default",function(d,b){var c=this.getConf(),j=a(window);if(!c.fixed){d.top+=j.scrollTop();d.left+=j.scrollLeft()}d.position=c.fixed?"fixed":"absolute";this.getOverlay().css(d).fadeIn(c.speed,b)},function(d){this.getOverlay().fadeOut(this.getConf().closeSpeed,
d)});a.fn.overlay=function(d){var b=this.data("overlay");if(b)return b;if(a.isFunction(d))d={onBeforeLoad:d};d=a.extend(true,{},a.tools.overlay.conf,d);this.each(function(){b=new t(a(this),d);s.push(b);a(this).data("overlay",b)});return d.api?b:this}})(jQuery);
(function(h){function k(d){var e=d.offset();return{top:e.top+d.height()/2,left:e.left+d.width()/2}}var l=h.tools.overlay,f=h(window);h.extend(l.conf,{start:{top:null,left:null},fadeInSpeed:"fast",zIndex:9999});function o(d,e){var a=this.getOverlay(),c=this.getConf(),g=this.getTrigger(),p=this,m=a.outerWidth({margin:true}),b=a.data("img"),n=c.fixed?"fixed":"absolute";if(!b){b=a.css("backgroundImage");if(!b)throw"background-image CSS property not set for overlay";b=b.slice(b.indexOf("(")+1,b.indexOf(")")).replace(/\"/g,
"");a.css("backgroundImage","none");b=h('<img src="'+b+'"/>');b.css({border:0,display:"none"}).width(m);h("body").append(b);a.data("img",b)}var i=c.start.top||Math.round(f.height()/2),j=c.start.left||Math.round(f.width()/2);if(g){g=k(g);i=g.top;j=g.left}if(c.fixed){i-=f.scrollTop();j-=f.scrollLeft()}else{d.top+=f.scrollTop();d.left+=f.scrollLeft()}b.css({position:"absolute",top:i,left:j,width:0,zIndex:c.zIndex}).show();d.position=n;a.css(d);b.animate({top:a.css("top"),left:a.css("left"),width:m},
c.speed,function(){a.css("zIndex",c.zIndex+1).fadeIn(c.fadeInSpeed,function(){p.isOpened()&&!h(this).index(a)?e.call():a.hide()})}).css("position",n)}function q(d){var e=this.getOverlay().hide(),a=this.getConf(),c=this.getTrigger();e=e.data("img");var g={top:a.start.top,left:a.start.left,width:0};c&&h.extend(g,k(c));a.fixed&&e.css({position:"absolute"}).animate({top:"+="+f.scrollTop(),left:"+="+f.scrollLeft()},0);e.animate(g,a.closeSpeed,d)}l.addEffect("apple",o,q)})(jQuery);
(function(d){function R(a,c){return 32-(new Date(a,c,32)).getDate()}function S(a,c){a=""+a;for(c=c||2;a.length<c;)a="0"+a;return a}function T(a,c,j){var q=a.getDate(),h=a.getDay(),r=a.getMonth();a=a.getFullYear();var f={d:q,dd:S(q),ddd:B[j].shortDays[h],dddd:B[j].days[h],m:r+1,mm:S(r+1),mmm:B[j].shortMonths[r],mmmm:B[j].months[r],yy:String(a).slice(2),yyyy:a};c=c.replace(X,function(s){return s in f?f[s]:s.slice(1,s.length-1)});return Y.html(c).html()}function v(a){return parseInt(a,10)}function U(a,
c){return a.getFullYear()===c.getFullYear()&&a.getMonth()==c.getMonth()&&a.getDate()==c.getDate()}function C(a){if(a){if(a.constructor==Date)return a;if(typeof a=="string"){var c=a.split("-");if(c.length==3)return new Date(v(c[0]),v(c[1])-1,v(c[2]));if(!/^-?\d+$/.test(a))return;a=v(a)}c=new Date;c.setDate(c.getDate()+a);return c}}function Z(a,c){function j(b,e,g){n=b;D=b.getFullYear();E=b.getMonth();G=b.getDate();g=g||d.Event("api");g.type="change";H.trigger(g,[b]);if(!g.isDefaultPrevented()){a.val(T(b,
e.format,e.lang));a.data("date",b);h.hide(g)}}function q(b){b.type="onShow";H.trigger(b);d(document).bind("keydown.d",function(e){if(e.ctrlKey)return true;var g=e.keyCode;if(g==8){a.val("");return h.hide(e)}if(g==27)return h.hide(e);if(d(V).index(g)>=0){if(!w){h.show(e);return e.preventDefault()}var i=d("#"+f.weeks+" a"),t=d("."+f.focus),o=i.index(t);t.removeClass(f.focus);if(g==74||g==40)o+=7;else if(g==75||g==38)o-=7;else if(g==76||g==39)o+=1;else if(g==72||g==37)o-=1;if(o>41){h.addMonth();t=d("#"+
f.weeks+" a:eq("+(o-42)+")")}else if(o<0){h.addMonth(-1);t=d("#"+f.weeks+" a:eq("+(o+42)+")")}else t=i.eq(o);t.addClass(f.focus);return e.preventDefault()}if(g==34)return h.addMonth();if(g==33)return h.addMonth(-1);if(g==36)return h.today();if(g==13)d(e.target).is("select")||d("."+f.focus).click();return d([16,17,18,9]).index(g)>=0});d(document).bind("click.d",function(e){var g=e.target;if(!d(g).parents("#"+f.root).length&&g!=a[0]&&(!L||g!=L[0]))h.hide(e)})}var h=this,r=new Date,f=c.css,s=B[c.lang],
k=d("#"+f.root),M=k.find("#"+f.title),L,I,J,D,E,G,n=a.attr("data-value")||c.value||a.val(),m=a.attr("min")||c.min,p=a.attr("max")||c.max,w;if(m===0)m="0";n=C(n)||r;m=C(m||c.yearRange[0]*365);p=C(p||c.yearRange[1]*365);if(!s)throw"Dateinput: invalid language: "+c.lang;if(a.attr("type")=="date"){var N=d("<input/>");d.each("class,disabled,id,maxlength,name,readonly,required,size,style,tabindex,title,value".split(","),function(b,e){N.attr(e,a.attr(e))});a.replaceWith(N);a=N}a.addClass(f.input);var H=
a.add(h);if(!k.length){k=d("<div><div><a/><div/><a/></div><div><div/><div/></div></div>").hide().css({position:"absolute"}).attr("id",f.root);k.children().eq(0).attr("id",f.head).end().eq(1).attr("id",f.body).children().eq(0).attr("id",f.days).end().eq(1).attr("id",f.weeks).end().end().end().find("a").eq(0).attr("id",f.prev).end().eq(1).attr("id",f.next);M=k.find("#"+f.head).find("div").attr("id",f.title);if(c.selectors){var z=d("<select/>").attr("id",f.month),A=d("<select/>").attr("id",f.year);M.html(z.add(A))}for(var $=
k.find("#"+f.days),O=0;O<7;O++)$.append(d("<span/>").text(s.shortDays[(O+c.firstDay)%7]));d("body").append(k)}if(c.trigger)L=d("<a/>").attr("href","#").addClass(f.trigger).click(function(b){h.show();return b.preventDefault()}).insertAfter(a);var K=k.find("#"+f.weeks);A=k.find("#"+f.year);z=k.find("#"+f.month);d.extend(h,{show:function(b){if(!(a.attr("readonly")||a.attr("disabled")||w)){b=b||d.Event();b.type="onBeforeShow";H.trigger(b);if(!b.isDefaultPrevented()){d.each(W,function(){this.hide()});
w=true;z.unbind("change").change(function(){h.setValue(A.val(),d(this).val())});A.unbind("change").change(function(){h.setValue(d(this).val(),z.val())});I=k.find("#"+f.prev).unbind("click").click(function(){I.hasClass(f.disabled)||h.addMonth(-1);return false});J=k.find("#"+f.next).unbind("click").click(function(){J.hasClass(f.disabled)||h.addMonth();return false});h.setValue(n);var e=a.offset();if(/iPad/i.test(navigator.userAgent))e.top-=d(window).scrollTop();k.css({top:e.top+a.outerHeight({margins:true})+
c.offset[0],left:e.left+c.offset[1]});if(c.speed)k.show(c.speed,function(){q(b)});else{k.show();q(b)}return h}}},setValue:function(b,e,g){var i=v(e)>=-1?new Date(v(b),v(e),v(g||1)):b||n;if(i<m)i=m;else if(i>p)i=p;b=i.getFullYear();e=i.getMonth();g=i.getDate();if(e==-1){e=11;b--}else if(e==12){e=0;b++}if(!w){j(i,c);return h}E=e;D=b;g=new Date(b,e,1-c.firstDay);g=g.getDay();var t=R(b,e),o=R(b,e-1),P;if(c.selectors){z.empty();d.each(s.months,function(x,F){m<new Date(b,x+1,-1)&&p>new Date(b,x,0)&&z.append(d("<option/>").html(F).attr("value",
x))});A.empty();i=r.getFullYear();for(var l=i+c.yearRange[0];l<i+c.yearRange[1];l++)m<=new Date(l+1,-1,1)&&p>new Date(l,0,0)&&A.append(d("<option/>").text(l));z.val(e);A.val(b)}else M.html(s.months[e]+" "+b);K.empty();I.add(J).removeClass(f.disabled);l=!g?-7:0;for(var u,y;l<(!g?35:42);l++){u=d("<a/>");if(l%7===0){P=d("<div/>").addClass(f.week);K.append(P)}if(l<g){u.addClass(f.off);y=o-g+l+1;i=new Date(b,e-1,y)}else if(l>=g+t){u.addClass(f.off);y=l-t-g+1;i=new Date(b,e+1,y)}else{y=l-g+1;i=new Date(b,
e,y);if(U(n,i))u.attr("id",f.current).addClass(f.focus);else U(r,i)&&u.attr("id",f.today)}m&&i<m&&u.add(I).addClass(f.disabled);p&&i>p&&u.add(J).addClass(f.disabled);u.attr("href","#"+y).text(y).data("date",i);P.append(u)}K.find("a").click(function(x){var F=d(this);if(!F.hasClass(f.disabled)){d("#"+f.current).removeAttr("id");F.attr("id",f.current);j(F.data("date"),c,x)}return false});f.sunday&&K.find(f.week).each(function(){var x=c.firstDay?7-c.firstDay:0;d(this).children().slice(x,x+1).addClass(f.sunday)});
return h},setMin:function(b,e){m=C(b);e&&n<m&&h.setValue(m);return h},setMax:function(b,e){p=C(b);e&&n>p&&h.setValue(p);return h},today:function(){return h.setValue(r)},addDay:function(b){return this.setValue(D,E,G+(b||1))},addMonth:function(b){return this.setValue(D,E+(b||1),G)},addYear:function(b){return this.setValue(D+(b||1),E,G)},hide:function(b){if(w){b=d.Event();b.type="onHide";H.trigger(b);d(document).unbind("click.d").unbind("keydown.d");if(b.isDefaultPrevented())return;k.hide();w=false}return h},
getConf:function(){return c},getInput:function(){return a},getCalendar:function(){return k},getValue:function(b){return b?T(n,b,c.lang):n},isOpen:function(){return w}});d.each(["onBeforeShow","onShow","change","onHide"],function(b,e){d.isFunction(c[e])&&d(h).bind(e,c[e]);h[e]=function(g){g&&d(h).bind(e,g);return h}});a.bind("focus click",h.show).keydown(function(b){var e=b.keyCode;if(!w&&d(V).index(e)>=0){h.show(b);return b.preventDefault()}return b.shiftKey||b.ctrlKey||b.altKey||e==9?true:b.preventDefault()});
C(a.val())&&j(n,c)}d.tools=d.tools||{version:"1.2.5"};var W=[],Q,V=[75,76,38,39,74,72,40,37],B={};Q=d.tools.dateinput={conf:{format:"mm/dd/yy",selectors:false,yearRange:[-5,5],lang:"en",offset:[0,0],speed:0,firstDay:0,min:undefined,max:undefined,trigger:false,css:{prefix:"cal",input:"date",root:0,head:0,title:0,prev:0,next:0,month:0,year:0,days:0,body:0,weeks:0,today:0,current:0,week:0,off:0,sunday:0,focus:0,disabled:0,trigger:0}},localize:function(a,c){d.each(c,function(j,q){c[j]=q.split(",")});
B[a]=c}};Q.localize("en",{months:"January,February,March,April,May,June,July,August,September,October,November,December",shortMonths:"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",days:"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday",shortDays:"Sun,Mon,Tue,Wed,Thu,Fri,Sat"});var X=/d{1,4}|m{1,4}|yy(?:yy)?|"[^"]*"|'[^']*'/g,Y=d("<a/>");d.expr[":"].date=function(a){var c=a.getAttribute("type");return c&&c=="date"||!!d(a).data("dateinput")};d.fn.dateinput=function(a){if(this.data("dateinput"))return this;
a=d.extend(true,{},Q.conf,a);d.each(a.css,function(j,q){if(!q&&j!="prefix")a.css[j]=(a.css.prefix||"")+(q||j)});var c;this.each(function(){var j=new Z(d(this),a);W.push(j);j=j.getInput().data("dateinput",j);c=c?c.add(j):j});return c?c:this}})(jQuery);
(function(e){function F(d,a){a=Math.pow(10,a);return Math.round(d*a)/a}function q(d,a){if(a=parseInt(d.css(a),10))return a;return(d=d[0].currentStyle)&&d.width&&parseInt(d.width,10)}function C(d){return(d=d.data("events"))&&d.onSlide}function G(d,a){function h(c,b,f,j){if(f===undefined)f=b/k*z;else if(j)f-=a.min;if(s)f=Math.round(f/s)*s;if(b===undefined||s)b=f*k/z;if(isNaN(f))return g;b=Math.max(0,Math.min(b,k));f=b/k*z;if(j||!n)f+=a.min;if(n)if(j)b=k-b;else f=a.max-f;f=F(f,t);var r=c.type=="click";
if(D&&l!==undefined&&!r){c.type="onSlide";A.trigger(c,[f,b]);if(c.isDefaultPrevented())return g}j=r?a.speed:0;r=r?function(){c.type="change";A.trigger(c,[f])}:null;if(n){m.animate({top:b},j,r);a.progress&&B.animate({height:k-b+m.width()/2},j)}else{m.animate({left:b},j,r);a.progress&&B.animate({width:b+m.width()/2},j)}l=f;H=b;d.val(f);return g}function o(){if(n=a.vertical||q(i,"height")>q(i,"width")){k=q(i,"height")-q(m,"height");u=i.offset().top+k}else{k=q(i,"width")-q(m,"width");u=i.offset().left}}
function v(){o();g.setValue(a.value!==undefined?a.value:a.min)}var g=this,p=a.css,i=e("<div><div/><a href='#'/></div>").data("rangeinput",g),n,l,u,k,H;d.before(i);var m=i.addClass(p.slider).find("a").addClass(p.handle),B=i.find("div").addClass(p.progress);e.each("min,max,step,value".split(","),function(c,b){c=d.attr(b);if(parseFloat(c))a[b]=parseFloat(c,10)});var z=a.max-a.min,s=a.step=="any"?0:a.step,t=a.precision;if(t===undefined)try{t=s.toString().split(".")[1].length}catch(I){t=0}if(d.attr("type")==
"range"){var w=e("<input/>");e.each("class,disabled,id,maxlength,name,readonly,required,size,style,tabindex,title,value".split(","),function(c,b){w.attr(b,d.attr(b))});w.val(a.value);d.replaceWith(w);d=w}d.addClass(p.input);var A=e(g).add(d),D=true;e.extend(g,{getValue:function(){return l},setValue:function(c,b){o();return h(b||e.Event("api"),undefined,c,true)},getConf:function(){return a},getProgress:function(){return B},getHandle:function(){return m},getInput:function(){return d},step:function(c,
b){b=b||e.Event();var f=a.step=="any"?1:a.step;g.setValue(l+f*(c||1),b)},stepUp:function(c){return g.step(c||1)},stepDown:function(c){return g.step(-c||-1)}});e.each("onSlide,change".split(","),function(c,b){e.isFunction(a[b])&&e(g).bind(b,a[b]);g[b]=function(f){f&&e(g).bind(b,f);return g}});m.drag({drag:false}).bind("dragStart",function(){o();D=C(e(g))||C(d)}).bind("drag",function(c,b,f){if(d.is(":disabled"))return false;h(c,n?b:f)}).bind("dragEnd",function(c){if(!c.isDefaultPrevented()){c.type=
"change";A.trigger(c,[l])}}).click(function(c){return c.preventDefault()});i.click(function(c){if(d.is(":disabled")||c.target==m[0])return c.preventDefault();o();var b=m.width()/2;h(c,n?k-u-b+c.pageY:c.pageX-u-b)});a.keyboard&&d.keydown(function(c){if(!d.attr("readonly")){var b=c.keyCode,f=e([75,76,38,33,39]).index(b)!=-1,j=e([74,72,40,34,37]).index(b)!=-1;if((f||j)&&!(c.shiftKey||c.altKey||c.ctrlKey)){if(f)g.step(b==33?10:1,c);else if(j)g.step(b==34?-10:-1,c);return c.preventDefault()}}});d.blur(function(c){var b=
e(this).val();b!==l&&g.setValue(b,c)});e.extend(d[0],{stepUp:g.stepUp,stepDown:g.stepDown});v();k||e(window).load(v)}e.tools=e.tools||{version:"1.2.5"};var E;E=e.tools.rangeinput={conf:{min:0,max:100,step:"any",steps:0,value:0,precision:undefined,vertical:0,keyboard:true,progress:false,speed:100,css:{input:"range",slider:"slider",progress:"progress",handle:"handle"}}};var x,y;e.fn.drag=function(d){document.ondragstart=function(){return false};d=e.extend({x:true,y:true,drag:true},d);x=x||e(document).bind("mousedown mouseup",
function(a){var h=e(a.target);if(a.type=="mousedown"&&h.data("drag")){var o=h.position(),v=a.pageX-o.left,g=a.pageY-o.top,p=true;x.bind("mousemove.drag",function(i){var n=i.pageX-v;i=i.pageY-g;var l={};if(d.x)l.left=n;if(d.y)l.top=i;if(p){h.trigger("dragStart");p=false}d.drag&&h.css(l);h.trigger("drag",[i,n]);y=h});a.preventDefault()}else try{y&&y.trigger("dragEnd")}finally{x.unbind("mousemove.drag");y=null}});return this.data("drag",true)};e.expr[":"].range=function(d){var a=d.getAttribute("type");
return a&&a=="range"||!!e(d).filter("input").data("rangeinput")};e.fn.rangeinput=function(d){if(this.data("rangeinput"))return this;d=e.extend(true,{},E.conf,d);var a;this.each(function(){var h=new G(e(this),e.extend(true,{},d));h=h.getInput().data("rangeinput",h);a=a?a.add(h):h});return a?a:this}})(jQuery);
(function(e){function t(a,b,c){var k=a.offset().top,f=a.offset().left,l=c.position.split(/,?\s+/),p=l[0];l=l[1];k-=b.outerHeight()-c.offset[0];f+=a.outerWidth()+c.offset[1];if(/iPad/i.test(navigator.userAgent))k-=e(window).scrollTop();c=b.outerHeight()+a.outerHeight();if(p=="center")k+=c/2;if(p=="bottom")k+=c;a=a.outerWidth();if(l=="center")f-=(a+b.outerWidth())/2;if(l=="left")f-=a;return{top:k,left:f}}function y(a){function b(){return this.getAttribute("type")==a}b.key="[type="+a+"]";return b}function u(a,
b,c){function k(g,d,i){if(!(!c.grouped&&g.length)){var j;if(i===false||e.isArray(i)){j=h.messages[d.key||d]||h.messages["*"];j=j[c.lang]||h.messages["*"].en;(d=j.match(/\$\d/g))&&e.isArray(i)&&e.each(d,function(m){j=j.replace(this,i[m])})}else j=i[c.lang]||i;g.push(j)}}var f=this,l=b.add(f);a=a.not(":button, :image, :reset, :submit");e.extend(f,{getConf:function(){return c},getForm:function(){return b},getInputs:function(){return a},reflow:function(){a.each(function(){var g=e(this),d=g.data("msg.el");
if(d){g=t(g,d,c);d.css({top:g.top,left:g.left})}});return f},invalidate:function(g,d){if(!d){var i=[];e.each(g,function(j,m){j=a.filter("[name='"+j+"']");if(j.length){j.trigger("OI",[m]);i.push({input:j,messages:[m]})}});g=i;d=e.Event()}d.type="onFail";l.trigger(d,[g]);d.isDefaultPrevented()||q[c.effect][0].call(f,g,d);return f},reset:function(g){g=g||a;g.removeClass(c.errorClass).each(function(){var d=e(this).data("msg.el");if(d){d.remove();e(this).data("msg.el",null)}}).unbind(c.errorInputEvent||
"");return f},destroy:function(){b.unbind(c.formEvent+".V").unbind("reset.V");a.unbind(c.inputEvent+".V").unbind("change.V");return f.reset()},checkValidity:function(g,d){g=g||a;g=g.not(":disabled");if(!g.length)return true;d=d||e.Event();d.type="onBeforeValidate";l.trigger(d,[g]);if(d.isDefaultPrevented())return d.result;var i=[];g.not(":radio:not(:checked)").each(function(){var m=[],n=e(this).data("messages",m),v=r&&n.is(":date")?"onHide.v":c.errorInputEvent+".v";n.unbind(v);e.each(w,function(){var o=
this,s=o[0];if(n.filter(s).length){o=o[1].call(f,n,n.val());if(o!==true){d.type="onBeforeFail";l.trigger(d,[n,s]);if(d.isDefaultPrevented())return false;var x=n.attr(c.messageAttr);if(x){m=[x];return false}else k(m,s,o)}}});if(m.length){i.push({input:n,messages:m});n.trigger("OI",[m]);c.errorInputEvent&&n.bind(v,function(o){f.checkValidity(n,o)})}if(c.singleError&&i.length)return false});var j=q[c.effect];if(!j)throw'Validator: cannot find effect "'+c.effect+'"';if(i.length){f.invalidate(i,d);return false}else{j[1].call(f,
g,d);d.type="onSuccess";l.trigger(d,[g]);g.unbind(c.errorInputEvent+".v")}return true}});e.each("onBeforeValidate,onBeforeFail,onFail,onSuccess".split(","),function(g,d){e.isFunction(c[d])&&e(f).bind(d,c[d]);f[d]=function(i){i&&e(f).bind(d,i);return f}});c.formEvent&&b.bind(c.formEvent+".V",function(g){if(!f.checkValidity(null,g))return g.preventDefault()});b.bind("reset.V",function(){f.reset()});a[0]&&a[0].validity&&a.each(function(){this.oninvalid=function(){return false}});if(b[0])b[0].checkValidity=
f.checkValidity;c.inputEvent&&a.bind(c.inputEvent+".V",function(g){f.checkValidity(e(this),g)});a.filter(":checkbox, select").filter("[required]").bind("change.V",function(g){var d=e(this);if(this.checked||d.is("select")&&e(this).val())q[c.effect][1].call(f,d,g)});var p=a.filter(":radio").change(function(g){f.checkValidity(p,g)});e(window).resize(function(){f.reflow()})}e.tools=e.tools||{version:"1.2.5"};var z=/\[type=([a-z]+)\]/,A=/^-?[0-9]*(\.[0-9]+)?$/,r=e.tools.dateinput,B=/^([a-z0-9_\.\-\+]+)@([\da-z\.\-]+)\.([a-z\.]{2,6})$/i,
C=/^(https?:\/\/)?[\da-z\.\-]+\.[a-z\.]{2,6}[#&+_\?\/\w \.\-=]*$/i,h;h=e.tools.validator={conf:{grouped:false,effect:"default",errorClass:"invalid",inputEvent:null,errorInputEvent:"keyup",formEvent:"submit",lang:"en",message:"<div/>",messageAttr:"data-message",messageClass:"error",offset:[0,0],position:"center right",singleError:false,speed:"normal"},messages:{"*":{en:"Please correct this value"}},localize:function(a,b){e.each(b,function(c,k){h.messages[c]=h.messages[c]||{};h.messages[c][a]=k})},
localizeFn:function(a,b){h.messages[a]=h.messages[a]||{};e.extend(h.messages[a],b)},fn:function(a,b,c){if(e.isFunction(b))c=b;else{if(typeof b=="string")b={en:b};this.messages[a.key||a]=b}if(b=z.exec(a))a=y(b[1]);w.push([a,c])},addEffect:function(a,b,c){q[a]=[b,c]}};var w=[],q={"default":[function(a){var b=this.getConf();e.each(a,function(c,k){c=k.input;c.addClass(b.errorClass);var f=c.data("msg.el");if(!f){f=e(b.message).addClass(b.messageClass).appendTo(document.body);c.data("msg.el",f)}f.css({visibility:"hidden"}).find("p").remove();
e.each(k.messages,function(l,p){e("<p/>").html(p).appendTo(f)});f.outerWidth()==f.parent().width()&&f.add(f.find("p")).css({display:"inline"});k=t(c,f,b);f.css({visibility:"visible",position:"absolute",top:k.top,left:k.left}).fadeIn(b.speed)})},function(a){var b=this.getConf();a.removeClass(b.errorClass).each(function(){var c=e(this).data("msg.el");c&&c.css({visibility:"hidden"})})}]};e.each("email,url,number".split(","),function(a,b){e.expr[":"][b]=function(c){return c.getAttribute("type")===b}});
e.fn.oninvalid=function(a){return this[a?"bind":"trigger"]("OI",a)};h.fn(":email","Please enter a valid email address",function(a,b){return!b||B.test(b)});h.fn(":url","Please enter a valid URL",function(a,b){return!b||C.test(b)});h.fn(":number","Please enter a numeric value.",function(a,b){return A.test(b)});h.fn("[max]","Please enter a value smaller than $1",function(a,b){if(b===""||r&&a.is(":date"))return true;a=a.attr("max");return parseFloat(b)<=parseFloat(a)?true:[a]});h.fn("[min]","Please enter a value larger than $1",
function(a,b){if(b===""||r&&a.is(":date"))return true;a=a.attr("min");return parseFloat(b)>=parseFloat(a)?true:[a]});h.fn("[required]","Please complete this mandatory field.",function(a,b){if(a.is(":checkbox"))return a.is(":checked");return!!b});h.fn("[pattern]",function(a){var b=new RegExp("^"+a.attr("pattern")+"$");return b.test(a.val())});e.fn.validator=function(a){var b=this.data("validator");if(b){b.destroy();this.removeData("validator")}a=e.extend(true,{},h.conf,a);if(this.is("form"))return this.each(function(){var c=
e(this);b=new u(c.find(":input"),c,a);c.data("validator",b)});else{b=new u(this,this.eq(0).closest("form"),a);return this.data("validator",b)}}})(jQuery);/*
 * Treeview 1.5pre - jQuery plugin to hide and show branches of a tree
 * 
 * http://bassistance.de/jquery-plugins/jquery-plugin-treeview/
 * http://docs.jquery.com/Plugins/Treeview
 *
 * Copyright (c) 2007 Jörn Zaefferer
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id: jquery.treeview.js 5759 2008-07-01 07:50:28Z joern.zaefferer $
 *
 */

;(function($) {

	// TODO rewrite as a widget, removing all the extra plugins
	$.extend($.fn, {
		swapClass: function(c1, c2) {
			var c1Elements = this.filter('.' + c1);
			this.filter('.' + c2).removeClass(c2).addClass(c1);
			c1Elements.removeClass(c1).addClass(c2);
			return this;
		},
		replaceClass: function(c1, c2) {
			return this.filter('.' + c1).removeClass(c1).addClass(c2).end();
		},
		hoverClass: function(className) {
			className = className || "hover";
			return this.hover(function() {
				$(this).addClass(className);
			}, function() {
				$(this).removeClass(className);
			});
		},
		heightToggle: function(animated, callback) {
			animated ?
				this.animate({ height: "toggle" }, animated, callback) :
				this.each(function(){
					jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
					if(callback)
						callback.apply(this, arguments);
				});
		},
		heightHide: function(animated, callback) {
			if (animated) {
				this.animate({ height: "hide" }, animated, callback);
			} else {
				this.hide();
				if (callback)
					this.each(callback);				
			}
		},
		prepareBranches: function(settings) {
			if (!settings.prerendered) {
				// mark last tree items
				this.filter(":last-child:not(ul)").addClass(CLASSES.last);
				// collapse whole tree, or only those marked as closed, anyway except those marked as open
				this.filter((settings.collapsed ? "" : "." + CLASSES.closed) + ":not(." + CLASSES.open + ")").find(">ul").hide();
			}
			// return all items with sublists
			return this.filter(":has(>ul)");
		},
		applyClasses: function(settings, toggler) {
			// TODO use event delegation
			this.filter(":has(>ul):not(:has(>a))").find(">span").unbind("click.treeview").bind("click.treeview", function(event) {
				// don't handle click events on children, eg. checkboxes
				if ( this == event.target )
					toggler.apply($(this).next());
			}).add( $("a", this) ).hoverClass();
			
			if (!settings.prerendered) {
				// handle closed ones first
				this.filter(":has(>ul:hidden)")
						.addClass(CLASSES.expandable)
						.replaceClass(CLASSES.last, CLASSES.lastExpandable);
						
				// handle open ones
				this.not(":has(>ul:hidden)")
						.addClass(CLASSES.collapsable)
						.replaceClass(CLASSES.last, CLASSES.lastCollapsable);
						
	            // create hitarea if not present
				var hitarea = this.find("div." + CLASSES.hitarea);
				if (!hitarea.length)
					hitarea = this.prepend("<div class=\"" + CLASSES.hitarea + "\"/>").find("div." + CLASSES.hitarea);
				hitarea.removeClass().addClass(CLASSES.hitarea).each(function() {
					var classes = "";
					$.each($(this).parent().attr("class").split(" "), function() {
						classes += this + "-hitarea ";
					});
					$(this).addClass( classes );
				})
			}
			
			// apply event to hitarea
			this.find("div." + CLASSES.hitarea).click( toggler );
		},
		treeview: function(settings) {
			
			settings = $.extend({
				cookieId: "treeview"
			}, settings);
			
			if ( settings.toggle ) {
				var callback = settings.toggle;
				settings.toggle = function() {
					return callback.apply($(this).parent()[0], arguments);
				};
			}
		
			// factory for treecontroller
			function treeController(tree, control) {
				// factory for click handlers
				function handler(filter) {
					return function() {
						// reuse toggle event handler, applying the elements to toggle
						// start searching for all hitareas
						toggler.apply( $("div." + CLASSES.hitarea, tree).filter(function() {
							// for plain toggle, no filter is provided, otherwise we need to check the parent element
							return filter ? $(this).parent("." + filter).length : true;
						}) );
						return false;
					};
				}
				// click on first element to collapse tree
				$("a:eq(0)", control).click( handler(CLASSES.collapsable) );
				// click on second to expand tree
				$("a:eq(1)", control).click( handler(CLASSES.expandable) );
				// click on third to toggle tree
				$("a:eq(2)", control).click( handler() ); 
			}
		
			// handle toggle event
			function toggler() {
				$(this)
					.parent()
					// swap classes for hitarea
					.find(">.hitarea")
						.swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
						.swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
					.end()
					// swap classes for parent li
					.swapClass( CLASSES.collapsable, CLASSES.expandable )
					.swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
					// find child lists
					.find( ">ul" )
					// toggle them
					.heightToggle( settings.animated, settings.toggle );
				if ( settings.unique ) {
					$(this).parent()
						.siblings()
						// swap classes for hitarea
						.find(">.hitarea")
							.replaceClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
							.replaceClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
						.end()
						.replaceClass( CLASSES.collapsable, CLASSES.expandable )
						.replaceClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
						.find( ">ul" )
						.heightHide( settings.animated, settings.toggle );
				}
			}
			this.data("toggler", toggler);
			
			function serialize() {
				function binary(arg) {
					return arg ? 1 : 0;
				}
				var data = [];
				branches.each(function(i, e) {
					data[i] = $(e).is(":has(>ul:visible)") ? 1 : 0;
				});
				$.cookie(settings.cookieId, data.join(""), settings.cookieOptions );
			}
			
			function deserialize() {
				var stored = $.cookie(settings.cookieId);
				if ( stored ) {
					var data = stored.split("");
					branches.each(function(i, e) {
						$(e).find(">ul")[ parseInt(data[i]) ? "show" : "hide" ]();
					});
				}
			}
			
			// add treeview class to activate styles
			this.addClass("treeview");
			
			// prepare branches and find all tree items with child lists
			var branches = this.find("li").prepareBranches(settings);
			
			switch(settings.persist) {
			case "cookie":
				var toggleCallback = settings.toggle;
				settings.toggle = function() {
					serialize();
					if (toggleCallback) {
						toggleCallback.apply(this, arguments);
					}
				};
				deserialize();
				break;
			case "location":
				var current = this.find("a").filter(function() {
					return this.href.toLowerCase() == location.href.toLowerCase();
				});
				if ( current.length ) {
					// TODO update the open/closed classes
					var items = current.addClass("selected").parents("ul, li").add( current.next() ).show();
					if (settings.prerendered) {
						// if prerendered is on, replicate the basic class swapping
						items.filter("li")
							.swapClass( CLASSES.collapsable, CLASSES.expandable )
							.swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
							.find(">.hitarea")
								.swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
								.swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea );
					}
				}
				break;
			}
			
			branches.applyClasses(settings, toggler);
				
			// if control option is set, create the treecontroller and show it
			if ( settings.control ) {
				treeController(this, settings.control);
				$(settings.control).show();
			}
			
			return this;
		}
	});
	
	// classes used by the plugin
	// need to be styled via external stylesheet, see first example
	$.treeview = {};
	var CLASSES = ($.treeview.classes = {
		open: "open",
		closed: "closed",
		expandable: "expandable",
		expandableHitarea: "expandable-hitarea",
		lastExpandableHitarea: "lastExpandable-hitarea",
		collapsable: "collapsable",
		collapsableHitarea: "collapsable-hitarea",
		lastCollapsableHitarea: "lastCollapsable-hitarea",
		lastCollapsable: "lastCollapsable",
		lastExpandable: "lastExpandable",
		last: "last",
		hitarea: "hitarea"
	});
	
})(jQuery);!function(a){a(function(){"use strict",a.support.transition=function(){var b=document.body||document.documentElement,c=b.style,d=c.transition!==undefined||c.WebkitTransition!==undefined||c.MozTransition!==undefined||c.MsTransition!==undefined||c.OTransition!==undefined;return d&&{end:function(){var b="TransitionEnd";return a.browser.webkit?b="webkitTransitionEnd":a.browser.mozilla?b="transitionend":a.browser.opera&&(b="oTransitionEnd"),b}()}}()})}(window.jQuery),!function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype={constructor:c,close:function(b){function f(){e.remove(),e.trigger("closed")}var c=a(this),d=c.attr("data-target"),e;d||(d=c.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),e=a(d),e.trigger("close"),b&&b.preventDefault(),e.length||(e=c.hasClass("alert")?c:c.parent()),e.removeClass("in"),a.support.transition&&e.hasClass("fade")?e.on(a.support.transition.end,f):f()}},a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("alert");e||d.data("alert",e=new c(this)),typeof b=="string"&&e[b].call(d)})},a.fn.alert.Constructor=c,a(function(){a("body").on("click.alert.data-api",b,c.prototype.close)})}(window.jQuery),!function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.button.defaults,c)};b.prototype={constructor:b,setState:function(a){var b="disabled",c=this.$element,d=c.data(),e=c.is("input")?"val":"html";a+="Text",d.resetText||c.data("resetText",c[e]()),c[e](d[a]||this.options[a]),setTimeout(function(){a=="loadingText"?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},toggle:function(){var a=this.$element.parent('[data-toggle="buttons-radio"]');a&&a.find(".active").removeClass("active"),this.$element.toggleClass("active")}},a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("button"),f=typeof c=="object"&&c;e||d.data("button",e=new b(this,f)),c=="toggle"?e.toggle():c&&e.setState(c)})},a.fn.button.defaults={loadingText:"loading..."},a.fn.button.Constructor=b,a(function(){a("body").on("click.button.data-api","[data-toggle^=button]",function(b){a(b.target).button("toggle")})})}(window.jQuery),!function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.carousel.defaults,c),this.options.slide&&this.slide(this.options.slide)};b.prototype={cycle:function(){return this.interval=setInterval(a.proxy(this.next,this),this.options.interval),this},to:function(b){var c=this.$element.find(".active"),d=c.parent().children(),e=d.index(c),f=this;if(b>d.length-1||b<0)return;return this.sliding?this.$element.one("slid",function(){f.to(b)}):e==b?this.pause().cycle():this.slide(b>e?"next":"prev",a(d[b]))},pause:function(){return clearInterval(this.interval),this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(b,c){var d=this.$element.find(".active"),e=c||d[b](),f=this.interval,g=b=="next"?"left":"right",h=b=="next"?"first":"last",i=this;return this.sliding=!0,f&&this.pause(),e=e.length?e:this.$element.find(".item")[h](),!a.support.transition&&this.$element.hasClass("slide")?(this.$element.trigger("slide"),d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid")):(e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),this.$element.trigger("slide"),this.$element.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid")},0)})),f&&this.cycle(),this}},a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("carousel"),f=typeof c=="object"&&c;e||d.data("carousel",e=new b(this,f)),typeof c=="number"?e.to(c):typeof c=="string"||(c=f.slide)?e[c]():e.cycle()})},a.fn.carousel.defaults={interval:5e3},a.fn.carousel.Constructor=b,a(function(){a("body").on("click.carousel.data-api","[data-slide]",function(b){var c=a(this),d,e=a(c.attr("data-target")||(d=c.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,"")),f=!e.data("modal")&&a.extend({},e.data(),c.data());e.carousel(f),b.preventDefault()})})}(window.jQuery),!function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.collapse.defaults,c),this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.prototype={constructor:b,dimension:function(){var a=this.$element.hasClass("width");return a?"width":"height"},show:function(){var b=this.dimension(),c=a.camelCase(["scroll",b].join("-")),d=this.$parent&&this.$parent.find(".in"),e;d&&d.length&&(e=d.data("collapse"),d.collapse("hide"),e||d.data("collapse",null)),this.$element[b](0),this.transition("addClass","show","shown"),this.$element[b](this.$element[0][c])},hide:function(){var a=this.dimension();this.reset(this.$element[a]()),this.transition("removeClass","hide","hidden"),this.$element[a](0)},reset:function(a){var b=this.dimension();this.$element.removeClass("collapse")[b](a||"auto")[0].offsetWidth,this.$element.addClass("collapse")},transition:function(b,c,d){var e=this,f=function(){c=="show"&&e.reset(),e.$element.trigger(d)};this.$element.trigger(c)[b]("in"),a.support.transition&&this.$element.hasClass("collapse")?this.$element.one(a.support.transition.end,f):f()},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}},a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("collapse"),f=typeof c=="object"&&c;e||d.data("collapse",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.collapse.defaults={toggle:!0},a.fn.collapse.Constructor=b,a(function(){a("body").on("click.collapse.data-api","[data-toggle=collapse]",function(b){var c=a(this),d,e=c.attr("data-target")||b.preventDefault()||(d=c.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""),f=a(e).data("collapse")?"toggle":c.data();a(e).collapse(f)})})}(window.jQuery),!function(a){function d(){a(b).parent().removeClass("open")}"use strict";var b='[data-toggle="dropdown"]',c=function(b){var c=a(b).on("click.dropdown.data-api",this.toggle);a("html").on("click.dropdown.data-api",function(){c.parent().removeClass("open")})};c.prototype={constructor:c,toggle:function(b){var c=a(this),e=c.attr("data-target"),f,g;return e||(e=c.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,"")),f=a(e),f.length||(f=c.parent()),g=f.hasClass("open"),d(),!g&&f.toggleClass("open"),!1}},a.fn.dropdown=function(b){return this.each(function(){var d=a(this),e=d.data("dropdown");e||d.data("dropdown",e=new c(this)),typeof b=="string"&&e[b].call(d)})},a.fn.dropdown.Constructor=c,a(function(){a("html").on("click.dropdown.data-api",d),a("body").on("click.dropdown.data-api",b,c.prototype.toggle)})}(window.jQuery),!function(a){function c(){var b=this,c=setTimeout(function(){b.$element.off(a.support.transition.end),d.call(b)},500);this.$element.one(a.support.transition.end,function(){clearTimeout(c),d.call(b)})}function d(a){this.$element.hide().trigger("hidden"),e.call(this)}function e(b){var c=this,d=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var e=a.support.transition&&d;this.$backdrop=a('<div class="modal-backdrop '+d+'" />').appendTo(document.body),this.options.backdrop!="static"&&this.$backdrop.click(a.proxy(this.hide,this)),e&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),e?this.$backdrop.one(a.support.transition.end,b):b()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(a.support.transition.end,a.proxy(f,this)):f.call(this)):b&&b()}function f(){this.$backdrop.remove(),this.$backdrop=null}function g(){var b=this;this.isShown&&this.options.keyboard?a(document).on("keyup.dismiss.modal",function(a){a.which==27&&b.hide()}):this.isShown||a(document).off("keyup.dismiss.modal")}"use strict";var b=function(b,c){this.options=a.extend({},a.fn.modal.defaults,c),this.$element=a(b).delegate('[data-dismiss="modal"]',"click.dismiss.modal",a.proxy(this.hide,this))};b.prototype={constructor:b,toggle:function(){return this[this.isShown?"hide":"show"]()},show:function(){var b=this;if(this.isShown)return;a("body").addClass("modal-open"),this.isShown=!0,this.$element.trigger("show"),g.call(this),e.call(this,function(){var c=a.support.transition&&b.$element.hasClass("fade");!b.$element.parent().length&&b.$element.appendTo(document.body),b.$element.show(),c&&b.$element[0].offsetWidth,b.$element.addClass("in"),c?b.$element.one(a.support.transition.end,function(){b.$element.trigger("shown")}):b.$element.trigger("shown")})},hide:function(b){b&&b.preventDefault();if(!this.isShown)return;var e=this;this.isShown=!1,a("body").removeClass("modal-open"),g.call(this),this.$element.trigger("hide").removeClass("in"),a.support.transition&&this.$element.hasClass("fade")?c.call(this):d.call(this)}},a.fn.modal=function(c){return this.each(function(){var d=a(this),e=d.data("modal"),f=typeof c=="object"&&c;e||d.data("modal",e=new b(this,f)),typeof c=="string"?e[c]():e.show()})},a.fn.modal.defaults={backdrop:!0,keyboard:!0},a.fn.modal.Constructor=b,a(function(){a("body").on("click.modal.data-api",'[data-toggle="modal"]',function(b){var c=a(this),d,e=a(c.attr("data-target")||(d=c.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,"")),f=e.data("modal")?"toggle":a.extend({},e.data(),c.data());b.preventDefault(),e.modal(f)})})}(window.jQuery),!function(a){"use strict";var b=function(a,b){this.init("tooltip",a,b)};b.prototype={constructor:b,init:function(b,c,d){var e,f;this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.enabled=!0,this.options.trigger!="manual"&&(e=this.options.trigger=="hover"?"mouseenter":"focus",f=this.options.trigger=="hover"?"mouseleave":"blur",this.$element.on(e,this.options.selector,a.proxy(this.enter,this)),this.$element.on(f,this.options.selector,a.proxy(this.leave,this))),this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},getOptions:function(b){return b=a.extend({},a.fn[this.type].defaults,b,this.$element.data()),b.delay&&typeof b.delay=="number"&&(b.delay={show:b.delay,hide:b.delay}),b},enter:function(b){var c=a(b.currentTarget)[this.type](this._options).data(this.type);!c.options.delay||!c.options.delay.show?c.show():(c.hoverState="in",setTimeout(function(){c.hoverState=="in"&&c.show()},c.options.delay.show))},leave:function(b){var c=a(b.currentTarget)[this.type](this._options).data(this.type);!c.options.delay||!c.options.delay.hide?c.hide():(c.hoverState="out",setTimeout(function(){c.hoverState=="out"&&c.hide()},c.options.delay.hide))},show:function(){var a,b,c,d,e,f,g;if(this.hasContent()&&this.enabled){a=this.tip(),this.setContent(),this.options.animation&&a.addClass("fade"),f=typeof this.options.placement=="function"?this.options.placement.call(this,a[0],this.$element[0]):this.options.placement,b=/in/.test(f),a.remove().css({top:0,left:0,display:"block"}).appendTo(b?this.$element:document.body),c=this.getPosition(b),d=a[0].offsetWidth,e=a[0].offsetHeight;switch(b?f.split(" ")[1]:f){case"bottom":g={top:c.top+c.height,left:c.left+c.width/2-d/2};break;case"top":g={top:c.top-e,left:c.left+c.width/2-d/2};break;case"left":g={top:c.top+c.height/2-e/2,left:c.left-d};break;case"right":g={top:c.top+c.height/2-e/2,left:c.left+c.width}}a.css(g).addClass(f).addClass("in")}},setContent:function(){var a=this.tip();a.find(".tooltip-inner").html(this.getTitle()),a.removeClass("fade in top bottom left right")},hide:function(){function d(){var b=setTimeout(function(){c.off(a.support.transition.end).remove()},500);c.one(a.support.transition.end,function(){clearTimeout(b),c.remove()})}var b=this,c=this.tip();c.removeClass("in"),a.support.transition&&this.$tip.hasClass("fade")?d():c.remove()},fixTitle:function(){var a=this.$element;(a.attr("title")||typeof a.attr("data-original-title")!="string")&&a.attr("data-original-title",a.attr("title")||"").removeAttr("title")},hasContent:function(){return this.getTitle()},getPosition:function(b){return a.extend({},b?{top:0,left:0}:this.$element.offset(),{width:this.$element[0].offsetWidth,height:this.$element[0].offsetHeight})},getTitle:function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||(typeof c.title=="function"?c.title.call(b[0]):c.title),a=a.toString().replace(/(^\s*|\s*$)/,""),a},tip:function(){return this.$tip=this.$tip||a(this.options.template)},validate:function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},enable:function(){this.enabled=!0},disable:function(){this.enabled=!1},toggleEnabled:function(){this.enabled=!this.enabled},toggle:function(){this[this.tip().hasClass("in")?"hide":"show"]()}},a.fn.tooltip=function(c){return this.each(function(){var d=a(this),e=d.data("tooltip"),f=typeof c=="object"&&c;e||d.data("tooltip",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.tooltip.Constructor=b,a.fn.tooltip.defaults={animation:!0,delay:0,selector:!1,placement:"top",trigger:"hover",title:"",template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'}}(window.jQuery),!function(a){"use strict";var b=function(a,b){this.init("popover",a,b)};b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype,{constructor:b,setContent:function(){var b=this.tip(),c=this.getTitle(),d=this.getContent();b.find(".popover-title")[a.type(c)=="object"?"append":"html"](c),b.find(".popover-content > *")[a.type(d)=="object"?"append":"html"](d),b.removeClass("fade top bottom left right in")},hasContent:function(){return this.getTitle()||this.getContent()},getContent:function(){var a,b=this.$element,c=this.options;return a=b.attr("data-content")||(typeof c.content=="function"?c.content.call(b[0]):c.content),a=a.toString().replace(/(^\s*|\s*$)/,""),a},tip:function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip}}),a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("popover"),f=typeof c=="object"&&c;e||d.data("popover",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.defaults=a.extend({},a.fn.tooltip.defaults,{placement:"right",content:"",template:'<div class="popover"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>'})}(window.jQuery),!function(a){function b(b,c){var d=a.proxy(this.process,this),e=a(b).is("body")?a(window):a(b),f;this.options=a.extend({},a.fn.scrollspy.defaults,c),this.$scrollElement=e.on("scroll.scroll.data-api",d),this.selector=(this.options.target||(f=a(b).attr("href"))&&f.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.$body=a("body").on("click.scroll.data-api",this.selector,d),this.refresh(),this.process()}"use strict",b.prototype={constructor:b,refresh:function(){this.targets=this.$body.find(this.selector).map(function(){var b=a(this).attr("href");return/^#\w/.test(b)&&a(b).length?b:null}),this.offsets=a.map(this.targets,function(b){return a(b).position().top})},process:function(){var a=this.$scrollElement.scrollTop()+this.options.offset,b=this.offsets,c=this.targets,d=this.activeTarget,e;for(e=b.length;e--;)d!=c[e]&&a>=b[e]&&(!b[e+1]||a<=b[e+1])&&this.activate(c[e])},activate:function(a){var b;this.activeTarget=a,this.$body.find(this.selector).parent(".active").removeClass("active"),b=this.$body.find(this.selector+'[href="'+a+'"]').parent("li").addClass("active"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active")}},a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("scrollspy"),f=typeof c=="object"&&c;e||d.data("scrollspy",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.defaults={offset:10},a(function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(window.jQuery),!function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype={constructor:b,show:function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.attr("data-target"),e,f;d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,""));if(b.parent("li").hasClass("active"))return;e=c.find(".active a").last()[0],b.trigger({type:"show",relatedTarget:e}),f=a(d),this.activate(b.parent("li"),c),this.activate(f,f.parent(),function(){b.trigger({type:"shown",relatedTarget:e})})},activate:function(b,c,d){function g(){e.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),f?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var e=c.find("> .active"),f=d&&a.support.transition&&e.hasClass("fade");f?e.one(a.support.transition.end,g):g(),e.removeClass("in")}},a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("tab");e||d.data("tab",e=new b(this)),typeof c=="string"&&e[c]()})},a.fn.tab.Constructor=b,a(function(){a("body").on("click.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})})}(window.jQuery),!function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.typeahead.defaults,c),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.highlighter=this.options.highlighter||this.highlighter,this.$menu=a(this.options.menu).appendTo("body"),this.source=this.options.source,this.shown=!1,this.listen()};b.prototype={constructor:b,select:function(){var a=this.$menu.find(".active").attr("data-value");return this.$element.val(a),this.hide()},show:function(){var b=a.extend({},this.$element.offset(),{height:this.$element[0].offsetHeight});return this.$menu.css({top:b.top+b.height,left:b.left}),this.$menu.show(),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(b){var c=this,d,e;return this.query=this.$element.val(),this.query?(d=a.grep(this.source,function(a){if(c.matcher(a))return a}),d=this.sorter(d),d.length?this.render(d.slice(0,this.options.items)).show():this.shown?this.hide():this):this.shown?this.hide():this},matcher:function(a){return~a.toLowerCase().indexOf(this.query.toLowerCase())},sorter:function(a){var b=[],c=[],d=[],e;while(e=a.shift())e.toLowerCase().indexOf(this.query.toLowerCase())?~e.indexOf(this.query)?c.push(e):d.push(e):b.push(e);return b.concat(c,d)},highlighter:function(a){return a.replace(new RegExp("("+this.query+")","ig"),function(a,b){return"<strong>"+b+"</strong>"})},render:function(b){var c=this;return b=a(b).map(function(b,d){return b=a(c.options.item).attr("data-value",d),b.find("a").html(c.highlighter(d)),b[0]}),b.first().addClass("active"),this.$menu.html(b),this},next:function(b){var c=this.$menu.find(".active").removeClass("active"),d=c.next();d.length||(d=a(this.$menu.find("li")[0])),d.addClass("active")},prev:function(a){var b=this.$menu.find(".active").removeClass("active"),c=b.prev();c.length||(c=this.$menu.find("li").last()),c.addClass("active")},listen:function(){this.$element.on("blur",a.proxy(this.blur,this)).on("keypress",a.proxy(this.keypress,this)).on("keyup",a.proxy(this.keyup,this)),(a.browser.webkit||a.browser.msie)&&this.$element.on("keydown",a.proxy(this.keypress,this)),this.$menu.on("click",a.proxy(this.click,this)).on("mouseenter","li",a.proxy(this.mouseenter,this))},keyup:function(a){a.stopPropagation(),a.preventDefault();switch(a.keyCode){case 40:case 38:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:this.hide();break;default:this.lookup()}},keypress:function(a){a.stopPropagation();if(!this.shown)return;switch(a.keyCode){case 9:case 13:case 27:a.preventDefault();break;case 38:a.preventDefault(),this.prev();break;case 40:a.preventDefault(),this.next()}},blur:function(a){var b=this;a.stopPropagation(),a.preventDefault(),setTimeout(function(){b.hide()},150)},click:function(a){a.stopPropagation(),a.preventDefault(),this.select()},mouseenter:function(b){this.$menu.find(".active").removeClass("active"),a(b.currentTarget).addClass("active")}},a.fn.typeahead=function(c){return this.each(function(){var d=a(this),e=d.data("typeahead"),f=typeof c=="object"&&c;e||d.data("typeahead",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.typeahead.defaults={source:[],items:8,menu:'<ul class="typeahead dropdown-menu"></ul>',item:'<li><a href="#"></a></li>'},a.fn.typeahead.Constructor=b,a(function(){a("body").on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(b){var c=a(this);if(c.data("typeahead"))return;b.preventDefault(),c.typeahead(c.data())})})}(window.jQuery);/* ===================================================
 * bootstrap-transition.js v2.0.0
 * http://twitter.github.com/bootstrap/javascript.html#transitions
 * ===================================================
 * Copyright 2012 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ========================================================== */

!function( $ ) {

  $(function () {

    "use strict"

    /* CSS TRANSITION SUPPORT (https://gist.github.com/373874)
     * ======================================================= */

    $.support.transition = (function () {
      var thisBody = document.body || document.documentElement
        , thisStyle = thisBody.style
        , support = thisStyle.transition !== undefined || thisStyle.WebkitTransition !== undefined || thisStyle.MozTransition !== undefined || thisStyle.MsTransition !== undefined || thisStyle.OTransition !== undefined

      return support && {
        end: (function () {
          var transitionEnd = "TransitionEnd"
          if ( $.browser.webkit ) {
          	transitionEnd = "webkitTransitionEnd"
          } else if ( $.browser.mozilla ) {
          	transitionEnd = "transitionend"
          } else if ( $.browser.opera ) {
          	transitionEnd = "oTransitionEnd"
          }
          return transitionEnd
        }())
      }
    })()

  })
  
}( window.jQuery )
/* ==========================================================
 * bootstrap-alert.js v2.0.0
 * http://twitter.github.com/bootstrap/javascript.html#alerts
 * ==========================================================
 * Copyright 2012 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ========================================================== */


!function( $ ){

  "use strict"

 /* ALERT CLASS DEFINITION
  * ====================== */

  var dismiss = '[data-dismiss="alert"]'
    , Alert = function ( el ) {
        $(el).on('click', dismiss, this.close)
      }

  Alert.prototype = {

    constructor: Alert

  , close: function ( e ) {
      var $this = $(this)
        , selector = $this.attr('data-target')
        , $parent

      if (!selector) {
        selector = $this.attr('href')
        selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
      }

      $parent = $(selector)
      $parent.trigger('close')

      e && e.preventDefault()

      $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent())

      $parent.removeClass('in')

      function removeElement() {
        $parent.remove()
        $parent.trigger('closed')
      }

      $.support.transition && $parent.hasClass('fade') ?
        $parent.on($.support.transition.end, removeElement) :
        removeElement()
    }

  }


 /* ALERT PLUGIN DEFINITION
  * ======================= */

  $.fn.alert = function ( option ) {
    return this.each(function () {
      var $this = $(this)
        , data = $this.data('alert')
      if (!data) $this.data('alert', (data = new Alert(this)))
      if (typeof option == 'string') data[option].call($this)
    })
  }

  $.fn.alert.Constructor = Alert


 /* ALERT DATA-API
  * ============== */

  $(function () {
    $('body').on('click.alert.data-api', dismiss, Alert.prototype.close)
  })

}( window.jQuery )
/* ============================================================
 * bootstrap-button.js v2.0.0
 * http://twitter.github.com/bootstrap/javascript.html#buttons
 * ============================================================
 * Copyright 2012 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ============================================================ */

!function( $ ){

  "use strict"

 /* BUTTON PUBLIC CLASS DEFINITION
  * ============================== */

  var Button = function ( element, options ) {
    this.$element = $(element)
    this.options = $.extend({}, $.fn.button.defaults, options)
  }

  Button.prototype = {

      constructor: Button

    , setState: function ( state ) {
        var d = 'disabled'
          , $el = this.$element
          , data = $el.data()
          , val = $el.is('input') ? 'val' : 'html'

        state = state + 'Text'
        data.resetText || $el.data('resetText', $el[val]())

        $el[val](data[state] || this.options[state])

        // push to event loop to allow forms to submit
        setTimeout(function () {
          state == 'loadingText' ?
            $el.addClass(d).attr(d, d) :
            $el.removeClass(d).removeAttr(d)
        }, 0)
      }

    , toggle: function () {
        var $parent = this.$element.parent('[data-toggle="buttons-radio"]')

        $parent && $parent
          .find('.active')
          .removeClass('active')

        this.$element.toggleClass('active')
      }

  }


 /* BUTTON PLUGIN DEFINITION
  * ======================== */

  $.fn.button = function ( option ) {
    return this.each(function () {
      var $this = $(this)
        , data = $this.data('button')
        , options = typeof option == 'object' && option
      if (!data) $this.data('button', (data = new Button(this, options)))
      if (option == 'toggle') data.toggle()
      else if (option) data.setState(option)
    })
  }

  $.fn.button.defaults = {
    loadingText: 'loading...'
  }

  $.fn.button.Constructor = Button


 /* BUTTON DATA-API
  * =============== */

  $(function () {
    $('body').on('click.button.data-api', '[data-toggle^=button]', function ( e ) {
      $(e.target).button('toggle')
    })
  })

}( window.jQuery )
/* ==========================================================
 * bootstrap-carousel.js v2.0.0
 * http://twitter.github.com/bootstrap/javascript.html#carousel
 * ==========================================================
 * Copyright 2012 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ========================================================== */


!function( $ ){

  "use strict"

 /* CAROUSEL CLASS DEFINITION
  * ========================= */

  var Carousel = function (element, options) {
    this.$element = $(element)
    this.options = $.extend({}, $.fn.carousel.defaults, options)
    this.options.slide && this.slide(this.options.slide)
  }

  Carousel.prototype = {

    cycle: function () {
      this.interval = setInterval($.proxy(this.next, this), this.options.interval)
      return this
    }

  , to: function (pos) {
      var $active = this.$element.find('.active')
        , children = $active.parent().children()
        , activePos = children.index($active)
        , that = this

      if (pos > (children.length - 1) || pos < 0) return

      if (this.sliding) {
        return this.$element.one('slid', function () {
          that.to(pos)
        })
      }

      if (activePos == pos) {
        return this.pause().cycle()
      }

      return this.slide(pos > activePos ? 'next' : 'prev', $(children[pos]))
    }

  , pause: function () {
      clearInterval(this.interval)
      return this
    }

  , next: function () {
      if (this.sliding) return
      return this.slide('next')
    }

  , prev: function () {
      if (this.sliding) return
      return this.slide('prev')
    }

  , slide: function (type, next) {
      var $active = this.$element.find('.active')
        , $next = next || $active[type]()
        , isCycling = this.interval
        , direction = type == 'next' ? 'left' : 'right'
        , fallback  = type == 'next' ? 'first' : 'last'
        , that = this

      this.sliding = true

      isCycling && this.pause()

      $next = $next.length ? $next : this.$element.find('.item')[fallback]()

      if (!$.support.transition && this.$element.hasClass('slide')) {
        this.$element.trigger('slide')
        $active.removeClass('active')
        $next.addClass('active')
        this.sliding = false
        this.$element.trigger('slid')
      } else {
        $next.addClass(type)
        $next[0].offsetWidth // force reflow
        $active.addClass(direction)
        $next.addClass(direction)
        this.$element.trigger('slide')
        this.$element.one($.support.transition.end, function () {
          $next.removeClass([type, direction].join(' ')).addClass('active')
          $active.removeClass(['active', direction].join(' '))
          that.sliding = false
          setTimeout(function () { that.$element.trigger('slid') }, 0)
        })
      }

      isCycling && this.cycle()

      return this
    }

  }


 /* CAROUSEL PLUGIN DEFINITION
  * ========================== */

  $.fn.carousel = function ( option ) {
    return this.each(function () {
      var $this = $(this)
        , data = $this.data('carousel')
        , options = typeof option == 'object' && option
      if (!data) $this.data('carousel', (data = new Carousel(this, options)))
      if (typeof option == 'number') data.to(option)
      else if (typeof option == 'string' || (option = options.slide)) data[option]()
      else data.cycle()
    })
  }

  $.fn.carousel.defaults = {
    interval: 5000
  }

  $.fn.carousel.Constructor = Carousel


 /* CAROUSEL DATA-API
  * ================= */

  $(function () {
    $('body').on('click.carousel.data-api', '[data-slide]', function ( e ) {
      var $this = $(this), href
        , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
        , options = !$target.data('modal') && $.extend({}, $target.data(), $this.data())
      $target.carousel(options)
      e.preventDefault()
    })
  })

}( window.jQuery )
/* =============================================================
 * bootstrap-collapse.js v2.0.0
 * http://twitter.github.com/bootstrap/javascript.html#collapse
 * =============================================================
 * Copyright 2012 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ============================================================ */

!function( $ ){

  "use strict"

  var Collapse = function ( element, options ) {
  	this.$element = $(element)
    this.options = $.extend({}, $.fn.collapse.defaults, options)

    if (this.options["parent"]) {
      this.$parent = $(this.options["parent"])
    }

    this.options.toggle && this.toggle()
  }

  Collapse.prototype = {

    constructor: Collapse

  , dimension: function () {
      var hasWidth = this.$element.hasClass('width')
      return hasWidth ? 'width' : 'height'
    }

  , show: function () {
      var dimension = this.dimension()
        , scroll = $.camelCase(['scroll', dimension].join('-'))
        , actives = this.$parent && this.$parent.find('.in')
        , hasData

      if (actives && actives.length) {
        hasData = actives.data('collapse')
        actives.collapse('hide')
        hasData || actives.data('collapse', null)
      }

      this.$element[dimension](0)
      this.transition('addClass', 'show', 'shown')
      this.$element[dimension](this.$element[0][scroll])

    }

  , hide: function () {
      var dimension = this.dimension()
      this.reset(this.$element[dimension]())
      this.transition('removeClass', 'hide', 'hidden')
      this.$element[dimension](0)
    }

  , reset: function ( size ) {
      var dimension = this.dimension()

      this.$element
        .removeClass('collapse')
        [dimension](size || 'auto')
        [0].offsetWidth

      this.$element.addClass('collapse')
    }

  , transition: function ( method, startEvent, completeEvent ) {
      var that = this
        , complete = function () {
            if (startEvent == 'show') that.reset()
            that.$element.trigger(completeEvent)
          }

      this.$element
        .trigger(startEvent)
        [method]('in')

      $.support.transition && this.$element.hasClass('collapse') ?
        this.$element.one($.support.transition.end, complete) :
        complete()
  	}

  , toggle: function () {
      this[this.$element.hasClass('in') ? 'hide' : 'show']()
  	}

  }

  /* COLLAPSIBLE PLUGIN DEFINITION
  * ============================== */

  $.fn.collapse = function ( option ) {
    return this.each(function () {
      var $this = $(this)
        , data = $this.data('collapse')
        , options = typeof option == 'object' && option
      if (!data) $this.data('collapse', (data = new Collapse(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }

  $.fn.collapse.defaults = {
    toggle: true
  }

  $.fn.collapse.Constructor = Collapse


 /* COLLAPSIBLE DATA-API
  * ==================== */

  $(function () {
    $('body').on('click.collapse.data-api', '[data-toggle=collapse]', function ( e ) {
      var $this = $(this), href
        , target = $this.attr('data-target')
          || e.preventDefault()
          || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
        , option = $(target).data('collapse') ? 'toggle' : $this.data()
      $(target).collapse(option)
    })
  })

}( window.jQuery )
/* ============================================================
 * bootstrap-dropdown.js v2.0.0
 * http://twitter.github.com/bootstrap/javascript.html#dropdowns
 * ============================================================
 * Copyright 2012 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ============================================================ */


!function( $ ){

  "use strict"

 /* DROPDOWN CLASS DEFINITION
  * ========================= */

  var toggle = '[data-toggle="dropdown"]'
    , Dropdown = function ( element ) {
        var $el = $(element).on('click.dropdown.data-api', this.toggle)
        $('html').on('click.dropdown.data-api', function () {
          $el.parent().removeClass('open')
        })
      }

  Dropdown.prototype = {

    constructor: Dropdown

  , toggle: function ( e ) {
      var $this = $(this)
        , selector = $this.attr('data-target')
        , $parent
        , isActive

      if (!selector) {
        selector = $this.attr('href')
        selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
      }

      $parent = $(selector)
      $parent.length || ($parent = $this.parent())

      isActive = $parent.hasClass('open')

      clearMenus()
      !isActive && $parent.toggleClass('open')

      return false
    }

  }

  function clearMenus() {
    $(toggle).parent().removeClass('open')
  }


  /* DROPDOWN PLUGIN DEFINITION
   * ========================== */

  $.fn.dropdown = function ( option ) {
    return this.each(function () {
      var $this = $(this)
        , data = $this.data('dropdown')
      if (!data) $this.data('dropdown', (data = new Dropdown(this)))
      if (typeof option == 'string') data[option].call($this)
    })
  }

  $.fn.dropdown.Constructor = Dropdown


  /* APPLY TO STANDARD DROPDOWN ELEMENTS
   * =================================== */

  $(function () {
    $('html').on('click.dropdown.data-api', clearMenus)
    $('body').on('click.dropdown.data-api', toggle, Dropdown.prototype.toggle)
  })

}( window.jQuery )
/* =========================================================
 * bootstrap-modal.js v2.0.0
 * http://twitter.github.com/bootstrap/javascript.html#modals
 * =========================================================
 * Copyright 2012 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ========================================================= */


!function( $ ){

  "use strict"

 /* MODAL CLASS DEFINITION
  * ====================== */

  var Modal = function ( content, options ) {
    this.options = $.extend({}, $.fn.modal.defaults, options)
    this.$element = $(content)
      .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this))
  }

  Modal.prototype = {

      constructor: Modal

    , toggle: function () {
        return this[!this.isShown ? 'show' : 'hide']()
      }

    , show: function () {
        var that = this

        if (this.isShown) return

        $('body').addClass('modal-open')

        this.isShown = true
        this.$element.trigger('show')

        escape.call(this)
        backdrop.call(this, function () {
          var transition = $.support.transition && that.$element.hasClass('fade')

          !that.$element.parent().length && that.$element.appendTo(document.body) //don't move modals dom position

          that.$element
            .show()

          if (transition) {
            that.$element[0].offsetWidth // force reflow
          }

          that.$element.addClass('in')

          transition ?
            that.$element.one($.support.transition.end, function () { that.$element.trigger('shown') }) :
            that.$element.trigger('shown')

        })
      }

    , hide: function ( e ) {
        e && e.preventDefault()

        if (!this.isShown) return

        var that = this
        this.isShown = false

        $('body').removeClass('modal-open')

        escape.call(this)

        this.$element
          .trigger('hide')
          .removeClass('in')

        $.support.transition && this.$element.hasClass('fade') ?
          hideWithTransition.call(this) :
          hideModal.call(this)
      }

  }


 /* MODAL PRIVATE METHODS
  * ===================== */

  function hideWithTransition() {
    var that = this
      , timeout = setTimeout(function () {
          that.$element.off($.support.transition.end)
          hideModal.call(that)
        }, 500)

    this.$element.one($.support.transition.end, function () {
      clearTimeout(timeout)
      hideModal.call(that)
    })
  }

  function hideModal( that ) {
    this.$element
      .hide()
      .trigger('hidden')

    backdrop.call(this)
  }

  function backdrop( callback ) {
    var that = this
      , animate = this.$element.hasClass('fade') ? 'fade' : ''

    if (this.isShown && this.options.backdrop) {
      var doAnimate = $.support.transition && animate

      this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
        .appendTo(document.body)

      if (this.options.backdrop != 'static') {
        this.$backdrop.click($.proxy(this.hide, this))
      }

      if (doAnimate) this.$backdrop[0].offsetWidth // force reflow

      this.$backdrop.addClass('in')

      doAnimate ?
        this.$backdrop.one($.support.transition.end, callback) :
        callback()

    } else if (!this.isShown && this.$backdrop) {
      this.$backdrop.removeClass('in')

      $.support.transition && this.$element.hasClass('fade')?
        this.$backdrop.one($.support.transition.end, $.proxy(removeBackdrop, this)) :
        removeBackdrop.call(this)

    } else if (callback) {
      callback()
    }
  }

  function removeBackdrop() {
    this.$backdrop.remove()
    this.$backdrop = null
  }

  function escape() {
    var that = this
    if (this.isShown && this.options.keyboard) {
      $(document).on('keyup.dismiss.modal', function ( e ) {
        e.which == 27 && that.hide()
      })
    } else if (!this.isShown) {
      $(document).off('keyup.dismiss.modal')
    }
  }


 /* MODAL PLUGIN DEFINITION
  * ======================= */

  $.fn.modal = function ( option ) {
    return this.each(function () {
      var $this = $(this)
        , data = $this.data('modal')
        , options = typeof option == 'object' && option
      if (!data) $this.data('modal', (data = new Modal(this, options)))
      if (typeof option == 'string') data[option]()
      else data.show()
    })
  }

  $.fn.modal.defaults = {
      backdrop: true
    , keyboard: true
  }

  $.fn.modal.Constructor = Modal


 /* MODAL DATA-API
  * ============== */

  $(function () {
    $('body').on('click.modal.data-api', '[data-toggle="modal"]', function ( e ) {
      var $this = $(this), href
        , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
        , option = $target.data('modal') ? 'toggle' : $.extend({}, $target.data(), $this.data())

      e.preventDefault()
      $target.modal(option)
    })
  })

}( window.jQuery )
/* ===========================================================
 * bootstrap-tooltip.js v2.0.0
 * http://twitter.github.com/bootstrap/javascript.html#tooltips
 * Inspired by the original jQuery.tipsy by Jason Frame
 * ===========================================================
 * Copyright 2012 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ========================================================== */

!function( $ ) {

  "use strict"

 /* TOOLTIP PUBLIC CLASS DEFINITION
  * =============================== */

  var Tooltip = function ( element, options ) {
    this.init('tooltip', element, options)
  }

  Tooltip.prototype = {

    constructor: Tooltip

  , init: function ( type, element, options ) {
      var eventIn
        , eventOut

      this.type = type
      this.$element = $(element)
      this.options = this.getOptions(options)
      this.enabled = true

      if (this.options.trigger != 'manual') {
        eventIn  = this.options.trigger == 'hover' ? 'mouseenter' : 'focus'
        eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur'
        this.$element.on(eventIn, this.options.selector, $.proxy(this.enter, this))
        this.$element.on(eventOut, this.options.selector, $.proxy(this.leave, this))
      }

      this.options.selector ?
        (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
        this.fixTitle()
    }

  , getOptions: function ( options ) {
      options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data())

      if (options.delay && typeof options.delay == 'number') {
        options.delay = {
          show: options.delay
        , hide: options.delay
        }
      }

      return options
    }

  , enter: function ( e ) {
      var self = $(e.currentTarget)[this.type](this._options).data(this.type)

      if (!self.options.delay || !self.options.delay.show) {
        self.show()
      } else {
        self.hoverState = 'in'
        setTimeout(function() {
          if (self.hoverState == 'in') {
            self.show()
          }
        }, self.options.delay.show)
      }
    }

  , leave: function ( e ) {
      var self = $(e.currentTarget)[this.type](this._options).data(this.type)

      if (!self.options.delay || !self.options.delay.hide) {
        self.hide()
      } else {
        self.hoverState = 'out'
        setTimeout(function() {
          if (self.hoverState == 'out') {
            self.hide()
          }
        }, self.options.delay.hide)
      }
    }

  , show: function () {
      var $tip
        , inside
        , pos
        , actualWidth
        , actualHeight
        , placement
        , tp

      if (this.hasContent() && this.enabled) {
        $tip = this.tip()
        this.setContent()

        if (this.options.animation) {
          $tip.addClass('fade')
        }

        placement = typeof this.options.placement == 'function' ?
          this.options.placement.call(this, $tip[0], this.$element[0]) :
          this.options.placement

        inside = /in/.test(placement)

        $tip
          .remove()
          .css({ top: 0, left: 0, display: 'block' })
          .appendTo(inside ? this.$element : document.body)

        pos = this.getPosition(inside)

        actualWidth = $tip[0].offsetWidth
        actualHeight = $tip[0].offsetHeight

        switch (inside ? placement.split(' ')[1] : placement) {
          case 'bottom':
            tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
            break
          case 'top':
            tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
            break
          case 'left':
            tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
            break
          case 'right':
            tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
            break
        }

        $tip
          .css(tp)
          .addClass(placement)
          .addClass('in')
      }
    }

  , setContent: function () {
      var $tip = this.tip()
      $tip.find('.tooltip-inner').html(this.getTitle())
      $tip.removeClass('fade in top bottom left right')
    }

  , hide: function () {
      var that = this
        , $tip = this.tip()

      $tip.removeClass('in')

      function removeWithAnimation() {
        var timeout = setTimeout(function () {
          $tip.off($.support.transition.end).remove()
        }, 500)

        $tip.one($.support.transition.end, function () {
          clearTimeout(timeout)
          $tip.remove()
        })
      }

      $.support.transition && this.$tip.hasClass('fade') ?
        removeWithAnimation() :
        $tip.remove()
    }

  , fixTitle: function () {
      var $e = this.$element
      if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
        $e.attr('data-original-title', $e.attr('title') || '').removeAttr('title')
      }
    }

  , hasContent: function () {
      return this.getTitle()
    }

  , getPosition: function (inside) {
      return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), {
        width: this.$element[0].offsetWidth
      , height: this.$element[0].offsetHeight
      })
    }

  , getTitle: function () {
      var title
        , $e = this.$element
        , o = this.options

      title = $e.attr('data-original-title')
        || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)

      title = title.toString().replace(/(^\s*|\s*$)/, "")

      return title
    }

  , tip: function () {
      return this.$tip = this.$tip || $(this.options.template)
    }

  , validate: function () {
      if (!this.$element[0].parentNode) {
        this.hide()
        this.$element = null
        this.options = null
      }
    }

  , enable: function () {
      this.enabled = true
    }

  , disable: function () {
      this.enabled = false
    }

  , toggleEnabled: function () {
      this.enabled = !this.enabled
    }

  , toggle: function () {
      this[this.tip().hasClass('in') ? 'hide' : 'show']()
    }

  }


 /* TOOLTIP PLUGIN DEFINITION
  * ========================= */

  $.fn.tooltip = function ( option ) {
    return this.each(function () {
      var $this = $(this)
        , data = $this.data('tooltip')
        , options = typeof option == 'object' && option
      if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }

  $.fn.tooltip.Constructor = Tooltip

  $.fn.tooltip.defaults = {
    animation: true
  , delay: 0
  , selector: false
  , placement: 'top'
  , trigger: 'hover'
  , title: ''
  , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
  }

}( window.jQuery )
/* ===========================================================
 * bootstrap-popover.js v2.0.0
 * http://twitter.github.com/bootstrap/javascript.html#popovers
 * ===========================================================
 * Copyright 2012 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * =========================================================== */


!function( $ ) {

 "use strict"

  var Popover = function ( element, options ) {
    this.init('popover', element, options)
  }

  /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js
     ========================================== */

  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {

    constructor: Popover

  , setContent: function () {
      var $tip = this.tip()
        , title = this.getTitle()
        , content = this.getContent()

      $tip.find('.popover-title')[ $.type(title) == 'object' ? 'append' : 'html' ](title)
      $tip.find('.popover-content > *')[ $.type(content) == 'object' ? 'append' : 'html' ](content)

      $tip.removeClass('fade top bottom left right in')
    }

  , hasContent: function () {
      return this.getTitle() || this.getContent()
    }

  , getContent: function () {
      var content
        , $e = this.$element
        , o = this.options

      content = $e.attr('data-content')
        || (typeof o.content == 'function' ? o.content.call($e[0]) :  o.content)

      content = content.toString().replace(/(^\s*|\s*$)/, "")

      return content
    }

  , tip: function() {
      if (!this.$tip) {
        this.$tip = $(this.options.template)
      }
      return this.$tip
    }

  })


 /* POPOVER PLUGIN DEFINITION
  * ======================= */

  $.fn.popover = function ( option ) {
    return this.each(function () {
      var $this = $(this)
        , data = $this.data('popover')
        , options = typeof option == 'object' && option
      if (!data) $this.data('popover', (data = new Popover(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }

  $.fn.popover.Constructor = Popover

  $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {
    placement: 'right'
  , content: ''
  , template: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>'
  })

}( window.jQuery )
/* =============================================================
 * bootstrap-scrollspy.js v2.0.0
 * http://twitter.github.com/bootstrap/javascript.html#scrollspy
 * =============================================================
 * Copyright 2012 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ============================================================== */

!function ( $ ) {

  "use strict"

  /* SCROLLSPY CLASS DEFINITION
   * ========================== */

  function ScrollSpy( element, options) {
    var process = $.proxy(this.process, this)
      , $element = $(element).is('body') ? $(window) : $(element)
      , href
    this.options = $.extend({}, $.fn.scrollspy.defaults, options)
    this.$scrollElement = $element.on('scroll.scroll.data-api', process)
    this.selector = (this.options.target
      || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
      || '') + ' .nav li > a'
    this.$body = $('body').on('click.scroll.data-api', this.selector, process)
    this.refresh()
    this.process()
  }

  ScrollSpy.prototype = {

      constructor: ScrollSpy

    , refresh: function () {
        this.targets = this.$body
          .find(this.selector)
          .map(function () {
            var href = $(this).attr('href')
            return /^#\w/.test(href) && $(href).length ? href : null
          })

        this.offsets = $.map(this.targets, function (id) {
          return $(id).position().top
        })
      }

    , process: function () {
        var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
          , offsets = this.offsets
          , targets = this.targets
          , activeTarget = this.activeTarget
          , i

        for (i = offsets.length; i--;) {
          activeTarget != targets[i]
            && scrollTop >= offsets[i]
            && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
            && this.activate( targets[i] )
        }
      }

    , activate: function (target) {
        var active

        this.activeTarget = target

        this.$body
          .find(this.selector).parent('.active')
          .removeClass('active')

        active = this.$body
          .find(this.selector + '[href="' + target + '"]')
          .parent('li')
          .addClass('active')

        if ( active.parent('.dropdown-menu') )  {
          active.closest('li.dropdown').addClass('active')
        }
      }

  }


 /* SCROLLSPY PLUGIN DEFINITION
  * =========================== */

  $.fn.scrollspy = function ( option ) {
    return this.each(function () {
      var $this = $(this)
        , data = $this.data('scrollspy')
        , options = typeof option == 'object' && option
      if (!data) $this.data('scrollspy', (data = new ScrollSpy(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }

  $.fn.scrollspy.Constructor = ScrollSpy

  $.fn.scrollspy.defaults = {
    offset: 10
  }


 /* SCROLLSPY DATA-API
  * ================== */

  $(function () {
    $('[data-spy="scroll"]').each(function () {
      var $spy = $(this)
      $spy.scrollspy($spy.data())
    })
  })

}( window.jQuery )
/* ========================================================
 * bootstrap-tab.js v2.0.0
 * http://twitter.github.com/bootstrap/javascript.html#tabs
 * ========================================================
 * Copyright 2012 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ======================================================== */


!function( $ ){

  "use strict"

 /* TAB CLASS DEFINITION
  * ==================== */

  var Tab = function ( element ) {
    this.element = $(element)
  }

  Tab.prototype = {

    constructor: Tab

  , show: function () {
      var $this = this.element
        , $ul = $this.closest('ul:not(.dropdown-menu)')
        , selector = $this.attr('data-target')
        , previous
        , $target

      if (!selector) {
        selector = $this.attr('href')
        selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
      }

      if ( $this.parent('li').hasClass('active') ) return

      previous = $ul.find('.active a').last()[0]

      $this.trigger({
        type: 'show'
      , relatedTarget: previous
      })

      $target = $(selector)

      this.activate($this.parent('li'), $ul)
      this.activate($target, $target.parent(), function () {
        $this.trigger({
          type: 'shown'
        , relatedTarget: previous
        })
      })
    }

  , activate: function ( element, container, callback) {
      var $active = container.find('> .active')
        , transition = callback
            && $.support.transition
            && $active.hasClass('fade')

      function next() {
        $active
          .removeClass('active')
          .find('> .dropdown-menu > .active')
          .removeClass('active')

        element.addClass('active')

        if (transition) {
          element[0].offsetWidth // reflow for transition
          element.addClass('in')
        } else {
          element.removeClass('fade')
        }

        if ( element.parent('.dropdown-menu') ) {
          element.closest('li.dropdown').addClass('active')
        }

        callback && callback()
      }

      transition ?
        $active.one($.support.transition.end, next) :
        next()

      $active.removeClass('in')
    }
  }


 /* TAB PLUGIN DEFINITION
  * ===================== */

  $.fn.tab = function ( option ) {
    return this.each(function () {
      var $this = $(this)
        , data = $this.data('tab')
      if (!data) $this.data('tab', (data = new Tab(this)))
      if (typeof option == 'string') data[option]()
    })
  }

  $.fn.tab.Constructor = Tab


 /* TAB DATA-API
  * ============ */

  $(function () {
    $('body').on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
      e.preventDefault()
      $(this).tab('show')
    })
  })

}( window.jQuery )
/* =============================================================
 * bootstrap-typeahead.js v2.0.0
 * http://twitter.github.com/bootstrap/javascript.html#typeahead
 * =============================================================
 * Copyright 2012 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ============================================================ */

!function( $ ){

  "use strict"

  var Typeahead = function ( element, options ) {
    this.$element = $(element)
    this.options = $.extend({}, $.fn.typeahead.defaults, options)
    this.matcher = this.options.matcher || this.matcher
    this.sorter = this.options.sorter || this.sorter
    this.highlighter = this.options.highlighter || this.highlighter
    this.$menu = $(this.options.menu).appendTo('body')
    this.source = this.options.source
    this.shown = false
    this.listen()
  }

  Typeahead.prototype = {

    constructor: Typeahead

  , select: function () {
      var val = this.$menu.find('.active').attr('data-value')
      this.$element.val(val)
      return this.hide()
    }

  , show: function () {
      var pos = $.extend({}, this.$element.offset(), {
        height: this.$element[0].offsetHeight
      })

      this.$menu.css({
        top: pos.top + pos.height
      , left: pos.left
      })

      this.$menu.show()
      this.shown = true
      return this
    }

  , hide: function () {
      this.$menu.hide()
      this.shown = false
      return this
    }

  , lookup: function (event) {
      var that = this
        , items
        , q

      this.query = this.$element.val()

      if (!this.query) {
        return this.shown ? this.hide() : this
      }

      items = $.grep(this.source, function (item) {
        if (that.matcher(item)) return item
      })

      items = this.sorter(items)

      if (!items.length) {
        return this.shown ? this.hide() : this
      }

      return this.render(items.slice(0, this.options.items)).show()
    }

  , matcher: function (item) {
      return ~item.toLowerCase().indexOf(this.query.toLowerCase())
    }

  , sorter: function (items) {
      var beginswith = []
        , caseSensitive = []
        , caseInsensitive = []
        , item

      while (item = items.shift()) {
        if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item)
        else if (~item.indexOf(this.query)) caseSensitive.push(item)
        else caseInsensitive.push(item)
      }

      return beginswith.concat(caseSensitive, caseInsensitive)
    }

  , highlighter: function (item) {
      return item.replace(new RegExp('(' + this.query + ')', 'ig'), function ($1, match) {
        return '<strong>' + match + '</strong>'
      })
    }

  , render: function (items) {
      var that = this

      items = $(items).map(function (i, item) {
        i = $(that.options.item).attr('data-value', item)
        i.find('a').html(that.highlighter(item))
        return i[0]
      })

      items.first().addClass('active')
      this.$menu.html(items)
      return this
    }

  , next: function (event) {
      var active = this.$menu.find('.active').removeClass('active')
        , next = active.next()

      if (!next.length) {
        next = $(this.$menu.find('li')[0])
      }

      next.addClass('active')
    }

  , prev: function (event) {
      var active = this.$menu.find('.active').removeClass('active')
        , prev = active.prev()

      if (!prev.length) {
        prev = this.$menu.find('li').last()
      }

      prev.addClass('active')
    }

  , listen: function () {
      this.$element
        .on('blur',     $.proxy(this.blur, this))
        .on('keypress', $.proxy(this.keypress, this))
        .on('keyup',    $.proxy(this.keyup, this))

      if ($.browser.webkit || $.browser.msie) {
        this.$element.on('keydown', $.proxy(this.keypress, this))
      }

      this.$menu
        .on('click', $.proxy(this.click, this))
        .on('mouseenter', 'li', $.proxy(this.mouseenter, this))
    }

  , keyup: function (e) {
      e.stopPropagation()
      e.preventDefault()

      switch(e.keyCode) {
        case 40: // down arrow
        case 38: // up arrow
          break

        case 9: // tab
        case 13: // enter
          if (!this.shown) return
          this.select()
          break

        case 27: // escape
          this.hide()
          break

        default:
          this.lookup()
      }

  }

  , keypress: function (e) {
      e.stopPropagation()
      if (!this.shown) return

      switch(e.keyCode) {
        case 9: // tab
        case 13: // enter
        case 27: // escape
          e.preventDefault()
          break

        case 38: // up arrow
          e.preventDefault()
          this.prev()
          break

        case 40: // down arrow
          e.preventDefault()
          this.next()
          break
      }
    }

  , blur: function (e) {
      var that = this
      e.stopPropagation()
      e.preventDefault()
      setTimeout(function () { that.hide() }, 150)
    }

  , click: function (e) {
      e.stopPropagation()
      e.preventDefault()
      this.select()
    }

  , mouseenter: function (e) {
      this.$menu.find('.active').removeClass('active')
      $(e.currentTarget).addClass('active')
    }

  }


  /* TYPEAHEAD PLUGIN DEFINITION
   * =========================== */

  $.fn.typeahead = function ( option ) {
    return this.each(function () {
      var $this = $(this)
        , data = $this.data('typeahead')
        , options = typeof option == 'object' && option
      if (!data) $this.data('typeahead', (data = new Typeahead(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }

  $.fn.typeahead.defaults = {
    source: []
  , items: 8
  , menu: '<ul class="typeahead dropdown-menu"></ul>'
  , item: '<li><a href="#"></a></li>'
  }

  $.fn.typeahead.Constructor = Typeahead


 /* TYPEAHEAD DATA-API
  * ================== */

  $(function () {
    $('body').on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) {
      var $this = $(this)
      if ($this.data('typeahead')) return
      e.preventDefault()
      $this.typeahead($this.data())
    })
  })

}( window.jQuery )
/*!
 * jQuery JavaScript Library v1.4.2
 * http://jquery.com/
 *
 * Copyright 2010, John Resig
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * Includes Sizzle.js
 * http://sizzlejs.com/
 * Copyright 2010, The Dojo Foundation
 * Released under the MIT, BSD, and GPL Licenses.
 *
 * Date: Sat Feb 13 22:33:48 2010 -0500
 */
(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML="   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);
var a=null;
PR.registerLangHandler(PR.createSimpleLexer([["pun",/^[:>?|]+/,a,":|>?"],["dec",/^%(?:YAML|TAG)[^\n\r#]+/,a,"%"],["typ",/^&\S+/,a,"&"],["typ",/^!\S*/,a,"!"],["str",/^"(?:[^"\\]|\\.)*(?:"|$)/,a,'"'],["str",/^'(?:[^']|'')*(?:'|$)/,a,"'"],["com",/^#[^\n\r]*/,a,"#"],["pln",/^\s+/,a," \t\r\n"]],[["dec",/^(?:---|\.\.\.)(?:[\n\r]|$)/],["pun",/^-/],["kwd",/^\w+:[\n\r ]/],["pln",/^\w+/]]),["yaml","yml"]);
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \xa0"],["pln",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])+(?:'|$)|`[^`]*(?:`|$))/,null,"\"'"]],[["com",/^(?:\/\/[^\n\r]*|\/\*[\S\s]*?\*\/)/],["pln",/^(?:[^"'/`]|\/(?![*/]))+/]]),["go"]);
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \xa0"],["str",/^"(?:""(?:""?(?!")|[^"\\]|\\.)*"{0,3}|(?:[^\n\r"\\]|\\.)*"?)/,null,'"'],["lit",/^`(?:[^\n\r\\`]|\\.)*`?/,null,"`"],["pun",/^[!#%&(--:-@[-^{-~]+/,null,"!#%&()*+,-:;<=>?@[\\]^{|}~"]],[["str",/^'(?:[^\n\r'\\]|\\(?:'|[^\n\r']+))'/],["lit",/^'[$A-Z_a-z][\w$]*(?![\w$'])/],["kwd",/^(?:abstract|case|catch|class|def|do|else|extends|final|finally|for|forSome|if|implicit|import|lazy|match|new|object|override|package|private|protected|requires|return|sealed|super|throw|trait|try|type|val|var|while|with|yield)\b/],
["lit",/^(?:true|false|null|this)\b/],["lit",/^(?:0(?:[0-7]+|x[\da-f]+)l?|(?:0|[1-9]\d*)(?:(?:\.\d+)?(?:e[+-]?\d+)?f?|l?)|\\.\d+(?:e[+-]?\d+)?f?)/i],["typ",/^[$_]*[A-Z][\d$A-Z_]*[a-z][\w$]*/],["pln",/^[$A-Z_a-z][\w$]*/],["com",/^\/(?:\/.*|\*(?:\/|\**[^*/])*(?:\*+\/?)?)/],["pun",/^(?:\.+|\/)/]]),["scala"]);
/*
 Copyright (C) 2011 Google Inc.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
*/
var a=null;
PR.registerLangHandler(PR.createSimpleLexer([["opn",/^[([{]+/,a,"([{"],["clo",/^[)\]}]+/,a,")]}"],["com",/^;[^\n\r]*/,a,";"],["pln",/^[\t\n\r \xa0]+/,a,"\t\n\r \xa0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,a,'"']],[["kwd",/^(?:def|if|do|let|quote|var|fn|loop|recur|throw|try|monitor-enter|monitor-exit|defmacro|defn|defn-|macroexpand|macroexpand-1|for|doseq|dosync|dotimes|and|or|when|not|assert|doto|proxy|defstruct|first|rest|cons|defprotocol|deftype|defrecord|reify|defmulti|defmethod|meta|with-meta|ns|in-ns|create-ns|import|intern|refer|alias|namespace|resolve|ref|deref|refset|new|set!|memfn|to-array|into-array|aset|gen-class|reduce|map|filter|find|nil?|empty?|hash-map|hash-set|vec|vector|seq|flatten|reverse|assoc|dissoc|list|list?|disj|get|union|difference|intersection|extend|extend-type|extend-protocol|prn)\b/,a],
["typ",/^:[\dA-Za-z-]+/]]),["clj"]);
var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;
(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a=
[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c<i;++c){var j=f[c];if(/\\[bdsw]/i.test(j))a.push(j);else{var j=m(j),d;c+2<i&&"-"===f[c+1]?(d=m(f[c+2]),c+=2):d=j;b.push([j,d]);d<65||j>122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c<b.length;++c)i=b[c],i[0]<=j[1]+1?j[1]=Math.max(j[1],i[1]):f.push(j=i);b=["["];o&&b.push("^");b.push.apply(b,a);for(c=0;c<
f.length;++c)i=f[c],b.push(e(i[0])),i[1]>i[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c<b;++c){var j=f[c];j==="("?++i:"\\"===j.charAt(0)&&(j=+j.substring(1))&&j<=i&&(d[j]=-1)}for(c=1;c<d.length;++c)-1===d[c]&&(d[c]=++t);for(i=c=0;c<b;++c)j=f[c],j==="("?(++i,d[i]===void 0&&(f[c]="(?:")):"\\"===j.charAt(0)&&
(j=+j.substring(1))&&j<=i&&(f[c]="\\"+d[i]);for(i=c=0;c<b;++c)"^"===f[c]&&"^"!==f[c+1]&&(f[c]="");if(a.ignoreCase&&s)for(c=0;c<b;++c)j=f[c],a=j.charAt(0),j.length>=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p<d;++p){var g=a[p];if(g.ignoreCase)l=!0;else if(/[a-z]/i.test(g.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){s=!0;l=!1;break}}for(var r=
{b:8,t:9,n:10,v:11,f:12,r:13},n=[],p=0,d=a.length;p<d;++p){g=a[p];if(g.global||g.multiline)throw Error(""+g);n.push("(?:"+y(g)+")")}return RegExp(n.join("|"),l?"gi":"g")}function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.className))break;for(var g=a.firstChild;g;g=g.nextSibling)m(g);g=a.nodeName;if("BR"===g||"LI"===g)h[s]="\n",t[s<<1]=y++,t[s++<<1|1]=a;break;case 3:case 4:g=a.nodeValue,g.length&&(g=p?g.replace(/\r\n?/g,"\n"):g.replace(/[\t\n\r ]+/g," "),h[s]=g,t[s<<1]=y,y+=g.length,
t[s++<<1|1]=a)}}var e=/(?:^|\s)nocode(?:\s|$)/,h=[],y=0,t=[],s=0,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=document.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);m(a);return{a:h.join("").replace(/\n$/,""),c:t}}function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}function x(a,m){function e(a){for(var l=a.d,p=[l,"pln"],d=0,g=a.a.match(y)||[],r={},n=0,z=g.length;n<z;++n){var f=g[n],b=r[f],o=void 0,c;if(typeof b===
"string")c=!1;else{var i=h[f.charAt(0)];if(i)o=f.match(i[1]),b=i[0];else{for(c=0;c<t;++c)if(i=m[c],o=f.match(i[1])){b=i[0];break}o||(b="pln")}if((c=b.length>=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m),
l=[],p={},d=0,g=e.length;d<g;++d){var r=e[d],n=r[3];if(n)for(var k=n.length;--k>=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,
q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/,
q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g,
"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a),
a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e}
for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g<d.length;++g)e(d[g]);m===(m|0)&&d[0].setAttribute("value",
m);var r=s.createElement("OL");r.className="linenums";for(var n=Math.max(0,m-1|0)||0,g=0,z=d.length;g<z;++g)l=d[g],l.className="L"+(g+n)%10,l.firstChild||l.appendChild(s.createTextNode("\xa0")),r.appendChild(l);a.appendChild(r)}function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*</.test(m)?"default-markup":"default-code";return A[a]}function E(a){var m=
a.g;try{var e=M(a.h),h=e.a;a.a=h;a.c=e.c;a.d=0;C(m,h)(a);var k=/\bMSIE\b/.test(navigator.userAgent),m=/\n/g,t=a.a,s=t.length,e=0,l=a.c,p=l.length,h=0,d=a.e,g=d.length,a=0;d[g]=s;var r,n;for(n=r=0;n<g;)d[n]!==d[n+2]?(d[r++]=d[n++],d[r++]=d[n++]):n+=2;g=r;for(n=r=0;n<g;){for(var z=d[n],f=d[n+1],b=n+2;b+2<=g&&d[b+1]===f;)b+=2;d[r++]=z;d[r++]=f;n=b}for(d.length=r;h<p;){var o=l[h+2]||s,c=d[a+2]||s,b=Math.min(o,c),i=l[h+1],j;if(i.nodeType!==1&&(j=t.substring(e,b))){k&&(j=j.replace(m,"\r"));i.nodeValue=
j;var u=i.ownerDocument,v=u.createElement("SPAN");v.className=d[a+1];var x=i.parentNode;x.replaceChild(v,i);v.appendChild(i);e<o&&(l[h+1]=i=u.createTextNode(t.substring(b,o)),x.insertBefore(i,v.nextSibling))}e=b;e>=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],
"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"],
H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],
J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+
I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),
["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",
/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),
["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes",
hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;if(k.indexOf("prettyprint")>=0){var k=k.match(g),f,b;if(b=
!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p<h.length?setTimeout(m,
250):a&&a()}for(var e=[document.getElementsByTagName("pre"),document.getElementsByTagName("code"),document.getElementsByTagName("xmp")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\blang(?:uage)?-([\w.]+)(?!\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",
PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ"}})();
var a=null;
PR.registerLangHandler(PR.createSimpleLexer([["str",/^(?:'(?:[^\n\r'\\]|\\.)*'|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,a,'"'],["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,a,"#"],["pln",/^\s+/,a," \r\n\t\xa0"]],[["str",/^@"(?:[^"]|"")*(?:"|$)/,a],["str",/^<#[^#>]*(?:#>|$)/,a],["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,a],["com",/^\/\/[^\n\r]*/,a],["com",/^\/\*[\S\s]*?(?:\*\/|$)/,
a],["kwd",/^(?:abstract|and|as|base|catch|class|def|delegate|enum|event|extern|false|finally|fun|implements|interface|internal|is|macro|match|matches|module|mutable|namespace|new|null|out|override|params|partial|private|protected|public|ref|sealed|static|struct|syntax|this|throw|true|try|type|typeof|using|variant|virtual|volatile|when|where|with|assert|assert2|async|break|checked|continue|do|else|ensures|for|foreach|if|late|lock|new|nolate|otherwise|regexp|repeat|requires|return|surroundwith|unchecked|unless|using|while|yield)\b/,
a],["typ",/^(?:array|bool|byte|char|decimal|double|float|int|list|long|object|sbyte|short|string|ulong|uint|ufloat|ulong|ushort|void)\b/,a],["lit",/^@[$_a-z][\w$@]*/i,a],["typ",/^@[A-Z]+[a-z][\w$@]*/,a],["pln",/^'?[$_a-z][\w$@]*/i,a],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,a,"0123456789"],["pun",/^.[^\s\w"-$'./@`]*/,a]]),["n","nemerle"]);
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t-\r ]+/,null,"\t\n\r "],["str",/^"(?:[^\n\f\r"\\]|\\[\S\s])*(?:"|$)/,null,'"'],["str",/^'(?:[^\n\f\r'\\]|\\[^&])'?/,null,"'"],["lit",/^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+-]?\d+)?)/i,null,"0123456789"]],[["com",/^(?:--+[^\n\f\r]*|{-(?:[^-]|-+[^}-])*-})/],["kwd",/^(?:case|class|data|default|deriving|do|else|if|import|in|infix|infixl|infixr|instance|let|module|newtype|of|then|type|where|_)(?=[^\d'A-Za-z]|$)/,
null],["pln",/^(?:[A-Z][\w']*\.)*[A-Za-z][\w']*/],["pun",/^[^\d\t-\r "'A-Za-z]+/]]),["hs"]);
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\d\t a-gi-z\xa0]+/,null,"\t \xa0abcdefgijklmnopqrstuvwxyz0123456789"],["pun",/^[*=[\]^~]+/,null,"=*~^[]"]],[["lang-wiki.meta",/(?:^^|\r\n?|\n)(#[a-z]+)\b/],["lit",/^[A-Z][a-z][\da-z]+[A-Z][a-z][^\W_]+\b/],["lang-",/^{{{([\S\s]+?)}}}/],["lang-",/^`([^\n\r`]+)`/],["str",/^https?:\/\/[^\s#/?]*(?:\/[^\s#?]*)?(?:\?[^\s#]*)?(?:#\S*)?/i],["pln",/^(?:\r\n|[\S\s])[^\n\r#*=A-[^`h{~]*/]]),["wiki"]);
PR.registerLangHandler(PR.createSimpleLexer([["kwd",/^#[a-z]+/i,null,"#"]],[]),["wiki.meta"]);
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0\u2028\u2029]+/,null,"\t\n\r \xa0  "],["str",/^(?:["\u201c\u201d](?:[^"\u201c\u201d]|["\u201c\u201d]{2})(?:["\u201c\u201d]c|$)|["\u201c\u201d](?:[^"\u201c\u201d]|["\u201c\u201d]{2})*(?:["\u201c\u201d]|$))/i,null,'"“”'],["com",/^['\u2018\u2019].*/,null,"'‘’"]],[["kwd",/^(?:addhandler|addressof|alias|and|andalso|ansi|as|assembly|auto|boolean|byref|byte|byval|call|case|catch|cbool|cbyte|cchar|cdate|cdbl|cdec|char|cint|class|clng|cobj|const|cshort|csng|cstr|ctype|date|decimal|declare|default|delegate|dim|directcast|do|double|each|else|elseif|end|endif|enum|erase|error|event|exit|finally|for|friend|function|get|gettype|gosub|goto|handles|if|implements|imports|in|inherits|integer|interface|is|let|lib|like|long|loop|me|mod|module|mustinherit|mustoverride|mybase|myclass|namespace|new|next|not|notinheritable|notoverridable|object|on|option|optional|or|orelse|overloads|overridable|overrides|paramarray|preserve|private|property|protected|public|raiseevent|readonly|redim|removehandler|resume|return|select|set|shadows|shared|short|single|static|step|stop|string|structure|sub|synclock|then|throw|to|try|typeof|unicode|until|variant|wend|when|while|with|withevents|writeonly|xor|endif|gosub|let|variant|wend)\b/i,
null],["com",/^rem.*/i],["lit",/^(?:true\b|false\b|nothing\b|\d+(?:e[+-]?\d+[dfr]?|[dfilrs])?|(?:&h[\da-f]+|&o[0-7]+)[ils]?|\d*\.\d+(?:e[+-]?\d+)?[dfr]?|#\s+(?:\d+[/-]\d+[/-]\d+(?:\s+\d+:\d+(?::\d+)?(\s*(?:am|pm))?)?|\d+:\d+(?::\d+)?(\s*(?:am|pm))?)\s+#)/i],["pln",/^(?:(?:[a-z]|_\w)\w*|\[(?:[a-z]|_\w)\w*])/i],["pun",/^[^\w\t\n\r "'[\]\xa0\u2018\u2019\u201c\u201d\u2028\u2029]+/],["pun",/^(?:\[|])/]]),["vb","vbs"]);
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \xa0"]],[["str",/^(?:[box]?"(?:[^"]|"")*"|'.')/i],["com",/^--[^\n\r]*/],["kwd",/^(?:abs|access|after|alias|all|and|architecture|array|assert|attribute|begin|block|body|buffer|bus|case|component|configuration|constant|disconnect|downto|else|elsif|end|entity|exit|file|for|function|generate|generic|group|guarded|if|impure|in|inertial|inout|is|label|library|linkage|literal|loop|map|mod|nand|new|next|nor|not|null|of|on|open|or|others|out|package|port|postponed|procedure|process|pure|range|record|register|reject|rem|report|return|rol|ror|select|severity|shared|signal|sla|sll|sra|srl|subtype|then|to|transport|type|unaffected|units|until|use|variable|wait|when|while|with|xnor|xor)(?=[^\w-]|$)/i,
null],["typ",/^(?:bit|bit_vector|character|boolean|integer|real|time|string|severity_level|positive|natural|signed|unsigned|line|text|std_u?logic(?:_vector)?)(?=[^\w-]|$)/i,null],["typ",/^'(?:active|ascending|base|delayed|driving|driving_value|event|high|image|instance_name|last_active|last_event|last_value|left|leftof|length|low|path_name|pos|pred|quiet|range|reverse_range|right|rightof|simple_name|stable|succ|transaction|val|value)(?=[^\w-]|$)/i,null],["lit",/^\d+(?:_\d+)*(?:#[\w.\\]+#(?:[+-]?\d+(?:_\d+)*)?|(?:\.\d+(?:_\d+)*)?(?:e[+-]?\d+(?:_\d+)*)?)/i],
["pln",/^(?:[a-z]\w*|\\[^\\]*\\)/i],["pun",/^[^\w\t\n\r "'\xa0][^\w\t\n\r "'\xa0-]*/]]),["vhdl","vhd"]);
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \xa0"],["str",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$))/,null,"\"'"]],[["com",/^--(?:\[(=*)\[[\S\s]*?(?:]\1]|$)|[^\n\r]*)/],["str",/^\[(=*)\[[\S\s]*?(?:]\1]|$)/],["kwd",/^(?:and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/,null],["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i],
["pln",/^[_a-z]\w*/i],["pun",/^[^\w\t\n\r \xa0][^\w\t\n\r "'+=\xa0-]*/]]),["lua"]);
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \xa0"],["com",/^%[^\n\r]*/,null,"%"]],[["kwd",/^\\[@-Za-z]+/],["kwd",/^\\./],["typ",/^[$&]/],["lit",/[+-]?(?:\.\d+|\d+(?:\.\d*)?)(cm|em|ex|in|pc|pt|bp|mm)/i],["pun",/^[()=[\]{}]+/]]),["latex","tex"]);
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \xa0"],["str",/^(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')/,null,"\"'"]],[["com",/^(?:--[^\n\r]*|\/\*[\S\s]*?(?:\*\/|$))/],["kwd",/^(?:add|all|alter|and|any|as|asc|authorization|backup|begin|between|break|browse|bulk|by|cascade|case|check|checkpoint|close|clustered|coalesce|collate|column|commit|compute|constraint|contains|containstable|continue|convert|create|cross|current|current_date|current_time|current_timestamp|current_user|cursor|database|dbcc|deallocate|declare|default|delete|deny|desc|disk|distinct|distributed|double|drop|dummy|dump|else|end|errlvl|escape|except|exec|execute|exists|exit|fetch|file|fillfactor|for|foreign|freetext|freetexttable|from|full|function|goto|grant|group|having|holdlock|identity|identitycol|identity_insert|if|in|index|inner|insert|intersect|into|is|join|key|kill|left|like|lineno|load|match|merge|national|nocheck|nonclustered|not|null|nullif|of|off|offsets|on|open|opendatasource|openquery|openrowset|openxml|option|or|order|outer|over|percent|plan|precision|primary|print|proc|procedure|public|raiserror|read|readtext|reconfigure|references|replication|restore|restrict|return|revoke|right|rollback|rowcount|rowguidcol|rule|save|schema|select|session_user|set|setuser|shutdown|some|statistics|system_user|table|textsize|then|to|top|tran|transaction|trigger|truncate|tsequal|union|unique|update|updatetext|use|user|using|values|varying|view|waitfor|when|where|while|with|writetext)(?=[^\w-]|$)/i,
null],["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i],["pln",/^[_a-z][\w-]*/i],["pun",/^[^\w\t\n\r "'\xa0][^\w\t\n\r "'+\xa0-]*/]]),["sql"]);
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n"]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com",
/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]);
PR.registerLangHandler(PR.sourceDecorator({keywords:"bytes,default,double,enum,extend,extensions,false,group,import,max,message,option,optional,package,repeated,required,returns,rpc,service,syntax,to,true",types:/^(bool|(double|s?fixed|[su]?int)(32|64)|float|string)\b/,cStyleComments:!0}),["proto"]);
PR.registerLangHandler(PR.createSimpleLexer([["com",/^#[^\n\r]*/,null,"#"],["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \xa0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,null,'"']],[["kwd",/^(?:ADS|AD|AUG|BZF|BZMF|CAE|CAF|CA|CCS|COM|CS|DAS|DCA|DCOM|DCS|DDOUBL|DIM|DOUBLE|DTCB|DTCF|DV|DXCH|EDRUPT|EXTEND|INCR|INDEX|NDX|INHINT|LXCH|MASK|MSK|MP|MSU|NOOP|OVSK|QXCH|RAND|READ|RELINT|RESUME|RETURN|ROR|RXOR|SQUARE|SU|TCR|TCAA|OVSK|TCF|TC|TS|WAND|WOR|WRITE|XCH|XLQ|XXALQ|ZL|ZQ|ADD|ADZ|SUB|SUZ|MPY|MPR|MPZ|DVP|COM|ABS|CLA|CLZ|LDQ|STO|STQ|ALS|LLS|LRS|TRA|TSQ|TMI|TOV|AXT|TIX|DLY|INP|OUT)\s/,
null],["typ",/^(?:-?GENADR|=MINUS|2BCADR|VN|BOF|MM|-?2CADR|-?[1-6]DNADR|ADRES|BBCON|[ES]?BANK=?|BLOCK|BNKSUM|E?CADR|COUNT\*?|2?DEC\*?|-?DNCHAN|-?DNPTR|EQUALS|ERASE|MEMORY|2?OCT|REMADR|SETLOC|SUBRO|ORG|BSS|BES|SYN|EQU|DEFINE|END)\s/,null],["lit",/^'(?:-*(?:\w|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?)?/],["pln",/^-*(?:[!-z]|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?/],["pun",/^[^\w\t\n\r "'-);\\\xa0]+/]]),["apollo","agc","aea"]);
PR.registerLangHandler(PR.createSimpleLexer([["var pln",/^\$[\w-]+/,null,"$"]],[["pln",/^[\s=][<>][\s=]/],["lit",/^@[\w-]+/],["tag",/^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["com",/^\(:[\S\s]*?:\)/],["pln",/^[(),/;[\]{}]$/],["str",/^(?:"(?:[^"\\{]|\\[\S\s])*(?:"|$)|'(?:[^'\\{]|\\[\S\s])*(?:'|$))/,null,"\"'"],["kwd",/^(?:xquery|where|version|variable|union|typeswitch|treat|to|then|text|stable|sortby|some|self|schema|satisfies|returns|return|ref|processing-instruction|preceding-sibling|preceding|precedes|parent|only|of|node|namespace|module|let|item|intersect|instance|in|import|if|function|for|follows|following-sibling|following|external|except|every|else|element|descending|descendant-or-self|descendant|define|default|declare|comment|child|cast|case|before|attribute|assert|ascending|as|ancestor-or-self|ancestor|after|eq|order|by|or|and|schema-element|document-node|node|at)\b/],
["typ",/^(?:xs:yearMonthDuration|xs:unsignedLong|xs:time|xs:string|xs:short|xs:QName|xs:Name|xs:long|xs:integer|xs:int|xs:gYearMonth|xs:gYear|xs:gMonthDay|xs:gDay|xs:float|xs:duration|xs:double|xs:decimal|xs:dayTimeDuration|xs:dateTime|xs:date|xs:byte|xs:boolean|xs:anyURI|xf:yearMonthDuration)\b/,null],["fun pln",/^(?:xp:dereference|xinc:node-expand|xinc:link-references|xinc:link-expand|xhtml:restructure|xhtml:clean|xhtml:add-lists|xdmp:zip-manifest|xdmp:zip-get|xdmp:zip-create|xdmp:xquery-version|xdmp:word-convert|xdmp:with-namespaces|xdmp:version|xdmp:value|xdmp:user-roles|xdmp:user-last-login|xdmp:user|xdmp:url-encode|xdmp:url-decode|xdmp:uri-is-file|xdmp:uri-format|xdmp:uri-content-type|xdmp:unquote|xdmp:unpath|xdmp:triggers-database|xdmp:trace|xdmp:to-json|xdmp:tidy|xdmp:subbinary|xdmp:strftime|xdmp:spawn-in|xdmp:spawn|xdmp:sleep|xdmp:shutdown|xdmp:set-session-field|xdmp:set-response-encoding|xdmp:set-response-content-type|xdmp:set-response-code|xdmp:set-request-time-limit|xdmp:set|xdmp:servers|xdmp:server-status|xdmp:server-name|xdmp:server|xdmp:security-database|xdmp:security-assert|xdmp:schema-database|xdmp:save|xdmp:role-roles|xdmp:role|xdmp:rethrow|xdmp:restart|xdmp:request-timestamp|xdmp:request-status|xdmp:request-cancel|xdmp:request|xdmp:redirect-response|xdmp:random|xdmp:quote|xdmp:query-trace|xdmp:query-meters|xdmp:product-edition|xdmp:privilege-roles|xdmp:privilege|xdmp:pretty-print|xdmp:powerpoint-convert|xdmp:platform|xdmp:permission|xdmp:pdf-convert|xdmp:path|xdmp:octal-to-integer|xdmp:node-uri|xdmp:node-replace|xdmp:node-kind|xdmp:node-insert-child|xdmp:node-insert-before|xdmp:node-insert-after|xdmp:node-delete|xdmp:node-database|xdmp:mul64|xdmp:modules-root|xdmp:modules-database|xdmp:merging|xdmp:merge-cancel|xdmp:merge|xdmp:md5|xdmp:logout|xdmp:login|xdmp:log-level|xdmp:log|xdmp:lock-release|xdmp:lock-acquire|xdmp:load|xdmp:invoke-in|xdmp:invoke|xdmp:integer-to-octal|xdmp:integer-to-hex|xdmp:http-put|xdmp:http-post|xdmp:http-options|xdmp:http-head|xdmp:http-get|xdmp:http-delete|xdmp:hosts|xdmp:host-status|xdmp:host-name|xdmp:host|xdmp:hex-to-integer|xdmp:hash64|xdmp:hash32|xdmp:has-privilege|xdmp:groups|xdmp:group-serves|xdmp:group-servers|xdmp:group-name|xdmp:group-hosts|xdmp:group|xdmp:get-session-field-names|xdmp:get-session-field|xdmp:get-response-encoding|xdmp:get-response-code|xdmp:get-request-username|xdmp:get-request-user|xdmp:get-request-url|xdmp:get-request-protocol|xdmp:get-request-path|xdmp:get-request-method|xdmp:get-request-header-names|xdmp:get-request-header|xdmp:get-request-field-names|xdmp:get-request-field-filename|xdmp:get-request-field-content-type|xdmp:get-request-field|xdmp:get-request-client-certificate|xdmp:get-request-client-address|xdmp:get-request-body|xdmp:get-current-user|xdmp:get-current-roles|xdmp:get|xdmp:function-name|xdmp:function-module|xdmp:function|xdmp:from-json|xdmp:forests|xdmp:forest-status|xdmp:forest-restore|xdmp:forest-restart|xdmp:forest-name|xdmp:forest-delete|xdmp:forest-databases|xdmp:forest-counts|xdmp:forest-clear|xdmp:forest-backup|xdmp:forest|xdmp:filesystem-file|xdmp:filesystem-directory|xdmp:exists|xdmp:excel-convert|xdmp:eval-in|xdmp:eval|xdmp:estimate|xdmp:email|xdmp:element-content-type|xdmp:elapsed-time|xdmp:document-set-quality|xdmp:document-set-property|xdmp:document-set-properties|xdmp:document-set-permissions|xdmp:document-set-collections|xdmp:document-remove-properties|xdmp:document-remove-permissions|xdmp:document-remove-collections|xdmp:document-properties|xdmp:document-locks|xdmp:document-load|xdmp:document-insert|xdmp:document-get-quality|xdmp:document-get-properties|xdmp:document-get-permissions|xdmp:document-get-collections|xdmp:document-get|xdmp:document-forest|xdmp:document-delete|xdmp:document-add-properties|xdmp:document-add-permissions|xdmp:document-add-collections|xdmp:directory-properties|xdmp:directory-locks|xdmp:directory-delete|xdmp:directory-create|xdmp:directory|xdmp:diacritic-less|xdmp:describe|xdmp:default-permissions|xdmp:default-collections|xdmp:databases|xdmp:database-restore-validate|xdmp:database-restore-status|xdmp:database-restore-cancel|xdmp:database-restore|xdmp:database-name|xdmp:database-forests|xdmp:database-backup-validate|xdmp:database-backup-status|xdmp:database-backup-purge|xdmp:database-backup-cancel|xdmp:database-backup|xdmp:database|xdmp:collection-properties|xdmp:collection-locks|xdmp:collection-delete|xdmp:collation-canonical-uri|xdmp:castable-as|xdmp:can-grant-roles|xdmp:base64-encode|xdmp:base64-decode|xdmp:architecture|xdmp:apply|xdmp:amp-roles|xdmp:amp|xdmp:add64|xdmp:add-response-header|xdmp:access|trgr:trigger-set-recursive|trgr:trigger-set-permissions|trgr:trigger-set-name|trgr:trigger-set-module|trgr:trigger-set-event|trgr:trigger-set-description|trgr:trigger-remove-permissions|trgr:trigger-module|trgr:trigger-get-permissions|trgr:trigger-enable|trgr:trigger-disable|trgr:trigger-database-online-event|trgr:trigger-data-event|trgr:trigger-add-permissions|trgr:remove-trigger|trgr:property-content|trgr:pre-commit|trgr:post-commit|trgr:get-trigger-by-id|trgr:get-trigger|trgr:document-scope|trgr:document-content|trgr:directory-scope|trgr:create-trigger|trgr:collection-scope|trgr:any-property-content|thsr:set-entry|thsr:remove-term|thsr:remove-synonym|thsr:remove-entry|thsr:query-lookup|thsr:lookup|thsr:load|thsr:insert|thsr:expand|thsr:add-synonym|spell:suggest-detailed|spell:suggest|spell:remove-word|spell:make-dictionary|spell:load|spell:levenshtein-distance|spell:is-correct|spell:insert|spell:double-metaphone|spell:add-word|sec:users-collection|sec:user-set-roles|sec:user-set-password|sec:user-set-name|sec:user-set-description|sec:user-set-default-permissions|sec:user-set-default-collections|sec:user-remove-roles|sec:user-privileges|sec:user-get-roles|sec:user-get-description|sec:user-get-default-permissions|sec:user-get-default-collections|sec:user-doc-permissions|sec:user-doc-collections|sec:user-add-roles|sec:unprotect-collection|sec:uid-for-name|sec:set-realm|sec:security-version|sec:security-namespace|sec:security-installed|sec:security-collection|sec:roles-collection|sec:role-set-roles|sec:role-set-name|sec:role-set-description|sec:role-set-default-permissions|sec:role-set-default-collections|sec:role-remove-roles|sec:role-privileges|sec:role-get-roles|sec:role-get-description|sec:role-get-default-permissions|sec:role-get-default-collections|sec:role-doc-permissions|sec:role-doc-collections|sec:role-add-roles|sec:remove-user|sec:remove-role-from-users|sec:remove-role-from-role|sec:remove-role-from-privileges|sec:remove-role-from-amps|sec:remove-role|sec:remove-privilege|sec:remove-amp|sec:protect-collection|sec:privileges-collection|sec:privilege-set-roles|sec:privilege-set-name|sec:privilege-remove-roles|sec:privilege-get-roles|sec:privilege-add-roles|sec:priv-doc-permissions|sec:priv-doc-collections|sec:get-user-names|sec:get-unique-elem-id|sec:get-role-names|sec:get-role-ids|sec:get-privilege|sec:get-distinct-permissions|sec:get-collection|sec:get-amp|sec:create-user-with-role|sec:create-user|sec:create-role|sec:create-privilege|sec:create-amp|sec:collections-collection|sec:collection-set-permissions|sec:collection-remove-permissions|sec:collection-get-permissions|sec:collection-add-permissions|sec:check-admin|sec:amps-collection|sec:amp-set-roles|sec:amp-remove-roles|sec:amp-get-roles|sec:amp-doc-permissions|sec:amp-doc-collections|sec:amp-add-roles|search:unparse|search:suggest|search:snippet|search:search|search:resolve-nodes|search:resolve|search:remove-constraint|search:parse|search:get-default-options|search:estimate|search:check-options|prof:value|prof:reset|prof:report|prof:invoke|prof:eval|prof:enable|prof:disable|prof:allowed|ppt:clean|pki:template-set-request|pki:template-set-name|pki:template-set-key-type|pki:template-set-key-options|pki:template-set-description|pki:template-in-use|pki:template-get-version|pki:template-get-request|pki:template-get-name|pki:template-get-key-type|pki:template-get-key-options|pki:template-get-id|pki:template-get-description|pki:need-certificate|pki:is-temporary|pki:insert-trusted-certificates|pki:insert-template|pki:insert-signed-certificates|pki:insert-certificate-revocation-list|pki:get-trusted-certificate-ids|pki:get-template-ids|pki:get-template-certificate-authority|pki:get-template-by-name|pki:get-template|pki:get-pending-certificate-requests-xml|pki:get-pending-certificate-requests-pem|pki:get-pending-certificate-request|pki:get-certificates-for-template-xml|pki:get-certificates-for-template|pki:get-certificates|pki:get-certificate-xml|pki:get-certificate-pem|pki:get-certificate|pki:generate-temporary-certificate-if-necessary|pki:generate-temporary-certificate|pki:generate-template-certificate-authority|pki:generate-certificate-request|pki:delete-template|pki:delete-certificate|pki:create-template|pdf:make-toc|pdf:insert-toc-headers|pdf:get-toc|pdf:clean|p:status-transition|p:state-transition|p:remove|p:pipelines|p:insert|p:get-by-id|p:get|p:execute|p:create|p:condition|p:collection|p:action|ooxml:runs-merge|ooxml:package-uris|ooxml:package-parts-insert|ooxml:package-parts|msword:clean|mcgm:polygon|mcgm:point|mcgm:geospatial-query-from-elements|mcgm:geospatial-query|mcgm:circle|math:tanh|math:tan|math:sqrt|math:sinh|math:sin|math:pow|math:modf|math:log10|math:log|math:ldexp|math:frexp|math:fmod|math:floor|math:fabs|math:exp|math:cosh|math:cos|math:ceil|math:atan2|math:atan|math:asin|math:acos|map:put|map:map|map:keys|map:get|map:delete|map:count|map:clear|lnk:to|lnk:remove|lnk:insert|lnk:get|lnk:from|lnk:create|kml:polygon|kml:point|kml:interior-polygon|kml:geospatial-query-from-elements|kml:geospatial-query|kml:circle|kml:box|gml:polygon|gml:point|gml:interior-polygon|gml:geospatial-query-from-elements|gml:geospatial-query|gml:circle|gml:box|georss:point|georss:geospatial-query|georss:circle|geo:polygon|geo:point|geo:interior-polygon|geo:geospatial-query-from-elements|geo:geospatial-query|geo:circle|geo:box|fn:zero-or-one|fn:years-from-duration|fn:year-from-dateTime|fn:year-from-date|fn:upper-case|fn:unordered|fn:true|fn:translate|fn:trace|fn:tokenize|fn:timezone-from-time|fn:timezone-from-dateTime|fn:timezone-from-date|fn:sum|fn:subtract-dateTimes-yielding-yearMonthDuration|fn:subtract-dateTimes-yielding-dayTimeDuration|fn:substring-before|fn:substring-after|fn:substring|fn:subsequence|fn:string-to-codepoints|fn:string-pad|fn:string-length|fn:string-join|fn:string|fn:static-base-uri|fn:starts-with|fn:seconds-from-time|fn:seconds-from-duration|fn:seconds-from-dateTime|fn:round-half-to-even|fn:round|fn:root|fn:reverse|fn:resolve-uri|fn:resolve-QName|fn:replace|fn:remove|fn:QName|fn:prefix-from-QName|fn:position|fn:one-or-more|fn:number|fn:not|fn:normalize-unicode|fn:normalize-space|fn:node-name|fn:node-kind|fn:nilled|fn:namespace-uri-from-QName|fn:namespace-uri-for-prefix|fn:namespace-uri|fn:name|fn:months-from-duration|fn:month-from-dateTime|fn:month-from-date|fn:minutes-from-time|fn:minutes-from-duration|fn:minutes-from-dateTime|fn:min|fn:max|fn:matches|fn:lower-case|fn:local-name-from-QName|fn:local-name|fn:last|fn:lang|fn:iri-to-uri|fn:insert-before|fn:index-of|fn:in-scope-prefixes|fn:implicit-timezone|fn:idref|fn:id|fn:hours-from-time|fn:hours-from-duration|fn:hours-from-dateTime|fn:floor|fn:false|fn:expanded-QName|fn:exists|fn:exactly-one|fn:escape-uri|fn:escape-html-uri|fn:error|fn:ends-with|fn:encode-for-uri|fn:empty|fn:document-uri|fn:doc-available|fn:doc|fn:distinct-values|fn:distinct-nodes|fn:default-collation|fn:deep-equal|fn:days-from-duration|fn:day-from-dateTime|fn:day-from-date|fn:data|fn:current-time|fn:current-dateTime|fn:current-date|fn:count|fn:contains|fn:concat|fn:compare|fn:collection|fn:codepoints-to-string|fn:codepoint-equal|fn:ceiling|fn:boolean|fn:base-uri|fn:avg|fn:adjust-time-to-timezone|fn:adjust-dateTime-to-timezone|fn:adjust-date-to-timezone|fn:abs|feed:unsubscribe|feed:subscription|feed:subscribe|feed:request|feed:item|feed:description|excel:clean|entity:enrich|dom:set-pipelines|dom:set-permissions|dom:set-name|dom:set-evaluation-context|dom:set-domain-scope|dom:set-description|dom:remove-pipeline|dom:remove-permissions|dom:remove|dom:get|dom:evaluation-context|dom:domains|dom:domain-scope|dom:create|dom:configuration-set-restart-user|dom:configuration-set-permissions|dom:configuration-set-evaluation-context|dom:configuration-set-default-domain|dom:configuration-get|dom:configuration-create|dom:collection|dom:add-pipeline|dom:add-permissions|dls:retention-rules|dls:retention-rule-remove|dls:retention-rule-insert|dls:retention-rule|dls:purge|dls:node-expand|dls:link-references|dls:link-expand|dls:documents-query|dls:document-versions-query|dls:document-version-uri|dls:document-version-query|dls:document-version-delete|dls:document-version-as-of|dls:document-version|dls:document-update|dls:document-unmanage|dls:document-set-quality|dls:document-set-property|dls:document-set-properties|dls:document-set-permissions|dls:document-set-collections|dls:document-retention-rules|dls:document-remove-properties|dls:document-remove-permissions|dls:document-remove-collections|dls:document-purge|dls:document-manage|dls:document-is-managed|dls:document-insert-and-manage|dls:document-include-query|dls:document-history|dls:document-get-permissions|dls:document-extract-part|dls:document-delete|dls:document-checkout-status|dls:document-checkout|dls:document-checkin|dls:document-add-properties|dls:document-add-permissions|dls:document-add-collections|dls:break-checkout|dls:author-query|dls:as-of-query|dbk:convert|dbg:wait|dbg:value|dbg:stopped|dbg:stop|dbg:step|dbg:status|dbg:stack|dbg:out|dbg:next|dbg:line|dbg:invoke|dbg:function|dbg:finish|dbg:expr|dbg:eval|dbg:disconnect|dbg:detach|dbg:continue|dbg:connect|dbg:clear|dbg:breakpoints|dbg:break|dbg:attached|dbg:attach|cvt:save-converted-documents|cvt:part-uri|cvt:destination-uri|cvt:basepath|cvt:basename|cts:words|cts:word-query-weight|cts:word-query-text|cts:word-query-options|cts:word-query|cts:word-match|cts:walk|cts:uris|cts:uri-match|cts:train|cts:tokenize|cts:thresholds|cts:stem|cts:similar-query-weight|cts:similar-query-nodes|cts:similar-query|cts:shortest-distance|cts:search|cts:score|cts:reverse-query-weight|cts:reverse-query-nodes|cts:reverse-query|cts:remainder|cts:registered-query-weight|cts:registered-query-options|cts:registered-query-ids|cts:registered-query|cts:register|cts:query|cts:quality|cts:properties-query-query|cts:properties-query|cts:polygon-vertices|cts:polygon|cts:point-longitude|cts:point-latitude|cts:point|cts:or-query-queries|cts:or-query|cts:not-query-weight|cts:not-query-query|cts:not-query|cts:near-query-weight|cts:near-query-queries|cts:near-query-options|cts:near-query-distance|cts:near-query|cts:highlight|cts:geospatial-co-occurrences|cts:frequency|cts:fitness|cts:field-words|cts:field-word-query-weight|cts:field-word-query-text|cts:field-word-query-options|cts:field-word-query-field-name|cts:field-word-query|cts:field-word-match|cts:entity-highlight|cts:element-words|cts:element-word-query-weight|cts:element-word-query-text|cts:element-word-query-options|cts:element-word-query-element-name|cts:element-word-query|cts:element-word-match|cts:element-values|cts:element-value-ranges|cts:element-value-query-weight|cts:element-value-query-text|cts:element-value-query-options|cts:element-value-query-element-name|cts:element-value-query|cts:element-value-match|cts:element-value-geospatial-co-occurrences|cts:element-value-co-occurrences|cts:element-range-query-weight|cts:element-range-query-value|cts:element-range-query-options|cts:element-range-query-operator|cts:element-range-query-element-name|cts:element-range-query|cts:element-query-query|cts:element-query-element-name|cts:element-query|cts:element-pair-geospatial-values|cts:element-pair-geospatial-value-match|cts:element-pair-geospatial-query-weight|cts:element-pair-geospatial-query-region|cts:element-pair-geospatial-query-options|cts:element-pair-geospatial-query-longitude-name|cts:element-pair-geospatial-query-latitude-name|cts:element-pair-geospatial-query-element-name|cts:element-pair-geospatial-query|cts:element-pair-geospatial-boxes|cts:element-geospatial-values|cts:element-geospatial-value-match|cts:element-geospatial-query-weight|cts:element-geospatial-query-region|cts:element-geospatial-query-options|cts:element-geospatial-query-element-name|cts:element-geospatial-query|cts:element-geospatial-boxes|cts:element-child-geospatial-values|cts:element-child-geospatial-value-match|cts:element-child-geospatial-query-weight|cts:element-child-geospatial-query-region|cts:element-child-geospatial-query-options|cts:element-child-geospatial-query-element-name|cts:element-child-geospatial-query-child-name|cts:element-child-geospatial-query|cts:element-child-geospatial-boxes|cts:element-attribute-words|cts:element-attribute-word-query-weight|cts:element-attribute-word-query-text|cts:element-attribute-word-query-options|cts:element-attribute-word-query-element-name|cts:element-attribute-word-query-attribute-name|cts:element-attribute-word-query|cts:element-attribute-word-match|cts:element-attribute-values|cts:element-attribute-value-ranges|cts:element-attribute-value-query-weight|cts:element-attribute-value-query-text|cts:element-attribute-value-query-options|cts:element-attribute-value-query-element-name|cts:element-attribute-value-query-attribute-name|cts:element-attribute-value-query|cts:element-attribute-value-match|cts:element-attribute-value-geospatial-co-occurrences|cts:element-attribute-value-co-occurrences|cts:element-attribute-range-query-weight|cts:element-attribute-range-query-value|cts:element-attribute-range-query-options|cts:element-attribute-range-query-operator|cts:element-attribute-range-query-element-name|cts:element-attribute-range-query-attribute-name|cts:element-attribute-range-query|cts:element-attribute-pair-geospatial-values|cts:element-attribute-pair-geospatial-value-match|cts:element-attribute-pair-geospatial-query-weight|cts:element-attribute-pair-geospatial-query-region|cts:element-attribute-pair-geospatial-query-options|cts:element-attribute-pair-geospatial-query-longitude-name|cts:element-attribute-pair-geospatial-query-latitude-name|cts:element-attribute-pair-geospatial-query-element-name|cts:element-attribute-pair-geospatial-query|cts:element-attribute-pair-geospatial-boxes|cts:document-query-uris|cts:document-query|cts:distance|cts:directory-query-uris|cts:directory-query-depth|cts:directory-query|cts:destination|cts:deregister|cts:contains|cts:confidence|cts:collections|cts:collection-query-uris|cts:collection-query|cts:collection-match|cts:classify|cts:circle-radius|cts:circle-center|cts:circle|cts:box-west|cts:box-south|cts:box-north|cts:box-east|cts:box|cts:bearing|cts:arc-intersection|cts:and-query-queries|cts:and-query-options|cts:and-query|cts:and-not-query-positive-query|cts:and-not-query-negative-query|cts:and-not-query|css:get|css:convert|cpf:success|cpf:failure|cpf:document-set-state|cpf:document-set-processing-status|cpf:document-set-last-updated|cpf:document-set-error|cpf:document-get-state|cpf:document-get-processing-status|cpf:document-get-last-updated|cpf:document-get-error|cpf:check-transition|alert:spawn-matching-actions|alert:rule-user-id-query|alert:rule-set-user-id|alert:rule-set-query|alert:rule-set-options|alert:rule-set-name|alert:rule-set-description|alert:rule-set-action|alert:rule-remove|alert:rule-name-query|alert:rule-insert|alert:rule-id-query|alert:rule-get-user-id|alert:rule-get-query|alert:rule-get-options|alert:rule-get-name|alert:rule-get-id|alert:rule-get-description|alert:rule-get-action|alert:rule-action-query|alert:remove-triggers|alert:make-rule|alert:make-log-action|alert:make-config|alert:make-action|alert:invoke-matching-actions|alert:get-my-rules|alert:get-all-rules|alert:get-actions|alert:find-matching-rules|alert:create-triggers|alert:config-set-uri|alert:config-set-trigger-ids|alert:config-set-options|alert:config-set-name|alert:config-set-description|alert:config-set-cpf-domain-names|alert:config-set-cpf-domain-ids|alert:config-insert|alert:config-get-uri|alert:config-get-trigger-ids|alert:config-get-options|alert:config-get-name|alert:config-get-id|alert:config-get-description|alert:config-get-cpf-domain-names|alert:config-get-cpf-domain-ids|alert:config-get|alert:config-delete|alert:action-set-options|alert:action-set-name|alert:action-set-module-root|alert:action-set-module-db|alert:action-set-module|alert:action-set-description|alert:action-remove|alert:action-insert|alert:action-get-options|alert:action-get-name|alert:action-get-module-root|alert:action-get-module-db|alert:action-get-module|alert:action-get-description|zero-or-one|years-from-duration|year-from-dateTime|year-from-date|upper-case|unordered|true|translate|trace|tokenize|timezone-from-time|timezone-from-dateTime|timezone-from-date|sum|subtract-dateTimes-yielding-yearMonthDuration|subtract-dateTimes-yielding-dayTimeDuration|substring-before|substring-after|substring|subsequence|string-to-codepoints|string-pad|string-length|string-join|string|static-base-uri|starts-with|seconds-from-time|seconds-from-duration|seconds-from-dateTime|round-half-to-even|round|root|reverse|resolve-uri|resolve-QName|replace|remove|QName|prefix-from-QName|position|one-or-more|number|not|normalize-unicode|normalize-space|node-name|node-kind|nilled|namespace-uri-from-QName|namespace-uri-for-prefix|namespace-uri|name|months-from-duration|month-from-dateTime|month-from-date|minutes-from-time|minutes-from-duration|minutes-from-dateTime|min|max|matches|lower-case|local-name-from-QName|local-name|last|lang|iri-to-uri|insert-before|index-of|in-scope-prefixes|implicit-timezone|idref|id|hours-from-time|hours-from-duration|hours-from-dateTime|floor|false|expanded-QName|exists|exactly-one|escape-uri|escape-html-uri|error|ends-with|encode-for-uri|empty|document-uri|doc-available|doc|distinct-values|distinct-nodes|default-collation|deep-equal|days-from-duration|day-from-dateTime|day-from-date|data|current-time|current-dateTime|current-date|count|contains|concat|compare|collection|codepoints-to-string|codepoint-equal|ceiling|boolean|base-uri|avg|adjust-time-to-timezone|adjust-dateTime-to-timezone|adjust-date-to-timezone|abs)\b/],
["pln",/^[\w:-]+/],["pln",/^[\t\n\r \xa0]+/]]),["xq","xquery"]);
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \xa0"],["com",/^#(?:if[\t\n\r \xa0]+(?:[$_a-z][\w']*|``[^\t\n\r`]*(?:``|$))|else|endif|light)/i,null,"#"],["str",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])(?:'|$))/,null,"\"'"]],[["com",/^(?:\/\/[^\n\r]*|\(\*[\S\s]*?\*\))/],["kwd",/^(?:abstract|and|as|assert|begin|class|default|delegate|do|done|downcast|downto|elif|else|end|exception|extern|false|finally|for|fun|function|if|in|inherit|inline|interface|internal|lazy|let|match|member|module|mutable|namespace|new|null|of|open|or|override|private|public|rec|return|static|struct|then|to|true|try|type|upcast|use|val|void|when|while|with|yield|asr|land|lor|lsl|lsr|lxor|mod|sig|atomic|break|checked|component|const|constraint|constructor|continue|eager|event|external|fixed|functor|global|include|method|mixin|object|parallel|process|protected|pure|sealed|trait|virtual|volatile)\b/],
["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i],["pln",/^(?:[_a-z][\w']*[!#?]?|``[^\t\n\r`]*(?:``|$))/i],["pun",/^[^\w\t\n\r "'\xa0]+/]]),["fs","ml"]);
var a=null;
PR.registerLangHandler(PR.createSimpleLexer([["opn",/^\(+/,a,"("],["clo",/^\)+/,a,")"],["com",/^;[^\n\r]*/,a,";"],["pln",/^[\t\n\r \xa0]+/,a,"\t\n\r \xa0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,a,'"']],[["kwd",/^(?:block|c[ad]+r|catch|con[ds]|def(?:ine|un)|do|eq|eql|equal|equalp|eval-when|flet|format|go|if|labels|lambda|let|load-time-value|locally|macrolet|multiple-value-call|nil|progn|progv|quote|require|return-from|setq|symbol-macrolet|t|tagbody|the|throw|unwind)\b/,a],
["lit",/^[+-]?(?:[#0]x[\da-f]+|\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[de][+-]?\d+)?)/i],["lit",/^'(?:-*(?:\w|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?)?/],["pln",/^-*(?:[_a-z]|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?/i],["pun",/^[^\w\t\n\r "'-);\\\xa0]+/]]),["cl","el","lisp","scm"]);
/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
 * Licensed under the MIT License (LICENSE.txt).
 *
 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
 * Thanks to: Seamus Leahy for adding deltaX and deltaY
 *
 * Version: 3.0.6
 * 
 * Requires: 1.2.2+
 */
(function(d){function e(a){var b=a||window.event,c=[].slice.call(arguments,1),f=0,e=0,g=0,a=d.event.fix(b);a.type="mousewheel";b.wheelDelta&&(f=b.wheelDelta/120);b.detail&&(f=-b.detail/3);g=f;b.axis!==void 0&&b.axis===b.HORIZONTAL_AXIS&&(g=0,e=-1*f);b.wheelDeltaY!==void 0&&(g=b.wheelDeltaY/120);b.wheelDeltaX!==void 0&&(e=-1*b.wheelDeltaX/120);c.unshift(a,f,e,g);return(d.event.dispatch||d.event.handle).apply(this,c)}var c=["DOMMouseScroll","mousewheel"];if(d.event.fixHooks)for(var h=c.length;h;)d.event.fixHooks[c[--h]]=
d.event.mouseHooks;d.event.special.mousewheel={setup:function(){if(this.addEventListener)for(var a=c.length;a;)this.addEventListener(c[--a],e,false);else this.onmousewheel=e},teardown:function(){if(this.removeEventListener)for(var a=c.length;a;)this.removeEventListener(c[--a],e,false);else this.onmousewheel=null}};d.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})})(jQuery);/*
 * jQuery.splitter.js - two-pane splitter window plugin
 *
 * version 1.51 (2009/01/09)
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */

/**
 * The splitter() plugin implements a two-pane resizable splitter window.
 * The selected elements in the jQuery object are converted to a splitter;
 * each selected element should have two child elements, used for the panes
 * of the splitter. The plugin adds a third child element for the splitbar.
 *
 * For more details see: http://methvin.com/splitter/
 *
 *
 * @example $('#MySplitter').splitter();
 * @desc Create a vertical splitter with default settings
 *
 * @example $('#MySplitter').splitter({type: 'h', accessKey: 'M'});
 * @desc Create a horizontal splitter resizable via Alt+Shift+M
 *
 * @name splitter
 * @type jQuery
 * @param Object options Options for the splitter (not required)
 * @cat Plugins/Splitter
 * @return jQuery
 * @author Dave Methvin (dave.methvin@gmail.com)
 */
;
(function($) {

    $.fn.splitter = function(args) {
        args = args || {};
        return this.each(function() {
            var zombie;      // left-behind splitbar for outline resizes
            function startSplitMouse(evt) {
                if (opts.outline)
                    zombie = zombie || bar.clone(false).insertAfter(A);
                panes.css("-webkit-user-select", "none");   // Safari selects A/B text on a move
                bar.addClass(opts.activeClass);
                $('<div class="splitterMask"></div>').insertAfter(bar);
                A._posSplit = A[0][opts.pxSplit] - evt[opts.eventPos];
                $(document)
                        .bind("mousemove", doSplitMouse)
                        .bind("mouseup", endSplitMouse);
            }

            function doSplitMouse(evt) {
                var newPos = A._posSplit + evt[opts.eventPos];
                if (opts.outline) {
                    newPos = Math.max(0, Math.min(newPos, splitter._DA - bar._DA));
                    bar.css(opts.origin, newPos);
                } else
                    resplit(newPos);
            }

            function endSplitMouse(evt) {
                $('div.splitterMask').remove();
                bar.removeClass(opts.activeClass);
                var newPos = A._posSplit + evt[opts.eventPos];
                if (opts.outline) {
                    zombie.remove();
                    zombie = null;
                    resplit(newPos);
                }
                panes.css("-webkit-user-select", "text");   // let Safari select text again
                $(document)
                        .unbind("mousemove", doSplitMouse)
                        .unbind("mouseup", endSplitMouse);
            }

            function resplit(newPos) {
                // Constrain new splitbar position to fit pane size limits
                newPos = Math.max(A._min, splitter._DA - B._max,
                        Math.min(newPos, A._max, splitter._DA - bar._DA - B._min));
                // Resize/position the two panes
                bar._DA = bar[0][opts.pxSplit];      // bar size may change during dock
                bar.css(opts.origin, newPos).css(opts.fixed, splitter._DF);
                A.css(opts.origin, 0).css(opts.split, newPos).css(opts.fixed, splitter._DF);
                B.css(opts.origin, newPos + bar._DA)
                        .css(opts.split, splitter._DA - bar._DA - newPos).css(opts.fixed, splitter._DF);
                // IE fires resize for us; all others pay cash
                if (!$.browser.msie)
                    panes.trigger("resize");
            }

            function dimSum(jq, dims) {
                // Opera returns -1 for missing min/max width, turn into 0
                var sum = 0;
                for (var i = 1; i < arguments.length; i++)
                    sum += Math.max(parseInt(jq.css(arguments[i])) || 0, 0);
                return sum;
            }

            // Determine settings based on incoming opts, element classes, and defaults
            var vh = (args.splitHorizontal ? 'h' : args.splitVertical ? 'v' : args.type) || 'v';
            var opts = $.extend({
                activeClass: 'active',   // class name for active splitter
                pxPerKey: 8,         // splitter px moved per keypress
                tabIndex: 0,         // tab order indicator
                accessKey: ''         // accessKey for splitbar
            }, {
                v: {               // Vertical splitters:
                    keyLeft: 39, keyRight: 37, cursor: "e-resize",
                    splitbarClass: "vsplitbar", outlineClass: "voutline",
                    type: 'v', eventPos: "pageX", origin: "left",
                    split: "width",  pxSplit: "offsetWidth",  side1: "Left", side2: "Right",
                    fixed: "height", pxFixed: "offsetHeight", side3: "Top",  side4: "Bottom"
                },
                h: {               // Horizontal splitters:
                    keyTop: 40, keyBottom: 38,  cursor: "n-resize",
                    splitbarClass: "hsplitbar", outlineClass: "houtline",
                    type: 'h', eventPos: "pageY", origin: "top",
                    split: "height", pxSplit: "offsetHeight", side1: "Top",  side2: "Bottom",
                    fixed: "width",  pxFixed: "offsetWidth",  side3: "Left", side4: "Right"
                }
            }[vh], args);

            // Create jQuery object closures for splitter and both panes
            var splitter = $(this).css({position: "relative"});
            var panes = $(">*", splitter[0]).css({
                position: "absolute",          // positioned inside splitter container
                "z-index": "1",               // splitbar is positioned above
                "-moz-outline-style": "none"   // don't show dotted outline
            });
            var A = $(panes[0]);      // left  or top
            var B = $(panes[1]);      // right or bottom

            // Focuser element, provides keyboard support; title is shown by Opera accessKeys
            var focuser = $('<a href="javascript:void(0)"></a>')
                    .attr({accessKey: opts.accessKey, tabIndex: opts.tabIndex, title: opts.splitbarClass})
                    .bind($.browser.opera ? "click" : "focus", function() {
                        this.focus();
                        bar.addClass(opts.activeClass)
                    })
                    .bind("keydown", function(e) {
                        var key = e.which || e.keyCode;
                        var dir = key == opts["key" + opts.side1] ? 1 : key == opts["key" + opts.side2] ? -1 : 0;
                        if (dir)
                            resplit(A[0][opts.pxSplit] + dir * opts.pxPerKey, false);
                    })
                    .bind("blur", function() {
                        bar.removeClass(opts.activeClass)
                    });

            // Splitbar element, can be already in the doc or we create one
            var bar = $(panes[2] || '<div></div>')
                    .insertAfter(A).css("z-index", "100").append(focuser)
                    .attr({"class": opts.splitbarClass, unselectable: "on"})
                    .css({position: "absolute",   "user-select": "none", "-webkit-user-select": "none",
                        "-khtml-user-select": "none", "-moz-user-select": "none", "top": "0px"})
                    .bind("mousedown", startSplitMouse);
            // Use our cursor unless the style specifies a non-default cursor
            if (/^(auto|default|)$/.test(bar.css("cursor")))
                bar.css("cursor", opts.cursor);

            // Cache several dimensions for speed, rather than re-querying constantly
            bar._DA = bar[0][opts.pxSplit];
            splitter._PBF = $.boxModel ? dimSum(splitter, "border" + opts.side3 + "Width", "border" + opts.side4 + "Width") : 0;
            splitter._PBA = $.boxModel ? dimSum(splitter, "border" + opts.side1 + "Width", "border" + opts.side2 + "Width") : 0;
            A._pane = opts.side1;
            B._pane = opts.side2;
            $.each([A,B], function() {
                this._min = opts["min" + this._pane] || dimSum(this, "min-" + opts.split);
                this._max = opts["max" + this._pane] || dimSum(this, "max-" + opts.split) || 9999;
                this._init = opts["size" + this._pane] === true ?
                        parseInt($.curCSS(this[0], opts.split)) : opts["size" + this._pane];
            });

            // Determine initial position, get from cookie if specified
            var initPos = A._init;
            if (!isNaN(B._init))   // recalc initial B size as an offset from the top or left side
                initPos = splitter[0][opts.pxSplit] - splitter._PBA - B._init - bar._DA;
            if (opts.cookie) {
                if (!$.cookie)
                    alert('jQuery.splitter(): jQuery cookie plugin required');
                var ckpos = parseInt($.cookie(opts.cookie));
                if (!isNaN(ckpos))
                    initPos = ckpos;
                $(window).bind("unload", function() {
                    var state = String(bar.css(opts.origin));   // current location of splitbar
                    $.cookie(opts.cookie, state, {expires: opts.cookieExpires || 365,
                        path: opts.cookiePath || document.location.pathname});
                });
            }
            if (isNaN(initPos))   // King Solomon's algorithm
                initPos = Math.round((splitter[0][opts.pxSplit] - splitter._PBA - bar._DA) / 2);

            // Resize event propagation and splitter sizing
            if (opts.anchorToWindow) {
                // Account for margin or border on the splitter container and enforce min height
                splitter._hadjust = dimSum(splitter, "borderTopWidth", "borderBottomWidth", "marginBottom");
                splitter._hmin = Math.max(dimSum(splitter, "minHeight"), 20);
                $(window).bind("resize",
                        function() {
                            var top = splitter.offset().top;
                            var wh = $(window).height();
                            splitter.css("height", Math.max(wh - top - splitter._hadjust, splitter._hmin) + "px");
                            if (!$.browser.msie) splitter.trigger("resize");
                        }).trigger("resize");
            }
            else if (opts.resizeToWidth && !$.browser.msie)
                $(window).bind("resize", function() {
                    splitter.trigger("resize");
                });

            // Resize event handler; triggered immediately to set initial position
            splitter.bind("resize",
                    function(e, size) {
                        // Custom events bubble in jQuery 1.3; don't Yo Dawg
                        if (e.target != this) return;
                        // Determine new width/height of splitter container
                        splitter._DF = splitter[0][opts.pxFixed] - splitter._PBF;
                        splitter._DA = splitter[0][opts.pxSplit] - splitter._PBA;
                        // Bail if splitter isn't visible or content isn't there yet
                        if (splitter._DF <= 0 || splitter._DA <= 0) return;
                        // Re-divvy the adjustable dimension; maintain size of the preferred pane
                        resplit(!isNaN(size) ? size : (!(opts.sizeRight || opts.sizeBottom) ? A[0][opts.pxSplit] :
                                splitter._DA - B[0][opts.pxSplit] - bar._DA));
                    }).trigger("resize", [initPos]);
        });
    };

})(jQuery);/**
 *  SVGPan library 1.2 - phpDocumentor1
 * ====================
 *
 * Given an unique existing element with id "viewport", including the
 * the library into any SVG adds the following capabilities:
 *
 *  - Mouse panning
 *  - Mouse zooming (using the wheel)
 *  - Object dargging
 *
 * Known issues:
 *
 *  - Zooming (while panning) on Safari has still some issues
 *
 * Releases:
 *
 * 1.2 - phpDocumentor1, Fri Apr 08 19:19:00 CET 2011, Mike van Riel
 *            Increased zoom speed with 20%
 *            Disabled element moving functionality
 *
 * 1.2, Sat Mar 20 08:42:50 GMT 2010, Zeng Xiaohui
 *	Fixed a bug with browser mouse handler interaction
 *
 * 1.1, Wed Feb  3 17:39:33 GMT 2010, Zeng Xiaohui
 *	Updated the zoom code to support the mouse wheel on Safari/Chrome
 *
 * 1.0, Andrea Leofreddi
 *	First release
 *
 * This code is licensed under the following BSD license:
 *
 * Copyright 2009-2010 Andrea Leofreddi <a.leofreddi@itcharm.com>. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are
 * permitted provided that the following conditions are met:
 *
 *    1. Redistributions of source code must retain the above copyright notice, this list of
 *       conditions and the following disclaimer.
 *
 *    2. Redistributions in binary form must reproduce the above copyright notice, this list
 *       of conditions and the following disclaimer in the documentation and/or other materials
 *       provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY Andrea Leofreddi ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Andrea Leofreddi OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * The views and conclusions contained in the software and documentation are those of the
 * authors and should not be interpreted as representing official policies, either expressed
 * or implied, of Andrea Leofreddi.
 */

var root = document.documentElement;

var state = 'none', stateTarget, stateOrigin, stateTf;

setupHandlers(root);

/**
 * Register handlers
 */
function setupHandlers(root){
	setAttributes(root, {
		"onmouseup" : "add(evt)",
		"onmousedown" : "handleMouseDown(evt)",
		"onmousemove" : "handleMouseMove(evt)",
		"onmouseup" : "handleMouseUp(evt)",
//		"onmouseout" : "handleMouseUp(evt)" // Decomment this to stop the pan functionality when dragging out of the SVG element
	});

	if(navigator.userAgent.toLowerCase().indexOf('webkit') >= 0)
		window.addEventListener('mousewheel', handleMouseWheel, false); // Chrome/Safari
	else
		window.addEventListener('DOMMouseScroll', handleMouseWheel, false); // Others
}

/**
 * Instance an SVGPoint object with given event coordinates.
 */
function getEventPoint(evt) {
	var p = root.createSVGPoint();

	p.x = evt.clientX;
	p.y = evt.clientY;

	return p;
}

/**
 * Sets the current transform matrix of an element.
 */
function setCTM(element, matrix) {
	var s = "matrix(" + matrix.a + "," + matrix.b + "," + matrix.c + "," + matrix.d + "," + matrix.e + "," + matrix.f + ")";

	element.setAttribute("transform", s);
}

/**
 * Dumps a matrix to a string (useful for debug).
 */
function dumpMatrix(matrix) {
	var s = "[ " + matrix.a + ", " + matrix.c + ", " + matrix.e + "\n  " + matrix.b + ", " + matrix.d + ", " + matrix.f + "\n  0, 0, 1 ]";

	return s;
}

/**
 * Sets attributes of an element.
 */
function setAttributes(element, attributes){
	for (i in attributes)
		element.setAttributeNS(null, i, attributes[i]);
}

/**
 * Handle mouse move event.
 */
function handleMouseWheel(evt) {
	if(evt.preventDefault)
		evt.preventDefault();

	evt.returnValue = false;

	var svgDoc = evt.target.ownerDocument;

	var delta;

	if(evt.wheelDelta)
		delta = evt.wheelDelta / 3600; // Chrome/Safari
	else
		delta = evt.detail / -90; // Mozilla

	var z = 1 + (delta * 1.2); // Zoom factor: 0.9/1.1

	var g = svgDoc.getElementById("viewport");

	var p = getEventPoint(evt);

	p = p.matrixTransform(g.getCTM().inverse());

	// Compute new scale matrix in current mouse position
	var k = root.createSVGMatrix().translate(p.x, p.y).scale(z).translate(-p.x, -p.y);

        setCTM(g, g.getCTM().multiply(k));

	stateTf = stateTf.multiply(k.inverse());
}

/**
 * Handle mouse move event.
 */
function handleMouseMove(evt) {
	if(evt.preventDefault)
		evt.preventDefault();

	evt.returnValue = false;

	var svgDoc = evt.target.ownerDocument;

	var g = svgDoc.getElementById("viewport");

	if(state == 'pan') {
		// Pan mode
		var p = getEventPoint(evt).matrixTransform(stateTf);

		setCTM(g, stateTf.inverse().translate(p.x - stateOrigin.x, p.y - stateOrigin.y));
	} else if(state == 'move') {
		// Move mode
		var p = getEventPoint(evt).matrixTransform(g.getCTM().inverse());

		setCTM(stateTarget, root.createSVGMatrix().translate(p.x - stateOrigin.x, p.y - stateOrigin.y).multiply(g.getCTM().inverse()).multiply(stateTarget.getCTM()));

		stateOrigin = p;
	}
}

/**
 * Handle click event.
 */
function handleMouseDown(evt) {
	if(evt.preventDefault)
		evt.preventDefault();

	evt.returnValue = false;

	var svgDoc = evt.target.ownerDocument;

	var g = svgDoc.getElementById("viewport");

//	if(evt.target.tagName == "svg") {
		// Pan mode
		state = 'pan';

		stateTf = g.getCTM().inverse();

		stateOrigin = getEventPoint(evt).matrixTransform(stateTf);
//	} else {
		// Move mode
//		state = 'move';
//
//		stateTarget = evt.target;
//
//		stateTf = g.getCTM().inverse();
//
//		stateOrigin = getEventPoint(evt).matrixTransform(stateTf);
//	}
}

/**
 * Handle mouse button release event.
 */
function handleMouseUp(evt) {
	if(evt.preventDefault)
		evt.preventDefault();

	evt.returnValue = false;

	var svgDoc = evt.target.ownerDocument;

	if(state == 'pan' || state == 'move') {
		// Quit pan mode
		state = '';
	}
}

/**
 * Cookie plugin
 *
 * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 */

/**
 * Create a cookie with the given name and value and other optional parameters.
 *
 * @example $.cookie('the_cookie', 'the_value');
 * @desc Set the value of a cookie.
 * @example $.cookie('the_cookie', 'the_value', {expires: 7, path: '/', domain: 'jquery.com', secure: true});
 * @desc Create a cookie with all available options.
 * @example $.cookie('the_cookie', 'the_value');
 * @desc Create a session cookie.
 * @example $.cookie('the_cookie', null);
 * @desc Delete a cookie by passing null as value.
 *
 * @param String name The name of the cookie.
 * @param String value The value of the cookie.
 * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
 * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
 *                             If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
 *                             If set to null or omitted, the cookie will be a session cookie and will not be retained
 *                             when the the browser exits.
 * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
 * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
 * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
 *                        require a secure protocol (like HTTPS).
 * @type undefined
 *
 * @name $.cookie
 * @cat Plugins/Cookie
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */

/**
 * Get the value of a cookie with the given name.
 *
 * @example $.cookie('the_cookie');
 * @desc Get the value of a cookie.
 *
 * @param String name The name of the cookie.
 * @return The value of the cookie.
 * @type String
 *
 * @name $.cookie
 * @cat Plugins/Cookie
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */
jQuery.cookie = function(name, value, options)
{
  if (typeof value != 'undefined')
  { // name and value given, set cookie
    options = options || {};
    if (value === null)
    {
      value = '';
      options.expires = -1;
    }
    var expires = '';
    if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString))
    {
      var date;
      if (typeof options.expires == 'number')
      {
        date = new Date();
        date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
      }
      else
      {
        date = options.expires;
      }
      expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
    }
    var path = options.path ? '; path=' + options.path : '';
    var domain = options.domain ? '; domain=' + options.domain : '';
    var secure = options.secure ? '; secure' : '';
    document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
  }
  else
  { // only name given, get cookie
    var cookieValue = null;
    if (document.cookie && document.cookie != '')
    {
      var cookies = document.cookie.split(';');
      for (var i = 0; i < cookies.length; i++)
      {
        var cookie = jQuery.trim(cookies[i]);
        // Does this cookie string begin with the name we want?
        if (cookie.substring(0, name.length + 1) == (name + '='))
        {
          cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
          break;
        }
      }
    }
    return cookieValue;
  }
};var timeout    = 500;
var closetimer = 0;
var ddmenuitem = 0;

function menu_open() {
    menu_canceltimer();
    menu_close();
    ddmenuitem = $(this).find('ul').css('visibility', 'visible');
}

function menu_close() {
    if (ddmenuitem) ddmenuitem.css('visibility', 'hidden');
}

function menu_timer() {
    closetimer = window.setTimeout(menu_close, timeout);
}

function menu_canceltimer() {
    if (closetimer) {
        window.clearTimeout(closetimer);
        closetimer = null;
    }
}

$(document).ready(function() {
    $('#file-nav > li').bind('mouseover', menu_open);
    $('#file-nav > li').bind('mouseout', menu_timer);
});

document.onclick = menu_close;.iviewer_common {
    position:absolute;
    bottom:10px;
    border: 1px  solid #000;
    height: 28px;
    z-index: 5000;
}

.iviewer_cursor {
    cursor: url(../img/iviewer/hand.cur) 6 8, pointer;
}

.iviewer_drag_cursor {
    cursor: url(../img/iviewer/grab.cur) 6 8, pointer;
}

.iviewer_button {
    width: 28px;
    cursor: pointer;
    background-position: center center;
    background-repeat: no-repeat;
}

.iviewer_zoom_in {
    left: 20px;
    background: url(../img/iviewer/iviewer.zoom_in.png);
}

.iviewer_zoom_out {
    left: 55px;
    background: url(../img/iviewer/iviewer.zoom_out.png);
}

.iviewer_zoom_zero {
    left: 90px;
    background: url(../img/iviewer/iviewer.zoom_zero.png);
}

.iviewer_zoom_fit {
    left: 125px;
    background: url(../img/iviewer/iviewer.zoom_fit.png);
}

.iviewer_zoom_status {
    left: 160px;
    font: 1em/28px Sans;
    color: #000;
    background-color: #fff;
    text-align: center;
    width: 60px;
}

.iviewer_rotate_left {
    left: 227px;
    background: #fff url(../img/iviewer/iviewer.rotate_left.png) center center no-repeat;
}

.iviewer_rotate_right {
    left: 262px;
    background: #fff url(../img/iviewer/iviewer.rotate_right.png) center center no-repeat;
}

.viewer
{
    width:      100%;
    height:     500px;
    position:   relative;
    background: transparent url('../img/loader.gif') no-repeat center center;
}

.viewer img
{
    max-width: none;
}

.wrapper
{
    overflow: hidden;
}

.iviewer_common
{
    border: 0;
    bottom: auto;
    top: 10px;
}

.iviewer_zoom_status
{
    border: 1px solid black;
}

.hidden{display:none;visibility:hidden;}
@media (max-width:480px){.nav-collapse{-webkit-transform:translate3d(0, 0, 0);} .page-header h1 small{display:block;line-height:18px;} input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;height:28px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;} .input-prepend input[class*="span"],.input-append input[class*="span"]{width:auto;} input[type="checkbox"],input[type="radio"]{border:1px solid #ccc;} .form-horizontal .control-group>label{float:none;width:auto;padding-top:0;text-align:left;} .form-horizontal .controls{margin-left:0;} .form-horizontal .control-list{padding-top:0;} .form-horizontal .form-actions{padding-left:10px;padding-right:10px;} .modal{position:absolute;top:10px;left:10px;right:10px;width:auto;margin:0;}.modal.fade.in{top:auto;} .modal-header .close{padding:10px;margin:-10px;} .carousel-caption{position:static;}}@media (max-width:768px){.container{width:auto;padding:0 20px;} .row-fluid{width:100%;} .row{margin-left:0;} .row>[class*="span"],.row-fluid>[class*="span"]{float:none;display:block;width:auto;margin:0;}}@media (min-width:768px) and (max-width:980px){.row{margin-left:-20px;*zoom:1;}.row:before,.row:after{display:table;content:"";} .row:after{clear:both;} [class*="span"]{float:left;margin-left:20px;} .span1{width:42px;} .span2{width:104px;} .span3{width:166px;} .span4{width:228px;} .span5{width:290px;} .span6{width:352px;} .span7{width:414px;} .span8{width:476px;} .span9{width:538px;} .span10{width:600px;} .span11{width:662px;} .span12,.container{width:724px;} .offset1{margin-left:82px;} .offset2{margin-left:144px;} .offset3{margin-left:206px;} .offset4{margin-left:268px;} .offset5{margin-left:330px;} .offset6{margin-left:392px;} .offset7{margin-left:454px;} .offset8{margin-left:516px;} .offset9{margin-left:578px;} .offset10{margin-left:640px;} .offset11{margin-left:702px;} .row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:"";} .row-fluid:after{clear:both;} .row-fluid>[class*="span"]{float:left;margin-left:2.762430939%;} .row-fluid>[class*="span"]:first-child{margin-left:0;} .row-fluid .span1{width:5.801104972%;} .row-fluid .span2{width:14.364640883%;} .row-fluid .span3{width:22.928176794%;} .row-fluid .span4{width:31.491712705%;} .row-fluid .span5{width:40.055248616%;} .row-fluid .span6{width:48.618784527%;} .row-fluid .span7{width:57.182320438000005%;} .row-fluid .span8{width:65.74585634900001%;} .row-fluid .span9{width:74.30939226%;} .row-fluid .span10{width:82.87292817100001%;} .row-fluid .span11{width:91.436464082%;} .row-fluid .span12{width:99.999999993%;} input.span1,textarea.span1,.uneditable-input.span1{width:32px;} input.span2,textarea.span2,.uneditable-input.span2{width:94px;} input.span3,textarea.span3,.uneditable-input.span3{width:156px;} input.span4,textarea.span4,.uneditable-input.span4{width:218px;} input.span5,textarea.span5,.uneditable-input.span5{width:280px;} input.span6,textarea.span6,.uneditable-input.span6{width:342px;} input.span7,textarea.span7,.uneditable-input.span7{width:404px;} input.span8,textarea.span8,.uneditable-input.span8{width:466px;} input.span9,textarea.span9,.uneditable-input.span9{width:528px;} input.span10,textarea.span10,.uneditable-input.span10{width:590px;} input.span11,textarea.span11,.uneditable-input.span11{width:652px;} input.span12,textarea.span12,.uneditable-input.span12{width:714px;}}@media (max-width:980px){body{padding-top:0;} .navbar-fixed-top{position:static;margin-bottom:18px;} .navbar-fixed-top .navbar-inner{padding:5px;} .navbar .container{width:auto;padding:0;} .navbar .brand{padding-left:10px;padding-right:10px;margin:0 0 0 -5px;} .navbar .nav-collapse{clear:left;} .navbar .nav{float:none;margin:0 0 9px;} .navbar .nav>li{float:none;} .navbar .nav>li>a{margin-bottom:2px;} .navbar .nav>.divider-vertical{display:none;} .navbar .nav>li>a,.navbar .dropdown-menu a{padding:6px 15px;font-weight:bold;color:#999999;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;} .navbar .dropdown-menu li+li a{margin-bottom:2px;} .navbar .nav>li>a:hover,.navbar .dropdown-menu a:hover{background-color:#222222;} .navbar .dropdown-menu{position:static;top:auto;left:auto;float:none;display:block;max-width:none;margin:0 15px;padding:0;background-color:transparent;border:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} .navbar .dropdown-menu:before,.navbar .dropdown-menu:after{display:none;} .navbar .dropdown-menu .divider{display:none;} .navbar-form,.navbar-search{float:none;padding:9px 15px;margin:9px 0;border-top:1px solid #222222;border-bottom:1px solid #222222;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.1);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.1);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.1);} .navbar .nav.pull-right{float:none;margin-left:0;} .navbar-static .navbar-inner{padding-left:10px;padding-right:10px;} .btn-navbar{display:block;} .nav-collapse{overflow:hidden;height:0;}}@media (min-width:980px){.nav-collapse.collapse{height:auto !important;}}@media (min-width:1200px){.row{margin-left:-30px;*zoom:1;}.row:before,.row:after{display:table;content:"";} .row:after{clear:both;} [class*="span"]{float:left;margin-left:30px;} .span1{width:70px;} .span2{width:170px;} .span3{width:270px;} .span4{width:370px;} .span5{width:470px;} .span6{width:570px;} .span7{width:670px;} .span8{width:770px;} .span9{width:870px;} .span10{width:970px;} .span11{width:1070px;} .span12,.container{width:1170px;} .offset1{margin-left:130px;} .offset2{margin-left:230px;} .offset3{margin-left:330px;} .offset4{margin-left:430px;} .offset5{margin-left:530px;} .offset6{margin-left:630px;} .offset7{margin-left:730px;} .offset8{margin-left:830px;} .offset9{margin-left:930px;} .offset10{margin-left:1030px;} .offset11{margin-left:1130px;} .row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:"";} .row-fluid:after{clear:both;} .row-fluid>[class*="span"]{float:left;margin-left:2.564102564%;} .row-fluid>[class*="span"]:first-child{margin-left:0;} .row-fluid .span1{width:5.982905983%;} .row-fluid .span2{width:14.529914530000001%;} .row-fluid .span3{width:23.076923077%;} .row-fluid .span4{width:31.623931624%;} .row-fluid .span5{width:40.170940171000005%;} .row-fluid .span6{width:48.717948718%;} .row-fluid .span7{width:57.264957265%;} .row-fluid .span8{width:65.81196581200001%;} .row-fluid .span9{width:74.358974359%;} .row-fluid .span10{width:82.905982906%;} .row-fluid .span11{width:91.45299145300001%;} .row-fluid .span12{width:100%;} input.span1,textarea.span1,.uneditable-input.span1{width:60px;} input.span2,textarea.span2,.uneditable-input.span2{width:160px;} input.span3,textarea.span3,.uneditable-input.span3{width:260px;} input.span4,textarea.span4,.uneditable-input.span4{width:360px;} input.span5,textarea.span5,.uneditable-input.span5{width:460px;} input.span6,textarea.span6,.uneditable-input.span6{width:560px;} input.span7,textarea.span7,.uneditable-input.span7{width:660px;} input.span8,textarea.span8,.uneditable-input.span8{width:760px;} input.span9,textarea.span9,.uneditable-input.span9{width:860px;} input.span10,textarea.span10,.uneditable-input.span10{width:960px;} input.span11,textarea.span11,.uneditable-input.span11{width:1060px;} input.span12,textarea.span12,.uneditable-input.span12{width:1160px;} .thumbnails{margin-left:-30px;} .thumbnails>li{margin-left:30px;}}
/*!
 * Bootstrap Responsive v2.0.0
 *
 * Copyright 2012 Twitter, Inc
 * Licensed under the Apache License v2.0
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Designed and built with all the love in the world @twitter by @mdo and @fat.
 */
.hidden {
  display: none;
  visibility: hidden;
}
@media (max-width: 480px) {
  .nav-collapse {
    -webkit-transform: translate3d(0, 0, 0);
  }
  .page-header h1 small {
    display: block;
    line-height: 18px;
  }
  input[class*="span"],
  select[class*="span"],
  textarea[class*="span"],
  .uneditable-input {
    display: block;
    width: 100%;
    height: 28px;
    /* Make inputs at least the height of their button counterpart */
  
    /* Makes inputs behave like true block-level elements */
  
    -webkit-box-sizing: border-box;
    /* Older Webkit */
  
    -moz-box-sizing: border-box;
    /* Older FF */
  
    -ms-box-sizing: border-box;
    /* IE8 */
  
    box-sizing: border-box;
    /* CSS3 spec*/
  
  }
  .input-prepend input[class*="span"], .input-append input[class*="span"] {
    width: auto;
  }
  input[type="checkbox"], input[type="radio"] {
    border: 1px solid #ccc;
  }
  .form-horizontal .control-group > label {
    float: none;
    width: auto;
    padding-top: 0;
    text-align: left;
  }
  .form-horizontal .controls {
    margin-left: 0;
  }
  .form-horizontal .control-list {
    padding-top: 0;
  }
  .form-horizontal .form-actions {
    padding-left: 10px;
    padding-right: 10px;
  }
  .modal {
    position: absolute;
    top: 10px;
    left: 10px;
    right: 10px;
    width: auto;
    margin: 0;
  }
  .modal.fade.in {
    top: auto;
  }
  .modal-header .close {
    padding: 10px;
    margin: -10px;
  }
  .carousel-caption {
    position: static;
  }
}
@media (max-width: 768px) {
  .container {
    width: auto;
    padding: 0 20px;
  }
  .row-fluid {
    width: 100%;
  }
  .row {
    margin-left: 0;
  }
  .row > [class*="span"], .row-fluid > [class*="span"] {
    float: none;
    display: block;
    width: auto;
    margin: 0;
  }
}
@media (min-width: 768px) and (max-width: 980px) {
  .row {
    margin-left: -20px;
    *zoom: 1;
  }
  .row:before, .row:after {
    display: table;
    content: "";
  }
  .row:after {
    clear: both;
  }
  [class*="span"] {
    float: left;
    margin-left: 20px;
  }
  .span1 {
    width: 42px;
  }
  .span2 {
    width: 104px;
  }
  .span3 {
    width: 166px;
  }
  .span4 {
    width: 228px;
  }
  .span5 {
    width: 290px;
  }
  .span6 {
    width: 352px;
  }
  .span7 {
    width: 414px;
  }
  .span8 {
    width: 476px;
  }
  .span9 {
    width: 538px;
  }
  .span10 {
    width: 600px;
  }
  .span11 {
    width: 662px;
  }
  .span12, .container {
    width: 724px;
  }
  .offset1 {
    margin-left: 82px;
  }
  .offset2 {
    margin-left: 144px;
  }
  .offset3 {
    margin-left: 206px;
  }
  .offset4 {
    margin-left: 268px;
  }
  .offset5 {
    margin-left: 330px;
  }
  .offset6 {
    margin-left: 392px;
  }
  .offset7 {
    margin-left: 454px;
  }
  .offset8 {
    margin-left: 516px;
  }
  .offset9 {
    margin-left: 578px;
  }
  .offset10 {
    margin-left: 640px;
  }
  .offset11 {
    margin-left: 702px;
  }
  .row-fluid {
    width: 100%;
    *zoom: 1;
  }
  .row-fluid:before, .row-fluid:after {
    display: table;
    content: "";
  }
  .row-fluid:after {
    clear: both;
  }
  .row-fluid > [class*="span"] {
    float: left;
    margin-left: 2.762430939%;
  }
  .row-fluid > [class*="span"]:first-child {
    margin-left: 0;
  }
  .row-fluid .span1 {
    width: 5.801104972%;
  }
  .row-fluid .span2 {
    width: 14.364640883%;
  }
  .row-fluid .span3 {
    width: 22.928176794%;
  }
  .row-fluid .span4 {
    width: 31.491712705%;
  }
  .row-fluid .span5 {
    width: 40.055248616%;
  }
  .row-fluid .span6 {
    width: 48.618784527%;
  }
  .row-fluid .span7 {
    width: 57.182320438000005%;
  }
  .row-fluid .span8 {
    width: 65.74585634900001%;
  }
  .row-fluid .span9 {
    width: 74.30939226%;
  }
  .row-fluid .span10 {
    width: 82.87292817100001%;
  }
  .row-fluid .span11 {
    width: 91.436464082%;
  }
  .row-fluid .span12 {
    width: 99.999999993%;
  }
  input.span1, textarea.span1, .uneditable-input.span1 {
    width: 32px;
  }
  input.span2, textarea.span2, .uneditable-input.span2 {
    width: 94px;
  }
  input.span3, textarea.span3, .uneditable-input.span3 {
    width: 156px;
  }
  input.span4, textarea.span4, .uneditable-input.span4 {
    width: 218px;
  }
  input.span5, textarea.span5, .uneditable-input.span5 {
    width: 280px;
  }
  input.span6, textarea.span6, .uneditable-input.span6 {
    width: 342px;
  }
  input.span7, textarea.span7, .uneditable-input.span7 {
    width: 404px;
  }
  input.span8, textarea.span8, .uneditable-input.span8 {
    width: 466px;
  }
  input.span9, textarea.span9, .uneditable-input.span9 {
    width: 528px;
  }
  input.span10, textarea.span10, .uneditable-input.span10 {
    width: 590px;
  }
  input.span11, textarea.span11, .uneditable-input.span11 {
    width: 652px;
  }
  input.span12, textarea.span12, .uneditable-input.span12 {
    width: 714px;
  }
}
@media (max-width: 980px) {
  body {
    padding-top: 0;
  }
  .navbar-fixed-top {
    position: static;
    margin-bottom: 18px;
  }
  .navbar-fixed-top .navbar-inner {
    padding: 5px;
  }
  .navbar .container {
    width: auto;
    padding: 0;
  }
  .navbar .brand {
    padding-left: 10px;
    padding-right: 10px;
    margin: 0 0 0 -5px;
  }
  .navbar .nav-collapse {
    clear: left;
  }
  .navbar .nav {
    float: none;
    margin: 0 0 9px;
  }
  .navbar .nav > li {
    float: none;
  }
  .navbar .nav > li > a {
    margin-bottom: 2px;
  }
  .navbar .nav > .divider-vertical {
    display: none;
  }
  .navbar .nav > li > a, .navbar .dropdown-menu a {
    padding: 6px 15px;
    font-weight: bold;
    color: #999999;
    -webkit-border-radius: 3px;
    -moz-border-radius: 3px;
    border-radius: 3px;
  }
  .navbar .dropdown-menu li + li a {
    margin-bottom: 2px;
  }
  .navbar .nav > li > a:hover, .navbar .dropdown-menu a:hover {
    background-color: #222222;
  }
  .navbar .dropdown-menu {
    position: static;
    top: auto;
    left: auto;
    float: none;
    display: block;
    max-width: none;
    margin: 0 15px;
    padding: 0;
    background-color: transparent;
    border: none;
    -webkit-border-radius: 0;
    -moz-border-radius: 0;
    border-radius: 0;
    -webkit-box-shadow: none;
    -moz-box-shadow: none;
    box-shadow: none;
  }
  .navbar .dropdown-menu:before, .navbar .dropdown-menu:after {
    display: none;
  }
  .navbar .dropdown-menu .divider {
    display: none;
  }
  .navbar-form, .navbar-search {
    float: none;
    padding: 9px 15px;
    margin: 9px 0;
    border-top: 1px solid #222222;
    border-bottom: 1px solid #222222;
    -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
    -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
  }
  .navbar .nav.pull-right {
    float: none;
    margin-left: 0;
  }
  .navbar-static .navbar-inner {
    padding-left: 10px;
    padding-right: 10px;
  }
  .btn-navbar {
    display: block;
  }
  .nav-collapse {
    overflow: hidden;
    height: 0;
  }
}
@media (min-width: 980px) {
  .nav-collapse.collapse {
    height: auto !important;
  }
}
@media (min-width: 1200px) {
  .row {
    margin-left: -30px;
    *zoom: 1;
  }
  .row:before, .row:after {
    display: table;
    content: "";
  }
  .row:after {
    clear: both;
  }
  [class*="span"] {
    float: left;
    margin-left: 30px;
  }
  .span1 {
    width: 70px;
  }
  .span2 {
    width: 170px;
  }
  .span3 {
    width: 270px;
  }
  .span4 {
    width: 370px;
  }
  .span5 {
    width: 470px;
  }
  .span6 {
    width: 570px;
  }
  .span7 {
    width: 670px;
  }
  .span8 {
    width: 770px;
  }
  .span9 {
    width: 870px;
  }
  .span10 {
    width: 970px;
  }
  .span11 {
    width: 1070px;
  }
  .span12, .container {
    width: 1170px;
  }
  .offset1 {
    margin-left: 130px;
  }
  .offset2 {
    margin-left: 230px;
  }
  .offset3 {
    margin-left: 330px;
  }
  .offset4 {
    margin-left: 430px;
  }
  .offset5 {
    margin-left: 530px;
  }
  .offset6 {
    margin-left: 630px;
  }
  .offset7 {
    margin-left: 730px;
  }
  .offset8 {
    margin-left: 830px;
  }
  .offset9 {
    margin-left: 930px;
  }
  .offset10 {
    margin-left: 1030px;
  }
  .offset11 {
    margin-left: 1130px;
  }
  .row-fluid {
    width: 100%;
    *zoom: 1;
  }
  .row-fluid:before, .row-fluid:after {
    display: table;
    content: "";
  }
  .row-fluid:after {
    clear: both;
  }
  .row-fluid > [class*="span"] {
    float: left;
    margin-left: 2.564102564%;
  }
  .row-fluid > [class*="span"]:first-child {
    margin-left: 0;
  }
  .row-fluid .span1 {
    width: 5.982905983%;
  }
  .row-fluid .span2 {
    width: 14.529914530000001%;
  }
  .row-fluid .span3 {
    width: 23.076923077%;
  }
  .row-fluid .span4 {
    width: 31.623931624%;
  }
  .row-fluid .span5 {
    width: 40.170940171000005%;
  }
  .row-fluid .span6 {
    width: 48.717948718%;
  }
  .row-fluid .span7 {
    width: 57.264957265%;
  }
  .row-fluid .span8 {
    width: 65.81196581200001%;
  }
  .row-fluid .span9 {
    width: 74.358974359%;
  }
  .row-fluid .span10 {
    width: 82.905982906%;
  }
  .row-fluid .span11 {
    width: 91.45299145300001%;
  }
  .row-fluid .span12 {
    width: 100%;
  }
  input.span1, textarea.span1, .uneditable-input.span1 {
    width: 60px;
  }
  input.span2, textarea.span2, .uneditable-input.span2 {
    width: 160px;
  }
  input.span3, textarea.span3, .uneditable-input.span3 {
    width: 260px;
  }
  input.span4, textarea.span4, .uneditable-input.span4 {
    width: 360px;
  }
  input.span5, textarea.span5, .uneditable-input.span5 {
    width: 460px;
  }
  input.span6, textarea.span6, .uneditable-input.span6 {
    width: 560px;
  }
  input.span7, textarea.span7, .uneditable-input.span7 {
    width: 660px;
  }
  input.span8, textarea.span8, .uneditable-input.span8 {
    width: 760px;
  }
  input.span9, textarea.span9, .uneditable-input.span9 {
    width: 860px;
  }
  input.span10, textarea.span10, .uneditable-input.span10 {
    width: 960px;
  }
  input.span11, textarea.span11, .uneditable-input.span11 {
    width: 1060px;
  }
  input.span12, textarea.span12, .uneditable-input.span12 {
    width: 1160px;
  }
  .thumbnails {
    margin-left: -30px;
  }
  .thumbnails > li {
    margin-left: 30px;
  }
}
@import url(bootstrap.min.css);
@import url(bootstrap-responsive.css);
@import url(prettify.css);
@import url(jquery.iviewer.css);
@import url(http://fonts.googleapis.com/css?family=Forum);

body
{
    padding-top: 60px; /* 60px to make the container go all the way to the bottom of the topbar */
    background:  #f9f9f9;
    color:       #444;
}

a
{
    color: #55A72F;
}

td p:last-of-type {
    margin: 0;
}

li.l0, li.l1, li.l2, li.l3, li.l5, li.l6, li.l7, li.l8
{
    list-style-type: decimal;
}

a.brand, h2, .hero-unit h1
{
    font-family: 'Forum', "Helvetica Neue", Helvetica, Arial, sans-serif;
}

.element .span4
{
    width: 275px;
}

.namespace-contents hr, .package-contents hr
{
    border-top: 3px dotted silver;
}

.namespace-indent, .package-indent
{
    padding-left: 10px; border-left: 1px dashed #f0f0f0;
}

.element h3 i, .namespace-contents h3 i, .package-contents h3 i
{
    margin-top: 2px;
    margin-right: 5px;
}

.element h3, .namespace-contents h3, .package-contents h3
{
    margin-top: 25px;
    margin-bottom: 20px;
    border-bottom: 1px solid silver;
}

.element h3:first-of-type, .namespace-contents h3:first-of-type,
.package-contents h3:first-of-type
{
    margin-top: 30px;
}

.element h2
{
    font-family: inherit;
    font-size: 1.2em;
    color: black;
}

.element .type
{
    font-weight: bold;
}

#search-query
{
    height: auto;
}

.hero-unit, div.element, .well
{
    border: 1px solid #e0e0e0;
    background: white;
}

.dropdown-menu a{
    overflow: hidden;
    text-overflow: ellipsis;
}
h2
{
    border-bottom:  1px dashed #55A72F;
    margin-bottom:  10px;
    padding-bottom: 0;
    padding-left:   5px;
    color:          #e9e9e9;
    font-weight:    normal;
    margin-top:     40px;
}

h2:first-of-type
{
    margin-top: 0;
}

.hero-unit
{
    background: #75a70d; /* Old browsers */
    background: -moz-radial-gradient(center, ellipse cover, #bfd255 0%, #8eb92a 72%, #72aa00 96%, #9ecb2d 100%); /* FF3.6+ */
    background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,#bfd255), color-stop(72%,#8eb92a), color-stop(96%,#72aa00), color-stop(100%,#9ecb2d)); /* Chrome,Safari4+ */
    background: -webkit-radial-gradient(center, ellipse cover, #bfd255 0%,#8eb92a 72%,#72aa00 96%,#9ecb2d 100%); /* Chrome10+,Safari5.1+ */
    background: -o-radial-gradient(center, ellipse cover, #bfd255 0%,#8eb92a 72%,#72aa00 96%,#9ecb2d 100%); /* Opera 12+ */
    background: -ms-radial-gradient(center, ellipse cover, #bfd255 0%,#8eb92a 72%,#72aa00 96%,#9ecb2d 100%); /* IE10+ */
    background: radial-gradient(center, ellipse cover, #bfd255 0%,#8eb92a 72%,#72aa00 96%,#9ecb2d 100%); /* W3C */
    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#bfd255', endColorstr='#9ecb2d',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */

    padding: 40px 0 15px 0;
    box-shadow: inset 0 0 10px gray;
}

.hero-unit h1
{
    font-weight: normal;
    text-align:  center;
    color:       white;
    text-shadow: black 0 0 15px;
}

.hero-unit h2
{
    border:     none;
    color:      white;
    background: rgba(48, 48, 48, 0.5);
    padding:    0;
    margin:     0;
    margin-top: 15px;
    text-align: center;
}

.namespace-contents h2, .package-contents h2
{
    padding-left: 44px;
    background: transparent url('../img/icons/icon-th-big.png') no-repeat 3px center;
}

.package-contents h2
{
    background-image: url('../img/icons/icon-folder-open-big.png');
}

.namespace-contents .element h2, .package-contents .element h2
{
    padding-left: 0;
    background: none;
}

div.element
{
    border-left:    10px solid #55A72F;
    border-radius:  5px;
    padding:        7px 7px 2px 7px;
    margin-bottom:  15px;
    margin-left:    0;
}

div.element.protected
{
    border-left-color: orange;
}

div.element.private
{
    border-left-color: red;
}

div.element.class, div.element.interface
{
    border-left-color: #e0e0e0;
}

div.element.class.abstract h1, div.element.interface.abstract h1
{
    font-style: italic;
}

div.element h1
{
    font-size:     1.2em;
    line-height:   1.5em;
    margin-bottom: 10px;
    padding-left:  22px;
    background:    transparent no-repeat left 2px;
    word-wrap:     break-word;
}

div.element h1 a
{
    color: transparent;
    margin-left: 10px;
}

div.element h1:hover a
{
    color: silver;
}

div.element h1 a:hover
{
    color: navy;
}

div.element a.more:hover
{
    background: #f0f0f0;
    color:      #444;
    text-decoration: none;
}

div.element a.more
{
    font-weight: bold;
    text-align: center;
    color:      gray;
    border-top: 1px dashed silver;
    display:    block;
    margin-top: 5px;
    padding:    5px 0;
    border-bottom-left-radius: 5px;
    border-bottom-right-radius: 5px;
}

div.element p
{
    font-size:     0.9em;
}

div.element .table
{
    font-size: 0.9em;
}

div.element .table th
{
    text-transform: capitalize;
}

div.detail-description
{
    padding-left: 30px;
}

div.detail-description table th {
    vertical-align: top;
}

body.invert
{
    background: white;
}

body.invert div.element
{
    background: #f9f9f9;
}

ul.side-nav
{
    clear: both;
}

ul.side-nav li
{
    word-wrap: break-word;
    padding-left: 10px;
    text-indent: -10px;
}

ul.side-nav li a
{
    background:     transparent no-repeat 5px 3px;
    padding-bottom: 10px;
    font-style:     italic;
}

ul.side-nav li pre
{
    font-size:        0.8em;
    margin:           5px 15px 0 15px;
    padding:          2px 5px;
    background-color: #f8f8f8;
    color:            gray;
    font-style:       normal;
    word-wrap:        break-word;
    text-indent:      0;
}

ul.side-nav li.view-simple span.description
{
    display: none;
}

ul.side-nav li.view-simple pre
{
    font-size:        inherit;
    margin:           inherit;
    padding:          inherit;
    background-color: inherit;
    border:           none;
    color:            inherit;
    font-family:      inherit;
    font-style:       inherit;
    padding-bottom:   0;
    padding-left:     5px;
}

ul.side-nav li.view-simple a
{
    padding-bottom: 0;
}

i.icon-custom
{
    width: 16px;
    height: 16px;
    background-position: 0;
}

.table.markers
{
    background: white;
}

/* JS only functionality; disable by default */
.btn-group.visibility, .btn-group.view, .btn-group.type-filter
{
    display: none;
}

.visibility button
{
    height: 24px;
}

div.element.constant h1,
i.icon-constant  { background-image: url('../img/icons/constant.png'); }

div.element.function h1,
i.icon-function  { background-image: url('../img/icons/function.png'); }

div.element.method h1,
i.icon-method    { background-image: url('../img/icons/method.png'); }

div.element.class h1,
i.icon-class     { background-image: url('../img/icons/class.png'); }

div.element.interface h1,
i.icon-interface { background-image: url('../img/icons/interface.png'); }

div.element.property h1,
i.icon-property  { background-image: url('../img/icons/property.png'); }

span.empty-namespace
{
    color: silver;
}

footer
{
    text-align: right;
    font-size: 0.8em;
    opacity: 0.5;
}

#mapHolder
{
    border:   4px solid #555;
    padding:  0 !important;
    overflow: hidden
}

div.element div.subelement
{
    margin-left:    10px;
    padding-bottom: 5px;
    clear: both;
}

pre code
{
    border: none;
}

div.element div.subelement  > code
{
    font-size:    0.8em;
    float:        left;
    margin-right: 10px;
    padding:      0 5px;
    line-height:  16px;
}

div.element div.subelement  > p
{
    margin-left: 20px;
    margin-right: 50px;
}

div.element div.subelement h4
{
    color: #666;
    margin-bottom: 5px;
}

div.element div.subelement.response
{
    padding-bottom: 15px;
    margin-right: 50px;
}

div.labels
{
    text-align: right;
}

.nav-list .nav-header
{
    font-size: 13px;
}

.nav-list .nav-header .side-nav-header
{
    font-weight: bold;
    line-height: 18px;
    color: #999999;
    text-transform: uppercase;
}

.detail-description code {
    white-space: pre;
    display:     inline-block;
    padding:     10px;
}

.go_to_top
{
    float:                      right;
    margin-right:               20px;
    background:                 #2C2C2C;
    color:                      #999;
    padding:                    3px 10px;
    border-bottom-right-radius: 5px;
    border-bottom-left-radius:  5px;
    text-shadow:                0 -1px 0 rgba(0, 0, 0, 0.25);
    line-height:                19px;
}

.visibility .btn {
    text-transform: uppercase;
    font-size: 0.7em;
    font-weight: bold;
}

.iviewer_common
{
    z-index: 100;
}

@media (min-width: 980px)
{
    a[name]
    {
        margin-top: -50px;
        position:   absolute;
    }
}

@media (min-width: 1200px)
{
    .method .span4
    {
        width: 345px;
    }
}

/* redefined because twitter bootstrap assumes that bootstrap-responsive.css */
@media (max-width: 980px)
{
    body
    {
        padding-top: 0;
    }

    .go_to_top
    {
        display: none;
    }

    .btn-group.visibility
    {
        font-size: 0.80em;
        margin-bottom: 7px;
        display: inline-block;
        float: right;
    }
}

@media (max-width: 768px)
{
    .hero-unit h1 {
        font-size: 30px;
    }
    .hero-unit h2 {
        font-size: 19px;
    }

}
@media (min-width: 768px) and (max-width: 980px)
{
    .method .span4
    {
        width: 203px;
    }
}
article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block;}
audio,canvas,video{display:inline-block;*display:inline;*zoom:1;}
audio:not([controls]){display:none;}
html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;}
a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}
a:hover,a:active{outline:0;}
sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline;}
sup{top:-0.5em;}
sub{bottom:-0.25em;}
img{max-width:100%;height:auto;border:0;-ms-interpolation-mode:bicubic;}
button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle;}
button,input{*overflow:visible;line-height:normal;}
button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0;}
button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button;}
input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;}
input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none;}
textarea{overflow:auto;vertical-align:top;}
body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;line-height:18px;color:#333333;background-color:#ffffff;}
a{color:#0088cc;text-decoration:none;}
a:hover{color:#005580;text-decoration:underline;}
.row{margin-left:-20px;*zoom:1;}.row:before,.row:after{display:table;content:"";}
.row:after{clear:both;}
[class*="span"]{float:left;margin-left:20px;}
.span1{width:60px;}
.span2{width:140px;}
.span3{width:220px;}
.span4{width:300px;}
.span5{width:380px;}
.span6{width:460px;}
.span7{width:540px;}
.span8{width:620px;}
.span9{width:700px;}
.span10{width:780px;}
.span11{width:860px;}
.span12,.container{width:940px;}
.offset1{margin-left:100px;}
.offset2{margin-left:180px;}
.offset3{margin-left:260px;}
.offset4{margin-left:340px;}
.offset5{margin-left:420px;}
.offset6{margin-left:500px;}
.offset7{margin-left:580px;}
.offset8{margin-left:660px;}
.offset9{margin-left:740px;}
.offset10{margin-left:820px;}
.offset11{margin-left:900px;}
.row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:"";}
.row-fluid:after{clear:both;}
.row-fluid>[class*="span"]{float:left;margin-left:2.127659574%;}
.row-fluid>[class*="span"]:first-child{margin-left:0;}
.row-fluid .span1{width:6.382978723%;}
.row-fluid .span2{width:14.89361702%;}
.row-fluid .span3{width:23.404255317%;}
.row-fluid .span4{width:31.914893614%;}
.row-fluid .span5{width:40.425531911%;}
.row-fluid .span6{width:48.93617020799999%;}
.row-fluid .span7{width:57.446808505%;}
.row-fluid .span8{width:65.95744680199999%;}
.row-fluid .span9{width:74.468085099%;}
.row-fluid .span10{width:82.97872339599999%;}
.row-fluid .span11{width:91.489361693%;}
.row-fluid .span12{width:99.99999998999999%;}
.container{width:940px;margin-left:auto;margin-right:auto;*zoom:1;}.container:before,.container:after{display:table;content:"";}
.container:after{clear:both;}
.container-fluid{padding-left:20px;padding-right:20px;*zoom:1;}.container-fluid:before,.container-fluid:after{display:table;content:"";}
.container-fluid:after{clear:both;}
p{margin:0 0 9px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;line-height:18px;}p small{font-size:11px;color:#999999;}
.lead{margin-bottom:18px;font-size:20px;font-weight:200;line-height:27px;}
h1,h2,h3,h4,h5,h6{margin:0;font-weight:bold;color:#333333;text-rendering:optimizelegibility;}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;color:#999999;}
h1{font-size:30px;line-height:36px;}h1 small{font-size:18px;}
h2{font-size:24px;line-height:36px;}h2 small{font-size:18px;}
h3{line-height:27px;font-size:18px;}h3 small{font-size:14px;}
h4,h5,h6{line-height:18px;}
h4{font-size:14px;}h4 small{font-size:12px;}
h5{font-size:12px;}
h6{font-size:11px;color:#999999;text-transform:uppercase;}
.page-header{padding-bottom:17px;margin:18px 0;border-bottom:1px solid #eeeeee;}
.page-header h1{line-height:1;}
ul,ol{padding:0;margin:0 0 9px 25px;}
ul ul,ul ol,ol ol,ol ul{margin-bottom:0;}
ul{list-style:disc;}
ol{list-style:decimal;}
li{line-height:18px;}
ul.unstyled{margin-left:0;list-style:none;}
dl{margin-bottom:18px;}
dt,dd{line-height:18px;}
dt{font-weight:bold;}
dd{margin-left:9px;}
hr{margin:18px 0;border:0;border-top:1px solid #e5e5e5;border-bottom:1px solid #ffffff;}
strong{font-weight:bold;}
em{font-style:italic;}
.muted{color:#999999;}
abbr{font-size:90%;text-transform:uppercase;border-bottom:1px dotted #ddd;cursor:help;}
blockquote{padding:0 0 0 15px;margin:0 0 18px;border-left:5px solid #eeeeee;}blockquote p{margin-bottom:0;font-size:16px;font-weight:300;line-height:22.5px;}
blockquote small{display:block;line-height:18px;color:#999999;}blockquote small:before{content:'\2014 \00A0';}
blockquote.pull-right{float:right;padding-left:0;padding-right:15px;border-left:0;border-right:5px solid #eeeeee;}blockquote.pull-right p,blockquote.pull-right small{text-align:right;}
q:before,q:after,blockquote:before,blockquote:after{content:"";}
address{display:block;margin-bottom:18px;line-height:18px;font-style:normal;}
small{font-size:100%;}
cite{font-style:normal;}
code,pre{padding:0 3px 2px;font-family:Menlo,Monaco,"Courier New",monospace;font-size:12px;color:#333333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
code{padding:3px 4px;color:#d14;background-color:#f7f7f9;border:1px solid #e1e1e8;}
pre{display:block;padding:8.5px;margin:0 0 9px;font-size:12px;line-height:18px;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;white-space:pre;white-space:pre-wrap;word-break:break-all;}pre.prettyprint{margin-bottom:18px;}
pre code{padding:0;background-color:transparent;}
form{margin:0 0 18px;}
fieldset{padding:0;margin:0;border:0;}
legend{display:block;width:100%;padding:0;margin-bottom:27px;font-size:19.5px;line-height:36px;color:#333333;border:0;border-bottom:1px solid #eee;}
label,input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:18px;}
label{display:block;margin-bottom:5px;color:#333333;}
input,textarea,select,.uneditable-input{display:inline-block;width:210px;height:18px;padding:4px;margin-bottom:9px;font-size:13px;line-height:18px;color:#555555;border:1px solid #ccc;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
.uneditable-textarea{width:auto;height:auto;}
label input,label textarea,label select{display:block;}
input[type="image"],input[type="checkbox"],input[type="radio"]{width:auto;height:auto;padding:0;margin:3px 0;*margin-top:0;line-height:normal;border:0;cursor:pointer;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
input[type="file"]{padding:initial;line-height:initial;border:initial;background-color:#ffffff;background-color:initial;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
input[type="button"],input[type="reset"],input[type="submit"]{width:auto;height:auto;}
select,input[type="file"]{height:28px;*margin-top:4px;line-height:28px;}
select{width:220px;background-color:#ffffff;}
select[multiple],select[size]{height:auto;}
input[type="image"]{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
textarea{height:auto;}
input[type="hidden"]{display:none;}
.radio,.checkbox{padding-left:18px;}
.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-18px;}
.controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px;}
.radio.inline,.checkbox.inline{display:inline-block;margin-bottom:0;vertical-align:middle;}
.radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px;}
.controls>.radio.inline:first-child,.controls>.checkbox.inline:first-child{padding-top:0;}
input,textarea{-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-webkit-transition:border linear 0.2s,box-shadow linear 0.2s;-moz-transition:border linear 0.2s,box-shadow linear 0.2s;-ms-transition:border linear 0.2s,box-shadow linear 0.2s;-o-transition:border linear 0.2s,box-shadow linear 0.2s;transition:border linear 0.2s,box-shadow linear 0.2s;}
input:focus,textarea:focus{border-color:rgba(82, 168, 236, 0.8);-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 8px rgba(82, 168, 236, 0.6);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 8px rgba(82, 168, 236, 0.6);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 8px rgba(82, 168, 236, 0.6);outline:0;outline:thin dotted \9;}
input[type="file"]:focus,input[type="checkbox"]:focus,select:focus{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}
.input-mini{width:60px;}
.input-small{width:90px;}
.input-medium{width:150px;}
.input-large{width:210px;}
.input-xlarge{width:270px;}
.input-xxlarge{width:530px;}
input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{float:none;margin-left:0;}
input.span1,textarea.span1,.uneditable-input.span1{width:50px;}
input.span2,textarea.span2,.uneditable-input.span2{width:130px;}
input.span3,textarea.span3,.uneditable-input.span3{width:210px;}
input.span4,textarea.span4,.uneditable-input.span4{width:290px;}
input.span5,textarea.span5,.uneditable-input.span5{width:370px;}
input.span6,textarea.span6,.uneditable-input.span6{width:450px;}
input.span7,textarea.span7,.uneditable-input.span7{width:530px;}
input.span8,textarea.span8,.uneditable-input.span8{width:610px;}
input.span9,textarea.span9,.uneditable-input.span9{width:690px;}
input.span10,textarea.span10,.uneditable-input.span10{width:770px;}
input.span11,textarea.span11,.uneditable-input.span11{width:850px;}
input.span12,textarea.span12,.uneditable-input.span12{width:930px;}
input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{background-color:#f5f5f5;border-color:#ddd;cursor:not-allowed;}
.control-group.warning>label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853;}
.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853;border-color:#c09853;}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:0 0 6px #dbc59e;-moz-box-shadow:0 0 6px #dbc59e;box-shadow:0 0 6px #dbc59e;}
.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853;}
.control-group.error>label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48;}
.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48;border-color:#b94a48;}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:0 0 6px #d59392;-moz-box-shadow:0 0 6px #d59392;box-shadow:0 0 6px #d59392;}
.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48;}
.control-group.success>label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847;}
.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847;border-color:#468847;}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:0 0 6px #7aba7b;-moz-box-shadow:0 0 6px #7aba7b;box-shadow:0 0 6px #7aba7b;}
.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847;}
input:focus:required:invalid,textarea:focus:required:invalid,select:focus:required:invalid{color:#b94a48;border-color:#ee5f5b;}input:focus:required:invalid:focus,textarea:focus:required:invalid:focus,select:focus:required:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7;}
.form-actions{padding:17px 20px 18px;margin-top:18px;margin-bottom:18px;background-color:#f5f5f5;border-top:1px solid #ddd;}
.uneditable-input{display:block;background-color:#ffffff;border-color:#eee;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);cursor:not-allowed;}
:-moz-placeholder{color:#999999;}
::-webkit-input-placeholder{color:#999999;}
.help-block{margin-top:5px;margin-bottom:0;color:#999999;}
.help-inline{display:inline-block;*display:inline;*zoom:1;margin-bottom:9px;vertical-align:middle;padding-left:5px;}
.input-prepend,.input-append{margin-bottom:5px;*zoom:1;}.input-prepend:before,.input-append:before,.input-prepend:after,.input-append:after{display:table;content:"";}
.input-prepend:after,.input-append:after{clear:both;}
.input-prepend input,.input-append input,.input-prepend .uneditable-input,.input-append .uneditable-input{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;}.input-prepend input:focus,.input-append input:focus,.input-prepend .uneditable-input:focus,.input-append .uneditable-input:focus{position:relative;z-index:2;}
.input-prepend .uneditable-input,.input-append .uneditable-input{border-left-color:#ccc;}
.input-prepend .add-on,.input-append .add-on{float:left;display:block;width:auto;min-width:16px;height:18px;margin-right:-1px;padding:4px 5px;font-weight:normal;line-height:18px;color:#999999;text-align:center;text-shadow:0 1px 0 #ffffff;background-color:#f5f5f5;border:1px solid #ccc;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;}
.input-prepend .active,.input-append .active{background-color:#a9dba9;border-color:#46a546;}
.input-prepend .add-on{*margin-top:1px;}
.input-append input,.input-append .uneditable-input{float:left;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;}
.input-append .uneditable-input{border-right-color:#ccc;}
.input-append .add-on{margin-right:0;margin-left:-1px;-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;}
.input-append input:first-child{*margin-left:-160px;}.input-append input:first-child+.add-on{*margin-left:-21px;}
.search-query{padding-left:14px;padding-right:14px;margin-bottom:0;-webkit-border-radius:14px;-moz-border-radius:14px;border-radius:14px;}
.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input{display:inline-block;margin-bottom:0;}
.form-search label,.form-inline label,.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{display:inline-block;}
.form-search .input-append .add-on,.form-inline .input-prepend .add-on,.form-search .input-append .add-on,.form-inline .input-prepend .add-on{vertical-align:middle;}
.control-group{margin-bottom:9px;}
.form-horizontal legend+.control-group{margin-top:18px;-webkit-margin-top-collapse:separate;}
.form-horizontal .control-group{margin-bottom:18px;*zoom:1;}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;content:"";}
.form-horizontal .control-group:after{clear:both;}
.form-horizontal .control-group>label{float:left;width:140px;padding-top:5px;text-align:right;}
.form-horizontal .controls{margin-left:160px;}
.form-horizontal .form-actions{padding-left:160px;}
table{max-width:100%;border-collapse:collapse;border-spacing:0;}
.table{width:100%;margin-bottom:18px;}.table th,.table td{padding:8px;line-height:18px;text-align:left;border-top:1px solid #ddd;}
.table th{font-weight:bold;vertical-align:bottom;}
.table td{vertical-align:top;}
.table thead:first-child tr th,.table thead:first-child tr td{border-top:0;}
.table tbody+tbody{border-top:2px solid #ddd;}
.table-condensed th,.table-condensed td{padding:4px 5px;}
.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapsed;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}.table-bordered th+th,.table-bordered td+td,.table-bordered th+td,.table-bordered td+th{border-left:1px solid #ddd;}
.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0;}
.table-bordered thead:first-child tr:first-child th:first-child,.table-bordered tbody:first-child tr:first-child td:first-child{-webkit-border-radius:4px 0 0 0;-moz-border-radius:4px 0 0 0;border-radius:4px 0 0 0;}
.table-bordered thead:first-child tr:first-child th:last-child,.table-bordered tbody:first-child tr:first-child td:last-child{-webkit-border-radius:0 4px 0 0;-moz-border-radius:0 4px 0 0;border-radius:0 4px 0 0;}
.table-bordered thead:last-child tr:last-child th:first-child,.table-bordered tbody:last-child tr:last-child td:first-child{-webkit-border-radius:0 0 0 4px;-moz-border-radius:0 0 0 4px;border-radius:0 0 0 4px;}
.table-bordered thead:last-child tr:last-child th:last-child,.table-bordered tbody:last-child tr:last-child td:last-child{-webkit-border-radius:0 0 4px 0;-moz-border-radius:0 0 4px 0;border-radius:0 0 4px 0;}
.table-striped tbody tr:nth-child(odd) td,.table-striped tbody tr:nth-child(odd) th{background-color:#f9f9f9;}
table .span1{float:none;width:44px;margin-left:0;}
table .span2{float:none;width:124px;margin-left:0;}
table .span3{float:none;width:204px;margin-left:0;}
table .span4{float:none;width:284px;margin-left:0;}
table .span5{float:none;width:364px;margin-left:0;}
table .span6{float:none;width:444px;margin-left:0;}
table .span7{float:none;width:524px;margin-left:0;}
table .span8{float:none;width:604px;margin-left:0;}
table .span9{float:none;width:684px;margin-left:0;}
table .span10{float:none;width:764px;margin-left:0;}
table .span11{float:none;width:844px;margin-left:0;}
table .span12{float:none;width:924px;margin-left:0;}
[class^="icon-"]{display:inline-block;width:14px;height:14px;vertical-align:text-top;background-image:url(../img/glyphicons-halflings.png);background-position:14px 14px;background-repeat:no-repeat;*margin-right:.3em;}[class^="icon-"]:last-child{*margin-left:0;}
.icon-white{background-image:url(../img/glyphicons-halflings-white.png);}
.icon-glass{background-position:0 0;}
.icon-music{background-position:-24px 0;}
.icon-search{background-position:-48px 0;}
.icon-envelope{background-position:-72px 0;}
.icon-heart{background-position:-96px 0;}
.icon-star{background-position:-120px 0;}
.icon-star-empty{background-position:-144px 0;}
.icon-user{background-position:-168px 0;}
.icon-film{background-position:-192px 0;}
.icon-th-large{background-position:-216px 0;}
.icon-th{background-position:-240px 0;}
.icon-th-list{background-position:-264px 0;}
.icon-ok{background-position:-288px 0;}
.icon-remove{background-position:-312px 0;}
.icon-zoom-in{background-position:-336px 0;}
.icon-zoom-out{background-position:-360px 0;}
.icon-off{background-position:-384px 0;}
.icon-signal{background-position:-408px 0;}
.icon-cog{background-position:-432px 0;}
.icon-trash{background-position:-456px 0;}
.icon-home{background-position:0 -24px;}
.icon-file{background-position:-24px -24px;}
.icon-time{background-position:-48px -24px;}
.icon-road{background-position:-72px -24px;}
.icon-download-alt{background-position:-96px -24px;}
.icon-download{background-position:-120px -24px;}
.icon-upload{background-position:-144px -24px;}
.icon-inbox{background-position:-168px -24px;}
.icon-play-circle{background-position:-192px -24px;}
.icon-repeat{background-position:-216px -24px;}
.icon-refresh{background-position:-240px -24px;}
.icon-list-alt{background-position:-264px -24px;}
.icon-lock{background-position:-287px -24px;}
.icon-flag{background-position:-312px -24px;}
.icon-headphones{background-position:-336px -24px;}
.icon-volume-off{background-position:-360px -24px;}
.icon-volume-down{background-position:-384px -24px;}
.icon-volume-up{background-position:-408px -24px;}
.icon-qrcode{background-position:-432px -24px;}
.icon-barcode{background-position:-456px -24px;}
.icon-tag{background-position:0 -48px;}
.icon-tags{background-position:-25px -48px;}
.icon-book{background-position:-48px -48px;}
.icon-bookmark{background-position:-72px -48px;}
.icon-print{background-position:-96px -48px;}
.icon-camera{background-position:-120px -48px;}
.icon-font{background-position:-144px -48px;}
.icon-bold{background-position:-167px -48px;}
.icon-italic{background-position:-192px -48px;}
.icon-text-height{background-position:-216px -48px;}
.icon-text-width{background-position:-240px -48px;}
.icon-align-left{background-position:-264px -48px;}
.icon-align-center{background-position:-288px -48px;}
.icon-align-right{background-position:-312px -48px;}
.icon-align-justify{background-position:-336px -48px;}
.icon-list{background-position:-360px -48px;}
.icon-indent-left{background-position:-384px -48px;}
.icon-indent-right{background-position:-408px -48px;}
.icon-facetime-video{background-position:-432px -48px;}
.icon-picture{background-position:-456px -48px;}
.icon-pencil{background-position:0 -72px;}
.icon-map-marker{background-position:-24px -72px;}
.icon-adjust{background-position:-48px -72px;}
.icon-tint{background-position:-72px -72px;}
.icon-edit{background-position:-96px -72px;}
.icon-share{background-position:-120px -72px;}
.icon-check{background-position:-144px -72px;}
.icon-move{background-position:-168px -72px;}
.icon-step-backward{background-position:-192px -72px;}
.icon-fast-backward{background-position:-216px -72px;}
.icon-backward{background-position:-240px -72px;}
.icon-play{background-position:-264px -72px;}
.icon-pause{background-position:-288px -72px;}
.icon-stop{background-position:-312px -72px;}
.icon-forward{background-position:-336px -72px;}
.icon-fast-forward{background-position:-360px -72px;}
.icon-step-forward{background-position:-384px -72px;}
.icon-eject{background-position:-408px -72px;}
.icon-chevron-left{background-position:-432px -72px;}
.icon-chevron-right{background-position:-456px -72px;}
.icon-plus-sign{background-position:0 -96px;}
.icon-minus-sign{background-position:-24px -96px;}
.icon-remove-sign{background-position:-48px -96px;}
.icon-ok-sign{background-position:-72px -96px;}
.icon-question-sign{background-position:-96px -96px;}
.icon-info-sign{background-position:-120px -96px;}
.icon-screenshot{background-position:-144px -96px;}
.icon-remove-circle{background-position:-168px -96px;}
.icon-ok-circle{background-position:-192px -96px;}
.icon-ban-circle{background-position:-216px -96px;}
.icon-arrow-left{background-position:-240px -96px;}
.icon-arrow-right{background-position:-264px -96px;}
.icon-arrow-up{background-position:-289px -96px;}
.icon-arrow-down{background-position:-312px -96px;}
.icon-share-alt{background-position:-336px -96px;}
.icon-resize-full{background-position:-360px -96px;}
.icon-resize-small{background-position:-384px -96px;}
.icon-plus{background-position:-408px -96px;}
.icon-minus{background-position:-433px -96px;}
.icon-asterisk{background-position:-456px -96px;}
.icon-exclamation-sign{background-position:0 -120px;}
.icon-gift{background-position:-24px -120px;}
.icon-leaf{background-position:-48px -120px;}
.icon-fire{background-position:-72px -120px;}
.icon-eye-open{background-position:-96px -120px;}
.icon-eye-close{background-position:-120px -120px;}
.icon-warning-sign{background-position:-144px -120px;}
.icon-plane{background-position:-168px -120px;}
.icon-calendar{background-position:-192px -120px;}
.icon-random{background-position:-216px -120px;}
.icon-comment{background-position:-240px -120px;}
.icon-magnet{background-position:-264px -120px;}
.icon-chevron-up{background-position:-288px -120px;}
.icon-chevron-down{background-position:-313px -119px;}
.icon-retweet{background-position:-336px -120px;}
.icon-shopping-cart{background-position:-360px -120px;}
.icon-folder-close{background-position:-384px -120px;}
.icon-folder-open{background-position:-408px -120px;}
.icon-resize-vertical{background-position:-432px -119px;}
.icon-resize-horizontal{background-position:-456px -118px;}
.dropdown{position:relative;}
.dropdown-toggle{*margin-bottom:-3px;}
.dropdown-toggle:active,.open .dropdown-toggle{outline:0;}
.caret{display:inline-block;width:0;height:0;text-indent:-99999px;*text-indent:0;vertical-align:top;border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid #000000;opacity:0.3;filter:alpha(opacity=30);content:"\2193";}
.dropdown .caret{margin-top:8px;margin-left:2px;}
.dropdown:hover .caret,.open.dropdown .caret{opacity:1;filter:alpha(opacity=100);}
.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;float:left;display:none;min-width:160px;max-width:220px;_width:160px;padding:4px 0;margin:0;list-style:none;background-color:#ffffff;border-color:#ccc;border-color:rgba(0, 0, 0, 0.2);border-style:solid;border-width:1px;-webkit-border-radius:0 0 5px 5px;-moz-border-radius:0 0 5px 5px;border-radius:0 0 5px 5px;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box;*border-right-width:2px;*border-bottom-width:2px;}.dropdown-menu.bottom-up{top:auto;bottom:100%;margin-bottom:2px;}
.dropdown-menu .divider{height:1px;margin:5px 1px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #ffffff;*width:100%;*margin:-5px 0 5px;}
.dropdown-menu a{display:block;padding:3px 15px;clear:both;font-weight:normal;line-height:18px;color:#555555;white-space:nowrap;}
.dropdown-menu li>a:hover,.dropdown-menu .active>a,.dropdown-menu .active>a:hover{color:#ffffff;text-decoration:none;background-color:#0088cc;}
.dropdown.open{*z-index:1000;}.dropdown.open .dropdown-toggle{color:#ffffff;background:#ccc;background:rgba(0, 0, 0, 0.3);}
.dropdown.open .dropdown-menu{display:block;}
.typeahead{margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #eee;border:1px solid rgba(0, 0, 0, 0.05);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);}.well blockquote{border-color:#ddd;border-color:rgba(0, 0, 0, 0.15);}
.fade{-webkit-transition:opacity 0.15s linear;-moz-transition:opacity 0.15s linear;-ms-transition:opacity 0.15s linear;-o-transition:opacity 0.15s linear;transition:opacity 0.15s linear;opacity:0;}.fade.in{opacity:1;}
.collapse{-webkit-transition:height 0.35s ease;-moz-transition:height 0.35s ease;-ms-transition:height 0.35s ease;-o-transition:height 0.35s ease;transition:height 0.35s ease;position:relative;overflow:hidden;height:0;}.collapse.in{height:auto;}
.close{float:right;font-size:20px;font-weight:bold;line-height:18px;color:#000000;text-shadow:0 1px 0 #ffffff;opacity:0.2;filter:alpha(opacity=20);}.close:hover{color:#000000;text-decoration:none;opacity:0.4;filter:alpha(opacity=40);cursor:pointer;}
.btn{display:inline-block;padding:4px 10px 4px;font-size:13px;line-height:18px;color:#333333;text-align:center;text-shadow:0 1px 1px rgba(255, 255, 255, 0.75);background-color:#fafafa;background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6));background-image:-webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-image:-moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6);background-image:-ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-image:-o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-image:linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0);border:1px solid #ccc;border-bottom-color:#bbb;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);cursor:pointer;*margin-left:.3em;}.btn:first-child{*margin-left:0;}
.btn:hover{color:#333333;text-decoration:none;background-color:#e6e6e6;background-position:0 -15px;-webkit-transition:background-position 0.1s linear;-moz-transition:background-position 0.1s linear;-ms-transition:background-position 0.1s linear;-o-transition:background-position 0.1s linear;transition:background-position 0.1s linear;}
.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}
.btn.active,.btn:active{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);background-color:#e6e6e6;background-color:#d9d9d9 \9;color:rgba(0, 0, 0, 0.5);outline:0;}
.btn.disabled,.btn[disabled]{cursor:default;background-image:none;background-color:#e6e6e6;opacity:0.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
.btn-large{padding:9px 14px;font-size:15px;line-height:normal;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;}
.btn-large .icon{margin-top:1px;}
.btn-small{padding:5px 9px;font-size:11px;line-height:16px;}
.btn-small .icon{margin-top:-1px;}
.btn-primary,.btn-primary:hover,.btn-warning,.btn-warning:hover,.btn-danger,.btn-danger:hover,.btn-success,.btn-success:hover,.btn-info,.btn-info:hover{text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);color:#ffffff;}
.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active{color:rgba(255, 255, 255, 0.75);}
.btn-primary{background-color:#006dcc;background-image:-moz-linear-gradient(top, #0088cc, #0044cc);background-image:-ms-linear-gradient(top, #0088cc, #0044cc);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));background-image:-webkit-linear-gradient(top, #0088cc, #0044cc);background-image:-o-linear-gradient(top, #0088cc, #0044cc);background-image:linear-gradient(top, #0088cc, #0044cc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);border-color:#0044cc #0044cc #002a80;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-primary:hover,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{background-color:#0044cc;}
.btn-primary:active,.btn-primary.active{background-color:#003399 \9;}
.btn-warning{background-color:#faa732;background-image:-moz-linear-gradient(top, #fbb450, #f89406);background-image:-ms-linear-gradient(top, #fbb450, #f89406);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));background-image:-webkit-linear-gradient(top, #fbb450, #f89406);background-image:-o-linear-gradient(top, #fbb450, #f89406);background-image:linear-gradient(top, #fbb450, #f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fbb450', endColorstr='#f89406', GradientType=0);border-color:#f89406 #f89406 #ad6704;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-warning:hover,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{background-color:#f89406;}
.btn-warning:active,.btn-warning.active{background-color:#c67605 \9;}
.btn-danger{background-color:#da4f49;background-image:-moz-linear-gradient(top, #ee5f5b, #bd362f);background-image:-ms-linear-gradient(top, #ee5f5b, #bd362f);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));background-image:-webkit-linear-gradient(top, #ee5f5b, #bd362f);background-image:-o-linear-gradient(top, #ee5f5b, #bd362f);background-image:linear-gradient(top, #ee5f5b, #bd362f);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#bd362f', GradientType=0);border-color:#bd362f #bd362f #802420;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-danger:hover,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{background-color:#bd362f;}
.btn-danger:active,.btn-danger.active{background-color:#942a25 \9;}
.btn-success{background-color:#5bb75b;background-image:-moz-linear-gradient(top, #62c462, #51a351);background-image:-ms-linear-gradient(top, #62c462, #51a351);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));background-image:-webkit-linear-gradient(top, #62c462, #51a351);background-image:-o-linear-gradient(top, #62c462, #51a351);background-image:linear-gradient(top, #62c462, #51a351);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#51a351', GradientType=0);border-color:#51a351 #51a351 #387038;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-success:hover,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{background-color:#51a351;}
.btn-success:active,.btn-success.active{background-color:#408140 \9;}
.btn-info{background-color:#49afcd;background-image:-moz-linear-gradient(top, #5bc0de, #2f96b4);background-image:-ms-linear-gradient(top, #5bc0de, #2f96b4);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));background-image:-webkit-linear-gradient(top, #5bc0de, #2f96b4);background-image:-o-linear-gradient(top, #5bc0de, #2f96b4);background-image:linear-gradient(top, #5bc0de, #2f96b4);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#2f96b4', GradientType=0);border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-info:hover,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{background-color:#2f96b4;}
.btn-info:active,.btn-info.active{background-color:#24748c \9;}
button.btn,input[type="submit"].btn{*padding-top:2px;*padding-bottom:2px;}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0;}
button.btn.large,input[type="submit"].btn.large{*padding-top:7px;*padding-bottom:7px;}
button.btn.small,input[type="submit"].btn.small{*padding-top:3px;*padding-bottom:3px;}
.btn-group{position:relative;*zoom:1;*margin-left:.3em;}.btn-group:before,.btn-group:after{display:table;content:"";}
.btn-group:after{clear:both;}
.btn-group:first-child{*margin-left:0;}
.btn-group+.btn-group{margin-left:5px;}
.btn-toolbar{margin-top:9px;margin-bottom:9px;}.btn-toolbar .btn-group{display:inline-block;*display:inline;*zoom:1;}
.btn-group .btn{position:relative;float:left;margin-left:-1px;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
.btn-group .btn:first-child{margin-left:0;-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px;}
.btn-group .btn:last-child,.btn-group .dropdown-toggle{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px;}
.btn-group .btn.large:first-child{margin-left:0;-webkit-border-top-left-radius:6px;-moz-border-radius-topleft:6px;border-top-left-radius:6px;-webkit-border-bottom-left-radius:6px;-moz-border-radius-bottomleft:6px;border-bottom-left-radius:6px;}
.btn-group .btn.large:last-child,.btn-group .large.dropdown-toggle{-webkit-border-top-right-radius:6px;-moz-border-radius-topright:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;-moz-border-radius-bottomright:6px;border-bottom-right-radius:6px;}
.btn-group .btn:hover,.btn-group .btn:focus,.btn-group .btn:active,.btn-group .btn.active{z-index:2;}
.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0;}
.btn-group .dropdown-toggle{padding-left:8px;padding-right:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255, 255, 255, 0.125),inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 1px 0 0 rgba(255, 255, 255, 0.125),inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 1px 0 0 rgba(255, 255, 255, 0.125),inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);*padding-top:5px;*padding-bottom:5px;}
.btn-group.open{*z-index:1000;}.btn-group.open .dropdown-menu{display:block;margin-top:1px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;}
.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 1px 6px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 6px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 6px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);}
.btn .caret{margin-top:7px;margin-left:0;}
.btn:hover .caret,.open.btn-group .caret{opacity:1;filter:alpha(opacity=100);}
.btn-primary .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret{border-top-color:#ffffff;opacity:0.75;filter:alpha(opacity=75);}
.btn-small .caret{margin-top:4px;}
.alert{padding:8px 35px 8px 14px;margin-bottom:18px;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
.alert,.alert-heading{color:#c09853;}
.alert .close{position:relative;top:-2px;right:-21px;line-height:18px;}
.alert-success{background-color:#dff0d8;border-color:#d6e9c6;}
.alert-success,.alert-success .alert-heading{color:#468847;}
.alert-danger,.alert-error{background-color:#f2dede;border-color:#eed3d7;}
.alert-danger,.alert-error,.alert-danger .alert-heading,.alert-error .alert-heading{color:#b94a48;}
.alert-info{background-color:#d9edf7;border-color:#bce8f1;}
.alert-info,.alert-info .alert-heading{color:#3a87ad;}
.alert-block{padding-top:14px;padding-bottom:14px;}
.alert-block>p,.alert-block>ul{margin-bottom:0;}
.alert-block p+p{margin-top:5px;}
.nav{margin-left:0;margin-bottom:18px;list-style:none;}
.nav>li>a{display:block;}
.nav>li>a:hover{text-decoration:none;background-color:#eeeeee;}
.nav-list{padding-left:14px;padding-right:14px;margin-bottom:0;}
.nav-list>li>a,.nav-list .nav-header{display:block;padding:3px 15px;margin-left:-15px;margin-right:-15px;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);}
.nav-list .nav-header{font-size:11px;font-weight:bold;line-height:18px;color:#999999;text-transform:uppercase;}
.nav-list .nav-header *{text-transform:none;}
.nav-list>li+.nav-header{margin-top:9px;}
.nav-list .active>a,.nav-list .active>a:hover{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.2);background-color:#0088cc;}
.nav-list [class^="icon-"]{margin-right:2px;}
.nav-tabs,.nav-pills{*zoom:1;}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;content:"";}
.nav-tabs:after,.nav-pills:after{clear:both;}
.nav-tabs>li,.nav-pills>li{float:left;}
.nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px;}
.nav-tabs{border-bottom:1px solid #ddd;}
.nav-tabs>li{margin-bottom:-1px;}
.nav-tabs>li>a{padding-top:9px;padding-bottom:9px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0;}.nav-tabs>li>a:hover{border-color:#eeeeee #eeeeee #dddddd;}
.nav-tabs>.active>a,.nav-tabs>.active>a:hover{color:#555555;background-color:#ffffff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default;}
.nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;}
.nav-pills .active>a,.nav-pills .active>a:hover{color:#ffffff;background-color:#0088cc;}
.nav-stacked>li{float:none;}
.nav-stacked>li>a{margin-right:0;}
.nav-tabs.nav-stacked{border-bottom:0;}
.nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
.nav-tabs.nav-stacked>li:first-child>a{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0;}
.nav-tabs.nav-stacked>li:last-child>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;}
.nav-tabs.nav-stacked>li>a:hover{border-color:#ddd;z-index:2;}
.nav-pills.nav-stacked>li>a{margin-bottom:3px;}
.nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px;}
.nav-tabs .dropdown-menu,.nav-pills .dropdown-menu{margin-top:1px;border-width:1px;}
.nav-pills .dropdown-menu{-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
.nav-tabs .dropdown-toggle .caret,.nav-pills .dropdown-toggle .caret{border-top-color:#0088cc;margin-top:6px;}
.nav-tabs .dropdown-toggle:hover .caret,.nav-pills .dropdown-toggle:hover .caret{border-top-color:#005580;}
.nav-tabs .active .dropdown-toggle .caret,.nav-pills .active .dropdown-toggle .caret{border-top-color:#333333;}
.nav>.dropdown.active>a:hover{color:#000000;cursor:pointer;}
.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>.open.active>a:hover{color:#ffffff;background-color:#999999;border-color:#999999;}
.nav .open .caret,.nav .open.active .caret,.nav .open a:hover .caret{border-top-color:#ffffff;opacity:1;filter:alpha(opacity=100);}
.tabs-stacked .open>a:hover{border-color:#999999;}
.tabbable{*zoom:1;}.tabbable:before,.tabbable:after{display:table;content:"";}
.tabbable:after{clear:both;}
.tabs-below .nav-tabs,.tabs-right .nav-tabs,.tabs-left .nav-tabs{border-bottom:0;}
.tab-content>.tab-pane,.pill-content>.pill-pane{display:none;}
.tab-content>.active,.pill-content>.active{display:block;}
.tabs-below .nav-tabs{border-top:1px solid #ddd;}
.tabs-below .nav-tabs>li{margin-top:-1px;margin-bottom:0;}
.tabs-below .nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;}.tabs-below .nav-tabs>li>a:hover{border-bottom-color:transparent;border-top-color:#ddd;}
.tabs-below .nav-tabs .active>a,.tabs-below .nav-tabs .active>a:hover{border-color:transparent #ddd #ddd #ddd;}
.tabs-left .nav-tabs>li,.tabs-right .nav-tabs>li{float:none;}
.tabs-left .nav-tabs>li>a,.tabs-right .nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px;}
.tabs-left .nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd;}
.tabs-left .nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px;}
.tabs-left .nav-tabs>li>a:hover{border-color:#eeeeee #dddddd #eeeeee #eeeeee;}
.tabs-left .nav-tabs .active>a,.tabs-left .nav-tabs .active>a:hover{border-color:#ddd transparent #ddd #ddd;*border-right-color:#ffffff;}
.tabs-right .nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd;}
.tabs-right .nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0;}
.tabs-right .nav-tabs>li>a:hover{border-color:#eeeeee #eeeeee #eeeeee #dddddd;}
.tabs-right .nav-tabs .active>a,.tabs-right .nav-tabs .active>a:hover{border-color:#ddd #ddd #ddd transparent;*border-left-color:#ffffff;}
.navbar{overflow:visible;margin-bottom:18px;}
.navbar-inner{padding-left:20px;padding-right:20px;background-color:#2c2c2c;background-image:-moz-linear-gradient(top, #333333, #222222);background-image:-ms-linear-gradient(top, #333333, #222222);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222));background-image:-webkit-linear-gradient(top, #333333, #222222);background-image:-o-linear-gradient(top, #333333, #222222);background-image:linear-gradient(top, #333333, #222222);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 3px rgba(0, 0, 0, 0.25),inset 0 -1px 0 rgba(0, 0, 0, 0.1);-moz-box-shadow:0 1px 3px rgba(0, 0, 0, 0.25),inset 0 -1px 0 rgba(0, 0, 0, 0.1);box-shadow:0 1px 3px rgba(0, 0, 0, 0.25),inset 0 -1px 0 rgba(0, 0, 0, 0.1);}
.btn-navbar{display:none;float:right;padding:7px 10px;margin-left:5px;margin-right:5px;background-color:#2c2c2c;background-image:-moz-linear-gradient(top, #333333, #222222);background-image:-ms-linear-gradient(top, #333333, #222222);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222));background-image:-webkit-linear-gradient(top, #333333, #222222);background-image:-o-linear-gradient(top, #333333, #222222);background-image:linear-gradient(top, #333333, #222222);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0);border-color:#222222 #222222 #000000;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.075);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.075);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.075);}.btn-navbar:hover,.btn-navbar:active,.btn-navbar.active,.btn-navbar.disabled,.btn-navbar[disabled]{background-color:#222222;}
.btn-navbar:active,.btn-navbar.active{background-color:#080808 \9;}
.btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0, 0, 0, 0.25);-moz-box-shadow:0 1px 0 rgba(0, 0, 0, 0.25);box-shadow:0 1px 0 rgba(0, 0, 0, 0.25);}
.btn-navbar .icon-bar+.icon-bar{margin-top:3px;}
.nav-collapse.collapse{height:auto;}
.navbar .brand:hover{text-decoration:none;}
.navbar .brand{float:left;display:block;padding:8px 20px 12px;margin-left:-20px;font-size:20px;font-weight:200;line-height:1;color:#ffffff;}
.navbar .navbar-text{margin-bottom:0;line-height:40px;color:#999999;}.navbar .navbar-text a:hover{color:#ffffff;background-color:transparent;}
.navbar .btn,.navbar .btn-group{margin-top:5px;}
.navbar .btn-group .btn{margin-top:0;}
.navbar-form{margin-bottom:0;*zoom:1;}.navbar-form:before,.navbar-form:after{display:table;content:"";}
.navbar-form:after{clear:both;}
.navbar-form input,.navbar-form select{display:inline-block;margin-top:5px;margin-bottom:0;}
.navbar-form .radio,.navbar-form .checkbox{margin-top:5px;}
.navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px;}
.navbar-search{position:relative;float:left;margin-top:6px;margin-bottom:0;}.navbar-search .search-query{padding:4px 9px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;color:#ffffff;color:rgba(255, 255, 255, 0.75);background:#666;background:rgba(255, 255, 255, 0.3);border:1px solid #111;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.15);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.15);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.15);-webkit-transition:none;-moz-transition:none;-ms-transition:none;-o-transition:none;transition:none;}.navbar-search .search-query :-moz-placeholder{color:#eeeeee;}
.navbar-search .search-query::-webkit-input-placeholder{color:#eeeeee;}
.navbar-search .search-query:hover{color:#ffffff;background-color:#999999;background-color:rgba(255, 255, 255, 0.5);}
.navbar-search .search-query:focus,.navbar-search .search-query.focused{padding:5px 10px;color:#333333;text-shadow:0 1px 0 #ffffff;background-color:#ffffff;border:0;-webkit-box-shadow:0 0 3px rgba(0, 0, 0, 0.15);-moz-box-shadow:0 0 3px rgba(0, 0, 0, 0.15);box-shadow:0 0 3px rgba(0, 0, 0, 0.15);outline:0;}
.navbar-fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030;}
.navbar-fixed-top .navbar-inner{padding-left:0;padding-right:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0;}
.navbar .nav.pull-right{float:right;}
.navbar .nav>li{display:block;float:left;}
.navbar .nav>li>a{float:none;padding:10px 10px 11px;line-height:19px;color:#999999;text-decoration:none;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);}
.navbar .nav>li>a:hover{background-color:transparent;color:#ffffff;text-decoration:none;}
.navbar .nav .active>a,.navbar .nav .active>a:hover{color:#ffffff;text-decoration:none;background-color:#222222;background-color:rgba(0, 0, 0, 0.5);}
.navbar .divider-vertical{height:40px;width:1px;margin:0 9px;overflow:hidden;background-color:#222222;border-right:1px solid #333333;}
.navbar .nav.pull-right{margin-left:10px;margin-right:0;}
.navbar .dropdown-menu{margin-top:1px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}.navbar .dropdown-menu:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0, 0, 0, 0.2);position:absolute;top:-7px;left:9px;}
.navbar .dropdown-menu:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #ffffff;position:absolute;top:-6px;left:10px;}
.navbar .nav .dropdown-toggle .caret,.navbar .nav .open.dropdown .caret{border-top-color:#ffffff;}
.navbar .nav .active .caret{opacity:1;filter:alpha(opacity=100);}
.navbar .nav .open>.dropdown-toggle,.navbar .nav .active>.dropdown-toggle,.navbar .nav .open.active>.dropdown-toggle{background-color:transparent;}
.navbar .nav .active>.dropdown-toggle:hover{color:#ffffff;}
.navbar .nav.pull-right .dropdown-menu{left:auto;right:0;}.navbar .nav.pull-right .dropdown-menu:before{left:auto;right:12px;}
.navbar .nav.pull-right .dropdown-menu:after{left:auto;right:13px;}
.breadcrumb{padding:7px 14px;margin:0 0 18px;background-color:#fbfbfb;background-image:-moz-linear-gradient(top, #ffffff, #f5f5f5);background-image:-ms-linear-gradient(top, #ffffff, #f5f5f5);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f5f5f5));background-image:-webkit-linear-gradient(top, #ffffff, #f5f5f5);background-image:-o-linear-gradient(top, #ffffff, #f5f5f5);background-image:linear-gradient(top, #ffffff, #f5f5f5);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0);border:1px solid #ddd;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 0 #ffffff;-moz-box-shadow:inset 0 1px 0 #ffffff;box-shadow:inset 0 1px 0 #ffffff;}.breadcrumb li{display:inline;text-shadow:0 1px 0 #ffffff;}
.breadcrumb .divider{padding:0 5px;color:#999999;}
.breadcrumb .active a{color:#333333;}
.pagination{height:36px;margin:18px 0;}
.pagination ul{display:inline-block;*display:inline;*zoom:1;margin-left:0;margin-bottom:0;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);}
.pagination li{display:inline;}
.pagination a{float:left;padding:0 14px;line-height:34px;text-decoration:none;border:1px solid #ddd;border-left-width:0;}
.pagination a:hover,.pagination .active a{background-color:#f5f5f5;}
.pagination .active a{color:#999999;cursor:default;}
.pagination .disabled a,.pagination .disabled a:hover{color:#999999;background-color:transparent;cursor:default;}
.pagination li:first-child a{border-left-width:1px;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;}
.pagination li:last-child a{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;}
.pagination-centered{text-align:center;}
.pagination-right{text-align:right;}
.pager{margin-left:0;margin-bottom:18px;list-style:none;text-align:center;*zoom:1;}.pager:before,.pager:after{display:table;content:"";}
.pager:after{clear:both;}
.pager li{display:inline;}
.pager a{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px;}
.pager a:hover{text-decoration:none;background-color:#f5f5f5;}
.pager .next a{float:right;}
.pager .previous a{float:left;}
.modal-open .dropdown-menu{z-index:2050;}
.modal-open .dropdown.open{*z-index:2050;}
.modal-open .popover{z-index:2060;}
.modal-open .tooltip{z-index:2070;}
.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000000;}.modal-backdrop.fade{opacity:0;}
.modal-backdrop,.modal-backdrop.fade.in{opacity:0.8;filter:alpha(opacity=80);}
.modal{position:fixed;top:50%;left:50%;z-index:1050;max-height:500px;overflow:auto;width:560px;margin:-250px 0 0 -280px;background-color:#ffffff;border:1px solid #999;border:1px solid rgba(0, 0, 0, 0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;}.modal.fade{-webkit-transition:opacity .3s linear, top .3s ease-out;-moz-transition:opacity .3s linear, top .3s ease-out;-ms-transition:opacity .3s linear, top .3s ease-out;-o-transition:opacity .3s linear, top .3s ease-out;transition:opacity .3s linear, top .3s ease-out;top:-25%;}
.modal.fade.in{top:50%;}
.modal-header{padding:9px 15px;border-bottom:1px solid #eee;}.modal-header .close{margin-top:2px;}
.modal-body{padding:15px;}
.modal-footer{padding:14px 15px 15px;margin-bottom:0;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;-webkit-box-shadow:inset 0 1px 0 #ffffff;-moz-box-shadow:inset 0 1px 0 #ffffff;box-shadow:inset 0 1px 0 #ffffff;*zoom:1;}.modal-footer:before,.modal-footer:after{display:table;content:"";}
.modal-footer:after{clear:both;}
.modal-footer .btn{float:right;margin-left:5px;margin-bottom:0;}
.tooltip{position:absolute;z-index:1020;display:block;visibility:visible;padding:5px;font-size:11px;opacity:0;filter:alpha(opacity=0);}.tooltip.in{opacity:0.8;filter:alpha(opacity=80);}
.tooltip.top{margin-top:-2px;}
.tooltip.right{margin-left:2px;}
.tooltip.bottom{margin-top:2px;}
.tooltip.left{margin-left:-2px;}
.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #000000;}
.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000000;}
.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid #000000;}
.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-right:5px solid #000000;}
.tooltip-inner{max-width:200px;padding:3px 8px;color:#ffffff;text-align:center;text-decoration:none;background-color:#000000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
.tooltip-arrow{position:absolute;width:0;height:0;}
.popover{position:absolute;top:0;left:0;z-index:1010;display:none;padding:5px;}.popover.top{margin-top:-5px;}
.popover.right{margin-left:5px;}
.popover.bottom{margin-top:5px;}
.popover.left{margin-left:-5px;}
.popover.top .arrow{bottom:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #000000;}
.popover.right .arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-right:5px solid #000000;}
.popover.bottom .arrow{top:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid #000000;}
.popover.left .arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000000;}
.popover .arrow{position:absolute;width:0;height:0;}
.popover-inner{padding:3px;width:280px;overflow:hidden;background:#000000;background:rgba(0, 0, 0, 0.8);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);}
.popover-title{padding:9px 15px;line-height:1;background-color:#f5f5f5;border-bottom:1px solid #eee;-webkit-border-radius:3px 3px 0 0;-moz-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0;}
.popover-content{padding:14px;background-color:#ffffff;-webkit-border-radius:0 0 3px 3px;-moz-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;}.popover-content p,.popover-content ul,.popover-content ol{margin-bottom:0;}
.thumbnails{margin-left:-20px;list-style:none;*zoom:1;}.thumbnails:before,.thumbnails:after{display:table;content:"";}
.thumbnails:after{clear:both;}
.thumbnails>li{float:left;margin:0 0 18px 20px;}
.thumbnail{display:block;padding:4px;line-height:1;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);}
a.thumbnail:hover{border-color:#0088cc;-webkit-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);-moz-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);}
.thumbnail>img{display:block;max-width:100%;margin-left:auto;margin-right:auto;}
.thumbnail .caption{padding:9px;}
.label{padding:1px 3px 2px;font-size:9.75px;font-weight:bold;color:#ffffff;text-transform:uppercase;background-color:#999999;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
.label-important{background-color:#b94a48;}
.label-warning{background-color:#f89406;}
.label-success{background-color:#468847;}
.label-info{background-color:#3a87ad;}
@-webkit-keyframes progress-bar-stripes{from{background-position:0 0;} to{background-position:40px 0;}}@-moz-keyframes progress-bar-stripes{from{background-position:0 0;} to{background-position:40px 0;}}@keyframes progress-bar-stripes{from{background-position:0 0;} to{background-position:40px 0;}}.progress{overflow:hidden;height:18px;margin-bottom:18px;background-color:#f7f7f7;background-image:-moz-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-ms-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));background-image:-webkit-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-o-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:linear-gradient(top, #f5f5f5, #f9f9f9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f5f5f5', endColorstr='#f9f9f9', GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
.progress .bar{width:0%;height:18px;color:#ffffff;font-size:12px;text-align:center;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top, #149bdf, #0480be);background-image:-ms-linear-gradient(top, #149bdf, #0480be);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));background-image:-webkit-linear-gradient(top, #149bdf, #0480be);background-image:-o-linear-gradient(top, #149bdf, #0480be);background-image:linear-gradient(top, #149bdf, #0480be);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#149bdf', endColorstr='#0480be', GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width 0.6s ease;-moz-transition:width 0.6s ease;-ms-transition:width 0.6s ease;-o-transition:width 0.6s ease;transition:width 0.6s ease;}
.progress-striped .bar{background-color:#62c462;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px;}
.progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite;}
.progress-danger .bar{background-color:#dd514c;background-image:-moz-linear-gradient(top, #ee5f5b, #c43c35);background-image:-ms-linear-gradient(top, #ee5f5b, #c43c35);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));background-image:-webkit-linear-gradient(top, #ee5f5b, #c43c35);background-image:-o-linear-gradient(top, #ee5f5b, #c43c35);background-image:linear-gradient(top, #ee5f5b, #c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0);}
.progress-danger.progress-striped .bar{background-color:#ee5f5b;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);}
.progress-success .bar{background-color:#5eb95e;background-image:-moz-linear-gradient(top, #62c462, #57a957);background-image:-ms-linear-gradient(top, #62c462, #57a957);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));background-image:-webkit-linear-gradient(top, #62c462, #57a957);background-image:-o-linear-gradient(top, #62c462, #57a957);background-image:linear-gradient(top, #62c462, #57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0);}
.progress-success.progress-striped .bar{background-color:#62c462;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);}
.progress-info .bar{background-color:#4bb1cf;background-image:-moz-linear-gradient(top, #5bc0de, #339bb9);background-image:-ms-linear-gradient(top, #5bc0de, #339bb9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));background-image:-webkit-linear-gradient(top, #5bc0de, #339bb9);background-image:-o-linear-gradient(top, #5bc0de, #339bb9);background-image:linear-gradient(top, #5bc0de, #339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0);}
.progress-info.progress-striped .bar{background-color:#5bc0de;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);}
.accordion{margin-bottom:18px;}
.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
.accordion-heading{border-bottom:0;}
.accordion-heading .accordion-toggle{display:block;padding:8px 15px;}
.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5;}
.carousel{position:relative;margin-bottom:18px;line-height:1;}
.carousel-inner{overflow:hidden;width:100%;position:relative;}
.carousel .item{display:none;position:relative;-webkit-transition:0.6s ease-in-out left;-moz-transition:0.6s ease-in-out left;-ms-transition:0.6s ease-in-out left;-o-transition:0.6s ease-in-out left;transition:0.6s ease-in-out left;}
.carousel .item>img{display:block;line-height:1;}
.carousel .active,.carousel .next,.carousel .prev{display:block;}
.carousel .active{left:0;}
.carousel .next,.carousel .prev{position:absolute;top:0;width:100%;}
.carousel .next{left:100%;}
.carousel .prev{left:-100%;}
.carousel .next.left,.carousel .prev.right{left:0;}
.carousel .active.left{left:-100%;}
.carousel .active.right{left:100%;}
.carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#ffffff;text-align:center;background:#222222;border:3px solid #ffffff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:0.5;filter:alpha(opacity=50);}.carousel-control.right{left:auto;right:15px;}
.carousel-control:hover{color:#ffffff;text-decoration:none;opacity:0.9;filter:alpha(opacity=90);}
.carousel-caption{position:absolute;left:0;right:0;bottom:0;padding:10px 15px 5px;background:#333333;background:rgba(0, 0, 0, 0.75);}
.carousel-caption h4,.carousel-caption p{color:#ffffff;}
.hero-unit{padding:60px;margin-bottom:30px;background-color:#f5f5f5;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;}
.hero-unit p{font-size:18px;font-weight:200;line-height:27px;}
.pull-right{float:right;}
.pull-left{float:left;}
.hide{display:none;}
.show{display:block;}
.invisible{visibility:hidden;}
/*!
 * Bootstrap v2.0.0
 *
 * Copyright 2012 Twitter, Inc
 * Licensed under the Apache License v2.0
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Designed and built with all the love in the world @twitter by @mdo and @fat.
 */
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
nav,
section {
  display: block;
}
audio, canvas, video {
  display: inline-block;
  *display: inline;
  *zoom: 1;
}
audio:not([controls]) {
  display: none;
}
html {
  font-size: 100%;
  -webkit-text-size-adjust: 100%;
  -ms-text-size-adjust: 100%;
}
a:focus {
  outline: thin dotted;
  outline: 5px auto -webkit-focus-ring-color;
  outline-offset: -2px;
}
a:hover, a:active {
  outline: 0;
}
sub, sup {
  position: relative;
  font-size: 75%;
  line-height: 0;
  vertical-align: baseline;
}
sup {
  top: -0.5em;
}
sub {
  bottom: -0.25em;
}
img {
  max-width: 100%;
  height: auto;
  border: 0;
  -ms-interpolation-mode: bicubic;
}
button,
input,
select,
textarea {
  margin: 0;
  font-size: 100%;
  vertical-align: middle;
}
button, input {
  *overflow: visible;
  line-height: normal;
}
button::-moz-focus-inner, input::-moz-focus-inner {
  padding: 0;
  border: 0;
}
button,
input[type="button"],
input[type="reset"],
input[type="submit"] {
  cursor: pointer;
  -webkit-appearance: button;
}
input[type="search"] {
  -webkit-appearance: textfield;
  -webkit-box-sizing: content-box;
  -moz-box-sizing: content-box;
  box-sizing: content-box;
}
input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button {
  -webkit-appearance: none;
}
textarea {
  overflow: auto;
  vertical-align: top;
}
body {
  margin: 0;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 13px;
  line-height: 18px;
  color: #333333;
  background-color: #ffffff;
}
a {
  color: #0088cc;
  text-decoration: none;
}
a:hover {
  color: #005580;
  text-decoration: underline;
}
.row {
  margin-left: -20px;
  *zoom: 1;
}
.row:before, .row:after {
  display: table;
  content: "";
}
.row:after {
  clear: both;
}
[class*="span"] {
  float: left;
  margin-left: 20px;
}
.span1 {
  width: 60px;
}
.span2 {
  width: 140px;
}
.span3 {
  width: 220px;
}
.span4 {
  width: 300px;
}
.span5 {
  width: 380px;
}
.span6 {
  width: 460px;
}
.span7 {
  width: 540px;
}
.span8 {
  width: 620px;
}
.span9 {
  width: 700px;
}
.span10 {
  width: 780px;
}
.span11 {
  width: 860px;
}
.span12, .container {
  width: 940px;
}
.offset1 {
  margin-left: 100px;
}
.offset2 {
  margin-left: 180px;
}
.offset3 {
  margin-left: 260px;
}
.offset4 {
  margin-left: 340px;
}
.offset5 {
  margin-left: 420px;
}
.offset6 {
  margin-left: 500px;
}
.offset7 {
  margin-left: 580px;
}
.offset8 {
  margin-left: 660px;
}
.offset9 {
  margin-left: 740px;
}
.offset10 {
  margin-left: 820px;
}
.offset11 {
  margin-left: 900px;
}
.row-fluid {
  width: 100%;
  *zoom: 1;
}
.row-fluid:before, .row-fluid:after {
  display: table;
  content: "";
}
.row-fluid:after {
  clear: both;
}
.row-fluid > [class*="span"] {
  float: left;
  margin-left: 2.127659574%;
}
.row-fluid > [class*="span"]:first-child {
  margin-left: 0;
}
.row-fluid .span1 {
  width: 6.382978723%;
}
.row-fluid .span2 {
  width: 14.89361702%;
}
.row-fluid .span3 {
  width: 23.404255317%;
}
.row-fluid .span4 {
  width: 31.914893614%;
}
.row-fluid .span5 {
  width: 40.425531911%;
}
.row-fluid .span6 {
  width: 48.93617020799999%;
}
.row-fluid .span7 {
  width: 57.446808505%;
}
.row-fluid .span8 {
  width: 65.95744680199999%;
}
.row-fluid .span9 {
  width: 74.468085099%;
}
.row-fluid .span10 {
  width: 82.97872339599999%;
}
.row-fluid .span11 {
  width: 91.489361693%;
}
.row-fluid .span12 {
  width: 99.99999998999999%;
}
.container {
  width: 940px;
  margin-left: auto;
  margin-right: auto;
  *zoom: 1;
}
.container:before, .container:after {
  display: table;
  content: "";
}
.container:after {
  clear: both;
}
.container-fluid {
  padding-left: 20px;
  padding-right: 20px;
  *zoom: 1;
}
.container-fluid:before, .container-fluid:after {
  display: table;
  content: "";
}
.container-fluid:after {
  clear: both;
}
p {
  margin: 0 0 9px;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 13px;
  line-height: 18px;
}
p small {
  font-size: 11px;
  color: #999999;
}
.lead {
  margin-bottom: 18px;
  font-size: 20px;
  font-weight: 200;
  line-height: 27px;
}
h1,
h2,
h3,
h4,
h5,
h6 {
  margin: 0;
  font-weight: bold;
  color: #333333;
  text-rendering: optimizelegibility;
}
h1 small,
h2 small,
h3 small,
h4 small,
h5 small,
h6 small {
  font-weight: normal;
  color: #999999;
}
h1 {
  font-size: 30px;
  line-height: 36px;
}
h1 small {
  font-size: 18px;
}
h2 {
  font-size: 24px;
  line-height: 36px;
}
h2 small {
  font-size: 18px;
}
h3 {
  line-height: 27px;
  font-size: 18px;
}
h3 small {
  font-size: 14px;
}
h4, h5, h6 {
  line-height: 18px;
}
h4 {
  font-size: 14px;
}
h4 small {
  font-size: 12px;
}
h5 {
  font-size: 12px;
}
h6 {
  font-size: 11px;
  color: #999999;
  text-transform: uppercase;
}
.page-header {
  padding-bottom: 17px;
  margin: 18px 0;
  border-bottom: 1px solid #eeeeee;
}
.page-header h1 {
  line-height: 1;
}
ul, ol {
  padding: 0;
  margin: 0 0 9px 25px;
}
ul ul,
ul ol,
ol ol,
ol ul {
  margin-bottom: 0;
}
ul {
  list-style: disc;
}
ol {
  list-style: decimal;
}
li {
  line-height: 18px;
}
ul.unstyled {
  margin-left: 0;
  list-style: none;
}
dl {
  margin-bottom: 18px;
}
dt, dd {
  line-height: 18px;
}
dt {
  font-weight: bold;
}
dd {
  margin-left: 9px;
}
hr {
  margin: 18px 0;
  border: 0;
  border-top: 1px solid #e5e5e5;
  border-bottom: 1px solid #ffffff;
}
strong {
  font-weight: bold;
}
em {
  font-style: italic;
}
.muted {
  color: #999999;
}
abbr {
  font-size: 90%;
  text-transform: uppercase;
  border-bottom: 1px dotted #ddd;
  cursor: help;
}
blockquote {
  padding: 0 0 0 15px;
  margin: 0 0 18px;
  border-left: 5px solid #eeeeee;
}
blockquote p {
  margin-bottom: 0;
  font-size: 16px;
  font-weight: 300;
  line-height: 22.5px;
}
blockquote small {
  display: block;
  line-height: 18px;
  color: #999999;
}
blockquote small:before {
  content: '\2014 \00A0';
}
blockquote.pull-right {
  float: right;
  padding-left: 0;
  padding-right: 15px;
  border-left: 0;
  border-right: 5px solid #eeeeee;
}
blockquote.pull-right p, blockquote.pull-right small {
  text-align: right;
}
q:before,
q:after,
blockquote:before,
blockquote:after {
  content: "";
}
address {
  display: block;
  margin-bottom: 18px;
  line-height: 18px;
  font-style: normal;
}
small {
  font-size: 100%;
}
cite {
  font-style: normal;
}
code, pre {
  padding: 0 3px 2px;
  font-family: Menlo, Monaco, "Courier New", monospace;
  font-size: 12px;
  color: #333333;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  border-radius: 3px;
}
code {
  padding: 3px 4px;
  color: #d14;
  background-color: #f7f7f9;
  border: 1px solid #e1e1e8;
}
pre {
  display: block;
  padding: 8.5px;
  margin: 0 0 9px;
  font-size: 12px;
  line-height: 18px;
  background-color: #f5f5f5;
  border: 1px solid #ccc;
  border: 1px solid rgba(0, 0, 0, 0.15);
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  border-radius: 4px;
  white-space: pre;
  white-space: pre-wrap;
  word-break: break-all;
}
pre.prettyprint {
  margin-bottom: 18px;
}
pre code {
  padding: 0;
  background-color: transparent;
}
form {
  margin: 0 0 18px;
}
fieldset {
  padding: 0;
  margin: 0;
  border: 0;
}
legend {
  display: block;
  width: 100%;
  padding: 0;
  margin-bottom: 27px;
  font-size: 19.5px;
  line-height: 36px;
  color: #333333;
  border: 0;
  border-bottom: 1px solid #eee;
}
label,
input,
button,
select,
textarea {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 13px;
  font-weight: normal;
  line-height: 18px;
}
label {
  display: block;
  margin-bottom: 5px;
  color: #333333;
}
input,
textarea,
select,
.uneditable-input {
  display: inline-block;
  width: 210px;
  height: 18px;
  padding: 4px;
  margin-bottom: 9px;
  font-size: 13px;
  line-height: 18px;
  color: #555555;
  border: 1px solid #ccc;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  border-radius: 3px;
}
.uneditable-textarea {
  width: auto;
  height: auto;
}
label input, label textarea, label select {
  display: block;
}
input[type="image"], input[type="checkbox"], input[type="radio"] {
  width: auto;
  height: auto;
  padding: 0;
  margin: 3px 0;
  *margin-top: 0;
  /* IE7 */

  line-height: normal;
  border: 0;
  cursor: pointer;
  -webkit-border-radius: 0;
  -moz-border-radius: 0;
  border-radius: 0;
}
input[type="file"] {
  padding: initial;
  line-height: initial;
  border: initial;
  background-color: #ffffff;
  background-color: initial;
  -webkit-box-shadow: none;
  -moz-box-shadow: none;
  box-shadow: none;
}
input[type="button"], input[type="reset"], input[type="submit"] {
  width: auto;
  height: auto;
}
select, input[type="file"] {
  height: 28px;
  /* In IE7, the height of the select element cannot be changed by height, only font-size */

  *margin-top: 4px;
  /* For IE7, add top margin to align select with labels */

  line-height: 28px;
}
select {
  width: 220px;
  background-color: #ffffff;
}
select[multiple], select[size] {
  height: auto;
}
input[type="image"] {
  -webkit-box-shadow: none;
  -moz-box-shadow: none;
  box-shadow: none;
}
textarea {
  height: auto;
}
input[type="hidden"] {
  display: none;
}
.radio, .checkbox {
  padding-left: 18px;
}
.radio input[type="radio"], .checkbox input[type="checkbox"] {
  float: left;
  margin-left: -18px;
}
.controls > .radio:first-child, .controls > .checkbox:first-child {
  padding-top: 5px;
}
.radio.inline, .checkbox.inline {
  display: inline-block;
  margin-bottom: 0;
  vertical-align: middle;
}
.radio.inline + .radio.inline, .checkbox.inline + .checkbox.inline {
  margin-left: 10px;
}
.controls > .radio.inline:first-child, .controls > .checkbox.inline:first-child {
  padding-top: 0;
}
input, textarea {
  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
  -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
  -moz-transition: border linear 0.2s, box-shadow linear 0.2s;
  -ms-transition: border linear 0.2s, box-shadow linear 0.2s;
  -o-transition: border linear 0.2s, box-shadow linear 0.2s;
  transition: border linear 0.2s, box-shadow linear 0.2s;
}
input:focus, textarea:focus {
  border-color: rgba(82, 168, 236, 0.8);
  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
  -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
  outline: 0;
  outline: thin dotted \9;
  /* IE6-8 */

}
input[type="file"]:focus, input[type="checkbox"]:focus, select:focus {
  -webkit-box-shadow: none;
  -moz-box-shadow: none;
  box-shadow: none;
  outline: thin dotted;
  outline: 5px auto -webkit-focus-ring-color;
  outline-offset: -2px;
}
.input-mini {
  width: 60px;
}
.input-small {
  width: 90px;
}
.input-medium {
  width: 150px;
}
.input-large {
  width: 210px;
}
.input-xlarge {
  width: 270px;
}
.input-xxlarge {
  width: 530px;
}
input[class*="span"],
select[class*="span"],
textarea[class*="span"],
.uneditable-input {
  float: none;
  margin-left: 0;
}
input.span1, textarea.span1, .uneditable-input.span1 {
  width: 50px;
}
input.span2, textarea.span2, .uneditable-input.span2 {
  width: 130px;
}
input.span3, textarea.span3, .uneditable-input.span3 {
  width: 210px;
}
input.span4, textarea.span4, .uneditable-input.span4 {
  width: 290px;
}
input.span5, textarea.span5, .uneditable-input.span5 {
  width: 370px;
}
input.span6, textarea.span6, .uneditable-input.span6 {
  width: 450px;
}
input.span7, textarea.span7, .uneditable-input.span7 {
  width: 530px;
}
input.span8, textarea.span8, .uneditable-input.span8 {
  width: 610px;
}
input.span9, textarea.span9, .uneditable-input.span9 {
  width: 690px;
}
input.span10, textarea.span10, .uneditable-input.span10 {
  width: 770px;
}
input.span11, textarea.span11, .uneditable-input.span11 {
  width: 850px;
}
input.span12, textarea.span12, .uneditable-input.span12 {
  width: 930px;
}
input[disabled],
select[disabled],
textarea[disabled],
input[readonly],
select[readonly],
textarea[readonly] {
  background-color: #f5f5f5;
  border-color: #ddd;
  cursor: not-allowed;
}
.control-group.warning > label, .control-group.warning .help-block, .control-group.warning .help-inline {
  color: #c09853;
}
.control-group.warning input, .control-group.warning select, .control-group.warning textarea {
  color: #c09853;
  border-color: #c09853;
}
.control-group.warning input:focus, .control-group.warning select:focus, .control-group.warning textarea:focus {
  border-color: #a47e3c;
  -webkit-box-shadow: 0 0 6px #dbc59e;
  -moz-box-shadow: 0 0 6px #dbc59e;
  box-shadow: 0 0 6px #dbc59e;
}
.control-group.warning .input-prepend .add-on, .control-group.warning .input-append .add-on {
  color: #c09853;
  background-color: #fcf8e3;
  border-color: #c09853;
}
.control-group.error > label, .control-group.error .help-block, .control-group.error .help-inline {
  color: #b94a48;
}
.control-group.error input, .control-group.error select, .control-group.error textarea {
  color: #b94a48;
  border-color: #b94a48;
}
.control-group.error input:focus, .control-group.error select:focus, .control-group.error textarea:focus {
  border-color: #953b39;
  -webkit-box-shadow: 0 0 6px #d59392;
  -moz-box-shadow: 0 0 6px #d59392;
  box-shadow: 0 0 6px #d59392;
}
.control-group.error .input-prepend .add-on, .control-group.error .input-append .add-on {
  color: #b94a48;
  background-color: #f2dede;
  border-color: #b94a48;
}
.control-group.success > label, .control-group.success .help-block, .control-group.success .help-inline {
  color: #468847;
}
.control-group.success input, .control-group.success select, .control-group.success textarea {
  color: #468847;
  border-color: #468847;
}
.control-group.success input:focus, .control-group.success select:focus, .control-group.success textarea:focus {
  border-color: #356635;
  -webkit-box-shadow: 0 0 6px #7aba7b;
  -moz-box-shadow: 0 0 6px #7aba7b;
  box-shadow: 0 0 6px #7aba7b;
}
.control-group.success .input-prepend .add-on, .control-group.success .input-append .add-on {
  color: #468847;
  background-color: #dff0d8;
  border-color: #468847;
}
input:focus:required:invalid, textarea:focus:required:invalid, select:focus:required:invalid {
  color: #b94a48;
  border-color: #ee5f5b;
}
input:focus:required:invalid:focus, textarea:focus:required:invalid:focus, select:focus:required:invalid:focus {
  border-color: #e9322d;
  -webkit-box-shadow: 0 0 6px #f8b9b7;
  -moz-box-shadow: 0 0 6px #f8b9b7;
  box-shadow: 0 0 6px #f8b9b7;
}
.form-actions {
  padding: 17px 20px 18px;
  margin-top: 18px;
  margin-bottom: 18px;
  background-color: #f5f5f5;
  border-top: 1px solid #ddd;
}
.uneditable-input {
  display: block;
  background-color: #ffffff;
  border-color: #eee;
  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
  -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
  cursor: not-allowed;
}
:-moz-placeholder {
  color: #999999;
}
::-webkit-input-placeholder {
  color: #999999;
}
.help-block {
  margin-top: 5px;
  margin-bottom: 0;
  color: #999999;
}
.help-inline {
  display: inline-block;
  *display: inline;
  /* IE7 inline-block hack */

  *zoom: 1;
  margin-bottom: 9px;
  vertical-align: middle;
  padding-left: 5px;
}
.input-prepend, .input-append {
  margin-bottom: 5px;
  *zoom: 1;
}
.input-prepend:before,
.input-append:before,
.input-prepend:after,
.input-append:after {
  display: table;
  content: "";
}
.input-prepend:after, .input-append:after {
  clear: both;
}
.input-prepend input,
.input-append input,
.input-prepend .uneditable-input,
.input-append .uneditable-input {
  -webkit-border-radius: 0 3px 3px 0;
  -moz-border-radius: 0 3px 3px 0;
  border-radius: 0 3px 3px 0;
}
.input-prepend input:focus,
.input-append input:focus,
.input-prepend .uneditable-input:focus,
.input-append .uneditable-input:focus {
  position: relative;
  z-index: 2;
}
.input-prepend .uneditable-input, .input-append .uneditable-input {
  border-left-color: #ccc;
}
.input-prepend .add-on, .input-append .add-on {
  float: left;
  display: block;
  width: auto;
  min-width: 16px;
  height: 18px;
  margin-right: -1px;
  padding: 4px 5px;
  font-weight: normal;
  line-height: 18px;
  color: #999999;
  text-align: center;
  text-shadow: 0 1px 0 #ffffff;
  background-color: #f5f5f5;
  border: 1px solid #ccc;
  -webkit-border-radius: 3px 0 0 3px;
  -moz-border-radius: 3px 0 0 3px;
  border-radius: 3px 0 0 3px;
}
.input-prepend .active, .input-append .active {
  background-color: #a9dba9;
  border-color: #46a546;
}
.input-prepend .add-on {
  *margin-top: 1px;
  /* IE6-7 */

}
.input-append input, .input-append .uneditable-input {
  float: left;
  -webkit-border-radius: 3px 0 0 3px;
  -moz-border-radius: 3px 0 0 3px;
  border-radius: 3px 0 0 3px;
}
.input-append .uneditable-input {
  border-right-color: #ccc;
}
.input-append .add-on {
  margin-right: 0;
  margin-left: -1px;
  -webkit-border-radius: 0 3px 3px 0;
  -moz-border-radius: 0 3px 3px 0;
  border-radius: 0 3px 3px 0;
}
.input-append input:first-child {
  *margin-left: -160px;
}
.input-append input:first-child + .add-on {
  *margin-left: -21px;
}
.search-query {
  padding-left: 14px;
  padding-right: 14px;
  margin-bottom: 0;
  -webkit-border-radius: 14px;
  -moz-border-radius: 14px;
  border-radius: 14px;
}
.form-search input,
.form-inline input,
.form-horizontal input,
.form-search textarea,
.form-inline textarea,
.form-horizontal textarea,
.form-search select,
.form-inline select,
.form-horizontal select,
.form-search .help-inline,
.form-inline .help-inline,
.form-horizontal .help-inline,
.form-search .uneditable-input,
.form-inline .uneditable-input,
.form-horizontal .uneditable-input {
  display: inline-block;
  margin-bottom: 0;
}
.form-search label,
.form-inline label,
.form-search .input-append,
.form-inline .input-append,
.form-search .input-prepend,
.form-inline .input-prepend {
  display: inline-block;
}
.form-search .input-append .add-on,
.form-inline .input-prepend .add-on,
.form-search .input-append .add-on,
.form-inline .input-prepend .add-on {
  vertical-align: middle;
}
.control-group {
  margin-bottom: 9px;
}
.form-horizontal legend + .control-group {
  margin-top: 18px;
  -webkit-margin-top-collapse: separate;
}
.form-horizontal .control-group {
  margin-bottom: 18px;
  *zoom: 1;
}
.form-horizontal .control-group:before, .form-horizontal .control-group:after {
  display: table;
  content: "";
}
.form-horizontal .control-group:after {
  clear: both;
}
.form-horizontal .control-group > label {
  float: left;
  width: 140px;
  padding-top: 5px;
  text-align: right;
}
.form-horizontal .controls {
  margin-left: 160px;
}
.form-horizontal .form-actions {
  padding-left: 160px;
}
table {
  max-width: 100%;
  border-collapse: collapse;
  border-spacing: 0;
}
.table {
  width: 100%;
  margin-bottom: 18px;
}
.table th, .table td {
  padding: 8px;
  line-height: 18px;
  text-align: left;
  border-top: 1px solid #ddd;
}
.table th {
  font-weight: bold;
  vertical-align: bottom;
}
.table td {
  vertical-align: top;
}
.table thead:first-child tr th, .table thead:first-child tr td {
  border-top: 0;
}
.table tbody + tbody {
  border-top: 2px solid #ddd;
}
.table-condensed th, .table-condensed td {
  padding: 4px 5px;
}
.table-bordered {
  border: 1px solid #ddd;
  border-collapse: separate;
  *border-collapse: collapsed;
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  border-radius: 4px;
}
.table-bordered th + th,
.table-bordered td + td,
.table-bordered th + td,
.table-bordered td + th {
  border-left: 1px solid #ddd;
}
.table-bordered thead:first-child tr:first-child th, .table-bordered tbody:first-child tr:first-child th, .table-bordered tbody:first-child tr:first-child td {
  border-top: 0;
}
.table-bordered thead:first-child tr:first-child th:first-child, .table-bordered tbody:first-child tr:first-child td:first-child {
  -webkit-border-radius: 4px 0 0 0;
  -moz-border-radius: 4px 0 0 0;
  border-radius: 4px 0 0 0;
}
.table-bordered thead:first-child tr:first-child th:last-child, .table-bordered tbody:first-child tr:first-child td:last-child {
  -webkit-border-radius: 0 4px 0 0;
  -moz-border-radius: 0 4px 0 0;
  border-radius: 0 4px 0 0;
}
.table-bordered thead:last-child tr:last-child th:first-child, .table-bordered tbody:last-child tr:last-child td:first-child {
  -webkit-border-radius: 0 0 0 4px;
  -moz-border-radius: 0 0 0 4px;
  border-radius: 0 0 0 4px;
}
.table-bordered thead:last-child tr:last-child th:last-child, .table-bordered tbody:last-child tr:last-child td:last-child {
  -webkit-border-radius: 0 0 4px 0;
  -moz-border-radius: 0 0 4px 0;
  border-radius: 0 0 4px 0;
}
.table-striped tbody tr:nth-child(odd) td, .table-striped tbody tr:nth-child(odd) th {
  background-color: #f9f9f9;
}
table .span1 {
  float: none;
  width: 44px;
  margin-left: 0;
}
table .span2 {
  float: none;
  width: 124px;
  margin-left: 0;
}
table .span3 {
  float: none;
  width: 204px;
  margin-left: 0;
}
table .span4 {
  float: none;
  width: 284px;
  margin-left: 0;
}
table .span5 {
  float: none;
  width: 364px;
  margin-left: 0;
}
table .span6 {
  float: none;
  width: 444px;
  margin-left: 0;
}
table .span7 {
  float: none;
  width: 524px;
  margin-left: 0;
}
table .span8 {
  float: none;
  width: 604px;
  margin-left: 0;
}
table .span9 {
  float: none;
  width: 684px;
  margin-left: 0;
}
table .span10 {
  float: none;
  width: 764px;
  margin-left: 0;
}
table .span11 {
  float: none;
  width: 844px;
  margin-left: 0;
}
table .span12 {
  float: none;
  width: 924px;
  margin-left: 0;
}
[class^="icon-"] {
  display: inline-block;
  width: 14px;
  height: 14px;
  vertical-align: text-top;
  background-image: url(../img/glyphicons-halflings.png);
  background-position: 14px 14px;
  background-repeat: no-repeat;
  *margin-right: .3em;
}
[class^="icon-"]:last-child {
  *margin-left: 0;
}
.icon-white {
  background-image: url(../img/glyphicons-halflings-white.png);
}
.icon-glass {
  background-position: 0      0;
}
.icon-music {
  background-position: -24px 0;
}
.icon-search {
  background-position: -48px 0;
}
.icon-envelope {
  background-position: -72px 0;
}
.icon-heart {
  background-position: -96px 0;
}
.icon-star {
  background-position: -120px 0;
}
.icon-star-empty {
  background-position: -144px 0;
}
.icon-user {
  background-position: -168px 0;
}
.icon-film {
  background-position: -192px 0;
}
.icon-th-large {
  background-position: -216px 0;
}
.icon-th {
  background-position: -240px 0;
}
.icon-th-list {
  background-position: -264px 0;
}
.icon-ok {
  background-position: -288px 0;
}
.icon-remove {
  background-position: -312px 0;
}
.icon-zoom-in {
  background-position: -336px 0;
}
.icon-zoom-out {
  background-position: -360px 0;
}
.icon-off {
  background-position: -384px 0;
}
.icon-signal {
  background-position: -408px 0;
}
.icon-cog {
  background-position: -432px 0;
}
.icon-trash {
  background-position: -456px 0;
}
.icon-home {
  background-position: 0 -24px;
}
.icon-file {
  background-position: -24px -24px;
}
.icon-time {
  background-position: -48px -24px;
}
.icon-road {
  background-position: -72px -24px;
}
.icon-download-alt {
  background-position: -96px -24px;
}
.icon-download {
  background-position: -120px -24px;
}
.icon-upload {
  background-position: -144px -24px;
}
.icon-inbox {
  background-position: -168px -24px;
}
.icon-play-circle {
  background-position: -192px -24px;
}
.icon-repeat {
  background-position: -216px -24px;
}
.icon-refresh {
  background-position: -240px -24px;
}
.icon-list-alt {
  background-position: -264px -24px;
}
.icon-lock {
  background-position: -287px -24px;
}
.icon-flag {
  background-position: -312px -24px;
}
.icon-headphones {
  background-position: -336px -24px;
}
.icon-volume-off {
  background-position: -360px -24px;
}
.icon-volume-down {
  background-position: -384px -24px;
}
.icon-volume-up {
  background-position: -408px -24px;
}
.icon-qrcode {
  background-position: -432px -24px;
}
.icon-barcode {
  background-position: -456px -24px;
}
.icon-tag {
  background-position: 0 -48px;
}
.icon-tags {
  background-position: -25px -48px;
}
.icon-book {
  background-position: -48px -48px;
}
.icon-bookmark {
  background-position: -72px -48px;
}
.icon-print {
  background-position: -96px -48px;
}
.icon-camera {
  background-position: -120px -48px;
}
.icon-font {
  background-position: -144px -48px;
}
.icon-bold {
  background-position: -167px -48px;
}
.icon-italic {
  background-position: -192px -48px;
}
.icon-text-height {
  background-position: -216px -48px;
}
.icon-text-width {
  background-position: -240px -48px;
}
.icon-align-left {
  background-position: -264px -48px;
}
.icon-align-center {
  background-position: -288px -48px;
}
.icon-align-right {
  background-position: -312px -48px;
}
.icon-align-justify {
  background-position: -336px -48px;
}
.icon-list {
  background-position: -360px -48px;
}
.icon-indent-left {
  background-position: -384px -48px;
}
.icon-indent-right {
  background-position: -408px -48px;
}
.icon-facetime-video {
  background-position: -432px -48px;
}
.icon-picture {
  background-position: -456px -48px;
}
.icon-pencil {
  background-position: 0 -72px;
}
.icon-map-marker {
  background-position: -24px -72px;
}
.icon-adjust {
  background-position: -48px -72px;
}
.icon-tint {
  background-position: -72px -72px;
}
.icon-edit {
  background-position: -96px -72px;
}
.icon-share {
  background-position: -120px -72px;
}
.icon-check {
  background-position: -144px -72px;
}
.icon-move {
  background-position: -168px -72px;
}
.icon-step-backward {
  background-position: -192px -72px;
}
.icon-fast-backward {
  background-position: -216px -72px;
}
.icon-backward {
  background-position: -240px -72px;
}
.icon-play {
  background-position: -264px -72px;
}
.icon-pause {
  background-position: -288px -72px;
}
.icon-stop {
  background-position: -312px -72px;
}
.icon-forward {
  background-position: -336px -72px;
}
.icon-fast-forward {
  background-position: -360px -72px;
}
.icon-step-forward {
  background-position: -384px -72px;
}
.icon-eject {
  background-position: -408px -72px;
}
.icon-chevron-left {
  background-position: -432px -72px;
}
.icon-chevron-right {
  background-position: -456px -72px;
}
.icon-plus-sign {
  background-position: 0 -96px;
}
.icon-minus-sign {
  background-position: -24px -96px;
}
.icon-remove-sign {
  background-position: -48px -96px;
}
.icon-ok-sign {
  background-position: -72px -96px;
}
.icon-question-sign {
  background-position: -96px -96px;
}
.icon-info-sign {
  background-position: -120px -96px;
}
.icon-screenshot {
  background-position: -144px -96px;
}
.icon-remove-circle {
  background-position: -168px -96px;
}
.icon-ok-circle {
  background-position: -192px -96px;
}
.icon-ban-circle {
  background-position: -216px -96px;
}
.icon-arrow-left {
  background-position: -240px -96px;
}
.icon-arrow-right {
  background-position: -264px -96px;
}
.icon-arrow-up {
  background-position: -289px -96px;
}
.icon-arrow-down {
  background-position: -312px -96px;
}
.icon-share-alt {
  background-position: -336px -96px;
}
.icon-resize-full {
  background-position: -360px -96px;
}
.icon-resize-small {
  background-position: -384px -96px;
}
.icon-plus {
  background-position: -408px -96px;
}
.icon-minus {
  background-position: -433px -96px;
}
.icon-asterisk {
  background-position: -456px -96px;
}
.icon-exclamation-sign {
  background-position: 0 -120px;
}
.icon-gift {
  background-position: -24px -120px;
}
.icon-leaf {
  background-position: -48px -120px;
}
.icon-fire {
  background-position: -72px -120px;
}
.icon-eye-open {
  background-position: -96px -120px;
}
.icon-eye-close {
  background-position: -120px -120px;
}
.icon-warning-sign {
  background-position: -144px -120px;
}
.icon-plane {
  background-position: -168px -120px;
}
.icon-calendar {
  background-position: -192px -120px;
}
.icon-random {
  background-position: -216px -120px;
}
.icon-comment {
  background-position: -240px -120px;
}
.icon-magnet {
  background-position: -264px -120px;
}
.icon-chevron-up {
  background-position: -288px -120px;
}
.icon-chevron-down {
  background-position: -313px -119px;
}
.icon-retweet {
  background-position: -336px -120px;
}
.icon-shopping-cart {
  background-position: -360px -120px;
}
.icon-folder-close {
  background-position: -384px -120px;
}
.icon-folder-open {
  background-position: -408px -120px;
}
.icon-resize-vertical {
  background-position: -432px -119px;
}
.icon-resize-horizontal {
  background-position: -456px -118px;
}
.dropdown {
  position: relative;
}
.dropdown-toggle {
  *margin-bottom: -3px;
}
.dropdown-toggle:active, .open .dropdown-toggle {
  outline: 0;
}
.caret {
  display: inline-block;
  width: 0;
  height: 0;
  text-indent: -99999px;
  *text-indent: 0;
  vertical-align: top;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 4px solid #000000;
  opacity: 0.3;
  filter: alpha(opacity=30);
  content: "\2193";
}
.dropdown .caret {
  margin-top: 8px;
  margin-left: 2px;
}
.dropdown:hover .caret, .open.dropdown .caret {
  opacity: 1;
  filter: alpha(opacity=100);
}
.dropdown-menu {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 1000;
  float: left;
  display: none;
  min-width: 160px;
  max-width: 220px;
  _width: 160px;
  padding: 4px 0;
  margin: 0;
  list-style: none;
  background-color: #ffffff;
  border-color: #ccc;
  border-color: rgba(0, 0, 0, 0.2);
  border-style: solid;
  border-width: 1px;
  -webkit-border-radius: 0 0 5px 5px;
  -moz-border-radius: 0 0 5px 5px;
  border-radius: 0 0 5px 5px;
  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
  -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
  box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
  -webkit-background-clip: padding-box;
  -moz-background-clip: padding;
  background-clip: padding-box;
  *border-right-width: 2px;
  *border-bottom-width: 2px;
}
.dropdown-menu.bottom-up {
  top: auto;
  bottom: 100%;
  margin-bottom: 2px;
}
.dropdown-menu .divider {
  height: 1px;
  margin: 5px 1px;
  overflow: hidden;
  background-color: #e5e5e5;
  border-bottom: 1px solid #ffffff;
  *width: 100%;
  *margin: -5px 0 5px;
}
.dropdown-menu a {
  display: block;
  padding: 3px 15px;
  clear: both;
  font-weight: normal;
  line-height: 18px;
  color: #555555;
  white-space: nowrap;
}
.dropdown-menu li > a:hover, .dropdown-menu .active > a, .dropdown-menu .active > a:hover {
  color: #ffffff;
  text-decoration: none;
  background-color: #0088cc;
}
.dropdown.open {
  *z-index: 1000;
}
.dropdown.open .dropdown-toggle {
  color: #ffffff;
  background: #ccc;
  background: rgba(0, 0, 0, 0.3);
}
.dropdown.open .dropdown-menu {
  display: block;
}
.typeahead {
  margin-top: 2px;
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  border-radius: 4px;
}
.well {
  min-height: 20px;
  padding: 19px;
  margin-bottom: 20px;
  background-color: #f5f5f5;
  border: 1px solid #eee;
  border: 1px solid rgba(0, 0, 0, 0.05);
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  border-radius: 4px;
  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
  -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
}
.well blockquote {
  border-color: #ddd;
  border-color: rgba(0, 0, 0, 0.15);
}
.fade {
  -webkit-transition: opacity 0.15s linear;
  -moz-transition: opacity 0.15s linear;
  -ms-transition: opacity 0.15s linear;
  -o-transition: opacity 0.15s linear;
  transition: opacity 0.15s linear;
  opacity: 0;
}
.fade.in {
  opacity: 1;
}
.collapse {
  -webkit-transition: height 0.35s ease;
  -moz-transition: height 0.35s ease;
  -ms-transition: height 0.35s ease;
  -o-transition: height 0.35s ease;
  transition: height 0.35s ease;
  position: relative;
  overflow: hidden;
  height: 0;
}
.collapse.in {
  height: auto;
}
.close {
  float: right;
  font-size: 20px;
  font-weight: bold;
  line-height: 18px;
  color: #000000;
  text-shadow: 0 1px 0 #ffffff;
  opacity: 0.2;
  filter: alpha(opacity=20);
}
.close:hover {
  color: #000000;
  text-decoration: none;
  opacity: 0.4;
  filter: alpha(opacity=40);
  cursor: pointer;
}
.btn {
  display: inline-block;
  padding: 4px 10px 4px;
  font-size: 13px;
  line-height: 18px;
  color: #333333;
  text-align: center;
  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
  background-color: #fafafa;
  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6));
  background-image: -webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
  background-image: -moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6);
  background-image: -ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
  background-image: -o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
  background-image: linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);
  background-repeat: no-repeat;
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0);
  border: 1px solid #ccc;
  border-bottom-color: #bbb;
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  border-radius: 4px;
  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
  -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
  cursor: pointer;
  *margin-left: .3em;
}
.btn:first-child {
  *margin-left: 0;
}
.btn:hover {
  color: #333333;
  text-decoration: none;
  background-color: #e6e6e6;
  background-position: 0 -15px;
  -webkit-transition: background-position 0.1s linear;
  -moz-transition: background-position 0.1s linear;
  -ms-transition: background-position 0.1s linear;
  -o-transition: background-position 0.1s linear;
  transition: background-position 0.1s linear;
}
.btn:focus {
  outline: thin dotted;
  outline: 5px auto -webkit-focus-ring-color;
  outline-offset: -2px;
}
.btn.active, .btn:active {
  background-image: none;
  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
  -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
  background-color: #e6e6e6;
  background-color: #d9d9d9 \9;
  color: rgba(0, 0, 0, 0.5);
  outline: 0;
}
.btn.disabled, .btn[disabled] {
  cursor: default;
  background-image: none;
  background-color: #e6e6e6;
  opacity: 0.65;
  filter: alpha(opacity=65);
  -webkit-box-shadow: none;
  -moz-box-shadow: none;
  box-shadow: none;
}
.btn-large {
  padding: 9px 14px;
  font-size: 15px;
  line-height: normal;
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  border-radius: 5px;
}
.btn-large .icon {
  margin-top: 1px;
}
.btn-small {
  padding: 5px 9px;
  font-size: 11px;
  line-height: 16px;
}
.btn-small .icon {
  margin-top: -1px;
}
.btn-primary,
.btn-primary:hover,
.btn-warning,
.btn-warning:hover,
.btn-danger,
.btn-danger:hover,
.btn-success,
.btn-success:hover,
.btn-info,
.btn-info:hover {
  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
  color: #ffffff;
}
.btn-primary.active,
.btn-warning.active,
.btn-danger.active,
.btn-success.active,
.btn-info.active {
  color: rgba(255, 255, 255, 0.75);
}
.btn-primary {
  background-color: #006dcc;
  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
  background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
  background-image: -o-linear-gradient(top, #0088cc, #0044cc);
  background-image: linear-gradient(top, #0088cc, #0044cc);
  background-repeat: repeat-x;
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
  border-color: #0044cc #0044cc #002a80;
  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
}
.btn-primary:hover,
.btn-primary:active,
.btn-primary.active,
.btn-primary.disabled,
.btn-primary[disabled] {
  background-color: #0044cc;
}
.btn-primary:active, .btn-primary.active {
  background-color: #003399 \9;
}
.btn-warning {
  background-color: #faa732;
  background-image: -moz-linear-gradient(top, #fbb450, #f89406);
  background-image: -ms-linear-gradient(top, #fbb450, #f89406);
  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));
  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);
  background-image: -o-linear-gradient(top, #fbb450, #f89406);
  background-image: linear-gradient(top, #fbb450, #f89406);
  background-repeat: repeat-x;
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fbb450', endColorstr='#f89406', GradientType=0);
  border-color: #f89406 #f89406 #ad6704;
  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
}
.btn-warning:hover,
.btn-warning:active,
.btn-warning.active,
.btn-warning.disabled,
.btn-warning[disabled] {
  background-color: #f89406;
}
.btn-warning:active, .btn-warning.active {
  background-color: #c67605 \9;
}
.btn-danger {
  background-color: #da4f49;
  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);
  background-image: -ms-linear-gradient(top, #ee5f5b, #bd362f);
  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));
  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);
  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);
  background-image: linear-gradient(top, #ee5f5b, #bd362f);
  background-repeat: repeat-x;
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#bd362f', GradientType=0);
  border-color: #bd362f #bd362f #802420;
  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
}
.btn-danger:hover,
.btn-danger:active,
.btn-danger.active,
.btn-danger.disabled,
.btn-danger[disabled] {
  background-color: #bd362f;
}
.btn-danger:active, .btn-danger.active {
  background-color: #942a25 \9;
}
.btn-success {
  background-color: #5bb75b;
  background-image: -moz-linear-gradient(top, #62c462, #51a351);
  background-image: -ms-linear-gradient(top, #62c462, #51a351);
  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));
  background-image: -webkit-linear-gradient(top, #62c462, #51a351);
  background-image: -o-linear-gradient(top, #62c462, #51a351);
  background-image: linear-gradient(top, #62c462, #51a351);
  background-repeat: repeat-x;
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#51a351', GradientType=0);
  border-color: #51a351 #51a351 #387038;
  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
}
.btn-success:hover,
.btn-success:active,
.btn-success.active,
.btn-success.disabled,
.btn-success[disabled] {
  background-color: #51a351;
}
.btn-success:active, .btn-success.active {
  background-color: #408140 \9;
}
.btn-info {
  background-color: #49afcd;
  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);
  background-image: -ms-linear-gradient(top, #5bc0de, #2f96b4);
  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));
  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);
  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);
  background-image: linear-gradient(top, #5bc0de, #2f96b4);
  background-repeat: repeat-x;
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#2f96b4', GradientType=0);
  border-color: #2f96b4 #2f96b4 #1f6377;
  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
}
.btn-info:hover,
.btn-info:active,
.btn-info.active,
.btn-info.disabled,
.btn-info[disabled] {
  background-color: #2f96b4;
}
.btn-info:active, .btn-info.active {
  background-color: #24748c \9;
}
button.btn, input[type="submit"].btn {
  *padding-top: 2px;
  *padding-bottom: 2px;
}
button.btn::-moz-focus-inner, input[type="submit"].btn::-moz-focus-inner {
  padding: 0;
  border: 0;
}
button.btn.large, input[type="submit"].btn.large {
  *padding-top: 7px;
  *padding-bottom: 7px;
}
button.btn.small, input[type="submit"].btn.small {
  *padding-top: 3px;
  *padding-bottom: 3px;
}
.btn-group {
  position: relative;
  *zoom: 1;
  *margin-left: .3em;
}
.btn-group:before, .btn-group:after {
  display: table;
  content: "";
}
.btn-group:after {
  clear: both;
}
.btn-group:first-child {
  *margin-left: 0;
}
.btn-group + .btn-group {
  margin-left: 5px;
}
.btn-toolbar {
  margin-top: 9px;
  margin-bottom: 9px;
}
.btn-toolbar .btn-group {
  display: inline-block;
  *display: inline;
  /* IE7 inline-block hack */

  *zoom: 1;
}
.btn-group .btn {
  position: relative;
  float: left;
  margin-left: -1px;
  -webkit-border-radius: 0;
  -moz-border-radius: 0;
  border-radius: 0;
}
.btn-group .btn:first-child {
  margin-left: 0;
  -webkit-border-top-left-radius: 4px;
  -moz-border-radius-topleft: 4px;
  border-top-left-radius: 4px;
  -webkit-border-bottom-left-radius: 4px;
  -moz-border-radius-bottomleft: 4px;
  border-bottom-left-radius: 4px;
}
.btn-group .btn:last-child, .btn-group .dropdown-toggle {
  -webkit-border-top-right-radius: 4px;
  -moz-border-radius-topright: 4px;
  border-top-right-radius: 4px;
  -webkit-border-bottom-right-radius: 4px;
  -moz-border-radius-bottomright: 4px;
  border-bottom-right-radius: 4px;
}
.btn-group .btn.large:first-child {
  margin-left: 0;
  -webkit-border-top-left-radius: 6px;
  -moz-border-radius-topleft: 6px;
  border-top-left-radius: 6px;
  -webkit-border-bottom-left-radius: 6px;
  -moz-border-radius-bottomleft: 6px;
  border-bottom-left-radius: 6px;
}
.btn-group .btn.large:last-child, .btn-group .large.dropdown-toggle {
  -webkit-border-top-right-radius: 6px;
  -moz-border-radius-topright: 6px;
  border-top-right-radius: 6px;
  -webkit-border-bottom-right-radius: 6px;
  -moz-border-radius-bottomright: 6px;
  border-bottom-right-radius: 6px;
}
.btn-group .btn:hover,
.btn-group .btn:focus,
.btn-group .btn:active,
.btn-group .btn.active {
  z-index: 2;
}
.btn-group .dropdown-toggle:active, .btn-group.open .dropdown-toggle {
  outline: 0;
}
.btn-group .dropdown-toggle {
  padding-left: 8px;
  padding-right: 8px;
  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
  -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
  box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
  *padding-top: 5px;
  *padding-bottom: 5px;
}
.btn-group.open {
  *z-index: 1000;
}
.btn-group.open .dropdown-menu {
  display: block;
  margin-top: 1px;
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  border-radius: 5px;
}
.btn-group.open .dropdown-toggle {
  background-image: none;
  -webkit-box-shadow: inset 0 1px 6px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
  -moz-box-shadow: inset 0 1px 6px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
  box-shadow: inset 0 1px 6px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
}
.btn .caret {
  margin-top: 7px;
  margin-left: 0;
}
.btn:hover .caret, .open.btn-group .caret {
  opacity: 1;
  filter: alpha(opacity=100);
}
.btn-primary .caret,
.btn-danger .caret,
.btn-info .caret,
.btn-success .caret {
  border-top-color: #ffffff;
  opacity: 0.75;
  filter: alpha(opacity=75);
}
.btn-small .caret {
  margin-top: 4px;
}
.alert {
  padding: 8px 35px 8px 14px;
  margin-bottom: 18px;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
  background-color: #fcf8e3;
  border: 1px solid #fbeed5;
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  border-radius: 4px;
}
.alert, .alert-heading {
  color: #c09853;
}
.alert .close {
  position: relative;
  top: -2px;
  right: -21px;
  line-height: 18px;
}
.alert-success {
  background-color: #dff0d8;
  border-color: #d6e9c6;
}
.alert-success, .alert-success .alert-heading {
  color: #468847;
}
.alert-danger, .alert-error {
  background-color: #f2dede;
  border-color: #eed3d7;
}
.alert-danger,
.alert-error,
.alert-danger .alert-heading,
.alert-error .alert-heading {
  color: #b94a48;
}
.alert-info {
  background-color: #d9edf7;
  border-color: #bce8f1;
}
.alert-info, .alert-info .alert-heading {
  color: #3a87ad;
}
.alert-block {
  padding-top: 14px;
  padding-bottom: 14px;
}
.alert-block > p, .alert-block > ul {
  margin-bottom: 0;
}
.alert-block p + p {
  margin-top: 5px;
}
.nav {
  margin-left: 0;
  margin-bottom: 18px;
  list-style: none;
}
.nav > li > a {
  display: block;
}
.nav > li > a:hover {
  text-decoration: none;
  background-color: #eeeeee;
}
.nav-list {
  padding-left: 14px;
  padding-right: 14px;
  margin-bottom: 0;
}
.nav-list > li > a, .nav-list .nav-header {
  display: block;
  padding: 3px 15px;
  margin-left: -15px;
  margin-right: -15px;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
}
.nav-list .nav-header {
  font-size: 11px;
  font-weight: bold;
  line-height: 18px;
  color: #999999;
  text-transform: uppercase;
}

.nav-list .nav-header * {
    text-transform:none;
}

.nav-list > li + .nav-header {
  margin-top: 9px;
}
.nav-list .active > a, .nav-list .active > a:hover {
  color: #ffffff;
  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);
  background-color: #0088cc;
}
.nav-list [class^="icon-"] {
  margin-right: 2px;
}
.nav-tabs, .nav-pills {
  *zoom: 1;
}
.nav-tabs:before,
.nav-pills:before,
.nav-tabs:after,
.nav-pills:after {
  display: table;
  content: "";
}
.nav-tabs:after, .nav-pills:after {
  clear: both;
}
.nav-tabs > li, .nav-pills > li {
  float: left;
}
.nav-tabs > li > a, .nav-pills > li > a {
  padding-right: 12px;
  padding-left: 12px;
  margin-right: 2px;
  line-height: 14px;
}
.nav-tabs {
  border-bottom: 1px solid #ddd;
}
.nav-tabs > li {
  margin-bottom: -1px;
}
.nav-tabs > li > a {
  padding-top: 9px;
  padding-bottom: 9px;
  border: 1px solid transparent;
  -webkit-border-radius: 4px 4px 0 0;
  -moz-border-radius: 4px 4px 0 0;
  border-radius: 4px 4px 0 0;
}
.nav-tabs > li > a:hover {
  border-color: #eeeeee #eeeeee #dddddd;
}
.nav-tabs > .active > a, .nav-tabs > .active > a:hover {
  color: #555555;
  background-color: #ffffff;
  border: 1px solid #ddd;
  border-bottom-color: transparent;
  cursor: default;
}
.nav-pills > li > a {
  padding-top: 8px;
  padding-bottom: 8px;
  margin-top: 2px;
  margin-bottom: 2px;
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  border-radius: 5px;
}
.nav-pills .active > a, .nav-pills .active > a:hover {
  color: #ffffff;
  background-color: #0088cc;
}
.nav-stacked > li {
  float: none;
}
.nav-stacked > li > a {
  margin-right: 0;
}
.nav-tabs.nav-stacked {
  border-bottom: 0;
}
.nav-tabs.nav-stacked > li > a {
  border: 1px solid #ddd;
  -webkit-border-radius: 0;
  -moz-border-radius: 0;
  border-radius: 0;
}
.nav-tabs.nav-stacked > li:first-child > a {
  -webkit-border-radius: 4px 4px 0 0;
  -moz-border-radius: 4px 4px 0 0;
  border-radius: 4px 4px 0 0;
}
.nav-tabs.nav-stacked > li:last-child > a {
  -webkit-border-radius: 0 0 4px 4px;
  -moz-border-radius: 0 0 4px 4px;
  border-radius: 0 0 4px 4px;
}
.nav-tabs.nav-stacked > li > a:hover {
  border-color: #ddd;
  z-index: 2;
}
.nav-pills.nav-stacked > li > a {
  margin-bottom: 3px;
}
.nav-pills.nav-stacked > li:last-child > a {
  margin-bottom: 1px;
}
.nav-tabs .dropdown-menu, .nav-pills .dropdown-menu {
  margin-top: 1px;
  border-width: 1px;
}
.nav-pills .dropdown-menu {
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  border-radius: 4px;
}
.nav-tabs .dropdown-toggle .caret, .nav-pills .dropdown-toggle .caret {
  border-top-color: #0088cc;
  margin-top: 6px;
}
.nav-tabs .dropdown-toggle:hover .caret, .nav-pills .dropdown-toggle:hover .caret {
  border-top-color: #005580;
}
.nav-tabs .active .dropdown-toggle .caret, .nav-pills .active .dropdown-toggle .caret {
  border-top-color: #333333;
}
.nav > .dropdown.active > a:hover {
  color: #000000;
  cursor: pointer;
}
.nav-tabs .open .dropdown-toggle, .nav-pills .open .dropdown-toggle, .nav > .open.active > a:hover {
  color: #ffffff;
  background-color: #999999;
  border-color: #999999;
}
.nav .open .caret, .nav .open.active .caret, .nav .open a:hover .caret {
  border-top-color: #ffffff;
  opacity: 1;
  filter: alpha(opacity=100);
}
.tabs-stacked .open > a:hover {
  border-color: #999999;
}
.tabbable {
  *zoom: 1;
}
.tabbable:before, .tabbable:after {
  display: table;
  content: "";
}
.tabbable:after {
  clear: both;
}
.tabs-below .nav-tabs, .tabs-right .nav-tabs, .tabs-left .nav-tabs {
  border-bottom: 0;
}
.tab-content > .tab-pane, .pill-content > .pill-pane {
  display: none;
}
.tab-content > .active, .pill-content > .active {
  display: block;
}
.tabs-below .nav-tabs {
  border-top: 1px solid #ddd;
}
.tabs-below .nav-tabs > li {
  margin-top: -1px;
  margin-bottom: 0;
}
.tabs-below .nav-tabs > li > a {
  -webkit-border-radius: 0 0 4px 4px;
  -moz-border-radius: 0 0 4px 4px;
  border-radius: 0 0 4px 4px;
}
.tabs-below .nav-tabs > li > a:hover {
  border-bottom-color: transparent;
  border-top-color: #ddd;
}
.tabs-below .nav-tabs .active > a, .tabs-below .nav-tabs .active > a:hover {
  border-color: transparent #ddd #ddd #ddd;
}
.tabs-left .nav-tabs > li, .tabs-right .nav-tabs > li {
  float: none;
}
.tabs-left .nav-tabs > li > a, .tabs-right .nav-tabs > li > a {
  min-width: 74px;
  margin-right: 0;
  margin-bottom: 3px;
}
.tabs-left .nav-tabs {
  float: left;
  margin-right: 19px;
  border-right: 1px solid #ddd;
}
.tabs-left .nav-tabs > li > a {
  margin-right: -1px;
  -webkit-border-radius: 4px 0 0 4px;
  -moz-border-radius: 4px 0 0 4px;
  border-radius: 4px 0 0 4px;
}
.tabs-left .nav-tabs > li > a:hover {
  border-color: #eeeeee #dddddd #eeeeee #eeeeee;
}
.tabs-left .nav-tabs .active > a, .tabs-left .nav-tabs .active > a:hover {
  border-color: #ddd transparent #ddd #ddd;
  *border-right-color: #ffffff;
}
.tabs-right .nav-tabs {
  float: right;
  margin-left: 19px;
  border-left: 1px solid #ddd;
}
.tabs-right .nav-tabs > li > a {
  margin-left: -1px;
  -webkit-border-radius: 0 4px 4px 0;
  -moz-border-radius: 0 4px 4px 0;
  border-radius: 0 4px 4px 0;
}
.tabs-right .nav-tabs > li > a:hover {
  border-color: #eeeeee #eeeeee #eeeeee #dddddd;
}
.tabs-right .nav-tabs .active > a, .tabs-right .nav-tabs .active > a:hover {
  border-color: #ddd #ddd #ddd transparent;
  *border-left-color: #ffffff;
}
.navbar {
  overflow: visible;
  margin-bottom: 18px;
}
.navbar-inner {
  padding-left: 20px;
  padding-right: 20px;
  background-color: #2c2c2c;
  background-image: -moz-linear-gradient(top, #333333, #222222);
  background-image: -ms-linear-gradient(top, #333333, #222222);
  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222));
  background-image: -webkit-linear-gradient(top, #333333, #222222);
  background-image: -o-linear-gradient(top, #333333, #222222);
  background-image: linear-gradient(top, #333333, #222222);
  background-repeat: repeat-x;
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0);
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  border-radius: 4px;
  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1);
  -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1);
}
.btn-navbar {
  display: none;
  float: right;
  padding: 7px 10px;
  margin-left: 5px;
  margin-right: 5px;
  background-color: #2c2c2c;
  background-image: -moz-linear-gradient(top, #333333, #222222);
  background-image: -ms-linear-gradient(top, #333333, #222222);
  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222));
  background-image: -webkit-linear-gradient(top, #333333, #222222);
  background-image: -o-linear-gradient(top, #333333, #222222);
  background-image: linear-gradient(top, #333333, #222222);
  background-repeat: repeat-x;
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0);
  border-color: #222222 #222222 #000000;
  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);
  -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);
}
.btn-navbar:hover,
.btn-navbar:active,
.btn-navbar.active,
.btn-navbar.disabled,
.btn-navbar[disabled] {
  background-color: #222222;
}
.btn-navbar:active, .btn-navbar.active {
  background-color: #080808 \9;
}
.btn-navbar .icon-bar {
  display: block;
  width: 18px;
  height: 2px;
  background-color: #f5f5f5;
  -webkit-border-radius: 1px;
  -moz-border-radius: 1px;
  border-radius: 1px;
  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
  -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
}
.btn-navbar .icon-bar + .icon-bar {
  margin-top: 3px;
}
.nav-collapse.collapse {
  height: auto;
}
.navbar .brand:hover {
  text-decoration: none;
}
.navbar .brand {
  float: left;
  display: block;
  padding: 8px 20px 12px;
  margin-left: -20px;
  font-size: 20px;
  font-weight: 200;
  line-height: 1;
  color: #ffffff;
}
.navbar .navbar-text {
  margin-bottom: 0;
  line-height: 40px;
  color: #999999;
}
.navbar .navbar-text a:hover {
  color: #ffffff;
  background-color: transparent;
}
.navbar .btn, .navbar .btn-group {
  margin-top: 5px;
}
.navbar .btn-group .btn {
  margin-top: 0;
}
.navbar-form {
  margin-bottom: 0;
  *zoom: 1;
}
.navbar-form:before, .navbar-form:after {
  display: table;
  content: "";
}
.navbar-form:after {
  clear: both;
}
.navbar-form input, .navbar-form select {
  display: inline-block;
  margin-top: 5px;
  margin-bottom: 0;
}
.navbar-form .radio, .navbar-form .checkbox {
  margin-top: 5px;
}
.navbar-form input[type="image"], .navbar-form input[type="checkbox"], .navbar-form input[type="radio"] {
  margin-top: 3px;
}
.navbar-search {
  position: relative;
  float: left;
  margin-top: 6px;
  margin-bottom: 0;
}
.navbar-search .search-query {
  padding: 4px 9px;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 13px;
  font-weight: normal;
  line-height: 1;
  color: #ffffff;
  color: rgba(255, 255, 255, 0.75);
  background: #666;
  background: rgba(255, 255, 255, 0.3);
  border: 1px solid #111;
  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.15);
  -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.15);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.15);
  -webkit-transition: none;
  -moz-transition: none;
  -ms-transition: none;
  -o-transition: none;
  transition: none;
}
.navbar-search .search-query :-moz-placeholder {
  color: #eeeeee;
}
.navbar-search .search-query::-webkit-input-placeholder {
  color: #eeeeee;
}
.navbar-search .search-query:hover {
  color: #ffffff;
  background-color: #999999;
  background-color: rgba(255, 255, 255, 0.5);
}
.navbar-search .search-query:focus, .navbar-search .search-query.focused {
  padding: 5px 10px;
  color: #333333;
  text-shadow: 0 1px 0 #ffffff;
  background-color: #ffffff;
  border: 0;
  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
  -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
  box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
  outline: 0;
}
.navbar-fixed-top {
  position: fixed;
  top: 0;
  right: 0;
  left: 0;
  z-index: 1030;
}
.navbar-fixed-top .navbar-inner {
  padding-left: 0;
  padding-right: 0;
  -webkit-border-radius: 0;
  -moz-border-radius: 0;
  border-radius: 0;
}
.navbar .nav {
  position: relative;
  left: 0;
  display: block;
  float: left;
  margin: 0 10px 0 0;
}
.navbar .nav.pull-right {
  float: right;
}
.navbar .nav > li {
  display: block;
  float: left;
}
.navbar .nav > li > a {
  float: none;
  padding: 10px 10px 11px;
  line-height: 19px;
  color: #999999;
  text-decoration: none;
  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
}
.navbar .nav > li > a:hover {
  background-color: transparent;
  color: #ffffff;
  text-decoration: none;
}
.navbar .nav .active > a, .navbar .nav .active > a:hover {
  color: #ffffff;
  text-decoration: none;
  background-color: #222222;
  background-color: rgba(0, 0, 0, 0.5);
}
.navbar .divider-vertical {
  height: 40px;
  width: 1px;
  margin: 0 9px;
  overflow: hidden;
  background-color: #222222;
  border-right: 1px solid #333333;
}
.navbar .nav.pull-right {
  margin-left: 10px;
  margin-right: 0;
}
.navbar .dropdown-menu {
  margin-top: 1px;
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  border-radius: 4px;
}
.navbar .dropdown-menu:before {
  content: '';
  display: inline-block;
  border-left: 7px solid transparent;
  border-right: 7px solid transparent;
  border-bottom: 7px solid #ccc;
  border-bottom-color: rgba(0, 0, 0, 0.2);
  position: absolute;
  top: -7px;
  left: 9px;
}
.navbar .dropdown-menu:after {
  content: '';
  display: inline-block;
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-bottom: 6px solid #ffffff;
  position: absolute;
  top: -6px;
  left: 10px;
}
.navbar .nav .dropdown-toggle .caret, .navbar .nav .open.dropdown .caret {
  border-top-color: #ffffff;
}
.navbar .nav .active .caret {
  opacity: 1;
  filter: alpha(opacity=100);
}
.navbar .nav .open > .dropdown-toggle, .navbar .nav .active > .dropdown-toggle, .navbar .nav .open.active > .dropdown-toggle {
  background-color: transparent;
}
.navbar .nav .active > .dropdown-toggle:hover {
  color: #ffffff;
}
.navbar .nav.pull-right .dropdown-menu {
  left: auto;
  right: 0;
}
.navbar .nav.pull-right .dropdown-menu:before {
  left: auto;
  right: 12px;
}
.navbar .nav.pull-right .dropdown-menu:after {
  left: auto;
  right: 13px;
}
.breadcrumb {
  padding: 7px 14px;
  margin: 0 0 18px;
  background-color: #fbfbfb;
  background-image: -moz-linear-gradient(top, #ffffff, #f5f5f5);
  background-image: -ms-linear-gradient(top, #ffffff, #f5f5f5);
  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f5f5f5));
  background-image: -webkit-linear-gradient(top, #ffffff, #f5f5f5);
  background-image: -o-linear-gradient(top, #ffffff, #f5f5f5);
  background-image: linear-gradient(top, #ffffff, #f5f5f5);
  background-repeat: repeat-x;
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0);
  border: 1px solid #ddd;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  border-radius: 3px;
  -webkit-box-shadow: inset 0 1px 0 #ffffff;
  -moz-box-shadow: inset 0 1px 0 #ffffff;
  box-shadow: inset 0 1px 0 #ffffff;
}
.breadcrumb li {
  display: inline;
  text-shadow: 0 1px 0 #ffffff;
}
.breadcrumb .divider {
  padding: 0 5px;
  color: #999999;
}
.breadcrumb .active a {
  color: #333333;
}
.pagination {
  height: 36px;
  margin: 18px 0;
}
.pagination ul {
  display: inline-block;
  *display: inline;
  /* IE7 inline-block hack */

  *zoom: 1;
  margin-left: 0;
  margin-bottom: 0;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  border-radius: 3px;
  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
  -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}
.pagination li {
  display: inline;
}
.pagination a {
  float: left;
  padding: 0 14px;
  line-height: 34px;
  text-decoration: none;
  border: 1px solid #ddd;
  border-left-width: 0;
}
.pagination a:hover, .pagination .active a {
  background-color: #f5f5f5;
}
.pagination .active a {
  color: #999999;
  cursor: default;
}
.pagination .disabled a, .pagination .disabled a:hover {
  color: #999999;
  background-color: transparent;
  cursor: default;
}
.pagination li:first-child a {
  border-left-width: 1px;
  -webkit-border-radius: 3px 0 0 3px;
  -moz-border-radius: 3px 0 0 3px;
  border-radius: 3px 0 0 3px;
}
.pagination li:last-child a {
  -webkit-border-radius: 0 3px 3px 0;
  -moz-border-radius: 0 3px 3px 0;
  border-radius: 0 3px 3px 0;
}
.pagination-centered {
  text-align: center;
}
.pagination-right {
  text-align: right;
}
.pager {
  margin-left: 0;
  margin-bottom: 18px;
  list-style: none;
  text-align: center;
  *zoom: 1;
}
.pager:before, .pager:after {
  display: table;
  content: "";
}
.pager:after {
  clear: both;
}
.pager li {
  display: inline;
}
.pager a {
  display: inline-block;
  padding: 5px 14px;
  background-color: #fff;
  border: 1px solid #ddd;
  -webkit-border-radius: 15px;
  -moz-border-radius: 15px;
  border-radius: 15px;
}
.pager a:hover {
  text-decoration: none;
  background-color: #f5f5f5;
}
.pager .next a {
  float: right;
}
.pager .previous a {
  float: left;
}
.modal-open .dropdown-menu {
  z-index: 2050;
}
.modal-open .dropdown.open {
  *z-index: 2050;
}
.modal-open .popover {
  z-index: 2060;
}
.modal-open .tooltip {
  z-index: 2070;
}
.modal-backdrop {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1040;
  background-color: #000000;
}
.modal-backdrop.fade {
  opacity: 0;
}
.modal-backdrop, .modal-backdrop.fade.in {
  opacity: 0.8;
  filter: alpha(opacity=80);
}
.modal {
  position: fixed;
  top: 50%;
  left: 50%;
  z-index: 1050;
  max-height: 500px;
  overflow: auto;
  width: 560px;
  margin: -250px 0 0 -280px;
  background-color: #ffffff;
  border: 1px solid #999;
  border: 1px solid rgba(0, 0, 0, 0.3);
  *border: 1px solid #999;
  /* IE6-7 */

  -webkit-border-radius: 6px;
  -moz-border-radius: 6px;
  border-radius: 6px;
  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
  -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
  box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
  -webkit-background-clip: padding-box;
  -moz-background-clip: padding-box;
  background-clip: padding-box;
}
.modal.fade {
  -webkit-transition: opacity .3s linear, top .3s ease-out;
  -moz-transition: opacity .3s linear, top .3s ease-out;
  -ms-transition: opacity .3s linear, top .3s ease-out;
  -o-transition: opacity .3s linear, top .3s ease-out;
  transition: opacity .3s linear, top .3s ease-out;
  top: -25%;
}
.modal.fade.in {
  top: 50%;
}
.modal-header {
  padding: 9px 15px;
  border-bottom: 1px solid #eee;
}
.modal-header .close {
  margin-top: 2px;
}
.modal-body {
  padding: 15px;
}
.modal-footer {
  padding: 14px 15px 15px;
  margin-bottom: 0;
  background-color: #f5f5f5;
  border-top: 1px solid #ddd;
  -webkit-border-radius: 0 0 6px 6px;
  -moz-border-radius: 0 0 6px 6px;
  border-radius: 0 0 6px 6px;
  -webkit-box-shadow: inset 0 1px 0 #ffffff;
  -moz-box-shadow: inset 0 1px 0 #ffffff;
  box-shadow: inset 0 1px 0 #ffffff;
  *zoom: 1;
}
.modal-footer:before, .modal-footer:after {
  display: table;
  content: "";
}
.modal-footer:after {
  clear: both;
}
.modal-footer .btn {
  float: right;
  margin-left: 5px;
  margin-bottom: 0;
}
.tooltip {
  position: absolute;
  z-index: 1020;
  display: block;
  visibility: visible;
  padding: 5px;
  font-size: 11px;
  opacity: 0;
  filter: alpha(opacity=0);
}
.tooltip.in {
  opacity: 0.8;
  filter: alpha(opacity=80);
}
.tooltip.top {
  margin-top: -2px;
}
.tooltip.right {
  margin-left: 2px;
}
.tooltip.bottom {
  margin-top: 2px;
}
.tooltip.left {
  margin-left: -2px;
}
.tooltip.top .tooltip-arrow {
  bottom: 0;
  left: 50%;
  margin-left: -5px;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 5px solid #000000;
}
.tooltip.left .tooltip-arrow {
  top: 50%;
  right: 0;
  margin-top: -5px;
  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
  border-left: 5px solid #000000;
}
.tooltip.bottom .tooltip-arrow {
  top: 0;
  left: 50%;
  margin-left: -5px;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-bottom: 5px solid #000000;
}
.tooltip.right .tooltip-arrow {
  top: 50%;
  left: 0;
  margin-top: -5px;
  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
  border-right: 5px solid #000000;
}
.tooltip-inner {
  max-width: 200px;
  padding: 3px 8px;
  color: #ffffff;
  text-align: center;
  text-decoration: none;
  background-color: #000000;
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  border-radius: 4px;
}
.tooltip-arrow {
  position: absolute;
  width: 0;
  height: 0;
}
.popover {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1010;
  display: none;
  padding: 5px;
}
.popover.top {
  margin-top: -5px;
}
.popover.right {
  margin-left: 5px;
}
.popover.bottom {
  margin-top: 5px;
}
.popover.left {
  margin-left: -5px;
}
.popover.top .arrow {
  bottom: 0;
  left: 50%;
  margin-left: -5px;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 5px solid #000000;
}
.popover.right .arrow {
  top: 50%;
  left: 0;
  margin-top: -5px;
  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
  border-right: 5px solid #000000;
}
.popover.bottom .arrow {
  top: 0;
  left: 50%;
  margin-left: -5px;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-bottom: 5px solid #000000;
}
.popover.left .arrow {
  top: 50%;
  right: 0;
  margin-top: -5px;
  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
  border-left: 5px solid #000000;
}
.popover .arrow {
  position: absolute;
  width: 0;
  height: 0;
}
.popover-inner {
  padding: 3px;
  width: 280px;
  overflow: hidden;
  background: #000000;
  background: rgba(0, 0, 0, 0.8);
  -webkit-border-radius: 6px;
  -moz-border-radius: 6px;
  border-radius: 6px;
  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
  -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
  box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
}
.popover-title {
  padding: 9px 15px;
  line-height: 1;
  background-color: #f5f5f5;
  border-bottom: 1px solid #eee;
  -webkit-border-radius: 3px 3px 0 0;
  -moz-border-radius: 3px 3px 0 0;
  border-radius: 3px 3px 0 0;
}
.popover-content {
  padding: 14px;
  background-color: #ffffff;
  -webkit-border-radius: 0 0 3px 3px;
  -moz-border-radius: 0 0 3px 3px;
  border-radius: 0 0 3px 3px;
  -webkit-background-clip: padding-box;
  -moz-background-clip: padding-box;
  background-clip: padding-box;
}
.popover-content p, .popover-content ul, .popover-content ol {
  margin-bottom: 0;
}
.thumbnails {
  margin-left: -20px;
  list-style: none;
  *zoom: 1;
}
.thumbnails:before, .thumbnails:after {
  display: table;
  content: "";
}
.thumbnails:after {
  clear: both;
}
.thumbnails > li {
  float: left;
  margin: 0 0 18px 20px;
}
.thumbnail {
  display: block;
  padding: 4px;
  line-height: 1;
  border: 1px solid #ddd;
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  border-radius: 4px;
  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
  -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);
}
a.thumbnail:hover {
  border-color: #0088cc;
  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
  -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
  box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
}
.thumbnail > img {
  display: block;
  max-width: 100%;
  margin-left: auto;
  margin-right: auto;
}
.thumbnail .caption {
  padding: 9px;
}
.label {
  padding: 1px 3px 2px;
  font-size: 9.75px;
  font-weight: bold;
  color: #ffffff;
  text-transform: uppercase;
  background-color: #999999;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  border-radius: 3px;
}
.label-important {
  background-color: #b94a48;
}
.label-warning {
  background-color: #f89406;
}
.label-success {
  background-color: #468847;
}
.label-info {
  background-color: #3a87ad;
}
@-webkit-keyframes progress-bar-stripes {
  from {
    background-position: 0 0;
  }
  to {
    background-position: 40px 0;
  }
}
@-moz-keyframes progress-bar-stripes {
  from {
    background-position: 0 0;
  }
  to {
    background-position: 40px 0;
  }
}
@keyframes progress-bar-stripes {
  from {
    background-position: 0 0;
  }
  to {
    background-position: 40px 0;
  }
}
.progress {
  overflow: hidden;
  height: 18px;
  margin-bottom: 18px;
  background-color: #f7f7f7;
  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);
  background-image: -ms-linear-gradient(top, #f5f5f5, #f9f9f9);
  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));
  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);
  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);
  background-image: linear-gradient(top, #f5f5f5, #f9f9f9);
  background-repeat: repeat-x;
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f5f5f5', endColorstr='#f9f9f9', GradientType=0);
  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
  -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  border-radius: 4px;
}
.progress .bar {
  width: 0%;
  height: 18px;
  color: #ffffff;
  font-size: 12px;
  text-align: center;
  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
  background-color: #0e90d2;
  background-image: -moz-linear-gradient(top, #149bdf, #0480be);
  background-image: -ms-linear-gradient(top, #149bdf, #0480be);
  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));
  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);
  background-image: -o-linear-gradient(top, #149bdf, #0480be);
  background-image: linear-gradient(top, #149bdf, #0480be);
  background-repeat: repeat-x;
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#149bdf', endColorstr='#0480be', GradientType=0);
  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
  -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
  box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  -webkit-transition: width 0.6s ease;
  -moz-transition: width 0.6s ease;
  -ms-transition: width 0.6s ease;
  -o-transition: width 0.6s ease;
  transition: width 0.6s ease;
}
.progress-striped .bar {
  background-color: #62c462;
  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
  background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
  background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
  background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
  background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
  background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
  -webkit-background-size: 40px 40px;
  -moz-background-size: 40px 40px;
  -o-background-size: 40px 40px;
  background-size: 40px 40px;
}
.progress.active .bar {
  -webkit-animation: progress-bar-stripes 2s linear infinite;
  -moz-animation: progress-bar-stripes 2s linear infinite;
  animation: progress-bar-stripes 2s linear infinite;
}
.progress-danger .bar {
  background-color: #dd514c;
  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);
  background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35);
  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));
  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);
  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);
  background-image: linear-gradient(top, #ee5f5b, #c43c35);
  background-repeat: repeat-x;
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0);
}
.progress-danger.progress-striped .bar {
  background-color: #ee5f5b;
  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
  background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
  background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
  background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
  background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
  background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
}
.progress-success .bar {
  background-color: #5eb95e;
  background-image: -moz-linear-gradient(top, #62c462, #57a957);
  background-image: -ms-linear-gradient(top, #62c462, #57a957);
  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));
  background-image: -webkit-linear-gradient(top, #62c462, #57a957);
  background-image: -o-linear-gradient(top, #62c462, #57a957);
  background-image: linear-gradient(top, #62c462, #57a957);
  background-repeat: repeat-x;
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0);
}
.progress-success.progress-striped .bar {
  background-color: #62c462;
  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
  background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
  background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
  background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
  background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
  background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
}
.progress-info .bar {
  background-color: #4bb1cf;
  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);
  background-image: -ms-linear-gradient(top, #5bc0de, #339bb9);
  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));
  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);
  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);
  background-image: linear-gradient(top, #5bc0de, #339bb9);
  background-repeat: repeat-x;
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0);
}
.progress-info.progress-striped .bar {
  background-color: #5bc0de;
  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
  background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
  background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
  background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
  background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
  background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
}
.accordion {
  margin-bottom: 18px;
}
.accordion-group {
  margin-bottom: 2px;
  border: 1px solid #e5e5e5;
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  border-radius: 4px;
}
.accordion-heading {
  border-bottom: 0;
}
.accordion-heading .accordion-toggle {
  display: block;
  padding: 8px 15px;
}
.accordion-inner {
  padding: 9px 15px;
  border-top: 1px solid #e5e5e5;
}
.carousel {
  position: relative;
  margin-bottom: 18px;
  line-height: 1;
}
.carousel-inner {
  overflow: hidden;
  width: 100%;
  position: relative;
}
.carousel .item {
  display: none;
  position: relative;
  -webkit-transition: 0.6s ease-in-out left;
  -moz-transition: 0.6s ease-in-out left;
  -ms-transition: 0.6s ease-in-out left;
  -o-transition: 0.6s ease-in-out left;
  transition: 0.6s ease-in-out left;
}
.carousel .item > img {
  display: block;
  line-height: 1;
}
.carousel .active, .carousel .next, .carousel .prev {
  display: block;
}
.carousel .active {
  left: 0;
}
.carousel .next, .carousel .prev {
  position: absolute;
  top: 0;
  width: 100%;
}
.carousel .next {
  left: 100%;
}
.carousel .prev {
  left: -100%;
}
.carousel .next.left, .carousel .prev.right {
  left: 0;
}
.carousel .active.left {
  left: -100%;
}
.carousel .active.right {
  left: 100%;
}
.carousel-control {
  position: absolute;
  top: 40%;
  left: 15px;
  width: 40px;
  height: 40px;
  margin-top: -20px;
  font-size: 60px;
  font-weight: 100;
  line-height: 30px;
  color: #ffffff;
  text-align: center;
  background: #222222;
  border: 3px solid #ffffff;
  -webkit-border-radius: 23px;
  -moz-border-radius: 23px;
  border-radius: 23px;
  opacity: 0.5;
  filter: alpha(opacity=50);
}
.carousel-control.right {
  left: auto;
  right: 15px;
}
.carousel-control:hover {
  color: #ffffff;
  text-decoration: none;
  opacity: 0.9;
  filter: alpha(opacity=90);
}
.carousel-caption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 10px 15px 5px;
  background: #333333;
  background: rgba(0, 0, 0, 0.75);
}
.carousel-caption h4, .carousel-caption p {
  color: #ffffff;
}
.hero-unit {
  padding: 60px;
  margin-bottom: 30px;
  background-color: #f5f5f5;
  -webkit-border-radius: 6px;
  -moz-border-radius: 6px;
  border-radius: 6px;
}
.hero-unit h1 {
  margin-bottom: 0;
  font-size: 60px;
  line-height: 1;
  letter-spacing: -1px;
}
.hero-unit p {
  font-size: 18px;
  font-weight: 200;
  line-height: 27px;
}
.pull-right {
  float: right;
}
.pull-left {
  float: left;
}
.hide {
  display: none;
}
.show {
  display: block;
}
.invisible {
  visibility: hidden;
}
.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}<!DOCTYPE html>

<html lang="en">
<head>
    <title>phpDocumentor</title>
    <meta charset="utf-8">
    <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
    <meta name="author" content="Mike van Riel">
    <meta name="description" content="">

    <!--[if lt IE 9]>
    <script src="http://html5shim.googlecode.com/svn/trunk/html5.js" type="text/javascript"></script>
    <![endif]-->

    <link href="css/template.css" rel="stylesheet" media="all">

    <!-- Le fav and touch icons -->
    <link rel="shortcut icon" href="images/favicon.ico">
    <link rel="apple-touch-icon" href="images/apple-touch-icon.png">
    <link rel="apple-touch-icon" sizes="72x72" href="images/apple-touch-icon-72x72.png">
    <link rel="apple-touch-icon" sizes="114x114" href="images/apple-touch-icon-114x114.png">
</head>

<body>
    <div class="navbar navbar-fixed-top">
        <div class="navbar-inner">
            <div class="container">
                <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
                    <span class="icon-bar"></span> <span class="icon-bar"></span>
                    <span class="icon-bar"></span> </a>
                <a class="brand" href="#">phpDocumentor</a>

                <div class="nav-collapse">
                    <ul class="nav">
                        <li class="active"><a href="#">Home</a></li>
                        <li class="dropdown" id="charts-menu">
                            <a href="#charts" class="dropdown-toggle" data-toggle="dropdown">
                                Charts <b class="caret"></b>
                            </a>
                            <ul class="dropdown-menu">
                                <li><a href="" onclick="$('body *').fadeOut(); $('body').load(this.href); return false;">Class hierarchy diagram</a></li>
                            </ul>
                        </li>
                        <li class="dropdown" id="reports-menu">
                            <a href="#reports" class="dropdown-toggle" data-toggle="dropdown">
                                Reports <b class="caret"></b>
                            </a>
                            <ul class="dropdown-menu">
                                <li><a href="#">Errors</a></li>
                                <li><a href="#">Markers (TODO/FIXME)</a></li>
                                <li><a href="">Deprecated elements</a></li>
                            </ul>
                        </li>
                    </ul>
                </div>
                <form class="navbar-search pull-right" onsubmit="$('.element:parent').show(); $('.element h1:not(:contains('+$('#search-query').val()+'))').parent().hide();return false;">
                    <input type="text" id="search-query" class="search-query" placeholder="Search" />
                </form>
                <!--/.nav-collapse -->
            </div>
        </div>
    </div>

    <div class="container">

        <div class="row">
            <div class="span9">
                <ul class="breadcrumb">
                    <li>
                        <a href="index.html"><i class="icon-leaf"></i></a> <span class="divider">\</span>
                    </li>
                    <li >
                        Charts <span class="divider">\</span>
                    </li>
                    <li class="active">
                        <a href="#">Class hierarchy diagram</a>
                    </li>
                </ul>

                <div id="displayXHProfReport" href="functions/displayXHProfReport.html" class="element function" data-toggle="collapse" data-target=".details">
                    <h1>
                        displayXHProfReport(object $xhprof_runs_impl, array $url_params, string $source, string $run, string $wts, string $symbol, $sort, string $run1, string $run2) : void
                        <a href="functions/displayXHProfReport.html">¶</a>
                    </h1>
                    <p class="short_description">Generate a XHProf Display View given the various URL parameters as arguments. The first argument is an object that implements the iXHProfRuns interface.</p>

                    <div class="details collapse">
                        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec non neque id mauris pharetra imperdiet. Mauris auctor, lectus id posuere fringilla, ligula eros iaculis odio, quis ornare augue erat id eros. Sed lorem lectus, luctus ullamcorper varius quis, viverra ut lacus. Aenean vitae leo massa, a ullamcorper velit. Nulla commodo velit id enim elementum eu tempor ipsum semper. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Proin sed arcu quam, bibendum vulputate nulla.
                    </div>
                    <a href="functions/displayXHProfReport.html" class="more">&laquo; More &raquo;</a>
                </div>

            </div>

            <div class="span3">
                <ul class="side-nav nav nav-list">
                    <li class="nav-header">Navigation</li>
                    <li class="function"><a href="#displayXHProfReport">displayXHProfReport</a></li>
                    <li class="function"><a href="#full_report">full_report</a></li>
                    <li class="function"><a href="#get_print_class">get_print_class</a></li>
                    <li class="class"><a href="#DocBlox_Abstract">\DocBlox_Abstract</a></li>
                </ul>
            </div>
        </div>
    </div>

    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
    <script src="js/bootstrap.js" type="text/javascript"></script>
    <script>
        $(".element a.more").hide();
        $(".element").css("cursor", "pointer");
    </script>
</body>
</html><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" method="html" />
    <xsl:include href="layout.xsl" />
    <xsl:include href="elements/common.xsl" />
    <xsl:include href="elements/namespace.xsl" />
    <xsl:include href="elements/class.xsl" />
    <xsl:include href="elements/constant.xsl" />
    <xsl:include href="elements/function.xsl" />

    <xsl:template match="/project" mode="contents">
        <xsl:variable name="element" select="//namespace[@full_name = $full_name]" />

        <xsl:variable name="parent_name">
            <xsl:if test="local-name($element/..) = 'namespace'">
                <xsl:value-of select="concat($element/../@full_name, '\')"/>
            </xsl:if>
        </xsl:variable>

        <div class="row">
            <div class="span4">
                <xsl:apply-templates select="$element" mode="sidebar-nav">
                    <xsl:with-param name="parent_name" select="$parent_name"/>
                </xsl:apply-templates>
            </div>

            <div class="span8 namespace-contents">
                <xsl:apply-templates select="$element" mode="contents">
                    <xsl:with-param name="parent_name" select="$parent_name"/>
                </xsl:apply-templates>
            </div>
        </div>
    </xsl:template>

    <xsl:template match="/" mode="title">
        <xsl:text> &#187; </xsl:text>
        <xsl:value-of select="$full_name" />
    </xsl:template>

</xsl:stylesheet><?xml version="1.0" encoding="utf-8"?>
<template>
  <author>Mike van Riel</author>
  <email>mike.vanriel@naenius.com</email>
  <version>1.0.1</version>
  <copyright>Mike van Riel 2012</copyright>
  <description><![CDATA[
      This is the 'Responsive' look and feel for phpDocumentor.

      This is a responsive template that is optimized to make the user's
      experience paramount.

      To improve performance you can add the following to your .htaccess:

      <ifModule mod_deflate.c>
          <filesMatch "\.(js|css|html)$">
              SetOutputFilter DEFLATE
          </filesMatch>
      </ifModule>
  ]]></description>
  <transformations>
    <transformation query="copy" writer="FileIo" source="templates/responsive/img" artifact="img"/>
    <transformation query="copy" writer="FileIo" source="templates/responsive/css" artifact="css"/>
    <transformation query="copy" writer="FileIo" source="templates/responsive/js" artifact="js"/>
    <transformation writer="xml" artifact="structure.xml" />
    <transformation writer="xsl" source="templates/responsive/index.xsl" artifact="index.html"/>
    <transformation query="//namespace/@full_name" writer="xsl" source="templates/responsive/namespaces.xsl" artifact="namespaces/{$full_name}"/>
    <transformation query="//package/@full_name" writer="xsl" source="templates/responsive/packages.xsl" artifact="packages/{$full_name}"/>
    <transformation query="//class/full_name|//interface/full_name" writer="xsl" source="templates/responsive/class.xsl" artifact="classes/{$full_name}"/>
    <transformation writer="xsl" source="templates/responsive/reports/markers.xsl" artifact="markers.html"/>
    <transformation writer="xsl" source="templates/responsive/reports/errors.xsl" artifact="errors.html"/>
    <transformation writer="xsl" source="templates/responsive/reports/deprecated.xsl" artifact="deprecated.html"/>
    <transformation writer="xsl" source="templates/responsive/graphs/class.xsl" artifact="graph_class.html"/>
    <transformation query="" writer="Graph" source="Class" artifact="classes.svg" />
  </transformations>
</template>
{
    "_readme": [
        "This file locks the dependencies of your project to a known state",
        "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
    ],
    "hash": "3863d70884e98d00b6edd554116499e9",
    "packages": [
        {
            "name": "phpdocumentor/unified-asset-installer",
            "version": "1.1",
            "source": {
                "type": "git",
                "url": "https://github.com/phpDocumentor/UnifiedAssetInstaller.git",
                "reference": "1.1"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phpDocumentor/UnifiedAssetInstaller/zipball/1.1",
                "reference": "1.1",
                "shasum": ""
            },
            "require-dev": {
                "composer/composer": "~1.0@dev",
                "phpunit/phpunit": "~3.7"
            },
            "type": "composer-installer",
            "extra": {
                "class": "\\phpDocumentor\\Composer\\UnifiedAssetInstaller"
            },
            "autoload": {
                "psr-0": {
                    "phpDocumentor\\Composer": [
                        "src/",
                        "test/unit/"
                    ]
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "description": "Asset installer for phpDocumentor",
            "homepage": "http://www.phpdoc.org",
            "keywords": [
                "assets",
                "installer",
                "plugins",
                "templates"
            ],
            "time": "2013-08-01 19:35:55"
        }
    ],
    "packages-dev": [

    ],
    "aliases": [

    ],
    "minimum-stability": "stable",
    "stability-flags": [

    ],
    "platform": {
        "ext-xsl": "*"
    },
    "platform-dev": [

    ]
}
<?xml version="1.0"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" method="html"/>
    <xsl:include href="../layout.xsl"/>

    <xsl:template match="/project" mode="contents">
        <div class="row">
            <div class="span12">
                <div class="well wrapper">
                    <div id="viewer" class="viewer"></div>
                </div>
            </div>
        </div>

        <script src="{$root}js/jquery.iviewer.min.js" type="text/javascript"></script>
        <script type="text/javascript">
            $(window).resize(function(){
                $("#viewer").height($(window).height() - 260);
            });

            $(document).ready(function() {
                $("#viewer").iviewer({src: "classes.svg", zoom_animation: false});
                $('#viewer img').bind('dragstart', function(event){
                    event.preventDefault();
                });
            });
        </script>
    </xsl:template>

</xsl:stylesheet><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" method="html" />
    <xsl:include href="layout.xsl" />
    <xsl:include href="elements/common.xsl" />
    <xsl:include href="elements/function.xsl" />
    <xsl:include href="elements/constant.xsl" />
    <xsl:include href="elements/property.xsl" />
    <xsl:include href="elements/class.xsl" />

    <!-- Body text that is inserted into the layout -->
    <xsl:template match="/project" mode="contents">
        <xsl:variable
            name="element"
            select="/project/file/class[full_name=$full_name]|/project/file/interface[full_name=$full_name]"
        />

        <div class="row">
            <div class="span4"><xsl:apply-templates select="$element" mode="sidebar" /></div>
            <div class="span8"><xsl:apply-templates select="$element" mode="contents"/></div>
        </div>
    </xsl:template>

    <xsl:template match="/" mode="title">
        <xsl:text> &#187; </xsl:text>
        <xsl:value-of select="$full_name" />
    </xsl:template>

</xsl:stylesheet><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" method="html" />

    <!-- Method/Function display name -->
    <xsl:template match="function/name|method/name">
        <xsl:value-of select="../docblock/description" />
        <xsl:if test="not(../docblock/description) or ../docblock/description = ''">
            <xsl:value-of select="." />()
        </xsl:if>
    </xsl:template>

    <xsl:template match="argument/type" mode="signature">
        <xsl:param name="exclude-link" />

        <xsl:variable name="name" select="../name" />
        <xsl:if test=". = '' and ../../docblock/tag[@name='param' and @variable=$name]/type">
            <xsl:call-template name="implodeTypes">
                <xsl:with-param name="items" select="../../docblock/tag[@name='param' and @variable=$name]/type"/>
                <xsl:with-param name="exclude-link" select="$exclude-link"/>
            </xsl:call-template>
            <xsl:text>&#160;</xsl:text>
        </xsl:if>
        <xsl:if test=". != ''">
            <xsl:apply-templates select="."/>
            <xsl:text>&#160;</xsl:text>
        </xsl:if>
    </xsl:template>

    <xsl:template match="function/name|method/name" mode="signature">
        <xsl:param name="exclude-link" />

        <pre>
            <xsl:value-of select="."/>
            <xsl:text>(</xsl:text>
            <xsl:call-template name="implodeTypesSignature">
                <xsl:with-param name="items" select="../argument"/>
                <xsl:with-param name="separator" select="', '"/>
                <xsl:with-param name="exclude-link" select="$exclude-link" />
            </xsl:call-template>
            <xsl:text>)&#160;</xsl:text>
            <xsl:apply-templates select="../docblock/tag[@name='return']" mode="signature">
                <xsl:with-param name="exclude-link" select="$exclude-link" />
            </xsl:apply-templates>
        </pre>
    </xsl:template>

    <xsl:template match="argument">
        <div class="subelement argument">
            <xsl:variable name="name" select="name"/>
            <xsl:variable name="tag" select="../docblock/tag[@name='param' and @variable=$name]" />
            <h4><xsl:value-of select="name"/></h4>
            <xsl:apply-templates select="$tag/type" mode="contents" />
            <xsl:value-of select="$tag/@description" disable-output-escaping="yes" />
        </div>
    </xsl:template>

    <xsl:template match="function|method" mode="contents">
        <a id="{local-name(.)}_{name}"></a>
        <div class="element clickable {local-name(.)} {@visibility} {local-name(.)}_{name}" data-toggle="collapse" data-target=".{local-name(.)}_{name} .collapse" title="{@visibility}">
            <h2><xsl:apply-templates select="name" /></h2>
            <xsl:apply-templates select="name" mode="signature" />
            <div class="labels">
                <xsl:if test="docblock/tag[@name='api']">
                    <span class="label label-info">API</span>
                </xsl:if>
                <xsl:if test="inherited_from">
                    <span class="label">Inherited</span>
                </xsl:if>
                <xsl:if test="@static='true' or docblock/tag[@name='static']">
                    <span class="label">Static</span>
                </xsl:if>
            </div>

            <div class="row collapse">
                <div>
                    <xsl:attribute name="class">
                        <xsl:if test="docblock/tag[@name='example']">span4</xsl:if>
                        <xsl:if test="not(docblock/tag[@name='example'])">detail-description</xsl:if>
                    </xsl:attribute>

                    <div class="long_description">
                        <xsl:value-of select="docblock/long-description" disable-output-escaping="yes" />
                    </div>

                    <xsl:if test="count(docblock/tag[@name != 'return' and @name != 'param' and @name != 'throws' and @name != 'throw']) > 0">
                        <table class="table table-bordered">
                            <xsl:apply-templates select="docblock/tag[@name != 'return' and @name != 'param' and @name != 'throws' and @name != 'throw']" mode="tabular" />
                        </table>
                    </xsl:if>

                    <xsl:if test="count(argument) > 0">
                    <h3>Parameters</h3>
                        <xsl:apply-templates select="argument" />
                    </xsl:if>

                    <xsl:if test="count(docblock/tag[@name = 'throws' or @name = 'throw']) > 0">
                        <h3>Exceptions</h3>
                        <table class="table table-bordered">
                            <xsl:apply-templates select="docblock/tag[@name = 'throws' and @name != 'throw']" mode="tabular" />
                        </table>
                    </xsl:if>

                    <xsl:if test="docblock/tag[@name='return' and @type != 'void']">
                        <h3>Returns</h3>
                        <xsl:apply-templates select="docblock/tag[@name='return' and @type != 'void']" mode="contents"/>
                    </xsl:if>
                </div>
                <xsl:if test="docblock/tag[@name='example']">
                    <div class="span4">
                        <h3>Examples</h3>
                        <xsl:for-each select="docblock/tag[@name='example']">
                            <pre class="prettyprint linenums">
                                <xsl:value-of select="."/>
                            </pre>
                        </xsl:for-each>
                    </div>
                </xsl:if>
            </div>
        </div>
    </xsl:template>

</xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" method="html" />

    <xsl:template match="package" mode="sidebar">
        <xsl:param name="parent_name" />
        <xsl:variable name="fqnn" select="concat($parent_name, @name)" />
        <xsl:variable name="element_count"
            select="count(/project/file/constant[@package=$fqnn]
                |/project/file/function[@package=$fqnn]
                |/project/file/class[@package=$fqnn]
                |/project/file/interface[@package=$fqnn])"
        />

        <li>
            <xsl:if test="$element_count > 0">
                <xsl:variable name="link">
                    <xsl:call-template name="createLink">
                        <xsl:with-param name="value" select="@full_name"/>
                    </xsl:call-template>
                </xsl:variable>
                <a href="{$root}packages/{$link}.html" title="{@name}"><i class="icon-folder-open"></i> <xsl:value-of select="@name" /></a>
            </xsl:if>

            <xsl:if test="$element_count = 0">
                <span class="empty-package"><i class="icon-folder-close"></i> <xsl:value-of select="@name" /></span>
            </xsl:if>

            <ul class="nav nav-list nav-packages">
                <xsl:apply-templates select="package" mode="sidebar">
                    <xsl:sort select="@name" />
                    <xsl:with-param name="parent_name" select="concat($fqnn, '\')" />
                </xsl:apply-templates>
            </ul>
        </li>
    </xsl:template>

    <xsl:template match="package" mode="contents">
        <xsl:param name="parent_name" />
        <xsl:variable name="fqnn" select="concat($parent_name, @name)" />

        <xsl:if test="count(/project/file/constant[@package=$fqnn]
            |/project/file/function[@package=$fqnn]
            |/project/file/class[@package=$fqnn]
            |/project/file/interface[@package=$fqnn]
            |package) > 0"
        >
            <ul class="breadcrumb">
                <li>
                    <a href="{$root}index.html"><i class="icon-folder-open"></i></a>
                    <span class="divider">\</span>
                    <xsl:apply-templates select="." mode="breadcrumb"/>
                </li>
            </ul>

            <div class="package-indent">
                <xsl:if test="count(/project/file/constant[@package=$fqnn]
                    |/project/file/function[@package=$fqnn]
                    |/project/file/class[@package=$fqnn]
                    |/project/file/interface[@package=$fqnn]
                    |package) = 0"
                >
                    <div class="alert alert-info">This package does not contain any documentable elements</div>
                </xsl:if>

                <xsl:variable name="functions" select="/project/file/function[@package=$fqnn]"/>
                <xsl:if test="count($functions) > 0">
                    <h3><i title="Functions" class="icon-custom icon-function"></i> Functions</h3>
                    <xsl:apply-templates select="$functions" mode="contents">
                        <xsl:sort select="name" />
                    </xsl:apply-templates>
                </xsl:if>

                <xsl:variable name="classes" select="/project/file/class[@package=$fqnn]|/project/file/interface[@package=$fqnn]"/>
                <xsl:if test="count($classes) > 0">
                    <h3><i title="Classes" class="icon-custom icon-class"></i> Classes and interfaces</h3>
                    <xsl:apply-templates select="$classes" mode="compact">
                        <xsl:sort select="local-name()" order="descending" />
                        <xsl:sort select="full_name" />
                    </xsl:apply-templates>
                </xsl:if>

                <xsl:variable name="constants" select="/project/file/constant[@package=$fqnn]"/>
                <xsl:if test="count($constants) > 0">
                    <h3><i title="Constants" class="icon-custom icon-constant"></i> Constants</h3>
                    <xsl:apply-templates select="$constants" mode="contents">
                        <xsl:sort select="name" />
                    </xsl:apply-templates>
                </xsl:if>

                <xsl:variable name="packages" select="package"/>
                <xsl:if test="count($packages) > 0">
                    <xsl:apply-templates select="$packages" mode="contents">
                        <xsl:sort select="@name" />
                        <xsl:with-param name="parent_name" select="concat($fqnn, '\')" />
                    </xsl:apply-templates>
                </xsl:if>
            </div>
        </xsl:if>
    </xsl:template>

    <xsl:template match="package" mode="sidebar-nav">
        <xsl:param name="parent_name"/>
        <xsl:variable name="name" select="@full_name"/>

        <div class="btn-group view pull-right" data-toggle="buttons-radio">
          <button class="btn details" title="Show descriptions and method names"><i class="icon-list"></i></button>
          <button class="btn simple" title="Show only method names"><i class="icon-align-justify"></i></button>
        </div>

        <ul class="side-nav nav nav-list">
            <li class="nav-header"><i class="icon-map-marker"></i> Packages</li>

            <xsl:apply-templates select="." mode="sidebar">
                <xsl:with-param name="parent_name" select="$parent_name" />
            </xsl:apply-templates>

            <xsl:variable name="functions" select="/project/file/function[@package=$name]"/>
            <xsl:if test="count($functions) > 0">
                <li class="nav-header"><i title="Functions" class="icon-custom icon-function"></i> Functions</li>
                <xsl:apply-templates select="$functions" mode="sidebar">
                    <xsl:sort select="name" />
                </xsl:apply-templates>
            </xsl:if>

            <xsl:variable name="interfaces" select="/project/file/interface[@package=$name]"/>
            <xsl:if test="count($interfaces) > 0">
                <li class="nav-header"><i title="Interfaces" class="icon-custom icon-interface"></i> Interfaces</li>
                <xsl:for-each select="$interfaces">
                    <li><a href="#{name}" title="{docblock/description}"><xsl:value-of select="name" /></a></li>
                </xsl:for-each>
            </xsl:if>

            <xsl:variable name="classes" select="/project/file/class[@package=$name]"/>
            <xsl:if test="count($classes) > 0">
                <li class="nav-header"><i title="Classes" class="icon-custom icon-class"></i> Classes</li>
                <xsl:for-each select="$classes">
                    <li><a href="#{name}" title="{docblock/description}"><xsl:value-of select="name" /></a></li>
                </xsl:for-each>
            </xsl:if>

            <xsl:variable name="constants" select="/project/file/constant[@package=$name]"/>
            <xsl:if test="count($constants) > 0">
                <li class="nav-header"><i title="Constants" class="icon-custom icon-constant"></i> Constants</li>
                <xsl:apply-templates select="$constants" mode="sidebar">
                    <xsl:sort select="name" />
                </xsl:apply-templates>
            </xsl:if>
        </ul>
    </xsl:template>

</xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" method="html" />

    <!-- Property display name -->
    <xsl:template match="property/name">
        <xsl:choose>
            <xsl:when test="../docblock/description[.!='']">
                <p><xsl:value-of select="../docblock/description" /></p>
            </xsl:when>
            <xsl:when test="../docblock/tag[@name='var']/@description[.!='']">
                <xsl:value-of select="../docblock/tag[@name='var']/@description" disable-output-escaping="yes"/>
            </xsl:when>
            <xsl:otherwise>
                <p><xsl:value-of select="." /></p>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template match="property/name" mode="signature">
        <xsl:param name="exclude-link" />

        <xsl:variable name="name" select="."/>
        <pre>
            <xsl:value-of select="$name"/>
            <xsl:text>&#160;</xsl:text>
            <xsl:apply-templates select="../docblock/tag[@name='var']" mode="signature">
                <xsl:with-param name="exclude-link" select="$exclude-link"/>
            </xsl:apply-templates>
        </pre>
        
        <div class="row collapse">
            <div class="detail-description">
                <h3>Default</h3>
                <div class="subelement argument">
                    <xsl:if test="../default[.!='']">
                        <code>
                            <xsl:value-of select="../default" disable-output-escaping="yes"/>
                        </code>
                    </xsl:if>
                </div>
            </div>
        </div>
    </xsl:template>

</xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" method="html" />

    <xsl:template match="namespace" mode="sidebar">
        <xsl:param name="parent_name" />
        <xsl:variable name="fqnn" select="concat($parent_name, @name)" />

        <li>
            <xsl:if test="count(/project/file/constant[@namespace=$fqnn]
                |/project/file/function[@namespace=$fqnn]
                |/project/file/class[@namespace=$fqnn]
                |/project/file/interface[@namespace=$fqnn]) > 0"
            >
                <xsl:variable name="link">
                    <xsl:call-template name="createLink">
                        <xsl:with-param name="value" select="@full_name"/>
                    </xsl:call-template>
                </xsl:variable>

                <a href="{$root}namespaces/{$link}.html" title="{@name}"><i class="icon-th"></i> <xsl:value-of select="@name" /></a>
            </xsl:if>

            <xsl:if test="count(/project/file/constant[@namespace=$fqnn]
                |/project/file/function[@namespace=$fqnn]
                |/project/file/class[@namespace=$fqnn]
                |/project/file/interface[@namespace=$fqnn]) = 0"
            >
                <span class="empty-namespace"><i class="icon-stop"></i> <xsl:value-of select="@name" /></span>
            </xsl:if>

            <ul class="nav nav-list nav-namespaces">
                <xsl:apply-templates select="namespace" mode="sidebar">
                    <xsl:sort select="@name" />
                    <xsl:with-param name="parent_name" select="concat($fqnn, '\')" />
                </xsl:apply-templates>
            </ul>
        </li>
    </xsl:template>

    <xsl:template match="namespace" mode="contents">
        <xsl:param name="parent_name" />
        <xsl:variable name="fqnn" select="concat($parent_name, @name)" />

        <xsl:if test="count(/project/file/constant[@namespace=$fqnn]
            |/project/file/function[@namespace=$fqnn]
            |/project/file/class[@namespace=$fqnn]
            |/project/file/interface[@namespace=$fqnn]
            |namespace) > 0"
        >
            <ul class="breadcrumb">
                <li>
                    <a href="{$root}index.html"><i class="icon-th"></i></a>
                    <span class="divider">\</span>
                </li>
                <xsl:apply-templates select="." mode="breadcrumb"/>
            </ul>

            <div class="namespace-indent">
                <xsl:if test="count(/project/file/constant[@namespace=$fqnn]
                    |/project/file/function[@namespace=$fqnn]
                    |/project/file/class[@namespace=$fqnn]
                    |/project/file/interface[@namespace=$fqnn]) = 0"
                >
                    <div class="alert alert-info">This namespace does not contain any documentable elements</div>
                </xsl:if>

                <xsl:variable name="functions" select="/project/file/function[@namespace=$fqnn]"/>
                <xsl:if test="count($functions) > 0">
                    <h3><i title="Functions" class="icon-custom icon-function"></i> Functions</h3>
                    <xsl:apply-templates select="$functions" mode="contents">
                        <xsl:sort select="name" />
                    </xsl:apply-templates>
                </xsl:if>

                <xsl:variable name="classes" select="/project/file/class[@namespace=$fqnn]"/>
                <xsl:variable name="interfaces" select="/project/file/interface[@namespace=$fqnn]"/>
                <xsl:if test="count($classes)+count($interfaces) > 0">
                    <h3><i title="Class" class="icon-custom icon-class"></i> Classes and interfaces</h3>
                    <xsl:apply-templates select="$classes|$interfaces" mode="compact">
                        <xsl:sort select="local-name()" order="descending" />
                        <xsl:sort select="full_name" />
                    </xsl:apply-templates>
                </xsl:if>

                <xsl:variable name="constants" select="/project/file/constant[@namespace=$fqnn]"/>
                <xsl:if test="count($constants) > 0">
                    <h3><i title="Constants" class="icon-custom icon-constant"></i> Constants</h3>
                    <xsl:apply-templates select="$constants" mode="contents">
                        <xsl:sort select="name" />
                    </xsl:apply-templates>
                </xsl:if>

                <xsl:variable name="namespaces" select="namespace"/>
                <xsl:if test="$namespaces">
                    <xsl:apply-templates select="$namespaces" mode="contents">
                        <xsl:sort select="@name" />
                        <xsl:with-param name="parent_name" select="concat($fqnn, '\')" />
                    </xsl:apply-templates>
                </xsl:if>
            </div>
        </xsl:if>

    </xsl:template>

    <xsl:template match="namespace" mode="sidebar-nav">
        <xsl:param name="parent_name" select="@full_name"/>

        <div class="btn-group view pull-right" data-toggle="buttons-radio">
          <button class="btn details" title="Show descriptions and method names"><i class="icon-list"></i></button>
          <button class="btn simple" title="Show only method names"><i class="icon-align-justify"></i></button>
        </div>

        <ul class="side-nav nav nav-list">
            <li class="nav-header"><i class="icon-map-marker"></i> Namespaces</li>

            <xsl:apply-templates select="." mode="sidebar">
                <xsl:with-param name="parent_name" select="$parent_name"/>
            </xsl:apply-templates>

            <xsl:variable name="functions" select="/project/file/function[@namespace=$parent_name]"/>
            <xsl:if test="count($functions) > 0">
                <li class="nav-header"><i title="Functions" class="icon-custom icon-function"></i> Functions</li>
                <xsl:apply-templates select="$functions" mode="sidebar">
                    <xsl:sort select="name" />
                </xsl:apply-templates>
            </xsl:if>

            <xsl:variable name="interfaces" select="/project/file/interface[@namespace=$parent_name]"/>
            <xsl:if test="count($interfaces) > 0">
                <li class="nav-header"><i title="Interfaces" class="icon-custom icon-interface"></i> Interfaces</li>
                <xsl:for-each select="$interfaces">
                    <li><a href="#{name}" title="{docblock/description}"><xsl:value-of select="name" /></a></li>
                </xsl:for-each>
            </xsl:if>

            <xsl:variable name="classes" select="/project/file/class[@namespace=$parent_name]"/>
            <xsl:if test="count($classes) > 0">
                <li class="nav-header"><i title="Classes" class="icon-custom icon-class"></i> Classes</li>
                <xsl:for-each select="$classes">
                    <li><a href="#{name}" title="{docblock/description}"><xsl:value-of select="name" /></a></li>
                </xsl:for-each>
            </xsl:if>

            <xsl:variable name="constants" select="/project/file/constant[@namespace=$parent_name]"/>
            <xsl:if test="count($constants) > 0">
                <li class="nav-header"><i title="Constants" class="icon-custom icon-constant"></i> Constants</li>
                <xsl:apply-templates select="$constants" mode="sidebar">
                    <xsl:sort select="name" />
                </xsl:apply-templates>
            </xsl:if>
        </ul>
    </xsl:template>

</xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" method="html" />

    <!-- Constant display name -->
    <xsl:template match="constant/name">
        <xsl:value-of select="../docblock/description" />
        <xsl:if test="not(../docblock/description) or ../docblock/description = ''">
            <xsl:value-of select="../docblock/tag[@name='var']/@description" />
            <xsl:if test="not(../docblock/tag[@name='var']/@description) or ../docblock/tag[@name='var']/@description = ''">
                <xsl:value-of select="." />
            </xsl:if>
        </xsl:if>
    </xsl:template>

    <xsl:template match="constant/name" mode="signature">
        <xsl:param name="exclude-link" />

        <xsl:variable name="name" select="."/>
        <xsl:variable name="value" select="../value"/>
        <pre>
            <xsl:value-of select="$name"/>
            <xsl:text>&#160;=&#160;</xsl:text>
            <xsl:value-of select="$value"/>
            <xsl:text>&#160;</xsl:text>
            <xsl:apply-templates select="../docblock/tag[@name='var']" mode="signature">
                <xsl:with-param name="exclude-link" select="$exclude-link"/>
            </xsl:apply-templates>
        </pre>
    </xsl:template>

    <xsl:template match="property|constant" mode="contents">
        <a id="{local-name(.)}_{translate(name, '$', '')}">&#160;</a>
        <xsl:variable name="desc">
            <xsl:apply-templates select="name" />
        </xsl:variable>
        <div class="element clickable {local-name(.)} {@visibility} {local-name(.)}_{translate(name, '$', '')}" data-toggle="collapse" data-target=".{local-name(.)}_{translate(name, '$', '')} .collapse" title="{@visibility}">
            <h2>
                <xsl:if test="not($desc)">
                    <xsl:value-of select="name"/>
                </xsl:if>

                <xsl:choose>
                    <xsl:when test="name()='property'">
                        <xsl:choose>
                            <xsl:when test="contains($desc, '&lt;p&gt;')">
                                <xsl:value-of select="substring-after(substring-before(string($desc), '&lt;/p&gt;'), '&lt;p&gt;')"/>
                            </xsl:when>
                            <xsl:otherwise>
                                <xsl:value-of select="$desc" />
                            </xsl:otherwise>
                        </xsl:choose>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="$desc" />
                    </xsl:otherwise>
                </xsl:choose>
            </h2>
            <xsl:apply-templates select="name" mode="signature" />
            <div class="labels">
                <xsl:if test="docblock/tag[@name='api']">
                    <span class="label label-info">API</span>
                </xsl:if>
                <xsl:if test="inherited_from">
                    <span class="label">Inherited</span>
                </xsl:if>
                <xsl:if test="@static='true' or docblock/tag[@name='static']">
                    <span class="label">Static</span>
                </xsl:if>
            </div>

            <div class="row collapse">
                <div>
                    <xsl:attribute name="class">
                        <xsl:if test="docblock/tag[@name='example']">span4</xsl:if>
                        <xsl:if test="not(docblock/tag[@name='example'])">detail-description</xsl:if>
                    </xsl:attribute>
                    <div class="long_description">
                        <xsl:value-of select="docblock/long-description" disable-output-escaping="yes" />
                    </div>

                    <xsl:if test="count(docblock/tag[@name != 'var']) > 0">
                        <table class="table table-bordered">
                            <xsl:apply-templates select="docblock/tag[@name != 'var']" mode="tabular" />
                        </table>
                    </xsl:if>
                </div>
                <xsl:if test="docblock/tag[@name='example']">
                    <div class="span4">
                        <h3>Examples</h3>
                        <xsl:for-each select="docblock/tag[@name='example']">
                            <pre class="prettyprint linenums">
                                <xsl:value-of select="."/>
                            </pre>
                        </xsl:for-each>
                    </div>
                </xsl:if>
            </div>
        </div>
    </xsl:template>

</xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" method="html" />

    <!-- Concatenate items with links with a given separator, based on: http://symphony-cms.com/download/xslt-utilities/view/22517/-->
    <xsl:template name="implodeTypes">
        <xsl:param name="items" />
        <xsl:param name="separator" select="' | '" />
        <xsl:param name="exclude-link" />

        <xsl:for-each select="$items">
            <xsl:if test="position() &gt; 1">
                <xsl:value-of select="$separator" />
            </xsl:if>

            <xsl:apply-templates select=".">
                <xsl:with-param name="exclude-link" select="$exclude-link"/>
            </xsl:apply-templates>
        </xsl:for-each>
    </xsl:template>

    <xsl:template name="implodeTypesSignature">
        <xsl:param name="items" />
        <xsl:param name="separator" select="' | '" />
        <xsl:param name="exclude-link" />

        <xsl:for-each select="$items">
            <xsl:if test="position() &gt; 1">
                <xsl:value-of select="$separator" />
            </xsl:if>

            <xsl:apply-templates select="." mode="signature">
                <xsl:with-param name="exclude-link" select="$exclude-link"/>
            </xsl:apply-templates>
        </xsl:for-each>
    </xsl:template>

    <xsl:template match="type">
        <xsl:param name="exclude-link" />

        <xsl:if test="@link and not($exclude-link)">
            <xsl:variable name="name" select="."/>
            <xsl:variable name="element" select="/project/file/class[full_name=$name]|/project/file/interface[full_name=$name]"/>

            <xsl:variable name="link">
                <xsl:call-template name="createLink">
                    <xsl:with-param name="value" select="$element/full_name"/>
                </xsl:call-template>
            </xsl:variable>

            <xsl:if test="$element">
                <a href="{$root}classes/{substring($link, 2)}.html"><xsl:value-of select="." /></a>
            </xsl:if>

            <xsl:if test="not($element)">
                <a href="{@link}"><xsl:value-of select="." /></a>
            </xsl:if>

        </xsl:if>
        <xsl:if test="not(@link) or $exclude-link"><xsl:value-of select="."/></xsl:if>
    </xsl:template>

    <xsl:template match="type" mode="contents">
        <code><xsl:apply-templates select="."/></code>
    </xsl:template>

    <xsl:template match="tag[@name='return' or @name='param' or @name='var']" mode="signature">
        <xsl:param name="exclude-link" />

        <xsl:text>:&#160;</xsl:text>

        <xsl:call-template name="implodeTypes">
            <xsl:with-param name="items" select="type"/>
            <xsl:with-param name="exclude-link" select="$exclude-link"/>
        </xsl:call-template>
    </xsl:template>

    <xsl:template match="argument" mode="signature">
        <xsl:param name="exclude-link" />

        <xsl:apply-templates select="type" mode="signature">
            <xsl:with-param name="exclude-link" select="$exclude-link"/>
        </xsl:apply-templates>
        <xsl:value-of select="name"/>
        <xsl:if test="default[.!='']">
            <code>
                <xsl:text>&#160;=&#160;</xsl:text>
                <xsl:value-of select="default"/>
            </code>
        </xsl:if>
    </xsl:template>

    <!-- Property/Constant list item in the sidebar -->
    <xsl:template match="method" mode="sidebar">
        <li>
            <xsl:attribute name="class">
                <xsl:value-of select="local-name()"/>
                <xsl:text> </xsl:text>
                <xsl:value-of select="@visibility" />
                <xsl:text> </xsl:text>
                <xsl:if test="inherited_from">inherited</xsl:if>
            </xsl:attribute>

			<xsl:variable name="tooltip">
			    <xsl:value-of select="name"/>
				<xsl:text>()</xsl:text>
				<xsl:if test="docblock/description">
					<xsl:text> :: </xsl:text>
					<xsl:value-of select="docblock/description"/>
				</xsl:if>	
			</xsl:variable>

            <a href="#{local-name(.)}_{translate(name, '$', '')}" title="{$tooltip}">
                <xsl:variable name="desc">
                    <xsl:apply-templates select="name" />
                </xsl:variable>
                <span class="description">
                    <xsl:choose>
                        <xsl:when test="name()='property'">
                            <xsl:value-of select="substring-after(substring-before(string($desc), '&lt;/p&gt;'), '&lt;p&gt;')"/>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:value-of select="$desc" />
                        </xsl:otherwise>
                    </xsl:choose>
                </span>
                <pre><xsl:value-of select="name" /><xsl:if test="local-name() = 'method'">()</xsl:if></pre>
            </a>
        </li>
    </xsl:template>

    <xsl:template match="function|property|constant|class|interface" mode="sidebar">
        <li>
            <xsl:attribute name="class">
                <xsl:value-of select="local-name()"/>
                <xsl:text> </xsl:text>
                <xsl:value-of select="@visibility" />
                <xsl:text> </xsl:text>
                <xsl:if test="inherited_from">inherited</xsl:if>
            </xsl:attribute>

            <a href="#{local-name(.)}_{translate(name, '$', '')}" title="{name}() :: {docblock/description}">
                <xsl:variable name="desc">
                    <xsl:apply-templates select="name" />
                </xsl:variable>
                <span class="description">
                    <xsl:choose>
                        <xsl:when test="name()='property'">
                            <xsl:value-of select="substring-after(substring-before(string($desc), '&lt;/p&gt;'), '&lt;p&gt;')"/>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:value-of select="$desc" />
                        </xsl:otherwise>
                    </xsl:choose>
                </span>
                <pre><xsl:value-of select="name" /><xsl:if test="local-name() = 'method'">()</xsl:if></pre>
            </a>
        </li>
    </xsl:template>

    <xsl:template match="tag" mode="tabular">
        <tr>
            <th><xsl:value-of select="@name"/></th>
            <td><xsl:value-of select="@description" disable-output-escaping="yes"/></td>
        </tr>
    </xsl:template>

    <xsl:template match="tag[@name = 'license' or @name = 'link' or @name = 'see' or @name = 'uses' or @name = 'author']" mode="tabular">
        <tr>
            <th><xsl:value-of select="@name"/></th>
            <td>
                <a href="{@link}">
                    <xsl:value-of select="@description" disable-output-escaping="yes" />
                </a>
            </td>
        </tr>
    </xsl:template>

    <xsl:template match="tag[@name = 'package']" mode="tabular">
        <xsl:variable name="link">
            <xsl:call-template name="createLink">
                <xsl:with-param name="value" select="../../@package"/>
            </xsl:call-template>
        </xsl:variable>

        <tr>
            <th><xsl:value-of select="@name"/></th>
            <td>
                <a href="{$root}packages/{$link}.html">
                    <xsl:value-of select="@description" />
                </a>
            </td>
        </tr>
    </xsl:template>

    <xsl:template match="tag[@name = 'throws' or @name = 'throw']" mode="tabular">
        <tr>
            <th><xsl:apply-templates select="type" mode="contents" /></th>
            <td><xsl:value-of select="@description" disable-output-escaping="yes"/></td>
        </tr>
    </xsl:template>

    <xsl:template match="tag[@name='return']" mode="contents">
        <div class="subelement response">
            <xsl:apply-templates select="type" mode="contents" />
            <xsl:value-of select="@description" disable-output-escaping="yes" />
        </div>
    </xsl:template>

    <xsl:template match="namespace|package" mode="breadcrumb">
        <xsl:param name="active" select="'true'"/>

        <xsl:variable name="link">
            <xsl:call-template name="createLink">
                <xsl:with-param name="value" select="@full_name" />
            </xsl:call-template>
        </xsl:variable>

        <xsl:if test="local-name(..) = local-name()">
            <xsl:apply-templates select=".." mode="breadcrumb">
                <xsl:with-param name="active" select="'false'" />
            </xsl:apply-templates>
        </xsl:if>

        <li>
            <xsl:if test="$active = 'true'"><xsl:attribute name="class">active</xsl:attribute></xsl:if>
            <xsl:if test="local-name(..) = local-name()">
                <span class="divider">\</span>
            </xsl:if>
            <a href="{$root}{local-name()}s/{$link}.html"><xsl:value-of select="@name" /></a>
        </li>
    </xsl:template>

</xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" method="html" />

    <!-- Sidebar index for classes and interfaces -->
        <xsl:template match="/project/file/class|/project/file/interface" mode="sidebar">
        <!-- Visibility toggles -->
        <div class="btn-toolbar">
            <div class="btn-group visibility" data-toggle="buttons-checkbox">
                <button class="btn public active" title="Show public elements">Public</button>
                <button class="btn protected" title="Show protected elements">Protected</button>
                <button class="btn private" title="Show private elements">Private</button>
                <button class="btn inherited active" title="Show inherited elements">Inherited</button>
            </div>

            <div class="btn-group view pull-right" data-toggle="buttons-radio">
                <button class="btn details" title="Show descriptions and method names"><i class="icon-list"></i></button>
                <button class="btn simple" title="Show only method names"><i class="icon-align-justify"></i></button>
            </div>
        </div>

        <ul class="side-nav nav nav-list">
            <xsl:if test="method">
                <li class="nav-header">
                    <i title="Methods" class="icon-custom icon-method"></i>&#160;Methods
                    <ul>
                        <xsl:apply-templates select="method[@visibility != 'protected' and @visibility != 'private']" mode="sidebar">
                            <xsl:sort select="name" />
                        </xsl:apply-templates>
                    </ul>
                </li>
            </xsl:if>

            <xsl:if test="method[@visibility = 'protected']">
                <li class="nav-header protected">&#187; Protected
                    <ul>
                        <xsl:apply-templates select="method[@visibility = 'protected']" mode="sidebar">
                            <xsl:sort select="name" />
                        </xsl:apply-templates>
                    </ul>
                </li>
            </xsl:if>

            <xsl:if test="method[@visibility = 'private']">
                <li class="nav-header private">&#187; Private
                    <ul>
                        <xsl:apply-templates select="method[@visibility = 'private']" mode="sidebar">
                            <xsl:sort select="name" />
                        </xsl:apply-templates>
                    </ul>
                </li>
            </xsl:if>

            <xsl:if test="property">
                <li class="nav-header">
                    <i title="Properties" class="icon-custom icon-property"></i>&#160;Properties
                    <ul>
                        <xsl:apply-templates select="property[@visibility != 'protected' and @visibility != 'private']" mode="sidebar">
                            <xsl:sort select="name" />
                        </xsl:apply-templates>
                    </ul>
                </li>
            </xsl:if>

            <xsl:if test="property[@visibility = 'protected']">
                <li class="nav-header protected">&#187; Protected
                    <ul>
                        <xsl:apply-templates select="property[@visibility = 'protected']" mode="sidebar">
                            <xsl:sort select="name" />
                        </xsl:apply-templates>
                    </ul>
                </li>
            </xsl:if>

            <xsl:if test="property[@visibility = 'private']">
                <li class="nav-header private">&#187; Private
                    <ul>
                        <xsl:apply-templates select="property[@visibility = 'private']" mode="sidebar">
                            <xsl:sort select="name" />
                        </xsl:apply-templates>
                    </ul>
                </li>
            </xsl:if>

            <xsl:if test="constant">
                <li class="nav-header">
                    <i title="Constants" class="icon-custom icon-constant"></i>&#160;Constants
                    <ul>
                        <xsl:apply-templates select="constant" mode="sidebar">
                            <xsl:sort select="name" />
                        </xsl:apply-templates>
                    </ul>
                </li>
            </xsl:if>
        </ul>
    </xsl:template>

    <xsl:template match="extends|implements">
        <xsl:param name="element" select="/project/file/class[full_name=.]|/project/file/interface[full_name=.]"/>

        <xsl:if test="$element">
            <xsl:variable name="link">
                <xsl:call-template name="createLink">
                    <xsl:with-param name="value" select="."/>
                </xsl:call-template>
            </xsl:variable>

            <a href="{$root}classes/{substring($link, 2)}.html">
                <xsl:value-of select="." />
            </a>
        </xsl:if>
        <xsl:if test="not($element)">
            <xsl:value-of select="." />
        </xsl:if>
    </xsl:template>

    <!-- Breadcrumb to display inheritance tree -->
    <xsl:template match="extends" mode="inheritance_breadcrumb">
        <xsl:variable name="name" select="."/>
        <xsl:variable
            name="extended_element"
            select="/project/file/class[full_name=$name]|/project/file/interface[full_name=$name]"
        />

        <xsl:if test="$name != ''">
            <li>
                <xsl:apply-templates select="$extended_element/extends" mode="inheritance_breadcrumb" />
            </li>

            <xsl:apply-templates select=".">
                <xsl:with-param name="element" select="$extended_element" />
            </xsl:apply-templates>
        </xsl:if>
    </xsl:template>

    <xsl:template match="class|interface" mode="compact">
        <xsl:variable name="filename">
            <xsl:call-template name="createLink">
                <xsl:with-param name="value" select="full_name"/>
            </xsl:call-template>
        </xsl:variable>
        <xsl:variable name="link" xml:space="preserve"><xsl:value-of select="$root" />classes/<xsl:value-of select="substring($filename, 2)" />.html</xsl:variable>

        <div id="{name}" class="element ajax clickable {local-name()}">
            <h1><xsl:value-of select="name"/><a href="{$link}">¶</a></h1>
            <p class="short_description"><xsl:value-of select="docblock/description" disable-output-escaping="yes"/></p>
            <div class="details collapse"></div>
            <a href="{$link}" class="more">&#171; More &#187;</a>
        </div>
    </xsl:template>

    <xsl:template match="class|interface" mode="contents">
        <xsl:variable name="namespace" select="@namespace"/>
        <xsl:variable name="filename">
            <xsl:call-template name="createLink">
                <xsl:with-param name="value" select="full_name"/>
            </xsl:call-template>
        </xsl:variable>
        <xsl:variable name="link" xml:space="preserve"><xsl:value-of select="$root" />classes/<xsl:value-of select="substring($filename, 2)" />.html</xsl:variable>

        <a id="{full_name}"></a>

        <ul class="breadcrumb">
            <li>
                <a href="{$root}index.html"><i title="Classes" class="icon-custom icon-class"></i></a>
                <span class="divider">\</span>
            </li>
            <xsl:apply-templates select="//namespace[@full_name=$namespace]" mode="breadcrumb">
                <xsl:with-param name="active" select="false()"/>
            </xsl:apply-templates>
            <li class="active">
                <span class="divider">\</span>
                <a href="{$link}"><xsl:value-of select="name" /></a>
            </li>
        </ul>

        <div class="element {local-name()}">
            <xsl:if test="docblock/description">
                <p class="short_description"><xsl:value-of select="docblock/description" disable-output-escaping="yes"/></p>
            </xsl:if>

            <div class="details">
                <xsl:if test="docblock/long-description">
                <div class="long_description"><xsl:value-of select="docblock/long-description" disable-output-escaping="yes"/></div>
                </xsl:if>

                <xsl:if test="count(docblock/tag) > 0">
                    <table class="table table-bordered">
                        <xsl:apply-templates select="docblock/tag" mode="tabular" />
                    </table>
                </xsl:if>

                <xsl:if test="method">
                    <h3><i title="Methods" class="icon-custom icon-method"></i>&#160;Methods</h3>
                    <xsl:apply-templates select="method" mode="contents">
                        <xsl:sort select="@visibility" order="descending"/>
                        <xsl:sort select="name"/>
                    </xsl:apply-templates>
                </xsl:if>

                <xsl:if test="property">
                    <h3><i title="Properties" class="icon-custom icon-property"></i>&#160;Properties</h3>
                    <xsl:apply-templates select="property" mode="contents">
                        <xsl:sort select="@visibility" order="descending" />
                        <xsl:sort select="name" />
                    </xsl:apply-templates>
                </xsl:if>

                <xsl:if test="constant">
                    <h3><i title="Constants" class="icon-custom icon-constant"></i>&#160;Constants</h3>
                    <xsl:apply-templates select="constant" mode="contents">
                        <xsl:sort select="name" />
                    </xsl:apply-templates>
                </xsl:if>
            </div>
        </div>
    </xsl:template>

</xsl:stylesheet>
{% macro renderMarkerCounter(files) %}
    {% set count = 0 %}
    {% for file in files %}
        {% set count = count + file.markers|length %}
    {% endfor %}
    <span class="label label-info">{{ count }}</span>
{% endmacro %}

{% macro renderErrorCounter(files) %}
    {% set count = 0 %}
    {% for file in files %}
        {% set count = count + file.allerrors|length %}
    {% endfor %}
    <span class="label label-info">{{ count }}</span>
{% endmacro %}

{% macro buildBreadcrumb(element) %}
    {% import _self as self %}

    {% if element.parentNamespace and element.parentNamespace.name != '\\' %}
        {{ self.buildBreadcrumb(element.parentNamespace) }}
    {% endif %}

    <li><span class="divider">\</span><a href="{{ path(element) }}">{{ element.name }}</a></li>
{% endmacro %}
{% block sidebar_buttons %}{% endblock %}
{% block sidebar_content %}{% endblock %}

{% block sidebar %}
    {{ block('sidebar_buttons') }}
    {{ block('sidebar_content') }}
{% endblock %}
{% use 'base/sidebar.html.twig' %}

{% block sidebar_buttons %}
    <div class="btn-group view pull-right" data-toggle="buttons-radio">
        <button class="btn details" title="Show descriptions and method names"><i class="icon-list"></i></button>
        <button class="btn simple" title="Show only method names"><i class="icon-align-justify"></i></button>
    </div>
    <div class="btn-group visibility" data-toggle="buttons-checkbox">
        <button class="btn public active" title="Show public elements">Public</button>
        <button class="btn protected" title="Show protected elements">Protected</button>
        <button class="btn private" title="Show private elements">Private</button>
        <button class="btn inherited active" title="Show inherited elements">Inherited</button>
    </div>
{% endblock %}

{% block sidebar_entry %}
    <li class="{{ type }} {{ item.visibility }}{{ item.parent.name != node.name ? ' inherited' : '' }}">
        <a href="#{{ type }}_{{ item.name }}" title="{{ item.name }} :: {{ item.summary }}">
            <span class="description">{{ item.summary }}</span><pre>{{ item.name }}</pre>
        </a>
    </li>
{% endblock %}

{% block sidebar_content %}
    <ul class="side-nav nav nav-list">
        <li class="nav-header">
            <i class="icon-custom icon-method"></i> Methods
            <ul>
                {% set specialMethods = node.magicMethods ? node.inheritedMethods.merge(node.magicMethods) : node.inheritedMethods %}
                {% for item in node.methods.merge(specialMethods) %}
                    {% set type='method' %}
                    {% if item.visibility == '' or item.visibility == 'public' %}
                        {{ block('sidebar_entry') }}
                    {% endif %}
                {% endfor %}
            </ul>
        </li>
        <li class="nav-header protected">» Protected
            <ul>
                {% set specialMethods = node.magicMethods ? node.inheritedMethods.merge(node.magicMethods) : node.inheritedMethods %}
                {% for method in node.methods.merge(specialMethods) %}
                    {% if method.visibility == 'protected' %}
                        <li class="method {{ method.visibility }}{{ method.parent.name != node.name ? ' inherited' : '' }}">
                            <a href="#method_{{ method.name }}" title="{{ method.name }} :: {{ method.summary }}">
                                <span class="description">{{ method.summary }}</span><pre>{{ method.name }}</pre>
                            </a>
                        </li>
                    {% endif %}
                {% endfor %}
            </ul>
        </li>
        <li class="nav-header private">» Private
            <ul>
                {% set specialMethods = node.magicMethods ? node.inheritedMethods.merge(node.magicMethods) : node.inheritedMethods %}
                {% for method in node.methods.merge(specialMethods) %}
                    {% if method.visibility == 'private' %}
                        <li class="method {{ method.visibility }}{{ method.parent.name != node.name ? ' inherited' : '' }}">
                            <a href="#method_{{ method.name }}" title="{{ method.name }} :: {{ method.summary }}">
                                <span class="description">{{ method.summary }}</span><pre>{{ method.name }}</pre>
                            </a>
                        </li>
                    {% endif %}
                {% endfor %}
            </ul>
        </li>
        <li class="nav-header">
            <i class="icon-custom icon-constant"></i> Constants
            <ul>
                {% for constant in node.constants.merge(node.inheritedConstants) %}
                <li class="constant {{ constant.visibility }}">
                    <a href="#constant_{{ constant.name }}" title="{{ constant.name }} :: {{ constant.summary }}">
                        <span class="description">{{ constant.summary }}</span><pre>{{ constant.name }}</pre>
                    </a>
                </li>
                {% endfor %}
            </ul>
        </li>
    </ul>
{% endblock %}
{
    "name": "phpdocumentor/template-responsive-twig",
    "type": "phpdocumentor-template",
    "description": "Responsive modern template for phpDocumentor for Twig",
    "keywords": ["documentation", "template", "phpdoc"],
    "homepage": "http://www.phpdoc.org",
    "license": "MIT",
    "require": {
        "phpdocumentor/unified-asset-installer": "~1.1"
    }
}
{% extends 'layout.html.twig' %}

{% macro elementSummary(element, type) %}
    <div id="{{ type }}_{{ element.name }}" class="element ajax clickable {{ type }}" data-toggle="collapse" data-target="#{{ type }}_{{ element.name }} .collapse">
        <h1>{{ element.name }}{% if path(element) %}<a href="{{ path(element) }}">¶</a>{% endif %}</h1>
        <p class="short_description">{{ element.summary }}</p>
        <div class="details collapse">{{ element.description|markdown|raw }}</div>
        {% if path(element) %}<a href="{{ path(element) }}" class="more">« More »</a>{% endif %}
    </div>
{% endmacro %}

{% macro buildBreadcrumb(element) %}
    {% import _self as self %}

    {% if element.parent and element.parent.name != '\\' %}
        {{ self.buildBreadcrumb(element.parent) }}
    {% endif %}

    <li>
        <span class="divider">\</span><a href="{{ path(element) }}">{{ element.name }}</a>
    </li>
{% endmacro %}

{% macro renderNamespaceDetails(node) %}
    {% import _self as self %}

    {% if node.classes|length > 0 or node.interfaces|length > 0 or node.traits|length > 0 or node.functions|length > 0 or node.constants|length > 0 %}

        <ul class="breadcrumb">
            <li><a href="{{ path('index.html') }}"><i class="icon-th"></i></a></li>
            {{ self.buildBreadcrumb(node) }}
        </ul>

        {% if node.functions|length > 0 %}
            <div class="namespace-indent">
                <h3><i class="icon-custom icon-function"></i> Functions</h3>
                {% for function in node.functions %}
                    {{ self.elementSummary(function, 'function') }}
                {% endfor %}
            </div>
        {% endif %}

        {% if node.constants|length > 0 %}
            <div class="namespace-indent">
                <h3><i class="icon-custom icon-constant"></i> Constants</h3>
                {% for constant in node.constants %}
                    {{ self.elementSummary(constant, 'constant') }}
                {% endfor %}
            </div>
        {% endif %}

        {% if node.classes|length > 0 or node.interfaces|length > 0 or node.traits|length > 0 %}
            <div class="namespace-indent">
                <h3><i class="icon-custom icon-class"></i> Classes, interfaces and traits</h3>
                {% for trait in node.traits %}
                    {{ self.elementSummary(trait, 'trait') }}
                {% endfor %}

                {% for interface in node.interfaces %}
                    {{ self.elementSummary(interface, 'interface') }}
                {% endfor %}

                {% for class in node.classes %}
                    {{ self.elementSummary(class, 'class') }}
                {% endfor %}
            </div>
        {% endif %}
    {% endif %}

    {% for namespace in node.children %}
        {{ self.renderNamespaceDetails(namespace) }}
    {% endfor %}
{% endmacro %}

{% macro renderNamespaceSidebar(node) %}
    {% import _self as self %}

    {% for namespace in node.children %}
    <li>
        <a href="{{ path(namespace) }}" title="{{ namespace.name }}">
            <i class="icon-th"></i> {{ namespace.name }}
        </a>
        <ul class="nav nav-list nav-namespaces">
            {{ self.renderNamespaceSidebar(namespace) }}
        </ul>
    </li>
    {% endfor %}
{% endmacro %}

{% block title %}
    {{ project.title }} &raquo; {{ node.FullyQualifiedStructuralElementName }}
{% endblock %}

{% block content %}
    {% import _self as self %}

    <div class="row">

        <div class="span4">
            <div class="btn-group view pull-right" data-toggle="buttons-radio">
                <button class="btn details" title="Show descriptions and method names">
                    <i class="icon-list"></i></button><button class="btn simple" title="Show only method names">
                    <i class="icon-align-justify"></i>
                </button>
            </div>
            <ul class="side-nav nav nav-list">
                <li class="nav-header">
                    <i class="icon-map-marker"></i> Namespaces
                </li>
                {{ self.renderNamespaceSidebar(node) }}
            </ul>
        </div>

        <div class="span8 namespace-contents">
            {{ self.renderNamespaceDetails(node) }}
        </div>
    </div>
{% endblock %}
{% extends 'layout.html.twig' %}

{% block title %}
    {{ project.title }} &raquo; Markers
{% endblock %}

{% block content %}
    <div class="row">
        <div class="span4">
            <ul class="side-nav nav nav-list">
                <li class="nav-header">Navigation</li>
                {% set markerCount = 0 %}
                {% for file in project.files %}
                    {% if file.markers|length > 0 %}
                    <li><a href="#{{ file.path }}"><i class="icon-file"></i> {{ file.path }}</a></li>
                    {% endif %}
                    {% set markerCount = markerCount + file.markers|length %}
                {% endfor %}
            </ul>
        </div>

        <div class="span8">

            <ul class="breadcrumb">
                <li><a href="{{ path('/') }}"><i class="icon-map-marker"></i></a><span class="divider">\</span></li>
                <li>Markers</li>
            </ul>

            {% if markerCount <= 0 %}
                <div class="alert alert-info">No markers have been found in this project.</div>
            {% endif %}

            <div id="marker-accordion">
                {% for file in project.files %}
                    {% if file.markers|length > 0 %}
                        <div class="package-contents">
                            <a name="{{ file.path }}" id="{{ file.path }}"></a>
                            <h3>
                            <i class="icon-file"></i>
                                {{ file.path }}
                                <small style="float: right;padding-right: 10px;">{{ file.markers|length }}</small>
                            </h3>
                            <div>
                                <table class="table markers table-bordered">
                                    <tr>
                                        <th>Type</th>
                                        <th>Line</th>
                                        <th>Description</th>
                                    </tr>
                                    {% for marker in file.markers %}
                                        <tr>
                                            <td>{{ marker.type }}</td>
                                            <td>{{ marker.line }}</td>
                                            <td>{{ marker.message }}</td>
                                        </tr>
                                    {% endfor %}
                                </table>
                            </div>
                        </div>
                    {% endif %}
                {% endfor %}
            </div>
        </div>
    </div>
{% endblock %}
{% extends 'layout.html.twig' %}

{% block title %}
    {{ project.title }} &raquo; Compilation errors
{% endblock %}

{% block content %}
<div class="row">
        <div class="span4">

            <ul class="side-nav nav nav-list">
                <li class="nav-header">Filter type</li>
                <li>
                    <div class="btn-group type-filter" data-toggle="buttons-checkbox">
                        <button class="btn critical">Critical</button>
                        <button class="btn error">Error</button>
                        <button class="btn notice">Notice</button>
                    </div>
                </li>
                <li class="nav-header">Navigation</li>
                {% set errorCount = 0 %}
                {% for file in project.files %}
                    {% if file.allerrors|length > 0 %}
                        <li><a href="#{{ file.path }}"><i class="icon-file"></i> {{ file.path }}</a></li>
                    {% endif %}
                    {% set errorCount = errorCount + file.allerrors|length %}
                {% endfor %}
            </ul>
        </div>

        <div class="span8">
            <ul class="breadcrumb">
                <li><a href="{{ path('/') }}"><i class="icon-remove-sign"></i></a><span class="divider">\</span></li>
                <li>Compilation Errors</li>
            </ul>

            {% if errorCount <= 0 %}
                <div class="alert alert-info">No errors have been found in this project.</div>
            {% endif %}

            {% for file in project.files %}
                <div class="package-contents">
                    {% if file.allerrors|length > 0 %}
                        <a name="{{ file.path }}" id="{{ file.path }}"></a>
                        <h3>
                            <i class="icon-file"></i>
                            {{ file.path }}
                            <small style="float: right;padding-right: 10px;">{{ file.allerrors|length }}</small>
                        </h3>
                        <div>
                            <table class="table markers table-bordered">
                                <thead>
                                <tr>
                                    <th>Type</th>
                                    <th>Line</th>
                                    <th>Description</th>
                                </tr>
                                </thead>
                                <tbody>
                                {% for error in file.allerrors %}
                                    <tr class="{{ error.severity }}">
                                        <td>{{ error.severity }}</td>
                                        <td>{{ error.line }}</td>
                                        <td>{{ error.code|trans(error.context) }}</td>
                                    </tr>
                                {% endfor %}
                            </tbody>
                            </table>
                        </div>
                    {% endif %}
                </div>
            {% endfor %}
        </div>
    </div>
{% endblock %}
{% extends 'layout.html.twig' %}

{% block title %}
    {{ project.title }} &raquo; Deprecated elements
{% endblock %}

{% block content %}
    <div class="row">

        <div class="span4">
            <ul class="side-nav nav nav-list">
                <li class="nav-header">Navigation</li>
                {% for file in project.files if file.tags.deprecated %}
                    <li><a href="#{{ file.path }}"><i class="icon-file"></i> {{ file.path }}</a></li>
                {% endfor %}
            </ul>
        </div>

        <div class="span8">
            <ul class="breadcrumb">
                <li><a href="{{ path('/') }}"><i class="icon-stop"></i></a><span class="divider">\</span></li>
                <li>Deprecated elements</li>
            </ul>

            <div id="marker-accordion">
                {% for file in project.files if file.tags.deprecated %}
                    <a name="{{ file.path }}" id="{{ file.path }}"></a>
                    <h3>
                        <i class="icon-file"></i> {{ file.path }}
                        <small style="float: right;padding-right: 10px;">{{ file.tags.deprecated|length }}</small>
                    </h3>
                    <div>
                        <table class="table markers table-bordered">
                            <tr>
                                <th>Type</th>
                                <th>Line</th>
                                <th>Description</th>
                            </tr>
                            {% for tag in file.tags.deprecated %}
                                <tr>
                                    <td>{{ tag.name }}</td>
                                    <td>{{ tag.line }}</td>
                                    <td>{{ tag.description }}</td>
                                </tr>
                            {% endfor %}
                        </table>
                    </div>
                {% else %}
                    <div class="alert alert-info">No deprecated elements have been found in this project.</div>
                {% endfor %}
            </div>
        </div>
    </div>
{% endblock %}
{% extends 'layout.html.twig' %}

{% macro elementSummary(element, type) %}
    <div id="{{ element.name }}" class="element ajax clickable {{ type }}">
        <h1>{{ element.name }}<a href="{{ path(element) }}">¶</a></h1>
        <p class="short_description">{{ element.summary }}</p>
        <div class="details collapse">{{ element.description }}</div>
        <a href="{{ path(element) }}" class="more">« More »</a>
    </div>
{% endmacro %}

{% macro buildBreadcrumb(element) %}
    {% import _self as self %}

    {% if element.parent and element.parent.name != '\\' %}
        {{ self.buildBreadcrumb(element.parent) }}
    {% endif %}

    <li>
        <span class="divider">\</span><a href="{{ path(element) }}">{{ element.name }}</a>
    </li>
{% endmacro %}

{% macro renderPackageDetails(node) %}
    {% import _self as self %}

    {% if node.classes|length > 0 or node.interfaces|length > 0 or node.traits|length > 0 or node.functions|length > 0 or node.constants|length > 0 %}

        <ul class="breadcrumb">
            <li><a href="{{ path('index.html') }}"><i class="icon-th"></i></a></li>
            {{ self.buildBreadcrumb(node) }}
        </ul>

        {% if node.functions|length > 0 %}
            <div class="package-indent">
                <h3><i class="icon-custom icon-function"></i> Functions</h3>
                {% for function in node.functions %}
                    {{ self.elementSummary(function, 'function') }}
                {% endfor %}
            </div>
        {% endif %}

        {% if node.constants|length > 0 %}
            <div class="package-indent">
                <h3><i class="icon-custom icon-constant"></i> Constants</h3>
                {% for constant in node.constants %}
                    {{ self.elementSummary(constant, 'constant') }}
                {% endfor %}
            </div>
        {% endif %}

        {% if node.classes|length > 0 or node.interfaces|length > 0 or node.traits|length > 0 %}
            <div class="package-indent">
                <h3><i class="icon-custom icon-class"></i> Classes, interfaces and traits</h3>
                {% for trait in node.traits %}
                    {{ self.elementSummary(trait, 'trait') }}
                {% endfor %}

                {% for interface in node.interfaces %}
                    {{ self.elementSummary(interface, 'interface') }}
                {% endfor %}

                {% for class in node.classes %}
                    {{ self.elementSummary(class, 'class') }}
                {% endfor %}
            </div>
        {% endif %}
    {% endif %}

    {% for package in node.children %}
        {{ self.renderPackageDetails(package) }}
    {% endfor %}
{% endmacro %}

{% macro renderPackageSidebar(node) %}
    {% import _self as self %}

    {% for package in node.children %}
    <li>
        <a href="{{ path(package) }}" title="{{ package.name }}">
            <i class="icon-th"></i> {{ package.name }}
        </a>
        <ul class="nav nav-list nav-packages">
            {{ self.renderPackageSidebar(package) }}
        </ul>
    </li>
    {% endfor %}
{% endmacro %}

{% block title %}
    {{ project.title }} &raquo; {{ node.FullyQualifiedStructuralElementName }}
{% endblock %}

{% block content %}
    {% import _self as self %}

    <div class="row">

        <div class="span4">
            <div class="btn-group view pull-right" data-toggle="buttons-radio">
                <button class="btn details" title="Show descriptions and method names">
                    <i class="icon-list"></i></button><button class="btn simple" title="Show only method names">
                    <i class="icon-align-justify"></i>
                </button>
            </div>
            <ul class="side-nav nav nav-list">
                <li class="nav-header">
                    <i class="icon-map-marker"></i> Packages
                </li>
                {{ self.renderPackageSidebar(node) }}
            </ul>
        </div>

        <div class="span8 package-contents">
            {{ self.renderPackageDetails(node) }}
        </div>
    </div>
{% endblock %}
{% extends 'layout.html.twig' %}

{% import 'base/macros.html.twig' as macros %}

{% block heroUnit %}
    <div class="hero-unit">
        <h1>{{ project.name|raw }}</h1>
        <h2>Documentation</h2>
    </div>
{% endblock %}

{% block content %}
    <div class="row">
        <div class="span7">
            {% if project.namespace.namespaces|length > 0 or not project.index.packages %}
                <div class="well">
                    <ul class="nav nav-list">
                        <li class="nav-header">Namespaces</li>
                        {% block listRootNamespaces %}
                            <li><a href="{{ path(project.namespace) }}">Global ({{ project.namespace.name }})</a></li>
                            {% for namespace in project.namespace.children %}
                                <li><a href="{{ path(namespace) }}">{{ namespace.name }}</a></li>
                            {% endfor %}
                        {% endblock %}
                    </ul>
                </div>
            {% endif %}

            {% if project.indexes.packages|length > 0 %}
                <div class="well">
                    <ul class="nav nav-list">
                        <li class="nav-header">Packages</li>
                        {% block listRootPackages %}
                            <li><a href="{{ path(project.indexes.packages|first) }}">Global ({{ (project.indexes.packages|first).name }})</a></li>
                            {% for package in (project.indexes.packages|first).children %}
                                <li><a href="{{ path(package) }}">{{ package.name }}</a></li>
                            {% endfor %}
                        {% endblock %}
                    </ul>
                </div>
            {% endif %}

        </div>
        <div class="span5">
            <div class="well">
                <ul class="nav nav-list">
                    <li class="nav-header">Charts</li>
                    {% block listCharts %}
                        <li><a href="{{ path('graph_class.html') }}"><i class="icon-list-alt"></i> Class inheritance diagram</a></li>
                    {% endblock %}
                </ul>
            </div>
            <div class="well">
                <ul class="nav nav-list">
                    <li class="nav-header">Reports</li>
                    {% block listReports %}
                        <li>
                            <a href="{{ path('errors.html') }}">
                                <i class="icon-list-alt"></i> Errors {{ macros.renderErrorCounter(project.files) }}
                            </a>
                        </li>
                        <li>
                            <a href="{{ path('markers.html') }}">
                                <i class="icon-list-alt"></i> Markers {{ macros.renderMarkerCounter(project.files) }}
                            </a>
                        </li>
                    {% endblock %}
                </ul>
            </div>
        </div>
    </div>
{% endblock %}
<?xml version="1.0" encoding="utf-8"?>
<template>
  <author>Mike van Riel</author>
  <email>mike.vanriel@naenius.com</email>
  <version>1.0.1</version>
  <copyright>Mike van Riel 2012</copyright>
  <description><![CDATA[
      This is the 'Responsive' look and feel for phpDocumentor.

      This is a responsive template that is optimized to make the user's
      experience paramount.

      To improve performance you can add the following to your .htaccess:

      <ifModule mod_deflate.c>
          <filesMatch "\.(js|css|html)$">
              SetOutputFilter DEFLATE
          </filesMatch>
      </ifModule>
  ]]></description>
  <transformations>
    <transformation query="copy" writer="FileIo" source="templates/responsive/img" artifact="img"/>
    <transformation query="copy" writer="FileIo" source="templates/responsive/css" artifact="css"/>
    <transformation query="copy" writer="FileIo" source="templates/responsive/js" artifact="js"/>
    <transformation writer="twig" source="templates/responsive-twig/index.html.twig" artifact="index.html"/>
    <transformation query="indexes.namespaces" writer="twig" source="templates/responsive-twig/namespace.html.twig" />
    <transformation query="indexes.packages" writer="twig" source="templates/responsive-twig/package.html.twig" />
    <transformation query="indexes.classes" writer="twig" source="templates/responsive-twig/class.html.twig" />
    <transformation query="indexes.interfaces" writer="twig" source="templates/responsive-twig/class.html.twig" />
    <transformation writer="twig" source="templates/responsive-twig/reports/markers.html.twig" artifact="markers.html"/>
    <transformation writer="twig" source="templates/responsive-twig/reports/errors.html.twig" artifact="errors.html"/>
    <transformation writer="twig" source="templates/responsive-twig/reports/deprecated.html.twig" artifact="deprecated.html"/>
    <transformation writer="twig" source="templates/responsive-twig/graphs/class.html.twig" artifact="graph_class.html"/>
    <transformation writer="Graph" source="Class" artifact="classes.svg" />
  </transformations>
</template>
{% extends 'layout.html.twig' %}

{% block content %}
    <div class="row">
        <div class="span12">
            <div class="well wrapper">
                <div id="viewer" class="viewer"></div>
            </div>
        </div>
    </div>

    <script src="{{ path('js/jquery.iviewer.min.js') }}" type="text/javascript"></script>
    <script type="text/javascript">
        $(window).resize(function(){
            $("#viewer").height($(window).height() - 260);
        });

        $(document).ready(function() {
            $("#viewer").iviewer({src: '{{ path('classes.svg') }}', zoom_animation: false});
            $('#viewer img').bind('dragstart', function(event){
                event.preventDefault();
            });
        });
    </script>
{% endblock %}
{% extends 'layout.html.twig' %}

{% import 'base/macros.html.twig' as macros %}
{% use 'base/class.sidebar.html.twig' %}

{% block title %}
    {{ parent() }} &raquo; {{ node.FullyQualifiedStructuralElementName }}
{% endblock %}

{% block content %}
    <style>
        .deprecated h2 {
            text-decoration: line-through;
        }
    </style>
    <div class="row">
        <div class="span4">
            {{ block('sidebar') }}
        </div>

        <div class="span8">
            <div class="element class">
                <h1>{{ node.name }}</h1>
                <small style="display: block; text-align: right">
                    {% if node.parent %}
                        Extends {{ node.parent|route|join(', ')|raw }}
                    {% endif %}
                    {% if node.interfaces|length %}
                        Implements {{ node.interfaces|route|join(', ')|raw }}
                    {% endif %}
                </small>
                <p class="short_description">{{ node.summary }}</p>
                <div class="details">
                    <div class="long_description">
                        {{ node.description|markdown|raw }}
                    </div>
                    <table class="table table-bordered">
                        {% for tagList in node.tags %}
                            {% for tag in tagList if tag.name not in ['method', 'property']%}
                                <tr>
                                    <th>
                                        {{ tag.name }}
                                        {% if tag.type %}
                                            {{ tag.type|route|join('|')|raw }}
                                        {% endif %}
                                    </th>
                                    <td>
                                        {% if (tag.name == "since" or "deprecated") %}
                                            {{ tag.version }}
                                        {% endif %}
                                        {{ tag.description|markdown|raw }}
                                    </td>
                                </tr>
                            {% endfor %}
                        {% endfor %}
                    </table>

                    <h3><i class="icon-custom icon-method"></i> Methods</h3>
                    {% set specialMethods = node.magicMethods ? node.inheritedMethods.merge(node.magicMethods) : node.inheritedMethods %}
                    {% for method in node.methods.merge(specialMethods) %}
                        <a id="method_{{ method.name }}"></a>
                        <div class="element clickable method {{ method.visibility }} {{ method.deprecated ? 'deprecated' }} method_{{ method.name }}{{ method.parent.name != node.name ? ' inherited' : '' }}" data-toggle="collapse" data-target=".method_{{ method.name }} .collapse">
                            <h2>{{ method.summary ?: method.name }}</h2>
                            <pre>{{ method.name }}({% for argument in method.arguments %}{{ argument.types ? argument.types|join('|')~' ' }}{{ argument.byReference ? '&' }}{{ argument.name }}{{ argument.default ? ' = '~argument.default }}{% if not loop.last %}, {% endif %}{% endfor %}) {{ method.response.types ? ': '~method.response.types|join('|') }}</pre>
                            <div class="labels">
                                {% if method.parent.name != node.name %}<span class="label">inherited</span>{% endif %}
                                {% if method.static %}<span class="label">static</span>{% endif %}
                                {% if method.final %}<span class="label">final</span>{% endif %}
                                {% if method.abstract %}<span class="label">abstract</span>{% endif %}
                                {% if method.tags.api is defined %}<span class="label label-info">api</span>{% endif %}
                            </div>
                            <div class="row collapse">
                                <div class="detail-description">
                                    <div class="long_description">{{ method.description|markdown|raw }}</div>

                                    <table class="table">
                                        {% for tagList in method.tags if tagList.0.name not in ['param', 'return', 'api'] %}
                                            <tr>
                                                <th>
                                                    {{ tagList.0.name }}
                                                </th>
                                                <td>
                                                    {% for tag in tagList %}
                                                        {% if (tag.name == "since" or "deprecated") %}
                                                            {{ tag.version }}
                                                        {% endif %}
                                                        {% if (tag.name == "see") %}
                                                            {{ tag.reference|route|raw }}
                                                        {% endif %}
                                                        {{ tag.description|markdown|raw }}
                                                    {% endfor %}
                                                </td>
                                            </tr>
                                        {% endfor %}
                                    </table>

                                    {% if method.arguments|length > 0 %}
                                        <h3>Arguments</h3>
                                        {% for argument in method.arguments %}
                                            <div class="subelement argument">
                                                <h4>{{ argument.name }}</h4>
                                                <code>{{ argument.types|route|join('|')|raw }}</code><p>{{ argument.description|markdown|raw }}</p>
                                            </div>
                                        {% endfor %}
                                    {% endif %}

                                    {% if method.response.types and method.response.types|join() != 'void' %}
                                        <h3>Response</h3>
                                        <code>{{ method.response.types|route|join('|')|raw }}</code><p>{{ method.response.description|markdown|raw }}</p>
                                    {% endif %}
                                </div>
                            </div>
                        </div>
                    {% endfor %}

                    {% if node.constants.merge(node.inheritedConstants)|length > 0 %}
                        <h3><i class="icon-custom icon-constant"></i> Constants</h3>
                        {% for constant in node.constants.merge(node.inheritedConstants) %}
                            <a id="constant_{{ constant.name }}"> </a>
                            <div class="element clickable constant {{ constant.deprecated ? 'deprecated' }} constant_{{ constant.name }}{{ constant.parent.name != node.name ? ' inherited' : '' }}" data-toggle="collapse" data-target=".constant_{{ constant.name }} .collapse">
                                <h2>{{ constant.summary ?: constant.name }}</h2>
                                <pre>{{ constant.name }}</pre>
                                <div class="labels">
                                    {% if constant.parent.name != node.name %}<span class="label">inherited</span>{% endif %}
                                </div>
                                <div class="row collapse">
                                    <div class="detail-description">
                                        <div class="long_description">{{ constant.description|markdown|raw }}</div>
                                        <table class="table">
                                            {% for tagList in constant.tags %}
                                                <tr>
                                                    <th>
                                                        {{ tagList.0.name }}
                                                    </th>
                                                    <td>
                                                        {% for tag in tagList %}
                                                            {{ tag.description|markdown|raw }}
                                                        {% endfor %}
                                                    </td>
                                                </tr>
                                            {% endfor %}
                                        </table>
                                    </div>
                                </div>
                            </div>
                        {% endfor %}
                    {% endif %}

                    {% set specialProperties = node.magicProperties ? node.inheritedProperties.merge(node.magicProperties) : node.inheritedProperties %}
                    {% if node.properties.merge(specialProperties)|length > 0 %}
                        <h3><i class="icon-custom icon-property"></i> Properties</h3>
                        {% for property in node.properties.merge(specialProperties) %}
                            <a id="property_{{ property.name }}"> </a>
                            <div class="element clickable property {{ property.deprecated ? 'deprecated' }} {{ property.visibility }} property_{{ property.name }}{{ property.parent.name != node.name ? ' inherited' : '' }}" data-toggle="collapse" data-target=".property_{{ property.name }} .collapse">
                                <h2>{{ property.summary ?: property.var.0.description ?: property.name }}</h2>
                                <pre>{{ property.name }} : {{ property.types|join('|') }}</pre>
                                <div class="labels">
                                    {% if property.parent.name != node.name %}<span class="label">inherited</span>{% endif %}
                                    {% if property.static %}<span class="label">static</span>{% endif %}
                                </div>
                                <div class="row collapse">
                                    <div class="detail-description">
                                        <div class="long_description">{{ property.description|markdown|raw }}</div>

                                        <table class="table">
                                            {% for tagList in property.tags %}
                                                <tr>
                                                    <th>
                                                        {{ tagList.0.name }}
                                                    </th>
                                                    <td>
                                                        {% for tag in tagList %}
                                                            {{ tag.description|markdown|raw }}
                                                        {% endfor %}
                                                    </td>
                                                </tr>
                                            {% endfor %}
                                        </table>

                                        {% if property.types and property.types|join() != 'void' %}
                                            <h3>Type(s)</h3>
                                            <code>{{ property.types|route|join('|')|raw }}</code>
                                        {% endif %}
                                    </div>
                                </div>
                            </div>
                        {% endfor %}
                    {% endif %}
                </div>
            </div>
            <a id="{{ node.fullyQualifiedStructuralElementName }}"></a>
            <ul class="breadcrumb">
                <li><a href="{{ path('index.html') }}"><i class="icon-custom icon-class"></i></a></li>
                {{ macros.buildBreadcrumb(node.namespace) }}
                <li class="active"><span class="divider">\</span><a href="{{ path(node) }}">{{ node.name }}</a></li>
            </ul>
        </div>
    </div>

{% endblock %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
    <meta charset="utf-8"/>
    <title>{% block title %}{{ project.name }}{% endblock %}</title>
    <meta name="author" content="{{ author }}"/>
    <meta name="description" content=""/>

    {% block stylesheets %}
        <link href="{{ path('css/template.css') }}" rel="stylesheet" media="all"/>
    {% endblock %}

    {% block javascripts %}
        <!--[if lt IE 9]>
        <script src="http://html5shim.googlecode.com/svn/trunk/html5.js" type="text/javascript"></script>
        <![endif]-->
        <script src="{{ path('js/jquery-1.7.1.min.js') }}" type="text/javascript"></script>
        <script src="{{ path('js/jquery-ui-1.8.2.custom.min.js') }}" type="text/javascript"></script>
        <script src="{{ path('js/jquery.mousewheel.min.js') }}" type="text/javascript"></script>
        <script src="{{ path('js/bootstrap.js') }}" type="text/javascript"></script>
        <script src="{{ path('js/template.js') }}" type="text/javascript"></script>
        <script src="{{ path('js/prettify/prettify.min.js') }}" type="text/javascript"></script>
    {% endblock %}

    {% block icons %}
        <link rel="shortcut icon" href="{{ path('img/favicon.ico') }}"/>
        <link rel="apple-touch-icon" href="{{ path('img/apple-touch-icon.png') }}"/>
        <link rel="apple-touch-icon" sizes="72x72" href="{{ path('img/apple-touch-icon-72x72.png') }}"/>
        <link rel="apple-touch-icon" sizes="114x114" href="{{ path('img/apple-touch-icon-114x114.png') }}"/>
    {% endblock %}
</head>
<body>

    {% block header %}
    <div class="navbar navbar-fixed-top">
        <div class="navbar-inner">
            <div class="container">
                <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
                    <span class="icon-bar"></span> <span class="icon-bar"></span>
                    <span class="icon-bar"></span> </a>
                <a class="brand" href="{{ path('index.html') }}">{{ project.name }}</a>

                <div class="nav-collapse">
                    <ul class="nav">
                        <li class="dropdown">
                            <a href="#api" class="dropdown-toggle" data-toggle="dropdown">
                                API Documentation <b class="caret"></b>
                            </a>
                            <ul class="dropdown-menu">
                                {% if (project.namespace.children|length > 0) %}
                                    <li><a>Namespaces</a></li>
                                    {% for namespace in project.namespace.children %}
                                    <li><a href="{{ path(namespace) }}">{{ namespace.name }}</a></li>
                                    {% endfor %}
                                {% endif %}
                                {% if (project.index.packages|length > 0) %}
                                    <li><a>Packages</a></li>
                                {% endif %}
                            </ul>
                        </li>
                        <li class="dropdown" id="charts-menu">
                            <a href="#charts" class="dropdown-toggle" data-toggle="dropdown">
                                Charts <b class="caret"></b>
                            </a>
                            <ul class="dropdown-menu">
                                <li>
                                    <a href="{{ path('graph_class.html') }}">
                                        <i class="icon-list-alt"></i>&#160;Class hierarchy diagram
                                    </a>
                                </li>
                            </ul>
                        </li>
                        <li class="dropdown" id="reports-menu">
                            <a href="#reports" class="dropdown-toggle" data-toggle="dropdown">
                                Reports <b class="caret"></b>
                            </a>
                            <ul class="dropdown-menu">
                                <li>
                                    <a href="{{ path('errors.html') }}">
                                        <i class="icon-list-alt"></i>&#160;Errors
                                    </a>
                                </li>
                                <li>
                                    <a href="{{ path('markers.html') }}">
                                        <i class="icon-list-alt"></i>&#160;Markers
                                    </a>
                                </li>
                                <li>
                                    <a href="{{ path('deprecated.html') }}">
                                        <i class="icon-list-alt"></i>&#160;Deprecated
                                    </a>
                                </li>
                            </ul>
                        </li>
                    </ul>
                </div>
            </div>
        </div>
        <div class="go_to_top">
            <a href="#___" style="color: inherit">Back to top&#160;&#160;<i class="icon-upload icon-white"></i></a>
        </div>
    </div>
    {% endblock header %}

    <div id="___" class="container">
        <noscript>
            <div class="alert alert-warning">
                Javascript is disabled; several features are only available if Javascript is enabled.
            </div>
        </noscript>

        {% block heroUnit %}{% endblock %}

        {% block content %}{% endblock %}
    </div>

    {% block footer %}
    <footer class="span12">
            Template is built using <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap 2</a> and icons provided by
            <a href="http://glyphicons.com/">Glyphicons</a>.<br/>
            Documentation is powered by <a href="http://www.phpdoc.org/">phpDocumentor {{ version }}</a> and<br/>
            generated on {{ now|date("r") }}.<br/>
    </footer>
    {% endblock %}
</body>
</html>
<?xml version="1.0" encoding="UTF-8" ?>
<phpdocumentor>
    <parser>
        <default-package-name>Default</default-package-name>
        <encoding>utf-8</encoding>
        <target>output/build</target>
        <markers>
            <item>TODO</item>
            <item>FIXME</item>
        </markers>
        <extensions>
            <extension>php</extension>
            <extension>php3</extension>
            <extension>phtml</extension>
        </extensions>
        <visibility></visibility>
    </parser>
    <files>
        <ignore-hidden>on</ignore-hidden>
        <ignore-symlinks>on</ignore-symlinks>
    </files>
    <transformer>
        <target>output</target>
    </transformer>
    <logging>
        <level>error</level>
    </logging>
    <transformations>
        <template name="clean"/>
    </transformations>
</phpdocumentor>
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace Cilex\Provider;

use Cilex\Application;
use Cilex\ServiceProviderInterface;
use Symfony\Component\Validator\ConstraintValidatorFactory;
use Symfony\Component\Validator\DefaultTranslator;
use Symfony\Component\Validator\Mapping\ClassMetadataFactory;
use Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader;
use Symfony\Component\Validator\Validator;

/**
 * Cilex Service Provider to provide validation services.
 *
 * @link https://github.com/fabpot/Silex/blob/master/src/Silex/Provider/ValidatorServiceProvider.php Inspired by the
 *     Silex Service Provider, written by Fabien Potencier.
 */
class ValidatorServiceProvider implements ServiceProviderInterface
{
    /**
     * Registers services on the given app.
     *
     * @param Application $app An Application instance
     */
    public function register(Application $app)
    {
        $app['validator'] = $app->share(
            function ($app) {
                return new Validator(
                    $app['validator.mapping.class_metadata_factory'],
                    $app['validator.validator_factory'],
                    isset($app['translator']) ? $app['translator'] : new DefaultTranslator()
                );
            }
        );

        $app['validator.mapping.class_metadata_factory'] = $app->share(
            function () {
                return new ClassMetadataFactory(new StaticMethodLoader());
            }
        );

        $app['validator.validator_factory'] = $app->share(
            function () use ($app) {
                $validators = isset($app['validator.validator_service_ids'])
                    ? $app['validator.validator_service_ids']
                    : array();

                return new ConstraintValidatorFactory($app, $validators);
            }
        );
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Event;

use Symfony\Component\EventDispatcher as Symfony;
use Symfony\Component\EventDispatcher\Event;

/**
 * Event Dispatching class.
 *
 * This class provides a bridge to the Symfony2 EventDispatcher.
 * At current this is provided by inheritance but future iterations should
 * solve this by making it an adapter pattern.
 *
 * The class is implemented as (mockable) Singleton as this was the best
 * solution to make the functionality available in every class of the project.
 */
class Dispatcher extends Symfony\EventDispatcher
{
    /** @var Dispatcher[] Keep track of an array of instances. */
    protected static $instances = array();

    /**
     * Override constructor to make this singleton.
     * @codeCoverageIgnore For some reason
     */
    protected function __construct()
    {
    }

    /**
     * Returns a named instance of the Event Dispatcher.
     *
     * @param string $name
     *
     * @return Dispatcher
     */
    public static function getInstance($name = 'default')
    {
        if (!isset(self::$instances[$name])) {
            self::setInstance($name, new self());
        }

        return self::$instances[$name];
    }

    /**
     * Sets a names instance of the Event Dispatcher.
     *
     * @param string     $name
     * @param Dispatcher $instance
     *
     * @return void
     */
    public static function setInstance($name, self $instance)
    {
        self::$instances[$name] = $instance;
    }

    /**
     * Dispatches an event.
     *
     * Please note that the typehint of this method indicates a Symfony Event
     * and this DocBlock a phpDocumentor event. This is because of inheritance
     * and that the dispatch signature must remain intact.
     *
     * @param string $eventName
     * @param Event  $event
     *
     * @codeCoverageIgnore Untestable and not really necessary
     *
     * @return EventAbstract
     */
    public function dispatch($eventName, Event $event = null)
    {
        return parent::dispatch($eventName, $event);
    }

    /**
     * Adds a callable that will listen on the named event.
     *
     * @param string   $eventName
     * @param callable $listener
     * @param int      $priority
     *
     * @codeCoverageIgnore Untestable and not really necessary
     *
     * @return void
     */
    public function addListener($eventName, $listener, $priority = 0)
    {
        parent::addListener($eventName, $listener, $priority);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Event;

use phpDocumentor\Event\EventAbstract;
use Psr\Log\LogLevel;

/**
 * Event representing some debugging information for phpDocumentor.
 *
 * The information logged by this event will only be visible if the verbose
 * option is provided to phpDocumentor.
 */
class DebugEvent extends EventAbstract
{
    /** @var string Message to display with the debugging event */
    protected $message;

    /** @var int Default priority level for these events is DEBUG */
    protected $priority = LogLevel::DEBUG;

    /** @var string[] Extra parameters to insert into the message after translation */
    protected $context = array();

    /**
     * Provides the message that is to be shown with this event.
     *
     * @param string $message
     *
     * @return DebugEvent
     */
    public function setMessage($message)
    {
        $this->message = $message;

        return $this;
    }

    /**
     * Returns the message that was provided with this event.
     *
     * @return string
     */
    public function getMessage()
    {
        return $this->message;
    }

    /**
     * Returns the priority level associated with this logging event.
     *
     * @return int
     */
    public function getPriority()
    {
        return $this->priority;
    }

    /**
     * Sets additional context (parameters) to use when translating messages.
     *
     * @param string[] $context
     *
     * @return self
     */
    public function setContext(array $context)
    {
        $this->context = $context;

        return $this;
    }

    /**
     * Returns the context for this event.
     *
     * @return string[]
     */
    public function getContext()
    {
        return $this->context;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Event;

use Symfony\Component\EventDispatcher\Event;

/**
 * Abstract class representing the base elements of a phpDocumentor event.
 */
abstract class EventAbstract extends Event
{
    /** @var object Represents an object that is the subject of this event */
    protected $subject;

    /**
     * Initializes this event with the given subject.
     *
     * @param object $subject
     */
    public function __construct($subject)
    {
        $this->subject = $subject;
    }

    /**
     * Returns the object that is the subject of this event.
     *
     * @return object
     */
    public function getSubject()
    {
        return $this->subject;
    }

    /**
     * Creates a new instance of a derived object and return that.
     *
     * Used as convenience method for fluent interfaces.
     *
     * @param object $subject
     *
     * @return EventAbstract
     */
    public static function createInstance($subject)
    {
        return new static($subject);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Event;

use Psr\Log\LogLevel;

/**
 * Logging event for phpDocumentor where information is output to the log or
 * stdout.
 */
class LogEvent extends DebugEvent
{
    /** @var int Default priority level for these events is INFO */
    protected $priority = LogLevel::INFO;

    /**
     * Set the priority level for this event.
     *
     * @param int $priority
     *
     * @see LogLevel for the constants used in determining the logging levels.
     *
     * @return LogEvent
     */
    public function setPriority($priority)
    {
        $this->priority = $priority;

        return $this;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius. (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Command;

use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Zend\Config\Config;
use Zend\Config\Factory;

/**
 * Base class for commands that may make use of the configuration.
 *
 * Provides helper methods and a default argument to work with the configuration
 * files.
 */
class ConfigurableCommand extends Command
{
    /**
     * Add an option 'config' for all children.
     *
     * @return void
     */
    protected function configure()
    {
        $this->addOption(
            'config',
            'c',
            InputOption::VALUE_OPTIONAL,
            'Location of a custom configuration file'
        );

        parent::configure();
    }

    /**
     * Overwrite execute to override the default config file.
     *
     * If an alternative configuration file is provided we override the 'config'
     * element in the Dependency Injection Container with a new instance. This
     * new instance uses the phpdoc.tpl.xml as base configuration and applies
     * the given configuration on top of it.
     *
     * Also, upon providing a custom configuration file, is the current working
     * directory set to the directory containing the configuration file so that
     * all relative paths for directory and file selections (and more) is based
     * on that location.
     *
     * @param InputInterface  $input
     * @param OutputInterface $output
     *
     * @return void
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $configFile = $input->getOption('config');

        if ($configFile && $configFile !== 'none') {
            $configFile = realpath($configFile);

            // all relative paths mentioned in the configuration file should
            // be relative to the configuration file.
            // This means that if we provide an alternate configuration file
            // that we need to go to that directory first so that paths can be
            // calculated from there.
            chdir(dirname($configFile));
        }

        $container = $this->getContainer();
        if ($configFile) {
            $container['config'] = $container->share(
                function () use ($configFile) {
                    $files = array(__DIR__ . '/../../../data/phpdoc.tpl.xml');
                    if ($configFile !== 'none') {
                        $files[] = $configFile;
                    }

                    return Factory::fromFiles($files, true);
                }
            );
        }

        $this->getHelper('phpdocumentor_logger')->reconfigureLogger($input, $output, $this);
    }

    /**
     * Returns the value of an option from the command-line parameters,
     * configuration or given default.
     *
     * @param InputInterface $input           Input interface to query for
     *     information
     * @param string         $name            Name of the option to retrieve
     *     from argv
     * @param string|null    $config_path     Path to the config element(s)
     *     containing the value to be used when no option is provided.
     * @param mixed|null     $default         Default value used if there is no
     *     configuration option or path set
     * @param bool           $comma_separated Could the value be a comma
     *     separated string requiring splitting
     *
     * @return string
     */
    public function getOption(
        InputInterface $input,
        $name,
        $config_path = null,
        $default = null,
        $comma_separated = false
    ) {
        $value = $input->getOption($name);

        // find value in config
        if (($value === null || is_array($value) && empty($value))
            && $config_path !== null
        ) {
            $value = $this->getConfigValueFromPath($config_path);
            if ($value === null) {
                return $default;
            }
        }

        // use default if value is still null
        if ($value === null || is_array($value) && empty($value)) {
            return (is_array($value) && $default === null)
                ? array()
                : $default;
        }

        // split comma separated values
        if ($comma_separated
            && (!is_array($value)
                || (count($value) == 1) && is_string(current($value))
            )
        ) {
            $value = (array) $value;
            $value = explode(',', $value[0]);
        }

        return $value;
    }

    /**
     * Returns a value by traversing the configuration tree as if it was a file
     * path.
     *
     * @param string $path Path to the config value separated by '/'.
     *
     * @return Config
     */
    protected function getConfigValueFromPath($path)
    {
        /** @var Config $node  */
        $node = $this->getService('config');

        foreach (explode('/', $path) as $node_name) {
            // premature end of the cycle
            if (!is_object($node)) {
                return null;
            }

            $node = $node->get($node_name);
        }

        if ($node === null) {
            return null;
        }

        return $node instanceof Config
            ? $node->toArray()
            : trim((string)$node);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius. (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Command;

use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Helper\ProgressHelper;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * Base command for phpDocumentor commands.
 *
 * Includes additional methods to forward the output to the logging events
 * of phpDocumentor.
 */
class Command extends \Cilex\Command\Command
{
    public function setHelperSet(HelperSet $helperSet)
    {
        parent::setHelperSet($helperSet);

        $this->getHelper('phpdocumentor_logger')->addOptions($this);
    }

    /**
     * Returns boolean based on whether given path is absolute or not.
     *
     * @param string $path Given path
     *
     * @author Michael Wallner <mike@php.net>
     *
     * @link http://pear.php.net/package/File_Util/docs/latest/File/File_Util/File_Util.html#methodisAbsolute
     *
     * @todo consider moving this method to a more logical place
     *
     * @return boolean True if the path is absolute, false if it is not
     */
    protected function isAbsolute($path)
    {
        if (preg_match('/(?:\/|\\\)\.\.(?=\/|$)/', $path)) {
            return false;
        }

        // windows detection
        if (defined('OS_WINDOWS') ? OS_WINDOWS : !strncasecmp(PHP_OS, 'win', 3)) {
            return (($path[0] == '/') || preg_match('/^[a-zA-Z]:(\\\|\/)/', $path));
        }

        return ($path[0] == '/') || ($path[0] == '~');
    }

    /**
     * Returns the Progress bar helper.
     *
     * With this helper it is possible to display a progress bar and make it fill.
     *
     * @param InputInterface $input
     *
     * @return ProgressHelper
     */
    protected function getProgressBar(InputInterface $input)
    {
        if (!$input->getOption('progressbar')) {
            return null;
        }

        return $this->getHelperSet()->get('progress');
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Command\Project;

use phpDocumentor\Command\ConfigurableCommand;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * Parse and transform the given directory (-d|-f) to the given location (-t).
 *
 * phpDocumentor creates documentation from PHP source files. The simplest way
 * to use it is:
 *
 *     $ phpdoc run -d <directory to parse> -t <output directory>
 *
 * This will parse every file ending with .php, .php3 and .phtml in <directory
 * to parse> and then output a HTML site containing easily readable documentation
 * in <output directory>.
 *
 * phpDocumentor will try to look for a phpdoc.dist.xml or phpdoc.xml file in your
 * current working directory and use that to override the default settings if
 * present. In the configuration file can you specify the same settings (and
 * more) as the command line provides.
 */
class RunCommand extends ConfigurableCommand
{
    /**
     * Initializes this command and sets the name, description, options and
     * arguments.
     *
     * @return void
     */
    protected function configure()
    {
        $this->setName('project:run')
            ->setAliases(array('run'))
            ->setDescription(
                'Parses and transforms the given files to a specified location'
            )
            ->setHelp(
<<<HELP
phpDocumentor creates documentation from PHP source files. The simplest way
to use it is:

    <info>$ phpdoc run -d [directory to parse] -t [output directory]</info>

This will parse every file ending with .php, .php3 and .phtml in <directory
to parse> and then output a HTML site containing easily readable documentation
in <output directory>.

phpDocumentor will try to look for a phpdoc.dist.xml or phpdoc.xml file in your
current working directory and use that to override the default settings if
present. In the configuration file can you specify the same settings (and
more) as the command line provides.

<comment>Other commands</comment>
In addition to this command phpDocumentor also supports additional commands:

<comment>Available commands:</comment>
<info>  help
  list
  parse
  run
  transform
<comment>project</comment>
  project:parse
  project:run
  project:transform
<comment>template</comment>
  template:generate
  template:list
  template:package</info>

You can get a more detailed listing of the commands using the <info>list</info>
command and get help by prepending the word <info>help</info> to the command
name.
HELP
            )
            ->addOption(
                'target',
                't',
                InputOption::VALUE_OPTIONAL,
                'Path where to store the generated output'
            )
            ->addOption(
                'filename',
                'f',
                InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
                'Comma-separated list of files to parse. The wildcards ? and * are supported'
            )
            ->addOption(
                'directory',
                'd',
                InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
                'Comma-separated list of directories to (recursively) parse'
            )
            ->addOption(
                'encoding',
                null,
                InputOption::VALUE_OPTIONAL,
                'encoding to be used to interpret source files with'
            )
            ->addOption(
                'extensions',
                'e',
                InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
                'Comma-separated list of extensions to parse, defaults to php, php3 and phtml'
            )
            ->addOption(
                'ignore',
                'i',
                InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
                'Comma-separated list of file(s) and directories that will be ignored. Wildcards * and ? are supported'
            )
            ->addOption(
                'ignore-tags',
                null,
                InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
                'Comma-separated list of tags that will be ignored, defaults to none. package, subpackage and ignore '
                . 'may not be ignored.'
            )
            ->addOption(
                'hidden',
                null,
                InputOption::VALUE_NONE,
                'set to on to descend into hidden directories (directories starting with \'.\'), default is on'
            )
            ->addOption(
                'ignore-symlinks',
                null,
                InputOption::VALUE_NONE,
                'Ignore symlinks to other files or directories, default is on'
            )
            ->addOption(
                'markers',
                'm',
                InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
                'Comma-separated list of markers/tags to filter'
            )
            ->addOption(
                'title',
                null,
                InputOption::VALUE_OPTIONAL,
                'Sets the title for this project; default is the phpDocumentor logo'
            )
            ->addOption(
                'force',
                null,
                InputOption::VALUE_NONE,
                'Forces a full build of the documentation, does not increment existing documentation'
            )
            ->addOption(
                'validate',
                null,
                InputOption::VALUE_NONE,
                'Validates every processed file using PHP Lint, costs a lot of performance'
            )
            ->addOption(
                'visibility',
                null,
                InputOption::VALUE_OPTIONAL,
                'Specifies the parse visibility that should be displayed in the documentation (comma separated e.g. '
                . '"public,protected")'
            )
            ->addOption(
                'defaultpackagename',
                null,
                InputOption::VALUE_OPTIONAL,
                'Name to use for the default package.',
                'Default'
            )
            ->addOption(
                'sourcecode',
                null,
                InputOption::VALUE_NONE,
                'Whether to include syntax highlighted source code'
            )
            ->addOption(
                'progressbar',
                'p',
                InputOption::VALUE_NONE,
                'Whether to show a progress bar; will automatically quiet logging to stdout'
            )
            ->addOption(
                'template',
                null,
                InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
                'Name of the template to use (optional)'
            )
            ->addOption(
                'parseprivate',
                null,
                InputOption::VALUE_NONE,
                'Whether to parse DocBlocks marked with @internal tag'
            );

        parent::configure();
    }

    /**
     * Executes the business logic involved with this command.
     *
     * @param \Symfony\Component\Console\Input\InputInterface   $input
     * @param \Symfony\Component\Console\Output\OutputInterface $output
     *
     * @return int
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        parent::execute($input, $output);

        $parse_command     = $this->getApplication()->find('project:parse');
        $transform_command = $this->getApplication()->find('project:transform');

        $parse_input = new ArrayInput(
            array(
                 'command'              => 'project:parse',
                 '--filename'           => $input->getOption('filename'),
                 '--directory'          => $input->getOption('directory'),
                 '--encoding'           => $input->getOption('encoding'),
                 '--extensions'         => $input->getOption('extensions'),
                 '--ignore'             => $input->getOption('ignore'),
                 '--ignore-tags'        => $input->getOption('ignore-tags'),
                 '--hidden'             => $input->getOption('hidden'),
                 '--ignore-symlinks'    => $input->getOption('ignore-symlinks'),
                 '--markers'            => $input->getOption('markers'),
                 '--title'              => $input->getOption('title'),
                 '--target'             => $input->getOption('target'),
                 '--force'              => $input->getOption('force'),
                 '--validate'           => $input->getOption('validate'),
                 '--visibility'         => $input->getOption('visibility'),
                 '--defaultpackagename' => $input->getOption('defaultpackagename'),
                 '--sourcecode'         => $input->getOption('sourcecode'),
                 '--parseprivate'       => $input->getOption('parseprivate'),
                 '--progressbar'        => $input->getOption('progressbar'),
                 '--log'                => $input->getOption('log')
            ),
            $this->getDefinition()
        );

        $return_code = $parse_command->run($parse_input, $output);
        if ($return_code !== 0) {
            return $return_code;
        }

        $transform_input = new ArrayInput(
            array(
                 'command'       => 'project:transform',
                 '--source'      => $input->getOption('target'),
                 '--target'      => $input->getOption('target'),
                 '--template'    => $input->getOption('template'),
                 '--progressbar' => $input->getOption('progressbar'),
                 '--log'         => $input->getOption('log')
            )
        );
        $return_code = $transform_command->run($transform_input, $output);
        if ($return_code !== 0) {
            return $return_code;
        }

        return 0;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Command\Helper;

use Monolog\Logger;
use phpDocumentor\Command\Command;
use phpDocumentor\Event\Dispatcher;
use phpDocumentor\Event\LogEvent;
use phpDocumentor\Parser\Event\PreFileEvent;
use phpDocumentor\Translator;
use Psr\Log\LogLevel;
use Symfony\Component\Console\Helper\Helper;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

class LoggerHelper extends Helper
{

    /**
     * Initializes the given command to accept logging options.
     *
     * This method is intended to be executed once in the Constructor of the given Command as it
     * adds a new option `log`.
     *
     * @param Command $command
     * @return void
     */
    public function addOptions($command)
    {
        $command->addOption('log', null, InputOption::VALUE_OPTIONAL, 'Log file to write to');
    }

    /**
     * Returns the canonical name of this helper.
     *
     * @return string The canonical name
     *
     * @api
     */
    public function getName()
    {
        return 'phpdocumentor_logger';
    }

    /**
     * Connect the logging events to the output object of Symfony Console.
     *
     * @param OutputInterface $output
     * @param Command $command
     *
     * @return void
     */
    public function connectOutputToLogging(OutputInterface $output, $command)
    {
        static $alreadyConnected = false;
        $helper = $this;

        // ignore any second or later invocations of this method
        if ($alreadyConnected) {
            return;
        }

        /** @var Dispatcher $eventDispatcher  */
        $eventDispatcher = $command->getService('event_dispatcher');

        $eventDispatcher->addListener(
            'parser.file.pre',
            function (PreFileEvent $event) use ($output) {
                $output->writeln('Parsing <info>'.$event->getFile().'</info>');
            }
        );

        $eventDispatcher->addListener(
            'system.log',
            function (LogEvent $event) use ($command, $helper, $output) {
                $helper->logEvent($output, $event, $command);
            }
        );

        $alreadyConnected = true;
    }

    /**
     * Logs an event with the output.
     *
     * This method will also colorize the message based on priority and withhold
     * certain logging in case of verbosity or not.
     *
     * @param OutputInterface $output
     * @param LogEvent        $event
     * @param Command         $command
     *
     * @return void
     */
    public function logEvent(OutputInterface $output, LogEvent $event, Command $command)
    {
        $numericErrors = array(
            LogLevel::DEBUG     => 0,
            LogLevel::NOTICE    => 1,
            LogLevel::INFO      => 2,
            LogLevel::WARNING   => 3,
            LogLevel::ERROR     => 4,
            LogLevel::ALERT     => 5,
            LogLevel::CRITICAL  => 6,
            LogLevel::EMERGENCY => 7,
        );

        $threshold = LogLevel::ERROR;
        if ($output->getVerbosity() === OutputInterface::VERBOSITY_DEBUG) {
            $threshold = LogLevel::DEBUG;
        }

        if ($numericErrors[$event->getPriority()] >= $numericErrors[$threshold]) {
            /** @var Translator $translator  */
            $translator = $command->getContainer()->offsetGet('translator');
            $message    = vsprintf($translator->translate($event->getMessage()), $event->getContext());

            switch ($event->getPriority()) {
                case LogLevel::WARNING:
                    $message = '<comment>' . $message . '</comment>';
                    break;
                case LogLevel::EMERGENCY:
                case LogLevel::ALERT:
                case LogLevel::CRITICAL:
                case LogLevel::ERROR:
                    $message = '<error>' . $message . '</error>';
                    break;
            }
            $output->writeln('  ' . $message);
        }
    }

    public function reconfigureLogger(InputInterface $input, OutputInterface $output, $command)
    {
        $logPath = $input->getOption('log');

        switch ($output->getVerbosity()) {
            case OutputInterface::VERBOSITY_VERBOSE:
                $logLevel = Logger::WARNING;
                break;
            case OutputInterface::VERBOSITY_VERY_VERBOSE:
                $logLevel = Logger::INFO;
                break;
            case OutputInterface::VERBOSITY_DEBUG:
                $logLevel = Logger::DEBUG;
                break;
            default:
                $logLevel = Logger::ERROR;
        }

        $container = $command->getContainer();
        if (isset($container['config']->logging)) {
            if ($output->getVerbosity() == OutputInterface::VERBOSITY_NORMAL) {
                $logLevel = (string)$container['config']->logging->level;
            }

            // null means the default is used
            if (!$logPath) {
                $logPath = isset($container['config']->logging->paths->default)
                    ? (string) $container['config']->logging->paths->default
                    : null;
            }
        }

        $container->configureLogger($container['monolog'], $logLevel, $logPath);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor;

use Cilex\Application as Cilex;
use Cilex\Provider\MonologServiceProvider;
use Cilex\Provider\ValidatorServiceProvider;
use Doctrine\Common\Annotations\AnnotationRegistry;
use JMS\Serializer\SerializerBuilder;
use Monolog\ErrorHandler;
use Monolog\Handler\NullHandler;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use phpDocumentor\Command\Helper\LoggerHelper;
use phpDocumentor\Console\Input\ArgvInput;
use phpDocumentor\Transformer\Writer\Exception\RequirementMissing;
use Symfony\Component\Console\Application as ConsoleApplication;
use Symfony\Component\Console\Helper\ProgressHelper;
use Symfony\Component\Console\Shell;
use Symfony\Component\Stopwatch\Stopwatch;
use Zend\Config\Factory;

/**
 * Finds and activates the autoloader.
 */
require_once findAutoloader();

/**
 * Application class for phpDocumentor.
 *
 * Can be used as bootstrap when the run method is not invoked.
 */
class Application extends Cilex
{
    /** @var string $VERSION represents the version of phpDocumentor as stored in /VERSION */
    public static $VERSION;

    /**
     * Initializes all components used by phpDocumentor.
     */
    public function __construct()
    {
        ini_set('memory_limit', -1);

        self::$VERSION = file_get_contents(__DIR__ . '/../../VERSION');

        parent::__construct('phpDocumentor', self::$VERSION);

        $this['kernel.timer.start'] = time();
        $this['kernel.stopwatch'] = function () {
            return new Stopwatch();
        };

        $this->setTimezone();
        $this->addAutoloader();
        $this->addConfiguration();
        $this->addLogging();
        $this->addEventDispatcher();
        $this->addTranslator();

        /** @var ConsoleApplication $console */
        $console = $this['console'];
        $console->getHelperSet()->set(new LoggerHelper());

        $this->addSerializer();

        $this->register(new ValidatorServiceProvider());
        $this->register(new Descriptor\ServiceProvider());
        $this->register(new Parser\ServiceProvider());
        $this->register(new Transformer\ServiceProvider());

        // TODO: make plugin service provider calls registrable from config
        $this->register(new Plugin\Core\ServiceProvider());

        $this->verifyWriterRequirementsAndExitIfBroken();
        $this->addCommandsForProjectNamespace();
    }

    /**
     * If the timezone is not set anywhere, set it to UTC.
     *
     * This is done to prevent any warnings being outputted in relation to using
     * date/time functions. What is checked is php.ini, and if the PHP version
     * is prior to 5.4, the TZ environment variable.
     *
     * @return void
     */
    public function setTimezone()
    {
        if (false === ini_get('date.timezone') || (version_compare(phpversion(), '5.4.0', '<')
            && false === getenv('TZ'))
        ) {
            date_default_timezone_set('UTC');
        }
    }

    /**
     * Instantiates the autoloader and adds it to phpDocumentor's container.
     *
     * @return void
     */
    protected function addAutoloader()
    {
        $this['autoloader'] = include findAutoloader();
    }

    /**
     * Adds a logging provider to the container of phpDocumentor.
     *
     * @return void
     */
    protected function addLogging()
    {
        $this->register(
            new MonologServiceProvider(),
            array(
                 'monolog.name'      => 'phpDocumentor',
                 'monolog.logfile'   => sys_get_temp_dir() . '/phpdoc.log',
                 'monolog.debugfile' => sys_get_temp_dir() . '/phpdoc.debug.log',
                 'monolog.level'     => Logger::INFO,
            )
        );

        $app = $this;
        $this['monolog.configure'] = $this->protect(
            function ($log) use ($app) {
                $level = (string)$app['config']->logging->level;

                // null means the default is used
                $logPath = isset($app['config']->logging->paths->default)
                    ? (string) $app['config']->logging->paths->default
                    : null;

                // null means the default is used
                $debugPath = isset($app['config']->logging->paths->errors)
                    ? (string) $app['config']->logging->paths->errors
                    : null;

                $app->configureLogger($log, $level, $logPath, $debugPath);
            }
        );
        ErrorHandler::register($this['monolog']);
    }

    /**
     * Removes all logging handlers and replaces them with handlers that can write to the given logPath and level.
     *
     * @param Logger  $logger       The logger instance that needs to be configured.
     * @param integer $level        The minimum level that will be written to the normal logfile; matches one of the
     *                              constants in {@see \Monolog\Logger}.
     * @param string  $logPath      The full path where the normal log file needs to be written.
     *
     * @return void
     */
    public function configureLogger($logger, $level, $logPath = null)
    {
        /** @var Logger $monolog */
        $monolog = $logger;

        switch($level) {
            case 'emergency':
            case 'emerg':
                $level = Logger::EMERGENCY;
                break;
            case 'alert':
                $level = Logger::ALERT;
                break;
            case 'critical':
            case 'crit':
                $level = Logger::CRITICAL;
                break;
            case 'error':
            case 'err':
                $level = Logger::ERROR;
                break;
            case 'warning':
            case 'warn':
                $level = Logger::WARNING;
                break;
            case 'notice':
                $level = Logger::NOTICE;
                break;
            case 'info':
                $level = Logger::INFO;
                break;
            case 'debug':
                $level = Logger::DEBUG;
                break;
        }

        $this['monolog.level']   = $level;
        if ($logPath) {
            $logPath = str_replace(
                array('{APP_ROOT}', '{DATE}'),
                array(realpath(__DIR__.'/../..'), $this['kernel.timer.start']),
                $logPath
            );
            $this['monolog.logfile'] = $logPath;
        }

        // remove all handlers from the stack
        try {
            while ($monolog->popHandler()) {
            }
        } catch (\LogicException $e) {
            // popHandler throws an exception when you try to pop the empty stack; to us this is not an
            // error but an indication that the handler stack is empty.
        }

        if ($level === 'quiet') {
            $monolog->pushHandler(new NullHandler());
            return;
        }

        // set our new handlers
        if ($logPath) {
            $monolog->pushHandler(new StreamHandler($logPath, $level));
        } else {
            $monolog->pushHandler(new StreamHandler('php://stdout', $level));
        }
    }

    /**
     * Adds the Configuration object to the DIC.
     *
     * phpDocumentor first loads the template config file (/data/phpdoc.tpl.xml)
     * and then the phpdoc.dist.xml, or the phpdoc.xml if it exists but not both,
     * from the current working directory.
     *
     * The user config file (either phpdoc.dist.xml or phpdoc.xml) is merged
     * with the template file.
     *
     * @return void
     */
    protected function addConfiguration()
    {
        $this['config'] = $this->share(
            function () {
                $user_config_file = (file_exists(getcwd() . DIRECTORY_SEPARATOR . 'phpdoc.xml'))
                    ? getcwd() . DIRECTORY_SEPARATOR . 'phpdoc.xml'
                    : getcwd() . DIRECTORY_SEPARATOR . 'phpdoc.dist.xml';
                $config_files     = array(__DIR__ . '/../../data/phpdoc.tpl.xml');
                if (is_readable($user_config_file)) {
                    $config_files[] = $user_config_file;
                }

                return Factory::fromFiles($config_files, true);
            }
        );
    }

    /**
     * Adds the event dispatcher to phpDocumentor's container.
     *
     * @return void
     */
    protected function addEventDispatcher()
    {
        $this['event_dispatcher'] = $this->share(
            function () {
                return Event\Dispatcher::getInstance();
            }
        );
    }

    /**
     * Adds the message translator to phpDocumentor's container.
     *
     * @return void
     */
    protected function addTranslator()
    {
        $config = $this['config']->toArray();

        $this['translator.locale'] = isset($config['translator']['locale']) ? $config['translator']['locale'] : 'en';

        $this['translator'] = $this->share(
            function ($app) {
                $translator = new Translator();
                $translator->setLocale($app['translator.locale']);

                return $translator;
            }
        );
    }

    /**
     * Adds the command to phpDocumentor that belong to the Project namespace.
     *
     * @return void
     */
    protected function addCommandsForProjectNamespace()
    {
        $this->command(new Command\Project\RunCommand());
    }

    /**
     * Adds the serializer to the container
     *
     * @return void
     */
    protected function addSerializer()
    {
        $this['serializer'] = $this->share(
            function () {
                $serializerPath = __DIR__ . '/../../vendor/jms/serializer/src';

                if (!file_exists($serializerPath)) {
                    $serializerPath = __DIR__ . '/../../../../jms/serializer/src';
                }

                AnnotationRegistry::registerAutoloadNamespace(
                    'JMS\Serializer\Annotation',
                    $serializerPath
                );

                return SerializerBuilder::create()->build();
            }
        );
    }

    /**
     * Run the application and if no command is provided, use project:run.
     *
     * @param bool $interactive Whether to run in interactive mode.
     *
     * @return void
     */
    public function run($interactive = false)
    {
        /** @var ConsoleApplication $app  */
        $app = $this['console'];
        $app->setAutoExit(false);

        if ($interactive) {
            $app = new Shell($app);
        }

        $output = new Console\Output\Output();
        $output->setLogger($this['monolog']);

        $app->run(new ArgvInput(), $output);
    }

    protected function verifyWriterRequirementsAndExitIfBroken()
    {
        try {
            $this['transformer.writer.collection']->checkRequirements();
        } catch (RequirementMissing $e) {
            $this['monolog']->emerg(
                'phpDocumentor detected that a requirement is missing in your system setup: ' . $e->getMessage()
            );
            exit(1);
        }
    }
}

/**
 * Tries to find the autoloader relative to this file and return its path.
 *
 * @throws \RuntimeException if the autoloader could not be found.
 *
 * @return string the path of the autoloader.
 */
function findAutoloader()
{
    $autoloader_base_path = '/../../vendor/autoload.php';

    // if the file does not exist from a base path it is included as vendor
    $autoloader_location = file_exists(__DIR__ . $autoloader_base_path)
        ? __DIR__ . $autoloader_base_path
        : __DIR__ . '/../../..' . $autoloader_base_path;

    if (!file_exists($autoloader_location)) {
        throw new \RuntimeException(
            'Unable to find autoloader at ' . $autoloader_location
        );
    }

    return $autoloader_location;
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Partials;

/**
 * Model representing a piece of text that can be injected into a template and can be set in the configuration.
 */
class Partial
{
    protected $href;
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Partials;

use phpDocumentor\Descriptor\Collection as DescriptorCollection;

/**
 * Represents an easily accessible collection of partials.
 */
class Collection extends DescriptorCollection
{
    /** @var \Parsedown $parser */
    protected $parser = null;

    /**
     * Constructs a new collection object.
     *
     * @param \Parsedown $parser
     */
    public function __construct($parser)
    {
        $this->parser = $parser;
    }

    /**
     * Sets a new object onto the collection or clear it using null.
     *
     * @param string|integer $index An index value to recognize this item with.
     * @param string         $item  The item to store, generally a Descriptor but may be something else.
     *
     * @return void
     */
    public function set($index, $item)
    {
        $this->offsetSet($index, $this->parser->parse($item));
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor;

require_once __DIR__.'/Application.php';

/**
 * This class provides a bootstrap for all application who wish to interface
 * with phpDocumentor.
 *
 * The Bootstrapper is responsible for setting up the phpDocumentor application.
 */
class Bootstrap
{
    /**
     * Helper static function to get an instance of this class.
     *
     * Usually used to do a one-line initialization, such as:
     *
     *     \phpDocumentor\Bootstrap::createInstance()->initialize();
     *
     * @return Bootstrap
     */
    public static function createInstance()
    {
        return new self();
    }

    /**
     * Convenience method that does the complete initialization for phpDocumentor.
     *
     * This method will register the application.
     * The methods called can also be implemented separately, for example when
     * you want to use your own autoloader.
     *
     * @return Application
     */
    public function initialize()
    {
        return new Application();
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Compiler\Linker;

use phpDocumentor\Compiler\CompilerPassInterface;
use phpDocumentor\Descriptor\DescriptorAbstract;
use phpDocumentor\Descriptor\ProjectDescriptor;

/**
 * The linker contains all rules to replace FQSENs in the ProjectDescriptor with aliases to objects.
 *
 * This object contains a list of class FQCNs for Descriptors and their associated linker rules.
 *
 * An example scenario should be:
 *
 *     The Descriptor ``\phpDocumentor\Descriptor\ClassDescriptor`` has a *Substitute* rule determining that the
 *     contents of the ``Parent`` field should be substituted with another ClassDescriptor with the FQCN
 *     represented by the value of the Parent field. In addition (second element) it has an *Analyse* rule
 *     specifying that the contents of the ``Methods`` field should be interpreted by the linker. Because that field
 *     contains an array or Descriptor Collection will each element be analysed by the linker.
 *
 * As can be seen in the above example is it possible to analyse a tree structure and substitute FQSENs where
 * encountered.
 */
class Linker implements CompilerPassInterface
{
    const COMPILER_PRIORITY = 10000;

    /** @var DescriptorAbstract[] */
    protected $elementList = array();

    /** @var string[][] */
    protected $substitutions = array();

    /** @var string[] Prevent cycles by tracking which objects have been analyzed */
    protected $processedObjects = array();

    /**
     * {@inheritDoc}
     */
    public function getDescription()
    {
        return 'Replace textual FQCNs with object aliases';
    }

    /**
     * Initializes the linker with a series of Descriptors to link to.
     *
     * @param string[] $substitutions
     */
    public function __construct(array $substitutions)
    {
        $this->substitutions = $substitutions;
    }

    /**
     * Returns the list of substitutions for the linker.
     *
     * @return string[]
     */
    public function getSubstitutions()
    {
        return $this->substitutions;
    }

    /**
     * Sets the list of object aliases to resolve the FQSENs with.
     *
     * @param DescriptorAbstract[] $elementList
     *
     * @return void
     */
    public function setObjectAliasesList(array $elementList)
    {
        $this->elementList = $elementList;
    }

    /**
     * Attempts to find a Descriptor object alias with the FQSEN of the element it represents.
     *
     * @param string $fqsen
     *
     * @return DescriptorAbstract|null
     */
    public function findAlias($fqsen)
    {
        return isset($this->elementList[$fqsen]) ? $this->elementList[$fqsen] : null;
    }

    /**
     * Returns the value of a field in the given object.
     *
     * @param object $object
     * @param string $fieldName
     *
     * @return string|object
     */
    public function findFieldValue($object, $fieldName)
    {
        $getter = 'get'.ucfirst($fieldName);

        return $object->$getter();
    }

    /**
     * Substitutes the given item or its children's FQCN with an object alias.
     *
     * This method may do either of the following depending on the item's type
     *
     * String
     *     If the given item is a string then this method will attempt to find an appropriate Class, Interface or
     *     TraitDescriptor object and return that.
     *
     * Array or Traversable
     *     Iterate through each item, pass each key's contents to a new call to substitute and replace the key's
     *     contents if the contents is not an object (objects automatically update and saves performance).
     *
     * Object
     *     Determines all eligible substitutions using the substitutions property, construct a getter and retrieve
     *     the field's contents. Pass these contents to a new call of substitute and use a setter to replace the field's
     *     contents if anything other than null is returned.
     *
     * This method will return null if no substitution was possible and all of the above should not update the parent
     * item when null is passed.
     *
     * @param string|object|\Traversable|array $item
     *
     * @return null|string|DescriptorAbstract
     */
    public function substitute($item)
    {
        $result = null;

        if (is_string($item)) {
            $result = $this->findAlias($item);
        } elseif (is_array($item) || $item instanceof \Traversable) {
            $isModified = false;
            foreach ($item as $key => $element) {
                $isModified = true;

                $element = $this->substitute($element);
                if ($element !== null) {
                    $item[$key] = $element;
                }
            }
            if ($isModified) {
                $result = $item;
            }
        } elseif (is_object($item)) {
            $hash = spl_object_hash($item);
            if (isset($this->processedObjects[$hash])) {
                // if analyzed; just return
                return null;
            }
            $this->processedObjects[$hash] = true;

            $objectClassName = get_class($item);
            $fieldNames = isset($this->substitutions[$objectClassName])
                ? $this->substitutions[$objectClassName]
                : array();

            foreach ($fieldNames as $fieldName) {
                $fieldValue = $this->findFieldValue($item, $fieldName);
                $response = $this->substitute($fieldValue);

                // if the returned response is not an object it must be grafted on the calling object
                if ($response !== null) {
                    $setter = 'set'.ucfirst($fieldName);
                    $item->$setter($response);
                }
            }
        }

        return $result;
    }

    /**
     * Executes the linker.
     *
     * @param ProjectDescriptor $project Representation of the Object Graph that can be manipulated.
     *
     * @return void
     */
    public function execute(ProjectDescriptor $project)
    {
        $this->setObjectAliasesList($project->getIndexes()->elements->getAll());
        $this->substitute($project);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Compiler;

use phpDocumentor\Descriptor\ProjectDescriptor;

/**
 * Represents a single pass / business rule to be executed by the Compiler.
 */
interface CompilerPassInterface
{
    /**
     * Returns a textual description of what this pass does for output purposes.
     *
     * Please note that the command line will be truncated to 68 characters (<message> .. 000.000s) so longer
     * descriptions won't have much use.
     *
     * @return string
     */
    public function getDescription();

    /**
     * Executes a compiler pass.
     *
     * This method will execute the business logic associated with a given compiler pass and allow it to manipulate
     * or consumer the Object Graph using the ProjectDescriptor object.
     *
     * @param ProjectDescriptor $project Representation of the Object Graph that can be manipulated.
     *
     * @return mixed
     */
    public function execute(ProjectDescriptor $project);
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Compiler\Pass;

use phpDocumentor\Compiler\CompilerPassInterface;
use phpDocumentor\Descriptor\Collection;
use phpDocumentor\Descriptor\DescriptorAbstract;
use phpDocumentor\Descriptor\NamespaceDescriptor;
use phpDocumentor\Descriptor\ProjectDescriptor;

/**
 * Rebuilds the namespace tree from the elements found in files.
 *
 * On every compiler pass is the namespace tree rebuild to aid in the process
 * of incremental updates. The Files Collection in the Project Descriptor is the
 * only location where aliases to elements may be serialized.
 *
 * If the namespace tree were to be persisted then both locations needed to be
 * invalidated if a file were to change.
 */
class NamespaceTreeBuilder implements CompilerPassInterface
{
    const COMPILER_PRIORITY = 9000;

    /**
     * {@inheritDoc}
     */
    public function getDescription()
    {
        return 'Build "namespaces" index and add namespaces to "elements"';
    }

    /**
     * {@inheritDoc}
     */
    public function execute(ProjectDescriptor $project)
    {
        $project->getIndexes()->get('elements', new Collection())->set('~\\', $project->getNamespace());
        $project->getIndexes()->get('namespaces', new Collection())->add($project->getNamespace());

        foreach ($project->getFiles() as $file) {
            $this->addElementsOfTypeToNamespace($project, $file->getConstants()->getAll(), 'constants');
            $this->addElementsOfTypeToNamespace($project, $file->getFunctions()->getAll(), 'functions');
            $this->addElementsOfTypeToNamespace($project, $file->getClasses()->getAll(), 'classes');
            $this->addElementsOfTypeToNamespace($project, $file->getInterfaces()->getAll(), 'interfaces');
            $this->addElementsOfTypeToNamespace($project, $file->getTraits()->getAll(), 'traits');
        }
    }

    /**
     * Adds the given elements of a specific type to their respective Namespace Descriptors.
     *
     * This method will assign the given elements to the namespace as registered in the namespace field of that
     * element. If a namespace does not exist yet it will automatically be created.
     *
     * @param ProjectDescriptor    $project
     * @param DescriptorAbstract[] $elements Series of elements to add to their respective namespace.
     * @param string               $type     Declares which field of the namespace will be populated with the given
     * series of elements. This name will be transformed to a getter which must exist. Out of performance
     * considerations will no effort be done to verify whether the provided type is valid.
     *
     * @return void
     */
    protected function addElementsOfTypeToNamespace(ProjectDescriptor $project, array $elements, $type)
    {
        /** @var DescriptorAbstract $element */
        foreach ($elements as $element) {
            $namespaceName = (string) $element->getNamespace();

            // ensure consistency by trimming the slash prefix and then re-appending it.
            $namespaceIndexName = '~\\' . ltrim($namespaceName, '\\');

            if (!isset($project->getIndexes()->elements[$namespaceIndexName])) {
                $this->createNamespaceDescriptorTree($project, $namespaceName);
            }

            /** @var NamespaceDescriptor $namespace */
            $namespace = $project->getIndexes()->elements[$namespaceIndexName];

            // replace textual representation with an object representation
            $element->setNamespace($namespace);

            // add element to namespace
            $getter = 'get'.ucfirst($type);

            /** @var Collection $collection  */
            $collection = $namespace->$getter();
            $collection->add($element);
        }
    }

    /**
     * Creates a tree of NamespaceDescriptors based on the provided FQNN (namespace name).
     *
     * This method will examine the namespace name and create a namespace descriptor for each part of
     * the FQNN if it doesn't exist in the namespaces field of the current namespace (starting with the root
     * Namespace in the Project Descriptor),
     *
     * As an intended side effect this method also populates the *elements* index of the ProjectDescriptor with all
     * created NamespaceDescriptors. Each index key is prefixed with a tilde (~) so that it will not conflict with
     * other FQSEN's, such as classes or interfaces.
     *
     * @param ProjectDescriptor $project
     * @param string            $namespaceName A FQNN of the namespace (and parents) to create.
     *
     * @see ProjectDescriptor::getNamespace() for the root namespace.
     * @see NamespaceDescriptor::getNamespaces() for the child namespaces of a given namespace.
     *
     * @return void
     */
    protected function createNamespaceDescriptorTree(ProjectDescriptor $project, $namespaceName)
    {
        $parts   = explode('\\', ltrim($namespaceName, '\\'));
        $fqnn    = '';

        // this method does not use recursion to traverse the tree but uses a pointer that will be overridden with the
        // next item that is to be traversed (child namespace) at the end of the loop.
        $pointer = $project->getNamespace();
        foreach ($parts as $part) {
            $fqnn .= '\\' . $part;
            if ($pointer->getChildren()->get($part)) {
                $pointer = $pointer->getChildren()->get($part);
                continue;
            }

            // namespace does not exist, create it
            $interimNamespaceDescriptor = new NamespaceDescriptor();
            $interimNamespaceDescriptor->setParent($pointer);
            $interimNamespaceDescriptor->setName($part);
            $interimNamespaceDescriptor->setFullyQualifiedStructuralElementName($fqnn);

            // add to the pointer's list of children
            $pointer->getChildren()->set($part, $interimNamespaceDescriptor);

            // add to index
            $project->getIndexes()->elements['~' . $fqnn] = $interimNamespaceDescriptor;
            $project->getIndexes()->get('namespaces', new Collection())->add($interimNamespaceDescriptor);

            // move pointer forward
            $pointer = $interimNamespaceDescriptor;
        }
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Compiler\Pass;

use Psr\Log\LoggerInterface;
use phpDocumentor\Compiler\CompilerPassInterface;
use phpDocumentor\Descriptor\ProjectAnalyzer;
use phpDocumentor\Descriptor\ProjectDescriptor;

/**
 * This class is responsible for sending statistical information to the log.
 *
 * For debugging purposes it can be convenient to send statistical information about the
 * ProjectDescriptor to the log of phpDocumentor.
 */
class Debug implements CompilerPassInterface
{
    const COMPILER_PRIORITY = 1000;

    /** @var \Psr\Log\LoggerInterface $log */
    protected $log;

    /** @var ProjectAnalyzer $analyzer */
    protected $analyzer;

    /**
     * Registers the logger with this Compiler Pass.
     *
     * @param LoggerInterface $log
     * @param ProjectAnalyzer $analyzer
     */
    public function __construct(LoggerInterface $log, ProjectAnalyzer $analyzer)
    {
        $this->log      = $log;
        $this->analyzer = $analyzer;
    }

    /**
     * {@inheritDoc}
     */
    public function getDescription()
    {
        return 'Analyze results and write report to log';
    }

    /**
     * {@inheritDoc}
     */
    public function execute(ProjectDescriptor $project)
    {
        $this->analyzer->analyze($project);
        $this->log->debug((string) $this->analyzer);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Compiler\Pass;

use phpDocumentor\Descriptor\DescriptorAbstract;
use phpDocumentor\Descriptor\TagDescriptor;
use phpDocumentor\Compiler\CompilerPassInterface;
use phpDocumentor\Descriptor\ProjectDescriptor;

/**
 * This index builder collects all markers from tags and inserts them into the marker index.
 */
class MarkerFromTagsExtractor implements CompilerPassInterface
{
    const COMPILER_PRIORITY = 9000;

    /**
     * {@inheritDoc}
     */
    public function getDescription()
    {
        return 'Collect all markers embedded in tags';
    }

    /**
     * {@inheritDoc}
     */
    public function execute(ProjectDescriptor $project)
    {
        /** @var DescriptorAbstract $element */
        foreach ($project->getIndexes()->get('elements') as $element) {
            $todos = $element->getTags()->get('todo', array());

            /** @var TagDescriptor $todo */
            foreach ($todos as $todo) {
                $element->getFile()->getMarkers()->add(
                    array(
                        'type'    => 'TODO',
                        'message' => $todo->getDescription(),
                        'line'    => $element->getLine(),
                    )
                );
            }
        }
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Compiler\Pass;

use phpDocumentor\Compiler\CompilerPassInterface;
use phpDocumentor\Descriptor\Collection;
use phpDocumentor\Descriptor\DescriptorAbstract;
use phpDocumentor\Descriptor\Interfaces\ClassInterface;
use phpDocumentor\Descriptor\Interfaces\InterfaceInterface;
use phpDocumentor\Descriptor\Interfaces\TraitInterface;
use phpDocumentor\Descriptor\ProjectDescriptor;
use phpDocumentor\Descriptor\Interfaces\PropertyInterface;

/**
 * This class constructs the index 'elements' and populates it with all Structural Elements.
 *
 * Please note that due to a conflict between namespace FQSEN's and that of classes, interfaces, traits and functions
 * will the namespace FQSEN be prefixed with a tilde (~).
 */
class ElementsIndexBuilder implements CompilerPassInterface
{
    const COMPILER_PRIORITY = 15000;

    /**
     * {@inheritDoc}
     */
    public function getDescription()
    {
        return 'Build "elements" index';
    }

    /**
     * {@inheritDoc}
     */
    public function execute(ProjectDescriptor $project)
    {
        $elementCollection = new Collection();
        $project->getIndexes()->set('elements', $elementCollection);

        $constantsIndex  = $project->getIndexes()->get('constants', new Collection());
        $functionsIndex  = $project->getIndexes()->get('functions', new Collection());
        $classesIndex    = $project->getIndexes()->get('classes', new Collection());
        $interfacesIndex = $project->getIndexes()->get('interfaces', new Collection());
        $traitsIndex     = $project->getIndexes()->get('traits', new Collection());

        foreach ($project->getFiles() as $file) {
            $this->addElementsToIndexes($file->getConstants()->getAll(), array($constantsIndex, $elementCollection));
            $this->addElementsToIndexes($file->getFunctions()->getAll(), array($functionsIndex, $elementCollection));

            foreach ($file->getClasses()->getAll() as $element) {
                $this->addElementsToIndexes($element, array($classesIndex, $elementCollection));
                $this->addElementsToIndexes($this->getSubElements($element), array($elementCollection));
            }

            foreach ($file->getInterfaces()->getAll() as $element) {
                $this->addElementsToIndexes($element, array($interfacesIndex, $elementCollection));
                $this->addElementsToIndexes($this->getSubElements($element), array($elementCollection));
            }

            foreach ($file->getTraits()->getAll() as $element) {
                $this->addElementsToIndexes($element, array($traitsIndex, $elementCollection));
                $this->addElementsToIndexes($this->getSubElements($element), array($elementCollection));
            }
        }
    }

    /**
     * Returns any sub-elements for the given element.
     *
     * This method checks whether the given element is a class, interface or trait and returns
     * their methods, properties and constants accordingly, or an empty array if no sub-elements
     * are applicable.
     *
     * @param DescriptorAbstract $element
     *
     * @return DescriptorAbstract[]
     */
    protected function getSubElements(DescriptorAbstract $element)
    {
        $subElements = array();

        if ($element instanceof ClassInterface) {
            $subElements = array_merge(
                $element->getMethods()->getAll(),
                $element->getConstants()->getAll(),
                $element->getProperties()->getAll()
            );
        }

        if ($element instanceof InterfaceInterface) {
            $subElements = array_merge(
                $element->getMethods()->getAll(),
                $element->getConstants()->getAll()
            );
        }

        if ($element instanceof TraitInterface) {
            $subElements = array_merge(
                $element->getMethods()->getAll(),
                $element->getProperties()->getAll()
            );
        }

        return $subElements;
    }

    /**
     * Adds a series of descriptors to the given list of collections.
     *
     * @param DescriptorAbstract|DescriptorAbstract[] $elements
     * @param Collection[]                            $indexes
     *
     * @return void
     */
    protected function addElementsToIndexes($elements, $indexes)
    {
        if (!is_array($elements)) {
            $elements = array($elements);
        }

        /** @var DescriptorAbstract $element */
        foreach ($elements as $element) {
            /** @var Collection $collection */
            foreach ($indexes as $collection) {
                $collection->set($this->getIndexKey($element), $element);
            }
        }
    }

    /**
     * Retrieves a key for the index for the provided element.
     *
     * @param DescriptorAbstract $element
     *
     * @return string
     */
    protected function getIndexKey($element)
    {
        $key = $element->getFullyQualifiedStructuralElementName();

        // properties should have an additional $ before the property name
        if ($element instanceof PropertyInterface) {
            list($fqcn, $propertyName) = explode('::', $key);
            $key = $fqcn . '::$' . $propertyName;
        }

        return $key;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Compiler\Pass;

use phpDocumentor\Compiler\CompilerPassInterface;
use phpDocumentor\Descriptor\Collection;
use phpDocumentor\Descriptor\DescriptorAbstract;
use phpDocumentor\Descriptor\PackageDescriptor;
use phpDocumentor\Descriptor\ProjectDescriptor;

/**
 * Rebuilds the package tree from the elements found in files.
 *
 * On every compiler pass is the package tree rebuild to aid in the process
 * of incremental updates.
 *
 * If the package tree were to be persisted then both locations needed to be
 * invalidated if a file were to change.
 */
class PackageTreeBuilder implements CompilerPassInterface
{
    const COMPILER_PRIORITY = 9001;

    /**
     * {@inheritDoc}
     */
    public function getDescription()
    {
        return 'Build "packages" index';
    }

    /**
     * {@inheritDoc}
     */
    public function execute(ProjectDescriptor $project)
    {
        $project->getIndexes()->set('packages', new Collection());
        $project->getIndexes()->packages['\\'] = new PackageDescriptor();

        foreach ($project->getFiles() as $file) {
            $this->addElementsOfTypeToPackage($project, $file->getConstants()->getAll(), 'constants');
            $this->addElementsOfTypeToPackage($project, $file->getFunctions()->getAll(), 'functions');
            $this->addElementsOfTypeToPackage($project, $file->getClasses()->getAll(), 'classes');
            $this->addElementsOfTypeToPackage($project, $file->getInterfaces()->getAll(), 'interfaces');
            $this->addElementsOfTypeToPackage($project, $file->getTraits()->getAll(), 'traits');
        }
    }

    /**
     * Adds the given elements of a specific type to their respective Package Descriptors.
     *
     * This method will assign the given elements to the package as registered in the package field of that
     * element. If a package does not exist yet it will automatically be created.
     *
     * @param ProjectDescriptor    $project
     * @param DescriptorAbstract[] $elements Series of elements to add to their respective package.
     * @param string               $type     Declares which field of the package will be populated with the given
     * series of elements. This name will be transformed to a getter which must exist. Out of performance
     * considerations will no effort be done to verify whether the provided type is valid.
     *
     * @return void
     */
    protected function addElementsOfTypeToPackage(ProjectDescriptor $project, array $elements, $type)
    {
        /** @var DescriptorAbstract $element */
        foreach ($elements as $element) {
            $packageName = (string) $element->getPackage();
            if ($element->getSubPackage()) {
                $packageName .= '\\' . $element->getSubPackage();
            }

            // ensure consistency by trimming the slash prefix and then re-appending it.
            $packageIndexName = '\\' . ltrim($packageName, '\\');

            if (!isset($project->getIndexes()->packages[$packageIndexName])) {
                $this->createPackageDescriptorTree($project, $packageName);
            }

            /** @var PackageDescriptor $package */
            $package = $project->getIndexes()->packages[$packageIndexName];

            // replace textual representation with an object representation
            $element->setPackage($package);

            // add element to package
            $getter = 'get'.ucfirst($type);

            /** @var Collection $collection  */
            $collection = $package->$getter();
            $collection->add($element);
        }
    }

    /**
     * Creates a tree of PackageDescriptors based on the provided FQNN (package name).
     *
     * This method will examine the package name and create a package descriptor for each part of
     * the FQNN if it doesn't exist in the packages field of the current package (starting with the root
     * Package in the Project Descriptor),
     *
     * As an intended side effect this method also populates the *elements* index of the ProjectDescriptor with all
     * created PackageDescriptors. Each index key is prefixed with a tilde (~) so that it will not conflict with
     * other FQSEN's, such as classes or interfaces.
     *
     * @param ProjectDescriptor $project
     * @param string            $packageName A FQNN of the package (and parents) to create.
     *
     * @see ProjectDescriptor::getPackage() for the root package.
     * @see PackageDescriptor::getChildren() for the child packages of a given package.
     *
     * @return void
     */
    protected function createPackageDescriptorTree(ProjectDescriptor $project, $packageName)
    {
        $parts   = explode('\\', ltrim($packageName, '\\'));
        $fqnn    = '';

        // this method does not use recursion to traverse the tree but uses a pointer that will be overridden with the
        // next item that is to be traversed (child package) at the end of the loop.

        /** @var PackageDescriptor $pointer  */
        $pointer = $project->getIndexes()->packages['\\'];
        foreach ($parts as $part) {
            $fqnn .= '\\' . $part;
            if ($pointer->getChildren()->get($part)) {
                $pointer = $pointer->getChildren()->get($part);
                continue;
            }

            // package does not exist, create it
            $interimPackageDescriptor = new PackageDescriptor();
            $interimPackageDescriptor->setParent($pointer);
            $interimPackageDescriptor->setName($part);
            $interimPackageDescriptor->setFullyQualifiedStructuralElementName($fqnn);

            // add to the pointer's list of children
            $pointer->getChildren()->set($part, $interimPackageDescriptor);

            // add to index
            $project->getIndexes()->packages[$fqnn] = $interimPackageDescriptor;

            // move pointer forward
            $pointer = $interimPackageDescriptor;
        }
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Compiler;

/**
 * Contains a series of compiler steps in a specific order; ready to be executed during transformation.
 */
class Compiler extends \SplPriorityQueue
{
    /** @var integer Default priority assigned to Compiler Passes without provided priority */
    const PRIORITY_DEFAULT = 10000;

    /**
     * {@inheritDoc}
     */
    public function insert($value, $priority = self::PRIORITY_DEFAULT)
    {
        parent::insert($value, $priority);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor;

use Zend\I18n\Translator\Translator as ZendTranslator;

/**
 * Translator proxy for phpDocumentor.
 *
 * This class encapsulates (or actually extends) a Translator object that can be used to translate messages from the
 * fallback language to another.
 *
 * This encapsulation serves two purposes;
 *
 * 1. To make a migration to another translator easier if necessary
 * 2. To fix a bug in Zend\I18n\Translator\Translator where the cache is not cleared when new messages are added.
 *
 * Due to issue 2 this class extends the Zend Translator and does not use composition to proxy calls to the translator;
 * as such it is not recommended to use any public function not defined in this proxy as it may be removed.
 *
 * Before invoking the {@see self::translate()} method the user must first load a series of translation messages in the
 * desired locale; this can be done by invoking the {@see self::addTranslationFile()} or
 * {@see self::addTranslationFolder()} methods. These try to include a file containing a plain PHP Array and merge that
 * with the translation table of this translator.
 *
 * An example of a translation file can be:
 *
 * ```
 * return array(
 *     'KEY' => 'translated message',
 * );
 * ```
 */
class Translator extends ZendTranslator
{
    /**
     * The translation file type.
     *
     * This type is hardcoded into a constant to simplify the signature of the addTranslationFile and
     * addTranslationFilePattern methods. This will simplify the migration to another component in the future as an
     * incompatibility between two libraries may emerge due to differing types or typenames.
     *
     * This translator class may be used by plugin developers to have translating elements in their plugins; as such
     * the signatures here are considered to be stable / api.
     * @var string
     */
    const TRANSLATION_FILE_TYPE = 'phparray';

    /** @var string Represents the default locale for phpDocumentor */
    const DEFAULT_LOCALE = 'en';

    /** @var string Translation strings may be divided into 'domains', this is the default domain */
    const DEFAULT_DOMAIN = 'default';

    /** @var string the default name of files loaded by {@see self::addTranslationFolder()} */
    const DEFAULT_PATTERN = '%s.php';

    /**
     * Pre-set the translator with the default locale as fallback.
     */
    public function __construct()
    {
        $this->setLocale(self::DEFAULT_LOCALE);
        $this->setFallbackLocale(self::DEFAULT_LOCALE);
    }

    /**
     * Sets the default locale to use when translating messages.
     *
     * @param string $locale
     *
     * @api
     *
     * @return Translator
     */
    public function setLocale($locale)
    {
        return parent::setLocale($locale);
    }

    /**
     * Adds a translation file for a specific locale, or the default locale when none is provided.
     *
     * @param string      $filename   Name of the file to add.
     * @param string|null $locale     The locale to assign to, matches
     *     {@link http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes ISO-639-1} and defaults to en (English).
     * @param string      $textDomain Translations may be divided into separate files / domains; this represents in
     *     which domain the translation should be.
     *
     * @api
     *
     * @return $this
     */
    public function addTranslations($filename, $locale = self::DEFAULT_LOCALE, $textDomain = self::DEFAULT_DOMAIN)
    {
        parent::addTranslationFile(self::TRANSLATION_FILE_TYPE, $filename, $textDomain, $locale);

        $this->messages = array();

        return $this;
    }

    /**
     * Adds a folder with files containing translation sources.
     *
     * This method scans the provided folder for any file matching the following format:
     *
     *     `[domain].[locale].php`
     *
     * If the domain matches the {@see self::DEFAULT_DOMAIN default domain} then that part is omitted and the filename
     * should match:
     *
     *     `[locale].php`
     *
     * @link http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes for a list of ISO-639-1 locale codes as used by
     *     this method.
     *
     * @param string   $folder  Name of the folder, it is recommended to use an absolute path.
     * @param string[] $domains One or more domains to load, when none is provided only the default is added.
     *
     * @api
     *
     * @return $this
     */
    public function addTranslationFolder($folder, array $domains = array())
    {
        if (empty($domains)) {
            $domains = array(self::DEFAULT_DOMAIN);
        }

        foreach ($domains as $domain) {
            $this->addTranslationsUsingPattern($folder, $domain);
        }

        return $this;
    }

    /**
     * Adds a series of translation files given a pattern.
     *
     * This method will search the base directory for a series of files matching the given pattern (where %s is replaces
     * by the two-letter locale shorthand) and adds any translations to the translation table.
     *
     * @param string $baseDir    Directory to search in (not-recursive)
     * @param string $textDomain The domain to assign the translation messages to.
     * @param string $pattern    The pattern used to load files for all languages, one variable `%s` is supported and
     *     is replaced with the {@link http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes ISO-639-1 code} for each
     *     locale that is requested by the translate method.
     *
     * @internal this method is not to be used by consumers; it is an extension of the Zend Translator component
     *     and is overridden to clear the messages caching array so it may be rebuild.
     *
     * @see self::addTranslationFolder() to provide a series of translation files.
     *
     * @return $this|ZendTranslator
     */
    public function addTranslationsUsingPattern(
        $baseDir,
        $textDomain = self::DEFAULT_DOMAIN,
        $pattern = self::DEFAULT_PATTERN
    ) {
        if ($textDomain !== self::DEFAULT_DOMAIN && $pattern === self::DEFAULT_PATTERN) {
            $pattern = $textDomain . '.' . $pattern;
        }

        parent::addTranslationFilePattern(self::TRANSLATION_FILE_TYPE, $baseDir, $pattern, $textDomain);

        $this->messages = array();

        return $this;
    }

    /**
     * Attempts to translate the given message or code into the provided locale.
     *
     * @param string $message    The message or code to translate.
     * @param string $textDomain A message may be located in a domain, here you can provide in which.
     * @param null   $locale     The locale to translate to or the default if not set.
     *
     * @return string
     */
    public function translate($message, $textDomain = self::DEFAULT_DOMAIN, $locale = null)
    {
        return parent::translate($message, $textDomain, $locale);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor;

use phpDocumentor\Descriptor\Builder\AssemblerFactory;
use phpDocumentor\Descriptor\Builder\Reflector\AssemblerAbstract;
use phpDocumentor\Descriptor\Filter\Filter;
use phpDocumentor\Descriptor\Filter\Filterable;
use phpDocumentor\Descriptor\Validator\Error;
use Psr\Log\LogLevel;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\Validator;

/**
 * Builds a Project Descriptor and underlying tree.
 */
class ProjectDescriptorBuilder
{
    /** @var string */
    const DEFAULT_PROJECT_NAME = 'Untitled project';

    /** @var AssemblerFactory $assemblerFactory */
    protected $assemblerFactory;

    /** @var Validator $validator */
    protected $validator;

    /** @var Filter $filter */
    protected $filter;

    /** @var ProjectDescriptor $project */
    protected $project;

    public function __construct(AssemblerFactory $assemblerFactory, Filter $filterManager, Validator $validator)
    {
        $this->assemblerFactory = $assemblerFactory;
        $this->validator        = $validator;
        $this->filter           = $filterManager;
    }

    public function createProjectDescriptor()
    {
        $this->project = new ProjectDescriptor(self::DEFAULT_PROJECT_NAME);
    }

    public function setProjectDescriptor(ProjectDescriptor $projectDescriptor)
    {
        $this->project = $projectDescriptor;
    }

    /**
     * Returns the project descriptor that is being built.
     *
     * @return ProjectDescriptor
     */
    public function getProjectDescriptor()
    {
        return $this->project;
    }

    /**
     * Verifies whether the given visibility is allowed to be included in the Descriptors.
     *
     * This method is used anytime a Descriptor is added to a collection (for example, when adding a Method to a Class)
     * to determine whether the visibility of that element is matches what the user has specified when it ran
     * phpDocumentor.
     *
     * @param integer $visibility One of the visibility constants of the ProjectDescriptor class.
     *
     * @see ProjectDescriptor where the visibility is stored and that declares the constants to use.
     *
     * @return boolean
     */
    public function isVisibilityAllowed($visibility)
    {
        return $this->getProjectDescriptor()->isVisibilityAllowed($visibility);
    }

    public function buildFileUsingSourceData($data)
    {
        $descriptor = $this->buildDescriptor($data);
        if (!$descriptor) {
            return;
        }

        $this->getProjectDescriptor()->getFiles()->set($descriptor->getPath(), $descriptor);
    }

    /**
     * Takes the given data and attempts to build a Descriptor from it.
     *
     * @param mixed $data
     *
     * @throws \InvalidArgumentException if no Assembler could be found that matches the given data.
     *
     * @return DescriptorAbstract|null
     */
    public function buildDescriptor($data)
    {
        $assembler = $this->getAssembler($data);
        if (!$assembler) {
            throw new \InvalidArgumentException(
                'Unable to build a Descriptor; the provided data did not match any Assembler '. get_class($data)
            );
        }

        if ($assembler instanceof Builder\AssemblerAbstract) {
            $assembler->setBuilder($this);
        }

        // create Descriptor and populate with the provided data
        $descriptor = $assembler->create($data);
        if (!$descriptor) {
            return null;
        }

        // filter the descriptor; this may result in the descriptor being removed!
        $descriptor = $this->filter($descriptor);
        if (!$descriptor) {
            return null;
        }

        // Validate the descriptor and store any errors
        $descriptor->setErrors($this->validate($descriptor));

        return $descriptor;
    }

    /**
     * Attempts to find an assembler matching the given data.
     *
     * @param mixed $data
     *
     * @return AssemblerAbstract
     */
    public function getAssembler($data)
    {
        return $this->assemblerFactory->get($data);
    }

    /**
     * Analyzes a Descriptor and alters its state based on its state or even removes the descriptor.
     *
     * @param Filterable $descriptor
     *
     * @return Filterable
     */
    public function filter(Filterable $descriptor)
    {
        return $this->filter->filter($descriptor);
    }

    /**
     * Validates the contents of the Descriptor and outputs warnings and error if something is amiss.
     *
     * @param DescriptorAbstract $descriptor
     *
     * @return Collection
     */
    public function validate($descriptor)
    {
        $violations = $this->validator->validate($descriptor);
        $errors = new Collection();

        /** @var ConstraintViolation $violation */
        foreach ($violations as $violation) {
            $errors->add(
                new Error(
                    LogLevel::ERROR, // TODO: Make configurable
                    $violation->getMessageTemplate(),
                    $descriptor->getLine(),
                    $violation->getMessageParameters() + array($descriptor->getFullyQualifiedStructuralElementName())
                )
            );
        }

        return $errors;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor;

use phpDocumentor\Descriptor\ProjectDescriptor\Settings;

/**
 * Represents the entire project with its files, namespaces and indexes.
 */
class ProjectDescriptor implements Interfaces\ProjectInterface
{
    /** @var string $name */
    protected $name = '';

    /** @var NamespaceDescriptor $namespace */
    protected $namespace;

    /** @var Collection $files*/
    protected $files;

    /** @var Collection $indexes */
    protected $indexes;

    /** @var Settings $settings */
    protected $settings;

    /** @var Collection $partials */
    protected $partials;

    /**
     * Initializes this descriptor.
     */
    public function __construct($name)
    {
        $this->setName($name);
        $this->setSettings(new Settings());

        $namespace = new NamespaceDescriptor();
        $namespace->setName('\\');
        $namespace->setFullyQualifiedStructuralElementName('\\');
        $this->setNamespace($namespace);

        $this->setFiles(new Collection());
        $this->setIndexes(new Collection());

        $this->setPartials(new Collection());
    }

    /**
     * Sets the name for this project.
     *
     * @param string $name
     *
     * @return void
     */
    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * Returns the name of this project.
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Sets all files on this project.
     *
     * @param Collection $files
     *
     * @return void
     */
    public function setFiles($files)
    {
        $this->files = $files;
    }

    /**
     * Returns all files with their sub-elements.
     *
     * @return Collection|FileDescriptor[]
     */
    public function getFiles()
    {
        return $this->files;
    }

    /**
     * Sets all indexes for this project.
     *
     * An index is a compilation of references to elements, usually constructed in a compiler step, that aids template
     * generation by providing a conveniently assembled list. An example of such an index is the 'marker' index where
     * a list of TODOs and FIXMEs are located in a central location for reporting.
     *
     * @param Collection $indexes
     *
     * @return void
     */
    public function setIndexes(Collection $indexes)
    {
        $this->indexes = $indexes;
    }

    /**
     * Returns all indexes in this project.
     *
     * @see setIndexes() for more information on what indexes are.
     *
     * @return Collection
     */
    public function getIndexes()
    {
        return $this->indexes;
    }

    /**
     * Sets the root namespace for this project together with all sub-namespaces.
     *
     * @param NamespaceDescriptor $namespace
     *
     * @return void
     */
    public function setNamespace($namespace)
    {
        $this->namespace = $namespace;
    }

    /**
     * Returns the root (global) namespace.
     *
     * @return NamespaceDescriptor
     */
    public function getNamespace()
    {
        return $this->namespace;
    }

    /**
     * Sets the settings used to build the documentation for this project.
     *
     * @param Settings $settings
     *
     * @return void
     */
    public function setSettings($settings)
    {
        $this->settings = $settings;
    }

    /**
     * Returns the settings used to build the documentation for this project.
     *
     * @return Settings
     */
    public function getSettings()
    {
        return $this->settings;
    }

    /**
     * Sets all partials that can be used in a template.
     *
     * Partials are blocks of text that can be inserted anywhere in a template using a special indicator. An example is
     * the introduction partial that can add a custom piece of text to the homepage.
     *
     * @param Collection $partials
     *
     * @return void
     */
    public function setPartials(Collection $partials)
    {
        $this->partials = $partials;
    }

    /**
     * Returns a list of all partials.
     *
     * @see setPartials() for more information on partials.
     *
     * @return Collection
     */
    public function getPartials()
    {
        return $this->partials;
    }

    /**
     * Checks whether the Project supports the given visibility.
     *
     * @param integer $visibility One of the VISIBILITY_* constants of the Settings class.
     *
     * @see Settings for a list of the available VISIBILITY_* constants.
     *
     * @return boolean
     */
    public function isVisibilityAllowed($visibility)
    {
        $visibilityAllowed = $this->getSettings()
            ? $this->getSettings()->getVisibility()
            : Settings::VISIBILITY_DEFAULT;

        return (bool) ($visibilityAllowed & $visibility);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor;

use phpDocumentor\Descriptor\Filter\Filterable;
use phpDocumentor\Descriptor\Interfaces\ChildInterface;

/**
 * Base class for descriptors containing the most used options.
 */
abstract class DescriptorAbstract implements Filterable
{
    /**
     * @var string $fqsen Fully Qualified Structural Element Name; the FQCN including method, property of constant name
     */
    protected $fqsen = '';

    /** @var string $name The local name for this element */
    protected $name = '';

    /** @var NamespaceDescriptor $namespace The namespace for this element */
    protected $namespace;

    /** @var string $package The package with which this element is associated */
    protected $package = '';

    /** @var string $summary A summary describing the function of this element in short. */
    protected $summary = '';

    /** @var string $description A more extensive description of this element. */
    protected $description = '';

    /** @var FileDescriptor|null $file The file to which this element belongs; if applicable */
    protected $fileDescriptor;

    /** @var int $line The line number on which this element occurs. */
    protected $line = 0;

    /** @var Collection $tags The tags associated with this element. */
    protected $tags;

    /** @var Collection $errors A list of errors found while building this element. */
    protected $errors;

    /**
     * Initializes this descriptor.
     */
    public function __construct()
    {
        $this->setTags(new Collection());
        $this->setErrors(new Collection());
    }

    /**
     * Sets the Fully Qualified Structural Element Name (FQSEN) for this element.
     *
     * @param string $name
     *
     * @return void
     */
    public function setFullyQualifiedStructuralElementName($name)
    {
        $this->fqsen = $name;
    }

    /**
     * Returns the Fully Qualified Structural Element Name (FQSEN) for this element.
     *
     * @return string
     */
    public function getFullyQualifiedStructuralElementName()
    {
        return $this->fqsen;
    }

    /**
     * Sets the local name for this element.
     *
     * @param string $name
     *
     * @return void
     */
    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * Returns the local name for this element.
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Sets the namespace (name) for this element.
     *
     * @param NamespaceDescriptor|string $namespace
     */
    public function setNamespace($namespace)
    {
        $this->namespace = $namespace;
    }

    /**
     * Returns the namespace for this element or null if none is attached.
     *
     * @return NamespaceDescriptor|string|null
     */
    public function getNamespace()
    {
        return $this->namespace;
    }

    /**
     * Sets the summary describing this element in short.
     *
     * @param string $summary
     *
     * @return void
     */
    public function setSummary($summary)
    {
        $this->summary = $summary;
    }

    /**
     * Returns the summary which describes this element.
     *
     * This method will automatically attempt to inherit the parent's summary if this one has none.
     *
     * @return string
     */
    public function getSummary()
    {
        // if the summary is not set, inherit it from the parent
        if ((!$this->summary || strtolower(trim($this->summary)) == '{@inheritdoc}')
            && ($this instanceof ChildInterface)
            && ($this->getParent() instanceof self)
        ) {
            return $this->getParent()->getSummary();
        }

        return $this->summary;
    }

    /**
     * Sets a description for this element.
     *
     * @param string $description
     *
     * @return void
     */
    public function setDescription($description)
    {
        $this->description = $description;
    }

    /**
     * Returns the description for this element.
     *
     * This method will automatically attempt to inherit the parent's description if this one has none.
     *
     * @return string
     */
    public function getDescription()
    {
        // if the description is not set, inherit it from the parent
        if (!$this->description && ($this instanceof ChildInterface) && ($this->getParent() instanceof self)) {
            return $this->getParent()->getDescription();
        }

        return $this->description;
    }

    /**
     * Sets the file and linenumber where this element is at.
     *
     * @param FileDescriptor $file
     * @param int            $line
     *
     * @return void
     */
    public function setLocation(FileDescriptor $file, $line = 0)
    {
        $this->setFile($file);
        $this->line = $line;
    }

    /**
     * Returns the path to the file containing this element relative to the project's root.
     *
     * @return string
     */
    public function getPath()
    {
        return $this->fileDescriptor ? $this->fileDescriptor->getPath() : '';
    }

    /**
     * Returns the file in which this element resides or null in case the element is not bound to a file..
     *
     * @return FileDescriptor|null
     */
    public function getFile()
    {
        return $this->fileDescriptor;
    }

    /**
     * Sets the file to which this element is associated.
     *
     * @param FileDescriptor $file
     *
     * @return false
     */
    public function setFile(FileDescriptor $file)
    {
        $this->fileDescriptor = $file;
    }

    /**
     * Returns the line number where the definition for this element can be found.
     *
     * @return int
     */
    public function getLine()
    {
        return $this->line;
    }

    /**
     * Sets the line number for this element's location in the source file.
     *
     * @param integer $lineNumber
     *
     * @return void
     */
    public function setLine($lineNumber)
    {
        $this->line = $lineNumber;
    }

    /**
     * Sets the tags associated with this element.
     *
     * @param Collection $tags
     *
     * @return void
     */
    public function setTags(Collection $tags)
    {
        $this->tags = $tags;
    }

    /**
     * Returns the tags associated with this element.
     *
     * @return Collection
     */
    public function getTags()
    {
        return $this->tags;
    }

    /**
     * Sets the name of the package to which this element belongs.
     *
     * @param string $package
     *
     * @return void
     */
    public function setPackage($package)
    {
        $this->package = trim($package);
    }

    /**
     * Returns the package to which this element belongs.
     *
     * This method will automatically attempt to inherit the parent's package if this one has none.
     *
     * @return string
     */
    public function getPackage()
    {
        // if the package is not set, inherit it from the parent
        if (!$this->package && ($this instanceof ChildInterface) && ($this->getParent() instanceof self)) {
            return $this->getParent()->getPackage();
        }

        return $this->package;
    }

    /**
     * Returns the subpackage for this element.
     *
     * This method will automatically attempt to inherit the parent's subpackage if this one has none.
     *
     * @return Collection
     */
    public function getSubPackage()
    {
        /** @var Collection $subpackage */
        $subpackage = $this->getTags()->get('subpackage', new Collection());

        // if the subpackage is not set, inherit it from the parent
        if ($subpackage->count() == 0
            && ($this instanceof ChildInterface)
            && ($this->getParent() instanceof self)
            && ($this->getParent()->getPackage() == $this->getPackage())
        ) {
            return $this->getParent()->getSubPackage();
        }

        $subpackageDescriptor = current(current($subpackage));

        return $subpackageDescriptor ? $subpackageDescriptor->getDescription() : '';
    }

    /**
     * Returns the authors for this element.
     *
     * @return Collection
     */
    public function getAuthor()
    {
        /** @var Collection $author */
        $author = $this->getTags()->get('author', new Collection());

        // if the author is not set, inherit it from the parent
        if ($author->count() == 0 && ($this instanceof ChildInterface) && ($this->getParent() instanceof self)) {
            return $this->getParent()->getAuthor();
        }

        return $author;
    }

    /**
     * Returns the versions for this element.
     *
     * @return Collection
     */
    public function getVersion()
    {
        /** @var Collection $version */
        $version = $this->getTags()->get('version', new Collection());

        // if the version is not set, inherit it from the parent
        if ($version->count() == 0 && ($this instanceof ChildInterface) && ($this->getParent() instanceof self)) {
            return $this->getParent()->getVersion();
        }

        return $version;
    }

    /**
     * Returns the copyrights for this element.
     *
     * @return Collection
     */
    public function getCopyright()
    {
        /** @var Collection $copyright */
        $copyright = $this->getTags()->get('copyright', new Collection());

        // if the copyright is not set, inherit it from the parent
        if ($copyright->count() == 0 && ($this instanceof ChildInterface) && ($this->getParent() instanceof self)) {
            return $this->getParent()->getCopyright();
        }

        return $copyright;
    }

    /**
     * Checks whether this element is deprecated.
     *
     * @return boolean
     */
    public function isDeprecated()
    {
        return isset($this->tags['deprecated']);
    }

    /**
     * Sets a list of all errors associated with this element.
     *
     * @param Collection $errors
     */
    public function setErrors(Collection $errors)
    {
        $this->errors = $errors;
    }

    /**
     * Returns all errors that occur in this element.
     *
     * @return Collection
     */
    public function getErrors()
    {
        return $this->errors;
    }

    /**
     * Dynamically constructs a set of getters to retrieve tag (collections) with.
     *
     * Important: __call() is not a fast method of access; it is preferred to directly use the getTags() collection.
     * This interface is provided to allow for uniform and easy access to certain tags.
     *
     * @param string  $name
     * @param mixed[] $arguments
     *
     * @return Collection|null
     */
    public function __call($name, $arguments)
    {
        if (substr($name, 0, 3) !== 'get') {
            return null;
        }

        $tagName = substr($name, 3);
        $tagName[0] = strtolower($tagName[0]); // lowercase the first letter

        return $this->getTags()->get($tagName, new Collection());
    }

    /**
     * Represents this object by its unique identifier, the Fully Qualified Structural Element Name.
     *
     * @return string
     */
    public function __toString()
    {
        return $this->getFullyQualifiedStructuralElementName();
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor;

/**
 * Descriptor representing a Trait.
 */
class TraitDescriptor extends DescriptorAbstract implements Interfaces\TraitInterface
{
    /** @var Collection $properties */
    protected $properties;

    /** @var Collection $methods */
    protected $methods;

    /** @var Collection $usedTraits */
    protected $usedTraits;

    /**
     * Initializes the all properties representing a collection with a new Collection object.
     */
    public function __construct()
    {
        parent::__construct();

        $this->setProperties(new Collection());
        $this->setMethods(new Collection());
        $this->setUsedTraits(new Collection());
    }

    /**
     * {@inheritDoc}
     */
    public function setMethods(Collection $methods)
    {
        $this->methods = $methods;
    }

    /**
     * {@inheritDoc}
     */
    public function getMethods()
    {
        return $this->methods;
    }

    /**
     * {@inheritDoc}
     */
    public function getInheritedMethods()
    {
        return new Collection();
    }

    /**
     * @return Collection
     */
    public function getMagicMethods()
    {
        /** @var Collection $methodTags */
        $methodTags = clone $this->getTags()->get('method', new Collection());

        $methods = new Collection();

        /** @var Tag\MethodDescriptor $methodTag */
        foreach ($methodTags as $methodTag) {
            $method = new MethodDescriptor();
            $method->setName($methodTag->getVariableName());
            $method->setDescription($methodTag->getDescription());

            $methods->add($method);
        }

        return $methods;
    }

    /**
     * {@inheritDoc}
     */
    public function setProperties(Collection $properties)
    {
        $this->properties = $properties;
    }

    /**
     * {@inheritDoc}
     */
    public function getProperties()
    {
        return $this->properties;
    }

    /**
     * {@inheritDoc}
     */
    public function getInheritedProperties()
    {
        return new Collection();
    }

    /**
     * @return Collection
     */
    public function getMagicProperties()
    {
        /** @var Collection $propertyTags */
        $propertyTags = clone $this->getTags()->get('property', new Collection());
        $propertyTags->merge($this->getTags()->get('property-read', new Collection()));
        $propertyTags->merge($this->getTags()->get('property-write', new Collection()));

        $properties = new Collection();

        /** @var Tag\PropertyDescriptor $propertyTag */
        foreach ($propertyTags as $propertyTag) {
            $property = new PropertyDescriptor();
            $property->setName($propertyTag->getVariableName());
            $property->setDescription($propertyTag->getDescription());
            $property->setTypes($propertyTag->getTypes());

            $properties->add($property);
        }

        return $properties;
    }

    public function setPackage($package)
    {
        parent::setPackage($package);

        foreach ($this->getProperties() as $property) {
            $property->setPackage($package);
        }

        foreach ($this->getMethods() as $method) {
            $method->setPackage($package);
        }
    }

    /**
     * Sets a collection of all traits used by this class.
     *
     * @param Collection $usedTraits
     *
     * @return void
     */
    public function setUsedTraits($usedTraits)
    {
        $this->usedTraits = $usedTraits;
    }

    /**
     * Returns the traits used by this class.
     *
     * Returned values may either be a string (when the Trait is not in this project) or a TraitDescriptor.
     *
     * @return Collection
     */
    public function getUsedTraits()
    {
        return $this->usedTraits;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Cache;

use Zend\Cache\Storage\IterableInterface;
use Zend\Cache\Storage\IteratorInterface;
use Zend\Cache\Storage\OptimizableInterface;
use Zend\Cache\Storage\StorageInterface;
use phpDocumentor\Descriptor\FileDescriptor;
use phpDocumentor\Descriptor\ProjectDescriptor;
use phpDocumentor\Fileset\Collection;

/**
 * Maps a projectDescriptor to and from a cache instance.
 */
class ProjectDescriptorMapper
{
    const FILE_PREFIX = 'file_';

    const KEY_SETTINGS = 'settings';

    /** @var StorageInterface|IterableInterface */
    protected $cache;

    /**
     * Initializes this mapper with the given cache instance.
     * @param StorageInterface $cache
     */
    public function __construct(StorageInterface $cache)
    {
        $this->cache = $cache;
    }

    /**
     * Returns the Cache instance for this Mapper.
     *
     * @return IterableInterface|StorageInterface
     */
    public function getCache()
    {
        return $this->cache;
    }

    /**
     * Returns the Project Descriptor from the cache.
     *
     * @param ProjectDescriptor $projectDescriptor
     *
     * @return void
     */
    public function populate(ProjectDescriptor $projectDescriptor)
    {
        /** @var IteratorInterface $iteratorInterface */
        $iteratorInterface = $this->getCache()->getIterator();

        // load the settings object
        $settings = $this->getCache()->getItem(self::KEY_SETTINGS);
        if ($settings) {
            $projectDescriptor->setSettings($settings);
        }

        // FIXME: Workaround for: https://github.com/zendframework/zf2/pull/4154
        if ($iteratorInterface->valid()) {
            foreach ($this->getCache() as $key) {
                $item = $this->getCache()->getItem($key);
                if ($item instanceof FileDescriptor) {
                    $projectDescriptor->getFiles()->set($item->getPath(), $item);
                }
            }
        }
    }

    /**
     * Stores a Project Descriptor in the Cache.
     *
     * @param ProjectDescriptor $projectDescriptor
     *
     * @return void
     */
    public function save(ProjectDescriptor $projectDescriptor)
    {
        $keys  = array();
        $cache = $this->getCache();

        /** @var IteratorInterface $iteratorInterface  */
        $iteratorInterface = $cache->getIterator();

        // FIXME: Workaround for: https://github.com/zendframework/zf2/pull/4154
        if ($iteratorInterface->valid()) {
            foreach ($cache as $key) {
                $keys[] = $key;
            }
        }

        // store the settings for this Project Descriptor
        $cache->setItem(self::KEY_SETTINGS, $projectDescriptor->getSettings());

        // store cache items
        $usedKeys = array();
        foreach ($projectDescriptor->getFiles() as $file) {
            $key        = self::FILE_PREFIX . md5($file->getPath());
            $usedKeys[] = $key;
            $cache->setItem($key, $file);
        }

        // remove any keys that are no longer used.
        $invalidatedKeys = array_diff($keys, $usedKeys);
        if ($invalidatedKeys) {
            $cache->removeItems($invalidatedKeys);
        }

        if ($cache instanceof OptimizableInterface) {
            $cache->optimize();
        }
    }

    /**
     * Removes all files in cache that do not occur in the given FileSet Collection.
     *
     * @param Collection $collection
     *
     * @return void
     */
    public function garbageCollect(Collection $collection)
    {
        $projectRoot = $collection->getProjectRoot();
        $filenames   = $collection->getFilenames();

        foreach ($filenames as &$name) {
            // the cache key contains a path relative to the project root; here we expect absolute paths.
            $name = self::FILE_PREFIX . md5(substr($name, strlen($projectRoot)));
        }

        /** @var IteratorInterface $iteratorInterface  */
        $iteratorInterface = $this->getCache()->getIterator();

        // FIXME: Workaround for: https://github.com/zendframework/zf2/pull/4154
        if ($iteratorInterface->valid()) {
            foreach ($this->getCache() as $item) {
                if (!in_array($item, $filenames)) {
                    $this->getCache()->removeItem($item);
                }
            }
        }
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor;

/**
 * Represents an easily accessible collection of elements.
 *
 * The goal for this class is to allow Descriptors to be easily retrieved and set so that interaction in
 * templates becomes easier.
 */
class Collection implements \Countable, \IteratorAggregate, \ArrayAccess
{
    /** @var mixed[] $items */
    protected $items = array();

    /**
     * Constructs a new collection object with optionally a series of items, generally Descriptors.
     *
     * @param DescriptorAbstract[]|mixed[] $items
     */
    public function __construct($items = array())
    {
        $this->items = $items;
    }

    /**
     * Adds a new item to this collection, generally a Descriptor.
     *
     * @param DescriptorAbstract|mixed $item
     *
     * @return void
     */
    public function add($item)
    {
        $this->items[] = $item;
    }

    /**
     * Sets a new object onto the collection or clear it using null.
     *
     * @param string|integer                $index An index value to recognize this item with.
     * @param DescriptorAbstract|mixed|null $item  The item to store, generally a Descriptor but may be something else.
     *
     * @return void
     */
    public function set($index, $item)
    {
        $this->offsetSet($index, $item);
    }

    /**
     * Retrieves a specific item from the Collection with its index.
     *
     * Please note that this method (intentionally) has the side effect that whenever a key does not exist that it will
     * be created with the value provided by the $valueIfEmpty argument. This will allow for easy initialization during
     * tree building operations.
     *
     * @param string|integer $index
     * @param mixed          $valueIfEmpty If the index does not exist it will be created with this value and returned.
     *
     * @return mixed The contents of the element with the given index and the provided default if the key doesn't exist.
     */
    public function get($index, $valueIfEmpty = null)
    {
        if (!$this->offsetExists($index) && $valueIfEmpty !== null) {
            $this->offsetSet($index, $valueIfEmpty);
        }

        return $this->offsetGet($index);
    }

    /**
     * Retrieves all items from this collection as PHP Array.
     *
     * @return mixed[]
     */
    public function getAll()
    {
        return $this->items;
    }

    /**
     * Retrieves an iterator to traverse this object.
     *
     * @return \Traversable|\ArrayIterator
     */
    public function getIterator()
    {
        return new \ArrayIterator($this->items);
    }

    /**
     * Returns a count of the number of elements in this collection.
     *
     * @return integer
     */
    public function count()
    {
        return count($this->items);
    }

    /**
     * Empties the collection.
     *
     * @return void
     */
    public function clear()
    {
        $this->items = array();
    }

    /**
     * Retrieves an item as if it were a property of the collection.
     *
     * @param string $name
     *
     * @return mixed
     */
    public function __get($name)
    {
        return $this->get($name);
    }

    /**
     * Checks whether an item in this collection exists.
     *
     * @param string|integer $offset The index to check on.
     *
     * @return boolean
     */
    public function offsetExists($offset)
    {
        return isset($this->items[$offset]);
    }

    /**
     * Retrieves an item from the collection with the given index.
     *
     * @param string|integer $offset The offset to retrieve.
     *
     * @return mixed
     */
    public function offsetGet($offset)
    {
        return ($this->offsetExists($offset)) ? $this->items[$offset] : null;
    }

    /**
     * Sets an item at the given index.
     *
     * @param string|integer $offset The offset to assign the value to.
     * @param mixed          $value  The value to set.
     *
     * @throws \InvalidArgumentException if the key is null or an empty string.
     *
     * @return void
     */
    public function offsetSet($offset, $value)
    {
        if ($offset === '' || $offset === null) {
            throw new \InvalidArgumentException('The key of a collection must always be set');
        }

        $this->items[$offset] = $value;
    }

    /**
     * Removes an item with the given index from the collection.
     *
     * @param string|integer $offset The offset to unset.
     *
     * @return void
     */
    public function offsetUnset($offset)
    {
        unset($this->items[$offset]);
    }

    /**
     * Returns a new collection with the items from this collection and the provided combined.
     *
     * @param Collection $collection
     *
     * @return Collection
     */
    public function merge(Collection $collection)
    {
        return new Collection(array_merge($this->items, $collection->getAll()));
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder\Reflector;

use phpDocumentor\Descriptor\ClassDescriptor;
use phpDocumentor\Descriptor\Collection;
use phpDocumentor\Reflection\ClassReflector;
use phpDocumentor\Reflection\ConstantReflector;

/**
 * Assembles an ClassDescriptor using an ClassReflector.
 */
class ClassAssembler extends AssemblerAbstract
{
    /**
     * Creates a Descriptor from the provided data.
     *
     * @param ClassReflector $data
     *
     * @return ClassDescriptor
     */
    public function create($data)
    {
        $classDescriptor = new ClassDescriptor();

        $classDescriptor->setFullyQualifiedStructuralElementName($data->getName());
        $classDescriptor->setName($data->getShortName());
        $classDescriptor->setPackage($this->extractPackageFromDocBlock($data->getDocBlock()) ?: '');
        $classDescriptor->setLine($data->getLinenumber());
        $classDescriptor->setParent($data->getParentClass());
        $classDescriptor->setAbstract($data->isAbstract());
        $classDescriptor->setFinal($data->isFinal());

        // Reflection library formulates namespace as global but this is not wanted for phpDocumentor itself
        $classDescriptor->setNamespace(
            '\\' . (strtolower($data->getNamespace()) == 'global' ? '' :$data->getNamespace())
        );

        foreach ($data->getInterfaces() as $interfaceClassName) {
            $classDescriptor->getInterfaces()->set($interfaceClassName, $interfaceClassName);
        }

        $fqcn = $classDescriptor->getFullyQualifiedStructuralElementName();
        $namespace = substr($fqcn, 0, strrpos($fqcn, '\\'));
        $classDescriptor->setNamespace($namespace);

        $this->assembleDocBlock($data->getDocBlock(), $classDescriptor);

        $this->addConstants($data->getConstants(), $classDescriptor);
        $this->addProperties($data->getProperties(), $classDescriptor);
        $this->addMethods($data->getMethods(), $classDescriptor);
        $this->addUses($data->getTraits(), $classDescriptor);

        return $classDescriptor;
    }

    /**
     * Registers the child constants with the generated Class Descriptor.
     *
     * @param ConstantReflector[] $constants
     * @param ClassDescriptor     $classDescriptor
     *
     * @return void
     */
    protected function addConstants($constants, $classDescriptor)
    {
        foreach ($constants as $constant) {
            $constantDescriptor = $this->getBuilder()->buildDescriptor($constant);
            if ($constantDescriptor) {
                $constantDescriptor->setParent($classDescriptor);
                $classDescriptor->getConstants()->set($constantDescriptor->getName(), $constantDescriptor);
            }
        }
    }

    /**
     * Registers the child properties with the generated Class Descriptor.
     *
     * @param ClassReflector\PropertyReflector[] $properties
     * @param ClassDescriptor                    $classDescriptor
     *
     * @return void
     */
    protected function addProperties($properties, $classDescriptor)
    {
        foreach ($properties as $property) {
            $propertyDescriptor = $this->getBuilder()->buildDescriptor($property);
            if ($propertyDescriptor) {
                $propertyDescriptor->setParent($classDescriptor);
                $classDescriptor->getProperties()->set($propertyDescriptor->getName(), $propertyDescriptor);
            }
        }
    }

    /**
     * Registers the child methods with the generated Class Descriptor.
     *
     * @param ClassReflector\MethodReflector[] $methods
     * @param ClassDescriptor $classDescriptor
     *
     * @return void
     */
    protected function addMethods($methods, $classDescriptor)
    {
        foreach ($methods as $method) {
            $methodDescriptor = $this->getBuilder()->buildDescriptor($method);
            if ($methodDescriptor) {
                $methodDescriptor->setParent($classDescriptor);
                $classDescriptor->getMethods()->set($methodDescriptor->getName(), $methodDescriptor);
            }
        }
    }

    /**
     * Registers the used traits with the generated Class Descriptor.
     *
     * @param string[] $traits
     * @param ClassDescriptor $classDescriptor
     *
     * @return void
     */
    protected function addUses(array $traits, ClassDescriptor $classDescriptor)
    {
        $classDescriptor->setUsedTraits(new Collection($traits));
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder\Reflector;

use phpDocumentor\Descriptor\ConstantDescriptor;
use phpDocumentor\Reflection\ConstantReflector;

/**
 * Assembles a ConstantDescriptor from a ConstantReflector.
 */
class ConstantAssembler extends AssemblerAbstract
{
    /**
     * Creates a Descriptor from the provided data.
     *
     * @param ConstantReflector $data
     *
     * @return ConstantDescriptor
     */
    public function create($data)
    {
        $constantDescriptor = new ConstantDescriptor();
        $constantDescriptor->setName($data->getShortName());
        $constantDescriptor->setValue($data->getValue());
        // Reflection library formulates namespace as global but this is not wanted for phpDocumentor itself
        $constantDescriptor->setNamespace(
            '\\' . (strtolower($data->getNamespace()) == 'global' ? '' :$data->getNamespace())
        );
        $constantDescriptor->setFullyQualifiedStructuralElementName(
            $constantDescriptor->getNamespace() . '\\' . $data->getShortName()
        );

        $this->assembleDocBlock($data->getDocBlock(), $constantDescriptor);

        $constantDescriptor->setLine($data->getLinenumber());

        return $constantDescriptor;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder\Reflector;

use phpDocumentor\Descriptor\InterfaceDescriptor;
use phpDocumentor\Reflection\ClassReflector\MethodReflector;
use phpDocumentor\Reflection\ConstantReflector;
use phpDocumentor\Reflection\InterfaceReflector;

/**
 * Assembles an InterfaceDescriptor using an InterfaceReflector.
 */
class InterfaceAssembler extends AssemblerAbstract
{
    /**
     * Creates a Descriptor from the provided data.
     *
     * @param InterfaceReflector $data
     *
     * @return InterfaceDescriptor
     */
    public function create($data)
    {
        $interfaceDescriptor = new InterfaceDescriptor();

        $interfaceDescriptor->setFullyQualifiedStructuralElementName($data->getName());
        $interfaceDescriptor->setName($data->getShortName());
        $interfaceDescriptor->setLine($data->getLinenumber());
        $interfaceDescriptor->setPackage($this->extractPackageFromDocBlock($data->getDocBlock()) ?: '');

        // Reflection library formulates namespace as global but this is not wanted for phpDocumentor itself
        $interfaceDescriptor->setNamespace(
            '\\' . (strtolower($data->getNamespace()) == 'global' ? '' :$data->getNamespace())
        );

        $this->assembleDocBlock($data->getDocBlock(), $interfaceDescriptor);
        $this->addConstants($data->getConstants(), $interfaceDescriptor);
        $this->addMethods($data->getMethods(), $interfaceDescriptor);

        foreach ($data->getParentInterfaces() as $interfaceClassName) {
            $interfaceDescriptor->getParent()->set($interfaceClassName, $interfaceClassName);
        }

        return $interfaceDescriptor;
    }

    /**
     * Registers the child constants with the generated Interface Descriptor.
     *
     * @param ConstantReflector[] $constants
     * @param InterfaceDescriptor $interfaceDescriptor
     *
     * @return void
     */
    protected function addConstants($constants, $interfaceDescriptor)
    {
        foreach ($constants as $constant) {
            $constantDescriptor = $this->getBuilder()->buildDescriptor($constant);
            if ($constantDescriptor) {
                $constantDescriptor->setParent($interfaceDescriptor);
                $interfaceDescriptor->getConstants()->set($constantDescriptor->getName(), $constantDescriptor);
            }
        }
    }

    /**
     * Registers the child methods with the generated Interface Descriptor.
     *
     * @param MethodReflector[] $methods
     * @param InterfaceDescriptor $interfaceDescriptor
     *
     * @return void
     */
    protected function addMethods($methods, $interfaceDescriptor)
    {
        foreach ($methods as $method) {
            $methodDescriptor = $this->getBuilder()->buildDescriptor($method);
            if ($methodDescriptor) {
                $methodDescriptor->setParent($interfaceDescriptor);
                $interfaceDescriptor->getMethods()->set($methodDescriptor->getName(), $methodDescriptor);
            }
        }
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder\Reflector;

use phpDocumentor\Descriptor\PropertyDescriptor;
use phpDocumentor\Reflection\ClassReflector\PropertyReflector;

/**
 * Assembles a PropertyDescriptor from a PropertyReflector.
 */
class PropertyAssembler extends AssemblerAbstract
{
    /**
     * Creates a Descriptor from the provided data.
     *
     * @param PropertyReflector $data
     *
     * @return PropertyDescriptor
     */
    public function create($data)
    {
        $propertyDescriptor = new PropertyDescriptor();
        $propertyDescriptor->setFullyQualifiedStructuralElementName($data->getName());
        $propertyDescriptor->setName($data->getShortName());
        $propertyDescriptor->setVisibility($data->getVisibility() ?: 'public');
        $propertyDescriptor->setStatic($data->isStatic());
        $propertyDescriptor->setDefault($data->getDefault());

        $this->assembleDocBlock($data->getDocBlock(), $propertyDescriptor);
        $propertyDescriptor->setLine($data->getLinenumber());

        return $propertyDescriptor;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder\Reflector;

use phpDocumentor\Descriptor\MethodDescriptor;
use phpDocumentor\Reflection\ClassReflector\MethodReflector;

/**
 * Assembles a MethodDescriptor from a MethodReflector.
 */
class MethodAssembler extends AssemblerAbstract
{
    /**
     * Creates a Descriptor from the provided data.
     *
     * @param MethodReflector $data
     *
     * @return MethodDescriptor
     */
    public function create($data)
    {
        $methodDescriptor = new MethodDescriptor();
        $methodDescriptor->setFullyQualifiedStructuralElementName($data->getName() . '()');
        $methodDescriptor->setName($data->getShortName());
        $methodDescriptor->setVisibility($data->getVisibility() ?: 'public');
        $methodDescriptor->setFinal($data->isFinal());
        $methodDescriptor->setAbstract($data->isAbstract());
        $methodDescriptor->setStatic($data->isStatic());

        $this->assembleDocBlock($data->getDocBlock(), $methodDescriptor);

        foreach ($data->getArguments() as $argument) {
            $argumentAssembler  = new ArgumentAssembler();
            $argumentDescriptor = $argumentAssembler->create(
                $argument,
                $methodDescriptor->getTags()->get('param', array())
            );
            $methodDescriptor->getArguments()->set($argumentDescriptor->getName(), $argumentDescriptor);
        }

        $methodDescriptor->setLine($data->getLinenumber());

        return $methodDescriptor;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder\Reflector;

use phpDocumentor\Descriptor\TraitDescriptor;
use phpDocumentor\Reflection\ClassReflector\MethodReflector;
use phpDocumentor\Reflection\ClassReflector\PropertyReflector;
use phpDocumentor\Reflection\TraitReflector;

/**
 * Assembles an TraitDescriptor using an TraitReflector.
 */
class TraitAssembler extends AssemblerAbstract
{
    /**
     * Creates a Descriptor from the provided data.
     *
     * @param TraitReflector $data
     *
     * @return TraitDescriptor
     */
    public function create($data)
    {
        $traitDescriptor = new TraitDescriptor();

        $traitDescriptor->setFullyQualifiedStructuralElementName($data->getName());
        $traitDescriptor->setName($data->getShortName());
        $traitDescriptor->setLine($data->getLinenumber());
        $traitDescriptor->setPackage($this->extractPackageFromDocBlock($data->getDocBlock()) ?: '');

        // Reflection library formulates namespace as global but this is not wanted for phpDocumentor itself
        $traitDescriptor->setNamespace(
            '\\' . (strtolower($data->getNamespace()) == 'global' ? '' :$data->getNamespace())
        );

        $this->assembleDocBlock($data->getDocBlock(), $traitDescriptor);

        $this->addProperties($data->getProperties(), $traitDescriptor);
        $this->addMethods($data->getMethods(), $traitDescriptor);

        return $traitDescriptor;
    }

    /**
     * Registers the child properties with the generated Trait Descriptor.
     *
     * @param PropertyReflector[] $properties
     * @param TraitDescriptor     $traitDescriptor
     *
     * @return void
     */
    protected function addProperties($properties, $traitDescriptor)
    {
        foreach ($properties as $property) {
            $propertyDescriptor = $this->getBuilder()->buildDescriptor($property);
            if ($propertyDescriptor) {
                $propertyDescriptor->setParent($traitDescriptor);
                $traitDescriptor->getProperties()->set($propertyDescriptor->getName(), $propertyDescriptor);
            }
        }
    }

    /**
     * Registers the child methods with the generated Trait Descriptor.
     *
     * @param MethodReflector[] $methods
     * @param TraitDescriptor   $traitDescriptor
     *
     * @return void
     */
    protected function addMethods($methods, $traitDescriptor)
    {
        foreach ($methods as $method) {
            $methodDescriptor = $this->getBuilder()->buildDescriptor($method);
            if ($methodDescriptor) {
                $methodDescriptor->setParent($traitDescriptor);
                $traitDescriptor->getMethods()->set($methodDescriptor->getName(), $methodDescriptor);
            }
        }
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder\Reflector;

use phpDocumentor\Descriptor\Collection;
use phpDocumentor\Descriptor\FileDescriptor;
use phpDocumentor\Reflection\ClassReflector;
use phpDocumentor\Reflection\ConstantReflector;
use phpDocumentor\Reflection\FileReflector;
use phpDocumentor\Reflection\FunctionReflector;
use phpDocumentor\Reflection\InterfaceReflector;
use phpDocumentor\Reflection\TraitReflector;

/**
 * Assembles an FileDescriptor using an FileReflector and ParamDescriptors.
 */
class FileAssembler extends AssemblerAbstract
{
    /**
     * Creates a Descriptor from the provided data.
     *
     * @param FileReflector $data
     *
     * @return FileDescriptor
     */
    public function create($data)
    {
        $fileDescriptor = new FileDescriptor($data->getHash());

        $fileDescriptor->setName(basename($data->getFilename()));
        $fileDescriptor->setPath($data->getFilename());
        $fileDescriptor->setSource($data->getContents());
        $fileDescriptor->setPackage(
            $this->extractPackageFromDocBlock($data->getDocBlock()) ?: $data->getDefaultPackageName()
        );
        $fileDescriptor->setIncludes(new Collection($data->getIncludes()));
        $fileDescriptor->setNamespaceAliases(new Collection($data->getNamespaceAliases()));

        $this->assembleDocBlock($data->getDocBlock(), $fileDescriptor);

        $this->addMarkers($data->getMarkers(), $fileDescriptor);
        $this->addConstants($data->getConstants(), $fileDescriptor);
        $this->addFunctions($data->getFunctions(), $fileDescriptor);
        $this->addClasses($data->getClasses(), $fileDescriptor);
        $this->addInterfaces($data->getInterfaces(), $fileDescriptor);
        $this->addTraits($data->getTraits(), $fileDescriptor);

        return $fileDescriptor;
    }

    /**
     * Registers the child constants with the generated File Descriptor.
     *
     * @param ConstantReflector[] $constants
     * @param FileDescriptor      $fileDescriptor
     *
     * @return void
     */
    protected function addConstants($constants, $fileDescriptor)
    {
        foreach ($constants as $constant) {
            $constantDescriptor = $this->getBuilder()->buildDescriptor($constant);
            if ($constantDescriptor) {
                $constantDescriptor->setLocation($fileDescriptor, $constant->getLineNumber());
                if ($constantDescriptor->getPackage() === '') {
                    $constantDescriptor->setPackage($fileDescriptor->getPackage());
                }

                $fileDescriptor->getConstants()->set(
                    $constantDescriptor->getFullyQualifiedStructuralElementName(),
                    $constantDescriptor
                );
            }
        }
    }

    /**
     * Registers the child functions with the generated File Descriptor.
     *
     * @param FunctionReflector[] $functions
     * @param FileDescriptor      $fileDescriptor
     *
     * @return void
     */
    protected function addFunctions($functions, $fileDescriptor)
    {
        foreach ($functions as $function) {
            $functionDescriptor = $this->getBuilder()->buildDescriptor($function);
            if ($functionDescriptor) {
                $functionDescriptor->setLocation($fileDescriptor, $function->getLineNumber());
                if ($functionDescriptor->getPackage() === '') {
                    $functionDescriptor->setPackage($fileDescriptor->getPackage());
                }

                $fileDescriptor->getFunctions()->set(
                    $functionDescriptor->getFullyQualifiedStructuralElementName(),
                    $functionDescriptor
                );
            }
        }
    }

    /**
     * Registers the child classes with the generated File Descriptor.
     *
     * @param ClassReflector[] $classes
     * @param FileDescriptor   $fileDescriptor
     *
     * @return void
     */
    protected function addClasses($classes, $fileDescriptor)
    {
        foreach ($classes as $class) {
            $classDescriptor = $this->getBuilder()->buildDescriptor($class);
            if ($classDescriptor) {
                $classDescriptor->setLocation($fileDescriptor, $class->getLineNumber());
                if ($classDescriptor->getPackage() === '') {
                    $classDescriptor->setPackage($fileDescriptor->getPackage());
                }

                $fileDescriptor->getClasses()->set(
                    $classDescriptor->getFullyQualifiedStructuralElementName(),
                    $classDescriptor
                );
            }
        }
    }

    /**
     * Registers the child interfaces with the generated File Descriptor.
     *
     * @param InterfaceReflector[] $interfaces
     * @param FileDescriptor   $fileDescriptor
     *
     * @return void
     */
    protected function addInterfaces($interfaces, $fileDescriptor)
    {
        foreach ($interfaces as $interface) {
            $interfaceDescriptor = $this->getBuilder()->buildDescriptor($interface);
            if ($interfaceDescriptor) {
                $interfaceDescriptor->setLocation($fileDescriptor, $interface->getLineNumber());
                if ($interfaceDescriptor->getPackage() === '') {
                    $interfaceDescriptor->setPackage($fileDescriptor->getPackage());
                }

                $fileDescriptor->getInterfaces()->set(
                    $interfaceDescriptor->getFullyQualifiedStructuralElementName(),
                    $interfaceDescriptor
                );
            }
        }
    }

    /**
     * Registers the child traits with the generated File Descriptor.
     *
     * @param TraitReflector[] $traits
     * @param FileDescriptor   $fileDescriptor
     *
     * @return void
     */
    protected function addTraits($traits, $fileDescriptor)
    {
        foreach ($traits as $trait) {
            $traitDescriptor = $this->getBuilder()->buildDescriptor($trait);
            if ($traitDescriptor) {
                $traitDescriptor->setLocation($fileDescriptor, $trait->getLineNumber());
                if ($traitDescriptor->getPackage() === '') {
                    $traitDescriptor->setPackage($fileDescriptor->getPackage());
                }

                $fileDescriptor->getTraits()->set(
                    $traitDescriptor->getFullyQualifiedStructuralElementName(),
                    $traitDescriptor
                );
            }
        }
    }

    /**
     * Registers the markers that were found in a File with the File Descriptor.
     *
     * @param string[]       $markers
     * @param FileDescriptor $fileDescriptor
     *
     * @return void
     */
    protected function addMarkers($markers, $fileDescriptor)
    {
        foreach ($markers as $marker) {
            list($type, $message, $line) = $marker;
            $fileDescriptor->getMarkers()->add(
                array(
                    'type'    => $type,
                    'message' => $message,
                    'line'    => $line,
                )
            );
        }
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder\Reflector\Tags;

use phpDocumentor\Descriptor\Tag\DeprecatedDescriptor;
use phpDocumentor\Descriptor\Builder\Reflector\AssemblerAbstract;
use phpDocumentor\Reflection\DocBlock\Tag\DeprecatedTag;

class DeprecatedAssembler extends AssemblerAbstract
{
    /**
     * Creates a new Descriptor from the given Reflector.
     *
     * @param DeprecatedTag $data
     *
     * @return DeprecatedDescriptor
     */
    public function create($data)
    {
        $descriptor = new DeprecatedDescriptor($data->getName());
        $descriptor->setDescription($data->getDescription());
        $descriptor->setVersion($data->getVersion());

        return $descriptor;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder\Reflector\Tags;

use phpDocumentor\Descriptor\Builder\Reflector\AssemblerAbstract;
use phpDocumentor\Descriptor\Tag\ReturnDescriptor;
use phpDocumentor\Reflection\DocBlock\Tag\ReturnTag;

class ReturnAssembler extends AssemblerAbstract
{
    /**
     * Creates a new Descriptor from the given Reflector.
     *
     * @param ReturnTag $data
     *
     * @return ReturnDescriptor
     */
    public function create($data)
    {
        $descriptor = new ReturnDescriptor($data->getName());
        $descriptor->setDescription($data->getDescription());
        $descriptor->setTypes($data->getTypes());

        return $descriptor;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder\Reflector\Tags;

use phpDocumentor\Descriptor\Builder\Reflector\AssemblerAbstract;
use phpDocumentor\Descriptor\Tag\UsesDescriptor;
use phpDocumentor\Reflection\DocBlock\Tag\UsesTag;

class UsesAssembler extends AssemblerAbstract
{
    /**
     * Creates a new Descriptor from the given Reflector.
     *
     * @param UsesTag $data
     *
     * @return UsesDescriptor
     */
    public function create($data)
    {
        $descriptor = new UsesDescriptor($data->getName());
        $descriptor->setDescription($data->getDescription());
        $descriptor->setReference($data->getReference());

        return $descriptor;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder\Reflector\Tags;

use phpDocumentor\Descriptor\Builder\Reflector\AssemblerAbstract;
use phpDocumentor\Descriptor\Tag\AuthorDescriptor;
use phpDocumentor\Reflection\DocBlock\Tag\AuthorTag;

class AuthorAssembler extends AssemblerAbstract
{
    /**
     * Creates a new Descriptor from the given Reflector.
     *
     * @param AuthorTag $data
     *
     * @return AuthorDescriptor
     */
    public function create($data)
    {
        $descriptor = new AuthorDescriptor($data->getName());
        $descriptor->setDescription($data->getDescription());

        return $descriptor;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder\Reflector\Tags;

use phpDocumentor\Descriptor\Builder\Reflector\AssemblerAbstract;
use phpDocumentor\Descriptor\Tag\ThrowsDescriptor;
use phpDocumentor\Reflection\DocBlock\Tag\ThrowsTag;

class ThrowsAssembler extends AssemblerAbstract
{
    /**
     * Creates a new Descriptor from the given Reflector.
     *
     * @param ThrowsTag $data
     *
     * @return ThrowsDescriptor
     */
    public function create($data)
    {
        $descriptor = new ThrowsDescriptor($data->getName());
        $descriptor->setDescription($data->getDescription());
        $descriptor->setTypes($data->getTypes());

        return $descriptor;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder\Reflector\Tags;

use phpDocumentor\Descriptor\Builder\Reflector\AssemblerAbstract;
use phpDocumentor\Descriptor\Tag\ParamDescriptor;
use phpDocumentor\Reflection\DocBlock\Tag\ParamTag;

class ParamAssembler extends AssemblerAbstract
{
    /**
     * Creates a new Descriptor from the given Reflector.
     *
     * @param ParamTag $data
     *
     * @return ParamDescriptor
     */
    public function create($data)
    {
        $descriptor = new ParamDescriptor($data->getName());
        $descriptor->setDescription($data->getDescription());
        $descriptor->setVariableName($data->getVariableName());
        $descriptor->setTypes($data->getTypes());

        return $descriptor;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder\Reflector\Tags;

use phpDocumentor\Descriptor\Builder\Reflector\AssemblerAbstract;
use phpDocumentor\Descriptor\Tag\SeeDescriptor;
use phpDocumentor\Reflection\DocBlock\Tag\SeeTag;
use phpDocumentor\Reflection\DocBlock\Type\Collection;

class SeeAssembler extends AssemblerAbstract
{
    /**
     * Creates a new Descriptor from the given Reflector.
     *
     * @param SeeTag $data
     *
     * @return SeeDescriptor
     */
    public function create($data)
    {
        $descriptor = new SeeDescriptor($data->getName());
        $descriptor->setDescription($data->getDescription());

        // TODO: move this to the ReflectionDocBlock component
        // Expand FQCN part of the FQSEN
        $referenceParts = explode('::', $data->getReference());
        $type = current($referenceParts);
        $type = new Collection(
            array($type),
            $data->getDocBlock() ? $data->getDocBlock()->getContext() : null
        );
        $referenceParts[0] = $type;

        $descriptor->setReference(implode('::', $referenceParts));

        return $descriptor;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder\Reflector\Tags;

use phpDocumentor\Descriptor\Builder\Reflector\AssemblerAbstract;
use phpDocumentor\Descriptor\Tag\PropertyDescriptor;
use phpDocumentor\Reflection\DocBlock\Tag\PropertyTag;

class PropertyAssembler extends AssemblerAbstract
{
    /**
     * Creates a new Descriptor from the given Reflector.
     *
     * @param PropertyTag $data
     *
     * @return PropertyDescriptor
     */
    public function create($data)
    {
        $descriptor = new PropertyDescriptor($data->getName());
        $descriptor->setVariableName($data->getVariableName());
        $descriptor->setDescription($data->getDescription());
        $descriptor->setTypes($data->getTypes());

        return $descriptor;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder\Reflector\Tags;

use phpDocumentor\Descriptor\ArgumentDescriptor;
use phpDocumentor\Descriptor\Builder\Reflector\AssemblerAbstract;
use phpDocumentor\Descriptor\Tag\MethodDescriptor;
use phpDocumentor\Descriptor\Tag\ReturnDescriptor;
use phpDocumentor\Reflection\DocBlock\Tag\MethodTag;

class MethodAssembler extends AssemblerAbstract
{
    /**
     * Creates a new Descriptor from the given Reflector.
     *
     * @param MethodTag $data
     *
     * @return MethodDescriptor
     */
    public function create($data)
    {
        $descriptor = new MethodDescriptor($data->getName());
        $descriptor->setDescription($data->getDescription());
        $descriptor->setMethodName($data->getMethodName());

        $response = new ReturnDescriptor('return');
        $response->setTypes($data->getTypes());
        $descriptor->setResponse($response);

        foreach ($data->getArguments() as $argument) {
            if (count($argument) > 1) {
                list($argumentType, $argumentName) = $argument;
            } else {
                $argumentName = current($argument);
                $argumentType = 'mixed';
            }
            $argumentDescriptor = new ArgumentDescriptor();
            $argumentDescriptor->setTypes(array($argumentType));
            $argumentDescriptor->setName($argumentName);
            $descriptor->getArguments()->set($argumentName, $argumentDescriptor);
        }

        return $descriptor;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder\Reflector\Tags;

use phpDocumentor\Descriptor\Builder\Reflector\AssemblerAbstract;
use phpDocumentor\Descriptor\Tag\VersionDescriptor;
use phpDocumentor\Reflection\DocBlock\Tag\VersionTag;

class VersionAssembler extends AssemblerAbstract
{
    /**
     * Creates a new Descriptor from the given Reflector.
     *
     * @param VersionTag $data
     *
     * @return VersionDescriptor
     */
    public function create($data)
    {
        $descriptor = new VersionDescriptor($data->getName());
        $descriptor->setDescription($data->getDescription());
        $descriptor->setVersion($data->getVersion());

        return $descriptor;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder\Reflector\Tags;

use phpDocumentor\Descriptor\Builder\Reflector\AssemblerAbstract;
use phpDocumentor\Descriptor\TagDescriptor;
use phpDocumentor\Reflection\DocBlock\Tag;

class GenericTagAssembler extends AssemblerAbstract
{
    /**
     * Creates a new Descriptor from the given Reflector.
     *
     * @param Tag $data
     *
     * @return TagDescriptor
     */
    public function create($data)
    {
        $descriptor = new TagDescriptor($data->getName());
        $descriptor->setDescription($data->getDescription());

        return $descriptor;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder\Reflector\Tags;

use phpDocumentor\Descriptor\Builder\Reflector\AssemblerAbstract;
use phpDocumentor\Descriptor\Tag\LinkDescriptor;
use phpDocumentor\Reflection\DocBlock\Tag\LinkTag;

class LinkAssembler extends AssemblerAbstract
{
    /**
     * Creates a new Descriptor from the given Reflector.
     *
     * @param LinkTag $data
     *
     * @return LinkDescriptor
     */
    public function create($data)
    {
        $descriptor = new LinkDescriptor($data->getName());
        $descriptor->setLink($data->getLink());
        $descriptor->setDescription($data->getDescription());

        return $descriptor;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder\Reflector\Tags;

use phpDocumentor\Descriptor\Builder\Reflector\AssemblerAbstract;
use phpDocumentor\Descriptor\Tag\VarDescriptor;
use phpDocumentor\Reflection\DocBlock\Tag\VarTag;

class VarAssembler extends AssemblerAbstract
{
    /**
     * Creates a new Descriptor from the given Reflector.
     *
     * @param VarTag $data
     *
     * @return VarDescriptor
     */
    public function create($data)
    {
        $descriptor = new VarDescriptor($data->getName());
        $descriptor->setDescription($data->getDescription());
        $descriptor->setTypes($data->getTypes());
        $descriptor->setVariableName($data->getVariableName());

        return $descriptor;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder\Reflector\Tags;

use phpDocumentor\Descriptor\Builder\Reflector\AssemblerAbstract;
use phpDocumentor\Descriptor\Tag\SinceDescriptor;
use phpDocumentor\Reflection\DocBlock\Tag\SinceTag;

class SinceAssembler extends AssemblerAbstract
{
    /**
     * Creates a new Descriptor from the given Reflector.
     *
     * @param SinceTag $data
     *
     * @return SinceDescriptor
     */
    public function create($data)
    {
        $descriptor = new SinceDescriptor($data->getName());
        $descriptor->setDescription($data->getDescription());
        $descriptor->setVersion($data->getVersion());

        return $descriptor;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder\Reflector;

use phpDocumentor\Descriptor\Builder\AssemblerAbstract as BaseAssembler;
use phpDocumentor\Descriptor\Collection;
use phpDocumentor\Descriptor\DescriptorAbstract;
use phpDocumentor\Reflection\DocBlock;

abstract class AssemblerAbstract extends BaseAssembler
{
    /**
     * @param DocBlock           $docBlock
     * @param DescriptorAbstract $target
     */
    protected function assembleDocBlock($docBlock, $target)
    {
        if (!$docBlock) {
            return;
        }

        $target->setSummary($docBlock->getShortDescription());
        $target->setDescription($docBlock->getLongDescription()->getContents());

        /** @var DocBlock\Tag $tag */
        foreach ($docBlock->getTags() as $tag) {
            $tagDescriptor = $this->builder->buildDescriptor($tag);

            // allow filtering of tags
            if (!$tagDescriptor) {
                continue;
            }

            $target->getTags()
                ->get($tag->getName(), new Collection())
                ->add($tagDescriptor);
        }
    }

    /**
     * Extracts the package from the DocBlock.
     *
     * @param DocBlock $docBlock
     *
     * @return string|null
     */
    protected function extractPackageFromDocBlock($docBlock)
    {
        $packageTags = $docBlock ? $docBlock->getTagsByName('package') : null;
        if (! $packageTags) {
            return null;
        }

        /** @var DocBlock\Tag $tag */
        $tag = reset($packageTags);

        return trim($tag->getContent());
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder\Reflector;

use phpDocumentor\Descriptor\ArgumentDescriptor;
use phpDocumentor\Descriptor\Tag\ParamDescriptor;
use phpDocumentor\Reflection\FunctionReflector\ArgumentReflector;

/**
 * Assembles an ArgumentDescriptor using an ArgumentReflector and ParamDescriptors.
 */
class ArgumentAssembler extends AssemblerAbstract
{
    /**
     * Creates a Descriptor from the provided data.
     *
     * @param ArgumentReflector $data
     * @param ParamDescriptor[] $params
     *
     * @return ArgumentDescriptor
     */
    public function create($data, $params = array())
    {
        $argumentDescriptor = new ArgumentDescriptor();
        $argumentDescriptor->setName($data->getName());
        $argumentDescriptor->setTypes($data->getType() ? array($data->getType()) : array());

        /** @var ParamDescriptor $tag */
        foreach ($params as $tag) {
            if ($tag->getVariableName() == $data->getName()) {
                $argumentDescriptor->setDescription($tag->getDescription());

                $types = $tag->getTypes() ?: array($data->getType() ?: 'mixed');
                $argumentDescriptor->setTypes($types);
            }
        }

        $argumentDescriptor->setDefault($data->getDefault());
        $argumentDescriptor->setByReference($data->isByRef());

        return $argumentDescriptor;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder\Reflector;

use phpDocumentor\Descriptor\FunctionDescriptor;
use phpDocumentor\Reflection\FunctionReflector;

/**
 * Assembles a FunctionDescriptor from a FunctionReflector.
 */
class FunctionAssembler extends AssemblerAbstract
{
    /**
     * Creates a Descriptor from the provided data.
     *
     * @param FunctionReflector $data
     *
     * @return FunctionDescriptor
     */
    public function create($data)
    {
        $functionDescriptor = new FunctionDescriptor();
        $functionDescriptor->setFullyQualifiedStructuralElementName($data->getName() . '()');
        $functionDescriptor->setName($data->getShortName());
        $functionDescriptor->setLine($data->getLinenumber());

        // Reflection library formulates namespace as global but this is not wanted for phpDocumentor itself
        $functionDescriptor->setNamespace(
            '\\' . (strtolower($data->getNamespace()) == 'global' ? '' :$data->getNamespace())
        );

        $this->assembleDocBlock($data->getDocBlock(), $functionDescriptor);

        foreach ($data->getArguments() as $argument) {
            $argumentAssembler  = new ArgumentAssembler();
            $argumentDescriptor = $argumentAssembler->create(
                $argument,
                $functionDescriptor->getTags()->get('param', array())
            );
            $functionDescriptor->getArguments()->set($argumentDescriptor->getName(), $argumentDescriptor);
        }

        return $functionDescriptor;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder;

use phpDocumentor\Descriptor\DescriptorAbstract;
use phpDocumentor\Descriptor\ProjectDescriptorBuilder;

/**
 * Interface for Assembler classes that transform data to specific Descriptor types.
 */
interface AssemblerInterface
{
    /**
     * Creates a Descriptor from the provided data.
     *
     * @param mixed $data
     *
     * @return DescriptorAbstract
     */
    public function create($data);

    public function setBuilder(ProjectDescriptorBuilder $builder);
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder;

use phpDocumentor\Descriptor\ProjectDescriptorBuilder;

/**
 * Base class for all assemblers.
 */
abstract class AssemblerAbstract implements AssemblerInterface
{
    /** @var ProjectDescriptorBuilder|null $builder */
    protected $builder;

    /**
     * Returns the builder for this Assembler or null if none is set.
     *
     * @return null|ProjectDescriptorBuilder
     */
    public function getBuilder()
    {
        return $this->builder;
    }

    /**
     * Registers the Builder with this Assembler.
     *
     * The Builder may be used to recursively assemble Descriptors using
     * the {@link ProjectDescriptorBuilder::buildDescriptor()} method.
     *
     * @param ProjectDescriptorBuilder $builder
     *
     * @return void
     */
    public function setBuilder(ProjectDescriptorBuilder $builder)
    {
        $this->builder = $builder;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Builder;

/**
 * Attempts to retrieve an Assembler for the provided criteria.
 */
class AssemblerFactory
{
    /** @var mixed[]  */
    protected $assemblers = array();
    protected $fallbackAssemblers = array();

    /**
     * Registers an assembler instance to this factory.
     *
     * @param callable           $matcher   A callback function accepting the criteria as only parameter and which must
     *     return a boolean.
     * @param AssemblerInterface $assembler An instance of the Assembler that will be returned if the callback returns
     *     true with the provided criteria.
     *
     * @return void
     */
    public function register($matcher, AssemblerInterface $assembler)
    {
        $this->assemblers[] = array(
            'matcher'   => $matcher,
            'assembler' => $assembler
        );
    }

    /**
     * Registers an assembler instance to this factory that is to be executed after all other assemblers have been
     * checked.
     *
     * @param callable           $matcher   A callback function accepting the criteria as only parameter and which must
     *     return a boolean.
     * @param AssemblerInterface $assembler An instance of the Assembler that will be returned if the callback returns
     *     true with the provided criteria.
     *
     * @return void
     */
    public function registerFallback($matcher, AssemblerInterface $assembler)
    {
        $this->fallbackAssemblers[] = array(
            'matcher'   => $matcher,
            'assembler' => $assembler
        );
    }

    /**
     * Retrieves a matching Assembler based on the provided criteria or null if none was found.
     *
     * @param mixed $criteria
     *
     * @return AssemblerInterface|null
     */
    public function get($criteria)
    {
        foreach (array_merge($this->assemblers, $this->fallbackAssemblers) as $candidate) {
            $matcher = $candidate['matcher'];
            if ($matcher($criteria) === true) {
                return $candidate['assembler'];
            }
        }

        return null;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor;

/**
 * Descriptor representing a Class.
 */
class ClassDescriptor extends DescriptorAbstract implements Interfaces\ClassInterface
{
    /** @var ClassDescriptor|null $extends Reference to an instance of the superclass for this class, if any. */
    protected $parent;

    /** @var Collection $implements References to interfaces that are implemented by this class. */
    protected $implements;

    /** @var boolean $abstract Whether this is an abstract class. */
    protected $abstract = false;

    /** @var boolean $final Whether this class is marked as final and can't be subclassed. */
    protected $final = false;

    /** @var Collection $constants References to constants defined in this class. */
    protected $constants;

    /** @var Collection $properties References to properties defined in this class. */
    protected $properties;

    /** @var Collection $methods References to methods defined in this class. */
    protected $methods;

    /** @var Collection $usedTraits References to traits consumed by this class */
    protected $usedTraits = array();

    /**
     * Initializes the all properties representing a collection with a new Collection object.
     */
    public function __construct()
    {
        parent::__construct();

        $this->setInterfaces(new Collection());
        $this->setUsedTraits(new Collection());
        $this->setConstants(new Collection());
        $this->setProperties(new Collection());
        $this->setMethods(new Collection());
    }

    /**
     * {@inheritDoc}
     */
    public function setParent($parents)
    {
        $this->parent = $parents;
    }

    /**
     * {@inheritDoc}
     */
    public function getParent()
    {
        return $this->parent;
    }

    /**
     * {@inheritDoc}
     */
    public function setInterfaces(Collection $implements)
    {
        $this->implements = $implements;
    }

    /**
     * {@inheritDoc}
     */
    public function getInterfaces()
    {
        return $this->implements;
    }

    /**
     * {@inheritDoc}
     */
    public function setFinal($final)
    {
        $this->final = $final;
    }

    /**
     * {@inheritDoc}
     */
    public function isFinal()
    {
        return $this->final;
    }

    /**
     * {@inheritDoc}
     */
    public function setAbstract($abstract)
    {
        $this->abstract = $abstract;
    }

    /**
     * {@inheritDoc}
     */
    public function isAbstract()
    {
        return $this->abstract;
    }

    /**
     * {@inheritDoc}
     */
    public function setConstants(Collection $constants)
    {
        $this->constants = $constants;
    }

    /**
     * {@inheritDoc}
     */
    public function getConstants()
    {
        return $this->constants;
    }

    /**
     * {@inheritDoc}
     */
    public function getInheritedConstants()
    {
        if (!$this->getParent() || (!$this->getParent() instanceof ClassDescriptor)) {
            return new Collection();
        }

        $inheritedConstants = clone $this->getParent()->getConstants();

        return $inheritedConstants->merge($this->getParent()->getInheritedConstants());
    }

    /**
     * {@inheritDoc}
     */
    public function setMethods(Collection $methods)
    {
        $this->methods = $methods;
    }

    /**
     * {@inheritDoc}
     */
    public function getMethods()
    {
        return $this->methods;
    }

    /**
     * {@inheritDoc}
     */
    public function getInheritedMethods()
    {
        if (!$this->getParent() || (!$this->getParent() instanceof ClassDescriptor)) {
            return new Collection();
        }

        $inheritedMethods = clone $this->getParent()->getMethods();

        return $inheritedMethods->merge($this->getParent()->getInheritedMethods());
    }

    /**
     * @return Collection
     */
    public function getMagicMethods()
    {
        /** @var Collection $methodTags */
        $methodTags = clone $this->getTags()->get('method', new Collection());

        $methods = new Collection();

        /** @var Tag\MethodDescriptor $methodTag */
        foreach ($methodTags as $methodTag) {
            $method = new MethodDescriptor();
            $method->setName($methodTag->getMethodName());
            $method->setDescription($methodTag->getDescription());
            $method->setParent($this);

            $returnTags = $method->getTags()->get('return', new Collection());
            $returnTags->add($methodTag->getResponse());

            foreach ($methodTag->getArguments() as $name => $argument) {
                $method->getArguments()->set($name, $argument);
            }

            $methods->add($method);
        }

        if ($this->getParent() instanceof static) {
            $methods = $methods->merge($this->getParent()->getMagicMethods());
        }

        return $methods;
    }

    /**
     * {@inheritDoc}
     */
    public function setProperties(Collection $properties)
    {
        $this->properties = $properties;
    }

    /**
     * {@inheritDoc}
     */
    public function getProperties()
    {
        return $this->properties;
    }

    /**
     * {@inheritDoc}
     */
    public function getInheritedProperties()
    {
        if (!$this->getParent() || (!$this->getParent() instanceof ClassDescriptor)) {
            return new Collection();
        }

        $inheritedProperties = clone $this->getParent()->getProperties();

        return $inheritedProperties->merge($this->getParent()->getInheritedProperties());
    }

    /**
     * @return Collection
     */
    public function getMagicProperties()
    {
        /** @var Collection $propertyTags */
        $propertyTags = clone $this->getTags()->get('property', new Collection());
        $propertyTags = $propertyTags->merge($this->getTags()->get('property-read', new Collection()));
        $propertyTags = $propertyTags->merge($this->getTags()->get('property-write', new Collection()));

        $properties = new Collection();

        /** @var Tag\PropertyDescriptor $propertyTag */
        foreach ($propertyTags as $propertyTag) {
            $property = new PropertyDescriptor();
            $property->setName(ltrim($propertyTag->getVariableName(), '$'));
            $property->setDescription($propertyTag->getDescription());
            $property->setTypes($propertyTag->getTypes());
            $property->setParent($this);

            $properties->add($property);
        }

        if ($this->getParent() instanceof ClassDescriptor) {
            $properties = $properties->merge($this->getParent()->getMagicProperties());
        }

        return $properties;
    }

    public function setPackage($package)
    {
        parent::setPackage($package);

        foreach ($this->getConstants() as $constant) {
            // TODO #840: Workaround; for some reason there are NULLs in the constants array.
            if ($constant) {
                $constant->setPackage($package);
            }
        }

        foreach ($this->getProperties() as $property) {
            // TODO #840: Workaround; for some reason there are NULLs in the properties array.
            if ($property) {
                $property->setPackage($package);
            }
        }

        foreach ($this->getMethods() as $method) {
            // TODO #840: Workaround; for some reason there are NULLs in the methods array.
            if ($method) {
                $method->setPackage($package);
            }
        }
    }

    /**
     * Sets a collection of all traits used by this class.
     *
     * @param Collection $usedTraits
     *
     * @return void
     */
    public function setUsedTraits($usedTraits)
    {
        $this->usedTraits = $usedTraits;
    }

    /**
     * Returns the traits used by this class.
     *
     * Returned values may either be a string (when the Trait is not in this project) or a TraitDescriptor.
     *
     * @return Collection
     */
    public function getUsedTraits()
    {
        return $this->usedTraits;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Validator;

/**
 * Struct to record a validation error.
 */
class Error
{
    protected $severity;
    protected $code;
    protected $line = 0;
    protected $context = array();

    public function __construct($severity, $code, $line, array $context = array())
    {
        $this->severity = $severity;
        $this->code     = $code;
        $this->line     = $line;
        $this->context  = $context;
    }

    public function getCode()
    {
        return $this->code;
    }

    public function getLine()
    {
        return $this->line;
    }

    public function getSeverity()
    {
        return $this->severity;
    }

    public function getContext()
    {
        return $this->context;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor;

/**
 * Analyzes a Project Descriptor and collects key information.
 *
 * This class can be used by external tools to analyze the Project Descriptor and collect key information from it such
 * as the total number of elements per type of Descriptor, the number of top level namespaces or the number of parent
 * classes that could not be interpreted by the Compiler passes.
 */
class ProjectAnalyzer
{
    /** @var integer $elementCount */
    protected $elementCount = 0;

    /** @var integer $fileCount */
    protected $fileCount = 0;

    /** @var integer $topLevelNamespaceCount */
    protected $topLevelNamespaceCount = 0;

    /** @var integer $unresolvedParentClassesCount */
    protected $unresolvedParentClassesCount = 0;

    /** @var integer[] $descriptorCountByType */
    protected $descriptorCountByType = array();

    /**
     * Analyzes the given project descriptor and populates this object's properties.
     *
     * @param ProjectDescriptor $projectDescriptor
     *
     * @return void
     */
    public function analyze(ProjectDescriptor $projectDescriptor)
    {
        $this->unresolvedParentClassesCount = 0;

        $elementCounter = array();
        foreach ($projectDescriptor->getIndexes()->elements as $element) {
            if (!isset($elementCounter[get_class($element)])) {
                $elementCounter[get_class($element)] = 0;
            }
            $elementCounter[get_class($element)]++;

            if ($element instanceof ClassDescriptor) {
                if (is_string($element->getParent())) {
                    $this->unresolvedParentClassesCount++;
                }
            }
        }

        $this->descriptorCountByType  = $elementCounter;
        $this->fileCount              = count($projectDescriptor->getFiles());
        $this->topLevelNamespaceCount = count($projectDescriptor->getNamespace()->getChildren());
    }

    /**
     * Returns a textual report of the findings of this class.
     *
     * @return string
     */
    public function __toString()
    {
        $logString = <<<TEXT
In the ProjectDescriptor are:
  %8d files
  %8d top-level namespaces
  %8d unresolvable parent classes

TEXT;
        foreach ($this->descriptorCountByType as $class => $count) {
            $logString .= sprintf('  %8d %s elements' . PHP_EOL, $count, $class);
        }

        return sprintf(
            $logString,
            $this->fileCount,
            $this->topLevelNamespaceCount,
            $this->unresolvedParentClassesCount
        );
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor;

/**
 * Descriptor representing an Interface.
 */
class InterfaceDescriptor extends DescriptorAbstract implements Interfaces\InterfaceInterface
{
    /** @var Collection $extends */
    protected $parents;

    /** @var Collection $constants */
    protected $constants;

    /** @var Collection $methods */
    protected $methods;

    /**
     * Initializes the all properties representing a collection with a new Collection object.
     */
    public function __construct()
    {
        parent::__construct();

        $this->setParent(new Collection());
        $this->setConstants(new Collection());
        $this->setMethods(new Collection());
    }

    /**
     * {@inheritDoc}
     */
    public function setParent($parents)
    {
        $this->parents = $parents;
    }

    /**
     * {@inheritDoc}
     */
    public function getParent()
    {
        return $this->parents;
    }

    /**
     * {@inheritDoc}
     */
    public function setConstants(Collection $constants)
    {
        $this->constants = $constants;
    }

    /**
     * {@inheritDoc}
     */
    public function getConstants()
    {
        return $this->constants;
    }

    /**
     * {@inheritDoc}
     */
    public function getInheritedConstants()
    {
        if (!$this->getParent() || !$this->getParent() instanceof Collection || $this->getParent()->count() === 0) {
            return new Collection();
        }

        $inheritedConstants = new Collection();

        /** @var self $parent */
        foreach ($this->getParent() as $parent) {
            if (!$parent instanceof Interfaces\InterfaceInterface) {
                continue;
            }

            $inheritedConstants = $inheritedConstants->merge($parent->getConstants());
            $inheritedConstants = $inheritedConstants->merge($parent->getInheritedConstants());
        }

        return $inheritedConstants;
    }

    /**
     * {@inheritDoc}
     */
    public function setMethods(Collection $methods)
    {
        $this->methods = $methods;
    }

    /**
     * {@inheritDoc}
     */
    public function getMethods()
    {
        return $this->methods;
    }

    /**
     * {@inheritDoc}
     */
    public function getInheritedMethods()
    {
        if (!$this->getParent() || !$this->getParent() instanceof Collection || $this->getParent()->count() === 0) {
            return new Collection();
        }

        $inheritedMethods = new Collection();

        /** @var self $parent */
        foreach ($this->getParent() as $parent) {
            if (!$parent instanceof Interfaces\InterfaceInterface) {
                continue;
            }

            $inheritedMethods = $inheritedMethods->merge($parent->getMethods());
            $inheritedMethods = $inheritedMethods->merge($parent->getInheritedMethods());
        }

        return $inheritedMethods;
    }

    public function setPackage($package)
    {
        parent::setPackage($package);

        foreach ($this->getConstants() as $constant) {
            $constant->setPackage($package);
        }

        foreach ($this->getMethods() as $method) {
            $method->setPackage($package);
        }
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Filter;

use phpDocumentor\Descriptor\DescriptorAbstract;
use phpDocumentor\Descriptor\ProjectDescriptorBuilder;
use Zend\Filter\AbstractFilter;

/**
 * Strips any Descriptor if the ignore tag is present with that element.
 */
class StripIgnore extends AbstractFilter
{
    /** @var ProjectDescriptorBuilder $builder */
    protected $builder;

    /**
     * Initializes this filter with an instance of the builder to retrieve the latest ProjectDescriptor from.
     *
     * @param ProjectDescriptorBuilder $builder
     */
    public function __construct(ProjectDescriptorBuilder $builder)
    {
        $this->builder = $builder;
    }

    /**
     * Filter Descriptor with ignore tags.
     *
     * @param DescriptorAbstract $value
     *
     * @return DescriptorAbstract|null
     */
    public function filter($value)
    {
        if (!is_null($value) && $value->getTags()->get('ignore')) {
            return null;
        }

        return $value;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Filter;

use phpDocumentor\Descriptor\DescriptorAbstract;
use phpDocumentor\Descriptor\ProjectDescriptor\Settings;
use phpDocumentor\Descriptor\ProjectDescriptorBuilder;
use Zend\Filter\AbstractFilter;

/**
 * Filters a Descriptor when the @internal inline tag, or normal tag, is used.
 *
 * When a Descriptor's description contains the inline tag @internal then the description of that tag should be
 * included only when the visibility allows INTERNAL information. Otherwise it needs to be removed.
 *
 * Similarly, whenever the normal @internal tag is used should this filter return null if the visibility does not allow
 * INTERNAL information. This will remove this descriptor from the project.
 *
 * @link http://www.phpdoc.org/docs/latest/for-users/phpdoc/tags/internal.html
 */
class StripInternal extends AbstractFilter
{
    /** @var ProjectDescriptorBuilder $builder */
    protected $builder;

    /**
     * Initializes this filter with an instance of the builder to retrieve the latest ProjectDescriptor from.
     *
     * @param ProjectDescriptorBuilder $builder
     */
    public function __construct(ProjectDescriptorBuilder $builder)
    {
        $this->builder = $builder;
    }

    /**
     * If the ProjectDescriptor's settings allow internal tags then return the Descriptor, otherwise null to filter it.
     *
     * @param DescriptorAbstract $value
     *
     * @return DescriptorAbstract|null
     */
    public function filter($value)
    {
        $isInternalAllowed = $this->builder->isVisibilityAllowed(Settings::VISIBILITY_INTERNAL);
        if ($isInternalAllowed) {
            $value->setDescription(preg_replace('/{@internal\ (.+)}}/', '$1', $value->getDescription()));

            return $value;
        }

        // remove inline @internal tags
        $value->setDescription(preg_replace('/{@internal\ .+}}/', '', $value->getDescription()));

        // if internal elements are not allowed; filter this element
        if ($value->getTags()->get('internal')) {
            return null;
        }

        return $value;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Filter;

use Zend\Filter\FilterInterface;

/**
 * Filter used to manipulate a descriptor after being build.
 *
 * This class is used during the building of descriptors. It passes the descriptor to each individual sub-filter, which
 * may change data in the descriptor or even remove it from the building process by returning null.
 */
class Filter
{
    /** @var int default priority for a filter in the series of filters. */
    const DEFAULT_PRIORITY = 1000;

    /** @var ClassFactory  */
    protected $factory;

    /**
     * Constructs the filter and attaches the factory to it.
     *
     * @param ClassFactory $factory
     */
    public function __construct($factory)
    {
        $this->factory = $factory;
    }

    /**
     * Attaches a filter to a specific FQCN.
     *
     * @param string          $fqcn
     * @param FilterInterface $filter
     * @param int             $priority [1000]
     *
     * @return void
     */
    public function attach($fqcn, $filter, $priority = self::DEFAULT_PRIORITY)
    {
        $chain = $this->factory->getChainFor($fqcn);
        $chain->attach($filter, $priority);
    }

    /**
     * Filters the given Descriptor and returns the altered object.
     *
     * @param Filterable $descriptor
     *
     * @return Filterable|null
     */
    public function filter(Filterable $descriptor)
    {
        $chain = $this->factory->getChainFor(get_class($descriptor));

        return $chain->filter($descriptor);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Filter;

use Zend\Filter\FilterChain;

/**
 * Retrieves a series of filters to manipulate a specific Descriptor with during building.
 */
class ClassFactory
{
    /** @var FilterChain[]  */
    protected $chains = array();

    /**
     * Retrieves the filters for a class with a given FQCN.
     *
     * @param string $fqcn
     *
     * @return FilterChain
     */
    public function getChainFor($fqcn)
    {
        if (!isset($this->chains[$fqcn])) {
            $this->chains[$fqcn] = new FilterChain();
        }

        return $this->chains[$fqcn];
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Filter;

use phpDocumentor\Descriptor\Collection;

/**
 * Interface to determine which elements can be filtered and to provide a way to set errors on the descriptor.
 */
interface Filterable
{
    /**
     * Sets a list of errors on the associated element.
     *
     * @param Collection $errors
     *
     * @return void
     */
    public function setErrors(Collection $errors);
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor;

/**
 * Represents a namespace and its children for a project.
 */
class NamespaceDescriptor extends DescriptorAbstract implements Interfaces\NamespaceInterface
{
    /** @var NamespaceDescriptor $parentNamespace */
    protected $parent;

    /** @var Collection $namespaces*/
    protected $children;

    /** @var Collection $functions*/
    protected $functions;

    /** @var Collection $constants*/
    protected $constants;

    /** @var Collection $classes*/
    protected $classes;

    /** @var Collection $interfaces*/
    protected $interfaces;

    /** @var Collection $traits*/
    protected $traits;

    /**
     * Initializes the namespace with collections for its children.
     */
    public function __construct()
    {
        $this->setChildren(new Collection());
        $this->setFunctions(new Collection());
        $this->setConstants(new Collection());
        $this->setClasses(new Collection());
        $this->setInterfaces(new Collection());
        $this->setTraits(new Collection());
    }

    /**
     * Sets the parent namespace for this namespace.
     *
     * @param NamespaceDescriptor $parent
     *
     * @return void
     */
    public function setParent($parent)
    {
        $this->parent = $parent;
    }

    /**
     * Returns the parent namespace for this namespace.
     *
     * @return NamespaceDescriptor|null
     */
    public function getParent()
    {
        return $this->parent;
    }

    /**
     * Sets a list of all classes in this project.
     *
     * @param Collection $classes
     *
     * @return void
     */
    public function setClasses(Collection $classes)
    {
        $this->classes = $classes;
    }

    /**
     * Returns a list of all classes in this namespace.
     *
     * @return Collection
     */
    public function getClasses()
    {
        return $this->classes;
    }

    /**
     * Sets a list of all constants in this namespace.
     *
     * @param Collection $constants
     *
     * @return void
     */
    public function setConstants(Collection $constants)
    {
        $this->constants = $constants;
    }

    /**
     * Returns a list of all constants in this namespace.
     *
     * @return Collection
     */
    public function getConstants()
    {
        return $this->constants;
    }

    /**
     * Sets a list of all functions in this namespace.
     *
     * @param Collection $functions
     *
     * @return void
     */
    public function setFunctions(Collection $functions)
    {
        $this->functions = $functions;
    }

    /**
     * Returns a list of all functions in this namespace.
     *
     * @return Collection
     */
    public function getFunctions()
    {
        return $this->functions;
    }

    /**
     * Sets a list of all interfaces in this namespace.
     *
     * @param Collection $interfaces
     *
     * @return void
     */
    public function setInterfaces(Collection $interfaces)
    {
        $this->interfaces = $interfaces;
    }

    /**
     * Returns a list of all interfaces in this namespace.
     *
     * @return Collection
     */
    public function getInterfaces()
    {
        return $this->interfaces;
    }

    /**
     * Sets a list of all child namespaces in this namespace.
     *
     * @param Collection $children
     *
     * @return void
     */
    public function setChildren(Collection $children)
    {
        $this->children = $children;
    }

    /**
     * Returns a list of all namespaces contained in this namespace and its children.
     *
     * @return Collection
     */
    public function getChildren()
    {
        return $this->children;
    }

    /**
     * Sets a list of all traits contained in this namespace.
     *
     * @param Collection $traits
     *
     * @return void
     */
    public function setTraits($traits)
    {
        $this->traits = $traits;
    }

    /**
     * Returns a list of all traits in this namespace.
     *
     * @return Collection
     */
    public function getTraits()
    {
        return $this->traits;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor;

use phpDocumentor\Descriptor\Interfaces\ClassInterface;
use phpDocumentor\Descriptor\Interfaces\FunctionInterface;
use phpDocumentor\Descriptor\Interfaces\InterfaceInterface;
use phpDocumentor\Descriptor\Interfaces\TraitInterface;

/**
 * Represents a file in the project.
 */
class FileDescriptor extends DescriptorAbstract implements Interfaces\FileInterface
{
    /** @var string $hash */
    protected $hash;

    /** @var string $path */
    protected $path = '';

    /** @var string|null $source */
    protected $source = null;

    /** @var Collection $namespace_aliases */
    protected $namespaceAliases;

    /** @var Collection $includes */
    protected $includes;

    /** @var Collection $constants */
    protected $constants;

    /** @var Collection $functions */
    protected $functions;

    /** @var Collection $classes */
    protected $classes;

    /** @var Collection $interfaces */
    protected $interfaces;

    /** @var Collection $traits */
    protected $traits;

    /** @var Collection $errors */
    protected $markers;

    /**
     * Initializes a new file descriptor with the given hash of its contents.
     *
     * @param string $hash An MD5 hash of the contents if this file.
     */
    public function __construct($hash)
    {
        parent::__construct();

        $this->setHash($hash);
        $this->setNamespaceAliases(new Collection());
        $this->setIncludes(new Collection());

        $this->setConstants(new Collection());
        $this->setFunctions(new Collection());
        $this->setClasses(new Collection());
        $this->setInterfaces(new Collection());
        $this->setTraits(new Collection());

        $this->setMarkers(new Collection());
    }

    /**
     * Returns the hash of the contents for this file.
     *
     * @return string
     */
    public function getHash()
    {
        return $this->hash;
    }

    /**
     * Sets the hash of the contents for this file.
     *
     * @param string $hash
     *
     * @return void
     */
    protected function setHash($hash)
    {
        $this->hash = $hash;
    }

    /**
     * Retrieves the contents of this file.
     *
     * @return string|null
     */
    public function getSource()
    {
        return $this->source;
    }

    /**
     * Sets the source contents for this file.
     *
     * @param string|null $source
     *
     * @return void
     */
    public function setSource($source)
    {
        $this->source = $source;
    }

    /**
     * Returns the namespace aliases that have been defined in this file.
     *
     * @return Collection
     */
    public function getNamespaceAliases()
    {
        return $this->namespaceAliases;
    }

    /**
     * Sets the collection of namespace aliases for this file.
     *
     * @param Collection $namespaceAliases
     *
     * @return void
     */
    public function setNamespaceAliases(Collection $namespaceAliases)
    {
        $this->namespaceAliases = $namespaceAliases;
    }

    /**
     * Returns a list of all includes that have been declared in this file.
     *
     * @return Collection
     */
    public function getIncludes()
    {
        return $this->includes;
    }

    /**
     * Sets a list of all includes that have been declared in this file.
     *
     * @param Collection $includes
     *
     * @return void
     */
    public function setIncludes(Collection $includes)
    {
        $this->includes = $includes;
    }

    /**
     * Returns a list of constant descriptors contained in this file.
     *
     * @return Collection
     */
    public function getConstants()
    {
        return $this->constants;
    }

    /**
     * Sets a list of constant descriptors contained in this file.
     *
     * @param Collection $constants
     *
     * @return void
     */
    public function setConstants(Collection $constants)
    {
        $this->constants = $constants;
    }

    /**
     * Returns a list of function descriptors contained in this file.
     *
     * @return Collection|FunctionInterface[]
     */
    public function getFunctions()
    {
        return $this->functions;
    }

    /**
     * Sets a list of function descriptors contained in this file.
     *
     * @param Collection $functions
     *
     * @return void
     */
    public function setFunctions(Collection $functions)
    {
        $this->functions = $functions;
    }

    /**
     * Returns a list of class descriptors contained in this file.
     *
     * @return Collection|ClassInterface[]
     */
    public function getClasses()
    {
        return $this->classes;
    }

    /**
     * Sets a list of class descriptors contained in this file.
     *
     * @param Collection $classes
     *
     * @return void
     */
    public function setClasses(Collection $classes)
    {
        $this->classes = $classes;
    }

    /**
     * Returns a list of interface descriptors contained in this file.
     *
     * @return Collection|InterfaceInterface[]
     */
    public function getInterfaces()
    {
        return $this->interfaces;
    }

    /**
     * Sets a list of interface descriptors contained in this file.
     *
     * @param Collection $interfaces
     *
     * @return void
     */
    public function setInterfaces(Collection $interfaces)
    {
        $this->interfaces = $interfaces;
    }

    /**
     * Returns a list of trait descriptors contained in this file.
     *
     * @return Collection|TraitInterface[]
     */
    public function getTraits()
    {
        return $this->traits;
    }

    /**
     * Sets a list of trait descriptors contained in this file.
     *
     * @param Collection $traits
     *
     * @return void
     */
    public function setTraits(Collection $traits)
    {
        $this->traits = $traits;
    }

    /**
     * Returns a series of markers contained in this file.
     *
     * A marker is a special inline comment that starts with a keyword and is followed by a single line description.
     *
     * Example:
     * ```
     * // TODO: This is an item that needs to be done.
     * ```
     *
     * @return Collection
     */
    public function getMarkers()
    {
        return $this->markers;
    }

    /**
     * Sets a series of markers contained in this file.
     *
     * @param Collection $markers
     *
     * @see getMarkers() for more information on markers.
     *
     * @return void
     */
    public function setMarkers(Collection $markers)
    {
        $this->markers = $markers;
    }

    /**
     * Returns a list of all errors in this file and all its child elements.
     *
     * @return Collection
     */
    public function getAllErrors()
    {
        $errors = $this->getErrors();

        foreach ($this->getFunctions() as $element) {
            if (!$element) {
                continue;
            }
            $errors = $errors->merge($element->getErrors());
        }

        foreach ($this->getConstants() as $element) {
            if (!$element) {
                continue;
            }
            $errors = $errors->merge($element->getErrors());
        }

        foreach ($this->getClasses() as $element) {
            $errors = $errors->merge($element->getErrors());
            foreach ($element->getConstants() as $item) {
                if (!$item) {
                    continue;
                }
                $errors = $errors->merge($item->getErrors());
            }
            foreach ($element->getProperties() as $item) {
                if (!$item) {
                    continue;
                }
                $errors = $errors->merge($item->getErrors());
            }
            foreach ($element->getMethods() as $item) {
                if (!$item) {
                    continue;
                }
                $errors = $errors->merge($item->getErrors());
            }
        }

        foreach ($this->getInterfaces() as $element) {
            $errors = $errors->merge($element->getErrors());
            foreach ($element->getConstants() as $item) {
                if (!$item) {
                    continue;
                }
                $errors = $errors->merge($item->getErrors());
            }
            foreach ($element->getMethods() as $item) {
                if (!$item) {
                    continue;
                }
                $errors = $errors->merge($item->getErrors());
            }
        }

        foreach ($this->getTraits() as $element) {
            $errors = $errors->merge($element->getErrors());
            foreach ($element->getProperties() as $item) {
                if (!$item) {
                    continue;
                }
                $errors = $errors->merge($item->getErrors());
            }
            foreach ($element->getMethods() as $item) {
                if (!$item) {
                    continue;
                }
                $errors = $errors->merge($item->getErrors());
            }
        }

        return $errors;
    }

    /**
     * Sets the file path for this file relative to the project's root.
     *
     * @param string $path
     *
     * @return void
     */
    public function setPath($path)
    {
        $this->path = $path;
    }

    /**
     * Returns the file path relative to the project's root.
     *
     * @return string
     */
    public function getPath()
    {
        return $this->path;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor;

use Cilex\Application;
use Cilex\ServiceProviderInterface;
use phpDocumentor\Descriptor\Builder\AssemblerFactory;
use phpDocumentor\Descriptor\Builder\Reflector\ArgumentAssembler;
use phpDocumentor\Descriptor\Builder\Reflector\ClassAssembler;
use phpDocumentor\Descriptor\Builder\Reflector\ConstantAssembler;
use phpDocumentor\Descriptor\Builder\Reflector\FileAssembler;
use phpDocumentor\Descriptor\Builder\Reflector\FunctionAssembler;
use phpDocumentor\Descriptor\Builder\Reflector\InterfaceAssembler;
use phpDocumentor\Descriptor\Builder\Reflector\MethodAssembler;
use phpDocumentor\Descriptor\Builder\Reflector\PropertyAssembler;
use phpDocumentor\Descriptor\Builder\Reflector\Tags\AuthorAssembler;
use phpDocumentor\Descriptor\Builder\Reflector\Tags\DeprecatedAssembler;
use phpDocumentor\Descriptor\Builder\Reflector\Tags\GenericTagAssembler;
use phpDocumentor\Descriptor\Builder\Reflector\Tags\LinkAssembler;
use phpDocumentor\Descriptor\Builder\Reflector\Tags\MethodAssembler as MethodTagAssembler;
use phpDocumentor\Descriptor\Builder\Reflector\Tags\ParamAssembler;
use phpDocumentor\Descriptor\Builder\Reflector\Tags\PropertyAssembler as PropertyTagAssembler;
use phpDocumentor\Descriptor\Builder\Reflector\Tags\ReturnAssembler;
use phpDocumentor\Descriptor\Builder\Reflector\Tags\SeeAssembler;
use phpDocumentor\Descriptor\Builder\Reflector\Tags\SinceAssembler;
use phpDocumentor\Descriptor\Builder\Reflector\Tags\ThrowsAssembler;
use phpDocumentor\Descriptor\Builder\Reflector\Tags\UsesAssembler;
use phpDocumentor\Descriptor\Builder\Reflector\Tags\VarAssembler;
use phpDocumentor\Descriptor\Builder\Reflector\Tags\VersionAssembler;
use phpDocumentor\Descriptor\Builder\Reflector\TraitAssembler;
use phpDocumentor\Descriptor\Filter\ClassFactory;
use phpDocumentor\Descriptor\Filter\Filter;
use phpDocumentor\Descriptor\Filter\StripIgnore;
use phpDocumentor\Descriptor\Filter\StripInternal;
use phpDocumentor\Plugin\Core\Descriptor\Validator\Constraints as phpDocAssert;
use phpDocumentor\Reflection\ClassReflector\ConstantReflector as ClassConstant;
use phpDocumentor\Reflection\ClassReflector;
use phpDocumentor\Reflection\ConstantReflector;
use phpDocumentor\Reflection\DocBlock\Tag\AuthorTag;
use phpDocumentor\Reflection\DocBlock\Tag\DeprecatedTag;
use phpDocumentor\Reflection\DocBlock\Tag\LinkTag;
use phpDocumentor\Reflection\DocBlock\Tag\MethodTag;
use phpDocumentor\Reflection\DocBlock\Tag\ParamTag;
use phpDocumentor\Reflection\DocBlock\Tag\PropertyTag;
use phpDocumentor\Reflection\DocBlock\Tag\ReturnTag;
use phpDocumentor\Reflection\DocBlock\Tag\SeeTag;
use phpDocumentor\Reflection\DocBlock\Tag\SinceTag;
use phpDocumentor\Reflection\DocBlock\Tag\ThrowsTag;
use phpDocumentor\Reflection\DocBlock\Tag\UsesTag;
use phpDocumentor\Reflection\DocBlock\Tag\VarTag;
use phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Reflection\FileReflector;
use phpDocumentor\Reflection\FunctionReflector;
use phpDocumentor\Reflection\InterfaceReflector;
use phpDocumentor\Reflection\TraitReflector;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Validator;
use Zend\Cache\Storage\Adapter\Filesystem;
use Zend\Cache\Storage\Plugin\Serializer as SerializerPlugin;

/**
 * This provider is responsible for registering the Descriptor component with the given Application.
 */
class ServiceProvider implements ServiceProviderInterface
{
    /**
     * Adds the services needed to build the descriptors.
     *
     * @param Application $app An Application instance
     *
     * @return void
     */
    public function register(Application $app)
    {
        $this->addCache($app);
        $this->addAssemblers($app);
        $this->addFilters($app);
        $this->addValidators($app);
        $this->addBuilder($app);

        // I would prefer to extend it but due to a circular reference will pimple fatal
        $this->attachFiltersToManager($app['descriptor.filter'], $app);

        $app['descriptor.analyzer'] = function () {
            return new ProjectAnalyzer();
        };
    }

    /**
     * Registers the Assemblers used to convert Reflection objects to Descriptors.
     *
     * @param AssemblerFactory $factory
     *
     * @return AssemblerFactory
     */
    public function attachAssemblersToFactory(AssemblerFactory $factory)
    {
        // @codingStandardsIgnoreStart because we limit the verbosity by making all closures single-line
        $fileMatcher      = function ($criteria) { return $criteria instanceof FileReflector; };
        $constantMatcher  = function ($criteria) {
            return $criteria instanceof ConstantReflector || $criteria instanceof ClassConstant;
        };
        $traitMatcher     = function ($criteria) { return $criteria instanceof TraitReflector; };
        $classMatcher     = function ($criteria) { return $criteria instanceof ClassReflector; };
        $interfaceMatcher = function ($criteria) { return $criteria instanceof InterfaceReflector; };
        $propertyMatcher  = function ($criteria) { return $criteria instanceof ClassReflector\PropertyReflector; };
        $methodMatcher    = function ($criteria) { return $criteria instanceof ClassReflector\MethodReflector; };
        $argumentMatcher  = function ($criteria) { return $criteria instanceof FunctionReflector\ArgumentReflector; };
        $functionMatcher  = function ($criteria) { return $criteria instanceof FunctionReflector; };

        $authorMatcher      = function ($criteria) { return $criteria instanceof AuthorTag; };
        $deprecatedMatcher  = function ($criteria) { return $criteria instanceof DeprecatedTag; };
        $linkMatcher        = function ($criteria) { return $criteria instanceof LinkTag; };
        $methodTagMatcher   = function ($criteria) { return $criteria instanceof MethodTag; };
        $propertyTagMatcher = function ($criteria) { return $criteria instanceof PropertyTag; };
        $paramMatcher       = function ($criteria) { return $criteria instanceof ParamTag; };
        $throwsMatcher      = function ($criteria) { return $criteria instanceof ThrowsTag; };
        $returnMatcher      = function ($criteria) { return $criteria instanceof ReturnTag; };
        $usesMatcher        = function ($criteria) { return $criteria instanceof UsesTag; };
        $seeMatcher         = function ($criteria) { return $criteria instanceof SeeTag; };
        $sinceMatcher       = function ($criteria) { return $criteria instanceof SinceTag; };
        $varMatcher         = function ($criteria) { return $criteria instanceof VarTag; };
        $versionMatcher     = function ($criteria) { return $criteria instanceof Tag\VersionTag; };

        $tagFallbackMatcher = function ($criteria) { return $criteria instanceof Tag; };
        // @codingStandardsIgnoreEnd

        $factory->register($fileMatcher, new FileAssembler());
        $factory->register($constantMatcher, new ConstantAssembler());
        $factory->register($traitMatcher, new TraitAssembler());
        $factory->register($classMatcher, new ClassAssembler());
        $factory->register($interfaceMatcher, new InterfaceAssembler());
        $factory->register($propertyMatcher, new PropertyAssembler());
        $factory->register($methodMatcher, new MethodAssembler());
        $factory->register($argumentMatcher, new ArgumentAssembler());
        $factory->register($functionMatcher, new FunctionAssembler());

        $factory->register($authorMatcher, new AuthorAssembler());
        $factory->register($deprecatedMatcher, new DeprecatedAssembler());
        $factory->register($linkMatcher, new LinkAssembler());
        $factory->register($methodTagMatcher, new MethodTagAssembler());
        $factory->register($propertyTagMatcher, new PropertyTagAssembler());
        $factory->register($paramMatcher, new ParamAssembler());
        $factory->register($throwsMatcher, new ThrowsAssembler());
        $factory->register($returnMatcher, new ReturnAssembler());
        $factory->register($usesMatcher, new UsesAssembler());
        $factory->register($seeMatcher, new SeeAssembler());
        $factory->register($sinceMatcher, new SinceAssembler());
        $factory->register($varMatcher, new VarAssembler());
        $factory->register($versionMatcher, new VersionAssembler());

        $factory->registerFallback($tagFallbackMatcher, new GenericTagAssembler());

        return $factory;
    }

    /**
     * Attaches filters to the manager.
     *
     * @param Filter $filterManager
     * @param Application $app
     *
     * @return Filter
     */
    public function attachFiltersToManager(Filter $filterManager, Application $app)
    {
        $filtersOnAllDescriptors = array(
            new StripInternal($app['descriptor.builder']),
            new StripIgnore($app['descriptor.builder'])
        );

        foreach ($filtersOnAllDescriptors as $filter) {
            $filterManager->attach('phpDocumentor\Descriptor\ConstantDescriptor', $filter);
            $filterManager->attach('phpDocumentor\Descriptor\FunctionDescriptor', $filter);
            $filterManager->attach('phpDocumentor\Descriptor\InterfaceDescriptor', $filter);
            $filterManager->attach('phpDocumentor\Descriptor\TraitDescriptor', $filter);
            $filterManager->attach('phpDocumentor\Descriptor\PropertyDescriptor', $filter);
            $filterManager->attach('phpDocumentor\Descriptor\MethodDescriptor', $filter);
        }

        return $filterManager;
    }

    /**
     * Adds validators to check the Descriptors.
     *
     * @param Validator $validator
     *
     * @return Validator
     */
    public function attachValidators(Validator $validator)
    {
        /** @var ClassMetadata $fileMetadata */
        $fileMetadata  = $validator->getMetadataFor('phpDocumentor\Descriptor\FileDescriptor');
        /** @var ClassMetadata $constantMetadata */
        $constantMetadata  = $validator->getMetadataFor('phpDocumentor\Descriptor\ConstantDescriptor');
        /** @var ClassMetadata $functionMetadata */
        $functionMetadata  = $validator->getMetadataFor('phpDocumentor\Descriptor\FunctionDescriptor');
        /** @var ClassMetadata $classMetadata */
        $classMetadata     = $validator->getMetadataFor('phpDocumentor\Descriptor\ClassDescriptor');
        /** @var ClassMetadata $interfaceMetadata */
        $interfaceMetadata = $validator->getMetadataFor('phpDocumentor\Descriptor\InterfaceDescriptor');
        /** @var ClassMetadata $traitMetadata */
        $traitMetadata     = $validator->getMetadataFor('phpDocumentor\Descriptor\TraitDescriptor');
        /** @var ClassMetadata $propertyMetadata */
        $propertyMetadata  = $validator->getMetadataFor('phpDocumentor\Descriptor\PropertyDescriptor');
        /** @var ClassMetadata $methodMetadata */
        $methodMetadata    = $validator->getMetadataFor('phpDocumentor\Descriptor\MethodDescriptor');

        $fileMetadata->addPropertyConstraint('summary', new Assert\NotBlank(array('message' => 'PPC:ERR-50000')));
        $classMetadata->addPropertyConstraint('summary', new Assert\NotBlank(array('message' => 'PPC:ERR-50005')));
        $propertyMetadata->addConstraint(new phpDocAssert\Property\HasSummary());
        $methodMetadata->addPropertyConstraint('summary', new Assert\NotBlank(array('message' => 'PPC:ERR-50008')));
        $interfaceMetadata->addPropertyConstraint('summary', new Assert\NotBlank(array('message' => 'PPC:ERR-50009')));
        $traitMetadata->addPropertyConstraint('summary', new Assert\NotBlank(array('message' => 'PPC:ERR-50010')));
        $functionMetadata->addPropertyConstraint('summary', new Assert\NotBlank(array('message' => 'PPC:ERR-50011')));

        $functionMetadata->addConstraint(new phpDocAssert\Functions\IsReturnTypeNotAnIdeDefault());
        $methodMetadata->addConstraint(new phpDocAssert\Functions\IsReturnTypeNotAnIdeDefault());

        $functionMetadata->addConstraint(new phpDocAssert\Functions\IsParamTypeNotAnIdeDefault());
        $methodMetadata->addConstraint(new phpDocAssert\Functions\IsParamTypeNotAnIdeDefault());

        $functionMetadata->addConstraint(new phpDocAssert\Functions\IsArgumentInDocBlock());
        $methodMetadata->addConstraint(new phpDocAssert\Functions\IsArgumentInDocBlock());

        $classMetadata->addConstraint(new phpDocAssert\Classes\HasSinglePackage());
        $interfaceMetadata->addConstraint(new phpDocAssert\Classes\HasSinglePackage());
        $traitMetadata->addConstraint(new phpDocAssert\Classes\HasSinglePackage());
        $fileMetadata->addConstraint(new phpDocAssert\Classes\HasSinglePackage());

        $classMetadata->addConstraint(new phpDocAssert\Classes\HasSingleSubpackage());
        $interfaceMetadata->addConstraint(new phpDocAssert\Classes\HasSingleSubpackage());
        $traitMetadata->addConstraint(new phpDocAssert\Classes\HasSingleSubpackage());
        $fileMetadata->addConstraint(new phpDocAssert\Classes\HasSingleSubpackage());

        $classMetadata->addConstraint(new phpDocAssert\Classes\HasPackageWithSubpackage());
        $interfaceMetadata->addConstraint(new phpDocAssert\Classes\HasPackageWithSubpackage());
        $traitMetadata->addConstraint(new phpDocAssert\Classes\HasPackageWithSubpackage());
        $fileMetadata->addConstraint(new phpDocAssert\Classes\HasPackageWithSubpackage());

        return $validator;
    }

    /**
     * Adds the caching mechanism to the dependency injection container with key 'descriptor.cache'.
     *
     * @param Application $app
     *
     * @return void
     */
    protected function addCache(Application $app)
    {
        $app['descriptor.cache'] = $app->share(
            function () {
                $cache = new Filesystem();
                $cache->setOptions(
                    array(
                         'namespace' => 'phpdoc-cache',
                         'cache_dir' => sys_get_temp_dir(),
                    )
                );
                $cache->addPlugin(new SerializerPlugin());

                return $cache;
            }
        );
    }

    /**
     * Adds the Building mechanism using the key 'descriptor.builder'.
     *
     * Please note that the type of serializer can be configured using the parameter 'descriptor.builder.serializer'; it
     * accepts any parameter that Zend\Serializer supports.
     *
     * @param Application $app
     *
     * @return void
     */
    protected function addBuilder(Application $app)
    {
        $app['descriptor.builder.serializer'] = 'PhpSerialize';

        $app['descriptor.builder'] = $app->share(
            function ($container) {
                $builder = new ProjectDescriptorBuilder(
                    $container['descriptor.builder.assembler.factory'],
                    $container['descriptor.filter'],
                    $container['validator']
                );

                return $builder;
            }
        );
    }

    /**
     * Adds the assembler factory and attaches the basic assemblers with key 'descriptor.builder.assembler.factory'.
     *
     * @param Application $app
     *
     * @return void
     */
    protected function addAssemblers(Application $app)
    {
        $app['descriptor.builder.assembler.factory'] = $app->share(
            function () {
                return new AssemblerFactory();
            }
        );

        $provider = $this;
        $app['descriptor.builder.assembler.factory'] = $app->share(
            $app->extend(
                'descriptor.builder.assembler.factory',
                function ($factory) use ($provider) {
                    return $provider->attachAssemblersToFactory($factory);
                }
            )
        );
    }

    /**
     * Adds the descriptor filtering mechanism and using key 'descriptor.filter'.
     *
     * Please note that filters can only be attached after the builder is instantiated because it is needed; so the
     * filters can be attached by extending 'descriptor.builder'.
     *
     * @param Application $app
     *
     * @return void
     */
    protected function addFilters(Application $app)
    {
        $app['descriptor.filter'] = $app->share(
            function () {
                return new Filter(new ClassFactory());
            }
        );
    }

    /**
     * Adds validators for the descriptors to the validator manager.
     *
     * @param Application $app
     *
     * @throws Exception\MissingDependencyException if the validator could not be found.
     *
     * @return void
     */
    protected function addValidators(Application $app)
    {
        if (!isset($app['validator'])) {
            throw new Exception\MissingDependencyException('The validator manager is missing');
        }

        $provider = $this;
        $app['validator'] = $app->share(
            $app->extend(
                'validator',
                function ($validatorManager) use ($provider) {
                    return $provider->attachValidators($validatorManager);
                }
            )
        );
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Interfaces;

use phpDocumentor\Descriptor\Collection;
use phpDocumentor\Descriptor\FileDescriptor;

/**
 * Represents the public interface to which all descriptors should be held.
 */
interface BaseInterface
{
    /**
     * Sets the Fully Qualified Structural Element Name (FQSEN) for this element.
     *
     * @param string $name
     *
     * @return void
     */
    public function setFullyQualifiedStructuralElementName($name);

    /**
     * Returns the Fully Qualified Structural Element Name (FQSEN) for this element.
     *
     * @return string
     */
    public function getFullyQualifiedStructuralElementName();

    /**
     * Sets the local name for this element.
     *
     * @param string $name
     *
     * @return void
     */
    public function setName($name);

    /**
     * Returns the local name for this element.
     *
     * @return string
     */
    public function getName();

    /**
     * Sets a summary describing this element.
     *
     * @param string $summary
     *
     * @return void
     */
    public function setSummary($summary);

    /**
     * Returns the summary describing this element.
     *
     * @return string
     */
    public function getSummary();

    /**
     * Sets a longer description for this element.
     *
     * @param string $description
     *
     * @return void
     */
    public function setDescription($description);

    /**
     * Returns a longer description for this element.
     *
     * @return string
     */
    public function getDescription();

    /**
     * Sets the file and location for this element.
     *
     * @param FileDescriptor $file
     * @param int            $line
     *
     * @return void
     */
    public function setLocation(FileDescriptor $file, $line = 0);

    /**
     * Returns the file location for this element relative to the project root.
     *
     * @return string
     */
    public function getPath();

    /**
     * Returns the line number where this element may be found.
     *
     * @see getPath() to find out in which file this element is found.
     *
     * @return int
     */
    public function getLine();

    /**
     * Returns all tags associated with this element.
     *
     * @return Collection
     */
    public function getTags();
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Interfaces;

/**
 * Descriptor representing a constant on a class, trait, property or file.
 */
interface ConstantInterface extends BaseInterface
{
    /**
     * Sets the types that this constant may contain.
     *
     * @param array $types
     *
     * @return void
     */
    public function setTypes(array $types);

    /**
     * Returns the types that may be present in this constant.
     *
     * @return array[]
     */
    public function getTypes();

    /**
     * Sets the value representation for this constant.
     *
     * @param string $value
     *
     * @return void
     */
    public function setValue($value);

    /**
     * Retrieves a textual representation of the value in this constant.
     *
     * @return string
     */
    public function getValue();
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Interfaces;

use phpDocumentor\Descriptor\Collection;

/**
 * Describes the public interface for a description of a File.
 */
interface FileInterface extends BaseInterface, ContainerInterface
{
    public function getHash();

    public function setSource($source);

    public function getSource();

    /**
     * @return Collection
     */
    public function getNamespaceAliases();

    /**
     * @return Collection
     */
    public function getIncludes();

    /**
     * @return Collection
     */
    public function getErrors();
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Interfaces;

use phpDocumentor\Descriptor\Collection;

/**
 * Descriptor representing a global function in a file.
 */
interface FunctionInterface extends BaseInterface
{
    /**
     * Sets the arguments related to this function.
     *
     * @param Collection $arguments
     *
     * @return void
     */
    public function setArguments(Collection $arguments);

    /**
     * Returns the arguments related to this function.
     *
     * @return Collection
     */
    public function getArguments();
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Interfaces;

use phpDocumentor\Descriptor\Collection;

/**
 * Represents the public interface for an interface descriptor.
 */
interface InterfaceInterface extends BaseInterface, ChildInterface
{
    /**
     * Sets the constants associated with this interface.
     *
     * @param Collection $constants
     *
     * @return void
     */
    public function setConstants(Collection $constants);

    /**
     * Returns the constants associated with this interface.
     *
     * @return Collection
     */
    public function getConstants();

    /**
     * Sets the methods belonging to this interface.
     *
     * @param Collection $methods
     *
     * @return void
     */
    public function setMethods(Collection $methods);

    /**
     * Returns the methods belonging to this interface.
     *
     * @return Collection
     */
    public function getMethods();

    /**
     * Returns a list of all methods that were inherited from parent interfaces.
     *
     * @return Collection
     */
    public function getInheritedMethods();
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Interfaces;

use phpDocumentor\Descriptor\Collection;

/**
 * Public interface definition for object representing traits.
 */
interface TraitInterface extends BaseInterface
{
    /**
     * Sets the properties associated with this trait.
     *
     * @param Collection $properties
     *
     * @return void
     */
    public function setProperties(Collection $properties);

    /**
     * Returns the properties associated with this trait.
     *
     * @return Collection
     */
    public function getProperties();

    /**
     * Returns all properties inherited from parent traits.
     *
     * @return Collection
     */
    public function getInheritedProperties();

    /**
     * Sets all methods belonging to this trait.
     *
     * @param Collection $methods
     *
     * @return void
     */
    public function setMethods(Collection $methods);

    /**
     * Returns all methods belonging to this trait.
     *
     * @return Collection
     */
    public function getMethods();

    /**
     * Returns a list of all methods inherited from parent traits.
     *
     * @return Collection
     */
    public function getInheritedMethods();
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Interfaces;

use phpDocumentor\Descriptor\Collection;

/**
 * Interface representing the common interface for all elements that can contain sub-elements.
 */
interface ContainerInterface
{
    /**
     * @return Collection
     */
    public function getConstants();

    /**
     * @return Collection
     */
    public function getFunctions();

    /**
     * @return Collection
     */
    public function getClasses();

    /**
     * @return Collection
     */
    public function getInterfaces();

    /**
     * @return Collection
     */
    public function getTraits();
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Interfaces;

/**
 * Describes the public interface for a descriptor of an Argument.
 */
interface ArgumentInterface extends BaseInterface
{
    /**
     * Sets a normalized list of types that the argument represents.
     *
     * Arguments should have one of the types mentioned in this array. If this array is empty than that is considered
     * to be the type `mixed` (meaning: can be anything).
     *
     * Any Type representing a class/interface/trait should be normalized to its complete FQCN, including preceding
     * backslash. Types that do not represent a class/interface/trait should be written in lowercaps and should not be
     * preceded by a backslash.
     *
     * @param string[] $types An array of normalized types that should be in this Argument
     *
     * @link https://github.com/phpDocumentor/phpDocumentor2/blob/develop/docs/PSR.md#appendix-a-types Definition of a
     *     type.
     *
     * @todo update link to point to the final destination for the PHPDoc Standard.
     *
     * @return void
     */
    public function setTypes(array $types);

    /**
     * Returns a normalized list of types.
     *
     * @see self::setTypes() for details on what types represent.
     *
     * @return string[]
     */
    public function getTypes();

    /**
     * Sets the default value for an argument expressed as a string.
     *
     * @param string $value A textual representation of the default value.
     *
     * @return void
     */
    public function setDefault($value);

    /**
     * Returns the default value for an argument as string or null is no default is set.
     *
     * @return string|null A textual representation of the default value, or null if no default value is present.
     */
    public function getDefault();

    /**
     * Sets whether this argument passes its parameter by reference or by value.
     *
     * @param boolean $byReference True if the parameter is passed by reference, otherwise it is by value.
     *
     * @return void
     */
    public function setByReference($byReference);

    /**
     * Returns whether the parameter is passed by reference or by value.
     *
     * @return boolean True if the parameter is passed by reference, otherwise it is by value.
     */
    public function isByReference();
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Interfaces;

use phpDocumentor\Descriptor\Collection;

/**
 * Describes the public interface of the description for a method.
 */
interface MethodInterface extends BaseInterface
{
    /**
     * @param boolean $abstract
     */
    public function setAbstract($abstract);

    /**
     * @return boolean
     */
    public function isAbstract();

    /**
     * @return Collection
     */
    public function getArguments();

    /**
     * @param boolean $final
     */
    public function setFinal($final);

    /**
     * @return boolean
     */
    public function isFinal();

    /**
     * @param boolean $static
     */
    public function setStatic($static);

    /**
     * @return boolean
     */
    public function isStatic();

    /**
     * @param string $visibility
     */
    public function setVisibility($visibility);

    /**
     * @return string
     */
    public function getVisibility();
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Interfaces;

use phpDocumentor\Descriptor\Collection;

/**
 * Common interface representing the description of a class.
 *
 * @see NamespaceInterface Classes may be contained in namespaces.
 * @see FileInterface      Classes may be defined in a file.
 */
interface ClassInterface extends BaseInterface, ChildInterface
{
    public function setInterfaces(Collection $interfaces);

    /**
     * @return Collection
     */
    public function getInterfaces();

    public function setFinal($final);

    public function isFinal();

    public function setAbstract($abstract);

    public function isAbstract();

    public function setConstants(Collection $constants);

    /**
     * @return Collection
     */
    public function getConstants();

    public function setMethods(Collection $methods);

    /**
     * @return Collection
     */
    public function getMethods();

    /**
     * @return Collection
     */
    public function getInheritedMethods();

    public function setProperties(Collection $properties);

    /**
     * @return Collection
     */
    public function getProperties();

    /**
     * @return Collection
     */
    public function getInheritedProperties();
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Interfaces;

use phpDocumentor\Descriptor\DescriptorAbstract;

/**
 * Describes the public interface for any descriptor that is the child is another.
 */
interface ChildInterface
{
    /**
     * Returns the parent for this descriptor.
     *
     * @return DescriptorAbstract
     */
    public function getParent();

    /**
     * Sets the parent for this Descriptor.
     *
     * @param DescriptorAbstract $parent
     *
     * @return void
     */
    public function setParent($parent);
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Interfaces;

/**
 * Descriptor representing a property on a class or trait.
 */
interface PropertyInterface extends BaseInterface
{
    /**
     * Stores a textual representation of the default value for a property.
     *
     * @param string $default
     *
     * @return void
     */
    public function setDefault($default);

    /**
     * Returns the textual representation of the default value for a property.
     *
     * @return string
     */
    public function getDefault();

    /**
     * Sets whether this property is static in scope.
     *
     * @param boolean $static
     *
     * @return void
     */
    public function setStatic($static);

    /**
     * Returns whether this property is static in scope.
     *
     * @return boolean
     */
    public function isStatic();

    /**
     * Sets the types associated with the value(s) for this property.
     *
     * @param string[] $types
     *
     * @return void
     */
    public function setTypes(array $types);

    /**
     * Returns the types associated with the value(s) for this property.
     *
     * @return string[]
     */
    public function getTypes();

    /**
     * Sets whether this property is available from inside or outside its class and/or descendants.
     *
     * @param string $visibility May be either 'public', 'private' or 'protected'.
     *
     * @return string
     */
    public function setVisibility($visibility);

    /**
     * Sets whether this property is available from inside or outside its class and/or descendants.
     *
     * @return string May be either 'public', 'private' or 'protected'.
     */
    public function getVisibility();
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Interfaces;

use phpDocumentor\Descriptor\Collection;

/**
 * Describes the public interface for the description of a project.
 */
interface ProjectInterface
{
    /**
     * @param string $name
     */
    public function setName($name);

    /**
     * @return string
     */
    public function getName();

    /**
     * @return Collection
     */
    public function getFiles();

    /**
     * @return Collection
     */
    public function getIndexes();

    /**
     * @return NamespaceInterface
     */
    public function getNamespace();
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Interfaces;

/**
 * Describes the public interface for a package descriptor.
 */
interface PackageInterface extends BaseInterface, ContainerInterface, NamespaceInterface
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Interfaces;

use phpDocumentor\Descriptor\Collection;

/**
 * Describes the public interface for the description of a namespace.
 */
interface NamespaceInterface extends BaseInterface, ContainerInterface, ChildInterface
{
    /**
     * @return Collection
     */
    public function getChildren();
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Descriptor;

/**
 * Descriptor representing a single Argument of a method or function.
 */
class ArgumentDescriptor extends DescriptorAbstract implements Interfaces\ArgumentInterface
{
    /** @var string[] $type an array of normalized types that should be in this Argument */
    protected $types = array();

    /** @var bool $default the default value for an argument or null if none is provided */
    protected $default;

    /** @var bool $byReference whether the argument passes the parameter by reference instead of by value */
    protected $byReference = false;

    /**
     * {@inheritDoc}
     */
    public function setTypes(array $types)
    {
        $this->types = $types;
    }

    /**
     * {@inheritDoc}
     */
    public function getTypes()
    {
        return $this->types;
    }

    /**
     * {@inheritDoc}
     */
    public function setDefault($value)
    {
        $this->default = $value;
    }

    /**
     * {@inheritDoc}
     */
    public function getDefault()
    {
        return $this->default;
    }

    /**
     * {@inheritDoc}
     */
    public function setByReference($byReference)
    {
        $this->byReference = $byReference;
    }

    /**
     * {@inheritDoc}
     */
    public function isByReference()
    {
        return $this->byReference;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\ProjectDescriptor;

/**
 * Contains the Settings for the current Project.
 */
class Settings
{
    const VISIBILITY_PUBLIC    = 1;
    const VISIBILITY_PROTECTED = 2;
    const VISIBILITY_PRIVATE   = 4;
    const VISIBILITY_INTERNAL  = 8;

    /** @var integer by default ignore internal visibility but show others */
    const VISIBILITY_DEFAULT   = 7;

    /** @var boolean Represents whether this settings object has been modified */
    protected $isModified = false;

    /** @var integer a bitflag representing which visibilities are contained and allowed in this project */
    protected $visibility = self::VISIBILITY_DEFAULT;

    /**
     * Stores the visibilities that are allowed to be executed as a bitflag.
     *
     * @param integer $visibilityFlag A bitflag combining the VISIBILITY_* constants.
     *
     * @return void
     */
    public function setVisibility($visibilityFlag)
    {
        $this->setValueAndCheckIfModified('visibility', $visibilityFlag);
    }

    /**
     * Returns the bit flag representing which visibilities are allowed.
     *
     * @see self::isVisibilityAllowed() for a convenience method to easily check against a specific visibility.
     *
     * @return integer
     */
    public function getVisibility()
    {
        return $this->visibility;
    }

    /**
     * Returns whether one of the values of this object was modified.
     *
     * @return boolean
     */
    public function isModified()
    {
        return $this->isModified;
    }

    /**
     * Sets a property's value and if it differs from the previous then mark these settings as modified.
     */
    protected function setValueAndCheckIfModified($propertyName, $value)
    {
        if ($this->$propertyName != $value) {
            $this->isModified = true;
        }

        $this->$propertyName = $value;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor;

/**
 * Descriptor representing a function.
 */
class FunctionDescriptor extends DescriptorAbstract implements Interfaces\FunctionInterface
{
    /** @var Collection $arguments */
    protected $arguments;

    /**
     * Initializes the all properties representing a collection with a new Collection object.
     */
    public function __construct()
    {
        parent::__construct();

        $this->setArguments(new Collection());
    }

    /**
     * {@inheritDoc}
     */
    public function setArguments(Collection $arguments)
    {
        $this->arguments = $arguments;
    }

    /**
     * {@inheritDoc}
     */
    public function getArguments()
    {
        return $this->arguments;
    }

    /**
     * {@inheritDoc}
     */
    public function getResponse()
    {
        /** @var Collection|null $returnTags */
        $returnTags = $this->getTags()->get('return');

        return $returnTags instanceof Collection ? current($returnTags->getAll()) : null;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor;

/**
 * Represents the package for a class, trait, interface or file.
 */
class PackageDescriptor extends NamespaceDescriptor implements Interfaces\PackageInterface
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor;

use phpDocumentor\Descriptor\Interfaces\ChildInterface;
use phpDocumentor\Descriptor\Tag\VarDescriptor;

/**
 * Descriptor representing a property.
 */
class PropertyDescriptor extends DescriptorAbstract implements Interfaces\PropertyInterface
{
    /** @var ClassDescriptor|TraitDescriptor $parent */
    protected $parent;

    /** @var string[]|null $types */
    protected $types;

    /** @var string $default */
    protected $default;

    /** @var bool $static */
    protected $static = false;

    /** @var string $visibility */
    protected $visibility = 'public';

    /**
     * @param ClassDescriptor|TraitDescriptor $parent
     */
    public function setParent($parent)
    {
        $this->setFullyQualifiedStructuralElementName(
            $parent->getFullyQualifiedStructuralElementName() . '::' . $this->getName()
        );

        $this->parent = $parent;
    }

    /**
     * @return ClassDescriptor|TraitDescriptor
     */
    public function getParent()
    {
        return $this->parent;
    }

    /**
     * {@inheritDoc}
     */
    public function setDefault($default)
    {
        $this->default = $default;
    }

    /**
     * {@inheritDoc}
     */
    public function getDefault()
    {
        return $this->default;
    }

    /**
     * {@inheritDoc}
     */
    public function setStatic($static)
    {
        $this->static = $static;
    }

    /**
     * {@inheritDoc}
     */
    public function isStatic()
    {
        return $this->static;
    }

    /**
     * {@inheritDoc}
     */
    public function setTypes(array $types)
    {
        $this->types = $types;
    }

    /**
     * {@inheritDoc}
     */
    public function getTypes()
    {
        if (!$this->types) {
            $this->types = array();

            /** @var VarDescriptor $var */
            $var = $this->getVar()->getIterator()->current();
            if ($var) {
                $this->types = $var->getTypes();
            }
        }

        return $this->types;
    }

    /**
     * {@inheritDoc}
     */
    public function setVisibility($visibility)
    {
        $this->visibility = $visibility;
    }

    /**
     * {@inheritDoc}
     */
    public function getVisibility()
    {
        return $this->visibility;
    }

    /**
     * @return Collection
     */
    public function getVar()
    {
        /** @var Collection $version */
        $var = $this->getTags()->get('var', new Collection());

        if ($var->count() == 0
            && ($this->getParent() instanceof ChildInterface)
            && (
                $this->getParent()->getParent() instanceof ClassDescriptor
                || $this->getParent()->getParent() instanceof InterfaceDescriptor
            )
        ) {
            /** @var PropertyDescriptor|null $parentProperty */
            $parentProperty = $this->getParent()->getParent()->getProperties()->get($this->getName());
            if ($parentProperty) {
                return $parentProperty->getVar();
            }
        }

        return $var;
    }

    /**
     * Returns the file associated with the parent class or trait.
     *
     * @return FileDescriptor
     */
    public function getFile()
    {
        return $this->getParent()->getFile();
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Exception;

/**
 * This exception is thrown when a required dependency is not included.
 */
class MissingDependencyException extends \RuntimeException
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor;

use phpDocumentor\Descriptor\Filter\Filterable;

/**
 * Base class for any tag descriptor and used when a tag has no specific descriptor.
 */
class TagDescriptor implements Filterable
{
    /** @var string $name Name of the tag. */
    protected $name;

    /** @var string $description A description line for this tag */
    protected $description;

    /** @var Collection A collection of errors found during filtering. */
    protected $errors;

    /**
     * Initializes the tag by setting the name and errors,
     *
     * @param string $name
     */
    public function __construct($name)
    {
        $this->setName($name);
        $this->errors = new Collection();
    }

    /**
     * Sets the name for this tag.
     *
     * @param string $name
     *
     * @return void
     */
    protected function setName($name)
    {
        $this->name = $name;
    }

    /**
     * Returns the name for this tag.
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Sets a description for this tab instance.
     *
     * @param string $description
     *
     * @return void
     */
    public function setDescription($description)
    {
        $this->description = $description;
    }

    /**
     * Returns the description for this tag,
     *
     * @return string
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     * Sets a list of errors found on the usage of this tag.
     *
     * @param Collection $errors
     *
     * @return void
     */
    public function setErrors(Collection $errors)
    {
        $this->errors = $errors;
    }

    /**
     * Returns all errors associated with this tag.
     *
     * @return Collection
     */
    public function getErrors()
    {
        return $this->errors;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor;

/**
 * Descriptor representing a Method in a Class, Interface or Trait.
 */
class MethodDescriptor extends DescriptorAbstract implements Interfaces\MethodInterface
{
    /** @var ClassDescriptor|InterfaceDescriptor|TraitDescriptor $parent */
    protected $parent;

    /** @var bool $abstract */
    protected $abstract = false;

    /** @var bool $final */
    protected $final = false;

    /** @var bool $static */
    protected $static = false;

    /** @var string $visibility */
    protected $visibility = 'public';

    /** @var Collection */
    protected $arguments;

    /**
     * Initializes the all properties representing a collection with a new Collection object.
     */
    public function __construct()
    {
        parent::__construct();

        $this->setArguments(new Collection());
    }

    /**
     * @param ClassDescriptor|InterfaceDescriptor|TraitDescriptor $parent
     */
    public function setParent($parent)
    {
        $this->setFullyQualifiedStructuralElementName(
            $parent->getFullyQualifiedStructuralElementName() . '::' . $this->getName() . '()'
        );

        $this->parent = $parent;
    }

    /**
     * @return ClassDescriptor|InterfaceDescriptor|TraitDescriptor
     */
    public function getParent()
    {
        return $this->parent;
    }

    /**
     * {@inheritDoc}
     */
    public function setAbstract($abstract)
    {
        $this->abstract = $abstract;
    }

    /**
     * {@inheritDoc}
     */
    public function isAbstract()
    {
        return $this->abstract;
    }

    /**
     * {@inheritDoc}
     */
    public function setFinal($final)
    {
        $this->final = $final;
    }

    /**
     * {@inheritDoc}
     */
    public function isFinal()
    {
        return $this->final;
    }

    /**
     * {@inheritDoc}
     */
    public function setStatic($static)
    {
        $this->static = $static;
    }

    /**
     * {@inheritDoc}
     */
    public function isStatic()
    {
        return $this->static;
    }

    /**
     * {@inheritDoc}
     */
    public function setVisibility($visibility)
    {
        $this->visibility = $visibility;
    }

    /**
     * {@inheritDoc}
     */
    public function getVisibility()
    {
        return $this->visibility;
    }

    /**
     * {@inheritDoc}
     */
    public function setArguments(Collection $arguments)
    {
        $this->arguments = $arguments;
    }

    /**
     * {@inheritDoc}
     */
    public function getArguments()
    {
        return $this->arguments;
    }

    /**
     * {@inheritDoc}
     */
    public function getResponse()
    {
        /** @var Collection|null $returnTags */
        $returnTags = $this->getTags()->get('return');

        return $returnTags instanceof Collection ? current($returnTags->getAll()) : null;
    }

    /**
     * Returns the file associated with the parent class, interface or trait.
     *
     * @return FileDescriptor
     */
    public function getFile()
    {
        return $this->getParent()->getFile();
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor;

use phpDocumentor\Descriptor\Interfaces\ChildInterface;
use phpDocumentor\Descriptor\Tag\VarDescriptor;

/**
 * Descriptor representing a constant
 */
class ConstantDescriptor extends DescriptorAbstract implements Interfaces\ConstantInterface
{
    /** @var ClassDescriptor|InterfaceDescriptor|null $parent */
    protected $parent;

    /** @var string[]|null $type */
    protected $types;

    /** @var string $value */
    protected $value;

    /**
     * Registers a parent class or interface with this constant.
     *
     * @param ClassDescriptor|InterfaceDescriptor|null $parent
     *
     * @throws \InvalidArgumentException if anything other than a class, interface or null was passed.
     *
     * @return void
     */
    public function setParent($parent)
    {
        if (!$parent instanceof ClassDescriptor && !$parent instanceof InterfaceDescriptor && $parent !== null) {
            throw new \InvalidArgumentException('Constants can only have an interface or class as parent');
        }

        $this->setFullyQualifiedStructuralElementName(
            $parent->getFullyQualifiedStructuralElementName() . '::' . $this->getName()
        );

        $this->parent = $parent;
    }

    /**
     * @return null|ClassDescriptor|InterfaceDescriptor
     */
    public function getParent()
    {
        return $this->parent;
    }

    /**
     * {@inheritDoc}
     */
    public function setTypes(array $types)
    {
        $this->types = $types;
    }

    /**
     * {@inheritDoc}
     */
    public function getTypes()
    {
        if ($this->types === null) {
            $this->types = array();

            /** @var VarDescriptor $var */
            $var = $this->getVar()->get(0);
            if ($var) {
                $this->types = $var->getTypes();
            }
        }

        return $this->types;
    }

    /**
     * {@inheritDoc}
     */
    public function setValue($value)
    {
        $this->value = $value;
    }

    /**
     * {@inheritDoc}
     */
    public function getValue()
    {
        return $this->value;
    }

    /**
     * @return Collection
     */
    public function getVar()
    {
        /** @var Collection $var */
        $var = $this->getTags()->get('var', new Collection());

        if ($var->count() == 0
            && ($this->getParent() instanceof ChildInterface)
            && (
                $this->getParent()->getParent() instanceof ClassDescriptor
                || $this->getParent()->getParent() instanceof InterfaceDescriptor
            )
        ) {
            $parentConstant = $this->getParent()->getParent()->getConstants()->get($this->getName());
            if ($parentConstant) {
                return $parentConstant->getVar();
            }
        }

        return $var;
    }

    /**
     * Returns the file associated with the parent class, interface or trait when inside a container.
     *
     * @return FileDescriptor
     */
    public function getFile()
    {
        return $this->getFile() ?: $this->getParent()->getFile();
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Tag;

/**
 * Descriptor representing the return tag on a function or method.
 */
class ReturnDescriptor extends BaseTypes\TypedAbstract
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Tag;

use phpDocumentor\Descriptor\DescriptorAbstract;
use phpDocumentor\Descriptor\TagDescriptor;

class SeeDescriptor extends TagDescriptor
{
    /** @var DescriptorAbstract|string $reference */
    protected $reference = '';

    /**
     * @param DescriptorAbstract|string $reference
     */
    public function setReference($reference)
    {
        $this->reference = $reference;
    }

    /**
     * @return DescriptorAbstract|string
     */
    public function getReference()
    {
        return $this->reference;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Tag;

/**
 * Descriptor representing the throws tag on a class or trait.
 */
class ThrowsDescriptor extends ReturnDescriptor
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Tag;

use phpDocumentor\Descriptor\TagDescriptor;

/**
 * Descriptor representing the since tag with another descriptor.
 */
class SinceDescriptor extends TagDescriptor
{
    /** @return string $version represents the version since when the associated element was introduced */
    protected $version;

    /**
     * Returns the version when the associated element was introduced.
     *
     * @return string
     */
    public function getVersion()
    {
        return $this->version;
    }

    /**
     * Sets the version since when the associated element was introduced.
     *
     * @param string $version
     *
     * @return void
     */
    public function setVersion($version)
    {
        $this->version = $version;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Tag;

use phpDocumentor\Descriptor\TagDescriptor;

/**
 * Descriptor representing the deprecated tag with a descriptor.
 */
class DeprecatedDescriptor extends TagDescriptor
{
    /** @var string $version represents the version since when the element was deprecated. */
    protected $version;

    /**
     * Returns the version since when the associated element was deprecated.
     *
     * @return string
     */
    public function getVersion()
    {
        return $this->version;
    }

    /**
     * Sets the version since when the associated element was deprecated.
     *
     * @param string $version
     *
     * @return void
     */
    public function setVersion($version)
    {
        $this->version = $version;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Tag;

/**
 * Descriptor representing the param tag with a function or method.
 */
class ParamDescriptor extends BaseTypes\TypedVariableAbstract
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Tag;

use phpDocumentor\Descriptor\TagDescriptor;

/**
 * Descriptor representing the version tag on a class, interface, trait or file.
 */
class VersionDescriptor extends TagDescriptor
{
    /** @var string $version Version string representing the current version of the element */
    protected $version;

    /**
     * Returns the current version for the associated element.
     *
     * @return string
     */
    public function getVersion()
    {
        return $this->version;
    }

    /**
     * Sets the version for the associated element.
     *
     * @param string $version
     *
     * @return void
     */
    public function setVersion($version)
    {
        $this->version = $version;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Tag;

/**
 * Descriptor representing the property tag on a class or trait.
 */
class PropertyDescriptor extends BaseTypes\TypedVariableAbstract
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Tag;

use phpDocumentor\Descriptor\TagDescriptor;

/**
 * Descriptor representing the author tag with a descriptor.
 */
class AuthorDescriptor extends TagDescriptor
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Tag;

/**
 * Descriptor representing the var tag on a property.
 */
class VarDescriptor extends BaseTypes\TypedVariableAbstract
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Tag;

use phpDocumentor\Descriptor\Collection;
use phpDocumentor\Descriptor\TagDescriptor;

class MethodDescriptor extends TagDescriptor
{
    protected $methodName = '';

    protected $arguments;

    protected $response;

    public function __construct($name)
    {
        parent::__construct($name);

        $this->arguments = new Collection();
    }

    /**
     * @param string $methodName
     */
    public function setMethodName($methodName)
    {
        $this->methodName = $methodName;
    }

    /**
     * @return string
     */
    public function getMethodName()
    {
        return $this->methodName;
    }

    /**
     * @param mixed $arguments
     */
    public function setArguments($arguments)
    {
        $this->arguments = $arguments;
    }

    /**
     * @return mixed
     */
    public function getArguments()
    {
        return $this->arguments;
    }

    /**
     * @param mixed $response
     */
    public function setResponse($response)
    {
        $this->response = $response;
    }

    /**
     * @return mixed
     */
    public function getResponse()
    {
        return $this->response;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Tag\BaseTypes;

use phpDocumentor\Descriptor\TagDescriptor;

/**
 * Base descriptor for tags that have a type associated with them.
 */
abstract class TypedAbstract extends TagDescriptor
{
    /** @var string[] $types */
    protected $types;

    /**
     * Sets a list of types associated with this tag.
     *
     * @param string[] $types
     *
     * @return void
     */
    public function setTypes(array $types)
    {
        $this->types = $types;
    }

    /**
     * Returns the list of types associated with this tag.
     *
     * @return string[]
     */
    public function getTypes()
    {
        return $this->types;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Tag\BaseTypes;

/**
 * Abstract class for Descriptors with a type and variable name.
 */
abstract class TypedVariableAbstract extends TypedAbstract
{
    /** @var string variableName */
    protected $variableName = '';

    /**
     * Retrieves the variable name stored on this descriptor.
     *
     * @return string
     */
    public function getVariableName()
    {
        return $this->variableName;
    }

    /**
     * Sets the variable name on this descriptor.
     *
     * @param string $variableName
     *
     * @return void
     */
    public function setVariableName($variableName)
    {
        $this->variableName = $variableName;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Tag;

use phpDocumentor\Descriptor\TagDescriptor;

/**
 * Descriptor representing the uses tag on any element.
 */
class UsesDescriptor extends TagDescriptor
{
    /** @var string the FQSEN where the uses tag refers to */
    protected $reference = '';

    /**
     * Returns the FQSEN to which this tag points.
     *
     * @return string
     */
    public function getReference()
    {
        return $this->reference;
    }

    /**
     * Sets the FQSEN to which this tag points.
     *
     * @param string $reference
     *
     * @return void
     */
    public function setReference($reference)
    {
        $this->reference = $reference;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Descriptor\Tag;

use phpDocumentor\Descriptor\TagDescriptor;

/**
 * Descriptor representing the link tag with a descriptor.
 */
class LinkDescriptor extends TagDescriptor
{
    /** @var string $link the url where the link points to. */
    protected $link;

    /**
     * Sets the URL where the link points to.
     *
     * @param string $link
     *
     * @return void
     */
    public function setLink($link)
    {
        $this->link = $link;
    }

    /**
     * Returns the URL where this link points to.
     *
     * @return string
     */
    public function getLink()
    {
        return $this->link;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Console\Output;

use Monolog\Logger;
use Symfony\Component\Console\Output\ConsoleOutput;

class Output extends ConsoleOutput
{
    /** @var Logger */
    protected $logger;

    /**
     * Sets a logger object to write information to.
     *
     * @param Logger $logger
     */
    public function setLogger(Logger $logger)
    {
        $this->logger = $logger;
    }

    /**
     * Returns the object where is being logged to.
     *
     * @return Logger
     */
    public function getLogger()
    {
        return $this->logger;
    }

    /**
     * Executes a callable piece of code and writes an entry to the log detailing how long it took.
     *
     * @param string   $message
     * @param callable $operation
     * @param array    $arguments
     *
     * @return void
     */
    public function writeTimedLog($message, $operation, array $arguments = array())
    {
        $this->write(sprintf('%-66.66s .. ', $message));
        $timerStart = microtime(true);

        call_user_func_array($operation, $arguments);

        $this->writeln(sprintf('%8.3fs', microtime(true) - $timerStart));
    }

    /**
     * Write an entry to the console and to the provided logger.
     *
     * @param array|string $message
     * @param bool         $newline
     * @param int          $type
     *
     * @return void
     */
    public function write($message, $newline = false, $type = 0)
    {
        if ($this->getLogger()) {
            $this->getLogger()->info($this->getFormatter()->format(strip_tags($message)));
        }

        parent::write($message, $newline, $type);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Console\Input;

use Symfony\Component\Console\Input\InputDefinition;

/**
 * Argv input for the Console component of Symfony adapted to phpDocumentor.
 *
 * This InputStream for the Symfony Console component prepends the namespace and command
 * name `project:run` to the Argv array if no command has been provided.
 */
class ArgvInput extends \Symfony\Component\Console\Input\ArgvInput
{
    /**
     * Constructor.
     *
     * The constructor has been overridden to check whether the first element in
     * the argument list is an argument (as it represents the command name).
     *
     * If it is not then we insert the command name: *project:run*.
     *
     * This way we can ensure that if no command name is given that the project
     * defaults to the execution of phpDocumentor. This is behavior that is
     * expected from previous releases of phpDocumentor.
     *
     * @param string[]        $argv       An array of parameters from the CLI (in the argv format)
     * @param InputDefinition $definition A InputDefinition instance
     *
     * @api
     */
    public function __construct(array $argv = null, InputDefinition $definition = null)
    {
        if (null === $argv) {
            $argv = $_SERVER['argv'];
        }

        if ((count($argv) === 1) || ($argv[1][0] === '-')) {
            array_splice($argv, 1, 0, 'project:run');
        }

        parent::__construct($argv, $definition);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor;

use JMS\Serializer\Annotation as Serializer;

/**
 * The definition for the configuration of phpDocumentor.
 */
class Configuration
{
    /**
     * @var Configuration\Parser $parser
     * @Serializer\Type("phpDocumentor\Configuration\Parser")
     */
    protected $parser;

    /**
     * @var Configuration\Transformer $transformer
     * @Serializer\Type("phpDocumentor\Configuration\Transformer")
     */
    protected $transformer;

    /**
     * @var Configuration\Files files
     * @Serializer\Type("phpDocumentor\Configuration\Files")
     */
    protected $files;

    /**
     * @var string[] $plugins
     * @Serializer\Type("array<string>")
     */
    protected $plugins;

    /**
     * @var (Transformer\Template|Transformer\Transformation)[] transformations
     * @Serializer\Type("phpDocumentor\Configuration\Transformer")
     */
    protected $transformations;

    /**
     * @var string[] partials
     */
    protected $partials;
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Parser;

/**
 * Provides the basic exception for the parser package.
 *
 * @author  Mike van Riel <mike.vanriel@naenius.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class Exception extends \Exception
{
    const NO_FILES_FOUND = 2;
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Parser;

use phpDocumentor\Descriptor\FileDescriptor;
use phpDocumentor\Descriptor\ProjectDescriptorBuilder;
use phpDocumentor\Event\DebugEvent;
use phpDocumentor\Event\Dispatcher;
use phpDocumentor\Event\LogEvent;
use phpDocumentor\Fileset\Collection;
use phpDocumentor\Parser\Event\PreFileEvent;
use phpDocumentor\Parser\Exception\FilesNotFoundException;
use phpDocumentor\Reflection\FileReflector;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use Symfony\Component\Stopwatch\Stopwatch;

/**
 * Class responsible for parsing the given file or files to the intermediate
 * structure file.
 *
 * This class can be used to parse one or more files to the intermediate file
 * format for further processing.
 *
 * Example of use:
 *
 *     $files = new \phpDocumentor\File\Collection();
 *     $ files->addDirectories(getcwd());
 *     $parser = new \phpDocumentor\Parser\Parser();
 *     $parser->setPath($files->getProjectRoot());
 *     echo $parser->parseFiles($files);
 */
class Parser implements LoggerAwareInterface
{
    /** @var string the name of the default package */
    protected $defaultPackageName = 'Default';

    /** @var bool whether we force a full re-parse */
    protected $force = false;

    /** @var bool whether to execute a PHPLint on every file */
    protected $validate = false;

    /** @var string[] which markers (i.e. TODO or FIXME) to collect */
    protected $markers = array('TODO', 'FIXME');

    /** @var string[] which tags to ignore */
    protected $ignoredTags = array();

    /** @var string target location's root path */
    protected $path = null;

    /** @var LoggerInterface $logger */
    protected $logger;

    /**
     * Array of visibility modifiers that should be adhered to when generating
     * the documentation
     *
     * @var array
     */
    protected $visibility = array('public', 'protected', 'private');

    /** @var string The encoding in which the files are encoded */
    protected $encoding = 'utf-8';

    /** @var Stopwatch $stopwatch The profiling component that measures time and memory usage over time */
    protected $stopwatch = null;

    /**
     * Initializes the parser.
     *
     * This constructor checks the user's PHP ini settings to detect which encoding is used by default. This encoding
     * is used as a default value for phpDocumentor to convert the source files that it receives.
     *
     * If no encoding is specified than 'utf-8' is assumed by default.
     */
    public function __construct()
    {
        $defaultEncoding = ini_get('zend.script_encoding');
        if ($defaultEncoding) {
            $this->encoding = $defaultEncoding;
        }
    }

    /**
     * Registers the component that profiles the execution of the parser.
     *
     * @param Stopwatch $stopwatch
     *
     * @return void
     */
    public function setStopwatch($stopwatch)
    {
        $this->stopwatch = $stopwatch;
    }

    /**
     * Sets whether to force a full parse run of all files.
     *
     * @param bool $forced Forces a full parse.
     *
     * @api
     *
     * @return void
     */
    public function setForced($forced)
    {
        $this->force = $forced;
    }

    /**
     * Returns whether a full rebuild is required.
     *
     * @api
     *
     * @return bool
     */
    public function isForced()
    {
        return $this->force;
    }

    /**
     * Sets whether to run PHPLint on every file.
     *
     * PHPLint has a huge performance impact on the execution of phpDocumentor and
     * is thus disabled by default.
     *
     * @param bool $validate when true this file will be checked.
     *
     * @api
     *
     * @return void
     */
    public function setValidate($validate)
    {
        $this->validate = $validate;
    }

    /**
     * Returns whether we want to run PHPLint on every file.
     *
     * @api
     *
     * @return bool
     */
    public function doValidation()
    {
        return $this->validate;
    }

    /**
     * Sets a list of markers to gather (i.e. TODO, FIXME).
     *
     * @param string[] $markers A list or markers to gather.
     *
     * @api
     *
     * @return void
     */
    public function setMarkers(array $markers)
    {
        $this->markers = $markers;
    }

    /**
     * Returns the list of markers.
     *
     * @api
     *
     * @return string[]
     */
    public function getMarkers()
    {
        return $this->markers;
    }

    /**
     * Sets a list of tags to ignore.
     *
     * @param string[] $ignoredTags A list of tags to ignore.
     *
     * @api
     *
     * @return void
     */
    public function setIgnoredTags(array $ignoredTags)
    {
        $this->ignoredTags = $ignoredTags;
    }

    /**
     * Returns the list of ignored tags.
     *
     * @api
     *
     * @return string[]
     */
    public function getIgnoredTags()
    {
        return $this->ignoredTags;
    }

    /**
     * Sets the base path of the files that will be parsed.
     *
     * @param string $path Must be an absolute path.
     *
     * @api
     *
     * @return void
     */
    public function setPath($path)
    {
        $this->path = $path;
    }

    /**
     * Set the visibility of the methods/properties that should be documented
     *
     * @param string $visibility Comma seperated string of visibility modifiers
     *
     * @api
     *
     * @return void
     */
    public function setVisibility($visibility)
    {
        if ('' != $visibility) {
            $this->visibility = explode(',', $visibility);
        }
    }

    /**
     * Returns which elements' are allowed to be returned by visibility.
     *
     * @return string[]
     */
    public function getVisibility()
    {
        return $this->visibility;
    }

    /**
     * Returns the filename, relative to the root of the project directory.
     *
     * @param string $filename The filename to make relative.
     *
     * @throws \InvalidArgumentException if file is not in the project root.
     *
     * @return string
     */
    public function getRelativeFilename($filename)
    {
        // strip path from filename
        $result = ltrim(substr($filename, strlen($this->path)), DIRECTORY_SEPARATOR);
        if ($result === '') {
            throw new \InvalidArgumentException(
                'File is not present in the given project path: ' . $filename
            );
        }

        return $result;
    }

    /**
     * Sets the name of the default package.
     *
     * @param string $defaultPackageName Name used to categorize elements
     *  without an @package tag.
     *
     * @return void
     */
    public function setDefaultPackageName($defaultPackageName)
    {
        $this->defaultPackageName = $defaultPackageName;
    }

    /**
     * Returns the name of the default package.
     *
     * @return string
     */
    public function getDefaultPackageName()
    {
        return $this->defaultPackageName;
    }

    /**
     * Sets the encoding of the files.
     *
     * With this option it is possible to tell the parser to use a specific encoding to interpret the provided files.
     * By default this is set to UTF-8, in which case no action is taken. Any other encoding will result in the output
     * being converted to UTF-8 using `iconv`.
     *
     * Please note that it is recommended to provide files in UTF-8 format; this will ensure a faster performance since
     * no transformation is required.
     *
     * @param string $encoding
     *
     * @return void
     */
    public function setEncoding($encoding)
    {
        $this->encoding = $encoding;
    }

    /**
     * Returns the currently active encoding.
     *
     * @return string
     */
    public function getEncoding()
    {
        return $this->encoding;
    }

    /**
     * Iterates through the given files feeds them to the builder.
     *
     * @param ProjectDescriptorBuilder $builder
     * @param Collection               $files   A files container to parse.
     *
     * @api
     *
     * @throws Exception if no files were found.
     *
     * @return bool|string
     */
    public function parse(ProjectDescriptorBuilder $builder, Collection $files)
    {
        if ($this->stopwatch) {
            $this->stopwatch->start('parser.parse');
        }

        $paths = $this->getFilenames($files);

        $this->log('  Project root is:  ' . $files->getProjectRoot());
        $this->log('  Ignore paths are: ' . implode(', ', $files->getIgnorePatterns()->getArrayCopy()));

        if ($builder->getProjectDescriptor()->getSettings()->isModified()) {
            $this->setForced(true);
            $this->log('One of the project\'s settings have changed, forcing a complete rebuild');
        }

        $memory = 0;
        foreach ($paths as $filename) {
            $this->parseFileIntoDescriptor($builder, $filename);

            $lap       = $this->stopwatch->lap('parser.parse');
            $oldMemory = $memory;
            $periods   = $lap->getPeriods();
            $memory    = end($periods)->getMemory();

            $this->log(
                '>> Memory after processing of file: ' . number_format($memory / 1024 / 1024, 2)
                . ' megabytes (' . (($memory - $oldMemory >= 0)
                    ? '+'
                    : '-') . number_format(($memory - $oldMemory) / 1024)
                . ' kilobytes)',
                LogLevel::DEBUG
            );
        }

        if ($this->stopwatch) {
            $event = $this->stopwatch->stop('parser.parse');

            $this->log('Elapsed time to parse all files: ' . round($event->getDuration(), 2) . 's');
            $this->log('Peak memory usage: '. round($event->getMemory() / 1024 / 1024, 2) . 'M');
        }

        return $builder->getProjectDescriptor();
    }

    /**
     * Extract all filenames from the given collection and output the amount of files.
     *
     * @param Collection $files
     *
     * @throws FilesNotFoundException if no files were found.
     *
     * @return string[]
     */
    protected function getFilenames(Collection $files)
    {
        $paths = $files->getFilenames();
        if (count($paths) < 1) {
            throw new FilesNotFoundException();
        }
        $this->log('Starting to process ' . count($paths) . ' files');

        return $paths;
    }

    /**
     * Parses a file and creates a Descriptor for it in the project.
     *
     * @param ProjectDescriptorBuilder $builder
     * @param string                   $filename
     *
     * @return void
     */
    protected function parseFileIntoDescriptor(ProjectDescriptorBuilder $builder, $filename)
    {
        if (class_exists('phpDocumentor\Event\Dispatcher')) {
            Dispatcher::getInstance()->dispatch(
                'parser.file.pre',
                PreFileEvent::createInstance($this)->setFile($filename)
            );
        }
        $this->log('Starting to parse file: ' . $filename);

        try {
            $file = $this->createFileReflector($builder, $filename);
            if (!$file) {
                $this->log('>> Skipped file ' . $filename . ' as no modifications were detected');
                return;
            }

            $file->process();
            $builder->buildFileUsingSourceData($file);
            $this->logErrorsForDescriptor($builder->getProjectDescriptor()->getFiles()->get($file->getFilename()));
        } catch (Exception $e) {
            $this->log(
                '  Unable to parse file "' . $filename . '", an error was detected: ' . $e->getMessage(),
                LogLevel::ALERT
            );
        }
    }

    /**
     * Creates a new FileReflector for the given filename or null if the file contains no modifications.
     *
     * @param ProjectDescriptorBuilder $builder
     * @param string                   $filename
     *
     * @return FileReflector|null Returns a new FileReflector or null if no modifications were detected for the given
     *     filename.
     */
    protected function createFileReflector(ProjectDescriptorBuilder $builder, $filename)
    {
        $file = new FileReflector($filename, $this->doValidation(), $this->getEncoding());
        $file->setDefaultPackageName($this->getDefaultPackageName());
        $file->setMarkers($this->getMarkers());
        $file->setFilename($this->getRelativeFilename($filename));

        $cachedFiles = $builder->getProjectDescriptor()->getFiles();
        $hash        = $cachedFiles->get($file->getFilename())
            ? $cachedFiles->get($file->getFilename())->getHash()
            : null;

        return $hash === $file->getHash() && !$this->isForced()
            ? null
            : $file;
    }

    /**
     * Writes the errors found in the Descriptor to the log.
     *
     * @param FileDescriptor $fileDescriptor
     *
     * @return void
     */
    protected function logErrorsForDescriptor($fileDescriptor)
    {
        $errors = $fileDescriptor->getAllErrors();
        foreach ($errors as $error) {
            $this->log($error->getCode(), $error->getSeverity(), $error->getContext());
        }
    }

    /**
     * Dispatches a logging request.
     *
     * @param string   $message  The message to log.
     * @param string   $priority The logging priority as declared in the LogLevel PSR-3 class.
     * @param string[] $parameters
     *
     * @return void
     */
    protected function log($message, $priority = LogLevel::INFO, $parameters = array())
    {
        Dispatcher::getInstance()->dispatch(
            'system.log',
            LogEvent::createInstance($this)
            ->setContext($parameters)
            ->setMessage($message)
            ->setPriority($priority)
        );
    }

    /**
     * Dispatches a logging request to log a debug message.
     *
     * @param string $message The message to log.
     *
     * @return void
     */
    protected function debug($message)
    {
        Dispatcher::getInstance()->dispatch(
            'system.debug',
            DebugEvent::createInstance($this)->setMessage($message)
        );
    }

    /**
     * Sets a logger instance on the object
     *
     * @param LoggerInterface $logger
     *
     * @return null
     */
    public function setLogger(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Parser\Event;

use phpDocumentor\Event\EventAbstract;

/**
 * Event thrown before the parsing of an individual file.
 */
class PreFileEvent extends EventAbstract
{
    /** @var string */
    protected $file;

    /**
     * Sets the name of the file that is about to be processed.
     *
     * @param string $file
     *
     * @return self|PreFileEvent
     */
    public function setFile($file)
    {
        $this->file = $file;

        return $this;
    }

    /**
     * Returns the name of the file that is about to be processed.
     *
     * @return string
     */
    public function getFile()
    {
        return $this->file;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Parser\Command\Project;

use phpDocumentor\Command\ConfigurableCommand;
use phpDocumentor\Descriptor\Cache\ProjectDescriptorMapper;
use phpDocumentor\Descriptor\ProjectDescriptor;
use phpDocumentor\Descriptor\ProjectDescriptorBuilder;
use phpDocumentor\Fileset\Collection;
use phpDocumentor\Parser\Event\PreFileEvent;
use phpDocumentor\Parser\Exception\FilesNotFoundException;
use phpDocumentor\Parser\Parser;
use Symfony\Component\Console\Helper\HelperInterface;
use Symfony\Component\Console\Helper\ProgressHelper;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Zend\Cache\Storage\StorageInterface;
use Zend\I18n\Translator\Translator;

/**
 * Parses the given source code and creates a structure file.
 *
 * The parse task uses the source files defined either by -f or -d options and
 * generates a structure file (structure.xml) at the target location (which is
 * the folder 'output' unless the option -t is provided).
 */
class ParseCommand extends ConfigurableCommand
{
    /** @var ProjectDescriptorBuilder $builder*/
    protected $builder;

    /** @var Parser $parser */
    protected $parser;

    /** @var Translator */
    protected $translator;

    public function __construct($builder, $parser, $translator)
    {
        $this->builder    = $builder;
        $this->parser     = $parser;
        $this->translator = $translator;

        parent::__construct('project:parse');
    }

    /**
     * @return ProjectDescriptorBuilder
     */
    public function getBuilder()
    {
        return $this->builder;
    }

    /**
     * @return \phpDocumentor\Parser\Parser
     */
    public function getParser()
    {
        return $this->parser;
    }

    /**
     * Returns the Cache.
     *
     * @return StorageInterface
     */
    protected function getCache()
    {
        return $this->getContainer()->offsetGet('descriptor.cache');
    }

    /**
     * Initializes this command and sets the name, description, options and
     * arguments.
     *
     * @return void
     */
    protected function configure()
    {
        // minimization of the following expression
        $VALUE_OPTIONAL_ARRAY = InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY;

        $this->setAliases(array('parse'))
            ->setDescription($this->__('PPCPP-DESCRIPTION'))
            ->setHelp($this->__('PPCPP-HELPTEXT'))
            ->addOption('filename', 'f', $VALUE_OPTIONAL_ARRAY, $this->__('PPCPP:OPT-FILENAME'))
            ->addOption('directory', 'd', $VALUE_OPTIONAL_ARRAY, $this->__('PPCPP:OPT-DIRECTORY'))
            ->addOption('target', 't', InputOption::VALUE_OPTIONAL, $this->__('PPCPP:OPT-TARGET'))
            ->addOption('encoding', null, InputOption::VALUE_OPTIONAL, $this->__('PPCPP:OPT-ENCODING'))
            ->addOption('extensions', 'e', $VALUE_OPTIONAL_ARRAY, $this->__('PPCPP:OPT-EXTENSIONS'))
            ->addOption('ignore', 'i', $VALUE_OPTIONAL_ARRAY, $this->__('PPCPP:OPT-IGNORE'))
            ->addOption('ignore-tags', null, $VALUE_OPTIONAL_ARRAY, $this->__('PPCPP:OPT-IGNORETAGS'))
            ->addOption('hidden', null, InputOption::VALUE_NONE, $this->__('PPCPP:OPT-HIDDEN'))
            ->addOption('ignore-symlinks', null, InputOption::VALUE_NONE, $this->__('PPCPP:OPT-IGNORESYMLINKS'))
            ->addOption('markers', 'm', $VALUE_OPTIONAL_ARRAY, $this->__('PPCPP:OPT-MARKERS'), array('TODO', 'FIXME'))
            ->addOption('title', null, InputOption::VALUE_OPTIONAL, $this->__('PPCPP:OPT-TITLE'))
            ->addOption('force', null, InputOption::VALUE_NONE, $this->__('PPCPP:OPT-FORCE'))
            ->addOption('validate', null, InputOption::VALUE_NONE, $this->__('PPCPP:OPT-VALIDATE'))
            ->addOption('visibility', null, InputOption::VALUE_OPTIONAL, $this->__('PPCPP:OPT-VISIBILITY'))
            ->addOption('sourcecode', null, InputOption::VALUE_NONE, $this->__('PPCPP:OPT-SOURCECODE'))
            ->addOption('progressbar', 'p', InputOption::VALUE_NONE, $this->__('PPCPP:OPT-PROGRESSBAR'))
            ->addOption('parseprivate', null, InputOption::VALUE_NONE, 'PPCPP:OPT-PARSEPRIVATE')
            ->addOption(
                'defaultpackagename',
                null,
                InputOption::VALUE_OPTIONAL,
                $this->__('PPCPP:OPT-DEFAULTPACKAGENAME'),
                'Default'
            );

        parent::configure();
    }

    /**
     * Executes the business logic involved with this command.
     *
     * @param InputInterface  $input
     * @param OutputInterface $output
     *
     * @throws \Exception if the target location is not a folder.
     *
     * @return integer
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        // invoke parent to load custom config
        parent::execute($input, $output);

        $target = $this->getOption($input, 'target', 'parser/target');
        if (!$this->isAbsolute($target)) {
            $target = getcwd().DIRECTORY_SEPARATOR.$target;
        }
        if (!file_exists($target)) {
            mkdir($target, 0777, true);
        }
        if (!is_dir($target)) {
            throw new \Exception($this->__('PPCPP:EXC-BADTARGET'));
        }
        $this->getCache()->getOptions()->setCacheDir($target);

        $builder = $this->getBuilder();
        $builder->createProjectDescriptor();
        $projectDescriptor = $builder->getProjectDescriptor();
        $visibility = ProjectDescriptor\Settings::VISIBILITY_DEFAULT;
        if ($input->getOption('parseprivate')) {
            $visibility = $visibility | ProjectDescriptor\Settings::VISIBILITY_INTERNAL;
        }
        $projectDescriptor->getSettings()->setVisibility($visibility);

        $output->write($this->__('PPCPP:LOG-COLLECTING'));
        $files = $this->getFileCollection($input);
        $output->writeln($this->__('PPCPP:LOG-OK'));

        /** @var ProgressHelper $progress  */
        $progress = $this->getProgressBar($input);
        if (!$progress) {
            $this->getHelper('phpdocumentor_logger')->connectOutputToLogging($output, $this);
        }

        $output->write($this->__('PPCPP:LOG-INITIALIZING'));
        $this->populateParser($input, $files);

        if ($progress) {
            $progress->start($output, $files->count());
        }

        try {
            $output->writeln($this->__('PPCPP:LOG-OK'));
            $output->writeln($this->__('PPCPP:LOG-PARSING'));

            $mapper = new ProjectDescriptorMapper($this->getCache());
            $mapper->garbageCollect($files);
            $mapper->populate($projectDescriptor);

            $this->getParser()->parse($builder, $files);
        } catch (FilesNotFoundException $e) {
            throw new \Exception($this->__('PPCPP:EXC-NOFILES'));
        } catch (\Exception $e) {
            throw new \Exception($e->getMessage(), 0, $e);
        }

        if ($progress) {
            $progress->finish();
        }

        $projectDescriptor->setPartials($this->getService('partials'));

        $output->write($this->__('PPCPP:LOG-STORECACHE', (array) $this->getCache()->getOptions()->getCacheDir()));
        $mapper->save($projectDescriptor);

        $output->writeln($this->__('PPCPP:LOG-OK'));

        return 0;
    }

    /**
     * @param InputInterface $input
     * @param Collection     $files
     */
    protected function populateParser(InputInterface $input, Collection $files)
    {
        $parser = $this->getParser();
        $title = (string) $this->getOption($input, 'title', 'title');
        $this->getBuilder()->getProjectDescriptor()->setName($title ?: 'API Documentation');
        $parser->setForced($input->getOption('force'));
        $parser->setEncoding($this->getOption($input, 'encoding', 'parser/encoding'));
        $parser->setMarkers($this->getOption($input, 'markers', 'parser/markers/item', null, true));
        $parser->setIgnoredTags($input->getOption('ignore-tags'));
        $parser->setValidate($input->getOption('validate'));
        $parser->setVisibility((string) $this->getOption($input, 'visibility', 'parser/visibility'));
        $parser->setDefaultPackageName($this->getOption($input, 'defaultpackagename', 'parser/default-package-name'));
        $parser->setPath($files->getProjectRoot());
    }

    /**
     * Returns the collection of files based on the input and configuration.
     *
     * @param InputInterface $input
     *
     * @return Collection
     */
    protected function getFileCollection($input)
    {
        $files = new Collection();
        $files->setAllowedExtensions(
            $this->getOption($input, 'extensions', 'parser/extensions/extension', array('php', 'php3', 'phtml'), true)
        );
        $files->setIgnorePatterns($this->getOption($input, 'ignore', 'files/ignore', array(), true));
        $files->setIgnoreHidden($this->getOption($input, 'hidden', 'files/ignore-hidden', 'off') == 'on');
        $files->setFollowSymlinks($this->getOption($input, 'ignore-symlinks', 'files/ignore-symlinks', 'off') == 'on');

        $file_options = $this->getOption($input, 'filename', 'files/file', array(), true);
        $added_files = array();
        foreach ($file_options as $glob) {
            if (!is_string($glob)) {
                continue;
            }

            $matches = glob($glob);
            if (is_array($matches)) {
                foreach ($matches as $file) {
                    if (!empty($file)) {
                        $file = realpath($file);
                        if (!empty($file)) {
                            $added_files[] = $file;
                        }
                    }
                }
            }
        }
        $files->addFiles($added_files);

        $directory_options = $this->getOption($input, 'directory', 'files/directory', array(), true);
        $added_directories = array();
        foreach ($directory_options as $glob) {
            if (!is_string($glob)) {
                continue;
            }

            $matches = glob($glob, GLOB_ONLYDIR);
            if (is_array($matches)) {
                foreach ($matches as $dir) {
                    if (!empty($dir)) {
                        $dir = realpath($dir);
                        if (!empty($dir)) {
                            $added_directories[] = $dir;
                        }
                    }
                }
            }
        }
        $files->addDirectories($added_directories);

        return $files;
    }

    /**
     * Adds the parser.file.pre event to the advance the progressbar.
     *
     * @param InputInterface $input
     *
     * @return \Symfony\Component\Console\Helper\HelperInterface|null
     */
    protected function getProgressBar(InputInterface $input)
    {
        $progress = parent::getProgressBar($input);
        if (!$progress) {
            return null;
        }

        $this->getService('event_dispatcher')->addListener(
            'parser.file.pre',
            function (PreFileEvent $event) use ($progress) {
                $progress->advance();
            }
        );

        return $progress;
    }

    /**
     * Translates the provided text and replaces any contained parameters using printf notation.
     *
     * @param string   $text
     * @param string[] $parameters
     *
     * @return string
     */
    // @codingStandardsIgnoreStart
    protected function __($text, $parameters = array())
    // @codingStandardsIgnoreEnd
    {
        return vsprintf($this->translator->translate($text), $parameters);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

return array(
    // File: phpDocumentor\Parser\Command\Project\ParseCommand (PPCPP)
    'PPCPP-DESCRIPTION' => 'Creates a structure file from your source code',
    'PPCPP-HELPTEXT' => <<<HELP
The parse task uses the source files defined either by -f or -d options and
generates cache files at the target location.
HELP
,
    // Parameter descriptions
    'PPCPP:OPT-FILENAME'           => 'Comma-separated list of files to parse. The wildcards ? and * are supported',
    'PPCPP:OPT-DIRECTORY'          => 'Comma-separated list of directories to (recursively) parse',
    'PPCPP:OPT-TARGET'             => 'Path where to store the cache (optional)',
    'PPCPP:OPT-ENCODING'           => 'Encoding to be used to interpret source files with',
    'PPCPP:OPT-EXTENSIONS'         => 'Comma-separated list of extensions to parse, defaults to php, php3 and phtml',
    'PPCPP:OPT-IGNORE'             => 'Comma-separated list of file(s) and directories that will be ignored. '
        . 'Wildcards * and ? are supported',
    'PPCPP:OPT-IGNORETAGS'         => 'Comma-separated list of tags that will be ignored, defaults to none. package, '
        . 'subpackage and ignore may not be ignored.',
    'PPCPP:OPT-HIDDEN'             => 'Set to on to descend into hidden directories (directories starting with \'.\'), '
        . 'default is on',
    'PPCPP:OPT-IGNORESYMLINKS'     => 'Ignore symlinks to other files or directories, default is on',
    'PPCPP:OPT-MARKERS'            => 'Comma-separated list of markers/tags to filter',
    'PPCPP:OPT-TITLE'              => 'Sets the title for this project; default is the phpDocumentor logo',
    'PPCPP:OPT-FORCE'              => 'Forces a full build of the documentation, does not increment existing '
        . 'documentation',
    'PPCPP:OPT-VALIDATE'           => 'Validates every processed file using PHP Lint, costs a lot of performance',
    'PPCPP:OPT-VISIBILITY'         => 'Specifies the parse visibility that should be displayed in the documentation '
        . '(comma separated e.g. "public,protected")',
    'PPCPP:OPT-DEFAULTPACKAGENAME' => 'Name to use for the default package.',
    'PPCPP:OPT-SOURCECODE'         => 'Whether to include syntax highlighted source code',
    'PPCPP:OPT-PROGRESSBAR'        => 'Whether to show a progress bar; will automatically quiet logging to stdout',
    'PPCPP:OPT-PARSEPRIVATE'       => 'Whether to parse DocBlocks marked with @internal tag',

    // Log and exception messages
    'PPCPP:LOG-COLLECTING'   => 'Collecting files .. ',
    'PPCPP:LOG-OK'           => 'OK',
    'PPCPP:LOG-INITIALIZING' => 'Initializing parser .. ',
    'PPCPP:LOG-PARSING'      => 'Parsing files',
    'PPCPP:LOG-STORECACHE'   => 'Storing cache in "%s" .. ',
    'PPCPP:EXC-NOFILES'      => 'No parsable files were found, did you specify any using the -f or -d parameter?',
    'PPCPP:EXC-BADTARGET'    => 'The provided target location must be a directory',
    'PPCPP:EXC-NOPARTIAL'    => 'Partial "%s" not readable or found.',
);
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Parser;

use Cilex\Application;
use Cilex\ServiceProviderInterface;
use phpDocumentor\Event\Dispatcher;
use phpDocumentor\Parser\Command\Project\ParseCommand;
use phpDocumentor\Partials\Collection as PartialsCollection;
use phpDocumentor\Plugin\Core\Descriptor\Validator\ValidatorAbstract;
use phpDocumentor\Reflection\Event\PostDocBlockExtractionEvent;
use phpDocumentor\Translator;

/**
 * This provider is responsible for registering the parser component with the given Application.
 */
class ServiceProvider implements ServiceProviderInterface
{
    /**
     * Registers services on the given app.
     *
     * @param Application $app An Application instance
     *
     * @throws Exception\MissingDependencyException if the Descriptor Builder is not present.
     * @throws Exception\MissingNameForPartialException if a partial has no name provided.
     *
     * @return void
     */
    public function register(Application $app)
    {
        if (!isset($app['descriptor.builder'])) {
            throw new Exception\MissingDependencyException(
                'The builder object that is used to construct the ProjectDescriptor is missing'
            );
        }

        $app['parser'] = $app->share(
            function ($app) {
                $parser = new Parser();
                $parser->setStopwatch($app['kernel.stopwatch']);
                $parser->setLogger($app['monolog']);
                return $parser;
            }
        );

        $app['markdown'] = $app->share(
            function () {
                return \Parsedown::instance();
            }
        );

        /** @var Translator $translator  */
        $translator = $app['translator'];
        $translator->addTranslationFolder(__DIR__ . DIRECTORY_SEPARATOR . 'Messages');

        $config = $app['config']->toArray();

        $partialsCollection = new PartialsCollection($app['markdown']);
        if (isset($config['partials'])) {
            $partials = is_array(current($config['partials']['partial']))
                ? $config['partials']['partial']
                : array($config['partials']['partial']);

            foreach ($partials as $partial) {
                if (!isset($partial['name'])) {
                    throw new Exception\MissingNameForPartialException('The name of the partial to load is missing');
                }
                if (isset($partial['content'])) {
                    $partialsCollection->set($partial['name'], $partial['content']);
                } elseif (isset($partial['link'])) {
                    if (!is_readable($partial['link'])) {
                        $app['monolog']->error(
                            sprintf($translator->translate('PPCPP:EXC-NOPARTIAL'), $partial['link'])
                        );
                    } else {
                        $partialsCollection->set($partial['name'], file_get_contents($partial['link']));
                    }
                } else {
                    $partialsCollection->set($partial['name'], '');
                }
            }

        }
        $app['partials'] = $partialsCollection;

        $app->command(new ParseCommand($app['descriptor.builder'], $app['parser'], $translator));

        /** @var Dispatcher $dispatcher  */
        $dispatcher = $app['event_dispatcher'];
        $dispatcher->addListener('reflection.docblock-extraction.post', array($this, 'validateDocBlocks'));
    }

    /**
     * Checks all phpDocumentor whether they match the given rules.
     *
     * @param PostDocBlockExtractionEvent $data Event object containing the parameters.
     *
     * @return void
     */
    public function validateDocBlocks($data)
    {
        /** @var \phpDocumentor\Reflection\BaseReflector $element */
        $element = $data->getSubject();

        /** @var \phpDocumentor\Reflection\DocBlock $docblock */
        $docblock = $data->getDocblock();

        // get the type of element
        $type = substr(
            get_class($element),
            strrpos(get_class($element), '\\') + 1,
            -9 // Reflector
        );

        // no docblock, or docblock should be ignored, so no reason to validate
        if ($docblock && $docblock->hasTag('ignore')) {
            return;
        }

        $validatorOptions = $this->loadConfiguration();

        foreach (array('Deprecated', 'Required', $type) as $validator) {

            // todo: move to a factory or builder class
            $class = 'phpDocumentor\Plugin\Core\Parser\DocBlock\Validator\\' . $validator . 'Validator';
            if (class_exists($class)) {
                /** @var ValidatorAbstract $val */
                $val = new $class($element->getName(), $docblock, $element);
                $val->setOptions($validatorOptions);
                $val->isValid($element);
            }
        }
    }

    /**
     * Load the configuration from the plugin.xml file
     *
     * @todo restore required/deprecated validators
     *
     * @return array
     */
    protected function loadConfiguration()
    {
        //$configOptions = $this->plugin->getOptions();
        $validatorOptions = array();

        //foreach (array('deprecated', 'required') as $tag) {
        //    $validatorOptions[$tag] = $this->loadConfigurationByElement($configOptions, $tag);
        //}

        return $validatorOptions;
    }

    /**
     * Load the configuration for given element (deprecated/required)
     *
     * @param array  $configOptions The configuration from the plugin.xml file
     * @param string $configType    Required/Deprecated for the time being
     *
     * @return array
     */
    protected function loadConfigurationByElement($configOptions, $configType)
    {
        $validatorOptions = array();

        if (isset($configOptions[$configType]->tag)) {

            foreach ($configOptions[$configType]->tag as $tag) {
                $tagName = (string) $tag['name'];

                if (isset($tag->element)) {
                    foreach ($tag->element as $type) {
                        $typeName = (string) $type;
                        $validatorOptions[$typeName][] = $tagName;
                    }
                } else {
                    $validatorOptions['__ALL__'][] = $tagName;
                }
            }
        }

        return $validatorOptions;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Parser\Exception;

/**
 * This exception is thrown when a required dependency is not included.
 */
class MissingDependencyException extends \RuntimeException
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Parser\Exception;

/**
 * This exception is thrown when a required name is not set.
 */
class MissingNameForPartialException extends \RuntimeException
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Parser\Exception;

/**
 * Exception that is thrown when the parser expects files but is unable to find them.
 */
class FilesNotFoundException extends \Exception
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Router\Matcher;

use phpDocumentor\Descriptor\DescriptorAbstract;

/**
 * Description of the public interface to match Descriptors with a Routing rule.
 */
interface MatcherInterface
{
    /**
     * Checks whether the given string or Descriptor matches this definition.
     *
     * @param string|DescriptorAbstract $node
     *
     * @return boolean
     */
    public function __invoke($node);
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Router;

use phpDocumentor\Descriptor\ClassDescriptor;
use phpDocumentor\Descriptor\ConstantDescriptor;
use phpDocumentor\Descriptor\FunctionDescriptor;
use phpDocumentor\Descriptor\InterfaceDescriptor;
use phpDocumentor\Descriptor\MethodDescriptor;
use phpDocumentor\Descriptor\NamespaceDescriptor;
use phpDocumentor\Descriptor\PackageDescriptor;
use phpDocumentor\Descriptor\PropertyDescriptor;
use phpDocumentor\Descriptor\TraitDescriptor;
use phpDocumentor\Descriptor\FileDescriptor;

/**
 * The default router for phpDocumentor.
 */
class StandardRouter extends RouterAbstract
{
    /**
     * Configuration function to add routing rules to a router.
     *
     * @return void
     */
    public function configure()
    {
        $fileGenerator      = new UrlGenerator\Standard\FileDescriptor();
        $namespaceGenerator = new UrlGenerator\Standard\NamespaceDescriptor();
        $packageGenerator   = new UrlGenerator\Standard\PackageDescriptor();
        $classGenerator     = new UrlGenerator\Standard\ClassDescriptor();
        $methodGenerator    = new UrlGenerator\Standard\MethodDescriptor();
        $constantGenerator  = new UrlGenerator\Standard\ConstantDescriptor();
        $functionGenerator  = new UrlGenerator\Standard\FunctionDescriptor();
        $propertyGenerator  = new UrlGenerator\Standard\PropertyDescriptor();

        // @codingStandardsIgnoreStart
        $this[] = new Rule(function ($node) { return ($node instanceof FileDescriptor); }, $fileGenerator);
        $this[] = new Rule(function ($node) { return ($node instanceof PackageDescriptor); }, $packageGenerator);
        $this[] = new Rule(function ($node) { return ($node instanceof TraitDescriptor); }, $classGenerator);
        $this[] = new Rule(function ($node) { return ($node instanceof NamespaceDescriptor); }, $namespaceGenerator);
        $this[] = new Rule(function ($node) { return ($node instanceof InterfaceDescriptor); }, $classGenerator );
        $this[] = new Rule(function ($node) { return ($node instanceof ClassDescriptor); }, $classGenerator);
        $this[] = new Rule(function ($node) { return ($node instanceof ConstantDescriptor); }, $constantGenerator);
        $this[] = new Rule(function ($node) { return ($node instanceof MethodDescriptor); }, $methodGenerator);
        $this[] = new Rule(function ($node) { return ($node instanceof FunctionDescriptor); }, $functionGenerator);
        $this[] = new Rule( function ($node) { return ($node instanceof PropertyDescriptor); }, $propertyGenerator);

        // do not generate a file for every unknown type
        $this[] = new Rule(function () { return true; }, function () { return false; });
        // @codingStandardsIgnoreEnd
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Router\UrlGenerator;

use phpDocumentor\Descriptor\DescriptorAbstract;

/**
 * Generates relative URLs with elements for use in the generated HTML documentation.
 */
interface UrlGeneratorInterface
{
    /**
     * Generates a URL from the given node or returns false if unable.
     *
     * @param string|DescriptorAbstract $node
     *
     * @return string|false
     */
    public function __invoke($node);
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Router\UrlGenerator\Standard;

use phpDocumentor\Descriptor;
use phpDocumentor\Transformer\Router\UrlGenerator\UrlGeneratorInterface;

class ClassDescriptor implements UrlGeneratorInterface
{
    /**
     * Generates a URL from the given node or returns false if unable.
     *
     * @param string|Descriptor\ClassDescriptor $node
     *
     * @return string|false
     */
    public function __invoke($node)
    {
        return '/classes/'
            . str_replace('\\', '.', ltrim($node->getFullyQualifiedStructuralElementName(), '\\')).'.html';
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Router\UrlGenerator\Standard;

use phpDocumentor\Descriptor;
use phpDocumentor\Transformer\Router\UrlGenerator\UrlGeneratorInterface;

class NamespaceDescriptor implements UrlGeneratorInterface
{
    /**
     * Generates a URL from the given node or returns false if unable.
     *
     * @param string|Descriptor\NamespaceDescriptor $node
     *
     * @return string|false
     */
    public function __invoke($node)
    {
        $name = str_replace('\\', '.', ltrim($node->getFullyQualifiedStructuralElementName(), '\\'));

        // convert root namespace to default; default is a keyword and no namespace CAN be named as such
        if ($name === '') {
            $name = 'default';
        }

        return '/namespaces/' . $name .'.html';
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Router\UrlGenerator\Standard;

use phpDocumentor\Descriptor;
use phpDocumentor\Transformer\Router\UrlGenerator\UrlGeneratorInterface;

class FileDescriptor implements UrlGeneratorInterface
{
    /**
     * Generates a URL from the given node or returns false if unable.
     *
     * @param string|Descriptor\FileDescriptor $node
     *
     * @return string|false
     */
    public function __invoke($node)
    {
        $name = str_replace(array('/', '\\'), '.', ltrim($node->getPath(), '/'));

        return '/files/' . $name .'.html';
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Router\UrlGenerator\Standard;

use phpDocumentor\Descriptor;
use phpDocumentor\Transformer\Router\UrlGenerator\UrlGeneratorInterface;

/**
 * Generates a relative URL with functions for use in the generated HTML documentation..
 */
class FunctionDescriptor implements UrlGeneratorInterface
{
    /**
     * Generates a URL from the given node or returns false if unable.
     *
     * @param string|Descriptor\FunctionDescriptor $node
     *
     * @return string|false
     */
    public function __invoke($node)
    {
        $namespaceName = $node->getNamespace();
        $name          = $node->getName();

        return '/namespaces/' . str_replace('\\', '.', ltrim($namespaceName, '\\')).'.html#function_' . $name;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Router\UrlGenerator\Standard;

use phpDocumentor\Descriptor;
use phpDocumentor\Transformer\Router\UrlGenerator\UrlGeneratorInterface;

class PackageDescriptor implements UrlGeneratorInterface
{
    /**
     * Generates a URL from the given node or returns false if unable.
     *
     * @param string|Descriptor\PackageDescriptor $node
     *
     * @return string|false
     */
    public function __invoke($node)
    {
        $name = str_replace(array('\\', '_'), '.', ltrim($node->getFullyQualifiedStructuralElementName(), '\\'));

        // convert root namespace to default; default is a keyword and no namespace CAN be named as such
        if ($name === '') {
            $name = 'default';
        }

        return '/packages/' . $name .'.html';
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Router\UrlGenerator\Standard;

use phpDocumentor\Descriptor;
use phpDocumentor\Transformer\Router\UrlGenerator\UrlGeneratorInterface;

/**
 * Generates a relative URL with properties for use in the generated HTML documentation.
 */
class PropertyDescriptor implements UrlGeneratorInterface
{
    /**
     * Generates a URL from the given node or returns false if unable.
     *
     * @param string|Descriptor\PropertyDescriptor $node
     *
     * @return string|false
     */
    public function __invoke($node)
    {
        $className = $node->getParent()->getFullyQualifiedStructuralElementName();
        $name = $node->getName();

        return '/classes/' . str_replace('\\', '.', ltrim($className, '\\')).'.html#property_' . $name;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Router\UrlGenerator\Standard;

use phpDocumentor\Descriptor;
use phpDocumentor\Transformer\Router\UrlGenerator\UrlGeneratorInterface;

/**
 * Generates a relative URL with methods for use in the generated HTML documentation.
 */
class MethodDescriptor implements UrlGeneratorInterface
{
    /**
     * Generates a URL from the given node or returns false if unable.
     *
     * @param string|Descriptor\MethodDescriptor $node
     *
     * @return string|false
     */
    public function __invoke($node)
    {
        $className = $node->getParent()->getFullyQualifiedStructuralElementName();
        $name = $node->getName();

        return '/classes/' . str_replace('\\', '.', ltrim($className, '\\')).'.html#method_' . $name;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Router\UrlGenerator\Standard;

use phpDocumentor\Descriptor;
use phpDocumentor\Transformer\Router\UrlGenerator\UrlGeneratorInterface;

class ConstantDescriptor implements UrlGeneratorInterface
{
    /**
     * Generates a URL from the given node or returns false if unable.
     *
     * @param string|Descriptor\ConstantDescriptor $node
     *
     * @return string|false
     */
    public function __invoke($node)
    {
        $name = $node->getName();

        // global constant
        if ($node->getParent() instanceof Descriptor\FileDescriptor || ! $node->getParent()) {
            $namespaceName = $node->getNamespace();

            return '/namespaces/' . str_replace('\\', '.', ltrim($namespaceName, '\\')).'.html#constant_' . $name;
        }

        // class constant
        $className = $node->getParent()->getFullyQualifiedStructuralElementName();

        return '/classes/' . str_replace('\\', '.', ltrim($className, '\\')).'.html#constant_' . $name;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Router;

/**
 * A rule determines if and how a node should be transformed to an URL.
 */
use phpDocumentor\Descriptor\DescriptorAbstract;

class Rule
{
    protected $matcher;
    protected $generator;

    /**
     * @param callable $matcher
     * @param callable $generator
     */
    public function __construct($matcher, $generator)
    {
        $this->matcher   = $matcher;
        $this->generator = $generator;
    }

    /**
     * @param string|DescriptorAbstract $node
     *
     * @return mixed
     */
    public function match($node)
    {
        $callable = $this->matcher;

        return $callable($node);
    }

    /**
     * Generates an URL for the given node.
     *
     * @param string|DescriptorAbstract $node The node for which to generate an URL.
     *
     * @return string|false a well-formed relative or absolute URL, or false if no URL could be generated.
     */
    public function generate($node)
    {
        $callable = $this->generator;

        return $callable($node);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Router;

use phpDocumentor\Descriptor\DescriptorAbstract;

/**
 * Provides a queue of routers to determine the order in which they are executed.
 */
class Queue extends \SplPriorityQueue
{
    /**
     * Tries to match the given node with a rule defined in one of the routers.
     *
     * @param string|DescriptorAbstract $node
     *
     * @return Rule|null
     */
    public function match($node)
    {
        /** @var RouterAbstract $router */
        foreach (clone $this as $router) {
            $rule = $router->match($node);
            if ($rule) {
                return $rule;
            }
        }

        return null;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Router;

use Zend\Config\Config;

/**
 * Connects class, interface and traits to remote documentation sets.
 */
class ExternalRouter extends RouterAbstract
{
    /** @var Config */
    protected $configuration;

    /**
     * Registers the application configuration with this router.
     *
     * The configuration is used to extract which external routes to add to the application.
     *
     * @param Config $configuration
     */
    public function __construct(Config $configuration)
    {
        $this->configuration = $configuration;
        parent::__construct();
    }

    /**
     * Configuration function to add routing rules to a router.
     *
     * @return void
     */
    public function configure()
    {
        if (!isset($this->configuration->transformer->{'external-class-documentation'})) {
            return;
        }

        $docs = $this->configuration->transformer->{'external-class-documentation'};
        if (isset($docs->prefix)) {
            $docs = array($docs);
        }

        foreach ((array)$docs as $external) {
            $prefix = (string)$external->prefix;
            $uri    = (string)$external->uri;

            $this[] = new Rule(
                function ($node) use ($prefix) {
                    return (is_string($node) && (strpos(ltrim($node, '\\'), $prefix) === 0));
                },
                function ($node) use ($uri) {
                    return str_replace('{CLASS}', ltrim($node, '\\'), $uri);
                }
            );
        }
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Router;

use phpDocumentor\Descriptor\DescriptorAbstract;

/**
 * Proxies a generated Routing Rule to generate physical filenames.
 *
 * By default a RoutingRule will generate a relative path on a webserver. This causes
 * issues between operating systems since Linux uses / and Windows \ as a directory
 * separator.
 *
 * To make sure that the correct file is generated can this proxy be used to generate
 * a filename instead of a webserver path.
 */
class ForFileProxy
{
    /** @var Rule $rule Contains the Routing Rule that is wrapped by this proxy */
    protected $rule;

    /**
     * Registers the Routing Rule that needs to be translated with this proxy.
     *
     * @param Rule $rule
     */
    public function __construct(Rule $rule)
    {
        $this->rule = $rule;
    }

    /**
     * Generates an URL for the given node.
     *
     * @param string|DescriptorAbstract $node               The node for which to generate an URL.
     * @param string                    $directorySeparator Which directory separator should be used to generate the
     *     paths with, defaults to the default separator for the current O/S.
     *
     * @return string|false a well-formed relative or absolute URL, or false if no URL could be generated.
     */
    public function generate($node, $directorySeparator = DIRECTORY_SEPARATOR)
    {
        $webserverPath = $this->rule->generate($node);

        return $webserverPath === false ? false : str_replace('/', $directorySeparator, $webserverPath);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Router;

use phpDocumentor\Descriptor\DescriptorAbstract;

/**
 * Object containing a collection of routes.
 */
abstract class RouterAbstract extends \ArrayObject
{
    /**
     * Invokes the configure method.
     */
    public function __construct()
    {
        parent::__construct();

        $this->configure();
    }

    /**
     * Configuration function to add routing rules to a router.
     *
     * @return void
     */
    abstract public function configure();

    /**
     * Tries to match the provided node with one of the rules in this router.
     *
     * @param string|DescriptorAbstract $node
     *
     * @return Rule|null
     */
    public function match($node)
    {
        /** @var Rule $rule */
        foreach ($this as $rule) {
            if ($rule->match($node)) {
                return $rule;
            }
        }

        return null;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer;

/**
 * Provides the basic exception for the parser package.
 */
class Exception extends \Exception
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Event;

use phpDocumentor\Event\EventAbstract;

/**
 * Event that happens prior to the execution of all transformations.
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 */
class PreTransformEvent extends EventAbstract
{
    /** @var \DOMDocument */
    protected $source;

    /**
     * Sets the source DOMDocument into this event.
     *
     * This DOMDocument contains the entire Abstract Syntax Tree and may be used
     * to extract information from or alter information in.
     *
     * @param \DOMDocument $source
     *
     * @return PreTransformEvent for a fluent interface
     */
    public function setSource($source)
    {
        $this->source = $source;

        return $this;
    }

    /**
     * Returns the Abstract Syntax Tree.
     *
     * @return \DOMDocument
     */
    public function getSource()
    {
        return $this->source;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Event;

/**
 * Event that happens after each individual transformation.
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 */
class PostTransformationEvent extends PreTransformationEvent
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Event;

use phpDocumentor\Event\EventAbstract;

/**
 * Event launched during the Xsl Transformation of an individual output file.
 *
 * If the XSL Writer loops through a resultset then this event will be thrown
 * for each result.
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 */
class PreXslWriterEvent extends EventAbstract
{
    /** @var \DOMElement */
    protected $element;

    /** @var int[] */
    protected $progress = array(0, 0);

    /**
     * Sets the currently parsed element in this event.
     *
     * @param \DOMElement $element
     *
     * @return PreXslWriterEvent
     */
    public function setElement($element)
    {
        $this->element = $element;

        return $this;
    }

    /**
     * Returns the event that is currently being parsed.
     *
     * @return \DOMElement
     */
    public function getElement()
    {
        return $this->element;
    }

    /**
     * Sets a progress indication for this XSL Writer session.
     *
     * @param int[] $progress Array containing 2 integer values, the current
     *     step in the process and the total number of steps involved.
     *
     * @return PreXslWriterEvent
     */
    public function setProgress($progress)
    {
        $this->progress = $progress;

        return $this;
    }

    /**
     * Returns the current step and tot number of steps as progress.
     *
     * @see setProgress() for a complete description of this array.
     *
     * @return int[]
     */
    public function getProgress()
    {
        return $this->progress;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Event;

/**
 * Event happen right after all transformations have completed.
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 */
class PostTransformEvent extends PreTransformEvent
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Event;

use phpDocumentor\Event\EventAbstract;

/**
 * Event happening prior to each individual transformation.
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 */
class PreTransformationEvent extends EventAbstract
{
    /** @var \DOMDocument */
    protected $source;

    /**
     * Sets the Abstract Syntax Tree as DOMDocument.
     *
     * @param \DOMDocument $source
     *
     * @return PreTransformationEvent
     */
    public function setSource($source)
    {
        $this->source = $source;

        return $this;
    }

    /**
     * Returns the Abstract Syntax Tree as DOMDocument.
     *
     * @return \DOMDocument
     */
    public function getSource()
    {
        return $this->source;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Transformer\Command\Project;

use phpDocumentor\Command\ConfigurableCommand;
use phpDocumentor\Compiler\Compiler;
use phpDocumentor\Compiler\CompilerPassInterface;
use phpDocumentor\Descriptor\Cache\ProjectDescriptorMapper;
use phpDocumentor\Descriptor\ProjectDescriptorBuilder;
use phpDocumentor\Transformer\Template;
use phpDocumentor\Transformer\Transformation;
use phpDocumentor\Transformer\Transformer;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Zend\Cache\Storage\StorageInterface;

/**
 * Transforms the structure file into the specified output format
 *
 * This task will execute the transformation rules described in the given
 * template (defaults to 'responsive') with the given source (defaults to
 * output/structure.xml) and writes these to the target location (defaults to
 * 'output').
 *
 * It is possible for the user to receive additional information using the
 * verbose option or stop additional information using the quiet option. Please
 * take note that the quiet option also disables logging to file.
 */
class TransformCommand extends ConfigurableCommand
{
    /** @var ProjectDescriptorBuilder $builder */
    protected $builder;

    /** @var Transformer $transformer */
    protected $transformer;

    /** @var Compiler $compiler */
    protected $compiler;

    public function __construct($builder, $transformer, $compiler)
    {
        parent::__construct('project:transform');

        $this->builder     = $builder;
        $this->transformer = $transformer;
        $this->compiler    = $compiler;
    }

    /**
     * Initializes this command and sets the name, description, options and
     * arguments.
     *
     * @return void
     */
    protected function configure()
    {
        $this->setAliases(array('transform'))
            ->setDescription(
                'Converts the PHPDocumentor structure file to documentation'
            )
            ->setHelp(
<<<TEXT
This task will execute the transformation rules described in the given
template (defaults to 'responsive') with the given source (defaults to
output/structure.xml) and writes these to the target location (defaults to
'output').

It is possible for the user to receive additional information using the
verbose option or stop additional information using the quiet option. Please
take note that the quiet option also disables logging to file.
TEXT
            );

        $this->addOption(
            'source',
            's',
            InputOption::VALUE_OPTIONAL,
            'Path where the XML source file is located (optional)'
        );
        $this->addOption(
            'target',
            't',
            InputOption::VALUE_OPTIONAL,
            'Path where to store the generated output (optional)'
        );
        $this->addOption(
            'template',
            null,
            InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
            'Name of the template to use (optional)'
        );
        $this->addOption(
            'progressbar',
            'p',
            InputOption::VALUE_NONE,
            'Whether to show a progress bar; will automatically quiet logging to stdout'
        );

        parent::configure();
    }

    /**
     * @return ProjectDescriptorBuilder
     */
    public function getBuilder()
    {
        return $this->builder;
    }

    /**
     * @return \phpDocumentor\Transformer\Transformer
     */
    public function getTransformer()
    {
        return $this->transformer;
    }

    /**
     * Returns the Cache.
     *
     * @return StorageInterface
     */
    protected function getCache()
    {
        return $this->getContainer()->offsetGet('descriptor.cache');
    }

    /**
     * Executes the business logic involved with this command.
     *
     * @param InputInterface  $input
     * @param OutputInterface $output
     *
     * @throws \Exception if the provided source is not an existing file or a folder.
     *
     * @return int
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        // invoke parent to load custom config
        parent::execute($input, $output);

        $progress = $this->getProgressBar($input);
        if (!$progress) {
            $this->getHelper('phpdocumentor_logger')->connectOutputToLogging($output, $this);
        }

        // initialize transformer
        $transformer = $this->getTransformer();

        $target = $this->getOption($input, 'target', 'transformer/target');
        if (!$this->isAbsolute($target)) {
            $target = getcwd() . DIRECTORY_SEPARATOR . $target;
        }
        $transformer->setTarget($target);

        $source = realpath($this->getOption($input, 'source', 'parser/target'));
        if (!file_exists($source) || !is_dir($source)) {
            throw new \Exception('Invalid source location provided, a path to an existing folder was expected');
        }

        $this->getCache()->getOptions()->setCacheDir($source);

        $projectDescriptor = $this->getBuilder()->getProjectDescriptor();
        $mapper = new ProjectDescriptorMapper($this->getCache());
        $output->writeTimedLog('Load cache', array($mapper, 'populate'), array($projectDescriptor));

        foreach ($this->getTemplates($input) as $template) {
            $output->writeTimedLog(
                'Preparing template "'. $template .'"',
                array($transformer->getTemplates(), 'load'),
                array($template, $transformer)
            );
        }
        $output->writeTimedLog(
            'Preparing ' . count($transformer->getTemplates()->getTransformations()) . ' transformations',
            array($this, 'loadTransformations'),
            array($transformer)
        );

        if ($progress) {
            $progress->start($output, count($transformer->getTemplates()->getTransformations()));
        }

        /** @var CompilerPassInterface $pass */
        foreach ($this->compiler as $pass) {
            $output->writeTimedLog($pass->getDescription(), array($pass, 'execute'), array($projectDescriptor));
        }

        if ($progress) {
            $progress->finish();
        }

        return 0;
    }

    /**
     * Retrieves the templates to be used by analyzing the options and the configuration.
     *
     * @param InputInterface $input
     *
     * @return string[]
     */
    protected function getTemplates(InputInterface $input)
    {
        $templates = $input->getOption('template');
        if (!$templates) {
            $value = $this->getConfigValueFromPath('transformations/template');
            if (is_array($value)) {
                if (isset($value['name'])) {
                    $templates[] = $value['name'];
                } else {
                    foreach ($value as $template) {
                        if (is_array($template)) {
                            $templates[] = $template['name'];
                        }
                    }
                }
            }
        }

        if (!$templates) {
            $templates = array('responsive');
        }

        return $templates;
    }

    /**
     * Load custom defined transformations.
     *
     * @param Transformer $transformer
     *
     * @todo this is an ugly implementation done for speed of development, should be refactored
     *
     * @return void
     */
    public function loadTransformations(Transformer $transformer)
    {
        $received = array();
        $transformations = $this->getConfigValueFromPath('transformations/transformation');
        if (is_array($transformations)) {
            if (isset($transformations['writer'])) {
                $received[] = new Transformation(
                    isset($transformations['query']) ? $transformations['query'] : '',
                    $transformations['writer'],
                    isset($transformations['source']) ? $transformations['source'] : '',
                    isset($transformations['artifact']) ? $transformations['artifact'] : ''
                );
            } else {
                foreach ($transformations as $transformation) {
                    if (is_array($transformation)) {
                        $received[] = new Transformation(
                            isset($transformations['query']) ? $transformations['query'] : '',
                            $transformations['writer'],
                            isset($transformations['source']) ? $transformations['source'] : '',
                            isset($transformations['artifact']) ? $transformations['artifact'] : ''
                        );
                    }
                }
            }
        }

        if (!empty($received)) {
            $template = new Template('__');
            foreach ($received as $transformation) {
                $template[] = $transformation;
            }
            $transformer->getTemplates()->append($template);
        }
    }

    /**
     * Adds the transformer.transformation.post event to advance the progressbar.
     *
     * @param InputInterface $input
     *
     * @return \Symfony\Component\Console\Helper\HelperInterface|null
     */
    protected function getProgressBar(InputInterface $input)
    {
        $progress = parent::getProgressBar($input);
        if (!$progress) {
            return null;
        }

        $this->getService('event_dispatcher')->addListener(
            'transformer.transformation.post',
            function () use ($progress) {
                $progress->advance();
            }
        );

        return $progress;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Transformer\Command\Template;

use Cilex\Command\Command;
use \Symfony\Component\Console\Input\InputInterface;
use \Symfony\Component\Console\Output\OutputInterface;

/**
 * Generates a skeleton template.
 */
class ListCommand extends Command
{
    /**
     * Initializes this command and sets the name, description, options and
     * arguments.
     *
     * @return void
     */
    protected function configure()
    {
        $this->setName('template:list')
            ->setDescription(
                'Displays a listing of all available templates in phpDocumentor'
            )
            ->setHelp(
<<<HELP
This task outputs a list of templates as available in phpDocumentor.
Please mind that custom templates which are situated outside phpDocumentor are not
shown in this listing.
HELP
            );
    }

    /**
     * Executes the business logic involved with this command.
     *
     * @param InputInterface  $input
     * @param OutputInterface $output
     *
     * @return int
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $output->writeln('Available templates:');
        foreach ($this->getTemplateNames() as $template_name) {
            $output->writeln('* '.$template_name);
        }
        $output->writeln('');

        return 0;
    }

    /**
     * Returns a list of all template names.
     *
     * @return string[]
     */
    protected function getTemplateNames()
    {
        // TODO: this directory needs to come from the parameter set in the DIC in the ServiceProvider
        $template_dir = dirname(__FILE__) . '/../../../../../data/templates';
        if (!file_exists($template_dir)) {
            //Vendored installation
            $template_dir = dirname(__FILE__) . '/../../../../../../templates';
        }

        /** @var \RecursiveDirectoryIterator $files */
        $files = new \DirectoryIterator($template_dir);

        $template_names = array();
        while ($files->valid()) {
            $name = $files->getBasename();

            // skip abstract files
            if (!$files->isDir() || in_array($name, array('.', '..'))) {
                $files->next();
                continue;
            }

            $template_names[] = $name;
            $files->next();
        }

        return $template_names;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer;

use Psr\Log\LogLevel;
use phpDocumentor\Compiler\CompilerPassInterface;
use phpDocumentor\Descriptor\ProjectDescriptor;
use phpDocumentor\Event\DebugEvent;
use phpDocumentor\Event\Dispatcher;
use phpDocumentor\Event\LogEvent;
use phpDocumentor\Transformer\Event\PostTransformEvent;
use phpDocumentor\Transformer\Event\PostTransformationEvent;
use phpDocumentor\Transformer\Event\PreTransformEvent;
use phpDocumentor\Transformer\Event\PreTransformationEvent;

/**
 * Core class responsible for transforming the cache file to a set of artifacts.
 */
class Transformer implements CompilerPassInterface
{
    /** @var integer represents the priority in the Compiler queue. */
    const COMPILER_PRIORITY = 5000;

    /** @var string|null $target Target location where to output the artifacts */
    protected $target = null;

    /** @var Template\Collection $templates */
    protected $templates;

    /** @var Writer\Collection $writers */
    protected $writers;

    /** @var Behaviour\Collection|null $behaviours */
    protected $behaviours = null;

    /** @var Transformation[] $transformations */
    protected $transformations = array();

    /**
     * Wires the template collection and writer collection to this transformer.
     *
     * @param Template\Collection $templateCollection
     * @param Writer\Collection   $writerCollection
     */
    public function __construct(Template\Collection $templateCollection, Writer\Collection $writerCollection)
    {
        $this->templates = $templateCollection;
        $this->writers   = $writerCollection;
    }

    /**
     * {@inheritDoc}
     */
    public function getDescription()
    {
        return 'Transform analyzed project into artifacts';
    }

    /**
     * Sets the collection of behaviours that are applied before the actual transformation process.
     *
     * @param Behaviour\Collection $behaviours
     *
     * @return void
     */
    public function setBehaviours(Behaviour\Collection $behaviours)
    {
        $this->behaviours = $behaviours;
    }

    /**
     * Retrieves the collection of behaviours that should occur before the transformation process.
     *
     * @return Behaviour\Collection|null
     */
    public function getBehaviours()
    {
        return $this->behaviours;
    }

    /**
     * Sets the target location where to output the artifacts.
     *
     * @param string $target The target location where to output the artifacts.
     *
     * @throws \InvalidArgumentException if the target is not a valid writable
     *   directory.
     *
     * @return void
     */
    public function setTarget($target)
    {
        $path = realpath($target);
        if (false === $path) {
            if (mkdir($target, 0755, true)) {
                $path = realpath($target);
            } else {
                throw new \InvalidArgumentException(
                    'Target directory ('
                    . $target .
                    ') does not exist and could not be created'
                );
            }
        }

        if (!is_dir($path) || !is_writable($path)) {
            throw new \InvalidArgumentException(
                'Given target (' . $target . ') is not a writable directory'
            );
        }

        $this->target = $path;
    }

    /**
     * Returns the location where to store the artifacts.
     *
     * @return string
     */
    public function getTarget()
    {
        return $this->target;
    }

    /**
     * Returns the list of templates which are going to be adopted.
     *
     * @return Template\Collection
     */
    public function getTemplates()
    {
        return $this->templates;
    }

    /**
     * Transforms the given project into a series of artifacts as provided by the templates.
     *
     * @param ProjectDescriptor $project
     *
     * @return void
     */
    public function execute(ProjectDescriptor $project)
    {
        Dispatcher::getInstance()->dispatch('transformer.transform.pre', PreTransformEvent::createInstance($this));

        if ($this->getBehaviours() instanceof Behaviour\Collection) {
            $this->log(sprintf('Applying %d behaviours', count($this->getBehaviours())));
            $this->getBehaviours()->process($project);
        }

        $transformations = $this->getTemplates()->getTransformations();
        $this->log(sprintf('Applying %d transformations', count($transformations)));
        foreach ($transformations as $transformation) {
            $this->log(
                '  Writer ' . $transformation->getWriter()
                . ($transformation->getQuery() ? (' using query "' . $transformation->getQuery() . '"') : '')
                . ' on '.$transformation->getArtifact()
            );

            $transformation->setTransformer($this);

            /** @var Writer\WriterAbstract $writer  */
            $writer = $this->writers[$transformation->getWriter()];

            Dispatcher::getInstance()->dispatch(
                'transformer.transformation.pre',
                PreTransformationEvent::createInstance($this)
            );
            $writer->transform($project, $transformation);
            Dispatcher::getInstance()->dispatch(
                'transformer.transformation.post',
                PostTransformationEvent::createInstance($this)
            );
        }

        Dispatcher::getInstance()->dispatch('transformer.transform.post', PostTransformEvent::createInstance($this));

        $this->log('Finished transformation process');
    }

    /**
     * Converts a source file name to the name used for generating the end result.
     *
     * This method strips down the given $name using the following rules:
     *
     * * if the $name is suffixed with .php then that is removed
     * * any occurrence of \ or DIRECTORY_SEPARATOR is replaced with .
     * * any dots that the name starts or ends with is removed
     * * the result is suffixed with .html
     *
     * @param string $name Name to convert.
     *
     * @return string
     */
    public function generateFilename($name)
    {
        if (substr($name, -4) == '.php') {
            $name = substr($name, 0, -4);
        }

        return trim(str_replace(array(DIRECTORY_SEPARATOR, '\\'), '.', trim($name, DIRECTORY_SEPARATOR . '.')), '.')
            . '.html';
    }

    /**
     * Dispatches a logging request.
     *
     * @param string $message  The message to log.
     * @param string $priority The logging priority
     *
     * @return void
     */
    public function log($message, $priority = LogLevel::INFO)
    {
        Dispatcher::getInstance()->dispatch(
            'system.log',
            LogEvent::createInstance($this)
                ->setMessage($message)
                ->setPriority($priority)
        );
    }

    /**
     * Dispatches a logging request to log a debug message.
     *
     * @param string $message The message to log.
     *
     * @return void
     */
    public function debug($message)
    {
        Dispatcher::getInstance()->dispatch(
            'system.debug',
            DebugEvent::createInstance($this)
                ->setMessage($message)
        );
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer;

use JMS\Serializer\Annotation as Serializer;
use phpDocumentor\Transformer\Template\Parameter;

/**
 * Class representing a single Transformation.
 */
class Transformation
{
    /**
     * @Serializer\XmlAttribute
     * @Serializer\Type("string")
     * @var string
     */
    protected $query = '';

    /**
     * @Serializer\XmlAttribute
     * @Serializer\Type("string")
     * @var string
     */
    protected $writer = null;

    /**
     * @Serializer\XmlAttribute
     * @Serializer\Type("string")
     * @var string
     */
    protected $source = '';

    /**
     * @Serializer\XmlAttribute
     * @Serializer\Type("string")
     * @var string
     */
    protected $artifact = '';

    /**
     * @Serializer\Exclude
     * @var Transformer $transformer
     */
    protected $transformer;

    /**
     * @Serializer\XmlList(entry = "parameter")
     * @Serializer\Type("array<phpDocumentor\Transformer\Template\Parameter>")
     * @var Parameter[]
     */
    protected $parameters = array();

    /**
     * Constructs a new Transformation object and populates the required parameters.
     *
     * @param string $query       What information to use as datasource for the writer's source.
     * @param string $writer      What type of transformation to apply (XSLT, PDF, Checkstyle etc).
     * @param string $source      Which template or type of source to use.
     * @param string $artifact    What is the filename of the result (relative to the generated root)
     */
    public function __construct($query, $writer, $source, $artifact)
    {
        $this->setQuery($query);
        $this->setWriter($writer);
        $this->setSource($source);
        $this->setArtifact($artifact);
    }

    /**
     * Sets the query.
     *
     * @param string $query Free-form string with writer-specific values.
     *
     * @return void
     */
    public function setQuery($query)
    {
        $this->query = $query;
    }

    /**
     * Returns the set query.
     *
     * @return string
     */
    public function getQuery()
    {
        return $this->query;
    }

    /**
     * Sets the writer type and instantiates a writer.
     *
     * @param string $writer Name of writer to instantiate.
     *
     * @return void
     */
    public function setWriter($writer)
    {
        $this->writer = $writer;
    }

    /**
     * Returns an instantiated writer object.
     *
     * @return Writer\WriterAbstract|null
     */
    public function getWriter()
    {
        return $this->writer;
    }

    /**
     * Sets the source / type which the writer will use to generate artifacts from.
     *
     * @param string $source Free-form string with writer-specific meaning.
     *
     * @return void
     */
    public function setSource($source)
    {
        $this->source = $source;
    }

    /**
     * Returns the name of the source / type used in the transformation process.
     *
     * @return string
     */
    public function getSource()
    {
        return $this->source;
    }

    /**
     * Returns the source as a path instead of a regular value.
     *
     * This method applies the following rules to the value of $source:
     *
     * 1. if the template_path parameter is set and that combined with the
     *    source gives an existing file; return that.
     * 2. if the value exists as a file (either relative to the current working
     *    directory or absolute), do a realpath and return it.
     * 3. Otherwise prepend it with the phpDocumentor data folder, if that does
     *    not exist: throw an exception
     *
     * @throws Exception if no valid file could be found.
     *
     * @return string
     */
    public function getSourceAsPath()
    {
        // externally loaded templates set this parameter so that template
        // resources may be placed in the same folder as the template.
        if ($this->getParameter('template_path') !== null) {
            $path = rtrim($this->getParameter('template_path'), '/\\');
            if (file_exists($path . DIRECTORY_SEPARATOR . $this->source)) {
                return $path . DIRECTORY_SEPARATOR . $this->source;
            }
        }

        // counter a BC break that we introduced in 2.0 stable; we removed the notion of global assets
        // to be able to provide composer integration
        // TODO: remove in version 3.0
        if (strpos($this->source, 'templates/') !== 0) {
            $this->source = 'templates/abstract/' . $this->source;
            trigger_error(
                'Using shared assets in a template is deprecated and will be removed in version 3.0',
                E_USER_DEPRECATED
            );
        }

        // check whether the file exists in the phpDocumentor project directory
        if (file_exists(__DIR__.'/../../../'.$this->source)) {
            return __DIR__ . '/../../../' .$this->source;
        }

        // in case of a composer installation
        if (file_exists(__DIR__ . '/../../../../templates')) {
            return __DIR__ . '/../../../../' . $this->source;
        }

        // TODO: replace this as it breaks the component stuff
        // we should ditch the idea of a global set of files to fetch and have
        // a variable / injection for the global templates folder and inject
        // that here.
        $file = __DIR__.'/../../../data/'.$this->source;

        if (!file_exists($file)) {
            throw new Exception('The source path does not exist: ' . $file);
        }

        return $file;
    }

    /**
     * Filename of the resulting artifact relative to the root.
     *
     * If the query results in a set of artifacts (multiple nodes / array);
     * then this string must contain an identifying variable as returned by the
     * writer.
     *
     * @param string $artifact Name of artifact to generate; usually a filepath.
     *
     * @return void
     */
    public function setArtifact($artifact)
    {
        $this->artifact = $artifact;
    }

    /**
     * Returns the name of the artifact.
     *
     * @return string
     */
    public function getArtifact()
    {
        return $this->artifact;
    }

    /**
     * Sets an array of parameters (key => value).
     *
     * @param Parameter[] $parameters Associative multidimensional array containing
     *     parameters for the Writer.
     *
     * @return void
     */
    public function setParameters(array $parameters)
    {
        $this->parameters = $parameters;
    }

    /**
     * Returns all parameters for this transformation.
     *
     * @return Parameter[]
     */
    public function getParameters()
    {
        return $this->parameters;
    }

    /**
     * Returns a specific parameter, or $default if none exists.
     *
     * @param string $name Name of the parameter to return.
     *
     * @return Parameter
     */
    public function getParameter($name)
    {
        /** @var Parameter $parameter */
        foreach ($this->parameters as $parameter) {
            if ($parameter->getKey() == $name) {
                return $parameter;
            }
        }

        return null;
    }

    /**
     * Returns a specific parameter, or $default if none exists.
     *
     * @param string $name Name of the parameter to return.
     *
     * @return Parameter
     */
    public function getParametersWithKey($name)
    {
        $parameters = array();

        /** @var Parameter $parameter */
        foreach ($this->parameters as $parameter) {
            if ($parameter->getKey() == $name) {
                $parameters[] = $parameter;
            }
        }

        return $parameters;
    }

    /**
     * Sets the transformer on this transformation.
     *
     * @param \phpDocumentor\Transformer\Transformer $transformer
     */
    public function setTransformer($transformer)
    {
        $this->transformer = $transformer;
    }

    /**
     * Returns the transformer for this transformation.
     *
     * @return \phpDocumentor\Transformer\Transformer
     */
    public function getTransformer()
    {
        return $this->transformer;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer;

use Cilex\Application;
use Cilex\ServiceProviderInterface;
use phpDocumentor\Compiler\Compiler;
use phpDocumentor\Compiler\Linker\Linker;
use phpDocumentor\Compiler\Pass\Debug;
use phpDocumentor\Compiler\Pass\ElementsIndexBuilder;
use phpDocumentor\Compiler\Pass\NamespaceTreeBuilder;
use phpDocumentor\Compiler\Pass\PackageTreeBuilder;
use phpDocumentor\Compiler\Pass\MarkerFromTagsExtractor;
use phpDocumentor\Transformer\Command\Project\TransformCommand;
use phpDocumentor\Transformer\Command\Template\ListCommand;

/**
 * This provider is responsible for registering the transformer component with the given Application.
 */
class ServiceProvider extends \stdClass implements ServiceProviderInterface
{
    /**
     * Registers services on the given app.
     *
     * @param Application $app An Application instance.
     *
     * @throws Exception\MissingDependencyException if the application does not have a descriptor.builder service.
     * @throws Exception\MissingDependencyException if the application does not have a serializer service.
     */
    public function register(Application $app)
    {
        if (!isset($app['descriptor.builder'])) {
            throw new Exception\MissingDependencyException(
                'The builder object that is used to construct the ProjectDescriptor is missing'
            );
        }
        if (!isset($app['serializer'])) {
            throw new Exception\MissingDependencyException(
                'The serializer object that is used to read the template configuration with is missing'
            );
        }

        $templateDir = __DIR__ . '/../../../data/templates';
        // vendored installation
        if (file_exists(__DIR__ . '/../../../../templates')) {
            $templateDir = __DIR__ . '/../../../../templates';
        }

        // parameters
        $app['transformer.template.location'] = $templateDir;
        $app['linker.substitutions'] = array(
            'phpDocumentor\Descriptor\ProjectDescriptor'      => array('files'),
            'phpDocumentor\Descriptor\FileDescriptor'         => array('tags', 'classes', 'interfaces', 'traits'),
            'phpDocumentor\Descriptor\ClassDescriptor'        => array(
                'tags',
                'parent',
                'interfaces',
                'constants',
                'properties',
                'methods',
                'usedTraits',
            ),
            'phpDocumentor\Descriptor\InterfaceDescriptor'    => array(
                'tags',
                'parent',
                'constants',
                'methods',
            ),
            'phpDocumentor\Descriptor\TraitDescriptor'        => array(
                'tags',
                'properties',
                'methods',
                'usedTraits',
            ),
            'phpDocumentor\Descriptor\MethodDescriptor'       => array('tags', 'arguments'),
            'phpDocumentor\Descriptor\ArgumentDescriptor'     => array('types'),
            'phpDocumentor\Descriptor\PropertyDescriptor'     => array('tags', 'types'),
            'phpDocumentor\Descriptor\ConstantDescriptor'     => array('tags', 'types'),
            'phpDocumentor\Descriptor\Tag\ParamDescriptor'    => array('types'),
            'phpDocumentor\Descriptor\Tag\ReturnDescriptor'   => array('types'),
            'phpDocumentor\Descriptor\Tag\SeeDescriptor'      => array('reference'),
        );

        // services
        $app['compiler'] = $app->share(
            function ($container) {
                $compiler = new Compiler();
                $compiler->insert(new ElementsIndexBuilder(), ElementsIndexBuilder::COMPILER_PRIORITY);
                $compiler->insert(new MarkerFromTagsExtractor(), MarkerFromTagsExtractor::COMPILER_PRIORITY);
                $compiler->insert(new PackageTreeBuilder(), PackageTreeBuilder::COMPILER_PRIORITY);
                $compiler->insert(new NamespaceTreeBuilder(), NamespaceTreeBuilder::COMPILER_PRIORITY);
                $compiler->insert($container['linker'], Linker::COMPILER_PRIORITY);
                $compiler->insert($container['transformer'], Transformer::COMPILER_PRIORITY);
                $compiler->insert(
                    new Debug($container['monolog'], $container['descriptor.analyzer']),
                    Debug::COMPILER_PRIORITY
                );

                return $compiler;
            }
        );

        $app['linker'] = $app->share(
            function ($app) {
                return new Linker($app['linker.substitutions']);
            }
        );

        $app['transformer.behaviour.collection'] = $app->share(
            function () {
                return new Behaviour\Collection();
            }
        );


        $app['transformer.routing.standard'] = $app->share(
            function () {
                return new Router\StandardRouter();
            }
        );
        $app['transformer.routing.external'] = $app->share(
            function ($container) {
                return new Router\ExternalRouter($container['config']);
            }
        );

        $app['transformer.routing.queue'] = $app->share(
            function ($container) {
                $queue = new Router\Queue();

                // TODO: load from app configuration instead of hardcoded
                $queue->insert($container['transformer.routing.external'], 10500);
                $queue->insert($container['transformer.routing.standard'], 10000);

                return $queue;
            }
        );

        $app['transformer.writer.collection'] = $app->share(
            function ($container) {
                return new Writer\Collection($container['transformer.routing.queue']);
            }
        );

        $app['transformer.template.collection'] = $app->share(
            function ($container) {
                return new Template\Collection(
                    $container['transformer.template.location'],
                    $container['serializer']
                );
            }
        );

        $app['transformer'] = $app->share(
            function ($container) {
                $transformer = new Transformer(
                    $container['transformer.template.collection'],
                    $container['transformer.writer.collection']
                );
                $transformer->setBehaviours($container['transformer.behaviour.collection']);

                return $transformer;
            }
        );

        $app->command(new TransformCommand($app['descriptor.builder'], $app['transformer'], $app['compiler']));
        $app->command(new ListCommand());
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer;

use JMS\Serializer\Annotation as Serializer;
use phpDocumentor\Transformer\Template\Parameter;

/**
 * Model representing a template.
 *
 * @Serializer\XmlRoot("template")
 */
class Template implements \ArrayAccess, \Countable, \Iterator
{
    /**
     * @Serializer\Type("string")
     * @var string Name for this template
     */
    protected $name = null;

    /**
     * @Serializer\Type("string")
     * @var string
     */
    protected $author = '';

    /**
     * @Serializer\Type("string")
     * @var string
     */
    protected $version = '';

    /**
     * @Serializer\Type("string")
     * @var string
     */
    protected $copyright = '';

    /**
     * @Serializer\Type("string")
     * @var string
     */
    protected $description = '';

    /**
     * @Serializer\XmlList(entry = "transformation")
     * @Serializer\Type("array<phpDocumentor\Transformer\Transformation>")
     * @var Transformation[]
     */
    protected $transformations = array();

    /**
     * @Serializer\XmlList(entry = "parameter")
     * @Serializer\Type("array<phpDocumentor\Transformer\Template\Parameter>")
     * @var Parameter[]
     */
    protected $parameters = array();

    /**
     * Initializes this object with a name and optionally with contents.
     *
     * @param string $name Name for this template.
     */
    public function __construct($name)
    {
        $this->name = $name;
    }

    /**
     * Name for this template.
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * The name of the author of this template (optionally including mail
     * address).
     *
     * @param string $author Name of the author optionally including mail address
     *  between angle brackets.
     *
     * @return void
     */
    public function setAuthor($author)
    {
        $this->author = $author;
    }

    /**
     * Returns the name and/or mail address of the author.
     *
     * @return string
     */
    public function getAuthor()
    {
        return $this->author;
    }

    /**
     * Sets the copyright string for this template.
     *
     * @param string $copyright Free-form copyright notice.
     *
     * @return void
     */
    public function setCopyright($copyright)
    {
        $this->copyright = $copyright;
    }

    /**
     * Returns the copyright string for this template.
     *
     * @return string
     */
    public function getCopyright()
    {
        return $this->copyright;
    }

    /**
     * Sets the version number for this template.
     *
     * @param string $version Semantic version number in this format: 1.0.0
     *
     * @throws \InvalidArgumentException if the version number is invalid
     * @return void
     */
    public function setVersion($version)
    {
        if (!preg_match('/^\d+\.\d+\.\d+$/', $version)) {
            throw new \InvalidArgumentException(
                'Version number is invalid; ' . $version . ' does not match '
                . 'x.x.x (where x is a number)'
            );
        }
        $this->version = $version;
    }

    /**
     * Returns the version number for this template.
     *
     * @return string
     */
    public function getVersion()
    {
        return $this->version;
    }

    /**
     * Sets the description for this template.
     *
     * @param string $description An unconstrained text field where the user can provide additional information
     *     regarding details of the template.
     *
     * @return void
     */
    public function setDescription($description)
    {
        $this->description = $description;
    }

    /**
     * Returns the description for this template.
     *
     * @return string
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     * Sets a transformation at the given offset.
     *
     * @param integer|string $offset The offset to place the value at.
     * @param Transformation $value  The transformation to add to this template.
     *
     * @throws \InvalidArgumentException if an invalid item was received
     * @return void
     */
    public function offsetSet($offset, $value)
    {
        if (!$value instanceof Transformation) {
            throw new \InvalidArgumentException(
                '\phpDocumentor\Transformer\Template may only contain items of '
                . 'type \phpDocumentor\Transformer\Transformation'
            );
        }

        $this->transformations[] = $value;
    }

    /**
     * Gets the transformation at the given offset.
     *
     * @param integer|string $offset The offset to retrieve from.
     *
     * @return Transformation
     */
    public function offsetGet($offset)
    {
        return $this->transformations[$offset];
    }

    /**
     * Offset to unset.
     *
     * @param integer|string $offset Index of item to unset.
     *
     * @link http://php.net/manual/en/arrayaccess.offsetunset.php
     *
     * @return void
     */
    public function offsetUnset($offset)
    {
        unset($this->transformations[$offset]);
    }

    /**
     * Whether a offset exists.
     *
     * @param mixed $offset An offset to check for.
     *
     * @link http://php.net/manual/en/arrayaccess.offsetexists.php
     *
     * @return boolean Returns true on success or false on failure.
     */
    public function offsetExists($offset)
    {
        return isset($this->transformations[$offset]);
    }

    /**
     * Count the number of transformations.
     *
     * @link http://php.net/manual/en/countable.count.php
     *
     * @return int The count as an integer.
     */
    public function count()
    {
        return count($this->transformations);
    }

    /**
     * Rewind the Iterator to the first element
     *
     * @link http://php.net/manual/en/iterator.rewind.php
     *
     * @return void
     */
    public function rewind()
    {
        reset($this->transformations);
    }

    /**
     * Checks if current position is valid.
     *
     * @link http://php.net/manual/en/iterator.valid.php
     *
     * @return boolean Returns true on success or false on failure.
     */
    public function valid()
    {
        return (current($this->transformations) === false)
            ? false
            : true;
    }

    /**
     * Return the key of the current element.
     *
     * @link http://php.net/manual/en/iterator.key.php
     *
     * @return int|string scalar on success, integer 0 on failure.
     */
    public function key()
    {
        key($this->transformations);
    }

    /**
     * Move forward to next element.
     *
     * @link http://php.net/manual/en/iterator.next.php
     *
     * @return void Any returned value is ignored.
     */
    public function next()
    {
        next($this->transformations);
    }

    /**
     * Return the current element.
     *
     * @link http://php.net/manual/en/iterator.current.php
     *
     * @return Transformation
     */
    public function current()
    {
        return current($this->transformations);
    }

    /**
     * Returns the parameters associated with this template.
     *
     * @return Parameter[]
     */
    public function getParameters()
    {
        return $this->parameters;
    }

    /**
     * Sets a new parameter in the collection.
     *
     * @param string|integer $key
     * @param Parameter      $value
     *
     * @return void
     */
    public function setParameter($key, $value)
    {
        $this->parameters[$key] = $value;
    }

    /**
     * Pushes the parameters of this template into the transformations.
     *
     * @return void
     */
    public function propagateParameters()
    {
        foreach ($this->transformations as $transformation) {
            $transformation->setParameters(array_merge($transformation->getParameters(), $this->getParameters()));
        }
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Template;

use JMS\Serializer\Serializer;
use phpDocumentor\Transformer\Template;
use phpDocumentor\Transformer\Transformation;

/**
 * Contains a collection of Templates that may be queried.
 */
class Collection extends \ArrayObject
{
    protected $templatesPath = 'data/templates';

    /** @var Serializer $serializer */
    protected $serializer;

    public function __construct($templatesPath, Serializer $serializer)
    {
        $this->templatesPath = $templatesPath;
        $this->serializer    = $serializer;
    }

    /**
     * Returns a list of all transformations contained in the templates of this collection.
     *
     * @return Transformation[]
     */
    public function getTransformations()
    {
        $result = array();
        foreach ($this as $template) {
            foreach ($template as $transformation) {
                $result[] = $transformation;
            }
        }

        return $result;
    }

    /**
     * @param string $nameOrPath
     *
     * @throws \InvalidArgumentException
     *
     * @return Template
     */
    public function load($nameOrPath)
    {
        $path = null;

        // if this is an absolute path; load the template into the configuration
        // Please note that this _could_ override an existing template when
        // you have a template in a subfolder with the same name as a default
        // template; we have left this in on purpose to allow people to override
        // templates should they choose to.
        $configPath = rtrim($nameOrPath, DIRECTORY_SEPARATOR) . '/template.xml';
        if (file_exists($configPath) && is_readable($configPath)) {
            $path = rtrim($nameOrPath, DIRECTORY_SEPARATOR);
            $templateNamePart = basename($path);
            $cachePath = rtrim($this->getTemplatesPath(), '/\\') . DIRECTORY_SEPARATOR . $templateNamePart;

            // move the files to a cache location and then change the path
            // variable to match the new location
            $this->copyRecursive($path, $cachePath);
            $path = $cachePath;

            // transform all directory separators to underscores and lowercase
            $nameOrPath = strtolower(
                str_replace(DIRECTORY_SEPARATOR, '_', rtrim($nameOrPath, DIRECTORY_SEPARATOR))
            );
        }

        // if we load a default template
        if ($path === null) {
            $path = rtrim($this->getTemplatesPath(), '/\\') . DIRECTORY_SEPARATOR . $nameOrPath;
        }

        if (!file_exists($path) || !is_readable($path)) {
            throw new \InvalidArgumentException(
                'The given template ' . $nameOrPath.' could not be found or is not readable'
            );
        }

        /** @var Template $template  */
        $template = $this->getSerializer()->deserialize(
            file_get_contents($path . DIRECTORY_SEPARATOR . 'template.xml'),
            'phpDocumentor\Transformer\Template',
            'xml'
        );
        $template->propagateParameters();

        $this[$template->getName()] = $template;
    }

    public function getTemplatesPath()
    {
        return $this->templatesPath;
    }

    /**
     * @return \JMS\Serializer\Serializer
     */
    public function getSerializer()
    {
        return $this->serializer;
    }

    /**
     * Copies a file or folder recursively to another location.
     *
     * @param string $src The source location to copy
     * @param string $dst The destination location to copy to
     *
     * @throws \Exception if $src does not exist or $dst is not writable
     *
     * @return void
     */
    public function copyRecursive($src, $dst)
    {
        // if $src is a normal file we can do a regular copy action
        if (is_file($src)) {
            copy($src, $dst);

            return;
        }

        $dir = opendir($src);
        if (!$dir) {
            throw new \Exception('Unable to locate path "' . $src . '"');
        }

        // check if the folder exists, otherwise create it
        if ((!file_exists($dst)) && (false === mkdir($dst))) {
            throw new \Exception('Unable to create folder "' . $dst . '"');
        }

        while (false !== ($file = readdir($dir))) {
            if (($file != '.') && ($file != '..')) {
                if (is_dir($src . DIRECTORY_SEPARATOR . $file)) {
                    $this->copyRecursive($src . DIRECTORY_SEPARATOR . $file, $dst . DIRECTORY_SEPARATOR . $file);
                } else {
                    copy($src . DIRECTORY_SEPARATOR . $file, $dst . DIRECTORY_SEPARATOR . $file);
                }
            }
        }
        closedir($dir);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Template;

use JMS\Serializer\Annotation as Serializer;

/**
 * Model representing a parameter in a template or transformation.
 *
 * @Serializer\XmlRoot("parameter")
 */
class Parameter
{
    /**
     * @Serializer\Type("string")
     * @var string
     * @Serializer\XmlAttribute
     */
    protected $key;

    /**
     * @Serializer\Type("string")
     * @var string
     * @Serializer\XmlValue
     */
    protected $value;

    /**
     * @return string
     */
    public function getKey()
    {
        return $this->key;
    }

    /**
     * @return string
     */
    public function getValue()
    {
        return $this->value;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Exception;

/**
 * This exception is thrown when a required dependency is not included.
 */
class MissingDependencyException extends \RuntimeException
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Exception;

use phpDocumentor\Transformer\Exception;

/**
 * Exception thrown when a template attempts to use a writer that is unknown to phpDocumentor.
 */
class UnknownWriter extends Exception
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Writer;

/**
 * Collection object for a set of Writers.
 */

use phpDocumentor\Transformer\Router\Queue;

class Collection extends \ArrayObject
{
    protected $routers;

    public function __construct(Queue $routers)
    {
        $this->routers = $routers;

        parent::__construct();
    }

    /**
     * Registers a writer with a given name.
     *
     * @param string         $index a Writer's name, must be at least 3
     *     characters, alphanumeric and/or contain one or more hyphens,
     *     underscores and forward slashes.
     * @param WriterAbstract $newval The Writer object to register to this name.
     *
     * @throws \InvalidArgumentException if either of the above restrictions is
     *     not met.
     *
     * @return void
     */
    public function offsetSet($index, $newval)
    {
        if (!$newval instanceof WriterAbstract) {
            throw new \InvalidArgumentException(
                'The Writer Collection may only contain objects descending from WriterAbstract'
            );
        }

        if (!preg_match('/^[a-zA-Z0-9\-\_\/]{3,}$/', $index)) {
            throw new \InvalidArgumentException(
                'The name of a Writer may only contain alphanumeric characters, one or more hyphens, underscores and '
                .'forward slashes and must be at least three characters wide'
            );
        }

        // if the writer supports routes, provide them with the router queue
        if ($newval instanceof Routable) {
            $newval->setRouters($this->routers);
        }

        parent::offsetSet($index, $newval);
    }

    /**
     * Retrieves a writer from the collection.
     *
     * @param string $index the name of the writer to retrieve.
     *
     * @throws \InvalidArgumentException if the writer is not in the collection.
     *
     * @return WriterAbstract
     */
    public function offsetGet($index)
    {
        if (!$this->offsetExists($index)) {
            throw new \InvalidArgumentException('Writer "' . $index .'" does not exist');
        }

        return parent::offsetGet($index);
    }

    /**
     * Iterates over each writer in this collection and checks its requirements.
     *
     * @throws Exception\RequirementMissing if a requirement of a writer is missing.
     *
     * @return void
     */
    public function checkRequirements()
    {
        /** @var WriterAbstract $writer */
        foreach ($this as $writer) {
            $writer->checkRequirements();
        }
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Writer;

use phpDocumentor\Descriptor\ProjectDescriptor;
use phpDocumentor\Transformer\Transformation;

/**
 * Base class for the actual transformation business logic (writers).
 */
abstract class WriterAbstract
{
    /**
     * This method verifies whether PHP has all requirements needed to run this writer.
     *
     * If one of the requirements is missing for this Writer then an exception of type RequirementMissing
     * should be thrown; this indicates to the calling process that this writer will not function.
     *
     * @throws Exception\RequirementMissing when a requirements is missing stating which one.
     *
     * @return void
     */
    public function checkRequirements()
    {
        // empty body since most writers do not have requirements
    }

    /**
     * Abstract definition of the transformation method.
     *
     * @param ProjectDescriptor $project        Document containing the structure.
     * @param Transformation    $transformation Transformation to execute.
     *
     * @return void
     */
    abstract public function transform(ProjectDescriptor $project, Transformation $transformation);
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Writer;

use phpDocumentor\Translator;

/**
 * All writers that have items that should be translated should implement this interface
 */
interface Translatable
{
    /**
     * Returns an instance of the object responsible for translating content.
     *
     * @return Translator
     */
    public function getTranslator();

    /**
     * Sets a new object capable of translating strings on this writer.
     *
     * @param Translator $translator
     *
     * @return void
     */
    public function setTranslator(Translator $translator);
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Writer\Exception;

/**
 * This exception should be thrown by a Writer when it is missing one of its requirements.
 */
class RequirementMissing extends \RuntimeException
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Writer;

use phpDocumentor\Transformer\Router\Queue;

/**
 * Public interface for writers who use the routing system to determine relative URLs for Descriptors.
 */
interface Routable
{
    /**
     * Sets the routers that can be used to determine the path of links.
     *
     * @param Queue $routers
     *
     * @return void
     */
    public function setRouters(Queue $routers);
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Transformer\Behaviour;

use phpDocumentor\Descriptor\ProjectDescriptor;

/**
 * Collection object for a set of Behaviours.
 */
class Collection extends BehaviourAbstract implements \Countable
{
    /** @var BehaviourAbstract[] */
    protected $behaviours = array();

    /**
     * Initializes the list of Behaviours to execute each request.
     *
     * @param BehaviourAbstract[] $behaviours  List of behaviours to process.
     */
    public function __construct(array $behaviours = array())
    {
        $this->behaviours  = $behaviours;
    }

    /**
     * Adds a behaviour to a collection
     *
     * @param BehaviourAbstract $behaviour Behaviour to add to the collection.
     *
     * @return void
     */
    public function addBehaviour(BehaviourAbstract $behaviour)
    {
        $this->behaviours[] = $behaviour;
    }

    /**
     * Removes a behaviour from the collection
     *
     * @param BehaviourAbstract $behaviour Behaviour to remove from the collection.
     *
     * @return void
     */
    public function removeBehaviour(BehaviourAbstract $behaviour)
    {
        foreach ($this->behaviours as $key => $thisBehaviour) {
            if ($behaviour == $thisBehaviour) {
                unset($this->behaviours[$key]);
            }
        }
    }

    /**
     * Executes the behaviour on the given object model,
     *
     * @param ProjectDescriptor $project.
     *
     * @return ProjectDescriptor
     */
    public function process(ProjectDescriptor $project)
    {
        foreach ($this->behaviours as $behaviour) {
            $project = $behaviour->process($project);
        }

        return $project;
    }

    /**
     * Count the number of behaviours in this collection.
     *
     * @return integer
     */
    public function count()
    {
        return count($this->behaviours);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Transformer\Behaviour;

use phpDocumentor\Descriptor\ProjectDescriptor;
use phpDocumentor\Transformer\Transformer;

/**
 * Collection object for a set of Behaviours.
 */
abstract class BehaviourAbstract
{
    /** @var Transformer $transformer */
    protected $transformer = null;

    /**
     * Executes the behaviour on the given dataset,
     *
     * @param ProjectDescriptor $project document containing the source structure.
     *
     * @return ProjectDescriptor
     */
    abstract public function process(ProjectDescriptor $project);

    /**
     * Sets the transformer used for this behaviour.
     *
     * @param Transformer $transformer Transformer responsible for output.
     *
     * @return void
     */
    public function setTransformer(Transformer $transformer)
    {
        $this->transformer = $transformer;
    }

    /**
     * Returns the transformer that hosts this behaviour.
     *
     * @return Transformer
     */
    public function getTransformer()
    {
        return $this->transformer;
    }
}
<?php

/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Fabien Potencier <fabien@symfony.com>
 * @author    Gordon Franke <info@nevalon.de>
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor;

use Symfony\Component\Finder\Finder;

/**
 * The Compiler class compiles the phpDocumentor utility.
 *
 * It is inspired by Goutte's Phar Compiler
 * https://github.com/fabpot/Goutte/blob/master/src/Goutte/Compiler.php
 */
class PharCompiler
{
    /**
     * Compiles the source code into a PHAR file with the given name,
     *
     * @param string $pharFile
     *
     * @see getFiles() for the file selection process.
     *
     * @return void
     */
    public function compile($pharFile = 'phpDocumentor.phar')
    {
        $this->removeExistingPharArchive($pharFile);

        $phar = $this->initializePharArchive($pharFile);

        $phar->startBuffering();
        $this->addFilesToPharArchive($this->getFiles(), $phar);
        $this->addStubsToPharArchive($phar);
        $phar->stopBuffering();

        echo '>> Finished creating phar archive' . PHP_EOL;

        unset($phar);
    }

    /**
     * Detects whether the given PHAR file already exists and removes it if so.
     *
     * @param string $pharFile
     *
     * @return void
     */
    protected function removeExistingPharArchive($pharFile)
    {
        echo '>> Checking whether a phar file has been left from a previous run'
            . PHP_EOL;

        if (file_exists($pharFile)) {
            echo '>>   Removing previous phar' . PHP_EOL;
            unlink($pharFile);
        }
    }

    /**
     * Initializes a new PHAR archive with the given name.
     *
     * The PHAR archive's Signature's algorithm is set to SHA1.
     *
     * @param string $pharFile
     *
     * @return \Phar
     */
    protected function initializePharArchive($pharFile)
    {
        echo '>> Initializing new phar archive' . PHP_EOL;
        $phar = new \Phar($pharFile, 0, 'phpDocumentor');
        $phar->setSignatureAlgorithm(\Phar::SHA1);

        return $phar;
    }

    /**
     * Retrieves an array containing all filenames that are to be included.
     *
     * The following files are added:
     *
     * - LICENCE
     * - README.md
     * - bin/*
     * - data/* (excluding the output folder)
     * - src/*
     * - vendor/*
     *
     * @return string[]
     */
    protected function getFiles()
    {
        $files = array('LICENSE', 'README.md', 'VERSION');

        $finder = new Finder();
        $iterator = $finder->files()
            ->in(array('bin', 'data', 'src', 'vendor'))
            ->notName('*.rst')
            ->notName('*.md')
            ->exclude(
                array(
                    'output',
                    'behat',
                    'cilex/cilex/tests',
                    'nikic/php-parser/doc',
                    'nikic/php-parser/test',
                    'nikic/php-parser/test_old',
                    'phpdocumentor/fileset/tests',
                    'phpdocumentor/graphviz/tests',
                    'phpdocumentor/reflection-docblock/tests',
                    'pimple/pimple/tests',
                    'twig/twig/test',
                )
            );

        return array_merge($files, iterator_to_array($iterator));
    }

    /**
     * Processes the given array of filenames to be added to the PHAR archive.
     *
     * @param string[] $files
     * @param \Phar    $phar
     *
     * @return void
     */
    protected function addFilesToPharArchive(array $files, \Phar $phar)
    {
        echo '>> Found ' . count($files) . ' files to add to archive' . PHP_EOL;

        $counter = 0;
        foreach ($files as $file) {
            echo '.';
            $counter++;
            if ($counter % 70 == 0) {
                echo ' [' . $counter . '/' . count($files) . ']' . PHP_EOL;
            }
            $this->addFileToPharArchive($file, $phar);
        }
        echo PHP_EOL;
        echo '>> Finished adding files to archive' . PHP_EOL;
    }

    /**
     * Adds the given file to the PHAR archive,
     *
     * Before adding files to the archive they are being converted to relative paths.
     *
     * @param string $file
     * @param \Phar  $phar
     *
     * @return void
     */
    protected function addFileToPharArchive($file, \Phar $phar)
    {
        $path = str_replace(__DIR__ . '/', '', $file);
        $file_contents = file_get_contents($file);
        $file_contents = str_replace('', '', $file_contents);
        $phar->addFromString($path, $file_contents);
    }

    /**
     * Adds the stubs for the CLI and Web interaction to the PHAR archive.
     *
     * @param \Phar $phar
     *
     * @see getCliStub() for the Stub for Command Line Interaction
     * @see getWebStub() for the Stub for Web Interaction
     *
     * @return void
     */
    protected function addStubsToPharArchive($phar)
    {
        $phar['_cli_stub.php'] = $this->getCliStub();
        $phar['_web_stub.php'] = $this->getWebStub();
        $phar->setDefaultStub('_cli_stub.php', '_web_stub.php');
    }

    /**
     * Adds a stub file that initiates the command line interaction.
     *
     * @return string
     */
    protected function getCliStub()
    {
        return <<<'PHP'

<?php
require_once __DIR__.'/bin/phpdoc.php'; __HALT_COMPILER();
PHP;
    }

    /**
     * Adds a stub file that initiates the web interaction.
     *
     * @return string
     */
    protected function getWebStub()
    {
        return <<<'PHP'

"<?php
throw new \LogicException('This PHAR file can only be used from the CLI.');
__HALT_COMPILER();
PHP;
    }

    /**
     * Returns a license file-level DocBlock for use in the Stubs.
     *
     * @return string
     */
    protected function getLicense()
    {
        return '
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */';
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core;

/**
 * Exception object for the Core Plugin.
 */
class Exception extends \Exception
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

/** @noinspection SpellCheckingInspection */
return array(
    'PPC:ERR-50000' => 'Es wurde keine Zusammenfassung in dieser Datei gefunden',
    'PPC:ERR-50001' => 'Es ist nur ein @package Tag erlaubt',
    'PPC:ERR-50002' => 'Es ist nur ein @subpackage Tag erlaubt',
    'PPC:ERR-50004' => 'Es kann kein @subpackage vorkommen, ohne Angabe eines @package Tags',
    'PPC:ERR-50005' => 'Keine Zusammenfassung für Klasse %s',
    'PPC:ERR-50006' => 'Veraltetes Tag "%s" in %s gefunden',
    'PPC:ERR-50007' => 'Keine Zusammenfassung für Property %s',
    'PPC:ERR-50008' => 'Keine Zusammenfassung für Methode %s',
    'PPC:ERR-50009' => 'Keine Zusammenfassung für Interface %s',
    'PPC:ERR-50010' => 'Keine Zusammenfassung für Trait %s',
    'PPC:ERR-50011' => 'Keine Zusammenfassung für Funktion %s',
    'PPC:ERR-50013' => 'Parameter %s konnte nicht in %s gefunden werden',
    'PPC:ERR-50014' => 'Der Name des Arguments %s stimmt nicht mit dem Namen %s aus dem DocBlock in %s überein',
    'PPC:ERR-50015' => 'Argument %s fehlt im Docblock von %s',
    'PPC:ERR-50016' => 'Der Type-Hint von dem Argument ist für die Typ-Definition '
        . 'des @param Tags mit dem Argument %s in %s nicht korrekt',
    'PPC:ERR-50017' => 'Der Typ für das %s Tag in %s ist "type"; ist das nicht ein IDE default?',
    'PPC:ERR-50018' => 'Der Typ für das param Tag %s in %s ist entweder "type" oder "unknown"; ist das nicht ein '
        . 'IDE default?',
    'PPC:ERR-50020' => 'Benötigtes Tag "%s" wurde nicht in %s gefunden',
);
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

return array(
    'PPC:ERR-50000' => 'No summary was found for this file',
    'PPC:ERR-50001' => 'Only one @package tag is allowed',
    'PPC:ERR-50002' => 'Only one @subpackage tag is allowed',
    'PPC:ERR-50004' => 'Cannot have a @subpackage when a @package tag is not present',
    'PPC:ERR-50005' => 'No summary for class %s',
    'PPC:ERR-50006' => 'Found deprecated tag "%s" in %s',
    'PPC:ERR-50007' => 'No summary for property %s',
    'PPC:ERR-50008' => 'No summary for method %s',
    'PPC:ERR-50009' => 'No summary for interface %s',
    'PPC:ERR-50010' => 'No summary for trait %s',
    'PPC:ERR-50011' => 'No summary for function %s',
    'PPC:ERR-50013' => 'Parameter %s could not be found in %s',
    'PPC:ERR-50014' => 'Name of argument %s does not match with the DocBlock\'s name %s in %s',
    'PPC:ERR-50015' => 'Argument %s is missing from the Docblock of %s',
    'PPC:ERR-50016' => 'The type hint of the argument is incorrect for the type definition '
        . 'of the @param tag with argument %s in %s',
    'PPC:ERR-50017' => 'The type for the %s tag in %s is "type"; isn\'t this an IDE default?',
    'PPC:ERR-50018' => 'The type for the param tag %s in %s is either "type" or "unknown"; isn\'t this an IDE default?',
    'PPC:ERR-50020' => 'Not found required tag "%s" in %s',
);
<?php
///**
// * phpDocumentor
// *
// * PHP Version 5.3
// *
// * @author    Mike van Riel <mike.vanriel@naenius.com>
// * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
// * @license   http://www.opensource.org/licenses/mit-license.php MIT
// * @link      http://phpdoc.org
// */
//namespace phpDocumentor\Plugin\Core;
//
//use phpDocumentor\Plugin\ListenerAbstract;
//use phpDocumentor\Transformer\Event\PreTransformationEvent;
//use phpDocumentor\Reflection\Event\PostDocBlockExtractionEvent;
//use phpDocumentor\Reflection\Event\ExportDocBlockTagEvent;
//
///**
// * Listener for the Core Plugin.
// */
//class Listener extends ListenerAbstract
//{
//    /**
//     * Applies all behaviours prior to transformation.
//     *
//     * @param PreTransformationEvent $data Event object containing the parameters.
//     *
//     * @phpdoc-event transformer.transform.pre
//     *
//     * @throws Exception if the event does not originate from the Transformer
//     *
//     * @return void
//     */
//    public function applyBehaviours($data)
//    {
////        if (!$data->getSubject() instanceof \phpDocumentor\Transformer\Transformer) {
////            throw new Exception(
////                'Unable to apply behaviours, the invoking object is not a '
////                . '\phpDocumentor\Transformer\Transformer'
////            );
////        }
////
////        $behaviour_objects = array(
////            new Transformer\Behaviour\GeneratePaths(),
////            new Transformer\Behaviour\Inherit(),
////            new Transformer\Behaviour\Tag\IgnoreTag(),
////            new Transformer\Behaviour\Tag\ReturnTag(),
////            new Transformer\Behaviour\Tag\ParamTag(),
////            new Transformer\Behaviour\Tag\VarTag(),
////            new Transformer\Behaviour\Tag\PropertyTag(),
////            new Transformer\Behaviour\Tag\MethodTag(),
////            new Transformer\Behaviour\Tag\UsesTag(),
////            new Transformer\Behaviour\Tag\CoversTag(),
////            new Transformer\Behaviour\Tag\AuthorTag(),
////            new Transformer\Behaviour\Tag\LicenseTag(),
////            new Transformer\Behaviour\Tag\InternalTag(),
////            new Transformer\Behaviour\AddLinkInformation(),
////        );
////
////        $behaviours = new \phpDocumentor\Transformer\Behaviour\Collection($data->getSubject(), $behaviour_objects);
////        $data->setSource($behaviours->process($data->getSource()));
//    }
//
//    /**
//     * Checks all phpDocumentor whether they match the given rules.
//     *
//     * @param PostDocBlockExtractionEvent $data Event object containing the
//     *     parameters.
//     *
//     * @phpdoc-event reflection.docblock-extraction.post
//     *
//     * @return void
//     */
//    public function validateDocBlocks($data)
//    {
//        /** @var \phpDocumentor\Reflection\BaseReflector $element  */
//        $element = $data->getSubject();
//
//        /** @var \phpDocumentor\Reflection\DocBlock $docblock  */
//        $docblock = $data->getDocblock();
//
//        // get the type of element
//        $type = substr(
//            get_class($element),
//            strrpos(get_class($element), '\\') + 1,
//            -9 // Reflector
//        );
//
//        // no docblock, or docblock should be ignored, so no reason to validate
//        if ($docblock && $docblock->hasTag('ignore')) {
//            return;
//        }
//
//        $validatorOptions = $this->loadConfiguration();
//
//        foreach (array('Deprecated', 'Required', $type) as $validator) {
//
//            // todo: move to a factory or builder class
//            $class = 'phpDocumentor\Plugin\Core\Parser\DocBlock\Validator\\'
//                . $validator.'Validator';
//
//            if (class_exists($class)) {
//                /** @var Parser\DocBlock\Validator\ValidatorAbstract $val */
//                $val = new $class(
//                    $this->plugin,
//                    $element->getName(),
//                    $docblock,
//                    $element
//                );
//
//                $val->setOptions($validatorOptions);
//                $val->isValid();
//            }
//        }
//    }
//
//    /**
//     * Load the configuration from the plugin.xml file
//     *
//     * @return array
//     */
//    protected function loadConfiguration()
//    {
//        $configOptions = $this->plugin->getOptions();
//        $validatorOptions = array();
//
//        foreach (array('deprecated', 'required') as $tag) {
//            $validatorOptions[$tag] = $this->loadConfigurationByElement($configOptions, $tag);
//        }
//
//        return $validatorOptions;
//    }
//
//    /**
//     * Load the configuration for given element (deprecated/required)
//     *
//     * @param array  $configOptions The configuration from the plugin.xml file
//     * @param string $configType    Required/Deprecated for the time being
//     *
//     * @return array
//     */
//    protected function loadConfigurationByElement($configOptions, $configType)
//    {
//        $validatorOptions = array();
//
//        if (isset($configOptions[$configType]->tag)) {
//
//            foreach ($configOptions[$configType]->tag as $tag) {
//                $tagName = (string)$tag['name'];
//
//                if (isset($tag->element)) {
//                    foreach ($tag->element as $type) {
//                        $typeName = (string)$type;
//                        $validatorOptions[$typeName][] = $tagName;
//                    }
//                } else {
//                    $validatorOptions['__ALL__'][] = $tagName;
//                }
//            }
//        }
//
//        return $validatorOptions;
//    }
//}
<?php
///**
// * File contains the
// * \phpDocumentor\Plugin\Core\Descriptor\Validator\RequiredValidator class.
// *
// * PHP Version 5
// *
// * @category   phpDocumentor
// * @package    Parser
// * @subpackage DocBlock_Validators
// * @author     Ben Selby <benmatselby@gmail.com>
// * @author     Mike van Riel <mike.vanriel@naenius.com>
// * @copyright  2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
// * @license    http://www.opensource.org/licenses/mit-license.php MIT
// * @link       http://phpdoc.org
// */
//
//namespace phpDocumentor\Plugin\Core\Descriptor\Validator;
//
///**
// * This class is responsible for validating which tags are required
// * as defined in /src/phpDocumentor/Plugin/Core/plugin.xml
// *
// * @category   phpDocumentor
// * @package    Parser
// * @subpackage DocBlock_Validators
// * @author     Ben Selby <benmatselby@gmail.com>
// * @author     Mike van Riel <mike.vanriel@naenius.com>
// * @copyright  2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
// * @license    http://www.opensource.org/licenses/mit-license.php MIT
// * @link       http://phpdoc.org
// */
//class RequiredValidator extends ValidatorAbstract
//{
//    /**
//     * Is the docblock valid based on the rules defined in plugin.xml
//     *
//     * <options>
//     *   <option name="deprecated">
//     *      <tag name="deprecated" />
//     *      <tag name="access" />
//     *   </option>
//     *   <option name="required">
//     *     <tag name="package">
//     *       <element>phpDocumentor\Reflection\FileReflector</element>
//     *       <element>phpDocumentor\Reflection\ClassReflector</element>
//     *     </tag>
//     *     <tag name="subpackage">
//     *       <element>phpDocumentor\Reflection\FileReflector</element>
//     *       <element>phpDocumentor\Reflection\ClassReflector</element>
//     *     </tag>
//     *   </option>
//     * </options>
//     *
//     * @see ValidatorAbstract::isValid()
//     *
//     * @return void
//     */
//    public function isValid()
//    {
//        $docType = get_class($this->source);
//        if (isset($this->options['required'][$docType])) {
//            $this->validateTags($docType);
//        } elseif (isset($this->options['required']['__ALL__'])) {
//            $this->validateTags('__ALL__');
//        }
//    }
//
//    /**
//     * Validate the tags based on the type of docblock being
//     * parsed etc
//     *
//     * @param string $key Access key to $this->options['required']
//     *
//     * @return void
//     */
//    protected function validateTags($key)
//    {
//        foreach ($this->options['required'][$key] as $tag) {
//            if (count($this->docblock->getTagsByName($tag)) == 0) {
//                $this->logParserError(
//                    'CRITICAL',
//                    'PPC:ERR-50020',
//                    $this->lineNumber,
//                    array($tag, $this->entityName)
//                );
//            }
//        }
//    }
//}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core\Descriptor\Validator\Constraints\Functions;

use phpDocumentor\Descriptor\MethodDescriptor;
use phpDocumentor\Descriptor\FunctionDescriptor;
use phpDocumentor\Descriptor\Tag\ReturnDescriptor;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;

class IsReturnTypeNotAnIdeDefaultValidator extends ConstraintValidator
{
    /**
     * @see \Symfony\Component\Validator\ConstraintValidatorInterface::validate()
     */
    public function validate($value, Constraint $constraint)
    {
        if (! $value instanceof MethodDescriptor
            && ! $value instanceof FunctionDescriptor
        ) {
            throw new ConstraintDefinitionException(
                'The Functions\IsReturnTypeNotAnIdeDefault validator may only be used on function or method objects'
            );
        }

        $return = $value->getResponse();
        if ($return instanceof ReturnDescriptor) {
            $types = $return->getTypes();
            if (is_array($types) && !empty($types) && preg_grep('/^.*type$/', $types)) {
                $this->context->addViolationAt(
                    'response',
                    $constraint->message,
                    array($return->getName(), $value->getFullyQualifiedStructuralElementName())
                );
            }
        }
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core\Descriptor\Validator\Constraints\Functions;

use phpDocumentor\Descriptor\MethodDescriptor;
use phpDocumentor\Descriptor\FunctionDescriptor;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;

class IsArgumentInDocBlockValidator extends ConstraintValidator
{
    /**
     * @see \Symfony\Component\Validator\ConstraintValidatorInterface::validate()
     */
    public function validate($value, Constraint $constraint)
    {
        if (! $value instanceof MethodDescriptor
            && ! $value instanceof FunctionDescriptor
        ) {
            throw new ConstraintDefinitionException(
                'The Functions\IsArgumentInDocBlock validator may only be used on function or method objects'
            );
        }

        $args = $value->getArguments();

        if ($args->count() > 0) {
            $params = $args->getAll();
            foreach ($params as $param) {
                $type = $param->getTypes();
                if (is_array($type) && empty($type)) {
                    $this->context->addViolationAt(
                        'argument',
                        $constraint->message,
                        array($param->getName(), $value->getFullyQualifiedStructuralElementName())
                    );
                }
            }
        }
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core\Descriptor\Validator\Constraints\Functions;

use phpDocumentor\Descriptor\MethodDescriptor;
use phpDocumentor\Descriptor\FunctionDescriptor;
use phpDocumentor\Descriptor\Tag\ParamDescriptor;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;

class IsParamTypeNotAnIdeDefaultValidator extends ConstraintValidator
{
    /**
     * @see \Symfony\Component\Validator\ConstraintValidatorInterface::validate()
     */
    public function validate($value, Constraint $constraint)
    {
        if (! $value instanceof MethodDescriptor
            && ! $value instanceof FunctionDescriptor
        ) {
            throw new ConstraintDefinitionException(
                'The Functions\IsParamTypeNotAnIdeDefault validator may only be used on function or method objects'
            );
        }

        $params = $value->getParam();
        foreach ($params as $param) {
            if ($param instanceof ParamDescriptor) {
                $types = $param->getTypes();
                if (is_array($types)
                    && !empty($types)
                    && (preg_grep('/^.*type$/', $types) || preg_grep('/^.*unknown$/', $types))
                ) {
                    $this->context->addViolationAt(
                        'params',
                        $constraint->message,
                        array($param->getVariableName(), $value->getFullyQualifiedStructuralElementName())
                    );
                }
            }
        }
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Plugin\Core\Descriptor\Validator\Constraints\Functions;

use Symfony\Component\Validator\Constraint;

/**
 * Validates whether a function has a default return type in the docblock present.
 *
 * @Annotation
 */
class IsReturnTypeNotAnIdeDefault extends Constraint
{
    /** @var string message phpDocumentor uses codes that are defined in a messages.[lang].php file in the a plugin. */
    public $message = 'PPC:ERR-50017';

    /**
     * Returns that the constraint can be put onto classes.
     *
     * @return string
     */
    public function getTargets()
    {
        return array(self::CLASS_CONSTRAINT);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Plugin\Core\Descriptor\Validator\Constraints\Functions;

use Symfony\Component\Validator\Constraint;

/**
 * Validates whether a function has a missing argument in the docblock.
 *
 * @Annotation
 */
class IsArgumentInDocBlock extends Constraint
{
    /** @var string message phpDocumentor uses codes that are defined in a messages.[lang].php file in the a plugin. */
    public $message = 'PPC:ERR-50015';

    /**
     * Returns that the constraint can be put onto classes.
     *
     * @return string
     */
    public function getTargets()
    {
        return array(self::CLASS_CONSTRAINT);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Plugin\Core\Descriptor\Validator\Constraints\Functions;

use Symfony\Component\Validator\Constraint;

/**
 * Validates whether a function has a default param type in the docblock present.
 *
 * @Annotation
 */
class IsParamTypeNotAnIdeDefault extends Constraint
{
    /** @var string message phpDocumentor uses codes that are defined in a messages.[lang].php file in the a plugin. */
    public $message = 'PPC:ERR-50018';

    /**
     * Returns that the constraint can be put onto classes.
     *
     * @return string
     */
    public function getTargets()
    {
        return array(self::CLASS_CONSTRAINT);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Plugin\Core\Descriptor\Validator\Constraints\Property;

use Symfony\Component\Validator\Constraint;

/**
 * Detects whether a property has a summary, or an @var tag with a description.
 *
 * @Annotation
 */
class HasSummary extends Constraint
{
    /** @var string message phpDocumentor uses codes that are defined in a messages.[lang].php file in the a plugin. */
    public $message = 'PPC:ERR-50007';

    /**
     * Returns that the constraint can be put onto classes.
     *
     * @return string
     */
    public function getTargets()
    {
        return array(self::CLASS_CONSTRAINT);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Plugin\Core\Descriptor\Validator\Constraints\Property;

use phpDocumentor\Descriptor\PropertyDescriptor;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;

/**
 * Validates whether a property has a summary, or an @var tag with a description.
 */
class HasSummaryValidator extends ConstraintValidator
{
    /**
     * Checks if the passed value is valid.
     *
     * @param PropertyDescriptor $value      The value that should be validated
     * @param Constraint         $constraint The constraint for the validation
     *
     * @throws ConstraintDefinitionException if this is not a constraint on a PropertyDescriptor object.
     */
    public function validate($value, Constraint $constraint)
    {
        if (! $value instanceof PropertyDescriptor) {
            throw new ConstraintDefinitionException(
                'The Property\HasSummary validator may only be used on property objects'
            );
        }

        $var = $value->getVar();
        if (! $value->getSummary() && ($var->count() == 0 || ! current($var->getAll())->getDescription())) {
            $this->context->addViolationAt('summary', $constraint->message);
        }
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Plugin\Core\Descriptor\Validator\Constraints\Classes;

use Symfony\Component\Validator\Constraint;

/**
 * Validates whether a file, class, interface or trait has not more than 1 subpackage tags.
 *
 * @Annotation
 */
class HasSingleSubpackage extends Constraint
{
    /** @var string message phpDocumentor uses codes that are defined in a messages.[lang].php file in the a plugin. */
    public $message = 'PPC:ERR-50002';

    /**
     * Returns that the constraint can be put onto classes.
     *
     * @return string
     */
    public function getTargets()
    {
        return array(self::CLASS_CONSTRAINT);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Plugin\Core\Descriptor\Validator\Constraints\Classes;

use Symfony\Component\Validator\Constraint;

/**
 * Validates whether a file, class, interface or trait always has a package if there is a subpackage present.
 *
 * @Annotation
 */
class HasPackageWithSubpackage extends Constraint
{
    /** @var string message phpDocumentor uses codes that are defined in a messages.[lang].php file in the a plugin. */
    public $message = 'PPC:ERR-50004';

    /**
     * Returns that the constraint can be put onto classes.
     *
     * @return string
     */
    public function getTargets()
    {
        return array(self::CLASS_CONSTRAINT);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Plugin\Core\Descriptor\Validator\Constraints\Classes;

use phpDocumentor\Descriptor\ClassDescriptor;
use phpDocumentor\Descriptor\Collection;
use phpDocumentor\Descriptor\FileDescriptor;
use phpDocumentor\Descriptor\InterfaceDescriptor;
use phpDocumentor\Descriptor\TraitDescriptor;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;

/**
 * Validates whether a file, class, interface or trait has not more than 1 package tags.
 */
class HasSinglePackageValidator extends ConstraintValidator
{
    /**
     * Checks if the passed value is valid.
     *
     * @param FileDescriptor|ClassDescriptor|InterfaceDescriptor|TraitDescriptor $value      The value that should
     *     be validated.
     * @param Constraint                                                         $constraint The constraint for
     *     the validation.
     *
     * @throws ConstraintDefinitionException if this is not a constraint on a PropertyDescriptor object.
     */
    public function validate($value, Constraint $constraint)
    {
        if (! $value instanceof FileDescriptor
            && ! $value instanceof ClassDescriptor
            && ! $value instanceof InterfaceDescriptor
            && ! $value instanceof TraitDescriptor
        ) {
            throw new ConstraintDefinitionException(
                'The HasSinglePackage validator may only be used on files, classes, interfaces and traits'
            );
        }

        if ($value->getTags()->get('package', new Collection())->count() > 1) {
            $this->context->addViolationAt('package', $constraint->message);
        }
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Plugin\Core\Descriptor\Validator\Constraints\Classes;

use phpDocumentor\Descriptor\ClassDescriptor;
use phpDocumentor\Descriptor\Collection;
use phpDocumentor\Descriptor\FileDescriptor;
use phpDocumentor\Descriptor\InterfaceDescriptor;
use phpDocumentor\Descriptor\TraitDescriptor;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;

/**
 * Validates whether a file, class, interface or trait always has a package if there is a subpackage present.
 */
class HasPackageWithSubpackageValidator extends ConstraintValidator
{
    /**
     * Checks if the passed value is valid.
     *
     * @param FileDescriptor|ClassDescriptor|InterfaceDescriptor|TraitDescriptor $value      The value that should
     *     be validated.
     * @param Constraint                                                         $constraint The constraint for
     *     the validation.
     *
     * @throws ConstraintDefinitionException if this is not a constraint on a PropertyDescriptor object.
     */
    public function validate($value, Constraint $constraint)
    {
        if (! $value instanceof FileDescriptor
            && ! $value instanceof ClassDescriptor
            && ! $value instanceof InterfaceDescriptor
            && ! $value instanceof TraitDescriptor
        ) {
            throw new ConstraintDefinitionException(
                'The HasPackageWithSubpackageValidator validator may only be used on files, classes, '
                . 'interfaces and traits'
            );
        }

        if ($value->getTags()->get('subpackage', new Collection())->count() > 0 && !$value->getPackage()) {
            $this->context->addViolationAt('package', $constraint->message);
        }
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Plugin\Core\Descriptor\Validator\Constraints\Classes;

use phpDocumentor\Descriptor\ClassDescriptor;
use phpDocumentor\Descriptor\Collection;
use phpDocumentor\Descriptor\FileDescriptor;
use phpDocumentor\Descriptor\InterfaceDescriptor;
use phpDocumentor\Descriptor\TraitDescriptor;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;

/**
 * Validates whether a file, class, interface or trait has not more than 1 subpackage tags.
 */
class HasSingleSubpackageValidator extends ConstraintValidator
{
    /**
     * Checks if the passed value is valid.
     *
     * @param FileDescriptor|ClassDescriptor|InterfaceDescriptor|TraitDescriptor $value      The value that should
     *     be validated.
     * @param Constraint                                                         $constraint The constraint for
     *     the validation.
     *
     * @throws ConstraintDefinitionException if this is not a constraint on a PropertyDescriptor object.
     */
    public function validate($value, Constraint $constraint)
    {
        if (! $value instanceof FileDescriptor
            && ! $value instanceof ClassDescriptor
            && ! $value instanceof InterfaceDescriptor
            && ! $value instanceof TraitDescriptor
        ) {
            throw new ConstraintDefinitionException(
                'The HasSingleSubpackage validator may only be used on files, classes, interfaces and traits'
            );
        }

        if ($value->getTags()->get('subpackage', new Collection())->count() > 1) {
            $this->context->addViolationAt('package', $constraint->message);
        }
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Plugin\Core\Descriptor\Validator\Constraints\Classes;

use Symfony\Component\Validator\Constraint;

/**
 * Validates whether a file, class, interface or trait has not more than ! package tags.
 *
 * @Annotation
 */
class HasSinglePackage extends Constraint
{
    /** @var string message phpDocumentor uses codes that are defined in a messages.[lang].php file in the a plugin. */
    public $message = 'PPC:ERR-50001';

    /**
     * Returns that the constraint can be put onto classes.
     *
     * @return string
     */
    public function getTargets()
    {
        return array(self::CLASS_CONSTRAINT);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core\Descriptor\Validator\Functions;

use phpDocumentor\Descriptor\Validator\Error;
use phpDocumentor\Reflection\BaseReflector;
use phpDocumentor\Reflection\DocBlock\Tag\ParamTag;
use phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Reflection\FunctionReflector\ArgumentReflector;
use phpDocumentor\Reflection\FunctionReflector;
use Psr\Log\LogLevel;

/**
 * @todo break this validator up in subvalidators for each Error
 */
class AreAllArgumentsValid
{
    /**
     * Validates whether the given Reflector's arguments match the business rules of phpDocumentor.
     *
     * @param BaseReflector $element
     *
     * @throws \UnexpectedValueException if no DocBlock is associated with the given Reflector.
     *
     * @return Error|null
     */
    public function validate($element)
    {
        $docBlock = $element->getDocBlock();
        if (null === $docBlock) {
            throw new \UnexpectedValueException(
                'A DocBlock should be present (and validated) before this validator can be applied'
            );
        }

        if ($docBlock->hasTag('return')) {
            $returnTag = current($docBlock->getTagsByName('return'));
            if ($returnTag->getType() == 'type') {
                return new Error(LogLevel::WARNING, 'PPC:ERR-50017', $element->getLinenumber());
            }
        }

        return null;
    }

    /**
     * Returns an error if the given Reflector's arguments do not match expectations.
     *
     * @param FunctionReflector $element
     *
     * @return Error|null
     */
    protected function validateArguments($element)
    {
        $params = $element->getDocBlock()->getTagsByName('param');
        $arguments = $element->getArguments();

        foreach (array_values($arguments) as $key => $argument) {
            if (!$this->isArgumentInDocBlock($key, $argument, $element, $params)) {
                continue;
            }

            $result = $this->doesArgumentNameMatchParam($params[$key], $argument, $element);
            if ($result) {
                return $result;
            }

            $result = $this->doesArgumentTypehintMatchParam($params[$key], $argument, $element);
            if ($result) {
                return $result;
            }
        }

        /** @var ParamTag $param */
        foreach ($params as $param) {
            $param_name = $param->getVariableName();

            if (isset($arguments[$param_name])) {
                continue;
            }

            return new Error(
                LogLevel::NOTICE,
                'PPC:ERR-50013',
                $element->getLinenumber(),
                array($param_name, $element->getName())
            );
        }

        return null;
    }

    /**
     * Validates whether an argument is mentioned in the docblock.
     *
     * @param integer           $index    The position in the argument listing.
     * @param ArgumentReflector $argument The argument itself.
     * @param BaseReflector     $element
     * @param Tag[]             $params   The list of param tags to validate against.
     *
     * @return bool whether an issue occurred.
     */
    protected function isArgumentInDocBlock($index, ArgumentReflector $argument, BaseReflector $element, array $params)
    {
        if (isset($params[$index])) {
            return null;
        }

        return new Error(
            LogLevel::ERROR,
            'PPC:ERR-50015',
            $argument->getLinenumber(),
            array($argument->getName(), $element->getName())
        );
    }

    /**
     * Validates whether the name of the argument is the same as that of the
     * param tag.
     *
     * If the param tag does not contain a name then this method will set it
     * based on the argument.
     *
     * @param ParamTag          $param    param to validate with.
     * @param ArgumentReflector $argument Argument to validate against.
     * @param BaseReflector     $element
     *
     * @return Error|null whether an issue occurred
     */
    protected function doesArgumentNameMatchParam(ParamTag $param, ArgumentReflector $argument, BaseReflector $element)
    {
        $param_name = $param->getVariableName();
        if ($param_name == $argument->getName()) {
            return null;
        }

        if ($param_name == '') {
            $param->setVariableName($argument->getName());

            return null;
        }

        return new Error(
            LogLevel::ERROR,
            'PPC:ERR-50014',
            $argument->getLinenumber(),
            array($argument->getName(), $param_name, $element->getName())
        );
    }

    /**
     * Checks the typehint of the argument versus the @param tag.
     *
     * If the argument has no typehint we do not check anything. When multiple
     * type are given then the typehint needs to be one of them.
     *
     * @param ParamTag          $param
     * @param ArgumentReflector $argument
     * @param BaseReflector     $element
     *
     * @return Error|null
     */
    protected function doesArgumentTypehintMatchParam(
        ParamTag $param,
        ArgumentReflector $argument,
        BaseReflector $element
    ) {
        if (!$argument->getType() || in_array($argument->getType(), $param->getTypes())) {
            return null;
        } elseif ($argument->getType() == 'array' && substr($param->getType(), -2) == '[]') {
            return null;
        }

        return new Error(
            LogLevel::ERROR,
            'PPC:ERR-50016',
            $argument->getLinenumber(),
            array($argument->getName(), $element->getName())
        );
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core\Descriptor\Validator;

use phpDocumentor\Translator;
use Psr\Log\LogLevel;
use phpDocumentor\Event\DebugEvent;
use phpDocumentor\Event\Dispatcher;
use phpDocumentor\Event\EventAbstract;
use phpDocumentor\Event\LogEvent;
use phpDocumentor\Reflection\BaseReflector;
use phpDocumentor\Reflection\DocBlock;

/**
 * Base class for DocBlock Validations.
 */
abstract class ValidatorAbstract
{
    /** @var Translator $translate */
    protected $translate;

    /**
     * Name of the "entity" being validated.
     *
     * @var string
     */
    protected $entityName;

    /**
     * Line number of the docblock
     *
     * @var int
     */
    protected $lineNumber;

    /**
     * Docblock for the file.
     *
     * @var \phpDocumentor\Reflection\DocBlock
     */
    protected $docblock;

    /**
     * Source element of the DocBlock.
     *
     * @var \phpDocumentor\Reflection\BaseReflector
     */
    protected $source;

    /**
     * Array of options that may or may not be used whilst validating
     *
     * @var array
     */
    protected $options;

    /**
     * Constructor
     *
     * @param string             $name     Name of the "entity"
     * @param DocBlock|null      $docblock Docblock
     * @param BaseReflector|null $source   Source Element.
     */
    public function __construct($name, $docblock = null, $source = null)
    {
        $this->entityName = $name;
        $this->lineNumber = $docblock
            ? $docblock->getLocation()->getLineNumber()
            : $source->getLineNumber();
        $this->docblock   = $docblock;
        $this->source     = $source;
    }

    /**
     * Set the options that may be used whilst validating the docblocks.
     * Can contain configuration as long as each validator knows how to
     * interrogate it
     *
     * @param array $options Options that may be used during validation
     *
     * @return void
     */
    public function setOptions($options)
    {
        $this->options = $options;
    }

    abstract public function isValid(BaseReflector $element);

    /**
     * Dispatches an event to the Event Dispatcher.
     *
     * This method tries to dispatch an event; if no Event Dispatcher has been
     * set than this method will explicitly not fail and return null.
     *
     * By not failing we make the Event Dispatcher optional and is it easier
     * for people to re-use this component in their own application.
     *
     * @param string        $name  Name of the event to dispatch.
     * @param EventAbstract $event Arguments for this event.
     *
     * @throws \Exception if there is a dispatcher but it is not of type EventDispatcher
     *
     * @return void
     */
    public function dispatch($name, $event)
    {
        if (!$this->event_dispatcher) {
            return null;
        }

        if (!$this->event_dispatcher instanceof Dispatcher) {
            throw new \Exception(
                'Expected the event dispatcher to be an instance of phpDocumentor\Event\Dispatcher'
            );
        }

        $this->event_dispatcher->dispatch($name, $event);
    }

    /**
     * Dispatches a logging request.
     *
     * @param string $message  The message to log.
     * @param string $priority The logging priority.
     *
     * @return void
     */
    public function log($message, $priority = LogLevel::INFO)
    {
        $this->dispatch(
            'system.log',
            LogEvent::createInstance($this)
                ->setMessage($message)
                ->setPriority($priority)
        );
    }

    /**
     * Dispatches a parser error to be logged.
     *
     * @param string   $type      The logging priority as string
     * @param string   $code      The message to log.
     * @param string   $line      The line number where the error occurred..
     * @param string[] $variables an array with message substitution variables.
     *
     * @return void
     */
    public function logParserError($type, $code, $line, $variables = array())
    {
        $message = $this->__($code, $variables);
        $this->log($message, LogLevel::ERROR);
        $this->dispatch(
            'parser.log',
            LogEvent::createInstance($this)
                ->setMessage($message)
                ->setType($type)
                ->setCode($code)
                ->setLine($line)
        );
    }

    /**
     * Dispatches a logging request to log a debug message.
     *
     * @param string $message The message to log.
     *
     * @return void
     */
    public function debug($message)
    {
        $this->dispatch('system.debug', DebugEvent::createInstance($this)->setMessage($message));
    }

    /**
     * Translates the ID or message in the given language.
     *
     * Translation messages may contain any formatting as used by the php
     * vsprintf function.
     *
     * @param string $message   ID or message to translate.
     * @param array  $variables Variables to use for substitution.
     * @codingStandardsIgnoreStart
     *
     * @return string
     */
    public function __($message, $variables = array())
    {
        if (!$this->translate) {
            return vsprintf($message, $variables);
        }

        $translator = $this->translate;

        return vsprintf($translator->translate($message), $variables);
    }

    /**
     * Returns the configuration for this object.
     *
     * @return \Zend\Config\Config
     */
    public function getConfiguration()
    {
        return $this->configuration;
    }

    /**
     * Returns the event dispatcher.
     *
     * @return Dispatcher
     */
    public function getEventDispatcher()
    {
        return $this->event_dispatcher;
    }

    /**
     * Returns the translation component.
     *
     * @return Translator|null
     */
    public function getTranslator()
    {
        return $this->translate;
    }
}
<?php
///**
// * File contains the
// * \phpDocumentor\Plugin\Core\Descriptor\Validator\DeprecatedValidator class.
// *
// * PHP Version 5
// *
// * @category   phpDocumentor
// * @package    Parser
// * @subpackage DocBlock_Validators
// * @author     Ben Selby <benmatselby@gmail.com>
// * @author     Mike van Riel <mike.vanriel@naenius.com>
// * @copyright  2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
// * @license    http://www.opensource.org/licenses/mit-license.php MIT
// * @link       http://phpdoc.org
// */
//
//namespace phpDocumentor\Plugin\Core\Descriptor\Validator;
//
///**
// * This class is responsible for validating which tags are deprecated
// * as defined in /src/phpDocumentor/Plugin/Core/plugin.xml
// *
// * @category   phpDocumentor
// * @package    Parser
// * @subpackage DocBlock_Validators
// * @author     Ben Selby <benmatselby@gmail.com>
// * @author     Mike van Riel <mike.vanriel@naenius.com>
// * @copyright  2010-2011 Mike van Riel / Naenius. (http://www.naenius.com)
// * @license    http://www.opensource.org/licenses/mit-license.php MIT
// * @link       http://phpdoc.org
// */
//class DeprecatedValidator extends ValidatorAbstract
//{
//    /**
//     * Is the docblock valid based on the rules defined in plugin.xml
//     *
//     * <options>
//     *   <option name="deprecated">
//     *      <tag name="deprecated" />
//     *      <tag name="access" />
//     *   </option>
//     *   <option name="required">
//     *     <tag name="package">
//     *       <element>phpDocumentor\Reflection\FileReflector</element>
//     *       <element>phpDocumentor\Reflection\ClassReflector</element>
//     *     </tag>
//     *     <tag name="subpackage">
//     *       <element>phpDocumentor\Reflection\FileReflector</element>
//     *       <element>phpDocumentor\Reflection\ClassReflector</element>
//     *     </tag>
//     *   </option>
//     * </options>
//     *
//     * @see ValidatorAbstract::isValid()
//     *
//     * @return boolean
//     */
//    public function isValid()
//    {
//        $docType = get_class($this->source);
//        if (isset($this->options['deprecated'][$docType])) {
//            $this->validateTags($docType);
//        } elseif (isset($this->options['deprecated']['__ALL__'])) {
//            $this->validateTags('__ALL__');
//        }
//    }
//
//    /**
//     * Validate the tags based on the type of docblock being
//     * parsed etc
//     *
//     * @param string $key Access key to $this->options['required']
//     *
//     * @return void
//     */
//    protected function validateTags($key)
//    {
//        foreach ($this->options['deprecated'][$key] as $tag) {
//            if (count($this->docblock->getTagsByName($tag)) < 1) {
//                continue;
//            }
//            $this->logParserError('CRITICAL', 'PPC:ERR-50006', $this->lineNumber, array($tag, $this->entityName));
//        }
//    }
//}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core\Twig;

use phpDocumentor\Descriptor\ProjectDescriptor;
use phpDocumentor\Transformer\Transformation;

/**
 * An interface shared by all Twig interfaces intended for phpDocumentor.
 */
interface ExtensionInterface
{
    /**
     * Registers the structure and transformation objects with this extension.
     *
     * The Structure and Transformation object can be used to get context from
     * and to provide additional information.
     *
     * @param ProjectDescriptor $project        Represents the complete Abstract Syntax Tree.
     * @param Transformation    $transformation Represents the transformation meta data used in the current generation
     *     cycle.
     */
    public function __construct(ProjectDescriptor $project, Transformation $transformation);
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core\Twig;

use phpDocumentor\Descriptor\Collection;
use phpDocumentor\Descriptor\ProjectDescriptor;
use phpDocumentor\Transformer\Router\Queue;
use phpDocumentor\Transformer\Transformation;
use phpDocumentor\Translator;

/**
 * Basic extension adding phpDocumentor specific functionality for Twig
 * templates.
 *
 * Global variables:
 *
 * - *ast_node*, the current $data element
 *
 * Functions:
 *
 * - *path(string)*, converts the given relative path to be based of the projects
 *   root instead of the current directory
 */
class Extension extends \Twig_Extension implements ExtensionInterface
{
    /**
     * @var ProjectDescriptor
     */
    protected $data = null;

    /** @var Queue $router */
    protected $routers;

    /** @var Translator */
    protected $translator;

    /**
     * @var string
     */
    protected $destination = '';

    /**
     * Registers the structure and transformation with this extension.
     *
     * @param ProjectDescriptor $project        Represents the complete Abstract Syntax Tree.
     * @param Transformation    $transformation Represents the transformation meta data used in the current generation
     *     cycle.
     */
    public function __construct(ProjectDescriptor $project, Transformation $transformation)
    {
        $this->data = $project;
    }

    /**
     * Returns the name of this extension.
     *
     * @return string The extension name
     */
    public function getName()
    {
        return 'phpdocumentor';
    }

    /**
     * @param Queue $router
     */
    public function setRouters($router)
    {
        $this->routers = $router;
    }

    /**
     * @param Translator $translator
     */
    public function setTranslator($translator)
    {
        $this->translator = $translator;
    }

    /**
     * Sets the destination directory relative to the Project's Root.
     *
     * The destination is the target directory containing the resulting
     * file. This destination is relative to the Project's root and can
     * be used for the calculation of nesting depths, etc.
     *
     * For this specific extension the destination is provided in the
     * Twig writer itself.
     *
     * @param string $destination
     *
     * @see phpDocumentor\Plugin\Twig\Transformer\Writer\Twig for the invocation
     *     of this method.
     *
     * @return void
     */
    public function setDestination($destination)
    {
        $this->destination = $destination;
    }

    /**
     * Returns the target directory relative to the Project's Root.
     *
     * @return string
     */
    public function getDestination()
    {
        return $this->destination;
    }

    /**
     * Returns a listing of all functions that this extension adds.
     *
     * This method is automatically used by Twig upon registering this
     * extension (which is done automatically by phpDocumentor) to determine
     * an additional list of functions.
     *
     * See the Class' DocBlock for a listing of functionality added by this
     * Extension.
     *
     * @return \Twig_FunctionInterface[]
     */
    public function getFunctions()
    {
        return array(
            'path' => new \Twig_Function_Method($this, 'convertToRootPath'),
        );
    }

    public function getFilters()
    {
        $extension = $this;
        $routers = $this->routers;
        $parser = \Parsedown::instance();
        $translator = $this->translator;

        return array(
            'markdown' => new \Twig_SimpleFilter(
                'markdown',
                function ($value) use ($parser) {
                    return $parser->parse($value);
                }
            ),
            'trans' => new \Twig_SimpleFilter(
                'trans',
                function ($value, $context) use ($translator) {
                    if (!$context) {
                        $context = array();
                    }

                    return vsprintf($translator->translate($value), $context);
                }
            ),
            'route' => new \Twig_SimpleFilter(
                'route',
                function ($value, $presentation = 'normal') use ($extension, $routers) {
                    // FIXME: this code is suboptimal and needs refactoring
                    $result = array();
                    if ($value instanceof Collection) {
                        $value = $value->getAll();
                    }
                    $singleResult = !is_array($value);
                    $value = !is_array($value) ? array($value) : $value;

                    foreach ($value as $path) {
                        $rule     = $routers->match($path);
                        $url      = $rule ? ltrim($rule->generate($path), '/') : false;

                        if ($url
                            && $url[0] != '/'
                            && (strpos($url, 'http://') !== 0)
                            && (strpos($url, 'https://') !== 0)
                        ) {
                            $url = $extension->convertToRootPath($url);
                        }

                        switch ($presentation) {
                            case 'url': // return the first url

                                return $url;
                            case 'class:short':
                                $parts = explode('\\', $path);
                                $path = end($parts);
                                break;
                        }

                        $result[] = $url ? sprintf('<a href="%s">%s</a>', $url, $path) : $path;
                    }

                    return $singleResult ? reset($result) : $result;
                }
            ),
        );
    }

    /**
     * Returns an array of global variables to inject into a Twig template.
     *
     * @return mixed
     */
    public function getGlobals()
    {
        return array(
            'project' => $this->data
        );
    }

    /**
     * Converts the given path to be relative to the root of the documentation
     * target directory.
     *
     * It is not possible to use absolute paths in documentation templates since
     * they may be used locally, or in a subfolder. As such we need to calculate
     * the number of levels to go up from the current document's directory and
     * then append the given path.
     *
     * For example:
     *
     *     Suppose you are in <root>/classes/my/class.html and you want open
     *     <root>/my/index.html then you provide 'my/index.html' to this method
     *     and it will convert it into ../../my/index.html (<root>/classes/my is
     *     two nesting levels until the root).
     *
     * This method does not try to normalize or optimize the paths in order to
     * save on development time and performance, and because it adds no real
     * value.
     *
     * @param string $relative_path
     *
     * @return string
     */
    public function convertToRootPath($relative_path)
    {
        // get the path to the root directory
        $path_parts = explode(DIRECTORY_SEPARATOR, $this->getDestination());
        if (count($path_parts) > 1) {
            $path_to_root = implode('/', array_fill(0, count($path_parts) -1, '..')).'/';
        } else {
            $path_to_root = '';
        }

        if (is_string($relative_path) && ($relative_path[0] != '@')) {
            // append the relative path to the root
            return $path_to_root.ltrim($relative_path, '/');
        }

        $rule = $this->routers->match($relative_path);
        if (!$rule) {
            return null;
        }

        $generatedPath = $rule->generate($relative_path);

        return $generatedPath ? $path_to_root.ltrim($generatedPath, '/') : null;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core;

use Cilex\Application;
use Cilex\ServiceProviderInterface;
use phpDocumentor\Translator;
use phpDocumentor\Plugin\Core\Transformer\Writer;
use phpDocumentor\Transformer\Writer\Collection;

class ServiceProvider implements ServiceProviderInterface
{
    /**
     * Registers services on the given app.
     *
     * @param Application $app An Application instance.
     */
    public function register(Application $app)
    {
        /** @var Translator $translator  */
        $translator = $app['translator'];
        $translator->addTranslationFolder(__DIR__ . DIRECTORY_SEPARATOR . 'Messages');

        /** @var Collection $writerCollection */
        $writerCollection = $app['transformer.writer.collection'];

        $writerCollection['FileIo']     = new Writer\FileIo();
        $writerCollection['twig']       = new Writer\Twig();
        $writerCollection['Graph']      = new Writer\Graph();
        $writerCollection['checkstyle'] = new Writer\Checkstyle();
        $writerCollection['sourcecode'] = new Writer\Sourcecode();
        $writerCollection['xml']        = new Writer\Xml();
        $writerCollection['xsl']        = new Writer\Xsl($app['monolog']);

        $writerCollection['checkstyle']->setTranslator($translator);
        $writerCollection['xml']->setTranslator($translator);
        $writerCollection['twig']->setTranslator($translator);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core\Transformer\Writer;

use Monolog\Logger;
use phpDocumentor\Application;
use phpDocumentor\Descriptor\ProjectDescriptor;
use phpDocumentor\Event\Dispatcher;
use phpDocumentor\Plugin\Core\Exception;
use phpDocumentor\Transformer\Event\PreXslWriterEvent;
use phpDocumentor\Transformer\Transformation;
use phpDocumentor\Transformer\Transformation as TransformationObject;
use phpDocumentor\Transformer\Writer\Exception\RequirementMissing;
use phpDocumentor\Transformer\Writer\WriterAbstract;

/**
 * XSL transformation writer; generates static HTML out of the structure and XSL templates.
 */
class Xsl extends WriterAbstract
{
    /** @var \Monolog\Logger $logger */
    protected $logger;

    protected $xsl_variables = array();

    /**
     * Initialize this writer with the logger so that it can output logs.
     *
     * @param Logger $logger
     */
    public function __construct(Logger $logger)
    {
        $this->logger = $logger;
    }

    /**
     * Checks whether XSL handling is enabled with PHP as that is not enabled by default.
     *
     * To enable XSL handling you need either the xsl extension or the xslcache extension installed.
     *
     * @throws RequirementMissing if neither xsl extensions are installed.
     *
     * @return void
     */
    public function checkRequirements()
    {
        if (!class_exists('XSLTProcessor') && (!extension_loaded('xslcache'))) {
            throw new RequirementMissing(
                'The XSL writer was unable to find your XSLTProcessor; '
                . 'please check if you have installed the PHP XSL extension or XSLCache extension'
            );
        }
    }

    /**
     * This method combines the structure.xml and the given target template
     * and creates a static html page at the artifact location.
     *
     * @param ProjectDescriptor $project        Document containing the structure.
     * @param Transformation    $transformation Transformation to execute.
     *
     * @throws \RuntimeException if the structure.xml file could not be found.
     * @throws Exception        if the structure.xml file's documentRoot could not be read because of encoding issues
     *    or because it was absent.
     *
     * @return void
     */
    public function transform(ProjectDescriptor $project, Transformation $transformation)
    {
        $artifact = $transformation->getTransformer()->getTarget()
            . DIRECTORY_SEPARATOR . $transformation->getArtifact();

        $structureFilename = $transformation->getTransformer()->getTarget() . DIRECTORY_SEPARATOR . 'structure.xml';
        if (!is_readable($structureFilename)) {
            throw new \RuntimeException(
                'Structure.xml file was not found in the target directory, is the XML writer missing from the '
                . 'template definition?'
            );
        }

        // load the structure file (ast)
        $structure = new \DOMDocument('1.0', 'utf-8');
        libxml_use_internal_errors(true);
        $structure->load($structureFilename);

        $proc = $this->getXslProcessor($transformation);

        if (empty($structure->documentElement)) {
            $message = 'Specified DOMDocument lacks documentElement, cannot transform.';
            if (libxml_get_last_error()) {
                $message .= PHP_EOL . 'Apparently an error occurred with reading the structure.xml file, the reported '
                . 'error was "' . trim(libxml_get_last_error()->message) . '" on line ' . libxml_get_last_error()->line;
            }
            throw new Exception($message);
        }

        $proc->setParameter('', 'title', $structure->documentElement->getAttribute('title'));
        $proc->setParameter('', 'root', str_repeat('../', substr_count($transformation->getArtifact(), '/')));
        $proc->setParameter('', 'search_template', $transformation->getParameter('search', 'none'));
        $proc->setParameter('', 'version', Application::$VERSION);
        $proc->setParameter('', 'generated_datetime', date('r'));

        // check parameters for variables and add them when found
        $this->setProcessorParameters($transformation, $proc);

        // if a query is given, then apply a transformation to the artifact
        // location by replacing ($<var>} with the sluggified node-value of the
        // search result
        if ($transformation->getQuery() !== '') {
            $xpath = new \DOMXPath($structure);

            /** @var \DOMNodeList $qry */
            $qry = $xpath->query($transformation->getQuery());
            $count = $qry->length;
            foreach ($qry as $key => $element) {
                Dispatcher::getInstance()->dispatch(
                    'transformer.writer.xsl.pre',
                    PreXslWriterEvent
                    ::createInstance($this)->setElement($element)
                    ->setProgress(array($key+1, $count))
                );

                $proc->setParameter('', $element->nodeName, $element->nodeValue);
                $file_name = $transformation->getTransformer()->generateFilename(
                    $element->nodeValue
                );

                $filename = str_replace('{$' . $element->nodeName . '}', $file_name, $artifact);

                if (!file_exists(dirname($filename))) {
                    mkdir(dirname($filename), 0755, true);
                }
                $proc->transformToURI($structure, $this->getXsltUriFromFilename($filename));
            }
        } else {
            if (substr($transformation->getArtifact(), 0, 1) == '$') {
                // not a file, it must become a variable!
                $variable_name = substr($transformation->getArtifact(), 1);
                $this->xsl_variables[$variable_name]
                    = $proc->transformToXml($structure);
            } else {
                if (!file_exists(dirname($artifact))) {
                    mkdir(dirname($artifact), 0755, true);
                }
                $proc->transformToURI($structure, $this->getXsltUriFromFilename($artifact));
            }
        }
    }

    /**
     * Takes the filename and converts it into a correct URI for XSLTProcessor.
     *
     * @param string $filename
     *
     * @return string
     */
    protected function getXsltUriFromFilename($filename)
    {
        // Windows requires an additional / after the scheme.
        // If not provided then errno 22 (I/O Error: Invalid Argument) will be
        // raised. Thanks to @FnTmLV for finding the cause.
        // See issue #284 for more information
        if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
            $filename = '/' . $filename;
        }

        return 'file://' . $filename;
    }

    /**
     * Sets the parameters of the XSLT processor.
     *
     * @param TransformationObject $transformation Transformation.
     * @param \XSLTProcessor       $proc           XSLTProcessor.
     *
     * @return void
     */
    public function setProcessorParameters(
        TransformationObject $transformation,
        \XSLTProcessor $proc
    ) {
        foreach ($this->xsl_variables as $key => $variable) {
            // XSL does not allow both single and double quotes in a string
            if ((strpos($variable, '"') !== false)
                && ((strpos($variable, "'") !== false))
            ) {
                // TODO: inject the logger and use it here
                //$this->log(
                //    'XSLT does not allow both double and single quotes in '
                //    . 'a variable; transforming single quotes to a character '
                //    . 'encoded version in variable: ' . $key,
                //    LogLevel::WARNING
                //);
                $variable = str_replace("'", "&#39;", $variable);
            }

            $proc->setParameter('', $key, $variable);
        }

        // add / overwrite the parameters with those defined in the
        // transformation entry
        $parameters = $transformation->getParameters();
        if (isset($parameters['variables'])) {
            /** @var \DOMElement $variable */
            foreach ($parameters['variables'] as $key => $value) {
                $proc->setParameter('', $key, $value);
            }
        }
    }

    /**
     *
     *
     * @param Transformation $transformation
     *
     * @return \XSLTCache|\XSLTProcessor
     */
    protected function getXslProcessor(Transformation $transformation)
    {
        $xslTemplatePath = $transformation->getSourceAsPath();
        $this->logger->debug('Loading XSL template: ' . $xslTemplatePath);
        if (!file_exists($xslTemplatePath)) {
            throw new Exception('Unable to find XSL template "' . $xslTemplatePath . '"');
        }

        if (extension_loaded('xslcache')) {
            $proc = new \XSLTCache();
            $proc->importStyleSheet($xslTemplatePath, true);

            return $proc;
        } else {
            $xsl = new \DOMDocument();
            $xsl->load($xslTemplatePath);

            $proc = new \XSLTProcessor();
            $proc->importStyleSheet($xsl);

            return $proc;
        }
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core\Transformer\Writer;

/**
 * Writer containing file system operations.
 *
 * The Query part of the transformation determines the action, currently
 * supported is:
 *
 * * copy, copies a file or directory to the destination given in $artifact
 */
use phpDocumentor\Descriptor\ProjectDescriptor;
use phpDocumentor\Transformer\Exception;
use phpDocumentor\Transformer\Transformation;
use phpDocumentor\Transformer\Writer\WriterAbstract;

class FileIo extends WriterAbstract
{
    /** @var \phpDocumentor\Transformer\Transformation */
    protected $transformation = null;

    /**
     * Invokes the query method contained in this class.
     *
     * @param ProjectDescriptor $project        Document containing the structure.
     * @param Transformation    $transformation Transformation to execute.
     *
     * @throws \InvalidArgumentException if the query is not supported.
     *
     * @return void
     */
    public function transform(ProjectDescriptor $project, Transformation $transformation)
    {
        $artifact = $transformation->getTransformer()->getTarget()
            . DIRECTORY_SEPARATOR . $transformation->getArtifact();
        $transformation->setArtifact($artifact);

        $method = 'executeQuery' . ucfirst($transformation->getQuery());
        if (!method_exists($this, $method)) {
            throw new \InvalidArgumentException(
                'The query ' . $method . ' is not supported by the FileIo writer, supported operation is "copy"'
            );
        }

        $this->$method($transformation);
    }

    /**
     * Copies files or folders to the Artifact location.
     *
     * @param Transformation $transformation Transformation to use as data source.
     *
     * @throws Exception
     *
     * @return void
     */
    public function executeQueryCopy(Transformation $transformation)
    {
        $path = $transformation->getSourceAsPath();

        if (!is_readable($path)) {
            throw new Exception('Unable to read the source file: ' . $path);
        }
        if (!is_writable($transformation->getTransformer()->getTarget())) {
            throw new Exception('Unable to write to: ' . dirname($transformation->getArtifact()));
        }

        $this->copyRecursive($path, $transformation->getArtifact());
    }

    /**
     * Copies a file or folder recursively to another location.
     *
     * @param string $src The source location to copy
     * @param string $dst The destination location to copy to
     *
     * @throws \Exception if $src does not exist or $dst is not writable
     *
     * @return void
     */
    public function copyRecursive($src, $dst)
    {
        // if $src is a normal file we can do a regular copy action
        if (is_file($src)) {
            copy($src, $dst);

            return;
        }

        $dir = opendir($src);
        if (!$dir) {
            throw new \Exception('Unable to locate path "' . $src . '"');
        }

        // check if the folder exists, otherwise create it
        if ((!file_exists($dst)) && (false === mkdir($dst))) {
            throw new \Exception('Unable to create folder "' . $dst . '"');
        }

        while (false !== ($file = readdir($dir))) {
            if (($file != '.') && ($file != '..')) {
                if (is_dir($src . DIRECTORY_SEPARATOR . $file)) {
                    $this->copyRecursive($src . DIRECTORY_SEPARATOR . $file, $dst . DIRECTORY_SEPARATOR . $file);
                } else {
                    copy($src . DIRECTORY_SEPARATOR . $file, $dst . DIRECTORY_SEPARATOR . $file);
                }
            }
        }
        closedir($dir);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core\Transformer\Writer;

use phpDocumentor\Descriptor\ClassDescriptor;
use phpDocumentor\Descriptor\Collection;
use phpDocumentor\Descriptor\InterfaceDescriptor;
use phpDocumentor\Descriptor\NamespaceDescriptor;
use phpDocumentor\Descriptor\ProjectDescriptor;
use phpDocumentor\Descriptor\TraitDescriptor;
use phpDocumentor\GraphViz\Edge;
use phpDocumentor\GraphViz\Graph as GraphVizGraph;
use phpDocumentor\GraphViz\Node;
use phpDocumentor\Transformer\Transformation;
use phpDocumentor\Transformer\Writer\WriterAbstract;
use Zend\Stdlib\Exception\ExtensionNotLoadedException;

/**
 * Writer responsible for generating various graphs.
 *
 * The Graph writer is capable of generating a Graph (as provided using the 'source' parameter) at the location provided
 * using the artifact parameter.
 *
 * Currently supported:
 *
 * * 'class', a Class Diagram Generated using GraphViz
 *
 * @todo Fix this class
 */
class Graph extends WriterAbstract
{
    /** @var string Name of the font to use to display the node labels with */
    protected $nodeFont = 'Courier';

    /** @var Node[] a cache where nodes for classes, interfaces and traits are stored for reference */
    protected $nodeCache = array();

    /**
     * Invokes the query method contained in this class.
     *
     * @param ProjectDescriptor $project        Document containing the structure.
     * @param Transformation    $transformation Transformation to execute.
     *
     * @return void
     */
    public function transform(ProjectDescriptor $project, Transformation $transformation)
    {
        $type_method = 'process' . ucfirst($transformation->getSource());
        $this->$type_method($project, $transformation);
    }

    /**
     * Creates a class inheritance diagram.
     *
     * @param ProjectDescriptor $project
     * @param Transformation    $transformation
     *
     * @return void
     */
    public function processClass(ProjectDescriptor $project, Transformation $transformation)
    {
        try {
            $this->checkIfGraphVizIsInstalled();
        } catch (\Exception $e) {
            echo $e->getMessage();
            return;
        }

        $this->nodeFont = $transformation->getParameter('font', 'Courier');

        $filename = $this->getDestinationPath($transformation);

        $graph = GraphVizGraph::create()
            ->setRankSep('1.0')
            ->setCenter('true')
            ->setRank('source')
            ->setRankDir('RL')
            ->setSplines('true')
            ->setConcentrate('true');

        $this->buildNamespaceTree($graph, $project->getNamespace());

        $classes    = $project->getIndexes()->get('classes', new Collection())->getAll();
        $interfaces = $project->getIndexes()->get('interfaces', new Collection())->getAll();
        $traits     = $project->getIndexes()->get('traits', new Collection())->getAll();

        /** @var ClassDescriptor[]|InterfaceDescriptor[]|TraitDescriptor[] $containers  */
        $containers = array_merge($classes, $interfaces, $traits);

        foreach ($containers as $container) {
            $from_name = $container->getFullyQualifiedStructuralElementName();

            $parents     = array();
            $implemented = array();
            if ($container instanceof ClassDescriptor) {
                if ($container->getParent()) {
                    $parents[] = $container->getParent();
                }
                $implemented = $container->getInterfaces()->getAll();
            }
            if ($container instanceof InterfaceDescriptor) {
                $parents = $container->getParent()->getAll();
            }

            /** @var string|ClassDescriptor|InterfaceDescriptor $parent */
            foreach ($parents as $parent) {
                $edge = $this->createEdge($graph, $from_name, $parent);
                $edge->setArrowHead('empty');
                $graph->link($edge);
            }

            /** @var string|ClassDescriptor|InterfaceDescriptor $parent */
            foreach ($implemented as $parent) {
                $edge = $this->createEdge($graph, $from_name, $parent);
                $edge->setStyle('dotted');
                $edge->setArrowHead('empty');
                $graph->link($edge);
            }
        }

        $graph->export('svg', $filename);
    }

    /**
     * Creates a GraphViz Edge between two nodes.
     *
     * @param Graph  $graph
     * @param string $from_name
     * @param string|ClassDescriptor|InterfaceDescriptor|TraitDescriptor $to
     *
     * @return Edge
     */
    protected function createEdge($graph, $from_name, $to)
    {
        $to_name = !is_string($to) ? $to->getFullyQualifiedStructuralElementName() : $to;

        if (!isset($this->nodeCache[$from_name])) {
            $this->nodeCache[$from_name] = $this->createEmptyNode($from_name, $graph);
        }
        if (!isset($this->nodeCache[$to_name])) {
            $this->nodeCache[$to_name] = $this->createEmptyNode($to_name, $graph);
        }

        return Edge::create($this->nodeCache[$from_name], $this->nodeCache[$to_name]);
    }

    /**
     * @param string $name
     * @param Graph $graph
     *
     * @return Node
     */
    protected function createEmptyNode($name, $graph)
    {
        $node = Node::create($name);
        $node->setFontColor('gray');
        $node->setLabel($name);
        $graph->setNode($node);

        return $node;
    }

    /**
     * Builds a tree of namespace subgraphs with their classes associated.
     *
     * @param GraphVizGraph       $graph
     * @param NamespaceDescriptor $namespace
     *
     * @return void
     */
    protected function buildNamespaceTree(GraphVizGraph $graph, NamespaceDescriptor $namespace)
    {
        $full_namespace_name = $namespace->getFullyQualifiedStructuralElementName();
        if ($full_namespace_name == '\\') {
            $full_namespace_name = 'Global';
        }

        $sub_graph = GraphVizGraph::create('cluster_' . $full_namespace_name)
            ->setLabel($namespace->getName())
            ->setStyle('rounded')
            ->setColor('gray')
            ->setFontColor('gray')
            ->setFontSize('11')
            ->setRankDir('LR');

        $elements = array_merge(
            $namespace->getClasses()->getAll(),
            $namespace->getInterfaces()->getAll(),
            $namespace->getTraits()->getAll()
        );

        /** @var ClassDescriptor|InterfaceDescriptor|TraitDescriptor $sub_element */
        foreach ($elements as $sub_element) {
            $node = Node::create($sub_element->getFullyQualifiedStructuralElementName(), $sub_element->getName())
                ->setShape('box')
                ->setFontName($this->nodeFont)
                ->setFontSize('11');

            if ($sub_element instanceof ClassDescriptor && $sub_element->isAbstract()) {
                $node->setLabel('<«abstract»<br/>' . $sub_element->getName(). '>');
            }

            //$full_name = $sub_element->getFullyQualifiedStructuralElementName();
            //$node->setURL($this->class_paths[$full_name]);
            //$node->setTarget('_parent');

            $this->nodeCache[$sub_element->getFullyQualifiedStructuralElementName()] = $node;
            $sub_graph->setNode($node);
        }

        foreach ($namespace->getChildren()->getAll() as $element) {
            $this->buildNamespaceTree($sub_graph, $element);
        }

        $graph->addGraph($sub_graph);
    }

    /**
     * @param \phpDocumentor\Transformer\Transformation $transformation
     * @return string
     */
    protected function getDestinationPath(Transformation $transformation)
    {
        $filename = $transformation->getTransformer()->getTarget()
            . DIRECTORY_SEPARATOR . $transformation->getArtifact();

        return $filename;
    }

    /**
     * Checks whether GraphViz is installed and throws an Exception otherwise.
     *
     * @throws ExtensionNotLoadedException if graphviz is not found.
     *
     * @return void
     */
    protected function checkIfGraphVizIsInstalled()
    {
        // NOTE: the -V flag sends output using STDERR and STDOUT
        exec('dot -V 2>&1', $output, $error);
        if ($error != 0) {
            throw new ExtensionNotLoadedException(
                'Unable to find the `dot` command of the GraphViz package. '
                . 'Is GraphViz correctly installed and present in your path?'
            );
        }
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core\Transformer\Writer;

use phpDocumentor\Descriptor\FileDescriptor;
use phpDocumentor\Descriptor\ProjectDescriptor;
use phpDocumentor\Descriptor\Validator\Error;
use phpDocumentor\Transformer\Transformation;
use phpDocumentor\Transformer\Writer\Translatable;
use phpDocumentor\Transformer\Writer\WriterAbstract;
use phpDocumentor\Translator;

/**
 * Checkstyle transformation writer; generates checkstyle report
 */
class Checkstyle extends WriterAbstract implements Translatable
{
    /** @var Translator $translator */
    protected $translator;

    /**
     * Returns an instance of the object responsible for translating content.
     *
     * @return Translator
     */
    public function getTranslator()
    {
        return $this->translator;
    }

    /**
     * Sets a new object capable of translating strings on this writer.
     *
     * @param Translator $translator
     *
     * @return void
     */
    public function setTranslator(Translator $translator)
    {
        $this->translator = $translator;
    }

    /**
     * This method generates the checkstyle.xml report
     *
     * @param ProjectDescriptor $project        Document containing the structure.
     * @param Transformation    $transformation Transformation to execute.
     *
     * @return void
     */
    public function transform(ProjectDescriptor $project, Transformation $transformation)
    {
        $artifact = $this->getDestinationPath($transformation);

        $document = new \DOMDocument();
        $document->formatOutput = true;
        $report = $document->createElement('checkstyle');
        $report->setAttribute('version', '1.3.0');
        $document->appendChild($report);

        /** @var FileDescriptor $fileDescriptor */
        foreach ($project->getFiles()->getAll() as $fileDescriptor) {
            $file = $document->createElement('file');
            $file->setAttribute('name', $fileDescriptor->getPath());
            $report->appendChild($file);

            /** @var Error $error */
            foreach ($fileDescriptor->getAllErrors()->getAll() as $error) {
                $item = $document->createElement('error');
                $item->setAttribute('line', $error->getLine());
                $item->setAttribute('severity', $error->getSeverity());
                $item->setAttribute(
                    'message',
                    vsprintf($this->getTranslator()->translate($error->getCode()), $error->getContext())
                );
                $item->setAttribute('source', 'phpDocumentor.file.'.$error->getCode());
                $file->appendChild($item);
            }
        }

        $this->saveCheckstyleReport($artifact, $document);
    }

    /**
     * Retrieves the destination location for this artifact.
     *
     * @param \phpDocumentor\Transformer\Transformation $transformation
     *
     * @return string
     */
    protected function getDestinationPath(Transformation $transformation)
    {
        $artifact = $transformation->getTransformer()->getTarget()
            . DIRECTORY_SEPARATOR . $transformation->getArtifact();

        return $artifact;
    }

    /**
     * Save the checkstyle report to the artifact
     *
     * @param string       $artifact Target name for the report
     * @param \DOMDocument $document The actual xml document being saved
     *
     * @return void
     */
    protected function saveCheckstyleReport($artifact, \DOMDocument $document)
    {
        file_put_contents($artifact, $document->saveXML());
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core\Transformer\Writer;

use phpDocumentor\Descriptor\FileDescriptor;
use phpDocumentor\Descriptor\ProjectDescriptor;
use phpDocumentor\Transformer\Transformation;
use phpDocumentor\Transformer\Writer\WriterAbstract;

/**
 * Sourcecode transformation writer; generates syntax highlighted source files in a destination's subfolder.
 */
class Sourcecode extends WriterAbstract
{
    /**
     * This method writes every source code entry in the structure file to a highlighted file.
     *
     * @param ProjectDescriptor $project        Document containing the structure.
     * @param Transformation    $transformation Transformation to execute.
     *
     * @return void
     */
    public function transform(ProjectDescriptor $project, Transformation $transformation)
    {
        $artifact = $transformation->getTransformer()->getTarget()
            . DIRECTORY_SEPARATOR
            . ($transformation->getArtifact()
                ? $transformation->getArtifact()
                : 'source');

        /** @var FileDescriptor $file */
        foreach ($project->getFiles() as $file) {
            $filename = $file->getPath();
            $source   = $file->getSource();

            $root = str_repeat('../', count(explode(DIRECTORY_SEPARATOR, $filename)));
            $path = $artifact . DIRECTORY_SEPARATOR . $filename;
            if (!file_exists(dirname($path))) {
                mkdir(dirname($path), 0755, true);
            }
            $source = htmlentities($source);
            file_put_contents(
                $path.'.html',
                <<<HTML
<html>
    <head>
        <script
            type="text/javascript"
            src="{$root}js/jquery-1.4.2.min.js">
        </script>
        <script
            type="text/javascript"
            src="{$root}syntax_highlighter/scripts/shCore.js">
        </script>
        <script
            type="text/javascript"
            src="{$root}syntax_highlighter/scripts/shBrushJScript.js">
        </script>
        <script
            type="text/javascript"
            src="{$root}syntax_highlighter/scripts/shBrushPhp.js">
        </script>
        <script
            type="text/javascript"
            src="{$root}syntax_highlighter/scripts/shBrushXml.js">
        </script>
        <link
            href="{$root}syntax_highlighter/styles/shCore.css" rel="stylesheet"
            type="text/css"
        />
        <link
            href="{$root}syntax_highlighter/styles/shCoreEclipse.css"
            rel="stylesheet" type="text/css"
        />
        <link
            href="{$root}syntax_highlighter/styles/shThemeWordpress.css"
            rel="stylesheet" type="text/css"
        />
    </head>
    <body>
        <pre class="brush: php">$source</pre>
        <script type="text/javascript">
             SyntaxHighlighter.all();
             jQuery('.gutter div').each(function(key, data){
                jQuery(data).prepend('<a name="L'+jQuery(data).text()+'"/>');
             });
        </script>
    </body>
</html>
HTML
            );

        }
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core\Transformer\Writer;

use phpDocumentor\Descriptor\DescriptorAbstract;
use phpDocumentor\Descriptor\ProjectDescriptor;
use phpDocumentor\Plugin\Core\Twig\Extension;
use phpDocumentor\Transformer\Router\ForFileProxy;
use phpDocumentor\Transformer\Router\Queue;
use phpDocumentor\Transformer\Template;
use phpDocumentor\Transformer\Transformation;
use phpDocumentor\Transformer\Writer\Routable;
use phpDocumentor\Transformer\Writer\WriterAbstract;
use phpDocumentor\Translator;

/**
 * A specialized writer which uses the Twig templating engine to convert
 * templates to HTML output.
 *
 * This writer support the Query attribute of a Transformation to generate
 * multiple templates in one transformation.
 *
 * The Query attribute supports a simplified version of Twig queries and will
 * use each individual result as the 'node' global variable in the Twig template.
 *
 * Example:
 *
 *   Suppose a Query `indexes.classes` is given then this writer will be
 *   invoked as many times as there are classes in the project and the
 *   'node' global variable in twig will be filled with each individual
 *   class entry.
 *
 * When using the Query attribute in the transformation it is important to
 * use a variable in the Artifact attribute as well (otherwise the same file
 * would be overwritten several times).
 *
 * A simple example transformation line could be:
 *
 *     ```
 *     <transformation
 *         writer="twig"
 *         source="templates/twig/index.twig"
 *         artifact="index.html"/>
 *     ```
 *
 *     This example transformation would use this writer to transform the
 *     index.twig template file in the twig template folder into index.html at
 *     the destination location.
 *     Since no Query is provided the 'node' global variable will contain
 *     the Project Descriptor of the Object Graph.
 *
 * A complex example transformation line could be:
 *
 *     ```
 *     <transformation
 *         query="indexes.classes"
 *         writer="twig"
 *         source="templates/twig/class.twig"
 *         artifact="{{name}}.html"/>
 *     ```
 *
 *     This example transformation would use this writer to transform the
 *     class.twig template file in the twig template folder into a file with
 *     the 'name' property for an individual class inside the Object Graph.
 *     Since a Query *is* provided will the 'node' global variable contain a
 *     specific instance of a class applicable to the current iteration.
 *
 * @see self::getDestinationPath() for more information about variables in the
 *     Artifact attribute.
 */
class Twig extends WriterAbstract implements Routable
{
    /** @var Queue $routers */
    protected $routers;

    /** @var Translator $translator */
    protected $translator;

    /**
     * This method combines the ProjectDescriptor and the given target template
     * and creates a static html page at the artifact location.
     *
     * @param ProjectDescriptor $project        Document containing the structure.
     * @param Transformation    $transformation Transformation to execute.
     *
     * @return void
     */
    public function transform(ProjectDescriptor $project, Transformation $transformation)
    {
        $template_path = $this->getTemplatePath($transformation);

        $nodes = $this->getListOfNodes($transformation->getQuery(), $project);

        foreach ($nodes as $node) {
            if (!$node) {
                continue;
            }
            $destination = $this->getDestinationPath($node, $transformation);
            if ($destination === false) {
                continue;
            }
            $environment = $this->initializeEnvironment($project, $transformation, $destination);
            $environment->addGlobal('node', $node);

            $html = $environment->render(substr($transformation->getSource(), strlen($template_path)));
            file_put_contents($destination, $html);
        }
    }

    /**
     * Combines the query and project to retrieve a list of nodes that are to be used as node-point in a template.
     *
     * This method interprets the provided query string and walks through the project descriptor to find the correct
     * element. This method will silently fail if an invalid query was provided; in such a case the project descriptor
     * is returned.
     *
     * @param string            $query
     * @param ProjectDescriptor $project
     *
     * @return \Traversable|mixed[]
     */
    protected function getListOfNodes($query, ProjectDescriptor $project)
    {
        if ($query) {
            $node = $this->walkObjectTree($project, $query);

            if (!is_array($node) && (!$node instanceof \Traversable)) {
                $node = array($node);
            }

            return $node;
        }

        return array($project);
    }

    /**
     * Walks an object graph and/or array using a twig query string.
     *
     * Note: this method is public because it is used in a closure in {{@see getDestinationPath()}}.
     *
     * @param \Traversable|mixed $objectOrArray
     * @param string             $query         A path to walk separated by dots, i.e. `namespace.namespaces`.
     *
     * @todo move this to a separate class and make it more flexible.
     *
     * @return mixed
     */
    public function walkObjectTree($objectOrArray, $query)
    {
        $node = $objectOrArray;
        $objectPath = explode('.', $query);

        // walk through the tree
        foreach ($objectPath as $pathNode) {
            if (is_array($node)) {
                if (isset($node[$pathNode])) {
                    $node = $node[$pathNode];
                    continue;
                }
            } elseif (is_object($node)) {
                if (isset($node->$pathNode) || (method_exists($node, '__get') && $node->$pathNode)) {
                    $node = $node->$pathNode;
                    continue;
                } elseif (method_exists($node, $pathNode)) {
                    $node = $node->$pathNode();
                    continue;
                } elseif (method_exists($node, 'get' . $pathNode)) {
                    $pathNode = 'get' . $pathNode;
                    $node = $node->$pathNode();
                    continue;
                } elseif (method_exists($node, 'is' . $pathNode)) {
                    $pathNode = 'is' . $pathNode;
                    $node = $node->$pathNode();
                    continue;
                }
            }

            return null;
        }

        return $node;
    }

    /**
     * Initializes the Twig environment with the template, base extension and additionally defined extensions.
     *
     * @param ProjectDescriptor $project
     * @param Transformation    $transformation
     * @param string            $destination
     *
     * @return \Twig_Environment
     */
    protected function initializeEnvironment(ProjectDescriptor $project, Transformation $transformation, $destination)
    {
        $callingTemplatePath = $this->getTemplatePath($transformation);

        $baseTemplatesPath = $transformation->getTransformer()->getTemplates()->getTemplatesPath();

        $templateFolders = array(
            $baseTemplatesPath . '/..' . DIRECTORY_SEPARATOR . $callingTemplatePath,
            // http://twig.sensiolabs.org/doc/recipes.html#overriding-a-template-that-also-extends-itself
            $baseTemplatesPath
        );

        // get all invoked template paths, they overrule the calling template path
        /** @var Template $template */
        foreach ($transformation->getTransformer()->getTemplates() as $template) {
            $path = $baseTemplatesPath . DIRECTORY_SEPARATOR . $template->getName();
            array_unshift($templateFolders, $path);
        }

        $env = new \Twig_Environment(
            new \Twig_Loader_Filesystem($templateFolders),
            array('cache' => sys_get_temp_dir() . '/phpdoc-twig-cache')
        );

        $this->addPhpDocumentorExtension($project, $transformation, $destination, $env);
        $this->addExtensionsFromTemplateConfiguration($transformation, $project, $env);

        return $env;
    }

    /**
     * Adds the phpDocumentor base extension to the Twig Environment.
     *
     * @param ProjectDescriptor $project
     * @param Transformation    $transformation
     * @param string            $destination
     * @param \Twig_Environment $twigEnvironment
     *
     * @return void
     */
    protected function addPhpDocumentorExtension(
        ProjectDescriptor $project,
        Transformation $transformation,
        $destination,
        \Twig_Environment $twigEnvironment
    ) {
        $base_extension = new Extension($project, $transformation);
        $base_extension->setDestination(
            substr($destination, strlen($transformation->getTransformer()->getTarget()) + 1)
        );
        $base_extension->setRouters($this->routers);
        $base_extension->setTranslator($this->translator);
        $twigEnvironment->addExtension($base_extension);
    }

    /**
     * Tries to add any custom extensions that have been defined in the template or the transformation's configuration.
     *
     * This method will read the `twig-extension` parameter of the transformation (which inherits the template's
     * parameter set) and try to add those extensions to the environment.
     *
     * @param Transformation    $transformation
     * @param ProjectDescriptor $project
     * @param \Twig_Environment $twigEnvironment
     *
     * @throws \InvalidArgumentException if a twig-extension should be loaded but it could not be found.
     *
     * @return void
     */
    protected function addExtensionsFromTemplateConfiguration(
        Transformation $transformation,
        ProjectDescriptor $project,
        \Twig_Environment $twigEnvironment
    ) {
        $isDebug = $transformation->getParameter('twig-debug')
            ? $transformation->getParameter('twig-debug')->getValue()
            : false;
        if ($isDebug == 'true') {
            $twigEnvironment->enableDebug();
            $twigEnvironment->addExtension(new \Twig_Extension_Debug());
        }

        /** @var Template\Parameter $extension */
        foreach ($transformation->getParametersWithKey('twig-extension') as $extension) {
            $extensionValue = $extension->getValue();
            if (!class_exists($extensionValue)) {
                throw new \InvalidArgumentException('Unknown twig extension: ' . $extensionValue);
            }

            // to support 'normal' Twig extensions we check the interface to determine what instantiation to do.
            $implementsInterface = in_array(
                'phpDocumentor\Plugin\Core\Twig\ExtensionInterface',
                class_implements($extensionValue)
            );

            $twigEnvironment->addExtension(
                $implementsInterface ? new $extensionValue($project, $transformation) : new $extensionValue()
            );
        }
    }

    /**
     * Uses the currently selected node and transformation to assemble the destination path for the file.
     *
     * The Twig writer accepts the use of a Query to be able to generate output for multiple objects using the same
     * template.
     *
     * The given node is the result of such a query, or if no query given the selected element, and the transformation
     * contains the destination file.
     *
     * Since it is important to be able to generate a unique name per element can the user provide a template variable
     * in the name of the file.
     * Such a template variable always resides between double braces and tries to take the node value of a given
     * query string.
     *
     * Example:
     *
     *   An artifact stating `classes/{{name}}.html` will try to find the
     *   node 'name' as a child of the given $node and use that value instead.
     *
     * @param DescriptorAbstract $node
     * @param Transformation     $transformation
     *
     * @throws \InvalidArgumentException if no artifact is provided and no routing rule matches.
     * @throws \UnexpectedValueException if the provided node does not contain anything.
     *
     * @return string|false returns the destination location or false if generation should be aborted.
     */
    protected function getDestinationPath($node, Transformation $transformation)
    {
        $writer = $this;

        if (!$node) {
            throw new \UnexpectedValueException(
                'The transformation node in the twig writer is not expected to be false or null'
            );
        }

        if (!$transformation->getArtifact()) {
            $rule = $this->routers->match($node);
            if (!$rule) {
                throw new \InvalidArgumentException(
                    'No matching routing rule could be found for the given node, please provide an artifact location, '
                    . 'encountered: ' . ($node === null ? 'NULL' : get_class($node))
                );
            }

            $rule = new ForFileProxy($rule);
            $url  = $rule->generate($node);
            if ($url === false || $url[0] !== DIRECTORY_SEPARATOR) {
                return false;
            }
            $path = $transformation->getTransformer()->getTarget() . str_replace('/', DIRECTORY_SEPARATOR, $url);
        } else {
            $path = $transformation->getTransformer()->getTarget()
                . DIRECTORY_SEPARATOR . $transformation->getArtifact();
        }

        $destination = preg_replace_callback(
            '/{{([^}]+)}}/u',
            function ($query) use ($node, $writer) {
                // strip any surrounding \ or /
                return trim((string) $writer->walkObjectTree($node, $query[1]), '\\/');
            },
            $path
        );


        // replace any \ with the directory separator to be compatible with the
        // current filesystem and allow the next file_exists to do its work
        $destination = str_replace(array('/','\\'), DIRECTORY_SEPARATOR, $destination);

        // create directory if it does not exist yet
        if (!file_exists(dirname($destination))) {
            mkdir(dirname($destination), 0777, true);
        }

        return $destination;
    }

    /**
     * Returns the path belonging to the template.
     *
     * @param Transformation $transformation
     *
     * @return string
     */
    protected function getTemplatePath($transformation)
    {
        $parts = preg_split('[\\\\|/]', $transformation->getSource());

        return $parts[0] . DIRECTORY_SEPARATOR . $parts[1];
    }

    /**
     * Sets the routers that can be used to determine the path of links.
     *
     * @param Queue $routers
     *
     * @return void
     */
    public function setRouters(Queue $routers)
    {
        $this->routers = $routers;
    }

    /**
     * @param \phpDocumentor\Translator $translator
     */
    public function setTranslator($translator)
    {
        $this->translator = $translator;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core\Transformer\Writer;

use phpDocumentor\Descriptor\Validator\Error;
use phpDocumentor\Transformer\Writer\WriterAbstract;
use phpDocumentor\Transformer\Writer\Translatable;
use phpDocumentor\Application;
use phpDocumentor\Descriptor\ArgumentDescriptor;
use phpDocumentor\Descriptor\ClassDescriptor;
use phpDocumentor\Descriptor\ConstantDescriptor;
use phpDocumentor\Descriptor\DescriptorAbstract;
use phpDocumentor\Descriptor\FileDescriptor;
use phpDocumentor\Descriptor\FunctionDescriptor;
use phpDocumentor\Descriptor\InterfaceDescriptor;
use phpDocumentor\Descriptor\MethodDescriptor;
use phpDocumentor\Descriptor\ProjectDescriptor;
use phpDocumentor\Descriptor\PropertyDescriptor;
use phpDocumentor\Descriptor\TraitDescriptor;
use phpDocumentor\Plugin\Core\Transformer\Behaviour\Tag\AuthorTag;
use phpDocumentor\Plugin\Core\Transformer\Behaviour\Tag\CoversTag;
use phpDocumentor\Plugin\Core\Transformer\Behaviour\Tag\IgnoreTag;
use phpDocumentor\Plugin\Core\Transformer\Behaviour\Tag\InternalTag;
use phpDocumentor\Plugin\Core\Transformer\Behaviour\Tag\LicenseTag;
use phpDocumentor\Plugin\Core\Transformer\Behaviour\Tag\MethodTag;
use phpDocumentor\Plugin\Core\Transformer\Behaviour\Tag\ParamTag;
use phpDocumentor\Plugin\Core\Transformer\Behaviour\Tag\PropertyTag;
use phpDocumentor\Plugin\Core\Transformer\Behaviour\Tag\ReturnTag;
use phpDocumentor\Plugin\Core\Transformer\Behaviour\Tag\UsesTag;
use phpDocumentor\Plugin\Core\Transformer\Behaviour\Tag\VarTag;
use phpDocumentor\Reflection\BaseReflector;
use phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Transformer\Transformation;
use phpDocumentor\Transformer\Transformer;
use phpDocumentor\Translator;

/**
 * Converts the structural information of phpDocumentor into an XML file.
 *
 * @todo this class currently only contains the old AST format for phpDocumentor; refactor!
 * @todo merge checkstyle writer into this one with query checkstyle
 * @todo the packages may not be propagated correctly, check it
 */
class Xml extends WriterAbstract implements Translatable
{
    /** @var \DOMDocument $xml */
    protected $xml;

    /** @var Translator $translator */
    protected $translator;

    /**
     * Returns an instance of the object responsible for translating content.
     *
     * @return Translator
     */
    public function getTranslator()
    {
        return $this->translator;
    }

    /**
     * Sets a new object capable of translating strings on this writer.
     *
     * @param Translator $translator
     *
     * @return void
     */
    public function setTranslator(Translator $translator)
    {
        $this->translator = $translator;
    }

    /**
     * This method generates the AST output
     *
     * @param ProjectDescriptor $project        Document containing the structure.
     * @param Transformation    $transformation Transformation to execute.
     *
     * @return void
     */
    public function transform(ProjectDescriptor $project, Transformation $transformation)
    {
        $artifact = $this->getDestinationPath($transformation);
        $this->xml = new \DOMDocument('1.0', 'utf-8');
        $this->xml->formatOutput = true;
        $document_element = new \DOMElement('project');
        $this->xml->appendChild($document_element);

        $document_element->setAttribute('title', $project->getName());
        $document_element->setAttribute('version', Application::$VERSION);

        $this->buildPartials($document_element, $project);

        $transformer = $transformation->getTransformer();

        foreach ($project->getFiles() as $file) {
            $this->buildFile($document_element, $file, $transformer);
        }

        $this->finalize($project);
        file_put_contents($artifact, $this->xml->saveXML());
    }

    protected function buildPartials(\DOMElement $parent, ProjectDescriptor $project)
    {
        $child = new \DOMElement('partials');
        $parent->appendChild($child);
        foreach ($project->getPartials() as $name => $element) {
            $partial = new \DOMElement('partial');
            $child->appendChild($partial);
            $partial->setAttribute('name', $name);
            $partial->appendChild(new \DOMText($element));
        }
    }

    protected function buildFile(
        \DOMElement $parent,
        FileDescriptor $file,
        Transformer $transformer
    ) {
        $child = new \DOMElement('file');
        $parent->appendChild($child);

        $path = ltrim($file->getPath(), './');
        $child->setAttribute('path', $path);
        $child->setAttribute(
            'generated-path',
            $transformer->generateFilename($path)
        );
        $child->setAttribute('hash', $file->getHash());

        $this->buildDocBlock($child, $file);

        // add namespace aliases
        foreach ($file->getNamespaceAliases() as $alias => $namespace) {
            $alias_obj = new \DOMElement('namespace-alias', $namespace);
            $child->appendChild($alias_obj);
            $alias_obj->setAttribute('name', $alias);
        }

        /** @var ConstantDescriptor $constant */
        foreach ($file->getConstants() as $constant) {
            $this->buildConstant($child, $constant);
        }

        /** @var FunctionDescriptor $function */
        foreach ($file->getFunctions() as $function) {
            $this->buildFunction($child, $function);
        }

        /** @var InterfaceDescriptor $interface */
        foreach ($file->getInterfaces() as $interface) {
            $this->buildInterface($child, $interface);
        }

        /** @var ClassDescriptor $class */
        foreach ($file->getClasses() as $class) {
            $this->buildClass($child, $class);
        }

        // add markers
        if (count($file->getMarkers()) > 0) {
            $markers = new \DOMElement('markers');
            $child->appendChild($markers);

            foreach ($file->getMarkers() as $marker) {
                $marker_obj = new \DOMElement(strtolower($marker['type']));
                $markers->appendChild($marker_obj);

                $marker_obj->appendChild(new \DOMText(trim($marker['message'])));
                $marker_obj->setAttribute('line', $marker['line']);
            }
        }

        if (count($file->getErrors()) > 0) {
            $parse_errors = new \DOMElement('parse_markers');
            $child->appendChild($parse_errors);

            /** @var Error $error */
            foreach ($file->getAllErrors() as $error) {
                $this->createErrorEntry($error, $parse_errors);
            }
        }

        // if we want to include the source for each file; append a new
        // element 'source' which contains a compressed, encoded version
        // of the source
        if ($file->getSource()) {
            $child->appendChild(new \DOMElement('source', base64_encode(gzcompress($file->getSource()))));
        }
    }

    /**
     * Creates an entry in the ParseErrors collection of a file for a given error.
     *
     * @param Error       $error
     * @param \DOMElement $parse_errors
     *
     * @return void
     */
    protected function createErrorEntry($error, $parse_errors)
    {
        $marker_obj = new \DOMElement(strtolower($error->getSeverity()));
        $parse_errors->appendChild($marker_obj);

        $message = ($this->getTranslator())
            ? vsprintf($this->getTranslator()->translate($error->getCode()), $error->getContext())
            : $error->getCode();

        $marker_obj->appendChild(new \DOMText($message));
        $marker_obj->setAttribute('line', $error->getLine());
        $marker_obj->setAttribute('code', $error->getCode());
    }

    /**
     * Retrieves the destination location for this artifact.
     *
     * @param Transformation $transformation
     *
     * @return string
     */
    protected function getDestinationPath(Transformation $transformation)
    {
        return $transformation->getTransformer()->getTarget()
            . DIRECTORY_SEPARATOR . $transformation->getArtifact();
    }

    /**
     * Exports the given constant to the parent XML element.
     *
     * This method creates a new child element on the given parent XML element
     * and takes the properties of the Reflection argument and sets the
     * elements and attributes on the child.
     *
     * If a child DOMElement is provided then the properties and attributes are
     * set on this but the child element is not appended onto the parent. This
     * is the responsibility of the invoker. Essentially this means that the
     * $parent argument is ignored in this case.
     *
     * @param \DOMElement        $parent   The parent element to augment.
     * @param ConstantDescriptor $constant The data source.
     * @param \DOMElement        $child    Optional: child element to use instead of creating a new one on the $parent.
     *
     * @return void
     */
    public function buildConstant(\DOMElement $parent, ConstantDescriptor $constant, \DOMElement $child = null)
    {
        if (!$constant->getName()) {
            return;
        }

        if (!$child) {
            $child = new \DOMElement('constant');
            $parent->appendChild($child);
        }

        $namespace = $constant->getNamespace()
            ? $constant->getNamespace()
            : $parent->getAttribute('namespace');
        $child->setAttribute('namespace', ltrim($namespace, '\\'));
        $child->setAttribute('line', $constant->getLine());

        $child->appendChild(new \DOMElement('name', $constant->getName()));
        $child->appendChild(new \DOMElement('full_name', $constant->getFullyQualifiedStructuralElementName()));

        $child->appendChild(new \DOMElement('value'))->appendChild(new \DOMText($constant->getValue()));

        $this->buildDocBlock($child, $constant);
    }

    /**
     * Export this function definition to the given parent DOMElement.
     *
     * @param \DOMElement        $parent   Element to augment.
     * @param FunctionDescriptor $function Element to export.
     * @param \DOMElement        $child    if supplied this element will be augmented instead of freshly added.
     *
     * @return void
     */
    public function buildFunction(\DOMElement $parent, FunctionDescriptor $function, \DOMElement $child = null)
    {
        if (!$child) {
            $child = new \DOMElement('function');
            $parent->appendChild($child);
        }

        $namespace = $function->getNamespace()
            ? $function->getNamespace()
            : $parent->getAttribute('namespace');
        $child->setAttribute('namespace', ltrim($namespace, '\\'));
        $child->setAttribute('line', $function->getLine());

        $child->appendChild(new \DOMElement('name', $function->getName()));
        $child->appendChild(new \DOMElement('full_name', $function->getFullyQualifiedStructuralElementName()));

        $this->buildDocBlock($child, $function);

        foreach ($function->getArguments() as $argument) {
            $this->buildArgument($child, $argument);
        }
    }

    /**
     * Exports the given reflection object to the parent XML element.
     *
     * This method creates a new child element on the given parent XML element
     * and takes the properties of the Reflection argument and sets the
     * elements and attributes on the child.
     *
     * If a child DOMElement is provided then the properties and attributes are
     * set on this but the child element is not appended onto the parent. This
     * is the responsibility of the invoker. Essentially this means that the
     * $parent argument is ignored in this case.
     *
     * @param \DOMElement        $parent   The parent element to augment.
     * @param ArgumentDescriptor $argument The data source.
     * @param \DOMElement        $child    Optional: child element to use instead of creating a new one on the $parent.
     *
     * @return void
     */
    public function buildArgument(\DOMElement $parent, ArgumentDescriptor $argument, \DOMElement $child = null)
    {
        if (!$child) {
            $child = new \DOMElement('argument');
            $parent->appendChild($child);
        }

        $child->setAttribute('line', $argument->getLine());
        $child->setAttribute('by_reference', var_export($argument->isByReference(), true));
        $child->appendChild(new \DOMElement('name', $argument->getName()));
        $child->appendChild(new \DOMElement('default'))
            ->appendChild(new \DOMText($argument->getDefault()));

        $types = $argument->getTypes();
        $child->appendChild(new \DOMElement('type', implode('|', $types)));
    }

    /**
     * Exports the given reflection object to the parent XML element.
     *
     * This method creates a new child element on the given parent XML element
     * and takes the properties of the Reflection argument and sets the
     * elements and attributes on the child.
     *
     * If a child DOMElement is provided then the properties and attributes are
     * set on this but the child element is not appended onto the parent. This
     * is the responsibility of the invoker. Essentially this means that the
     * $parent argument is ignored in this case.
     *
     * @param \DOMElement     $parent The parent element to augment.
     * @param ClassDescriptor $class  The data source.
     * @param \DOMElement     $child  Optional: child element to use instead of creating a
     *      new one on the $parent.
     *
     * @return void
     */
    public function buildClass(\DOMElement $parent, ClassDescriptor $class, \DOMElement $child = null)
    {
        if (!$child) {
            $child = new \DOMElement('class');
            $parent->appendChild($child);
        }

        $child->setAttribute('final', $class->isFinal() ? 'true' : 'false');
        $child->setAttribute('abstract', $class->isAbstract() ? 'true' : 'false');

        $parentFqcn = is_string($class->getParent())
            ? $class->getParent()
            : $class->getParent()->getFullyQualifiedStructuralElementName();
        $child->appendChild(new \DOMElement('extends', $parentFqcn));

        /** @var InterfaceDescriptor $interface */
        foreach ($class->getInterfaces() as $interface) {
            $interfaceFqcn = is_string($interface)
                ? $interface
                : $interface->getFullyQualifiedStructuralElementName();
            $child->appendChild(new \DOMElement('implements', $interfaceFqcn));
        }

        if ($child === null) {
            $child = new \DOMElement('interface');
            $parent->appendChild($child);
        }

        $namespace = $class->getNamespace()->getFullyQualifiedStructuralElementName();
        $child->setAttribute('namespace', ltrim($namespace, '\\'));
        $child->setAttribute('line', $class->getLine());

        $child->appendChild(new \DOMElement('name', $class->getName()));
        $child->appendChild(new \DOMElement('full_name', $class->getFullyQualifiedStructuralElementName()));

        $this->buildDocBlock($child, $class);

        foreach ($class->getConstants() as $constant) {
            // TODO #840: Workaround; for some reason there are NULLs in the constants array.
            if ($constant) {
                $this->buildConstant($child, $constant);
            }
        }

        foreach ($class->getProperties() as $property) {
            // TODO #840: Workaround; for some reason there are NULLs in the properties array.
            if ($property) {
                $this->buildProperty($child, $property);
            }
        }

        foreach ($class->getMethods() as $method) {
            // TODO #840: Workaround; for some reason there are NULLs in the methods array.
            if ($method) {
                $this->buildMethod($child, $method);
            }
        }
    }

    /**
     * Exports the given reflection object to the parent XML element.
     *
     * This method creates a new child element on the given parent XML element
     * and takes the properties of the Reflection argument and sets the
     * elements and attributes on the child.
     *
     * If a child DOMElement is provided then the properties and attributes are
     * set on this but the child element is not appended onto the parent. This
     * is the responsibility of the invoker. Essentially this means that the
     * $parent argument is ignored in this case.
     *
     * @param \DOMElement     $parent The parent element to augment.
     * @param TraitDescriptor $trait  The data source.
     * @param \DOMElement     $child  Optional: child element to use instead of creating a
     *      new one on the $parent.
     *
     * @return void
     */
    public function buildTrait(\DOMElement $parent, TraitDescriptor $trait, \DOMElement $child = null)
    {
        if (!$child) {
            $child = new \DOMElement('trait');
            $parent->appendChild($child);
        }

        $child->setAttribute('final', $trait->isFinal() ? 'true' : 'false');
        $child->setAttribute('abstract', $trait->isAbstract() ? 'true' : 'false');

        $namespace = $trait->getNamespace();
        $child->setAttribute('namespace', ltrim($namespace, '\\'));
        $child->setAttribute('line', $trait->getLine());

        $child->appendChild(new \DOMElement('name', $trait->getName()));
        $child->appendChild(new \DOMElement('full_name', $trait->getFullyQualifiedStructuralElementName()));

        $this->buildDocBlock($child, $trait);

        foreach ($trait->getProperties() as $property) {
            $this->buildProperty($child, $property);
        }

        foreach ($trait->getMethods() as $method) {
            $this->buildMethod($child, $method);
        }
    }

    /**
     * Exports the given reflection object to the parent XML element.
     *
     * This method creates a new child element on the given parent XML element
     * and takes the properties of the Reflection argument and sets the
     * elements and attributes on the child.
     *
     * If a child DOMElement is provided then the properties and attributes are
     * set on this but the child element is not appended onto the parent. This
     * is the responsibility of the invoker. Essentially this means that the
     * $parent argument is ignored in this case.
     *
     * @param \DOMElement                         $parent The parent element to augment.
     * @param InterfaceDescriptor $interface  The data source.
     * @param \DOMElement                         $child  Optional: child element to use instead of creating a
     *      new one on the $parent.
     *
     * @return void
     */
    public function buildInterface(\DOMElement $parent, InterfaceDescriptor $interface, \DOMElement $child = null)
    {
        if (!$child) {
            $child = new \DOMElement('interface');
            $parent->appendChild($child);
        }

        /** @var InterfaceDescriptor $parentInterface */
        foreach ($interface->getParent() as $parentInterface) {
            $parentFqcn = is_string($parentInterface) === false
                ? $parentInterface->getFullyQualifiedStructuralElementName()
                : $parentInterface;
            $child->appendChild(new \DOMElement('extends', $parentFqcn));
        }

        $namespace = $interface->getNamespace()->getFullyQualifiedStructuralElementName();
        $child->setAttribute('namespace', ltrim($namespace, '\\'));
        $child->setAttribute('line', $interface->getLine());

        $child->appendChild(new \DOMElement('name', $interface->getName()));
        $child->appendChild(new \DOMElement('full_name', $interface->getFullyQualifiedStructuralElementName()));

        $this->buildDocBlock($child, $interface);

        foreach ($interface->getConstants() as $constant) {
            $this->buildConstant($child, $constant);
        }

        foreach ($interface->getMethods() as $method) {
            $this->buildMethod($child, $method);
        }
    }

    /**
     * Export the given property definition to the provided parent element.
     *
     * @param \DOMElement        $parent   Element to augment.
     * @param PropertyDescriptor $property Element to export.
     *
     * @return void
     */
    public function buildProperty(\DOMElement $parent, PropertyDescriptor $property)
    {
        $child = new \DOMElement('property');
        $parent->appendChild($child);

        $child->setAttribute('static', $property->isStatic() ? 'true' : 'false');
        $child->setAttribute('visibility', $property->getVisibility());

        $child->setAttribute('line', $property->getLine());

        $namespaceFqnn = $property->getNamespace()
            ? $property->getNamespace()->getFullyQualifiedStructuralElementName()
            : $parent->getAttribute('namespace');
        $child->setAttribute('namespace', $namespaceFqnn);

        $child->appendChild(new \DOMElement('name', '$' . $property->getName()));
        $child->appendChild(new \DOMElement('default'))
            ->appendChild(new \DOMText($property->getDefault()));

        $this->buildDocBlock($child, $property);
    }

    /**
     * Export the given reflected method definition to the provided parent element.
     *
     * @param \DOMElement     $parent Element to augment.
     * @param MethodDescriptor $method Element to export.
     *
     * @return \DOMElement
     */
    public function buildMethod(\DOMElement $parent, MethodDescriptor $method)
    {
        $child = new \DOMElement('method');
        $parent->appendChild($child);

        $child->setAttribute('final', $method->isFinal() ? 'true' : 'false');
        $child->setAttribute('abstract', $method->isAbstract() ? 'true' : 'false');
        $child->setAttribute('static', $method->isStatic() ? 'true' : 'false');
        $child->setAttribute('visibility', $method->getVisibility());

        $namespaceFqnn = $method->getNamespace()
            ? $method->getNamespace()->getFullyQualifiedStructuralElementName()
            : $parent->getAttribute('namespace');
        $child->setAttribute('namespace', $namespaceFqnn);
        $child->setAttribute('line', $method->getLine());

        $child->appendChild(new \DOMElement('name', $method->getName()));
        $child->appendChild(new \DOMElement('full_name', $method->getFullyQualifiedStructuralElementName()));

        $this->buildDocBlock($child, $method);

        foreach ($method->getArguments() as $argument) {
            $this->buildArgument($child, $argument);
        }

        return $child;
    }

    /**
     * Exports the given reflection object to the parent XML element.
     *
     * This method creates a new child element on the given parent XML element
     * and takes the properties of the Reflection argument and sets the
     * elements and attributes on the child.
     *
     * If a child DOMElement is provided then the properties and attributes are
     * set on this but the child element is not appended onto the parent. This
     * is the responsibility of the invoker. Essentially this means that the
     * $parent argument is ignored in this case.
     *
     * @param \DOMElement        $parent  The parent element to augment.
     * @param DescriptorAbstract $element The data source.
     *
     * @return void
     */
    public function buildDocBlock(\DOMElement $parent, DescriptorAbstract $element)
    {
        $child = new \DOMElement('docblock');
        $parent->appendChild($child);

        $child->setAttribute('line', $element->getLine());
        $parent->setAttribute(
            'package',
            str_replace('&', '&amp;', ltrim($element->getPackage(), '\\'))
        );

        $this->addDescription($child, $element);
        $this->addLongDescription($child, $element);
        $this->addTags($child, $element);
    }

    /**
     * Export this tag to the given DocBlock.
     *
     * This method also invokes the 'reflection.docblock.tag.export' which can
     * be used to augment the data. This is useful for plugins so that they
     * can provide custom tags.
     *
     * @param \DOMElement   $parent  Element to augment.
     * @param Tag           $tag     The tag to export.
     * @param BaseReflector $element Element to log from.
     *
     * @return void
     */
    public function buildDocBlockTag(\DOMElement $parent, $tag, $element)
    {
        if (!$tag) {
            // TODO #840: Workaround; for some reason there are NULLs in the tags array.
            return;
        }
        $child = new \DOMElement('tag');
        $parent->appendChild($child);

        $child->setAttribute(
            'name',
            str_replace('&', '&amp;', $tag->getName())
        );
        $child->setAttribute('line', $parent->getAttribute('line'));

        $description = '';
        //@version, @deprecated, @since
        if (method_exists($tag, 'getVersion')) {
            $description .= $tag->getVersion() . ' ';
        }
        //TODO: Other previously unsupported tags are to be "serialized" here.
        $description .= $tag->getDescription();

        $child->setAttribute(
            'description',
            str_replace('&', '&amp;', trim($description))
        );

        if (method_exists($tag, 'getTypes')) {
            $typeString = '';
            foreach ($tag->getTypes() as $type) {
                $typeString .= $type . '|';
                $typeNode = $child->appendChild(new \DOMElement('type'));
                $typeNode->appendChild(new \DOMText($type));
                $lastSlashPos = strrpos($type, '\\');
                if (false !== $lastSlashPos) {
                    $typeNode->setAttribute(
                        'link',
                        str_replace('&', '&amp;', substr($type, $lastSlashPos + 1)) . '.html'
                    );
                }
            }
            $child->setAttribute(
                'type',
                str_replace('&', '&amp;', rtrim($typeString, '|'))
            );
        }
        if (method_exists($tag, 'getVariableName')) {
            $child->setAttribute(
                'variable',
                str_replace('&', '&amp;', $tag->getVariableName())
            );
        }
        if (method_exists($tag, 'getReference')) {
            $child->setAttribute(
                'link',
                str_replace('&', '&amp;', $tag->getReference())
            );
        }
        if (method_exists($tag, 'getLink')) {
            $child->setAttribute(
                'link',
                str_replace('&', '&amp;', $tag->getLink())
            );
        }
        if (method_exists($tag, 'getMethodName')) {
            $child->setAttribute(
                'method_name',
                str_replace('&', '&amp;', $tag->getMethodName())
            );
        }
    }

    /**
     * Adds the short description of $docblock to the given node as description
     * field.
     *
     * @param \DOMElement        $node
     * @param DescriptorAbstract $element
     *
     * @return void
     */
    protected function addDescription(\DOMElement $node, DescriptorAbstract $element)
    {
        $node->appendChild(new \DOMElement('description'))
            ->appendChild(new \DOMText($element->getSummary()));
    }

    /**
     * Adds the DocBlock's long description to the $child element,
     *
     * @param \DOMElement        $child
     * @param DescriptorAbstract $element
     *
     * @return void
     */
    protected function addLongDescription(\DOMElement $child, DescriptorAbstract $element)
    {
        $child
            ->appendChild(new \DOMElement('long-description'))
            ->appendChild(new \DOMText($element->getDescription()));
    }

    /**
     * Adds each tag to the $xml_node.
     *
     * @param \DOMElement        $xml_node
     * @param DescriptorAbstract $element
     *
     * @return void
     */
    protected function addTags(\DOMElement $xml_node, $element)
    {
        foreach ($element->getTags() as $tagGroup) {
            if ($tagGroup === null) {
                continue;
            }

            foreach ($tagGroup as $tag) {
                $this->buildDocBlockTag($xml_node, $tag, $element);
            }
        }
    }

    /**
     * Finalizes the processing and executing all post-processing actions.
     *
     * This method is responsible for extracting and manipulating the data that
     * is global to the project, such as:
     *
     * - Package tree
     * - Namespace tree
     * - Marker list
     * - Deprecated elements listing
     * - Removal of objects related to visibility
     *
     * @param ProjectDescriptor $projectDescriptor
     *
     * @return void
     */
    protected function finalize(ProjectDescriptor $projectDescriptor)
    {
        // TODO: move all these behaviours to a central location for all template parsers
        $behaviour = new AuthorTag();
        $behaviour->process($this->xml);
        $behaviour = new CoversTag();
        $behaviour->process($this->xml);
        $behaviour = new IgnoreTag();
        $behaviour->process($this->xml);
        $behaviour = new InternalTag(
            $projectDescriptor->isVisibilityAllowed(ProjectDescriptor\Settings::VISIBILITY_INTERNAL)
        );
        $behaviour->process($this->xml);
        $behaviour = new LicenseTag();
        $behaviour->process($this->xml);
        $behaviour = new MethodTag();
        $behaviour->process($this->xml);
        $behaviour = new ParamTag();
        $behaviour->process($this->xml);
        $behaviour = new PropertyTag();
        $behaviour->process($this->xml);
        $behaviour = new ReturnTag();
        $behaviour->process($this->xml);
        $behaviour = new UsesTag();
        $behaviour->process($this->xml);
        $behaviour = new VarTag();
        $behaviour->process($this->xml);
        $this->buildPackageTree($this->xml);
        $this->buildNamespaceTree($this->xml);
        $this->buildDeprecationList($this->xml);
    }

    /**
     * Collects all packages and subpackages, and adds a new section in the
     * DOM to provide an overview.
     *
     * @param \DOMDocument $dom Packages are extracted and a summary inserted
     *     in this object.
     *
     * @return void
     */
    protected function buildPackageTree(\DOMDocument $dom)
    {
        $xpath = new \DOMXPath($dom);
        $packages = array();
        $qry = $xpath->query('//@package');
        for ($i = 0; $i < $qry->length; $i++) {
            if (isset($packages[$qry->item($i)->nodeValue])) {
                continue;
            }

            $packages[$qry->item($i)->nodeValue] = true;
        }

        $packages = $this->generateNamespaceTree(array_keys($packages));
        $this->generateNamespaceElements($packages, $dom->documentElement, 'package');
    }

    /**
     * Collects all namespaces and sub-namespaces, and adds a new section in
     * the DOM to provide an overview.
     *
     * @param \DOMDocument $dom Namespaces are extracted and a summary inserted
     *     in this object.
     *
     * @return void
     */
    protected function buildNamespaceTree(\DOMDocument $dom)
    {
        $xpath = new \DOMXPath($dom);
        $namespaces = array();
        $qry = $xpath->query('//@namespace');
        for ($i = 0; $i < $qry->length; $i++) {
            if (isset($namespaces[$qry->item($i)->nodeValue])) {
                continue;
            }

            $namespaces[$qry->item($i)->nodeValue] = true;
        }

        $namespaces = $this->generateNamespaceTree(array_keys($namespaces));
        $this->generateNamespaceElements($namespaces, $dom->documentElement);
    }

    /**
     * Adds a node to the xml for deprecations and the count value
     *
     * @param \DOMDocument $dom Markers are extracted and a summary inserted in this object.
     *
     * @return void
     */
    protected function buildDeprecationList(\DOMDocument $dom)
    {
        $nodes = $this->getNodeListForTagBasedQuery($dom, 'deprecated');

        $node = new \DOMElement('deprecated');
        $dom->documentElement->appendChild($node);
        $node->setAttribute('count', $nodes->length);
    }

    /**
     * Build a tag based query string and return result
     *
     * @param \DOMDocument $dom    Markers are extracted and a summary inserted
     *      in this object.
     * @param string       $marker The marker we're searching for throughout xml
     *
     * @return \DOMNodeList
     */
    protected function getNodeListForTagBasedQuery($dom, $marker)
    {
        $xpath = new \DOMXPath($dom);

        $query = '/project/file/markers/'.$marker.'|';
        $query .= '/project/file/docblock/tag[@name="'.$marker.'"]|';
        $query .= '/project/file/class/docblock/tag[@name="'.$marker.'"]|';
        $query .= '/project/file/class/*/docblock/tag[@name="'.$marker.'"]|';
        $query .= '/project/file/interface/docblock/tag[@name="'.$marker.'"]|';
        $query .= '/project/file/interface/*/docblock/tag[@name="'.$marker.'"]|';
        $query .= '/project/file/function/docblock/tag[@name="'.$marker.'"]|';
        $query .= '/project/file/constant/docblock/tag[@name="'.$marker.'"]';

        $nodes = $xpath->query($query);

        return $nodes;
    }

    /**
     * Generates a hierarchical array of namespaces with their singular name
     * from a single level list of namespaces with their full name.
     *
     * @param array $namespaces the list of namespaces as retrieved from the xml.
     *
     * @return array
     */
    protected function generateNamespaceTree($namespaces)
    {
        sort($namespaces);

        $result = array();
        foreach ($namespaces as $namespace) {
            if (!$namespace) {
                $namespace = 'global';
            }

            $namespace_list = explode('\\', $namespace);

            $node = &$result;
            foreach ($namespace_list as $singular) {
                if (!isset($node[$singular])) {
                    $node[$singular] = array();
                }

                $node = &$node[$singular];
            }
        }

        return $result;
    }

    /**
     * Recursive method to create a hierarchical set of nodes in the dom.
     *
     * @param array[]     $namespaces     the list of namespaces to process.
     * @param \DOMElement $parent_element the node to receive the children of
     *                                    the above list.
     * @param string      $node_name      the name of the summary element.
     *
     * @return void
     */
    protected function generateNamespaceElements($namespaces, $parent_element, $node_name = 'namespace')
    {
        foreach ($namespaces as $name => $sub_namespaces) {
            $node = new \DOMElement($node_name);
            $parent_element->appendChild($node);
            $node->setAttribute('name', $name);
            $fullName = $parent_element->nodeName == $node_name
                ? $parent_element->getAttribute('full_name') . '\\' . $name
                : $name;
            $node->setAttribute('full_name', $fullName);
            $this->generateNamespaceElements($sub_namespaces, $node, $node_name);
        }
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core\Transformer\Behaviour\Tag;

use Psr\Log\LogLevel;

/**
 * Behaviour that adds support for the @covers tag
 */
class CoversTag
{
    /**
     * Find all return tags that contain 'self' or '$this' and replace those
     * terms for the name of the current class' type.
     *
     * @param \DOMDocument $xml Structure source to apply behaviour onto.
     *
     * @todo split method into submethods
     *
     * @return \DOMDocument
     */
    public function process(\DOMDocument $xml)
    {
        $xpath = new \DOMXPath($xml);
        $nodes = $xpath->query('//tag[@name=\'covers\']');

        /** @var \DOMElement $node */
        foreach ($nodes as $node) {
            $refers = $node->getAttribute('refers');
            $refers_array = explode('::', $refers);

            // determine the type so we know where to put the @coveredby tag on
            $type = 'class';
            if (isset($refers_array[1])) {
                // starts with $ = property, ends with () = method,
                // otherwise constant
                $type = $refers_array[1][0] == '$' ? 'property' : 'constant';
                $type = substr($refers_array[1], -2) == '()' ? 'method' : $type;
            }

            switch ($type) {
                case 'class':
                    // escape single quotes in the class name
                    $xpath_refers = 'concat(\''.str_replace(
                        array("'", '"'),
                        array('\', "\'", \'', '\', \'"\' , \''),
                        $refers
                    ) . "', '')";

                    $qry = '/project/file/class[full_name=' . $xpath_refers . ']';
                    break;
                default:
                    $class_name = $refers_array[0];

                    // escape single quotes in the class name
                    $xpath_class_name = 'concat(\''.str_replace(
                        array("'", '"'),
                        array('\', "\'", \'', '\', \'"\' , \''),
                        $class_name
                    ) . "', '')";

                    // escape single quotes in the method name
                    $xpath_method_name = 'concat(\''.str_replace(
                        array("'", '"'),
                        array('\', "\'", \'', '\', \'"\' , \''),
                        rtrim($refers_array[1], '()')
                    ) . "', '')";

                    $qry = '/project/file/class[full_name=' . $xpath_class_name
                        . ']/'.$type.'[name=' . $xpath_method_name .']';
                    break;
            }

            /** @noinspection PhpUsageOfSilenceOperatorInspection as there is no pre-validation possible */
            $referral_nodes = @$xpath->query($qry);

            // if the query is wrong; output a Critical error and continue to
            // the next @covers
            if ($referral_nodes === false) {
                $this->log(
                    'An XPath error occurs while processing @covers, the query used was: ' . $qry,
                    LogLevel::CRITICAL
                );
                continue;
            }

            // check if the result is unique; if not we error and continue
            // to the next @covers
            if ($referral_nodes->length > 1) {
                continue;
            }

            // if there is one matching element; link them together
            if ($referral_nodes->length > 0) {
                /** @var \DOMElement $referral  */
                $referral = $referral_nodes->item(0);
                $docblock = $referral->getElementsByTagName('docblock');
                if ($docblock->length < 1) {
                    $docblock = new \DOMElement('docblock');
                    $referral->appendChild($docblock);
                } else {
                    $docblock = $docblock->item(0);
                }

                $used_by = new \DOMElement('tag');
                $docblock->appendChild($used_by);
                $used_by->setAttribute('name', 'used_by');
                $used_by->setAttribute('line', '');

                // gather the name of the referring element and set that as refers
                // attribute
                if ($node->parentNode->parentNode->nodeName == 'class') {
                    // if the element where the @covers is in is a class; nothing
                    // more than the class name need to returned
                    $referral_name = $node->parentNode->parentNode
                        ->getElementsByTagName('full_name')->item(0)->nodeValue;
                } else {

                    $referral_class_name = null;
                    if ($node->parentNode->parentNode->nodeName == 'method') {
                        // gather the name of the class where the @covers is in
                        $referral_class_name = $node->parentNode->parentNode
                            ->parentNode->getElementsByTagName('full_name')->item(0)
                            ->nodeValue;
                    }

                    // gather the name of the subelement of the class where
                    // the @covers is in
                    $referral_name = $node->parentNode->parentNode
                        ->getElementsByTagName('name')->item(0)->nodeValue;

                    // if it is a method; suffix with ()
                    if ($node->parentNode->parentNode->nodeName == 'method'
                        || $node->parentNode->parentNode->nodeName == 'function'
                    ) {
                        $referral_name .= '()';
                    }

                    // only prefix class name if this is a class member
                    if ($referral_class_name) {
                        $referral_name = $referral_class_name . '::'
                            . $referral_name;
                    }
                }

                $used_by->setAttribute('description', $referral_name);
                $used_by->setAttribute('refers', $referral_name);
            }
        }

        return $xml;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core\Transformer\Behaviour\Tag;

/**
 * Behaviour that adds support for the @param tags.
 */
class ParamTag
{
    /** @var string Make element name overrideable. */
    protected $element_name = 'param';

    /**
     * Find all the param tags and if using special characters transform
     * using markdown otherwise just add a <p> tag to be consistent.
     *
     * @param \DOMDocument $xml Structure source to apply behaviour onto.
     *
     * @return \DOMDocument
     */
    public function process(\DOMDocument $xml)
    {
        $qry = '//tag[@name=\''.$this->element_name.'\']/@description[. != ""]';

        $xpath = new \DOMXPath($xml);
        $nodes = $xpath->query($qry);

        /** @var \DOMElement $node */
        foreach ($nodes as $node) {
            // only transform using markdown if the text contains characters
            // other than word characters, whitespaces and punctuation characters.
            // This is because Markdown is a huge performance hit on the system
            if (!preg_match('/^[\w|\s|\.|,|;|\:|\&|\#]+$/', $node->nodeValue)) {
                $md = \Parsedown::instance();
                $node->nodeValue =  $md->parse($node->nodeValue);
            } else {
                // markdown will always surround the element with a paragraph;
                // we do the same here to make it consistent
                $node->nodeValue = '&lt;p&gt;' . $node->nodeValue . '&lt;/p&gt;';
            }
        }

        return $xml;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core\Transformer\Behaviour\Tag;

/**
 * Behaviour that adds support for the property tag
 */
class PropertyTag
{
    /**
     * Find all return tags that contain 'self' or '$this' and replace those
     * terms for the name of the current class' type.
     *
     * @param \DOMDocument $xml Structure source to apply behaviour onto.
     *
     * @return \DOMDocument
     */
    public function process(\DOMDocument $xml)
    {
        $xpath = new \DOMXPath($xml);
        $nodes = $xpath->query(
            '/project/file/class/docblock/tag[@name="property"]'
            .'|/project/file/class/docblock/tag[@name="property-read"]'
            .'|/project/file/class/docblock/tag[@name="property-write"]'
        );

        /** @var \DOMElement $node */
        foreach ($nodes as $node) {
            $class = $node->parentNode->parentNode;

            $property = new \DOMElement('property');
            $class->appendChild($property);

            $property->setAttribute('final', 'false');
            $property->setAttribute('static', 'false');
            $property->setAttribute('visibility', 'public');
            $property->setAttribute('line', $node->getAttribute('line'));
            $property->appendChild(
                new \DOMElement('name', $node->getAttribute('variable'))
            );
            $property->appendChild(new \DOMElement('default'));

            $docblock = new \DOMElement('docblock');
            $property->appendChild($docblock);
            $docblock->appendChild(
                new \DOMElement('description', $node->getAttribute('description'))
            );
            $docblock->appendChild(new \DOMElement('long-description'));

            $var_tag = new \DOMElement('tag');
            $docblock->appendChild($var_tag);
            $var_tag->setAttribute('name', 'var');
            $var_tag->setAttribute('description', $node->getAttribute('description'));
            $var_tag->setAttribute('type', $node->getAttribute('type'));
            $var_tag->setAttribute('line', $node->getAttribute('line'));

            $var_tag_type = new \DOMElement('type', $node->getAttribute('type'));
            $var_tag->appendChild($var_tag_type);
            $var_tag_type->setAttribute('by_reference', 'false');

            $magic_tag = new \DOMElement('tag');
            $docblock->appendChild($magic_tag);
            $magic_tag->setAttribute('name', 'magic');
            $magic_tag->setAttribute('line', $node->getAttribute('line'));

            $node->parentNode->removeChild($node);
            $docblock->appendChild($node);
        }

        return $xml;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core\Transformer\Behaviour\Tag;

/**
 * Behaviour that adds support for the return tag
 */
class ReturnTag
{
    /**
     * Find all return tags that contain 'self' or '$this' and replace those
     * terms for the name of the current class' type.
     *
     * @param \DOMDocument $xml Structure source to apply behaviour onto.
     *
     * @return \DOMDocument
     */
    public function process(\DOMDocument $xml)
    {
        $ignoreQry = '//tag[@name=\'return\' and @type=\'self\']'
            . '|//tag[@name=\'return\' and @type=\'$this\']'
            . '|//tag[@name=\'return\']/type[.=\'self\']'
            . '|//tag[@name=\'return\']/type[.=\'$this\']';

        $xpath = new \DOMXPath($xml);
        $nodes = $xpath->query($ignoreQry);

        /** @var \DOMElement $node */
        foreach ($nodes as $node) {
            // if a node with name 'type' is selected we need to reach one
            // level further.
            $docblock = ($node->nodeName == 'type')
                ? $node->parentNode->parentNode
                : $node->parentNode;

            /** @var \DOMElement $method  */
            $method = $docblock->parentNode;

            // if the method is not a method but a global function: error!
            if ($method->nodeName != 'method') {
                continue;
            }

            $type = $method->parentNode->getElementsByTagName('full_name')
                ->item(0)->nodeValue;

            // nodes with name type need to set their content; otherwise we set
            // an attribute of the class itself
            if ($node->nodeName == 'type') {
                $node->nodeValue = $type;

                // add a new tag @fluent to indicate that this is a fluent interface
                // we only add it here since there should always be a node `type`
                $fluent_tag = new \DOMElement('tag');
                $docblock->appendChild($fluent_tag);
                $fluent_tag->setAttribute('name', 'fluent');
                $fluent_tag->setAttribute(
                    'description',
                    'This method is part of a fluent interface and will return '
                    . 'the same instance'
                );
            } else {
                $node->setAttribute('type', $type);
            }

            // check if an excerpt is set and override that as well
            if ($node->hasAttribute('excerpt')
                && (($node->getAttribute('excerpt') == 'self')
                || ($node->getAttribute('excerpt') == '$this'))
            ) {
                $node->setAttribute('excerpt', $type);
            }
        }

        return $xml;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core\Transformer\Behaviour\Tag;

/**
 * Behaviour that adds support for @internal inline tag.
 */
class InternalTag
{
    /** @var boolean $internalAllowed */
    protected $internalAllowed;

    public function __construct($internalAllowed)
    {
        $this->internalAllowed = $internalAllowed;
    }

    /**
     * Converts the 'internal' tags in Long Descriptions.
     *
     * @param \DOMDocument $xml Structure source to apply behaviour onto.
     *
     * @todo This behaviours actions should be moved to the parser / Reflector builder so that it can be cached
     *     and is available to all writers.
     *
     * @return \DOMDocument
     */
    public function process(\DOMDocument $xml)
    {
        $ignoreQry = '//long-description[contains(., "{@internal")]';

        $xpath = new \DOMXPath($xml);
        $nodes = $xpath->query($ignoreQry);

        // either replace it with nothing or with the 'stored' value
        $replacement = $this->internalAllowed ? '$1' : '';

        /** @var \DOMElement $node */
        foreach ($nodes as $node) {
            $node->nodeValue = preg_replace('/\{@internal\s(.+?)\}\}/', $replacement, $node->nodeValue);
        }

        return $xml;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core\Transformer\Behaviour\Tag;

/**
 * Behaviour that adds support for the uses tag
 */
class UsesTag
{
    /**
     * Find all return tags that contain 'self' or '$this' and replace those
     * terms for the name of the current class' type.
     *
     * @param \DOMDocument $xml Structure source to apply behaviour onto.
     *
     * @todo split method into submethods
     *
     * @return \DOMDocument
     */
    public function process(\DOMDocument $xml)
    {
        $xpath = new \DOMXPath($xml);
        $nodes = $xpath->query('//tag[@name=\'uses\']');

        /** @var \DOMElement $node */
        foreach ($nodes as $node) {
            $refers = $node->getAttribute('refers');
            $refers_array = explode('::', $refers);

            // determine the type so we know where to put the @usedby tag on
            $type = 'class';
            if (isset($refers_array[1])) {
                // starts with $ = property, ends with () = method,
                // otherwise constant
                $type = $refers_array[1][0] == '$' ? 'property' : 'constant';
                $type = substr($refers_array[1], -2) == '()' ? 'method' : $type;
            }

            switch ($type) {
                case 'class':
                    // escape single quotes in the class name
                    $xpath_refers = 'concat(\''.str_replace(
                        array("'", '"'),
                        array('\', "\'", \'', '\', \'"\' , \''),
                        $refers
                    ) . "', '')";

                    $qry = '/project/file/class[full_name=' . $xpath_refers . ']';
                    break;
                default:
                    $class_name = $refers_array[0];

                    // escape single quotes in the class name
                    $xpath_class_name = 'concat(\''.str_replace(
                        array("'", '"'),
                        array('\', "\'", \'', '\', \'"\' , \''),
                        $class_name
                    ) . "', '')";

                    // escape single quotes in the method name
                    $xpath_method_name = 'concat(\''.str_replace(
                        array("'", '"'),
                        array('\', "\'", \'', '\', \'"\' , \''),
                        rtrim($refers_array[1], '()')
                    ) . "', '')";

                    $qry = '/project/file/class[full_name=' . $xpath_class_name
                        . ']/'.$type.'[name=' . $xpath_method_name .']';
                    break;
            }

            /** @noinspection PhpUsageOfSilenceOperatorInspection as there is no pre-validation possible */
            $referral_nodes = @$xpath->query($qry);

            // if the query is wrong; output a Critical error and continue to
            // the next @uses
            if ($referral_nodes === false) {
                continue;
            }

            // check if the result is unique; if not we error and continue
            // to the next @uses
            if ($referral_nodes->length > 1) {
                continue;
            }

            // if there is one matching element; link them together
            if ($referral_nodes->length > 0) {
                /** @var \DOMElement $referral */
                $referral = $referral_nodes->item(0);
                $docblock = $referral->getElementsByTagName('docblock');
                if ($docblock->length < 1) {
                    $docblock = new \DOMElement('docblock');
                    $referral->appendChild($docblock);
                } else {
                    $docblock = $docblock->item(0);
                }

                $used_by = new \DOMElement('tag');
                $docblock->appendChild($used_by);
                $used_by->setAttribute('name', 'used_by');
                $used_by->setAttribute('line', '');

                // gather the name of the referring element and set that as refers
                // attribute
                if ($node->parentNode->parentNode->nodeName == 'class') {
                    // if the element where the @uses is in is a class; nothing
                    // more than the class name need to returned
                    $referral_name = $node->parentNode->parentNode
                        ->getElementsByTagName('full_name')->item(0)->nodeValue;
                } else {

                    $referral_class_name = null;
                    if ($node->parentNode->parentNode->nodeName == 'method') {
                        // gather the name of the class where the @uses is in
                        $referral_class_name = $node->parentNode->parentNode
                            ->parentNode->getElementsByTagName('full_name')->item(0)
                            ->nodeValue;
                    }

                    // gather the name of the subelement of the class where
                    // the @uses is in
                    $referral_name = $node->parentNode->parentNode
                        ->getElementsByTagName('name')->item(0)->nodeValue;

                    // if it is a method; suffix with ()
                    if ($node->parentNode->parentNode->nodeName == 'method'
                        || $node->parentNode->parentNode->nodeName == 'function'
                    ) {
                        $referral_name .= '()';
                    }

                    // only prefix class name if this is a class member
                    if ($referral_class_name) {
                        $referral_name = $referral_class_name . '::'
                            . $referral_name;
                    }
                }

                $used_by->setAttribute('description', $referral_name);
                $used_by->setAttribute('refers', $referral_name);
            }
        }

        return $xml;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core\Transformer\Behaviour\Tag;

/**
 * Behaviour that links to email addresses in the @author tag.
 */
class AuthorTag
{
    /**
     * Find all return tags that contain 'self' or '$this' and replace those
     * terms for the name of the current class' type.
     *
     * @param \DOMDocument $xml Structure source to apply behaviour onto.
     *
     * @return \DOMDocument
     */
    public function process(\DOMDocument $xml)
    {
        // matches:
        // - foo@bar.com
        // - <foo@bar.com>
        // - Some Name <foo@bar.com>
        // ignores leading and trailing whitespace
        // requires angled brackets when a name is given (that's what the
        //   two (?(1)) conditions do)
        // requires closing angled bracket if email address is given with an
        //   opening angled bracket but no name (that's what the (?(3))
        //   condition is for)
        $regex = '#^\s*(?P<name>[^<]+?)?\s*((?(1)<|<?)(?:mailto:)?'
            .'(?P<email>\b[a-z0-9._%-]+@[a-z0-9.-]+\.[a-z]{2,4}\b)'
            .'(?(1)>|(?(3)>|>?)))\s*$#u';

        $xpath = new \DOMXPath($xml);
        $nodes = $xpath->query('//tag[@name="author"]/@description');

        /** @var \DOMElement $node */
        foreach ($nodes as $node) {

            // FIXME: #193
            if (preg_match($regex, $node->nodeValue, $matches)) {
                if ($matches['name']) {
                    $value = $matches['name'];
                } else {
                    // in case there were <> but no name... this cleans up the
                    // output a bit
                    $value = $matches['email'];
                }

                $node->nodeValue = $value;
                $node->parentNode->setAttribute(
                    'link',
                    'mailto:' . $matches['email']
                );
            }
        }

        return $xml;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core\Transformer\Behaviour\Tag;

/**
 * Behaviour that enables links to URLs in the @license tag.
 */
class LicenseTag
{
    /**
     * Find all return tags that contain 'self' or '$this' and replace those
     * terms for the name of the current class' type.
     *
     * @param \DOMDocument $xml Structure source to apply behaviour onto.
     *
     * @return \DOMDocument
     */
    public function process(\DOMDocument $xml)
    {
        $licenseMap = array(
            '#^\s*(GPL|GNU General Public License)((\s?v?|version)?2)\s*$#i'
                => 'http://opensource.org/licenses/GPL-2.0',
            '#^\s*(GPL|GNU General Public License)((\s?v?|version)?3?)\s*$#i'
                => 'http://opensource.org/licenses/GPL-3.0',
            '#^\s*(LGPL|GNU (Lesser|Library) (General Public License|GPL))'
                .'((\s?v?|version)?2(\.1)?)\s*$#i'
                => 'http://opensource.org/licenses/LGPL-2.1',
            '#^\s*(LGPL|GNU (Lesser|Library) (General Public License|GPL))'
                .'((\s?v?|version)?3?)\s*$#i'
                => 'http://opensource.org/licenses/LGPL-3.0',
            '#^\s*((new |revised |modified |three-clause |3-clause )BSD'
                .'( License)?)\s*$#i'
                => 'http://opensource.org/licenses/BSD-3-Clause',
            '#^\s*((simplified |two-clause |2-clause |Free)BSD)( License)?\s*$#i'
                => 'http://opensource.org/licenses/BSD-2-Clause',
            '#^\s*MIT( License)?\s*$#i' => 'http://opensource.org/licenses/MIT',
        );

        $xpath = new \DOMXPath($xml);
        $nodes = $xpath->query('//tag[@name="license"]/@description');

        /** @var \DOMElement $node */
        foreach ($nodes as $node) {

            $license = $node->nodeValue;

            // FIXME: migrate to '#^' . PHPDOC::LINK_REGEX . '(\s+(?P<text>.+))
            // ?$#u' once that const exists
            if (preg_match(
                '#^(?i)\b(?P<url>(?:https?://|www\d{0,3}\.|[a-z0-9.\-]+\.'
                .'[a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+'
                .'(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|'
                .'[^\s`!()\[\]{};:\'".,<>?«»“”‘’]))(\s+(?P<text>.+))?$#u',
                $license,
                $matches
            )) {
                if (!isset($matches['text']) || !$matches['text']) {
                    // set text to URL if not present
                    $matches['text'] = $matches['url'];
                }
                $node->parentNode->setAttribute('link', $matches['url']);
                $node->nodeValue = $matches['text'];

                // bail out early
                continue;
            }

            // check map if any license matches
            foreach ($licenseMap as $regex => $url) {
                if (preg_match($regex, $license, $matches)) {
                    $node->parentNode->setAttribute('link', $url);

                    // we're done here
                    break;
                }
            }
        }

        return $xml;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core\Transformer\Behaviour\Tag;

/**
 * Behaviour that adds support for the @method tag
 */
class MethodTag
{
    /**
     * Find all return tags that contain 'self' or '$this' and replace those
     * terms for the name of the current class' type.
     *
     * @param \DOMDocument $xml Structure source to apply behaviour onto.
     *
     * @return \DOMDocument
     */
    public function process(\DOMDocument $xml)
    {
        $xpath = new \DOMXPath($xml);
        $nodes = $xpath->query(
            '/project/file/class/docblock/tag[@name="method"]'
        );

        /** @var \DOMElement $node */
        foreach ($nodes as $node) {
            $class = $node->parentNode->parentNode;

            $method = new \DOMElement('method');
            $class->appendChild($method);

            // set basic information
            $method->setAttribute('final', 'false');
            $method->setAttribute('static', 'false');
            $method->setAttribute('visibility', 'public');
            $method->setAttribute('line', $node->getAttribute('line'));
            $method->appendChild(
                new \DOMElement('name', $node->getAttribute('method_name'))
            );

            // fill docblock
            $docblock = new \DOMElement('docblock');
            $method->appendChild($docblock);
            $docblock->appendChild(
                new \DOMElement('description', $node->getAttribute('description'))
            );
            $docblock->appendChild(new \DOMElement('long-description'));

            // for each argument; create an @param tag and an argument element
            /** @var \DOMElement $argument */
            foreach ($node->getElementsByTagName('argument') as $argument) {
                $param_tag = new \DOMElement('tag');
                $docblock->appendChild($param_tag);
                $param_tag->setAttribute('name', 'param');
                $param_tag->setAttribute(
                    'type',
                    $argument->getElementsByTagName('type')->item(0)->nodeValue
                );
                $param_tag->setAttribute(
                    'variable',
                    $argument->getElementsByTagName('name')->item(0)->nodeValue
                );
                $param_tag->setAttribute('line', $node->getAttribute('line'));

                $types = explode(
                    '|',
                    $argument->getElementsByTagName('type')->item(0)->nodeValue
                );

                foreach ($types as $type) {
                    $type_element = new \DOMElement('type', $type);
                    $param_tag->appendChild($type_element);
                }

                $argument_element = $argument->cloneNode(true);
                $method->appendChild($argument_element);
            }

            // add a tag 'magic'
            $magic_tag = new \DOMElement('tag');
            $docblock->appendChild($magic_tag);
            $magic_tag->setAttribute('name', 'magic');
            $magic_tag->setAttribute('line', $node->getAttribute('line'));

            // add a @return tag
            $return_tag = new \DOMElement('tag');
            $docblock->appendChild($return_tag);
            $return_tag->setAttribute('name', 'return');
            $return_tag->setAttribute('line', $node->getAttribute('line'));
            $return_tag->setAttribute('type', $node->getAttribute('type'));

            // add type sub elements to the param
            foreach (explode('|', $node->getAttribute('type')) as $type) {
                $type_element = new \DOMElement('type', $type);
                $return_tag->appendChild($type_element);
            }

            // remove the tag, it is unneeded
            $node->parentNode->removeChild($node);
            $docblock->appendChild($node);
        }

        return $xml;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core\Transformer\Behaviour\Tag;

/**
 * Behaviour that adds support for the @method tag
 */
class VarTag extends ParamTag
{
    protected $element_name = 'var';
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Plugin\Core\Transformer\Behaviour\Tag;

/**
 * Behaviour that adds support for @ignore tag.
 */
class IgnoreTag
{
    protected $tag = 'ignore';

    /**
     * Removes DocBlocks marked with 'ignore' tag from the structure.
     *
     * @param \DOMDocument $xml Structure source to apply behaviour onto.
     *
     * @return \DOMDocument
     */
    public function process(\DOMDocument $xml)
    {
        $ignoreQry = '//tag[@name=\''. $this->tag . '\']';

        $xpath = new \DOMXPath($xml);
        $nodes = $xpath->query($ignoreQry);

        /** @var \DOMElement $node */
        foreach ($nodes as $node) {
            $remove = $node->parentNode->parentNode;

            // sometimes the parent node of the entity-to-be-removed is already
            // gone; for instance when a File docblock contains an @internal and
            // the underlying class also contains an @internal.
            // Because the File Docblock is found sooner, it is removed first.
            // Without the following check the application would fatal since
            // it cannot find, and then remove, this node from the parent.
            if (!isset($remove->parentNode)) {
                continue;
            }

            $remove->parentNode->removeChild($remove);
        }

        return $xml;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Configuration;

use JMS\Serializer\Annotation as Serializer;

/**
 * Configuration definition for the parser.
 */
class Parser
{
    /**
     * @var string name of the package when there is no @package tag defined
     * @Serializer\Type("string")
     */
    protected $defaultPackageName;

    /**
     * @var string destination location for the parser's output cache
     * @Serializer\Type("string")
     */
    protected $target;
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Configuration;

use JMS\Serializer\Annotation as Serializer;

/**
 * Configuration definition for the transformer.
 */
class Transformer
{
    /** @var string destination location for the transformer's output */
    protected $target;
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Configuration;

use JMS\Serializer\Annotation as Serializer;

/**
 * Represents the settings in the phpdoc.xml related to finding the files that are to be parsed.
 */
class Files
{
    /**
     * @var string[]
     * @Serializer\Type("array<string>")
     */
    protected $directories;

    /**
     * @var string[] files
     * @Serializer\Type("array<string>")
     */
    protected $files;

    /**
     * @var string[] ignore
     * @Serializer\Type("array<string>")
     */
    protected $ignore;
}
{
    "name": "jms/parser-lib",
    "description": "A library for easily creating recursive-descent parsers.",
    "license": "Apache2",
    "require": {
        "phpoption/phpoption": ">=0.9,<2.0-dev"
    },
    "autoload": {
        "psr-0": {
            "JMS\\": "src/"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.0-dev"
        }
    }
}<?php

/*
 * Copyright 2012 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Parser;

/**
 * Base Parser which provides some useful parsing methods intended for sub-classing.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
abstract class AbstractParser
{
    protected $lexer;
    protected $context;

    public function __construct(AbstractLexer $lexer)
    {
        $this->lexer = $lexer;
    }

    /**
     * Parses the given input.
     *
     * @param string $str
     * @param string $context parsing context (allows to produce better error messages)
     *
     * @return mixed
     */
    public function parse($str, $context = null)
    {
        $this->lexer->setInput($str);
        $this->context = $context;

        $rs = $this->parseInternal();

        if (null !== $this->lexer->next) {
            $this->syntaxError('end of input');
        }

        return $rs;
    }

    /**
     * @return mixed
     */
    abstract protected function parseInternal();

    /**
     * Matches a token, and returns its value.
     *
     * @param integer $type
     *
     * @return mixed the value of the matched token
     */
    protected function match($type)
    {
        if ( ! $this->lexer->isNext($type)) {
            $this->syntaxError($this->lexer->getName($type));
        }

        $this->lexer->moveNext();

        return $this->lexer->token[0];
    }

    /**
     * Matches any of the passed tokens, and returns the matched token's value.
     *
     * @param array<integer> $types
     *
     * @return mixed
     */
    protected function matchAny(array $types)
    {
        if ( ! $this->lexer->isNextAny($types)) {
            $this->syntaxError('any of '.implode(' or ', array_map(array($this->lexer, 'getName'), $types)));
        }

        $this->lexer->moveNext();

        return $this->lexer->token[0];
    }

    /**
     * Raises a syntax error exception.
     *
     * @param string $expectedDesc A human understandable explanation what was expected
     * @param array $actualToken The token that was found. If not given, next token will be assumed.
     */
    protected function syntaxError($expectedDesc, $actualToken = null)
    {
        if (null === $actualToken) {
            $actualToken = $this->lexer->next;
        }
        if (null === $actualToken) {
            $actualDesc = 'end of input';
        } else if ($actualToken[1] === 0) {
            $actualDesc = sprintf('"%s" of type %s at beginning of input', $actualToken[0], $this->lexer->getName($actualToken[2]));
        } else {
            $actualDesc = sprintf('"%s" of type %s at position %d (0-based)', $actualToken[0], $this->lexer->getName($actualToken[2]), $actualToken[1]);
        }

        $ex = new SyntaxErrorException(sprintf('Expected %s, but got %s%s.', $expectedDesc, $actualDesc, $this->context ? ' '.$this->context : ''));
        if (null !== $actualToken) {
            $ex->setActualToken($actualToken);
        }
        if (null !== $this->context) {
            $ex->setContext($this->context);
        }

        throw $ex;
    }
}<?php

/*
 * Copyright 2012 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Parser;

class SyntaxErrorException extends \RuntimeException
{
    private $actualToken;
    private $context;

    public function setActualToken(array $actualToken)
    {
        $this->actualToken = $actualToken;
    }

    public function setContext($context)
    {
        $this->context = $context;
    }

    public function getActualToken()
    {
        return $this->actualToken;
    }

    public function getContext()
    {
        return $this->context;
    }
}
<?php

/*
 * Copyright 2012 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Parser;

/**
 * Abstract Lexer.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
abstract class AbstractLexer
{
    public $token;
    public $next;

    private $i;
    private $peek;
    private $tokens;

    /**
     * Returns the name of the given token.
     *
     * @param integer $type
     *
     * @return string
     */
    public function getName($type)
    {
        $ref = new \ReflectionClass($this);
        foreach ($ref->getConstants() as $name => $value) {
            if ($value === $type) {
                return $name;
            }
        }

        throw new \InvalidArgumentException(sprintf('There is no token with value %s.', json_encode($type)));
    }

    public function setInput($str)
    {
        $tokens = preg_split($this->getRegex(), $str, null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE);

        $this->tokens = array();
        foreach ($tokens as $token) {
            list($token[2], $token[0]) = $this->determineTypeAndValue($token[0]);
            $this->tokens[] = $token;
        }

        $this->reset();
    }

    public function reset()
    {
        $this->i = -1;
        $this->peek = 0;
        $this->token = $this->next = null;
        $this->moveNext();
    }

    /**
     * Moves the pointer one token forward.
     *
     * @return boolean if we have not yet reached the end of the input
     */
    public function moveNext()
    {
        $this->peek = 0;
        $this->token = $this->next;
        $this->next = isset($this->tokens[++$this->i]) ? $this->tokens[$this->i] : null;

        return null !== $this->next;
    }

    /**
     * Skips the token stream until a token of the given type.
     *
     * @param integer $type
     *
     * @return boolean true if a token of the passed type was found, false otherwise.
     */
    public function skipUntil($type)
    {
        while ( ! $this->isNext($type) && $this->moveNext());

        if ( ! $this->isNext($type)) {
            throw new \RuntimeException(sprintf('Could not find the token %s.', $this->getName($type)));
        }
    }

    /**
     * @param integer $type
     *
     * @return boolean
     */
    public function isNext($type)
    {
        return null !== $this->next && $type === $this->next[2];
    }

    /**
     * @param array<integer> $types
     *
     * @return boolean
     */
    public function isNextAny(array $types)
    {
        if (null === $this->next) {
            return false;
        }

        foreach ($types as $type) {
            if ($type === $this->next[2]) {
                return true;
            }
        }

        return false;
    }

    /**
     * @return \PhpOption\Option<[string,integer,integer]>
     */
    public function peek()
    {
        if ( ! isset($this->tokens[$this->i + (++$this->peek)])) {
            return \PhpOption\None::create();
        }

        return new \PhpOption\Some($this->tokens[$this->i + $this->peek]);
    }

    /**
     * @return string
     */
    abstract protected function getRegex();

    /**
     * Determines the type of the given value.
     *
     * This method may also modify the passed value for example to cast them to
     * a different PHP type where necessary.
     *
     * @param string $value
     *
     * @return array a tupel of type and normalized value
     */
    abstract protected function determineTypeAndValue($value);
}
<?php

/*
 * Copyright 2012 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Parser;

/**
 * The simple lexer is a fully usable lexer that does not require sub-classing.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class SimpleLexer extends AbstractLexer
{
    private $regex;
    private $callable;
    private $tokenNames;

    public function __construct($regex, array $tokenNames, $typeCallable)
    {
        $this->regex = $regex;
        $this->callable = $typeCallable;
        $this->tokenNames = $tokenNames;
    }

    public function getName($type)
    {
        if ( ! isset($this->tokenNames[$type])) {
            throw new \InvalidArgumentException(sprintf('There is no token with type %s.', json_encode($type)));
        }

        return $this->tokenNames[$type];
    }

    protected function getRegex()
    {
        return $this->regex;
    }

    protected function determineTypeAndValue($value)
    {
        return call_user_func($this->callable, $value);
    }
}                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.<?php

namespace JMS\Parser;

class AbstractLexerTest extends \PHPUnit_Framework_TestCase
{
    const T_UNKNOWN = 0;
    const T_STRING = 1;
    const T_INTEGER = 2;

    const T_COMMA = 100;

    private $lexer;

    public function testTokenization()
    {
        $this->lexer->setInput('"foo"  1234');

        $this->assertNull($this->lexer->token);
        $this->assertNotNull($this->lexer->next);

        $this->assertAttributeEquals(array(
            array('foo', 0, self::T_STRING),
            array(1234, 7, self::T_INTEGER),
        ), 'tokens', $this->lexer);
    }

    public function testMoveNext()
    {
        $this->lexer->setInput('1 2 3');
        $this->assertNull($this->lexer->token);

        $this->assertTrue($this->lexer->moveNext());
        $this->assertValue(1, $this->lexer->token);

        $this->assertTrue($this->lexer->moveNext());
        $this->assertValue(2, $this->lexer->token);

        $this->assertFalse($this->lexer->moveNext());
        $this->assertValue(3, $this->lexer->token);
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testSkipUntilWithNonExistent()
    {
        $this->lexer->setInput('1 2 3');
        $this->lexer->skipUntil(self::T_STRING);
    }

    public function testSkipUntil()
    {
        $this->lexer->setInput('1 "foo"');
        $this->assertNull($this->lexer->skipUntil(self::T_STRING));
        $this->assertValue(1, $this->lexer->token);
        $this->assertValue('foo', $this->lexer->next);
    }

    public function testIsNext()
    {
        $this->lexer->setInput('1');
        $this->assertTrue($this->lexer->isNext(self::T_INTEGER));
        $this->assertFalse($this->lexer->isNext(self::T_COMMA));
    }

    public function testIsNextAny()
    {
        $this->lexer->setInput('1');
        $this->assertTrue($this->lexer->isNextAny(array(self::T_COMMA, self::T_INTEGER)));
        $this->assertFalse($this->lexer->isNextAny(array(self::T_COMMA, self::T_STRING)));
    }

    public function testPeek()
    {
        $this->lexer->setInput('1 2 3');

        $this->assertValue(1, $this->lexer->next);
        $this->assertValue(2, $this->lexer->peek()->get());

        $this->assertValue(1, $this->lexer->next);
        $this->assertValue(3, $this->lexer->peek()->get());

        $this->assertValue(1, $this->lexer->next);
        $this->assertTrue($this->lexer->moveNext());
        $this->assertValue(2, $this->lexer->next);
        $this->assertValue(3, $this->lexer->peek()->get());
        $this->assertValue(2, $this->lexer->next);
    }

    private function assertValue($expected, $actualToken)
    {
        $this->assertNotNull($actualToken);
        $this->assertSame($expected, $actualToken[0]);
    }

    protected function setUp()
    {
        $this->lexer = $this->getMockForAbstractClass('JMS\Parser\AbstractLexer');
        $this->lexer->expects($this->any())
                ->method('getRegex')
                ->will($this->returnValue('/("(?:[^"]*|(?<=\\)"))*")|([0-9]+)|\s+|(.)/i'));
        $this->lexer->expects($this->any())
                ->method('determineTypeAndValue')
                ->will($this->returnCallback(function($value) {
                    if (',' === $value) {
                        return array(AbstractLexerTest::T_COMMA, $value);
                    }

                    if ('"' === $value[0]) {
                        return array(AbstractLexerTest::T_STRING, substr($value, 1, -1));
                    }

                    if (preg_match('/^[0-9]+$/', $value)) {
                        return array(AbstractLexerTest::T_INTEGER, (integer) $value);
                    }

                    return array(AbstractLexerTest::T_UNKNOWN, $value);
                }));
    }
}
<?php

namespace JMS\Parser\Tests;

class AbstractParserTest extends \PHPUnit_Framework_TestCase
{
    const T_UNKNOWN = 0;
    const T_INT = 1;
    const T_PLUS = 100;
    const T_MINUS = 101;

    private $parser;
    private $lexer;

    public function testParse()
    {
        $this->assertSame(2, $this->parser->parse('1 + 1'));
        $this->assertSame(5, $this->parser->parse('1 + 1 + 4 - 1'));
    }

    /**
     * @expectedException JMS\Parser\SyntaxErrorException
     * @expectedExceptionMessage Expected T_INT, but got end of input.
     */
    public function testUnexpectedEnd()
    {
        $this->parser->parse('1 + ');
    }

    protected function setUp()
    {
        $this->lexer = $lexer = new \JMS\Parser\SimpleLexer(
            '/([0-9]+)|\s+|(.)/',
            array(0 => 'T_UNKNOWN', 1 => 'T_INT', 100 => 'T_PLUS', 101 => 'T_MINUS'),
            function($value) {
                if ('+' === $value) {
                    return array(AbstractParserTest::T_PLUS, $value);
                }
                if ('-' === $value) {
                    return array(AbstractParserTest::T_MINUS, $value);
                }

                // We would loose information on doubles here, but for this test it
                // does not matter anyway.
                if (is_numeric($value)) {
                    return array(AbstractParserTest::T_INT, (integer) $value);
                }

                return AbstractParserTest::T_UNKNOWN;
            }
        );

        $this->parser = $parser = $this->getMockBuilder('JMS\Parser\AbstractParser')
                            ->setConstructorArgs(array($this->lexer))
                            ->getMockForAbstractClass();

        $match = function($type) use ($parser) {
            $ref = new \ReflectionMethod($parser, 'match');
            $ref->setAccessible(true);

            return $ref->invoke($parser, $type);
        };

        $this->parser->expects($this->any())
                ->method('parseInternal')
                ->will($this->returnCallback(function() use ($lexer, $match) {
                    // Result :== Number ( ("+"|"-") Number )*

                    $result = $match(AbstractParserTest::T_INT);
                    while ($lexer->isNextAny(array(AbstractParserTest::T_PLUS, AbstractParserTest::T_MINUS))) {
                        if ($lexer->isNext(AbstractParserTest::T_PLUS)) {
                            $lexer->moveNext();

                            $result += $match(AbstractParserTest::T_INT);
                        } else if ($lexer->isNext(AbstractParserTest::T_MINUS)) {
                            $lexer->moveNext();

                            $result -= $match(AbstractParserTest::T_INT);
                        } else {
                            throw new \LogicException('Previous ifs were exhaustive.');
                        }
                    }

                    return $result;
                }));
    }
}<?php

if ( ! is_file($autoloadFile = __DIR__.'/../vendor/autoload.php')) {
    echo 'Could not find "vendor/autoload.php". Did you forget to run "composer install --dev"?'.PHP_EOL;
    exit(1);
}

require_once $autoloadFile;{
    "hash": "804f267fbd2c33067f6cafd3576f70dd",
    "packages": [
        {
            "name": "phpoption/phpoption",
            "version": "0.9.0",
            "source": {
                "type": "git",
                "url": "git://github.com/schmittjoh/php-option",
                "reference": "0.9.0"
            },
            "dist": {
                "type": "zip",
                "url": "https://github.com/schmittjoh/php-option/archive/0.9.0.zip",
                "reference": "0.9.0",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.0"
            },
            "require-dev": {
                "phpunit/phpunit": "3.7.*"
            },
            "time": "2012-11-12 08:25:35",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-0": {
                    "PhpOption\\": "src/"
                }
            },
            "license": [
                "Apache2"
            ],
            "authors": [
                {
                    "name": "Johannes M. Schmitt",
                    "email": "schmittjoh@gmail.com",
                    "homepage": "http://jmsyst.com",
                    "role": "Developer of wrapped JMSSerializerBundle"
                }
            ],
            "description": "Option Type for PHP",
            "keywords": [
                "php",
                "language",
                "type",
                "option"
            ]
        }
    ],
    "packages-dev": [

    ],
    "aliases": [

    ],
    "minimum-stability": "stable",
    "stability-flags": [

    ]
}
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="tests/bootstrap.php"
>
    <testsuites>
        <testsuite name="Parser-Lib Test Suite">
            <directory>./tests/JMS/</directory>
        </testsuite>
    </testsuites>

    <groups>
        <exclude>
            <group>performance</group>
        </exclude>
    </groups>
</phpunit>
THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.

BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.

1. Definitions

    "Adaptation" means a work based upon the Work, or upon the Work and other pre-existing works, such as a translation, adaptation, derivative work, arrangement of music or other alterations of a literary or artistic work, or phonogram or performance and includes cinematographic adaptations or any other form in which the Work may be recast, transformed, or adapted including in any form recognizably derived from the original, except that a work that constitutes a Collection will not be considered an Adaptation for the purpose of this License. For the avoidance of doubt, where the Work is a musical work, performance or phonogram, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered an Adaptation for the purpose of this License.
    "Collection" means a collection of literary or artistic works, such as encyclopedias and anthologies, or performances, phonograms or broadcasts, or other works or subject matter other than works listed in Section 1(f) below, which, by reason of the selection and arrangement of their contents, constitute intellectual creations, in which the Work is included in its entirety in unmodified form along with one or more other contributions, each constituting separate and independent works in themselves, which together are assembled into a collective whole. A work that constitutes a Collection will not be considered an Adaptation (as defined above) for the purposes of this License.
    "Distribute" means to make available to the public the original and copies of the Work through sale or other transfer of ownership.
    "Licensor" means the individual, individuals, entity or entities that offer(s) the Work under the terms of this License.
    "Original Author" means, in the case of a literary or artistic work, the individual, individuals, entity or entities who created the Work or if no individual or entity can be identified, the publisher; and in addition (i) in the case of a performance the actors, singers, musicians, dancers, and other persons who act, sing, deliver, declaim, play in, interpret or otherwise perform literary or artistic works or expressions of folklore; (ii) in the case of a phonogram the producer being the person or legal entity who first fixes the sounds of a performance or other sounds; and, (iii) in the case of broadcasts, the organization that transmits the broadcast.
    "Work" means the literary and/or artistic work offered under the terms of this License including without limitation any production in the literary, scientific and artistic domain, whatever may be the mode or form of its expression including digital form, such as a book, pamphlet and other writing; a lecture, address, sermon or other work of the same nature; a dramatic or dramatico-musical work; a choreographic work or entertainment in dumb show; a musical composition with or without words; a cinematographic work to which are assimilated works expressed by a process analogous to cinematography; a work of drawing, painting, architecture, sculpture, engraving or lithography; a photographic work to which are assimilated works expressed by a process analogous to photography; a work of applied art; an illustration, map, plan, sketch or three-dimensional work relative to geography, topography, architecture or science; a performance; a broadcast; a phonogram; a compilation of data to the extent it is protected as a copyrightable work; or a work performed by a variety or circus performer to the extent it is not otherwise considered a literary or artistic work.
    "You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation.
    "Publicly Perform" means to perform public recitations of the Work and to communicate to the public those public recitations, by any means or process, including by wire or wireless means or public digital performances; to make available to the public Works in such a way that members of the public may access these Works from a place and at a place individually chosen by them; to perform the Work to the public by any means or process and the communication to the public of the performances of the Work, including by public digital performance; to broadcast and rebroadcast the Work by any means including signs, sounds or images.
    "Reproduce" means to make copies of the Work by any means including without limitation by sound or visual recordings and the right of fixation and reproducing fixations of the Work, including storage of a protected performance or phonogram in digital form or other electronic medium.

2. Fair Dealing Rights. Nothing in this License is intended to reduce, limit, or restrict any uses free from copyright or rights arising from limitations or exceptions that are provided for in connection with the copyright protection under copyright law or other applicable laws.

3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below:

    to Reproduce the Work, to incorporate the Work into one or more Collections, and to Reproduce the Work as incorporated in the Collections; and,
    to Distribute and Publicly Perform the Work including as incorporated in Collections.

The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats, but otherwise you have no rights to make Adaptations. Subject to 8(f), all rights not expressly granted by Licensor are hereby reserved, including but not limited to the rights set forth in Section 4(d).

4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions:

    You may Distribute or Publicly Perform the Work only under the terms of this License. You must include a copy of, or the Uniform Resource Identifier (URI) for, this License with every copy of the Work You Distribute or Publicly Perform. You may not offer or impose any terms on the Work that restrict the terms of this License or the ability of the recipient of the Work to exercise the rights granted to that recipient under the terms of the License. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties with every copy of the Work You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Work, You may not impose any effective technological measures on the Work that restrict the ability of a recipient of the Work from You to exercise the rights granted to that recipient under the terms of the License. This Section 4(a) applies to the Work as incorporated in a Collection, but this does not require the Collection apart from the Work itself to be made subject to the terms of this License. If You create a Collection, upon notice from any Licensor You must, to the extent practicable, remove from the Collection any credit as required by Section 4(c), as requested.
    You may not exercise any of the rights granted to You in Section 3 above in any manner that is primarily intended for or directed toward commercial advantage or private monetary compensation. The exchange of the Work for other copyrighted works by means of digital file-sharing or otherwise shall not be considered to be intended for or directed toward commercial advantage or private monetary compensation, provided there is no payment of any monetary compensation in connection with the exchange of copyrighted works.
    If You Distribute, or Publicly Perform the Work or Collections, You must, unless a request has been made pursuant to Section 4(a), keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or if the Original Author and/or Licensor designate another party or parties (e.g., a sponsor institute, publishing entity, journal) for attribution ("Attribution Parties") in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; (ii) the title of the Work if supplied; (iii) to the extent reasonably practicable, the URI, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work. The credit required by this Section 4(c) may be implemented in any reasonable manner; provided, however, that in the case of a Collection, at a minimum such credit will appear, if a credit for all contributing authors of Collection appears, then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors. For the avoidance of doubt, You may only use the credit required by this Section for the purpose of attribution in the manner set out above and, by exercising Your rights under this License, You may not implicitly or explicitly assert or imply any connection with, sponsorship or endorsement by the Original Author, Licensor and/or Attribution Parties, as appropriate, of You or Your use of the Work, without the separate, express prior written permission of the Original Author, Licensor and/or Attribution Parties.

    For the avoidance of doubt:
        Non-waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme cannot be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License;
        Waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme can be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License if Your exercise of such rights is for a purpose or use which is otherwise than noncommercial as permitted under Section 4(b) and otherwise waives the right to collect royalties through any statutory or compulsory licensing scheme; and,
        Voluntary License Schemes. The Licensor reserves the right to collect royalties, whether individually or, in the event that the Licensor is a member of a collecting society that administers voluntary licensing schemes, via that society, from any exercise by You of the rights granted under this License that is for a purpose or use which is otherwise than noncommercial as permitted under Section 4(b).
    Except as otherwise agreed in writing by the Licensor or as may be otherwise permitted by applicable law, if You Reproduce, Distribute or Publicly Perform the Work either by itself or as part of any Collections, You must not distort, mutilate, modify or take other derogatory action in relation to the Work which would be prejudicial to the Original Author's honor or reputation.

5. Representations, Warranties and Disclaimer

UNLESS OTHERWISE MUTUALLY AGREED BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.

6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

7. Termination

    This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Collections from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License.
    Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above.

8. Miscellaneous

    Each time You Distribute or Publicly Perform the Work or a Collection, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License.
    If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
    No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent.
    This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You.
    The rights granted under, and the subject matter referenced, in this License were drafted utilizing the terminology of the Berne Convention for the Protection of Literary and Artistic Works (as amended on September 28, 1979), the Rome Convention of 1961, the WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and the Universal Copyright Convention (as revised on July 24, 1971). These rights and subject matter take effect in the relevant jurisdiction in which the License terms are sought to be enforced according to the corresponding provisions of the implementation of those treaty provisions in the applicable national law. If the standard suite of rights granted under applicable copyright law includes additional rights not granted under this License, such additional rights are deemed to be included in the License; this License is not intended to restrict the license of any rights under applicable law.
{
    "name": "jms/serializer",
    "type": "library",
    "description": "Library for (de-)serializing data of any complexity; supports XML, JSON, and YAML.",
    "keywords": ["serialization", "deserialization", "json", "jaxb", "xml"],
    "homepage": "http://jmsyst.com/libs/serializer",
    "license": "Apache2",
    "authors": [
        {
            "name": "Johannes M. Schmitt",
            "email": "schmittjoh@gmail.com"
        }
    ],
    "require": {
        "php": ">=5.3.2",
        "jms/metadata": "~1.1",
        "jms/parser-lib": "1.*",
        "phpcollection/phpcollection": ">=0.1,<0.3-dev",
        "doctrine/annotations": "1.*"
    },
    "suggest": {
        "symfony/yaml": "Required if you'd like to serialize data to YAML format."
    },
    "minimum-stability": "dev",
    "require-dev": {
        "twig/twig": ">=1.8,<2.0-dev",
        "doctrine/orm": ">=2.1,<2.4-dev",
        "symfony/yaml": "2.*",
        "symfony/translation": ">=2.0,<2.2-dev",
        "symfony/validator": ">=2.0,<2.2-dev",
        "symfony/form": ">=2.1,<2.2-dev",
        "symfony/filesystem": "2.*"
    },
    "autoload": {
        "psr-0": {
            "JMS\\Serializer": "src/"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "0.13-dev"
        }
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\EventDispatcher;

interface EventSubscriberInterface
{
    /**
     * Returns the events to which this class has subscribed.
     *
     * Return format:
     *     array(
     *         array('event' => 'the-event-name', 'method' => 'onEventName', 'class' => 'some-class', 'format' => 'json'),
     *         array(...),
     *     )
     *
     * The class may be omitted if the class wants to subscribe to events of all classes.
     * Same goes for the format key.
     *
     * @return array
     */
    public static function getSubscribedEvents();
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\EventDispatcher;

use Symfony\Component\DependencyInjection\ContainerInterface;

class LazyEventDispatcher extends EventDispatcher
{
    private $container;

    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    /**
     * {@inheritdoc}
     */
    protected function initializeListeners($eventName, $loweredClass, $format)
    {
        $listeners = parent::initializeListeners($eventName, $loweredClass, $format);

        foreach ($listeners as &$listener) {
            if ( ! is_array($listener) || ! is_string($listener[0])) {
                continue;
            }

            if ( ! $this->container->has($listener[0])) {
                continue;
            }

            $listener[0] = $this->container->get($listener[0]);
        }

        return $listeners;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\EventDispatcher;

use JMS\Serializer\DeserializationContext;

class PreDeserializeEvent extends Event
{
    private $data;

    public function __construct(DeserializationContext $context, $data, array $type)
    {
        parent::__construct($context, $type);

        $this->data = $data;
    }

    public function setType($name, array $params = array())
    {
        $this->type = array('name' => $name, 'params' => $params);
    }

    public function getData()
    {
        return $this->data;
    }

    public function setData($data)
    {
        $this->data = $data;
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\EventDispatcher;

class PreSerializeEvent extends ObjectEvent
{
    /**
     * @param string $typeName
     * @param array $params
     */
    public function setType($typeName, array $params = array())
    {
        $this->type = array('name' => $typeName, 'params' => $params);
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\EventDispatcher;

abstract class Events
{
    const PRE_SERIALIZE = 'serializer.pre_serialize';
    const POST_SERIALIZE = 'serializer.post_serialize';
    const PRE_DESERIALIZE = 'serializer.pre_deserialize';
    const POST_DESERIALIZE = 'serializer.post_deserialize';

    final private function __construct() { }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\EventDispatcher;

interface EventDispatcherInterface
{
    /**
     * Returns whether there are listeners.
     *
     * @param string $eventName
     * @param string $class
     * @param string $format
     *
     * @return boolean
     */
    public function hasListeners($eventName, $class, $format);

    /**
     * Dispatches an event.
     *
     * The listeners/subscribers are called in the same order in which they
     * were added to the dispatcher.
     *
     * @param string $eventName
     * @param string $class
     * @param string $format
     * @param Event $event
     * @return void
     */
    public function dispatch($eventName, $class, $format, Event $event);

    /**
     * Adds a listener.
     *
     * @param string $eventName
     * @param callable $callable
     * @param string|null $class
     * @param string|null $format
     * @return void
     */
    public function addListener($eventName, $callable, $class = null, $format = null);

    /**
     * Adds a subscribers.
     *
     * @param EventSubscriberInterface $subscriber
     * @return void
     */
    public function addSubscriber(EventSubscriberInterface $subscriber);
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\EventDispatcher;
use JMS\Serializer\Exception\InvalidArgumentException;

/**
 * Light-weight event dispatcher.
 *
 * This implementation focuses primarily on performance, and dispatching
 * events for certain classes. It is not a general purpose event dispatcher.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class EventDispatcher implements EventDispatcherInterface
{
    private $listeners = array();
    private $classListeners = array();

    public static function getDefaultMethodName($eventName)
    {
        return 'on'.str_replace(array('_', '.'), '', $eventName);
    }

    /**
     * Sets the listeners.
     *
     * @param array $listeners
     */
    public function setListeners(array $listeners)
    {
        $this->listeners = $listeners;
        $this->classListeners = array();
    }

    public function addListener($eventName, $callable, $class = null, $format = null)
    {
        $this->listeners[$eventName][] = array($callable, null === $class ? null : strtolower($class), $format);
        unset($this->classListeners[$eventName]);
    }

    public function addSubscriber(EventSubscriberInterface $subscriber)
    {
        foreach ($subscriber->getSubscribedEvents() as $eventData) {
            if ( ! isset($eventData['event'])) {
                throw new InvalidArgumentException(sprintf('Each event must have a "event" key.'));
            }

            $method = isset($eventData['method']) ? $eventData['method'] : self::getDefaultMethodName($eventData['event']);
            $class = isset($eventData['class']) ? strtolower($eventData['class']) : null;
            $format = isset($eventData['format']) ? $eventData['format'] : null;
            $this->listeners[$eventData['event']][] = array(array($subscriber, $method), $class, $format);
            unset($this->classListeners[$eventData['event']]);
        }
    }

    public function hasListeners($eventName, $class, $format)
    {
        if ( ! isset($this->listeners[$eventName])) {
            return false;
        }

        $loweredClass = strtolower($class);
        if ( ! isset($this->classListeners[$eventName][$loweredClass][$format])) {
            $this->classListeners[$eventName][$loweredClass][$format] = $this->initializeListeners($eventName, $loweredClass, $format);
        }

        return !!$this->classListeners[$eventName][$loweredClass][$format];
    }

    public function dispatch($eventName, $class, $format, Event $event)
    {
        if ( ! isset($this->listeners[$eventName])) {
            return;
        }

        $loweredClass = strtolower($class);
        if ( ! isset($this->classListeners[$eventName][$loweredClass][$format])) {
            $this->classListeners[$eventName][$loweredClass][$format] = $this->initializeListeners($eventName, $loweredClass, $format);
        }

        foreach ($this->classListeners[$eventName][$loweredClass][$format] as $listener) {
            call_user_func($listener, $event);
        }
    }

    /**
     * @param string $eventName
     * @param string $loweredClass
     * @param string $format
     *
     * @return array An array of listeners
     */
    protected function initializeListeners($eventName, $loweredClass, $format)
    {
        $listeners = array();
        foreach ($this->listeners[$eventName] as $listener) {
            if (null !== $listener[1] && $loweredClass !== $listener[1]) {
                continue;
            }
            if (null !== $listener[2] && $format !== $listener[2]) {
                continue;
            }

            $listeners[] = $listener[0];
        }

        return $listeners;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\EventDispatcher;

use JMS\Serializer\Context;

class Event
{
    protected $type;
    private $context;

    public function __construct(Context $context, array $type)
    {
        $this->context = $context;
        $this->type = $type;
    }

    public function getVisitor()
    {
        return $this->context->getVisitor();
    }

    public function getContext()
    {
        return $this->context;
    }

    public function getType()
    {
        return $this->type;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\EventDispatcher;

use JMS\Serializer\Context;

class ObjectEvent extends Event
{
    private $object;

    public function __construct(Context $context, $object, array $type)
    {
        parent::__construct($context, $type);

        $this->object = $object;
    }

    public function getObject()
    {
        return $this->object;
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\EventDispatcher\Subscriber;

use Doctrine\ORM\PersistentCollection;
use Doctrine\Common\Persistence\Proxy;
use Doctrine\ORM\Proxy\Proxy as ORMProxy;
use JMS\Serializer\EventDispatcher\PreSerializeEvent;
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;

class DoctrineProxySubscriber implements EventSubscriberInterface
{
    public function onPreSerialize(PreSerializeEvent $event)
    {
        $object = $event->getObject();
        $type = $event->getType();

        // If the set type name is not an actual class, but a faked type for which a custom handler exists, we do not
        // modify it with this subscriber. Also, we forgo autoloading here as an instance of this type is already created,
        // so it must be loaded if its a real class.
        $virtualType = ! class_exists($type['name'], false);

        if ($object instanceof PersistentCollection) {
            if ( ! $virtualType) {
                $event->setType('ArrayCollection');
            }

            return;
        }

        if ( ! $object instanceof Proxy && ! $object instanceof ORMProxy) {
            return;
        }

        $object->__load();

        if ( ! $virtualType) {
            $event->setType(get_parent_class($object));
        }
    }

    public static function getSubscribedEvents()
    {
        return array(
            array('event' => 'serializer.pre_serialize', 'method' => 'onPreSerialize'),
        );
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\EventDispatcher\Subscriber;

use JMS\Serializer\EventDispatcher\Event;
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\Exception\ValidationFailedException;
use Symfony\Component\Validator\ValidatorInterface;

class SymfonyValidatorSubscriber implements EventSubscriberInterface
{
    private $validator;

    public function __construct(ValidatorInterface $validator)
    {
        $this->validator = $validator;
    }

    public static function getSubscribedEvents()
    {
        return array(
            array('event' => 'serializer.post_deserialize', 'method' => 'onPostDeserialize'),
        );
    }

    public function onPostDeserialize(Event $event)
    {
        $context = $event->getContext();

        if ($context->getDepth() > 0) {
            return;
        }

        $validator = $this->validator;
        $context->attributes->get('validation_groups')->map(
            function(array $groups) use ($event, $validator) {
                $list = $validator->validate($event->getObject(), $groups);

                if ($list->count() > 0) {
                    throw new ValidationFailedException($list);
                }
            }
        );
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer;

/**
 * Parses a serializer type.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
final class TypeParser extends \JMS\Parser\AbstractParser
{
    const T_NAME = 1;
    const T_STRING = 2;
    const T_OPEN_BRACKET = 3;
    const T_CLOSE_BRACKET = 4;
    const T_COMMA = 5;
    const T_NONE = 6;

    public function __construct()
    {
        parent::__construct(new \JMS\Parser\SimpleLexer(
            '/
                # PHP Class Names
                ((?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\\\\)*[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)

                # Strings
                |("(?:[^"]|"")*"|\'(?:[^\']|\'\')*\')

                # Ignore whitespace
                |\s*

                # Terminals
                |(.)
            /x',
            array(self::T_NAME => 'T_NAME', self::T_STRING => 'T_STRING', self::T_OPEN_BRACKET => 'T_OPEN_BRACKET',
                  self::T_CLOSE_BRACKET => 'T_CLOSE_BRACKET', self::T_COMMA => 'T_COMMA', self::T_NONE => 'T_NONE'),
            function($value) {
                switch ($value[0]) {
                    case '"':
                    case "'":
                        return array(TypeParser::T_STRING, substr($value, 1, -1));

                    case '<':
                        return array(TypeParser::T_OPEN_BRACKET, '<');

                    case '>':
                        return array(TypeParser::T_CLOSE_BRACKET, '>');

                    case ',':
                        return array(TypeParser::T_COMMA, ',');

                    default:
                        if (preg_match('/^(?:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\\\\)*[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $value)) {
                            return array(TypeParser::T_NAME, $value);
                        }

                        return array(TypeParser::T_NONE, $value);
                }
            }
        ));
    }

    /**
     * @return array of the format ["name" => string, "params" => array]
     */
    protected function parseInternal()
    {
        $typeName = $this->match(self::T_NAME);
        if ( ! $this->lexer->isNext(self::T_OPEN_BRACKET)) {
            return array('name' => $typeName, 'params' => array());
        }

        $this->match(self::T_OPEN_BRACKET);
        $params = array();
        do {
            if ($this->lexer->isNext(self::T_NAME)) {
                $params[] = $this->parseInternal();
            } else if ($this->lexer->isNext(self::T_STRING)) {
                $params[] = $this->match(self::T_STRING);
            } else {
                $this->matchAny(array(self::T_NAME, self::T_STRING)); // Will throw an exception.
            }
        } while ($this->lexer->isNext(self::T_COMMA) && $this->lexer->moveNext());

        $this->match(self::T_CLOSE_BRACKET);

        return array('name' => $typeName, 'params' => $params);
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Naming;

use JMS\Serializer\Metadata\PropertyMetadata;

/**
 * Naming strategy which uses an annotation to translate the property name.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class SerializedNameAnnotationStrategy implements PropertyNamingStrategyInterface
{
    private $delegate;

    public function __construct(PropertyNamingStrategyInterface $namingStrategy)
    {
        $this->delegate = $namingStrategy;
    }

    /**
     * {@inheritDoc}
     */
    public function translateName(PropertyMetadata $property)
    {
        if (null !== $name = $property->serializedName) {
            return $name;
        }

        return $this->delegate->translateName($property);
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Naming;

use JMS\Serializer\Metadata\PropertyMetadata;

/**
 * Generic naming strategy which translates a camel-cased property name.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class CamelCaseNamingStrategy implements PropertyNamingStrategyInterface
{
    private $separator;
    private $lowerCase;

    public function __construct($separator = '_', $lowerCase = true)
    {
        $this->separator = $separator;
        $this->lowerCase = $lowerCase;
    }

    /**
     * {@inheritDoc}
     */
    public function translateName(PropertyMetadata $property)
    {
        $name = preg_replace('/[A-Z]/', $this->separator.'\\0', $property->name);

        if ($this->lowerCase) {
            return strtolower($name);
        }

        return ucfirst($name);
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Naming;

use JMS\Serializer\Metadata\PropertyMetadata;

class CacheNamingStrategy implements PropertyNamingStrategyInterface
{
    private $delegate;
    private $cache;

    public function __construct(PropertyNamingStrategyInterface $delegate)
    {
        $this->delegate = $delegate;
        $this->cache = new \SplObjectStorage();
    }

    public function translateName(PropertyMetadata $property)
    {
        if (isset($this->cache[$property])) {
            return $this->cache[$property];
        }

        return $this->cache[$property] = $this->delegate->translateName($property);
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Naming;

use JMS\Serializer\Naming\PropertyNamingStrategyInterface;
use JMS\Serializer\Metadata\PropertyMetadata;

class IdenticalPropertyNamingStrategy implements PropertyNamingStrategyInterface
{
    public function translateName(PropertyMetadata $property)
    {
        return $property->name;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Naming;

use JMS\Serializer\Metadata\PropertyMetadata;

/**
 * Interface for property naming strategies.
 *
 * Implementations translate the property name to a serialized name that is
 * displayed.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface PropertyNamingStrategyInterface
{
    /**
     * Translates the name of the property to the serialized version.
     *
     * @param PropertyMetadata $property
     *
     * @return string
     */
    public function translateName(PropertyMetadata $property);
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer;

use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Exception\InvalidArgumentException;
use JMS\Serializer\Metadata\PropertyMetadata;

abstract class GenericSerializationVisitor extends AbstractVisitor
{
    private $navigator;
    private $root;
    private $dataStack;
    private $data;

    public function setNavigator(GraphNavigator $navigator)
    {
        $this->navigator = $navigator;
        $this->root = null;
        $this->dataStack = new \SplStack;
    }

    /**
     * @return GraphNavigator
     */
    public function getNavigator()
    {
        return $this->navigator;
    }

    public function visitNull($data, array $type, Context $context)
    {
        return null;
    }

    public function visitString($data, array $type, Context $context)
    {
        if (null === $this->root) {
            $this->root = $data;
        }

        return (string) $data;
    }

    public function visitBoolean($data, array $type, Context $context)
    {
        if (null === $this->root) {
            $this->root = $data;
        }

        return (boolean) $data;
    }

    public function visitInteger($data, array $type, Context $context)
    {
        if (null === $this->root) {
            $this->root = $data;
        }

        return (int) $data;
    }

    public function visitDouble($data, array $type, Context $context)
    {
        if (null === $this->root) {
            $this->root = $data;
        }

        return (float) $data;
    }

    /**
     * @param array $data
     * @param array $type
     */
    public function visitArray($data, array $type, Context $context)
    {
        if (null === $this->root) {
            $this->root = array();
            $rs = &$this->root;
        } else {
            $rs = array();
        }

        foreach ($data as $k => $v) {
            $v = $this->navigator->accept($v, isset($type['params'][1]) ? $type['params'][1] : null, $context);

            if (null === $v && (!is_string($k) || !$context->shouldSerializeNull())) {
                continue;
            }

            $rs[$k] = $v;
        }

        return $rs;
    }

    public function startVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context)
    {
        if (null === $this->root) {
            $this->root = new \stdClass;
        }

        $this->dataStack->push($this->data);
        $this->data = array();
    }

    public function endVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context)
    {
        $rs = $this->data;
        $this->data = $this->dataStack->pop();

        if ($this->root instanceof \stdClass && 0 === $this->dataStack->count()) {
            $this->root = $rs;
        }

        return $rs;
    }

    public function visitProperty(PropertyMetadata $metadata, $data, Context $context)
    {
        $v = $metadata->getValue($data);

        $v = $this->navigator->accept($v, $metadata->type, $context);
        if (null === $v && !$context->shouldSerializeNull()) {
            return;
        }

        $k = $this->namingStrategy->translateName($metadata);

        if ($metadata->inline && is_array($v)) {
            $this->data = array_merge($this->data, $v);
        } else {
            $this->data[$k] = $v;
        }
    }

    /**
     * Allows you to add additional data to the current object/root element.
     *
     * @param string $key
     * @param scalar|array $value This value must either be a regular scalar, or an array.
     *                            It must not contain any objects anymore.
     */
    public function addData($key, $value)
    {
        if (isset($this->data[$key])) {
            throw new InvalidArgumentException(sprintf('There is already data for "%s".', $key));
        }

        $this->data[$key] = $value;
    }

    public function getRoot()
    {
        return $this->root;
    }

    /**
     * @param array|\ArrayObject $data the passed data must be understood by whatever encoding function is applied later.
     */
    public function setRoot($data)
    {
        $this->root = $data;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer;

use JMS\Serializer\Exception\RuntimeException;
use JMS\Serializer\Exclusion\DepthExclusionStrategy;
use JMS\Serializer\Exclusion\DisjunctExclusionStrategy;
use JMS\Serializer\Exclusion\ExclusionStrategyInterface;
use JMS\Serializer\Exclusion\GroupsExclusionStrategy;
use JMS\Serializer\Exclusion\VersionExclusionStrategy;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
use Metadata\MetadataFactory;
use Metadata\MetadataFactoryInterface;
use PhpCollection\Map;

abstract class Context
{
    /**
     * @var \PhpCollection\Map
     */
    public $attributes;

    private $format;

    /** @var VisitorInterface */
    private $visitor;

    /** @var GraphNavigator */
    private $navigator;

    /** @var MetadataFactory */
    private $metadataFactory;

    /** @var ExclusionStrategyInterface */
    private $exclusionStrategy;

    /** @var boolean */
    private $serializeNull;

    private $initialized = false;

    /** @var \SplStack */
    private $metadataStack;

    public function __construct()
    {
        $this->attributes = new Map();
    }

    public function initialize($format, VisitorInterface $visitor, GraphNavigator $navigator, MetadataFactoryInterface $factory)
    {
        if ($this->initialized) {
            throw new \LogicException('This context was already initialized, and cannot be re-used.');
        }

        $this->initialized = true;
        $this->format = $format;
        $this->visitor = $visitor;
        $this->navigator = $navigator;
        $this->metadataFactory = $factory;
        $this->metadataStack = new \SplStack();
    }

    public function accept($data, array $type = null)
    {
        return $this->navigator->accept($data, $type, $this);
    }

    public function getMetadataFactory()
    {
        return $this->metadataFactory;
    }

    public function getVisitor()
    {
        return $this->visitor;
    }

    public function getNavigator()
    {
        return $this->navigator;
    }

    public function getExclusionStrategy()
    {
        return $this->exclusionStrategy;
    }

    public function setAttribute($key, $value)
    {
        $this->assertMutable();
        $this->attributes->set($key, $value);

        return $this;
    }

    private function assertMutable()
    {
        if ( ! $this->initialized) {
            return;
        }

        throw new \LogicException('This context was already initialized and is immutable; you cannot modify it anymore.');
    }

    public function addExclusionStrategy(ExclusionStrategyInterface $strategy)
    {
        $this->assertMutable();

        if (null === $this->exclusionStrategy) {
            $this->exclusionStrategy = $strategy;

            return $this;
        }

        if ($this->exclusionStrategy instanceof DisjunctExclusionStrategy) {
            $this->exclusionStrategy->addStrategy($strategy);

            return $this;
        }

        $this->exclusionStrategy = new DisjunctExclusionStrategy(array(
            $this->exclusionStrategy,
            $strategy,
        ));

        return $this;
    }

    /**
     * @param integer $version
     */
    public function setVersion($version)
    {
        if (null === $version) {
            throw new \LogicException('The version must not be null.');
        }

        $this->attributes->set('version', $version);
        $this->addExclusionStrategy(new VersionExclusionStrategy($version));

        return $this;
    }

    /**
     * @param array|string $groups
     */
    public function setGroups($groups)
    {
        if (empty($groups)) {
            throw new \LogicException('The groups must not be empty.');
        }

        $this->attributes->set('groups', (array) $groups);
        $this->addExclusionStrategy(new GroupsExclusionStrategy((array) $groups));

        return $this;
    }

    public function enableMaxDepthChecks()
    {
        $this->addExclusionStrategy(new DepthExclusionStrategy());

        return $this;
    }

    public function setSerializeNull($bool)
    {
        $this->serializeNull = (boolean) $bool;

        return $this;
    }

    public function shouldSerializeNull()
    {
        return $this->serializeNull;
    }

    public function getFormat()
    {
        return $this->format;
    }

    public function pushClassMetadata(ClassMetadata $metadata)
    {
        $this->metadataStack->push($metadata);
    }

    public function pushPropertyMetadata(PropertyMetadata $metadata)
    {
        $this->metadataStack->push($metadata);
    }

    public function popPropertyMetadata()
    {
        $metadata = $this->metadataStack->pop();

        if (!$metadata instanceof PropertyMetadata) {
            throw new RuntimeException('Context metadataStack not working well');
        }
    }

    public function popClassMetadata()
    {
        $metadata = $this->metadataStack->pop();

        if (!$metadata instanceof ClassMetadata) {
            throw new RuntimeException('Context metadataStack not working well');
        }
    }

    public function getMetadataStack()
    {
        return $this->metadataStack;
    }

    abstract public function getDepth();
    abstract public function getDirection();
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Exclusion;

use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Context;

/**
 * Interface for exclusion strategies.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface ExclusionStrategyInterface
{
    /**
     * Whether the class should be skipped.
     *
     * @param ClassMetadata $metadata
     * @param Context $navigatorContext
     *
     * @return boolean
     */
    public function shouldSkipClass(ClassMetadata $metadata, Context $context);

    /**
     * Whether the property should be skipped.
     *
     * @param PropertyMetadata $property
     * @param Context $navigatorContext
     *
     * @return boolean
     */
    public function shouldSkipProperty(PropertyMetadata $property, Context $context);
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Exclusion;

use JMS\Serializer\Context;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
use PhpCollection\Sequence;
use PhpCollection\SequenceInterface;

/**
 * Disjunct Exclusion Strategy.
 *
 * This strategy is short-circuiting and will skip a class, or property as soon as one of the delegates skips it.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class DisjunctExclusionStrategy implements ExclusionStrategyInterface
{
    /** @var \PhpCollection\SequenceInterface */
    private $delegates;

    /**
     * @param ExclusionStrategyInterface[]|SequenceInterface $delegates
     */
    public function __construct($delegates)
    {
        if ( ! $delegates instanceof SequenceInterface) {
            $delegates = new Sequence($delegates);
        }

        $this->delegates = $delegates;
    }

    public function addStrategy(ExclusionStrategyInterface $strategy)
    {
        $this->delegates->add($strategy);
    }

    /**
     * Whether the class should be skipped.
     *
     * @param ClassMetadata $metadata
     * @param Context $navigatorContext
     *
     * @return boolean
     */
    public function shouldSkipClass(ClassMetadata $metadata, Context $context)
    {
        foreach ($this->delegates as $delegate) {
            /** @var $delegate ExclusionStrategyInterface */
            if ($delegate->shouldSkipClass($metadata, $context)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Whether the property should be skipped.
     *
     * @param PropertyMetadata $property
     * @param Context $navigatorContext
     *
     * @return boolean
     */
    public function shouldSkipProperty(PropertyMetadata $property, Context $context)
    {
        foreach ($this->delegates as $delegate) {
            /** @var $delegate ExclusionStrategyInterface */
            if ($delegate->shouldSkipProperty($property, $context)) {
                return true;
            }
        }

        return false;
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Exclusion;

use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Context;

class VersionExclusionStrategy implements ExclusionStrategyInterface
{
    private $version;

    public function __construct($version)
    {
        $this->version = $version;
    }

    /**
     * {@inheritDoc}
     */
    public function shouldSkipClass(ClassMetadata $metadata, Context $navigatorContext)
    {
        return false;
    }

    /**
     * {@inheritDoc}
     */
    public function shouldSkipProperty(PropertyMetadata $property, Context $navigatorContext)
    {
        if ((null !== $version = $property->sinceVersion) && version_compare($this->version, $version, '<')) {
            return true;
        }

        if ((null !== $version = $property->untilVersion) && version_compare($this->version, $version, '>')) {
            return true;
        }

        return false;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Exclusion;

use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Context;

class GroupsExclusionStrategy implements ExclusionStrategyInterface
{
    const DEFAULT_GROUP = 'Default';

    private $groups = array();

    public function __construct(array $groups)
    {
        if (empty($groups)) {
            $groups = array(self::DEFAULT_GROUP);
        }

        foreach ($groups as $group) {
            $this->groups[$group] = true;
        }
    }

    /**
     * {@inheritDoc}
     */
    public function shouldSkipClass(ClassMetadata $metadata, Context $navigatorContext)
    {
        return false;
    }

    /**
     * {@inheritDoc}
     */
    public function shouldSkipProperty(PropertyMetadata $property, Context $navigatorContext)
    {
        if ( ! $property->groups) {
            return ! isset($this->groups[self::DEFAULT_GROUP]);
        }

        foreach ($property->groups as $group) {
            if (isset($this->groups[$group])) {
                return false;
            }
        }

        return true;
    }
}
<?php

/*
 * Copyright 2011 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Exclusion;

use JMS\Serializer\Context;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;

/**
 * @author Adrien Brault <adrien.brault@gmail.com>
 */
class DepthExclusionStrategy implements ExclusionStrategyInterface
{
    /**
     * {@inheritDoc}
     */
    public function shouldSkipClass(ClassMetadata $metadata, Context $context)
    {
        return $this->isTooDeep($context);
    }

    /**
     * {@inheritDoc}
     */
    public function shouldSkipProperty(PropertyMetadata $property, Context $context)
    {
        return $this->isTooDeep($context);
    }

    private function isTooDeep(Context $context)
    {
        $depth = $context->getDepth();
        $metadataStack = $context->getMetadataStack();

        $nthProperty = 0;
        // iterate from the first added items to the lasts
        for ($i = $metadataStack->count() - 1; $i > 0; $i--) {
            $metadata = $metadataStack[$i];
            if ($metadata instanceof PropertyMetadata) {
                $nthProperty++;
                $relativeDepth = $depth - $nthProperty;

                if (null !== $metadata->maxDepth && $relativeDepth > $metadata->maxDepth) {
                    return true;
                }
            }
        }

        return false;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

/**
 * This annotation can be declared on methods which should be called
 * before the Serialization process.
 *
 * These methods do not need to be public, and should do any clean-up, or
 * preparation of the object that is necessary.
 *
 * @Annotation
 * @Target("METHOD")
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
final class PreSerialize
{
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

/**
 * @Annotation
 * @Target("PROPERTY")
 */
final class Expose
{
}
<?php

/*
 * Copyright 2011 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

/**
 * @Annotation
 * @Target({"PROPERTY","METHOD"})
 */
final class MaxDepth
{
    /**
     * @Required
     * @var integer
     */
    public $depth;
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

/**
 * @Annotation
 * @Target("METHOD")
 */
final class PostSerialize
{
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

/**
 * @Annotation
 * @Target("PROPERTY")
 */
final class ReadOnly
{
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

/**
 * @Annotation
 * @Target({"PROPERTY","METHOD"})
 */
final class XmlValue
{
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

abstract class XmlCollection
{
    /**
     * @var string
     */
    public $entry = 'entry';

    /**
     * @var boolean
     */
    public $inline = false;
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

/**
 * @Annotation
 * @Target({"PROPERTY", "METHOD"})
 */
final class Since extends Version
{
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

/**
 * Controls the order of properties in a class.
 *
 * @Annotation
 * @Target("CLASS")
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
final class AccessorOrder
{
    /**
     * @Required
     * @var string
     */
    public $order;

    /**
     * @var array<string>
     */
    public $custom = array();
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

/**
 * @Annotation
 * @Target({"PROPERTY", "METHOD"})
 */
final class Until extends Version
{
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

/**
 * @Annotation
 * @Target({"PROPERTY","METHOD"})
 */
final class XmlList extends XmlCollection
{
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

/**
 * @Annotation
 * @Target("CLASS")
 */
final class XmlRoot
{
    /**
     * @Required
     * @var string
     */
    public $name;
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

use JMS\Serializer\Exception\RuntimeException;

/**
 * @Annotation
 * @Target("CLASS")
 */
final class ExclusionPolicy
{
    const NONE = 'NONE';
    const ALL  = 'ALL';

    public $policy;

    public function __construct(array $values)
    {
        if (!is_string($values['value'])) {
            throw new RuntimeException('"value" must be a string.');
        }

        $this->policy = strtoupper($values['value']);

        if (self::NONE !== $this->policy && self::ALL !== $this->policy) {
            throw new RuntimeException('Exclusion policy must either be "ALL", or "NONE".');
        }
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

/**
 * @Annotation
 * @Target("PROPERTY")
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
final class Accessor
{
    /**
     * @var string
     */
    public $getter;

    /**
     * @var string
     */
    public $setter;
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

/**
 * @Annotation
 * @Target({"PROPERTY", "METHOD"})
 */
final class Type
{
    /**
     * @Required
     * @var string
     */
    public $name;
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

/**
 * @Annotation
 * @Target({"PROPERTY","METHOD"})
 */
final class XmlMap extends XmlCollection
{
    /**
     * @var string
     */
    public $keyAttribute = '_key';
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

/**
 * @Annotation
 * @Target("METHOD")
 *
 * @author Alexander Klimenkov <alx.devel@gmail.com>
 */
final class VirtualProperty
{
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

/**
 * @Annotation
 * @Target({"PROPERTY","METHOD"})
 */
final class Inline
{
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

/**
 * @Annotation
 * @Target({"PROPERTY","METHOD"})
 */
final class Groups
{
    /** @var array<string> @Required */
    public $groups;
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

/**
 * @Annotation
 * @Target({"PROPERTY", "METHOD"})
 */
final class XmlAttributeMap
{
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

abstract class Version
{
    /**
     * @Required
     * @var string
     */
    public $version;
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

/**
 * @Annotation
 * @Target({"PROPERTY", "METHOD"})
 */
final class XmlAttribute
{
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

/**
 * @Annotation
 * @Target({"CLASS", "PROPERTY"})
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
final class AccessType
{
    /**
     * @Required
     * @var string
     */
    public $type;
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

/**
 * This annotation can be defined on methods which are called after the
 * deserialization of the object is complete.
 *
 * These methods do not necessarily have to be public.
 *
 * @Annotation
 * @Target("METHOD")
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
final class PostDeserialize
{
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

use JMS\Serializer\Exception\RuntimeException;

/**
 * @Annotation
 * @Target({"PROPERTY","METHOD"})
 */
final class SerializedName
{
    public $name;

    public function __construct(array $values)
    {
        if (!is_string($values['value'])) {
            throw new RuntimeException(sprintf('"value" must be a string.'));
        }

        $this->name = $values['value'];
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

/**
 * @Annotation
 * @Target({"PROPERTY","METHOD"})
 */
final class XmlKeyValuePairs
{
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

/**
 * @Annotation
 * @Target("METHOD")
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
final class HandlerCallback
{
    /**
     * @Required
     * @var string
     */
    public $format;

    /**
     * @Required
     * @var string
     */
    public $direction;
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

/**
 * @Annotation
 * @Target({"PROPERTY", "CLASS"})
 */
final class Exclude
{
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Annotation;

/**
 * @Annotation
 * @Target("CLASS")
 */
class Discriminator
{
    /** @var array<string> */
    public $map;

    /** @var string */
    public $field = 'type';

    /** @var boolean */
    public $disabled = false;
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer;

use JMS\Serializer\Exception\LogicException;
use JMS\Serializer\Exception\RuntimeException;
use Metadata\MetadataFactoryInterface;

class SerializationContext extends Context
{
    /** @var \SplObjectStorage */
    private $visitingSet;

    /** @var \SplStack */
    private $visitingStack;

    public static function create()
    {
        return new self();
    }

    public function initialize($format, VisitorInterface $visitor, GraphNavigator $navigator, MetadataFactoryInterface $factory)
    {
        parent::initialize($format, $visitor, $navigator, $factory);

        $this->visitingSet = new \SplObjectStorage();
        $this->visitingStack = new \SplStack();
    }

    public function startVisiting($object)
    {
        $this->visitingSet->attach($object);
        $this->visitingStack->push($object);
    }

    public function stopVisiting($object)
    {
        $this->visitingSet->detach($object);
        $poppedObject = $this->visitingStack->pop();

        if ($object !== $poppedObject) {
            throw new RuntimeException('Context visitingStack not working well');
        }
    }

    public function isVisiting($object)
    {
        if (! is_object($object)) {
            throw new LogicException('Expected object but got ' . gettype($object) . '. Do you have the wrong @Type mapping or could this be a Doctrine many-to-many relation?');
        }
        return $this->visitingSet->contains($object);
    }

    public function getPath()
    {
        $path = array();
        foreach ($this->visitingStack as $obj) {
            $path[] = get_class($obj);
        }

        if ( ! $path) {
            return null;
        }

        return implode(' -> ', $path);
    }

    public function getDirection()
    {
        return GraphNavigator::DIRECTION_SERIALIZATION;
    }

    public function getDepth()
    {
        return $this->visitingStack->count();
    }

    public function getObject()
    {
        return !$this->visitingStack->isEmpty() ? $this->visitingStack->top() : null;
    }

    public function getVisitingStack()
    {
        return $this->visitingStack;
    }

    public function getVisitingSet()
    {
        return $this->visitingSet;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Construction;

use JMS\Serializer\VisitorInterface;
use JMS\Serializer\Metadata\ClassMetadata;

class UnserializeObjectConstructor implements ObjectConstructorInterface
{
    public function construct(VisitorInterface $visitor, ClassMetadata $metadata, $data, array $type)
    {
        return unserialize(sprintf('O:%d:"%s":0:{}', strlen($metadata->name), $metadata->name));
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Construction;

use Doctrine\Common\Persistence\ManagerRegistry;
use JMS\Serializer\VisitorInterface;
use JMS\Serializer\Metadata\ClassMetadata;

/**
 * Doctrine object constructor for new (or existing) objects during deserialization.
 */
class DoctrineObjectConstructor implements ObjectConstructorInterface
{
    private $managerRegistry;
    private $fallbackConstructor;

    /**
     * Constructor.
     *
     * @param ManagerRegistry            $managerRegistry     Manager registry
     * @param ObjectConstructorInterface $fallbackConstructor Fallback object constructor
     */
    public function __construct(ManagerRegistry $managerRegistry, ObjectConstructorInterface $fallbackConstructor)
    {
        $this->managerRegistry     = $managerRegistry;
        $this->fallbackConstructor = $fallbackConstructor;
    }

    /**
     * {@inheritdoc}
     */
    public function construct(VisitorInterface $visitor, ClassMetadata $metadata, $data, array $type)
    {
        // Locate possible ObjectManager
        $objectManager = $this->managerRegistry->getManagerForClass($metadata->name);

        if (!$objectManager) {
            // No ObjectManager found, proceed with normal deserialization
            return $this->fallbackConstructor->construct($visitor, $metadata, $data, $type);
        }

        // Locate possible ClassMetadata
        $classMetadataFactory = $objectManager->getMetadataFactory();

        if ($classMetadataFactory->isTransient($metadata->name)) {
            // No ClassMetadata found, proceed with normal deserialization
            return $this->fallbackConstructor->construct($visitor, $metadata, $data, $type);
        }

        // Managed entity, check for proxy load
        if (!is_array($data)) {
            // Single identifier, load proxy
            return $objectManager->getReference($metadata->name, $data);
        }

        // Fallback to default constructor if missing identifier(s)
        $classMetadata  = $objectManager->getClassMetadata($metadata->name);
        $identifierList = array();

        foreach ($classMetadata->getIdentifierFieldNames() as $name) {
            if ( ! array_key_exists($name, $data)) {
                return $this->fallbackConstructor->construct($visitor, $metadata, $data, $type);
            }

            $identifierList[$name] = $data[$name];
        }

        // Entity update, load it from database
        $object = $objectManager->find($metadata->name, $identifierList);

        $objectManager->initializeObject($object);

        return $object;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Construction;

use JMS\Serializer\VisitorInterface;
use JMS\Serializer\Metadata\ClassMetadata;

/**
 * Implementations of this interface construct new objects during deserialization.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface ObjectConstructorInterface
{
    /**
     * Constructs a new object.
     *
     * Implementations could for example create a new object calling "new", use
     * "unserialize" techniques, reflection, or other means.
     *
     * @param VisitorInterface $visitor
     * @param ClassMetadata $metadata
     * @param mixed $data
     * @param array $type ["name" => string, "params" => array]
     *
     * @return object
     */
    public function construct(VisitorInterface $visitor, ClassMetadata $metadata, $data, array $type);
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer;

use JMS\Serializer\Exception\RuntimeException;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Metadata\ClassMetadata;

/**
 * Generic Deserialization Visitor.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
abstract class GenericDeserializationVisitor extends AbstractVisitor
{
    private $navigator;
    private $result;
    private $objectStack;
    private $currentObject;

    public function setNavigator(GraphNavigator $navigator)
    {
        $this->navigator = $navigator;
        $this->result = null;
        $this->objectStack = new \SplStack;
    }

    public function getNavigator()
    {
        return $this->navigator;
    }

    public function prepare($data)
    {
        return $this->decode($data);
    }

    public function visitNull($data, array $type, Context $context)
    {
        return null;
    }

    public function visitString($data, array $type, Context $context)
    {
        $data = (string) $data;

        if (null === $this->result) {
            $this->result = $data;
        }

        return $data;
    }

    public function visitBoolean($data, array $type, Context $context)
    {
        $data = (Boolean) $data;

        if (null === $this->result) {
            $this->result = $data;
        }

        return $data;
    }

    public function visitInteger($data, array $type, Context $context)
    {
        $data = (integer) $data;

        if (null === $this->result) {
            $this->result = $data;
        }

        return $data;
    }

    public function visitDouble($data, array $type, Context $context)
    {
        $data = (double) $data;

        if (null === $this->result) {
            $this->result = $data;
        }

        return $data;
    }

    public function visitArray($data, array $type, Context $context)
    {
        if ( ! is_array($data)) {
            throw new RuntimeException(sprintf('Expected array, but got %s: %s', gettype($data), json_encode($data)));
        }

        // If no further parameters were given, keys/values are just passed as is.
        if ( ! $type['params']) {
            if (null === $this->result) {
                $this->result = $data;
            }

            return $data;
        }

        switch (count($type['params'])) {
            case 1: // Array is a list.
                $listType = $type['params'][0];

                $result = array();
                if (null === $this->result) {
                    $this->result = &$result;
                }

                foreach ($data as $v) {
                    $result[] = $this->navigator->accept($v, $listType, $context);
                }

                return $result;

            case 2: // Array is a map.
                list($keyType, $entryType) = $type['params'];

                $result = array();
                if (null === $this->result) {
                    $this->result = &$result;
                }

                foreach ($data as $k => $v) {
                    $result[$this->navigator->accept($k, $keyType, $context)] = $this->navigator->accept($v, $entryType, $context);
                }

                return $result;

            default:
                throw new RuntimeException(sprintf('Array type cannot have more than 2 parameters, but got %s.', json_encode($type['params'])));
        }
    }

    public function startVisitingObject(ClassMetadata $metadata, $object, array $type, Context $context)
    {
        $this->setCurrentObject($object);

        if (null === $this->result) {
            $this->result = $this->currentObject;
        }
    }

    public function visitProperty(PropertyMetadata $metadata, $data, Context $context)
    {
        $name = $this->namingStrategy->translateName($metadata);

        if (null === $data || ! array_key_exists($name, $data)) {
            return;
        }

        if ( ! $metadata->type) {
            throw new RuntimeException(sprintf('You must define a type for %s::$%s.', $metadata->reflection->class, $metadata->name));
        }

        $v = $data[$name] !== null ? $this->navigator->accept($data[$name], $metadata->type, $context) : null;

        if (null === $metadata->setter) {
            $metadata->reflection->setValue($this->currentObject, $v);

            return;
        }

        $this->currentObject->{$metadata->setter}($v);
    }

    public function endVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context)
    {
        $obj = $this->currentObject;
        $this->revertCurrentObject();

        return $obj;
    }

    public function getResult()
    {
        return $this->result;
    }

    public function setCurrentObject($object)
    {
        $this->objectStack->push($this->currentObject);
        $this->currentObject = $object;
    }

    public function getCurrentObject()
    {
        return $this->currentObject;
    }

    public function revertCurrentObject()
    {
        return $this->currentObject = $this->objectStack->pop();
    }

    abstract protected function decode($str);
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer;

use JMS\Serializer\Exception\XmlErrorException;
use JMS\Serializer\Exception\LogicException;
use JMS\Serializer\Exception\InvalidArgumentException;
use JMS\Serializer\Exception\RuntimeException;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Metadata\ClassMetadata;

class XmlDeserializationVisitor extends AbstractVisitor
{
    private $objectStack;
    private $metadataStack;
    private $currentObject;
    private $currentMetadata;
    private $result;
    private $navigator;
    private $disableExternalEntities = true;
    private $doctypeWhitelist = array();

    public function enableExternalEntities()
    {
        $this->disableExternalEntities = false;
    }

    public function setNavigator(GraphNavigator $navigator)
    {
        $this->navigator = $navigator;
        $this->objectStack = new \SplStack;
        $this->metadataStack = new \SplStack;
        $this->result = null;
    }

    public function getNavigator()
    {
        return $this->navigator;
    }

    public function prepare($data)
    {
        $previous = libxml_use_internal_errors(true);
        $previousEntityLoaderState = libxml_disable_entity_loader($this->disableExternalEntities);

        $dom = new \DOMDocument();
        $dom->loadXML($data);
        foreach ($dom->childNodes as $child) {
            if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) {
                $internalSubset = str_replace(array("\n", "\r"), '', $child->internalSubset);
                if (!in_array($internalSubset, $this->doctypeWhitelist, true)) {
                    throw new InvalidArgumentException(sprintf(
                        'The document type "%s" is not allowed. If it is safe, you may add it to the whitelist configuration.',
                        $internalSubset
                    ));
                }
            }
        }

        $doc = simplexml_load_string($data);
        libxml_use_internal_errors($previous);
        libxml_disable_entity_loader($previousEntityLoaderState);

        if (false === $doc) {
            throw new XmlErrorException(libxml_get_last_error());
        }

        return $doc;
    }

    public function visitNull($data, array $type, Context $context)
    {
        return null;
    }

    public function visitString($data, array $type, Context $context)
    {
        $data = (string) $data;

        if (null === $this->result) {
            $this->result = $data;
        }

        return $data;
    }

    public function visitBoolean($data, array $type, Context $context)
    {
        $data = (string) $data;

        if ('true' === $data) {
            $data = true;
        } elseif ('false' === $data) {
            $data = false;
        } else {
            throw new RuntimeException(sprintf('Could not convert data to boolean. Expected "true", or "false", but got %s.', json_encode($data)));
        }

        if (null === $this->result) {
            $this->result = $data;
        }

        return $data;
    }

    public function visitInteger($data, array $type, Context $context)
    {
        $data = (integer) $data;

        if (null === $this->result) {
            $this->result = $data;
        }

        return $data;
    }

    public function visitDouble($data, array $type, Context $context)
    {
        $data = (double) $data;

        if (null === $this->result) {
            $this->result = $data;
        }

        return $data;
    }

    public function visitArray($data, array $type, Context $context)
    {
        $entryName = null !== $this->currentMetadata && $this->currentMetadata->xmlEntryName ? $this->currentMetadata->xmlEntryName : 'entry';

        if ( ! isset($data->$entryName)) {
            if (null === $this->result) {
                return $this->result = array();
            }

            return array();
        }

        switch (count($type['params'])) {
            case 0:
                throw new RuntimeException(sprintf('The array type must be specified either as "array<T>", or "array<K,V>".'));

            case 1:
                $result = array();
                if (null === $this->result) {
                    $this->result = &$result;
                }

                foreach ($data->$entryName as $v) {
                    $result[] = $this->navigator->accept($v, $type['params'][0], $context);
                }

                return $result;

            case 2:
                if (null === $this->currentMetadata) {
                    throw new RuntimeException('Maps are not supported on top-level without metadata.');
                }

                list($keyType, $entryType) = $type['params'];
                $result = array();
                if (null === $this->result) {
                    $this->result = &$result;
                }

                foreach ($data->$entryName as $v) {
                    if (!isset($v[$this->currentMetadata->xmlKeyAttribute])) {
                        throw new RuntimeException(sprintf('The key attribute "%s" must be set for each entry of the map.', $this->currentMetadata->xmlKeyAttribute));
                    }

                    $k = $this->navigator->accept($v[$this->currentMetadata->xmlKeyAttribute], $keyType, $context);
                    $result[$k] = $this->navigator->accept($v, $entryType, $context);
                }

                return $result;

            default:
                throw new LogicException(sprintf('The array type does not support more than 2 parameters, but got %s.', json_encode($type['params'])));
        }
    }

    public function startVisitingObject(ClassMetadata $metadata, $object, array $type, Context $context)
    {
        $this->setCurrentObject($object);

        if (null === $this->result) {
            $this->result = $this->currentObject;
        }
    }

    public function visitProperty(PropertyMetadata $metadata, $data, Context $context)
    {
        $name = $this->namingStrategy->translateName($metadata);

        if (!$metadata->type) {
            throw new RuntimeException(sprintf('You must define a type for %s::$%s.', $metadata->reflection->class, $metadata->name));
        }

        if ($metadata->xmlAttribute) {
            if (isset($data[$name])) {
                $v = $this->navigator->accept($data[$name], $metadata->type, $context);
                $metadata->reflection->setValue($this->currentObject, $v);
            }

            return;
        }

        if ($metadata->xmlValue) {
            $v = $this->navigator->accept($data, $metadata->type, $context);
            $metadata->reflection->setValue($this->currentObject, $v);

            return;
        }

        if ($metadata->xmlCollection) {
            $enclosingElem = $data;
            if (!$metadata->xmlCollectionInline && isset($data->$name)) {
                $enclosingElem = $data->$name;
            }

            $this->setCurrentMetadata($metadata);
            $v = $this->navigator->accept($enclosingElem, $metadata->type, $context);
            $this->revertCurrentMetadata();
            $metadata->reflection->setValue($this->currentObject, $v);

            return;
        }

        if (!isset($data->$name)) {
            return;
        }

        $v = $this->navigator->accept($data->$name, $metadata->type, $context);

        if (null === $metadata->setter) {
            $metadata->reflection->setValue($this->currentObject, $v);

            return;
        }

        $this->currentObject->{$metadata->setter}($v);
    }

    public function endVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context)
    {
        $rs = $this->currentObject;
        $this->revertCurrentObject();

        return $rs;
    }

    public function setCurrentObject($object)
    {
        $this->objectStack->push($this->currentObject);
        $this->currentObject = $object;
    }

    public function getCurrentObject()
    {
        return $this->currentObject;
    }

    public function revertCurrentObject()
    {
        return $this->currentObject = $this->objectStack->pop();
    }

    public function setCurrentMetadata(PropertyMetadata $metadata)
    {
        $this->metadataStack->push($this->currentMetadata);
        $this->currentMetadata = $metadata;
    }

    public function getCurrentMetadata()
    {
        return $this->currentMetadata;
    }

    public function revertCurrentMetadata()
    {
        return $this->currentMetadata = $this->metadataStack->pop();
    }

    public function getResult()
    {
        return $this->result;
    }

    /**
     * @param array<string> $doctypeWhitelist
     */
    public function setDoctypeWhitelist(array $doctypeWhitelist)
    {
        $this->doctypeWhitelist = $doctypeWhitelist;
    }

    /**
     * @return array<string>
     */
    public function getDoctypeWhitelist()
    {
        return $this->doctypeWhitelist;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer;

use Symfony\Component\Yaml\Inline;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Naming\PropertyNamingStrategyInterface;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Util\Writer;

/**
 * Serialization Visitor for the YAML format.
 *
 * @see http://www.yaml.org/spec/
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class YamlSerializationVisitor extends AbstractVisitor
{
    public $writer;

    private $navigator;
    private $stack;
    private $metadataStack;
    private $currentMetadata;

    public function __construct(PropertyNamingStrategyInterface $namingStrategy)
    {
        parent::__construct($namingStrategy);

        $this->writer = new Writer();
    }

    public function setNavigator(GraphNavigator $navigator)
    {
        $this->navigator = $navigator;
        $this->writer->reset();
        $this->stack = new \SplStack;
        $this->metadataStack = new \SplStack;
    }

    public function visitNull($data, array $type, Context $context)
    {
        if ('' === $this->writer->content) {
            $this->writer->writeln('null');
        }

        return 'null';
    }

    public function visitString($data, array $type, Context $context)
    {
        $v = Inline::dump($data);

        if ('' === $this->writer->content) {
            $this->writer->writeln($v);
        }

        return $v;
    }

    /**
     * @param array $data
     * @param array $type
     */
    public function visitArray($data, array $type, Context $context)
    {
        $count = $this->writer->changeCount;
        $isList = array_keys($data) === range(0, count($data) - 1);

        foreach ($data as $k => $v) {
            if (null === $v && (!is_string($k) || ! $context->shouldSerializeNull())) {
                continue;
            }

            if ($isList) {
                $this->writer->writeln('-');
            } else {
                $this->writer->writeln(Inline::dump($k).':');
            }

            $this->writer->indent();

            if (null !== $v = $this->navigator->accept($v, null, $context)) {
                $this->writer
                    ->rtrim(false)
                    ->writeln(' '.$v)
                ;
            }

            $this->writer->outdent();
        }

        if ($count === $this->writer->changeCount && isset($type['params'][1])) {
            $this->writer
                ->rtrim(false)
                ->writeln(' {}')
            ;
        }
    }

    public function visitBoolean($data, array $type, Context $context)
    {
        $v = $data ? 'true' : 'false';

        if ('' === $this->writer->content) {
            $this->writer->writeln($v);
        }

        return $v;
    }

    public function visitDouble($data, array $type, Context $context)
    {
        $v = (string) $data;

        if ('' === $this->writer->content) {
            $this->writer->writeln($v);
        }

        return $v;
    }

    public function visitInteger($data, array $type, Context $context)
    {
        $v = (string) $data;

        if ('' === $this->writer->content) {
            $this->writer->writeln($v);
        }

        return $v;
    }

    public function startVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context)
    {
    }

    public function visitProperty(PropertyMetadata $metadata, $data, Context $context)
    {
        $v = $metadata->getValue($data);

        if (null === $v && !$context->shouldSerializeNull()) {
            return;
        }

        $name = $this->namingStrategy->translateName($metadata);

        if (!$metadata->inline) {
            $this->writer
                 ->writeln(Inline::dump($name).':')
                 ->indent();
        }

        $this->setCurrentMetadata($metadata);

        $count = $this->writer->changeCount;

        if (null !== $v = $this->navigator->accept($v, $metadata->type, $context)) {
            $this->writer
                ->rtrim(false)
                ->writeln(' '.$v)
            ;
        } elseif ($count === $this->writer->changeCount) {
            $this->writer->revert();
        }

        if (!$metadata->inline) {
            $this->writer->outdent();
        }
        $this->revertCurrentMetadata();
    }

    public function endVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context)
    {
    }

    public function setCurrentMetadata(PropertyMetadata $metadata)
    {
        $this->metadataStack->push($this->currentMetadata);
        $this->currentMetadata = $metadata;
    }

    public function revertCurrentMetadata()
    {
        return $this->currentMetadata = $this->metadataStack->pop();
    }

    public function getNavigator()
    {
        return $this->navigator;
    }

    public function getResult()
    {
        return $this->writer->getContent();
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer;

use JMS\Serializer\Naming\PropertyNamingStrategyInterface;

abstract class AbstractVisitor implements VisitorInterface
{
    protected $namingStrategy;

    public function __construct(PropertyNamingStrategyInterface $namingStrategy)
    {
        $this->namingStrategy = $namingStrategy;
    }

    public function getNamingStrategy()
    {
        return $this->namingStrategy;
    }

    public function prepare($data)
    {
        return $data;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Util;

use JMS\Serializer\Exception\RuntimeException;

/**
 * A writer implementation.
 *
 * This may be used to simplify writing well-formatted code.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class Writer
{
    public $indentationSpaces = 4;
    public $indentationLevel = 0;
    public $content = '';
    public $changeCount = 0;

    private $changes = array();

    public function indent()
    {
        $this->indentationLevel += 1;

        return $this;
    }

    public function outdent()
    {
        $this->indentationLevel -= 1;

        if ($this->indentationLevel < 0) {
            throw new RuntimeException('The identation level cannot be less than zero.');
        }

        return $this;
    }

    /**
     * @param string $content
     *
     * @return Writer
     */
    public function writeln($content)
    {
        $this->write($content."\n");

        return $this;
    }

    public function revert()
    {
        $change = array_pop($this->changes);
        $this->changeCount -=1 ;
        $this->content = substr($this->content, 0, -1 * strlen($change));
    }

    /**
     * @param string $content
     *
     * @return Writer
     */
    public function write($content)
    {
        $addition = '';

        $lines = explode("\n", $content);
        for ($i=0,$c=count($lines); $i<$c; $i++) {
            if ($this->indentationLevel > 0
                && !empty($lines[$i])
                && ((empty($addition) && "\n" === substr($this->content, -1)) || "\n" === substr($addition, -1))) {
                $addition .= str_repeat(' ', $this->indentationLevel * $this->indentationSpaces);
            }

            $addition .= $lines[$i];

            if ($i+1 < $c) {
                $addition .= "\n";
            }
        }

        $this->content .= $addition;
        $this->changes[] = $addition;
        $this->changeCount += 1;

        return $this;
    }

    public function rtrim($preserveNewLines = true)
    {
        if (!$preserveNewLines) {
            $this->content = rtrim($this->content);

            return $this;
        }

        $addNl = "\n" === substr($this->content, -1);
        $this->content = rtrim($this->content);

        if ($addNl) {
            $this->content .= "\n";
        }

        return $this;
    }

    public function reset()
    {
        $this->content = '';
        $this->indentationLevel = 0;

        return $this;
    }

    public function getContent()
    {
        return $this->content;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer;

/**
 * Serializer Interface.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface SerializerInterface
{
    /**
     * Serializes the given data to the specified output format.
     *
     * @param object|array|scalar $data
     * @param string $format
     * @param Context $context
     *
     * @return string
     */
    public function serialize($data, $format, SerializationContext $context = null);

    /**
     * Deserializes the given data to the specified type.
     *
     * @param string $data
     * @param string $type
     * @param string $format
     * @param Context $context
     *
     * @return object|array|scalar
     */
    public function deserialize($data, $type, $format, DeserializationContext $context = null);
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Twig;

use JMS\Serializer\SerializerInterface;
use JMS\Serializer\SerializationContext;

/**
 * Serializer helper twig extension
 *
 * Basically provides access to JMSSerializer from Twig
 */
class SerializerExtension extends \Twig_Extension
{
    protected $serializer;

    public function getName()
    {
        return 'jms_serializer';
    }

    public function __construct(SerializerInterface $serializer)
    {
        $this->serializer = $serializer;
    }

    public function getFilters()
    {
        return array(
            'serialize'      => new \Twig_Filter_Method($this, 'serialize'),
        );
    }

    public function getFunctions()
    {
        return array(
            'serialization_context' => new \Twig_Function_Method($this, 'createContext'),
        );
    }

    /**
     * Creates the serialization context
     *
     * @return SerializationContext
     */
    public function createContext()
    {
        return SerializationContext::create();
    }

    /**
     * @param object $object
     * @param string $type
     * @param SerializationContext $context
     */
    public function serialize($object, $type = 'json', SerializationContext $context = null)
    {
        return $this->serializer->serialize($object, $type, $context);
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer;

use JMS\Serializer\Handler\PhpCollectionHandler;
use JMS\Serializer\Exception\RuntimeException;
use Metadata\MetadataFactory;
use JMS\Serializer\Metadata\Driver\AnnotationDriver;
use JMS\Serializer\Handler\HandlerRegistry;
use JMS\Serializer\Construction\UnserializeObjectConstructor;
use PhpCollection\Map;
use JMS\Serializer\EventDispatcher\EventDispatcher;
use Metadata\Driver\DriverChain;
use JMS\Serializer\Metadata\Driver\YamlDriver;
use JMS\Serializer\Metadata\Driver\XmlDriver;
use Metadata\Driver\FileLocator;
use JMS\Serializer\Handler\DateHandler;
use JMS\Serializer\Handler\ArrayCollectionHandler;
use JMS\Serializer\Construction\ObjectConstructorInterface;
use JMS\Serializer\EventDispatcher\Subscriber\DoctrineProxySubscriber;
use JMS\Serializer\Naming\CamelCaseNamingStrategy;
use JMS\Serializer\Naming\PropertyNamingStrategyInterface;
use Doctrine\Common\Annotations\Reader;
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\FileCacheReader;
use Metadata\Cache\FileCache;
use JMS\Serializer\Naming\SerializedNameAnnotationStrategy;
use JMS\Serializer\Exception\InvalidArgumentException;

/**
 * Builder for serializer instances.
 *
 * This object makes serializer construction a breeze for projects that do not use
 * any special dependency injection container.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class SerializerBuilder
{
    private $metadataDirs = array();
    private $handlerRegistry;
    private $handlersConfigured = false;
    private $eventDispatcher;
    private $listenersConfigured = false;
    private $objectConstructor;
    private $serializationVisitors;
    private $deserializationVisitors;
    private $visitorsAdded = false;
    private $propertyNamingStrategy;
    private $debug = false;
    private $cacheDir;
    private $annotationReader;
    private $includeInterfaceMetadata = false;

    public static function create()
    {
        return new static();
    }

    public function __construct()
    {
        $this->handlerRegistry = new HandlerRegistry();
        $this->eventDispatcher = new EventDispatcher();
        $this->serializationVisitors = new Map();
        $this->deserializationVisitors = new Map();
    }

    public function setAnnotationReader(Reader $reader)
    {
        $this->annotationReader = $reader;

        return $this;
    }

    public function setDebug($bool)
    {
        $this->debug = (boolean) $bool;

        return $this;
    }

    public function setCacheDir($dir)
    {
        if ( ! is_dir($dir)) {
            $this->createDir($dir);
        }
        if ( ! is_writable($dir)) {
            throw new InvalidArgumentException(sprintf('The cache directory "%s" is not writable.', $dir));
        }

        $this->cacheDir = $dir;

        return $this;
    }

    public function addDefaultHandlers()
    {
        $this->handlersConfigured = true;
        $this->handlerRegistry->registerSubscribingHandler(new DateHandler());
        $this->handlerRegistry->registerSubscribingHandler(new PhpCollectionHandler());
        $this->handlerRegistry->registerSubscribingHandler(new ArrayCollectionHandler());

        return $this;
    }

    public function configureHandlers(\Closure $closure)
    {
        $this->handlersConfigured = true;
        $closure($this->handlerRegistry);

        return $this;
    }

    public function addDefaultListeners()
    {
        $this->listenersConfigured = true;
        $this->eventDispatcher->addSubscriber(new DoctrineProxySubscriber());

        return $this;
    }

    public function configureListeners(\Closure $closure)
    {
        $this->listenersConfigured = true;
        $closure($this->eventDispatcher);

        return $this;
    }

    public function setObjectConstructor(ObjectConstructorInterface $constructor)
    {
        $this->objectConstructor = $constructor;

        return $this;
    }

    public function setPropertyNamingStrategy(PropertyNamingStrategyInterface $propertyNamingStrategy)
    {
        $this->propertyNamingStrategy = $propertyNamingStrategy;

        return $this;
    }

    public function setSerializationVisitor($format, VisitorInterface $visitor)
    {
        $this->visitorsAdded = true;
        $this->serializationVisitors->set($format, $visitor);

        return $this;
    }

    public function setDeserializationVisitor($format, VisitorInterface $visitor)
    {
        $this->visitorsAdded = true;
        $this->deserializationVisitors->set($format, $visitor);

        return $this;
    }

    public function addDefaultSerializationVisitors()
    {
        $this->initializePropertyNamingStrategy();

        $this->visitorsAdded = true;
        $this->serializationVisitors->setAll(array(
            'xml' => new XmlSerializationVisitor($this->propertyNamingStrategy),
            'yml' => new YamlSerializationVisitor($this->propertyNamingStrategy),
            'json' => new JsonSerializationVisitor($this->propertyNamingStrategy),
        ));

        return $this;
    }

    public function addDefaultDeserializationVisitors()
    {
        $this->initializePropertyNamingStrategy();

        $this->visitorsAdded = true;
        $this->deserializationVisitors->setAll(array(
            'xml' => new XmlDeserializationVisitor($this->propertyNamingStrategy),
            'json' => new JsonDeserializationVisitor($this->propertyNamingStrategy),
        ));

        return $this;
    }

    /**
     * @param Boolean $include Whether to include the metadata from the interfaces
     *
     * @return SerializerBuilder
     */
    public function includeInterfaceMetadata($include)
    {
        $this->includeInterfaceMetadata = (Boolean) $include;

        return $this;
    }

    /**
     * Sets a map of namespace prefixes to directories.
     *
     * This method overrides any previously defined directories.
     *
     * @param array<string,string> $namespacePrefixToDirMap
     *
     * @return SerializerBuilder
     *
     * @throws InvalidArgumentException When a directory does not exist
     */
    public function setMetadataDirs(array $namespacePrefixToDirMap)
    {
        foreach ($namespacePrefixToDirMap as $dir) {
            if ( ! is_dir($dir)) {
                throw new InvalidArgumentException(sprintf('The directory "%s" does not exist.', $dir));
            }
        }

        $this->metadataDirs = $namespacePrefixToDirMap;

        return $this;
    }

    /**
     * Adds a directory where the serializer will look for class metadata.
     *
     * The namespace prefix will make the names of the actual metadata files a bit shorter. For example, let's assume
     * that you have a directory where you only store metadata files for the ``MyApplication\Entity`` namespace.
     *
     * If you use an empty prefix, your metadata files would need to look like:
     *
     * ``my-dir/MyApplication.Entity.SomeObject.yml``
     * ``my-dir/MyApplication.Entity.OtherObject.xml``
     *
     * If you use ``MyApplication\Entity`` as prefix, your metadata files would need to look like:
     *
     * ``my-dir/SomeObject.yml``
     * ``my-dir/OtherObject.yml``
     *
     * Please keep in mind that you currently may only have one directory per namespace prefix.
     *
     * @param string $dir The directory where metadata files are located.
     * @param string $namespacePrefix An optional prefix if you only store metadata for specific namespaces in this directory.
     *
     * @return SerializerBuilder
     *
     * @throws InvalidArgumentException When a directory does not exist
     * @throws InvalidArgumentException When a directory has already been registered
     */
    public function addMetadataDir($dir, $namespacePrefix = '')
    {
        if ( ! is_dir($dir)) {
            throw new InvalidArgumentException(sprintf('The directory "%s" does not exist.', $dir));
        }

        if (isset($this->metadataDirs[$namespacePrefix])) {
            throw new InvalidArgumentException(sprintf('There is already a directory configured for the namespace prefix "%s". Please use replaceMetadataDir() to override directories.', $namespacePrefix));
        }

        $this->metadataDirs[$namespacePrefix] = $dir;

        return $this;
    }

    /**
     * Adds a map of namespace prefixes to directories.
     *
     * @param array<string,string> $namespacePrefixToDirMap
     *
     * @return SerializerBuilder
     */
    public function addMetadataDirs(array $namespacePrefixToDirMap)
    {
        foreach ($namespacePrefixToDirMap as $prefix => $dir) {
            $this->addMetadataDir($dir, $prefix);
        }

        return $this;
    }

    /**
     * Similar to addMetadataDir(), but overrides an existing entry.
     *
     * @param string $dir
     * @param string $namespacePrefix
     *
     * @return SerializerBuilder
     *
     * @throws InvalidArgumentException When a directory does not exist
     * @throws InvalidArgumentException When no directory is configured for the ns prefix
     */
    public function replaceMetadataDir($dir, $namespacePrefix = '')
    {
        if ( ! is_dir($dir)) {
            throw new InvalidArgumentException(sprintf('The directory "%s" does not exist.', $dir));
        }

        if ( ! isset($this->metadataDirs[$namespacePrefix])) {
            throw new InvalidArgumentException(sprintf('There is no directory configured for namespace prefix "%s". Please use addMetadataDir() for adding new directories.', $namespacePrefix));
        }

        $this->metadataDirs[$namespacePrefix] = $dir;

        return $this;
    }

    public function build()
    {
        $annotationReader = $this->annotationReader;
        if (null === $annotationReader) {
            $annotationReader = new AnnotationReader();

            if (null !== $this->cacheDir) {
                $this->createDir($this->cacheDir.'/annotations');
                $annotationReader = new FileCacheReader($annotationReader, $this->cacheDir.'/annotations', $this->debug);
            }
        }

        if ( ! empty($this->metadataDirs)) {
            $fileLocator = new FileLocator($this->metadataDirs);
            $metadataDriver = new DriverChain(array(
                new YamlDriver($fileLocator),
                new XmlDriver($fileLocator),
                new AnnotationDriver($annotationReader),
            ));
        } else {
            $metadataDriver = new AnnotationDriver($annotationReader);
        }

        $metadataFactory = new MetadataFactory($metadataDriver, null, $this->debug);

        $metadataFactory->setIncludeInterfaces($this->includeInterfaceMetadata);

        if (null !== $this->cacheDir) {
            $this->createDir($this->cacheDir.'/metadata');
            $metadataFactory->setCache(new FileCache($this->cacheDir.'/metadata'));
        }

        if ( ! $this->handlersConfigured) {
            $this->addDefaultHandlers();
        }

        if ( ! $this->listenersConfigured) {
            $this->addDefaultListeners();
        }

        if ( ! $this->visitorsAdded) {
            $this->addDefaultSerializationVisitors();
            $this->addDefaultDeserializationVisitors();
        }

        return new Serializer(
            $metadataFactory,
            $this->handlerRegistry,
            $this->objectConstructor ?: new UnserializeObjectConstructor(),
            $this->serializationVisitors,
            $this->deserializationVisitors,
            $this->eventDispatcher
        );
    }

    private function initializePropertyNamingStrategy()
    {
        if (null !== $this->propertyNamingStrategy) {
            return;
        }

        $this->propertyNamingStrategy = new SerializedNameAnnotationStrategy(new CamelCaseNamingStrategy());
    }

    private function createDir($dir)
    {
        if (is_dir($dir)) {
            return;
        }

        if (false === @mkdir($dir, 0777, true)) {
            throw new RuntimeException(sprintf('Could not create directory "%s".', $dir));
        }
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer;

class DeserializationContext extends Context
{
    private $depth = 0;

    public static function create()
    {
        return new self();
    }

    public function getDirection()
    {
        return GraphNavigator::DIRECTION_DESERIALIZATION;
    }

    public function getDepth()
    {
        return $this->depth;
    }

    public function increaseDepth()
    {
        $this->depth += 1;
    }

    public function decreaseDepth()
    {
        if ($this->depth <= 0) {
            throw new \LogicException('Depth cannot be smaller than zero.');
        }

        $this->depth -= 1;
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer;

use JMS\Serializer\Exception\RuntimeException;

class JsonDeserializationVisitor extends GenericDeserializationVisitor
{
    protected function decode($str)
    {
        $decoded = json_decode($str, true);

        switch (json_last_error()) {
            case JSON_ERROR_NONE:
                return $decoded;

            case JSON_ERROR_DEPTH:
                throw new RuntimeException('Could not decode JSON, maximum stack depth exceeded.');

            case JSON_ERROR_STATE_MISMATCH:
                throw new RuntimeException('Could not decode JSON, underflow or the nodes mismatch.');

            case JSON_ERROR_CTRL_CHAR:
                throw new RuntimeException('Could not decode JSON, unexpected control character found.');

            case JSON_ERROR_SYNTAX:
                throw new RuntimeException('Could not decode JSON, syntax error - malformed JSON.');

            case JSON_ERROR_UTF8:
                throw new RuntimeException('Could not decode JSON, malformed UTF-8 characters (incorrectly encoded?)');

            default:
                throw new RuntimeException('Could not decode JSON.');
        }
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer;

use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;

/**
 * Interface for visitors.
 *
 * This contains the minimal set of values that must be supported for any
 * output format.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface VisitorInterface
{
    /**
     * Allows visitors to convert the input data to a different representation
     * before the actual serialization/deserialization process starts.
     *
     * @param mixed $data
     *
     * @return mixed
     */
    public function prepare($data);

    /**
     * @param mixed $data
     * @param array $type
     *
     * @return mixed
     */
    public function visitNull($data, array $type, Context $context);

    /**
     * @param mixed $data
     * @param array $type
     *
     * @return mixed
     */
    public function visitString($data, array $type, Context $context);

    /**
     * @param mixed $data
     * @param array $type
     *
     * @return mixed
     */
    public function visitBoolean($data, array $type, Context $context);

    /**
     * @param mixed $data
     * @param array $type
     *
     * @return mixed
     */
    public function visitDouble($data, array $type, Context $context);

    /**
     * @param mixed $data
     * @param array $type
     *
     * @return mixed
     */
    public function visitInteger($data, array $type, Context $context);

    /**
     * @param mixed $data
     * @param array $type
     *
     * @return mixed
     */
    public function visitArray($data, array $type, Context $context);

    /**
     * Called before the properties of the object are being visited.
     *
     * @param ClassMetadata $metadata
     * @param mixed $data
     * @param array $type
     *
     * @return void
     */
    public function startVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context);

    /**
     * @param PropertyMetadata $metadata
     * @param mixed $data
     *
     * @return void
     */
    public function visitProperty(PropertyMetadata $metadata, $data, Context $context);

    /**
     * Called after all properties of the object have been visited.
     *
     * @param ClassMetadata $metadata
     * @param mixed $data
     * @param array $type
     *
     * @return mixed
     */
    public function endVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context);

    /**
     * Called before serialization/deserialization starts.
     *
     * @param GraphNavigator $navigator
     *
     * @return void
     */
    public function setNavigator(GraphNavigator $navigator);

    /**
     * @deprecated use Context::getNavigator/Context::accept instead
     * @return GraphNavigator
     */
    public function getNavigator();

    /**
     * @return object|array|scalar
     */
    public function getResult();
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer;

use JMS\Serializer\Exception\RuntimeException;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;

/**
 * XmlSerializationVisitor.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class XmlSerializationVisitor extends AbstractVisitor
{
    public $document;

    private $navigator;
    private $defaultRootName = 'result';
    private $defaultVersion = '1.0';
    private $defaultEncoding = 'UTF-8';
    private $stack;
    private $metadataStack;
    private $currentNode;
    private $currentMetadata;
    private $hasValue;
    private $nullWasVisited;

    public function setDefaultRootName($name)
    {
        $this->defaultRootName = $name;
    }

    /**
     * @return boolean
     */
    public function hasDefaultRootName()
    {
        return 'result' === $this->defaultRootName;
    }

    public function setDefaultVersion($version)
    {
        $this->defaultVersion = $version;
    }

    public function setDefaultEncoding($encoding)
    {
        $this->defaultEncoding = $encoding;
    }

    public function setNavigator(GraphNavigator $navigator)
    {
        $this->navigator = $navigator;
        $this->document = null;
        $this->stack = new \SplStack;
        $this->metadataStack = new \SplStack;
    }

    public function getNavigator()
    {
        return $this->navigator;
    }

    public function visitNull($data, array $type, Context $context)
    {
        if (null === $this->document) {
            $this->document = $this->createDocument(null, null, true);
            $node = $this->document->createAttribute('xsi:nil');
            $node->value = 'true';
            $this->currentNode->appendChild($node);

            $this->attachNullNamespace();

            return;
        }

        $node = $this->document->createAttribute('xsi:nil');
        $node->value = 'true';
        $this->attachNullNamespace();

        return $node;
    }

    public function visitString($data, array $type, Context $context)
    {
        if (null === $this->document) {
            $this->document = $this->createDocument(null, null, true);
            $this->currentNode->appendChild($this->document->createCDATASection($data));

            return;
        }

        return $this->document->createCDATASection($data);
    }

    public function visitBoolean($data, array $type, Context $context)
    {
        if (null === $this->document) {
            $this->document = $this->createDocument(null, null, true);
            $this->currentNode->appendChild($this->document->createTextNode($data ? 'true' : 'false'));

            return;
        }

        return $this->document->createTextNode($data ? 'true' : 'false');
    }

    public function visitInteger($data, array $type, Context $context)
    {
        return $this->visitNumeric($data, $type);
    }

    public function visitDouble($data, array $type, Context $context)
    {
        return $this->visitNumeric($data, $type);
    }

    public function visitArray($data, array $type, Context $context)
    {
        if (null === $this->document) {
            $this->document = $this->createDocument(null, null, true);
        }

        $entryName = (null !== $this->currentMetadata && null !== $this->currentMetadata->xmlEntryName) ? $this->currentMetadata->xmlEntryName : 'entry';
        $keyAttributeName = (null !== $this->currentMetadata && null !== $this->currentMetadata->xmlKeyAttribute) ? $this->currentMetadata->xmlKeyAttribute : null;

        foreach ($data as $k => $v) {
            $tagName = (null !== $this->currentMetadata && $this->currentMetadata->xmlKeyValuePairs && $this->isElementNameValid($k)) ? $k : $entryName;

            $entryNode = $this->document->createElement($tagName);
            $this->currentNode->appendChild($entryNode);
            $this->setCurrentNode($entryNode);

            if (null !== $keyAttributeName) {
                $entryNode->setAttribute($keyAttributeName, (string) $k);
            }

            if (null !== $node = $this->navigator->accept($v, isset($type['params'][1]) ? $type['params'][1] : null, $context)) {
                $this->currentNode->appendChild($node);
            }

            $this->revertCurrentNode();
        }
    }

    public function startVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context)
    {
        if (null === $this->document) {
            $this->document = $this->createDocument(null, null, false);
            $this->document->appendChild($this->currentNode = $this->document->createElement($metadata->xmlRootName ?: $this->defaultRootName));
        }

        $this->hasValue = false;
    }

    public function visitProperty(PropertyMetadata $metadata, $object, Context $context)
    {
        $v = $metadata->getValue($object);

        if (null === $v && !$context->shouldSerializeNull()) {
            return;
        }

        if ($metadata->xmlAttribute) {
            $node = $this->navigator->accept($v, $metadata->type, $context);
            if (!$node instanceof \DOMCharacterData) {
                throw new RuntimeException(sprintf('Unsupported value for XML attribute. Expected character data, but got %s.', json_encode($v)));
            }

            $this->currentNode->setAttribute($this->namingStrategy->translateName($metadata), $node->nodeValue);

            return;
        }

        if (($metadata->xmlValue && $this->currentNode->childNodes->length > 0)
            || (!$metadata->xmlValue && $this->hasValue)) {
            throw new RuntimeException(sprintf('If you make use of @XmlValue, all other properties in the class must have the @XmlAttribute annotation. Invalid usage detected in class %s.', $metadata->class));
        }

        if ($metadata->xmlValue) {
            $this->hasValue = true;

            $node = $this->navigator->accept($v, $metadata->type, $context);
            if (!$node instanceof \DOMCharacterData) {
                throw new RuntimeException(sprintf('Unsupported value for property %s::$%s. Expected character data, but got %s.', $metadata->reflection->class, $metadata->reflection->name, is_object($node) ? get_class($node) : gettype($node)));
            }

            $this->currentNode->appendChild($node);

            return;
        }

        if ($metadata->xmlAttributeMap) {
            if (!is_array($v)) {
                throw new RuntimeException(sprintf('Unsupported value type for XML attribute map. Expected array but got %s.', gettype($v)));
            }

            foreach ($v as $key => $value) {
                $node = $this->navigator->accept($value, null, $context);
                if (!$node instanceof \DOMCharacterData) {
                    throw new RuntimeException(sprintf('Unsupported value for a XML attribute map value. Expected character data, but got %s.', json_encode($v)));
                }

                $this->currentNode->setAttribute($key, $node->nodeValue);
            }

            return;
        }

        if ($addEnclosingElement = (!$metadata->xmlCollection || !$metadata->xmlCollectionInline) && !$metadata->inline) {
            $element = $this->document->createElement($this->namingStrategy->translateName($metadata));
            $this->setCurrentNode($element);
        }

        $this->setCurrentMetadata($metadata);

        if (null !== $node = $this->navigator->accept($v, $metadata->type, $context)) {
            $this->currentNode->appendChild($node);
        }

        $this->revertCurrentMetadata();

        if ($addEnclosingElement) {
            $this->revertCurrentNode();

            if ($element->hasChildNodes() || $element->hasAttributes()
                || (isset($metadata->type['name']) && $metadata->type['name'] === 'array' && isset($metadata->type['params'][1]))) {
                $this->currentNode->appendChild($element);
            }
        }

        $this->hasValue = false;
    }

    public function endVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context)
    {
    }

    public function getResult()
    {
        return $this->document->saveXML();
    }

    public function getCurrentNode()
    {
        return $this->currentNode;
    }

    public function getCurrentMetadata()
    {
        return $this->currentMetadata;
    }

    public function getDocument()
    {
        return $this->document;
    }

    public function setCurrentMetadata(PropertyMetadata $metadata)
    {
        $this->metadataStack->push($this->currentMetadata);
        $this->currentMetadata = $metadata;
    }

    public function setCurrentNode(\DOMNode $node)
    {
        $this->stack->push($this->currentNode);
        $this->currentNode = $node;
    }

    public function revertCurrentNode()
    {
        return $this->currentNode = $this->stack->pop();
    }

    public function revertCurrentMetadata()
    {
        return $this->currentMetadata = $this->metadataStack->pop();
    }

    public function createDocument($version = null, $encoding = null, $addRoot = true)
    {
        $doc = new \DOMDocument($version ?: $this->defaultVersion, $encoding ?: $this->defaultEncoding);
        $doc->formatOutput = true;

        if ($addRoot) {
            $this->setCurrentNode($rootNode = $doc->createElement($this->defaultRootName));
            $doc->appendChild($rootNode);
        }

        return $doc;
    }

    public function prepare($data)
    {
        $this->nullWasVisited = false;

        return $data;
    }

    private function visitNumeric($data, array $type)
    {
        if (null === $this->document) {
            $this->document = $this->createDocument(null, null, true);
            $this->currentNode->appendChild($textNode = $this->document->createTextNode((string) $data));

            return $textNode;
        }

        return $this->document->createTextNode((string) $data);
    }

    /**
     * Checks that the name is a valid XML element name.
     *
     * @param string $name
     *
     * @return boolean
     */
    private function isElementNameValid($name)
    {
        return $name && false === strpos($name, ' ') && preg_match('#^[\pL_][\pL0-9._-]*$#ui', $name);
    }

    private function attachNullNamespace()
    {
        if (!$this->nullWasVisited) {
            $this->document->documentElement->setAttributeNS(
                'http://www.w3.org/2000/xmlns/',
                'xmlns:xsi',
                'http://www.w3.org/2001/XMLSchema-instance'
            );
            $this->nullWasVisited = true;
        }
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Metadata;

use JMS\Serializer\TypeParser;
use Metadata\PropertyMetadata as BasePropertyMetadata;
use JMS\Serializer\Exception\RuntimeException;

class PropertyMetadata extends BasePropertyMetadata
{
    const ACCESS_TYPE_PROPERTY        = 'property';
    const ACCESS_TYPE_PUBLIC_METHOD   = 'public_method';

    public $sinceVersion;
    public $untilVersion;
    public $groups;
    public $serializedName;
    public $type;
    public $xmlCollection = false;
    public $xmlCollectionInline = false;
    public $xmlEntryName;
    public $xmlKeyAttribute;
    public $xmlAttribute = false;
    public $xmlValue = false;
    public $xmlKeyValuePairs = false;
    public $getter;
    public $setter;
    public $inline = false;
    public $readOnly = false;
    public $xmlAttributeMap = false;
    public $maxDepth = null;

    private static $typeParser;

    public function setAccessor($type, $getter = null, $setter = null)
    {
        if (self::ACCESS_TYPE_PUBLIC_METHOD === $type) {
            $class = $this->reflection->getDeclaringClass();

            if (empty($getter)) {
                if ($class->hasMethod('get'.$this->name) && $class->getMethod('get'.$this->name)->isPublic()) {
                    $getter = 'get'.$this->name;
                } elseif ($class->hasMethod('is'.$this->name) && $class->getMethod('is'.$this->name)->isPublic()) {
                    $getter = 'is'.$this->name;
                } else {
                    throw new RuntimeException(sprintf('There is neither a public %s method, nor a public %s method in class %s. Please specify which public method should be used for retrieving the value of the property %s.', 'get'.ucfirst($this->name), 'is'.ucfirst($this->name), $this->class, $this->name));
                }
            }

            if (empty($setter) && !$this->readOnly) {
                if ($class->hasMethod('set'.$this->name) && $class->getMethod('set'.$this->name)->isPublic()) {
                    $setter = 'set'.$this->name;
                } else {
                    throw new RuntimeException(sprintf('There is no public %s method in class %s. Please specify which public method should be used for setting the value of the property %s.', 'set'.ucfirst($this->name), $this->class, $this->name));
                }
            }
        }

        $this->getter = $getter;
        $this->setter = $setter;
    }

    public function getValue($obj)
    {
        if (null === $this->getter) {
            return parent::getValue($obj);
        }

        return $obj->{$this->getter}();
    }

    public function setType($type)
    {
        if (null === self::$typeParser) {
            self::$typeParser = new TypeParser();
        }

        $this->type = self::$typeParser->parse($type);
    }

    public function serialize()
    {
        return serialize(array(
            $this->sinceVersion,
            $this->untilVersion,
            $this->groups,
            $this->serializedName,
            $this->type,
            $this->xmlCollection,
            $this->xmlCollectionInline,
            $this->xmlEntryName,
            $this->xmlKeyAttribute,
            $this->xmlAttribute,
            $this->xmlValue,
            $this->xmlKeyValuePairs,
            $this->getter,
            $this->setter,
            $this->inline,
            $this->readOnly,
            $this->xmlAttributeMap,
            $this->maxDepth,
            parent::serialize(),
        ));
    }

    public function unserialize($str)
    {
        list(
            $this->sinceVersion,
            $this->untilVersion,
            $this->groups,
            $this->serializedName,
            $this->type,
            $this->xmlCollection,
            $this->xmlCollectionInline,
            $this->xmlEntryName,
            $this->xmlKeyAttribute,
            $this->xmlAttribute,
            $this->xmlValue,
            $this->xmlKeyValuePairs,
            $this->getter,
            $this->setter,
            $this->inline,
            $this->readOnly,
            $this->xmlAttributeMap,
            $this->maxDepth,
            $parentStr
        ) = unserialize($str);

        parent::unserialize($parentStr);
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Metadata;


class VirtualPropertyMetadata extends PropertyMetadata
{
    public function __construct($class, $methodName)
    {
        if (0 === strpos($methodName, 'get')) {
            $fieldName = lcfirst(substr($methodName, 3));
        } else {
            $fieldName = $methodName;
        }

        $this->class = $class;
        $this->name = $fieldName;
        $this->getter = $methodName;
        $this->readOnly = true;
    }

    public function setValue($obj, $value)
    {
        throw new \LogicException('VirtualPropertyMetadata is immutable.');
    }

    public function setAccessor($type, $getter = null, $setter = null)
    {
    }

    public function serialize()
    {
        return serialize(array(
            $this->sinceVersion,
            $this->untilVersion,
            $this->groups,
            $this->serializedName,
            $this->type,
            $this->xmlCollection,
            $this->xmlCollectionInline,
            $this->xmlEntryName,
            $this->xmlKeyAttribute,
            $this->xmlAttribute,
            $this->xmlValue,
            $this->xmlKeyValuePairs,
            $this->getter,
            $this->setter,
            $this->inline,
            $this->readOnly,
            $this->class,
            $this->name
        ));
    }

    public function unserialize($str)
    {
        list(
            $this->sinceVersion,
            $this->untilVersion,
            $this->groups,
            $this->serializedName,
            $this->type,
            $this->xmlCollection,
            $this->xmlCollectionInline,
            $this->xmlEntryName,
            $this->xmlKeyAttribute,
            $this->xmlAttribute,
            $this->xmlValue,
            $this->xmlKeyValuePairs,
            $this->getter,
            $this->setter,
            $this->inline,
            $this->readOnly,
            $this->class,
            $this->name
        ) = unserialize($str);
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Metadata;

use JMS\Serializer\Exception\InvalidArgumentException;
use Metadata\MergeableInterface;
use Metadata\MethodMetadata;
use Metadata\MergeableClassMetadata;
use Metadata\PropertyMetadata as BasePropertyMetadata;

/**
 * Class Metadata used to customize the serialization process.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ClassMetadata extends MergeableClassMetadata
{
    const ACCESSOR_ORDER_UNDEFINED = 'undefined';
    const ACCESSOR_ORDER_ALPHABETICAL = 'alphabetical';
    const ACCESSOR_ORDER_CUSTOM = 'custom';

    /** @var \ReflectionMethod[] */
    public $preSerializeMethods = array();

    /** @var \ReflectionMethod[] */
    public $postSerializeMethods = array();

    /** @var \ReflectionMethod[] */
    public $postDeserializeMethods = array();

    public $xmlRootName;
    public $accessorOrder;
    public $customOrder;
    public $handlerCallbacks = array();

    public $discriminatorDisabled = false;
    public $discriminatorBaseClass;
    public $discriminatorFieldName;
    public $discriminatorValue;
    public $discriminatorMap = array();

    public function setDiscriminator($fieldName, array $map)
    {
        if (empty($fieldName)) {
            throw new \InvalidArgumentException('The $fieldName cannot be empty.');
        }

        if (empty($map)) {
            throw new \InvalidArgumentException('The discriminator map cannot be empty.');
        }

        $this->discriminatorBaseClass = $this->name;
        $this->discriminatorFieldName = $fieldName;
        $this->discriminatorMap = $map;
    }

    /**
     * Sets the order of properties in the class.
     *
     * @param string $order
     * @param array $customOrder
     *
     * @throws InvalidArgumentException When the accessor order is not valid
     * @throws InvalidArgumentException When the custom order is not valid
     */
    public function setAccessorOrder($order, array $customOrder = array())
    {
        if (!in_array($order, array(self::ACCESSOR_ORDER_UNDEFINED, self::ACCESSOR_ORDER_ALPHABETICAL, self::ACCESSOR_ORDER_CUSTOM), true)) {
            throw new InvalidArgumentException(sprintf('The accessor order "%s" is invalid.', $order));
        }

        foreach ($customOrder as $name) {
            if (!is_string($name)) {
                throw new InvalidArgumentException(sprintf('$customOrder is expected to be a list of strings, but got element of value %s.', json_encode($name)));
            }
        }

        $this->accessorOrder = $order;
        $this->customOrder = array_flip($customOrder);
        $this->sortProperties();
    }

    public function addPropertyMetadata(BasePropertyMetadata $metadata)
    {
        parent::addPropertyMetadata($metadata);
        $this->sortProperties();
    }

    public function addPreSerializeMethod(MethodMetadata $method)
    {
        $this->preSerializeMethods[] = $method;
    }

    public function addPostSerializeMethod(MethodMetadata $method)
    {
        $this->postSerializeMethods[] = $method;
    }

    public function addPostDeserializeMethod(MethodMetadata $method)
    {
        $this->postDeserializeMethods[] = $method;
    }

    /**
     * @param integer $direction
     * @param string|integer $format
     * @param string $methodName
     */
    public function addHandlerCallback($direction, $format, $methodName)
    {
        $this->handlerCallbacks[$direction][$format] = $methodName;
    }

    public function merge(MergeableInterface $object)
    {
        if ( ! $object instanceof ClassMetadata) {
            throw new InvalidArgumentException('$object must be an instance of ClassMetadata.');
        }
        parent::merge($object);

        $this->preSerializeMethods = array_merge($this->preSerializeMethods, $object->preSerializeMethods);
        $this->postSerializeMethods = array_merge($this->postSerializeMethods, $object->postSerializeMethods);
        $this->postDeserializeMethods = array_merge($this->postDeserializeMethods, $object->postDeserializeMethods);
        $this->xmlRootName = $object->xmlRootName;

        // Handler methods are taken from the outer class completely.
        $this->handlerCallbacks = $object->handlerCallbacks;

        if ($object->accessorOrder) {
            $this->accessorOrder = $object->accessorOrder;
            $this->customOrder = $object->customOrder;
        }

        if ($object->discriminatorFieldName && $this->discriminatorFieldName) {
            throw new \LogicException(sprintf(
                'The discriminator of class "%s" would overwrite the discriminator of the parent class "%s". Please define all possible sub-classes in the discriminator of %s.',
                $object->name,
                $this->discriminatorBaseClass,
                $this->discriminatorBaseClass
            ));
        }

        if ($this->discriminatorMap && ! $this->reflection->isAbstract()) {
            if (false === $typeValue = array_search($this->name, $this->discriminatorMap, true)) {
                throw new \LogicException(sprintf(
                    'The sub-class "%s" is not listed in the discriminator of the base class "%s".',
                    $this->name,
                    $this->discriminatorBaseClass
                ));
            }

            $this->discriminatorValue = $typeValue;

            if (isset($this->propertyMetadata[$this->discriminatorFieldName])
                    && ! $this->propertyMetadata[$this->discriminatorFieldName] instanceof StaticPropertyMetadata) {
                throw new \LogicException(sprintf(
                    'The discriminator field name "%s" of the base-class "%s" conflicts with a regular property of the sub-class "%s".',
                    $this->discriminatorFieldName,
                    $this->discriminatorBaseClass,
                    $this->name
                ));
            }

            $discriminatorProperty = new StaticPropertyMetadata(
                $this->name,
                $this->discriminatorFieldName,
                $typeValue
            );
            $discriminatorProperty->serializedName = $this->discriminatorFieldName;
            $this->propertyMetadata[$this->discriminatorFieldName] = $discriminatorProperty;
        }

        $this->sortProperties();
    }

    public function serialize()
    {
        $this->sortProperties();

        return serialize(array(
            $this->preSerializeMethods,
            $this->postSerializeMethods,
            $this->postDeserializeMethods,
            $this->xmlRootName,
            $this->accessorOrder,
            $this->customOrder,
            $this->handlerCallbacks,
            $this->discriminatorDisabled,
            $this->discriminatorBaseClass,
            $this->discriminatorFieldName,
            $this->discriminatorValue,
            $this->discriminatorMap,
            parent::serialize(),
        ));
    }

    public function unserialize($str)
    {
        list(
            $this->preSerializeMethods,
            $this->postSerializeMethods,
            $this->postDeserializeMethods,
            $this->xmlRootName,
            $this->accessorOrder,
            $this->customOrder,
            $this->handlerCallbacks,
            $this->discriminatorDisabled,
            $this->discriminatorBaseClass,
            $this->discriminatorFieldName,
            $this->discriminatorValue,
            $this->discriminatorMap,
            $parentStr
        ) = unserialize($str);

        parent::unserialize($parentStr);
    }

    private function sortProperties()
    {
        switch ($this->accessorOrder) {
            case self::ACCESSOR_ORDER_ALPHABETICAL:
                ksort($this->propertyMetadata);
                break;

            case self::ACCESSOR_ORDER_CUSTOM:
                $order = $this->customOrder;
                uksort($this->propertyMetadata, function($a, $b) use ($order) {
                    $existsA = isset($order[$a]);
                    $existsB = isset($order[$b]);

                    if (!$existsA && !$existsB) {
                        return 0;
                    }

                    if (!$existsA) {
                        return 1;
                    }

                    if (!$existsB) {
                        return -1;
                    }

                    return $order[$a] < $order[$b] ? -1 : 1;
                });
                break;
        }
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Metadata\Driver;

use Doctrine\Common\Persistence\ManagerRegistry;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
use Metadata\Driver\DriverInterface;
use Doctrine\ORM\Mapping\ClassMetadataInfo;

/**
 * This class decorates any other driver. If the inner driver does not provide a
 * a property type, the decorator will guess based on Doctrine 2 metadata.
 */
class DoctrineTypeDriver implements DriverInterface
{
    /**
     * Map of doctrine 2 field types to JMS\Serializer types
     * @var array
     */
    protected $fieldMapping = array(
        'string'       => 'string',
        'text'         => 'string',
        'blob'         => 'string',

        'integer'      => 'integer',
        'smallint'     => 'integer',
        'bigint'       => 'integer',

        'datetime'     => 'DateTime',
        'datetimetz'   => 'DateTime',
        'time'         => 'DateTime',

        'float'        => 'float',
        'decimal'      => 'float',

        'boolean'      => 'boolean',

        'array'        => 'array',
        'json_array'   => 'array',
        'simple_array' => 'array<string>',
    );

    /**
     * @var DriverInterface
     */
    protected $delegate;

    /**
     * @var ManagerRegistry
     */
    protected $registry;

    public function __construct(DriverInterface $delegate, ManagerRegistry $registry)
    {
        $this->delegate = $delegate;
        $this->registry = $registry;
    }

    public function loadMetadataForClass(\ReflectionClass $class)
    {
        /** @var $classMetadata ClassMetadata */
        $classMetadata = $this->delegate->loadMetadataForClass($class);

        // Abort if the given class is not a mapped entity
        if (!$doctrineMetadata = $this->tryLoadingDoctrineMetadata($class->name)) {
            return $classMetadata;
        }

        if ($doctrineMetadata instanceof ClassMetadataInfo) {
            if (empty($classMetadata->discriminatorMap) && ! $classMetadata->discriminatorDisabled
                    && ! empty($doctrineMetadata->discriminatorMap) && $doctrineMetadata->isRootEntity()) {
                $classMetadata->setDiscriminator(
                    $doctrineMetadata->discriminatorColumn['name'],
                    $doctrineMetadata->discriminatorMap
                );
            }
        }

        // We base our scan on the internal driver's property list so that we
        // respect any internal white/blacklisting like in the AnnotationDriver
        foreach ($classMetadata->propertyMetadata as $propertyMetadata) {
            /** @var $propertyMetadata PropertyMetadata */

            // If the inner driver provides a type, don't guess anymore.
            if ($propertyMetadata->type) {
                continue;
            }

            $propertyName = $propertyMetadata->name;
            if ($doctrineMetadata->hasField($propertyName) && $fieldType = $this->normalizeFieldType($doctrineMetadata->getTypeOfField($propertyName))) {
                $propertyMetadata->setType($fieldType);
            } elseif ($doctrineMetadata->hasAssociation($propertyName)) {
                $targetEntity = $doctrineMetadata->getAssociationTargetClass($propertyName);

                if (null === $targetMetadata = $this->tryLoadingDoctrineMetadata($targetEntity)) {
                    continue;
                }

                // For inheritance schemes, we cannot add any type as we would only add the super-type of the hierarchy.
                // On serialization, this would lead to only the supertype being serialized, and properties of subtypes
                // being ignored.
                if ($targetMetadata instanceof ClassMetadataInfo && ! $targetMetadata->isInheritanceTypeNone()) {
                    continue;
                }

                if ($doctrineMetadata->isSingleValuedAssociation($propertyName)) {
                    $propertyMetadata->setType($targetEntity);
                } else {
                    $propertyMetadata->setType("ArrayCollection<{$targetEntity}>");
                }
            }
        }

        return $classMetadata;
    }

    /**
     * @param string $className
     *
     * @return ClassMetadataInfo|null
     */
    private function tryLoadingDoctrineMetadata($className) {
        if (!$manager = $this->registry->getManagerForClass($className)) {
            return null;
        }

        if ($manager->getMetadataFactory()->isTransient($className)) {
            return null;
        }

        return $manager->getClassMetadata($className);
    }

    private function normalizeFieldType($type)
    {
        if (!isset($this->fieldMapping[$type])) {
            return;
        }

        return $this->fieldMapping[$type];
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Metadata\Driver;

use JMS\Serializer\Exception\RuntimeException;
use JMS\Serializer\Metadata\ClassMetadata;
use Metadata\Driver\AbstractFileDriver;

class PhpDriver extends AbstractFileDriver
{
    protected function loadMetadataFromFile(\ReflectionClass $class, $file)
    {
        $metadata = require $file;

        if (!$metadata instanceof ClassMetadata) {
            throw new RuntimeException(sprintf('The file %s was expected to return an instance of ClassMetadata, but returned %s.', $file, json_encode($metadata)));
        }
        if ($metadata->name !== $class->name) {
            throw new RuntimeException(sprintf('The file %s was expected to return metadata for class %s, but instead returned metadata for class %s.', $class->name, $metadata->name));
        }

        return $metadata;
    }

    protected function getExtension()
    {
        return 'php';
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Metadata\Driver;

use JMS\Serializer\GraphNavigator;
use JMS\Serializer\Exception\RuntimeException;
use JMS\Serializer\Annotation\ExclusionPolicy;
use Metadata\MethodMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Metadata\VirtualPropertyMetadata;
use JMS\Serializer\Metadata\ClassMetadata;
use Symfony\Component\Yaml\Yaml;
use Metadata\Driver\AbstractFileDriver;

class YamlDriver extends AbstractFileDriver
{
    protected function loadMetadataFromFile(\ReflectionClass $class, $file)
    {
        $config = Yaml::parse(file_get_contents($file));

        if (!isset($config[$name = $class->name])) {
            throw new RuntimeException(sprintf('Expected metadata for class %s to be defined in %s.', $class->name, $file));
        }

        $config = $config[$name];
        $metadata = new ClassMetadata($name);
        $metadata->fileResources[] = $file;
        $metadata->fileResources[] = $class->getFileName();
        $exclusionPolicy = isset($config['exclusion_policy']) ? strtoupper($config['exclusion_policy']) : 'NONE';
        $excludeAll = isset($config['exclude']) ? (Boolean) $config['exclude'] : false;
        $classAccessType = isset($config['access_type']) ? $config['access_type'] : PropertyMetadata::ACCESS_TYPE_PROPERTY;

        $propertiesMetadata = array();

        if (isset($config['accessor_order'])) {
            $metadata->setAccessorOrder($config['accessor_order'], isset($config['custom_accessor_order']) ? $config['custom_accessor_order'] : array());
        }

        if (isset($config['xml_root_name'])) {
            $metadata->xmlRootName = (string) $config['xml_root_name'];
        }

        if (isset($config['discriminator'])) {
            if (isset($config['discriminator']['disabled']) && true === $config['discriminator']['disabled']) {
                $metadata->discriminatorDisabled = true;
            } else {
                if ( ! isset($config['discriminator']['field_name'])) {
                    throw new RuntimeException('The "field_name" attribute must be set for discriminators.');
                }

                if ( ! isset($config['discriminator']['map']) || ! is_array($config['discriminator']['map'])) {
                    throw new RuntimeException('The "map" attribute must be set, and be an array for discriminators.');
                }

                $metadata->setDiscriminator($config['discriminator']['field_name'], $config['discriminator']['map']);
            }
        }

        if (array_key_exists('virtual_properties', $config) ) {

            foreach ( $config['virtual_properties'] as $methodName => $propertySettings ) {

                if ( !$class->hasMethod( $methodName ) ) {
                    throw new RuntimeException('The method '.$methodName.' not found in class ' . $class->name);
                }

                $virtualPropertyMetadata = new VirtualPropertyMetadata( $name, $methodName );

                $propertiesMetadata[$methodName] = $virtualPropertyMetadata;
                $config['properties'][$methodName] = $propertySettings;
            }
        }

        if (!$excludeAll) {
            foreach ($class->getProperties() as $property) {
                if ($name !== $property->class) {
                    continue;
                }
                $pName = $property->getName();
                $propertiesMetadata[$pName] = new PropertyMetadata($name, $pName);
            }

            foreach ($propertiesMetadata as $pName => $pMetadata) {

                $isExclude = false;
                $isExpose = $pMetadata instanceof VirtualPropertyMetadata;

                if (isset($config['properties'][$pName])) {
                    $pConfig = $config['properties'][$pName];

                    if (isset($pConfig['exclude'])) {
                        $isExclude = (Boolean) $pConfig['exclude'];
                    }

                    if (isset($pConfig['expose'])) {
                        $isExpose = (Boolean) $pConfig['expose'];
                    }

                    if (isset($pConfig['since_version'])) {
                        $pMetadata->sinceVersion = (string) $pConfig['since_version'];
                    }

                    if (isset($pConfig['until_version'])) {
                        $pMetadata->untilVersion = (string) $pConfig['until_version'];
                    }

                    if (isset($pConfig['serialized_name'])) {
                        $pMetadata->serializedName = (string) $pConfig['serialized_name'];
                    }

                    if (isset($pConfig['type'])) {
                        $pMetadata->setType((string) $pConfig['type']);
                    }

                    if (isset($pConfig['groups'])) {
                        $pMetadata->groups = $pConfig['groups'];
                    }

                    if (isset($pConfig['xml_list'])) {
                        $pMetadata->xmlCollection = true;

                        $colConfig = $pConfig['xml_list'];
                        if (isset($colConfig['inline'])) {
                            $pMetadata->xmlCollectionInline = (Boolean) $colConfig['inline'];
                        }

                        if (isset($colConfig['entry_name'])) {
                            $pMetadata->xmlEntryName = (string) $colConfig['entry_name'];
                        }
                    }

                    if (isset($pConfig['xml_map'])) {
                        $pMetadata->xmlCollection = true;

                        $colConfig = $pConfig['xml_map'];
                        if (isset($colConfig['inline'])) {
                            $pMetadata->xmlCollectionInline = (Boolean) $colConfig['inline'];
                        }

                        if (isset($colConfig['entry_name'])) {
                            $pMetadata->xmlEntryName = (string) $colConfig['entry_name'];
                        }

                        if (isset($colConfig['key_attribute_name'])) {
                            $pMetadata->xmlKeyAttribute = $colConfig['key_attribute_name'];
                        }
                    }

                    if (isset($pConfig['xml_attribute'])) {
                        $pMetadata->xmlAttribute = (Boolean) $pConfig['xml_attribute'];
                    }

                    if (isset($pConfig['xml_attribute_map'])) {
                        $pMetadata->xmlAttribute = (Boolean) $pConfig['xml_attribute_map'];
                    }

                    if (isset($pConfig['xml_value'])) {
                        $pMetadata->xmlValue = (Boolean) $pConfig['xml_value'];
                    }

                    if (isset($pConfig['xml_key_value_pairs'])) {
                        $pMetadata->xmlKeyValuePairs = (Boolean) $pConfig['xml_key_value_pairs'];
                    }

                    //we need read_only before setter and getter set, because that method depends on flag being set
                    if (isset($pConfig['read_only'])) {
                          $pMetadata->readOnly = (Boolean) $pConfig['read_only'];
                    }

                    $pMetadata->setAccessor(
                        isset($pConfig['access_type']) ? $pConfig['access_type'] : $classAccessType,
                        isset($pConfig['accessor']['getter']) ? $pConfig['accessor']['getter'] : null,
                        isset($pConfig['accessor']['setter']) ? $pConfig['accessor']['setter'] : null
                    );

                    if (isset($pConfig['inline'])) {
                        $pMetadata->inline = (Boolean) $pConfig['inline'];
                    }

                    if (isset($pConfig['max_depth'])) {
                        $pMetadata->maxDepth = (int) $pConfig['max_depth'];
                    }
                }
                if ((ExclusionPolicy::NONE === $exclusionPolicy && !$isExclude)
                || (ExclusionPolicy::ALL === $exclusionPolicy && $isExpose)) {
                    $metadata->addPropertyMetadata($pMetadata);
                }
            }
        }

        if (isset($config['handler_callbacks'])) {
            foreach ($config['handler_callbacks'] as $direction => $formats) {
                foreach ($formats as $format => $methodName) {
                    $direction = GraphNavigator::parseDirection($direction);
                    $metadata->addHandlerCallback($direction, $format, $methodName);
                }
            }
        }

        if (isset($config['callback_methods'])) {
            $cConfig = $config['callback_methods'];

            if (isset($cConfig['pre_serialize'])) {
                $metadata->preSerializeMethods = $this->getCallbackMetadata($class, $cConfig['pre_serialize']);
            }
            if (isset($cConfig['post_serialize'])) {
                $metadata->postSerializeMethods = $this->getCallbackMetadata($class, $cConfig['post_serialize']);
            }
            if (isset($cConfig['post_deserialize'])) {
                $metadata->postDeserializeMethods = $this->getCallbackMetadata($class, $cConfig['post_deserialize']);
            }
        }

        return $metadata;
    }

    protected function getExtension()
    {
        return 'yml';
    }

    private function getCallbackMetadata(\ReflectionClass $class, $config)
    {
        if (is_string($config)) {
            $config = array($config);
        } elseif (!is_array($config)) {
            throw new RuntimeException(sprintf('callback methods expects a string, or an array of strings that represent method names, but got %s.', json_encode($config['pre_serialize'])));
        }

        $methods = array();
        foreach ($config as $name) {
            if (!$class->hasMethod($name)) {
                throw new RuntimeException(sprintf('The method %s does not exist in class %s.', $name, $class->name));
            }

            $methods[] = new MethodMetadata($class->name, $name);
        }

        return $methods;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Metadata\Driver;

use JMS\Serializer\Annotation\Discriminator;
use JMS\Serializer\GraphNavigator;
use JMS\Serializer\Annotation\HandlerCallback;
use JMS\Serializer\Annotation\AccessorOrder;
use JMS\Serializer\Annotation\Accessor;
use JMS\Serializer\Annotation\AccessType;
use JMS\Serializer\Annotation\XmlMap;
use JMS\Serializer\Annotation\XmlRoot;
use JMS\Serializer\Annotation\XmlAttribute;
use JMS\Serializer\Annotation\XmlList;
use JMS\Serializer\Annotation\XmlValue;
use JMS\Serializer\Annotation\XmlKeyValuePairs;
use JMS\Serializer\Annotation\PostSerialize;
use JMS\Serializer\Annotation\PostDeserialize;
use JMS\Serializer\Annotation\PreSerialize;
use JMS\Serializer\Annotation\VirtualProperty;
use Metadata\MethodMetadata;
use Doctrine\Common\Annotations\Reader;
use JMS\Serializer\Annotation\Type;
use JMS\Serializer\Annotation\Exclude;
use JMS\Serializer\Annotation\Groups;
use JMS\Serializer\Annotation\Expose;
use JMS\Serializer\Annotation\SerializedName;
use JMS\Serializer\Annotation\Until;
use JMS\Serializer\Annotation\Since;
use JMS\Serializer\Annotation\ExclusionPolicy;
use JMS\Serializer\Annotation\Inline;
use JMS\Serializer\Annotation\ReadOnly;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Metadata\VirtualPropertyMetadata;
use JMS\Serializer\Exception\InvalidArgumentException;
use JMS\Serializer\Annotation\XmlAttributeMap;
use Metadata\Driver\DriverInterface;
use JMS\Serializer\Annotation\MaxDepth;

class AnnotationDriver implements DriverInterface
{
    private $reader;

    public function __construct(Reader $reader)
    {
        $this->reader = $reader;
    }

    public function loadMetadataForClass(\ReflectionClass $class)
    {
        $classMetadata = new ClassMetadata($name = $class->name);
        $classMetadata->fileResources[] = $class->getFilename();

        $propertiesMetadata = array();
        $propertiesAnnotations = array();

        $exclusionPolicy = 'NONE';
        $excludeAll = false;
        $classAccessType = PropertyMetadata::ACCESS_TYPE_PROPERTY;
        foreach ($this->reader->getClassAnnotations($class) as $annot) {
            if ($annot instanceof ExclusionPolicy) {
                $exclusionPolicy = $annot->policy;
            } elseif ($annot instanceof XmlRoot) {
                $classMetadata->xmlRootName = $annot->name;
            } elseif ($annot instanceof Exclude) {
                $excludeAll = true;
            } elseif ($annot instanceof AccessType) {
                $classAccessType = $annot->type;
            } elseif ($annot instanceof AccessorOrder) {
                $classMetadata->setAccessorOrder($annot->order, $annot->custom);
            } elseif ($annot instanceof Discriminator) {
                if ($annot->disabled) {
                    $classMetadata->discriminatorDisabled = true;
                } else {
                    $classMetadata->setDiscriminator($annot->field, $annot->map);
                }
            }
        }

        foreach ($class->getMethods() as $method) {
            if ($method->class !== $name) {
                continue;
            }

            $methodAnnotations = $this->reader->getMethodAnnotations($method);

            foreach ($methodAnnotations as $annot) {
                if ($annot instanceof PreSerialize) {
                    $classMetadata->addPreSerializeMethod(new MethodMetadata($name, $method->name));
                    continue 2;
                } elseif ($annot instanceof PostDeserialize) {
                    $classMetadata->addPostDeserializeMethod(new MethodMetadata($name, $method->name));
                    continue 2;
                } elseif ($annot instanceof PostSerialize) {
                    $classMetadata->addPostSerializeMethod(new MethodMetadata($name, $method->name));
                    continue 2;
                } elseif ($annot instanceof VirtualProperty) {
                    $virtualPropertyMetadata = new VirtualPropertyMetadata($name, $method->name);
                    $propertiesMetadata[] = $virtualPropertyMetadata;
                    $propertiesAnnotations[] = $methodAnnotations;
                    continue 2;
                } elseif ($annot instanceof HandlerCallback) {
                    $classMetadata->addHandlerCallback(GraphNavigator::parseDirection($annot->direction), $annot->format, $method->name);
                    continue 2;
                }
            }
        }

        if (!$excludeAll) {
            foreach ($class->getProperties() as $property) {
                if ($property->class !== $name) {
                    continue;
                }
                $propertiesMetadata[] = new PropertyMetadata($name, $property->getName());
                $propertiesAnnotations[] = $this->reader->getPropertyAnnotations($property);
            }

            foreach ($propertiesMetadata as $propertyKey => $propertyMetadata) {

                $isExclude = false;
                $isExpose = $propertyMetadata instanceof VirtualPropertyMetadata;
                $accessType = $classAccessType;
                $accessor = array(null, null);

                $propertyAnnotations = $propertiesAnnotations[$propertyKey];

                foreach ($propertyAnnotations as $annot) {
                    if ($annot instanceof Since) {
                        $propertyMetadata->sinceVersion = $annot->version;
                    } elseif ($annot instanceof Until) {
                        $propertyMetadata->untilVersion = $annot->version;
                    } elseif ($annot instanceof SerializedName) {
                        $propertyMetadata->serializedName = $annot->name;
                    } elseif ($annot instanceof Expose) {
                        $isExpose = true;
                    } elseif ($annot instanceof Exclude) {
                        $isExclude = true;
                    } elseif ($annot instanceof Type) {
                        $propertyMetadata->setType($annot->name);
                    } elseif ($annot instanceof XmlList) {
                        $propertyMetadata->xmlCollection = true;
                        $propertyMetadata->xmlCollectionInline = $annot->inline;
                        $propertyMetadata->xmlEntryName = $annot->entry;
                    } elseif ($annot instanceof XmlMap) {
                        $propertyMetadata->xmlCollection = true;
                        $propertyMetadata->xmlCollectionInline = $annot->inline;
                        $propertyMetadata->xmlEntryName = $annot->entry;
                        $propertyMetadata->xmlKeyAttribute = $annot->keyAttribute;
                    } elseif ($annot instanceof XmlKeyValuePairs) {
                        $propertyMetadata->xmlKeyValuePairs = true;
                    } elseif ($annot instanceof XmlAttribute) {
                        $propertyMetadata->xmlAttribute = true;
                    } elseif ($annot instanceof XmlValue) {
                        $propertyMetadata->xmlValue = true;
                    } elseif ($annot instanceof AccessType) {
                        $accessType = $annot->type;
                    } elseif ($annot instanceof ReadOnly) {
                       $propertyMetadata->readOnly = true;
                    } elseif ($annot instanceof Accessor) {
                        $accessor = array($annot->getter, $annot->setter);
                    } elseif ($annot instanceof Groups) {
                        $propertyMetadata->groups = $annot->groups;
                        foreach ((array) $propertyMetadata->groups as $groupName) {
                            if (false !== strpos($groupName, ',')) {
                                throw new InvalidArgumentException(sprintf(
                                    'Invalid group name "%s" on "%s", did you mean to create multiple groups?',
                                    implode(', ', $propertyMetadata->groups),
                                    $propertyMetadata->class.'->'.$propertyMetadata->name
                                ));
                            }
                        }
                    } elseif ($annot instanceof Inline) {
                        $propertyMetadata->inline = true;
                    } elseif ($annot instanceof XmlAttributeMap) {
                        $propertyMetadata->xmlAttributeMap = true;
                    } elseif ($annot instanceof MaxDepth) {
                        $propertyMetadata->maxDepth = $annot->depth;
                    }
                }

                $propertyMetadata->setAccessor($accessType, $accessor[0], $accessor[1]);

                if ((ExclusionPolicy::NONE === $exclusionPolicy && !$isExclude)
                    || (ExclusionPolicy::ALL === $exclusionPolicy && $isExpose)) {
                    $classMetadata->addPropertyMetadata($propertyMetadata);
                }
            }
        }

        return $classMetadata;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Metadata\Driver;

use JMS\Serializer\GraphNavigator;
use JMS\Serializer\Exception\RuntimeException;
use JMS\Serializer\Exception\XmlErrorException;
use JMS\Serializer\Annotation\ExclusionPolicy;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Metadata\VirtualPropertyMetadata;
use Metadata\MethodMetadata;
use JMS\Serializer\Metadata\ClassMetadata;
use Metadata\Driver\AbstractFileDriver;

class XmlDriver extends AbstractFileDriver
{
    protected function loadMetadataFromFile(\ReflectionClass $class, $path)
    {
        $previous = libxml_use_internal_errors(true);
        $elem = simplexml_load_file($path);
        libxml_use_internal_errors($previous);

        if (false === $elem) {
            throw new XmlErrorException(libxml_get_last_error());
        }

        $metadata = new ClassMetadata($name = $class->name);
        if (!$elems = $elem->xpath("./class[@name = '".$name."']")) {
            throw new RuntimeException(sprintf('Could not find class %s inside XML element.', $name));
        }
        $elem = reset($elems);

        $metadata->fileResources[] = $path;
        $metadata->fileResources[] = $class->getFileName();
        $exclusionPolicy = strtoupper($elem->attributes()->{'exclusion-policy'}) ?: 'NONE';
        $excludeAll = null !== ($exclude = $elem->attributes()->exclude) ? 'true' === strtolower($exclude) : false;
        $classAccessType = (string) ($elem->attributes()->{'access-type'} ?: PropertyMetadata::ACCESS_TYPE_PROPERTY);

        $propertiesMetadata = array();
        $propertiesNodes = array();

        if (null !== $accessorOrder = $elem->attributes()->{'accessor-order'}) {
            $metadata->setAccessorOrder((string) $accessorOrder, preg_split('/\s*,\s*/', (string) $elem->attributes()->{'custom-accessor-order'}));
        }

        if (null !== $xmlRootName = $elem->attributes()->{'xml-root-name'}) {
            $metadata->xmlRootName = (string) $xmlRootName;
        }

        $discriminatorFieldName = (string) $elem->attributes()->{'discriminator-field-name'};
        $discriminatorMap = array();
        foreach ($elem->xpath('./discriminator-class') as $entry) {
            if ( ! isset($entry->attributes()->value)) {
                throw new RuntimeException('Each discriminator-class element must have a "value" attribute.');
            }

            $discriminatorMap[(string) $entry->attributes()->value] = (string) $entry;
        }

        if ('true' === (string) $elem->attributes()->{'discriminator-disabled'}) {
            $metadata->discriminatorDisabled = true;
        } elseif ( ! empty($discriminatorFieldName) || ! empty($discriminatorMap)) {
            $metadata->setDiscriminator($discriminatorFieldName, $discriminatorMap);
        }

        foreach ($elem->xpath('./virtual-property') as $method) {
            if (!isset($method->attributes()->method)) {
                throw new RuntimeException('The method attribute must be set for all virtual-property elements.');
            }

            $virtualPropertyMetadata = new VirtualPropertyMetadata( $name, (string) $method->attributes()->method );

            $propertiesMetadata[] = $virtualPropertyMetadata;
            $propertiesNodes[] = $method;
        }

        if (!$excludeAll) {

            foreach ($class->getProperties() as $property) {
                if ($name !== $property->class) {
                    continue;
                }

                $propertiesMetadata[] = new PropertyMetadata($name, $pName = $property->getName());
                $pElems = $elem->xpath("./property[@name = '".$pName."']");

                $propertiesNodes[] = $pElems ? reset( $pElems ) : null;
            }

            foreach ($propertiesMetadata as $propertyKey => $pMetadata) {

                $isExclude = false;
                $isExpose = $pMetadata instanceof VirtualPropertyMetadata;

                $pElem = $propertiesNodes[$propertyKey];
                if (!empty( $pElem )) {

                    if (null !== $exclude = $pElem->attributes()->exclude) {
                        $isExclude = 'true' === strtolower($exclude);
                    }

                    if (null !== $expose = $pElem->attributes()->expose) {
                        $isExpose = 'true' === strtolower($expose);
                    }

                    if (null !== $version = $pElem->attributes()->{'since-version'}) {
                        $pMetadata->sinceVersion = (string) $version;
                    }

                    if (null !== $version = $pElem->attributes()->{'until-version'}) {
                        $pMetadata->untilVersion = (string) $version;
                    }

                    if (null !== $serializedName = $pElem->attributes()->{'serialized-name'}) {
                        $pMetadata->serializedName = (string) $serializedName;
                    }

                    if (null !== $type = $pElem->attributes()->type) {
                        $pMetadata->setType((string) $type);
                    } elseif (isset($pElem->type)) {
                        $pMetadata->setType((string) $pElem->type);
                    }

                    if (null !== $groups = $pElem->attributes()->groups) {
                        $pMetadata->groups =  preg_split('/\s*,\s*/', (string) $groups);
                    }

                    if (isset($pElem->{'xml-list'})) {
                        $pMetadata->xmlCollection = true;

                        $colConfig = $pElem->{'xml-list'};
                        if (isset($colConfig->attributes()->inline)) {
                            $pMetadata->xmlCollectionInline = 'true' === (string) $colConfig->attributes()->inline;
                        }

                        if (isset($colConfig->attributes()->{'entry-name'})) {
                            $pMetadata->xmlEntryName = (string) $colConfig->attributes()->{'entry-name'};
                        }
                    }

                    if (isset($pElem->{'xml-map'})) {
                        $pMetadata->xmlCollection = true;

                        $colConfig = $pElem->{'xml-map'};
                        if (isset($colConfig->attributes()->inline)) {
                            $pMetadata->xmlCollectionInline = 'true' === (string) $colConfig->attributes()->inline;
                        }

                        if (isset($colConfig->attributes()->{'entry-name'})) {
                            $pMetadata->xmlEntryName = (string) $colConfig->attributes()->{'entry-name'};
                        }

                        if (isset($colConfig->attributes()->{'key-attribute-name'})) {
                            $pMetadata->xmlKeyAttribute = (string) $colConfig->attributes()->{'key-attribute-name'};
                        }
                    }

                    if (isset($pElem->attributes()->{'xml-attribute'})) {
                        $pMetadata->xmlAttribute = 'true' === (string) $pElem->attributes()->{'xml-attribute'};
                    }

                    if (isset($pElem->attributes()->{'xml-attribute-map'})) {
                        $pMetadata->xmlAttribute = 'true' === (string) $pElem->attributes()->{'xml-attribute-map'};
                    }

                    if (isset($pElem->attributes()->{'xml-value'})) {
                        $pMetadata->xmlValue = 'true' === (string) $pElem->attributes()->{'xml-value'};
                    }

                    if (isset($pElem->attributes()->{'xml-key-value-pairs'})) {
                        $pMetadata->xmlKeyValuePairs = 'true' === (string) $pElem->attributes()->{'xml-key-value-pairs'};
                    }

                    if (isset($pElem->attributes()->{'max-depth'})) {
                        $pMetadata->maxDepth = (int) $pElem->attributes()->{'max-depth'};
                    }

                    //we need read-only before setter and getter set, because that method depends on flag being set
                    if (null !== $readOnly = $pElem->attributes()->{'read-only'}) {
                        $pMetadata->readOnly = 'true' === strtolower($readOnly);
                    }

                    $getter = $pElem->attributes()->{'accessor-getter'};
                    $setter = $pElem->attributes()->{'accessor-setter'};
                    $pMetadata->setAccessor(
                        (string) ($pElem->attributes()->{'access-type'} ?: $classAccessType),
                        $getter ? (string) $getter : null,
                        $setter ? (string) $setter : null
                    );

                    if (null !== $inline = $pElem->attributes()->inline) {
                        $pMetadata->inline = 'true' === strtolower($inline);
                    }

                }

                if ((ExclusionPolicy::NONE === (string)$exclusionPolicy && !$isExclude)
                    || (ExclusionPolicy::ALL === (string)$exclusionPolicy && $isExpose)) {

                    $metadata->addPropertyMetadata($pMetadata);
                }
            }
        }

        foreach ($elem->xpath('./callback-method') as $method) {
            if (!isset($method->attributes()->type)) {
                throw new RuntimeException('The type attribute must be set for all callback-method elements.');
            }
            if (!isset($method->attributes()->name)) {
                throw new RuntimeException('The name attribute must be set for all callback-method elements.');
            }

            switch ((string) $method->attributes()->type) {
                case 'pre-serialize':
                    $metadata->addPreSerializeMethod(new MethodMetadata($name, (string) $method->attributes()->name));
                    break;

                case 'post-serialize':
                    $metadata->addPostSerializeMethod(new MethodMetadata($name, (string) $method->attributes()->name));
                    break;

                case 'post-deserialize':
                    $metadata->addPostDeserializeMethod(new MethodMetadata($name, (string) $method->attributes()->name));
                    break;

                case 'handler':
                    if ( ! isset($method->attributes()->format)) {
                        throw new RuntimeException('The format attribute must be set for "handler" callback methods.');
                    }
                    if ( ! isset($method->attributes()->direction)) {
                        throw new RuntimeException('The direction attribute must be set for "handler" callback methods.');
                    }

                    $direction = GraphNavigator::parseDirection((string) $method->attributes()->direction);
                    $format = (string) $method->attributes()->format;
                    $metadata->addHandlerCallback($direction, $format, (string) $method->attributes()->name);

                    break;

                default:
                    throw new RuntimeException(sprintf('The type "%s" is not supported.', $method->attributes()->name));
            }
        }

        return $metadata;
    }

    protected function getExtension()
    {
        return 'xml';
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Metadata;

class StaticPropertyMetadata extends PropertyMetadata
{
    private $value;

    public function __construct($className, $fieldName, $fieldValue)
    {
        $this->class = $className;
        $this->name = $fieldName;
        $this->value = $fieldValue;
        $this->readOnly = true;
    }

    public function getValue($obj)
    {
        return $this->value;
    }

    public function setValue($obj, $value)
    {
        throw new \LogicException('StaticPropertyMetadata is immutable.');
    }

    public function setAccessor($type, $getter = null, $setter = null)
    {
    }

    public function serialize()
    {
        return serialize(array(
            $this->sinceVersion,
            $this->untilVersion,
            $this->groups,
            $this->serializedName,
            $this->type,
            $this->xmlCollection,
            $this->xmlCollectionInline,
            $this->xmlEntryName,
            $this->xmlKeyAttribute,
            $this->xmlAttribute,
            $this->xmlValue,
            $this->xmlKeyValuePairs,
            $this->getter,
            $this->setter,
            $this->inline,
            $this->readOnly,
            $this->class,
            $this->name,
            $this->value
        ));
    }

    public function unserialize($str)
    {
        list(
            $this->sinceVersion,
            $this->untilVersion,
            $this->groups,
            $this->serializedName,
            $this->type,
            $this->xmlCollection,
            $this->xmlCollectionInline,
            $this->xmlEntryName,
            $this->xmlKeyAttribute,
            $this->xmlAttribute,
            $this->xmlValue,
            $this->xmlKeyValuePairs,
            $this->getter,
            $this->setter,
            $this->inline,
            $this->readOnly,
            $this->class,
            $this->name,
            $this->value
        ) = unserialize($str);
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer;

use JMS\Serializer\Metadata\ClassMetadata;

class JsonSerializationVisitor extends GenericSerializationVisitor
{
    private $options = 0;

    public function getResult()
    {
        return json_encode($this->getRoot(), $this->options);
    }

    public function getOptions()
    {
        return $this->options;
    }

    public function setOptions($options)
    {
        $this->options = (integer) $options;
    }

    public function visitArray($data, array $type, Context $context)
    {
        $result = parent::visitArray($data, $type, $context);

        if (null !== $this->getRoot() && isset($type['params'][1]) && 0 === count($result)) {
            // ArrayObject is specially treated by the json_encode function and
            // serialized to { } while a mere array would be serialized to [].
            return new \ArrayObject();
        }

        return $result;
    }

    public function endVisitingObject(ClassMetadata $metadata, $data, array $type, Context $context)
    {
        $rs = parent::endVisitingObject($metadata, $data, $type, $context);

        // Force JSON output to "{}" instead of "[]" if it contains either no properties or all properties are null.
        if (empty($rs)) {
            $rs = new \ArrayObject();

            if (array() === $this->getRoot()) {
                $this->setRoot($rs);
            }
        }

        return $rs;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer;

use JMS\Serializer\Construction\ObjectConstructorInterface;
use JMS\Serializer\Handler\HandlerRegistryInterface;
use JMS\Serializer\EventDispatcher\EventDispatcherInterface;
use JMS\Serializer\Exception\UnsupportedFormatException;
use Metadata\MetadataFactoryInterface;
use PhpCollection\MapInterface;

/**
 * Serializer Implementation.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class Serializer implements SerializerInterface
{
    private $factory;
    private $handlerRegistry;
    private $objectConstructor;
    private $dispatcher;
    private $typeParser;

    /** @var \PhpCollection\MapInterface */
    private $serializationVisitors;

    /** @var \PhpCollection\MapInterface */
    private $deserializationVisitors;

    private $navigator;

    /**
     * Constructor.
     *
     * @param \Metadata\MetadataFactoryInterface $factory
     * @param Handler\HandlerRegistryInterface $handlerRegistry
     * @param Construction\ObjectConstructorInterface $objectConstructor
     * @param \PhpCollection\MapInterface<VisitorInterface> $serializationVisitors
     * @param \PhpCollection\MapInterface<VisitorInterface> $deserializationVisitors
     * @param EventDispatcher\EventDispatcherInterface $dispatcher
     * @param TypeParser $typeParser
     */
    public function __construct(MetadataFactoryInterface $factory, HandlerRegistryInterface $handlerRegistry, ObjectConstructorInterface $objectConstructor, MapInterface $serializationVisitors, MapInterface $deserializationVisitors, EventDispatcherInterface $dispatcher = null, TypeParser $typeParser = null)
    {
        $this->factory = $factory;
        $this->handlerRegistry = $handlerRegistry;
        $this->objectConstructor = $objectConstructor;
        $this->dispatcher = $dispatcher;
        $this->typeParser = $typeParser ?: new TypeParser();
        $this->serializationVisitors = $serializationVisitors;
        $this->deserializationVisitors = $deserializationVisitors;

        $this->navigator = new GraphNavigator($this->factory, $this->handlerRegistry, $this->objectConstructor, $this->dispatcher);
    }

    public function serialize($data, $format, SerializationContext $context = null)
    {
        if ( ! $this->serializationVisitors->containsKey($format)) {
            throw new UnsupportedFormatException(sprintf('The format "%s" is not supported for serialization.', $format));
        }

        if (null === $context) {
            $context = new SerializationContext();
        }

        $context->initialize(
            $format,
            $visitor = $this->serializationVisitors->get($format)->get(),
            $this->navigator,
            $this->factory
        );

        $visitor->setNavigator($this->navigator);
        $this->navigator->accept($visitor->prepare($data), null, $context);

        return $visitor->getResult();
    }

    public function deserialize($data, $type, $format, DeserializationContext $context = null)
    {
        if ( ! $this->deserializationVisitors->containsKey($format)) {
            throw new UnsupportedFormatException(sprintf('The format "%s" is not supported for deserialization.', $format));
        }

        if (null === $context) {
            $context = new DeserializationContext();
        }

        $context->initialize(
            $format,
            $visitor = $this->deserializationVisitors->get($format)->get(),
            $this->navigator,
            $this->factory
        );

        $visitor->setNavigator($this->navigator);
        $navigatorResult = $this->navigator->accept($visitor->prepare($data), $this->typeParser->parse($type), $context);

        // This is a special case if the root is handled by a callback on the object iself.
        if ((null === $visitorResult = $visitor->getResult()) && null !== $navigatorResult) {
            return $navigatorResult;
        }

        return $visitorResult;
    }

    /**
     * @return MetadataFactoryInterface
     */
    public function getMetadataFactory()
    {
        return $this->factory;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Exception;

use Symfony\Component\Validator\ConstraintViolationList;

class ValidationFailedException extends RuntimeException
{
    private $list;

    public function __construct(ConstraintViolationList $list)
    {
        parent::__construct(sprintf('Validation failed with %d error(s).', count($list)));

        $this->list = $list;
    }

    public function getConstraintViolationList()
    {
        return $this->list;
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Exception;

/**
 * Base exception for the Serializer.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface Exception
{
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Exception;

/**
 * InvalidArgumentException for the Serializer.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class InvalidArgumentException extends \InvalidArgumentException implements Exception
{
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Exception;

/**
 * RuntimeException for the Serializer.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class RuntimeException extends \RuntimeException implements Exception
{
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Exception;

/**
 * LogicException for the Serializer.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class LogicException extends \LogicException implements Exception
{
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Exception;

class XmlErrorException extends RuntimeException
{
    private $xmlError;

    public function __construct(\LibXMLError $error)
    {
        switch ($error->level) {
            case LIBXML_ERR_WARNING:
                $level = 'WARNING';
                break;

            case LIBXML_ERR_FATAL:
                $level = 'FATAL';
                break;

            case LIBXML_ERR_ERROR:
                $level = 'ERROR';
                break;

            default:
                $level = 'UNKNOWN';
        }

        parent::__construct(sprintf('[%s] %s in %s (line: %d, column: %d)', $level, $error->message, $error->file, $error->line, $error->column));

        $this->xmlError = $error;
    }

    public function getXmlError()
    {
        return $this->xmlError;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Exception;

class UnsupportedFormatException extends InvalidArgumentException
{
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer;

use JMS\Serializer\EventDispatcher\ObjectEvent;
use JMS\Serializer\EventDispatcher\PreDeserializeEvent;
use JMS\Serializer\EventDispatcher\PreSerializeEvent;
use JMS\Serializer\Exception\RuntimeException;
use JMS\Serializer\Construction\ObjectConstructorInterface;
use JMS\Serializer\Handler\HandlerRegistryInterface;
use JMS\Serializer\EventDispatcher\EventDispatcherInterface;
use JMS\Serializer\Metadata\ClassMetadata;
use Metadata\MetadataFactoryInterface;
use JMS\Serializer\Exception\InvalidArgumentException;

/**
 * Handles traversal along the object graph.
 *
 * This class handles traversal along the graph, and calls different methods
 * on visitors, or custom handlers to process its nodes.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
final class GraphNavigator
{
    const DIRECTION_SERIALIZATION = 1;
    const DIRECTION_DESERIALIZATION = 2;

    private $dispatcher;
    private $metadataFactory;
    private $handlerRegistry;
    private $objectConstructor;

    /**
     * Parses a direction string to one of the direction constants.
     *
     * @param string $dirStr
     *
     * @return integer
     */
    public static function parseDirection($dirStr)
    {
        switch (strtolower($dirStr)) {
            case 'serialization':
                return self::DIRECTION_SERIALIZATION;

            case 'deserialization':
                return self::DIRECTION_DESERIALIZATION;

            default:
                throw new InvalidArgumentException(sprintf('The direction "%s" does not exist.', $dirStr));
        }
    }

    public function __construct(MetadataFactoryInterface $metadataFactory, HandlerRegistryInterface $handlerRegistry, ObjectConstructorInterface $objectConstructor, EventDispatcherInterface $dispatcher = null)
    {
        $this->dispatcher = $dispatcher;
        $this->metadataFactory = $metadataFactory;
        $this->handlerRegistry = $handlerRegistry;
        $this->objectConstructor = $objectConstructor;
    }

    /**
     * Called for each node of the graph that is being traversed.
     *
     * @param mixed $data the data depends on the direction, and type of visitor
     * @param null|array $type array has the format ["name" => string, "params" => array]
     * @param VisitorInterface $visitor
     *
     * @return mixed the return value depends on the direction, and type of visitor
     */
    public function accept($data, array $type = null, Context $context)
    {
        $visitor = $context->getVisitor();

        // If the type was not given, we infer the most specific type from the
        // input data in serialization mode.
        if (null === $type) {
            if ($context instanceof DeserializationContext) {
                throw new RuntimeException('The type must be given for all properties when deserializing.');
            }

            $typeName = gettype($data);
            if ('object' === $typeName) {
                $typeName = get_class($data);
            }

            $type = array('name' => $typeName, 'params' => array());
        }
        // If the data is null, we have to force the type to null regardless of the input in order to
        // guarantee correct handling of null values, and not have any internal auto-casting behavior.
        else if ($context instanceof SerializationContext && null === $data) {
            $type = array('name' => 'NULL', 'params' => array());
        }

        switch ($type['name']) {
            case 'NULL':
                return $visitor->visitNull($data, $type, $context);

            case 'string':
                return $visitor->visitString($data, $type, $context);

            case 'integer':
                return $visitor->visitInteger($data, $type, $context);

            case 'boolean':
                return $visitor->visitBoolean($data, $type, $context);

            case 'double':
            case 'float':
                return $visitor->visitDouble($data, $type, $context);

            case 'array':
                return $visitor->visitArray($data, $type, $context);

            case 'resource':
                $msg = 'Resources are not supported in serialized data.';
                if ($context instanceof SerializationContext && null !== $path = $context->getPath()) {
                    $msg .= ' Path: '.$path;
                }

                throw new RuntimeException($msg);

            default:
                // TODO: The rest of this method needs some refactoring.
                if ($context instanceof SerializationContext) {
                    if (null !== $data) {
                        if ($context->isVisiting($data)) {
                            return null;
                        }
                        $context->startVisiting($data);
                    }
                } elseif ($context instanceof DeserializationContext) {
                    $context->increaseDepth();
                }

                // Trigger pre-serialization callbacks, and listeners if they exist.
                // Dispatch pre-serialization event before handling data to have ability change type in listener
                if ($context instanceof SerializationContext) {
                    if (null !== $this->dispatcher && $this->dispatcher->hasListeners('serializer.pre_serialize', $type['name'], $context->getFormat())) {
                        $this->dispatcher->dispatch('serializer.pre_serialize', $type['name'], $context->getFormat(), $event = new PreSerializeEvent($context, $data, $type));
                        $type = $event->getType();
                    }
                } elseif ($context instanceof DeserializationContext) {
                    if (null !== $this->dispatcher && $this->dispatcher->hasListeners('serializer.pre_deserialize', $type['name'], $context->getFormat())) {
                        $this->dispatcher->dispatch('serializer.pre_deserialize', $type['name'], $context->getFormat(), $event = new PreDeserializeEvent($context, $data, $type));
                        $type = $event->getType();
                        $data = $event->getData();
                    }
                }

                // First, try whether a custom handler exists for the given type. This is done
                // before loading metadata because the type name might not be a class, but
                // could also simply be an artifical type.
                if (null !== $handler = $this->handlerRegistry->getHandler($context->getDirection(), $type['name'], $context->getFormat())) {
                    $rs = call_user_func($handler, $visitor, $data, $type, $context);
                    $this->leaveScope($context, $data);

                    return $rs;
                }

                $exclusionStrategy = $context->getExclusionStrategy();

                /** @var $metadata ClassMetadata */
                $metadata = $this->metadataFactory->getMetadataForClass($type['name']);

                if ($context instanceof DeserializationContext && ! empty($metadata->discriminatorMap) && $type['name'] === $metadata->discriminatorBaseClass) {
                    $metadata = $this->resolveMetadata($context, $data, $metadata);
                }

                if (null !== $exclusionStrategy && $exclusionStrategy->shouldSkipClass($metadata, $context)) {
                    $this->leaveScope($context, $data);

                    return null;
                }

                $context->pushClassMetadata($metadata);

                if ($context instanceof SerializationContext) {
                    foreach ($metadata->preSerializeMethods as $method) {
                        $method->invoke($data);
                    }
                }

                $object = $data;
                if ($context instanceof DeserializationContext) {
                    $object = $this->objectConstructor->construct($visitor, $metadata, $data, $type);
                }

                if (isset($metadata->handlerCallbacks[$context->getDirection()][$context->getFormat()])) {
                    $rs = $object->{$metadata->handlerCallbacks[$context->getDirection()][$context->getFormat()]}(
                        $visitor,
                        $context instanceof SerializationContext ? null : $data,
                        $context
                    );
                    $this->afterVisitingObject($metadata, $object, $type, $context);

                    return $context instanceof SerializationContext ? $rs : $object;
                }

                $visitor->startVisitingObject($metadata, $object, $type, $context);
                foreach ($metadata->propertyMetadata as $propertyMetadata) {
                    if (null !== $exclusionStrategy && $exclusionStrategy->shouldSkipProperty($propertyMetadata, $context)) {
                        continue;
                    }

                    if ($context instanceof DeserializationContext && $propertyMetadata->readOnly) {
                        continue;
                    }

                    $context->pushPropertyMetadata($propertyMetadata);
                    $visitor->visitProperty($propertyMetadata, $data, $context);
                    $context->popPropertyMetadata();
                }

                if ($context instanceof SerializationContext) {
                    $this->afterVisitingObject($metadata, $data, $type, $context);

                    return $visitor->endVisitingObject($metadata, $data, $type, $context);
                }

                $rs = $visitor->endVisitingObject($metadata, $data, $type, $context);
                $this->afterVisitingObject($metadata, $rs, $type, $context);

                return $rs;
        }
    }

    private function resolveMetadata(DeserializationContext $context, $data, ClassMetadata $metadata)
    {
        switch (true) {
            case is_array($data) && isset($data[$metadata->discriminatorFieldName]):
                $typeValue = (string) $data[$metadata->discriminatorFieldName];
                break;

            case is_object($data) && isset($data->{$metadata->discriminatorFieldName}):
                $typeValue = (string) $data->{$metadata->discriminatorFieldName};
                break;

            default:
                throw new \LogicException(sprintf(
                    'The discriminator field name "%s" for base-class "%s" was not found in input data.',
                    $metadata->discriminatorFieldName,
                    $metadata->name
                ));
        }

        if ( ! isset($metadata->discriminatorMap[$typeValue])) {
            throw new \LogicException(sprintf(
                'The type value "%s" does not exist in the discriminator map of class "%s". Available types: %s',
                $typeValue,
                $metadata->name,
                implode(', ', array_keys($metadata->discriminatorMap))
            ));
        }

        return $this->metadataFactory->getMetadataForClass($metadata->discriminatorMap[$typeValue]);
    }

    private function leaveScope(Context $context, $data)
    {
        if ($context instanceof SerializationContext) {
            $context->stopVisiting($data);
        } elseif ($context instanceof DeserializationContext) {
            $context->decreaseDepth();
        }
    }

    private function afterVisitingObject(ClassMetadata $metadata, $object, array $type, Context $context)
    {
        $this->leaveScope($context, $object);
        $context->popClassMetadata();

        if ($context instanceof SerializationContext) {
            foreach ($metadata->postSerializeMethods as $method) {
                $method->invoke($object);
            }

            if (null !== $this->dispatcher && $this->dispatcher->hasListeners('serializer.post_serialize', $metadata->name, $context->getFormat())) {
                $this->dispatcher->dispatch('serializer.post_serialize', $metadata->name, $context->getFormat(), new ObjectEvent($context, $object, $type));
            }

            return;
        }

        foreach ($metadata->postDeserializeMethods as $method) {
            $method->invoke($object);
        }

        if (null !== $this->dispatcher && $this->dispatcher->hasListeners('serializer.post_deserialize', $metadata->name, $context->getFormat())) {
            $this->dispatcher->dispatch('serializer.post_deserialize', $metadata->name, $context->getFormat(), new ObjectEvent($context, $object, $type));
        }
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Handler;

use Symfony\Component\DependencyInjection\ContainerInterface;

class LazyHandlerRegistry extends HandlerRegistry
{
    private $container;
    private $initializedHandlers = array();

    public function __construct(ContainerInterface $container, array $handlers = array())
    {
        parent::__construct($handlers);
        $this->container = $container;
    }

    public function registerHandler($direction, $typeName, $format, $handler)
    {
        parent::registerHandler($direction, $typeName, $format, $handler);
        unset($this->initializedHandlers[$direction][$typeName][$format]);
    }

    public function getHandler($direction, $typeName, $format)
    {
        if (isset($this->initializedHandlers[$direction][$typeName][$format])) {
            return $this->initializedHandlers[$direction][$typeName][$format];
        }

        if ( ! isset($this->handlers[$direction][$typeName][$format])) {
            return null;
        }

        $handler = $this->handlers[$direction][$typeName][$format];
        if (is_array($handler) && is_string($handler[0]) && $this->container->has($handler[0])) {
            $handler[0] = $this->container->get($handler[0]);
        }

        return $this->initializedHandlers[$direction][$typeName][$format] = $handler;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Handler;

use JMS\Serializer\GraphNavigator;
use JMS\Serializer\Exception\RuntimeException;
use JMS\Serializer\Exception\LogicException;

class HandlerRegistry implements HandlerRegistryInterface
{
    protected $handlers;

    public static function getDefaultMethod($direction, $type, $format)
    {
        if (false !== $pos = strrpos($type, '\\')) {
            $type = substr($type, $pos + 1);
        }

        switch ($direction) {
            case GraphNavigator::DIRECTION_DESERIALIZATION:
                return 'deserialize'.$type.'From'.$format;

            case GraphNavigator::DIRECTION_SERIALIZATION:
                return 'serialize'.$type.'To'.$format;

            default:
                throw new LogicException(sprintf('The direction %s does not exist; see GraphNavigator::DIRECTION_??? constants.', json_encode($direction)));
        }
    }

    public function __construct(array $handlers = array())
    {
        $this->handlers = $handlers;
    }

    public function registerSubscribingHandler(SubscribingHandlerInterface $handler)
    {
        foreach ($handler->getSubscribingMethods() as $methodData) {
            if ( ! isset($methodData['type'], $methodData['format'])) {
                throw new RuntimeException(sprintf('For each subscribing method a "type" and "format" attribute must be given, but only got "%s" for %s.', implode('" and "', array_keys($methodData)), get_class($handler)));
            }

            $directions = array(GraphNavigator::DIRECTION_DESERIALIZATION, GraphNavigator::DIRECTION_SERIALIZATION);
            if (isset($methodData['direction'])) {
                $directions = array($methodData['direction']);
            }

            foreach ($directions as $direction) {
                $method = isset($methodData['method']) ? $methodData['method'] : self::getDefaultMethod($direction, $methodData['type'], $methodData['format']);
                $this->registerHandler($direction, $methodData['type'], $methodData['format'], array($handler, $method));
            }
        }
    }

    public function registerHandler($direction, $typeName, $format, $handler)
    {
        if (is_string($direction)) {
            $direction = GraphNavigator::parseDirection($direction);
        }

        $this->handlers[$direction][$typeName][$format] = $handler;
    }

    public function getHandler($direction, $typeName, $format)
    {
        if ( ! isset($this->handlers[$direction][$typeName][$format])) {
            return null;
        }

        return $this->handlers[$direction][$typeName][$format];
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Handler;

use JMS\Serializer\YamlSerializationVisitor;
use JMS\Serializer\JsonSerializationVisitor;
use JMS\Serializer\GraphNavigator;
use JMS\Serializer\GenericSerializationVisitor;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormError;
use Symfony\Component\Translation\TranslatorInterface;
use JMS\Serializer\XmlSerializationVisitor;

class FormErrorHandler implements SubscribingHandlerInterface
{
    private $translator;

    public static function getSubscribingMethods()
    {
        $methods = array();
        foreach (array('xml', 'json', 'yml') as $format) {
            $methods[] = array(
                'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
                'type' => 'Symfony\Component\Form\Form',
                'format' => $format,
            );
            $methods[] = array(
                'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
                'type' => 'Symfony\Component\Form\FormError',
                'format' => $format,
            );
        }

        return $methods;
    }

    public function __construct(TranslatorInterface $translator)
    {
        $this->translator = $translator;
    }

    public function serializeFormToXml(XmlSerializationVisitor $visitor, Form $form, array $type)
    {
        if (null === $visitor->document) {
            $visitor->document = $visitor->createDocument(null, null, false);
            $visitor->document->appendChild($formNode = $visitor->document->createElement('form'));
            $visitor->setCurrentNode($formNode);
        } else {
            $visitor->getCurrentNode()->appendChild(
                $formNode = $visitor->document->createElement('form')
            );
        }

        $formNode->setAttribute('name', $form->getName());

        $formNode->appendChild($errorsNode = $visitor->document->createElement('errors'));
        foreach ($form->getErrors() as $error) {
            $errorNode = $visitor->document->createElement('entry');
            $errorNode->appendChild($this->serializeFormErrorToXml($visitor, $error, array()));
            $errorsNode->appendChild($errorNode);
        }

        foreach ($form->all() as $child) {
            if (null !== $node = $this->serializeFormToXml($visitor, $child, array())) {
                $formNode->appendChild($node);
            }
        }

        return $formNode;
    }

    public function serializeFormToJson(JsonSerializationVisitor $visitor, Form $form, array $type)
    {
        return $this->convertFormToArray($visitor, $form);
    }

    public function serializeFormToYml(YamlSerializationVisitor $visitor, Form $form, array $type)
    {
        return $this->convertFormToArray($visitor, $form);
    }

    public function serializeFormErrorToXml(XmlSerializationVisitor $visitor, FormError $formError, array $type)
    {
        if (null === $visitor->document) {
            $visitor->document = $visitor->createDocument(null, null, true);
        }

        return $visitor->document->createCDATASection($this->getErrorMessage($formError));
    }

    public function serializeFormErrorToJson(JsonSerializationVisitor $visitor, FormError $formError, array $type)
    {
        return $this->getErrorMessage($formError);
    }

    public function serializeFormErrorToYml(YamlSerializationVisitor $visitor, FormError $formError, array $type)
    {
        return $this->getErrorMessage($formError);
    }

    private function getErrorMessage(FormError $error)
    {
        if (null !== $error->getMessagePluralization()) {
            return $this->translator->transChoice($error->getMessageTemplate(), $error->getMessagePluralization(), $error->getMessageParameters(), 'validators');
        }

        return $this->translator->trans($error->getMessageTemplate(), $error->getMessageParameters(), 'validators');
    }

    private function convertFormToArray(GenericSerializationVisitor $visitor, Form $data)
    {
        $isRoot = null === $visitor->getRoot();

        $form = $errors = array();
        foreach ($data->getErrors() as $error) {
            $errors[] = $this->getErrorMessage($error);
        }

        if ($errors) {
            $form['errors'] = $errors;
        }

        $children = array();
        foreach ($data->all() as $child) {
            $children[$child->getName()] = $this->convertFormToArray($visitor, $child);
        }

        if ($children) {
            $form['children'] = $children;
        }

        if ($isRoot) {
            $visitor->setRoot($form);
        }

        return $form;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Handler;

use JMS\Serializer\Context;
use JMS\Serializer\YamlSerializationVisitor;
use JMS\Serializer\JsonSerializationVisitor;
use JMS\Serializer\GraphNavigator;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
use JMS\Serializer\XmlSerializationVisitor;

class ConstraintViolationHandler implements SubscribingHandlerInterface
{
    public static function getSubscribingMethods()
    {
        $methods = array();
        $formats = array('xml', 'json', 'yml');
        $types = array('Symfony\Component\Validator\ConstraintViolationList' => 'serializeList', 'Symfony\Component\Validator\ConstraintViolation' => 'serializeViolation');

        foreach ($types as $type => $method) {
            foreach ($formats as $format) {
                $methods[] = array(
                    'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
                    'type' => $type,
                    'format' => $format,
                    'method' => $method.'To'.$format,
                );
            }
        }

        return $methods;
    }

    public function serializeListToXml(XmlSerializationVisitor $visitor, ConstraintViolationList $list, array $type)
    {
        if (null === $visitor->document) {
            $visitor->document = $visitor->createDocument();
        }

        foreach ($list as $violation) {
            $this->serializeViolationToXml($visitor, $violation);
        }
    }

    public function serializeListToJson(JsonSerializationVisitor $visitor, ConstraintViolationList $list, array $type, Context $context)
    {
        return $visitor->visitArray(iterator_to_array($list), $type, $context);
    }

    public function serializeListToYml(YamlSerializationVisitor $visitor, ConstraintViolationList $list, array $type, Context $context)
    {
        return $visitor->visitArray(iterator_to_array($list), $type, $context);
    }

    public function serializeViolationToXml(XmlSerializationVisitor $visitor, ConstraintViolation $violation, array $type = null)
    {
        if (null === $visitor->document) {
            $visitor->document = $visitor->createDocument(null, null, false);
            $visitor->document->appendChild($violationNode = $visitor->document->createElement('violation'));
            $visitor->setCurrentNode($violationNode);
        } else {
            $visitor->getCurrentNode()->appendChild(
                $violationNode = $visitor->document->createElement('violation')
            );
        }

        $violationNode->setAttribute('property_path', $violation->getPropertyPath());
        $violationNode->appendChild($messageNode = $visitor->document->createElement('message'));

        $messageNode->appendChild($visitor->document->createCDATASection($violation->getMessage()));
    }

    public function serializeViolationToJson(JsonSerializationVisitor $visitor, ConstraintViolation $violation, array $type = null)
    {
        $data = array(
            'property_path' => $violation->getPropertyPath(),
            'message' => $violation->getMessage()
        );

        if (null === $visitor->getRoot()) {
            $visitor->setRoot($data);
        }

        return $data;
    }

    public function serializeViolationToYml(YamlSerializationVisitor $visitor, ConstraintViolation $violation, array $type = null)
    {
        return array(
            'property_path' => $violation->getPropertyPath(),
            'message' => $violation->getMessage(),
        );
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Handler;

/**
 * Handler Registry Interface.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface HandlerRegistryInterface
{
    /**
     * @param SubscribingHandlerInterface $handler
     *
     * @return void
     */
    public function registerSubscribingHandler(SubscribingHandlerInterface $handler);

    /**
     * Registers a handler in the registry.
     *
     * @param integer $direction one of the GraphNavigator::DIRECTION_??? constants
     * @param string $typeName
     * @param string $format
     * @param callable $handler function(VisitorInterface, mixed $data, array $type): mixed
     *
     * @return void
     */
    public function registerHandler($direction, $typeName, $format, $handler);

    /**
     * @param integer $direction one of the GraphNavigator::DIRECTION_??? constants
     * @param string $typeName
     * @param string $format
     *
     * @return callable|null
     */
    public function getHandler($direction, $typeName, $format);
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Handler;

interface SubscribingHandlerInterface
{
    /**
     * Return format:
     *
     *      array(
     *          array(
     *              'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
     *              'format' => 'json',
     *              'type' => 'DateTime',
     *              'method' => 'serializeDateTimeToJson',
     *          ),
     *      )
     *
     * The direction and method keys can be omitted.
     *
     * @return array
     */
    public static function getSubscribingMethods();
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Handler;

use JMS\Serializer\Context;
use JMS\Serializer\GraphNavigator;
use JMS\Serializer\VisitorInterface;
use PhpCollection\Map;
use PhpCollection\Sequence;

class PhpCollectionHandler implements SubscribingHandlerInterface
{
    public static function getSubscribingMethods()
    {
        $methods = array();
        $formats = array('json', 'xml', 'yml');
        $collectionTypes = array(
            'PhpCollection\Sequence' => 'Sequence',
            'PhpCollection\Map' => 'Map',
        );

        foreach ($collectionTypes as $type => $shortName) {
            foreach ($formats as $format) {
                $methods[] = array(
                    'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
                    'type' => $type,
                    'format' => $format,
                    'method' => 'serialize'.$shortName,
                );

                $methods[] = array(
                    'direction' => GraphNavigator::DIRECTION_DESERIALIZATION,
                    'type' => $type,
                    'format' => $format,
                    'method' => 'deserialize'.$shortName,
                );
            }
        }

        return $methods;
    }

    public function serializeMap(VisitorInterface $visitor, Map $map, array $type, Context $context)
    {
        $type['name'] = 'array';

        return $visitor->visitArray(iterator_to_array($map), $type, $context);
    }

    public function deserializeMap(VisitorInterface $visitor, $data, array $type, Context $context)
    {
        $type['name'] = 'array';

        return new Map($visitor->visitArray($data, $type, $context));
    }

    public function serializeSequence(VisitorInterface $visitor, Sequence $sequence, array $type, Context $context)
    {
        // We change the base type, and pass through possible parameters.
        $type['name'] = 'array';

        return $visitor->visitArray($sequence->all(), $type, $context);
    }

    public function deserializeSequence(VisitorInterface $visitor, $data, array $type, Context $context)
    {
        // See above.
        $type['name'] = 'array';

        return new Sequence($visitor->visitArray($data, $type, $context));
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Handler;

use JMS\Serializer\Context;
use JMS\Serializer\JsonDeserializationVisitor;
use JMS\Serializer\XmlDeserializationVisitor;
use JMS\Serializer\Exception\RuntimeException;
use JMS\Serializer\VisitorInterface;
use JMS\Serializer\GraphNavigator;

class DateHandler implements SubscribingHandlerInterface
{
    private $defaultFormat;
    private $defaultTimezone;

    public static function getSubscribingMethods()
    {
        $methods = array();
        $types = array('DateTime', 'DateInterval');

        foreach (array('json', 'xml', 'yml') as $format) {
            $methods[] = array(
                'type' => 'DateTime',
                'direction' => GraphNavigator::DIRECTION_DESERIALIZATION,
                'format' => $format,
            );

            foreach ($types as $type) {
                $methods[] = array(
                    'type' => $type,
                    'format' => $format,
                    'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
                    'method' => 'serialize'.$type,
                );
            }
        }

        return $methods;
    }

    public function __construct($defaultFormat = \DateTime::ISO8601, $defaultTimezone = 'UTC')
    {
        $this->defaultFormat = $defaultFormat;
        $this->defaultTimezone = new \DateTimeZone($defaultTimezone);
    }

    public function serializeDateTime(VisitorInterface $visitor, \DateTime $date, array $type, Context $context)
    {
        return $visitor->visitString($date->format($this->getFormat($type)), $type, $context);
    }

    public function serializeDateInterval(VisitorInterface $visitor, \DateInterval $date, array $type, Context $context)
    {
        $iso8601DateIntervalString = $this->format($date);

        return $visitor->visitString($iso8601DateIntervalString, $type, $context);
    }

    public function deserializeDateTimeFromXml(XmlDeserializationVisitor $visitor, $data, array $type)
    {
        $attributes = $data->attributes();
        if ((isset($attributes['nil'][0]) && (string) $attributes['nil'][0] === 'true') ||
            (isset($attributes['xsi:nil'][0]) && (string) $attributes['xsi:nil'][0] === 'true')) {
            return null;
        }

        return $this->parseDateTime($data, $type);
    }

    public function deserializeDateTimeFromJson(JsonDeserializationVisitor $visitor, $data, array $type)
    {
        if (null === $data) {
            return null;
        }

        return $this->parseDateTime($data, $type);
    }

    private function parseDateTime($data, array $type)
    {
        $timezone = isset($type['params'][1]) ? new \DateTimeZone($type['params'][1]) : $this->defaultTimezone;
        $format = $this->getFormat($type);
        $datetime = \DateTime::createFromFormat($format, (string) $data, $timezone);
        if (false === $datetime) {
            throw new RuntimeException(sprintf('Invalid datetime "%s", expected format %s.', $data, $format));
        }

        return $datetime;
    }

    /**
     * @return string
     * @param array $type
     */
    private function getFormat(array $type)
    {
        return isset($type['params'][0]) ? $type['params'][0] : $this->defaultFormat;
    }

    /**
     * @param \DateInterval $dateInterval
     * @return string
     */
    public function format(\DateInterval $dateInterval)
    {
        $format = 'P';

        if (0 < $dateInterval->y) {
            $format .= $dateInterval->y.'Y';
        }

        if (0 < $dateInterval->m) {
            $format .= $dateInterval->m.'M';
        }

        if (0 < $dateInterval->d) {
            $format .= $dateInterval->d.'D';
        }

        if (0 < $dateInterval->h || 0 < $dateInterval->i || 0 < $dateInterval->s) {
            $format .= 'T';
        }

        if (0 < $dateInterval->h) {
            $format .= $dateInterval->h.'H';
        }

        if (0 < $dateInterval->i) {
            $format .= $dateInterval->i.'M';
        }

        if (0 < $dateInterval->s) {
            $format .= $dateInterval->s.'S';
        }

        return $format;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Handler;

use Doctrine\Common\Collections\ArrayCollection;
use JMS\Serializer\Context;
use JMS\Serializer\GraphNavigator;
use JMS\Serializer\VisitorInterface;
use Doctrine\Common\Collections\Collection;
use JMS\Serializer\Handler\SubscribingHandlerInterface;

class ArrayCollectionHandler implements SubscribingHandlerInterface
{
    public static function getSubscribingMethods()
    {
        $methods = array();
        $formats = array('json', 'xml', 'yml');
        $collectionTypes = array('ArrayCollection', 'Doctrine\Common\Collections\ArrayCollection', 'Doctrine\ORM\PersistentCollection', 'Doctrine\ODM\MongoDB\PersistentCollection');

        foreach ($collectionTypes as $type) {
            foreach ($formats as $format) {
                $methods[] = array(
                    'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
                    'type' => $type,
                    'format' => $format,
                    'method' => 'serializeCollection',
                );

                $methods[] = array(
                    'direction' => GraphNavigator::DIRECTION_DESERIALIZATION,
                    'type' => $type,
                    'format' => $format,
                    'method' => 'deserializeCollection',
                );
            }
        }

        return $methods;
    }

    public function serializeCollection(VisitorInterface $visitor, Collection $collection, array $type, Context $context)
    {
        // We change the base type, and pass through possible parameters.
        $type['name'] = 'array';

        return $visitor->visitArray($collection->toArray(), $type, $context);
    }

    public function deserializeCollection(VisitorInterface $visitor, $data, array $type, Context $context)
    {
        // See above.
        $type['name'] = 'array';

        return new ArrayCollection($visitor->visitArray($data, $type, $context));
    }
}
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Exclusion;

use JMS\Serializer\Exclusion\DisjunctExclusionStrategy;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Metadata\StaticPropertyMetadata;
use JMS\Serializer\SerializationContext;

class DisjunctExclusionStrategyTest extends \PHPUnit_Framework_TestCase
{
    public function testShouldSkipClassShortCircuiting()
    {
        $metadata = new ClassMetadata('stdClass');
        $context = SerializationContext::create();

        $strat = new DisjunctExclusionStrategy(array(
            $first = $this->getMock('JMS\Serializer\Exclusion\ExclusionStrategyInterface'),
            $last = $this->getMock('JMS\Serializer\Exclusion\ExclusionStrategyInterface'),
        ));

        $first->expects($this->once())
            ->method('shouldSkipClass')
            ->with($metadata, $context)
            ->will($this->returnValue(true));

        $last->expects($this->never())
            ->method('shouldSkipClass');

        $this->assertTrue($strat->shouldSkipClass($metadata, $context));
    }

    public function testShouldSkipClassDisjunctBehavior()
    {
        $metadata = new ClassMetadata('stdClass');
        $context = SerializationContext::create();

        $strat = new DisjunctExclusionStrategy(array(
            $first = $this->getMock('JMS\Serializer\Exclusion\ExclusionStrategyInterface'),
            $last = $this->getMock('JMS\Serializer\Exclusion\ExclusionStrategyInterface'),
        ));

        $first->expects($this->once())
            ->method('shouldSkipClass')
            ->with($metadata, $context)
            ->will($this->returnValue(false));

        $last->expects($this->once())
            ->method('shouldSkipClass')
            ->with($metadata, $context)
            ->will($this->returnValue(true));

        $this->assertTrue($strat->shouldSkipClass($metadata, $context));
    }

    public function testShouldSkipClassReturnsFalseIfNoPredicateMatched()
    {
        $metadata = new ClassMetadata('stdClass');
        $context = SerializationContext::create();

        $strat = new DisjunctExclusionStrategy(array(
            $first = $this->getMock('JMS\Serializer\Exclusion\ExclusionStrategyInterface'),
            $last = $this->getMock('JMS\Serializer\Exclusion\ExclusionStrategyInterface'),
        ));

        $first->expects($this->once())
            ->method('shouldSkipClass')
            ->with($metadata, $context)
            ->will($this->returnValue(false));

        $last->expects($this->once())
            ->method('shouldSkipClass')
            ->with($metadata, $context)
            ->will($this->returnValue(false));

        $this->assertFalse($strat->shouldSkipClass($metadata, $context));
    }

    public function testShouldSkipPropertyShortCircuiting()
    {
        $metadata = new StaticPropertyMetadata('stdClass', 'foo', 'bar');
        $context = SerializationContext::create();

        $strat = new DisjunctExclusionStrategy(array(
            $first = $this->getMock('JMS\Serializer\Exclusion\ExclusionStrategyInterface'),
            $last = $this->getMock('JMS\Serializer\Exclusion\ExclusionStrategyInterface'),
        ));

        $first->expects($this->once())
            ->method('shouldSkipProperty')
            ->with($metadata, $context)
            ->will($this->returnValue(true));

        $last->expects($this->never())
            ->method('shouldSkipProperty');

        $this->assertTrue($strat->shouldSkipProperty($metadata, $context));
    }

    public function testShouldSkipPropertyDisjunct()
    {
        $metadata = new StaticPropertyMetadata('stdClass', 'foo', 'bar');
        $context = SerializationContext::create();

        $strat = new DisjunctExclusionStrategy(array(
            $first = $this->getMock('JMS\Serializer\Exclusion\ExclusionStrategyInterface'),
            $last = $this->getMock('JMS\Serializer\Exclusion\ExclusionStrategyInterface'),
        ));

        $first->expects($this->once())
            ->method('shouldSkipProperty')
            ->with($metadata, $context)
            ->will($this->returnValue(false));

        $last->expects($this->once())
            ->method('shouldSkipProperty')
            ->with($metadata, $context)
            ->will($this->returnValue(true));

        $this->assertTrue($strat->shouldSkipProperty($metadata, $context));
    }


    public function testShouldSkipPropertyReturnsFalseIfNoPredicateMatches()
    {
        $metadata = new StaticPropertyMetadata('stdClass', 'foo', 'bar');
        $context = SerializationContext::create();

        $strat = new DisjunctExclusionStrategy(array(
            $first = $this->getMock('JMS\Serializer\Exclusion\ExclusionStrategyInterface'),
            $last = $this->getMock('JMS\Serializer\Exclusion\ExclusionStrategyInterface'),
        ));

        $first->expects($this->once())
            ->method('shouldSkipProperty')
            ->with($metadata, $context)
            ->will($this->returnValue(false));

        $last->expects($this->once())
            ->method('shouldSkipProperty')
            ->with($metadata, $context)
            ->will($this->returnValue(false));

        $this->assertFalse($strat->shouldSkipProperty($metadata, $context));
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\SerializedName;
use JMS\Serializer\Annotation\Since;
use JMS\Serializer\Annotation\Until;

class VersionedObject
{
    /**
     * @Until("1.0.0")
     */
    private $name;

    /**
     * @Since("1.0.1")
     * @SerializedName("name")
     */
    private $name2;

    public function __construct($name, $name2)
    {
        $this->name  = $name;
        $this->name2 = $name2;
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\Type;
use JMS\Serializer\Annotation\SerializedName;
use JMS\Serializer\Annotation\XmlMap;
use JMS\Serializer\Annotation\XmlRoot;
use JMS\Serializer\Annotation\XmlAttribute;
use JMS\Serializer\Annotation\XmlList;
use JMS\Serializer\Annotation\Groups;
use Doctrine\Common\Collections\ArrayCollection;
use PhpCollection\Map;
use PhpCollection\Sequence;

/** @XmlRoot("blog-post") */
class BlogPost
{
    /**
     * @Type("string")
     * @Groups({"comments","post"})
     */
    private $title;

    /**
     * @Type("DateTime")
     * @XmlAttribute
     */
    private $createdAt;

    /**
     * @Type("boolean")
     * @SerializedName("is_published")
     * @XmlAttribute
     * @Groups({"post"})
     */
    private $published;

    /**
     * @Type("ArrayCollection<JMS\Serializer\Tests\Fixtures\Comment>")
     * @XmlList(inline=true, entry="comment")
     * @Groups({"comments"})
     */
    private $comments;

    /**
     * @Type("PhpCollection\Sequence<JMS\Serializer\Tests\Fixtures\Comment>")
     * @XmlList(inline=true, entry="comment2")
     * @Groups({"comments"})
     */
    private $comments2;

    /**
     * @Type("PhpCollection\Map<string,string>")
     * @XmlMap(keyAttribute = "key")
     */
    private $metadata;

    /**
     * @Type("JMS\Serializer\Tests\Fixtures\Author")
     * @Groups({"post"})
     */
    private $author;

    public function __construct($title, Author $author, \DateTime $createdAt)
    {
        $this->title = $title;
        $this->author = $author;
        $this->published = false;
        $this->comments = new ArrayCollection();
        $this->comments2 = new Sequence();
        $this->metadata = new Map();
        $this->metadata->set('foo', 'bar');
        $this->createdAt = $createdAt;
    }

    public function setPublished()
    {
        $this->published = true;
    }

    public function getMetadata()
    {
        return $this->metadata;
    }

    public function addComment(Comment $comment)
    {
        $this->comments->add($comment);
        $this->comments2->add($comment);
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation as Serializer;
use JMS\Serializer\Annotation\Type;

class InlineChild
{
    /**
     * @Type("string")
     */
    private $a = 'a';

    /**
     * @Type("string")
     */
    private $b = 'b';
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation as Serializer;

/** @Serializer\AccessorOrder("custom",  custom = {"method", "b", "a"}) */
class AccessorOrderMethod
{
    private $b = 'b', $a = 'a';

    /**
     * @Serializer\VirtualProperty
     * @Serializer\SerializedName("foo")
     *
     * @return string
     */
    public function getMethod()
    {
        return 'c';
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\Groups;
use JMS\Serializer\Annotation\Type;

/** blablub */
class GroupsObject
{
    /**
     * @Groups({"foo"})
     * @Type("string")
     */
    private $foo;

    /**
     * @Groups({"foo","bar"})
     * @Type("string")
     */
    private $foobar;

    /**
     * @Groups({"bar", "Default"})
     * @Type("string")
     */
    private $bar;

     /**
     * @Type("string")
     */
    private $none;

    public function __construct()
    {
        $this->foo  = "foo";
        $this->bar = "bar";
        $this->foobar  = "foobar";
        $this->none = "none";
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures\Discriminator;

class Car extends Vehicle
{
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures\Discriminator;

class Moped extends Vehicle
{
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures\Discriminator;

use JMS\Serializer\Annotation as Serializer;

/**
 * @Serializer\Discriminator(field = "type", map = {
 *    "car": "JMS\Serializer\Tests\Fixtures\Discriminator\Car",
 *    "moped": "JMS\Serializer\Tests\Fixtures\Discriminator\Moped",
 * })
 */
abstract class Vehicle
{
    /** @Serializer\Type("integer") */
    public $km;

    public function __construct($km)
    {
        $this->km = (integer) $km;
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\XmlRoot;
use JMS\Serializer\Annotation\Type;

/** @XmlRoot("order") */
class CurrencyAwareOrder
{
    /** @Type("JMS\Serializer\Tests\Fixtures\CurrencyAwarePrice") */
    private $cost;

    public function __construct(CurrencyAwarePrice $price = null)
    {
        $this->cost = $price ?: new CurrencyAwarePrice(5);
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Context;
use JMS\Serializer\JsonDeserializationVisitor;
use JMS\Serializer\XmlDeserializationVisitor;
use Symfony\Component\Yaml\Inline;
use JMS\Serializer\YamlSerializationVisitor;
use JMS\Serializer\JsonSerializationVisitor;
use JMS\Serializer\XmlSerializationVisitor;
use JMS\Serializer\Annotation\HandlerCallback;

class Article
{
    public $element;
    public $value;

    /** @HandlerCallback("xml", direction = "serialization") */
    public function serializeToXml(XmlSerializationVisitor $visitor, $data, Context $context)
    {
        if (null === $visitor->document) {
            $visitor->document = $visitor->createDocument(null, null, false);
        }

        $visitor->document->appendChild($visitor->document->createElement($this->element, $this->value));
    }

    /** @HandlerCallback("json", direction = "serialization") */
    public function serializeToJson(JsonSerializationVisitor $visitor)
    {
        $visitor->setRoot(array($this->element => $this->value));
    }

    /** @HandlerCallback("yml", direction = "serialization") */
    public function serializeToYml(YamlSerializationVisitor $visitor)
    {
        $visitor->writer->writeln(Inline::dump($this->element).': '.Inline::dump($this->value));
    }

    /** @HandlerCallback("xml", direction = "deserialization") */
    public function deserializeFromXml(XmlDeserializationVisitor $visitor, \SimpleXMLElement $data)
    {
        $this->element = $data->getName();
        $this->value = (string) $data;
    }

    /** @HandlerCallback("json", direction = "deserialization") */
    public function deserializeFromJson(JsonDeserializationVisitor $visitor, array $data)
    {
        $this->element = key($data);
        $this->value = reset($data);
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation as Serializer;

class Node
{
    /**
     * @Serializer\MaxDepth(2)
     */
    public $children;

    public $foo = 'bar';

    public function __construct($children = array())
    {
        $this->children = $children;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures\Doctrine;

use JMS\Serializer\Annotation\SerializedName;
use JMS\Serializer\Annotation\XmlRoot;
use JMS\Serializer\Annotation\XmlAttribute;
use JMS\Serializer\Annotation\XmlList;
use JMS\Serializer\Annotation\Groups;
use JMS\Serializer\Annotation\Type;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;

/** 
 * @ORM\Entity 
 * @XmlRoot("blog-post")
 */
class BlogPost
{
    /** 
     * @ORM\Id @ORM\Column(type="integer") 
     */
    protected $id;

    /**
     * @ORM\Column(type="string")
     * @Groups({"comments","post"})
     */
    private $title;

    /** 
     * @ORM\Column(type="some_custom_type")
     */
    protected $slug;

    /**
     * @ORM\Column(type="datetime")
     * @XmlAttribute
     */
    private $createdAt;

    /**
     * @ORM\Column(type="boolean")
     * @Type("integer")
     * This boolean to integer conversion is one of the few changes between this
     * and the standard BlogPost class. It's used to test the override behavior
     * of the DoctrineTypeDriver so notice it, but please don't change it.
     *
     * @SerializedName("is_published")
     * @Groups({"post"})
     * @XmlAttribute
     */
    private $published;

    /**
     * @ORM\OneToMany(targetEntity="Comment", mappedBy="blogPost")
     * @XmlList(inline=true, entry="comment")
     * @Groups({"comments"})
     */
    private $comments;

    /**
     * @ORM\OneToOne(targetEntity="Author")
     * @Groups({"post"})
     */
    private $author;

    public function __construct($title, Author $author, \DateTime $createdAt)
    {
        $this->title = $title;
        $this->author = $author;
        $this->published = false;
        $this->comments = new ArrayCollection();
        $this->createdAt = $createdAt;
    }

    public function setPublished()
    {
        $this->published = true;
    }

    public function addComment(Comment $comment)
    {
        $this->comments->add($comment);
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures\Doctrine;

use JMS\Serializer\Annotation\Type;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;

/** @ORM\Entity */
class Comment
{
    /** 
     * @ORM\Id @ORM\Column(type="integer") 
     */
    protected $id;

    /**
     * @ORM\Column(type="Author")
     */
    private $author;

    /** @ORM\ManyToOne(targetEntity="BlogPost") */
    private $blogPost;

    /**
     * @ORM\Column(type="string")
     */
    private $text;

    public function __construct(Author $author, $text)
    {
        $this->author = $author;
        $this->text = $text;
        $this->blogPost = new ArrayCollection();
    }

    public function getAuthor()
    {
        return $this->author;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures\Doctrine;

use JMS\Serializer\Annotation\Type;
use JMS\Serializer\Annotation\SerializedName;

use Doctrine\ORM\Mapping as ORM;

/** @ORM\Entity */
class Author
{
    /** 
     * @ORM\Id @ORM\Column(type="integer") 
     */
    protected $id;

    /**
     * @ORM\Column(type="string")
     * @SerializedName("full_name")
     */
    private $name;

    public function __construct($name)
    {
        $this->name = $name;
    }

    public function getName()
    {
        return $this->name;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation as Serializer;

/** @Serializer\XmlRoot("price") */
class CurrencyAwarePrice
{
    /**
     * @Serializer\XmlAttribute
     * @Serializer\Type("string")
     */
    private $currency;

    /**
     * @Serializer\XmlValue
     * @Serializer\Type("double")
     */
    private $amount;

    public function __construct($amount, $currency = 'EUR')
    {
        $this->currency = $currency;
        $this->amount = $amount;
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\Accessor;
use JMS\Serializer\Annotation\XmlMap;
use JMS\Serializer\Annotation\XmlRoot;
use JMS\Serializer\Annotation\XmlList;
use JMS\Serializer\Annotation\XmlAttribute;

/** @XmlRoot("post") */
class IndexedCommentsBlogPost
{
    /**
     * @XmlMap(keyAttribute="author-name", inline=true, entry="comments")
     * @Accessor(getter="getCommentsIndexedByAuthor")
     */
    private $comments = array();

    public function __construct()
    {
        $author = new Author('Foo');
        $this->comments[] = new Comment($author, 'foo');
        $this->comments[] = new Comment($author, 'bar');
    }

    public function getCommentsIndexedByAuthor()
    {
        $indexedComments = array();
        foreach ($this->comments as $comment) {
            $authorName = $comment->getAuthor()->getName();

            if (!isset($indexedComments[$authorName])) {
                $indexedComments[$authorName] = new IndexedCommentsList();
            }

            $indexedComments[$authorName]->addComment($comment);
        }

        return $indexedComments;
    }
}

class IndexedCommentsList
{
    /** @XmlList(inline=true, entry="comment") */
    private $comments = array();

    /** @XmlAttribute */
    private $count = 0;

    public function addComment(Comment $comment)
    {
        $this->comments[] = $comment;
        $this->count += 1;
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation as Serializer;

/** @Serializer\AccessorOrder("alphabetical") */
class AccessorOrderParent
{
    private $b = 'b', $a = 'a';
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\Type;
use JMS\Serializer\Annotation\XmlValue;
use JMS\Serializer\Annotation\XmlRoot;

/**
 * @XmlRoot("price")
 */
class Price
{
    /**
     * @Type("double")
     * @XmlValue
     */
    private $price;

    function __construct($price)
    {
        $this->price = $price;
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\Exclude;
use JMS\Serializer\Annotation\PreSerialize;
use JMS\Serializer\Annotation\PostSerialize;
use JMS\Serializer\Annotation\PostDeserialize;
use JMS\Serializer\Annotation\Type;

class ObjectWithLifecycleCallbacks
{
    /**
     * @Exclude
     */
    private $firstname;

    /**
     * @Exclude
     */
    private $lastname;

    /**
     * @Type("string")
     */
    private $name;

    public function __construct($firstname = 'Foo', $lastname = 'Bar')
    {
        $this->firstname = $firstname;
        $this->lastname = $lastname;
    }

    /**
     * @PreSerialize
     */
    private function prepareForSerialization()
    {
        $this->name = $this->firstname.' '.$this->lastname;
    }

    /**
     * @PostSerialize
     */
    private function cleanUpAfterSerialization()
    {
        $this->name = null;
    }

    /**
     * @PostDeserialize
     */
    private function afterDeserialization()
    {
        list($this->firstname, $this->lastname) = explode(' ', $this->name);
        $this->name = null;
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\SerializedName;
use JMS\Serializer\Annotation\Type;
use JMS\Serializer\Annotation\XmlRoot;
use JMS\Serializer\Annotation\ReadOnly;
use JMS\Serializer\Annotation\Accessor;

/** @XmlRoot("author") */
class AuthorReadOnly
{
    /**
     * @ReadOnly
     * @SerializedName("id")
     */
    private $id;

    /**
     * @Type("string")
     * @SerializedName("full_name")
     * @Accessor("getName")
     */
    private $name;

    public function __construct($id, $name)
    {
        $this->id = $id;
        $this->name = $name;
    }

    public function getId()
    {
        return $this->id;
    }

    public function getName()
    {
        return $this->name;
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use Doctrine\Common\Collections\ArrayCollection;
use JMS\Serializer\Annotation\Type;
use JMS\Serializer\Annotation\PostDeserialize;

/** No annotation */
class CircularReferenceParent
{
    /** @Type("array<JMS\Serializer\Tests\Fixtures\CircularReferenceChild>") */
    protected $collection = array();

    /** @Type("ArrayCollection<JMS\Serializer\Tests\Fixtures\CircularReferenceChild>") */
    private $anotherCollection;

    public function __construct()
    {
        $this->collection[] = new CircularReferenceChild('child1', $this);
        $this->collection[] = new CircularReferenceChild('child2', $this);

        $this->anotherCollection = new ArrayCollection();
        $this->anotherCollection->add(new CircularReferenceChild('child1', $this));
        $this->anotherCollection->add(new CircularReferenceChild('child2', $this));
    }

    /** @PostDeserialize */
    private function afterDeserialization()
    {
        if (!$this->collection) {
            $this->collection = array();
        }
        foreach ($this->collection as $v) {
            $v->setParent($this);
        }

        if (!$this->anotherCollection) {
            $this->anotherCollection = new ArrayCollection();
        }
        foreach ($this->anotherCollection as $v) {
            $v->setParent($this);
        }
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use Doctrine\Common\Collections\ArrayCollection;

use JMS\Serializer\Metadata\ClassMetadata;

use JMS\Serializer\Construction\ObjectConstructorInterface;
use JMS\Serializer\VisitorInterface;

use JMS\Serializer\Tests\Fixtures\Author;
use JMS\Serializer\Construction\UnserializeObjectConstructor;

class InitializedObjectConstructor extends UnserializeObjectConstructor
{
    public function construct(VisitorInterface $visitor, ClassMetadata $metadata, $data, array $type)
    {
        if ($type['name'] !== 'JMS\Serializer\Tests\Fixtures\BlogPost') {
            return parent::construct($visitor, $metadata, $data, $type);
        }

        return new BlogPost('This is a nice title.', new Author('Foo Bar'), new \DateTime('2011-07-30 00:00', new \DateTimeZone('UTC')));
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\Groups;
use JMS\Serializer\Annotation\Type;

class InvalidGroupsObject
{
    /**
     * @Groups({"foo, bar"})
     * @Type("string")
     */
    private $foo;
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\XmlRoot;
use JMS\Serializer\Annotation\Type;

/**
 * @XmlRoot("person_location")
 */
class PersonLocation
{
    /**
     * @Type("JMS\Serializer\Tests\Fixtures\Person")
     */
    public $person;

    /**
     * @Type("string")
     */
    public $location;
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use Doctrine\ORM\Proxy\Proxy;

class SimpleObjectProxy extends SimpleObject implements Proxy
{
    public $__isInitialized__ = false;

    private $baz = 'baz';

    public function __load()
    {
        if (!$this->__isInitialized__) {
            $this->camelCase = 'proxy-boo';
            $this->__isInitialized__ = true;
        }
    }

    public function __isInitialized()
    {
        return $this->__isInitialized__;
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation as Serializer;

class Tree
{
    /**
     * @Serializer\MaxDepth(10)
     */
    public $tree;

    public function __construct($tree)
    {
        $this->tree = $tree;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\Type;

class Comment
{
    /**
     * @Type("JMS\Serializer\Tests\Fixtures\Author")
     */
    private $author;

    /**
     * @Type("string")
     */
    private $text;

    public function __construct(Author $author = null, $text)
    {
        $this->author = $author;
        $this->text = $text;
    }

    public function getAuthor()
    {
        return $this->author;
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\XmlKeyValuePairs;

class ObjectWithXmlKeyValuePairs
{
    /**
     * @var array
     * @XmlKeyValuePairs
     */
    private $array = array(
        'key-one' => 'foo',
        'key-two' => 1,
        'nested-array' => array(
            'bar' => 'foo',
        ),
        'without-keys' => array(
            1,
            'test'
        ),
        'mixed' => array(
            'test',
            'foo' => 'bar',
            '1_foo' => 'bar'
        ),
        1 => 'foo'
    );
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\Type;

class CircularReferenceChild
{
    /** @Type("string") */
    private $name;

    /** @Type("JMS\Serializer\Tests\Fixtures\CircularReferenceParent") */
    private $parent;

    public function __construct($name, CircularReferenceParent $parent)
    {
        $this->name   = $name;
        $this->parent = $parent;
    }

    public function getName()
    {
        return $this->name;
    }

    public function getParent()
    {
        return $this->parent;
    }

    public function setParent(CircularReferenceParent $parent)
    {
        $this->parent = $parent;
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\XmlRoot;
use JMS\Serializer\Annotation\XmlList;
use Doctrine\Common\Collections\ArrayCollection;
use JMS\Serializer\Annotation\Type;

/**
 * @XmlRoot("person_collection")
 */
class PersonCollection
{
    /**
     * @Type("ArrayCollection<JMS\Serializer\Tests\Fixtures\Person>")
     * @XmlList(entry = "person", inline = true)
     */
    public $persons;

    /**
     * @Type("string")
     */
    public $location;

    public function __construct()
    {
        $this->persons = new ArrayCollection;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\XmlRoot;
use JMS\Serializer\Annotation\Type;

/** @XmlRoot("order") */
class Order
{
    /** @Type("JMS\Serializer\Tests\Fixtures\Price") */
    private $cost;

    public function __construct(Price $price = null)
    {
        $this->cost = $price ?: new Price(5);
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Tests\Fixtures\SimpleObject;

class ObjectWithNullProperty extends SimpleObject
{
    private $nullProperty = null;
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\Groups;
use JMS\Serializer\Annotation\XmlValue;
use JMS\Serializer\Annotation\XmlAttribute;
use JMS\Serializer\Annotation\XmlList;
use JMS\Serializer\Annotation\XmlMap;
use JMS\Serializer\Annotation\Since;
use JMS\Serializer\Annotation\Until;
use JMS\Serializer\Annotation\VirtualProperty;
use JMS\Serializer\Annotation\SerializedName;


class ObjectWithVirtualXmlProperties
{

    /**
     *
     * @VirtualProperty
     * @SerializedName("foo")
     * @Groups({"attributes"})
     * @XmlAttribute
     */
    public function getVirualXmlAttributeValue()
    {
        return 'bar';
    }

    /**
     *
     * @VirtualProperty
     * @SerializedName("xml-value")
     * @Groups({"values"})
     * @XmlValue
     */
    public function getVirualXmlValue()
    {
        return 'xml-value';
    }
    
    /**
     *
     * @VirtualProperty
     * @SerializedName("list")
     * @Groups({"list"})
     * @XmlList(inline = true, entry = "val")
     */
    public function getVirualXmlList()
    {
        return array('One','Two');
    }

    /**
     *
     * @VirtualProperty
     * @SerializedName("map")
     * @Groups({"map"})
     * @XmlMap(keyAttribute = "key")
     */
    public function getVirualXmlMap()
    {
        return array(
            'key-one'   => 'One',
            'key-two'   => 'Two'
        );
    }
    
    /**
     *
     * @VirtualProperty
     * @SerializedName("low")
     * @Groups({"versions"})
     * @Until("8")
     */
    public function getVirualLowValue()
    {
        return 1;
    }
    
    /**
     * @VirtualProperty
     * @SerializedName("hight")
     * @Groups({"versions"})
     * @Since("8")
     */
    public function getVirualHighValue()
    {
        return 8;
    }

}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\VirtualProperty;
use JMS\Serializer\Annotation\ExclusionPolicy;

/**
 * @ExclusionPolicy("all")
 */
class ObjectWithVirtualPropertiesAndExcludeAll
{
    /**
     * @VirtualProperty
     */
    public function getVirtualValue()
    {
        return 'value';
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation as Serializer;

class ObjectWithEmptyHash
{
    /**
     * @Serializer\Type("array<string,string>")
     */
    private $hash = array();
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation as Serializer;

/**
 * An array-acting object that holds many author instances.
 */
class AuthorList implements \IteratorAggregate, \Countable, \ArrayAccess
{
    /**
     * @Serializer\Type("array<JMS\Serializer\Tests\Fixtures\Author>")
     * @var array
     */
    protected $authors = array();

    /**
     * @param Author $author
     */
    public function add(Author $author)
    {
        $this->authors[] = $author;
    }

    /**
     * @see IteratorAggregate
     */
    public function getIterator()
    {
        return new \ArrayIterator($this->authors);
    }

    /**
     * @see Countable
     */
    public function count()
    {
        return count($this->authors);
    }

    /**
     * @see ArrayAccess
     */
    public function offsetExists($offset)
    {
        return isset($this->authors[$offset]);
    }

    /**
     * @see ArrayAccess
     */
    public function offsetGet($offset)
    {
        return isset($this->authors[$offset]) ? $this->authors[$offset] : null;
    }

    /**
     * @see ArrayAccess
     */
    public function offsetSet($offset, $value)
    {
        if (null === $offset) {
            $this->authors[] = $value;
        } else {
            $this->authors[$offset] = $value;
        }
    }

    /**
     * @see ArrayAccess
     */
    public function offsetUnset($offset)
    {
        unset($this->authors[$offset]);
    }
    
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\XmlRoot;
use JMS\Serializer\Annotation\SerializedName;
use JMS\Serializer\Annotation\XmlList;
use JMS\Serializer\Annotation\XmlMap;
use JMS\Serializer\Annotation\Type;

/** @XmlRoot("log") */
class Log
{
    /**
     * @SerializedName("author_list")
     * @XmlMap
     * @Type("AuthorList")
     */
    private $authors;

    /**
     * @XmlList(inline=true, entry = "comment")
     * @Type("array<JMS\Serializer\Tests\Fixtures\Comment>")
     */
    private $comments;

    public function __construct()
    {
        $this->authors = new AuthorList();
        $this->authors->add(new Author('Johannes Schmitt'));
        $this->authors->add(new Author('John Doe'));

        $author = new Author('Foo Bar');
        $this->comments = array();
        $this->comments[] = new Comment($author, 'foo');
        $this->comments[] = new Comment($author, 'bar');
        $this->comments[] = new Comment($author, 'baz');
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\Expose;
use JMS\Serializer\Annotation\ExclusionPolicy;

/**
 * @ExclusionPolicy("all")
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class AllExcludedObject
{
    private $foo = 'foo';

    /**
     * @Expose
     */
    private $bar = 'bar';
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation as Serializer;

/** @Serializer\AccessorOrder("custom", custom = {"c", "d", "a", "b"}) */
class AccessorOrderChild extends AccessorOrderParent
{
    private $c = 'c', $d = 'd';
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\SerializedName;
use JMS\Serializer\Annotation\Type;

class Author
{
    /**
     * @Type("string")
     * @SerializedName("full_name")
     */
    private $name;

    public function __construct($name)
    {
        $this->name = $name;
    }

    public function getName()
    {
        return $this->name;
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\Type;

class CustomDeserializationObject
{
    /**
     * @Type("string")
     */
    public $someProperty;

    public function __construct($value)
    {
        $this->someProperty = $value;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\XmlAttribute;
use JMS\Serializer\Annotation\XmlValue;
use JMS\Serializer\Annotation\XmlRoot;
use JMS\Serializer\Annotation\Type;

/**
 * @XmlRoot("child")
 */
class Person
{
    /**
     * @Type("string")
     * @XmlValue
     */
    public $name;

    /**
     * @Type("integer")
     * @XmlAttribute
     */
    public $age;
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation as Serializer;

/**
 * @Serializer\XmlRoot("input")
 */
class Input
{
    /**
     * @Serializer\XmlAttributeMap
     */
    private $attributes;

    public function __construct($attributes = null)
    {
        $this->attributes = $attributes ?: array(
            'type' => 'text',
            'name' => 'firstname',
            'value' => 'Adrien',
        );
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\SerializedName;
use JMS\Serializer\Annotation\Type;

class SimpleObject
{
    /** @Type("string") */
    private $foo;

    /**
     * @SerializedName("moo")
     * @Type("string")
     */
    private $bar;

    /** @Type("string") */
    protected $camelCase = 'boo';

    public function __construct($foo, $bar)
    {
        $this->foo = $foo;
        $this->bar = $bar;
    }

    public function getFoo()
    {
        return $this->foo;
    }

    public function getBar()
    {
        return $this->bar;
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\AccessType;
use JMS\Serializer\Annotation\Type;
use JMS\Serializer\Annotation\ReadOnly;

/** @AccessType("public_method") */
class GetSetObject
{
    /** @AccessType("property") @Type("integer") */
    private $id = 1;

    /** @Type("string") */
    private $name = 'Foo';

    /**
     * @ReadOnly
     */
    private $readOnlyProperty = 42;

    public function getId()
    {
        throw new \RuntimeException('This should not be called.');
    }

    public function getName()
    {
        return 'Johannes';
    }

    public function setName($name)
    {
        $this->name = $name;
    }

    public function getReadOnlyProperty()
    {
        return $this->readOnlyProperty;
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\Groups;
use JMS\Serializer\Annotation\XmlValue;
use JMS\Serializer\Annotation\XmlAttribute;
use JMS\Serializer\Annotation\XmlList;
use JMS\Serializer\Annotation\XmlMap;
use JMS\Serializer\Annotation\Since;
use JMS\Serializer\Annotation\Until;
use JMS\Serializer\Annotation\VirtualProperty;
use JMS\Serializer\Annotation\SerializedName;

/**
 * dummy comment
 */
class ObjectWithVersionedVirtualProperties
{
    /**
     * @Groups({"versions"})
     * @VirtualProperty
     * @SerializedName("low")
     * @Until("8")
     */
    public function getVirualLowValue()
    {
        return 1;
    }

    /**
     * @Groups({"versions"})
     * @VirtualProperty
     * @SerializedName("high")
     * @Since("6")
     */
    public function getVirualHighValue()
    {
        return 8;
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation as Serializer;
use JMS\Serializer\Annotation\Type;

/** @Serializer\AccessorOrder("alphabetical") */
class InlineParent
{
    /**
     * @Type("string")
     */
    private $c = 'c';

    /**
     * @Type("string")
     */
    private $d = 'd';

    /**
     * @Type("JMS\Serializer\Tests\Fixtures\InlineChild")
     * @Serializer\Inline
     */
    private $child;

    public function __construct()
    {
        $this->child = new InlineChild();
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\XmlValue;

/** Dummy */
class InvalidUsageOfXmlValue
{
    /** @XmlValue */
    private $value = 'bar';

    private $element = 'foo';
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Fixtures;

use JMS\Serializer\Annotation\AccessorOrder;
use JMS\Serializer\Annotation\Type;
use JMS\Serializer\Annotation\VirtualProperty;
use JMS\Serializer\Annotation\SerializedName;
use JMS\Serializer\Annotation\Exclude;

/**
 * @AccessorOrder("custom", custom = {"prop_name", "existField", "foo" }) 
 */
class ObjectWithVirtualProperties
{

    /**
     * @Type("string")
     */
    protected $existField = 'value';
   
    /**
     * 
     * @VirtualProperty
     */
    public function getVirtualValue()
    {
        return 'value';
    }

    /**
     * @VirtualProperty
     * @SerializedName("test")
     */
    public function getVirtualSerializedValue()
    {
        return 'other-name';
    }

    /**
     * @VirtualProperty
     * @Type("integer")
     */
    public function getTypedVirtualProperty()
    {
        return '1';
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Twig;

use JMS\Serializer\SerializerInterface;
use JMS\Serializer\Twig\SerializerExtension;

class SerializerExtensionTest extends \PHPUnit_Framework_TestCase
{
    public function setUp()
    {
        $this->mockSerializer = $this->getMock('JMS\Serializer\SerializerInterface');
    }

    public function testSerialize()
    {
        $obj = new \stdClass();
        $this->mockSerializer
            ->expects($this->once())
            ->method('serialize')
            ->with($this->equalTo($obj), $this->equalTo('json'));
        $serializerExtension = new SerializerExtension($this->mockSerializer);
        $serializerExtension->serialize($obj);
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests;

use JMS\Serializer\SerializerBuilder;
use Symfony\Component\Filesystem\Filesystem;
use JMS\Serializer\Handler\HandlerRegistry;
use JMS\Serializer\JsonSerializationVisitor;
use JMS\Serializer\Naming\CamelCaseNamingStrategy;

class SerializerBuilderTest extends \PHPUnit_Framework_TestCase
{
    /** @var SerializerBuilder */
    private $builder;
    private $fs;
    private $tmpDir;

    public function testBuildWithoutAnythingElse()
    {
        $serializer = $this->builder->build();

        $this->assertEquals('"foo"', $serializer->serialize('foo', 'json'));
        $this->assertEquals('<?xml version="1.0" encoding="UTF-8"?>
<result><![CDATA[foo]]></result>
', $serializer->serialize('foo', 'xml'));
        $this->assertEquals('foo
', $serializer->serialize('foo', 'yml'));

        $this->assertEquals('foo', $serializer->deserialize('"foo"', 'string', 'json'));
        $this->assertEquals('foo', $serializer->deserialize('<?xml version="1.0" encoding="UTF-8"?><result><![CDATA[foo]]></result>', 'string', 'xml'));
    }

    public function testWithCache()
    {
        $this->assertFileNotExists($this->tmpDir);

        $this->assertSame($this->builder, $this->builder->setCacheDir($this->tmpDir));
        $serializer = $this->builder->build();

        $this->assertFileExists($this->tmpDir);
        $this->assertFileExists($this->tmpDir.'/annotations');
        $this->assertFileExists($this->tmpDir.'/metadata');

        $factory = $this->getField($serializer, 'factory');
        $this->assertAttributeSame(false, 'debug', $factory);
        $this->assertAttributeNotSame(null, 'cache', $factory);
    }

    public function testDoesAddDefaultHandlers()
    {
        $serializer = $this->builder->build();

        $this->assertEquals('"2020-04-16T00:00:00+0000"', $serializer->serialize(new \DateTime('2020-04-16', new \DateTimeZone('UTC')), 'json'));
    }

    public function testDoesNotAddDefaultHandlersWhenExplicitlyConfigured()
    {
        $this->assertSame($this->builder, $this->builder->configureHandlers(function(HandlerRegistry $registry) {
        }));

        $this->assertEquals('{}', $this->builder->build()->serialize(new \DateTime('2020-04-16'), 'json'));
    }

    /**
     * @expectedException JMS\Serializer\Exception\UnsupportedFormatException
     * @expectedExceptionMessage The format "xml" is not supported for serialization.
     */
    public function testDoesNotAddOtherVisitorsWhenConfiguredExplicitly()
    {
        $this->assertSame(
            $this->builder,
            $this->builder->setSerializationVisitor('json', new JsonSerializationVisitor(new CamelCaseNamingStrategy()))
        );

        $this->builder->build()->serialize('foo', 'xml');
    }

    public function testIncludeInterfaceMetadata()
    {
        $this->assertFalse(
            $this->getIncludeInterfaces($this->builder),
            'Interface metadata are not included by default'
        );

        $this->assertTrue(
            $this->getIncludeInterfaces($this->builder->includeInterfaceMetadata(true)),
            'Force including interface metadata'
        );

        $this->assertFalse(
            $this->getIncludeInterfaces($this->builder->includeInterfaceMetadata(false)),
            'Force not including interface metadata'
        );

        $this->assertSame(
            $this->builder,
            $this->builder->includeInterfaceMetadata(true)
        );
    }

    protected function setUp()
    {
        $this->builder = SerializerBuilder::create();
        $this->fs = new Filesystem();

        $this->tmpDir = sys_get_temp_dir().'/serializer';
        $this->fs->remove($this->tmpDir);
        clearstatcache();
    }

    protected function tearDown()
    {
        $this->fs->remove($this->tmpDir);
    }

    private function getField($obj, $name)
    {
        $ref = new \ReflectionProperty($obj, $name);
        $ref->setAccessible(true);

        return $ref->getValue($obj);
    }

    private function getIncludeInterfaces(SerializerBuilder $builder)
    {
        $factory = $this->getField($builder->build(), 'factory');
        return $this->getField($factory, 'includeInterfaces');
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Metadata;

use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Metadata\ClassMetadata;

class ClassMetadataTest extends \PHPUnit_Framework_TestCase
{
    public function testSetAccessorOrder()
    {
        $metadata = new ClassMetadata('JMS\Serializer\Tests\Metadata\PropertyMetadataOrder');
        $metadata->addPropertyMetadata(new PropertyMetadata('JMS\Serializer\Tests\Metadata\PropertyMetadataOrder', 'b'));
        $metadata->addPropertyMetadata(new PropertyMetadata('JMS\Serializer\Tests\Metadata\PropertyMetadataOrder', 'a'));
        $this->assertEquals(array('b', 'a'), array_keys($metadata->propertyMetadata));

        $metadata->setAccessorOrder(ClassMetadata::ACCESSOR_ORDER_ALPHABETICAL);
        $this->assertEquals(array('a', 'b'), array_keys($metadata->propertyMetadata));

        $metadata->setAccessorOrder(ClassMetadata::ACCESSOR_ORDER_CUSTOM, array('b', 'a'));
        $this->assertEquals(array('b', 'a'), array_keys($metadata->propertyMetadata));

        $metadata->setAccessorOrder(ClassMetadata::ACCESSOR_ORDER_CUSTOM, array('a', 'b'));
        $this->assertEquals(array('a', 'b'), array_keys($metadata->propertyMetadata));

        $metadata->setAccessorOrder(ClassMetadata::ACCESSOR_ORDER_CUSTOM, array('b'));
        $this->assertEquals(array('b', 'a'), array_keys($metadata->propertyMetadata));

        $metadata->setAccessorOrder(ClassMetadata::ACCESSOR_ORDER_CUSTOM, array('a'));
        $this->assertEquals(array('a', 'b'), array_keys($metadata->propertyMetadata));

        $metadata->setAccessorOrder(ClassMetadata::ACCESSOR_ORDER_CUSTOM, array('foo', 'bar'));
        $this->assertEquals(array('b', 'a'), array_keys($metadata->propertyMetadata));
    }
}

class PropertyMetadataOrder
{
    private $b, $a;
}<?php

use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;

$metadata = new ClassMetadata('JMS\Serializer\Tests\Fixtures\BlogPost');
$metadata->xmlRootName = 'blog-post';

$pMetadata = new PropertyMetadata('JMS\Serializer\Tests\Fixtures\BlogPost', 'title');
$pMetadata->setType('string');
$pMetadata->groups = array('comments','post');
$metadata->addPropertyMetadata($pMetadata);

$pMetadata = new PropertyMetadata('JMS\Serializer\Tests\Fixtures\BlogPost', 'createdAt');
$pMetadata->setType('DateTime');
$pMetadata->xmlAttribute = true;
$metadata->addPropertyMetadata($pMetadata);

$pMetadata = new PropertyMetadata('JMS\Serializer\Tests\Fixtures\BlogPost', 'published');
$pMetadata->setType('boolean');
$pMetadata->serializedName = 'is_published';
$pMetadata->groups = array('post');
$pMetadata->xmlAttribute = true;
$metadata->addPropertyMetadata($pMetadata);

$pMetadata = new PropertyMetadata('JMS\Serializer\Tests\Fixtures\BlogPost', 'comments');
$pMetadata->setType('ArrayCollection<JMS\Serializer\Tests\Fixtures\Comment>');
$pMetadata->xmlCollection = true;
$pMetadata->xmlCollectionInline = true;
$pMetadata->xmlEntryName = 'comment';
$pMetadata->groups = array('comments');

$metadata->addPropertyMetadata($pMetadata);

$pMetadata = new PropertyMetadata('JMS\Serializer\Tests\Fixtures\BlogPost', 'author');
$pMetadata->setType('JMS\Serializer\Tests\Fixtures\Author');
$pMetadata->groups = array('post');

$metadata->addPropertyMetadata($pMetadata);

return $metadata;<?php

use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;

$metadata = new ClassMetadata('JMS\Serializer\Tests\Fixtures\Node');

$pMetadata = new PropertyMetadata('JMS\Serializer\Tests\Fixtures\Node', 'children');
$pMetadata->maxDepth = 2;
$metadata->addPropertyMetadata($pMetadata);

return $metadata;
<?php

use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;

$metadata = new ClassMetadata('JMS\Serializer\Tests\Fixtures\Price');

$pMetadata = new PropertyMetadata('JMS\Serializer\Tests\Fixtures\Price', 'price');
$pMetadata->setType('double');
$pMetadata->xmlValue = true;
$metadata->addPropertyMetadata($pMetadata);

return $metadata;<?php

use JMS\Serializer\Metadata\ClassMetadata;

$metadata = new ClassMetadata('JMS\Serializer\Tests\Fixtures\AuthorReadOnly');

return $metadata;<?php

use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;

$metadata = new ClassMetadata('JMS\Serializer\Tests\Fixtures\Discriminator\Car');

return $metadata;<?php

use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;

$metadata = new ClassMetadata('JMS\Serializer\Tests\Fixtures\Discriminator\Vehicle');
$metadata->setDiscriminator('type', array(
    'car' => 'JMS\Serializer\Tests\Fixtures\Discriminator\Car',
    'moped' => 'JMS\Serializer\Tests\Fixtures\Discriminator\Moped',
));

$km = new PropertyMetadata('JMS\Serializer\Tests\Fixtures\Discriminator\Vehicle', 'km');
$km->setType('integer');
$metadata->addPropertyMetadata($km);

return $metadata;<?php
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;

$className = 'JMS\Serializer\Tests\Fixtures\ObjectWithXmlKeyValuePairs';

$metadata = new ClassMetadata($className);

$pMetadata = new PropertyMetadata($className, 'array');
$pMetadata->xmlKeyValuePairs = true;
$metadata->addPropertyMetadata($pMetadata);

return $metadata;
<?php

use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\VirtualPropertyMetadata;

$className = 'JMS\Serializer\Tests\Fixtures\ObjectWithVirtualPropertiesAndExcludeAll';

$metadata = new ClassMetadata( $className );

$pMetadata = new VirtualPropertyMetadata($className, 'virtualValue');
$pMetadata->getter = 'getVirtualValue';
$metadata->addPropertyMetadata($pMetadata);

return $metadata;<?php

use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;

$metadata = new ClassMetadata('JMS\Serializer\Tests\Fixtures\Discriminator\Moped');

return $metadata;<?php

use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Metadata\VirtualPropertyMetadata;

$className = 'JMS\Serializer\Tests\Fixtures\ObjectWithVirtualProperties';

$metadata = new ClassMetadata( $className );

$pMetadata = new PropertyMetadata($className, 'existField');
$metadata->addPropertyMetadata($pMetadata);

$pMetadata = new VirtualPropertyMetadata($className, 'virtualValue');
$pMetadata->getter = 'getVirtualValue';
$metadata->addPropertyMetadata($pMetadata);


$pMetadata = new VirtualPropertyMetadata($className, 'virtualSerializedValue');
$pMetadata->getter = 'getVirtualSerializedValue';
$pMetadata->serializedName = 'test';
$metadata->addPropertyMetadata($pMetadata);

$pMetadata = new VirtualPropertyMetadata($className, 'typedVirtualProperty');
$pMetadata->getter = 'getTypedVirtualProperty';
$pMetadata->setType('integer');
$metadata->addPropertyMetadata($pMetadata);

return $metadata;
JMS\Serializer\Tests\Fixtures\Discriminator\Car: { }JMS\Serializer\Tests\Fixtures\ObjectWithVirtualPropertiesAndExcludeAll:
    exclusion_policy: all
    virtual_properties:
        getVirtualValue: ~JMS\Serializer\Tests\Fixtures\BlogPost:
    xml_root_name: blog-post
    exclusion_policy: NONE
    properties:
        title:
            type: string
            exclude: true
JMS\Serializer\Tests\Fixtures\ObjectWithXmlKeyValuePairs:
    properties:
        array:
            type: array
            xml_key_value_pairs: true
JMS\Serializer\Tests\Fixtures\BlogPost:
    xml_root_name: blog-post
    exclusion_policy: ALL
    properties:
        title:
            type: string
            expose: true
JMS\Serializer\Tests\Fixtures\ObjectWithVirtualProperties:
    properties:
        existField:
            type: string
    virtual_properties:
        getVirtualValue: ~
        getVirtualSerializedValue:
            serialized_name: test
        getTypedVirtualProperty:
            type: integer
JMS\Serializer\Tests\Fixtures\Discriminator\Vehicle:
    discriminator:
        field_name: type
        map:
            car: JMS\Serializer\Tests\Fixtures\Discriminator\Car
            moped: JMS\Serializer\Tests\Fixtures\Discriminator\Moped

    properties:
        km:
            type: integerJMS\Serializer\Tests\Fixtures\Price:
    properties:
        price:
            type: double
            xml_value: trueJMS\Serializer\Tests\Fixtures\BlogPost:
    xml_root_name: blog-post
    properties:
        title:
            type: string
            groups: [comments, post]
        createdAt:
            type: DateTime
            xml_attribute: true
        published:
            type: boolean
            serialized_name: is_published
            xml_attribute: true
            groups: [post]
        comments:
            type: ArrayCollection<JMS\Serializer\Tests\Fixtures\Comment>
            groups: [comments]
            xml_list:
                inline: true
                entry_name: comment
        author:
            type: JMS\Serializer\Tests\Fixtures\Author
            groups: [post]JMS\Serializer\Tests\Fixtures\BlogPost:
    xml_root_name: blog-post
    exclusion_policy: all
    properties:
        title:
            type: string
            expose: TRUE
JMS\Serializer\Tests\Fixtures\Discriminator\Moped: { }JMS\Serializer\Tests\Fixtures\Node:
    properties:
        children:
            max_depth: 2
JMS\Serializer\Tests\Fixtures\BlogPost:
    xml_root_name: blog-post
    properties:
        title:
            accessor:
                getter: getOtherTitle
                setter: setOtherTitle
JMS\Serializer\Tests\Fixtures\AuthorReadOnly:
    xml_root_name: author
    properties:
        id:
            read_only: true
        name:
            serialized_name:  full_name
            access_type:      public_method
            accessor_getter:  getName
            read_only:        true
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Metadata\Driver;

use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Metadata\VirtualPropertyMetadata;
use Metadata\Driver\DriverInterface;

abstract class BaseDriverTest extends \PHPUnit_Framework_TestCase
{
    public function testLoadBlogPostMetadata()
    {
        $m = $this->getDriver()->loadMetadataForClass(new \ReflectionClass('JMS\Serializer\Tests\Fixtures\BlogPost'));

        $this->assertNotNull($m);
        $this->assertEquals('blog-post', $m->xmlRootName);

        $p = new PropertyMetadata($m->name, 'title');
        $p->type = array('name' => 'string', 'params' => array());
        $p->groups = array("comments","post");
        $this->assertEquals($p, $m->propertyMetadata['title']);

        $p = new PropertyMetadata($m->name, 'createdAt');
        $p->type = array('name' => 'DateTime', 'params' => array());
        $p->xmlAttribute = true;
        $this->assertEquals($p, $m->propertyMetadata['createdAt']);

        $p = new PropertyMetadata($m->name, 'published');
        $p->type = array('name' => 'boolean', 'params' => array());
        $p->serializedName = 'is_published';
        $p->xmlAttribute = true;
        $p->groups = array("post");
        $this->assertEquals($p, $m->propertyMetadata['published']);

        $p = new PropertyMetadata($m->name, 'comments');
        $p->type = array('name' => 'ArrayCollection', 'params' => array(array('name' => 'JMS\Serializer\Tests\Fixtures\Comment', 'params' => array())));
        $p->xmlCollection = true;
        $p->xmlCollectionInline = true;
        $p->xmlEntryName = 'comment';
        $p->groups = array("comments");
        $this->assertEquals($p, $m->propertyMetadata['comments']);

        $p = new PropertyMetadata($m->name, 'author');
        $p->type = array('name' => 'JMS\Serializer\Tests\Fixtures\Author', 'params' => array());
        $p->groups = array("post");
        $this->assertEquals($p, $m->propertyMetadata['author']);

        $m = $this->getDriver()->loadMetadataForClass(new \ReflectionClass('JMS\Serializer\Tests\Fixtures\Price'));
        $this->assertNotNull($m);

        $p = new PropertyMetadata($m->name, 'price');
        $p->type = array('name' => 'double', 'params' => array());
        $p->xmlValue = true;
        $this->assertEquals($p, $m->propertyMetadata['price']);
    }

    public function testVirtualProperty()
    {
        $m = $this->getDriver()->loadMetadataForClass(new \ReflectionClass('JMS\Serializer\Tests\Fixtures\ObjectWithVirtualProperties'));

        $this->assertArrayHasKey('existField', $m->propertyMetadata);
        $this->assertArrayHasKey('virtualValue', $m->propertyMetadata);
        $this->assertArrayHasKey('virtualSerializedValue', $m->propertyMetadata);
        $this->assertArrayHasKey('typedVirtualProperty', $m->propertyMetadata);

        $this->assertEquals($m->propertyMetadata['virtualSerializedValue']->serializedName, 'test', 'Serialized name is missing' );

        $p = new VirtualPropertyMetadata($m->name, 'virtualValue');
        $p->getter = 'getVirtualValue';

        $this->assertEquals($p, $m->propertyMetadata['virtualValue']);
    }

    public function testXmlKeyValuePairs()
    {
        $m = $this->getDriver()->loadMetadataForClass(new \ReflectionClass('JMS\Serializer\Tests\Fixtures\ObjectWithXmlKeyValuePairs'));

        $this->assertArrayHasKey('array', $m->propertyMetadata);
        $this->assertTrue($m->propertyMetadata['array']->xmlKeyValuePairs);
    }

    public function testVirtualPropertyWithExcludeAll()
    {
        $a = new \JMS\Serializer\Tests\Fixtures\ObjectWithVirtualPropertiesAndExcludeAll();
        $m = $this->getDriver()->loadMetadataForClass(new \ReflectionClass($a));

        $this->assertArrayHasKey('virtualValue', $m->propertyMetadata);

        $p = new VirtualPropertyMetadata($m->name, 'virtualValue');
        $p->getter = 'getVirtualValue';

        $this->assertEquals($p, $m->propertyMetadata['virtualValue']);
    }

    public function testReadOnlyDefinedBeforeGetterAndSetter()
    {
        $m = $this->getDriver()->loadMetadataForClass(new \ReflectionClass('JMS\Serializer\Tests\Fixtures\AuthorReadOnly'));

        $this->assertNotNull($m);
    }

    public function testLoadDiscriminator()
    {
        /** @var $m ClassMetadata */
        $m = $this->getDriver()->loadMetadataForClass(new \ReflectionClass('JMS\Serializer\Tests\Fixtures\Discriminator\Vehicle'));

        $this->assertNotNull($m);
        $this->assertEquals('type', $m->discriminatorFieldName);
        $this->assertEquals($m->name, $m->discriminatorBaseClass);
        $this->assertEquals(
            array(
                'car' => 'JMS\Serializer\Tests\Fixtures\Discriminator\Car',
                'moped' => 'JMS\Serializer\Tests\Fixtures\Discriminator\Moped',
            ),
            $m->discriminatorMap
        );
    }

    public function testLoadDiscriminatorSubClass()
    {
        /** @var $m ClassMetadata */
        $m = $this->getDriver()->loadMetadataForClass(new \ReflectionClass('JMS\Serializer\Tests\Fixtures\Discriminator\Car'));

        $this->assertNotNull($m);
        $this->assertNull($m->discriminatorValue);
        $this->assertNull($m->discriminatorBaseClass);
        $this->assertNull($m->discriminatorFieldName);
        $this->assertEquals(array(), $m->discriminatorMap);
    }

    public function testMaxDepth()
    {
        $m = $this->getDriver()->loadMetadataForClass(new \ReflectionClass('JMS\Serializer\Tests\Fixtures\Node'));

        $this->assertEquals(2, $m->propertyMetadata['children']->maxDepth);
    }

    /**
     * @return DriverInterface
     */
    abstract protected function getDriver();
}
<?xml version="1.0" encoding="UTF-8"?>
<serializer>
    <class name="JMS\Serializer\Tests\Fixtures\ObjectWithVirtualProperties">
        <property name="existField" type="string"/>
        <virtual-property method="getVirtualValue"/>
        <virtual-property method="getVirtualSerializedValue" serialized-name="test"/>
        <virtual-property method="getTypedVirtualProperty" type="integer" />
    </class>
</serializer>
<?xml version="1.0" encoding="UTF-8"?>
<serializer>
    <class name="JMS\Serializer\Tests\Fixtures\BlogPost" xml-root-name="blog-post" exclusion-policy="NONE">
        <property name="title" type="string" exclude="true" />
    </class>
</serializer><?xml version="1.0" encoding="UTF-8"?>
<serializer>
    <class name="JMS\Serializer\Tests\Fixtures\ObjectWithVirtualPropertiesAndExcludeAll"  exclusion-policy="ALL">
        <virtual-property method="getVirtualValue"/>
    </class>
</serializer>This contains no valid XML markup.<?xml version="1.0" encoding="UTF-8"?>
<serializer>
    <class name="JMS\Serializer\Tests\Fixtures\AuthorReadOnly" xml-root-name="author">
        <property name="id" read-only="true"/>
        <property name="name" serialized-name="full_name" access-type="public_method" accessor-getter="getName" read-only="true"/>
    </class>
</serializer><?xml version="1.0" encoding="UTF-8"?>
<serializer>
    <class name="JMS\Serializer\Tests\Fixtures\GetSetObject" access-type="public_method">
        <property name="id" type="integer" access-type="property" />
        <property name="name" type="string" accessor-getter="getTrimmedName" accessor-setter="setCapitalizedName" />
    </class>
</serializer><?xml version="1.0" encoding="UTF-8"?>
<serializer>
    <class name="JMS\Serializer\Tests\Fixtures\Node">
        <property name="children" max-depth="2" />
    </class>
</serializer>
<?xml version="1.0" encoding="UTF-8"?>
<serializer>
    <class name="JMS\Serializer\Tests\Fixtures\BlogPost" xml-root-name="blog-post">
        <property name="title" type="string" groups="comments,post"/>
        <property name="createdAt" xml-attribute="true" type="DateTime"/>
        <property name="published" type="boolean" serialized-name="is_published" xml-attribute="true" groups="post" />
        <property name="comments" groups="comments">
            <type><![CDATA[ArrayCollection<JMS\Serializer\Tests\Fixtures\Comment>]]></type>
            <xml-list inline="true" entry-name="comment" />
        </property>
        <property name="author" groups="post" type="JMS\Serializer\Tests\Fixtures\Author" />
    </class>
</serializer><?xml version="1.0" encoding="UTF-8"?>
<serializer>
    <class name="JMS\Serializer\Tests\Fixtures\Discriminator\Moped">
    </class>
</serializer><?xml version="1.0" encoding="UTF-8"?>
<serializer>
    <class name="JMS\Serializer\Tests\Fixtures\Price">
        <property name="price" xml-value="true" type="double" />
    </class>
</serializer><?xml version="1.0" encoding="UTF-8"?>
<serializer>
    <class name="JMS\Serializer\Tests\Fixtures\BlogPost" xml-root-name="blog-post" exclusion-policy="ALL">
        <property name="title" type="string" expose="true" />
    </class>
</serializer><?xml version="1.0" encoding="UTF-8"?>
<serializer>
    <class name="JMS\Serializer\Tests\Fixtures\Discriminator\Vehicle" discriminator-field-name="type">
        <discriminator-class value="car">JMS\Serializer\Tests\Fixtures\Discriminator\Car</discriminator-class>
        <discriminator-class value="moped">JMS\Serializer\Tests\Fixtures\Discriminator\Moped</discriminator-class>
        <property name="km" type="integer" />
    </class>
</serializer><?xml version="1.0" encoding="UTF-8"?>
<serializer>
    <class name="JMS\Serializer\Tests\Fixtures\ObjectWithXmlKeyValuePairs" >
        <property name="array" type="array" xml-key-value-pairs="true" />
    </class>
</serializer>
<?xml version="1.0" encoding="UTF-8"?>
<serializer>
    <class name="JMS\Serializer\Tests\Fixtures\BlogPost" xml-root-name="blog-post" exclusion-policy="all">
        <property name="title" type="string" expose="TRUE" />
    </class>
</serializer><?xml version="1.0" encoding="UTF-8"?>
<serializer>
    <class name="JMS\Serializer\Tests\Fixtures\Discriminator\Car">
    </class>
</serializer><?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Metadata\Driver;

use Metadata\Driver\FileLocator;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Metadata\Driver\XmlDriver;

class XmlDriverTest extends BaseDriverTest
{
    /**
     * @expectedException JMS\Serializer\Exception\XmlErrorException
     * @expectedExceptionMessage [FATAL] Start tag expected, '<' not found
     */
    public function testInvalidXml()
    {
        $driver = $this->getDriver();

        $ref = new \ReflectionMethod($driver, 'loadMetadataFromFile');
        $ref->setAccessible(true);
        $ref->invoke($driver, new \ReflectionClass('stdClass'), __DIR__.'/xml/invalid.xml');
    }

    public function testBlogPostExcludeAllStrategy()
    {
        $m = $this->getDriver('exclude_all')->loadMetadataForClass(new \ReflectionClass('JMS\Serializer\Tests\Fixtures\BlogPost'));

        $this->assertArrayHasKey('title', $m->propertyMetadata);

        $excluded = array('createdAt', 'published', 'comments', 'author');
        foreach ($excluded as $key) {
            $this->assertArrayNotHasKey($key, $m->propertyMetadata);
        }
    }

    public function testBlogPostExcludeNoneStrategy()
    {
        $m = $this->getDriver('exclude_none')->loadMetadataForClass(new \ReflectionClass('JMS\Serializer\Tests\Fixtures\BlogPost'));

        $this->assertArrayNotHasKey('title', $m->propertyMetadata);

        $excluded = array('createdAt', 'published', 'comments', 'author');
        foreach ($excluded as $key) {
            $this->assertArrayHasKey($key, $m->propertyMetadata);
        }
    }

    public function testBlogPostCaseInsensitive()
    {
        $m = $this->getDriver('case')->loadMetadataForClass(new \ReflectionClass('JMS\Serializer\Tests\Fixtures\BlogPost'));

        $p = new PropertyMetadata($m->name, 'title');
        $p->type = array('name' => 'string', 'params' => array());
        $this->assertEquals($p, $m->propertyMetadata['title']);
    }

    public function testAccessorAttributes()
    {
        $m = $this->getDriver()->loadMetadataForClass(new \ReflectionClass('JMS\Serializer\Tests\Fixtures\GetSetObject'));

        $p = new PropertyMetadata($m->name, 'name');
        $p->type = array('name' => 'string', 'params' => array());
        $p->getter = 'getTrimmedName';
        $p->setter = 'setCapitalizedName';

        $this->assertEquals($p, $m->propertyMetadata['name']);
    }

    protected function getDriver()
    {
        $append = '';
        if (func_num_args() == 1) {
            $append = '/'.func_get_arg(0);
        }
        return new XmlDriver(new FileLocator(array(
            'JMS\Serializer\Tests\Fixtures' => __DIR__.'/xml'.$append,
        )));
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Metadata\Driver;

use Metadata\Driver\FileLocator;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\Metadata\Driver\YamlDriver;

class YamlDriverTest extends BaseDriverTest
{
    public function testBlogPostExcludeAllStrategy()
    {
        $m = $this->getDriver('exclude_all')->loadMetadataForClass(new \ReflectionClass('JMS\Serializer\Tests\Fixtures\BlogPost'));

        $this->assertArrayHasKey('title', $m->propertyMetadata);

        $excluded = array('createdAt', 'published', 'comments', 'author');
        foreach ($excluded as $key) {
            $this->assertArrayNotHasKey($key, $m->propertyMetadata);
        }
    }

    public function testBlogPostExcludeNoneStrategy()
    {
        $m = $this->getDriver('exclude_none')->loadMetadataForClass(new \ReflectionClass('JMS\Serializer\Tests\Fixtures\BlogPost'));

        $this->assertArrayNotHasKey('title', $m->propertyMetadata);

        $excluded = array('createdAt', 'published', 'comments', 'author');
        foreach ($excluded as $key) {
            $this->assertArrayHasKey($key, $m->propertyMetadata);
        }
    }

    public function testBlogPostCaseInsensitive()
    {
        $m = $this->getDriver('case')->loadMetadataForClass(new \ReflectionClass('JMS\Serializer\Tests\Fixtures\BlogPost'));

        $p = new PropertyMetadata($m->name, 'title');
        $p->type = array('name' => 'string', 'params' => array());
        $this->assertEquals($p, $m->propertyMetadata['title']);
    }

    public function testBlogPostAccessor()
    {
        $m = $this->getDriver('accessor')->loadMetadataForClass(new \ReflectionClass('JMS\Serializer\Tests\Fixtures\BlogPost'));

        $this->assertArrayHasKey('title', $m->propertyMetadata);

        $p = new PropertyMetadata($m->name, 'title');
        $p->getter = 'getOtherTitle';
        $p->setter = 'setOtherTitle';
        $this->assertEquals($p, $m->propertyMetadata['title']);
    }

    protected function getDriver()
    {
        $append = '';
        if (func_num_args() == 1) {
            $append = '/'.func_get_arg(0);
        }

        return new YamlDriver(new FileLocator(array(
            'JMS\Serializer\Tests\Fixtures' => __DIR__.'/yml'.$append,
        )));
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Metadata\Driver;

use Doctrine\Common\Annotations\AnnotationReader;
use JMS\Serializer\Metadata\Driver\AnnotationDriver;

class AnnotationDriverTest extends BaseDriverTest
{
    protected function getDriver()
    {
        return new AnnotationDriver(new AnnotationReader());
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Metadata\Driver;

use Metadata\Driver\FileLocator;
use JMS\Serializer\Metadata\Driver\PhpDriver;

class PhpDriverTest extends BaseDriverTest
{
    protected function getDriver()
    {
        return new PhpDriver(new FileLocator(array(
            'JMS\Serializer\Tests\Fixtures' => __DIR__.'/php',
        )));
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Metadata\Driver;

use JMS\Serializer\Metadata\Driver\AnnotationDriver;
use JMS\Serializer\Metadata\Driver\DoctrineTypeDriver;
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\ORM\Configuration;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping\Driver\AnnotationDriver as DoctrineDriver;

class DoctrineDriverTest extends \PHPUnit_Framework_TestCase
{
    public function getMetadata()
    {
        $refClass = new \ReflectionClass('JMS\Serializer\Tests\Fixtures\Doctrine\BlogPost');
        $metadata = $this->getDoctrineDriver()->loadMetadataForClass($refClass);

        return $metadata;
    }

    public function testTypelessPropertyIsGivenTypeFromDoctrineMetadata()
    {
        $metadata = $this->getMetadata();

        $this->assertEquals(
            array('name'=> 'DateTime', 'params' => array()),
            $metadata->propertyMetadata['createdAt']->type
        );
    }

    public function testSingleValuedAssociationIsProperlyHinted()
    {
        $metadata = $this->getMetadata();
        $this->assertEquals(
            array('name'=> 'JMS\Serializer\Tests\Fixtures\Doctrine\Author', 'params' => array()),
            $metadata->propertyMetadata['author']->type
        );
    }

    public function testMultiValuedAssociationIsProperlyHinted()
    {
        $metadata = $this->getMetadata();

        $this->assertEquals(
            array('name'=> 'ArrayCollection', 'params' => array(
                array('name' => 'JMS\Serializer\Tests\Fixtures\Doctrine\Comment', 'params' => array()))
            ),
            $metadata->propertyMetadata['comments']->type
        );
    }

    public function testTypeGuessByDoctrineIsOverwrittenByDelegateDriver()
    {
        $metadata = $this->getMetadata();

        // This would be guessed as boolean but we've overriden it to integer
        $this->assertEquals(
            array('name'=> 'integer', 'params' => array()), 
            $metadata->propertyMetadata['published']->type
        );
    }

    public function testUnknownDoctrineTypeDoesNotResultInAGuess()
    {
        $metadata = $this->getMetadata();
        $this->assertNull($metadata->propertyMetadata['slug']->type);
    }

    public function testNonDoctrineEntityClassIsNotModified()
    {
        // Note: Using regular BlogPost fixture here instead of Doctrine fixture
        // because it has no Doctrine metadata.
        $refClass = new \ReflectionClass('JMS\Serializer\Tests\Fixtures\BlogPost');

        $plainMetadata = $this->getAnnotationDriver()->loadMetadataForClass($refClass);
        $doctrineMetadata = $this->getDoctrineDriver()->loadMetadataForClass($refClass);

        $this->assertEquals($plainMetadata, $doctrineMetadata);
    }

    protected function getEntityManager()
    {
        $config = new Configuration();
        $config->setProxyDir(sys_get_temp_dir() . '/JMSDoctrineTestProxies');
        $config->setProxyNamespace('JMS\Tests\Proxies');
        $config->setMetadataDriverImpl(
            new DoctrineDriver(new AnnotationReader(), __DIR__.'/../../Fixtures/Doctrine')
        );

        $conn = array(
            'driver' => 'pdo_sqlite',
            'memory' => true,
        );

        return EntityManager::create($conn, $config);
    }

    public function getAnnotationDriver()
    {
        return new AnnotationDriver(new AnnotationReader());
    }

    protected function getDoctrineDriver()
    {
        $registry = $this->getMock('Doctrine\Common\Persistence\ManagerRegistry');
        $registry->expects($this->atLeastOnce())
             ->method('getManagerForClass')
             ->will($this->returnValue($this->getEntityManager()));

        return new DoctrineTypeDriver(
            $this->getAnnotationDriver(),
            $registry
        );
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Serializer\EventDispatcher;

use JMS\Serializer\EventDispatcher\Event;
use JMS\Serializer\EventDispatcher\EventDispatcher;
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\EventDispatcher\ObjectEvent;

class EventDispatcherTest extends \PHPUnit_Framework_TestCase
{
    private $dispatcher;
    private $event;

    public function testHasListeners()
    {
        $this->assertFalse($this->dispatcher->hasListeners('foo', 'Foo', 'json'));
        $this->dispatcher->addListener('foo', function() { });
        $this->assertTrue($this->dispatcher->hasListeners('foo', 'Foo', 'json'));

        $this->assertFalse($this->dispatcher->hasListeners('bar', 'Bar', 'json'));
        $this->dispatcher->addListener('bar', function() { }, 'Foo');
        $this->assertFalse($this->dispatcher->hasListeners('bar', 'Bar', 'json'));
        $this->dispatcher->addListener('bar', function() { }, 'Bar', 'xml');
        $this->assertFalse($this->dispatcher->hasListeners('bar', 'Bar', 'json'));
        $this->dispatcher->addListener('bar', function() { }, null, 'json');
        $this->assertTrue($this->dispatcher->hasListeners('bar', 'Baz', 'json'));
        $this->assertTrue($this->dispatcher->hasListeners('bar', 'Bar', 'json'));

        $this->assertFalse($this->dispatcher->hasListeners('baz', 'Bar', 'xml'));
        $this->dispatcher->addListener('baz', function() { }, 'Bar');
        $this->assertTrue($this->dispatcher->hasListeners('baz', 'Bar', 'xml'));
        $this->assertTrue($this->dispatcher->hasListeners('baz', 'bAr', 'xml'));
    }

    public function testDispatch()
    {
        $a = new MockListener();
        $this->dispatcher->addListener('foo', array($a, 'foo'));
        $this->dispatch('bar');
        $a->_verify('Listener is not called for other event.');

        $b = new MockListener();
        $this->dispatcher->addListener('pre', array($b, 'bar'), 'Bar');
        $this->dispatcher->addListener('pre', array($b, 'foo'), 'Foo');
        $this->dispatcher->addListener('pre', array($b, 'all'));

        $b->bar($this->event);
        $b->all($this->event);
        $b->foo($this->event);
        $b->all($this->event);
        $b->_replay();
        $this->dispatch('pre', 'Bar');
        $this->dispatch('pre', 'Foo');
        $b->_verify();
    }

    public function testAddSubscriber()
    {
        $subscriber = new MockSubscriber();
        MockSubscriber::$events = array(
            array('event' => 'foo.bar_baz', 'format' => 'foo'),
            array('event' => 'bar', 'method' => 'bar', 'class' => 'foo'),
        );

        $this->dispatcher->addSubscriber($subscriber);
        $this->assertAttributeEquals(array(
            'foo.bar_baz' => array(
                array(array($subscriber, 'onfoobarbaz'), null, 'foo'),
            ),
            'bar' => array(
                array(array($subscriber, 'bar'), 'foo', null),
            ),
        ), 'listeners', $this->dispatcher);
    }

    protected function setUp()
    {
        $this->dispatcher = new EventDispatcher();
        $this->event = new ObjectEvent($this->getMock('JMS\Serializer\Context'), new \stdClass(), array('name' => 'foo', 'params' => array()));
    }

    private function dispatch($eventName, $class = 'Foo', $format = 'json', Event $event = null)
    {
        $this->dispatcher->dispatch($eventName, $class, $format, $event ?: $this->event);
    }
}

class MockSubscriber implements EventSubscriberInterface
{
    public static $events = array();

    public static function getSubscribedEvents()
    {
        return self::$events;
    }
}

class MockListener
{
    private $expected = array();
    private $actual = array();
    private $wasReplayed = false;

    public function __call($method, array $args = array())
    {
        if ( ! $this->wasReplayed) {
            $this->expected[] = array($method, $args);

            return;
        }

        $this->actual[] = array($method, $args);
    }

    public function _replay()
    {
        $this->wasReplayed = true;
    }

    public function _verify($message = null)
    {
        \PHPUnit_Framework_Assert::assertSame($this->expected, $this->actual, $message);
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Serializer\EventDispatcher\Subscriber;

use JMS\Serializer\EventDispatcher\PreSerializeEvent;
use JMS\Serializer\EventDispatcher\Subscriber\DoctrineProxySubscriber;
use JMS\Serializer\Tests\Fixtures\SimpleObjectProxy;
use JMS\Serializer\VisitorInterface;

class DoctrineProxySubscriberTest extends \PHPUnit_Framework_TestCase
{
    /** @var VisitorInterface */
    private $visitor;

    /** @var DoctrineProxySubscriber */
    private $subscriber;

    public function testRewritesProxyClassName()
    {
        $event = $this->createEvent($obj = new SimpleObjectProxy('a', 'b'), array('name' => get_class($obj), 'params' => array()));
        $this->subscriber->onPreSerialize($event);

        $this->assertEquals(array('name' => get_parent_class($obj), 'params' => array()), $event->getType());
        $this->assertTrue($obj->__isInitialized());
    }

    public function testDoesNotRewriteCustomType()
    {
        $event = $this->createEvent($obj = new SimpleObjectProxy('a', 'b'), array('name' => 'FakedName', 'params' => array()));
        $this->subscriber->onPreSerialize($event);

        $this->assertEquals(array('name' => 'FakedName', 'params' => array()), $event->getType());
        $this->assertTrue($obj->__isInitialized());
    }

    protected function setUp()
    {
        $this->subscriber = new DoctrineProxySubscriber();
        $this->visitor = $this->getMock('JMS\Serializer\Context');
    }

    private function createEvent($object, array $type)
    {
        return new PreSerializeEvent($this->visitor, $object, $type);
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Serializer\EventDispatcher\Subscriber;

use JMS\Serializer\Context;
use JMS\Serializer\DeserializationContext;
use JMS\Serializer\EventDispatcher\Event;
use JMS\Serializer\EventDispatcher\EventDispatcher;
use JMS\Serializer\EventDispatcher\ObjectEvent;
use JMS\Serializer\EventDispatcher\Subscriber\SymfonyValidatorSubscriber;
use JMS\Serializer\GraphNavigator;
use JMS\Serializer\Handler\HandlerRegistryInterface;
use JMS\Serializer\SerializerBuilder;
use JMS\Serializer\Tests\Fixtures\AuthorList;
use JMS\Serializer\Tests\Fixtures\Doctrine\Author;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;

class SymfonyValidatorSubscriberTest extends \PHPUnit_Framework_TestCase
{
    private $validator;

    /** @var SymfonyValidatorSubscriber */
    private $subscriber;

    /** @var Context */
    private $context;

    public function testValidate()
    {
        $obj = new \stdClass;

        $this->validator->expects($this->once())
            ->method('validate')
            ->with($obj, array('foo'))
            ->will($this->returnValue(new ConstraintViolationList()));

        $context = DeserializationContext::create()->setAttribute('validation_groups', array('foo'));

        $this->subscriber->onPostDeserialize(new ObjectEvent($context, $obj, array()));
    }

    /**
     * @expectedException JMS\Serializer\Exception\ValidationFailedException
     * @expectedExceptionMessage Validation failed with 1 error(s).
     */
    public function testValidateThrowsExceptionWhenListIsNotEmpty()
    {
        $obj = new \stdClass;

        $this->validator->expects($this->once())
            ->method('validate')
            ->with($obj, array('foo'))
            ->will($this->returnValue(new ConstraintViolationList(array(new ConstraintViolation('foo', array(), 'a', 'b', 'c')))));

        $context = DeserializationContext::create()->setAttribute('validation_groups', array('foo'));

        $this->subscriber->onPostDeserialize(new ObjectEvent($context, $obj, array()));
    }

    public function testValidatorIsNotCalledWhenNoGroupsAreSet()
    {
        $this->validator->expects($this->never())
            ->method('validate');

        $this->subscriber->onPostDeserialize(new ObjectEvent(DeserializationContext::create(), new \stdClass, array()));
    }

    public function testValidationIsOnlyPerformedOnRootObject()
    {
        $this->validator->expects($this->once())
            ->method('validate')
            ->with($this->isInstanceOf('JMS\Serializer\Tests\Fixtures\AuthorList'), array('Foo'))
            ->will($this->returnValue(new ConstraintViolationList()));

        $subscriber = $this->subscriber;
        $list = SerializerBuilder::create()
            ->configureListeners(function(EventDispatcher $dispatcher) use ($subscriber) {
                $dispatcher->addSubscriber($subscriber);
            })
            ->build()
            ->deserialize(
                '{"authors":[{"full_name":"foo"},{"full_name":"bar"}]}',
                'JMS\Serializer\Tests\Fixtures\AuthorList',
                'json',
                DeserializationContext::create()->setAttribute('validation_groups', array('Foo'))
            );

        $this->assertCount(2, $list);
    }

    protected function setUp()
    {
        $this->validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface');
        $this->subscriber = new SymfonyValidatorSubscriber($this->validator);
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Serializer;

use JMS\Serializer\Exception\RuntimeException;

class YamlSerializationTest extends BaseSerializationTest
{
    public function testConstraintViolation()
    {
        $this->markTestSkipped('This is not available for the YAML format.');
    }

    public function testConstraintViolationList()
    {
        $this->markTestSkipped('This is not available for the YAML format.');
    }

    public function testFormErrors()
    {
        $this->markTestSkipped('This is not available for the YAML format.');
    }

    public function testNestedFormErrors()
    {
        $this->markTestSkipped('This is not available for the YAML format.');
    }

    protected function getContent($key)
    {
        if (!file_exists($file = __DIR__.'/yml/'.$key.'.yml')) {
            throw new RuntimeException(sprintf('The content with key "%s" does not exist.', $key));
        }

        return file_get_contents($file);
    }

    protected function getFormat()
    {
        return 'yml';
    }

    protected function hasDeserializer()
    {
        return false;
    }
}-
    foo: foo
    moo: bar
    camel_case: boo
-
    foo: baz
    moo: boo
    camel_case: boo
title: 'This is a nice title.'
created_at: '2011-07-30T00:00:00+0000'
is_published: false
metadata:
    foo: bar
author: null
- foo
- bar
bar: bar
none: none
c: c
d: d
a: a
b: b
cost:
    currency: EUR
    amount: 1.23
low: 1
high: 8
false
foo: c
b: b
a: a
attributes:
    type: text
    name: firstname
    value: Adrien
foo: foo
foobar: foobar
bar: bar
hash: {}
tree:
    children:
        -
            children:
                -
                    children:
                        -
                    foo: bar
            foo: bar
    foo: bar
name: 'Foo Bar'
'2011-08-30T00:00:00+0000'
foo: foo
foobar: foobar
bar: bar
none: none
true
cost:
    price: 12.34
comments:
    Foo:
        comments:
            -
                author:
                    full_name: Foo
                text: foo
            -
                author:
                    full_name: Foo
                text: bar
        count: 2
low: 1
foo: foo
moo: bar
camel_case: boo
author_list:
    -
        full_name: 'Johannes Schmitt'
    -
        full_name: 'John Doe'
comments:
    -
        author:
            full_name: 'Foo Bar'
        text: foo
    -
        author:
            full_name: 'Foo Bar'
        text: bar
    -
        author:
            full_name: 'Foo Bar'
        text: baz
- true
- false
exist_field: value
test: other-name
virtual_value: value
typed_virtual_property: 1
id: 1
name: Johannes
read_only_property: 42
null
- 1.34
- 3
- 6.42
foo
title: 'This is a nice title.'
created_at: '2011-07-30T00:00:00+0000'
is_published: false
comments:
    -
        author:
            full_name: 'Foo Bar'
        text: foo
comments2:
    -
        author:
            full_name: 'Foo Bar'
        text: foo
metadata:
    foo: bar
author:
    full_name: 'Foo Bar'
author: null
text: foo
1
- 1
- 3
- 4
foo: foo
foobar: foobar
PT45M
high: 8
foo: bar
baz: null
km: 5
type: car
- foo
- 1
- true
-
    foo: foo
    moo: bar
    camel_case: boo
-
    - 1
    - 3
    - true
km: 5
custom: serialized
id: 123
full_name: 'Ruud Kamphuis'
foo: foo
moo: bar
camel_case: proxy-boo
foo: foo
moo: bar
camel_case: boo
null_property: null
currency: EUR
amount: 2.34
text: foo
c: c
a: a
b: b
d: d
a: a
b: b
4.533
collection:
    -
        name: child1
    -
        name: child2
another_collection:
    -
        name: child1
    -
        name: child2
price: 3
1
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Serializer;

use JMS\Serializer\TypeParser;

class TypeParserTest extends \PHPUnit_Framework_TestCase
{
    private $parser;

    /**
     * @dataProvider getTypes
     */
    public function testParse($type, $name, array $params = array())
    {
        $this->assertEquals(array('name' => $name, 'params' => $params), $this->parser->parse($type));
    }

    public function getTypes()
    {
        $types = array();
        $types[] = array('string', 'string');
        $types[] = array('array<Foo>', 'array', array(array('name' => 'Foo', 'params' => array())));
        $types[] = array('array<Foo,Bar>', 'array', array(array('name' => 'Foo', 'params' => array()), array('name' => 'Bar', 'params' => array())));
        $types[] = array('array<Foo\Bar, Baz\Boo>', 'array', array(array('name' => 'Foo\Bar', 'params' => array()), array('name' => 'Baz\Boo', 'params' => array())));
        $types[] = array('a<b<c,d>,e>', 'a', array(array('name' => 'b', 'params' => array(array('name' => 'c', 'params' => array()), array('name' => 'd', 'params' => array()))), array('name' => 'e', 'params' => array())));
        $types[] = array('Foo', 'Foo');
        $types[] = array('Foo\Bar', 'Foo\Bar');
        $types[] = array('Foo<"asdf asdf">', 'Foo', array('asdf asdf'));

        return $types;
    }

    /**
     * @expectedException \JMS\Parser\SyntaxErrorException
     * @expectedExceptionMessage Expected T_CLOSE_BRACKET, but got end of input.
     */
    public function testParamTypeMustEndWithBracket()
    {
        $this->parser->parse('Foo<bar');
    }

    /**
     * @expectedException \JMS\Parser\SyntaxErrorException
     * @expectedExceptionMessage Expected T_NAME, but got "," of type T_COMMA at beginning of input.
     */
    public function testMustStartWithName()
    {
        $this->parser->parse(',');
    }

    /**
     * @expectedException \JMS\Parser\SyntaxErrorException
     * @expectedExceptionMessage Expected any of T_NAME or T_STRING, but got ">" of type T_CLOSE_BRACKET at position 4 (0-based).
     */
    public function testEmptyParams()
    {
        $this->parser->parse('Foo<>');
    }

    /**
     * @expectedException \JMS\Parser\SyntaxErrorException
     * @expectedExceptionMessage Expected any of T_NAME or T_STRING, but got ">" of type T_CLOSE_BRACKET at position 7 (0-based).
     */
    public function testNoTrailingComma()
    {
        $this->parser->parse('Foo<aa,>');
    }

    protected function setUp()
    {
        $this->parser = new TypeParser();
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Serializer\Naming;

use JMS\Serializer\Naming\IdenticalPropertyNamingStrategy;

class IdenticalPropertyNamingStrategyTest extends \PHPUnit_Framework_TestCase
{
    public function providePropertyNames()
    {
        return array(
            array('createdAt'),
            array('my_field'),
            array('identical')
        );
    }

    /**
     * @dataProvider providePropertyNames
     */
    public function testTranslateName($propertyName)
    {
        $mockProperty = $this->getMockBuilder('JMS\Serializer\Metadata\PropertyMetadata')->disableOriginalConstructor()->getMock();
        $mockProperty->name = $propertyName;

        $strategy = new IdenticalPropertyNamingStrategy();
        $this->assertEquals($propertyName, $strategy->translateName($mockProperty));
    }
}<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Serializer;

use JMS\Serializer\Context;
use JMS\Serializer\SerializationContext;
use JMS\Serializer\Tests\Fixtures\InvalidUsageOfXmlValue;
use JMS\Serializer\Exception\InvalidArgumentException;
use JMS\Serializer\Tests\Fixtures\PersonCollection;
use JMS\Serializer\Tests\Fixtures\PersonLocation;
use JMS\Serializer\Tests\Fixtures\Person;
use JMS\Serializer\Tests\Fixtures\ObjectWithVirtualXmlProperties;
use JMS\Serializer\Tests\Fixtures\ObjectWithXmlKeyValuePairs;
use JMS\Serializer\Tests\Fixtures\Input;

class XmlSerializationTest extends BaseSerializationTest
{
    /**
     * @expectedException JMS\Serializer\Exception\RuntimeException
     */
    public function testInvalidUsageOfXmlValue()
    {
        $obj = new InvalidUsageOfXmlValue();
        $this->serialize($obj);
    }

    public function testPropertyIsObjectWithAttributeAndValue()
    {
        $personCollection = new PersonLocation;
        $person = new Person;
        $person->name = 'Matthias Noback';
        $person->age = 28;
        $personCollection->person = $person;
        $personCollection->location = 'The Netherlands';

        $this->assertEquals($this->getContent('person_location'), $this->serialize($personCollection));
    }

    public function testPropertyIsCollectionOfObjectsWithAttributeAndValue()
    {
        $personCollection = new PersonCollection;
        $person = new Person;
        $person->name = 'Matthias Noback';
        $person->age = 28;
        $personCollection->persons->add($person);
        $personCollection->location = 'The Netherlands';

        $this->assertEquals($this->getContent('person_collection'), $this->serialize($personCollection));
    }

    /**
     * @expectedException JMS\Serializer\Exception\InvalidArgumentException
     * @expectedExceptionMessage The document type "<!DOCTYPE author [<!ENTITY foo SYSTEM "php://filter/read=convert.base64-encode/resource=XmlSerializationTest.php">]>" is not allowed. If it is safe, you may add it to the whitelist configuration.
     */
    public function testExternalEntitiesAreDisabledByDefault()
    {
        $this->deserialize('<?xml version="1.0"?>
            <!DOCTYPE author [
                <!ENTITY foo SYSTEM "php://filter/read=convert.base64-encode/resource='.basename(__FILE__).'">
            ]>
            <result>
                &foo;
            </result>', 'stdClass');
    }

    /**
     * @expectedException JMS\Serializer\Exception\InvalidArgumentException
     * @expectedExceptionMessage The document type "<!DOCTYPE foo>" is not allowed. If it is safe, you may add it to the whitelist configuration.
     */
    public function testDocumentTypesAreNotAllowed()
    {
        $this->deserialize('<?xml version="1.0"?><!DOCTYPE foo><foo></foo>', 'stdClass');
    }

    public function testWhitelistedDocumentTypesAreAllowed()
    {
        $this->deserializationVisitors->get('xml')->get()->setDoctypeWhitelist(array(
            '<!DOCTYPE authorized SYSTEM "http://authorized_url.dtd">',
            '<!DOCTYPE author [<!ENTITY foo SYSTEM "php://filter/read=convert.base64-encode/resource='.basename(__FILE__).'">]>'));

        $this->serializer->deserialize('<?xml version="1.0"?>
            <!DOCTYPE authorized SYSTEM "http://authorized_url.dtd">
            <foo></foo>', 'stdClass', 'xml');

        $this->serializer->deserialize('<?xml version="1.0"?>
            <!DOCTYPE author [
                <!ENTITY foo SYSTEM "php://filter/read=convert.base64-encode/resource='.basename(__FILE__).'">
            ]>
            <foo></foo>', 'stdClass', 'xml');
    }

    public function testVirtualAttributes()
    {
        $this->assertEquals(
            $this->getContent('virtual_attributes'),
            $this->serialize(new ObjectWithVirtualXmlProperties(), SerializationContext::create()->setGroups(array('attributes')))
        );
    }

    public function testVirtualValues()
    {
        $this->assertEquals(
            $this->getContent('virtual_values'),
            $this->serialize(new ObjectWithVirtualXmlProperties(), SerializationContext::create()->setGroups(array('values')))
        );
    }

    public function testVirtualXmlList()
    {
        $this->assertEquals(
            $this->getContent('virtual_properties_list'),
            $this->serialize(new ObjectWithVirtualXmlProperties(), SerializationContext::create()->setGroups(array('list')))
        );
    }

    public function testVirtualXmlMap()
    {
        $this->assertEquals(
            $this->getContent('virtual_properties_map'),
            $this->serialize(new ObjectWithVirtualXmlProperties(), SerializationContext::create()->setGroups(array('map')))
        );
    }

    public function testArrayKeyValues()
    {
        $this->assertEquals($this->getContent('array_key_values'), $this->serializer->serialize(new ObjectWithXmlKeyValuePairs(), 'xml'));
    }

    /**
     * @expectedException JMS\Serializer\Exception\RuntimeException
     * @expectedExceptionMessage Unsupported value type for XML attribute map. Expected array but got object
     */
    public function testXmlAttributeMapWithoutArray()
    {
        $attributes = new \ArrayObject(array(
            'type' => 'text',
        ));

        $this->serializer->serialize(new Input($attributes), $this->getFormat());
    }

    public function testDeserializingNull()
    {
        $this->markTestSkipped('Not supported in XML.');
    }

    /**
     * @param string $key
     */
    protected function getContent($key)
    {
        if (!file_exists($file = __DIR__.'/xml/'.$key.'.xml')) {
            throw new InvalidArgumentException(sprintf('The key "%s" is not supported.', $key));
        }

        return file_get_contents($file);
    }

    protected function getFormat()
    {
        return 'xml';
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Serializer;

use JMS\Serializer\Handler\DateHandler;

class DateIntervalFormatTest extends \PHPUnit_Framework_TestCase
{
    public function testFormat()
    {
        $dtf = new DateHandler();

        $iso8601DateIntervalString = $dtf->format(new \DateInterval('PT45M'));

        $this->assertEquals($iso8601DateIntervalString, 'PT45M');

        $iso8601DateIntervalString = $dtf->format(new \DateInterval('P2YT45M'));

        $this->assertEquals($iso8601DateIntervalString, 'P2YT45M');

        $iso8601DateIntervalString = $dtf->format(new \DateInterval('P2Y4DT6H8M16S'));

        $this->assertEquals($iso8601DateIntervalString, 'P2Y4DT6H8M16S');
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <foo><![CDATA[foo]]></foo>
  <moo><![CDATA[bar]]></moo>
  <camel_case><![CDATA[boo]]></camel_case>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result>1</result>
<?xml version="1.0" encoding="UTF-8"?>
<order>
  <cost>12.34</cost>
</order>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <name><![CDATA[Foo Bar]]></name>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <c><![CDATA[c]]></c>
  <d><![CDATA[d]]></d>
  <a><![CDATA[a]]></a>
  <b><![CDATA[b]]></b>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<price currency="EUR">2.34</price>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <low>1</low>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <foo><![CDATA[foo]]></foo>
  <moo><![CDATA[bar]]></moo>
  <camel_case><![CDATA[proxy-boo]]></camel_case>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <exist_field><![CDATA[value]]></exist_field>
  <test><![CDATA[other-name]]></test>
  <virtual_value><![CDATA[value]]></virtual_value>
  <typed_virtual_property>1</typed_virtual_property>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <tree>
    <children>
      <entry>
        <children>
          <entry>
            <children>
              <entry/>
            </children>
            <foo><![CDATA[bar]]></foo>
          </entry>
        </children>
        <foo><![CDATA[bar]]></foo>
      </entry>
    </children>
    <foo><![CDATA[bar]]></foo>
  </tree>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <high>8</high>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<person_collection>
  <person age="28"><![CDATA[Matthias Noback]]></person>
  <location><![CDATA[The Netherlands]]></location>
</person_collection>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <entry>
    <foo><![CDATA[foo]]></foo>
    <moo><![CDATA[bar]]></moo>
    <camel_case><![CDATA[boo]]></camel_case>
  </entry>
  <entry>
    <foo><![CDATA[baz]]></foo>
    <moo><![CDATA[boo]]></moo>
    <camel_case><![CDATA[boo]]></camel_case>
  </entry>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result>false</result>
<?xml version="1.0" encoding="UTF-8"?>
<post>
  <comments author-name="Foo" count="2">
    <comment>
      <author>
        <full_name><![CDATA[Foo]]></full_name>
      </author>
      <text><![CDATA[foo]]></text>
    </comment>
    <comment>
      <author>
        <full_name><![CDATA[Foo]]></full_name>
      </author>
      <text><![CDATA[bar]]></text>
    </comment>
  </comments>
</post>
<?xml version="1.0" encoding="UTF-8"?>
<custom>serialized</custom>
<?xml version="1.0" encoding="UTF-8"?>
<form name="foo">
  <errors>
    <entry><![CDATA[This is the form error]]></entry>
  </errors>
  <form name="bar">
    <errors>
      <entry><![CDATA[Error of the child form]]></entry>
    </errors>
  </form>
</form>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <foo><![CDATA[c]]></foo>
  <b><![CDATA[b]]></b>
  <a><![CDATA[a]]></a>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <violation property_path="foo">
    <message><![CDATA[Message of violation]]></message>
  </violation>
  <violation property_path="bar">
    <message><![CDATA[Message of another violation]]></message>
  </violation>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <a><![CDATA[a]]></a>
  <b><![CDATA[b]]></b>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <entry><![CDATA[This is the form error]]></entry>
  <entry><![CDATA[Another error]]></entry>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <bar><![CDATA[bar]]></bar>
  <none><![CDATA[none]]></none>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <foo><![CDATA[foo]]></foo>
  <moo><![CDATA[bar]]></moo>
  <camel_case><![CDATA[boo]]></camel_case>
  <null_property xsi:nil="true"/>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <foo><![CDATA[foo]]></foo>
  <foobar><![CDATA[foobar]]></foobar>
  <bar><![CDATA[bar]]></bar>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<blog-post created_at="2011-07-30T00:00:00+0000" is_published="false">
  <title><![CDATA[This is a nice title.]]></title>
  <comment>
    <author>
      <full_name><![CDATA[Foo Bar]]></full_name>
    </author>
    <text><![CDATA[foo]]></text>
  </comment>
  <comment2>
    <author>
      <full_name><![CDATA[Foo Bar]]></full_name>
    </author>
    <text><![CDATA[foo]]></text>
  </comment2>
  <metadata>
    <entry key="foo"><![CDATA[bar]]></entry>
  </metadata>
  <author>
    <full_name><![CDATA[Foo Bar]]></full_name>
  </author>
</blog-post>
<?xml version="1.0" encoding="UTF-8"?>
<log>
  <author_list>
    <entry _key="0">
      <full_name><![CDATA[Johannes Schmitt]]></full_name>
    </entry>
    <entry _key="1">
      <full_name><![CDATA[John Doe]]></full_name>
    </entry>
  </author_list>
  <comment>
    <author>
      <full_name><![CDATA[Foo Bar]]></full_name>
    </author>
    <text><![CDATA[foo]]></text>
  </comment>
  <comment>
    <author>
      <full_name><![CDATA[Foo Bar]]></full_name>
    </author>
    <text><![CDATA[bar]]></text>
  </comment>
  <comment>
    <author>
      <full_name><![CDATA[Foo Bar]]></full_name>
    </author>
    <text><![CDATA[baz]]></text>
  </comment>
</log>
<?xml version="1.0" encoding="UTF-8"?>
<result>4.533</result>
<?xml version="1.0" encoding="UTF-8"?>
<result><![CDATA[xml-value]]></result>
<?xml version="1.0" encoding="UTF-8"?>
<result xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <entry><![CDATA[bar]]></entry>
  <entry xsi:nil="true"/>
  <entry xsi:nil="true"/>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <id>1</id>
  <name><![CDATA[Johannes]]></name>
  <read_only_property>42</read_only_property>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <entry>true</entry>
  <entry>false</entry>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result>1</result>
<?xml version="1.0" encoding="UTF-8"?>
<person_location>
  <person age="28"><![CDATA[Matthias Noback]]></person>
  <location><![CDATA[The Netherlands]]></location>
</person_location>
<?xml version="1.0" encoding="UTF-8"?>
<result>true</result>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <low>1</low>
  <high>8</high>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<blog-post created_at="2011-07-30T00:00:00+0000" is_published="false">
  <title><![CDATA[This is a nice title.]]></title>
  <author xsi:nil="true"/>
</blog-post>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <entry><![CDATA[foo]]></entry>
  <entry>1</entry>
  <entry>true</entry>
  <entry>
    <foo><![CDATA[foo]]></foo>
    <moo><![CDATA[bar]]></moo>
    <camel_case><![CDATA[boo]]></camel_case>
  </entry>
  <entry>
    <entry>1</entry>
    <entry>3</entry>
    <entry>true</entry>
  </entry>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <entry>1</entry>
  <entry>3</entry>
  <entry>4</entry>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result><![CDATA[2011-08-30T00:00:00+0000]]></result>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <collection>
    <entry>
      <name><![CDATA[child1]]></name>
    </entry>
    <entry>
      <name><![CDATA[child2]]></name>
    </entry>
  </collection>
  <another_collection>
    <entry>
      <name><![CDATA[child1]]></name>
    </entry>
    <entry>
      <name><![CDATA[child2]]></name>
    </entry>
  </another_collection>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <km>5</km>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <hash/>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <foo><![CDATA[foo]]></foo>
  <foobar><![CDATA[foobar]]></foobar>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result><![CDATA[foo]]></result>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <c><![CDATA[c]]></c>
  <a><![CDATA[a]]></a>
  <b><![CDATA[b]]></b>
  <d><![CDATA[d]]></d>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<order>
  <cost currency="EUR">1.23</cost>
</order>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <entry>1.34</entry>
  <entry>3</entry>
  <entry>6.42</entry>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<price>3</price>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <km>5</km>
  <type><![CDATA[car]]></type>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<author>
  <id>123</id>
  <full_name><![CDATA[Ruud Kamphuis]]></full_name>
</author>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <foo><![CDATA[foo]]></foo>
  <foobar><![CDATA[foobar]]></foobar>
  <bar><![CDATA[bar]]></bar>
  <none><![CDATA[none]]></none>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<input type="text" name="firstname" value="Adrien"/>
<?xml version="1.0" encoding="UTF-8"?>
<violation property_path="foo">
  <message><![CDATA[Message of violation]]></message>
</violation>
<?xml version="1.0" encoding="UTF-8"?>
<result xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <text><![CDATA[foo]]></text>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <array>
    <key-one><![CDATA[foo]]></key-one>
    <key-two>1</key-two>
    <nested-array>
      <bar><![CDATA[foo]]></bar>
    </nested-array>
    <without-keys>
      <entry>1</entry>
      <entry><![CDATA[test]]></entry>
    </without-keys>
    <mixed>
      <entry><![CDATA[test]]></entry>
      <foo><![CDATA[bar]]></foo>
      <entry><![CDATA[bar]]></entry>
    </mixed>
    <entry><![CDATA[foo]]></entry>
  </array>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result><![CDATA[PT45M]]></result>
<?xml version="1.0" encoding="UTF-8"?>
<result xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <author xsi:nil="true"/>
  <text><![CDATA[foo]]></text>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <val><![CDATA[One]]></val>
  <val><![CDATA[Two]]></val>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <entry><![CDATA[foo]]></entry>
  <entry><![CDATA[bar]]></entry>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result foo="bar"/>
<?xml version="1.0" encoding="UTF-8"?>
<result>
  <map>
    <entry key="key-one"><![CDATA[One]]></entry>
    <entry key="key-two"><![CDATA[Two]]></entry>
  </map>
</result>
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Serializer;

use JMS\Serializer\Context;
use JMS\Serializer\DeserializationContext;
use JMS\Serializer\GraphNavigator;
use JMS\Serializer\Handler\PhpCollectionHandler;
use JMS\Serializer\SerializationContext;
use JMS\Serializer\Tests\Fixtures\Discriminator\Car;
use JMS\Serializer\Tests\Fixtures\Tree;
use PhpCollection\Sequence;
use Symfony\Component\Translation\MessageSelector;
use Symfony\Component\Translation\IdentityTranslator;
use JMS\Serializer\EventDispatcher\Subscriber\DoctrineProxySubscriber;
use JMS\Serializer\Handler\HandlerRegistry;
use JMS\Serializer\EventDispatcher\EventDispatcher;
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Collections\ArrayCollection;
use JMS\Serializer\Metadata\Driver\AnnotationDriver;
use JMS\Serializer\Construction\UnserializeObjectConstructor;
use JMS\Serializer\Handler\ArrayCollectionHandler;
use JMS\Serializer\Handler\ConstraintViolationHandler;
use JMS\Serializer\Handler\DateHandler;
use JMS\Serializer\Handler\FormErrorHandler;
use JMS\Serializer\JsonDeserializationVisitor;
use JMS\Serializer\JsonSerializationVisitor;
use JMS\Serializer\Naming\CamelCaseNamingStrategy;
use JMS\Serializer\Naming\SerializedNameAnnotationStrategy;
use JMS\Serializer\Serializer;
use JMS\Serializer\VisitorInterface;
use JMS\Serializer\XmlDeserializationVisitor;
use JMS\Serializer\XmlSerializationVisitor;
use JMS\Serializer\YamlSerializationVisitor;
use JMS\Serializer\Tests\Fixtures\AccessorOrderChild;
use JMS\Serializer\Tests\Fixtures\AccessorOrderParent;
use JMS\Serializer\Tests\Fixtures\AccessorOrderMethod;
use JMS\Serializer\Tests\Fixtures\Author;
use JMS\Serializer\Tests\Fixtures\AuthorList;
use JMS\Serializer\Tests\Fixtures\AuthorReadOnly;
use JMS\Serializer\Tests\Fixtures\BlogPost;
use JMS\Serializer\Tests\Fixtures\CircularReferenceParent;
use JMS\Serializer\Tests\Fixtures\Comment;
use JMS\Serializer\Tests\Fixtures\CurrencyAwareOrder;
use JMS\Serializer\Tests\Fixtures\CurrencyAwarePrice;
use JMS\Serializer\Tests\Fixtures\CustomDeserializationObject;
use JMS\Serializer\Tests\Fixtures\GetSetObject;
use JMS\Serializer\Tests\Fixtures\GroupsObject;
use JMS\Serializer\Tests\Fixtures\InvalidGroupsObject;
use JMS\Serializer\Tests\Fixtures\IndexedCommentsBlogPost;
use JMS\Serializer\Tests\Fixtures\InlineParent;
use JMS\Serializer\Tests\Fixtures\InitializedObjectConstructor;
use JMS\Serializer\Tests\Fixtures\Log;
use JMS\Serializer\Tests\Fixtures\ObjectWithLifecycleCallbacks;
use JMS\Serializer\Tests\Fixtures\ObjectWithVersionedVirtualProperties;
use JMS\Serializer\Tests\Fixtures\ObjectWithVirtualProperties;
use JMS\Serializer\Tests\Fixtures\Order;
use JMS\Serializer\Tests\Fixtures\Price;
use JMS\Serializer\Tests\Fixtures\SimpleObject;
use JMS\Serializer\Tests\Fixtures\ObjectWithNullProperty;
use JMS\Serializer\Tests\Fixtures\SimpleObjectProxy;
use JMS\Serializer\Tests\Fixtures\Article;
use JMS\Serializer\Tests\Fixtures\Input;
use JMS\Serializer\Tests\Fixtures\ObjectWithEmptyHash;
use Metadata\MetadataFactory;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormError;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
use PhpCollection\Map;
use JMS\Serializer\Exclusion\DepthExclusionStrategy;
use JMS\Serializer\Tests\Fixtures\Node;

abstract class BaseSerializationTest extends \PHPUnit_Framework_TestCase
{
    protected $factory;
    protected $dispatcher;

    /** @var Serializer */
    protected $serializer;
    protected $handlerRegistry;
    protected $serializationVisitors;
    protected $deserializationVisitors;

    public function testSerializeNullArray()
    {
        $arr = array('foo' => 'bar', 'baz' => null, null);

        $this->assertEquals(
            $this->getContent('nullable'),
            $this->serializer->serialize($arr, $this->getFormat(), SerializationContext::create()->setSerializeNull(true))
        );
    }

    public function testSerializeNullObject()
    {
        $obj = new ObjectWithNullProperty('foo', 'bar');

        $this->assertEquals(
            $this->getContent('simple_object_nullable'),
            $this->serializer->serialize($obj, $this->getFormat(), SerializationContext::create()->setSerializeNull(true))
        );
    }

    /**
     * @dataProvider getTypes
     */
    public function testNull($type)
    {
        $this->assertEquals($this->getContent('null'), $this->serialize(null), $type);

        if ($this->hasDeserializer()) {
            $this->assertEquals(null, $this->deserialize($this->getContent('null'), $type));
        }
    }

    public function getTypes()
    {
        return array(
            array('NULL'),
            array('integer'),
            array('double'),
            array('float'),
            array('string'),
            array('DateTime'),
        );
    }

    public function testString()
    {
        $this->assertEquals($this->getContent('string'), $this->serialize('foo'));

        if ($this->hasDeserializer()) {
            $this->assertEquals('foo', $this->deserialize($this->getContent('string'), 'string'));
        }
    }

    /**
     * @dataProvider getBooleans
     */
    public function testBooleans($strBoolean, $boolean)
    {
        $this->assertEquals($this->getContent('boolean_'.$strBoolean), $this->serialize($boolean));

        if ($this->hasDeserializer()) {
            $this->assertSame($boolean, $this->deserialize($this->getContent('boolean_'.$strBoolean), 'boolean'));
        }
    }

    public function getBooleans()
    {
        return array(array('true', true), array('false', false));
    }

    /**
     * @dataProvider getNumerics
     */
    public function testNumerics($key, $value, $type)
    {
        $this->assertEquals($this->getContent($key), $this->serialize($value));

        if ($this->hasDeserializer()) {
            $this->assertEquals($value, $this->deserialize($this->getContent($key), $type));
        }
    }

    public function getNumerics()
    {
        return array(
            array('integer', 1, 'integer'),
            array('float', 4.533, 'double'),
            array('float', 4.533, 'float'),
            array('float_trailing_zero', 1.0, 'double'),
            array('float_trailing_zero', 1.0, 'float'),
        );
    }

    public function testSimpleObject()
    {
        $this->assertEquals($this->getContent('simple_object'), $this->serialize($obj = new SimpleObject('foo', 'bar')));

        if ($this->hasDeserializer()) {
            $this->assertEquals($obj, $this->deserialize($this->getContent('simple_object'), get_class($obj)));
        }
    }

    public function testArrayStrings()
    {
        $data = array('foo', 'bar');
        $this->assertEquals($this->getContent('array_strings'), $this->serialize($data));

        if ($this->hasDeserializer()) {
            $this->assertEquals($data, $this->deserialize($this->getContent('array_strings'), 'array<string>'));
        }
    }

    public function testArrayBooleans()
    {
        $data = array(true, false);
        $this->assertEquals($this->getContent('array_booleans'), $this->serialize($data));

        if ($this->hasDeserializer()) {
            $this->assertEquals($data, $this->deserialize($this->getContent('array_booleans'), 'array<boolean>'));
        }
    }

    public function testArrayIntegers()
    {
        $data = array(1, 3, 4);
        $this->assertEquals($this->getContent('array_integers'), $this->serialize($data));

        if ($this->hasDeserializer()) {
            $this->assertEquals($data, $this->deserialize($this->getContent('array_integers'), 'array<integer>'));
        }
    }

    public function testArrayFloats()
    {
        $data = array(1.34, 3.0, 6.42);
        $this->assertEquals($this->getContent('array_floats'), $this->serialize($data));

        if ($this->hasDeserializer()) {
            $this->assertEquals($data, $this->deserialize($this->getContent('array_floats'), 'array<double>'));
        }
    }

    public function testArrayObjects()
    {
        $data = array(new SimpleObject('foo', 'bar'), new SimpleObject('baz', 'boo'));
        $this->assertEquals($this->getContent('array_objects'), $this->serialize($data));

        if ($this->hasDeserializer()) {
            $this->assertEquals($data, $this->deserialize($this->getContent('array_objects'), 'array<JMS\Serializer\Tests\Fixtures\SimpleObject>'));
        }
    }

    public function testArrayMixed()
    {
        $this->assertEquals($this->getContent('array_mixed'), $this->serialize(array('foo', 1, true, new SimpleObject('foo', 'bar'), array(1, 3, true))));
    }

    /**
     * @dataProvider getDateTime
     * @group datetime
     */
    public function testDateTime($key, $value, $type)
    {
        $this->assertEquals($this->getContent($key), $this->serialize($value));

        if ($this->hasDeserializer()) {
            $deserialized = $this->deserialize($this->getContent($key), $type);

            $this->assertTrue(is_object($deserialized));
            $this->assertEquals(get_class($value), get_class($deserialized));
            $this->assertEquals($value->getTimestamp(), $deserialized->getTimestamp());
        }
    }

    public function getDateTime()
    {
        return array(
            array('date_time', new \DateTime('2011-08-30 00:00', new \DateTimeZone('UTC')), 'DateTime'),
        );
    }

    public function testDateInterval()
    {
        $duration = new \DateInterval('PT45M');

        $this->assertEquals($this->getContent('date_interval'), $this->serializer->serialize($duration, $this->getFormat()));
    }

    public function testBlogPost()
    {
        $post = new BlogPost('This is a nice title.', $author = new Author('Foo Bar'), new \DateTime('2011-07-30 00:00', new \DateTimeZone('UTC')));
        $post->addComment($comment = new Comment($author, 'foo'));

        $this->assertEquals($this->getContent('blog_post'), $this->serialize($post));

        if ($this->hasDeserializer()) {
            $deserialized = $this->deserialize($this->getContent('blog_post'), get_class($post));
            $this->assertEquals('2011-07-30T00:00:00+0000', $this->getField($deserialized, 'createdAt')->format(\DateTime::ISO8601));
            $this->assertAttributeEquals('This is a nice title.', 'title', $deserialized);
            $this->assertAttributeSame(false, 'published', $deserialized);
            $this->assertAttributeEquals(new ArrayCollection(array($comment)), 'comments', $deserialized);
            $this->assertAttributeEquals(new Sequence(array($comment)), 'comments2', $deserialized);
            $this->assertAttributeEquals($author, 'author', $deserialized);
        }
    }

    public function testDeserializingNull()
    {
        $objectConstructor = new InitializedObjectConstructor();
        $this->serializer = new Serializer($this->factory, $this->handlerRegistry, $objectConstructor, $this->serializationVisitors, $this->deserializationVisitors, $this->dispatcher);

        $post = new BlogPost('This is a nice title.', $author = new Author('Foo Bar'), new \DateTime('2011-07-30 00:00', new \DateTimeZone('UTC')));

        $this->setField($post, 'author', null);

        $this->assertEquals($this->getContent('blog_post_unauthored'), $this->serialize($post, SerializationContext::create()->setSerializeNull(true)));

        if ($this->hasDeserializer()) {
            $deserialized = $this->deserialize($this->getContent('blog_post_unauthored'), get_class($post), DeserializationContext::create()->setSerializeNull(true));

            $this->assertEquals('2011-07-30T00:00:00+0000', $this->getField($deserialized, 'createdAt')->format(\DateTime::ISO8601));
            $this->assertAttributeEquals('This is a nice title.', 'title', $deserialized);
            $this->assertAttributeSame(false, 'published', $deserialized);
            $this->assertAttributeEquals(new ArrayCollection(), 'comments', $deserialized);
            $this->assertEquals(null, $this->getField($deserialized, 'author'));
        }
    }

    public function testReadOnly()
    {
        $author = new AuthorReadOnly(123, 'Ruud Kamphuis');
        $this->assertEquals($this->getContent('readonly'), $this->serialize($author));

        if ($this->hasDeserializer()) {
            $deserialized = $this->deserialize($this->getContent('readonly'), get_class($author));
            $this->assertNull($this->getField($deserialized, 'id'));
            $this->assertEquals('Ruud Kamphuis', $this->getField($deserialized, 'name'));
        }
    }

    public function testPrice()
    {
        $price = new Price(3);
        $this->assertEquals($this->getContent('price'), $this->serialize($price));

        if ($this->hasDeserializer()) {
            $deserialized = $this->deserialize($this->getContent('price'), get_class($price));
            $this->assertEquals(3, $this->getField($deserialized, 'price'));
        }
    }

    public function testOrder()
    {
        $order = new Order(new Price(12.34));
        $this->assertEquals($this->getContent('order'), $this->serialize($order));

        if ($this->hasDeserializer()) {
            $this->assertEquals($order, $this->deserialize($this->getContent('order'), get_class($order)));
        }
    }

    public function testCurrencyAwarePrice()
    {
        $price = new CurrencyAwarePrice(2.34);
        $this->assertEquals($this->getContent('currency_aware_price'), $this->serialize($price));

        if ($this->hasDeserializer()) {
            $this->assertEquals($price, $this->deserialize($this->getContent('currency_aware_price'), get_class($price)));
        }
    }

    public function testOrderWithCurrencyAwarePrice()
    {
        $order = new CurrencyAwareOrder(new CurrencyAwarePrice(1.23));
        $this->assertEquals($this->getContent('order_with_currency_aware_price'), $this->serialize($order));

        if ($this->hasDeserializer()) {
            $this->assertEquals($order, $this->deserialize($this->getContent('order_with_currency_aware_price'), get_class($order)));
        }
    }

    /**
     * @group handlerCallback
     */
    public function testArticle()
    {
        $article = new Article();
        $article->element = 'custom';
        $article->value = 'serialized';

        $result = $this->serialize($article);
        $this->assertEquals($this->getContent('article'), $result);

        if ($this->hasDeserializer()) {
            $this->assertEquals($article, $this->deserialize($result, 'JMS\Serializer\Tests\Fixtures\Article'));
        }
    }

    public function testInline()
    {
        $inline = new InlineParent();

        $result = $this->serialize($inline);
        $this->assertEquals($this->getContent('inline'), $result);

        // no deserialization support
    }

    /**
     * @group log
     */
    public function testLog()
    {
        $this->assertEquals($this->getContent('log'), $this->serialize($log = new Log()));

        if ($this->hasDeserializer()) {
            $deserialized = $this->deserialize($this->getContent('log'), get_class($log));
            $this->assertEquals($log, $deserialized);
        }
    }

    public function testCircularReference()
    {
        $object = new CircularReferenceParent();
        $this->assertEquals($this->getContent('circular_reference'), $this->serialize($object));

        if ($this->hasDeserializer()) {
            $deserialized = $this->deserialize($this->getContent('circular_reference'), get_class($object));

            $col = $this->getField($deserialized, 'collection');
            $this->assertEquals(2, count($col));
            $this->assertEquals('child1', $col[0]->getName());
            $this->assertEquals('child2', $col[1]->getName());
            $this->assertSame($deserialized, $col[0]->getParent());
            $this->assertSame($deserialized, $col[1]->getParent());

            $col = $this->getField($deserialized, 'anotherCollection');
            $this->assertEquals(2, count($col));
            $this->assertEquals('child1', $col[0]->getName());
            $this->assertEquals('child2', $col[1]->getName());
            $this->assertSame($deserialized, $col[0]->getParent());
            $this->assertSame($deserialized, $col[1]->getParent());
        }
    }

    public function testLifecycleCallbacks()
    {
        $object = new ObjectWithLifecycleCallbacks();
        $this->assertEquals($this->getContent('lifecycle_callbacks'), $this->serialize($object));
        $this->assertAttributeSame(null, 'name', $object);

        if ($this->hasDeserializer()) {
            $deserialized = $this->deserialize($this->getContent('lifecycle_callbacks'), get_class($object));
            $this->assertEquals($object, $deserialized);
        }
    }

    public function testFormErrors()
    {
        $errors = array(
            new FormError('This is the form error'),
            new FormError('Another error')
        );

        $this->assertEquals($this->getContent('form_errors'), $this->serialize($errors));
    }

    public function testNestedFormErrors()
    {
        $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');

        $formConfigBuilder = new \Symfony\Component\Form\FormConfigBuilder('foo', null, $dispatcher);
        $formConfigBuilder->setCompound(true);
        $formConfigBuilder->setDataMapper($this->getMock('Symfony\Component\Form\DataMapperInterface'));
        $fooConfig = $formConfigBuilder->getFormConfig();

        $form = new Form($fooConfig);
        $form->addError(new FormError('This is the form error'));

        $formConfigBuilder = new \Symfony\Component\Form\FormConfigBuilder('bar', null, $dispatcher);
        $barConfig = $formConfigBuilder->getFormConfig();
        $child = new Form($barConfig);
        $child->addError(new FormError('Error of the child form'));
        $form->add($child);

        $this->assertEquals($this->getContent('nested_form_errors'), $this->serialize($form));
    }

    public function testConstraintViolation()
    {
        $violation = new ConstraintViolation('Message of violation', array(), null, 'foo', null);

        $this->assertEquals($this->getContent('constraint_violation'), $this->serialize($violation));
    }

    public function testConstraintViolationList()
    {
        $violations = new ConstraintViolationList();
        $violations->add(new ConstraintViolation('Message of violation', array(), null, 'foo', null));
        $violations->add(new ConstraintViolation('Message of another violation', array(), null, 'bar', null));

        $this->assertEquals($this->getContent('constraint_violation_list'), $this->serialize($violations));
    }

    public function testDoctrineProxy()
    {
        if (!class_exists('Doctrine\ORM\Version')) {
            $this->markTestSkipped('Doctrine is not available.');
        }

        $object = new SimpleObjectProxy('foo', 'bar');

        $this->assertEquals($this->getContent('orm_proxy'), $this->serialize($object));
    }

    public function testInitializedDoctrineProxy()
    {
        if (!class_exists('Doctrine\ORM\Version')) {
            $this->markTestSkipped('Doctrine is not available.');
        }

        $object = new SimpleObjectProxy('foo', 'bar');
        $object->__load();

        $this->assertEquals($this->getContent('orm_proxy'), $this->serialize($object));
    }

    public function testCustomAccessor()
    {
        $post = new IndexedCommentsBlogPost();

        $this->assertEquals($this->getContent('custom_accessor'), $this->serialize($post));
    }

    public function testMixedAccessTypes()
    {
        $object = new GetSetObject();

        $this->assertEquals($this->getContent('mixed_access_types'), $this->serialize($object));

        if ($this->hasDeserializer()) {
            $object = $this->deserialize($this->getContent('mixed_access_types'), 'JMS\Serializer\Tests\Fixtures\GetSetObject');
            $this->assertAttributeEquals(1, 'id', $object);
            $this->assertAttributeEquals('Johannes', 'name', $object);
            $this->assertAttributeEquals(42, 'readOnlyProperty', $object);
        }
    }

    public function testAccessorOrder()
    {
        $this->assertEquals($this->getContent('accessor_order_child'), $this->serialize(new AccessorOrderChild()));
        $this->assertEquals($this->getContent('accessor_order_parent'), $this->serialize(new AccessorOrderParent()));
        $this->assertEquals($this->getContent('accessor_order_methods'), $this->serialize(new AccessorOrderMethod()));
    }

    public function testGroups()
    {
        $groupsObject = new GroupsObject();

        $this->assertEquals($this->getContent('groups_all'), $this->serializer->serialize($groupsObject, $this->getFormat()));

        $this->assertEquals(
            $this->getContent('groups_foo'),
            $this->serializer->serialize($groupsObject, $this->getFormat(), SerializationContext::create()->setGroups(array('foo')))
        );

        $this->assertEquals(
            $this->getContent('groups_foobar'),
            $this->serializer->serialize($groupsObject, $this->getFormat(), SerializationContext::create()->setGroups(array('foo', 'bar')))
        );

        $this->assertEquals(
            $this->getContent('groups_all'),
            $this->serializer->serialize($groupsObject, $this->getFormat())
        );

        $this->assertEquals(
            $this->getContent('groups_default'),
            $this->serializer->serialize($groupsObject, $this->getFormat(), SerializationContext::create()->setGroups(array('Default')))
        );
    }

    /**
     * @expectedException JMS\Serializer\Exception\InvalidArgumentException
     * @expectedExceptionMessage Invalid group name "foo, bar" on "JMS\Serializer\Tests\Fixtures\InvalidGroupsObject->foo", did you mean to create multiple groups?
     */
    public function testInvalidGroupName()
    {
        $groupsObject = new InvalidGroupsObject();

        $this->serializer->serialize($groupsObject, $this->getFormat());
    }

    public function testVirtualProperty()
    {
        $this->assertEquals($this->getContent('virtual_properties'), $this->serialize(new ObjectWithVirtualProperties()));
    }

    public function testVirtualVersions()
    {
        $this->assertEquals(
            $this->getContent('virtual_properties_low'),
            $this->serialize(new ObjectWithVersionedVirtualProperties(), SerializationContext::create()->setVersion(2))
        );

        $this->assertEquals(
            $this->getContent('virtual_properties_all'),
            $this->serialize(new ObjectWithVersionedVirtualProperties(), SerializationContext::create()->setVersion(7))
        );

        $this->assertEquals(
            $this->getContent('virtual_properties_high'),
            $this->serialize(new ObjectWithVersionedVirtualProperties(), SerializationContext::create()->setVersion(9))
        );
    }

    public function testCustomHandler()
    {
        if ( ! $this->hasDeserializer()) {
            return;
        }

        $handler = function() {
            return new CustomDeserializationObject('customly_unserialized_value');
        };

        $this->handlerRegistry->registerHandler(GraphNavigator::DIRECTION_DESERIALIZATION, 'CustomDeserializationObject', $this->getFormat(), $handler);

        $serialized = $this->serializer->serialize(new CustomDeserializationObject('sometext'), $this->getFormat());
        $object = $this->serializer->deserialize($serialized, 'CustomDeserializationObject', $this->getFormat());
        $this->assertEquals('customly_unserialized_value', $object->someProperty);
    }

    public function testInput()
    {
        $this->assertEquals($this->getContent('input'), $this->serializer->serialize(new Input(), $this->getFormat()));
    }

    public function testObjectWithEmptyHash()
    {
        $this->assertEquals($this->getContent('hash_empty'), $this->serializer->serialize(new ObjectWithEmptyHash(), $this->getFormat()));
    }

    /**
     * @group null
     */
    public function testSerializeObjectWhenNull()
    {
        $this->assertEquals(
            $this->getContent('object_when_null'),
            $this->serialize(new Comment(null, 'foo'), SerializationContext::create()->setSerializeNull(false))
        );

        $this->assertEquals(
            $this->getContent('object_when_null_and_serialized'),
            $this->serialize(new Comment(null, 'foo'), SerializationContext::create()->setSerializeNull(true))
        );
    }

    /**
     * @group polymorphic
     */
    public function testPolymorphicObjects()
    {
        $this->assertEquals(
            $this->getContent('car'),
            $this->serialize(new Car(5))
        );

        if ($this->hasDeserializer()) {
            $this->assertEquals(
                new Car(5),
                $this->deserialize(
                    $this->getContent('car'),
                    'JMS\Serializer\Tests\Fixtures\Discriminator\Car'
                ),
                'Class is resolved correctly when concrete sub-class is used.'
            );

            $this->assertEquals(
                new Car(5),
                $this->deserialize(
                    $this->getContent('car'),
                    'JMS\Serializer\Tests\Fixtures\Discriminator\Vehicle'
                ),
                'Class is resolved correctly when least supertype is used.'
            );

            $this->assertEquals(
                new Car(5),
                $this->deserialize(
                    $this->getContent('car_without_type'),
                    'JMS\Serializer\Tests\Fixtures\Discriminator\Car'
                ),
                'Class is resolved correctly when concrete sub-class is used and no type is defined.'
            );
        }
    }

    /**
     * @group polymorphic
     * @expectedException LogicException
     */
    public function testPolymorphicObjectsInvalidDeserialization()
    {
        if (!$this->hasDeserializer()) {
            throw new \LogicException('No deserializer');
        }

        $this->deserialize(
            $this->getContent('car_without_type'),
            'JMS\Serializer\Tests\Fixtures\Discriminator\Vehicle'
        );
    }

    public function testDepthExclusionStrategy()
    {
        $context = SerializationContext::create()
            ->addExclusionStrategy(new DepthExclusionStrategy())
        ;

        $data = new Tree(
            new Node(array(
                new Node(array(
                    new Node(array(
                        new Node(array(
                            new Node(),
                        )),
                    )),
                )),
            ))
        );

        $this->assertEquals($this->getContent('tree'), $this->serializer->serialize($data, $this->getFormat(), $context));
    }

    abstract protected function getContent($key);
    abstract protected function getFormat();

    protected function hasDeserializer()
    {
        return true;
    }

    protected function serialize($data, Context $context = null)
    {
        return $this->serializer->serialize($data, $this->getFormat(), $context);
    }

    protected function deserialize($content, $type, Context $context = null)
    {
        return $this->serializer->deserialize($content, $type, $this->getFormat(), $context);
    }

    protected function setUp()
    {
        $this->factory = new MetadataFactory(new AnnotationDriver(new AnnotationReader()));

        $this->handlerRegistry = new HandlerRegistry();
        $this->handlerRegistry->registerSubscribingHandler(new ConstraintViolationHandler());
        $this->handlerRegistry->registerSubscribingHandler(new DateHandler());
        $this->handlerRegistry->registerSubscribingHandler(new FormErrorHandler(new IdentityTranslator(new MessageSelector())));
        $this->handlerRegistry->registerSubscribingHandler(new PhpCollectionHandler());
        $this->handlerRegistry->registerSubscribingHandler(new ArrayCollectionHandler());
        $this->handlerRegistry->registerHandler(GraphNavigator::DIRECTION_SERIALIZATION, 'AuthorList', $this->getFormat(),
            function(VisitorInterface $visitor, $object, array $type, Context $context) {
                return $visitor->visitArray(iterator_to_array($object), $type, $context);
            }
        );
        $this->handlerRegistry->registerHandler(GraphNavigator::DIRECTION_DESERIALIZATION, 'AuthorList', $this->getFormat(),
            function(VisitorInterface $visitor, $data, $type, Context $context) {
                $type = array(
                    'name' => 'array',
                    'params' => array(
                        array('name' => 'integer', 'params' => array()),
                        array('name' => 'JMS\Serializer\Tests\Fixtures\Author', 'params' => array()),
                    ),
                );

                $elements = $visitor->getNavigator()->accept($data, $type, $context);
                $list = new AuthorList();
                foreach ($elements as $author) {
                    $list->add($author);
                }

                return $list;
            }
        );

        $this->dispatcher = new EventDispatcher();
        $this->dispatcher->addSubscriber(new DoctrineProxySubscriber());

        $namingStrategy = new SerializedNameAnnotationStrategy(new CamelCaseNamingStrategy());
        $objectConstructor = new UnserializeObjectConstructor();
        $this->serializationVisitors = new Map(array(
            'json' => new JsonSerializationVisitor($namingStrategy),
            'xml'  => new XmlSerializationVisitor($namingStrategy),
            'yml'  => new YamlSerializationVisitor($namingStrategy),
        ));
        $this->deserializationVisitors = new Map(array(
            'json' => new JsonDeserializationVisitor($namingStrategy),
            'xml'  => new XmlDeserializationVisitor($namingStrategy),
        ));

        $this->serializer = new Serializer($this->factory, $this->handlerRegistry, $objectConstructor, $this->serializationVisitors, $this->deserializationVisitors, $this->dispatcher);
    }

    private function getField($obj, $name)
    {
        $ref = new \ReflectionProperty($obj, $name);
        $ref->setAccessible(true);

        return $ref->getValue($obj);
    }

    private function setField($obj, $name, $value)
    {
        $ref = new \ReflectionProperty($obj, $name);
        $ref->setAccessible(true);
        $ref->setValue($obj, $value);
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Serializer;

use JMS\Serializer\Construction\UnserializeObjectConstructor;
use JMS\Serializer\Handler\HandlerRegistry;
use JMS\Serializer\EventDispatcher\EventDispatcher;
use Doctrine\Common\Annotations\AnnotationReader;
use JMS\Serializer\Metadata\Driver\AnnotationDriver;
use JMS\Serializer\GraphNavigator;
use Metadata\MetadataFactory;

class GraphNavigatorTest extends \PHPUnit_Framework_TestCase
{
    private $metadataFactory;
    private $handlerRegistry;
    private $objectConstructor;
    private $dispatcher;
    private $navigator;
    private $context;

    /**
     * @expectedException JMS\Serializer\Exception\RuntimeException
     * @expectedExceptionMessage Resources are not supported in serialized data.
     */
    public function testResourceThrowsException()
    {
        $this->context->expects($this->any())
            ->method('getDirection')
            ->will($this->returnValue(GraphNavigator::DIRECTION_SERIALIZATION));

        $this->navigator->accept(STDIN, null, $this->context);
    }

    public function testNavigatorPassesInstanceOnSerialization()
    {
        $object = new SerializableClass;
        $metadata = $this->metadataFactory->getMetadataForClass(get_class($object));

        $self = $this;
        $context = $this->context;
        $exclusionStrategy = $this->getMock('JMS\Serializer\Exclusion\ExclusionStrategyInterface');
        $exclusionStrategy->expects($this->once())
            ->method('shouldSkipClass')
            ->will($this->returnCallback(function($passedMetadata, $passedContext) use ($metadata, $context, $self) {
                $self->assertSame($metadata, $passedMetadata);
                $self->assertSame($context, $passedContext);
            }));
        $exclusionStrategy->expects($this->once())
            ->method('shouldSkipProperty')
            ->will($this->returnCallback(function($propertyMetadata, $passedContext) use ($context, $metadata, $self) {
                $self->assertSame($metadata->propertyMetadata['foo'], $propertyMetadata);
                $self->assertSame($context, $passedContext);
            }));

        $this->context->expects($this->once())
            ->method('getExclusionStrategy')
            ->will($this->returnValue($exclusionStrategy));

        $this->context->expects($this->any())
            ->method('getDirection')
            ->will($this->returnValue(GraphNavigator::DIRECTION_SERIALIZATION));

        $this->context->expects($this->any())
            ->method('getVisitor')
            ->will($this->returnValue($this->getMock('JMS\Serializer\VisitorInterface')));

        $this->navigator = new GraphNavigator($this->metadataFactory, $this->handlerRegistry, $this->objectConstructor, $this->dispatcher);
        $this->navigator->accept($object, null, $this->context);
    }

    public function testNavigatorPassesNullOnDeserialization()
    {
        $class = __NAMESPACE__.'\SerializableClass';
        $metadata = $this->metadataFactory->getMetadataForClass($class);

        $context = $this->context;
        $exclusionStrategy = $this->getMock('JMS\Serializer\Exclusion\ExclusionStrategyInterface');
        $exclusionStrategy->expects($this->once())
            ->method('shouldSkipClass')
            ->with($metadata, $this->callback(function ($navigatorContext) use ($context) {
                return $navigatorContext === $context;
            }));

        $exclusionStrategy->expects($this->once())
            ->method('shouldSkipProperty')
            ->with($metadata->propertyMetadata['foo'], $this->callback(function ($navigatorContext) use ($context) {
                return $navigatorContext === $context;
            }));

        $this->context->expects($this->once())
            ->method('getExclusionStrategy')
            ->will($this->returnValue($exclusionStrategy));

        $this->context->expects($this->any())
            ->method('getDirection')
            ->will($this->returnValue(GraphNavigator::DIRECTION_DESERIALIZATION));

        $this->context->expects($this->any())
            ->method('getVisitor')
            ->will($this->returnValue($this->getMock('JMS\Serializer\VisitorInterface')));

        $this->navigator = new GraphNavigator($this->metadataFactory, $this->handlerRegistry, $this->objectConstructor, $this->dispatcher);
        $this->navigator->accept('random', array('name' => $class, 'params' => array()), $this->context);
    }

    public function testNavigatorChangeTypeOnSerialization()
    {
        $object = new SerializableClass;
        $typeName = 'JsonSerializable';

        $this->dispatcher->addListener('serializer.pre_serialize', function($event) use ($typeName) {
            $type = $event->getType();
            $type['name'] = $typeName;
            $event->setType($type['name'], $type['params']);
        });

        $subscribingHandlerClass = $this->getMockClass('JMS\Serializer\Handler\SubscribingHandlerInterface', array('getSubscribingMethods', 'serialize'));
        $subscribingHandlerClass::staticExpects($this->once())
            ->method('getSubscribingMethods')
            ->will($this->returnValue(array(array(
                'type' => $typeName,
                'format' => 'foo',
                'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
                'method' => 'serialize'
            ))));

        $subscribingHandler = new $subscribingHandlerClass();
        $subscribingHandler->expects($this->once())
            ->method('serialize')
            ->with($this->equalTo($this->context), $this->equalTo($object));

        $this->handlerRegistry->registerSubscribingHandler($subscribingHandler);

        $this->context->expects($this->any())
            ->method('getDirection')
            ->will($this->returnValue(GraphNavigator::DIRECTION_SERIALIZATION));

        $this->context->expects($this->any())
            ->method('getVisitor')
            ->will($this->returnValue($this->getMock('JMS\Serializer\VisitorInterface')));

        $this->navigator = new GraphNavigator($this->metadataFactory, $this->handlerRegistry, $this->objectConstructor, $this->dispatcher);
        $this->navigator->accept($object, null, $this->context);
    }

    protected function setUp()
    {
        $this->context = $this->getMock('JMS\Serializer\Context');
        $this->dispatcher = new EventDispatcher();
        $this->handlerRegistry = new HandlerRegistry();
        $this->objectConstructor = new UnserializeObjectConstructor();

        $this->metadataFactory = new MetadataFactory(new AnnotationDriver(new AnnotationReader()));
        $this->navigator = new GraphNavigator($this->metadataFactory, $this->handlerRegistry, $this->objectConstructor, $this->dispatcher);
    }
}

class SerializableClass
{
    public $foo = 'bar';
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Serializer;

use JMS\Serializer\Context;
use JMS\Serializer\Exception\RuntimeException;
use JMS\Serializer\EventDispatcher\Event;
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\GraphNavigator;
use JMS\Serializer\VisitorInterface;
use JMS\Serializer\Tests\Fixtures\Author;
use JMS\Serializer\Tests\Fixtures\AuthorList;

class JsonSerializationTest extends BaseSerializationTest
{
    protected function getContent($key)
    {
        static $outputs = array();

        if (!$outputs) {
            $outputs['readonly'] = '{"id":123,"full_name":"Ruud Kamphuis"}';
            $outputs['string'] = '"foo"';
            $outputs['boolean_true'] = 'true';
            $outputs['boolean_false'] = 'false';
            $outputs['integer'] = '1';
            $outputs['float'] = '4.533';
            $outputs['float_trailing_zero'] = '1';
            $outputs['simple_object'] = '{"foo":"foo","moo":"bar","camel_case":"boo"}';
            $outputs['circular_reference'] = '{"collection":[{"name":"child1"},{"name":"child2"}],"another_collection":[{"name":"child1"},{"name":"child2"}]}';
            $outputs['array_strings'] = '["foo","bar"]';
            $outputs['array_booleans'] = '[true,false]';
            $outputs['array_integers'] = '[1,3,4]';
            $outputs['array_floats'] = '[1.34,3,6.42]';
            $outputs['array_objects'] = '[{"foo":"foo","moo":"bar","camel_case":"boo"},{"foo":"baz","moo":"boo","camel_case":"boo"}]';
            $outputs['array_mixed'] = '["foo",1,true,{"foo":"foo","moo":"bar","camel_case":"boo"},[1,3,true]]';
            $outputs['blog_post'] = '{"title":"This is a nice title.","created_at":"2011-07-30T00:00:00+0000","is_published":false,"comments":[{"author":{"full_name":"Foo Bar"},"text":"foo"}],"comments2":[{"author":{"full_name":"Foo Bar"},"text":"foo"}],"metadata":{"foo":"bar"},"author":{"full_name":"Foo Bar"}}';
            $outputs['blog_post_unauthored'] = '{"title":"This is a nice title.","created_at":"2011-07-30T00:00:00+0000","is_published":false,"comments":[],"comments2":[],"metadata":{"foo":"bar"},"author":null}';
            $outputs['price'] = '{"price":3}';
            $outputs['currency_aware_price'] = '{"currency":"EUR","amount":2.34}';
            $outputs['order'] = '{"cost":{"price":12.34}}';
            $outputs['order_with_currency_aware_price'] = '{"cost":{"currency":"EUR","amount":1.23}}';
            $outputs['log'] = '{"author_list":[{"full_name":"Johannes Schmitt"},{"full_name":"John Doe"}],"comments":[{"author":{"full_name":"Foo Bar"},"text":"foo"},{"author":{"full_name":"Foo Bar"},"text":"bar"},{"author":{"full_name":"Foo Bar"},"text":"baz"}]}';
            $outputs['lifecycle_callbacks'] = '{"name":"Foo Bar"}';
            $outputs['form_errors'] = '["This is the form error","Another error"]';
            $outputs['nested_form_errors'] = '{"errors":["This is the form error"],"children":{"bar":{"errors":["Error of the child form"]}}}';
            $outputs['constraint_violation'] = '{"property_path":"foo","message":"Message of violation"}';
            $outputs['constraint_violation_list'] = '[{"property_path":"foo","message":"Message of violation"},{"property_path":"bar","message":"Message of another violation"}]';
            $outputs['article'] = '{"custom":"serialized"}';
            $outputs['orm_proxy'] = '{"foo":"foo","moo":"bar","camel_case":"proxy-boo"}';
            $outputs['custom_accessor'] = '{"comments":{"Foo":{"comments":[{"author":{"full_name":"Foo"},"text":"foo"},{"author":{"full_name":"Foo"},"text":"bar"}],"count":2}}}';
            $outputs['mixed_access_types'] = '{"id":1,"name":"Johannes","read_only_property":42}';
            $outputs['accessor_order_child'] = '{"c":"c","d":"d","a":"a","b":"b"}';
            $outputs['accessor_order_parent'] = '{"a":"a","b":"b"}';
            $outputs['accessor_order_methods'] = '{"foo":"c","b":"b","a":"a"}';
            $outputs['inline'] = '{"c":"c","a":"a","b":"b","d":"d"}';
            $outputs['groups_all'] = '{"foo":"foo","foobar":"foobar","bar":"bar","none":"none"}';
            $outputs['groups_foo'] = '{"foo":"foo","foobar":"foobar"}';
            $outputs['groups_foobar'] = '{"foo":"foo","foobar":"foobar","bar":"bar"}';
            $outputs['groups_default'] = '{"bar":"bar","none":"none"}';
            $outputs['virtual_properties'] = '{"exist_field":"value","test":"other-name","virtual_value":"value","typed_virtual_property":1}';
            $outputs['virtual_properties_low'] = '{"low":1}';
            $outputs['virtual_properties_high'] = '{"high":8}';
            $outputs['virtual_properties_all'] = '{"low":1,"high":8}';
            $outputs['nullable'] = '{"foo":"bar","baz":null}';
            $outputs['null'] = 'null';
            $outputs['simple_object_nullable'] = '{"foo":"foo","moo":"bar","camel_case":"boo","null_property":null}';
            $outputs['input'] = '{"attributes":{"type":"text","name":"firstname","value":"Adrien"}}';
            $outputs['hash_empty'] = '{"hash":{}}';
            $outputs['object_when_null'] = '{"text":"foo"}';
            $outputs['object_when_null_and_serialized'] = '{"author":null,"text":"foo"}';
            $outputs['date_time'] = '"2011-08-30T00:00:00+0000"';
            $outputs['date_interval'] = '"PT45M"';
            $outputs['car'] = '{"km":5,"type":"car"}';
            $outputs['car_without_type'] = '{"km":5}';
            $outputs['tree'] = '{"tree":{"children":[{"children":[{"children":[],"foo":"bar"}],"foo":"bar"}],"foo":"bar"}}';
        }

        if (!isset($outputs[$key])) {
            throw new RuntimeException(sprintf('The key "%s" is not supported.', $key));
        }

        return $outputs[$key];
    }

    public function testAddLinksToOutput()
    {
        $this->dispatcher->addSubscriber(new LinkAddingSubscriber());
        $this->handlerRegistry->registerHandler(GraphNavigator::DIRECTION_SERIALIZATION, 'JMS\Serializer\Tests\Fixtures\AuthorList', 'json',
            function(VisitorInterface $visitor, AuthorList $data, array $type, Context $context) {
                return $visitor->visitArray(iterator_to_array($data), $type, $context);
            }
        );

        $list = new AuthorList();
        $list->add(new Author('foo'));
        $list->add(new Author('bar'));

        $this->assertEquals('[{"full_name":"foo","_links":{"details":"http:\/\/foo.bar\/details\/foo","comments":"http:\/\/foo.bar\/details\/foo\/comments"}},{"full_name":"bar","_links":{"details":"http:\/\/foo.bar\/details\/bar","comments":"http:\/\/foo.bar\/details\/bar\/comments"}}]', $this->serialize($list));
    }

    public function getPrimitiveTypes()
    {
        return array(
            array(
                'type' => 'boolean',
                'data' => true,
            ),
            array(
                'type' => 'boolean',
                'data' => 1,
            ),
            array(
                'type' => 'integer',
                'data' => 123,
            ),
            array(
                'type' => 'integer',
                'data' => "123",
            ),
            array(
                'type' => 'string',
                'data' => "hello",
            ),
            array(
                'type' => 'string',
                'data' => 123,
            ),
            array(
                'type' => 'double',
                'data' => 0.1234,
            ),
            array(
                'type' => 'double',
                'data' => "0.1234",
            ),
        );
    }

    /**
     * @dataProvider getPrimitiveTypes
     */
    public function testPrimitiveTypes($primitiveType, $data)
    {
        $visitor = $this->serializationVisitors->get('json')->get();
        $functionToCall = 'visit' . ucfirst($primitiveType);
        $result = $visitor->$functionToCall($data, array(), $this->getMock('JMS\Serializer\Context'));
        if ($primitiveType == 'double') {
            $primitiveType = 'float';
        }
        $this->assertInternalType($primitiveType, $result);
    }

    /**
     * @group empty-object
     */
    public function testSerializeEmptyObject()
    {
        $this->assertEquals('{}', $this->serialize(new Author(null)));
    }

    protected function getFormat()
    {
        return 'json';
    }
}

class LinkAddingSubscriber implements EventSubscriberInterface
{
    public function onPostSerialize(Event $event)
    {
        $author = $event->getObject();

        $event->getVisitor()->addData('_links', array(
            'details' => 'http://foo.bar/details/'.$author->getName(),
            'comments' => 'http://foo.bar/details/'.$author->getName().'/comments',
        ));
    }

    public static function getSubscribedEvents()
    {
        return array(
            array('event' => 'serializer.post_serialize', 'method' => 'onPostSerialize', 'format' => 'json', 'class' => 'JMS\Serializer\Tests\Fixtures\Author'),
        );
    }
}
<?php

/*
 * Copyright 2013 Johannes M. Schmitt <schmittjoh@gmail.com>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace JMS\Serializer\Tests\Serializer;

use JMS\Serializer\Context;
use JMS\Serializer\Metadata\ClassMetadata;
use JMS\Serializer\Metadata\PropertyMetadata;
use JMS\Serializer\SerializationContext;
use JMS\Serializer\Tests\Fixtures\InlineChild;
use JMS\Serializer\Tests\Fixtures\Node;
use JMS\Serializer\SerializerBuilder;

class ContextTest extends \PHPUnit_Framework_TestCase
{
    public function testSerializationContextPathAndDepth()
    {
        $object = new Node(array(
            new Node(),
            new Node(array(
                new Node()
            )),
        ));
        $objects = array($object, $object->children[0], $object->children[1], $object->children[1]->children[0]);

        $self = $this;

        $exclusionStrategy = $this->getMock('JMS\Serializer\Exclusion\ExclusionStrategyInterface');
        $exclusionStrategy->expects($this->any())
            ->method('shouldSkipClass')
            ->with($this->anything(), $this->callback(function (SerializationContext $context) use ($self, $objects) {
                $expectedDepth = $expectedPath = null;

                if ($context->getObject() === $objects[0]) {
                    $expectedDepth = 1;
                    $expectedPath = 'JMS\Serializer\Tests\Fixtures\Node';
                } elseif ($context->getObject() === $objects[1]) {
                    $expectedDepth = 2;
                    $expectedPath = 'JMS\Serializer\Tests\Fixtures\Node -> JMS\Serializer\Tests\Fixtures\Node';
                } elseif ($context->getObject() === $objects[2]) {
                    $expectedDepth = 2;
                    $expectedPath = 'JMS\Serializer\Tests\Fixtures\Node -> JMS\Serializer\Tests\Fixtures\Node';
                } elseif ($context->getObject() === $objects[3]) {
                    $expectedDepth = 3;
                    $expectedPath = 'JMS\Serializer\Tests\Fixtures\Node -> JMS\Serializer\Tests\Fixtures\Node -> JMS\Serializer\Tests\Fixtures\Node';
                }

                $self->assertEquals($expectedDepth, $context->getDepth(), 'shouldSkipClass depth');
                $self->assertEquals($expectedPath, $context->getPath(), 'shouldSkipClass path');

                return true;
            }))
            ->will($this->returnValue(false));

        $exclusionStrategy->expects($this->any())
            ->method('shouldSkipProperty')
            ->with($this->anything(), $this->callback(function (SerializationContext $context) use ($self, $objects) {
                $expectedDepth = $expectedPath = null;

                if ($context->getObject() === $objects[0]) {
                    $expectedDepth = 1;
                    $expectedPath = 'JMS\Serializer\Tests\Fixtures\Node';
                } elseif ($context->getObject() === $objects[1]) {
                    $expectedDepth = 2;
                    $expectedPath = 'JMS\Serializer\Tests\Fixtures\Node -> JMS\Serializer\Tests\Fixtures\Node';
                } elseif ($context->getObject() === $objects[2]) {
                    $expectedDepth = 2;
                    $expectedPath = 'JMS\Serializer\Tests\Fixtures\Node -> JMS\Serializer\Tests\Fixtures\Node';
                } elseif ($context->getObject() === $objects[3]) {
                    $expectedDepth = 3;
                    $expectedPath = 'JMS\Serializer\Tests\Fixtures\Node -> JMS\Serializer\Tests\Fixtures\Node -> JMS\Serializer\Tests\Fixtures\Node';
                }

                $self->assertEquals($expectedDepth, $context->getDepth(), 'shouldSkipProperty depth');
                $self->assertEquals($expectedPath, $context->getPath(), 'shouldSkipProperty path');

                return true;
            }))
            ->will($this->returnValue(false));

        $serializer = SerializerBuilder::create()->build();

        $serializer->serialize($object, 'json', SerializationContext::create()->addExclusionStrategy($exclusionStrategy));
    }

    public function testSerializationMetadataStack()
    {
        $object = new Node(array(
            $child = new InlineChild(),
        ));
        $self = $this;

        $exclusionStrategy = $this->getMock('JMS\Serializer\Exclusion\ExclusionStrategyInterface');
        $exclusionStrategy->expects($this->any())
            ->method('shouldSkipClass')
            ->will($this->returnCallback(function (ClassMetadata $classMetadata, SerializationContext $context) use ($self, $object, $child) {
                $stack = $context->getMetadataStack();

                if ($object === $context->getObject()) {
                    $self->assertEquals(0, $stack->count());
                }

                if ($child === $context->getObject()) {
                    $self->assertEquals(2, $stack->count());
                    $self->assertEquals('JMS\Serializer\Tests\Fixtures\Node', $stack[1]->name);
                    $self->assertEquals('children', $stack[0]->name);
                }

                return false;
            }));

        $exclusionStrategy->expects($this->any())
            ->method('shouldSkipProperty')
            ->will($this->returnCallback(function (PropertyMetadata $propertyMetadata, SerializationContext $context) use ($self, $object, $child) {
                $stack = $context->getMetadataStack();

                if ('JMS\Serializer\Tests\Fixtures\Node' === $propertyMetadata->class && $propertyMetadata->name === 'children') {
                    $self->assertEquals(1, $stack->count());
                    $self->assertEquals('JMS\Serializer\Tests\Fixtures\Node', $stack[0]->name);
                }

                if ('JMS\Serializer\Tests\Fixtures\InlineChild' === $propertyMetadata->class) {
                    $self->assertEquals(3, $stack->count());
                    $self->assertEquals('JMS\Serializer\Tests\Fixtures\Node', $stack[2]->name);
                    $self->assertEquals('children', $stack[1]->name);
                    $self->assertEquals('JMS\Serializer\Tests\Fixtures\InlineChild', $stack[0]->name);
                }

                return false;
            }));

        $serializer = SerializerBuilder::create()->build();
        $serializer->serialize($object, 'json', SerializationContext::create()->addExclusionStrategy($exclusionStrategy));
    }
}
<?php

if ( ! isset($_SERVER['argv'][1], $_SERVER['argv'][2])) {
    echo 'Usage: php benchmark.php <format> <iterations> [output-file]'.PHP_EOL;
    exit(1);
}

list(, $format, $iterations) = $_SERVER['argv'];

require_once 'bootstrap.php';

function benchmark(\Closure $f, $times = 10) {
    $time = microtime(true);
    for ($i=0; $i<$times; $i++) {
        $f();
    }

    return (microtime(true) - $time) / $times;
}

function createCollection() {
    $collection = array();
    for ($i=0; $i<50; $i++) {
        $collection[] = createObject();
    }

    return $collection;
}

function createObject() {
    $post = new \JMS\Serializer\Tests\Fixtures\BlogPost('FooooooooooooooooooooooBAR', new \JMS\Serializer\Tests\Fixtures\Author('Foo'), new \DateTime);
    for ($i=0; $i<10; $i++) {
        $post->addComment(new \JMS\Serializer\Tests\Fixtures\Comment(new \JMS\Serializer\Tests\Fixtures\Author('foo'), 'foobar'));
    }

    return $post;
}



$serializer = \JMS\Serializer\SerializerBuilder::create()->build();
$collection = createCollection();
$metrics = array();
$f = function() use ($serializer, $collection, $format) {
    $serializer->serialize($collection, $format);
};


// Load all necessary classes into memory.
benchmark($f, 1);

printf('Benchmarking collection for format "%s".'.PHP_EOL, $format);
$metrics['benchmark-collection-'.$format] = benchmark($f, $iterations);

$output = json_encode(array('metrics' => $metrics));

if (isset($_SERVER['argv'][3])) {
    file_put_contents($_SERVER['argv'][3], $output);
    echo "Done.".PHP_EOL;
} else {
    echo $output.PHP_EOL;
}
<?php

/*
 * Copyright 2011 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use Doctrine\Common\Annotations\AnnotationRegistry;

call_user_func(function() {
    if ( ! is_file($autoloadFile = __DIR__.'/../vendor/autoload.php')) {
        throw new \RuntimeException('Did not find vendor/autoload.php. Did you run "composer install --dev"?');
    }

    $loader = require $autoloadFile;
    $loader->add('JMS\Serializer\Tests', __DIR__);

    AnnotationRegistry::registerLoader('class_exists');
});
{
    "hash": "064fb78d8b7dfa1ee7477308d1c6f2dd",
    "packages": [
        {
            "name": "doctrine/annotations",
            "version": "v1.1.1",
            "source": {
                "type": "git",
                "url": "https://github.com/doctrine/annotations.git",
                "reference": "v1.1.1"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/doctrine/annotations/zipball/v1.1.1",
                "reference": "v1.1.1",
                "shasum": ""
            },
            "require": {
                "doctrine/lexer": "1.*",
                "php": ">=5.3.2"
            },
            "require-dev": {
                "doctrine/cache": "1.*"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.0.x-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Doctrine\\Common\\Annotations\\": "lib/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Jonathan Wage",
                    "email": "jonwage@gmail.com",
                    "homepage": "http://www.jwage.com/"
                },
                {
                    "name": "Guilherme Blanco",
                    "email": "guilhermeblanco@gmail.com",
                    "homepage": "http://www.instaclick.com"
                },
                {
                    "name": "Roman Borschel",
                    "email": "roman@code-factory.org"
                },
                {
                    "name": "Benjamin Eberlei",
                    "email": "kontakt@beberlei.de"
                },
                {
                    "name": "Johannes Schmitt",
                    "email": "schmittjoh@gmail.com",
                    "homepage": "https://github.com/schmittjoh",
                    "role": "Developer of wrapped JMSSerializerBundle"
                }
            ],
            "description": "Docblock Annotations Parser",
            "homepage": "http://www.doctrine-project.org",
            "keywords": [
                "annotations",
                "docblock",
                "parser"
            ],
            "time": "2013-04-20 08:30:17"
        },
        {
            "name": "doctrine/lexer",
            "version": "dev-master",
            "source": {
                "type": "git",
                "url": "https://github.com/doctrine/lexer.git",
                "reference": "bc0e1f0cc285127a38c6c8ea88bc5dba2fd53e94"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/doctrine/lexer/zipball/bc0e1f0cc285127a38c6c8ea88bc5dba2fd53e94",
                "reference": "bc0e1f0cc285127a38c6c8ea88bc5dba2fd53e94",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.2"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.0.x-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Doctrine\\Common\\Lexer\\": "lib/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Guilherme Blanco",
                    "email": "guilhermeblanco@gmail.com",
                    "homepage": "http://www.instaclick.com"
                },
                {
                    "name": "Roman Borschel",
                    "email": "roman@code-factory.org"
                },
                {
                    "name": "Johannes Schmitt",
                    "email": "schmittjoh@gmail.com",
                    "homepage": "https://github.com/schmittjoh",
                    "role": "Developer of wrapped JMSSerializerBundle"
                }
            ],
            "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.",
            "homepage": "http://www.doctrine-project.org",
            "keywords": [
                "lexer",
                "parser"
            ],
            "time": "2013-03-07 12:15:25"
        },
        {
            "name": "jms/metadata",
            "version": "dev-master",
            "source": {
                "type": "git",
                "url": "https://github.com/schmittjoh/metadata.git",
                "reference": "0979c7d9eb7f0031a3c5ffed1d6e1fa4eb846e4e"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/schmittjoh/metadata/zipball/0979c7d9eb7f0031a3c5ffed1d6e1fa4eb846e4e",
                "reference": "0979c7d9eb7f0031a3c5ffed1d6e1fa4eb846e4e",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.0"
            },
            "require-dev": {
                "doctrine/common": ">=2.0,<2.4-dev"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.4.x-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Metadata\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "Apache"
            ],
            "authors": [
                {
                    "name": "Johannes M. Schmitt",
                    "email": "schmittjoh@gmail.com",
                    "homepage": "http://jmsyst.com",
                    "role": "Developer of wrapped JMSSerializerBundle"
                }
            ],
            "description": "Class/method/property metadata management in PHP",
            "keywords": [
                "annotations",
                "metadata",
                "xml",
                "yaml"
            ],
            "time": "2013-03-28 16:32:37"
        },
        {
            "name": "jms/parser-lib",
            "version": "dev-master",
            "source": {
                "type": "git",
                "url": "https://github.com/schmittjoh/parser-lib.git",
                "reference": "4d469a70c6dd03f921cbdeadafbcb261bb23e8b0"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/schmittjoh/parser-lib/zipball/4d469a70c6dd03f921cbdeadafbcb261bb23e8b0",
                "reference": "4d469a70c6dd03f921cbdeadafbcb261bb23e8b0",
                "shasum": ""
            },
            "require": {
                "phpoption/phpoption": ">=0.9,<2.0-dev"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.1-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "JMS\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "Apache2"
            ],
            "description": "A library for easily creating recursive-descent parsers.",
            "time": "2012-11-30 08:11:04"
        },
        {
            "name": "phpcollection/phpcollection",
            "version": "dev-master",
            "source": {
                "type": "git",
                "url": "https://github.com/schmittjoh/php-collection.git",
                "reference": "3ce8ffb990e9511c7a843f20740373eb27e4c3bd"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/schmittjoh/php-collection/zipball/3ce8ffb990e9511c7a843f20740373eb27e4c3bd",
                "reference": "3ce8ffb990e9511c7a843f20740373eb27e4c3bd",
                "shasum": ""
            },
            "require": {
                "phpoption/phpoption": "1.*"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "0.2-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "PhpCollection": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "Apache2"
            ],
            "authors": [
                {
                    "name": "Johannes M. Schmitt",
                    "email": "schmittjoh@gmail.com",
                    "homepage": "https://github.com/schmittjoh",
                    "role": "Developer of wrapped JMSSerializerBundle"
                }
            ],
            "description": "General-Purpose Collection Library for PHP",
            "keywords": [
                "collection",
                "list",
                "map",
                "sequence",
                "set"
            ],
            "time": "2013-02-25 13:15:41"
        },
        {
            "name": "phpoption/phpoption",
            "version": "dev-master",
            "source": {
                "type": "git",
                "url": "https://github.com/schmittjoh/php-option.git",
                "reference": "e686c0d55c87e042dec9c7fe3fa86b2b3b9d9ee3"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/e686c0d55c87e042dec9c7fe3fa86b2b3b9d9ee3",
                "reference": "e686c0d55c87e042dec9c7fe3fa86b2b3b9d9ee3",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.0"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.3-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "PhpOption\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "Apache2"
            ],
            "authors": [
                {
                    "name": "Johannes Schmitt",
                    "email": "schmittjoh@gmail.com",
                    "homepage": "https://github.com/schmittjoh",
                    "role": "Developer of wrapped JMSSerializerBundle"
                }
            ],
            "description": "Option Type for PHP",
            "keywords": [
                "language",
                "option",
                "php",
                "type"
            ],
            "time": "2013-03-28 16:34:57"
        }
    ],
    "packages-dev": [
        {
            "name": "doctrine/cache",
            "version": "dev-master",
            "source": {
                "type": "git",
                "url": "https://github.com/doctrine/cache.git",
                "reference": "4116eff37635219101a22c9732f409633eb07c5d"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/doctrine/cache/zipball/4116eff37635219101a22c9732f409633eb07c5d",
                "reference": "4116eff37635219101a22c9732f409633eb07c5d",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.2"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.0.x-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Doctrine\\Common\\Cache\\": "lib/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Jonathan Wage",
                    "email": "jonwage@gmail.com",
                    "homepage": "http://www.jwage.com/"
                },
                {
                    "name": "Guilherme Blanco",
                    "email": "guilhermeblanco@gmail.com",
                    "homepage": "http://www.instaclick.com"
                },
                {
                    "name": "Roman Borschel",
                    "email": "roman@code-factory.org"
                },
                {
                    "name": "Benjamin Eberlei",
                    "email": "kontakt@beberlei.de"
                },
                {
                    "name": "Johannes Schmitt",
                    "email": "schmittjoh@gmail.com",
                    "homepage": "https://github.com/schmittjoh",
                    "role": "Developer of wrapped JMSSerializerBundle"
                }
            ],
            "description": "Caching library offering an object-oriented API for many cache backends",
            "homepage": "http://www.doctrine-project.org",
            "keywords": [
                "cache",
                "caching"
            ],
            "time": "2013-05-04 23:23:40"
        },
        {
            "name": "doctrine/collections",
            "version": "dev-master",
            "source": {
                "type": "git",
                "url": "https://github.com/doctrine/collections.git",
                "reference": "df2138bcb467533bfe6b3a01301d480aec008b93"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/doctrine/collections/zipball/df2138bcb467533bfe6b3a01301d480aec008b93",
                "reference": "df2138bcb467533bfe6b3a01301d480aec008b93",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.2"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.1.x-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Doctrine\\Common\\Collections\\": "lib/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Jonathan Wage",
                    "email": "jonwage@gmail.com",
                    "homepage": "http://www.jwage.com/"
                },
                {
                    "name": "Guilherme Blanco",
                    "email": "guilhermeblanco@gmail.com",
                    "homepage": "http://www.instaclick.com"
                },
                {
                    "name": "Roman Borschel",
                    "email": "roman@code-factory.org"
                },
                {
                    "name": "Benjamin Eberlei",
                    "email": "kontakt@beberlei.de"
                },
                {
                    "name": "Johannes Schmitt",
                    "email": "schmittjoh@gmail.com",
                    "homepage": "https://github.com/schmittjoh",
                    "role": "Developer of wrapped JMSSerializerBundle"
                }
            ],
            "description": "Collections Abstraction library",
            "homepage": "http://www.doctrine-project.org",
            "keywords": [
                "array",
                "collections",
                "iterator"
            ],
            "time": "2013-03-17 14:01:33"
        },
        {
            "name": "doctrine/common",
            "version": "dev-master",
            "source": {
                "type": "git",
                "url": "https://github.com/doctrine/common.git",
                "reference": "ce87784a45f93c73a4035748fd98ecbbda3098fb"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/doctrine/common/zipball/ce87784a45f93c73a4035748fd98ecbbda3098fb",
                "reference": "ce87784a45f93c73a4035748fd98ecbbda3098fb",
                "shasum": ""
            },
            "require": {
                "doctrine/annotations": "1.*",
                "doctrine/cache": "1.*",
                "doctrine/collections": "1.*",
                "doctrine/inflector": "1.*",
                "doctrine/lexer": "1.*",
                "php": ">=5.3.2"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.4.x-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Doctrine\\Common\\": "lib/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Jonathan Wage",
                    "email": "jonwage@gmail.com",
                    "homepage": "http://www.jwage.com/"
                },
                {
                    "name": "Guilherme Blanco",
                    "email": "guilhermeblanco@gmail.com",
                    "homepage": "http://www.instaclick.com"
                },
                {
                    "name": "Roman Borschel",
                    "email": "roman@code-factory.org"
                },
                {
                    "name": "Benjamin Eberlei",
                    "email": "kontakt@beberlei.de"
                },
                {
                    "name": "Johannes Schmitt",
                    "email": "schmittjoh@gmail.com",
                    "homepage": "https://github.com/schmittjoh",
                    "role": "Developer of wrapped JMSSerializerBundle"
                }
            ],
            "description": "Common Library for Doctrine projects",
            "homepage": "http://www.doctrine-project.org",
            "keywords": [
                "annotations",
                "collections",
                "eventmanager",
                "persistence",
                "spl"
            ],
            "time": "2013-05-09 21:35:24"
        },
        {
            "name": "doctrine/dbal",
            "version": "2.3.x-dev",
            "source": {
                "type": "git",
                "url": "https://github.com/doctrine/dbal.git",
                "reference": "587b5510a7c22f3a4829c933279a4ade8bf45c3a"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/doctrine/dbal/zipball/587b5510a7c22f3a4829c933279a4ade8bf45c3a",
                "reference": "587b5510a7c22f3a4829c933279a4ade8bf45c3a",
                "shasum": ""
            },
            "require": {
                "doctrine/common": ">=2.3.0,<2.5-dev",
                "php": ">=5.3.2"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3.x-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Doctrine\\DBAL": "lib/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Jonathan Wage",
                    "email": "jonwage@gmail.com",
                    "homepage": "http://www.jwage.com/"
                },
                {
                    "name": "Guilherme Blanco",
                    "email": "guilhermeblanco@gmail.com",
                    "homepage": "http://www.instaclick.com"
                },
                {
                    "name": "Roman Borschel",
                    "email": "roman@code-factory.org"
                },
                {
                    "name": "Benjamin Eberlei",
                    "email": "kontakt@beberlei.de"
                }
            ],
            "description": "Database Abstraction Layer",
            "homepage": "http://www.doctrine-project.org",
            "keywords": [
                "database",
                "dbal",
                "persistence",
                "queryobject"
            ],
            "time": "2013-05-09 14:04:51"
        },
        {
            "name": "doctrine/inflector",
            "version": "dev-master",
            "source": {
                "type": "git",
                "url": "https://github.com/doctrine/inflector.git",
                "reference": "8b4b3ccec7aafc596e2fc1e593c9f2e78f939c8c"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/doctrine/inflector/zipball/8b4b3ccec7aafc596e2fc1e593c9f2e78f939c8c",
                "reference": "8b4b3ccec7aafc596e2fc1e593c9f2e78f939c8c",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.2"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.0.x-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Doctrine\\Common\\Inflector\\": "lib/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Jonathan Wage",
                    "email": "jonwage@gmail.com",
                    "homepage": "http://www.jwage.com/"
                },
                {
                    "name": "Guilherme Blanco",
                    "email": "guilhermeblanco@gmail.com",
                    "homepage": "http://www.instaclick.com"
                },
                {
                    "name": "Roman Borschel",
                    "email": "roman@code-factory.org"
                },
                {
                    "name": "Benjamin Eberlei",
                    "email": "kontakt@beberlei.de"
                },
                {
                    "name": "Johannes Schmitt",
                    "email": "schmittjoh@gmail.com",
                    "homepage": "https://github.com/schmittjoh",
                    "role": "Developer of wrapped JMSSerializerBundle"
                }
            ],
            "description": "Common String Manipulations with regard to casing and singular/plural rules.",
            "homepage": "http://www.doctrine-project.org",
            "keywords": [
                "inflection",
                "pluralize",
                "singularize",
                "string"
            ],
            "time": "2013-04-10 16:14:30"
        },
        {
            "name": "doctrine/orm",
            "version": "2.3.x-dev",
            "source": {
                "type": "git",
                "url": "https://github.com/doctrine/doctrine2.git",
                "reference": "e0feccc2e46021689d3c5cf2a1d1e920a060b8ad"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/doctrine/doctrine2/zipball/e0feccc2e46021689d3c5cf2a1d1e920a060b8ad",
                "reference": "e0feccc2e46021689d3c5cf2a1d1e920a060b8ad",
                "shasum": ""
            },
            "require": {
                "doctrine/dbal": "2.3.*",
                "ext-pdo": "*",
                "php": ">=5.3.2",
                "symfony/console": "2.*"
            },
            "suggest": {
                "symfony/yaml": "If you want to use YAML Metadata Mapping Driver"
            },
            "bin": [
                "bin/doctrine",
                "bin/doctrine.php"
            ],
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3.x-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Doctrine\\ORM": "lib/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Jonathan Wage",
                    "email": "jonwage@gmail.com",
                    "homepage": "http://www.jwage.com/"
                },
                {
                    "name": "Guilherme Blanco",
                    "email": "guilhermeblanco@gmail.com",
                    "homepage": "http://www.instaclick.com"
                },
                {
                    "name": "Roman Borschel",
                    "email": "roman@code-factory.org"
                },
                {
                    "name": "Benjamin Eberlei",
                    "email": "kontakt@beberlei.de"
                }
            ],
            "description": "Object-Relational-Mapper for PHP",
            "homepage": "http://www.doctrine-project.org",
            "keywords": [
                "database",
                "orm"
            ],
            "time": "2013-05-09 16:17:03"
        },
        {
            "name": "symfony/console",
            "version": "dev-master",
            "target-dir": "Symfony/Component/Console",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Console.git",
                "reference": "v2.3.0-BETA2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Console/zipball/v2.3.0-BETA2",
                "reference": "v2.3.0-BETA2",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "require-dev": {
                "symfony/event-dispatcher": ">=2.1,<3.0"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Console\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Console Component",
            "homepage": "http://symfony.com",
            "time": "2013-05-10 18:12:13"
        },
        {
            "name": "symfony/event-dispatcher",
            "version": "2.1.x-dev",
            "target-dir": "Symfony/Component/EventDispatcher",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/EventDispatcher.git",
                "reference": "v2.1.10"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/v2.1.10",
                "reference": "v2.1.10",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "require-dev": {
                "symfony/dependency-injection": "2.1.*"
            },
            "suggest": {
                "symfony/dependency-injection": "2.1.*",
                "symfony/http-kernel": "2.1.*"
            },
            "type": "library",
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\EventDispatcher": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony EventDispatcher Component",
            "homepage": "http://symfony.com",
            "time": "2013-02-11 11:26:14"
        },
        {
            "name": "symfony/filesystem",
            "version": "dev-master",
            "target-dir": "Symfony/Component/Filesystem",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Filesystem.git",
                "reference": "v2.3.0-BETA2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Filesystem/zipball/v2.3.0-BETA2",
                "reference": "v2.3.0-BETA2",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Filesystem\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Filesystem Component",
            "homepage": "http://symfony.com",
            "time": "2013-05-06 20:03:44"
        },
        {
            "name": "symfony/form",
            "version": "2.1.x-dev",
            "target-dir": "Symfony/Component/Form",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Form.git",
                "reference": "v2.1.10"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Form/zipball/v2.1.10",
                "reference": "v2.1.10",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3",
                "symfony/event-dispatcher": "2.1.*",
                "symfony/locale": "2.1.*",
                "symfony/options-resolver": "2.1.*"
            },
            "require-dev": {
                "symfony/http-foundation": "2.1.*",
                "symfony/validator": "2.1.*"
            },
            "suggest": {
                "symfony/http-foundation": "2.1.*",
                "symfony/validator": "2.1.*"
            },
            "type": "library",
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Form": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Form Component",
            "homepage": "http://symfony.com",
            "time": "2013-05-06 10:48:41"
        },
        {
            "name": "symfony/locale",
            "version": "2.1.x-dev",
            "target-dir": "Symfony/Component/Locale",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Locale.git",
                "reference": "v2.1.10"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Locale/zipball/v2.1.10",
                "reference": "v2.1.10",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "suggest": {
                "ext-intl": ">=5.3.3"
            },
            "type": "library",
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Locale": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Locale Component",
            "homepage": "http://symfony.com",
            "time": "2013-01-10 04:41:59"
        },
        {
            "name": "symfony/options-resolver",
            "version": "2.1.x-dev",
            "target-dir": "Symfony/Component/OptionsResolver",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/OptionsResolver.git",
                "reference": "v2.1.10"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/OptionsResolver/zipball/v2.1.10",
                "reference": "v2.1.10",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\OptionsResolver": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony OptionsResolver Component",
            "homepage": "http://symfony.com",
            "keywords": [
                "config",
                "configuration",
                "options"
            ],
            "time": "2013-01-09 08:51:07"
        },
        {
            "name": "symfony/translation",
            "version": "2.1.x-dev",
            "target-dir": "Symfony/Component/Translation",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Translation.git",
                "reference": "v2.1.10"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Translation/zipball/v2.1.10",
                "reference": "v2.1.10",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "require-dev": {
                "symfony/config": "2.1.*",
                "symfony/yaml": "2.1.*"
            },
            "suggest": {
                "symfony/config": "2.1.*",
                "symfony/yaml": "2.1.*"
            },
            "type": "library",
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Translation": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Translation Component",
            "homepage": "http://symfony.com",
            "time": "2013-04-20 08:25:59"
        },
        {
            "name": "symfony/validator",
            "version": "2.1.x-dev",
            "target-dir": "Symfony/Component/Validator",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Validator.git",
                "reference": "bd1aa1eb092f3f01cd87e9c18e959cbb07cf7579"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Validator/zipball/bd1aa1eb092f3f01cd87e9c18e959cbb07cf7579",
                "reference": "bd1aa1eb092f3f01cd87e9c18e959cbb07cf7579",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "require-dev": {
                "symfony/http-foundation": "2.1.*",
                "symfony/locale": "2.1.*",
                "symfony/yaml": "2.1.*"
            },
            "suggest": {
                "doctrine/common": "~2.1",
                "symfony/http-foundation": "2.1.*",
                "symfony/yaml": "2.1.*"
            },
            "type": "library",
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Validator": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Validator Component",
            "homepage": "http://symfony.com",
            "time": "2013-05-10 16:13:09"
        },
        {
            "name": "symfony/yaml",
            "version": "dev-master",
            "target-dir": "Symfony/Component/Yaml",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Yaml.git",
                "reference": "030e5f857f4089912ea3ee01d84ef41bc9a961a4"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Yaml/zipball/030e5f857f4089912ea3ee01d84ef41bc9a961a4",
                "reference": "030e5f857f4089912ea3ee01d84ef41bc9a961a4",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Yaml\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Yaml Component",
            "homepage": "http://symfony.com",
            "time": "2013-05-10 18:12:13"
        },
        {
            "name": "twig/twig",
            "version": "dev-master",
            "source": {
                "type": "git",
                "url": "https://github.com/fabpot/Twig.git",
                "reference": "4a49a3ae30ad2694057a63eccc3fb7b551b93e74"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/fabpot/Twig/zipball/4a49a3ae30ad2694057a63eccc3fb7b551b93e74",
                "reference": "4a49a3ae30ad2694057a63eccc3fb7b551b93e74",
                "shasum": ""
            },
            "require": {
                "php": ">=5.2.4"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.13-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Twig_": "lib/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Armin Ronacher",
                    "email": "armin.ronacher@active-4.com"
                }
            ],
            "description": "Twig, the flexible, fast, and secure template language for PHP",
            "homepage": "http://twig.sensiolabs.org",
            "keywords": [
                "templating"
            ],
            "time": "2013-05-10 15:25:39"
        }
    ],
    "aliases": [

    ],
    "minimum-stability": "dev",
    "stability-flags": [

    ],
    "platform": {
        "php": ">=5.3.2"
    },
    "platform-dev": [

    ]
}
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="tests/bootstrap.php"
>
         
    <testsuites>
        <testsuite name="JMS Serializer Test Suite">
            <directory>./tests</directory>
        </testsuite>
    </testsuites>
    
    <groups>
        <exclude>
            <group>performance</group>
        </exclude>
    </groups>
</phpunit>
THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.

BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.

1. Definitions

    "Adaptation" means a work based upon the Work, or upon the Work and other pre-existing works, such as a translation, adaptation, derivative work, arrangement of music or other alterations of a literary or artistic work, or phonogram or performance and includes cinematographic adaptations or any other form in which the Work may be recast, transformed, or adapted including in any form recognizably derived from the original, except that a work that constitutes a Collection will not be considered an Adaptation for the purpose of this License. For the avoidance of doubt, where the Work is a musical work, performance or phonogram, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered an Adaptation for the purpose of this License.
    "Collection" means a collection of literary or artistic works, such as encyclopedias and anthologies, or performances, phonograms or broadcasts, or other works or subject matter other than works listed in Section 1(f) below, which, by reason of the selection and arrangement of their contents, constitute intellectual creations, in which the Work is included in its entirety in unmodified form along with one or more other contributions, each constituting separate and independent works in themselves, which together are assembled into a collective whole. A work that constitutes a Collection will not be considered an Adaptation (as defined above) for the purposes of this License.
    "Distribute" means to make available to the public the original and copies of the Work through sale or other transfer of ownership.
    "Licensor" means the individual, individuals, entity or entities that offer(s) the Work under the terms of this License.
    "Original Author" means, in the case of a literary or artistic work, the individual, individuals, entity or entities who created the Work or if no individual or entity can be identified, the publisher; and in addition (i) in the case of a performance the actors, singers, musicians, dancers, and other persons who act, sing, deliver, declaim, play in, interpret or otherwise perform literary or artistic works or expressions of folklore; (ii) in the case of a phonogram the producer being the person or legal entity who first fixes the sounds of a performance or other sounds; and, (iii) in the case of broadcasts, the organization that transmits the broadcast.
    "Work" means the literary and/or artistic work offered under the terms of this License including without limitation any production in the literary, scientific and artistic domain, whatever may be the mode or form of its expression including digital form, such as a book, pamphlet and other writing; a lecture, address, sermon or other work of the same nature; a dramatic or dramatico-musical work; a choreographic work or entertainment in dumb show; a musical composition with or without words; a cinematographic work to which are assimilated works expressed by a process analogous to cinematography; a work of drawing, painting, architecture, sculpture, engraving or lithography; a photographic work to which are assimilated works expressed by a process analogous to photography; a work of applied art; an illustration, map, plan, sketch or three-dimensional work relative to geography, topography, architecture or science; a performance; a broadcast; a phonogram; a compilation of data to the extent it is protected as a copyrightable work; or a work performed by a variety or circus performer to the extent it is not otherwise considered a literary or artistic work.
    "You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation.
    "Publicly Perform" means to perform public recitations of the Work and to communicate to the public those public recitations, by any means or process, including by wire or wireless means or public digital performances; to make available to the public Works in such a way that members of the public may access these Works from a place and at a place individually chosen by them; to perform the Work to the public by any means or process and the communication to the public of the performances of the Work, including by public digital performance; to broadcast and rebroadcast the Work by any means including signs, sounds or images.
    "Reproduce" means to make copies of the Work by any means including without limitation by sound or visual recordings and the right of fixation and reproducing fixations of the Work, including storage of a protected performance or phonogram in digital form or other electronic medium.

2. Fair Dealing Rights. Nothing in this License is intended to reduce, limit, or restrict any uses free from copyright or rights arising from limitations or exceptions that are provided for in connection with the copyright protection under copyright law or other applicable laws.

3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below:

    to Reproduce the Work, to incorporate the Work into one or more Collections, and to Reproduce the Work as incorporated in the Collections; and,
    to Distribute and Publicly Perform the Work including as incorporated in Collections.

The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats, but otherwise you have no rights to make Adaptations. Subject to 8(f), all rights not expressly granted by Licensor are hereby reserved, including but not limited to the rights set forth in Section 4(d).

4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions:

    You may Distribute or Publicly Perform the Work only under the terms of this License. You must include a copy of, or the Uniform Resource Identifier (URI) for, this License with every copy of the Work You Distribute or Publicly Perform. You may not offer or impose any terms on the Work that restrict the terms of this License or the ability of the recipient of the Work to exercise the rights granted to that recipient under the terms of the License. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties with every copy of the Work You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Work, You may not impose any effective technological measures on the Work that restrict the ability of a recipient of the Work from You to exercise the rights granted to that recipient under the terms of the License. This Section 4(a) applies to the Work as incorporated in a Collection, but this does not require the Collection apart from the Work itself to be made subject to the terms of this License. If You create a Collection, upon notice from any Licensor You must, to the extent practicable, remove from the Collection any credit as required by Section 4(c), as requested.
    You may not exercise any of the rights granted to You in Section 3 above in any manner that is primarily intended for or directed toward commercial advantage or private monetary compensation. The exchange of the Work for other copyrighted works by means of digital file-sharing or otherwise shall not be considered to be intended for or directed toward commercial advantage or private monetary compensation, provided there is no payment of any monetary compensation in connection with the exchange of copyrighted works.
    If You Distribute, or Publicly Perform the Work or Collections, You must, unless a request has been made pursuant to Section 4(a), keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or if the Original Author and/or Licensor designate another party or parties (e.g., a sponsor institute, publishing entity, journal) for attribution ("Attribution Parties") in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; (ii) the title of the Work if supplied; (iii) to the extent reasonably practicable, the URI, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work. The credit required by this Section 4(c) may be implemented in any reasonable manner; provided, however, that in the case of a Collection, at a minimum such credit will appear, if a credit for all contributing authors of Collection appears, then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors. For the avoidance of doubt, You may only use the credit required by this Section for the purpose of attribution in the manner set out above and, by exercising Your rights under this License, You may not implicitly or explicitly assert or imply any connection with, sponsorship or endorsement by the Original Author, Licensor and/or Attribution Parties, as appropriate, of You or Your use of the Work, without the separate, express prior written permission of the Original Author, Licensor and/or Attribution Parties.

    For the avoidance of doubt:
        Non-waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme cannot be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License;
        Waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme can be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License if Your exercise of such rights is for a purpose or use which is otherwise than noncommercial as permitted under Section 4(b) and otherwise waives the right to collect royalties through any statutory or compulsory licensing scheme; and,
        Voluntary License Schemes. The Licensor reserves the right to collect royalties, whether individually or, in the event that the Licensor is a member of a collecting society that administers voluntary licensing schemes, via that society, from any exercise by You of the rights granted under this License that is for a purpose or use which is otherwise than noncommercial as permitted under Section 4(b).
    Except as otherwise agreed in writing by the Licensor or as may be otherwise permitted by applicable law, if You Reproduce, Distribute or Publicly Perform the Work either by itself or as part of any Collections, You must not distort, mutilate, modify or take other derogatory action in relation to the Work which would be prejudicial to the Original Author's honor or reputation.

5. Representations, Warranties and Disclaimer

UNLESS OTHERWISE MUTUALLY AGREED BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.

6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

7. Termination

    This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Collections from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License.
    Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above.

8. Miscellaneous

    Each time You Distribute or Publicly Perform the Work or a Collection, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License.
    If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
    No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent.
    This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You.
    The rights granted under, and the subject matter referenced, in this License were drafted utilizing the terminology of the Berne Convention for the Protection of Literary and Artistic Works (as amended on September 28, 1979), the Rome Convention of 1961, the WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and the Universal Copyright Convention (as revised on July 24, 1971). These rights and subject matter take effect in the relevant jurisdiction in which the License terms are sought to be enforced according to the corresponding provisions of the implementation of those treaty provisions in the applicable national law. If the standard suite of rights granted under applicable copyright law includes additional rights not granted under this License, such additional rights are deemed to be included in the License; this License is not intended to restrict the license of any rights under applicable law.
{
    "name": "jms/metadata",
    "description": "Class/method/property metadata management in PHP",
    "keywords": ["annotations","metadata","yaml","xml"],
    "type": "library",
    "license": "Apache",
    "authors": [
        {
            "name": "Johannes M. Schmitt",
            "email": "schmittjoh@gmail.com"
        }
    ],
    "require": {
        "php": ">=5.3.0"
    },
    "require-dev" : {
        "doctrine/cache" : "~1.0"
    },
    "autoload": {
        "psr-0": { "Metadata\\": "src/" }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.5.x-dev"
        }
    }
}
<?php

/*
 * Copyright 2011 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Metadata;

use Metadata\Driver\AdvancedDriverInterface;
use Metadata\Driver\DriverInterface;
use Metadata\Cache\CacheInterface;

class MetadataFactory implements AdvancedMetadataFactoryInterface
{
    private $driver;
    private $cache;
    private $loadedMetadata = array();
    private $loadedClassMetadata = array();
    private $hierarchyMetadataClass;
    private $includeInterfaces = false;
    private $debug;

    /**
     * @param DriverInterface $driver
     * @param string          $hierarchyMetadataClass
     * @param boolean         $debug
     */
    public function __construct(DriverInterface $driver, $hierarchyMetadataClass = 'Metadata\ClassHierarchyMetadata', $debug = false)
    {
        $this->driver = $driver;
        $this->hierarchyMetadataClass = $hierarchyMetadataClass;
        $this->debug = (Boolean) $debug;
    }

    /**
     * @param boolean $bool
     */
    public function setIncludeInterfaces($include)
    {
        $this->includeInterfaces = (Boolean) $include;
    }

    public function setCache(CacheInterface $cache)
    {
        $this->cache = $cache;
    }

    /**
     * @param string $className
     *
     * @return ClassMetaData
     */
    public function getMetadataForClass($className)
    {
        if (isset($this->loadedMetadata[$className])) {
            return $this->filterNullMetadata($this->loadedMetadata[$className]);
        }

        $metadata = null;
        foreach ($this->getClassHierarchy($className) as $class) {
            if (isset($this->loadedClassMetadata[$name = $class->getName()])) {
                if (null !== $classMetadata = $this->filterNullMetadata($this->loadedClassMetadata[$name])) {
                    $this->addClassMetadata($metadata, $classMetadata);
                }
                continue;
            }

            // check the cache
            if (null !== $this->cache) {
                if (($classMetadata = $this->cache->loadClassMetadataFromCache($class)) instanceof NullMetadata) {
                    $this->loadedClassMetadata[$name] = $classMetadata;
                    continue;
                }

                if (null !== $classMetadata) {
                    if ( ! $classMetadata instanceof ClassMetadata) {
                        throw new \LogicException(sprintf('The cache must return instances of ClassMetadata, but got %s.', var_export($classMetadata, true)));
                    }

                    if ($this->debug && !$classMetadata->isFresh()) {
                        $this->cache->evictClassMetadataFromCache($classMetadata->reflection);
                    } else {
                        $this->loadedClassMetadata[$name] = $classMetadata;
                        $this->addClassMetadata($metadata, $classMetadata);
                        continue;
                    }
                }
            }

            // load from source
            if (null !== $classMetadata = $this->driver->loadMetadataForClass($class)) {
                $this->loadedClassMetadata[$name] = $classMetadata;
                $this->addClassMetadata($metadata, $classMetadata);

                if (null !== $this->cache) {
                    $this->cache->putClassMetadataInCache($classMetadata);
                }

                continue;
            }

            if (null !== $this->cache && !$this->debug) {
                $this->cache->putClassMetadataInCache(new NullMetadata());
            }
        }

        if (null === $metadata) {
            $metadata = new NullMetadata();
        }

        return $this->filterNullMetadata($this->loadedMetadata[$className] = $metadata);
    }

    /**
     * {@inheritDoc}
     */
    public function getAllClassNames()
    {
        if (!$this->driver instanceof AdvancedDriverInterface) {
            throw new \RuntimeException(
                sprintf('Driver "%s" must be an instance of "AdvancedDriverInterface".', get_class($this->driver))
            );
        }

        return $this->driver->getAllClassNames();
    }

    /**
     * @param ClassMetadata|null $metadata
     * @param ClassMetadata      $toAdd
     */
    private function addClassMetadata(&$metadata, $toAdd)
    {
        if ($toAdd instanceof MergeableInterface) {
            if (null === $metadata) {
                $metadata = clone $toAdd;
            } else {
                $metadata->merge($toAdd);
            }
        } else {
            if (null === $metadata) {
                $metadata = new $this->hierarchyMetadataClass;
            }

            $metadata->addClassMetadata($toAdd);
        }
    }

    private function getClassHierarchy($class)
    {
        $classes = array();
        $refl = new \ReflectionClass($class);

        do {
            $classes[] = $refl;
            $refl = $refl->getParentClass();
        } while (false !== $refl);

        $classes = array_reverse($classes, false);

        if (!$this->includeInterfaces) {
            return $classes;
        }

        $addedInterfaces = array();
        $newHierarchy = array();

        foreach ($classes as $class) {
            foreach ($class->getInterfaces() as $interface) {
                if (isset($addedInterfaces[$interface->getName()])) {
                    continue;
                }
                $addedInterfaces[$interface->getName()] = true;

                $newHierarchy[] = $interface;
            }

            $newHierarchy[] = $class;
        }

        return $newHierarchy;
    }

    private function filterNullMetadata($metadata = null)
    {
        return !$metadata instanceof NullMetadata ? $metadata : null;
    }
}
<?php

/*
 * Copyright 2011 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Metadata;

/**
 * Base class for property metadata.
 *
 * This class is intended to be extended to add your application specific
 * properties, and flags.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class PropertyMetadata implements \Serializable
{
    public $class;
    public $name;
    public $reflection;

    public function __construct($class, $name)
    {
        $this->class = $class;
        $this->name = $name;

        $this->reflection = new \ReflectionProperty($class, $name);
        $this->reflection->setAccessible(true);
    }

    /**
     * @param object $obj
     *
     * @return mixed
     */
    public function getValue($obj)
    {
        return $this->reflection->getValue($obj);
    }

    /**
     * @param object $obj
     * @param string $value
     */
    public function setValue($obj, $value)
    {
        $this->reflection->setValue($obj, $value);
    }

    public function serialize()
    {
        return serialize(array(
            $this->class,
            $this->name,
        ));
    }

    public function unserialize($str)
    {
        list($this->class, $this->name) = unserialize($str);

        $this->reflection = new \ReflectionProperty($this->class, $this->name);
        $this->reflection->setAccessible(true);
    }
}
<?php

namespace Metadata;

/**
 * Represents the metadata for a class that has not metadata.
 *
 * @author Adrien Brault <adrien.brault@gmail.com>
 */
class NullMetadata extends ClassMetadata
{
    public function __construct()
    {

    }

    public function serialize()
    {
        return '';
    }

    public function unserialize($str)
    {

    }
}
<?php

namespace Metadata\Cache;

use Doctrine\Common\Cache\Cache;
use Metadata\ClassMetadata;

/**
 * @author Henrik Bjornskov <henrik@bjrnskov.dk>
 */
class DoctrineCacheAdapter implements CacheInterface
{
    /**
     * @param string $prefix
     */
    private $prefix;

    /**
     * @var Cache $cache
     */
    private $cache;

    /**
     * @param string $prefix
     * @param Cache $cache
     */
    public function __construct($prefix, Cache $cache)
    {
        $this->prefix = $prefix;
        $this->cache = $cache;
    }

    /**
     * {@inheritDoc}
     */
    public function loadClassMetadataFromCache(\ReflectionClass $class)
    {
        $cache = $this->cache->fetch($this->prefix . $class->name);
        return false === $cache ? null : $cache;
    }

    /**
     * {@inheritDoc}
     */
    public function putClassMetadataInCache(ClassMetadata $metadata)
    {
        $this->cache->save($this->prefix . $metadata->name, $metadata);
    }

    /**
     * {@inheritDoc}
     */
    public function evictClassMetadataFromCache(\ReflectionClass $class)
    {
        $this->cache->delete($this->prefix . $class->name);
    }
}
<?php

namespace Metadata\Cache;

use Metadata\ClassMetadata;

class FileCache implements CacheInterface
{
    private $dir;

    public function __construct($dir)
    {
        if (!is_dir($dir)) {
            throw new \InvalidArgumentException(sprintf('The directory "%s" does not exist.', $dir));
        }
        if (!is_writable($dir)) {
            throw new \InvalidArgumentException(sprintf('The directory "%s" is not writable.', $dir));
        }

        $this->dir = rtrim($dir, '\\/');
    }

    /**
     * {@inheritDoc}
     */
    public function loadClassMetadataFromCache(\ReflectionClass $class)
    {
        $path = $this->dir.'/'.strtr($class->name, '\\', '-').'.cache.php';
        if (!file_exists($path)) {
            return null;
        }

        return include $path;
    }

    /**
     * {@inheritDoc}
     */
    public function putClassMetadataInCache(ClassMetadata $metadata)
    {
        $path = $this->dir.'/'.strtr($metadata->name, '\\', '-').'.cache.php';

        $tmpFile = tempnam($this->dir, 'metadata-cache');
        file_put_contents($tmpFile, '<?php return unserialize('.var_export(serialize($metadata), true).');');
        chmod($tmpFile, 0666 & ~umask());

        if (false === @rename($tmpFile, $path)) {
            throw new \RuntimeException(sprintf('Could not write new cache file to %s.', $path));
        }
    }

    /**
     * {@inheritDoc}
     */
    public function evictClassMetadataFromCache(\ReflectionClass $class)
    {
        $path = $this->dir.'/'.strtr($class->name, '\\', '-').'.cache.php';
        if (file_exists($path)) {
            unlink($path);
        }
    }
}
<?php

namespace Metadata\Cache;

use Metadata\ClassMetadata;

interface CacheInterface
{
    /**
     * Loads a class metadata instance from the cache
     *
     * @param \ReflectionClass $class
     *
     * @return ClassMetadata
     */
    function loadClassMetadataFromCache(\ReflectionClass $class);

    /**
     * Puts a class metadata instance into the cache
     *
     * @param ClassMetadata $metadata
     *
     * @return void
     */
    function putClassMetadataInCache(ClassMetadata $metadata);

    /**
     * Evicts the class metadata for the given class from the cache.
     *
     * @param \ReflectionClass $class
     *
     * @return void
     */
    function evictClassMetadataFromCache(\ReflectionClass $class);
}<?php

/*
 * Copyright 2011 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Metadata;

/**
 * Represents the metadata for the entire class hierarchy.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ClassHierarchyMetadata
{
    public $classMetadata = array();

    public function addClassMetadata(ClassMetadata $metadata)
    {
        $this->classMetadata[$metadata->name] = $metadata;
    }

    public function getRootClassMetadata()
    {
        return reset($this->classMetadata);
    }

    public function getOutsideClassMetadata()
    {
        return end($this->classMetadata);
    }

    public function isFresh($timestamp)
    {
        foreach ($this->classMetadata as $metadata) {
            if (!$metadata->isFresh($timestamp)) {
                return false;
            }
        }

        return true;
    }
}
<?php

namespace Metadata;

class MergeableClassMetadata extends ClassMetadata implements MergeableInterface
{
    public function merge(MergeableInterface $object)
    {
        if (!$object instanceof MergeableClassMetadata) {
            throw new \InvalidArgumentException('$object must be an instance of MergeableClassMetadata.');
        }

        $this->name = $object->name;
        $this->reflection = $object->reflection;
        $this->methodMetadata = array_merge($this->methodMetadata, $object->methodMetadata);
        $this->propertyMetadata = array_merge($this->propertyMetadata, $object->propertyMetadata);
        $this->fileResources = array_merge($this->fileResources, $object->fileResources);

        if ($object->createdAt < $this->createdAt) {
            $this->createdAt = $object->createdAt;
        }
    }
}<?php

namespace Metadata;

interface MergeableInterface
{
    /**
     * @param MergeableInterface $object
     *
     * @return void
     */
    public function merge(MergeableInterface $object);
}
<?php

/*
 * Copyright 2011 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Metadata;

/**
 * Base class for method metadata.
 *
 * This class is intended to be extended to add your application specific
 * properties, and flags.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class MethodMetadata implements \Serializable
{
    public $class;
    public $name;
    public $reflection;

    public function __construct($class, $name)
    {
        $this->class = $class;
        $this->name = $name;

        $this->reflection = new \ReflectionMethod($class, $name);
        $this->reflection->setAccessible(true);
    }

    /**
     * @param object $obj
     * @param array  $args
     *
     * @return mixed
     */
    public function invoke($obj, array $args = array())
    {
        return $this->reflection->invokeArgs($obj, $args);
    }

    public function serialize()
    {
        return serialize(array($this->class, $this->name));
    }

    public function unserialize($str)
    {
        list($this->class, $this->name) = unserialize($str);

        $this->reflection = new \ReflectionMethod($this->class, $this->name);
        $this->reflection->setAccessible(true);
    }
}
<?php

/*
 * Copyright 2011 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Metadata;

/**
 * Base class for class metadata.
 *
 * This class is intended to be extended to add your own application specific
 * properties, and flags.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ClassMetadata implements \Serializable
{
    public $name;
    public $reflection;
    public $methodMetadata = array();
    public $propertyMetadata = array();
    public $fileResources = array();
    public $createdAt;

    public function __construct($name)
    {
        $this->name = $name;

        $this->reflection = new \ReflectionClass($name);
        $this->createdAt = time();
    }

    public function addMethodMetadata(MethodMetadata $metadata)
    {
        $this->methodMetadata[$metadata->name] = $metadata;
    }

    public function addPropertyMetadata(PropertyMetadata $metadata)
    {
        $this->propertyMetadata[$metadata->name] = $metadata;
    }

    public function isFresh($timestamp = null)
    {
        if (null === $timestamp) {
            $timestamp = $this->createdAt;
        }

        foreach ($this->fileResources as $filepath) {
            if (!file_exists($filepath)) {
                return false;
            }

            if ($timestamp < filemtime($filepath)) {
                return false;
            }
        }

        return true;
    }

    public function serialize()
    {
        return serialize(array(
            $this->name,
            $this->methodMetadata,
            $this->propertyMetadata,
            $this->fileResources,
            $this->createdAt,
        ));
    }

    public function unserialize($str)
    {
        list(
            $this->name,
            $this->methodMetadata,
            $this->propertyMetadata,
            $this->fileResources,
            $this->createdAt
        ) = unserialize($str);

        $this->reflection = new \ReflectionClass($this->name);
    }
}
<?php

/*
 * Copyright 2011 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Metadata;

final class Version
{
    const VERSION = '1.4-DEV';
}
<?php

/*
 * Copyright 2011 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Metadata;

/**
 * Interface for advanced Metadata Factory implementations.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Jordan Stout <j@jrdn.org>
 */
interface AdvancedMetadataFactoryInterface extends MetadataFactoryInterface
{
    /**
     * Gets all the possible classes.
     *
     * @throws \RuntimeException if driver does not an advanced driver.
     * @return array
     */
    public function getAllClassNames();
}
<?php

/*
 * Copyright 2011 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Metadata\Driver;

interface DriverInterface
{
    /**
     * @param \ReflectionClass $class
     *
     * @return \Metadata\ClassMetadata
     */
    public function loadMetadataForClass(\ReflectionClass $class);
}
<?php

namespace Metadata\Driver;

use Symfony\Component\DependencyInjection\ContainerInterface;

class LazyLoadingDriver implements DriverInterface
{
    private $container;
    private $realDriverId;

    public function __construct(ContainerInterface $container, $realDriverId)
    {
        $this->container = $container;
        $this->realDriverId = $realDriverId;
    }

    /**
     * {@inheritDoc}
     */
    public function loadMetadataForClass(\ReflectionClass $class)
    {
        return $this->container->get($this->realDriverId)->loadMetadataForClass($class);
    }
}
<?php

/*
 * Copyright 2011 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Metadata\Driver;

final class DriverChain implements AdvancedDriverInterface
{
    private $drivers;

    public function __construct(array $drivers = array())
    {
        $this->drivers = $drivers;
    }
    
    public function addDriver(DriverInterface $driver)
    {
        $this->drivers[] = $driver;
    }

    public function loadMetadataForClass(\ReflectionClass $class)
    {
        foreach ($this->drivers as $driver) {
            if (null !== $metadata = $driver->loadMetadataForClass($class)) {
                return $metadata;
            }
        }

        return null;
    }

    /**
     * {@inheritDoc}
     */
    public function getAllClassNames()
    {
        $classes = array();
        foreach ($this->drivers as $driver) {
            if (!$driver instanceof AdvancedDriverInterface) {
                throw new \RuntimeException(
                    sprintf(
                        'Driver "%s" must be an instance of "AdvancedDriverInterface" to use '.
                        '"DriverChain::getAllClassNames()".',
                        get_class($driver)
                    )
                );
            }
            $driverClasses = $driver->getAllClassNames();
            if (!empty($driverClasses)) {
                $classes = array_merge($classes, $driverClasses);
            }
        }

        return $classes;
    }
}
<?php

/*
 * Copyright 2011 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Metadata\Driver;

/**
 * Forces advanced logic on a file locator.
 *
 * @author Jordan Stout <j@jrdn.org>
 */
interface AdvancedFileLocatorInterface extends FileLocatorInterface
{
    /**
     * Finds all possible metadata files.
     *
     * @param string $extension
     *
     * @return array
     */
    public function findAllClasses($extension);
}<?php

namespace Metadata\Driver;

interface FileLocatorInterface
{
    /**
     * @param \ReflectionClass $class
     * @param string           $extension
     *
     * @return string|null
     */
    public function findFileForClass(\ReflectionClass $class, $extension);
}
<?php

namespace Metadata\Driver;

/**
 * Base file driver implementation.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
abstract class AbstractFileDriver implements AdvancedDriverInterface
{
    /**
     * @var FileLocatorInterface|FileLocator
     */
    private $locator;

    public function __construct(FileLocatorInterface $locator)
    {
        $this->locator = $locator;
    }

    public function loadMetadataForClass(\ReflectionClass $class)
    {
        if (null === $path = $this->locator->findFileForClass($class, $this->getExtension())) {
            return null;
        }

        return $this->loadMetadataFromFile($class, $path);
    }

    /**
     * {@inheritDoc}
     */
    public function getAllClassNames()
    {
        if (!$this->locator instanceof AdvancedFileLocatorInterface) {
            throw new \RuntimeException('Locator "%s" must be an instance of "AdvancedFileLocatorInterface".');
        }

        return $this->locator->findAllClasses($this->getExtension());
    }

    /**
     * Parses the content of the file, and converts it to the desired metadata.
     *
     * @param \ReflectionClass $class
     * @param string           $file
     *
     * @return \MetaData\ClassMetadata|null
     */
    abstract protected function loadMetadataFromFile(\ReflectionClass $class, $file);

    /**
     * Returns the extension of the file.
     *
     * @return string
     */
    abstract protected function getExtension();
}
<?php

namespace Metadata\Driver;

class FileLocator implements AdvancedFileLocatorInterface
{
    private $dirs;

    public function __construct(array $dirs)
    {
        $this->dirs = $dirs;
    }

    public function getDirs()
    {
        return $this->dirs;
    }

    /**
     * @param \ReflectionClass $class
     * @param string           $extension
     *
     * @return string|null
     */
    public function findFileForClass(\ReflectionClass $class, $extension)
    {
        foreach ($this->dirs as $prefix => $dir) {
            if ('' !== $prefix && 0 !== strpos($class->getNamespaceName(), $prefix)) {
                continue;
            }

            $len = '' === $prefix ? 0 : strlen($prefix) + 1;
            $path = $dir.'/'.str_replace('\\', '.', substr($class->name, $len)).'.'.$extension;
            if (file_exists($path)) {
                return $path;
            }
        }

        return null;
    }

    /**
     * {@inheritDoc}
     */
    public function findAllClasses($extension)
    {
        $classes = array();
        foreach ($this->dirs as $prefix => $dir) {
            /** @var $iterator \RecursiveIteratorIterator|\SplFileInfo[] */
            $iterator = new \RecursiveIteratorIterator(
                new \RecursiveDirectoryIterator($dir),
                \RecursiveIteratorIterator::LEAVES_ONLY
            );
            $nsPrefix = $prefix !== '' ? $prefix.'\\' : '';
            foreach ($iterator as $file) {
                if (($fileName = $file->getBasename('.'.$extension)) == $file->getBasename()) {
                    continue;
                }

                $classes[] = $nsPrefix.str_replace('.', '\\', $fileName);
            }
        }

        return $classes;
    }
}
<?php

/*
 * Copyright 2011 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Metadata\Driver;

/**
 * Forces advanced logic to drivers.
 *
 * @author Jordan Stout <j@jrdn.org>
 */
interface AdvancedDriverInterface extends DriverInterface
{
    /**
     * Gets all the metadata class names known to this driver.
     *
     * @return array
     */
    public function getAllClassNames();
}<?php

/*
 * Copyright 2011 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace Metadata;

/**
 * Interface for Metadata Factory implementations.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface MetadataFactoryInterface
{
    /**
     * Returns the gathered metadata for the given class name.
     *
     * If the drivers return instances of MergeableClassMetadata, these will be
     * merged prior to returning. Otherwise, all metadata for the inheritance
     * hierarchy will be returned as ClassHierarchyMetadata unmerged.
     *
     * If no metadata is available, null is returned.
     *
     * @param string $className
     *
     * @return ClassHierarchyMetadata|MergeableClassMetadata|null
     */
    public function getMetadataForClass($className);
}
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.<?php

namespace Metadata\Tests\Cache;

use Metadata\ClassMetadata;

use Metadata\Cache\FileCache;

class FileCacheTest extends \PHPUnit_Framework_TestCase
{
    public function testLoadEvictPutClassMetadataFromInCache()
    {
        $cache = new FileCache(sys_get_temp_dir());

        $this->assertNull($cache->loadClassMetadataFromCache($refl = new \ReflectionClass('Metadata\Tests\Fixtures\TestObject')));
        $cache->putClassMetadataInCache($metadata = new ClassMetadata('Metadata\Tests\Fixtures\TestObject'));

        $this->assertEquals($metadata, $cache->loadClassMetadataFromCache($refl));

        $cache->evictClassMetadataFromCache($refl);
        $this->assertNull($cache->loadClassMetadataFromCache($refl));
    }
}<?php

namespace Metadata\Tests\Cache;

use Metadata\ClassMetadata;
use Metadata\Cache\DoctrineCacheAdapter;
use Doctrine\Common\Cache\ArrayCache;

class DoctrineCacheAdapterTest extends \PHPUnit_Framework_TestCase
{
    public function setUp()
    {
        if (!interface_exists('Doctrine\Common\Cache\Cache')) {
            $this->markTestSkipped('Doctrine\Common is not installed.');
        }
    }

    public function testLoadEvictPutClassMetadataFromInCache()
    {
        $cache = new DoctrineCacheAdapter('metadata-test', new ArrayCache());

        $this->assertNull($cache->loadClassMetadataFromCache($refl = new \ReflectionClass('Metadata\Tests\Fixtures\TestObject')));
        $cache->putClassMetadataInCache($metadata = new ClassMetadata('Metadata\Tests\Fixtures\TestObject'));

        $this->assertEquals($metadata, $cache->loadClassMetadataFromCache($refl));

        $cache->evictClassMetadataFromCache($refl);
        $this->assertNull($cache->loadClassMetadataFromCache($refl));
    }
}
<?php

namespace Metadata\Tests\Fixtures;

class TestParent extends TestObject
{
}<?php

namespace Metadata\Tests\Fixtures\ComplexHierarchy;

class SubClassB extends BaseClass
{
    private $baz;
}<?php

namespace Metadata\Tests\Fixtures\ComplexHierarchy;

class SubClassA extends BaseClass implements InterfaceA, InterfaceB
{
    private $bar;
}<?php

namespace Metadata\Tests\Fixtures\ComplexHierarchy;

interface InterfaceA
{
}
<?php

namespace Metadata\Tests\Fixtures\ComplexHierarchy;

interface InterfaceB
{
}
<?php

namespace Metadata\Tests\Fixtures\ComplexHierarchy;

abstract class BaseClass implements InterfaceA
{
    private $foo;
}<?php

namespace Metadata\Tests\Fixtures;

class TestObject
{
    private $foo;

    public function getFoo()
    {
        return $this->foo;
    }

    private function setFoo($foo)
    {
        $this->foo = $foo;
    }
}
<?php

namespace Metadata\Tests;

use Metadata\ClassMetadata;

class ClassMetadataTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $metadata = new ClassMetadata('Metadata\Tests\Fixtures\TestObject');

        $this->assertEquals('Metadata\Tests\Fixtures\TestObject', $metadata->name);
        $this->assertEquals('Metadata\Tests\Fixtures\TestObject', $metadata->reflection->name);
    }

    public function testSerializeUnserialize()
    {
        $metadata = new ClassMetadata('Metadata\Tests\Fixtures\TestObject');

        $this->assertEquals($metadata, unserialize(serialize($metadata)));
    }

    public function testIsFresh()
    {
        $ref = new \ReflectionClass('Metadata\Tests\Fixtures\TestObject');
        touch($ref->getFilename());
        sleep(2);

        $metadata = new ClassMetadata($ref->name);
        $metadata->fileResources[] = $ref->getFilename();
        $this->assertTrue($metadata->isFresh());

        sleep(2);
        clearstatcache($ref->getFilename());
        touch($ref->getFilename());
        $this->assertFalse($metadata->isFresh());
    }
}
<?php

namespace Metadata\Tests;

use Metadata\Tests\Fixtures\TestObject;

use Metadata\PropertyMetadata;

class PropertyMetadataTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $metadata = new PropertyMetadata('Metadata\Tests\Fixtures\TestObject', 'foo');

        $this->assertEquals('Metadata\Tests\Fixtures\TestObject', $metadata->class);
        $this->assertEquals('foo', $metadata->name);
        $this->assertEquals(new \ReflectionProperty('Metadata\Tests\Fixtures\TestObject', 'foo'), $metadata->reflection);
    }

    public function testSerializeUnserialize()
    {
        $metadata = new PropertyMetadata('Metadata\Tests\Fixtures\TestObject', 'foo');

        $this->assertEquals($metadata, unserialize(serialize($metadata)));
    }

    public function testSetGetValue()
    {
        $obj = new TestObject();
        $metadata = new PropertyMetadata('Metadata\Tests\Fixtures\TestObject', 'foo');

        $this->assertNull($metadata->getValue($obj));
        $metadata->setValue($obj, 'foo');
        $this->assertEquals('foo', $metadata->getValue($obj));
    }
}<?php

namespace Metadata\Tests;

use Metadata\Tests\Fixtures\TestObject;

use Metadata\MethodMetadata;

class MethodMetadataTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $metadata = new MethodMetadata('Metadata\Tests\Fixtures\TestObject', 'setFoo');

        $this->assertEquals('Metadata\Tests\Fixtures\TestObject', $metadata->class);
        $this->assertEquals('setFoo', $metadata->name);
        $this->assertEquals(new \ReflectionMethod('Metadata\Tests\Fixtures\TestObject', 'setFoo'), $metadata->reflection);
    }

    public function testSerializeUnserialize()
    {
        $metadata = new MethodMetadata('Metadata\Tests\Fixtures\TestObject', 'setFoo');

        $this->assertEquals($metadata, unserialize(serialize($metadata)));
    }

    public function testInvoke()
    {
        $obj = new TestObject();
        $metadata = new MethodMetadata('Metadata\Tests\Fixtures\TestObject', 'setFoo');

        $this->assertNull($obj->getFoo());
        $metadata->invoke($obj, array('foo'));
        $this->assertEquals('foo', $obj->getFoo());
    }
}<?php

namespace Metadata\Tests\Driver;

use Metadata\ClassMetadata;

/**
 * @author Jordan Stout <j@jrdn.org>
 */
class AbstractFileDriverTest extends \PHPUnit_Framework_TestCase
{
    private static $extension = 'jms_metadata.yml';

    /** @var \PHPUnit_Framework_MockObject_MockObject */
    private $locator;

    /** @var \PHPUnit_Framework_MockObject_MockObject */
    private $driver;

    public function setUp()
    {
        $this->locator = $this->getMock('Metadata\Driver\FileLocator', array(), array(), '', false);
        $this->driver = $this->getMockBuilder('Metadata\Driver\AbstractFileDriver')
            ->setConstructorArgs(array($this->locator))
            ->getMockForAbstractClass();

        $this->driver->expects($this->any())->method('getExtension')->will($this->returnValue(self::$extension));
    }

    public function testLoadMetadataForClass()
    {
        $class = new \ReflectionClass('\stdClass');
        $this->locator
            ->expects($this->once())
            ->method('findFileForClass')
            ->with($class, self::$extension)
            ->will($this->returnValue('Some\Path'));

        $this->driver
            ->expects($this->once())
            ->method('loadMetadataFromFile')
            ->with($class, 'Some\Path')
            ->will($this->returnValue($metadata = new ClassMetadata('\stdClass')));

        $this->assertSame($metadata, $this->driver->loadMetadataForClass($class));
    }

    public function testLoadMetadataForClassWillReturnNull()
    {
        $class = new \ReflectionClass('\stdClass');
        $this->locator
            ->expects($this->once())
            ->method('findFileForClass')
            ->with($class, self::$extension)
            ->will($this->returnValue(null));

        $this->assertSame(null, $this->driver->loadMetadataForClass($class));
    }

    public function testGetAllClassNames()
    {
        $class = new \ReflectionClass('\stdClass');
        $this->locator
            ->expects($this->once())
            ->method('findAllClasses')
            ->with(self::$extension)
            ->will($this->returnValue(array('\stdClass')));

        $this->assertSame(array('\stdClass'), $this->driver->getAllClassNames($class));
    }

    public function testGetAllClassNamesThrowsRuntimeException()
    {
        $this->setExpectedException('RuntimeException');

        $locator = $this->getMock('Metadata\Driver\FileLocatorInterface', array(), array(), '', false);
        $driver = $this->getMockBuilder('Metadata\Driver\AbstractFileDriver')
            ->setConstructorArgs(array($locator))
            ->getMockForAbstractClass();
        $class = new \ReflectionClass('\stdClass');
        $locator->expects($this->never())->method('findAllClasses');

        $driver->getAllClassNames($class);
    }
}
<?php

namespace Metadata\Tests\Driver\Fixture\B;

class B { }<?php

namespace Metadata\Tests\Driver\Fixture\C\SubDir;

class C { }<?php

class D { }
<?php

namespace Metadata\Tests\Driver\Fixture\T;

trait T {}
<?php

namespace Metadata\Tests\Driver\Fixture\A;

class A {}
<?php

namespace Metadata\Tests\Driver;

use Metadata\ClassMetadata;
use Metadata\Driver\DriverChain;

class DriverChainTest extends \PHPUnit_Framework_TestCase
{
    public function testLoadMetadataForClass()
    {
        $driver = $this->getMock('Metadata\\Driver\\DriverInterface');
        $driver
            ->expects($this->once())
            ->method('loadMetadataForClass')
            ->will($this->returnValue($metadata = new ClassMetadata('\stdClass')))
        ;
        $chain = new DriverChain(array($driver));

        $this->assertSame($metadata, $chain->loadMetadataForClass(new \ReflectionClass('\stdClass')));
    }

    public function testGetAllClassNames()
    {
        $driver1 = $this->getMock('Metadata\\Driver\\AdvancedDriverInterface');
        $driver1
            ->expects($this->once())
            ->method('getAllClassNames')
            ->will($this->returnValue(array('Foo')));

        $driver2 = $this->getMock('Metadata\\Driver\\AdvancedDriverInterface');
        $driver2
            ->expects($this->once())
            ->method('getAllClassNames')
            ->will($this->returnValue(array('Bar')));

        $chain = new DriverChain(array($driver1, $driver2));

        $this->assertSame(array('Foo', 'Bar'), $chain->getAllClassNames());
    }

    public function testLoadMetadataForClassReturnsNullWhenNoMetadataIsFound()
    {
        $driver = new DriverChain(array());
        $this->assertNull($driver->loadMetadataForClass(new \ReflectionClass('\stdClass')));

        $driver = $this->getMock('Metadata\\Driver\\DriverInterface');
        $driver
            ->expects($this->once())
            ->method('loadMetadataForClass')
            ->will($this->returnValue(null))
        ;
        $driverChain = new DriverChain(array($driver));
        $this->assertNull($driver->loadMetadataForClass(new \ReflectionClass('\stdClass')));
    }

    public function testGetAllClassNamesThrowsException()
    {
        $this->setExpectedException('RuntimeException');
        $driver = $this->getMock('Metadata\\Driver\\DriverInterface');
        $driver->expects($this->never())->method('getAllClassNames');
        $chain = new DriverChain(array($driver));
        $chain->getAllClassNames();
    }
}
<?php

namespace Metadata\Tests\Driver;

use Metadata\Driver\FileLocator;

class FileLocatorTest extends \PHPUnit_Framework_TestCase
{
    public function testFindFileForClass()
    {
        $locator = new FileLocator(array(
            'Metadata\Tests\Driver\Fixture\A' => __DIR__.'/Fixture/A',
            'Metadata\Tests\Driver\Fixture\B' => __DIR__.'/Fixture/B',
            'Metadata\Tests\Driver\Fixture\C' => __DIR__.'/Fixture/C',
        ));

        $ref = new \ReflectionClass('Metadata\Tests\Driver\Fixture\A\A');
        $this->assertEquals(realpath(__DIR__.'/Fixture/A/A.xml'), realpath($locator->findFileForClass($ref, 'xml')));

        $ref = new \ReflectionClass('Metadata\Tests\Driver\Fixture\B\B');
        $this->assertNull($locator->findFileForClass($ref, 'xml'));

        $ref = new \ReflectionClass('Metadata\Tests\Driver\Fixture\C\SubDir\C');
        $this->assertEquals(realpath(__DIR__.'/Fixture/C/SubDir.C.yml'), realpath($locator->findFileForClass($ref, 'yml')));
    }

    public function testTraits()
    {
        if (version_compare(PHP_VERSION, '5.4.0', '<')) {
            $this->markTestSkipped('No traits available');
        }

        $locator = new FileLocator(array(
            'Metadata\Tests\Driver\Fixture\T' => __DIR__.'/Fixture/T',
        ));

        $ref = new \ReflectionClass('Metadata\Tests\Driver\Fixture\T\T');
        $this->assertEquals(realpath(__DIR__.'/Fixture/T/T.xml'), realpath($locator->findFileForClass($ref, 'xml')));
    }

    public function testFindFileForGlobalNamespacedClass()
    {
        $locator = new FileLocator(array(
            '' => __DIR__.'/Fixture/D',
        ));

        require_once __DIR__.'/Fixture/D/D.php';
        $ref = new \ReflectionClass('D');
        $this->assertEquals(realpath(__DIR__.'/Fixture/D/D.yml'), realpath($locator->findFileForClass($ref, 'yml')));
    }

    public function testFindAllFiles()
    {
        $locator = new FileLocator(array(
            'Metadata\Tests\Driver\Fixture\A' => __DIR__.'/Fixture/A',
            'Metadata\Tests\Driver\Fixture\B' => __DIR__.'/Fixture/B',
            'Metadata\Tests\Driver\Fixture\C' => __DIR__.'/Fixture/C',
            'Metadata\Tests\Driver\Fixture\D' => __DIR__.'/Fixture/D'
        ));

        $this->assertCount(1, $xmlFiles = $locator->findAllClasses('xml'));
        $this->assertSame('Metadata\Tests\Driver\Fixture\A\A', $xmlFiles[0]);

        $this->assertCount(3, $ymlFiles = $locator->findAllClasses('yml'));
        $this->assertSame('Metadata\Tests\Driver\Fixture\B\B', $ymlFiles[0]);
        $this->assertSame('Metadata\Tests\Driver\Fixture\C\SubDir\C', $ymlFiles[1]);
        $this->assertSame('Metadata\Tests\Driver\Fixture\D\D', $ymlFiles[2]);
    }
}
<?php

namespace Metadata\Tests;

use Metadata\PropertyMetadata;
use Metadata\MergeableClassMetadata;
use Metadata\ClassMetadata;
use Metadata\MetadataFactory;

class MetadataFactoryTest extends \PHPUnit_Framework_TestCase
{
    public function testGetMetadataForClass()
    {
        $driver = $this->getMock('Metadata\Driver\DriverInterface');

        $driver
            ->expects($this->at(0))
            ->method('loadMetadataForClass')
            ->with($this->equalTo(new \ReflectionClass('Metadata\Tests\Fixtures\TestObject')))
            ->will($this->returnCallback(function($class) {
                return new ClassMetadata($class->getName());
            }))
        ;
        $driver
            ->expects($this->at(1))
            ->method('loadMetadataForClass')
            ->with($this->equalTo(new \ReflectionClass('Metadata\Tests\Fixtures\TestParent')))
            ->will($this->returnCallback(function($class) {
                return new ClassMetadata($class->getName());
            }))
        ;

        $factory = new MetadataFactory($driver);
        $metadata = $factory->getMetadataForClass('Metadata\Tests\Fixtures\TestParent');

        $this->assertInstanceOf('Metadata\ClassHierarchyMetadata', $metadata);
        $this->assertEquals(2, count($metadata->classMetadata));
    }

    public function testGetMetadataForClassWhenMergeable()
    {
        $driver = $this->getMock('Metadata\Driver\DriverInterface');

        $driver
            ->expects($this->at(0))
            ->method('loadMetadataForClass')
            ->with($this->equalTo(new \ReflectionClass('Metadata\Tests\Fixtures\TestObject')))
            ->will($this->returnCallback(function($class) {
                return new MergeableClassMetadata($class->getName());
            }))
        ;
        $driver
            ->expects($this->at(1))
            ->method('loadMetadataForClass')
            ->with($this->equalTo(new \ReflectionClass('Metadata\Tests\Fixtures\TestParent')))
            ->will($this->returnCallback(function($class) {
                return new MergeableClassMetadata($class->getName());
            }))
        ;

        $factory = new MetadataFactory($driver);
        $metadata = $factory->getMetadataForClass('Metadata\Tests\Fixtures\TestParent');

        $this->assertInstanceOf('Metadata\MergeableClassMetadata', $metadata);
        $this->assertEquals('Metadata\Tests\Fixtures\TestParent', $metadata->name);
    }

    public function testGetMetadataWithComplexHierarchy()
    {
        $driver = $this->getMock('Metadata\Driver\DriverInterface');

        $driver
            ->expects($this->any())
            ->method('loadMetadataForClass')
            ->will($this->returnCallback(function($class) {
                $metadata = new MergeableClassMetadata($class->name);

                switch ($class->name) {
                    case 'Metadata\Tests\Fixtures\ComplexHierarchy\BaseClass':
                        $metadata->propertyMetadata['foo'] = new PropertyMetadata($class->name, 'foo');
                        break;

                    case 'Metadata\Tests\Fixtures\ComplexHierarchy\SubClassA':
                        $metadata->propertyMetadata['bar'] = new PropertyMetadata($class->name, 'bar');
                        break;

                    case 'Metadata\Tests\Fixtures\ComplexHierarchy\SubClassB':
                        $metadata->propertyMetadata['baz'] = new PropertyMetadata($class->name, 'baz');
                        break;

                    default:
                        throw new \RuntimeException(sprintf('Unsupported class "%s".', $class->name));
                }

                return $metadata;
            }))
        ;

        $factory = new MetadataFactory($driver);

        $subClassA = $factory->getMetadataForClass('Metadata\Tests\Fixtures\ComplexHierarchy\SubClassA');
        $this->assertInstanceOf('Metadata\MergeableClassMetadata', $subClassA);
        $this->assertEquals(array('foo', 'bar'), array_keys($subClassA->propertyMetadata));

        $subClassB = $factory->getMetadataForClass('Metadata\Tests\Fixtures\ComplexHierarchy\SubClassB');
        $this->assertInstanceOf('Metadata\MergeableClassMetadata', $subClassB);
        $this->assertEquals(array('foo', 'baz'), array_keys($subClassB->propertyMetadata));
    }

    public function testGetMetadataWithCache()
    {
        $driver = $this->getMock('Metadata\Driver\DriverInterface');
        $driver
            ->expects($this->once())
            ->method('loadMetadataForClass')
            ->will($this->returnValue($metadata = new ClassMetadata('Metadata\Tests\Fixtures\TestObject')))
        ;

        $factory = new MetadataFactory($driver);

        $cache = $this->getMock('Metadata\Cache\CacheInterface');
        $cache
            ->expects($this->once())
            ->method('loadClassMetadataFromCache')
            ->with($this->equalTo(new \ReflectionClass('Metadata\Tests\Fixtures\TestObject')))
            ->will($this->returnValue(null))
        ;
        $cache
            ->expects($this->once())
            ->method('putClassMetadataInCache')
            ->with($this->equalTo($metadata))
        ;
        $factory->setCache($cache);


        $factory->getMetadataForClass('Metadata\Tests\Fixtures\TestObject');
        $factory->getMetadataForClass('Metadata\Tests\Fixtures\TestObject');
        $this->assertSame($metadata, reset($factory->getMetadataForClass('Metadata\Tests\Fixtures\TestObject')->classMetadata));
    }

    public function testGetMetadataReturnsNullIfNoMetadataIsFound()
    {
        $driver = $this->getMock('Metadata\Driver\DriverInterface');
        $driver
            ->expects($this->once())
            ->method('loadMetadataForClass')
            ->will($this->returnValue(null))
        ;

        $factory = new MetadataFactory($driver);

        $this->assertNull($factory->getMetadataForClass('stdClass'));
    }

    public function testGetMetadataWithInterfaces()
    {
        $driver = $this->getMock('Metadata\Driver\DriverInterface');

        $driver
            ->expects($this->at(3))
            ->method('loadMetadataForClass')
            ->with($this->equalTo(new \ReflectionClass('Metadata\Tests\Fixtures\ComplexHierarchy\SubClassA')))
        ;
        $driver
            ->expects($this->at(2))
            ->method('loadMetadataForClass')
            ->with($this->equalTo(new \ReflectionClass('Metadata\Tests\Fixtures\ComplexHierarchy\InterfaceB')))
        ;
        $driver
            ->expects($this->at(1))
            ->method('loadMetadataForClass')
            ->with($this->equalTo(new \ReflectionClass('Metadata\Tests\Fixtures\ComplexHierarchy\BaseClass')))
        ;
        $driver
            ->expects($this->at(0))
            ->method('loadMetadataForClass')
            ->with($this->equalTo(new \ReflectionClass('Metadata\Tests\Fixtures\ComplexHierarchy\InterfaceA')))
        ;

        $factory = new MetadataFactory($driver);
        $factory->setIncludeInterfaces(true);

        $factory->getMetadataForClass('Metadata\Tests\Fixtures\ComplexHierarchy\SubClassA');
    }

    public function testGetAllClassNames()
    {
        $driver = $this->getMock('Metadata\Driver\AdvancedDriverInterface');
        $driver
            ->expects($this->once())
            ->method('getAllClassNames')
            ->will($this->returnValue(array()));

        $factory = new MetadataFactory($driver);
        $this->assertSame(array(), $factory->getAllClassNames());
    }

    public function testGetAllClassNamesThrowsException()
    {
        $this->setExpectedException('RuntimeException');
        $factory = new MetadataFactory($this->getMock('Metadata\Driver\DriverInterface'));
        $factory->getAllClassNames();
    }

    public function testNotFoundMetadataIsCached()
    {
        $driver = $this->getMock('Metadata\Driver\DriverInterface');
        $driver
            ->expects($this->once()) // This is the important part of this test
            ->method('loadMetadataForClass')
            ->will($this->returnValue(null))
        ;

        $cachedMetadata = null;
        $cache = $this->getMock('Metadata\Cache\CacheInterface');
        $cache
            ->expects($this->any())
            ->method('loadClassMetadataFromCache')
            ->with($this->equalTo(new \ReflectionClass('Metadata\Tests\Fixtures\TestObject')))
            ->will($this->returnCallback(function () use (&$cachedMetadata) {
                return $cachedMetadata;
            }))
        ;
        $cache
            ->expects($this->once())
            ->method('putClassMetadataInCache')
            ->will($this->returnCallback(function ($metadata) use (&$cachedMetadata) {
                $cachedMetadata = $metadata;
            }))
        ;

        $factory = new MetadataFactory($driver);
        $factory->setCache($cache);
        $factory->getMetadataForClass('Metadata\Tests\Fixtures\TestObject');
        $factory->getMetadataForClass('Metadata\Tests\Fixtures\TestObject');
        $this->assertNull($factory->getMetadataForClass('Metadata\Tests\Fixtures\TestObject'));

        // We use another factory with the same cache, to simulate another request and skip the in memory
        $factory = new MetadataFactory($driver);
        $factory->setCache($cache);
        $factory->getMetadataForClass('Metadata\Tests\Fixtures\TestObject');
        $factory->getMetadataForClass('Metadata\Tests\Fixtures\TestObject');
        $this->assertNull($factory->getMetadataForClass('Metadata\Tests\Fixtures\TestObject'));
    }

    public function testNotFoundMetadataIsNotCachedInDebug()
    {
        $driver = $this->getMock('Metadata\Driver\DriverInterface');
        $driver
            ->expects($this->exactly(2))
            ->method('loadMetadataForClass')
            ->will($this->returnValue(null))
        ;

        $cachedMetadata = null;
        $cache = $this->getMock('Metadata\Cache\CacheInterface');
        $cache
            ->expects($this->any())
            ->method('loadClassMetadataFromCache')
            ->with($this->equalTo(new \ReflectionClass('Metadata\Tests\Fixtures\TestObject')))
            ->will($this->returnValue(null))
        ;
        $cache
            ->expects($this->never())
            ->method('putClassMetadataInCache')
        ;

        $factory = new MetadataFactory($driver, 'Metadata\ClassHierarchyMetadata', true);
        $factory->setCache($cache);
        $factory->getMetadataForClass('Metadata\Tests\Fixtures\TestObject');
        $this->assertNull($factory->getMetadataForClass('Metadata\Tests\Fixtures\TestObject'));

        // We use another factory with the same cache, to simulate another request and skip the in memory
        $factory = new MetadataFactory($driver, 'Metadata\ClassHierarchyMetadata', true);
        $factory->setCache($cache);
        $factory->getMetadataForClass('Metadata\Tests\Fixtures\TestObject');
        $this->assertNull($factory->getMetadataForClass('Metadata\Tests\Fixtures\TestObject'));
    }
}
<?php

namespace Metadata\Tests;

use Metadata\MergeableClassMetadata;
use Metadata\ClassMetadata;

class MergeableClassMetadataTest extends \PHPUnit_Framework_TestCase
{
    public function testMerge()
    {
        $parentMetadata = new MergeableClassMetadata('Metadata\Tests\Fixtures\TestParent');
        $parentMetadata->propertyMetadata['foo'] = 'bar';
        $parentMetadata->propertyMetadata['baz'] = 'baz';
        $parentMetadata->methodMetadata['foo'] = 'bar';
        $parentMetadata->createdAt = 2;
        $parentMetadata->fileResources[] = 'foo';

        $childMetadata = new MergeableClassMetadata('Metadata\Tests\Fixtures\TestObject');
        $childMetadata->propertyMetadata['foo'] = 'baz';
        $childMetadata->methodMetadata['foo'] = 'baz';
        $childMetadata->createdAt = 1;
        $childMetadata->fileResources[] = 'bar';

        $parentMetadata->merge($childMetadata);
        $this->assertEquals('Metadata\Tests\Fixtures\TestObject', $parentMetadata->name);
        $this->assertEquals('Metadata\Tests\Fixtures\TestObject', $parentMetadata->reflection->name);
        $this->assertEquals(array('foo' => 'baz', 'baz' => 'baz',), $parentMetadata->propertyMetadata);
        $this->assertEquals(array('foo' => 'baz',), $parentMetadata->methodMetadata);
        $this->assertEquals(1, $parentMetadata->createdAt);
        $this->assertEquals(array('foo', 'bar'), $parentMetadata->fileResources);
    }
}<?php

/*
 * This file is part of the Metadata library.
 *
 *    (C) 2011 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 */

spl_autoload_register(function($class) {
    if (0 === strpos($class, 'Metadata\Tests\\')) {
        $path = __DIR__.'/../tests/'.strtr($class, '\\', '/').'.php';
        if (file_exists($path) && is_readable($path)) {
            require_once $path;

            return true;
        }
    } elseif (0 === strpos($class, 'Metadata\\')) {
        $path = __DIR__.'/../src/'.($class = strtr($class, '\\', '/')).'.php';
        if (file_exists($path) && is_readable($path)) {
            require_once $path;

            return true;
        }
    } elseif (0 === strpos($class, 'Symfony\\')) {
        $path = __DIR__.'/../../symfony/src/'.strtr($class, '\\', '/').'.php';

        if (file_exists($path) && is_readable($path)) {
            require_once $path;

            return true;
        }
    }
});

@include __DIR__ . '/../vendor/.composer/autoload.php';
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="tests/bootstrap.php"
>
    <testsuites>
        <testsuite name="Metadata Test Suite">
            <directory>./tests/Metadata/</directory>
        </testsuite>
    </testsuites>
    
    <groups>
        <exclude>
            <group>performance</group>
        </exclude>
    </groups>    
</phpunit>
{
    "name": "phpunit/php-token-stream",
    "description": "Wrapper around PHP's tokenizer extension.",
    "type": "library",
    "keywords": [
        "tokenizer"
    ],
    "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
    "license": "BSD-3-Clause",
    "authors": [
        {
            "name": "Sebastian Bergmann",
            "email": "sb@sebastian-bergmann.de",
            "role": "lead"
        }
    ],
    "support": {
        "issues": "https://github.com/sebastianbergmann/php-token-stream/issues",
        "irc": "irc://irc.freenode.net/phpunit"
    },
    "require": {
        "php": ">=5.3.3",
        "ext-tokenizer": "*"
    },
    "autoload": {
        "classmap": [
            "PHP/"
        ]
    },
    "include-path": [
        ""
    ],
    "extra": {
        "branch-alias": {
            "dev-master": "1.2-dev"
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.4.10" version="2.0"
  xmlns="http://pear.php.net/dtd/package-2.0"
  xmlns:tasks="http://pear.php.net/dtd/tasks-1.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
                      http://pear.php.net/dtd/tasks-1.0.xsd
                      http://pear.php.net/dtd/package-2.0
                      http://pear.php.net/dtd/package-2.0.xsd">
 <name>PHP_TokenStream</name>
 <channel>pear.phpunit.de</channel>
 <summary>Wrapper around PHP's tokenizer extension.</summary>
 <description>Wrapper around PHP's tokenizer extension.</description>
 <lead>
  <name>Sebastian Bergmann</name>
  <user>sb</user>
  <email>sb@sebastian-bergmann.de</email>
  <active>yes</active>
 </lead>
 <date>2013-09-13</date>
 <version>
  <release>1.2.1</release>
  <api>1.2.0</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license>The BSD 3-Clause License</license>
 <notes>http://github.com/sebastianbergmann/php-token-stream/tree</notes>
 <contents>
  <dir name="/">
   <dir name="PHP">
    <dir name="Token">
     <dir name="Stream">
      <file baseinstalldir="/" name="Autoload.php" role="php">
       <tasks:replace from="@package_version@" to="version" type="package-info" />
      </file>
      <file baseinstalldir="/" name="CachingFactory.php" role="php">
       <tasks:replace from="@package_version@" to="version" type="package-info" />
      </file>
     </dir>
     <file baseinstalldir="/" name="Stream.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
    </dir>
    <file baseinstalldir="/" name="Token.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
   </dir>
   <file baseinstalldir="/" name="LICENSE" role="doc"/>
   <file baseinstalldir="/" name="README.md" role="doc"/>
  </dir>
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.3.3</min>
   </php>
   <pearinstaller>
    <min>1.9.4</min>
   </pearinstaller>
   <extension>
    <name>tokenizer</name>
   </extension>
  </required>
 </dependencies>
 <phprelease/>
</package>
<?xml version="1.0"?>

<ruleset name="Sebastian"
         xmlns="http://pmd.sf.net/ruleset/1.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
         xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
  <description>Sebastian Bergmann's ruleset</description>

  <rule ref="rulesets/codesize.xml/CyclomaticComplexity" />
  <rule ref="rulesets/codesize.xml/NPathComplexity" />
  <rule ref="rulesets/codesize.xml/ExcessiveClassComplexity" />
  <rule ref="rulesets/codesize.xml/ExcessiveClassLength" />
  <rule ref="rulesets/codesize.xml/ExcessiveMethodLength" />
  <rule ref="rulesets/codesize.xml/ExcessiveParameterList" />

  <rule ref="rulesets/design.xml/EvalExpression" />
  <rule ref="rulesets/design.xml/ExitExpression" />
  <rule ref="rulesets/design.xml/GotoStatement" />

  <rule ref="rulesets/naming.xml/ConstructorWithNameAsEnclosingClass" />

  <rule ref="rulesets/unusedcode.xml/UnusedFormalParameter" />
  <rule ref="rulesets/unusedcode.xml/UnusedLocalVariable" />
  <rule ref="rulesets/unusedcode.xml/UnusedPrivateField" />
  <rule ref="rulesets/unusedcode.xml/UnusedPrivateMethod" />
</ruleset>
<?php
class PHPCS_Sniffs_ControlStructures_ControlSignatureSniff extends PHP_CodeSniffer_Standards_AbstractPatternSniff
{
    public function __construct()
    {
        parent::__construct(true);
    }

    protected function getPatterns()
    {
        return array(
          'do {EOL...} while (...);EOL',
          'while (...) {EOL',
          'for (...) {EOL',
          'if (...) {EOL',
          'foreach (...) {EOL',
          '}EOLelse if (...) {EOL',
          '}EOLelse {EOL',
          'do {EOL',
        );
    }
}
<?php
class PHPCS_Sniffs_Whitespace_ConcatenationSpacingSniff implements PHP_CodeSniffer_Sniff
{
    public function register()
    {
        return array(T_STRING_CONCAT);
    }

    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE ||
            $tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) {

            $phpcsFile->addError(
              'Concatenation operator must be surrounded by whitespace',
              $stackPtr
            );
        }
    }
}
<?xml version="1.0"?>
<ruleset name="Sebastian">
 <description>Sebastian Bergmann's coding standard</description>

 <rule ref="Generic.CodeAnalysis.ForLoopShouldBeWhileLoop"/>
 <rule ref="Generic.CodeAnalysis.ForLoopWithTestFunctionCall"/>
 <rule ref="Generic.CodeAnalysis.JumbledIncrementer"/>
 <rule ref="Generic.CodeAnalysis.UnconditionalIfStatement"/>
 <rule ref="Generic.CodeAnalysis.UnnecessaryFinalModifier"/>
 <rule ref="Generic.CodeAnalysis.UselessOverridingMethod"/>

 <rule ref="Generic.Commenting.Todo"/>

 <rule ref="Generic.ControlStructures.InlineControlStructure"/>

 <rule ref="Generic.Files.LineEndings"/>

 <rule ref="Generic.Formatting.DisallowMultipleStatements"/>
 <rule ref="Generic.Formatting.NoSpaceAfterCast"/>

 <rule ref="Generic.Functions.OpeningFunctionBraceBsdAllman"/>
 <rule ref="PEAR.Functions.ValidDefaultValue"/>

 <rule ref="Generic.NamingConventions.ConstructorName"/>
 <rule ref="Generic.NamingConventions.UpperCaseConstantName"/>
 <rule ref="PEAR.NamingConventions.ValidClassName"/>

 <rule ref="Generic.PHP.DisallowShortOpenTag"/>
 <rule ref="Generic.PHP.NoSilencedErrors"/>
 <rule ref="Generic.PHP.UpperCaseConstant"/>

 <rule ref="Generic.WhiteSpace.DisallowTabIndent"/>
 <rule ref="Generic.WhiteSpace.ScopeIndent"/>
 <rule ref="Squiz.WhiteSpace.SuperfluousWhitespace"/>
</ruleset>
PHP_TokenStream

Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

 * Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in
   the documentation and/or other materials provided with the
   distribution.

 * Neither the name of Sebastian Bergmann nor the names of his
   contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
<?xml version="1.0" encoding="UTF-8"?>

<project name="PHP_TokenStream" default="build">
 <property name="php" value="php"/>
 <property name="phpunit" value="phpunit"/>

 <target name="build"
   depends="prepare,lint,phploc,pdepend,phpmd-ci,phpcs-ci,phpcpd,phpunit,phpcb"/>

 <target name="build-parallel"
   depends="prepare,lint,tools-parallel,phpunit,phpcb"/>

 <target name="tools-parallel"
         description="Run tools in parallel">
  <parallel threadCount="2">
   <sequential>
    <antcall target="pdepend"/>
    <antcall target="phpmd-ci"/>
   </sequential>
   <antcall target="phpcpd"/>
   <antcall target="phpcs-ci"/>
   <antcall target="phploc"/>
  </parallel>
 </target>

 <target name="clean" description="Cleanup build artifacts">
  <delete dir="${basedir}/build/api"/>
  <delete dir="${basedir}/build/code-browser"/>
  <delete dir="${basedir}/build/coverage"/>
  <delete dir="${basedir}/build/logs"/>
  <delete dir="${basedir}/build/pdepend"/>
 </target>

 <target name="prepare" depends="clean,phpab"
         description="Prepare for build">
  <mkdir dir="${basedir}/build/api"/>
  <mkdir dir="${basedir}/build/code-browser"/>
  <mkdir dir="${basedir}/build/coverage"/>
  <mkdir dir="${basedir}/build/logs"/>
  <mkdir dir="${basedir}/build/pdepend"/>
 </target>

 <target name="phpab" description="Generate autoloader scripts">
  <exec executable="phpab">
   <arg value="--output" />
   <arg path="PHP/Token/Stream/Autoload.php" />
   <arg value="--template" />
   <arg path="PHP/Token/Stream/Autoload.php.in" />
   <arg value="--indent" />
   <arg value="            " />
   <arg path="PHP" />
  </exec>
 </target>

 <target name="lint">
  <apply executable="${php}" failonerror="true">
   <arg value="-l" />

   <fileset dir="${basedir}/PHP">
    <include name="**/*.php" />
    <modified />
   </fileset>

   <fileset dir="${basedir}/Tests">
    <include name="**/*.php" />
    <modified />
   </fileset>
  </apply>
 </target>

 <target name="phploc" description="Measure project size using PHPLOC">
  <exec executable="phploc">
   <arg value="--log-csv" />
   <arg value="${basedir}/build/logs/phploc.csv" />
   <arg path="${basedir}/PHP" />
  </exec>
 </target>

 <target name="pdepend"
         description="Calculate software metrics using PHP_Depend">
  <exec executable="pdepend">
   <arg value="--jdepend-xml=${basedir}/build/logs/jdepend.xml" />
   <arg value="--jdepend-chart=${basedir}/build/pdepend/dependencies.svg" />
   <arg value="--overview-pyramid=${basedir}/build/pdepend/overview-pyramid.svg" />
   <arg path="${basedir}/PHP" />
  </exec>
 </target>

 <target name="phpmd"
         description="Perform project mess detection using PHPMD">
  <exec executable="phpmd">
   <arg path="${basedir}/PHP" />
   <arg value="text" />
   <arg value="${basedir}/build/phpmd.xml" />
  </exec>
 </target>

 <target name="phpmd-ci"
         description="Perform project mess detection using PHPMD">
  <exec executable="phpmd">
   <arg path="${basedir}/PHP" />
   <arg value="xml" />
   <arg value="${basedir}/build/phpmd.xml" />
   <arg value="--reportfile" />
   <arg value="${basedir}/build/logs/pmd.xml" />
  </exec>
 </target>

 <target name="phpcs"
         description="Find coding standard violations using PHP_CodeSniffer">
  <exec executable="phpcs">
   <arg value="--standard=${basedir}/build/PHPCS" />
   <arg value="--extensions=php" />
   <arg value="--ignore=Autoload.php" />
   <arg path="${basedir}/PHP" />
   <arg path="${basedir}/Tests" />
  </exec>
 </target>

 <target name="phpcs-ci"
         description="Find coding standard violations using PHP_CodeSniffer">
  <exec executable="phpcs" output="/dev/null">
   <arg value="--report=checkstyle" />
   <arg value="--report-file=${basedir}/build/logs/checkstyle.xml" />
   <arg value="--standard=${basedir}/build/PHPCS" />
   <arg value="--extensions=php" />
   <arg value="--ignore=Autoload.php" />
   <arg path="${basedir}/PHP" />
   <arg path="${basedir}/Tests" />
  </exec>
 </target>

 <target name="phpcpd" description="Find duplicate code using PHPCPD">
  <exec executable="phpcpd">
   <arg value="--log-pmd" />
   <arg value="${basedir}/build/logs/pmd-cpd.xml" />
   <arg path="${basedir}/PHP" />
  </exec>
 </target>

 <target name="phpunit" description="Run unit tests with PHPUnit">
  <condition property="phpunit_cmd" value="${php} ${phpunit}" else="${phpunit}">
   <not>
    <equals arg1="${phpunit}" arg2="phpunit" />
   </not>
  </condition>

  <exec executable="${phpunit_cmd}" failonerror="true"/>
 </target>

 <target name="phpcb"
         description="Aggregate tool output with PHP_CodeBrowser">
  <exec executable="phpcb">
   <arg value="--log" />
   <arg path="${basedir}/build/logs" />
   <arg value="--source" />
   <arg path="${basedir}/PHP" />
   <arg value="--output" />
   <arg path="${basedir}/build/code-browser" />
  </exec>
 </target>
</project>
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         syntaxCheck="false"
         bootstrap="PHP/Token/Stream/Autoload.php"
         strict="true">
  <testsuites>
    <testsuite name="php-token-stream">
      <directory suffix="Test.php">Tests</directory>
    </testsuite>
  </testsuites>

  <logging>
    <log type="coverage-html" target="build/coverage" title="PHP_TokenStream"
         charset="UTF-8" yui="true" highlight="true"
         lowUpperBound="35" highLowerBound="70"/>
    <log type="coverage-clover" target="build/logs/clover.xml"/>
    <log type="junit" target="build/logs/junit.xml" logIncompleteSkipped="false"/>
  </logging>

  <filter>
    <whitelist addUncoveredFilesFromWhitelist="true">
      <directory suffix=".php">PHP</directory>
    </whitelist>
  </filter>
</phpunit>
<?php
/**
 * php-token-stream
 *
 * Copyright (c) 2009-2010, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package   PHP_TokenStream
 * @author    Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright 2009-2010 Sebastian Bergmann <sebastian@phpunit.de>
 * @license   http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link      http://github.com/sebastianbergmann/php-token-stream/tree
 * @since     File available since Release 1.1.0
 */

spl_autoload_register(
  function ($class)
  {
      static $classes = NULL;
      static $path = NULL;;

      if ($classes === NULL) {
          $classes = array(
            'php_token' => '/Token.php',
            'php_token_abstract' => '/Token.php',
            'php_token_ampersand' => '/Token.php',
            'php_token_and_equal' => '/Token.php',
            'php_token_array' => '/Token.php',
            'php_token_array_cast' => '/Token.php',
            'php_token_as' => '/Token.php',
            'php_token_at' => '/Token.php',
            'php_token_backtick' => '/Token.php',
            'php_token_bad_character' => '/Token.php',
            'php_token_bool_cast' => '/Token.php',
            'php_token_boolean_and' => '/Token.php',
            'php_token_boolean_or' => '/Token.php',
            'php_token_break' => '/Token.php',
            'php_token_callable' => '/Token.php',
            'php_token_caret' => '/Token.php',
            'php_token_case' => '/Token.php',
            'php_token_catch' => '/Token.php',
            'php_token_character' => '/Token.php',
            'php_token_class' => '/Token.php',
            'php_token_class_c' => '/Token.php',
            'php_token_clone' => '/Token.php',
            'php_token_close_bracket' => '/Token.php',
            'php_token_close_curly' => '/Token.php',
            'php_token_close_square' => '/Token.php',
            'php_token_close_tag' => '/Token.php',
            'php_token_colon' => '/Token.php',
            'php_token_comma' => '/Token.php',
            'php_token_comment' => '/Token.php',
            'php_token_concat_equal' => '/Token.php',
            'php_token_const' => '/Token.php',
            'php_token_constant_encapsed_string' => '/Token.php',
            'php_token_continue' => '/Token.php',
            'php_token_curly_open' => '/Token.php',
            'php_token_dec' => '/Token.php',
            'php_token_declare' => '/Token.php',
            'php_token_default' => '/Token.php',
            'php_token_dir' => '/Token.php',
            'php_token_div' => '/Token.php',
            'php_token_div_equal' => '/Token.php',
            'php_token_dnumber' => '/Token.php',
            'php_token_do' => '/Token.php',
            'php_token_doc_comment' => '/Token.php',
            'php_token_dollar' => '/Token.php',
            'php_token_dollar_open_curly_braces' => '/Token.php',
            'php_token_dot' => '/Token.php',
            'php_token_double_arrow' => '/Token.php',
            'php_token_double_cast' => '/Token.php',
            'php_token_double_colon' => '/Token.php',
            'php_token_double_quotes' => '/Token.php',
            'php_token_echo' => '/Token.php',
            'php_token_else' => '/Token.php',
            'php_token_elseif' => '/Token.php',
            'php_token_empty' => '/Token.php',
            'php_token_encapsed_and_whitespace' => '/Token.php',
            'php_token_end_heredoc' => '/Token.php',
            'php_token_enddeclare' => '/Token.php',
            'php_token_endfor' => '/Token.php',
            'php_token_endforeach' => '/Token.php',
            'php_token_endif' => '/Token.php',
            'php_token_endswitch' => '/Token.php',
            'php_token_endwhile' => '/Token.php',
            'php_token_equal' => '/Token.php',
            'php_token_eval' => '/Token.php',
            'php_token_exclamation_mark' => '/Token.php',
            'php_token_exit' => '/Token.php',
            'php_token_extends' => '/Token.php',
            'php_token_file' => '/Token.php',
            'php_token_final' => '/Token.php',
            'php_token_for' => '/Token.php',
            'php_token_foreach' => '/Token.php',
            'php_token_func_c' => '/Token.php',
            'php_token_function' => '/Token.php',
            'php_token_global' => '/Token.php',
            'php_token_goto' => '/Token.php',
            'php_token_gt' => '/Token.php',
            'php_token_halt_compiler' => '/Token.php',
            'php_token_if' => '/Token.php',
            'php_token_implements' => '/Token.php',
            'php_token_inc' => '/Token.php',
            'php_token_include' => '/Token.php',
            'php_token_include_once' => '/Token.php',
            'php_token_includes' => '/Token.php',
            'php_token_inline_html' => '/Token.php',
            'php_token_instanceof' => '/Token.php',
            'php_token_insteadof' => '/Token.php',
            'php_token_int_cast' => '/Token.php',
            'php_token_interface' => '/Token.php',
            'php_token_is_equal' => '/Token.php',
            'php_token_is_greater_or_equal' => '/Token.php',
            'php_token_is_identical' => '/Token.php',
            'php_token_is_not_equal' => '/Token.php',
            'php_token_is_not_identical' => '/Token.php',
            'php_token_is_smaller_or_equal' => '/Token.php',
            'php_token_isset' => '/Token.php',
            'php_token_line' => '/Token.php',
            'php_token_list' => '/Token.php',
            'php_token_lnumber' => '/Token.php',
            'php_token_logical_and' => '/Token.php',
            'php_token_logical_or' => '/Token.php',
            'php_token_logical_xor' => '/Token.php',
            'php_token_lt' => '/Token.php',
            'php_token_method_c' => '/Token.php',
            'php_token_minus' => '/Token.php',
            'php_token_minus_equal' => '/Token.php',
            'php_token_mod_equal' => '/Token.php',
            'php_token_mul_equal' => '/Token.php',
            'php_token_mult' => '/Token.php',
            'php_token_namespace' => '/Token.php',
            'php_token_new' => '/Token.php',
            'php_token_ns_c' => '/Token.php',
            'php_token_ns_separator' => '/Token.php',
            'php_token_num_string' => '/Token.php',
            'php_token_object_cast' => '/Token.php',
            'php_token_object_operator' => '/Token.php',
            'php_token_open_bracket' => '/Token.php',
            'php_token_open_curly' => '/Token.php',
            'php_token_open_square' => '/Token.php',
            'php_token_open_tag' => '/Token.php',
            'php_token_open_tag_with_echo' => '/Token.php',
            'php_token_or_equal' => '/Token.php',
            'php_token_paamayim_nekudotayim' => '/Token.php',
            'php_token_percent' => '/Token.php',
            'php_token_pipe' => '/Token.php',
            'php_token_plus' => '/Token.php',
            'php_token_plus_equal' => '/Token.php',
            'php_token_print' => '/Token.php',
            'php_token_private' => '/Token.php',
            'php_token_protected' => '/Token.php',
            'php_token_public' => '/Token.php',
            'php_token_question_mark' => '/Token.php',
            'php_token_require' => '/Token.php',
            'php_token_require_once' => '/Token.php',
            'php_token_return' => '/Token.php',
            'php_token_semicolon' => '/Token.php',
            'php_token_sl' => '/Token.php',
            'php_token_sl_equal' => '/Token.php',
            'php_token_sr' => '/Token.php',
            'php_token_sr_equal' => '/Token.php',
            'php_token_start_heredoc' => '/Token.php',
            'php_token_static' => '/Token.php',
            'php_token_stream' => '/Token/Stream.php',
            'php_token_stream_cachingfactory' => '/Token/Stream/CachingFactory.php',
            'php_token_string' => '/Token.php',
            'php_token_string_cast' => '/Token.php',
            'php_token_string_varname' => '/Token.php',
            'php_token_switch' => '/Token.php',
            'php_token_throw' => '/Token.php',
            'php_token_tilde' => '/Token.php',
            'php_token_trait' => '/Token.php',
            'php_token_trait_c' => '/Token.php',
            'php_token_try' => '/Token.php',
            'php_token_unset' => '/Token.php',
            'php_token_unset_cast' => '/Token.php',
            'php_token_use' => '/Token.php',
            'php_token_var' => '/Token.php',
            'php_token_variable' => '/Token.php',
            'php_token_while' => '/Token.php',
            'php_token_whitespace' => '/Token.php',
            'php_token_xor_equal' => '/Token.php',
            'php_tokenwithscope' => '/Token.php',
            'php_tokenwithscopeandvisibility' => '/Token.php'
          );

          $path = dirname(dirname(dirname(__FILE__)));
      }

      $cn = strtolower($class);

      if (isset($classes[$cn])) {
          require $path . $classes[$cn];
      }
  }
);
<?php
/**
 * php-token-stream
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package   PHP_TokenStream
 * @author    Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright 2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license   http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @since     File available since Release 1.0.0
 */

/**
 * A caching factory for token stream objects.
 *
 * @author    Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright 2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license   http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version   Release: @package_version@
 * @link      http://github.com/sebastianbergmann/php-token-stream/tree
 * @since     Class available since Release 1.0.0
 */
class PHP_Token_Stream_CachingFactory
{
    /**
     * @var array
     */
    protected static $cache = array();

    /**
     * @param  string $filename
     * @return PHP_Token_Stream
     */
    public static function get($filename)
    {
        if (!isset(self::$cache[$filename])) {
            self::$cache[$filename] = new PHP_Token_Stream($filename);
        }

        return self::$cache[$filename];
    }

    /**
     * @param string $filename
     */
    public static function clear($filename = NULL)
    {
        if (is_string($filename)) {
            unset(self::$cache[$filename]);
        } else {
            self::$cache = array();
        }
    }
}
<?php
/**
 * php-token-stream
 *
 * Copyright (c) 2009-2010, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package   PHP_TokenStream
 * @author    Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright 2009-2010 Sebastian Bergmann <sebastian@phpunit.de>
 * @license   http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link      http://github.com/sebastianbergmann/php-token-stream/tree
 * @since     File available since Release 1.1.0
 */

spl_autoload_register(
  function ($class)
  {
      static $classes = NULL;
      static $path = NULL;;

      if ($classes === NULL) {
          $classes = array(
            ___CLASSLIST___
          );

          $path = dirname(dirname(dirname(__FILE__)));
      }

      $cn = strtolower($class);

      if (isset($classes[$cn])) {
          require $path . $classes[$cn];
      }
  }
);
<?php
/**
 * php-token-stream
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package   PHP_TokenStream
 * @author    Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright 2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license   http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @since     File available since Release 1.0.0
 */

/**
 * A stream of PHP tokens.
 *
 * @author    Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright 2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license   http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version   Release: @package_version@
 * @link      http://github.com/sebastianbergmann/php-token-stream/tree
 * @since     Class available since Release 1.0.0
 */
class PHP_Token_Stream implements ArrayAccess, Countable, SeekableIterator
{
    /**
     * @var array
     */
    protected static $customTokens = array(
      '(' => 'PHP_Token_OPEN_BRACKET',
      ')' => 'PHP_Token_CLOSE_BRACKET',
      '[' => 'PHP_Token_OPEN_SQUARE',
      ']' => 'PHP_Token_CLOSE_SQUARE',
      '{' => 'PHP_Token_OPEN_CURLY',
      '}' => 'PHP_Token_CLOSE_CURLY',
      ';' => 'PHP_Token_SEMICOLON',
      '.' => 'PHP_Token_DOT',
      ',' => 'PHP_Token_COMMA',
      '=' => 'PHP_Token_EQUAL',
      '<' => 'PHP_Token_LT',
      '>' => 'PHP_Token_GT',
      '+' => 'PHP_Token_PLUS',
      '-' => 'PHP_Token_MINUS',
      '*' => 'PHP_Token_MULT',
      '/' => 'PHP_Token_DIV',
      '?' => 'PHP_Token_QUESTION_MARK',
      '!' => 'PHP_Token_EXCLAMATION_MARK',
      ':' => 'PHP_Token_COLON',
      '"' => 'PHP_Token_DOUBLE_QUOTES',
      '@' => 'PHP_Token_AT',
      '&' => 'PHP_Token_AMPERSAND',
      '%' => 'PHP_Token_PERCENT',
      '|' => 'PHP_Token_PIPE',
      '$' => 'PHP_Token_DOLLAR',
      '^' => 'PHP_Token_CARET',
      '~' => 'PHP_Token_TILDE',
      '`' => 'PHP_Token_BACKTICK'
    );

    /**
     * @var string
     */
    protected $filename;

    /**
     * @var array
     */
    protected $tokens = array();

    /**
     * @var integer
     */
    protected $position = 0;

    /**
     * @var array
     */
    protected $linesOfCode = array('loc' => 0, 'cloc' => 0, 'ncloc' => 0);

    /**
     * @var array
     */
    protected $classes;

    /**
     * @var array
     */
    protected $functions;

    /**
     * @var array
     */
    protected $includes;

    /**
     * @var array
     */
    protected $interfaces;

    /**
     * @var array
     */
    protected $traits;

    /**
     * @var array
     */
    protected $lineToFunctionMap = array();

    /**
     * Constructor.
     *
     * @param string $sourceCode
     */
    public function __construct($sourceCode)
    {
        if (is_file($sourceCode)) {
            $this->filename = $sourceCode;
            $sourceCode     = file_get_contents($sourceCode);
        }

        $this->scan($sourceCode);
    }

    /**
     * Destructor.
     */
    public function __destruct()
    {
        $this->tokens = array();
    }

    /**
     * @return string
     */
    public function __toString()
    {
        $buffer = '';

        foreach ($this as $token) {
            $buffer .= $token;
        }

        return $buffer;
    }

    /**
     * @return string
     * @since  Method available since Release 1.1.0
     */
    public function getFilename()
    {
        return $this->filename;
    }

    /**
     * Scans the source for sequences of characters and converts them into a
     * stream of tokens.
     *
     * @param string $sourceCode
     */
    protected function scan($sourceCode)
    {
        $line      = 1;
        $tokens    = token_get_all($sourceCode);
        $numTokens = count($tokens);

        $lastNonWhitespaceTokenWasDoubleColon = FALSE;

        for ($i = 0; $i < $numTokens; ++$i) {
            $token = $tokens[$i];
            unset($tokens[$i]);

            if (is_array($token)) {
                $name = substr(token_name($token[0]), 2);
                $text = $token[1];

                if ($lastNonWhitespaceTokenWasDoubleColon && $name == 'CLASS') {
                    $name = 'CLASS_NAME_CONSTANT';
                }

                $tokenClass = 'PHP_Token_' . $name;
            } else {
                $text       = $token;
                $tokenClass = self::$customTokens[$token];
            }

            $this->tokens[] = new $tokenClass($text, $line, $this, $i);
            $lines          = substr_count($text, "\n");
            $line          += $lines;

            if ($tokenClass == 'PHP_Token_HALT_COMPILER') {
                break;
            }

            else if ($tokenClass == 'PHP_Token_COMMENT' ||
                $tokenClass == 'PHP_Token_DOC_COMMENT') {
                $this->linesOfCode['cloc'] += $lines + 1;
            }

            if ($name == 'DOUBLE_COLON') {
                $lastNonWhitespaceTokenWasDoubleColon = TRUE;
            }

            else if ($name != 'WHITESPACE') {
                $lastNonWhitespaceTokenWasDoubleColon = FALSE;
            }
        }

        $this->linesOfCode['loc']   = substr_count($sourceCode, "\n");
        $this->linesOfCode['ncloc'] = $this->linesOfCode['loc'] -
                                      $this->linesOfCode['cloc'];
    }

    /**
     * @return integer
     */
    public function count()
    {
        return count($this->tokens);
    }

    /**
     * @return PHP_Token[]
     */
    public function tokens()
    {
        return $this->tokens;
    }

    /**
     * @return array
     */
    public function getClasses()
    {
        if ($this->classes !== NULL) {
            return $this->classes;
        }

        $this->parse();

        return $this->classes;
    }

    /**
     * @return array
     */
    public function getFunctions()
    {
        if ($this->functions !== NULL) {
            return $this->functions;
        }

        $this->parse();

        return $this->functions;
    }

    /**
     * @return array
     */
    public function getInterfaces()
    {
        if ($this->interfaces !== NULL) {
            return $this->interfaces;
        }

        $this->parse();

        return $this->interfaces;
    }

    /**
     * @return array
     * @since  Method available since Release 1.1.0
     */
    public function getTraits()
    {
        if ($this->traits !== NULL) {
            return $this->traits;
        }

        $this->parse();

        return $this->traits;
    }

    /**
     * Gets the names of all files that have been included
     * using include(), include_once(), require() or require_once().
     *
     * Parameter $categorize set to TRUE causing this function to return a
     * multi-dimensional array with categories in the keys of the first dimension
     * and constants and their values in the second dimension.
     *
     * Parameter $category allow to filter following specific inclusion type
     *
     * @param bool   $categorize OPTIONAL
     * @param string $category   OPTIONAL Either 'require_once', 'require',
     *                                           'include_once', 'include'.
     * @return array
     * @since  Method available since Release 1.1.0
     */
    public function getIncludes($categorize = FALSE, $category = NULL)
    {
        if ($this->includes === NULL) {
            $this->includes = array(
              'require_once' => array(),
              'require'      => array(),
              'include_once' => array(),
              'include'      => array()
            );

            foreach ($this->tokens as $token) {
                switch (get_class($token)) {
                    case 'PHP_Token_REQUIRE_ONCE':
                    case 'PHP_Token_REQUIRE':
                    case 'PHP_Token_INCLUDE_ONCE':
                    case 'PHP_Token_INCLUDE': {
                        $this->includes[$token->getType()][] = $token->getName();
                    }
                    break;
                }
            }
        }

        if (isset($this->includes[$category])) {
            $includes = $this->includes[$category];
        }

        else if ($categorize === FALSE) {
            $includes = array_merge(
              $this->includes['require_once'],
              $this->includes['require'],
              $this->includes['include_once'],
              $this->includes['include']
            );
        } else {
            $includes = $this->includes;
        }

        return $includes;
    }

    /**
     * Returns the name of the function or method a line belongs to.
     *
     * @return string or null if the line is not in a function or method
     * @since  Method available since Release 1.2.0
     */
    public function getFunctionForLine($line)
    {
        $this->parse();

        if (isset($this->lineToFunctionMap[$line])) {
            return $this->lineToFunctionMap[$line];
        }
    }

    protected function parse()
    {
        $this->interfaces = array();
        $this->classes    = array();
        $this->traits     = array();
        $this->functions  = array();
        $class            = FALSE;
        $classEndLine     = FALSE;
        $trait            = FALSE;
        $traitEndLine     = FALSE;
        $interface        = FALSE;
        $interfaceEndLine = FALSE;

        foreach ($this->tokens as $token) {
            switch (get_class($token)) {
                case 'PHP_Token_HALT_COMPILER': {
                    return;
                }
                break;

                case 'PHP_Token_INTERFACE': {
                    $interface        = $token->getName();
                    $interfaceEndLine = $token->getEndLine();

                    $this->interfaces[$interface] = array(
                      'methods'   => array(),
                      'parent'    => $token->getParent(),
                      'keywords'  => $token->getKeywords(),
                      'docblock'  => $token->getDocblock(),
                      'startLine' => $token->getLine(),
                      'endLine'   => $interfaceEndLine,
                      'package'   => $token->getPackage(),
                      'file'      => $this->filename
                    );
                }
                break;

                case 'PHP_Token_CLASS':
                case 'PHP_Token_TRAIT': {
                    $tmp = array(
                      'methods'   => array(),
                      'parent'    => $token->getParent(),
                      'interfaces'=> $token->getInterfaces(),
                      'keywords'  => $token->getKeywords(),
                      'docblock'  => $token->getDocblock(),
                      'startLine' => $token->getLine(),
                      'endLine'   => $token->getEndLine(),
                      'package'   => $token->getPackage(),
                      'file'      => $this->filename
                    );

                    if ($token instanceof PHP_Token_CLASS) {
                        $class                 = $token->getName();
                        $classEndLine          = $token->getEndLine();
                        $this->classes[$class] = $tmp;
                    } else {
                        $trait                = $token->getName();
                        $traitEndLine         = $token->getEndLine();
                        $this->traits[$trait] = $tmp;
                    }
                }
                break;

                case 'PHP_Token_FUNCTION': {
                    $name = $token->getName();
                    $tmp  = array(
                      'docblock'  => $token->getDocblock(),
                      'keywords'  => $token->getKeywords(),
                      'visibility'=> $token->getVisibility(),
                      'signature' => $token->getSignature(),
                      'startLine' => $token->getLine(),
                      'endLine'   => $token->getEndLine(),
                      'ccn'       => $token->getCCN(),
                      'file'      => $this->filename
                    );

                    if ($class === FALSE &&
                        $trait === FALSE &&
                        $interface === FALSE) {
                        $this->functions[$name] = $tmp;

                        $this->addFunctionToMap(
                          $name, $tmp['startLine'], $tmp['endLine']
                        );
                    }

                    else if ($class !== FALSE) {
                        $this->classes[$class]['methods'][$name] = $tmp;

                        $this->addFunctionToMap(
                          $class . '::' . $name,
                          $tmp['startLine'],
                          $tmp['endLine']
                        );
                    }

                    else if ($trait !== FALSE) {
                        $this->traits[$trait]['methods'][$name] = $tmp;

                        $this->addFunctionToMap(
                          $trait . '::' . $name,
                          $tmp['startLine'],
                          $tmp['endLine']
                        );
                    }

                    else {
                        $this->interfaces[$interface]['methods'][$name] = $tmp;
                    }
                }
                break;

                case 'PHP_Token_CLOSE_CURLY': {
                    if ($classEndLine !== FALSE &&
                        $classEndLine == $token->getLine()) {
                        $class        = FALSE;
                        $classEndLine = FALSE;
                    }

                    else if ($traitEndLine !== FALSE &&
                        $traitEndLine == $token->getLine()) {
                        $trait        = FALSE;
                        $traitEndLine = FALSE;
                    }

                    else if ($interfaceEndLine !== FALSE &&
                        $interfaceEndLine == $token->getLine()) {
                        $interface        = FALSE;
                        $interfaceEndLine = FALSE;
                    }
                }
                break;
            }
        }
    }

    /**
     * @return array
     */
    public function getLinesOfCode()
    {
        return $this->linesOfCode;
    }

    /**
     */
    public function rewind()
    {
        $this->position = 0;
    }

    /**
     * @return boolean
     */
    public function valid()
    {
        return isset($this->tokens[$this->position]);
    }

    /**
     * @return integer
     */
    public function key()
    {
        return $this->position;
    }

    /**
     * @return PHP_Token
     */
    public function current()
    {
        return $this->tokens[$this->position];
    }

    /**
     */
    public function next()
    {
        $this->position++;
    }

    /**
     * @param mixed $offset
     */
    public function offsetExists($offset)
    {
        return isset($this->tokens[$offset]);
    }

    /**
     * @param  mixed $offset
     * @return mixed
     */
    public function offsetGet($offset)
    {
        return $this->tokens[$offset];
    }

    /**
     * @param mixed $offset
     * @param mixed $value
     */
    public function offsetSet($offset, $value)
    {
        $this->tokens[$offset] = $value;
    }

    /**
     * @param mixed $offset
     */
    public function offsetUnset($offset)
    {
        unset($this->tokens[$offset]);
    }

    /**
     * Seek to an absolute position.
     *
     * @param  integer $position
     * @throws OutOfBoundsException
     */
    public function seek($position)
    {
        $this->position = $position;

        if (!$this->valid()) {
            throw new OutOfBoundsException('Invalid seek position');
        }
    }

    private function addFunctionToMap($name, $startLine, $endLine)
    {
        for ($line = $startLine; $line <= $endLine; $line++) {
            $this->lineToFunctionMap[$line] = $name;
        }
    }
}
<?php
/**
 * php-token-stream
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package   PHP_TokenStream
 * @author    Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright 2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license   http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @since     File available since Release 1.0.0
 */

/**
 * A PHP token.
 *
 * @author    Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright 2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license   http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version   Release: @package_version@
 * @link      http://github.com/sebastianbergmann/php-token-stream/tree
 * @since     Class available since Release 1.0.0
 */
abstract class PHP_Token
{
    /**
     * @var string
     */
    protected $text;

    /**
     * @var integer
     */
    protected $line;

    /**
     * @var PHP_Token_Stream
     */
    protected $tokenStream;

    /**
     * @var integer
     */
    protected $id;

    /**
     * Constructor.
     *
     * @param string           $text
     * @param integer          $line
     * @param PHP_Token_Stream $tokenStream
     * @param integer          $id
     */
    public function __construct($text, $line, PHP_Token_Stream $tokenStream, $id)
    {
        $this->text        = $text;
        $this->line        = $line;
        $this->tokenStream = $tokenStream;
        $this->id          = $id;
    }

    /**
     * @return string
     */
    public function __toString()
    {
        return $this->text;
    }

    /**
     * @return integer
     */
    public function getLine()
    {
        return $this->line;
    }
}

abstract class PHP_TokenWithScope extends PHP_Token
{
    protected $endTokenId;

    /**
     * Get the docblock for this token
     *
     * This method will fetch the docblock belonging to the current token. The
     * docblock must be placed on the line directly above the token to be
     * recognized.
     *
     * @return string|null Returns the docblock as a string if found
     */
    public function getDocblock()
    {
        $tokens            = $this->tokenStream->tokens();
        $currentLineNumber = $tokens[$this->id]->getLine();
        $prevLineNumber    = $currentLineNumber - 1;

        for ($i = $this->id - 1; $i; $i--) {
            if (!isset($tokens[$i])) {
                return;
            }

            if ($tokens[$i] instanceof PHP_Token_FUNCTION ||
                $tokens[$i] instanceof PHP_Token_CLASS ||
                $tokens[$i] instanceof PHP_Token_TRAIT) {
                // Some other trait, class or function, no docblock can be
                // used for the current token
                break;
            }

            $line = $tokens[$i]->getLine();

            if ($line == $currentLineNumber ||
                ($line == $prevLineNumber &&
                 $tokens[$i] instanceof PHP_Token_WHITESPACE)) {
                continue;
            }

            if ($line < $currentLineNumber &&
                !$tokens[$i] instanceof PHP_Token_DOC_COMMENT) {
                break;
            }

            return (string)$tokens[$i];
        }
    }

    public function getEndTokenId()
    {
        $block  = 0;
        $i      = $this->id;
        $tokens = $this->tokenStream->tokens();

        while ($this->endTokenId === NULL && isset($tokens[$i])) {
            if ($tokens[$i] instanceof PHP_Token_OPEN_CURLY ||
                $tokens[$i] instanceof PHP_Token_CURLY_OPEN) {
                $block++;
            }

            else if ($tokens[$i] instanceof PHP_Token_CLOSE_CURLY) {
                $block--;

                if ($block === 0) {
                    $this->endTokenId = $i;
                }
            }

            else if (($this instanceof PHP_Token_FUNCTION ||
                $this instanceof PHP_Token_NAMESPACE) &&
                $tokens[$i] instanceof PHP_Token_SEMICOLON) {
                if ($block === 0) {
                    $this->endTokenId = $i;
                }
            }

            $i++;
        }

        if ($this->endTokenId === NULL) {
            $this->endTokenId = $this->id;
        }

        return $this->endTokenId;
    }

    public function getEndLine()
    {
        return $this->tokenStream[$this->getEndTokenId()]->getLine();
    }

}

abstract class PHP_TokenWithScopeAndVisibility extends PHP_TokenWithScope {

    public function getVisibility()
    {
        $tokens = $this->tokenStream->tokens();

        for ($i = $this->id - 2; $i > $this->id - 7; $i -= 2) {
            if (isset($tokens[$i]) &&
               ($tokens[$i] instanceof PHP_Token_PRIVATE ||
                $tokens[$i] instanceof PHP_Token_PROTECTED ||
                $tokens[$i] instanceof PHP_Token_PUBLIC)) {
                return strtolower(
                  str_replace('PHP_Token_', '', get_class($tokens[$i]))
                );
            }
            if (isset($tokens[$i]) &&
              !($tokens[$i] instanceof PHP_Token_STATIC ||
                $tokens[$i] instanceof PHP_Token_FINAL ||
                $tokens[$i] instanceof PHP_Token_ABSTRACT)) {
                // no keywords; stop visibility search
                break;
            }
        }
    }

    public function getKeywords()
    {
        $keywords = array();
        $tokens = $this->tokenStream->tokens();

        for ($i = $this->id - 2; $i > $this->id - 7; $i -= 2) {
            if (isset($tokens[$i]) &&
               ($tokens[$i] instanceof PHP_Token_PRIVATE ||
                $tokens[$i] instanceof PHP_Token_PROTECTED ||
                $tokens[$i] instanceof PHP_Token_PUBLIC)) {
                continue;
            }

            if (isset($tokens[$i]) &&
               ($tokens[$i] instanceof PHP_Token_STATIC ||
                $tokens[$i] instanceof PHP_Token_FINAL ||
                $tokens[$i] instanceof PHP_Token_ABSTRACT)) {
                $keywords[] = strtolower(
                  str_replace('PHP_Token_', '', get_class($tokens[$i]))
                );
            }
        }

        return implode(',', $keywords);
    }

}

abstract class PHP_Token_Includes extends PHP_Token
{
    protected $name;
    protected $type;

    public function getName()
    {
        if ($this->name !== NULL) {
            return $this->name;
        }

        $tokens = $this->tokenStream->tokens();

        if ($tokens[$this->id+2] instanceof PHP_Token_CONSTANT_ENCAPSED_STRING) {
            $this->name = trim($tokens[$this->id+2], "'\"");
            $this->type = strtolower(
              str_replace('PHP_Token_', '', get_class($tokens[$this->id]))
            );
        }

        return $this->name;
    }

    public function getType()
    {
        $this->getName();
        return $this->type;
    }
}

class PHP_Token_REQUIRE_ONCE extends PHP_Token_Includes {}
class PHP_Token_REQUIRE extends PHP_Token_Includes {}
class PHP_Token_EVAL extends PHP_Token {}
class PHP_Token_INCLUDE_ONCE extends PHP_Token_Includes {}
class PHP_Token_INCLUDE extends PHP_Token_Includes {}
class PHP_Token_LOGICAL_OR extends PHP_Token {}
class PHP_Token_LOGICAL_XOR extends PHP_Token {}
class PHP_Token_LOGICAL_AND extends PHP_Token {}
class PHP_Token_PRINT extends PHP_Token {}
class PHP_Token_SR_EQUAL extends PHP_Token {}
class PHP_Token_SL_EQUAL extends PHP_Token {}
class PHP_Token_XOR_EQUAL extends PHP_Token {}
class PHP_Token_OR_EQUAL extends PHP_Token {}
class PHP_Token_AND_EQUAL extends PHP_Token {}
class PHP_Token_MOD_EQUAL extends PHP_Token {}
class PHP_Token_CONCAT_EQUAL extends PHP_Token {}
class PHP_Token_DIV_EQUAL extends PHP_Token {}
class PHP_Token_MUL_EQUAL extends PHP_Token {}
class PHP_Token_MINUS_EQUAL extends PHP_Token {}
class PHP_Token_PLUS_EQUAL extends PHP_Token {}
class PHP_Token_BOOLEAN_OR extends PHP_Token {}
class PHP_Token_BOOLEAN_AND extends PHP_Token {}
class PHP_Token_IS_NOT_IDENTICAL extends PHP_Token {}
class PHP_Token_IS_IDENTICAL extends PHP_Token {}
class PHP_Token_IS_NOT_EQUAL extends PHP_Token {}
class PHP_Token_IS_EQUAL extends PHP_Token {}
class PHP_Token_IS_GREATER_OR_EQUAL extends PHP_Token {}
class PHP_Token_IS_SMALLER_OR_EQUAL extends PHP_Token {}
class PHP_Token_SR extends PHP_Token {}
class PHP_Token_SL extends PHP_Token {}
class PHP_Token_INSTANCEOF extends PHP_Token {}
class PHP_Token_UNSET_CAST extends PHP_Token {}
class PHP_Token_BOOL_CAST extends PHP_Token {}
class PHP_Token_OBJECT_CAST extends PHP_Token {}
class PHP_Token_ARRAY_CAST extends PHP_Token {}
class PHP_Token_STRING_CAST extends PHP_Token {}
class PHP_Token_DOUBLE_CAST extends PHP_Token {}
class PHP_Token_INT_CAST extends PHP_Token {}
class PHP_Token_DEC extends PHP_Token {}
class PHP_Token_INC extends PHP_Token {}
class PHP_Token_CLONE extends PHP_Token {}
class PHP_Token_NEW extends PHP_Token {}
class PHP_Token_EXIT extends PHP_Token {}
class PHP_Token_IF extends PHP_Token {}
class PHP_Token_ELSEIF extends PHP_Token {}
class PHP_Token_ELSE extends PHP_Token {}
class PHP_Token_ENDIF extends PHP_Token {}
class PHP_Token_LNUMBER extends PHP_Token {}
class PHP_Token_DNUMBER extends PHP_Token {}
class PHP_Token_STRING extends PHP_Token {}
class PHP_Token_STRING_VARNAME extends PHP_Token {}
class PHP_Token_VARIABLE extends PHP_Token {}
class PHP_Token_NUM_STRING extends PHP_Token {}
class PHP_Token_INLINE_HTML extends PHP_Token {}
class PHP_Token_CHARACTER extends PHP_Token {}
class PHP_Token_BAD_CHARACTER extends PHP_Token {}
class PHP_Token_ENCAPSED_AND_WHITESPACE extends PHP_Token {}
class PHP_Token_CONSTANT_ENCAPSED_STRING extends PHP_Token {}
class PHP_Token_ECHO extends PHP_Token {}
class PHP_Token_DO extends PHP_Token {}
class PHP_Token_WHILE extends PHP_Token {}
class PHP_Token_ENDWHILE extends PHP_Token {}
class PHP_Token_FOR extends PHP_Token {}
class PHP_Token_ENDFOR extends PHP_Token {}
class PHP_Token_FOREACH extends PHP_Token {}
class PHP_Token_ENDFOREACH extends PHP_Token {}
class PHP_Token_DECLARE extends PHP_Token {}
class PHP_Token_ENDDECLARE extends PHP_Token {}
class PHP_Token_AS extends PHP_Token {}
class PHP_Token_SWITCH extends PHP_Token {}
class PHP_Token_ENDSWITCH extends PHP_Token {}
class PHP_Token_CASE extends PHP_Token {}
class PHP_Token_DEFAULT extends PHP_Token {}
class PHP_Token_BREAK extends PHP_Token {}
class PHP_Token_CONTINUE extends PHP_Token {}
class PHP_Token_GOTO extends PHP_Token {}
class PHP_Token_CALLABLE extends PHP_Token {}
class PHP_Token_INSTEADOF extends PHP_Token {}

class PHP_Token_FUNCTION extends PHP_TokenWithScopeAndVisibility
{
    protected $arguments;
    protected $ccn;
    protected $name;
    protected $signature;

    public function getArguments()
    {
        if ($this->arguments !== NULL) {
            return $this->arguments;
        }

        $this->arguments = array();
        $i               = $this->id + 2;
        $tokens          = $this->tokenStream->tokens();
        $typeHint        = NULL;

        while (!$tokens[$i] instanceof PHP_Token_CLOSE_BRACKET) {
            if ($tokens[$i] instanceof PHP_Token_STRING) {
                $typeHint = (string)$tokens[$i];
            }

            else if ($tokens[$i] instanceof PHP_Token_VARIABLE) {
                $this->arguments[(string)$tokens[$i]] = $typeHint;
                $typeHint                             = NULL;
            }

            $i++;
        }

        return $this->arguments;
    }

    public function getName()
    {
        if ($this->name !== NULL) {
            return $this->name;
        }

        $tokens = $this->tokenStream->tokens();

        for ($i = $this->id + 1; $i < count($tokens); $i++) {
            if ($tokens[$i] instanceof PHP_Token_STRING) {
                $this->name = (string)$tokens[$i];
                break;
            }

            else if ($tokens[$i] instanceof PHP_Token_AMPERSAND &&
                     $tokens[$i+1] instanceof PHP_Token_STRING) {
                $this->name = (string)$tokens[$i+1];
                break;
            }

            else if ($tokens[$i] instanceof PHP_Token_OPEN_BRACKET) {
                $this->name = 'anonymous function';
                break;
            }
        }

        if ($this->name != 'anonymous function') {
            for ($i = $this->id; $i; --$i) {
                if ($tokens[$i] instanceof PHP_Token_NAMESPACE) {
                    $this->name = $tokens[$i]->getName() . '\\' . $this->name;
                    break;
                }

                if ($tokens[$i] instanceof PHP_Token_INTERFACE) {
                    break;
                }
            }
        }

        return $this->name;
    }

    public function getCCN()
    {
        if ($this->ccn !== NULL) {
            return $this->ccn;
        }

        $this->ccn = 1;
        $end       = $this->getEndTokenId();
        $tokens    = $this->tokenStream->tokens();

        for ($i = $this->id; $i <= $end; $i++) {
            switch (get_class($tokens[$i])) {
                case 'PHP_Token_IF':
                case 'PHP_Token_ELSEIF':
                case 'PHP_Token_FOR':
                case 'PHP_Token_FOREACH':
                case 'PHP_Token_WHILE':
                case 'PHP_Token_CASE':
                case 'PHP_Token_CATCH':
                case 'PHP_Token_BOOLEAN_AND':
                case 'PHP_Token_LOGICAL_AND':
                case 'PHP_Token_BOOLEAN_OR':
                case 'PHP_Token_LOGICAL_OR':
                case 'PHP_Token_QUESTION_MARK': {
                    $this->ccn++;
                }
                break;
            }
        }

        return $this->ccn;
    }

    public function getSignature()
    {
        if ($this->signature !== NULL) {
            return $this->signature;
        }

        if ($this->getName() == 'anonymous function') {
            $this->signature = 'anonymous function';
            $i               = $this->id + 1;
        } else {
            $this->signature = '';
            $i               = $this->id + 2;
        }

        $tokens = $this->tokenStream->tokens();

        while (isset($tokens[$i]) &&
               !$tokens[$i] instanceof PHP_Token_OPEN_CURLY &&
               !$tokens[$i] instanceof PHP_Token_SEMICOLON) {
            $this->signature .= $tokens[$i++];
        }

        $this->signature = trim($this->signature);

        return $this->signature;
    }
}

class PHP_Token_CONST extends PHP_Token {}
class PHP_Token_RETURN extends PHP_Token {}
class PHP_Token_YIELD extends PHP_Token {}
class PHP_Token_TRY extends PHP_Token {}
class PHP_Token_CATCH extends PHP_Token {}
class PHP_Token_FINALLY extends PHP_Token {}
class PHP_Token_THROW extends PHP_Token {}
class PHP_Token_USE extends PHP_Token {}
class PHP_Token_GLOBAL extends PHP_Token {}
class PHP_Token_PUBLIC extends PHP_Token {}
class PHP_Token_PROTECTED extends PHP_Token {}
class PHP_Token_PRIVATE extends PHP_Token {}
class PHP_Token_FINAL extends PHP_Token {}
class PHP_Token_ABSTRACT extends PHP_Token {}
class PHP_Token_STATIC extends PHP_Token {}
class PHP_Token_VAR extends PHP_Token {}
class PHP_Token_UNSET extends PHP_Token {}
class PHP_Token_ISSET extends PHP_Token {}
class PHP_Token_EMPTY extends PHP_Token {}
class PHP_Token_HALT_COMPILER extends PHP_Token {}

class PHP_Token_INTERFACE extends PHP_TokenWithScopeAndVisibility
{
    protected $interfaces;

    public function getName()
    {
        return (string)$this->tokenStream[$this->id + 2];
    }

    public function hasParent()
    {
        return $this->tokenStream[$this->id + 4] instanceof PHP_Token_EXTENDS;
    }

    public function getPackage()
    {
        $className  = $this->getName();
        $docComment = $this->getDocblock();

        $result = array(
          'namespace'   => '',
          'fullPackage' => '',
          'category'    => '',
          'package'     => '',
          'subpackage'  => ''
        );

        for ($i = $this->id; $i; --$i) {
            if ($this->tokenStream[$i] instanceof PHP_Token_NAMESPACE) {
                $result['namespace'] = $this->tokenStream[$i]->getName();
                break;
            }
        }

        if (preg_match('/@category[\s]+([\.\w]+)/', $docComment, $matches)) {
            $result['category'] = $matches[1];
        }

        if (preg_match('/@package[\s]+([\.\w]+)/', $docComment, $matches)) {
            $result['package']     = $matches[1];
            $result['fullPackage'] = $matches[1];
        }

        if (preg_match('/@subpackage[\s]+([\.\w]+)/', $docComment, $matches)) {
            $result['subpackage']   = $matches[1];
            $result['fullPackage'] .= '.' . $matches[1];
        }

        if (empty($result['fullPackage'])) {
            $result['fullPackage'] = $this->arrayToName(
              explode('_', str_replace('\\', '_', $className)), '.'
            );
        }

        return $result;
    }

    protected function arrayToName(array $parts, $join = '\\')
    {
        $result = '';

        if (count($parts) > 1) {
            array_pop($parts);

            $result = join($join, $parts);
        }

        return $result;
    }

    public function getParent()
    {
        if (!$this->hasParent()) {
            return FALSE;
        }

        $i         = $this->id + 6;
        $tokens    = $this->tokenStream->tokens();
        $className = (string)$tokens[$i];

        while (isset($tokens[$i+1]) &&
               !$tokens[$i+1] instanceof PHP_Token_WHITESPACE) {
            $className .= (string)$tokens[++$i];
        }

        return $className;
    }

    public function hasInterfaces()
    {
        return (isset($this->tokenStream[$this->id + 4]) &&
                $this->tokenStream[$this->id + 4] instanceof PHP_Token_IMPLEMENTS) ||
               (isset($this->tokenStream[$this->id + 8]) &&
                $this->tokenStream[$this->id + 8] instanceof PHP_Token_IMPLEMENTS);
    }

    public function getInterfaces()
    {
        if ($this->interfaces !== NULL) {
            return $this->interfaces;
        }

        if (!$this->hasInterfaces()) {
            return ($this->interfaces = FALSE);
        }

        if ($this->tokenStream[$this->id + 4] instanceof PHP_Token_IMPLEMENTS) {
            $i = $this->id + 3;
        } else {
            $i = $this->id + 7;
        }

        $tokens = $this->tokenStream->tokens();

        while (!$tokens[$i+1] instanceof PHP_Token_OPEN_CURLY) {
            $i++;

            if ($tokens[$i] instanceof PHP_Token_STRING) {
                $this->interfaces[] = (string)$tokens[$i];
            }
        }

        return $this->interfaces;
    }
}

class PHP_Token_CLASS extends PHP_Token_INTERFACE {}
class PHP_Token_CLASS_NAME_CONSTANT extends PHP_Token {}
class PHP_Token_TRAIT extends PHP_Token_INTERFACE {}
class PHP_Token_EXTENDS extends PHP_Token {}
class PHP_Token_IMPLEMENTS extends PHP_Token {}
class PHP_Token_OBJECT_OPERATOR extends PHP_Token {}
class PHP_Token_DOUBLE_ARROW extends PHP_Token {}
class PHP_Token_LIST extends PHP_Token {}
class PHP_Token_ARRAY extends PHP_Token {}
class PHP_Token_CLASS_C extends PHP_Token {}
class PHP_Token_TRAIT_C extends PHP_Token {}
class PHP_Token_METHOD_C extends PHP_Token {}
class PHP_Token_FUNC_C extends PHP_Token {}
class PHP_Token_LINE extends PHP_Token {}
class PHP_Token_FILE extends PHP_Token {}
class PHP_Token_COMMENT extends PHP_Token {}
class PHP_Token_DOC_COMMENT extends PHP_Token {}
class PHP_Token_OPEN_TAG extends PHP_Token {}
class PHP_Token_OPEN_TAG_WITH_ECHO extends PHP_Token {}
class PHP_Token_CLOSE_TAG extends PHP_Token {}
class PHP_Token_WHITESPACE extends PHP_Token {}
class PHP_Token_START_HEREDOC extends PHP_Token {}
class PHP_Token_END_HEREDOC extends PHP_Token {}
class PHP_Token_DOLLAR_OPEN_CURLY_BRACES extends PHP_Token {}
class PHP_Token_CURLY_OPEN extends PHP_Token {}
class PHP_Token_PAAMAYIM_NEKUDOTAYIM extends PHP_Token {}

class PHP_Token_NAMESPACE extends PHP_TokenWithScope
{
    public function getName()
    {
        $tokens    = $this->tokenStream->tokens();
        $namespace = (string)$tokens[$this->id+2];

        for ($i = $this->id + 3; ; $i += 2) {
            if (isset($tokens[$i]) &&
                $tokens[$i] instanceof PHP_Token_NS_SEPARATOR) {
                $namespace .= '\\' . $tokens[$i+1];
            } else {
                break;
            }
        }

        return $namespace;
    }
}

class PHP_Token_NS_C extends PHP_Token {}
class PHP_Token_DIR extends PHP_Token {}
class PHP_Token_NS_SEPARATOR extends PHP_Token {}
class PHP_Token_DOUBLE_COLON extends PHP_Token {}
class PHP_Token_OPEN_BRACKET extends PHP_Token {}
class PHP_Token_CLOSE_BRACKET extends PHP_Token {}
class PHP_Token_OPEN_SQUARE extends PHP_Token {}
class PHP_Token_CLOSE_SQUARE extends PHP_Token {}
class PHP_Token_OPEN_CURLY extends PHP_Token {}
class PHP_Token_CLOSE_CURLY extends PHP_Token {}
class PHP_Token_SEMICOLON extends PHP_Token {}
class PHP_Token_DOT extends PHP_Token {}
class PHP_Token_COMMA extends PHP_Token {}
class PHP_Token_EQUAL extends PHP_Token {}
class PHP_Token_LT extends PHP_Token {}
class PHP_Token_GT extends PHP_Token {}
class PHP_Token_PLUS extends PHP_Token {}
class PHP_Token_MINUS extends PHP_Token {}
class PHP_Token_MULT extends PHP_Token {}
class PHP_Token_DIV extends PHP_Token {}
class PHP_Token_QUESTION_MARK extends PHP_Token {}
class PHP_Token_EXCLAMATION_MARK extends PHP_Token {}
class PHP_Token_COLON extends PHP_Token {}
class PHP_Token_DOUBLE_QUOTES extends PHP_Token {}
class PHP_Token_AT extends PHP_Token {}
class PHP_Token_AMPERSAND extends PHP_Token {}
class PHP_Token_PERCENT extends PHP_Token {}
class PHP_Token_PIPE extends PHP_Token {}
class PHP_Token_DOLLAR extends PHP_Token {}
class PHP_Token_CARET extends PHP_Token {}
class PHP_Token_TILDE extends PHP_Token {}
class PHP_Token_BACKTICK extends PHP_Token {}
<?php
/**
 * php-token-stream
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHP_TokenStream
 * @subpackage Tests
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @since      File available since Release 1.0.0
 */

if (!defined('TEST_FILES_PATH')) {
    define(
      'TEST_FILES_PATH',
      dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR .
      '_files' . DIRECTORY_SEPARATOR
    );
}

require_once 'PHP/Token/Stream.php';

/**
 * Tests for the PHP_Token_FUNCTION class.
 *
 * @package    PHP_TokenStream
 * @subpackage Tests
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/php-token-stream/
 * @since      Class available since Release 1.0.0
 */
class PHP_Token_FunctionTest extends PHPUnit_Framework_TestCase
{
    protected $functions;

    protected function setUp()
    {
        $ts = new PHP_Token_Stream(TEST_FILES_PATH . 'source.php');

        foreach ($ts as $token) {
            if ($token instanceof PHP_Token_FUNCTION) {
                $this->functions[] = $token;
            }
        }
    }

    /**
     * @covers PHP_Token_FUNCTION::getArguments
     */
    public function testGetArguments()
    {
        $this->assertEquals(array(), $this->functions[0]->getArguments());

        $this->assertEquals(
          array('$baz' => 'Baz'), $this->functions[1]->getArguments()
        );

        $this->assertEquals(
          array('$foobar' => 'Foobar'), $this->functions[2]->getArguments()
        );

        $this->assertEquals(
          array('$barfoo' => 'Barfoo'), $this->functions[3]->getArguments()
        );

        $this->assertEquals(array(), $this->functions[4]->getArguments());
    }

    /**
     * @covers PHP_Token_FUNCTION::getName
     */
    public function testGetName()
    {
        $this->assertEquals('foo', $this->functions[0]->getName());
        $this->assertEquals('bar', $this->functions[1]->getName());
        $this->assertEquals('foobar', $this->functions[2]->getName());
        $this->assertEquals('barfoo', $this->functions[3]->getName());
        $this->assertEquals('baz', $this->functions[4]->getName());
    }

    /**
     * @covers PHP_Token::getLine
     */
    public function testGetLine()
    {
        $this->assertEquals(5, $this->functions[0]->getLine());
        $this->assertEquals(10, $this->functions[1]->getLine());
        $this->assertEquals(17, $this->functions[2]->getLine());
        $this->assertEquals(21, $this->functions[3]->getLine());
        $this->assertEquals(29, $this->functions[4]->getLine());
    }

    /**
     * @covers PHP_TokenWithScope::getEndLine
     */
    public function testGetEndLine()
    {
        $this->assertEquals(5, $this->functions[0]->getEndLine());
        $this->assertEquals(12, $this->functions[1]->getEndLine());
        $this->assertEquals(19, $this->functions[2]->getEndLine());
        $this->assertEquals(23, $this->functions[3]->getEndLine());
        $this->assertEquals(31, $this->functions[4]->getEndLine());
    }

    /**
     * @covers PHP_Token_FUNCTION::getDocblock
     */
    public function testGetDocblock()
    {
        $this->assertNull($this->functions[0]->getDocblock());

        $this->assertEquals(
          "/**\n     * @param Baz \$baz\n     */",
          $this->functions[1]->getDocblock()
        );

        $this->assertEquals(
          "/**\n     * @param Foobar \$foobar\n     */",
          $this->functions[2]->getDocblock()
        );

        $this->assertNull($this->functions[3]->getDocblock());
        $this->assertNull($this->functions[4]->getDocblock());
    }

    public function testSignature()
    {
        $ts = new PHP_Token_Stream(TEST_FILES_PATH . 'source5.php');
        $f  = $ts->getFunctions();
        $c  = $ts->getClasses();
        $i  = $ts->getInterfaces();

        $this->assertEquals(
          'foo($a, array $b, array $c = array())',
          $f['foo']['signature']
        );

        $this->assertEquals(
          'm($a, array $b, array $c = array())',
          $c['c']['methods']['m']['signature']
        );

        $this->assertEquals(
          'm($a, array $b, array $c = array())',
          $c['a']['methods']['m']['signature']
        );

        $this->assertEquals(
          'm($a, array $b, array $c = array())',
          $i['i']['methods']['m']['signature']
        );
    }
}
<?php
/**
 * php-token-stream
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHP_TokenStream
 * @subpackage Tests
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @since      File available since Release 1.0.0
 */

if (!defined('TEST_FILES_PATH')) {
    define(
      'TEST_FILES_PATH',
      dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR .
      '_files' . DIRECTORY_SEPARATOR
    );
}

require_once 'PHP/Token/Stream.php';

/**
 * Tests for the PHP_Token_FUNCTION class.
 *
 * @package    PHP_TokenStream
 * @subpackage Tests
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/php-token-stream/
 * @since      Class available since Release 1.0.0
 */
class PHP_Token_ClosureTest extends PHPUnit_Framework_TestCase
{
    protected $functions;

    protected function setUp()
    {
        $ts = new PHP_Token_Stream(TEST_FILES_PATH . 'closure.php');

        foreach ($ts as $token) {
            if ($token instanceof PHP_Token_FUNCTION) {
                $this->functions[] = $token;
            }
        }
    }

    /**
     * @covers PHP_Token_FUNCTION::getArguments
     */
    public function testGetArguments()
    {
        $this->assertEquals(array('$foo' => null, '$bar' => null), $this->functions[0]->getArguments());
        $this->assertEquals(array('$foo' => 'Foo', '$bar' => null), $this->functions[1]->getArguments());
        $this->assertEquals(array('$foo' => null, '$bar' => null, '$baz' => null), $this->functions[2]->getArguments());
        $this->assertEquals(array('$foo' => 'Foo', '$bar' => null, '$baz' => null), $this->functions[3]->getArguments());
        $this->assertEquals(array(), $this->functions[4]->getArguments());
        $this->assertEquals(array(), $this->functions[5]->getArguments());
    }

    /**
     * @covers PHP_Token_FUNCTION::getName
     */
    public function testGetName()
    {
        $this->assertEquals('anonymous function', $this->functions[0]->getName());
        $this->assertEquals('anonymous function', $this->functions[1]->getName());
        $this->assertEquals('anonymous function', $this->functions[2]->getName());
        $this->assertEquals('anonymous function', $this->functions[3]->getName());
        $this->assertEquals('anonymous function', $this->functions[4]->getName());
        $this->assertEquals('anonymous function', $this->functions[5]->getName());
    }

    /**
     * @covers PHP_Token::getLine
     */
    public function testGetLine()
    {
        $this->assertEquals(2, $this->functions[0]->getLine());
        $this->assertEquals(3, $this->functions[1]->getLine());
        $this->assertEquals(4, $this->functions[2]->getLine());
        $this->assertEquals(5, $this->functions[3]->getLine());
    }

    /**
     * @covers PHP_TokenWithScope::getEndLine
     */
    public function testGetEndLine()
    {
        $this->assertEquals(2, $this->functions[0]->getLine());
        $this->assertEquals(3, $this->functions[1]->getLine());
        $this->assertEquals(4, $this->functions[2]->getLine());
        $this->assertEquals(5, $this->functions[3]->getLine());
    }
}
<?php
/**
 * php-token-stream
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHP_TokenStream
 * @subpackage Tests
 * @author     Laurent Laville <pear@laurent-laville.org>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @since      File available since Release 1.0.2
 */

if (!defined('TEST_FILES_PATH')) {
    define(
      'TEST_FILES_PATH',
      dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR .
      '_files' . DIRECTORY_SEPARATOR
    );
}

require_once 'PHP/Token/Stream.php';

/**
 * Tests for the PHP_Token_CLASS class.
 *
 * @package    PHP_TokenStream
 * @subpackage Tests
 * @author     Laurent Laville <pear@laurent-laville.org>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/php-token-stream/
 * @since      Class available since Release 1.0.2
 */
class PHP_Token_ClassTest extends PHPUnit_Framework_TestCase
{
    protected $class;
    protected $function;

    protected function setUp()
    {
        $ts = new PHP_Token_Stream(TEST_FILES_PATH . 'source2.php');

        foreach ($ts as $token) {
            if ($token instanceof PHP_Token_CLASS) {
                $this->class = $token;
            }

            if ($token instanceof PHP_Token_FUNCTION) {
                $this->function = $token;
                break;
            }
        }
    }

    /**
     * @covers PHP_Token_CLASS::getKeywords
     */
    public function testGetClassKeywords()
    {
        $this->assertEquals('abstract', $this->class->getKeywords());
    }

    /**
     * @covers PHP_Token_FUNCTION::getKeywords
     */
    public function testGetFunctionKeywords()
    {
        $this->assertEquals('abstract,static', $this->function->getKeywords());
    }

    /**
     * @covers PHP_Token_FUNCTION::getVisibility
     */
    public function testGetFunctionVisibility()
    {
        $this->assertEquals('public', $this->function->getVisibility());
    }

    public function testIssue19()
    {
        $ts = new PHP_Token_Stream(TEST_FILES_PATH . 'issue19.php');

        foreach ($ts as $token) {
            if ($token instanceof PHP_Token_CLASS) {
                $this->assertFalse($token->hasInterfaces());
            }
        }
    }

    public function testIssue30()
    {
        $ts = new PHP_Token_Stream(TEST_FILES_PATH . 'issue30.php');
        $this->assertCount(1, $ts->getClasses());
    }
}
<?php
/**
 * php-token-stream
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHP_TokenStream
 * @subpackage Tests
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Laurent Laville <pear@laurent-laville.org>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @since      File available since Release 1.0.0
 */

if (!defined('TEST_FILES_PATH')) {
    define(
      'TEST_FILES_PATH',
      dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR .
      '_files' . DIRECTORY_SEPARATOR
    );
}

require_once 'PHP/Token/Stream.php';

/**
 * Tests for the PHP_Token_INTERFACE class.
 *
 * @package    PHP_TokenStream
 * @subpackage Tests
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Laurent Laville <pear@laurent-laville.org>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/php-token-stream/
 * @since      Class available since Release 1.0.0
 */
class PHP_Token_InterfaceTest extends PHPUnit_Framework_TestCase
{
    protected $class;
    protected $interfaces;

    protected function setUp()
    {
        $ts = new PHP_Token_Stream(TEST_FILES_PATH . 'source4.php');
        $i  = 0;
        foreach ($ts as $token) {
            if ($token instanceof PHP_Token_CLASS) {
                $this->class = $token;
            }
            elseif ($token instanceof PHP_Token_INTERFACE) {
                $this->interfaces[$i] = $token;
                $i++;
            }
        }
    }

    /**
     * @covers PHP_Token_INTERFACE::getName
     */
    public function testGetName()
    {
        $this->assertEquals(
            'iTemplate', $this->interfaces[0]->getName()
        );
    }

    /**
     * @covers PHP_Token_INTERFACE::getParent
     */
    public function testGetParentNotExists()
    {
        $this->assertFalse(
            $this->interfaces[0]->getParent()
        );
    }

    /**
     * @covers PHP_Token_INTERFACE::hasParent
     */
    public function testHasParentNotExists()
    {
        $this->assertFalse(
            $this->interfaces[0]->hasParent()
        );
    }

    /**
     * @covers PHP_Token_INTERFACE::getParent
     */
    public function testGetParentExists()
    {
        $this->assertEquals(
            'a', $this->interfaces[2]->getParent()
        );
    }

    /**
     * @covers PHP_Token_INTERFACE::hasParent
     */
    public function testHasParentExists()
    {
        $this->assertTrue(
            $this->interfaces[2]->hasParent()
        );
    }

    /**
     * @covers PHP_Token_INTERFACE::getInterfaces
     */
    public function testGetInterfacesExists()
    {
        $this->assertEquals(
            array('b'),
            $this->class->getInterfaces()
        );
    }

    /**
     * @covers PHP_Token_INTERFACE::hasInterfaces
     */
    public function testHasInterfacesExists()
    {
        $this->assertTrue(
            $this->class->hasInterfaces()
        );
    }
    /**
     * @covers PHP_Token_INTERFACE::getPackage
     */
    public function testGetPackageNamespace() {
        $tokenStream = new PHP_Token_Stream(TEST_FILES_PATH . 'classInNamespace.php');
        foreach($tokenStream as $token) {
            if($token instanceOf PHP_Token_INTERFACE) {
                $package = $token->getPackage();
                $this->assertSame('Foo\\Bar', $package['namespace']);
            }
        }
    }


    public function provideFilesWithClassesWithinMultipleNamespaces() {
        return array(
            array(TEST_FILES_PATH . 'multipleNamespacesWithOneClassUsingBraces.php'),
            array(TEST_FILES_PATH . 'multipleNamespacesWithOneClassUsingNonBraceSyntax.php'),
        );
    }

    /**
     * @dataProvider provideFilesWithClassesWithinMultipleNamespaces
     * @covers PHP_Token_INTERFACE::getPackage
     */
    public function testGetPackageNamespaceForFileWithMultipleNamespaces($filepath) {
        $tokenStream = new PHP_Token_Stream($filepath);
        $firstClassFound = false;
        foreach($tokenStream as $token) {
            if($firstClassFound === false && $token instanceOf PHP_Token_INTERFACE) {
                $package = $token->getPackage();
                $this->assertSame('TestClassInBar', $token->getName());
                $this->assertSame('Foo\\Bar', $package['namespace']);
                $firstClassFound = true;
                continue;
            }
            // Secound class
            if($token instanceOf PHP_Token_INTERFACE) {
                $package = $token->getPackage();
                $this->assertSame('TestClassInBaz', $token->getName());
                $this->assertSame('Foo\\Baz', $package['namespace']);
                return;
            }
        }
        $this->fail("Seachring for 2 classes failed");
    }

    public function testGetPackageNamespaceIsEmptyForInterfacesThatAreNotWithinNamespaces() {
        foreach($this->interfaces as $token) {
            $package = $token->getPackage();
            $this->assertSame("", $package['namespace']);
        }
    }

    /**
     * @covers PHP_Token_INTERFACE::getPackage
     */
    public function testGetPackageNamespaceWhenExtentingFromNamespaceClass() {
        $tokenStream = new PHP_Token_Stream(TEST_FILES_PATH . 'classExtendsNamespacedClass.php');
        $firstClassFound = false;
        foreach($tokenStream as $token) {
            if($firstClassFound === false && $token instanceOf PHP_Token_INTERFACE) {
                $package = $token->getPackage();
                $this->assertSame('Baz', $token->getName());
                $this->assertSame('Foo\\Bar', $package['namespace']);
                $firstClassFound = true;
                continue;
            }
            if($token instanceOf PHP_Token_INTERFACE) {
                $package = $token->getPackage();
                $this->assertSame('Extender', $token->getName());
                $this->assertSame('Other\\Space', $package['namespace']);
                return;
            }
        }
        $this->fail("Searching for 2 classes failed");
    }
}
<?php
/**
 * php-token-stream
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHP_TokenStream
 * @subpackage Tests
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @since      File available since Release 1.0.0
 */

if (!defined('TEST_FILES_PATH')) {
    define(
      'TEST_FILES_PATH',
      dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR .
      '_files' . DIRECTORY_SEPARATOR
    );
}

require_once 'PHP/Token/Stream.php';

/**
 * Tests for the PHP_Token_NAMESPACE class.
 *
 * @package    PHP_TokenStream
 * @subpackage Tests
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/php-token-stream/
 * @since      Class available since Release 1.0.0
 */
class PHP_Token_NamespaceTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers PHP_Token_NAMESPACE::getName
     */
    public function testGetName()
    {
        $tokenStream = new PHP_Token_Stream(
          TEST_FILES_PATH . 'classInNamespace.php'
        );

        foreach ($tokenStream as $token) {
            if ($token instanceof PHP_Token_NAMESPACE) {
                $this->assertSame('Foo\\Bar', $token->getName());
            }
        }
    }

    public function testGetStartLineWithUnscopedNamespace()
    {
        $tokenStream = new PHP_Token_Stream(TEST_FILES_PATH . 'classInNamespace.php');
        foreach($tokenStream as $token) {
            if($token instanceOf PHP_Token_NAMESPACE) {
                $this->assertSame(2, $token->getLine());
            }
        }
    }

    public function testGetEndLineWithUnscopedNamespace()
    {
        $tokenStream = new PHP_Token_Stream(TEST_FILES_PATH . 'classInNamespace.php');
        foreach($tokenStream as $token) {
            if($token instanceOf PHP_Token_NAMESPACE) {
                $this->assertSame(2, $token->getEndLine());
            }
        }
    }
    public function testGetStartLineWithScopedNamespace()
    {
        $tokenStream = new PHP_Token_Stream(TEST_FILES_PATH . 'classInScopedNamespace.php');
        foreach($tokenStream as $token) {
            if($token instanceOf PHP_Token_NAMESPACE) {
                $this->assertSame(2, $token->getLine());
            }
        }
    }

    public function testGetEndLineWithScopedNamespace()
    {
        $tokenStream = new PHP_Token_Stream(TEST_FILES_PATH . 'classInScopedNamespace.php');
        foreach($tokenStream as $token) {
            if($token instanceOf PHP_Token_NAMESPACE) {
                $this->assertSame(8, $token->getEndLine());
            }
        }
    }

}
<?php
/**
 * php-token-stream
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHP_TokenStream
 * @subpackage Tests
 * @author     Laurent Laville <pear@laurent-laville.org>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @since      File available since Release 1.0.2
 */

if (!defined('TEST_FILES_PATH')) {
    define(
      'TEST_FILES_PATH',
      dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR .
      '_files' . DIRECTORY_SEPARATOR
    );
}

require_once 'PHP/Token/Stream.php';

/**
 * Tests for the PHP_Token_REQUIRE_ONCE, PHP_Token_REQUIRE
 * PHP_Token_INCLUDE_ONCE and PHP_Token_INCLUDE_ONCE classes.
 *
 * @package    PHP_TokenStream
 * @subpackage Tests
 * @author     Laurent Laville <pear@laurent-laville.org>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/php-token-stream/
 * @since      Class available since Release 1.0.2
 */
class PHP_Token_IncludeTest extends PHPUnit_Framework_TestCase
{
    protected $ts;

    protected function setUp()
    {
        $this->ts = new PHP_Token_Stream(TEST_FILES_PATH . 'source3.php');
    }

    /**
     * @covers PHP_Token_Includes::getName
     * @covers PHP_Token_Includes::getType
     */
    public function testGetIncludes()
    {
        $this->assertSame(
          array('test4.php', 'test3.php', 'test2.php', 'test1.php'),
          $this->ts->getIncludes()
        );
    }

    /**
     * @covers PHP_Token_Includes::getName
     * @covers PHP_Token_Includes::getType
     */
    public function testGetIncludesCategorized()
    {
        $this->assertSame(
          array(
            'require_once' => array('test4.php'),
            'require'      => array('test3.php'),
            'include_once' => array('test2.php'),
            'include'      => array('test1.php')
          ),
          $this->ts->getIncludes(TRUE)
        );
    }

    /**
     * @covers PHP_Token_Includes::getName
     * @covers PHP_Token_Includes::getType
     */
    public function testGetIncludesCategory()
    {
        $this->assertSame(
          array('test4.php'),
          $this->ts->getIncludes(TRUE, 'require_once')
        );
    }
}
<?php
/**
 * php-token-stream
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHP_TokenStream
 * @subpackage Tests
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @since      File available since Release 1.0.0
 */

if (!defined('TEST_FILES_PATH')) {
    define(
      'TEST_FILES_PATH',
      dirname(__FILE__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR
    );
}

require_once 'PHP/Token/Stream.php';

/**
 * Tests for the PHP_Token class.
 *
 * @package    PHP_TokenStream
 * @subpackage Tests
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/php-token-stream/
 * @since      Class available since Release 1.0.0
 */
class PHP_TokenTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers PHP_Token::__construct
     * @covers PHP_Token::__toString
     */
    public function testToString()
    {
        $this->markTestIncomplete();
    }

    /**
     * @covers PHP_Token::__construct
     * @covers PHP_Token::getLine
     */
    public function testGetLine()
    {
        $this->markTestIncomplete();
    }
}
<?php
namespace Foo\Bar;

class TestClass
{
}
<?php
$function1 = function($foo, $bar) use ($var) {};
$function2 = function(Foo $foo, $bar) use ($var) {};
$function3 = function ($foo, $bar, $baz) {};
$function4 = function (Foo $foo, $bar, $baz) {};
$function5 = function () {};
$function6 = function() {};
<?php
namespace Foo\Bar;

class TestClassInBar
{
}

namespace Foo\Baz;

class TestClassInBaz
{
}
<?php
// This file is example#1
// from http://www.php.net/manual/en/function.get-included-files.php

include 'test1.php';
include_once 'test2.php';
require 'test3.php';
require_once 'test4.php';

$included_files = get_included_files();

foreach ($included_files as $filename) {
    echo "$filename\n";
}
<?php
// short desc
abstract class A {
    /* abst meth: */
    public static  abstract function method();
}
<?php

namespace Foo\Bar;

class Baz {}

namespace Other\Space;

class Extender extends \Foo\Bar\Baz {}

<?php
namespace Foo\Bar
{
    class TestClassInBar
    {
    }
}

namespace Foo\Baz
{
    class TestClassInBaz
    {
    }
}
<?php
function foo($a, array $b, array $c = array()) {}
interface i { public function m($a, array $b, array $c = array()); }
abstract class a { abstract public function m($a, array $b, array $c = array()); }
class c { public function m($a, array $b, array $c = array()) {} }
<?php
class Foo
{
    public function bar()
    {
        return Foo::CLASS;
    }
}
<?php
namespace Foo\BarScoped {

    class TestClass {

    }

}

<?php
/**
 * Some comment
 */
class Foo{function foo(){}

    /**
     * @param Baz $baz
     */
    public function bar(Baz $baz)
    {
    }

    /**
     * @param Foobar $foobar
     */
    static public function foobar(Foobar $foobar)
    {
    }

    public function barfoo(Barfoo $barfoo)
    {
    }

    /**
     * This docblock does not belong to the baz function
     */

    public function baz()
    {
    }
}
<?php
class TestClass {
}
<?php
// Declare the interface 'iTemplate'
interface iTemplate
{
    public function setVariable($name, $var);
    public function
        getHtml($template);
}

interface a
{
    public function foo();
}

interface b extends a
{
    public function baz(Baz $baz);
}

// short desc for class that implement a unique interface
class c implements b
{
    public function foo()
    {
    }

    public function baz(Baz $baz)
    {
    }
}
{
    "name": "phpunit/phpunit",
    "description": "The PHP Unit Testing framework.",
    "type": "library",
    "keywords": [
        "phpunit",
        "xunit",
        "testing"
    ],
    "homepage": "http://www.phpunit.de/",
    "license": "BSD-3-Clause",
    "authors": [
        {
            "name": "Sebastian Bergmann",
            "email": "sebastian@phpunit.de",
            "role": "lead"
        }
    ],
    "support": {
        "issues": "https://github.com/sebastianbergmann/phpunit/issues",
        "irc": "irc://irc.freenode.net/phpunit"
    },
    "require": {
        "php": ">=5.3.3",
        "phpunit/php-file-iterator": ">=1.3.1",
        "phpunit/php-text-template": ">=1.1.1",
        "phpunit/php-code-coverage": "~1.2.1",
        "phpunit/php-timer": ">=1.0.4",
        "phpunit/phpunit-mock-objects": "~1.2.0",
        "symfony/yaml": "~2.0",
        "ext-dom": "*",
        "ext-pcre": "*",
        "ext-reflection": "*",
        "ext-spl": "*"
    },
    "require-dev": {
        "pear-pear/pear": "1.9.4"
    },
    "repositories": [
        {
            "type": "pear",
            "url": "http://pear.php.net"
        }
    ],
    "suggest": {
        "phpunit/php-invoker": ">=1.1.0,<1.2.0",
        "ext-json": "*",
        "ext-simplexml": "*",
        "ext-tokenizer": "*"
    },
    "bin": [
        "composer/bin/phpunit"
    ],
    "autoload": {
        "classmap": [
            "PHPUnit/"
        ]
    },
    "extra": {
        "branch-alias": {
            "dev-master": "3.7.x-dev"
        }
    },
    "include-path": [
        "",
        "../../symfony/yaml/"
    ]
}
<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.4.10" version="2.0"
  xmlns="http://pear.php.net/dtd/package-2.0"
  xmlns:tasks="http://pear.php.net/dtd/tasks-1.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
                      http://pear.php.net/dtd/tasks-1.0.xsd
                      http://pear.php.net/dtd/package-2.0
                      http://pear.php.net/dtd/package-2.0.xsd">
 <name>PHPUnit</name>
 <channel>pear.phpunit.de</channel>
 <summary>The PHP Unit Testing framework.</summary>
 <description>The PHP Unit Testing framework.</description>
 <lead>
  <name>Sebastian Bergmann</name>
  <user>sb</user>
  <email>sebastian@phpunit.de</email>
  <active>yes</active>
 </lead>
 <date>2013-10-17</date>
 <version>
  <release>3.7.28</release>
  <api>3.7.0</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license>The BSD 3-Clause License</license>
 <notes>http://github.com/sebastianbergmann/phpunit/blob/master/README.md</notes>
 <contents>
  <dir name="/">
   <dir name="PHPUnit">
    <dir name="Extensions">
     <dir name="PhptTestCase">
      <file baseinstalldir="/" name="Logger.php" role="php" />
     </dir>
     <file baseinstalldir="/" name="GroupTestSuite.php" role="php" />
     <file baseinstalldir="/" name="PhptTestCase.php" role="php" />
     <file baseinstalldir="/" name="PhptTestSuite.php" role="php" />
     <file baseinstalldir="/" name="RepeatedTest.php" role="php" />
     <file baseinstalldir="/" name="TestDecorator.php" role="php" />
     <file baseinstalldir="/" name="TicketListener.php" role="php" />
    </dir>
    <dir name="Framework">
     <dir name="Assert">
      <file baseinstalldir="/" name="Functions.php" role="php" />
     </dir>
     <dir name="Comparator">
      <file baseinstalldir="/" name="Array.php" role="php" />
      <file baseinstalldir="/" name="DOMDocument.php" role="php" />
      <file baseinstalldir="/" name="Double.php" role="php" />
      <file baseinstalldir="/" name="Exception.php" role="php" />
      <file baseinstalldir="/" name="MockObject.php" role="php" />
      <file baseinstalldir="/" name="Numeric.php" role="php" />
      <file baseinstalldir="/" name="Object.php" role="php" />
      <file baseinstalldir="/" name="Resource.php" role="php" />
      <file baseinstalldir="/" name="Scalar.php" role="php" />
      <file baseinstalldir="/" name="SplObjectStorage.php" role="php" />
      <file baseinstalldir="/" name="Type.php" role="php" />
     </dir>
     <dir name="Constraint">
      <dir name="JsonMatches">
       <file baseinstalldir="/" name="ErrorMessageProvider.php" role="php" />
      </dir>
      <file baseinstalldir="/" name="And.php" role="php" />
      <file baseinstalldir="/" name="ArrayHasKey.php" role="php" />
      <file baseinstalldir="/" name="Attribute.php" role="php" />
      <file baseinstalldir="/" name="Callback.php" role="php" />
      <file baseinstalldir="/" name="ClassHasAttribute.php" role="php" />
      <file baseinstalldir="/" name="ClassHasStaticAttribute.php" role="php" />
      <file baseinstalldir="/" name="Composite.php" role="php" />
      <file baseinstalldir="/" name="Count.php" role="php" />
      <file baseinstalldir="/" name="ExceptionCode.php" role="php" />
      <file baseinstalldir="/" name="ExceptionMessage.php" role="php" />
      <file baseinstalldir="/" name="Exception.php" role="php" />
      <file baseinstalldir="/" name="FileExists.php" role="php" />
      <file baseinstalldir="/" name="GreaterThan.php" role="php" />
      <file baseinstalldir="/" name="IsAnything.php" role="php" />
      <file baseinstalldir="/" name="IsEmpty.php" role="php" />
      <file baseinstalldir="/" name="IsEqual.php" role="php" />
      <file baseinstalldir="/" name="IsFalse.php" role="php" />
      <file baseinstalldir="/" name="IsIdentical.php" role="php" />
      <file baseinstalldir="/" name="IsInstanceOf.php" role="php" />
      <file baseinstalldir="/" name="IsJson.php" role="php" />
      <file baseinstalldir="/" name="IsNull.php" role="php" />
      <file baseinstalldir="/" name="IsTrue.php" role="php" />
      <file baseinstalldir="/" name="IsType.php" role="php" />
      <file baseinstalldir="/" name="JsonMatches.php" role="php" />
      <file baseinstalldir="/" name="LessThan.php" role="php" />
      <file baseinstalldir="/" name="Not.php" role="php" />
      <file baseinstalldir="/" name="ObjectHasAttribute.php" role="php" />
      <file baseinstalldir="/" name="Or.php" role="php" />
      <file baseinstalldir="/" name="PCREMatch.php" role="php" />
      <file baseinstalldir="/" name="SameSize.php" role="php" />
      <file baseinstalldir="/" name="StringContains.php" role="php" />
      <file baseinstalldir="/" name="StringEndsWith.php" role="php" />
      <file baseinstalldir="/" name="StringMatches.php" role="php" />
      <file baseinstalldir="/" name="StringStartsWith.php" role="php" />
      <file baseinstalldir="/" name="TraversableContainsOnly.php" role="php" />
      <file baseinstalldir="/" name="TraversableContains.php" role="php" />
      <file baseinstalldir="/" name="Xor.php" role="php" />
     </dir>
     <dir name="Error">
      <file baseinstalldir="/" name="Deprecated.php" role="php" />
      <file baseinstalldir="/" name="Notice.php" role="php" />
      <file baseinstalldir="/" name="Warning.php" role="php" />
     </dir>
     <dir name="Process">
      <file baseinstalldir="/" name="TestCaseMethod.tpl.dist" role="php" />
     </dir>
     <dir name="TestSuite">
      <file baseinstalldir="/" name="DataProvider.php" role="php" />
     </dir>
     <file baseinstalldir="/" name="AssertionFailedError.php" role="php" />
     <file baseinstalldir="/" name="Assert.php" role="php" />
     <file baseinstalldir="/" name="ComparatorFactory.php" role="php" />
     <file baseinstalldir="/" name="Comparator.php" role="php" />
     <file baseinstalldir="/" name="ComparisonFailure.php" role="php" />
     <file baseinstalldir="/" name="Constraint.php" role="php" />
     <file baseinstalldir="/" name="Error.php" role="php" />
     <file baseinstalldir="/" name="Exception.php" role="php" />
     <file baseinstalldir="/" name="ExpectationFailedException.php" role="php" />
     <file baseinstalldir="/" name="IncompleteTestError.php" role="php" />
     <file baseinstalldir="/" name="IncompleteTest.php" role="php" />
     <file baseinstalldir="/" name="OutputError.php" role="php" />
     <file baseinstalldir="/" name="SelfDescribing.php" role="php" />
     <file baseinstalldir="/" name="SkippedTestError.php" role="php" />
     <file baseinstalldir="/" name="SkippedTest.php" role="php" />
     <file baseinstalldir="/" name="SkippedTestSuiteError.php" role="php" />
     <file baseinstalldir="/" name="SyntheticError.php" role="php" />
     <file baseinstalldir="/" name="TestCase.php" role="php" />
     <file baseinstalldir="/" name="TestFailure.php" role="php" />
     <file baseinstalldir="/" name="TestListener.php" role="php" />
     <file baseinstalldir="/" name="Test.php" role="php" />
     <file baseinstalldir="/" name="TestResult.php" role="php" />
     <file baseinstalldir="/" name="TestSuite.php" role="php" />
     <file baseinstalldir="/" name="Warning.php" role="php" />
    </dir>
    <dir name="Runner">
     <file baseinstalldir="/" name="BaseTestRunner.php" role="php" />
     <file baseinstalldir="/" name="StandardTestSuiteLoader.php" role="php" />
     <file baseinstalldir="/" name="TestSuiteLoader.php" role="php" />
     <file baseinstalldir="/" name="Version.php" role="php" />
    </dir>
    <dir name="TextUI">
     <file baseinstalldir="/" name="Command.php" role="php" />
     <file baseinstalldir="/" name="ResultPrinter.php" role="php" />
     <file baseinstalldir="/" name="TestRunner.php" role="php" />
    </dir>
    <dir name="Util">
     <dir name="DeprecatedFeature">
      <file baseinstalldir="/" name="Logger.php" role="php" />
     </dir>
     <dir name="Log">
      <file baseinstalldir="/" name="JSON.php" role="php" />
      <file baseinstalldir="/" name="JUnit.php" role="php" />
      <file baseinstalldir="/" name="TAP.php" role="php" />
     </dir>
     <dir name="PHP">
      <file baseinstalldir="/" name="Default.php" role="php" />
      <file baseinstalldir="/" name="Windows.php" role="php" />
     </dir>
     <dir name="TestDox">
      <dir name="ResultPrinter">
       <file baseinstalldir="/" name="HTML.php" role="php" />
       <file baseinstalldir="/" name="Text.php" role="php" />
      </dir>
      <file baseinstalldir="/" name="NamePrettifier.php" role="php" />
      <file baseinstalldir="/" name="ResultPrinter.php" role="php" />
     </dir>
     <file baseinstalldir="/" name="Class.php" role="php" />
     <file baseinstalldir="/" name="Configuration.php" role="php" />
     <file baseinstalldir="/" name="DeprecatedFeature.php" role="php" />
     <file baseinstalldir="/" name="Diff.php" role="php" />
     <file baseinstalldir="/" name="ErrorHandler.php" role="php" />
     <file baseinstalldir="/" name="Fileloader.php" role="php" />
     <file baseinstalldir="/" name="Filesystem.php" role="php" />
     <file baseinstalldir="/" name="Filter.php" role="php" />
     <file baseinstalldir="/" name="Getopt.php" role="php" />
     <file baseinstalldir="/" name="GlobalState.php" role="php" />
     <file baseinstalldir="/" name="InvalidArgumentHelper.php" role="php" />
     <file baseinstalldir="/" name="PHP.php" role="php">
      <tasks:replace from="@php_bin@" to="php_bin" type="pear-config" />
     </file>
     <file baseinstalldir="/" name="Printer.php" role="php" />
     <file baseinstalldir="/" name="String.php" role="php" />
     <file baseinstalldir="/" name="Test.php" role="php" />
     <file baseinstalldir="/" name="TestSuiteIterator.php" role="php" />
     <file baseinstalldir="/" name="Type.php" role="php" />
     <file baseinstalldir="/" name="XML.php" role="php" />
    </dir>
    <file baseinstalldir="/" name="Autoload.php" role="php" />
   </dir>
   <file baseinstalldir="/" name="CONTRIBUTING.md" role="doc" />
   <file baseinstalldir="/" name="LICENSE" role="doc" />
   <file baseinstalldir="/" name="README.md" role="doc" />
   <file baseinstalldir="/" name="phpunit.php" role="script">
    <tasks:replace from="/usr/bin/env php" to="php_bin" type="pear-config" />
    <tasks:replace from="@php_bin@" to="php_bin" type="pear-config" />
    <tasks:replace from="@php_dir@" to="php_dir" type="pear-config" />
   </file>
   <file baseinstalldir="/" name="phpunit.bat" role="script">
    <tasks:replace from="@php_bin@" to="php_bin" type="pear-config" />
    <tasks:replace from="@bin_dir@" to="bin_dir" type="pear-config" />
   </file>
  </dir>
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.3.3</min>
   </php>
   <pearinstaller>
    <min>1.9.4</min>
   </pearinstaller>
   <package>
    <name>File_Iterator</name>
    <channel>pear.phpunit.de</channel>
    <min>1.3.1</min>
   </package>
   <package>
    <name>Text_Template</name>
    <channel>pear.phpunit.de</channel>
    <min>1.1.1</min>
   </package>
   <package>
    <name>PHP_CodeCoverage</name>
    <channel>pear.phpunit.de</channel>
    <min>1.2.1</min>
    <max>1.2.99</max>
   </package>
   <package>
    <name>PHP_Timer</name>
    <channel>pear.phpunit.de</channel>
    <min>1.0.4</min>
   </package>
   <package>
    <name>PHPUnit_MockObject</name>
    <channel>pear.phpunit.de</channel>
    <min>1.2.0</min>
    <max>1.2.99</max>
   </package>
   <package>
    <name>Yaml</name>
    <channel>pear.symfony.com</channel>
    <min>2.0.0</min>
    <max>2.99.99</max>
   </package>
   <extension>
    <name>dom</name>
   </extension>
   <extension>
    <name>pcre</name>
   </extension>
  </required>
  <optional>
   <package>
    <name>PHP_Invoker</name>
    <channel>pear.phpunit.de</channel>
    <min>1.1.0</min>
    <max>1.1.99</max>
   </package>
   <extension>
    <name>json</name>
   </extension>
   <extension>
    <name>simplexml</name>
   </extension>
   <extension>
    <name>tokenizer</name>
   </extension>
  </optional>
 </dependencies>
 <phprelease>
  <installconditions>
   <os>
    <name>windows</name>
   </os>
  </installconditions>
  <filelist>
   <install as="phpunit" name="phpunit.php" />
   <install as="phpunit.bat" name="phpunit.bat" />
  </filelist>
 </phprelease>
 <phprelease>
  <filelist>
   <install as="phpunit" name="phpunit.php" />
   <ignore name="phpunit.bat" />
  </filelist>
 </phprelease>
</package>
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:annotation>
    <xs:documentation source="http://www.phpunit.de/manual/3.7/en/appendixes.configuration.html">
      This Schema file defines the rules by which the XML configuration file of PHPUnit 3.7 may be structured.
    </xs:documentation>
    <xs:appinfo source="http://www.phpunit.de/manual/current/en/appendixes.configuration.html"/>
  </xs:annotation>
  <xs:element name="phpunit" type="phpUnitType">
    <xs:annotation>
      <xs:documentation>Root Element</xs:documentation>
    </xs:annotation>
  </xs:element>
  <xs:complexType name="filtersType">
    <xs:choice>
      <xs:sequence>
        <xs:element name="blacklist" type="filterType"/>
        <xs:element name="whitelist" type="whiteListType" minOccurs="0"/>
      </xs:sequence>
      <xs:sequence>
        <xs:element name="whitelist" type="whiteListType"/>
      </xs:sequence>
    </xs:choice>
  </xs:complexType>
  <xs:complexType name="filterType">
    <xs:sequence>
      <xs:group ref="pathGroup"/>
      <xs:element name="exclude" maxOccurs="unbounded" minOccurs="0">
        <xs:complexType>
          <xs:group ref="pathGroup"/>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="whiteListType">
    <xs:complexContent>
      <xs:extension base="filterType">
        <xs:attribute name="processUncoveredFilesFromWhitelist" default="true" type="xs:boolean"/>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
  <xs:complexType name="groupsType">
    <xs:choice>
      <xs:sequence>
        <xs:element name="include" type="groupType"/>
        <xs:element name="exclude" type="groupType" minOccurs="0"/>
      </xs:sequence>
      <xs:sequence>
        <xs:element name="exclude" type="groupType"/>
      </xs:sequence>
    </xs:choice>
  </xs:complexType>
  <xs:complexType name="groupType">
    <xs:sequence>
      <xs:element name="group" type="xs:string" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="listenersType">
    <xs:sequence>
      <xs:element name="listener" type="objectType" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="objectType">
    <xs:sequence>
      <xs:element name="arguments" minOccurs="0">
        <xs:complexType>
          <xs:group ref="argumentsGroup"/>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
    <xs:attribute name="class" type="xs:string" use="required"/>
    <xs:attribute name="file" type="xs:anyURI"/>
  </xs:complexType>
  <xs:complexType name="arrayType">
    <xs:sequence>
      <xs:element name="element" type="argumentType" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="argumentType">
    <xs:group ref="argumentChoice"/>
    <xs:attribute name="key" use="required"/>
  </xs:complexType>
  <xs:group name="argumentsGroup">
    <xs:sequence>
      <xs:element name="array" type="arrayType" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="integer" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="string" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="double" type="xs:double" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="null" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="object" type="objectType" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="file" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="directory" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:group>
  <xs:group name="argumentChoice">
    <xs:choice>
      <xs:element name="array" type="arrayType" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="integer" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="string" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="double" type="xs:double" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="null" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="object" type="objectType" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="file" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="directory" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/>
    </xs:choice>
  </xs:group>
  <xs:complexType name="loggersType">
    <xs:sequence>
      <xs:element name="log" type="loggerType" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="loggerType">
    <xs:attribute name="type">
      <xs:simpleType>
        <xs:restriction base="xs:string">
          <xs:enumeration value="coverage-html"/>
          <xs:enumeration value="coverage-clover"/>
          <xs:enumeration value="json"/>
          <xs:enumeration value="plain"/>
          <xs:enumeration value="tap"/>
          <xs:enumeration value="junit"/>
          <xs:enumeration value="testdox-html"/>
          <xs:enumeration value="testdox-text"/>
        </xs:restriction>
      </xs:simpleType>
    </xs:attribute>
    <xs:attribute name="target" type="xs:anyURI"/>
    <xs:attribute name="title" type="xs:string"/>
    <xs:attribute name="charset" type="xs:string" default="UTF-8"/>
    <xs:attribute name="yui" type="xs:boolean" default="true"/>
    <xs:attribute name="highlight" type="xs:boolean" default="false"/>
    <xs:attribute name="lowUpperBound" type="xs:nonNegativeInteger" default="35"/>
    <xs:attribute name="highLowerBound" type="xs:nonNegativeInteger" default="70"/>
    <xs:attribute name="logIncompleteSkipped" type="xs:boolean" default="false"/>
  </xs:complexType>
  <xs:group name="pathGroup">
    <xs:sequence>
      <xs:element name="directory" type="directoryFilterType" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="file" type="fileFilterType" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:group>
  <xs:complexType name="directoryFilterType">
    <xs:simpleContent>
      <xs:extension base="xs:anyURI">
        <xs:attribute type="xs:string" name="suffix" default="Test.php"/>
        <xs:attributeGroup ref="phpVersionGroup"/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
  <xs:complexType name="fileFilterType">
    <xs:simpleContent>
      <xs:extension base="xs:anyURI">
        <xs:attributeGroup ref="phpVersionGroup"/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
  <xs:attributeGroup name="phpVersionGroup">
    <xs:attribute name="phpVersion" type="xs:string" default="5.3.0"/>
    <xs:attribute name="phpVersionOperator" type="xs:string" default="&gt;="/>
  </xs:attributeGroup>
  <xs:complexType name="phpType">
    <xs:sequence>
      <xs:element name="includePath" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="ini" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="const" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="var" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="env" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="post" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="get" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="cookie" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="server" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="files" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
      <xs:element name="request" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="namedValueType">
    <xs:attribute name="name" use="required" type="xs:string"/>
    <xs:attribute name="value" use="required" type="xs:anySimpleType"/>
  </xs:complexType>
  <xs:complexType name="phpUnitType">
    <xs:annotation>
      <xs:documentation>The main type specifying the document structure</xs:documentation>
    </xs:annotation>
    <xs:group ref="configGroup"/>
    <xs:attributeGroup ref="configAttributeGroup"/>
  </xs:complexType>
  <xs:attributeGroup name="configAttributeGroup">
    <xs:attribute name="backupGlobals" type="xs:boolean" default="true"/>
    <xs:attribute name="backupStaticAttributes" type="xs:boolean" default="false"/>
    <xs:attribute name="bootstrap" type="xs:anyURI"/>
    <xs:attribute name="cacheTokens" type="xs:boolean"/>
    <xs:attribute name="colors" type="xs:boolean" default="false"/>
    <xs:attribute name="convertErrorsToExceptions" type="xs:boolean" default="true"/>
    <xs:attribute name="convertNoticesToExceptions" type="xs:boolean" default="true"/>
    <xs:attribute name="convertWarningsToExceptions" type="xs:boolean" default="true"/>
    <xs:attribute name="forceCoversAnnotation" type="xs:boolean" default="false"/>
    <xs:attribute name="mapTestClassNameToCoveredClassName" type="xs:boolean" default="false"/>
    <xs:attribute name="printerClass" type="xs:string" default="PHPUnit_TextUI_ResultPrinter"/>
    <xs:attribute name="printerFile" type="xs:anyURI"/>
    <xs:attribute name="processIsolation" type="xs:boolean" default="false"/>
    <xs:attribute name="stopOnError" type="xs:boolean" default="false"/>
    <xs:attribute name="stopOnFailure" type="xs:boolean" default="false"/>
    <xs:attribute name="stopOnIncomplete" type="xs:boolean" default="false"/>
    <xs:attribute name="stopOnSkipped" type="xs:boolean" default="false"/>
    <xs:attribute name="strict" type="xs:boolean" default="false"/>
    <xs:attribute name="testSuiteLoaderClass" type="xs:string" default="PHPUnit_Runner_StandardTestSuiteLoader"/>
    <xs:attribute name="testSuiteLoaderFile" type="xs:anyURI"/>
    <xs:attribute name="timeoutForSmallTests" type="xs:integer" default="1"/>
    <xs:attribute name="timeoutForMediumTests" type="xs:integer" default="10"/>
    <xs:attribute name="timeoutForLargeTests" type="xs:integer" default="60"/>
    <xs:attribute name="verbose" type="xs:boolean" default="false"/>
  </xs:attributeGroup>
  <xs:group name="configGroup">
    <xs:all>
      <xs:element ref="testSuiteFacet" minOccurs="0"/>
      <xs:element name="groups" type="groupsType" minOccurs="0"/>
      <xs:element name="filter" type="filtersType" minOccurs="0"/>
      <xs:element name="logging" type="loggersType" minOccurs="0"/>
      <xs:element name="listeners" type="listenersType" minOccurs="0"/>
      <xs:element name="php" type="phpType" minOccurs="0"/>
      <xs:element name="selenium" type="seleniumType" minOccurs="0"/>
    </xs:all>
  </xs:group>
  <xs:complexType name="seleniumType">
    <xs:sequence>
      <xs:element name="browser" type="browserType"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="browserType">
    <xs:attribute name="name" type="xs:string"/>
    <xs:attribute name="browser" type="xs:string"/>
    <xs:attribute name="host" type="xs:anyURI"/>
    <xs:attribute name="port" type="xs:nonNegativeInteger"/>
    <xs:attribute name="timeout" type="xs:nonNegativeInteger"/>
  </xs:complexType>
  <xs:element name="testSuiteFacet" abstract="true"/>
  <xs:element name="testsuite" type="testSuiteType" substitutionGroup="testSuiteFacet"/>
  <xs:element name="testsuites" type="testSuitesType" substitutionGroup="testSuiteFacet"/>
  <xs:complexType name="testSuitesType">
    <xs:sequence>
      <xs:element name="testsuite" type="testSuiteType"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="testSuiteType">
    <xs:sequence>
      <xs:group ref="pathGroup"/>
      <xs:element name="exclude" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
    <xs:attribute name="name" type="xs:string" use="required"/>
  </xs:complexType>
</xs:schema>
<?xml version="1.0"?>

<ruleset name="Sebastian"
         xmlns="http://pmd.sf.net/ruleset/1.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
         xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
  <description>Sebastian Bergmann's ruleset</description>

  <rule ref="rulesets/codesize.xml/CyclomaticComplexity" />
  <rule ref="rulesets/codesize.xml/NPathComplexity" />
  <rule ref="rulesets/codesize.xml/ExcessiveClassComplexity" />
  <rule ref="rulesets/codesize.xml/ExcessiveClassLength" />
  <rule ref="rulesets/codesize.xml/ExcessiveMethodLength" />
  <rule ref="rulesets/codesize.xml/ExcessiveParameterList" />

  <rule ref="rulesets/design.xml/EvalExpression" />
  <rule ref="rulesets/design.xml/ExitExpression" />
  <rule ref="rulesets/design.xml/GotoStatement" />

  <rule ref="rulesets/naming.xml/ConstructorWithNameAsEnclosingClass" />

  <rule ref="rulesets/unusedcode.xml/UnusedFormalParameter" />
  <rule ref="rulesets/unusedcode.xml/UnusedLocalVariable" />
  <rule ref="rulesets/unusedcode.xml/UnusedPrivateField" />
  <rule ref="rulesets/unusedcode.xml/UnusedPrivateMethod" />
</ruleset>

<?php
if ($GLOBALS['_SERVER']['SCRIPT_NAME'] != '-') {
    $phar = realpath($GLOBALS['_SERVER']['SCRIPT_NAME']);
} else {
    $files = get_included_files();
    $phar = $files[0];
}

define('__PHPUNIT_PHAR__', str_replace(DIRECTORY_SEPARATOR, '/', $phar));

spl_autoload_register(
  function ($class)
  {
      static $classes = NULL;

      if ($classes === NULL) {
          $classes = array(
            ___CLASSLIST___
          );
      }

      $class = strtolower($class);

      if (isset($classes[$class])) {
          require 'phar://___PHAR___' . $classes[$class];
      }
  }
);

Phar::mapPhar('___PHAR___');

if ($GLOBALS['_SERVER']['SCRIPT_NAME'] != '-') {
    PHPUnit_TextUI_Command::main();
}

__HALT_COMPILER();

<?php
require dirname(__DIR__) . '/PHPUnit/Autoload.php';

$buffer  = '';
$class   = new ReflectionClass('PHPUnit_Framework_Assert');
$methods = array();

foreach ($class->getMethods() as $method) {
    $docblock = $method->getDocComment();
    $name     = $method->getName();

    if (strpos($name, 'assert') === 0 ||
        strpos($docblock, '@return PHPUnit_Framework_Constraint') !== FALSE) {
        $methods[$name] = array(
          'class'    => 'PHPUnit_Framework_Assert',
          'docblock' => $docblock,
          'sigDecl'  => str_replace(
            array('= false', '= true'),
            array('= FALSE', '= TRUE'),
            PHPUnit_Util_Class::getMethodParameters($method)
          ),
          'sigCall'  => PHPUnit_Util_Class::getMethodParameters($method, TRUE)
        );
    }
}

$class = new ReflectionClass('PHPUnit_Framework_TestCase');

foreach ($class->getMethods() as $method) {
    $docblock = $method->getDocComment();
    $name     = $method->getName();

    if (strpos($docblock, '@return PHPUnit_Framework_MockObject_Matcher') !== FALSE ||
        strpos($docblock, '@return PHPUnit_Framework_MockObject_Stub') !== FALSE) {
        $methods[$name] = array(
          'class'    => 'PHPUnit_Framework_TestCase',
          'docblock' => $docblock,
          'sigDecl'  => str_replace(
            array('= false', '= true'),
            array('= FALSE', '= TRUE'),
            PHPUnit_Util_Class::getMethodParameters($method)
          ),
          'sigCall'  => PHPUnit_Util_Class::getMethodParameters($method, TRUE)
        );
    }
}

ksort($methods);

foreach ($methods as $name => $data) {
    $buffer .= sprintf(
      "\n\n%s\nfunction %s(%s)\n{\n    return call_user_func_array(\n      '%s::%s',\n      func_get_args()\n    );\n}",
      str_replace('    ', '', $data['docblock']),
      $name,
      $data['sigDecl'],
      $data['class'],
      $name,
      $data['sigCall']
    );
}

$template = new Text_Template(dirname(__DIR__) . '/PHPUnit/Framework/Assert/Functions.php.in');
$template->setVar(array('functions' => $buffer));
$template->renderTo(dirname(__DIR__) . '/PHPUnit/Framework/Assert/Functions.php');
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://phpunit.de/phpunit.xsd"
         backupGlobals="false"
         colors="true"
         verbose="true">
  <testsuites>
    <testsuite name="PHPUnit">
      <directory suffix="Test.php">../Tests/Framework</directory>
      <directory suffix=".phpt">../Tests/Framework/MockObject</directory>
      <directory suffix="Test.php">../Tests/Extensions</directory>
      <directory suffix=".phpt">../Tests/Regression</directory>
      <directory suffix="Test.php">../Tests/Runner</directory>
      <directory suffix=".phpt">../Tests/TextUI</directory>
      <directory suffix="Test.php">../Tests/Util</directory>
    </testsuite>
  </testsuites>

  <logging>
    <log type="coverage-text" target="php://stdout"/>
  </logging>

  <filter>
    <whitelist processUncoveredFilesFromWhitelist="true">
      <directory suffix=".php">../PHPUnit</directory>
      <exclude>
       <file>../PHPUnit/Autoload.php</file>
       <file>../PHPUnit/Framework/Assert/Functions.php</file>
      </exclude>
    </whitelist>
  </filter>

  <php>
    <const name="PHPUNIT_TESTSUITE" value="true"/>
  </php>
</phpunit>
<?php
class PHPCS_Sniffs_ControlStructures_ControlSignatureSniff extends PHP_CodeSniffer_Standards_AbstractPatternSniff
{
    public function __construct()
    {
        parent::__construct(true);
    }

    protected function getPatterns()
    {
        return array(
          'do {EOL...} while (...);EOL',
          'while (...) {EOL',
          'for (...) {EOL',
          'if (...) {EOL',
          'foreach (...) {EOL',
          // Decide wether to use '}EOLelse' or '} else'
          #'}EOLelse if (...) {EOL',
          #'}EOLelse {EOL',
          'do {EOL',
        );
    }
}
<?php
class PHPCS_Sniffs_Whitespace_ConcatenationSpacingSniff implements PHP_CodeSniffer_Sniff
{
    public function register()
    {
        return array(T_STRING_CONCAT);
    }

    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE ||
            $tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) {

            $phpcsFile->addError(
              'Concatenation operator must be surrounded by whitespace',
              $stackPtr
            );
        }
    }
}
<?xml version="1.0"?>
<ruleset name="Sebastian">
 <description>Sebastian Bergmann's coding standard</description>

 <rule ref="Generic.CodeAnalysis.ForLoopShouldBeWhileLoop"/>
 <rule ref="Generic.CodeAnalysis.ForLoopWithTestFunctionCall"/>
 <rule ref="Generic.CodeAnalysis.JumbledIncrementer"/>
 <rule ref="Generic.CodeAnalysis.UnconditionalIfStatement"/>
 <rule ref="Generic.CodeAnalysis.UnnecessaryFinalModifier"/>
 <rule ref="Generic.CodeAnalysis.UselessOverridingMethod"/>

 <rule ref="Generic.Commenting.Todo"/>

 <rule ref="Generic.ControlStructures.InlineControlStructure"/>

 <rule ref="Generic.Files.LineEndings"/>

 <rule ref="Generic.Formatting.DisallowMultipleStatements"/>
 <rule ref="Generic.Formatting.NoSpaceAfterCast"/>

 <rule ref="Generic.Functions.OpeningFunctionBraceBsdAllman"/>
 <rule ref="PEAR.Functions.ValidDefaultValue"/>

 <rule ref="Generic.NamingConventions.ConstructorName"/>
 <rule ref="Generic.NamingConventions.UpperCaseConstantName"/>
 <rule ref="PEAR.NamingConventions.ValidClassName"/>

 <rule ref="Generic.PHP.DisallowShortOpenTag"/>
 <rule ref="Generic.PHP.NoSilencedErrors"/>
 <rule ref="Generic.PHP.UpperCaseConstant"/>

 <rule ref="Generic.WhiteSpace.DisallowTabIndent"/>
 <rule ref="Generic.WhiteSpace.ScopeIndent"/>
 <rule ref="Squiz.WhiteSpace.SuperfluousWhitespace"/>
</ruleset>
@echo off
REM PHPUnit
REM
REM Copyright (c) 2002-2010, Sebastian Bergmann <sebastian@phpunit.de>.
REM All rights reserved.
REM
REM Redistribution and use in source and binary forms, with or without
REM modification, are permitted provided that the following conditions
REM are met:
REM
REM   * Redistributions of source code must retain the above copyright
REM     notice, this list of conditions and the following disclaimer.
REM
REM   * Redistributions in binary form must reproduce the above copyright
REM     notice, this list of conditions and the following disclaimer in
REM     the documentation and/or other materials provided with the
REM     distribution.
REM
REM   * Neither the name of Sebastian Bergmann nor the names of his
REM     contributors may be used to endorse or promote products derived
REM     from this software without specific prior written permission.
REM
REM THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
REM "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
REM LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
REM FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
REM COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
REM INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
REM BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
REM LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
REM CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
REM LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
REM ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
REM POSSIBILITY OF SUCH DAMAGE.
REM

if "%PHPBIN%" == "" set PHPBIN=@php_bin@
if not exist "%PHPBIN%" if "%PHP_PEAR_PHP_BIN%" neq "" goto USE_PEAR_PATH
GOTO RUN
:USE_PEAR_PATH
set PHPBIN=%PHP_PEAR_PHP_BIN%
:RUN
"%PHPBIN%" "@bin_dir@\phpunit" %*
PHPUnit

Copyright (c) 2002-2013, Sebastian Bergmann <sebastian@phpunit.de>.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

 * Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in
   the documentation and/or other materials provided with the
   distribution.

 * Neither the name of Sebastian Bergmann nor the names of his
   contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Extensions_PhptTestCase
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.1.4
 */

if (stream_resolve_include_path('PEAR/RunTest.php')) {
    $currentErrorReporting = error_reporting(E_ERROR | E_WARNING | E_PARSE);
    require_once 'PEAR/RunTest.php';
    error_reporting($currentErrorReporting);
}

/**
 * Wrapper to run .phpt test cases.
 *
 * @package    PHPUnit
 * @subpackage Extensions_PhptTestCase
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.1.4
 */
class PHPUnit_Extensions_PhptTestCase implements PHPUnit_Framework_Test, PHPUnit_Framework_SelfDescribing
{
    /**
     * The filename of the .phpt file.
     *
     * @var    string
     */
    protected $filename;

    /**
     * Options for PEAR_RunTest.
     *
     * @var    array
     */
    protected $options = array();

    /**
     * Constructs a test case with the given filename.
     *
     * @param  string $filename
     * @param  array  $options
     */
    public function __construct($filename, array $options = array())
    {
        if (!is_string($filename)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        if (!is_file($filename)) {
            throw new PHPUnit_Framework_Exception(
              sprintf(
                'File "%s" does not exist.',
                $filename
              )
            );
        }

        $this->filename = $filename;
        $this->options  = $options;
    }

    /**
     * Counts the number of test cases executed by run(TestResult result).
     *
     * @return integer
     */
    public function count()
    {
        return 1;
    }

    /**
     * Runs a test and collects its result in a TestResult instance.
     *
     * @param  PHPUnit_Framework_TestResult $result
     * @param  array                        $options
     * @return PHPUnit_Framework_TestResult
     */
    public function run(PHPUnit_Framework_TestResult $result = NULL, array $options = array())
    {
        if (!class_exists('PEAR_RunTest', FALSE)) {
            throw new PHPUnit_Framework_Exception('Class PEAR_RunTest not found.');
        }

        if (isset($GLOBALS['_PEAR_destructor_object_list']) &&
            is_array($GLOBALS['_PEAR_destructor_object_list']) &&
            !empty($GLOBALS['_PEAR_destructor_object_list'])) {
            $pearDestructorObjectListCount = count($GLOBALS['_PEAR_destructor_object_list']);
        } else {
            $pearDestructorObjectListCount = 0;
        }

        if ($result === NULL) {
            $result = new PHPUnit_Framework_TestResult;
        }

        $coverage = $result->getCollectCodeCoverageInformation();
        $options  = array_merge($options, $this->options);

        if (!isset($options['include_path'])) {
            $options['include_path'] = get_include_path();
        }

        if ($coverage) {
            $options['coverage'] = TRUE;
        } else {
            $options['coverage'] = FALSE;
        }

        $currentErrorReporting = error_reporting(E_ERROR | E_WARNING | E_PARSE);
        $runner                = new PEAR_RunTest(new PHPUnit_Extensions_PhptTestCase_Logger, $options);

        if ($coverage) {
            $runner->xdebug_loaded = TRUE;
        } else {
            $runner->xdebug_loaded = FALSE;
        }

        $result->startTest($this);

        PHP_Timer::start();

        $buffer = $runner->run($this->filename, $options);
        $time   = PHP_Timer::stop();

        error_reporting($currentErrorReporting);

        $base         = basename($this->filename);
        $path         = dirname($this->filename);
        $coverageFile = $path . DIRECTORY_SEPARATOR . str_replace(
                          '.phpt', '.xdebug', $base
                        );
        $diffFile     = $path . DIRECTORY_SEPARATOR . str_replace(
                          '.phpt', '.diff', $base
                        );
        $expFile      = $path . DIRECTORY_SEPARATOR . str_replace(
                          '.phpt', '.exp', $base
                        );
        $logFile      = $path . DIRECTORY_SEPARATOR . str_replace(
                          '.phpt', '.log', $base
                        );
        $outFile      = $path . DIRECTORY_SEPARATOR . str_replace(
                          '.phpt', '.out', $base
                        );
        $phpFile      = $path . DIRECTORY_SEPARATOR . str_replace(
                          '.phpt', '.php', $base
                        );

        if (is_object($buffer) && $buffer instanceof PEAR_Error) {
            $result->addError(
              $this,
              new PHPUnit_Framework_Exception($buffer->getMessage()),
              $time
            );
        }

        else if ($buffer == 'SKIPPED') {
            $result->addFailure($this, new PHPUnit_Framework_SkippedTestError, 0);
        }

        else if ($buffer != 'PASSED') {
            $expContent = file_get_contents($expFile);
            $outContent = file_get_contents($outFile);

            $result->addFailure(
              $this,
              new PHPUnit_Framework_ComparisonFailure(
                $expContent,
                $outContent,
                $expContent,
                $outContent
              ),
              $time
            );
        }

        foreach (array($diffFile, $expFile, $logFile, $phpFile, $outFile) as $file) {
            if (file_exists($file)) {
                unlink($file);
            }
        }

        if ($coverage && file_exists($coverageFile)) {
            eval('$coverageData = ' . file_get_contents($coverageFile) . ';');
            unset($coverageData[$phpFile]);

            $result->getCodeCoverage()->append($coverageData, $this);
            unlink($coverageFile);
        }

        $result->endTest($this, $time);

        // Do not invoke PEAR's destructor mechanism for PHP 4
        // as it raises an E_STRICT.
        if ($pearDestructorObjectListCount == 0) {
            unset($GLOBALS['_PEAR_destructor_object_list']);
        } else {
            $count = count($GLOBALS['_PEAR_destructor_object_list']) - $pearDestructorObjectListCount;

            for ($i = 0; $i < $count; $i++) {
                array_pop($GLOBALS['_PEAR_destructor_object_list']);
            }
        }

        return $result;
    }

    /**
     * Returns the name of the test case.
     *
     * @return string
     */
    public function getName()
    {
        return $this->toString();
    }

    /**
     * Returns a string representation of the test case.
     *
     * @return string
     */
    public function toString()
    {
        return $this->filename;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

/**
 * A Decorator that runs a test repeatedly.
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.0.0
 */
class PHPUnit_Extensions_RepeatedTest extends PHPUnit_Extensions_TestDecorator
{
    /**
     * @var mixed
     */
    protected $filter = FALSE;

    /**
     * @var array
     */
    protected $groups = array();

    /**
     * @var array
     */
    protected $excludeGroups = array();

    /**
     * @var boolean
     */
    protected $processIsolation = FALSE;

    /**
     * @var integer
     */
    protected $timesRepeat = 1;

    /**
     * Constructor.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  integer                $timesRepeat
     * @param  mixed                  $filter
     * @param  array                  $groups
     * @param  array                  $excludeGroups
     * @param  boolean                $processIsolation
     * @throws PHPUnit_Framework_Exception
     */
    public function __construct(PHPUnit_Framework_Test $test, $timesRepeat = 1, $filter = FALSE, array $groups = array(), array $excludeGroups = array(), $processIsolation = FALSE)
    {
        parent::__construct($test);

        if (is_integer($timesRepeat) &&
            $timesRepeat >= 0) {
            $this->timesRepeat = $timesRepeat;
        } else {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(
              2, 'positive integer'
            );
        }

        $this->filter           = $filter;
        $this->groups           = $groups;
        $this->excludeGroups    = $excludeGroups;
        $this->processIsolation = $processIsolation;
    }

    /**
     * Counts the number of test cases that
     * will be run by this test.
     *
     * @return integer
     */
    public function count()
    {
        return $this->timesRepeat * count($this->test);
    }

    /**
     * Runs the decorated test and collects the
     * result in a TestResult.
     *
     * @param  PHPUnit_Framework_TestResult $result
     * @return PHPUnit_Framework_TestResult
     * @throws PHPUnit_Framework_Exception
     */
    public function run(PHPUnit_Framework_TestResult $result = NULL)
    {
        if ($result === NULL) {
            $result = $this->createResult();
        }

        //@codingStandardsIgnoreStart
        for ($i = 0; $i < $this->timesRepeat && !$result->shouldStop(); $i++) {
            //@codingStandardsIgnoreEnd
            if ($this->test instanceof PHPUnit_Framework_TestSuite) {
                $this->test->run(
                  $result,
                  $this->filter,
                  $this->groups,
                  $this->excludeGroups,
                  $this->processIsolation
                );
            } else {
                $this->test->run($result);
            }
        }

        return $result;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Extensions_PhptTestCase
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.1.4
 */

/**
 * Suite for .phpt test cases.
 *
 * @package    PHPUnit
 * @subpackage Extensions_PhptTestCase
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.1.4
 */
class PHPUnit_Extensions_PhptTestSuite extends PHPUnit_Framework_TestSuite
{
    /**
     * Constructs a new TestSuite for .phpt test cases.
     *
     * @param  string $directory
     * @param  array  $options Array with ini settings for the php instance run,
     *                         key being the name if the setting, value the ini value.
     * @throws PHPUnit_Framework_Exception
     */
    public function __construct($directory, array $options = array())
    {
        if (is_string($directory) && is_dir($directory)) {
            $this->setName($directory);

            $facade = new File_Iterator_Facade;
            $files  = $facade->getFilesAsArray($directory, '.phpt');

            foreach ($files as $file) {
                $this->addTestFile($file, $options);
            }
        } else {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'directory name');
        }
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Extensions
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

/**
 * A Decorator for Tests.
 *
 * Use TestDecorator as the base class for defining new
 * test decorators. Test decorator subclasses can be introduced
 * to add behaviour before or after a test is run.
 *
 * @package    PHPUnit
 * @subpackage Extensions
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.0.0
 */
class PHPUnit_Extensions_TestDecorator extends PHPUnit_Framework_Assert implements PHPUnit_Framework_Test, PHPUnit_Framework_SelfDescribing
{
    /**
     * The Test to be decorated.
     *
     * @var    object
     */
    protected $test = NULL;

    /**
     * Constructor.
     *
     * @param  PHPUnit_Framework_Test $test
     */
    public function __construct(PHPUnit_Framework_Test $test)
    {
        $this->test = $test;
    }

    /**
     * Returns a string representation of the test.
     *
     * @return string
     */
    public function toString()
    {
        return $this->test->toString();
    }

    /**
     * Runs the test and collects the
     * result in a TestResult.
     *
     * @param  PHPUnit_Framework_TestResult $result
     */
    public function basicRun(PHPUnit_Framework_TestResult $result)
    {
        $this->test->run($result);
    }

    /**
     * Counts the number of test cases that
     * will be run by this test.
     *
     * @return integer
     */
    public function count()
    {
        return count($this->test);
    }

    /**
     * Creates a default TestResult object.
     *
     * @return PHPUnit_Framework_TestResult
     */
    protected function createResult()
    {
        return new PHPUnit_Framework_TestResult;
    }

    /**
     * Returns the test to be run.
     *
     * @return PHPUnit_Framework_Test
     */
    public function getTest()
    {
        return $this->test;
    }

    /**
     * Runs the decorated test and collects the
     * result in a TestResult.
     *
     * @param  PHPUnit_Framework_TestResult $result
     * @return PHPUnit_Framework_TestResult
     */
    public function run(PHPUnit_Framework_TestResult $result = NULL)
    {
        if ($result === NULL) {
            $result = $this->createResult();
        }

        $this->basicRun($result);

        return $result;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Extensions_TicketListener
 * @author     Sean Coates <sean@caedmon.net>
 * @author     Raphael Stolt <raphael.stolt@gmail.com>
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.4.0
 */

/**
 * Base class for test listeners that interact with an issue tracker.
 *
 * @package    PHPUnit
 * @subpackage Extensions_TicketListener
 * @author     Sean Coates <sean@caedmon.net>
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.4.0
 */
abstract class PHPUnit_Extensions_TicketListener implements PHPUnit_Framework_TestListener
{
    /**
     * @var array
     */
    protected $ticketCounts = array();

    /**
     * @var boolean
     */
    protected $ran = FALSE;

    /**
     * An error occurred.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  Exception              $e
     * @param  float                  $time
     */
    public function addError(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
    }

    /**
     * A failure occurred.
     *
     * @param  PHPUnit_Framework_Test                 $test
     * @param  PHPUnit_Framework_AssertionFailedError $e
     * @param  float                                  $time
     */
    public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time)
    {
    }

    /**
     * Incomplete test.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  Exception              $e
     * @param  float                  $time
     */
    public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
    }

    /**
     * Skipped test.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  Exception              $e
     * @param  float                  $time
     * @since  Method available since Release 3.0.0
     */
    public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
    }

    /**
     * A test suite started.
     *
     * @param  PHPUnit_Framework_TestSuite $suite
     * @since  Method available since Release 2.2.0
     */
    public function startTestSuite(PHPUnit_Framework_TestSuite $suite)
    {
    }

    /**
     * A test suite ended.
     *
     * @param  PHPUnit_Framework_TestSuite $suite
     * @since  Method available since Release 2.2.0
     */
    public function endTestSuite(PHPUnit_Framework_TestSuite $suite)
    {
    }

    /**
     * A test started.
     *
     * @param  PHPUnit_Framework_Test $test
     */
    public function startTest(PHPUnit_Framework_Test $test)
    {
        if (!$test instanceof PHPUnit_Framework_Warning) {
            if ($this->ran) {
                return;
            }

            $name    = $test->getName(FALSE);
            $tickets = PHPUnit_Util_Test::getTickets(get_class($test), $name);

            foreach ($tickets as $ticket) {
                $this->ticketCounts[$ticket][$name] = 1;
            }

            $this->ran = TRUE;
        }
    }

    /**
     * A test ended.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  float                  $time
     */
    public function endTest(PHPUnit_Framework_Test $test, $time)
    {
        if (!$test instanceof PHPUnit_Framework_Warning) {
            if ($test->getStatus() == PHPUnit_Runner_BaseTestRunner::STATUS_PASSED) {
                $ifStatus   = array('assigned', 'new', 'reopened');
                $newStatus  = 'closed';
                $message    = 'Automatically closed by PHPUnit (test passed).';
                $resolution = 'fixed';
                $cumulative = TRUE;
            }

            else if ($test->getStatus() == PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE) {
                $ifStatus   = array('closed');
                $newStatus  = 'reopened';
                $message    = 'Automatically reopened by PHPUnit (test failed).';
                $resolution = '';
                $cumulative = FALSE;
            }

            else {
                return;
            }

            $name    = $test->getName(FALSE);
            $tickets = PHPUnit_Util_Test::getTickets(get_class($test), $name);

            foreach ($tickets as $ticket) {
                // Remove this test from the totals (if it passed).
                if ($test->getStatus() == PHPUnit_Runner_BaseTestRunner::STATUS_PASSED) {
                    unset($this->ticketCounts[$ticket][$name]);
                }

                // Only close tickets if ALL referenced cases pass
                // but reopen tickets if a single test fails.
                if ($cumulative) {
                    // Determine number of to-pass tests:
                    if (count($this->ticketCounts[$ticket]) > 0) {
                        // There exist remaining test cases with this reference.
                        $adjustTicket = FALSE;
                    } else {
                        // No remaining tickets, go ahead and adjust.
                        $adjustTicket = TRUE;
                    }
                } else {
                    $adjustTicket = TRUE;
                }

                $ticketInfo = $this->getTicketInfo($ticket);

                if ($adjustTicket && in_array($ticketInfo['status'], $ifStatus)) {
                    $this->updateTicket($ticket, $newStatus, $message, $resolution);
                }
            }
        }
    }

    abstract protected function getTicketInfo($ticketId = NULL);
    abstract protected function updateTicket($ticketId, $newStatus, $message, $resolution);
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Extensions_PhptTestCase
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.1.4
 */

/**
 * Dummy logger for PEAR_RunTest.
 *
 * @package    PHPUnit
 * @subpackage Extensions_PhptTestCase
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.1.4
 */
class PHPUnit_Extensions_PhptTestCase_Logger
{
    public function log($level, $msg, $append_crlf = TRUE)
    {
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Extensions
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.3.0
 */

/**
 * We have a TestSuite object A.
 * In TestSuite object A we have Tests tagged with @group.
 * We want a TestSuite object B that contains TestSuite objects C, D, ...
 * for the Tests tagged with @group C, @group D, ...
 * Running the Tests from TestSuite object B results in Tests tagged with both
 * @group C and @group D in TestSuite object A to be run twice .
 *
 * <code>
 * $suite = new PHPUnit_Extensions_GroupTestSuite($A, array('C', 'D'));
 * </code>
 *
 * @package    PHPUnit
 * @subpackage Extensions
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.3.0
 */
class PHPUnit_Extensions_GroupTestSuite extends PHPUnit_Framework_TestSuite
{
    public function __construct(PHPUnit_Framework_TestSuite $suite, array $groups)
    {
        $groupSuites = array();
        $name        = $suite->getName();

        foreach ($groups as $group) {
            $groupSuites[$group] = new PHPUnit_Framework_TestSuite($name . ' - ' . $group);
            $this->addTest($groupSuites[$group]);
        }

        $tests = new RecursiveIteratorIterator(
          new PHPUnit_Util_TestSuiteIterator($suite),
          RecursiveIteratorIterator::LEAVES_ONLY
        );

        foreach ($tests as $test) {
            if ($test instanceof PHPUnit_Framework_TestCase) {
                $testGroups = PHPUnit_Util_Test::getGroups(
                  get_class($test), $test->getName(FALSE)
                );

                foreach ($groups as $group) {
                    foreach ($testGroups as $testGroup) {
                        if ($group == $testGroup) {
                            $groupSuites[$group]->addTest($test);
                        }
                    }
                }
            }
        }
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage TextUI
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

/**
 * A TestRunner for the Command Line Interface (CLI)
 * PHP SAPI Module.
 *
 * @package    PHPUnit
 * @subpackage TextUI
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.0.0
 */
class PHPUnit_TextUI_TestRunner extends PHPUnit_Runner_BaseTestRunner
{
    const SUCCESS_EXIT   = 0;
    const FAILURE_EXIT   = 1;
    const EXCEPTION_EXIT = 2;

    /**
     * @var PHP_CodeCoverage_Filter
     */
    protected $codeCoverageFilter;

    /**
     * @var PHPUnit_Runner_TestSuiteLoader
     */
    protected $loader = NULL;

    /**
     * @var PHPUnit_TextUI_ResultPrinter
     */
    protected $printer = NULL;

    /**
     * @var boolean
     */
    protected static $versionStringPrinted = FALSE;

    /**
     * @param PHPUnit_Runner_TestSuiteLoader $loader
     * @param PHP_CodeCoverage_Filter        $filter
     * @since Method available since Release 3.4.0
     */
    public function __construct(PHPUnit_Runner_TestSuiteLoader $loader = NULL, PHP_CodeCoverage_Filter $filter = NULL)
    {
        if ($filter === NULL) {
            $filter = new PHP_CodeCoverage_Filter;
        }

        $this->codeCoverageFilter = $filter;
        $this->loader             = $loader;
    }

    /**
     * @param  mixed $test
     * @param  array $arguments
     * @throws PHPUnit_Framework_Exception
     */
    public static function run($test, array $arguments = array())
    {
        if ($test instanceof ReflectionClass) {
            $test = new PHPUnit_Framework_TestSuite($test);
        }

        if ($test instanceof PHPUnit_Framework_Test) {
            $aTestRunner = new PHPUnit_TextUI_TestRunner;

            return $aTestRunner->doRun(
              $test,
              $arguments
            );
        } else {
            throw new PHPUnit_Framework_Exception(
              'No test case or test suite found.'
            );
        }
    }

    /**
     * @return PHPUnit_Framework_TestResult
     */
    protected function createTestResult()
    {
        return new PHPUnit_Framework_TestResult;
    }

    /**
     * @param  PHPUnit_Framework_Test $suite
     * @param  array                  $arguments
     * @return PHPUnit_Framework_TestResult
     */
    public function doRun(PHPUnit_Framework_Test $suite, array $arguments = array())
    {
        $this->handleConfiguration($arguments);

        if (isset($arguments['bootstrap'])) {
            $GLOBALS['__PHPUNIT_BOOTSTRAP'] = $arguments['bootstrap'];
        }

        if ($arguments['backupGlobals'] === FALSE) {
            $suite->setBackupGlobals(FALSE);
        }

        if ($arguments['backupStaticAttributes'] === TRUE) {
            $suite->setBackupStaticAttributes(TRUE);
        }

        if (is_integer($arguments['repeat'])) {
            $test = new PHPUnit_Extensions_RepeatedTest(
              $suite,
              $arguments['repeat'],
              $arguments['filter'],
              $arguments['groups'],
              $arguments['excludeGroups'],
              $arguments['processIsolation']
            );

            $suite = new PHPUnit_Framework_TestSuite();
            $suite->addTest($test);
        }

        $result = $this->createTestResult();

        if (!$arguments['convertErrorsToExceptions']) {
            $result->convertErrorsToExceptions(FALSE);
        }

        if (!$arguments['convertNoticesToExceptions']) {
            PHPUnit_Framework_Error_Notice::$enabled = FALSE;
        }

        if (!$arguments['convertWarningsToExceptions']) {
            PHPUnit_Framework_Error_Warning::$enabled = FALSE;
        }

        if ($arguments['stopOnError']) {
            $result->stopOnError(TRUE);
        }

        if ($arguments['stopOnFailure']) {
            $result->stopOnFailure(TRUE);
        }

        if ($arguments['stopOnIncomplete']) {
            $result->stopOnIncomplete(TRUE);
        }

        if ($arguments['stopOnSkipped']) {
            $result->stopOnSkipped(TRUE);
        }

        if ($this->printer === NULL) {
            if (isset($arguments['printer']) &&
                $arguments['printer'] instanceof PHPUnit_Util_Printer) {
                $this->printer = $arguments['printer'];
            } else {
                $this->printer = new PHPUnit_TextUI_ResultPrinter(
                  NULL,
                  $arguments['verbose'],
                  $arguments['colors'],
                  $arguments['debug']
                );
            }
        }

        if (!$this->printer instanceof PHPUnit_Util_Log_TAP &&
            !self::$versionStringPrinted) {
            $this->printer->write(
              PHPUnit_Runner_Version::getVersionString() . "\n\n"
            );

            if (isset($arguments['configuration'])) {
                $this->printer->write(
                  sprintf(
                    "Configuration read from %s\n\n",
                    $arguments['configuration']->getFilename()
                  )
                );
            }
        }

        foreach ($arguments['listeners'] as $listener) {
            $result->addListener($listener);
        }

        $result->addListener($this->printer);

        if ($this->printer instanceof PHPUnit_TextUI_ResultPrinter) {
            $result->addListener(new PHPUnit_Util_DeprecatedFeature_Logger);
        }

        if (isset($arguments['testdoxHTMLFile'])) {
            $result->addListener(
              new PHPUnit_Util_TestDox_ResultPrinter_HTML(
                $arguments['testdoxHTMLFile']
              )
            );
        }

        if (isset($arguments['testdoxTextFile'])) {
            $result->addListener(
              new PHPUnit_Util_TestDox_ResultPrinter_Text(
                $arguments['testdoxTextFile']
              )
            );
        }

        $codeCoverageReports = 0;

        if (extension_loaded('xdebug')) {
            if (isset($arguments['coverageClover'])) {
                $codeCoverageReports++;
            }

            if (isset($arguments['reportDirectory'])) {
                $codeCoverageReports++;
            }

            if (isset($arguments['coveragePHP'])) {
                $codeCoverageReports++;
            }

            if (isset($arguments['coverageText'])) {
                $codeCoverageReports++;
            }
        }

        if ($codeCoverageReports > 0) {
            $codeCoverage = new PHP_CodeCoverage(
              NULL, $this->codeCoverageFilter
            );

            $codeCoverage->setAddUncoveredFilesFromWhitelist(
              $arguments['addUncoveredFilesFromWhitelist']
            );

            $codeCoverage->setProcessUncoveredFilesFromWhitelist(
              $arguments['processUncoveredFilesFromWhitelist']
            );

            if (isset($arguments['forceCoversAnnotation'])) {
                $codeCoverage->setForceCoversAnnotation(
                  $arguments['forceCoversAnnotation']
                );
            }

            if (isset($arguments['mapTestClassNameToCoveredClassName'])) {
                $codeCoverage->setMapTestClassNameToCoveredClassName(
                  $arguments['mapTestClassNameToCoveredClassName']
                );
            }

            $result->setCodeCoverage($codeCoverage);
        }

        if ($codeCoverageReports > 1) {
            if (isset($arguments['cacheTokens'])) {
                $codeCoverage->setCacheTokens($arguments['cacheTokens']);
            }
        }

        if (isset($arguments['jsonLogfile'])) {
            $result->addListener(
              new PHPUnit_Util_Log_JSON($arguments['jsonLogfile'])
            );
        }

        if (isset($arguments['tapLogfile'])) {
            $result->addListener(
              new PHPUnit_Util_Log_TAP($arguments['tapLogfile'])
            );
        }

        if (isset($arguments['junitLogfile'])) {
            $result->addListener(
              new PHPUnit_Util_Log_JUnit(
                $arguments['junitLogfile'], $arguments['logIncompleteSkipped']
              )
            );
        }

        if ($arguments['strict']) {
            $result->strictMode(TRUE);

            $result->setTimeoutForSmallTests(
              $arguments['timeoutForSmallTests']
            );

            $result->setTimeoutForMediumTests(
              $arguments['timeoutForMediumTests']
            );

            $result->setTimeoutForLargeTests(
              $arguments['timeoutForLargeTests']
            );
        }

        $suite->run(
          $result,
          $arguments['filter'],
          $arguments['groups'],
          $arguments['excludeGroups'],
          $arguments['processIsolation']
        );

        unset($suite);
        $result->flushListeners();

        if ($this->printer instanceof PHPUnit_TextUI_ResultPrinter) {
            $this->printer->printResult($result);
        }

        if (isset($codeCoverage)) {
            if (isset($arguments['coverageClover'])) {
                $this->printer->write(
                  "\nGenerating code coverage report in Clover XML format ..."
                );

                $writer = new PHP_CodeCoverage_Report_Clover;
                $writer->process($codeCoverage, $arguments['coverageClover']);

                $this->printer->write(" done\n");
                unset($writer);
            }

            if (isset($arguments['reportDirectory'])) {
                $this->printer->write(
                  "\nGenerating code coverage report in HTML format ..."
                );

                $writer = new PHP_CodeCoverage_Report_HTML(
                  $arguments['reportCharset'],
                  $arguments['reportHighlight'],
                  $arguments['reportLowUpperBound'],
                  $arguments['reportHighLowerBound'],
                  sprintf(
                    ' and <a href="http://phpunit.de/">PHPUnit %s</a>',
                    PHPUnit_Runner_Version::id()
                  )
                );

                $writer->process($codeCoverage, $arguments['reportDirectory']);

                $this->printer->write(" done\n");
                unset($writer);
            }

            if (isset($arguments['coveragePHP'])) {
                $this->printer->write(
                  "\nGenerating code coverage report in PHP format ..."
                );

                $writer = new PHP_CodeCoverage_Report_PHP;
                $writer->process($codeCoverage, $arguments['coveragePHP']);

                $this->printer->write(" done\n");
                unset($writer);
            }

            if (isset($arguments['coverageText'])) {
                if ($arguments['coverageText'] == 'php://stdout') {
                    $outputStream = $this->printer;
                    $colors       = (bool)$arguments['colors'];
                } else {
                    $outputStream = new PHPUnit_Util_Printer($arguments['coverageText']);
                    $colors       = FALSE;
                }

                $writer = new PHP_CodeCoverage_Report_Text(
                  $outputStream,
                  $arguments['reportLowUpperBound'],
                  $arguments['reportHighLowerBound'],
                  $arguments['coverageTextShowUncoveredFiles']
                );

                $writer->process($codeCoverage, $colors);
            }
        }

        return $result;
    }

    /**
     * @param  PHPUnit_TextUI_ResultPrinter $resultPrinter
     */
    public function setPrinter(PHPUnit_TextUI_ResultPrinter $resultPrinter)
    {
        $this->printer = $resultPrinter;
    }

    /**
     * Override to define how to handle a failed loading of
     * a test suite.
     *
     * @param  string  $message
     */
    protected function runFailed($message)
    {
        self::printVersionString();
        self::write($message . PHP_EOL);
        exit(self::FAILURE_EXIT);
    }

    /**
     * @param  string $buffer
     * @since  Method available since Release 3.1.0
     */
    protected static function write($buffer)
    {
        if (PHP_SAPI != 'cli') {
            $buffer = htmlspecialchars($buffer);
        }

        print $buffer;
    }

    /**
     * Returns the loader to be used.
     *
     * @return PHPUnit_Runner_TestSuiteLoader
     * @since  Method available since Release 2.2.0
     */
    public function getLoader()
    {
        if ($this->loader === NULL) {
            $this->loader = new PHPUnit_Runner_StandardTestSuiteLoader;
        }

        return $this->loader;
    }

    /**
     */
    public static function showError($message)
    {
        self::printVersionString();
        self::write($message . "\n");

        exit(self::FAILURE_EXIT);
    }

    /**
     */
    public static function printVersionString()
    {
        if (!self::$versionStringPrinted) {
            self::write(PHPUnit_Runner_Version::getVersionString() . "\n\n");
            self::$versionStringPrinted = TRUE;
        }
    }

    /**
     * @param  array $arguments
     * @since  Method available since Release 3.2.1
     */
    protected function handleConfiguration(array &$arguments)
    {
        if (isset($arguments['configuration']) &&
            !$arguments['configuration'] instanceof PHPUnit_Util_Configuration) {
            $arguments['configuration'] = PHPUnit_Util_Configuration::getInstance(
              $arguments['configuration']
            );
        }

        $arguments['debug']     = isset($arguments['debug'])     ? $arguments['debug']     : FALSE;
        $arguments['filter']    = isset($arguments['filter'])    ? $arguments['filter']    : FALSE;
        $arguments['listeners'] = isset($arguments['listeners']) ? $arguments['listeners'] : array();

        if (isset($arguments['configuration'])) {
            $arguments['configuration']->handlePHPConfiguration();

            $phpunitConfiguration = $arguments['configuration']->getPHPUnitConfiguration();

            if (isset($phpunitConfiguration['backupGlobals']) &&
                !isset($arguments['backupGlobals'])) {
                $arguments['backupGlobals'] = $phpunitConfiguration['backupGlobals'];
            }

            if (isset($phpunitConfiguration['backupStaticAttributes']) &&
                !isset($arguments['backupStaticAttributes'])) {
                $arguments['backupStaticAttributes'] = $phpunitConfiguration['backupStaticAttributes'];
            }

            if (isset($phpunitConfiguration['bootstrap']) &&
                !isset($arguments['bootstrap'])) {
                $arguments['bootstrap'] = $phpunitConfiguration['bootstrap'];
            }

            if (isset($phpunitConfiguration['cacheTokens']) &&
                !isset($arguments['cacheTokens'])) {
                $arguments['cacheTokens'] = $phpunitConfiguration['cacheTokens'];
            }

            if (isset($phpunitConfiguration['colors']) &&
                !isset($arguments['colors'])) {
                $arguments['colors'] = $phpunitConfiguration['colors'];
            }

            if (isset($phpunitConfiguration['convertErrorsToExceptions']) &&
                !isset($arguments['convertErrorsToExceptions'])) {
                $arguments['convertErrorsToExceptions'] = $phpunitConfiguration['convertErrorsToExceptions'];
            }

            if (isset($phpunitConfiguration['convertNoticesToExceptions']) &&
                !isset($arguments['convertNoticesToExceptions'])) {
                $arguments['convertNoticesToExceptions'] = $phpunitConfiguration['convertNoticesToExceptions'];
            }

            if (isset($phpunitConfiguration['convertWarningsToExceptions']) &&
                !isset($arguments['convertWarningsToExceptions'])) {
                $arguments['convertWarningsToExceptions'] = $phpunitConfiguration['convertWarningsToExceptions'];
            }

            if (isset($phpunitConfiguration['processIsolation']) &&
                !isset($arguments['processIsolation'])) {
                $arguments['processIsolation'] = $phpunitConfiguration['processIsolation'];
            }

            if (isset($phpunitConfiguration['stopOnFailure']) &&
                !isset($arguments['stopOnFailure'])) {
                $arguments['stopOnFailure'] = $phpunitConfiguration['stopOnFailure'];
            }

            if (isset($phpunitConfiguration['timeoutForSmallTests']) &&
                !isset($arguments['timeoutForSmallTests'])) {
                $arguments['timeoutForSmallTests'] = $phpunitConfiguration['timeoutForSmallTests'];
            }

            if (isset($phpunitConfiguration['timeoutForMediumTests']) &&
                !isset($arguments['timeoutForMediumTests'])) {
                $arguments['timeoutForMediumTests'] = $phpunitConfiguration['timeoutForMediumTests'];
            }

            if (isset($phpunitConfiguration['timeoutForLargeTests']) &&
                !isset($arguments['timeoutForLargeTests'])) {
                $arguments['timeoutForLargeTests'] = $phpunitConfiguration['timeoutForLargeTests'];
            }

            if (isset($phpunitConfiguration['strict']) &&
                !isset($arguments['strict'])) {
                $arguments['strict'] = $phpunitConfiguration['strict'];
            }

            if (isset($phpunitConfiguration['verbose']) &&
                !isset($arguments['verbose'])) {
                $arguments['verbose'] = $phpunitConfiguration['verbose'];
            }

            if (isset($phpunitConfiguration['forceCoversAnnotation']) &&
                !isset($arguments['forceCoversAnnotation'])) {
                $arguments['forceCoversAnnotation'] = $phpunitConfiguration['forceCoversAnnotation'];
            }

            if (isset($phpunitConfiguration['mapTestClassNameToCoveredClassName']) &&
                !isset($arguments['mapTestClassNameToCoveredClassName'])) {
                $arguments['mapTestClassNameToCoveredClassName'] = $phpunitConfiguration['mapTestClassNameToCoveredClassName'];
            }

            $groupCliArgs = array();
            if (!empty($arguments['groups'])) {
                $groupCliArgs = $arguments['groups'];
            }

            $groupConfiguration = $arguments['configuration']->getGroupConfiguration();

            if (!empty($groupConfiguration['include']) &&
                !isset($arguments['groups'])) {
                $arguments['groups'] = $groupConfiguration['include'];
            }

            if (!empty($groupConfiguration['exclude']) &&
                !isset($arguments['excludeGroups'])) {
                $arguments['excludeGroups'] = array_diff($groupConfiguration['exclude'], $groupCliArgs);
            }

            foreach ($arguments['configuration']->getListenerConfiguration() as $listener) {
                if (!class_exists($listener['class'], FALSE) &&
                    $listener['file'] !== '') {
                    require_once $listener['file'];
                }

                if (class_exists($listener['class'])) {
                    if (count($listener['arguments']) == 0) {
                        $listener = new $listener['class'];
                    } else {
                        $listenerClass = new ReflectionClass(
                                           $listener['class']
                                         );
                        $listener      = $listenerClass->newInstanceArgs(
                                           $listener['arguments']
                                         );
                    }

                    if ($listener instanceof PHPUnit_Framework_TestListener) {
                        $arguments['listeners'][] = $listener;
                    }
                }
            }

            $loggingConfiguration = $arguments['configuration']->getLoggingConfiguration();

            if (isset($loggingConfiguration['coverage-html']) &&
                !isset($arguments['reportDirectory'])) {
                if (isset($loggingConfiguration['charset']) &&
                    !isset($arguments['reportCharset'])) {
                    $arguments['reportCharset'] = $loggingConfiguration['charset'];
                }

                if (isset($loggingConfiguration['highlight']) &&
                    !isset($arguments['reportHighlight'])) {
                    $arguments['reportHighlight'] = $loggingConfiguration['highlight'];
                }

                if (isset($loggingConfiguration['lowUpperBound']) &&
                    !isset($arguments['reportLowUpperBound'])) {
                    $arguments['reportLowUpperBound'] = $loggingConfiguration['lowUpperBound'];
                }

                if (isset($loggingConfiguration['highLowerBound']) &&
                    !isset($arguments['reportHighLowerBound'])) {
                    $arguments['reportHighLowerBound'] = $loggingConfiguration['highLowerBound'];
                }

                $arguments['reportDirectory'] = $loggingConfiguration['coverage-html'];
            }

            if (isset($loggingConfiguration['coverage-clover']) &&
                !isset($arguments['coverageClover'])) {
                $arguments['coverageClover'] = $loggingConfiguration['coverage-clover'];
            }

            if (isset($loggingConfiguration['coverage-php']) &&
                !isset($arguments['coveragePHP'])) {
                $arguments['coveragePHP'] = $loggingConfiguration['coverage-php'];
            }

            if (isset($loggingConfiguration['coverage-text']) &&
                !isset($arguments['coverageText'])) {
                $arguments['coverageText'] = $loggingConfiguration['coverage-text'];
                if (isset($loggingConfiguration['coverageTextShowUncoveredFiles'])) {
                    $arguments['coverageTextShowUncoveredFiles'] = $loggingConfiguration['coverageTextShowUncoveredFiles'];
                } else {
                    $arguments['coverageTextShowUncoveredFiles'] = FALSE;
                }
            }

            if (isset($loggingConfiguration['json']) &&
                !isset($arguments['jsonLogfile'])) {
                $arguments['jsonLogfile'] = $loggingConfiguration['json'];
            }

            if (isset($loggingConfiguration['plain'])) {
                $arguments['listeners'][] = new PHPUnit_TextUI_ResultPrinter(
                  $loggingConfiguration['plain'], TRUE
                );
            }

            if (isset($loggingConfiguration['tap']) &&
                !isset($arguments['tapLogfile'])) {
                $arguments['tapLogfile'] = $loggingConfiguration['tap'];
            }

            if (isset($loggingConfiguration['junit']) &&
                !isset($arguments['junitLogfile'])) {
                $arguments['junitLogfile'] = $loggingConfiguration['junit'];

                if (isset($loggingConfiguration['logIncompleteSkipped']) &&
                    !isset($arguments['logIncompleteSkipped'])) {
                    $arguments['logIncompleteSkipped'] = $loggingConfiguration['logIncompleteSkipped'];
                }
            }

            if (isset($loggingConfiguration['testdox-html']) &&
                !isset($arguments['testdoxHTMLFile'])) {
                $arguments['testdoxHTMLFile'] = $loggingConfiguration['testdox-html'];
            }

            if (isset($loggingConfiguration['testdox-text']) &&
                !isset($arguments['testdoxTextFile'])) {
                $arguments['testdoxTextFile'] = $loggingConfiguration['testdox-text'];
            }

            if ((isset($arguments['coverageClover']) ||
                isset($arguments['reportDirectory']) ||
                isset($arguments['coveragePHP']) ||
                isset($arguments['coverageText'])) &&
                extension_loaded('xdebug')) {

                $filterConfiguration = $arguments['configuration']->getFilterConfiguration();
                $arguments['addUncoveredFilesFromWhitelist'] = $filterConfiguration['whitelist']['addUncoveredFilesFromWhitelist'];
                $arguments['processUncoveredFilesFromWhitelist'] = $filterConfiguration['whitelist']['processUncoveredFilesFromWhitelist'];

                foreach ($filterConfiguration['blacklist']['include']['directory'] as $dir) {
                    $this->codeCoverageFilter->addDirectoryToBlacklist(
                      $dir['path'], $dir['suffix'], $dir['prefix'], $dir['group']
                    );
                }

                foreach ($filterConfiguration['blacklist']['include']['file'] as $file) {
                    $this->codeCoverageFilter->addFileToBlacklist($file);
                }

                foreach ($filterConfiguration['blacklist']['exclude']['directory'] as $dir) {
                    $this->codeCoverageFilter->removeDirectoryFromBlacklist(
                      $dir['path'], $dir['suffix'], $dir['prefix'], $dir['group']
                    );
                }

                foreach ($filterConfiguration['blacklist']['exclude']['file'] as $file) {
                    $this->codeCoverageFilter->removeFileFromBlacklist($file);
                }

                foreach ($filterConfiguration['whitelist']['include']['directory'] as $dir) {
                    $this->codeCoverageFilter->addDirectoryToWhitelist(
                      $dir['path'], $dir['suffix'], $dir['prefix']
                    );
                }

                foreach ($filterConfiguration['whitelist']['include']['file'] as $file) {
                    $this->codeCoverageFilter->addFileToWhitelist($file);
                }

                foreach ($filterConfiguration['whitelist']['exclude']['directory'] as $dir) {
                    $this->codeCoverageFilter->removeDirectoryFromWhitelist(
                      $dir['path'], $dir['suffix'], $dir['prefix']
                    );
                }

                foreach ($filterConfiguration['whitelist']['exclude']['file'] as $file) {
                    $this->codeCoverageFilter->removeFileFromWhitelist($file);
                }
            }
        }

        $arguments['addUncoveredFilesFromWhitelist']     = isset($arguments['addUncoveredFilesFromWhitelist'])     ? $arguments['addUncoveredFilesFromWhitelist']     : TRUE;
        $arguments['processUncoveredFilesFromWhitelist'] = isset($arguments['processUncoveredFilesFromWhitelist']) ? $arguments['processUncoveredFilesFromWhitelist'] : FALSE;
        $arguments['backupGlobals']                      = isset($arguments['backupGlobals'])                      ? $arguments['backupGlobals']                      : NULL;
        $arguments['backupStaticAttributes']             = isset($arguments['backupStaticAttributes'])             ? $arguments['backupStaticAttributes']             : NULL;
        $arguments['cacheTokens']                        = isset($arguments['cacheTokens'])                        ? $arguments['cacheTokens']                        : FALSE;
        $arguments['colors']                             = isset($arguments['colors'])                             ? $arguments['colors']                             : FALSE;
        $arguments['convertErrorsToExceptions']          = isset($arguments['convertErrorsToExceptions'])          ? $arguments['convertErrorsToExceptions']          : TRUE;
        $arguments['convertNoticesToExceptions']         = isset($arguments['convertNoticesToExceptions'])         ? $arguments['convertNoticesToExceptions']         : TRUE;
        $arguments['convertWarningsToExceptions']        = isset($arguments['convertWarningsToExceptions'])        ? $arguments['convertWarningsToExceptions']        : TRUE;
        $arguments['excludeGroups']                      = isset($arguments['excludeGroups'])                      ? $arguments['excludeGroups']                      : array();
        $arguments['groups']                             = isset($arguments['groups'])                             ? $arguments['groups']                             : array();
        $arguments['logIncompleteSkipped']               = isset($arguments['logIncompleteSkipped'])               ? $arguments['logIncompleteSkipped']               : FALSE;
        $arguments['processIsolation']                   = isset($arguments['processIsolation'])                   ? $arguments['processIsolation']                   : FALSE;
        $arguments['repeat']                             = isset($arguments['repeat'])                             ? $arguments['repeat']                             : FALSE;
        $arguments['reportCharset']                      = isset($arguments['reportCharset'])                      ? $arguments['reportCharset']                      : 'UTF-8';
        $arguments['reportHighlight']                    = isset($arguments['reportHighlight'])                    ? $arguments['reportHighlight']                    : FALSE;
        $arguments['reportHighLowerBound']               = isset($arguments['reportHighLowerBound'])               ? $arguments['reportHighLowerBound']               : 70;
        $arguments['reportLowUpperBound']                = isset($arguments['reportLowUpperBound'])                ? $arguments['reportLowUpperBound']                : 35;
        $arguments['stopOnError']                        = isset($arguments['stopOnError'])                        ? $arguments['stopOnError']                        : FALSE;
        $arguments['stopOnFailure']                      = isset($arguments['stopOnFailure'])                      ? $arguments['stopOnFailure']                      : FALSE;
        $arguments['stopOnIncomplete']                   = isset($arguments['stopOnIncomplete'])                   ? $arguments['stopOnIncomplete']                   : FALSE;
        $arguments['stopOnSkipped']                      = isset($arguments['stopOnSkipped'])                      ? $arguments['stopOnSkipped']                      : FALSE;
        $arguments['timeoutForSmallTests']               = isset($arguments['timeoutForSmallTests'])               ? $arguments['timeoutForSmallTests']               : 1;
        $arguments['timeoutForMediumTests']              = isset($arguments['timeoutForMediumTests'])              ? $arguments['timeoutForMediumTests']              : 10;
        $arguments['timeoutForLargeTests']               = isset($arguments['timeoutForLargeTests'])               ? $arguments['timeoutForLargeTests']               : 60;
        $arguments['strict']                             = isset($arguments['strict'])                             ? $arguments['strict']                             : FALSE;
        $arguments['verbose']                            = isset($arguments['verbose'])                            ? $arguments['verbose']                            : FALSE;

        if ($arguments['filter'] !== FALSE &&
            preg_match('/^[a-zA-Z0-9_]/', $arguments['filter'])) {
            // Escape delimiters in regular expression. Do NOT use preg_quote,
            // to keep magic characters.
            $arguments['filter'] = '/' . str_replace(
              '/', '\\/', $arguments['filter']
            ) . '/';
        }
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage TextUI
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

/**
 * Prints the result of a TextUI TestRunner run.
 *
 * @package    PHPUnit
 * @subpackage TextUI
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.0.0
 */
class PHPUnit_TextUI_ResultPrinter extends PHPUnit_Util_Printer implements PHPUnit_Framework_TestListener
{
    const EVENT_TEST_START      = 0;
    const EVENT_TEST_END        = 1;
    const EVENT_TESTSUITE_START = 2;
    const EVENT_TESTSUITE_END   = 3;

    /**
     * @var integer
     */
    protected $column = 0;

    /**
     * @var integer
     */
    protected $maxColumn;

    /**
     * @var boolean
     */
    protected $lastTestFailed = FALSE;

    /**
     * @var integer
     */
    protected $numAssertions = 0;

    /**
     * @var integer
     */
    protected $numTests = -1;

    /**
     * @var integer
     */
    protected $numTestsRun = 0;

    /**
     * @var integer
     */
    protected $numTestsWidth;

    /**
     * @var boolean
     */
    protected $colors = FALSE;

    /**
     * @var boolean
     */
    protected $debug = FALSE;

    /**
     * @var boolean
     */
    protected $verbose = FALSE;

    /**
     * Constructor.
     *
     * @param  mixed   $out
     * @param  boolean $verbose
     * @param  boolean $colors
     * @param  boolean $debug
     * @throws PHPUnit_Framework_Exception
     * @since  Method available since Release 3.0.0
     */
    public function __construct($out = NULL, $verbose = FALSE, $colors = FALSE, $debug = FALSE)
    {
        parent::__construct($out);

        if (is_bool($verbose)) {
            $this->verbose = $verbose;
        } else {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'boolean');
        }

        if (is_bool($colors)) {
            $this->colors = $colors;
        } else {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(3, 'boolean');
        }

        if (is_bool($debug)) {
            $this->debug = $debug;
        } else {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(4, 'boolean');
        }
    }

    /**
     * @param  PHPUnit_Framework_TestResult $result
     */
    public function printResult(PHPUnit_Framework_TestResult $result)
    {
        $this->printHeader();

        if ($result->errorCount() > 0) {
            $this->printErrors($result);
        }

        if ($result->failureCount() > 0) {
            if ($result->errorCount() > 0) {
                print "\n--\n\n";
            }

            $this->printFailures($result);
        }

        if ($this->verbose) {
            if ($result->deprecatedFeaturesCount() > 0) {
                if ($result->failureCount() > 0) {
                    print "\n--\n\nDeprecated PHPUnit features are being used";
                }

                foreach ($result->deprecatedFeatures() as $deprecatedFeature) {
                    $this->write($deprecatedFeature . "\n\n");
                }
            }

            if ($result->notImplementedCount() > 0) {
                if ($result->failureCount() > 0) {
                    print "\n--\n\n";
                }

                $this->printIncompletes($result);
            }

            if ($result->skippedCount() > 0) {
                if ($result->notImplementedCount() > 0) {
                    print "\n--\n\n";
                }

                $this->printSkipped($result);
            }
        }

        $this->printFooter($result);
    }

    /**
     * @param  array   $defects
     * @param  integer $count
     * @param  string  $type
     */
    protected function printDefects(array $defects, $count, $type)
    {
        static $called = FALSE;

        if ($count == 0) {
            return;
        }

        $this->write(
          sprintf(
            "%sThere %s %d %s%s:\n",

            $called ? "\n" : '',
            ($count == 1) ? 'was' : 'were',
            $count,
            $type,
            ($count == 1) ? '' : 's'
          )
        );

        $i = 1;

        foreach ($defects as $defect) {
            $this->printDefect($defect, $i++);
        }

        $called = TRUE;
    }

    /**
     * @param  PHPUnit_Framework_TestFailure $defect
     * @param  integer                       $count
     */
    protected function printDefect(PHPUnit_Framework_TestFailure $defect, $count)
    {
        $this->printDefectHeader($defect, $count);
        $this->printDefectTrace($defect);
    }

    /**
     * @param  PHPUnit_Framework_TestFailure $defect
     * @param  integer                       $count
     */
    protected function printDefectHeader(PHPUnit_Framework_TestFailure $defect, $count)
    {
        $failedTest = $defect->failedTest();

        if ($failedTest instanceof PHPUnit_Framework_SelfDescribing) {
            $testName = $failedTest->toString();
        } else {
            $testName = get_class($failedTest);
        }

        $this->write(
          sprintf(
            "\n%d) %s\n",

            $count,
            $testName
          )
        );
    }

    /**
     * @param  PHPUnit_Framework_TestFailure $defect
     */
    protected function printDefectTrace(PHPUnit_Framework_TestFailure $defect)
    {
        $this->write(
          $defect->getExceptionAsString() . "\n" .
          PHPUnit_Util_Filter::getFilteredStacktrace(
            $defect->thrownException()
          )
        );
        
        $e = $defect->thrownException()->getPrevious();

        while ($e) {
          $this->write(
            "\nCaused by\n" .
            PHPUnit_Framework_TestFailure::exceptionToString($e). "\n" .
            PHPUnit_Util_Filter::getFilteredStacktrace($e)
          );

          $e = $e->getPrevious();
        }
    }

    /**
     * @param  PHPUnit_Framework_TestResult  $result
     */
    protected function printErrors(PHPUnit_Framework_TestResult $result)
    {
        $this->printDefects($result->errors(), $result->errorCount(), 'error');
    }

    /**
     * @param  PHPUnit_Framework_TestResult  $result
     */
    protected function printFailures(PHPUnit_Framework_TestResult $result)
    {
        $this->printDefects(
          $result->failures(),
          $result->failureCount(),
          'failure'
        );
    }

    /**
     * @param  PHPUnit_Framework_TestResult  $result
     */
    protected function printIncompletes(PHPUnit_Framework_TestResult $result)
    {
        $this->printDefects(
          $result->notImplemented(),
          $result->notImplementedCount(),
          'incomplete test'
        );
    }

    /**
     * @param  PHPUnit_Framework_TestResult  $result
     * @since  Method available since Release 3.0.0
     */
    protected function printSkipped(PHPUnit_Framework_TestResult $result)
    {
        $this->printDefects(
          $result->skipped(),
          $result->skippedCount(),
          'skipped test'
        );
    }

    protected function printHeader()
    {
        $this->write("\n\n" . PHP_Timer::resourceUsage() . "\n\n");
    }

    /**
     * @param  PHPUnit_Framework_TestResult  $result
     */
    protected function printFooter(PHPUnit_Framework_TestResult $result)
    {
        if (count($result) === 0) {
            if ($this->colors) {
                $this->write("\x1b[30;43m\x1b[2K");
            }

            $this->write(
              "No tests executed!\n"
            );

            if ($this->colors) {
                $this->write("\x1b[0m\x1b[2K");
            }
        }

        else if ($result->wasSuccessful() &&
            $result->allCompletelyImplemented() &&
            $result->noneSkipped()) {
            if ($this->colors) {
                $this->write("\x1b[30;42m\x1b[2K");
            }

            $this->write(
              sprintf(
                "OK (%d test%s, %d assertion%s)\n",

                count($result),
                (count($result) == 1) ? '' : 's',
                $this->numAssertions,
                ($this->numAssertions == 1) ? '' : 's'
              )
            );

            if ($this->colors) {
                $this->write("\x1b[0m\x1b[2K");
            }
        }

        else if ((!$result->allCompletelyImplemented() ||
                  !$result->noneSkipped()) &&
                 $result->wasSuccessful()) {
            if ($this->colors) {
                $this->write(
                  "\x1b[30;43m\x1b[2KOK, but incomplete or skipped tests!\n" .
                  "\x1b[0m\x1b[30;43m\x1b[2K"
                );
            } else {
                $this->write("OK, but incomplete or skipped tests!\n");
            }

            $this->write(
              sprintf(
                "Tests: %d, Assertions: %d%s%s.\n",

                count($result),
                $this->numAssertions,
                $this->getCountString(
                  $result->notImplementedCount(), 'Incomplete'
                ),
                $this->getCountString(
                  $result->skippedCount(), 'Skipped'
                )
              )
            );

            if ($this->colors) {
                $this->write("\x1b[0m\x1b[2K");
            }
        }

        else {
            $this->write("\n");

            if ($this->colors) {
                $this->write(
                  "\x1b[37;41m\x1b[2KFAILURES!\n\x1b[0m\x1b[37;41m\x1b[2K"
                );
            } else {
                $this->write("FAILURES!\n");
            }

            $this->write(
              sprintf(
                "Tests: %d, Assertions: %s%s%s%s%s.\n",

                count($result),
                $this->numAssertions,
                $this->getCountString($result->failureCount(), 'Failures'),
                $this->getCountString($result->errorCount(), 'Errors'),
                $this->getCountString(
                  $result->notImplementedCount(), 'Incomplete'
                ),
                $this->getCountString($result->skippedCount(), 'Skipped')
              )
            );

            if ($this->colors) {
                $this->write("\x1b[0m\x1b[2K");
            }
        }

        if (!$this->verbose &&
            $result->deprecatedFeaturesCount() > 0) {
            $message = sprintf(
              "Warning: Deprecated PHPUnit features are being used %s times!\n" .
              "Use --verbose for more information.\n",
              $result->deprecatedFeaturesCount()
            );

            if ($this->colors) {
                $message = "\x1b[37;41m\x1b[2K" . $message .
                           "\x1b[0m";
            }

            $this->write("\n" . $message);
        }
    }

    /**
     * @param  integer $count
     * @param  string  $name
     * @return string
     * @since  Method available since Release 3.0.0
     */
    protected function getCountString($count, $name)
    {
        $string = '';

        if ($count > 0) {
            $string = sprintf(
              ', %s: %d',

              $name,
              $count
            );
        }

        return $string;
    }

    /**
     */
    public function printWaitPrompt()
    {
        $this->write("\n<RETURN> to continue\n");
    }

    /**
     * An error occurred.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  Exception              $e
     * @param  float                  $time
     */
    public function addError(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
        if ($this->colors) {
            $this->writeProgress("\x1b[31;1mE\x1b[0m");
        } else {
            $this->writeProgress('E');
        }

        $this->lastTestFailed = TRUE;
    }

    /**
     * A failure occurred.
     *
     * @param  PHPUnit_Framework_Test                 $test
     * @param  PHPUnit_Framework_AssertionFailedError $e
     * @param  float                                  $time
     */
    public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time)
    {
        if ($this->colors) {
            $this->writeProgress("\x1b[41;37mF\x1b[0m");
        } else {
            $this->writeProgress('F');
        }

        $this->lastTestFailed = TRUE;
    }

    /**
     * Incomplete test.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  Exception              $e
     * @param  float                  $time
     */
    public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
        if ($this->colors) {
            $this->writeProgress("\x1b[33;1mI\x1b[0m");
        } else {
            $this->writeProgress('I');
        }

        $this->lastTestFailed = TRUE;
    }

    /**
     * Skipped test.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  Exception              $e
     * @param  float                  $time
     * @since  Method available since Release 3.0.0
     */
    public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
        if ($this->colors) {
            $this->writeProgress("\x1b[36;1mS\x1b[0m");
        } else {
            $this->writeProgress('S');
        }

        $this->lastTestFailed = TRUE;
    }

    /**
     * A testsuite started.
     *
     * @param  PHPUnit_Framework_TestSuite $suite
     * @since  Method available since Release 2.2.0
     */
    public function startTestSuite(PHPUnit_Framework_TestSuite $suite)
    {
        if ($this->numTests == -1) {
            $this->numTests      = count($suite);
            $this->numTestsWidth = strlen((string)$this->numTests);
            $this->maxColumn     = 69 - (2 * $this->numTestsWidth);
        }
    }

    /**
     * A testsuite ended.
     *
     * @param  PHPUnit_Framework_TestSuite $suite
     * @since  Method available since Release 2.2.0
     */
    public function endTestSuite(PHPUnit_Framework_TestSuite $suite)
    {
    }

    /**
     * A test started.
     *
     * @param  PHPUnit_Framework_Test $test
     */
    public function startTest(PHPUnit_Framework_Test $test)
    {
        if ($this->debug) {
            $this->write(
              sprintf(
                "\nStarting test '%s'.\n", PHPUnit_Util_Test::describe($test)
              )
            );
        }
    }

    /**
     * A test ended.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  float                  $time
     */
    public function endTest(PHPUnit_Framework_Test $test, $time)
    {
        if (!$this->lastTestFailed) {
            $this->writeProgress('.');
        }

        if ($test instanceof PHPUnit_Framework_TestCase) {
            $this->numAssertions += $test->getNumAssertions();
        }

        else if ($test instanceof PHPUnit_Extensions_PhptTestCase) {
            $this->numAssertions++;
        }

        $this->lastTestFailed = FALSE;

        if ($test instanceof PHPUnit_Framework_TestCase) {
            if (!$test->hasPerformedExpectationsOnOutput()) {
                $this->write($test->getActualOutput());
            }
        }
    }

    /**
     * @param  string $progress
     */
    protected function writeProgress($progress)
    {
        $this->write($progress);
        $this->column++;
        $this->numTestsRun++;

        if ($this->column == $this->maxColumn) {
            $this->write(
              sprintf(
                ' %' . $this->numTestsWidth . 'd / %' .
                       $this->numTestsWidth . 'd (%3s%%)',

                $this->numTestsRun,
                $this->numTests,
                floor(($this->numTestsRun / $this->numTests) * 100)
              )
            );

            $this->writeNewLine();
        }
    }

    protected function writeNewLine()
    {
        $this->column = 0;
        $this->write("\n");
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage TextUI
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * A TestRunner for the Command Line Interface (CLI)
 * PHP SAPI Module.
 *
 * @package    PHPUnit
 * @subpackage TextUI
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class PHPUnit_TextUI_Command
{
    /**
     * @var array
     */
    protected $arguments = array(
      'listGroups'              => FALSE,
      'loader'                  => NULL,
      'useDefaultConfiguration' => TRUE
    );

    /**
     * @var array
     */
    protected $options = array();

    /**
     * @var array
     */
    protected $longOptions = array(
      'colors' => NULL,
      'bootstrap=' => NULL,
      'configuration=' => NULL,
      'coverage-html=' => NULL,
      'coverage-clover=' => NULL,
      'coverage-php=' => NULL,
      'coverage-text==' => NULL,
      'debug' => NULL,
      'exclude-group=' => NULL,
      'filter=' => NULL,
      'testsuite=' => NULL,
      'group=' => NULL,
      'help' => NULL,
      'include-path=' => NULL,
      'list-groups' => NULL,
      'loader=' => NULL,
      'log-json=' => NULL,
      'log-junit=' => NULL,
      'log-tap=' => NULL,
      'process-isolation' => NULL,
      'repeat=' => NULL,
      'stderr' => NULL,
      'stop-on-error' => NULL,
      'stop-on-failure' => NULL,
      'stop-on-incomplete' => NULL,
      'stop-on-skipped' => NULL,
      'strict' => NULL,
      'tap' => NULL,
      'testdox' => NULL,
      'testdox-html=' => NULL,
      'testdox-text=' => NULL,
      'test-suffix=' => NULL,
      'no-configuration' => NULL,
      'no-globals-backup' => NULL,
      'printer=' => NULL,
      'static-backup' => NULL,
      'verbose' => NULL,
      'version' => NULL
    );

    /**
     * @var array
     */
    protected $missingExtensions = array();

    /**
     * @param boolean $exit
     */
    public static function main($exit = TRUE)
    {
        $command = new PHPUnit_TextUI_Command;
        return $command->run($_SERVER['argv'], $exit);
    }

    /**
     * @param array   $argv
     * @param boolean $exit
     */
    public function run(array $argv, $exit = TRUE)
    {
        $this->handleArguments($argv);

        $runner = $this->createRunner();

        if (is_object($this->arguments['test']) &&
            $this->arguments['test'] instanceof PHPUnit_Framework_Test) {
            $suite = $this->arguments['test'];
        } else {
            $suite = $runner->getTest(
              $this->arguments['test'],
              $this->arguments['testFile'],
              $this->arguments['testSuffixes']
            );
        }

        if ($this->arguments['listGroups']) {
            PHPUnit_TextUI_TestRunner::printVersionString();

            print "Available test group(s):\n";

            $groups = $suite->getGroups();
            sort($groups);

            foreach ($groups as $group) {
                print " - $group\n";
            }

            if ($exit) {
                exit(PHPUnit_TextUI_TestRunner::SUCCESS_EXIT);
            } else {
                return PHPUnit_TextUI_TestRunner::SUCCESS_EXIT;
            }
        }

        unset($this->arguments['test']);
        unset($this->arguments['testFile']);

        try {
            $result = $runner->doRun($suite, $this->arguments);
        }

        catch (PHPUnit_Framework_Exception $e) {
            print $e->getMessage() . "\n";
        }

        $ret = PHPUnit_TextUI_TestRunner::FAILURE_EXIT;

        if (isset($result) && $result->wasSuccessful()) {
            $ret = PHPUnit_TextUI_TestRunner::SUCCESS_EXIT;
        }

        else if (!isset($result) || $result->errorCount() > 0) {
            $ret = PHPUnit_TextUI_TestRunner::EXCEPTION_EXIT;
        }

        if ($exit) {
            exit($ret);
        } else {
            return $ret;
        }
    }

    /**
     * Create a TestRunner, override in subclasses.
     *
     * @return PHPUnit_TextUI_TestRunner
     * @since  Method available since Release 3.6.0
     */
    protected function createRunner()
    {
        return new PHPUnit_TextUI_TestRunner($this->arguments['loader']);
    }

    /**
     * Handles the command-line arguments.
     *
     * A child class of PHPUnit_TextUI_Command can hook into the argument
     * parsing by adding the switch(es) to the $longOptions array and point to a
     * callback method that handles the switch(es) in the child class like this
     *
     * <code>
     * <?php
     * class MyCommand extends PHPUnit_TextUI_Command
     * {
     *     public function __construct()
     *     {
     *         $this->longOptions['--my-switch'] = 'myHandler';
     *     }
     *
     *     // --my-switch foo -> myHandler('foo')
     *     protected function myHandler($value)
     *     {
     *     }
     * }
     * </code>
     *
     * @param array $argv
     */
    protected function handleArguments(array $argv)
    {
        try {
            $this->options = PHPUnit_Util_Getopt::getopt(
              $argv,
              'd:c:hv',
              array_keys($this->longOptions)
            );
        }

        catch (PHPUnit_Framework_Exception $e) {
            PHPUnit_TextUI_TestRunner::showError($e->getMessage());
        }

        foreach ($this->options[0] as $option) {
            switch ($option[0]) {
                case '--colors': {
                    $this->arguments['colors'] = TRUE;
                }
                break;

                case '--bootstrap': {
                    $this->arguments['bootstrap'] = $option[1];
                }
                break;

                case 'c':
                case '--configuration': {
                    $this->arguments['configuration'] = $option[1];
                }
                break;

                case '--coverage-clover':
                case '--coverage-html':
                case '--coverage-php':
                case '--coverage-text': {
                    if (!extension_loaded('tokenizer')) {
                        $this->showExtensionNotLoadedMessage(
                          'tokenizer', 'No code coverage will be generated.'
                        );

                        continue;
                    }

                    if (!extension_loaded('xdebug')) {
                        $this->showExtensionNotLoadedMessage(
                          'Xdebug', 'No code coverage will be generated.'
                        );

                        continue;
                    }

                    switch ($option[0]) {
                        case '--coverage-clover': {
                            $this->arguments['coverageClover'] = $option[1];
                        }
                        break;

                        case '--coverage-html': {
                            $this->arguments['reportDirectory'] = $option[1];
                        }
                        break;

                        case '--coverage-php': {
                            $this->arguments['coveragePHP'] = $option[1];
                        }
                        break;

                        case '--coverage-text': {
                            if ($option[1] === NULL) {
                                $option[1] = 'php://stdout';
                            }

                            $this->arguments['coverageText'] = $option[1];
                            $this->arguments['coverageTextShowUncoveredFiles'] = FALSE;
                        }
                        break;
                    }
                }
                break;

                case 'd': {
                    $ini = explode('=', $option[1]);

                    if (isset($ini[0])) {
                        if (isset($ini[1])) {
                            ini_set($ini[0], $ini[1]);
                        } else {
                            ini_set($ini[0], TRUE);
                        }
                    }
                }
                break;

                case '--debug': {
                    $this->arguments['debug'] = TRUE;
                }
                break;

                case 'h':
                case '--help': {
                    $this->showHelp();
                    exit(PHPUnit_TextUI_TestRunner::SUCCESS_EXIT);
                }
                break;

                case '--filter': {
                    $this->arguments['filter'] = $option[1];
                }
                break;

                case '--testsuite': {
                    $this->arguments['testsuite'] = $option[1];
                }
                break;

                case '--group': {
                    $this->arguments['groups'] = explode(',', $option[1]);
                }
                break;

                case '--exclude-group': {
                    $this->arguments['excludeGroups'] = explode(
                      ',', $option[1]
                    );
                }
                break;

                case '--test-suffix': {
                    $this->arguments['testSuffixes'] = explode(
                      ',', $option[1]
                    );
                }
                break;

                case '--include-path': {
                    $includePath = $option[1];
                }
                break;

                case '--list-groups': {
                    $this->arguments['listGroups'] = TRUE;
                }
                break;

                case '--printer': {
                    $this->arguments['printer'] = $option[1];
                }
                break;

                case '--loader': {
                    $this->arguments['loader'] = $option[1];
                }
                break;

                case '--log-json': {
                    $this->arguments['jsonLogfile'] = $option[1];
                }
                break;

                case '--log-junit': {
                    $this->arguments['junitLogfile'] = $option[1];
                }
                break;

                case '--log-tap': {
                    $this->arguments['tapLogfile'] = $option[1];
                }
                break;

                case '--process-isolation': {
                    $this->arguments['processIsolation'] = TRUE;
                }
                break;

                case '--repeat': {
                    $this->arguments['repeat'] = (int)$option[1];
                }
                break;

                case '--stderr': {
                    $this->arguments['printer'] = new PHPUnit_TextUI_ResultPrinter(
                      'php://stderr',
                      isset($this->arguments['verbose']) ? $this->arguments['verbose'] : FALSE
                    );
                }
                break;

                case '--stop-on-error': {
                    $this->arguments['stopOnError'] = TRUE;
                }
                break;

                case '--stop-on-failure': {
                    $this->arguments['stopOnFailure'] = TRUE;
                }
                break;

                case '--stop-on-incomplete': {
                    $this->arguments['stopOnIncomplete'] = TRUE;
                }
                break;

                case '--stop-on-skipped': {
                    $this->arguments['stopOnSkipped'] = TRUE;
                }
                break;

                case '--tap': {
                    $this->arguments['printer'] = new PHPUnit_Util_Log_TAP;
                }
                break;

                case '--testdox': {
                    $this->arguments['printer'] = new PHPUnit_Util_TestDox_ResultPrinter_Text;
                }
                break;

                case '--testdox-html': {
                    $this->arguments['testdoxHTMLFile'] = $option[1];
                }
                break;

                case '--testdox-text': {
                    $this->arguments['testdoxTextFile'] = $option[1];
                }
                break;

                case '--no-configuration': {
                    $this->arguments['useDefaultConfiguration'] = FALSE;
                }
                break;

                case '--no-globals-backup': {
                    $this->arguments['backupGlobals'] = FALSE;
                }
                break;

                case '--static-backup': {
                    $this->arguments['backupStaticAttributes'] = TRUE;
                }
                break;

                case 'v':
                case '--verbose': {
                    $this->arguments['verbose'] = TRUE;
                }
                break;

                case '--version': {
                    PHPUnit_TextUI_TestRunner::printVersionString();
                    exit(PHPUnit_TextUI_TestRunner::SUCCESS_EXIT);
                }
                break;

                case '--strict': {
                    $this->arguments['strict'] = TRUE;
                }
                break;

                default: {
                    $optionName = str_replace('--', '', $option[0]);

                    if (isset($this->longOptions[$optionName])) {
                        $handler = $this->longOptions[$optionName];
                    }

                    else if (isset($this->longOptions[$optionName . '='])) {
                        $handler = $this->longOptions[$optionName . '='];
                    }

                    if (isset($handler) && is_callable(array($this, $handler))) {
                        $this->$handler($option[1]);
                    }
                }
            }
        }

        $this->handleCustomTestSuite();

        if (!isset($this->arguments['test'])) {

            if (isset($this->options[1][0])) {
                $this->arguments['test'] = $this->options[1][0];
            }

            if (isset($this->options[1][1])) {
                $this->arguments['testFile'] = $this->options[1][1];
            } else {
                $this->arguments['testFile'] = '';
            }

            if (isset($this->arguments['test']) &&
                is_file($this->arguments['test']) &&
                substr($this->arguments['test'], -5, 5) != '.phpt') {
                $this->arguments['testFile'] = realpath($this->arguments['test']);
                $this->arguments['test']     = substr($this->arguments['test'], 0, strrpos($this->arguments['test'], '.'));
            }
        }

        if (!isset($this->arguments['testSuffixes'])) {
            $this->arguments['testSuffixes'] = array('Test.php', '.phpt');
        }

        if (isset($includePath)) {
            ini_set(
              'include_path',
              $includePath . PATH_SEPARATOR . ini_get('include_path')
            );
        }

        if (isset($this->arguments['bootstrap'])) {
            $this->handleBootstrap($this->arguments['bootstrap']);
        }

        if (isset($this->arguments['printer']) &&
            is_string($this->arguments['printer'])) {
            $this->arguments['printer'] = $this->handlePrinter($this->arguments['printer']);
        }

        if ($this->arguments['loader'] !== NULL) {
            $this->arguments['loader'] = $this->handleLoader($this->arguments['loader']);
        }

        if (isset($this->arguments['configuration']) &&
            is_dir($this->arguments['configuration'])) {
            $configurationFile = $this->arguments['configuration'] .
                                 '/phpunit.xml';

            if (file_exists($configurationFile)) {
                $this->arguments['configuration'] = realpath(
                  $configurationFile
                );
            }

            else if (file_exists($configurationFile . '.dist')) {
                $this->arguments['configuration'] = realpath(
                  $configurationFile . '.dist'
                );
            }
        }

        else if (!isset($this->arguments['configuration']) &&
                 $this->arguments['useDefaultConfiguration']) {
            if (file_exists('phpunit.xml')) {
                $this->arguments['configuration'] = realpath('phpunit.xml');
            } else if (file_exists('phpunit.xml.dist')) {
                $this->arguments['configuration'] = realpath(
                  'phpunit.xml.dist'
                );
            }
        }

        if (isset($this->arguments['configuration'])) {
            try {
                $configuration = PHPUnit_Util_Configuration::getInstance(
                  $this->arguments['configuration']
                );
            }

            catch (Exception $e) {
                print $e->getMessage() . "\n";
                exit(PHPUnit_TextUI_TestRunner::FAILURE_EXIT);
            }

            $phpunit = $configuration->getPHPUnitConfiguration();

            $configuration->handlePHPConfiguration();

            if (!isset($this->arguments['bootstrap']) && isset($phpunit['bootstrap'])) {
                $this->handleBootstrap($phpunit['bootstrap']);
            }

            if (isset($phpunit['printerClass'])) {
                if (isset($phpunit['printerFile'])) {
                    $file = $phpunit['printerFile'];
                } else {
                    $file = '';
                }

                $this->arguments['printer'] = $this->handlePrinter(
                  $phpunit['printerClass'], $file
                );
            }

            if (isset($phpunit['testSuiteLoaderClass'])) {
                if (isset($phpunit['testSuiteLoaderFile'])) {
                    $file = $phpunit['testSuiteLoaderFile'];
                } else {
                    $file = '';
                }

                $this->arguments['loader'] = $this->handleLoader(
                  $phpunit['testSuiteLoaderClass'], $file
                );
            }

            $logging = $configuration->getLoggingConfiguration();

            if (isset($logging['coverage-html']) || isset($logging['coverage-clover']) || isset($logging['coverage-text']) ) {
                if (!extension_loaded('tokenizer')) {
                    $this->showExtensionNotLoadedMessage(
                      'tokenizer', 'No code coverage will be generated.'
                    );
                }

                else if (!extension_loaded('Xdebug')) {
                    $this->showExtensionNotLoadedMessage(
                      'Xdebug', 'No code coverage will be generated.'
                    );
                }
            }

            $browsers = $configuration->getSeleniumBrowserConfiguration();

            if (!empty($browsers) &&
                class_exists('PHPUnit_Extensions_SeleniumTestCase')) {
                PHPUnit_Extensions_SeleniumTestCase::$browsers = $browsers;
            }

            if (!isset($this->arguments['test'])) {
                $testSuite = $configuration->getTestSuiteConfiguration(isset($this->arguments['testsuite']) ? $this->arguments['testsuite'] : null);

                if ($testSuite !== NULL) {
                    $this->arguments['test'] = $testSuite;
                }
            }
        }

        if (isset($this->arguments['test']) && is_string($this->arguments['test']) && substr($this->arguments['test'], -5, 5) == '.phpt') {
            $test = new PHPUnit_Extensions_PhptTestCase($this->arguments['test']);

            $this->arguments['test'] = new PHPUnit_Framework_TestSuite;
            $this->arguments['test']->addTest($test);
        }

        if (!isset($this->arguments['test']) ||
            (isset($this->arguments['testDatabaseLogRevision']) && !isset($this->arguments['testDatabaseDSN']))) {
            $this->showHelp();
            exit(PHPUnit_TextUI_TestRunner::EXCEPTION_EXIT);
        }
    }

    /**
     * Handles the loading of the PHPUnit_Runner_TestSuiteLoader implementation.
     *
     * @param  string  $loaderClass
     * @param  string  $loaderFile
     * @return PHPUnit_Runner_TestSuiteLoader
     */
    protected function handleLoader($loaderClass, $loaderFile = '')
    {
        if (!class_exists($loaderClass, FALSE)) {
            if ($loaderFile == '') {
                $loaderFile = PHPUnit_Util_Filesystem::classNameToFilename(
                  $loaderClass
                );
            }

            $loaderFile = stream_resolve_include_path($loaderFile);

            if ($loaderFile) {
                require $loaderFile;
            }
        }

        if (class_exists($loaderClass, FALSE)) {
            $class = new ReflectionClass($loaderClass);

            if ($class->implementsInterface('PHPUnit_Runner_TestSuiteLoader') &&
                $class->isInstantiable()) {
                $loader = $class->newInstance();
            }
        }

        if (!isset($loader)) {
            PHPUnit_TextUI_TestRunner::showError(
              sprintf(
                'Could not use "%s" as loader.',

                $loaderClass
              )
            );
        }

        return $loader;
    }

    /**
     * Handles the loading of the PHPUnit_Util_Printer implementation.
     *
     * @param  string $printerClass
     * @param  string $printerFile
     * @return PHPUnit_Util_Printer
     */
    protected function handlePrinter($printerClass, $printerFile = '')
    {
        if (!class_exists($printerClass, FALSE)) {
            if ($printerFile == '') {
                $printerFile = PHPUnit_Util_Filesystem::classNameToFilename(
                  $printerClass
                );
            }

            $printerFile = stream_resolve_include_path($printerFile);

            if ($printerFile) {
                require $printerFile;
            }
        }

        if (class_exists($printerClass, FALSE)) {
            $class = new ReflectionClass($printerClass);

            if ($class->implementsInterface('PHPUnit_Framework_TestListener') &&
                $class->isSubclassOf('PHPUnit_Util_Printer') &&
                $class->isInstantiable()) {
                $printer = $class->newInstance();
            }
        }

        if (!isset($printer)) {
            PHPUnit_TextUI_TestRunner::showError(
              sprintf(
                'Could not use "%s" as printer.',

                $printerClass
              )
            );
        }

        return $printer;
    }

    /**
     * Loads a bootstrap file.
     *
     * @param string $filename
     */
    protected function handleBootstrap($filename)
    {
        try {
            PHPUnit_Util_Fileloader::checkAndLoad($filename);
        }

        catch (PHPUnit_Framework_Exception $e) {
            PHPUnit_TextUI_TestRunner::showError($e->getMessage());
        }
    }

    /**
     * @param string  $message
     * @since Method available since Release 3.6.0
     */
    protected function showExtensionNotLoadedMessage($extension, $message = '')
    {
        if (isset($this->missingExtensions[$extension])) {
            return;
        }

        if (!empty($message)) {
            $message = ' ' . $message;
        }

        $this->showMessage(
          'The ' . $extension . ' extension is not loaded.' . $message . "\n",
          FALSE
        );

        $this->missingExtensions[$extension] = TRUE;
    }

    /**
     * Shows a message.
     *
     * @param string  $message
     * @param boolean $exit
     */
    protected function showMessage($message, $exit = TRUE)
    {
        PHPUnit_TextUI_TestRunner::printVersionString();
        print $message . "\n";

        if ($exit) {
            exit(PHPUnit_TextUI_TestRunner::EXCEPTION_EXIT);
        } else {
            print "\n";
        }
    }

    /**
     * Show the help message.
     */
    protected function showHelp()
    {
        PHPUnit_TextUI_TestRunner::printVersionString();

        print <<<EOT
Usage: phpunit [switches] UnitTest [UnitTest.php]
       phpunit [switches] <directory>

  --log-junit <file>        Log test execution in JUnit XML format to file.
  --log-tap <file>          Log test execution in TAP format to file.
  --log-json <file>         Log test execution in JSON format.

  --coverage-clover <file>  Generate code coverage report in Clover XML format.
  --coverage-html <dir>     Generate code coverage report in HTML format.
  --coverage-php <file>     Serialize PHP_CodeCoverage object to file.
  --coverage-text=<file>    Generate code coverage report in text format.
                            Default to writing to the standard output.

  --testdox-html <file>     Write agile documentation in HTML format to file.
  --testdox-text <file>     Write agile documentation in Text format to file.

  --filter <pattern>        Filter which tests to run.
  --testsuite <pattern>     Filter which testsuite to run.
  --group ...               Only runs tests from the specified group(s).
  --exclude-group ...       Exclude tests from the specified group(s).
  --list-groups             List available test groups.
  --test-suffix ...         Only search for test in files with specified
                            suffix(es). Default: Test.php,.phpt

  --loader <loader>         TestSuiteLoader implementation to use.
  --printer <printer>       TestSuiteListener implementation to use.
  --repeat <times>          Runs the test(s) repeatedly.

  --tap                     Report test execution progress in TAP format.
  --testdox                 Report test execution progress in TestDox format.

  --colors                  Use colors in output.
  --stderr                  Write to STDERR instead of STDOUT.
  --stop-on-error           Stop execution upon first error.
  --stop-on-failure         Stop execution upon first error or failure.
  --stop-on-skipped         Stop execution upon first skipped test.
  --stop-on-incomplete      Stop execution upon first incomplete test.
  --strict                  Run tests in strict mode.
  -v|--verbose              Output more verbose information.
  --debug                   Display debugging information during test execution.

  --process-isolation       Run each test in a separate PHP process.
  --no-globals-backup       Do not backup and restore \$GLOBALS for each test.
  --static-backup           Backup and restore static attributes for each test.

  --bootstrap <file>        A "bootstrap" PHP file that is run before the tests.
  -c|--configuration <file> Read configuration from XML file.
  --no-configuration        Ignore default configuration file (phpunit.xml).
  --include-path <path(s)>  Prepend PHP's include_path with given path(s).
  -d key[=value]            Sets a php.ini value.

  -h|--help                 Prints this usage information.
  --version                 Prints the version and exits.

EOT;
    }

    /**
     * Custom callback for test suite discovery.
     */
    protected function handleCustomTestSuite()
    {
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.0
 */

/**
 * String helpers.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.0
 */
class PHPUnit_Util_String
{
    /**
     * Converts a string to UTF-8 encoding.
     *
     * @param  string $string
     * @return string
     */
    public static function convertToUtf8($string)
    {
        if (!self::isUtf8($string)) {
            if (function_exists('mb_convert_encoding')) {
                $string = mb_convert_encoding($string, 'UTF-8');
            } else {
                $string = utf8_encode($string);
            }
        }

        return $string;
    }

    /**
     * Checks a string for UTF-8 encoding.
     *
     * @param  string $string
     * @return boolean
     */
    protected static function isUtf8($string)
    {
        $length = strlen($string);

        for ($i = 0; $i < $length; $i++) {
            if (ord($string[$i]) < 0x80) {
                $n = 0;
            }

            else if ((ord($string[$i]) & 0xE0) == 0xC0) {
                $n = 1;
            }

            else if ((ord($string[$i]) & 0xF0) == 0xE0) {
                $n = 2;
            }

            else if ((ord($string[$i]) & 0xF0) == 0xF0) {
                $n = 3;
            }

            else {
                return FALSE;
            }

            for ($j = 0; $j < $n; $j++) {
                if ((++$i == $length) || ((ord($string[$i]) & 0xC0) != 0x80)) {
                    return FALSE;
                }
            }
        }

        return TRUE;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Util_Log
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * A TestListener that generates JSON messages.
 *
 * @package    PHPUnit
 * @subpackage Util_Log
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class PHPUnit_Util_Log_JSON extends PHPUnit_Util_Printer implements PHPUnit_Framework_TestListener
{
    /**
     * @var    string
     */
    protected $currentTestSuiteName = '';

    /**
     * @var    string
     */
    protected $currentTestName = '';

    /**
     * @var     boolean
     * @access  private
     */
    protected $currentTestPass = TRUE;

    /**
     * An error occurred.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  Exception              $e
     * @param  float                  $time
     */
    public function addError(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
        $this->writeCase(
          'error',
          $time,
          PHPUnit_Util_Filter::getFilteredStacktrace($e, FALSE),
          $e->getMessage(),
          $test
        );

        $this->currentTestPass = FALSE;
    }

    /**
     * A failure occurred.
     *
     * @param  PHPUnit_Framework_Test                 $test
     * @param  PHPUnit_Framework_AssertionFailedError $e
     * @param  float                                  $time
     */
    public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time)
    {
        $this->writeCase(
          'fail',
          $time,
          PHPUnit_Util_Filter::getFilteredStacktrace($e, FALSE),
          $e->getMessage(),
          $test
        );

        $this->currentTestPass = FALSE;
    }

    /**
     * Incomplete test.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  Exception              $e
     * @param  float                  $time
     */
    public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
        $this->writeCase(
          'error',
          $time,
          PHPUnit_Util_Filter::getFilteredStacktrace($e, FALSE),
          'Incomplete Test: ' . $e->getMessage(),
          $test
        );

        $this->currentTestPass = FALSE;
    }

    /**
     * Skipped test.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  Exception              $e
     * @param  float                  $time
     */
    public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
        $this->writeCase(
          'error',
          $time,
          PHPUnit_Util_Filter::getFilteredStacktrace($e, FALSE),
          'Skipped Test: ' . $e->getMessage(),
          $test
        );

        $this->currentTestPass = FALSE;
    }

    /**
     * A testsuite started.
     *
     * @param  PHPUnit_Framework_TestSuite $suite
     */
    public function startTestSuite(PHPUnit_Framework_TestSuite $suite)
    {
        $this->currentTestSuiteName = $suite->getName();
        $this->currentTestName      = '';

        $this->write(
          array(
            'event' => 'suiteStart',
            'suite' => $this->currentTestSuiteName,
            'tests' => count($suite)
          )
        );
    }

    /**
     * A testsuite ended.
     *
     * @param  PHPUnit_Framework_TestSuite $suite
     */
    public function endTestSuite(PHPUnit_Framework_TestSuite $suite)
    {
        $this->currentTestSuiteName = '';
        $this->currentTestName      = '';
    }

    /**
     * A test started.
     *
     * @param  PHPUnit_Framework_Test $test
     */
    public function startTest(PHPUnit_Framework_Test $test)
    {
        $this->currentTestName = PHPUnit_Util_Test::describe($test);
        $this->currentTestPass = TRUE;

        $this->write(
          array(
            'event' => 'testStart',
            'suite' => $this->currentTestSuiteName,
            'test'  => $this->currentTestName
          )
        );
    }

    /**
     * A test ended.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  float                  $time
     */
    public function endTest(PHPUnit_Framework_Test $test, $time)
    {
        if ($this->currentTestPass) {
            $this->writeCase('pass', $time, array(), '', $test);
        }
    }

    /**
     * @param string $status
     * @param float  $time
     * @param array  $trace
     * @param string $message
     */
    protected function writeCase($status, $time, array $trace = array(), $message = '', $test = NULL)
    {
        $output = '';
        if ($test !== NULL && $test->hasOutput()) {
            $output = $test->getActualOutput();
        }
        $this->write(
          array(
            'event'   => 'test',
            'suite'   => $this->currentTestSuiteName,
            'test'    => $this->currentTestName,
            'status'  => $status,
            'time'    => $time,
            'trace'   => $trace,
            'message' => PHPUnit_Util_String::convertToUtf8($message),
            'output'  => $output,
          )
        );
    }

    /**
     * @param string $buffer
     */
    public function write($buffer)
    {
        array_walk_recursive($buffer, function(&$input) {
            if (is_string($input)) {
                $input = PHPUnit_Util_String::convertToUtf8($input);
            }
        });

        if (defined('JSON_PRETTY_PRINT')) {
            parent::write(json_encode($buffer, JSON_PRETTY_PRINT));
        } else {
            parent::write(json_encode($buffer));
        }
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Util_Log
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.3.0
 */

/**
 * A TestListener that generates a logfile of the test execution in XML markup.
 *
 * The XML markup used is the same as the one that is used by the JUnit Ant task.
 *
 * @package    PHPUnit
 * @subpackage Util_Log
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.1.0
 */
class PHPUnit_Util_Log_JUnit extends PHPUnit_Util_Printer implements PHPUnit_Framework_TestListener
{
    /**
     * @var    DOMDocument
     */
    protected $document;

    /**
     * @var    DOMElement
     */
    protected $root;

    /**
     * @var    boolean
     */
    protected $logIncompleteSkipped = FALSE;

    /**
     * @var    boolean
     */
    protected $writeDocument = TRUE;

    /**
     * @var    DOMElement[]
     */
    protected $testSuites = array();

    /**
     * @var    integer[]
     */
    protected $testSuiteTests = array(0);

    /**
     * @var    integer[]
     */
    protected $testSuiteAssertions = array(0);

    /**
     * @var    integer[]
     */
    protected $testSuiteErrors = array(0);

    /**
     * @var    integer[]
     */
    protected $testSuiteFailures = array(0);

    /**
     * @var    integer[]
     */
    protected $testSuiteTimes = array(0);

    /**
     * @var    integer
     */
    protected $testSuiteLevel = 0;

    /**
     * @var    DOMElement
     */
    protected $currentTestCase = NULL;

    /**
     * @var    boolean
     */
    protected $attachCurrentTestCase = TRUE;

    /**
     * Constructor.
     *
     * @param  mixed   $out
     * @param  boolean $logIncompleteSkipped
     */
    public function __construct($out = NULL, $logIncompleteSkipped = FALSE)
    {
        $this->document = new DOMDocument('1.0', 'UTF-8');
        $this->document->formatOutput = TRUE;

        $this->root = $this->document->createElement('testsuites');
        $this->document->appendChild($this->root);

        parent::__construct($out);

        $this->logIncompleteSkipped = $logIncompleteSkipped;
    }

    /**
     * Flush buffer and close output.
     *
     */
    public function flush()
    {
        if ($this->writeDocument === TRUE) {
            $this->write($this->getXML());
        }

        parent::flush();
    }

    /**
     * An error occurred.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  Exception              $e
     * @param  float                  $time
     */
    public function addError(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
        if ($this->currentTestCase !== NULL) {
            if ($test instanceof PHPUnit_Framework_SelfDescribing) {
                $buffer = $test->toString() . "\n";
            } else {
                $buffer = '';
            }

            $buffer .= PHPUnit_Framework_TestFailure::exceptionToString($e) .
                       "\n" .
                       PHPUnit_Util_Filter::getFilteredStacktrace($e);

            $error = $this->document->createElement(
              'error', PHPUnit_Util_XML::prepareString($buffer)
            );

            $error->setAttribute('type', get_class($e));

            $this->currentTestCase->appendChild($error);

            $this->testSuiteErrors[$this->testSuiteLevel]++;
        }
    }

    /**
     * A failure occurred.
     *
     * @param  PHPUnit_Framework_Test                 $test
     * @param  PHPUnit_Framework_AssertionFailedError $e
     * @param  float                                  $time
     */
    public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time)
    {
        if ($this->currentTestCase !== NULL) {
            if (!$test instanceof PHPUnit_Framework_Warning) {
                if ($test instanceof PHPUnit_Framework_SelfDescribing) {
                    $buffer = $test->toString() . "\n";
                } else {
                    $buffer = '';
                }

                $buffer .= PHPUnit_Framework_TestFailure::exceptionToString($e) .
                           "\n" .
                           PHPUnit_Util_Filter::getFilteredStacktrace($e);

                $failure = $this->document->createElement(
                  'failure', PHPUnit_Util_XML::prepareString($buffer)
                );

                $failure->setAttribute('type', get_class($e));

                $this->currentTestCase->appendChild($failure);

                $this->testSuiteFailures[$this->testSuiteLevel]++;
            }
        }
    }

    /**
     * Incomplete test.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  Exception              $e
     * @param  float                  $time
     */
    public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
        if ($this->logIncompleteSkipped && $this->currentTestCase !== NULL) {
            $error = $this->document->createElement(
              'error',
              PHPUnit_Util_XML::prepareString(
                "Incomplete Test\n" .
                PHPUnit_Util_Filter::getFilteredStacktrace($e)
              )
            );

            $error->setAttribute('type', get_class($e));

            $this->currentTestCase->appendChild($error);

            $this->testSuiteErrors[$this->testSuiteLevel]++;
        } else {
            $this->attachCurrentTestCase = FALSE;
        }
    }

    /**
     * Skipped test.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  Exception              $e
     * @param  float                  $time
     * @since  Method available since Release 3.0.0
     */
    public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
        if ($this->logIncompleteSkipped && $this->currentTestCase !== NULL) {
            $error = $this->document->createElement(
              'error',
              PHPUnit_Util_XML::prepareString(
                "Skipped Test\n" .
                PHPUnit_Util_Filter::getFilteredStacktrace($e)
              )
            );

            $error->setAttribute('type', get_class($e));

            $this->currentTestCase->appendChild($error);

            $this->testSuiteErrors[$this->testSuiteLevel]++;
        } else {
            $this->attachCurrentTestCase = FALSE;
        }
    }

    /**
     * A testsuite started.
     *
     * @param  PHPUnit_Framework_TestSuite $suite
     * @since  Method available since Release 2.2.0
     */
    public function startTestSuite(PHPUnit_Framework_TestSuite $suite)
    {
        $testSuite = $this->document->createElement('testsuite');
        $testSuite->setAttribute('name', $suite->getName());

        if (class_exists($suite->getName(), FALSE)) {
            try {
                $class = new ReflectionClass($suite->getName());

                $testSuite->setAttribute('file', $class->getFileName());

                $packageInformation = PHPUnit_Util_Class::getPackageInformation(
                  $suite->getName(), $class->getDocComment()
                );

                if (!empty($packageInformation['namespace'])) {
                    $testSuite->setAttribute(
                      'namespace', $packageInformation['namespace']
                    );
                }

                if (!empty($packageInformation['fullPackage'])) {
                    $testSuite->setAttribute(
                      'fullPackage', $packageInformation['fullPackage']
                    );
                }

                if (!empty($packageInformation['category'])) {
                    $testSuite->setAttribute(
                      'category', $packageInformation['category']
                    );
                }

                if (!empty($packageInformation['package'])) {
                    $testSuite->setAttribute(
                      'package', $packageInformation['package']
                    );
                }

                if (!empty($packageInformation['subpackage'])) {
                    $testSuite->setAttribute(
                      'subpackage', $packageInformation['subpackage']
                    );
                }
            }

            catch (ReflectionException $e) {
            }
        }

        if ($this->testSuiteLevel > 0) {
            $this->testSuites[$this->testSuiteLevel]->appendChild($testSuite);
        } else {
            $this->root->appendChild($testSuite);
        }

        $this->testSuiteLevel++;
        $this->testSuites[$this->testSuiteLevel]          = $testSuite;
        $this->testSuiteTests[$this->testSuiteLevel]      = 0;
        $this->testSuiteAssertions[$this->testSuiteLevel] = 0;
        $this->testSuiteErrors[$this->testSuiteLevel]     = 0;
        $this->testSuiteFailures[$this->testSuiteLevel]   = 0;
        $this->testSuiteTimes[$this->testSuiteLevel]      = 0;
    }

    /**
     * A testsuite ended.
     *
     * @param  PHPUnit_Framework_TestSuite $suite
     * @since  Method available since Release 2.2.0
     */
    public function endTestSuite(PHPUnit_Framework_TestSuite $suite)
    {
        $this->testSuites[$this->testSuiteLevel]->setAttribute(
          'tests', $this->testSuiteTests[$this->testSuiteLevel]
        );

        $this->testSuites[$this->testSuiteLevel]->setAttribute(
          'assertions', $this->testSuiteAssertions[$this->testSuiteLevel]
        );

        $this->testSuites[$this->testSuiteLevel]->setAttribute(
          'failures', $this->testSuiteFailures[$this->testSuiteLevel]
        );

        $this->testSuites[$this->testSuiteLevel]->setAttribute(
          'errors', $this->testSuiteErrors[$this->testSuiteLevel]
        );

        $this->testSuites[$this->testSuiteLevel]->setAttribute(
          'time', sprintf('%F', $this->testSuiteTimes[$this->testSuiteLevel])
        );

        if ($this->testSuiteLevel > 1) {
            $this->testSuiteTests[$this->testSuiteLevel - 1]      += $this->testSuiteTests[$this->testSuiteLevel];
            $this->testSuiteAssertions[$this->testSuiteLevel - 1] += $this->testSuiteAssertions[$this->testSuiteLevel];
            $this->testSuiteErrors[$this->testSuiteLevel - 1]     += $this->testSuiteErrors[$this->testSuiteLevel];
            $this->testSuiteFailures[$this->testSuiteLevel - 1]   += $this->testSuiteFailures[$this->testSuiteLevel];
            $this->testSuiteTimes[$this->testSuiteLevel - 1]      += $this->testSuiteTimes[$this->testSuiteLevel];
        }

        $this->testSuiteLevel--;
    }

    /**
     * A test started.
     *
     * @param  PHPUnit_Framework_Test $test
     */
    public function startTest(PHPUnit_Framework_Test $test)
    {
        if (!$test instanceof PHPUnit_Framework_Warning) {
            $testCase = $this->document->createElement('testcase');
            $testCase->setAttribute('name', $test->getName());

            if ($test instanceof PHPUnit_Framework_TestCase) {
                $class      = new ReflectionClass($test);
                $methodName = $test->getName();

                if ($class->hasMethod($methodName)) {
                    $method = $class->getMethod($test->getName());

                    $testCase->setAttribute('class', $class->getName());
                    $testCase->setAttribute('file', $class->getFileName());
                    $testCase->setAttribute('line', $method->getStartLine());
                }
            }

            $this->currentTestCase = $testCase;
        }
    }

    /**
     * A test ended.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  float                  $time
     */
    public function endTest(PHPUnit_Framework_Test $test, $time)
    {
        if (!$test instanceof PHPUnit_Framework_Warning) {
            if ($this->attachCurrentTestCase) {
                if ($test instanceof PHPUnit_Framework_TestCase) {
                    $numAssertions = $test->getNumAssertions();
                    $this->testSuiteAssertions[$this->testSuiteLevel] += $numAssertions;

                    $this->currentTestCase->setAttribute(
                      'assertions', $numAssertions
                    );
                }

                $this->currentTestCase->setAttribute(
                  'time', sprintf('%F', $time)
                );

                $this->testSuites[$this->testSuiteLevel]->appendChild(
                  $this->currentTestCase
                );

                $this->testSuiteTests[$this->testSuiteLevel]++;
                $this->testSuiteTimes[$this->testSuiteLevel] += $time;
            }
        }

        $this->attachCurrentTestCase = TRUE;
        $this->currentTestCase       = NULL;
    }

    /**
     * Returns the XML as a string.
     *
     * @return string
     * @since  Method available since Release 2.2.0
     */
    public function getXML()
    {
        return $this->document->saveXML();
    }

    /**
     * Enables or disables the writing of the document
     * in flush().
     *
     * This is a "hack" needed for the integration of
     * PHPUnit with Phing.
     *
     * @return string
     * @since  Method available since Release 2.2.0
     */
    public function setWriteDocument($flag)
    {
        if (is_bool($flag)) {
            $this->writeDocument = $flag;
        }
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Util_Log
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * A TestListener that generates a logfile of the
 * test execution using the Test Anything Protocol (TAP).
 *
 * @package    PHPUnit
 * @subpackage Util_Log
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class PHPUnit_Util_Log_TAP extends PHPUnit_Util_Printer implements PHPUnit_Framework_TestListener
{
    /**
     * @var    integer
     */
    protected $testNumber = 0;

    /**
     * @var    integer
     */
    protected $testSuiteLevel = 0;

    /**
     * @var    boolean
     */
    protected $testSuccessful = TRUE;

    /**
     * Constructor.
     *
     * @param  mixed $out
     * @throws PHPUnit_Framework_Exception
     * @since  Method available since Release 3.3.4
     */
    public function __construct($out = NULL)
    {
        parent::__construct($out);
        $this->write("TAP version 13\n");
    }

    /**
     * An error occurred.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  Exception              $e
     * @param  float                  $time
     */
    public function addError(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
        $this->writeNotOk($test, 'Error');
    }

    /**
     * A failure occurred.
     *
     * @param  PHPUnit_Framework_Test                 $test
     * @param  PHPUnit_Framework_AssertionFailedError $e
     * @param  float                                  $time
     */
    public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time)
    {
        $this->writeNotOk($test, 'Failure');

        $message = explode(
          "\n", PHPUnit_Framework_TestFailure::exceptionToString($e)
        );

        $diagnostic = array(
          'message'  => $message[0],
          'severity' => 'fail'
        );

        if ($e instanceof PHPUnit_Framework_ExpectationFailedException) {
            $cf = $e->getComparisonFailure();

            if ($cf !== NULL) {
                $diagnostic['data'] = array(
                  'got'      => $cf->getActual(),
                  'expected' => $cf->getExpected()
                );
            }
        }

        $yaml = new Symfony\Component\Yaml\Dumper;

        $this->write(
          sprintf(
            "  ---\n%s  ...\n",
            $yaml->dump($diagnostic, 2, 2)
          )
        );
    }

    /**
     * Incomplete test.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  Exception              $e
     * @param  float                  $time
     */
    public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
        $this->writeNotOk($test, '', 'TODO Incomplete Test');
    }

    /**
     * Skipped test.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  Exception              $e
     * @param  float                  $time
     * @since  Method available since Release 3.0.0
     */
    public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
        $this->write(
          sprintf(
            "ok %d - # SKIP%s\n",

            $this->testNumber,
            $e->getMessage() != '' ? ' ' . $e->getMessage() : ''
          )
        );

        $this->testSuccessful = FALSE;
    }

    /**
     * A testsuite started.
     *
     * @param  PHPUnit_Framework_TestSuite $suite
     */
    public function startTestSuite(PHPUnit_Framework_TestSuite $suite)
    {
        $this->testSuiteLevel++;
    }

    /**
     * A testsuite ended.
     *
     * @param  PHPUnit_Framework_TestSuite $suite
     */
    public function endTestSuite(PHPUnit_Framework_TestSuite $suite)
    {
        $this->testSuiteLevel--;

        if ($this->testSuiteLevel == 0) {
            $this->write(sprintf("1..%d\n", $this->testNumber));
        }
    }

    /**
     * A test started.
     *
     * @param  PHPUnit_Framework_Test $test
     */
    public function startTest(PHPUnit_Framework_Test $test)
    {
        $this->testNumber++;
        $this->testSuccessful = TRUE;
    }

    /**
     * A test ended.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  float                  $time
     */
    public function endTest(PHPUnit_Framework_Test $test, $time)
    {
        if ($this->testSuccessful === TRUE) {
            $this->write(
              sprintf(
                "ok %d - %s\n",

                $this->testNumber,
                PHPUnit_Util_Test::describe($test)
              )
            );
        }
    }

    /**
     * @param  PHPUnit_Framework_Test $test
     * @param  string                 $prefix
     * @param  string                 $directive
     */
    protected function writeNotOk(PHPUnit_Framework_Test $test, $prefix = '', $directive = '')
    {
        $this->write(
          sprintf(
            "not ok %d - %s%s%s\n",

            $this->testNumber,
            $prefix != '' ? $prefix . ': ' : '',
            PHPUnit_Util_Test::describe($test),
            $directive != '' ? ' # ' . $directive : ''
          )
        );

        $this->testSuccessful = FALSE;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * Filesystem helpers.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class PHPUnit_Util_Filesystem
{
    /**
     * @var array
     */
    protected static $buffer = array();

    /**
     * Maps class names to source file names:
     *   - PEAR CS:   Foo_Bar_Baz -> Foo/Bar/Baz.php
     *   - Namespace: Foo\Bar\Baz -> Foo/Bar/Baz.php
     *
     * @param  string $className
     * @return string
     * @since  Method available since Release 3.4.0
     */
    public static function classNameToFilename($className)
    {
        return str_replace(
          array('_', '\\'),
          DIRECTORY_SEPARATOR,
          $className
        ) . '.php';
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.3.0
 */

/**
 * Utility methods to load PHP sourcefiles.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.3.0
 */
class PHPUnit_Util_Fileloader
{
    /**
     * Checks if a PHP sourcefile is readable.
     * The sourcefile is loaded through the load() method.
     *
     * @param  string $filename
     * @throws PHPUnit_Framework_Exception
     */
    public static function checkAndLoad($filename)
    {
        $includePathFilename = stream_resolve_include_path($filename);

        if (!$includePathFilename || !is_readable($includePathFilename)) {
            throw new PHPUnit_Framework_Exception(
              sprintf('Cannot open file "%s".' . "\n", $filename)
            );
        }

        self::load($includePathFilename);

        return $includePathFilename;
    }

    /**
     * Loads a PHP sourcefile.
     *
     * @param  string $filename
     * @return mixed
     * @since  Method available since Release 3.0.0
     */
    public static function load($filename)
    {
        $oldVariableNames = array_keys(get_defined_vars());

        include_once $filename;

        $newVariables     = get_defined_vars();
        $newVariableNames = array_diff(
                              array_keys($newVariables), $oldVariableNames
                            );

        foreach ($newVariableNames as $variableName) {
            if ($variableName != 'oldVariableNames') {
                $GLOBALS[$variableName] = $newVariables[$variableName];
            }
        }

        return $filename;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2002-2010, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Ralph Schindler <ralph.schindler@zend.com>
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2002-2010 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.5.7
 */

/**
 * Test Listener that tracks the usage of deprecated features.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Ralph Schindler <ralph.schindler@zend.com>
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2002-2010 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.5.7
 */
class PHPUnit_Util_DeprecatedFeature_Logger implements PHPUnit_Framework_TestListener
{
    /**
     * @var PHPUnit_Framework_TestCase
     */
    protected static $currentTest = NULL;

    /**
     * This is the publically accessible API for notifying the system that a
     * deprecated feature has been used.
     *
     * If it is run via a TestRunner and the test extends
     * PHPUnit_Framework_TestCase, then this will inject the result into the
     * test runner for display, if not, it will throw the notice to STDERR.
     *
     * @param string $message
     * @param int|bool $backtraceDepth
     */
    public static function log($message, $backtraceDepth = 2)
    {
        if ($backtraceDepth !== FALSE) {
            $trace = debug_backtrace(FALSE);

            if (is_int($backtraceDepth)) {
                $traceItem = $trace[$backtraceDepth];
            }

            if (!isset($traceItem['file'])) {
                $reflectionClass   = new ReflectionClass($traceItem['class']);
                $traceItem['file'] = $reflectionClass->getFileName();
            }

            if (!isset($traceItem['line']) &&
                 isset($traceItem['class']) &&
                 isset($traceItem['function'])) {
                if (!isset($reflectionClass)) {
                    $reflectionClass = new ReflectionClass($traceItem['class']);
                }

                $method = $reflectionClass->getMethod($traceItem['function']);
                $traceItem['line'] = '(between ' . $method->getStartLine() .
                                     ' and ' . $method->getEndLine() . ')';
            }
        }

        $deprecatedFeature = new PHPUnit_Util_DeprecatedFeature(
          $message, $traceItem
        );

        if (self::$currentTest instanceof PHPUnit_Framework_TestCase) {
            $result = self::$currentTest->getTestResultObject();
            $result->addDeprecatedFeature($deprecatedFeature);
        } else {
            file_put_contents('php://stderr', $deprecatedFeature);
        }
    }

    /**
     * An error occurred.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  Exception              $e
     * @param  float                  $time
     */
    public function addError(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
    }

    /**
     * A failure occurred.
     *
     * @param  PHPUnit_Framework_Test                 $test
     * @param  PHPUnit_Framework_AssertionFailedError $e
     * @param  float                                  $time
     */
    public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time)
    {
    }

    /**
     * Incomplete test.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  Exception              $e
     * @param  float                  $time
     */
    public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
    }

    /**
     * Skipped test.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  Exception              $e
     * @param  float                  $time
     * @since  Method available since Release 3.0.0
     */
    public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
    }

    /**
     * A test suite started.
     *
     * @param  PHPUnit_Framework_TestSuite $suite
     * @since  Method available since Release 2.2.0
     */
    public function startTestSuite(PHPUnit_Framework_TestSuite $suite)
    {
    }

    /**
     * A test suite ended.
     *
     * @param  PHPUnit_Framework_TestSuite $suite
     * @since  Method available since Release 2.2.0
     */
    public function endTestSuite(PHPUnit_Framework_TestSuite $suite)
    {
    }

    /**
     * A test started.
     *
     * @param  PHPUnit_Framework_Test $test
     */
    public function startTest(PHPUnit_Framework_Test $test)
    {
        self::$currentTest = $test;
    }

    /**
     * A test ended.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  float                  $time
     */
    public function endTest(PHPUnit_Framework_Test $test, $time)
    {
        self::$currentTest = NULL;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Util_TestDox
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.3.0
 */

/**
 * Base class for printers of TestDox documentation.
 *
 * @package    PHPUnit
 * @subpackage Util_TestDox
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.1.0
 */
abstract class PHPUnit_Util_TestDox_ResultPrinter extends PHPUnit_Util_Printer implements PHPUnit_Framework_TestListener
{
    /**
     * @var PHPUnit_Util_TestDox_NamePrettifier
     */
    protected $prettifier;

    /**
     * @var string
     */
    protected $testClass = '';

    /**
     * @var integer
     */
    protected $testStatus = FALSE;

    /**
     * @var array
     */
    protected $tests = array();

    /**
     * @var integer
     */
    protected $successful = 0;

    /**
     * @var integer
     */
    protected $failed = 0;

    /**
     * @var integer
     */
    protected $skipped = 0;

    /**
     * @var integer
     */
    protected $incomplete = 0;

    /**
     * @var string
     */
    protected $testTypeOfInterest = 'PHPUnit_Framework_TestCase';

    /**
     * @var string
     */
    protected $currentTestClassPrettified;

    /**
     * @var string
     */
    protected $currentTestMethodPrettified;

    /**
     * Constructor.
     *
     * @param  resource  $out
     */
    public function __construct($out = NULL)
    {
        parent::__construct($out);

        $this->prettifier = new PHPUnit_Util_TestDox_NamePrettifier;
        $this->startRun();
    }

    /**
     * Flush buffer and close output.
     *
     */
    public function flush()
    {
        $this->doEndClass();
        $this->endRun();

        parent::flush();
    }

    /**
     * An error occurred.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  Exception              $e
     * @param  float                  $time
     */
    public function addError(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
        if ($test instanceof $this->testTypeOfInterest) {
            $this->testStatus = PHPUnit_Runner_BaseTestRunner::STATUS_ERROR;
            $this->failed++;
        }
    }

    /**
     * A failure occurred.
     *
     * @param  PHPUnit_Framework_Test                 $test
     * @param  PHPUnit_Framework_AssertionFailedError $e
     * @param  float                                  $time
     */
    public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time)
    {
        if ($test instanceof $this->testTypeOfInterest) {
            $this->testStatus = PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE;
            $this->failed++;
        }
    }

    /**
     * Incomplete test.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  Exception              $e
     * @param  float                  $time
     */
    public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
        if ($test instanceof $this->testTypeOfInterest) {
            $this->testStatus = PHPUnit_Runner_BaseTestRunner::STATUS_INCOMPLETE;
            $this->incomplete++;
        }
    }

    /**
     * Skipped test.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  Exception              $e
     * @param  float                  $time
     * @since  Method available since Release 3.0.0
     */
    public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
        if ($test instanceof $this->testTypeOfInterest) {
            $this->testStatus = PHPUnit_Runner_BaseTestRunner::STATUS_SKIPPED;
            $this->skipped++;
        }
    }

    /**
     * A testsuite started.
     *
     * @param  PHPUnit_Framework_TestSuite $suite
     * @since  Method available since Release 2.2.0
     */
    public function startTestSuite(PHPUnit_Framework_TestSuite $suite)
    {
    }

    /**
     * A testsuite ended.
     *
     * @param  PHPUnit_Framework_TestSuite $suite
     * @since  Method available since Release 2.2.0
     */
    public function endTestSuite(PHPUnit_Framework_TestSuite $suite)
    {
    }

    /**
     * A test started.
     *
     * @param  PHPUnit_Framework_Test $test
     */
    public function startTest(PHPUnit_Framework_Test $test)
    {
        if ($test instanceof $this->testTypeOfInterest) {
            $class = get_class($test);

            if ($this->testClass != $class) {
                if ($this->testClass != '') {
                    $this->doEndClass();
                }

                $this->currentTestClassPrettified = $this->prettifier->prettifyTestClass($class);
                $this->startClass($class);

                $this->testClass = $class;
                $this->tests     = array();
            }

            $prettified = FALSE;

            if ($test instanceof PHPUnit_Framework_TestCase &&
               !$test instanceof PHPUnit_Framework_Warning) {
                $annotations = $test->getAnnotations();

                if (isset($annotations['method']['testdox'][0])) {
                    $this->currentTestMethodPrettified = $annotations['method']['testdox'][0];
                    $prettified                        = TRUE;
                }
            }

            if (!$prettified) {
                $this->currentTestMethodPrettified = $this->prettifier->prettifyTestMethod($test->getName(FALSE));
            }

            $this->testStatus = PHPUnit_Runner_BaseTestRunner::STATUS_PASSED;
        }
    }

    /**
     * A test ended.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  float                  $time
     */
    public function endTest(PHPUnit_Framework_Test $test, $time)
    {
        if ($test instanceof $this->testTypeOfInterest) {
            if (!isset($this->tests[$this->currentTestMethodPrettified])) {
                if ($this->testStatus == PHPUnit_Runner_BaseTestRunner::STATUS_PASSED) {
                    $this->tests[$this->currentTestMethodPrettified]['success'] = 1;
                    $this->tests[$this->currentTestMethodPrettified]['failure'] = 0;
                } else {
                    $this->tests[$this->currentTestMethodPrettified]['success'] = 0;
                    $this->tests[$this->currentTestMethodPrettified]['failure'] = 1;
                }
            } else {
                if ($this->testStatus == PHPUnit_Runner_BaseTestRunner::STATUS_PASSED) {
                    $this->tests[$this->currentTestMethodPrettified]['success']++;
                } else {
                    $this->tests[$this->currentTestMethodPrettified]['failure']++;
                }
            }

            $this->currentTestClassPrettified  = NULL;
            $this->currentTestMethodPrettified = NULL;
        }
    }

    /**
     * @since  Method available since Release 2.3.0
     */
    protected function doEndClass()
    {
        foreach ($this->tests as $name => $data) {
            $this->onTest($name, $data['failure'] == 0);
        }

        $this->endClass($this->testClass);
    }

    /**
     * Handler for 'start run' event.
     *
     */
    protected function startRun()
    {
    }

    /**
     * Handler for 'start class' event.
     *
     * @param  string $name
     */
    protected function startClass($name)
    {
    }

    /**
     * Handler for 'on test' event.
     *
     * @param  string  $name
     * @param  boolean $success
     */
    protected function onTest($name, $success = TRUE)
    {
    }

    /**
     * Handler for 'end class' event.
     *
     * @param  string $name
     */
    protected function endClass($name)
    {
    }

    /**
     * Handler for 'end run' event.
     *
     */
    protected function endRun()
    {
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Util_TestDox
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.3.0
 */

/**
 * Prints TestDox documentation in HTML format.
 *
 * @package    PHPUnit
 * @subpackage Util_TestDox
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.1.0
 */
class PHPUnit_Util_TestDox_ResultPrinter_HTML extends PHPUnit_Util_TestDox_ResultPrinter
{
    /**
     * @var    boolean
     */
    protected $printsHTML = TRUE;

    /**
     * Handler for 'start run' event.
     *
     */
    protected function startRun()
    {
        $this->write('<html><body>');
    }

    /**
     * Handler for 'start class' event.
     *
     * @param  string $name
     */
    protected function startClass($name)
    {
        $this->write(
          '<h2 id="' . $name . '">' . $this->currentTestClassPrettified .
          '</h2><ul>'
        );
    }

    /**
     * Handler for 'on test' event.
     *
     * @param  string  $name
     * @param  boolean $success
     */
    protected function onTest($name, $success = TRUE)
    {
        if (!$success) {
            $strikeOpen  = '<strike>';
            $strikeClose = '</strike>';
        } else {
            $strikeOpen  = '';
            $strikeClose = '';
        }

        $this->write('<li>' . $strikeOpen . $name . $strikeClose . '</li>');
    }

    /**
     * Handler for 'end class' event.
     *
     * @param  string $name
     */
    protected function endClass($name)
    {
        $this->write('</ul>');
    }

    /**
     * Handler for 'end run' event.
     *
     */
    protected function endRun()
    {
        $this->write('</body></html>');
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Util_TestDox
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.3.0
 */

/**
 * Prints TestDox documentation in text format.
 *
 * @package    PHPUnit
 * @subpackage Util_TestDox
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.1.0
 */
class PHPUnit_Util_TestDox_ResultPrinter_Text extends PHPUnit_Util_TestDox_ResultPrinter
{
    /**
     * Handler for 'start class' event.
     *
     * @param  string $name
     */
    protected function startClass($name)
    {
        $this->write($this->currentTestClassPrettified . "\n");
    }

    /**
     * Handler for 'on test' event.
     *
     * @param  string  $name
     * @param  boolean $success
     */
    protected function onTest($name, $success = TRUE)
    {
        if ($success) {
            $this->write(' [x] ');
        } else {
            $this->write(' [ ] ');
        }

        $this->write($name . "\n");
    }

    /**
     * Handler for 'end class' event.
     *
     * @param  string $name
     */
    protected function endClass($name)
    {
        $this->write("\n");
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Util_TestDox
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.3.0
 */

/**
 * Prettifies class and method names for use in TestDox documentation.
 *
 * @package    PHPUnit
 * @subpackage Util_TestDox
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.1.0
 */
class PHPUnit_Util_TestDox_NamePrettifier
{
    /**
     * @var    string
     */
    protected $prefix = 'Test';

    /**
     * @var    string
     */
    protected $suffix = 'Test';

    /**
     * @var    array
     */
    protected $strings = array();

    /**
     * Prettifies the name of a test class.
     *
     * @param  string  $name
     * @return string
     */
    public function prettifyTestClass($name)
    {
        $title = $name;

        if ($this->suffix !== NULL &&
            $this->suffix == substr($name, -1 * strlen($this->suffix))) {
            $title = substr($title, 0, strripos($title, $this->suffix));
        }

        if ($this->prefix !== NULL &&
            $this->prefix == substr($name, 0, strlen($this->prefix))) {
            $title = substr($title, strlen($this->prefix));
        }

        return $title;
    }

    /**
     * Prettifies the name of a test method.
     *
     * @param  string  $name
     * @return string
     */
    public function prettifyTestMethod($name)
    {
        $buffer = '';

        if (!is_string($name) || strlen($name) == 0) {
            return $buffer;
        }

        $string = preg_replace('#\d+$#', '', $name, -1, $count);

        if (in_array($string, $this->strings)) {
            $name = $string;
        } else if ($count == 0) {
            $this->strings[] = $string;
        }

        if (strpos($name, '_') !== FALSE) {
            return str_replace('_', ' ', $name);
        }

        $max = strlen($name);

        if (substr($name, 0, 4) == 'test') {
            $offset = 4;
        } else {
            $offset  = 0;
            $name[0] = strtoupper($name[0]);
        }

        $wasNumeric = FALSE;

        for ($i = $offset; $i < $max; $i++) {
            if ($i > $offset &&
                ord($name[$i]) >= 65 &&
                ord($name[$i]) <= 90) {
                $buffer .= ' ' . strtolower($name[$i]);
            } else {
                $isNumeric = is_numeric($name[$i]);

                if (!$wasNumeric && $isNumeric) {
                    $buffer    .= ' ';
                    $wasNumeric = TRUE;
                }

                if ($wasNumeric && !$isNumeric) {
                    $wasNumeric = FALSE;
                }

                $buffer .= $name[$i];
            }
        }

        return $buffer;
    }

    /**
     * Sets the prefix of test names.
     *
     * @param  string  $prefix
     */
    public function setPrefix($prefix)
    {
        $this->prefix = $prefix;
    }

    /**
     * Sets the suffix of test names.
     *
     * @param  string  $prefix
     */
    public function setSuffix($suffix)
    {
        $this->suffix = $suffix;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2002-2010, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Ralph Schindler <ralph.schindler@zend.com>
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2002-2010 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.5.7
 */

/**
 * Class to hold the information about a deprecated feature that was used
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Ralph Schindler <ralph.schindler@zend.com>
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2002-2010 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Interface available since Release 3.5.7
 */
class PHPUnit_Util_DeprecatedFeature
{
    /**
     * @var array
     */
    protected $traceInfo = array();

    /**
     * @var string
     */
    protected $message = NULL;

    /**
     * @param  string $message
     * @param  array  $traceInfo
     */
    public function __construct($message, array $traceInfo = array())
    {
        $this->message   = $message;
        $this->traceInfo = $traceInfo;
    }

    /**
     * Build a string representation of the deprecated feature that was raised
     *
     * @return string
     */
    public function __toString()
    {
        $string = '';

        if (isset($this->traceInfo['file'])) {
            $string .= $this->traceInfo['file'];

            if (isset($this->traceInfo['line'])) {
                $string .= ':' . $this->traceInfo['line'] . ' - ';
            }
        }

        $string .= $this->message;

        return $string;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

/**
 * Utility class that can print to STDOUT or write to a file.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.0.0
 */
class PHPUnit_Util_Printer
{
    /**
     * If TRUE, flush output after every write.
     *
     * @var boolean
     */
    protected $autoFlush = FALSE;

    /**
     * @var    resource
     */
    protected $out;

    /**
     * @var    string
     */
    protected $outTarget;

    /**
     * @var    boolean
     */
    protected $printsHTML = FALSE;

    /**
     * Constructor.
     *
     * @param  mixed $out
     * @throws PHPUnit_Framework_Exception
     */
    public function __construct($out = NULL)
    {
        if ($out !== NULL) {
            if (is_string($out)) {
                if (strpos($out, 'socket://') === 0) {
                    $out = explode(':', str_replace('socket://', '', $out));

                    if (sizeof($out) != 2) {
                        throw new PHPUnit_Framework_Exception;
                    }

                    $this->out = fsockopen($out[0], $out[1]);
                } else {
                    if (strpos($out, 'php://') === FALSE &&
                        !is_dir(dirname($out))) {
                        mkdir(dirname($out), 0777, TRUE);
                    }

                    $this->out = fopen($out, 'wt');
                }

                $this->outTarget = $out;
            } else {
                $this->out = $out;
            }
        }
    }

    /**
     * Flush buffer, optionally tidy up HTML, and close output if it's not to a php stream
     */
    public function flush()
    {
        if ($this->out && strncmp($this->outTarget, 'php://', 6) !== 0) {
            fclose($this->out);
        }

        if ($this->printsHTML === TRUE &&
            $this->outTarget !== NULL &&
            strpos($this->outTarget, 'php://') !== 0 &&
            strpos($this->outTarget, 'socket://') !== 0 &&
            extension_loaded('tidy')) {
            file_put_contents(
              $this->outTarget,
              tidy_repair_file(
                $this->outTarget, array('indent' => TRUE, 'wrap' => 0), 'utf8'
              )
            );
        }
    }

    /**
     * Performs a safe, incremental flush.
     *
     * Do not confuse this function with the flush() function of this class,
     * since the flush() function may close the file being written to, rendering
     * the current object no longer usable.
     *
     * @since  Method available since Release 3.3.0
     */
    public function incrementalFlush()
    {
        if ($this->out) {
            fflush($this->out);
        } else {
            flush();
        }
    }

    /**
     * @param  string $buffer
     */
    public function write($buffer)
    {
        if ($this->out) {
            fwrite($this->out, $buffer);

            if ($this->autoFlush) {
                $this->incrementalFlush();
            }
        } else {
            if (PHP_SAPI != 'cli') {
                $buffer = htmlspecialchars($buffer);
            }

            print $buffer;

            if ($this->autoFlush) {
                $this->incrementalFlush();
            }
        }
    }

    /**
     * Check auto-flush mode.
     *
     * @return boolean
     * @since  Method available since Release 3.3.0
     */
    public function getAutoFlush()
    {
        return $this->autoFlush;
    }

    /**
     * Set auto-flushing mode.
     *
     * If set, *incremental* flushes will be done after each write. This should
     * not be confused with the different effects of this class' flush() method.
     *
     * @param boolean $autoFlush
     * @since  Method available since Release 3.3.0
     */
    public function setAutoFlush($autoFlush)
    {
        if (is_bool($autoFlush)) {
            $this->autoFlush = $autoFlush;
        } else {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
        }
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Kore Nordmann <mail@kore-nordmann.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.4.0
 */

/**
 * Diff implementation.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Kore Nordmann <mail@kore-nordmann.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.4.0
 */
class PHPUnit_Util_Diff
{
    /**
     * Returns the diff between two arrays or strings as string.
     *
     * @param  array|string $from
     * @param  array|string $to
     * @return string
     */
    public static function diff($from, $to)
    {
        $buffer= "--- Expected\n+++ Actual\n";
        $diff  = self::diffToArray($from,$to);

        $inOld = FALSE;
        $i     = 0;
        $old   = array();

        foreach ($diff as $line) {
            if ($line[1] ===  0 /* OLD */) {
                if ($inOld === FALSE) {
                    $inOld = $i;
                }
            }

            else if ($inOld !== FALSE) {
                if (($i - $inOld) > 5) {
                    $old[$inOld] = $i - 1;
                }

                $inOld = FALSE;
            }

            ++$i;
        }

        $start = isset($old[0]) ? $old[0] : 0;
        $end   = count($diff);
        $i     = 0;

        if ($tmp = array_search($end, $old)) {
            $end = $tmp;
        }

        $newChunk = TRUE;

        for ($i = $start; $i < $end; $i++) {
            if (isset($old[$i])) {
                $buffer  .= "\n";
                $newChunk = TRUE;
                $i        = $old[$i];
            }

            if ($newChunk) {
                $buffer  .= "@@ @@\n";
                $newChunk = FALSE;
            }

            if ($diff[$i][1] === 1 /* ADDED */) {
                $buffer .= '+' . $diff[$i][0] . "\n";
            }

            else if ($diff[$i][1] === 2 /* REMOVED */) {
                $buffer .= '-' . $diff[$i][0] . "\n";
            }

            else {
                $buffer .= ' ' . $diff[$i][0] . "\n";
            }
        }

        return $buffer;
    }

    /**
     * Returns the diff between two arrays or strings as array.
     *
     * every array-entry containts two elements:
     *   - [0] => string $token
     *   - [1] => 2|1|0
     *
     * - 2: REMOVED: $token was removed from $from
     * - 1: ADDED: $token was added to $from
     * - 0: OLD: $token is not changed in $to
     *
     * @param  array|string $from
     * @param  array|string $to
     * @return array
     */
    public static function diffToArray($from, $to)
    {
        preg_match_all('(\r\n|\r|\n)', $from, $fromMatches);
        preg_match_all('(\r\n|\r|\n)', $to, $toMatches);

        if (is_string($from)) {
            $from = preg_split('(\r\n|\r|\n)', $from);
        }

        if (is_string($to)) {
            $to = preg_split('(\r\n|\r|\n)', $to);
        }

        $start      = array();
        $end        = array();
        $fromLength = count($from);
        $toLength   = count($to);
        $length     = min($fromLength, $toLength);

        for ($i = 0; $i < $length; ++$i) {
            if ($from[$i] === $to[$i]) {
                $start[] = $from[$i];
                unset($from[$i], $to[$i]);
            } else {
                break;
            }
        }

        $length -= $i;

        for ($i = 1; $i < $length; ++$i) {
            if ($from[$fromLength - $i] === $to[$toLength - $i]) {
                array_unshift($end, $from[$fromLength - $i]);
                unset($from[$fromLength - $i], $to[$toLength - $i]);
            } else {
                break;
            }
        }

        $common = self::longestCommonSubsequence(
          array_values($from), array_values($to)
        );

        $diff = array();
        $line = 0;

        if (isset($fromMatches[0]) && $toMatches[0] &&
            count($fromMatches[0]) === count($toMatches[0]) &&
            $fromMatches[0] !== $toMatches[0]) {
            $diff[] = array(
              '#Warning: Strings contain different line endings!', 0
            );
        }

        foreach ($start as $token) {
            $diff[] = array($token, 0 /* OLD */);
        }

        reset($from);
        reset($to);

        foreach ($common as $token) {
            while ((($fromToken = reset($from)) !== $token)) {
                $diff[] = array(array_shift($from), 2 /* REMOVED */);
            }

            while ((($toToken = reset($to)) !== $token)) {
                $diff[] = array(array_shift($to), 1 /* ADDED */);
            }

            $diff[] = array($token, 0 /* OLD */);

            array_shift($from);
            array_shift($to);
        }

        while (($token = array_shift($from)) !== NULL) {
            $diff[] = array($token, 2 /* REMOVED */);
        }

        while (($token = array_shift($to)) !== NULL) {
            $diff[] = array($token, 1 /* ADDED */);
        }

        foreach ($end as $token) {
            $diff[] = array($token, 0 /* OLD */);
        }

        return $diff;
    }

    /**
     * Calculates the longest common subsequence of two arrays.
     *
     * @param  array $from
     * @param  array $to
     * @return array
     */
    protected static function longestCommonSubsequence(array $from, array $to)
    {
        $common     = array();
        $matrix     = array();
        $fromLength = count($from);
        $toLength   = count($to);

        for ($i = 0; $i <= $fromLength; ++$i) {
            $matrix[$i][0] = 0;
        }

        for ($j = 0; $j <= $toLength; ++$j) {
            $matrix[0][$j] = 0;
        }

        for ($i = 1; $i <= $fromLength; ++$i) {
            for ($j = 1; $j <= $toLength; ++$j) {
                $matrix[$i][$j] = max(
                  $matrix[$i-1][$j],
                  $matrix[$i][$j-1],
                  $from[$i-1] === $to[$j-1] ? $matrix[$i-1][$j-1] + 1 : 0
                );
            }
        }

        $i = $fromLength;
        $j = $toLength;

        while ($i > 0 && $j > 0) {
            if ($from[$i-1] === $to[$j-1]) {
                array_unshift($common, $from[$i-1]);
                --$i;
                --$j;
            }

            else if ($matrix[$i][$j-1] > $matrix[$i-1][$j]) {
                --$j;
            }

            else {
                --$i;
            }
        }

        return $common;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.1.0
 */

/**
 * Class helpers.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.1.0
 */
class PHPUnit_Util_Class
{
    protected static $buffer = array();

    /**
     * Starts the collection of loaded classes.
     *
     */
    public static function collectStart()
    {
        self::$buffer = get_declared_classes();
    }

    /**
     * Stops the collection of loaded classes and
     * returns the names of the loaded classes.
     *
     * @return array
     */
    public static function collectEnd()
    {
        return array_values(
          array_diff(get_declared_classes(), self::$buffer)
        );
    }

    /**
     * Returns the class hierarchy for a given class.
     *
     * @param  string  $className
     * @param  boolean $asReflectionObjects
     * @return array
     */
    public static function getHierarchy($className, $asReflectionObjects = FALSE)
    {
        if ($asReflectionObjects) {
            $classes = array(new ReflectionClass($className));
        } else {
            $classes = array($className);
        }

        $done = FALSE;

        while (!$done) {
            if ($asReflectionObjects) {
                $class = new ReflectionClass(
                  $classes[count($classes)-1]->getName()
                );
            } else {
                $class = new ReflectionClass($classes[count($classes)-1]);
            }

            $parent = $class->getParentClass();

            if ($parent !== FALSE) {
                if ($asReflectionObjects) {
                    $classes[] = $parent;
                } else {
                    $classes[] = $parent->getName();
                }
            } else {
                $done = TRUE;
            }
        }

        return $classes;
    }

    /**
     * Returns the parameters of a function or method.
     *
     * @param  ReflectionFunction|ReflectionMethod $method
     * @param  boolean                             $forCall
     * @return string
     * @since  Method available since Release 3.2.0
     */
    public static function getMethodParameters($method, $forCall = FALSE)
    {
        $parameters = array();

        foreach ($method->getParameters() as $i => $parameter) {
            $name = '$' . $parameter->getName();

            /* Note: PHP extensions may use empty names for reference arguments
             * or "..." for methods taking a variable number of arguments.
             */
            if ($name === '$' || $name === '$...') {
                $name = '$arg' . $i;
            }

            $default   = '';
            $reference = '';
            $typeHint  = '';

            if (!$forCall) {
                if ($parameter->isArray()) {
                    $typeHint = 'array ';
                }

                else if (version_compare(PHP_VERSION, '5.4', '>') &&
                         $parameter->isCallable()) {
                    $typeHint = 'callable ';
                }

                else {
                    try {
                        $class = $parameter->getClass();
                    }

                    catch (ReflectionException $e) {
                        $class = FALSE;
                    }

                    if ($class) {
                        $typeHint = $class->getName() . ' ';
                    }
                }

                if ($parameter->isDefaultValueAvailable()) {
                    $value   = $parameter->getDefaultValue();
                    $default = ' = ' . var_export($value, TRUE);
                }

                else if ($parameter->isOptional()) {
                    $default = ' = null';
                }
            }

            if ($parameter->isPassedByReference()) {
                $reference = '&';
            }

            $parameters[] = $typeHint . $reference . $name . $default;
        }

        return join(', ', $parameters);
    }

    /**
     * Returns the package information of a user-defined class.
     *
     * @param  string $className
     * @param  string $docComment
     * @return array
     */
    public static function getPackageInformation($className, $docComment)
    {
        $result = array(
          'namespace'   => '',
          'fullPackage' => '',
          'category'    => '',
          'package'     => '',
          'subpackage'  => ''
        );

        if (strpos($className, '\\') !== FALSE) {
            $result['namespace'] = self::arrayToName(
              explode('\\', $className)
            );
        }

        if (preg_match('/@category[\s]+([\.\w]+)/', $docComment, $matches)) {
            $result['category'] = $matches[1];
        }

        if (preg_match('/@package[\s]+([\.\w]+)/', $docComment, $matches)) {
            $result['package']     = $matches[1];
            $result['fullPackage'] = $matches[1];
        }

        if (preg_match('/@subpackage[\s]+([\.\w]+)/', $docComment, $matches)) {
            $result['subpackage']   = $matches[1];
            $result['fullPackage'] .= '.' . $matches[1];
        }

        if (empty($result['fullPackage'])) {
            $result['fullPackage'] = self::arrayToName(
              explode('_', str_replace('\\', '_', $className)), '.'
            );
        }

        return $result;
    }

    /**
     * Returns the value of a static attribute.
     * This also works for attributes that are declared protected or private.
     *
     * @param  string  $className
     * @param  string  $attributeName
     * @return mixed
     * @throws PHPUnit_Framework_Exception
     * @since  Method available since Release 3.4.0
     */
    public static function getStaticAttribute($className, $attributeName)
    {
        if (!is_string($className)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        if (!class_exists($className)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'class name');
        }

        if (!is_string($attributeName)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string');
        }

        $class = new ReflectionClass($className);

        while ($class) {
            $attributes = $class->getStaticProperties();

            if (array_key_exists($attributeName, $attributes)) {
                return $attributes[$attributeName];
            }

            $class = $class->getParentClass();
        }

        throw new PHPUnit_Framework_Exception(
          sprintf(
            'Attribute "%s" not found in class.',

            $attributeName
          )
        );
    }

    /**
     * Returns the value of an object's attribute.
     * This also works for attributes that are declared protected or private.
     *
     * @param  object  $object
     * @param  string  $attributeName
     * @return mixed
     * @throws PHPUnit_Framework_Exception
     * @since  Method available since Release 3.4.0
     */
    public static function getObjectAttribute($object, $attributeName)
    {
        if (!is_object($object)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'object');
        }

        if (!is_string($attributeName)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string');
        }

        try {
            $attribute = new ReflectionProperty($object, $attributeName);
        }

        catch (ReflectionException $e) {
            $reflector = new ReflectionObject($object);

            while ($reflector = $reflector->getParentClass()) {
                try {
                    $attribute = $reflector->getProperty($attributeName);
                    break;
                }

                catch(ReflectionException $e) {
                }
            }
        }

        if (isset($attribute)) {
            if (!$attribute || $attribute->isPublic()) {
                return $object->$attributeName;
            }
            $attribute->setAccessible(TRUE);
            $value = $attribute->getValue($object);
            $attribute->setAccessible(FALSE);

            return $value;
        }

        throw new PHPUnit_Framework_Exception(
          sprintf(
            'Attribute "%s" not found in object.',
            $attributeName
          )
        );
    }

    /**
     * Returns the package information of a user-defined class.
     *
     * @param  array  $parts
     * @param  string $join
     * @return string
     * @since  Method available since Release 3.2.12
     */
    protected static function arrayToName(array $parts, $join = '\\')
    {
        $result = '';

        if (count($parts) > 1) {
            array_pop($parts);

            $result = join($join, $parts);
        }

        return $result;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * Utility class for textual type (and value) representation.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class PHPUnit_Util_Type
{
    public static function isType($type)
    {
        return in_array(
          $type,
          array(
            'numeric',
            'integer',
            'int',
            'float',
            'string',
            'boolean',
            'bool',
            'null',
            'array',
            'object',
            'resource',
            'scalar'
          )
        );
    }

    /**
     * Exports a value into a string
     *
     * The output of this method is similar to the output of print_r(), but
     * improved in various aspects:
     *
     *  - NULL is rendered as "null" (instead of "")
     *  - TRUE is rendered as "true" (instead of "1")
     *  - FALSE is rendered as "false" (instead of "")
     *  - Strings are always quoted with single quotes
     *  - Carriage returns and newlines are normalized to \n
     *  - Recursion and repeated rendering is treated properly
     *
     * @param  mixed $value The value to export
     * @param  integer $indentation The indentation level of the 2nd+ line
     * @return string
     * @since  Method available since Release 3.6.0
     */
    public static function export($value, $indentation = 0)
    {
        return self::recursiveExport($value, $indentation);
    }

    /**
     * Recursive implementation of export
     *
     * @param  mixed $value The value to export
     * @param  integer $indentation The indentation level of the 2nd+ line
     * @param  array $processedObjects Contains all objects that were already
     *                                 rendered
     * @return string
     * @since  Method available since Release 3.6.0
     * @see    PHPUnit_Util_Type::export
     */
    protected static function recursiveExport($value, $indentation, &$processedObjects = array())
    {
        if ($value === NULL) {
            return 'null';
        }

        if ($value === TRUE) {
            return 'true';
        }

        if ($value === FALSE) {
            return 'false';
        }

        if (is_string($value)) {
            // Match for most non printable chars somewhat taking multibyte chars into account
            if (preg_match('/[^\x09-\x0d\x20-\xff]/', $value)) {
                return 'Binary String: 0x' . bin2hex($value);
            }

            return "'" .
                   str_replace(array("\r\n", "\n\r", "\r"), array("\n", "\n", "\n"), $value) .
                   "'";
        }

        $origValue = $value;

        if (is_object($value)) {
            if (in_array($value, $processedObjects, TRUE)) {
                return sprintf(
                  '%s Object (*RECURSION*)',

                  get_class($value)
                );
            }

            $processedObjects[] = $value;

            // Convert object to array
            $value = self::toArray($value);
        }

        if (is_array($value)) {
            $whitespace = str_repeat('    ', $indentation);

            // There seems to be no other way to check arrays for recursion
            // http://www.php.net/manual/en/language.types.array.php#73936
            preg_match_all('/\n            \[(\w+)\] => Array\s+\*RECURSION\*/', print_r($value, TRUE), $matches);
            $recursiveKeys = array_unique($matches[1]);

            // Convert to valid array keys
            // Numeric integer strings are automatically converted to integers
            // by PHP
            foreach ($recursiveKeys as $key => $recursiveKey) {
                if ((string)(integer)$recursiveKey === $recursiveKey) {
                    $recursiveKeys[$key] = (integer)$recursiveKey;
                }
            }

            $content = '';

            foreach ($value as $key => $val) {
                if (in_array($key, $recursiveKeys, TRUE)) {
                    $val = 'Array (*RECURSION*)';
                }

                else {
                    $val = self::recursiveExport($val, $indentation+1, $processedObjects);
                }

                $content .=  $whitespace . '    ' . self::export($key) . ' => ' . $val . "\n";
            }

            if (strlen($content) > 0) {
                $content = "\n" . $content . $whitespace;
            }

            return sprintf(
              "%s (%s)",

              is_object($origValue) ? get_class($origValue) . ' Object' : 'Array',
              $content
            );
        }

        if (is_double($value) && (double)(integer)$value === $value) {
            return $value . '.0';
        }

        return (string)$value;
    }

    /**
     * Exports a value into a single-line string
     *
     * The output of this method is similar to the output of
     * PHPUnit_Util_Type::export. This method guarantees thought that the
     * result contains now newlines.
     *
     * Newlines are replaced by the visible string '\n'. Contents of arrays
     * and objects (if any) are replaced by '...'.
     *
     * @param  mixed $value The value to export
     * @param  integer $indentation The indentation level of the 2nd+ line
     * @return string
     * @see    PHPUnit_Util_Type::export
     */
    public static function shortenedExport($value)
    {
        if (is_string($value)) {
            return self::shortenedString($value);
        }

        if (is_object($value)) {
            return sprintf(
              '%s Object (%s)',
              get_class($value),
              count(self::toArray($value)) > 0 ? '...' : ''
            );
        }

        if (is_array($value)) {
            return sprintf(
              'Array (%s)',
              count($value) > 0 ? '...' : ''
            );
        }

        return self::export($value);
    }

    /**
     * Shortens a string and converts all new lines to '\n'
     *
     * @param  string $string The string to shorten
     * @param  integer $max The maximum length for the string
     * @return string
     */
    public static function shortenedString($string, $maxLength = 40)
    {
        $string = self::export($string);

        if (strlen($string) > $maxLength) {
            $string = substr($string, 0, $maxLength - 10) . '...' . substr($string, -7);
        }

        return str_replace("\n", '\n', $string);
    }

    /**
     * Converts an object to an array containing all of its private, protected
     * and public properties.
     *
     * @param  object $object
     * @return array
     * @since  Method available since Release 3.6.0
     */
    public static function toArray($object)
    {
        $array = array();

        foreach ((array)$object as $key => $value) {
            // properties are transformed to keys in the following way:

            // private   $property => "\0Classname\0property"
            // protected $property => "\0*\0property"
            // public    $property => "property"

            if (preg_match('/^\0.+\0(.+)$/', $key, $matches)) {
                $key = $matches[1];
            }

            $array[$key] = $value;
        }

        // Some internal classes like SplObjectStorage don't work with the
        // above (fast) mechanism nor with reflection
        // Format the output similarly to print_r() in this case
        if ($object instanceof SplObjectStorage) {
            foreach ($object as $key => $value) {
                $array[spl_object_hash($value)] = array(
                    'obj' => $value,
                    'inf' => $object->getInfo(),
                );
            }
        }

        return $array;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.2.0
 */

/**
 * Wrapper for the PHPUnit XML configuration file.
 *
 * Example XML configuration file:
 * <code>
 * <?xml version="1.0" encoding="utf-8" ?>
 *
 * <phpunit backupGlobals="true"
 *          backupStaticAttributes="false"
 *          bootstrap="/path/to/bootstrap.php"
 *          cacheTokens="false"
 *          colors="false"
 *          convertErrorsToExceptions="true"
 *          convertNoticesToExceptions="true"
 *          convertWarningsToExceptions="true"
 *          forceCoversAnnotation="false"
 *          mapTestClassNameToCoveredClassName="false"
 *          printerClass="PHPUnit_TextUI_ResultPrinter"
 *          processIsolation="false"
 *          stopOnError="false"
 *          stopOnFailure="false"
 *          stopOnIncomplete="false"
 *          stopOnSkipped="false"
 *          testSuiteLoaderClass="PHPUnit_Runner_StandardTestSuiteLoader"
 *          timeoutForSmallTests="1"
 *          timeoutForMediumTests="10"
 *          timeoutForLargeTests="60"
 *          strict="false"
 *          verbose="false">
 *   <testsuites>
 *     <testsuite name="My Test Suite">
 *       <directory suffix="Test.php" phpVersion="5.3.0" phpVersionOperator=">=">/path/to/files</directory>
 *       <file phpVersion="5.3.0" phpVersionOperator=">=">/path/to/MyTest.php</file>
 *       <exclude>/path/to/files/exclude</exclude>
 *     </testsuite>
 *   </testsuites>
 *
 *   <groups>
 *     <include>
 *       <group>name</group>
 *     </include>
 *     <exclude>
 *       <group>name</group>
 *     </exclude>
 *   </groups>
 *
 *   <filter>
 *     <blacklist>
 *       <directory suffix=".php">/path/to/files</directory>
 *       <file>/path/to/file</file>
 *       <exclude>
 *         <directory suffix=".php">/path/to/files</directory>
 *         <file>/path/to/file</file>
 *       </exclude>
 *     </blacklist>
 *     <whitelist addUncoveredFilesFromWhitelist="true"
 *                processUncoveredFilesFromWhitelist="false">
 *       <directory suffix=".php">/path/to/files</directory>
 *       <file>/path/to/file</file>
 *       <exclude>
 *         <directory suffix=".php">/path/to/files</directory>
 *         <file>/path/to/file</file>
 *       </exclude>
 *     </whitelist>
 *   </filter>
 *
 *   <listeners>
 *     <listener class="MyListener" file="/optional/path/to/MyListener.php">
 *       <arguments>
 *         <array>
 *           <element key="0">
 *             <string>Sebastian</string>
 *           </element>
 *         </array>
 *         <integer>22</integer>
 *         <string>April</string>
 *         <double>19.78</double>
 *         <null/>
 *         <object class="stdClass"/>
 *         <file>MyRelativeFile.php</file>
 *         <directory>MyRelativeDir</directory>
 *       </arguments>
 *     </listener>
 *   </listeners>
 *
 *   <logging>
 *     <log type="coverage-html" target="/tmp/report"
            charset="UTF-8" highlight="false"
 *          lowUpperBound="35" highLowerBound="70"/>
 *     <log type="coverage-clover" target="/tmp/clover.xml"/>
 *     <log type="json" target="/tmp/logfile.json"/>
 *     <log type="plain" target="/tmp/logfile.txt"/>
 *     <log type="tap" target="/tmp/logfile.tap"/>
 *     <log type="junit" target="/tmp/logfile.xml" logIncompleteSkipped="false"/>
 *     <log type="testdox-html" target="/tmp/testdox.html"/>
 *     <log type="testdox-text" target="/tmp/testdox.txt"/>
 *   </logging>
 *
 *   <php>
 *     <includePath>.</includePath>
 *     <ini name="foo" value="bar"/>
 *     <const name="foo" value="bar"/>
 *     <var name="foo" value="bar"/>
 *     <env name="foo" value="bar"/>
 *     <post name="foo" value="bar"/>
 *     <get name="foo" value="bar"/>
 *     <cookie name="foo" value="bar"/>
 *     <server name="foo" value="bar"/>
 *     <files name="foo" value="bar"/>
 *     <request name="foo" value="bar"/>
 *   </php>
 *
 *   <selenium>
 *     <browser name="Firefox on Linux"
 *              browser="*firefox /usr/lib/firefox/firefox-bin"
 *              host="my.linux.box"
 *              port="4444"
 *              timeout="30000"/>
 *   </selenium>
 * </phpunit>
 * </code>
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.2.0
 */
class PHPUnit_Util_Configuration
{
    private static $instances = array();

    protected $document;
    protected $xpath;
    protected $filename;

    /**
     * Loads a PHPUnit configuration file.
     *
     * @param  string $filename
     */
    protected function __construct($filename)
    {
        $this->filename = $filename;
        $this->document = PHPUnit_Util_XML::loadFile($filename, FALSE, TRUE);
        $this->xpath    = new DOMXPath($this->document);
    }

    /**
     * @since  Method available since Release 3.4.0
     */
    private final function __clone()
    {
    }

    /**
     * Returns a PHPUnit configuration object.
     *
     * @param  string $filename
     * @return PHPUnit_Util_Configuration
     * @since  Method available since Release 3.4.0
     */
    public static function getInstance($filename)
    {
        $realpath = realpath($filename);

        if ($realpath === FALSE) {
            throw new PHPUnit_Framework_Exception(
              sprintf(
                'Could not read "%s".',
                $filename
              )
            );
        }

        if (!isset(self::$instances[$realpath])) {
            self::$instances[$realpath] = new PHPUnit_Util_Configuration($realpath);
        }

        return self::$instances[$realpath];
    }

    /**
     * Returns the realpath to the configuration file.
     *
     * @return string
     * @since  Method available since Release 3.6.0
     */
    public function getFilename()
    {
        return $this->filename;
    }

    /**
     * Returns the configuration for SUT filtering.
     *
     * @return array
     * @since  Method available since Release 3.2.1
     */
    public function getFilterConfiguration()
    {
        $addUncoveredFilesFromWhitelist     = TRUE;
        $processUncoveredFilesFromWhitelist = FALSE;

        $tmp = $this->xpath->query('filter/whitelist');

        if ($tmp->length == 1) {
            if ($tmp->item(0)->hasAttribute('addUncoveredFilesFromWhitelist')) {
                $addUncoveredFilesFromWhitelist = $this->getBoolean(
                  (string)$tmp->item(0)->getAttribute(
                    'addUncoveredFilesFromWhitelist'
                  ),
                  TRUE
                );
            }

            if ($tmp->item(0)->hasAttribute('processUncoveredFilesFromWhitelist')) {
                $processUncoveredFilesFromWhitelist = $this->getBoolean(
                  (string)$tmp->item(0)->getAttribute(
                    'processUncoveredFilesFromWhitelist'
                  ),
                  FALSE
                );
            }
        }

        return array(
          'blacklist' => array(
            'include' => array(
              'directory' => $this->readFilterDirectories(
                'filter/blacklist/directory'
              ),
              'file' => $this->readFilterFiles(
                'filter/blacklist/file'
              )
            ),
            'exclude' => array(
              'directory' => $this->readFilterDirectories(
                'filter/blacklist/exclude/directory'
               ),
              'file' => $this->readFilterFiles(
                'filter/blacklist/exclude/file'
              )
            )
          ),
          'whitelist' => array(
            'addUncoveredFilesFromWhitelist' => $addUncoveredFilesFromWhitelist,
            'processUncoveredFilesFromWhitelist' => $processUncoveredFilesFromWhitelist,
            'include' => array(
              'directory' => $this->readFilterDirectories(
                'filter/whitelist/directory'
              ),
              'file' => $this->readFilterFiles(
                'filter/whitelist/file'
              )
            ),
            'exclude' => array(
              'directory' => $this->readFilterDirectories(
                'filter/whitelist/exclude/directory'
              ),
              'file' => $this->readFilterFiles(
                'filter/whitelist/exclude/file'
              )
            )
          )
        );
    }

    /**
     * Returns the configuration for groups.
     *
     * @return array
     * @since  Method available since Release 3.2.1
     */
    public function getGroupConfiguration()
    {
        $groups = array(
          'include' => array(),
          'exclude' => array()
        );

        foreach ($this->xpath->query('groups/include/group') as $group) {
            $groups['include'][] = (string)$group->nodeValue;
        }

        foreach ($this->xpath->query('groups/exclude/group') as $group) {
            $groups['exclude'][] = (string)$group->nodeValue;
        }

        return $groups;
    }

    /**
     * Returns the configuration for listeners.
     *
     * @return array
     * @since  Method available since Release 3.4.0
     */
    public function getListenerConfiguration()
    {
        $result = array();

        foreach ($this->xpath->query('listeners/listener') as $listener) {
            $class     = (string)$listener->getAttribute('class');
            $file      = '';
            $arguments = array();

            if ($listener->hasAttribute('file')) {
                $file = $this->toAbsolutePath(
                  (string)$listener->getAttribute('file'), TRUE
                );
            }

            foreach ($listener->childNodes as $node) {
              if ($node instanceof DOMElement && $node->tagName == 'arguments') {
                foreach ($node->childNodes as $argument) {
                    if ($argument instanceof DOMElement) {
                        if ($argument->tagName == 'file' ||
                            $argument->tagName == 'directory') {
                            $arguments[] = $this->toAbsolutePath((string)$argument->nodeValue);
                        } else {
                            $arguments[] = PHPUnit_Util_XML::xmlToVariable($argument);
                        }
                    }
                }
              }
            }

            $result[] = array(
              'class'     => $class,
              'file'      => $file,
              'arguments' => $arguments
            );
        }

        return $result;
    }

    /**
     * Returns the logging configuration.
     *
     * @return array
     */
    public function getLoggingConfiguration()
    {
        $result = array();

        foreach ($this->xpath->query('logging/log') as $log) {
            $type = (string)$log->getAttribute('type');

            $target = $this->toAbsolutePath(
              (string)$log->getAttribute('target')
            );

            if ($type == 'coverage-html') {
                if ($log->hasAttribute('title')) {
                    $result['title'] = (string)$log->getAttribute('title');
                }

                if ($log->hasAttribute('charset')) {
                    $result['charset'] = (string)$log->getAttribute('charset');
                }

                if ($log->hasAttribute('lowUpperBound')) {
                    $result['lowUpperBound'] = (string)$log->getAttribute('lowUpperBound');
                }

                if ($log->hasAttribute('highLowerBound')) {
                    $result['highLowerBound'] = (string)$log->getAttribute('highLowerBound');
                }

                if ($log->hasAttribute('highlight')) {
                    $result['highlight'] = $this->getBoolean(
                      (string)$log->getAttribute('highlight'),
                      FALSE
                    );
                }
            }

            else if ($type == 'junit') {
                if ($log->hasAttribute('logIncompleteSkipped')) {
                    $result['logIncompleteSkipped'] = $this->getBoolean(
                      (string)$log->getAttribute('logIncompleteSkipped'),
                      FALSE
                    );
                }
            }

            else if ($type == 'coverage-text') {
                if ($log->hasAttribute('showUncoveredFiles')) {
                    $result['coverageTextShowUncoveredFiles'] = $this->getBoolean(
                      (string)$log->getAttribute('showUncoveredFiles'),
                      FALSE
                    );
                }
            }

            $result[$type] = $target;
        }

        return $result;
    }

    /**
     * Returns the PHP configuration.
     *
     * @return array
     * @since  Method available since Release 3.2.1
     */
    public function getPHPConfiguration()
    {
        $result = array(
          'include_path' => array(),
          'ini'          => array(),
          'const'        => array(),
          'var'          => array(),
          'env'          => array(),
          'post'         => array(),
          'get'          => array(),
          'cookie'       => array(),
          'server'       => array(),
          'files'        => array(),
          'request'      => array()
        );

        foreach ($this->xpath->query('php/includePath') as $includePath) {
            $path = (string)$includePath->nodeValue;

            $result['include_path'][] = $this->toAbsolutePath($path);
        }

        foreach ($this->xpath->query('php/ini') as $ini) {
            $name  = (string)$ini->getAttribute('name');
            $value = (string)$ini->getAttribute('value');

            $result['ini'][$name] = $value;
        }

        foreach ($this->xpath->query('php/const') as $const) {
            $name  = (string)$const->getAttribute('name');
            $value = (string)$const->getAttribute('value');

            $result['const'][$name] = $this->getBoolean($value, $value);
        }

        foreach (array('var', 'env', 'post', 'get', 'cookie', 'server', 'files', 'request') as $array) {
            foreach ($this->xpath->query('php/' . $array) as $var) {
                $name  = (string)$var->getAttribute('name');
                $value = (string)$var->getAttribute('value');

                $result[$array][$name] = $this->getBoolean($value, $value);
            }
        }

        return $result;
    }

    /**
     * Handles the PHP configuration.
     *
     * @since  Method available since Release 3.2.20
     */
    public function handlePHPConfiguration()
    {
        $configuration = $this->getPHPConfiguration();

        if (! empty($configuration['include_path'])) {
            ini_set(
              'include_path',
              implode(PATH_SEPARATOR, $configuration['include_path']) .
              PATH_SEPARATOR .
              ini_get('include_path')
            );
        }

        foreach ($configuration['ini'] as $name => $value) {
            if (defined($value)) {
                $value = constant($value);
            }

            ini_set($name, $value);
        }

        foreach ($configuration['const'] as $name => $value) {
            if (!defined($name)) {
                define($name, $value);
            }
        }

        foreach (array('var', 'env', 'post', 'get', 'cookie', 'server', 'files', 'request') as $array) {
            // See https://github.com/sebastianbergmann/phpunit/issues/277
            switch ($array) {
                case 'var':
                    $target = &$GLOBALS;
                    break;

                case 'env':
                    $target = &$_ENV;
                    break;

                case 'server':
                    $target = &$_SERVER;
                    break;

                default:
                    $target = &$GLOBALS['_' . strtoupper($array)];
                    break;
            }

            foreach ($configuration[$array] as $name => $value) {
                $target[$name] = $value;
            }
        }

        foreach ($configuration['env'] as $name => $value) {
            putenv("$name=$value");
        }
    }

    /**
     * Returns the PHPUnit configuration.
     *
     * @return array
     * @since  Method available since Release 3.2.14
     */
    public function getPHPUnitConfiguration()
    {
        $result = array();
        $root   = $this->document->documentElement;

        if ($root->hasAttribute('cacheTokens')) {
            $result['cacheTokens'] = $this->getBoolean(
              (string)$root->getAttribute('cacheTokens'), FALSE
            );
        }

        if ($root->hasAttribute('colors')) {
            $result['colors'] = $this->getBoolean(
              (string)$root->getAttribute('colors'), FALSE
            );
        }

        if ($root->hasAttribute('backupGlobals')) {
            $result['backupGlobals'] = $this->getBoolean(
              (string)$root->getAttribute('backupGlobals'), TRUE
            );
        }

        if ($root->hasAttribute('backupStaticAttributes')) {
            $result['backupStaticAttributes'] = $this->getBoolean(
              (string)$root->getAttribute('backupStaticAttributes'), FALSE
            );
        }

        if ($root->hasAttribute('bootstrap')) {
            $result['bootstrap'] = $this->toAbsolutePath(
              (string)$root->getAttribute('bootstrap')
            );
        }

        if ($root->hasAttribute('convertErrorsToExceptions')) {
            $result['convertErrorsToExceptions'] = $this->getBoolean(
              (string)$root->getAttribute('convertErrorsToExceptions'), TRUE
            );
        }

        if ($root->hasAttribute('convertNoticesToExceptions')) {
            $result['convertNoticesToExceptions'] = $this->getBoolean(
              (string)$root->getAttribute('convertNoticesToExceptions'), TRUE
            );
        }

        if ($root->hasAttribute('convertWarningsToExceptions')) {
            $result['convertWarningsToExceptions'] = $this->getBoolean(
              (string)$root->getAttribute('convertWarningsToExceptions'), TRUE
            );
        }

        if ($root->hasAttribute('forceCoversAnnotation')) {
            $result['forceCoversAnnotation'] = $this->getBoolean(
              (string)$root->getAttribute('forceCoversAnnotation'), FALSE
            );
        }

        if ($root->hasAttribute('mapTestClassNameToCoveredClassName')) {
            $result['mapTestClassNameToCoveredClassName'] = $this->getBoolean(
              (string)$root->getAttribute('mapTestClassNameToCoveredClassName'),
              FALSE
            );
        }

        if ($root->hasAttribute('processIsolation')) {
            $result['processIsolation'] = $this->getBoolean(
              (string)$root->getAttribute('processIsolation'), FALSE
            );
        }

        if ($root->hasAttribute('stopOnError')) {
            $result['stopOnError'] = $this->getBoolean(
              (string)$root->getAttribute('stopOnError'), FALSE
            );
        }

        if ($root->hasAttribute('stopOnFailure')) {
            $result['stopOnFailure'] = $this->getBoolean(
              (string)$root->getAttribute('stopOnFailure'), FALSE
            );
        }

        if ($root->hasAttribute('stopOnIncomplete')) {
            $result['stopOnIncomplete'] = $this->getBoolean(
              (string)$root->getAttribute('stopOnIncomplete'), FALSE
            );
        }

        if ($root->hasAttribute('stopOnSkipped')) {
            $result['stopOnSkipped'] = $this->getBoolean(
              (string)$root->getAttribute('stopOnSkipped'), FALSE
            );
        }

        if ($root->hasAttribute('testSuiteLoaderClass')) {
            $result['testSuiteLoaderClass'] = (string)$root->getAttribute(
              'testSuiteLoaderClass'
            );
        }

        if ($root->hasAttribute('testSuiteLoaderFile')) {
            $result['testSuiteLoaderFile'] = (string)$root->getAttribute(
              'testSuiteLoaderFile'
            );
        }

        if ($root->hasAttribute('printerClass')) {
            $result['printerClass'] = (string)$root->getAttribute(
              'printerClass'
            );
        }

        if ($root->hasAttribute('printerFile')) {
            $result['printerFile'] = (string)$root->getAttribute(
              'printerFile'
            );
        }

        if ($root->hasAttribute('timeoutForSmallTests')) {
            $result['timeoutForSmallTests'] = $this->getInteger(
              (string)$root->getAttribute('timeoutForSmallTests'), 1
            );
        }

        if ($root->hasAttribute('timeoutForMediumTests')) {
            $result['timeoutForMediumTests'] = $this->getInteger(
              (string)$root->getAttribute('timeoutForMediumTests'), 10
            );
        }

        if ($root->hasAttribute('timeoutForLargeTests')) {
            $result['timeoutForLargeTests'] = $this->getInteger(
              (string)$root->getAttribute('timeoutForLargeTests'), 60
            );
        }

        if ($root->hasAttribute('strict')) {
            $result['strict'] = $this->getBoolean(
              (string)$root->getAttribute('strict'), FALSE
            );
        }

        if ($root->hasAttribute('verbose')) {
            $result['verbose'] = $this->getBoolean(
              (string)$root->getAttribute('verbose'), FALSE
            );
        }

        return $result;
    }

    /**
     * Returns the SeleniumTestCase browser configuration.
     *
     * @return array
     * @since  Method available since Release 3.2.9
     */
    public function getSeleniumBrowserConfiguration()
    {
        $result = array();

        foreach ($this->xpath->query('selenium/browser') as $config) {
            $name    = (string)$config->getAttribute('name');
            $browser = (string)$config->getAttribute('browser');

            if ($config->hasAttribute('host')) {
                $host = (string)$config->getAttribute('host');
            } else {
                $host = 'localhost';
            }

            if ($config->hasAttribute('port')) {
                $port = $this->getInteger(
                  (string)$config->getAttribute('port'), 4444
                );
            } else {
                $port = 4444;
            }

            if ($config->hasAttribute('timeout')) {
                $timeout = $this->getInteger(
                  (string)$config->getAttribute('timeout'), 30000
                );
            } else {
                $timeout = 30000;
            }

            $result[] = array(
              'name'    => $name,
              'browser' => $browser,
              'host'    => $host,
              'port'    => $port,
              'timeout' => $timeout
            );
        }

        return $result;
    }

    /**
     * Returns the test suite configuration.
     *
     * @return PHPUnit_Framework_TestSuite
     * @since  Method available since Release 3.2.1
     */
    public function getTestSuiteConfiguration($testSuiteFilter=null)
    {
        $testSuiteNodes = $this->xpath->query('testsuites/testsuite');

        if ($testSuiteNodes->length == 0) {
            $testSuiteNodes = $this->xpath->query('testsuite');
        }

        if ($testSuiteNodes->length == 1) {
            return $this->getTestSuite($testSuiteNodes->item(0), $testSuiteFilter);
        }

        if ($testSuiteNodes->length > 1) {
            $suite = new PHPUnit_Framework_TestSuite;

            foreach ($testSuiteNodes as $testSuiteNode) {
                $suite->addTestSuite(
                  $this->getTestSuite($testSuiteNode, $testSuiteFilter)
                );
            }

            return $suite;
        }
    }

    /**
     * @param  DOMElement $testSuiteNode
     * @return PHPUnit_Framework_TestSuite
     * @since  Method available since Release 3.4.0
     */
    protected function getTestSuite(DOMElement $testSuiteNode, $testSuiteFilter=null)
    {
        if ($testSuiteNode->hasAttribute('name')) {
            $suite = new PHPUnit_Framework_TestSuite(
              (string)$testSuiteNode->getAttribute('name')
            );
        } else {
            $suite = new PHPUnit_Framework_TestSuite;
        }

        $exclude = array();

        foreach ($testSuiteNode->getElementsByTagName('exclude') as $excludeNode) {
            $exclude[] = (string)$excludeNode->nodeValue;
        }

        $fileIteratorFacade = new File_Iterator_Facade;

        foreach ($testSuiteNode->getElementsByTagName('directory') as $directoryNode) {
            if ($testSuiteFilter && $directoryNode->parentNode->getAttribute('name') != $testSuiteFilter) {
                continue;
            }

            $directory = (string)$directoryNode->nodeValue;

            if (empty($directory)) {
                continue;
            }

            if ($directoryNode->hasAttribute('phpVersion')) {
                $phpVersion = (string)$directoryNode->getAttribute('phpVersion');
            } else {
                $phpVersion = PHP_VERSION;
            }

            if ($directoryNode->hasAttribute('phpVersionOperator')) {
                $phpVersionOperator = (string)$directoryNode->getAttribute('phpVersionOperator');
            } else {
                $phpVersionOperator = '>=';
            }

            if (!version_compare(PHP_VERSION, $phpVersion, $phpVersionOperator)) {
                continue;
            }

            if ($directoryNode->hasAttribute('prefix')) {
                $prefix = (string)$directoryNode->getAttribute('prefix');
            } else {
                $prefix = '';
            }

            if ($directoryNode->hasAttribute('suffix')) {
                $suffix = (string)$directoryNode->getAttribute('suffix');
            } else {
                $suffix = 'Test.php';
            }

            $files = $fileIteratorFacade->getFilesAsArray(
              $this->toAbsolutePath($directory),
              $suffix,
              $prefix,
              $exclude
            );
            $suite->addTestFiles($files);
        }

        foreach ($testSuiteNode->getElementsByTagName('file') as $fileNode) {
            if ($testSuiteFilter && $fileNode->parentNode->getAttribute('name') != $testSuiteFilter) {
                continue;
            }

            $file = (string)$fileNode->nodeValue;

            if (empty($file)) {
                continue;
            }

            // Get the absolute path to the file
            $file = $fileIteratorFacade->getFilesAsArray($file);

            if (!isset($file[0])) {
                continue;
            }

            $file = $file[0];

            if ($fileNode->hasAttribute('phpVersion')) {
                $phpVersion = (string)$fileNode->getAttribute('phpVersion');
            } else {
                $phpVersion = PHP_VERSION;
            }

            if ($fileNode->hasAttribute('phpVersionOperator')) {
                $phpVersionOperator = (string)$fileNode->getAttribute('phpVersionOperator');
            } else {
                $phpVersionOperator = '>=';
            }

            if (!version_compare(PHP_VERSION, $phpVersion, $phpVersionOperator)) {
                continue;
            }

            $suite->addTestFile($file);
        }

        return $suite;
    }

    /**
     * @param  string  $value
     * @param  boolean $default
     * @return boolean
     * @since  Method available since Release 3.2.3
     */
    protected function getBoolean($value, $default)
    {
        if (strtolower($value) == 'false') {
            return FALSE;
        }

        else if (strtolower($value) == 'true') {
            return TRUE;
        }

        return $default;
    }

    /**
     * @param  string  $value
     * @param  boolean $default
     * @return boolean
     * @since  Method available since Release 3.6.0
     */
    protected function getInteger($value, $default)
    {
        if (is_numeric($value)) {
            return (int)$value;
        }

        return $default;
    }

    /**
     * @param  string $query
     * @return array
     * @since  Method available since Release 3.2.3
     */
    protected function readFilterDirectories($query)
    {
        $directories = array();

        foreach ($this->xpath->query($query) as $directory) {
            if ($directory->hasAttribute('prefix')) {
                $prefix = (string)$directory->getAttribute('prefix');
            } else {
                $prefix = '';
            }

            if ($directory->hasAttribute('suffix')) {
                $suffix = (string)$directory->getAttribute('suffix');
            } else {
                $suffix = '.php';
            }

            if ($directory->hasAttribute('group')) {
                $group = (string)$directory->getAttribute('group');
            } else {
                $group = 'DEFAULT';
            }

            $directories[] = array(
              'path'   => $this->toAbsolutePath((string)$directory->nodeValue),
              'prefix' => $prefix,
              'suffix' => $suffix,
              'group'  => $group
            );
        }

        return $directories;
    }

    /**
     * @param  string $query
     * @return array
     * @since  Method available since Release 3.2.3
     */
    protected function readFilterFiles($query)
    {
        $files = array();

        foreach ($this->xpath->query($query) as $file) {
            $files[] = $this->toAbsolutePath((string)$file->nodeValue);
        }

        return $files;
    }

    /**
     * @param  string  $path
     * @param  boolean $useIncludePath
     * @return string
     * @since  Method available since Release 3.5.0
     */
    protected function toAbsolutePath($path, $useIncludePath = FALSE)
    {
        // Check whether the path is already absolute.
        if ($path[0] === '/' || $path[0] === '\\' ||
            (strlen($path) > 3 && ctype_alpha($path[0]) &&
             $path[1] === ':' && ($path[2] === '\\' || $path[2] === '/'))) {
            return $path;
        }

        // Check whether a stream is used.
        if (strpos($path, '://') !== FALSE) {
            return $path;
        }

        $file = dirname($this->filename) . DIRECTORY_SEPARATOR . $path;

        if ($useIncludePath && !file_exists($file)) {
            $includePathFile = stream_resolve_include_path($path);

            if ($includePathFile) {
                $file = $includePathFile;
            }
        }

        return $file;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

/**
 * Utility class for code filtering.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.0.0
 */
class PHPUnit_Util_Filter
{
    /**
     * Filters stack frames from PHPUnit classes.
     *
     * @param  Exception $e
     * @param  boolean   $asString
     * @return string
     */
    public static function getFilteredStacktrace(Exception $e, $asString = TRUE)
    {
        $prefix = FALSE;
        $script = realpath($GLOBALS['_SERVER']['SCRIPT_NAME']);

        if (defined('__PHPUNIT_PHAR__')) {
            $prefix = 'phar://' . __PHPUNIT_PHAR__ . '/';
        }

        if (!defined('PHPUNIT_TESTSUITE')) {
            $blacklist = PHPUnit_Util_GlobalState::phpunitFiles();
        } else {
            $blacklist = array();
        }

        if ($asString === TRUE) {
            $filteredStacktrace = '';
        } else {
            $filteredStacktrace = array();
        }

        if ($e instanceof PHPUnit_Framework_SyntheticError) {
            $eTrace = $e->getSyntheticTrace();
            $eFile  = $e->getSyntheticFile();
            $eLine  = $e->getSyntheticLine();
        } else {
            if ($e->getPrevious()) {
                $eTrace = $e->getPrevious()->getTrace();
            } else {
                $eTrace = $e->getTrace();
            }
            $eFile  = $e->getFile();
            $eLine  = $e->getLine();
        }

        if (!self::frameExists($eTrace, $eFile, $eLine)) {
            array_unshift(
              $eTrace, array('file' => $eFile, 'line' => $eLine)
            );
        }

        foreach ($eTrace as $frame) {
            if (isset($frame['file']) && is_file($frame['file']) &&
                !isset($blacklist[$frame['file']]) &&
                strpos($frame['file'], $prefix) !== 0 &&
                $frame['file'] !== $script) {
                if ($asString === TRUE) {
                    $filteredStacktrace .= sprintf(
                      "%s:%s\n",

                      $frame['file'],
                      isset($frame['line']) ? $frame['line'] : '?'
                    );
                } else {
                    $filteredStacktrace[] = $frame;
                }
            }
        }

        return $filteredStacktrace;
    }

    /**
     * @param  array  $trace
     * @param  string $file
     * @param  int    $line
     * @return boolean
     * @since  Method available since Release 3.3.2
     */
    public static function frameExists(array $trace, $file, $line)
    {
        foreach ($trace as $frame) {
            if (isset($frame['file']) && $frame['file'] == $file &&
                isset($frame['line']) && $frame['line'] == $line) {
                return TRUE;
            }
        }

        return FALSE;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * Command-line options parsing class.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Andrei Zmievski <andrei@php.net>
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class PHPUnit_Util_Getopt
{
    public static function getopt(array $args, $short_options, $long_options = NULL)
    {
        if (empty($args)) {
            return array(array(), array());
        }

        $opts     = array();
        $non_opts = array();

        if ($long_options) {
            sort($long_options);
        }

        if (isset($args[0][0]) && $args[0][0] != '-') {
            array_shift($args);
        }

        reset($args);
        array_map('trim', $args);

        while (list($i, $arg) = each($args)) {
            if ($arg == '') {
                continue;
            }

            if ($arg == '--') {
                $non_opts = array_merge($non_opts, array_slice($args, $i + 1));
                break;
            }

            if ($arg[0] != '-' ||
                (strlen($arg) > 1 && $arg[1] == '-' && !$long_options)) {
                $non_opts = array_merge($non_opts, array_slice($args, $i));
                break;
            }

            elseif (strlen($arg) > 1 && $arg[1] == '-') {
                self::parseLongOption(
                  substr($arg, 2), $long_options, $opts, $args
                );
            }

            else {
                self::parseShortOption(
                  substr($arg, 1), $short_options, $opts, $args
                );
            }
        }

        return array($opts, $non_opts);
    }

    protected static function parseShortOption($arg, $short_options, &$opts, &$args)
    {
        $argLen = strlen($arg);

        for ($i = 0; $i < $argLen; $i++) {
            $opt     = $arg[$i];
            $opt_arg = NULL;

            if (($spec = strstr($short_options, $opt)) === FALSE ||
                $arg[$i] == ':') {
                throw new PHPUnit_Framework_Exception(
                  "unrecognized option -- $opt"
                );
            }

            if (strlen($spec) > 1 && $spec[1] == ':') {
                if (strlen($spec) > 2 && $spec[2] == ':') {
                    if ($i + 1 < $argLen) {
                        $opts[] = array($opt, substr($arg, $i + 1));
                        break;
                    }
                } else {
                    if ($i + 1 < $argLen) {
                        $opts[] = array($opt, substr($arg, $i + 1));
                        break;
                    }

                    else if (list(, $opt_arg) = each($args)) {
                    }

                    else {
                        throw new PHPUnit_Framework_Exception(
                          "option requires an argument -- $opt"
                        );
                    }
                }
            }

            $opts[] = array($opt, $opt_arg);
        }
    }

    protected static function parseLongOption($arg, $long_options, &$opts, &$args)
    {
        $count   = count($long_options);
        $list    = explode('=', $arg);
        $opt     = $list[0];
        $opt_arg = NULL;

        if (count($list) > 1) {
            $opt_arg = $list[1];
        }

        $opt_len = strlen($opt);

        for ($i = 0; $i < $count; $i++) {
            $long_opt  = $long_options[$i];
            $opt_start = substr($long_opt, 0, $opt_len);

            if ($opt_start != $opt) {
                continue;
            }

            $opt_rest = substr($long_opt, $opt_len);

            if ($opt_rest != '' && $opt[0] != '=' && $i + 1 < $count &&
                $opt == substr($long_options[$i+1], 0, $opt_len)) {
                throw new PHPUnit_Framework_Exception(
                  "option --$opt is ambiguous"
                );
            }

            if (substr($long_opt, -1) == '=') {
                if (substr($long_opt, -2) != '==') {
                    if (!strlen($opt_arg) &&
                        !(list(, $opt_arg) = each($args))) {
                        throw new PHPUnit_Framework_Exception(
                          "option --$opt requires an argument"
                        );
                    }
                }
            }

            else if ($opt_arg) {
                throw new PHPUnit_Framework_Exception(
                  "option --$opt doesn't allow an argument"
                );
            }

            $opts[] = array('--' . $opt, $opt_arg);
            return;
        }

        throw new PHPUnit_Framework_Exception("unrecognized option --$opt");
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.4.0
 */

/**
 * Utility methods for PHP sub-processes.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.4.0
 */
abstract class PHPUnit_Util_PHP
{
    /**
     * @var string $phpBinary
     */
    protected $phpBinary;

    /**
     * Returns the path to a PHP interpreter.
     *
     * PHPUnit_Util_PHP::$phpBinary contains the path to the PHP
     * interpreter.
     *
     * When not set, the following assumptions will be made:
     *
     *   1. When PHPUnit is run using the CLI SAPI and the $_SERVER['_']
     *      variable does not contain the string "PHPUnit", $_SERVER['_']
     *      is assumed to contain the path to the current PHP interpreter
     *      and that will be used.
     *
     *   2. When PHPUnit is run using the CLI SAPI and the $_SERVER['_']
     *      variable contains the string "PHPUnit", the file that $_SERVER['_']
     *      points to is assumed to be the PHPUnit TextUI CLI wrapper script
     *      "phpunit" and the binary set up using #! on that file's first
     *      line of code is assumed to contain the path to the current PHP
     *      interpreter and that will be used.
     *
     *   3. When the PHP CLI/CGI binary configured with the PEAR Installer
     *      (php_bin configuration value) is readable, it will be used.
     *
     *   4. The current PHP interpreter is assumed to be in the $PATH and
     *      to be invokable through "php".
     *
     * @return string
     */
    protected function getPhpBinary()
    {
        if ($this->phpBinary === NULL) {
            if (defined("PHP_BINARY")) {
                $this->phpBinary = PHP_BINARY;
            } else if (PHP_SAPI == 'cli' && isset($_SERVER['_'])) {
                if (strpos($_SERVER['_'], 'phpunit') !== FALSE) {
                    $file = file($_SERVER['_']);

                    if (strpos($file[0], ' ') !== FALSE) {
                        $tmp = explode(' ', $file[0]);
                        $this->phpBinary = trim($tmp[1]);
                    } else {
                        $this->phpBinary = ltrim(trim($file[0]), '#!');
                    }
                } else if (strpos(basename($_SERVER['_']), 'php') !== FALSE) {
                    $this->phpBinary = $_SERVER['_'];
                }
            }

            if ($this->phpBinary === NULL) {
                $possibleBinaryLocations = array(
                    PHP_BINDIR . '/php',
                    PHP_BINDIR . '/php-cli.exe',
                    PHP_BINDIR . '/php.exe',
                    '@php_bin@',
                );
                foreach ($possibleBinaryLocations as $binary) {
                    if (is_readable($binary)) {
                        $this->phpBinary = $binary;
                        break;
                    }
                }
            }

            if (!is_readable($this->phpBinary)) {
                $this->phpBinary = 'php';
            } else {
                $this->phpBinary = escapeshellarg($this->phpBinary);
            }
        }

        return $this->phpBinary;
    }

    /**
     * @return PHPUnit_Util_PHP
     * @since  Method available since Release 3.5.12
     */
    public static function factory()
    {
        if (DIRECTORY_SEPARATOR == '\\') {
            return new PHPUnit_Util_PHP_Windows;
        }

        return new PHPUnit_Util_PHP_Default;
    }

    /**
     * Runs a single job (PHP code) using a separate PHP process.
     *
     * @param  string                       $job
     * @param  PHPUnit_Framework_TestCase   $test
     * @param  PHPUnit_Framework_TestResult $result
     * @return array|null
     * @throws PHPUnit_Framework_Exception
     */
    public function runJob($job, PHPUnit_Framework_Test $test = NULL, PHPUnit_Framework_TestResult $result = NULL)
    {
        $process = proc_open(
          $this->getPhpBinary(),
          array(
            0 => array('pipe', 'r'),
            1 => array('pipe', 'w'),
            2 => array('pipe', 'w')
          ),
          $pipes
        );

        if (!is_resource($process)) {
            throw new PHPUnit_Framework_Exception(
              'Unable to create process for process isolation.'
            );
        }

        if ($result !== NULL) {
            $result->startTest($test);
        }

        $this->process($pipes[0], $job);
        fclose($pipes[0]);

        $stdout = stream_get_contents($pipes[1]);
        fclose($pipes[1]);

        $stderr = stream_get_contents($pipes[2]);
        fclose($pipes[2]);

        proc_close($process);
        $this->cleanup();

        if ($result !== NULL) {
            $this->processChildResult($test, $result, $stdout, $stderr);
        } else {
            return array('stdout' => $stdout, 'stderr' => $stderr);
        }
    }

    /**
     * @param resource $pipe
     * @param string   $job
     * @since Method available since Release 3.5.12
     */
    abstract protected function process($pipe, $job);

    /**
     * @since Method available since Release 3.5.12
     */
    protected function cleanup()
    {
    }

    /**
     * Processes the TestResult object from an isolated process.
     *
     * @param PHPUnit_Framework_TestCase   $test
     * @param PHPUnit_Framework_TestResult $result
     * @param string                       $stdout
     * @param string                       $stderr
     * @since Method available since Release 3.5.0
     */
    protected function processChildResult(PHPUnit_Framework_Test $test, PHPUnit_Framework_TestResult $result, $stdout, $stderr)
    {
        $time = 0;

        if (!empty($stderr)) {
            $result->addError(
              $test,
              new PHPUnit_Framework_Exception(trim($stderr)), $time
            );
        } else {
            set_error_handler(function($errno, $errstr, $errfile, $errline) {
                throw new ErrorException($errstr, $errno, $errno, $errfile, $errline);
            });
            try {
                if (strpos($stdout, "\n") === 0) {
                    $stdout = substr($stdout, 19);
                }

                $childResult = unserialize(str_replace("\n", '', $stdout));
                restore_error_handler();
            } catch (ErrorException $e) {
                restore_error_handler();
                $childResult = FALSE;

                $result->addError(
                  $test, new PHPUnit_Framework_Exception(trim($stdout), 0, $e), $time
                );
            }

            if ($childResult !== FALSE) {
                if (!empty($childResult['output'])) {
                    print $childResult['output'];
                }

                $test->setResult($childResult['testResult']);
                $test->addToAssertionCount($childResult['numAssertions']);

                $childResult = $childResult['result'];

                if ($result->getCollectCodeCoverageInformation()) {
                    $result->getCodeCoverage()->merge(
                      $childResult->getCodeCoverage()
                    );
                }

                $time           = $childResult->time();
                $notImplemented = $childResult->notImplemented();
                $skipped        = $childResult->skipped();
                $errors         = $childResult->errors();
                $failures       = $childResult->failures();

                if (!empty($notImplemented)) {
                    $result->addError(
                      $test, $this->getException($notImplemented[0]), $time
                    );
                }

                else if (!empty($skipped)) {
                    $result->addError(
                      $test, $this->getException($skipped[0]), $time
                    );
                }

                else if (!empty($errors)) {
                    $result->addError(
                      $test, $this->getException($errors[0]), $time
                    );
                }

                else if (!empty($failures)) {
                    $result->addFailure(
                      $test, $this->getException($failures[0]), $time
                    );
                }
            }
        }

        $result->endTest($test, $time);
    }

    /**
     * Gets the thrown exception from a PHPUnit_Framework_TestFailure.
     *
     * @param PHPUnit_Framework_TestFailure $error
     * @since Method available since Release 3.6.0
     * @see   https://github.com/sebastianbergmann/phpunit/issues/74
     */
    protected function getException(PHPUnit_Framework_TestFailure $error)
    {
        $exception = $error->thrownException();

        if ($exception instanceof __PHP_Incomplete_Class) {
            $exceptionArray = array();
            foreach ((array)$exception as $key => $value) {
                $key = substr($key, strrpos($key, "\0") + 1);
                $exceptionArray[$key] = $value;
            }

            $exception = new PHPUnit_Framework_SyntheticError(
              sprintf(
                '%s: %s',
                $exceptionArray['_PHP_Incomplete_Class_Name'],
                $exceptionArray['message']
              ),
              $exceptionArray['code'],
              $exceptionArray['file'],
              $exceptionArray['line'],
              $exceptionArray['trace']
            );
        }

        return $exception;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * Test helpers.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class PHPUnit_Util_Test
{
    const REGEX_DATA_PROVIDER      = '/@dataProvider\s+([a-zA-Z0-9._:-\\\\x7f-\xff]+)/';
    const REGEX_EXPECTED_EXCEPTION = '(@expectedException\s+([:.\w\\\\x7f-\xff]+)(?:[\t ]+(\S*))?(?:[\t ]+(\S*))?\s*$)m';
    const REGEX_REQUIRES_VERSION   = '/@requires\s+(?P<name>PHP(?:Unit)?)\s+(?P<value>[\d\.-]+(dev|(RC|alpha|beta)[\d\.])?)[ \t]*\r?$/m';
    const REGEX_REQUIRES           = '/@requires\s+(?P<name>function|extension)\s(?P<value>([^ ]+))\r?$/m';

    const SMALL  = 0;
    const MEDIUM = 1;
    const LARGE  = 2;

    private static $annotationCache = array();

    protected static $templateMethods = array(
      'setUp', 'assertPreConditions', 'assertPostConditions', 'tearDown'
    );

    /**
     * @param  PHPUnit_Framework_Test $test
     * @param  boolean                $asString
     * @return mixed
     */
    public static function describe(PHPUnit_Framework_Test $test, $asString = TRUE)
    {
        if ($asString) {
            if ($test instanceof PHPUnit_Framework_SelfDescribing) {
                return $test->toString();
            } else {
                return get_class($test);
            }
        } else {
            if ($test instanceof PHPUnit_Framework_TestCase) {
                return array(
                  get_class($test), $test->getName()
                );
            }

            else if ($test instanceof PHPUnit_Framework_SelfDescribing) {
                return array('', $test->toString());
            }

            else {
                return array('', get_class($test));
            }
        }
    }

    /**
     * Returns the requirements for a test.
     *
     * @param  string $className
     * @param  string $methodName
     * @return array
     * @since  Method available since Release 3.6.0
     */
    public static function getRequirements($className, $methodName)
    {
        $reflector  = new ReflectionClass($className);
        $docComment = $reflector->getDocComment();
        $reflector  = new ReflectionMethod($className, $methodName);
        $docComment .= "\n" . $reflector->getDocComment();
        $requires   = array();

        if ($count = preg_match_all(self::REGEX_REQUIRES_VERSION, $docComment, $matches)) {
            for ($i = 0; $i < $count; $i++) {
                $requires[$matches['name'][$i]] = $matches['value'][$i];
            }
        }

        // https://bugs.php.net/bug.php?id=63055
        $matches = array();

        if ($count = preg_match_all(self::REGEX_REQUIRES, $docComment, $matches)) {
            for ($i = 0; $i < $count; $i++) {
                $name = $matches['name'][$i] . 's';
                if (!isset($requires[$name])) {
                    $requires[$name] = array();
                }
                $requires[$name][] = $matches['value'][$i];
            }
        }

        return $requires;
    }

    /**
     * Returns the expected exception for a test.
     *
     * @param  string $className
     * @param  string $methodName
     * @return array
     * @since  Method available since Release 3.3.6
     */
    public static function getExpectedException($className, $methodName)
    {
        $reflector  = new ReflectionMethod($className, $methodName);
        $docComment = $reflector->getDocComment();
        $docComment = substr($docComment, 3, -2);

        if (preg_match(self::REGEX_EXPECTED_EXCEPTION, $docComment, $matches)) {
            $annotations = self::parseTestMethodAnnotations(
              $className, $methodName
            );

            $class   = $matches[1];
            $code    = NULL;
            $message = '';

            if (isset($matches[2])) {
                $message = trim($matches[2]);
            }

            else if (isset($annotations['method']['expectedExceptionMessage'])) {
                $message = self::_parseAnnotationContent(
                    $annotations['method']['expectedExceptionMessage'][0]
                );
            }

            if (isset($matches[3])) {
                $code = $matches[3];
            }

            else if (isset($annotations['method']['expectedExceptionCode'])) {
                $code = self::_parseAnnotationContent(
                    $annotations['method']['expectedExceptionCode'][0]
                );
            }

            if (is_numeric($code)) {
                $code = (int)$code;
            }

            else if (is_string($code) && defined($code)) {
                $code = (int)constant($code);
            }

            return array(
              'class' => $class, 'code' => $code, 'message' => $message
            );
        }

        return FALSE;
    }

    /**
     * Parse annotation content to use constant/class constant values
     *
     * Constants are specified using a starting '@'. For example: @ClassName::CONST_NAME
     *
     * If the constant is not found the string is used as is to ensure maximum BC.
     *
     * @param  string $message
     * @return string
     */
    protected static function _parseAnnotationContent($message)
    {
        if (strpos($message, '::') !== FALSE && count(explode('::', $message) == 2)) {
            if (defined($message)) {
                $message = constant($message);
            }
        }
        return $message;
    }

    /**
     * Returns the provided data for a method.
     *
     * @param  string $className
     * @param  string $methodName
     * @param  string $docComment
     * @return mixed  array|Iterator when a data provider is specified and exists
     *                false          when a data provider is specified and does not exist
     *                null           when no data provider is specified
     * @since  Method available since Release 3.2.0
     */
    public static function getProvidedData($className, $methodName)
    {
        $reflector  = new ReflectionMethod($className, $methodName);
        $docComment = $reflector->getDocComment();
        $data       = NULL;

        if (preg_match(self::REGEX_DATA_PROVIDER, $docComment, $matches)) {
            $dataProviderMethodNameNamespace = explode('\\', $matches[1]);
            $leaf                            = explode('::', array_pop($dataProviderMethodNameNamespace));
            $dataProviderMethodName          = array_pop($leaf);

            if (!empty($dataProviderMethodNameNamespace)) {
                $dataProviderMethodNameNamespace = join('\\', $dataProviderMethodNameNamespace) . '\\';
            } else {
                $dataProviderMethodNameNamespace = '';
            }

            if (!empty($leaf)) {
                $dataProviderClassName = $dataProviderMethodNameNamespace . array_pop($leaf);
            } else {
                $dataProviderClassName = $className;
            }

            $dataProviderClass  = new ReflectionClass($dataProviderClassName);
            $dataProviderMethod = $dataProviderClass->getMethod(
              $dataProviderMethodName
            );

            if ($dataProviderMethod->isStatic()) {
                $object = NULL;
            } else {
                $object = $dataProviderClass->newInstance();
            }

            if ($dataProviderMethod->getNumberOfParameters() == 0) {
                $data = $dataProviderMethod->invoke($object);
            } else {
                $data = $dataProviderMethod->invoke($object, $methodName);
            }
        }

        if ($data !== NULL) {
            if (is_object($data)) {
                $data = iterator_to_array($data);
            }

            foreach ($data as $key => $value) {
                if (!is_array($value)) {
                    throw new PHPUnit_Framework_Exception(
                      sprintf(
                        'Data set %s is invalid.',
                        is_int($key) ? '#' . $key : '"' . $key . '"'
                      )
                    );
                }
            }
        }

        return $data;
    }

    /**
     * @param  string $className
     * @param  string $methodName
     * @return array
     * @throws ReflectionException
     * @since  Method available since Release 3.4.0
     */
    public static function parseTestMethodAnnotations($className, $methodName = '')
    {
        if (!isset(self::$annotationCache[$className])) {
            $class = new ReflectionClass($className);
            self::$annotationCache[$className] = self::parseAnnotations($class->getDocComment());
        }

        if (!empty($methodName) && !isset(self::$annotationCache[$className . '::' . $methodName])) {
            try {
                $method = new ReflectionMethod($className, $methodName);
                $annotations = self::parseAnnotations($method->getDocComment());
            } catch (ReflectionException $e) {
                $annotations = array();
            }
            self::$annotationCache[$className . '::' . $methodName] = $annotations;
        }

        return array(
          'class'  => self::$annotationCache[$className],
          'method' => !empty($methodName) ? self::$annotationCache[$className . '::' . $methodName] : array()
        );
    }

    /**
     * @param  string $docblock
     * @return array
     * @since  Method available since Release 3.4.0
     */
    private static function parseAnnotations($docblock)
    {
        $annotations = array();
        // Strip away the docblock header and footer to ease parsing of one line annotations
        $docblock = substr($docblock, 3, -2);

        if (preg_match_all('/@(?P<name>[A-Za-z_-]+)(?:[ \t]+(?P<value>.*?))?[ \t]*\r?$/m', $docblock, $matches)) {
            $numMatches = count($matches[0]);

            for ($i = 0; $i < $numMatches; ++$i) {
                $annotations[$matches['name'][$i]][] = $matches['value'][$i];
            }
        }

        return $annotations;
    }

    /**
     * Returns the backup settings for a test.
     *
     * @param  string $className
     * @param  string $methodName
     * @return array
     * @since  Method available since Release 3.4.0
     */
    public static function getBackupSettings($className, $methodName)
    {
        return array(
          'backupGlobals' => self::getBooleanAnnotationSetting(
            $className, $methodName, 'backupGlobals'
          ),
          'backupStaticAttributes' => self::getBooleanAnnotationSetting(
            $className, $methodName, 'backupStaticAttributes'
          )
        );
    }

    /**
     * Returns the dependencies for a test class or method.
     *
     * @param  string $className
     * @param  string $methodName
     * @return array
     * @since  Method available since Release 3.4.0
     */
    public static function getDependencies($className, $methodName)
    {
        $annotations = self::parseTestMethodAnnotations(
          $className, $methodName
        );

        $dependencies = array();

        if (isset($annotations['class']['depends'])) {
            $dependencies = $annotations['class']['depends'];
        }

        if (isset($annotations['method']['depends'])) {
            $dependencies = array_merge(
              $dependencies, $annotations['method']['depends']
            );
        }

        return array_unique($dependencies);
    }

    /**
     * Returns the error handler settings for a test.
     *
     * @param  string $className
     * @param  string $methodName
     * @return boolean
     * @since  Method available since Release 3.4.0
     */
    public static function getErrorHandlerSettings($className, $methodName)
    {
        return self::getBooleanAnnotationSetting(
          $className, $methodName, 'errorHandler'
        );
    }

    /**
     * Returns the groups for a test class or method.
     *
     * @param  string $className
     * @param  string $methodName
     * @return array
     * @since  Method available since Release 3.2.0
     */
    public static function getGroups($className, $methodName = '')
    {
        $annotations = self::parseTestMethodAnnotations(
          $className, $methodName
        );

        $groups = array();

        if (isset($annotations['method']['author'])) {
            $groups = $annotations['method']['author'];
        }

        else if (isset($annotations['class']['author'])) {
            $groups = $annotations['class']['author'];
        }

        if (isset($annotations['class']['group'])) {
            $groups = array_merge($groups, $annotations['class']['group']);
        }

        if (isset($annotations['method']['group'])) {
            $groups = array_merge($groups, $annotations['method']['group']);
        }

        if (isset($annotations['class']['ticket'])) {
            $groups = array_merge($groups, $annotations['class']['ticket']);
        }

        if (isset($annotations['method']['ticket'])) {
            $groups = array_merge($groups, $annotations['method']['ticket']);
        }

        foreach (array('small', 'medium', 'large') as $size) {
            if (isset($annotations['method'][$size])) {
                $groups[] = $size;
            }

            else if (isset($annotations['class'][$size])) {
                $groups[] = $size;
            }
        }

        return array_unique($groups);
    }

    /**
     * Returns the size of the test.
     *
     * @param  string $className
     * @param  string $methodName
     * @return integer
     * @since  Method available since Release 3.6.0
     */
    public static function getSize($className, $methodName)
    {
        $groups = array_flip(self::getGroups($className, $methodName));
        $size   = self::SMALL;
        $class  = new ReflectionClass($className);

        if ((class_exists('PHPUnit_Extensions_Database_TestCase', FALSE) &&
             $class->isSubclassOf('PHPUnit_Extensions_Database_TestCase')) ||
            (class_exists('PHPUnit_Extensions_SeleniumTestCase', FALSE) &&
             $class->isSubclassOf('PHPUnit_Extensions_SeleniumTestCase'))) {
            $size = self::LARGE;
        }

        else if (isset($groups['medium'])) {
            $size = self::MEDIUM;
        }

        else if (isset($groups['large'])) {
            $size = self::LARGE;
        }

        return $size;
    }

    /**
     * Returns the tickets for a test class or method.
     *
     * @param  string $className
     * @param  string $methodName
     * @return array
     * @since  Method available since Release 3.4.0
     */
    public static function getTickets($className, $methodName)
    {
        $annotations = self::parseTestMethodAnnotations(
          $className, $methodName
        );

        $tickets = array();

        if (isset($annotations['class']['ticket'])) {
            $tickets = $annotations['class']['ticket'];
        }

        if (isset($annotations['method']['ticket'])) {
            $tickets = array_merge($tickets, $annotations['method']['ticket']);
        }

        return array_unique($tickets);
    }

    /**
     * Returns the output buffering settings for a test.
     *
     * @param  string $className
     * @param  string $methodName
     * @return boolean
     * @since  Method available since Release 3.4.0
     */
    public static function getOutputBufferingSettings($className, $methodName)
    {
        return self::getBooleanAnnotationSetting(
          $className, $methodName, 'outputBuffering'
        );
    }

    /**
     * Returns the process isolation settings for a test.
     *
     * @param  string $className
     * @param  string $methodName
     * @return boolean
     * @since  Method available since Release 3.4.1
     */
    public static function getProcessIsolationSettings($className, $methodName)
    {
        $annotations = self::parseTestMethodAnnotations(
          $className, $methodName
        );

        if (isset($annotations['class']['runTestsInSeparateProcesses']) ||
            isset($annotations['method']['runInSeparateProcess'])) {
            return TRUE;
        } else {
            return FALSE;
        }
    }

    /**
     * Returns the preserve global state settings for a test.
     *
     * @param  string $className
     * @param  string $methodName
     * @return boolean
     * @since  Method available since Release 3.4.0
     */
    public static function getPreserveGlobalStateSettings($className, $methodName)
    {
        return self::getBooleanAnnotationSetting(
          $className, $methodName, 'preserveGlobalState'
        );
    }

    /**
     * @param  string $className
     * @param  string $methodName
     * @param  string $settingName
     * @return boolean
     * @since  Method available since Release 3.4.0
     */
    private static function getBooleanAnnotationSetting($className, $methodName, $settingName)
    {
        $annotations = self::parseTestMethodAnnotations(
          $className, $methodName
        );

        $result = NULL;

        if (isset($annotations['class'][$settingName])) {
            if ($annotations['class'][$settingName][0] == 'enabled') {
                $result = TRUE;
            }

            else if ($annotations['class'][$settingName][0] == 'disabled') {
                $result = FALSE;
            }
        }

        if (isset($annotations['method'][$settingName])) {
            if ($annotations['method'][$settingName][0] == 'enabled') {
                $result = TRUE;
            }

            else if ($annotations['method'][$settingName][0] == 'disabled') {
                $result = FALSE;
            }
        }

        return $result;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.3.0
 */

// Workaround for http://bugs.php.net/bug.php?id=47987,
// see https://github.com/sebastianbergmann/phpunit/issues#issue/125 for details
require_once __DIR__ . '/../Framework/Error.php';
require_once __DIR__ . '/../Framework/Error/Notice.php';
require_once __DIR__ . '/../Framework/Error/Warning.php';
require_once __DIR__ . '/../Framework/Error/Deprecated.php';

/**
 * Error handler that converts PHP errors and warnings to exceptions.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.3.0
 */
class PHPUnit_Util_ErrorHandler
{
    protected static $errorStack = array();

    /**
     * Returns the error stack.
     *
     * @return array
     */
    public static function getErrorStack()
    {
        return self::$errorStack;
    }

    /**
     * @param  integer $errno
     * @param  string  $errstr
     * @param  string  $errfile
     * @param  integer $errline
     * @throws PHPUnit_Framework_Error
     */
    public static function handleError($errno, $errstr, $errfile, $errline)
    {
        if (!($errno & error_reporting())) {
            return FALSE;
        }

        self::$errorStack[] = array($errno, $errstr, $errfile, $errline);

        $trace = debug_backtrace(FALSE);
        array_shift($trace);

        foreach ($trace as $frame) {
            if ($frame['function'] == '__toString') {
                return FALSE;
            }
        }

        if ($errno == E_NOTICE || $errno == E_USER_NOTICE || $errno == E_STRICT) {
            if (PHPUnit_Framework_Error_Notice::$enabled !== TRUE) {
                return FALSE;
            }

            $exception = 'PHPUnit_Framework_Error_Notice';
        }

        else if ($errno == E_WARNING || $errno == E_USER_WARNING) {
            if (PHPUnit_Framework_Error_Warning::$enabled !== TRUE) {
                return FALSE;
            }

            $exception = 'PHPUnit_Framework_Error_Warning';
        }

        else if ($errno == E_DEPRECATED || $errno == E_USER_DEPRECATED) {
            if (PHPUnit_Framework_Error_Deprecated::$enabled !== TRUE) {
                return FALSE;
            }

            $exception = 'PHPUnit_Framework_Error_Deprecated';
        }

        else {
            $exception = 'PHPUnit_Framework_Error';
        }

        throw new $exception($errstr, $errno, $errfile, $errline);
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.2.0
 */

/**
 * XML helpers.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.2.0
 */
class PHPUnit_Util_XML
{
    /**
     * @param  string $string
     * @return string
     * @author Kore Nordmann <mail@kore-nordmann.de>
     * @since  Method available since Release 3.4.6
     */
    public static function prepareString($string)
    {
        return preg_replace_callback(
          '/[\\x00-\\x04\\x0b\\x0c\\x0e-\\x1f\\x7f]/',
          function ($matches)
          {
              return sprintf('&#x%02x;', ord($matches[0]));
          },
          htmlspecialchars(
            PHPUnit_Util_String::convertToUtf8($string), ENT_COMPAT, 'UTF-8'
          )
        );
    }

    /**
     * Loads an XML (or HTML) file into a DOMDocument object.
     *
     * @param  string  $filename
     * @param  boolean $isHtml
     * @param  boolean $xinclude
     * @return DOMDocument
     * @since  Method available since Release 3.3.0
     */
    public static function loadFile($filename, $isHtml = FALSE, $xinclude = FALSE)
    {
        $reporting = error_reporting(0);
        $contents  = file_get_contents($filename);
        error_reporting($reporting);

        if ($contents === FALSE) {
            throw new PHPUnit_Framework_Exception(
              sprintf(
                'Could not read "%s".',
                $filename
              )
            );
        }

        return self::load($contents, $isHtml, $filename, $xinclude);
    }

    /**
     * Load an $actual document into a DOMDocument.  This is called
     * from the selector assertions.
     *
     * If $actual is already a DOMDocument, it is returned with
     * no changes.  Otherwise, $actual is loaded into a new DOMDocument
     * as either HTML or XML, depending on the value of $isHtml. If $isHtml is
     * false and $xinclude is true, xinclude is performed on the loaded
     * DOMDocument.
     *
     * Note: prior to PHPUnit 3.3.0, this method loaded a file and
     * not a string as it currently does.  To load a file into a
     * DOMDocument, use loadFile() instead.
     *
     * @param  string|DOMDocument  $actual
     * @param  boolean             $isHtml
     * @param  string              $filename
     * @param  boolean             $xinclude
     * @return DOMDocument
     * @since  Method available since Release 3.3.0
     * @author Mike Naberezny <mike@maintainable.com>
     * @author Derek DeVries <derek@maintainable.com>
     * @author Tobias Schlitt <toby@php.net>
     */
    public static function load($actual, $isHtml = FALSE, $filename = '', $xinclude = FALSE)
    {
        if ($actual instanceof DOMDocument) {
            return $actual;
        }

        $document  = new DOMDocument;

        $internal  = libxml_use_internal_errors(TRUE);
        $message   = '';
        $reporting = error_reporting(0);

        if ($isHtml) {
            $loaded = $document->loadHTML($actual);
        } else {
            $loaded = $document->loadXML($actual);
        }

        if ('' !== $filename) {
            // Necessary for xinclude
            $document->documentURI = $filename;
        }

        if (!$isHtml && $xinclude) {
            $document->xinclude();
        }

        foreach (libxml_get_errors() as $error) {
            $message .= $error->message;
        }

        libxml_use_internal_errors($internal);
        error_reporting($reporting);

        if ($loaded === FALSE) {
            if ($filename != '') {
                throw new PHPUnit_Framework_Exception(
                  sprintf(
                    'Could not load "%s".%s',

                    $filename,
                    $message != '' ? "\n" . $message : ''
                  )
                );
            } else {
                throw new PHPUnit_Framework_Exception($message);
            }
        }

        return $document;
    }

    /**
     *
     *
     * @param  DOMNode $node
     * @return string
     * @since  Method available since Release 3.4.0
     */
    public static function nodeToText(DOMNode $node)
    {
        if ($node->childNodes->length == 1) {
            return $node->nodeValue;
        }

        $result = '';

        foreach ($node->childNodes as $childNode) {
            $result .= $node->ownerDocument->saveXML($childNode);
        }

        return $result;
    }

    /**
     *
     *
     * @param  DOMNode $node
     * @since  Method available since Release 3.3.0
     * @author Mattis Stordalen Flister <mattis@xait.no>
     */
    public static function removeCharacterDataNodes(DOMNode $node)
    {
        if ($node->hasChildNodes()) {
            for ($i = $node->childNodes->length - 1; $i >= 0; $i--) {
                if (($child = $node->childNodes->item($i)) instanceof DOMCharacterData) {
                    $node->removeChild($child);
                }
            }
        }
    }

    /**
     * "Convert" a DOMElement object into a PHP variable.
     *
     * @param  DOMElement $element
     * @return mixed
     * @since  Method available since Release 3.4.0
     */
    public static function xmlToVariable(DOMElement $element)
    {
        $variable = NULL;

        switch ($element->tagName) {
            case 'array': {
                $variable = array();

                foreach ($element->getElementsByTagName('element') as $element) {
                    $value = self::xmlToVariable($element->childNodes->item(1));

                    if ($element->hasAttribute('key')) {
                        $variable[(string)$element->getAttribute('key')] = $value;
                    } else {
                        $variable[] = $value;
                    }
                }
            }
            break;

            case 'object': {
                $className = $element->getAttribute('class');

                if ($element->hasChildNodes()) {
                    $arguments       = $element->childNodes->item(1)->childNodes;
                    $constructorArgs = array();

                    foreach ($arguments as $argument) {
                        if ($argument instanceof DOMElement) {
                            $constructorArgs[] = self::xmlToVariable($argument);
                        }
                    }

                    $class    = new ReflectionClass($className);
                    $variable = $class->newInstanceArgs($constructorArgs);
                } else {
                    $variable = new $className;
                }
            }
            break;

            case 'boolean': {
                $variable = $element->nodeValue == 'true' ? TRUE : FALSE;
            }
            break;

            case 'integer':
            case 'double':
            case 'string': {
                $variable = $element->nodeValue;

                settype($variable, $element->tagName);
            }
            break;
        }

        return $variable;
    }

    /**
     * Validate list of keys in the associative array.
     *
     * @param  array $hash
     * @param  array $validKeys
     * @return array
     * @throws PHPUnit_Framework_Exception
     * @since  Method available since Release 3.3.0
     * @author Mike Naberezny <mike@maintainable.com>
     * @author Derek DeVries <derek@maintainable.com>
     */
    public static function assertValidKeys(array $hash, array $validKeys)
    {
        $valids = array();

        // Normalize validation keys so that we can use both indexed and
        // associative arrays.
        foreach ($validKeys as $key => $val) {
            is_int($key) ? $valids[$val] = NULL : $valids[$key] = $val;
        }

        $validKeys = array_keys($valids);

        // Check for invalid keys.
        foreach ($hash as $key => $value) {
            if (!in_array($key, $validKeys)) {
                $unknown[] = $key;
            }
        }

        if (!empty($unknown)) {
            throw new PHPUnit_Framework_Exception(
              'Unknown key(s): ' . implode(', ', $unknown)
            );
        }

        // Add default values for any valid keys that are empty.
        foreach ($valids as $key => $value) {
            if (!isset($hash[$key])) {
                $hash[$key] = $value;
            }
        }

        return $hash;
    }

    /**
     * Parse a CSS selector into an associative array suitable for
     * use with findNodes().
     *
     * @param  string $selector
     * @param  mixed  $content
     * @return array
     * @since  Method available since Release 3.3.0
     * @author Mike Naberezny <mike@maintainable.com>
     * @author Derek DeVries <derek@maintainable.com>
     */
    public static function convertSelectToTag($selector, $content = TRUE)
    {
        $selector = trim(preg_replace("/\s+/", " ", $selector));

        // substitute spaces within attribute value
        while (preg_match('/\[[^\]]+"[^"]+\s[^"]+"\]/', $selector)) {
            $selector = preg_replace(
              '/(\[[^\]]+"[^"]+)\s([^"]+"\])/', "$1__SPACE__$2", $selector
            );
        }

        if (strstr($selector, ' ')) {
            $elements = explode(' ', $selector);
        } else {
            $elements = array($selector);
        }

        $previousTag = array();

        foreach (array_reverse($elements) as $element) {
            $element = str_replace('__SPACE__', ' ', $element);

            // child selector
            if ($element == '>') {
                $previousTag = array('child' => $previousTag['descendant']);
                continue;
            }

            $tag = array();

            // match element tag
            preg_match("/^([^\.#\[]*)/", $element, $eltMatches);

            if (!empty($eltMatches[1])) {
                $tag['tag'] = $eltMatches[1];
            }

            // match attributes (\[[^\]]*\]*), ids (#[^\.#\[]*),
            // and classes (\.[^\.#\[]*))
            preg_match_all(
              "/(\[[^\]]*\]*|#[^\.#\[]*|\.[^\.#\[]*)/", $element, $matches
            );

            if (!empty($matches[1])) {
                $classes = array();
                $attrs   = array();

                foreach ($matches[1] as $match) {
                    // id matched
                    if (substr($match, 0, 1) == '#') {
                        $tag['id'] = substr($match, 1);
                    }

                    // class matched
                    else if (substr($match, 0, 1) == '.') {
                        $classes[] = substr($match, 1);
                    }

                    // attribute matched
                    else if (substr($match, 0, 1) == '[' &&
                             substr($match, -1, 1) == ']') {
                        $attribute = substr($match, 1, strlen($match) - 2);
                        $attribute = str_replace('"', '', $attribute);

                        // match single word
                        if (strstr($attribute, '~=')) {
                            list($key, $value) = explode('~=', $attribute);
                            $value             = "regexp:/.*\b$value\b.*/";
                        }

                        // match substring
                        else if (strstr($attribute, '*=')) {
                            list($key, $value) = explode('*=', $attribute);
                            $value             = "regexp:/.*$value.*/";
                        }

                        // exact match
                        else {
                            list($key, $value) = explode('=', $attribute);
                        }

                        $attrs[$key] = $value;
                    }
                }

                if ($classes) {
                    $tag['class'] = join(' ', $classes);
                }

                if ($attrs) {
                    $tag['attributes'] = $attrs;
                }
            }

            // tag content
            if (is_string($content)) {
                $tag['content'] = $content;
            }

            // determine previous child/descendants
            if (!empty($previousTag['descendant'])) {
                $tag['descendant'] = $previousTag['descendant'];
            }

            else if (!empty($previousTag['child'])) {
                $tag['child'] = $previousTag['child'];
            }

            $previousTag = array('descendant' => $tag);
        }

        return $tag;
    }

    /**
     * Parse an $actual document and return an array of DOMNodes
     * matching the CSS $selector.  If an error occurs, it will
     * return FALSE.
     *
     * To only return nodes containing a certain content, give
     * the $content to match as a string.  Otherwise, setting
     * $content to TRUE will return all nodes matching $selector.
     *
     * The $actual document may be a DOMDocument or a string
     * containing XML or HTML, identified by $isHtml.
     *
     * @param  array   $selector
     * @param  string  $content
     * @param  mixed   $actual
     * @param  boolean $isHtml
     * @return false|array
     * @since  Method available since Release 3.3.0
     * @author Mike Naberezny <mike@maintainable.com>
     * @author Derek DeVries <derek@maintainable.com>
     * @author Tobias Schlitt <toby@php.net>
     */
    public static function cssSelect($selector, $content, $actual, $isHtml = TRUE)
    {
        $matcher = self::convertSelectToTag($selector, $content);
        $dom     = self::load($actual, $isHtml);
        $tags    = self::findNodes($dom, $matcher, $isHtml);

        return $tags;
    }

    /**
     * Parse out the options from the tag using DOM object tree.
     *
     * @param  DOMDocument $dom
     * @param  array       $options
     * @param  boolean     $isHtml
     * @return array
     * @since  Method available since Release 3.3.0
     * @author Mike Naberezny <mike@maintainable.com>
     * @author Derek DeVries <derek@maintainable.com>
     * @author Tobias Schlitt <toby@php.net>
     */
    public static function findNodes(DOMDocument $dom, array $options, $isHtml = TRUE)
    {
        $valid = array(
          'id', 'class', 'tag', 'content', 'attributes', 'parent',
          'child', 'ancestor', 'descendant', 'children'
        );

        $filtered = array();
        $options  = self::assertValidKeys($options, $valid);

        // find the element by id
        if ($options['id']) {
            $options['attributes']['id'] = $options['id'];
        }

        if ($options['class']) {
            $options['attributes']['class'] = $options['class'];
        }

        // find the element by a tag type
        if ($options['tag']) {
            if ($isHtml) {
                $elements = self::getElementsByCaseInsensitiveTagName(
                  $dom, $options['tag']
                );
            } else {
                $elements = $dom->getElementsByTagName($options['tag']);
            }

            foreach ($elements as $element) {
                $nodes[] = $element;
            }

            if (empty($nodes)) {
                return FALSE;
            }
        }

        // no tag selected, get them all
        else {
            $tags = array(
              'a', 'abbr', 'acronym', 'address', 'area', 'b', 'base', 'bdo',
              'big', 'blockquote', 'body', 'br', 'button', 'caption', 'cite',
              'code', 'col', 'colgroup', 'dd', 'del', 'div', 'dfn', 'dl',
              'dt', 'em', 'fieldset', 'form', 'frame', 'frameset', 'h1', 'h2',
              'h3', 'h4', 'h5', 'h6', 'head', 'hr', 'html', 'i', 'iframe',
              'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'link',
              'map', 'meta', 'noframes', 'noscript', 'object', 'ol', 'optgroup',
              'option', 'p', 'param', 'pre', 'q', 'samp', 'script', 'select',
              'small', 'span', 'strong', 'style', 'sub', 'sup', 'table',
              'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'title',
              'tr', 'tt', 'ul', 'var'
            );

            foreach ($tags as $tag) {
                if ($isHtml) {
                    $elements = self::getElementsByCaseInsensitiveTagName(
                      $dom, $tag
                    );
                } else {
                    $elements = $dom->getElementsByTagName($tag);
                }

                foreach ($elements as $element) {
                    $nodes[] = $element;
                }
            }

            if (empty($nodes)) {
                return FALSE;
            }
        }

        // filter by attributes
        if ($options['attributes']) {
            foreach ($nodes as $node) {
                $invalid = FALSE;

                foreach ($options['attributes'] as $name => $value) {
                    // match by regexp if like "regexp:/foo/i"
                    if (preg_match('/^regexp\s*:\s*(.*)/i', $value, $matches)) {
                        if (!preg_match($matches[1], $node->getAttribute($name))) {
                            $invalid = TRUE;
                        }
                    }

                    // class can match only a part
                    else if ($name == 'class') {
                        // split to individual classes
                        $findClasses = explode(
                          ' ', preg_replace("/\s+/", " ", $value)
                        );

                        $allClasses = explode(
                          ' ',
                          preg_replace("/\s+/", " ", $node->getAttribute($name))
                        );

                        // make sure each class given is in the actual node
                        foreach ($findClasses as $findClass) {
                            if (!in_array($findClass, $allClasses)) {
                                $invalid = TRUE;
                            }
                        }
                    }

                    // match by exact string
                    else {
                        if ($node->getAttribute($name) != $value) {
                            $invalid = TRUE;
                        }
                    }
                }

                // if every attribute given matched
                if (!$invalid) {
                    $filtered[] = $node;
                }
            }

            $nodes    = $filtered;
            $filtered = array();

            if (empty($nodes)) {
                return FALSE;
            }
        }

        // filter by content
        if ($options['content'] !== NULL) {
            foreach ($nodes as $node) {
                $invalid = FALSE;

                // match by regexp if like "regexp:/foo/i"
                if (preg_match('/^regexp\s*:\s*(.*)/i', $options['content'], $matches)) {
                    if (!preg_match($matches[1], self::getNodeText($node))) {
                        $invalid = TRUE;
                    }
                }

                // match empty string
                else if ($options['content'] === '') {
                    if (self::getNodeText($node) !== '') {
                        $invalid = TRUE;
                    }
                }

                // match by exact string
                else if (strstr(self::getNodeText($node), $options['content']) === FALSE) {
                    $invalid = TRUE;
                }

                if (!$invalid) {
                    $filtered[] = $node;
                }
            }

            $nodes    = $filtered;
            $filtered = array();

            if (empty($nodes)) {
                return FALSE;
            }
        }

        // filter by parent node
        if ($options['parent']) {
            $parentNodes = self::findNodes($dom, $options['parent'], $isHtml);
            $parentNode  = isset($parentNodes[0]) ? $parentNodes[0] : NULL;

            foreach ($nodes as $node) {
                if ($parentNode !== $node->parentNode) {
                    continue;
                }

                $filtered[] = $node;
            }

            $nodes    = $filtered;
            $filtered = array();

            if (empty($nodes)) {
                return FALSE;
            }
        }

        // filter by child node
        if ($options['child']) {
            $childNodes = self::findNodes($dom, $options['child'], $isHtml);
            $childNodes = !empty($childNodes) ? $childNodes : array();

            foreach ($nodes as $node) {
                foreach ($node->childNodes as $child) {
                    foreach ($childNodes as $childNode) {
                        if ($childNode === $child) {
                            $filtered[] = $node;
                        }
                    }
                }
            }

            $nodes    = $filtered;
            $filtered = array();

            if (empty($nodes)) {
                return FALSE;
            }
        }

        // filter by ancestor
        if ($options['ancestor']) {
            $ancestorNodes = self::findNodes($dom, $options['ancestor'], $isHtml);
            $ancestorNode  = isset($ancestorNodes[0]) ? $ancestorNodes[0] : NULL;

            foreach ($nodes as $node) {
                $parent = $node->parentNode;

                while ($parent && $parent->nodeType != XML_HTML_DOCUMENT_NODE) {
                    if ($parent === $ancestorNode) {
                        $filtered[] = $node;
                    }

                    $parent = $parent->parentNode;
                }
            }

            $nodes    = $filtered;
            $filtered = array();

            if (empty($nodes)) {
                return FALSE;
            }
        }

        // filter by descendant
        if ($options['descendant']) {
            $descendantNodes = self::findNodes($dom, $options['descendant'], $isHtml);
            $descendantNodes = !empty($descendantNodes) ? $descendantNodes : array();

            foreach ($nodes as $node) {
                foreach (self::getDescendants($node) as $descendant) {
                    foreach ($descendantNodes as $descendantNode) {
                        if ($descendantNode === $descendant) {
                            $filtered[] = $node;
                        }
                    }
                }
            }

            $nodes    = $filtered;
            $filtered = array();

            if (empty($nodes)) {
                return FALSE;
            }
        }

        // filter by children
        if ($options['children']) {
            $validChild   = array('count', 'greater_than', 'less_than', 'only');
            $childOptions = self::assertValidKeys(
                              $options['children'], $validChild
                            );

            foreach ($nodes as $node) {
                $childNodes = $node->childNodes;

                foreach ($childNodes as $childNode) {
                    if ($childNode->nodeType !== XML_CDATA_SECTION_NODE &&
                        $childNode->nodeType !== XML_TEXT_NODE) {
                        $children[] = $childNode;
                    }
                }

                // we must have children to pass this filter
                if (!empty($children)) {
                    // exact count of children
                    if ($childOptions['count'] !== NULL) {
                        if (count($children) !== $childOptions['count']) {
                            break;
                        }
                    }

                    // range count of children
                    else if ($childOptions['less_than']    !== NULL &&
                            $childOptions['greater_than'] !== NULL) {
                        if (count($children) >= $childOptions['less_than'] ||
                            count($children) <= $childOptions['greater_than']) {
                            break;
                        }
                    }

                    // less than a given count
                    else if ($childOptions['less_than'] !== NULL) {
                        if (count($children) >= $childOptions['less_than']) {
                            break;
                        }
                    }

                    // more than a given count
                    else if ($childOptions['greater_than'] !== NULL) {
                        if (count($children) <= $childOptions['greater_than']) {
                            break;
                        }
                    }

                    // match each child against a specific tag
                    if ($childOptions['only']) {
                        $onlyNodes = self::findNodes(
                          $dom, $childOptions['only'], $isHtml
                        );

                        // try to match each child to one of the 'only' nodes
                        foreach ($children as $child) {
                            $matched = FALSE;

                            foreach ($onlyNodes as $onlyNode) {
                                if ($onlyNode === $child) {
                                    $matched = TRUE;
                                }
                            }

                            if (!$matched) {
                                break(2);
                            }
                        }
                    }

                    $filtered[] = $node;
                }
            }

            $nodes    = $filtered;
            $filtered = array();

            if (empty($nodes)) {
                return;
            }
        }

        // return the first node that matches all criteria
        return !empty($nodes) ? $nodes : array();
    }

    /**
     * Recursively get flat array of all descendants of this node.
     *
     * @param  DOMNode $node
     * @return array
     * @since  Method available since Release 3.3.0
     * @author Mike Naberezny <mike@maintainable.com>
     * @author Derek DeVries <derek@maintainable.com>
     */
    protected static function getDescendants(DOMNode $node)
    {
        $allChildren = array();
        $childNodes  = $node->childNodes ? $node->childNodes : array();

        foreach ($childNodes as $child) {
            if ($child->nodeType === XML_CDATA_SECTION_NODE ||
                $child->nodeType === XML_TEXT_NODE) {
                continue;
            }

            $children    = self::getDescendants($child);
            $allChildren = array_merge($allChildren, $children, array($child));
        }

        return isset($allChildren) ? $allChildren : array();
    }

    /**
     * Gets elements by case insensitive tagname.
     *
     * @param  DOMDocument $dom
     * @param  string      $tag
     * @return DOMNodeList
     * @since  Method available since Release 3.4.0
     */
    protected static function getElementsByCaseInsensitiveTagName(DOMDocument $dom, $tag)
    {
        $elements = $dom->getElementsByTagName(strtolower($tag));

        if ($elements->length == 0) {
            $elements = $dom->getElementsByTagName(strtoupper($tag));
        }

        return $elements;
    }

    /**
     * Get the text value of this node's child text node.
     *
     * @param  DOMNode $node
     * @return string
     * @since  Method available since Release 3.3.0
     * @author Mike Naberezny <mike@maintainable.com>
     * @author Derek DeVries <derek@maintainable.com>
     */
    protected static function getNodeText(DOMNode $node)
    {
        if (!$node->childNodes instanceof DOMNodeList) {
            return '';
        }

        $result = '';

        foreach ($node->childNodes as $childNode) {
            if ($childNode->nodeType === XML_TEXT_NODE ||
                $childNode->nodeType === XML_CDATA_SECTION_NODE) {
                $result .= trim($childNode->data) . ' ';
            } else {
                $result .= self::getNodeText($childNode);
            }
        }

        return str_replace('  ', ' ', $result);
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.5.12
 */

/**
 * Windows utility for PHP sub-processes.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.5.12
 */
class PHPUnit_Util_PHP_Windows extends PHPUnit_Util_PHP
{
    /**
     * @var string
     */
    protected $tempFile;

    /**
     * @param resource $pipe
     * @since Method available since Release 3.5.12
     */
    protected function process($pipe, $job)
    {
        if (!($this->tempFile = tempnam(sys_get_temp_dir(), 'PHPUnit')) ||
            file_put_contents($this->tempFile, $job) === FALSE) {
            throw new PHPUnit_Framework_Exception(
              'Unable to write temporary files for process isolation.'
            );
        }

        fwrite(
          $pipe,
          "<?php require_once " . var_export($this->tempFile, TRUE) .  "; ?>"
        );
    }

    /**
     * @since Method available since Release 3.5.12
     */
    protected function cleanup()
    {
        unlink($this->tempFile);
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.5.12
 */

/**
 * Default utility for PHP sub-processes.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.5.12
 */
class PHPUnit_Util_PHP_Default extends PHPUnit_Util_PHP
{
    /**
     * @param resource $pipe
     * @since Method available since Release 3.5.12
     */
    protected function process($pipe, $job)
    {
        fwrite($pipe, $job);
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.4.0
 */

/**
 *
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.4.0
 */
class PHPUnit_Util_GlobalState
{
    /**
     * @var array
     */
    protected static $globals = array();

    /**
     * @var array
     */
    protected static $staticAttributes = array();

    /**
     * @var array
     */
    protected static $superGlobalArrays = array(
      '_ENV',
      '_POST',
      '_GET',
      '_COOKIE',
      '_SERVER',
      '_FILES',
      '_REQUEST'
    );

    /**
     * @var array
     */
    protected static $superGlobalArraysLong = array(
      'HTTP_ENV_VARS',
      'HTTP_POST_VARS',
      'HTTP_GET_VARS',
      'HTTP_COOKIE_VARS',
      'HTTP_SERVER_VARS',
      'HTTP_POST_FILES'
    );

    /**
     * @var array
     */
    protected static $phpunitFiles;

    public static function backupGlobals(array $blacklist)
    {
        self::$globals     = array();
        $superGlobalArrays = self::getSuperGlobalArrays();

        foreach ($superGlobalArrays as $superGlobalArray) {
            if (!in_array($superGlobalArray, $blacklist)) {
                self::backupSuperGlobalArray($superGlobalArray);
            }
        }

        foreach (array_keys($GLOBALS) as $key) {
            if ($key != 'GLOBALS' &&
                !in_array($key, $superGlobalArrays) &&
                !in_array($key, $blacklist) &&
                !$GLOBALS[$key] instanceof Closure) {
                self::$globals['GLOBALS'][$key] = serialize($GLOBALS[$key]);
            }
        }
    }

    public static function restoreGlobals(array $blacklist)
    {
        if (ini_get('register_long_arrays') == '1') {
            $superGlobalArrays = array_merge(
              self::$superGlobalArrays, self::$superGlobalArraysLong
            );
        } else {
            $superGlobalArrays = self::$superGlobalArrays;
        }

        foreach ($superGlobalArrays as $superGlobalArray) {
            if (!in_array($superGlobalArray, $blacklist)) {
                self::restoreSuperGlobalArray($superGlobalArray);
            }
        }

        foreach (array_keys($GLOBALS) as $key) {
            if ($key != 'GLOBALS' &&
                !in_array($key, $superGlobalArrays) &&
                !in_array($key, $blacklist)) {
                if (isset(self::$globals['GLOBALS'][$key])) {
                    $GLOBALS[$key] = unserialize(
                      self::$globals['GLOBALS'][$key]
                    );
                } else {
                    unset($GLOBALS[$key]);
                }
            }
        }

        self::$globals = array();
    }

    protected static function backupSuperGlobalArray($superGlobalArray)
    {
        self::$globals[$superGlobalArray] = array();

        if (isset($GLOBALS[$superGlobalArray]) &&
            is_array($GLOBALS[$superGlobalArray])) {
            foreach ($GLOBALS[$superGlobalArray] as $key => $value) {
                self::$globals[$superGlobalArray][$key] = serialize($value);
            }
        }
    }

    protected static function restoreSuperGlobalArray($superGlobalArray)
    {
        if (isset($GLOBALS[$superGlobalArray]) &&
            is_array($GLOBALS[$superGlobalArray]) &&
            isset(self::$globals[$superGlobalArray])) {
            $keys = array_keys(
              array_merge(
                $GLOBALS[$superGlobalArray], self::$globals[$superGlobalArray]
              )
            );

            foreach ($keys as $key) {
                if (isset(self::$globals[$superGlobalArray][$key])) {
                    $GLOBALS[$superGlobalArray][$key] = unserialize(
                      self::$globals[$superGlobalArray][$key]
                    );
                } else {
                    unset($GLOBALS[$superGlobalArray][$key]);
                }
            }
        }

        self::$globals[$superGlobalArray] = array();
    }

    public static function getIncludedFilesAsString()
    {
        $blacklist = self::phpunitFiles();
        $files     = get_included_files();
        $prefix    = FALSE;
        $result    = '';

        if (defined('__PHPUNIT_PHAR__')) {
            $prefix = 'phar://' . __PHPUNIT_PHAR__ . '/';
        }

        for ($i = count($files) - 1; $i > 0; $i--) {
            $file = $files[$i];

            if ($prefix !== FALSE && strpos($file, $prefix) === 0) {
                continue;
            }

            if (!isset($blacklist[$file]) && is_file($file)) {
                $result = 'require_once \'' . $file . "';\n" . $result;
            }
        }

        return $result;
    }

    public static function getConstantsAsString()
    {
        $constants = get_defined_constants(TRUE);
        $result    = '';

        if (isset($constants['user'])) {
            foreach ($constants['user'] as $name => $value) {
                $result .= sprintf(
                  'if (!defined(\'%s\')) define(\'%s\', %s);' . "\n",
                  $name,
                  $name,
                  self::exportVariable($value)
                );
            }
        }

        return $result;
    }

    public static function getGlobalsAsString()
    {
        $result            = '';
        $superGlobalArrays = self::getSuperGlobalArrays();

        foreach ($superGlobalArrays as $superGlobalArray) {
            if (isset($GLOBALS[$superGlobalArray]) &&
                is_array($GLOBALS[$superGlobalArray])) {
                foreach (array_keys($GLOBALS[$superGlobalArray]) as $key) {
                    if ($GLOBALS[$superGlobalArray][$key] instanceof Closure) {
                        continue;
                    }

                    $result .= sprintf(
                      '$GLOBALS[\'%s\'][\'%s\'] = %s;' . "\n",
                      $superGlobalArray,
                      $key,
                      self::exportVariable($GLOBALS[$superGlobalArray][$key])
                    );
                }
            }
        }

        $blacklist   = $superGlobalArrays;
        $blacklist[] = 'GLOBALS';
        $blacklist[] = '_PEAR_Config_instance';

        foreach (array_keys($GLOBALS) as $key) {
            if (!in_array($key, $blacklist) && !$GLOBALS[$key] instanceof Closure) {
                $result .= sprintf(
                  '$GLOBALS[\'%s\'] = %s;' . "\n",
                  $key,
                  self::exportVariable($GLOBALS[$key])
                );
            }
        }

        return $result;
    }

    protected static function getSuperGlobalArrays()
    {
        if (ini_get('register_long_arrays') == '1') {
            return array_merge(
              self::$superGlobalArrays, self::$superGlobalArraysLong
            );
        } else {
            return self::$superGlobalArrays;
        }
    }

    public static function backupStaticAttributes(array $blacklist)
    {
        self::$staticAttributes = array();
        $declaredClasses        = get_declared_classes();
        $declaredClassesNum     = count($declaredClasses);

        for ($i = $declaredClassesNum - 1; $i >= 0; $i--) {
            if (strpos($declaredClasses[$i], 'PHPUnit') !== 0 &&
                strpos($declaredClasses[$i], 'File_Iterator') !== 0 &&
                strpos($declaredClasses[$i], 'PHP_CodeCoverage') !== 0 &&
                strpos($declaredClasses[$i], 'PHP_Invoker') !== 0 &&
                strpos($declaredClasses[$i], 'PHP_Timer') !== 0 &&
                strpos($declaredClasses[$i], 'PHP_Token_Stream') !== 0 &&
                strpos($declaredClasses[$i], 'Symfony') !== 0 &&
                strpos($declaredClasses[$i], 'Text_Template') !== 0 &&
                !$declaredClasses[$i] instanceof PHPUnit_Framework_Test) {
                $class = new ReflectionClass($declaredClasses[$i]);

                if (!$class->isUserDefined()) {
                    break;
                }

                $backup = array();

                foreach ($class->getProperties() as $attribute) {
                    if ($attribute->isStatic()) {
                        $name = $attribute->getName();

                        if (!isset($blacklist[$declaredClasses[$i]]) ||
                           !in_array($name, $blacklist[$declaredClasses[$i]])) {
                            $attribute->setAccessible(TRUE);
                            $value = $attribute->getValue();

                            if (!$value instanceof Closure) {
                                $backup[$name] = serialize($value);
                            }
                        }
                    }
                }

                if (!empty($backup)) {
                    self::$staticAttributes[$declaredClasses[$i]] = $backup;
                }
            }
        }
    }

    public static function restoreStaticAttributes()
    {
        foreach (self::$staticAttributes as $className => $staticAttributes) {
            foreach ($staticAttributes as $name => $value) {
                $reflector = new ReflectionProperty($className, $name);
                $reflector->setAccessible(TRUE);
                $reflector->setValue(unserialize($value));
            }
        }

        self::$staticAttributes = array();
    }

    protected static function exportVariable($variable)
    {
        if (is_scalar($variable) || is_null($variable) ||
           (is_array($variable) && self::arrayOnlyContainsScalars($variable))) {
            return var_export($variable, TRUE);
        }

        return 'unserialize(\'' .
                str_replace("'", "\'", serialize($variable)) .
                '\')';
    }

    protected static function arrayOnlyContainsScalars(array $array)
    {
        $result = TRUE;

        foreach ($array as $element) {
            if (is_array($element)) {
                $result = self::arrayOnlyContainsScalars($element);
            }

            else if (!is_scalar($element) && !is_null($element)) {
                $result = FALSE;
            }

            if ($result === FALSE) {
                break;
            }
        }

        return $result;
    }

    /**
     * @return array
     * @since  Method available since Release 3.6.0
     */
    public static function phpunitFiles()
    {
        if (self::$phpunitFiles === NULL) {
            self::$phpunitFiles = array();
            self::addDirectoryContainingClassToPHPUnitFilesList('File_Iterator');
            self::addDirectoryContainingClassToPHPUnitFilesList('PHP_CodeCoverage');
            self::addDirectoryContainingClassToPHPUnitFilesList('PHP_Invoker');
            self::addDirectoryContainingClassToPHPUnitFilesList('PHP_Timer');
            self::addDirectoryContainingClassToPHPUnitFilesList('PHP_Token');
            self::addDirectoryContainingClassToPHPUnitFilesList('PHPUnit_Framework_TestCase', 2);
            self::addDirectoryContainingClassToPHPUnitFilesList('PHPUnit_Extensions_Database_TestCase', 2);
            self::addDirectoryContainingClassToPHPUnitFilesList('PHPUnit_Framework_MockObject_Generator', 2);
            self::addDirectoryContainingClassToPHPUnitFilesList('PHPUnit_Extensions_SeleniumTestCase', 2);
            self::addDirectoryContainingClassToPHPUnitFilesList('PHPUnit_Extensions_Story_TestCase', 2);
            self::addDirectoryContainingClassToPHPUnitFilesList('Text_Template');
        }

        return self::$phpunitFiles;
    }

    /**
     * @param string  $className
     * @param integer $parent
     * @since Method available since Release 3.7.2
     */
    protected static function addDirectoryContainingClassToPHPUnitFilesList($className, $parent = 1)
    {
        if (!class_exists($className)) {
            return;
        }

        $reflector = new ReflectionClass($className);
        $directory = $reflector->getFileName();

        for ($i = 0; $i < $parent; $i++) {
            $directory = dirname($directory);
        }

        $facade = new File_Iterator_Facade;

        foreach ($facade->getFilesAsArray($directory, '.php') as $file) {
            self::$phpunitFiles[$file] = TRUE;
        }
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.4.0
 */

/**
 * Factory for PHPUnit_Framework_Exception objects that are used to describe
 * invalid arguments passed to a function or method.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.4.0
 */
class PHPUnit_Util_InvalidArgumentHelper
{
    /**
     * @param integer $argument
     * @param string  $type
     * @param mixed   $value
     */
    public static function factory($argument, $type, $value = NULL)
    {
        $stack = debug_backtrace(FALSE);

        return new PHPUnit_Framework_Exception(
          sprintf(
            'Argument #%d%sof %s::%s() must be a %s',
            $argument,
            $value !== NULL ? ' (' . $value . ')' : ' ',
            $stack[1]['class'],
            $stack[1]['function'],
            $type
          )
        );
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.1.0
 */

/**
 * Iterator for test suites.
 *
 * @package    PHPUnit
 * @subpackage Util
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.1.0
 */
class PHPUnit_Util_TestSuiteIterator implements RecursiveIterator
{
    /**
     * @var    integer
     */
    protected $position;

    /**
     * @var    PHPUnit_Framework_Test[]
     */
    protected $tests;

    /**
     * Constructor.
     *
     * @param  PHPUnit_Framework_TestSuite $suite
     */
    public function __construct(PHPUnit_Framework_TestSuite $testSuite)
    {
        $this->tests = $testSuite->tests();
    }

    /**
     * Rewinds the Iterator to the first element.
     *
     */
    public function rewind()
    {
        $this->position = 0;
    }

    /**
     * Checks if there is a current element after calls to rewind() or next().
     *
     * @return boolean
     */
    public function valid()
    {
        return $this->position < count($this->tests);
    }

    /**
     * Returns the key of the current element.
     *
     * @return integer
     */
    public function key()
    {
        return $this->position;
    }

    /**
     * Returns the current element.
     *
     * @return PHPUnit_Framework_Test
     */
    public function current()
    {
        return $this->valid() ? $this->tests[$this->position] : NULL;
    }

    /**
     * Moves forward to next element.
     *
     */
    public function next()
    {
        $this->position++;
    }

    /**
     * Returns the sub iterator for the current element.
     *
     * @return PHPUnit_Util_TestSuiteIterator
     */
    public function getChildren()
    {
        return new PHPUnit_Util_TestSuiteIterator(
          $this->tests[$this->position]
        );
    }

    /**
     * Checks whether the current element has children.
     *
     * @return boolean
     */
    public function hasChildren()
    {
        return $this->tests[$this->position] instanceof PHPUnit_Framework_TestSuite;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.4.0
 */

/**
 * Exception for PHPUnit runtime errors.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.4.0
 */
class PHPUnit_Framework_Exception extends RuntimeException
{
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

/**
 * A TestCase defines the fixture to run multiple tests.
 *
 * To define a TestCase
 *
 *   1) Implement a subclass of PHPUnit_Framework_TestCase.
 *   2) Define instance variables that store the state of the fixture.
 *   3) Initialize the fixture state by overriding setUp().
 *   4) Clean-up after a test by overriding tearDown().
 *
 * Each test runs in its own fixture so there can be no side effects
 * among test runs.
 *
 * Here is an example:
 *
 * <code>
 * <?php
 * class MathTest extends PHPUnit_Framework_TestCase
 * {
 *     public $value1;
 *     public $value2;
 *
 *     protected function setUp()
 *     {
 *         $this->value1 = 2;
 *         $this->value2 = 3;
 *     }
 * }
 * ?>
 * </code>
 *
 * For each test implement a method which interacts with the fixture.
 * Verify the expected results with assertions specified by calling
 * assert with a boolean.
 *
 * <code>
 * <?php
 * public function testPass()
 * {
 *     $this->assertTrue($this->value1 + $this->value2 == 5);
 * }
 * ?>
 * </code>
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.0.0
 */
abstract class PHPUnit_Framework_TestCase extends PHPUnit_Framework_Assert implements PHPUnit_Framework_Test, PHPUnit_Framework_SelfDescribing
{
    /**
     * Enable or disable the backup and restoration of the $GLOBALS array.
     * Overwrite this attribute in a child class of TestCase.
     * Setting this attribute in setUp() has no effect!
     *
     * @var boolean
     */
    protected $backupGlobals = NULL;

    /**
     * @var array
     */
    protected $backupGlobalsBlacklist = array();

    /**
     * Enable or disable the backup and restoration of static attributes.
     * Overwrite this attribute in a child class of TestCase.
     * Setting this attribute in setUp() has no effect!
     *
     * @var boolean
     */
    protected $backupStaticAttributes = NULL;

    /**
     * @var array
     */
    protected $backupStaticAttributesBlacklist = array();

    /**
     * Whether or not this test is to be run in a separate PHP process.
     *
     * @var boolean
     */
    protected $runTestInSeparateProcess = NULL;

    /**
     * Whether or not this test should preserve the global state when
     * running in a separate PHP process.
     *
     * @var boolean
     */
    protected $preserveGlobalState = TRUE;

    /**
     * Whether or not this test is running in a separate PHP process.
     *
     * @var boolean
     */
    private $inIsolation = FALSE;

    /**
     * @var array
     */
    private $data = array();

    /**
     * @var string
     */
    private $dataName = '';

    /**
     * @var boolean
     */
    private $useErrorHandler = NULL;

    /**
     * @var boolean
     */
    private $useOutputBuffering = NULL;

    /**
     * The name of the expected Exception.
     *
     * @var mixed
     */
    private $expectedException = NULL;

    /**
     * The message of the expected Exception.
     *
     * @var string
     */
    private $expectedExceptionMessage = '';

    /**
     * The code of the expected Exception.
     *
     * @var integer
     */
    private $expectedExceptionCode;

    /**
     * The required preconditions for a test.
     *
     * @var array
     */
    private $required = array(
        'PHP' => NULL,
        'PHPUnit' => NULL,
        'functions' => array(),
        'extensions' => array()
    );

    /**
     * The name of the test case.
     *
     * @var string
     */
    private $name = NULL;

    /**
     * @var array
     */
    private $dependencies = array();

    /**
     * @var array
     */
    private $dependencyInput = array();

    /**
     * @var array
     */
    private $iniSettings = array();

    /**
     * @var array
     */
    private $locale = array();

    /**
     * @var array
     */
    private $mockObjects = array();

    /**
     * @var integer
     */
    private $status;

    /**
     * @var string
     */
    private $statusMessage = '';

    /**
     * @var integer
     */
    private $numAssertions = 0;

    /**
     * @var PHPUnit_Framework_TestResult
     */
    private $result;

    /**
     * @var mixed
     */
    private $testResult;

    /**
     * @var string
     */
    private $output = '';

    /**
     * @var string
     */
    private $outputExpectedRegex = NULL;

    /**
     * @var string
     */
    private $outputExpectedString = NULL;

    /**
     * @var bool
     */
    private $hasPerformedExpectationsOnOutput = FALSE;

    /**
     * @var mixed
     */
    private $outputCallback = FALSE;

    /**
     * @var boolean
     */
    private $outputBufferingActive = FALSE;

    /**
     * Constructs a test case with the given name.
     *
     * @param  string $name
     * @param  array  $data
     * @param  string $dataName
     */
    public function __construct($name = NULL, array $data = array(), $dataName = '')
    {
        if ($name !== NULL) {
            $this->setName($name);
        }

        $this->data     = $data;
        $this->dataName = $dataName;
    }

    /**
     * Returns a string representation of the test case.
     *
     * @return string
     */
    public function toString()
    {
        $class = new ReflectionClass($this);

        $buffer = sprintf(
          '%s::%s',

          $class->name,
          $this->getName(FALSE)
        );

        return $buffer . $this->getDataSetAsString();
    }

    /**
     * Counts the number of test cases executed by run(TestResult result).
     *
     * @return integer
     */
    public function count()
    {
        return 1;
    }

    /**
     * Returns the annotations for this test.
     *
     * @return array
     * @since Method available since Release 3.4.0
     */
    public function getAnnotations()
    {
        return PHPUnit_Util_Test::parseTestMethodAnnotations(
          get_class($this), $this->name
        );
    }

    /**
     * Gets the name of a TestCase.
     *
     * @param  boolean $withDataSet
     * @return string
     */
    public function getName($withDataSet = TRUE)
    {
        if ($withDataSet) {
            return $this->name . $this->getDataSetAsString(FALSE);
        } else {
            return $this->name;
        }
    }

    /**
     * Returns the size of the test.
     *
     * @return integer
     * @since  Method available since Release 3.6.0
     */
    public function getSize()
    {
        return PHPUnit_Util_Test::getSize(
          get_class($this), $this->getName(FALSE)
        );
    }

    /**
     * @return string
     * @since  Method available since Release 3.6.0
     */
    public function getActualOutput()
    {
        if (!$this->outputBufferingActive) {
            return $this->output;
        } else {
            return ob_get_contents();
        }
    }

    /**
     * @return string
     * @since  Method available since Release 3.6.0
     */
    public function hasOutput()
    {
        if (strlen($this->output) === 0) {
            return FALSE;
        }

        if ($this->outputExpectedString !== NULL ||
            $this->outputExpectedRegex  !== NULL ||
            $this->hasPerformedExpectationsOnOutput) {
            return FALSE;
        }

        return TRUE;
    }

    /**
     * @param string $expectedRegex
     * @since Method available since Release 3.6.0
     */
    public function expectOutputRegex($expectedRegex)
    {
        if ($this->outputExpectedString !== NULL) {
            throw new PHPUnit_Framework_Exception;
        }

        if (is_string($expectedRegex) || is_null($expectedRegex)) {
            $this->outputExpectedRegex = $expectedRegex;
        }
    }

    /**
     * @param string $expectedString
     * @since Method available since Release 3.6.0
     */
    public function expectOutputString($expectedString)
    {
        if ($this->outputExpectedRegex !== NULL) {
            throw new PHPUnit_Framework_Exception;
        }

        if (is_string($expectedString) || is_null($expectedString)) {
            $this->outputExpectedString = $expectedString;
        }
    }

    /**
     * @return bool
     * @since Method available since Release 3.6.5
     */
    public function hasPerformedExpectationsOnOutput()
    {
        return $this->hasPerformedExpectationsOnOutput;
    }

    /**
     * @return string
     * @since  Method available since Release 3.2.0
     */
    public function getExpectedException()
    {
        return $this->expectedException;
    }

    /**
     * @param  mixed   $exceptionName
     * @param  string  $exceptionMessage
     * @param  integer $exceptionCode
     * @since  Method available since Release 3.2.0
     */
    public function setExpectedException($exceptionName, $exceptionMessage = '', $exceptionCode = NULL)
    {
        $this->expectedException        = $exceptionName;
        $this->expectedExceptionMessage = $exceptionMessage;
        $this->expectedExceptionCode    = $exceptionCode;
    }

    /**
     * @since  Method available since Release 3.4.0
     */
    protected function setExpectedExceptionFromAnnotation()
    {
        try {
            $expectedException = PHPUnit_Util_Test::getExpectedException(
              get_class($this), $this->name
            );

            if ($expectedException !== FALSE) {
                $this->setExpectedException(
                  $expectedException['class'],
                  $expectedException['message'],
                  $expectedException['code']
                );
            }
        }

        catch (ReflectionException $e) {
        }
    }

    /**
     * @param boolean $useErrorHandler
     * @since Method available since Release 3.4.0
     */
    public function setUseErrorHandler($useErrorHandler)
    {
        $this->useErrorHandler = $useErrorHandler;
    }

    /**
     * @since Method available since Release 3.4.0
     */
    protected function setUseErrorHandlerFromAnnotation()
    {
        try {
            $useErrorHandler = PHPUnit_Util_Test::getErrorHandlerSettings(
              get_class($this), $this->name
            );

            if ($useErrorHandler !== NULL) {
                $this->setUseErrorHandler($useErrorHandler);
            }
        }

        catch (ReflectionException $e) {
        }
    }

    /**
     * @param boolean $useOutputBuffering
     * @since Method available since Release 3.4.0
     */
    public function setUseOutputBuffering($useOutputBuffering)
    {
        $this->useOutputBuffering = $useOutputBuffering;
    }

    /**
     * @since Method available since Release 3.4.0
     */
    protected function setUseOutputBufferingFromAnnotation()
    {
        try {
            $useOutputBuffering = PHPUnit_Util_Test::getOutputBufferingSettings(
              get_class($this), $this->name
            );

            if ($useOutputBuffering !== NULL) {
                $this->setUseOutputBuffering($useOutputBuffering);
            }
        }

        catch (ReflectionException $e) {
        }
    }

    /**
     * @since Method available since Release 3.6.0
     */
    protected function setRequirementsFromAnnotation()
    {
        try {
            $requirements = PHPUnit_Util_Test::getRequirements(
              get_class($this), $this->name
            );

            if (isset($requirements['PHP'])) {
                $this->required['PHP'] = $requirements['PHP'];
            }

            if (isset($requirements['PHPUnit'])) {
                $this->required['PHPUnit'] = $requirements['PHPUnit'];
            }

            if (isset($requirements['extensions'])) {
                $this->required['extensions'] = $requirements['extensions'];
            }

            if (isset($requirements['functions'])) {
                $this->required['functions'] = $requirements['functions'];
            }
        }

        catch (ReflectionException $e) {
        }
    }

    /**
     * @since Method available since Release 3.6.0
     */
    protected function checkRequirements()
    {
        $this->setRequirementsFromAnnotation();

        $missingRequirements = array();

        if ($this->required['PHP'] &&
            version_compare(PHP_VERSION, $this->required['PHP'], '<')) {
            $missingRequirements[] = sprintf(
              'PHP %s (or later) is required.',
              $this->required['PHP']
            );
        }

        $phpunitVersion = PHPUnit_Runner_Version::id();
        if ($this->required['PHPUnit'] &&
            version_compare($phpunitVersion, $this->required['PHPUnit'], '<')) {
            $missingRequirements[] = sprintf(
              'PHPUnit %s (or later) is required.',
              $this->required['PHPUnit']
            );
        }

        foreach ($this->required['functions'] as $requiredFunction) {
            if (!function_exists($requiredFunction)) {
                $missingRequirements[] = sprintf(
                  'Function %s is required.',
                  $requiredFunction
                );
            }
        }

        foreach ($this->required['extensions'] as $requiredExtension) {
            if (!extension_loaded($requiredExtension)) {
                $missingRequirements[] = sprintf(
                  'Extension %s is required.',
                  $requiredExtension
                );
            }
        }

        if ($missingRequirements) {
            $this->markTestSkipped(
              implode(
                PHP_EOL,
                $missingRequirements
              )
            );
        }
    }

    /**
     * Returns the status of this test.
     *
     * @return integer
     * @since  Method available since Release 3.1.0
     */
    public function getStatus()
    {
        return $this->status;
    }

    /**
     * Returns the status message of this test.
     *
     * @return string
     * @since  Method available since Release 3.3.0
     */
    public function getStatusMessage()
    {
        return $this->statusMessage;
    }

    /**
     * Returns whether or not this test has failed.
     *
     * @return boolean
     * @since  Method available since Release 3.0.0
     */
    public function hasFailed()
    {
        $status = $this->getStatus();

        return $status == PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE ||
               $status == PHPUnit_Runner_BaseTestRunner::STATUS_ERROR;
    }

    /**
     * Runs the test case and collects the results in a TestResult object.
     * If no TestResult object is passed a new one will be created.
     *
     * @param  PHPUnit_Framework_TestResult $result
     * @return PHPUnit_Framework_TestResult
     * @throws PHPUnit_Framework_Exception
     */
    public function run(PHPUnit_Framework_TestResult $result = NULL)
    {
        if ($result === NULL) {
            $result = $this->createResult();
        }

        if (!$this instanceof PHPUnit_Framework_Warning) {
            $this->setTestResultObject($result);
            $this->setUseErrorHandlerFromAnnotation();
            $this->setUseOutputBufferingFromAnnotation();
        }

        if ($this->useErrorHandler !== NULL) {
            $oldErrorHandlerSetting = $result->getConvertErrorsToExceptions();
            $result->convertErrorsToExceptions($this->useErrorHandler);
        }

        if (!$this instanceof PHPUnit_Framework_Warning && !$this->handleDependencies()) {
            return;
        }

        if ($this->runTestInSeparateProcess === TRUE &&
            $this->inIsolation !== TRUE &&
            !$this instanceof PHPUnit_Extensions_SeleniumTestCase &&
            !$this instanceof PHPUnit_Extensions_PhptTestCase) {
            $class = new ReflectionClass($this);

            $template = new Text_Template(
              sprintf(
                '%s%sProcess%sTestCaseMethod.tpl',

                __DIR__,
                DIRECTORY_SEPARATOR,
                DIRECTORY_SEPARATOR,
                DIRECTORY_SEPARATOR
              )
            );

            if ($this->preserveGlobalState) {
                $constants     = PHPUnit_Util_GlobalState::getConstantsAsString();
                $globals       = PHPUnit_Util_GlobalState::getGlobalsAsString();
                $includedFiles = PHPUnit_Util_GlobalState::getIncludedFilesAsString();
            } else {
                $constants     = '';
                $globals       = '';
                $includedFiles = '';
            }

            if ($result->getCollectCodeCoverageInformation()) {
                $coverage = 'TRUE';
            } else {
                $coverage = 'FALSE';
            }

            if ($result->isStrict()) {
                $strict = 'TRUE';
            } else {
                $strict = 'FALSE';
            }

            if (defined('PHPUNIT_COMPOSER_INSTALL')) {
                $composerAutoload = var_export(PHPUNIT_COMPOSER_INSTALL, TRUE);
            } else {
                $composerAutoload = '\'\'';
            }

            if (defined('__PHPUNIT_PHAR__')) {
                $phar = var_export(__PHPUNIT_PHAR__, TRUE);
            } else {
                $phar = '\'\'';
            }

            $data            = var_export(serialize($this->data), TRUE);
            $dependencyInput = var_export(serialize($this->dependencyInput), TRUE);
            $includePath     = var_export(get_include_path(), TRUE);
            // must do these fixes because TestCaseMethod.tpl has unserialize('{data}') in it, and we can't break BC
            // the lines above used to use addcslashes() rather than var_export(), which breaks null byte escape sequences
            $data            = "'." . $data . ".'";
            $dependencyInput = "'." . $dependencyInput . ".'";
            $includePath     = "'." . $includePath . ".'";

            $template->setVar(
              array(
                'composerAutoload'               => $composerAutoload,
                'phar'                           => $phar,
                'filename'                       => $class->getFileName(),
                'className'                      => $class->getName(),
                'methodName'                     => $this->name,
                'collectCodeCoverageInformation' => $coverage,
                'data'                           => $data,
                'dataName'                       => $this->dataName,
                'dependencyInput'                => $dependencyInput,
                'constants'                      => $constants,
                'globals'                        => $globals,
                'include_path'                   => $includePath,
                'included_files'                 => $includedFiles,
                'strict'                         => $strict
              )
            );

            $this->prepareTemplate($template);

            $php = PHPUnit_Util_PHP::factory();
            $php->runJob($template->render(), $this, $result);
        } else {
            $result->run($this);
        }

        if ($this->useErrorHandler !== NULL) {
            $result->convertErrorsToExceptions($oldErrorHandlerSetting);
        }

        $this->result = NULL;

        return $result;
    }

    /**
     * Runs the bare test sequence.
     */
    public function runBare()
    {
        $this->numAssertions = 0;

        // Backup the $GLOBALS array and static attributes.
        if ($this->runTestInSeparateProcess !== TRUE &&
            $this->inIsolation !== TRUE) {
            if ($this->backupGlobals === NULL ||
                $this->backupGlobals === TRUE) {
                PHPUnit_Util_GlobalState::backupGlobals(
                  $this->backupGlobalsBlacklist
                );
            }

            if ($this->backupStaticAttributes === TRUE) {
                PHPUnit_Util_GlobalState::backupStaticAttributes(
                  $this->backupStaticAttributesBlacklist
                );
            }
        }

        // Start output buffering.
        ob_start();
        $this->outputBufferingActive = TRUE;

        // Clean up stat cache.
        clearstatcache();

        // Backup the cwd
        $currentWorkingDirectory = getcwd();

        try {
            if ($this->inIsolation) {
                $this->setUpBeforeClass();
            }

            $this->setExpectedExceptionFromAnnotation();
            $this->setUp();
            $this->checkRequirements();
            $this->assertPreConditions();
            $this->testResult = $this->runTest();
            $this->verifyMockObjects();
            $this->assertPostConditions();
            $this->status = PHPUnit_Runner_BaseTestRunner::STATUS_PASSED;
        }

        catch (PHPUnit_Framework_IncompleteTest $e) {
            $this->status        = PHPUnit_Runner_BaseTestRunner::STATUS_INCOMPLETE;
            $this->statusMessage = $e->getMessage();
        }

        catch (PHPUnit_Framework_SkippedTest $e) {
            $this->status        = PHPUnit_Runner_BaseTestRunner::STATUS_SKIPPED;
            $this->statusMessage = $e->getMessage();
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            $this->status        = PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE;
            $this->statusMessage = $e->getMessage();
        }

        catch (Exception $e) {
            $this->status        = PHPUnit_Runner_BaseTestRunner::STATUS_ERROR;
            $this->statusMessage = $e->getMessage();
        }

        // Clean up the mock objects.
        $this->mockObjects = array();

        // Tear down the fixture. An exception raised in tearDown() will be
        // caught and passed on when no exception was raised before.
        try {
            $this->tearDown();

            if ($this->inIsolation) {
                $this->tearDownAfterClass();
            }
        }

        catch (Exception $_e) {
            if (!isset($e)) {
                $e = $_e;
            }
        }

        // Stop output buffering.
        if ($this->outputCallback === FALSE) {
            $this->output = ob_get_contents();
        } else {
            $this->output = call_user_func_array(
              $this->outputCallback, array(ob_get_contents())
            );
        }

        ob_end_clean();
        $this->outputBufferingActive = FALSE;

        // Clean up stat cache.
        clearstatcache();

        // Restore the cwd if it was changed by the test
        if ($currentWorkingDirectory != getcwd()) {
            chdir($currentWorkingDirectory);
        }

        // Restore the $GLOBALS array and static attributes.
        if ($this->runTestInSeparateProcess !== TRUE &&
            $this->inIsolation !== TRUE) {
            if ($this->backupGlobals === NULL ||
                $this->backupGlobals === TRUE) {
                PHPUnit_Util_GlobalState::restoreGlobals(
                   $this->backupGlobalsBlacklist
                );
            }

            if ($this->backupStaticAttributes === TRUE) {
                PHPUnit_Util_GlobalState::restoreStaticAttributes();
            }
        }

        // Clean up INI settings.
        foreach ($this->iniSettings as $varName => $oldValue) {
            ini_set($varName, $oldValue);
        }

        $this->iniSettings = array();

        // Clean up locale settings.
        foreach ($this->locale as $category => $locale) {
            setlocale($category, $locale);
        }

        // Perform assertion on output.
        if (!isset($e)) {
            try {
                if ($this->outputExpectedRegex !== NULL) {
                    $this->hasPerformedExpectationsOnOutput = TRUE;
                    $this->assertRegExp($this->outputExpectedRegex, $this->output);
                    $this->outputExpectedRegex = NULL;
                }

                else if ($this->outputExpectedString !== NULL) {
                    $this->hasPerformedExpectationsOnOutput = TRUE;
                    $this->assertEquals($this->outputExpectedString, $this->output);
                    $this->outputExpectedString = NULL;
                }
            }

            catch (Exception $_e) {
                $e = $_e;
            }
        }

        // Workaround for missing "finally".
        if (isset($e)) {
            $this->onNotSuccessfulTest($e);
        }
    }

    /**
     * Override to run the test and assert its state.
     *
     * @return mixed
     * @throws PHPUnit_Framework_Exception
     */
    protected function runTest()
    {
        if ($this->name === NULL) {
            throw new PHPUnit_Framework_Exception(
              'PHPUnit_Framework_TestCase::$name must not be NULL.'
            );
        }

        try {
            $class  = new ReflectionClass($this);
            $method = $class->getMethod($this->name);
        }

        catch (ReflectionException $e) {
            $this->fail($e->getMessage());
        }

        try {
            $testResult = $method->invokeArgs(
              $this, array_merge($this->data, $this->dependencyInput)
            );
        }

        catch (Exception $e) {
            $checkException = FALSE;

            if (is_string($this->expectedException)) {
                $checkException = TRUE;

                if ($e instanceof PHPUnit_Framework_Exception) {
                    $checkException = FALSE;
                }

                $reflector = new ReflectionClass($this->expectedException);

                if ($this->expectedException == 'PHPUnit_Framework_Exception' ||
                    $reflector->isSubclassOf('PHPUnit_Framework_Exception')) {
                    $checkException = TRUE;
                }
            }

            if ($checkException) {
                $this->assertThat(
                  $e,
                  new PHPUnit_Framework_Constraint_Exception(
                    $this->expectedException
                  )
                );

                if (is_string($this->expectedExceptionMessage) &&
                    !empty($this->expectedExceptionMessage)) {
                    $this->assertThat(
                      $e,
                      new PHPUnit_Framework_Constraint_ExceptionMessage(
                        $this->expectedExceptionMessage
                      )
                    );
                }

                if ($this->expectedExceptionCode !== NULL) {
                    $this->assertThat(
                      $e,
                      new PHPUnit_Framework_Constraint_ExceptionCode(
                        $this->expectedExceptionCode
                      )
                    );
                }

                return;
            } else {
                throw $e;
            }
        }

        if ($this->expectedException !== NULL) {
            $this->assertThat(
              NULL,
              new PHPUnit_Framework_Constraint_Exception(
                $this->expectedException
              )
            );
        }

        return $testResult;
    }

    /**
     * Verifies the mock object expectations.
     *
     * @since Method available since Release 3.5.0
     */
    protected function verifyMockObjects()
    {
        foreach ($this->mockObjects as $mockObject) {
            if ($mockObject->__phpunit_hasMatchers()) {
                $this->numAssertions++;
            }

            $mockObject->__phpunit_verify();
            $mockObject->__phpunit_cleanup();
        }
    }

    /**
     * Sets the name of a TestCase.
     *
     * @param  string
     */
    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * Sets the dependencies of a TestCase.
     *
     * @param  array $dependencies
     * @since  Method available since Release 3.4.0
     */
    public function setDependencies(array $dependencies)
    {
        $this->dependencies = $dependencies;
    }

    /**
     * Sets
     *
     * @param  array $dependencyInput
     * @since  Method available since Release 3.4.0
     */
    public function setDependencyInput(array $dependencyInput)
    {
        $this->dependencyInput = $dependencyInput;
    }

    /**
     * Calling this method in setUp() has no effect!
     *
     * @param  boolean $backupGlobals
     * @since  Method available since Release 3.3.0
     */
    public function setBackupGlobals($backupGlobals)
    {
        if (is_null($this->backupGlobals) && is_bool($backupGlobals)) {
            $this->backupGlobals = $backupGlobals;
        }
    }

    /**
     * Calling this method in setUp() has no effect!
     *
     * @param  boolean $backupStaticAttributes
     * @since  Method available since Release 3.4.0
     */
    public function setBackupStaticAttributes($backupStaticAttributes)
    {
        if (is_null($this->backupStaticAttributes) &&
            is_bool($backupStaticAttributes)) {
            $this->backupStaticAttributes = $backupStaticAttributes;
        }
    }

    /**
     * @param  boolean $runTestInSeparateProcess
     * @throws PHPUnit_Framework_Exception
     * @since  Method available since Release 3.4.0
     */
    public function setRunTestInSeparateProcess($runTestInSeparateProcess)
    {
        if (is_bool($runTestInSeparateProcess)) {
            if ($this->runTestInSeparateProcess === NULL) {
                $this->runTestInSeparateProcess = $runTestInSeparateProcess;
            }
        } else {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
        }
    }

    /**
     * @param  boolean $preserveGlobalState
     * @throws PHPUnit_Framework_Exception
     * @since  Method available since Release 3.4.0
     */
    public function setPreserveGlobalState($preserveGlobalState)
    {
        if (is_bool($preserveGlobalState)) {
            $this->preserveGlobalState = $preserveGlobalState;
        } else {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
        }
    }

    /**
     * @param  boolean $inIsolation
     * @throws PHPUnit_Framework_Exception
     * @since  Method available since Release 3.4.0
     */
    public function setInIsolation($inIsolation)
    {
        if (is_bool($inIsolation)) {
            $this->inIsolation = $inIsolation;
        } else {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
        }
    }

    /**
     * @return mixed
     * @since  Method available since Release 3.4.0
     */
    public function getResult()
    {
        return $this->testResult;
    }

    /**
     * @param  mixed $result
     * @since  Method available since Release 3.4.0
     */
    public function setResult($result)
    {
        $this->testResult = $result;
    }

    /**
     * @param  callable $callback
     * @throws PHPUnit_Framework_Exception
     * @since Method available since Release 3.6.0
     */
    public function setOutputCallback($callback)
    {
        if (!is_callable($callback)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'callback');
        }

        $this->outputCallback = $callback;
    }

    /**
     * @return PHPUnit_Framework_TestResult
     * @since  Method available since Release 3.5.7
     */
    public function getTestResultObject()
    {
        return $this->result;
    }

    /**
     * @param PHPUnit_Framework_TestResult $result
     * @since Method available since Release 3.6.0
     */
    public function setTestResultObject(PHPUnit_Framework_TestResult $result)
    {
        $this->result = $result;
    }

    /**
     * This method is a wrapper for the ini_set() function that automatically
     * resets the modified php.ini setting to its original value after the
     * test is run.
     *
     * @param  string  $varName
     * @param  string  $newValue
     * @throws PHPUnit_Framework_Exception
     * @since  Method available since Release 3.0.0
     */
    protected function iniSet($varName, $newValue)
    {
        if (!is_string($varName)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        $currentValue = ini_set($varName, $newValue);

        if ($currentValue !== FALSE) {
            $this->iniSettings[$varName] = $currentValue;
        } else {
            throw new PHPUnit_Framework_Exception(
              sprintf(
                'INI setting "%s" could not be set to "%s".',
                $varName,
                $newValue
              )
            );
        }
    }

    /**
     * This method is a wrapper for the setlocale() function that automatically
     * resets the locale to its original value after the test is run.
     *
     * @param  integer $category
     * @param  string  $locale
     * @throws PHPUnit_Framework_Exception
     * @since  Method available since Release 3.1.0
     */
    protected function setLocale()
    {
        $args = func_get_args();

        if (count($args) < 2) {
            throw new PHPUnit_Framework_Exception;
        }

        $category = $args[0];
        $locale   = $args[1];

        $categories = array(
          LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME
        );

        if (defined('LC_MESSAGES')) {
            $categories[] = LC_MESSAGES;
        }

        if (!in_array($category, $categories)) {
            throw new PHPUnit_Framework_Exception;
        }

        if (!is_array($locale) && !is_string($locale)) {
            throw new PHPUnit_Framework_Exception;
        }

        $this->locale[$category] = setlocale($category, NULL);

        $result = call_user_func_array( 'setlocale', $args );

        if ($result === FALSE) {
            throw new PHPUnit_Framework_Exception(
              'The locale functionality is not implemented on your platform, ' .
              'the specified locale does not exist or the category name is ' .
              'invalid.'
            );
        }
    }

    /**
     * Returns a mock object for the specified class.
     *
     * @param  string  $originalClassName
     * @param  array   $methods
     * @param  array   $arguments
     * @param  string  $mockClassName
     * @param  boolean $callOriginalConstructor
     * @param  boolean $callOriginalClone
     * @param  boolean $callAutoload
     * @param  boolean $cloneArguments
     * @return PHPUnit_Framework_MockObject_MockObject
     * @throws PHPUnit_Framework_Exception
     * @since  Method available since Release 3.0.0
     */
    public function getMock($originalClassName, $methods = array(), array $arguments = array(), $mockClassName = '', $callOriginalConstructor = TRUE, $callOriginalClone = TRUE, $callAutoload = TRUE, $cloneArguments = FALSE)
    {
        $mockObject = PHPUnit_Framework_MockObject_Generator::getMock(
          $originalClassName,
          $methods,
          $arguments,
          $mockClassName,
          $callOriginalConstructor,
          $callOriginalClone,
          $callAutoload,
          $cloneArguments
        );

        $this->mockObjects[] = $mockObject;

        return $mockObject;
    }

    /**
     * Returns a builder object to create mock objects using a fluent interface.
     *
     * @param  string $className
     * @return PHPUnit_Framework_MockObject_MockBuilder
     * @since  Method available since Release 3.5.0
     */
    public function getMockBuilder($className)
    {
        return new PHPUnit_Framework_MockObject_MockBuilder(
          $this, $className
        );
    }

    /**
     * Mocks the specified class and returns the name of the mocked class.
     *
     * @param  string  $originalClassName
     * @param  array   $methods
     * @param  array   $arguments
     * @param  string  $mockClassName
     * @param  boolean $callOriginalConstructor
     * @param  boolean $callOriginalClone
     * @param  boolean $callAutoload
     * @param  boolean $cloneArguments
     * @return string
     * @throws PHPUnit_Framework_Exception
     * @since  Method available since Release 3.5.0
     */
    protected function getMockClass($originalClassName, $methods = array(), array $arguments = array(), $mockClassName = '', $callOriginalConstructor = FALSE, $callOriginalClone = TRUE, $callAutoload = TRUE, $cloneArguments = FALSE)
    {
        $mock = $this->getMock(
          $originalClassName,
          $methods,
          $arguments,
          $mockClassName,
          $callOriginalConstructor,
          $callOriginalClone,
          $callAutoload,
          $cloneArguments
        );

        return get_class($mock);
    }

    /**
     * Returns a mock object for the specified abstract class with all abstract
     * methods of the class mocked. Concrete methods to mock can be specified with
     * the last parameter
     *
     * @param  string  $originalClassName
     * @param  array   $arguments
     * @param  string  $mockClassName
     * @param  boolean $callOriginalConstructor
     * @param  boolean $callOriginalClone
     * @param  boolean $callAutoload
     * @param  array   $mockedMethods
     * @param  boolean $cloneArguments
     * @return PHPUnit_Framework_MockObject_MockObject
     * @since  Method available since Release 3.4.0
     * @throws PHPUnit_Framework_Exception
     */
    public function getMockForAbstractClass($originalClassName, array $arguments = array(), $mockClassName = '', $callOriginalConstructor = TRUE, $callOriginalClone = TRUE, $callAutoload = TRUE, $mockedMethods = array(), $cloneArguments = FALSE)
    {
        $mockObject = PHPUnit_Framework_MockObject_Generator::getMockForAbstractClass(
          $originalClassName,
          $arguments,
          $mockClassName,
          $callOriginalConstructor,
          $callOriginalClone,
          $callAutoload,
          $mockedMethods,
          $cloneArguments
        );

        $this->mockObjects[] = $mockObject;

        return $mockObject;
    }

    /**
     * Returns a mock object based on the given WSDL file.
     *
     * @param  string  $wsdlFile
     * @param  string  $originalClassName
     * @param  string  $mockClassName
     * @param  array   $methods
     * @param  boolean $callOriginalConstructor
     * @return PHPUnit_Framework_MockObject_MockObject
     * @since  Method available since Release 3.4.0
     */
    protected function getMockFromWsdl($wsdlFile, $originalClassName = '', $mockClassName = '', array $methods = array(), $callOriginalConstructor = TRUE)
    {
        if ($originalClassName === '') {
            $originalClassName = str_replace(
              '.wsdl', '', basename($wsdlFile)
            );
        }

        if (!class_exists($originalClassName)) {
          eval(
            PHPUnit_Framework_MockObject_Generator::generateClassFromWsdl(
              $wsdlFile, $originalClassName, $methods
            )
          );
        }

        return $this->getMock(
          $originalClassName,
          $methods,
          array('', array()),
          $mockClassName,
          $callOriginalConstructor,
          FALSE,
          FALSE
        );
    }

    /**
     * Returns an object for the specified trait.
     *
     * @param  string  $traitName
     * @param  array   $arguments
     * @param  string  $traitClassName
     * @param  boolean $callOriginalConstructor
     * @param  boolean $callOriginalClone
     * @param  boolean $callAutoload
     * @param  boolean $cloneArguments
     * @return object
     * @since  Method available since Release 3.6.0
     * @throws PHPUnit_Framework_Exception
     */
    protected function getObjectForTrait($traitName, array $arguments = array(), $traitClassName = '', $callOriginalConstructor = TRUE, $callOriginalClone = TRUE, $callAutoload = TRUE, $cloneArguments = FALSE)
    {
        return PHPUnit_Framework_MockObject_Generator::getObjectForTrait(
          $traitName,
          $arguments,
          $traitClassName,
          $callOriginalConstructor,
          $callOriginalClone,
          $callAutoload,
          $cloneArguments
        );
    }

    /**
     * Adds a value to the assertion counter.
     *
     * @param integer $count
     * @since Method available since Release 3.3.3
     */
    public function addToAssertionCount($count)
    {
        $this->numAssertions += $count;
    }

    /**
     * Returns the number of assertions performed by this test.
     *
     * @return integer
     * @since  Method available since Release 3.3.0
     */
    public function getNumAssertions()
    {
        return $this->numAssertions;
    }

    /**
     * Returns a matcher that matches when the method it is evaluated for
     * is executed zero or more times.
     *
     * @return PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount
     * @since  Method available since Release 3.0.0
     */
    public static function any()
    {
        return new PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount;
    }

    /**
     * Returns a matcher that matches when the method it is evaluated for
     * is never executed.
     *
     * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount
     * @since  Method available since Release 3.0.0
     */
    public static function never()
    {
        return new PHPUnit_Framework_MockObject_Matcher_InvokedCount(0);
    }

    /**
     * Returns a matcher that matches when the method it is evaluated for
     * is executed at least once.
     *
     * @return PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastOnce
     * @since  Method available since Release 3.0.0
     */
    public static function atLeastOnce()
    {
        return new PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastOnce;
    }

    /**
     * Returns a matcher that matches when the method it is evaluated for
     * is executed exactly once.
     *
     * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount
     * @since  Method available since Release 3.0.0
     */
    public static function once()
    {
        return new PHPUnit_Framework_MockObject_Matcher_InvokedCount(1);
    }

    /**
     * Returns a matcher that matches when the method it is evaluated for
     * is executed exactly $count times.
     *
     * @param  integer $count
     * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount
     * @since  Method available since Release 3.0.0
     */
    public static function exactly($count)
    {
        return new PHPUnit_Framework_MockObject_Matcher_InvokedCount($count);
    }

    /**
     * Returns a matcher that matches when the method it is evaluated for
     * is invoked at the given $index.
     *
     * @param  integer $index
     * @return PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex
     * @since  Method available since Release 3.0.0
     */
    public static function at($index)
    {
        return new PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex($index);
    }

    /**
     *
     *
     * @param  mixed $value
     * @return PHPUnit_Framework_MockObject_Stub_Return
     * @since  Method available since Release 3.0.0
     */
    public static function returnValue($value)
    {
        return new PHPUnit_Framework_MockObject_Stub_Return($value);
    }

    /**
     *
     *
     * @param  array $valueMap
     * @return PHPUnit_Framework_MockObject_Stub_ReturnValueMap
     * @since  Method available since Release 3.6.0
     */
    public static function returnValueMap(array $valueMap)
    {
        return new PHPUnit_Framework_MockObject_Stub_ReturnValueMap($valueMap);
    }

    /**
     *
     *
     * @param  integer $argumentIndex
     * @return PHPUnit_Framework_MockObject_Stub_ReturnArgument
     * @since  Method available since Release 3.3.0
     */
    public static function returnArgument($argumentIndex)
    {
        return new PHPUnit_Framework_MockObject_Stub_ReturnArgument(
          $argumentIndex
        );
    }

    /**
     *
     *
     * @param  mixed $callback
     * @return PHPUnit_Framework_MockObject_Stub_ReturnCallback
     * @since  Method available since Release 3.3.0
     */
    public static function returnCallback($callback)
    {
        return new PHPUnit_Framework_MockObject_Stub_ReturnCallback($callback);
    }

    /**
     * Returns the current object.
     *
     * This method is useful when mocking a fluent interface.
     *
     * @return PHPUnit_Framework_MockObject_Stub_ReturnSelf
     * @since  Method available since Release 3.6.0
     */
    public static function returnSelf()
    {
        return new PHPUnit_Framework_MockObject_Stub_ReturnSelf();
    }

    /**
     *
     *
     * @param  Exception $exception
     * @return PHPUnit_Framework_MockObject_Stub_Exception
     * @since  Method available since Release 3.1.0
     */
    public static function throwException(Exception $exception)
    {
        return new PHPUnit_Framework_MockObject_Stub_Exception($exception);
    }

    /**
     *
     *
     * @param  mixed $value, ...
     * @return PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls
     * @since  Method available since Release 3.0.0
     */
    public static function onConsecutiveCalls()
    {
        $args = func_get_args();

        return new PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls($args);
    }

    /**
     * @param  mixed $data
     * @return string
     * @since  Method available since Release 3.2.1
     */
    protected function dataToString($data)
    {
        $result = array();

        // There seems to be no other way to check arrays for recursion
        // http://www.php.net/manual/en/language.types.array.php#73936
        preg_match_all('/\n            \[(\w+)\] => Array\s+\*RECURSION\*/', print_r($data, TRUE), $matches);
        $recursiveKeys = array_unique($matches[1]);

        // Convert to valid array keys
        // Numeric integer strings are automatically converted to integers
        // by PHP
        foreach ($recursiveKeys as $key => $recursiveKey) {
            if ((string)(integer)$recursiveKey === $recursiveKey) {
                $recursiveKeys[$key] = (integer)$recursiveKey;
            }
        }

        foreach ($data as $key => $_data) {
            if (in_array($key, $recursiveKeys, TRUE)) {
                $result[] = '*RECURSION*';
            }

            else if (is_array($_data)) {
                $result[] = 'array(' . $this->dataToString($_data) . ')';
            }

            else if (is_object($_data)) {
                $object = new ReflectionObject($_data);

                if ($object->hasMethod('__toString')) {
                    $result[] = (string)$_data;
                } else {
                    $result[] = get_class($_data);
                }
            }

            else if (is_resource($_data)) {
                $result[] = '<resource>';
            }

            else {
                $result[] = var_export($_data, TRUE);
            }
        }

        return join(', ', $result);
    }

    /**
     * Gets the data set description of a TestCase.
     *
     * @param  boolean $includeData
     * @return string
     * @since  Method available since Release 3.3.0
     */
    protected function getDataSetAsString($includeData = TRUE)
    {
        $buffer = '';

        if (!empty($this->data)) {
            if (is_int($this->dataName)) {
                $buffer .= sprintf(' with data set #%d', $this->dataName);
            } else {
                $buffer .= sprintf(' with data set "%s"', $this->dataName);
            }

            if ($includeData) {
                $buffer .= sprintf(' (%s)', $this->dataToString($this->data));
            }
        }

        return $buffer;
    }

    /**
     * Creates a default TestResult object.
     *
     * @return PHPUnit_Framework_TestResult
     */
    protected function createResult()
    {
        return new PHPUnit_Framework_TestResult;
    }

    /**
     * @since Method available since Release 3.5.4
     */
    protected function handleDependencies()
    {
        if (!empty($this->dependencies) && !$this->inIsolation) {
            $className  = get_class($this);
            $passed     = $this->result->passed();
            $passedKeys = array_keys($passed);
            $numKeys    = count($passedKeys);

            for ($i = 0; $i < $numKeys; $i++) {
                $pos = strpos($passedKeys[$i], ' with data set');

                if ($pos !== FALSE) {
                    $passedKeys[$i] = substr($passedKeys[$i], 0, $pos);
                }
            }

            $passedKeys = array_flip(array_unique($passedKeys));

            foreach ($this->dependencies as $dependency) {
                if (strpos($dependency, '::') === FALSE) {
                    $dependency = $className . '::' . $dependency;
                }

                if (!isset($passedKeys[$dependency])) {
                    $this->result->addError(
                      $this,
                      new PHPUnit_Framework_SkippedTestError(
                        sprintf(
                          'This test depends on "%s" to pass.', $dependency
                        )
                      ),
                      0
                    );

                    return FALSE;
                }

                if (isset($passed[$dependency])) {
                    if ($passed[$dependency]['size'] > $this->getSize()) {
                        $this->result->addError(
                          $this,
                          new PHPUnit_Framework_SkippedTestError(
                            'This test depends on a test that is larger than itself.'
                          ),
                          0
                        );

                        return FALSE;
                    }

                    $this->dependencyInput[] = $passed[$dependency]['result'];
                } else {
                    $this->dependencyInput[] = NULL;
                }
            }
        }

        return TRUE;
    }

    /**
     * This method is called before the first test of this test class is run.
     *
     * @since Method available since Release 3.4.0
     */
    public static function setUpBeforeClass()
    {
    }

    /**
     * Sets up the fixture, for example, open a network connection.
     * This method is called before a test is executed.
     *
     */
    protected function setUp()
    {
    }

    /**
     * Performs assertions shared by all tests of a test case.
     *
     * This method is called before the execution of a test starts
     * and after setUp() is called.
     *
     * @since  Method available since Release 3.2.8
     */
    protected function assertPreConditions()
    {
    }

    /**
     * Performs assertions shared by all tests of a test case.
     *
     * This method is called before the execution of a test ends
     * and before tearDown() is called.
     *
     * @since  Method available since Release 3.2.8
     */
    protected function assertPostConditions()
    {
    }

    /**
     * Tears down the fixture, for example, close a network connection.
     * This method is called after a test is executed.
     */
    protected function tearDown()
    {
    }

    /**
     * This method is called after the last test of this test class is run.
     *
     * @since Method available since Release 3.4.0
     */
    public static function tearDownAfterClass()
    {
    }

    /**
     * This method is called when a test method did not execute successfully.
     *
     * @param Exception $e
     * @since Method available since Release 3.4.0
     */
    protected function onNotSuccessfulTest(Exception $e)
    {
        throw $e;
    }

    /**
     * Performs custom preparations on the process isolation template.
     *
     * @param Text_Template $template
     * @since Method available since Release 3.4.0
     */
    protected function prepareTemplate(Text_Template $template)
    {
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.0
 */

/**
 * Compares arrays for equality.
 *
 * @package    PHPUnit
 * @subpackage Framework_Comparator
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.0
 */
class PHPUnit_Framework_Comparator_Array extends PHPUnit_Framework_Comparator
{
    /**
     * Returns whether the comparator can compare two values.
     *
     * @param  mixed $expected The first value to compare
     * @param  mixed $actual The second value to compare
     * @return boolean
     */
    public function accepts($expected, $actual)
    {
        return is_array($expected) && is_array($actual);
    }

    /**
     * Asserts that two values are equal.
     *
     * @param  mixed $expected The first value to compare
     * @param  mixed $actual The second value to compare
     * @param  float $delta The allowed numerical distance between two values to
     *                      consider them equal
     * @param  bool  $canonicalize If set to TRUE, arrays are sorted before
     *                             comparison
     * @param  bool  $ignoreCase If set to TRUE, upper- and lowercasing is
     *                           ignored when comparing string values
     * @throws PHPUnit_Framework_ComparisonFailure Thrown when the comparison
     *                           fails. Contains information about the
     *                           specific errors that lead to the failure.
     */
    public function assertEquals($expected, $actual, $delta = 0, $canonicalize = FALSE, $ignoreCase = FALSE, array &$processed = array())
    {
        if ($canonicalize) {
            sort($expected);
            sort($actual);
        }

        $remaining = $actual;
        $expString = $actString = "Array (\n";
        $equal = TRUE;

        foreach ($expected as $key => $value) {
            unset($remaining[$key]);

            if (!array_key_exists($key, $actual)) {
                $expString .= sprintf(
                  "    %s => %s\n",

                  PHPUnit_Util_Type::export($key),
                  PHPUnit_Util_Type::shortenedExport($value)
                );
                $equal = FALSE;
                continue;
            }

            try {
                $this->factory->getComparatorFor($value, $actual[$key])->assertEquals($value, $actual[$key], $delta, $canonicalize, $ignoreCase, $processed);
                $expString .= sprintf(
                  "    %s => %s\n",

                  PHPUnit_Util_Type::export($key),
                  PHPUnit_Util_Type::shortenedExport($value)
                );
                $actString .= sprintf(
                  "    %s => %s\n",

                  PHPUnit_Util_Type::export($key),
                  PHPUnit_Util_Type::shortenedExport($actual[$key])
                );
            }

            catch (PHPUnit_Framework_ComparisonFailure $e) {
                $expString .= sprintf(
                  "    %s => %s\n",

                  PHPUnit_Util_Type::export($key),
                  $e->getExpectedAsString()
                    ? $this->indent($e->getExpectedAsString())
                    : PHPUnit_Util_Type::shortenedExport($e->getExpected())
                );
                $actString .= sprintf(
                  "    %s => %s\n",

                  PHPUnit_Util_Type::export($key),
                  $e->getActualAsString()
                    ? $this->indent($e->getActualAsString())
                    : PHPUnit_Util_Type::shortenedExport($e->getActual())
                );
                $equal = FALSE;
            }
        }

        foreach ($remaining as $key => $value) {
            $actString .= sprintf(
              "    %s => %s\n",

              PHPUnit_Util_Type::export($key),
              PHPUnit_Util_Type::shortenedExport($value)
            );
            $equal = FALSE;
        }

        $expString .= ')';
        $actString .= ')';

        if (!$equal) {
            throw new PHPUnit_Framework_ComparisonFailure(
              $expected,
              $actual,
              $expString,
              $actString,
              FALSE,
             'Failed asserting that two arrays are equal.'
            );
        }
    }

    protected function indent($lines)
    {
        return trim(str_replace("\n", "\n    ", $lines));
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.0
 */

/**
 * Compares doubles for equality.
 *
 * @package    PHPUnit
 * @subpackage Framework_Comparator
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.0
 */
class PHPUnit_Framework_Comparator_Double extends PHPUnit_Framework_Comparator_Numeric
{
    /**
     * Smallest value available in PHP.
     *
     * @var float
     */
    const EPSILON = 0.0000000001;

    /**
     * Returns whether the comparator can compare two values.
     *
     * @param  mixed $expected The first value to compare
     * @param  mixed $actual The second value to compare
     * @return boolean
     */
    public function accepts($expected, $actual)
    {
        return (is_double($expected) || is_double($actual)) && is_numeric($expected) && is_numeric($actual);
    }

    /**
     * Asserts that two values are equal.
     *
     * @param  mixed $expected The first value to compare
     * @param  mixed $actual The second value to compare
     * @param  float $delta The allowed numerical distance between two values to
     *                      consider them equal
     * @param  bool  $canonicalize If set to TRUE, arrays are sorted before
     *                             comparison
     * @param  bool  $ignoreCase If set to TRUE, upper- and lowercasing is
     *                           ignored when comparing string values
     * @throws PHPUnit_Framework_ComparisonFailure Thrown when the comparison
     *                           fails. Contains information about the
     *                           specific errors that lead to the failure.
     */
    public function assertEquals($expected, $actual, $delta = 0, $canonicalize = FALSE, $ignoreCase = FALSE)
    {
        if ($delta == 0) {
            $delta = self::EPSILON;
        }

        parent::assertEquals($expected, $actual, $delta, $canonicalize, $ignoreCase);
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.0
 */

/**
 * Compares Exception instances for equality.
 *
 * @package    PHPUnit
 * @subpackage Framework_Comparator
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.0
 */
class PHPUnit_Framework_Comparator_Exception extends PHPUnit_Framework_Comparator_Object
{
    /**
     * Returns whether the comparator can compare two values.
     *
     * @param  mixed $expected The first value to compare
     * @param  mixed $actual The second value to compare
     * @return boolean
     */
    public function accepts($expected, $actual)
    {
        return $expected instanceof Exception && $actual instanceof Exception;
    }

    /**
     * Converts an object to an array containing all of its private, protected
     * and public properties.
     *
     * @param  object $object
     * @return array
     */
    protected function toArray($object)
    {
        $array = parent::toArray($object);

        unset(
            $array['file'],
            $array['line'],
            $array['trace'],
            $array['string'], // some internal property of Exception
            $array['xdebug_message'] // some internal property added by XDebug
        );

        return $array;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.0
 */

/**
 * Compares PHPUnit_Framework_MockObject_MockObject instances for equality.
 *
 * @package    PHPUnit
 * @subpackage Framework_Comparator
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.0
 */
class PHPUnit_Framework_Comparator_MockObject extends PHPUnit_Framework_Comparator_Object
{
    /**
     * Returns whether the comparator can compare two values.
     *
     * @param  mixed $expected The first value to compare
     * @param  mixed $actual The second value to compare
     * @return boolean
     */
    public function accepts($expected, $actual)
    {
        return $expected instanceof PHPUnit_Framework_MockObject_MockObject && $actual instanceof PHPUnit_Framework_MockObject_MockObject;
    }

    /**
     * Converts an object to an array containing all of its private, protected
     * and public properties.
     *
     * @param  object $object
     * @return array
     */
    protected function toArray($object)
    {
        $array = parent::toArray($object);

        unset($array['__phpunit_invocationMocker']);

        return $array;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.0
 */

/**
 * Compares SplObjectStorage instances for equality.
 *
 * @package    PHPUnit
 * @subpackage Framework_Comparator
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.0
 */
class PHPUnit_Framework_Comparator_SplObjectStorage extends PHPUnit_Framework_Comparator
{
    /**
     * Returns whether the comparator can compare two values.
     *
     * @param  mixed $expected The first value to compare
     * @param  mixed $actual The second value to compare
     * @return boolean
     */
    public function accepts($expected, $actual)
    {
        return $expected instanceof SplObjectStorage && $actual instanceof SplObjectStorage;
    }

    /**
     * Asserts that two values are equal.
     *
     * @param  mixed $expected The first value to compare
     * @param  mixed $actual The second value to compare
     * @param  float $delta The allowed numerical distance between two values to
     *                      consider them equal
     * @param  bool  $canonicalize If set to TRUE, arrays are sorted before
     *                             comparison
     * @param  bool  $ignoreCase If set to TRUE, upper- and lowercasing is
     *                           ignored when comparing string values
     * @throws PHPUnit_Framework_ComparisonFailure Thrown when the comparison
     *                           fails. Contains information about the
     *                           specific errors that lead to the failure.
     */
    public function assertEquals($expected, $actual, $delta = 0, $canonicalize = FALSE, $ignoreCase = FALSE)
    {
        foreach ($actual as $object) {
            if (!$expected->contains($object)) {
                throw new PHPUnit_Framework_ComparisonFailure(
                  $expected,
                  $actual,
                  PHPUnit_Util_Type::export($expected),
                  PHPUnit_Util_Type::export($actual),
                  FALSE,
                  'Failed asserting that two objects are equal.'
                );
            }
        }

        foreach ($expected as $object) {
            if (!$actual->contains($object)) {
                throw new PHPUnit_Framework_ComparisonFailure(
                  $expected,
                  $actual,
                  PHPUnit_Util_Type::export($expected),
                  PHPUnit_Util_Type::export($actual),
                  FALSE,
                  'Failed asserting that two objects are equal.'
                );
            }
        }
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.0
 */

/**
 * Compares scalar or NULL values for equality.
 *
 * @package    PHPUnit
 * @subpackage Framework_Comparator
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.0
 */
class PHPUnit_Framework_Comparator_Scalar extends PHPUnit_Framework_Comparator
{
    /**
     * Returns whether the comparator can compare two values.
     *
     * @param  mixed $expected The first value to compare
     * @param  mixed $actual The second value to compare
     * @return boolean
     * @since  Method available since Release 3.6.0
     */
    public function accepts($expected, $actual)
    {
        return ((is_scalar($expected) XOR NULL === $expected) &&
                 (is_scalar($actual) XOR NULL === $actual))
          // allow comparison between strings and objects featuring __toString()
          || (is_string($expected) && is_object($actual) && method_exists($actual, '__toString'))
          || (is_object($expected) && method_exists($expected, '__toString') && is_string($actual));
    }

    /**
     * Asserts that two values are equal.
     *
     * @param  mixed $expected The first value to compare
     * @param  mixed $actual The second value to compare
     * @param  float $delta The allowed numerical distance between two values to
     *                      consider them equal
     * @param  bool  $canonicalize If set to TRUE, arrays are sorted before
     *                             comparison
     * @param  bool  $ignoreCase If set to TRUE, upper- and lowercasing is
     *                           ignored when comparing string values
     * @throws PHPUnit_Framework_ComparisonFailure Thrown when the comparison
     *                           fails. Contains information about the
     *                           specific errors that lead to the failure.
     */
    public function assertEquals($expected, $actual, $delta = 0, $canonicalize = FALSE, $ignoreCase = FALSE)
    {
        $expectedToCompare = $expected;
        $actualToCompare = $actual;

        // always compare as strings to avoid strange behaviour
        // otherwise 0 == 'Foobar'
        if (is_string($expected) || is_string($actual)) {
            $expectedToCompare = (string)$expectedToCompare;
            $actualToCompare = (string)$actualToCompare;

            if ($ignoreCase) {
                $expectedToCompare = strtolower($expectedToCompare);
                $actualToCompare = strtolower($actualToCompare);
            }
        }

        if ($expectedToCompare != $actualToCompare) {
            if (is_string($expected) && is_string($actual)) {
                throw new PHPUnit_Framework_ComparisonFailure(
                  $expected,
                  $actual,
                  PHPUnit_Util_Type::export($expected),
                  PHPUnit_Util_Type::export($actual),
                  FALSE,
                  'Failed asserting that two strings are equal.'
                );
            }

            throw new PHPUnit_Framework_ComparisonFailure(
              $expected,
              $actual,
              // no diff is required
              '',
              '',
              FALSE,
              sprintf(
                'Failed asserting that %s matches expected %s.',

                PHPUnit_Util_Type::export($actual),
                PHPUnit_Util_Type::export($expected)
              )
            );
        }
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.0
 */

/**
 * Compares objects for equality.
 *
 * @package    PHPUnit
 * @subpackage Framework_Comparator
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.0
 */
class PHPUnit_Framework_Comparator_Object extends PHPUnit_Framework_Comparator_Array
{
    /**
     * Returns whether the comparator can compare two values.
     *
     * @param  mixed $expected The first value to compare
     * @param  mixed $actual The second value to compare
     * @return boolean
     */
    public function accepts($expected, $actual)
    {
        return is_object($expected) && is_object($actual);
    }

    /**
     * Asserts that two values are equal.
     *
     * @param  mixed $expected The first value to compare
     * @param  mixed $actual The second value to compare
     * @param  float $delta The allowed numerical distance between two values to
     *                      consider them equal
     * @param  bool  $canonicalize If set to TRUE, arrays are sorted before
     *                             comparison
     * @param  bool  $ignoreCase If set to TRUE, upper- and lowercasing is
     *                           ignored when comparing string values
     * @throws PHPUnit_Framework_ComparisonFailure Thrown when the comparison
     *                           fails. Contains information about the
     *                           specific errors that lead to the failure.
     */
    public function assertEquals($expected, $actual, $delta = 0, $canonicalize = FALSE, $ignoreCase = FALSE, array &$processed = array())
    {
        if (get_class($actual) !== get_class($expected)) {
            throw new PHPUnit_Framework_ComparisonFailure(
              $expected,
              $actual,
              PHPUnit_Util_Type::export($expected),
              PHPUnit_Util_Type::export($actual),
              FALSE,
              sprintf(
                '%s is not instance of expected class "%s".',

                PHPUnit_Util_Type::export($actual),
                get_class($expected)
              )
            );
        }

        // don't compare twice to allow for cyclic dependencies
        if (in_array(array($actual, $expected), $processed, TRUE) ||
            in_array(array($expected, $actual), $processed, TRUE)) {
            return;
        }

        $processed[] = array($actual, $expected);

        // don't compare objects if they are identical
        // this helps to avoid the error "maximum function nesting level reached"
        // CAUTION: this conditional clause is not tested
        if ($actual !== $expected) {
            try {
                parent::assertEquals($this->toArray($expected), $this->toArray($actual), $delta, $canonicalize, $ignoreCase, $processed);
            }

            catch (PHPUnit_Framework_ComparisonFailure $e) {
                throw new PHPUnit_Framework_ComparisonFailure(
                  $expected,
                  $actual,
                  // replace "Array" with "MyClass object"
                  substr_replace($e->getExpectedAsString(), get_class($expected) . ' Object', 0, 5),
                  substr_replace($e->getActualAsString(), get_class($actual) . ' Object', 0, 5),
                  FALSE,
                  'Failed asserting that two objects are equal.'
                );
            }
        }
    }

    /**
     * Converts an object to an array containing all of its private, protected
     * and public properties.
     *
     * @param  object $object
     * @return array
     */
    protected function toArray($object)
    {
        return PHPUnit_Util_Type::toArray($object);
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.0
 */

/**
 * Compares values for type equality.
 *
 * @package    PHPUnit
 * @subpackage Framework_Comparator
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.0
 */
class PHPUnit_Framework_Comparator_Type extends PHPUnit_Framework_Comparator
{
    /**
     * Returns whether the comparator can compare two values.
     *
     * @param  mixed $expected The first value to compare
     * @param  mixed $actual The second value to compare
     * @return boolean
     */
    public function accepts($expected, $actual)
    {
        return TRUE;
    }

    /**
     * Asserts that two values are equal.
     *
     * @param  mixed $expected The first value to compare
     * @param  mixed $actual The second value to compare
     * @param  float $delta The allowed numerical distance between two values to
     *                      consider them equal
     * @param  bool  $canonicalize If set to TRUE, arrays are sorted before
     *                             comparison
     * @param  bool  $ignoreCase If set to TRUE, upper- and lowercasing is
     *                           ignored when comparing string values
     * @throws PHPUnit_Framework_ComparisonFailure Thrown when the comparison
     *                           fails. Contains information about the
     *                           specific errors that lead to the failure.
     */
    public function assertEquals($expected, $actual, $delta = 0, $canonicalize = FALSE, $ignoreCase = FALSE)
    {
        if (gettype($expected) != gettype($actual)) {
            throw new PHPUnit_Framework_ComparisonFailure(
              $expected,
              $actual,
              // we don't need a diff
              '',
              '',
              FALSE,
              sprintf(
                '%s does not match expected type "%s".',

                PHPUnit_Util_Type::shortenedExport($actual),
                gettype($expected)
              )
            );
        }
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.0
 */

/**
 * Compares resources for equality.
 *
 * @package    PHPUnit
 * @subpackage Framework_Comparator
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.0
 */
class PHPUnit_Framework_Comparator_Resource extends PHPUnit_Framework_Comparator
{
    /**
     * Returns whether the comparator can compare two values.
     *
     * @param  mixed $expected The first value to compare
     * @param  mixed $actual The second value to compare
     * @return boolean
     */
    public function accepts($expected, $actual)
    {
        return is_resource($expected) && is_resource($actual);
    }

    /**
     * Asserts that two values are equal.
     *
     * @param  mixed $expected The first value to compare
     * @param  mixed $actual The second value to compare
     * @param  float $delta The allowed numerical distance between two values to
     *                      consider them equal
     * @param  bool  $canonicalize If set to TRUE, arrays are sorted before
     *                             comparison
     * @param  bool  $ignoreCase If set to TRUE, upper- and lowercasing is
     *                           ignored when comparing string values
     * @throws PHPUnit_Framework_ComparisonFailure Thrown when the comparison
     *                           fails. Contains information about the
     *                           specific errors that lead to the failure.
     */
    public function assertEquals($expected, $actual, $delta = 0, $canonicalize = FALSE, $ignoreCase = FALSE)
    {
        if ($actual != $expected) {
            throw new PHPUnit_Framework_ComparisonFailure(
              $expected,
              $actual,
              PHPUnit_Util_Type::export($expected),
              PHPUnit_Util_Type::export($actual)
            );
        }
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.0
 */

/**
 * Compares numerical values for equality.
 *
 * @package    PHPUnit
 * @subpackage Framework_Comparator
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @author     Alexander <iam.asm89@gmail.com>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.0
 */
class PHPUnit_Framework_Comparator_Numeric extends PHPUnit_Framework_Comparator_Scalar
{
    /**
     * Returns whether the comparator can compare two values.
     *
     * @param  mixed $expected The first value to compare
     * @param  mixed $actual The second value to compare
     * @return boolean
     */
    public function accepts($expected, $actual)
    {
        // all numerical values, but not if one of them is a double
        return is_numeric($expected) && is_numeric($actual) && !(is_double($expected) || is_double($actual));
    }

    /**
     * Asserts that two values are equal.
     *
     * @param  mixed $expected The first value to compare
     * @param  mixed $actual The second value to compare
     * @param  float $delta The allowed numerical distance between two values to
     *                      consider them equal
     * @param  bool  $canonicalize If set to TRUE, arrays are sorted before
     *                             comparison
     * @param  bool  $ignoreCase If set to TRUE, upper- and lowercasing is
     *                           ignored when comparing string values
     * @throws PHPUnit_Framework_ComparisonFailure Thrown when the comparison
     *                           fails. Contains information about the
     *                           specific errors that lead to the failure.
     */
    public function assertEquals($expected, $actual, $delta = 0, $canonicalize = FALSE, $ignoreCase = FALSE)
    {
        if (is_infinite($actual) && is_infinite($expected)) {
            return;
        }

        if ((is_infinite($actual) XOR is_infinite($expected)) ||
            (is_nan($actual) OR is_nan($expected)) ||
            abs($actual - $expected) > $delta) {
            throw new PHPUnit_Framework_ComparisonFailure(
              $expected,
              $actual,
              '',
              '',
              FALSE,
              sprintf(
                'Failed asserting that %s matches expected %s.',

                PHPUnit_Util_Type::export($actual),
                PHPUnit_Util_Type::export($expected)
              )
            );
        }
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.0
 */

/**
 * Compares DOMDocument instances for equality.
 *
 * @package    PHPUnit
 * @subpackage Framework_Comparator
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.0
 */
class PHPUnit_Framework_Comparator_DOMDocument extends PHPUnit_Framework_Comparator_Object
{
    /**
     * Returns whether the comparator can compare two values.
     *
     * @param  mixed $expected The first value to compare
     * @param  mixed $actual The second value to compare
     * @return boolean
     */
    public function accepts($expected, $actual)
    {
        return $expected instanceof DOMDocument && $actual instanceof DOMDocument;
    }

    /**
     * Asserts that two values are equal.
     *
     * @param  mixed $expected The first value to compare
     * @param  mixed $actual The second value to compare
     * @param  float $delta The allowed numerical distance between two values to
     *                      consider them equal
     * @param  bool  $canonicalize If set to TRUE, arrays are sorted before
     *                             comparison
     * @param  bool  $ignoreCase If set to TRUE, upper- and lowercasing is
     *                           ignored when comparing string values
     * @throws PHPUnit_Framework_ComparisonFailure Thrown when the comparison
     *                           fails. Contains information about the
     *                           specific errors that lead to the failure.
     */
    public function assertEquals($expected, $actual, $delta = 0, $canonicalize = FALSE, $ignoreCase = FALSE)
    {
        if ($expected->C14N() !== $actual->C14N()) {
            throw new PHPUnit_Framework_ComparisonFailure(
              $expected,
              $actual,
              $this->domToText($expected),
              $this->domToText($actual),
              FALSE,
              'Failed asserting that two DOM documents are equal.'
            );
        }
    }

    /**
     * Returns the normalized, whitespace-cleaned, and indented textual
     * representation of a DOMDocument.
     *
     * @param DOMDocument $document
     * @return string
     */
    protected function domToText(DOMDocument $document)
    {
        $document->formatOutput = TRUE;
        $document->normalizeDocument();

        return $document->saveXML();
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.2.0
 */

/**
 * Wrapper for PHP errors.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.2.0
 */
class PHPUnit_Framework_Error extends Exception
{
    /**
     * Constructor.
     *
     * @param  string     $message
     * @param  integer    $code
     * @param  string     $file
     * @param  integer    $line
     * @param  Exception  $previous
     */
    public function __construct($message, $code, $file, $line, Exception $previous = NULL)
    {
        parent::__construct($message, $code, $previous);

        $this->file  = $file;
        $this->line  = $line;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * Extension to PHPUnit_Framework_AssertionFailedError to mark the special
 * case of a skipped test.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class PHPUnit_Framework_SkippedTestError extends PHPUnit_Framework_AssertionFailedError implements PHPUnit_Framework_SkippedTest
{
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.5.0
 */{functions}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.5.0
 */

/**
 * Returns a matcher that matches when the method it is evaluated for
 * is executed zero or more times.
 *
 * @return PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount
 * @since  Method available since Release 3.0.0
 */
function any()
{
    return call_user_func_array(
      'PHPUnit_Framework_TestCase::any',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_IsAnything matcher object.
 *
 * @return PHPUnit_Framework_Constraint_IsAnything
 * @since  Method available since Release 3.0.0
 */
function anything()
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::anything',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_ArrayHasKey matcher object.
 *
 * @param  mixed $key
 * @return PHPUnit_Framework_Constraint_ArrayHasKey
 * @since  Method available since Release 3.0.0
 */
function arrayHasKey($key)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::arrayHasKey',
      func_get_args()
    );
}

/**
 * Asserts that an array has a specified key.
 *
 * @param  mixed  $key
 * @param  array|ArrayAccess  $array
 * @param  string $message
 * @since  Method available since Release 3.0.0
 */
function assertArrayHasKey($key, $array, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertArrayHasKey',
      func_get_args()
    );
}

/**
 * Asserts that an array does not have a specified key.
 *
 * @param  mixed  $key
 * @param  array|ArrayAccess  $array
 * @param  string $message
 * @since  Method available since Release 3.0.0
 */
function assertArrayNotHasKey($key, $array, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertArrayNotHasKey',
      func_get_args()
    );
}

/**
 * Asserts that a haystack that is stored in a static attribute of a class
 * or an attribute of an object contains a needle.
 *
 * @param  mixed   $needle
 * @param  string  $haystackAttributeName
 * @param  mixed   $haystackClassOrObject
 * @param  string  $message
 * @param  boolean $ignoreCase
 * @param  boolean $checkForObjectIdentity
 * @since  Method available since Release 3.0.0
 */
function assertAttributeContains($needle, $haystackAttributeName, $haystackClassOrObject, $message = '', $ignoreCase = FALSE, $checkForObjectIdentity = TRUE)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertAttributeContains',
      func_get_args()
    );
}

/**
 * Asserts that a haystack that is stored in a static attribute of a class
 * or an attribute of an object contains only values of a given type.
 *
 * @param  string  $type
 * @param  string  $haystackAttributeName
 * @param  mixed   $haystackClassOrObject
 * @param  boolean $isNativeType
 * @param  string  $message
 * @since  Method available since Release 3.1.4
 */
function assertAttributeContainsOnly($type, $haystackAttributeName, $haystackClassOrObject, $isNativeType = NULL, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertAttributeContainsOnly',
      func_get_args()
    );
}

/**
 * Asserts the number of elements of an array, Countable or Iterator
 * that is stored in an attribute.
 *
 * @param integer $expectedCount
 * @param string  $haystackAttributeName
 * @param mixed   $haystackClassOrObject
 * @param string  $message
 * @since Method available since Release 3.6.0
 */
function assertAttributeCount($expectedCount, $haystackAttributeName, $haystackClassOrObject, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertAttributeCount',
      func_get_args()
    );
}

/**
 * Asserts that a static attribute of a class or an attribute of an object
 * is empty.
 *
 * @param string $haystackAttributeName
 * @param mixed  $haystackClassOrObject
 * @param string $message
 * @since Method available since Release 3.5.0
 */
function assertAttributeEmpty($haystackAttributeName, $haystackClassOrObject, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertAttributeEmpty',
      func_get_args()
    );
}

/**
 * Asserts that a variable is equal to an attribute of an object.
 *
 * @param  mixed   $expected
 * @param  string  $actualAttributeName
 * @param  string  $actualClassOrObject
 * @param  string  $message
 * @param  float   $delta
 * @param  integer $maxDepth
 * @param  boolean $canonicalize
 * @param  boolean $ignoreCase
 */
function assertAttributeEquals($expected, $actualAttributeName, $actualClassOrObject, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertAttributeEquals',
      func_get_args()
    );
}

/**
 * Asserts that an attribute is greater than another value.
 *
 * @param  mixed   $expected
 * @param  string  $actualAttributeName
 * @param  string  $actualClassOrObject
 * @param  string  $message
 * @since  Method available since Release 3.1.0
 */
function assertAttributeGreaterThan($expected, $actualAttributeName, $actualClassOrObject, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertAttributeGreaterThan',
      func_get_args()
    );
}

/**
 * Asserts that an attribute is greater than or equal to another value.
 *
 * @param  mixed   $expected
 * @param  string  $actualAttributeName
 * @param  string  $actualClassOrObject
 * @param  string  $message
 * @since  Method available since Release 3.1.0
 */
function assertAttributeGreaterThanOrEqual($expected, $actualAttributeName, $actualClassOrObject, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertAttributeGreaterThanOrEqual',
      func_get_args()
    );
}

/**
 * Asserts that an attribute is of a given type.
 *
 * @param string $expected
 * @param string $attributeName
 * @param mixed  $classOrObject
 * @param string $message
 * @since Method available since Release 3.5.0
 */
function assertAttributeInstanceOf($expected, $attributeName, $classOrObject, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertAttributeInstanceOf',
      func_get_args()
    );
}

/**
 * Asserts that an attribute is of a given type.
 *
 * @param string $expected
 * @param string $attributeName
 * @param mixed  $classOrObject
 * @param string $message
 * @since Method available since Release 3.5.0
 */
function assertAttributeInternalType($expected, $attributeName, $classOrObject, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertAttributeInternalType',
      func_get_args()
    );
}

/**
 * Asserts that an attribute is smaller than another value.
 *
 * @param  mixed   $expected
 * @param  string  $actualAttributeName
 * @param  string  $actualClassOrObject
 * @param  string  $message
 * @since  Method available since Release 3.1.0
 */
function assertAttributeLessThan($expected, $actualAttributeName, $actualClassOrObject, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertAttributeLessThan',
      func_get_args()
    );
}

/**
 * Asserts that an attribute is smaller than or equal to another value.
 *
 * @param  mixed   $expected
 * @param  string  $actualAttributeName
 * @param  string  $actualClassOrObject
 * @param  string  $message
 * @since  Method available since Release 3.1.0
 */
function assertAttributeLessThanOrEqual($expected, $actualAttributeName, $actualClassOrObject, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertAttributeLessThanOrEqual',
      func_get_args()
    );
}

/**
 * Asserts that a haystack that is stored in a static attribute of a class
 * or an attribute of an object does not contain a needle.
 *
 * @param  mixed   $needle
 * @param  string  $haystackAttributeName
 * @param  mixed   $haystackClassOrObject
 * @param  string  $message
 * @param  boolean $ignoreCase
 * @param  boolean $checkForObjectIdentity
 * @since  Method available since Release 3.0.0
 */
function assertAttributeNotContains($needle, $haystackAttributeName, $haystackClassOrObject, $message = '', $ignoreCase = FALSE, $checkForObjectIdentity = TRUE)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertAttributeNotContains',
      func_get_args()
    );
}

/**
 * Asserts that a haystack that is stored in a static attribute of a class
 * or an attribute of an object does not contain only values of a given
 * type.
 *
 * @param  string  $type
 * @param  string  $haystackAttributeName
 * @param  mixed   $haystackClassOrObject
 * @param  boolean $isNativeType
 * @param  string  $message
 * @since  Method available since Release 3.1.4
 */
function assertAttributeNotContainsOnly($type, $haystackAttributeName, $haystackClassOrObject, $isNativeType = NULL, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertAttributeNotContainsOnly',
      func_get_args()
    );
}

/**
 * Asserts the number of elements of an array, Countable or Iterator
 * that is stored in an attribute.
 *
 * @param integer $expectedCount
 * @param string  $haystackAttributeName
 * @param mixed   $haystackClassOrObject
 * @param string  $message
 * @since Method available since Release 3.6.0
 */
function assertAttributeNotCount($expectedCount, $haystackAttributeName, $haystackClassOrObject, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertAttributeNotCount',
      func_get_args()
    );
}

/**
 * Asserts that a static attribute of a class or an attribute of an object
 * is not empty.
 *
 * @param string $haystackAttributeName
 * @param mixed  $haystackClassOrObject
 * @param string $message
 * @since Method available since Release 3.5.0
 */
function assertAttributeNotEmpty($haystackAttributeName, $haystackClassOrObject, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertAttributeNotEmpty',
      func_get_args()
    );
}

/**
 * Asserts that a variable is not equal to an attribute of an object.
 *
 * @param  mixed   $expected
 * @param  string  $actualAttributeName
 * @param  string  $actualClassOrObject
 * @param  string  $message
 * @param  float   $delta
 * @param  integer $maxDepth
 * @param  boolean $canonicalize
 * @param  boolean $ignoreCase
 */
function assertAttributeNotEquals($expected, $actualAttributeName, $actualClassOrObject, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertAttributeNotEquals',
      func_get_args()
    );
}

/**
 * Asserts that an attribute is of a given type.
 *
 * @param string $expected
 * @param string $attributeName
 * @param mixed  $classOrObject
 * @param string $message
 * @since Method available since Release 3.5.0
 */
function assertAttributeNotInstanceOf($expected, $attributeName, $classOrObject, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertAttributeNotInstanceOf',
      func_get_args()
    );
}

/**
 * Asserts that an attribute is of a given type.
 *
 * @param string $expected
 * @param string $attributeName
 * @param mixed  $classOrObject
 * @param string $message
 * @since Method available since Release 3.5.0
 */
function assertAttributeNotInternalType($expected, $attributeName, $classOrObject, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertAttributeNotInternalType',
      func_get_args()
    );
}

/**
 * Asserts that a variable and an attribute of an object do not have the
 * same type and value.
 *
 * @param  mixed  $expected
 * @param  string $actualAttributeName
 * @param  object $actualClassOrObject
 * @param  string $message
 */
function assertAttributeNotSame($expected, $actualAttributeName, $actualClassOrObject, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertAttributeNotSame',
      func_get_args()
    );
}

/**
 * Asserts that a variable and an attribute of an object have the same type
 * and value.
 *
 * @param  mixed  $expected
 * @param  string $actualAttributeName
 * @param  object $actualClassOrObject
 * @param  string $message
 */
function assertAttributeSame($expected, $actualAttributeName, $actualClassOrObject, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertAttributeSame',
      func_get_args()
    );
}

/**
 * Asserts that a class has a specified attribute.
 *
 * @param  string $attributeName
 * @param  string $className
 * @param  string $message
 * @since  Method available since Release 3.1.0
 */
function assertClassHasAttribute($attributeName, $className, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertClassHasAttribute',
      func_get_args()
    );
}

/**
 * Asserts that a class has a specified static attribute.
 *
 * @param  string $attributeName
 * @param  string $className
 * @param  string $message
 * @since  Method available since Release 3.1.0
 */
function assertClassHasStaticAttribute($attributeName, $className, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertClassHasStaticAttribute',
      func_get_args()
    );
}

/**
 * Asserts that a class does not have a specified attribute.
 *
 * @param  string $attributeName
 * @param  string $className
 * @param  string $message
 * @since  Method available since Release 3.1.0
 */
function assertClassNotHasAttribute($attributeName, $className, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertClassNotHasAttribute',
      func_get_args()
    );
}

/**
 * Asserts that a class does not have a specified static attribute.
 *
 * @param  string $attributeName
 * @param  string $className
 * @param  string $message
 * @since  Method available since Release 3.1.0
 */
function assertClassNotHasStaticAttribute($attributeName, $className, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertClassNotHasStaticAttribute',
      func_get_args()
    );
}

/**
 * Asserts that a haystack contains a needle.
 *
 * @param  mixed   $needle
 * @param  mixed   $haystack
 * @param  string  $message
 * @param  boolean $ignoreCase
 * @param  boolean $checkForObjectIdentity
 * @since  Method available since Release 2.1.0
 */
function assertContains($needle, $haystack, $message = '', $ignoreCase = FALSE, $checkForObjectIdentity = TRUE)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertContains',
      func_get_args()
    );
}

/**
 * Asserts that a haystack contains only values of a given type.
 *
 * @param  string  $type
 * @param  mixed   $haystack
 * @param  boolean $isNativeType
 * @param  string  $message
 * @since  Method available since Release 3.1.4
 */
function assertContainsOnly($type, $haystack, $isNativeType = NULL, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertContainsOnly',
      func_get_args()
    );
}

/**
 * Asserts that a haystack contains only instances of a given classname
 *
 * @param string $classname
 * @param array|Traversable $haystack
 * @param string $message
 */
function assertContainsOnlyInstancesOf($classname, $haystack, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertContainsOnlyInstancesOf',
      func_get_args()
    );
}

/**
 * Asserts the number of elements of an array, Countable or Iterator.
 *
 * @param integer $expectedCount
 * @param mixed   $haystack
 * @param string  $message
 */
function assertCount($expectedCount, $haystack, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertCount',
      func_get_args()
    );
}

/**
 * Asserts that a variable is empty.
 *
 * @param  mixed   $actual
 * @param  string  $message
 * @throws PHPUnit_Framework_AssertionFailedError
 */
function assertEmpty($actual, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertEmpty',
      func_get_args()
    );
}

/**
 * Asserts that a hierarchy of DOMElements matches.
 *
 * @param DOMElement $expectedElement
 * @param DOMElement $actualElement
 * @param boolean $checkAttributes
 * @param string  $message
 * @author Mattis Stordalen Flister <mattis@xait.no>
 * @since  Method available since Release 3.3.0
 */
function assertEqualXMLStructure(DOMElement $expectedElement, DOMElement $actualElement, $checkAttributes = FALSE, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertEqualXMLStructure',
      func_get_args()
    );
}

/**
 * Asserts that two variables are equal.
 *
 * @param  mixed   $expected
 * @param  mixed   $actual
 * @param  string  $message
 * @param  float   $delta
 * @param  integer $maxDepth
 * @param  boolean $canonicalize
 * @param  boolean $ignoreCase
 */
function assertEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertEquals',
      func_get_args()
    );
}

/**
 * Asserts that a condition is false.
 *
 * @param  boolean  $condition
 * @param  string   $message
 * @throws PHPUnit_Framework_AssertionFailedError
 */
function assertFalse($condition, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertFalse',
      func_get_args()
    );
}

/**
 * Asserts that the contents of one file is equal to the contents of another
 * file.
 *
 * @param  string  $expected
 * @param  string  $actual
 * @param  string  $message
 * @param  boolean $canonicalize
 * @param  boolean $ignoreCase
 * @since  Method available since Release 3.2.14
 */
function assertFileEquals($expected, $actual, $message = '', $canonicalize = FALSE, $ignoreCase = FALSE)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertFileEquals',
      func_get_args()
    );
}

/**
 * Asserts that a file exists.
 *
 * @param  string $filename
 * @param  string $message
 * @since  Method available since Release 3.0.0
 */
function assertFileExists($filename, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertFileExists',
      func_get_args()
    );
}

/**
 * Asserts that the contents of one file is not equal to the contents of
 * another file.
 *
 * @param  string  $expected
 * @param  string  $actual
 * @param  string  $message
 * @param  boolean $canonicalize
 * @param  boolean $ignoreCase
 * @since  Method available since Release 3.2.14
 */
function assertFileNotEquals($expected, $actual, $message = '', $canonicalize = FALSE, $ignoreCase = FALSE)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertFileNotEquals',
      func_get_args()
    );
}

/**
 * Asserts that a file does not exist.
 *
 * @param  string $filename
 * @param  string $message
 * @since  Method available since Release 3.0.0
 */
function assertFileNotExists($filename, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertFileNotExists',
      func_get_args()
    );
}

/**
 * Asserts that a value is greater than another value.
 *
 * @param  mixed   $expected
 * @param  mixed   $actual
 * @param  string  $message
 * @since  Method available since Release 3.1.0
 */
function assertGreaterThan($expected, $actual, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertGreaterThan',
      func_get_args()
    );
}

/**
 * Asserts that a value is greater than or equal to another value.
 *
 * @param  mixed   $expected
 * @param  mixed   $actual
 * @param  string  $message
 * @since  Method available since Release 3.1.0
 */
function assertGreaterThanOrEqual($expected, $actual, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertGreaterThanOrEqual',
      func_get_args()
    );
}

/**
 * Asserts that a variable is of a given type.
 *
 * @param string $expected
 * @param mixed  $actual
 * @param string $message
 * @since Method available since Release 3.5.0
 */
function assertInstanceOf($expected, $actual, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertInstanceOf',
      func_get_args()
    );
}

/**
 * Asserts that a variable is of a given type.
 *
 * @param string $expected
 * @param mixed  $actual
 * @param string $message
 * @since Method available since Release 3.5.0
 */
function assertInternalType($expected, $actual, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertInternalType',
      func_get_args()
    );
}

/**
 * Asserts that a string is a valid JSON string.
 *
 * @param  string $filename
 * @param  string $message
 * @since  Method available since Release 3.7.20
 */
function assertJson($expectedJson, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertJson',
      func_get_args()
    );
}

/**
 * Asserts that two JSON files are equal.
 *
 * @param  string $expectedFile
 * @param  string $actualFile
 * @param  string $message
 */
function assertJsonFileEqualsJsonFile($expectedFile, $actualFile, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertJsonFileEqualsJsonFile',
      func_get_args()
    );
}

/**
 * Asserts that two JSON files are not equal.
 *
 * @param  string $expectedFile
 * @param  string $actualFile
 * @param  string $message
 */
function assertJsonFileNotEqualsJsonFile($expectedFile, $actualFile, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertJsonFileNotEqualsJsonFile',
      func_get_args()
    );
}

/**
 * Asserts that the generated JSON encoded object and the content of the given file are equal.
 *
 * @param string $expectedFile
 * @param string $actualJson
 * @param string $message
 */
function assertJsonStringEqualsJsonFile($expectedFile, $actualJson, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertJsonStringEqualsJsonFile',
      func_get_args()
    );
}

/**
 * Asserts that two given JSON encoded objects or arrays are equal.
 *
 * @param string $expectedJson
 * @param string $actualJson
 * @param string $message
 */
function assertJsonStringEqualsJsonString($expectedJson, $actualJson, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertJsonStringEqualsJsonString',
      func_get_args()
    );
}

/**
 * Asserts that the generated JSON encoded object and the content of the given file are not equal.
 *
 * @param string $expectedFile
 * @param string $actualJson
 * @param string $message
 */
function assertJsonStringNotEqualsJsonFile($expectedFile, $actualJson, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertJsonStringNotEqualsJsonFile',
      func_get_args()
    );
}

/**
 * Asserts that two given JSON encoded objects or arrays are not equal.
 *
 * @param string $expectedJson
 * @param string $actualJson
 * @param string $message
 */
function assertJsonStringNotEqualsJsonString($expectedJson, $actualJson, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertJsonStringNotEqualsJsonString',
      func_get_args()
    );
}

/**
 * Asserts that a value is smaller than another value.
 *
 * @param  mixed   $expected
 * @param  mixed   $actual
 * @param  string  $message
 * @since  Method available since Release 3.1.0
 */
function assertLessThan($expected, $actual, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertLessThan',
      func_get_args()
    );
}

/**
 * Asserts that a value is smaller than or equal to another value.
 *
 * @param  mixed   $expected
 * @param  mixed   $actual
 * @param  string  $message
 * @since  Method available since Release 3.1.0
 */
function assertLessThanOrEqual($expected, $actual, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertLessThanOrEqual',
      func_get_args()
    );
}

/**
 * Asserts that a haystack does not contain a needle.
 *
 * @param  mixed   $needle
 * @param  mixed   $haystack
 * @param  string  $message
 * @param  boolean $ignoreCase
 * @param  boolean $checkForObjectIdentity
 * @since  Method available since Release 2.1.0
 */
function assertNotContains($needle, $haystack, $message = '', $ignoreCase = FALSE, $checkForObjectIdentity = TRUE)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertNotContains',
      func_get_args()
    );
}

/**
 * Asserts that a haystack does not contain only values of a given type.
 *
 * @param  string  $type
 * @param  mixed   $haystack
 * @param  boolean $isNativeType
 * @param  string  $message
 * @since  Method available since Release 3.1.4
 */
function assertNotContainsOnly($type, $haystack, $isNativeType = NULL, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertNotContainsOnly',
      func_get_args()
    );
}

/**
 * Asserts the number of elements of an array, Countable or Iterator.
 *
 * @param integer $expectedCount
 * @param mixed   $haystack
 * @param string  $message
 */
function assertNotCount($expectedCount, $haystack, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertNotCount',
      func_get_args()
    );
}

/**
 * Asserts that a variable is not empty.
 *
 * @param  mixed   $actual
 * @param  string  $message
 * @throws PHPUnit_Framework_AssertionFailedError
 */
function assertNotEmpty($actual, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertNotEmpty',
      func_get_args()
    );
}

/**
 * Asserts that two variables are not equal.
 *
 * @param  mixed   $expected
 * @param  mixed   $actual
 * @param  string  $message
 * @param  float   $delta
 * @param  integer $maxDepth
 * @param  boolean $canonicalize
 * @param  boolean $ignoreCase
 * @since  Method available since Release 2.3.0
 */
function assertNotEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertNotEquals',
      func_get_args()
    );
}

/**
 * Asserts that a variable is not of a given type.
 *
 * @param string $expected
 * @param mixed  $actual
 * @param string $message
 * @since Method available since Release 3.5.0
 */
function assertNotInstanceOf($expected, $actual, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertNotInstanceOf',
      func_get_args()
    );
}

/**
 * Asserts that a variable is not of a given type.
 *
 * @param string $expected
 * @param mixed  $actual
 * @param string $message
 * @since Method available since Release 3.5.0
 */
function assertNotInternalType($expected, $actual, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertNotInternalType',
      func_get_args()
    );
}

/**
 * Asserts that a variable is not NULL.
 *
 * @param  mixed  $actual
 * @param  string $message
 */
function assertNotNull($actual, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertNotNull',
      func_get_args()
    );
}

/**
 * Asserts that a string does not match a given regular expression.
 *
 * @param  string $pattern
 * @param  string $string
 * @param  string $message
 * @since  Method available since Release 2.1.0
 */
function assertNotRegExp($pattern, $string, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertNotRegExp',
      func_get_args()
    );
}

/**
 * Asserts that two variables do not have the same type and value.
 * Used on objects, it asserts that two variables do not reference
 * the same object.
 *
 * @param  mixed  $expected
 * @param  mixed  $actual
 * @param  string $message
 */
function assertNotSame($expected, $actual, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertNotSame',
      func_get_args()
    );
}

/**
 * Assert that the size of two arrays (or `Countable` or `Iterator` objects)
 * is not the same.
 *
 * @param array|Countable|Iterator $expected
 * @param array|Countable|Iterator $actual
 * @param string $message
 */
function assertNotSameSize($expected, $actual, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertNotSameSize',
      func_get_args()
    );
}

/**
 * This assertion is the exact opposite of assertTag().
 *
 * Rather than asserting that $matcher results in a match, it asserts that
 * $matcher does not match.
 *
 * @param  array   $matcher
 * @param  string  $actual
 * @param  string  $message
 * @param  boolean $isHtml
 * @since  Method available since Release 3.3.0
 * @author Mike Naberezny <mike@maintainable.com>
 * @author Derek DeVries <derek@maintainable.com>
 */
function assertNotTag($matcher, $actual, $message = '', $isHtml = TRUE)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertNotTag',
      func_get_args()
    );
}

/**
 * Asserts that a variable is NULL.
 *
 * @param  mixed  $actual
 * @param  string $message
 */
function assertNull($actual, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertNull',
      func_get_args()
    );
}

/**
 * Asserts that an object has a specified attribute.
 *
 * @param  string $attributeName
 * @param  object $object
 * @param  string $message
 * @since  Method available since Release 3.0.0
 */
function assertObjectHasAttribute($attributeName, $object, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertObjectHasAttribute',
      func_get_args()
    );
}

/**
 * Asserts that an object does not have a specified attribute.
 *
 * @param  string $attributeName
 * @param  object $object
 * @param  string $message
 * @since  Method available since Release 3.0.0
 */
function assertObjectNotHasAttribute($attributeName, $object, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertObjectNotHasAttribute',
      func_get_args()
    );
}

/**
 * Asserts that a string matches a given regular expression.
 *
 * @param  string $pattern
 * @param  string $string
 * @param  string $message
 */
function assertRegExp($pattern, $string, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertRegExp',
      func_get_args()
    );
}

/**
 * Asserts that two variables have the same type and value.
 * Used on objects, it asserts that two variables reference
 * the same object.
 *
 * @param  mixed  $expected
 * @param  mixed  $actual
 * @param  string $message
 */
function assertSame($expected, $actual, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertSame',
      func_get_args()
    );
}

/**
 * Assert that the size of two arrays (or `Countable` or `Iterator` objects)
 * is the same.
 *
 * @param array|Countable|Iterator $expected
 * @param array|Countable|Iterator $actual
 * @param string $message
 */
function assertSameSize($expected, $actual, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertSameSize',
      func_get_args()
    );
}

/**
 * Assert the presence, absence, or count of elements in a document matching
 * the CSS $selector, regardless of the contents of those elements.
 *
 * The first argument, $selector, is the CSS selector used to match
 * the elements in the $actual document.
 *
 * The second argument, $count, can be either boolean or numeric.
 * When boolean, it asserts for presence of elements matching the selector
 * (TRUE) or absence of elements (FALSE).
 * When numeric, it asserts the count of elements.
 *
 * assertSelectCount("#binder", true, $xml);  // any?
 * assertSelectCount(".binder", 3, $xml); // exactly 3?
 *
 * @param  array   $selector
 * @param  integer $count
 * @param  mixed   $actual
 * @param  string  $message
 * @param  boolean $isHtml
 * @since  Method available since Release 3.3.0
 * @author Mike Naberezny <mike@maintainable.com>
 * @author Derek DeVries <derek@maintainable.com>
 */
function assertSelectCount($selector, $count, $actual, $message = '', $isHtml = TRUE)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertSelectCount',
      func_get_args()
    );
}

/**
 * assertSelectEquals("#binder .name", "Chuck", true,  $xml);  // any?
 * assertSelectEquals("#binder .name", "Chuck", false, $xml);  // none?
 *
 * @param  array   $selector
 * @param  string  $content
 * @param  integer $count
 * @param  mixed   $actual
 * @param  string  $message
 * @param  boolean $isHtml
 * @since  Method available since Release 3.3.0
 * @author Mike Naberezny <mike@maintainable.com>
 * @author Derek DeVries <derek@maintainable.com>
 */
function assertSelectEquals($selector, $content, $count, $actual, $message = '', $isHtml = TRUE)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertSelectEquals',
      func_get_args()
    );
}

/**
 * assertSelectRegExp("#binder .name", "/Mike|Derek/", true, $xml); // any?
 * assertSelectRegExp("#binder .name", "/Mike|Derek/", 3, $xml);// 3?
 *
 * @param  array   $selector
 * @param  string  $pattern
 * @param  integer $count
 * @param  mixed   $actual
 * @param  string  $message
 * @param  boolean $isHtml
 * @since  Method available since Release 3.3.0
 * @author Mike Naberezny <mike@maintainable.com>
 * @author Derek DeVries <derek@maintainable.com>
 */
function assertSelectRegExp($selector, $pattern, $count, $actual, $message = '', $isHtml = TRUE)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertSelectRegExp',
      func_get_args()
    );
}

/**
 * Asserts that a string ends not with a given prefix.
 *
 * @param  string $suffix
 * @param  string $string
 * @param  string $message
 * @since  Method available since Release 3.4.0
 */
function assertStringEndsNotWith($suffix, $string, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertStringEndsNotWith',
      func_get_args()
    );
}

/**
 * Asserts that a string ends with a given prefix.
 *
 * @param  string $suffix
 * @param  string $string
 * @param  string $message
 * @since  Method available since Release 3.4.0
 */
function assertStringEndsWith($suffix, $string, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertStringEndsWith',
      func_get_args()
    );
}

/**
 * Asserts that the contents of a string is equal
 * to the contents of a file.
 *
 * @param  string  $expectedFile
 * @param  string  $actualString
 * @param  string  $message
 * @param  boolean $canonicalize
 * @param  boolean $ignoreCase
 * @since  Method available since Release 3.3.0
 */
function assertStringEqualsFile($expectedFile, $actualString, $message = '', $canonicalize = FALSE, $ignoreCase = FALSE)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertStringEqualsFile',
      func_get_args()
    );
}

/**
 * Asserts that a string matches a given format string.
 *
 * @param  string $format
 * @param  string $string
 * @param  string $message
 * @since  Method available since Release 3.5.0
 */
function assertStringMatchesFormat($format, $string, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertStringMatchesFormat',
      func_get_args()
    );
}

/**
 * Asserts that a string matches a given format file.
 *
 * @param  string $formatFile
 * @param  string $string
 * @param  string $message
 * @since  Method available since Release 3.5.0
 */
function assertStringMatchesFormatFile($formatFile, $string, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertStringMatchesFormatFile',
      func_get_args()
    );
}

/**
 * Asserts that the contents of a string is not equal
 * to the contents of a file.
 *
 * @param  string  $expectedFile
 * @param  string  $actualString
 * @param  string  $message
 * @param  boolean $canonicalize
 * @param  boolean $ignoreCase
 * @since  Method available since Release 3.3.0
 */
function assertStringNotEqualsFile($expectedFile, $actualString, $message = '', $canonicalize = FALSE, $ignoreCase = FALSE)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertStringNotEqualsFile',
      func_get_args()
    );
}

/**
 * Asserts that a string does not match a given format string.
 *
 * @param  string $format
 * @param  string $string
 * @param  string $message
 * @since  Method available since Release 3.5.0
 */
function assertStringNotMatchesFormat($format, $string, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertStringNotMatchesFormat',
      func_get_args()
    );
}

/**
 * Asserts that a string does not match a given format string.
 *
 * @param  string $formatFile
 * @param  string $string
 * @param  string $message
 * @since  Method available since Release 3.5.0
 */
function assertStringNotMatchesFormatFile($formatFile, $string, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertStringNotMatchesFormatFile',
      func_get_args()
    );
}

/**
 * Asserts that a string starts not with a given prefix.
 *
 * @param  string $prefix
 * @param  string $string
 * @param  string $message
 * @since  Method available since Release 3.4.0
 */
function assertStringStartsNotWith($prefix, $string, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertStringStartsNotWith',
      func_get_args()
    );
}

/**
 * Asserts that a string starts with a given prefix.
 *
 * @param  string $prefix
 * @param  string $string
 * @param  string $message
 * @since  Method available since Release 3.4.0
 */
function assertStringStartsWith($prefix, $string, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertStringStartsWith',
      func_get_args()
    );
}

/**
 * Evaluate an HTML or XML string and assert its structure and/or contents.
 *
 * The first argument ($matcher) is an associative array that specifies the
 * match criteria for the assertion:
 *
 *  - `id`   : the node with the given id attribute must match the
 * corresponsing value.
 *  - `tag`  : the node type must match the corresponding value.
 *  - `attributes`   : a hash. The node's attributres must match the
 * corresponsing values in the hash.
 *  - `content`  : The text content must match the given value.
 *  - `parent`   : a hash. The node's parent must match the
 * corresponsing hash.
 *  - `child`: a hash. At least one of the node's immediate children
 * must meet the criteria described by the hash.
 *  - `ancestor` : a hash. At least one of the node's ancestors must
 * meet the criteria described by the hash.
 *  - `descendant`   : a hash. At least one of the node's descendants must
 * meet the criteria described by the hash.
 *  - `children` : a hash, for counting children of a node.
 * Accepts the keys:
 *- `count`: a number which must equal the number of children
 *   that match
 *- `less_than`: the number of matching children must be greater
 *   than this number
 *- `greater_than` : the number of matching children must be less than
 *   this number
 *- `only` : another hash consisting of the keys to use to match
 *   on the children, and only matching children will be
 *   counted
 *
 * <code>
 * // Matcher that asserts that there is an element with an id="my_id".
 * $matcher = array('id' => 'my_id');
 *
 * // Matcher that asserts that there is a "span" tag.
 * $matcher = array('tag' => 'span');
 *
 * // Matcher that asserts that there is a "span" tag with the content
 * // "Hello World".
 * $matcher = array('tag' => 'span', 'content' => 'Hello World');
 *
 * // Matcher that asserts that there is a "span" tag with content matching
 * // the regular expression pattern.
 * $matcher = array('tag' => 'span', 'content' => 'regexp:/Try P(HP|ython)/');
 *
 * // Matcher that asserts that there is a "span" with an "list" class
 * // attribute.
 * $matcher = array(
 *   'tag'=> 'span',
 *   'attributes' => array('class' => 'list')
 * );
 *
 * // Matcher that asserts that there is a "span" inside of a "div".
 * $matcher = array(
 *   'tag'=> 'span',
 *   'parent' => array('tag' => 'div')
 * );
 *
 * // Matcher that asserts that there is a "span" somewhere inside a
 * // "table".
 * $matcher = array(
 *   'tag'  => 'span',
 *   'ancestor' => array('tag' => 'table')
 * );
 *
 * // Matcher that asserts that there is a "span" with at least one "em"
 * // child.
 * $matcher = array(
 *   'tag'   => 'span',
 *   'child' => array('tag' => 'em')
 * );
 *
 * // Matcher that asserts that there is a "span" containing a (possibly
 * // nested) "strong" tag.
 * $matcher = array(
 *   'tag'=> 'span',
 *   'descendant' => array('tag' => 'strong')
 * );
 *
 * // Matcher that asserts that there is a "span" containing 5-10 "em" tags
 * // as immediate children.
 * $matcher = array(
 *   'tag'  => 'span',
 *   'children' => array(
 * 'less_than'=> 11,
 * 'greater_than' => 4,
 * 'only' => array('tag' => 'em')
 *   )
 * );
 *
 * // Matcher that asserts that there is a "div", with an "ul" ancestor and
 * // a "li" parent (with class="enum"), and containing a "span" descendant
 * // that contains an element with id="my_test" and the text "Hello World".
 * $matcher = array(
 *   'tag'=> 'div',
 *   'ancestor'   => array('tag' => 'ul'),
 *   'parent' => array(
 * 'tag'=> 'li',
 * 'attributes' => array('class' => 'enum')
 *   ),
 *   'descendant' => array(
 * 'tag'   => 'span',
 * 'child' => array(
 *   'id'  => 'my_test',
 *   'content' => 'Hello World'
 * )
 *   )
 * );
 *
 * // Use assertTag() to apply a $matcher to a piece of $html.
 * $this->assertTag($matcher, $html);
 *
 * // Use assertTag() to apply a $matcher to a piece of $xml.
 * $this->assertTag($matcher, $xml, '', FALSE);
 * </code>
 *
 * The second argument ($actual) is a string containing either HTML or
 * XML text to be tested.
 *
 * The third argument ($message) is an optional message that will be
 * used if the assertion fails.
 *
 * The fourth argument ($html) is an optional flag specifying whether
 * to load the $actual string into a DOMDocument using the HTML or
 * XML load strategy.  It is TRUE by default, which assumes the HTML
 * load strategy.  In many cases, this will be acceptable for XML as well.
 *
 * @param  array   $matcher
 * @param  string  $actual
 * @param  string  $message
 * @param  boolean $isHtml
 * @since  Method available since Release 3.3.0
 * @author Mike Naberezny <mike@maintainable.com>
 * @author Derek DeVries <derek@maintainable.com>
 */
function assertTag($matcher, $actual, $message = '', $isHtml = TRUE)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertTag',
      func_get_args()
    );
}

/**
 * Evaluates a PHPUnit_Framework_Constraint matcher object.
 *
 * @param  mixed$value
 * @param  PHPUnit_Framework_Constraint $constraint
 * @param  string   $message
 * @since  Method available since Release 3.0.0
 */
function assertThat($value, PHPUnit_Framework_Constraint $constraint, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertThat',
      func_get_args()
    );
}

/**
 * Asserts that a condition is true.
 *
 * @param  boolean $condition
 * @param  string  $message
 * @throws PHPUnit_Framework_AssertionFailedError
 */
function assertTrue($condition, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertTrue',
      func_get_args()
    );
}

/**
 * Asserts that two XML files are equal.
 *
 * @param  string $expectedFile
 * @param  string $actualFile
 * @param  string $message
 * @since  Method available since Release 3.1.0
 */
function assertXmlFileEqualsXmlFile($expectedFile, $actualFile, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertXmlFileEqualsXmlFile',
      func_get_args()
    );
}

/**
 * Asserts that two XML files are not equal.
 *
 * @param  string $expectedFile
 * @param  string $actualFile
 * @param  string $message
 * @since  Method available since Release 3.1.0
 */
function assertXmlFileNotEqualsXmlFile($expectedFile, $actualFile, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertXmlFileNotEqualsXmlFile',
      func_get_args()
    );
}

/**
 * Asserts that two XML documents are equal.
 *
 * @param  string $expectedFile
 * @param  string $actualXml
 * @param  string $message
 * @since  Method available since Release 3.3.0
 */
function assertXmlStringEqualsXmlFile($expectedFile, $actualXml, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertXmlStringEqualsXmlFile',
      func_get_args()
    );
}

/**
 * Asserts that two XML documents are equal.
 *
 * @param  string $expectedXml
 * @param  string $actualXml
 * @param  string $message
 * @since  Method available since Release 3.1.0
 */
function assertXmlStringEqualsXmlString($expectedXml, $actualXml, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertXmlStringEqualsXmlString',
      func_get_args()
    );
}

/**
 * Asserts that two XML documents are not equal.
 *
 * @param  string $expectedFile
 * @param  string $actualXml
 * @param  string $message
 * @since  Method available since Release 3.3.0
 */
function assertXmlStringNotEqualsXmlFile($expectedFile, $actualXml, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertXmlStringNotEqualsXmlFile',
      func_get_args()
    );
}

/**
 * Asserts that two XML documents are not equal.
 *
 * @param  string $expectedXml
 * @param  string $actualXml
 * @param  string $message
 * @since  Method available since Release 3.1.0
 */
function assertXmlStringNotEqualsXmlString($expectedXml, $actualXml, $message = '')
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::assertXmlStringNotEqualsXmlString',
      func_get_args()
    );
}

/**
 * Returns a matcher that matches when the method it is evaluated for
 * is invoked at the given $index.
 *
 * @param  integer $index
 * @return PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex
 * @since  Method available since Release 3.0.0
 */
function at($index)
{
    return call_user_func_array(
      'PHPUnit_Framework_TestCase::at',
      func_get_args()
    );
}

/**
 * Returns a matcher that matches when the method it is evaluated for
 * is executed at least once.
 *
 * @return PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastOnce
 * @since  Method available since Release 3.0.0
 */
function atLeastOnce()
{
    return call_user_func_array(
      'PHPUnit_Framework_TestCase::atLeastOnce',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_Attribute matcher object.
 *
 * @param  PHPUnit_Framework_Constraint $constraint
 * @param  string   $attributeName
 * @return PHPUnit_Framework_Constraint_Attribute
 * @since  Method available since Release 3.1.0
 */
function attribute(PHPUnit_Framework_Constraint $constraint, $attributeName)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::attribute',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_IsEqual matcher object
 * that is wrapped in a PHPUnit_Framework_Constraint_Attribute matcher
 * object.
 *
 * @param  string  $attributeName
 * @param  mixed   $value
 * @param  float   $delta
 * @param  integer $maxDepth
 * @param  boolean $canonicalize
 * @param  boolean $ignoreCase
 * @return PHPUnit_Framework_Constraint_Attribute
 * @since  Method available since Release 3.1.0
 */
function attributeEqualTo($attributeName, $value, $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::attributeEqualTo',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_Callback matcher object.
 *
 * @param callable $callback
 * @return PHPUnit_Framework_Constraint_Callback
 */
function callback($callback)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::callback',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_ClassHasAttribute matcher object.
 *
 * @param  string $attributeName
 * @return PHPUnit_Framework_Constraint_ClassHasAttribute
 * @since  Method available since Release 3.1.0
 */
function classHasAttribute($attributeName)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::classHasAttribute',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_ClassHasStaticAttribute matcher
 * object.
 *
 * @param  string $attributeName
 * @return PHPUnit_Framework_Constraint_ClassHasStaticAttribute
 * @since  Method available since Release 3.1.0
 */
function classHasStaticAttribute($attributeName)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::classHasStaticAttribute',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_TraversableContains matcher
 * object.
 *
 * @param  mixed   $value
 * @param  boolean $checkForObjectIdentity
 * @return PHPUnit_Framework_Constraint_TraversableContains
 * @since  Method available since Release 3.0.0
 */
function contains($value, $checkForObjectIdentity = TRUE)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::contains',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_TraversableContainsOnly matcher
 * object.
 *
 * @param  string $type
 * @return PHPUnit_Framework_Constraint_TraversableContainsOnly
 * @since  Method available since Release 3.1.4
 */
function containsOnly($type)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::containsOnly',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_TraversableContainsOnly matcher
 * object.
 *
 * @param string $classname
 * @return PHPUnit_Framework_Constraint_TraversableContainsOnly
 */
function containsOnlyInstancesOf($classname)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::containsOnlyInstancesOf',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_IsEqual matcher object.
 *
 * @param  mixed   $value
 * @param  float   $delta
 * @param  integer $maxDepth
 * @param  boolean $canonicalize
 * @param  boolean $ignoreCase
 * @return PHPUnit_Framework_Constraint_IsEqual
 * @since  Method available since Release 3.0.0
 */
function equalTo($value, $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::equalTo',
      func_get_args()
    );
}

/**
 * Returns a matcher that matches when the method it is evaluated for
 * is executed exactly $count times.
 *
 * @param  integer $count
 * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount
 * @since  Method available since Release 3.0.0
 */
function exactly($count)
{
    return call_user_func_array(
      'PHPUnit_Framework_TestCase::exactly',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_FileExists matcher object.
 *
 * @return PHPUnit_Framework_Constraint_FileExists
 * @since  Method available since Release 3.0.0
 */
function fileExists()
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::fileExists',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_GreaterThan matcher object.
 *
 * @param  mixed $value
 * @return PHPUnit_Framework_Constraint_GreaterThan
 * @since  Method available since Release 3.0.0
 */
function greaterThan($value)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::greaterThan',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_Or matcher object that wraps
 * a PHPUnit_Framework_Constraint_IsEqual and a
 * PHPUnit_Framework_Constraint_GreaterThan matcher object.
 *
 * @param  mixed $value
 * @return PHPUnit_Framework_Constraint_Or
 * @since  Method available since Release 3.1.0
 */
function greaterThanOrEqual($value)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::greaterThanOrEqual',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_IsIdentical matcher object.
 *
 * @param  mixed $value
 * @return PHPUnit_Framework_Constraint_IsIdentical
 * @since  Method available since Release 3.0.0
 */
function identicalTo($value)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::identicalTo',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_IsEmpty matcher object.
 *
 * @return PHPUnit_Framework_Constraint_IsEmpty
 * @since  Method available since Release 3.5.0
 */
function isEmpty()
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::isEmpty',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_IsFalse matcher object.
 *
 * @return PHPUnit_Framework_Constraint_IsFalse
 * @since  Method available since Release 3.3.0
 */
function isFalse()
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::isFalse',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_IsInstanceOf matcher object.
 *
 * @param  string $className
 * @return PHPUnit_Framework_Constraint_IsInstanceOf
 * @since  Method available since Release 3.0.0
 */
function isInstanceOf($className)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::isInstanceOf',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_IsJson matcher object.
 *
 * @return PHPUnit_Framework_Constraint_IsJson
 * @since  Method available since Release 3.7.20
 */
function isJson()
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::isJson',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_IsNull matcher object.
 *
 * @return PHPUnit_Framework_Constraint_IsNull
 * @since  Method available since Release 3.3.0
 */
function isNull()
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::isNull',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_IsTrue matcher object.
 *
 * @return PHPUnit_Framework_Constraint_IsTrue
 * @since  Method available since Release 3.3.0
 */
function isTrue()
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::isTrue',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_IsType matcher object.
 *
 * @param  string $type
 * @return PHPUnit_Framework_Constraint_IsType
 * @since  Method available since Release 3.0.0
 */
function isType($type)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::isType',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_LessThan matcher object.
 *
 * @param  mixed $value
 * @return PHPUnit_Framework_Constraint_LessThan
 * @since  Method available since Release 3.0.0
 */
function lessThan($value)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::lessThan',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_Or matcher object that wraps
 * a PHPUnit_Framework_Constraint_IsEqual and a
 * PHPUnit_Framework_Constraint_LessThan matcher object.
 *
 * @param  mixed $value
 * @return PHPUnit_Framework_Constraint_Or
 * @since  Method available since Release 3.1.0
 */
function lessThanOrEqual($value)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::lessThanOrEqual',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_And matcher object.
 *
 * @return PHPUnit_Framework_Constraint_And
 * @since  Method available since Release 3.0.0
 */
function logicalAnd()
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::logicalAnd',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_Not matcher object.
 *
 * @param  PHPUnit_Framework_Constraint $constraint
 * @return PHPUnit_Framework_Constraint_Not
 * @since  Method available since Release 3.0.0
 */
function logicalNot(PHPUnit_Framework_Constraint $constraint)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::logicalNot',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_Or matcher object.
 *
 * @return PHPUnit_Framework_Constraint_Or
 * @since  Method available since Release 3.0.0
 */
function logicalOr()
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::logicalOr',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_Xor matcher object.
 *
 * @return PHPUnit_Framework_Constraint_Xor
 * @since  Method available since Release 3.0.0
 */
function logicalXor()
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::logicalXor',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_StringMatches matcher object.
 *
 * @param  string $string
 * @return PHPUnit_Framework_Constraint_StringMatches
 * @since  Method available since Release 3.5.0
 */
function matches($string)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::matches',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_PCREMatch matcher object.
 *
 * @param  string $pattern
 * @return PHPUnit_Framework_Constraint_PCREMatch
 * @since  Method available since Release 3.0.0
 */
function matchesRegularExpression($pattern)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::matchesRegularExpression',
      func_get_args()
    );
}

/**
 * Returns a matcher that matches when the method it is evaluated for
 * is never executed.
 *
 * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount
 * @since  Method available since Release 3.0.0
 */
function never()
{
    return call_user_func_array(
      'PHPUnit_Framework_TestCase::never',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_ObjectHasAttribute matcher object.
 *
 * @param  string $attributeName
 * @return PHPUnit_Framework_Constraint_ObjectHasAttribute
 * @since  Method available since Release 3.0.0
 */
function objectHasAttribute($attributeName)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::objectHasAttribute',
      func_get_args()
    );
}

/**
 *
 *
 * @param  mixed $value, ...
 * @return PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls
 * @since  Method available since Release 3.0.0
 */
function onConsecutiveCalls()
{
    return call_user_func_array(
      'PHPUnit_Framework_TestCase::onConsecutiveCalls',
      func_get_args()
    );
}

/**
 * Returns a matcher that matches when the method it is evaluated for
 * is executed exactly once.
 *
 * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount
 * @since  Method available since Release 3.0.0
 */
function once()
{
    return call_user_func_array(
      'PHPUnit_Framework_TestCase::once',
      func_get_args()
    );
}

/**
 *
 *
 * @param  integer $argumentIndex
 * @return PHPUnit_Framework_MockObject_Stub_ReturnArgument
 * @since  Method available since Release 3.3.0
 */
function returnArgument($argumentIndex)
{
    return call_user_func_array(
      'PHPUnit_Framework_TestCase::returnArgument',
      func_get_args()
    );
}

/**
 *
 *
 * @param  mixed $callback
 * @return PHPUnit_Framework_MockObject_Stub_ReturnCallback
 * @since  Method available since Release 3.3.0
 */
function returnCallback($callback)
{
    return call_user_func_array(
      'PHPUnit_Framework_TestCase::returnCallback',
      func_get_args()
    );
}

/**
 * Returns the current object.
 *
 * This method is useful when mocking a fluent interface.
 *
 * @return PHPUnit_Framework_MockObject_Stub_ReturnSelf
 * @since  Method available since Release 3.6.0
 */
function returnSelf()
{
    return call_user_func_array(
      'PHPUnit_Framework_TestCase::returnSelf',
      func_get_args()
    );
}

/**
 *
 *
 * @param  mixed $value
 * @return PHPUnit_Framework_MockObject_Stub_Return
 * @since  Method available since Release 3.0.0
 */
function returnValue($value)
{
    return call_user_func_array(
      'PHPUnit_Framework_TestCase::returnValue',
      func_get_args()
    );
}

/**
 *
 *
 * @param  array $valueMap
 * @return PHPUnit_Framework_MockObject_Stub_ReturnValueMap
 * @since  Method available since Release 3.6.0
 */
function returnValueMap(array $valueMap)
{
    return call_user_func_array(
      'PHPUnit_Framework_TestCase::returnValueMap',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_StringContains matcher object.
 *
 * @param  string  $string
 * @param  boolean $case
 * @return PHPUnit_Framework_Constraint_StringContains
 * @since  Method available since Release 3.0.0
 */
function stringContains($string, $case = TRUE)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::stringContains',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_StringEndsWith matcher object.
 *
 * @param  mixed $suffix
 * @return PHPUnit_Framework_Constraint_StringEndsWith
 * @since  Method available since Release 3.4.0
 */
function stringEndsWith($suffix)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::stringEndsWith',
      func_get_args()
    );
}

/**
 * Returns a PHPUnit_Framework_Constraint_StringStartsWith matcher object.
 *
 * @param  mixed $prefix
 * @return PHPUnit_Framework_Constraint_StringStartsWith
 * @since  Method available since Release 3.4.0
 */
function stringStartsWith($prefix)
{
    return call_user_func_array(
      'PHPUnit_Framework_Assert::stringStartsWith',
      func_get_args()
    );
}

/**
 *
 *
 * @param  Exception $exception
 * @return PHPUnit_Framework_MockObject_Stub_Exception
 * @since  Method available since Release 3.1.0
 */
function throwException(Exception $exception)
{
    return call_user_func_array(
      'PHPUnit_Framework_TestCase::throwException',
      func_get_args()
    );
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

/**
 * A warning.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.0.0
 */
class PHPUnit_Framework_Warning extends PHPUnit_Framework_TestCase
{
    /**
     * @var string
     */
    protected $message = '';

    /**
     * @var boolean
     */
    protected $backupGlobals = FALSE;

    /**
     * @var boolean
     */
    protected $backupStaticAttributes = FALSE;

    /**
     * @var boolean
     */
    protected $runTestInSeparateProcess = FALSE;

    /**
     * @var boolean
     */
    protected $useErrorHandler = FALSE;

    /**
     * @var boolean
     */
    protected $useOutputBuffering = FALSE;

    /**
     * @param string $message
     */
    public function __construct($message = '')
    {
        $this->message = $message;
        parent::__construct('Warning');
    }

    /**
     * @throws PHPUnit_Framework_Exception
     */
    protected function runTest()
    {
        $this->fail($this->message);
    }

    /**
     * @return string
     * @since  Method available since Release 3.0.0
     */
    public function getMessage()
    {
        return $this->message;
    }

    /**
     * Returns a string representation of the test case.
     *
     * @return string
     * @since  Method available since Release 3.4.0
     */
    public function toString()
    {
        return 'Warning';
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

/**
 * Extension to PHPUnit_Framework_AssertionFailedError to mark the special
 * case of an incomplete test.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.0.0
 */
class PHPUnit_Framework_IncompleteTestError extends PHPUnit_Framework_AssertionFailedError implements PHPUnit_Framework_IncompleteTest
{
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.1.0
 */

/**
 * Extension to PHPUnit_Framework_AssertionFailedError to mark the special
 * case of a skipped test suite.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.1.0
 */
class PHPUnit_Framework_SkippedTestSuiteError extends PHPUnit_Framework_AssertionFailedError implements PHPUnit_Framework_SkippedTest
{
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_TestSuite
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.4.0
 */

/**
 *
 *
 * @package    PHPUnit
 * @subpackage Framework_TestSuite
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.4.0
 */
class PHPUnit_Framework_TestSuite_DataProvider extends PHPUnit_Framework_TestSuite
{
    /**
     * Sets the dependencies of a TestCase.
     *
     * @param array $dependencies
     */
    public function setDependencies(array $dependencies)
    {
        foreach ($this->tests as $test) {
            $test->setDependencies($dependencies);
        }
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * Abstract base class for constraints. which are placed upon any value.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Interface available since Release 3.0.0
 */
abstract class PHPUnit_Framework_Constraint implements Countable, PHPUnit_Framework_SelfDescribing
{

    /**
     * Evaluates the constraint for parameter $other
     *
     * If $returnResult is set to FALSE (the default), an exception is thrown
     * in case of a failure. NULL is returned otherwise.
     *
     * If $returnResult is TRUE, the result of the evaluation is returned as
     * a boolean value instead: TRUE in case of success, FALSE in case of a
     * failure.
     *
     * @param  mixed $other Value or object to evaluate.
     * @param  string $description Additional information about the test
     * @param  bool $returnResult Whether to return a result or throw an exception
     * @return mixed
     * @throws PHPUnit_Framework_ExpectationFailedException
     */
    public function evaluate($other, $description = '', $returnResult = FALSE)
    {
        $success = FALSE;

        if ($this->matches($other)) {
            $success = TRUE;
        }

        if ($returnResult) {
            return $success;
        }

        if (!$success) {
            $this->fail($other, $description);
        }
    }

    /**
     * Evaluates the constraint for parameter $other. Returns TRUE if the
     * constraint is met, FALSE otherwise.
     *
     * This method can be overridden to implement the evaluation algorithm.
     *
     * @param mixed $other Value or object to evaluate.
     * @return bool
     */
    protected function matches($other)
    {
        return FALSE;
    }

    /**
     * Counts the number of constraint elements.
     *
     * @return integer
     * @since  Method available since Release 3.4.0
     */
    public function count()
    {
        return 1;
    }

    /**
     * Throws an exception for the given compared value and test description
     *
     * @param  mixed $other Evaluated value or object.
     * @param  string $description Additional information about the test
     * @param  PHPUnit_Framework_ComparisonFailure $comparisonFailure
     * @throws PHPUnit_Framework_ExpectationFailedException
     */
    protected function fail($other, $description, PHPUnit_Framework_ComparisonFailure $comparisonFailure = NULL)
    {
        $failureDescription = sprintf(
          'Failed asserting that %s.',
          $this->failureDescription($other)
        );

        $additionalFailureDescription = $this->additionalFailureDescription($other);
        if ($additionalFailureDescription) {
            $failureDescription .= "\n" . $additionalFailureDescription;
        }

        if (!empty($description)) {
            $failureDescription = $description . "\n" . $failureDescription;
        }

        throw new PHPUnit_Framework_ExpectationFailedException(
          $failureDescription,
          $comparisonFailure
        );
    }

    /**
     * Return additional failure description where needed
     *
     * The function can be overridden to provide additional failure
     * information like a diff
     *
     * @param  mixed $other Evaluated value or object.
     * @return string
     */
    protected function additionalFailureDescription($other)
    {
        return "";
    }

    /**
     * Returns the description of the failure
     *
     * The beginning of failure messages is "Failed asserting that" in most
     * cases. This method should return the second part of that sentence.
     *
     * To provide additional failure information additionalFailureDescription
     * can be used.
     *
     * @param  mixed $other Evaluated value or object.
     * @return string
     */
    protected function failureDescription($other)
    {
        return PHPUnit_Util_Type::export($other) . ' ' . $this->toString();
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.0
 */

/**
 * Factory for comparators which compare values for equality.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.0
 */
class PHPUnit_Framework_ComparatorFactory
{
    /**
     * @var array
     */
    protected $comparators = array();

    /**
     * @var PHPUnit_Framework_ComparatorFactory
     */
    private static $defaultInstance = NULL;

    /**
     * Constructs a new factory.
     */
    public function __construct()
    {
        $this->register(new PHPUnit_Framework_Comparator_Type);
        $this->register(new PHPUnit_Framework_Comparator_Scalar);
        $this->register(new PHPUnit_Framework_Comparator_Numeric);
        $this->register(new PHPUnit_Framework_Comparator_Double);
        $this->register(new PHPUnit_Framework_Comparator_Array);
        $this->register(new PHPUnit_Framework_Comparator_Resource);
        $this->register(new PHPUnit_Framework_Comparator_Object);
        $this->register(new PHPUnit_Framework_Comparator_Exception);
        $this->register(new PHPUnit_Framework_Comparator_SplObjectStorage);
        $this->register(new PHPUnit_Framework_Comparator_DOMDocument);
        $this->register(new PHPUnit_Framework_Comparator_MockObject);
    }

    /**
     * Returns the default instance.
     *
     * @return PHPUnit_Framework_ComparatorFactory
     */
    public static function getDefaultInstance()
    {
        if (self::$defaultInstance === NULL) {
            self::$defaultInstance = new PHPUnit_Framework_ComparatorFactory;
        }

        return self::$defaultInstance;
    }

    /**
     * Returns the correct comparator for comparing two values.
     *
     * @param  mixed $expected The first value to compare
     * @param  mixed $actual The second value to compare
     * @return PHPUnit_Framework_Comparator
     * @throws PHPUnit_Framework_Exception
     */
    public function getComparatorFor($expected, $actual)
    {
        foreach ($this->comparators as $comparator) {
            if ($comparator->accepts($expected, $actual)) {
                return $comparator;
            }
        }

        throw new PHPUnit_Framework_Exception(
          sprintf(
            'No comparator is registered for comparing the types "%s" and "%s"',
            gettype($expected), gettype($actual)
          )
        );
    }

    /**
     * Registers a new comparator.
     *
     * This comparator will be returned by getInstance() if its accept() method
     * returns TRUE for the compared values. It has higher priority than the
     * existing comparators, meaning that its accept() method will be tested
     * before those of the other comparators.
     *
     * @param  PHPUnit_Framework_Comparator $comparator The registered comparator
     */
    public function register(PHPUnit_Framework_Comparator $comparator)
    {
        array_unshift($this->comparators, $comparator);
        $comparator->setFactory($this);
    }

    /**
     * Unregisters a comparator.
     *
     * This comparator will no longer be returned by getInstance().
     *
     * @param  PHPUnit_Framework_Comparator $comparator The unregistered comparator
     */
    public function unregister(PHPUnit_Framework_Comparator $comparator)
    {
        foreach ($this->comparators as $key => $_comparator) {
            if ($comparator === $_comparator) {
                unset($this->comparators[$key]);
            }
        }
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * A marker interface for marking a unit test as being skipped.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Interface available since Release 3.0.0
 */
interface PHPUnit_Framework_SkippedTest
{
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.0
 */

/**
 * Abstract base class for comparators which compare values for equality.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.0
 */
abstract class PHPUnit_Framework_Comparator
{
    /**
     * @var PHPUnit_Framework_ComparatorFactory
     */
    protected $factory;

    /**
     * @param PHPUnit_Framework_ComparatorFactory $factory
     */
    public function setFactory(PHPUnit_Framework_ComparatorFactory $factory)
    {
        $this->factory = $factory;
    }

    /**
     * Returns whether the comparator can compare two values.
     *
     * @param  mixed $expected The first value to compare
     * @param  mixed $actual The second value to compare
     * @return boolean
     */
    abstract public function accepts($expected, $actual);

    /**
     * Asserts that two values are equal.
     *
     * @param  mixed $expected The first value to compare
     * @param  mixed $actual The second value to compare
     * @param  float $delta The allowed numerical distance between two values to
     *                      consider them equal
     * @param  bool  $canonicalize If set to TRUE, arrays are sorted before
     *                             comparison
     * @param  bool  $ignoreCase If set to TRUE, upper- and lowercasing is
     *                           ignored when comparing string values
     * @throws PHPUnit_Framework_ComparisonFailure Thrown when the comparison
     *                           fails. Contains information about the
     *                           specific errors that lead to the failure.
     */
    abstract public function assertEquals($expected, $actual, $delta = 0, $canonicalize = FALSE, $ignoreCase = FALSE);
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * Constraint that asserts that the Traversable it is applied to contains
 * a given value.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class PHPUnit_Framework_Constraint_TraversableContains extends PHPUnit_Framework_Constraint
{
    /**
     * @var boolean
     */
    protected $checkForObjectIdentity;

    /**
     * @var mixed
     */
    protected $value;

    /**
     * @param  boolean $value
     * @param  mixed   $checkForObjectIdentity
     * @throws PHPUnit_Framework_Exception
     */
    public function __construct($value, $checkForObjectIdentity = TRUE)
    {
        if (!is_bool($checkForObjectIdentity)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'boolean');
        }

        $this->checkForObjectIdentity = $checkForObjectIdentity;
        $this->value                  = $value;
    }

    /**
     * Evaluates the constraint for parameter $other. Returns TRUE if the
     * constraint is met, FALSE otherwise.
     *
     * @param mixed $other Value or object to evaluate.
     * @return bool
     */
    protected function matches($other)
    {
        if ($other instanceof SplObjectStorage) {
            return $other->contains($this->value);
        }

        if (is_object($this->value)) {
            foreach ($other as $element) {
                if (($this->checkForObjectIdentity &&
                     $element === $this->value) ||
                    (!$this->checkForObjectIdentity &&
                     $element == $this->value)) {
                    return TRUE;
                }
            }
        } else {
            foreach ($other as $element) {
                if ($element == $this->value) {
                    return TRUE;
                }
            }
        }

        return FALSE;
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        if (is_string($this->value) && strpos($this->value, "\n") !== FALSE) {
            return 'contains "' . $this->value . '"';
        } else {
            return 'contains ' . PHPUnit_Util_Type::export($this->value);
        }
    }

    /**
     * Returns the description of the failure
     *
     * The beginning of failure messages is "Failed asserting that" in most
     * cases. This method should return the second part of that sentence.
     *
     * @param  mixed $other Evaluated value or object.
     * @return string
     */
    protected function failureDescription($other)
    {
        return sprintf(
          'an %s %s',

           is_array($other) ? 'array' : 'iterator',
           $this->toString()
        );
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.1.0
 */

/**
 *
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.1.0
 */

class PHPUnit_Framework_Constraint_Attribute extends PHPUnit_Framework_Constraint_Composite
{
    /**
     * @var string
     */
    protected $attributeName;

    /**
     * @param PHPUnit_Framework_Constraint $constraint
     * @param string                       $attributeName
     */
    public function __construct(PHPUnit_Framework_Constraint $constraint, $attributeName)
    {
        parent::__construct($constraint);

        $this->attributeName = $attributeName;
    }

    /**
     * Evaluates the constraint for parameter $other
     *
     * If $returnResult is set to FALSE (the default), an exception is thrown
     * in case of a failure. NULL is returned otherwise.
     *
     * If $returnResult is TRUE, the result of the evaluation is returned as
     * a boolean value instead: TRUE in case of success, FALSE in case of a
     * failure.
     *
     * @param  mixed $other Value or object to evaluate.
     * @param  string $description Additional information about the test
     * @param  bool $returnResult Whether to return a result or throw an exception
     * @return mixed
     * @throws PHPUnit_Framework_ExpectationFailedException
     */
    public function evaluate($other, $description = '', $returnResult = FALSE)
    {
        return parent::evaluate(
          PHPUnit_Framework_Assert::readAttribute(
            $other, $this->attributeName
          ),
          $description,
          $returnResult
        );
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        return 'attribute "' . $this->attributeName . '" ' .
               $this->innerConstraint->toString();
    }

    /**
     * Returns the description of the failure
     *
     * The beginning of failure messages is "Failed asserting that" in most
     * cases. This method should return the second part of that sentence.
     *
     * @param  mixed $other Evaluated value or object.
     * @return string
     */
    protected function failureDescription($other)
    {
        return $this->toString();
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.5.0
 */

/**
 * ...
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.5.0
 */
class PHPUnit_Framework_Constraint_StringMatches extends PHPUnit_Framework_Constraint_PCREMatch
{
    /**
     * @var string
     */
    protected $string;

    /**
     * @param string $string
     */
    public function __construct($string)
    {
        $this->pattern = $this->createPatternFromFormat(
            preg_replace('/\r\n/', "\n", $string)
        );
        $this->string  = $string;
    }

    protected function failureDescription($other)
    {
        return "format description matches text";
    }

    protected function additionalFailureDescription($other)
    {
        $from = preg_split('(\r\n|\r|\n)', $this->string);
        $to = preg_split('(\r\n|\r|\n)', $other);
        foreach ($from as $index => $line) {
            if (isset($to[$index]) && $line !== $to[$index]) {
                $line = $this->createPatternFromFormat($line);
                if (preg_match($line, $to[$index]) > 0) {
                    $from[$index] = $to[$index];
                }
            }
        }
        $this->string = join("\n", $from);
        $other = join("\n", $to);
        return PHPUnit_Util_Diff::diff($this->string, $other);
    }

    protected function createPatternFromFormat($string)
    {
        $string = str_replace(
          array(
            '%e',
            '%s',
            '%S',
            '%a',
            '%A',
            '%w',
            '%i',
            '%d',
            '%x',
            '%f',
            '%c'
          ),
          array(
            '\\' . DIRECTORY_SEPARATOR,
            '[^\r\n]+',
            '[^\r\n]*',
            '.+',
            '.*',
            '\s*',
            '[+-]?\d+',
            '\d+',
            '[0-9a-fA-F]+',
            '[+-]?\.?\d+\.?\d*(?:[Ee][+-]?\d+)?',
            '.'
          ),
          preg_quote($string, '/')
        );
        return '/^' . $string . '$/s';
    }

}

<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.1.0
 */

/**
 * Constraint that asserts that the class it is evaluated for has a given
 * static attribute.
 *
 * The attribute name is passed in the constructor.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.1.0
 */
class PHPUnit_Framework_Constraint_ClassHasStaticAttribute extends PHPUnit_Framework_Constraint_ClassHasAttribute
{
    /**
     * Evaluates the constraint for parameter $other. Returns TRUE if the
     * constraint is met, FALSE otherwise.
     *
     * @param mixed $other Value or object to evaluate.
     * @return bool
     */
    protected function matches($other)
    {
        $class = new ReflectionClass($other);

        if ($class->hasProperty($this->attributeName)) {
            $attribute = $class->getProperty($this->attributeName);

            return $attribute->isStatic();
        } else {
            return FALSE;
        }
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     * @since  Method available since Release 3.3.0
     */
    public function toString()
    {
        return sprintf(
          'has static attribute "%s"',

          $this->attributeName
        );
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.6
 */

/**
 *
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.6
 */
class PHPUnit_Framework_Constraint_Exception extends PHPUnit_Framework_Constraint
{
    /**
     * @var string
     */
    protected $className;

    /**
     * @param string $className
     */
    public function __construct($className)
    {
        $this->className = $className;
    }

    /**
     * Evaluates the constraint for parameter $other. Returns TRUE if the
     * constraint is met, FALSE otherwise.
     *
     * @param mixed $other Value or object to evaluate.
     * @return bool
     */
    protected function matches($other)
    {
        return $other instanceof $this->className;
    }

    /**
     * Returns the description of the failure
     *
     * The beginning of failure messages is "Failed asserting that" in most
     * cases. This method should return the second part of that sentence.
     *
     * @param  mixed $other Evaluated value or object.
     * @return string
     */
    protected function failureDescription($other)
    {
        if ($other !== NULL) {
            $message = '';
            if ($other instanceof Exception && $other->getMessage()) {
                $message = '. Message was: "' . $other->getMessage() . '"';
            }
            return sprintf(
              'exception of type "%s" matches expected exception "%s"%s',

              get_class($other),
              $this->className,
              $message
            );
        }

        return sprintf(
          'exception of type "%s" is thrown',

          $this->className
        );
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        return sprintf(
          'exception of type "%s"',

          $this->className
        );
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * Logical NOT.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */

class PHPUnit_Framework_Constraint_Not extends PHPUnit_Framework_Constraint
{
    /**
     * @var PHPUnit_Framework_Constraint
     */
    protected $constraint;

    /**
     * @param PHPUnit_Framework_Constraint $constraint
     */
    public function __construct($constraint)
    {
        if (!($constraint instanceof PHPUnit_Framework_Constraint)) {
            $constraint = new PHPUnit_Framework_Constraint_IsEqual($constraint);
        }

        $this->constraint = $constraint;
    }

    /**
     * @param  string $string
     * @return string
     */
    public static function negate($string)
    {
        return str_replace(
          array(
            'contains ',
            'exists',
            'has ',
            'is ',
            'are ',
            'matches ',
            'starts with ',
            'ends with ',
            'reference ',
            'not not '
          ),
          array(
            'does not contain ',
            'does not exist',
            'does not have ',
            'is not ',
            'are not ',
            'does not match ',
            'starts not with ',
            'ends not with ',
            'don\'t reference ',
            'not '
          ),
          $string
        );
    }

    /**
     * Evaluates the constraint for parameter $other
     *
     * If $returnResult is set to FALSE (the default), an exception is thrown
     * in case of a failure. NULL is returned otherwise.
     *
     * If $returnResult is TRUE, the result of the evaluation is returned as
     * a boolean value instead: TRUE in case of success, FALSE in case of a
     * failure.
     *
     * @param  mixed $other Value or object to evaluate.
     * @param  string $description Additional information about the test
     * @param  bool $returnResult Whether to return a result or throw an exception
     * @return mixed
     * @throws PHPUnit_Framework_ExpectationFailedException
     */
    public function evaluate($other, $description = '', $returnResult = FALSE)
    {
        $success = !$this->constraint->evaluate($other, $description, TRUE);

        if ($returnResult) {
            return $success;
        }

        if (!$success) {
            $this->fail($other, $description);
        }
    }

    /**
     * Returns the description of the failure
     *
     * The beginning of failure messages is "Failed asserting that" in most
     * cases. This method should return the second part of that sentence.
     *
     * @param  mixed $other Evaluated value or object.
     * @return string
     */
    protected function failureDescription($other)
    {
        switch (get_class($this->constraint)) {
            case 'PHPUnit_Framework_Constraint_And':
            case 'PHPUnit_Framework_Constraint_Not':
            case 'PHPUnit_Framework_Constraint_Or': {
                return 'not( ' . $this->constraint->failureDescription($other) . ' )';
            }
            break;

            default: {
                return self::negate(
                  $this->constraint->failureDescription($other)
                );
            }
        }
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        switch (get_class($this->constraint)) {
            case 'PHPUnit_Framework_Constraint_And':
            case 'PHPUnit_Framework_Constraint_Not':
            case 'PHPUnit_Framework_Constraint_Or': {
                return 'not( ' . $this->constraint->toString() . ' )';
            }
            break;

            default: {
                return self::negate(
                  $this->constraint->toString()
                );
            }
        }
    }

    /**
     * Counts the number of constraint elements.
     *
     * @return integer
     * @since  Method available since Release 3.4.0
     */
    public function count()
    {
        return count($this->constraint);
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.4.0
 */

/**
 * Constraint that asserts that the string it is evaluated for ends with a given
 * suffix.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.4.0
 */
class PHPUnit_Framework_Constraint_StringEndsWith extends PHPUnit_Framework_Constraint
{
    /**
     * @var string
     */
    protected $suffix;

    /**
     * @param string $suffix
     */
    public function __construct($suffix)
    {
        $this->suffix = $suffix;
    }

    /**
     * Evaluates the constraint for parameter $other. Returns TRUE if the
     * constraint is met, FALSE otherwise.
     *
     * @param mixed $other Value or object to evaluate.
     * @return bool
     */
    protected function matches($other)
    {
        return substr($other, 0 - strlen($this->suffix)) == $this->suffix;
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        return 'ends with "' . $this->suffix . '"';
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2002-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Bastian Feder <php@bastian-feder.de>
 * @copyright  2002-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.7.0
 */

/**
 * Asserts whether or not two JSON objects are equal.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Bastian Feder <php@bastian-feder.de>
 * @copyright  2011 Bastian Feder <php@bastian-feder.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.7.0
 */
class PHPUnit_Framework_Constraint_JsonMatches extends PHPUnit_Framework_Constraint
{
    /**
     * @var string
     */
    protected $value;

    /**
     * Creates a new constraint.
     *
     * @param string $value
     */
    public function __construct($value)
    {
        $this->value = $value;
    }

    /**
     * Evaluates the constraint for parameter $other. Returns TRUE if the
     * constraint is met, FALSE otherwise.
     *
     * This method can be overridden to implement the evaluation algorithm.
     *
     * @param mixed $other Value or object to evaluate.
     * @return bool
     */
    protected function matches($other)
    {
        $decodedOther = json_decode($other);
        if (json_last_error()) {
            return FALSE;
        }

        $decodedValue = json_decode($this->value);
        if (json_last_error()) {
            return FALSE;
        }

        return $decodedOther == $decodedValue;
    }

    /**
     * Returns a string representation of the object.
     *
     * @return string
     */
    public function toString()
    {
        return sprintf(
            'matches JSON string "%s"',
            $this->value
        );
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.5.0
 */

/**
 * Constraint that checks whether a variable is empty().
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.5.0
 */
class PHPUnit_Framework_Constraint_IsEmpty extends PHPUnit_Framework_Constraint
{
    /**
     * Evaluates the constraint for parameter $other. Returns TRUE if the
     * constraint is met, FALSE otherwise.
     *
     * @param mixed $other Value or object to evaluate.
     * @return bool
     */
    protected function matches($other)
    {
        return empty($other);
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        return 'is empty';
    }

    /**
     * Returns the description of the failure
     *
     * The beginning of failure messages is "Failed asserting that" in most
     * cases. This method should return the second part of that sentence.
     *
     * @param  mixed $other Evaluated value or object.
     * @return string
     */
    protected function failureDescription($other)
    {
        $type = gettype($other);

        return sprintf(
          '%s %s %s',

          $type[0] == 'a' || $type[0] == 'o' ? 'an' : 'a',
          $type,
          $this->toString()
        );
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * Constraint that asserts that the object it is evaluated for has a given
 * attribute.
 *
 * The attribute name is passed in the constructor.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class PHPUnit_Framework_Constraint_ObjectHasAttribute extends PHPUnit_Framework_Constraint_ClassHasAttribute
{
    /**
     * Evaluates the constraint for parameter $other. Returns TRUE if the
     * constraint is met, FALSE otherwise.
     *
     * @param mixed $other Value or object to evaluate.
     * @return bool
     */
    protected function matches($other)
    {
        $object = new ReflectionObject($other);

        return $object->hasProperty($this->attributeName);
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.3.0
 */

/**
 * Constraint that accepts NULL.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.3.0
 */
class PHPUnit_Framework_Constraint_IsNull extends PHPUnit_Framework_Constraint
{
    /**
     * Evaluates the constraint for parameter $other. Returns TRUE if the
     * constraint is met, FALSE otherwise.
     *
     * @param mixed $other Value or object to evaluate.
     * @return bool
     */
    protected function matches($other)
    {
        return $other === NULL;
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        return 'is null';
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * Constraint that asserts that the value it is evaluated for is less than
 * a given value.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class PHPUnit_Framework_Constraint_LessThan extends PHPUnit_Framework_Constraint
{
    /**
     * @var numeric
     */
    protected $value;

    /**
     * @param numeric $value
     */
    public function __construct($value)
    {
        $this->value = $value;
    }

    /**
     * Evaluates the constraint for parameter $other. Returns TRUE if the
     * constraint is met, FALSE otherwise.
     *
     * @param mixed $other Value or object to evaluate.
     * @return bool
     */
    protected function matches($other)
    {
        return $this->value > $other;
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        return 'is less than ' . PHPUnit_Util_Type::export($this->value);
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2002-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2002-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 */

/**
 * Constraint that evaluates against a specified closure.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Timon Rapp <timon@zaeda.net>
 * @copyright  2002-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 */
class PHPUnit_Framework_Constraint_Callback extends PHPUnit_Framework_Constraint
{
    private $callback;

    /**
     * @param callable $callback
     * @throws InvalidArgumentException
     */
    public function __construct($callback)
    {
        if (!is_callable($callback)) {
            throw new InvalidArgumentException(
              sprintf(
                'Specified callback <%s> is not callable.',
                $this->callbackToString($callback)
              )
            );
        }
        $this->callback = $callback;
    }

    /**
     * Evaluates the constraint for parameter $value. Returns TRUE if the
     * constraint is met, FALSE otherwise.
     *
     * @param mixed $value Value or object to evaluate.
     * @return bool
     */
    protected function matches($other)
    {
        return call_user_func($this->callback, $other);
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        return 'is accepted by specified callback';
    }

    private function callbackToString($callback)
    {
        if (!is_array($callback)) {
            return $callback;
        }
        if (empty($callback)) {
            return "empty array";
        }
        if (!isset($callback[0]) || !isset($callback[1])) {
            return "array without indexes 0 and 1 set";
        }
        if (is_object($callback[0])) {
            $callback[0] = get_class($callback[0]);
        }
        return $callback[0] . '::' . $callback[1];
    }

}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.0
 */

/**
 *
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.0
 */

abstract class PHPUnit_Framework_Constraint_Composite extends PHPUnit_Framework_Constraint
{
    /**
     * @var PHPUnit_Framework_Constraint
     */
    protected $innerConstraint;

    /**
     * @param PHPUnit_Framework_Constraint $innerConstraint
     * @param string                       $attributeName
     */
    public function __construct(PHPUnit_Framework_Constraint $innerConstraint)
    {
        $this->innerConstraint = $innerConstraint;
    }

    /**
     * Evaluates the constraint for parameter $other
     *
     * If $returnResult is set to FALSE (the default), an exception is thrown
     * in case of a failure. NULL is returned otherwise.
     *
     * If $returnResult is TRUE, the result of the evaluation is returned as
     * a boolean value instead: TRUE in case of success, FALSE in case of a
     * failure.
     *
     * @param  mixed $other Value or object to evaluate.
     * @param  string $description Additional information about the test
     * @param  bool $returnResult Whether to return a result or throw an exception
     * @return mixed
     * @throws PHPUnit_Framework_ExpectationFailedException
     */
    public function evaluate($other, $description = '', $returnResult = FALSE)
    {
        try {
            return $this->innerConstraint->evaluate(
              $other,
              $description,
              $returnResult
            );
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->fail($other, $description);
        }
    }

    /**
     * Counts the number of constraint elements.
     *
     * @return integer
     */
    public function count()
    {
        return count($this->innerConstraint);
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * Logical XOR.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class PHPUnit_Framework_Constraint_Xor extends PHPUnit_Framework_Constraint
{
    /**
     * @var PHPUnit_Framework_Constraint[]
     */
    protected $constraints = array();

    /**
     * @param PHPUnit_Framework_Constraint[] $constraints
     */
    public function setConstraints(array $constraints)
    {
        $this->constraints = array();

        foreach ($constraints as $key => $constraint) {
            if (!($constraint instanceof PHPUnit_Framework_Constraint)) {
                $constraint = new PHPUnit_Framework_Constraint_IsEqual(
                  $constraint
                );
            }

            $this->constraints[] = $constraint;
        }
    }

    /**
     * Evaluates the constraint for parameter $other
     *
     * If $returnResult is set to FALSE (the default), an exception is thrown
     * in case of a failure. NULL is returned otherwise.
     *
     * If $returnResult is TRUE, the result of the evaluation is returned as
     * a boolean value instead: TRUE in case of success, FALSE in case of a
     * failure.
     *
     * @param  mixed $other Value or object to evaluate.
     * @param  string $description Additional information about the test
     * @param  bool $returnResult Whether to return a result or throw an exception
     * @return mixed
     * @throws PHPUnit_Framework_ExpectationFailedException
     */
    public function evaluate($other, $description = '', $returnResult = FALSE)
    {
        $success = TRUE;
        $lastResult = NULL;
        $constraint = NULL;

        foreach ($this->constraints as $constraint) {
            $result = $constraint->evaluate($other, $description, TRUE);

            if ($result === $lastResult) {
                $success = FALSE;
                break;
            }

            $lastResult = $result;
        }

        if ($returnResult) {
            return $success;
        }

        if (!$success) {
            $this->fail($other, $description);
        }
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        $text = '';

        foreach ($this->constraints as $key => $constraint) {
            if ($key > 0) {
                $text .= ' xor ';
            }

            $text .= $constraint->toString();
        }

        return $text;
    }

    /**
     * Counts the number of constraint elements.
     *
     * @return integer
     * @since  Method available since Release 3.4.0
     */
    public function count()
    {
        $count = 0;

        foreach ($this->constraints as $constraint) {
            $count += count($constraint);
        }

        return $count;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * Constraint that asserts that the string it is evaluated for contains
 * a given string.
 *
 * Uses strpos() to find the position of the string in the input, if not found
 * the evaluaton fails.
 *
 * The sub-string is passed in the constructor.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class PHPUnit_Framework_Constraint_StringContains extends PHPUnit_Framework_Constraint
{
    /**
     * @var string
     */
    protected $string;

    /**
     * @var boolean
     */
    protected $ignoreCase;

    /**
     * @param string  $string
     * @param boolean $ignoreCase
     */
    public function __construct($string, $ignoreCase = FALSE)
    {
        $this->string     = $string;
        $this->ignoreCase = $ignoreCase;
    }

    /**
     * Evaluates the constraint for parameter $other. Returns TRUE if the
     * constraint is met, FALSE otherwise.
     *
     * @param mixed $other Value or object to evaluate.
     * @return bool
     */
    protected function matches($other)
    {
        if ($this->ignoreCase) {
            return stripos($other, $this->string) !== FALSE;
        } else {
            return strpos($other, $this->string) !== FALSE;
        }
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        if ($this->ignoreCase) {
            $string = strtolower($this->string);
        } else {
            $string = $this->string;
        }

        return sprintf(
          'contains "%s"',

          $string
        );
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * Logical AND.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class PHPUnit_Framework_Constraint_And extends PHPUnit_Framework_Constraint
{
    /**
     * @var PHPUnit_Framework_Constraint[]
     */
    protected $constraints = array();

    /**
     * @var PHPUnit_Framework_Constraint
     */
    protected $lastConstraint = NULL;

    /**
     * @param  PHPUnit_Framework_Constraint[] $constraints
     * @throws PHPUnit_Framework_Exception
     */
    public function setConstraints(array $constraints)
    {
        $this->constraints = array();

        foreach ($constraints as $key => $constraint) {
            if (!($constraint instanceof PHPUnit_Framework_Constraint)) {
                throw new PHPUnit_Framework_Exception(
                  'All parameters to ' . __CLASS__ .
                  ' must be a constraint object.'
                );
            }

            $this->constraints[] = $constraint;
        }
    }

    /**
     * Evaluates the constraint for parameter $other
     *
     * If $returnResult is set to FALSE (the default), an exception is thrown
     * in case of a failure. NULL is returned otherwise.
     *
     * If $returnResult is TRUE, the result of the evaluation is returned as
     * a boolean value instead: TRUE in case of success, FALSE in case of a
     * failure.
     *
     * @param  mixed $other Value or object to evaluate.
     * @param  string $description Additional information about the test
     * @param  bool $returnResult Whether to return a result or throw an exception
     * @return mixed
     * @throws PHPUnit_Framework_ExpectationFailedException
     */
    public function evaluate($other, $description = '', $returnResult = FALSE)
    {
        $success = TRUE;
        $constraint = NULL;

        foreach ($this->constraints as $constraint) {
            if (!$constraint->evaluate($other, $description, TRUE)) {
                $success = FALSE;
                break;
            }
        }

        if ($returnResult) {
            return $success;
        }

        if (!$success) {
            $this->fail($other, $description);
        }
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        $text = '';

        foreach ($this->constraints as $key => $constraint) {
            if ($key > 0) {
                $text .= ' and ';
            }

            $text .= $constraint->toString();
        }

        return $text;
    }

    /**
     * Counts the number of constraint elements.
     *
     * @return integer
     * @since  Method available since Release 3.4.0
     */
    public function count()
    {
        $count = 0;

        foreach ($this->constraints as $constraint) {
            $count += count($constraint);
        }

        return $count;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * Constraint that asserts that the value it is evaluated for is greater
 * than a given value.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class PHPUnit_Framework_Constraint_GreaterThan extends PHPUnit_Framework_Constraint
{
    /**
     * @var numeric
     */
    protected $value;

    /**
     * @param numeric $value
     */
    public function __construct($value)
    {
        $this->value = $value;
    }

    /**
     * Evaluates the constraint for parameter $other. Returns TRUE if the
     * constraint is met, FALSE otherwise.
     *
     * @param mixed $other Value or object to evaluate.
     * @return bool
     */
    protected function matches($other)
    {
        return $this->value < $other;
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        return 'is greater than ' . PHPUnit_Util_Type::export($this->value);
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.0
 */

/**
 *
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.0
 */
class PHPUnit_Framework_Constraint_Count extends PHPUnit_Framework_Constraint
{
    /**
     * @var integer
     */
    protected $expectedCount = 0;

    /**
     * @param integer $expected
     */
    public function __construct($expected)
    {
        $this->expectedCount = $expected;
    }

    /**
     * Evaluates the constraint for parameter $other. Returns TRUE if the
     * constraint is met, FALSE otherwise.
     *
     * @param mixed $other
     * @return boolean
     */
    protected function matches($other)
    {
        return $this->expectedCount === $this->getCountOf($other);
    }

    /**
     * @param mixed $other
     * @return boolean
     */
    protected function getCountOf($other)
    {
        if ($other instanceof Countable || is_array($other)) {
            return count($other);
        }

        else if ($other instanceof Iterator) {
            return iterator_count($other);
        }
    }


    /**
     * Returns the description of the failure
     *
     * The beginning of failure messages is "Failed asserting that" in most
     * cases. This method should return the second part of that sentence.
     *
     * @param  mixed $other Evaluated value or object.
     * @return string
     */
    protected function failureDescription($other)
    {
        return sprintf(
          'actual size %d matches expected size %d',

          $this->getCountOf($other),
          $this->expectedCount
        );
    }

    /**
     * @return string
     */
    public function toString()
    {
        return 'count matches ';
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * Constraint that asserts that the array it is evaluated for has a given key.
 *
 * Uses array_key_exists() to check if the key is found in the input array, if
 * not found the evaluaton fails.
 *
 * The array key is passed in the constructor.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class PHPUnit_Framework_Constraint_ArrayHasKey extends PHPUnit_Framework_Constraint
{
    /**
     * @var integer|string
     */
    protected $key;

    /**
     * @param integer|string $key
     */
    public function __construct($key)
    {
        $this->key = $key;
    }

    /**
     * Evaluates the constraint for parameter $other. Returns TRUE if the
     * constraint is met, FALSE otherwise.
     *
     * @param mixed $other Value or object to evaluate.
     * @return bool
     */
    protected function matches($other)
    {
        return array_key_exists($this->key, $other);
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        return 'has the key ' . PHPUnit_Util_Type::export($this->key);
    }

    /**
     * Returns the description of the failure
     *
     * The beginning of failure messages is "Failed asserting that" in most
     * cases. This method should return the second part of that sentence.
     *
     * @param  mixed $other Evaluated value or object.
     * @return string
     */
    protected function failureDescription($other)
    {
        return 'an array ' . $this->toString();
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.7.20
 */

/**
 * Constraint that asserts that a string is valid JSON.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.7.20
 */
class PHPUnit_Framework_Constraint_IsJson extends PHPUnit_Framework_Constraint
{
    /**
     * Evaluates the constraint for parameter $other. Returns TRUE if the
     * constraint is met, FALSE otherwise.
     *
     * @param mixed $other Value or object to evaluate.
     * @return bool
     */
    protected function matches($other)
    {
        json_decode($other);
        if (json_last_error()) {
            return FALSE;
        }

        return TRUE;
    }

    /**
     * Returns the description of the failure
     *
     * The beginning of failure messages is "Failed asserting that" in most
     * cases. This method should return the second part of that sentence.
     *
     * @param  mixed $other Evaluated value or object.
     * @return string
     */
    protected function failureDescription($other)
    {
        json_decode($other);
        $error = PHPUnit_Framework_Constraint_JsonMatches_ErrorMessageProvider::determineJsonError(
          json_last_error()
        );

        return sprintf(
          '%s is valid JSON (%s)',

          PHPUnit_Util_Type::shortenedExport($other),
          $error
        );
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        return 'is valid JSON';
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * Logical OR.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class PHPUnit_Framework_Constraint_Or extends PHPUnit_Framework_Constraint
{
    /**
     * @var PHPUnit_Framework_Constraint[]
     */
    protected $constraints = array();

    /**
     * @param PHPUnit_Framework_Constraint[] $constraints
     */
    public function setConstraints(array $constraints)
    {
        $this->constraints = array();

        foreach ($constraints as $key => $constraint) {
            if (!($constraint instanceof PHPUnit_Framework_Constraint)) {
                $constraint = new PHPUnit_Framework_Constraint_IsEqual(
                  $constraint
                );
            }

            $this->constraints[] = $constraint;
        }
    }

    /**
     * Evaluates the constraint for parameter $other
     *
     * If $returnResult is set to FALSE (the default), an exception is thrown
     * in case of a failure. NULL is returned otherwise.
     *
     * If $returnResult is TRUE, the result of the evaluation is returned as
     * a boolean value instead: TRUE in case of success, FALSE in case of a
     * failure.
     *
     * @param  mixed $other Value or object to evaluate.
     * @param  string $description Additional information about the test
     * @param  bool $returnResult Whether to return a result or throw an exception
     * @return mixed
     * @throws PHPUnit_Framework_ExpectationFailedException
     */
    public function evaluate($other, $description = '', $returnResult = FALSE)
    {
        $success = FALSE;
        $constraint = NULL;

        foreach ($this->constraints as $constraint) {
            if ($constraint->evaluate($other, $description, TRUE)) {
                $success = TRUE;
                break;
            }
        }

        if ($returnResult) {
            return $success;
        }

        if (!$success) {
            $this->fail($other, $description);
        }
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        $text = '';

        foreach ($this->constraints as $key => $constraint) {
            if ($key > 0) {
                $text .= ' or ';
            }

            $text .= $constraint->toString();
        }

        return $text;
    }

    /**
     * Counts the number of constraint elements.
     *
     * @return integer
     * @since  Method available since Release 3.4.0
     */
    public function count()
    {
        $count = 0;

        foreach ($this->constraints as $constraint) {
            $count += count($constraint);
        }

        return $count;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * Constraint that asserts that the object it is evaluated for is an instance
 * of a given class.
 *
 * The expected class name is passed in the constructor.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class PHPUnit_Framework_Constraint_IsInstanceOf extends PHPUnit_Framework_Constraint
{
    /**
     * @var string
     */
    protected $className;

    /**
     * @param string $className
     */
    public function __construct($className)
    {
        $this->className = $className;
    }

    /**
     * Evaluates the constraint for parameter $other. Returns TRUE if the
     * constraint is met, FALSE otherwise.
     *
     * @param mixed $other Value or object to evaluate.
     * @return bool
     */
    protected function matches($other)
    {
        return ($other instanceof $this->className);
    }

    /**
     * Returns the description of the failure
     *
     * The beginning of failure messages is "Failed asserting that" in most
     * cases. This method should return the second part of that sentence.
     *
     * @param  mixed $other Evaluated value or object.
     * @return string
     */
    protected function failureDescription($other)
    {
        return sprintf(
          '%s is an instance of class "%s"',

          PHPUnit_Util_Type::shortenedExport($other),
          $this->className
        );
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        return sprintf(
          'is instance of class "%s"',

          $this->className
        );
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.6
 */

/**
 *
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.6
 */
class PHPUnit_Framework_Constraint_ExceptionMessage extends PHPUnit_Framework_Constraint
{
    /**
     * @var integer
     */
    protected $expectedMessage;

    /**
     * @param string $expected
     */
    public function __construct($expected)
    {
        $this->expectedMessage = $expected;
    }

    /**
     * Evaluates the constraint for parameter $other. Returns TRUE if the
     * constraint is met, FALSE otherwise.
     *
     * @param  Exception $other
     * @return boolean
     */
    protected function matches($other)
    {
        return strpos($other->getMessage(), $this->expectedMessage) !== FALSE;
    }

    /**
     * Returns the description of the failure
     *
     * The beginning of failure messages is "Failed asserting that" in most
     * cases. This method should return the second part of that sentence.
     *
     * @param  mixed $other Evaluated value or object.
     * @return string
     */
    protected function failureDescription($other)
    {
        return sprintf(
          "exception message '%s' contains '%s'",
          $other->getMessage(),
          $this->expectedMessage
        );
    }

    /**
     * @return string
     */
    public function toString()
    {
        return 'exception message contains ';
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Kore Nordmann <kn@ez.no>
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * Constraint that checks if one value is equal to another.
 *
 * Equality is checked with PHP's == operator, the operator is explained in
 * detail at {@url http://www.php.net/manual/en/types.comparisons.php}.
 * Two values are equal if they have the same value disregarding type.
 *
 * The expected value is passed in the constructor.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Kore Nordmann <kn@ez.no>
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class PHPUnit_Framework_Constraint_IsEqual extends PHPUnit_Framework_Constraint
{
    /**
     * @var mixed
     */
    protected $value;

    /**
     * @var float
     */
    protected $delta = 0;

    /**
     * @var integer
     */
    protected $maxDepth = 10;

    /**
     * @var boolean
     */
    protected $canonicalize = FALSE;

    /**
     * @var boolean
     */
    protected $ignoreCase = FALSE;

    /**
     * @var PHPUnit_Framework_ComparisonFailure
     */
    protected $lastFailure;

    /**
     * @param mixed   $value
     * @param float   $delta
     * @param integer $maxDepth
     * @param boolean $canonicalize
     * @param boolean $ignoreCase
     */
    public function __construct($value, $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE)
    {
        if (!is_numeric($delta)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'numeric');
        }

        if (!is_int($maxDepth)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(3, 'integer');
        }

        if (!is_bool($canonicalize)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(4, 'boolean');
        }

        if (!is_bool($ignoreCase)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(5, 'boolean');
        }

        $this->value        = $value;
        $this->delta        = $delta;
        $this->maxDepth     = $maxDepth;
        $this->canonicalize = $canonicalize;
        $this->ignoreCase   = $ignoreCase;
    }

    /**
     * Evaluates the constraint for parameter $other
     *
     * If $returnResult is set to FALSE (the default), an exception is thrown
     * in case of a failure. NULL is returned otherwise.
     *
     * If $returnResult is TRUE, the result of the evaluation is returned as
     * a boolean value instead: TRUE in case of success, FALSE in case of a
     * failure.
     *
     * @param  mixed $other Value or object to evaluate.
     * @param  string $description Additional information about the test
     * @param  bool $returnResult Whether to return a result or throw an exception
     * @return mixed
     * @throws PHPUnit_Framework_ExpectationFailedException
     */
    public function evaluate($other, $description = '', $returnResult = FALSE)
    {
        $comparatorFactory = PHPUnit_Framework_ComparatorFactory::getDefaultInstance();

        try {
            $comparator = $comparatorFactory->getComparatorFor(
              $other, $this->value
            );

            $comparator->assertEquals(
              $this->value,
              $other,
              $this->delta,
              $this->canonicalize,
              $this->ignoreCase
            );
        }

        catch (PHPUnit_Framework_ComparisonFailure $f) {
            if ($returnResult) {
                return FALSE;
            }

            throw new PHPUnit_Framework_ExpectationFailedException(
              trim($description . "\n" . $f->getMessage()),
              $f
            );
        }

        return TRUE;
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        $delta = '';

        if (is_string($this->value)) {
            if (strpos($this->value, "\n") !== FALSE) {
                return 'is equal to <text>';
            } else {
                return sprintf(
                  'is equal to <string:%s>',

                  $this->value
                );
            }
        } else {
            if ($this->delta != 0) {
                $delta = sprintf(
                  ' with delta <%F>',

                  $this->delta
                );
            }

            return sprintf(
              'is equal to %s%s',

              PHPUnit_Util_Type::export($this->value),
              $delta
            );
        }
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.1.0
 */

/**
 * Constraint that asserts that the class it is evaluated for has a given
 * attribute.
 *
 * The attribute name is passed in the constructor.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.1.0
 */
class PHPUnit_Framework_Constraint_ClassHasAttribute extends PHPUnit_Framework_Constraint
{
    /**
     * @var string
     */
    protected $attributeName;

    /**
     * @param string $attributeName
     */
    public function __construct($attributeName)
    {
        $this->attributeName = $attributeName;
    }

    /**
     * Evaluates the constraint for parameter $other. Returns TRUE if the
     * constraint is met, FALSE otherwise.
     *
     * @param mixed $other Value or object to evaluate.
     * @return bool
     */
    protected function matches($other)
    {
        $class = new ReflectionClass($other);

        return $class->hasProperty($this->attributeName);
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        return sprintf(
          'has attribute "%s"',

          $this->attributeName
        );
    }

    /**
     * Returns the description of the failure
     *
     * The beginning of failure messages is "Failed asserting that" in most
     * cases. This method should return the second part of that sentence.
     *
     * @param  mixed $other Evaluated value or object.
     * @return string
     */
    protected function failureDescription($other)
    {
        return sprintf(
          '%sclass "%s" %s',

          is_object($other) ? 'object of ' : '',
          is_object($other) ? get_class($other) : $other,
          $this->toString()
        );
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * Constraint that accepts any input value.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class PHPUnit_Framework_Constraint_IsAnything extends PHPUnit_Framework_Constraint
{
    /**
     * Evaluates the constraint for parameter $other
     *
     * If $returnResult is set to FALSE (the default), an exception is thrown
     * in case of a failure. NULL is returned otherwise.
     *
     * If $returnResult is TRUE, the result of the evaluation is returned as
     * a boolean value instead: TRUE in case of success, FALSE in case of a
     * failure.
     *
     * @param  mixed $other Value or object to evaluate.
     * @param  string $description Additional information about the test
     * @param  bool $returnResult Whether to return a result or throw an exception
     * @return mixed
     * @throws PHPUnit_Framework_ExpectationFailedException
     */
    public function evaluate($other, $description = '', $returnResult = FALSE)
    {
        return $returnResult ? TRUE : NULL;
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        return 'is anything';
    }

    /**
     * Counts the number of constraint elements.
     *
     * @return integer
     * @since  Method available since Release 3.5.0
     */
    public function count()
    {
        return 0;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * Constraint that asserts that the string it is evaluated for matches
 * a regular expression.
 *
 * Checks a given value using the Perl Compatible Regular Expression extension
 * in PHP. The pattern is matched by executing preg_match().
 *
 * The pattern string passed in the constructor.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class PHPUnit_Framework_Constraint_PCREMatch extends PHPUnit_Framework_Constraint
{
    /**
     * @var string
     */
    protected $pattern;

    /**
     * @param string $pattern
     */
    public function __construct($pattern)
    {
        $this->pattern = $pattern;
    }

    /**
     * Evaluates the constraint for parameter $other. Returns TRUE if the
     * constraint is met, FALSE otherwise.
     *
     * @param mixed $other Value or object to evaluate.
     * @return bool
     */
    protected function matches($other)
    {
        return preg_match($this->pattern, $other) > 0;
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        return sprintf(
          'matches PCRE pattern "%s"',

          $this->pattern
        );
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.6
 */

/**
 *
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.6
 */
class PHPUnit_Framework_Constraint_ExceptionCode extends PHPUnit_Framework_Constraint
{
    /**
     * @var integer
     */
    protected $expectedCode;

    /**
     * @param integer $expected
     */
    public function __construct($expected)
    {
        $this->expectedCode = $expected;
    }

    /**
     * Evaluates the constraint for parameter $other. Returns TRUE if the
     * constraint is met, FALSE otherwise.
     *
     * @param  Exception $other
     * @return boolean
     */
    protected function matches($other)
    {
        return (string)$other->getCode() == (string)$this->expectedCode;
    }

    /**
     * Returns the description of the failure
     *
     * The beginning of failure messages is "Failed asserting that" in most
     * cases. This method should return the second part of that sentence.
     *
     * @param  mixed $other Evaluated value or object.
     * @return string
     */
    protected function failureDescription($other)
    {
        return sprintf(
          '%s is equal to expected exception code %s',
          PHPUnit_Util_Type::export($other->getCode()),
          PHPUnit_Util_Type::export($this->expectedCode)
        );
    }

    /**
     * @return string
     */
    public function toString()
    {
        return 'exception code is ';
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.4.0
 */

/**
 * Constraint that asserts that the string it is evaluated for begins with a
 * given prefix.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.4.0
 */
class PHPUnit_Framework_Constraint_StringStartsWith extends PHPUnit_Framework_Constraint
{
    /**
     * @var string
     */
    protected $prefix;

    /**
     * @param string $prefix
     */
    public function __construct($prefix)
    {
        $this->prefix = $prefix;
    }

    /**
     * Evaluates the constraint for parameter $other. Returns TRUE if the
     * constraint is met, FALSE otherwise.
     *
     * @param mixed $other Value or object to evaluate.
     * @return bool
     */
    protected function matches($other)
    {
        return strpos($other, $this->prefix) === 0;
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        return 'starts with "' . $this->prefix . '"';
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.3.0
 */

/**
 * Constraint that accepts TRUE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.3.0
 */
class PHPUnit_Framework_Constraint_IsTrue extends PHPUnit_Framework_Constraint
{
    /**
     * Evaluates the constraint for parameter $other. Returns TRUE if the
     * constraint is met, FALSE otherwise.
     *
     * @param mixed $other Value or object to evaluate.
     * @return bool
     */
    protected function matches($other)
    {
        return $other === TRUE;
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        return 'is true';
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * Constraint that checks if the file(name) that it is evaluated for exists.
 *
 * The file path to check is passed as $other in evaluate().
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class PHPUnit_Framework_Constraint_FileExists extends PHPUnit_Framework_Constraint
{
    /**
     * Evaluates the constraint for parameter $other. Returns TRUE if the
     * constraint is met, FALSE otherwise.
     *
     * @param mixed $other Value or object to evaluate.
     * @return bool
     */
    protected function matches($other)
    {
        return file_exists($other);
    }

    /**
     * Returns the description of the failure
     *
     * The beginning of failure messages is "Failed asserting that" in most
     * cases. This method should return the second part of that sentence.
     *
     * @param  mixed $other Evaluated value or object.
     * @return string
     */
    protected function failureDescription($other)
    {
        return sprintf(
          'file "%s" exists',

          $other
        );
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        return 'file exists';
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.1.4
 */

/**
 * Constraint that asserts that the Traversable it is applied to contains
 * only values of a given type.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.1.4
 */
class PHPUnit_Framework_Constraint_TraversableContainsOnly extends PHPUnit_Framework_Constraint
{
    /**
     * @var PHPUnit_Framework_Constraint
     */
    protected $constraint;

    /**
     * @var string
     */
    protected $type;

    /**
     * @param string  $type
     * @param boolean $isNativeType
     */
    public function __construct($type, $isNativeType = TRUE)
    {
        if ($isNativeType) {
            $this->constraint = new PHPUnit_Framework_Constraint_IsType($type);
        } else {
            $this->constraint = new PHPUnit_Framework_Constraint_IsInstanceOf(
              $type
            );
        }

        $this->type = $type;
    }

    /**
     * Evaluates the constraint for parameter $other
     *
     * If $returnResult is set to FALSE (the default), an exception is thrown
     * in case of a failure. NULL is returned otherwise.
     *
     * If $returnResult is TRUE, the result of the evaluation is returned as
     * a boolean value instead: TRUE in case of success, FALSE in case of a
     * failure.
     *
     * @param  mixed $other Value or object to evaluate.
     * @param  string $description Additional information about the test
     * @param  bool $returnResult Whether to return a result or throw an exception
     * @return mixed
     * @throws PHPUnit_Framework_ExpectationFailedException
     */
    public function evaluate($other, $description = '', $returnResult = FALSE)
    {
        $success = TRUE;
        $constraint = NULL;

        foreach ($other as $item) {
            if (!$this->constraint->evaluate($item, '', TRUE)) {
                $success = FALSE;
                break;
            }
        }

        if ($returnResult) {
            return $success;
        }

        if (!$success) {
            $this->fail($other, $description);
        }
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        return 'contains only values of type "' . $this->type . '"';
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2002-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Bastian Feder <php@bastian-feder.de>
 * @copyright  2002-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.7.0
 */

/**
 * Provides human readable messages for each JSON error.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Bastian Feder <php@bastian-feder.de>
 * @copyright  2011 Bastian Feder <php@bastian-feder.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.7.0
 */
class PHPUnit_Framework_Constraint_JsonMatches_ErrorMessageProvider
{
    /**
     * Translates JSON error to a human readable string.
     *
     * @param string $error
     * @return string
     */
    public static function determineJsonError($error, $prefix = '')
    {
        switch ($error) {
            case JSON_ERROR_NONE:
                return;
            case JSON_ERROR_DEPTH:
                return $prefix . 'Maximum stack depth exceeded';
            case JSON_ERROR_STATE_MISMATCH:
                return $prefix . 'Underflow or the modes mismatch';
            case JSON_ERROR_CTRL_CHAR:
                return $prefix . 'Unexpected control character found';
            case JSON_ERROR_SYNTAX:
                return $prefix . 'Syntax error, malformed JSON';
            case JSON_ERROR_UTF8:
                return $prefix . 'Malformed UTF-8 characters, possibly incorrectly encoded';
            default:
                return $prefix . 'Unknown error';
        }
    }

    /**
     * Translates a given type to a human readable message prefix.
     *
     * @param string $type
     * @return string
     */
    public static function translateTypeToPrefix($type)
    {
        switch (strtolower($type)) {
            case 'expected':
                $prefix = 'Expected value JSON decode error - ';
                break;
            case 'actual':
                $prefix = 'Actual value JSON decode error - ';
                break;
            default:
                $prefix = '';
                break;
        }
        return $prefix;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * Constraint that asserts that the value it is evaluated for is of a
 * specified type.
 *
 * The expected value is passed in the constructor.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class PHPUnit_Framework_Constraint_IsType extends PHPUnit_Framework_Constraint
{
    const TYPE_ARRAY    = 'array';
    const TYPE_BOOL     = 'bool';
    const TYPE_FLOAT    = 'float';
    const TYPE_INT      = 'int';
    const TYPE_NULL     = 'null';
    const TYPE_NUMERIC  = 'numeric';
    const TYPE_OBJECT   = 'object';
    const TYPE_RESOURCE = 'resource';
    const TYPE_STRING   = 'string';
    const TYPE_SCALAR   = 'scalar';
    const TYPE_CALLABLE = 'callable';

    /**
     * @var array
     */
    protected $types = array(
      'array' => TRUE,
      'boolean' => TRUE,
      'bool' => TRUE,
      'float' => TRUE,
      'integer' => TRUE,
      'int' => TRUE,
      'null' => TRUE,
      'numeric' => TRUE,
      'object' => TRUE,
      'resource' => TRUE,
      'string' => TRUE,
      'scalar' => TRUE,
      'callable' => TRUE
    );

    /**
     * @var string
     */
    protected $type;

    /**
     * @param  string $type
     * @throws PHPUnit_Framework_Exception
     */
    public function __construct($type)
    {
        if (!isset($this->types[$type])) {
            throw new PHPUnit_Framework_Exception(
              sprintf(
                'Type specified for PHPUnit_Framework_Constraint_IsType <%s> ' .
                'is not a valid type.',
                $type
              )
            );
        }

        $this->type = $type;
    }

    /**
     * Evaluates the constraint for parameter $other. Returns TRUE if the
     * constraint is met, FALSE otherwise.
     *
     * @param mixed $other Value or object to evaluate.
     * @return bool
     */
    protected function matches($other)
    {
        switch ($this->type) {
            case 'numeric': {
                return is_numeric($other);
            }

            case 'integer':
            case 'int': {
                return is_integer($other);
            }

            case 'float': {
                return is_float($other);
            }

            case 'string': {
                return is_string($other);
            }

            case 'boolean':
            case 'bool': {
                return is_bool($other);
            }

            case 'null': {
                return is_null($other);
            }

            case 'array': {
                return is_array($other);
            }

            case 'object': {
                return is_object($other);
            }

            case 'resource': {
                return is_resource($other);
            }

            case 'scalar': {
                return is_scalar($other);
            }

            case 'callable': {
                return is_callable($other);
            }
        }
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        return sprintf(
          'is of type "%s"',

          $this->type
        );
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.0
 */

/**
 *
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.0
 */
class PHPUnit_Framework_Constraint_SameSize extends PHPUnit_Framework_Constraint_Count
{
    /**
     * @var integer
     */
    protected $expectedCount;

    /**
     * @param integer $expected
     */
    public function __construct($expected)
    {
        parent::__construct($this->getCountOf($expected));
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * Constraint that asserts that one value is identical to another.
 *
 * Identical check is performed with PHP's === operator, the operator is
 * explained in detail at
 * {@url http://www.php.net/manual/en/types.comparisons.php}.
 * Two values are identical if they have the same value and are of the same
 * type.
 *
 * The expected value is passed in the constructor.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class PHPUnit_Framework_Constraint_IsIdentical extends PHPUnit_Framework_Constraint
{
    /**
     * @var double
     */
    const EPSILON = 0.0000000001;

    /**
     * @var mixed
     */
    protected $value;

    /**
     * @param mixed $value
     */
    public function __construct($value)
    {
        $this->value = $value;
    }

    /**
     * Evaluates the constraint for parameter $other
     *
     * If $returnResult is set to FALSE (the default), an exception is thrown
     * in case of a failure. NULL is returned otherwise.
     *
     * If $returnResult is TRUE, the result of the evaluation is returned as
     * a boolean value instead: TRUE in case of success, FALSE in case of a
     * failure.
     *
     * @param  mixed $other Value or object to evaluate.
     * @param  string $description Additional information about the test
     * @param  bool $returnResult Whether to return a result or throw an exception
     * @return mixed
     * @throws PHPUnit_Framework_ExpectationFailedException
     */
    public function evaluate($other, $description = '', $returnResult = FALSE)
    {
        if (is_double($this->value) && is_double($other) &&
            !is_infinite($this->value) && !is_infinite($other) &&
            !is_nan($this->value) && !is_nan($other)) {
            $success = abs($this->value - $other) < self::EPSILON;
        }

        else {
            $success = $this->value === $other;
        }

        if ($returnResult) {
            return $success;
        }

        if (!$success) {
            $f = NULL;

            // if both values are strings, make sure a diff is generated
            if (is_string($this->value) && is_string($other)) {
                $f = new PHPUnit_Framework_ComparisonFailure(
                  $this->value,
                  $other,
                  $this->value,
                  $other
                );
            }

            $this->fail($other, $description, $f);
        }
    }

    /**
     * Returns the description of the failure
     *
     * The beginning of failure messages is "Failed asserting that" in most
     * cases. This method should return the second part of that sentence.
     *
     * @param  mixed $other Evaluated value or object.
     * @return string
     */
    protected function failureDescription($other)
    {
        if (is_object($this->value) && is_object($other)) {
            return 'two variables reference the same object';
        }

        if (is_string($this->value) && is_string($other)) {
            return 'two strings are identical';
        }

        return parent::failureDescription($other);
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        if (is_object($this->value)) {
            return 'is identical to an object of class "' .
                   get_class($this->value) . '"';
        } else {
            return 'is identical to ' .
                   PHPUnit_Util_Type::export($this->value);
        }
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.3.0
 */

/**
 * Constraint that accepts FALSE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Constraint
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.3.0
 */
class PHPUnit_Framework_Constraint_IsFalse extends PHPUnit_Framework_Constraint
{
    /**
     * Evaluates the constraint for parameter $other. Returns TRUE if the
     * constraint is met, FALSE otherwise.
     *
     * @param mixed $other Value or object to evaluate.
     * @return bool
     */
    protected function matches($other)
    {
        return $other === FALSE;
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        return 'is false';
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

/**
 * A Listener for test progress.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Interface available since Release 2.0.0
 */
interface PHPUnit_Framework_TestListener
{
    /**
     * An error occurred.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  Exception              $e
     * @param  float                  $time
     */
    public function addError(PHPUnit_Framework_Test $test, Exception $e, $time);

    /**
     * A failure occurred.
     *
     * @param  PHPUnit_Framework_Test                 $test
     * @param  PHPUnit_Framework_AssertionFailedError $e
     * @param  float                                  $time
     */
    public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time);

    /**
     * Incomplete test.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  Exception              $e
     * @param  float                  $time
     */
    public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time);

    /**
     * Skipped test.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  Exception              $e
     * @param  float                  $time
     * @since  Method available since Release 3.0.0
     */
    public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time);

    /**
     * A test suite started.
     *
     * @param  PHPUnit_Framework_TestSuite $suite
     * @since  Method available since Release 2.2.0
     */
    public function startTestSuite(PHPUnit_Framework_TestSuite $suite);

    /**
     * A test suite ended.
     *
     * @param  PHPUnit_Framework_TestSuite $suite
     * @since  Method available since Release 2.2.0
     */
    public function endTestSuite(PHPUnit_Framework_TestSuite $suite);

    /**
     * A test started.
     *
     * @param  PHPUnit_Framework_Test $test
     */
    public function startTest(PHPUnit_Framework_Test $test);

    /**
     * A test ended.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  float                  $time
     */
    public function endTest(PHPUnit_Framework_Test $test, $time);
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

/**
 * A TestSuite is a composite of Tests. It runs a collection of test cases.
 *
 * Here is an example using the dynamic test definition.
 *
 * <code>
 * <?php
 * $suite = new PHPUnit_Framework_TestSuite;
 * $suite->addTest(new MathTest('testPass'));
 * ?>
 * </code>
 *
 * Alternatively, a TestSuite can extract the tests to be run automatically.
 * To do so you pass a ReflectionClass instance for your
 * PHPUnit_Framework_TestCase class to the PHPUnit_Framework_TestSuite
 * constructor.
 *
 * <code>
 * <?php
 * $suite = new PHPUnit_Framework_TestSuite(
 *   new ReflectionClass('MathTest')
 * );
 * ?>
 * </code>
 *
 * This constructor creates a suite with all the methods starting with
 * "test" that take no arguments.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.0.0
 */
class PHPUnit_Framework_TestSuite implements PHPUnit_Framework_Test, PHPUnit_Framework_SelfDescribing, IteratorAggregate
{
    /**
     * Enable or disable the backup and restoration of the $GLOBALS array.
     *
     * @var    boolean
     */
    protected $backupGlobals = NULL;

    /**
     * Enable or disable the backup and restoration of static attributes.
     *
     * @var    boolean
     */
    protected $backupStaticAttributes = NULL;

    /**
     * The name of the test suite.
     *
     * @var    string
     */
    protected $name = '';

    /**
     * The test groups of the test suite.
     *
     * @var    array
     */
    protected $groups = array();

    /**
     * The tests in the test suite.
     *
     * @var    array
     */
    protected $tests = array();

    /**
     * The number of tests in the test suite.
     *
     * @var    integer
     */
    protected $numTests = -1;

    /**
     * @var boolean
     */
    protected $testCase = FALSE;

    /**
     * Constructs a new TestSuite:
     *
     *   - PHPUnit_Framework_TestSuite() constructs an empty TestSuite.
     *
     *   - PHPUnit_Framework_TestSuite(ReflectionClass) constructs a
     *     TestSuite from the given class.
     *
     *   - PHPUnit_Framework_TestSuite(ReflectionClass, String)
     *     constructs a TestSuite from the given class with the given
     *     name.
     *
     *   - PHPUnit_Framework_TestSuite(String) either constructs a
     *     TestSuite from the given class (if the passed string is the
     *     name of an existing class) or constructs an empty TestSuite
     *     with the given name.
     *
     * @param  mixed  $theClass
     * @param  string $name
     * @throws PHPUnit_Framework_Exception
     */
    public function __construct($theClass = '', $name = '')
    {
        $argumentsValid = FALSE;

        if (is_object($theClass) &&
            $theClass instanceof ReflectionClass) {
            $argumentsValid = TRUE;
        }

        else if (is_string($theClass) &&
                 $theClass !== '' &&
                 class_exists($theClass, FALSE)) {
            $argumentsValid = TRUE;

            if ($name == '') {
                $name = $theClass;
            }

            $theClass = new ReflectionClass($theClass);
        }

        else if (is_string($theClass)) {
            $this->setName($theClass);
            return;
        }

        if (!$argumentsValid) {
            throw new PHPUnit_Framework_Exception;
        }

        if (!$theClass->isSubclassOf('PHPUnit_Framework_TestCase')) {
            throw new PHPUnit_Framework_Exception(
              'Class "' . $theClass->name . '" does not extend PHPUnit_Framework_TestCase.'
            );
        }

        if ($name != '') {
            $this->setName($name);
        } else {
            $this->setName($theClass->getName());
        }

        $constructor = $theClass->getConstructor();

        if ($constructor !== NULL &&
            !$constructor->isPublic()) {
            $this->addTest(
              self::warning(
                sprintf(
                  'Class "%s" has no public constructor.',

                  $theClass->getName()
                )
              )
            );

            return;
        }

        foreach ($theClass->getMethods() as $method) {
            $this->addTestMethod($theClass, $method);
        }

        if (empty($this->tests)) {
            $this->addTest(
              self::warning(
                sprintf(
                  'No tests found in class "%s".',

                  $theClass->getName()
                )
              )
            );
        }

        $this->testCase = TRUE;
    }

    /**
     * Returns a string representation of the test suite.
     *
     * @return string
     */
    public function toString()
    {
        return $this->getName();
    }

    /**
     * Adds a test to the suite.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  array                  $groups
     */
    public function addTest(PHPUnit_Framework_Test $test, $groups = array())
    {
        $class = new ReflectionClass($test);

        if (!$class->isAbstract()) {
            $this->tests[]  = $test;
            $this->numTests = -1;

            if ($test instanceof PHPUnit_Framework_TestSuite &&
                empty($groups)) {
                $groups = $test->getGroups();
            }

            if (empty($groups)) {
                $groups = array('__nogroup__');
            }

            foreach ($groups as $group) {
                if (!isset($this->groups[$group])) {
                    $this->groups[$group] = array($test);
                } else {
                    $this->groups[$group][] = $test;
                }
            }
        }
    }

    /**
     * Adds the tests from the given class to the suite.
     *
     * @param  mixed $testClass
     * @throws PHPUnit_Framework_Exception
     */
    public function addTestSuite($testClass)
    {
        if (is_string($testClass) && class_exists($testClass)) {
            $testClass = new ReflectionClass($testClass);
        }

        if (!is_object($testClass)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(
              1, 'class name or object'
            );
        }

        if ($testClass instanceof PHPUnit_Framework_TestSuite) {
            $this->addTest($testClass);
        }

        else if ($testClass instanceof ReflectionClass) {
            $suiteMethod = FALSE;

            if (!$testClass->isAbstract()) {
                if ($testClass->hasMethod(PHPUnit_Runner_BaseTestRunner::SUITE_METHODNAME)) {
                    $method = $testClass->getMethod(
                      PHPUnit_Runner_BaseTestRunner::SUITE_METHODNAME
                    );

                    if ($method->isStatic()) {
                        $this->addTest(
                          $method->invoke(NULL, $testClass->getName())
                        );

                        $suiteMethod = TRUE;
                    }
                }
            }

            if (!$suiteMethod && !$testClass->isAbstract()) {
                $this->addTest(new PHPUnit_Framework_TestSuite($testClass));
            }
        }

        else {
            throw new PHPUnit_Framework_Exception;
        }
    }

    /**
     * Wraps both <code>addTest()</code> and <code>addTestSuite</code>
     * as well as the separate import statements for the user's convenience.
     *
     * If the named file cannot be read or there are no new tests that can be
     * added, a <code>PHPUnit_Framework_Warning</code> will be created instead,
     * leaving the current test run untouched.
     *
     * @param  string  $filename
     * @param  array   $phptOptions Array with ini settings for the php instance
     *                              run, key being the name if the setting,
     *                              value the ini value.
     * @throws PHPUnit_Framework_Exception
     * @since  Method available since Release 2.3.0
     * @author Stefano F. Rausch <stefano@rausch-e.net>
     */
    public function addTestFile($filename, $phptOptions = array())
    {
        if (!is_string($filename)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        if (file_exists($filename) && substr($filename, -5) == '.phpt') {
            $this->addTest(
              new PHPUnit_Extensions_PhptTestCase($filename, $phptOptions)
            );

            return;
        }

        PHPUnit_Util_Class::collectStart();
        $filename   = PHPUnit_Util_Fileloader::checkAndLoad($filename);
        $newClasses = PHPUnit_Util_Class::collectEnd();
        $baseName   = str_replace('.php', '', basename($filename));

        foreach ($newClasses as $className) {
            if (substr($className, 0 - strlen($baseName)) == $baseName) {
                $class = new ReflectionClass($className);

                if ($class->getFileName() == $filename) {
                    $newClasses = array($className);
                    break;
                }
            }
        }

        $testsFound = FALSE;

        foreach ($newClasses as $className) {
            $class = new ReflectionClass($className);

            if (!$class->isAbstract()) {
                if ($class->hasMethod(PHPUnit_Runner_BaseTestRunner::SUITE_METHODNAME)) {
                    $method = $class->getMethod(
                      PHPUnit_Runner_BaseTestRunner::SUITE_METHODNAME
                    );

                    if ($method->isStatic()) {
                        $this->addTest($method->invoke(NULL, $className));

                        $testsFound = TRUE;
                    }
                }

                else if ($class->implementsInterface('PHPUnit_Framework_Test')) {
                    $this->addTestSuite($class);

                    $testsFound = TRUE;
                }
            }
        }

        $this->numTests = -1;
    }

    /**
     * Wrapper for addTestFile() that adds multiple test files.
     *
     * @param  array|Iterator $filenames
     * @throws PHPUnit_Framework_Exception
     * @since  Method available since Release 2.3.0
     */
    public function addTestFiles($filenames)
    {
        if (!(is_array($filenames) ||
             (is_object($filenames) && $filenames instanceof Iterator))) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(
              1, 'array or iterator'
            );
        }

        foreach ($filenames as $filename) {
            $this->addTestFile((string)$filename);
        }
    }

    /**
     * Counts the number of test cases that will be run by this test.
     *
     * @return integer
     */
    public function count()
    {
        if ($this->numTests > -1) {
            return $this->numTests;
        }

        $this->numTests = 0;

        foreach ($this->tests as $test) {
            $this->numTests += count($test);
        }

        return $this->numTests;
    }

    /**
     * @param  ReflectionClass $theClass
     * @param  string          $name
     * @return PHPUnit_Framework_Test
     * @throws PHPUnit_Framework_Exception
     */
    public static function createTest(ReflectionClass $theClass, $name)
    {
        $className = $theClass->getName();

        if (!$theClass->isInstantiable()) {
            return self::warning(
              sprintf('Cannot instantiate class "%s".', $className)
            );
        }

        $backupSettings           = PHPUnit_Util_Test::getBackupSettings(
                                      $className, $name
                                    );
        $preserveGlobalState      = PHPUnit_Util_Test::getPreserveGlobalStateSettings(
                                      $className, $name
                                    );
        $runTestInSeparateProcess = PHPUnit_Util_Test::getProcessIsolationSettings(
                                      $className, $name
                                    );

        $constructor = $theClass->getConstructor();

        if ($constructor !== NULL) {
            $parameters = $constructor->getParameters();

            // TestCase() or TestCase($name)
            if (count($parameters) < 2) {
                $test = new $className;
            }

            // TestCase($name, $data)
            else {
                try {
                    $data = PHPUnit_Util_Test::getProvidedData(
                      $className, $name
                    );
                }

                catch (Exception $e) {
                    $message = sprintf(
                      'The data provider specified for %s::%s is invalid.',
                      $className,
                      $name
                    );

                    $_message = $e->getMessage();

                    if (!empty($_message)) {
                        $message .= "\n" . $_message;
                    }

                    $data = self::warning($message);
                }

                // Test method with @dataProvider.
                if (isset($data)) {
                    $test = new PHPUnit_Framework_TestSuite_DataProvider(
                      $className . '::' . $name
                    );

                    if (empty($data)) {
                        $data = self::warning(
                          sprintf(
                            'No tests found in suite "%s".',
                            $test->getName()
                          )
                        );
                    }

                    $groups = PHPUnit_Util_Test::getGroups($className, $name);

                    if ($data instanceof PHPUnit_Framework_Warning) {
                        $test->addTest($data, $groups);
                    }

                    else {
                        foreach ($data as $_dataName => $_data) {
                            $_test = new $className($name, $_data, $_dataName);

                            if ($runTestInSeparateProcess) {
                                $_test->setRunTestInSeparateProcess(TRUE);

                                if ($preserveGlobalState !== NULL) {
                                    $_test->setPreserveGlobalState($preserveGlobalState);
                                }
                            }

                            if ($backupSettings['backupGlobals'] !== NULL) {
                                $_test->setBackupGlobals(
                                  $backupSettings['backupGlobals']
                                );
                            }

                            if ($backupSettings['backupStaticAttributes'] !== NULL) {
                                $_test->setBackupStaticAttributes(
                                  $backupSettings['backupStaticAttributes']
                                );
                            }

                            $test->addTest($_test, $groups);
                        }
                    }
                }

                else {
                    $test = new $className;
                }
            }
        }

        if (!isset($test)) {
            throw new PHPUnit_Framework_Exception('No valid test provided.');
        }

        if ($test instanceof PHPUnit_Framework_TestCase) {
            $test->setName($name);

            if ($runTestInSeparateProcess) {
                $test->setRunTestInSeparateProcess(TRUE);

                if ($preserveGlobalState !== NULL) {
                    $test->setPreserveGlobalState($preserveGlobalState);
                }
            }

            if ($backupSettings['backupGlobals'] !== NULL) {
                $test->setBackupGlobals($backupSettings['backupGlobals']);
            }

            if ($backupSettings['backupStaticAttributes'] !== NULL) {
                $test->setBackupStaticAttributes(
                  $backupSettings['backupStaticAttributes']
                );
            }
        }

        return $test;
    }

    /**
     * Creates a default TestResult object.
     *
     * @return PHPUnit_Framework_TestResult
     */
    protected function createResult()
    {
        return new PHPUnit_Framework_TestResult;
    }

    /**
     * Returns the name of the suite.
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Returns the test groups of the suite.
     *
     * @return array
     * @since  Method available since Release 3.2.0
     */
    public function getGroups()
    {
        return array_keys($this->groups);
    }

    /**
     * Runs the tests and collects their result in a TestResult.
     *
     * @param  PHPUnit_Framework_TestResult $result
     * @param  mixed                        $filter
     * @param  array                        $groups
     * @param  array                        $excludeGroups
     * @param  boolean                      $processIsolation
     * @return PHPUnit_Framework_TestResult
     * @throws PHPUnit_Framework_Exception
     */
    public function run(PHPUnit_Framework_TestResult $result = NULL, $filter = FALSE, array $groups = array(), array $excludeGroups = array(), $processIsolation = FALSE)
    {
        if ($result === NULL) {
            $result = $this->createResult();
        }

        $result->startTestSuite($this);

        $doSetup = TRUE;

        if (!empty($excludeGroups)) {
            foreach ($this->groups as $_group => $_tests) {
                if (in_array($_group, $excludeGroups) &&
                    count($_tests) == count($this->tests)) {
                    $doSetup = FALSE;
                }
            }
        }

        if ($doSetup) {
            try {
                $this->setUp();

                if ($this->testCase &&
                    // Some extensions use test names that are not classes;
                    // The method_exists() triggers an autoload call that causes issues with die()ing autoloaders.
                    class_exists($this->name, false) &&
                    method_exists($this->name, 'setUpBeforeClass')) {
                    call_user_func(array($this->name, 'setUpBeforeClass'));
                }
            }

            catch (PHPUnit_Framework_SkippedTestSuiteError $e) {
                $numTests = count($this);

                for ($i = 0; $i < $numTests; $i++) {
                    $result->addFailure($this, $e, 0);
                }

                return $result;
            }

            catch (Exception $e) {
                $numTests = count($this);

                for ($i = 0; $i < $numTests; $i++) {
                    $result->addError($this, $e, 0);
                }

                return $result;
            }
        }

        if (empty($groups)) {
            $tests = $this->tests;
        } else {
            $tests = new SplObjectStorage;

            foreach ($groups as $group) {
                if (isset($this->groups[$group])) {
                    foreach ($this->groups[$group] as $test) {
                        $tests->attach($test);
                    }
                }
            }
        }

        foreach ($tests as $test) {
            if ($result->shouldStop()) {
                break;
            }

            if ($test instanceof PHPUnit_Framework_TestSuite) {
                $test->setBackupGlobals($this->backupGlobals);
                $test->setBackupStaticAttributes($this->backupStaticAttributes);

                $test->run(
                  $result, $filter, $groups, $excludeGroups, $processIsolation
                );
            } else {
                $runTest = TRUE;

                if ($filter !== FALSE ) {
                    $tmp = PHPUnit_Util_Test::describe($test, FALSE);

                    if ($tmp[0] != '') {
                        $name = join('::', $tmp);
                    } else {
                        $name = $tmp[1];
                    }

                    if (preg_match($filter, $name) == 0) {
                        $runTest = FALSE;
                    }
                }

                if ($runTest && !empty($excludeGroups)) {
                    foreach ($this->groups as $_group => $_tests) {
                        if (in_array($_group, $excludeGroups)) {
                            foreach ($_tests as $_test) {
                                if ($test === $_test) {
                                    $runTest = FALSE;
                                    break 2;
                                }
                            }
                        }
                    }
                }

                if ($runTest) {
                    if ($test instanceof PHPUnit_Framework_TestCase) {
                        $test->setBackupGlobals($this->backupGlobals);
                        $test->setBackupStaticAttributes(
                          $this->backupStaticAttributes
                        );
                        $test->setRunTestInSeparateProcess($processIsolation);
                    }

                    $this->runTest($test, $result);
                }
            }
        }

        if ($doSetup) {
            if ($this->testCase &&
                // Some extensions use test names that are not classes;
                // The method_exists() triggers an autoload call that causes issues with die()ing autoloaders.
                class_exists($this->name, false) &&
                method_exists($this->name, 'tearDownAfterClass')) {
                call_user_func(array($this->name, 'tearDownAfterClass'));
            }

            $this->tearDown();
        }

        $result->endTestSuite($this);

        return $result;
    }

    /**
     * Runs a test.
     *
     * @param  PHPUnit_Framework_Test        $test
     * @param  PHPUnit_Framework_TestResult  $result
     */
    public function runTest(PHPUnit_Framework_Test $test, PHPUnit_Framework_TestResult $result)
    {
        $test->run($result);
    }

    /**
     * Sets the name of the suite.
     *
     * @param  string
     */
    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * Returns the test at the given index.
     *
     * @param  integer
     * @return PHPUnit_Framework_Test
     */
    public function testAt($index)
    {
        if (isset($this->tests[$index])) {
            return $this->tests[$index];
        } else {
            return FALSE;
        }
    }

    /**
     * Returns the tests as an enumeration.
     *
     * @return array
     */
    public function tests()
    {
        return $this->tests;
    }

    /**
     * Mark the test suite as skipped.
     *
     * @param  string  $message
     * @throws PHPUnit_Framework_SkippedTestSuiteError
     * @since  Method available since Release 3.0.0
     */
    public function markTestSuiteSkipped($message = '')
    {
        throw new PHPUnit_Framework_SkippedTestSuiteError($message);
    }

    /**
     * @param ReflectionClass  $class
     * @param ReflectionMethod $method
     */
    protected function addTestMethod(ReflectionClass $class, ReflectionMethod $method)
    {
        $name = $method->getName();

        if ($this->isPublicTestMethod($method)) {
            $test = self::createTest($class, $name);

            if ($test instanceof PHPUnit_Framework_TestCase ||
                $test instanceof PHPUnit_Framework_TestSuite_DataProvider) {
                $test->setDependencies(
                  PHPUnit_Util_Test::getDependencies($class->getName(), $name)
                );
            }

            $this->addTest($test, PHPUnit_Util_Test::getGroups(
              $class->getName(), $name)
            );
        }

        else if ($this->isTestMethod($method)) {
            $this->addTest(
              self::warning(
                sprintf(
                  'Test method "%s" in test class "%s" is not public.',
                  $name,
                  $class->getName()
                )
              )
            );
        }
    }

    /**
     * @param  ReflectionMethod $method
     * @return boolean
     */
    public static function isPublicTestMethod(ReflectionMethod $method)
    {
        return (self::isTestMethod($method) && $method->isPublic());
    }

    /**
     * @param  ReflectionMethod $method
     * @return boolean
     */
    public static function isTestMethod(ReflectionMethod $method)
    {
        if (strpos($method->name, 'test') === 0) {
            return TRUE;
        }

        // @scenario on TestCase::testMethod()
        // @test     on TestCase::testMethod()
        return strpos($method->getDocComment(), '@test')     !== FALSE ||
               strpos($method->getDocComment(), '@scenario') !== FALSE;
    }

    /**
     * @param  string  $message
     * @return PHPUnit_Framework_Warning
     */
    protected static function warning($message)
    {
        return new PHPUnit_Framework_Warning($message);
    }

    /**
     * @param  boolean $backupGlobals
     * @since  Method available since Release 3.3.0
     */
    public function setBackupGlobals($backupGlobals)
    {
        if (is_null($this->backupGlobals) && is_bool($backupGlobals)) {
            $this->backupGlobals = $backupGlobals;
        }
    }

    /**
     * @param  boolean $backupStaticAttributes
     * @since  Method available since Release 3.4.0
     */
    public function setBackupStaticAttributes($backupStaticAttributes)
    {
        if (is_null($this->backupStaticAttributes) &&
            is_bool($backupStaticAttributes)) {
            $this->backupStaticAttributes = $backupStaticAttributes;
        }
    }

    /**
     * Returns an iterator for this test suite.
     *
     * @return RecursiveIteratorIterator
     * @since  Method available since Release 3.1.0
     */
    public function getIterator()
    {
        return new RecursiveIteratorIterator(
          new PHPUnit_Util_TestSuiteIterator($this)
        );
    }

    /**
     * Template Method that is called before the tests
     * of this test suite are run.
     *
     * @since  Method available since Release 3.1.0
     */
    protected function setUp()
    {
    }

    /**
     * Template Method that is called after the tests
     * of this test suite have finished running.
     *
     * @since  Method available since Release 3.1.0
     */
    protected function tearDown()
    {
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

/**
 * A Test can be run and collect its results.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Interface available since Release 2.0.0
 */
interface PHPUnit_Framework_Test extends Countable
{
    /**
     * Runs a test and collects its result in a TestResult instance.
     *
     * @param  PHPUnit_Framework_TestResult $result
     * @return PHPUnit_Framework_TestResult
     */
    public function run(PHPUnit_Framework_TestResult $result = NULL);
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.5.0
 */

/**
 * Creates a synthetic failed assertion.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.5.0
 */
class PHPUnit_Framework_SyntheticError extends PHPUnit_Framework_AssertionFailedError
{
    /**
     * The synthetic file.
     *
     * @var string
     */
    protected $syntheticFile = '';

    /**
     * The synthetic line number.
     *
     * @var integer
     */
    protected $syntheticLine = 0;

    /**
     * The synthetic trace.
     *
     * @var array
     */
    protected $syntheticTrace = array();

    /**
     * Constructor.
     *
     * @param string  $message
     * @param integer $code
     * @param string  $file
     * @param integer $line
     * @param array   $trace
     */
    public function __construct($message, $code, $file, $line, $trace)
    {
        parent::__construct($message, $code);

        $this->syntheticFile  = $file;
        $this->syntheticLine  = $line;
        $this->syntheticTrace = $trace;
    }

    /**
     * @return string
     */
    public function getSyntheticFile()
    {
        return $this->syntheticFile;
    }

    /**
     * @return integer
     */
    public function getSyntheticLine()
    {
        return $this->syntheticLine;
    }

    /**
     * @return array
     */
    public function getSyntheticTrace()
    {
        return $this->syntheticTrace;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.0
 */

/**
 * Extension to PHPUnit_Framework_AssertionFailedError to mark the special
 * case of a test that printed output.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.0
 */
class PHPUnit_Framework_OutputError extends PHPUnit_Framework_AssertionFailedError
{
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

/**
 * A marker interface for marking any exception/error as result of an unit
 * test as incomplete implementation or currently not implemented.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Interface available since Release 2.0.0
 */
interface PHPUnit_Framework_IncompleteTest
{
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

/**
 * Thrown when an assertion failed.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.0.0
 */
class PHPUnit_Framework_AssertionFailedError extends PHPUnit_Framework_Exception implements PHPUnit_Framework_SelfDescribing
{
    /**
     * Wrapper for getMessage() which is declared as final.
     *
     * @return string
     */
    public function toString()
    {
        return $this->getMessage();
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * Interface for classes that can return a description of itself.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Interface available since Release 3.0.0
 */
interface PHPUnit_Framework_SelfDescribing
{
    /**
     * Returns a string representation of the object.
     *
     * @return string
     */
    public function toString();
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Error
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.3.0
 */

/**
 * Wrapper for PHP warnings.
 * You can disable notice-to-exception conversion by setting
 *
 * <code>
 * PHPUnit_Framework_Error_Warning::$enabled = FALSE;
 * </code>
 *
 * @package    PHPUnit
 * @subpackage Framework_Error
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.3.0
 */
class PHPUnit_Framework_Error_Warning extends PHPUnit_Framework_Error
{
    public static $enabled = TRUE;
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Error
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.3.0
 */

/**
 * Wrapper for PHP deprecated errors.
 * You can disable deprecated-to-exception conversion by setting
 *
 * <code>
 * PHPUnit_Framework_Error_Deprecated::$enabled = FALSE;
 * </code>
 *
 * @package    PHPUnit
 * @subpackage Framework_Error
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.3.0
 */
class PHPUnit_Framework_Error_Deprecated extends PHPUnit_Framework_Error
{
    public static $enabled = TRUE;
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework_Error
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.3.0
 */

/**
 * Wrapper for PHP notices.
 * You can disable notice-to-exception conversion by setting
 *
 * <code>
 * PHPUnit_Framework_Error_Notice::$enabled = FALSE;
 * </code>
 *
 * @package    PHPUnit
 * @subpackage Framework_Error
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.3.0
 */
class PHPUnit_Framework_Error_Notice extends PHPUnit_Framework_Error
{
    public static $enabled = TRUE;
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

/**
 * A TestResult collects the results of executing a test case.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.0.0
 */
class PHPUnit_Framework_TestResult implements Countable
{
    /**
     * @var boolean
     */
    protected static $xdebugLoaded = NULL;

    /**
     * @var boolean
     */
    protected static $useXdebug = NULL;

    /**
     * @var array
     */
    protected $passed = array();

    /**
     * @var array
     */
    protected $errors = array();

    /**
     * @var array
     */
    protected $deprecatedFeatures = array();

    /**
     * @var array
     */
    protected $failures = array();

    /**
     * @var array
     */
    protected $notImplemented = array();

    /**
     * @var array
     */
    protected $skipped = array();

    /**
     * @var array
     */
    protected $listeners = array();

    /**
     * @var integer
     */
    protected $runTests = 0;

    /**
     * @var float
     */
    protected $time = 0;

    /**
     * @var PHPUnit_Framework_TestSuite
     */
    protected $topTestSuite = NULL;

    /**
     * Code Coverage information.
     *
     * @var PHP_CodeCoverage
     */
    protected $codeCoverage;

    /**
     * @var boolean
     */
    protected $convertErrorsToExceptions = TRUE;

    /**
     * @var boolean
     */
    protected $stop = FALSE;

    /**
     * @var boolean
     */
    protected $stopOnError = FALSE;

    /**
     * @var boolean
     */
    protected $stopOnFailure = FALSE;

    /**
     * @var boolean
     */
    protected $strictMode = FALSE;

    /**
     * @var boolean
     */
    protected $stopOnIncomplete = FALSE;

    /**
     * @var boolean
     */
    protected $stopOnSkipped = FALSE;

    /**
     * @var boolean
     */
    protected $lastTestFailed = FALSE;

    /**
     * @var integer
     */
    protected $timeoutForSmallTests = 1;

    /**
     * @var integer
     */
    protected $timeoutForMediumTests = 10;

    /**
     * @var integer
     */
    protected $timeoutForLargeTests = 60;

    /**
     * Registers a TestListener.
     *
     * @param  PHPUnit_Framework_TestListener
     */
    public function addListener(PHPUnit_Framework_TestListener $listener)
    {
        $this->listeners[] = $listener;
    }

    /**
     * Unregisters a TestListener.
     *
     * @param  PHPUnit_Framework_TestListener $listener
     */
    public function removeListener(PHPUnit_Framework_TestListener $listener)
    {
        foreach ($this->listeners as $key => $_listener) {
            if ($listener === $_listener) {
                unset($this->listeners[$key]);
            }
        }
    }

    /**
     * Flushes all flushable TestListeners.
     *
     * @since  Method available since Release 3.0.0
     */
    public function flushListeners()
    {
        foreach ($this->listeners as $listener) {
            if ($listener instanceof PHPUnit_Util_Printer) {
                $listener->flush();
            }
        }
    }

    /**
     * Adds an error to the list of errors.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  Exception              $e
     * @param  float                  $time
     */
    public function addError(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
        if ($e instanceof PHPUnit_Framework_IncompleteTest) {
            $this->notImplemented[] = new PHPUnit_Framework_TestFailure(
              $test, $e
            );

            $notifyMethod = 'addIncompleteTest';

            if ($this->stopOnIncomplete) {
                $this->stop();
            }
        }

        else if ($e instanceof PHPUnit_Framework_SkippedTest) {
            $this->skipped[] = new PHPUnit_Framework_TestFailure($test, $e);
            $notifyMethod    = 'addSkippedTest';

            if ($this->stopOnSkipped) {
                $this->stop();
            }
        }

        else {
            $this->errors[] = new PHPUnit_Framework_TestFailure($test, $e);
            $notifyMethod   = 'addError';

            if ($this->stopOnError || $this->stopOnFailure) {
                $this->stop();
            }
        }

        foreach ($this->listeners as $listener) {
            $listener->$notifyMethod($test, $e, $time);
        }

        $this->lastTestFailed = TRUE;
        $this->time          += $time;
    }

    /**
     * Adds a failure to the list of failures.
     * The passed in exception caused the failure.
     *
     * @param  PHPUnit_Framework_Test                 $test
     * @param  PHPUnit_Framework_AssertionFailedError $e
     * @param  float                                  $time
     */
    public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time)
    {
        if ($e instanceof PHPUnit_Framework_IncompleteTest) {
            $this->notImplemented[] = new PHPUnit_Framework_TestFailure(
              $test, $e
            );

            $notifyMethod = 'addIncompleteTest';

            if ($this->stopOnIncomplete) {
                $this->stop();
            }
        }

        else if ($e instanceof PHPUnit_Framework_SkippedTest) {
            $this->skipped[] = new PHPUnit_Framework_TestFailure($test, $e);
            $notifyMethod    = 'addSkippedTest';

            if ($this->stopOnSkipped) {
                $this->stop();
            }
        }

        else {
            $this->failures[] = new PHPUnit_Framework_TestFailure($test, $e);
            $notifyMethod     = 'addFailure';

            if ($this->stopOnFailure) {
                $this->stop();
            }
        }

        foreach ($this->listeners as $listener) {
            $listener->$notifyMethod($test, $e, $time);
        }

        $this->lastTestFailed = TRUE;
        $this->time          += $time;
    }

    /**
     * Adds a deprecated feature notice to the list of deprecated features used during run
     *
     * @param PHPUnit_Util_DeprecatedFeature $deprecatedFeature
     */
    public function addDeprecatedFeature(PHPUnit_Util_DeprecatedFeature $deprecatedFeature)
    {
        $this->deprecatedFeatures[] = $deprecatedFeature;
    }

    /**
     * Informs the result that a testsuite will be started.
     *
     * @param  PHPUnit_Framework_TestSuite $suite
     * @since  Method available since Release 2.2.0
     */
    public function startTestSuite(PHPUnit_Framework_TestSuite $suite)
    {
        if ($this->topTestSuite === NULL) {
            $this->topTestSuite = $suite;
        }

        foreach ($this->listeners as $listener) {
            $listener->startTestSuite($suite);
        }
    }

    /**
     * Informs the result that a testsuite was completed.
     *
     * @param  PHPUnit_Framework_TestSuite $suite
     * @since  Method available since Release 2.2.0
     */
    public function endTestSuite(PHPUnit_Framework_TestSuite $suite)
    {
        foreach ($this->listeners as $listener) {
            $listener->endTestSuite($suite);
        }
    }

    /**
     * Informs the result that a test will be started.
     *
     * @param  PHPUnit_Framework_Test $test
     */
    public function startTest(PHPUnit_Framework_Test $test)
    {
        $this->lastTestFailed = FALSE;
        $this->runTests      += count($test);

        foreach ($this->listeners as $listener) {
            $listener->startTest($test);
        }
    }

    /**
     * Informs the result that a test was completed.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  float                  $time
     */
    public function endTest(PHPUnit_Framework_Test $test, $time)
    {
        foreach ($this->listeners as $listener) {
            $listener->endTest($test, $time);
        }

        if (!$this->lastTestFailed && $test instanceof PHPUnit_Framework_TestCase) {
            $class  = get_class($test);
            $key    =  $class . '::' . $test->getName();

            $this->passed[$key] = array(
              'result' => $test->getResult(),
              'size'   => PHPUnit_Util_Test::getSize(
                            $class, $test->getName(FALSE)
                          )
            );

            $this->time += $time;
        }
    }

    /**
     * Returns TRUE if no incomplete test occured.
     *
     * @return boolean
     */
    public function allCompletelyImplemented()
    {
        return $this->notImplementedCount() == 0;
    }

    /**
     * Gets the number of incomplete tests.
     *
     * @return integer
     */
    public function notImplementedCount()
    {
        return count($this->notImplemented);
    }

    /**
     * Returns an Enumeration for the incomplete tests.
     *
     * @return array
     */
    public function notImplemented()
    {
        return $this->notImplemented;
    }

    /**
     * Returns TRUE if no test has been skipped.
     *
     * @return boolean
     * @since  Method available since Release 3.0.0
     */
    public function noneSkipped()
    {
        return $this->skippedCount() == 0;
    }

    /**
     * Gets the number of skipped tests.
     *
     * @return integer
     * @since  Method available since Release 3.0.0
     */
    public function skippedCount()
    {
        return count($this->skipped);
    }

    /**
     * Returns an Enumeration for the skipped tests.
     *
     * @return array
     * @since  Method available since Release 3.0.0
     */
    public function skipped()
    {
        return $this->skipped;
    }

    /**
     * Gets the number of detected errors.
     *
     * @return integer
     */
    public function errorCount()
    {
        return count($this->errors);
    }

    /**
     * Returns an Enumeration for the errors.
     *
     * @return array
     */
    public function errors()
    {
        return $this->errors;
    }

    /**
     * Returns an Enumeration for the deprecated features used.
     *
     * @return array
     * @since  Method available since Release 3.5.7
     */
    public function deprecatedFeatures()
    {
        return $this->deprecatedFeatures;
    }

    /**
     * Returns an Enumeration for the deprecated features used.
     *
     * @return array
     * @since  Method available since Release 3.5.7
     */
    public function deprecatedFeaturesCount()
    {
        return count($this->deprecatedFeatures);
    }

    /**
     * Gets the number of detected failures.
     *
     * @return integer
     */
    public function failureCount()
    {
        return count($this->failures);
    }

    /**
     * Returns an Enumeration for the failures.
     *
     * @return array
     */
    public function failures()
    {
        return $this->failures;
    }

    /**
     * Returns the names of the tests that have passed.
     *
     * @return array
     * @since  Method available since Release 3.4.0
     */
    public function passed()
    {
        return $this->passed;
    }

    /**
     * Returns the (top) test suite.
     *
     * @return PHPUnit_Framework_TestSuite
     * @since  Method available since Release 3.0.0
     */
    public function topTestSuite()
    {
        return $this->topTestSuite;
    }

    /**
     * Returns whether code coverage information should be collected.
     *
     * @return boolean If code coverage should be collected
     * @since  Method available since Release 3.2.0
     */
    public function getCollectCodeCoverageInformation()
    {
        return $this->codeCoverage !== NULL;
    }

    /**
     * Returns the strict mode configuration option
     *
     * @return boolean
     */
    public function isStrict()
    {
        return $this->strictMode;
    }

    /**
     * Runs a TestCase.
     *
     * @param  PHPUnit_Framework_Test $test
     */
    public function run(PHPUnit_Framework_Test $test)
    {
        PHPUnit_Framework_Assert::resetCount();

        $error      = FALSE;
        $failure    = FALSE;
        $incomplete = FALSE;
        $skipped    = FALSE;

        $this->startTest($test);

        $errorHandlerSet = FALSE;

        if ($this->convertErrorsToExceptions) {
            $oldErrorHandler = set_error_handler(
              array('PHPUnit_Util_ErrorHandler', 'handleError'),
              E_ALL | E_STRICT
            );

            if ($oldErrorHandler === NULL) {
                $errorHandlerSet = TRUE;
            } else {
                restore_error_handler();
            }
        }

        if (self::$xdebugLoaded === NULL) {
            self::$xdebugLoaded = extension_loaded('xdebug');
            self::$useXdebug    = self::$xdebugLoaded;
        }

        $useXdebug = self::$useXdebug &&
                     $this->codeCoverage !== NULL &&
                     !$test instanceof PHPUnit_Extensions_SeleniumTestCase &&
                     !$test instanceof PHPUnit_Framework_Warning;

        if ($useXdebug) {
            // We need to blacklist test source files when no whitelist is used.
            if (!$this->codeCoverage->filter()->hasWhitelist()) {
                $classes = PHPUnit_Util_Class::getHierarchy(
                  get_class($test), TRUE
                );

                foreach ($classes as $class) {
                    $this->codeCoverage->filter()->addFileToBlacklist(
                      $class->getFileName()
                    );
                }
            }

            $this->codeCoverage->start($test);
        }

        PHP_Timer::start();

        try {
            if (!$test instanceof PHPUnit_Framework_Warning &&
                $this->strictMode &&
                extension_loaded('pcntl') && class_exists('PHP_Invoker')) {
                switch ($test->getSize()) {
                    case PHPUnit_Util_Test::SMALL: {
                        $_timeout = $this->timeoutForSmallTests;
                    }
                    break;

                    case PHPUnit_Util_Test::MEDIUM: {
                        $_timeout = $this->timeoutForMediumTests;
                    }
                    break;

                    case PHPUnit_Util_Test::LARGE: {
                        $_timeout = $this->timeoutForLargeTests;
                    }
                    break;
                }

                $invoker = new PHP_Invoker;
                $invoker->invoke(array($test, 'runBare'), array(), $_timeout);
            } else {
                $test->runBare();
            }
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            $failure = TRUE;

            if ($e instanceof PHPUnit_Framework_IncompleteTestError) {
                $incomplete = TRUE;
            }

            else if ($e instanceof PHPUnit_Framework_SkippedTestError) {
                $skipped = TRUE;
            }
        }

        catch (Exception $e) {
            $error = TRUE;
        }

        $time = PHP_Timer::stop();
        $test->addToAssertionCount(PHPUnit_Framework_Assert::getCount());

        if ($this->strictMode && $test->getNumAssertions() == 0) {
            $incomplete = TRUE;
        }

        if ($useXdebug) {
            try {
                $this->codeCoverage->stop(!$incomplete && !$skipped);
            }

            catch (PHP_CodeCoverage_Exception $cce) {
                $error = TRUE;

                if (!isset($e)) {
                    $e = $cce;
                }
            }
        }

        if ($errorHandlerSet === TRUE) {
            restore_error_handler();
        }

        if ($error === TRUE) {
            $this->addError($test, $e, $time);
        }

        else if ($failure === TRUE) {
            $this->addFailure($test, $e, $time);
        }

        else if ($this->strictMode && $test->getNumAssertions() == 0) {
            $this->addFailure(
              $test,
              new PHPUnit_Framework_IncompleteTestError(
                'This test did not perform any assertions'
              ),
              $time
            );
        }

        else if ($this->strictMode && $test->hasOutput()) {
            $this->addFailure(
              $test,
              new PHPUnit_Framework_OutputError(
                sprintf(
                  'This test printed output: %s',
                  $test->getActualOutput()
                )
              ),
              $time
            );
        }

        $this->endTest($test, $time);
    }

    /**
     * Gets the number of run tests.
     *
     * @return integer
     */
    public function count()
    {
        return $this->runTests;
    }

    /**
     * Checks whether the test run should stop.
     *
     * @return boolean
     */
    public function shouldStop()
    {
        return $this->stop;
    }

    /**
     * Marks that the test run should stop.
     *
     */
    public function stop()
    {
        $this->stop = TRUE;
    }

    /**
     * Returns the PHP_CodeCoverage object.
     *
     * @return PHP_CodeCoverage
     * @since  Method available since Release 3.5.0
     */
    public function getCodeCoverage()
    {
        return $this->codeCoverage;
    }

    /**
     * Returns the PHP_CodeCoverage object.
     *
     * @return PHP_CodeCoverage
     * @since  Method available since Release 3.6.0
     */
    public function setCodeCoverage(PHP_CodeCoverage $codeCoverage)
    {
        $this->codeCoverage = $codeCoverage;
    }

    /**
     * Enables or disables the error-to-exception conversion.
     *
     * @param  boolean $flag
     * @throws PHPUnit_Framework_Exception
     * @since  Method available since Release 3.2.14
     */
    public function convertErrorsToExceptions($flag)
    {
        if (is_bool($flag)) {
            $this->convertErrorsToExceptions = $flag;
        } else {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
        }
    }

    /**
     * Returns the error-to-exception conversion setting.
     *
     * @return boolean
     * @since  Method available since Release 3.4.0
     */
    public function getConvertErrorsToExceptions()
    {
        return $this->convertErrorsToExceptions;
    }

    /**
     * Enables or disables the stopping when an error occurs.
     *
     * @param  boolean $flag
     * @throws PHPUnit_Framework_Exception
     * @since  Method available since Release 3.5.0
     */
    public function stopOnError($flag)
    {
        if (is_bool($flag)) {
            $this->stopOnError = $flag;
        } else {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
        }
    }

    /**
     * Enables or disables the stopping when a failure occurs.
     *
     * @param  boolean $flag
     * @throws PHPUnit_Framework_Exception
     * @since  Method available since Release 3.1.0
     */
    public function stopOnFailure($flag)
    {
        if (is_bool($flag)) {
            $this->stopOnFailure = $flag;
        } else {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
        }
    }

    /**
     * Enables or disables the strict mode.
     *
     * When active
     *   * Tests that do not assert anything will be marked as incomplete.
     *   * Tests that are incomplete or skipped yield no code coverage.
     *
     * @param  boolean $flag
     * @throws PHPUnit_Framework_Exception
     * @since  Method available since Release 3.5.2
     */
    public function strictMode($flag)
    {
        if (is_bool($flag)) {
            $this->strictMode = $flag;
        } else {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
        }
    }

    /**
     * Enables or disables the stopping for incomplete tests.
     *
     * @param  boolean $flag
     * @throws PHPUnit_Framework_Exception
     * @since  Method available since Release 3.5.0
     */
    public function stopOnIncomplete($flag)
    {
        if (is_bool($flag)) {
            $this->stopOnIncomplete = $flag;
        } else {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
        }
    }

    /**
     * Enables or disables the stopping for skipped tests.
     *
     * @param  boolean $flag
     * @throws PHPUnit_Framework_Exception
     * @since  Method available since Release 3.1.0
     */
    public function stopOnSkipped($flag)
    {
        if (is_bool($flag)) {
            $this->stopOnSkipped = $flag;
        } else {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
        }
    }

    /**
     * Returns the time spent running the tests.
     *
     * @return float
     */
    public function time()
    {
        return $this->time;
    }

    /**
     * Returns whether the entire test was successful or not.
     *
     * @return boolean
     */
    public function wasSuccessful()
    {
        return empty($this->errors) && empty($this->failures);
    }

    /**
     * Sets the timeout for small tests.
     *
     * @param  integer $timeout
     * @throws PHPUnit_Framework_Exception
     * @since  Method available since Release 3.6.0
     */
    public function setTimeoutForSmallTests($timeout)
    {
        if (is_integer($timeout)) {
            $this->timeoutForSmallTests = $timeout;
        } else {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'integer');
        }
    }

    /**
     * Sets the timeout for medium tests.
     *
     * @param  integer $timeout
     * @throws PHPUnit_Framework_Exception
     * @since  Method available since Release 3.6.0
     */
    public function setTimeoutForMediumTests($timeout)
    {
        if (is_integer($timeout)) {
            $this->timeoutForMediumTests = $timeout;
        } else {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'integer');
        }
    }

    /**
     * Sets the timeout for large tests.
     *
     * @param  integer $timeout
     * @throws PHPUnit_Framework_Exception
     * @since  Method available since Release 3.6.0
     */
    public function setTimeoutForLargeTests($timeout)
    {
        if (is_integer($timeout)) {
            $this->timeoutForLargeTests = $timeout;
        } else {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'integer');
        }
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

/**
 * Thrown when an assertion for string equality failed.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.0.0
 */
class PHPUnit_Framework_ComparisonFailure extends PHPUnit_Framework_AssertionFailedError
{
    /**
     * Expected value of the retrieval which does not match $actual.
     * @var mixed
     */
    protected $expected;

    /**
     * Actually retrieved value which does not match $expected.
     * @var mixed
     */
    protected $actual;

    /**
     * The string representation of the expected value
     * @var string
     */
    protected $expectedAsString;

    /**
     * The string representation of the actual value
     * @var string
     */
    protected $actualAsString;

    /**
     * @var boolean
     */
    protected $identical;

    /**
     * Optional message which is placed in front of the first line
     * returned by toString().
     * @var string
     */
    protected $message;

    /**
     * Initialises with the expected value and the actual value.
     *
     * @param mixed $expected Expected value retrieved.
     * @param mixed $actual Actual value retrieved.
     * @param string $expectedAsString
     * @param string $actualAsString
     * @param boolean $identical
     * @param string $message A string which is prefixed on all returned lines
     *                        in the difference output.
     */
    public function __construct($expected, $actual, $expectedAsString, $actualAsString, $identical = FALSE, $message = '')
    {
        $this->expected         = $expected;
        $this->actual           = $actual;
        $this->expectedAsString = $expectedAsString;
        $this->actualAsString   = $actualAsString;
        $this->message          = $message;
    }

    /**
     * @return mixed
     */
    public function getActual()
    {
        return $this->actual;
    }

    /**
     * @return mixed
     */
    public function getExpected()
    {
        return $this->expected;
    }

    /**
     * @return string
     */
    public function getActualAsString()
    {
        return $this->actualAsString;
    }

    /**
     * @return string
     */
    public function getExpectedAsString()
    {
        return $this->expectedAsString;
    }

    /**
     * @return string
     */
    public function getDiff()
    {
        return $this->actualAsString || $this->expectedAsString
          ? PHPUnit_Util_Diff::diff($this->expectedAsString, $this->actualAsString)
          : '';
    }

    /**
     * @return string
     */
    public function toString()
    {
        return $this->message . $this->getDiff();
    }
}
<?php
ini_set('display_errors', 'stderr');
set_include_path('{include_path}');

$composerAutoload = {composerAutoload};
$phar             = {phar};

if ($composerAutoload) {
    require_once $composerAutoload;
    define('PHPUNIT_COMPOSER_INSTALL', $composerAutoload);
} else if ($phar) {
    require $phar;
} else {
    require 'PHPUnit/Autoload.php';
}

ob_start();

function __phpunit_run_isolated_test()
{
    if (!class_exists('{className}')) {
        require_once '{filename}';
    }

    $result = new PHPUnit_Framework_TestResult;

    if ({collectCodeCoverageInformation}) {
        $result->setCodeCoverage(new PHP_CodeCoverage);
    }

    $result->strictMode({strict});

    $test = new {className}('{methodName}', unserialize('{data}'), '{dataName}');
    $test->setDependencyInput(unserialize('{dependencyInput}'));
    $test->setInIsolation(TRUE);

    ob_end_clean();
    ob_start();
    $test->run($result);
    $output = ob_get_clean();

    print serialize(
      array(
        'testResult'    => $test->getResult(),
        'numAssertions' => $test->getNumAssertions(),
        'result'        => $result,
        'output'        => $output
      )
    );

    ob_start();
}

{constants}
{included_files}
{globals}

if (isset($GLOBALS['__PHPUNIT_BOOTSTRAP'])) {
    require_once $GLOBALS['__PHPUNIT_BOOTSTRAP'];
    unset($GLOBALS['__PHPUNIT_BOOTSTRAP']);
}

__phpunit_run_isolated_test();
ob_end_clean();
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

/**
 * A TestFailure collects a failed test together with the caught exception.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.0.0
 */
class PHPUnit_Framework_TestFailure
{
    /**
     * @var    PHPUnit_Framework_Test
     */
    protected $failedTest;

    /**
     * @var    Exception
     */
    protected $thrownException;

    /**
     * Constructs a TestFailure with the given test and exception.
     *
     * @param  PHPUnit_Framework_Test $failedTest
     * @param  Exception               $thrownException
     */
    public function __construct(PHPUnit_Framework_Test $failedTest, Exception $thrownException)
    {
        $this->failedTest      = $failedTest;
        $this->thrownException = $thrownException;
    }

    /**
     * Returns a short description of the failure.
     *
     * @return string
     */
    public function toString()
    {
        return sprintf(
          '%s: %s',

          $this->failedTest->toString(),
          $this->thrownException->getMessage()
        );
    }

    /**
     * Returns a description for the thrown exception.
     *
     * @return string
     * @since  Method available since Release 3.4.0
     */
    public function getExceptionAsString()
    {
        return self::exceptionToString($this->thrownException);
    }

    /**
     * Returns a description for an exception.
     *
     * @param  Exception $e
     * @return string
     * @since  Method available since Release 3.2.0
     */
    public static function exceptionToString(Exception $e)
    {
        if ($e instanceof PHPUnit_Framework_SelfDescribing) {
            $buffer = $e->toString();

            if ($e instanceof PHPUnit_Framework_ExpectationFailedException && $e->getComparisonFailure()) {
                $buffer = $buffer . "\n" . $e->getComparisonFailure()->getDiff();
            }

            if (!empty($buffer)) {
                $buffer = trim($buffer) . "\n";
            }
        }

        else if ($e instanceof PHPUnit_Framework_Error) {
            $buffer = $e->getMessage() . "\n";
        }

        else {
            $buffer = get_class($e) . ': ' . $e->getMessage() . "\n";
        }

        return $buffer;
    }

    /**
     * Gets the failed test.
     *
     * @return Test
     */
    public function failedTest()
    {
        return $this->failedTest;
    }

    /**
     * Gets the thrown exception.
     *
     * @return Exception
     */
    public function thrownException()
    {
        return $this->thrownException;
    }

    /**
     * Returns the exception's message.
     *
     * @return string
     */
    public function exceptionMessage()
    {
        return $this->thrownException()->getMessage();
    }

    /**
     * Returns TRUE if the thrown exception
     * is of type AssertionFailedError.
     *
     * @return boolean
     */
    public function isFailure()
    {
        return ($this->thrownException() instanceof PHPUnit_Framework_AssertionFailedError);
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

/**
 * A set of assert methods.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.0.0
 */
abstract class PHPUnit_Framework_Assert
{
    /**
     * @var integer
     */
    private static $count = 0;

    /**
     * Asserts that an array has a specified key.
     *
     * @param  mixed  $key
     * @param  array|ArrayAccess  $array
     * @param  string $message
     * @since  Method available since Release 3.0.0
     */
    public static function assertArrayHasKey($key, $array, $message = '')
    {
        if (!(is_integer($key) || is_string($key))) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(
              1, 'integer or string'
            );
        }
        if (!(is_array($array) || $array instanceof ArrayAccess)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(
              2, 'array or ArrayAccess'
            );
        }

        $constraint = new PHPUnit_Framework_Constraint_ArrayHasKey($key);

        self::assertThat($array, $constraint, $message);
    }

    /**
     * Asserts that an array does not have a specified key.
     *
     * @param  mixed  $key
     * @param  array|ArrayAccess  $array
     * @param  string $message
     * @since  Method available since Release 3.0.0
     */
    public static function assertArrayNotHasKey($key, $array, $message = '')
    {
        if (!(is_integer($key) || is_string($key))) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(
              1, 'integer or string'
            );
        }
        if (!(is_array($array) || $array instanceof ArrayAccess)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(
              2, 'array or ArrayAccess'
            );
        }

        $constraint = new PHPUnit_Framework_Constraint_Not(
          new PHPUnit_Framework_Constraint_ArrayHasKey($key)
        );

        self::assertThat($array, $constraint, $message);
    }

    /**
     * Asserts that a haystack contains a needle.
     *
     * @param  mixed   $needle
     * @param  mixed   $haystack
     * @param  string  $message
     * @param  boolean $ignoreCase
     * @param  boolean $checkForObjectIdentity
     * @since  Method available since Release 2.1.0
     */
    public static function assertContains($needle, $haystack, $message = '', $ignoreCase = FALSE, $checkForObjectIdentity = TRUE)
    {
        if (is_array($haystack) ||
            is_object($haystack) && $haystack instanceof Traversable) {
            $constraint = new PHPUnit_Framework_Constraint_TraversableContains(
              $needle, $checkForObjectIdentity
            );
        }

        else if (is_string($haystack)) {
            $constraint = new PHPUnit_Framework_Constraint_StringContains(
              $needle, $ignoreCase
            );
        }

        else {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(
              2, 'array, iterator or string'
            );
        }

        self::assertThat($haystack, $constraint, $message);
    }

    /**
     * Asserts that a haystack that is stored in a static attribute of a class
     * or an attribute of an object contains a needle.
     *
     * @param  mixed   $needle
     * @param  string  $haystackAttributeName
     * @param  mixed   $haystackClassOrObject
     * @param  string  $message
     * @param  boolean $ignoreCase
     * @param  boolean $checkForObjectIdentity
     * @since  Method available since Release 3.0.0
     */
    public static function assertAttributeContains($needle, $haystackAttributeName, $haystackClassOrObject, $message = '', $ignoreCase = FALSE, $checkForObjectIdentity = TRUE)
    {
        self::assertContains(
          $needle,
          self::readAttribute($haystackClassOrObject, $haystackAttributeName),
          $message,
          $ignoreCase,
          $checkForObjectIdentity
        );
    }

    /**
     * Asserts that a haystack does not contain a needle.
     *
     * @param  mixed   $needle
     * @param  mixed   $haystack
     * @param  string  $message
     * @param  boolean $ignoreCase
     * @param  boolean $checkForObjectIdentity
     * @since  Method available since Release 2.1.0
     */
    public static function assertNotContains($needle, $haystack, $message = '', $ignoreCase = FALSE, $checkForObjectIdentity = TRUE)
    {
        if (is_array($haystack) ||
            is_object($haystack) && $haystack instanceof Traversable) {
            $constraint = new PHPUnit_Framework_Constraint_Not(
              new PHPUnit_Framework_Constraint_TraversableContains(
                $needle, $checkForObjectIdentity
              )
            );
        }

        else if (is_string($haystack)) {
            $constraint = new PHPUnit_Framework_Constraint_Not(
              new PHPUnit_Framework_Constraint_StringContains(
                $needle, $ignoreCase
              )
            );
        }

        else {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(
              2, 'array, iterator or string'
            );
        }

        self::assertThat($haystack, $constraint, $message);
    }

    /**
     * Asserts that a haystack that is stored in a static attribute of a class
     * or an attribute of an object does not contain a needle.
     *
     * @param  mixed   $needle
     * @param  string  $haystackAttributeName
     * @param  mixed   $haystackClassOrObject
     * @param  string  $message
     * @param  boolean $ignoreCase
     * @param  boolean $checkForObjectIdentity
     * @since  Method available since Release 3.0.0
     */
    public static function assertAttributeNotContains($needle, $haystackAttributeName, $haystackClassOrObject, $message = '', $ignoreCase = FALSE, $checkForObjectIdentity = TRUE)
    {
        self::assertNotContains(
          $needle,
          self::readAttribute($haystackClassOrObject, $haystackAttributeName),
          $message,
          $ignoreCase,
          $checkForObjectIdentity
        );
    }

    /**
     * Asserts that a haystack contains only values of a given type.
     *
     * @param  string  $type
     * @param  mixed   $haystack
     * @param  boolean $isNativeType
     * @param  string  $message
     * @since  Method available since Release 3.1.4
     */
    public static function assertContainsOnly($type, $haystack, $isNativeType = NULL, $message = '')
    {
        if (!(is_array($haystack) ||
            is_object($haystack) && $haystack instanceof Traversable)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(
              2, 'array or iterator'
            );
        }

        if ($isNativeType == NULL) {
            $isNativeType = PHPUnit_Util_Type::isType($type);
        }

        self::assertThat(
          $haystack,
          new PHPUnit_Framework_Constraint_TraversableContainsOnly(
            $type, $isNativeType
          ),
          $message
        );
    }

    /**
     * Asserts that a haystack contains only instances of a given classname
     *
     * @param string $classname
     * @param array|Traversable $haystack
     * @param string $message
     */
    public static function assertContainsOnlyInstancesOf($classname, $haystack, $message = '')
    {
        if (!(is_array($haystack) ||
            is_object($haystack) && $haystack instanceof Traversable)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(
              2, 'array or iterator'
            );
        }

        self::assertThat(
            $haystack,
            new PHPUnit_Framework_Constraint_TraversableContainsOnly(
                $classname, FALSE
            ),
            $message
        );
    }

    /**
     * Asserts that a haystack that is stored in a static attribute of a class
     * or an attribute of an object contains only values of a given type.
     *
     * @param  string  $type
     * @param  string  $haystackAttributeName
     * @param  mixed   $haystackClassOrObject
     * @param  boolean $isNativeType
     * @param  string  $message
     * @since  Method available since Release 3.1.4
     */
    public static function assertAttributeContainsOnly($type, $haystackAttributeName, $haystackClassOrObject, $isNativeType = NULL, $message = '')
    {
        self::assertContainsOnly(
          $type,
          self::readAttribute($haystackClassOrObject, $haystackAttributeName),
          $isNativeType,
          $message
        );
    }

    /**
     * Asserts that a haystack does not contain only values of a given type.
     *
     * @param  string  $type
     * @param  mixed   $haystack
     * @param  boolean $isNativeType
     * @param  string  $message
     * @since  Method available since Release 3.1.4
     */
    public static function assertNotContainsOnly($type, $haystack, $isNativeType = NULL, $message = '')
    {
        if (!(is_array($haystack) ||
            is_object($haystack) && $haystack instanceof Traversable)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(
              2, 'array or iterator'
            );
        }

        if ($isNativeType == NULL) {
            $isNativeType = PHPUnit_Util_Type::isType($type);
        }

        self::assertThat(
          $haystack,
          new PHPUnit_Framework_Constraint_Not(
            new PHPUnit_Framework_Constraint_TraversableContainsOnly(
              $type, $isNativeType
            )
          ),
          $message
        );
    }

    /**
     * Asserts that a haystack that is stored in a static attribute of a class
     * or an attribute of an object does not contain only values of a given
     * type.
     *
     * @param  string  $type
     * @param  string  $haystackAttributeName
     * @param  mixed   $haystackClassOrObject
     * @param  boolean $isNativeType
     * @param  string  $message
     * @since  Method available since Release 3.1.4
     */
    public static function assertAttributeNotContainsOnly($type, $haystackAttributeName, $haystackClassOrObject, $isNativeType = NULL, $message = '')
    {
        self::assertNotContainsOnly(
          $type,
          self::readAttribute($haystackClassOrObject, $haystackAttributeName),
          $isNativeType,
          $message
        );
    }

    /**
     * Asserts the number of elements of an array, Countable or Iterator.
     *
     * @param integer $expectedCount
     * @param mixed   $haystack
     * @param string  $message
     */
    public static function assertCount($expectedCount, $haystack, $message = '')
    {
        if (!is_int($expectedCount)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'integer');
        }

        if (!$haystack instanceof Countable &&
            !$haystack instanceof Iterator &&
            !is_array($haystack)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'countable');
        }

        self::assertThat(
          $haystack,
          new PHPUnit_Framework_Constraint_Count($expectedCount),
          $message
        );
    }

    /**
     * Asserts the number of elements of an array, Countable or Iterator
     * that is stored in an attribute.
     *
     * @param integer $expectedCount
     * @param string  $haystackAttributeName
     * @param mixed   $haystackClassOrObject
     * @param string  $message
     * @since Method available since Release 3.6.0
     */
    public static function assertAttributeCount($expectedCount, $haystackAttributeName, $haystackClassOrObject, $message = '')
    {
        self::assertCount(
          $expectedCount,
          self::readAttribute($haystackClassOrObject, $haystackAttributeName),
          $message
        );
    }

    /**
     * Asserts the number of elements of an array, Countable or Iterator.
     *
     * @param integer $expectedCount
     * @param mixed   $haystack
     * @param string  $message
     */
    public static function assertNotCount($expectedCount, $haystack, $message = '')
    {
        if (!is_int($expectedCount)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'integer');
        }

        if (!$haystack instanceof Countable &&
            !$haystack instanceof Iterator &&
            !is_array($haystack)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'countable');
        }

        $constraint = new PHPUnit_Framework_Constraint_Not(
          new PHPUnit_Framework_Constraint_Count($expectedCount)
        );

        self::assertThat($haystack, $constraint, $message);
    }

    /**
     * Asserts the number of elements of an array, Countable or Iterator
     * that is stored in an attribute.
     *
     * @param integer $expectedCount
     * @param string  $haystackAttributeName
     * @param mixed   $haystackClassOrObject
     * @param string  $message
     * @since Method available since Release 3.6.0
     */
    public static function assertAttributeNotCount($expectedCount, $haystackAttributeName, $haystackClassOrObject, $message = '')
    {
        self::assertNotCount(
          $expectedCount,
          self::readAttribute($haystackClassOrObject, $haystackAttributeName),
          $message
        );
    }

    /**
     * Asserts that two variables are equal.
     *
     * @param  mixed   $expected
     * @param  mixed   $actual
     * @param  string  $message
     * @param  float   $delta
     * @param  integer $maxDepth
     * @param  boolean $canonicalize
     * @param  boolean $ignoreCase
     */
    public static function assertEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE)
    {
        $constraint = new PHPUnit_Framework_Constraint_IsEqual(
          $expected, $delta, $maxDepth, $canonicalize, $ignoreCase
        );

        self::assertThat($actual, $constraint, $message);
    }

    /**
     * Asserts that a variable is equal to an attribute of an object.
     *
     * @param  mixed   $expected
     * @param  string  $actualAttributeName
     * @param  string  $actualClassOrObject
     * @param  string  $message
     * @param  float   $delta
     * @param  integer $maxDepth
     * @param  boolean $canonicalize
     * @param  boolean $ignoreCase
     */
    public static function assertAttributeEquals($expected, $actualAttributeName, $actualClassOrObject, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE)
    {
        self::assertEquals(
          $expected,
          self::readAttribute($actualClassOrObject, $actualAttributeName),
          $message,
          $delta,
          $maxDepth,
          $canonicalize,
          $ignoreCase
        );
    }

    /**
     * Asserts that two variables are not equal.
     *
     * @param  mixed   $expected
     * @param  mixed   $actual
     * @param  string  $message
     * @param  float   $delta
     * @param  integer $maxDepth
     * @param  boolean $canonicalize
     * @param  boolean $ignoreCase
     * @since  Method available since Release 2.3.0
     */
    public static function assertNotEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE)
    {
        $constraint = new PHPUnit_Framework_Constraint_Not(
          new PHPUnit_Framework_Constraint_IsEqual(
            $expected, $delta, $maxDepth, $canonicalize, $ignoreCase
          )
        );

        self::assertThat($actual, $constraint, $message);
    }

    /**
     * Asserts that a variable is not equal to an attribute of an object.
     *
     * @param  mixed   $expected
     * @param  string  $actualAttributeName
     * @param  string  $actualClassOrObject
     * @param  string  $message
     * @param  float   $delta
     * @param  integer $maxDepth
     * @param  boolean $canonicalize
     * @param  boolean $ignoreCase
     */
    public static function assertAttributeNotEquals($expected, $actualAttributeName, $actualClassOrObject, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE)
    {
        self::assertNotEquals(
          $expected,
          self::readAttribute($actualClassOrObject, $actualAttributeName),
          $message,
          $delta,
          $maxDepth,
          $canonicalize,
          $ignoreCase
        );
    }

    /**
     * Asserts that a variable is empty.
     *
     * @param  mixed   $actual
     * @param  string  $message
     * @throws PHPUnit_Framework_AssertionFailedError
     */
    public static function assertEmpty($actual, $message = '')
    {
        self::assertThat($actual, self::isEmpty(), $message);
    }

    /**
     * Asserts that a static attribute of a class or an attribute of an object
     * is empty.
     *
     * @param string $haystackAttributeName
     * @param mixed  $haystackClassOrObject
     * @param string $message
     * @since Method available since Release 3.5.0
     */
    public static function assertAttributeEmpty($haystackAttributeName, $haystackClassOrObject, $message = '')
    {
        self::assertEmpty(
          self::readAttribute($haystackClassOrObject, $haystackAttributeName),
          $message
        );
    }

    /**
     * Asserts that a variable is not empty.
     *
     * @param  mixed   $actual
     * @param  string  $message
     * @throws PHPUnit_Framework_AssertionFailedError
     */
    public static function assertNotEmpty($actual, $message = '')
    {
        self::assertThat($actual, self::logicalNot(self::isEmpty()), $message);
    }

    /**
     * Asserts that a static attribute of a class or an attribute of an object
     * is not empty.
     *
     * @param string $haystackAttributeName
     * @param mixed  $haystackClassOrObject
     * @param string $message
     * @since Method available since Release 3.5.0
     */
    public static function assertAttributeNotEmpty($haystackAttributeName, $haystackClassOrObject, $message = '')
    {
        self::assertNotEmpty(
          self::readAttribute($haystackClassOrObject, $haystackAttributeName),
          $message
        );
    }

    /**
     * Asserts that a value is greater than another value.
     *
     * @param  mixed   $expected
     * @param  mixed   $actual
     * @param  string  $message
     * @since  Method available since Release 3.1.0
     */
    public static function assertGreaterThan($expected, $actual, $message = '')
    {
        self::assertThat($actual, self::greaterThan($expected), $message);
    }

    /**
     * Asserts that an attribute is greater than another value.
     *
     * @param  mixed   $expected
     * @param  string  $actualAttributeName
     * @param  string  $actualClassOrObject
     * @param  string  $message
     * @since  Method available since Release 3.1.0
     */
    public static function assertAttributeGreaterThan($expected, $actualAttributeName, $actualClassOrObject, $message = '')
    {
        self::assertGreaterThan(
          $expected,
          self::readAttribute($actualClassOrObject, $actualAttributeName),
          $message
        );
    }

    /**
     * Asserts that a value is greater than or equal to another value.
     *
     * @param  mixed   $expected
     * @param  mixed   $actual
     * @param  string  $message
     * @since  Method available since Release 3.1.0
     */
    public static function assertGreaterThanOrEqual($expected, $actual, $message = '')
    {
        self::assertThat(
          $actual, self::greaterThanOrEqual($expected), $message
        );
    }

    /**
     * Asserts that an attribute is greater than or equal to another value.
     *
     * @param  mixed   $expected
     * @param  string  $actualAttributeName
     * @param  string  $actualClassOrObject
     * @param  string  $message
     * @since  Method available since Release 3.1.0
     */
    public static function assertAttributeGreaterThanOrEqual($expected, $actualAttributeName, $actualClassOrObject, $message = '')
    {
        self::assertGreaterThanOrEqual(
          $expected,
          self::readAttribute($actualClassOrObject, $actualAttributeName),
          $message
        );
    }

    /**
     * Asserts that a value is smaller than another value.
     *
     * @param  mixed   $expected
     * @param  mixed   $actual
     * @param  string  $message
     * @since  Method available since Release 3.1.0
     */
    public static function assertLessThan($expected, $actual, $message = '')
    {
        self::assertThat($actual, self::lessThan($expected), $message);
    }

    /**
     * Asserts that an attribute is smaller than another value.
     *
     * @param  mixed   $expected
     * @param  string  $actualAttributeName
     * @param  string  $actualClassOrObject
     * @param  string  $message
     * @since  Method available since Release 3.1.0
     */
    public static function assertAttributeLessThan($expected, $actualAttributeName, $actualClassOrObject, $message = '')
    {
        self::assertLessThan(
          $expected,
          self::readAttribute($actualClassOrObject, $actualAttributeName),
          $message
        );
    }

    /**
     * Asserts that a value is smaller than or equal to another value.
     *
     * @param  mixed   $expected
     * @param  mixed   $actual
     * @param  string  $message
     * @since  Method available since Release 3.1.0
     */
    public static function assertLessThanOrEqual($expected, $actual, $message = '')
    {
        self::assertThat($actual, self::lessThanOrEqual($expected), $message);
    }

    /**
     * Asserts that an attribute is smaller than or equal to another value.
     *
     * @param  mixed   $expected
     * @param  string  $actualAttributeName
     * @param  string  $actualClassOrObject
     * @param  string  $message
     * @since  Method available since Release 3.1.0
     */
    public static function assertAttributeLessThanOrEqual($expected, $actualAttributeName, $actualClassOrObject, $message = '')
    {
        self::assertLessThanOrEqual(
          $expected,
          self::readAttribute($actualClassOrObject, $actualAttributeName),
          $message
        );
    }

    /**
     * Asserts that the contents of one file is equal to the contents of another
     * file.
     *
     * @param  string  $expected
     * @param  string  $actual
     * @param  string  $message
     * @param  boolean $canonicalize
     * @param  boolean $ignoreCase
     * @since  Method available since Release 3.2.14
     */
    public static function assertFileEquals($expected, $actual, $message = '', $canonicalize = FALSE, $ignoreCase = FALSE)
    {
        self::assertFileExists($expected, $message);
        self::assertFileExists($actual, $message);

        self::assertEquals(
          file_get_contents($expected),
          file_get_contents($actual),
          $message,
          0,
          10,
          $canonicalize,
          $ignoreCase
        );
    }

    /**
     * Asserts that the contents of one file is not equal to the contents of
     * another file.
     *
     * @param  string  $expected
     * @param  string  $actual
     * @param  string  $message
     * @param  boolean $canonicalize
     * @param  boolean $ignoreCase
     * @since  Method available since Release 3.2.14
     */
    public static function assertFileNotEquals($expected, $actual, $message = '', $canonicalize = FALSE, $ignoreCase = FALSE)
    {
        self::assertFileExists($expected, $message);
        self::assertFileExists($actual, $message);

        self::assertNotEquals(
          file_get_contents($expected),
          file_get_contents($actual),
          $message,
          0,
          10,
          $canonicalize,
          $ignoreCase
        );
    }

    /**
     * Asserts that the contents of a string is equal
     * to the contents of a file.
     *
     * @param  string  $expectedFile
     * @param  string  $actualString
     * @param  string  $message
     * @param  boolean $canonicalize
     * @param  boolean $ignoreCase
     * @since  Method available since Release 3.3.0
     */
    public static function assertStringEqualsFile($expectedFile, $actualString, $message = '', $canonicalize = FALSE, $ignoreCase = FALSE)
    {
        self::assertFileExists($expectedFile, $message);

        self::assertEquals(
          file_get_contents($expectedFile),
          $actualString,
          $message,
          0,
          10,
          $canonicalize,
          $ignoreCase
        );
    }

    /**
     * Asserts that the contents of a string is not equal
     * to the contents of a file.
     *
     * @param  string  $expectedFile
     * @param  string  $actualString
     * @param  string  $message
     * @param  boolean $canonicalize
     * @param  boolean $ignoreCase
     * @since  Method available since Release 3.3.0
     */
    public static function assertStringNotEqualsFile($expectedFile, $actualString, $message = '', $canonicalize = FALSE, $ignoreCase = FALSE)
    {
        self::assertFileExists($expectedFile, $message);

        self::assertNotEquals(
          file_get_contents($expectedFile),
          $actualString,
          $message,
          0,
          10,
          $canonicalize,
          $ignoreCase
        );
    }

    /**
     * Asserts that a file exists.
     *
     * @param  string $filename
     * @param  string $message
     * @since  Method available since Release 3.0.0
     */
    public static function assertFileExists($filename, $message = '')
    {
        if (!is_string($filename)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        $constraint = new PHPUnit_Framework_Constraint_FileExists;

        self::assertThat($filename, $constraint, $message);
    }

    /**
     * Asserts that a file does not exist.
     *
     * @param  string $filename
     * @param  string $message
     * @since  Method available since Release 3.0.0
     */
    public static function assertFileNotExists($filename, $message = '')
    {
        if (!is_string($filename)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        $constraint = new PHPUnit_Framework_Constraint_Not(
          new PHPUnit_Framework_Constraint_FileExists
        );

        self::assertThat($filename, $constraint, $message);
    }

    /**
     * Asserts that a condition is true.
     *
     * @param  boolean $condition
     * @param  string  $message
     * @throws PHPUnit_Framework_AssertionFailedError
     */
    public static function assertTrue($condition, $message = '')
    {
        self::assertThat($condition, self::isTrue(), $message);
    }

    /**
     * Asserts that a condition is false.
     *
     * @param  boolean  $condition
     * @param  string   $message
     * @throws PHPUnit_Framework_AssertionFailedError
     */
    public static function assertFalse($condition, $message = '')
    {
        self::assertThat($condition, self::isFalse(), $message);
    }

    /**
     * Asserts that a variable is not NULL.
     *
     * @param  mixed  $actual
     * @param  string $message
     */
    public static function assertNotNull($actual, $message = '')
    {
        self::assertThat($actual, self::logicalNot(self::isNull()), $message);
    }

    /**
     * Asserts that a variable is NULL.
     *
     * @param  mixed  $actual
     * @param  string $message
     */
    public static function assertNull($actual, $message = '')
    {
        self::assertThat($actual, self::isNull(), $message);
    }

    /**
     * Asserts that a class has a specified attribute.
     *
     * @param  string $attributeName
     * @param  string $className
     * @param  string $message
     * @since  Method available since Release 3.1.0
     */
    public static function assertClassHasAttribute($attributeName, $className, $message = '')
    {
        if (!is_string($attributeName)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        if (!is_string($className) || !class_exists($className, FALSE)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'class name');
        }

        $constraint = new PHPUnit_Framework_Constraint_ClassHasAttribute(
          $attributeName
        );

        self::assertThat($className, $constraint, $message);
    }

    /**
     * Asserts that a class does not have a specified attribute.
     *
     * @param  string $attributeName
     * @param  string $className
     * @param  string $message
     * @since  Method available since Release 3.1.0
     */
    public static function assertClassNotHasAttribute($attributeName, $className, $message = '')
    {
        if (!is_string($attributeName)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        if (!is_string($className) || !class_exists($className, FALSE)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'class name');
        }

        $constraint = new PHPUnit_Framework_Constraint_Not(
          new PHPUnit_Framework_Constraint_ClassHasAttribute($attributeName)
        );

        self::assertThat($className, $constraint, $message);
    }

    /**
     * Asserts that a class has a specified static attribute.
     *
     * @param  string $attributeName
     * @param  string $className
     * @param  string $message
     * @since  Method available since Release 3.1.0
     */
    public static function assertClassHasStaticAttribute($attributeName, $className, $message = '')
    {
        if (!is_string($attributeName)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        if (!is_string($className) || !class_exists($className, FALSE)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'class name');
        }

        $constraint = new PHPUnit_Framework_Constraint_ClassHasStaticAttribute(
          $attributeName
        );

        self::assertThat($className, $constraint, $message);
    }

    /**
     * Asserts that a class does not have a specified static attribute.
     *
     * @param  string $attributeName
     * @param  string $className
     * @param  string $message
     * @since  Method available since Release 3.1.0
     */
    public static function assertClassNotHasStaticAttribute($attributeName, $className, $message = '')
    {
        if (!is_string($attributeName)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        if (!is_string($className) || !class_exists($className, FALSE)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'class name');
        }

        $constraint = new PHPUnit_Framework_Constraint_Not(
          new PHPUnit_Framework_Constraint_ClassHasStaticAttribute(
            $attributeName
          )
        );

        self::assertThat($className, $constraint, $message);
    }

    /**
     * Asserts that an object has a specified attribute.
     *
     * @param  string $attributeName
     * @param  object $object
     * @param  string $message
     * @since  Method available since Release 3.0.0
     */
    public static function assertObjectHasAttribute($attributeName, $object, $message = '')
    {
        if (!is_string($attributeName)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        if (!is_object($object)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'object');
        }

        $constraint = new PHPUnit_Framework_Constraint_ObjectHasAttribute(
          $attributeName
        );

        self::assertThat($object, $constraint, $message);
    }

    /**
     * Asserts that an object does not have a specified attribute.
     *
     * @param  string $attributeName
     * @param  object $object
     * @param  string $message
     * @since  Method available since Release 3.0.0
     */
    public static function assertObjectNotHasAttribute($attributeName, $object, $message = '')
    {
        if (!is_string($attributeName)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        if (!is_object($object)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'object');
        }

        $constraint = new PHPUnit_Framework_Constraint_Not(
          new PHPUnit_Framework_Constraint_ObjectHasAttribute($attributeName)
        );

        self::assertThat($object, $constraint, $message);
    }

    /**
     * Asserts that two variables have the same type and value.
     * Used on objects, it asserts that two variables reference
     * the same object.
     *
     * @param  mixed  $expected
     * @param  mixed  $actual
     * @param  string $message
     */
    public static function assertSame($expected, $actual, $message = '')
    {
        if (is_bool($expected) && is_bool($actual)) {
            self::assertEquals($expected, $actual, $message);
        } else {
            $constraint = new PHPUnit_Framework_Constraint_IsIdentical(
              $expected
            );

            self::assertThat($actual, $constraint, $message);
        }
    }

    /**
     * Asserts that a variable and an attribute of an object have the same type
     * and value.
     *
     * @param  mixed  $expected
     * @param  string $actualAttributeName
     * @param  object $actualClassOrObject
     * @param  string $message
     */
    public static function assertAttributeSame($expected, $actualAttributeName, $actualClassOrObject, $message = '')
    {
        self::assertSame(
          $expected,
          self::readAttribute($actualClassOrObject, $actualAttributeName),
          $message
        );
    }

    /**
     * Asserts that two variables do not have the same type and value.
     * Used on objects, it asserts that two variables do not reference
     * the same object.
     *
     * @param  mixed  $expected
     * @param  mixed  $actual
     * @param  string $message
     */
    public static function assertNotSame($expected, $actual, $message = '')
    {
        if (is_bool($expected) && is_bool($actual)) {
            self::assertNotEquals($expected, $actual, $message);
        } else {
            $constraint = new PHPUnit_Framework_Constraint_Not(
              new PHPUnit_Framework_Constraint_IsIdentical($expected)
            );

            self::assertThat($actual, $constraint, $message);
        }
    }

    /**
     * Asserts that a variable and an attribute of an object do not have the
     * same type and value.
     *
     * @param  mixed  $expected
     * @param  string $actualAttributeName
     * @param  object $actualClassOrObject
     * @param  string $message
     */
    public static function assertAttributeNotSame($expected, $actualAttributeName, $actualClassOrObject, $message = '')
    {
        self::assertNotSame(
          $expected,
          self::readAttribute($actualClassOrObject, $actualAttributeName),
          $message
        );
    }

    /**
     * Asserts that a variable is of a given type.
     *
     * @param string $expected
     * @param mixed  $actual
     * @param string $message
     * @since Method available since Release 3.5.0
     */
    public static function assertInstanceOf($expected, $actual, $message = '')
    {
        if (is_string($expected)) {
            if (class_exists($expected) || interface_exists($expected)) {
                $constraint = new PHPUnit_Framework_Constraint_IsInstanceOf(
                  $expected
                );
            }

            else {
                throw PHPUnit_Util_InvalidArgumentHelper::factory(
                  1, 'class or interface name'
                );
            }
        } else {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        self::assertThat($actual, $constraint, $message);
    }

    /**
     * Asserts that an attribute is of a given type.
     *
     * @param string $expected
     * @param string $attributeName
     * @param mixed  $classOrObject
     * @param string $message
     * @since Method available since Release 3.5.0
     */
    public static function assertAttributeInstanceOf($expected, $attributeName, $classOrObject, $message = '')
    {
        self::assertInstanceOf(
          $expected,
          self::readAttribute($classOrObject, $attributeName),
          $message
        );
    }

    /**
     * Asserts that a variable is not of a given type.
     *
     * @param string $expected
     * @param mixed  $actual
     * @param string $message
     * @since Method available since Release 3.5.0
     */
    public static function assertNotInstanceOf($expected, $actual, $message = '')
    {
        if (is_string($expected)) {
            if (class_exists($expected) || interface_exists($expected)) {
                $constraint = new PHPUnit_Framework_Constraint_Not(
                  new PHPUnit_Framework_Constraint_IsInstanceOf($expected)
                );
            }

            else {
                throw PHPUnit_Util_InvalidArgumentHelper::factory(
                  1, 'class or interface name'
                );
            }
        } else {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        self::assertThat($actual, $constraint, $message);
    }

    /**
     * Asserts that an attribute is of a given type.
     *
     * @param string $expected
     * @param string $attributeName
     * @param mixed  $classOrObject
     * @param string $message
     * @since Method available since Release 3.5.0
     */
    public static function assertAttributeNotInstanceOf($expected, $attributeName, $classOrObject, $message = '')
    {
        self::assertNotInstanceOf(
          $expected,
          self::readAttribute($classOrObject, $attributeName),
          $message
        );
    }

    /**
     * Asserts that a variable is of a given type.
     *
     * @param string $expected
     * @param mixed  $actual
     * @param string $message
     * @since Method available since Release 3.5.0
     */
    public static function assertInternalType($expected, $actual, $message = '')
    {
        if (is_string($expected)) {
            $constraint = new PHPUnit_Framework_Constraint_IsType(
              $expected
            );
        } else {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        self::assertThat($actual, $constraint, $message);
    }

    /**
     * Asserts that an attribute is of a given type.
     *
     * @param string $expected
     * @param string $attributeName
     * @param mixed  $classOrObject
     * @param string $message
     * @since Method available since Release 3.5.0
     */
    public static function assertAttributeInternalType($expected, $attributeName, $classOrObject, $message = '')
    {
        self::assertInternalType(
          $expected,
          self::readAttribute($classOrObject, $attributeName),
          $message
        );
    }

    /**
     * Asserts that a variable is not of a given type.
     *
     * @param string $expected
     * @param mixed  $actual
     * @param string $message
     * @since Method available since Release 3.5.0
     */
    public static function assertNotInternalType($expected, $actual, $message = '')
    {
        if (is_string($expected)) {
            $constraint = new PHPUnit_Framework_Constraint_Not(
              new PHPUnit_Framework_Constraint_IsType($expected)
            );
        } else {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        self::assertThat($actual, $constraint, $message);
    }

    /**
     * Asserts that an attribute is of a given type.
     *
     * @param string $expected
     * @param string $attributeName
     * @param mixed  $classOrObject
     * @param string $message
     * @since Method available since Release 3.5.0
     */
    public static function assertAttributeNotInternalType($expected, $attributeName, $classOrObject, $message = '')
    {
        self::assertNotInternalType(
          $expected,
          self::readAttribute($classOrObject, $attributeName),
          $message
        );
    }

    /**
     * Asserts that a string matches a given regular expression.
     *
     * @param  string $pattern
     * @param  string $string
     * @param  string $message
     */
    public static function assertRegExp($pattern, $string, $message = '')
    {
        if (!is_string($pattern)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        if (!is_string($string)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string');
        }

        $constraint = new PHPUnit_Framework_Constraint_PCREMatch($pattern);

        self::assertThat($string, $constraint, $message);
    }

    /**
     * Asserts that a string does not match a given regular expression.
     *
     * @param  string $pattern
     * @param  string $string
     * @param  string $message
     * @since  Method available since Release 2.1.0
     */
    public static function assertNotRegExp($pattern, $string, $message = '')
    {
        if (!is_string($pattern)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        if (!is_string($string)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string');
        }

        $constraint = new PHPUnit_Framework_Constraint_Not(
          new PHPUnit_Framework_Constraint_PCREMatch($pattern)
        );

        self::assertThat($string, $constraint, $message);
    }

    /**
     * Assert that the size of two arrays (or `Countable` or `Iterator` objects)
     * is the same.
     *
     * @param array|Countable|Iterator $expected
     * @param array|Countable|Iterator $actual
     * @param string $message
     */
    public static function assertSameSize($expected, $actual, $message = '')
    {
        if (!$expected instanceof Countable &&
            !$expected instanceof Iterator &&
            !is_array($expected)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'countable');
        }

        if (!$actual instanceof Countable &&
            !$actual instanceof Iterator &&
            !is_array($actual)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'countable');
        }

        self::assertThat(
          $actual,
          new PHPUnit_Framework_Constraint_SameSize($expected),
          $message
        );
    }

    /**
     * Assert that the size of two arrays (or `Countable` or `Iterator` objects)
     * is not the same.
     *
     * @param array|Countable|Iterator $expected
     * @param array|Countable|Iterator $actual
     * @param string $message
     */
    public static function assertNotSameSize($expected, $actual, $message = '')
    {
        if (!$expected instanceof Countable &&
            !$expected instanceof Iterator &&
            !is_array($expected)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'countable');
        }

        if (!$actual instanceof Countable &&
            !$actual instanceof Iterator &&
            !is_array($actual)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'countable');
        }

        $constraint = new PHPUnit_Framework_Constraint_Not(
          new PHPUnit_Framework_Constraint_SameSize($expected)
        );

        self::assertThat($actual, $constraint, $message);
    }

    /**
     * Asserts that a string matches a given format string.
     *
     * @param  string $format
     * @param  string $string
     * @param  string $message
     * @since  Method available since Release 3.5.0
     */
    public static function assertStringMatchesFormat($format, $string, $message = '')
    {
        if (!is_string($format)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        if (!is_string($string)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string');
        }

        $constraint = new PHPUnit_Framework_Constraint_StringMatches($format);

        self::assertThat($string, $constraint, $message);
    }

    /**
     * Asserts that a string does not match a given format string.
     *
     * @param  string $format
     * @param  string $string
     * @param  string $message
     * @since  Method available since Release 3.5.0
     */
    public static function assertStringNotMatchesFormat($format, $string, $message = '')
    {
        if (!is_string($format)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        if (!is_string($string)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string');
        }

        $constraint = new PHPUnit_Framework_Constraint_Not(
          new PHPUnit_Framework_Constraint_StringMatches($format)
        );

        self::assertThat($string, $constraint, $message);
    }

    /**
     * Asserts that a string matches a given format file.
     *
     * @param  string $formatFile
     * @param  string $string
     * @param  string $message
     * @since  Method available since Release 3.5.0
     */
    public static function assertStringMatchesFormatFile($formatFile, $string, $message = '')
    {
        self::assertFileExists($formatFile, $message);

        if (!is_string($string)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string');
        }

        $constraint = new PHPUnit_Framework_Constraint_StringMatches(
          file_get_contents($formatFile)
        );

        self::assertThat($string, $constraint, $message);
    }

    /**
     * Asserts that a string does not match a given format string.
     *
     * @param  string $formatFile
     * @param  string $string
     * @param  string $message
     * @since  Method available since Release 3.5.0
     */
    public static function assertStringNotMatchesFormatFile($formatFile, $string, $message = '')
    {
        self::assertFileExists($formatFile, $message);

        if (!is_string($string)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string');
        }

        $constraint = new PHPUnit_Framework_Constraint_Not(
          new PHPUnit_Framework_Constraint_StringMatches(
            file_get_contents($formatFile)
          )
        );

        self::assertThat($string, $constraint, $message);
    }

    /**
     * Asserts that a string starts with a given prefix.
     *
     * @param  string $prefix
     * @param  string $string
     * @param  string $message
     * @since  Method available since Release 3.4.0
     */
    public static function assertStringStartsWith($prefix, $string, $message = '')
    {
        if (!is_string($prefix)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        if (!is_string($string)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string');
        }

        $constraint = new PHPUnit_Framework_Constraint_StringStartsWith(
          $prefix
        );

        self::assertThat($string, $constraint, $message);
    }

    /**
     * Asserts that a string starts not with a given prefix.
     *
     * @param  string $prefix
     * @param  string $string
     * @param  string $message
     * @since  Method available since Release 3.4.0
     */
    public static function assertStringStartsNotWith($prefix, $string, $message = '')
    {
        if (!is_string($prefix)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        if (!is_string($string)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string');
        }

        $constraint = new PHPUnit_Framework_Constraint_Not(
          new PHPUnit_Framework_Constraint_StringStartsWith($prefix)
        );

        self::assertThat($string, $constraint, $message);
    }

    /**
     * Asserts that a string ends with a given suffix.
     *
     * @param  string $suffix
     * @param  string $string
     * @param  string $message
     * @since  Method available since Release 3.4.0
     */
    public static function assertStringEndsWith($suffix, $string, $message = '')
    {
        if (!is_string($suffix)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        if (!is_string($string)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string');
        }

        $constraint = new PHPUnit_Framework_Constraint_StringEndsWith($suffix);

        self::assertThat($string, $constraint, $message);
    }

    /**
     * Asserts that a string ends not with a given suffix.
     *
     * @param  string $suffix
     * @param  string $string
     * @param  string $message
     * @since  Method available since Release 3.4.0
     */
    public static function assertStringEndsNotWith($suffix, $string, $message = '')
    {
        if (!is_string($suffix)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        if (!is_string($string)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string');
        }

        $constraint = new PHPUnit_Framework_Constraint_Not(
          new PHPUnit_Framework_Constraint_StringEndsWith($suffix)
        );

        self::assertThat($string, $constraint, $message);
    }

    /**
     * Asserts that two XML files are equal.
     *
     * @param  string $expectedFile
     * @param  string $actualFile
     * @param  string $message
     * @since  Method available since Release 3.1.0
     */
    public static function assertXmlFileEqualsXmlFile($expectedFile, $actualFile, $message = '')
    {
        self::assertFileExists($expectedFile);
        self::assertFileExists($actualFile);

        $expected = new DOMDocument;
        $expected->preserveWhiteSpace = FALSE;
        $expected->load($expectedFile);

        $actual = new DOMDocument;
        $actual->preserveWhiteSpace = FALSE;
        $actual->load($actualFile);

        self::assertEquals($expected, $actual, $message);
    }

    /**
     * Asserts that two XML files are not equal.
     *
     * @param  string $expectedFile
     * @param  string $actualFile
     * @param  string $message
     * @since  Method available since Release 3.1.0
     */
    public static function assertXmlFileNotEqualsXmlFile($expectedFile, $actualFile, $message = '')
    {
        self::assertFileExists($expectedFile);
        self::assertFileExists($actualFile);

        $expected = new DOMDocument;
        $expected->preserveWhiteSpace = FALSE;
        $expected->load($expectedFile);

        $actual = new DOMDocument;
        $actual->preserveWhiteSpace = FALSE;
        $actual->load($actualFile);

        self::assertNotEquals($expected, $actual, $message);
    }

    /**
     * Asserts that two XML documents are equal.
     *
     * @param  string $expectedFile
     * @param  string $actualXml
     * @param  string $message
     * @since  Method available since Release 3.3.0
     */
    public static function assertXmlStringEqualsXmlFile($expectedFile, $actualXml, $message = '')
    {
        self::assertFileExists($expectedFile);

        $expected = new DOMDocument;
        $expected->preserveWhiteSpace = FALSE;
        $expected->load($expectedFile);

        $actual = new DOMDocument;
        $actual->preserveWhiteSpace = FALSE;
        $actual->loadXML($actualXml);

        self::assertEquals($expected, $actual, $message);
    }

    /**
     * Asserts that two XML documents are not equal.
     *
     * @param  string $expectedFile
     * @param  string $actualXml
     * @param  string $message
     * @since  Method available since Release 3.3.0
     */
    public static function assertXmlStringNotEqualsXmlFile($expectedFile, $actualXml, $message = '')
    {
        self::assertFileExists($expectedFile);

        $expected = new DOMDocument;
        $expected->preserveWhiteSpace = FALSE;
        $expected->load($expectedFile);

        $actual = new DOMDocument;
        $actual->preserveWhiteSpace = FALSE;
        $actual->loadXML($actualXml);

        self::assertNotEquals($expected, $actual, $message);
    }

    /**
     * Asserts that two XML documents are equal.
     *
     * @param  string $expectedXml
     * @param  string $actualXml
     * @param  string $message
     * @since  Method available since Release 3.1.0
     */
    public static function assertXmlStringEqualsXmlString($expectedXml, $actualXml, $message = '')
    {
        $expected = new DOMDocument;
        $expected->preserveWhiteSpace = FALSE;
        $expected->loadXML($expectedXml);

        $actual = new DOMDocument;
        $actual->preserveWhiteSpace = FALSE;
        $actual->loadXML($actualXml);

        self::assertEquals($expected, $actual, $message);
    }

    /**
     * Asserts that two XML documents are not equal.
     *
     * @param  string $expectedXml
     * @param  string $actualXml
     * @param  string $message
     * @since  Method available since Release 3.1.0
     */
    public static function assertXmlStringNotEqualsXmlString($expectedXml, $actualXml, $message = '')
    {
        $expected = new DOMDocument;
        $expected->preserveWhiteSpace = FALSE;
        $expected->loadXML($expectedXml);

        $actual = new DOMDocument;
        $actual->preserveWhiteSpace = FALSE;
        $actual->loadXML($actualXml);

        self::assertNotEquals($expected, $actual, $message);
    }

    /**
     * Asserts that a hierarchy of DOMElements matches.
     *
     * @param DOMElement $expectedElement
     * @param DOMElement $actualElement
     * @param boolean $checkAttributes
     * @param string  $message
     * @author Mattis Stordalen Flister <mattis@xait.no>
     * @since  Method available since Release 3.3.0
     */
    public static function assertEqualXMLStructure(DOMElement $expectedElement, DOMElement $actualElement, $checkAttributes = FALSE, $message = '')
    {
        self::assertEquals(
          $expectedElement->tagName,
          $actualElement->tagName,
          $message
        );

        if ($checkAttributes) {
            self::assertEquals(
              $expectedElement->attributes->length,
              $actualElement->attributes->length,
              sprintf(
                '%s%sNumber of attributes on node "%s" does not match',
                $message,
                !empty($message) ? "\n" : '',
                $expectedElement->tagName
              )
            );

            for ($i = 0 ; $i < $expectedElement->attributes->length; $i++) {
                $expectedAttribute = $expectedElement->attributes->item($i);
                $actualAttribute   = $actualElement->attributes->getNamedItem(
                  $expectedAttribute->name
                );

                if (!$actualAttribute) {
                    self::fail(
                      sprintf(
                        '%s%sCould not find attribute "%s" on node "%s"',
                        $message,
                        !empty($message) ? "\n" : '',
                        $expectedAttribute->name,
                        $expectedElement->tagName
                      )
                    );
                }
            }
        }

        PHPUnit_Util_XML::removeCharacterDataNodes($expectedElement);
        PHPUnit_Util_XML::removeCharacterDataNodes($actualElement);

        self::assertEquals(
          $expectedElement->childNodes->length,
          $actualElement->childNodes->length,
          sprintf(
            '%s%sNumber of child nodes of "%s" differs',
            $message,
            !empty($message) ? "\n" : '',
            $expectedElement->tagName
          )
        );

        for ($i = 0; $i < $expectedElement->childNodes->length; $i++) {
            self::assertEqualXMLStructure(
              $expectedElement->childNodes->item($i),
              $actualElement->childNodes->item($i),
              $checkAttributes,
              $message
            );
        }
    }

    /**
     * Assert the presence, absence, or count of elements in a document matching
     * the CSS $selector, regardless of the contents of those elements.
     *
     * The first argument, $selector, is the CSS selector used to match
     * the elements in the $actual document.
     *
     * The second argument, $count, can be either boolean or numeric.
     * When boolean, it asserts for presence of elements matching the selector
     * (TRUE) or absence of elements (FALSE).
     * When numeric, it asserts the count of elements.
     *
     * assertSelectCount("#binder", true, $xml);  // any?
     * assertSelectCount(".binder", 3, $xml);     // exactly 3?
     *
     * @param  array   $selector
     * @param  integer $count
     * @param  mixed   $actual
     * @param  string  $message
     * @param  boolean $isHtml
     * @since  Method available since Release 3.3.0
     * @author Mike Naberezny <mike@maintainable.com>
     * @author Derek DeVries <derek@maintainable.com>
     */
    public static function assertSelectCount($selector, $count, $actual, $message = '', $isHtml = TRUE)
    {
        self::assertSelectEquals(
          $selector, TRUE, $count, $actual, $message, $isHtml
        );
    }

    /**
     * assertSelectRegExp("#binder .name", "/Mike|Derek/", true, $xml); // any?
     * assertSelectRegExp("#binder .name", "/Mike|Derek/", 3, $xml);    // 3?
     *
     * @param  array   $selector
     * @param  string  $pattern
     * @param  integer $count
     * @param  mixed   $actual
     * @param  string  $message
     * @param  boolean $isHtml
     * @since  Method available since Release 3.3.0
     * @author Mike Naberezny <mike@maintainable.com>
     * @author Derek DeVries <derek@maintainable.com>
     */
    public static function assertSelectRegExp($selector, $pattern, $count, $actual, $message = '', $isHtml = TRUE)
    {
        self::assertSelectEquals(
          $selector, "regexp:$pattern", $count, $actual, $message, $isHtml
        );
    }

    /**
     * assertSelectEquals("#binder .name", "Chuck", true,  $xml);  // any?
     * assertSelectEquals("#binder .name", "Chuck", false, $xml);  // none?
     *
     * @param  array   $selector
     * @param  string  $content
     * @param  integer $count
     * @param  mixed   $actual
     * @param  string  $message
     * @param  boolean $isHtml
     * @since  Method available since Release 3.3.0
     * @author Mike Naberezny <mike@maintainable.com>
     * @author Derek DeVries <derek@maintainable.com>
     */
    public static function assertSelectEquals($selector, $content, $count, $actual, $message = '', $isHtml = TRUE)
    {
        $tags = PHPUnit_Util_XML::cssSelect(
          $selector, $content, $actual, $isHtml
        );

        // assert specific number of elements
        if (is_numeric($count)) {
            $counted = $tags ? count($tags) : 0;
            self::assertEquals($count, $counted, $message);
        }

        // assert any elements exist if true, assert no elements exist if false
        else if (is_bool($count)) {
            $any = count($tags) > 0 && $tags[0] instanceof DOMNode;

            if ($count) {
                self::assertTrue($any, $message);
            } else {
                self::assertFalse($any, $message);
            }
        }

        // check for range number of elements
        else if (is_array($count) &&
                (isset($count['>']) || isset($count['<']) ||
                isset($count['>=']) || isset($count['<=']))) {
            $counted = $tags ? count($tags) : 0;

            if (isset($count['>'])) {
                self::assertTrue($counted > $count['>'], $message);
            }

            if (isset($count['>='])) {
                self::assertTrue($counted >= $count['>='], $message);
            }

            if (isset($count['<'])) {
                self::assertTrue($counted < $count['<'], $message);
            }

            if (isset($count['<='])) {
                self::assertTrue($counted <= $count['<='], $message);
            }
        } else {
            throw new PHPUnit_Framework_Exception;
        }
    }

    /**
     * Evaluate an HTML or XML string and assert its structure and/or contents.
     *
     * The first argument ($matcher) is an associative array that specifies the
     * match criteria for the assertion:
     *
     *  - `id`           : the node with the given id attribute must match the
     *                     corresponsing value.
     *  - `tag`          : the node type must match the corresponding value.
     *  - `attributes`   : a hash. The node's attributres must match the
     *                     corresponsing values in the hash.
     *  - `content`      : The text content must match the given value.
     *  - `parent`       : a hash. The node's parent must match the
     *                     corresponsing hash.
     *  - `child`        : a hash. At least one of the node's immediate children
     *                     must meet the criteria described by the hash.
     *  - `ancestor`     : a hash. At least one of the node's ancestors must
     *                     meet the criteria described by the hash.
     *  - `descendant`   : a hash. At least one of the node's descendants must
     *                     meet the criteria described by the hash.
     *  - `children`     : a hash, for counting children of a node.
     *                     Accepts the keys:
     *    - `count`        : a number which must equal the number of children
     *                       that match
     *    - `less_than`    : the number of matching children must be greater
     *                       than this number
     *    - `greater_than` : the number of matching children must be less than
     *                       this number
     *    - `only`         : another hash consisting of the keys to use to match
     *                       on the children, and only matching children will be
     *                       counted
     *
     * <code>
     * // Matcher that asserts that there is an element with an id="my_id".
     * $matcher = array('id' => 'my_id');
     *
     * // Matcher that asserts that there is a "span" tag.
     * $matcher = array('tag' => 'span');
     *
     * // Matcher that asserts that there is a "span" tag with the content
     * // "Hello World".
     * $matcher = array('tag' => 'span', 'content' => 'Hello World');
     *
     * // Matcher that asserts that there is a "span" tag with content matching
     * // the regular expression pattern.
     * $matcher = array('tag' => 'span', 'content' => 'regexp:/Try P(HP|ython)/');
     *
     * // Matcher that asserts that there is a "span" with an "list" class
     * // attribute.
     * $matcher = array(
     *   'tag'        => 'span',
     *   'attributes' => array('class' => 'list')
     * );
     *
     * // Matcher that asserts that there is a "span" inside of a "div".
     * $matcher = array(
     *   'tag'    => 'span',
     *   'parent' => array('tag' => 'div')
     * );
     *
     * // Matcher that asserts that there is a "span" somewhere inside a
     * // "table".
     * $matcher = array(
     *   'tag'      => 'span',
     *   'ancestor' => array('tag' => 'table')
     * );
     *
     * // Matcher that asserts that there is a "span" with at least one "em"
     * // child.
     * $matcher = array(
     *   'tag'   => 'span',
     *   'child' => array('tag' => 'em')
     * );
     *
     * // Matcher that asserts that there is a "span" containing a (possibly
     * // nested) "strong" tag.
     * $matcher = array(
     *   'tag'        => 'span',
     *   'descendant' => array('tag' => 'strong')
     * );
     *
     * // Matcher that asserts that there is a "span" containing 5-10 "em" tags
     * // as immediate children.
     * $matcher = array(
     *   'tag'      => 'span',
     *   'children' => array(
     *     'less_than'    => 11,
     *     'greater_than' => 4,
     *     'only'         => array('tag' => 'em')
     *   )
     * );
     *
     * // Matcher that asserts that there is a "div", with an "ul" ancestor and
     * // a "li" parent (with class="enum"), and containing a "span" descendant
     * // that contains an element with id="my_test" and the text "Hello World".
     * $matcher = array(
     *   'tag'        => 'div',
     *   'ancestor'   => array('tag' => 'ul'),
     *   'parent'     => array(
     *     'tag'        => 'li',
     *     'attributes' => array('class' => 'enum')
     *   ),
     *   'descendant' => array(
     *     'tag'   => 'span',
     *     'child' => array(
     *       'id'      => 'my_test',
     *       'content' => 'Hello World'
     *     )
     *   )
     * );
     *
     * // Use assertTag() to apply a $matcher to a piece of $html.
     * $this->assertTag($matcher, $html);
     *
     * // Use assertTag() to apply a $matcher to a piece of $xml.
     * $this->assertTag($matcher, $xml, '', FALSE);
     * </code>
     *
     * The second argument ($actual) is a string containing either HTML or
     * XML text to be tested.
     *
     * The third argument ($message) is an optional message that will be
     * used if the assertion fails.
     *
     * The fourth argument ($html) is an optional flag specifying whether
     * to load the $actual string into a DOMDocument using the HTML or
     * XML load strategy.  It is TRUE by default, which assumes the HTML
     * load strategy.  In many cases, this will be acceptable for XML as well.
     *
     * @param  array   $matcher
     * @param  string  $actual
     * @param  string  $message
     * @param  boolean $isHtml
     * @since  Method available since Release 3.3.0
     * @author Mike Naberezny <mike@maintainable.com>
     * @author Derek DeVries <derek@maintainable.com>
     */
    public static function assertTag($matcher, $actual, $message = '', $isHtml = TRUE)
    {
        $dom     = PHPUnit_Util_XML::load($actual, $isHtml);
        $tags    = PHPUnit_Util_XML::findNodes($dom, $matcher, $isHtml);
        $matched = count($tags) > 0 && $tags[0] instanceof DOMNode;

        self::assertTrue($matched, $message);
    }

    /**
     * This assertion is the exact opposite of assertTag().
     *
     * Rather than asserting that $matcher results in a match, it asserts that
     * $matcher does not match.
     *
     * @param  array   $matcher
     * @param  string  $actual
     * @param  string  $message
     * @param  boolean $isHtml
     * @since  Method available since Release 3.3.0
     * @author Mike Naberezny <mike@maintainable.com>
     * @author Derek DeVries <derek@maintainable.com>
     */
    public static function assertNotTag($matcher, $actual, $message = '', $isHtml = TRUE)
    {
        $dom     = PHPUnit_Util_XML::load($actual, $isHtml);
        $tags    = PHPUnit_Util_XML::findNodes($dom, $matcher, $isHtml);
        $matched = count($tags) > 0 && $tags[0] instanceof DOMNode;

        self::assertFalse($matched, $message);
    }

    /**
     * Evaluates a PHPUnit_Framework_Constraint matcher object.
     *
     * @param  mixed                        $value
     * @param  PHPUnit_Framework_Constraint $constraint
     * @param  string                       $message
     * @since  Method available since Release 3.0.0
     */
    public static function assertThat($value, PHPUnit_Framework_Constraint $constraint, $message = '')
    {
        self::$count += count($constraint);

        $constraint->evaluate($value, $message);
    }

    /**
     * Asserts that a string is a valid JSON string.
     *
     * @param  string $filename
     * @param  string $message
     * @since  Method available since Release 3.7.20
     */
    public static function assertJson($expectedJson, $message = '')
    {
        if (!is_string($expectedJson)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        self::assertThat($expectedJson, self::isJson(), $message);
    }

    /**
     * Asserts that two given JSON encoded objects or arrays are equal.
     *
     * @param string $expectedJson
     * @param string $actualJson
     * @param string $message
     */
    public static function assertJsonStringEqualsJsonString($expectedJson, $actualJson, $message = '')
    {
        self::assertJson($expectedJson, $message);
        self::assertJson($actualJson, $message);

        $expected = json_decode($expectedJson);
        $actual   = json_decode($actualJson);

        self::assertEquals($expected, $actual, $message);
    }

    /**
     * Asserts that two given JSON encoded objects or arrays are not equal.
     *
     * @param string $expectedJson
     * @param string $actualJson
     * @param string $message
     */
    public static function assertJsonStringNotEqualsJsonString($expectedJson, $actualJson, $message = '')
    {
        self::assertJson($expectedJson, $message);
        self::assertJson($actualJson, $message);

        $expected = json_decode($expectedJson);
        $actual   = json_decode($actualJson);

        self::assertNotEquals($expected, $actual, $message);
    }

    /**
     * Asserts that the generated JSON encoded object and the content of the given file are equal.
     *
     * @param string $expectedFile
     * @param string $actualJson
     * @param string $message
     */
    public static function assertJsonStringEqualsJsonFile($expectedFile, $actualJson, $message = '')
    {
        self::assertFileExists($expectedFile, $message);
        $expectedJson = file_get_contents($expectedFile);

        self::assertJson($expectedJson, $message);
        self::assertJson($actualJson, $message);

        // call constraint
        $constraint = new PHPUnit_Framework_Constraint_JsonMatches(
          $expectedJson
        );

        self::assertThat($actualJson, $constraint, $message);
    }

    /**
     * Asserts that the generated JSON encoded object and the content of the given file are not equal.
     *
     * @param string $expectedFile
     * @param string $actualJson
     * @param string $message
     */
    public static function assertJsonStringNotEqualsJsonFile($expectedFile, $actualJson, $message = '')
    {
        self::assertFileExists($expectedFile, $message);
        $expectedJson = file_get_contents($expectedFile);

        self::assertJson($expectedJson, $message);
        self::assertJson($actualJson, $message);

        // call constraint
        $constraint = new PHPUnit_Framework_Constraint_JsonMatches(
          $expectedJson
        );

        self::assertThat($actualJson, new PHPUnit_Framework_Constraint_Not($constraint), $message);
    }

    /**
     * Asserts that two JSON files are not equal.
     *
     * @param  string $expectedFile
     * @param  string $actualFile
     * @param  string $message
     */
    public static function assertJsonFileNotEqualsJsonFile($expectedFile, $actualFile, $message = '')
    {
        self::assertFileExists($expectedFile, $message);
        self::assertFileExists($actualFile, $message);

        $actualJson = file_get_contents($actualFile);
        $expectedJson = file_get_contents($expectedFile);

        self::assertJson($expectedJson, $message);
        self::assertJson($actualJson, $message);

        // call constraint
        $constraintExpected = new PHPUnit_Framework_Constraint_JsonMatches(
          $expectedJson
        );

        $constraintActual = new PHPUnit_Framework_Constraint_JsonMatches($actualJson);

        self::assertThat($expectedJson, new PHPUnit_Framework_Constraint_Not($constraintActual), $message);
        self::assertThat($actualJson, new PHPUnit_Framework_Constraint_Not($constraintExpected), $message);
    }

    /**
     * Asserts that two JSON files are equal.
     *
     * @param  string $expectedFile
     * @param  string $actualFile
     * @param  string $message
     */
    public static function assertJsonFileEqualsJsonFile($expectedFile, $actualFile, $message = '')
    {
        self::assertFileExists($expectedFile, $message);
        self::assertFileExists($actualFile, $message);

        $actualJson = file_get_contents($actualFile);
        $expectedJson = file_get_contents($expectedFile);

        self::assertJson($expectedJson, $message);
        self::assertJson($actualJson, $message);

        // call constraint
        $constraintExpected = new PHPUnit_Framework_Constraint_JsonMatches(
          $expectedJson
        );

        $constraintActual = new PHPUnit_Framework_Constraint_JsonMatches($actualJson);

        self::assertThat($expectedJson, $constraintActual, $message);
        self::assertThat($actualJson, $constraintExpected, $message);
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_And matcher object.
     *
     * @return PHPUnit_Framework_Constraint_And
     * @since  Method available since Release 3.0.0
     */
    public static function logicalAnd()
    {
        $constraints = func_get_args();

        $constraint = new PHPUnit_Framework_Constraint_And;
        $constraint->setConstraints($constraints);

        return $constraint;
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_Or matcher object.
     *
     * @return PHPUnit_Framework_Constraint_Or
     * @since  Method available since Release 3.0.0
     */
    public static function logicalOr()
    {
        $constraints = func_get_args();

        $constraint = new PHPUnit_Framework_Constraint_Or;
        $constraint->setConstraints($constraints);

        return $constraint;
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_Not matcher object.
     *
     * @param  PHPUnit_Framework_Constraint $constraint
     * @return PHPUnit_Framework_Constraint_Not
     * @since  Method available since Release 3.0.0
     */
    public static function logicalNot(PHPUnit_Framework_Constraint $constraint)
    {
        return new PHPUnit_Framework_Constraint_Not($constraint);
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_Xor matcher object.
     *
     * @return PHPUnit_Framework_Constraint_Xor
     * @since  Method available since Release 3.0.0
     */
    public static function logicalXor()
    {
        $constraints = func_get_args();

        $constraint = new PHPUnit_Framework_Constraint_Xor;
        $constraint->setConstraints($constraints);

        return $constraint;
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_IsAnything matcher object.
     *
     * @return PHPUnit_Framework_Constraint_IsAnything
     * @since  Method available since Release 3.0.0
     */
    public static function anything()
    {
        return new PHPUnit_Framework_Constraint_IsAnything;
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_IsTrue matcher object.
     *
     * @return PHPUnit_Framework_Constraint_IsTrue
     * @since  Method available since Release 3.3.0
     */
    public static function isTrue()
    {
        return new PHPUnit_Framework_Constraint_IsTrue;
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_Callback matcher object.
     *
     * @param callable $callback
     * @return PHPUnit_Framework_Constraint_Callback
     */
    public static function callback($callback)
    {
        return new PHPUnit_Framework_Constraint_Callback($callback);
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_IsFalse matcher object.
     *
     * @return PHPUnit_Framework_Constraint_IsFalse
     * @since  Method available since Release 3.3.0
     */
    public static function isFalse()
    {
        return new PHPUnit_Framework_Constraint_IsFalse;
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_IsJson matcher object.
     *
     * @return PHPUnit_Framework_Constraint_IsJson
     * @since  Method available since Release 3.7.20
     */
    public static function isJson()
    {
        return new PHPUnit_Framework_Constraint_IsJson;
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_IsNull matcher object.
     *
     * @return PHPUnit_Framework_Constraint_IsNull
     * @since  Method available since Release 3.3.0
     */
    public static function isNull()
    {
        return new PHPUnit_Framework_Constraint_IsNull;
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_Attribute matcher object.
     *
     * @param  PHPUnit_Framework_Constraint $constraint
     * @param  string                       $attributeName
     * @return PHPUnit_Framework_Constraint_Attribute
     * @since  Method available since Release 3.1.0
     */
    public static function attribute(PHPUnit_Framework_Constraint $constraint, $attributeName)
    {
        return new PHPUnit_Framework_Constraint_Attribute(
          $constraint, $attributeName
        );
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_TraversableContains matcher
     * object.
     *
     * @param  mixed   $value
     * @param  boolean $checkForObjectIdentity
     * @return PHPUnit_Framework_Constraint_TraversableContains
     * @since  Method available since Release 3.0.0
     */
    public static function contains($value, $checkForObjectIdentity = TRUE)
    {
        return new PHPUnit_Framework_Constraint_TraversableContains($value, $checkForObjectIdentity);
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_TraversableContainsOnly matcher
     * object.
     *
     * @param  string $type
     * @return PHPUnit_Framework_Constraint_TraversableContainsOnly
     * @since  Method available since Release 3.1.4
     */
    public static function containsOnly($type)
    {
        return new PHPUnit_Framework_Constraint_TraversableContainsOnly($type);
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_TraversableContainsOnly matcher
     * object.
     *
     * @param string $classname
     * @return PHPUnit_Framework_Constraint_TraversableContainsOnly
     */
    public static function containsOnlyInstancesOf($classname)
    {
        return new PHPUnit_Framework_Constraint_TraversableContainsOnly($classname, FALSE);
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_ArrayHasKey matcher object.
     *
     * @param  mixed $key
     * @return PHPUnit_Framework_Constraint_ArrayHasKey
     * @since  Method available since Release 3.0.0
     */
    public static function arrayHasKey($key)
    {
        return new PHPUnit_Framework_Constraint_ArrayHasKey($key);
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_IsEqual matcher object.
     *
     * @param  mixed   $value
     * @param  float   $delta
     * @param  integer $maxDepth
     * @param  boolean $canonicalize
     * @param  boolean $ignoreCase
     * @return PHPUnit_Framework_Constraint_IsEqual
     * @since  Method available since Release 3.0.0
     */
    public static function equalTo($value, $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE)
    {
        return new PHPUnit_Framework_Constraint_IsEqual(
          $value, $delta, $maxDepth, $canonicalize, $ignoreCase
        );
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_IsEqual matcher object
     * that is wrapped in a PHPUnit_Framework_Constraint_Attribute matcher
     * object.
     *
     * @param  string  $attributeName
     * @param  mixed   $value
     * @param  float   $delta
     * @param  integer $maxDepth
     * @param  boolean $canonicalize
     * @param  boolean $ignoreCase
     * @return PHPUnit_Framework_Constraint_Attribute
     * @since  Method available since Release 3.1.0
     */
    public static function attributeEqualTo($attributeName, $value, $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE)
    {
        return self::attribute(
          self::equalTo(
            $value, $delta, $maxDepth, $canonicalize, $ignoreCase
          ),
          $attributeName
        );
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_IsEmpty matcher object.
     *
     * @return PHPUnit_Framework_Constraint_IsEmpty
     * @since  Method available since Release 3.5.0
     */
    public static function isEmpty()
    {
        return new PHPUnit_Framework_Constraint_IsEmpty;
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_FileExists matcher object.
     *
     * @return PHPUnit_Framework_Constraint_FileExists
     * @since  Method available since Release 3.0.0
     */
    public static function fileExists()
    {
        return new PHPUnit_Framework_Constraint_FileExists;
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_GreaterThan matcher object.
     *
     * @param  mixed $value
     * @return PHPUnit_Framework_Constraint_GreaterThan
     * @since  Method available since Release 3.0.0
     */
    public static function greaterThan($value)
    {
        return new PHPUnit_Framework_Constraint_GreaterThan($value);
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_Or matcher object that wraps
     * a PHPUnit_Framework_Constraint_IsEqual and a
     * PHPUnit_Framework_Constraint_GreaterThan matcher object.
     *
     * @param  mixed $value
     * @return PHPUnit_Framework_Constraint_Or
     * @since  Method available since Release 3.1.0
     */
    public static function greaterThanOrEqual($value)
    {
        return self::logicalOr(
          new PHPUnit_Framework_Constraint_IsEqual($value),
          new PHPUnit_Framework_Constraint_GreaterThan($value)
        );
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_ClassHasAttribute matcher object.
     *
     * @param  string $attributeName
     * @return PHPUnit_Framework_Constraint_ClassHasAttribute
     * @since  Method available since Release 3.1.0
     */
    public static function classHasAttribute($attributeName)
    {
        return new PHPUnit_Framework_Constraint_ClassHasAttribute(
          $attributeName
        );
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_ClassHasStaticAttribute matcher
     * object.
     *
     * @param  string $attributeName
     * @return PHPUnit_Framework_Constraint_ClassHasStaticAttribute
     * @since  Method available since Release 3.1.0
     */
    public static function classHasStaticAttribute($attributeName)
    {
        return new PHPUnit_Framework_Constraint_ClassHasStaticAttribute(
          $attributeName
        );
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_ObjectHasAttribute matcher object.
     *
     * @param  string $attributeName
     * @return PHPUnit_Framework_Constraint_ObjectHasAttribute
     * @since  Method available since Release 3.0.0
     */
    public static function objectHasAttribute($attributeName)
    {
        return new PHPUnit_Framework_Constraint_ObjectHasAttribute(
          $attributeName
        );
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_IsIdentical matcher object.
     *
     * @param  mixed $value
     * @return PHPUnit_Framework_Constraint_IsIdentical
     * @since  Method available since Release 3.0.0
     */
    public static function identicalTo($value)
    {
        return new PHPUnit_Framework_Constraint_IsIdentical($value);
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_IsInstanceOf matcher object.
     *
     * @param  string $className
     * @return PHPUnit_Framework_Constraint_IsInstanceOf
     * @since  Method available since Release 3.0.0
     */
    public static function isInstanceOf($className)
    {
        return new PHPUnit_Framework_Constraint_IsInstanceOf($className);
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_IsType matcher object.
     *
     * @param  string $type
     * @return PHPUnit_Framework_Constraint_IsType
     * @since  Method available since Release 3.0.0
     */
    public static function isType($type)
    {
        return new PHPUnit_Framework_Constraint_IsType($type);
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_LessThan matcher object.
     *
     * @param  mixed $value
     * @return PHPUnit_Framework_Constraint_LessThan
     * @since  Method available since Release 3.0.0
     */
    public static function lessThan($value)
    {
        return new PHPUnit_Framework_Constraint_LessThan($value);
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_Or matcher object that wraps
     * a PHPUnit_Framework_Constraint_IsEqual and a
     * PHPUnit_Framework_Constraint_LessThan matcher object.
     *
     * @param  mixed $value
     * @return PHPUnit_Framework_Constraint_Or
     * @since  Method available since Release 3.1.0
     */
    public static function lessThanOrEqual($value)
    {
        return self::logicalOr(
          new PHPUnit_Framework_Constraint_IsEqual($value),
          new PHPUnit_Framework_Constraint_LessThan($value)
        );
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_PCREMatch matcher object.
     *
     * @param  string $pattern
     * @return PHPUnit_Framework_Constraint_PCREMatch
     * @since  Method available since Release 3.0.0
     */
    public static function matchesRegularExpression($pattern)
    {
        return new PHPUnit_Framework_Constraint_PCREMatch($pattern);
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_StringMatches matcher object.
     *
     * @param  string $string
     * @return PHPUnit_Framework_Constraint_StringMatches
     * @since  Method available since Release 3.5.0
     */
    public static function matches($string)
    {
        return new PHPUnit_Framework_Constraint_StringMatches($string);
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_StringStartsWith matcher object.
     *
     * @param  mixed $prefix
     * @return PHPUnit_Framework_Constraint_StringStartsWith
     * @since  Method available since Release 3.4.0
     */
    public static function stringStartsWith($prefix)
    {
        return new PHPUnit_Framework_Constraint_StringStartsWith($prefix);
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_StringContains matcher object.
     *
     * @param  string  $string
     * @param  boolean $case
     * @return PHPUnit_Framework_Constraint_StringContains
     * @since  Method available since Release 3.0.0
     */
    public static function stringContains($string, $case = TRUE)
    {
        return new PHPUnit_Framework_Constraint_StringContains($string, $case);
    }

    /**
     * Returns a PHPUnit_Framework_Constraint_StringEndsWith matcher object.
     *
     * @param  mixed $suffix
     * @return PHPUnit_Framework_Constraint_StringEndsWith
     * @since  Method available since Release 3.4.0
     */
    public static function stringEndsWith($suffix)
    {
        return new PHPUnit_Framework_Constraint_StringEndsWith($suffix);
    }

    /**
     * Fails a test with the given message.
     *
     * @param  string $message
     * @throws PHPUnit_Framework_AssertionFailedError
     */
    public static function fail($message = '')
    {
        throw new PHPUnit_Framework_AssertionFailedError($message);
    }

    /**
     * Returns the value of an attribute of a class or an object.
     * This also works for attributes that are declared protected or private.
     *
     * @param  mixed   $classOrObject
     * @param  string  $attributeName
     * @return mixed
     * @throws PHPUnit_Framework_Exception
     */
    public static function readAttribute($classOrObject, $attributeName)
    {
        if (!is_string($attributeName)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string');
        }

        if (is_string($classOrObject)) {
            if (!class_exists($classOrObject)) {
                throw PHPUnit_Util_InvalidArgumentHelper::factory(
                  1, 'class name'
                );
            }

            return PHPUnit_Util_Class::getStaticAttribute(
              $classOrObject,
              $attributeName
            );
        }

        else if (is_object($classOrObject)) {
            return PHPUnit_Util_Class::getObjectAttribute(
              $classOrObject,
              $attributeName
            );
        }

        else {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(
              1, 'class name or object'
            );
        }
    }

    /**
     * Mark the test as incomplete.
     *
     * @param  string  $message
     * @throws PHPUnit_Framework_IncompleteTestError
     * @since  Method available since Release 3.0.0
     */
    public static function markTestIncomplete($message = '')
    {
        throw new PHPUnit_Framework_IncompleteTestError($message);
    }

    /**
     * Mark the test as skipped.
     *
     * @param  string  $message
     * @throws PHPUnit_Framework_SkippedTestError
     * @since  Method available since Release 3.0.0
     */
    public static function markTestSkipped($message = '')
    {
        throw new PHPUnit_Framework_SkippedTestError($message);
    }

    /**
     * Return the current assertion count.
     *
     * @return integer
     * @since  Method available since Release 3.3.3
     */
    public static function getCount()
    {
        return self::$count;
    }

    /**
     * Reset the assertion counter.
     *
     * @since  Method available since Release 3.3.3
     */
    public static function resetCount()
    {
        self::$count = 0;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

/**
 * Exception for expectations which failed their check.
 *
 * The exception contains the error message and optionally a
 * PHPUnit_Framework_ComparisonFailure which is used to
 * generate diff output of the failed expectations.
 *
 * @package    PHPUnit
 * @subpackage Framework
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class PHPUnit_Framework_ExpectationFailedException extends PHPUnit_Framework_AssertionFailedError
{
    /**
     * @var PHPUnit_Framework_ComparisonFailure
     */
    protected $comparisonFailure;

    public function __construct($message, PHPUnit_Framework_ComparisonFailure $comparisonFailure = NULL, Exception $previous = NULL)
    {
        $this->comparisonFailure = $comparisonFailure;

        parent::__construct($message, 0, $previous);
    }

    /**
     * @return PHPUnit_Framework_ComparisonFailure
     */
    public function getComparisonFailure()
    {
        return $this->comparisonFailure;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.5.0
 */

if (defined('PHPUNIT_COMPOSER_INSTALL')) {
    return;
}

$paths = array(
  __DIR__ . '/../vendor',
  __DIR__ . '/../../..'
);

foreach ($paths as $path) {
    if (@is_dir($path . '/composer') &&
        @is_file($path . '/autoload.php')) {
        require_once $path . '/autoload.php';
        define('PHPUNIT_COMPOSER_INSTALL', $path . '/autoload.php');

        return;
    }
}

require_once 'File/Iterator/Autoload.php';
require_once 'PHP/CodeCoverage/Autoload.php';
require_once 'PHP/Timer/Autoload.php';
require_once 'PHPUnit/Framework/MockObject/Autoload.php';
require_once 'Text/Template/Autoload.php';

spl_autoload_register(
  function ($class)
  {
      static $classes = NULL;
      static $path    = NULL;

      if ($classes === NULL) {
          $classes = array(
            'phpunit_extensions_grouptestsuite' => '/Extensions/GroupTestSuite.php',
            'phpunit_extensions_phpttestcase' => '/Extensions/PhptTestCase.php',
            'phpunit_extensions_phpttestcase_logger' => '/Extensions/PhptTestCase/Logger.php',
            'phpunit_extensions_phpttestsuite' => '/Extensions/PhptTestSuite.php',
            'phpunit_extensions_repeatedtest' => '/Extensions/RepeatedTest.php',
            'phpunit_extensions_testdecorator' => '/Extensions/TestDecorator.php',
            'phpunit_extensions_ticketlistener' => '/Extensions/TicketListener.php',
            'phpunit_framework_assert' => '/Framework/Assert.php',
            'phpunit_framework_assertionfailederror' => '/Framework/AssertionFailedError.php',
            'phpunit_framework_comparator' => '/Framework/Comparator.php',
            'phpunit_framework_comparator_array' => '/Framework/Comparator/Array.php',
            'phpunit_framework_comparator_domdocument' => '/Framework/Comparator/DOMDocument.php',
            'phpunit_framework_comparator_double' => '/Framework/Comparator/Double.php',
            'phpunit_framework_comparator_exception' => '/Framework/Comparator/Exception.php',
            'phpunit_framework_comparator_mockobject' => '/Framework/Comparator/MockObject.php',
            'phpunit_framework_comparator_numeric' => '/Framework/Comparator/Numeric.php',
            'phpunit_framework_comparator_object' => '/Framework/Comparator/Object.php',
            'phpunit_framework_comparator_resource' => '/Framework/Comparator/Resource.php',
            'phpunit_framework_comparator_scalar' => '/Framework/Comparator/Scalar.php',
            'phpunit_framework_comparator_splobjectstorage' => '/Framework/Comparator/SplObjectStorage.php',
            'phpunit_framework_comparator_type' => '/Framework/Comparator/Type.php',
            'phpunit_framework_comparatorfactory' => '/Framework/ComparatorFactory.php',
            'phpunit_framework_comparisonfailure' => '/Framework/ComparisonFailure.php',
            'phpunit_framework_constraint' => '/Framework/Constraint.php',
            'phpunit_framework_constraint_and' => '/Framework/Constraint/And.php',
            'phpunit_framework_constraint_arrayhaskey' => '/Framework/Constraint/ArrayHasKey.php',
            'phpunit_framework_constraint_attribute' => '/Framework/Constraint/Attribute.php',
            'phpunit_framework_constraint_callback' => '/Framework/Constraint/Callback.php',
            'phpunit_framework_constraint_classhasattribute' => '/Framework/Constraint/ClassHasAttribute.php',
            'phpunit_framework_constraint_classhasstaticattribute' => '/Framework/Constraint/ClassHasStaticAttribute.php',
            'phpunit_framework_constraint_composite' => '/Framework/Constraint/Composite.php',
            'phpunit_framework_constraint_count' => '/Framework/Constraint/Count.php',
            'phpunit_framework_constraint_exception' => '/Framework/Constraint/Exception.php',
            'phpunit_framework_constraint_exceptioncode' => '/Framework/Constraint/ExceptionCode.php',
            'phpunit_framework_constraint_exceptionmessage' => '/Framework/Constraint/ExceptionMessage.php',
            'phpunit_framework_constraint_fileexists' => '/Framework/Constraint/FileExists.php',
            'phpunit_framework_constraint_greaterthan' => '/Framework/Constraint/GreaterThan.php',
            'phpunit_framework_constraint_isanything' => '/Framework/Constraint/IsAnything.php',
            'phpunit_framework_constraint_isempty' => '/Framework/Constraint/IsEmpty.php',
            'phpunit_framework_constraint_isequal' => '/Framework/Constraint/IsEqual.php',
            'phpunit_framework_constraint_isfalse' => '/Framework/Constraint/IsFalse.php',
            'phpunit_framework_constraint_isidentical' => '/Framework/Constraint/IsIdentical.php',
            'phpunit_framework_constraint_isinstanceof' => '/Framework/Constraint/IsInstanceOf.php',
            'phpunit_framework_constraint_isjson' => '/Framework/Constraint/IsJson.php',
            'phpunit_framework_constraint_isnull' => '/Framework/Constraint/IsNull.php',
            'phpunit_framework_constraint_istrue' => '/Framework/Constraint/IsTrue.php',
            'phpunit_framework_constraint_istype' => '/Framework/Constraint/IsType.php',
            'phpunit_framework_constraint_jsonmatches' => '/Framework/Constraint/JsonMatches.php',
            'phpunit_framework_constraint_jsonmatches_errormessageprovider' => '/Framework/Constraint/JsonMatches/ErrorMessageProvider.php',
            'phpunit_framework_constraint_lessthan' => '/Framework/Constraint/LessThan.php',
            'phpunit_framework_constraint_not' => '/Framework/Constraint/Not.php',
            'phpunit_framework_constraint_objecthasattribute' => '/Framework/Constraint/ObjectHasAttribute.php',
            'phpunit_framework_constraint_or' => '/Framework/Constraint/Or.php',
            'phpunit_framework_constraint_pcrematch' => '/Framework/Constraint/PCREMatch.php',
            'phpunit_framework_constraint_samesize' => '/Framework/Constraint/SameSize.php',
            'phpunit_framework_constraint_stringcontains' => '/Framework/Constraint/StringContains.php',
            'phpunit_framework_constraint_stringendswith' => '/Framework/Constraint/StringEndsWith.php',
            'phpunit_framework_constraint_stringmatches' => '/Framework/Constraint/StringMatches.php',
            'phpunit_framework_constraint_stringstartswith' => '/Framework/Constraint/StringStartsWith.php',
            'phpunit_framework_constraint_traversablecontains' => '/Framework/Constraint/TraversableContains.php',
            'phpunit_framework_constraint_traversablecontainsonly' => '/Framework/Constraint/TraversableContainsOnly.php',
            'phpunit_framework_constraint_xor' => '/Framework/Constraint/Xor.php',
            'phpunit_framework_error' => '/Framework/Error.php',
            'phpunit_framework_error_deprecated' => '/Framework/Error/Deprecated.php',
            'phpunit_framework_error_notice' => '/Framework/Error/Notice.php',
            'phpunit_framework_error_warning' => '/Framework/Error/Warning.php',
            'phpunit_framework_exception' => '/Framework/Exception.php',
            'phpunit_framework_expectationfailedexception' => '/Framework/ExpectationFailedException.php',
            'phpunit_framework_incompletetest' => '/Framework/IncompleteTest.php',
            'phpunit_framework_incompletetesterror' => '/Framework/IncompleteTestError.php',
            'phpunit_framework_outputerror' => '/Framework/OutputError.php',
            'phpunit_framework_selfdescribing' => '/Framework/SelfDescribing.php',
            'phpunit_framework_skippedtest' => '/Framework/SkippedTest.php',
            'phpunit_framework_skippedtesterror' => '/Framework/SkippedTestError.php',
            'phpunit_framework_skippedtestsuiteerror' => '/Framework/SkippedTestSuiteError.php',
            'phpunit_framework_syntheticerror' => '/Framework/SyntheticError.php',
            'phpunit_framework_test' => '/Framework/Test.php',
            'phpunit_framework_testcase' => '/Framework/TestCase.php',
            'phpunit_framework_testfailure' => '/Framework/TestFailure.php',
            'phpunit_framework_testlistener' => '/Framework/TestListener.php',
            'phpunit_framework_testresult' => '/Framework/TestResult.php',
            'phpunit_framework_testsuite' => '/Framework/TestSuite.php',
            'phpunit_framework_testsuite_dataprovider' => '/Framework/TestSuite/DataProvider.php',
            'phpunit_framework_warning' => '/Framework/Warning.php',
            'phpunit_runner_basetestrunner' => '/Runner/BaseTestRunner.php',
            'phpunit_runner_standardtestsuiteloader' => '/Runner/StandardTestSuiteLoader.php',
            'phpunit_runner_testsuiteloader' => '/Runner/TestSuiteLoader.php',
            'phpunit_runner_version' => '/Runner/Version.php',
            'phpunit_textui_command' => '/TextUI/Command.php',
            'phpunit_textui_resultprinter' => '/TextUI/ResultPrinter.php',
            'phpunit_textui_testrunner' => '/TextUI/TestRunner.php',
            'phpunit_util_class' => '/Util/Class.php',
            'phpunit_util_configuration' => '/Util/Configuration.php',
            'phpunit_util_deprecatedfeature' => '/Util/DeprecatedFeature.php',
            'phpunit_util_deprecatedfeature_logger' => '/Util/DeprecatedFeature/Logger.php',
            'phpunit_util_diff' => '/Util/Diff.php',
            'phpunit_util_errorhandler' => '/Util/ErrorHandler.php',
            'phpunit_util_fileloader' => '/Util/Fileloader.php',
            'phpunit_util_filesystem' => '/Util/Filesystem.php',
            'phpunit_util_filter' => '/Util/Filter.php',
            'phpunit_util_getopt' => '/Util/Getopt.php',
            'phpunit_util_globalstate' => '/Util/GlobalState.php',
            'phpunit_util_invalidargumenthelper' => '/Util/InvalidArgumentHelper.php',
            'phpunit_util_log_json' => '/Util/Log/JSON.php',
            'phpunit_util_log_junit' => '/Util/Log/JUnit.php',
            'phpunit_util_log_tap' => '/Util/Log/TAP.php',
            'phpunit_util_php' => '/Util/PHP.php',
            'phpunit_util_php_default' => '/Util/PHP/Default.php',
            'phpunit_util_php_windows' => '/Util/PHP/Windows.php',
            'phpunit_util_printer' => '/Util/Printer.php',
            'phpunit_util_string' => '/Util/String.php',
            'phpunit_util_test' => '/Util/Test.php',
            'phpunit_util_testdox_nameprettifier' => '/Util/TestDox/NamePrettifier.php',
            'phpunit_util_testdox_resultprinter' => '/Util/TestDox/ResultPrinter.php',
            'phpunit_util_testdox_resultprinter_html' => '/Util/TestDox/ResultPrinter/HTML.php',
            'phpunit_util_testdox_resultprinter_text' => '/Util/TestDox/ResultPrinter/Text.php',
            'phpunit_util_testsuiteiterator' => '/Util/TestSuiteIterator.php',
            'phpunit_util_type' => '/Util/Type.php',
            'phpunit_util_xml' => '/Util/XML.php'
          );

          $path = dirname(__FILE__);
      }

      $cn = strtolower($class);

      if (isset($classes[$cn])) {
          require $path . $classes[$cn];
      }
  }
);

// Symfony Yaml autoloader
spl_autoload_register(
  function ($class) {
      if (0 === strpos(ltrim($class, '/'), 'Symfony\Component\Yaml')) {
          $file = sprintf(
            'Symfony/Component/Yaml%s.php',

            substr(
              str_replace('\\', '/', $class),
              strlen('Symfony\Component\Yaml')
            )
          );

          if (stream_resolve_include_path($file)) {
              require_once $file;
          }
      }
  }
);

if (stream_resolve_include_path('PHP/Invoker/Autoload.php')) {
    require_once 'PHP/Invoker/Autoload.php';
}

if (stream_resolve_include_path('PHPUnit/Extensions/Database/Autoload.php')) {
    require_once 'PHPUnit/Extensions/Database/Autoload.php';
}

if (stream_resolve_include_path('PHPUnit/Extensions/SeleniumCommon/Autoload.php')) {
    require_once 'PHPUnit/Extensions/SeleniumCommon/Autoload.php';
}

else if (stream_resolve_include_path('PHPUnit/Extensions/SeleniumTestCase/Autoload.php')) {
    require_once 'PHPUnit/Extensions/SeleniumTestCase/Autoload.php';
}

if (stream_resolve_include_path('PHPUnit/Extensions/Story/Autoload.php')) {
    require_once 'PHPUnit/Extensions/Story/Autoload.php';
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.5.0
 */

if (defined('PHPUNIT_COMPOSER_INSTALL')) {
    return;
}

$paths = array(
  __DIR__ . '/../vendor',
  __DIR__ . '/../../..'
);

foreach ($paths as $path) {
    if (@is_dir($path . '/composer') &&
        @is_file($path . '/autoload.php')) {
        require_once $path . '/autoload.php';
        define('PHPUNIT_COMPOSER_INSTALL', $path . '/autoload.php');

        return;
    }
}

require_once 'File/Iterator/Autoload.php';
require_once 'PHP/CodeCoverage/Autoload.php';
require_once 'PHP/Timer/Autoload.php';
require_once 'PHPUnit/Framework/MockObject/Autoload.php';
require_once 'Text/Template/Autoload.php';

spl_autoload_register(
  function ($class)
  {
      static $classes = NULL;
      static $path    = NULL;

      if ($classes === NULL) {
          $classes = array(
            ___CLASSLIST___
          );

          $path = dirname(__FILE__);
      }

      $cn = strtolower($class);

      if (isset($classes[$cn])) {
          require $path . $classes[$cn];
      }
  }
);

// Symfony Yaml autoloader
spl_autoload_register(
  function ($class) {
      if (0 === strpos(ltrim($class, '/'), 'Symfony\Component\Yaml')) {
          $file = sprintf(
            'Symfony/Component/Yaml%s.php',

            substr(
              str_replace('\\', '/', $class),
              strlen('Symfony\Component\Yaml')
            )
          );

          if (stream_resolve_include_path($file)) {
              require_once $file;
          }
      }
  }
);

if (stream_resolve_include_path('PHP/Invoker/Autoload.php')) {
    require_once 'PHP/Invoker/Autoload.php';
}

if (stream_resolve_include_path('PHPUnit/Extensions/Database/Autoload.php')) {
    require_once 'PHPUnit/Extensions/Database/Autoload.php';
}

if (stream_resolve_include_path('PHPUnit/Extensions/SeleniumCommon/Autoload.php')) {
    require_once 'PHPUnit/Extensions/SeleniumCommon/Autoload.php';
}

else if (stream_resolve_include_path('PHPUnit/Extensions/SeleniumTestCase/Autoload.php')) {
    require_once 'PHPUnit/Extensions/SeleniumTestCase/Autoload.php';
}

if (stream_resolve_include_path('PHPUnit/Extensions/Story/Autoload.php')) {
    require_once 'PHPUnit/Extensions/Story/Autoload.php';
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Runner
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

/**
 * An interface to define how a test suite should be loaded.
 *
 * @package    PHPUnit
 * @subpackage Runner
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Interface available since Release 2.0.0
 */
interface PHPUnit_Runner_TestSuiteLoader
{
    /**
     * @param  string  $suiteClassName
     * @param  string  $suiteClassFile
     * @return ReflectionClass
     */
    public function load($suiteClassName, $suiteClassFile = '');

    /**
     * @param  ReflectionClass $aClass
     * @return ReflectionClass
     */
    public function reload(ReflectionClass $aClass);
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Runner
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

/**
 * This class defines the current version of PHPUnit.
 *
 * @package    PHPUnit
 * @subpackage Runner
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.0.0
 */
class PHPUnit_Runner_Version
{
    const VERSION = '3.7.28';
    protected static $version;

    /**
     * Returns the current version of PHPUnit.
     *
     * @return string
     */
    public static function id()
    {
        if (self::$version === NULL) {
            self::$version = self::VERSION;

            if (is_dir(dirname(dirname(__DIR__)) . '/.git')) {
                $dir = getcwd();
                chdir(__DIR__);
                $version = exec('git describe --tags 2>&1', $output, $returnCode);
                chdir($dir);

                if ($version && $returnCode === 0) {
                    if (count(explode('.', self::VERSION)) == 3) {
                        self::$version = $version;
                    } else {
                        $version = explode('-', $version);

                        self::$version = self::VERSION . '-' . $version[2];
                    }
                } else {
                    self::$version = self::VERSION . '-dev';
                }
            }
        }

        return self::$version;
    }

    /**
     * @return string
     */
    public static function getVersionString()
    {
        return 'PHPUnit ' . self::id() . ' by Sebastian Bergmann.';
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Runner
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

/**
 * The standard test suite loader.
 *
 * @package    PHPUnit
 * @subpackage Runner
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.0.0
 */
class PHPUnit_Runner_StandardTestSuiteLoader implements PHPUnit_Runner_TestSuiteLoader
{
    /**
     * @param  string  $suiteClassName
     * @param  string  $suiteClassFile
     * @return ReflectionClass
     * @throws PHPUnit_Framework_Exception
     */
    public function load($suiteClassName, $suiteClassFile = '')
    {
        $suiteClassName = str_replace('.php', '', $suiteClassName);

        if (empty($suiteClassFile)) {
            $suiteClassFile = PHPUnit_Util_Filesystem::classNameToFilename(
              $suiteClassName
            );
        }

        if (!class_exists($suiteClassName, FALSE)) {
            PHPUnit_Util_Class::collectStart();
            $filename = PHPUnit_Util_Fileloader::checkAndLoad($suiteClassFile);
            $loadedClasses = PHPUnit_Util_Class::collectEnd();
        }

        if (!class_exists($suiteClassName, FALSE) && !empty($loadedClasses)) {
            $offset = 0 - strlen($suiteClassName);

            foreach ($loadedClasses as $loadedClass) {
                $class = new ReflectionClass($loadedClass);
                if (substr($loadedClass, $offset) === $suiteClassName &&
                    $class->getFileName() == $filename) {
                    $suiteClassName = $loadedClass;
                    break;
                }
            }
        }

        if (!class_exists($suiteClassName, FALSE) && !empty($loadedClasses)) {
            $testCaseClass = 'PHPUnit_Framework_TestCase';

            foreach ($loadedClasses as $loadedClass) {
                $class     = new ReflectionClass($loadedClass);
                $classFile = $class->getFileName();

                if ($class->isSubclassOf($testCaseClass) &&
                    !$class->isAbstract()) {
                    $suiteClassName = $loadedClass;
                    $testCaseClass  = $loadedClass;

                    if ($classFile == realpath($suiteClassFile)) {
                        break;
                    }
                }

                if ($class->hasMethod('suite')) {
                    $method = $class->getMethod('suite');

                    if (!$method->isAbstract() &&
                        $method->isPublic() &&
                        $method->isStatic()) {
                        $suiteClassName = $loadedClass;

                        if ($classFile == realpath($suiteClassFile)) {
                            break;
                        }
                    }
                }
            }
        }

        if (class_exists($suiteClassName, FALSE)) {
            $class = new ReflectionClass($suiteClassName);

            if ($class->getFileName() == realpath($suiteClassFile)) {
                return $class;
            }
        }

        throw new PHPUnit_Framework_Exception(
          sprintf(
            "Class '%s' could not be found in '%s'.",

            $suiteClassName,
            $suiteClassFile
          )
        );
    }

    /**
     * @param  ReflectionClass  $aClass
     * @return ReflectionClass
     */
    public function reload(ReflectionClass $aClass)
    {
        return $aClass;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @subpackage Runner
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

/**
 * Base class for all test runners.
 *
 * @package    PHPUnit
 * @subpackage Runner
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.0.0
 */
abstract class PHPUnit_Runner_BaseTestRunner
{
    const STATUS_PASSED     = 0;
    const STATUS_SKIPPED    = 1;
    const STATUS_INCOMPLETE = 2;
    const STATUS_FAILURE    = 3;
    const STATUS_ERROR      = 4;
    const SUITE_METHODNAME  = 'suite';

    /**
     * Returns the loader to be used.
     *
     * @return PHPUnit_Runner_TestSuiteLoader
     */
    public function getLoader()
    {
        return new PHPUnit_Runner_StandardTestSuiteLoader;
    }

    /**
     * Returns the Test corresponding to the given suite.
     * This is a template method, subclasses override
     * the runFailed() and clearStatus() methods.
     *
     * @param  string  $suiteClassName
     * @param  string  $suiteClassFile
     * @param  mixed   $suffixes
     * @return PHPUnit_Framework_Test
     */
    public function getTest($suiteClassName, $suiteClassFile = '', $suffixes = '')
    {
        if (is_dir($suiteClassName) &&
            !is_file($suiteClassName . '.php') && empty($suiteClassFile)) {
            $facade = new File_Iterator_Facade;
            $files  = $facade->getFilesAsArray(
              $suiteClassName, $suffixes
            );

            $suite = new PHPUnit_Framework_TestSuite($suiteClassName);
            $suite->addTestFiles($files);

            return $suite;
        }

        try {
            $testClass = $this->loadSuiteClass(
              $suiteClassName, $suiteClassFile
            );
        }

        catch (Exception $e) {
            $this->runFailed($e->getMessage());
            return NULL;
        }

        try {
            $suiteMethod = $testClass->getMethod(self::SUITE_METHODNAME);

            if (!$suiteMethod->isStatic()) {
                $this->runFailed(
                  'suite() method must be static.'
                );

                return NULL;
            }

            try {
                $test = $suiteMethod->invoke(NULL, $testClass->getName());
            }

            catch (ReflectionException $e) {
                $this->runFailed(
                  sprintf(
                    "Failed to invoke suite() method.\n%s",

                    $e->getMessage()
                  )
                );

                return NULL;
            }
        }

        catch (ReflectionException $e) {
            try {
                $test = new PHPUnit_Framework_TestSuite($testClass);
            }

            catch (PHPUnit_Framework_Exception $e) {
                $test = new PHPUnit_Framework_TestSuite;
                $test->setName($suiteClassName);
            }
        }

        $this->clearStatus();

        return $test;
    }

    /**
     * Returns the loaded ReflectionClass for a suite name.
     *
     * @param  string  $suiteClassName
     * @param  string  $suiteClassFile
     * @return ReflectionClass
     */
    protected function loadSuiteClass($suiteClassName, $suiteClassFile = '')
    {
        $loader = $this->getLoader();

        if ($loader instanceof PHPUnit_Runner_StandardTestSuiteLoader) {
            return $loader->load($suiteClassName, $suiteClassFile);
        } else {
            return $loader->load($suiteClassName, $suiteClassFile);
        }
    }

    /**
     * Clears the status message.
     *
     */
    protected function clearStatus()
    {
    }

    /**
     * Override to define how to handle a failed loading of
     * a test suite.
     *
     * @param  string  $message
     */
    abstract protected function runFailed($message);
}

<?php
/* PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

define('PHPUnit_MAIN_METHOD', 'PHPUnit_TextUI_Command::main');

if (strpos('@php_bin@', '@php_bin') === 0) {
    require dirname(__FILE__) . DIRECTORY_SEPARATOR . 'PHPUnit' . DIRECTORY_SEPARATOR . 'Autoload.php';
} else {
    require '@php_dir@' . DIRECTORY_SEPARATOR . 'PHPUnit' . DIRECTORY_SEPARATOR . 'Autoload.php';
}

PHPUnit_TextUI_Command::main();
<?xml version="1.0" encoding="UTF-8"?>

<project name="PHPUnit" default="build">
 <property name="php" value="php"/>

 <target name="build"
   depends="prepare,lint,phploc,pdepend,phpmd-ci,phpcs-ci,phpcpd,phpunit,phpcb"/>

 <target name="build-parallel"
   depends="prepare,lint,tools-parallel,phpunit,phpcb"/>

 <target name="tools-parallel"
         description="Run tools in parallel">
  <parallel threadCount="2">
   <sequential>
    <antcall target="pdepend"/>
    <antcall target="phpmd-ci"/>
   </sequential>
   <antcall target="phpcpd"/>
   <antcall target="phpcs-ci"/>
   <antcall target="phploc"/>
  </parallel>
 </target>

 <target name="clean" description="Cleanup build artifacts">
  <delete dir="${basedir}/bin"/>
  <delete dir="${basedir}/vendor"/>
  <delete file="${basedir}/composer.lock"/>
  <delete file="${basedir}/composer.phar"/>
  <delete dir="${basedir}/build/api"/>
  <delete dir="${basedir}/build/code-browser"/>
  <delete dir="${basedir}/build/coverage"/>
  <delete dir="${basedir}/build/logs"/>
  <delete dir="${basedir}/build/pdepend"/>
  <delete dir="${basedir}/build/phar"/>

  <delete>
   <fileset dir="${basedir}/build">
    <include name="**/*.phar" />
   </fileset>
  </delete>
 </target>

 <target name="prepare" depends="clean,phpab"
         description="Prepare for build">
  <mkdir dir="${basedir}/build/api"/>
  <mkdir dir="${basedir}/build/code-browser"/>
  <mkdir dir="${basedir}/build/coverage"/>
  <mkdir dir="${basedir}/build/logs"/>
  <mkdir dir="${basedir}/build/pdepend"/>
  <mkdir dir="${basedir}/build/phpdox"/>
 </target>

 <target name="phpab" description="Generate autoloader scripts">
  <exec executable="phpab">
   <arg value="--output" />
   <arg path="PHPUnit/Autoload.php" />
   <arg value="--template" />
   <arg path="PHPUnit/Autoload.php.in" />
   <arg value="--indent" />
   <arg value="            " />
   <arg path="PHPUnit" />
  </exec>
 </target>

 <target name="lint">
  <apply executable="${php}" failonerror="true">
   <arg value="-l" />

   <fileset dir="${basedir}/PHPUnit">
    <include name="**/*.php" />
    <modified />
   </fileset>

   <fileset dir="${basedir}/Tests">
    <include name="**/*.php" />
    <modified />
   </fileset>
  </apply>
 </target>

 <target name="phploc" description="Measure project size using PHPLOC">
  <exec executable="phploc">
   <arg value="--log-csv" />
   <arg value="${basedir}/build/logs/phploc.csv" />
   <arg path="${basedir}/PHPUnit" />
  </exec>
 </target>

 <target name="pdepend"
         description="Calculate software metrics using PHP_Depend">
  <exec executable="pdepend">
   <arg value="--jdepend-xml=${basedir}/build/logs/jdepend.xml" />
   <arg value="--jdepend-chart=${basedir}/build/pdepend/dependencies.svg" />
   <arg value="--overview-pyramid=${basedir}/build/pdepend/overview-pyramid.svg" />
   <arg path="${basedir}/PHPUnit" />
  </exec>
 </target>

 <target name="phpmd"
         description="Perform project mess detection using PHPMD">
  <exec executable="phpmd">
   <arg path="${basedir}/PHPUnit" />
   <arg value="text" />
   <arg value="${basedir}/build/phpmd.xml" />
  </exec>
 </target>

 <target name="phpmd-ci"
         description="Perform project mess detection using PHPMD">
  <exec executable="phpmd">
   <arg path="${basedir}/PHPUnit" />
   <arg value="xml" />
   <arg value="${basedir}/build/phpmd.xml" />
   <arg value="--reportfile" />
   <arg value="${basedir}/build/logs/pmd.xml" />
  </exec>
 </target>

 <target name="phpcs"
         description="Find coding standard violations using PHP_CodeSniffer">
  <exec executable="phpcs">
   <arg value="--standard=${basedir}/build/PHPCS" />
   <arg value="--extensions=php" />
   <arg value="--ignore=Autoload.php" />
   <arg path="${basedir}/PHPUnit" />
   <arg path="${basedir}/Tests" />
  </exec>
 </target>

 <target name="phpcs-ci"
         description="Find coding standard violations using PHP_CodeSniffer">
  <exec executable="phpcs" output="/dev/null">
   <arg value="--report=checkstyle" />
   <arg value="--report-file=${basedir}/build/logs/checkstyle.xml" />
   <arg value="--standard=${basedir}/build/PHPCS" />
   <arg value="--extensions=php" />
   <arg value="--ignore=Autoload.php" />
   <arg path="${basedir}/PHPUnit" />
   <arg path="${basedir}/Tests" />
  </exec>
 </target>

 <target name="phpcpd" description="Find duplicate code using PHPCPD">
  <exec executable="phpcpd">
   <arg value="--log-pmd" />
   <arg value="${basedir}/build/logs/pmd-cpd.xml" />
   <arg path="${basedir}/PHPUnit" />
  </exec>
 </target>

 <target name="phpunit" description="Run unit tests with PHPUnit">
  <exec executable="${php}" failonerror="true">
   <arg path="${basedir}/phpunit.php" />
  </exec>
 </target>

 <target name="phpcb"
         description="Aggregate tool output with PHP_CodeBrowser">
  <exec executable="phpcb">
   <arg value="--log" />
   <arg path="${basedir}/build/logs" />
   <arg value="--source" />
   <arg path="${basedir}/PHPUnit" />
   <arg value="--output" />
   <arg path="${basedir}/build/code-browser" />
  </exec>
 </target>

 <target name="phar"
         description="Create PHAR archive of PHPUnit and all its dependencies"
         depends="phar-prepare,phar-build">
 </target>

 <target name="phar-prepare" depends="clean">
  <mkdir dir="${basedir}/build/phar"/>

  <get src="https://getcomposer.org/composer.phar" dest="${basedir}/composer.phar"/>

  <exec executable="php">
   <arg value="composer.phar"/>
   <arg value="install"/>
  </exec>

  <copy file="${basedir}/composer.json" tofile="${basedir}/composer.json.bak"/>

  <exec executable="php">
   <arg value="composer.phar"/>
   <arg value="require"/>
   <arg value="phpunit/dbunit"/>
   <arg value="1.2.*"/>
  </exec>

  <exec executable="php">
   <arg value="composer.phar"/>
   <arg value="require"/>
   <arg value="phpunit/phpunit-selenium"/>
   <arg value="1.3.*"/>
  </exec>

  <exec executable="php">
   <arg value="composer.phar"/>
   <arg value="require"/>
   <arg value="phpunit/php-invoker"/>
   <arg value="1.1.*"/>
  </exec>

  <move file="${basedir}/composer.json.bak" tofile="${basedir}/composer.json"/>

  <copy todir="${basedir}/build/phar/php-code-coverage">
   <fileset dir="${basedir}/vendor/phpunit/php-code-coverage/PHP">
    <include name="**/*" />
    <exclude name="**/Autoload.*" />
   </fileset>
  </copy>

  <copy todir="${basedir}/build/phar/php-file-iterator">
   <fileset dir="${basedir}/vendor/phpunit/php-file-iterator/File">
    <include name="**/*.php" />
    <exclude name="**/Autoload.*" />
   </fileset>
  </copy>

  <copy todir="${basedir}/build/phar/php-text-template">
   <fileset dir="${basedir}/vendor/phpunit/php-text-template/Text">
    <include name="**/*.php" />
    <exclude name="**/Autoload.*" />
   </fileset>
  </copy>

  <copy todir="${basedir}/build/phar/php-timer">
   <fileset dir="${basedir}/vendor/phpunit/php-timer/PHP">
    <include name="**/*.php" />
    <exclude name="**/Autoload.*" />
   </fileset>
  </copy>

  <copy todir="${basedir}/build/phar/php-token-stream">
   <fileset dir="${basedir}/vendor/phpunit/php-token-stream/PHP">
    <include name="**/*.php" />
    <exclude name="**/Autoload.*" />
   </fileset>
  </copy>

  <copy todir="${basedir}/build/phar/phpunit-mock-objects">
   <fileset dir="${basedir}/vendor/phpunit/phpunit-mock-objects/PHPUnit">
    <include name="**/*" />
    <exclude name="**/Autoload.*" />
   </fileset>
  </copy>

  <copy todir="${basedir}/build/phar/symfony">
   <fileset dir="${basedir}/vendor/symfony">
    <include name="**/*.php" />
    <exclude name="**/Tests/**" />
   </fileset>
  </copy>

  <copy todir="${basedir}/build/phar/pear">
   <fileset dir="${basedir}/vendor/pear-pear.php.net">
    <include name="**/*.php" />
   </fileset>
  </copy>

  <copy todir="${basedir}/build/phar/dbunit">
   <fileset dir="${basedir}/vendor/phpunit/dbunit/PHPUnit">
    <include name="**/*.php" />
    <exclude name="**/Autoload.*" />
   </fileset>
  </copy>

  <copy todir="${basedir}/build/phar/php-invoker">
   <fileset dir="${basedir}/vendor/phpunit/php-invoker/PHP">
    <include name="**/*.php" />
    <exclude name="**/Autoload.*" />
   </fileset>
  </copy>

  <copy todir="${basedir}/build/phar/phpunit-selenium">
   <fileset dir="${basedir}/vendor/phpunit/phpunit-selenium/PHPUnit">
    <include name="**/*.php" />
    <exclude name="**/Autoload.*" />
   </fileset>
  </copy>
 </target>

 <target name="phar-build">
  <exec executable="bash" outputproperty="version">
   <arg value="-c" />
   <arg value="${basedir}/phpunit.php --version | awk 'BEGIN { ORS = &quot;&quot;; } {print $2}'" />
  </exec>

  <copy todir="${basedir}/build/phar/phpunit">
   <fileset dir="${basedir}/PHPUnit">
    <include name="**/*.php" />
    <include name="**/*.tpl*" />
    <exclude name="**/Autoload.*" />
   </fileset>
  </copy>

  <exec executable="phpab">
   <arg value="--all" />
   <arg value="--phar" />
   <arg value="--output" />
   <arg path="${basedir}/build/phpunit-${version}.phar" />
   <arg value="--template" />
   <arg path="${basedir}/build/phar-autoload.php.in" />
   <arg value="--indent" />
   <arg value="            " />
   <arg path="${basedir}/build/phar" />
  </exec>

  <chmod file="${basedir}/build/phpunit-${version}.phar" perm="ugo+rx"/>
 </target>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/3.7/phpunit.xsd"
         bootstrap="PHPUnit/Autoload.php"
         backupGlobals="false"
         verbose="true">
  <testsuites>
    <testsuite name="PHPUnit">
      <directory suffix="Test.php">Tests/Framework</directory>
      <directory suffix=".phpt">Tests/Framework/MockObject</directory>
      <directory suffix="Test.php">Tests/Extensions</directory>
      <directory suffix=".phpt">Tests/Regression</directory>
      <directory suffix="Test.php">Tests/Runner</directory>
      <directory suffix=".phpt">Tests/TextUI</directory>
      <directory suffix="Test.php">Tests/Util</directory>
    </testsuite>
  </testsuites>

  <logging>
    <log type="coverage-html" target="build/coverage" title="PHPUnit"
         charset="UTF-8" yui="true" highlight="true"
         lowUpperBound="35" highLowerBound="70"/>
    <log type="coverage-clover" target="build/logs/clover.xml"/>
    <log type="junit" target="build/logs/junit.xml" logIncompleteSkipped="false"/>
  </logging>

  <filter>
    <whitelist processUncoveredFilesFromWhitelist="true">
      <directory suffix=".php">PHPUnit</directory>
      <exclude>
       <file>PHPUnit/Autoload.php</file>
       <file>PHPUnit/Framework/Assert/Functions.php</file>
      </exclude>
    </whitelist>
  </filter>

  <php>
    <const name="PHPUNIT_TESTSUITE" value="true"/>
  </php>
</phpunit>

<?php
/* PHPUnit
 *
 * Copyright (c) 2001-2012, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

define('PHPUnit_MAIN_METHOD', 'PHPUnit_TextUI_Command::main');

$files = array(
  __DIR__ . '/../../vendor/autoload.php',
  __DIR__ . '/../../../../autoload.php'
);

foreach ($files as $file) {
    if (file_exists($file)) {
        require $file;

        define('PHPUNIT_COMPOSER_INSTALL', $file);

        break;
    }
}

if (!defined('PHPUNIT_COMPOSER_INSTALL')) {
    die(
      'You need to set up the project dependencies using the following commands:' . PHP_EOL .
      'curl -s http://getcomposer.org/installer | php' . PHP_EOL .
      'php composer.phar install' . PHP_EOL
    );
}

PHPUnit_TextUI_Command::main();
<?xml version="1.0" encoding="utf-8" ?>

<phpdox xmlns="http://phpdox.de/config">
 <project name="PHPUnit" source="PHPUnit" workdir="build/phpdox">
  <collector publiconly="false">
   <include mask="*.php" />
   <exclude mask="*Autoload.php" />
  </collector>

  <generator output="build">
   <build engine="html" enabled="true" output="api">
    <file extension="html" />
   </build>
  </generator>
 </project>
</phpdox>
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'Success.php';

/**
 *
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.0.0
 */
class Extensions_RepeatedTestTest extends PHPUnit_Framework_TestCase
{
    protected $suite;

    public function __construct()
    {
        $this->suite = new PHPUnit_Framework_TestSuite;

        $this->suite->addTest(new Success);
        $this->suite->addTest(new Success);
    }

    public function testRepeatedOnce()
    {
        $test = new PHPUnit_Extensions_RepeatedTest($this->suite, 1);
        $this->assertEquals(2, count($test));

        $result = $test->run();
        $this->assertEquals(2, count($result));
    }

    public function testRepeatedMoreThanOnce()
    {
        $test = new PHPUnit_Extensions_RepeatedTest($this->suite, 3);
        $this->assertEquals(6, count($test));

        $result = $test->run();
        $this->assertEquals(6, count($result));
    }

    public function testRepeatedZero()
    {
        $test = new PHPUnit_Extensions_RepeatedTest($this->suite, 0);
        $this->assertEquals(0, count($test));

        $result = $test->run();
        $this->assertEquals(0, count($result));
    }

    public function testRepeatedNegative()
    {
        try {
            $test = new PHPUnit_Extensions_RepeatedTest($this->suite, -1);
        }

        catch (Exception $e) {
            return;
        }

        $this->fail('Should throw an Exception');
    }
}
--TEST--
phpunit --process-isolation --exclude-group balanceIsInitiallyZero BankAccountTest ../_files/BankAccountTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--process-isolation';
$_SERVER['argv'][3] = '--exclude-group';
$_SERVER['argv'][4] = 'balanceIsInitiallyZero';
$_SERVER['argv'][5] = 'BankAccountTest';
$_SERVER['argv'][6] = dirname(__FILE__).'/../_files/BankAccountTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

..

Time: %s, Memory: %sMb

OK (2 tests, 2 assertions)
--TEST--
phpunit --filter BankAccountTest BankAccountTest ../_files/BankAccountTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--filter';
$_SERVER['argv'][3] = 'BankAccountTest';
$_SERVER['argv'][4] = 'BankAccountTest';
$_SERVER['argv'][5] = dirname(__FILE__).'/../_files/BankAccountTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

...

Time: %s, Memory: %sMb

OK (3 tests, 3 assertions)
--TEST--
phpunit --tap BankAccountTest ../_files/BankAccountTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--tap';
$_SERVER['argv'][3] = 'BankAccountTest';
$_SERVER['argv'][4] = dirname(__FILE__).'/../_files/BankAccountTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
TAP version 13
ok 1 - BankAccountTest::testBalanceIsInitiallyZero
ok 2 - BankAccountTest::testBalanceCannotBecomeNegative
ok 3 - BankAccountTest::testBalanceCannotBecomeNegative2
1..3
--TEST--
phpunit FailureTest ../_files/FailureTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = 'FailureTest';
$_SERVER['argv'][3] = dirname(dirname(__FILE__)) . '/_files/FailureTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

FFFFFFFFFFFFF

Time: %s, Memory: %sMb

There were 13 failures:

1) FailureTest::testAssertArrayEqualsArray
message
Failed asserting that two arrays are equal.
--- Expected
+++ Actual
@@ @@
 Array (
-    0 => 1
+    0 => 2
 )

%s:%i

2) FailureTest::testAssertIntegerEqualsInteger
message
Failed asserting that 2 matches expected 1.

%s:%i

3) FailureTest::testAssertObjectEqualsObject
message
Failed asserting that two objects are equal.
--- Expected
+++ Actual
@@ @@
 stdClass Object (
-    'foo' => 'bar'
+    'bar' => 'foo'
 )

%s:%i

4) FailureTest::testAssertNullEqualsString
message
Failed asserting that 'bar' matches expected null.

%s:%i

5) FailureTest::testAssertStringEqualsString
message
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'foo'
+'bar'

%s:%i

6) FailureTest::testAssertTextEqualsText
message
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
 'foo
-bar
+baz
 '

%s:%i

7) FailureTest::testAssertStringMatchesFormat
message
Failed asserting that format description matches text.
--- Expected
+++ Actual
@@ @@
-*%s*
+**

%s:%i

8) FailureTest::testAssertNumericEqualsNumeric
message
Failed asserting that 2 matches expected 1.

%s:%i

9) FailureTest::testAssertTextSameText
message
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-foo
+bar

%s:%i

10) FailureTest::testAssertObjectSameObject
message
Failed asserting that two variables reference the same object.

%s:%i

11) FailureTest::testAssertObjectSameNull
message
Failed asserting that null is identical to an object of class "stdClass".

%s:%i

12) FailureTest::testAssertFloatSameFloat
message
Failed asserting that 1.5 is identical to 1.0.

%s:%i

13) FailureTest::testAssertStringMatchesFormatFile
Failed asserting that format description matches text.
--- Expected
+++ Actual
@@ @@
-FOO
-
+...BAR...

%s:%i

FAILURES!
Tests: 13, Assertions: 14, Failures: 13.

--TEST--
phpunit --process-isolation --filter BankAccountTest BankAccountTest ../_files/BankAccountTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--process-isolation';
$_SERVER['argv'][3] = '--filter';
$_SERVER['argv'][4] = 'BankAccountTest';
$_SERVER['argv'][5] = 'BankAccountTest';
$_SERVER['argv'][6] = dirname(__FILE__).'/../_files/BankAccountTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

...

Time: %s, Memory: %sMb

OK (3 tests, 3 assertions)
--TEST--
phpunit --process-isolation FailureTest ../_files/FailureTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--process-isolation';
$_SERVER['argv'][3] = 'FailureTest';
$_SERVER['argv'][4] = dirname(dirname(__FILE__)) . '/_files/FailureTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

FFFFFFFFFFFFF

Time: %s, Memory: %sMb

There were 13 failures:

1) FailureTest::testAssertArrayEqualsArray
message
Failed asserting that two arrays are equal.
--- Expected
+++ Actual
@@ @@
 Array (
-    0 => 1
+    0 => 2
 )

%s:%i

2) FailureTest::testAssertIntegerEqualsInteger
message
Failed asserting that 2 matches expected 1.

%s:%i

3) FailureTest::testAssertObjectEqualsObject
message
Failed asserting that two objects are equal.
--- Expected
+++ Actual
@@ @@
 stdClass Object (
-    'foo' => 'bar'
+    'bar' => 'foo'
 )

%s:%i

4) FailureTest::testAssertNullEqualsString
message
Failed asserting that 'bar' matches expected null.

%s:%i

5) FailureTest::testAssertStringEqualsString
message
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'foo'
+'bar'

%s:%i

6) FailureTest::testAssertTextEqualsText
message
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
 'foo
-bar
+baz
 '

%s:%i

7) FailureTest::testAssertStringMatchesFormat
message
Failed asserting that format description matches text.
--- Expected
+++ Actual
@@ @@
-*%s*
+**

%s:%i

8) FailureTest::testAssertNumericEqualsNumeric
message
Failed asserting that 2 matches expected 1.

%s:%i

9) FailureTest::testAssertTextSameText
message
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-foo
+bar

%s:%i

10) FailureTest::testAssertObjectSameObject
message
Failed asserting that two variables reference the same object.

%s:%i

11) FailureTest::testAssertObjectSameNull
message
Failed asserting that null is identical to an object of class "stdClass".

%s:%i

12) FailureTest::testAssertFloatSameFloat
message
Failed asserting that 1.5 is identical to 1.0.

%s:%i

13) FailureTest::testAssertStringMatchesFormatFile
Failed asserting that format description matches text.
--- Expected
+++ Actual
@@ @@
-FOO
-
+...BAR...

%s:%i

FAILURES!
Tests: 13, Assertions: 14, Failures: 13.
--TEST--
phpunit FatalTest ../_files/FatalTest.php
--FILE--
<?php

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--process-isolation';
$_SERVER['argv'][3] = 'FatalTest';
$_SERVER['argv'][4] = dirname(dirname(__FILE__)) . '/_files/FatalTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

E

Time: %s, Memory: %sMb

There was 1 error:

1) FatalTest::testFatalError
PHPUnit_Framework_Exception: %s error: Call to undefined function non_existing_function() in %s


FAILURES!
Tests: 1, Assertions: 0, Errors: 1.

--TEST--
phpunit
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

Usage: phpunit [switches] UnitTest [UnitTest.php]
       phpunit [switches] <directory>

  --log-junit <file>        Log test execution in JUnit XML format to file.
  --log-tap <file>          Log test execution in TAP format to file.
  --log-json <file>         Log test execution in JSON format.

  --coverage-clover <file>  Generate code coverage report in Clover XML format.
  --coverage-html <dir>     Generate code coverage report in HTML format.
  --coverage-php <file>     Serialize PHP_CodeCoverage object to file.
  --coverage-text=<file>    Generate code coverage report in text format.
                            Default to writing to the standard output.

  --testdox-html <file>     Write agile documentation in HTML format to file.
  --testdox-text <file>     Write agile documentation in Text format to file.

  --filter <pattern>        Filter which tests to run.
  --testsuite <pattern>     Filter which testsuite to run.
  --group ...               Only runs tests from the specified group(s).
  --exclude-group ...       Exclude tests from the specified group(s).
  --list-groups             List available test groups.
  --test-suffix ...         Only search for test in files with specified
                            suffix(es). Default: Test.php,.phpt

  --loader <loader>         TestSuiteLoader implementation to use.
  --printer <printer>       TestSuiteListener implementation to use.
  --repeat <times>          Runs the test(s) repeatedly.

  --tap                     Report test execution progress in TAP format.
  --testdox                 Report test execution progress in TestDox format.

  --colors                  Use colors in output.
  --stderr                  Write to STDERR instead of STDOUT.
  --stop-on-error           Stop execution upon first error.
  --stop-on-failure         Stop execution upon first error or failure.
  --stop-on-skipped         Stop execution upon first skipped test.
  --stop-on-incomplete      Stop execution upon first incomplete test.
  --strict                  Run tests in strict mode.
  -v|--verbose              Output more verbose information.
  --debug                   Display debugging information during test execution.

  --process-isolation       Run each test in a separate PHP process.
  --no-globals-backup       Do not backup and restore $GLOBALS for each test.
  --static-backup           Backup and restore static attributes for each test.

  --bootstrap <file>        A "bootstrap" PHP file that is run before the tests.
  -c|--configuration <file> Read configuration from XML file.
  --no-configuration        Ignore default configuration file (phpunit.xml).
  --include-path <path(s)>  Prepend PHP's include_path with given path(s).
  -d key[=value]            Sets a php.ini value.

  -h|--help                 Prints this usage information.
  --version                 Prints the version and exits.
--TEST--
phpunit --list-groups BankAccountTest ../_files/BankAccountTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--list-groups';
$_SERVER['argv'][3] = 'BankAccountTest';
$_SERVER['argv'][4] = dirname(__FILE__).'/../_files/BankAccountTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

Available test group(s):
 - Sebastian Bergmann <sebastian@phpunit.de>
 - balanceCannotBecomeNegative
 - balanceIsInitiallyZero
 - specification
--TEST--
phpunit --filter testBalanceIsInitiallyZero BankAccountTest ../_files/BankAccountTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--filter';
$_SERVER['argv'][3] = 'testBalanceIsInitiallyZero';
$_SERVER['argv'][4] = 'BankAccountTest';
$_SERVER['argv'][5] = dirname(__FILE__).'/../_files/BankAccountTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

.

Time: %s, Memory: %sMb

OK (1 test, 1 assertion)
--TEST--
phpunit --testdox php://stdout BankAccountTest ../_files/BankAccountTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--testdox';
$_SERVER['argv'][3] = 'BankAccountTest';
$_SERVER['argv'][4] = dirname(__FILE__).'/../_files/BankAccountTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

BankAccount
 [x] Balance is initially zero
 [x] Balance cannot become negative

--TEST--
phpunit BankAccountTest ../_files/BankAccountTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = 'BankAccountTest';
$_SERVER['argv'][3] = dirname(__FILE__).'/../_files/BankAccountTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

...

Time: %s, Memory: %sMb

OK (3 tests, 3 assertions)
--TEST--
phpunit --filter testBalanceIsInitiallyZero BankAccountTest ../_files/BankAccountTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--filter';
$_SERVER['argv'][3] = 'doesNotExist';
$_SERVER['argv'][4] = 'BankAccountTest';
$_SERVER['argv'][5] = dirname(__FILE__).'/../_files/BankAccountTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.



Time: %s, Memory: %sMb

No tests executed!
--TEST--
phpunit StackTest ../_files/StackTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = 'StackTest';
$_SERVER['argv'][3] = dirname(dirname(__FILE__)) . '/_files/StackTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

..

Time: %s, Memory: %sMb

OK (2 tests, 5 assertions)

--TEST--
phpunit --test-suffix .test.php,.my.php ../_files/
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--test-suffix';
$_SERVER['argv'][3] = '.test.php,.my.php';
$_SERVER['argv'][4] = dirname(__FILE__).'/../_files/';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

.....

Time: %s, Memory: %sMb

OK (5 tests, 3 assertions)
--TEST--
phpunit --help
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--help';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

Usage: phpunit [switches] UnitTest [UnitTest.php]
       phpunit [switches] <directory>

  --log-junit <file>        Log test execution in JUnit XML format to file.
  --log-tap <file>          Log test execution in TAP format to file.
  --log-json <file>         Log test execution in JSON format.

  --coverage-clover <file>  Generate code coverage report in Clover XML format.
  --coverage-html <dir>     Generate code coverage report in HTML format.
  --coverage-php <file>     Serialize PHP_CodeCoverage object to file.
  --coverage-text=<file>    Generate code coverage report in text format.
                            Default to writing to the standard output.

  --testdox-html <file>     Write agile documentation in HTML format to file.
  --testdox-text <file>     Write agile documentation in Text format to file.

  --filter <pattern>        Filter which tests to run.
  --testsuite <pattern>     Filter which testsuite to run.
  --group ...               Only runs tests from the specified group(s).
  --exclude-group ...       Exclude tests from the specified group(s).
  --list-groups             List available test groups.
  --test-suffix ...         Only search for test in files with specified
                            suffix(es). Default: Test.php,.phpt

  --loader <loader>         TestSuiteLoader implementation to use.
  --printer <printer>       TestSuiteListener implementation to use.
  --repeat <times>          Runs the test(s) repeatedly.

  --tap                     Report test execution progress in TAP format.
  --testdox                 Report test execution progress in TestDox format.

  --colors                  Use colors in output.
  --stderr                  Write to STDERR instead of STDOUT.
  --stop-on-error           Stop execution upon first error.
  --stop-on-failure         Stop execution upon first error or failure.
  --stop-on-skipped         Stop execution upon first skipped test.
  --stop-on-incomplete      Stop execution upon first incomplete test.
  --strict                  Run tests in strict mode.
  -v|--verbose              Output more verbose information.
  --debug                   Display debugging information during test execution.

  --process-isolation       Run each test in a separate PHP process.
  --no-globals-backup       Do not backup and restore $GLOBALS for each test.
  --static-backup           Backup and restore static attributes for each test.

  --bootstrap <file>        A "bootstrap" PHP file that is run before the tests.
  -c|--configuration <file> Read configuration from XML file.
  --no-configuration        Ignore default configuration file (phpunit.xml).
  --include-path <path(s)>  Prepend PHP's include_path with given path(s).
  -d key[=value]            Sets a php.ini value.

  -h|--help                 Prints this usage information.
  --version                 Prints the version and exits.
--TEST--
phpunit --exclude-group balanceIsInitiallyZero BankAccountTest ../_files/BankAccountTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--exclude-group';
$_SERVER['argv'][3] = 'balanceIsInitiallyZero';
$_SERVER['argv'][4] = 'BankAccountTest';
$_SERVER['argv'][5] = dirname(__FILE__).'/../_files/BankAccountTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

..

Time: %s, Memory: %sMb

OK (2 tests, 2 assertions)
--TEST--
phpunit --process-isolation --filter testBalanceIsInitiallyZero BankAccountTest ../_files/BankAccountTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--process-isolation';
$_SERVER['argv'][3] = '--filter';
$_SERVER['argv'][4] = 'testBalanceIsInitiallyZero';
$_SERVER['argv'][5] = 'BankAccountTest';
$_SERVER['argv'][6] = dirname(__FILE__).'/../_files/BankAccountTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

.

Time: %s, Memory: %sMb

OK (1 test, 1 assertion)
--TEST--
phpunit FatalTest ../_files/FatalTest.php
--FILE--
<?php

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = 'FatalTest';
$_SERVER['argv'][3] = dirname(dirname(__FILE__)) . '/_files/FatalTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.


Fatal error: Call to undefined function non_existing_function() in %s
--TEST--
phpunit --debug BankAccountTest ../_files/BankAccountTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--debug';
$_SERVER['argv'][3] = 'BankAccountTest';
$_SERVER['argv'][4] = dirname(__FILE__).'/../_files/BankAccountTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.


Starting test 'BankAccountTest::testBalanceIsInitiallyZero'.
.
Starting test 'BankAccountTest::testBalanceCannotBecomeNegative'.
.
Starting test 'BankAccountTest::testBalanceCannotBecomeNegative2'.
.

Time: %s, Memory: %sMb

OK (3 tests, 3 assertions)
--TEST--
phpunit --test-suffix .test.php ../_files/
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--test-suffix';
$_SERVER['argv'][3] = '.test.php';
$_SERVER['argv'][4] = dirname(__FILE__).'/../_files/';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

...

Time: %s, Memory: %sMb

OK (3 tests, 3 assertions)
--TEST--
phpunit --testdox DataProviderTest ../_files/DataProviderTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--testdox';
$_SERVER['argv'][3] = 'DataProviderTest';
$_SERVER['argv'][4] = dirname(dirname(__FILE__)) . '/_files/DataProviderTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

DataProvider
 [ ] Add
--TEST--
phpunit --process-isolation BankAccountTest ../_files/BankAccountTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--process-isolation';
$_SERVER['argv'][3] = 'BankAccountTest';
$_SERVER['argv'][4] = dirname(__FILE__).'/../_files/BankAccountTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

...

Time: %s, Memory: %sMb

OK (3 tests, 3 assertions)
--TEST--
phpunit --strict --process-isolation IncompleteTest ../_files/IncompleteTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--strict';
$_SERVER['argv'][3] = '--process-isolation';
$_SERVER['argv'][4] = 'NothingTest';
$_SERVER['argv'][5] = dirname(dirname(__FILE__)) . '/_files/NothingTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

I

Time: %s, Memory: %sMb

OK, but incomplete or skipped tests!
Tests: 1, Assertions: 0, Incomplete: 1.
--TEST--
phpunit ConcreteTest ../_files/ConcreteTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = 'ConcreteTest';
$_SERVER['argv'][3] = dirname(dirname(__FILE__)) . '/_files/ConcreteTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

..

Time: %s, Memory: %sMb

OK (2 tests, 0 assertions)

--TEST--
phpunit --process-isolation StackTest ../_files/StackTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--process-isolation';
$_SERVER['argv'][3] = 'StackTest';
$_SERVER['argv'][4] = dirname(dirname(__FILE__)) . '/_files/StackTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

..

Time: %s, Memory: %sMb

OK (2 tests, 5 assertions)

--TEST--
phpunit --process-isolation --verbose DependencyTestSuite ../_files/DependencyTestSuite.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--process-isolation';
$_SERVER['argv'][3] = '--verbose';
$_SERVER['argv'][4] = 'DependencyTestSuite';
$_SERVER['argv'][5] = dirname(dirname(__FILE__)) . '/_files/DependencyTestSuite.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

...FSS

Time: %s, Memory: %sMb

There was 1 failure:

1) DependencyFailureTest::testOne

%s:%i

There were 2 skipped tests:

1) DependencyFailureTest::testTwo
This test depends on "DependencyFailureTest::testOne" to pass.

%s:%i

2) DependencyFailureTest::testThree
This test depends on "DependencyFailureTest::testTwo" to pass.

%s:%i

FAILURES!
Tests: 4, Assertions: 0, Failures: 1, Skipped: 2.
--TEST--
phpunit --log-junit php://stdout BankAccountTest ../_files/BankAccountTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--log-junit';
$_SERVER['argv'][3] = 'php://stdout';
$_SERVER['argv'][4] = 'BankAccountTest';
$_SERVER['argv'][5] = dirname(__FILE__).'/../_files/BankAccountTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

...<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
  <testsuite name="BankAccountTest" file="%sBankAccountTest.php" fullPackage="PHPUnit" package="PHPUnit" tests="3" assertions="3" failures="0" errors="0" time="%f">
    <testcase name="testBalanceIsInitiallyZero" class="BankAccountTest" file="%sBankAccountTest.php" line="72" assertions="1" time="%f"/>
    <testcase name="testBalanceCannotBecomeNegative" class="BankAccountTest" file="%sBankAccountTest.php" line="82" assertions="1" time="%f"/>
    <testcase name="testBalanceCannotBecomeNegative2" class="BankAccountTest" file="%sBankAccountTest.php" line="102" assertions="1" time="%f"/>
  </testsuite>
</testsuites>


Time: %s, Memory: %sMb

OK (3 tests, 3 assertions)
--TEST--
phpunit --log-junit php://stdout DataProviderTest ../_files/DataProviderTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--log-junit';
$_SERVER['argv'][3] = 'php://stdout';
$_SERVER['argv'][4] = 'DataProviderTest';
$_SERVER['argv'][5] = dirname(dirname(__FILE__)) . '/_files/DataProviderTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

..F.<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
  <testsuite name="DataProviderTest" file="%s/DataProviderTest.php" tests="4" assertions="4" failures="1" errors="0" time="%f">
    <testsuite name="DataProviderTest::testAdd" tests="4" assertions="4" failures="1" errors="0" time="%f">
      <testcase name="testAdd with data set #0" assertions="1" time="%f"/>
      <testcase name="testAdd with data set #1" assertions="1" time="%f"/>
      <testcase name="testAdd with data set #2" assertions="1" time="%f">
        <failure type="PHPUnit_Framework_ExpectationFailedException">DataProviderTest::testAdd with data set #2 (1, 1, 3)
Failed asserting that 2 matches expected 3.

%s:%i
%s:%i
</failure>
      </testcase>
      <testcase name="testAdd with data set #3" assertions="1" time="%f"/>
    </testsuite>
  </testsuite>
</testsuites>


Time: %s, Memory: %sMb

There was 1 failure:

1) DataProviderTest::testAdd with data set #2 (1, 1, 3)
Failed asserting that 2 matches expected 3.
%s:%i
%s:%i

FAILURES!
Tests: 4, Assertions: 4, Failures: 1.

--TEST--
phpunit --process-isolation --group balanceIsInitiallyZero BankAccountTest ../_files/BankAccountTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--process-isolation';
$_SERVER['argv'][3] = '--group';
$_SERVER['argv'][4] = 'balanceIsInitiallyZero';
$_SERVER['argv'][5] = 'BankAccountTest';
$_SERVER['argv'][6] = dirname(__FILE__).'/../_files/BankAccountTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

.

Time: %s, Memory: %sMb

OK (1 test, 1 assertion)
--TEST--
phpunit --log-json php://stdout BankAccountTest ../_files/BankAccountTest.php
--SKIPIF--
<?php
if (!defined("JSON_PRETTY_PRINT")) {
    echo "Skip: Test requires JSON_PRETTY_PRINT / PHP >= 5.4";
}
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--log-json';
$_SERVER['argv'][3] = 'php://stdout';
$_SERVER['argv'][4] = 'BankAccountTest';
$_SERVER['argv'][5] = dirname(__FILE__).'/../_files/BankAccountTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

{
    "event": "suiteStart",
    "suite": "BankAccountTest",
    "tests": 3
}{
    "event": "testStart",
    "suite": "BankAccountTest",
    "test": "BankAccountTest::testBalanceIsInitiallyZero"
}.{
    "event": "test",
    "suite": "BankAccountTest",
    "test": "BankAccountTest::testBalanceIsInitiallyZero",
    "status": "pass",
    "time": %f,
    "trace": [

    ],
    "message": "",
    "output": ""
}{
    "event": "testStart",
    "suite": "BankAccountTest",
    "test": "BankAccountTest::testBalanceCannotBecomeNegative"
}.{
    "event": "test",
    "suite": "BankAccountTest",
    "test": "BankAccountTest::testBalanceCannotBecomeNegative",
    "status": "pass",
    "time": %f,
    "trace": [

    ],
    "message": "",
    "output": ""
}{
    "event": "testStart",
    "suite": "BankAccountTest",
    "test": "BankAccountTest::testBalanceCannotBecomeNegative2"
}.{
    "event": "test",
    "suite": "BankAccountTest",
    "test": "BankAccountTest::testBalanceCannotBecomeNegative2",
    "status": "pass",
    "time": %f,
    "trace": [

    ],
    "message": "",
    "output": ""
}

Time: %s, Memory: %sMb

OK (3 tests, 3 assertions)
--TEST--
phpunit EmptyTestCaseTest ../_files/EmptyTestCaseTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = 'EmptyTestCaseTest';
$_SERVER['argv'][3] = dirname(dirname(__FILE__)) . '/_files/EmptyTestCaseTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

F

Time: %s, Memory: %sMb

There was 1 failure:

1) Warning
No tests found in class "EmptyTestCaseTest".

%s:%i

FAILURES!
Tests: 1, Assertions: 0, Failures: 1.
--TEST--
phpunit --strict IncompleteTest ../_files/IncompleteTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--strict';
$_SERVER['argv'][3] = 'IncompleteTest';
$_SERVER['argv'][4] = dirname(dirname(__FILE__)) . '/_files/IncompleteTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

I

Time: %s, Memory: %sMb

OK, but incomplete or skipped tests!
Tests: 1, Assertions: 0, Incomplete: 1.
--TEST--
phpunit AbstractTest ../_files/AbstractTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = 'AbstractTest';
$_SERVER['argv'][3] = dirname(dirname(__FILE__)) . '/_files/AbstractTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

F

Time: %s, Memory: %sMb

There was 1 failure:

1) Warning
Cannot instantiate class "AbstractTest".

%s:%i

FAILURES!
Tests: 1, Assertions: 0, Failures: 1.

--TEST--
phpunit --testdox-text php://stdout BankAccountTest ../_files/BankAccountTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--testdox-text';
$_SERVER['argv'][3] = 'php://stdout';
$_SERVER['argv'][4] = 'BankAccountTest';
$_SERVER['argv'][5] = dirname(__FILE__).'/../_files/BankAccountTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

BankAccount
... [x] Balance is initially zero
 [x] Balance cannot become negative



Time: %s, Memory: %sMb

OK (3 tests, 3 assertions)
--TEST--
phpunit --verbose DependencyTestSuite ../_files/DependencyTestSuite.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--verbose';
$_SERVER['argv'][3] = 'DependencyTestSuite';
$_SERVER['argv'][4] = dirname(dirname(__FILE__)) . '/_files/DependencyTestSuite.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

...FSS

Time: %s, Memory: %sMb

There was 1 failure:

1) DependencyFailureTest::testOne

%s:%i
%s:%i

There were 2 skipped tests:

1) DependencyFailureTest::testTwo
This test depends on "DependencyFailureTest::testOne" to pass.

%s:%i

2) DependencyFailureTest::testThree
This test depends on "DependencyFailureTest::testTwo" to pass.

%s:%i

FAILURES!
Tests: 4, Assertions: 0, Failures: 1, Skipped: 2.
--TEST--
phpunit MultiDependencyTest ../_files/MultiDependencyTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = 'MultiDependencyTest';
$_SERVER['argv'][3] = dirname(dirname(__FILE__)) . '/_files/MultiDependencyTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

...

Time: %s, Memory: %sMb

OK (3 tests, 2 assertions)
--TEST--
phpunit --process-isolation MultiDependencyTest ../_files/MultiDependencyTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--process-isolation';
$_SERVER['argv'][3] = 'MultiDependencyTest';
$_SERVER['argv'][4] = dirname(dirname(__FILE__)) . '/_files/MultiDependencyTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

...

Time: %s, Memory: %sMb

OK (3 tests, 2 assertions)

--TEST--
phpunit --log-tap php://stdout BankAccountTest ../_files/BankAccountTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--log-tap';
$_SERVER['argv'][3] = 'php://stdout';
$_SERVER['argv'][4] = 'BankAccountTest';
$_SERVER['argv'][5] = dirname(__FILE__).'/../_files/BankAccountTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

TAP version 13
.ok 1 - BankAccountTest::testBalanceIsInitiallyZero
.ok 2 - BankAccountTest::testBalanceCannotBecomeNegative
.ok 3 - BankAccountTest::testBalanceCannotBecomeNegative2
1..3


Time: %s, Memory: %sMb

OK (3 tests, 3 assertions)
--TEST--
phpunit --strict NothingTest ../_files/NothingTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--strict';
$_SERVER['argv'][3] = 'NothingTest';
$_SERVER['argv'][4] = dirname(dirname(__FILE__)) . '/_files/NothingTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

I

Time: %s, Memory: %sMb

OK, but incomplete or skipped tests!
Tests: 1, Assertions: 0, Incomplete: 1.
--TEST--
phpunit --testdox-html php://stdout BankAccountTest ../_files/BankAccountTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--testdox-html';
$_SERVER['argv'][3] = 'php://stdout';
$_SERVER['argv'][4] = 'BankAccountTest';
$_SERVER['argv'][5] = dirname(__FILE__).'/../_files/BankAccountTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

<html><body><h2 id="BankAccountTest">BankAccount</h2><ul>...<li>Balance is initially zero</li><li>Balance cannot become negative</li></ul></body></html>

Time: %s, Memory: %sMb

OK (3 tests, 3 assertions)
--TEST--
phpunit --process-isolation --log-junit php://stdout DataProviderTest ../_files/DataProviderTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--process-isolation';
$_SERVER['argv'][3] = '--log-junit';
$_SERVER['argv'][4] = 'php://stdout';
$_SERVER['argv'][5] = 'DataProviderTest';
$_SERVER['argv'][6] = dirname(dirname(__FILE__)) . '/_files/DataProviderTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

..F.<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
  <testsuite name="DataProviderTest" file="%s/DataProviderTest.php" tests="4" assertions="4" failures="1" errors="0" time="%f">
    <testsuite name="DataProviderTest::testAdd" tests="4" assertions="4" failures="1" errors="0" time="%f">
      <testcase name="testAdd with data set #0" assertions="1" time="%f"/>
      <testcase name="testAdd with data set #1" assertions="1" time="%f"/>
      <testcase name="testAdd with data set #2" assertions="1" time="%f">
        <failure type="PHPUnit_Framework_ExpectationFailedException">DataProviderTest::testAdd with data set #2 (1, 1, 3)
Failed asserting that 2 matches expected 3.

%s:%i
</failure>
      </testcase>
      <testcase name="testAdd with data set #3" assertions="1" time="%f"/>
    </testsuite>
  </testsuite>
</testsuites>


Time: %s, Memory: %sMb

There was 1 failure:

1) DataProviderTest::testAdd with data set #2 (1, 1, 3)
Failed asserting that 2 matches expected 3.
%s:%i

FAILURES!
Tests: 4, Assertions: 4, Failures: 1.

--TEST--
phpunit --group balanceIsInitiallyZero BankAccountTest ../_files/BankAccountTest.php
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--group';
$_SERVER['argv'][3] = 'balanceIsInitiallyZero';
$_SERVER['argv'][4] = 'BankAccountTest';
$_SERVER['argv'][5] = dirname(__FILE__).'/../_files/BankAccountTest.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

.

Time: %s, Memory: %sMb

OK (1 test, 1 assertion)
--TEST--
phpunit ExceptionStackTest ../_files/ExceptionStack.php
--FILE--
<?php
$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = 'ExceptionStackTest';
$_SERVER['argv'][3] = dirname(dirname(__FILE__)) . '/_files/ExceptionStack.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

EE

Time: %s, Memory: %sMb

There were 2 errors:

1) ExceptionStackTest::testPrintingChildException
ExceptionStackTestException: Child exception
message
Failed asserting that two arrays are equal.
--- Expected
+++ Actual
@@ @@
 Array (
-    0 => 1
+    0 => 2
 )

%s:%i

Caused by
%s:%i

2) ExceptionStackTest::testNestedExceptions
Exception: One

%s:%i

Caused by
InvalidArgumentException: Two

%s:%i

Caused by
Exception: Three

%s:%i

FAILURES!
Tests: 2, Assertions: 1, Errors: 2.

<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Mike Naberezny <mike@maintainable.com>
 * @author     Derek DeVries <derek@maintainable.com>
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.3.0
 */

/**
 *
 *
 * @package    PHPUnit
 * @author     Mike Naberezny <mike@maintainable.com>
 * @author     Derek DeVries <derek@maintainable.com>
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.3.0
 */
class Util_XMLTest extends PHPUnit_Framework_TestCase
{
    public function testAssertValidKeysValidKeys()
    {
        $options   = array('testA' => 1, 'testB' => 2, 'testC' => 3);
        $valid     = array('testA', 'testB', 'testC');
        $expected  = array('testA' => 1, 'testB' => 2, 'testC' => 3);
        $validated = PHPUnit_Util_XML::assertValidKeys($options, $valid);

        $this->assertEquals($expected, $validated);
    }

    public function testAssertValidKeysValidKeysEmpty()
    {
        $options   = array('testA' => 1, 'testB' => 2);
        $valid     = array('testA', 'testB', 'testC');
        $expected  = array('testA' => 1, 'testB' => 2, 'testC' => NULL);
        $validated = PHPUnit_Util_XML::assertValidKeys($options, $valid);

        $this->assertEquals($expected, $validated);
    }

    public function testAssertValidKeysDefaultValuesA()
    {
        $options   = array('testA' => 1, 'testB' => 2);
        $valid     = array('testA' => 23, 'testB' => 24, 'testC' => 25);
        $expected  = array('testA' => 1, 'testB' => 2, 'testC' => 25);
        $validated = PHPUnit_Util_XML::assertValidKeys($options, $valid);

        $this->assertEquals($expected, $validated);
    }

    public function testAssertValidKeysDefaultValuesB()
    {
        $options   = array();
        $valid     = array('testA' => 23, 'testB' => 24, 'testC' => 25);
        $expected  = array('testA' => 23, 'testB' => 24, 'testC' => 25);
        $validated = PHPUnit_Util_XML::assertValidKeys($options, $valid);

        $this->assertEquals($expected, $validated);
    }

    public function testAssertValidKeysInvalidKey()
    {
        $options = array('testA' => 1, 'testB' => 2, 'testD' => 3);
        $valid   = array('testA', 'testB', 'testC');

        try {
            $validated = PHPUnit_Util_XML::assertValidKeys($options, $valid);
            $this->fail();
        }

        catch (PHPUnit_Framework_Exception $e) {
            $this->assertEquals('Unknown key(s): testD', $e->getMessage());
        }
    }

    public function testAssertValidKeysInvalidKeys()
    {
        $options = array('testA' => 1, 'testD' => 2, 'testE' => 3);
        $valid   = array('testA', 'testB', 'testC');

        try {
            $validated = PHPUnit_Util_XML::assertValidKeys($options, $valid);
            $this->fail();
        }

        catch (PHPUnit_Framework_Exception $e) {
            $this->assertEquals('Unknown key(s): testD, testE', $e->getMessage());
        }
    }

    public function testConvertAssertSelect()
    {
        $selector  = 'div#folder.open a[href="http://www.xerox.com"][title="xerox"].selected.big > span';
        $converted = PHPUnit_Util_XML::convertSelectToTag($selector);
        $tag       = array('tag'   => 'div',
                           'id'    => 'folder',
                           'class' => 'open',
                           'descendant' => array('tag'        => 'a',
                                                 'class'      => 'selected big',
                                                 'attributes' => array('href'  => 'http://www.xerox.com',
                                                                       'title' => 'xerox'),
                                                 'child'      => array('tag' => 'span')));
         $this->assertEquals($tag, $converted);
    }

    public function testConvertAssertSelectElt()
    {
        $selector  = 'div';
        $converted = PHPUnit_Util_XML::convertSelectToTag($selector);
        $tag       = array('tag' => 'div');

        $this->assertEquals($tag, $converted);
    }

    public function testConvertAssertClass()
    {
        $selector  = '.foo';
        $converted = PHPUnit_Util_XML::convertSelectToTag($selector);
        $tag       = array('class' => 'foo');

        $this->assertEquals($tag, $converted);
    }

    public function testConvertAssertId()
    {
        $selector  = '#foo';
        $converted = PHPUnit_Util_XML::convertSelectToTag($selector);
        $tag       = array('id' => 'foo');

        $this->assertEquals($tag, $converted);
    }

    public function testConvertAssertAttribute()
    {
        $selector  = '[foo="bar"]';
        $converted = PHPUnit_Util_XML::convertSelectToTag($selector);
        $tag       = array('attributes' => array('foo' => 'bar'));

        $this->assertEquals($tag, $converted);
    }

    public function testConvertAssertAttributeSpaces()
    {
        $selector  = '[foo="bar baz"] div[value="foo bar"]';
        $converted = PHPUnit_Util_XML::convertSelectToTag($selector);
        $tag       = array('attributes' => array('foo' => 'bar baz'),
                           'descendant' => array('tag'        => 'div',
                                                 'attributes' => array('value' => 'foo bar')));
        $this->assertEquals($tag, $converted);
    }

    public function testConvertAssertAttributeMultipleSpaces()
    {
        $selector = '[foo="bar baz"] div[value="foo bar baz"]';
        $converted = PHPUnit_Util_XML::convertSelectToTag($selector);
        $tag      = array('attributes' => array('foo' => 'bar baz'),
                          'descendant' => array('tag' => 'div',
                                                'attributes' => array('value' => 'foo bar baz')));
        $this->assertEquals($tag, $converted);
    }

    public function testConvertAssertSelectEltClass()
    {
        $selector  = 'div.foo';
        $converted = PHPUnit_Util_XML::convertSelectToTag($selector);
        $tag       = array('tag' => 'div', 'class' => 'foo');

        $this->assertEquals($tag, $converted);
    }

    public function testConvertAssertSelectEltId()
    {
        $selector  = 'div#foo';
        $converted = PHPUnit_Util_XML::convertSelectToTag($selector);
        $tag       = array('tag' => 'div', 'id' => 'foo');

        $this->assertEquals($tag, $converted);
    }

    public function testConvertAssertSelectEltAttrEqual()
    {
        $selector  = 'div[foo="bar"]';
        $converted = PHPUnit_Util_XML::convertSelectToTag($selector);
        $tag       = array('tag' => 'div', 'attributes' => array('foo' => 'bar'));

        $this->assertEquals($tag, $converted);
    }

    public function testConvertAssertSelectEltMultiAttrEqual()
    {
        $selector  = 'div[foo="bar"][baz="fob"]';
        $converted = PHPUnit_Util_XML::convertSelectToTag($selector);
        $tag       = array('tag' => 'div', 'attributes' => array('foo' => 'bar', 'baz' => 'fob'));

        $this->assertEquals($tag, $converted);
    }

    public function testConvertAssertSelectEltAttrHasOne()
    {
        $selector  = 'div[foo~="bar"]';
        $converted = PHPUnit_Util_XML::convertSelectToTag($selector);
        $tag       = array('tag' => 'div', 'attributes' => array('foo' => 'regexp:/.*\bbar\b.*/'));

        $this->assertEquals($tag, $converted);
    }

    public function testConvertAssertSelectEltAttrContains()
    {
        $selector  = 'div[foo*="bar"]';
        $converted = PHPUnit_Util_XML::convertSelectToTag($selector);
        $tag       = array('tag' => 'div', 'attributes' => array('foo' => 'regexp:/.*bar.*/'));

        $this->assertEquals($tag, $converted);
    }

    public function testConvertAssertSelectEltChild()
    {
        $selector  = 'div > a';
        $converted = PHPUnit_Util_XML::convertSelectToTag($selector);
        $tag       = array('tag' => 'div', 'child' => array('tag' => 'a'));

        $this->assertEquals($tag, $converted);
    }

    public function testConvertAssertSelectEltDescendant()
    {
        $selector  = 'div a';
        $converted = PHPUnit_Util_XML::convertSelectToTag($selector);
        $tag       = array('tag' => 'div', 'descendant' => array('tag' => 'a'));

        $this->assertEquals($tag, $converted);
    }

    public function testConvertAssertSelectContent()
    {
        $selector  = '#foo';
        $content   = 'div contents';
        $converted = PHPUnit_Util_XML::convertSelectToTag($selector, $content);
        $tag       = array('id' => 'foo', 'content' => 'div contents');

        $this->assertEquals($tag, $converted);
    }

    public function testConvertAssertSelectTrue()
    {
        $selector  = '#foo';
        $content   = TRUE;
        $converted = PHPUnit_Util_XML::convertSelectToTag($selector, $content);
        $tag       = array('id' => 'foo');

        $this->assertEquals($tag, $converted);
    }

    public function testConvertAssertSelectFalse()
    {
        $selector  = '#foo';
        $content   = FALSE;
        $converted = PHPUnit_Util_XML::convertSelectToTag($selector, $content);
        $tag       = array('id' => 'foo');

        $this->assertEquals($tag, $converted);
    }

    public function testConvertAssertNumber()
    {
        $selector  = '.foo';
        $content   = 3;
        $converted = PHPUnit_Util_XML::convertSelectToTag($selector, $content);
        $tag       = array('class' => 'foo');

        $this->assertEquals($tag, $converted);
    }

    public function testConvertAssertRange()
    {
        $selector  = '#foo';
        $content   = array('greater_than' => 5, 'less_than' => 10);
        $converted = PHPUnit_Util_XML::convertSelectToTag($selector, $content);
        $tag       = array('id' => 'foo');

        $this->assertEquals($tag, $converted);
    }

    public function testPrepareStringEscapesChars()
    {
        $this->assertEquals('&#x1b;', PHPUnit_Util_XML::prepareString("\033"));
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.3.6
 */

require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'ExceptionTest.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'ExceptionNamespaceTest.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'RequirementsTest.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'RequirementsClassDocBlockTest.php';

/**
 *
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.3.6
 */
class Util_TestTest extends PHPUnit_Framework_TestCase
{
    public function testGetExpectedException()
    {
        $this->assertSame(
          array('class' => 'FooBarBaz', 'code' => NULL, 'message' => ''),
          PHPUnit_Util_Test::getExpectedException('ExceptionTest', 'testOne')
        );

        $this->assertSame(
          array('class' => 'Foo_Bar_Baz', 'code' => NULL, 'message' => ''),
          PHPUnit_Util_Test::getExpectedException('ExceptionTest', 'testTwo')
        );

        $this->assertSame(
          array('class' => 'Foo\Bar\Baz', 'code' => NULL, 'message' => ''),
          PHPUnit_Util_Test::getExpectedException('ExceptionTest', 'testThree')
        );

        $this->assertSame(
          array('class' => 'ほげ', 'code' => NULL, 'message' => ''),
          PHPUnit_Util_Test::getExpectedException('ExceptionTest', 'testFour')
        );

        $this->assertSame(
          array('class' => 'Class', 'code' => 1234, 'message' => 'Message'),
          PHPUnit_Util_Test::getExpectedException('ExceptionTest', 'testFive')
        );

        $this->assertSame(
          array('class' => 'Class', 'code' => 1234, 'message' => 'Message'),
          PHPUnit_Util_Test::getExpectedException('ExceptionTest', 'testSix')
        );

        $this->assertSame(
          array('class' => 'Class', 'code' => 'ExceptionCode', 'message' => 'Message'),
          PHPUnit_Util_Test::getExpectedException('ExceptionTest', 'testSeven')
        );

        $this->assertSame(
          array('class' => 'Class', 'code' => 0, 'message' => 'Message'),
          PHPUnit_Util_Test::getExpectedException('ExceptionTest', 'testEight')
        );
        $this->assertSame(
          array('class' => 'Class', 'code' => ExceptionTest::ERROR_CODE, 'message' => ExceptionTest::ERROR_MESSAGE),
          PHPUnit_Util_Test::getExpectedException('ExceptionTest', 'testNine')
        );
        $this->assertSame(
          array('class' => 'Class', 'code' => NULL, 'message' => ''),
          PHPUnit_Util_Test::getExpectedException('ExceptionTest', 'testSingleLine')
        );
        $this->assertSame(
            array('class' => 'Class', 'code' => My\Space\ExceptionNamespaceTest::ERROR_CODE, 'message' => My\Space\ExceptionNamespaceTest::ERROR_MESSAGE),
            PHPUnit_Util_Test::getExpectedException('My\Space\ExceptionNamespaceTest', 'testConstants')
        );
        // Ensure the Class::CONST expression is only evaluated when the constant really exists
        $this->assertSame(
            array('class' => 'Class', 'code' => 'ExceptionTest::UNKNOWN_CODE_CONSTANT', 'message' => 'ExceptionTest::UNKNOWN_MESSAGE_CONSTANT'),
            PHPUnit_Util_Test::getExpectedException('ExceptionTest', 'testUnknownConstants')
        );
        $this->assertSame(
            array('class' => 'Class', 'code' => 'My\Space\ExceptionNamespaceTest::UNKNOWN_CODE_CONSTANT', 'message' => 'My\Space\ExceptionNamespaceTest::UNKNOWN_MESSAGE_CONSTANT'),
            PHPUnit_Util_Test::getExpectedException('My\Space\ExceptionNamespaceTest', 'testUnknownConstants')
        );
    }

    public function provideRequirements()
    {
        return array(
            array('testOne',   array()),
            array('testTwo',   array('PHPUnit' => '1.0')),
            array('testThree', array('PHP' => '2.0')),
            array('testFour',  array('PHPUnit'=>'2.0', 'PHP' => '1.0')),
            array('testFive',  array('PHP' => '5.4.0RC6')),
            array('testSix',   array('PHP' => '5.4.0-alpha1')),
            array('testSeven', array('PHP' => '5.4.0beta2')),
            array('testEight', array('PHP' => '5.4-dev')),
            array('testNine',  array('functions' => array('testFunc'))),
            array('testTen',   array('extensions' => array('testExt'))),
            array(
                'testAllPossibleRequirements',
                array(
                    'PHP' => '99-dev',
                    'PHPUnit' => '9-dev',
                    'functions' => array(
                        'testFuncOne',
                        'testFuncTwo',
                    ),
                    'extensions' => array(
                        'testExtOne',
                        'testExtTwo',
                    )
                )
            )
        );
    }

    /**
     * @dataProvider provideRequirements
     */
    public function testGetRequirements($test, $result)
    {
        $this->assertEquals(
          $result,
          PHPUnit_Util_Test::getRequirements('RequirementsTest', $test)
        );
    }

    public function testGetRequirementsMergesClassAndMethodDocBlocks()
    {
        $expectedAnnotations = array(
            'PHP' => '5.4',
            'PHPUnit' => '3.7',
            'functions' => array(
                'testFuncClass',
                'testFuncMethod',
            ),
            'extensions' => array(
                'testExtClass',
                'testExtMethod',
            )
        );

        $this->assertEquals(
          $expectedAnnotations,
          PHPUnit_Util_Test::getRequirements('RequirementsClassDocBlockTest', 'testMethod')
        );
    }

    public function testGetProvidedDataRegEx()
    {
        $result = preg_match(PHPUnit_Util_Test::REGEX_DATA_PROVIDER, '@dataProvider method', $matches);
        $this->assertEquals(1, $result);
        $this->assertEquals('method', $matches[1]);

        $result = preg_match(PHPUnit_Util_Test::REGEX_DATA_PROVIDER, '@dataProvider class::method', $matches);
        $this->assertEquals(1, $result);
        $this->assertEquals('class::method', $matches[1]);

        $result = preg_match(PHPUnit_Util_Test::REGEX_DATA_PROVIDER, '@dataProvider namespace\class::method', $matches);
        $this->assertEquals(1, $result);
        $this->assertEquals('namespace\class::method', $matches[1]);

        $result = preg_match(PHPUnit_Util_Test::REGEX_DATA_PROVIDER, '@dataProvider namespace\namespace\class::method', $matches);
        $this->assertEquals(1, $result);
        $this->assertEquals('namespace\namespace\class::method', $matches[1]);

        $result = preg_match(PHPUnit_Util_Test::REGEX_DATA_PROVIDER, '@dataProvider メソッド', $matches);
        $this->assertEquals(1, $result);
        $this->assertEquals('メソッド', $matches[1]);
    }

    public function testParseAnnotation()
    {
        $this->assertEquals(
          array('Foo', 'ほげ'),
          PHPUnit_Util_Test::getDependencies(get_class($this), 'methodForTestParseAnnotation')
        );
    }

    /**
     * @depends Foo
     * @depends ほげ
     */
    public function methodForTestParseAnnotation()
    {
    }

    public function testParseAnnotationThatIsOnlyOneLine()
    {
        $this->assertEquals(
          array('Bar'),
          PHPUnit_Util_Test::getDependencies(get_class($this), 'methodForTestParseAnnotationThatIsOnlyOneLine')
        );
    }

    /** @depends Bar */
    public function methodForTestParseAnnotationThatIsOnlyOneLine()
    {
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.3.0
 */

/**
 *
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.1.0
 */
class Util_TestDox_NamePrettifierTest extends PHPUnit_Framework_TestCase
{
    protected $namePrettifier;

    protected function setUp()
    {
        $this->namePrettifier = new PHPUnit_Util_TestDox_NamePrettifier;
    }

    public function testTitleHasSensibleDefaults()
    {
        $this->assertEquals('Foo', $this->namePrettifier->prettifyTestClass('FooTest'));
        $this->assertEquals('Foo', $this->namePrettifier->prettifyTestClass('TestFoo'));
        $this->assertEquals('Foo', $this->namePrettifier->prettifyTestClass('TestFooTest'));
    }

    public function testCaterForUserDefinedSuffix()
    {
        $this->namePrettifier->setSuffix('TestCase');
        $this->namePrettifier->setPrefix(NULL);

        $this->assertEquals('Foo', $this->namePrettifier->prettifyTestClass('FooTestCase'));
        $this->assertEquals('TestFoo', $this->namePrettifier->prettifyTestClass('TestFoo'));
        $this->assertEquals('FooTest', $this->namePrettifier->prettifyTestClass('FooTest'));
    }

    public function testCaterForUserDefinedPrefix()
    {
        $this->namePrettifier->setSuffix(NULL);
        $this->namePrettifier->setPrefix('XXX');

        $this->assertEquals('Foo', $this->namePrettifier->prettifyTestClass('XXXFoo'));
        $this->assertEquals('TestXXX', $this->namePrettifier->prettifyTestClass('TestXXX'));
        $this->assertEquals('XXX', $this->namePrettifier->prettifyTestClass('XXXXXX'));
    }

    public function testTestNameIsConvertedToASentence()
    {
        $this->assertEquals('This is a test', $this->namePrettifier->prettifyTestMethod('testThisIsATest'));
        $this->assertEquals('This is a test', $this->namePrettifier->prettifyTestMethod('testThisIsATest2'));
        $this->assertEquals('this is a test', $this->namePrettifier->prettifyTestMethod('this_is_a_test'));
        $this->assertEquals('Foo for bar is 0', $this->namePrettifier->prettifyTestMethod('testFooForBarIs0'));
        $this->assertEquals('Foo for baz is 1', $this->namePrettifier->prettifyTestMethod('testFooForBazIs1'));
    }

    /**
     * @ticket 224
     */
    public function testTestNameIsNotGroupedWhenNotInSequence()
    {
        $this->assertEquals('Sets redirect header on 301', $this->namePrettifier->prettifyTestMethod('testSetsRedirectHeaderOn301'));
        $this->assertEquals('Sets redirect header on 302', $this->namePrettifier->prettifyTestMethod('testSetsRedirectHeaderOn302'));
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Ben Selby <benmatselby@gmail.com>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.5.6
 */

require_once 'PHPUnit/Framework/TestCase.php';

require_once 'PHPUnit/Util/Class.php';

/**
 *
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Ben Selby <benmatselby@gmail.com>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.5.6
 */
class Util_ClassTest extends PHPUnit_Framework_TestCase
{
    /**
     * Test that if a dynamic variable is defined on a class then
     * the $attribute variable will be NULL, but the variable defined
     * will be a public one so we are safe to return it
     *
     * Currently $attribute is NULL but we try and call isPublic() on it.
     * This breaks for php 5.2.10
     *
     * @covers PHPUnit_Util_Class::getObjectAttribute
     *
     * @return void
     */
    public function testGetObjectAttributeCanHandleDynamicVariables()
    {
        $attributeName = '_variable';
        $object = new stdClass();
        $object->$attributeName = 'Test';

        $actual = PHPUnit_Util_Class::getObjectAttribute($object, $attributeName);
        $this->assertEquals('Test', $actual);
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.3.0
 */

/**
 *
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.3.0
 */
class Util_ConfigurationTest extends PHPUnit_Framework_TestCase
{
    protected $configuration;

    protected function setUp()
    {
        $this->configuration = PHPUnit_Util_Configuration::getInstance(
          dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'configuration.xml'
        );
    }

    /**
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testExceptionIsThrownForNotExistingConfigurationFile()
    {
        PHPUnit_Util_Configuration::getInstance('not_existing_file.xml');
    }

    public function testFilterConfigurationIsReadCorrectly()
    {
        $this->assertEquals(
          array(
            'blacklist' =>
            array(
              'include' =>
              array(
                'directory' =>
                array(
                  0 =>
                  array(
                    'path' => '/path/to/files',
                    'prefix' => '',
                    'suffix' => '.php',
                    'group' => 'DEFAULT'
                  ),
                ),
                'file' =>
                array(
                  0 => '/path/to/file',
                ),
              ),
              'exclude' =>
              array(
                'directory' =>
                array(
                  0 =>
                  array(
                    'path' => '/path/to/files',
                    'prefix' => '',
                    'suffix' => '.php',
                    'group' => 'DEFAULT'
                  ),
                ),
                'file' =>
                array(
                  0 => '/path/to/file',
                ),
              ),
            ),
            'whitelist' =>
            array(
              'addUncoveredFilesFromWhitelist' => TRUE,
              'processUncoveredFilesFromWhitelist' => FALSE,
              'include' =>
              array(
                'directory' =>
                array(
                  0 =>
                  array(
                    'path' => '/path/to/files',
                    'prefix' => '',
                    'suffix' => '.php',
                    'group' => 'DEFAULT'
                  ),
                ),
                'file' =>
                array(
                  0 => '/path/to/file',
                ),
              ),
              'exclude' =>
              array(
                'directory' =>
                array(
                  0 =>
                  array(
                    'path' => '/path/to/files',
                    'prefix' => '',
                    'suffix' => '.php',
                    'group' => 'DEFAULT'
                  ),
                ),
                'file' =>
                array(
                  0 => '/path/to/file',
                ),
              ),
            ),
          ),
          $this->configuration->getFilterConfiguration()
        );
    }

    public function testGroupConfigurationIsReadCorrectly()
    {
        $this->assertEquals(
          array(
            'include' =>
            array(
              0 => 'name',
            ),
            'exclude' =>
            array(
              0 => 'name',
            ),
          ),
          $this->configuration->getGroupConfiguration()
        );
    }

    public function testListenerConfigurationIsReadCorrectly()
    {
        $dir = __DIR__;
        $includePath = ini_get('include_path');

        ini_set('include_path', $dir . PATH_SEPARATOR . $includePath);

        $this->assertEquals(
          array(
            0 =>
            array(
              'class' => 'MyListener',
              'file' => '/optional/path/to/MyListener.php',
              'arguments' =>
              array(
                0 =>
                array(
                  0 => 'Sebastian',
                ),
                1 => 22,
                2 => 'April',
                3 => 19.78,
                4 => NULL,
                5 => new stdClass,
                6 => dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'MyTestFile.php',
                7 => dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'MyRelativePath',
              ),
            ),
            array(
              'class' => 'IncludePathListener',
              'file' => __FILE__,
              'arguments' => array()
            ),
            array(
              'class' => 'CompactArgumentsListener',
              'file' => '/CompactArgumentsListener.php',
              'arguments' =>
              array(
                0 => 42
              ),
            ),
          ),
          $this->configuration->getListenerConfiguration()
        );

        ini_set('include_path', $includePath);
    }

    public function testLoggingConfigurationIsReadCorrectly()
    {
        $this->assertEquals(
          array(
            'charset' => 'UTF-8',
            'lowUpperBound' => '35',
            'highLowerBound' => '70',
            'highlight' => FALSE,
            'coverage-html' => '/tmp/report',
            'coverage-clover' => '/tmp/clover.xml',
            'json' => '/tmp/logfile.json',
            'plain' => '/tmp/logfile.txt',
            'tap' => '/tmp/logfile.tap',
            'logIncompleteSkipped' => FALSE,
            'junit' => '/tmp/logfile.xml',
            'testdox-html' => '/tmp/testdox.html',
            'testdox-text' => '/tmp/testdox.txt',
          ),
          $this->configuration->getLoggingConfiguration()
        );
    }

    public function testPHPConfigurationIsReadCorrectly()
    {
        $this->assertEquals(
          array(
            'include_path' =>
            array(
              dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . '.',
              '/path/to/lib'
            ),
            'ini'=> array('foo' => 'bar'),
            'const'=> array('FOO' => FALSE, 'BAR' => TRUE),
            'var'=> array('foo' => FALSE),
            'env'=> array('foo' => TRUE),
            'post'=> array('foo' => 'bar'),
            'get'=> array('foo' => 'bar'),
            'cookie'=> array('foo' => 'bar'),
            'server'=> array('foo' => 'bar'),
            'files'=> array('foo' => 'bar'),
            'request'=> array('foo' => 'bar'),
          ),
          $this->configuration->getPHPConfiguration()
        );
    }

    /**
     * @backupGlobals enabled
     */
    public function testPHPConfigurationIsHandledCorrectly()
    {
        $this->configuration->handlePHPConfiguration();

        $path = dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . '.' . PATH_SEPARATOR . '/path/to/lib';
        $this->assertStringStartsWith($path, ini_get('include_path'));
        $this->assertEquals(FALSE, FOO);
        $this->assertEquals(TRUE, BAR);
        $this->assertEquals(FALSE, $GLOBALS['foo']);
        $this->assertEquals(TRUE, $_ENV['foo']);
        $this->assertEquals(TRUE, getenv('foo'));
        $this->assertEquals('bar', $_POST['foo']);
        $this->assertEquals('bar', $_GET['foo']);
        $this->assertEquals('bar', $_COOKIE['foo']);
        $this->assertEquals('bar', $_SERVER['foo']);
        $this->assertEquals('bar', $_FILES['foo']);
        $this->assertEquals('bar', $_REQUEST['foo']);
    }

    public function testPHPUnitConfigurationIsReadCorrectly()
    {
        $this->assertEquals(
          array(
            'backupGlobals' => TRUE,
            'backupStaticAttributes' => FALSE,
            'bootstrap' => '/path/to/bootstrap.php',
            'cacheTokens' => FALSE,
            'colors' => FALSE,
            'convertErrorsToExceptions' => TRUE,
            'convertNoticesToExceptions' => TRUE,
            'convertWarningsToExceptions' => TRUE,
            'forceCoversAnnotation' => FALSE,
            'mapTestClassNameToCoveredClassName' => FALSE,
            'printerClass' => 'PHPUnit_TextUI_ResultPrinter',
            'stopOnFailure' => FALSE,
            'strict' => FALSE,
            'testSuiteLoaderClass' => 'PHPUnit_Runner_StandardTestSuiteLoader',
            'verbose' => FALSE,
            'timeoutForSmallTests' => 1,
            'timeoutForMediumTests' => 10,
            'timeoutForLargeTests' => 60
          ),
          $this->configuration->getPHPUnitConfiguration()
        );
    }

    public function testSeleniumBrowserConfigurationIsReadCorrectly()
    {
        $this->assertEquals(
          array(
            0 =>
            array(
              'name' => 'Firefox on Linux',
              'browser' => '*firefox /usr/lib/firefox/firefox-bin',
              'host' => 'my.linux.box',
              'port' => 4444,
              'timeout' => 30000,
            ),
          ),
          $this->configuration->getSeleniumBrowserConfiguration()
        );
    }

    public function testXincludeInConfiguration()
    {
        $configurationWithXinclude = PHPUnit_Util_Configuration::getInstance(
          dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'configuration_xinclude.xml'
        );

        $this->assertConfigurationEquals(
            $this->configuration,
            $configurationWithXinclude
        );
    }

    /**
     * Asserts that the values in $actualConfiguration equal $expectedConfiguration.
     *
     * @param PHPUnit_Util_Configuration $expectedConfiguration
     * @param PHPUnit_Util_Configuration $actualConfiguration
     * @return void
     */
    protected function assertConfigurationEquals( PHPUnit_Util_Configuration $expectedConfiguration, PHPUnit_Util_Configuration $actualConfiguration )
    {
        $this->assertEquals(
            $expectedConfiguration->getFilterConfiguration(),
            $actualConfiguration->getFilterConfiguration()
        );
        $this->assertEquals(
            $expectedConfiguration->getGroupConfiguration(),
            $actualConfiguration->getGroupConfiguration()
        );
        $this->assertEquals(
            $expectedConfiguration->getListenerConfiguration(),
            $actualConfiguration->getListenerConfiguration()
        );
        $this->assertEquals(
            $expectedConfiguration->getLoggingConfiguration(),
            $actualConfiguration->getLoggingConfiguration()
        );
        $this->assertEquals(
            $expectedConfiguration->getPHPConfiguration(),
            $actualConfiguration->getPHPConfiguration()
        );
        $this->assertEquals(
            $expectedConfiguration->getPHPUnitConfiguration(),
            $actualConfiguration->getPHPUnitConfiguration()
        );
        $this->assertEquals(
            $expectedConfiguration->getSeleniumBrowserConfiguration(),
            $actualConfiguration->getSeleniumBrowserConfiguration()
        );
        $this->assertEquals(
            $expectedConfiguration->getTestSuiteConfiguration(),
            $actualConfiguration->getTestSuiteConfiguration()
        );
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.0
 */

require_once 'PHPUnit/Framework/TestCase.php';

require_once 'PHPUnit/Util/Type.php';

/**
 *
 *
 * @package    PHPUnit
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.0
 */
class Util_TypeTest extends PHPUnit_Framework_TestCase
{
    /**
     * Removes spaces in front newlines
     *
     * @param  string $string
     * @return string
     */
    public static function trimnl($string)
    {
        return preg_replace('/[ ]*\n/', "\n", $string);
    }

    public function exportProvider()
    {
        $obj2 = new stdClass;
        $obj2->foo = 'bar';

        $obj = new stdClass;
        //@codingStandardsIgnoreStart 
        $obj->null = NULL;
        //@codingStandardsIgnoreEnd 
        $obj->boolean = TRUE;
        $obj->integer = 1;
        $obj->double = 1.2;
        $obj->string = '1';
        $obj->text = "this\nis\na\nvery\nvery\nvery\nvery\nvery\nvery\rlong\n\rtext";
        $obj->object = $obj2;
        $obj->objectagain = $obj2;
        $obj->array = array('foo' => 'bar');
        $obj->self = $obj;

        $array = array(
            0 => 0,
            'null' => NULL,
            'boolean' => TRUE,
            'integer' => 1,
            'double' => 1.2,
            'string' => '1',
            'text' => "this\nis\na\nvery\nvery\nvery\nvery\nvery\nvery\rlong\n\rtext",
            'object' => $obj2,
            'objectagain' => $obj2,
            'array' => array('foo' => 'bar'),
        );

        $array['self'] = &$array;

        return array(
            array(NULL, 'null'),
            array(TRUE, 'true'),
            array(1, '1'),
            array(1.0, '1.0'),
            array(1.2, '1.2'),
            array('1', "'1'"),
            // \n\r and \r is converted to \n
            array("this\nis\na\nvery\nvery\nvery\nvery\nvery\nvery\rlong\n\rtext",
<<<EOF
'this
is
a
very
very
very
very
very
very
long
text'
EOF
            ),
            array(new stdClass, 'stdClass Object ()'),
            array($obj,
<<<EOF
stdClass Object (
    'null' => null
    'boolean' => true
    'integer' => 1
    'double' => 1.2
    'string' => '1'
    'text' => 'this
is
a
very
very
very
very
very
very
long
text'
    'object' => stdClass Object (
        'foo' => 'bar'
    )
    'objectagain' => stdClass Object (*RECURSION*)
    'array' => Array (
        'foo' => 'bar'
    )
    'self' => stdClass Object (*RECURSION*)
)
EOF
            ),
            array(array(), 'Array ()'),
            array($array,
<<<EOF
Array (
    0 => 0
    'null' => null
    'boolean' => true
    'integer' => 1
    'double' => 1.2
    'string' => '1'
    'text' => 'this
is
a
very
very
very
very
very
very
long
text'
    'object' => stdClass Object (
        'foo' => 'bar'
    )
    'objectagain' => stdClass Object (*RECURSION*)
    'array' => Array (
        'foo' => 'bar'
    )
    'self' => Array (*RECURSION*)
)
EOF
            ),
            array(
                chr(0) . chr(1) . chr(2) . chr(3) . chr(4) . chr(5),
                'Binary String: 0x000102030405'
            ),
            array(
                implode('', array_map('chr', range(0x0e, 0x1f))),
                'Binary String: 0x0e0f101112131415161718191a1b1c1d1e1f'
            ),
            array(
                chr(0x00) . chr(0x09),
                'Binary String: 0x0009'
            ),
            array(
                '',
                "''"
            ),
        );
    }

    /**
     * @dataProvider exportProvider
     */
    public function testExport($value, $expected)
    {
        $this->assertSame($expected, self::trimnl(PHPUnit_Util_Type::export($value)));
    }

    public function shortenedExportProvider()
    {
        $obj = new stdClass;
        $obj->foo = 'bar';

        $array = array(
            'foo' => 'bar',
        );

        return array(
            array(NULL, 'null'),
            array(TRUE, 'true'),
            array(1, '1'),
            array(1.0, '1.0'),
            array(1.2, '1.2'),
            array('1', "'1'"),
            // \n\r and \r is converted to \n
            array("this\nis\na\nvery\nvery\nvery\nvery\nvery\nvery\rlong\n\rtext", "'this\\nis\\na\\nvery\\nvery\\nvery\\nvery...g\\ntext'"),
            array(new stdClass, 'stdClass Object ()'),
            array($obj, 'stdClass Object (...)'),
            array(array(), 'Array ()'),
            array($array, 'Array (...)'),
        );
    }

    /**
     * @dataProvider shortenedExportProvider
     */
    public function testShortenedExport($value, $expected)
    {
        $this->assertSame($expected, self::trimnl(PHPUnit_Util_Type::shortenedExport($value)));
    }

    public function provideNonBinaryMultibyteStrings()
    {
        return array(
            array(implode('', array_map('chr', range(0x09, 0x0d))), 5),
            array(implode('', array_map('chr', range(0x20, 0x7f))), 96),
            array(implode('', array_map('chr', range(0x80, 0xff))), 128),
        );
    }


    /**
     * @dataProvider provideNonBinaryMultibyteStrings
     */
    public function testNonBinaryStringExport($value, $expectedLength)
    {
        $this->assertRegExp("~'.{{$expectedLength}}'\$~s", PHPUnit_Util_Type::export($value));
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.0
 */

/**
 *
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.0
 */
class Util_DiffTest extends PHPUnit_Framework_TestCase
{
    const REMOVED = 2;
    const ADDED = 1;
    const OLD = 0;

    /**
     * @covers PHPUnit_Util_Diff::diff
     */
    public function testComparisonErrorMessage()
    {
        $this->assertEquals(
          "--- Expected\n+++ Actual\n@@ @@\n-a\n+b\n",
          PHPUnit_Util_Diff::diff('a', 'b')
        );
    }

    /**
     * @covers PHPUnit_Util_Diff::diffToArray
     */
    public function testComparisonErrorMessage_toArray()
    {
        $diff = array();
        $diff[] = array('a', self::REMOVED);
        $diff[] = array('b', self::ADDED);

        $this->assertEquals(
          $diff,
          PHPUnit_Util_Diff::diffToArray('a', 'b')
        );
    }

    /**
     * @covers PHPUnit_Util_Diff::diff
     */
    public function testComparisonErrorStartSame()
    {
        $this->assertEquals(
          "--- Expected\n+++ Actual\n@@ @@\n-ba\n+bc\n",
          PHPUnit_Util_Diff::diff('ba', 'bc')
        );
    }

    /**
     * @covers PHPUnit_Util_Diff::diffToArray
     */
    public function testComparisonErrorStartSame_toArray()
    {
        $diff = array();
        $diff[] = array('ba', self::REMOVED);
        $diff[] = array('bc', self::ADDED);

        $this->assertEquals(
          $diff,
          PHPUnit_Util_Diff::diffToArray('ba', 'bc')
        );
    }

    /**
     * @covers PHPUnit_Util_Diff::diff
     */
    public function testComparisonErrorEndSame()
    {
        $this->assertEquals(
          "--- Expected\n+++ Actual\n@@ @@\n-ab\n+cb\n",
          PHPUnit_Util_Diff::diff('ab', 'cb')
        );
    }

    /**
     * @covers PHPUnit_Util_Diff::diffToArray
     */
    public function testComparisonErrorEndSame_toArray()
    {
        $diff = array();
        $diff[] = array('ab', self::REMOVED);
        $diff[] = array('cb', self::ADDED);

        $this->assertEquals(
          $diff,
          PHPUnit_Util_Diff::diffToArray('ab', 'cb')
        );
    }

    /**
     * @covers PHPUnit_Util_Diff::diff
     */
    public function testComparisonErrorStartAndEndSame()
    {
        $this->assertEquals(
          "--- Expected\n+++ Actual\n@@ @@\n-abc\n+adc\n",
          PHPUnit_Util_Diff::diff('abc', 'adc')
        );
    }

    /**
     * @covers PHPUnit_Util_Diff::diffToArray
     */
    public function testComparisonErrorStartAndEndSame_toArray()
    {
        $diff = array();
        $diff[] = array('abc', self::REMOVED);
        $diff[] = array('adc', self::ADDED);

        $this->assertEquals(
          $diff,
          PHPUnit_Util_Diff::diffToArray('abc', 'adc')
        );
    }

    /**
     * @covers PHPUnit_Util_Diff::diff
     */
    public function testComparisonErrorStartSameComplete()
    {
        $this->assertEquals(
          "--- Expected\n+++ Actual\n@@ @@\n-ab\n+abc\n",
          PHPUnit_Util_Diff::diff('ab', 'abc')
        );
    }

    /**
     * @covers PHPUnit_Util_Diff::diffToArray
     */
    public function testComparisonErrorStartSameComplete_toArray()
    {
        $diff = array();
        $diff[] = array('ab', self::REMOVED);
        $diff[] = array('abc', self::ADDED);

        $this->assertEquals(
          $diff,
          PHPUnit_Util_Diff::diffToArray('ab', 'abc')
        );
    }

    /**
     * @covers PHPUnit_Util_Diff::diff
     */
    public function testComparisonErrorEndSameComplete()
    {
        $this->assertEquals(
          "--- Expected\n+++ Actual\n@@ @@\n-bc\n+abc\n",
          PHPUnit_Util_Diff::diff('bc', 'abc')
        );
    }

    /**
     * @covers PHPUnit_Util_Diff::diffToArray
     */
    public function testComparisonErrorEndSameComplete_toArray()
    {
        $diff = array();
        $diff[] = array('bc', self::REMOVED);
        $diff[] = array('abc', self::ADDED);

        $this->assertEquals(
          $diff,
          PHPUnit_Util_Diff::diffToArray('bc', 'abc')
        );
    }

    /**
     * @covers PHPUnit_Util_Diff::diff
     */
    public function testComparisonErrorOverlapingMatches()
    {
        $this->assertEquals(
          "--- Expected\n+++ Actual\n@@ @@\n-abc\n+abbc\n",
          PHPUnit_Util_Diff::diff('abc', 'abbc')
        );
    }

    /**
     * @covers PHPUnit_Util_Diff::diffToArray
     */
    public function testComparisonErrorOverlapingMatches_toArray()
    {
        $diff = array();
        $diff[] = array('abc', self::REMOVED);
        $diff[] = array('abbc', self::ADDED);

        $this->assertEquals(
          $diff,
          PHPUnit_Util_Diff::diffToArray('abc', 'abbc')
        );
    }

    /**
     * @covers PHPUnit_Util_Diff::diff
     */
    public function testComparisonErrorOverlapingMatches2()
    {
        $this->assertEquals(
          "--- Expected\n+++ Actual\n@@ @@\n-abcdde\n+abcde\n",
          PHPUnit_Util_Diff::diff('abcdde', 'abcde')
        );
    }

    /**
     * @covers PHPUnit_Util_Diff::diffToArray
     */
    public function testComparisonErrorOverlapingMatches2_toArray()
    {
        $diff = array();
        $diff[] = array('abcdde', self::REMOVED);
        $diff[] = array('abcde', self::ADDED);

        $this->assertEquals(
          $diff,
          PHPUnit_Util_Diff::diffToArray('abcdde', 'abcde')
        );
    }
}
--TEST--
#783: Tests getting executed twice when using multiple groups
--FILE--
<?php
$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--group';
$_SERVER['argv'][3] = 'foo,bar';
$_SERVER['argv'][4] = 'ParentSuite';
$_SERVER['argv'][5] = dirname(__FILE__).'/783/ParentSuite.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

..

Time: %s, Memory: %sMb

OK (2 tests, 0 assertions)
<?php
class Foo_Bar_Issue684Test extends PHPUnit_Framework_TestCase
{
}
<?php
class Issue523Test extends PHPUnit_Framework_TestCase
{
    public function testAttributeEquals()
    {
        $this->assertAttributeEquals('foo', 'field', new Issue523());
    }
};

class Issue523 extends ArrayIterator
{
    protected $field = 'foo';
}
--TEST--
#684: Unable to find test class when no test methods exists
--FILE--
<?php
$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = 'Issue684Test';
$_SERVER['argv'][3] = dirname(__FILE__).'/684/Issue684Test.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

F

Time: %s, Memory: %sMb

There was 1 failure:

1) Warning
No tests found in class "Foo_Bar_Issue684Test".


FAILURES!
Tests: 1, Assertions: 0, Failures: 1.
<?php
class Issue1021Test extends PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider provider
     */
    public function testSomething($data)
    {
        $this->assertTrue($data);
    }

    /**
     * @depends testSomething
     */
    public function testSomethingElse()
    {
    }

    public function provider()
    {
        return array(array(TRUE));
    }
}
--TEST--
#578: Double printing of trace line for exceptions from notices and warnings
--FILE--
<?php
$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = 'Issue578Test';
$_SERVER['argv'][3] = dirname(__FILE__).'/578/Issue578Test.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

EEE

Time: %s, Memory: %sMb

There were 3 errors:

1) Issue578Test::testNoticesDoublePrintStackTrace
Invalid error type specified

%s/Issue578Test.php:%i

2) Issue578Test::testWarningsDoublePrintStackTrace
Invalid error type specified

%s/Issue578Test.php:%i

3) Issue578Test::testUnexpectedExceptionsPrintsCorrectly
Exception: Double printed exception

%s/Issue578Test.php:%i

FAILURES!
Tests: 3, Assertions: 0, Errors: 3.
--TEST--
#1021: Depending on a test that uses a data provider does not work
--FILE--
<?php
$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = 'Issue1021Test';
$_SERVER['argv'][3] = dirname(__FILE__).'/1021/Issue1021Test.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

..

Time: %s, Memory: %sMb

OK (2 tests, 1 assertion)
<?php
class Issue581Test extends PHPUnit_Framework_TestCase
{
    public function testExportingObjectsDoesNotBreakWindowsLineFeeds() {
        $this->assertEquals(
            (object)array(1,2,"Test\r\n",4,5,6,7,8),
            (object)array(1,2,"Test\r\n",4,1,6,7,8)
        );
    }
}
<?php
class Issue765Test extends PHPUnit_Framework_TestCase
{
    public function testDependee()
    {
        $this->assertTrue(true);
    }

    /**
     * @depends testDependee
     * @dataProvider dependentProvider
     */
    public function testDependent($a)
    {
        $this->assertTrue(true);
    }

    public function dependentProvider()
    {
        throw new Exception;
    }
}
--TEST--
GH-455: expectOutputString not working in strict mode
--FILE--
<?php

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--strict';
$_SERVER['argv'][3] = 'Issue445Test';
$_SERVER['argv'][4] = dirname(__FILE__).'/445/Issue445Test.php';

require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

..F

Time: %s, Memory: %sMb

There was 1 failure:

1) Issue445Test::testNotMatchingOutput
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'foo'
+'bar'


FAILURES!
Tests: 3, Assertions: 3, Failures: 1.

<?php
class Issue445Test extends PHPUnit_Framework_TestCase
{
    public function testOutputWithExpectationBefore()
    {
        $this->expectOutputString('test');
        print 'test';
    }

    public function testOutputWithExpectationAfter()
    {
        print 'test';
        $this->expectOutputString('test');
    }

    public function testNotMatchingOutput()
    {
        print 'bar';
        $this->expectOutputString('foo');
    }
}
--TEST--
GH-322: group commandline option should override group/exclude setting in phpunit.xml
--FILE--
<?php

$_SERVER['argv'][1] = '--configuration';
$_SERVER['argv'][2] = dirname(__FILE__).'/322/phpunit322.xml';
$_SERVER['argv'][3] = '--debug';
$_SERVER['argv'][4] = '--group';
$_SERVER['argv'][5] = 'one';
$_SERVER['argv'][6] = 'Issue322Test';
$_SERVER['argv'][7] = dirname(__FILE__).'/322/Issue322Test.php';

require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

Configuration read from %s


Starting test 'Issue322Test::testOne'.
.

Time: %s, Memory: %sMb

OK (1 test, 0 assertions)
--TEST--
GH-498: The test methods won't be run if a dataProvider throws Exception and --group is added in command line
--FILE--
<?php

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--group';
$_SERVER['argv'][3] = 'trueOnly';
$_SERVER['argv'][4] = 'Issue498Test';
$_SERVER['argv'][5] = dirname(__FILE__).'/498/Issue498Test.php';

require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

F

Time: %s, Memory: %sMb

There was 1 failure:

1) Warning
The data provider specified for Issue498Test::shouldBeFalse is invalid.
Can't create the data


FAILURES!
Tests: 1, Assertions: 0, Failures: 1.

--TEST--
GH-244: Expected Exception should support string codes
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--process-isolation';
$_SERVER['argv'][3] = 'Issue244Test';
$_SERVER['argv'][4] = dirname(__FILE__).'/244/Issue244Test.php';

require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

.FFF

Time: %s, Memory: %sMb

There were 3 failures:

1) Issue244Test::testFails
Failed asserting that '123StringCode' is equal to expected exception code 'OtherString'.

%s:%i

2) Issue244Test::testFailsTooIfExpectationIsANumber
Failed asserting that '123StringCode' is equal to expected exception code 123.

%s:%i

3) Issue244Test::testFailsTooIfExceptionCodeIsANumber
Failed asserting that 123 is equal to expected exception code '123String'.

%s:%i

FAILURES!
Tests: 4, Assertions: 8, Failures: 3.
<?php
class Issue74Test extends PHPUnit_Framework_TestCase
{
    public function testCreateAndThrowNewExceptionInProcessIsolation()
    {
        require_once __DIR__ . '/NewException.php';
        throw new NewException('Testing GH-74');
    }
}<?php
class NewException extends Exception
{
}<?php
class Issue244Test extends PHPUnit_Framework_TestCase
{
    /**
     * @expectedException Issue244Exception
     * @expectedExceptionCode 123StringCode
     */
    public function testWorks()
    {
        throw new Issue244Exception;
    }

    /**
     * @expectedException Issue244Exception
     * @expectedExceptionCode OtherString
     */
    public function testFails()
    {
        throw new Issue244Exception;
    }

    /**
     * @expectedException Issue244Exception
     * @expectedExceptionCode 123
     */
    public function testFailsTooIfExpectationIsANumber()
    {
        throw new Issue244Exception;
    }

    /**
     * @expectedException Issue244ExceptionIntCode
     * @expectedExceptionCode 123String
     */
    public function testFailsTooIfExceptionCodeIsANumber()
    {
        throw new Issue244ExceptionIntCode;
    }
}

class Issue244Exception extends Exception
{
    public function __construct()
    {
        $this->code = '123StringCode';
    }
}

class Issue244ExceptionIntCode extends Exception
{
    public function __construct()
    {
        $this->code = 123;
    }
}
<?php
class Issue503Test extends PHPUnit_Framework_TestCase
{
    public function testCompareDifferentLineEndings()
    {
        $this->assertSame(
            "foo\n",
            "foo\r\n"
        );
    }
}
<?php

class Issue498Test extends PHPUnit_Framework_TestCase
{

    /**
     * @test
     * @dataProvider shouldBeTrueDataProvider
     * @group falseOnly
     */
    public function shouldBeTrue($testData)
    {
        $this->assertTrue(true);
    }


    /**
     * @test
     * @dataProvider shouldBeFalseDataProvider
     * @group trueOnly
     */
    public function shouldBeFalse($testData)
    {
        $this->assertFalse(false);
    }

    public function shouldBeTrueDataProvider() 
    {

        //throw new Exception("Can't create the data");
        return array(
            array(true),
            array(false)
        );
    }

    public function shouldBeFalseDataProvider()
    {

        throw new Exception("Can't create the data");
        return array(
            array(true),
            array(false)
        );
    }
}
--TEST--
GH-581: PHPUnit_Util_Type::export adds extra newlines in Windows
--FILE--
<?php

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = 'Issue581Test';
$_SERVER['argv'][3] = dirname(__FILE__).'/581/Issue581Test.php';

require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

F

Time: %s, Memory: %sMb

There was 1 failure:

1) Issue581Test::testExportingObjectsDoesNotBreakWindowsLineFeeds
Failed asserting that two objects are equal.
--- Expected
+++ Actual
@@ @@
 stdClass Object (
     0 => 1
     1 => 2
     2 => 'Test\n'
     3 => 4
-    4 => 5
+    4 => 1
     5 => 6
     6 => 7
     7 => 8
 )

%s:%i

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

<phpunit>
  <testsuite name="My Test Suite">
    <file>Test.php</file>
  </testsuite>

  <groups>
    <exclude>
      <group>one</group>
    </exclude>
  </groups>
</phpunit><?php
class Issue322Test extends PHPUnit_Framework_TestCase
{
    /**
     * @group one
     */
    public function testOne()
    {
    }

    /**
     * @group two
     */
    public function testTwo()
    {
    }
}
<?php
class Issue433Test extends PHPUnit_Framework_TestCase
{
    public function testOutputWithExpectationBefore()
    {
        $this->expectOutputString('test');
        print 'test';
    }

    public function testOutputWithExpectationAfter()
    {
        print 'test';
        $this->expectOutputString('test');
    }

    public function testNotMatchingOutput()
    {
        print 'bar';
        $this->expectOutputString('foo');
    }
}
--TEST--
GH-863: Number of tests to run calculated incorrectly when --repeat is used
--FILE--
<?php

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--repeat';
$_SERVER['argv'][3] = '50';
$_SERVER['argv'][4] = 'BankAccountTest';
$_SERVER['argv'][5] = dirname(dirname(dirname(__FILE__))) . '/_files/BankAccountTest.php';

require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

...............................................................  63 / 150 ( 42%)
............................................................... 126 / 150 ( 84%)
........................

Time: %s, Memory: %sMb

OK (150 tests, 150 assertions)

--TEST--
GH-74: catchable fatal error in 3.5
--FILE--
<?php
define('PHPUNIT_TESTSUITE', TRUE);

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = '--process-isolation';
$_SERVER['argv'][3] = 'Issue74Test';
$_SERVER['argv'][4] = dirname(__FILE__).'/74/Issue74Test.php';

require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

E

Time: %s, Memory: %sMb

There was 1 error:

1) Issue74Test::testCreateAndThrowNewExceptionInProcessIsolation
NewException: Testing GH-74

%s/Tests/Regression/GitHub/74/Issue74Test.php:7
%s

FAILURES!
Tests: 1, Assertions: 0, Errors: 1.
--TEST--
GH-503: assertEquals() Line Ending Differences Are Obscure
--FILE--
<?php

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = 'Issue503Test';
$_SERVER['argv'][3] = dirname(__FILE__).'/503/Issue503Test.php';

require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

F

Time: %s, Memory: %sMb

There was 1 failure:

1) Issue503Test::testCompareDifferentLineEndings
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
 #Warning: Strings contain different line endings!
 foo

%s:%i

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

--TEST--
GH-433: expectOutputString not completely working as expected
--FILE--
<?php

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = 'Issue433Test';
$_SERVER['argv'][3] = dirname(__FILE__).'/433/Issue433Test.php';

require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

..F

Time: %s, Memory: %sMb

There was 1 failure:

1) Issue433Test::testNotMatchingOutput
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'foo'
+'bar'


FAILURES!
Tests: 3, Assertions: 3, Failures: 1.

--TEST--
GH-765: Fatal error triggered in PHPUnit when exception is thrown in data provider of a test with a dependency
--FILE--
<?php

$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = 'Issue765Test';
$_SERVER['argv'][3] = dirname(__FILE__).'/765/Issue765Test.php';

require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

.F

Time: %s, Memory: %sMb

There was 1 failure:

1) Warning
The data provider specified for Issue765Test::testDependent is invalid.


FAILURES!
Tests: 2, Assertions: 1, Failures: 1.

<?php
class Issue578Test extends PHPUnit_Framework_TestCase
{
    public function testNoticesDoublePrintStackTrace()
    {
        $this->iniSet('error_reporting', E_ALL | E_NOTICE);
        trigger_error('Stack Trace Test Notice', E_NOTICE);
    }

    public function testWarningsDoublePrintStackTrace()
    {
        $this->iniSet('error_reporting', E_ALL | E_NOTICE);
        trigger_error('Stack Trace Test Notice', E_WARNING);
    }

    public function testUnexpectedExceptionsPrintsCorrectly()
    {
        throw new Exception('Double printed exception');
    }
}
--TEST--
#523: assertAttributeEquals does not work with classes extending ArrayIterator
--FILE--
<?php
$_SERVER['argv'][1] = '--no-configuration';
$_SERVER['argv'][2] = 'Issue523Test';
$_SERVER['argv'][3] = dirname(__FILE__).'/523/Issue523Test.php';

require_once dirname(dirname(dirname(__FILE__))) . '/PHPUnit/Autoload.php';
PHPUnit_TextUI_Command::main();
?>
--EXPECTF--
PHPUnit %s by Sebastian Bergmann.

.

Time: %s, Memory: %sMb

OK (1 test, 1 assertion)
<?php
/**
* @group bar
*/
class TwoTest extends PHPUnit_Framework_TestCase
{
    public function testSomething()
    {
    }
}
<?php
require_once 'ChildSuite.php';

class ParentSuite
{
    public static function suite()
    {
        $suite = new PHPUnit_Framework_TestSuite('Parent');
        $suite->addTest(ChildSuite::suite());

        return $suite;
    }
}
<?php
/**
* @group foo
*/
class OneTest extends PHPUnit_Framework_TestCase
{
    public function testSomething()
    {
    }
}
<?php
require_once 'OneTest.php';
require_once 'TwoTest.php';

class ChildSuite
{
    public static function suite()
    {
        $suite = new PHPUnit_Framework_TestSuite('Child');
        $suite->addTestSuite('OneTest');
        $suite->addTestSuite('TwoTest');

        return $suite;
    }
}
<?php
require_once 'OneTestCase.php';

class InheritedTestCase extends OneTestCase
{
    public function test2()
    {
    }
}
<?xml version="1.0" encoding="utf-8" ?>

<phpunit backupGlobals="true"
         backupStaticAttributes="false"
         bootstrap="/path/to/bootstrap.php"
         cacheTokens="false"
         colors="false"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         forceCoversAnnotation="false"
         mapTestClassNameToCoveredClassName="false"
         printerClass="PHPUnit_TextUI_ResultPrinter"
         stopOnFailure="false"
         testSuiteLoaderClass="PHPUnit_Runner_StandardTestSuiteLoader"
         timeoutForSmallTests="1"
         timeoutForMediumTests="10"
         timeoutForLargeTests="60"
         strict="false"
		 verbose="false">
		 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
			 href="configuration.xml"
			 parse="xml"
			 xpointer="xpointer(/phpunit/testsuites)" />

  <groups>
    <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
	  	href="configuration.xml"
		parse="xml"
		xpointer="xpointer(/phpunit/groups/*)" />
  </groups>


  <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
	  href="configuration.xml"
	  parse="xml"
	  xpointer="xpointer(/phpunit/filter)" />
  <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
	  href="configuration.xml"
	  parse="xml"
	  xpointer="xpointer(/phpunit/listeners)" />
  <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
	  href="configuration.xml"
	  parse="xml"
	  xpointer="xpointer(/phpunit/logging)" />

  <php>
    <includePath>.</includePath>
    <includePath>/path/to/lib</includePath>
    <ini name="foo" value="bar"/>
    <const name="FOO" value="false"/>
    <const name="BAR" value="true"/>
    <var name="foo" value="false"/>
    <env name="foo" value="true"/>
    <post name="foo" value="bar"/>
    <get name="foo" value="bar"/>
    <cookie name="foo" value="bar"/>
    <server name="foo" value="bar"/>
    <files name="foo" value="bar"/>
    <request name="foo" value="bar"/>
  </php>

  <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
	  href="configuration.xml"
	  parse="xml"
	  xpointer="xpointer(/phpunit/selenium)" />
</phpunit>

<?php
class NonStatic
{
    public function suite()
    {
        return NULL;
    }
}
<?php
class ThrowExceptionTestCase extends PHPUnit_Framework_TestCase
{
    public function test()
    {
        throw new RuntimeException;
    }
}
<?php
class ChangeCurrentWorkingDirectoryTest extends PHPUnit_Framework_TestCase
{
    public function testSomethingThatChangesTheCwd()
    {
        chdir('../');
        $this->assertTrue(TRUE);
    }

}
<?php
class Struct
{
    public $var;

    public function __construct($var)
    {
        $this->var = $var;
    }
}
<?php
class ThrowNoExceptionTestCase extends PHPUnit_Framework_TestCase
{
    public function test()
    {
    }
}
["Mascott", "Tux", "OS", "Linux"]
{"Mascott":"Tux"}{"Mascott":"Tux"}<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
<html>
 <head>
  <title>Login</title>
  <link type="text/css" rel="Stylesheet" href="/stylesheets/screen.css">
  <script type="text/javascript">alert('Hello, world!');</script>
 </head>
 <body id="login">
  <ul id="my_ul" class="my_ul_class">
    <li class="my_li">Test LI 1</li>
    <li class="my_li">Test LI 2</li>
    <li class="my_li">Test LI 3</li>
  </ul>
  <ul id="another_ul" class="my_ul_class">
    <li class="my_li">Test LI 4</li>
  </ul>
  <div id="test_id" class="my_test_class">
    <div id="test_child_id">
      <span id="test_subchild_id">My Subchild</span>
      My Child
    </div>

    Test Id Text
  </div>
  <div id="test_children" class="children">
    My Children
    <div class="my_child">1</div>
    <div class="my_child">2</div>
    <div class="my_child">3</div>
    <div class="my_child">4</div>
  </div>
  <span class="test_class">
    Test Class Text
  </span>
  <img src="/images/login_logo.gif" alt="Login Logo">
  <input id="input_test_id" type="text" class="full">
  <div id="test_text">
    My test tag content
    <div class="another_node">more text</div>
  </div>
  <div id="test_multi_class" class="multi part class">test</div>
 </body>
</html>
<?php
class Error extends PHPUnit_Framework_TestCase
{
    protected function runTest()
    {
        throw new Exception;
    }
}
<?php

/**
 * @requires PHP 5.3
 * @requires PHPUnit 3.8
 * @requires function testFuncClass
 * @requires extension testExtClass
 */
class RequirementsClassDocBlockTest {

    /**
     * @requires PHP 5.4
     * @requires PHPUnit 3.7
     * @requires function testFuncMethod
     * @requires extension testExtMethod
     */
    public function testMethod()
    {
    }

}


<?php
class MockRunner extends PHPUnit_Runner_BaseTestRunner
{
    protected function runFailed($message)
    {
    }
}
<?php
class TemplateMethodsTest extends PHPUnit_Framework_TestCase
{
    public static function setUpBeforeClass()
    {
        print __METHOD__ . "\n";
    }

    protected function setUp()
    {
        print __METHOD__ . "\n";
    }

    protected function assertPreConditions()
    {
        print __METHOD__ . "\n";
    }

    public function testOne()
    {
        print __METHOD__ . "\n";
        $this->assertTrue(TRUE);
    }

    public function testTwo()
    {
        print __METHOD__ . "\n";
        $this->assertTrue(FALSE);
    }

    protected function assertPostConditions()
    {
        print __METHOD__ . "\n";
    }

    protected function tearDown()
    {
        print __METHOD__ . "\n";
    }

    public static function tearDownAfterClass()
    {
        print __METHOD__ . "\n";
    }

    protected function onNotSuccessfulTest(Exception $e)
    {
        print __METHOD__ . "\n";
        throw $e;
    }
}
?>
<text:p xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0">
  <draw:frame xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" svg:width="12.567708175cm" svg:height="16.848541467cm" draw:style-name="Frame">
    <draw:text-box>
      <draw:frame svg:width="12.567708175cm" svg:height="15.848541467cm" draw:style-name="Image">
        <draw:image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="Pictures/kristian.jpg"/>
      </draw:frame>
      <text:p text:style-name="Text">Image is not the same <text:sequence xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" text:ref-name="refImage1" style:num-format="1" text:formula="ooow:Image+1" text:name="Image">1</text:sequence>: Dette er en test caption</text:p>
    </draw:text-box>
  </draw:frame>
</text:p>
<?php
class ParentClassWithPrivateAttributes
{
    private static $privateStaticParentAttribute = 'foo';
    private $privateParentAttribute = 'bar';
}

class ParentClassWithProtectedAttributes extends ParentClassWithPrivateAttributes
{
    protected static $protectedStaticParentAttribute = 'foo';
    protected $protectedParentAttribute = 'bar';
}

class ClassWithNonPublicAttributes extends ParentClassWithProtectedAttributes
{
    public static $publicStaticAttribute = 'foo';
    protected static $protectedStaticAttribute = 'bar';
    protected static $privateStaticAttribute = 'baz';

    public $publicAttribute = 'foo';
    public $foo = 1;
    public $bar = 2;
    protected $protectedAttribute = 'bar';
    protected $privateAttribute = 'baz';

    public $publicArray = array('foo');
    protected $protectedArray = array('bar');
    protected $privateArray = array('baz');
}
<?php
require_once 'DependencyFailureTest.php';
require_once 'DependencySuccessTest.php';

class DependencyTestSuite
{
    public static function suite()
    {
        $suite = new PHPUnit_Framework_TestSuite('Test Dependencies');

        $suite->addTestSuite('DependencySuccessTest');
        $suite->addTestSuite('DependencyFailureTest');

        return $suite;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.0
 */

/**
 * A class with a __toString() method.
 *
 * @package    PHPUnit
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.0
 */
class ClassWithToString
{
    public function __toString()
    {
        return 'string representation';
    }
}<?php
class NotVoidTestCase extends PHPUnit_Framework_TestCase
{
}
<?php
class RequirementsTest extends PHPUnit_Framework_TestCase
{
    public function testOne()
    {
    }

    /**
     * @requires PHPUnit 1.0
     */
    public function testTwo()
    {
    }

    /**
     * @requires PHP 2.0
     */
    public function testThree()
    {
    }

    /**
     * @requires PHPUnit 2.0
     * @requires PHP 1.0
     */
    public function testFour()
    {
    }

    /**
     * @requires PHP 5.4.0RC6
     */
    public function testFive()
    {
    }

    /**
     * @requires PHP 5.4.0-alpha1
     */
    public function testSix()
    {
    }

    /**
     * @requires PHP 5.4.0beta2
     */
    public function testSeven()
    {
    }

    /**
     * @requires PHP 5.4-dev
     */
    public function testEight()
    {
    }


    /**
     * @requires function testFunc
     */
    public function testNine()
    {
    }

    /**
     * @requires extension testExt
     */
    public function testTen()
    {
    }

    /**
     * @requires PHP 99-dev
     * @requires PHPUnit 9-dev
     * @requires function testFuncOne
     * @requires function testFuncTwo
     * @requires extension testExtOne
     * @requires extension testExtTwo
     */
    public function testAllPossibleRequirements()
    {
    }

    /**
     * @requires function array_merge
     */
    public function testExistingFunction()
    {
    }

    /**
     * @requires extension spl
     */
    public function testExistingExtension()
    {
    }

    /**
     * @requires PHPUnit 1111111
     */
    public function testAlwaysSkip()
    {
    }

    /**
     * @requires PHP 9999999
     */
    public function testAlwaysSkip2()
    {
    }
}
<?php
class ExceptionTest extends PHPUnit_Framework_TestCase
{
    /**
     * Exception message
     * 
     * @var string
     */
    const ERROR_MESSAGE = 'Exception message';

    /**
     * Exception code
     * 
     * @var integer
     */
    const ERROR_CODE = 500;

    /**
     * @expectedException FooBarBaz
     */
    public function testOne()
    {
    }

    /**
     * @expectedException Foo_Bar_Baz
     */
    public function testTwo()
    {
    }

    /**
     * @expectedException Foo\Bar\Baz
     */
    public function testThree()
    {
    }

    /**
     * @expectedException ほげ
     */
    public function testFour()
    {
    }

    /**
     * @expectedException Class Message 1234
     */
    public function testFive()
    {
    }

    /**
     * @expectedException Class
     * @expectedExceptionMessage Message
     * @expectedExceptionCode 1234
     */
    public function testSix()
    {
    }

    /**
     * @expectedException Class
     * @expectedExceptionMessage Message
     * @expectedExceptionCode ExceptionCode
     */
    public function testSeven()
    {
    }

    /**
     * @expectedException Class
     * @expectedExceptionMessage Message
     * @expectedExceptionCode 0
     */
    public function testEight()
    {
    }

    /**
     * @expectedException Class
     * @expectedExceptionMessage ExceptionTest::ERROR_MESSAGE
     * @expectedExceptionCode ExceptionTest::ERROR_CODE
     */
    public function testNine()
    {
    }

    /** @expectedException Class */
    public function testSingleLine()
    {
    }

    /**
     * @expectedException Class
     * @expectedExceptionCode ExceptionTest::UNKNOWN_CODE_CONSTANT
     * @expectedExceptionMessage ExceptionTest::UNKNOWN_MESSAGE_CONSTANT
     */
    public function testUnknownConstants()
    {
    }
}
<text:p xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0">
  <draw:frame xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" svg:width="12.567708175cm" svg:height="16.848541467cm" draw:style-name="Frame">
    <draw:text-box>
      <draw:frame svg:width="12.567708175cm" svg:height="15.848541467cm" draw:style-name="Image">
        <draw:image xmlns:xlink="notthesame" xlink:href="Pictures/kristian.jpg"/>
      </draw:frame>
      <text:p text:style-name="Text">Image <text:sequence xmlns:style="notthesame" text:ref-name="refImage1" style:num-format="1" text:formula="ooow:Image+1" text:name="Image">1</text:sequence>: Dette er en test caption</text:p>
    </draw:text-box>
  </draw:frame>
</text:p>
<?php

namespace My\Space;

class ExceptionNamespaceTest extends \PHPUnit_Framework_TestCase
{
    /**
     * Exception message
     *
     * @var string
     */
    const ERROR_MESSAGE = 'Exception namespace message';

    /**
     * Exception code
     *
     * @var integer
     */
    const ERROR_CODE = 200;

    /**
     * @expectedException Class
     * @expectedExceptionMessage My\Space\ExceptionNamespaceTest::ERROR_MESSAGE
     * @expectedExceptionCode My\Space\ExceptionNamespaceTest::ERROR_CODE
     */
    public function testConstants()
    {
    }

    /**
     * @expectedException Class
     * @expectedExceptionCode My\Space\ExceptionNamespaceTest::UNKNOWN_CODE_CONSTANT
     * @expectedExceptionMessage My\Space\ExceptionNamespaceTest::UNKNOWN_MESSAGE_CONSTANT
     */
    public function testUnknownConstants()
    {
    }
}
<?php
class WasRun extends PHPUnit_Framework_TestCase
{
    public $wasRun = FALSE;

    protected function runTest()
    {
        $this->wasRun = TRUE;
    }
}
<?php
class DoubleTestCase implements PHPUnit_Framework_Test
{
    protected $testCase;

    public function __construct(PHPUnit_Framework_TestCase $testCase)
    {
        $this->testCase = $testCase;
    }

    public function count()
    {
        return 2;
    }

    public function run(PHPUnit_Framework_TestResult $result = NULL)
    {
        $result->startTest($this);

        $this->testCase->runBare();
        $this->testCase->runBare();

        $result->endTest($this, 0);
    }
}
<?php
class Success extends PHPUnit_Framework_TestCase
{
    protected function runTest()
    {
    }
}
<?xml version="1.0" encoding="utf-8" ?>

<phpunit backupGlobals="true"
         backupStaticAttributes="false"
         bootstrap="/path/to/bootstrap.php"
         cacheTokens="false"
         colors="false"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         forceCoversAnnotation="false"
         mapTestClassNameToCoveredClassName="false"
         printerClass="PHPUnit_TextUI_ResultPrinter"
         stopOnFailure="false"
         testSuiteLoaderClass="PHPUnit_Runner_StandardTestSuiteLoader"
         timeoutForSmallTests="1"
         timeoutForMediumTests="10"
         timeoutForLargeTests="60"
         strict="false"
         verbose="false">
  <testsuites>
    <testsuite name="My Test Suite">
      <directory suffix="Test.php" phpVersion="5.3.0" phpVersionOperator=">=">/path/to/files</directory>
      <file phpVersion="5.3.0" phpVersionOperator=">=">/path/to/MyTest.php</file>
    </testsuite>
  </testsuites>

  <groups>
    <include>
      <group>name</group>
    </include>
    <exclude>
      <group>name</group>
    </exclude>
  </groups>

  <filter>
    <blacklist>
      <directory suffix=".php">/path/to/files</directory>
      <file>/path/to/file</file>
      <exclude>
        <directory suffix=".php">/path/to/files</directory>
        <file>/path/to/file</file>
      </exclude>
    </blacklist>
    <whitelist addUncoveredFilesFromWhitelist="true"
               processUncoveredFilesFromWhitelist="false">
      <directory suffix=".php">/path/to/files</directory>
      <file>/path/to/file</file>
      <exclude>
        <directory suffix=".php">/path/to/files</directory>
        <file>/path/to/file</file>
      </exclude>
    </whitelist>
  </filter>

  <listeners>
    <listener class="MyListener" file="/optional/path/to/MyListener.php">
      <arguments>
        <array>
          <element key="0">
            <string>Sebastian</string>
          </element>
        </array>
        <integer>22</integer>
        <string>April</string>
        <double>19.78</double>
        <null/>
        <object class="stdClass"/>
        <file>MyTestFile.php</file>
        <directory>MyRelativePath</directory>
      </arguments>
    </listener>
    <listener class="IncludePathListener" file="ConfigurationTest.php" />
    <listener class="CompactArgumentsListener" file="/CompactArgumentsListener.php"><arguments><integer>42</integer></arguments></listener>
  </listeners>

  <logging>
    <log type="coverage-html" target="/tmp/report"
         charset="UTF-8" highlight="false"
         lowUpperBound="35" highLowerBound="70"/>
    <log type="coverage-clover" target="/tmp/clover.xml"/>
    <log type="json" target="/tmp/logfile.json"/>
    <log type="plain" target="/tmp/logfile.txt"/>
    <log type="tap" target="/tmp/logfile.tap"/>
    <log type="junit" target="/tmp/logfile.xml" logIncompleteSkipped="false"/>
    <log type="testdox-html" target="/tmp/testdox.html"/>
    <log type="testdox-text" target="/tmp/testdox.txt"/>
  </logging>

  <php>
    <includePath>.</includePath>
    <includePath>/path/to/lib</includePath>
    <ini name="foo" value="bar"/>
    <const name="FOO" value="false"/>
    <const name="BAR" value="true"/>
    <var name="foo" value="false"/>
    <env name="foo" value="true"/>
    <post name="foo" value="bar"/>
    <get name="foo" value="bar"/>
    <cookie name="foo" value="bar"/>
    <server name="foo" value="bar"/>
    <files name="foo" value="bar"/>
    <request name="foo" value="bar"/>
  </php>

  <selenium>
    <browser name="Firefox on Linux"
             browser="*firefox /usr/lib/firefox/firefox-bin"
             host="my.linux.box"
             port="4444"
             timeout="30000"/>
  </selenium>
</phpunit>

<text:p xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0">
  <draw:frame xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" svg:width="12.567708175cm" svg:height="16.848541467cm" draw:style-name="Frame">
    <draw:text-box>
      <draw:frame svg:width="12.567708175cm" svg:height="15.848541467cm" draw:style-name="Image">
        <draw:image/>
      </draw:frame>
      <text:p text:style-name="Text">Image <text:sequence xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" text:ref-name="refImage1" style:num-format="1" text:formula="ooow:Image+1" text:name="Image">1</text:sequence>: Dette er en test caption</text:p>
    </draw:text-box>
  </draw:frame>
</text:p>
<?php
class ExceptionInTearDownTest extends PHPUnit_Framework_TestCase
{
    public $setUp = FALSE;
    public $assertPreConditions = FALSE;
    public $assertPostConditions = FALSE;
    public $tearDown = FALSE;
    public $testSomething = FALSE;

    protected function setUp()
    {
        $this->setUp = TRUE;
    }

    protected function assertPreConditions()
    {
        $this->assertPreConditions = TRUE;
    }

    public function testSomething()
    {
        $this->testSomething = TRUE;
    }

    protected function assertPostConditions()
    {
        $this->assertPostConditions = TRUE;
    }

    protected function tearDown()
    {
        $this->tearDown = TRUE;
        throw new Exception;
    }
}
<?php
class NoArgTestCaseTest extends PHPUnit_Framework_TestCase
{
    public function testNothing()
    {
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2002-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2002-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.3.0
 */

require_once 'PHPUnit/Framework/TestCase.php';
require_once 'BankAccount.php';

/**
 * Tests for the BankAccount class.
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2002-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.3.0
 */
class BankAccountWithCustomExtensionTest extends PHPUnit_Framework_TestCase
{
    protected $ba;

    protected function setUp()
    {
        $this->ba = new BankAccount;
    }

    /**
     * @covers BankAccount::getBalance
     * @group balanceIsInitiallyZero
     * @group specification
     */
    public function testBalanceIsInitiallyZero()
    {
        $this->assertEquals(0, $this->ba->getBalance());
    }

    /**
     * @covers BankAccount::withdrawMoney
     * @group balanceCannotBecomeNegative
     * @group specification
     */
    public function testBalanceCannotBecomeNegative()
    {
        try {
            $this->ba->withdrawMoney(1);
        }

        catch (BankAccountException $e) {
            $this->assertEquals(0, $this->ba->getBalance());

            return;
        }

        $this->fail();
    }

    /**
     * @covers BankAccount::depositMoney
     * @group balanceCannotBecomeNegative
     * @group specification
     */
    public function testBalanceCannotBecomeNegative2()
    {
        try {
            $this->ba->depositMoney(-1);
        }

        catch (BankAccountException $e) {
            $this->assertEquals(0, $this->ba->getBalance());

            return;
        }

        $this->fail();
    }

    /**
     * @covers BankAccount::getBalance
     * @covers BankAccount::depositMoney
     * @covers BankAccount::withdrawMoney
     * @group balanceCannotBecomeNegative
     */
    /*
    public function testDepositingAndWithdrawingMoneyWorks()
    {
        $this->assertEquals(0, $this->ba->getBalance());
        $this->ba->depositMoney(1);
        $this->assertEquals(1, $this->ba->getBalance());
        $this->ba->withdrawMoney(1);
        $this->assertEquals(0, $this->ba->getBalance());
    }
    */
}
<text:p xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0">
  <draw:frame xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" svg:width="12.567708175cm" svg:height="16.848541467cm" draw:style-name="Frame">
    <draw:text-box>
	textnode
      <draw:frame svg:width="12.567708175cm" svg:height="15.848541467cm" draw:style-name="Image">
        <draw:image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="Pictures/kristian.jpg"/> textnode
      </draw:frame>
	  textnode
      <text:p text:style-name="Text">Image <text:sequence xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" text:ref-name="refImage1" style:num-format="1" text:formula="ooow:Image+1" text:name="Image">1</text:sequence>: Dette er en test caption</text:p>
	  textnode
    </draw:text-box>
  </draw:frame>
</text:p>
<bar/>
<?php
class ExceptionInSetUpTest extends PHPUnit_Framework_TestCase
{
    public $setUp = FALSE;
    public $assertPreConditions = FALSE;
    public $assertPostConditions = FALSE;
    public $tearDown = FALSE;
    public $testSomething = FALSE;

    protected function setUp()
    {
        $this->setUp = TRUE;
        throw new Exception;
    }

    protected function assertPreConditions()
    {
        $this->assertPreConditions = TRUE;
    }

    public function testSomething()
    {
        $this->testSomething = TRUE;
    }

    protected function assertPostConditions()
    {
        $this->assertPostConditions = TRUE;
    }

    protected function tearDown()
    {
        $this->tearDown = TRUE;
    }
}
<?php
class MultiDependencyTest extends PHPUnit_Framework_TestCase
{
    public function testOne()
    {
        return 'foo';
    }

    public function testTwo()
    {
        return 'bar';
    }

    /**
     * @depends testOne
     * @depends testTwo
     */
    public function testThree($a, $b)
    {
        $this->assertEquals('foo', $a);
        $this->assertEquals('bar', $b);
    }
}
<?php
class NoTestCases extends PHPUnit_Framework_TestCase
{
    public function noTestCase()
    {
    }
}
<?php
class SampleClass
{
    public $a;
    protected $b;
    protected $c;

    public function __construct($a, $b, $c)
    {
        $this->a = $a;
        $this->b = $b;
        $this->c = $c;
    }
}
FOO
<?php
class EmptyTestCaseTest extends PHPUnit_Framework_TestCase
{
}
<?php
abstract class AbstractTest extends PHPUnit_Framework_TestCase
{
    public function testOne()
    {
    }
}
<?php
class ExceptionInAssertPostConditionsTest extends PHPUnit_Framework_TestCase
{
    public $setUp = FALSE;
    public $assertPreConditions = FALSE;
    public $assertPostConditions = FALSE;
    public $tearDown = FALSE;
    public $testSomething = FALSE;

    protected function setUp()
    {
        $this->setUp = TRUE;
    }

    protected function assertPreConditions()
    {
        $this->assertPreConditions = TRUE;
    }

    public function testSomething()
    {
        $this->testSomething = TRUE;
    }

    protected function assertPostConditions()
    {
        $this->assertPostConditions = TRUE;
        throw new Exception;
    }

    protected function tearDown()
    {
        $this->tearDown = TRUE;
    }
}
<?php
class ExceptionInTest extends PHPUnit_Framework_TestCase
{
    public $setUp = FALSE;
    public $assertPreConditions = FALSE;
    public $assertPostConditions = FALSE;
    public $tearDown = FALSE;
    public $testSomething = FALSE;

    protected function setUp()
    {
        $this->setUp = TRUE;
    }

    protected function assertPreConditions()
    {
        $this->assertPreConditions = TRUE;
    }

    public function testSomething()
    {
        $this->testSomething = TRUE;
        throw new Exception;
    }

    protected function assertPostConditions()
    {
        $this->assertPostConditions = TRUE;
    }

    protected function tearDown()
    {
        $this->tearDown = TRUE;
    }
}
<?php 
class ExceptionStackTestException extends Exception { }

class ExceptionStackTest extends PHPUnit_Framework_TestCase
{
    public function testPrintingChildException()
    {
        try {
            $this->assertEquals(array(1), array(2), 'message');
        } catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $message = $e->getMessage() . "\n" . $e->getComparisonFailure()->getDiff();
            throw new ExceptionStackTestException("Child exception\n$message", 101, $e);
        }
    }

    public function testNestedExceptions()
    {
        $exceptionThree = new Exception('Three');
        $exceptionTwo = new InvalidArgumentException('Two', 0, $exceptionThree);
        $exceptionOne = new Exception('One', 0, $exceptionTwo);
        throw $exceptionOne;
    }
}
<?php
class NoTestCaseClass
{
}
<?php
class DependencyFailureTest extends PHPUnit_Framework_TestCase
{
    public function testOne()
    {
        $this->fail();
    }

    /**
     * @depends testOne
     */
    public function testTwo()
    {
    }

    /**
     * @depends testTwo
     */
    public function testThree()
    {
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.3.0
 */

class BankAccountException extends RuntimeException {}

/**
 * A bank account.
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.3.0
 */
class BankAccount
{
    /**
     * The bank account's balance.
     *
     * @var    float
     */
    protected $balance = 0;

    /**
     * Returns the bank account's balance.
     *
     * @return float
     */
    public function getBalance()
    {
        return $this->balance;
    }

    /**
     * Sets the bank account's balance.
     *
     * @param  float $balance
     * @throws BankAccountException
     */
    protected function setBalance($balance)
    {
        if ($balance >= 0) {
            $this->balance = $balance;
        } else {
            throw new BankAccountException;
        }
    }

    /**
     * Deposits an amount of money to the bank account.
     *
     * @param  float $balance
     * @throws BankAccountException
     */
    public function depositMoney($balance)
    {
        $this->setBalance($this->getBalance() + $balance);

        return $this->getBalance();
    }

    /**
     * Withdraws an amount of money from the bank account.
     *
     * @param  float $balance
     * @throws BankAccountException
     */
    public function withdrawMoney($balance)
    {
        $this->setBalance($this->getBalance() - $balance);

        return $this->getBalance();
    }
}
<?php
require_once 'AbstractTest.php';

class ConcreteTest extends AbstractTest
{
    public function testTwo()
    {
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.0
 */

/**
 * A book.
 *
 * @package    PHPUnit
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.0
 */
class Book
{
    // the order of properties is important for testing the cycle!
    public $author = NULL;
}
<?php
class FailureTest extends PHPUnit_Framework_TestCase
{
    public function testAssertArrayEqualsArray()
    {
        $this->assertEquals(array(1), array(2), 'message');
    }

    public function testAssertIntegerEqualsInteger()
    {
        $this->assertEquals(1, 2, 'message');
    }

    public function testAssertObjectEqualsObject()
    {
        $a = new StdClass;
        $a->foo = 'bar';

        $b = new StdClass;
        $b->bar = 'foo';

        $this->assertEquals($a, $b, 'message');
    }

    public function testAssertNullEqualsString()
    {
        $this->assertEquals(NULL, 'bar', 'message');
    }

    public function testAssertStringEqualsString()
    {
        $this->assertEquals('foo', 'bar', 'message');
    }

    public function testAssertTextEqualsText()
    {
        $this->assertEquals("foo\nbar\n", "foo\nbaz\n", 'message');
    }

    public function testAssertStringMatchesFormat()
    {
        $this->assertStringMatchesFormat('*%s*', '**', 'message');
    }

    public function testAssertNumericEqualsNumeric()
    {
        $this->assertEquals(1, 2, 'message');
    }

    public function testAssertTextSameText()
    {
        $this->assertSame('foo', 'bar', 'message');
    }

    public function testAssertObjectSameObject()
    {
        $this->assertSame(new StdClass, new StdClass, 'message');
    }

    public function testAssertObjectSameNull()
    {
        $this->assertSame(new StdClass, NULL, 'message');
    }

    public function testAssertFloatSameFloat()
    {
        $this->assertSame(1.0, 1.5, 'message');
    }

    // Note that due to the implementation of this assertion it counts as 2 asserts
    public function testAssertStringMatchesFormatFile()
    {
        $this->assertStringMatchesFormatFile(__DIR__ . '/expectedFileFormat.txt', '...BAR...');
    }

}
<text:p xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0">
  <draw:frame xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" svg:width="12.567708175cm" svg:height="16.848541467cm" draw:style-name="Frame">
    <draw:text-box>
      <draw:frame svg:width="12.567708175cm" svg:height="15.848541467cm" draw:style-name="Image">
        <draw:image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="Pictures/kristian.jpg"/>
      </draw:frame>
    </draw:text-box>
  </draw:frame>
</text:p>
<?php
class Singleton
{
    private static $uniqueInstance = NULL;

    protected function __construct()
    {
    }

    private final function __clone()
    {
    }

    public static function getInstance()
    {
        if (self::$uniqueInstance === NULL) {
            self::$uniqueInstance = new Singleton;
        }

        return self::$uniqueInstance;
    }
}
<?php
require_once 'OneTestCase.php';

class OverrideTestCase extends OneTestCase
{
    public function testCase($arg = '')
    {
    }
}
<?php
class TestIterator implements Iterator
{
    protected $array;
    protected $position;

    public function __construct($array = array())
    {
        $this->array = $array;
    }

    public function rewind()
    {
        $this->position = 0;
    }

    public function valid()
    {
        return $this->position < count($this->array);
    }

    public function key()
    {
        return $this->position;
    }

    public function current()
    {
        return $this->array[$this->position];
    }

    public function next()
    {
        $this->position++;
    }
}
<text:p xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0">
  <draw:frame xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" svg:width="12.567708175cm" svg:height="16.848541467cm" draw:style-name="Frame">
    <draw:text-box>
      <draw:frame svg:width="12.567708175cm" svg:height="15.848541467cm" draw:style-name="Image">
        <draw:image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="Pictures/kristian.jpg"/>
      </draw:frame>
      <text:p text:style-name="Text">Image <text:sequence xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" text:ref-name="refImage1" style:num-format="1" text:formula="ooow:Image+1" text:name="Image">1</text:sequence>: Dette er en test caption</text:p>
    </draw:text-box>
  </draw:frame>
</text:p>
<?php
class IncompleteTest extends PHPUnit_Framework_TestCase
{
    public function testIncomplete()
    {
        $this->markTestIncomplete('Test incomplete');
    }
}
<?php
class StackTest extends PHPUnit_Framework_TestCase
{
    public function testPush()
    {
        $stack = array();
        $this->assertEquals(0, count($stack));

        array_push($stack, 'foo');
        $this->assertEquals('foo', $stack[count($stack)-1]);
        $this->assertEquals(1, count($stack));

        return $stack;
    }

    /**
     * @depends testPush
     */
    public function testPop(array $stack)
    {
        $this->assertEquals('foo', array_pop($stack));
        $this->assertEquals(0, count($stack));
    }
}
<foo/>
<?php
class DataProviderTest extends PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider providerMethod
     */
    public function testAdd($a, $b, $c)
    {
        $this->assertEquals($c, $a + $b);
    }

    public static function providerMethod()
    {
        return array(
          array(0, 0, 0),
          array(0, 1, 1),
          array(1, 1, 3),
          array(1, 0, 1)
        );
    }
}
<?php
class Failure extends PHPUnit_Framework_TestCase
{
    protected function runTest()
    {
        $this->fail();
    }
}
<?php
class ExceptionInAssertPreConditionsTest extends PHPUnit_Framework_TestCase
{
    public $setUp = FALSE;
    public $assertPreConditions = FALSE;
    public $assertPostConditions = FALSE;
    public $tearDown = FALSE;
    public $testSomething = FALSE;

    protected function setUp()
    {
        $this->setUp = TRUE;
    }

    protected function assertPreConditions()
    {
        $this->assertPreConditions = TRUE;
        throw new Exception;
    }

    public function testSomething()
    {
        $this->testSomething = TRUE;
    }

    protected function assertPostConditions()
    {
        $this->assertPostConditions = TRUE;
    }

    protected function tearDown()
    {
        $this->tearDown = TRUE;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.0
 */

/**
 * An author.
 *
 * @package    PHPUnit
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.0
 */
class Author
{
    // the order of properties is important for testing the cycle!
    public $books = array();

    private $name = '';

    public function __construct($name)
    {
        $this->name = $name;
    }
}<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.3.0
 */

require_once 'PHPUnit/Framework/TestCase.php';
require_once 'BankAccount.php';

/**
 * Tests for the BankAccount class.
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.3.0
 */
class BankAccountTest extends PHPUnit_Framework_TestCase
{
    protected $ba;

    protected function setUp()
    {
        $this->ba = new BankAccount;
    }

    /**
     * @covers BankAccount::getBalance
     * @group balanceIsInitiallyZero
     * @group specification
     */
    public function testBalanceIsInitiallyZero()
    {
        $this->assertEquals(0, $this->ba->getBalance());
    }

    /**
     * @covers BankAccount::withdrawMoney
     * @group balanceCannotBecomeNegative
     * @group specification
     */
    public function testBalanceCannotBecomeNegative()
    {
        try {
            $this->ba->withdrawMoney(1);
        }

        catch (BankAccountException $e) {
            $this->assertEquals(0, $this->ba->getBalance());

            return;
        }

        $this->fail();
    }

    /**
     * @covers BankAccount::depositMoney
     * @group balanceCannotBecomeNegative
     * @group specification
     */
    public function testBalanceCannotBecomeNegative2()
    {
        try {
            $this->ba->depositMoney(-1);
        }

        catch (BankAccountException $e) {
            $this->assertEquals(0, $this->ba->getBalance());

            return;
        }

        $this->fail();
    }

    /**
     * @covers BankAccount::getBalance
     * @covers BankAccount::depositMoney
     * @covers BankAccount::withdrawMoney
     * @group balanceCannotBecomeNegative
     */
    /*
    public function testDepositingAndWithdrawingMoneyWorks()
    {
        $this->assertEquals(0, $this->ba->getBalance());
        $this->ba->depositMoney(1);
        $this->assertEquals(1, $this->ba->getBalance());
        $this->ba->withdrawMoney(1);
        $this->assertEquals(0, $this->ba->getBalance());
    }
    */
}
<?php
class Calculator
{
    /**
     * @assert (0, 0) == 0
     * @assert (0, 1) == 1
     * @assert (1, 0) == 1
     * @assert (1, 1) == 2
     */
    public function add($a, $b)
    {
        return $a + $b;
    }
}
<?php

class FatalTest extends PHPUnit_Framework_TestCase
{
    public function testFatalError()
    {
        if(extension_loaded('xdebug')) {
            xdebug_disable();
        }

        non_existing_function();
    }

}
<?php
class NotPublicTestCase extends PHPUnit_Framework_TestCase
{
    public function testPublic()
    {
    }

    protected function testNotPublic()
    {
    }
}
<?php
class OutputTestCase extends PHPUnit_Framework_TestCase
{
    public function testExpectOutputStringFooActualFoo()
    {
        $this->expectOutputString('foo');
        print 'foo';
    }

    public function testExpectOutputStringFooActualBar()
    {
        $this->expectOutputString('foo');
        print 'bar';
    }

    public function testExpectOutputRegexFooActualFoo()
    {
        $this->expectOutputRegex('/foo/');
        print 'foo';
    }

    public function testExpectOutputRegexFooActualBar()
    {
        $this->expectOutputRegex('/foo/');
        print 'bar';
    }
}
<?php
class DependencySuccessTest extends PHPUnit_Framework_TestCase
{
    public function testOne()
    {
    }

    /**
     * @depends testOne
     */
    public function testTwo()
    {
    }

    /**
     * @depends DependencySuccessTest::testTwo
     */
    public function testThree()
    {
    }
}
<?php
class NothingTest extends PHPUnit_Framework_TestCase
{
    public function testNothing()
    {
    }
}
<?php
require_once 'AbstractTest.php';

class ConcreteWithMyCustomExtensionTest extends AbstractTest
{
    public function testTwo()
    {
    }
}
<?php
class OneTestCase extends PHPUnit_Framework_TestCase
{
    public function noTestCase()
    {
    }

    public function testCase($arg = '')
    {
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.6.0
 */

require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'ClassWithToString.php';

class TestClass {}
class TestClassComparator extends PHPUnit_Framework_Comparator_Object {}

/**
 *
 *
 * @package    PHPUnit
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.6.0
 */
class Framework_ComparatorTest extends PHPUnit_Framework_TestCase
{
    // Don't use other test methods than ->fail() here, because the testers tested
    // here are the foundation for the other test methods

    public function instanceProvider()
    {
        $tmpfile = tmpfile();

        return array(
            array(NULL, NULL, 'PHPUnit_Framework_Comparator_Scalar'),
            array(NULL, TRUE, 'PHPUnit_Framework_Comparator_Scalar'),
            array(TRUE, NULL, 'PHPUnit_Framework_Comparator_Scalar'),
            array(TRUE, TRUE, 'PHPUnit_Framework_Comparator_Scalar'),
            array(FALSE, FALSE, 'PHPUnit_Framework_Comparator_Scalar'),
            array(TRUE, FALSE, 'PHPUnit_Framework_Comparator_Scalar'),
            array(FALSE, TRUE, 'PHPUnit_Framework_Comparator_Scalar'),
            array('', '', 'PHPUnit_Framework_Comparator_Scalar'),
            array('0', '0', 'PHPUnit_Framework_Comparator_Numeric'),
            array('0', 0, 'PHPUnit_Framework_Comparator_Numeric'),
            array(0, '0', 'PHPUnit_Framework_Comparator_Numeric'),
            array(0, 0, 'PHPUnit_Framework_Comparator_Numeric'),
            array(1.0, 0, 'PHPUnit_Framework_Comparator_Double'),
            array(0, 1.0, 'PHPUnit_Framework_Comparator_Double'),
            array(1.0, 1.0, 'PHPUnit_Framework_Comparator_Double'),
            array(array(1), array(1), 'PHPUnit_Framework_Comparator_Array'),
            array($tmpfile, $tmpfile, 'PHPUnit_Framework_Comparator_Resource'),
            array(new stdClass, new stdClass, 'PHPUnit_Framework_Comparator_Object'),
            array(new SplObjectStorage, new SplObjectStorage, 'PHPUnit_Framework_Comparator_SplObjectStorage'),
            array(new Exception, new Exception, 'PHPUnit_Framework_Comparator_Exception'),
            array(new DOMDocument, new DOMDocument, 'PHPUnit_Framework_Comparator_DOMDocument'),
            // mixed types
            array($tmpfile, array(1), 'PHPUnit_Framework_Comparator_Type'),
            array(array(1), $tmpfile, 'PHPUnit_Framework_Comparator_Type'),
            array($tmpfile, '1', 'PHPUnit_Framework_Comparator_Type'),
            array('1', $tmpfile, 'PHPUnit_Framework_Comparator_Type'),
            array($tmpfile, new stdClass, 'PHPUnit_Framework_Comparator_Type'),
            array(new stdClass, $tmpfile, 'PHPUnit_Framework_Comparator_Type'),
            array(new stdClass, array(1), 'PHPUnit_Framework_Comparator_Type'),
            array(array(1), new stdClass, 'PHPUnit_Framework_Comparator_Type'),
            array(new stdClass, '1', 'PHPUnit_Framework_Comparator_Type'),
            array('1', new stdClass, 'PHPUnit_Framework_Comparator_Type'),
            array(new ClassWithToString, '1', 'PHPUnit_Framework_Comparator_Scalar'),
            array('1', new ClassWithToString, 'PHPUnit_Framework_Comparator_Scalar'),
            array(1.0, new stdClass, 'PHPUnit_Framework_Comparator_Type'),
            array(new stdClass, 1.0, 'PHPUnit_Framework_Comparator_Type'),
            array(1.0, array(1), 'PHPUnit_Framework_Comparator_Type'),
            array(array(1), 1.0, 'PHPUnit_Framework_Comparator_Type'),
        );
    }

    /**
     * @dataProvider instanceProvider
     */
    public function testGetInstance($a, $b, $expected)
    {
        $factory = new PHPUnit_Framework_ComparatorFactory;

        if (get_class($factory->getComparatorFor($a, $b)) != $expected) {
            $this->fail();
        }
    }

    public function testRegister()
    {
        $comparator = new TestClassComparator;

        $factory = new PHPUnit_Framework_ComparatorFactory;
        $factory->register($comparator);

        $a = new TestClass;
        $b = new TestClass;
        $expected = 'TestClassComparator';

        if (get_class($factory->getComparatorFor($a, $b)) != $expected) {
            $factory->unregister($comparator);
            $this->fail();
        }

        $factory->unregister($comparator);
    }

    public function testUnregister()
    {
        $comparator = new TestClassComparator;

        $factory = new PHPUnit_Framework_ComparatorFactory;
        $factory->register($comparator);
        $factory->unregister($comparator);

        $a = new TestClass;
        $b = new TestClass;
        $expected = 'PHPUnit_Framework_Comparator_Object';

        if (get_class($factory->getComparatorFor($a, $b)) != $expected) {
            var_dump(get_class($factory->getComparatorFor($a, $b)));
            $this->fail();
        }
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'Error.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'ExceptionInAssertPostConditionsTest.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'ExceptionInAssertPreConditionsTest.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'ExceptionInSetUpTest.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'ExceptionInTearDownTest.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'ExceptionInTest.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'Failure.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'NoArgTestCaseTest.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'OutputTestCase.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'RequirementsTest.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'Singleton.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'Success.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'ThrowExceptionTestCase.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'ThrowNoExceptionTestCase.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'WasRun.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'ChangeCurrentWorkingDirectoryTest.php';

$GLOBALS['a']  = 'a';
$_ENV['b']     = 'b';
$_POST['c']    = 'c';
$_GET['d']     = 'd';
$_COOKIE['e']  = 'e';
$_SERVER['f']  = 'f';
$_FILES['g']   = 'g';
$_REQUEST['h'] = 'h';
$GLOBALS['i']  = 'i';

/**
 *
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.0.0
 */
class Framework_TestCaseTest extends PHPUnit_Framework_TestCase
{
    protected $backupGlobalsBlacklist = array('i', 'singleton');

    public function testCaseToString()
    {
        $this->assertEquals(
          'Framework_TestCaseTest::testCaseToString',
          $this->toString()
        );
    }

    public function testSuccess()
    {
        $test   = new Success;
        $result = $test->run();

        $this->assertEquals(0, $result->errorCount());
        $this->assertEquals(0, $result->failureCount());
        $this->assertEquals(1, count($result));
    }

    public function testFailure()
    {
        $test   = new Failure;
        $result = $test->run();

        $this->assertEquals(0, $result->errorCount());
        $this->assertEquals(1, $result->failureCount());
        $this->assertEquals(1, count($result));
    }

    public function testError()
    {
        $test   = new Error;
        $result = $test->run();

        $this->assertEquals(1, $result->errorCount());
        $this->assertEquals(0, $result->failureCount());
        $this->assertEquals(1, count($result));
    }

    public function testExceptionInSetUp()
    {
        $test   = new ExceptionInSetUpTest('testSomething');
        $result = $test->run();

        $this->assertTrue($test->setUp);
        $this->assertFalse($test->assertPreConditions);
        $this->assertFalse($test->testSomething);
        $this->assertFalse($test->assertPostConditions);
        $this->assertTrue($test->tearDown);
    }

    public function testExceptionInAssertPreConditions()
    {
        $test   = new ExceptionInAssertPreConditionsTest('testSomething');
        $result = $test->run();

        $this->assertTrue($test->setUp);
        $this->assertTrue($test->assertPreConditions);
        $this->assertFalse($test->testSomething);
        $this->assertFalse($test->assertPostConditions);
        $this->assertTrue($test->tearDown);
    }

    public function testExceptionInTest()
    {
        $test   = new ExceptionInTest('testSomething');
        $result = $test->run();

        $this->assertTrue($test->setUp);
        $this->assertTrue($test->assertPreConditions);
        $this->assertTrue($test->testSomething);
        $this->assertFalse($test->assertPostConditions);
        $this->assertTrue($test->tearDown);
    }

    public function testExceptionInAssertPostConditions()
    {
        $test   = new ExceptionInAssertPostConditionsTest('testSomething');
        $result = $test->run();

        $this->assertTrue($test->setUp);
        $this->assertTrue($test->assertPreConditions);
        $this->assertTrue($test->testSomething);
        $this->assertTrue($test->assertPostConditions);
        $this->assertTrue($test->tearDown);
    }

    public function testExceptionInTearDown()
    {
        $test   = new ExceptionInTearDownTest('testSomething');
        $result = $test->run();

        $this->assertTrue($test->setUp);
        $this->assertTrue($test->assertPreConditions);
        $this->assertTrue($test->testSomething);
        $this->assertTrue($test->assertPostConditions);
        $this->assertTrue($test->tearDown);
    }

    public function testNoArgTestCasePasses()
    {
        $result = new PHPUnit_Framework_TestResult;
        $t      = new PHPUnit_Framework_TestSuite('NoArgTestCaseTest');

        $t->run($result);

        $this->assertEquals(1, count($result));
        $this->assertEquals(0, $result->failureCount());
        $this->assertEquals(0, $result->errorCount());
    }

    public function testWasRun()
    {
        $test = new WasRun;
        $test->run();

        $this->assertTrue($test->wasRun);
    }

    public function testException()
    {
        $test = new ThrowExceptionTestCase('test');
        $test->setExpectedException('RuntimeException');

        $result = $test->run();

        $this->assertEquals(1, count($result));
        $this->assertTrue($result->wasSuccessful());
    }

    public function testNoException()
    {
        $test = new ThrowNoExceptionTestCase('test');
        $test->setExpectedException('RuntimeException');

        $result = $test->run();

        $this->assertEquals(1, $result->failureCount());
        $this->assertEquals(1, count($result));
    }

    public function testWrongException()
    {
        $test = new ThrowExceptionTestCase('test');
        $test->setExpectedException('InvalidArgumentException');

        $result = $test->run();

        $this->assertEquals(1, $result->failureCount());
        $this->assertEquals(1, count($result));
    }

    /**
     * @backupGlobals enabled
     */
    public function testGlobalsBackupPre()
    {
        global $a;
        global $i;

        $this->assertEquals('a', $a);
        $this->assertEquals('a', $GLOBALS['a']);
        $this->assertEquals('b', $_ENV['b']);
        $this->assertEquals('c', $_POST['c']);
        $this->assertEquals('d', $_GET['d']);
        $this->assertEquals('e', $_COOKIE['e']);
        $this->assertEquals('f', $_SERVER['f']);
        $this->assertEquals('g', $_FILES['g']);
        $this->assertEquals('h', $_REQUEST['h']);
        $this->assertEquals('i', $i);
        $this->assertEquals('i', $GLOBALS['i']);

        $GLOBALS['a']   = 'aa';
        $GLOBALS['foo'] = 'bar';
        $_ENV['b']      = 'bb';
        $_POST['c']     = 'cc';
        $_GET['d']      = 'dd';
        $_COOKIE['e']   = 'ee';
        $_SERVER['f']   = 'ff';
        $_FILES['g']    = 'gg';
        $_REQUEST['h']  = 'hh';
        $GLOBALS['i']   = 'ii';

        $this->assertEquals('aa', $a);
        $this->assertEquals('aa', $GLOBALS['a']);
        $this->assertEquals('bar', $GLOBALS['foo']);
        $this->assertEquals('bb', $_ENV['b']);
        $this->assertEquals('cc', $_POST['c']);
        $this->assertEquals('dd', $_GET['d']);
        $this->assertEquals('ee', $_COOKIE['e']);
        $this->assertEquals('ff', $_SERVER['f']);
        $this->assertEquals('gg', $_FILES['g']);
        $this->assertEquals('hh', $_REQUEST['h']);
        $this->assertEquals('ii', $i);
        $this->assertEquals('ii', $GLOBALS['i']);
    }

    public function testGlobalsBackupPost()
    {
        global $a;
        global $i;

        $this->assertEquals('a', $a);
        $this->assertEquals('a', $GLOBALS['a']);
        $this->assertEquals('b', $_ENV['b']);
        $this->assertEquals('c', $_POST['c']);
        $this->assertEquals('d', $_GET['d']);
        $this->assertEquals('e', $_COOKIE['e']);
        $this->assertEquals('f', $_SERVER['f']);
        $this->assertEquals('g', $_FILES['g']);
        $this->assertEquals('h', $_REQUEST['h']);
        $this->assertEquals('ii', $i);
        $this->assertEquals('ii', $GLOBALS['i']);

        $this->assertArrayNotHasKey('foo', $GLOBALS);
    }

    /**
     * @backupGlobals enabled
     * @backupStaticAttributes enabled
     */
    public function testStaticAttributesBackupPre()
    {
        $GLOBALS['singleton'] = Singleton::getInstance();
    }

    public function testStaticAttributesBackupPost()
    {
        $this->assertNotSame($GLOBALS['singleton'], Singleton::getInstance());
    }

    public function testExpectOutputStringFooActualFoo()
    {
        $test   = new OutputTestCase('testExpectOutputStringFooActualFoo');
        $result = $test->run();

        $this->assertEquals(1, count($result));
        $this->assertTrue($result->wasSuccessful());
    }

    public function testExpectOutputStringFooActualBar()
    {
        $test   = new OutputTestCase('testExpectOutputStringFooActualBar');
        $result = $test->run();

        $this->assertEquals(1, count($result));
        $this->assertFalse($result->wasSuccessful());
    }

    public function testExpectOutputRegexFooActualFoo()
    {
        $test   = new OutputTestCase('testExpectOutputRegexFooActualFoo');
        $result = $test->run();

        $this->assertEquals(1, count($result));
        $this->assertTrue($result->wasSuccessful());
    }

    public function testExpectOutputRegexFooActualBar()
    {
        $test   = new OutputTestCase('testExpectOutputRegexFooActualBar');
        $result = $test->run();

        $this->assertEquals(1, count($result));
        $this->assertFalse($result->wasSuccessful());
    }

    public function testSkipsIfRequiresHigherVersionOfPHPUnit()
    {
        $test   = new RequirementsTest('testAlwaysSkip');
        $result = $test->run();

        $this->assertEquals(1, $result->skippedCount());
        $this->assertEquals(
          'PHPUnit 1111111 (or later) is required.',
          $test->getStatusMessage()
        );
    }

    public function testSkipsIfRequiresHigherVersionOfPHP()
    {
        $test   = new RequirementsTest('testAlwaysSkip2');
        $result = $test->run();

        $this->assertEquals(1, $result->skippedCount());
        $this->assertEquals(
          'PHP 9999999 (or later) is required.',
          $test->getStatusMessage()
        );
    }

    public function testSkipsIfRequiresNonExistingFunction()
    {
        $test   = new RequirementsTest('testNine');
        $result = $test->run();

        $this->assertEquals(1, $result->skippedCount());
        $this->assertEquals(
          'Function testFunc is required.',
          $test->getStatusMessage()
        );
    }

    public function testSkipsIfRequiresNonExistingExtension()
    {
        $test   = new RequirementsTest('testTen');
        $result = $test->run();

        $this->assertEquals(
          'Extension testExt is required.',
          $test->getStatusMessage()
        );
    }

    public function testSkipsProvidesMessagesForAllSkippingReasons()
    {
        $test   = new RequirementsTest('testAllPossibleRequirements');
        $result = $test->run();

        $this->assertEquals(
          'PHP 99-dev (or later) is required.' . PHP_EOL .
          'PHPUnit 9-dev (or later) is required.' . PHP_EOL .
          'Function testFuncOne is required.' . PHP_EOL .
          'Function testFuncTwo is required.' . PHP_EOL .
          'Extension testExtOne is required.' . PHP_EOL .
          'Extension testExtTwo is required.',
          $test->getStatusMessage()
        );
    }

    public function testRequiringAnExistingFunctionDoesNotSkip()
    {
        $test   = new RequirementsTest('testExistingFunction');
        $result = $test->run();
        $this->assertEquals(0, $result->skippedCount());
    }

    public function testRequiringAnExistingExtensionDoesNotSkip()
    {
        $test   = new RequirementsTest('testExistingExtension');
        $result = $test->run();
        $this->assertEquals(0, $result->skippedCount());
    }

    public function testCurrentWorkingDirectoryIsRestored()
    {
        $expectedCwd = getcwd();

        $test = new ChangeCurrentWorkingDirectoryTest('testSomethingThatChangesTheCwd');
        $test->run();

        $this->assertSame($expectedCwd, getcwd());
    }

}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Kuzuha SHINODA <kuzuha01@hotmail.com>
 * @copyright  2013-2013 Kuzuha SHINODA <kuzuha01@hotmail.com>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.7.20
 */

require_once dirname(dirname(dirname(__DIR__))) . '/PHPUnit/Framework/Assert/Functions.php';

/**
 *
 *
 * @package    PHPUnit
 * @author     Kuzuha SHINODA <kuzuha01@hotmail.com>
 * @copyright  2013-2013 Kuzuha SHINODA <kuzuha01@hotmail.com>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.7.20
 */
class Framework_Assert_FunctionsTest extends PHPUnit_Framework_TestCase
{

    public function testLogicalAnd()
    {
        $expected = $this->logicalAnd($this->isTrue(), $this->isFalse());
        $actual = logicalAnd($this->isTrue(), $this->isFalse());
        $this->assertSame($expected->toString(), $actual->toString());
    }

    public function testLogicalOr()
    {
        $expected = $this->logicalOr($this->isTrue(), $this->isFalse());
        $actual = logicalOr($this->isTrue(), $this->isFalse());
        $this->assertSame($expected->toString(), $actual->toString());
    }

    public function testLogicalXor()
    {
        $expected = $this->logicalXor($this->isTrue(), $this->isFalse());
        $actual = logicalXor($this->isTrue(), $this->isFalse());
        $this->assertSame($expected->toString(), $actual->toString());
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.7.20
 */

/**
 *
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.7.20
 */
class Framework_TestFailureTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers PHPUnit_Framework_TestFailure::toString
     */
    public function testToString()
    {
        $test = new self(__FUNCTION__);
        $exception = new PHPUnit_Framework_Exception('message');
        $failure = new PHPUnit_Framework_TestFailure($test, $exception);
        
        $this->assertEquals(__METHOD__ . ': message', $failure->toString());
    }
}<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'Error.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'Failure.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'Success.php';

/**
 *
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.0.0
 */
class Framework_TestListenerTest extends PHPUnit_Framework_TestCase implements PHPUnit_Framework_TestListener
{
    protected $endCount;
    protected $errorCount;
    protected $failureCount;
    protected $notImplementedCount;
    protected $skippedCount;
    protected $result;
    protected $startCount;

    public function addError(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
        $this->errorCount++;
    }

    public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time)
    {
        $this->failureCount++;
    }

    public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
        $this->notImplementedCount++;
    }

    public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time)
    {
        $this->skippedCount++;
    }

    public function startTestSuite(PHPUnit_Framework_TestSuite $suite)
    {
    }

    public function endTestSuite(PHPUnit_Framework_TestSuite $suite)
    {
    }

    public function startTest(PHPUnit_Framework_Test $test)
    {
        $this->startCount++;
    }

    public function endTest(PHPUnit_Framework_Test $test, $time)
    {
        $this->endCount++;
    }

    protected function setUp()
    {
        $this->result = new PHPUnit_Framework_TestResult;
        $this->result->addListener($this);

        $this->endCount            = 0;
        $this->failureCount        = 0;
        $this->notImplementedCount = 0;
        $this->skippedCount        = 0;
        $this->startCount          = 0;
    }

    public function testError()
    {
        $test = new Error;
        $test->run($this->result);

        $this->assertEquals(1, $this->errorCount);
        $this->assertEquals(1, $this->endCount);
    }

    public function testFailure()
    {
        $test = new Failure;
        $test->run($this->result);

        $this->assertEquals(1, $this->failureCount);
        $this->assertEquals(1, $this->endCount);
    }

    public function testStartStop()
    {
        $test = new Success;
        $test->run($this->result);

        $this->assertEquals(1, $this->startCount);
        $this->assertEquals(1, $this->endCount);
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2002-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Bastian Feder <php@bastian-feder.de>
 * @copyright  2002-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.7.0
 */

/**
 * @package    PHPUnit
 * @author     Bastian Feder <php@bastian-feder.de>
 * @copyright  2011 Bastian Feder <php@bastian-feder.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.7.0
 */
class Framework_Constraint_JsonMatchesTest extends PHPUnit_Framework_TestCase
{

    /**
     * @dataProvider evaluateDataprovider
     * @covers PHPUnit_Framework_Constraint_JsonMatches::evaluate
     * @covers PHPUnit_Framework_Constraint_JsonMatches::matches
     * @covers PHPUnit_Framework_Constraint_JsonMatches::__construct
     */
    public function testEvaluate($expected, $jsonOther, $jsonValue)
    {
        $constraint = new PHPUnit_Framework_Constraint_JsonMatches($jsonValue);
        $this->assertEquals($expected, $constraint->evaluate($jsonOther, '', TRUE));
    }

    /**
     * @covers PHPUnit_Framework_Constraint_JsonMatches::toString
     */
    public function testToString()
    {
        $jsonValue = json_encode(array('Mascott' => 'Tux'));
        $constraint = new PHPUnit_Framework_Constraint_JsonMatches($jsonValue);

        $this->assertEquals('matches JSON string "' . $jsonValue . '"', $constraint->toString());
    }


    public static function evaluateDataprovider()
    {
        return array(
            'valid JSON' => array(TRUE, json_encode(array('Mascott' => 'Tux')), json_encode(array('Mascott' => 'Tux'))),
            'error syntax' => array(FALSE, '{"Mascott"::}', json_encode(array('Mascott' => 'Tux'))),
            'error UTF-8' => array(FALSE, json_encode('\xB1\x31'), json_encode(array('Mascott' => 'Tux'))),
            'invalid JSON in class instantiation' => array(FALSE, json_encode(array('Mascott' => 'Tux')), '{"Mascott"::}'),
        );
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2002-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Bastian Feder <php@bastian-feder.de>
 * @copyright  2002-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.7.0
 */

/**
 * @package    PHPUnit
 * @author     Bastian Feder <php@bastian-feder.de>
 * @copyright  2011-2013 Bastian Feder <php@bastian-feder.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.7.0
 */
class Framework_Constraint_JsonMatches_ErrorMessageProviderTest extends PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider translateTypeToPrefixDataprovider
     * @covers PHPUnit_Framework_Constraint_JsonMatches_ErrorMessageProvider::translateTypeToPrefix
     */
    public function testTranslatTypeToPrefix($expected, $type)
    {
        $this->assertEquals(
            $expected,
            PHPUnit_Framework_Constraint_JsonMatches_ErrorMessageProvider::translateTypeToPrefix($type)
        );
    }

    /**
     * @dataProvider determineJsonErrorDataprovider
     * @covers PHPUnit_Framework_Constraint_JsonMatches_ErrorMessageProvider::determineJsonError
     */
    public function testDetermineJsonError($expected, $error, $prefix)
    {
        $this->assertEquals(
            $expected,
            PHPUnit_Framework_Constraint_JsonMatches_ErrorMessageProvider::determineJsonError(
                $error,
                $prefix
            )
        );
    }

    public static function determineJsonErrorDataprovider()
    {
        return array(
            'JSON_ERROR_NONE'  => array(
                NULL, 'json_error_none', ''
            ),
            'JSON_ERROR_DEPTH' => array(
                'Maximum stack depth exceeded', JSON_ERROR_DEPTH, ''
            ),
            'prefixed JSON_ERROR_DEPTH' => array(
                'TUX: Maximum stack depth exceeded', JSON_ERROR_DEPTH, 'TUX: '
            ),
            'JSON_ERROR_STATE_MISMatch' => array(
                'Underflow or the modes mismatch', JSON_ERROR_STATE_MISMATCH, ''
            ),
            'JSON_ERROR_CTRL_CHAR' => array(
                'Unexpected control character found', JSON_ERROR_CTRL_CHAR, ''
            ),
            'JSON_ERROR_SYNTAX' => array(
                'Syntax error, malformed JSON', JSON_ERROR_SYNTAX, ''
            ),
            'JSON_ERROR_UTF8`' => array(
                'Malformed UTF-8 characters, possibly incorrectly encoded',
                JSON_ERROR_UTF8,
                ''
            ),
            'Invalid error indicator' => array(
                'Unknown error', 55, ''
            ),
        );
    }

    public static function translateTypeToPrefixDataprovider()
    {
        return array(
            'expected' => array('Expected value JSON decode error - ', 'expected'),
            'actual' => array('Actual value JSON decode error - ', 'actual'),
            'default' => array('', ''),
        );
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'ClassWithNonPublicAttributes.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'TestIterator.php';

/**
 *
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class Framework_ConstraintTest extends PHPUnit_Framework_TestCase
{
    /**
     * Removes spaces in front of newlines
     *
     * @param  string $string
     * @return string
     */
    public static function trimnl($string)
    {
        return preg_replace('/[ ]*\n/', "\n", $string);
    }

    /**
     * @covers PHPUnit_Framework_Constraint_ArrayHasKey
     * @covers PHPUnit_Framework_Assert::arrayHasKey
     * @covers PHPUnit_Framework_Constraint::count
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintArrayHasKey()
    {
        $constraint = PHPUnit_Framework_Assert::arrayHasKey(0);

        $this->assertFalse($constraint->evaluate(array(), '', TRUE));
        $this->assertEquals('has the key 0', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate(array());
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(<<<EOF
Failed asserting that an array has the key 0.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_ArrayHasKey
     * @covers PHPUnit_Framework_Assert::arrayHasKey
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintArrayHasKey2()
    {
        $constraint = PHPUnit_Framework_Assert::arrayHasKey(0);

        try {
            $constraint->evaluate(array(), 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
custom message\nFailed asserting that an array has the key 0.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_ArrayHasKey
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::arrayHasKey
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintArrayNotHasKey()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::arrayHasKey(0)
        );

        $this->assertFalse($constraint->evaluate(array(0 => 1), '', TRUE));
        $this->assertEquals('does not have the key 0', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate(array(0 => 1));
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that an array does not have the key 0.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_ArrayHasKey
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::arrayHasKey
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintArrayNotHasKey2()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::arrayHasKey(0)
        );

        try {
            $constraint->evaluate(array(0), 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
custom message
Failed asserting that an array does not have the key 0.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_FileExists
     * @covers PHPUnit_Framework_Assert::fileExists
     * @covers PHPUnit_Framework_Constraint::count
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintFileExists()
    {
        $constraint = PHPUnit_Framework_Assert::fileExists();

        $this->assertFalse($constraint->evaluate('foo', '', TRUE));
        $this->assertEquals('file exists', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate('foo');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that file "foo" exists.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_FileExists
     * @covers PHPUnit_Framework_Assert::fileExists
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintFileExists2()
    {
        $constraint = PHPUnit_Framework_Assert::fileExists();

        try {
            $constraint->evaluate('foo', 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(<<<EOF
custom message
Failed asserting that file "foo" exists.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_FileExists
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_Assert::fileExists
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintFileNotExists()
    {
        $file = dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'ClassWithNonPublicAttributes.php';

        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::fileExists()
        );

        $this->assertFalse($constraint->evaluate($file, '', TRUE));
        $this->assertEquals('file does not exist', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate($file);
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that file "$file" does not exist.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_FileExists
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_Assert::fileExists
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintFileNotExists2()
    {
        $file = dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'ClassWithNonPublicAttributes.php';

        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::fileExists()
        );

        try {
            $constraint->evaluate($file, 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(<<<EOF
custom message
Failed asserting that file "$file" does not exist.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_GreaterThan
     * @covers PHPUnit_Framework_Assert::greaterThan
     * @covers PHPUnit_Framework_Constraint::count
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintGreaterThan()
    {
        $constraint = PHPUnit_Framework_Assert::greaterThan(1);

        $this->assertFalse($constraint->evaluate(0, '', TRUE));
        $this->assertTrue($constraint->evaluate(2, '', TRUE));
        $this->assertEquals('is greater than 1', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate(0);
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that 0 is greater than 1.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_GreaterThan
     * @covers PHPUnit_Framework_Assert::greaterThan
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintGreaterThan2()
    {
        $constraint = PHPUnit_Framework_Assert::greaterThan(1);

        try {
            $constraint->evaluate(0, 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
custom message
Failed asserting that 0 is greater than 1.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_GreaterThan
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::greaterThan
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintNotGreaterThan()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::greaterThan(1)
        );

        $this->assertTrue($constraint->evaluate(1, '', TRUE));
        $this->assertEquals('is not greater than 1', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate(2);
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that 2 is not greater than 1.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_GreaterThan
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::greaterThan
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintNotGreaterThan2()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::greaterThan(1)
        );

        try {
            $constraint->evaluate(2, 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
custom message
Failed asserting that 2 is not greater than 1.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsEqual
     * @covers PHPUnit_Framework_Constraint_GreaterThan
     * @covers PHPUnit_Framework_Constraint_Or
     * @covers PHPUnit_Framework_Assert::greaterThanOrEqual
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintGreaterThanOrEqual()
    {
        $constraint = PHPUnit_Framework_Assert::greaterThanOrEqual(1);

        $this->assertTrue($constraint->evaluate(1, '', TRUE));
        $this->assertFalse($constraint->evaluate(0, '', TRUE));
        $this->assertEquals('is equal to 1 or is greater than 1', $constraint->toString());
        $this->assertEquals(2, count($constraint));

        try {
            $constraint->evaluate(0);
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that 0 is equal to 1 or is greater than 1.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsEqual
     * @covers PHPUnit_Framework_Constraint_GreaterThan
     * @covers PHPUnit_Framework_Constraint_Or
     * @covers PHPUnit_Framework_Assert::greaterThanOrEqual
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintGreaterThanOrEqual2()
    {
        $constraint = PHPUnit_Framework_Assert::greaterThanOrEqual(1);

        try {
            $constraint->evaluate(0, 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
custom message
Failed asserting that 0 is equal to 1 or is greater than 1.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsEqual
     * @covers PHPUnit_Framework_Constraint_GreaterThan
     * @covers PHPUnit_Framework_Constraint_Or
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::greaterThanOrEqual
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintNotGreaterThanOrEqual()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::greaterThanOrEqual(1)
        );

        $this->assertFalse($constraint->evaluate(1, '', TRUE));
        $this->assertEquals('not( is equal to 1 or is greater than 1 )', $constraint->toString());
        $this->assertEquals(2, count($constraint));

        try {
            $constraint->evaluate(1);
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that not( 1 is equal to 1 or is greater than 1 ).

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsEqual
     * @covers PHPUnit_Framework_Constraint_GreaterThan
     * @covers PHPUnit_Framework_Constraint_Or
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::greaterThanOrEqual
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintNotGreaterThanOrEqual2()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::greaterThanOrEqual(1)
        );

        try {
            $constraint->evaluate(1, 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
custom message
Failed asserting that not( 1 is equal to 1 or is greater than 1 ).

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsAnything
     * @covers PHPUnit_Framework_Assert::anything
     * @covers PHPUnit_Framework_Constraint::count
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintIsAnything()
    {
        $constraint = PHPUnit_Framework_Assert::anything();

        $this->assertTrue($constraint->evaluate(NULL, '', TRUE));
        $this->assertNull($constraint->evaluate(NULL));
        $this->assertEquals('is anything', $constraint->toString());
        $this->assertEquals(0, count($constraint));
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsAnything
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::anything
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintNotIsAnything()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::anything()
        );

        $this->assertFalse($constraint->evaluate(NULL, '', TRUE));
        $this->assertEquals('is not anything', $constraint->toString());
        $this->assertEquals(0, count($constraint));

        try {
            $constraint->evaluate(NULL);
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that null is not anything.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsEqual
     * @covers PHPUnit_Framework_Assert::equalTo
     * @covers PHPUnit_Framework_Constraint::count
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintIsEqual()
    {
        $constraint = PHPUnit_Framework_Assert::equalTo(1);

        $this->assertTrue($constraint->evaluate(1, '', TRUE));
        $this->assertFalse($constraint->evaluate(0, '', TRUE));
        $this->assertEquals('is equal to 1', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate(0);
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that 0 matches expected 1.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    public function isEqualProvider()
    {
        $a = new stdClass;
        $a->foo = 'bar';
        $b = new stdClass;
        $ahash = spl_object_hash($a);
        $bhash = spl_object_hash($b);

        $c = new stdClass;
        $c->foo = 'bar';
        $c->int = 1;
        $c->array = array(0, array(1), array(2), 3);
        $c->related = new stdClass;
        $c->related->foo = "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk";
        $c->self = $c;
        $c->c = $c;
        $d = new stdClass;
        $d->foo = 'bar';
        $d->int = 2;
        $d->array = array(0, array(4), array(2), 3);
        $d->related = new stdClass;
        $d->related->foo = "a\np\nc\nd\ne\nf\ng\nh\ni\nw\nk";
        $d->self = $d;
        $d->c = $c;

        $storage1 = new SplObjectStorage;
        $storage1->attach($a);
        $storage1->attach($b);
        $storage2 = new SplObjectStorage;
        $storage2->attach($b);

        $dom1 = new DOMDocument;
        $dom1->preserveWhiteSpace = FALSE;
        $dom1->loadXML('<root></root>');
        $dom2 = new DOMDocument;
        $dom2->preserveWhiteSpace = FALSE;
        $dom2->loadXML('<root><foo/></root>');

        return array(
            array(1, 0, <<<EOF
Failed asserting that 0 matches expected 1.

EOF
            ),
            array(1.1, 0, <<<EOF
Failed asserting that 0 matches expected 1.1.

EOF
            ),
            array('a', 'b', <<<EOF
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'a'
+'b'

EOF
            ),
            array("a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk", "a\np\nc\nd\ne\nf\ng\nh\ni\nw\nk", <<<EOF
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
 'a
-b
+p

@@ @@
 i
-j
+w
 k'

EOF
            ),
            array(1, array(0), <<<EOF
Array (...) does not match expected type "integer".

EOF
            ),
            array(array(0), 1, <<<EOF
1 does not match expected type "array".

EOF
            ),
            array(array(0), array(1), <<<EOF
Failed asserting that two arrays are equal.
--- Expected
+++ Actual
@@ @@
 Array (
-    0 => 0
+    0 => 1
 )

EOF
            ),
            array(array(TRUE), array('true'), <<<EOF
Failed asserting that two arrays are equal.
--- Expected
+++ Actual
@@ @@
 Array (
-    0 => true
+    0 => 'true'
 )

EOF
            ),
            array(array(0, array(1), array(2), 3), array(0, array(4), array(2), 3), <<<EOF
Failed asserting that two arrays are equal.
--- Expected
+++ Actual
@@ @@
 Array (
     0 => 0
     1 => Array (
-        0 => 1
+        0 => 4
     )
     2 => Array (...)
     3 => 3
 )

EOF
            ),
            array($a, array(0), <<<EOF
Array (...) does not match expected type "object".

EOF
            ),
            array(array(0), $a, <<<EOF
stdClass Object (...) does not match expected type "array".

EOF
            ),
            array($a, $b, <<<EOF
Failed asserting that two objects are equal.
--- Expected
+++ Actual
@@ @@
 stdClass Object (
-    'foo' => 'bar'
 )

EOF
            ),
            array($c, $d, <<<EOF
Failed asserting that two objects are equal.
--- Expected
+++ Actual
@@ @@
 stdClass Object (
     'foo' => 'bar'
-    'int' => 1
+    'int' => 2
     'array' => Array (
         0 => 0
         1 => Array (
-            0 => 1
+            0 => 4

@@ @@
         'foo' => 'a
-        b
+        p

@@ @@
         i
-        j
+        w
         k'
     )
     'self' => stdClass Object (...)
     'c' => stdClass Object (...)
 )

EOF
            ),
            array($storage1, $storage2, <<<EOF
Failed asserting that two objects are equal.
--- Expected
+++ Actual
@@ @@
 SplObjectStorage Object (
-    '$ahash' => Array (
-        'obj' => stdClass Object (
-            'foo' => 'bar'
-        )
-        'inf' => null
-    )
     '$bhash' => Array (
         'obj' => stdClass Object ()
         'inf' => null
     )
 )

EOF
            ),
            array($dom1, $dom2, <<<EOF
Failed asserting that two DOM documents are equal.
--- Expected
+++ Actual
@@ @@
 <?xml version="1.0"?>
-<root/>
+<root>
+  <foo/>
+</root>

EOF
            ),
        );
    }

    /**
     * @dataProvider isEqualProvider
     * @covers PHPUnit_Framework_Constraint_IsEqual
     * @covers PHPUnit_Framework_Assert::equalTo
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintIsEqual2($expected, $actual, $message)
    {
        $constraint = PHPUnit_Framework_Assert::equalTo($expected);

        try {
            $constraint->evaluate($actual, 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              "custom message\n$message",
              self::trimnl(PHPUnit_Framework_TestFailure::exceptionToString($e))
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsEqual
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::equalTo
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintIsNotEqual()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::equalTo(1)
        );

        $this->assertTrue($constraint->evaluate(0, '', TRUE));
        $this->assertFalse($constraint->evaluate(1, '', TRUE));
        $this->assertEquals('is not equal to 1', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate(1);
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that 1 is not equal to 1.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsEqual
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::equalTo
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintIsNotEqual2()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::equalTo(1)
        );

        try {
            $constraint->evaluate(1, 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
custom message
Failed asserting that 1 is not equal to 1.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsIdentical
     * @covers PHPUnit_Framework_Assert::identicalTo
     * @covers PHPUnit_Framework_Constraint::count
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintIsIdentical()
    {
        $a = new stdClass;
        $b = new stdClass;

        $constraint = PHPUnit_Framework_Assert::identicalTo($a);

        $this->assertFalse($constraint->evaluate($b, '', TRUE));
        $this->assertTrue($constraint->evaluate($a, '', TRUE));
        $this->assertEquals('is identical to an object of class "stdClass"', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate($b);
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(<<<EOF
Failed asserting that two variables reference the same object.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsIdentical
     * @covers PHPUnit_Framework_Assert::identicalTo
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintIsIdentical2()
    {
        $a = new stdClass;
        $b = new stdClass;

        $constraint = PHPUnit_Framework_Assert::identicalTo($a);

        try {
            $constraint->evaluate($b, 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(<<<EOF
custom message
Failed asserting that two variables reference the same object.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsIdentical
     * @covers PHPUnit_Framework_Assert::identicalTo
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintIsIdentical3()
    {
        $constraint = PHPUnit_Framework_Assert::identicalTo('a');

        try {
            $constraint->evaluate('b', 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(<<<EOF
custom message
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-a
+b

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsIdentical
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::identicalTo
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintIsNotIdentical()
    {
        $a = new stdClass;
        $b = new stdClass;

        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::identicalTo($a)
        );

        $this->assertTrue($constraint->evaluate($b, '', TRUE));
        $this->assertFalse($constraint->evaluate($a, '', TRUE));
        $this->assertEquals('is not identical to an object of class "stdClass"', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate($a);
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(<<<EOF
Failed asserting that two variables don't reference the same object.

EOF
              ,
              self::trimnl(PHPUnit_Framework_TestFailure::exceptionToString($e))
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsIdentical
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::identicalTo
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintIsNotIdentical2()
    {
        $a = new stdClass;

        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::identicalTo($a)
        );

        try {
            $constraint->evaluate($a, 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(<<<EOF
custom message
Failed asserting that two variables don't reference the same object.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsIdentical
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::identicalTo
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintIsNotIdentical3()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::identicalTo('a')
        );

        try {
            $constraint->evaluate('a', 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(<<<EOF
custom message
Failed asserting that two strings are not identical.

EOF
              ,
              self::trimnl(PHPUnit_Framework_TestFailure::exceptionToString($e))
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsInstanceOf
     * @covers PHPUnit_Framework_Assert::isInstanceOf
     * @covers PHPUnit_Framework_Constraint::count
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintIsInstanceOf()
    {
        $constraint = PHPUnit_Framework_Assert::isInstanceOf('Exception');

        $this->assertFalse($constraint->evaluate(new stdClass, '', TRUE));
        $this->assertTrue($constraint->evaluate(new Exception, '', TRUE));
        $this->assertEquals('is instance of class "Exception"', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate(new stdClass);
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that stdClass Object () is an instance of class "Exception".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsInstanceOf
     * @covers PHPUnit_Framework_Assert::isInstanceOf
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintIsInstanceOf2()
    {
        $constraint = PHPUnit_Framework_Assert::isInstanceOf('Exception');

        try {
            $constraint->evaluate(new stdClass, 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(<<<EOF
custom message
Failed asserting that stdClass Object () is an instance of class "Exception".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsInstanceOf
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::isInstanceOf
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintIsNotInstanceOf()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::isInstanceOf('stdClass')
        );

        $this->assertFalse($constraint->evaluate(new stdClass, '', TRUE));
        $this->assertTrue($constraint->evaluate(new Exception, '', TRUE));
        $this->assertEquals('is not instance of class "stdClass"', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate(new stdClass);
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that stdClass Object () is not an instance of class "stdClass".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsInstanceOf
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::isInstanceOf
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintIsNotInstanceOf2()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::isInstanceOf('stdClass')
        );

        try {
            $constraint->evaluate(new stdClass, 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(<<<EOF
custom message
Failed asserting that stdClass Object () is not an instance of class "stdClass".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsType
     * @covers PHPUnit_Framework_Assert::isType
     * @covers PHPUnit_Framework_Constraint::count
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintIsType()
    {
        $constraint = PHPUnit_Framework_Assert::isType('string');

        $this->assertFalse($constraint->evaluate(0, '', TRUE));
        $this->assertTrue($constraint->evaluate('', '', TRUE));
        $this->assertEquals('is of type "string"', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate(new stdClass);
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(<<<EOF
Failed asserting that stdClass Object () is of type "string".

EOF
              ,
              self::trimnl(PHPUnit_Framework_TestFailure::exceptionToString($e))
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsType
     * @covers PHPUnit_Framework_Assert::isType
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintIsType2()
    {
        $constraint = PHPUnit_Framework_Assert::isType('string');

        try {
            $constraint->evaluate(new stdClass, 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(<<<EOF
custom message
Failed asserting that stdClass Object () is of type "string".

EOF
              ,
              self::trimnl(PHPUnit_Framework_TestFailure::exceptionToString($e))
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsType
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::isType
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintIsNotType()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::isType('string')
        );

        $this->assertTrue($constraint->evaluate(0, '', TRUE));
        $this->assertFalse($constraint->evaluate('', '', TRUE));
        $this->assertEquals('is not of type "string"', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate('');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that '' is not of type "string".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsType
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::isType
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintIsNotType2()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::isType('string')
        );

        try {
            $constraint->evaluate('', 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(<<<EOF
custom message
Failed asserting that '' is not of type "string".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsNull
     * @covers PHPUnit_Framework_Assert::isNull
     * @covers PHPUnit_Framework_Constraint::count
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintIsNull()
    {
        $constraint = PHPUnit_Framework_Assert::isNull();

        $this->assertFalse($constraint->evaluate(0, '', TRUE));
        $this->assertTrue($constraint->evaluate(NULL, '', TRUE));
        $this->assertEquals('is null', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate(0);
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(<<<EOF
Failed asserting that 0 is null.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsNull
     * @covers PHPUnit_Framework_Assert::isNull
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintIsNull2()
    {
        $constraint = PHPUnit_Framework_Assert::isNull();

        try {
            $constraint->evaluate(0, 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(<<<EOF
custom message
Failed asserting that 0 is null.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsNull
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::isNull
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_Constraint::count
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintIsNotNull()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::isNull()
        );

        $this->assertFalse($constraint->evaluate(NULL, '', TRUE));
        $this->assertTrue($constraint->evaluate(0, '', TRUE));
        $this->assertEquals('is not null', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate(NULL);
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(<<<EOF
Failed asserting that null is not null.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsNull
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::isNull
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintIsNotNull2()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::isNull()
        );

        try {
            $constraint->evaluate(NULL, 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(<<<EOF
custom message
Failed asserting that null is not null.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_LessThan
     * @covers PHPUnit_Framework_Assert::lessThan
     * @covers PHPUnit_Framework_Constraint::count
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintLessThan()
    {
        $constraint = PHPUnit_Framework_Assert::lessThan(1);

        $this->assertTrue($constraint->evaluate(0, '', TRUE));
        $this->assertFalse($constraint->evaluate(1, '', TRUE));
        $this->assertEquals('is less than 1', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate(1);
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that 1 is less than 1.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_LessThan
     * @covers PHPUnit_Framework_Assert::lessThan
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintLessThan2()
    {
        $constraint = PHPUnit_Framework_Assert::lessThan(1);

        try {
            $constraint->evaluate(1, 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
custom message
Failed asserting that 1 is less than 1.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_LessThan
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::lessThan
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintNotLessThan()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::lessThan(1)
        );

        $this->assertTrue($constraint->evaluate(1, '', TRUE));
        $this->assertFalse($constraint->evaluate(0, '', TRUE));
        $this->assertEquals('is not less than 1', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate(0);
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that 0 is not less than 1.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_LessThan
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::lessThan
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintNotLessThan2()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::lessThan(1)
        );

        try {
            $constraint->evaluate(0, 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
custom message
Failed asserting that 0 is not less than 1.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsEqual
     * @covers PHPUnit_Framework_Constraint_LessThan
     * @covers PHPUnit_Framework_Constraint_Or
     * @covers PHPUnit_Framework_Assert::lessThanOrEqual
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintLessThanOrEqual()
    {
        $constraint = PHPUnit_Framework_Assert::lessThanOrEqual(1);

        $this->assertTrue($constraint->evaluate(1, '', TRUE));
        $this->assertFalse($constraint->evaluate(2, '', TRUE));
        $this->assertEquals('is equal to 1 or is less than 1', $constraint->toString());
        $this->assertEquals(2, count($constraint));

        try {
            $constraint->evaluate(2);
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that 2 is equal to 1 or is less than 1.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_Callback
     */
    public function testConstraintCallback()
    {
        $closureReflect = function($parameter) {
            return $parameter;
        };

        $closureWithoutParameter = function() {
            return TRUE;
        };

        $constraint = PHPUnit_Framework_Assert::callback($closureWithoutParameter);
        $this->assertTrue($constraint->evaluate('', '', TRUE));

        $constraint = PHPUnit_Framework_Assert::callback($closureReflect);
        $this->assertTrue($constraint->evaluate(TRUE, '', TRUE));
        $this->assertFalse($constraint->evaluate(FALSE, '', TRUE));

        $callback = array($this, 'callbackReturningTrue');
        $constraint = PHPUnit_Framework_Assert::callback($callback);
        $this->assertTrue($constraint->evaluate(FALSE,  '', TRUE));

        $callback = array('Framework_ConstraintTest', 'staticCallbackReturningTrue');
        $constraint = PHPUnit_Framework_Assert::callback($callback);
        $this->assertTrue($constraint->evaluate(NULL, '', TRUE));

        $this->assertEquals('is accepted by specified callback', $constraint->toString());
    }

    /**
     * @covers PHPUnit_Framework_Constraint_Callback
     * @expectedException PHPUnit_Framework_ExpectationFailedException
     * @expectedExceptionMessage Failed asserting that 'This fails' is accepted by specified callback.
     */
    public function testConstraintCallbackFailure()
    {
        $constraint = PHPUnit_Framework_Assert::callback(function() {
            return FALSE;
        });
        $constraint->evaluate('This fails');
    }

    public function callbackReturningTrue()
    {
        return TRUE;
    }

    public static function staticCallbackReturningTrue()
    {
        return TRUE;
    }

    /**
     * @covers PHPUnit_Framework_Constraint_Callback
     * @expectedException InvalidArgumentException
     * @expectedExceptionMessage Specified callback <invalid callback> is not callable.
     */
    public function testConstraintCallbackInvalidFunctionArgument()
    {
        PHPUnit_Framework_Assert::callback('invalid callback');
    }

    /**
     * @covers PHPUnit_Framework_Constraint_Callback
     * @expectedException InvalidArgumentException
     * @expectedExceptionMessage Specified callback <empty array> is not callable.
     */
    public function testConstraintCallbackInvalidArrayArgumentWithEmptyArray()
    {
        PHPUnit_Framework_Assert::callback(array());
    }

    /**
     * @covers PHPUnit_Framework_Constraint_Callback
     * @expectedException InvalidArgumentException
     * @expectedExceptionMessage Specified callback <array without indexes 0 and 1 set> is not callable.
     */
    public function testConstraintCallbackInvalidArrayArgumentWithBadArray()
    {
        PHPUnit_Framework_Assert::callback(array(3 => 'foo'));
    }


    /**
     * @covers PHPUnit_Framework_Constraint_Callback
     * @expectedException InvalidArgumentException
     * @expectedExceptionMessage Specified callback <Framework_ConstraintTest::invalid callback> is not callable.
     */
    public function testConstraintCallbackInvalidArrayArgumentWithObject()
    {
        PHPUnit_Framework_Assert::callback(array($this, 'invalid callback'));
    }

    /**
     * @covers PHPUnit_Framework_Constraint_Callback
     * @expectedException InvalidArgumentException
     * @expectedExceptionMessage Specified callback <Framework_ConstraintTest::invalid callback> is not callable.
     */
    public function testConstraintCallbackInvalidArrayArgumentWithClassname()
    {
        PHPUnit_Framework_Assert::callback(array('Framework_ConstraintTest', 'invalid callback'));
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsEqual
     * @covers PHPUnit_Framework_Constraint_LessThan
     * @covers PHPUnit_Framework_Constraint_Or
     * @covers PHPUnit_Framework_Assert::lessThanOrEqual
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintLessThanOrEqual2()
    {
        $constraint = PHPUnit_Framework_Assert::lessThanOrEqual(1);

        try {
            $constraint->evaluate(2, 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
custom message
Failed asserting that 2 is equal to 1 or is less than 1.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsEqual
     * @covers PHPUnit_Framework_Constraint_LessThan
     * @covers PHPUnit_Framework_Constraint_Or
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::lessThanOrEqual
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintNotLessThanOrEqual()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::lessThanOrEqual(1)
        );

        $this->assertTrue($constraint->evaluate(2, '', TRUE));
        $this->assertFalse($constraint->evaluate(1, '', TRUE));
        $this->assertEquals('not( is equal to 1 or is less than 1 )', $constraint->toString());
        $this->assertEquals(2, count($constraint));

        try {
            $constraint->evaluate(1);
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that not( 1 is equal to 1 or is less than 1 ).

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsEqual
     * @covers PHPUnit_Framework_Constraint_LessThan
     * @covers PHPUnit_Framework_Constraint_Or
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::lessThanOrEqual
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintNotLessThanOrEqual2()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::lessThanOrEqual(1)
        );

        try {
            $constraint->evaluate(1, 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
custom message
Failed asserting that not( 1 is equal to 1 or is less than 1 ).

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_ClassHasAttribute
     * @covers PHPUnit_Framework_Assert::classHasAttribute
     * @covers PHPUnit_Framework_Constraint::count
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintClassHasAttribute()
    {
        $constraint = PHPUnit_Framework_Assert::classHasAttribute('privateAttribute');

        $this->assertTrue($constraint->evaluate('ClassWithNonPublicAttributes', '', TRUE));
        $this->assertFalse($constraint->evaluate('stdClass', '', TRUE));
        $this->assertEquals('has attribute "privateAttribute"', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate('stdClass');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that class "stdClass" has attribute "privateAttribute".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_ClassHasAttribute
     * @covers PHPUnit_Framework_Assert::classHasAttribute
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintClassHasAttribute2()
    {
        $constraint = PHPUnit_Framework_Assert::classHasAttribute('privateAttribute');

        try {
            $constraint->evaluate('stdClass', 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(<<<EOF
custom message
Failed asserting that class "stdClass" has attribute "privateAttribute".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_ClassHasAttribute
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::classHasAttribute
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintClassNotHasAttribute()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::classHasAttribute('privateAttribute')
        );

        $this->assertTrue($constraint->evaluate('stdClass', '', TRUE));
        $this->assertFalse($constraint->evaluate('ClassWithNonPublicAttributes', '', TRUE));
        $this->assertEquals('does not have attribute "privateAttribute"', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate('ClassWithNonPublicAttributes');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that class "ClassWithNonPublicAttributes" does not have attribute "privateAttribute".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_ClassHasAttribute
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::classHasAttribute
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintClassNotHasAttribute2()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::classHasAttribute('privateAttribute')
        );

        try {
            $constraint->evaluate('ClassWithNonPublicAttributes', 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(<<<EOF
custom message
Failed asserting that class "ClassWithNonPublicAttributes" does not have attribute "privateAttribute".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_ClassHasStaticAttribute
     * @covers PHPUnit_Framework_Assert::classHasStaticAttribute
     * @covers PHPUnit_Framework_Constraint::count
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintClassHasStaticAttribute()
    {
        $constraint = PHPUnit_Framework_Assert::classHasStaticAttribute('privateStaticAttribute');

        $this->assertTrue($constraint->evaluate('ClassWithNonPublicAttributes', '', TRUE));
        $this->assertFalse($constraint->evaluate('stdClass', '', TRUE));
        $this->assertEquals('has static attribute "privateStaticAttribute"', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate('stdClass');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that class "stdClass" has static attribute "privateStaticAttribute".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_ClassHasStaticAttribute
     * @covers PHPUnit_Framework_Assert::classHasStaticAttribute
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintClassHasStaticAttribute2()
    {
        $constraint = PHPUnit_Framework_Assert::classHasStaticAttribute('foo');

        try {
            $constraint->evaluate('stdClass', 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(<<<EOF
custom message
Failed asserting that class "stdClass" has static attribute "foo".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_ClassHasStaticAttribute
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::classHasStaticAttribute
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintClassNotHasStaticAttribute()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::classHasStaticAttribute('privateStaticAttribute')
        );

        $this->assertTrue($constraint->evaluate('stdClass', '', TRUE));
        $this->assertFalse($constraint->evaluate('ClassWithNonPublicAttributes', '', TRUE));
        $this->assertEquals('does not have static attribute "privateStaticAttribute"', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate('ClassWithNonPublicAttributes');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that class "ClassWithNonPublicAttributes" does not have static attribute "privateStaticAttribute".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_ClassHasStaticAttribute
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::classHasStaticAttribute
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintClassNotHasStaticAttribute2()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::classHasStaticAttribute('privateStaticAttribute')
        );

        try {
            $constraint->evaluate('ClassWithNonPublicAttributes', 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(<<<EOF
custom message
Failed asserting that class "ClassWithNonPublicAttributes" does not have static attribute "privateStaticAttribute".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_ObjectHasAttribute
     * @covers PHPUnit_Framework_Assert::objectHasAttribute
     * @covers PHPUnit_Framework_Constraint::count
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintObjectHasAttribute()
    {
        $constraint = PHPUnit_Framework_Assert::objectHasAttribute('privateAttribute');

        $this->assertTrue($constraint->evaluate(new ClassWithNonPublicAttributes, '', TRUE));
        $this->assertFalse($constraint->evaluate(new stdClass, '', TRUE));
        $this->assertEquals('has attribute "privateAttribute"', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate(new stdClass);
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that object of class "stdClass" has attribute "privateAttribute".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_ObjectHasAttribute
     * @covers PHPUnit_Framework_Assert::objectHasAttribute
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintObjectHasAttribute2()
    {
        $constraint = PHPUnit_Framework_Assert::objectHasAttribute('privateAttribute');

        try {
            $constraint->evaluate(new stdClass, 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(<<<EOF
custom message
Failed asserting that object of class "stdClass" has attribute "privateAttribute".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_ObjectHasAttribute
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::objectHasAttribute
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintObjectNotHasAttribute()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::objectHasAttribute('privateAttribute')
        );

        $this->assertTrue($constraint->evaluate(new stdClass, '', TRUE));
        $this->assertFalse($constraint->evaluate(new ClassWithNonPublicAttributes, '', TRUE));
        $this->assertEquals('does not have attribute "privateAttribute"', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate(new ClassWithNonPublicAttributes);
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that object of class "ClassWithNonPublicAttributes" does not have attribute "privateAttribute".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_ObjectHasAttribute
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::objectHasAttribute
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintObjectNotHasAttribute2()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::objectHasAttribute('privateAttribute')
        );

        try {
            $constraint->evaluate(new ClassWithNonPublicAttributes, 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(<<<EOF
custom message
Failed asserting that object of class "ClassWithNonPublicAttributes" does not have attribute "privateAttribute".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_PCREMatch
     * @covers PHPUnit_Framework_Assert::matchesRegularExpression
     * @covers PHPUnit_Framework_Constraint::count
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintPCREMatch()
    {
        $constraint = PHPUnit_Framework_Assert::matchesRegularExpression('/foo/');

        $this->assertFalse($constraint->evaluate('barbazbar', '', TRUE));
        $this->assertTrue($constraint->evaluate('barfoobar', '', TRUE));
        $this->assertEquals('matches PCRE pattern "/foo/"', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate('barbazbar');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that 'barbazbar' matches PCRE pattern "/foo/".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_PCREMatch
     * @covers PHPUnit_Framework_Assert::matchesRegularExpression
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintPCREMatch2()
    {
        $constraint = PHPUnit_Framework_Assert::matchesRegularExpression('/foo/');

        try {
            $constraint->evaluate('barbazbar', 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(<<<EOF
custom message
Failed asserting that 'barbazbar' matches PCRE pattern "/foo/".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_PCREMatch
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::matchesRegularExpression
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintPCRENotMatch()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::matchesRegularExpression('/foo/')
        );

        $this->assertTrue($constraint->evaluate('barbazbar', '', TRUE));
        $this->assertFalse($constraint->evaluate('barfoobar', '', TRUE));
        $this->assertEquals('does not match PCRE pattern "/foo/"', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate('barfoobar');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that 'barfoobar' does not match PCRE pattern "/foo/".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_PCREMatch
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::matchesRegularExpression
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintPCRENotMatch2()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::matchesRegularExpression('/foo/')
        );

        try {
            $constraint->evaluate('barfoobar', 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(<<<EOF
custom message
Failed asserting that 'barfoobar' does not match PCRE pattern "/foo/".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_StringMatches
     * @covers PHPUnit_Framework_Assert::matches
     * @covers PHPUnit_Framework_Constraint::count
     */
    public function testConstraintStringMatches()
    {
        $constraint = PHPUnit_Framework_Assert::matches('*%c*');
        $this->assertFalse($constraint->evaluate('**', '', TRUE));
        $this->assertTrue($constraint->evaluate('***', '', TRUE));
        $this->assertEquals('matches PCRE pattern "/^\*.\*$/s"', $constraint->toString());
        $this->assertEquals(1, count($constraint));
    }

    /**
     * @covers PHPUnit_Framework_Constraint_StringMatches
     * @covers PHPUnit_Framework_Assert::matches
     * @covers PHPUnit_Framework_Constraint::count
     */
    public function testConstraintStringMatches2()
    {
        $constraint = PHPUnit_Framework_Assert::matches('*%s*');
        $this->assertFalse($constraint->evaluate('**', '', TRUE));
        $this->assertTrue($constraint->evaluate('***', '', TRUE));
        $this->assertEquals('matches PCRE pattern "/^\*[^\r\n]+\*$/s"', $constraint->toString());
        $this->assertEquals(1, count($constraint));
    }

    /**
     * @covers PHPUnit_Framework_Constraint_StringMatches
     * @covers PHPUnit_Framework_Assert::matches
     * @covers PHPUnit_Framework_Constraint::count
     */
    public function testConstraintStringMatches3()
    {
        $constraint = PHPUnit_Framework_Assert::matches('*%i*');
        $this->assertFalse($constraint->evaluate('**', '', TRUE));
        $this->assertTrue($constraint->evaluate('*0*', '', TRUE));
        $this->assertEquals('matches PCRE pattern "/^\*[+-]?\d+\*$/s"', $constraint->toString());
        $this->assertEquals(1, count($constraint));
    }

    /**
     * @covers PHPUnit_Framework_Constraint_StringMatches
     * @covers PHPUnit_Framework_Assert::matches
     * @covers PHPUnit_Framework_Constraint::count
     */
    public function testConstraintStringMatches4()
    {
        $constraint = PHPUnit_Framework_Assert::matches('*%d*');
        $this->assertFalse($constraint->evaluate('**', '', TRUE));
        $this->assertTrue($constraint->evaluate('*0*', '', TRUE));
        $this->assertEquals('matches PCRE pattern "/^\*\d+\*$/s"', $constraint->toString());
        $this->assertEquals(1, count($constraint));
    }

    /**
     * @covers PHPUnit_Framework_Constraint_StringMatches
     * @covers PHPUnit_Framework_Assert::matches
     * @covers PHPUnit_Framework_Constraint::count
     */
    public function testConstraintStringMatches5()
    {
        $constraint = PHPUnit_Framework_Assert::matches('*%x*');
        $this->assertFalse($constraint->evaluate('**', '', TRUE));
        $this->assertTrue($constraint->evaluate('*0f0f0f*', '', TRUE));
        $this->assertEquals('matches PCRE pattern "/^\*[0-9a-fA-F]+\*$/s"', $constraint->toString());
        $this->assertEquals(1, count($constraint));
    }

    /**
     * @covers PHPUnit_Framework_Constraint_StringMatches
     * @covers PHPUnit_Framework_Assert::matches
     * @covers PHPUnit_Framework_Constraint::count
     */
    public function testConstraintStringMatches6()
    {
        $constraint = PHPUnit_Framework_Assert::matches('*%f*');
        $this->assertFalse($constraint->evaluate('**', '', TRUE));
        $this->assertTrue($constraint->evaluate('*1.0*', '', TRUE));
        $this->assertEquals('matches PCRE pattern "/^\*[+-]?\.?\d+\.?\d*(?:[Ee][+-]?\d+)?\*$/s"', $constraint->toString());
        $this->assertEquals(1, count($constraint));
    }

    /**
     * @covers PHPUnit_Framework_Constraint_StringStartsWith
     * @covers PHPUnit_Framework_Assert::stringStartsWith
     * @covers PHPUnit_Framework_Constraint::count
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintStringStartsWith()
    {
        $constraint = PHPUnit_Framework_Assert::stringStartsWith('prefix');

        $this->assertFalse($constraint->evaluate('foo', '', TRUE));
        $this->assertTrue($constraint->evaluate('prefixfoo', '', TRUE));
        $this->assertEquals('starts with "prefix"', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate('foo');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that 'foo' starts with "prefix".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_StringStartsWith
     * @covers PHPUnit_Framework_Assert::stringStartsWith
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintStringStartsWith2()
    {
        $constraint = PHPUnit_Framework_Assert::stringStartsWith('prefix');

        try {
            $constraint->evaluate('foo', 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
custom message\nFailed asserting that 'foo' starts with "prefix".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_StringStartsWith
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::stringStartsWith
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintStringStartsNotWith()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::stringStartsWith('prefix')
        );

        $this->assertTrue($constraint->evaluate('foo', '', TRUE));
        $this->assertFalse($constraint->evaluate('prefixfoo', '', TRUE));
        $this->assertEquals('starts not with "prefix"', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate('prefixfoo');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that 'prefixfoo' starts not with "prefix".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_StringStartsWith
     * @covers PHPUnit_Framework_Assert::stringStartsWith
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintStringStartsNotWith2()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::stringStartsWith('prefix')
        );

        try {
            $constraint->evaluate('prefixfoo', 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
custom message
Failed asserting that 'prefixfoo' starts not with "prefix".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_StringContains
     * @covers PHPUnit_Framework_Assert::stringContains
     * @covers PHPUnit_Framework_Constraint::count
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintStringContains()
    {
        $constraint = PHPUnit_Framework_Assert::stringContains('foo');

        $this->assertFalse($constraint->evaluate('barbazbar', '', TRUE));
        $this->assertTrue($constraint->evaluate('barfoobar', '', TRUE));
        $this->assertEquals('contains "foo"', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate('barbazbar');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that 'barbazbar' contains "foo".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_StringContains
     * @covers PHPUnit_Framework_Assert::stringContains
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintStringContains2()
    {
        $constraint = PHPUnit_Framework_Assert::stringContains('foo');

        try {
            $constraint->evaluate('barbazbar', 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
custom message
Failed asserting that 'barbazbar' contains "foo".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_StringContains
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::stringContains
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintStringNotContains()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::stringContains('foo')
        );

        $this->assertTrue($constraint->evaluate('barbazbar', '', TRUE));
        $this->assertFalse($constraint->evaluate('barfoobar', '', TRUE));
        $this->assertEquals('does not contain "foo"', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate('barfoobar');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that 'barfoobar' does not contain "foo".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_StringContains
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::stringContains
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintStringNotContains2()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::stringContains('foo')
        );

        try {
            $constraint->evaluate('barfoobar', 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
custom message
Failed asserting that 'barfoobar' does not contain "foo".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_StringEndsWith
     * @covers PHPUnit_Framework_Assert::stringEndsWith
     * @covers PHPUnit_Framework_Constraint::count
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintStringEndsWith()
    {
        $constraint = PHPUnit_Framework_Assert::stringEndsWith('suffix');

        $this->assertFalse($constraint->evaluate('foo', '', TRUE));
        $this->assertTrue($constraint->evaluate('foosuffix', '', TRUE));
        $this->assertEquals('ends with "suffix"', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate('foo');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that 'foo' ends with "suffix".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_StringEndsWith
     * @covers PHPUnit_Framework_Assert::stringEndsWith
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintStringEndsWith2()
    {
        $constraint = PHPUnit_Framework_Assert::stringEndsWith('suffix');

        try {
            $constraint->evaluate('foo', 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
custom message
Failed asserting that 'foo' ends with "suffix".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_StringEndsWith
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::stringEndsWith
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintStringEndsNotWith()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::stringEndsWith('suffix')
        );

        $this->assertTrue($constraint->evaluate('foo', '', TRUE));
        $this->assertFalse($constraint->evaluate('foosuffix', '', TRUE));
        $this->assertEquals('ends not with "suffix"', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate('foosuffix');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that 'foosuffix' ends not with "suffix".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_StringEndsWith
     * @covers PHPUnit_Framework_Assert::stringEndsWith
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintStringEndsNotWith2()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::stringEndsWith('suffix')
        );

        try {
            $constraint->evaluate('foosuffix', 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
custom message
Failed asserting that 'foosuffix' ends not with "suffix".

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_TraversableContains
     * @covers PHPUnit_Framework_Constraint::count
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintArrayContains()
    {
        $constraint = new PHPUnit_Framework_Constraint_TraversableContains('foo');

        $this->assertFalse($constraint->evaluate(array('bar'), '', TRUE));
        $this->assertTrue($constraint->evaluate(array('foo'), '', TRUE));
        $this->assertEquals("contains 'foo'", $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate(array('bar'));
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that an array contains 'foo'.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_TraversableContains
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintArrayContains2()
    {
        $constraint = new PHPUnit_Framework_Constraint_TraversableContains('foo');

        try {
            $constraint->evaluate(array('bar'), 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
custom message
Failed asserting that an array contains 'foo'.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_TraversableContains
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintArrayNotContains()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          new PHPUnit_Framework_Constraint_TraversableContains('foo')
        );

        $this->assertTrue($constraint->evaluate(array('bar'), '', TRUE));
        $this->assertFalse($constraint->evaluate(array('foo'), '', TRUE));
        $this->assertEquals("does not contain 'foo'", $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate(array('foo'));
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that an array does not contain 'foo'.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_TraversableContains
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintArrayNotContains2()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          new PHPUnit_Framework_Constraint_TraversableContains('foo')
        );

        try {
            $constraint->evaluate(array('foo'), 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
custom message
Failed asserting that an array does not contain 'foo'.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_TraversableContains
     * @covers PHPUnit_Framework_Constraint::count
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintSplObjectStorageContains()
    {
        $object     = new StdClass;
        $constraint = new PHPUnit_Framework_Constraint_TraversableContains($object);
        $this->assertEquals("contains stdClass Object ()", $constraint->toString());

        $storage = new SplObjectStorage;
        $this->assertFalse($constraint->evaluate($storage, '', TRUE));

        $storage->attach($object);
        $this->assertTrue($constraint->evaluate($storage, '', TRUE));

        try {
            $constraint->evaluate(new SplObjectStorage);
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that an iterator contains stdClass Object ().

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_TraversableContains
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintSplObjectStorageContains2()
    {
        $object     = new StdClass;
        $constraint = new PHPUnit_Framework_Constraint_TraversableContains($object);

        try {
            $constraint->evaluate(new SplObjectStorage, 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
custom message
Failed asserting that an iterator contains stdClass Object ().

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::attributeEqualTo
     * @covers PHPUnit_Framework_Constraint_Attribute
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testAttributeEqualTo()
    {
        $object     = new ClassWithNonPublicAttributes;
        $constraint = PHPUnit_Framework_Assert::attributeEqualTo('foo', 1);

        $this->assertTrue($constraint->evaluate($object, '', TRUE));
        $this->assertEquals('attribute "foo" is equal to 1', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        $constraint = PHPUnit_Framework_Assert::attributeEqualTo('foo', 2);

        $this->assertFalse($constraint->evaluate($object, '', TRUE));

        try {
            $constraint->evaluate($object);
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that attribute "foo" is equal to 2.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::attributeEqualTo
     * @covers PHPUnit_Framework_Constraint_Attribute
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testAttributeEqualTo2()
    {
        $object     = new ClassWithNonPublicAttributes;
        $constraint = PHPUnit_Framework_Assert::attributeEqualTo('foo', 2);

        try {
            $constraint->evaluate($object, 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
custom message\nFailed asserting that attribute "foo" is equal to 2.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::attributeEqualTo
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_Constraint_Attribute
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testAttributeNotEqualTo()
    {
        $object     = new ClassWithNonPublicAttributes;
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::attributeEqualTo('foo', 2)
        );

        $this->assertTrue($constraint->evaluate($object, '', TRUE));
        $this->assertEquals('attribute "foo" is not equal to 2', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::attributeEqualTo('foo', 1)
        );

        $this->assertFalse($constraint->evaluate($object, '', TRUE));

        try {
            $constraint->evaluate($object);
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that attribute "foo" is not equal to 1.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::attributeEqualTo
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_Constraint_Attribute
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testAttributeNotEqualTo2()
    {
        $object     = new ClassWithNonPublicAttributes;
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          PHPUnit_Framework_Assert::attributeEqualTo('foo', 1)
        );

        try {
            $constraint->evaluate($object, 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
custom message\nFailed asserting that attribute "foo" is not equal to 1.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsEmpty
     * @covers PHPUnit_Framework_Constraint::count
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintIsEmpty()
    {
        $constraint = new PHPUnit_Framework_Constraint_IsEmpty;

        $this->assertFalse($constraint->evaluate(array('foo'), '', TRUE));
        $this->assertTrue($constraint->evaluate(array(), '', TRUE));
        $this->assertEquals('is empty', $constraint->toString());
        $this->assertEquals(1, count($constraint));

        try {
            $constraint->evaluate(array('foo'));
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that an array is empty.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_IsEmpty
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintIsEmpty2()
    {
        $constraint = new PHPUnit_Framework_Constraint_IsEmpty;

        try {
            $constraint->evaluate(array('foo'), 'custom message');
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
custom message\nFailed asserting that an array is empty.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_Count
     */
    public function testConstraintCountWithAnArray()
    {
        $constraint = new PHPUnit_Framework_Constraint_Count(5);

        $this->assertTrue($constraint->evaluate(array(1,2,3,4,5), '', TRUE));
        $this->assertFalse($constraint->evaluate(array(1,2,3,4), '', TRUE));
    }

    /**
     * @covers PHPUnit_Framework_Constraint_Count
     */
    public function testConstraintCountWithAnIteratorWhichDoesNotImplementCountable()
    {
        $constraint = new PHPUnit_Framework_Constraint_Count(5);

        $this->assertTrue($constraint->evaluate(new TestIterator(array(1,2,3,4,5)), '', TRUE));
        $this->assertFalse($constraint->evaluate(new TestIterator(array(1,2,3,4)), '', TRUE));
    }

    /**
     * @covers PHPUnit_Framework_Constraint_Count
     */
    public function testConstraintCountWithAnObjectImplementingCountable()
    {
        $constraint = new PHPUnit_Framework_Constraint_Count(5);

        $this->assertTrue($constraint->evaluate(new ArrayObject(array(1,2,3,4,5)), '', TRUE));
        $this->assertFalse($constraint->evaluate(new ArrayObject(array(1,2,3,4)), '', TRUE));
    }

    /**
     * @covers PHPUnit_Framework_Constraint_Count
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintCountFailing()
    {
        $constraint = new PHPUnit_Framework_Constraint_Count(5);

        try {
            $constraint->evaluate(array(1,2));
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that actual size 2 matches expected size 5.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_Count
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintNotCountFailing()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          new PHPUnit_Framework_Constraint_Count(2)
        );

        try {
            $constraint->evaluate(array(1,2));
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that actual size 2 does not match expected size 2.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_SameSize
     */
    public function testConstraintSameSizeWithAnArray()
    {
        $constraint = new PHPUnit_Framework_Constraint_SameSize(array(1,2,3,4,5));

        $this->assertTrue($constraint->evaluate(array(6,7,8,9,10), '', TRUE));
        $this->assertFalse($constraint->evaluate(array(1,2,3,4), '', TRUE));
    }

    /**
     * @covers PHPUnit_Framework_Constraint_SameSize
     */
    public function testConstraintSameSizeWithAnIteratorWhichDoesNotImplementCountable()
    {
        $constraint = new PHPUnit_Framework_Constraint_SameSize(new TestIterator(array(1,2,3,4,5)));

        $this->assertTrue($constraint->evaluate(new TestIterator(array(6,7,8,9,10)), '', TRUE));
        $this->assertFalse($constraint->evaluate(new TestIterator(array(1,2,3,4)), '', TRUE));
    }

    /**
     * @covers PHPUnit_Framework_Constraint_SameSize
     */
    public function testConstraintSameSizeWithAnObjectImplementingCountable()
    {
        $constraint = new PHPUnit_Framework_Constraint_SameSize(new ArrayObject(array(1,2,3,4,5)));

        $this->assertTrue($constraint->evaluate(new ArrayObject(array(6,7,8,9,10)), '', TRUE));
        $this->assertFalse($constraint->evaluate(new ArrayObject(array(1,2,3,4)), '', TRUE));
    }

    /**
     * @covers PHPUnit_Framework_Constraint_SameSize
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintSameSizeFailing()
    {
        $constraint = new PHPUnit_Framework_Constraint_SameSize(array(1,2,3,4,5));

        try {
            $constraint->evaluate(array(1,2));
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that actual size 2 matches expected size 5.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Constraint_SameSize
     * @covers PHPUnit_Framework_Constraint_Not
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_TestFailure::exceptionToString
     */
    public function testConstraintNotSameSizeFailing()
    {
        $constraint = PHPUnit_Framework_Assert::logicalNot(
          new PHPUnit_Framework_Constraint_SameSize(array(1,2))
        );

        try {
            $constraint->evaluate(array(3,4));
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
              <<<EOF
Failed asserting that actual size 2 does not match expected size 2.

EOF
              ,
              PHPUnit_Framework_TestFailure::exceptionToString($e)
            );

            return;
        }

        $this->fail();
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'ClassWithNonPublicAttributes.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'SampleClass.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'Struct.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'TestIterator.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'Author.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'Book.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'ClassWithToString.php';

/**
 *
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @author     Bernhard Schussek <bschussek@2bepublished.at>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.0.0
 */
class Framework_AssertTest extends PHPUnit_Framework_TestCase
{
    protected $filesDirectory;

    protected function setUp()
    {
        $this->filesDirectory = dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR;

        $this->html = file_get_contents(
            $this->filesDirectory . 'SelectorAssertionsFixture.html'
        );
    }

    /**
     * @covers PHPUnit_Framework_Assert::fail
     */
    public function testFail()
    {
        try {
            $this->fail();
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        throw new PHPUnit_Framework_AssertionFailedError('Fail did not throw fail exception');
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertContains
     */
    public function testAssertSplObjectStorageContainsObject()
    {
        $a = new stdClass;
        $b = new stdClass;
        $c = new SplObjectStorage;
        $c->attach($a);

        $this->assertContains($a, $c);

        try {
            $this->assertContains($b, $c);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertContains
     */
    public function testAssertArrayContainsObject()
    {
        $a = new stdClass;
        $b = new stdClass;

        $this->assertContains($a, array($a));

        try {
            $this->assertContains($a, array($b));
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertContains
     */
    public function testAssertArrayContainsString()
    {
        $this->assertContains('foo', array('foo'));

        try {
            $this->assertContains('foo', array('bar'));
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }
    /**
     * @covers PHPUnit_Framework_Assert::assertContainsOnlyInstancesOf
     */
    public function testAssertContainsOnlyInstancesOf()
    {
        $test = array(
            new Book(),
            new Book
        );
        $this->assertContainsOnlyInstancesOf('Book', $test);
        $this->assertContainsOnlyInstancesOf('stdClass', array(new stdClass()));

        $test2 = array(
            new Author('Test')
        );
        try {
            $this->assertContainsOnlyInstancesOf('Book', $test2);
        } catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }
        $this->fail();
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertArrayHasKey
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertArrayHasKeyThrowsException()
    {
        $this->assertArrayHasKey(NULL, array());
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertArrayHasKey
     */
    public function testAssertArrayHasIntegerKey()
    {
        $this->assertArrayHasKey(0, array('foo'));

        try {
            $this->assertArrayHasKey(1, array('foo'));
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertArrayNotHasKey
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertArrayNotHasKeyThrowsException()
    {
        $this->assertArrayNotHasKey(NULL, array());
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertArrayNotHasKey
     */
    public function testAssertArrayNotHasIntegerKey()
    {
        $this->assertArrayNotHasKey(1, array('foo'));

        try {
            $this->assertArrayNotHasKey(0, array('foo'));
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertArrayHasKey
     */
    public function testAssertArrayHasStringKey()
    {
        $this->assertArrayHasKey('foo', array('foo' => 'bar'));

        try {
            $this->assertArrayHasKey('bar', array('foo' => 'bar'));
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertArrayNotHasKey
     */
    public function testAssertArrayNotHasStringKey()
    {
        $this->assertArrayNotHasKey('bar', array('foo' => 'bar'));

        try {
            $this->assertArrayNotHasKey('foo', array('foo' => 'bar'));
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertArrayHasKey
     */
    public function testAssertArrayHasKeyAcceptsArrayAccessValue()
    {
        $array = new ArrayObject();
        $array['foo'] = 'bar';
        $this->assertArrayHasKey('foo', $array);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertArrayHasKey
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertArrayHasKeyProperlyFailsWithArrayAccessValue()
    {
        $array = new ArrayObject();
        $array['bar'] = 'bar';
        $this->assertArrayHasKey('foo', $array);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertArrayNotHasKey
     */
    public function testAssertArrayNotHasKeyAcceptsArrayAccessValue()
    {
        $array = new ArrayObject();
        $array['foo'] = 'bar';
        $this->assertArrayNotHasKey('bar', $array);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertArrayNotHasKey
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertArrayNotHasKeyPropertlyFailsWithArrayAccessValue()
    {
        $array = new ArrayObject();
        $array['bar'] = 'bar';
        $this->assertArrayNotHasKey('bar', $array);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertContains
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertContainsThrowsException()
    {
        $this->assertContains(NULL, NULL);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertContains
     */
    public function testAssertIteratorContainsObject()
    {
        $foo = new stdClass;

        $this->assertContains($foo, new TestIterator(array($foo)));

        try {
            $this->assertContains($foo, new TestIterator(array(new stdClass)));
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertContains
     */
    public function testAssertIteratorContainsString()
    {
        $this->assertContains('foo', new TestIterator(array('foo')));

        try {
            $this->assertContains('foo', new TestIterator(array('bar')));
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertContains
     */
    public function testAssertStringContainsString()
    {
        $this->assertContains('foo', 'foobar');

        try {
            $this->assertContains('foo', 'bar');
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertNotContains
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertNotContainsThrowsException()
    {
        $this->assertNotContains(NULL, NULL);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertNotContains
     */
    public function testAssertSplObjectStorageNotContainsObject()
    {
        $a = new stdClass;
        $b = new stdClass;
        $c = new SplObjectStorage;
        $c->attach($a);

        $this->assertNotContains($b, $c);

        try {
            $this->assertNotContains($a, $c);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertNotContains
     */
    public function testAssertArrayNotContainsObject()
    {
        $a = new stdClass;
        $b = new stdClass;

        $this->assertNotContains($a, array($b));

        try {
            $this->assertNotContains($a, array($a));
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertNotContains
     */
    public function testAssertArrayNotContainsString()
    {
        $this->assertNotContains('foo', array('bar'));

        try {
            $this->assertNotContains('foo', array('foo'));
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertNotContains
     */
    public function testAssertStringNotContainsString()
    {
        $this->assertNotContains('foo', 'bar');

        try {
            $this->assertNotContains('foo', 'foo');
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertContainsOnly
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertContainsOnlyThrowsException()
    {
        $this->assertContainsOnly(NULL, NULL);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertContainsOnlyInstancesOf
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertContainsOnlyInstancesOfThrowsException()
    {
        $this->assertContainsOnlyInstancesOf(NULL, NULL);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertContainsOnly
     */
    public function testAssertArrayContainsOnlyIntegers()
    {
        $this->assertContainsOnly('integer', array(1, 2, 3));

        try {
            $this->assertContainsOnly('integer', array("1", 2, 3));
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertNotContainsOnly
     */
    public function testAssertArrayNotContainsOnlyIntegers()
    {
        $this->assertNotContainsOnly('integer', array("1", 2, 3));

        try {
            $this->assertNotContainsOnly('integer', array(1, 2, 3));
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertContainsOnly
     */
    public function testAssertArrayContainsOnlyStdClass()
    {
        $this->assertContainsOnly('StdClass', array(new StdClass));

        try {
            $this->assertContainsOnly('StdClass', array('StdClass'));
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertNotContainsOnly
     */
    public function testAssertArrayNotContainsOnlyStdClass()
    {
        $this->assertNotContainsOnly('StdClass', array('StdClass'));

        try {
            $this->assertNotContainsOnly('StdClass', array(new StdClass));
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    protected function createDOMDocument($content)
    {
        $document = new DOMDocument;
        $document->preserveWhiteSpace = FALSE;
        $document->loadXML($content);

        return $document;
    }

    protected function sameValues()
    {
        $object = new SampleClass(4, 8, 15);
        // cannot use $filesDirectory, because neither setUp() nor
        // setUpBeforeClass() are executed before the data providers
        $file = dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'foo.xml';
        $resource = fopen($file, 'r');

        return array(
            // NULL
            array(NULL, NULL),
            // strings
            array('a', 'a'),
            // integers
            array(0, 0),
            // floats
            array(2.3, 2.3),
            array(1/3, 1 - 2/3),
            array(log(0), log(0)),
            // arrays
            array(array(), array()),
            array(array(0 => 1), array(0 => 1)),
            array(array(0 => NULL), array(0 => NULL)),
            array(array('a', 'b' => array(1, 2)), array('a', 'b' => array(1, 2))),
            // objects
            array($object, $object),
            // resources
            array($resource, $resource),
        );
    }

    protected function notEqualValues()
    {
        // cyclic dependencies
        $book1 = new Book;
        $book1->author = new Author('Terry Pratchett');
        $book1->author->books[] = $book1;
        $book2 = new Book;
        $book2->author = new Author('Terry Pratch');
        $book2->author->books[] = $book2;

        $book3 = new Book;
        $book3->author = 'Terry Pratchett';
        $book4 = new stdClass;
        $book4->author = 'Terry Pratchett';

        $object1 = new SampleClass( 4,  8, 15);
        $object2 = new SampleClass(16, 23, 42);
        $object3 = new SampleClass( 4,  8, 15);
        $storage1 = new SplObjectStorage;
        $storage1->attach($object1);
        $storage2 = new SplObjectStorage;
        $storage2->attach($object3); // same content, different object

        // cannot use $filesDirectory, because neither setUp() nor
        // setUpBeforeClass() are executed before the data providers
        $file = dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'foo.xml';

        return array(
            // strings
            array('a', 'b'),
            array('a', 'A'),
            // integers
            array(1, 2),
            array(2, 1),
            // floats
            array(2.3, 4.2),
            array(2.3, 4.2, 0.5),
            array(array(2.3), array(4.2), 0.5),
            array(array(array(2.3)), array(array(4.2)), 0.5),
            array(new Struct(2.3), new Struct(4.2), 0.5),
            array(array(new Struct(2.3)), array(new Struct(4.2)), 0.5),
            // NAN
            array(NAN, NAN),
            // arrays
            array(array(), array(0 => 1)),
            array(array(0 => 1), array()),
            array(array(0 => NULL), array()),
            array(array(0 => 1, 1 => 2), array(0 => 1, 1 => 3)),
            array(array('a', 'b' => array(1, 2)), array('a', 'b' => array(2, 1))),
            // objects
            array(new SampleClass(4, 8, 15), new SampleClass(16, 23, 42)),
            array($object1, $object2),
            array($book1, $book2),
            array($book3, $book4), // same content, different class
            // resources
            array(fopen($file, 'r'), fopen($file, 'r')),
            // SplObjectStorage
            array($storage1, $storage2),
            // DOMDocument
            array(
                $this->createDOMDocument('<root></root>'),
                $this->createDOMDocument('<bar/>'),
            ),
            array(
                $this->createDOMDocument('<foo attr1="bar"/>'),
                $this->createDOMDocument('<foo attr1="foobar"/>'),
            ),
            array(
                $this->createDOMDocument('<foo> bar </foo>'),
                $this->createDOMDocument('<foo />'),
            ),
            array(
                $this->createDOMDocument('<foo xmlns="urn:myns:bar"/>'),
                $this->createDOMDocument('<foo xmlns="urn:notmyns:bar"/>'),
            ),
            array(
                $this->createDOMDocument('<foo> bar </foo>'),
                $this->createDOMDocument('<foo> bir </foo>'),
            ),
            // Exception
            //array(new Exception('Exception 1'), new Exception('Exception 2')),
            // different types
            array(new SampleClass(4, 8, 15), FALSE),
            array(FALSE, new SampleClass(4, 8, 15)),
            array(array(0 => 1, 1 => 2), FALSE),
            array(FALSE, array(0 => 1, 1 => 2)),
            array(array(), new stdClass),
            array(new stdClass, array()),
            // PHP: 0 == 'Foobar' => TRUE!
            // We want these values to differ
            array(0, 'Foobar'),
            array('Foobar', 0),
            array(3, acos(8)),
            array(acos(8), 3)
        );
    }

    protected function equalValues()
    {
        // cyclic dependencies
        $book1 = new Book;
        $book1->author = new Author('Terry Pratchett');
        $book1->author->books[] = $book1;
        $book2 = new Book;
        $book2->author = new Author('Terry Pratchett');
        $book2->author->books[] = $book2;

        $object1 = new SampleClass(4, 8, 15);
        $object2 = new SampleClass(4, 8, 15);
        $storage1 = new SplObjectStorage;
        $storage1->attach($object1);
        $storage2 = new SplObjectStorage;
        $storage2->attach($object1);

        return array(
            // strings
            array('a', 'A', 0, FALSE, TRUE), // ignore case
            // arrays
            array(array('a' => 1, 'b' => 2), array('b' => 2, 'a' => 1)),
            array(array(1), array('1')),
            array(array(3, 2, 1), array(2, 3, 1), 0, TRUE), // canonicalized comparison
            // floats
            array(2.3, 2.5, 0.5),
            array(array(2.3), array(2.5), 0.5),
            array(array(array(2.3)), array(array(2.5)), 0.5),
            array(new Struct(2.3), new Struct(2.5), 0.5),
            array(array(new Struct(2.3)), array(new Struct(2.5)), 0.5),
            // numeric with delta
            array(1, 2, 1),
            // objects
            array($object1, $object2),
            array($book1, $book2),
            // SplObjectStorage
            array($storage1, $storage2),
            // DOMDocument
            array(
                $this->createDOMDocument('<root></root>'),
                $this->createDOMDocument('<root/>'),
            ),
            array(
                $this->createDOMDocument('<root attr="bar"></root>'),
                $this->createDOMDocument('<root attr="bar"/>'),
            ),
            array(
                $this->createDOMDocument('<root><foo attr="bar"></foo></root>'),
                $this->createDOMDocument('<root><foo attr="bar"/></root>'),
            ),
            array(
                $this->createDOMDocument("<root>\n  <child/>\n</root>"),
                $this->createDOMDocument('<root><child/></root>'),
            ),
            // Exception
            //array(new Exception('Exception 1'), new Exception('Exception 1')),
            // mixed types
            array(0, '0'),
            array('0', 0),
            array(2.3, '2.3'),
            array('2.3', 2.3),
            array((string)(1/3), 1 - 2/3),
            array(1/3, (string)(1 - 2/3)),
            array('string representation', new ClassWithToString),
            array(new ClassWithToString, 'string representation'),
        );
    }

    public function equalProvider()
    {
        // same |= equal
        return array_merge($this->equalValues(), $this->sameValues());
    }

    public function notEqualProvider()
    {
        return $this->notEqualValues();
    }

    public function sameProvider()
    {
        return $this->sameValues();
    }

    public function notSameProvider()
    {
        // not equal |= not same
        // equal, ¬same |= not same
        return array_merge($this->notEqualValues(), $this->equalValues());
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertEquals
     * @dataProvider equalProvider
     */
    public function testAssertEqualsSucceeds($a, $b, $delta = 0, $canonicalize = FALSE, $ignoreCase = FALSE)
    {
        $this->assertEquals($a, $b, '', $delta, 10, $canonicalize, $ignoreCase);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertEquals
     * @dataProvider notEqualProvider
     */
    public function testAssertEqualsFails($a, $b, $delta = 0, $canonicalize = FALSE, $ignoreCase = FALSE)
    {
        try {
            $this->assertEquals($a, $b, '', $delta, 10, $canonicalize, $ignoreCase);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertNotEquals
     * @dataProvider notEqualProvider
     */
    public function testAssertNotEqualsSucceeds($a, $b, $delta = 0, $canonicalize = FALSE, $ignoreCase = FALSE)
    {
        $this->assertNotEquals($a, $b, '', $delta, 10, $canonicalize, $ignoreCase);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertNotEquals
     * @dataProvider equalProvider
     */
    public function testAssertNotEqualsFails($a, $b, $delta = 0, $canonicalize = FALSE, $ignoreCase = FALSE)
    {
        try {
            $this->assertNotEquals($a, $b, '', $delta, 10, $canonicalize, $ignoreCase);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertSame
     * @dataProvider sameProvider
     */
    public function testAssertSameSucceeds($a, $b)
    {
        $this->assertSame($a, $b);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertSame
     * @dataProvider notSameProvider
     */
    public function testAssertSameFails($a, $b)
    {
        try {
            $this->assertSame($a, $b);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertNotSame
     * @dataProvider notSameProvider
     */
    public function testAssertNotSameSucceeds($a, $b)
    {
        $this->assertNotSame($a, $b);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertNotSame
     * @dataProvider sameProvider
     */
    public function testAssertNotSameFails($a, $b)
    {
        try {
            $this->assertNotSame($a, $b);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertXmlFileEqualsXmlFile
     */
    public function testAssertXmlFileEqualsXmlFile()
    {
        $this->assertXmlFileEqualsXmlFile(
          $this->filesDirectory . 'foo.xml',
          $this->filesDirectory . 'foo.xml'
        );

        try {
            $this->assertXmlFileEqualsXmlFile(
              $this->filesDirectory . 'foo.xml',
              $this->filesDirectory . 'bar.xml'
            );
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertXmlFileNotEqualsXmlFile
     */
    public function testAssertXmlFileNotEqualsXmlFile()
    {
        $this->assertXmlFileNotEqualsXmlFile(
          $this->filesDirectory . 'foo.xml',
          $this->filesDirectory . 'bar.xml'
        );

        try {
            $this->assertXmlFileNotEqualsXmlFile(
              $this->filesDirectory . 'foo.xml',
              $this->filesDirectory . 'foo.xml'
            );
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertXmlStringEqualsXmlFile
     */
    public function testAssertXmlStringEqualsXmlFile()
    {
        $this->assertXmlStringEqualsXmlFile(
          $this->filesDirectory . 'foo.xml',
          file_get_contents($this->filesDirectory . 'foo.xml')
        );

        try {
            $this->assertXmlStringEqualsXmlFile(
              $this->filesDirectory . 'foo.xml',
              file_get_contents($this->filesDirectory . 'bar.xml')
            );
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertXmlStringNotEqualsXmlFile
     */
    public function testXmlStringNotEqualsXmlFile()
    {
        $this->assertXmlStringNotEqualsXmlFile(
          $this->filesDirectory . 'foo.xml',
          file_get_contents($this->filesDirectory . 'bar.xml')
        );

        try {
            $this->assertXmlStringNotEqualsXmlFile(
              $this->filesDirectory . 'foo.xml',
              file_get_contents($this->filesDirectory . 'foo.xml')
            );
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertXmlStringEqualsXmlString
     */
    public function testAssertXmlStringEqualsXmlString()
    {
        $this->assertXmlStringEqualsXmlString('<root/>', '<root/>');

        try {
            $this->assertXmlStringEqualsXmlString('<foo/>', '<bar/>');
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertXmlStringNotEqualsXmlString
     */
    public function testAssertXmlStringNotEqualsXmlString()
    {
        $this->assertXmlStringNotEqualsXmlString('<foo/>', '<bar/>');

        try {
            $this->assertXmlStringNotEqualsXmlString('<root/>', '<root/>');
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertEqualXMLStructure
     */
    public function testXMLStructureIsSame()
    {
        $expected = new DOMDocument;
        $expected->load($this->filesDirectory . 'structureExpected.xml');

        $actual = new DOMDocument;
        $actual->load($this->filesDirectory . 'structureExpected.xml');

        $this->assertEqualXMLStructure(
          $expected->firstChild, $actual->firstChild, TRUE
        );
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertEqualXMLStructure
     * @expectedException PHPUnit_Framework_ExpectationFailedException
     */
    public function testXMLStructureWrongNumberOfAttributes()
    {
        $expected = new DOMDocument;
        $expected->load($this->filesDirectory . 'structureExpected.xml');

        $actual = new DOMDocument;
        $actual->load($this->filesDirectory . 'structureWrongNumberOfAttributes.xml');

        $this->assertEqualXMLStructure(
          $expected->firstChild, $actual->firstChild, TRUE
        );
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertEqualXMLStructure
     * @expectedException PHPUnit_Framework_ExpectationFailedException
     */
    public function testXMLStructureWrongNumberOfNodes()
    {
        $expected = new DOMDocument;
        $expected->load($this->filesDirectory . 'structureExpected.xml');

        $actual = new DOMDocument;
        $actual->load($this->filesDirectory . 'structureWrongNumberOfNodes.xml');

        $this->assertEqualXMLStructure(
          $expected->firstChild, $actual->firstChild, TRUE
        );
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertEqualXMLStructure
     */
    public function testXMLStructureIsSameButDataIsNot()
    {
        $expected = new DOMDocument;
        $expected->load($this->filesDirectory . 'structureExpected.xml');

        $actual = new DOMDocument;
        $actual->load($this->filesDirectory . 'structureIsSameButDataIsNot.xml');

        $this->assertEqualXMLStructure(
          $expected->firstChild, $actual->firstChild, TRUE
        );
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertEqualXMLStructure
     */
    public function testXMLStructureAttributesAreSameButValuesAreNot()
    {
        $expected = new DOMDocument;
        $expected->load($this->filesDirectory . 'structureExpected.xml');

        $actual = new DOMDocument;
        $actual->load($this->filesDirectory . 'structureAttributesAreSameButValuesAreNot.xml');

        $this->assertEqualXMLStructure(
          $expected->firstChild, $actual->firstChild, TRUE
        );
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertEqualXMLStructure
     */
    public function testXMLStructureIgnoreTextNodes()
    {
        $expected = new DOMDocument;
        $expected->load($this->filesDirectory . 'structureExpected.xml');

        $actual = new DOMDocument;
        $actual->load($this->filesDirectory . 'structureIgnoreTextNodes.xml');

        $this->assertEqualXMLStructure(
          $expected->firstChild, $actual->firstChild, TRUE
        );
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertEquals
     */
    public function testAssertStringEqualsNumeric()
    {
        $this->assertEquals('0', 0);

        try {
            $this->assertEquals('0', 1);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertNotEquals
     */
    public function testAssertStringEqualsNumeric2()
    {
        $this->assertNotEquals('A', 0);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertFileExists
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertFileExistsThrowsException()
    {
        $this->assertFileExists(NULL);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertFileExists
     */
    public function testAssertFileExists()
    {
        $this->assertFileExists(__FILE__);

        try {
            $this->assertFileExists(__DIR__ . DIRECTORY_SEPARATOR . 'NotExisting');
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertFileNotExists
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertFileNotExistsThrowsException()
    {
        $this->assertFileNotExists(NULL);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertFileNotExists
     */
    public function testAssertFileNotExists()
    {
        $this->assertFileNotExists(__DIR__ . DIRECTORY_SEPARATOR . 'NotExisting');

        try {
            $this->assertFileNotExists(__FILE__);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertObjectHasAttribute
     */
    public function testAssertObjectHasAttribute()
    {
        $o = new Author('Terry Pratchett');

        $this->assertObjectHasAttribute('name', $o);

        try {
            $this->assertObjectHasAttribute('foo', $o);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertObjectNotHasAttribute
     */
    public function testAssertObjectNotHasAttribute()
    {
        $o = new Author('Terry Pratchett');

        $this->assertObjectNotHasAttribute('foo', $o);

        try {
            $this->assertObjectNotHasAttribute('name', $o);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertNull
     */
    public function testAssertNull()
    {
        $this->assertNull(NULL);

        try {
            $this->assertNull(new stdClass);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertNotNull
     */
    public function testAssertNotNull()
    {
        $this->assertNotNull(new stdClass);

        try {
            $this->assertNotNull(NULL);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTrue
     */
    public function testAssertTrue()
    {
        $this->assertTrue(TRUE);

        try {
            $this->assertTrue(FALSE);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertFalse
     */
    public function testAssertFalse()
    {
        $this->assertFalse(FALSE);

        try {
            $this->assertFalse(TRUE);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertRegExp
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertRegExpThrowsException()
    {
        $this->assertRegExp(NULL, NULL);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertRegExp
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertRegExpThrowsException2()
    {
        $this->assertRegExp('', NULL);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertNotRegExp
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertNotRegExpThrowsException()
    {
        $this->assertNotRegExp(NULL, NULL);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertNotRegExp
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertNotRegExpThrowsException2()
    {
        $this->assertNotRegExp('', NULL);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertRegExp
     */
    public function testAssertRegExp()
    {
        $this->assertRegExp('/foo/', 'foobar');

        try {
            $this->assertRegExp('/foo/', 'bar');
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertNotRegExp
     */
    public function testAssertNotRegExp()
    {
        $this->assertNotRegExp('/foo/', 'bar');

        try {
            $this->assertNotRegExp('/foo/', 'foobar');
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertSame
     */
    public function testAssertSame()
    {
        $o = new stdClass;

        $this->assertSame($o, $o);

        try {
            $this->assertSame(
              new stdClass,
              new stdClass
            );
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertSame
     */
    public function testAssertSame2()
    {
        $this->assertSame(TRUE, TRUE);
        $this->assertSame(FALSE, FALSE);

        try {
            $this->assertSame(TRUE, FALSE);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertNotSame
     */
    public function testAssertNotSame()
    {
        $this->assertNotSame(
          new stdClass,
          NULL
        );

        $this->assertNotSame(
          NULL,
          new stdClass
        );

        $this->assertNotSame(
          new stdClass,
          new stdClass
        );

        $o = new stdClass;

        try {
            $this->assertNotSame($o, $o);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertNotSame
     */
    public function testAssertNotSame2()
    {
        $this->assertNotSame(TRUE, FALSE);
        $this->assertNotSame(FALSE, TRUE);

        try {
            $this->assertNotSame(TRUE, TRUE);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertNotSame
     */
    public function testAssertNotSameFailsNull()
    {
        try {
            $this->assertNotSame(NULL, NULL);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertGreaterThan
     */
    public function testGreaterThan()
    {
        $this->assertGreaterThan(1, 2);

        try {
            $this->assertGreaterThan(2, 1);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeGreaterThan
     */
    public function testAttributeGreaterThan()
    {
        $this->assertAttributeGreaterThan(
          1, 'bar', new ClassWithNonPublicAttributes
        );

        try {
            $this->assertAttributeGreaterThan(
              1, 'foo', new ClassWithNonPublicAttributes
            );
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertGreaterThanOrEqual
     */
    public function testGreaterThanOrEqual()
    {
        $this->assertGreaterThanOrEqual(1, 2);

        try {
            $this->assertGreaterThanOrEqual(2, 1);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeGreaterThanOrEqual
     */
    public function testAttributeGreaterThanOrEqual()
    {
        $this->assertAttributeGreaterThanOrEqual(
          1, 'bar', new ClassWithNonPublicAttributes
        );

        try {
            $this->assertAttributeGreaterThanOrEqual(
              2, 'foo', new ClassWithNonPublicAttributes
            );
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertLessThan
     */
    public function testLessThan()
    {
        $this->assertLessThan(2, 1);

        try {
            $this->assertLessThan(1, 2);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeLessThan
     */
    public function testAttributeLessThan()
    {
        $this->assertAttributeLessThan(
          2, 'foo', new ClassWithNonPublicAttributes
        );

        try {
            $this->assertAttributeLessThan(
              1, 'bar', new ClassWithNonPublicAttributes
            );
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertLessThanOrEqual
     */
    public function testLessThanOrEqual()
    {
        $this->assertLessThanOrEqual(2, 1);

        try {
            $this->assertLessThanOrEqual(1, 2);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeLessThanOrEqual
     */
    public function testAttributeLessThanOrEqual()
    {
        $this->assertAttributeLessThanOrEqual(
          2, 'foo', new ClassWithNonPublicAttributes
        );

        try {
            $this->assertAttributeLessThanOrEqual(
              1, 'bar', new ClassWithNonPublicAttributes
            );
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::readAttribute
     */
    public function testReadAttribute()
    {
        $obj = new ClassWithNonPublicAttributes;

        $this->assertEquals('foo', $this->readAttribute($obj, 'publicAttribute'));
        $this->assertEquals('bar', $this->readAttribute($obj, 'protectedAttribute'));
        $this->assertEquals('baz', $this->readAttribute($obj, 'privateAttribute'));
        $this->assertEquals('bar', $this->readAttribute($obj, 'protectedParentAttribute'));
        //$this->assertEquals('bar', $this->readAttribute($obj, 'privateParentAttribute'));
    }

    /**
     * @covers PHPUnit_Framework_Assert::readAttribute
     */
    public function testReadAttribute2()
    {
        $this->assertEquals('foo', $this->readAttribute('ClassWithNonPublicAttributes', 'publicStaticAttribute'));
        $this->assertEquals('bar', $this->readAttribute('ClassWithNonPublicAttributes', 'protectedStaticAttribute'));
        $this->assertEquals('baz', $this->readAttribute('ClassWithNonPublicAttributes', 'privateStaticAttribute'));
        $this->assertEquals('foo', $this->readAttribute('ClassWithNonPublicAttributes', 'protectedStaticParentAttribute'));
        $this->assertEquals('foo', $this->readAttribute('ClassWithNonPublicAttributes', 'privateStaticParentAttribute'));
    }

    /**
     * @covers            PHPUnit_Framework_Assert::readAttribute
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testReadAttribute3()
    {
        $this->readAttribute('StdClass', NULL);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::readAttribute
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testReadAttribute4()
    {
        $this->readAttribute('NotExistingClass', 'foo');
    }

    /**
     * @covers            PHPUnit_Framework_Assert::readAttribute
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testReadAttribute5()
    {
        $this->readAttribute(NULL, 'foo');
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeContains
     */
    public function testAssertPublicAttributeContains()
    {
        $obj = new ClassWithNonPublicAttributes;

        $this->assertAttributeContains('foo', 'publicArray', $obj);

        try {
            $this->assertAttributeContains('bar', 'publicArray', $obj);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeContainsOnly
     */
    public function testAssertPublicAttributeContainsOnly()
    {
        $obj = new ClassWithNonPublicAttributes;

        $this->assertAttributeContainsOnly('string', 'publicArray', $obj);

        try {
            $this->assertAttributeContainsOnly('integer', 'publicArray', $obj);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeNotContains
     */
    public function testAssertPublicAttributeNotContains()
    {
        $obj = new ClassWithNonPublicAttributes;

        $this->assertAttributeNotContains('bar', 'publicArray', $obj);

        try {
            $this->assertAttributeNotContains('foo', 'publicArray', $obj);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeNotContainsOnly
     */
    public function testAssertPublicAttributeNotContainsOnly()
    {
        $obj = new ClassWithNonPublicAttributes;

        $this->assertAttributeNotContainsOnly('integer', 'publicArray', $obj);

        try {
            $this->assertAttributeNotContainsOnly('string', 'publicArray', $obj);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeContains
     */
    public function testAssertProtectedAttributeContains()
    {
        $obj = new ClassWithNonPublicAttributes;

        $this->assertAttributeContains('bar', 'protectedArray', $obj);

        try {
            $this->assertAttributeContains('foo', 'protectedArray', $obj);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeNotContains
     */
    public function testAssertProtectedAttributeNotContains()
    {
        $obj = new ClassWithNonPublicAttributes;

        $this->assertAttributeNotContains('foo', 'protectedArray', $obj);

        try {
            $this->assertAttributeNotContains('bar', 'protectedArray', $obj);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeContains
     */
    public function testAssertPrivateAttributeContains()
    {
        $obj = new ClassWithNonPublicAttributes;

        $this->assertAttributeContains('baz', 'privateArray', $obj);

        try {
            $this->assertAttributeContains('foo', 'privateArray', $obj);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeNotContains
     */
    public function testAssertPrivateAttributeNotContains()
    {
        $obj = new ClassWithNonPublicAttributes;

        $this->assertAttributeNotContains('foo', 'privateArray', $obj);

        try {
            $this->assertAttributeNotContains('baz', 'privateArray', $obj);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeEquals
     */
    public function testAssertPublicAttributeEquals()
    {
        $obj = new ClassWithNonPublicAttributes;

        $this->assertAttributeEquals('foo', 'publicAttribute', $obj);

        try {
            $this->assertAttributeEquals('bar', 'publicAttribute', $obj);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeNotEquals
     */
    public function testAssertPublicAttributeNotEquals()
    {
        $obj = new ClassWithNonPublicAttributes;

        $this->assertAttributeNotEquals('bar', 'publicAttribute', $obj);

        try {
            $this->assertAttributeNotEquals('foo', 'publicAttribute', $obj);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeSame
     */
    public function testAssertPublicAttributeSame()
    {
        $obj = new ClassWithNonPublicAttributes;

        $this->assertAttributeSame('foo', 'publicAttribute', $obj);

        try {
            $this->assertAttributeSame('bar', 'publicAttribute', $obj);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeNotSame
     */
    public function testAssertPublicAttributeNotSame()
    {
        $obj = new ClassWithNonPublicAttributes;

        $this->assertAttributeNotSame('bar', 'publicAttribute', $obj);

        try {
            $this->assertAttributeNotSame('foo', 'publicAttribute', $obj);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeEquals
     */
    public function testAssertProtectedAttributeEquals()
    {
        $obj = new ClassWithNonPublicAttributes;

        $this->assertAttributeEquals('bar', 'protectedAttribute', $obj);

        try {
            $this->assertAttributeEquals('foo', 'protectedAttribute', $obj);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeNotEquals
     */
    public function testAssertProtectedAttributeNotEquals()
    {
        $obj = new ClassWithNonPublicAttributes;

        $this->assertAttributeNotEquals('foo', 'protectedAttribute', $obj);

        try {
            $this->assertAttributeNotEquals('bar', 'protectedAttribute', $obj);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeEquals
     */
    public function testAssertPrivateAttributeEquals()
    {
        $obj = new ClassWithNonPublicAttributes;

        $this->assertAttributeEquals('baz', 'privateAttribute', $obj);

        try {
            $this->assertAttributeEquals('foo', 'privateAttribute', $obj);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeNotEquals
     */
    public function testAssertPrivateAttributeNotEquals()
    {
        $obj = new ClassWithNonPublicAttributes;

        $this->assertAttributeNotEquals('foo', 'privateAttribute', $obj);

        try {
            $this->assertAttributeNotEquals('baz', 'privateAttribute', $obj);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeEquals
     */
    public function testAssertPublicStaticAttributeEquals()
    {
        $this->assertAttributeEquals('foo', 'publicStaticAttribute', 'ClassWithNonPublicAttributes');

        try {
            $this->assertAttributeEquals('bar', 'publicStaticAttribute', 'ClassWithNonPublicAttributes');
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeNotEquals
     */
    public function testAssertPublicStaticAttributeNotEquals()
    {
        $this->assertAttributeNotEquals('bar', 'publicStaticAttribute', 'ClassWithNonPublicAttributes');

        try {
            $this->assertAttributeNotEquals('foo', 'publicStaticAttribute', 'ClassWithNonPublicAttributes');
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeEquals
     */
    public function testAssertProtectedStaticAttributeEquals()
    {
        $this->assertAttributeEquals('bar', 'protectedStaticAttribute', 'ClassWithNonPublicAttributes');

        try {
            $this->assertAttributeEquals('foo', 'protectedStaticAttribute', 'ClassWithNonPublicAttributes');
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeNotEquals
     */
    public function testAssertProtectedStaticAttributeNotEquals()
    {
        $this->assertAttributeNotEquals('foo', 'protectedStaticAttribute', 'ClassWithNonPublicAttributes');

        try {
            $this->assertAttributeNotEquals('bar', 'protectedStaticAttribute', 'ClassWithNonPublicAttributes');
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeEquals
     */
    public function testAssertPrivateStaticAttributeEquals()
    {
        $this->assertAttributeEquals('baz', 'privateStaticAttribute', 'ClassWithNonPublicAttributes');

        try {
            $this->assertAttributeEquals('foo', 'privateStaticAttribute', 'ClassWithNonPublicAttributes');
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeNotEquals
     */
    public function testAssertPrivateStaticAttributeNotEquals()
    {
        $this->assertAttributeNotEquals('foo', 'privateStaticAttribute', 'ClassWithNonPublicAttributes');

        try {
            $this->assertAttributeNotEquals('baz', 'privateStaticAttribute', 'ClassWithNonPublicAttributes');
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertClassHasAttribute
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertClassHasAttributeThrowsException()
    {
        $this->assertClassHasAttribute(NULL, NULL);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertClassHasAttribute
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertClassHasAttributeThrowsException2()
    {
        $this->assertClassHasAttribute('foo', NULL);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertClassNotHasAttribute
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertClassNotHasAttributeThrowsException()
    {
        $this->assertClassNotHasAttribute(NULL, NULL);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertClassNotHasAttribute
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertClassNotHasAttributeThrowsException2()
    {
        $this->assertClassNotHasAttribute('foo', NULL);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertClassHasStaticAttribute
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertClassHasStaticAttributeThrowsException()
    {
        $this->assertClassHasStaticAttribute(NULL, NULL);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertClassHasStaticAttribute
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertClassHasStaticAttributeThrowsException2()
    {
        $this->assertClassHasStaticAttribute('foo', NULL);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertClassNotHasStaticAttribute
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertClassNotHasStaticAttributeThrowsException()
    {
        $this->assertClassNotHasStaticAttribute(NULL, NULL);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertClassNotHasStaticAttribute
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertClassNotHasStaticAttributeThrowsException2()
    {
        $this->assertClassNotHasStaticAttribute('foo', NULL);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertObjectHasAttribute
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertObjectHasAttributeThrowsException()
    {
        $this->assertObjectHasAttribute(NULL, NULL);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertObjectHasAttribute
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertObjectHasAttributeThrowsException2()
    {
        $this->assertObjectHasAttribute('foo', NULL);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertObjectNotHasAttribute
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertObjectNotHasAttributeThrowsException()
    {
        $this->assertObjectNotHasAttribute(NULL, NULL);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertObjectNotHasAttribute
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertObjectNotHasAttributeThrowsException2()
    {
        $this->assertObjectNotHasAttribute('foo', NULL);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertClassHasAttribute
     */
    public function testClassHasPublicAttribute()
    {
        $this->assertClassHasAttribute('publicAttribute', 'ClassWithNonPublicAttributes');

        try {
            $this->assertClassHasAttribute('attribute', 'ClassWithNonPublicAttributes');
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertClassNotHasAttribute
     */
    public function testClassNotHasPublicAttribute()
    {
        $this->assertClassNotHasAttribute('attribute', 'ClassWithNonPublicAttributes');

        try {
            $this->assertClassNotHasAttribute('publicAttribute', 'ClassWithNonPublicAttributes');
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertClassHasStaticAttribute
     */
    public function testClassHasPublicStaticAttribute()
    {
        $this->assertClassHasStaticAttribute('publicStaticAttribute', 'ClassWithNonPublicAttributes');

        try {
            $this->assertClassHasStaticAttribute('attribute', 'ClassWithNonPublicAttributes');
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertClassNotHasStaticAttribute
     */
    public function testClassNotHasPublicStaticAttribute()
    {
        $this->assertClassNotHasStaticAttribute('attribute', 'ClassWithNonPublicAttributes');

        try {
            $this->assertClassNotHasStaticAttribute('publicStaticAttribute', 'ClassWithNonPublicAttributes');
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertObjectHasAttribute
     */
    public function testObjectHasPublicAttribute()
    {
        $obj = new ClassWithNonPublicAttributes;

        $this->assertObjectHasAttribute('publicAttribute', $obj);

        try {
            $this->assertObjectHasAttribute('attribute', $obj);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertObjectNotHasAttribute
     */
    public function testObjectNotHasPublicAttribute()
    {
        $obj = new ClassWithNonPublicAttributes;

        $this->assertObjectNotHasAttribute('attribute', $obj);

        try {
            $this->assertObjectNotHasAttribute('publicAttribute', $obj);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertObjectHasAttribute
     */
    public function testObjectHasOnTheFlyAttribute()
    {
        $obj = new StdClass;
        $obj->foo = 'bar';

        $this->assertObjectHasAttribute('foo', $obj);

        try {
            $this->assertObjectHasAttribute('bar', $obj);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertObjectNotHasAttribute
     */
    public function testObjectNotHasOnTheFlyAttribute()
    {
        $obj = new StdClass;
        $obj->foo = 'bar';

        $this->assertObjectNotHasAttribute('bar', $obj);

        try {
            $this->assertObjectNotHasAttribute('foo', $obj);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertObjectHasAttribute
     */
    public function testObjectHasProtectedAttribute()
    {
        $obj = new ClassWithNonPublicAttributes;

        $this->assertObjectHasAttribute('protectedAttribute', $obj);

        try {
            $this->assertObjectHasAttribute('attribute', $obj);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertObjectNotHasAttribute
     */
    public function testObjectNotHasProtectedAttribute()
    {
        $obj = new ClassWithNonPublicAttributes;

        $this->assertObjectNotHasAttribute('attribute', $obj);

        try {
            $this->assertObjectNotHasAttribute('protectedAttribute', $obj);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertObjectHasAttribute
     */
    public function testObjectHasPrivateAttribute()
    {
        $obj = new ClassWithNonPublicAttributes;

        $this->assertObjectHasAttribute('privateAttribute', $obj);

        try {
            $this->assertObjectHasAttribute('attribute', $obj);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertObjectNotHasAttribute
     */
    public function testObjectNotHasPrivateAttribute()
    {
        $obj = new ClassWithNonPublicAttributes;

        $this->assertObjectNotHasAttribute('attribute', $obj);

        try {
            $this->assertObjectNotHasAttribute('privateAttribute', $obj);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertThat
     * @covers PHPUnit_Framework_Assert::attribute
     * @covers PHPUnit_Framework_Assert::equalTo
     */
    public function testAssertThatAttributeEquals()
    {
        $this->assertThat(
          new ClassWithNonPublicAttributes,
          $this->attribute(
            $this->equalTo('foo'),
            'publicAttribute'
          )
        );
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertThat
     * @covers            PHPUnit_Framework_Assert::attribute
     * @covers            PHPUnit_Framework_Assert::equalTo
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertThatAttributeEquals2()
    {
        $this->assertThat(
          new ClassWithNonPublicAttributes,
          $this->attribute(
            $this->equalTo('bar'),
            'publicAttribute'
          )
        );
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertThat
     * @covers PHPUnit_Framework_Assert::attribute
     * @covers PHPUnit_Framework_Assert::equalTo
     */
    public function testAssertThatAttributeEqualTo()
    {
        $this->assertThat(
          new ClassWithNonPublicAttributes,
          $this->attributeEqualTo('publicAttribute', 'foo')
        );
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertThat
     * @covers PHPUnit_Framework_Assert::anything
     */
    public function testAssertThatAnything()
    {
        $this->assertThat('anything', $this->anything());
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertThat
     * @covers PHPUnit_Framework_Assert::anything
     * @covers PHPUnit_Framework_Assert::logicalAnd
     */
    public function testAssertThatAnythingAndAnything()
    {
        $this->assertThat(
          'anything',
          $this->logicalAnd(
            $this->anything(), $this->anything()
          )
        );
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertThat
     * @covers PHPUnit_Framework_Assert::anything
     * @covers PHPUnit_Framework_Assert::logicalOr
     */
    public function testAssertThatAnythingOrAnything()
    {
        $this->assertThat(
          'anything',
          $this->logicalOr(
            $this->anything(), $this->anything()
          )
        );
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertThat
     * @covers PHPUnit_Framework_Assert::anything
     * @covers PHPUnit_Framework_Assert::logicalNot
     * @covers PHPUnit_Framework_Assert::logicalXor
     */
    public function testAssertThatAnythingXorNotAnything()
    {
        $this->assertThat(
          'anything',
          $this->logicalXor(
            $this->anything(),
            $this->logicalNot($this->anything())
          )
        );
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertThat
     * @covers PHPUnit_Framework_Assert::contains
     */
    public function testAssertThatContains()
    {
        $this->assertThat(array('foo'), $this->contains('foo'));
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertThat
     * @covers PHPUnit_Framework_Assert::stringContains
     */
    public function testAssertThatStringContains()
    {
        $this->assertThat('barfoobar', $this->stringContains('foo'));
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertThat
     * @covers PHPUnit_Framework_Assert::containsOnly
     */
    public function testAssertThatContainsOnly()
    {
        $this->assertThat(array('foo'), $this->containsOnly('string'));
    }
    /**
     * @covers PHPUnit_Framework_Assert::assertThat
     * @covers PHPUnit_Framework_Assert::containsOnlyInstancesOf
     */
    public function testAssertThatContainsOnlyInstancesOf()
    {
        $this->assertThat(array(new Book), $this->containsOnlyInstancesOf('Book'));
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertThat
     * @covers PHPUnit_Framework_Assert::arrayHasKey
     */
    public function testAssertThatArrayHasKey()
    {
        $this->assertThat(array('foo' => 'bar'), $this->arrayHasKey('foo'));
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertThat
     * @covers PHPUnit_Framework_Assert::classHasAttribute
     */
    public function testAssertThatClassHasAttribute()
    {
        $this->assertThat(
          new ClassWithNonPublicAttributes,
          $this->classHasAttribute('publicAttribute')
        );
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertThat
     * @covers PHPUnit_Framework_Assert::classHasStaticAttribute
     */
    public function testAssertThatClassHasStaticAttribute()
    {
        $this->assertThat(
          new ClassWithNonPublicAttributes,
          $this->classHasStaticAttribute('publicStaticAttribute')
        );
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertThat
     * @covers PHPUnit_Framework_Assert::objectHasAttribute
     */
    public function testAssertThatObjectHasAttribute()
    {
        $this->assertThat(
          new ClassWithNonPublicAttributes,
          $this->objectHasAttribute('publicAttribute')
        );
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertThat
     * @covers PHPUnit_Framework_Assert::equalTo
     */
    public function testAssertThatEqualTo()
    {
        $this->assertThat('foo', $this->equalTo('foo'));
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertThat
     * @covers PHPUnit_Framework_Assert::identicalTo
     */
    public function testAssertThatIdenticalTo()
    {
        $value      = new StdClass;
        $constraint = $this->identicalTo($value);

        $this->assertThat($value, $constraint);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertThat
     * @covers PHPUnit_Framework_Assert::isInstanceOf
     */
    public function testAssertThatIsInstanceOf()
    {
        $this->assertThat(new StdClass, $this->isInstanceOf('StdClass'));
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertThat
     * @covers PHPUnit_Framework_Assert::isType
     */
    public function testAssertThatIsType()
    {
        $this->assertThat('string', $this->isType('string'));
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertThat
     * @covers PHPUnit_Framework_Assert::fileExists
     */
    public function testAssertThatFileExists()
    {
        $this->assertThat(__FILE__, $this->fileExists());
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertThat
     * @covers PHPUnit_Framework_Assert::greaterThan
     */
    public function testAssertThatGreaterThan()
    {
        $this->assertThat(2, $this->greaterThan(1));
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertThat
     * @covers PHPUnit_Framework_Assert::greaterThanOrEqual
     */
    public function testAssertThatGreaterThanOrEqual()
    {
        $this->assertThat(2, $this->greaterThanOrEqual(1));
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertThat
     * @covers PHPUnit_Framework_Assert::lessThan
     */
    public function testAssertThatLessThan()
    {
        $this->assertThat(1, $this->lessThan(2));
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertThat
     * @covers PHPUnit_Framework_Assert::lessThanOrEqual
     */
    public function testAssertThatLessThanOrEqual()
    {
        $this->assertThat(1, $this->lessThanOrEqual(2));
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertThat
     * @covers PHPUnit_Framework_Assert::matchesRegularExpression
     */
    public function testAssertThatMatchesRegularExpression()
    {
        $this->assertThat('foobar', $this->matchesRegularExpression('/foo/'));
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertTagTypeTrue()
    {
        $matcher = array('tag' => 'html');
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertTag
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertTagTypeFalse()
    {
        $matcher = array('tag' => 'code');
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertTagIdTrue()
    {
        $matcher = array('id' => 'test_text');
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertTag
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertTagIdFalse()
    {
        $matcher = array('id' => 'test_text_doesnt_exist');
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertTagStringContentTrue()
    {
        $matcher = array('id' => 'test_text',
                         'content' => 'My test tag content');
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertTag
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertTagStringContentFalse()
    {
        $matcher = array('id' => 'test_text',
                         'content' => 'My non existent tag content');
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertTagRegexpContentTrue()
    {
        $matcher = array('id' => 'test_text',
                         'content' => 'regexp:/test tag/');
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertTagRegexpModifierContentTrue()
    {
        $matcher = array('id' => 'test_text',
                         'content' => 'regexp:/TEST TAG/i');
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertTag
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertTagRegexpContentFalse()
    {
        $matcher = array('id' => 'test_text',
                         'content' => 'regexp:/asdf/');
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertTagCdataContentTrue()
    {
        $matcher = array('tag' => 'script',
                         'content' => 'alert(\'Hello, world!\');');
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertTag
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertTagCdataontentFalse()
    {
        $matcher = array('tag' => 'script',
                         'content' => 'asdf');
        $this->assertTag($matcher, $this->html);
    }



    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertTagAttributesTrueA()
    {
        $matcher = array('tag' => 'span',
                         'attributes' => array('class' => 'test_class'));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertTagAttributesTrueB()
    {
        $matcher = array('tag' => 'div',
                         'attributes' => array('id' => 'test_child_id'));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertTag
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertTagAttributesFalse()
    {
        $matcher = array('tag' => 'span',
                         'attributes' => array('class' => 'test_missing_class'));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertTagAttributesRegexpTrueA()
    {
        $matcher = array('tag' => 'span',
                         'attributes' => array('class' => 'regexp:/.+_class/'));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertTagAttributesRegexpTrueB()
    {
        $matcher = array('tag' => 'div',
                         'attributes' => array('id' => 'regexp:/.+_child_.+/'));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertTagAttributesRegexpModifierTrue()
    {
        $matcher = array('tag' => 'div',
                         'attributes' => array('id' => 'regexp:/.+_CHILD_.+/i'));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertTag
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertTagAttributesRegexpModifierFalse()
    {
        $matcher = array('tag' => 'div',
                         'attributes' => array('id' => 'regexp:/.+_CHILD_.+/'));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertTag
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertTagAttributesRegexpFalse()
    {
        $matcher = array('tag' => 'span',
                         'attributes' => array('class' => 'regexp:/.+_missing_.+/'));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertTagAttributesMultiPartClassTrueA()
    {
        $matcher = array('tag' => 'div',
                         'id'  => 'test_multi_class',
                         'attributes' => array('class' => 'multi class'));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertTagAttributesMultiPartClassTrueB()
    {
        $matcher = array('tag' => 'div',
                         'id'  => 'test_multi_class',
                         'attributes' => array('class' => 'multi'));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertTag
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertTagAttributesMultiPartClassFalse()
    {
        $matcher = array('tag' => 'div',
                         'id'  => 'test_multi_class',
                         'attributes' => array('class' => 'mul'));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertTagParentTrue()
    {
        $matcher = array('tag' => 'head',
                         'parent' => array('tag' => 'html'));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertTag
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertTagParentFalse()
    {
        $matcher = array('tag' => 'head',
                         'parent' => array('tag' => 'div'));
        $this->assertTag($matcher, $this->html);
    }

    /**
    * @covers PHPUnit_Framework_Assert::assertTag
    */
    public function testAssertTagMultiplePossibleChildren()
    {
        $matcher = array(
            'tag' => 'li',
            'parent' => array(
                'tag' => 'ul',
                'id' => 'another_ul'
            )
        );
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertTagChildTrue()
    {
        $matcher = array('tag' => 'html',
                         'child' => array('tag' => 'head'));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertTag
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertTagChildFalse()
    {
        $matcher = array('tag' => 'html',
                         'child' => array('tag' => 'div'));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertTagAncestorTrue()
    {
        $matcher = array('tag' => 'div',
                         'ancestor' => array('tag' => 'html'));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertTag
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertTagAncestorFalse()
    {
        $matcher = array('tag' => 'html',
                         'ancestor' => array('tag' => 'div'));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertTagDescendantTrue()
    {
        $matcher = array('tag' => 'html',
                         'descendant' => array('tag' => 'div'));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertTag
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertTagDescendantFalse()
    {
        $matcher = array('tag' => 'div',
                         'descendant' => array('tag' => 'html'));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertTagChildrenCountTrue()
    {
        $matcher = array('tag' => 'ul',
                         'children' => array('count' => 3));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertTag
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertTagChildrenCountFalse()
    {
        $matcher = array('tag' => 'ul',
                         'children' => array('count' => 5));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertTagChildrenLessThanTrue()
    {
        $matcher = array('tag' => 'ul',
                         'children' => array('less_than' => 10));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertTag
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertTagChildrenLessThanFalse()
    {
        $matcher = array('tag' => 'ul',
                         'children' => array('less_than' => 2));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertTagChildrenGreaterThanTrue()
    {
        $matcher = array('tag' => 'ul',
                         'children' => array('greater_than' => 2));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertTag
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertTagChildrenGreaterThanFalse()
    {
        $matcher = array('tag' => 'ul',
                         'children' => array('greater_than' => 10));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertTagChildrenOnlyTrue()
    {
        $matcher = array('tag' => 'ul',
                         'children' => array('only' => array('tag' =>'li')));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertTag
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertTagChildrenOnlyFalse()
    {
        $matcher = array('tag' => 'ul',
                         'children' => array('only' => array('tag' =>'div')));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertTagTypeIdTrueA()
    {
        $matcher = array('tag' => 'ul', 'id' => 'my_ul');
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertTagTypeIdTrueB()
    {
        $matcher = array('id' => 'my_ul', 'tag' => 'ul');
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertTagTypeIdTrueC()
    {
        $matcher = array('tag' => 'input', 'id'  => 'input_test_id');
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertTag
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertTagTypeIdFalse()
    {
        $matcher = array('tag' => 'div', 'id'  => 'my_ul');
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertTagContentAttributes()
    {
        $matcher = array('tag' => 'div',
                         'content'    => 'Test Id Text',
                         'attributes' => array('id' => 'test_id',
                                               'class' => 'my_test_class'));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertParentContentAttributes()
    {
        $matcher = array('tag'        => 'div',
                         'content'    => 'Test Id Text',
                         'attributes' => array('id'    => 'test_id',
                                               'class' => 'my_test_class'),
                         'parent'     => array('tag' => 'body'));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertChildContentAttributes()
    {
        $matcher = array('tag'        => 'div',
                         'content'    => 'Test Id Text',
                         'attributes' => array('id'    => 'test_id',
                                               'class' => 'my_test_class'),
                         'child'      => array('tag'        => 'div',
                                               'attributes' => array('id' => 'test_child_id')));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertChildSubChildren()
    {
        $matcher = array('id' => 'test_id',
                         'child' => array('id' => 'test_child_id',
                                          'child' => array('id' => 'test_subchild_id')));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertAncestorContentAttributes()
    {
        $matcher = array('id'         => 'test_subchild_id',
                         'content'    => 'My Subchild',
                         'attributes' => array('id' => 'test_subchild_id'),
                         'ancestor'   => array('tag'        => 'div',
                                               'attributes' => array('id' => 'test_id')));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertDescendantContentAttributes()
    {
        $matcher = array('id'         => 'test_id',
                         'content'    => 'Test Id Text',
                         'attributes' => array('id'  => 'test_id'),
                         'descendant' => array('tag'        => 'span',
                                               'attributes' => array('id' => 'test_subchild_id')));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertTag
     */
    public function testAssertChildrenContentAttributes()
    {
        $matcher = array('id'         => 'test_children',
                         'content'    => 'My Children',
                         'attributes' => array('class'  => 'children'),

                         'children' => array('less_than'    => '25',
                                             'greater_than' => '2',
                                             'only'         => array('tag' => 'div',
                                                                     'attributes' => array('class' => 'my_child'))
                                            ));
        $this->assertTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertNotTag
     */
    public function testAssertNotTagTypeIdFalse()
    {
        $matcher = array('tag' => 'div', 'id'  => 'my_ul');
        $this->assertNotTag($matcher, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertNotTag
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertNotTagContentAttributes()
    {
        $matcher = array('tag' => 'div',
                         'content'    => 'Test Id Text',
                         'attributes' => array('id' => 'test_id',
                                               'class' => 'my_test_class'));
        $this->assertNotTag($matcher, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertSelectCount
     */
    public function testAssertSelectCountPresentTrue()
    {
        $selector = 'div#test_id';
        $count    = TRUE;

        $this->assertSelectCount($selector, $count, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertSelectCount
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertSelectCountPresentFalse()
    {
        $selector = 'div#non_existent';
        $count    = TRUE;

        $this->assertSelectCount($selector, $count, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertSelectCount
     */
    public function testAssertSelectCountNotPresentTrue()
    {
        $selector = 'div#non_existent';
        $count    = FALSE;

        $this->assertSelectCount($selector, $count, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertSelectCount
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertSelectNotPresentFalse()
    {
        $selector = 'div#test_id';
        $count    = FALSE;

        $this->assertSelectCount($selector, $count, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertSelectCount
     */
    public function testAssertSelectCountChildTrue()
    {
        $selector = '#my_ul > li';
        $count    = 3;

        $this->assertSelectCount($selector, $count, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertSelectCount
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertSelectCountChildFalse()
    {
        $selector = '#my_ul > li';
        $count    = 4;

        $this->assertSelectCount($selector, $count, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertSelectCount
     */
    public function testAssertSelectCountDescendantTrue()
    {
        $selector = '#my_ul li';
        $count    = 3;

        $this->assertSelectCount($selector, $count, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertSelectCount
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertSelectCountDescendantFalse()
    {
        $selector = '#my_ul li';
        $count    = 4;

        $this->assertSelectCount($selector, $count, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertSelectCount
     */
    public function testAssertSelectCountGreaterThanTrue()
    {
        $selector = '#my_ul > li';
        $range    = array('>' => 2);

        $this->assertSelectCount($selector, $range, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertSelectCount
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertSelectCountGreaterThanFalse()
    {
        $selector = '#my_ul > li';
        $range    = array('>' => 3);

        $this->assertSelectCount($selector, $range, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertSelectCount
     */
    public function testAssertSelectCountGreaterThanEqualToTrue()
    {
        $selector = '#my_ul > li';
        $range    = array('>=' => 3);

        $this->assertSelectCount($selector, $range, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertSelectCount
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertSelectCountGreaterThanEqualToFalse()
    {
        $selector = '#my_ul > li';
        $range    = array('>=' => 4);

        $this->assertSelectCount($selector, $range, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertSelectCount
     */
    public function testAssertSelectCountLessThanTrue()
    {
        $selector = '#my_ul > li';
        $range    = array('<' => 4);

        $this->assertSelectCount($selector, $range, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertSelectCount
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertSelectCountLessThanFalse()
    {
        $selector = '#my_ul > li';
        $range    = array('<' => 3);

        $this->assertSelectCount($selector, $range, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertSelectCount
     */
    public function testAssertSelectCountLessThanEqualToTrue()
    {
        $selector = '#my_ul > li';
        $range    = array('<=' => 3);

        $this->assertSelectCount($selector, $range, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertSelectCount
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertSelectCountLessThanEqualToFalse()
    {
        $selector = '#my_ul > li';
        $range  = array('<=' => 2);

        $this->assertSelectCount($selector, $range, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertSelectCount
     */
    public function testAssertSelectCountRangeTrue()
    {
        $selector = '#my_ul > li';
        $range    = array('>' => 2, '<' => 4);

        $this->assertSelectCount($selector, $range, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertSelectCount
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertSelectCountRangeFalse()
    {
        $selector = '#my_ul > li';
        $range    = array('>' => 1, '<' => 3);

        $this->assertSelectCount($selector, $range, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertSelectEquals
     */
    public function testAssertSelectEqualsContentPresentTrue()
    {
        $selector = 'span.test_class';
        $content  = 'Test Class Text';

        $this->assertSelectEquals($selector, $content, TRUE, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertSelectEquals
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertSelectEqualsContentPresentFalse()
    {
        $selector = 'span.test_class';
        $content  = 'Test Nonexistent';

        $this->assertSelectEquals($selector, $content, TRUE, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertSelectEquals
     */
    public function testAssertSelectEqualsContentNotPresentTrue()
    {
        $selector = 'span.test_class';
        $content  = 'Test Nonexistent';

        $this->assertSelectEquals($selector, $content, FALSE, $this->html);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertSelectEquals
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertSelectEqualsContentNotPresentFalse()
    {
        $selector = 'span.test_class';
        $content  = 'Test Class Text';

        $this->assertSelectEquals($selector, $content, FALSE, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertSelectRegExp
     */
    public function testAssertSelectRegExpContentPresentTrue()
    {
        $selector = 'span.test_class';
        $regexp   = '/Test.*Text/';

        $this->assertSelectRegExp($selector, $regexp, TRUE, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertSelectRegExp
     */
    public function testAssertSelectRegExpContentPresentFalse()
    {
        $selector = 'span.test_class';
        $regexp   = '/Nonexistant/';

        $this->assertSelectRegExp($selector, $regexp, FALSE, $this->html);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertFileEquals
     */
    public function testAssertFileEquals()
    {
        $this->assertFileEquals(
          $this->filesDirectory . 'foo.xml',
          $this->filesDirectory . 'foo.xml'
        );

        try {
            $this->assertFileEquals(
              $this->filesDirectory . 'foo.xml',
              $this->filesDirectory . 'bar.xml'
            );
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertFileNotEquals
     */
    public function testAssertFileNotEquals()
    {
        $this->assertFileNotEquals(
          $this->filesDirectory . 'foo.xml',
          $this->filesDirectory . 'bar.xml'
        );

        try {
            $this->assertFileNotEquals(
              $this->filesDirectory . 'foo.xml',
              $this->filesDirectory . 'foo.xml'
            );
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertStringEqualsFile
     */
    public function testAssertStringEqualsFile()
    {
        $this->assertStringEqualsFile(
          $this->filesDirectory . 'foo.xml',
          file_get_contents($this->filesDirectory . 'foo.xml')
        );

        try {
            $this->assertStringEqualsFile(
              $this->filesDirectory . 'foo.xml',
              file_get_contents($this->filesDirectory . 'bar.xml')
            );
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertStringNotEqualsFile
     */
    public function testAssertStringNotEqualsFile()
    {
        $this->assertStringNotEqualsFile(
          $this->filesDirectory . 'foo.xml',
          file_get_contents($this->filesDirectory . 'bar.xml')
        );

        try {
            $this->assertStringNotEqualsFile(
              $this->filesDirectory . 'foo.xml',
              file_get_contents($this->filesDirectory . 'foo.xml')
            );
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertStringStartsWith
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertStringStartsWithThrowsException()
    {
        $this->assertStringStartsWith(NULL, NULL);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertStringStartsWith
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertStringStartsWithThrowsException2()
    {
        $this->assertStringStartsWith('', NULL);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertStringStartsNotWith
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertStringStartsNotWithThrowsException()
    {
        $this->assertStringStartsNotWith(NULL, NULL);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertStringStartsNotWith
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertStringStartsNotWithThrowsException2()
    {
        $this->assertStringStartsNotWith('', NULL);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertStringEndsWith
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertStringEndsWithThrowsException()
    {
        $this->assertStringEndsWith(NULL, NULL);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertStringEndsWith
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertStringEndsWithThrowsException2()
    {
        $this->assertStringEndsWith('', NULL);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertStringEndsNotWith
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertStringEndsNotWithThrowsException()
    {
        $this->assertStringEndsNotWith(NULL, NULL);
    }

    /**
     * @covers            PHPUnit_Framework_Assert::assertStringEndsNotWith
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testAssertStringEndsNotWithThrowsException2()
    {
        $this->assertStringEndsNotWith('', NULL);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertStringStartsWith
     */
    public function testAssertStringStartsWith()
    {
        $this->assertStringStartsWith('prefix', 'prefixfoo');

        try {
            $this->assertStringStartsWith('prefix', 'foo');
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertStringStartsNotWith
     */
    public function testAssertStringStartsNotWith()
    {
        $this->assertStringStartsNotWith('prefix', 'foo');

        try {
            $this->assertStringStartsNotWith('prefix', 'prefixfoo');
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertStringEndsWith
     */
    public function testAssertStringEndsWith()
    {
        $this->assertStringEndsWith('suffix', 'foosuffix');

        try {
            $this->assertStringEndsWith('suffix', 'foo');
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertStringEndsNotWith
     */
    public function testAssertStringEndsNotWith()
    {
        $this->assertStringEndsNotWith('suffix', 'foo');

        try {
            $this->assertStringEndsNotWith('suffix', 'foosuffix');
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertStringMatchesFormat
     */
    public function testAssertStringMatchesFormat()
    {
        $this->assertStringMatchesFormat('*%s*', '***');
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertStringMatchesFormat
     * @expectedException PHPUnit_Framework_AssertionFailedError
     */
    public function testAssertStringMatchesFormatFailure()
    {
        $this->assertStringMatchesFormat('*%s*', '**');
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertStringNotMatchesFormat
     */
    public function testAssertStringNotMatchesFormat()
    {
        $this->assertStringNotMatchesFormat('*%s*', '**');

        try {
            $this->assertStringMatchesFormat('*%s*', '**');
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertEmpty
     */
    public function testAssertEmpty()
    {
        $this->assertEmpty(array());

        try {
            $this->assertEmpty(array('foo'));
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertNotEmpty
     */
    public function testAssertNotEmpty()
    {
        $this->assertNotEmpty(array('foo'));

        try {
            $this->assertNotEmpty(array());
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeEmpty
     */
    public function testAssertAttributeEmpty()
    {
        $o    = new StdClass;
        $o->a = array();

        $this->assertAttributeEmpty('a', $o);

        try {
            $o->a = array('b');
            $this->assertAttributeEmpty('a', $o);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertAttributeNotEmpty
     */
    public function testAssertAttributeNotEmpty()
    {
        $o    = new StdClass;
        $o->a = array('b');

        $this->assertAttributeNotEmpty('a', $o);

        try {
            $o->a = array();
            $this->assertAttributeNotEmpty('a', $o);
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::markTestIncomplete
     */
    public function testMarkTestIncomplete()
    {
        try {
            $this->markTestIncomplete('incomplete');
        }

        catch (PHPUnit_Framework_IncompleteTestError $e) {
            $this->assertEquals('incomplete', $e->getMessage());

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::markTestSkipped
     */
    public function testMarkTestSkipped()
    {
        try {
            $this->markTestSkipped('skipped');
        }

        catch (PHPUnit_Framework_SkippedTestError $e) {
            $this->assertEquals('skipped', $e->getMessage());

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertCount
     */
    public function testAssertCount()
    {
        $this->assertCount(2, array(1,2));

        try {
            $this->assertCount(2, array(1,2,3));
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertCount
     */
    public function testAssertCountThrowsExceptionIfExpectedCountIsNoInteger()
    {

        try {
            $this->assertCount('a', array());
        }

        catch (PHPUnit_Framework_Exception $e) {
            $this->assertEquals('Argument #1 of PHPUnit_Framework_Assert::assertCount() must be a integer', $e->getMessage());

            return;
        }

        $this->fail();
    }


    /**
     * @covers PHPUnit_Framework_Assert::assertCount
     */
    public function testAssertCountThrowsExceptionIfElementIsNotCountable()
    {

        try {
            $this->assertCount(2, '');
        }

        catch (PHPUnit_Framework_Exception $e) {
            $this->assertEquals('Argument #2 of PHPUnit_Framework_Assert::assertCount() must be a countable', $e->getMessage());

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertSameSize
     */
    public function testAssertSameSize()
    {
        $this->assertSameSize(array(1,2), array(3,4));

        try {
            $this->assertSameSize(array(1,2), array(1,2,3));
        }

        catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertSameSize
     */
    public function testAssertSameSizeThrowsExceptionIfExpectedIsNotCoutable()
    {

        try {
            $this->assertSameSize('a', array());
        }

        catch (PHPUnit_Framework_Exception $e) {
            $this->assertEquals('Argument #1 of PHPUnit_Framework_Assert::assertSameSize() must be a countable', $e->getMessage());

            return;
        }

        $this->fail();
    }


    /**
     * @covers PHPUnit_Framework_Assert::assertSameSize
     */
    public function testAssertSameSizeThrowsExceptionIfActualIsNotCountable()
    {

        try {
            $this->assertSameSize(array(), '');
        }

        catch (PHPUnit_Framework_Exception $e) {
            $this->assertEquals('Argument #2 of PHPUnit_Framework_Assert::assertSameSize() must be a countable', $e->getMessage());

            return;
        }

        $this->fail();
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertJsonStringEqualsJsonString
     */
    public function testAssertJsonStringEqualsJsonString()
    {
        $expected = '{"Mascott" : "Tux"}';
        $actual   = '{"Mascott" : "Tux"}';
        $message  = 'Given Json strings do not match';

        $this->assertJsonStringEqualsJsonString($expected, $actual, $message);
    }

    /**
     * @dataProvider validInvalidJsonDataprovider
     * @covers PHPUnit_Framework_Assert::assertJsonStringEqualsJsonString
     */
    public function testAssertJsonStringEqualsJsonStringErrorRaised($expected, $actual)
    {
        try {
            $this->assertJsonStringEqualsJsonString($expected, $actual);
        } catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }
        $this->fail('Expected exception not found');
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertJsonStringNotEqualsJsonString
     */
    public function testAssertJsonStringNotEqualsJsonString()
    {
        $expected = '{"Mascott" : "Beastie"}';
        $actual   = '{"Mascott" : "Tux"}';
        $message  = 'Given Json strings do match';

        $this->assertJsonStringNotEqualsJsonString($expected, $actual, $message);
    }

    /**
     * @dataProvider validInvalidJsonDataprovider
     * @covers PHPUnit_Framework_Assert::assertJsonStringNotEqualsJsonString
     */
    public function testAssertJsonStringNotEqualsJsonStringErrorRaised($expected, $actual)
    {
        try {
            $this->assertJsonStringNotEqualsJsonString($expected, $actual);
        } catch (PHPUnit_Framework_AssertionFailedError $e) {
            return;
        }
        $this->fail('Expected exception not found');
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertJsonStringEqualsJsonFile
     */
    public function testAssertJsonStringEqualsJsonFile()
    {
        $file = __DIR__ . '/../_files/JsonData/simpleObject.js';
        $actual = json_encode(array("Mascott" => "Tux"));
        $message = '';
        $this->assertJsonStringEqualsJsonFile($file, $actual, $message);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertJsonStringEqualsJsonFile
     */
    public function testAssertJsonStringEqualsJsonFileExpectingExpectationFailedException()
    {
        $file = __DIR__ . '/../_files/JsonData/simpleObject.js';
        $actual = json_encode(array("Mascott" => "Beastie"));
        $message = '';
        try {
            $this->assertJsonStringEqualsJsonFile($file, $actual, $message);
        } catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertEquals(
                'Failed asserting that \'{"Mascott":"Beastie"}\' matches JSON string "{"Mascott":"Tux"}".',
                $e->getMessage()
            );
            return;
        }

        $this->fail('Expected Exception not thrown.');
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertJsonStringEqualsJsonFile
     */
    public function testAssertJsonStringEqualsJsonFileExpectingException()
    {
        $file = __DIR__ . '/../_files/JsonData/simpleObject.js';
        try {
            $this->assertJsonStringEqualsJsonFile($file, NULL);
        } catch (PHPUnit_Framework_Exception $e) {
            return;
        }
        $this->fail('Expected Exception not thrown.');
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertJsonStringNotEqualsJsonFile
     */
    public function testAssertJsonStringNotEqualsJsonFile()
    {
        $file = __DIR__ . '/../_files/JsonData/simpleObject.js';
        $actual = json_encode(array("Mascott" => "Beastie"));
        $message = '';
        $this->assertJsonStringNotEqualsJsonFile($file, $actual, $message);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertJsonStringNotEqualsJsonFile
     */
    public function testAssertJsonStringNotEqualsJsonFileExpectingException()
    {
        $file = __DIR__ . '/../_files/JsonData/simpleObject.js';
        try {
            $this->assertJsonStringNotEqualsJsonFile($file, NULL);
        } catch (PHPUnit_Framework_Exception $e) {
            return;
        }
        $this->fail('Expected exception not found.');
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertJsonFileNotEqualsJsonFile
     */
    public function testAssertJsonFileNotEqualsJsonFile()
    {
        $fileExpected = __DIR__ . '/../_files/JsonData/simpleObject.js';
        $fileActual   = __DIR__ . '/../_files/JsonData/arrayObject.js';
        $message = '';
        $this->assertJsonFileNotEqualsJsonFile($fileExpected, $fileActual, $message);
    }

    /**
     * @covers PHPUnit_Framework_Assert::assertJsonFileEqualsJsonFile
     */
    public function testAssertJsonFileEqualsJsonFile()
    {
        $file = __DIR__ . '/../_files/JsonData/simpleObject.js';
        $message = '';
        $this->assertJsonFileEqualsJsonFile($file, $file, $message);
    }

    public static function validInvalidJsonDataprovider()
    {
        return array(
            'error syntax in expected JSON' => array('{"Mascott"::}', '{"Mascott" : "Tux"}'),
            'error UTF-8 in actual JSON'    => array('{"Mascott" : "Tux"}', '{"Mascott" : :}'),
        );
    }

}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'InheritedTestCase.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'NoTestCaseClass.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'NoTestCases.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'NotPublicTestCase.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'NotVoidTestCase.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'OneTestCase.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'OverrideTestCase.php';

/**
 *
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.0.0
 */
class Framework_SuiteTest extends PHPUnit_Framework_TestCase {
    protected $result;

    protected function setUp()
    {
        $this->result = new PHPUnit_Framework_TestResult;
    }

    public static function suite()
    {
        $suite = new PHPUnit_Framework_TestSuite;

        $suite->addTest(new Framework_SuiteTest('testAddTestSuite'));
        $suite->addTest(new Framework_SuiteTest('testInheritedTests'));
        $suite->addTest(new Framework_SuiteTest('testNoTestCases'));
        $suite->addTest(new Framework_SuiteTest('testNoTestCaseClass'));
        $suite->addTest(new Framework_SuiteTest('testNotExistingTestCase'));
        $suite->addTest(new Framework_SuiteTest('testNotPublicTestCase'));
        $suite->addTest(new Framework_SuiteTest('testNotVoidTestCase'));
        $suite->addTest(new Framework_SuiteTest('testOneTestCase'));
        $suite->addTest(new Framework_SuiteTest('testShadowedTests'));

        return $suite;
    }

    public function testAddTestSuite()
    {
        $suite = new PHPUnit_Framework_TestSuite(
          'OneTestCase'
        );

        $suite->run($this->result);

        $this->assertEquals(1, count($this->result));
    }

    public function testInheritedTests()
    {
        $suite = new PHPUnit_Framework_TestSuite(
          'InheritedTestCase'
        );

        $suite->run($this->result);

        $this->assertTrue($this->result->wasSuccessful());
        $this->assertEquals(2, count($this->result));
    }

    public function testNoTestCases()
    {
        $suite = new PHPUnit_Framework_TestSuite(
          'NoTestCases'
        );

        $suite->run($this->result);

        $this->assertTrue(!$this->result->wasSuccessful());
        $this->assertEquals(1, $this->result->failureCount());
        $this->assertEquals(1, count($this->result));
    }

    /**
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testNoTestCaseClass()
    {
        $suite = new PHPUnit_Framework_TestSuite('NoTestCaseClass');
    }

    public function testNotExistingTestCase()
    {
        $suite = new Framework_SuiteTest('notExistingMethod');

        $suite->run($this->result);

        $this->assertEquals(0, $this->result->errorCount());
        $this->assertEquals(1, $this->result->failureCount());
        $this->assertEquals(1, count($this->result));
    }

    public function testNotPublicTestCase()
    {
        $suite = new PHPUnit_Framework_TestSuite(
          'NotPublicTestCase'
        );

        $this->assertEquals(2, count($suite));
    }

    public function testNotVoidTestCase()
    {
        $suite = new PHPUnit_Framework_TestSuite(
          'NotVoidTestCase'
        );

        $this->assertEquals(1, count($suite));
    }

    public function testOneTestCase()
    {
        $suite = new PHPUnit_Framework_TestSuite(
          'OneTestCase'
        );

        $suite->run($this->result);

        $this->assertEquals(0, $this->result->errorCount());
        $this->assertEquals(0, $this->result->failureCount());
        $this->assertEquals(1, count($this->result));
        $this->assertTrue($this->result->wasSuccessful());
    }

    public function testShadowedTests()
    {
        $suite = new PHPUnit_Framework_TestSuite(
          'OverrideTestCase'
        );

        $suite->run($this->result);

        $this->assertEquals(1, count($this->result));
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'DoubleTestCase.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'Success.php';

/**
 *
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.0.0
 */
class Framework_TestImplementorTest extends PHPUnit_Framework_TestCase
{
    protected $test;

    public function __construct()
    {
        $this->test = new DoubleTestCase(
          new Success
        );
    }

    public function testSuccessfulRun()
    {
        $result = new PHPUnit_Framework_TestResult;

        $this->test->run($result);

        $this->assertEquals(count($this->test), count($result));
        $this->assertEquals(0, $result->errorCount());
        $this->assertEquals(0, $result->failureCount());
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2001-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 2.0.0
 */

require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'MockRunner.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'NonStatic.php';

/**
 *
 *
 * @package    PHPUnit
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2001-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 2.0.0
 */
class Runner_BaseTestRunnerTest extends PHPUnit_Framework_TestCase
{
    public function testInvokeNonStaticSuite()
    {
        $runner = new MockRunner;
        $runner->getTest('NonStatic');
    }
}
{
    "name": "phpunit/phpunit-mock-objects",
    "description": "Mock Object library for PHPUnit",
    "type": "library",
    "keywords": [
        "xunit",
        "mock"
    ],
    "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
    "license": "BSD-3-Clause",
    "authors": [
        {
            "name": "Sebastian Bergmann",
            "email": "sb@sebastian-bergmann.de",
            "role": "lead"
        }
    ],
    "support": {
        "issues": "https://github.com/sebastianbergmann/phpunit-mock-objects/issues",
        "irc": "irc://irc.freenode.net/phpunit"
    },
    "require": {
        "php": ">=5.3.3",
        "phpunit/php-text-template": ">=1.1.1@stable"
    },
    "suggest": {
        "ext-soap": "*"
    },
    "autoload": {
        "classmap": [
            "PHPUnit/"
        ]
    },
    "include-path": [
        ""
    ]
}
<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.4.10" version="2.0"
  xmlns="http://pear.php.net/dtd/package-2.0"
  xmlns:tasks="http://pear.php.net/dtd/tasks-1.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
                      http://pear.php.net/dtd/tasks-1.0.xsd
                      http://pear.php.net/dtd/package-2.0
                      http://pear.php.net/dtd/package-2.0.xsd">
 <name>PHPUnit_MockObject</name>
 <channel>pear.phpunit.de</channel>
 <summary>Mock Object library for PHPUnit</summary>
 <description>Mock Object library for PHPUnit</description>
 <lead>
  <name>Sebastian Bergmann</name>
  <user>sb</user>
  <email>sb@sebastian-bergmann.de</email>
  <active>yes</active>
 </lead>
 <date>2013-01-13</date>
 <version>
  <release>1.2.3</release>
  <api>1.2.0</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license>The BSD 3-Clause License</license>
 <notes>http://github.com/sebastianbergmann/phpunit-mock-objects/blob/master/README.markdown</notes>
 <contents>
  <dir name="/">
   <dir name="PHPUnit">
    <dir name="Framework">
     <dir name="MockObject">
      <dir name="Builder">
       <file baseinstalldir="/" name="Identity.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
       <file baseinstalldir="/" name="InvocationMocker.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
       <file baseinstalldir="/" name="Match.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
       <file baseinstalldir="/" name="MethodNameMatch.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
       <file baseinstalldir="/" name="Namespace.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
       <file baseinstalldir="/" name="ParametersMatch.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
       <file baseinstalldir="/" name="Stub.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
      </dir>
      <dir name="Generator">
       <file baseinstalldir="/" name="mocked_class.tpl.dist" role="php" />
       <file baseinstalldir="/" name="mocked_clone.tpl.dist" role="php" />
       <file baseinstalldir="/" name="mocked_object_method.tpl.dist" role="php" />
       <file baseinstalldir="/" name="mocked_static_method.tpl.dist" role="php" />
       <file baseinstalldir="/" name="trait_class.tpl.dist" role="php" />
       <file baseinstalldir="/" name="unmocked_clone.tpl.dist" role="php" />
       <file baseinstalldir="/" name="wsdl_class.tpl.dist" role="php" />
       <file baseinstalldir="/" name="wsdl_method.tpl.dist" role="php" />
      </dir>
      <dir name="Invocation">
       <file baseinstalldir="/" name="Object.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
       <file baseinstalldir="/" name="Static.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
      </dir>
      <dir name="Matcher">
       <file baseinstalldir="/" name="AnyInvokedCount.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
       <file baseinstalldir="/" name="AnyParameters.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
       <file baseinstalldir="/" name="Invocation.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
       <file baseinstalldir="/" name="InvokedAtIndex.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
       <file baseinstalldir="/" name="InvokedAtLeastOnce.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
       <file baseinstalldir="/" name="InvokedCount.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
       <file baseinstalldir="/" name="InvokedRecorder.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
       <file baseinstalldir="/" name="MethodName.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
       <file baseinstalldir="/" name="Parameters.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
       <file baseinstalldir="/" name="StatelessInvocation.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
      </dir>
      <dir name="Stub">
       <file baseinstalldir="/" name="ConsecutiveCalls.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
       <file baseinstalldir="/" name="Exception.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
       <file baseinstalldir="/" name="MatcherCollection.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
       <file baseinstalldir="/" name="Return.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
       <file baseinstalldir="/" name="ReturnArgument.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
       <file baseinstalldir="/" name="ReturnCallback.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
       <file baseinstalldir="/" name="ReturnSelf.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
       <file baseinstalldir="/" name="ReturnValueMap.php" role="php">
        <tasks:replace from="@package_version@" to="version" type="package-info" />
       </file>
      </dir>
      <file baseinstalldir="/" name="Autoload.php" role="php">
       <tasks:replace from="@package_version@" to="version" type="package-info" />
      </file>
      <file baseinstalldir="/" name="Generator.php" role="php">
       <tasks:replace from="@package_version@" to="version" type="package-info" />
      </file>
      <file baseinstalldir="/" name="InvocationMocker.php" role="php">
       <tasks:replace from="@package_version@" to="version" type="package-info" />
      </file>
      <file baseinstalldir="/" name="Invocation.php" role="php">
       <tasks:replace from="@package_version@" to="version" type="package-info" />
      </file>
      <file baseinstalldir="/" name="Invokable.php" role="php">
       <tasks:replace from="@package_version@" to="version" type="package-info" />
      </file>
      <file baseinstalldir="/" name="Matcher.php" role="php">
       <tasks:replace from="@package_version@" to="version" type="package-info" />
      </file>
      <file baseinstalldir="/" name="MockBuilder.php" role="php">
       <tasks:replace from="@package_version@" to="version" type="package-info" />
      </file>
      <file baseinstalldir="/" name="MockObject.php" role="php">
       <tasks:replace from="@package_version@" to="version" type="package-info" />
      </file>
      <file baseinstalldir="/" name="Stub.php" role="php">
       <tasks:replace from="@package_version@" to="version" type="package-info" />
      </file>
      <file baseinstalldir="/" name="Verifiable.php" role="php">
       <tasks:replace from="@package_version@" to="version" type="package-info" />
      </file>
     </dir>
    </dir>
   </dir>
   <file baseinstalldir="/" name="ChangeLog.markdown" role="doc"/>
   <file baseinstalldir="/" name="LICENSE" role="doc"/>
  </dir>
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.3.3</min>
   </php>
   <pearinstaller>
    <min>1.9.4</min>
   </pearinstaller>
   <package>
    <name>Text_Template</name>
    <channel>pear.phpunit.de</channel>
    <min>1.1.1</min>
   </package>
  </required>
  <optional>
   <extension>
    <name>soap</name>
   </extension>
  </optional>
 </dependencies>
 <phprelease/>
</package>
<?xml version="1.0"?>

<ruleset name="Sebastian"
         xmlns="http://pmd.sf.net/ruleset/1.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
         xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
  <description>Sebastian Bergmann's ruleset</description>

  <rule ref="rulesets/codesize.xml/CyclomaticComplexity" />
  <rule ref="rulesets/codesize.xml/NPathComplexity" />
  <rule ref="rulesets/codesize.xml/ExcessiveClassComplexity" />
  <rule ref="rulesets/codesize.xml/ExcessiveClassLength" />
  <rule ref="rulesets/codesize.xml/ExcessiveMethodLength" />
  <rule ref="rulesets/codesize.xml/ExcessiveParameterList" />

  <rule ref="rulesets/design.xml/EvalExpression" />
  <rule ref="rulesets/design.xml/ExitExpression" />
  <rule ref="rulesets/design.xml/GotoStatement" />

  <rule ref="rulesets/naming.xml/ConstructorWithNameAsEnclosingClass" />

  <rule ref="rulesets/unusedcode.xml/UnusedFormalParameter" />
  <rule ref="rulesets/unusedcode.xml/UnusedLocalVariable" />
  <rule ref="rulesets/unusedcode.xml/UnusedPrivateField" />
  <rule ref="rulesets/unusedcode.xml/UnusedPrivateMethod" />
</ruleset>
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         colors="true">
  <php>
    <const name="PHPUNIT_TESTSUITE" value="true"/>
  </php>

  <testsuites>
    <testsuite name="PHPUnit Mock Objects">
      <directory suffix="Test.php">../Tests</directory>
      <directory suffix=".phpt">../Tests</directory>
    </testsuite>
  </testsuites>

  <logging>
    <log type="coverage-text" target="php://stdout"/>
  </logging>

  <filter>
    <whitelist addUncoveredFilesFromWhitelist="true">
      <directory suffix=".php">../PHPUnit</directory>
      <exclude>
       <file>../PHPUnit/Framework/MockObject/Autoload.php</file>
      </exclude>
    </whitelist>
  </filter>
</phpunit>
<?php
class PHPCS_Sniffs_ControlStructures_ControlSignatureSniff extends PHP_CodeSniffer_Standards_AbstractPatternSniff
{
    public function __construct()
    {
        parent::__construct(true);
    }

    protected function getPatterns()
    {
        return array(
          'do {EOL...} while (...);EOL',
          'while (...) {EOL',
          'for (...) {EOL',
          'if (...) {EOL',
          'foreach (...) {EOL',
          '}EOLelse if (...) {EOL',
          '}EOLelse {EOL',
          'do {EOL',
        );
    }
}
<?php
class PHPCS_Sniffs_Whitespace_ConcatenationSpacingSniff implements PHP_CodeSniffer_Sniff
{
    public function register()
    {
        return array(T_STRING_CONCAT);
    }

    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE ||
            $tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) {

            $phpcsFile->addError(
              'Concatenation operator must be surrounded by whitespace',
              $stackPtr
            );
        }
    }
}
<?xml version="1.0"?>
<ruleset name="Sebastian">
 <description>Sebastian Bergmann's coding standard</description>

 <rule ref="Generic.CodeAnalysis.ForLoopShouldBeWhileLoop"/>
 <rule ref="Generic.CodeAnalysis.ForLoopWithTestFunctionCall"/>
 <rule ref="Generic.CodeAnalysis.JumbledIncrementer"/>
 <rule ref="Generic.CodeAnalysis.UnconditionalIfStatement"/>
 <rule ref="Generic.CodeAnalysis.UnnecessaryFinalModifier"/>
 <rule ref="Generic.CodeAnalysis.UselessOverridingMethod"/>

 <rule ref="Generic.Commenting.Todo"/>

 <rule ref="Generic.ControlStructures.InlineControlStructure"/>

 <rule ref="Generic.Files.LineEndings"/>

 <rule ref="Generic.Formatting.DisallowMultipleStatements"/>
 <rule ref="Generic.Formatting.NoSpaceAfterCast"/>

 <rule ref="Generic.Functions.OpeningFunctionBraceBsdAllman"/>
 <rule ref="PEAR.Functions.ValidDefaultValue"/>

 <rule ref="Generic.NamingConventions.ConstructorName"/>
 <rule ref="Generic.NamingConventions.UpperCaseConstantName"/>
 <rule ref="PEAR.NamingConventions.ValidClassName"/>

 <rule ref="Generic.PHP.DisallowShortOpenTag"/>
 <rule ref="Generic.PHP.NoSilencedErrors"/>
 <rule ref="Generic.PHP.UpperCaseConstant"/>

 <rule ref="Generic.WhiteSpace.DisallowTabIndent"/>
 <rule ref="Generic.WhiteSpace.ScopeIndent"/>
 <rule ref="Squiz.WhiteSpace.SuperfluousWhitespace"/>
</ruleset>
PHPUnit_MockObject

Copyright (c) 2002-2013, Sebastian Bergmann <sebastian@phpunit.de>.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

 * Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in
   the documentation and/or other materials provided with the
   distribution.

 * Neither the name of Sebastian Bergmann nor the names of his
   contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Invocation matcher which checks if a method has been invoked a certain amount
 * of times.
 * If the number of invocations exceeds the value it will immediately throw an
 * exception,
 * If the number is less it will later be checked in verify() and also throw an
 * exception.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Class available since Release 1.0.0
 */
class PHPUnit_Framework_MockObject_Matcher_InvokedCount extends PHPUnit_Framework_MockObject_Matcher_InvokedRecorder
{
    /**
     * @var integer
     */
    protected $expectedCount;

    /**
     * @param interger $expectedCount
     */
    public function __construct($expectedCount)
    {
        $this->expectedCount = $expectedCount;
    }

    /**
     * @return string
     */
    public function toString()
    {
        return 'invoked ' . $this->expectedCount . ' time(s)';
    }

    /**
     * @param  PHPUnit_Framework_MockObject_Invocation $invocation
     * @throws PHPUnit_Framework_ExpectationFailedException
     */
    public function invoked(PHPUnit_Framework_MockObject_Invocation $invocation)
    {
        parent::invoked($invocation);

        $count = $this->getInvocationCount();

        if ($count > $this->expectedCount) {
            $message = $invocation->toString() . ' ';

            switch ($this->expectedCount) {
                case 0: {
                    $message .= 'was not expected to be called.';
                }
                break;

                case 1: {
                    $message .= 'was not expected to be called more than once.';
                }
                break;

                default: {
                    $message .= sprintf(
                      'was not expected to be called more than %d times.',

                      $this->expectedCount
                    );
                }
            }

            throw new PHPUnit_Framework_ExpectationFailedException($message);
        }
    }

    /**
     * Verifies that the current expectation is valid. If everything is OK the
     * code should just return, if not it must throw an exception.
     *
     * @throws PHPUnit_Framework_ExpectationFailedException
     */
    public function verify()
    {
        $count = $this->getInvocationCount();

        if ($count !== $this->expectedCount) {
            throw new PHPUnit_Framework_ExpectationFailedException(
              sprintf(
                'Method was expected to be called %d times, ' .
                'actually called %d times.',

                $this->expectedCount,
                $count
              )
            );
        }
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Invocation matcher which looks for a specific method name in the invocations.
 *
 * Checks the method name all incoming invocations, the name is checked against
 * the defined constraint $constraint. If the constraint is met it will return
 * true in matches().
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Class available since Release 1.0.0
 */
class PHPUnit_Framework_MockObject_Matcher_MethodName extends PHPUnit_Framework_MockObject_Matcher_StatelessInvocation
{
    /**
     * @var PHPUnit_Framework_Constraint
     */
    protected $constraint;

    /**
     * @param  PHPUnit_Framework_Constraint|string
     * @throws PHPUnit_Framework_Constraint
     */
    public function __construct($constraint)
    {
        if (!$constraint instanceof PHPUnit_Framework_Constraint) {
            if (!is_string($constraint)) {
                throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
            }

            $constraint = new PHPUnit_Framework_Constraint_IsEqual(
              $constraint, 0, 10, FALSE, TRUE
            );
        }

        $this->constraint = $constraint;
    }

    /**
     * @return string
     */
    public function toString()
    {
        return 'method name ' . $this->constraint->toString();
    }

    /**
     * @param  PHPUnit_Framework_MockObject_Invocation $invocation
     * @return boolean
     */
    public function matches(PHPUnit_Framework_MockObject_Invocation $invocation)
    {
        return $this->constraint->evaluate($invocation->methodName, '', TRUE);
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Interface for classes which matches an invocation based on its
 * method name, argument, order or call count.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Interface available since Release 1.0.0
 */
interface PHPUnit_Framework_MockObject_Matcher_Invocation extends PHPUnit_Framework_SelfDescribing, PHPUnit_Framework_MockObject_Verifiable
{
    /**
     * Registers the invocation $invocation in the object as being invoked.
     * This will only occur after matches() returns true which means the
     * current invocation is the correct one.
     *
     * The matcher can store information from the invocation which can later
     * be checked in verify(), or it can check the values directly and throw
     * and exception if an expectation is not met.
     *
     * If the matcher is a stub it will also have a return value.
     *
     * @param  PHPUnit_Framework_MockObject_Invocation $invocation
     *         Object containing information on a mocked or stubbed method which
     *         was invoked.
     * @return mixed
     */
    public function invoked(PHPUnit_Framework_MockObject_Invocation $invocation);

    /**
     * Checks if the invocation $invocation matches the current rules. If it does
     * the matcher will get the invoked() method called which should check if an
     * expectation is met.
     *
     * @param  PHPUnit_Framework_MockObject_Invocation $invocation
     *         Object containing information on a mocked or stubbed method which
     *         was invoked.
     * @return bool
     */
    public function matches(PHPUnit_Framework_MockObject_Invocation $invocation);
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Invocation matcher which looks for specific parameters in the invocations.
 *
 * Checks the parameters of all incoming invocations, the parameter list is
 * checked against the defined constraints in $parameters. If the constraint
 * is met it will return true in matches().
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Class available since Release 1.0.0
 */
class PHPUnit_Framework_MockObject_Matcher_Parameters extends PHPUnit_Framework_MockObject_Matcher_StatelessInvocation
{
    /**
     * @var array
     */
    protected $parameters = array();

    /**
     * @var PHPUnit_Framework_MockObject_Invocation
     */
    protected $invocation;

    /**
     * @param array $parameters
     */
    public function __construct(array $parameters)
    {
        foreach ($parameters as $parameter) {
            if (!($parameter instanceof PHPUnit_Framework_Constraint)) {
                $parameter = new PHPUnit_Framework_Constraint_IsEqual(
                  $parameter
                );
            }

            $this->parameters[] = $parameter;
        }
    }

    /**
     * @return string
     */
    public function toString()
    {
        $text = 'with parameter';

        foreach ($this->parameters as $index => $parameter) {
            if ($index > 0) {
                $text .= ' and';
            }

            $text .= ' ' . $index . ' ' . $parameter->toString();
        }

        return $text;
    }

    /**
     * @param  PHPUnit_Framework_MockObject_Invocation $invocation
     * @return boolean
     */
    public function matches(PHPUnit_Framework_MockObject_Invocation $invocation)
    {
        $this->invocation = $invocation;
        $this->verify();

        return count($invocation->parameters) < count($this->parameters);
    }

    /**
     * Checks if the invocation $invocation matches the current rules. If it
     * does the matcher will get the invoked() method called which should check
     * if an expectation is met.
     *
     * @param  PHPUnit_Framework_MockObject_Invocation $invocation
     *         Object containing information on a mocked or stubbed method which
     *         was invoked.
     * @return bool
     * @throws PHPUnit_Framework_ExpectationFailedException
     */
    public function verify()
    {
        if ($this->invocation === NULL) {
            throw new PHPUnit_Framework_ExpectationFailedException(
              'Mocked method does not exist.'
            );
        }

        if (count($this->invocation->parameters) < count($this->parameters)) {
            throw new PHPUnit_Framework_ExpectationFailedException(
              sprintf(
                'Parameter count for invocation %s is too low.',

                $this->invocation->toString()
              )
            );
        }

        foreach ($this->parameters as $i => $parameter) {
            $parameter->evaluate(
              $this->invocation->parameters[$i],
              sprintf(
                'Parameter %s for invocation %s does not match expected ' .
                'value.',

                $i,
                $this->invocation->toString()
              )
            );
        }
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Invocation matcher which allos any parameters to a method.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Class available since Release 1.0.0
 */
class PHPUnit_Framework_MockObject_Matcher_AnyParameters extends PHPUnit_Framework_MockObject_Matcher_StatelessInvocation
{
    /**
     * @return string
     */
    public function toString()
    {
        return 'with any parameters';
    }

    /**
     * @param  PHPUnit_Framework_MockObject_Invocation $invocation
     * @return boolean
     */
    public function matches(PHPUnit_Framework_MockObject_Invocation $invocation)
    {
        return TRUE;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Records invocations and provides convenience methods for checking them later
 * on.
 * This abstract class can be implemented by matchers which needs to check the
 * number of times an invocation has occured.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Class available since Release 1.0.0
 * @abstract
 */
abstract class PHPUnit_Framework_MockObject_Matcher_InvokedRecorder implements PHPUnit_Framework_MockObject_Matcher_Invocation
{
    /**
     * @var PHPUnit_Framework_MockObject_Invocation[]
     */
    protected $invocations = array();

    /**
     * @return integer
     */
    public function getInvocationCount()
    {
        return count($this->invocations);
    }

    /**
     * @return PHPUnit_Framework_MockObject_Invocation[]
     */
    public function getInvocations()
    {
        return $this->invocations;
    }

    /**
     * @return boolean
     */
    public function hasBeenInvoked()
    {
        return count($this->invocations) > 0;
    }

    /**
     * @param PHPUnit_Framework_MockObject_Invocation $invocation
     */
    public function invoked(PHPUnit_Framework_MockObject_Invocation $invocation)
    {
        $this->invocations[] = $invocation;
    }

    /**
     * @param  PHPUnit_Framework_MockObject_Invocation $invocation
     * @return boolean
     */
    public function matches(PHPUnit_Framework_MockObject_Invocation $invocation)
    {
        return TRUE;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Invocation matcher which checks if a method was invoked at a certain index.
 *
 * If the expected index number does not match the current invocation index it
 * will not match which means it skips all method and parameter matching. Only
 * once the index is reached will the method and parameter start matching and
 * verifying.
 *
 * If the index is never reached it will throw an exception in index.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Class available since Release 1.0.0
 */
class PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex implements PHPUnit_Framework_MockObject_Matcher_Invocation
{
    /**
     * @var integer
     */
    protected $sequenceIndex;

    /**
     * @var integer
     */
    protected $currentIndex = -1;

    /**
     * @param integer $sequenceIndex
     */
    public function __construct($sequenceIndex)
    {
        $this->sequenceIndex = $sequenceIndex;
    }

    /**
     * @return string
     */
    public function toString()
    {
        return 'invoked at sequence index ' . $this->sequenceIndex;
    }

    /**
     * @param  PHPUnit_Framework_MockObject_Invocation $invocation
     * @return boolean
     */
    public function matches(PHPUnit_Framework_MockObject_Invocation $invocation)
    {
        $this->currentIndex++;

        return $this->currentIndex == $this->sequenceIndex;
    }

    /**
     * @param PHPUnit_Framework_MockObject_Invocation $invocation
     */
    public function invoked(PHPUnit_Framework_MockObject_Invocation $invocation)
    {
    }

    /**
     * Verifies that the current expectation is valid. If everything is OK the
     * code should just return, if not it must throw an exception.
     *
     * @throws PHPUnit_Framework_ExpectationFailedException
     */
    public function verify()
    {
        if ($this->currentIndex < $this->sequenceIndex) {
            throw new PHPUnit_Framework_ExpectationFailedException(
              sprintf(
                'The expected invocation at index %s was never reached.',

                $this->sequenceIndex
              )
            );
        }
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Invocation matcher which checks if a method has been invoked zero or more
 * times. This matcher will always match.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Class available since Release 1.0.0
 */
class PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount extends PHPUnit_Framework_MockObject_Matcher_InvokedRecorder
{
    /**
     * @return string
     */
    public function toString()
    {
        return 'invoked zero or more times';
    }

    /**
     */
    public function verify()
    {
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Invocation matcher which does not care about previous state from earlier
 * invocations.
 *
 * This abstract class can be implemented by matchers which does not care about
 * state but only the current run-time value of the invocation itself.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Class available since Release 1.0.0
 * @abstract
 */
abstract class PHPUnit_Framework_MockObject_Matcher_StatelessInvocation implements PHPUnit_Framework_MockObject_Matcher_Invocation
{
    /**
     * Registers the invocation $invocation in the object as being invoked.
     * This will only occur after matches() returns true which means the
     * current invocation is the correct one.
     *
     * The matcher can store information from the invocation which can later
     * be checked in verify(), or it can check the values directly and throw
     * and exception if an expectation is not met.
     *
     * If the matcher is a stub it will also have a return value.
     *
     * @param  PHPUnit_Framework_MockObject_Invocation $invocation
     *         Object containing information on a mocked or stubbed method which
     *         was invoked.
     * @return mixed
     */
    public function invoked(PHPUnit_Framework_MockObject_Invocation $invocation)
    {
    }

    /**
     * Checks if the invocation $invocation matches the current rules. If it does
     * the matcher will get the invoked() method called which should check if an
     * expectation is met.
     *
     * @param  PHPUnit_Framework_MockObject_Invocation $invocation
     *         Object containing information on a mocked or stubbed method which
     *         was invoked.
     * @return bool
     */
    public function verify()
    {
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Invocation matcher which checks if a method has been invoked at least one
 * time.
 *
 * If the number of invocations is 0 it will throw an exception in verify.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Class available since Release 1.0.0
 */
class PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastOnce extends PHPUnit_Framework_MockObject_Matcher_InvokedRecorder
{
    /**
     * @return string
     */
    public function toString()
    {
        return 'invoked at least once';
    }

    /**
     * Verifies that the current expectation is valid. If everything is OK the
     * code should just return, if not it must throw an exception.
     *
     * @throws PHPUnit_Framework_ExpectationFailedException
     */
    public function verify()
    {
        $count = $this->getInvocationCount();

        if ($count < 1) {
            throw new PHPUnit_Framework_ExpectationFailedException(
              'Expected invocation at least once but it never occured.'
            );
        }
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Interface for classes which can be invoked.
 *
 * The invocation will be taken from a mock object and passed to an object
 * of this class.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Interface available since Release 1.0.0
 */
interface PHPUnit_Framework_MockObject_Invokable extends PHPUnit_Framework_MockObject_Verifiable
{
    /**
     * Invokes the invocation object $invocation so that it can be checked for
     * expectations or matched against stubs.
     *
     * @param  PHPUnit_Framework_MockObject_Invocation $invocation
     *         The invocation object passed from mock object.
     * @return object
     */
    public function invoke(PHPUnit_Framework_MockObject_Invocation $invocation);

    /**
     * Checks if the invocation matches.
     *
     * @param  PHPUnit_Framework_MockObject_Invocation $invocation
     *         The invocation object passed from mock object.
     * @return boolean
     */
    public function matches(PHPUnit_Framework_MockObject_Invocation $invocation);
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Main matcher which defines a full expectation using method, parameter and
 * invocation matchers.
 * This matcher encapsulates all the other matchers and allows the builder to
 * set the specific matchers when the appropriate methods are called (once(),
 * where() etc.).
 *
 * All properties are public so that they can easily be accessed by the builder.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Class available since Release 1.0.0
 */
class PHPUnit_Framework_MockObject_Matcher implements PHPUnit_Framework_MockObject_Matcher_Invocation
{
    /**
     * @var PHPUnit_Framework_MockObject_Matcher_Invocation
     */
    public $invocationMatcher;

    /**
     * @var mixed
     */
    public $afterMatchBuilderId = NULL;

    /**
     * @var boolean
     */
    public $afterMatchBuilderIsInvoked = FALSE;

    /**
     * @var PHPUnit_Framework_MockObject_Matcher_MethodName
     */
    public $methodNameMatcher = NULL;

    /**
     * @var PHPUnit_Framework_MockObject_Matcher_Parameters
     */
    public $parametersMatcher = NULL;

    /**
     * @var PHPUnit_Framework_MockObject_Stub
     */
    public $stub = NULL;

    /**
     * @param PHPUnit_Framework_MockObject_Matcher_Invocation $invocationMatcher
     */
    public function __construct(PHPUnit_Framework_MockObject_Matcher_Invocation $invocationMatcher)
    {
        $this->invocationMatcher = $invocationMatcher;
    }

    /**
     * @return string
     */
    public function toString()
    {
        $list = array();

        if ($this->invocationMatcher !== NULL) {
            $list[] = $this->invocationMatcher->toString();
        }

        if ($this->methodNameMatcher !== NULL) {
            $list[] = 'where ' . $this->methodNameMatcher->toString();
        }

        if ($this->parametersMatcher !== NULL) {
            $list[] = 'and ' . $this->parametersMatcher->toString();
        }

        if ($this->afterMatchBuilderId !== NULL) {
            $list[] = 'after ' . $this->afterMatchBuilderId;
        }

        if ($this->stub !== NULL) {
            $list[] = 'will ' . $this->stub->toString();
        }

        return join(' ', $list);
    }

    /**
     * @param  PHPUnit_Framework_MockObject_Invocation $invocation
     * @return mixed
     */
    public function invoked(PHPUnit_Framework_MockObject_Invocation $invocation)
    {
        if ($this->invocationMatcher === NULL) {
            throw new PHPUnit_Framework_Exception(
              'No invocation matcher is set'
            );
        }

        if ($this->methodNameMatcher === NULL) {
            throw new PHPUnit_Framework_Exception('No method matcher is set');
        }

        if ($this->afterMatchBuilderId !== NULL) {
            $builder = $invocation->object
                                  ->__phpunit_getInvocationMocker()
                                  ->lookupId($this->afterMatchBuilderId);

            if (!$builder) {
                throw new PHPUnit_Framework_Exception(
                  sprintf(
                    'No builder found for match builder identification <%s>',

                    $this->afterMatchBuilderId
                  )
                );
            }

            $matcher = $builder->getMatcher();

            if ($matcher && $matcher->invocationMatcher->hasBeenInvoked()) {
                $this->afterMatchBuilderIsInvoked = TRUE;
            }
        }

        $this->invocationMatcher->invoked($invocation);

        try {
            if ( $this->parametersMatcher !== NULL &&
                !$this->parametersMatcher->matches($invocation)) {
                $this->parametersMatcher->verify();
            }
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            throw new PHPUnit_Framework_ExpectationFailedException(
              sprintf(
                "Expectation failed for %s when %s\n%s",

                $this->methodNameMatcher->toString(),
                $this->invocationMatcher->toString(),
                $e->getMessage()
              ),
              $e->getComparisonFailure()
            );
        }

        if ($this->stub) {
            return $this->stub->invoke($invocation);
        }

        return NULL;
    }

    /**
     * @param  PHPUnit_Framework_MockObject_Invocation $invocation
     * @return boolean
     */
    public function matches(PHPUnit_Framework_MockObject_Invocation $invocation)
    {
        if ($this->afterMatchBuilderId !== NULL) {
            $builder = $invocation->object
                                  ->__phpunit_getInvocationMocker()
                                  ->lookupId($this->afterMatchBuilderId);

            if (!$builder) {
                throw new PHPUnit_Framework_Exception(
                  sprintf(
                    'No builder found for match builder identification <%s>',

                    $this->afterMatchBuilderId
                  )
                );
            }

            $matcher = $builder->getMatcher();

            if (!$matcher) {
                return FALSE;
            }

            if (!$matcher->invocationMatcher->hasBeenInvoked()) {
                return FALSE;
            }
        }

        if ($this->invocationMatcher === NULL) {
            throw new PHPUnit_Framework_Exception(
              'No invocation matcher is set'
            );
        }

        if ($this->methodNameMatcher === NULL) {
            throw new PHPUnit_Framework_Exception('No method matcher is set');
        }

        if (!$this->invocationMatcher->matches($invocation)) {
            return FALSE;
        }

        try {
            if (!$this->methodNameMatcher->matches($invocation)) {
                return FALSE;
            }
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            throw new PHPUnit_Framework_ExpectationFailedException(
              sprintf(
                "Expectation failed for %s when %s\n%s",

                $this->methodNameMatcher->toString(),
                $this->invocationMatcher->toString(),
                $e->getMessage()
              ),
              $e->getComparisonFailure()
            );
        }

        return TRUE;
    }

    /**
     * @throws PHPUnit_Framework_Exception
     * @throws PHPUnit_Framework_ExpectationFailedException
     */
    public function verify()
    {
        if ($this->invocationMatcher === NULL) {
            throw new PHPUnit_Framework_Exception(
              'No invocation matcher is set'
            );
        }

        if ($this->methodNameMatcher === NULL) {
            throw new PHPUnit_Framework_Exception('No method matcher is set');
        }

        try {
            $this->invocationMatcher->verify();

            if ($this->parametersMatcher === NULL) {
                $this->parametersMatcher = new PHPUnit_Framework_MockObject_Matcher_AnyParameters;
            }

            $invocationIsAny = get_class($this->invocationMatcher) === 'PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount';
            if (!$invocationIsAny) {
                $this->parametersMatcher->verify();
            }
        }

        catch (PHPUnit_Framework_ExpectationFailedException $e) {
            throw new PHPUnit_Framework_ExpectationFailedException(
              sprintf(
                "Expectation failed for %s when %s.\n%s",

                $this->methodNameMatcher->toString(),
                $this->invocationMatcher->toString(),
                $e->getMessage()
              )
            );
        }
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Interface for all mock objects which are generated by
 * PHPUnit_Framework_MockObject_Mock.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Interface available since Release 1.0.0
 */
interface PHPUnit_Framework_MockObject_MockObject /*extends PHPUnit_Framework_MockObject_Verifiable*/
{
    /**
     * Registers a new expectation in the mock object and returns the match
     * object which can be infused with further details.
     *
     * @param  PHPUnit_Framework_MockObject_Matcher_Invocation $matcher
     * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker
     */
    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher);

    /**
     * Registers a new static expectation in the mock object and returns the
     * match object which can be infused with further details.
     *
     * @param  PHPUnit_Framework_MockObject_Matcher_Invocation $matcher
     * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker
     */
    public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher);

    /**
     * @return PHPUnit_Framework_MockObject_InvocationMocker
     */
    public function __phpunit_getInvocationMocker();

    /**
     * @return PHPUnit_Framework_MockObject_InvocationMocker
     */
    public static function __phpunit_getStaticInvocationMocker();

    /**
     * Verifies that the current expectation is valid. If everything is OK the
     * code should just return, if not it must throw an exception.
     *
     * @throws PHPUnit_Framework_ExpectationFailedException
     */
    public function __phpunit_verify();
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Builder interface for unique identifiers.
 *
 * Defines the interface for recording unique identifiers. The identifiers
 * can be used to define the invocation order of expectations. The expectation
 * is recorded using id() and then defined in order using
 * PHPUnit_Framework_MockObject_Builder_Match::after().
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Interface available since Release 1.0.0
 */
interface PHPUnit_Framework_MockObject_Builder_Identity
{
    /**
     * Sets the identification of the expectation to $id.
     *
     * @note The identifier is unique per mock object.
     * @param string $id Unique identifiation of expectation.
     */
    public function id($id);
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Builder interface for parameter matchers.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Interface available since Release 1.0.0
 */
interface PHPUnit_Framework_MockObject_Builder_ParametersMatch extends PHPUnit_Framework_MockObject_Builder_Match
{
    /**
     * Sets the parameters to match for, each parameter to this funtion will
     * be part of match. To perform specific matches or constraints create a
     * new PHPUnit_Framework_Constraint and use it for the parameter.
     * If the parameter value is not a constraint it will use the
     * PHPUnit_Framework_Constraint_IsEqual for the value.
     *
     * Some examples:
     * <code>
     * // match first parameter with value 2
     * $b->with(2);
     * // match first parameter with value 'smock' and second identical to 42
     * $b->with('smock', new PHPUnit_Framework_Constraint_IsEqual(42));
     * </code>
     *
     * @return PHPUnit_Framework_MockObject_Builder_ParametersMatch
     */
    public function with();

    /**
     * Sets a matcher which allows any kind of parameters.
     *
     * Some examples:
     * <code>
     * // match any number of parameters
     * $b->withAnyParamers();
     * </code>
     *
     * @return PHPUnit_Framework_MockObject_Matcher_AnyParameters
     */
    public function withAnyParameters();
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Interface for builders which can register builders with a given identification.
 *
 * This interface relates to PHPUnit_Framework_MockObject_Builder_Identity.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Interface available since Release 1.0.0
 */
interface PHPUnit_Framework_MockObject_Builder_Namespace
{
    /**
     * Looks up the match builder with identification $id and returns it.
     *
     * @param string $id The identifiction of the match builder.
     * @return PHPUnit_Framework_MockObject_Builder_Match
     */
    public function lookupId($id);

    /**
     * Registers the match builder $builder with the identification $id. The
     * builder can later be looked up using lookupId() to figure out if it
     * has been invoked.
     *
     * @param string                                     $id
     *        The identification of the match builder.
     * @param PHPUnit_Framework_MockObject_Builder_Match $builder
     *        The builder which is being registered.
     */
    public function registerId($id, PHPUnit_Framework_MockObject_Builder_Match $builder);
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Builder for mocked or stubbed invocations.
 *
 * Provides methods for building expectations without having to resort to
 * instantiating the various matchers manually. These methods also form a
 * more natural way of reading the expectation. This class should be together
 * with the test case PHPUnit_Framework_MockObject_TestCase.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Class available since Release 1.0.0
 */
class PHPUnit_Framework_MockObject_Builder_InvocationMocker implements PHPUnit_Framework_MockObject_Builder_MethodNameMatch
{
    /**
     * @var PHPUnit_Framework_MockObject_Stub_MatcherCollection
     */
    protected $collection;

    /**
     * @var PHPUnit_Framework_MockObject_Matcher
     */
    protected $matcher;

    /**
     * @param PHPUnit_Framework_MockObject_Stub_MatcherCollection $collection
     * @param PHPUnit_Framework_MockObject_Matcher_Invocation $invocationMatcher
     */
    public function __construct(PHPUnit_Framework_MockObject_Stub_MatcherCollection $collection, PHPUnit_Framework_MockObject_Matcher_Invocation $invocationMatcher)
    {
        $this->collection = $collection;
        $this->matcher    = new PHPUnit_Framework_MockObject_Matcher(
          $invocationMatcher
        );

        $this->collection->addMatcher($this->matcher);
    }

    /**
     * @return PHPUnit_Framework_MockObject_Matcher
     */
    public function getMatcher()
    {
        return $this->matcher;
    }

    /**
     * @param  mixed $id
     * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker
     */
    public function id($id)
    {
        $this->collection->registerId($id, $this);

        return $this;
    }

    /**
     * @param  PHPUnit_Framework_MockObject_Stub $stub
     * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker
     */
    public function will(PHPUnit_Framework_MockObject_Stub $stub)
    {
        $this->matcher->stub = $stub;

        return $this;
    }

    /**
     * @param  mixed $id
     * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker
     */
    public function after($id)
    {
        $this->matcher->afterMatchBuilderId = $id;

        return $this;
    }

    /**
     * @param  mixed $argument, ...
     * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker
     */
    public function with()
    {
        $args = func_get_args();

        if ($this->matcher->methodNameMatcher === NULL) {
            throw new PHPUnit_Framework_Exception(
              'Method name matcher is not defined, cannot define parameter ' .
              ' matcher without one'
            );
        }

        if ($this->matcher->parametersMatcher !== NULL) {
            throw new PHPUnit_Framework_Exception(
              'Parameter matcher is already defined, cannot redefine'
            );
        }

        $this->matcher->parametersMatcher = new PHPUnit_Framework_MockObject_Matcher_Parameters($args);

        return $this;
    }

    /**
     * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker
     */
    public function withAnyParameters()
    {
        if ($this->matcher->methodNameMatcher === NULL) {
            throw new PHPUnit_Framework_Exception(
              'Method name matcher is not defined, cannot define parameter ' .
              'matcher without one'
            );
        }

        if ($this->matcher->parametersMatcher !== NULL) {
            throw new PHPUnit_Framework_Exception(
              'Parameter matcher is already defined, cannot redefine'
            );
        }

        $this->matcher->parametersMatcher = new PHPUnit_Framework_MockObject_Matcher_AnyParameters;

        return $this;
    }

    /**
     * @param  PHPUnit_Framework_Constraint|string $constraint
     * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker
     */
    public function method($constraint)
    {
        if ($this->matcher->methodNameMatcher !== NULL) {
            throw new PHPUnit_Framework_Exception(
              'Method name matcher is already defined, cannot redefine'
            );
        }

        $this->matcher->methodNameMatcher = new PHPUnit_Framework_MockObject_Matcher_MethodName($constraint);

        return $this;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Builder interface for invocation order matches.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Interface available since Release 1.0.0
 */
interface PHPUnit_Framework_MockObject_Builder_Match extends PHPUnit_Framework_MockObject_Builder_Stub
{
    /**
     * Defines the expectation which must occur before the current is valid.
     *
     * @param string $id The identification of the expectation that should
     *                   occur before this one.
     * @return PHPUnit_Framework_MockObject_Builder_Stub
     */
    public function after($id);
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Builder interface for stubs which are actions replacing an invocation.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Interface available since Release 1.0.0
 */
interface PHPUnit_Framework_MockObject_Builder_Stub extends PHPUnit_Framework_MockObject_Builder_Identity
{
    /**
     * Stubs the matching method with the stub object $stub. Any invocations of
     * the matched method will now be handled by the stub instead.
     *
     * @param PHPUnit_Framework_MockObject_Stub $stub The stub object.
     * @return PHPUnit_Framework_MockObject_Builder_Identity
     */
    public function will(PHPUnit_Framework_MockObject_Stub $stub);
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Builder interface for matcher of method names.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Interface available since Release 1.0.0
 */
interface PHPUnit_Framework_MockObject_Builder_MethodNameMatch extends PHPUnit_Framework_MockObject_Builder_ParametersMatch
{
    /**
     * Adds a new method name match and returns the parameter match object for
     * further matching possibilities.
     *
     * @param  PHPUnit_Framework_Constraint $name
     *         Constraint for matching method, if a string is passed it will use
     *         the PHPUnit_Framework_Constraint_IsEqual.
     * @return PHPUnit_Framework_MockObject_Builder_ParametersMatch
     */
    public function method($name);
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Patrick Müller <elias0@gmx.net>
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Stubs a method by returning a user-defined stack of values.
 *
 * @package    PHPUnit_MockObject
 * @author     Patrick Müller <elias0@gmx.net>
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Class available since Release 1.0.0
 */
class PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls implements PHPUnit_Framework_MockObject_Stub
{
    protected $stack;
    protected $value;

    public function __construct($stack)
    {
        $this->stack = $stack;
    }

    public function invoke(PHPUnit_Framework_MockObject_Invocation $invocation)
    {
        $this->value = array_shift($this->stack);

        if ($this->value instanceof PHPUnit_Framework_MockObject_Stub) {
            $this->value = $this->value->invoke($invocation);
        }

        return $this->value;
    }

    public function toString()
    {
        return sprintf(
          'return user-specified value %s',

          PHPUnit_Util_Type::toString($this->value)
        );
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.1.0
 */

/**
 * Stubs a method by returning a value from a map.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Class available since Release 1.1.0
 */
class PHPUnit_Framework_MockObject_Stub_ReturnValueMap implements PHPUnit_Framework_MockObject_Stub
{
    protected $valueMap;

    public function __construct(array $valueMap)
    {
        $this->valueMap = $valueMap;
    }

    public function invoke(PHPUnit_Framework_MockObject_Invocation $invocation)
    {
        $parameterCount = count($invocation->parameters);

        foreach ($this->valueMap as $map) {
            if (!is_array($map) || $parameterCount != count($map) - 1) {
                continue;
            }

            $return = array_pop($map);
            if ($invocation->parameters === $map) {
                return $return;
            }
        }

        return NULL;
    }

    public function toString()
    {
        return 'return value from a map';
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Oliver Schlicht <o.schlicht@bitExpert.de>
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Stubs a method by raising a user-defined exception.
 *
 * @package    PHPUnit_MockObject
 * @author     Oliver Schlicht <o.schlicht@bitExpert.de>
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Class available since Release 1.0.0
 */
class PHPUnit_Framework_MockObject_Stub_Exception implements PHPUnit_Framework_MockObject_Stub
{
    protected $exception;

    public function __construct(Exception $exception)
    {
        $this->exception = $exception;
    }

    public function invoke(PHPUnit_Framework_MockObject_Invocation $invocation)
    {
        throw $this->exception;
    }

    public function toString()
    {
        return sprintf(
          'raise user-specified exception %s',

          PHPUnit_Util_Type::toString($this->exception)
        );
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @author     Kris Wallsmith <kris.wallsmith@gmail.com>
 * @copyright  2010 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.1.0
 */

/**
 * Stubs a method by returning the current object.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @author     Kris Wallsmith <kris.wallsmith@gmail.com>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Class available since Release 1.1.0
 */
class PHPUnit_Framework_MockObject_Stub_ReturnSelf implements PHPUnit_Framework_MockObject_Stub
{
    public function invoke(PHPUnit_Framework_MockObject_Invocation $invocation)
    {
        if (!$invocation instanceof PHPUnit_Framework_MockObject_Invocation_Object) {
            throw new PHPUnit_Framework_Exception(
                'The current object can only be returned when mocking an ' .
                'object, not a static class.'
            );
        }

        return $invocation->object;
    }

    public function toString()
    {
        return 'return the current object';
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Stubs a method by returning an argument that was passed to the mocked method.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Class available since Release 1.0.0
 */
class PHPUnit_Framework_MockObject_Stub_ReturnArgument extends PHPUnit_Framework_MockObject_Stub_Return
{
    protected $argumentIndex;

    public function __construct($argumentIndex)
    {
        $this->argumentIndex = $argumentIndex;
    }

    public function invoke(PHPUnit_Framework_MockObject_Invocation $invocation)
    {
        if (isset($invocation->parameters[$this->argumentIndex])) {
            return $invocation->parameters[$this->argumentIndex];
        } else {
            return NULL;
        }
    }

    public function toString()
    {
        return sprintf('return argument #%d', $this->argumentIndex);
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Stubs a method by returning a user-defined value.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Interface available since Release 1.0.0
 */
interface PHPUnit_Framework_MockObject_Stub_MatcherCollection
{
    /**
     * Adds a new matcher to the collection which can be used as an expectation
     * or a stub.
     *
     * @param PHPUnit_Framework_MockObject_Matcher_Invocation $matcher
     *        Matcher for invocations to mock objects.
     */
    public function addMatcher(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher);
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 *
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Class available since Release 1.0.0
 */
class PHPUnit_Framework_MockObject_Stub_ReturnCallback implements PHPUnit_Framework_MockObject_Stub
{
    protected $callback;

    public function __construct($callback)
    {
        $this->callback = $callback;
    }

    public function invoke(PHPUnit_Framework_MockObject_Invocation $invocation)
    {
        return call_user_func_array($this->callback, $invocation->parameters);
    }

    public function toString()
    {
        if (is_array($this->callback)) {
            if (is_object($this->callback[0])) {
                $class = get_class($this->callback[0]);
                $type  = '->';
            } else {
                $class = $this->callback[0];
                $type  = '::';
            }

            return sprintf(
              'return result of user defined callback %s%s%s() with the ' .
              'passed arguments',

              $class,
              $type,
              $this->callback[1]
            );
        } else {
            return 'return result of user defined callback ' . $this->callback .
                   ' with the passed arguments';
        }
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Stubs a method by returning a user-defined value.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Class available since Release 1.0.0
 */
class PHPUnit_Framework_MockObject_Stub_Return implements PHPUnit_Framework_MockObject_Stub
{
    protected $value;

    public function __construct($value)
    {
        $this->value = $value;
    }

    public function invoke(PHPUnit_Framework_MockObject_Invocation $invocation)
    {
        return $this->value;
    }

    public function toString()
    {
        return sprintf(
          'return user-specified value %s',

          PHPUnit_Util_Type::toString($this->value)
        );
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Interface for invocations.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Interface available since Release 1.0.0
 */
interface PHPUnit_Framework_MockObject_Invocation
{
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Represents a non-static invocation.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Class available since Release 1.0.0
 */
class PHPUnit_Framework_MockObject_Invocation_Object extends PHPUnit_Framework_MockObject_Invocation_Static
{
    /**
     * @var object
     */
    public $object;

    /**
     * @param string $className
     * @param string $methodname
     * @param array  $parameters
     * @param object $object
     * @param object $cloneObjects
     */
    public function __construct($className, $methodName, array $parameters, $object, $cloneObjects = FALSE)
    {
        parent::__construct($className, $methodName, $parameters, $cloneObjects);
        $this->object = $object;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Represents a static invocation.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Class available since Release 1.0.0
 */
class PHPUnit_Framework_MockObject_Invocation_Static implements PHPUnit_Framework_MockObject_Invocation, PHPUnit_Framework_SelfDescribing
{
    /**
     * @var array
     */
    protected static $uncloneableExtensions = array(
      'mysqli' => TRUE,
      'SQLite' => TRUE,
      'sqlite3' => TRUE,
      'tidy' => TRUE,
      'xmlwriter' => TRUE,
      'xsl' => TRUE
    );

    /**
     * @var array
     */
    protected static $uncloneableClasses = array(
      'Closure',
      'COMPersistHelper',
      'IteratorIterator',
      'RecursiveIteratorIterator',
      'SplFileObject',
      'PDORow',
      'ZipArchive'
    );

    /**
     * @var string
     */
    public $className;

    /**
     * @var string
     */
    public $methodName;

    /**
     * @var array
     */
    public $parameters;

    /**
     * @param string  $className
     * @param string  $methodname
     * @param array   $parameters
     * @param boolean $cloneObjects
     */
    public function __construct($className, $methodName, array $parameters, $cloneObjects = FALSE)
    {
        $this->className  = $className;
        $this->methodName = $methodName;
        $this->parameters = $parameters;

        if (!$cloneObjects) {
            return;
        }

        foreach ($this->parameters as $key => $value) {
            if (is_object($value)) {
                $this->parameters[$key] = $this->cloneObject($value);
            }
        }
    }

    /**
     * @return string
     */
    public function toString()
    {
        return sprintf(
          "%s::%s(%s)",

          $this->className,
          $this->methodName,
          join(
            ', ',
            array_map(
              array('PHPUnit_Util_Type', 'shortenedExport'),
              $this->parameters
            )
          )
        );
    }

    /**
     * @param  object $original
     * @return object
     */
    protected function cloneObject($original)
    {
        $cloneable = NULL;
        $object    = new ReflectionObject($original);

        // Check the blacklist before asking PHP reflection to work around
        // https://bugs.php.net/bug.php?id=53967
        if ($object->isInternal() &&
            isset(self::$uncloneableExtensions[$object->getExtensionName()])) {
            $cloneable = FALSE;
        }

        if ($cloneable === NULL) {
            foreach (self::$uncloneableClasses as $class) {
                if ($original instanceof $class) {
                    $cloneable = FALSE;
                    break;
                }
            }
        }

        if ($cloneable === NULL && method_exists($object, 'isCloneable')) {
            $cloneable = $object->isCloneable();
        }

        if ($cloneable === NULL && $object->hasMethod('__clone')) {
            $method    = $object->getMethod('__clone');
            $cloneable = $method->isPublic();
        }

        if ($cloneable === NULL) {
            $cloneable = TRUE;
        }

        if ($cloneable) {
            try {
                return clone $original;
            }

            catch (Exception $e) {
                return $original;
            }
        } else {
            return $original;
        }
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Mocker for invocations which are sent from
 * PHPUnit_Framework_MockObject_MockObject objects.
 *
 * Keeps track of all expectations and stubs as well as registering
 * identifications for builders.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Class available since Release 1.0.0
 */
class PHPUnit_Framework_MockObject_InvocationMocker implements PHPUnit_Framework_MockObject_Stub_MatcherCollection, PHPUnit_Framework_MockObject_Invokable, PHPUnit_Framework_MockObject_Builder_Namespace
{
    /**
     * @var PHPUnit_Framework_MockObject_Matcher_Invocation[]
     */
    protected $matchers = array();

    /**
     * @var PHPUnit_Framework_MockObject_Builder_Match[]
     */
    protected $builderMap = array();

    /**
     * @param PHPUnit_Framework_MockObject_Matcher_Invocation $matcher
     */
    public function addMatcher(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        $this->matchers[] = $matcher;
    }

    /**
     * @since Method available since Release 1.1.0
     */
    public function hasMatchers()
    {
        if (empty($this->matchers)) {
            return FALSE;
        }

        foreach ($this->matchers as $matcher) {
            if (!$matcher instanceof PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount) {
                return TRUE;
            }
        }

        return FALSE;
    }

    /**
     * @param  mixed $id
     * @return boolean|null
     */
    public function lookupId($id)
    {
        if (isset($this->builderMap[$id])) {
            return $this->builderMap[$id];
        }

        return NULL;
    }

    /**
     * @param  mixed                                      $id
     * @param  PHPUnit_Framework_MockObject_Builder_Match $builder
     * @throws PHPUnit_Framework_Exception
     */
    public function registerId($id, PHPUnit_Framework_MockObject_Builder_Match $builder)
    {
        if (isset($this->builderMap[$id])) {
            throw new PHPUnit_Framework_Exception(
              'Match builder with id <' . $id . '> is already registered.'
            );
        }

        $this->builderMap[$id] = $builder;
    }

    /**
     * @param  PHPUnit_Framework_MockObject_Matcher_Invocation $matcher
     * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker
     */
    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return new PHPUnit_Framework_MockObject_Builder_InvocationMocker(
          $this, $matcher
        );
    }

    /**
     * @param  PHPUnit_Framework_MockObject_Invocation $invocation
     * @return mixed
     */
    public function invoke(PHPUnit_Framework_MockObject_Invocation $invocation)
    {
        $exception      = NULL;
        $hasReturnValue = FALSE;

        if (strtolower($invocation->methodName) == '__tostring') {
            $returnValue = '';
        } else {
            $returnValue = NULL;
        }

        foreach ($this->matchers as $match) {
            try {
                if ($match->matches($invocation)) {
                    $value = $match->invoked($invocation);

                    if (!$hasReturnValue) {
                        $returnValue    = $value;
                        $hasReturnValue = TRUE;
                    }
                }
            }

            catch (Exception $e) {
                $exception = $e;
            }
        }

        if ($exception !== NULL) {
            throw $exception;
        }

        return $returnValue;
    }

    /**
     * @param  PHPUnit_Framework_MockObject_Invocation $invocation
     * @return boolean
     */
    public function matches(PHPUnit_Framework_MockObject_Invocation $invocation)
    {
        foreach ($this->matchers as $matcher) {
            if (!$matcher->matches($invocation)) {
                return FALSE;
            }
        }

        return TRUE;
    }

    /**
     * @return boolean
     */
    public function verify()
    {
        foreach ($this->matchers as $matcher) {
            $matcher->verify();
        }
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Giorgio Sironi <piccoloprincipeazzurro@gmail.com>
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Implementation of the Builder pattern for Mock objects.
 *
 * @package    PHPUnit_MockObject
 * @author     Giorgio Sironi <piccoloprincipeazzurro@gmail.com>
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */
class PHPUnit_Framework_MockObject_MockBuilder
{
    /**
     * @var PHPUnit_Framework_TestCase
     */
    protected $testCase;

    /**
     * @var string
     */
    protected $className;

    /**
     * @var array
     */
    protected $methods = array();

    /**
     * @var string
     */
    protected $mockClassName = '';

    /**
     * @var array
     */
    protected $constructorArgs = array();

    /**
     * @var boolean
     */
    protected $originalConstructor = TRUE;

    /**
     * @var boolean
     */
    protected $originalClone = TRUE;

    /**
     * @var boolean
     */
    protected $autoload = TRUE;

    /**
     * @var boolean
     */
    protected $cloneArguments = FALSE;

    /**
     * @param PHPUnit_Framework_TestCase
     * @param string
     */
    public function __construct(PHPUnit_Framework_TestCase $testCase, $className)
    {
        $this->testCase  = $testCase;
        $this->className = $className;
    }

    /**
     * Creates a mock object using a fluent interface.
     *
     * @return PHPUnit_Framework_MockObject_MockObject
     */
    public function getMock()
    {
        return $this->testCase->getMock(
          $this->className,
          $this->methods,
          $this->constructorArgs,
          $this->mockClassName,
          $this->originalConstructor,
          $this->originalClone,
          $this->autoload,
          $this->cloneArguments
        );
    }

    /**
     * Creates a mock object for an abstract class using a fluent interface.
     *
     * @return PHPUnit_Framework_MockObject_MockObject
     */
    public function getMockForAbstractClass()
    {
        return $this->testCase->getMockForAbstractClass(
          $this->className,
          $this->constructorArgs,
          $this->mockClassName,
          $this->originalConstructor,
          $this->originalClone,
          $this->autoload,
          $this->methods,
          $this->cloneArguments
        );
    }

    /**
     * Specifies the subset of methods to mock. Default is to mock all of them.
     *
     * @param  array|null $methods
     * @return PHPUnit_Framework_MockObject_MockBuilder
     */
    public function setMethods($methods)
    {
        $this->methods = $methods;

        return $this;
    }

    /**
     * Specifies the arguments for the constructor.
     *
     * @param  array $args
     * @return PHPUnit_Framework_MockObject_MockBuilder
     */
    public function setConstructorArgs(array $args)
    {
        $this->constructorArgs = $args;

        return $this;
    }

    /**
     * Specifies the name for the mock class.
     *
     * @param string $name
     * @return PHPUnit_Framework_MockObject_MockBuilder
     */
    public function setMockClassName($name)
    {
        $this->mockClassName = $name;

        return $this;
    }

    /**
     * Disables the invocation of the original constructor.
     *
     * @return PHPUnit_Framework_MockObject_MockBuilder
     */
    public function disableOriginalConstructor()
    {
        $this->originalConstructor = FALSE;

        return $this;
    }

    /**
     * Enables the invocation of the original constructor.
     *
     * @return PHPUnit_Framework_MockObject_MockBuilder
     * @since  Method available since Release 1.2.0
     */
    public function enableOriginalConstructor()
    {
        $this->originalConstructor = TRUE;

        return $this;
    }

    /**
     * Disables the invocation of the original clone constructor.
     *
     * @return PHPUnit_Framework_MockObject_MockBuilder
     */
    public function disableOriginalClone()
    {
        $this->originalClone = FALSE;

        return $this;
    }

    /**
     * Enables the invocation of the original clone constructor.
     *
     * @return PHPUnit_Framework_MockObject_MockBuilder
     * @since  Method available since Release 1.2.0
     */
    public function enableOriginalClone()
    {
        $this->originalClone = TRUE;

        return $this;
    }

    /**
     * Disables the use of class autoloading while creating the mock object.
     *
     * @return PHPUnit_Framework_MockObject_MockBuilder
     */
    public function disableAutoload()
    {
        $this->autoload = FALSE;

        return $this;
    }

    /**
     * Enables the use of class autoloading while creating the mock object.
     *
     * @return PHPUnit_Framework_MockObject_MockBuilder
     * @since  Method available since Release 1.2.0
     */
    public function enableAutoload()
    {
        $this->autoload = TRUE;

        return $this;
    }

    /**
     * Disables the cloning of arguments passed to mocked methods.
     *
     * @return PHPUnit_Framework_MockObject_MockBuilder
     * @since  Method available since Release 1.2.0
     */
    public function disableArgumentCloning()
    {
        $this->cloneArguments = FALSE;

        return $this;
    }

    /**
     * Enables the cloning of arguments passed to mocked methods.
     *
     * @return PHPUnit_Framework_MockObject_MockBuilder
     * @since  Method available since Release 1.2.0
     */
    public function enableArgumentCloning()
    {
        $this->cloneArguments = TRUE;

        return $this;
    }
}

    public function {method_name}({arguments})
    {
    }
    public function __clone()
    {
        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
    }
{prologue}{class_declaration}
{
    private static $__phpunit_staticInvocationMocker;
    private $__phpunit_invocationMocker;

{clone}{mocked_methods}
    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return $this->__phpunit_getInvocationMocker()->expects($matcher);
    }

    public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return self::__phpunit_getStaticInvocationMocker()->expects($matcher);
    }

    public function __phpunit_getInvocationMocker()
    {
        if ($this->__phpunit_invocationMocker === NULL) {
            $this->__phpunit_invocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return $this->__phpunit_invocationMocker;
    }

    public static function __phpunit_getStaticInvocationMocker()
    {
        if (self::$__phpunit_staticInvocationMocker === NULL) {
            self::$__phpunit_staticInvocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return self::$__phpunit_staticInvocationMocker;
    }

    public function __phpunit_hasMatchers()
    {
        return self::__phpunit_getStaticInvocationMocker()->hasMatchers() ||
               $this->__phpunit_getInvocationMocker()->hasMatchers();
    }

    public function __phpunit_verify()
    {
        self::__phpunit_getStaticInvocationMocker()->verify();
        $this->__phpunit_getInvocationMocker()->verify();
    }

    public function __phpunit_cleanup()
    {
        self::$__phpunit_staticInvocationMocker = NULL;
        $this->__phpunit_invocationMocker       = NULL;
    }
}{epilogue}
{namespace}

class {class_name} extends \SOAPClient
{
    public function __construct($wsdl, array $options)
    {
        parent::__construct('{wsdl}', $options);
    }
{methods}}
class {class_name}
{
    use {trait_name};
}

    {modifier} function {reference}{method_name}({arguments_decl})
    {
        $arguments = array({arguments_call});
        $count     = func_num_args();

        if ($count > {arguments_count}) {
            $_arguments = func_get_args();

            for ($i = {arguments_count}; $i < $count; $i++) {
                $arguments[] = $_arguments[$i];
            }
        }

        $result = $this->__phpunit_getInvocationMocker()->invoke(
          new PHPUnit_Framework_MockObject_Invocation_Object(
            '{class_name}', '{method_name}', $arguments, $this, {clone_arguments}
          )
        );

        return $result;
    }
    public function __clone()
    {
        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
        parent::__clone();
    }

    {modifier} static function {reference}{method_name}({arguments_decl})
    {
        $arguments = array({arguments_call});
        $count     = func_num_args();

        if ($count > {arguments_count}) {
            $_arguments = func_get_args();

            for ($i = {arguments_count}; $i < $count; $i++) {
                $arguments[] = $_arguments[$i];
            }
        }

        $result = self::__phpunit_getStaticInvocationMocker()->invoke(
          new PHPUnit_Framework_MockObject_Invocation_Static(
            '{class_name}', '{method_name}', $arguments, {clone_arguments}
          )
        );

        return $result;
    }
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2002-2011, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2002-2011 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.1.0
 */

spl_autoload_register(
  function ($class)
  {
      static $classes = NULL;
      static $path = NULL;

      if ($classes === NULL) {
          $classes = array(
            'phpunit_framework_mockobject_builder_identity' => '/Framework/MockObject/Builder/Identity.php',
            'phpunit_framework_mockobject_builder_invocationmocker' => '/Framework/MockObject/Builder/InvocationMocker.php',
            'phpunit_framework_mockobject_builder_match' => '/Framework/MockObject/Builder/Match.php',
            'phpunit_framework_mockobject_builder_methodnamematch' => '/Framework/MockObject/Builder/MethodNameMatch.php',
            'phpunit_framework_mockobject_builder_namespace' => '/Framework/MockObject/Builder/Namespace.php',
            'phpunit_framework_mockobject_builder_parametersmatch' => '/Framework/MockObject/Builder/ParametersMatch.php',
            'phpunit_framework_mockobject_builder_stub' => '/Framework/MockObject/Builder/Stub.php',
            'phpunit_framework_mockobject_generator' => '/Framework/MockObject/Generator.php',
            'phpunit_framework_mockobject_invocation' => '/Framework/MockObject/Invocation.php',
            'phpunit_framework_mockobject_invocation_object' => '/Framework/MockObject/Invocation/Object.php',
            'phpunit_framework_mockobject_invocation_static' => '/Framework/MockObject/Invocation/Static.php',
            'phpunit_framework_mockobject_invocationmocker' => '/Framework/MockObject/InvocationMocker.php',
            'phpunit_framework_mockobject_invokable' => '/Framework/MockObject/Invokable.php',
            'phpunit_framework_mockobject_matcher' => '/Framework/MockObject/Matcher.php',
            'phpunit_framework_mockobject_matcher_anyinvokedcount' => '/Framework/MockObject/Matcher/AnyInvokedCount.php',
            'phpunit_framework_mockobject_matcher_anyparameters' => '/Framework/MockObject/Matcher/AnyParameters.php',
            'phpunit_framework_mockobject_matcher_invocation' => '/Framework/MockObject/Matcher/Invocation.php',
            'phpunit_framework_mockobject_matcher_invokedatindex' => '/Framework/MockObject/Matcher/InvokedAtIndex.php',
            'phpunit_framework_mockobject_matcher_invokedatleastonce' => '/Framework/MockObject/Matcher/InvokedAtLeastOnce.php',
            'phpunit_framework_mockobject_matcher_invokedcount' => '/Framework/MockObject/Matcher/InvokedCount.php',
            'phpunit_framework_mockobject_matcher_invokedrecorder' => '/Framework/MockObject/Matcher/InvokedRecorder.php',
            'phpunit_framework_mockobject_matcher_methodname' => '/Framework/MockObject/Matcher/MethodName.php',
            'phpunit_framework_mockobject_matcher_parameters' => '/Framework/MockObject/Matcher/Parameters.php',
            'phpunit_framework_mockobject_matcher_statelessinvocation' => '/Framework/MockObject/Matcher/StatelessInvocation.php',
            'phpunit_framework_mockobject_mockbuilder' => '/Framework/MockObject/MockBuilder.php',
            'phpunit_framework_mockobject_mockobject' => '/Framework/MockObject/MockObject.php',
            'phpunit_framework_mockobject_stub' => '/Framework/MockObject/Stub.php',
            'phpunit_framework_mockobject_stub_consecutivecalls' => '/Framework/MockObject/Stub/ConsecutiveCalls.php',
            'phpunit_framework_mockobject_stub_exception' => '/Framework/MockObject/Stub/Exception.php',
            'phpunit_framework_mockobject_stub_matchercollection' => '/Framework/MockObject/Stub/MatcherCollection.php',
            'phpunit_framework_mockobject_stub_return' => '/Framework/MockObject/Stub/Return.php',
            'phpunit_framework_mockobject_stub_returnargument' => '/Framework/MockObject/Stub/ReturnArgument.php',
            'phpunit_framework_mockobject_stub_returncallback' => '/Framework/MockObject/Stub/ReturnCallback.php',
            'phpunit_framework_mockobject_stub_returnself' => '/Framework/MockObject/Stub/ReturnSelf.php',
            'phpunit_framework_mockobject_stub_returnvaluemap' => '/Framework/MockObject/Stub/ReturnValueMap.php',
            'phpunit_framework_mockobject_verifiable' => '/Framework/MockObject/Verifiable.php'
          );

          $path = dirname(dirname(dirname(__FILE__)));
      }

      $cn = strtolower($class);

      if (isset($classes[$cn])) {
          require $path . $classes[$cn];
      }
  }
);
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Mock Object Code Generator
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Class available since Release 1.0.0
 */
class PHPUnit_Framework_MockObject_Generator
{
    /**
     * @var array
     */
    protected static $cache = array();

    /**
     * @var array
     */
    protected static $blacklistedMethodNames = array(
      '__clone' => TRUE,
      'abstract' => TRUE,
      'and' => TRUE,
      'array' => TRUE,
      'as' => TRUE,
      'break' => TRUE,
      'case' => TRUE,
      'catch' => TRUE,
      'class' => TRUE,
      'clone' => TRUE,
      'const' => TRUE,
      'continue' => TRUE,
      'declare' => TRUE,
      'default' => TRUE,
      'die' => TRUE,
      'do' => TRUE,
      'echo' => TRUE,
      'else' => TRUE,
      'elseif' => TRUE,
      'empty' => TRUE,
      'enddeclare' => TRUE,
      'endfor' => TRUE,
      'endforeach' => TRUE,
      'endif' => TRUE,
      'endswitch' => TRUE,
      'endwhile' => TRUE,
      'eval' => TRUE,
      'exit' => TRUE,
      'expects' => TRUE,
      'extends' => TRUE,
      'final' => TRUE,
      'for' => TRUE,
      'foreach' => TRUE,
      'function' => TRUE,
      'global' => TRUE,
      'goto' => TRUE,
      'if' => TRUE,
      'implements' => TRUE,
      'include' => TRUE,
      'include_once' => TRUE,
      'instanceof' => TRUE,
      'interface' => TRUE,
      'isset' => TRUE,
      'list' => TRUE,
      'namespace' => TRUE,
      'new' => TRUE,
      'or' => TRUE,
      'print' => TRUE,
      'private' => TRUE,
      'protected' => TRUE,
      'public' => TRUE,
      'require' => TRUE,
      'require_once' => TRUE,
      'return' => TRUE,
      'static' => TRUE,
      'staticExpects' => TRUE,
      'switch' => TRUE,
      'throw' => TRUE,
      'try' => TRUE,
      'unset' => TRUE,
      'use' => TRUE,
      'var' => TRUE,
      'while' => TRUE,
      'xor' => TRUE
    );

    /**
     * @var boolean
     */
    protected static $soapLoaded = NULL;

    /**
     * Returns a mock object for the specified class.
     *
     * @param  string  $originalClassName
     * @param  array   $methods
     * @param  array   $arguments
     * @param  string  $mockClassName
     * @param  boolean $callOriginalConstructor
     * @param  boolean $callOriginalClone
     * @param  boolean $callAutoload
     * @param  boolean $cloneArguments
     * @return object
     * @throws InvalidArgumentException
     * @since  Method available since Release 1.0.0
     */
    public static function getMock($originalClassName, $methods = array(), array $arguments = array(), $mockClassName = '', $callOriginalConstructor = TRUE, $callOriginalClone = TRUE, $callAutoload = TRUE, $cloneArguments = TRUE)
    {
        if (!is_string($originalClassName)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        if (!is_string($mockClassName)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(4, 'string');
        }

        if (!is_array($methods) && !is_null($methods)) {
            throw new InvalidArgumentException;
        }

        if (NULL !== $methods) {
            foreach ($methods as $method) {
                if (!preg_match('~[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*~', $method)) {
                    throw new PHPUnit_Framework_Exception(
                      sprintf(
                        'Cannot stub or mock method with invalid name "%s"',
                        $method
                      )
                    );
                }
            }
            if ($methods != array_unique($methods)) {
                throw new PHPUnit_Framework_Exception(
                  sprintf(
                    'Cannot stub or mock using a method list that contains duplicates: "%s"',
                    implode(', ', $methods)
                  )
                );
            }
        }

        if ($mockClassName != '' && class_exists($mockClassName, FALSE)) {
            $reflect = new ReflectionClass($mockClassName);
            if (!$reflect->implementsInterface("PHPUnit_Framework_MockObject_MockObject")) {
                throw new PHPUnit_Framework_Exception(
                  sprintf(
                    'Class "%s" already exists.',
                    $mockClassName
                  )
                );
            }
        }

        $mock = self::generate(
          $originalClassName,
          $methods,
          $mockClassName,
          $callOriginalClone,
          $callAutoload,
          $cloneArguments
        );

        return self::getObject(
          $mock['code'],
          $mock['mockClassName'],
          $originalClassName,
          $callOriginalConstructor,
          $callAutoload,
          $arguments
        );
    }

    /**
     * @param  string $code
     * @param  string $className
     * @param  string $originalClassName
     * @param  string $callOriginalConstructor
     * @param  string $callAutoload
     * @param  array  $arguments
     * @return object
     */
    protected static function getObject($code, $className, $originalClassName = '', $callOriginalConstructor = FALSE, $callAutoload = FALSE, array $arguments = array())
    {
        if (!class_exists($className, FALSE)) {
            eval($code);
        }

        if ($callOriginalConstructor &&
            !interface_exists($originalClassName, $callAutoload)) {
            if (count($arguments) == 0) {
                $object = new $className;
            } else {
                $class = new ReflectionClass($className);
                $object = $class->newInstanceArgs($arguments);
            }
        } else {
            // Use a trick to create a new object of a class
            // without invoking its constructor.
            $object = unserialize(
              sprintf('O:%d:"%s":0:{}', strlen($className), $className)
            );
        }

        return $object;
    }

    /**
     * Returns a mock object for the specified abstract class with all abstract
     * methods of the class mocked. Concrete methods to mock can be specified with
     * the last parameter
     *
     * @param  string  $originalClassName
     * @param  array   $arguments
     * @param  string  $mockClassName
     * @param  boolean $callOriginalConstructor
     * @param  boolean $callOriginalClone
     * @param  boolean $callAutoload
     * @param  array   $mockedMethods
     * @param  boolean $cloneArguments
     * @return object
     * @since  Method available since Release 1.0.0
     * @throws InvalidArgumentException
     */
    public static function getMockForAbstractClass($originalClassName, array $arguments = array(), $mockClassName = '', $callOriginalConstructor = TRUE, $callOriginalClone = TRUE, $callAutoload = TRUE, $mockedMethods = array(), $cloneArguments = TRUE)
    {
        if (!is_string($originalClassName)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        if (!is_string($mockClassName)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(3, 'string');
        }

        if (class_exists($originalClassName, $callAutoload) ||
            interface_exists($originalClassName, $callAutoload)) {
            $methods   = array();
            $reflector = new ReflectionClass($originalClassName);

            foreach ($reflector->getMethods() as $method) {
                if ($method->isAbstract() || in_array($method->getName(), $mockedMethods)) {
                    $methods[] = $method->getName();
                }
            }

            if (empty($methods)) {
                $methods = NULL;
            }

            return self::getMock(
              $originalClassName,
              $methods,
              $arguments,
              $mockClassName,
              $callOriginalConstructor,
              $callOriginalClone,
              $callAutoload,
              $cloneArguments
            );
        } else {
            throw new PHPUnit_Framework_Exception(
              sprintf(
                'Class "%s" does not exist.',
                $originalClassName
              )
            );
        }
    }

    /**
     * Returns an object for the specified trait.
     *
     * @param  string  $traitName
     * @param  array   $arguments
     * @param  string  $traitClassName
     * @param  boolean $callOriginalConstructor
     * @param  boolean $callOriginalClone
     * @param  boolean $callAutoload
     * @return object
     * @since  Method available since Release 1.1.0
     * @throws InvalidArgumentException
     */
    public static function getObjectForTrait($traitName, array $arguments = array(), $traitClassName = '', $callOriginalConstructor = TRUE, $callOriginalClone = TRUE, $callAutoload = TRUE)
    {
        if (!is_string($traitName)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string');
        }

        if (!is_string($traitClassName)) {
            throw PHPUnit_Util_InvalidArgumentHelper::factory(3, 'string');
        }

        if (!trait_exists($traitName, $callAutoload)) {
            throw new PHPUnit_Framework_Exception(
              sprintf(
                'Trait "%s" does not exist.',
                $traitName
              )
            );
        }

        $className = self::generateClassName(
          $traitName, $traitClassName, 'Trait_'
        );

        $templateDir   = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Generator' .
                         DIRECTORY_SEPARATOR;
        $classTemplate = new Text_Template(
                           $templateDir . 'trait_class.tpl'
                         );

        $classTemplate->setVar(
          array(
            'class_name' => $className['className'],
            'trait_name' => $traitName
          )
        );

        return self::getObject(
          $classTemplate->render(),
          $className['className']
        );
    }

    /**
     * @param  string  $originalClassName
     * @param  array   $methods
     * @param  string  $mockClassName
     * @param  boolean $callOriginalClone
     * @param  boolean $callAutoload
     * @param  boolean $cloneArguments
     * @return array
     */
    public static function generate($originalClassName, array $methods = NULL, $mockClassName = '', $callOriginalClone = TRUE, $callAutoload = TRUE, $cloneArguments = TRUE)
    {
        if ($mockClassName == '') {
            $key = md5(
              $originalClassName .
              serialize($methods) .
              serialize($callOriginalClone) .
              serialize($cloneArguments)
            );

            if (isset(self::$cache[$key])) {
                return self::$cache[$key];
            }
        }

        $mock = self::generateMock(
          $originalClassName,
          $methods,
          $mockClassName,
          $callOriginalClone,
          $callAutoload,
          $cloneArguments
        );

        if (isset($key)) {
            self::$cache[$key] = $mock;
        }

        return $mock;
    }

    /**
     * @param  string $wsdlFile
     * @param  string $originalClassName
     * @param  array  $methods
     * @param  array  $options
     * @return array
     */
    public static function generateClassFromWsdl($wsdlFile, $originalClassName, array $methods = array(), array $options = array())
    {
        if (self::$soapLoaded === NULL) {
            self::$soapLoaded = extension_loaded('soap');
        }

        if (self::$soapLoaded) {
            $client   = new SOAPClient($wsdlFile, $options);
            $_methods = array_unique($client->__getFunctions());
            unset($client);

            $templateDir    = dirname(__FILE__) . DIRECTORY_SEPARATOR .
                              'Generator' . DIRECTORY_SEPARATOR;
            $methodTemplate = new Text_Template(
                                $templateDir . 'wsdl_method.tpl'
                              );
            $methodsBuffer  = '';

            foreach ($_methods as $method) {
                $nameStart = strpos($method, ' ') + 1;
                $nameEnd   = strpos($method, '(');
                $name      = substr($method, $nameStart, $nameEnd - $nameStart);

                if (empty($methods) || in_array($name, $methods)) {
                    $args    = explode(
                                 ',',
                                 substr(
                                   $method,
                                   $nameEnd + 1,
                                   strpos($method, ')') - $nameEnd - 1
                                 )
                               );
                    $numArgs = count($args);

                    for ($i = 0; $i < $numArgs; $i++) {
                        $args[$i] = substr($args[$i], strpos($args[$i], '$'));
                    }

                    $methodTemplate->setVar(
                      array(
                        'method_name' => $name,
                        'arguments'   => join(', ', $args)
                      )
                    );

                    $methodsBuffer .= $methodTemplate->render();
                }
            }

            $optionsBuffer = 'array(';
            foreach ($options as $key => $value) {
                $optionsBuffer .= $key . ' => ' . $value;
            }

            $optionsBuffer .= ')';

            $classTemplate = new Text_Template(
              $templateDir . 'wsdl_class.tpl'
            );

            $namespace = '';
            if(strpos($originalClassName, '\\') !== FALSE) {
                $parts = explode('\\', $originalClassName);
                $originalClassName = array_pop($parts);
                $namespace = 'namespace ' . join('\\', $parts) . ';';
            }

            $classTemplate->setVar(
              array(
                'namespace'  => $namespace,
                'class_name' => $originalClassName,
                'wsdl'       => $wsdlFile,
                'options'    => $optionsBuffer,
                'methods'    => $methodsBuffer
              )
            );

            return $classTemplate->render();
        } else {
            throw new PHPUnit_Framework_Exception(
              'The SOAP extension is required to generate a mock object ' .
              'from WSDL.'
            );
        }
    }

    /**
     * @param  string     $originalClassName
     * @param  array|null $methods
     * @param  string     $mockClassName
     * @param  boolean    $callOriginalClone
     * @param  boolean    $callAutoload
     * @param  boolean    $cloneArguments
     * @return array
     */
    protected static function generateMock($originalClassName, $methods, $mockClassName, $callOriginalClone, $callAutoload, $cloneArguments = TRUE)
    {
        $templateDir   = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Generator' .
                         DIRECTORY_SEPARATOR;
        $classTemplate = new Text_Template(
                           $templateDir . 'mocked_class.tpl'
                         );
        $cloneTemplate = '';
        $isClass       = FALSE;
        $isInterface   = FALSE;

        $mockClassName = self::generateClassName(
          $originalClassName, $mockClassName, 'Mock_'
        );

        if (class_exists($mockClassName['fullClassName'], $callAutoload)) {
            $isClass = TRUE;
        } else {
            if (interface_exists($mockClassName['fullClassName'], $callAutoload)) {
                $isInterface = TRUE;
            }
        }

        if (!class_exists($mockClassName['fullClassName'], $callAutoload) &&
            !interface_exists($mockClassName['fullClassName'], $callAutoload)) {
            $prologue = 'class ' . $mockClassName['originalClassName'] . "\n{\n}\n\n";

            if (!empty($mockClassName['namespaceName'])) {
                $prologue = 'namespace ' . $mockClassName['namespaceName'] .
                            " {\n\n" . $prologue . "}\n\n" .
                            "namespace {\n\n";

                $epilogue = "\n\n}";
            }

            $cloneTemplate = new Text_Template(
              $templateDir . 'mocked_clone.tpl'
            );
        } else {
            $class = new ReflectionClass($mockClassName['fullClassName']);

            if ($class->isFinal()) {
                throw new PHPUnit_Framework_Exception(
                  sprintf(
                    'Class "%s" is declared "final" and cannot be mocked.',
                    $mockClassName['fullClassName']
                  )
                );
            }

            if ($class->hasMethod('__clone')) {
                $cloneMethod = $class->getMethod('__clone');

                if (!$cloneMethod->isFinal()) {
                    if ($callOriginalClone && !$isInterface) {
                        $cloneTemplate = new Text_Template(
                          $templateDir . 'unmocked_clone.tpl'
                        );
                    } else {
                        $cloneTemplate = new Text_Template(
                          $templateDir . 'mocked_clone.tpl'
                        );
                    }
                }
            } else {
                $cloneTemplate = new Text_Template(
                  $templateDir . 'mocked_clone.tpl'
                );
            }
        }

        if (is_object($cloneTemplate)) {
            $cloneTemplate = $cloneTemplate->render();
        }

        if (is_array($methods) && empty($methods) &&
            ($isClass || $isInterface)) {
            $methods = get_class_methods($mockClassName['fullClassName']);
        }

        if (!is_array($methods)) {
            $methods = array();
        }

        $mockedMethods = '';

        if (isset($class)) {
            foreach ($methods as $methodName) {
                try {
                    $method = $class->getMethod($methodName);

                    if (self::canMockMethod($method)) {
                        $mockedMethods .= self::generateMockedMethodDefinitionFromExisting(
                          $templateDir, $method, $cloneArguments
                        );
                    }
                }

                catch (ReflectionException $e) {
                    $mockedMethods .= self::generateMockedMethodDefinition(
                      $templateDir, $mockClassName['fullClassName'], $methodName, $cloneArguments
                    );
                }
            }
        } else {
            foreach ($methods as $methodName) {
                $mockedMethods .= self::generateMockedMethodDefinition(
                  $templateDir, $mockClassName['fullClassName'], $methodName, $cloneArguments
                );
            }
        }

        $classTemplate->setVar(
          array(
            'prologue'          => isset($prologue) ? $prologue : '',
            'epilogue'          => isset($epilogue) ? $epilogue : '',
            'class_declaration' => self::generateMockClassDeclaration(
                                     $mockClassName, $isInterface
                                   ),
            'clone'             => $cloneTemplate,
            'mock_class_name'   => $mockClassName['className'],
            'mocked_methods'    => $mockedMethods
          )
        );

        return array(
          'code'          => $classTemplate->render(),
          'mockClassName' => $mockClassName['className']
        );
    }

    /**
     * @param  string $originalClassName
     * @param  string $className
     * @param  string $prefix
     * @return array
     */
    protected static function generateClassName($originalClassName, $className, $prefix)
    {
        if ($originalClassName[0] == '\\') {
            $originalClassName = substr($originalClassName, 1);
        }

        $classNameParts = explode('\\', $originalClassName);

        if (count($classNameParts) > 1) {
            $originalClassName = array_pop($classNameParts);
            $namespaceName     = join('\\', $classNameParts);
            $fullClassName     = $namespaceName . '\\' . $originalClassName;
        } else {
            $namespaceName = '';
            $fullClassName = $originalClassName;
        }

        if ($className == '') {
            do {
                $className = $prefix . $originalClassName . '_' .
                             substr(md5(microtime()), 0, 8);
            }
            while (class_exists($className, FALSE));
        }

        return array(
          'className'         => $className,
          'originalClassName' => $originalClassName,
          'fullClassName'     => $fullClassName,
          'namespaceName'     => $namespaceName
        );
    }

    /**
     * @param  array   $mockClassName
     * @param  boolean $isInterface
     * @return array
     */
    protected static function generateMockClassDeclaration(array $mockClassName, $isInterface)
    {
        $buffer = 'class ';

        if ($isInterface) {
            $buffer .= sprintf(
              "%s implements PHPUnit_Framework_MockObject_MockObject, %s%s",
              $mockClassName['className'],
              !empty($mockClassName['namespaceName']) ? $mockClassName['namespaceName'] . '\\' : '',
              $mockClassName['originalClassName']
            );
        } else {
            $buffer .= sprintf(
              "%s extends %s%s implements PHPUnit_Framework_MockObject_MockObject",
              $mockClassName['className'],
              !empty($mockClassName['namespaceName']) ? $mockClassName['namespaceName'] . '\\' : '',
              $mockClassName['originalClassName']
            );
        }

        return $buffer;
    }

    /**
     * @param  string           $templateDir
     * @param  ReflectionMethod $method
     * @param  boolean          $cloneArguments
     * @return string
     */
    protected static function generateMockedMethodDefinitionFromExisting($templateDir, ReflectionMethod $method, $cloneArguments = TRUE)
    {
        if ($method->isPrivate()) {
            $modifier = 'private';
        }

        else if ($method->isProtected()) {
            $modifier = 'protected';
        }

        else {
            $modifier = 'public';
        }

        if ($method->isStatic()) {
            $static = TRUE;
        } else {
            $static = FALSE;
        }

        if ($method->returnsReference()) {
            $reference = '&';
        } else {
            $reference = '';
        }

        return self::generateMockedMethodDefinition(
          $templateDir,
          $method->getDeclaringClass()->getName(),
          $method->getName(),
          $cloneArguments,
          $modifier,
          PHPUnit_Util_Class::getMethodParameters($method),
          PHPUnit_Util_Class::getMethodParameters($method, TRUE),
          $reference,
          $static
        );
    }

    /**
     * @param  string  $templateDir
     * @param  string  $className
     * @param  string  $methodName
     * @param  boolean $cloneArguments
     * @param  string  $modifier
     * @param  string  $arguments_decl
     * @param  string  $arguments_call
     * @param  string  $reference
     * @param  boolean $static
     * @return string
     */
    protected static function generateMockedMethodDefinition($templateDir, $className, $methodName, $cloneArguments = TRUE, $modifier = 'public', $arguments_decl = '', $arguments_call = '', $reference = '', $static = FALSE)
    {
        if ($static) {
            $template = new Text_Template(
              $templateDir . 'mocked_static_method.tpl'
            );
        } else {
            $template = new Text_Template(
              $templateDir . 'mocked_object_method.tpl'
            );
        }

        $template->setVar(
          array(
            'arguments_decl'  => $arguments_decl,
            'arguments_call'  => $arguments_call,
            'arguments_count' => !empty($arguments_call) ? count(explode(',', $arguments_call)) : 0,
            'class_name'      => $className,
            'method_name'     => $methodName,
            'modifier'        => $modifier,
            'reference'       => $reference,
            'clone_arguments' => $cloneArguments ? 'TRUE' : 'FALSE'
          )
        );

        return $template->render();
    }

    /**
     * @param  ReflectionMethod $method
     * @return boolean
     */
    protected static function canMockMethod(ReflectionMethod $method)
    {
        if ($method->isConstructor() || $method->isFinal() ||
            isset(self::$blacklistedMethodNames[$method->getName()])) {
            return FALSE;
        }

        return TRUE;
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * An object that stubs the process of a normal method for a mock object.
 *
 * The stub object will replace the code for the stubbed method and return a
 * specific value instead of the original value.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Interface available since Release 1.0.0
 */
interface PHPUnit_Framework_MockObject_Stub extends PHPUnit_Framework_SelfDescribing
{
    /**
     * Fakes the processing of the invocation $invocation by returning a
     * specific value.
     *
     * @param  PHPUnit_Framework_MockObject_Invocation $invocation
     *         The invocation which was mocked and matched by the current method
     *         and argument matchers.
     * @return mixed
     */
    public function invoke(PHPUnit_Framework_MockObject_Invocation $invocation);
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

/**
 * Interface for classes which must verify a given expectation.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      Interface available since Release 1.0.0
 */
interface PHPUnit_Framework_MockObject_Verifiable
{
    /**
     * Verifies that the current expectation is valid. If everything is OK the
     * code should just return, if not it must throw an exception.
     *
     * @throws PHPUnit_Framework_ExpectationFailedException
     */
    public function verify();
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2002-2011, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2002-2011 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.1.0
 */

spl_autoload_register(
  function ($class)
  {
      static $classes = NULL;
      static $path = NULL;

      if ($classes === NULL) {
          $classes = array(
            ___CLASSLIST___
          );

          $path = dirname(dirname(dirname(__FILE__)));
      }

      $cn = strtolower($class);

      if (isset($classes[$cn])) {
          require $path . $classes[$cn];
      }
  }
);
PHPUnit_MockObject 1.2
======================

This is the list of changes for the PHPUnit_MockObject 1.2 release series.

PHPUnit_MockObject 1.2.3
------------------------

* Fixed a bug where getting two mocks with different argument cloning options returned the same mock.

PHPUnit_MockObject 1.2.2
------------------------

* Fixed #100: Removed the unique mock object ID introduced in version 1.2.

PHPUnit_MockObject 1.2.1
------------------------

* No changes.

PHPUnit_MockObject 1.2.0
------------------------

* Implemented #47: Make cloning of arguments passed to mocked methods optional.
* Implemented #84: `getMockFromWsdl()` now works with namespaces.
* Fixed #90: Mocks with a fixed class name could only be created once.

<?xml version="1.0" encoding="UTF-8"?>

<project name="PHPUnit_MockObject" default="build">
 <property name="php" value="php"/>
 <property name="phpunit" value="phpunit"/>

 <target name="build"
   depends="prepare,lint,phploc,pdepend,phpmd-ci,phpcs-ci,phpcpd,phpunit,phpcb"/>

 <target name="build-parallel"
   depends="prepare,lint,tools-parallel,phpunit,phpcb"/>

 <target name="tools-parallel"
         description="Run tools in parallel">
  <parallel threadCount="2">
   <sequential>
    <antcall target="pdepend"/>
    <antcall target="phpmd-ci"/>
   </sequential>
   <antcall target="phpcpd"/>
   <antcall target="phpcs-ci"/>
   <antcall target="phploc"/>
  </parallel>
 </target>

 <target name="clean" description="Cleanup build artifacts">
  <delete dir="${basedir}/build/api"/>
  <delete dir="${basedir}/build/code-browser"/>
  <delete dir="${basedir}/build/coverage"/>
  <delete dir="${basedir}/build/logs"/>
  <delete dir="${basedir}/build/pdepend"/>
 </target>

 <target name="prepare" depends="clean,phpab"
         description="Prepare for build">
  <mkdir dir="${basedir}/build/api"/>
  <mkdir dir="${basedir}/build/code-browser"/>
  <mkdir dir="${basedir}/build/coverage"/>
  <mkdir dir="${basedir}/build/logs"/>
  <mkdir dir="${basedir}/build/pdepend"/>
 </target>

 <target name="phpab" description="Generate autoloader scripts">
  <exec executable="phpab">
   <arg value="--output" />
   <arg path="PHPUnit/Framework/MockObject/Autoload.php" />
   <arg value="--template" />
   <arg path="PHPUnit/Framework/MockObject/Autoload.php.in" />
   <arg value="--indent" />
   <arg value="            " />
   <arg path="PHPUnit" />
  </exec>
 </target>

 <target name="lint">
  <apply executable="${php}" failonerror="true">
   <arg value="-l" />

   <fileset dir="${basedir}/PHPUnit">
    <include name="**/*.php" />
    <modified />
   </fileset>

   <fileset dir="${basedir}/Tests">
    <include name="**/*.php" />
    <modified />
   </fileset>
  </apply>
 </target>

 <target name="phploc" description="Measure project size using PHPLOC">
  <exec executable="phploc">
   <arg value="--log-csv" />
   <arg value="${basedir}/build/logs/phploc.csv" />
   <arg path="${basedir}/PHPUnit" />
  </exec>
 </target>

 <target name="pdepend"
         description="Calculate software metrics using PHP_Depend">
  <exec executable="pdepend">
   <arg value="--jdepend-xml=${basedir}/build/logs/jdepend.xml" />
   <arg value="--jdepend-chart=${basedir}/build/pdepend/dependencies.svg" />
   <arg value="--overview-pyramid=${basedir}/build/pdepend/overview-pyramid.svg" />
   <arg path="${basedir}/PHPUnit" />
  </exec>
 </target>

 <target name="phpmd"
         description="Perform project mess detection using PHPMD">
  <exec executable="phpmd">
   <arg path="${basedir}/PHPUnit" />
   <arg value="text" />
   <arg value="${basedir}/build/phpmd.xml" />
  </exec>
 </target>

 <target name="phpmd-ci"
         description="Perform project mess detection using PHPMD">
  <exec executable="phpmd">
   <arg path="${basedir}/PHPUnit" />
   <arg value="xml" />
   <arg value="${basedir}/build/phpmd.xml" />
   <arg value="--reportfile" />
   <arg value="${basedir}/build/logs/pmd.xml" />
  </exec>
 </target>

 <target name="phpcs"
         description="Find coding standard violations using PHP_CodeSniffer">
  <exec executable="phpcs">
   <arg value="--standard=${basedir}/build/PHPCS" />
   <arg value="--extensions=php" />
   <arg value="--ignore=Autoload.php" />
   <arg path="${basedir}/PHPUnit" />
   <arg path="${basedir}/Tests" />
  </exec>
 </target>

 <target name="phpcs-ci"
         description="Find coding standard violations using PHP_CodeSniffer">
  <exec executable="phpcs" output="/dev/null">
   <arg value="--report=checkstyle" />
   <arg value="--report-file=${basedir}/build/logs/checkstyle.xml" />
   <arg value="--standard=${basedir}/build/PHPCS" />
   <arg value="--extensions=php" />
   <arg value="--ignore=Autoload.php" />
   <arg path="${basedir}/PHPUnit" />
   <arg path="${basedir}/Tests" />
  </exec>
 </target>

 <target name="phpcpd" description="Find duplicate code using PHPCPD">
  <exec executable="phpcpd">
   <arg value="--log-pmd" />
   <arg value="${basedir}/build/logs/pmd-cpd.xml" />
   <arg path="${basedir}/PHPUnit" />
  </exec>
 </target>

 <target name="phpunit" description="Run unit tests with PHPUnit">
  <condition property="phpunit_cmd" value="${php} ${phpunit}" else="${phpunit}">
   <not>
    <equals arg1="${phpunit}" arg2="phpunit" />
   </not>
  </condition>

  <exec executable="${phpunit_cmd}" failonerror="true"/>
 </target>

 <target name="phpcb"
         description="Aggregate tool output with PHP_CodeBrowser">
  <exec executable="phpcb">
   <arg value="--log" />
   <arg path="${basedir}/build/logs" />
   <arg value="--source" />
   <arg path="${basedir}/PHPUnit" />
   <arg value="--output" />
   <arg path="${basedir}/build/code-browser" />
  </exec>
 </target>
</project>
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false">
  <php>
    <const name="PHPUNIT_TESTSUITE" value="true"/>
  </php>

  <testsuites>
    <testsuite name="PHPUnit Mock Objects">
      <directory suffix="Test.php">Tests</directory>
      <directory suffix=".phpt">Tests</directory>
    </testsuite>
  </testsuites>

  <logging>
    <log type="coverage-html" target="build/coverage" title="PHPUnit Mock Objects"
         charset="UTF-8" yui="true" highlight="true"
         lowUpperBound="35" highLowerBound="70"/>
    <log type="coverage-clover" target="build/logs/clover.xml"/>
    <log type="junit" target="build/logs/junit.xml" logIncompleteSkipped="false"/>
  </logging>

  <filter>
    <whitelist addUncoveredFilesFromWhitelist="true">
      <directory suffix=".php">PHPUnit</directory>
      <exclude>
       <file>PHPUnit/Framework/MockObject/Autoload.php</file>
      </exclude>
    </whitelist>
  </filter>
</phpunit>
<?php
class Framework_MockObject_GeneratorTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers PHPUnit_Framework_MockObject_Generator::getMock
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testGetMockFailsWhenInvalidFunctionNameIsPassedInAsAFunctionToMock()
    {
        PHPUnit_Framework_MockObject_Generator::getMock('StdClass', array(0));
    }

    /**
     * @covers PHPUnit_Framework_MockObject_Generator::getMock
     */
    public function testGetMockCanCreateNonExistingFunctions()
    {
        $mock = PHPUnit_Framework_MockObject_Generator::getMock('StdClass', array('testFunction'));
        $this->assertTrue(method_exists($mock, 'testFunction'));
    }

    /**
     * @covers PHPUnit_Framework_MockObject_Generator::getMock
     * @expectedException PHPUnit_Framework_Exception
     * @expectedExceptionMessage duplicates: "foo, foo"
     */
    public function testGetMockGeneratorFails()
    {
        $mock = PHPUnit_Framework_MockObject_Generator::getMock('StdClass', array('foo', 'foo'));
    }

    /**
     * @covers PHPUnit_Framework_MockObject_Generator::getMockForAbstractClass
     */
    public function testGetMockForAbstractClassDoesNotFailWhenFakingInterfaces()
    {
        $mock = PHPUnit_Framework_MockObject_Generator::getMockForAbstractClass('Countable');
        $this->assertTrue(method_exists($mock, 'count'));
    }

    /**
     * @covers PHPUnit_Framework_MockObject_Generator::getMockForAbstractClass
     */
    public function testGetMockForAbstractClassStubbingAbstractClass()
    {
        $mock = PHPUnit_Framework_MockObject_Generator::getMockForAbstractClass('AbstractMockTestClass');
        $this->assertTrue(method_exists($mock, 'doSomething'));
    }

    /**
     * @dataProvider getMockForAbstractClassExpectsInvalidArgumentExceptionDataprovider
     * @covers PHPUnit_Framework_MockObject_Generator::getMockForAbstractClass
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testGetMockForAbstractClassExpectingInvalidArgumentException($className, $mockClassName)
    {
        $mock = PHPUnit_Framework_MockObject_Generator::getMockForAbstractClass($className, array(), $mockClassName);
    }

    /**
     * @covers PHPUnit_Framework_MockObject_Generator::getMockForAbstractClass
     * @expectedException PHPUnit_Framework_Exception
     */
    public function testGetMockForAbstractClassAnstractClassDoesNotExist()
    {
        $mock = PHPUnit_Framework_MockObject_Generator::getMockForAbstractClass('Tux');
    }

    /**
     * Dataprovider for test "testGetMockForAbstractClassExpectingInvalidArgumentException"
     */
    public static function getMockForAbstractClassExpectsInvalidArgumentExceptionDataprovider()
    {
        return array(
            'className not a string' => array(array(), ''),
            'mockClassName not a string' => array('Countable', new StdClass),
        );
    }
}
--TEST--
PHPUnit_Framework_MockObject_Generator::generate('NS\Foo', array(), 'MockFoo', TRUE, TRUE)
--FILE--
<?php
namespace NS;

interface Foo
{
    public function bar(Foo $foo);
}

require_once 'PHPUnit/Autoload.php';
require_once 'Text/Template.php';

$mock = \PHPUnit_Framework_MockObject_Generator::generate(
  'NS\Foo',
  array(),
  'MockFoo',
  TRUE,
  TRUE
);

print $mock['code'];
?>
--EXPECTF--
class MockFoo implements PHPUnit_Framework_MockObject_MockObject, NS\Foo
{
    private static $__phpunit_staticInvocationMocker;
    private $__phpunit_invocationMocker;

    public function __clone()
    {
        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
    }

    public function bar(NS\Foo $foo)
    {
        $arguments = array($foo);
        $count     = func_num_args();

        if ($count > 1) {
            $_arguments = func_get_args();

            for ($i = 1; $i < $count; $i++) {
                $arguments[] = $_arguments[$i];
            }
        }

        $result = $this->__phpunit_getInvocationMocker()->invoke(
          new PHPUnit_Framework_MockObject_Invocation_Object(
            'NS\Foo', 'bar', $arguments, $this, TRUE
          )
        );

        return $result;
    }

    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return $this->__phpunit_getInvocationMocker()->expects($matcher);
    }

    public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return self::__phpunit_getStaticInvocationMocker()->expects($matcher);
    }

    public function __phpunit_getInvocationMocker()
    {
        if ($this->__phpunit_invocationMocker === NULL) {
            $this->__phpunit_invocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return $this->__phpunit_invocationMocker;
    }

    public static function __phpunit_getStaticInvocationMocker()
    {
        if (self::$__phpunit_staticInvocationMocker === NULL) {
            self::$__phpunit_staticInvocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return self::$__phpunit_staticInvocationMocker;
    }

    public function __phpunit_hasMatchers()
    {
        return self::__phpunit_getStaticInvocationMocker()->hasMatchers() ||
               $this->__phpunit_getInvocationMocker()->hasMatchers();
    }

    public function __phpunit_verify()
    {
        self::__phpunit_getStaticInvocationMocker()->verify();
        $this->__phpunit_getInvocationMocker()->verify();
    }

    public function __phpunit_cleanup()
    {
        self::$__phpunit_staticInvocationMocker = NULL;
        $this->__phpunit_invocationMocker       = NULL;
    }
}
--TEST--
PHPUnit_Framework_MockObject_Generator::generate('Foo', array(), 'MockFoo', TRUE, TRUE)
--FILE--
<?php
require_once 'PHPUnit/Autoload.php';
require_once 'Text/Template.php';

$mock = PHPUnit_Framework_MockObject_Generator::generate(
  '\NS\Foo',
  array(),
  'MockFoo',
  TRUE,
  TRUE
);

print $mock['code'];
?>
--EXPECTF--
namespace NS {

class Foo
{
}

}

namespace {

class MockFoo extends NS\Foo implements PHPUnit_Framework_MockObject_MockObject
{
    private static $__phpunit_staticInvocationMocker;
    private $__phpunit_invocationMocker;

    public function __clone()
    {
        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
    }

    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return $this->__phpunit_getInvocationMocker()->expects($matcher);
    }

    public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return self::__phpunit_getStaticInvocationMocker()->expects($matcher);
    }

    public function __phpunit_getInvocationMocker()
    {
        if ($this->__phpunit_invocationMocker === NULL) {
            $this->__phpunit_invocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return $this->__phpunit_invocationMocker;
    }

    public static function __phpunit_getStaticInvocationMocker()
    {
        if (self::$__phpunit_staticInvocationMocker === NULL) {
            self::$__phpunit_staticInvocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return self::$__phpunit_staticInvocationMocker;
    }

    public function __phpunit_hasMatchers()
    {
        return self::__phpunit_getStaticInvocationMocker()->hasMatchers() ||
               $this->__phpunit_getInvocationMocker()->hasMatchers();
    }

    public function __phpunit_verify()
    {
        self::__phpunit_getStaticInvocationMocker()->verify();
        $this->__phpunit_getInvocationMocker()->verify();
    }

    public function __phpunit_cleanup()
    {
        self::$__phpunit_staticInvocationMocker = NULL;
        $this->__phpunit_invocationMocker       = NULL;
    }
}

}
--TEST--
PHPUnit_Framework_MockObject_Generator::generate('Foo', array(), 'MockFoo', TRUE)
--FILE--
<?php
class Foo
{
    public function __clone()
    {
    }
}

require_once 'PHPUnit/Autoload.php';
require_once 'Text/Template.php';

$mock = PHPUnit_Framework_MockObject_Generator::generate(
  'Foo',
  array(),
  'MockFoo',
  TRUE
);

print $mock['code'];
?>
--EXPECTF--
class MockFoo extends Foo implements PHPUnit_Framework_MockObject_MockObject
{
    private static $__phpunit_staticInvocationMocker;
    private $__phpunit_invocationMocker;

    public function __clone()
    {
        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
        parent::__clone();
    }

    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return $this->__phpunit_getInvocationMocker()->expects($matcher);
    }

    public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return self::__phpunit_getStaticInvocationMocker()->expects($matcher);
    }

    public function __phpunit_getInvocationMocker()
    {
        if ($this->__phpunit_invocationMocker === NULL) {
            $this->__phpunit_invocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return $this->__phpunit_invocationMocker;
    }

    public static function __phpunit_getStaticInvocationMocker()
    {
        if (self::$__phpunit_staticInvocationMocker === NULL) {
            self::$__phpunit_staticInvocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return self::$__phpunit_staticInvocationMocker;
    }

    public function __phpunit_hasMatchers()
    {
        return self::__phpunit_getStaticInvocationMocker()->hasMatchers() ||
               $this->__phpunit_getInvocationMocker()->hasMatchers();
    }

    public function __phpunit_verify()
    {
        self::__phpunit_getStaticInvocationMocker()->verify();
        $this->__phpunit_getInvocationMocker()->verify();
    }

    public function __phpunit_cleanup()
    {
        self::$__phpunit_staticInvocationMocker = NULL;
        $this->__phpunit_invocationMocker       = NULL;
    }
}

--TEST--
PHPUnit_Framework_MockObject_Generator::generate('NS\Foo', array(), 'MockFoo', TRUE)
--FILE--
<?php
namespace NS;

class Foo
{
    public function __construct()
    {
    }
}

require_once 'PHPUnit/Autoload.php';
require_once 'Text/Template.php';

$mock = \PHPUnit_Framework_MockObject_Generator::generate(
  'NS\Foo',
  array(),
  'MockFoo',
  TRUE
);

print $mock['code'];
?>
--EXPECTF--
class MockFoo extends NS\Foo implements PHPUnit_Framework_MockObject_MockObject
{
    private static $__phpunit_staticInvocationMocker;
    private $__phpunit_invocationMocker;

    public function __clone()
    {
        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
    }

    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return $this->__phpunit_getInvocationMocker()->expects($matcher);
    }

    public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return self::__phpunit_getStaticInvocationMocker()->expects($matcher);
    }

    public function __phpunit_getInvocationMocker()
    {
        if ($this->__phpunit_invocationMocker === NULL) {
            $this->__phpunit_invocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return $this->__phpunit_invocationMocker;
    }

    public static function __phpunit_getStaticInvocationMocker()
    {
        if (self::$__phpunit_staticInvocationMocker === NULL) {
            self::$__phpunit_staticInvocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return self::$__phpunit_staticInvocationMocker;
    }

    public function __phpunit_hasMatchers()
    {
        return self::__phpunit_getStaticInvocationMocker()->hasMatchers() ||
               $this->__phpunit_getInvocationMocker()->hasMatchers();
    }

    public function __phpunit_verify()
    {
        self::__phpunit_getStaticInvocationMocker()->verify();
        $this->__phpunit_getInvocationMocker()->verify();
    }

    public function __phpunit_cleanup()
    {
        self::$__phpunit_staticInvocationMocker = NULL;
        $this->__phpunit_invocationMocker       = NULL;
    }
}

--TEST--
PHPUnit_Framework_MockObject_Generator::generate('Foo', array(), 'MockFoo', TRUE)
--FILE--
<?php
class Foo
{
    public function __construct()
    {
    }
}

require_once 'PHPUnit/Autoload.php';
require_once 'Text/Template.php';

$mock = PHPUnit_Framework_MockObject_Generator::generate(
  'Foo',
  array(),
  'MockFoo',
  TRUE
);

print $mock['code'];
?>
--EXPECTF--
class MockFoo extends Foo implements PHPUnit_Framework_MockObject_MockObject
{
    private static $__phpunit_staticInvocationMocker;
    private $__phpunit_invocationMocker;

    public function __clone()
    {
        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
    }

    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return $this->__phpunit_getInvocationMocker()->expects($matcher);
    }

    public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return self::__phpunit_getStaticInvocationMocker()->expects($matcher);
    }

    public function __phpunit_getInvocationMocker()
    {
        if ($this->__phpunit_invocationMocker === NULL) {
            $this->__phpunit_invocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return $this->__phpunit_invocationMocker;
    }

    public static function __phpunit_getStaticInvocationMocker()
    {
        if (self::$__phpunit_staticInvocationMocker === NULL) {
            self::$__phpunit_staticInvocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return self::$__phpunit_staticInvocationMocker;
    }

    public function __phpunit_hasMatchers()
    {
        return self::__phpunit_getStaticInvocationMocker()->hasMatchers() ||
               $this->__phpunit_getInvocationMocker()->hasMatchers();
    }

    public function __phpunit_verify()
    {
        self::__phpunit_getStaticInvocationMocker()->verify();
        $this->__phpunit_getInvocationMocker()->verify();
    }

    public function __phpunit_cleanup()
    {
        self::$__phpunit_staticInvocationMocker = NULL;
        $this->__phpunit_invocationMocker       = NULL;
    }
}

--TEST--
PHPUnit_Framework_MockObject_Generator::generate('NS\Foo', array(), 'MockFoo', FALSE)
--FILE--
<?php
namespace NS;

class Foo
{
    public function __clone()
    {
    }
}

require_once 'PHPUnit/Autoload.php';
require_once 'Text/Template.php';

$mock = \PHPUnit_Framework_MockObject_Generator::generate(
  'NS\Foo',
  array(),
  'MockFoo',
  FALSE
);

print $mock['code'];
?>
--EXPECTF--
class MockFoo extends NS\Foo implements PHPUnit_Framework_MockObject_MockObject
{
    private static $__phpunit_staticInvocationMocker;
    private $__phpunit_invocationMocker;

    public function __clone()
    {
        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
    }

    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return $this->__phpunit_getInvocationMocker()->expects($matcher);
    }

    public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return self::__phpunit_getStaticInvocationMocker()->expects($matcher);
    }

    public function __phpunit_getInvocationMocker()
    {
        if ($this->__phpunit_invocationMocker === NULL) {
            $this->__phpunit_invocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return $this->__phpunit_invocationMocker;
    }

    public static function __phpunit_getStaticInvocationMocker()
    {
        if (self::$__phpunit_staticInvocationMocker === NULL) {
            self::$__phpunit_staticInvocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return self::$__phpunit_staticInvocationMocker;
    }

    public function __phpunit_hasMatchers()
    {
        return self::__phpunit_getStaticInvocationMocker()->hasMatchers() ||
               $this->__phpunit_getInvocationMocker()->hasMatchers();
    }

    public function __phpunit_verify()
    {
        self::__phpunit_getStaticInvocationMocker()->verify();
        $this->__phpunit_getInvocationMocker()->verify();
    }

    public function __phpunit_cleanup()
    {
        self::$__phpunit_staticInvocationMocker = NULL;
        $this->__phpunit_invocationMocker       = NULL;
    }
}

--TEST--
PHPUnit_Framework_MockObject_Generator::generate('NS\Foo', array(), 'MockFoo', TRUE)
--FILE--
<?php
namespace NS;

class Foo
{
    public function __clone()
    {
    }
}

require_once 'PHPUnit/Autoload.php';
require_once 'Text/Template.php';

$mock = \PHPUnit_Framework_MockObject_Generator::generate(
  'NS\Foo',
  array(),
  'MockFoo',
  TRUE
);

print $mock['code'];
?>
--EXPECTF--
class MockFoo extends NS\Foo implements PHPUnit_Framework_MockObject_MockObject
{
    private static $__phpunit_staticInvocationMocker;
    private $__phpunit_invocationMocker;

    public function __clone()
    {
        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
        parent::__clone();
    }

    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return $this->__phpunit_getInvocationMocker()->expects($matcher);
    }

    public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return self::__phpunit_getStaticInvocationMocker()->expects($matcher);
    }

    public function __phpunit_getInvocationMocker()
    {
        if ($this->__phpunit_invocationMocker === NULL) {
            $this->__phpunit_invocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return $this->__phpunit_invocationMocker;
    }

    public static function __phpunit_getStaticInvocationMocker()
    {
        if (self::$__phpunit_staticInvocationMocker === NULL) {
            self::$__phpunit_staticInvocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return self::$__phpunit_staticInvocationMocker;
    }

    public function __phpunit_hasMatchers()
    {
        return self::__phpunit_getStaticInvocationMocker()->hasMatchers() ||
               $this->__phpunit_getInvocationMocker()->hasMatchers();
    }

    public function __phpunit_verify()
    {
        self::__phpunit_getStaticInvocationMocker()->verify();
        $this->__phpunit_getInvocationMocker()->verify();
    }

    public function __phpunit_cleanup()
    {
        self::$__phpunit_staticInvocationMocker = NULL;
        $this->__phpunit_invocationMocker       = NULL;
    }
}

--TEST--
PHPUnit_Framework_MockObject_Generator::generate('Foo', array(), 'MockFoo', TRUE, TRUE)
--FILE--
<?php
class Foo
{
    public function bar(Foo $foo)
    {
    }

    public function baz(Foo $foo)
    {
    }
}

require_once 'PHPUnit/Autoload.php';

$mock = PHPUnit_Framework_MockObject_Generator::generate(
  'Foo',
  array(),
  'MockFoo',
  TRUE,
  TRUE
);

print $mock['code'];
?>
--EXPECTF--
class MockFoo extends Foo implements PHPUnit_Framework_MockObject_MockObject
{
    private static $__phpunit_staticInvocationMocker;
    private $__phpunit_invocationMocker;

    public function __clone()
    {
        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
    }

    public function bar(Foo $foo)
    {
        $arguments = array($foo);
        $count     = func_num_args();

        if ($count > 1) {
            $_arguments = func_get_args();

            for ($i = 1; $i < $count; $i++) {
                $arguments[] = $_arguments[$i];
            }
        }

        $result = $this->__phpunit_getInvocationMocker()->invoke(
          new PHPUnit_Framework_MockObject_Invocation_Object(
            'Foo', 'bar', $arguments, $this, TRUE
          )
        );

        return $result;
    }

    public function baz(Foo $foo)
    {
        $arguments = array($foo);
        $count     = func_num_args();

        if ($count > 1) {
            $_arguments = func_get_args();

            for ($i = 1; $i < $count; $i++) {
                $arguments[] = $_arguments[$i];
            }
        }

        $result = $this->__phpunit_getInvocationMocker()->invoke(
          new PHPUnit_Framework_MockObject_Invocation_Object(
            'Foo', 'baz', $arguments, $this, TRUE
          )
        );

        return $result;
    }

    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return $this->__phpunit_getInvocationMocker()->expects($matcher);
    }

    public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return self::__phpunit_getStaticInvocationMocker()->expects($matcher);
    }

    public function __phpunit_getInvocationMocker()
    {
        if ($this->__phpunit_invocationMocker === NULL) {
            $this->__phpunit_invocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return $this->__phpunit_invocationMocker;
    }

    public static function __phpunit_getStaticInvocationMocker()
    {
        if (self::$__phpunit_staticInvocationMocker === NULL) {
            self::$__phpunit_staticInvocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return self::$__phpunit_staticInvocationMocker;
    }

    public function __phpunit_hasMatchers()
    {
        return self::__phpunit_getStaticInvocationMocker()->hasMatchers() ||
               $this->__phpunit_getInvocationMocker()->hasMatchers();
    }

    public function __phpunit_verify()
    {
        self::__phpunit_getStaticInvocationMocker()->verify();
        $this->__phpunit_getInvocationMocker()->verify();
    }

    public function __phpunit_cleanup()
    {
        self::$__phpunit_staticInvocationMocker = NULL;
        $this->__phpunit_invocationMocker       = NULL;
    }
}
--TEST--
PHPUnit_Framework_MockObject_Generator::generate('NS\Foo', array(), 'MockFoo', TRUE)
--FILE--
<?php
namespace NS;

class Foo
{
    public function __construct()
    {
    }
}

require_once 'PHPUnit/Autoload.php';
require_once 'Text/Template.php';

$mock = \PHPUnit_Framework_MockObject_Generator::generate(
  'NS\Foo',
  array(),
  'MockFoo',
  TRUE
);

print $mock['code'];
?>
--EXPECTF--
class MockFoo extends NS\Foo implements PHPUnit_Framework_MockObject_MockObject
{
    private static $__phpunit_staticInvocationMocker;
    private $__phpunit_invocationMocker;

    public function __clone()
    {
        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
    }

    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return $this->__phpunit_getInvocationMocker()->expects($matcher);
    }

    public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return self::__phpunit_getStaticInvocationMocker()->expects($matcher);
    }

    public function __phpunit_getInvocationMocker()
    {
        if ($this->__phpunit_invocationMocker === NULL) {
            $this->__phpunit_invocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return $this->__phpunit_invocationMocker;
    }

    public static function __phpunit_getStaticInvocationMocker()
    {
        if (self::$__phpunit_staticInvocationMocker === NULL) {
            self::$__phpunit_staticInvocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return self::$__phpunit_staticInvocationMocker;
    }

    public function __phpunit_hasMatchers()
    {
        return self::__phpunit_getStaticInvocationMocker()->hasMatchers() ||
               $this->__phpunit_getInvocationMocker()->hasMatchers();
    }

    public function __phpunit_verify()
    {
        self::__phpunit_getStaticInvocationMocker()->verify();
        $this->__phpunit_getInvocationMocker()->verify();
    }

    public function __phpunit_cleanup()
    {
        self::$__phpunit_staticInvocationMocker = NULL;
        $this->__phpunit_invocationMocker       = NULL;
    }
}

--TEST--
PHPUnit_Framework_MockObject_Generator::generate('Foo', array('bar'), 'MockFoo', TRUE, TRUE)
--FILE--
<?php
class Foo
{
    public function bar(Foo $foo)
    {
    }

    public function baz(Foo $foo)
    {
    }
}

require_once 'PHPUnit/Autoload.php';
require_once 'Text/Template.php';

$mock = PHPUnit_Framework_MockObject_Generator::generate(
  'Foo',
  array('bar'),
  'MockFoo',
  TRUE,
  TRUE
);

print $mock['code'];
?>
--EXPECTF--
class MockFoo extends Foo implements PHPUnit_Framework_MockObject_MockObject
{
    private static $__phpunit_staticInvocationMocker;
    private $__phpunit_invocationMocker;

    public function __clone()
    {
        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
    }

    public function bar(Foo $foo)
    {
        $arguments = array($foo);
        $count     = func_num_args();

        if ($count > 1) {
            $_arguments = func_get_args();

            for ($i = 1; $i < $count; $i++) {
                $arguments[] = $_arguments[$i];
            }
        }

        $result = $this->__phpunit_getInvocationMocker()->invoke(
          new PHPUnit_Framework_MockObject_Invocation_Object(
            'Foo', 'bar', $arguments, $this, TRUE
          )
        );

        return $result;
    }

    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return $this->__phpunit_getInvocationMocker()->expects($matcher);
    }

    public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return self::__phpunit_getStaticInvocationMocker()->expects($matcher);
    }

    public function __phpunit_getInvocationMocker()
    {
        if ($this->__phpunit_invocationMocker === NULL) {
            $this->__phpunit_invocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return $this->__phpunit_invocationMocker;
    }

    public static function __phpunit_getStaticInvocationMocker()
    {
        if (self::$__phpunit_staticInvocationMocker === NULL) {
            self::$__phpunit_staticInvocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return self::$__phpunit_staticInvocationMocker;
    }

    public function __phpunit_hasMatchers()
    {
        return self::__phpunit_getStaticInvocationMocker()->hasMatchers() ||
               $this->__phpunit_getInvocationMocker()->hasMatchers();
    }

    public function __phpunit_verify()
    {
        self::__phpunit_getStaticInvocationMocker()->verify();
        $this->__phpunit_getInvocationMocker()->verify();
    }

    public function __phpunit_cleanup()
    {
        self::$__phpunit_staticInvocationMocker = NULL;
        $this->__phpunit_invocationMocker       = NULL;
    }
}
--TEST--
PHPUnit_Framework_MockObject_Generator::generate('NS\Foo', array(), 'MockFoo', TRUE, TRUE)
--FILE--
<?php
namespace NS;

class Foo
{
    public function bar(Foo $foo)
    {
    }

    public function baz(Foo $foo)
    {
    }
}

require_once 'PHPUnit/Autoload.php';
require_once 'Text/Template.php';

$mock = \PHPUnit_Framework_MockObject_Generator::generate(
  'NS\Foo',
  array(),
  'MockFoo',
  TRUE,
  TRUE
);

print $mock['code'];
?>
--EXPECTF--
class MockFoo extends NS\Foo implements PHPUnit_Framework_MockObject_MockObject
{
    private static $__phpunit_staticInvocationMocker;
    private $__phpunit_invocationMocker;

    public function __clone()
    {
        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
    }

    public function bar(NS\Foo $foo)
    {
        $arguments = array($foo);
        $count     = func_num_args();

        if ($count > 1) {
            $_arguments = func_get_args();

            for ($i = 1; $i < $count; $i++) {
                $arguments[] = $_arguments[$i];
            }
        }

        $result = $this->__phpunit_getInvocationMocker()->invoke(
          new PHPUnit_Framework_MockObject_Invocation_Object(
            'NS\Foo', 'bar', $arguments, $this, TRUE
          )
        );

        return $result;
    }

    public function baz(NS\Foo $foo)
    {
        $arguments = array($foo);
        $count     = func_num_args();

        if ($count > 1) {
            $_arguments = func_get_args();

            for ($i = 1; $i < $count; $i++) {
                $arguments[] = $_arguments[$i];
            }
        }

        $result = $this->__phpunit_getInvocationMocker()->invoke(
          new PHPUnit_Framework_MockObject_Invocation_Object(
            'NS\Foo', 'baz', $arguments, $this, TRUE
          )
        );

        return $result;
    }

    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return $this->__phpunit_getInvocationMocker()->expects($matcher);
    }

    public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return self::__phpunit_getStaticInvocationMocker()->expects($matcher);
    }

    public function __phpunit_getInvocationMocker()
    {
        if ($this->__phpunit_invocationMocker === NULL) {
            $this->__phpunit_invocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return $this->__phpunit_invocationMocker;
    }

    public static function __phpunit_getStaticInvocationMocker()
    {
        if (self::$__phpunit_staticInvocationMocker === NULL) {
            self::$__phpunit_staticInvocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return self::$__phpunit_staticInvocationMocker;
    }

    public function __phpunit_hasMatchers()
    {
        return self::__phpunit_getStaticInvocationMocker()->hasMatchers() ||
               $this->__phpunit_getInvocationMocker()->hasMatchers();
    }

    public function __phpunit_verify()
    {
        self::__phpunit_getStaticInvocationMocker()->verify();
        $this->__phpunit_getInvocationMocker()->verify();
    }

    public function __phpunit_cleanup()
    {
        self::$__phpunit_staticInvocationMocker = NULL;
        $this->__phpunit_invocationMocker       = NULL;
    }
}
<?php

class Framework_MockObject_Invocation_ObjectTest extends PHPUnit_Framework_TestCase
{
    public function testConstructorRequiresClassAndMethodAndParametersAndObject()
    {
        new PHPUnit_Framework_MockObject_Invocation_Object(
            'FooClass',
            'FooMethod',
            array('an_argument'),
            new StdClass);
    }

    public function testAllowToGetClassNameSetInConstructor()
    {
        $invocation = new PHPUnit_Framework_MockObject_Invocation_Object(
            'FooClass',
            'FooMethod',
            array('an_argument'),
            new StdClass);

        $this->assertSame('FooClass', $invocation->className);
    }

    public function testAllowToGetMethodNameSetInConstructor()
    {
        $invocation = new PHPUnit_Framework_MockObject_Invocation_Object(
            'FooClass',
            'FooMethod',
            array('an_argument'),
            new StdClass);

        $this->assertSame('FooMethod', $invocation->methodName);
    }

    public function testAllowToGetObjectSetInConstructor()
    {
        $expectedObject = new StdClass;

        $invocation = new PHPUnit_Framework_MockObject_Invocation_Object(
            'FooClass',
            'FooMethod',
            array('an_argument'),
            $expectedObject);

        $this->assertSame($expectedObject, $invocation->object);
    }

    public function testAllowToGetMethodParametersSetInConstructor()
    {
        $expectedParameters = array(
          'foo', 5, array('a', 'b'), new StdClass, NULL, FALSE
        );

        $invocation = new PHPUnit_Framework_MockObject_Invocation_Object(
          'FooClass',
          'FooMethod',
          $expectedParameters,
          new StdClass
        );

        $this->assertSame($expectedParameters, $invocation->parameters);
    }

    public function testConstructorAllowToSetFlagCloneObjectsInParameters()
    {
        $parameters   = array(new StdClass);
        $cloneObjects = TRUE;

        $invocation = new PHPUnit_Framework_MockObject_Invocation_Object(
          'FooClass',
          'FooMethod',
          $parameters,
          new StdClass,
          $cloneObjects
        );

        $this->assertEquals($parameters, $invocation->parameters);
        $this->assertNotSame($parameters, $invocation->parameters);
    }
}

<?php

class Framework_MockObject_Invocation_StaticTest extends PHPUnit_Framework_TestCase
{
    public function testConstructorRequiresClassAndMethodAndParameters()
    {
        new PHPUnit_Framework_MockObject_Invocation_Static('FooClass', 'FooMethod', array('an_argument'));
    }

    public function testAllowToGetClassNameSetInConstructor()
    {
        $invocation = new PHPUnit_Framework_MockObject_Invocation_Static('FooClass', 'FooMethod', array('an_argument'));

        $this->assertSame('FooClass', $invocation->className);
    }

    public function testAllowToGetMethodNameSetInConstructor()
    {
        $invocation = new PHPUnit_Framework_MockObject_Invocation_Static('FooClass', 'FooMethod', array('an_argument'));

        $this->assertSame('FooMethod', $invocation->methodName);
    }

    public function testAllowToGetMethodParametersSetInConstructor()
    {
        $expectedParameters = array(
          'foo', 5, array('a', 'b'), new StdClass, NULL, FALSE
        );

        $invocation = new PHPUnit_Framework_MockObject_Invocation_Static(
          'FooClass', 'FooMethod', $expectedParameters
        );

        $this->assertSame($expectedParameters, $invocation->parameters);
    }

    public function testConstructorAllowToSetFlagCloneObjectsInParameters()
    {
        $parameters = array(new StdClass);
        $cloneObjects = TRUE;

        $invocation = new PHPUnit_Framework_MockObject_Invocation_Static(
          'FooClass',
          'FooMethod',
          $parameters,
          $cloneObjects
        );

        $this->assertEquals($parameters, $invocation->parameters);
        $this->assertNotSame($parameters, $invocation->parameters);
    }
}
--TEST--
PHPUnit_Framework_MockObject_Generator::generate('Foo', array(), 'MockFoo', TRUE)
--FILE--
<?php
interface IFoo
{
    public function __construct($bar);
}

class Foo implements IFoo
{
    public function __construct($bar)
    {
    }
}

require_once 'PHPUnit/Autoload.php';
require_once 'Text/Template.php';

$mock = PHPUnit_Framework_MockObject_Generator::generate(
  'Foo',
  array(),
  'MockFoo',
  TRUE
);

print $mock['code'];
?>
--EXPECTF--
class MockFoo extends Foo implements PHPUnit_Framework_MockObject_MockObject
{
    private static $__phpunit_staticInvocationMocker;
    private $__phpunit_invocationMocker;

    public function __clone()
    {
        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
    }

    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return $this->__phpunit_getInvocationMocker()->expects($matcher);
    }

    public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return self::__phpunit_getStaticInvocationMocker()->expects($matcher);
    }

    public function __phpunit_getInvocationMocker()
    {
        if ($this->__phpunit_invocationMocker === NULL) {
            $this->__phpunit_invocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return $this->__phpunit_invocationMocker;
    }

    public static function __phpunit_getStaticInvocationMocker()
    {
        if (self::$__phpunit_staticInvocationMocker === NULL) {
            self::$__phpunit_staticInvocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return self::$__phpunit_staticInvocationMocker;
    }

    public function __phpunit_hasMatchers()
    {
        return self::__phpunit_getStaticInvocationMocker()->hasMatchers() ||
               $this->__phpunit_getInvocationMocker()->hasMatchers();
    }

    public function __phpunit_verify()
    {
        self::__phpunit_getStaticInvocationMocker()->verify();
        $this->__phpunit_getInvocationMocker()->verify();
    }

    public function __phpunit_cleanup()
    {
        self::$__phpunit_staticInvocationMocker = NULL;
        $this->__phpunit_invocationMocker       = NULL;
    }
}

--TEST--
PHPUnit_Framework_MockObject_Generator::generate('NS\Foo', array(), 'MockFoo', TRUE)
--FILE--
<?php
namespace NS;

interface IFoo
{
    public function __construct($bar);
}

class Foo implements IFoo
{
    public function __construct($bar)
    {
    }
}

require_once 'PHPUnit/Autoload.php';
require_once 'Text/Template.php';

$mock = \PHPUnit_Framework_MockObject_Generator::generate(
  'NS\Foo',
  array(),
  'MockFoo',
  TRUE
);

print $mock['code'];
?>
--EXPECTF--
class MockFoo extends NS\Foo implements PHPUnit_Framework_MockObject_MockObject
{
    private static $__phpunit_staticInvocationMocker;
    private $__phpunit_invocationMocker;

    public function __clone()
    {
        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
    }

    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return $this->__phpunit_getInvocationMocker()->expects($matcher);
    }

    public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return self::__phpunit_getStaticInvocationMocker()->expects($matcher);
    }

    public function __phpunit_getInvocationMocker()
    {
        if ($this->__phpunit_invocationMocker === NULL) {
            $this->__phpunit_invocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return $this->__phpunit_invocationMocker;
    }

    public static function __phpunit_getStaticInvocationMocker()
    {
        if (self::$__phpunit_staticInvocationMocker === NULL) {
            self::$__phpunit_staticInvocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return self::$__phpunit_staticInvocationMocker;
    }

    public function __phpunit_hasMatchers()
    {
        return self::__phpunit_getStaticInvocationMocker()->hasMatchers() ||
               $this->__phpunit_getInvocationMocker()->hasMatchers();
    }

    public function __phpunit_verify()
    {
        self::__phpunit_getStaticInvocationMocker()->verify();
        $this->__phpunit_getInvocationMocker()->verify();
    }

    public function __phpunit_cleanup()
    {
        self::$__phpunit_staticInvocationMocker = NULL;
        $this->__phpunit_invocationMocker       = NULL;
    }
}

--TEST--
PHPUnit_Framework_MockObject_Generator::generate('Foo', array(), 'MockFoo', TRUE, TRUE, TRUE)
--FILE--
<?php
class Foo
{
    public function bar(Foo $foo)
    {
    }

    public function baz(Foo $foo)
    {
    }
}

require_once 'PHPUnit/Autoload.php';
require_once 'Text/Template.php';

$mock = PHPUnit_Framework_MockObject_Generator::generate(
  'Foo',
  array(),
  'MockFoo',
  TRUE,
  TRUE,
  TRUE
);

print $mock['code'];
?>
--EXPECTF--
class MockFoo extends Foo implements PHPUnit_Framework_MockObject_MockObject
{
    private static $__phpunit_staticInvocationMocker;
    private $__phpunit_invocationMocker;

    public function __clone()
    {
        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
    }

    public function bar(Foo $foo)
    {
        $arguments = array($foo);
        $count     = func_num_args();

        if ($count > 1) {
            $_arguments = func_get_args();

            for ($i = 1; $i < $count; $i++) {
                $arguments[] = $_arguments[$i];
            }
        }

        $result = $this->__phpunit_getInvocationMocker()->invoke(
          new PHPUnit_Framework_MockObject_Invocation_Object(
            'Foo', 'bar', $arguments, $this, TRUE
          )
        );

        return $result;
    }

    public function baz(Foo $foo)
    {
        $arguments = array($foo);
        $count     = func_num_args();

        if ($count > 1) {
            $_arguments = func_get_args();

            for ($i = 1; $i < $count; $i++) {
                $arguments[] = $_arguments[$i];
            }
        }

        $result = $this->__phpunit_getInvocationMocker()->invoke(
          new PHPUnit_Framework_MockObject_Invocation_Object(
            'Foo', 'baz', $arguments, $this, TRUE
          )
        );

        return $result;
    }

    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return $this->__phpunit_getInvocationMocker()->expects($matcher);
    }

    public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return self::__phpunit_getStaticInvocationMocker()->expects($matcher);
    }

    public function __phpunit_getInvocationMocker()
    {
        if ($this->__phpunit_invocationMocker === NULL) {
            $this->__phpunit_invocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return $this->__phpunit_invocationMocker;
    }

    public static function __phpunit_getStaticInvocationMocker()
    {
        if (self::$__phpunit_staticInvocationMocker === NULL) {
            self::$__phpunit_staticInvocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return self::$__phpunit_staticInvocationMocker;
    }

    public function __phpunit_hasMatchers()
    {
        return self::__phpunit_getStaticInvocationMocker()->hasMatchers() ||
               $this->__phpunit_getInvocationMocker()->hasMatchers();
    }

    public function __phpunit_verify()
    {
        self::__phpunit_getStaticInvocationMocker()->verify();
        $this->__phpunit_getInvocationMocker()->verify();
    }

    public function __phpunit_cleanup()
    {
        self::$__phpunit_staticInvocationMocker = NULL;
        $this->__phpunit_invocationMocker       = NULL;
    }
}
--TEST--
PHPUnit_Framework_MockObject_Generator::generateClassFromWsdl('GoogleSearch.wsdl', 'GoogleSearch')
--SKIPIF--
<?php
if (!extension_loaded('soap')) echo 'skip: SOAP extension is required';
?>
--FILE--
<?php
require_once 'PHPUnit/Autoload.php';
require_once 'Text/Template.php';

print PHPUnit_Framework_MockObject_Generator::generateClassFromWsdl(
  dirname(dirname(__FILE__)) . '/_files/GoogleSearch.wsdl',
  'My\\Space\\GoogleSearch'
);
?>
--EXPECTF--
namespace My\Space;

class GoogleSearch extends \SOAPClient
{
    public function __construct($wsdl, array $options)
    {
        parent::__construct('%s/GoogleSearch.wsdl', $options);
    }

    public function doGetCachedPage($key, $url)
    {
    }

    public function doSpellingSuggestion($key, $phrase)
    {
    }

    public function doGoogleSearch($key, $q, $start, $maxResults, $filter, $restrict, $safeSearch, $lr, $ie, $oe)
    {
    }
}
--TEST--
PHPUnit_Framework_MockObject_Generator::generate('Foo', array(), 'MockFoo', TRUE)
--FILE--
<?php
interface IFoo
{
    public function __construct($bar);
}

class Foo implements IFoo
{
    public function __construct($bar)
    {
    }
}

require_once 'PHPUnit/Autoload.php';
require_once 'Text/Template.php';

$mock = PHPUnit_Framework_MockObject_Generator::generate(
  'Foo',
  array(),
  'MockFoo',
  TRUE
);

print $mock['code'];
?>
--EXPECTF--
class MockFoo extends Foo implements PHPUnit_Framework_MockObject_MockObject
{
    private static $__phpunit_staticInvocationMocker;
    private $__phpunit_invocationMocker;

    public function __clone()
    {
        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
    }

    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return $this->__phpunit_getInvocationMocker()->expects($matcher);
    }

    public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return self::__phpunit_getStaticInvocationMocker()->expects($matcher);
    }

    public function __phpunit_getInvocationMocker()
    {
        if ($this->__phpunit_invocationMocker === NULL) {
            $this->__phpunit_invocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return $this->__phpunit_invocationMocker;
    }

    public static function __phpunit_getStaticInvocationMocker()
    {
        if (self::$__phpunit_staticInvocationMocker === NULL) {
            self::$__phpunit_staticInvocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return self::$__phpunit_staticInvocationMocker;
    }

    public function __phpunit_hasMatchers()
    {
        return self::__phpunit_getStaticInvocationMocker()->hasMatchers() ||
               $this->__phpunit_getInvocationMocker()->hasMatchers();
    }

    public function __phpunit_verify()
    {
        self::__phpunit_getStaticInvocationMocker()->verify();
        $this->__phpunit_getInvocationMocker()->verify();
    }

    public function __phpunit_cleanup()
    {
        self::$__phpunit_staticInvocationMocker = NULL;
        $this->__phpunit_invocationMocker       = NULL;
    }
}

--TEST--
PHPUnit_Framework_MockObject_Generator::generate('Foo', array(), 'MockFoo', TRUE, TRUE)
--FILE--
<?php
require_once 'PHPUnit/Autoload.php';
require_once 'Text/Template.php';

$mock = PHPUnit_Framework_MockObject_Generator::generate(
  'NS\Foo',
  array(),
  'MockFoo',
  TRUE,
  TRUE
);

print $mock['code'];
?>
--EXPECTF--
namespace NS {

class Foo
{
}

}

namespace {

class MockFoo extends NS\Foo implements PHPUnit_Framework_MockObject_MockObject
{
    private static $__phpunit_staticInvocationMocker;
    private $__phpunit_invocationMocker;

    public function __clone()
    {
        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
    }

    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return $this->__phpunit_getInvocationMocker()->expects($matcher);
    }

    public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return self::__phpunit_getStaticInvocationMocker()->expects($matcher);
    }

    public function __phpunit_getInvocationMocker()
    {
        if ($this->__phpunit_invocationMocker === NULL) {
            $this->__phpunit_invocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return $this->__phpunit_invocationMocker;
    }

    public static function __phpunit_getStaticInvocationMocker()
    {
        if (self::$__phpunit_staticInvocationMocker === NULL) {
            self::$__phpunit_staticInvocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return self::$__phpunit_staticInvocationMocker;
    }

    public function __phpunit_hasMatchers()
    {
        return self::__phpunit_getStaticInvocationMocker()->hasMatchers() ||
               $this->__phpunit_getInvocationMocker()->hasMatchers();
    }

    public function __phpunit_verify()
    {
        self::__phpunit_getStaticInvocationMocker()->verify();
        $this->__phpunit_getInvocationMocker()->verify();
    }

    public function __phpunit_cleanup()
    {
        self::$__phpunit_staticInvocationMocker = NULL;
        $this->__phpunit_invocationMocker       = NULL;
    }
}

}
--TEST--
PHPUnit_Framework_MockObject_Generator::generateClassFromWsdl('GoogleSearch.wsdl', 'GoogleSearch', array('doGoogleSearch'))
--SKIPIF--
<?php
if (!extension_loaded('soap')) echo 'skip: SOAP extension is required';
?>
--FILE--
<?php
require_once 'PHPUnit/Autoload.php';
require_once 'Text/Template.php';

print PHPUnit_Framework_MockObject_Generator::generateClassFromWsdl(
  dirname(dirname(__FILE__)) . '/_files/GoogleSearch.wsdl',
  'GoogleSearch',
  array('doGoogleSearch')
);
?>
--EXPECTF--
class GoogleSearch extends \SOAPClient
{
    public function __construct($wsdl, array $options)
    {
        parent::__construct('%s/GoogleSearch.wsdl', $options);
    }

    public function doGoogleSearch($key, $q, $start, $maxResults, $filter, $restrict, $safeSearch, $lr, $ie, $oe)
    {
    }
}
--TEST--
PHPUnit_Framework_MockObject_Generator::generate('Foo', array(), 'MockFoo', FALSE)
--FILE--
<?php
class Foo
{
    public function __clone()
    {
    }
}

require_once 'PHPUnit/Autoload.php';
require_once 'Text/Template.php';

$mock = PHPUnit_Framework_MockObject_Generator::generate(
  'Foo',
  array(),
  'MockFoo',
  FALSE
);

print $mock['code'];
?>
--EXPECTF--
class MockFoo extends Foo implements PHPUnit_Framework_MockObject_MockObject
{
    private static $__phpunit_staticInvocationMocker;
    private $__phpunit_invocationMocker;

    public function __clone()
    {
        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
    }

    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return $this->__phpunit_getInvocationMocker()->expects($matcher);
    }

    public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return self::__phpunit_getStaticInvocationMocker()->expects($matcher);
    }

    public function __phpunit_getInvocationMocker()
    {
        if ($this->__phpunit_invocationMocker === NULL) {
            $this->__phpunit_invocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return $this->__phpunit_invocationMocker;
    }

    public static function __phpunit_getStaticInvocationMocker()
    {
        if (self::$__phpunit_staticInvocationMocker === NULL) {
            self::$__phpunit_staticInvocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return self::$__phpunit_staticInvocationMocker;
    }

    public function __phpunit_hasMatchers()
    {
        return self::__phpunit_getStaticInvocationMocker()->hasMatchers() ||
               $this->__phpunit_getInvocationMocker()->hasMatchers();
    }

    public function __phpunit_verify()
    {
        self::__phpunit_getStaticInvocationMocker()->verify();
        $this->__phpunit_getInvocationMocker()->verify();
    }

    public function __phpunit_cleanup()
    {
        self::$__phpunit_staticInvocationMocker = NULL;
        $this->__phpunit_invocationMocker       = NULL;
    }
}

--TEST--
PHPUnit_Framework_MockObject_Generator::generate('Foo', array(), 'MockFoo', TRUE, TRUE)
--FILE--
<?php
interface Foo
{
    public function bar(Foo $foo);
}

require_once 'PHPUnit/Autoload.php';
require_once 'Text/Template.php';

$mock = PHPUnit_Framework_MockObject_Generator::generate(
  'Foo',
  array(),
  'MockFoo',
  TRUE,
  TRUE
);

print $mock['code'];
?>
--EXPECTF--
class MockFoo implements PHPUnit_Framework_MockObject_MockObject, Foo
{
    private static $__phpunit_staticInvocationMocker;
    private $__phpunit_invocationMocker;

    public function __clone()
    {
        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
    }

    public function bar(Foo $foo)
    {
        $arguments = array($foo);
        $count     = func_num_args();

        if ($count > 1) {
            $_arguments = func_get_args();

            for ($i = 1; $i < $count; $i++) {
                $arguments[] = $_arguments[$i];
            }
        }

        $result = $this->__phpunit_getInvocationMocker()->invoke(
          new PHPUnit_Framework_MockObject_Invocation_Object(
            'Foo', 'bar', $arguments, $this, TRUE
          )
        );

        return $result;
    }

    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return $this->__phpunit_getInvocationMocker()->expects($matcher);
    }

    public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return self::__phpunit_getStaticInvocationMocker()->expects($matcher);
    }

    public function __phpunit_getInvocationMocker()
    {
        if ($this->__phpunit_invocationMocker === NULL) {
            $this->__phpunit_invocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return $this->__phpunit_invocationMocker;
    }

    public static function __phpunit_getStaticInvocationMocker()
    {
        if (self::$__phpunit_staticInvocationMocker === NULL) {
            self::$__phpunit_staticInvocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return self::$__phpunit_staticInvocationMocker;
    }

    public function __phpunit_hasMatchers()
    {
        return self::__phpunit_getStaticInvocationMocker()->hasMatchers() ||
               $this->__phpunit_getInvocationMocker()->hasMatchers();
    }

    public function __phpunit_verify()
    {
        self::__phpunit_getStaticInvocationMocker()->verify();
        $this->__phpunit_getInvocationMocker()->verify();
    }

    public function __phpunit_cleanup()
    {
        self::$__phpunit_staticInvocationMocker = NULL;
        $this->__phpunit_invocationMocker       = NULL;
    }
}
--TEST--
PHPUnit_Framework_MockObject_Generator::generate('Foo', array(), 'MockFoo', TRUE)
--FILE--
<?php
class Foo
{
    public function __construct()
    {
    }
}

require_once 'PHPUnit/Autoload.php';
require_once 'Text/Template.php';

$mock = PHPUnit_Framework_MockObject_Generator::generate(
  'Foo',
  array(),
  'MockFoo',
  TRUE
);

print $mock['code'];
?>
--EXPECTF--
class MockFoo extends Foo implements PHPUnit_Framework_MockObject_MockObject
{
    private static $__phpunit_staticInvocationMocker;
    private $__phpunit_invocationMocker;

    public function __clone()
    {
        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
    }

    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return $this->__phpunit_getInvocationMocker()->expects($matcher);
    }

    public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return self::__phpunit_getStaticInvocationMocker()->expects($matcher);
    }

    public function __phpunit_getInvocationMocker()
    {
        if ($this->__phpunit_invocationMocker === NULL) {
            $this->__phpunit_invocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return $this->__phpunit_invocationMocker;
    }

    public static function __phpunit_getStaticInvocationMocker()
    {
        if (self::$__phpunit_staticInvocationMocker === NULL) {
            self::$__phpunit_staticInvocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return self::$__phpunit_staticInvocationMocker;
    }

    public function __phpunit_hasMatchers()
    {
        return self::__phpunit_getStaticInvocationMocker()->hasMatchers() ||
               $this->__phpunit_getInvocationMocker()->hasMatchers();
    }

    public function __phpunit_verify()
    {
        self::__phpunit_getStaticInvocationMocker()->verify();
        $this->__phpunit_getInvocationMocker()->verify();
    }

    public function __phpunit_cleanup()
    {
        self::$__phpunit_staticInvocationMocker = NULL;
        $this->__phpunit_invocationMocker       = NULL;
    }
}

--TEST--
PHPUnit_Framework_MockObject_Generator::generateClassFromWsdl('GoogleSearch.wsdl', 'GoogleSearch')
--SKIPIF--
<?php
if (!extension_loaded('soap')) echo 'skip: SOAP extension is required';
?>
--FILE--
<?php
require_once 'PHPUnit/Autoload.php';
require_once 'Text/Template.php';

print PHPUnit_Framework_MockObject_Generator::generateClassFromWsdl(
  dirname(dirname(__FILE__)) . '/_files/GoogleSearch.wsdl',
  'GoogleSearch'
);
?>
--EXPECTF--
class GoogleSearch extends \SOAPClient
{
    public function __construct($wsdl, array $options)
    {
        parent::__construct('%s/GoogleSearch.wsdl', $options);
    }

    public function doGetCachedPage($key, $url)
    {
    }

    public function doSpellingSuggestion($key, $phrase)
    {
    }

    public function doGoogleSearch($key, $q, $start, $maxResults, $filter, $restrict, $safeSearch, $lr, $ie, $oe)
    {
    }
}
--TEST--
PHPUnit_Framework_MockObject_Generator::generate('Foo', array(), 'MockFoo', TRUE, TRUE)
--FILE--
<?php
require_once 'PHPUnit/Autoload.php';
require_once 'Text/Template.php';

$mock = PHPUnit_Framework_MockObject_Generator::generate(
  'Foo',
  array(),
  'MockFoo',
  TRUE,
  TRUE
);

print $mock['code'];
?>
--EXPECTF--
class Foo
{
}

class MockFoo extends Foo implements PHPUnit_Framework_MockObject_MockObject
{
    private static $__phpunit_staticInvocationMocker;
    private $__phpunit_invocationMocker;

    public function __clone()
    {
        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
    }

    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return $this->__phpunit_getInvocationMocker()->expects($matcher);
    }

    public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return self::__phpunit_getStaticInvocationMocker()->expects($matcher);
    }

    public function __phpunit_getInvocationMocker()
    {
        if ($this->__phpunit_invocationMocker === NULL) {
            $this->__phpunit_invocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return $this->__phpunit_invocationMocker;
    }

    public static function __phpunit_getStaticInvocationMocker()
    {
        if (self::$__phpunit_staticInvocationMocker === NULL) {
            self::$__phpunit_staticInvocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return self::$__phpunit_staticInvocationMocker;
    }

    public function __phpunit_hasMatchers()
    {
        return self::__phpunit_getStaticInvocationMocker()->hasMatchers() ||
               $this->__phpunit_getInvocationMocker()->hasMatchers();
    }

    public function __phpunit_verify()
    {
        self::__phpunit_getStaticInvocationMocker()->verify();
        $this->__phpunit_getInvocationMocker()->verify();
    }

    public function __phpunit_cleanup()
    {
        self::$__phpunit_staticInvocationMocker = NULL;
        $this->__phpunit_invocationMocker       = NULL;
    }
}
--TEST--
PHPUnit_Framework_MockObject_Generator::generate('NS\Foo', array(), 'MockFoo', TRUE)
--FILE--
<?php
namespace NS;

interface IFoo
{
    public function __construct($bar);
}

class Foo implements IFoo
{
    public function __construct($bar)
    {
    }
}

require_once 'PHPUnit/Autoload.php';
require_once 'Text/Template.php';

$mock = \PHPUnit_Framework_MockObject_Generator::generate(
  'NS\Foo',
  array(),
  'MockFoo',
  TRUE
);

print $mock['code'];
?>
--EXPECTF--
class MockFoo extends NS\Foo implements PHPUnit_Framework_MockObject_MockObject
{
    private static $__phpunit_staticInvocationMocker;
    private $__phpunit_invocationMocker;

    public function __clone()
    {
        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
    }

    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return $this->__phpunit_getInvocationMocker()->expects($matcher);
    }

    public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return self::__phpunit_getStaticInvocationMocker()->expects($matcher);
    }

    public function __phpunit_getInvocationMocker()
    {
        if ($this->__phpunit_invocationMocker === NULL) {
            $this->__phpunit_invocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return $this->__phpunit_invocationMocker;
    }

    public static function __phpunit_getStaticInvocationMocker()
    {
        if (self::$__phpunit_staticInvocationMocker === NULL) {
            self::$__phpunit_staticInvocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return self::$__phpunit_staticInvocationMocker;
    }

    public function __phpunit_hasMatchers()
    {
        return self::__phpunit_getStaticInvocationMocker()->hasMatchers() ||
               $this->__phpunit_getInvocationMocker()->hasMatchers();
    }

    public function __phpunit_verify()
    {
        self::__phpunit_getStaticInvocationMocker()->verify();
        $this->__phpunit_getInvocationMocker()->verify();
    }

    public function __phpunit_cleanup()
    {
        self::$__phpunit_staticInvocationMocker = NULL;
        $this->__phpunit_invocationMocker       = NULL;
    }
}

--TEST--
PHPUnit_Framework_MockObject_Generator::generate('NS\Foo', array('bar'), 'MockFoo', TRUE, TRUE)
--FILE--
<?php
namespace NS;

class Foo
{
    public function bar(Foo $foo)
    {
    }

    public function baz(Foo $foo)
    {
    }
}

require_once 'PHPUnit/Autoload.php';
require_once 'Text/Template.php';

$mock = \PHPUnit_Framework_MockObject_Generator::generate(
  'NS\Foo',
  array('bar'),
  'MockFoo',
  TRUE,
  TRUE
);

print $mock['code'];
?>
--EXPECTF--
class MockFoo extends NS\Foo implements PHPUnit_Framework_MockObject_MockObject
{
    private static $__phpunit_staticInvocationMocker;
    private $__phpunit_invocationMocker;

    public function __clone()
    {
        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
    }

    public function bar(NS\Foo $foo)
    {
        $arguments = array($foo);
        $count     = func_num_args();

        if ($count > 1) {
            $_arguments = func_get_args();

            for ($i = 1; $i < $count; $i++) {
                $arguments[] = $_arguments[$i];
            }
        }

        $result = $this->__phpunit_getInvocationMocker()->invoke(
          new PHPUnit_Framework_MockObject_Invocation_Object(
            'NS\Foo', 'bar', $arguments, $this, TRUE
          )
        );

        return $result;
    }

    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return $this->__phpunit_getInvocationMocker()->expects($matcher);
    }

    public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return self::__phpunit_getStaticInvocationMocker()->expects($matcher);
    }

    public function __phpunit_getInvocationMocker()
    {
        if ($this->__phpunit_invocationMocker === NULL) {
            $this->__phpunit_invocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return $this->__phpunit_invocationMocker;
    }

    public static function __phpunit_getStaticInvocationMocker()
    {
        if (self::$__phpunit_staticInvocationMocker === NULL) {
            self::$__phpunit_staticInvocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return self::$__phpunit_staticInvocationMocker;
    }

    public function __phpunit_hasMatchers()
    {
        return self::__phpunit_getStaticInvocationMocker()->hasMatchers() ||
               $this->__phpunit_getInvocationMocker()->hasMatchers();
    }

    public function __phpunit_verify()
    {
        self::__phpunit_getStaticInvocationMocker()->verify();
        $this->__phpunit_getInvocationMocker()->verify();
    }

    public function __phpunit_cleanup()
    {
        self::$__phpunit_staticInvocationMocker = NULL;
        $this->__phpunit_invocationMocker       = NULL;
    }
}
--TEST--
PHPUnit_Framework_MockObject_Generator::generate('Foo', array(), 'MockFoo', TRUE, TRUE, TRUE)
--FILE--
<?php
class Foo
{
    public static function bar(Foo $foo)
    {
    }

    public static function baz(Foo $foo)
    {
    }
}

require_once 'PHPUnit/Autoload.php';
require_once 'Text/Template.php';

$mock = PHPUnit_Framework_MockObject_Generator::generate(
  'Foo',
  array(),
  'MockFoo',
  TRUE,
  TRUE,
  TRUE
);

print $mock['code'];
?>
--EXPECTF--
class MockFoo extends Foo implements PHPUnit_Framework_MockObject_MockObject
{
    private static $__phpunit_staticInvocationMocker;
    private $__phpunit_invocationMocker;

    public function __clone()
    {
        $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
    }

    public static function bar(Foo $foo)
    {
        $arguments = array($foo);
        $count     = func_num_args();

        if ($count > 1) {
            $_arguments = func_get_args();

            for ($i = 1; $i < $count; $i++) {
                $arguments[] = $_arguments[$i];
            }
        }

        $result = self::__phpunit_getStaticInvocationMocker()->invoke(
          new PHPUnit_Framework_MockObject_Invocation_Static(
            'Foo', 'bar', $arguments, TRUE
          )
        );

        return $result;
    }

    public static function baz(Foo $foo)
    {
        $arguments = array($foo);
        $count     = func_num_args();

        if ($count > 1) {
            $_arguments = func_get_args();

            for ($i = 1; $i < $count; $i++) {
                $arguments[] = $_arguments[$i];
            }
        }

        $result = self::__phpunit_getStaticInvocationMocker()->invoke(
          new PHPUnit_Framework_MockObject_Invocation_Static(
            'Foo', 'baz', $arguments, TRUE
          )
        );

        return $result;
    }

    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return $this->__phpunit_getInvocationMocker()->expects($matcher);
    }

    public static function staticExpects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return self::__phpunit_getStaticInvocationMocker()->expects($matcher);
    }

    public function __phpunit_getInvocationMocker()
    {
        if ($this->__phpunit_invocationMocker === NULL) {
            $this->__phpunit_invocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return $this->__phpunit_invocationMocker;
    }

    public static function __phpunit_getStaticInvocationMocker()
    {
        if (self::$__phpunit_staticInvocationMocker === NULL) {
            self::$__phpunit_staticInvocationMocker = new PHPUnit_Framework_MockObject_InvocationMocker;
        }

        return self::$__phpunit_staticInvocationMocker;
    }

    public function __phpunit_hasMatchers()
    {
        return self::__phpunit_getStaticInvocationMocker()->hasMatchers() ||
               $this->__phpunit_getInvocationMocker()->hasMatchers();
    }

    public function __phpunit_verify()
    {
        self::__phpunit_getStaticInvocationMocker()->verify();
        $this->__phpunit_getInvocationMocker()->verify();
    }

    public function __phpunit_cleanup()
    {
        self::$__phpunit_staticInvocationMocker = NULL;
        $this->__phpunit_invocationMocker       = NULL;
    }
}
<?php
class MethodCallback
{
    public static function staticCallback()
    {
        $args = func_get_args();

        if ($args == array('foo', 'bar')) {
            return 'pass';
        }
    }

    public function nonStaticCallback()
    {
        $args = func_get_args();

        if ($args == array('foo', 'bar')) {
            return 'pass';
        }
    }
}
<?php
class SomeClass
{
    public function doSomething($a, $b)
    {
        return NULL;
    }

    public function doSomethingElse($c)
    {
        return NULL;
    }
}
<?php
class Mockable
{
    public $constructorArgs;
    public $cloned;

    public function __construct($arg1 = NULL, $arg2 = NULL)
    {
        $this->constructorArgs = array($arg1, $arg2);
    }

    public function mockableMethod()
    {
        // something different from NULL
        return TRUE;
    }

    public function anotherMockableMethod()
    {
        // something different from NULL
        return TRUE;
    }

    public function __clone()
    {
        $this->cloned = TRUE;
    }
}
<?php
abstract class AbstractMockTestClass
{
    abstract public function doSomething();
}
<?php
class MethodCallbackByReference
{
    public function bar($a, &$b, $c) {
        Legacy::bar($a, $b, $c);
    }

    public function callback($a, &$b, $c) {
        $b = 1;
    }
}
<?php
function functionCallback()
{
    $args = func_get_args();

    if ($args == array('foo', 'bar')) {
        return 'pass';
    }
}
<?php
class PartialMockTestClass
{
    public $constructorCalled = FALSE;

    public function __construct()
    {
        $this->constructorCalled = TRUE;
    }

    public function doSomething()
    {
    }

    public function doAnotherThing()
    {
    }
}
<?php
interface AnInterface
{
    public function doSomething();
}
<?php
class StaticMockTestClass
{
    public static function doSomething()
    {
    }

    public static function doSomethingElse()
    {
        return static::doSomething();
    }
}
<?xml version="1.0"?>

<!-- WSDL description of the Google Web APIs.
     The Google Web APIs are in beta release. All interfaces are subject to
     change as we refine and extend our APIs. Please see the terms of use
     for more information. -->

<!-- Revision 2002-08-16 -->

<definitions name="GoogleSearch"
             targetNamespace="urn:GoogleSearch"
             xmlns:typens="urn:GoogleSearch"
             xmlns:xsd="http://www.w3.org/2001/XMLSchema"
             xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
             xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
             xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
             xmlns="http://schemas.xmlsoap.org/wsdl/">

  <!-- Types for search - result elements, directory categories -->

  <types>
    <xsd:schema xmlns="http://www.w3.org/2001/XMLSchema"
                targetNamespace="urn:GoogleSearch">

      <xsd:complexType name="GoogleSearchResult">
        <xsd:all>
          <xsd:element name="documentFiltering"           type="xsd:boolean"/>
          <xsd:element name="searchComments"              type="xsd:string"/>
          <xsd:element name="estimatedTotalResultsCount"  type="xsd:int"/>
          <xsd:element name="estimateIsExact"             type="xsd:boolean"/>
          <xsd:element name="resultElements"              type="typens:ResultElementArray"/>
          <xsd:element name="searchQuery"                 type="xsd:string"/>
          <xsd:element name="startIndex"                  type="xsd:int"/>
          <xsd:element name="endIndex"                    type="xsd:int"/>
          <xsd:element name="searchTips"                  type="xsd:string"/>
          <xsd:element name="directoryCategories"         type="typens:DirectoryCategoryArray"/>
          <xsd:element name="searchTime"                  type="xsd:double"/>
        </xsd:all>
      </xsd:complexType>

      <xsd:complexType name="ResultElement">
        <xsd:all>
          <xsd:element name="summary" type="xsd:string"/>
          <xsd:element name="URL" type="xsd:string"/>
          <xsd:element name="snippet" type="xsd:string"/>
          <xsd:element name="title" type="xsd:string"/>
          <xsd:element name="cachedSize" type="xsd:string"/>
          <xsd:element name="relatedInformationPresent" type="xsd:boolean"/>
          <xsd:element name="hostName" type="xsd:string"/>
          <xsd:element name="directoryCategory" type="typens:DirectoryCategory"/>
          <xsd:element name="directoryTitle" type="xsd:string"/>
        </xsd:all>
      </xsd:complexType>

      <xsd:complexType name="ResultElementArray">
        <xsd:complexContent>
          <xsd:restriction base="soapenc:Array">
             <xsd:attribute ref="soapenc:arrayType" wsdl:arrayType="typens:ResultElement[]"/>
          </xsd:restriction>
        </xsd:complexContent>
      </xsd:complexType>

      <xsd:complexType name="DirectoryCategoryArray">
        <xsd:complexContent>
          <xsd:restriction base="soapenc:Array">
             <xsd:attribute ref="soapenc:arrayType" wsdl:arrayType="typens:DirectoryCategory[]"/>
          </xsd:restriction>
        </xsd:complexContent>
      </xsd:complexType>

      <xsd:complexType name="DirectoryCategory">
        <xsd:all>
          <xsd:element name="fullViewableName" type="xsd:string"/>
          <xsd:element name="specialEncoding" type="xsd:string"/>
        </xsd:all>
      </xsd:complexType>

    </xsd:schema>
  </types>

  <!-- Messages for Google Web APIs - cached page, search, spelling. -->

  <message name="doGetCachedPage">
    <part name="key"            type="xsd:string"/>
    <part name="url"            type="xsd:string"/>
  </message>

  <message name="doGetCachedPageResponse">
    <part name="return"         type="xsd:base64Binary"/>
  </message>

  <message name="doSpellingSuggestion">
    <part name="key"            type="xsd:string"/>
    <part name="phrase"         type="xsd:string"/>
  </message>

  <message name="doSpellingSuggestionResponse">
    <part name="return"         type="xsd:string"/>
  </message>

  <!-- note, ie and oe are ignored by server; all traffic is UTF-8. -->

  <message name="doGoogleSearch">
    <part name="key"            type="xsd:string"/>
    <part name="q"              type="xsd:string"/>
    <part name="start"          type="xsd:int"/>
    <part name="maxResults"     type="xsd:int"/>
    <part name="filter"         type="xsd:boolean"/>
    <part name="restrict"       type="xsd:string"/>
    <part name="safeSearch"     type="xsd:boolean"/>
    <part name="lr"             type="xsd:string"/>
    <part name="ie"             type="xsd:string"/>
    <part name="oe"             type="xsd:string"/>
  </message>

  <message name="doGoogleSearchResponse">
    <part name="return"         type="typens:GoogleSearchResult"/>
  </message>

  <!-- Port for Google Web APIs, "GoogleSearch" -->

  <portType name="GoogleSearchPort">

    <operation name="doGetCachedPage">
      <input message="typens:doGetCachedPage"/>
      <output message="typens:doGetCachedPageResponse"/>
    </operation>

    <operation name="doSpellingSuggestion">
      <input message="typens:doSpellingSuggestion"/>
      <output message="typens:doSpellingSuggestionResponse"/>
    </operation>

    <operation name="doGoogleSearch">
      <input message="typens:doGoogleSearch"/>
      <output message="typens:doGoogleSearchResponse"/>
    </operation>

  </portType>


  <!-- Binding for Google Web APIs - RPC, SOAP over HTTP -->

  <binding name="GoogleSearchBinding" type="typens:GoogleSearchPort">
    <soap:binding style="rpc"
                  transport="http://schemas.xmlsoap.org/soap/http"/>

    <operation name="doGetCachedPage">
      <soap:operation soapAction="urn:GoogleSearchAction"/>
      <input>
        <soap:body use="encoded"
                   namespace="urn:GoogleSearch"
                   encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
      </input>
      <output>
        <soap:body use="encoded"
                   namespace="urn:GoogleSearch"
                   encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
      </output>
    </operation>

    <operation name="doSpellingSuggestion">
      <soap:operation soapAction="urn:GoogleSearchAction"/>
      <input>
        <soap:body use="encoded"
                   namespace="urn:GoogleSearch"
                   encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
      </input>
      <output>
        <soap:body use="encoded"
                   namespace="urn:GoogleSearch"
                   encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
      </output>
    </operation>

    <operation name="doGoogleSearch">
      <soap:operation soapAction="urn:GoogleSearchAction"/>
      <input>
        <soap:body use="encoded"
                   namespace="urn:GoogleSearch"
                   encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
      </input>
      <output>
        <soap:body use="encoded"
                   namespace="urn:GoogleSearch"
                   encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
      </output>
    </operation>
  </binding>

  <!-- Endpoint for Google Web APIs -->
  <service name="GoogleSearchService">
    <port name="GoogleSearchPort" binding="typens:GoogleSearchBinding">
      <soap:address location="http://api.google.com/search/beta2"/>
    </port>
  </service>

</definitions>
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://www.phpunit.de/
 * @since      File available since Release 3.0.0
 */

require_once 'PHPUnit/Framework/TestCase.php';

require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'AbstractMockTestClass.php';
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'AnInterface.php';
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'FunctionCallback.php';
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'MethodCallback.php';
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'MethodCallbackByReference.php';
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'PartialMockTestClass.php';
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'SomeClass.php';
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'StaticMockTestClass.php';

/**
 *
 *
 * @package    PHPUnit_MockObject
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @author     Patrick Mueller <elias0@gmx.net>
 * @author     Frank Kleine <mikey@stubbles.net>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://www.phpunit.de/
 * @since      Class available since Release 3.0.0
 */
class Framework_MockObjectTest extends PHPUnit_Framework_TestCase
{
    public function testMockedMethodIsNeverCalled()
    {
        $mock = $this->getMock('AnInterface');
        $mock->expects($this->never())
             ->method('doSomething');
    }

    public function testMockedMethodIsNotCalledWhenExpectsAnyWithParameter()
    {
        $mock = $this->getMock('SomeClass');
        $mock->expects($this->any())
             ->method('doSomethingElse')
             ->with('someArg');
    }

    public function testMockedMethodIsCalledAtLeastOnce()
    {
        $mock = $this->getMock('AnInterface');
        $mock->expects($this->atLeastOnce())
             ->method('doSomething');

        $mock->doSomething();
    }

    public function testMockedMethodIsCalledAtLeastOnce2()
    {
        $mock = $this->getMock('AnInterface');
        $mock->expects($this->atLeastOnce())
             ->method('doSomething');

        $mock->doSomething();
        $mock->doSomething();
    }

    public function testMockedMethodIsCalledOnce()
    {
        $mock = $this->getMock('AnInterface');
        $mock->expects($this->once())
             ->method('doSomething');

        $mock->doSomething();
    }

    public function testMockedMethodIsCalledOnceWithParameter()
    {
        $mock = $this->getMock('SomeClass');
        $mock->expects($this->once())
             ->method('doSomethingElse')
             ->with($this->equalTo('something'));

        $mock->doSomethingElse('something');
    }

    public function testMockedMethodIsCalledExactly()
    {
        $mock = $this->getMock('AnInterface');
        $mock->expects($this->exactly(2))
             ->method('doSomething');

        $mock->doSomething();
        $mock->doSomething();
    }

    public function testStubbedException()
    {
        $mock = $this->getMock('AnInterface');
        $mock->expects($this->any())
             ->method('doSomething')
             ->will($this->throwException(new Exception));

        try {
            $mock->doSomething();
        }

        catch (Exception $e) {
            return;
        }

        $this->fail();
    }

    public function testStubbedReturnValue()
    {
        $mock = $this->getMock('AnInterface');
        $mock->expects($this->any())
             ->method('doSomething')
             ->will($this->returnValue('something'));

        $this->assertEquals('something', $mock->doSomething());
    }

    public function testStubbedReturnValueMap()
    {
        $map = array(
            array('a', 'b', 'c', 'd'),
            array('e', 'f', 'g', 'h')
        );

        $mock = $this->getMock('AnInterface');
        $mock->expects($this->any())
             ->method('doSomething')
             ->will($this->returnValueMap($map));

        $this->assertEquals('d', $mock->doSomething('a', 'b', 'c'));
        $this->assertEquals('h', $mock->doSomething('e', 'f', 'g'));
        $this->assertEquals(NULL, $mock->doSomething('foo', 'bar'));
    }

    public function testFunctionCallback()
    {
        $mock = $this->getMock('SomeClass', array('doSomething'), array(), '', FALSE);
        $mock->expects($this->once())
             ->method('doSomething')
             ->will($this->returnCallback('functionCallback'));

        $this->assertEquals('pass', $mock->doSomething('foo', 'bar'));
    }

    public function testStaticMethodCallback()
    {
        $mock = $this->getMock('SomeClass', array('doSomething'), array(), '', FALSE);
        $mock->expects($this->once())
             ->method('doSomething')
             ->will($this->returnCallback(array('MethodCallback', 'staticCallback')));

        $this->assertEquals('pass', $mock->doSomething('foo', 'bar'));
    }

    public function testPublicMethodCallback()
    {
        $mock = $this->getMock('SomeClass', array('doSomething'), array(), '', FALSE);
        $mock->expects($this->once())
             ->method('doSomething')
             ->will($this->returnCallback(array(new MethodCallback, 'nonStaticCallback')));

        $this->assertEquals('pass', $mock->doSomething('foo', 'bar'));
    }

    public function testMockClassOnlyGeneratedOnce()
    {
        $mock1 = $this->getMock('AnInterface');
        $mock2 = $this->getMock('AnInterface');

        $this->assertEquals(get_class($mock1), get_class($mock2));
    }

    public function testMockClassDifferentForPartialMocks()
    {
        $mock1 = $this->getMock('PartialMockTestClass');
        $mock2 = $this->getMock('PartialMockTestClass', array('doSomething'));
        $mock3 = $this->getMock('PartialMockTestClass', array('doSomething'));
        $mock4 = $this->getMock('PartialMockTestClass', array('doAnotherThing'));
        $mock5 = $this->getMock('PartialMockTestClass', array('doAnotherThing'));

        $this->assertNotEquals(get_class($mock1), get_class($mock2));
        $this->assertNotEquals(get_class($mock1), get_class($mock3));
        $this->assertNotEquals(get_class($mock1), get_class($mock4));
        $this->assertNotEquals(get_class($mock1), get_class($mock5));
        $this->assertEquals(get_class($mock2), get_class($mock3));
        $this->assertNotEquals(get_class($mock2), get_class($mock4));
        $this->assertNotEquals(get_class($mock2), get_class($mock5));
        $this->assertEquals(get_class($mock4), get_class($mock5));
    }

    public function testMockClassStoreOverrulable()
    {
        $mock1 = $this->getMock('PartialMockTestClass');
        $mock2 = $this->getMock('PartialMockTestClass', array(), array(), 'MyMockClassNameForPartialMockTestClass1');
        $mock3 = $this->getMock('PartialMockTestClass');
        $mock4 = $this->getMock('PartialMockTestClass', array('doSomething'), array(), 'AnotherMockClassNameForPartialMockTestClass');
        $mock5 = $this->getMock('PartialMockTestClass', array(), array(), 'MyMockClassNameForPartialMockTestClass2');

        $this->assertNotEquals(get_class($mock1), get_class($mock2));
        $this->assertEquals(get_class($mock1), get_class($mock3));
        $this->assertNotEquals(get_class($mock1), get_class($mock4));
        $this->assertNotEquals(get_class($mock2), get_class($mock3));
        $this->assertNotEquals(get_class($mock2), get_class($mock4));
        $this->assertNotEquals(get_class($mock2), get_class($mock5));
        $this->assertNotEquals(get_class($mock3), get_class($mock4));
        $this->assertNotEquals(get_class($mock3), get_class($mock5));
        $this->assertNotEquals(get_class($mock4), get_class($mock5));
    }

    /**
     * @covers PHPUnit_Framework_MockObject_Generator::getMock
     */
    public function testGetMockWithFixedClassNameCanProduceTheSameMockTwice()
    {
        $mock = $this->getMockBuilder('StdClass')->setMockClassName('FixedName')->getMock();
        $mock = $this->getMockBuilder('StdClass')->setMockClassName('FixedName')->getMock();
        $this->assertInstanceOf('StdClass', $mock);
    }

    public function testOriginalConstructorSettingConsidered()
    {
        $mock1 = $this->getMock('PartialMockTestClass');
        $mock2 = $this->getMock('PartialMockTestClass', array(), array(), '', FALSE);

        $this->assertTrue($mock1->constructorCalled);
        $this->assertFalse($mock2->constructorCalled);
    }

    public function testOriginalCloneSettingConsidered()
    {
        $mock1 = $this->getMock('PartialMockTestClass');
        $mock2 = $this->getMock('PartialMockTestClass', array(), array(), '', TRUE, FALSE);

        $this->assertNotEquals(get_class($mock1), get_class($mock2));
    }

    public function testStubbedReturnValueForStaticMethod()
    {
        $this->getMockClass(
          'StaticMockTestClass',
          array('doSomething'),
          array(),
          'StaticMockTestClassMock'
        );

        StaticMockTestClassMock::staticExpects($this->any())
          ->method('doSomething')
          ->will($this->returnValue('something'));

        $this->assertEquals(
          'something', StaticMockTestClassMock::doSomething()
        );
    }

    public function testStubbedReturnValueForStaticMethod2()
    {
        $this->getMockClass(
          'StaticMockTestClass',
          array('doSomething'),
          array(),
          'StaticMockTestClassMock2'
        );

        StaticMockTestClassMock2::staticExpects($this->any())
          ->method('doSomething')
          ->will($this->returnValue('something'));

        $this->assertEquals(
          'something', StaticMockTestClassMock2::doSomethingElse()
        );
    }

    public function testGetMockForAbstractClass()
    {
        $mock = $this->getMock('AbstractMockTestClass');
        $mock->expects($this->never())
             ->method('doSomething');
    }

    public function testClonedMockObjectShouldStillEqualTheOriginal()
    {
        $a = $this->getMock('stdClass');
        $b = clone $a;
        $this->assertEquals($a, $b);
    }

    public function testMockObjectsConstructedIndepentantlyShouldBeEqual()
    {
        $a = $this->getMock('stdClass');
        $b = $this->getMock('stdClass');
        $this->assertEquals($a, $b);
    }

    public function testMockObjectsConstructedIndepentantlyShouldNotBeTheSame()
    {
        $a = $this->getMock('stdClass');
        $b = $this->getMock('stdClass');
        $this->assertNotSame($a, $b);
    }

    public function testClonedMockObjectCanBeUsedInPlaceOfOriginalOne()
    {
        $x = $this->getMock('stdClass');
        $y = clone $x;

        $mock = $this->getMock('stdClass', array('foo'));
        $mock->expects($this->once())->method('foo')->with($this->equalTo($x));
        $mock->foo($y);
    }

    public function testClonedMockObjectIsNotIdenticalToOriginalOne()
    {
        $x = $this->getMock('stdClass');
        $y = clone $x;

        $mock = $this->getMock('stdClass', array('foo'));
        $mock->expects($this->once())->method('foo')->with($this->logicalNot($this->identicalTo($x)));
        $mock->foo($y);
    }

    public function testStaticMethodCallWithArgumentCloningEnabled()
    {
        $expectedObject = new StdClass;

        $this->getMockClass(
          'StaticMockTestClass',
          array('doSomething'),
          array(),
          'StaticMockTestClassMock3',
          FALSE,
          TRUE,
          TRUE,
          TRUE
        );

        $actualArguments = array();

        StaticMockTestClassMock3::staticExpects($this->any())
        ->method('doSomething')
        ->will($this->returnCallback(function() use (&$actualArguments) {
            $actualArguments = func_get_args();
        }));

        StaticMockTestClassMock3::doSomething($expectedObject);

        $this->assertEquals(1, count($actualArguments));
        $this->assertNotSame($expectedObject, $actualArguments[0]);
    }

    public function testStaticMethodCallWithArgumentCloningDisabled()
    {
        $expectedObject = new StdClass;

        $this->getMockClass(
          'StaticMockTestClass',
          array('doSomething'),
          array(),
          'StaticMockTestClassMock4',
          FALSE,
          TRUE,
          TRUE,
          FALSE
        );

        $actualArguments = array();

        StaticMockTestClassMock4::staticExpects($this->any())
        ->method('doSomething')
        ->will($this->returnCallback(function() use (&$actualArguments) {
            $actualArguments = func_get_args();
        }));

        StaticMockTestClassMock4::doSomething($expectedObject);

        $this->assertEquals(1, count($actualArguments));
        $this->assertEquals($expectedObject, $actualArguments[0]);
        $this->assertSame($expectedObject, $actualArguments[0]);
    }

    public function testObjectMethodCallWithArgumentCloningEnabled()
    {
        $expectedObject = new StdClass;

        $mock = $this->getMockBuilder('SomeClass')
                     ->setMethods(array('doSomethingElse'))
                     ->enableArgumentCloning()
                     ->getMock();

        $actualArguments = array();

        $mock->expects($this->any())
        ->method('doSomethingElse')
        ->will($this->returnCallback(function() use (&$actualArguments) {
            $actualArguments = func_get_args();
        }));

        $mock->doSomethingElse($expectedObject);

        $this->assertEquals(1, count($actualArguments));
        $this->assertEquals($expectedObject, $actualArguments[0]);
        $this->assertNotSame($expectedObject, $actualArguments[0]);
    }

    public function testObjectMethodCallWithArgumentCloningDisabled()
    {
        $expectedObject = new StdClass;

        $mock = $this->getMockBuilder('SomeClass')
                     ->setMethods(array('doSomethingElse'))
                     ->disableArgumentCloning()
                     ->getMock();

        $actualArguments = array();

        $mock->expects($this->any())
        ->method('doSomethingElse')
        ->will($this->returnCallback(function() use (&$actualArguments) {
            $actualArguments = func_get_args();
        }));

        $mock->doSomethingElse($expectedObject);

        $this->assertEquals(1, count($actualArguments));
        $this->assertSame($expectedObject, $actualArguments[0]);
    }

    public function testArgumentCloningOptionGeneratesUniqueMock()
    {
        $mockWithCloning = $this->getMockBuilder('SomeClass')
                                ->setMethods(array('doSomethingElse'))
                                ->enableArgumentCloning()
                                ->getMock();

        $mockWithoutCloning = $this->getMockBuilder('SomeClass')
                                   ->setMethods(array('doSomethingElse'))
                                   ->disableArgumentCloning()
                                   ->getMock();

        $this->assertNotEquals($mockWithCloning, $mockWithoutCloning);
    }

    public function testVerificationOfMethodNameFailsWithoutParameters()
    {
        $mock = $this->getMock('SomeClass', array('right', 'wrong'), array(), '', TRUE, TRUE, TRUE);
        $mock->expects($this->once())
             ->method('right');

        $mock->wrong();
        try {
            $mock->__phpunit_verify();
            $this->fail('Expected exception');
        } catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertSame(
                "Expectation failed for method name is equal to <string:right> when invoked 1 time(s).\n"
                . 'Method was expected to be called 1 times, actually called 0 times.',
                $e->getMessage()
            );
        }

        $this->resetMockObjects();
    }

    public function testVerificationOfMethodNameFailsWithParameters()
    {
        $mock = $this->getMock('SomeClass', array('right', 'wrong'), array(), '', TRUE, TRUE, TRUE);
        $mock->expects($this->once())
             ->method('right');

        $mock->wrong();
        try {
            $mock->__phpunit_verify();
            $this->fail('Expected exception');
        } catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertSame(
                "Expectation failed for method name is equal to <string:right> when invoked 1 time(s).\n"
                . 'Method was expected to be called 1 times, actually called 0 times.',
                $e->getMessage()
            );
        }

        $this->resetMockObjects();
    }

    public function testVerificationOfNeverFailsWithEmptyParameters()
    {
        $mock = $this->getMock('SomeClass', array('right', 'wrong'), array(), '', TRUE, TRUE, TRUE);
        $mock->expects($this->never())
             ->method('right')
             ->with();

        try {
            $mock->right();
            $this->fail('Expected exception');
        } catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertSame(
                'SomeClass::right() was not expected to be called.',
                $e->getMessage()
            );
        }

        $this->resetMockObjects();
    }

    public function testVerificationOfNeverFailsWithAnyParameters()
    {
        $mock = $this->getMock('SomeClass', array('right', 'wrong'), array(), '', TRUE, TRUE, TRUE);
        $mock->expects($this->never())
             ->method('right')
             ->withAnyParameters();

        try {
            $mock->right();
            $this->fail('Expected exception');
        } catch (PHPUnit_Framework_ExpectationFailedException $e) {
            $this->assertSame(
                'SomeClass::right() was not expected to be called.',
                $e->getMessage()
            );
        }

        $this->resetMockObjects();
    }

    public function testMockArgumentsPassedByReference() {
        $foo = $this->getMockBuilder('MethodCallbackByReference')
                    ->setMethods(array('bar'))
                    ->disableOriginalConstructor()
                    ->disableArgumentCloning()
                    ->getMock();

        $foo->expects($this->any())
            ->method('bar')
            ->will($this->returnCallback(array($foo, 'callback')));

        $a = $b = $c = 0;

        $foo->bar($a, $b, $c);

        $this->assertEquals(1, $b);
    }

    public function testMockArgumentsPassedByReference2() {
        $foo = $this->getMockBuilder('MethodCallbackByReference')
                    ->disableOriginalConstructor()
                    ->disableArgumentCloning()
                    ->getMock();

        $foo->expects($this->any())
            ->method('bar')
            ->will($this->returnCallback(
            function ($a, &$b, $c) {
                $b = 1;
            }
            ));

        $a = $b = $c = 0;

        $foo->bar($a, $b, $c);

        $this->assertEquals(1, $b);
    }

    /**
     * @requires extension soap
     */
    public function testCreateMockFromWsdl()
    {
        $mock = $this->getMockFromWsdl(__DIR__ . '/_files/GoogleSearch.wsdl', 'WsdlMock');
        $this->assertStringStartsWith(
            'Mock_WsdlMock_',
            get_class($mock)
        );
    }

    /**
     * @requires extension soap
     */
    public function testCreateNamespacedMockFromWsdl()
    {
        $mock = $this->getMockFromWsdl(__DIR__ . '/_files/GoogleSearch.wsdl', 'My\\Space\\WsdlMock');
        $this->assertStringStartsWith(
            'Mock_WsdlMock_',
            get_class($mock)
        );
    }

    /**
     * @requires extension soap
     */
    public function testCreateTwoMocksOfOneWsdlFile()
    {
        $mock = $this->getMockFromWsdl(__DIR__ . '/_files/GoogleSearch.wsdl');
        $mock = $this->getMockFromWsdl(__DIR__ . '/_files/GoogleSearch.wsdl');
    }

    private function resetMockObjects()
    {
        $refl = new ReflectionObject($this);
        $refl = $refl->getParentClass();
        $prop = $refl->getProperty('mockObjects');
        $prop->setAccessible(true);
        $prop->setValue($this, array());
    }
}
<?php
/**
 * PHPUnit
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHPUnit_MockObject
 * @author     Giorgio Sironi <piccoloprincipeazzurro@gmail.com>
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */

require_once 'PHPUnit/Framework/TestCase.php';

require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'Mockable.php';

/**
 * @package    PHPUnit_MockObject
 * @author     Giorgio Sironi <piccoloprincipeazzurro@gmail.com>
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2010-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/phpunit-mock-objects
 * @since      File available since Release 1.0.0
 */
class Framework_MockBuilderTest extends PHPUnit_Framework_TestCase
{
    public function testMockBuilderRequiresClassName()
    {
        $spec = $this->getMockBuilder('Mockable');
        $mock = $spec->getMock();
        $this->assertTrue($mock instanceof Mockable);
    }

    public function testByDefaultMocksAllMethods()
    {
        $spec = $this->getMockBuilder('Mockable');
        $mock = $spec->getMock();
        $this->assertNull($mock->mockableMethod());
        $this->assertNull($mock->anotherMockableMethod());
    }

    public function testMethodsToMockCanBeSpecified()
    {
        $spec = $this->getMockBuilder('Mockable');
        $spec->setMethods(array('mockableMethod'));
        $mock = $spec->getMock();
        $this->assertNull($mock->mockableMethod());
        $this->assertTrue($mock->anotherMockableMethod());
    }

    public function testByDefaultDoesNotPassArgumentsToTheConstructor()
    {
        $spec = $this->getMockBuilder('Mockable');
        $mock = $spec->getMock();
        $this->assertEquals(array(NULL, NULL), $mock->constructorArgs);
    }

    public function testMockClassNameCanBeSpecified()
    {
        $spec = $this->getMockBuilder('Mockable');
        $spec->setMockClassName('ACustomClassName');
        $mock = $spec->getMock();
        $this->assertTrue($mock instanceof ACustomClassName);
    }

    public function testConstructorArgumentsCanBeSpecified()
    {
        $spec = $this->getMockBuilder('Mockable');
        $spec->setConstructorArgs($expected = array(23, 42));
        $mock = $spec->getMock();
        $this->assertEquals($expected, $mock->constructorArgs);
    }

    public function testOriginalConstructorCanBeDisabled()
    {
        $spec = $this->getMockBuilder('Mockable');
        $spec->disableOriginalConstructor();
        $mock = $spec->getMock();
        $this->assertNull($mock->constructorArgs);
    }

    public function testByDefaultOriginalCloneIsPreserved()
    {
        $spec = $this->getMockBuilder('Mockable');
        $mock = $spec->getMock();
        $cloned = clone $mock;
        $this->assertTrue($cloned->cloned);
    }

    public function testOriginalCloneCanBeDisabled()
    {
        $spec = $this->getMockBuilder('Mockable');
        $spec->disableOriginalClone();
        $mock = $spec->getMock();
        $mock->cloned = FALSE;
        $cloned = clone $mock;
        $this->assertFalse($cloned->cloned);
    }

    public function testCallingAutoloadCanBeDisabled()
    {
        // it is not clear to me how to test this nor the difference
        // between calling it or not
        $this->markTestIncomplete();
    }

    public function testProvidesAFluentInterface()
    {
        $spec = $this->getMockBuilder('Mockable')
                     ->setMethods(array('mockableMethod'))
                     ->setConstructorArgs(array())
                     ->setMockClassName('DummyClassName')
                     ->disableOriginalConstructor()
                     ->disableOriginalClone()
                     ->disableAutoload();
        $this->assertTrue($spec instanceof PHPUnit_Framework_MockObject_MockBuilder);
    }
}
{
    "name": "phpunit/php-code-coverage",
    "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
    "type": "library",
    "keywords": [
        "coverage",
        "testing",
        "xunit"
    ],
    "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
    "license": "BSD-3-Clause",
    "authors": [
        {
            "name": "Sebastian Bergmann",
            "email": "sb@sebastian-bergmann.de",
            "role": "lead"
        }
    ],
    "support": {
        "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
        "irc": "irc://irc.freenode.net/phpunit"
    },
    "require": {
        "php": ">=5.3.3",
        "phpunit/php-file-iterator": ">=1.3.0@stable",
        "phpunit/php-token-stream": ">=1.1.3@stable",
        "phpunit/php-text-template": ">=1.1.1@stable"
    },
    "require-dev": {
        "phpunit/phpunit": "3.7.*@dev"
    },
    "suggest": {
        "ext-dom": "*",
        "ext-xdebug": ">=2.0.5"
    },
    "autoload": {
        "classmap": [
            "PHP/"
        ]
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.2.x-dev"
        }
    },
    "include-path": [
        ""
    ]
}
<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.4.10" version="2.0"
  xmlns="http://pear.php.net/dtd/package-2.0"
  xmlns:tasks="http://pear.php.net/dtd/tasks-1.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
                      http://pear.php.net/dtd/tasks-1.0.xsd
                      http://pear.php.net/dtd/package-2.0
                      http://pear.php.net/dtd/package-2.0.xsd">
 <name>PHP_CodeCoverage</name>
 <channel>pear.phpunit.de</channel>
 <summary>Library that provides collection, processing, and rendering functionality for PHP code coverage information.</summary>
 <description>Library that provides collection, processing, and rendering functionality for PHP code coverage information.</description>
 <lead>
  <name>Sebastian Bergmann</name>
  <user>sb</user>
  <email>sb@sebastian-bergmann.de</email>
  <active>yes</active>
 </lead>
 <date>2013-09-10</date>
 <version>
  <release>1.2.13</release>
  <api>1.2.11</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license>The BSD 3-Clause License</license>
 <notes>http://github.com/sebastianbergmann/php-code-coverage/</notes>
 <contents>
  <dir name="/">
   <dir name="PHP">
    <dir name="CodeCoverage">
     <dir name="Driver">
      <file baseinstalldir="/" name="Xdebug.php" role="php" />
     </dir>
     <dir name="Report">
      <dir name="HTML">
       <dir name="Renderer">
        <dir name="Template">
         <dir name="css">
          <file baseinstalldir="/" name="bootstrap-responsive.min.css" role="php" />
          <file baseinstalldir="/" name="bootstrap.min.css" role="php" />
          <file baseinstalldir="/" name="style.css" role="php" />
         </dir>
         <dir name="img">
          <file baseinstalldir="/" name="glyphicons-halflings-white.png" role="php" />
          <file baseinstalldir="/" name="glyphicons-halflings.png" role="php" />
         </dir>
         <dir name="js">
          <file baseinstalldir="/" name="bootstrap.min.js" role="php" />
          <file baseinstalldir="/" name="highcharts.js" role="php" />
          <file baseinstalldir="/" name="html5shiv.js" role="php" />
          <file baseinstalldir="/" name="jquery.min.js" role="php" />
         </dir>
         <file baseinstalldir="/" name="coverage_bar.html.dist" role="php" />
         <file baseinstalldir="/" name="dashboard.html.dist" role="php" />
         <file baseinstalldir="/" name="directory.html.dist" role="php" />
         <file baseinstalldir="/" name="directory_item.html.dist" role="php" />
         <file baseinstalldir="/" name="file.html.dist" role="php" />
         <file baseinstalldir="/" name="file_item.html.dist" role="php" />
         <file baseinstalldir="/" name="method_item.html.dist" role="php" />
        </dir>
        <file baseinstalldir="/" name="Dashboard.php" role="php" />
        <file baseinstalldir="/" name="Directory.php" role="php" />
        <file baseinstalldir="/" name="File.php" role="php" />
       </dir>
       <file baseinstalldir="/" name="Renderer.php" role="php" />
      </dir>
      <dir name="Node">
       <file baseinstalldir="/" name="Directory.php" role="php" />
       <file baseinstalldir="/" name="File.php" role="php" />
       <file baseinstalldir="/" name="Iterator.php" role="php" />
      </dir>
      <file baseinstalldir="/" name="Clover.php" role="php" />
      <file baseinstalldir="/" name="Factory.php" role="php" />
      <file baseinstalldir="/" name="HTML.php" role="php" />
      <file baseinstalldir="/" name="Node.php" role="php" />
      <file baseinstalldir="/" name="PHP.php" role="php" />
      <file baseinstalldir="/" name="Text.php" role="php" />
     </dir>
     <dir name="Util">
      <file baseinstalldir="/" name="InvalidArgumentHelper.php" role="php" />
     </dir>
     <file baseinstalldir="/" name="Autoload.php" role="php" />
     <file baseinstalldir="/" name="Driver.php" role="php" />
     <file baseinstalldir="/" name="Exception.php" role="php" />
     <file baseinstalldir="/" name="Filter.php" role="php" />
     <file baseinstalldir="/" name="Util.php" role="php" />
     <file baseinstalldir="/" name="Version.php" role="php" />
    </dir>
    <file baseinstalldir="/" name="CodeCoverage.php" role="php" />
   </dir>
   <file baseinstalldir="/" name="LICENSE" role="doc" />
  </dir>
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.3.3</min>
   </php>
   <pearinstaller>
    <min>1.9.4</min>
   </pearinstaller>
   <package>
    <name>File_Iterator</name>
    <channel>pear.phpunit.de</channel>
    <min>1.3.0</min>
   </package>
   <package>
    <name>PHP_TokenStream</name>
    <channel>pear.phpunit.de</channel>
    <min>1.1.3</min>
   </package>
   <package>
    <name>Text_Template</name>
    <channel>pear.phpunit.de</channel>
    <min>1.1.1</min>
   </package>
  </required>
  <optional>
   <extension>
    <name>dom</name>
   </extension>
   <extension>
    <name>xdebug</name>
    <min>2.0.5</min>
   </extension>
  </optional>
 </dependencies>
 <phprelease />
</package>
<?php
$coverage->stop();

$writer = new PHP_CodeCoverage_Report_HTML;
$writer->process($coverage, '/tmp/coverage');
<?php
require_once 'PHP/CodeCoverage/Autoload.php';

$coverage = new PHP_CodeCoverage;
$filter   = $coverage->filter();

$filter->addFileToBlacklist(__FILE__);
$filter->addFileToBlacklist(dirname(__FILE__) . '/auto_append.php');

$coverage->start($_SERVER['SCRIPT_FILENAME']);
<?xml version="1.0"?>

<ruleset name="Sebastian"
         xmlns="http://pmd.sf.net/ruleset/1.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
         xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
  <description>Sebastian Bergmann's ruleset</description>

  <rule ref="rulesets/codesize.xml/CyclomaticComplexity" />
  <rule ref="rulesets/codesize.xml/NPathComplexity" />
  <rule ref="rulesets/codesize.xml/ExcessiveClassComplexity" />
  <rule ref="rulesets/codesize.xml/ExcessiveClassLength" />
  <rule ref="rulesets/codesize.xml/ExcessiveMethodLength" />
  <rule ref="rulesets/codesize.xml/ExcessiveParameterList" />

  <rule ref="rulesets/design.xml/EvalExpression" />
  <rule ref="rulesets/design.xml/ExitExpression" />
  <rule ref="rulesets/design.xml/GotoStatement" />

  <rule ref="rulesets/naming.xml/ConstructorWithNameAsEnclosingClass" />

  <rule ref="rulesets/unusedcode.xml/UnusedFormalParameter" />
  <rule ref="rulesets/unusedcode.xml/UnusedLocalVariable" />
  <rule ref="rulesets/unusedcode.xml/UnusedPrivateField" />
  <rule ref="rulesets/unusedcode.xml/UnusedPrivateMethod" />
</ruleset>
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true">
  <testsuites>
    <testsuite name="PHP_CodeCoverage">
      <directory suffix="Test.php">../Tests/PHP</directory>
    </testsuite>
  </testsuites>

  <logging>
    <log type="coverage-text" target="php://stdout"/>
  </logging>

  <filter>
    <whitelist addUncoveredFilesFromWhitelist="true">
      <directory suffix=".php">../PHP</directory>
      <exclude>
        <file>../PHP/CodeCoverage/Autoload.php</file>
      </exclude>
    </whitelist>
  </filter>
</phpunit>
<?php
class PHPCS_Sniffs_ControlStructures_ControlSignatureSniff extends PHP_CodeSniffer_Standards_AbstractPatternSniff
{
    public function __construct()
    {
        parent::__construct(true);
    }

    protected function getPatterns()
    {
        return array(
          'do {EOL...} while (...);EOL',
          'while (...) {EOL',
          'for (...) {EOL',
          'if (...) {EOL',
          'foreach (...) {EOL',
          '}EOLelse if (...) {EOL',
          '}EOLelse {EOL',
          'do {EOL',
        );
    }
}
<?php
class PHPCS_Sniffs_Whitespace_ConcatenationSpacingSniff implements PHP_CodeSniffer_Sniff
{
    public function register()
    {
        return array(T_STRING_CONCAT);
    }

    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE ||
            $tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) {

            $phpcsFile->addError(
              'Concatenation operator must be surrounded by whitespace',
              $stackPtr
            );
        }
    }
}
<?xml version="1.0"?>
<ruleset name="Sebastian">
 <description>Sebastian Bergmann's coding standard</description>

 <rule ref="Generic.CodeAnalysis.ForLoopShouldBeWhileLoop"/>
 <rule ref="Generic.CodeAnalysis.ForLoopWithTestFunctionCall"/>
 <rule ref="Generic.CodeAnalysis.JumbledIncrementer"/>
 <rule ref="Generic.CodeAnalysis.UnconditionalIfStatement"/>
 <rule ref="Generic.CodeAnalysis.UnnecessaryFinalModifier"/>
 <rule ref="Generic.CodeAnalysis.UselessOverridingMethod"/>

 <rule ref="Generic.Commenting.Todo"/>

 <rule ref="Generic.ControlStructures.InlineControlStructure"/>

 <rule ref="Generic.Files.LineEndings"/>

 <rule ref="Generic.Formatting.DisallowMultipleStatements"/>
 <rule ref="Generic.Formatting.NoSpaceAfterCast"/>

 <rule ref="Generic.Functions.OpeningFunctionBraceBsdAllman"/>
 <rule ref="PEAR.Functions.ValidDefaultValue"/>

 <rule ref="Generic.NamingConventions.ConstructorName"/>
 <rule ref="Generic.NamingConventions.UpperCaseConstantName"/>
 <rule ref="PEAR.NamingConventions.ValidClassName"/>

 <rule ref="Generic.PHP.DisallowShortOpenTag"/>
 <rule ref="Generic.PHP.NoSilencedErrors"/>
 <rule ref="Generic.PHP.UpperCaseConstant"/>

 <rule ref="Generic.WhiteSpace.DisallowTabIndent"/>
 <rule ref="Generic.WhiteSpace.ScopeIndent"/>
 <rule ref="Squiz.WhiteSpace.SuperfluousWhitespace"/>
</ruleset>
PHP_CodeCoverage

Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

 * Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in
   the documentation and/or other materials provided with the
   distribution.

 * Neither the name of Sebastian Bergmann nor the names of his
   contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
# PHP_CodeCoverage

**PHP_CodeCoverage** is a library that provides collection, processing, and rendering functionality for PHP code coverage information.

## Requirements

* PHP_CodeCoverage 1.2 requires PHP 5.3.3 (or later) but PHP 5.4.7 (or later) is highly recommended.
* [Xdebug](http://xdebug.org/) 2.0.5 (or later) is required but Xdebug 2.2.1 (or later) is highly recommended.

## Installation

You can use the [PEAR Installer](http://pear.php.net/manual/en/guide.users.commandline.cli.php) or [Composer](http://getcomposer.org/) to download and install PHP_CodeCoverage as well as its dependencies

### PEAR Installer

Depending on your OS distribution and/or your PHP environment, you may need to install PEAR or update your existing PEAR installation before you can proceed with the following instructions. `sudo pear upgrade PEAR` usually suffices to upgrade an existing PEAR installation. The [PEAR Manual ](http://pear.php.net/manual/en/installation.getting.php) explains how to perform a fresh installation of PEAR.

The following two commands (which you may have to run as `root`) are all that is required to install PHP_CodeCoverage using the PEAR Installer:

    pear config-set auto_discover 1
    pear install pear.phpunit.de/PHP_CodeCoverage

After the installation you can find the PHP_CodeCoverage source files inside your local PEAR directory; the path is usually `/usr/lib/php/PHP/CodeCoverage`.

### Composer

To add PHP_CodeCoverage as a local, per-project dependency to your project, simply add a dependency on `phpunit/php-code-coverage` to your project's `composer.json` file. Here is a minimal example of a `composer.json` file that just defines a dependency on PHP_CodeCoverage 1.2:

    {
        "require": {
            "phpunit/php-code-coverage": ">=1.2.10,<1.3.0"
        }
    }

## Using the PHP_CodeCoverage API

```php
<?php
require 'PHP/CodeCoverage/Autoload.php';

$coverage = new PHP_CodeCoverage;
$coverage->start('<name of test>');

// ...

$coverage->stop();

$writer = new PHP_CodeCoverage_Report_Clover;
$writer->process($coverage, '/tmp/clover.xml');

$writer = new PHP_CodeCoverage_Report_HTML;
$writer->process($coverage, '/tmp/code-coverage-report');
```<?xml version="1.0" encoding="UTF-8"?>

<project name="PHP_CodeCoverage" default="build">
 <property name="php" value="php"/>
 <property name="phpunit" value="phpunit"/>

 <target name="build"
   depends="prepare,lint,phploc,pdepend,phpmd-ci,phpcs-ci,phpcpd,phpunit,phpcb"/>

 <target name="build-parallel"
   depends="prepare,lint,tools-parallel,phpunit,phpcb"/>

 <target name="tools-parallel"
         description="Run tools in parallel">
  <parallel threadCount="2">
   <sequential>
    <antcall target="pdepend"/>
    <antcall target="phpmd-ci"/>
   </sequential>
   <antcall target="phpcpd"/>
   <antcall target="phpcs-ci"/>
   <antcall target="phploc"/>
  </parallel>
 </target>

 <target name="clean" description="Cleanup build artifacts">
  <delete dir="${basedir}/build/api"/>
  <delete dir="${basedir}/build/code-browser"/>
  <delete dir="${basedir}/build/coverage"/>
  <delete dir="${basedir}/build/logs"/>
  <delete dir="${basedir}/build/pdepend"/>
 </target>

 <target name="prepare" depends="clean,phpab"
         description="Prepare for build">
  <mkdir dir="${basedir}/build/api"/>
  <mkdir dir="${basedir}/build/code-browser"/>
  <mkdir dir="${basedir}/build/coverage"/>
  <mkdir dir="${basedir}/build/logs"/>
  <mkdir dir="${basedir}/build/pdepend"/>
 </target>

 <target name="phpab" description="Generate autoloader scripts">
  <exec executable="phpab">
   <arg value="--output" />
   <arg path="PHP/CodeCoverage/Autoload.php" />
   <arg value="--template" />
   <arg path="PHP/CodeCoverage/Autoload.php.in" />
   <arg value="--indent" />
   <arg value="            " />
   <arg path="PHP" />
  </exec>
 </target>

 <target name="lint">
  <apply executable="${php}" failonerror="true">
   <arg value="-l" />

   <fileset dir="${basedir}/PHP">
    <include name="**/*.php" />
    <modified />
   </fileset>

   <fileset dir="${basedir}/Tests">
    <include name="**/*.php" />
    <modified />
   </fileset>
  </apply>
 </target>

 <target name="phploc" description="Measure project size using PHPLOC">
  <exec executable="phploc">
   <arg value="--log-csv" />
   <arg value="${basedir}/build/logs/phploc.csv" />
   <arg path="${basedir}/PHP" />
  </exec>
 </target>

 <target name="pdepend"
         description="Calculate software metrics using PHP_Depend">
  <exec executable="pdepend">
   <arg value="--jdepend-xml=${basedir}/build/logs/jdepend.xml" />
   <arg value="--jdepend-chart=${basedir}/build/pdepend/dependencies.svg" />
   <arg value="--overview-pyramid=${basedir}/build/pdepend/overview-pyramid.svg" />
   <arg path="${basedir}/PHP" />
  </exec>
 </target>

 <target name="phpmd"
         description="Perform project mess detection using PHPMD">
  <exec executable="phpmd">
   <arg path="${basedir}/PHP" />
   <arg value="text" />
   <arg value="${basedir}/build/phpmd.xml" />
  </exec>
 </target>

 <target name="phpmd-ci"
         description="Perform project mess detection using PHPMD">
  <exec executable="phpmd">
   <arg path="${basedir}/PHP" />
   <arg value="xml" />
   <arg value="${basedir}/build/phpmd.xml" />
   <arg value="--reportfile" />
   <arg value="${basedir}/build/logs/pmd.xml" />
  </exec>
 </target>

 <target name="phpcs"
         description="Find coding standard violations using PHP_CodeSniffer">
  <exec executable="phpcs">
   <arg value="--standard=${basedir}/build/PHPCS" />
   <arg value="--extensions=php" />
   <arg value="--ignore=Autoload.php" />
   <arg path="${basedir}/PHP" />
   <arg path="${basedir}/Tests" />
  </exec>
 </target>

 <target name="phpcs-ci"
         description="Find coding standard violations using PHP_CodeSniffer">
  <exec executable="phpcs" output="/dev/null">
   <arg value="--report=checkstyle" />
   <arg value="--report-file=${basedir}/build/logs/checkstyle.xml" />
   <arg value="--standard=${basedir}/build/PHPCS" />
   <arg value="--extensions=php" />
   <arg value="--ignore=Autoload.php" />
   <arg path="${basedir}/PHP" />
   <arg path="${basedir}/Tests" />
  </exec>
 </target>

 <target name="phpcpd" description="Find duplicate code using PHPCPD">
  <exec executable="phpcpd">
   <arg value="--log-pmd" />
   <arg value="${basedir}/build/logs/pmd-cpd.xml" />
   <arg path="${basedir}/PHP" />
  </exec>
 </target>

 <target name="phpunit" description="Run unit tests with PHPUnit">
  <condition property="phpunit_cmd" value="${php} ${phpunit}" else="${phpunit}">
   <not>
    <equals arg1="${phpunit}" arg2="phpunit" />
   </not>
  </condition>

  <exec executable="${phpunit_cmd}" failonerror="true"/>
 </target>

 <target name="phpcb"
         description="Aggregate tool output with PHP_CodeBrowser">
  <exec executable="phpcb">
   <arg value="--log" />
   <arg path="${basedir}/build/logs" />
   <arg value="--source" />
   <arg path="${basedir}/PHP" />
   <arg value="--output" />
   <arg path="${basedir}/build/code-browser" />
  </exec>
 </target>
</project>
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         syntaxCheck="false"
         bootstrap="PHP/CodeCoverage/Autoload.php">
  <testsuites>
    <testsuite name="php-code-coverage">
      <directory suffix="Test.php">Tests/PHP</directory>
    </testsuite>
  </testsuites>

  <logging>
    <log type="coverage-html" target="build/coverage" title="PHP_CodeCoverage"
         charset="UTF-8" yui="true" highlight="true"
         lowUpperBound="35" highLowerBound="70"/>
    <log type="coverage-clover" target="build/logs/clover.xml"/>
    <log type="junit" target="build/logs/junit.xml" logIncompleteSkipped="false"/>
  </logging>

  <filter>
    <whitelist addUncoveredFilesFromWhitelist="true">
      <directory suffix=".php">PHP</directory>
      <exclude>
        <file>PHP/CodeCoverage/Autoload.php</file>
      </exclude>
    </whitelist>
  </filter>
</phpunit>
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.0.0
 */

/**
 * Interface for code coverage drivers.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.0.0
 */
interface PHP_CodeCoverage_Driver
{
    /**
     * Start collection of code coverage information.
     */
    public function start();

    /**
     * Stop collection of code coverage information.
     *
     * @return array
     */
    public function stop();
}
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.1.0
 */

/**
 * Exception class for PHP_CodeCoverage component.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.1.0
 */
class PHP_CodeCoverage_Exception extends RuntimeException
{
}
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.0.0
 */

/**
 * Utility methods.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.0.0
 */
class PHP_CodeCoverage_Util
{
    /**
     * @var array
     */
    protected static $ignoredLines = array();

    /**
     * @var array
     */
    protected static $ids = array();


    /**
     * Returns the lines of a source file that should be ignored.
     *
     * @param  string  $filename
     * @param  boolean $cacheTokens
     * @return array
     * @throws PHP_CodeCoverage_Exception
     */
    public static function getLinesToBeIgnored($filename, $cacheTokens = TRUE)
    {
        if (!is_string($filename)) {
            throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory(
              1, 'string'
            );
        }

        if (!is_bool($cacheTokens)) {
            throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory(
              2, 'boolean'
            );
        }

        if (!isset(self::$ignoredLines[$filename])) {
            self::$ignoredLines[$filename] = array();
            $ignore                        = FALSE;
            $stop                          = FALSE;
            $lines                         = file($filename);

            foreach ($lines as $index => $line) {
                if (!trim($line)) {
                    self::$ignoredLines[$filename][$index+1] = TRUE;
                }
            }

            if ($cacheTokens) {
                $tokens = PHP_Token_Stream_CachingFactory::get($filename);
            } else {
                $tokens = new PHP_Token_Stream($filename);
            }

            $classes = array_merge($tokens->getClasses(), $tokens->getTraits());
            $tokens  = $tokens->tokens();

            foreach ($tokens as $token) {
                switch (get_class($token)) {
                    case 'PHP_Token_COMMENT':
                    case 'PHP_Token_DOC_COMMENT': {

                        $_token = trim($token);
                        $_line  = trim($lines[$token->getLine() - 1]);

                        if ($_token == '// @codeCoverageIgnore' ||
                            $_token == '//@codeCoverageIgnore') {
                            $ignore = TRUE;
                            $stop   = TRUE;
                        }

                        else if ($_token == '// @codeCoverageIgnoreStart' ||
                                 $_token == '//@codeCoverageIgnoreStart') {
                            $ignore = TRUE;
                        }

                        else if ($_token == '// @codeCoverageIgnoreEnd' ||
                                 $_token == '//@codeCoverageIgnoreEnd') {
                            $stop = TRUE;
                        }

                        // be sure the comment doesn't have some token BEFORE it on the same line...
                        // it would not be safe to ignore the whole line in those cases.
                        if (0 === strpos($_token, $_line)) {
                            $count = substr_count($token, "\n");
                            $line  = $token->getLine();

                            for ($i = $line; $i < $line + $count; $i++) {
                                self::$ignoredLines[$filename][$i] = TRUE;
                            }

                            if ($token instanceof PHP_Token_DOC_COMMENT) {
                                // Workaround for the fact the DOC_COMMENT token
                                // does not include the final \n character in its
                                // text.
                                if (substr(trim($lines[$i-1]), -2) == '*/') {
                                    self::$ignoredLines[$filename][$i] = TRUE;
                                }
                            }
                        }
                    }
                    break;

                    case 'PHP_Token_INTERFACE':
                    case 'PHP_Token_TRAIT':
                    case 'PHP_Token_CLASS':
                    case 'PHP_Token_FUNCTION': {
                        $docblock = $token->getDocblock();

                        if (strpos($docblock, '@codeCoverageIgnore')) {
                            $endLine = $token->getEndLine();

                            for ($i = $token->getLine(); $i <= $endLine; $i++) {
                                self::$ignoredLines[$filename][$i] = TRUE;
                            }
                        }

                        else if ($token instanceof PHP_Token_INTERFACE ||
                                 $token instanceof PHP_Token_TRAIT ||
                                 $token instanceof PHP_Token_CLASS) {
                            if (empty($classes[$token->getName()]['methods'])) {
                                for ($i = $token->getLine();
                                     $i <= $token->getEndLine();
                                     $i++) {
                                    self::$ignoredLines[$filename][$i] = TRUE;
                                }
                            } else {
                                $firstMethod = array_shift(
                                  $classes[$token->getName()]['methods']
                                );

                                do {
                                    $lastMethod = array_pop(
                                      $classes[$token->getName()]['methods']
                                    );
                                } while ($lastMethod !== NULL && substr($lastMethod['signature'], 0, 18) == 'anonymous function');

                                if ($lastMethod === NULL) {
                                    $lastMethod = $firstMethod;
                                }

                                for ($i = $token->getLine();
                                     $i < $firstMethod['startLine'];
                                     $i++) {
                                    self::$ignoredLines[$filename][$i] = TRUE;
                                }

                                for ($i = $token->getEndLine();
                                     $i > $lastMethod['endLine'];
                                     $i--) {
                                    self::$ignoredLines[$filename][$i] = TRUE;
                                }
                            }
                        }
                    }
                    break;

                    case 'PHP_Token_NAMESPACE': {
                        self::$ignoredLines[$filename][$token->getEndLine()] = TRUE;
                    } // Intentional fallthrough
                    case 'PHP_Token_OPEN_TAG':
                    case 'PHP_Token_CLOSE_TAG':
                    case 'PHP_Token_USE': {
                        self::$ignoredLines[$filename][$token->getLine()] = TRUE;
                    }
                    break;
                }

                if ($ignore) {
                    self::$ignoredLines[$filename][$token->getLine()] = TRUE;

                    if ($stop) {
                        $ignore = FALSE;
                        $stop   = FALSE;
                    }
                }
            }
        }

        return self::$ignoredLines[$filename];
    }

    /**
     * @param  float $a
     * @param  float $b
     * @return float ($a / $b) * 100
     */
    public static function percent($a, $b, $asString = FALSE, $fixedWidth = FALSE)
    {
        if ($asString && $b == 0) {
            return '';
        }

        if ($b > 0) {
            $percent = ($a / $b) * 100;
        } else {
            $percent = 100;
        }

        if ($asString) {
            if ($fixedWidth) {
                return sprintf('%6.2F%%', $percent);
            }

            return sprintf('%01.2F%%', $percent);
        } else {
            return $percent;
        }
    }
}
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.2.0
 */

/**
 * Factory for PHP_CodeCoverage_Exception objects that are used to describe
 * invalid arguments passed to a function or method.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.2.0
 */
class PHP_CodeCoverage_Util_InvalidArgumentHelper
{
    /**
     * @param integer $argument
     * @param string  $type
     * @param mixed   $value
     */
    public static function factory($argument, $type, $value = NULL)
    {
        $stack = debug_backtrace(FALSE);

        return new PHP_CodeCoverage_Exception(
          sprintf(
            'Argument #%d%sof %s::%s() must be a %s',
            $argument,
            $value !== NULL ? ' (' . $value . ')' : ' ',
            $stack[1]['class'],
            $stack[1]['function'],
            $type
          )
        );
    }
}
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.0.0
 */

/**
 * Filter for blacklisting and whitelisting of code coverage information.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.0.0
 */
class PHP_CodeCoverage_Filter
{
    /**
     * Source files that are blacklisted.
     *
     * @var array
     */
    protected $blacklistedFiles = array();

    /**
     * Source files that are whitelisted.
     *
     * @var array
     */
    protected $whitelistedFiles = array();

    /**
     * @var boolean
     */
    protected $blacklistPrefilled = FALSE;

    /**
     * Adds a directory to the blacklist (recursively).
     *
     * @param string $directory
     * @param string $suffix
     * @param string $prefix
     */
    public function addDirectoryToBlacklist($directory, $suffix = '.php', $prefix = '')
    {
        $facade = new File_Iterator_Facade;
        $files  = $facade->getFilesAsArray(
          $directory, $suffix, $prefix
        );

        foreach ($files as $file) {
            $this->addFileToBlacklist($file);
        }
    }

    /**
     * Adds a file to the blacklist.
     *
     * @param string $filename
     */
    public function addFileToBlacklist($filename)
    {
        $this->blacklistedFiles[realpath($filename)] = TRUE;
    }

    /**
     * Adds files to the blacklist.
     *
     * @param array $files
     */
    public function addFilesToBlacklist(array $files)
    {
        foreach ($files as $file) {
            $this->addFileToBlacklist($file);
        }
    }

    /**
     * Removes a directory from the blacklist (recursively).
     *
     * @param string $directory
     * @param string $suffix
     * @param string $prefix
     */
    public function removeDirectoryFromBlacklist($directory, $suffix = '.php', $prefix = '')
    {
        $facade = new File_Iterator_Facade;
        $files  = $facade->getFilesAsArray(
          $directory, $suffix, $prefix
        );

        foreach ($files as $file) {
            $this->removeFileFromBlacklist($file);
        }
    }

    /**
     * Removes a file from the blacklist.
     *
     * @param string $filename
     */
    public function removeFileFromBlacklist($filename)
    {
        $filename = realpath($filename);

        if (isset($this->blacklistedFiles[$filename])) {
            unset($this->blacklistedFiles[$filename]);
        }
    }

    /**
     * Adds a directory to the whitelist (recursively).
     *
     * @param string $directory
     * @param string $suffix
     * @param string $prefix
     */
    public function addDirectoryToWhitelist($directory, $suffix = '.php', $prefix = '')
    {
        $facade = new File_Iterator_Facade;
        $files  = $facade->getFilesAsArray(
          $directory, $suffix, $prefix
        );

        foreach ($files as $file) {
            $this->addFileToWhitelist($file);
        }
    }

    /**
     * Adds a file to the whitelist.
     *
     * @param string $filename
     */
    public function addFileToWhitelist($filename)
    {
        $this->whitelistedFiles[realpath($filename)] = TRUE;
    }

    /**
     * Adds files to the whitelist.
     *
     * @param array $files
     */
    public function addFilesToWhitelist(array $files)
    {
        foreach ($files as $file) {
            $this->addFileToWhitelist($file);
        }
    }

    /**
     * Removes a directory from the whitelist (recursively).
     *
     * @param string $directory
     * @param string $suffix
     * @param string $prefix
     */
    public function removeDirectoryFromWhitelist($directory, $suffix = '.php', $prefix = '')
    {
        $facade = new File_Iterator_Facade;
        $files  = $facade->getFilesAsArray(
          $directory, $suffix, $prefix
        );

        foreach ($files as $file) {
            $this->removeFileFromWhitelist($file);
        }
    }

    /**
     * Removes a file from the whitelist.
     *
     * @param string $filename
     */
    public function removeFileFromWhitelist($filename)
    {
        $filename = realpath($filename);

        if (isset($this->whitelistedFiles[$filename])) {
            unset($this->whitelistedFiles[$filename]);
        }
    }

    /**
     * Checks whether a filename is a real filename.
     *
     * @param string $filename
     */
    public function isFile($filename)
    {
        if ($filename == '-' ||
            strpos($filename, 'eval()\'d code') !== FALSE ||
            strpos($filename, 'runtime-created function') !== FALSE ||
            strpos($filename, 'runkit created function') !== FALSE ||
            strpos($filename, 'assert code') !== FALSE ||
            strpos($filename, 'regexp code') !== FALSE) {
            return FALSE;
        }

        return TRUE;
    }

    /**
     * Checks whether or not a file is filtered.
     *
     * When the whitelist is empty (default), blacklisting is used.
     * When the whitelist is not empty, whitelisting is used.
     *
     * @param  string  $filename
     * @param  boolean $ignoreWhitelist
     * @return boolean
     * @throws PHP_CodeCoverage_Exception
     */
    public function isFiltered($filename)
    {
        $filename = realpath($filename);

        if (!empty($this->whitelistedFiles)) {
            return !isset($this->whitelistedFiles[$filename]);
        }

        if (!$this->blacklistPrefilled) {
            $this->prefillBlacklist();
        }

        return isset($this->blacklistedFiles[$filename]);
    }

    /**
     * Returns the list of blacklisted files.
     *
     * @return array
     */
    public function getBlacklist()
    {
        return array_keys($this->blacklistedFiles);
    }

    /**
     * Returns the list of whitelisted files.
     *
     * @return array
     */
    public function getWhitelist()
    {
        return array_keys($this->whitelistedFiles);
    }

    /**
     * Returns whether this filter has a whitelist.
     *
     * @return boolean
     * @since  Method available since Release 1.1.0
     */
    public function hasWhitelist()
    {
        return !empty($this->whitelistedFiles);
    }

    /**
     * @since Method available since Release 1.2.3
     */
    protected function prefillBlacklist()
    {
        if (defined('__PHPUNIT_PHAR__')) {
            $this->addFileToBlacklist(__PHPUNIT_PHAR__);
        }

        $this->addDirectoryContainingClassToBlacklist('File_Iterator');
        $this->addDirectoryContainingClassToBlacklist('PHP_CodeCoverage');
        $this->addDirectoryContainingClassToBlacklist('PHP_Invoker');
        $this->addDirectoryContainingClassToBlacklist('PHP_Timer');
        $this->addDirectoryContainingClassToBlacklist('PHP_Token');
        $this->addDirectoryContainingClassToBlacklist('PHPUnit_Framework_TestCase', 2);
        $this->addDirectoryContainingClassToBlacklist('PHPUnit_Extensions_Database_TestCase', 2);
        $this->addDirectoryContainingClassToBlacklist('PHPUnit_Framework_MockObject_Generator', 2);
        $this->addDirectoryContainingClassToBlacklist('PHPUnit_Extensions_SeleniumTestCase', 2);
        $this->addDirectoryContainingClassToBlacklist('PHPUnit_Extensions_Story_TestCase', 2);
        $this->addDirectoryContainingClassToBlacklist('Text_Template');
        $this->addDirectoryContainingClassToBlacklist('Symfony\Component\Yaml\Yaml');

        $this->blacklistPrefilled = TRUE;
    }

    /**
     * @param string  $className
     * @param integer $parent
     * @since Method available since Release 1.2.3
     */
    protected function addDirectoryContainingClassToBlacklist($className, $parent = 1)
    {
        if (!class_exists($className)) {
            return;
        }

        $reflector = new ReflectionClass($className);
        $directory = $reflector->getFileName();

        for ($i = 0; $i < $parent; $i++) {
            $directory = dirname($directory);
        }

        $this->addDirectoryToBlacklist($directory);
    }
}
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.2.1
 */

/**
 * 
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.2.1
 */
class PHP_CodeCoverage_Version
{
    const VERSION = '1.2.13';
    protected static $version;

    /**
     * Returns the version of PHP_CodeCoverage.
     *
     * @return string
     */
    public static function id()
    {
        if (self::$version === NULL) {
            self::$version = self::VERSION;

            if (is_dir(dirname(dirname(__DIR__)) . '/.git')) {
                $dir = getcwd();
                chdir(__DIR__);
                $version = exec('git describe --tags');
                chdir($dir);

                if ($version) {
                    if (count(explode('.', self::VERSION)) == 3) {
                        self::$version = $version;
                    } else {
                        $version = explode('-', $version);

                        self::$version = self::VERSION . '-' . $version[2];
                    }
                }
            }
        }

        return self::$version;
    }
}
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.1.0
 */

/**
 * Base class for nodes in the code coverage information tree.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.1.0
 */
abstract class PHP_CodeCoverage_Report_Node implements Countable
{
    /**
     * @var string
     */
    protected $name;

    /**
     * @var string
     */
    protected $path;

    /**
     * @var array
     */
    protected $pathArray;

    /**
     * @var PHP_CodeCoverage_Report_Node
     */
    protected $parent;

    /**
     * @var string
     */
    protected $id;

    /**
     * Constructor.
     *
     * @param string                       $name
     * @param PHP_CodeCoverage_Report_Node $parent
     */
    public function __construct($name, PHP_CodeCoverage_Report_Node $parent = NULL)
    {
        if (substr($name, -1) == '/') {
            $name = substr($name, 0, -1);
        }

        $this->name   = $name;
        $this->parent = $parent;
    }

    /**
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @return string
     */
    public function getId()
    {
        if ($this->id === NULL) {
            $parent = $this->getParent();

            if ($parent === NULL) {
                $this->id = 'index';
            } else {
                $parentId = $parent->getId();

                if ($parentId == 'index') {
                    $this->id = str_replace(':', '_', $this->name);
                } else {
                    $this->id = $parentId . '_' . $this->name;
                }
            }
        }

        return $this->id;
    }

    /**
     * @return string
     */
    public function getPath()
    {
        if ($this->path === NULL) {
            if ($this->parent === NULL) {
                $this->path = $this->name;
            } else {
                $this->path = $this->parent->getPath() . '/' . $this->name;
            }
        }

        return $this->path;
    }

    /**
     * @return array
     */
    public function getPathAsArray()
    {
        if ($this->pathArray === NULL) {
            if ($this->parent === NULL) {
                $this->pathArray = array();
            } else {
                $this->pathArray = $this->parent->getPathAsArray();
            }

            $this->pathArray[] = $this;
        }

        return $this->pathArray;
    }

    /**
     * @return PHP_CodeCoverage_Report_Node
     */
    public function getParent()
    {
        return $this->parent;
    }

    /**
     * Returns the percentage of classes that has been tested.
     *
     * @param  boolean $asString
     * @return integer
     */
    public function getTestedClassesPercent($asString = TRUE)
    {
        return PHP_CodeCoverage_Util::percent(
          $this->getNumTestedClasses(),
          $this->getNumClasses(),
          $asString
        );
    }

    /**
     * Returns the percentage of traits that has been tested.
     *
     * @param  boolean $asString
     * @return integer
     */
    public function getTestedTraitsPercent($asString = TRUE)
    {
        return PHP_CodeCoverage_Util::percent(
          $this->getNumTestedTraits(),
          $this->getNumTraits(),
          $asString
        );
    }

    /**
     * Returns the percentage of traits that has been tested.
     *
     * @param  boolean $asString
     * @return integer
     * @since  Method available since Release 1.2.0
     */
    public function getTestedClassesAndTraitsPercent($asString = TRUE)
    {
        return PHP_CodeCoverage_Util::percent(
          $this->getNumTestedClassesAndTraits(),
          $this->getNumClassesAndTraits(),
          $asString
        );
    }

    /**
     * Returns the percentage of methods that has been tested.
     *
     * @param  boolean $asString
     * @return integer
     */
    public function getTestedMethodsPercent($asString = TRUE)
    {
        return PHP_CodeCoverage_Util::percent(
          $this->getNumTestedMethods(),
          $this->getNumMethods(),
          $asString
        );
    }

    /**
     * Returns the percentage of executed lines.
     *
     * @param  boolean $asString
     * @return integer
     */
    public function getLineExecutedPercent($asString = TRUE)
    {
        return PHP_CodeCoverage_Util::percent(
          $this->getNumExecutedLines(),
          $this->getNumExecutableLines(),
          $asString
        );
    }

    /**
     * Returns the number of classes and traits.
     *
     * @return integer
     * @since  Method available since Release 1.2.0
     */
    public function getNumClassesAndTraits()
    {
        return $this->getNumClasses() + $this->getNumTraits();
    }

    /**
     * Returns the number of tested classes and traits.
     *
     * @return integer
     * @since  Method available since Release 1.2.0
     */
    public function getNumTestedClassesAndTraits()
    {
        return $this->getNumTestedClasses() + $this->getNumTestedTraits();
    }

    /**
     * Returns the classes and traits of this node.
     *
     * @return array
     * @since  Method available since Release 1.2.0
     */
    public function getClassesAndTraits()
    {
        return array_merge($this->getClasses(), $this->getTraits());
    }

    /**
     * Returns the classes of this node.
     *
     * @return array
     */
    abstract public function getClasses();

    /**
     * Returns the traits of this node.
     *
     * @return array
     */
    abstract public function getTraits();

    /**
     * Returns the functions of this node.
     *
     * @return array
     */
    abstract public function getFunctions();

    /**
     * Returns the LOC/CLOC/NCLOC of this node.
     *
     * @return array
     */
    abstract public function getLinesOfCode();

    /**
     * Returns the number of executable lines.
     *
     * @return integer
     */
    abstract public function getNumExecutableLines();

    /**
     * Returns the number of executed lines.
     *
     * @return integer
     */
    abstract public function getNumExecutedLines();

    /**
     * Returns the number of classes.
     *
     * @return integer
     */
    abstract public function getNumClasses();

    /**
     * Returns the number of tested classes.
     *
     * @return integer
     */
    abstract public function getNumTestedClasses();

    /**
     * Returns the number of traits.
     *
     * @return integer
     */
    abstract public function getNumTraits();

    /**
     * Returns the number of tested traits.
     *
     * @return integer
     */
    abstract public function getNumTestedTraits();

    /**
     * Returns the number of methods.
     *
     * @return integer
     */
    abstract public function getNumMethods();

    /**
     * Returns the number of tested methods.
     *
     * @return integer
     */
    abstract public function getNumTestedMethods();

    /**
     * Returns the number of functions.
     *
     * @return integer
     */
    abstract public function getNumFunctions();

    /**
     * Returns the number of tested functions.
     *
     * @return integer
     */
    abstract public function getNumTestedFunctions();
}
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.0.0
 */

/**
 * Generates an HTML report from an PHP_CodeCoverage object.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.0.0
 */
class PHP_CodeCoverage_Report_HTML
{
    /**
     * @var string
     */
    protected $templatePath;

    /**
     * @var string
     */
    protected $charset;

    /**
     * @var string
     */
    protected $generator;

    /**
     * @var integer
     */
    protected $lowUpperBound;

    /**
     * @var integer
     */
    protected $highLowerBound;

    /**
     * @var boolean
     */
    protected $highlight;

    /**
     * Constructor.
     *
     * @param array $options
     */
    public function __construct($charset = 'UTF-8', $highlight = FALSE, $lowUpperBound = 35, $highLowerBound = 70, $generator = '')
    {
        $this->charset        = $charset;
        $this->generator      = $generator;
        $this->highLowerBound = $highLowerBound;
        $this->highlight      = $highlight;
        $this->lowUpperBound  = $lowUpperBound;

        $this->templatePath = sprintf(
          '%s%sHTML%sRenderer%sTemplate%s',

          dirname(__FILE__),
          DIRECTORY_SEPARATOR,
          DIRECTORY_SEPARATOR,
          DIRECTORY_SEPARATOR,
          DIRECTORY_SEPARATOR
        );
    }

    /**
     * @param PHP_CodeCoverage $coverage
     * @param string           $target
     */
    public function process(PHP_CodeCoverage $coverage, $target)
    {
        $target = $this->getDirectory($target);
        $report = $coverage->getReport();
        unset($coverage);

        if (!isset($_SERVER['REQUEST_TIME'])) {
            $_SERVER['REQUEST_TIME'] = time();
        }

        $date = date('D M j G:i:s T Y', $_SERVER['REQUEST_TIME']);

        $dashboard = new PHP_CodeCoverage_Report_HTML_Renderer_Dashboard(
          $this->templatePath,
          $this->charset,
          $this->generator,
          $date,
          $this->lowUpperBound,
          $this->highLowerBound
        );

        $directory = new PHP_CodeCoverage_Report_HTML_Renderer_Directory(
          $this->templatePath,
          $this->charset,
          $this->generator,
          $date,
          $this->lowUpperBound,
          $this->highLowerBound
        );

        $file = new PHP_CodeCoverage_Report_HTML_Renderer_File(
          $this->templatePath,
          $this->charset,
          $this->generator,
          $date,
          $this->lowUpperBound,
          $this->highLowerBound,
          $this->highlight
        );

        $dashboard->render($report, $target . 'index.dashboard.html');
        $directory->render($report, $target . 'index.html');

        foreach ($report as $node) {
            $id = $node->getId();

            if ($node instanceof PHP_CodeCoverage_Report_Node_Directory) {
                $dashboard->render($node, $target . $id . '.dashboard.html');
                $directory->render($node, $target . $id . '.html');
            } else {
                $file->render($node, $target . $id . '.html');
            }
        }

        $this->copyFiles($target);
    }

    /**
     * @param string $target
     */
    protected function copyFiles($target)
    {
        $dir = $this->getDirectory($target . 'css');
        copy($this->templatePath . 'css/bootstrap.min.css', $dir . 'bootstrap.min.css');
        copy($this->templatePath . 'css/bootstrap-responsive.min.css', $dir . 'bootstrap-responsive.min.css');
        copy($this->templatePath . 'css/style.css', $dir . 'style.css');

        $dir = $this->getDirectory($target . 'js');
        copy($this->templatePath . 'js/bootstrap.min.js', $dir . 'bootstrap.min.js');
        copy($this->templatePath . 'js/highcharts.js', $dir . 'highcharts.js');
        copy($this->templatePath . 'js/jquery.min.js', $dir . 'jquery.min.js');
        copy($this->templatePath . 'js/html5shiv.js', $dir . 'html5shiv.js');

        $dir = $this->getDirectory($target . 'img');
        copy($this->templatePath . 'img/glyphicons-halflings.png', $dir . 'glyphicons-halflings.png');
        copy($this->templatePath . 'img/glyphicons-halflings-white.png', $dir . 'glyphicons-halflings-white.png');
    }

    /**
     * @param  string $directory
     * @return string
     * @throws PHP_CodeCoverage_Exception
     * @since  Method available since Release 1.2.0
     */
    protected function getDirectory($directory)
    {
        if (substr($directory, -1, 1) != DIRECTORY_SEPARATOR) {
            $directory .= DIRECTORY_SEPARATOR;
        }

        if (is_dir($directory)) {
            return $directory;
        }

        if (@mkdir($directory, 0777, TRUE)) {
            return $directory;
        }

        throw new PHP_CodeCoverage_Exception(
          sprintf(
            'Directory "%s" does not exist.',
            $directory
          )
        );
    }
}
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.1.0
 */

// @codeCoverageIgnoreStart
if (!defined('T_TRAIT')) {
    define('T_TRAIT', 1001);
}

if (!defined('T_INSTEADOF')) {
    define('T_INSTEADOF', 1002);
}

if (!defined('T_CALLABLE')) {
    define('T_CALLABLE', 1003);
}
// @codeCoverageIgnoreEnd

/**
 * Renders a PHP_CodeCoverage_Report_Node_File node.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.1.0
 */
class PHP_CodeCoverage_Report_HTML_Renderer_File extends PHP_CodeCoverage_Report_HTML_Renderer
{
    /**
     * @var boolean
     */
    protected $highlight;

    /**
     * Constructor.
     *
     * @param string  $templatePath
     * @param string  $charset
     * @param string  $generator
     * @param string  $date
     * @param integer $lowUpperBound
     * @param integer $highLowerBound
     * @param boolean $highlight
     */
    public function __construct($templatePath, $charset, $generator, $date, $lowUpperBound, $highLowerBound, $highlight)
    {
        parent::__construct(
          $templatePath,
          $charset,
          $generator,
          $date,
          $lowUpperBound,
          $highLowerBound
        );

        $this->highlight = $highlight;
    }

    /**
     * @param PHP_CodeCoverage_Report_Node_File $node
     * @param string                            $file
     */
    public function render(PHP_CodeCoverage_Report_Node_File $node, $file)
    {
        $template = new Text_Template($this->templatePath . 'file.html');

        $template->setVar(
          array(
            'items' => $this->renderItems($node),
            'lines' => $this->renderSource($node)
          )
        );

        $this->setCommonTemplateVariables($template, $node);

        $template->renderTo($file);
    }

    /**
     * @param  PHP_CodeCoverage_Report_Node_File $node
     * @return string
     */
    protected function renderItems(PHP_CodeCoverage_Report_Node_File $node)
    {
        $template = new Text_Template($this->templatePath . 'file_item.html');

        $methodItemTemplate = new Text_Template(
          $this->templatePath . 'method_item.html'
        );

        $items = $this->renderItemTemplate(
          $template,
          array(
            'name'                         => 'Total',
            'numClasses'                   => $node->getNumClassesAndTraits(),
            'numTestedClasses'             => $node->getNumTestedClassesAndTraits(),
            'numMethods'                   => $node->getNumMethods(),
            'numTestedMethods'             => $node->getNumTestedMethods(),
            'linesExecutedPercent'         => $node->getLineExecutedPercent(FALSE),
            'linesExecutedPercentAsString' => $node->getLineExecutedPercent(),
            'numExecutedLines'             => $node->getNumExecutedLines(),
            'numExecutableLines'           => $node->getNumExecutableLines(),
            'testedMethodsPercent'         => $node->getTestedMethodsPercent(FALSE),
            'testedMethodsPercentAsString' => $node->getTestedMethodsPercent(),
            'testedClassesPercent'         => $node->getTestedClassesAndTraitsPercent(FALSE),
            'testedClassesPercentAsString' => $node->getTestedClassesAndTraitsPercent(),
            'crap'                         => '<abbr title="Change Risk Anti-Patterns (CRAP) Index">CRAP</abbr>'
          )
        );

        $items .= $this->renderFunctionItems(
          $node->getFunctions(), $methodItemTemplate
        );

        $items .= $this->renderTraitOrClassItems(
          $node->getTraits(), $template, $methodItemTemplate
        );

        $items .= $this->renderTraitOrClassItems(
          $node->getClasses(), $template, $methodItemTemplate
        );

        return $items;
    }

    /**
     * @param  array         $items
     * @param  Text_Template $template
     * @return string
     */
    protected function renderTraitOrClassItems(array $items, Text_Template $template, Text_Template $methodItemTemplate)
    {
        if (empty($items)) {
            return '';
        }

        $buffer = '';

        foreach ($items as $name => $item) {
            $numMethods       = count($item['methods']);
            $numTestedMethods = 0;

            foreach ($item['methods'] as $method) {
                if ($method['executedLines'] == $method['executableLines']) {
                    $numTestedMethods++;
                }
            }

            $buffer .= $this->renderItemTemplate(
              $template,
              array(
                'name'                         => $name,
                'numClasses'                   => 1,
                'numTestedClasses'             => $numTestedMethods == $numMethods ? 1 : 0,
                'numMethods'                   => $numMethods,
                'numTestedMethods'             => $numTestedMethods,
                'linesExecutedPercent'         => PHP_CodeCoverage_Util::percent(
                                                    $item['executedLines'],
                                                    $item['executableLines'],
                                                    FALSE
                                                  ),
                'linesExecutedPercentAsString' => PHP_CodeCoverage_Util::percent(
                                                    $item['executedLines'],
                                                    $item['executableLines'],
                                                    TRUE
                                                  ),
                'numExecutedLines'             => $item['executedLines'],
                'numExecutableLines'           => $item['executableLines'],
                'testedMethodsPercent'         => PHP_CodeCoverage_Util::percent(
                                                    $numTestedMethods,
                                                    $numMethods,
                                                    FALSE
                                                  ),
                'testedMethodsPercentAsString' => PHP_CodeCoverage_Util::percent(
                                                    $numTestedMethods,
                                                    $numMethods,
                                                    TRUE
                                                  ),
                'testedClassesPercent'         => PHP_CodeCoverage_Util::percent(
                                                    $numTestedMethods == $numMethods ? 1 : 0,
                                                    1,
                                                    FALSE
                                                  ),
                'testedClassesPercentAsString' => PHP_CodeCoverage_Util::percent(
                                                    $numTestedMethods == $numMethods ? 1 : 0,
                                                    1,
                                                    TRUE
                                                  ),
                'crap'                         => $item['crap']
              )
            );

            foreach ($item['methods'] as $method) {
                $buffer .= $this->renderFunctionOrMethodItem(
                  $methodItemTemplate, $method, '&nbsp;'
                );
            }
        }

        return $buffer;
    }

    /**
     * @param  array         $functions
     * @param  Text_Template $template
     * @return string
     */
    protected function renderFunctionItems(array $functions, Text_Template $template)
    {
        if (empty($functions)) {
            return '';
        }

        $buffer = '';

        foreach ($functions as $function) {
            $buffer .= $this->renderFunctionOrMethodItem(
              $template, $function
            );
        }

        return $buffer;
    }

    /**
     * @param  Text_Template $template
     * @return string
     */
    protected function renderFunctionOrMethodItem(Text_Template $template, array $item, $indent = '')
    {
        $numTestedItems = $item['executedLines'] == $item['executableLines'] ? 1 : 0;

        return $this->renderItemTemplate(
          $template,
          array(
            'name'                         => sprintf(
                                                '%s<a href="#%d">%s</a>',
                                                $indent,
                                                $item['startLine'],
                                                htmlspecialchars($item['signature'])
                                              ),
            'numMethods'                   => 1,
            'numTestedMethods'             => $numTestedItems,
            'linesExecutedPercent'         => PHP_CodeCoverage_Util::percent(
                                                $item['executedLines'],
                                                $item['executableLines'],
                                                FALSE
                                              ),
            'linesExecutedPercentAsString' => PHP_CodeCoverage_Util::percent(
                                                $item['executedLines'],
                                                $item['executableLines'],
                                                TRUE
                                              ),
            'numExecutedLines'             => $item['executedLines'],
            'numExecutableLines'           => $item['executableLines'],
            'testedMethodsPercent'         => PHP_CodeCoverage_Util::percent(
                                                $numTestedItems,
                                                1,
                                                FALSE
                                              ),
            'testedMethodsPercentAsString' => PHP_CodeCoverage_Util::percent(
                                                $numTestedItems,
                                                1,
                                                TRUE
                                              ),
            'crap'                         => $item['crap']
          )
        );
    }

    /**
     * @param  PHP_CodeCoverage_Report_Node_File $node
     * @return string
     */
    protected function renderSource(PHP_CodeCoverage_Report_Node_File $node)
    {
        $coverageData = $node->getCoverageData();
        $ignoredLines = $node->getIgnoredLines();
        $testData     = $node->getTestData();
        $codeLines    = $this->loadFile($node->getPath());
        $lines        = '';
        $i            = 1;

        foreach ($codeLines as $line) {
            $numTests       = '';
            $trClass        = '';
            $popoverContent = '';
            $popoverTitle   = '';

            if (!isset($ignoredLines[$i]) && isset($coverageData[$i])) {
                $numTests = count($coverageData[$i]);

                if ($coverageData[$i] === NULL) {
                    $trClass = ' class="warning"';
                }

                else if ($numTests == 0) {
                    $trClass = ' class="danger"';
                }

                else {
                    $trClass        = ' class="success popin"';
                    $popoverContent = '<ul>';

                    if ($numTests > 1) {
                        $popoverTitle = $numTests . ' tests cover line ' . $i;
                    } else {
                        $popoverTitle = '1 test covers line ' . $i;
                    }

                    foreach ($coverageData[$i] as $test) {
                        switch ($testData[$test]) {
                            case 0: {
                                $testCSS = ' class="success"';
                            }
                            break;

                            case 1:
                            case 2: {
                                $testCSS = ' class="warning"';
                            }
                            break;

                            case 3: {
                                $testCSS = ' class="danger"';
                            }
                            break;

                            case 4: {
                                $testCSS = ' class="danger"';
                            }
                            break;

                            default: {
                                $testCSS = '';
                            }
                        }

                        $popoverContent .= sprintf(
                          '<li%s>%s</li>',

                          $testCSS,
                          htmlspecialchars($test)
                        );
                    }

                    $popoverContent .= '</ul>';
                }
            }

            if (!empty($popoverTitle)) {
                $popover = sprintf(
                  ' data-title="%s" data-content="%s" data-placement="bottom" data-html="true"',
                  $popoverTitle,
                  htmlspecialchars($popoverContent)
                );
            } else {
                $popover = '';
            }

            $lines .= sprintf(
              '     <tr%s%s><td><div align="right"><a name="%d"></a><a href="#%d">%d</a></div></td><td class="codeLine">%s</td></tr>' . "\n",
              $trClass,
              $popover,
              $i,
              $i,
              $i,
              !$this->highlight ? htmlspecialchars($line) : $line
            );

            $i++;
        }

        return $lines;
    }

    /**
     * @param  string $file
     * @return array
     */
    protected function loadFile($file)
    {
        $buffer = file_get_contents($file);
        $lines  = explode("\n", str_replace("\t", '    ', $buffer));
        $result = array();

        if (count($lines) == 0) {
            return $result;
        }

        $lines = array_map('rtrim', $lines);

        if (!$this->highlight) {
            unset($lines[count($lines)-1]);
            return $lines;
        }

        $tokens     = token_get_all($buffer);
        $stringFlag = FALSE;
        $i          = 0;
        $result[$i] = '';

        foreach ($tokens as $j => $token) {
            if (is_string($token)) {
                if ($token === '"' && $tokens[$j - 1] !== '\\') {
                    $result[$i] .= sprintf(
                      '<span class="string">%s</span>',

                      htmlspecialchars($token)
                    );

                    $stringFlag = !$stringFlag;
                } else {
                    $result[$i] .= sprintf(
                      '<span class="keyword">%s</span>',

                      htmlspecialchars($token)
                    );
                }

                continue;
            }

            list ($token, $value) = $token;

            $value = str_replace(
              array("\t", ' '),
              array('&nbsp;&nbsp;&nbsp;&nbsp;', '&nbsp;'),
              htmlspecialchars($value)
            );

            if ($value === "\n") {
                $result[++$i] = '';
            } else {
                $lines = explode("\n", $value);

                foreach ($lines as $jj => $line) {
                    $line = trim($line);

                    if ($line !== '') {
                        if ($stringFlag) {
                            $colour = 'string';
                        } else {
                            switch ($token) {
                                case T_INLINE_HTML: {
                                    $colour = 'html';
                                }
                                break;

                                case T_COMMENT:
                                case T_DOC_COMMENT: {
                                    $colour = 'comment';
                                }
                                break;

                                case T_ABSTRACT:
                                case T_ARRAY:
                                case T_AS:
                                case T_BREAK:
                                case T_CALLABLE:
                                case T_CASE:
                                case T_CATCH:
                                case T_CLASS:
                                case T_CLONE:
                                case T_CONTINUE:
                                case T_DEFAULT:
                                case T_ECHO:
                                case T_ELSE:
                                case T_ELSEIF:
                                case T_EMPTY:
                                case T_ENDDECLARE:
                                case T_ENDFOR:
                                case T_ENDFOREACH:
                                case T_ENDIF:
                                case T_ENDSWITCH:
                                case T_ENDWHILE:
                                case T_EXIT:
                                case T_EXTENDS:
                                case T_FINAL:
                                case T_FOREACH:
                                case T_FUNCTION:
                                case T_GLOBAL:
                                case T_IF:
                                case T_IMPLEMENTS:
                                case T_INCLUDE:
                                case T_INCLUDE_ONCE:
                                case T_INSTANCEOF:
                                case T_INSTEADOF:
                                case T_INTERFACE:
                                case T_ISSET:
                                case T_LOGICAL_AND:
                                case T_LOGICAL_OR:
                                case T_LOGICAL_XOR:
                                case T_NAMESPACE:
                                case T_NEW:
                                case T_PRIVATE:
                                case T_PROTECTED:
                                case T_PUBLIC:
                                case T_REQUIRE:
                                case T_REQUIRE_ONCE:
                                case T_RETURN:
                                case T_STATIC:
                                case T_THROW:
                                case T_TRAIT:
                                case T_TRY:
                                case T_UNSET:
                                case T_USE:
                                case T_VAR:
                                case T_WHILE: {
                                    $colour = 'keyword';
                                }
                                break;

                                default: {
                                    $colour = 'default';
                                }
                            }
                        }

                        $result[$i] .= sprintf(
                          '<span class="%s">%s</span>',

                          $colour,
                          $line
                        );
                    }

                    if (isset($lines[$jj + 1])) {
                        $result[++$i] = '';
                    }
                }
            }
        }

        unset($result[count($result)-1]);

        return $result;
    }
}
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.1.0
 */

/**
 * Renders the dashboard for a PHP_CodeCoverage_Report_Node_Directory node.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.1.0
 */
class PHP_CodeCoverage_Report_HTML_Renderer_Dashboard extends PHP_CodeCoverage_Report_HTML_Renderer
{
    /**
     * @param PHP_CodeCoverage_Report_Node_Directory $node
     * @param string                                 $file
     */
    public function render(PHP_CodeCoverage_Report_Node_Directory $node, $file)
    {
        $classes  = $node->getClassesAndTraits();
        $template = new Text_Template(
          $this->templatePath . 'dashboard.html'
        );

        $this->setCommonTemplateVariables($template, $node);

        $template->setVar(
          array(
            'least_tested_methods' => $this->leastTestedMethods($classes),
            'top_project_risks'    => $this->topProjectRisks($classes),
            'cc_values'            => $this->classComplexity($classes),
            'ccd_values'           => $this->classCoverageDistribution($classes),
            'backlink'             => basename(str_replace('.dashboard', '', $file))
          )
        );

        $template->renderTo($file);
    }

    /**
     * Returns the data for the Class Complexity chart.
     *
     * @param  array $classes
     * @return string
     */
    protected function classComplexity(array $classes)
    {
        $data = array();

        foreach ($classes as $name => $class) {
            $data[] = array(
              $class['coverage'],
              $class['ccn'],
              sprintf(
                '<a href="%s">%s</a>',
                $class['link'],
                $name
              )
            );
        }

        return json_encode($data);
    }

    /**
     * Returns the data for the Class Coverage Distribution chart.
     *
     * @param  array $classes
     * @return string
     */
    protected function classCoverageDistribution(array $classes)
    {
        $data = array(
          '0%'      => 0,
          '0-10%'   => 0,
          '10-20%'  => 0,
          '20-30%'  => 0,
          '30-40%'  => 0,
          '40-50%'  => 0,
          '50-60%'  => 0,
          '60-70%'  => 0,
          '70-80%'  => 0,
          '80-90%'  => 0,
          '90-100%' => 0,
          '100%'    => 0
        );

        foreach ($classes as $class) {
            if ($class['coverage'] == 0) {
                $data['0%']++;
            }

            else if ($class['coverage'] == 100) {
                $data['100%']++;
            }

            else {
                $key = floor($class['coverage']/10)*10;
                $key = $key . '-' . ($key + 10) . '%';
                $data[$key]++;
            }
        }

        return json_encode(array_values($data));
    }

    /**
     * Returns the least tested methods.
     *
     * @param  array   $classes
     * @param  integer $max
     * @return string
     */
    protected function leastTestedMethods(array $classes, $max = 10)
    {
        $methods = array();

        foreach ($classes as $className => $class) {
            foreach ($class['methods'] as $methodName => $method) {
                if ($method['coverage'] < 100) {
                    if ($className != '*') {
                        $key = $className . '::' . $methodName;
                    } else {
                        $key = $methodName;
                    }

                    $methods[$key] = $method['coverage'];
                }
            }
        }

        asort($methods);

        $methods = array_slice($methods, 0, min($max, count($methods)));
        $buffer  = '';

        foreach ($methods as $name => $coverage) {
            list($class, $method) = explode('::', $name);

            $buffer .= sprintf(
              '              <li><a href="%s">%s</a> (%d%%)</li>' . "\n",
              $classes[$class]['methods'][$method]['link'],
              $name,
              $coverage
            );
        }

        return $buffer;
    }

    /**
     * Returns the top project risks according to the CRAP index.
     *
     * @param  array   $classes
     * @param  integer $max
     * @return string
     */
    protected function topProjectRisks(array $classes, $max = 10)
    {
        $risks = array();

        foreach ($classes as $className => $class) {
            if ($class['coverage'] < 100 &&
                $class['ccn'] > count($class['methods'])) {
                $risks[$className] = $class['crap'];
            }
        }

        arsort($risks);

        $buffer = '';
        $risks  = array_slice($risks, 0, min($max, count($risks)));

        foreach ($risks as $name => $crap) {
            $buffer .= sprintf(
              '              <li><a href="%s">%s</a> (%d)</li>' . "\n",
              $classes[$name]['link'],
              $name,
              $crap
            );
        }

        return $buffer;
    }

    protected function getActiveBreadcrumb(PHP_CodeCoverage_Report_Node $node, $isDirectory)
    {
        return sprintf(
          '        <li><a href="%s.html">%s</a></li>' . "\n" .
          '        <li class="active">(Dashboard)</li>' . "\n",
          $node->getId(),
          $node->getName()
        );
    }
}
     <tr>
      <td class="{methods_level}" colspan="4">{name}</td>
      <td class="{methods_level} big">{methods_bar}</td>
      <td class="{methods_level} small"><div align="right">{methods_tested_percent}</div></td>
      <td class="{methods_level} small"><div align="right">{methods_number}</div></td>
      <td class="{methods_level} small">{crap}</td>
      <td class="{lines_level} big">{lines_bar}</td>
      <td class="{lines_level} small"><div align="right">{lines_executed_percent}</div></td>
      <td class="{lines_level} small"><div align="right">{lines_number}</div></td>
     </tr>

PNG

   IHDR        ӳ{  PLTE         mmm                              ⰰ         ᒒttt   󻻻bbbeeeggg𶶶xxx󛛛Ƽ   몪֢UUU   鿿rO   tRNS  #_
/oS?CkDOS_6>4!~a@1_'onҋM3BQjp&%!l"Xqr; A[<`am}43/0IPCM!6(*gK&YQGDP,`{VP-x)h7e1]W$1bzSܕcO]U;Zi<N#)	86pV:h#0ZQJNEDT~^  -IDATx^읇#Ǚb'4A$Ah )p3<MF9Y9X,riھ|st9s޿X kjv@l_I*~h>'y"؆K64Y*.v@c.};tN%DI	!ZЏ5LH26 ɯ"-bE,,)ʏ B>mn6pmRO
wm@V#?'CȑZ#qb|$:)/E%nRqChn%i̓}lm
?idd", `H"r.z~(bQU&)5X#EMR<*p[[%.Ọk7 lIoJFlV!̡ăuH`&,zRk$|$lXbjߪdU?Σ$HW$U'HE3*խU\}(
zhVk}guRk$%|T|ck獳"D_W+.Q)@ƽHbslTDR 2Xm#a3lYzj㒚#!	4J8( cvt]aT	 D΅Q?^-_^$:\V	$N|=(vZ'q6Z׆B5V!y3K㱿b v4xR]al!IoP@tVyL٪mlڿIUb|[*lke'*WddDӝ}\W_WߝrN?vޫ۲X%0uoui*JVƦb%}i5IYlNE-wςf_W3mI-mQ)SkTC7m<"܌bT|'$ҘR&>Op6tSN\ׯLm\r@3uT
b7t.5.q3r0=8TiJ\6uF
R32^'ŪxI	F8O{%8kJMSȴdBEdWCYO:/ON/I_=xFE! =i:o~ y?''[͓[͓[͓[͓[ͭ.U>$PƦc%]\c:|	,eSZ,oXrX!R@Zv 0> ?*< |N60;{ad2v+D^t[q !۞V}fۨϏYeॗ)Vyl|"fUq@Ǽ4Y-Y-!6aB:o%JIUQ|UKO`=\:0xPau@!KPdxhw1>$j΍vZdxSUA&[URd7øzk/rU^w:I.VǮc>q.!zSr&2)Wg	R	-iQ	8Pa\ОU%iݡU_=p	Lu(N?0?Æ:]άtB%U|NsorNf	,P	!v"
Y6hL_ @ @bscqgv4||0lϟ$S9bʱj#~?o}}7sAPm:IV=n
!{{hEࢪ8s u oLT$;VscqD3༂3.DB B4 &V'T	`D 6Ϸqyj8V*X%@s\jrN$|=5Ά 'mUiKi%CI:ssaƅ`*`=l)>u՘MeuSI_OL_}o&jz p{lu:O)s%Q@$<]f	xO%PCbhr2  PKpf5Në3^o]eJiB464^tuٲU֌:G4'22YpuG'/Py4?.SBP_>I	1t3ΓBɭɭɭɭVVVVVs]!67(gy@4>Q VF}^Xׇڼje26	L%YGhlC})<
!EEPZWZV+@R5{@ouɐ4& H6ey V݀VťcqZޒrJyByFzFN$Hb*+jՏqэ ګkݿUXle1d0d^-B%}{Y%r*j5Ak5u",:~ҸY~
hSA~6fulՇf{ȵQtATHZkƭ/ _Sn
u']b]|m`BāJ,O$du]ZsFL:aǙT4o~by?wpj滥A(x]f~an֧/^dڲc Շ,!1i&xi_VK@ip̓9Vi%a;L?0J*Ū5U'x^6V[^ {eU|:0=0d۫o*Jq%[YN.sQLud[29I:WnmXlڃ6!lNlVէKUjV\J%UߊBLcKfb>a=b~R]aG%[js@<i[Х*^.d;UIR+OD2eܶ QN34"1g0u\I}wFV4y/Djjjn5On5On5On5On5h,ҷUr]]L^%JDiɭGԝߴ/ %='qå):Q<X.'[@Pv/ɼ>/9MطݘU>yɲX@}Ftg^vO\Ӹwvpz3K5i!$P>ā'VƛL2r@UMKZ6tw맟¦bm1h||]}~0MjA (J JP68C&yr׉e}j_cJ?I0k>W	|Bޝ."TEXd 8!cw*E(J)![W"j_ТeX_XB;oO0~?:PC(.[!Wq%*leY)E<^KZT60.#A\5;Rmtkd/8)5~^0 #Ckgey)ͶԺ 6ĥ<(?&uAVm0^h.txR*a':,H|ōl5z;8+e#b'#|}2w(|KcJl6w^Տoi3HR	̔9,YgPְ:N[5SR![)]i}` mN4Хv`|;f(FltL8÷Z#AO%Y)NU5YedJE3dZذ<xɝe @PڧFTR2S·Φ/uZ~C3XzUx\2se DD.fBO&en'iR%?FyVsS~$umw()ro0*Di!3:On[B!sʇBp>ݣHT1;8MjnʏӤqp1h^<<<jjjjjnq(qpOk}I?TY8HmhyK̝u5ItenQBޗ`R`EPڦx>>yt{?|'j)}YUU{@V/J1F+7䀉[OWO[yUY!?BD%DWj>-Ai6xz)U 	R7d@g \so)a4zf[W+>P>
|qLG8vȣlj2Zt+VA6g</QHSrΣd}Yqg]sY];]FC@5YՖ5C38o)k1'd6>T*ʆUz(m)CD`He/.:zN9pgo&NC׃އ>Wհ_Hj)Xe6F 7pm-`'c.AZ=^e8F;<J1{+8'ɪ'և\A*[R$UY)VAyɃw)Ec#<T\vW<U1IؘCDoYo]wmaw:B :'Z+v}|0q1P΃*uT7 F39A}$f+o[I5ʰ޽x(&i ʼY:cPp*b¸JjV7 ljtsNkv[fy3g]u鲱gJE0)Viłù\vW<Ugt e~B[AHJ'.n&	1Ԕ	o%gͱ_N
5.W3y/Ddyr<<<<<jܪ{waw:6dJ;&3ptlasW_UT_'9{?aԬl /0dHgqllc8Rym=ˢ_ͺ[Է71x""SIfVrx33y) hhՠ0?r5x_-jчoO:$ XBX Jѣ1#ֈu7`zu2{\;uܗ9@0V$2XS&Ba[O~jN2ߠȪ/jz_ n A~uh @GLOeɵ?Tf<Ve@* -}e@0Zt/~Xm0**H'\uSEmLֻ6;+{l5۽?u*_	Ni-:I@,;]WY`	*߀n SO~nWP.cZTu Po^ǃ7wBRBW_mdjB6:*H]dQ>{Rtn(z!S7o
Iew 3]bܗ85|iϠR JkʱZRO+8U&:]ZieR<I~|d,j릟{;7U ݌XB`[u5~=zq굵Ű޹e bc5o{;ߩ@;n*Tĵ2$ܨ0'Y-?
j[Zjӭvi-*rD{mL-,L=ymxc:WevұoÏń
"dF8[T}ӵF-IVlV[P)DVC8ݪ}|kZ{Y|xrrxaG_>(JMޗ7Z@5a^\GzsρU*rMezT^:ɬͦX=>$
bi>U&XQoybbGk8 
Ҙn).Ս o^MmdZi$soo*{4eLbLٳ""mx:`:mk[geTެ)'0*TB{!I''''[͓[͓[͓[͓[]ZjQ.e'/yvQ71(Z&X?(_Z){tڀmZWϏ)-Cjqn,̋"IvUL!h꛿skAcrN佚фVE40yX~4zʸV㳰%,)fqtpu~*^0:ܲ33JO(ZB?K^ v]unlWi0p6[착C_5X#[wX3b廫R{NKAe Se|wxso>P\儔ԕ6;nVmfI$V͓J- J%֌0UwYЎSnum藮xz˗VƫIvnW_qLZ"_Xz 8]Ap?C 543zw({7e*Ȳ`۰!AQ:KUnz]1yVGaCm0PY
ٚUx6TT&hV9V
ӬzÑ 1[XzZ9erqJND/gX*9oN6D`{I%Mz9TQ7f\"j_3~xB'ܷY]*KЌ%"5"qxq~ƕ=jS>jV&~]2xzF1X_yD<#NRB}K/iy!V^˿eJ}/FkA7 S+.(ecJ:zWZ몖wQ~ä́p6,e5,+,tv%O^OO}ן -O7>ekC6wa_C|9*WA)UJg8<Zx^?2uY*^?ڇKCZ[0.C@m$-/~|Y[eweQ ׶&cO4s|cJwsX8/6/ڼ;'FLN^8]eadZ1' ^LsBd%+M`SK8פ*)gl#3"gъSqtcxx|H>=:mjUvqysܒLglC6+[FSWg9wV31A	ND<$5e(s[    ۨbaF.]K    IENDB`PNG

   IHDR           tEXtSoftware Adobe ImageReadyqe<  1IDATx}ml\EW^ɺD$|nw';vю8m0k<f8ـ<h3$ b,mn ғ0L Y`6s'>QSnSV;1KGsԩ>UoTU1cƖYuּca&#C,pؚ>kںULW
-sn3Vq~NocI~L {-	H8%_M£wB6EW,ĢpY2+(Y@&A/3kXhߍ-aA<>P'\J;(}# Qz:4%m?nfntK*l9J+DIYu1YZ^(]YYEf@ОlXz]Ut	u&5-PW}@t|#LY=s܂,w#+R+?Ƌax	X0"ea)tG*ԡwVwV^ rf%xB(qּ4>WG#lWU<ЁXJVѶlR$kDVrI7:X<s>%X1NEzw;y9z9O%~~uɗ*=Ixcy}Y(ou
±N$^je\iX񝜬];Y-r Ѳ&>!zlYaVHVN԰9=]=mRMdOUCJUiT}rWW'ڹu)ʢF"YU#P׾&ܑЅROwyzm$Os?  +^FTIEq%&~>M}]ԖwA?
[Nteexn(措BdMTpʥnqqS?bWXmW6x*{V_!VjΧsVL^jXkQjU6sk̩n~[qǸ-`O:G7l"ksRe2vQ=QƼJUX`gQy~	ďKȰE]#P:td\T/u;س:Jc-%'eq
?j"/yh48Zi1|JUu>_N;hxwNUJQU7\j̮bT:B?6oJ1Ί%I
UY-Ii4{=rǤ7@)HKJ+f4X8Cd?'j1 N<39E<w߬VzE}^_e檴pt붾39,?glYO<xx|a؎UeF	1;{EF0`DR+UYiD4?Y`|Bs2yipIq>WoVTGzg#
%D0#ܠ3[tiآ(U,]125|Ṋfw7w u+]Db]K xbW՛7|ВX㕛{UcGXk¬|( h)IUa)lp 3luPU]D)/7~4Wt5J}V
X0z VM;>Gԙ^|gF:jaZ^)74C#jwr,еSlGu;1vm><)}<VZue۠D+jyJ6V{jK>ZQՖ&mZ:1UMB~
a:/᜗:KWWOҠ&Y2f7cƌ3f̘1cƌ3f̘1cƌ3f̘1cƌ3f̘g*3fF5LbN2#Tf=C`!ZGUe꣇e2V<1mkS4iϗ*.{N8Xaj~ڀnAx,%fE:|YDVj
¢lg6(:k~MM5?4	]WO>诋WZiG|QGJeK[YcյpmjE\f/ǎ8&OQ3 .3tt2'-V8pXSrY#J!Q ",ub@FK:u^iy[]<.Cw +W\)b
kr-.MtڀMqʄ۰#$^X$"V`T4m~w%Pp1|+&UxY8*r8: k7QЃҀT$Ўƙ
S>~Sjs:5q.w&_Z.X=:ވbw` _kd{'0:ds#qi!224nq\9-KUTsSUuVo@;Uz>^=Np>oPO
@I@'Gj5o*U>^*ew>ͫʧ᫠Q5̈́<$#5Jٻj6e)_d]2B:^(*:8JYS鬆Kݗ]U4_rj{5ׇaǑ/yV?GtGb@xPU7O3|鍪	IQ5QGw	*(;wf0*PUU<YƔvbt5{2!,}Ҧ:)j2OkΪ'֊0I.q\(%ojQĖՇa<ԍexAgt'[d;׸`rcdjPFU$UeJI6T&Z}z(zvfuz {}ۿߝݞlxUZ謊.Y岟b%nw@ǩS9|źs%>_o#9\EU~/ځt(r[QZuOo;!MrU]0TcpDő? .cPuF;L_Sb}R/J_+h2$aiUǩS9>Є}76rzu~国4oĨ
1J
^̘~i C޸55<Pھr/GYk૵5mK
2姪Ϊ5,?1'jÓQpT뾺
*~I?Hם):\J:3ѴUGo)X.Ë*j\?}㉎G~A{Y#W/3鬶!ʼ=Cgu	*u_ޮ+Qe5w:UK?UW1j\S5/<z7P^<,SjUU8v,2__i뻊^R5^vNl>G׹]gwsnzTuO=?/zƲc>Οb#7ֻcgkޛTUj*-T=]uu}>ݨNЭ[]:%/_Sz]6D.mD7Uƌ3f̘1cƌ3f̘1cƌ3f̘1cƌ3f̘1cƌ3f̘1c>J4hPP+A;'G_XKmL5I.},wFFum$S-E-;Õ
C3I-`BRx1ғTJݕ;hΊ8DYJo;Y5MKɰM;%P d9KhnD[zgVh,'C
p!^M(WK2X>UQ%^p8	˽^#Ζ؄+.@gCz%ɔ-Pr
KX
n>=ՔѨeSvRLz5%9UQS \WիK'hp)ô
JrhM0F(f_R5///G+x	1"eS5
:Tf=+7Qɧ\TEs༬rYs8&k#pSՊ5MTbD܊[Ng5Q\s 5PB@[ 8ɨV1&4Wsy[Ǿ
wU2V77jމd^~YfC_h;a.&M
i UWpzs`>/"'OI۲y:BzdTq£=йb:"m/-/PWDQǴ͐57m`H%AV!Hԛ׿@"Q zދ|ߒT-*OU^Ҧ6!Cwk|h&Hd5LEYy'ƣ7%*<C'@l b!w LWW(%C43\x*QFҨ<m߃g?߉^)D}{U֘|Q=C'@| uw LׂQE=?x+x"gSOҨj׈.fqj[YGͤC焓m>{=)Z%ٝP	*G] / 8L w$?8M)\į/#7Ufd7'6\h1
vIfEIr=1w\WKVZHKgZ͡$mx %`j}TuTQJZ*H>*QxkLFTyU-)ôbiA|q`F'+	4^QyxH)#t^?@]^`ARSqjgB:r<h̆RnzPΦ)[+nMXH!0IrsKϡէUR2T	Xg ƴڳEcƌ3f̘1cƌ3f̘1cƌ3f̘1cƌ3f̘1cnjǴyƌIxQq7fM4EF.34<.i;eВi1c%9K	͠2JCnwE¤cF`5v6%˿]3Ty`~a[[J>K۷l<2-4YKhgQLxVwP~MΦ0l 3ƅaŊITȀhwJmxIMչ|U7xˆS~2ߕ?kW1kC3];YnSґAeXYz8,'x<k7Kx]$x$vgT#w;o@z_Vmn|HֵhZg-^TAn-)@4[*9xKƋj>!,Vt:eqn8%ohS(2\Q^aigF3vTUDVlQꅧWc%Ueq4ҝº/U$_Q!>t| ,țG<tC[xTXmf|<OڡMT|(w:_Xj7wt 
AXͦp$^xZRjx`3=^ll+˗eQ8g8V+9M/ o14snbtX܍svEl+@\e,,cѮ<(iHVYrQO7aI>Q%d#jUՆ|;H[bά#,Ws7NT1~m&ǻ{' \㟾bBKJo8%!$Qj:/RX)$Sy޳䍧RDUg_D軦J\jN֖SU;~?Ohssdƣ}6(T<_4b5 ^NN%8QejF7toMyө`)g[/|?өJuGL坕/=CTܠhdifHcǞG4,`D՞{'xG_p/5@m +$jVH3a"*ũ,,HJҵȸT^Qyo&IÉJUVwWLeM~3tA6rwɤ6տ \0HL%LX5c@HHÃZ|NV+7WM{cig*ȸU7iÉбzd *?gtX8̝OX:]2ɍ]p^++>AVڛE{DB.&/56ArxY#ܕy)cKQtȪ~ ! ;C}ʃtf{6$NVsjwupZ)zŁ|-wg+nMVj/d+U~ͯi:_ixwhqr>駃-x뼬)ݷyR=! ì:J/lIkV@n74758ZKJ(Uxz1w)^\ԣzȪ󲦨c2f؍v+6f̘1cƌ3f̘1cƌ3f̘1cƌ3f̘1cƌ3f̘2NoC\F1ִUZJV̚\4Mgq1z{&YT
,HX~Du\g}x>+YdN̮olZX+F[/j+S~2/jV8Jr^ԉ]J}J*ۏ<2԰&JݣjOM@ѯ#0O[SXB^uze\]dd./xXE
f'vO_H${%;kt7ށmő|d{aފ^ǛڎE5ʋBr]W=_SAf(0  oU5q,_\luz˪uz㻲o=Yi~|
0+=V Jت/ލzM\zCL[U:|k*^8"\Wٚ\.XTjX5SkFu\1 q'mģ/QUؕ*AɽDNZ׮?_[#ˍ4:^j|5LG|| øBW{6[uQF.1$qF9IHg)\5>C#uXZ$#*<ߐsRv1Tj>Jm>*#(
[Fhsש5*jQʼ&&&P犛L[Q1* ;X}Iΰ[Q?qQZHݙ֞VEsBCZ9JTKtup˷/O,.kUdsOHMg4=-)+ؿh2Nw/r|WQn=GIU;'j,vfǳpe$VGTYsBZO1pj:r"nTUSCgrveAۘFC+Ֆ#[JTe'v9-3	Dmӻuuz?0 o	hxuY&_54=f07kלU0]D:jdw/+PGUVS<\2uatc^zYRąmC+7#,|:iNw*|^sm|X>Ъ^1\#͹	&%{,2U>ݎ.c05z#
ogNO+Q쓭 ,˗-%K\[S_`y+b_94"U+Ύap}I[M,B.NtwHj漬EL߀0DX(kڵNoU{gquz
RwkէRx'uZ[3'zyyד%<UhN[tzx1 cc]FݯB"]a[JDս[cƌ3f̘1cƌ3f̘1cƌ3f̘1cƌ3f̘1cƌ3Ves{L+3VH]YPA	>sƕ3jYF\s=m1&VAɼ?k\+]6yﾓ1gtOIW7al|1 >$]e7؝WIe?ަL#>|
ҭ]
pM5MUdI61ԠeǼYGhOn3խR:^k_'Yuuq#p#
J2xl>OjcY馃!ڡ+sZ/D}2AYm pc#<'xSKx`*W[,e|6BH)㶤kjpDU(2qzx9*tqa/,
Z[	0>Ө֜xN)fă@qըFU՝w(a;ˋ>|Tc|w2eiT]*!_\WG{
]^݅Z5t|6oYHaO@=my^akE.uz]#٥hWv(:,6A߉JFa\wWex>v<?|&i_qz]eR_7|& c*kր4f,J U_h\1Au\-L\Ϝ^~Phr*tqa0fT:MU;q>etuMYA>).,;ɦCbwjE)WFӫ@s4e6^Q9oI}4x<.B?B߫#$Hx.x9,a!RTpgd5xBe.L7@*
AsduttSVUaRU|I	xG߃$T񭟬#_IFM_X@foQIDII?|%$r	{ENĸwޕqq?Dؽ}}o/`ӣCTi	<QR{\yYFQJkh^?Us:E|]V )Z|HjsW|H'|o=d|߼j #T%O	W!N#w1[iH(SVs[=Ɉ71ȳT]A G換3CT׻lRݕCV9Q\V#ܛNӏjˇ1/sl R%^s1nUj,x}fW|JuKwpSm,<7<
Ȼ[R<&p?',Й\;5bH$3#Q4\_>/ywOrD9YUD]	Ή@s]+'UaL}hrU'7:sU|k)H@hNq#ϵ8y˭Xű#w
1!흉R'7fuד0p!WÖW+Nmp\-ioD$ g٠˅%%ÐmV]̱rw*Z}y+L
Nouj}xt)lStuqxmNyKUOnDbhf}k>6ufT%{ <񐮸mjFcmUïc;w8@dGFUA& =nq5]iP}z:k⼶-ʓ	Κl*'UzaxWFdZzTNRs+# wzgi:MBqtMl#^'Gߣ*^t{=rERnQ$adJl02%Tڊ^<~g?Of*U^?:N+o[PUs|QR']V-L)HK䐞mYn\4}YVDhR;g-'3aסMDh}1cƌ3f̘1cƌ3f̘1cƌ3f̘1cƌ3f̘1cƌk*Ț4`L$b	U4\dt'>HȄ|.+Y+/Gy2OCWv3v,'kiaWO6߯E=Hv
$LlxI躍/}^]x\3ɮ5 QT&G9Ay^i}O[5ޱwq4,sJJI.myE^%'VB~dׯ}*j*	~uTk\fKЬ*Y]_v'I˨鑩6Xo'j&uɧngT]oڌ9\*wVHӖ|	>:5EF'Jɝ`!A 
e~_;5ױϊ镋m_&OVi<}"靍hW9X6KPƣG"ƭ?/O^hCHLciPj)}QQզ#tMg9xGw~d;_J+RỲ<;e5/Qs/5N[!a+NPb+ѺI}-t_qU=MKʞY5no*vvbʊ{]|~	Z{-끇^FVviϵ3Ya=6ndS;-ʹ^;uꪪ^|=_w+"i&4l#wir|W3U$"J~O@]~tRJVMHw:̦@?>O?vdrtS*$&~1>Z}^nL(]f*&*QaIꝄ|3*O?r?*4Gyz[k/tkQϖWCCKk/x5|S*`ϹγQEwy
oKYqTb$-/PtsZNKQ*>ݢU@Џ"JQ;¹&
Lx;+T/+O赟>(T?ķD^N*'p$IW֐W~=J|_UTe7ְP`;CYjk=sU[mߙ-;};2|wo1p0~>0m
@Jrǟcٷ4͜?q\UUIV?2L/+Шꄾ<܇^T?tj\JrҀB*=kmX,n}aՒIadp׷ll{\6v8RꅟҲf1F|Տ;e=\D,D:ψrxQT◎*|{nS
9~=}ӕG~%j:Dj<ឫ:jO%
$T8!jvm|'OЗ¹➱z\vsIv`Ȕʨj-^$-^GQ{m`T#c֞㸝|n.ߪN$OJUVʼt,jg-mסּNVz:(Ι*|1Ux=Yk*tMNNDUhK ؞X(刄Rv!#B_cxRŹoE5Dg>?fXQQ˔|@"աMveC>mO$H#]YI=)_`k*
:a>!X!W^wҒl'<;vwgIt_?Jh`#E:fdx=6Wu< Ӌd2di˂c#h¬c4 ?<HFYoVpN;ݷJ\ >`(t3{>⦊;;qFx4YcS$w.da*k|Q,+xs^K߫P^nO֮L5mIwl?-.ʲJ8FB.-:2Ȕ!/A#b_m%I($|PZ[1G{^#o>3mw?'cx[^:Wk/`'=~֥W(gQbfv7UzM3+؍K:4|GCtA+Kʨ{@Ɩ[05E|yn4M    IENDB`/*
 HTML5 Shiv v3.6.2pre | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
*/
(function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag();
a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/\w+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x<style>article,aside,figcaption,figure,footer,header,hgroup,nav,section{display:block}mark{background:#FF0;color:#000}</style>";
c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="<xyz></xyz>";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode||
"undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",version:"3.6.2pre",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);if(g)return a.createDocumentFragment();
for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d<h;d++)c.createElement(e[d]);return c}};l.html5=e;q(f)})(this,document);
/*!
* Bootstrap.js by @fat & @mdo
* Copyright 2012 Twitter, Inc.
* http://www.apache.org/licenses/LICENSE-2.0.txt
*/
!function($){"use strict";$(function(){$.support.transition=function(){var transitionEnd=function(){var name,el=document.createElement("bootstrap"),transEndEventNames={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(name in transEndEventNames)if(void 0!==el.style[name])return transEndEventNames[name]}();return transitionEnd&&{end:transitionEnd}}()})}(window.jQuery),!function($){"use strict";var dismiss='[data-dismiss="alert"]',Alert=function(el){$(el).on("click",dismiss,this.close)};Alert.prototype.close=function(e){function removeElement(){$parent.trigger("closed").remove()}var $parent,$this=$(this),selector=$this.attr("data-target");selector||(selector=$this.attr("href"),selector=selector&&selector.replace(/.*(?=#[^\s]*$)/,"")),$parent=$(selector),e&&e.preventDefault(),$parent.length||($parent=$this.hasClass("alert")?$this:$this.parent()),$parent.trigger(e=$.Event("close")),e.isDefaultPrevented()||($parent.removeClass("in"),$.support.transition&&$parent.hasClass("fade")?$parent.on($.support.transition.end,removeElement):removeElement())};var old=$.fn.alert;$.fn.alert=function(option){return this.each(function(){var $this=$(this),data=$this.data("alert");data||$this.data("alert",data=new Alert(this)),"string"==typeof option&&data[option].call($this)})},$.fn.alert.Constructor=Alert,$.fn.alert.noConflict=function(){return $.fn.alert=old,this},$(document).on("click.alert.data-api",dismiss,Alert.prototype.close)}(window.jQuery),!function($){"use strict";var Button=function(element,options){this.$element=$(element),this.options=$.extend({},$.fn.button.defaults,options)};Button.prototype.setState=function(state){var d="disabled",$el=this.$element,data=$el.data(),val=$el.is("input")?"val":"html";state+="Text",data.resetText||$el.data("resetText",$el[val]()),$el[val](data[state]||this.options[state]),setTimeout(function(){"loadingText"==state?$el.addClass(d).attr(d,d):$el.removeClass(d).removeAttr(d)},0)},Button.prototype.toggle=function(){var $parent=this.$element.closest('[data-toggle="buttons-radio"]');$parent&&$parent.find(".active").removeClass("active"),this.$element.toggleClass("active")};var old=$.fn.button;$.fn.button=function(option){return this.each(function(){var $this=$(this),data=$this.data("button"),options="object"==typeof option&&option;data||$this.data("button",data=new Button(this,options)),"toggle"==option?data.toggle():option&&data.setState(option)})},$.fn.button.defaults={loadingText:"loading..."},$.fn.button.Constructor=Button,$.fn.button.noConflict=function(){return $.fn.button=old,this},$(document).on("click.button.data-api","[data-toggle^=button]",function(e){var $btn=$(e.target);$btn.hasClass("btn")||($btn=$btn.closest(".btn")),$btn.button("toggle")})}(window.jQuery),!function($){"use strict";var Carousel=function(element,options){this.$element=$(element),this.options=options,"hover"==this.options.pause&&this.$element.on("mouseenter",$.proxy(this.pause,this)).on("mouseleave",$.proxy(this.cycle,this))};Carousel.prototype={cycle:function(e){return e||(this.paused=!1),this.options.interval&&!this.paused&&(this.interval=setInterval($.proxy(this.next,this),this.options.interval)),this},to:function(pos){var $active=this.$element.find(".item.active"),children=$active.parent().children(),activePos=children.index($active),that=this;if(!(pos>children.length-1||0>pos))return this.sliding?this.$element.one("slid",function(){that.to(pos)}):activePos==pos?this.pause().cycle():this.slide(pos>activePos?"next":"prev",$(children[pos]))},pause:function(e){return e||(this.paused=!0),this.$element.find(".next, .prev").length&&$.support.transition.end&&(this.$element.trigger($.support.transition.end),this.cycle()),clearInterval(this.interval),this.interval=null,this},next:function(){return this.sliding?void 0:this.slide("next")},prev:function(){return this.sliding?void 0:this.slide("prev")},slide:function(type,next){var e,$active=this.$element.find(".item.active"),$next=next||$active[type](),isCycling=this.interval,direction="next"==type?"left":"right",fallback="next"==type?"first":"last",that=this;if(this.sliding=!0,isCycling&&this.pause(),$next=$next.length?$next:this.$element.find(".item")[fallback](),e=$.Event("slide",{relatedTarget:$next[0]}),!$next.hasClass("active")){if($.support.transition&&this.$element.hasClass("slide")){if(this.$element.trigger(e),e.isDefaultPrevented())return;$next.addClass(type),$next[0].offsetWidth,$active.addClass(direction),$next.addClass(direction),this.$element.one($.support.transition.end,function(){$next.removeClass([type,direction].join(" ")).addClass("active"),$active.removeClass(["active",direction].join(" ")),that.sliding=!1,setTimeout(function(){that.$element.trigger("slid")},0)})}else{if(this.$element.trigger(e),e.isDefaultPrevented())return;$active.removeClass("active"),$next.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return isCycling&&this.cycle(),this}}};var old=$.fn.carousel;$.fn.carousel=function(option){return this.each(function(){var $this=$(this),data=$this.data("carousel"),options=$.extend({},$.fn.carousel.defaults,"object"==typeof option&&option),action="string"==typeof option?option:options.slide;data||$this.data("carousel",data=new Carousel(this,options)),"number"==typeof option?data.to(option):action?data[action]():options.interval&&data.cycle()})},$.fn.carousel.defaults={interval:5e3,pause:"hover"},$.fn.carousel.Constructor=Carousel,$.fn.carousel.noConflict=function(){return $.fn.carousel=old,this},$(document).on("click.carousel.data-api","[data-slide]",function(e){var href,$this=$(this),$target=$($this.attr("data-target")||(href=$this.attr("href"))&&href.replace(/.*(?=#[^\s]+$)/,"")),options=$.extend({},$target.data(),$this.data());$target.carousel(options),e.preventDefault()})}(window.jQuery),!function($){"use strict";var Collapse=function(element,options){this.$element=$(element),this.options=$.extend({},$.fn.collapse.defaults,options),this.options.parent&&(this.$parent=$(this.options.parent)),this.options.toggle&&this.toggle()};Collapse.prototype={constructor:Collapse,dimension:function(){var hasWidth=this.$element.hasClass("width");return hasWidth?"width":"height"},show:function(){var dimension,scroll,actives,hasData;if(!this.transitioning){if(dimension=this.dimension(),scroll=$.camelCase(["scroll",dimension].join("-")),actives=this.$parent&&this.$parent.find("> .accordion-group > .in"),actives&&actives.length){if(hasData=actives.data("collapse"),hasData&&hasData.transitioning)return;actives.collapse("hide"),hasData||actives.data("collapse",null)}this.$element[dimension](0),this.transition("addClass",$.Event("show"),"shown"),$.support.transition&&this.$element[dimension](this.$element[0][scroll])}},hide:function(){var dimension;this.transitioning||(dimension=this.dimension(),this.reset(this.$element[dimension]()),this.transition("removeClass",$.Event("hide"),"hidden"),this.$element[dimension](0))},reset:function(size){var dimension=this.dimension();return this.$element.removeClass("collapse")[dimension](size||"auto")[0].offsetWidth,this.$element[null!==size?"addClass":"removeClass"]("collapse"),this},transition:function(method,startEvent,completeEvent){var that=this,complete=function(){"show"==startEvent.type&&that.reset(),that.transitioning=0,that.$element.trigger(completeEvent)};this.$element.trigger(startEvent),startEvent.isDefaultPrevented()||(this.transitioning=1,this.$element[method]("in"),$.support.transition&&this.$element.hasClass("collapse")?this.$element.one($.support.transition.end,complete):complete())},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}};var old=$.fn.collapse;$.fn.collapse=function(option){return this.each(function(){var $this=$(this),data=$this.data("collapse"),options="object"==typeof option&&option;data||$this.data("collapse",data=new Collapse(this,options)),"string"==typeof option&&data[option]()})},$.fn.collapse.defaults={toggle:!0},$.fn.collapse.Constructor=Collapse,$.fn.collapse.noConflict=function(){return $.fn.collapse=old,this},$(document).on("click.collapse.data-api","[data-toggle=collapse]",function(e){var href,$this=$(this),target=$this.attr("data-target")||e.preventDefault()||(href=$this.attr("href"))&&href.replace(/.*(?=#[^\s]+$)/,""),option=$(target).data("collapse")?"toggle":$this.data();$this[$(target).hasClass("in")?"addClass":"removeClass"]("collapsed"),$(target).collapse(option)})}(window.jQuery),!function($){"use strict";function clearMenus(){$(toggle).each(function(){getParent($(this)).removeClass("open")})}function getParent($this){var $parent,selector=$this.attr("data-target");return selector||(selector=$this.attr("href"),selector=selector&&/#/.test(selector)&&selector.replace(/.*(?=#[^\s]*$)/,"")),$parent=$(selector),$parent.length||($parent=$this.parent()),$parent}var toggle="[data-toggle=dropdown]",Dropdown=function(element){var $el=$(element).on("click.dropdown.data-api",this.toggle);$("html").on("click.dropdown.data-api",function(){$el.parent().removeClass("open")})};Dropdown.prototype={constructor:Dropdown,toggle:function(){var $parent,isActive,$this=$(this);if(!$this.is(".disabled, :disabled"))return $parent=getParent($this),isActive=$parent.hasClass("open"),clearMenus(),isActive||$parent.toggleClass("open"),$this.focus(),!1},keydown:function(e){var $this,$items,$parent,isActive,index;if(/(38|40|27)/.test(e.keyCode)&&($this=$(this),e.preventDefault(),e.stopPropagation(),!$this.is(".disabled, :disabled"))){if($parent=getParent($this),isActive=$parent.hasClass("open"),!isActive||isActive&&27==e.keyCode)return $this.click();$items=$("[role=menu] li:not(.divider):visible a",$parent),$items.length&&(index=$items.index($items.filter(":focus")),38==e.keyCode&&index>0&&index--,40==e.keyCode&&$items.length-1>index&&index++,~index||(index=0),$items.eq(index).focus())}}};var old=$.fn.dropdown;$.fn.dropdown=function(option){return this.each(function(){var $this=$(this),data=$this.data("dropdown");data||$this.data("dropdown",data=new Dropdown(this)),"string"==typeof option&&data[option].call($this)})},$.fn.dropdown.Constructor=Dropdown,$.fn.dropdown.noConflict=function(){return $.fn.dropdown=old,this},$(document).on("click.dropdown.data-api touchstart.dropdown.data-api",clearMenus).on("click.dropdown touchstart.dropdown.data-api",".dropdown form",function(e){e.stopPropagation()}).on("touchstart.dropdown.data-api",".dropdown-menu",function(e){e.stopPropagation()}).on("click.dropdown.data-api touchstart.dropdown.data-api",toggle,Dropdown.prototype.toggle).on("keydown.dropdown.data-api touchstart.dropdown.data-api",toggle+", [role=menu]",Dropdown.prototype.keydown)}(window.jQuery),!function($){"use strict";var Modal=function(element,options){this.options=options,this.$element=$(element).delegate('[data-dismiss="modal"]',"click.dismiss.modal",$.proxy(this.hide,this)),this.options.remote&&this.$element.find(".modal-body").load(this.options.remote)};Modal.prototype={constructor:Modal,toggle:function(){return this[this.isShown?"hide":"show"]()},show:function(){var that=this,e=$.Event("show");this.$element.trigger(e),this.isShown||e.isDefaultPrevented()||(this.isShown=!0,this.escape(),this.backdrop(function(){var transition=$.support.transition&&that.$element.hasClass("fade");that.$element.parent().length||that.$element.appendTo(document.body),that.$element.show(),transition&&that.$element[0].offsetWidth,that.$element.addClass("in").attr("aria-hidden",!1),that.enforceFocus(),transition?that.$element.one($.support.transition.end,function(){that.$element.focus().trigger("shown")}):that.$element.focus().trigger("shown")}))},hide:function(e){e&&e.preventDefault(),e=$.Event("hide"),this.$element.trigger(e),this.isShown&&!e.isDefaultPrevented()&&(this.isShown=!1,this.escape(),$(document).off("focusin.modal"),this.$element.removeClass("in").attr("aria-hidden",!0),$.support.transition&&this.$element.hasClass("fade")?this.hideWithTransition():this.hideModal())},enforceFocus:function(){var that=this;$(document).on("focusin.modal",function(e){that.$element[0]===e.target||that.$element.has(e.target).length||that.$element.focus()})},escape:function(){var that=this;this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.modal",function(e){27==e.which&&that.hide()}):this.isShown||this.$element.off("keyup.dismiss.modal")},hideWithTransition:function(){var that=this,timeout=setTimeout(function(){that.$element.off($.support.transition.end),that.hideModal()},500);this.$element.one($.support.transition.end,function(){clearTimeout(timeout),that.hideModal()})},hideModal:function(){this.$element.hide().trigger("hidden"),this.backdrop()},removeBackdrop:function(){this.$backdrop.remove(),this.$backdrop=null},backdrop:function(callback){var animate=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var doAnimate=$.support.transition&&animate;this.$backdrop=$('<div class="modal-backdrop '+animate+'" />').appendTo(document.body),this.$backdrop.click("static"==this.options.backdrop?$.proxy(this.$element[0].focus,this.$element[0]):$.proxy(this.hide,this)),doAnimate&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),doAnimate?this.$backdrop.one($.support.transition.end,callback):callback()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),$.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one($.support.transition.end,$.proxy(this.removeBackdrop,this)):this.removeBackdrop()):callback&&callback()}};var old=$.fn.modal;$.fn.modal=function(option){return this.each(function(){var $this=$(this),data=$this.data("modal"),options=$.extend({},$.fn.modal.defaults,$this.data(),"object"==typeof option&&option);data||$this.data("modal",data=new Modal(this,options)),"string"==typeof option?data[option]():options.show&&data.show()})},$.fn.modal.defaults={backdrop:!0,keyboard:!0,show:!0},$.fn.modal.Constructor=Modal,$.fn.modal.noConflict=function(){return $.fn.modal=old,this},$(document).on("click.modal.data-api",'[data-toggle="modal"]',function(e){var $this=$(this),href=$this.attr("href"),$target=$($this.attr("data-target")||href&&href.replace(/.*(?=#[^\s]+$)/,"")),option=$target.data("modal")?"toggle":$.extend({remote:!/#/.test(href)&&href},$target.data(),$this.data());e.preventDefault(),$target.modal(option).one("hide",function(){$this.focus()})})}(window.jQuery),!function($){"use strict";var Tooltip=function(element,options){this.init("tooltip",element,options)};Tooltip.prototype={constructor:Tooltip,init:function(type,element,options){var eventIn,eventOut;this.type=type,this.$element=$(element),this.options=this.getOptions(options),this.enabled=!0,"click"==this.options.trigger?this.$element.on("click."+this.type,this.options.selector,$.proxy(this.toggle,this)):"manual"!=this.options.trigger&&(eventIn="hover"==this.options.trigger?"mouseenter":"focus",eventOut="hover"==this.options.trigger?"mouseleave":"blur",this.$element.on(eventIn+"."+this.type,this.options.selector,$.proxy(this.enter,this)),this.$element.on(eventOut+"."+this.type,this.options.selector,$.proxy(this.leave,this))),this.options.selector?this._options=$.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},getOptions:function(options){return options=$.extend({},$.fn[this.type].defaults,options,this.$element.data()),options.delay&&"number"==typeof options.delay&&(options.delay={show:options.delay,hide:options.delay}),options},enter:function(e){var self=$(e.currentTarget)[this.type](this._options).data(this.type);return self.options.delay&&self.options.delay.show?(clearTimeout(this.timeout),self.hoverState="in",this.timeout=setTimeout(function(){"in"==self.hoverState&&self.show()},self.options.delay.show),void 0):self.show()},leave:function(e){var self=$(e.currentTarget)[this.type](this._options).data(this.type);return this.timeout&&clearTimeout(this.timeout),self.options.delay&&self.options.delay.hide?(self.hoverState="out",this.timeout=setTimeout(function(){"out"==self.hoverState&&self.hide()},self.options.delay.hide),void 0):self.hide()},show:function(){var $tip,inside,pos,actualWidth,actualHeight,placement,tp;if(this.hasContent()&&this.enabled){switch($tip=this.tip(),this.setContent(),this.options.animation&&$tip.addClass("fade"),placement="function"==typeof this.options.placement?this.options.placement.call(this,$tip[0],this.$element[0]):this.options.placement,inside=/in/.test(placement),$tip.detach().css({top:0,left:0,display:"block"}).insertAfter(this.$element),pos=this.getPosition(inside),actualWidth=$tip[0].offsetWidth,actualHeight=$tip[0].offsetHeight,inside?placement.split(" ")[1]:placement){case"bottom":tp={top:pos.top+pos.height,left:pos.left+pos.width/2-actualWidth/2};break;case"top":tp={top:pos.top-actualHeight,left:pos.left+pos.width/2-actualWidth/2};break;case"left":tp={top:pos.top+pos.height/2-actualHeight/2,left:pos.left-actualWidth};break;case"right":tp={top:pos.top+pos.height/2-actualHeight/2,left:pos.left+pos.width}}$tip.offset(tp).addClass(placement).addClass("in")}},setContent:function(){var $tip=this.tip(),title=this.getTitle();$tip.find(".tooltip-inner")[this.options.html?"html":"text"](title),$tip.removeClass("fade in top bottom left right")},hide:function(){function removeWithAnimation(){var timeout=setTimeout(function(){$tip.off($.support.transition.end).detach()},500);$tip.one($.support.transition.end,function(){clearTimeout(timeout),$tip.detach()})}var $tip=this.tip();return $tip.removeClass("in"),$.support.transition&&this.$tip.hasClass("fade")?removeWithAnimation():$tip.detach(),this},fixTitle:function(){var $e=this.$element;($e.attr("title")||"string"!=typeof $e.attr("data-original-title"))&&$e.attr("data-original-title",$e.attr("title")||"").removeAttr("title")},hasContent:function(){return this.getTitle()},getPosition:function(inside){return $.extend({},inside?{top:0,left:0}:this.$element.offset(),{width:this.$element[0].offsetWidth,height:this.$element[0].offsetHeight})},getTitle:function(){var title,$e=this.$element,o=this.options;return title=$e.attr("data-original-title")||("function"==typeof o.title?o.title.call($e[0]):o.title)},tip:function(){return this.$tip=this.$tip||$(this.options.template)},validate:function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},enable:function(){this.enabled=!0},disable:function(){this.enabled=!1},toggleEnabled:function(){this.enabled=!this.enabled},toggle:function(e){var self=$(e.currentTarget)[this.type](this._options).data(this.type);self[self.tip().hasClass("in")?"hide":"show"]()},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}};var old=$.fn.tooltip;$.fn.tooltip=function(option){return this.each(function(){var $this=$(this),data=$this.data("tooltip"),options="object"==typeof option&&option;data||$this.data("tooltip",data=new Tooltip(this,options)),"string"==typeof option&&data[option]()})},$.fn.tooltip.Constructor=Tooltip,$.fn.tooltip.defaults={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover",title:"",delay:0,html:!1},$.fn.tooltip.noConflict=function(){return $.fn.tooltip=old,this}}(window.jQuery),!function($){"use strict";var Popover=function(element,options){this.init("popover",element,options)};Popover.prototype=$.extend({},$.fn.tooltip.Constructor.prototype,{constructor:Popover,setContent:function(){var $tip=this.tip(),title=this.getTitle(),content=this.getContent();$tip.find(".popover-title")[this.options.html?"html":"text"](title),$tip.find(".popover-content")[this.options.html?"html":"text"](content),$tip.removeClass("fade top bottom left right in")},hasContent:function(){return this.getTitle()||this.getContent()},getContent:function(){var content,$e=this.$element,o=this.options;return content=$e.attr("data-content")||("function"==typeof o.content?o.content.call($e[0]):o.content)},tip:function(){return this.$tip||(this.$tip=$(this.options.template)),this.$tip},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}});var old=$.fn.popover;$.fn.popover=function(option){return this.each(function(){var $this=$(this),data=$this.data("popover"),options="object"==typeof option&&option;data||$this.data("popover",data=new Popover(this,options)),"string"==typeof option&&data[option]()})},$.fn.popover.Constructor=Popover,$.fn.popover.defaults=$.extend({},$.fn.tooltip.defaults,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"></div></div></div>'}),$.fn.popover.noConflict=function(){return $.fn.popover=old,this}}(window.jQuery),!function($){"use strict";function ScrollSpy(element,options){var href,process=$.proxy(this.process,this),$element=$(element).is("body")?$(window):$(element);this.options=$.extend({},$.fn.scrollspy.defaults,options),this.$scrollElement=$element.on("scroll.scroll-spy.data-api",process),this.selector=(this.options.target||(href=$(element).attr("href"))&&href.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.$body=$("body"),this.refresh(),this.process()}ScrollSpy.prototype={constructor:ScrollSpy,refresh:function(){var $targets,self=this;this.offsets=$([]),this.targets=$([]),$targets=this.$body.find(this.selector).map(function(){var $el=$(this),href=$el.data("target")||$el.attr("href"),$href=/^#\w/.test(href)&&$(href);return $href&&$href.length&&[[$href.position().top+self.$scrollElement.scrollTop(),href]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){self.offsets.push(this[0]),self.targets.push(this[1])})},process:function(){var i,scrollTop=this.$scrollElement.scrollTop()+this.options.offset,scrollHeight=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,maxScroll=scrollHeight-this.$scrollElement.height(),offsets=this.offsets,targets=this.targets,activeTarget=this.activeTarget;if(scrollTop>=maxScroll)return activeTarget!=(i=targets.last()[0])&&this.activate(i);for(i=offsets.length;i--;)activeTarget!=targets[i]&&scrollTop>=offsets[i]&&(!offsets[i+1]||offsets[i+1]>=scrollTop)&&this.activate(targets[i])},activate:function(target){var active,selector;this.activeTarget=target,$(this.selector).parent(".active").removeClass("active"),selector=this.selector+'[data-target="'+target+'"],'+this.selector+'[href="'+target+'"]',active=$(selector).parent("li").addClass("active"),active.parent(".dropdown-menu").length&&(active=active.closest("li.dropdown").addClass("active")),active.trigger("activate")}};var old=$.fn.scrollspy;$.fn.scrollspy=function(option){return this.each(function(){var $this=$(this),data=$this.data("scrollspy"),options="object"==typeof option&&option;data||$this.data("scrollspy",data=new ScrollSpy(this,options)),"string"==typeof option&&data[option]()})},$.fn.scrollspy.Constructor=ScrollSpy,$.fn.scrollspy.defaults={offset:10},$.fn.scrollspy.noConflict=function(){return $.fn.scrollspy=old,this},$(window).on("load",function(){$('[data-spy="scroll"]').each(function(){var $spy=$(this);$spy.scrollspy($spy.data())})})}(window.jQuery),!function($){"use strict";var Tab=function(element){this.element=$(element)};Tab.prototype={constructor:Tab,show:function(){var previous,$target,e,$this=this.element,$ul=$this.closest("ul:not(.dropdown-menu)"),selector=$this.attr("data-target");selector||(selector=$this.attr("href"),selector=selector&&selector.replace(/.*(?=#[^\s]*$)/,"")),$this.parent("li").hasClass("active")||(previous=$ul.find(".active:last a")[0],e=$.Event("show",{relatedTarget:previous}),$this.trigger(e),e.isDefaultPrevented()||($target=$(selector),this.activate($this.parent("li"),$ul),this.activate($target,$target.parent(),function(){$this.trigger({type:"shown",relatedTarget:previous})})))},activate:function(element,container,callback){function next(){$active.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),element.addClass("active"),transition?(element[0].offsetWidth,element.addClass("in")):element.removeClass("fade"),element.parent(".dropdown-menu")&&element.closest("li.dropdown").addClass("active"),callback&&callback()}var $active=container.find("> .active"),transition=callback&&$.support.transition&&$active.hasClass("fade");transition?$active.one($.support.transition.end,next):next(),$active.removeClass("in")}};var old=$.fn.tab;$.fn.tab=function(option){return this.each(function(){var $this=$(this),data=$this.data("tab");data||$this.data("tab",data=new Tab(this)),"string"==typeof option&&data[option]()})},$.fn.tab.Constructor=Tab,$.fn.tab.noConflict=function(){return $.fn.tab=old,this},$(document).on("click.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(e){e.preventDefault(),$(this).tab("show")})}(window.jQuery),!function($){"use strict";var Typeahead=function(element,options){this.$element=$(element),this.options=$.extend({},$.fn.typeahead.defaults,options),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.highlighter=this.options.highlighter||this.highlighter,this.updater=this.options.updater||this.updater,this.source=this.options.source,this.$menu=$(this.options.menu),this.shown=!1,this.listen()};Typeahead.prototype={constructor:Typeahead,select:function(){var val=this.$menu.find(".active").attr("data-value");return this.$element.val(this.updater(val)).change(),this.hide()},updater:function(item){return item},show:function(){var pos=$.extend({},this.$element.position(),{height:this.$element[0].offsetHeight});return this.$menu.insertAfter(this.$element).css({top:pos.top+pos.height,left:pos.left}).show(),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(){var items;return this.query=this.$element.val(),!this.query||this.query.length<this.options.minLength?this.shown?this.hide():this:(items=$.isFunction(this.source)?this.source(this.query,$.proxy(this.process,this)):this.source,items?this.process(items):this)},process:function(items){var that=this;return items=$.grep(items,function(item){return that.matcher(item)}),items=this.sorter(items),items.length?this.render(items.slice(0,this.options.items)).show():this.shown?this.hide():this},matcher:function(item){return~item.toLowerCase().indexOf(this.query.toLowerCase())},sorter:function(items){for(var item,beginswith=[],caseSensitive=[],caseInsensitive=[];item=items.shift();)item.toLowerCase().indexOf(this.query.toLowerCase())?~item.indexOf(this.query)?caseSensitive.push(item):caseInsensitive.push(item):beginswith.push(item);return beginswith.concat(caseSensitive,caseInsensitive)},highlighter:function(item){var query=this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&");return item.replace(RegExp("("+query+")","ig"),function($1,match){return"<strong>"+match+"</strong>"})},render:function(items){var that=this;return items=$(items).map(function(i,item){return i=$(that.options.item).attr("data-value",item),i.find("a").html(that.highlighter(item)),i[0]}),items.first().addClass("active"),this.$menu.html(items),this},next:function(){var active=this.$menu.find(".active").removeClass("active"),next=active.next();next.length||(next=$(this.$menu.find("li")[0])),next.addClass("active")},prev:function(){var active=this.$menu.find(".active").removeClass("active"),prev=active.prev();prev.length||(prev=this.$menu.find("li").last()),prev.addClass("active")},listen:function(){this.$element.on("blur",$.proxy(this.blur,this)).on("keypress",$.proxy(this.keypress,this)).on("keyup",$.proxy(this.keyup,this)),this.eventSupported("keydown")&&this.$element.on("keydown",$.proxy(this.keydown,this)),this.$menu.on("click",$.proxy(this.click,this)).on("mouseenter","li",$.proxy(this.mouseenter,this))},eventSupported:function(eventName){var isSupported=eventName in this.$element;return isSupported||(this.$element.setAttribute(eventName,"return;"),isSupported="function"==typeof this.$element[eventName]),isSupported},move:function(e){if(this.shown){switch(e.keyCode){case 9:case 13:case 27:e.preventDefault();break;case 38:e.preventDefault(),this.prev();break;case 40:e.preventDefault(),this.next()}e.stopPropagation()}},keydown:function(e){this.suppressKeyPressRepeat=~$.inArray(e.keyCode,[40,38,9,13,27]),this.move(e)},keypress:function(e){this.suppressKeyPressRepeat||this.move(e)},keyup:function(e){switch(e.keyCode){case 40:case 38:case 16:case 17:case 18:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide();break;default:this.lookup()}e.stopPropagation(),e.preventDefault()},blur:function(){var that=this;setTimeout(function(){that.hide()},150)},click:function(e){e.stopPropagation(),e.preventDefault(),this.select()},mouseenter:function(e){this.$menu.find(".active").removeClass("active"),$(e.currentTarget).addClass("active")}};var old=$.fn.typeahead;$.fn.typeahead=function(option){return this.each(function(){var $this=$(this),data=$this.data("typeahead"),options="object"==typeof option&&option;data||$this.data("typeahead",data=new Typeahead(this,options)),"string"==typeof option&&data[option]()})},$.fn.typeahead.defaults={source:[],items:8,menu:'<ul class="typeahead dropdown-menu"></ul>',item:'<li><a href="#"></a></li>',minLength:1},$.fn.typeahead.Constructor=Typeahead,$.fn.typeahead.noConflict=function(){return $.fn.typeahead=old,this},$(document).on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(e){var $this=$(this);$this.data("typeahead")||(e.preventDefault(),$this.typeahead($this.data()))})}(window.jQuery),!function($){"use strict";var Affix=function(element,options){this.options=$.extend({},$.fn.affix.defaults,options),this.$window=$(window).on("scroll.affix.data-api",$.proxy(this.checkPosition,this)).on("click.affix.data-api",$.proxy(function(){setTimeout($.proxy(this.checkPosition,this),1)},this)),this.$element=$(element),this.checkPosition()};Affix.prototype.checkPosition=function(){if(this.$element.is(":visible")){var affix,scrollHeight=$(document).height(),scrollTop=this.$window.scrollTop(),position=this.$element.offset(),offset=this.options.offset,offsetBottom=offset.bottom,offsetTop=offset.top,reset="affix affix-top affix-bottom";"object"!=typeof offset&&(offsetBottom=offsetTop=offset),"function"==typeof offsetTop&&(offsetTop=offset.top()),"function"==typeof offsetBottom&&(offsetBottom=offset.bottom()),affix=null!=this.unpin&&scrollTop+this.unpin<=position.top?!1:null!=offsetBottom&&position.top+this.$element.height()>=scrollHeight-offsetBottom?"bottom":null!=offsetTop&&offsetTop>=scrollTop?"top":!1,this.affixed!==affix&&(this.affixed=affix,this.unpin="bottom"==affix?position.top-scrollTop:null,this.$element.removeClass(reset).addClass("affix"+(affix?"-"+affix:"")))}};var old=$.fn.affix;$.fn.affix=function(option){return this.each(function(){var $this=$(this),data=$this.data("affix"),options="object"==typeof option&&option;data||$this.data("affix",data=new Affix(this,options)),"string"==typeof option&&data[option]()})},$.fn.affix.Constructor=Affix,$.fn.affix.defaults={offset:0},$.fn.affix.noConflict=function(){return $.fn.affix=old,this},$(window).on("load",function(){$('[data-spy="affix"]').each(function(){var $spy=$(this),data=$spy.data();data.offset=data.offset||{},data.offsetBottom&&(data.offset.bottom=data.offsetBottom),data.offsetTop&&(data.offset.top=data.offsetTop),$spy.affix(data)})})}(window.jQuery);/*! jQuery v1.9.1 | (c) 2005, 2012 jQuery Foundation, Inc. | jquery.org/license
//@ sourceMappingURL=jquery.min.map
*/(function(e,t){var n,r,i=typeof t,o=e.document,a=e.location,s=e.jQuery,u=e.$,l={},c=[],p="1.9.1",f=c.concat,d=c.push,h=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=p.trim,b=function(e,t){return new b.fn.init(e,t,r)},x=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^[\],:{}\s]*$/,E=/(?:^|:|,)(?:\s*\[)+/g,S=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,A=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,j=/^-ms-/,D=/-([\da-z])/gi,L=function(e,t){return t.toUpperCase()},H=function(e){(o.addEventListener||"load"===e.type||"complete"===o.readyState)&&(q(),b.ready())},q=function(){o.addEventListener?(o.removeEventListener("DOMContentLoaded",H,!1),e.removeEventListener("load",H,!1)):(o.detachEvent("onreadystatechange",H),e.detachEvent("onload",H))};b.fn=b.prototype={jquery:p,constructor:b,init:function(e,n,r){var i,a;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof b?n[0]:n,b.merge(this,b.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:o,!0)),C.test(i[1])&&b.isPlainObject(n))for(i in n)b.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(a=o.getElementById(i[2]),a&&a.parentNode){if(a.id!==i[2])return r.find(e);this.length=1,this[0]=a}return this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):b.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),b.makeArray(e,this))},selector:"",length:0,size:function(){return this.length},toArray:function(){return h.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=b.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return b.each(this,e,t)},ready:function(e){return b.ready.promise().done(e),this},slice:function(){return this.pushStack(h.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(b.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:d,sort:[].sort,splice:[].splice},b.fn.init.prototype=b.fn,b.extend=b.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},u=1,l=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},u=2),"object"==typeof s||b.isFunction(s)||(s={}),l===u&&(s=this,--u);l>u;u++)if(null!=(o=arguments[u]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(b.isPlainObject(r)||(n=b.isArray(r)))?(n?(n=!1,a=e&&b.isArray(e)?e:[]):a=e&&b.isPlainObject(e)?e:{},s[i]=b.extend(c,a,r)):r!==t&&(s[i]=r));return s},b.extend({noConflict:function(t){return e.$===b&&(e.$=u),t&&e.jQuery===b&&(e.jQuery=s),b},isReady:!1,readyWait:1,holdReady:function(e){e?b.readyWait++:b.ready(!0)},ready:function(e){if(e===!0?!--b.readyWait:!b.isReady){if(!o.body)return setTimeout(b.ready);b.isReady=!0,e!==!0&&--b.readyWait>0||(n.resolveWith(o,[b]),b.fn.trigger&&b(o).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===b.type(e)},isArray:Array.isArray||function(e){return"array"===b.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if(!e||"object"!==b.type(e)||e.nodeType||b.isWindow(e))return!1;try{if(e.constructor&&!y.call(e,"constructor")&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||y.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=b.buildFragment([e],t,i),i&&b(i).remove(),b.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=b.trim(n),n&&k.test(n.replace(S,"@").replace(A,"]").replace(E,"")))?Function("return "+n)():(b.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||b.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&b.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(j,"ms-").replace(D,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:v&&!v.call("\ufeff\u00a0")?function(e){return null==e?"":v.call(e)}:function(e){return null==e?"":(e+"").replace(T,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?b.merge(n,"string"==typeof e?[e]:e):d.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(g)return g.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return f.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),b.isFunction(e)?(r=h.call(arguments,2),i=function(){return e.apply(n||this,r.concat(h.call(arguments)))},i.guid=e.guid=e.guid||b.guid++,i):t},access:function(e,n,r,i,o,a,s){var u=0,l=e.length,c=null==r;if("object"===b.type(r)){o=!0;for(u in r)b.access(e,n,u,r[u],!0,a,s)}else if(i!==t&&(o=!0,b.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(b(e),n)})),n))for(;l>u;u++)n(e[u],r,s?i:i.call(e[u],u,n(e[u],r)));return o?e:c?n.call(e):l?n(e[0],r):a},now:function(){return(new Date).getTime()}}),b.ready.promise=function(t){if(!n)if(n=b.Deferred(),"complete"===o.readyState)setTimeout(b.ready);else if(o.addEventListener)o.addEventListener("DOMContentLoaded",H,!1),e.addEventListener("load",H,!1);else{o.attachEvent("onreadystatechange",H),e.attachEvent("onload",H);var r=!1;try{r=null==e.frameElement&&o.documentElement}catch(i){}r&&r.doScroll&&function a(){if(!b.isReady){try{r.doScroll("left")}catch(e){return setTimeout(a,50)}q(),b.ready()}}()}return n.promise(t)},b.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=b.type(e);return b.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=b(o);var _={};function F(e){var t=_[e]={};return b.each(e.match(w)||[],function(e,n){t[n]=!0}),t}b.Callbacks=function(e){e="string"==typeof e?_[e]||F(e):b.extend({},e);var n,r,i,o,a,s,u=[],l=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=u.length,n=!0;u&&o>a;a++)if(u[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,u&&(l?l.length&&c(l.shift()):r?u=[]:p.disable())},p={add:function(){if(u){var t=u.length;(function i(t){b.each(t,function(t,n){var r=b.type(n);"function"===r?e.unique&&p.has(n)||u.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=u.length:r&&(s=t,c(r))}return this},remove:function(){return u&&b.each(arguments,function(e,t){var r;while((r=b.inArray(t,u,r))>-1)u.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?b.inArray(e,u)>-1:!(!u||!u.length)},empty:function(){return u=[],this},disable:function(){return u=l=r=t,this},disabled:function(){return!u},lock:function(){return l=t,r||p.disable(),this},locked:function(){return!l},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!u||i&&!l||(n?l.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},b.extend({Deferred:function(e){var t=[["resolve","done",b.Callbacks("once memory"),"resolved"],["reject","fail",b.Callbacks("once memory"),"rejected"],["notify","progress",b.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return b.Deferred(function(n){b.each(t,function(t,o){var a=o[0],s=b.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&b.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?b.extend(e,r):r}},i={};return r.pipe=r.then,b.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=h.call(arguments),r=n.length,i=1!==r||e&&b.isFunction(e.promise)?r:0,o=1===i?e:b.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?h.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,u,l;if(r>1)for(s=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&b.isFunction(n[t].promise)?n[t].promise().done(a(t,l,n)).fail(o.reject).progress(a(t,u,s)):--i;return i||o.resolveWith(l,n),o.promise()}}),b.support=function(){var t,n,r,a,s,u,l,c,p,f,d=o.createElement("div");if(d.setAttribute("className","t"),d.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",n=d.getElementsByTagName("*"),r=d.getElementsByTagName("a")[0],!n||!r||!n.length)return{};s=o.createElement("select"),l=s.appendChild(o.createElement("option")),a=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={getSetAttribute:"t"!==d.className,leadingWhitespace:3===d.firstChild.nodeType,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:"/a"===r.getAttribute("href"),opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:!!a.value,optSelected:l.selected,enctype:!!o.createElement("form").enctype,html5Clone:"<:nav></:nav>"!==o.createElement("nav").cloneNode(!0).outerHTML,boxModel:"CSS1Compat"===o.compatMode,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},a.checked=!0,t.noCloneChecked=a.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!l.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}a=o.createElement("input"),a.setAttribute("value",""),t.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),t.radioValue="t"===a.value,a.setAttribute("checked","t"),a.setAttribute("name","t"),u=o.createDocumentFragment(),u.appendChild(a),t.appendChecked=a.checked,t.checkClone=u.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;return d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip,b(function(){var n,r,a,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",u=o.getElementsByTagName("body")[0];u&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",u.appendChild(n).appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",a=d.getElementsByTagName("td"),a[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===a[0].offsetHeight,a[0].style.display="",a[1].style.display="none",t.reliableHiddenOffsets=p&&0===a[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=4===d.offsetWidth,t.doesNotIncludeMarginInBodyOffset=1!==u.offsetTop,e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(o.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="<div></div>",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(u.style.zoom=1)),u.removeChild(n),n=d=a=r=null)}),n=s=u=l=r=a=null,t}();var O=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,B=/([A-Z])/g;function P(e,n,r,i){if(b.acceptData(e)){var o,a,s=b.expando,u="string"==typeof n,l=e.nodeType,p=l?b.cache:e,f=l?e[s]:e[s]&&s;if(f&&p[f]&&(i||p[f].data)||!u||r!==t)return f||(l?e[s]=f=c.pop()||b.guid++:f=s),p[f]||(p[f]={},l||(p[f].toJSON=b.noop)),("object"==typeof n||"function"==typeof n)&&(i?p[f]=b.extend(p[f],n):p[f].data=b.extend(p[f].data,n)),o=p[f],i||(o.data||(o.data={}),o=o.data),r!==t&&(o[b.camelCase(n)]=r),u?(a=o[n],null==a&&(a=o[b.camelCase(n)])):a=o,a}}function R(e,t,n){if(b.acceptData(e)){var r,i,o,a=e.nodeType,s=a?b.cache:e,u=a?e[b.expando]:b.expando;if(s[u]){if(t&&(o=n?s[u]:s[u].data)){b.isArray(t)?t=t.concat(b.map(t,b.camelCase)):t in o?t=[t]:(t=b.camelCase(t),t=t in o?[t]:t.split(" "));for(r=0,i=t.length;i>r;r++)delete o[t[r]];if(!(n?$:b.isEmptyObject)(o))return}(n||(delete s[u].data,$(s[u])))&&(a?b.cleanData([e],!0):b.support.deleteExpando||s!=s.window?delete s[u]:s[u]=null)}}}b.extend({cache:{},expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?b.cache[e[b.expando]]:e[b.expando],!!e&&!$(e)},data:function(e,t,n){return P(e,t,n)},removeData:function(e,t){return R(e,t)},_data:function(e,t,n){return P(e,t,n,!0)},_removeData:function(e,t){return R(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&b.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),b.fn.extend({data:function(e,n){var r,i,o=this[0],a=0,s=null;if(e===t){if(this.length&&(s=b.data(o),1===o.nodeType&&!b._data(o,"parsedAttrs"))){for(r=o.attributes;r.length>a;a++)i=r[a].name,i.indexOf("data-")||(i=b.camelCase(i.slice(5)),W(o,i,s[i]));b._data(o,"parsedAttrs",!0)}return s}return"object"==typeof e?this.each(function(){b.data(this,e)}):b.access(this,function(n){return n===t?o?W(o,e,b.data(o,e)):null:(this.each(function(){b.data(this,e,n)}),t)},null,n,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){b.removeData(this,e)})}});function W(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(B,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:O.test(r)?b.parseJSON(r):r}catch(o){}b.data(e,n,r)}else r=t}return r}function $(e){var t;for(t in e)if(("data"!==t||!b.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}b.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=b._data(e,n),r&&(!i||b.isArray(r)?i=b._data(e,n,b.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=b.queue(e,t),r=n.length,i=n.shift(),o=b._queueHooks(e,t),a=function(){b.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),o.cur=i,i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return b._data(e,n)||b._data(e,n,{empty:b.Callbacks("once memory").add(function(){b._removeData(e,t+"queue"),b._removeData(e,n)})})}}),b.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?b.queue(this[0],e):n===t?this:this.each(function(){var t=b.queue(this,e,n);b._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&b.dequeue(this,e)})},dequeue:function(e){return this.each(function(){b.dequeue(this,e)})},delay:function(e,t){return e=b.fx?b.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=b.Deferred(),a=this,s=this.length,u=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=b._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(u));return u(),o.promise(n)}});var I,z,X=/[\t\r\n]/g,U=/\r/g,V=/^(?:input|select|textarea|button|object)$/i,Y=/^(?:a|area)$/i,J=/^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,G=/^(?:checked|selected)$/i,Q=b.support.getSetAttribute,K=b.support.input;b.fn.extend({attr:function(e,t){return b.access(this,b.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){b.removeAttr(this,e)})},prop:function(e,t){return b.access(this,b.prop,e,t,arguments.length>1)},removeProp:function(e){return e=b.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,u="string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=b.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,u=0===arguments.length||"string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?b.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e,r="boolean"==typeof t;return b.isFunction(e)?this.each(function(n){b(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var o,a=0,s=b(this),u=t,l=e.match(w)||[];while(o=l[a++])u=r?u:!s.hasClass(o),s[u?"addClass":"removeClass"](o)}else(n===i||"boolean"===n)&&(this.className&&b._data(this,"__className__",this.className),this.className=this.className||e===!1?"":b._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(X," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=b.isFunction(e),this.each(function(n){var o,a=b(this);1===this.nodeType&&(o=i?e.call(this,n,a.val()):e,null==o?o="":"number"==typeof o?o+="":b.isArray(o)&&(o=b.map(o,function(e){return null==e?"":e+""})),r=b.valHooks[this.type]||b.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=b.valHooks[o.type]||b.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(U,""):null==n?"":n)}}}),b.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,u=0>i?s:o?i:0;for(;s>u;u++)if(n=r[u],!(!n.selected&&u!==i||(b.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&b.nodeName(n.parentNode,"optgroup"))){if(t=b(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n=b.makeArray(t);return b(e).find("option").each(function(){this.selected=b.inArray(b(this).val(),n)>=0}),n.length||(e.selectedIndex=-1),n}}},attr:function(e,n,r){var o,a,s,u=e.nodeType;if(e&&3!==u&&8!==u&&2!==u)return typeof e.getAttribute===i?b.prop(e,n,r):(a=1!==u||!b.isXMLDoc(e),a&&(n=n.toLowerCase(),o=b.attrHooks[n]||(J.test(n)?z:I)),r===t?o&&a&&"get"in o&&null!==(s=o.get(e,n))?s:(typeof e.getAttribute!==i&&(s=e.getAttribute(n)),null==s?t:s):null!==r?o&&a&&"set"in o&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r):(b.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=b.propFix[n]||n,J.test(n)?!Q&&G.test(n)?e[b.camelCase("default-"+n)]=e[r]=!1:e[r]=!1:b.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!b.support.radioValue&&"radio"===t&&b.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!b.isXMLDoc(e),a&&(n=b.propFix[n]||n,o=b.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var n=e.getAttributeNode("tabindex");return n&&n.specified?parseInt(n.value,10):V.test(e.nodeName)||Y.test(e.nodeName)&&e.href?0:t}}}}),z={get:function(e,n){var r=b.prop(e,n),i="boolean"==typeof r&&e.getAttribute(n),o="boolean"==typeof r?K&&Q?null!=i:G.test(n)?e[b.camelCase("default-"+n)]:!!i:e.getAttributeNode(n);return o&&o.value!==!1?n.toLowerCase():t},set:function(e,t,n){return t===!1?b.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&b.propFix[n]||n,n):e[b.camelCase("default-"+n)]=e[n]=!0,n}},K&&Q||(b.attrHooks.value={get:function(e,n){var r=e.getAttributeNode(n);return b.nodeName(e,"input")?e.defaultValue:r&&r.specified?r.value:t},set:function(e,n,r){return b.nodeName(e,"input")?(e.defaultValue=n,t):I&&I.set(e,n,r)}}),Q||(I=b.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&("id"===n||"name"===n||"coords"===n?""!==r.value:r.specified)?r.value:t},set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},b.attrHooks.contenteditable={get:I.get,set:function(e,t,n){I.set(e,""===t?!1:t,n)}},b.each(["width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}})})),b.support.hrefNormalized||(b.each(["href","src","width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{get:function(e){var r=e.getAttribute(n,2);return null==r?t:r}})}),b.each(["href","src"],function(e,t){b.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}})),b.support.style||(b.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),b.support.optSelected||(b.propHooks.selected=b.extend(b.propHooks.selected,{get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}})),b.support.enctype||(b.propFix.enctype="encoding"),b.support.checkOn||b.each(["radio","checkbox"],function(){b.valHooks[this]={get:function(e){return null===e.getAttribute("value")?"on":e.value}}}),b.each(["radio","checkbox"],function(){b.valHooks[this]=b.extend(b.valHooks[this],{set:function(e,n){return b.isArray(n)?e.checked=b.inArray(b(e).val(),n)>=0:t}})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}b.event={global:{},add:function(e,n,r,o,a){var s,u,l,c,p,f,d,h,g,m,y,v=b._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=b.guid++),(u=v.events)||(u=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof b===i||e&&b.event.triggered===e.type?t:b.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(w)||[""],l=n.length;while(l--)s=rt.exec(n[l])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),p=b.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=b.event.special[g]||{},d=b.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&b.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=u[g])||(h=u[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),b.event.global[g]=!0;e=null}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,p,f,d,h,g,m=b.hasData(e)&&b._data(e);if(m&&(c=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(s=rt.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=b.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),u=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));u&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||b.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)b.event.remove(e,d+t[l],n,r,!0);b.isEmptyObject(c)&&(delete m.handle,b._removeData(e,"events"))}},trigger:function(n,r,i,a){var s,u,l,c,p,f,d,h=[i||o],g=y.call(n,"type")?n.type:n,m=y.call(n,"namespace")?n.namespace.split("."):[];if(l=f=i=i||o,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+b.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),u=0>g.indexOf(":")&&"on"+g,n=n[b.expando]?n:new b.Event(g,"object"==typeof n&&n),n.isTrigger=!0,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:b.makeArray(r,[n]),p=b.event.special[g]||{},a||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!a&&!p.noBubble&&!b.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(l=l.parentNode);l;l=l.parentNode)h.push(l),f=l;f===(i.ownerDocument||o)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((l=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(b._data(l,"events")||{})[n.type]&&b._data(l,"handle"),s&&s.apply(l,r),s=u&&l[u],s&&b.acceptData(l)&&s.apply&&s.apply(l,r)===!1&&n.preventDefault();if(n.type=g,!(a||n.isDefaultPrevented()||p._default&&p._default.apply(i.ownerDocument,r)!==!1||"click"===g&&b.nodeName(i,"a")||!b.acceptData(i)||!u||!i[g]||b.isWindow(i))){f=i[u],f&&(i[u]=null),b.event.triggered=g;try{i[g]()}catch(v){}b.event.triggered=t,f&&(i[u]=f)}return n.result}},dispatch:function(e){e=b.event.fix(e);var n,r,i,o,a,s=[],u=h.call(arguments),l=(b._data(this,"events")||{})[e.type]||[],c=b.event.special[e.type]||{};if(u[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=b.event.handlers.call(this,e,l),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((b.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,u),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],u=n.delegateCount,l=e.target;if(u&&l.nodeType&&(!e.button||"click"!==e.type))for(;l!=this;l=l.parentNode||this)if(1===l.nodeType&&(l.disabled!==!0||"click"!==e.type)){for(o=[],a=0;u>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?b(r,this).index(l)>=0:b.find(r,this,null,[l]).length),o[r]&&o.push(i);o.length&&s.push({elem:l,handlers:o})}return n.length>u&&s.push({elem:this,handlers:n.slice(u)}),s},fix:function(e){if(e[b.expando])return e;var t,n,r,i=e.type,a=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new b.Event(a),t=r.length;while(t--)n=r[t],e[n]=a[n];return e.target||(e.target=a.srcElement||o),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,a):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,a,s=n.button,u=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||o,a=i.documentElement,r=i.body,e.pageX=n.clientX+(a&&a.scrollLeft||r&&r.scrollLeft||0)-(a&&a.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(a&&a.scrollTop||r&&r.scrollTop||0)-(a&&a.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&u&&(e.relatedTarget=u===e.target?n.toElement:u),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},click:{trigger:function(){return b.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t}},focus:{trigger:function(){if(this!==o.activeElement&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===o.activeElement&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=b.extend(new b.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?b.event.trigger(i,null,t):b.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},b.removeEvent=o.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},b.Event=function(e,n){return this instanceof b.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&b.extend(this,n),this.timeStamp=e&&e.timeStamp||b.now(),this[b.expando]=!0,t):new b.Event(e,n)},b.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},b.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){b.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;
return(!i||i!==r&&!b.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),b.support.submitBubbles||(b.event.special.submit={setup:function(){return b.nodeName(this,"form")?!1:(b.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=b.nodeName(n,"input")||b.nodeName(n,"button")?n.form:t;r&&!b._data(r,"submitBubbles")&&(b.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),b._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&b.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return b.nodeName(this,"form")?!1:(b.event.remove(this,"._submit"),t)}}),b.support.changeBubbles||(b.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(b.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),b.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),b.event.simulate("change",this,e,!0)})),!1):(b.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!b._data(t,"changeBubbles")&&(b.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||b.event.simulate("change",this.parentNode,e,!0)}),b._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return b.event.remove(this,"._change"),!Z.test(this.nodeName)}}),b.support.focusinBubbles||b.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){b.event.simulate(t,e.target,b.event.fix(e),!0)};b.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),b.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return b().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=b.guid++)),this.each(function(){b.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,b(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){b.event.remove(this,e,r,n)})},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},trigger:function(e,t){return this.each(function(){b.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?b.event.trigger(e,n,r,!0):t}}),function(e,t){var n,r,i,o,a,s,u,l,c,p,f,d,h,g,m,y,v,x="sizzle"+-new Date,w=e.document,T={},N=0,C=0,k=it(),E=it(),S=it(),A=typeof t,j=1<<31,D=[],L=D.pop,H=D.push,q=D.slice,M=D.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},_="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=F.replace("w","w#"),B="([*^$|!~]?=)",P="\\["+_+"*("+F+")"+_+"*(?:"+B+_+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+O+")|)|)"+_+"*\\]",R=":("+F+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+P.replace(3,8)+")*)|.*)\\)|)",W=RegExp("^"+_+"+|((?:^|[^\\\\])(?:\\\\.)*)"+_+"+$","g"),$=RegExp("^"+_+"*,"+_+"*"),I=RegExp("^"+_+"*([\\x20\\t\\r\\n\\f>+~])"+_+"*"),z=RegExp(R),X=RegExp("^"+O+"$"),U={ID:RegExp("^#("+F+")"),CLASS:RegExp("^\\.("+F+")"),NAME:RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:RegExp("^("+F.replace("w","w*")+")"),ATTR:RegExp("^"+P),PSEUDO:RegExp("^"+R),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+_+"*(even|odd|(([+-]|)(\\d*)n|)"+_+"*(?:([+-]|)"+_+"*(\\d+)|))"+_+"*\\)|)","i"),needsContext:RegExp("^"+_+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+_+"*((?:-\\d)?\\d*)"+_+"*\\)|)(?=[^-]|$)","i")},V=/[\x20\t\r\n\f]*[+~]/,Y=/^[^{]+\{\s*\[native code/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,G=/^(?:input|select|textarea|button)$/i,Q=/^h\d$/i,K=/'|\\/g,Z=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,et=/\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,tt=function(e,t){var n="0x"+t-65536;return n!==n?t:0>n?String.fromCharCode(n+65536):String.fromCharCode(55296|n>>10,56320|1023&n)};try{q.call(w.documentElement.childNodes,0)[0].nodeType}catch(nt){q=function(e){var t,n=[];while(t=this[e++])n.push(t);return n}}function rt(e){return Y.test(e+"")}function it(){var e,t=[];return e=function(n,r){return t.push(n+=" ")>i.cacheLength&&delete e[t.shift()],e[n]=r}}function ot(e){return e[x]=!0,e}function at(e){var t=p.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}}function st(e,t,n,r){var i,o,a,s,u,l,f,g,m,v;if((t?t.ownerDocument||t:w)!==p&&c(t),t=t||p,n=n||[],!e||"string"!=typeof e)return n;if(1!==(s=t.nodeType)&&9!==s)return[];if(!d&&!r){if(i=J.exec(e))if(a=i[1]){if(9===s){if(o=t.getElementById(a),!o||!o.parentNode)return n;if(o.id===a)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(a))&&y(t,o)&&o.id===a)return n.push(o),n}else{if(i[2])return H.apply(n,q.call(t.getElementsByTagName(e),0)),n;if((a=i[3])&&T.getByClassName&&t.getElementsByClassName)return H.apply(n,q.call(t.getElementsByClassName(a),0)),n}if(T.qsa&&!h.test(e)){if(f=!0,g=x,m=t,v=9===s&&e,1===s&&"object"!==t.nodeName.toLowerCase()){l=ft(e),(f=t.getAttribute("id"))?g=f.replace(K,"\\$&"):t.setAttribute("id",g),g="[id='"+g+"'] ",u=l.length;while(u--)l[u]=g+dt(l[u]);m=V.test(e)&&t.parentNode||t,v=l.join(",")}if(v)try{return H.apply(n,q.call(m.querySelectorAll(v),0)),n}catch(b){}finally{f||t.removeAttribute("id")}}}return wt(e.replace(W,"$1"),t,n,r)}a=st.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},c=st.setDocument=function(e){var n=e?e.ownerDocument||e:w;return n!==p&&9===n.nodeType&&n.documentElement?(p=n,f=n.documentElement,d=a(n),T.tagNameNoComments=at(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),T.attributes=at(function(e){e.innerHTML="<select></select>";var t=typeof e.lastChild.getAttribute("multiple");return"boolean"!==t&&"string"!==t}),T.getByClassName=at(function(e){return e.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",e.getElementsByClassName&&e.getElementsByClassName("e").length?(e.lastChild.className="e",2===e.getElementsByClassName("e").length):!1}),T.getByName=at(function(e){e.id=x+0,e.innerHTML="<a name='"+x+"'></a><div name='"+x+"'></div>",f.insertBefore(e,f.firstChild);var t=n.getElementsByName&&n.getElementsByName(x).length===2+n.getElementsByName(x+0).length;return T.getIdNotName=!n.getElementById(x),f.removeChild(e),t}),i.attrHandle=at(function(e){return e.innerHTML="<a href='#'></a>",e.firstChild&&typeof e.firstChild.getAttribute!==A&&"#"===e.firstChild.getAttribute("href")})?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},T.getIdNotName?(i.find.ID=function(e,t){if(typeof t.getElementById!==A&&!d){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){return e.getAttribute("id")===t}}):(i.find.ID=function(e,n){if(typeof n.getElementById!==A&&!d){var r=n.getElementById(e);return r?r.id===e||typeof r.getAttributeNode!==A&&r.getAttributeNode("id").value===e?[r]:t:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){var n=typeof e.getAttributeNode!==A&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=T.tagNameNoComments?function(e,n){return typeof n.getElementsByTagName!==A?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.NAME=T.getByName&&function(e,n){return typeof n.getElementsByName!==A?n.getElementsByName(name):t},i.find.CLASS=T.getByClassName&&function(e,n){return typeof n.getElementsByClassName===A||d?t:n.getElementsByClassName(e)},g=[],h=[":focus"],(T.qsa=rt(n.querySelectorAll))&&(at(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||h.push("\\["+_+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||h.push(":checked")}),at(function(e){e.innerHTML="<input type='hidden' i=''/>",e.querySelectorAll("[i^='']").length&&h.push("[*^$]="+_+"*(?:\"\"|'')"),e.querySelectorAll(":enabled").length||h.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),h.push(",.*:")})),(T.matchesSelector=rt(m=f.matchesSelector||f.mozMatchesSelector||f.webkitMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&at(function(e){T.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",R)}),h=RegExp(h.join("|")),g=RegExp(g.join("|")),y=rt(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},v=f.compareDocumentPosition?function(e,t){var r;return e===t?(u=!0,0):(r=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t))?1&r||e.parentNode&&11===e.parentNode.nodeType?e===n||y(w,e)?-1:t===n||y(w,t)?1:0:4&r?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return u=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:0;if(o===a)return ut(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?ut(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},u=!1,[0,0].sort(v),T.detectDuplicates=u,p):p},st.matches=function(e,t){return st(e,null,null,t)},st.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Z,"='$1']"),!(!T.matchesSelector||d||g&&g.test(t)||h.test(t)))try{var n=m.call(e,t);if(n||T.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(r){}return st(t,p,null,[e]).length>0},st.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},st.attr=function(e,t){var n;return(e.ownerDocument||e)!==p&&c(e),d||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):d||T.attributes?e.getAttribute(t):((n=e.getAttributeNode(t))||e.getAttribute(t))&&e[t]===!0?t:n&&n.specified?n.value:null},st.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},st.uniqueSort=function(e){var t,n=[],r=1,i=0;if(u=!T.detectDuplicates,e.sort(v),u){for(;t=e[r];r++)t===e[r-1]&&(i=n.push(r));while(i--)e.splice(n[i],1)}return e};function ut(e,t){var n=t&&e,r=n&&(~t.sourceIndex||j)-(~e.sourceIndex||j);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function lt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ct(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function pt(e){return ot(function(t){return t=+t,ot(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}o=st.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=o(t);return n},i=st.selectors={cacheLength:50,createPseudo:ot,match:U,find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(et,tt),e[3]=(e[4]||e[5]||"").replace(et,tt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||st.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&st.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return U.CHILD.test(e[0])?null:(e[4]?e[2]=e[4]:n&&z.test(n)&&(t=ft(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){return"*"===e?function(){return!0}:(e=e.replace(et,tt).toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[e+" "];return t||(t=RegExp("(^|"+_+")"+e+"("+_+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==A&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=st.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[x]||(m[x]={}),l=c[e]||[],d=l[0]===N&&l[1],f=l[0]===N&&l[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[N,d,f];break}}else if(v&&(l=(t[x]||(t[x]={}))[e])&&l[0]===N)f=l[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[x]||(p[x]={}))[e]=[N,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||st.error("unsupported pseudo: "+e);return r[x]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?ot(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=M.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:ot(function(e){var t=[],n=[],r=s(e.replace(W,"$1"));return r[x]?ot(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:ot(function(e){return function(t){return st(e,t).length>0}}),contains:ot(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:ot(function(e){return X.test(e||"")||st.error("unsupported lang: "+e),e=e.replace(et,tt).toLowerCase(),function(t){var n;do if(n=d?t.getAttribute("xml:lang")||t.getAttribute("lang"):t.lang)return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!i.pseudos.empty(e)},header:function(e){return Q.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:pt(function(){return[0]}),last:pt(function(e,t){return[t-1]}),eq:pt(function(e,t,n){return[0>n?n+t:n]}),even:pt(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:pt(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:pt(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:pt(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}};for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[n]=lt(n);for(n in{submit:!0,reset:!0})i.pseudos[n]=ct(n);function ft(e,t){var n,r,o,a,s,u,l,c=E[e+" "];if(c)return t?0:c.slice(0);s=e,u=[],l=i.preFilter;while(s){(!n||(r=$.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),u.push(o=[])),n=!1,(r=I.exec(s))&&(n=r.shift(),o.push({value:n,type:r[0].replace(W," ")}),s=s.slice(n.length));for(a in i.filter)!(r=U[a].exec(s))||l[a]&&!(r=l[a](r))||(n=r.shift(),o.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?st.error(e):E(e,u).slice(0)}function dt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function ht(e,t,n){var i=t.dir,o=n&&"parentNode"===i,a=C++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,s){var u,l,c,p=N+" "+a;if(s){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[x]||(t[x]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,s)||r,l[1]===!0)return!0}}function gt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function mt(e,t,n,r,i){var o,a=[],s=0,u=e.length,l=null!=t;for(;u>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),l&&t.push(s));return a}function yt(e,t,n,r,i,o){return r&&!r[x]&&(r=yt(r)),i&&!i[x]&&(i=yt(i,o)),ot(function(o,a,s,u){var l,c,p,f=[],d=[],h=a.length,g=o||xt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:mt(g,f,e,s,u),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,u),r){l=mt(y,d),r(l,[],s,u),c=l.length;while(c--)(p=l[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?M.call(o,p):f[c])>-1&&(o[l]=!(a[l]=p))}}else y=mt(y===a?y.splice(h,y.length):y),i?i(null,a,y,u):H.apply(a,y)})}function vt(e){var t,n,r,o=e.length,a=i.relative[e[0].type],s=a||i.relative[" "],u=a?1:0,c=ht(function(e){return e===t},s,!0),p=ht(function(e){return M.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>u;u++)if(n=i.relative[e[u].type])f=[ht(gt(f),n)];else{if(n=i.filter[e[u].type].apply(null,e[u].matches),n[x]){for(r=++u;o>r;r++)if(i.relative[e[r].type])break;return yt(u>1&&gt(f),u>1&&dt(e.slice(0,u-1)).replace(W,"$1"),n,r>u&&vt(e.slice(u,r)),o>r&&vt(e=e.slice(r)),o>r&&dt(e))}f.push(n)}return gt(f)}function bt(e,t){var n=0,o=t.length>0,a=e.length>0,s=function(s,u,c,f,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,T=l,C=s||a&&i.find.TAG("*",d&&u.parentNode||u),k=N+=null==T?1:Math.random()||.1;for(w&&(l=u!==p&&u,r=n);null!=(h=C[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,u,c)){f.push(h);break}w&&(N=k,r=++n)}o&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,o&&b!==v){g=0;while(m=t[g++])m(x,y,u,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=L.call(f));y=mt(y)}H.apply(f,y),w&&!s&&y.length>0&&v+t.length>1&&st.uniqueSort(f)}return w&&(N=k,l=T),x};return o?ot(s):s}s=st.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=ft(e)),n=t.length;while(n--)o=vt(t[n]),o[x]?r.push(o):i.push(o);o=S(e,bt(i,r))}return o};function xt(e,t,n){var r=0,i=t.length;for(;i>r;r++)st(e,t[r],n);return n}function wt(e,t,n,r){var o,a,u,l,c,p=ft(e);if(!r&&1===p.length){if(a=p[0]=p[0].slice(0),a.length>2&&"ID"===(u=a[0]).type&&9===t.nodeType&&!d&&i.relative[a[1].type]){if(t=i.find.ID(u.matches[0].replace(et,tt),t)[0],!t)return n;e=e.slice(a.shift().value.length)}o=U.needsContext.test(e)?0:a.length;while(o--){if(u=a[o],i.relative[l=u.type])break;if((c=i.find[l])&&(r=c(u.matches[0].replace(et,tt),V.test(a[0].type)&&t.parentNode||t))){if(a.splice(o,1),e=r.length&&dt(a),!e)return H.apply(n,q.call(r,0)),n;break}}}return s(e,p)(r,t,d,n,V.test(e)),n}i.pseudos.nth=i.pseudos.eq;function Tt(){}i.filters=Tt.prototype=i.pseudos,i.setFilters=new Tt,c(),st.attr=b.attr,b.find=st,b.expr=st.selectors,b.expr[":"]=b.expr.pseudos,b.unique=st.uniqueSort,b.text=st.getText,b.isXMLDoc=st.isXML,b.contains=st.contains}(e);var at=/Until$/,st=/^(?:parents|prev(?:Until|All))/,ut=/^.[^:#\[\.,]*$/,lt=b.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};b.fn.extend({find:function(e){var t,n,r,i=this.length;if("string"!=typeof e)return r=this,this.pushStack(b(e).filter(function(){for(t=0;i>t;t++)if(b.contains(r[t],this))return!0}));for(n=[],t=0;i>t;t++)b.find(e,this[t],n);return n=this.pushStack(i>1?b.unique(n):n),n.selector=(this.selector?this.selector+" ":"")+e,n},has:function(e){var t,n=b(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(b.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e,!1))},filter:function(e){return this.pushStack(ft(this,e,!0))},is:function(e){return!!e&&("string"==typeof e?lt.test(e)?b(e,this.context).index(this[0])>=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,o=[],a=lt.test(e)||"string"!=typeof e?b(e,t||this.context):0;for(;i>r;r++){n=this[r];while(n&&n.ownerDocument&&n!==t&&11!==n.nodeType){if(a?a.index(n)>-1:b.find.matchesSelector(n,e)){o.push(n);break}n=n.parentNode}}return this.pushStack(o.length>1?b.unique(o):o)},index:function(e){return e?"string"==typeof e?b.inArray(this[0],b(e)):b.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?b(e,t):b.makeArray(e&&e.nodeType?[e]:e),r=b.merge(this.get(),n);return this.pushStack(b.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),b.fn.andSelf=b.fn.addBack;function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}b.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(e,t,n){return b.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(e,t,n){return b.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return b.dir(e,"previousSibling",n)},siblings:function(e){return b.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.merge([],e.childNodes)}},function(e,t){b.fn[e]=function(n,r){var i=b.map(this,t,n);return at.test(e)||(r=n),r&&"string"==typeof r&&(i=b.filter(r,i)),i=this.length>1&&!ct[e]?b.unique(i):i,this.length>1&&st.test(e)&&(i=i.reverse()),this.pushStack(i)}}),b.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),1===t.length?b.find.matchesSelector(t[0],e)?[t[0]]:[]:b.find.matches(e,t)},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!b(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(t=t||0,b.isFunction(t))return b.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return b.grep(e,function(e){return e===t===n});if("string"==typeof t){var r=b.grep(e,function(e){return 1===e.nodeType});if(ut.test(t))return b.filter(t,r,!n);t=b.filter(t,r)}return b.grep(e,function(e){return b.inArray(e,t)>=0===n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/<tbody/i,wt=/<|&#?\w+;/,Tt=/<(?:script|style|link)/i,Nt=/^(?:checkbox|radio)$/i,Ct=/checked\s*(?:[^=]|=\s*.checked.)/i,kt=/^$|\/(?:java|ecma)script/i,Et=/^true\/(.*)/,St=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,At={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:b.support.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},jt=dt(o),Dt=jt.appendChild(o.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,b.fn.extend({text:function(e){return b.access(this,function(e){return e===t?b.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(b.isFunction(e))return this.each(function(t){b(this).wrapAll(e.call(this,t))});if(this[0]){var t=b(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return b.isFunction(e)?this.each(function(t){b(this).wrapInner(e.call(this,t))}):this.each(function(){var t=b(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=b.isFunction(e);return this.each(function(n){b(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){b.nodeName(this,"body")||b(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.insertBefore(e,this.firstChild)})},before:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=0;for(;null!=(n=this[r]);r++)(!e||b.filter(e,[n]).length>0)&&(t||1!==n.nodeType||b.cleanData(Ot(n)),n.parentNode&&(t&&b.contains(n.ownerDocument,n)&&Mt(Ot(n,"script")),n.parentNode.removeChild(n)));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&b.cleanData(Ot(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&b.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return b.clone(this,e,t)})},html:function(e){return b.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!b.support.htmlSerialize&&mt.test(e)||!b.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1></$2>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(b.cleanData(Ot(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(e){var t=b.isFunction(e);return t||"string"==typeof e||(e=b(e).not(this).detach()),this.domManip([e],!0,function(e){var t=this.nextSibling,n=this.parentNode;n&&(b(this).remove(),n.insertBefore(e,t))})},detach:function(e){return this.remove(e,!0)},domManip:function(e,n,r){e=f.apply([],e);var i,o,a,s,u,l,c=0,p=this.length,d=this,h=p-1,g=e[0],m=b.isFunction(g);if(m||!(1>=p||"string"!=typeof g||b.support.checkClone)&&Ct.test(g))return this.each(function(i){var o=d.eq(i);m&&(e[0]=g.call(this,i,n?o.html():t)),o.domManip(e,n,r)});if(p&&(l=b.buildFragment(e,this[0].ownerDocument,!1,this),i=l.firstChild,1===l.childNodes.length&&(l=i),i)){for(n=n&&b.nodeName(i,"tr"),s=b.map(Ot(l,"script"),Ht),a=s.length;p>c;c++)o=l,c!==h&&(o=b.clone(o,!0,!0),a&&b.merge(s,Ot(o,"script"))),r.call(n&&b.nodeName(this[c],"table")?Lt(this[c],"tbody"):this[c],o,c);if(a)for(u=s[s.length-1].ownerDocument,b.map(s,qt),c=0;a>c;c++)o=s[c],kt.test(o.type||"")&&!b._data(o,"globalEval")&&b.contains(u,o)&&(o.src?b.ajax({url:o.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):b.globalEval((o.text||o.textContent||o.innerHTML||"").replace(St,"")));l=i=null}return this}});function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function Ht(e){var t=e.getAttributeNode("type");return e.type=(t&&t.specified)+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function Mt(e,t){var n,r=0;for(;null!=(n=e[r]);r++)b._data(n,"globalEval",!t||b._data(t[r],"globalEval"))}function _t(e,t){if(1===t.nodeType&&b.hasData(e)){var n,r,i,o=b._data(e),a=b._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)b.event.add(t,n,s[n][r])}a.data&&(a.data=b.extend({},a.data))}}function Ft(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!b.support.noCloneEvent&&t[b.expando]){i=b._data(t);for(r in i.events)b.removeEvent(t,r,i.handle);t.removeAttribute(b.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),b.support.html5Clone&&e.innerHTML&&!b.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Nt.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}b.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){b.fn[e]=function(e){var n,r=0,i=[],o=b(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),b(o[r])[t](n),d.apply(i,n.get());return this.pushStack(i)}});function Ot(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||b.nodeName(o,n)?s.push(o):b.merge(s,Ot(o,n));return n===t||n&&b.nodeName(e,n)?b.merge([e],s):s}function Bt(e){Nt.test(e.type)&&(e.defaultChecked=e.checked)}b.extend({clone:function(e,t,n){var r,i,o,a,s,u=b.contains(e.ownerDocument,e);if(b.support.html5Clone||b.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(b.support.noCloneEvent&&b.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||b.isXMLDoc(e)))for(r=Ot(o),s=Ot(e),a=0;null!=(i=s[a]);++a)r[a]&&Ft(i,r[a]);if(t)if(n)for(s=s||Ot(e),r=r||Ot(o),a=0;null!=(i=s[a]);a++)_t(i,r[a]);else _t(e,o);return r=Ot(o,"script"),r.length>0&&Mt(r,!u&&Ot(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,u,l,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===b.type(o))b.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),u=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[u]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1></$2>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!b.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!b.support.tbody){o="table"!==u||xt.test(o)?"<table>"!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)b.nodeName(l=o.childNodes[i],"tbody")&&!l.childNodes.length&&o.removeChild(l)
}b.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),b.support.appendChecked||b.grep(Ot(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===b.inArray(o,r))&&(a=b.contains(o.ownerDocument,o),s=Ot(f.appendChild(o),"script"),a&&Mt(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,u=b.expando,l=b.cache,p=b.support.deleteExpando,f=b.event.special;for(;null!=(n=e[s]);s++)if((t||b.acceptData(n))&&(o=n[u],a=o&&l[o])){if(a.events)for(r in a.events)f[r]?b.event.remove(n,r):b.removeEvent(n,r,a.handle);l[o]&&(delete l[o],p?delete n[u]:typeof n.removeAttribute!==i?n.removeAttribute(u):n[u]=null,c.push(o))}}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+x+")(.*)$","i"),Yt=RegExp("^("+x+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+x+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===b.css(e,"display")||!b.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=b._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=b._data(r,"olddisplay",un(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&b._data(r,"olddisplay",i?n:b.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}b.fn.extend({css:function(e,n){return b.access(this,function(e,n,r){var i,o,a={},s=0;if(b.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=b.css(e,n[s],!1,o);return a}return r!==t?b.style(e,n,r):b.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:nn(this))?b(this).show():b(this).hide()})}}),b.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":b.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,u=b.camelCase(n),l=e.style;if(n=b.cssProps[u]||(b.cssProps[u]=tn(l,u)),s=b.cssHooks[n]||b.cssHooks[u],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:l[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(b.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||b.cssNumber[u]||(r+="px"),b.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(l[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{l[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,u=b.camelCase(n);return n=b.cssProps[u]||(b.cssProps[u]=tn(e.style,u)),s=b.cssHooks[n]||b.cssHooks[u],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||b.isNumeric(o)?o||0:a):a},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s.getPropertyValue(n)||s[n]:t,l=e.style;return s&&(""!==u||b.contains(e.ownerDocument,e)||(u=b.style(e,n)),Yt.test(u)&&Ut.test(n)&&(i=l.width,o=l.minWidth,a=l.maxWidth,l.minWidth=l.maxWidth=l.width=u,u=s.width,l.width=i,l.minWidth=o,l.maxWidth=a)),u}):o.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s[n]:t,l=e.style;return null==u&&l&&l[n]&&(u=l[n]),Yt.test(u)&&!zt.test(n)&&(i=l.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),l.left="fontSize"===n?"1em":u,u=l.pixelLeft+"px",l.left=i,a&&(o.left=a)),""===u?"auto":u});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=b.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=b.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=b.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=b.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=b.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(b.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function un(e){var t=o,n=Gt[e];return n||(n=ln(e,t),"none"!==n&&n||(Pt=(Pt||b("<iframe frameborder='0' width='0' height='0'/>").css("cssText","display:block !important")).appendTo(t.documentElement),t=(Pt[0].contentWindow||Pt[0].contentDocument).document,t.write("<!doctype html><html><body>"),t.close(),n=ln(e,t),Pt.detach()),Gt[e]=n),n}function ln(e,t){var n=b(t.createElement(e)).appendTo(t.body),r=b.css(n[0],"display");return n.remove(),r}b.each(["height","width"],function(e,n){b.cssHooks[n]={get:function(e,r,i){return r?0===e.offsetWidth&&Xt.test(b.css(e,"display"))?b.swap(e,Qt,function(){return sn(e,n,i)}):sn(e,n,i):t},set:function(e,t,r){var i=r&&Rt(e);return on(e,t,r?an(e,n,r,b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,i),i):0)}}}),b.support.opacity||(b.cssHooks.opacity={get:function(e,t){return It.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=b.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===b.trim(o.replace($t,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=$t.test(o)?o.replace($t,i):o+" "+i)}}),b(function(){b.support.reliableMarginRight||(b.cssHooks.marginRight={get:function(e,n){return n?b.swap(e,{display:"inline-block"},Wt,[e,"marginRight"]):t}}),!b.support.pixelPosition&&b.fn.position&&b.each(["top","left"],function(e,n){b.cssHooks[n]={get:function(e,r){return r?(r=Wt(e,n),Yt.test(r)?b(e).position()[n]+"px":r):t}}})}),b.expr&&b.expr.filters&&(b.expr.filters.hidden=function(e){return 0>=e.offsetWidth&&0>=e.offsetHeight||!b.support.reliableHiddenOffsets&&"none"===(e.style&&e.style.display||b.css(e,"display"))},b.expr.filters.visible=function(e){return!b.expr.filters.hidden(e)}),b.each({margin:"",padding:"",border:"Width"},function(e,t){b.cssHooks[e+t]={expand:function(n){var r=0,i={},o="string"==typeof n?n.split(" "):[n];for(;4>r;r++)i[e+Zt[r]+t]=o[r]||o[r-2]||o[0];return i}},Ut.test(e)||(b.cssHooks[e+t].set=on)});var cn=/%20/g,pn=/\[\]$/,fn=/\r?\n/g,dn=/^(?:submit|button|image|reset|file)$/i,hn=/^(?:input|select|textarea|keygen)/i;b.fn.extend({serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=b.prop(this,"elements");return e?b.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!b(this).is(":disabled")&&hn.test(this.nodeName)&&!dn.test(e)&&(this.checked||!Nt.test(e))}).map(function(e,t){var n=b(this).val();return null==n?null:b.isArray(n)?b.map(n,function(e){return{name:t.name,value:e.replace(fn,"\r\n")}}):{name:t.name,value:n.replace(fn,"\r\n")}}).get()}}),b.param=function(e,n){var r,i=[],o=function(e,t){t=b.isFunction(t)?t():null==t?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(n===t&&(n=b.ajaxSettings&&b.ajaxSettings.traditional),b.isArray(e)||e.jquery&&!b.isPlainObject(e))b.each(e,function(){o(this.name,this.value)});else for(r in e)gn(r,e[r],n,o);return i.join("&").replace(cn,"+")};function gn(e,t,n,r){var i;if(b.isArray(t))b.each(t,function(t,i){n||pn.test(e)?r(e,i):gn(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==b.type(t))r(e,t);else for(i in t)gn(e+"["+i+"]",t[i],n,r)}b.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){b.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),b.fn.hover=function(e,t){return this.mouseenter(e).mouseleave(t||e)};var mn,yn,vn=b.now(),bn=/\?/,xn=/#.*$/,wn=/([?&])_=[^&]*/,Tn=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Nn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Cn=/^(?:GET|HEAD)$/,kn=/^\/\//,En=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,Sn=b.fn.load,An={},jn={},Dn="*/".concat("*");try{yn=a.href}catch(Ln){yn=o.createElement("a"),yn.href="",yn=yn.href}mn=En.exec(yn.toLowerCase())||[];function Hn(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(w)||[];if(b.isFunction(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function qn(e,n,r,i){var o={},a=e===jn;function s(u){var l;return o[u]=!0,b.each(e[u]||[],function(e,u){var c=u(n,r,i);return"string"!=typeof c||a||o[c]?a?!(l=c):t:(n.dataTypes.unshift(c),s(c),!1)}),l}return s(n.dataTypes[0])||!o["*"]&&s("*")}function Mn(e,n){var r,i,o=b.ajaxSettings.flatOptions||{};for(i in n)n[i]!==t&&((o[i]?e:r||(r={}))[i]=n[i]);return r&&b.extend(!0,e,r),e}b.fn.load=function(e,n,r){if("string"!=typeof e&&Sn)return Sn.apply(this,arguments);var i,o,a,s=this,u=e.indexOf(" ");return u>=0&&(i=e.slice(u,e.length),e=e.slice(0,u)),b.isFunction(n)?(r=n,n=t):n&&"object"==typeof n&&(a="POST"),s.length>0&&b.ajax({url:e,type:a,dataType:"html",data:n}).done(function(e){o=arguments,s.html(i?b("<div>").append(b.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,o||[e.responseText,t,e])}),this},b.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){b.fn[t]=function(e){return this.on(t,e)}}),b.each(["get","post"],function(e,n){b[n]=function(e,r,i,o){return b.isFunction(r)&&(o=o||i,i=r,r=t),b.ajax({url:e,type:n,dataType:o,data:r,success:i})}}),b.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:yn,type:"GET",isLocal:Nn.test(mn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Dn,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?Mn(Mn(e,b.ajaxSettings),t):Mn(b.ajaxSettings,e)},ajaxPrefilter:Hn(An),ajaxTransport:Hn(jn),ajax:function(e,n){"object"==typeof e&&(n=e,e=t),n=n||{};var r,i,o,a,s,u,l,c,p=b.ajaxSetup({},n),f=p.context||p,d=p.context&&(f.nodeType||f.jquery)?b(f):b.event,h=b.Deferred(),g=b.Callbacks("once memory"),m=p.statusCode||{},y={},v={},x=0,T="canceled",N={readyState:0,getResponseHeader:function(e){var t;if(2===x){if(!c){c={};while(t=Tn.exec(a))c[t[1].toLowerCase()]=t[2]}t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===x?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return x||(e=v[n]=v[n]||e,y[e]=t),this},overrideMimeType:function(e){return x||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>x)for(t in e)m[t]=[m[t],e[t]];else N.always(e[N.status]);return this},abort:function(e){var t=e||T;return l&&l.abort(t),k(0,t),this}};if(h.promise(N).complete=g.add,N.success=N.done,N.error=N.fail,p.url=((e||p.url||yn)+"").replace(xn,"").replace(kn,mn[1]+"//"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=b.trim(p.dataType||"*").toLowerCase().match(w)||[""],null==p.crossDomain&&(r=En.exec(p.url.toLowerCase()),p.crossDomain=!(!r||r[1]===mn[1]&&r[2]===mn[2]&&(r[3]||("http:"===r[1]?80:443))==(mn[3]||("http:"===mn[1]?80:443)))),p.data&&p.processData&&"string"!=typeof p.data&&(p.data=b.param(p.data,p.traditional)),qn(An,p,n,N),2===x)return N;u=p.global,u&&0===b.active++&&b.event.trigger("ajaxStart"),p.type=p.type.toUpperCase(),p.hasContent=!Cn.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(bn.test(o)?"&":"?")+p.data,delete p.data),p.cache===!1&&(p.url=wn.test(o)?o.replace(wn,"$1_="+vn++):o+(bn.test(o)?"&":"?")+"_="+vn++)),p.ifModified&&(b.lastModified[o]&&N.setRequestHeader("If-Modified-Since",b.lastModified[o]),b.etag[o]&&N.setRequestHeader("If-None-Match",b.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&N.setRequestHeader("Content-Type",p.contentType),N.setRequestHeader("Accept",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+("*"!==p.dataTypes[0]?", "+Dn+"; q=0.01":""):p.accepts["*"]);for(i in p.headers)N.setRequestHeader(i,p.headers[i]);if(p.beforeSend&&(p.beforeSend.call(f,N,p)===!1||2===x))return N.abort();T="abort";for(i in{success:1,error:1,complete:1})N[i](p[i]);if(l=qn(jn,p,n,N)){N.readyState=1,u&&d.trigger("ajaxSend",[N,p]),p.async&&p.timeout>0&&(s=setTimeout(function(){N.abort("timeout")},p.timeout));try{x=1,l.send(y,k)}catch(C){if(!(2>x))throw C;k(-1,C)}}else k(-1,"No Transport");function k(e,n,r,i){var c,y,v,w,T,C=n;2!==x&&(x=2,s&&clearTimeout(s),l=t,a=i||"",N.readyState=e>0?4:0,r&&(w=_n(p,N,r)),e>=200&&300>e||304===e?(p.ifModified&&(T=N.getResponseHeader("Last-Modified"),T&&(b.lastModified[o]=T),T=N.getResponseHeader("etag"),T&&(b.etag[o]=T)),204===e?(c=!0,C="nocontent"):304===e?(c=!0,C="notmodified"):(c=Fn(p,w),C=c.state,y=c.data,v=c.error,c=!v)):(v=C,(e||!C)&&(C="error",0>e&&(e=0))),N.status=e,N.statusText=(n||C)+"",c?h.resolveWith(f,[y,C,N]):h.rejectWith(f,[N,C,v]),N.statusCode(m),m=t,u&&d.trigger(c?"ajaxSuccess":"ajaxError",[N,p,c?y:v]),g.fireWith(f,[N,C]),u&&(d.trigger("ajaxComplete",[N,p]),--b.active||b.event.trigger("ajaxStop")))}return N},getScript:function(e,n){return b.get(e,t,n,"script")},getJSON:function(e,t,n){return b.get(e,t,n,"json")}});function _n(e,n,r){var i,o,a,s,u=e.contents,l=e.dataTypes,c=e.responseFields;for(s in c)s in r&&(n[c[s]]=r[s]);while("*"===l[0])l.shift(),o===t&&(o=e.mimeType||n.getResponseHeader("Content-Type"));if(o)for(s in u)if(u[s]&&u[s].test(o)){l.unshift(s);break}if(l[0]in r)a=l[0];else{for(s in r){if(!l[0]||e.converters[s+" "+l[0]]){a=s;break}i||(i=s)}a=a||i}return a?(a!==l[0]&&l.unshift(a),r[a]):t}function Fn(e,t){var n,r,i,o,a={},s=0,u=e.dataTypes.slice(),l=u[0];if(e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u[1])for(i in e.converters)a[i.toLowerCase()]=e.converters[i];for(;r=u[++s];)if("*"!==r){if("*"!==l&&l!==r){if(i=a[l+" "+r]||a["* "+r],!i)for(n in a)if(o=n.split(" "),o[1]===r&&(i=a[l+" "+o[0]]||a["* "+o[0]])){i===!0?i=a[n]:a[n]!==!0&&(r=o[0],u.splice(s--,0,r));break}if(i!==!0)if(i&&e["throws"])t=i(t);else try{t=i(t)}catch(c){return{state:"parsererror",error:i?c:"No conversion from "+l+" to "+r}}}l=r}return{state:"success",data:t}}b.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return b.globalEval(e),e}}}),b.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),b.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=o.head||b("head")[0]||o.documentElement;return{send:function(t,i){n=o.createElement("script"),n.async=!0,e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readyState))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,"success"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var On=[],Bn=/(=)\?(?=&|$)|\?\?/;b.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=On.pop()||b.expando+"_"+vn++;return this[e]=!0,e}}),b.ajaxPrefilter("json jsonp",function(n,r,i){var o,a,s,u=n.jsonp!==!1&&(Bn.test(n.url)?"url":"string"==typeof n.data&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Bn.test(n.data)&&"data");return u||"jsonp"===n.dataTypes[0]?(o=n.jsonpCallback=b.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,u?n[u]=n[u].replace(Bn,"$1"+o):n.jsonp!==!1&&(n.url+=(bn.test(n.url)?"&":"?")+n.jsonp+"="+o),n.converters["script json"]=function(){return s||b.error(o+" was not called"),s[0]},n.dataTypes[0]="json",a=e[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,On.push(o)),s&&b.isFunction(a)&&a(s[0]),s=a=t}),"script"):t});var Pn,Rn,Wn=0,$n=e.ActiveXObject&&function(){var e;for(e in Pn)Pn[e](t,!0)};function In(){try{return new e.XMLHttpRequest}catch(t){}}function zn(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}b.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&In()||zn()}:In,Rn=b.ajaxSettings.xhr(),b.support.cors=!!Rn&&"withCredentials"in Rn,Rn=b.support.ajax=!!Rn,Rn&&b.ajaxTransport(function(n){if(!n.crossDomain||b.support.cors){var r;return{send:function(i,o){var a,s,u=n.xhr();if(n.username?u.open(n.type,n.url,n.async,n.username,n.password):u.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)u[s]=n.xhrFields[s];n.mimeType&&u.overrideMimeType&&u.overrideMimeType(n.mimeType),n.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");try{for(s in i)u.setRequestHeader(s,i[s])}catch(l){}u.send(n.hasContent&&n.data||null),r=function(e,i){var s,l,c,p;try{if(r&&(i||4===u.readyState))if(r=t,a&&(u.onreadystatechange=b.noop,$n&&delete Pn[a]),i)4!==u.readyState&&u.abort();else{p={},s=u.status,l=u.getAllResponseHeaders(),"string"==typeof u.responseText&&(p.text=u.responseText);try{c=u.statusText}catch(f){c=""}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=p.text?200:404}}catch(d){i||o(-1,d)}p&&o(s,c,p,l)},n.async?4===u.readyState?setTimeout(r):(a=++Wn,$n&&(Pn||(Pn={},b(e).unload($n)),Pn[a]=r),u.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Xn,Un,Vn=/^(?:toggle|show|hide)$/,Yn=RegExp("^(?:([+-])=|)("+x+")([a-z%]*)$","i"),Jn=/queueHooks$/,Gn=[nr],Qn={"*":[function(e,t){var n,r,i=this.createTween(e,t),o=Yn.exec(t),a=i.cur(),s=+a||0,u=1,l=20;if(o){if(n=+o[2],r=o[3]||(b.cssNumber[e]?"":"px"),"px"!==r&&s){s=b.css(i.elem,e,!0)||n||1;do u=u||".5",s/=u,b.style(i.elem,e,s+r);while(u!==(u=i.cur()/a)&&1!==u&&--l)}i.unit=r,i.start=s,i.end=o[1]?s+(o[1]+1)*n:n}return i}]};function Kn(){return setTimeout(function(){Xn=t}),Xn=b.now()}function Zn(e,t){b.each(t,function(t,n){var r=(Qn[t]||[]).concat(Qn["*"]),i=0,o=r.length;for(;o>i;i++)if(r[i].call(e,t,n))return})}function er(e,t,n){var r,i,o=0,a=Gn.length,s=b.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;var t=Xn||Kn(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,a=0,u=l.tweens.length;for(;u>a;a++)l.tweens[a].run(o);return s.notifyWith(e,[l,o,n]),1>o&&u?n:(s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:b.extend({},t),opts:b.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Xn||Kn(),duration:n.duration,tweens:[],createTween:function(t,n){var r=b.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)l.tweens[n].run(1);return t?s.resolveWith(e,[l,t]):s.rejectWith(e,[l,t]),this}}),c=l.props;for(tr(c,l.opts.specialEasing);a>o;o++)if(r=Gn[o].call(l,e,c,l.opts))return r;return Zn(l,c),b.isFunction(l.opts.start)&&l.opts.start.call(e,l),b.fx.timer(b.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function tr(e,t){var n,r,i,o,a;for(i in e)if(r=b.camelCase(i),o=t[r],n=e[i],b.isArray(n)&&(o=n[1],n=e[i]=n[0]),i!==r&&(e[r]=n,delete e[i]),a=b.cssHooks[r],a&&"expand"in a){n=a.expand(n),delete e[r];for(i in n)i in e||(e[i]=n[i],t[i]=o)}else t[r]=o}b.Animation=b.extend(er,{tweener:function(e,t){b.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],Qn[n]=Qn[n]||[],Qn[n].unshift(t)},prefilter:function(e,t){t?Gn.unshift(e):Gn.push(e)}});function nr(e,t,n){var r,i,o,a,s,u,l,c,p,f=this,d=e.style,h={},g=[],m=e.nodeType&&nn(e);n.queue||(c=b._queueHooks(e,"fx"),null==c.unqueued&&(c.unqueued=0,p=c.empty.fire,c.empty.fire=function(){c.unqueued||p()}),c.unqueued++,f.always(function(){f.always(function(){c.unqueued--,b.queue(e,"fx").length||c.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[d.overflow,d.overflowX,d.overflowY],"inline"===b.css(e,"display")&&"none"===b.css(e,"float")&&(b.support.inlineBlockNeedsLayout&&"inline"!==un(e.nodeName)?d.zoom=1:d.display="inline-block")),n.overflow&&(d.overflow="hidden",b.support.shrinkWrapBlocks||f.always(function(){d.overflow=n.overflow[0],d.overflowX=n.overflow[1],d.overflowY=n.overflow[2]}));for(i in t)if(a=t[i],Vn.exec(a)){if(delete t[i],u=u||"toggle"===a,a===(m?"hide":"show"))continue;g.push(i)}if(o=g.length){s=b._data(e,"fxshow")||b._data(e,"fxshow",{}),"hidden"in s&&(m=s.hidden),u&&(s.hidden=!m),m?b(e).show():f.done(function(){b(e).hide()}),f.done(function(){var t;b._removeData(e,"fxshow");for(t in h)b.style(e,t,h[t])});for(i=0;o>i;i++)r=g[i],l=f.createTween(r,m?s[r]:0),h[r]=s[r]||b.style(e,r),r in s||(s[r]=l.start,m&&(l.end=l.start,l.start="width"===r||"height"===r?1:0))}}function rr(e,t,n,r,i){return new rr.prototype.init(e,t,n,r,i)}b.Tween=rr,rr.prototype={constructor:rr,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(b.cssNumber[n]?"":"px")},cur:function(){var e=rr.propHooks[this.prop];return e&&e.get?e.get(this):rr.propHooks._default.get(this)},run:function(e){var t,n=rr.propHooks[this.prop];return this.pos=t=this.options.duration?b.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):rr.propHooks._default.set(this),this}},rr.prototype.init.prototype=rr.prototype,rr.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=b.css(e.elem,e.prop,""),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){b.fx.step[e.prop]?b.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[b.cssProps[e.prop]]||b.cssHooks[e.prop])?b.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},rr.propHooks.scrollTop=rr.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},b.each(["toggle","show","hide"],function(e,t){var n=b.fn[t];b.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ir(t,!0),e,r,i)}}),b.fn.extend({fadeTo:function(e,t,n,r){return this.filter(nn).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=b.isEmptyObject(e),o=b.speed(t,n,r),a=function(){var t=er(this,b.extend({},e),o);a.finish=function(){t.stop(!0)},(i||b._data(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return"string"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=null!=e&&e+"queueHooks",o=b.timers,a=b._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&Jn.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].elem!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&b.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=b._data(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=b.timers,a=r?r.length:0;for(n.finish=!0,b.queue(this,e,[]),i&&i.cur&&i.cur.finish&&i.cur.finish.call(this),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function ir(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=Zt[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}b.each({slideDown:ir("show"),slideUp:ir("hide"),slideToggle:ir("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){b.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),b.speed=function(e,t,n){var r=e&&"object"==typeof e?b.extend({},e):{complete:n||!n&&t||b.isFunction(e)&&e,duration:e,easing:n&&t||t&&!b.isFunction(t)&&t};return r.duration=b.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in b.fx.speeds?b.fx.speeds[r.duration]:b.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){b.isFunction(r.old)&&r.old.call(this),r.queue&&b.dequeue(this,r.queue)},r},b.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},b.timers=[],b.fx=rr.prototype.init,b.fx.tick=function(){var e,n=b.timers,r=0;for(Xn=b.now();n.length>r;r++)e=n[r],e()||n[r]!==e||n.splice(r--,1);n.length||b.fx.stop(),Xn=t},b.fx.timer=function(e){e()&&b.timers.push(e)&&b.fx.start()},b.fx.interval=13,b.fx.start=function(){Un||(Un=setInterval(b.fx.tick,b.fx.interval))},b.fx.stop=function(){clearInterval(Un),Un=null},b.fx.speeds={slow:600,fast:200,_default:400},b.fx.step={},b.expr&&b.expr.filters&&(b.expr.filters.animated=function(e){return b.grep(b.timers,function(t){return e===t.elem}).length}),b.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){b.offset.setOffset(this,e,t)});var n,r,o={top:0,left:0},a=this[0],s=a&&a.ownerDocument;if(s)return n=s.documentElement,b.contains(n,a)?(typeof a.getBoundingClientRect!==i&&(o=a.getBoundingClientRect()),r=or(s),{top:o.top+(r.pageYOffset||n.scrollTop)-(n.clientTop||0),left:o.left+(r.pageXOffset||n.scrollLeft)-(n.clientLeft||0)}):o},b.offset={setOffset:function(e,t,n){var r=b.css(e,"position");"static"===r&&(e.style.position="relative");var i=b(e),o=i.offset(),a=b.css(e,"top"),s=b.css(e,"left"),u=("absolute"===r||"fixed"===r)&&b.inArray("auto",[a,s])>-1,l={},c={},p,f;u?(c=i.position(),p=c.top,f=c.left):(p=parseFloat(a)||0,f=parseFloat(s)||0),b.isFunction(t)&&(t=t.call(e,n,o)),null!=t.top&&(l.top=t.top-o.top+p),null!=t.left&&(l.left=t.left-o.left+f),"using"in t?t.using.call(e,l):i.css(l)}},b.fn.extend({position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===b.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),b.nodeName(e[0],"html")||(n=e.offset()),n.top+=b.css(e[0],"borderTopWidth",!0),n.left+=b.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-b.css(r,"marginTop",!0),left:t.left-n.left-b.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||o.documentElement;while(e&&!b.nodeName(e,"html")&&"static"===b.css(e,"position"))e=e.offsetParent;return e||o.documentElement})}}),b.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);b.fn[e]=function(i){return b.access(this,function(e,i,o){var a=or(e);return o===t?a?n in a?a[n]:a.document.documentElement[i]:e[i]:(a?a.scrollTo(r?b(a).scrollLeft():o,r?o:b(a).scrollTop()):e[i]=o,t)},e,i,arguments.length,null)}});function or(e){return b.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}b.each({Height:"height",Width:"width"},function(e,n){b.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){b.fn[i]=function(i,o){var a=arguments.length&&(r||"boolean"!=typeof i),s=r||(i===!0||o===!0?"margin":"border");return b.access(this,function(n,r,i){var o;return b.isWindow(n)?n.document.documentElement["client"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body["scroll"+e],o["scroll"+e],n.body["offset"+e],o["offset"+e],o["client"+e])):i===t?b.css(n,r,s):b.style(n,r,i,s)},n,a?i:t,a,null)}})}),e.jQuery=e.$=b,"function"==typeof define&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return b})})(window);/*
 Highcharts JS v2.3.5 (2012-12-19)

 (c) 2009-2012 Torstein Hønsi

 License: www.highcharts.com/license
*/
(function(){function x(a,b){var c;a||(a={});for(c in b)a[c]=b[c];return a}function ia(){for(var a=0,b=arguments,c=b.length,d={};a<c;a++)d[b[a++]]=b[a];return d}function z(a,b){return parseInt(a,b||10)}function ja(a){return typeof a==="string"}function Y(a){return typeof a==="object"}function Ia(a){return Object.prototype.toString.call(a)==="[object Array]"}function Da(a){return typeof a==="number"}function ka(a){return K.log(a)/K.LN10}function aa(a){return K.pow(10,a)}function ta(a,b){for(var c=a.length;c--;)if(a[c]===
b){a.splice(c,1);break}}function r(a){return a!==A&&a!==null}function w(a,b,c){var d,e;if(ja(b))r(c)?a.setAttribute(b,c):a&&a.getAttribute&&(e=a.getAttribute(b));else if(r(b)&&Y(b))for(d in b)a.setAttribute(d,b[d]);return e}function la(a){return Ia(a)?a:[a]}function n(){var a=arguments,b,c,d=a.length;for(b=0;b<d;b++)if(c=a[b],typeof c!=="undefined"&&c!==null)return c}function I(a,b){if(Ea&&b&&b.opacity!==A)b.filter="alpha(opacity="+b.opacity*100+")";x(a.style,b)}function T(a,b,c,d,e){a=C.createElement(a);
b&&x(a,b);e&&I(a,{padding:0,border:Q,margin:0});c&&I(a,c);d&&d.appendChild(a);return a}function ba(a,b){var c=function(){};c.prototype=new a;x(c.prototype,b);return c}function Ja(a,b,c,d){var e=N.lang,f=a;b===-1?(b=(a||0).toString(),a=b.indexOf(".")>-1?b.split(".")[1].length:0):a=isNaN(b=M(b))?2:b;var b=a,c=c===void 0?e.decimalPoint:c,d=d===void 0?e.thousandsSep:d,e=f<0?"-":"",a=String(z(f=M(+f||0).toFixed(b))),g=a.length>3?a.length%3:0;return e+(g?a.substr(0,g)+d:"")+a.substr(g).replace(/(\d{3})(?=\d)/g,
"$1"+d)+(b?c+M(f-a).toFixed(b).slice(2):"")}function ua(a,b){return Array((b||2)+1-String(a).length).join(0)+a}function hb(a,b,c,d){var e,c=n(c,1);e=a/c;b||(b=[1,2,2.5,5,10],d&&d.allowDecimals===!1&&(c===1?b=[1,2,5,10]:c<=0.1&&(b=[1/c])));for(d=0;d<b.length;d++)if(a=b[d],e<=(b[d]+(b[d+1]||b[d]))/2)break;a*=c;return a}function Ab(a,b){var c=b||[[Bb,[1,2,5,10,20,25,50,100,200,500]],[ib,[1,2,5,10,15,30]],[Va,[1,2,5,10,15,30]],[Ka,[1,2,3,4,6,8,12]],[ma,[1,2]],[Wa,[1,2]],[La,[1,2,3,4,6]],[va,null]],d=
c[c.length-1],e=D[d[0]],f=d[1],g;for(g=0;g<c.length;g++)if(d=c[g],e=D[d[0]],f=d[1],c[g+1]&&a<=(e*f[f.length-1]+D[c[g+1][0]])/2)break;e===D[va]&&a<5*e&&(f=[1,2,5]);e===D[va]&&a<5*e&&(f=[1,2,5]);c=hb(a/e,f);return{unitRange:e,count:c,unitName:d[0]}}function Cb(a,b,c,d){var e=[],f={},g=N.global.useUTC,h,i=new Date(b),j=a.unitRange,k=a.count;if(r(b)){j>=D[ib]&&(i.setMilliseconds(0),i.setSeconds(j>=D[Va]?0:k*U(i.getSeconds()/k)));if(j>=D[Va])i[Db](j>=D[Ka]?0:k*U(i[jb]()/k));if(j>=D[Ka])i[Eb](j>=D[ma]?
0:k*U(i[kb]()/k));if(j>=D[ma])i[lb](j>=D[La]?1:k*U(i[Ma]()/k));j>=D[La]&&(i[Fb](j>=D[va]?0:k*U(i[Xa]()/k)),h=i[Ya]());j>=D[va]&&(h-=h%k,i[Gb](h));if(j===D[Wa])i[lb](i[Ma]()-i[mb]()+n(d,1));b=1;h=i[Ya]();for(var d=i.getTime(),l=i[Xa](),m=i[Ma](),i=g?0:(864E5+i.getTimezoneOffset()*6E4)%864E5;d<c;)e.push(d),j===D[va]?d=Za(h+b*k,0):j===D[La]?d=Za(h,l+b*k):!g&&(j===D[ma]||j===D[Wa])?d=Za(h,l,m+b*k*(j===D[ma]?1:7)):(d+=j*k,j<=D[Ka]&&d%D[ma]===i&&(f[d]=ma)),b++;e.push(d)}e.info=x(a,{higherRanks:f,totalRange:j*
k});return e}function Hb(){this.symbol=this.color=0}function Ib(a,b){var c=a.length,d,e;for(e=0;e<c;e++)a[e].ss_i=e;a.sort(function(a,c){d=b(a,c);return d===0?a.ss_i-c.ss_i:d});for(e=0;e<c;e++)delete a[e].ss_i}function Fa(a){for(var b=a.length,c=a[0];b--;)a[b]<c&&(c=a[b]);return c}function wa(a){for(var b=a.length,c=a[0];b--;)a[b]>c&&(c=a[b]);return c}function Ga(a,b){for(var c in a)a[c]&&a[c]!==b&&a[c].destroy&&a[c].destroy(),delete a[c]}function Na(a){$a||($a=T(ga));a&&$a.appendChild(a);$a.innerHTML=
""}function Oa(a,b){var c="Highcharts error #"+a+": www.highcharts.com/errors/"+a;if(b)throw c;else L.console&&console.log(c)}function da(a){return parseFloat(a.toPrecision(14))}function xa(a,b){Pa=n(a,b.animation)}function Jb(){var a=N.global.useUTC,b=a?"getUTC":"get",c=a?"setUTC":"set";Za=a?Date.UTC:function(a,b,c,g,h,i){return(new Date(a,b,n(c,1),n(g,0),n(h,0),n(i,0))).getTime()};jb=b+"Minutes";kb=b+"Hours";mb=b+"Day";Ma=b+"Date";Xa=b+"Month";Ya=b+"FullYear";Db=c+"Minutes";Eb=c+"Hours";lb=c+"Date";
Fb=c+"Month";Gb=c+"FullYear"}function ya(){}function Qa(a,b,c){this.axis=a;this.pos=b;this.type=c||"";this.isNew=!0;c||this.addLabel()}function nb(a,b){this.axis=a;if(b)this.options=b,this.id=b.id;return this}function Kb(a,b,c,d,e,f){var g=a.chart.inverted;this.axis=a;this.isNegative=c;this.options=b;this.x=d;this.stack=e;this.percent=f==="percent";this.alignOptions={align:b.align||(g?c?"left":"right":"center"),verticalAlign:b.verticalAlign||(g?"middle":c?"bottom":"top"),y:n(b.y,g?4:c?14:-6),x:n(b.x,
g?c?-6:6:0)};this.textAlign=b.textAlign||(g?c?"right":"left":"center")}function ob(){this.init.apply(this,arguments)}function pb(a,b){var c=b.borderWidth,d=b.style,e=z(d.padding);this.chart=a;this.options=b;this.crosshairs=[];this.now={x:0,y:0};this.isHidden=!0;this.label=a.renderer.label("",0,0,b.shape,null,null,b.useHTML,null,"tooltip").attr({padding:e,fill:b.backgroundColor,"stroke-width":c,r:b.borderRadius,zIndex:8}).css(d).css({padding:0}).hide().add();V||this.label.shadow(b.shadow);this.shared=
b.shared}function qb(a,b){var c=V?"":b.chart.zoomType;this.zoomX=/x/.test(c);this.zoomY=/y/.test(c);this.options=b;this.chart=a;this.init(a,b.tooltip)}function rb(a){this.init(a)}function sb(){this.init.apply(this,arguments)}var A,C=document,L=window,K=Math,u=K.round,U=K.floor,za=K.ceil,s=K.max,O=K.min,M=K.abs,W=K.cos,Z=K.sin,Aa=K.PI,ab=Aa*2/360,na=navigator.userAgent,Lb=L.opera,Ea=/msie/i.test(na)&&!Lb,Ra=C.documentMode===8,bb=/AppleWebKit/.test(na),cb=/Firefox/.test(na),Mb=/(Mobile|Android|Windows Phone)/.test(na),
oa="http://www.w3.org/2000/svg",ca=!!C.createElementNS&&!!C.createElementNS(oa,"svg").createSVGRect,Sb=cb&&parseInt(na.split("Firefox/")[1],10)<4,V=!ca&&!Ea&&!!C.createElement("canvas").getContext,Sa,Ba=C.documentElement.ontouchstart!==A,Nb={},tb=0,$a,N,db,Pa,ub,D,pa=function(){},Ha=[],ga="div",Q="none",vb="rgba(192,192,192,"+(ca?1.0E-4:0.002)+")",Bb="millisecond",ib="second",Va="minute",Ka="hour",ma="day",Wa="week",La="month",va="year",wb="stroke-width",Za,jb,kb,mb,Ma,Xa,Ya,Db,Eb,lb,Fb,Gb,$={};L.Highcharts=
{};db=function(a,b,c){if(!r(b)||isNaN(b))return"Invalid date";var a=n(a,"%Y-%m-%d %H:%M:%S"),d=new Date(b),e,f=d[kb](),g=d[mb](),h=d[Ma](),i=d[Xa](),j=d[Ya](),k=N.lang,l=k.weekdays,b={a:l[g].substr(0,3),A:l[g],d:ua(h),e:h,b:k.shortMonths[i],B:k.months[i],m:ua(i+1),y:j.toString().substr(2,2),Y:j,H:ua(f),I:ua(f%12||12),l:f%12||12,M:ua(d[jb]()),p:f<12?"AM":"PM",P:f<12?"am":"pm",S:ua(d.getSeconds()),L:ua(u(b%1E3),3)};for(e in b)for(;a.indexOf("%"+e)!==-1;)a=a.replace("%"+e,b[e]);return c?a.substr(0,1).toUpperCase()+
a.substr(1):a};Hb.prototype={wrapColor:function(a){if(this.color>=a)this.color=0},wrapSymbol:function(a){if(this.symbol>=a)this.symbol=0}};D=ia(Bb,1,ib,1E3,Va,6E4,Ka,36E5,ma,864E5,Wa,6048E5,La,26784E5,va,31556952E3);ub={init:function(a,b,c){var b=b||"",d=a.shift,e=b.indexOf("C")>-1,f=e?7:3,g,b=b.split(" "),c=[].concat(c),h,i,j=function(a){for(g=a.length;g--;)a[g]==="M"&&a.splice(g+1,0,a[g+1],a[g+2],a[g+1],a[g+2])};e&&(j(b),j(c));a.isArea&&(h=b.splice(b.length-6,6),i=c.splice(c.length-6,6));if(d<=
c.length/f)for(;d--;)c=[].concat(c).splice(0,f).concat(c);a.shift=0;if(b.length)for(a=c.length;b.length<a;)d=[].concat(b).splice(b.length-f,f),e&&(d[f-6]=d[f-2],d[f-5]=d[f-1]),b=b.concat(d);h&&(b=b.concat(h),c=c.concat(i));return[b,c]},step:function(a,b,c,d){var e=[],f=a.length;if(c===1)e=d;else if(f===b.length&&c<1)for(;f--;)d=parseFloat(a[f]),e[f]=isNaN(d)?a[f]:c*parseFloat(b[f]-d)+d;else e=b;return e}};(function(a){L.HighchartsAdapter=L.HighchartsAdapter||a&&{init:function(b){var c=a.fx,d=c.step,
e,f=a.Tween,g=f&&f.propHooks;a.extend(a.easing,{easeOutQuad:function(a,b,c,d,e){return-d*(b/=e)*(b-2)+c}});a.each(["cur","_default","width","height"],function(a,b){var e=d,k,l;b==="cur"?e=c.prototype:b==="_default"&&f&&(e=g[b],b="set");(k=e[b])&&(e[b]=function(c){c=a?c:this;l=c.elem;return l.attr?l.attr(c.prop,b==="cur"?A:c.now):k.apply(this,arguments)})});e=function(a){var c=a.elem,d;if(!a.started)d=b.init(c,c.d,c.toD),a.start=d[0],a.end=d[1],a.started=!0;c.attr("d",b.step(a.start,a.end,a.pos,c.toD))};
f?g.d={set:e}:d.d=e;this.each=Array.prototype.forEach?function(a,b){return Array.prototype.forEach.call(a,b)}:function(a,b){for(var c=0,d=a.length;c<d;c++)if(b.call(a[c],a[c],c,a)===!1)return c}},getScript:a.getScript,inArray:a.inArray,adapterRun:function(b,c){return a(b)[c]()},grep:a.grep,map:function(a,c){for(var d=[],e=0,f=a.length;e<f;e++)d[e]=c.call(a[e],a[e],e,a);return d},merge:function(){var b=arguments;return a.extend(!0,null,b[0],b[1],b[2],b[3])},offset:function(b){return a(b).offset()},
addEvent:function(b,c,d){a(b).bind(c,d)},removeEvent:function(b,c,d){var e=C.removeEventListener?"removeEventListener":"detachEvent";C[e]&&!b[e]&&(b[e]=function(){});a(b).unbind(c,d)},fireEvent:function(b,c,d,e){var f=a.Event(c),g="detached"+c,h;!Ea&&d&&(delete d.layerX,delete d.layerY);x(f,d);b[c]&&(b[g]=b[c],b[c]=null);a.each(["preventDefault","stopPropagation"],function(a,b){var c=f[b];f[b]=function(){try{c.call(f)}catch(a){b==="preventDefault"&&(h=!0)}}});a(b).trigger(f);b[g]&&(b[c]=b[g],b[g]=
null);e&&!f.isDefaultPrevented()&&!h&&e(f)},washMouseEvent:function(a){var c=a.originalEvent||a;if(c.pageX===A)c.pageX=a.pageX,c.pageY=a.pageY;return c},animate:function(b,c,d){var e=a(b);if(c.d)b.toD=c.d,c.d=1;e.stop();e.animate(c,d)},stop:function(b){a(b).stop()}}})(L.jQuery);var ea=L.HighchartsAdapter,G=ea||{};ea&&ea.init.call(ea,ub);var eb=G.adapterRun,Tb=G.getScript,Ub=G.inArray,o=G.each,Ob=G.grep,Vb=G.offset,Ta=G.map,B=G.merge,J=G.addEvent,R=G.removeEvent,F=G.fireEvent,Pb=G.washMouseEvent,xb=
G.animate,fb=G.stop,G={enabled:!0,align:"center",x:0,y:15,style:{color:"#666",fontSize:"11px",lineHeight:"14px"}};N={colors:"#4572A7,#AA4643,#89A54E,#80699B,#3D96AE,#DB843D,#92A8CD,#A47D7C,#B5CA92".split(","),symbols:["circle","diamond","square","triangle","triangle-down"],lang:{loading:"Loading...",months:"January,February,March,April,May,June,July,August,September,October,November,December".split(","),shortMonths:"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec".split(","),weekdays:"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday".split(","),
decimalPoint:".",numericSymbols:"k,M,G,T,P,E".split(","),resetZoom:"Reset zoom",resetZoomTitle:"Reset zoom level 1:1",thousandsSep:","},global:{useUTC:!0,canvasToolsURL:"http://code.highcharts.com/2.3.5/modules/canvas-tools.js",VMLRadialGradientURL:"http://code.highcharts.com/2.3.5/gfx/vml-radial-gradient.png"},chart:{borderColor:"#4572A7",borderRadius:5,defaultSeriesType:"line",ignoreHiddenSeries:!0,spacingTop:10,spacingRight:10,spacingBottom:15,spacingLeft:10,style:{fontFamily:'"Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif',
fontSize:"12px"},backgroundColor:"#FFFFFF",plotBorderColor:"#C0C0C0",resetZoomButton:{theme:{zIndex:20},position:{align:"right",x:-10,y:10}}},title:{text:"Chart title",align:"center",y:15,style:{color:"#3E576F",fontSize:"16px"}},subtitle:{text:"",align:"center",y:30,style:{color:"#6D869F"}},plotOptions:{line:{allowPointSelect:!1,showCheckbox:!1,animation:{duration:1E3},events:{},lineWidth:2,shadow:!0,marker:{enabled:!0,lineWidth:0,radius:4,lineColor:"#FFFFFF",states:{hover:{enabled:!0},select:{fillColor:"#FFFFFF",
lineColor:"#000000",lineWidth:2}}},point:{events:{}},dataLabels:B(G,{enabled:!1,formatter:function(){return this.y},verticalAlign:"bottom",y:0}),cropThreshold:300,pointRange:0,showInLegend:!0,states:{hover:{marker:{}},select:{marker:{}}},stickyTracking:!0}},labels:{style:{position:"absolute",color:"#3E576F"}},legend:{enabled:!0,align:"center",layout:"horizontal",labelFormatter:function(){return this.name},borderWidth:1,borderColor:"#909090",borderRadius:5,navigation:{activeColor:"#3E576F",inactiveColor:"#CCC"},
shadow:!1,itemStyle:{cursor:"pointer",color:"#3E576F",fontSize:"12px"},itemHoverStyle:{color:"#000"},itemHiddenStyle:{color:"#CCC"},itemCheckboxStyle:{position:"absolute",width:"13px",height:"13px"},symbolWidth:16,symbolPadding:5,verticalAlign:"bottom",x:0,y:0},loading:{labelStyle:{fontWeight:"bold",position:"relative",top:"1em"},style:{position:"absolute",backgroundColor:"white",opacity:0.5,textAlign:"center"}},tooltip:{enabled:!0,backgroundColor:"rgba(255, 255, 255, .85)",borderWidth:2,borderRadius:5,
dateTimeLabelFormats:{millisecond:"%A, %b %e, %H:%M:%S.%L",second:"%A, %b %e, %H:%M:%S",minute:"%A, %b %e, %H:%M",hour:"%A, %b %e, %H:%M",day:"%A, %b %e, %Y",week:"Week from %A, %b %e, %Y",month:"%B %Y",year:"%Y"},headerFormat:'<span style="font-size: 10px">{point.key}</span><br/>',pointFormat:'<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b><br/>',shadow:!0,shared:V,snap:Mb?25:10,style:{color:"#333333",fontSize:"12px",padding:"5px",whiteSpace:"nowrap"}},credits:{enabled:!0,
text:"Highcharts.com",href:"http://www.highcharts.com",position:{align:"right",x:-10,verticalAlign:"bottom",y:-5},style:{cursor:"pointer",color:"#909090",fontSize:"10px"}}};var X=N.plotOptions,ea=X.line;Jb();var qa=function(a){var b=[],c;(function(a){(c=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/.exec(a))?b=[z(c[1]),z(c[2]),z(c[3]),parseFloat(c[4],10)]:(c=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(a))&&(b=[z(c[1],16),z(c[2],16),z(c[3],
16),1])})(a);return{get:function(c){return b&&!isNaN(b[0])?c==="rgb"?"rgb("+b[0]+","+b[1]+","+b[2]+")":c==="a"?b[3]:"rgba("+b.join(",")+")":a},brighten:function(a){if(Da(a)&&a!==0){var c;for(c=0;c<3;c++)b[c]+=z(a*255),b[c]<0&&(b[c]=0),b[c]>255&&(b[c]=255)}return this},setOpacity:function(a){b[3]=a;return this}}};ya.prototype={init:function(a,b){this.element=b==="span"?T(b):C.createElementNS(oa,b);this.renderer=a;this.attrSetters={}},animate:function(a,b,c){b=n(b,Pa,!0);fb(this);if(b){b=B(b);if(c)b.complete=
c;xb(this,a,b)}else this.attr(a),c&&c()},attr:function(a,b){var c,d,e,f,g=this.element,h=g.nodeName.toLowerCase(),i=this.renderer,j,k=this.attrSetters,l=this.shadows,m,q,p=this;ja(a)&&r(b)&&(c=a,a={},a[c]=b);if(ja(a))c=a,h==="circle"?c={x:"cx",y:"cy"}[c]||c:c==="strokeWidth"&&(c="stroke-width"),p=w(g,c)||this[c]||0,c!=="d"&&c!=="visibility"&&(p=parseFloat(p));else for(c in a)if(j=!1,d=a[c],e=k[c]&&k[c].call(this,d,c),e!==!1){e!==A&&(d=e);if(c==="d")d&&d.join&&(d=d.join(" ")),/(NaN| {2}|^$)/.test(d)&&
(d="M 0 0");else if(c==="x"&&h==="text"){for(e=0;e<g.childNodes.length;e++)f=g.childNodes[e],w(f,"x")===w(g,"x")&&w(f,"x",d);this.rotation&&w(g,"transform","rotate("+this.rotation+" "+d+" "+z(a.y||w(g,"y"))+")")}else if(c==="fill")d=i.color(d,g,c);else if(h==="circle"&&(c==="x"||c==="y"))c={x:"cx",y:"cy"}[c]||c;else if(h==="rect"&&c==="r")w(g,{rx:d,ry:d}),j=!0;else if(c==="translateX"||c==="translateY"||c==="rotation"||c==="verticalAlign")j=q=!0;else if(c==="stroke")d=i.color(d,g,c);else if(c==="dashstyle")if(c=
"stroke-dasharray",d=d&&d.toLowerCase(),d==="solid")d=Q;else{if(d){d=d.replace("shortdashdotdot","3,1,1,1,1,1,").replace("shortdashdot","3,1,1,1").replace("shortdot","1,1,").replace("shortdash","3,1,").replace("longdash","8,3,").replace(/dot/g,"1,3,").replace("dash","4,3,").replace(/,$/,"").split(",");for(e=d.length;e--;)d[e]=z(d[e])*a["stroke-width"];d=d.join(",")}}else if(c==="isTracker")this[c]=d;else if(c==="width")d=z(d);else if(c==="align")c="text-anchor",d={left:"start",center:"middle",right:"end"}[d];
else if(c==="title")e=g.getElementsByTagName("title")[0],e||(e=C.createElementNS(oa,"title"),g.appendChild(e)),e.textContent=d;c==="strokeWidth"&&(c="stroke-width");if(c==="stroke-width"&&d===0&&(bb||i.forExport))d=1.0E-6;this.symbolName&&/^(x|y|width|height|r|start|end|innerR|anchorX|anchorY)/.test(c)&&(m||(this.symbolAttr(a),m=!0),j=!0);if(l&&/^(width|height|visibility|x|y|d|transform)$/.test(c))for(e=l.length;e--;)w(l[e],c,c==="height"?s(d-(l[e].cutHeight||0),0):d);if((c==="width"||c==="height")&&
h==="rect"&&d<0)d=0;this[c]=d;q&&this.updateTransform();c==="text"?(d!==this.textStr&&delete this.bBox,this.textStr=d,this.added&&i.buildText(this)):j||w(g,c,d)}return p},symbolAttr:function(a){var b=this;o("x,y,r,start,end,width,height,innerR,anchorX,anchorY".split(","),function(c){b[c]=n(a[c],b[c])});b.attr({d:b.renderer.symbols[b.symbolName](b.x,b.y,b.width,b.height,b)})},clip:function(a){return this.attr("clip-path",a?"url("+this.renderer.url+"#"+a.id+")":Q)},crisp:function(a,b,c,d,e){var f,g=
{},h={},i,a=a||this.strokeWidth||this.attr&&this.attr("stroke-width")||0;i=u(a)%2/2;h.x=U(b||this.x||0)+i;h.y=U(c||this.y||0)+i;h.width=U((d||this.width||0)-2*i);h.height=U((e||this.height||0)-2*i);h.strokeWidth=a;for(f in h)this[f]!==h[f]&&(this[f]=g[f]=h[f]);return g},css:function(a){var b=this.element,b=a&&a.width&&b.nodeName.toLowerCase()==="text",c,d="",e=function(a,b){return"-"+b.toLowerCase()};if(a&&a.color)a.fill=a.color;this.styles=a=x(this.styles,a);V&&b&&delete a.width;if(Ea&&!ca)b&&delete a.width,
I(this.element,a);else{for(c in a)d+=c.replace(/([A-Z])/g,e)+":"+a[c]+";";this.attr({style:d})}b&&this.added&&this.renderer.buildText(this);return this},on:function(a,b){if(Ba&&a==="click")this.element.ontouchstart=function(a){a.preventDefault();b()};this.element["on"+a]=b;return this},setRadialReference:function(a){this.element.radialReference=a;return this},translate:function(a,b){return this.attr({translateX:a,translateY:b})},invert:function(){this.inverted=!0;this.updateTransform();return this},
htmlCss:function(a){var b=this.element;if(b=a&&b.tagName==="SPAN"&&a.width)delete a.width,this.textWidth=b,this.updateTransform();this.styles=x(this.styles,a);I(this.element,a);return this},htmlGetBBox:function(){var a=this.element,b=this.bBox;if(!b){if(a.nodeName==="text")a.style.position="absolute";b=this.bBox={x:a.offsetLeft,y:a.offsetTop,width:a.offsetWidth,height:a.offsetHeight}}return b},htmlUpdateTransform:function(){if(this.added){var a=this.renderer,b=this.element,c=this.translateX||0,d=
this.translateY||0,e=this.x||0,f=this.y||0,g=this.textAlign||"left",h={left:0,center:0.5,right:1}[g],i=g&&g!=="left",j=this.shadows;if(c||d)I(b,{marginLeft:c,marginTop:d}),j&&o(j,function(a){I(a,{marginLeft:c+1,marginTop:d+1})});this.inverted&&o(b.childNodes,function(c){a.invertChild(c,b)});if(b.tagName==="SPAN"){var k,l,j=this.rotation,m,q=0,p=1,q=0,y;m=z(this.textWidth);var t=this.xCorr||0,H=this.yCorr||0,ra=[j,g,b.innerHTML,this.textWidth].join(",");k={};if(ra!==this.cTT){if(r(j))a.isSVG?(t=Ea?
"-ms-transform":bb?"-webkit-transform":cb?"MozTransform":Lb?"-o-transform":"",k[t]=k.transform="rotate("+j+"deg)"):(q=j*ab,p=W(q),q=Z(q),k.filter=j?["progid:DXImageTransform.Microsoft.Matrix(M11=",p,", M12=",-q,", M21=",q,", M22=",p,", sizingMethod='auto expand')"].join(""):Q),I(b,k);k=n(this.elemWidth,b.offsetWidth);l=n(this.elemHeight,b.offsetHeight);if(k>m&&/[ \-]/.test(b.textContent||b.innerText))I(b,{width:m+"px",display:"block",whiteSpace:"normal"}),k=m;m=a.fontMetrics(b.style.fontSize).b;t=
p<0&&-k;H=q<0&&-l;y=p*q<0;t+=q*m*(y?1-h:h);H-=p*m*(j?y?h:1-h:1);i&&(t-=k*h*(p<0?-1:1),j&&(H-=l*h*(q<0?-1:1)),I(b,{textAlign:g}));this.xCorr=t;this.yCorr=H}I(b,{left:e+t+"px",top:f+H+"px"});if(bb)l=b.offsetHeight;this.cTT=ra}}else this.alignOnAdd=!0},updateTransform:function(){var a=this.translateX||0,b=this.translateY||0,c=this.inverted,d=this.rotation,e=[];c&&(a+=this.attr("width"),b+=this.attr("height"));(a||b)&&e.push("translate("+a+","+b+")");c?e.push("rotate(90) scale(-1,1)"):d&&e.push("rotate("+
d+" "+(this.x||0)+" "+(this.y||0)+")");e.length&&w(this.element,"transform",e.join(" "))},toFront:function(){var a=this.element;a.parentNode.appendChild(a);return this},align:function(a,b,c){a?(this.alignOptions=a,this.alignByTranslate=b,c||this.renderer.alignedObjects.push(this)):(a=this.alignOptions,b=this.alignByTranslate);var c=n(c,this.renderer),d=a.align,e=a.verticalAlign,f=(c.x||0)+(a.x||0),g=(c.y||0)+(a.y||0),h={};if(d==="right"||d==="center")f+=(c.width-(a.width||0))/{right:1,center:2}[d];
h[b?"translateX":"x"]=u(f);if(e==="bottom"||e==="middle")g+=(c.height-(a.height||0))/({bottom:1,middle:2}[e]||1);h[b?"translateY":"y"]=u(g);this[this.placed?"animate":"attr"](h);this.placed=!0;this.alignAttr=h;return this},getBBox:function(){var a=this.bBox,b=this.renderer,c,d=this.rotation;c=this.element;var e=this.styles,f=d*ab;if(!a){if(c.namespaceURI===oa||b.forExport){try{a=c.getBBox?x({},c.getBBox()):{width:c.offsetWidth,height:c.offsetHeight}}catch(g){}if(!a||a.width<0)a={width:0,height:0}}else a=
this.htmlGetBBox();if(b.isSVG){b=a.width;c=a.height;if(Ea&&e&&e.fontSize==="11px"&&c===22.700000762939453)a.height=c=14;if(d)a.width=M(c*Z(f))+M(b*W(f)),a.height=M(c*W(f))+M(b*Z(f))}this.bBox=a}return a},show:function(){return this.attr({visibility:"visible"})},hide:function(){return this.attr({visibility:"hidden"})},add:function(a){var b=this.renderer,c=a||b,d=c.element||b.box,e=d.childNodes,f=this.element,g=w(f,"zIndex"),h;if(a)this.parentGroup=a;this.parentInverted=a&&a.inverted;this.textStr!==
void 0&&b.buildText(this);if(g)c.handleZ=!0,g=z(g);if(c.handleZ)for(c=0;c<e.length;c++)if(a=e[c],b=w(a,"zIndex"),a!==f&&(z(b)>g||!r(g)&&r(b))){d.insertBefore(f,a);h=!0;break}h||d.appendChild(f);this.added=!0;F(this,"add");return this},safeRemoveChild:function(a){var b=a.parentNode;b&&b.removeChild(a)},destroy:function(){var a=this,b=a.element||{},c=a.shadows,d,e;b.onclick=b.onmouseout=b.onmouseover=b.onmousemove=null;fb(a);if(a.clipPath)a.clipPath=a.clipPath.destroy();if(a.stops){for(e=0;e<a.stops.length;e++)a.stops[e]=
a.stops[e].destroy();a.stops=null}a.safeRemoveChild(b);c&&o(c,function(b){a.safeRemoveChild(b)});ta(a.renderer.alignedObjects,a);for(d in a)delete a[d];return null},empty:function(){for(var a=this.element,b=a.childNodes,c=b.length;c--;)a.removeChild(b[c])},shadow:function(a,b,c){var d=[],e,f,g=this.element,h,i,j,k;if(a){i=n(a.width,3);j=(a.opacity||0.15)/i;k=this.parentInverted?"(-1,-1)":"("+n(a.offsetX,1)+", "+n(a.offsetY,1)+")";for(e=1;e<=i;e++){f=g.cloneNode(0);h=i*2+1-2*e;w(f,{isShadow:"true",
stroke:a.color||"black","stroke-opacity":j*e,"stroke-width":h,transform:"translate"+k,fill:Q});if(c)w(f,"height",s(w(f,"height")-h,0)),f.cutHeight=h;b?b.element.appendChild(f):g.parentNode.insertBefore(f,g);d.push(f)}this.shadows=d}return this}};var sa=function(){this.init.apply(this,arguments)};sa.prototype={Element:ya,init:function(a,b,c,d){var e=location,f;f=this.createElement("svg").attr({xmlns:oa,version:"1.1"});a.appendChild(f.element);this.isSVG=!0;this.box=f.element;this.boxWrapper=f;this.alignedObjects=
[];this.url=(cb||bb)&&C.getElementsByTagName("base").length?e.href.replace(/#.*?$/,"").replace(/([\('\)])/g,"\\$1").replace(/ /g,"%20"):"";this.defs=this.createElement("defs").add();this.forExport=d;this.gradients={};this.setSize(b,c,!1);var g;if(cb&&a.getBoundingClientRect)this.subPixelFix=b=function(){I(a,{left:0,top:0});g=a.getBoundingClientRect();I(a,{left:za(g.left)-g.left+"px",top:za(g.top)-g.top+"px"})},b(),J(L,"resize",b)},isHidden:function(){return!this.boxWrapper.getBBox().width},destroy:function(){var a=
this.defs;this.box=null;this.boxWrapper=this.boxWrapper.destroy();Ga(this.gradients||{});this.gradients=null;if(a)this.defs=a.destroy();this.subPixelFix&&R(L,"resize",this.subPixelFix);return this.alignedObjects=null},createElement:function(a){var b=new this.Element;b.init(this,a);return b},draw:function(){},buildText:function(a){for(var b=a.element,c=n(a.textStr,"").toString().replace(/<(b|strong)>/g,'<span style="font-weight:bold">').replace(/<(i|em)>/g,'<span style="font-style:italic">').replace(/<a/g,
"<span").replace(/<\/(b|strong|i|em|a)>/g,"</span>").split(/<br.*?>/g),d=b.childNodes,e=/style="([^"]+)"/,f=/href="([^"]+)"/,g=w(b,"x"),h=a.styles,i=h&&h.width&&z(h.width),j=h&&h.lineHeight,k,h=d.length,l=[];h--;)b.removeChild(d[h]);i&&!a.added&&this.box.appendChild(b);c[c.length-1]===""&&c.pop();o(c,function(c,d){var h,y=0,t,c=c.replace(/<span/g,"|||<span").replace(/<\/span>/g,"</span>|||");h=c.split("|||");o(h,function(c){if(c!==""||h.length===1){var m={},n=C.createElementNS(oa,"tspan"),o;e.test(c)&&
(o=c.match(e)[1].replace(/(;| |^)color([ :])/,"$1fill$2"),w(n,"style",o));f.test(c)&&(w(n,"onclick",'location.href="'+c.match(f)[1]+'"'),I(n,{cursor:"pointer"}));c=(c.replace(/<(.|\n)*?>/g,"")||" ").replace(/&lt;/g,"<").replace(/&gt;/g,">");n.appendChild(C.createTextNode(c));y?m.dx=3:m.x=g;if(!y){if(d){!ca&&a.renderer.forExport&&I(n,{display:"block"});t=L.getComputedStyle&&z(L.getComputedStyle(k,null).getPropertyValue("line-height"));if(!t||isNaN(t)){var r;if(!(r=j))if(!(r=k.offsetHeight))l[d]=b.getBBox?
b.getBBox().height:a.renderer.fontMetrics(b.style.fontSize).h,r=u(l[d]-(l[d-1]||0))||18;t=r}w(n,"dy",t)}k=n}w(n,m);b.appendChild(n);y++;if(i)for(var c=c.replace(/([^\^])-/g,"$1- ").split(" "),E=[];c.length||E.length;)delete a.bBox,r=a.getBBox().width,m=r>i,!m||c.length===1?(c=E,E=[],c.length&&(n=C.createElementNS(oa,"tspan"),w(n,{dy:j||16,x:g}),o&&w(n,"style",o),b.appendChild(n),r>i&&(i=r))):(n.removeChild(n.firstChild),E.unshift(c.pop())),c.length&&n.appendChild(C.createTextNode(c.join(" ").replace(/- /g,
"-")))}})})},button:function(a,b,c,d,e,f,g){var h=this.label(a,b,c),i=0,j,k,l,m,q,a={x1:0,y1:0,x2:0,y2:1},e=B(ia(wb,1,"stroke","#999","fill",ia("linearGradient",a,"stops",[[0,"#FFF"],[1,"#DDD"]]),"r",3,"padding",3,"style",ia("color","black")),e);l=e.style;delete e.style;f=B(e,ia("stroke","#68A","fill",ia("linearGradient",a,"stops",[[0,"#FFF"],[1,"#ACF"]])),f);m=f.style;delete f.style;g=B(e,ia("stroke","#68A","fill",ia("linearGradient",a,"stops",[[0,"#9BD"],[1,"#CDF"]])),g);q=g.style;delete g.style;
J(h.element,"mouseenter",function(){h.attr(f).css(m)});J(h.element,"mouseleave",function(){j=[e,f,g][i];k=[l,m,q][i];h.attr(j).css(k)});h.setState=function(a){(i=a)?a===2&&h.attr(g).css(q):h.attr(e).css(l)};return h.on("click",function(){d.call(h)}).attr(e).css(x({cursor:"default"},l))},crispLine:function(a,b){a[1]===a[4]&&(a[1]=a[4]=u(a[1])-b%2/2);a[2]===a[5]&&(a[2]=a[5]=u(a[2])+b%2/2);return a},path:function(a){var b={fill:Q};Ia(a)?b.d=a:Y(a)&&x(b,a);return this.createElement("path").attr(b)},circle:function(a,
b,c){a=Y(a)?a:{x:a,y:b,r:c};return this.createElement("circle").attr(a)},arc:function(a,b,c,d,e,f){if(Y(a))b=a.y,c=a.r,d=a.innerR,e=a.start,f=a.end,a=a.x;return this.symbol("arc",a||0,b||0,c||0,c||0,{innerR:d||0,start:e||0,end:f||0})},rect:function(a,b,c,d,e,f){e=Y(a)?a.r:e;e=this.createElement("rect").attr({rx:e,ry:e,fill:Q});return e.attr(Y(a)?a:e.crisp(f,a,b,s(c,0),s(d,0)))},setSize:function(a,b,c){var d=this.alignedObjects,e=d.length;this.width=a;this.height=b;for(this.boxWrapper[n(c,!0)?"animate":
"attr"]({width:a,height:b});e--;)d[e].align()},g:function(a){var b=this.createElement("g");return r(a)?b.attr({"class":"highcharts-"+a}):b},image:function(a,b,c,d,e){var f={preserveAspectRatio:Q};arguments.length>1&&x(f,{x:b,y:c,width:d,height:e});f=this.createElement("image").attr(f);f.element.setAttributeNS?f.element.setAttributeNS("http://www.w3.org/1999/xlink","href",a):f.element.setAttribute("hc-svg-href",a);return f},symbol:function(a,b,c,d,e,f){var g,h=this.symbols[a],h=h&&h(u(b),u(c),d,e,
f),i=/^url\((.*?)\)$/,j,k;h?(g=this.path(h),x(g,{symbolName:a,x:b,y:c,width:d,height:e}),f&&x(g,f)):i.test(a)&&(k=function(a,b){a.element&&(a.attr({width:b[0],height:b[1]}),a.alignByTranslate||a.translate(u((d-b[0])/2),u((e-b[1])/2)))},j=a.match(i)[1],a=Nb[j],g=this.image(j).attr({x:b,y:c}),a?k(g,a):(g.attr({width:0,height:0}),T("img",{onload:function(){k(g,Nb[j]=[this.width,this.height])},src:j})));return g},symbols:{circle:function(a,b,c,d){var e=0.166*c;return["M",a+c/2,b,"C",a+c+e,b,a+c+e,b+d,
a+c/2,b+d,"C",a-e,b+d,a-e,b,a+c/2,b,"Z"]},square:function(a,b,c,d){return["M",a,b,"L",a+c,b,a+c,b+d,a,b+d,"Z"]},triangle:function(a,b,c,d){return["M",a+c/2,b,"L",a+c,b+d,a,b+d,"Z"]},"triangle-down":function(a,b,c,d){return["M",a,b,"L",a+c,b,a+c/2,b+d,"Z"]},diamond:function(a,b,c,d){return["M",a+c/2,b,"L",a+c,b+d/2,a+c/2,b+d,a,b+d/2,"Z"]},arc:function(a,b,c,d,e){var f=e.start,c=e.r||c||d,g=e.end-1.0E-6,d=e.innerR,h=e.open,i=W(f),j=Z(f),k=W(g),g=Z(g),e=e.end-f<Aa?0:1;return["M",a+c*i,b+c*j,"A",c,c,
0,e,1,a+c*k,b+c*g,h?"M":"L",a+d*k,b+d*g,"A",d,d,0,e,0,a+d*i,b+d*j,h?"":"Z"]}},clipRect:function(a,b,c,d){var e="highcharts-"+tb++,f=this.createElement("clipPath").attr({id:e}).add(this.defs),a=this.rect(a,b,c,d,0).add(f);a.id=e;a.clipPath=f;return a},color:function(a,b,c){var d=this,e,f=/^rgba/,g,h,i,j,k,l,m,q=[];a&&a.linearGradient?g="linearGradient":a&&a.radialGradient&&(g="radialGradient");if(g){c=a[g];h=d.gradients;j=a.stops;b=b.radialReference;Ia(c)&&(a[g]=c={x1:c[0],y1:c[1],x2:c[2],y2:c[3],
gradientUnits:"userSpaceOnUse"});g==="radialGradient"&&b&&!r(c.gradientUnits)&&x(c,{cx:b[0]-b[2]/2+c.cx*b[2],cy:b[1]-b[2]/2+c.cy*b[2],r:c.r*b[2],gradientUnits:"userSpaceOnUse"});for(m in c)m!=="id"&&q.push(m,c[m]);for(m in j)q.push(j[m]);q=q.join(",");h[q]?a=h[q].id:(c.id=a="highcharts-"+tb++,h[q]=i=d.createElement(g).attr(c).add(d.defs),i.stops=[],o(j,function(a){f.test(a[1])?(e=qa(a[1]),k=e.get("rgb"),l=e.get("a")):(k=a[1],l=1);a=d.createElement("stop").attr({offset:a[0],"stop-color":k,"stop-opacity":l}).add(i);
i.stops.push(a)}));return"url("+d.url+"#"+a+")"}else return f.test(a)?(e=qa(a),w(b,c+"-opacity",e.get("a")),e.get("rgb")):(b.removeAttribute(c+"-opacity"),a)},text:function(a,b,c,d){var e=N.chart.style,f=V||!ca&&this.forExport;if(d&&!this.forExport)return this.html(a,b,c);b=u(n(b,0));c=u(n(c,0));a=this.createElement("text").attr({x:b,y:c,text:a}).css({fontFamily:e.fontFamily,fontSize:e.fontSize});f&&a.css({position:"absolute"});a.x=b;a.y=c;return a},html:function(a,b,c){var d=N.chart.style,e=this.createElement("span"),
f=e.attrSetters,g=e.element,h=e.renderer;f.text=function(a){a!==g.innerHTML&&delete this.bBox;g.innerHTML=a;return!1};f.x=f.y=f.align=function(a,b){b==="align"&&(b="textAlign");e[b]=a;e.htmlUpdateTransform();return!1};e.attr({text:a,x:u(b),y:u(c)}).css({position:"absolute",whiteSpace:"nowrap",fontFamily:d.fontFamily,fontSize:d.fontSize});e.css=e.htmlCss;if(h.isSVG)e.add=function(a){var b,c=h.box.parentNode,d=[];if(a){if(b=a.div,!b){for(;a;)d.push(a),a=a.parentGroup;o(d.reverse(),function(a){var d;
b=a.div=a.div||T(ga,{className:w(a.element,"class")},{position:"absolute",left:(a.translateX||0)+"px",top:(a.translateY||0)+"px"},b||c);d=b.style;x(a.attrSetters,{translateX:function(a){d.left=a+"px"},translateY:function(a){d.top=a+"px"},visibility:function(a,b){d[b]=a}})})}}else b=c;b.appendChild(g);e.added=!0;e.alignOnAdd&&e.htmlUpdateTransform();return e};return e},fontMetrics:function(a){var a=z(a||11),a=a<24?a+4:u(a*1.2),b=u(a*0.8);return{h:a,b:b}},label:function(a,b,c,d,e,f,g,h,i){function j(){var a;
a=y.element.style;H=(s===void 0||yb===void 0||p.styles.textAlign)&&y.getBBox();p.width=(s||H.width||0)+2*v;p.height=(yb||H.height||0)+2*v;zb=v+q.fontMetrics(a&&a.fontSize).b;if(z){if(!n)a=h?-zb:0,p.box=n=d?q.symbol(d,-ra*v,a,p.width,p.height):q.rect(-ra*v,a,p.width,p.height,0,w[wb]),n.add(p);n.attr(B({width:p.width,height:p.height},w));w=null}}function k(){var a=p.styles,a=a&&a.textAlign,b=v*(1-ra),c;c=h?0:zb;if(r(s)&&(a==="center"||a==="right"))b+={center:0.5,right:1}[a]*(s-H.width);(b!==y.x||c!==
y.y)&&y.attr({x:b,y:c});y.x=b;y.y=c}function l(a,b){n?n.attr(a,b):w[a]=b}function m(){y.add(p);p.attr({text:a,x:b,y:c});n&&r(e)&&p.attr({anchorX:e,anchorY:f})}var q=this,p=q.g(i),y=q.text("",0,0,g).attr({zIndex:1}),n,H,ra=0,v=3,s,yb,E,S,Qb=0,w={},zb,g=p.attrSetters,z;J(p,"add",m);g.width=function(a){s=a;return!1};g.height=function(a){yb=a;return!1};g.padding=function(a){r(a)&&a!==v&&(v=a,k());return!1};g.align=function(a){ra={left:0,center:0.5,right:1}[a];return!1};g.text=function(a,b){y.attr(b,a);
j();k();return!1};g[wb]=function(a,b){z=!0;Qb=a%2/2;l(b,a);return!1};g.stroke=g.fill=g.r=function(a,b){b==="fill"&&(z=!0);l(b,a);return!1};g.anchorX=function(a,b){e=a;l(b,a+Qb-E);return!1};g.anchorY=function(a,b){f=a;l(b,a-S);return!1};g.x=function(a){p.x=a;a-=ra*((s||H.width)+v);E=u(a);p.attr("translateX",E);return!1};g.y=function(a){S=p.y=u(a);p.attr("translateY",a);return!1};var C=p.css;return x(p,{css:function(a){if(a){var b={},a=B({},a);o("fontSize,fontWeight,fontFamily,color,lineHeight,width".split(","),
function(c){a[c]!==A&&(b[c]=a[c],delete a[c])});y.css(b)}return C.call(p,a)},getBBox:function(){return{width:H.width+2*v,height:H.height+2*v,x:H.x-v,y:H.y-v}},shadow:function(a){n&&n.shadow(a);return p},destroy:function(){R(p,"add",m);R(p.element,"mouseenter");R(p.element,"mouseleave");y&&(y=y.destroy());n&&(n=n.destroy());ya.prototype.destroy.call(p);p=q=j=k=l=m=null}})}};Sa=sa;var ha;if(!ca&&!V){ha={init:function(a,b){var c=["<",b,' filled="f" stroked="f"'],d=["position: ","absolute",";"];(b===
"shape"||b===ga)&&d.push("left:0;top:0;width:1px;height:1px;");Ra&&d.push("visibility: ",b===ga?"hidden":"visible");c.push(' style="',d.join(""),'"/>');if(b)c=b===ga||b==="span"||b==="img"?c.join(""):a.prepVML(c),this.element=T(c);this.renderer=a;this.attrSetters={}},add:function(a){var b=this.renderer,c=this.element,d=b.box,d=a?a.element||a:d;a&&a.inverted&&b.invertChild(c,d);d.appendChild(c);this.added=!0;this.alignOnAdd&&!this.deferUpdateTransform&&this.updateTransform();F(this,"add");return this},
updateTransform:ya.prototype.htmlUpdateTransform,attr:function(a,b){var c,d,e,f=this.element||{},g=f.style,h=f.nodeName,i=this.renderer,j=this.symbolName,k,l=this.shadows,m,q=this.attrSetters,p=this;ja(a)&&r(b)&&(c=a,a={},a[c]=b);if(ja(a))c=a,p=c==="strokeWidth"||c==="stroke-width"?this.strokeweight:this[c];else for(c in a)if(d=a[c],m=!1,e=q[c]&&q[c].call(this,d,c),e!==!1&&d!==null){e!==A&&(d=e);if(j&&/^(x|y|r|start|end|width|height|innerR|anchorX|anchorY)/.test(c))k||(this.symbolAttr(a),k=!0),m=
!0;else if(c==="d"){d=d||[];this.d=d.join(" ");e=d.length;for(m=[];e--;)m[e]=Da(d[e])?u(d[e]*10)-5:d[e]==="Z"?"x":d[e];d=m.join(" ")||"x";f.path=d;if(l)for(e=l.length;e--;)l[e].path=l[e].cutOff?this.cutOffPath(d,l[e].cutOff):d;m=!0}else if(c==="visibility"){if(l)for(e=l.length;e--;)l[e].style[c]=d;h==="DIV"&&(d=d==="hidden"?"-999em":0,c="top");g[c]=d;m=!0}else if(c==="zIndex")d&&(g[c]=d),m=!0;else if(c==="width"||c==="height")d=s(0,d),this[c]=d,this.updateClipping?(this[c]=d,this.updateClipping()):
g[c]=d,m=!0;else if(c==="x"||c==="y")this[c]=d,g[{x:"left",y:"top"}[c]]=d;else if(c==="class")f.className=d;else if(c==="stroke")d=i.color(d,f,c),c="strokecolor";else if(c==="stroke-width"||c==="strokeWidth")f.stroked=d?!0:!1,c="strokeweight",this[c]=d,Da(d)&&(d+="px");else if(c==="dashstyle")(f.getElementsByTagName("stroke")[0]||T(i.prepVML(["<stroke/>"]),null,null,f))[c]=d||"solid",this.dashstyle=d,m=!0;else if(c==="fill")if(h==="SPAN")g.color=d;else{if(h!=="IMG")f.filled=d!==Q?!0:!1,d=i.color(d,
f,c,this),c="fillcolor"}else if(h==="shape"&&c==="rotation")this[c]=d,f.style.left=-u(Z(d*ab)+1)+"px",f.style.top=u(W(d*ab))+"px";else if(c==="translateX"||c==="translateY"||c==="rotation")this[c]=d,this.updateTransform(),m=!0;else if(c==="text")this.bBox=null,f.innerHTML=d,m=!0;m||(Ra?f[c]=d:w(f,c,d))}return p},clip:function(a){var b=this,c,d=b.element,e=d.parentNode;a?(c=a.members,ta(c,b),c.push(b),b.destroyClip=function(){ta(c,b)},e&&e.className==="highcharts-tracker"&&!Ra&&I(d,{visibility:"hidden"}),
a=a.getCSS(b)):(b.destroyClip&&b.destroyClip(),a={clip:Ra?"inherit":"rect(auto)"});return b.css(a)},css:ya.prototype.htmlCss,safeRemoveChild:function(a){a.parentNode&&Na(a)},destroy:function(){this.destroyClip&&this.destroyClip();return ya.prototype.destroy.apply(this)},empty:function(){for(var a=this.element.childNodes,b=a.length,c;b--;)c=a[b],c.parentNode.removeChild(c)},on:function(a,b){this.element["on"+a]=function(){var a=L.event;a.target=a.srcElement;b(a)};return this},cutOffPath:function(a,
b){var c,a=a.split(/[ ,]/);c=a.length;if(c===9||c===11)a[c-4]=a[c-2]=z(a[c-2])-10*b;return a.join(" ")},shadow:function(a,b,c){var d=[],e,f=this.element,g=this.renderer,h,i=f.style,j,k=f.path,l,m,q,p;k&&typeof k.value!=="string"&&(k="x");m=k;if(a){q=n(a.width,3);p=(a.opacity||0.15)/q;for(e=1;e<=3;e++){l=q*2+1-2*e;c&&(m=this.cutOffPath(k.value,l+0.5));j=['<shape isShadow="true" strokeweight="',l,'" filled="false" path="',m,'" coordsize="10 10" style="',f.style.cssText,'" />'];h=T(g.prepVML(j),null,
{left:z(i.left)+n(a.offsetX,1),top:z(i.top)+n(a.offsetY,1)});if(c)h.cutOff=l+1;j=['<stroke color="',a.color||"black",'" opacity="',p*e,'"/>'];T(g.prepVML(j),null,null,h);b?b.element.appendChild(h):f.parentNode.insertBefore(h,f);d.push(h)}this.shadows=d}return this}};ha=ba(ya,ha);var fa={Element:ha,isIE8:na.indexOf("MSIE 8.0")>-1,init:function(a,b,c){var d,e;this.alignedObjects=[];d=this.createElement(ga);e=d.element;e.style.position="relative";a.appendChild(d.element);this.box=e;this.boxWrapper=d;
this.setSize(b,c,!1);if(!C.namespaces.hcv)C.namespaces.add("hcv","urn:schemas-microsoft-com:vml"),C.createStyleSheet().cssText="hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke{ behavior:url(#default#VML); display: inline-block; } "},isHidden:function(){return!this.box.offsetWidth},clipRect:function(a,b,c,d){var e=this.createElement(),f=Y(a);return x(e,{members:[],left:f?a.x:a,top:f?a.y:b,width:f?a.width:c,height:f?a.height:d,getCSS:function(a){var b=a.inverted,c=this.top,d=this.left,e=d+this.width,
f=c+this.height,c={clip:"rect("+u(b?d:c)+"px,"+u(b?f:e)+"px,"+u(b?e:f)+"px,"+u(b?c:d)+"px)"};!b&&Ra&&a.element.nodeName!=="IMG"&&x(c,{width:e+"px",height:f+"px"});return c},updateClipping:function(){o(e.members,function(a){a.css(e.getCSS(a))})}})},color:function(a,b,c,d){var e=this,f,g=/^rgba/,h,i,j=Q;a&&a.linearGradient?i="gradient":a&&a.radialGradient&&(i="pattern");if(i){var k,l,m=a.linearGradient||a.radialGradient,q,p,n,t,H,r="",a=a.stops,v,s=[],u=function(){h=['<fill colors="'+s.join(",")+'" opacity="',
n,'" o:opacity2="',p,'" type="',i,'" ',r,'focus="100%" method="any" />'];T(e.prepVML(h),null,null,b)};q=a[0];v=a[a.length-1];q[0]>0&&a.unshift([0,q[1]]);v[0]<1&&a.push([1,v[1]]);o(a,function(a,b){g.test(a[1])?(f=qa(a[1]),k=f.get("rgb"),l=f.get("a")):(k=a[1],l=1);s.push(a[0]*100+"% "+k);b?(n=l,t=k):(p=l,H=k)});if(c==="fill")if(i==="gradient")c=m.x1||m[0]||0,a=m.y1||m[1]||0,q=m.x2||m[2]||0,m=m.y2||m[3]||0,r='angle="'+(90-K.atan((m-a)/(q-c))*180/Aa)+'"',u();else{var j=m.r,E=j*2,S=j*2,x=m.cx,A=m.cy,w=
b.radialReference,z,j=function(){w&&(z=d.getBBox(),x+=(w[0]-z.x)/z.width-0.5,A+=(w[1]-z.y)/z.height-0.5,E*=w[2]/z.width,S*=w[2]/z.height);r='src="'+N.global.VMLRadialGradientURL+'" size="'+E+","+S+'" origin="0.5,0.5" position="'+x+","+A+'" color2="'+H+'" ';u()};d.added?j():J(d,"add",j);j=t}else j=k}else if(g.test(a)&&b.tagName!=="IMG")f=qa(a),h=["<",c,' opacity="',f.get("a"),'"/>'],T(this.prepVML(h),null,null,b),j=f.get("rgb");else{j=b.getElementsByTagName(c);if(j.length)j[0].opacity=1;j=a}return j},
prepVML:function(a){var b=this.isIE8,a=a.join("");b?(a=a.replace("/>",' xmlns="urn:schemas-microsoft-com:vml" />'),a=a.indexOf('style="')===-1?a.replace("/>",' style="display:inline-block;behavior:url(#default#VML);" />'):a.replace('style="','style="display:inline-block;behavior:url(#default#VML);')):a=a.replace("<","<hcv:");return a},text:sa.prototype.html,path:function(a){var b={coordsize:"10 10"};Ia(a)?b.d=a:Y(a)&&x(b,a);return this.createElement("shape").attr(b)},circle:function(a,b,c){return this.symbol("circle").attr({x:a-
c,y:b-c,width:2*c,height:2*c})},g:function(a){var b;a&&(b={className:"highcharts-"+a,"class":"highcharts-"+a});return this.createElement(ga).attr(b)},image:function(a,b,c,d,e){var f=this.createElement("img").attr({src:a});arguments.length>1&&f.attr({x:b,y:c,width:d,height:e});return f},rect:function(a,b,c,d,e,f){if(Y(a))b=a.y,c=a.width,d=a.height,f=a.strokeWidth,a=a.x;var g=this.symbol("rect");g.r=e;return g.attr(g.crisp(f,a,b,s(c,0),s(d,0)))},invertChild:function(a,b){var c=b.style;I(a,{flip:"x",
left:z(c.width)-1,top:z(c.height)-1,rotation:-90})},symbols:{arc:function(a,b,c,d,e){var f=e.start,g=e.end,h=e.r||c||d,c=W(f),d=Z(f),i=W(g),j=Z(g),k=e.innerR,l=0.08/h,m=k&&0.1/k||0;if(g-f===0)return["x"];else 2*Aa-g+f<l?i=-l:g-f<m&&(i=W(f+m));f=["wa",a-h,b-h,a+h,b+h,a+h*c,b+h*d,a+h*i,b+h*j];e.open&&!k&&f.push("e","M",a,b);f.push("at",a-k,b-k,a+k,b+k,a+k*i,b+k*j,a+k*c,b+k*d,"x","e");return f},circle:function(a,b,c,d){return["wa",a,b,a+c,b+d,a+c,b+d/2,a+c,b+d/2,"e"]},rect:function(a,b,c,d,e){var f=
a+c,g=b+d,h;!r(e)||!e.r?f=sa.prototype.symbols.square.apply(0,arguments):(h=O(e.r,c,d),f=["M",a+h,b,"L",f-h,b,"wa",f-2*h,b,f,b+2*h,f-h,b,f,b+h,"L",f,g-h,"wa",f-2*h,g-2*h,f,g,f,g-h,f-h,g,"L",a+h,g,"wa",a,g-2*h,a+2*h,g,a+h,g,a,g-h,"L",a,b+h,"wa",a,b,a+2*h,b+2*h,a,b+h,a+h,b,"x","e"]);return f}}};ha=function(){this.init.apply(this,arguments)};ha.prototype=B(sa.prototype,fa);Sa=ha}var gb,Rb;if(V)gb=function(){oa="http://www.w3.org/1999/xhtml"},gb.prototype.symbols={},Rb=function(){function a(){var a=b.length,
d;for(d=0;d<a;d++)b[d]();b=[]}var b=[];return{push:function(c,d){b.length===0&&Tb(d,a);b.push(c)}}}();Sa=ha||gb||sa;Qa.prototype={addLabel:function(){var a=this.axis,b=a.options,c=a.chart,d=a.horiz,e=a.categories,f=this.pos,g=b.labels,h=a.tickPositions,d=e&&d&&e.length&&!g.step&&!g.staggerLines&&!g.rotation&&c.plotWidth/h.length||!d&&c.plotWidth/2,i=f===h[0],j=f===h[h.length-1],k=e&&r(e[f])?e[f]:f,e=this.label,h=h.info,l;a.isDatetimeAxis&&h&&(l=b.dateTimeLabelFormats[h.higherRanks[f]||h.unitName]);
this.isFirst=i;this.isLast=j;b=a.labelFormatter.call({axis:a,chart:c,isFirst:i,isLast:j,dateTimeLabelFormat:l,value:a.isLog?da(aa(k)):k});f=d&&{width:s(1,u(d-2*(g.padding||10)))+"px"};f=x(f,g.style);if(r(e))e&&e.attr({text:b}).css(f);else{d={align:g.align};if(Da(g.rotation))d.rotation=g.rotation;this.label=r(b)&&g.enabled?c.renderer.text(b,0,0,g.useHTML).attr(d).css(f).add(a.labelGroup):null}},getLabelSize:function(){var a=this.label,b=this.axis;return a?(this.labelBBox=a.getBBox())[b.horiz?"height":
"width"]:0},getLabelSides:function(){var a=this.axis.options.labels,b=this.labelBBox.width,a=b*{left:0,center:0.5,right:1}[a.align]-a.x;return[-a,b-a]},handleOverflow:function(a,b){var c=!0,d=this.axis,e=d.chart,f=this.isFirst,g=this.isLast,h=b.x,i=d.reversed,j=d.tickPositions;if(f||g){var k=this.getLabelSides(),l=k[0],k=k[1],e=e.plotLeft,m=e+d.len,j=(d=d.ticks[j[a+(f?1:-1)]])&&d.label.xy&&d.label.xy.x+d.getLabelSides()[f?0:1];f&&!i||g&&i?h+l<e&&(h=e-l,d&&h+k>j&&(c=!1)):h+k>m&&(h=m-k,d&&h+l<j&&(c=
!1));b.x=h}return c},getPosition:function(a,b,c,d){var e=this.axis,f=e.chart,g=d&&f.oldChartHeight||f.chartHeight;return{x:a?e.translate(b+c,null,null,d)+e.transB:e.left+e.offset+(e.opposite?(d&&f.oldChartWidth||f.chartWidth)-e.right-e.left:0),y:a?g-e.bottom+e.offset-(e.opposite?e.height:0):g-e.translate(b+c,null,null,d)-e.transB}},getLabelPosition:function(a,b,c,d,e,f,g,h){var i=this.axis,j=i.transA,k=i.reversed,i=i.staggerLines,a=a+e.x-(f&&d?f*j*(k?-1:1):0),b=b+e.y-(f&&!d?f*j*(k?1:-1):0);r(e.y)||
(b+=z(c.styles.lineHeight)*0.9-c.getBBox().height/2);i&&(b+=g/(h||1)%i*16);return{x:a,y:b}},getMarkPath:function(a,b,c,d,e,f){return f.crispLine(["M",a,b,"L",a+(e?0:-c),b+(e?c:0)],d)},render:function(a,b){var c=this.axis,d=c.options,e=c.chart.renderer,f=c.horiz,g=this.type,h=this.label,i=this.pos,j=d.labels,k=this.gridLine,l=g?g+"Grid":"grid",m=g?g+"Tick":"tick",q=d[l+"LineWidth"],p=d[l+"LineColor"],y=d[l+"LineDashStyle"],t=d[m+"Length"],l=d[m+"Width"]||0,o=d[m+"Color"],r=d[m+"Position"],m=this.mark,
v=j.step,s=!0,u=c.tickmarkOffset,E=this.getPosition(f,i,u,b),S=E.x,E=E.y,x=c.staggerLines;if(q){i=c.getPlotLinePath(i+u,q,b);if(k===A){k={stroke:p,"stroke-width":q};if(y)k.dashstyle=y;if(!g)k.zIndex=1;this.gridLine=k=q?e.path(i).attr(k).add(c.gridGroup):null}if(!b&&k&&i)k[this.isNew?"attr":"animate"]({d:i})}if(l&&t)r==="inside"&&(t=-t),c.opposite&&(t=-t),g=this.getMarkPath(S,E,t,l,f,e),m?m.animate({d:g}):this.mark=e.path(g).attr({stroke:o,"stroke-width":l}).add(c.axisGroup);if(h&&!isNaN(S))h.xy=E=
this.getLabelPosition(S,E,h,f,j,u,a,v),this.isFirst&&!n(d.showFirstLabel,1)||this.isLast&&!n(d.showLastLabel,1)?s=!1:!x&&f&&j.overflow==="justify"&&!this.handleOverflow(a,E)&&(s=!1),v&&a%v&&(s=!1),s?(h[this.isNew?"attr":"animate"](E),this.isNew=!1):h.attr("y",-9999)},destroy:function(){Ga(this,this.axis)}};nb.prototype={render:function(){var a=this,b=a.axis,c=b.horiz,d=(b.pointRange||0)/2,e=a.options,f=e.label,g=a.label,h=e.width,i=e.to,j=e.from,k=r(j)&&r(i),l=e.value,m=e.dashStyle,q=a.svgElem,p=
[],y,t=e.color,o=e.zIndex,u=e.events,v=b.chart.renderer;b.isLog&&(j=ka(j),i=ka(i),l=ka(l));if(h){if(p=b.getPlotLinePath(l,h),d={stroke:t,"stroke-width":h},m)d.dashstyle=m}else if(k){if(j=s(j,b.min-d),i=O(i,b.max+d),p=b.getPlotBandPath(j,i,e),d={fill:t},e.borderWidth)d.stroke=e.borderColor,d["stroke-width"]=e.borderWidth}else return;if(r(o))d.zIndex=o;if(q)p?q.animate({d:p},null,q.onGetPath):(q.hide(),q.onGetPath=function(){q.show()});else if(p&&p.length&&(a.svgElem=q=v.path(p).attr(d).add(),u))for(y in e=
function(b){q.on(b,function(c){u[b].apply(a,[c])})},u)e(y);if(f&&r(f.text)&&p&&p.length&&b.width>0&&b.height>0){f=B({align:c&&k&&"center",x:c?!k&&4:10,verticalAlign:!c&&k&&"middle",y:c?k?16:10:k?6:-4,rotation:c&&!k&&90},f);if(!g)a.label=g=v.text(f.text,0,0).attr({align:f.textAlign||f.align,rotation:f.rotation,zIndex:o}).css(f.style).add();b=[p[1],p[4],n(p[6],p[1])];p=[p[2],p[5],n(p[7],p[2])];c=Fa(b);k=Fa(p);g.align(f,!1,{x:c,y:k,width:wa(b)-c,height:wa(p)-k});g.show()}else g&&g.hide();return a},destroy:function(){ta(this.axis.plotLinesAndBands,
this);Ga(this,this.axis)}};Kb.prototype={destroy:function(){Ga(this,this.axis)},setTotal:function(a){this.cum=this.total=a},render:function(a){var b=this.options.formatter.call(this);this.label?this.label.attr({text:b,visibility:"hidden"}):this.label=this.axis.chart.renderer.text(b,0,0).css(this.options.style).attr({align:this.textAlign,rotation:this.options.rotation,visibility:"hidden"}).add(a)},setOffset:function(a,b){var c=this.axis,d=c.chart,e=d.inverted,f=this.isNegative,g=c.translate(this.percent?
100:this.total,0,0,0,1),c=c.translate(0),c=M(g-c),h=d.xAxis[0].translate(this.x)+a,i=d.plotHeight,f={x:e?f?g:g-c:h,y:e?i-h-b:f?i-g-c:i-g,width:e?c:b,height:e?b:c};if(e=this.label)e.align(this.alignOptions,null,f),f=e.alignAttr,e.attr({visibility:this.options.crop===!1||d.isInsidePlot(f.x,f.y)?ca?"inherit":"visible":"hidden"})}};ob.prototype={defaultOptions:{dateTimeLabelFormats:{millisecond:"%H:%M:%S.%L",second:"%H:%M:%S",minute:"%H:%M",hour:"%H:%M",day:"%e. %b",week:"%e. %b",month:"%b '%y",year:"%Y"},
endOnTick:!1,gridLineColor:"#C0C0C0",labels:G,lineColor:"#C0D0E0",lineWidth:1,minPadding:0.01,maxPadding:0.01,minorGridLineColor:"#E0E0E0",minorGridLineWidth:1,minorTickColor:"#A0A0A0",minorTickLength:2,minorTickPosition:"outside",startOfWeek:1,startOnTick:!1,tickColor:"#C0D0E0",tickLength:5,tickmarkPlacement:"between",tickPixelInterval:100,tickPosition:"outside",tickWidth:1,title:{align:"middle",style:{color:"#6D869F",fontWeight:"bold"}},type:"linear"},defaultYAxisOptions:{endOnTick:!0,gridLineWidth:1,
tickPixelInterval:72,showLastLabel:!0,labels:{align:"right",x:-8,y:3},lineWidth:0,maxPadding:0.05,minPadding:0.05,startOnTick:!0,tickWidth:0,title:{rotation:270,text:"Y-values"},stackLabels:{enabled:!1,formatter:function(){return this.total},style:G.style}},defaultLeftAxisOptions:{labels:{align:"right",x:-8,y:null},title:{rotation:270}},defaultRightAxisOptions:{labels:{align:"left",x:8,y:null},title:{rotation:90}},defaultBottomAxisOptions:{labels:{align:"center",x:0,y:14},title:{rotation:0}},defaultTopAxisOptions:{labels:{align:"center",
x:0,y:-5},title:{rotation:0}},init:function(a,b){var c=b.isX;this.horiz=a.inverted?!c:c;this.xOrY=(this.isXAxis=c)?"x":"y";this.opposite=b.opposite;this.side=this.horiz?this.opposite?0:2:this.opposite?1:3;this.setOptions(b);var d=this.options,e=d.type,f=e==="datetime";this.labelFormatter=d.labels.formatter||this.defaultLabelFormatter;this.staggerLines=this.horiz&&d.labels.staggerLines;this.userOptions=b;this.minPixelPadding=0;this.chart=a;this.reversed=d.reversed;this.categories=d.categories;this.isLog=
e==="logarithmic";this.isLinked=r(d.linkedTo);this.isDatetimeAxis=f;this.tickmarkOffset=d.categories&&d.tickmarkPlacement==="between"?0.5:0;this.ticks={};this.minorTicks={};this.plotLinesAndBands=[];this.alternateBands={};this.len=0;this.minRange=this.userMinRange=d.minRange||d.maxZoom;this.range=d.range;this.offset=d.offset||0;this.stacks={};this.min=this.max=null;var g,d=this.options.events;a.axes.push(this);a[c?"xAxis":"yAxis"].push(this);this.series=[];if(a.inverted&&c&&this.reversed===A)this.reversed=
!0;this.removePlotLine=this.removePlotBand=this.removePlotBandOrLine;this.addPlotLine=this.addPlotBand=this.addPlotBandOrLine;for(g in d)J(this,g,d[g]);if(this.isLog)this.val2lin=ka,this.lin2val=aa},setOptions:function(a){this.options=B(this.defaultOptions,this.isXAxis?{}:this.defaultYAxisOptions,[this.defaultTopAxisOptions,this.defaultRightAxisOptions,this.defaultBottomAxisOptions,this.defaultLeftAxisOptions][this.side],B(N[this.isXAxis?"xAxis":"yAxis"],a))},defaultLabelFormatter:function(){var a=
this.axis,b=this.value,c=this.dateTimeLabelFormat,d=N.lang.numericSymbols,e=d&&d.length,f,g=a.isLog?b:a.tickInterval;if(a.categories)f=b;else if(c)f=db(c,b);else if(e&&g>=1E3)for(;e--&&f===A;)a=Math.pow(1E3,e+1),g>=a&&d[e]!==null&&(f=Ja(b/a,-1)+d[e]);f===A&&(f=b>=1E3?Ja(b,0):Ja(b,-1));return f},getSeriesExtremes:function(){var a=this,b=a.chart,c=a.stacks,d=[],e=[],f;a.hasVisibleSeries=!1;a.dataMin=a.dataMax=null;o(a.series,function(g){if(g.visible||!b.options.chart.ignoreHiddenSeries){var h=g.options,
i,j,k,l,m,q,p,y,t,o=h.threshold,u,v=[],x=0;a.hasVisibleSeries=!0;if(a.isLog&&o<=0)o=h.threshold=null;if(a.isXAxis){if(h=g.xData,h.length)a.dataMin=O(n(a.dataMin,h[0]),Fa(h)),a.dataMax=s(n(a.dataMax,h[0]),wa(h))}else{var z,E,S,w=g.cropped,B=g.xAxis.getExtremes(),C=!!g.modifyValue;i=h.stacking;a.usePercentage=i==="percent";if(i)m=h.stack,l=g.type+n(m,""),q="-"+l,g.stackKey=l,j=d[l]||[],d[l]=j,k=e[q]||[],e[q]=k;if(a.usePercentage)a.dataMin=0,a.dataMax=99;h=g.processedXData;p=g.processedYData;u=p.length;
for(f=0;f<u;f++)if(y=h[f],t=p[f],i&&(E=(z=t<o)?k:j,S=z?q:l,r(E[y])?(E[y]=da(E[y]+t),t=[t,E[y]]):E[y]=t,c[S]||(c[S]={}),c[S][y]||(c[S][y]=new Kb(a,a.options.stackLabels,z,y,m,i)),c[S][y].setTotal(E[y])),t!==null&&t!==A&&(C&&(t=g.modifyValue(t)),w||(h[f+1]||y)>=B.min&&(h[f-1]||y)<=B.max))if(y=t.length)for(;y--;)t[y]!==null&&(v[x++]=t[y]);else v[x++]=t;if(!a.usePercentage&&v.length)a.dataMin=O(n(a.dataMin,v[0]),Fa(v)),a.dataMax=s(n(a.dataMax,v[0]),wa(v));if(r(o))if(a.dataMin>=o)a.dataMin=o,a.ignoreMinPadding=
!0;else if(a.dataMax<o)a.dataMax=o,a.ignoreMaxPadding=!0}}})},translate:function(a,b,c,d,e,f){var g=this.len,h=1,i=0,j=d?this.oldTransA:this.transA,d=d?this.oldMin:this.min,e=this.options.ordinal||this.isLog&&e;if(!j)j=this.transA;c&&(h*=-1,i=g);this.reversed&&(h*=-1,i-=h*g);b?(this.reversed&&(a=g-a),a=a/j+d,e&&(a=this.lin2val(a))):(e&&(a=this.val2lin(a)),a=h*(a-d)*j+i+h*this.minPixelPadding+(f?j*this.pointRange/2:0));return a},getPlotLinePath:function(a,b,c){var d=this.chart,e=this.left,f=this.top,
g,h,i,a=this.translate(a,null,null,c),j=c&&d.oldChartHeight||d.chartHeight,k=c&&d.oldChartWidth||d.chartWidth,l;g=this.transB;c=h=u(a+g);g=i=u(j-a-g);if(isNaN(a))l=!0;else if(this.horiz){if(g=f,i=j-this.bottom,c<e||c>e+this.width)l=!0}else if(c=e,h=k-this.right,g<f||g>f+this.height)l=!0;return l?null:d.renderer.crispLine(["M",c,g,"L",h,i],b||0)},getPlotBandPath:function(a,b){var c=this.getPlotLinePath(b),d=this.getPlotLinePath(a);d&&c?d.push(c[4],c[5],c[1],c[2]):d=null;return d},getLinearTickPositions:function(a,
b,c){for(var d,b=da(U(b/a)*a),c=da(za(c/a)*a),e=[];b<=c;){e.push(b);b=da(b+a);if(b===d)break;d=b}return e},getLogTickPositions:function(a,b,c,d){var e=this.options,f=this.len,g=[];if(!d)this._minorAutoInterval=null;if(a>=0.5)a=u(a),g=this.getLinearTickPositions(a,b,c);else if(a>=0.08)for(var f=U(b),h,i,j,k,l,e=a>0.3?[1,2,4]:a>0.15?[1,2,4,6,8]:[1,2,3,4,5,6,7,8,9];f<c+1&&!l;f++){i=e.length;for(h=0;h<i&&!l;h++)j=ka(aa(f)*e[h]),j>b&&g.push(k),k>c&&(l=!0),k=j}else if(b=aa(b),c=aa(c),a=e[d?"minorTickInterval":
"tickInterval"],a=n(a==="auto"?null:a,this._minorAutoInterval,(c-b)*(e.tickPixelInterval/(d?5:1))/((d?f/this.tickPositions.length:f)||1)),a=hb(a,null,K.pow(10,U(K.log(a)/K.LN10))),g=Ta(this.getLinearTickPositions(a,b,c),ka),!d)this._minorAutoInterval=a/5;if(!d)this.tickInterval=a;return g},getMinorTickPositions:function(){var a=this.options,b=this.tickPositions,c=this.minorTickInterval,d=[],e;if(this.isLog){e=b.length;for(a=1;a<e;a++)d=d.concat(this.getLogTickPositions(c,b[a-1],b[a],!0))}else if(this.isDatetimeAxis&&
a.minorTickInterval==="auto")d=d.concat(Cb(Ab(c),this.min,this.max,a.startOfWeek));else for(b=this.min+(b[0]-this.min)%c;b<=this.max;b+=c)d.push(b);return d},adjustForMinRange:function(){var a=this.options,b=this.min,c=this.max,d,e=this.dataMax-this.dataMin>=this.minRange,f,g,h,i,j;if(this.isXAxis&&this.minRange===A&&!this.isLog)r(a.min)||r(a.max)?this.minRange=null:(o(this.series,function(a){i=a.xData;for(g=j=a.xIncrement?1:i.length-1;g>0;g--)if(h=i[g]-i[g-1],f===A||h<f)f=h}),this.minRange=O(f*5,
this.dataMax-this.dataMin));if(c-b<this.minRange){var k=this.minRange;d=(k-c+b)/2;d=[b-d,n(a.min,b-d)];if(e)d[2]=this.dataMin;b=wa(d);c=[b+k,n(a.max,b+k)];if(e)c[2]=this.dataMax;c=Fa(c);c-b<k&&(d[0]=c-k,d[1]=n(a.min,c-k),b=wa(d))}this.min=b;this.max=c},setAxisTranslation:function(){var a=this.max-this.min,b=0,c,d=0,e=0,f=this.linkedParent,g=this.transA;if(this.isXAxis)f?(d=f.minPointOffset,e=f.pointRangePadding):o(this.series,function(a){var f=a.pointRange,g=a.options.pointPlacement,k=a.closestPointRange;
b=s(b,f);d=s(d,g?0:f/2);e=s(e,g==="on"?0:f);!a.noSharedTooltip&&r(k)&&(c=r(c)?O(c,k):k)}),this.minPointOffset=d,this.pointRangePadding=e,this.pointRange=b,this.closestPointRange=c;this.oldTransA=g;this.translationSlope=this.transA=g=this.len/(a+e||1);this.transB=this.horiz?this.left:this.bottom;this.minPixelPadding=g*d},setTickPositions:function(a){var b=this,c=b.chart,d=b.options,e=b.isLog,f=b.isDatetimeAxis,g=b.isXAxis,h=b.isLinked,i=b.options.tickPositioner,j=d.maxPadding,k=d.minPadding,l=d.tickInterval,
m=d.minTickInterval,q=d.tickPixelInterval,p=b.categories;h?(b.linkedParent=c[g?"xAxis":"yAxis"][d.linkedTo],c=b.linkedParent.getExtremes(),b.min=n(c.min,c.dataMin),b.max=n(c.max,c.dataMax),d.type!==b.linkedParent.options.type&&Oa(11,1)):(b.min=n(b.userMin,d.min,b.dataMin),b.max=n(b.userMax,d.max,b.dataMax));if(e)!a&&O(b.min,n(b.dataMin,b.min))<=0&&Oa(10,1),b.min=da(ka(b.min)),b.max=da(ka(b.max));if(b.range&&(b.userMin=b.min=s(b.min,b.max-b.range),b.userMax=b.max,a))b.range=null;b.adjustForMinRange();
if(!p&&!b.usePercentage&&!h&&r(b.min)&&r(b.max)&&(c=b.max-b.min)){if(!r(d.min)&&!r(b.userMin)&&k&&(b.dataMin<0||!b.ignoreMinPadding))b.min-=c*k;if(!r(d.max)&&!r(b.userMax)&&j&&(b.dataMax>0||!b.ignoreMaxPadding))b.max+=c*j}b.tickInterval=b.min===b.max||b.min===void 0||b.max===void 0?1:h&&!l&&q===b.linkedParent.options.tickPixelInterval?b.linkedParent.tickInterval:n(l,p?1:(b.max-b.min)*q/(b.len||1));g&&!a&&o(b.series,function(a){a.processData(b.min!==b.oldMin||b.max!==b.oldMax)});b.setAxisTranslation(a);
b.beforeSetTickPositions&&b.beforeSetTickPositions();if(b.postProcessTickInterval)b.tickInterval=b.postProcessTickInterval(b.tickInterval);if(!l&&b.tickInterval<m)b.tickInterval=m;if(!f&&!e&&(a=K.pow(10,U(K.log(b.tickInterval)/K.LN10)),!l))b.tickInterval=hb(b.tickInterval,null,a,d);b.minorTickInterval=d.minorTickInterval==="auto"&&b.tickInterval?b.tickInterval/5:d.minorTickInterval;b.tickPositions=i=d.tickPositions||i&&i.apply(b,[b.min,b.max]);if(!i)i=f?(b.getNonLinearTimeTicks||Cb)(Ab(b.tickInterval,
d.units),b.min,b.max,d.startOfWeek,b.ordinalPositions,b.closestPointRange,!0):e?b.getLogTickPositions(b.tickInterval,b.min,b.max):b.getLinearTickPositions(b.tickInterval,b.min,b.max),b.tickPositions=i;if(!h)e=i[0],f=i[i.length-1],h=b.minPointOffset||0,d.startOnTick?b.min=e:b.min-h>e&&i.shift(),d.endOnTick?b.max=f:b.max+h<f&&i.pop(),i.length===1&&(b.min-=1.0E-9,b.max+=1.0E-9)},setMaxTicks:function(){var a=this.chart,b=a.maxTicks,c=this.tickPositions,d=this.xOrY;b||(b={x:0,y:0});if(!this.isLinked&&
!this.isDatetimeAxis&&c.length>b[d]&&this.options.alignTicks!==!1)b[d]=c.length;a.maxTicks=b},adjustTickAmount:function(){var a=this.xOrY,b=this.tickPositions,c=this.chart.maxTicks;if(c&&c[a]&&!this.isDatetimeAxis&&!this.categories&&!this.isLinked&&this.options.alignTicks!==!1){var d=this.tickAmount,e=b.length;this.tickAmount=a=c[a];if(e<a){for(;b.length<a;)b.push(da(b[b.length-1]+this.tickInterval));this.transA*=(e-1)/(a-1);this.max=b[b.length-1]}if(r(d)&&a!==d)this.isDirty=!0}},setScale:function(){var a=
this.stacks,b,c,d,e;this.oldMin=this.min;this.oldMax=this.max;this.oldAxisLength=this.len;this.setAxisSize();e=this.len!==this.oldAxisLength;o(this.series,function(a){if(a.isDirtyData||a.isDirty||a.xAxis.isDirty)d=!0});if(e||d||this.isLinked||this.userMin!==this.oldUserMin||this.userMax!==this.oldUserMax)if(this.getSeriesExtremes(),this.setTickPositions(),this.oldUserMin=this.userMin,this.oldUserMax=this.userMax,!this.isDirty)this.isDirty=e||this.min!==this.oldMin||this.max!==this.oldMax;if(!this.isXAxis)for(b in a)for(c in a[b])a[b][c].cum=
a[b][c].total;this.setMaxTicks()},setExtremes:function(a,b,c,d,e){var f=this,g=f.chart,c=n(c,!0),e=x(e,{min:a,max:b});F(f,"setExtremes",e,function(){f.userMin=a;f.userMax=b;f.isDirtyExtremes=!0;c&&g.redraw(d)})},zoom:function(a,b){this.setExtremes(a,b,!1,A,{trigger:"zoom"});return!0},setAxisSize:function(){var a=this.chart,b=this.options,c=b.offsetLeft||0,d=b.offsetRight||0;this.left=n(b.left,a.plotLeft+c);this.top=n(b.top,a.plotTop);this.width=n(b.width,a.plotWidth-c+d);this.height=n(b.height,a.plotHeight);
this.bottom=a.chartHeight-this.height-this.top;this.right=a.chartWidth-this.width-this.left;this.len=s(this.horiz?this.width:this.height,0)},getExtremes:function(){var a=this.isLog;return{min:a?da(aa(this.min)):this.min,max:a?da(aa(this.max)):this.max,dataMin:this.dataMin,dataMax:this.dataMax,userMin:this.userMin,userMax:this.userMax}},getThreshold:function(a){var b=this.isLog,c=b?aa(this.min):this.min,b=b?aa(this.max):this.max;c>a||a===null?a=c:b<a&&(a=b);return this.translate(a,0,1,0,1)},addPlotBandOrLine:function(a){a=
(new nb(this,a)).render();this.plotLinesAndBands.push(a);return a},getOffset:function(){var a=this,b=a.chart,c=b.renderer,d=a.options,e=a.tickPositions,f=a.ticks,g=a.horiz,h=a.side,i,j=0,k,l=0,m=d.title,q=d.labels,p=0,y=b.axisOffset,t=[-1,1,1,-1][h],H;a.hasData=b=a.hasVisibleSeries||r(a.min)&&r(a.max)&&!!e;a.showAxis=i=b||n(d.showEmpty,!0);if(!a.axisGroup)a.gridGroup=c.g("grid").attr({zIndex:d.gridZIndex||1}).add(),a.axisGroup=c.g("axis").attr({zIndex:d.zIndex||2}).add(),a.labelGroup=c.g("axis-labels").attr({zIndex:q.zIndex||
7}).add();if(b||a.isLinked)o(e,function(b){f[b]?f[b].addLabel():f[b]=new Qa(a,b)}),o(e,function(a){if(h===0||h===2||{1:"left",3:"right"}[h]===q.align)p=s(f[a].getLabelSize(),p)}),a.staggerLines&&(p+=(a.staggerLines-1)*16);else for(H in f)f[H].destroy(),delete f[H];if(m&&m.text){if(!a.axisTitle)a.axisTitle=c.text(m.text,0,0,m.useHTML).attr({zIndex:7,rotation:m.rotation||0,align:m.textAlign||{low:"left",middle:"center",high:"right"}[m.align]}).css(m.style).add(a.axisGroup),a.axisTitle.isNew=!0;if(i)j=
a.axisTitle.getBBox()[g?"height":"width"],l=n(m.margin,g?5:10),k=m.offset;a.axisTitle[i?"show":"hide"]()}a.offset=t*n(d.offset,y[h]);a.axisTitleMargin=n(k,p+l+(h!==2&&p&&t*d.labels[g?"y":"x"]));y[h]=s(y[h],a.axisTitleMargin+j+t*a.offset)},getLinePath:function(a){var b=this.chart,c=this.opposite,d=this.offset,e=this.horiz,f=this.left+(c?this.width:0)+d;this.lineTop=c=b.chartHeight-this.bottom-(c?this.height:0)+d;return b.renderer.crispLine(["M",e?this.left:f,e?c:this.top,"L",e?b.chartWidth-this.right:
f,e?c:b.chartHeight-this.bottom],a)},getTitlePosition:function(){var a=this.horiz,b=this.left,c=this.top,d=this.len,e=this.options.title,f=a?b:c,g=this.opposite,h=this.offset,i=z(e.style.fontSize||12),d={low:f+(a?0:d),middle:f+d/2,high:f+(a?d:0)}[e.align],b=(a?c+this.height:b)+(a?1:-1)*(g?-1:1)*this.axisTitleMargin+(this.side===2?i:0);return{x:a?d:b+(g?this.width:0)+h+(e.x||0),y:a?b-(g?this.height:0)+h:d+(e.y||0)}},render:function(){var a=this,b=a.chart,c=b.renderer,d=a.options,e=a.isLog,f=a.isLinked,
g=a.tickPositions,h=a.axisTitle,i=a.stacks,j=a.ticks,k=a.minorTicks,l=a.alternateBands,m=d.stackLabels,q=d.alternateGridColor,p=a.tickmarkOffset,n=d.lineWidth,t,H=b.hasRendered&&r(a.oldMin)&&!isNaN(a.oldMin),u=a.showAxis,v,s;if(a.hasData||f)if(a.minorTickInterval&&!a.categories&&o(a.getMinorTickPositions(),function(b){k[b]||(k[b]=new Qa(a,b,"minor"));H&&k[b].isNew&&k[b].render(null,!0);k[b].isActive=!0;k[b].render()}),g.length&&o(g.slice(1).concat([g[0]]),function(b,c){c=c===g.length-1?0:c+1;if(!f||
b>=a.min&&b<=a.max)j[b]||(j[b]=new Qa(a,b)),H&&j[b].isNew&&j[b].render(c,!0),j[b].isActive=!0,j[b].render(c)}),q&&o(g,function(b,c){if(c%2===0&&b<a.max)l[b]||(l[b]=new nb(a)),v=b+p,s=g[c+1]!==A?g[c+1]+p:a.max,l[b].options={from:e?aa(v):v,to:e?aa(s):s,color:q},l[b].render(),l[b].isActive=!0}),!a._addedPlotLB)o((d.plotLines||[]).concat(d.plotBands||[]),function(b){a.addPlotBandOrLine(b)}),a._addedPlotLB=!0;o([j,k,l],function(a){for(var b in a)a[b].isActive?a[b].isActive=!1:(a[b].destroy(),delete a[b])});
if(n)t=a.getLinePath(n),a.axisLine?a.axisLine.animate({d:t}):a.axisLine=c.path(t).attr({stroke:d.lineColor,"stroke-width":n,zIndex:7}).add(a.axisGroup),a.axisLine[u?"show":"hide"]();if(h&&u)h[h.isNew?"attr":"animate"](a.getTitlePosition()),h.isNew=!1;if(m&&m.enabled){var x,E,d=a.stackTotalGroup;if(!d)a.stackTotalGroup=d=c.g("stack-labels").attr({visibility:"visible",zIndex:6}).add();d.translate(b.plotLeft,b.plotTop);for(x in i)for(E in b=i[x],b)b[E].render(d)}a.isDirty=!1},removePlotBandOrLine:function(a){for(var b=
this.plotLinesAndBands,c=b.length;c--;)b[c].id===a&&b[c].destroy()},setTitle:function(a,b){var c=this.chart,d=this.options,e=this.axisTitle;d.title=B(d.title,a);this.axisTitle=e&&e.destroy();this.isDirty=!0;n(b,!0)&&c.redraw()},redraw:function(){var a=this.chart;a.tracker.resetTracker&&a.tracker.resetTracker(!0);this.render();o(this.plotLinesAndBands,function(a){a.render()});o(this.series,function(a){a.isDirty=!0})},setCategories:function(a,b){var c=this.chart;this.categories=this.userOptions.categories=
a;o(this.series,function(a){a.translate();a.setTooltipPoints(!0)});this.isDirty=!0;n(b,!0)&&c.redraw()},destroy:function(){var a=this,b=a.stacks,c;R(a);for(c in b)Ga(b[c]),b[c]=null;o([a.ticks,a.minorTicks,a.alternateBands,a.plotLinesAndBands],function(a){Ga(a)});o("stackTotalGroup,axisLine,axisGroup,gridGroup,labelGroup,axisTitle".split(","),function(b){a[b]&&(a[b]=a[b].destroy())})}};pb.prototype={destroy:function(){o(this.crosshairs,function(a){a&&a.destroy()});if(this.label)this.label=this.label.destroy()},
move:function(a,b,c,d){var e=this,f=e.now,g=e.options.animation!==!1&&!e.isHidden;x(f,{x:g?(2*f.x+a)/3:a,y:g?(f.y+b)/2:b,anchorX:g?(2*f.anchorX+c)/3:c,anchorY:g?(f.anchorY+d)/2:d});e.label.attr(f);if(g&&(M(a-f.x)>1||M(b-f.y)>1))clearTimeout(this.tooltipTimeout),this.tooltipTimeout=setTimeout(function(){e&&e.move(a,b,c,d)},32)},hide:function(){if(!this.isHidden){var a=this.chart.hoverPoints;this.label.hide();a&&o(a,function(a){a.setState()});this.chart.hoverPoints=null;this.isHidden=!0}},hideCrosshairs:function(){o(this.crosshairs,
function(a){a&&a.hide()})},getAnchor:function(a,b){var c,d=this.chart,e=d.inverted,f=0,g=0,h,a=la(a);c=a[0].tooltipPos;c||(o(a,function(a){h=a.series.yAxis;f+=a.plotX;g+=(a.plotLow?(a.plotLow+a.plotHigh)/2:a.plotY)+(!e&&h?h.top-d.plotTop:0)}),f/=a.length,g/=a.length,c=[e?d.plotWidth-g:f,this.shared&&!e&&a.length>1&&b?b.chartY-d.plotTop:e?d.plotHeight-f:g]);return Ta(c,u)},getPosition:function(a,b,c){var d=this.chart,e=d.plotLeft,f=d.plotTop,g=d.plotWidth,h=d.plotHeight,i=n(this.options.distance,12),
j=c.plotX,c=c.plotY,d=j+e+(d.inverted?i:-a-i),k=c-b+f+15,l;d<7&&(d=e+s(j,0)+i);d+a>e+g&&(d-=d+a-(e+g),k=c-b+f-i,l=!0);k<f+5&&(k=f+5,l&&c>=k&&c<=k+b&&(k=c+f+i));k+b>f+h&&(k=s(f,f+h-b-i));return{x:d,y:k}},refresh:function(a,b){function c(){var a=this.points||la(this),b=a[0].series,c;c=[b.tooltipHeaderFormatter(a[0].key)];o(a,function(a){b=a.series;c.push(b.tooltipFormatter&&b.tooltipFormatter(a)||a.point.tooltipFormatter(b.tooltipOptions.pointFormat))});c.push(f.footerFormat||"");return c.join("")}
var d=this.chart,e=this.label,f=this.options,g,h,i,j={},k,l=[];k=f.formatter||c;var j=d.hoverPoints,m,q=f.crosshairs;i=this.shared;h=this.getAnchor(a,b);g=h[0];h=h[1];i&&(!a.series||!a.series.noSharedTooltip)?(d.hoverPoints=a,j&&o(j,function(a){a.setState()}),o(a,function(a){a.setState("hover");l.push(a.getLabelConfig())}),j={x:a[0].category,y:a[0].y},j.points=l,a=a[0]):j=a.getLabelConfig();k=k.call(j);j=a.series;i=i||!j.isCartesian||j.tooltipOutsidePlot||d.isInsidePlot(g,h);k===!1||!i?this.hide():
(this.isHidden&&e.show(),e.attr({text:k}),m=f.borderColor||a.color||j.color||"#606060",e.attr({stroke:m}),e=(f.positioner||this.getPosition).call(this,e.width,e.height,{plotX:g,plotY:h}),this.move(u(e.x),u(e.y),g+d.plotLeft,h+d.plotTop),this.isHidden=!1);if(q){q=la(q);for(e=q.length;e--;)if(i=a.series[e?"yAxis":"xAxis"],q[e]&&i)if(i=i.getPlotLinePath(e?n(a.stackY,a.y):a.x,1),this.crosshairs[e])this.crosshairs[e].attr({d:i,visibility:"visible"});else{j={"stroke-width":q[e].width||1,stroke:q[e].color||
"#C0C0C0",zIndex:q[e].zIndex||2};if(q[e].dashStyle)j.dashstyle=q[e].dashStyle;this.crosshairs[e]=d.renderer.path(i).attr(j).add()}}F(d,"tooltipRefresh",{text:k,x:g+d.plotLeft,y:h+d.plotTop,borderColor:m})}};qb.prototype={normalizeMouseEvent:function(a){var b,c,d,a=a||L.event;if(!a.target)a.target=a.srcElement;a=Pb(a);d=a.touches?a.touches.item(0):a;this.chartPosition=b=Vb(this.chart.container);d.pageX===A?(c=a.x,b=a.y):(c=d.pageX-b.left,b=d.pageY-b.top);return x(a,{chartX:u(c),chartY:u(b)})},getMouseCoordinates:function(a){var b=
{xAxis:[],yAxis:[]},c=this.chart;o(c.axes,function(d){var e=d.isXAxis;b[e?"xAxis":"yAxis"].push({axis:d,value:d.translate(((c.inverted?!e:e)?a.chartX-c.plotLeft:d.top+d.len-a.chartY)-d.minPixelPadding,!0)})});return b},getIndex:function(a){var b=this.chart;return b.inverted?b.plotHeight+b.plotTop-a.chartY:a.chartX-b.plotLeft},onmousemove:function(a){var b=this.chart,c=b.series,d=b.tooltip,e,f=b.hoverPoint,g=b.hoverSeries,h,i,j=b.chartWidth,k=this.getIndex(a);if(d&&this.options.tooltip.shared&&(!g||
!g.noSharedTooltip)){e=[];h=c.length;for(i=0;i<h;i++)if(c[i].visible&&c[i].options.enableMouseTracking!==!1&&!c[i].noSharedTooltip&&c[i].tooltipPoints&&c[i].tooltipPoints.length)b=c[i].tooltipPoints[k],b._dist=M(k-b[c[i].xAxis.tooltipPosName||"plotX"]),j=O(j,b._dist),e.push(b);for(h=e.length;h--;)e[h]._dist>j&&e.splice(h,1);if(e.length&&e[0].plotX!==this.hoverX)d.refresh(e,a),this.hoverX=e[0].plotX}if(g&&g.tracker&&(b=g.tooltipPoints[k])&&b!==f)b.onMouseOver()},resetTracker:function(a){var b=this.chart,
c=b.hoverSeries,d=b.hoverPoint,e=b.tooltip,b=e&&e.shared?b.hoverPoints:d;(a=a&&e&&b)&&la(b)[0].plotX===A&&(a=!1);if(a)e.refresh(b);else{if(d)d.onMouseOut();if(c)c.onMouseOut();e&&(e.hide(),e.hideCrosshairs());this.hoverX=null}},setDOMEvents:function(){function a(){if(b.selectionMarker){var f={xAxis:[],yAxis:[]},g=b.selectionMarker.getBBox(),h=g.x-c.plotLeft,l=g.y-c.plotTop,m;e&&(o(c.axes,function(a){if(a.options.zoomEnabled!==!1){var b=a.isXAxis,d=c.inverted?!b:b,e=a.translate(d?h:c.plotHeight-l-
g.height,!0,0,0,1),d=a.translate((d?h+g.width:c.plotHeight-l)-2*a.minPixelPadding,!0,0,0,1);!isNaN(e)&&!isNaN(d)&&(f[b?"xAxis":"yAxis"].push({axis:a,min:O(e,d),max:s(e,d)}),m=!0)}}),m&&F(c,"selection",f,function(a){c.zoom(a)}));b.selectionMarker=b.selectionMarker.destroy()}if(c)I(d,{cursor:"auto"}),c.cancelClick=e,c.mouseIsDown=e=!1;R(C,"mouseup",a);Ba&&R(C,"touchend",a)}var b=this,c=b.chart,d=c.container,e,f=b.zoomX&&!c.inverted||b.zoomY&&c.inverted,g=b.zoomY&&!c.inverted||b.zoomX&&c.inverted;b.hideTooltipOnMouseMove=
function(a){a=Pb(a);b.chartPosition&&c.hoverSeries&&c.hoverSeries.isCartesian&&!c.isInsidePlot(a.pageX-b.chartPosition.left-c.plotLeft,a.pageY-b.chartPosition.top-c.plotTop)&&b.resetTracker()};b.hideTooltipOnMouseLeave=function(){b.resetTracker();b.chartPosition=null};d.onmousedown=function(d){d=b.normalizeMouseEvent(d);d.type.indexOf("touch")===-1&&d.preventDefault&&d.preventDefault();c.mouseIsDown=!0;c.cancelClick=!1;c.mouseDownX=b.mouseDownX=d.chartX;b.mouseDownY=d.chartY;J(C,"mouseup",a);Ba&&
J(C,"touchend",a)};var h=function(a){if(!a||!(a.touches&&a.touches.length>1)){var a=b.normalizeMouseEvent(a),d=a.type,h=a.chartX,l=a.chartY,m=!c.isInsidePlot(h-c.plotLeft,l-c.plotTop);if(d.indexOf("touch")===-1)a.returnValue=!1;d==="touchstart"&&(w(a.target,"isTracker")?c.runTrackerClick||a.preventDefault():!c.runChartClick&&!m&&a.preventDefault());if(m)h<c.plotLeft?h=c.plotLeft:h>c.plotLeft+c.plotWidth&&(h=c.plotLeft+c.plotWidth),l<c.plotTop?l=c.plotTop:l>c.plotTop+c.plotHeight&&(l=c.plotTop+c.plotHeight);
if(c.mouseIsDown&&d!=="touchstart"&&(e=Math.sqrt(Math.pow(b.mouseDownX-h,2)+Math.pow(b.mouseDownY-l,2)),e>10)){d=c.isInsidePlot(b.mouseDownX-c.plotLeft,b.mouseDownY-c.plotTop);if(c.hasCartesianSeries&&(b.zoomX||b.zoomY)&&d&&!b.selectionMarker)b.selectionMarker=c.renderer.rect(c.plotLeft,c.plotTop,f?1:c.plotWidth,g?1:c.plotHeight,0).attr({fill:b.options.chart.selectionMarkerFill||"rgba(69,114,167,0.25)",zIndex:7}).add();if(b.selectionMarker&&f){var q=h-b.mouseDownX;b.selectionMarker.attr({width:M(q),
x:(q>0?0:q)+b.mouseDownX})}b.selectionMarker&&g&&(l-=b.mouseDownY,b.selectionMarker.attr({height:M(l),y:(l>0?0:l)+b.mouseDownY}));d&&!b.selectionMarker&&b.options.chart.panning&&c.pan(h)}if(!m)b.onmousemove(a);return m||!c.hasCartesianSeries}};if(!/Android 4\.0/.test(na))d.onmousemove=h;J(d,"mouseleave",b.hideTooltipOnMouseLeave);Ba||J(C,"mousemove",b.hideTooltipOnMouseMove);d.ontouchstart=function(a){if(b.zoomX||b.zoomY)d.onmousedown(a);h(a)};d.ontouchmove=h;d.ontouchend=function(){e&&b.resetTracker()};
d.onclick=function(a){var d=c.hoverPoint,e,f,a=b.normalizeMouseEvent(a);a.cancelBubble=!0;if(!c.cancelClick)d&&(w(a.target,"isTracker")||w(a.target.parentNode,"isTracker"))?(e=d.plotX,f=d.plotY,x(d,{pageX:b.chartPosition.left+c.plotLeft+(c.inverted?c.plotWidth-f:e),pageY:b.chartPosition.top+c.plotTop+(c.inverted?c.plotHeight-e:f)}),F(d.series,"click",x(a,{point:d})),d.firePointEvent("click",a)):(x(a,b.getMouseCoordinates(a)),c.isInsidePlot(a.chartX-c.plotLeft,a.chartY-c.plotTop)&&F(c,"click",a))}},
destroy:function(){var a=this.chart,b=a.container;if(a.trackerGroup)a.trackerGroup=a.trackerGroup.destroy();R(b,"mouseleave",this.hideTooltipOnMouseLeave);R(C,"mousemove",this.hideTooltipOnMouseMove);b.onclick=b.onmousedown=b.onmousemove=b.ontouchstart=b.ontouchend=b.ontouchmove=null;clearInterval(this.tooltipTimeout)},init:function(a,b){if(!a.trackerGroup)a.trackerGroup=a.renderer.g("tracker").attr({zIndex:9}).add();if(b.enabled)a.tooltip=new pb(a,b);this.setDOMEvents()}};rb.prototype={init:function(a){var b=
this,c=b.options=a.options.legend;if(c.enabled){var d=c.itemStyle,e=n(c.padding,8),f=c.itemMarginTop||0;b.baseline=z(d.fontSize)+3+f;b.itemStyle=d;b.itemHiddenStyle=B(d,c.itemHiddenStyle);b.itemMarginTop=f;b.padding=e;b.initialItemX=e;b.initialItemY=e-5;b.maxItemWidth=0;b.chart=a;b.itemHeight=0;b.lastLineHeight=0;b.render();J(b.chart,"endResize",function(){b.positionCheckboxes()})}},colorizeItem:function(a,b){var c=this.options,d=a.legendItem,e=a.legendLine,f=a.legendSymbol,g=this.itemHiddenStyle.color,
c=b?c.itemStyle.color:g,h=b?a.color:g,g=a.options&&a.options.marker,i={stroke:h,fill:h},j;d&&d.css({fill:c});e&&e.attr({stroke:h});if(f){if(g)for(j in g=a.convertAttribs(g),g)d=g[j],d!==A&&(i[j]=d);f.attr(i)}},positionItem:function(a){var b=this.options,c=b.symbolPadding,b=!b.rtl,d=a._legendItemPos,e=d[0],d=d[1],f=a.checkbox;a.legendGroup&&a.legendGroup.translate(b?e:this.legendWidth-e-2*c-4,d);if(f)f.x=e,f.y=d},destroyItem:function(a){var b=a.checkbox;o(["legendItem","legendLine","legendSymbol",
"legendGroup"],function(b){a[b]&&a[b].destroy()});b&&Na(a.checkbox)},destroy:function(){var a=this.group,b=this.box;if(b)this.box=b.destroy();if(a)this.group=a.destroy()},positionCheckboxes:function(a){var b=this.group.alignAttr,c,d=this.clipHeight||this.legendHeight;if(b)c=b.translateY,o(this.allItems,function(e){var f=e.checkbox,g;f&&(g=c+f.y+(a||0)+3,I(f,{left:b.translateX+e.legendItemWidth+f.x-20+"px",top:g+"px",display:g>c-6&&g<c+d-6?"":Q}))})},renderItem:function(a){var p;var b=this,c=b.chart,
d=c.renderer,e=b.options,f=e.layout==="horizontal",g=e.symbolWidth,h=e.symbolPadding,i=b.itemStyle,j=b.itemHiddenStyle,k=b.padding,l=!e.rtl,m=e.width,q=e.itemMarginBottom||0,n=b.itemMarginTop,o=b.initialItemX,t=a.legendItem,r=a.series||a,u=r.options,v=u.showCheckbox,x=e.useHTML;if(!t&&(a.legendGroup=d.g("legend-item").attr({zIndex:1}).add(b.scrollGroup),r.drawLegendSymbol(b,a),a.legendItem=t=d.text(e.labelFormatter.call(a),l?g+h:-h,b.baseline,x).css(B(a.visible?i:j)).attr({align:l?"left":"right",
zIndex:2}).add(a.legendGroup),(x?t:a.legendGroup).on("mouseover",function(){a.setState("hover");t.css(b.options.itemHoverStyle)}).on("mouseout",function(){t.css(a.visible?i:j);a.setState()}).on("click",function(b){var c=function(){a.setVisible()},b={browserEvent:b};a.firePointEvent?a.firePointEvent("legendItemClick",b,c):F(a,"legendItemClick",b,c)}),b.colorizeItem(a,a.visible),u&&v))a.checkbox=T("input",{type:"checkbox",checked:a.selected,defaultChecked:a.selected},e.itemCheckboxStyle,c.container),
J(a.checkbox,"click",function(b){F(a,"checkboxClick",{checked:b.target.checked},function(){a.select()})});d=t.getBBox();p=a.legendItemWidth=e.itemWidth||g+h+d.width+k+(v?20:0),e=p;b.itemHeight=g=d.height;if(f&&b.itemX-o+e>(m||c.chartWidth-2*k-o))b.itemX=o,b.itemY+=n+b.lastLineHeight+q,b.lastLineHeight=0;b.maxItemWidth=s(b.maxItemWidth,e);b.lastItemY=n+b.itemY+q;b.lastLineHeight=s(g,b.lastLineHeight);a._legendItemPos=[b.itemX,b.itemY];f?b.itemX+=e:(b.itemY+=n+g+q,b.lastLineHeight=g);b.offsetWidth=
m||s(f?b.itemX-o:e,b.offsetWidth)},render:function(){var a=this,b=a.chart,c=b.renderer,d=a.group,e,f,g,h,i=a.box,j=a.options,k=a.padding,l=j.borderWidth,m=j.backgroundColor;a.itemX=a.initialItemX;a.itemY=a.initialItemY;a.offsetWidth=0;a.lastItemY=0;if(!d)a.group=d=c.g("legend").attr({zIndex:7}).add(),a.contentGroup=c.g().attr({zIndex:1}).add(d),a.scrollGroup=c.g().add(a.contentGroup),a.clipRect=c.clipRect(0,0,9999,b.chartHeight),a.contentGroup.clip(a.clipRect);e=[];o(b.series,function(a){var b=a.options;
b.showInLegend&&(e=e.concat(a.legendItems||(b.legendType==="point"?a.data:a)))});Ib(e,function(a,b){return(a.options&&a.options.legendIndex||0)-(b.options&&b.options.legendIndex||0)});j.reversed&&e.reverse();a.allItems=e;a.display=f=!!e.length;o(e,function(b){a.renderItem(b)});g=j.width||a.offsetWidth;h=a.lastItemY+a.lastLineHeight;h=a.handleOverflow(h);if(l||m){g+=k;h+=k;if(i){if(g>0&&h>0)i[i.isNew?"attr":"animate"](i.crisp(null,null,null,g,h)),i.isNew=!1}else a.box=i=c.rect(0,0,g,h,j.borderRadius,
l||0).attr({stroke:j.borderColor,"stroke-width":l||0,fill:m||Q}).add(d).shadow(j.shadow),i.isNew=!0;i[f?"show":"hide"]()}a.legendWidth=g;a.legendHeight=h;o(e,function(b){a.positionItem(b)});f&&d.align(x({width:g,height:h},j),!0,b.spacingBox);b.isResizing||this.positionCheckboxes()},handleOverflow:function(a){var b=this,c=this.chart,d=c.renderer,e=this.options,f=e.y,f=c.spacingBox.height+(e.verticalAlign==="top"?-f:f)-this.padding,g=e.maxHeight,h=this.clipRect,i=e.navigation,j=n(i.animation,!0),k=
i.arrowSize||12,l=this.nav;e.layout==="horizontal"&&(f/=2);g&&(f=O(f,g));if(a>f){this.clipHeight=c=f-20;this.pageCount=za(a/c);this.currentPage=n(this.currentPage,1);this.fullHeight=a;h.attr({height:c});if(!l)this.nav=l=d.g().attr({zIndex:1}).add(this.group),this.up=d.symbol("triangle",0,0,k,k).on("click",function(){b.scroll(-1,j)}).add(l),this.pager=d.text("",15,10).css(i.style).add(l),this.down=d.symbol("triangle-down",0,0,k,k).on("click",function(){b.scroll(1,j)}).add(l);b.scroll(0);a=f}else if(l)h.attr({height:c.chartHeight}),
l.hide(),this.scrollGroup.attr({translateY:1}),this.clipHeight=0;return a},scroll:function(a,b){var c=this.pageCount,d=this.currentPage+a,e=this.clipHeight,f=this.options.navigation,g=f.activeColor,h=f.inactiveColor,f=this.pager,i=this.padding;d>c&&(d=c);if(d>0)b!==A&&xa(b,this.chart),this.nav.attr({translateX:i,translateY:e+7,visibility:"visible"}),this.up.attr({fill:d===1?h:g}).css({cursor:d===1?"default":"pointer"}),f.attr({text:d+"/"+this.pageCount}),this.down.attr({x:18+this.pager.getBBox().width,
fill:d===c?h:g}).css({cursor:d===c?"default":"pointer"}),e=-O(e*(d-1),this.fullHeight-e+i)+1,this.scrollGroup.animate({translateY:e}),f.attr({text:d+"/"+c}),this.currentPage=d,this.positionCheckboxes(e)}};sb.prototype={init:function(a,b){var c,d=a.series;a.series=null;c=B(N,a);c.series=a.series=d;var d=c.chart,e=d.margin,e=Y(e)?e:[e,e,e,e];this.optionsMarginTop=n(d.marginTop,e[0]);this.optionsMarginRight=n(d.marginRight,e[1]);this.optionsMarginBottom=n(d.marginBottom,e[2]);this.optionsMarginLeft=
n(d.marginLeft,e[3]);this.runChartClick=(e=d.events)&&!!e.click;this.callback=b;this.isResizing=0;this.options=c;this.axes=[];this.series=[];this.hasCartesianSeries=d.showAxes;var f;this.index=Ha.length;Ha.push(this);d.reflow!==!1&&J(this,"load",this.initReflow);if(e)for(f in e)J(this,f,e[f]);this.xAxis=[];this.yAxis=[];this.animation=V?!1:n(d.animation,!0);this.pointCount=0;this.counters=new Hb;this.firstRender()},initSeries:function(a){var b=this.options.chart,b=new $[a.type||b.type||b.defaultSeriesType];
b.init(this,a);return b},addSeries:function(a,b,c){var d,e=this;a&&(xa(c,e),b=n(b,!0),F(e,"addSeries",{options:a},function(){d=e.initSeries(a);e.isDirtyLegend=!0;b&&e.redraw()}));return d},isInsidePlot:function(a,b,c){var d=c?b:a,a=c?a:b;return d>=0&&d<=this.plotWidth&&a>=0&&a<=this.plotHeight},adjustTickAmounts:function(){this.options.chart.alignTicks!==!1&&o(this.axes,function(a){a.adjustTickAmount()});this.maxTicks=null},redraw:function(a){var b=this.axes,c=this.series,d=this.tracker,e=this.legend,
f=this.isDirtyLegend,g,h=this.isDirtyBox,i=c.length,j=i,k=this.renderer,l=k.isHidden(),m=[];xa(a,this);for(l&&this.cloneRenderTo();j--;)if(a=c[j],a.isDirty&&a.options.stacking){g=!0;break}if(g)for(j=i;j--;)if(a=c[j],a.options.stacking)a.isDirty=!0;o(c,function(a){a.isDirty&&a.options.legendType==="point"&&(f=!0)});if(f&&e.options.enabled)e.render(),this.isDirtyLegend=!1;if(this.hasCartesianSeries){if(!this.isResizing)this.maxTicks=null,o(b,function(a){a.setScale()});this.adjustTickAmounts();this.getMargins();
o(b,function(a){if(a.isDirtyExtremes)a.isDirtyExtremes=!1,m.push(function(){F(a,"afterSetExtremes",a.getExtremes())});if(a.isDirty||h||g)a.redraw(),h=!0})}h&&this.drawChartBox();o(c,function(a){a.isDirty&&a.visible&&(!a.isCartesian||a.xAxis)&&a.redraw()});d&&d.resetTracker&&d.resetTracker(!0);k.draw();F(this,"redraw");l&&this.cloneRenderTo(!0);o(m,function(a){a.call()})},showLoading:function(a){var b=this.options,c=this.loadingDiv,d=b.loading;if(!c)this.loadingDiv=c=T(ga,{className:"highcharts-loading"},
x(d.style,{left:this.plotLeft+"px",top:this.plotTop+"px",width:this.plotWidth+"px",height:this.plotHeight+"px",zIndex:10,display:Q}),this.container),this.loadingSpan=T("span",null,d.labelStyle,c);this.loadingSpan.innerHTML=a||b.lang.loading;if(!this.loadingShown)I(c,{opacity:0,display:""}),xb(c,{opacity:d.style.opacity},{duration:d.showDuration||0}),this.loadingShown=!0},hideLoading:function(){var a=this.options,b=this.loadingDiv;b&&xb(b,{opacity:0},{duration:a.loading.hideDuration||100,complete:function(){I(b,
{display:Q})}});this.loadingShown=!1},get:function(a){var b=this.axes,c=this.series,d,e;for(d=0;d<b.length;d++)if(b[d].options.id===a)return b[d];for(d=0;d<c.length;d++)if(c[d].options.id===a)return c[d];for(d=0;d<c.length;d++){e=c[d].points||[];for(b=0;b<e.length;b++)if(e[b].id===a)return e[b]}return null},getAxes:function(){var a=this,b=this.options,c=b.xAxis||{},b=b.yAxis||{},c=la(c);o(c,function(a,b){a.index=b;a.isX=!0});b=la(b);o(b,function(a,b){a.index=b});c=c.concat(b);o(c,function(b){new ob(a,
b)});a.adjustTickAmounts()},getSelectedPoints:function(){var a=[];o(this.series,function(b){a=a.concat(Ob(b.points,function(a){return a.selected}))});return a},getSelectedSeries:function(){return Ob(this.series,function(a){return a.selected})},showResetZoom:function(){var a=this,b=N.lang,c=a.options.chart.resetZoomButton,d=c.theme,e=d.states,f=c.relativeTo==="chart"?null:"plotBox";this.resetZoomButton=a.renderer.button(b.resetZoom,null,null,function(){a.zoomOut()},d,e&&e.hover).attr({align:c.position.align,
title:b.resetZoomTitle}).add().align(c.position,!1,a[f]);this.resetZoomButton.alignTo=f},zoomOut:function(){var a=this,b=a.resetZoomButton;F(a,"selection",{resetSelection:!0},function(){a.zoom()});if(b)a.resetZoomButton=b.destroy()},zoom:function(a){var b=this,c;!a||a.resetSelection?o(b.axes,function(a){c=a.zoom()}):o(a.xAxis.concat(a.yAxis),function(a){var e=a.axis;if(b.tracker[e.isXAxis?"zoomX":"zoomY"])c=e.zoom(a.min,a.max)});b.resetZoomButton||b.showResetZoom();c&&b.redraw(n(b.options.chart.animation,
b.pointCount<100))},pan:function(a){var b=this.xAxis[0],c=this.mouseDownX,d=b.pointRange/2,e=b.getExtremes(),f=b.translate(c-a,!0)+d,c=b.translate(c+this.plotWidth-a,!0)-d;(d=this.hoverPoints)&&o(d,function(a){a.setState()});b.series.length&&f>O(e.dataMin,e.min)&&c<s(e.dataMax,e.max)&&b.setExtremes(f,c,!0,!1,{trigger:"pan"});this.mouseDownX=a;I(this.container,{cursor:"move"})},setTitle:function(a,b){var c=this,d=c.options,e;c.chartTitleOptions=e=B(d.title,a);c.chartSubtitleOptions=d=B(d.subtitle,
b);o([["title",a,e],["subtitle",b,d]],function(a){var b=a[0],d=c[b],e=a[1],a=a[2];d&&e&&(c[b]=d=d.destroy());a&&a.text&&!d&&(c[b]=c.renderer.text(a.text,0,0,a.useHTML).attr({align:a.align,"class":"highcharts-"+b,zIndex:a.zIndex||4}).css(a.style).add().align(a,!1,c.spacingBox))})},getChartSize:function(){var a=this.options.chart,b=this.renderToClone||this.renderTo;this.containerWidth=eb(b,"width");this.containerHeight=eb(b,"height");this.chartWidth=s(0,n(a.width,this.containerWidth,600));this.chartHeight=
s(0,n(a.height,this.containerHeight>19?this.containerHeight:400))},cloneRenderTo:function(a){var b=this.renderToClone,c=this.container;a?b&&(this.renderTo.appendChild(c),Na(b),delete this.renderToClone):(c&&this.renderTo.removeChild(c),this.renderToClone=b=this.renderTo.cloneNode(0),I(b,{position:"absolute",top:"-9999px",display:"block"}),C.body.appendChild(b),c&&b.appendChild(c))},getContainer:function(){var a,b=this.options.chart,c,d,e;this.renderTo=a=b.renderTo;e="highcharts-"+tb++;if(ja(a))this.renderTo=
a=C.getElementById(a);a||Oa(13,!0);c=z(w(a,"data-highcharts-chart"));!isNaN(c)&&Ha[c]&&Ha[c].destroy();w(a,"data-highcharts-chart",this.index);a.innerHTML="";a.offsetWidth||this.cloneRenderTo();this.getChartSize();c=this.chartWidth;d=this.chartHeight;this.container=a=T(ga,{className:"highcharts-container"+(b.className?" "+b.className:""),id:e},x({position:"relative",overflow:"hidden",width:c+"px",height:d+"px",textAlign:"left",lineHeight:"normal",zIndex:0},b.style),this.renderToClone||a);this.renderer=
b.forExport?new sa(a,c,d,!0):new Sa(a,c,d);V&&this.renderer.create(this,a,c,d)},getMargins:function(){var a=this.options.chart,b=a.spacingTop,c=a.spacingRight,d=a.spacingBottom,a=a.spacingLeft,e,f=this.legend,g=this.optionsMarginTop,h=this.optionsMarginLeft,i=this.optionsMarginRight,j=this.optionsMarginBottom,k=this.chartTitleOptions,l=this.chartSubtitleOptions,m=this.options.legend,q=n(m.margin,10),p=m.x,y=m.y,t=m.align,u=m.verticalAlign;this.resetMargins();e=this.axisOffset;if((this.title||this.subtitle)&&
!r(this.optionsMarginTop))if(l=s(this.title&&!k.floating&&!k.verticalAlign&&k.y||0,this.subtitle&&!l.floating&&!l.verticalAlign&&l.y||0))this.plotTop=s(this.plotTop,l+n(k.margin,15)+b);if(f.display&&!m.floating)if(t==="right"){if(!r(i))this.marginRight=s(this.marginRight,f.legendWidth-p+q+c)}else if(t==="left"){if(!r(h))this.plotLeft=s(this.plotLeft,f.legendWidth+p+q+a)}else if(u==="top"){if(!r(g))this.plotTop=s(this.plotTop,f.legendHeight+y+q+b)}else if(u==="bottom"&&!r(j))this.marginBottom=s(this.marginBottom,
f.legendHeight-y+q+d);this.extraBottomMargin&&(this.marginBottom+=this.extraBottomMargin);this.extraTopMargin&&(this.plotTop+=this.extraTopMargin);this.hasCartesianSeries&&o(this.axes,function(a){a.getOffset()});r(h)||(this.plotLeft+=e[3]);r(g)||(this.plotTop+=e[0]);r(j)||(this.marginBottom+=e[2]);r(i)||(this.marginRight+=e[1]);this.setChartSize()},initReflow:function(){function a(a){var g=c.width||eb(d,"width"),h=c.height||eb(d,"height"),a=a?a.target:L;if(!b.hasUserSize&&g&&h&&(a===L||a===C)){if(g!==
b.containerWidth||h!==b.containerHeight)clearTimeout(e),b.reflowTimeout=e=setTimeout(function(){if(b.container)b.setSize(g,h,!1),b.hasUserSize=null},100);b.containerWidth=g;b.containerHeight=h}}var b=this,c=b.options.chart,d=b.renderTo,e;J(L,"resize",a);J(b,"destroy",function(){R(L,"resize",a)})},setSize:function(a,b,c){var d=this,e,f,g=d.resetZoomButton,h=d.title,i=d.subtitle,j;d.isResizing+=1;j=function(){d&&F(d,"endResize",null,function(){d.isResizing-=1})};xa(c,d);d.oldChartHeight=d.chartHeight;
d.oldChartWidth=d.chartWidth;if(r(a))d.chartWidth=e=s(0,u(a)),d.hasUserSize=!!e;if(r(b))d.chartHeight=f=s(0,u(b));I(d.container,{width:e+"px",height:f+"px"});d.renderer.setSize(e,f,c);d.plotWidth=e-d.plotLeft-d.marginRight;d.plotHeight=f-d.plotTop-d.marginBottom;d.maxTicks=null;o(d.axes,function(a){a.isDirty=!0;a.setScale()});o(d.series,function(a){a.isDirty=!0});d.isDirtyLegend=!0;d.isDirtyBox=!0;d.getMargins();a=d.spacingBox;h&&h.align(null,null,a);i&&i.align(null,null,a);g&&g.align&&g.align(null,
null,d[g.alignTo]);d.redraw(c);d.oldChartHeight=null;F(d,"resize");Pa===!1?j():setTimeout(j,Pa&&Pa.duration||500)},setChartSize:function(){var a=this.inverted,b=this.chartWidth,c=this.chartHeight,d=this.options.chart,e=d.spacingTop,f=d.spacingRight,g=d.spacingBottom,h=d.spacingLeft,i,j,k,l;this.plotLeft=i=u(this.plotLeft);this.plotTop=j=u(this.plotTop);this.plotWidth=k=s(0,u(b-i-this.marginRight));this.plotHeight=l=s(0,u(c-j-this.marginBottom));this.plotSizeX=a?l:k;this.plotSizeY=a?k:l;this.plotBorderWidth=
a=d.plotBorderWidth||0;this.spacingBox={x:h,y:e,width:b-h-f,height:c-e-g};this.plotBox={x:i,y:j,width:k,height:l};this.clipBox={x:a/2,y:a/2,width:this.plotSizeX-a,height:this.plotSizeY-a};o(this.axes,function(a){a.setAxisSize();a.setAxisTranslation()})},resetMargins:function(){var a=this.options.chart,b=a.spacingRight,c=a.spacingBottom,d=a.spacingLeft;this.plotTop=n(this.optionsMarginTop,a.spacingTop);this.marginRight=n(this.optionsMarginRight,b);this.marginBottom=n(this.optionsMarginBottom,c);this.plotLeft=
n(this.optionsMarginLeft,d);this.axisOffset=[0,0,0,0]},drawChartBox:function(){var a=this.options.chart,b=this.renderer,c=this.chartWidth,d=this.chartHeight,e=this.chartBackground,f=this.plotBackground,g=this.plotBorder,h=this.plotBGImage,i=a.borderWidth||0,j=a.backgroundColor,k=a.plotBackgroundColor,l=a.plotBackgroundImage,m=a.plotBorderWidth||0,n,p=this.plotLeft,o=this.plotTop,t=this.plotWidth,r=this.plotHeight,u=this.plotBox,v=this.clipRect,s=this.clipBox;n=i+(a.shadow?8:0);if(i||j)if(e)e.animate(e.crisp(null,
null,null,c-n,d-n));else{e={fill:j||Q};if(i)e.stroke=a.borderColor,e["stroke-width"]=i;this.chartBackground=b.rect(n/2,n/2,c-n,d-n,a.borderRadius,i).attr(e).add().shadow(a.shadow)}if(k)f?f.animate(u):this.plotBackground=b.rect(p,o,t,r,0).attr({fill:k}).add().shadow(a.plotShadow);if(l)h?h.animate(u):this.plotBGImage=b.image(l,p,o,t,r).add();v?v.animate({width:s.width,height:s.height}):this.clipRect=b.clipRect(s);if(m)g?g.animate(g.crisp(null,p,o,t,r)):this.plotBorder=b.rect(p,o,t,r,0,m).attr({stroke:a.plotBorderColor,
"stroke-width":m,zIndex:1}).add();this.isDirtyBox=!1},propFromSeries:function(){var a=this,b=a.options.chart,c,d=a.options.series,e,f;o(["inverted","angular","polar"],function(g){c=$[b.type||b.defaultSeriesType];f=a[g]||b[g]||c&&c.prototype[g];for(e=d&&d.length;!f&&e--;)(c=$[d[e].type])&&c.prototype[g]&&(f=!0);a[g]=f})},render:function(){var a=this,b=a.axes,c=a.renderer,d=a.options,e=d.labels,d=d.credits,f;a.setTitle();a.legend=new rb(a);o(b,function(a){a.setScale()});a.getMargins();a.maxTicks=null;
o(b,function(a){a.setTickPositions(!0);a.setMaxTicks()});a.adjustTickAmounts();a.getMargins();a.drawChartBox();a.hasCartesianSeries&&o(b,function(a){a.render()});if(!a.seriesGroup)a.seriesGroup=c.g("series-group").attr({zIndex:3}).add();o(a.series,function(a){a.translate();a.setTooltipPoints();a.render()});e.items&&o(e.items,function(b){var d=x(e.style,b.style),f=z(d.left)+a.plotLeft,j=z(d.top)+a.plotTop+12;delete d.left;delete d.top;c.text(b.html,f,j).attr({zIndex:2}).css(d).add()});if(d.enabled&&
!a.credits)f=d.href,a.credits=c.text(d.text,0,0).on("click",function(){if(f)location.href=f}).attr({align:d.position.align,zIndex:8}).css(d.style).add().align(d.position);a.hasRendered=!0},destroy:function(){var a=this,b=a.axes,c=a.series,d=a.container,e,f=d&&d.parentNode;F(a,"destroy");Ha[a.index]=A;a.renderTo.removeAttribute("data-highcharts-chart");R(a);for(e=b.length;e--;)b[e]=b[e].destroy();for(e=c.length;e--;)c[e]=c[e].destroy();o("title,subtitle,chartBackground,plotBackground,plotBGImage,plotBorder,seriesGroup,clipRect,credits,tracker,scroller,rangeSelector,legend,resetZoomButton,tooltip,renderer".split(","),
function(b){var c=a[b];c&&c.destroy&&(a[b]=c.destroy())});if(d)d.innerHTML="",R(d),f&&Na(d);for(e in a)delete a[e]},isReadyToRender:function(){var a=this;return!ca&&L==L.top&&C.readyState!=="complete"||V&&!L.canvg?(V?Rb.push(function(){a.firstRender()},a.options.global.canvasToolsURL):C.attachEvent("onreadystatechange",function(){C.detachEvent("onreadystatechange",a.firstRender);C.readyState==="complete"&&a.firstRender()}),!1):!0},firstRender:function(){var a=this,b=a.options,c=a.callback;if(a.isReadyToRender()){a.getContainer();
F(a,"init");if(Highcharts.RangeSelector&&b.rangeSelector.enabled)a.rangeSelector=new Highcharts.RangeSelector(a);a.resetMargins();a.setChartSize();a.propFromSeries();a.getAxes();o(b.series||[],function(b){a.initSeries(b)});if(Highcharts.Scroller&&(b.navigator.enabled||b.scrollbar.enabled))a.scroller=new Highcharts.Scroller(a);a.tracker=new qb(a,b);a.render();a.renderer.draw();c&&c.apply(a,[a]);o(a.callbacks,function(b){b.apply(a,[a])});a.cloneRenderTo(!0);F(a,"load")}}};sb.prototype.callbacks=[];
var Ua=function(){};Ua.prototype={init:function(a,b,c){var d=a.chart.counters;this.series=a;this.applyOptions(b,c);this.pointAttr={};if(a.options.colorByPoint)b=a.chart.options.colors,this.color=this.color||b[d.color++],d.wrapColor(b.length);a.chart.pointCount++;return this},applyOptions:function(a,b){var c=this.series,d=typeof a;this.config=a;if(d==="number"||a===null)this.y=a;else if(typeof a[0]==="number")this.x=a[0],this.y=a[1];else if(d==="object"&&typeof a.length!=="number"){x(this,a);this.options=
a;if(a.dataLabels)c._hasPointLabels=!0;if(a.marker)c._hasPointMarkers=!0}else if(typeof a[0]==="string")this.name=a[0],this.y=a[1];if(this.x===A)this.x=b===A?c.autoIncrement():b},destroy:function(){var a=this.series.chart,b=a.hoverPoints,c;a.pointCount--;if(b&&(this.setState(),ta(b,this),!b.length))a.hoverPoints=null;if(this===a.hoverPoint)this.onMouseOut();if(this.graphic||this.dataLabel)R(this),this.destroyElements();this.legendItem&&a.legend.destroyItem(this);for(c in this)this[c]=null},destroyElements:function(){for(var a=
"graphic,tracker,dataLabel,dataLabelUpper,group,connector,shadowGroup".split(","),b,c=6;c--;)b=a[c],this[b]&&(this[b]=this[b].destroy())},getLabelConfig:function(){return{x:this.category,y:this.y,key:this.name||this.category,series:this.series,point:this,percentage:this.percentage,total:this.total||this.stackTotal}},select:function(a,b){var c=this,d=c.series.chart,a=n(a,!c.selected);c.firePointEvent(a?"select":"unselect",{accumulate:b},function(){c.selected=a;c.setState(a&&"select");b||o(d.getSelectedPoints(),
function(a){if(a.selected&&a!==c)a.selected=!1,a.setState(""),a.firePointEvent("unselect")})})},onMouseOver:function(){var a=this.series,b=a.chart,c=b.tooltip,d=b.hoverPoint;if(d&&d!==this)d.onMouseOut();this.firePointEvent("mouseOver");c&&(!c.shared||a.noSharedTooltip)&&c.refresh(this);this.setState("hover");b.hoverPoint=this},onMouseOut:function(){var a=this.series.chart,b=a.hoverPoints;if(!b||Ub(this,b)===-1)this.firePointEvent("mouseOut"),this.setState(),a.hoverPoint=null},tooltipFormatter:function(a){var b=
this.series,c=b.tooltipOptions,d=a.match(/\{(series|point)\.[a-zA-Z]+\}/g),e=/[{\.}]/,f,g,h,i,j={y:0,open:0,high:0,low:0,close:0,percentage:1,total:1};c.valuePrefix=c.valuePrefix||c.yPrefix;c.valueDecimals=n(c.valueDecimals,c.yDecimals);c.valueSuffix=c.valueSuffix||c.ySuffix;for(i in d)g=d[i],ja(g)&&g!==a&&(h=(" "+g).split(e),f={point:this,series:b}[h[1]],h=h[2],f===this&&j.hasOwnProperty(h)?(f=j[h]?h:"value",f=(c[f+"Prefix"]||"")+Ja(this[h],n(c[f+"Decimals"],-1))+(c[f+"Suffix"]||"")):f=f[h],a=a.replace(g,
f));return a},update:function(a,b,c){var d=this,e=d.series,f=d.graphic,g,h=e.data,i=h.length,j=e.chart,b=n(b,!0);d.firePointEvent("update",{options:a},function(){d.applyOptions(a);Y(a)&&(e.getAttribs(),f&&f.attr(d.pointAttr[e.state]));for(g=0;g<i;g++)if(h[g]===d){e.xData[g]=d.x;e.yData[g]=d.toYData?d.toYData():d.y;e.options.data[g]=a;break}e.isDirty=!0;e.isDirtyData=!0;b&&j.redraw(c)})},remove:function(a,b){var c=this,d=c.series,e=d.chart,f,g=d.data,h=g.length;xa(b,e);a=n(a,!0);c.firePointEvent("remove",
null,function(){for(f=0;f<h;f++)if(g[f]===c){g.splice(f,1);d.options.data.splice(f,1);d.xData.splice(f,1);d.yData.splice(f,1);break}c.destroy();d.isDirty=!0;d.isDirtyData=!0;a&&e.redraw()})},firePointEvent:function(a,b,c){var d=this,e=this.series.options;(e.point.events[a]||d.options&&d.options.events&&d.options.events[a])&&this.importEvents();a==="click"&&e.allowPointSelect&&(c=function(a){d.select(null,a.ctrlKey||a.metaKey||a.shiftKey)});F(this,a,b,c)},importEvents:function(){if(!this.hasImportedEvents){var a=
B(this.series.options.point,this.options).events,b;this.events=a;for(b in a)J(this,b,a[b]);this.hasImportedEvents=!0}},setState:function(a){var b=this.plotX,c=this.plotY,d=this.series,e=d.options.states,f=X[d.type].marker&&d.options.marker,g=f&&!f.enabled,h=f&&f.states[a],i=h&&h.enabled===!1,j=d.stateMarkerGraphic,k=d.chart,l=this.pointAttr,a=a||"";if(!(a===this.state||this.selected&&a!=="select"||e[a]&&e[a].enabled===!1||a&&(i||g&&!h.enabled))){if(this.graphic)e=f&&this.graphic.symbolName&&l[a].r,
this.graphic.attr(B(l[a],e?{x:b-e,y:c-e,width:2*e,height:2*e}:{}));else{if(a&&h)e=h.radius,j?j.attr({x:b-e,y:c-e}):d.stateMarkerGraphic=j=k.renderer.symbol(d.symbol,b-e,c-e,2*e,2*e).attr(l[a]).add(d.markerGroup);if(j)j[a&&k.isInsidePlot(b,c)?"show":"hide"]()}this.state=a}}};var P=function(){};P.prototype={isCartesian:!0,type:"line",pointClass:Ua,sorted:!0,requireSorting:!0,pointAttrToOptions:{stroke:"lineColor","stroke-width":"lineWidth",fill:"fillColor",r:"radius"},init:function(a,b){var c,d;this.chart=
a;this.options=b=this.setOptions(b);this.bindAxes();x(this,{name:b.name,state:"",pointAttr:{},visible:b.visible!==!1,selected:b.selected===!0});if(V)b.animation=!1;d=b.events;for(c in d)J(this,c,d[c]);if(d&&d.click||b.point&&b.point.events&&b.point.events.click||b.allowPointSelect)a.runTrackerClick=!0;this.getColor();this.getSymbol();this.setData(b.data,!1);if(this.isCartesian)a.hasCartesianSeries=!0;a.series.push(this);Ib(a.series,function(a,b){return(a.options.index||0)-(b.options.index||0)});o(a.series,
function(a,b){a.index=b;a.name=a.name||"Series "+(b+1)})},bindAxes:function(){var a=this,b=a.options,c=a.chart,d;a.isCartesian&&o(["xAxis","yAxis"],function(e){o(c[e],function(c){d=c.options;if(b[e]===d.index||b[e]===A&&d.index===0)c.series.push(a),a[e]=c,c.isDirty=!0})})},autoIncrement:function(){var a=this.options,b=this.xIncrement,b=n(b,a.pointStart,0);this.pointInterval=n(this.pointInterval,a.pointInterval,1);this.xIncrement=b+this.pointInterval;return b},getSegments:function(){var a=-1,b=[],
c,d=this.points,e=d.length;if(e)if(this.options.connectNulls){for(c=e;c--;)d[c].y===null&&d.splice(c,1);d.length&&(b=[d])}else o(d,function(c,g){c.y===null?(g>a+1&&b.push(d.slice(a+1,g)),a=g):g===e-1&&b.push(d.slice(a+1,g+1))});this.segments=b},setOptions:function(a){var b=this.chart.options,c=b.plotOptions,d=c[this.type],e=a.data;a.data=null;c=B(d,c.series,a);c.data=a.data=e;this.tooltipOptions=B(b.tooltip,c.tooltip);d.marker===null&&delete c.marker;return c},getColor:function(){var a=this.options,
b=this.chart.options.colors,c=this.chart.counters;this.color=a.color||!a.colorByPoint&&b[c.color++]||"gray";c.wrapColor(b.length)},getSymbol:function(){var a=this.options.marker,b=this.chart,c=b.options.symbols,b=b.counters;this.symbol=a.symbol||c[b.symbol++];if(/^url/.test(this.symbol))a.radius=0;b.wrapSymbol(c.length)},drawLegendSymbol:function(a){var b=this.options,c=b.marker,d=a.options.symbolWidth,e=this.chart.renderer,f=this.legendGroup,a=a.baseline,g;if(b.lineWidth){g={"stroke-width":b.lineWidth};
if(b.dashStyle)g.dashstyle=b.dashStyle;this.legendLine=e.path(["M",0,a-4,"L",d,a-4]).attr(g).add(f)}if(c&&c.enabled)b=c.radius,this.legendSymbol=e.symbol(this.symbol,d/2-b,a-4-b,2*b,2*b).add(f)},addPoint:function(a,b,c,d){var e=this.options,f=this.data,g=this.graph,h=this.area,i=this.chart,j=this.xData,k=this.yData,l=g&&g.shift||0,m=e.data,q=this.pointClass.prototype;xa(d,i);if(g&&c)g.shift=l+1;if(h){if(c)h.shift=l+1;h.isArea=!0}b=n(b,!0);d={series:this};q.applyOptions.apply(d,[a]);j.push(d.x);k.push(q.toYData?
q.toYData.call(d):d.y);m.push(a);e.legendType==="point"&&this.generatePoints();c&&(f[0]&&f[0].remove?f[0].remove(!1):(f.shift(),j.shift(),k.shift(),m.shift()));this.getAttribs();this.isDirtyData=this.isDirty=!0;b&&i.redraw()},setData:function(a,b){var c=this.points,d=this.options,e=this.initialColor,f=this.chart,g=null,h=this.xAxis,i,j=this.pointClass.prototype;this.xIncrement=null;this.pointRange=h&&h.categories?1:d.pointRange;if(r(e))f.counters.color=e;var e=[],k=[],l=a?a.length:[],m=(i=this.pointArrayMap)&&
i.length;if(l>(d.turboThreshold||1E3)){for(i=0;g===null&&i<l;)g=a[i],i++;if(Da(g)){j=n(d.pointStart,0);d=n(d.pointInterval,1);for(i=0;i<l;i++)e[i]=j,k[i]=a[i],j+=d;this.xIncrement=j}else if(Ia(g))if(m)for(i=0;i<l;i++)d=a[i],e[i]=d[0],k[i]=d.slice(1,m+1);else for(i=0;i<l;i++)d=a[i],e[i]=d[0],k[i]=d[1]}else for(i=0;i<l;i++)d={series:this},j.applyOptions.apply(d,[a[i]]),e[i]=d.x,k[i]=j.toYData?j.toYData.call(d):d.y;this.requireSorting&&e.length>1&&e[1]<e[0]&&Oa(15);ja(k[0])&&Oa(14,!0);this.data=[];this.options.data=
a;this.xData=e;this.yData=k;for(i=c&&c.length||0;i--;)c[i]&&c[i].destroy&&c[i].destroy();if(h)h.minRange=h.userMinRange;this.isDirty=this.isDirtyData=f.isDirtyBox=!0;n(b,!0)&&f.redraw(!1)},remove:function(a,b){var c=this,d=c.chart,a=n(a,!0);if(!c.isRemoving)c.isRemoving=!0,F(c,"remove",null,function(){c.destroy();d.isDirtyLegend=d.isDirtyBox=!0;a&&d.redraw(b)});c.isRemoving=!1},processData:function(a){var b=this.xData,c=this.yData,d=b.length,e=0,f=d,g,h,i=this.xAxis,j=this.options,k=j.cropThreshold,
l=this.isCartesian;if(l&&!this.isDirty&&!i.isDirty&&!this.yAxis.isDirty&&!a)return!1;if(l&&this.sorted&&(!k||d>k||this.forceCrop))if(a=i.getExtremes(),i=a.min,k=a.max,b[d-1]<i||b[0]>k)b=[],c=[];else if(b[0]<i||b[d-1]>k){for(a=0;a<d;a++)if(b[a]>=i){e=s(0,a-1);break}for(;a<d;a++)if(b[a]>k){f=a+1;break}b=b.slice(e,f);c=c.slice(e,f);g=!0}for(a=b.length-1;a>0;a--)if(d=b[a]-b[a-1],d>0&&(h===A||d<h))h=d;this.cropped=g;this.cropStart=e;this.processedXData=b;this.processedYData=c;if(j.pointRange===null)this.pointRange=
h||1;this.closestPointRange=h},generatePoints:function(){var a=this.options.data,b=this.data,c,d=this.processedXData,e=this.processedYData,f=this.pointClass,g=d.length,h=this.cropStart||0,i,j=this.hasGroupedData,k,l=[],m;if(!b&&!j)b=[],b.length=a.length,b=this.data=b;for(m=0;m<g;m++)i=h+m,j?l[m]=(new f).init(this,[d[m]].concat(la(e[m]))):(b[i]?k=b[i]:a[i]!==A&&(b[i]=k=(new f).init(this,a[i],d[m])),l[m]=k);if(b&&(g!==(c=b.length)||j))for(m=0;m<c;m++)if(m===h&&!j&&(m+=g),b[m])b[m].destroyElements(),
b[m].plotX=A;this.data=b;this.points=l},translate:function(){this.processedXData||this.processData();this.generatePoints();for(var a=this.chart,b=this.options,c=b.stacking,d=this.xAxis,e=d.categories,f=this.yAxis,g=this.points,h=g.length,i=!!this.modifyValue,j,k=f.series,l=k.length,m=b.pointPlacement==="between";l--;)if(k[l].visible){k[l]===this&&(j=!0);break}for(l=0;l<h;l++){var k=g[l],q=k.x,p=k.y,o=k.low,t=f.stacks[(p<b.threshold?"-":"")+this.stackKey];k.plotX=d.translate(q,0,0,0,1,m);if(c&&this.visible&&
t&&t[q])o=t[q],q=o.total,o.cum=o=o.cum-p,p=o+p,j&&(o=n(b.threshold,f.min)),f.isLog&&o<=0&&(o=null),c==="percent"&&(o=q?o*100/q:0,p=q?p*100/q:0),k.percentage=q?k.y*100/q:0,k.total=k.stackTotal=q,k.stackY=p;k.yBottom=r(o)?f.translate(o,0,1,0,1):null;i&&(p=this.modifyValue(p,k));k.plotY=typeof p==="number"?u(f.translate(p,0,1,0,1)*10)/10:A;k.clientX=a.inverted?a.plotHeight-k.plotX:k.plotX;k.category=e&&e[k.x]!==A?e[k.x]:k.x}this.getSegments()},setTooltipPoints:function(a){var b=[],c,d,e=(c=this.xAxis)?
c.tooltipLen||c.len:this.chart.plotSizeX,f=c&&c.tooltipPosName||"plotX",g,h,i=[];if(this.options.enableMouseTracking!==!1){if(a)this.tooltipPoints=null;o(this.segments||this.points,function(a){b=b.concat(a)});c&&c.reversed&&(b=b.reverse());a=b.length;for(h=0;h<a;h++){g=b[h];c=b[h-1]?d+1:0;for(d=b[h+1]?s(0,U((g[f]+(b[h+1]?b[h+1][f]:e))/2)):e;c>=0&&c<=d;)i[c++]=g}this.tooltipPoints=i}},tooltipHeaderFormatter:function(a){var b=this.tooltipOptions,c=b.xDateFormat,d=this.xAxis,e=d&&d.options.type==="datetime",
f;if(e&&!c)for(f in D)if(D[f]>=d.closestPointRange){c=b.dateTimeLabelFormats[f];break}return b.headerFormat.replace("{point.key}",e&&Da(a)?db(c,a):a).replace("{series.name}",this.name).replace("{series.color}",this.color)},onMouseOver:function(){var a=this.chart,b=a.hoverSeries;if(b&&b!==this)b.onMouseOut();this.options.events.mouseOver&&F(this,"mouseOver");this.setState("hover");a.hoverSeries=this},onMouseOut:function(){var a=this.options,b=this.chart,c=b.tooltip,d=b.hoverPoint;if(d)d.onMouseOut();
this&&a.events.mouseOut&&F(this,"mouseOut");c&&!a.stickyTracking&&!c.shared&&c.hide();this.setState();b.hoverSeries=null},animate:function(a){var b=this,c=b.chart,d=c.renderer,e;e=b.options.animation;var f=c.clipBox,g=c.inverted,h;if(e&&!Y(e))e=X[b.type].animation;h="_sharedClip"+e.duration+e.easing;if(a)a=c[h],e=c[h+"m"],a||(c[h]=a=d.clipRect(x(f,{width:0})),c[h+"m"]=e=d.clipRect(-99,g?-c.plotLeft:-c.plotTop,99,g?c.chartWidth:c.chartHeight)),b.group.clip(a),b.markerGroup.clip(e),b.sharedClipKey=
h;else{if(a=c[h])a.animate({width:c.plotSizeX},e),c[h+"m"].animate({width:c.plotSizeX+99},e);b.animate=null;b.animationTimeout=setTimeout(function(){b.afterAnimate()},e.duration)}},afterAnimate:function(){var a=this.chart,b=this.sharedClipKey,c=this.group,d=this.trackerGroup;c&&this.options.clip!==!1&&(c.clip(a.clipRect),d&&d.clip(a.clipRect),this.markerGroup.clip());setTimeout(function(){b&&a[b]&&(a[b]=a[b].destroy(),a[b+"m"]=a[b+"m"].destroy())},100)},drawPoints:function(){var a,b=this.points,c=
this.chart,d,e,f,g,h,i,j,k,l=this.options.marker,m,o=this.markerGroup;if(l.enabled||this._hasPointMarkers)for(f=b.length;f--;)if(g=b[f],d=g.plotX,e=g.plotY,k=g.graphic,i=g.marker||{},a=l.enabled&&i.enabled===A||i.enabled,m=c.isInsidePlot(d,e,c.inverted),a&&e!==A&&!isNaN(e))if(a=g.pointAttr[g.selected?"select":""],h=a.r,i=n(i.symbol,this.symbol),j=i.indexOf("url")===0,k)k.attr({visibility:m?ca?"inherit":"visible":"hidden"}).animate(x({x:d-h,y:e-h},k.symbolName?{width:2*h,height:2*h}:{}));else{if(m&&
(h>0||j))g.graphic=c.renderer.symbol(i,d-h,e-h,2*h,2*h).attr(a).add(o)}else if(k)g.graphic=k.destroy()},convertAttribs:function(a,b,c,d){var e=this.pointAttrToOptions,f,g,h={},a=a||{},b=b||{},c=c||{},d=d||{};for(f in e)g=e[f],h[f]=n(a[g],b[f],c[f],d[f]);return h},getAttribs:function(){var a=this,b=X[a.type].marker?a.options.marker:a.options,c=b.states,d=c.hover,e,f=a.color,g={stroke:f,fill:f},h=a.points||[],i=[],j,k=a.pointAttrToOptions,l;a.options.marker?(d.radius=d.radius||b.radius+2,d.lineWidth=
d.lineWidth||b.lineWidth+1):d.color=d.color||qa(d.color||f).brighten(d.brightness).get();i[""]=a.convertAttribs(b,g);o(["hover","select"],function(b){i[b]=a.convertAttribs(c[b],i[""])});a.pointAttr=i;for(f=h.length;f--;){g=h[f];if((b=g.options&&g.options.marker||g.options)&&b.enabled===!1)b.radius=0;e=a.options.colorByPoint;if(g.options)for(l in k)r(b[k[l]])&&(e=!0);if(e){b=b||{};j=[];c=b.states||{};e=c.hover=c.hover||{};if(!a.options.marker)e.color=qa(e.color||g.color).brighten(e.brightness||d.brightness).get();
j[""]=a.convertAttribs(x({color:g.color},b),i[""]);j.hover=a.convertAttribs(c.hover,i.hover,j[""]);j.select=a.convertAttribs(c.select,i.select,j[""])}else j=i;g.pointAttr=j}},destroy:function(){var a=this,b=a.chart,c=/AppleWebKit\/533/.test(na),d,e,f=a.data||[],g,h,i;F(a,"destroy");R(a);o(["xAxis","yAxis"],function(b){if(i=a[b])ta(i.series,a),i.isDirty=!0});a.legendItem&&a.chart.legend.destroyItem(a);for(e=f.length;e--;)(g=f[e])&&g.destroy&&g.destroy();a.points=null;clearTimeout(a.animationTimeout);
o("area,graph,dataLabelsGroup,group,markerGroup,tracker,trackerGroup".split(","),function(b){a[b]&&(d=c&&b==="group"?"hide":"destroy",a[b][d]())});if(b.hoverSeries===a)b.hoverSeries=null;ta(b.series,a);for(h in a)delete a[h]},drawDataLabels:function(){var a=this,b=a.options.dataLabels,c=a.points,d,e,f,g;if(b.enabled||a._hasPointLabels)a.dlProcessOptions&&a.dlProcessOptions(b),g=a.plotGroup("dataLabelsGroup","data-labels",a.visible?"visible":"hidden",b.zIndex||6),e=b,o(c,function(c){var i,j=c.dataLabel,
k,l=!0;d=c.options&&c.options.dataLabels;i=e.enabled||d&&d.enabled;if(j&&!i)c.dataLabel=j.destroy();else if(i){i=b.rotation;b=B(e,d);f=b.formatter.call(c.getLabelConfig(),b);b.style.color=n(b.color,b.style.color,a.color,"black");if(j)j.attr({text:f}),l=!1;else if(r(f)){j={fill:b.backgroundColor,stroke:b.borderColor,"stroke-width":b.borderWidth,r:b.borderRadius||0,rotation:i,padding:b.padding,zIndex:1};for(k in j)j[k]===A&&delete j[k];j=c.dataLabel=a.chart.renderer[i?"text":"label"](f,0,-999,null,
null,null,b.useHTML).attr(j).css(b.style).add(g).shadow(b.shadow)}j&&a.alignDataLabel(c,j,b,null,l)}})},alignDataLabel:function(a,b,c,d,e){var f=this.chart,g=f.inverted,h=n(a.plotX,-999),a=n(a.plotY,-999),i=b.getBBox(),d=x({x:g?f.plotWidth-a:h,y:u(g?f.plotHeight-h:a),width:0,height:0},d);x(c,{width:i.width,height:i.height});c.rotation?(d={align:c.align,x:d.x+c.x+d.width/2,y:d.y+c.y+d.height/2},b[e?"attr":"animate"](d)):(b.align(c,null,d),d=b.alignAttr);b.attr({visibility:c.crop===!1||f.isInsidePlot(d.x,
d.y)||f.isInsidePlot(h,a,g)?f.renderer.isSVG?"inherit":"visible":"hidden"})},getSegmentPath:function(a){var b=this,c=[],d=b.options.step;o(a,function(e,f){var g=e.plotX,h=e.plotY,i;b.getPointSpline?c.push.apply(c,b.getPointSpline(a,e,f)):(c.push(f?"L":"M"),d&&f&&(i=a[f-1],d==="right"?c.push(i.plotX,h):d==="center"?c.push((i.plotX+g)/2,i.plotY,(i.plotX+g)/2,h):c.push(g,i.plotY)),c.push(e.plotX,e.plotY))});return c},getGraphPath:function(){var a=this,b=[],c,d=[];o(a.segments,function(e){c=a.getSegmentPath(e);
e.length>1?b=b.concat(c):d.push(e[0])});a.singlePoints=d;return a.graphPath=b},drawGraph:function(){var a=this.options,b=this.graph,c=this.group,d=a.lineColor||this.color,e=a.lineWidth,f=a.dashStyle,g=this.getGraphPath();if(b)fb(b),b.animate({d:g});else if(e){b={stroke:d,"stroke-width":e,zIndex:1};if(f)b.dashstyle=f;this.graph=this.chart.renderer.path(g).attr(b).add(c).shadow(a.shadow)}},invertGroups:function(){function a(){var a={width:b.yAxis.len,height:b.xAxis.len};o(["group","trackerGroup","markerGroup"],
function(c){b[c]&&b[c].attr(a).invert()})}var b=this,c=b.chart;J(c,"resize",a);J(b,"destroy",function(){R(c,"resize",a)});a();b.invertGroups=a},plotGroup:function(a,b,c,d,e){var f=this[a],g=this.chart,h=this.xAxis,i=this.yAxis;f||(this[a]=f=g.renderer.g(b).attr({visibility:c,zIndex:d||0.1}).add(e));f.translate(h?h.left:g.plotLeft,i?i.top:g.plotTop);return f},render:function(){var a=this.chart,b,c=this.options,d=c.animation&&!!this.animate,e=this.visible?"visible":"hidden",f=c.zIndex,g=this.hasRendered,
h=a.seriesGroup;b=this.plotGroup("group","series",e,f,h);this.markerGroup=this.plotGroup("markerGroup","markers",e,f,h);d&&this.animate(!0);this.getAttribs();b.inverted=a.inverted;this.drawGraph&&this.drawGraph();this.drawPoints();this.drawDataLabels();this.options.enableMouseTracking!==!1&&this.drawTracker();a.inverted&&this.invertGroups();c.clip!==!1&&!this.sharedClipKey&&!g&&(b.clip(a.clipRect),this.trackerGroup&&this.trackerGroup.clip(a.clipRect));d?this.animate():g||this.afterAnimate();this.isDirty=
this.isDirtyData=!1;this.hasRendered=!0},redraw:function(){var a=this.chart,b=this.isDirtyData,c=this.group;c&&(a.inverted&&c.attr({width:a.plotWidth,height:a.plotHeight}),c.animate({translateX:this.xAxis.left,translateY:this.yAxis.top}));this.translate();this.setTooltipPoints(!0);this.render();b&&F(this,"updatedData")},setState:function(a){var b=this.options,c=this.graph,d=b.states,b=b.lineWidth,a=a||"";if(this.state!==a)this.state=a,d[a]&&d[a].enabled===!1||(a&&(b=d[a].lineWidth||b+1),c&&!c.dashstyle&&
c.attr({"stroke-width":b},a?0:500))},setVisible:function(a,b){var c=this.chart,d=this.legendItem,e=this.group,f=this.tracker,g=this.dataLabelsGroup,h=this.markerGroup,i,j=this.points,k=c.options.chart.ignoreHiddenSeries;i=this.visible;i=(this.visible=a=a===A?!i:a)?"show":"hide";if(e)e[i]();if(h)h[i]();if(f)f[i]();else if(j)for(e=j.length;e--;)if(f=j[e],f.tracker)f.tracker[i]();if(c.hoverSeries===this)this.onMouseOut();if(g)g[i]();d&&c.legend.colorizeItem(this,a);this.isDirty=!0;this.options.stacking&&
o(c.series,function(a){if(a.options.stacking&&a.visible)a.isDirty=!0});if(k)c.isDirtyBox=!0;b!==!1&&c.redraw();F(this,i)},show:function(){this.setVisible(!0)},hide:function(){this.setVisible(!1)},select:function(a){this.selected=a=a===A?!this.selected:a;if(this.checkbox)this.checkbox.checked=a;F(this,a?"select":"unselect")},drawTracker:function(){var a=this,b=a.options,c=b.trackByArea,d=[].concat(c?a.areaPath:a.graphPath),e=d.length,f=a.chart,g=f.renderer,h=f.options.tooltip.snap,i=a.tracker,j=b.cursor,
j=j&&{cursor:j},k=a.singlePoints,l=this.isCartesian&&this.plotGroup("trackerGroup",null,"visible",b.zIndex||1,f.trackerGroup),m,n=function(){if(f.hoverSeries!==a)a.onMouseOver()},o=function(){if(!b.stickyTracking)a.onMouseOut()};if(e&&!c)for(m=e+1;m--;)d[m]==="M"&&d.splice(m+1,0,d[m+1]-h,d[m+2],"L"),(m&&d[m]==="M"||m===e)&&d.splice(m,0,"L",d[m-2]+h,d[m-1]);for(m=0;m<k.length;m++)e=k[m],d.push("M",e.plotX-h,e.plotY,"L",e.plotX+h,e.plotY);if(i)i.attr({d:d});else if(a.tracker=i=g.path(d).attr({isTracker:!0,
"stroke-linejoin":"round",visibility:a.visible?"visible":"hidden",stroke:vb,fill:c?vb:Q,"stroke-width":b.lineWidth+(c?0:2*h)}).on("mouseover",n).on("mouseout",o).css(j).add(l),Ba)i.on("touchstart",n)}};G=ba(P);$.line=G;X.area=B(ea,{threshold:0});G=ba(P,{type:"area",getSegmentPath:function(a){var b=P.prototype.getSegmentPath.call(this,a),c=[].concat(b),d,e=this.options;b.length===3&&c.push("L",b[1],b[2]);if(e.stacking&&!this.closedStacks)for(d=a.length-1;d>=0;d--)d<a.length-1&&e.step&&c.push(a[d+1].plotX,
a[d].yBottom),c.push(a[d].plotX,a[d].yBottom);else this.closeSegment(c,a);this.areaPath=this.areaPath.concat(c);return b},closeSegment:function(a,b){var c=this.yAxis.getThreshold(this.options.threshold);a.push("L",b[b.length-1].plotX,c,"L",b[0].plotX,c)},drawGraph:function(){this.areaPath=[];P.prototype.drawGraph.apply(this);var a=this.areaPath,b=this.options,c=this.area;c?c.animate({d:a}):this.area=this.chart.renderer.path(a).attr({fill:n(b.fillColor,qa(this.color).setOpacity(b.fillOpacity||0.75).get()),
zIndex:0}).add(this.group)},drawLegendSymbol:function(a,b){b.legendSymbol=this.chart.renderer.rect(0,a.baseline-11,a.options.symbolWidth,12,2).attr({zIndex:3}).add(b.legendGroup)}});$.area=G;X.spline=B(ea);fa=ba(P,{type:"spline",getPointSpline:function(a,b,c){var d=b.plotX,e=b.plotY,f=a[c-1],g=a[c+1],h,i,j,k;if(f&&g){a=f.plotY;j=g.plotX;var g=g.plotY,l;h=(1.5*d+f.plotX)/2.5;i=(1.5*e+a)/2.5;j=(1.5*d+j)/2.5;k=(1.5*e+g)/2.5;l=(k-i)*(j-d)/(j-h)+e-k;i+=l;k+=l;i>a&&i>e?(i=s(a,e),k=2*e-i):i<a&&i<e&&(i=O(a,
e),k=2*e-i);k>g&&k>e?(k=s(g,e),i=2*e-k):k<g&&k<e&&(k=O(g,e),i=2*e-k);b.rightContX=j;b.rightContY=k}c?(b=["C",f.rightContX||f.plotX,f.rightContY||f.plotY,h||d,i||e,d,e],f.rightContX=f.rightContY=null):b=["M",d,e];return b}});$.spline=fa;X.areaspline=B(X.area);var Ca=G.prototype,fa=ba(fa,{type:"areaspline",closedStacks:!0,getSegmentPath:Ca.getSegmentPath,closeSegment:Ca.closeSegment,drawGraph:Ca.drawGraph});$.areaspline=fa;X.column=B(ea,{borderColor:"#FFFFFF",borderWidth:1,borderRadius:0,groupPadding:0.2,
marker:null,pointPadding:0.1,minPointLength:0,cropThreshold:50,pointRange:null,states:{hover:{brightness:0.1,shadow:!1},select:{color:"#C0C0C0",borderColor:"#000000",shadow:!1}},dataLabels:{align:null,verticalAlign:null,y:null},threshold:0});fa=ba(P,{type:"column",tooltipOutsidePlot:!0,pointAttrToOptions:{stroke:"borderColor","stroke-width":"borderWidth",fill:"color",r:"borderRadius"},init:function(){P.prototype.init.apply(this,arguments);var a=this,b=a.chart;b.hasRendered&&o(b.series,function(b){if(b.type===
a.type)b.isDirty=!0})},translate:function(){var a=this,b=a.chart,c=a.options,d=c.stacking,e=c.borderWidth,f=0,g=a.xAxis,h=a.yAxis,i=g.reversed,j={},k,l;P.prototype.translate.apply(a);c.grouping===!1?f=1:o(b.series,function(b){var c=b.options;if(b.type===a.type&&b.visible&&a.options.group===c.group)c.stacking?(k=b.stackKey,j[k]===A&&(j[k]=f++),l=j[k]):c.grouping!==!1&&(l=f++),b.columnIndex=l});var m=a.points,g=M(g.transA)*(g.ordinalSlope||c.pointRange||g.closestPointRange||1),q=g*c.groupPadding,p=
(g-2*q)/f,y=c.pointWidth,t=r(y)?(p-y)/2:p*c.pointPadding,u=n(y,p-2*t),x=za(s(u,1+2*e)),v=t+(q+((i?f-(a.columnIndex||0):a.columnIndex)||0)*p-g/2)*(i?-1:1),z=a.translatedThreshold=h.getThreshold(c.threshold),w=n(c.minPointLength,5);o(m,function(c){var f=O(s(-999,c.plotY),h.len+999),g=n(c.yBottom,z),i=c.plotX+v,j=za(O(f,g)),k=za(s(f,g)-j),l=h.stacks[(c.y<0?"-":"")+a.stackKey];d&&a.visible&&l&&l[c.x]&&l[c.x].setOffset(v,x);M(k)<w&&w&&(k=w,j=M(j-z)>w?g-w:z-(f<=z?w:0));c.barX=i;c.pointWidth=u;c.shapeType=
"rect";c.shapeArgs=f=b.renderer.Element.prototype.crisp.call(0,e,i,j,x,k);e%2&&(f.y-=1,f.height+=1);c.trackerArgs=M(k)<3&&B(c.shapeArgs,{height:6,y:j-3})})},getSymbol:pa,drawLegendSymbol:G.prototype.drawLegendSymbol,drawGraph:pa,drawPoints:function(){var a=this,b=a.options,c=a.chart.renderer,d;o(a.points,function(e){var f=e.plotY,g=e.graphic;if(f!==A&&!isNaN(f)&&e.y!==null)d=e.shapeArgs,g?(fb(g),g.animate(B(d))):e.graphic=c[e.shapeType](d).attr(e.pointAttr[e.selected?"select":""]).add(a.group).shadow(b.shadow,
null,b.stacking&&!b.borderRadius);else if(g)e.graphic=g.destroy()})},drawTracker:function(){for(var a=this,b=a.chart,c=b.renderer,d,e,f=+new Date,g=a.options,h=(d=g.cursor)&&{cursor:d},i=a.isCartesian&&a.plotGroup("trackerGroup",null,"visible",g.zIndex||1,b.trackerGroup),j,k,l=a.points,m,n=l.length,o=function(c){j=c.relatedTarget||c.fromElement;if(b.hoverSeries!==a&&w(j,"isTracker")!==f)a.onMouseOver();l[c.target._i].onMouseOver()},r=function(b){if(!g.stickyTracking&&(j=b.relatedTarget||b.toElement,
w(j,"isTracker")!==f))a.onMouseOut()};n--;)if(m=l[n],e=m.tracker,d=m.trackerArgs||m.shapeArgs,k=m.plotY,k=!a.isCartesian||k!==A&&!isNaN(k),delete d.strokeWidth,m.y!==null&&k){if(e)e.attr(d);else if(m.tracker=e=c[m.shapeType](d).attr({isTracker:f,fill:vb,visibility:a.visible?"visible":"hidden"}).on("mouseover",o).on("mouseout",r).css(h).add(m.group||i),Ba)e.on("touchstart",o);e.element._i=n}},alignDataLabel:function(a,b,c,d,e){var f=this.chart,g=f.inverted,h=a.below||a.plotY>n(this.translatedThreshold,
f.plotSizeY),i=this.options.stacking||c.inside;if(a.shapeArgs&&(d=B(a.shapeArgs),g&&(d={x:f.plotWidth-d.y-d.height,y:f.plotHeight-d.x-d.width,width:d.height,height:d.width}),!i))g?(d.x+=h?0:d.width,d.width=0):(d.y+=h?d.height:0,d.height=0);c.align=n(c.align,!g||i?"center":h?"right":"left");c.verticalAlign=n(c.verticalAlign,g||i?"middle":h?"top":"bottom");P.prototype.alignDataLabel.call(this,a,b,c,d,e)},animate:function(a){var b=this,c=b.points,d=b.options;if(!a)o(c,function(a){var c=a.graphic,a=a.shapeArgs,
g=b.yAxis,h=d.threshold;c&&(c.attr({height:0,y:r(h)?g.getThreshold(h):g.translate(g.getExtremes().min,0,1,0,1)}),c.animate({height:a.height,y:a.y},d.animation))}),b.animate=null},remove:function(){var a=this,b=a.chart;b.hasRendered&&o(b.series,function(b){if(b.type===a.type)b.isDirty=!0});P.prototype.remove.apply(a,arguments)}});$.column=fa;X.bar=B(X.column);Ca=ba(fa,{type:"bar",inverted:!0});$.bar=Ca;X.scatter=B(ea,{lineWidth:0,states:{hover:{lineWidth:0}},tooltip:{headerFormat:'<span style="font-size: 10px; color:{series.color}">{series.name}</span><br/>',
pointFormat:"x: <b>{point.x}</b><br/>y: <b>{point.y}</b><br/>"}});Ca=ba(P,{type:"scatter",sorted:!1,requireSorting:!1,translate:function(){var a=this;P.prototype.translate.apply(a);o(a.points,function(b){b.shapeType="circle";b.shapeArgs={x:b.plotX,y:b.plotY,r:a.chart.options.tooltip.snap}})},drawTracker:function(){for(var a=this,b=a.options.cursor,b=b&&{cursor:b},c=a.points,d=c.length,e,f=a.markerGroup,g=function(b){a.onMouseOver();if(b.target._i!==A)c[b.target._i].onMouseOver()};d--;)if(e=c[d].graphic)e.element._i=
d;if(a._hasTracking)a._hasTracking=!0;else if(f.attr({isTracker:!0}).on("mouseover",g).on("mouseout",function(){if(!a.options.stickyTracking)a.onMouseOut()}).css(b),Ba)f.on("touchstart",g)},setTooltipPoints:pa});$.scatter=Ca;X.pie=B(ea,{borderColor:"#FFFFFF",borderWidth:1,center:["50%","50%"],colorByPoint:!0,dataLabels:{distance:30,enabled:!0,formatter:function(){return this.point.name}},legendType:"point",marker:null,size:"75%",showInLegend:!1,slicedOffset:10,states:{hover:{brightness:0.1,shadow:!1}}});
pa={type:"pie",isCartesian:!1,pointClass:ba(Ua,{init:function(){Ua.prototype.init.apply(this,arguments);var a=this,b;x(a,{visible:a.visible!==!1,name:n(a.name,"Slice")});b=function(){a.slice()};J(a,"select",b);J(a,"unselect",b);return a},setVisible:function(a){var b=this.series,c=b.chart,d=this.tracker,e=this.dataLabel,f=this.connector,g=this.shadowGroup,h;h=(this.visible=a=a===A?!this.visible:a)?"show":"hide";this.group[h]();if(d)d[h]();if(e)e[h]();if(f)f[h]();if(g)g[h]();this.legendItem&&c.legend.colorizeItem(this,
a);if(!b.isDirty&&b.options.ignoreHiddenPoint)b.isDirty=!0,c.redraw()},slice:function(a,b,c){var d=this.series.chart,e=this.slicedTranslation;xa(c,d);n(b,!0);a=this.sliced=r(a)?a:!this.sliced;a={translateX:a?e[0]:d.plotLeft,translateY:a?e[1]:d.plotTop};this.group.animate(a);this.shadowGroup&&this.shadowGroup.animate(a)}}),requireSorting:!1,pointAttrToOptions:{stroke:"borderColor","stroke-width":"borderWidth",fill:"color"},getColor:function(){this.initialColor=this.chart.counters.color},animate:function(){var a=
this,b=a.startAngleRad;o(a.points,function(c){var d=c.graphic,c=c.shapeArgs;d&&(d.attr({r:a.center[3]/2,start:b,end:b}),d.animate({r:c.r,start:c.start,end:c.end},a.options.animation))});a.animate=null},setData:function(a,b){P.prototype.setData.call(this,a,!1);this.processData();this.generatePoints();n(b,!0)&&this.chart.redraw()},getCenter:function(){var a=this.options,b=this.chart,c=b.plotWidth,d=b.plotHeight,a=a.center.concat([a.size,a.innerSize||0]),e=O(c,d),f;return Ta(a,function(a,b){return(f=
/%$/.test(a))?[c,d,e,e][b]*z(a)/100:a})},translate:function(){this.generatePoints();var a=0,b=0,c=this.options,d=c.slicedOffset,e=d+c.borderWidth,f,g=this.chart,h,i,j,k=this.startAngleRad=Aa/180*((c.startAngle||0)%360-90),l=this.points,m=2*Aa,n=c.dataLabels.distance,o=c.ignoreHiddenPoint,r,t=l.length,s;this.center=f=this.getCenter();this.getX=function(a,b){j=K.asin((a-f[1])/(f[2]/2+n));return f[0]+(b?-1:1)*W(j)*(f[2]/2+n)};for(r=0;r<t;r++)s=l[r],a+=o&&!s.visible?0:s.y;for(r=0;r<t;r++){s=l[r];c=a?
s.y/a:0;h=u((k+b*m)*1E3)/1E3;if(!o||s.visible)b+=c;i=u((k+b*m)*1E3)/1E3;s.shapeType="arc";s.shapeArgs={x:f[0],y:f[1],r:f[2]/2,innerR:f[3]/2,start:h,end:i};j=(i+h)/2;j>0.75*m&&(j-=2*Aa);s.slicedTranslation=Ta([W(j)*d+g.plotLeft,Z(j)*d+g.plotTop],u);h=W(j)*f[2]/2;i=Z(j)*f[2]/2;s.tooltipPos=[f[0]+h*0.7,f[1]+i*0.7];s.half=j<m/4?0:1;s.angle=j;s.labelPos=[f[0]+h+W(j)*n,f[1]+i+Z(j)*n,f[0]+h+W(j)*e,f[1]+i+Z(j)*e,f[0]+h,f[1]+i,n<0?"center":s.half?"right":"left",j];s.percentage=c*100;s.total=a}this.setTooltipPoints()},
render:function(){this.getAttribs();this.drawPoints();this.options.enableMouseTracking!==!1&&this.drawTracker();this.drawDataLabels();this.options.animation&&this.animate&&this.animate();this.isDirty=!1},drawPoints:function(){var a=this,b=a.chart,c=b.renderer,d,e,f,g=a.options.shadow,h,i;o(a.points,function(j){e=j.graphic;i=j.shapeArgs;f=j.group;h=j.shadowGroup;if(g&&!h)h=j.shadowGroup=c.g("shadow").attr({zIndex:4}).add();if(!f)f=j.group=c.g("point").attr({zIndex:5}).add();d=j.sliced?j.slicedTranslation:
[b.plotLeft,b.plotTop];f.translate(d[0],d[1]);h&&h.translate(d[0],d[1]);e?e.animate(i):j.graphic=e=c.arc(i).setRadialReference(a.center).attr(x(j.pointAttr[""],{"stroke-linejoin":"round"})).add(j.group).shadow(g,h);j.visible===!1&&j.setVisible(!1)})},drawDataLabels:function(){var a=this.data,b,c=this.chart,d=this.options.dataLabels,e=n(d.connectorPadding,10),f=n(d.connectorWidth,1),g,h,i=n(d.softConnector,!0),j=d.distance,k=this.center,l=k[2]/2,m=k[1],q=j>0,p=[[],[]],r,t,s,u=2,v,x=function(a,b){return b.y-
a.y},z=function(a,b){a.sort(function(a,c){return(c.angle-a.angle)*b})};if(d.enabled||this._hasPointLabels){P.prototype.drawDataLabels.apply(this);o(a,function(a){a.dataLabel&&p[a.half].push(a)});for(a=p[0][0]&&p[0][0].dataLabel&&(p[0][0].dataLabel.getBBox().height||21);u--;){var w=[],A=[],B=p[u],C=B.length,D;z(B,u-0.5);if(j>0){for(v=m-l-j;v<=m+l+j;v+=a)w.push(v);s=w.length;if(C>s){h=[].concat(B);h.sort(x);for(v=C;v--;)h[v].rank=v;for(v=C;v--;)B[v].rank>=s&&B.splice(v,1);C=B.length}for(v=0;v<C;v++){b=
B[v];h=b.labelPos;b=9999;for(t=0;t<s;t++)g=M(w[t]-h[1]),g<b&&(b=g,D=t);if(D<v&&w[v]!==null)D=v;else for(s<C-v+D&&w[v]!==null&&(D=s-C+v);w[D]===null;)D++;A.push({i:D,y:w[D]});w[D]=null}A.sort(x)}for(v=0;v<C;v++){b=B[v];h=b.labelPos;g=b.dataLabel;s=b.visible===!1?"hidden":"visible";r=h[1];if(j>0){if(t=A.pop(),D=t.i,t=t.y,r>t&&w[D+1]!==null||r<t&&w[D-1]!==null)t=r}else t=r;r=d.justify?k[0]+(u?-1:1)*(l+j):this.getX(D===0||D===w.length-1?r:t,u);g.attr({visibility:s,align:h[6]})[g.moved?"animate":"attr"]({x:r+
d.x+({left:e,right:-e}[h[6]]||0),y:t+d.y-10});g.moved=!0;if(q&&f)g=b.connector,h=i?["M",r+(h[6]==="left"?5:-5),t,"C",r,t,2*h[2]-h[4],2*h[3]-h[5],h[2],h[3],"L",h[4],h[5]]:["M",r+(h[6]==="left"?5:-5),t,"L",h[2],h[3],"L",h[4],h[5]],g?(g.animate({d:h}),g.attr("visibility",s)):b.connector=g=this.chart.renderer.path(h).attr({"stroke-width":f,stroke:d.connectorColor||b.color||"#606060",visibility:s,zIndex:3}).translate(c.plotLeft,c.plotTop).add()}}}},alignDataLabel:pa,drawTracker:fa.prototype.drawTracker,
drawLegendSymbol:G.prototype.drawLegendSymbol,getSymbol:function(){}};pa=ba(P,pa);$.pie=pa;x(Highcharts,{Axis:ob,CanVGRenderer:gb,Chart:sb,Color:qa,Legend:rb,MouseTracker:qb,Point:Ua,Tick:Qa,Tooltip:pb,Renderer:Sa,Series:P,SVGRenderer:sa,VMLRenderer:ha,arrayMin:Fa,arrayMax:wa,charts:Ha,dateFormat:db,pathAnim:ub,getOptions:function(){return N},hasBidiBug:Sb,isTouchDevice:Mb,numberFormat:Ja,seriesTypes:$,setOptions:function(a){N=B(N,a);Jb();return N},addEvent:J,removeEvent:R,createElement:T,discardElement:Na,
css:I,each:o,extend:x,map:Ta,merge:B,pick:n,splat:la,extendClass:ba,pInt:z,wrap:function(a,b,c){var d=a[b];a[b]=function(){var a=Array.prototype.slice.call(arguments);a.unshift(d);return c.apply(this,a)}},svg:ca,canvas:V,vml:!ca&&!V,product:"Highcharts",version:"2.3.5"})})();
body {
 padding-top: 10px;
}

.popover {
 width: 600px;
}

.table td {
 padding-top: 3px;
 padding-bottom: 3px;
}

.table-condensed td {
 padding-top: 0;
 padding-bottom: 0;
}

.table .progress {
 margin-bottom: inherit;
}

.table-borderless th, .table-borderless td {
 border: 0 !important;
}

.table tbody td.success, li.success, span.success {
 background-color: #dff0d8;
}

.table tbody tr.danger, .table tbody td.danger, li.danger, span.danger {
 background-color: #f2dede;
}

.table tbody td.warning, li.warning, span.warning {
 background-color: #fcf8e3;
}

.table tbody td.info {
 background-color: #d9edf7;
}

td.big {
 width: 100px;
}

td.small {
}

td.codeLine {
 font-family: monospace;
 white-space: pre;
}

td span.comment {
 color: #888a85;
}

td span.default {
 color: #2e3436;
}

td span.html {
 color: #888a85;
}

td span.keyword {
 color: #2e3436;
 font-weight: bold;
}

pre span.string {
 color: #2e3436;
}

span.success, span.warning, span.danger {
 margin-right: 2px;
 padding-left: 10px;
 padding-right: 10px;
 text-align: center;
}

#classCoverageDistribution, #classComplexity {
 height: 200px;
 width: 475px;
}
/*!
 * Bootstrap Responsive v2.2.2
 *
 * Copyright 2012 Twitter, Inc
 * Licensed under the Apache License v2.0
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Designed and built with all the love in the world @twitter by @mdo and @fat.
 */@-ms-viewport{width:device-width}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}.visible-desktop{display:inherit!important}@media(min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}}@media(max-width:767px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-phone{display:inherit!important}.hidden-phone{display:none!important}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:30px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.564102564102564%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%}.row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%}.row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%}.row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%}.row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%}.row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%}.row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%}.row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%}.row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%}.row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%}.row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%}.row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%}.row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%}.row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%}.row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%}.row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%}.row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%}.row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%}.row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%}.row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%}.row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%}.row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%}.row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%}.row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%}.row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%}.row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%}.row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%}.row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%}.row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%}.row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%}.row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%}.row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%}.row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%}.row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%}.row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:30px}input.span12,textarea.span12,.uneditable-input.span12{width:1156px}input.span11,textarea.span11,.uneditable-input.span11{width:1056px}input.span10,textarea.span10,.uneditable-input.span10{width:956px}input.span9,textarea.span9,.uneditable-input.span9{width:856px}input.span8,textarea.span8,.uneditable-input.span8{width:756px}input.span7,textarea.span7,.uneditable-input.span7{width:656px}input.span6,textarea.span6,.uneditable-input.span6{width:556px}input.span5,textarea.span5,.uneditable-input.span5{width:456px}input.span4,textarea.span4,.uneditable-input.span4{width:356px}input.span3,textarea.span3,.uneditable-input.span3{width:256px}input.span2,textarea.span2,.uneditable-input.span2{width:156px}input.span1,textarea.span1,.uneditable-input.span1{width:56px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media(min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px}.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px}.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.7624309392265194%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%}.row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%}.row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%}.row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%}.row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%}.row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%}.row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%}.row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%}.row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%}.row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%}.row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%}.row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%}.row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%}.row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%}.row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%}.row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%}.row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%}.row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%}.row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%}.row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%}.row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%}.row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%}.row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%}.row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%}.row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%}.row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%}.row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%}.row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%}.row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%}.row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%}.row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%}.row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%}.row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%}.row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%}.row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:710px}input.span11,textarea.span11,.uneditable-input.span11{width:648px}input.span10,textarea.span10,.uneditable-input.span10{width:586px}input.span9,textarea.span9,.uneditable-input.span9{width:524px}input.span8,textarea.span8,.uneditable-input.span8{width:462px}input.span7,textarea.span7,.uneditable-input.span7{width:400px}input.span6,textarea.span6,.uneditable-input.span6{width:338px}input.span5,textarea.span5,.uneditable-input.span5{width:276px}input.span4,textarea.span4,.uneditable-input.span4{width:214px}input.span3,textarea.span3,.uneditable-input.span3{width:152px}input.span2,textarea.span2,.uneditable-input.span2{width:90px}input.span1,textarea.span1,.uneditable-input.span1{width:28px}}@media(max-width:767px){body{padding-right:20px;padding-left:20px}.navbar-fixed-top,.navbar-fixed-bottom,.navbar-static-top{margin-right:-20px;margin-left:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:auto}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}.thumbnails>li{float:none;margin-left:0}[class*="span"],.uneditable-input[class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="offset"]:first-child{margin-left:0}.input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto}.controls-row [class*="span"]+[class*="span"]{margin-left:0}.modal{position:fixed;top:20px;right:20px;left:20px;width:auto;margin:0}.modal.fade{top:-100px}.modal.fade.in{top:20px}}@media(max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:20px}input[type="checkbox"],input[type="radio"]{border:1px solid #ccc}.form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-right:10px;padding-left:10px}.media .pull-left,.media .pull-right{display:block;float:none;margin-bottom:10px}.media-object{margin-right:0;margin-left:0}.modal{top:10px;right:10px;left:10px}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media(max-width:979px){body{padding-top:0}.navbar-fixed-top,.navbar-fixed-bottom{position:static}.navbar-fixed-top{margin-bottom:20px}.navbar-fixed-bottom{margin-top:20px}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px}.navbar .container{width:auto;padding:0}.navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 10px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#777;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .nav>li>a:hover,.nav-collapse .dropdown-menu a:hover{background-color:#f2f2f2}.navbar-inverse .nav-collapse .nav>li>a,.navbar-inverse .nav-collapse .dropdown-menu a{color:#999}.navbar-inverse .nav-collapse .nav>li>a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:hover{background-color:#111}.nav-collapse.in .btn-group{padding:0;margin-top:5px}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:none;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.nav-collapse .open>.dropdown-menu{display:block}.nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none}.nav-collapse .dropdown-menu .divider{display:none}.nav-collapse .nav>li>.dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}.navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111;border-bottom-color:#111}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.nav-collapse.collapse{height:auto!important;overflow:visible!important}}
/*!
 * Bootstrap v2.2.2
 *
 * Copyright 2012 Twitter, Inc
 * Licensed under the Apache License v2.0
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Designed and built with all the love in the world @twitter by @mdo and @fat.
 */article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:hover,a:active{outline:0}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{width:auto\9;height:auto;max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}#map_canvas img,.google-maps img{max-width:none}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle}button,input{*overflow:visible;line-height:normal}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}button,html input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}label,select,button,input[type="button"],input[type="reset"],input[type="submit"],input[type="radio"],input[type="checkbox"]{cursor:pointer}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}textarea{overflow:auto;vertical-align:top}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:20px;color:#333;background-color:#fff}a{color:#08c;text-decoration:none}a:hover{color:#005580;text-decoration:underline}.img-rounded{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1)}.img-circle{-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px}.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.span12{width:940px}.span11{width:860px}.span10{width:780px}.span9{width:700px}.span8{width:620px}.span7{width:540px}.span6{width:460px}.span5{width:380px}.span4{width:300px}.span3{width:220px}.span2{width:140px}.span1{width:60px}.offset12{margin-left:980px}.offset11{margin-left:900px}.offset10{margin-left:820px}.offset9{margin-left:740px}.offset8{margin-left:660px}.offset7{margin-left:580px}.offset6{margin-left:500px}.offset5{margin-left:420px}.offset4{margin-left:340px}.offset3{margin-left:260px}.offset2{margin-left:180px}.offset1{margin-left:100px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.127659574468085%;*margin-left:2.074468085106383%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.127659574468085%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.48936170212765%;*width:91.43617021276594%}.row-fluid .span10{width:82.97872340425532%;*width:82.92553191489361%}.row-fluid .span9{width:74.46808510638297%;*width:74.41489361702126%}.row-fluid .span8{width:65.95744680851064%;*width:65.90425531914893%}.row-fluid .span7{width:57.44680851063829%;*width:57.39361702127659%}.row-fluid .span6{width:48.93617021276595%;*width:48.88297872340425%}.row-fluid .span5{width:40.42553191489362%;*width:40.37234042553192%}.row-fluid .span4{width:31.914893617021278%;*width:31.861702127659576%}.row-fluid .span3{width:23.404255319148934%;*width:23.351063829787233%}.row-fluid .span2{width:14.893617021276595%;*width:14.840425531914894%}.row-fluid .span1{width:6.382978723404255%;*width:6.329787234042553%}.row-fluid .offset12{margin-left:104.25531914893617%;*margin-left:104.14893617021275%}.row-fluid .offset12:first-child{margin-left:102.12765957446808%;*margin-left:102.02127659574467%}.row-fluid .offset11{margin-left:95.74468085106382%;*margin-left:95.6382978723404%}.row-fluid .offset11:first-child{margin-left:93.61702127659574%;*margin-left:93.51063829787232%}.row-fluid .offset10{margin-left:87.23404255319149%;*margin-left:87.12765957446807%}.row-fluid .offset10:first-child{margin-left:85.1063829787234%;*margin-left:84.99999999999999%}.row-fluid .offset9{margin-left:78.72340425531914%;*margin-left:78.61702127659572%}.row-fluid .offset9:first-child{margin-left:76.59574468085106%;*margin-left:76.48936170212764%}.row-fluid .offset8{margin-left:70.2127659574468%;*margin-left:70.10638297872339%}.row-fluid .offset8:first-child{margin-left:68.08510638297872%;*margin-left:67.9787234042553%}.row-fluid .offset7{margin-left:61.70212765957446%;*margin-left:61.59574468085106%}.row-fluid .offset7:first-child{margin-left:59.574468085106375%;*margin-left:59.46808510638297%}.row-fluid .offset6{margin-left:53.191489361702125%;*margin-left:53.085106382978715%}.row-fluid .offset6:first-child{margin-left:51.063829787234035%;*margin-left:50.95744680851063%}.row-fluid .offset5{margin-left:44.68085106382979%;*margin-left:44.57446808510638%}.row-fluid .offset5:first-child{margin-left:42.5531914893617%;*margin-left:42.4468085106383%}.row-fluid .offset4{margin-left:36.170212765957444%;*margin-left:36.06382978723405%}.row-fluid .offset4:first-child{margin-left:34.04255319148936%;*margin-left:33.93617021276596%}.row-fluid .offset3{margin-left:27.659574468085104%;*margin-left:27.5531914893617%}.row-fluid .offset3:first-child{margin-left:25.53191489361702%;*margin-left:25.425531914893618%}.row-fluid .offset2{margin-left:19.148936170212764%;*margin-left:19.04255319148936%}.row-fluid .offset2:first-child{margin-left:17.02127659574468%;*margin-left:16.914893617021278%}.row-fluid .offset1{margin-left:10.638297872340425%;*margin-left:10.53191489361702%}.row-fluid .offset1:first-child{margin-left:8.51063829787234%;*margin-left:8.404255319148938%}[class*="span"].hide,.row-fluid [class*="span"].hide{display:none}[class*="span"].pull-right,.row-fluid [class*="span"].pull-right{float:right}.container{margin-right:auto;margin-left:auto;*zoom:1}.container:before,.container:after{display:table;line-height:0;content:""}.container:after{clear:both}.container-fluid{padding-right:20px;padding-left:20px;*zoom:1}.container-fluid:before,.container-fluid:after{display:table;line-height:0;content:""}.container-fluid:after{clear:both}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:21px;font-weight:200;line-height:30px}small{font-size:85%}strong{font-weight:bold}em{font-style:italic}cite{font-style:normal}.muted{color:#999}a.muted:hover{color:#808080}.text-warning{color:#c09853}a.text-warning:hover{color:#a47e3c}.text-error{color:#b94a48}a.text-error:hover{color:#953b39}.text-info{color:#3a87ad}a.text-info:hover{color:#2d6987}.text-success{color:#468847}a.text-success:hover{color:#356635}h1,h2,h3,h4,h5,h6{margin:10px 0;font-family:inherit;font-weight:bold;line-height:20px;color:inherit;text-rendering:optimizelegibility}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;line-height:1;color:#999}h1,h2,h3{line-height:40px}h1{font-size:38.5px}h2{font-size:31.5px}h3{font-size:24.5px}h4{font-size:17.5px}h5{font-size:14px}h6{font-size:11.9px}h1 small{font-size:24.5px}h2 small{font-size:17.5px}h3 small{font-size:14px}h4 small{font-size:14px}.page-header{padding-bottom:9px;margin:20px 0 30px;border-bottom:1px solid #eee}ul,ol{padding:0;margin:0 0 10px 25px}ul ul,ul ol,ol ol,ol ul{margin-bottom:0}li{line-height:20px}ul.unstyled,ol.unstyled{margin-left:0;list-style:none}ul.inline,ol.inline{margin-left:0;list-style:none}ul.inline>li,ol.inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-bottom:20px}dt,dd{line-height:20px}dt{font-weight:bold}dd{margin-left:10px}.dl-horizontal{*zoom:1}.dl-horizontal:before,.dl-horizontal:after{display:table;line-height:0;content:""}.dl-horizontal:after{clear:both}.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}hr{margin:20px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:16px;font-weight:300;line-height:25px}blockquote small{display:block;line-height:20px;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right}blockquote.pull-right small:before{content:''}blockquote.pull-right small:after{content:'\00A0 \2014'}q:before,q:after,blockquote:before,blockquote:after{content:""}address{display:block;margin-bottom:20px;font-style:normal;line-height:20px}code,pre{padding:0 3px 2px;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;font-size:12px;color:#333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}code{padding:2px 4px;color:#d14;white-space:nowrap;background-color:#f7f7f9;border:1px solid #e1e1e8}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}pre.prettyprint{margin-bottom:20px}pre code{padding:0;color:inherit;white-space:pre;white-space:pre-wrap;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}form{margin:0 0 20px}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:40px;color:#333;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:15px;color:#999}label,input,button,select,textarea{font-size:14px;font-weight:normal;line-height:20px}input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}label{display:block;margin-bottom:5px}select,textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{display:inline-block;height:20px;padding:4px 6px;margin-bottom:10px;font-size:14px;line-height:20px;color:#555;vertical-align:middle;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}input,textarea,.uneditable-input{width:206px}textarea{height:auto}textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{background-color:#fff;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s}textarea:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{border-color:rgba(82,168,236,0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;*margin-top:0;line-height:normal}input[type="file"],input[type="image"],input[type="submit"],input[type="reset"],input[type="button"],input[type="radio"],input[type="checkbox"]{width:auto}select,input[type="file"]{height:30px;*margin-top:4px;line-height:30px}select{width:220px;background-color:#fff;border:1px solid #ccc}select[multiple],select[size]{height:auto}select:focus,input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.uneditable-input,.uneditable-textarea{color:#999;cursor:not-allowed;background-color:#fcfcfc;border-color:#ccc;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);box-shadow:inset 0 1px 2px rgba(0,0,0,0.025)}.uneditable-input{overflow:hidden;white-space:nowrap}.uneditable-textarea{width:auto;height:auto}input:-moz-placeholder,textarea:-moz-placeholder{color:#999}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#999}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#999}.radio,.checkbox{min-height:20px;padding-left:20px}.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-20px}.controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px}.radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle}.radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px}.input-mini{width:60px}.input-small{width:90px}.input-medium{width:150px}.input-large{width:210px}.input-xlarge{width:270px}.input-xxlarge{width:530px}input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0}.input-append input[class*="span"],.input-append .uneditable-input[class*="span"],.input-prepend input[class*="span"],.input-prepend .uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"],.row-fluid .input-prepend [class*="span"],.row-fluid .input-append [class*="span"]{display:inline-block}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:926px}input.span11,textarea.span11,.uneditable-input.span11{width:846px}input.span10,textarea.span10,.uneditable-input.span10{width:766px}input.span9,textarea.span9,.uneditable-input.span9{width:686px}input.span8,textarea.span8,.uneditable-input.span8{width:606px}input.span7,textarea.span7,.uneditable-input.span7{width:526px}input.span6,textarea.span6,.uneditable-input.span6{width:446px}input.span5,textarea.span5,.uneditable-input.span5{width:366px}input.span4,textarea.span4,.uneditable-input.span4{width:286px}input.span3,textarea.span3,.uneditable-input.span3{width:206px}input.span2,textarea.span2,.uneditable-input.span2{width:126px}input.span1,textarea.span1,.uneditable-input.span1{width:46px}.controls-row{*zoom:1}.controls-row:before,.controls-row:after{display:table;line-height:0;content:""}.controls-row:after{clear:both}.controls-row [class*="span"],.row-fluid .controls-row [class*="span"]{float:left}.controls-row .checkbox[class*="span"],.controls-row .radio[class*="span"]{padding-top:5px}input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#eee}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"][readonly],input[type="checkbox"][readonly]{background-color:transparent}.control-group.warning .control-label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853}.control-group.warning .checkbox,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853}.control-group.warning input,.control-group.warning select,.control-group.warning textarea{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e}.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.control-group.error .control-label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48}.control-group.error .checkbox,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48}.control-group.error input,.control-group.error select,.control-group.error textarea{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392}.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.control-group.success .control-label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847}.control-group.success .checkbox,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847}.control-group.success input,.control-group.success select,.control-group.success textarea{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b}.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847}.control-group.info .control-label,.control-group.info .help-block,.control-group.info .help-inline{color:#3a87ad}.control-group.info .checkbox,.control-group.info .radio,.control-group.info input,.control-group.info select,.control-group.info textarea{color:#3a87ad}.control-group.info input,.control-group.info select,.control-group.info textarea{border-color:#3a87ad;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.info input:focus,.control-group.info select:focus,.control-group.info textarea:focus{border-color:#2d6987;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3}.control-group.info .input-prepend .add-on,.control-group.info .input-append .add-on{color:#3a87ad;background-color:#d9edf7;border-color:#3a87ad}input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#b94a48;border-color:#ee5f5b}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7}.form-actions{padding:19px 20px 20px;margin-top:20px;margin-bottom:20px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1}.form-actions:before,.form-actions:after{display:table;line-height:0;content:""}.form-actions:after{clear:both}.help-block,.help-inline{color:#595959}.help-block{display:block;margin-bottom:10px}.help-inline{display:inline-block;*display:inline;padding-left:5px;vertical-align:middle;*zoom:1}.input-append,.input-prepend{margin-bottom:5px;font-size:0;white-space:nowrap}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input,.input-append .dropdown-menu,.input-prepend .dropdown-menu{font-size:14px}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;vertical-align:top;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append input:focus,.input-prepend input:focus,.input-append select:focus,.input-prepend select:focus,.input-append .uneditable-input:focus,.input-prepend .uneditable-input:focus{z-index:2}.input-append .add-on,.input-prepend .add-on{display:inline-block;width:auto;height:20px;min-width:16px;padding:4px 5px;font-size:14px;font-weight:normal;line-height:20px;text-align:center;text-shadow:0 1px 0 #fff;background-color:#eee;border:1px solid #ccc}.input-append .add-on,.input-prepend .add-on,.input-append .btn,.input-prepend .btn,.input-append .btn-group>.dropdown-toggle,.input-prepend .btn-group>.dropdown-toggle{vertical-align:top;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-append .active,.input-prepend .active{background-color:#a9dba9;border-color:#46a546}.input-prepend .add-on,.input-prepend .btn{margin-right:-1px}.input-prepend .add-on:first-child,.input-prepend .btn:first-child{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input,.input-append select,.input-append .uneditable-input{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input+.btn-group .btn:last-child,.input-append select+.btn-group .btn:last-child,.input-append .uneditable-input+.btn-group .btn:last-child{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append .add-on,.input-append .btn,.input-append .btn-group{margin-left:-1px}.input-append .add-on:last-child,.input-append .btn:last-child,.input-append .btn-group:last-child>.dropdown-toggle{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .uneditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-prepend.input-append input+.btn-group .btn,.input-prepend.input-append select+.btn-group .btn,.input-prepend.input-append .uneditable-input+.btn-group .btn{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .btn-group:first-child{margin-left:0}input.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.form-search .input-append .search-query,.form-search .input-prepend .search-query{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.form-search .input-append .search-query{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search .input-append .btn{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .search-query{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .btn{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;margin-bottom:0;vertical-align:middle;*zoom:1}.form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none}.form-search label,.form-inline label,.form-search .btn-group,.form-inline .btn-group{display:inline-block}.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{margin-bottom:0}.form-search .radio,.form-search .checkbox,.form-inline .radio,.form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle}.form-search .radio input[type="radio"],.form-search .checkbox input[type="checkbox"],.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0}.control-group{margin-bottom:10px}legend+.control-group{margin-top:20px;-webkit-margin-top-collapse:separate}.form-horizontal .control-group{margin-bottom:20px;*zoom:1}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;line-height:0;content:""}.form-horizontal .control-group:after{clear:both}.form-horizontal .control-label{float:left;width:160px;padding-top:5px;text-align:right}.form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:180px;*margin-left:0}.form-horizontal .controls:first-child{*padding-left:180px}.form-horizontal .help-block{margin-bottom:0}.form-horizontal input+.help-block,.form-horizontal select+.help-block,.form-horizontal textarea+.help-block,.form-horizontal .uneditable-input+.help-block,.form-horizontal .input-prepend+.help-block,.form-horizontal .input-append+.help-block{margin-top:10px}.form-horizontal .form-actions{padding-left:180px}table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0}.table{width:100%;margin-bottom:20px}.table th,.table td{padding:8px;line-height:20px;text-align:left;vertical-align:top;border-top:1px solid #ddd}.table th{font-weight:bold}.table thead th{vertical-align:bottom}.table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child th,.table thead:first-child tr:first-child td{border-top:0}.table tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed th,.table-condensed td{padding:4px 5px}.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;border-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.table-bordered th,.table-bordered td{border-left:1px solid #ddd}.table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0}.table-bordered thead:first-child tr:first-child>th:first-child,.table-bordered tbody:first-child tr:first-child>td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered thead:first-child tr:first-child>th:last-child,.table-bordered tbody:first-child tr:first-child>td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-bordered thead:last-child tr:last-child>th:first-child,.table-bordered tbody:last-child tr:last-child>td:first-child,.table-bordered tfoot:last-child tr:last-child>td:first-child{-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px}.table-bordered thead:last-child tr:last-child>th:last-child,.table-bordered tbody:last-child tr:last-child>td:last-child,.table-bordered tfoot:last-child tr:last-child>td:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px}.table-bordered tfoot+tbody:last-child tr:last-child td:first-child{-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomleft:0}.table-bordered tfoot+tbody:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-moz-border-radius-bottomright:0}.table-bordered caption+thead tr:first-child th:first-child,.table-bordered caption+tbody tr:first-child td:first-child,.table-bordered colgroup+thead tr:first-child th:first-child,.table-bordered colgroup+tbody tr:first-child td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered caption+thead tr:first-child th:last-child,.table-bordered caption+tbody tr:first-child td:last-child,.table-bordered colgroup+thead tr:first-child th:last-child,.table-bordered colgroup+tbody tr:first-child td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-striped tbody>tr:nth-child(odd)>td,.table-striped tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover tbody tr:hover td,.table-hover tbody tr:hover th{background-color:#f5f5f5}table td[class*="span"],table th[class*="span"],.row-fluid table td[class*="span"],.row-fluid table th[class*="span"]{display:table-cell;float:none;margin-left:0}.table td.span1,.table th.span1{float:none;width:44px;margin-left:0}.table td.span2,.table th.span2{float:none;width:124px;margin-left:0}.table td.span3,.table th.span3{float:none;width:204px;margin-left:0}.table td.span4,.table th.span4{float:none;width:284px;margin-left:0}.table td.span5,.table th.span5{float:none;width:364px;margin-left:0}.table td.span6,.table th.span6{float:none;width:444px;margin-left:0}.table td.span7,.table th.span7{float:none;width:524px;margin-left:0}.table td.span8,.table th.span8{float:none;width:604px;margin-left:0}.table td.span9,.table th.span9{float:none;width:684px;margin-left:0}.table td.span10,.table th.span10{float:none;width:764px;margin-left:0}.table td.span11,.table th.span11{float:none;width:844px;margin-left:0}.table td.span12,.table th.span12{float:none;width:924px;margin-left:0}.table tbody tr.success td{background-color:#dff0d8}.table tbody tr.error td{background-color:#f2dede}.table tbody tr.warning td{background-color:#fcf8e3}.table tbody tr.info td{background-color:#d9edf7}.table-hover tbody tr.success:hover td{background-color:#d0e9c6}.table-hover tbody tr.error:hover td{background-color:#ebcccc}.table-hover tbody tr.warning:hover td{background-color:#faf2cc}.table-hover tbody tr.info:hover td{background-color:#c4e3f3}[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;margin-top:1px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat}.icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"]{background-image:url("../img/glyphicons-halflings-white.png")}.icon-glass{background-position:0 0}.icon-music{background-position:-24px 0}.icon-search{background-position:-48px 0}.icon-envelope{background-position:-72px 0}.icon-heart{background-position:-96px 0}.icon-star{background-position:-120px 0}.icon-star-empty{background-position:-144px 0}.icon-user{background-position:-168px 0}.icon-film{background-position:-192px 0}.icon-th-large{background-position:-216px 0}.icon-th{background-position:-240px 0}.icon-th-list{background-position:-264px 0}.icon-ok{background-position:-288px 0}.icon-remove{background-position:-312px 0}.icon-zoom-in{background-position:-336px 0}.icon-zoom-out{background-position:-360px 0}.icon-off{background-position:-384px 0}.icon-signal{background-position:-408px 0}.icon-cog{background-position:-432px 0}.icon-trash{background-position:-456px 0}.icon-home{background-position:0 -24px}.icon-file{background-position:-24px -24px}.icon-time{background-position:-48px -24px}.icon-road{background-position:-72px -24px}.icon-download-alt{background-position:-96px -24px}.icon-download{background-position:-120px -24px}.icon-upload{background-position:-144px -24px}.icon-inbox{background-position:-168px -24px}.icon-play-circle{background-position:-192px -24px}.icon-repeat{background-position:-216px -24px}.icon-refresh{background-position:-240px -24px}.icon-list-alt{background-position:-264px -24px}.icon-lock{background-position:-287px -24px}.icon-flag{background-position:-312px -24px}.icon-headphones{background-position:-336px -24px}.icon-volume-off{background-position:-360px -24px}.icon-volume-down{background-position:-384px -24px}.icon-volume-up{background-position:-408px -24px}.icon-qrcode{background-position:-432px -24px}.icon-barcode{background-position:-456px -24px}.icon-tag{background-position:0 -48px}.icon-tags{background-position:-25px -48px}.icon-book{background-position:-48px -48px}.icon-bookmark{background-position:-72px -48px}.icon-print{background-position:-96px -48px}.icon-camera{background-position:-120px -48px}.icon-font{background-position:-144px -48px}.icon-bold{background-position:-167px -48px}.icon-italic{background-position:-192px -48px}.icon-text-height{background-position:-216px -48px}.icon-text-width{background-position:-240px -48px}.icon-align-left{background-position:-264px -48px}.icon-align-center{background-position:-288px -48px}.icon-align-right{background-position:-312px -48px}.icon-align-justify{background-position:-336px -48px}.icon-list{background-position:-360px -48px}.icon-indent-left{background-position:-384px -48px}.icon-indent-right{background-position:-408px -48px}.icon-facetime-video{background-position:-432px -48px}.icon-picture{background-position:-456px -48px}.icon-pencil{background-position:0 -72px}.icon-map-marker{background-position:-24px -72px}.icon-adjust{background-position:-48px -72px}.icon-tint{background-position:-72px -72px}.icon-edit{background-position:-96px -72px}.icon-share{background-position:-120px -72px}.icon-check{background-position:-144px -72px}.icon-move{background-position:-168px -72px}.icon-step-backward{background-position:-192px -72px}.icon-fast-backward{background-position:-216px -72px}.icon-backward{background-position:-240px -72px}.icon-play{background-position:-264px -72px}.icon-pause{background-position:-288px -72px}.icon-stop{background-position:-312px -72px}.icon-forward{background-position:-336px -72px}.icon-fast-forward{background-position:-360px -72px}.icon-step-forward{background-position:-384px -72px}.icon-eject{background-position:-408px -72px}.icon-chevron-left{background-position:-432px -72px}.icon-chevron-right{background-position:-456px -72px}.icon-plus-sign{background-position:0 -96px}.icon-minus-sign{background-position:-24px -96px}.icon-remove-sign{background-position:-48px -96px}.icon-ok-sign{background-position:-72px -96px}.icon-question-sign{background-position:-96px -96px}.icon-info-sign{background-position:-120px -96px}.icon-screenshot{background-position:-144px -96px}.icon-remove-circle{background-position:-168px -96px}.icon-ok-circle{background-position:-192px -96px}.icon-ban-circle{background-position:-216px -96px}.icon-arrow-left{background-position:-240px -96px}.icon-arrow-right{background-position:-264px -96px}.icon-arrow-up{background-position:-289px -96px}.icon-arrow-down{background-position:-312px -96px}.icon-share-alt{background-position:-336px -96px}.icon-resize-full{background-position:-360px -96px}.icon-resize-small{background-position:-384px -96px}.icon-plus{background-position:-408px -96px}.icon-minus{background-position:-433px -96px}.icon-asterisk{background-position:-456px -96px}.icon-exclamation-sign{background-position:0 -120px}.icon-gift{background-position:-24px -120px}.icon-leaf{background-position:-48px -120px}.icon-fire{background-position:-72px -120px}.icon-eye-open{background-position:-96px -120px}.icon-eye-close{background-position:-120px -120px}.icon-warning-sign{background-position:-144px -120px}.icon-plane{background-position:-168px -120px}.icon-calendar{background-position:-192px -120px}.icon-random{width:16px;background-position:-216px -120px}.icon-comment{background-position:-240px -120px}.icon-magnet{background-position:-264px -120px}.icon-chevron-up{background-position:-288px -120px}.icon-chevron-down{background-position:-313px -119px}.icon-retweet{background-position:-336px -120px}.icon-shopping-cart{background-position:-360px -120px}.icon-folder-close{background-position:-384px -120px}.icon-folder-open{width:16px;background-position:-408px -120px}.icon-resize-vertical{background-position:-432px -119px}.icon-resize-horizontal{background-position:-456px -118px}.icon-hdd{background-position:0 -144px}.icon-bullhorn{background-position:-24px -144px}.icon-bell{background-position:-48px -144px}.icon-certificate{background-position:-72px -144px}.icon-thumbs-up{background-position:-96px -144px}.icon-thumbs-down{background-position:-120px -144px}.icon-hand-right{background-position:-144px -144px}.icon-hand-left{background-position:-168px -144px}.icon-hand-up{background-position:-192px -144px}.icon-hand-down{background-position:-216px -144px}.icon-circle-arrow-right{background-position:-240px -144px}.icon-circle-arrow-left{background-position:-264px -144px}.icon-circle-arrow-up{background-position:-288px -144px}.icon-circle-arrow-down{background-position:-312px -144px}.icon-globe{background-position:-336px -144px}.icon-wrench{background-position:-360px -144px}.icon-tasks{background-position:-384px -144px}.icon-filter{background-position:-408px -144px}.icon-briefcase{background-position:-432px -144px}.icon-fullscreen{background-position:-456px -144px}.dropup,.dropdown{position:relative}.dropdown-toggle{*margin-bottom:-3px}.dropdown-toggle:active,.open .dropdown-toggle{outline:0}.caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.dropdown .caret{margin-top:8px;margin-left:2px}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.dropdown-menu li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap}.dropdown-menu li>a:hover,.dropdown-menu li>a:focus,.dropdown-submenu:hover>a{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu .active>a,.dropdown-menu .active>a:hover{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;outline:0;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu .disabled>a,.dropdown-menu .disabled>a:hover{color:#999}.dropdown-menu .disabled>a:hover{text-decoration:none;cursor:default;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open{*z-index:1000}.open>.dropdown-menu{display:block}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #000;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}.dropdown-submenu{position:relative}.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px}.dropdown-submenu:hover>.dropdown-menu{display:block}.dropup .dropdown-submenu>.dropdown-menu{top:auto;bottom:0;margin-top:0;margin-bottom:-2px;-webkit-border-radius:5px 5px 5px 0;-moz-border-radius:5px 5px 5px 0;border-radius:5px 5px 5px 0}.dropdown-submenu>a:after{display:block;float:right;width:0;height:0;margin-top:5px;margin-right:-10px;border-color:transparent;border-left-color:#ccc;border-style:solid;border-width:5px 0 5px 5px;content:" "}.dropdown-submenu:hover>a:after{border-left-color:#fff}.dropdown-submenu.pull-left{float:none}.dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.dropdown .dropdown-menu .nav-header{padding-right:20px;padding-left:20px}.typeahead{z-index:1051;margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-large{padding:24px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.well-small{padding:9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fade{opacity:0;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.collapse.in{height:auto}.close{float:right;font-size:20px;font-weight:bold;line-height:20px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.btn{display:inline-block;*display:inline;padding:4px 12px;margin-bottom:0;*margin-left:.3em;font-size:14px;line-height:20px;color:#333;text-align:center;text-shadow:0 1px 1px rgba(255,255,255,0.75);vertical-align:middle;cursor:pointer;background-color:#f5f5f5;*background-color:#e6e6e6;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;border:1px solid #bbb;*border:0;border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);border-bottom-color:#a2a2a2;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);*zoom:1;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn:hover,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#333;background-color:#e6e6e6;*background-color:#d9d9d9}.btn:active,.btn.active{background-color:#ccc \9}.btn:first-child{*margin-left:0}.btn:hover{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn.disabled,.btn[disabled]{cursor:default;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-large{padding:11px 19px;font-size:17.5px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.btn-large [class^="icon-"],.btn-large [class*=" icon-"]{margin-top:4px}.btn-small{padding:2px 10px;font-size:11.9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-small [class^="icon-"],.btn-small [class*=" icon-"]{margin-top:0}.btn-mini [class^="icon-"],.btn-mini [class*=" icon-"]{margin-top:-1px}.btn-mini{padding:0 6px;font-size:10.5px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255,255,255,0.75)}.btn{border-color:#c5c5c5;border-color:rgba(0,0,0,0.15) rgba(0,0,0,0.15) rgba(0,0,0,0.25)}.btn-primary{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#006dcc;*background-color:#04c;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0044cc',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-primary:hover,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#fff;background-color:#04c;*background-color:#003bb3}.btn-primary:active,.btn-primary.active{background-color:#039 \9}.btn-warning{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#faa732;*background-color:#f89406;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-warning:hover,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#fff;background-color:#f89406;*background-color:#df8505}.btn-warning:active,.btn-warning.active{background-color:#c67605 \9}.btn-danger{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#da4f49;*background-color:#bd362f;background-image:-moz-linear-gradient(top,#ee5f5b,#bd362f);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#bd362f));background-image:-webkit-linear-gradient(top,#ee5f5b,#bd362f);background-image:-o-linear-gradient(top,#ee5f5b,#bd362f);background-image:linear-gradient(to bottom,#ee5f5b,#bd362f);background-repeat:repeat-x;border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffbd362f',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-danger:hover,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#fff;background-color:#bd362f;*background-color:#a9302a}.btn-danger:active,.btn-danger.active{background-color:#942a25 \9}.btn-success{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#5bb75b;*background-color:#51a351;background-image:-moz-linear-gradient(top,#62c462,#51a351);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#51a351));background-image:-webkit-linear-gradient(top,#62c462,#51a351);background-image:-o-linear-gradient(top,#62c462,#51a351);background-image:linear-gradient(to bottom,#62c462,#51a351);background-repeat:repeat-x;border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff51a351',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-success:hover,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#fff;background-color:#51a351;*background-color:#499249}.btn-success:active,.btn-success.active{background-color:#408140 \9}.btn-info{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#49afcd;*background-color:#2f96b4;background-image:-moz-linear-gradient(top,#5bc0de,#2f96b4);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#2f96b4));background-image:-webkit-linear-gradient(top,#5bc0de,#2f96b4);background-image:-o-linear-gradient(top,#5bc0de,#2f96b4);background-image:linear-gradient(to bottom,#5bc0de,#2f96b4);background-repeat:repeat-x;border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff2f96b4',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-info:hover,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#fff;background-color:#2f96b4;*background-color:#2a85a0}.btn-info:active,.btn-info.active{background-color:#24748c \9}.btn-inverse{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#363636;*background-color:#222;background-image:-moz-linear-gradient(top,#444,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#444),to(#222));background-image:-webkit-linear-gradient(top,#444,#222);background-image:-o-linear-gradient(top,#444,#222);background-image:linear-gradient(to bottom,#444,#222);background-repeat:repeat-x;border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444',endColorstr='#ff222222',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-inverse:hover,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#fff;background-color:#222;*background-color:#151515}.btn-inverse:active,.btn-inverse.active{background-color:#080808 \9}button.btn,input[type="submit"].btn{*padding-top:3px;*padding-bottom:3px}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0}button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px}button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px}button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px}.btn-link,.btn-link:active,.btn-link[disabled]{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-link{color:#08c;cursor:pointer;border-color:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-link:hover{color:#005580;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover{color:#333;text-decoration:none}.btn-group{position:relative;display:inline-block;*display:inline;*margin-left:.3em;font-size:0;white-space:nowrap;vertical-align:middle;*zoom:1}.btn-group:first-child{*margin-left:0}.btn-group+.btn-group{margin-left:5px}.btn-toolbar{margin-top:10px;margin-bottom:10px;font-size:0}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group{margin-left:5px}.btn-group>.btn{position:relative;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group>.btn+.btn{margin-left:-1px}.btn-group>.btn,.btn-group>.dropdown-menu,.btn-group>.popover{font-size:14px}.btn-group>.btn-mini{font-size:10.5px}.btn-group>.btn-small{font-size:11.9px}.btn-group>.btn-large{font-size:17.5px}.btn-group>.btn:first-child{margin-left:0;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.btn-group>.btn.large:first-child{margin-left:0;-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{*padding-top:5px;padding-right:8px;*padding-bottom:5px;padding-left:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn-group>.btn-mini+.dropdown-toggle{*padding-top:2px;padding-right:5px;*padding-bottom:2px;padding-left:5px}.btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px}.btn-group>.btn-large+.dropdown-toggle{*padding-top:7px;padding-right:12px;*padding-bottom:7px;padding-left:12px}.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6}.btn-group.open .btn-primary.dropdown-toggle{background-color:#04c}.btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406}.btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f}.btn-group.open .btn-success.dropdown-toggle{background-color:#51a351}.btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4}.btn-group.open .btn-inverse.dropdown-toggle{background-color:#222}.btn .caret{margin-top:8px;margin-left:0}.btn-mini .caret,.btn-small .caret,.btn-large .caret{margin-top:6px}.btn-large .caret{border-top-width:5px;border-right-width:5px;border-left-width:5px}.dropup .btn-large .caret{border-bottom-width:5px}.btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#fff;border-bottom-color:#fff}.btn-group-vertical{display:inline-block;*display:inline;*zoom:1}.btn-group-vertical>.btn{display:block;float:none;max-width:100%;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group-vertical>.btn+.btn{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:first-child{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.btn-group-vertical>.btn:last-child{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.btn-group-vertical>.btn-large:first-child{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0}.btn-group-vertical>.btn-large:last-child{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.alert{padding:8px 35px 8px 14px;margin-bottom:20px;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.alert,.alert h4{color:#c09853}.alert h4{margin:0}.alert .close{position:relative;top:-2px;right:-21px;line-height:20px}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-success h4{color:#468847}.alert-danger,.alert-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.alert-danger h4,.alert-error h4{color:#b94a48}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-info h4{color:#3a87ad}.alert-block{padding-top:14px;padding-bottom:14px}.alert-block>p,.alert-block>ul{margin-bottom:0}.alert-block p+p{margin-top:5px}.nav{margin-bottom:20px;margin-left:0;list-style:none}.nav>li>a{display:block}.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li>a>img{max-width:none}.nav>.pull-right{float:right}.nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:20px;color:#999;text-shadow:0 1px 0 rgba(255,255,255,0.5);text-transform:uppercase}.nav li+.nav-header{margin-top:9px}.nav-list{padding-right:15px;padding-left:15px;margin-bottom:0}.nav-list>li>a,.nav-list .nav-header{margin-right:-15px;margin-left:-15px;text-shadow:0 1px 0 rgba(255,255,255,0.5)}.nav-list>li>a{padding:3px 15px}.nav-list>.active>a,.nav-list>.active>a:hover{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.2);background-color:#08c}.nav-list [class^="icon-"],.nav-list [class*=" icon-"]{margin-right:2px}.nav-list .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.nav-tabs,.nav-pills{*zoom:1}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;line-height:0;content:""}.nav-tabs:after,.nav-pills:after{clear:both}.nav-tabs>li,.nav-pills>li{float:left}.nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{margin-bottom:-1px}.nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:20px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>.active>a,.nav-tabs>.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nav-pills>.active>a,.nav-pills>.active>a:hover{color:#fff;background-color:#08c}.nav-stacked>li{float:none}.nav-stacked>li>a{margin-right:0}.nav-tabs.nav-stacked{border-bottom:0}.nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.nav-tabs.nav-stacked>li:first-child>a{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-topleft:4px}.nav-tabs.nav-stacked>li:last-child>a{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-moz-border-radius-bottomleft:4px}.nav-tabs.nav-stacked>li>a:hover{z-index:2;border-color:#ddd}.nav-pills.nav-stacked>li>a{margin-bottom:3px}.nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px}.nav-tabs .dropdown-menu{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.nav-pills .dropdown-menu{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.nav .dropdown-toggle .caret{margin-top:6px;border-top-color:#08c;border-bottom-color:#08c}.nav .dropdown-toggle:hover .caret{border-top-color:#005580;border-bottom-color:#005580}.nav-tabs .dropdown-toggle .caret{margin-top:8px}.nav .active .dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.nav-tabs .active .dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.nav>.dropdown.active>a:hover{cursor:pointer}.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover{color:#fff;background-color:#999;border-color:#999}.nav li.dropdown.open .caret,.nav li.dropdown.open.active .caret,.nav li.dropdown.open a:hover .caret{border-top-color:#fff;border-bottom-color:#fff;opacity:1;filter:alpha(opacity=100)}.tabs-stacked .open>a:hover{border-color:#999}.tabbable{*zoom:1}.tabbable:before,.tabbable:after{display:table;line-height:0;content:""}.tabbable:after{clear:both}.tab-content{overflow:auto}.tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.tabs-below>.nav-tabs{border-top:1px solid #ddd}.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.tabs-below>.nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.tabs-below>.nav-tabs>li>a:hover{border-top-color:#ddd;border-bottom-color:transparent}.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover{border-color:transparent #ddd #ddd #ddd}.tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>li{float:none}.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px}.tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd}.tabs-left>.nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.tabs-left>.nav-tabs>li>a:hover{border-color:#eee #ddd #eee #eee}.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff}.tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd}.tabs-right>.nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.tabs-right>.nav-tabs>li>a:hover{border-color:#eee #eee #eee #ddd}.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}.nav>.disabled>a{color:#999}.nav>.disabled>a:hover{text-decoration:none;cursor:default;background-color:transparent}.navbar{*position:relative;*z-index:2;margin-bottom:20px;overflow:visible}.navbar-inner{min-height:40px;padding-right:20px;padding-left:20px;background-color:#fafafa;background-image:-moz-linear-gradient(top,#fff,#f2f2f2);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#f2f2f2));background-image:-webkit-linear-gradient(top,#fff,#f2f2f2);background-image:-o-linear-gradient(top,#fff,#f2f2f2);background-image:linear-gradient(to bottom,#fff,#f2f2f2);background-repeat:repeat-x;border:1px solid #d4d4d4;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff2f2f2',GradientType=0);*zoom:1;-webkit-box-shadow:0 1px 4px rgba(0,0,0,0.065);-moz-box-shadow:0 1px 4px rgba(0,0,0,0.065);box-shadow:0 1px 4px rgba(0,0,0,0.065)}.navbar-inner:before,.navbar-inner:after{display:table;line-height:0;content:""}.navbar-inner:after{clear:both}.navbar .container{width:auto}.nav-collapse.collapse{height:auto;overflow:visible}.navbar .brand{display:block;float:left;padding:10px 20px 10px;margin-left:-20px;font-size:20px;font-weight:200;color:#777;text-shadow:0 1px 0 #fff}.navbar .brand:hover{text-decoration:none}.navbar-text{margin-bottom:0;line-height:40px;color:#777}.navbar-link{color:#777}.navbar-link:hover{color:#333}.navbar .divider-vertical{height:40px;margin:0 9px;border-right:1px solid #fff;border-left:1px solid #f2f2f2}.navbar .btn,.navbar .btn-group{margin-top:5px}.navbar .btn-group .btn,.navbar .input-prepend .btn,.navbar .input-append .btn{margin-top:0}.navbar-form{margin-bottom:0;*zoom:1}.navbar-form:before,.navbar-form:after{display:table;line-height:0;content:""}.navbar-form:after{clear:both}.navbar-form input,.navbar-form select,.navbar-form .radio,.navbar-form .checkbox{margin-top:5px}.navbar-form input,.navbar-form select,.navbar-form .btn{display:inline-block;margin-bottom:0}.navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px}.navbar-form .input-append,.navbar-form .input-prepend{margin-top:5px;white-space:nowrap}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0}.navbar-search{position:relative;float:left;margin-top:5px;margin-bottom:0}.navbar-search .search-query{padding:4px 14px;margin-bottom:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.navbar-static-top{position:static;margin-bottom:0}.navbar-static-top .navbar-inner{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{border-width:0 0 1px}.navbar-fixed-bottom .navbar-inner{border-width:1px 0 0}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding-right:0;padding-left:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.navbar-fixed-top{top:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{-webkit-box-shadow:0 1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 10px rgba(0,0,0,0.1);box-shadow:0 1px 10px rgba(0,0,0,0.1)}.navbar-fixed-bottom{bottom:0}.navbar-fixed-bottom .navbar-inner{-webkit-box-shadow:0 -1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 -1px 10px rgba(0,0,0,0.1);box-shadow:0 -1px 10px rgba(0,0,0,0.1)}.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0}.navbar .nav.pull-right{float:right;margin-right:0}.navbar .nav>li{float:left}.navbar .nav>li>a{float:none;padding:10px 15px 10px;color:#777;text-decoration:none;text-shadow:0 1px 0 #fff}.navbar .nav .dropdown-toggle .caret{margin-top:8px}.navbar .nav>li>a:focus,.navbar .nav>li>a:hover{color:#333;text-decoration:none;background-color:transparent}.navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{color:#555;text-decoration:none;background-color:#e5e5e5;-webkit-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);-moz-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);box-shadow:inset 0 3px 8px rgba(0,0,0,0.125)}.navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-right:5px;margin-left:5px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#ededed;*background-color:#e5e5e5;background-image:-moz-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f2f2f2),to(#e5e5e5));background-image:-webkit-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-o-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:linear-gradient(to bottom,#f2f2f2,#e5e5e5);background-repeat:repeat-x;border-color:#e5e5e5 #e5e5e5 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2',endColorstr='#ffe5e5e5',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075)}.navbar .btn-navbar:hover,.navbar .btn-navbar:active,.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar[disabled]{color:#fff;background-color:#e5e5e5;*background-color:#d9d9d9}.navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color:#ccc \9}.navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,0.25);-moz-box-shadow:0 1px 0 rgba(0,0,0,0.25);box-shadow:0 1px 0 rgba(0,0,0,0.25)}.btn-navbar .icon-bar+.icon-bar{margin-top:3px}.navbar .nav>li>.dropdown-menu:before{position:absolute;top:-7px;left:9px;display:inline-block;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-left:7px solid transparent;border-bottom-color:rgba(0,0,0,0.2);content:''}.navbar .nav>li>.dropdown-menu:after{position:absolute;top:-6px;left:10px;display:inline-block;border-right:6px solid transparent;border-bottom:6px solid #fff;border-left:6px solid transparent;content:''}.navbar-fixed-bottom .nav>li>.dropdown-menu:before{top:auto;bottom:-7px;border-top:7px solid #ccc;border-bottom:0;border-top-color:rgba(0,0,0,0.2)}.navbar-fixed-bottom .nav>li>.dropdown-menu:after{top:auto;bottom:-6px;border-top:6px solid #fff;border-bottom:0}.navbar .nav li.dropdown>a:hover .caret{border-top-color:#555;border-bottom-color:#555}.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{color:#555;background-color:#e5e5e5}.navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#777;border-bottom-color:#777}.navbar .nav li.dropdown.open>.dropdown-toggle .caret,.navbar .nav li.dropdown.active>.dropdown-toggle .caret,.navbar .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.navbar .pull-right>li>.dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar .pull-right>li>.dropdown-menu:before,.navbar .nav>li>.dropdown-menu.pull-right:before{right:12px;left:auto}.navbar .pull-right>li>.dropdown-menu:after,.navbar .nav>li>.dropdown-menu.pull-right:after{right:13px;left:auto}.navbar .pull-right>li>.dropdown-menu .dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right .dropdown-menu{right:100%;left:auto;margin-right:-1px;margin-left:0;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.navbar-inverse .navbar-inner{background-color:#1b1b1b;background-image:-moz-linear-gradient(top,#222,#111);background-image:-webkit-gradient(linear,0 0,0 100%,from(#222),to(#111));background-image:-webkit-linear-gradient(top,#222,#111);background-image:-o-linear-gradient(top,#222,#111);background-image:linear-gradient(to bottom,#222,#111);background-repeat:repeat-x;border-color:#252525;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222',endColorstr='#ff111111',GradientType=0)}.navbar-inverse .brand,.navbar-inverse .nav>li>a{color:#999;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-inverse .brand:hover,.navbar-inverse .nav>li>a:hover{color:#fff}.navbar-inverse .brand{color:#999}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .nav .active>a,.navbar-inverse .nav .active>a:hover,.navbar-inverse .nav .active>a:focus{color:#fff;background-color:#111}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .divider-vertical{border-right-color:#222;border-left-color:#111}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle{color:#fff;background-color:#111}.navbar-inverse .nav li.dropdown>a:hover .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-search .search-query{color:#fff;background-color:#515151;border-color:#111;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}.navbar-inverse .navbar-search .search-query:-moz-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:focus,.navbar-inverse .navbar-search .search-query.focused{padding:5px 15px;color:#333;text-shadow:0 1px 0 #fff;background-color:#fff;border:0;outline:0;-webkit-box-shadow:0 0 3px rgba(0,0,0,0.15);-moz-box-shadow:0 0 3px rgba(0,0,0,0.15);box-shadow:0 0 3px rgba(0,0,0,0.15)}.navbar-inverse .btn-navbar{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e0e0e;*background-color:#040404;background-image:-moz-linear-gradient(top,#151515,#040404);background-image:-webkit-gradient(linear,0 0,0 100%,from(#151515),to(#040404));background-image:-webkit-linear-gradient(top,#151515,#040404);background-image:-o-linear-gradient(top,#151515,#040404);background-image:linear-gradient(to bottom,#151515,#040404);background-repeat:repeat-x;border-color:#040404 #040404 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515',endColorstr='#ff040404',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .btn-navbar:hover,.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active,.navbar-inverse .btn-navbar.disabled,.navbar-inverse .btn-navbar[disabled]{color:#fff;background-color:#040404;*background-color:#000}.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active{background-color:#000 \9}.breadcrumb{padding:8px 15px;margin:0 0 20px;list-style:none;background-color:#f5f5f5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.breadcrumb>li{display:inline-block;*display:inline;text-shadow:0 1px 0 #fff;*zoom:1}.breadcrumb>li>.divider{padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.pagination{margin:20px 0}.pagination ul{display:inline-block;*display:inline;margin-bottom:0;margin-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*zoom:1;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.pagination ul>li{display:inline}.pagination ul>li>a,.pagination ul>li>span{float:left;padding:4px 12px;line-height:20px;text-decoration:none;background-color:#fff;border:1px solid #ddd;border-left-width:0}.pagination ul>li>a:hover,.pagination ul>.active>a,.pagination ul>.active>span{background-color:#f5f5f5}.pagination ul>.active>a,.pagination ul>.active>span{color:#999;cursor:default}.pagination ul>.disabled>span,.pagination ul>.disabled>a,.pagination ul>.disabled>a:hover{color:#999;cursor:default;background-color:transparent}.pagination ul>li:first-child>a,.pagination ul>li:first-child>span{border-left-width:1px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.pagination ul>li:last-child>a,.pagination ul>li:last-child>span{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.pagination-centered{text-align:center}.pagination-right{text-align:right}.pagination-large ul>li>a,.pagination-large ul>li>span{padding:11px 19px;font-size:17.5px}.pagination-large ul>li:first-child>a,.pagination-large ul>li:first-child>span{-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.pagination-large ul>li:last-child>a,.pagination-large ul>li:last-child>span{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.pagination-mini ul>li:first-child>a,.pagination-small ul>li:first-child>a,.pagination-mini ul>li:first-child>span,.pagination-small ul>li:first-child>span{-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-moz-border-radius-bottomleft:3px;-moz-border-radius-topleft:3px}.pagination-mini ul>li:last-child>a,.pagination-small ul>li:last-child>a,.pagination-mini ul>li:last-child>span,.pagination-small ul>li:last-child>span{-webkit-border-top-right-radius:3px;border-top-right-radius:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px;-moz-border-radius-topright:3px;-moz-border-radius-bottomright:3px}.pagination-small ul>li>a,.pagination-small ul>li>span{padding:2px 10px;font-size:11.9px}.pagination-mini ul>li>a,.pagination-mini ul>li>span{padding:0 6px;font-size:10.5px}.pager{margin:20px 0;text-align:center;list-style:none;*zoom:1}.pager:before,.pager:after{display:table;line-height:0;content:""}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.pager li>a:hover{text-decoration:none;background-color:#f5f5f5}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>span{color:#999;cursor:default;background-color:#fff}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop,.modal-backdrop.fade.in{opacity:.8;filter:alpha(opacity=80)}.modal{position:fixed;top:10%;left:50%;z-index:1050;width:560px;margin-left:-280px;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;outline:0;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box}.modal.fade{top:-25%;-webkit-transition:opacity .3s linear,top .3s ease-out;-moz-transition:opacity .3s linear,top .3s ease-out;-o-transition:opacity .3s linear,top .3s ease-out;transition:opacity .3s linear,top .3s ease-out}.modal.fade.in{top:10%}.modal-header{padding:9px 15px;border-bottom:1px solid #eee}.modal-header .close{margin-top:2px}.modal-header h3{margin:0;line-height:30px}.modal-body{position:relative;max-height:400px;padding:15px;overflow-y:auto}.modal-form{margin-bottom:0}.modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;*zoom:1;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.modal-footer:before,.modal-footer:after{display:table;line-height:0;content:""}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.tooltip{position:absolute;z-index:1030;display:block;padding:5px;font-size:11px;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.8;filter:alpha(opacity=80)}.tooltip.top{margin-top:-3px}.tooltip.right{margin-left:3px}.tooltip.bottom{margin-top:3px}.tooltip.left{margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;width:236px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{border-width:10px;content:""}.popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);border-bottom-width:0}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,0.25);border-left-width:0}.popover.right .arrow:after{bottom:-10px;left:1px;border-right-color:#fff;border-left-width:0}.popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);border-top-width:0}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-left-color:#999;border-left-color:rgba(0,0,0,0.25);border-right-width:0}.popover.left .arrow:after{right:1px;bottom:-10px;border-left-color:#fff;border-right-width:0}.thumbnails{margin-left:-20px;list-style:none;*zoom:1}.thumbnails:before,.thumbnails:after{display:table;line-height:0;content:""}.thumbnails:after{clear:both}.row-fluid .thumbnails{margin-left:0}.thumbnails>li{float:left;margin-bottom:20px;margin-left:20px}.thumbnail{display:block;padding:4px;line-height:20px;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.055);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.055);box-shadow:0 1px 3px rgba(0,0,0,0.055);-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}a.thumbnail:hover{border-color:#08c;-webkit-box-shadow:0 1px 4px rgba(0,105,214,0.25);-moz-box-shadow:0 1px 4px rgba(0,105,214,0.25);box-shadow:0 1px 4px rgba(0,105,214,0.25)}.thumbnail>img{display:block;max-width:100%;margin-right:auto;margin-left:auto}.thumbnail .caption{padding:9px;color:#555}.media,.media-body{overflow:hidden;*overflow:visible;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media .pull-left{margin-right:10px}.media .pull-right{margin-left:10px}.media-list{margin-left:0;list-style:none}.label,.badge{display:inline-block;padding:2px 4px;font-size:11.844px;font-weight:bold;line-height:14px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);white-space:nowrap;vertical-align:baseline;background-color:#999}.label{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.badge{padding-right:9px;padding-left:9px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px}.label:empty,.badge:empty{display:none}a.label:hover,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.label-important,.badge-important{background-color:#b94a48}.label-important[href],.badge-important[href]{background-color:#953b39}.label-warning,.badge-warning{background-color:#f89406}.label-warning[href],.badge-warning[href]{background-color:#c67605}.label-success,.badge-success{background-color:#468847}.label-success[href],.badge-success[href]{background-color:#356635}.label-info,.badge-info{background-color:#3a87ad}.label-info[href],.badge-info[href]{background-color:#2d6987}.label-inverse,.badge-inverse{background-color:#333}.label-inverse[href],.badge-inverse[href]{background-color:#1a1a1a}.btn .label,.btn .badge{position:relative;top:-1px}.btn-mini .label,.btn-mini .badge{top:0}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-ms-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f7f7f7;background-image:-moz-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f5f5f5),to(#f9f9f9));background-image:-webkit-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-o-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:linear-gradient(to bottom,#f5f5f5,#f9f9f9);background-repeat:repeat-x;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#fff9f9f9',GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress .bar{float:left;width:0;height:100%;font-size:12px;color:#fff;text-align:center;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top,#149bdf,#0480be);background-image:-webkit-gradient(linear,0 0,0 100%,from(#149bdf),to(#0480be));background-image:-webkit-linear-gradient(top,#149bdf,#0480be);background-image:-o-linear-gradient(top,#149bdf,#0480be);background-image:linear-gradient(to bottom,#149bdf,#0480be);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf',endColorstr='#ff0480be',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width .6s ease;-moz-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress .bar+.bar{-webkit-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15)}.progress-striped .bar{background-color:#149bdf;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px}.progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-danger .bar,.progress .bar-danger{background-color:#dd514c;background-image:-moz-linear-gradient(top,#ee5f5b,#c43c35);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#c43c35));background-image:-webkit-linear-gradient(top,#ee5f5b,#c43c35);background-image:-o-linear-gradient(top,#ee5f5b,#c43c35);background-image:linear-gradient(to bottom,#ee5f5b,#c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffc43c35',GradientType=0)}.progress-danger.progress-striped .bar,.progress-striped .bar-danger{background-color:#ee5f5b;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-success .bar,.progress .bar-success{background-color:#5eb95e;background-image:-moz-linear-gradient(top,#62c462,#57a957);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#57a957));background-image:-webkit-linear-gradient(top,#62c462,#57a957);background-image:-o-linear-gradient(top,#62c462,#57a957);background-image:linear-gradient(to bottom,#62c462,#57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff57a957',GradientType=0)}.progress-success.progress-striped .bar,.progress-striped .bar-success{background-color:#62c462;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-info .bar,.progress .bar-info{background-color:#4bb1cf;background-image:-moz-linear-gradient(top,#5bc0de,#339bb9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#339bb9));background-image:-webkit-linear-gradient(top,#5bc0de,#339bb9);background-image:-o-linear-gradient(top,#5bc0de,#339bb9);background-image:linear-gradient(to bottom,#5bc0de,#339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff339bb9',GradientType=0)}.progress-info.progress-striped .bar,.progress-striped .bar-info{background-color:#5bc0de;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-warning .bar,.progress .bar-warning{background-color:#faa732;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0)}.progress-warning.progress-striped .bar,.progress-striped .bar-warning{background-color:#fbb450;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.accordion{margin-bottom:20px}.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.accordion-heading{border-bottom:0}.accordion-heading .accordion-toggle{display:block;padding:8px 15px}.accordion-toggle{cursor:pointer}.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5}.carousel{position:relative;margin-bottom:20px;line-height:1}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-moz-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img{display:block;line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#fff;text-align:center;background:#222;border:3px solid #fff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:.5;filter:alpha(opacity=50)}.carousel-control.right{right:15px;left:auto}.carousel-control:hover{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-caption{position:absolute;right:0;bottom:0;left:0;padding:15px;background:#333;background:rgba(0,0,0,0.75)}.carousel-caption h4,.carousel-caption p{line-height:20px;color:#fff}.carousel-caption h4{margin:0 0 5px}.carousel-caption p{margin-bottom:0}.hero-unit{padding:60px;margin-bottom:30px;font-size:18px;font-weight:200;line-height:30px;color:inherit;background-color:#eee;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;color:inherit}.hero-unit li{line-height:30px}.pull-right{float:right}.pull-left{float:left}.hide{display:none}.show{display:block}.invisible{visibility:hidden}.affix{position:fixed}
     <tr>
      <td class="{lines_level}">{icon}{name}</td>
      <td class="{lines_level} big">{lines_bar}</td>
      <td class="{lines_level} small"><div align="right">{lines_executed_percent}</div></td>
      <td class="{lines_level} small"><div align="right">{lines_number}</div></td>
      <td class="{methods_level} big">{methods_bar}</td>
      <td class="{methods_level} small"><div align="right">{methods_tested_percent}</div></td>
      <td class="{methods_level} small"><div align="right">{methods_number}</div></td>
      <td class="{classes_level} big">{classes_bar}</td>
      <td class="{classes_level} small"><div align="right">{classes_tested_percent}</div></td>
      <td class="{classes_level} small"><div align="right">{classes_number}</div></td>
     </tr>

     <tr>
      <td class="{classes_level}">{name}</td>
      <td class="{classes_level} big">{classes_bar}</td>
      <td class="{classes_level} small"><div align="right">{classes_tested_percent}</div></td>
      <td class="{classes_level} small"><div align="right">{classes_number}</div></td>
      <td class="{methods_level} big">{methods_bar}</td>
      <td class="{methods_level} small"><div align="right">{methods_tested_percent}</div></td>
      <td class="{methods_level} small"><div align="right">{methods_number}</div></td>
      <td class="{methods_level} small">{crap}</td>
      <td class="{lines_level} big">{lines_bar}</td>
      <td class="{lines_level} small"><div align="right">{lines_executed_percent}</div></td>
      <td class="{lines_level} small"><div align="right">{lines_number}</div></td>
     </tr>

<!DOCTYPE html>
<html lang="en">
 <head>
  <meta charset="{charset}">
  <title>Dashboard for {full_path}</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link href="css/bootstrap.min.css" rel="stylesheet">
  <link href="css/bootstrap-responsive.min.css" rel="stylesheet">
  <link href="css/style.css" rel="stylesheet">
  <!--[if lt IE 9]>
  <script src="js/html5shiv.js"></script>
  <![endif]-->
 </head>
 <body>
  <header>
   <div class="container">
    <div class="row">
     <div class="span12">
      <ul class="breadcrumb">
{breadcrumbs}
      </ul>
     </div>
    </div>
   </div>
  </header>
  <div class="container">
   <div class="row">
    <div class="span6">
     <h2>Class Coverage Distribution</h2>
     <div id="classCoverageDistribution"></div>
    </div>
    <div class="span6">
     <h2>Class Complexity</h2>
     <div id="classComplexity"></div>
    </div>
   </div>
   <div class="row">
    <div class="span6">
     <h2>Top Project Risks</h2>
     <ul>
{top_project_risks}
     </ul>
    </div>
    <div class="span6">
     <h2>Least Tested Methods</h2>
     <ul>
{least_tested_methods}
     </ul>
    </div>
   </div>
   <footer>
    <p>
     <small>Generated by <a href="http://github.com/sebastianbergmann/php-code-coverage" target="_top">PHP_CodeCoverage {version}</a> using <a href="http://www.php.net/" target="_top">PHP {php_version}</a>{generator} at {date}.</small>
    </p>
   </footer>
  </div>
  <script src="js/jquery.min.js" type="text/javascript"></script>
  <script src="js/bootstrap.min.js" type="text/javascript"></script>
  <script src="js/highcharts.js" type="text/javascript"></script>
  <script type="text/javascript">
$(document).ready(function() {
 var classCoverageDistribution = new Highcharts.Chart({
  chart: {
   renderTo: 'classCoverageDistribution',
   type: 'column'
  },
  title: {text: ''},
  legend: {enabled: false},
  credits: {enabled: false},
  tooltip: {enabled: false},
  xAxis: {
   labels: {style: {fontSize: '8px'}},
   categories: [
    '0%','0-10%','10-20%','20-30%','30-40%','40-50%','50-60%','60-70%','70-80%','80-90%','90-100%','100%'
   ],
   min: 0
  },
  yAxis: {
   title: '',
   labels: {style: {fontSize: '8px'}},
   min: 0
  },
  series: [{
   data: {ccd_values}
  }],
 });

 var classComplexity = new Highcharts.Chart({
  chart: {
   renderTo: 'classComplexity',
   type: 'scatter'
  },
  title: {text: ''},
  legend: {enabled: false},
  credits: {enabled: false},
  xAxis: {
   title: {text: 'Code Coverage (in percent)'},
   labels: {enabled: true},
   min: 0
  },
  yAxis: {
   title: {text: 'Cyclomatic Complexity'},
   labels: {enabled: true},
   min: 0
  },
  tooltip: {
   formatter: function() {
    return this.point.config[2];
   }
  },
  series: [{
   data: {cc_values},
   marker: {
    symbol: 'diamond'
   }
  }],
 });
});
  </script>
 </body>
</html>
<!DOCTYPE html>
<html lang="en">
 <head>
  <meta charset="{charset}">
  <title>Code Coverage for {full_path}</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link href="css/bootstrap.min.css" rel="stylesheet">
  <link href="css/bootstrap-responsive.min.css" rel="stylesheet">
  <link href="css/style.css" rel="stylesheet">
  <!--[if lt IE 9]>
  <script src="js/html5shiv.js"></script>
  <![endif]-->
 </head>
 <body>
  <header>
   <div class="container">
    <div class="row">
     <div class="span12">
      <ul class="breadcrumb">
{breadcrumbs}
      </ul>
     </div>
    </div>
   </div>
  </header>
  <div class="container">
   <table class="table table-bordered">
    <thead>
     <tr>
      <td>&nbsp;</td>
      <td colspan="9"><div align="center"><strong>Code Coverage</strong></div></td>
     </tr>
     <tr>
      <td>&nbsp;</td>
      <td colspan="3"><div align="center"><strong>Lines</strong></div></td>
      <td colspan="3"><div align="center"><strong>Functions and Methods</strong></div></td>
      <td colspan="3"><div align="center"><strong>Classes and Traits</strong></div></td>
     </tr>
    </thead>
    <tbody>
{items}
    </tbody>
   </table>
   <footer>
    <h4>Legend</h4>
    <p>
     <span class="danger"><strong>Low</strong>: 0% to {low_upper_bound}%</span>
     <span class="warning"><strong>Medium</strong>: {low_upper_bound}% to {high_lower_bound}%</span>
     <span class="success"><strong>High</strong>: {high_lower_bound}% to 100%</span>
    </p>
    <p>
     <small>Generated by <a href="http://github.com/sebastianbergmann/php-code-coverage" target="_top">PHP_CodeCoverage {version}</a> using <a href="http://www.php.net/" target="_top">PHP {php_version}</a>{generator} at {date}.</small>
    </p>
   </footer>
  </div>
  <script src="js/jquery.min.js" type="text/javascript"></script>
  <script src="js/bootstrap.min.js" type="text/javascript"></script>
 </body>
</html>
<!DOCTYPE html>
<html lang="en">
 <head>
  <meta charset="{charset}">
  <title>Code Coverage for {full_path}</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link href="css/bootstrap.min.css" rel="stylesheet">
  <link href="css/bootstrap-responsive.min.css" rel="stylesheet">
  <link href="css/style.css" rel="stylesheet">
  <!--[if lt IE 9]>
  <script src="js/html5shiv.js"></script>
  <![endif]-->
 </head>
 <body>
  <header>
   <div class="container">
    <div class="row">
     <div class="span12">
      <ul class="breadcrumb">
{breadcrumbs}
      </ul>
     </div>
    </div>
   </div>
  </header>
  <div class="container">
   <table class="table table-bordered">
    <thead>
     <tr>
      <td>&nbsp;</td>
      <td colspan="10"><div align="center"><strong>Code Coverage</strong></div></td>
     </tr>
     <tr>
      <td>&nbsp;</td>
      <td colspan="3"><div align="center"><strong>Classes and Traits</strong></div></td>
      <td colspan="4"><div align="center"><strong>Functions and Methods</strong></div></td>
      <td colspan="3"><div align="center"><strong>Lines</strong></div></td>
     </tr>
    </thead>
    <tbody>
{items}
    </tbody>
   </table>
   <table class="table table-borderless table-condensed">
    <tbody>
{lines}
    </tbody>
   </table>
   <footer>
    <h4>Legend</h4>
    <p>
     <span class="success"><strong>Executed</strong></span>
     <span class="danger"><strong>Not Executed</strong></span>
     <span class="warning"><strong>Dead Code</strong></span>
    </p>
    <p>
     <small>Generated by <a href="http://github.com/sebastianbergmann/php-code-coverage" target="_top">PHP_CodeCoverage {version}</a> using <a href="http://www.php.net/" target="_top">PHP {php_version}</a>{generator} at {date}.</small>
    </p>
   </footer>
  </div>
  <script src="js/jquery.min.js" type="text/javascript"></script>
  <script src="js/bootstrap.min.js" type="text/javascript"></script>
  <script type="text/javascript">$('.popin').popover({trigger: 'hover'});</script>
 </body>
</html>
       <div class="progress progress-{level}" style="width: 100px;">
        <div class="bar" style="width: {percent}%;"></div>
       </div>
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.1.0
 */

/**
 * Renders a PHP_CodeCoverage_Report_Node_Directory node.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.1.0
 */
class PHP_CodeCoverage_Report_HTML_Renderer_Directory extends PHP_CodeCoverage_Report_HTML_Renderer
{
    /**
     * @param PHP_CodeCoverage_Report_Node_Directory $node
     * @param string                                 $file
     */
    public function render(PHP_CodeCoverage_Report_Node_Directory $node, $file)
    {
        $template = new Text_Template($this->templatePath . 'directory.html');

        $this->setCommonTemplateVariables($template, $node);

        $items = $this->renderItem($node, TRUE);

        foreach ($node->getDirectories() as $item) {
            $items .= $this->renderItem($item);
        }

        foreach ($node->getFiles() as $item) {
            $items .= $this->renderItem($item);
        }

        $template->setVar(
          array(
            'id'    => $node->getId(),
            'items' => $items
          )
        );

        $template->renderTo($file);
    }

    /**
     * @param  PHP_CodeCoverage_Report_Node $item
     * @param  boolean                      $total
     * @return string
     */
    protected function renderItem(PHP_CodeCoverage_Report_Node $item, $total = FALSE)
    {
        $data = array(
          'numClasses'                   => $item->getNumClassesAndTraits(),
          'numTestedClasses'             => $item->getNumTestedClassesAndTraits(),
          'numMethods'                   => $item->getNumMethods(),
          'numTestedMethods'             => $item->getNumTestedMethods(),
          'linesExecutedPercent'         => $item->getLineExecutedPercent(FALSE),
          'linesExecutedPercentAsString' => $item->getLineExecutedPercent(),
          'numExecutedLines'             => $item->getNumExecutedLines(),
          'numExecutableLines'           => $item->getNumExecutableLines(),
          'testedMethodsPercent'         => $item->getTestedMethodsPercent(FALSE),
          'testedMethodsPercentAsString' => $item->getTestedMethodsPercent(),
          'testedClassesPercent'         => $item->getTestedClassesAndTraitsPercent(FALSE),
          'testedClassesPercentAsString' => $item->getTestedClassesAndTraitsPercent()
        );

        if ($total) {
            $data['name'] = 'Total';
        } else {
            $data['name'] = sprintf(
              '<a href="%s.html">%s</a>',
              $item->getId(),
              $item->getName()
            );

            if ($item instanceof PHP_CodeCoverage_Report_Node_Directory) {
                $data['icon'] = '<i class="icon-folder-open"></i> ';
            } else {
                $data['icon'] = '<i class="icon-file"></i> ';
            }
        }

        return $this->renderItemTemplate(
          new Text_Template($this->templatePath . 'directory_item.html'),
          $data
        );
    }
}
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.1.0
 */

/**
 * Base class for PHP_CodeCoverage_Report_Node renderers.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.1.0
 */
abstract class PHP_CodeCoverage_Report_HTML_Renderer
{
    /**
     * @var string
     */
    protected $templatePath;

    /**
     * @var string
     */
    protected $charset;

    /**
     * @var string
     */
    protected $generator;

    /**
     * @var string
     */
    protected $date;

    /**
     * @var integer
     */
    protected $lowUpperBound;

    /**
     * @var integer
     */
    protected $highLowerBound;

    /**
     * Constructor.
     *
     * @param string  $templatePath
     * @param string  $charset
     * @param string  $generator
     * @param string  $date
     * @param integer $lowUpperBound
     * @param integer $highLowerBound
     */
    public function __construct($templatePath, $charset, $generator, $date, $lowUpperBound, $highLowerBound)
    {
        $this->templatePath   = $templatePath;
        $this->charset        = $charset;
        $this->generator      = $generator;
        $this->date           = $date;
        $this->lowUpperBound  = $lowUpperBound;
        $this->highLowerBound = $highLowerBound;
    }

    /**
     * @param  Text_Template $template
     * @param  array         $data
     * @return string
     */
    protected function renderItemTemplate(Text_Template $template, array $data)
    {
        $numSeperator = '&nbsp;/&nbsp;';
        $classesBar    = '&nbsp;';
        $classesLevel  = 'None';
        $classesNumber = '&nbsp;';

        if (isset($data['numClasses']) && $data['numClasses'] > 0) {
            $classesLevel = $this->getColorLevel($data['testedClassesPercent']);

            $classesNumber = $data['numTestedClasses'] . $numSeperator .
                             $data['numClasses'];

            $classesBar = $this->getCoverageBar(
              $data['testedClassesPercent']
            );
        }

        $methodsBar    = '&nbsp;';
        $methodsLevel  = 'None';
        $methodsNumber = '&nbsp;';

        if ($data['numMethods'] > 0) {
            $methodsLevel = $this->getColorLevel($data['testedMethodsPercent']);

            $methodsNumber = $data['numTestedMethods'] . $numSeperator .
                             $data['numMethods'];

            $methodsBar = $this->getCoverageBar(
              $data['testedMethodsPercent']
            );
        }

        $linesBar    = '&nbsp;';
        $linesLevel  = 'None';
        $linesNumber = '&nbsp;';

        if ($data['numExecutableLines'] > 0) {
            $linesLevel = $this->getColorLevel($data['linesExecutedPercent']);

            $linesNumber = $data['numExecutedLines'] . $numSeperator .
                           $data['numExecutableLines'];

            $linesBar = $this->getCoverageBar(
              $data['linesExecutedPercent']
            );
        }

        $template->setVar(
          array(
            'icon' => isset($data['icon']) ? $data['icon'] : '',
            'crap' => isset($data['crap']) ? $data['crap'] : '',
            'name' => $data['name'],
            'lines_bar' => $linesBar,
            'lines_executed_percent' => $data['linesExecutedPercentAsString'],
            'lines_level' => $linesLevel,
            'lines_number' => $linesNumber,
            'methods_bar' => $methodsBar,
            'methods_tested_percent' => $data['testedMethodsPercentAsString'],
            'methods_level' => $methodsLevel,
            'methods_number' => $methodsNumber,
            'classes_bar' => $classesBar,
            'classes_tested_percent' => isset($data['testedClassesPercentAsString']) ? $data['testedClassesPercentAsString'] : '',
            'classes_level' => $classesLevel,
            'classes_number' => $classesNumber
          )
        );

        return $template->render();
    }

    /**
     * @param Text_Template                $template
     * @param PHP_CodeCoverage_Report_Node $node
     */
    protected function setCommonTemplateVariables(Text_Template $template, PHP_CodeCoverage_Report_Node $node)
    {
        $template->setVar(
          array(
            'id'               => $node->getId(),
            'full_path'        => $node->getPath(),
            'breadcrumbs'      => $this->getBreadcrumbs($node),
            'charset'          => $this->charset,
            'date'             => $this->date,
            'version'          => PHP_CodeCoverage_Version::id(),
            'php_version'      => PHP_VERSION,
            'generator'        => $this->generator,
            'low_upper_bound'  => $this->lowUpperBound,
            'high_lower_bound' => $this->highLowerBound
          )
        );
    }

    protected function getBreadcrumbs(PHP_CodeCoverage_Report_Node $node)
    {
        $breadcrumbs = '';

        $path = $node->getPathAsArray();

        foreach ($path as $step) {
            if ($step !== $node) {
                $breadcrumbs .= $this->getInactiveBreadcrumb($step);
            } else {
                $breadcrumbs .= $this->getActiveBreadcrumb(
                  $step,
                  $node instanceof PHP_CodeCoverage_Report_Node_Directory
                );
            }
        }

        return $breadcrumbs;
    }

    protected function getActiveBreadcrumb(PHP_CodeCoverage_Report_Node $node, $isDirectory)
    {
        $buffer = sprintf(
          '        <li class="active">%s</li>' . "\n",
          $node->getName()
        );

        if ($isDirectory) {
            $buffer .= sprintf(
              '        <li>(<a href="%s.dashboard.html">Dashboard</a>)</li>' . "\n",
              $node->getId()
            );
        }

        return $buffer;
    }

    protected function getInactiveBreadcrumb(PHP_CodeCoverage_Report_Node $node)
    {
        return sprintf(
          '        <li><a href="%s.html">%s</a> <span class="divider">/</span></li>' . "\n",
          $node->getId(),
          $node->getName()
        );
    }

    protected function getCoverageBar($percent)
    {
        $level = $this->getColorLevel($percent);

        $template = new Text_Template(
          $this->templatePath . 'coverage_bar.html'
        );

        $template->setVar(array('level' => $level, 'percent' => sprintf("%.2F", $percent)));

        return $template->render();
    }

    /**
     * @param  integer $percent
     * @return string
     */
    protected function getColorLevel($percent)
    {
        if ($percent < $this->lowUpperBound) {
            return 'danger';
        }

        else if ($percent >= $this->lowUpperBound &&
                 $percent <  $this->highLowerBound) {
            return 'warning';
        }

        else {
            return 'success';
        }
    }
}
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.1.0
 */

/**
 * Generates human readable output from an PHP_CodeCoverage object.
 *
 * The output gets put into a text file our written to the CLI.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.1.0
 */
class PHP_CodeCoverage_Report_Text
{
    protected $outputStream;
    protected $lowUpperBound;
    protected $highLowerBound;
    protected $showUncoveredFiles;

    protected $colors = array(
      'green'  => "\x1b[30;42m",
      'yellow' => "\x1b[30;43m",
      'red'    => "\x1b[37;41m",
      'header' => "\x1b[47;40m",
      'reset'  => "\x1b[0m",
      'eol'    => "\x1b[2K",
    );

    public function __construct(PHPUnit_Util_Printer $outputStream, $lowUpperBound, $highLowerBound, $showUncoveredFiles)
    {
        $this->outputStream       = $outputStream;
        $this->lowUpperBound      = $lowUpperBound;
        $this->highLowerBound     = $highLowerBound;
        $this->showUncoveredFiles = $showUncoveredFiles;
    }

    /**
     * @param  PHP_CodeCoverage $coverage
     * @param  string           $target
     * @param  string           $name
     * @return string
     */
    public function process(PHP_CodeCoverage $coverage, $showColors = FALSE)
    {
        $output = '';
        $report = $coverage->getReport();
        unset($coverage);

        $colors = array(
          'header'  => '',
          'classes' => '',
          'methods' => '',
          'lines'   => '',
          'reset'   => '',
          'eol'     => ''
        );

        if ($showColors) {
            $colors['classes'] = $this->getCoverageColor(
                                   $report->getNumTestedClassesAndTraits(),
                                   $report->getNumClassesAndTraits()
                                 );
            $colors['methods'] = $this->getCoverageColor(
                                   $report->getNumTestedMethods(),
                                   $report->getNumMethods()
                                 );
            $colors['lines']   = $this->getCoverageColor(
                                   $report->getNumExecutedLines(),
                                   $report->getNumExecutableLines()
                                 );
            $colors['reset']   = $this->colors['reset'];
            $colors['header']  = $this->colors['header'];
            $colors['eol']     = $this->colors['eol'];
        }

        $output .= PHP_EOL . PHP_EOL .
                   $colors['header'] . 'Code Coverage Report ';

        $output .= PHP_EOL .
                   date('  Y-m-d H:i:s', $_SERVER['REQUEST_TIME']) .
                   PHP_EOL;

        $output .= PHP_EOL . ' Summary: ' . PHP_EOL . $colors['reset']
          . $colors['classes'] . $colors['eol'] . '  Classes: ' . PHP_CodeCoverage_Util::percent($report->getNumTestedClassesAndTraits(), $report->getNumClassesAndTraits(), TRUE)
          . ' (' . $report->getNumTestedClassesAndTraits() . '/' . $report->getNumClassesAndTraits() . ')' . PHP_EOL . $colors ['eol']
          . $colors['methods'] . $colors['eol'] . '  Methods: ' . PHP_CodeCoverage_Util::percent($report->getNumTestedMethods(), $report->getNumMethods(), TRUE)
          . ' (' . $report->getNumTestedMethods() . '/' . $report->getNumMethods() . ')' . PHP_EOL . $colors ['eol']
          . $colors['lines'] . $colors['eol'] . '  Lines:   ' . PHP_CodeCoverage_Util::percent($report->getNumExecutedLines(), $report->getNumExecutableLines(), TRUE)
          . ' (' . $report->getNumExecutedLines() . '/' . $report->getNumExecutableLines() . ')' . PHP_EOL . $colors['reset'] . $colors ['eol'];

        $classCoverage = array();

        foreach ($report as $item) {
            if (!$item instanceof PHP_CodeCoverage_Report_Node_File) {
                continue;
            }

            $classes      = $item->getClassesAndTraits();
            $coverage     = $item->getCoverageData();
            $lines        = array();
            $ignoredLines = $item->getIgnoredLines();

            foreach ($classes as $className => $class) {
                $classStatements        = 0;
                $coveredClassStatements = 0;
                $coveredMethods         = 0;

                foreach ($class['methods'] as $method) {
                    $methodCount        = 0;
                    $methodLines        = 0;
                    $methodLinesCovered = 0;

                    for ($i  = $method['startLine'];
                         $i <= $method['endLine'];
                         $i++) {
                        if (isset($ignoredLines[$i])) {
                            continue;
                        }

                        $add   = TRUE;
                        $count = 0;

                        if (isset($coverage[$i])) {
                            if ($coverage[$i] !== NULL) {
                                $classStatements++;
                                $methodLines++;
                            } else {
                                $add = FALSE;
                            }

                            $count = count($coverage[$i]);

                            if ($count > 0) {
                                $coveredClassStatements++;
                                $methodLinesCovered++;
                            }
                        } else {
                            $add = FALSE;
                        }

                        $methodCount = max($methodCount, $count);

                        if ($add) {
                            $lines[$i] = array(
                              'count' => $count, 'type'  => 'stmt'
                            );
                        }
                    }

                    if ($methodCount > 0) {
                        $coveredMethods++;
                    }

                }

                if (!empty($class['package']['namespace'])) {
                    $namespace = '\\' . $class['package']['namespace'] . '::';
                }

                else if (!empty($class['package']['fullPackage'])) {
                    $namespace = '@' . $class['package']['fullPackage'] . '::';
                }

                else {
                    $namespace = '';
                }

                $classCoverage[$namespace . $className] = array(
                    'namespace'         => $namespace,
                    'className '        => $className,
                    'methodsCovered'    => $coveredMethods,
                    'methodCount'       => count($class['methods']),
                    'statementsCovered' => $coveredClassStatements,
                    'statementCount'    => $classStatements,
                );
            }
        }

        ksort($classCoverage);

        $methodColor = '';
        $linesColor  = '';
        $resetColor  = '';

        foreach ($classCoverage as $fullQualifiedPath => $classInfo) {
            if ($classInfo['statementsCovered'] != 0 ||
                $this->showUncoveredFiles) {

                if ($showColors) {
                    $methodColor = $this->getCoverageColor($classInfo['methodsCovered'], $classInfo['methodCount']);
                    $linesColor  = $this->getCoverageColor($classInfo['statementsCovered'], $classInfo['statementCount']);
                    $resetColor  = $colors['reset'];
                }

                $output .= PHP_EOL . $fullQualifiedPath . PHP_EOL
                  . '  ' . $methodColor . 'Methods: ' . $this->printCoverageCounts($classInfo['methodsCovered'], $classInfo['methodCount'], 2) . $resetColor . ' '
                  . '  ' . $linesColor  . 'Lines: ' . $this->printCoverageCounts($classInfo['statementsCovered'], $classInfo['statementCount'], 3) . $resetColor
                ;
            }
        }

        $this->outputStream->write($output . PHP_EOL);
    }

    protected function getCoverageColor($numberOfCoveredElements, $totalNumberOfElements)
    {
        $coverage = PHP_CodeCoverage_Util::percent(
          $numberOfCoveredElements, $totalNumberOfElements
        );

        if ($coverage > $this->highLowerBound) {
            return $this->colors['green'];
        }

        else if ($coverage > $this->lowUpperBound) {
            return $this->colors['yellow'];
        }

        return $this->colors['red'];
    }

    protected function printCoverageCounts($numberOfCoveredElements, $totalNumberOfElements, $presicion)
    {
        $format = '%' . $presicion . 's';

        return PHP_CodeCoverage_Util::percent(
          $numberOfCoveredElements, $totalNumberOfElements, TRUE, TRUE
        ) .
        ' (' . sprintf($format, $numberOfCoveredElements) . '/' .
        sprintf($format, $totalNumberOfElements) . ')';
    }
}
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.0.0
 */

/**
 * Generates a Clover XML logfile from an PHP_CodeCoverage object.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.0.0
 */
class PHP_CodeCoverage_Report_Clover
{
    /**
     * @param  PHP_CodeCoverage $coverage
     * @param  string           $target
     * @param  string           $name
     * @return string
     */
    public function process(PHP_CodeCoverage $coverage, $target = NULL, $name = NULL)
    {
        $xmlDocument = new DOMDocument('1.0', 'UTF-8');
        $xmlDocument->formatOutput = TRUE;

        $xmlCoverage = $xmlDocument->createElement('coverage');
        $xmlCoverage->setAttribute('generated', (int)$_SERVER['REQUEST_TIME']);
        $xmlDocument->appendChild($xmlCoverage);

        $xmlProject = $xmlDocument->createElement('project');
        $xmlProject->setAttribute('timestamp', (int)$_SERVER['REQUEST_TIME']);

        if (is_string($name)) {
            $xmlProject->setAttribute('name', $name);
        }

        $xmlCoverage->appendChild($xmlProject);

        $packages = array();
        $report   = $coverage->getReport();
        unset($coverage);

        foreach ($report as $item) {
            $namespace = 'global';

            if (!$item instanceof PHP_CodeCoverage_Report_Node_File) {
                continue;
            }

            $xmlFile = $xmlDocument->createElement('file');
            $xmlFile->setAttribute('name', $item->getPath());

            $classes      = $item->getClassesAndTraits();
            $coverage     = $item->getCoverageData();
            $lines        = array();
            $ignoredLines = $item->getIgnoredLines();

            foreach ($classes as $className => $class) {
                $classStatements        = 0;
                $coveredClassStatements = 0;
                $coveredMethods         = 0;

                foreach ($class['methods'] as $methodName => $method) {
                    $methodCount        = 0;
                    $methodLines        = 0;
                    $methodLinesCovered = 0;

                    for ($i  = $method['startLine'];
                         $i <= $method['endLine'];
                         $i++) {
                        if (isset($ignoredLines[$i])) {
                            continue;
                        }

                        $add   = TRUE;
                        $count = 0;

                        if (isset($coverage[$i])) {
                            if ($coverage[$i] !== NULL) {
                                $classStatements++;
                                $methodLines++;
                            } else {
                                $add = FALSE;
                            }

                            $count = count($coverage[$i]);

                            if ($count > 0) {
                                $coveredClassStatements++;
                                $methodLinesCovered++;
                            }
                        } else {
                            $add = FALSE;
                        }

                        $methodCount = max($methodCount, $count);

                        if ($add) {
                            $lines[$i] = array(
                              'count' => $count, 'type'  => 'stmt'
                            );
                        }
                    }

                    if ($methodCount > 0) {
                        $coveredMethods++;
                    }

                    $lines[$method['startLine']] = array(
                      'count' => $methodCount,
                      'crap'  => $method['crap'],
                      'type'  => 'method',
                      'name'  => $methodName
                    );
                }

                if (!empty($class['package']['namespace'])) {
                    $namespace = $class['package']['namespace'];
                }

                $xmlClass = $xmlDocument->createElement('class');
                $xmlClass->setAttribute('name', $className);
                $xmlClass->setAttribute('namespace', $namespace);

                if (!empty($class['package']['fullPackage'])) {
                    $xmlClass->setAttribute(
                      'fullPackage', $class['package']['fullPackage']
                    );
                }

                if (!empty($class['package']['category'])) {
                    $xmlClass->setAttribute(
                      'category', $class['package']['category']
                    );
                }

                if (!empty($class['package']['package'])) {
                    $xmlClass->setAttribute(
                      'package', $class['package']['package']
                    );
                }

                if (!empty($class['package']['subpackage'])) {
                    $xmlClass->setAttribute(
                      'subpackage', $class['package']['subpackage']
                    );
                }

                $xmlFile->appendChild($xmlClass);

                $xmlMetrics = $xmlDocument->createElement('metrics');
                $xmlMetrics->setAttribute('methods', count($class['methods']));
                $xmlMetrics->setAttribute('coveredmethods', $coveredMethods);
                $xmlMetrics->setAttribute('conditionals', 0);
                $xmlMetrics->setAttribute('coveredconditionals', 0);
                $xmlMetrics->setAttribute('statements', $classStatements);
                $xmlMetrics->setAttribute(
                  'coveredstatements', $coveredClassStatements
                );
                $xmlMetrics->setAttribute(
                  'elements',
                  count($class['methods']) +
                  $classStatements
                  /* + conditionals */);
                $xmlMetrics->setAttribute(
                  'coveredelements',
                  $coveredMethods +
                  $coveredClassStatements
                  /* + coveredconditionals */
                );
                $xmlClass->appendChild($xmlMetrics);
            }

            foreach ($coverage as $line => $data) {
                if ($data === NULL ||
                    isset($lines[$line]) ||
                    isset($ignoredLines[$line])) {
                    continue;
                }

                $lines[$line] = array(
                  'count' => count($data), 'type' => 'stmt'
                );
            }

            ksort($lines);

            foreach ($lines as $line => $data) {
                if (isset($ignoredLines[$line])) {
                    continue;
                }

                $xmlLine = $xmlDocument->createElement('line');
                $xmlLine->setAttribute('num', $line);
                $xmlLine->setAttribute('type', $data['type']);

                if (isset($data['name'])) {
                    $xmlLine->setAttribute('name', $data['name']);
                }

                if (isset($data['crap'])) {
                    $xmlLine->setAttribute('crap', $data['crap']);
                }

                $xmlLine->setAttribute('count', $data['count']);
                $xmlFile->appendChild($xmlLine);
            }

            $linesOfCode = $item->getLinesOfCode();

            $xmlMetrics = $xmlDocument->createElement('metrics');
            $xmlMetrics->setAttribute('loc', $linesOfCode['loc']);
            $xmlMetrics->setAttribute('ncloc', $linesOfCode['ncloc']);
            $xmlMetrics->setAttribute('classes', $item->getNumClassesAndTraits());
            $xmlMetrics->setAttribute('methods', $item->getNumMethods());
            $xmlMetrics->setAttribute(
              'coveredmethods', $item->getNumTestedMethods()
            );
            $xmlMetrics->setAttribute('conditionals', 0);
            $xmlMetrics->setAttribute('coveredconditionals', 0);
            $xmlMetrics->setAttribute(
              'statements', $item->getNumExecutableLines()
            );
            $xmlMetrics->setAttribute(
              'coveredstatements', $item->getNumExecutedLines()
            );
            $xmlMetrics->setAttribute(
              'elements',
              $item->getNumMethods() +
              $item->getNumExecutableLines()
              /* + conditionals */
            );
            $xmlMetrics->setAttribute(
              'coveredelements',
              $item->getNumTestedMethods() +
              $item->getNumExecutedLines()
              /* + coveredconditionals */
            );
            $xmlFile->appendChild($xmlMetrics);

            if ($namespace == 'global') {
                $xmlProject->appendChild($xmlFile);
            } else {
                if (!isset($packages[$namespace])) {
                    $packages[$namespace] = $xmlDocument->createElement(
                      'package'
                    );

                    $packages[$namespace]->setAttribute('name', $namespace);
                    $xmlProject->appendChild($packages[$namespace]);
                }

                $packages[$namespace]->appendChild($xmlFile);
            }
        }

        $linesOfCode = $report->getLinesOfCode();

        $xmlMetrics = $xmlDocument->createElement('metrics');
        $xmlMetrics->setAttribute('files', count($report));
        $xmlMetrics->setAttribute('loc', $linesOfCode['loc']);
        $xmlMetrics->setAttribute('ncloc', $linesOfCode['ncloc']);
        $xmlMetrics->setAttribute(
          'classes', $report->getNumClassesAndTraits()
        );
        $xmlMetrics->setAttribute('methods', $report->getNumMethods());
        $xmlMetrics->setAttribute(
          'coveredmethods', $report->getNumTestedMethods()
        );
        $xmlMetrics->setAttribute('conditionals', 0);
        $xmlMetrics->setAttribute('coveredconditionals', 0);
        $xmlMetrics->setAttribute(
          'statements', $report->getNumExecutableLines()
        );
        $xmlMetrics->setAttribute(
          'coveredstatements', $report->getNumExecutedLines()
        );
        $xmlMetrics->setAttribute(
          'elements',
          $report->getNumMethods() +
          $report->getNumExecutableLines()
          /* + conditionals */
        );
        $xmlMetrics->setAttribute(
          'coveredelements',
          $report->getNumTestedMethods() +
          $report->getNumExecutedLines()
          /* + coveredconditionals */
        );
        $xmlProject->appendChild($xmlMetrics);

        if ($target !== NULL) {
            if (!is_dir(dirname($target))) {
                mkdir(dirname($target), 0777, TRUE);
            }

            return $xmlDocument->save($target);
        } else {
            return $xmlDocument->saveXML();
        }
    }
}
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.1.0
 */

/**
 * Uses serialize() to write a PHP_CodeCoverage object to a file.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.1.0
 */
class PHP_CodeCoverage_Report_PHP
{
    /**
     * @param  PHP_CodeCoverage $coverage
     * @param  string           $target
     * @return string
     */
    public function process(PHP_CodeCoverage $coverage, $target = NULL)
    {
        $coverage = serialize($coverage);

        if ($target !== NULL) {
            return file_put_contents($target, $coverage);
        } else {
            return $coverage;
        }
    }
}
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.1.0
 */

/**
 * Factory for PHP_CodeCoverage_Report_Node_* object graphs.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.1.0
 */
class PHP_CodeCoverage_Report_Factory
{
    /**
     * @param PHP_CodeCoverage $coverage
     */
    public function create(PHP_CodeCoverage $coverage)
    {
        $files      = $coverage->getData();
        $commonPath = $this->reducePaths($files);
        $root       = new PHP_CodeCoverage_Report_Node_Directory(
                        $commonPath, NULL
                      );

        $this->addItems(
          $root,
          $this->buildDirectoryStructure($files),
          $coverage->getTests(),
          $coverage->getCacheTokens()
        );

        return $root;
    }

    /**
     * @param PHP_CodeCoverage_Report_Node_Directory $root
     * @param array                                  $items
     * @param array                                  $tests
     * @param boolean                                $cacheTokens
     */
    protected function addItems(PHP_CodeCoverage_Report_Node_Directory $root, array $items, array $tests, $cacheTokens)
    {
        foreach ($items as $key => $value) {
            if (substr($key, -2) == '/f') {
                $key = substr($key, 0, -2);

                if (file_exists($root->getPath() . DIRECTORY_SEPARATOR . $key)) {
                    $root->addFile($key, $value, $tests, $cacheTokens);
                }
            } else {
                $child = $root->addDirectory($key);
                $this->addItems($child, $value, $tests, $cacheTokens);
            }
        }
    }

    /**
     * Builds an array representation of the directory structure.
     *
     * For instance,
     *
     * <code>
     * Array
     * (
     *     [Money.php] => Array
     *         (
     *             ...
     *         )
     *
     *     [MoneyBag.php] => Array
     *         (
     *             ...
     *         )
     * )
     * </code>
     *
     * is transformed into
     *
     * <code>
     * Array
     * (
     *     [.] => Array
     *         (
     *             [Money.php] => Array
     *                 (
     *                     ...
     *                 )
     *
     *             [MoneyBag.php] => Array
     *                 (
     *                     ...
     *                 )
     *         )
     * )
     * </code>
     *
     * @param  array $files
     * @return array
     */
    protected function buildDirectoryStructure($files)
    {
        $result = array();

        foreach ($files as $path => $file) {
            $path    = explode('/', $path);
            $pointer = &$result;
            $max     = count($path);

            for ($i = 0; $i < $max; $i++) {
                if ($i == ($max - 1)) {
                    $type = '/f';
                } else {
                    $type = '';
                }

                $pointer = &$pointer[$path[$i] . $type];
            }

            $pointer = $file;
        }

        return $result;
    }

    /**
     * Reduces the paths by cutting the longest common start path.
     *
     * For instance,
     *
     * <code>
     * Array
     * (
     *     [/home/sb/Money/Money.php] => Array
     *         (
     *             ...
     *         )
     *
     *     [/home/sb/Money/MoneyBag.php] => Array
     *         (
     *             ...
     *         )
     * )
     * </code>
     *
     * is reduced to
     *
     * <code>
     * Array
     * (
     *     [Money.php] => Array
     *         (
     *             ...
     *         )
     *
     *     [MoneyBag.php] => Array
     *         (
     *             ...
     *         )
     * )
     * </code>
     *
     * @param  array $files
     * @return string
     */
    protected function reducePaths(&$files)
    {
        if (empty($files)) {
            return '.';
        }

        $commonPath = '';
        $paths      = array_keys($files);

        if (count($files) == 1) {
            $commonPath                 = dirname($paths[0]) . '/';
            $files[basename($paths[0])] = $files[$paths[0]];

            unset($files[$paths[0]]);

            return $commonPath;
        }

        $max = count($paths);

        for ($i = 0; $i < $max; $i++) {
            // strip phar:// prefixes
            if (strpos($paths[$i], 'phar://') === 0) {
                $paths[$i] = substr($paths[$i], 7);
            }
            $paths[$i] = explode(DIRECTORY_SEPARATOR, $paths[$i]);

            if (empty($paths[$i][0])) {
                $paths[$i][0] = DIRECTORY_SEPARATOR;
            }
        }

        $done = FALSE;
        $max  = count($paths);

        while (!$done) {
            for ($i = 0; $i < $max - 1; $i++) {
                if (!isset($paths[$i][0]) ||
                    !isset($paths[$i+1][0]) ||
                    $paths[$i][0] != $paths[$i+1][0]) {
                    $done = TRUE;
                    break;
                }
            }

            if (!$done) {
                $commonPath .= $paths[0][0];

                if ($paths[0][0] != DIRECTORY_SEPARATOR) {
                    $commonPath .= DIRECTORY_SEPARATOR;
                }

                for ($i = 0; $i < $max; $i++) {
                    array_shift($paths[$i]);
                }
            }
        }

        $original = array_keys($files);
        $max      = count($original);

        for ($i = 0; $i < $max; $i++) {
            $files[join('/', $paths[$i])] = $files[$original[$i]];
            unset($files[$original[$i]]);
        }

        ksort($files);

        return substr($commonPath, 0, -1);
    }
}
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.1.0
 */

/**
 * Represents a file in the code coverage information tree.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.1.0
 */
class PHP_CodeCoverage_Report_Node_File extends PHP_CodeCoverage_Report_Node
{
    /**
     * @var array
     */
    protected $coverageData;

    /**
     * @var array
     */
    protected $testData;

    /**
     * @var array
     */
    protected $ignoredLines;

    /**
     * @var integer
     */
    protected $numExecutableLines = 0;

    /**
     * @var integer
     */
    protected $numExecutedLines = 0;

    /**
     * @var array
     */
    protected $classes = array();

    /**
     * @var array
     */
    protected $traits = array();

    /**
     * @var array
     */
    protected $functions = array();

    /**
     * @var array
     */
    protected $linesOfCode = array();

    /**
     * @var integer
     */
    protected $numTestedTraits = 0;

    /**
     * @var integer
     */
    protected $numTestedClasses = 0;

    /**
     * @var integer
     */
    protected $numMethods = NULL;

    /**
     * @var integer
     */
    protected $numTestedMethods = NULL;

    /**
     * @var integer
     */
    protected $numTestedFunctions = NULL;

    /**
     * @var array
     */
    protected $startLines = array();

    /**
     * @var array
     */
    protected $endLines = array();

    /**
     * @var boolean
     */
    protected $cacheTokens;

    /**
     * Constructor.
     *
     * @param  string                       $name
     * @param  PHP_CodeCoverage_Report_Node $parent
     * @param  array                        $coverageData
     * @param  array                        $testData
     * @param  boolean                      $cacheTokens
     * @throws PHP_CodeCoverage_Exception
     */
    public function __construct($name, PHP_CodeCoverage_Report_Node $parent, array $coverageData, array $testData, $cacheTokens)
    {
        if (!is_bool($cacheTokens)) {
            throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory(
              1, 'boolean'
            );
        }

        parent::__construct($name, $parent);

        $this->coverageData = $coverageData;
        $this->testData     = $testData;
        $this->ignoredLines = PHP_CodeCoverage_Util::getLinesToBeIgnored(
                                $this->getPath(), $cacheTokens
                              );
        $this->cacheTokens  = $cacheTokens;

        $this->calculateStatistics();
    }

    /**
     * Returns the number of files in/under this node.
     *
     * @return integer
     */
    public function count()
    {
        return 1;
    }

    /**
     * Returns the code coverage data of this node.
     *
     * @return array
     */
    public function getCoverageData()
    {
        return $this->coverageData;
    }

    /**
     * Returns the test data of this node.
     *
     * @return array
     */
    public function getTestData()
    {
        return $this->testData;
    }

    /**
     * @return array
     */
    public function getIgnoredLines()
    {
        return $this->ignoredLines;
    }

    /**
     * Returns the classes of this node.
     *
     * @return array
     */
    public function getClasses()
    {
        return $this->classes;
    }

    /**
     * Returns the traits of this node.
     *
     * @return array
     */
    public function getTraits()
    {
        return $this->traits;
    }

    /**
     * Returns the functions of this node.
     *
     * @return array
     */
    public function getFunctions()
    {
        return $this->functions;
    }

    /**
     * Returns the LOC/CLOC/NCLOC of this node.
     *
     * @return array
     */
    public function getLinesOfCode()
    {
        return $this->linesOfCode;
    }

    /**
     * Returns the number of executable lines.
     *
     * @return integer
     */
    public function getNumExecutableLines()
    {
        return $this->numExecutableLines;
    }

    /**
     * Returns the number of executed lines.
     *
     * @return integer
     */
    public function getNumExecutedLines()
    {
        return $this->numExecutedLines;
    }

    /**
     * Returns the number of classes.
     *
     * @return integer
     */
    public function getNumClasses()
    {
        return count($this->classes);
    }

    /**
     * Returns the number of tested classes.
     *
     * @return integer
     */
    public function getNumTestedClasses()
    {
        return $this->numTestedClasses;
    }

    /**
     * Returns the number of traits.
     *
     * @return integer
     */
    public function getNumTraits()
    {
        return count($this->traits);
    }

    /**
     * Returns the number of tested traits.
     *
     * @return integer
     */
    public function getNumTestedTraits()
    {
        return $this->numTestedTraits;
    }

    /**
     * Returns the number of methods.
     *
     * @return integer
     */
    public function getNumMethods()
    {
        if ($this->numMethods === NULL) {
            $this->numMethods = 0;

            foreach ($this->classes as $class) {
                foreach ($class['methods'] as $method) {
                    if ($method['executableLines'] > 0) {
                        $this->numMethods++;
                    }
                }
            }

            foreach ($this->traits as $trait) {
                foreach ($trait['methods'] as $method) {
                    if ($method['executableLines'] > 0) {
                        $this->numMethods++;
                    }
                }
            }
        }

        return $this->numMethods;
    }

    /**
     * Returns the number of tested methods.
     *
     * @return integer
     */
    public function getNumTestedMethods()
    {
        if ($this->numTestedMethods === NULL) {
            $this->numTestedMethods = 0;

            foreach ($this->classes as $class) {
                foreach ($class['methods'] as $method) {
                    if ($method['executableLines'] > 0 &&
                        $method['coverage'] == 100) {
                        $this->numTestedMethods++;
                    }
                }
            }

            foreach ($this->traits as $trait) {
                foreach ($trait['methods'] as $method) {
                    if ($method['executableLines'] > 0 &&
                        $method['coverage'] == 100) {
                        $this->numTestedMethods++;
                    }
                }
            }
        }

        return $this->numTestedMethods;
    }

    /**
     * Returns the number of functions.
     *
     * @return integer
     */
    public function getNumFunctions()
    {
        return count($this->functions);
    }

    /**
     * Returns the number of tested functions.
     *
     * @return integer
     */
    public function getNumTestedFunctions()
    {
        if ($this->numTestedFunctions === NULL) {
            $this->numTestedFunctions = 0;

            foreach ($this->functions as $function) {
                if ($function['executableLines'] > 0 &&
                    $function['coverage'] == 100) {
                    $this->numTestedFunctions++;
                }
            }
        }

        return $this->numTestedFunctions;
    }

    /**
     * Calculates coverage statistics for the file.
     */
    protected function calculateStatistics()
    {
        if ($this->cacheTokens) {
            $tokens = PHP_Token_Stream_CachingFactory::get($this->getPath());
        } else {
            $tokens = new PHP_Token_Stream($this->getPath());
        }

        $this->processClasses($tokens);
        $this->processTraits($tokens);
        $this->processFunctions($tokens);
        $this->linesOfCode = $tokens->getLinesOfCode();
        unset($tokens);

        for ($lineNumber = 1; $lineNumber <= $this->linesOfCode['loc']; $lineNumber++) {
            if (isset($this->startLines[$lineNumber])) {
                // Start line of a class.
                if (isset($this->startLines[$lineNumber]['className'])) {
                    $currentClass = &$this->startLines[$lineNumber];
                }

                // Start line of a trait.
                else if (isset($this->startLines[$lineNumber]['traitName'])) {
                    $currentTrait = &$this->startLines[$lineNumber];
                }

                // Start line of a method.
                else if (isset($this->startLines[$lineNumber]['methodName'])) {
                    $currentMethod = &$this->startLines[$lineNumber];
                }

                // Start line of a function.
                else if (isset($this->startLines[$lineNumber]['functionName'])) {
                    $currentFunction = &$this->startLines[$lineNumber];
                }
            }

            if (!isset($this->ignoredLines[$lineNumber]) &&
                isset($this->coverageData[$lineNumber]) &&
                $this->coverageData[$lineNumber] !== NULL) {
                if (isset($currentClass)) {
                    $currentClass['executableLines']++;
                }

                if (isset($currentTrait)) {
                    $currentTrait['executableLines']++;
                }

                if (isset($currentMethod)) {
                    $currentMethod['executableLines']++;
                }

                if (isset($currentFunction)) {
                    $currentFunction['executableLines']++;
                }

                $this->numExecutableLines++;

                if (count($this->coverageData[$lineNumber]) > 0 ||
                    isset($this->ignoredLines[$lineNumber])) {
                    if (isset($currentClass)) {
                        $currentClass['executedLines']++;
                    }

                    if (isset($currentTrait)) {
                        $currentTrait['executedLines']++;
                    }

                    if (isset($currentMethod)) {
                        $currentMethod['executedLines']++;
                    }

                    if (isset($currentFunction)) {
                        $currentFunction['executedLines']++;
                    }

                    $this->numExecutedLines++;
                }
            }

            if (isset($this->endLines[$lineNumber])) {
                // End line of a class.
                if (isset($this->endLines[$lineNumber]['className'])) {
                    unset($currentClass);
                }

                // End line of a trait.
                else if (isset($this->endLines[$lineNumber]['traitName'])) {
                    unset($currentTrait);
                }

                // End line of a method.
                else if (isset($this->endLines[$lineNumber]['methodName'])) {
                    unset($currentMethod);
                }

                // End line of a function.
                else if (isset($this->endLines[$lineNumber]['functionName'])) {
                    unset($currentFunction);
                }
            }
        }

        foreach ($this->traits as &$trait) {
            foreach ($trait['methods'] as &$method) {
                if ($method['executableLines'] > 0) {
                    $method['coverage'] = ($method['executedLines'] /
                                           $method['executableLines']) * 100;
                } else {
                    $method['coverage'] = 100;
                }

                $method['crap'] = $this->crap(
                  $method['ccn'], $method['coverage']
                );

                $trait['ccn'] += $method['ccn'];
            }

            if ($trait['executableLines'] > 0) {
                $trait['coverage'] = ($trait['executedLines'] /
                                      $trait['executableLines']) * 100;
            } else {
                $trait['coverage'] = 100;
            }

            if ($trait['coverage'] == 100) {
                $this->numTestedClasses++;
            }

            $trait['crap'] = $this->crap(
              $trait['ccn'], $trait['coverage']
            );
        }

        foreach ($this->classes as &$class) {
            foreach ($class['methods'] as &$method) {
                if ($method['executableLines'] > 0) {
                    $method['coverage'] = ($method['executedLines'] /
                                           $method['executableLines']) * 100;
                } else {
                    $method['coverage'] = 100;
                }

                $method['crap'] = $this->crap(
                  $method['ccn'], $method['coverage']
                );

                $class['ccn'] += $method['ccn'];
            }

            if ($class['executableLines'] > 0) {
                $class['coverage'] = ($class['executedLines'] /
                                      $class['executableLines']) * 100;
            } else {
                $class['coverage'] = 100;
            }

            if ($class['coverage'] == 100) {
                $this->numTestedClasses++;
            }

            $class['crap'] = $this->crap(
              $class['ccn'], $class['coverage']
            );
        }
    }

    /**
     * @param PHP_Token_Stream $tokens
     */
    protected function processClasses(PHP_Token_Stream $tokens)
    {
        $classes = $tokens->getClasses();
        unset($tokens);

        $link = $this->getId() . '.html#';

        foreach ($classes as $className => $class) {
            $this->classes[$className] = array(
              'className'       => $className,
              'methods'         => array(),
              'startLine'       => $class['startLine'],
              'executableLines' => 0,
              'executedLines'   => 0,
              'ccn'             => 0,
              'coverage'        => 0,
              'crap'            => 0,
              'package'         => $class['package'],
              'link'            => $link . $class['startLine']
            );

            $this->startLines[$class['startLine']] = &$this->classes[$className];
            $this->endLines[$class['endLine']]     = &$this->classes[$className];

            foreach ($class['methods'] as $methodName => $method) {
                $this->classes[$className]['methods'][$methodName] = array(
                  'methodName'      => $methodName,
                  'signature'       => $method['signature'],
                  'startLine'       => $method['startLine'],
                  'endLine'         => $method['endLine'],
                  'executableLines' => 0,
                  'executedLines'   => 0,
                  'ccn'             => $method['ccn'],
                  'coverage'        => 0,
                  'crap'            => 0,
                  'link'            => $link . $method['startLine']
                );

                $this->startLines[$method['startLine']] = &$this->classes[$className]['methods'][$methodName];
                $this->endLines[$method['endLine']]     = &$this->classes[$className]['methods'][$methodName];
            }
        }
    }

    /**
     * @param PHP_Token_Stream $tokens
     */
    protected function processTraits(PHP_Token_Stream $tokens)
    {
        $traits = $tokens->getTraits();
        unset($tokens);

        $link = $this->getId() . '.html#';

        foreach ($traits as $traitName => $trait) {
            $this->traits[$traitName] = array(
              'traitName'       => $traitName,
              'methods'         => array(),
              'startLine'       => $trait['startLine'],
              'executableLines' => 0,
              'executedLines'   => 0,
              'ccn'             => 0,
              'coverage'        => 0,
              'crap'            => 0,
              'package'         => $trait['package'],
              'link'            => $link . $trait['startLine']
            );

            $this->startLines[$trait['startLine']] = &$this->traits[$traitName];
            $this->endLines[$trait['endLine']]     = &$this->traits[$traitName];

            foreach ($trait['methods'] as $methodName => $method) {
                $this->traits[$traitName]['methods'][$methodName] = array(
                  'methodName'      => $methodName,
                  'signature'       => $method['signature'],
                  'startLine'       => $method['startLine'],
                  'endLine'         => $method['endLine'],
                  'executableLines' => 0,
                  'executedLines'   => 0,
                  'ccn'             => $method['ccn'],
                  'coverage'        => 0,
                  'crap'            => 0,
                  'link'            => $link . $method['startLine']
                );

                $this->startLines[$method['startLine']] = &$this->traits[$traitName]['methods'][$methodName];
                $this->endLines[$method['endLine']]     = &$this->traits[$traitName]['methods'][$methodName];
            }
        }
    }

    /**
     * @param PHP_Token_Stream $tokens
     */
    protected function processFunctions(PHP_Token_Stream $tokens)
    {
        $functions = $tokens->getFunctions();
        unset($tokens);

        $link = $this->getId() . '.html#';

        foreach ($functions as $functionName => $function) {
            $this->functions[$functionName] = array(
              'functionName'    => $functionName,
              'signature'       => $function['signature'],
              'startLine'       => $function['startLine'],
              'executableLines' => 0,
              'executedLines'   => 0,
              'ccn'             => $function['ccn'],
              'coverage'        => 0,
              'crap'            => 0,
              'link'            => $link . $function['startLine']
            );

            $this->startLines[$function['startLine']] = &$this->functions[$functionName];
            $this->endLines[$function['endLine']]     = &$this->functions[$functionName];
        }
    }

    /**
     * Calculates the Change Risk Anti-Patterns (CRAP) index for a unit of code
     * based on its cyclomatic complexity and percentage of code coverage.
     *
     * @param  integer $ccn
     * @param  float   $coverage
     * @return string
     * @since  Method available since Release 1.2.0
     */
    protected function crap($ccn, $coverage)
    {
        if ($coverage == 0) {
            return (string)pow($ccn, 2) + $ccn;
        }

        if ($coverage >= 95) {
            return (string)$ccn;
        }

        return sprintf(
          '%01.2F', pow($ccn, 2) * pow(1 - $coverage/100, 3) + $ccn
        );
    }
}
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.1.0
 */

/**
 * Recursive iterator for PHP_CodeCoverage_Report_Node object graphs.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.1.0
 */
class PHP_CodeCoverage_Report_Node_Iterator implements RecursiveIterator
{
    /**
     * @var integer
     */
    protected $position;

    /**
     * @var PHP_CodeCoverage_Report_Node[]
     */
    protected $nodes;

    /**
     * Constructor.
     *
     * @param PHP_CodeCoverage_Report_Node_Directory $node
     */
    public function __construct(PHP_CodeCoverage_Report_Node_Directory $node)
    {
        $this->nodes = $node->getChildNodes();
    }

    /**
     * Rewinds the Iterator to the first element.
     *
     */
    public function rewind()
    {
        $this->position = 0;
    }

    /**
     * Checks if there is a current element after calls to rewind() or next().
     *
     * @return boolean
     */
    public function valid()
    {
        return $this->position < count($this->nodes);
    }

    /**
     * Returns the key of the current element.
     *
     * @return integer
     */
    public function key()
    {
        return $this->position;
    }

    /**
     * Returns the current element.
     *
     * @return PHPUnit_Framework_Test
     */
    public function current()
    {
        return $this->valid() ? $this->nodes[$this->position] : NULL;
    }

    /**
     * Moves forward to next element.
     *
     */
    public function next()
    {
        $this->position++;
    }

    /**
     * Returns the sub iterator for the current element.
     *
     * @return PHP_CodeCoverage_Report_Node_Iterator
     */
    public function getChildren()
    {
        return new PHP_CodeCoverage_Report_Node_Iterator(
          $this->nodes[$this->position]
        );
    }

    /**
     * Checks whether the current element has children.
     *
     * @return boolean
     */
    public function hasChildren()
    {
        return $this->nodes[$this->position] instanceof PHP_CodeCoverage_Report_Node_Directory;
    }
}
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.1.0
 */

/**
 * Represents a directory in the code coverage information tree.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.1.0
 */
class PHP_CodeCoverage_Report_Node_Directory extends PHP_CodeCoverage_Report_Node implements IteratorAggregate
{
    /**
     * @var PHP_CodeCoverage_Report_Node[]
     */
    protected $children = array();

    /**
     * @var PHP_CodeCoverage_Report_Node_Directory[]
     */
    protected $directories = array();

    /**
     * @var PHP_CodeCoverage_Report_Node_File[]
     */
    protected $files = array();

    /**
     * @var array
     */
    protected $classes;

    /**
     * @var array
     */
    protected $traits;

    /**
     * @var array
     */
    protected $functions;

    /**
     * @var array
     */
    protected $linesOfCode = NULL;

    /**
     * @var integer
     */
    protected $numFiles = -1;

    /**
     * @var integer
     */
    protected $numExecutableLines = -1;

    /**
     * @var integer
     */
    protected $numExecutedLines = -1;

    /**
     * @var integer
     */
    protected $numClasses = -1;

    /**
     * @var integer
     */
    protected $numTestedClasses = -1;

    /**
     * @var integer
     */
    protected $numTraits = -1;

    /**
     * @var integer
     */
    protected $numTestedTraits = -1;

    /**
     * @var integer
     */
    protected $numMethods = -1;

    /**
     * @var integer
     */
    protected $numTestedMethods = -1;

    /**
     * @var integer
     */
    protected $numFunctions = -1;

    /**
     * @var integer
     */
    protected $numTestedFunctions = -1;

    /**
     * Returns the number of files in/under this node.
     *
     * @return integer
     */
    public function count()
    {
        if ($this->numFiles == -1) {
            $this->numFiles = 0;

            foreach ($this->children as $child) {
                $this->numFiles += count($child);
            }
        }

        return $this->numFiles;
    }

    /**
     * Returns an iterator for this node.
     *
     * @return RecursiveIteratorIterator
     */
    public function getIterator()
    {
        return new RecursiveIteratorIterator(
          new PHP_CodeCoverage_Report_Node_Iterator($this),
          RecursiveIteratorIterator::SELF_FIRST
        );
    }

    /**
     * Adds a new directory.
     *
     * @param  string $name
     * @return PHP_CodeCoverage_Report_Node_Directory
     */
    public function addDirectory($name)
    {
        $directory = new PHP_CodeCoverage_Report_Node_Directory($name, $this);

        $this->children[]    = $directory;
        $this->directories[] = &$this->children[count($this->children) - 1];

        return $directory;
    }

    /**
     * Adds a new file.
     *
     * @param  string  $name
     * @param  array   $coverageData
     * @param  array   $testData
     * @param  boolean $cacheTokens
     * @return PHP_CodeCoverage_Report_Node_File
     * @throws PHP_CodeCoverage_Exception
     */
    public function addFile($name, array $coverageData, array $testData, $cacheTokens)
    {
        $file = new PHP_CodeCoverage_Report_Node_File(
          $name, $this, $coverageData, $testData, $cacheTokens
        );

        $this->children[] = $file;
        $this->files[]    = &$this->children[count($this->children) - 1];

        $this->numExecutableLines = -1;
        $this->numExecutedLines   = -1;

        return $file;
    }

    /**
     * Returns the directories in this directory.
     *
     * @return array
     */
    public function getDirectories()
    {
        return $this->directories;
    }

    /**
     * Returns the files in this directory.
     *
     * @return array
     */
    public function getFiles()
    {
        return $this->files;
    }

    /**
     * Returns the child nodes of this node.
     *
     * @return array
     */
    public function getChildNodes()
    {
        return $this->children;
    }

    /**
     * Returns the classes of this node.
     *
     * @return array
     */
    public function getClasses()
    {
        if ($this->classes === NULL) {
            $this->classes = array();

            foreach ($this->children as $child) {
                $this->classes = array_merge(
                  $this->classes, $child->getClasses()
                );
            }
        }

        return $this->classes;
    }

    /**
     * Returns the traits of this node.
     *
     * @return array
     */
    public function getTraits()
    {
        if ($this->traits === NULL) {
            $this->traits = array();

            foreach ($this->children as $child) {
                $this->traits = array_merge(
                  $this->traits, $child->getTraits()
                );
            }
        }

        return $this->traits;
    }

    /**
     * Returns the functions of this node.
     *
     * @return array
     */
    public function getFunctions()
    {
        if ($this->functions === NULL) {
            $this->functions = array();

            foreach ($this->children as $child) {
                $this->functions = array_merge(
                  $this->functions, $child->getFunctions()
                );
            }
        }

        return $this->functions;
    }

    /**
     * Returns the LOC/CLOC/NCLOC of this node.
     *
     * @return array
     */
    public function getLinesOfCode()
    {
        if ($this->linesOfCode === NULL) {
            $this->linesOfCode = array('loc' => 0, 'cloc' => 0, 'ncloc' => 0);

            foreach ($this->children as $child) {
                $linesOfCode = $child->getLinesOfCode();

                $this->linesOfCode['loc']   += $linesOfCode['loc'];
                $this->linesOfCode['cloc']  += $linesOfCode['cloc'];
                $this->linesOfCode['ncloc'] += $linesOfCode['ncloc'];
            }
        }

        return $this->linesOfCode;
    }

    /**
     * Returns the number of executable lines.
     *
     * @return integer
     */
    public function getNumExecutableLines()
    {
        if ($this->numExecutableLines == -1) {
            $this->numExecutableLines = 0;

            foreach ($this->children as $child) {
                $this->numExecutableLines += $child->getNumExecutableLines();
            }
        }

        return $this->numExecutableLines;
    }

    /**
     * Returns the number of executed lines.
     *
     * @return integer
     */
    public function getNumExecutedLines()
    {
        if ($this->numExecutedLines == -1) {
            $this->numExecutedLines = 0;

            foreach ($this->children as $child) {
                $this->numExecutedLines += $child->getNumExecutedLines();
            }
        }

        return $this->numExecutedLines;
    }

    /**
     * Returns the number of classes.
     *
     * @return integer
     */
    public function getNumClasses()
    {
        if ($this->numClasses == -1) {
            $this->numClasses = 0;

            foreach ($this->children as $child) {
                $this->numClasses += $child->getNumClasses();
            }
        }

        return $this->numClasses;
    }

    /**
     * Returns the number of tested classes.
     *
     * @return integer
     */
    public function getNumTestedClasses()
    {
        if ($this->numTestedClasses == -1) {
            $this->numTestedClasses = 0;

            foreach ($this->children as $child) {
                $this->numTestedClasses += $child->getNumTestedClasses();
            }
        }

        return $this->numTestedClasses;
    }

    /**
     * Returns the number of traits.
     *
     * @return integer
     */
    public function getNumTraits()
    {
        if ($this->numTraits == -1) {
            $this->numTraits = 0;

            foreach ($this->children as $child) {
                $this->numTraits += $child->getNumTraits();
            }
        }

        return $this->numTraits;
    }

    /**
     * Returns the number of tested traits.
     *
     * @return integer
     */
    public function getNumTestedTraits()
    {
        if ($this->numTestedTraits == -1) {
            $this->numTestedTraits = 0;

            foreach ($this->children as $child) {
                $this->numTestedTraits += $child->getNumTestedTraits();
            }
        }

        return $this->numTestedTraits;
    }

    /**
     * Returns the number of methods.
     *
     * @return integer
     */
    public function getNumMethods()
    {
        if ($this->numMethods == -1) {
            $this->numMethods = 0;

            foreach ($this->children as $child) {
                $this->numMethods += $child->getNumMethods();
            }
        }

        return $this->numMethods;
    }

    /**
     * Returns the number of tested methods.
     *
     * @return integer
     */
    public function getNumTestedMethods()
    {
        if ($this->numTestedMethods == -1) {
            $this->numTestedMethods = 0;

            foreach ($this->children as $child) {
                $this->numTestedMethods += $child->getNumTestedMethods();
            }
        }

        return $this->numTestedMethods;
    }

    /**
     * Returns the number of functions.
     *
     * @return integer
     */
    public function getNumFunctions()
    {
        if ($this->numFunctions == -1) {
            $this->numFunctions = 0;

            foreach ($this->children as $child) {
                $this->numFunctions += $child->getNumFunctions();
            }
        }

        return $this->numFunctions;
    }

    /**
     * Returns the number of tested functions.
     *
     * @return integer
     */
    public function getNumTestedFunctions()
    {
        if ($this->numTestedFunctions == -1) {
            $this->numTestedFunctions = 0;

            foreach ($this->children as $child) {
                $this->numTestedFunctions += $child->getNumTestedFunctions();
            }
        }

        return $this->numTestedFunctions;
    }
}
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2010 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.1.0
 */

if (defined('PHPUNIT_COMPOSER_INSTALL')) {
    return;
}

require_once 'File/Iterator/Autoload.php';
require_once 'PHP/Token/Stream/Autoload.php';
require_once 'Text/Template/Autoload.php';

spl_autoload_register(
  function ($class)
  {
      static $classes = NULL;
      static $path = NULL;

      if ($classes === NULL) {
          $classes = array(
            'php_codecoverage' => '/CodeCoverage.php',
            'php_codecoverage_driver' => '/CodeCoverage/Driver.php',
            'php_codecoverage_driver_xdebug' => '/CodeCoverage/Driver/Xdebug.php',
            'php_codecoverage_exception' => '/CodeCoverage/Exception.php',
            'php_codecoverage_filter' => '/CodeCoverage/Filter.php',
            'php_codecoverage_report_clover' => '/CodeCoverage/Report/Clover.php',
            'php_codecoverage_report_factory' => '/CodeCoverage/Report/Factory.php',
            'php_codecoverage_report_html' => '/CodeCoverage/Report/HTML.php',
            'php_codecoverage_report_html_renderer' => '/CodeCoverage/Report/HTML/Renderer.php',
            'php_codecoverage_report_html_renderer_dashboard' => '/CodeCoverage/Report/HTML/Renderer/Dashboard.php',
            'php_codecoverage_report_html_renderer_directory' => '/CodeCoverage/Report/HTML/Renderer/Directory.php',
            'php_codecoverage_report_html_renderer_file' => '/CodeCoverage/Report/HTML/Renderer/File.php',
            'php_codecoverage_report_node' => '/CodeCoverage/Report/Node.php',
            'php_codecoverage_report_node_directory' => '/CodeCoverage/Report/Node/Directory.php',
            'php_codecoverage_report_node_file' => '/CodeCoverage/Report/Node/File.php',
            'php_codecoverage_report_node_iterator' => '/CodeCoverage/Report/Node/Iterator.php',
            'php_codecoverage_report_php' => '/CodeCoverage/Report/PHP.php',
            'php_codecoverage_report_text' => '/CodeCoverage/Report/Text.php',
            'php_codecoverage_util' => '/CodeCoverage/Util.php',
            'php_codecoverage_util_invalidargumenthelper' => '/CodeCoverage/Util/InvalidArgumentHelper.php',
            'php_codecoverage_version' => '/CodeCoverage/Version.php'
          );

          $path = dirname(dirname(__FILE__));
      }

      $cn = strtolower($class);

      if (isset($classes[$cn])) {
          require $path . $classes[$cn];
      }
  }
);
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.0.0
 */

/**
 * Driver for Xdebug's code coverage functionality.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.0.0
 * @codeCoverageIgnore
 */
class PHP_CodeCoverage_Driver_Xdebug implements PHP_CodeCoverage_Driver
{
    /**
     * Constructor.
     */
    public function __construct()
    {
        if (!extension_loaded('xdebug')) {
            throw new PHP_CodeCoverage_Exception('Xdebug is not loaded.');
        }

        if (version_compare(phpversion('xdebug'), '2.2.0-dev', '>=') &&
            !ini_get('xdebug.coverage_enable')) {
            throw new PHP_CodeCoverage_Exception(
              'You need to set xdebug.coverage_enable=On in your php.ini.'
            );
        }
    }

    /**
     * Start collection of code coverage information.
     */
    public function start()
    {
        xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE);
    }

    /**
     * Stop collection of code coverage information.
     *
     * @return array
     */
    public function stop()
    {
        $codeCoverage = xdebug_get_code_coverage();
        xdebug_stop_code_coverage();

        return $codeCoverage;
    }
}
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2010 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.1.0
 */

if (defined('PHPUNIT_COMPOSER_INSTALL')) {
    return;
}

require_once 'File/Iterator/Autoload.php';
require_once 'PHP/Token/Stream/Autoload.php';
require_once 'Text/Template/Autoload.php';

spl_autoload_register(
  function ($class)
  {
      static $classes = NULL;
      static $path = NULL;

      if ($classes === NULL) {
          $classes = array(
            ___CLASSLIST___
          );

          $path = dirname(dirname(__FILE__));
      }

      $cn = strtolower($class);

      if (isset($classes[$cn])) {
          require $path . $classes[$cn];
      }
  }
);
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.0.0
 */

// @codeCoverageIgnoreStart
// @codingStandardsIgnoreStart
/**
 * @SuppressWarnings(PHPMD)
 */
if (!function_exists('trait_exists')) {
    function trait_exists($name)
    {
        return FALSE;
    }
}
// @codingStandardsIgnoreEnd
// @codeCoverageIgnoreEnd

/**
 * Provides collection functionality for PHP code coverage information.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.0.0
 */
class PHP_CodeCoverage
{
    /**
     * @var PHP_CodeCoverage_Driver
     */
    protected $driver;

    /**
     * @var PHP_CodeCoverage_Filter
     */
    protected $filter;

    /**
     * @var boolean
     */
    protected $cacheTokens = FALSE;

    /**
     * @var boolean
     */
    protected $forceCoversAnnotation = FALSE;

    /**
     * @var boolean
     */
    protected $mapTestClassNameToCoveredClassName = FALSE;

    /**
     * @var boolean
     */
    protected $addUncoveredFilesFromWhitelist = TRUE;

    /**
     * @var boolean
     */
    protected $processUncoveredFilesFromWhitelist = FALSE;

    /**
     * @var mixed
     */
    protected $currentId;

    /**
     * Code coverage data.
     *
     * @var array
     */
    protected $data = array();

    /**
     * Test data.
     *
     * @var array
     */
    protected $tests = array();

    /**
     * Constructor.
     *
     * @param PHP_CodeCoverage_Driver $driver
     * @param PHP_CodeCoverage_Filter $filter
     */
    public function __construct(PHP_CodeCoverage_Driver $driver = NULL, PHP_CodeCoverage_Filter $filter = NULL)
    {
        if ($driver === NULL) {
            $driver = new PHP_CodeCoverage_Driver_Xdebug;
        }

        if ($filter === NULL) {
            $filter = new PHP_CodeCoverage_Filter;
        }

        $this->driver = $driver;
        $this->filter = $filter;
    }

    /**
     * Returns the PHP_CodeCoverage_Report_Node_* object graph
     * for this PHP_CodeCoverage object.
     *
     * @return PHP_CodeCoverage_Report_Node_Directory
     * @since  Method available since Release 1.1.0
     */
    public function getReport()
    {
        $factory = new PHP_CodeCoverage_Report_Factory;

        return $factory->create($this);
    }

    /**
     * Clears collected code coverage data.
     */
    public function clear()
    {
        $this->currentId = NULL;
        $this->data      = array();
        $this->tests     = array();
    }

    /**
     * Returns the PHP_CodeCoverage_Filter used.
     *
     * @return PHP_CodeCoverage_Filter
     */
    public function filter()
    {
        return $this->filter;
    }

    /**
     * Returns the collected code coverage data.
     *
     * @return array
     * @since  Method available since Release 1.1.0
     */
    public function getData()
    {
        if ($this->addUncoveredFilesFromWhitelist) {
            $this->addUncoveredFilesFromWhitelist();
        }

        // We need to apply the blacklist filter a second time
        // when no whitelist is used.
        if (!$this->filter->hasWhitelist()) {
            $this->applyListsFilter($this->data);
        }

        return $this->data;
    }

    /**
     * Returns the test data.
     *
     * @return array
     * @since  Method available since Release 1.1.0
     */
    public function getTests()
    {
        return $this->tests;
    }

    /**
     * Start collection of code coverage information.
     *
     * @param  mixed   $id
     * @param  boolean $clear
     * @throws PHP_CodeCoverage_Exception
     */
    public function start($id, $clear = FALSE)
    {
        if (!is_bool($clear)) {
            throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory(
              1, 'boolean'
            );
        }

        if ($clear) {
            $this->clear();
        }

        $this->currentId = $id;

        $this->driver->start();
    }

    /**
     * Stop collection of code coverage information.
     *
     * @param  boolean $append
     * @return array
     * @throws PHP_CodeCoverage_Exception
     */
    public function stop($append = TRUE)
    {
        if (!is_bool($append)) {
            throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory(
              1, 'boolean'
            );
        }

        $data = $this->driver->stop();
        $this->append($data, NULL, $append);

        $this->currentId = NULL;

        return $data;
    }

    /**
     * Appends code coverage data.
     *
     * @param array   $data
     * @param mixed   $id
     * @param boolean $append
     */
    public function append(array $data, $id = NULL, $append = TRUE)
    {
        if ($id === NULL) {
            $id = $this->currentId;
        }

        if ($id === NULL) {
            throw new PHP_CodeCoverage_Exception;
        }

        $this->applyListsFilter($data);
        $this->initializeFilesThatAreSeenTheFirstTime($data);

        if (!$append) {
            return;
        }

        if ($id != 'UNCOVERED_FILES_FROM_WHITELIST') {
            $this->applyCoversAnnotationFilter($data, $id);
        }

        if (empty($data)) {
            return;
        }

        $status = NULL;

        if ($id instanceof PHPUnit_Framework_TestCase) {
            $status = $id->getStatus();
            $id     = get_class($id) . '::' . $id->getName();
        }

        else if ($id instanceof PHPUnit_Extensions_PhptTestCase) {
            $id = $id->getName();
        }

        $this->tests[$id] = $status;

        foreach ($data as $file => $lines) {
            if (!$this->filter->isFile($file)) {
                continue;
            }

            foreach ($lines as $k => $v) {
                if ($v == 1) {
                    $this->data[$file][$k][] = $id;
                }
            }
        }
    }

    /**
     * Merges the data from another instance of PHP_CodeCoverage.
     *
     * @param PHP_CodeCoverage $that
     */
    public function merge(PHP_CodeCoverage $that)
    {
        foreach ($that->data as $file => $lines) {
            if (!isset($this->data[$file])) {
                if (!$this->filter->isFiltered($file)) {
                    $this->data[$file] = $lines;
                }

                continue;
            }

            foreach ($lines as $line => $data) {
                if ($data !== NULL) {
                    if (!isset($this->data[$file][$line])) {
                        $this->data[$file][$line] = $data;
                    } else {
                        $this->data[$file][$line] = array_unique(
                          array_merge($this->data[$file][$line], $data)
                        );
                    }
                }
            }
        }

        $this->tests = array_merge($this->tests, $that->getTests());
    }

    /**
     * @param  boolean $flag
     * @throws PHP_CodeCoverage_Exception
     * @since  Method available since Release 1.1.0
     */
    public function setCacheTokens($flag)
    {
        if (!is_bool($flag)) {
            throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory(
              1, 'boolean'
            );
        }

        $this->cacheTokens = $flag;
    }

    /**
     * @param boolean $flag
     * @since Method available since Release 1.1.0
     */
    public function getCacheTokens()
    {
        return $this->cacheTokens;
    }

    /**
     * @param  boolean $flag
     * @throws PHP_CodeCoverage_Exception
     */
    public function setForceCoversAnnotation($flag)
    {
        if (!is_bool($flag)) {
            throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory(
              1, 'boolean'
            );
        }

        $this->forceCoversAnnotation = $flag;
    }

    /**
     * @param  boolean $flag
     * @throws PHP_CodeCoverage_Exception
     */
    public function setMapTestClassNameToCoveredClassName($flag)
    {
        if (!is_bool($flag)) {
            throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory(
              1, 'boolean'
            );
        }

        $this->mapTestClassNameToCoveredClassName = $flag;
    }

    /**
     * @param  boolean $flag
     * @throws PHP_CodeCoverage_Exception
     */
    public function setAddUncoveredFilesFromWhitelist($flag)
    {
        if (!is_bool($flag)) {
            throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory(
              1, 'boolean'
            );
        }

        $this->addUncoveredFilesFromWhitelist = $flag;
    }

    /**
     * @param  boolean $flag
     * @throws PHP_CodeCoverage_Exception
     */
    public function setProcessUncoveredFilesFromWhitelist($flag)
    {
        if (!is_bool($flag)) {
            throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory(
              1, 'boolean'
            );
        }

        $this->processUncoveredFilesFromWhitelist = $flag;
    }

    /**
     * Applies the @covers annotation filtering.
     *
     * @param array $data
     * @param mixed $id
     */
    protected function applyCoversAnnotationFilter(&$data, $id)
    {
        if ($id instanceof PHPUnit_Framework_TestCase) {
            $testClassName    = get_class($id);
            $linesToBeCovered = $this->getLinesToBeCovered(
              $testClassName, $id->getName()
            );

            if ($linesToBeCovered === FALSE) {
                $data = array();
                return;
            }

            if ($this->mapTestClassNameToCoveredClassName &&
                empty($linesToBeCovered)) {
                $testedClass = substr($testClassName, 0, -4);

                if (class_exists($testedClass)) {
                    $class = new ReflectionClass($testedClass);

                    $linesToBeCovered = array(
                      $class->getFileName() => range(
                        $class->getStartLine(), $class->getEndLine()
                      )
                    );
                }
            }
        } else {
            $linesToBeCovered = array();
        }

        if (!empty($linesToBeCovered)) {
            $data = array_intersect_key($data, $linesToBeCovered);

            foreach (array_keys($data) as $filename) {
                $data[$filename] = array_intersect_key(
                  $data[$filename], array_flip($linesToBeCovered[$filename])
                );
            }
        }

        else if ($this->forceCoversAnnotation) {
            $data = array();
        }
    }

    /**
     * Applies the blacklist/whitelist filtering.
     *
     * @param array $data
     */
    protected function applyListsFilter(&$data)
    {
        foreach (array_keys($data) as $filename) {
            if ($this->filter->isFiltered($filename)) {
                unset($data[$filename]);
            }
        }
    }

    /**
     * @since Method available since Release 1.1.0
     */
    protected function initializeFilesThatAreSeenTheFirstTime($data)
    {
        foreach ($data as $file => $lines) {
            if ($this->filter->isFile($file) && !isset($this->data[$file])) {
                $this->data[$file] = array();

                foreach ($lines as $k => $v) {
                    $this->data[$file][$k] = $v == -2 ? NULL : array();
                }
            }
        }
    }

    /**
     * Processes whitelisted files that are not covered.
     */
    protected function addUncoveredFilesFromWhitelist()
    {
        $data           = array();
        $uncoveredFiles = array_diff(
          $this->filter->getWhitelist(), array_keys($this->data)
        );

        foreach ($uncoveredFiles as $uncoveredFile) {
            if (!file_exists($uncoveredFile)) {
                continue;
            }

            if ($this->processUncoveredFilesFromWhitelist) {
                $this->processUncoveredFileFromWhitelist(
                  $uncoveredFile, $data, $uncoveredFiles
                );
            } else {
                $data[$uncoveredFile] = array();

                $lines = count(file($uncoveredFile));

                for ($i = 1; $i <= $lines; $i++) {
                    $data[$uncoveredFile][$i] = -1;
                }
            }
        }

        $this->append($data, 'UNCOVERED_FILES_FROM_WHITELIST');
    }

    /**
     * @param string $uncoveredFile
     * @param array  $data
     * @param array  $uncoveredFiles
     */
    protected function processUncoveredFileFromWhitelist($uncoveredFile, array &$data, array $uncoveredFiles)
    {
        $this->driver->start();
        include_once $uncoveredFile;
        $coverage = $this->driver->stop();

        foreach ($coverage as $file => $fileCoverage) {
            if (!isset($data[$file]) &&
                in_array($file, $uncoveredFiles)) {
                foreach (array_keys($fileCoverage) as $key) {
                    if ($fileCoverage[$key] == 1) {
                        $fileCoverage[$key] = -1;
                    }
                }

                $data[$file] = $fileCoverage;
            }
        }
    }

    /**
     * Returns the files and lines a test method wants to cover.
     *
     * @param  string $className
     * @param  string $methodName
     * @return array
     * @since  Method available since Release 1.2.0
     */
    protected function getLinesToBeCovered($className, $methodName)
    {
        $codeToCoverList = array();
        $result          = array();

        // @codeCoverageIgnoreStart
        if (($pos = strpos($methodName, ' ')) !== FALSE) {
            $methodName = substr($methodName, 0, $pos);
        }
        // @codeCoverageIgnoreEnd

        $class = new ReflectionClass($className);

        try {
            $method = new ReflectionMethod($className, $methodName);
        }

        catch (ReflectionException $e) {
            return array();
        }

        $docComment = substr($class->getDocComment(), 3, -2) . PHP_EOL . substr($method->getDocComment(), 3, -2);

        $templateMethods = array(
          'setUp', 'assertPreConditions', 'assertPostConditions', 'tearDown'
        );

        foreach ($templateMethods as $templateMethod) {
            if ($class->hasMethod($templateMethod)) {
                $reflector   = $class->getMethod($templateMethod);
                $docComment .= PHP_EOL . substr($reflector->getDocComment(), 3, -2);
                unset($reflector);
            }
        }

        if (strpos($docComment, '@coversNothing') !== FALSE) {
            return FALSE;
        }

        $classShortcut = preg_match_all(
          '(@coversDefaultClass\s+(?P<coveredClass>[^\s]++)\s*$)m',
          $class->getDocComment(),
          $matches
        );

        if ($classShortcut) {
            if ($classShortcut > 1) {
                throw new PHP_CodeCoverage_Exception(
                  sprintf(
                    'More than one @coversClass annotation in class or interface "%s".',
                    $className
                  )
                );
            }

            $classShortcut = $matches['coveredClass'][0];
        }

        $match = preg_match_all(
          '(@covers\s+(?P<coveredElement>[^\s()]++)[\s()]*$)m',
          $docComment,
          $matches
        );

        if ($match) {
            foreach ($matches['coveredElement'] as $coveredElement) {
                if ($classShortcut && strncmp($coveredElement, '::', 2) === 0) {
                    $coveredElement = $classShortcut . $coveredElement;
                }

                $codeToCoverList = array_merge(
                  $codeToCoverList,
                  $this->resolveCoversToReflectionObjects($coveredElement)
                );
            }

            foreach ($codeToCoverList as $codeToCover) {
                $fileName = $codeToCover->getFileName();

                if (!isset($result[$fileName])) {
                    $result[$fileName] = array();
                }

                $result[$fileName] = array_unique(
                  array_merge(
                    $result[$fileName],
                    range(
                      $codeToCover->getStartLine(), $codeToCover->getEndLine()
                    )
                  )
                );
            }
        }

        return $result;
    }

    /**
     * @param  string $coveredElement
     * @return array
     * @since  Method available since Release 1.2.0
     */
    protected function resolveCoversToReflectionObjects($coveredElement)
    {
        $codeToCoverList = array();

        if (strpos($coveredElement, '::') !== FALSE) {
            list($className, $methodName) = explode('::', $coveredElement);

            if (isset($methodName[0]) && $methodName[0] == '<') {
                $classes = array($className);

                foreach ($classes as $className) {
                    if (!class_exists($className) &&
                        !interface_exists($className)) {
                        throw new PHP_CodeCoverage_Exception(
                          sprintf(
                            'Trying to @cover not existing class or ' .
                            'interface "%s".',
                            $className
                          )
                        );
                    }

                    $class   = new ReflectionClass($className);
                    $methods = $class->getMethods();
                    $inverse = isset($methodName[1]) && $methodName[1] == '!';

                    if (strpos($methodName, 'protected')) {
                        $visibility = 'isProtected';
                    }

                    else if (strpos($methodName, 'private')) {
                        $visibility = 'isPrivate';
                    }

                    else if (strpos($methodName, 'public')) {
                        $visibility = 'isPublic';
                    }

                    foreach ($methods as $method) {
                        if ($inverse && !$method->$visibility()) {
                            $codeToCoverList[] = $method;
                        }

                        else if (!$inverse && $method->$visibility()) {
                            $codeToCoverList[] = $method;
                        }
                    }
                }
            } else {
                $classes = array($className);

                foreach ($classes as $className) {
                    if ($className == '' && function_exists($methodName)) {
                        $codeToCoverList[] = new ReflectionFunction(
                          $methodName
                        );
                    } else {
                        if (!((class_exists($className) ||
                               interface_exists($className) ||
                               trait_exists($className)) &&
                              method_exists($className, $methodName))) {
                            throw new PHP_CodeCoverage_Exception(
                              sprintf(
                                'Trying to @cover not existing method "%s::%s".',
                                $className,
                                $methodName
                              )
                            );
                        }

                        $codeToCoverList[] = new ReflectionMethod(
                          $className, $methodName
                        );
                    }
                }
            }
        } else {
            $extended = FALSE;

            if (strpos($coveredElement, '<extended>') !== FALSE) {
                $coveredElement = str_replace(
                  '<extended>', '', $coveredElement
                );

                $extended = TRUE;
            }

            $classes = array($coveredElement);

            if ($extended) {
                $classes = array_merge(
                  $classes,
                  class_implements($coveredElement),
                  class_parents($coveredElement)
                );
            }

            foreach ($classes as $className) {
                if (!class_exists($className) &&
                    !interface_exists($className) &&
                    !trait_exists($className)) {
                    throw new PHP_CodeCoverage_Exception(
                      sprintf(
                        'Trying to @cover not existing class or ' .
                        'interface "%s".',
                        $className
                      )
                    );
                }

                $codeToCoverList[] = new ReflectionClass($className);
            }
        }

        return $codeToCoverList;
    }
}
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @subpackage Tests
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.0.0
 */

/**
 * Abstract base class for test case classes.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @subpackage Tests
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.0.0
 */
abstract class PHP_CodeCoverage_TestCase extends PHPUnit_Framework_TestCase
{
    protected function getXdebugDataForBankAccount()
    {
        return array(
          array(
            TEST_FILES_PATH . 'BankAccount.php' => array(
               8 =>  1,
               9 => -2,
              13 => -1,
              14 => -1,
              15 => -1,
              16 => -1,
              18 => -1,
              22 => -1,
              24 => -1,
              25 => -2,
              29 => -1,
              31 => -1,
              32 => -2
            )
          ),
          array(
            TEST_FILES_PATH . 'BankAccount.php' => array(
               8 => 1,
              13 => 1,
              16 => 1,
              29 => 1,
            )
          ),
          array(
            TEST_FILES_PATH . 'BankAccount.php' => array(
               8 => 1,
              13 => 1,
              16 => 1,
              22 => 1,
            )
          ),
          array(
            TEST_FILES_PATH . 'BankAccount.php' => array(
               8 => 1,
              13 => 1,
              14 => 1,
              15 => 1,
              18 => 1,
              22 => 1,
              24 => 1,
              29 => 1,
              31 => 1,
            )
          )
        );
    }

    protected function getCoverageForBankAccount()
    {
        $data = $this->getXdebugDataForBankAccount();

        $stub = $this->getMock('PHP_CodeCoverage_Driver_Xdebug');
        $stub->expects($this->any())
             ->method('stop')
             ->will($this->onConsecutiveCalls(
               $data[0], $data[1], $data[2], $data[3]
             ));

        $coverage = new PHP_CodeCoverage($stub, new PHP_CodeCoverage_Filter);

        $coverage->start(
          new BankAccountTest('testBalanceIsInitiallyZero'), TRUE
        );
        $coverage->stop();

        $coverage->start(
          new BankAccountTest('testBalanceCannotBecomeNegative')
        );
        $coverage->stop();

        $coverage->start(
          new BankAccountTest('testBalanceCannotBecomeNegative2')
        );
        $coverage->stop();

        $coverage->start(
          new BankAccountTest('testDepositWithdrawMoney')
        );
        $coverage->stop();

        return $coverage;
    }

    protected function getCoverageForBankAccountForFirstTwoTests()
    {
        $data = $this->getXdebugDataForBankAccount();

        $stub = $this->getMock('PHP_CodeCoverage_Driver_Xdebug');
        $stub->expects($this->any())
             ->method('stop')
             ->will($this->onConsecutiveCalls(
               $data[0], $data[1]
             ));

        $coverage = new PHP_CodeCoverage($stub, new PHP_CodeCoverage_Filter);

        $coverage->start(
          new BankAccountTest('testBalanceIsInitiallyZero'), TRUE
        );
        $coverage->stop();

        $coverage->start(
          new BankAccountTest('testBalanceCannotBecomeNegative')
        );
        $coverage->stop();

        return $coverage;
    }

    protected function getCoverageForBankAccountForLastTwoTests()
    {
        $data = $this->getXdebugDataForBankAccount();

        $stub = $this->getMock('PHP_CodeCoverage_Driver_Xdebug');
        $stub->expects($this->any())
             ->method('stop')
             ->will($this->onConsecutiveCalls(
               $data[2], $data[3]
             ));

        $coverage = new PHP_CodeCoverage($stub, new PHP_CodeCoverage_Filter);

        $coverage->start(
          new BankAccountTest('testBalanceCannotBecomeNegative2'), TRUE
        );
        $coverage->stop();

        $coverage->start(
          new BankAccountTest('testDepositWithdrawMoney')
        );
        $coverage->stop();

        return $coverage;
    }

    protected function getExpectedDataArrayForBankAccount()
    {
        return array(
          TEST_FILES_PATH . 'BankAccount.php' => array(
            8 => array(
              0 => 'BankAccountTest::testBalanceIsInitiallyZero',
              1 => 'BankAccountTest::testDepositWithdrawMoney'
            ),
            9 => NULL,
            13 => array(),
            14 => array(),
            15 => array(),
            16 => array(),
            18 => array(),
            22 => array(
              0 => 'BankAccountTest::testBalanceCannotBecomeNegative2',
              1 => 'BankAccountTest::testDepositWithdrawMoney'
            ),
            24 => array(
              0 => 'BankAccountTest::testDepositWithdrawMoney',
            ),
            25 => NULL,
            29 => array(
              0 => 'BankAccountTest::testBalanceCannotBecomeNegative',
              1 => 'BankAccountTest::testDepositWithdrawMoney'
            ),
            31 => array(
              0 => 'BankAccountTest::testDepositWithdrawMoney'
            ),
            32 => NULL
          )
        );
    }

    protected function getCoverageForFileWithIgnoredLines()
    {
        $coverage = new PHP_CodeCoverage(
          $this->setUpXdebugStubForFileWithIgnoredLines(),
          new PHP_CodeCoverage_Filter
        );

        $coverage->start('FileWithIgnoredLines', TRUE);
        $coverage->stop();

        return $coverage;
    }

    protected function setUpXdebugStubForFileWithIgnoredLines()
    {
        $stub = $this->getMock('PHP_CodeCoverage_Driver_Xdebug');
        $stub->expects($this->any())
             ->method('stop')
             ->will($this->returnValue(
               array(
                 TEST_FILES_PATH . 'source_with_ignore.php' => array(
                   2 => 1,
                   4 => -1,
                   6 => -1,
                   7 => 1
                 )
               )
            ));

        return $stub;
    }

    protected function getCoverageForClassWithAnonymousFunction()
    {
        $coverage = new PHP_CodeCoverage(
          $this->setUpXdebugStubForClassWithAnonymousFunction(),
          new PHP_CodeCoverage_Filter
        );

        $coverage->start('ClassWithAnonymousFunction', TRUE);
        $coverage->stop();

        return $coverage;
    }

    protected function setUpXdebugStubForClassWithAnonymousFunction()
    {
        $stub = $this->getMock('PHP_CodeCoverage_Driver_Xdebug');
        $stub->expects($this->any())
             ->method('stop')
             ->will($this->returnValue(
               array(
                 TEST_FILES_PATH . 'source_with_class_and_anonymous_function.php' => array(
                    7  => 1,
                    9  => 1,
                    10 => -1,
                    11 => 1,
                    12 => 1,
                    13 => 1,
                    14 => 1,
                    17 => 1,
                    18 => 1
                 )
               )
            ));

        return $stub;
    }
}
<?php
if ($neverHappens) {
    print '*';
}
<?php
class CoverageNotPrivateTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers CoveredClass::<!private>
     */
    public function testSomething()
    {
        $o = new CoveredClass;
        $o->publicMethod();
    }
}
<?php
class CoverageMethodParenthesesWhitespaceTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers CoveredClass::publicMethod ( ) 
     */
    public function testSomething()
    {
        $o = new CoveredClass;
        $o->publicMethod();
    }
}
<?php
class NamespaceCoverageClassTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers Foo\CoveredClass
     */
    public function testSomething()
    {
        $o = new Foo\CoveredClass;
        $o->publicMethod();
    }
}
<?php
class CoveredParentClass
{
    private function privateMethod()
    {
    }

    protected function protectedMethod()
    {
        $this->privateMethod();
    }

    public function publicMethod()
    {
        $this->protectedMethod();
    }
}

class CoveredClass extends CoveredParentClass
{
    private function privateMethod()
    {
    }

    protected function protectedMethod()
    {
        parent::protectedMethod();
        $this->privateMethod();
    }

    public function publicMethod()
    {
        parent::publicMethod();
        $this->protectedMethod();
    }
}
<?php
function globalFunction()
{
}
<?php
class NamespaceCoverageNotPublicTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers Foo\CoveredClass::<!public>
     */
    public function testSomething()
    {
        $o = new Foo\CoveredClass;
        $o->publicMethod();
    }
}
<?php
class CoveragePublicTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers CoveredClass::<public>
     */
    public function testSomething()
    {
        $o = new CoveredClass;
        $o->publicMethod();
    }
}
<?php
class CoverageClassExtendedTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers CoveredClass<extended>
     */
    public function testSomething()
    {
        $o = new CoveredClass;
        $o->publicMethod();
    }
}
<?php
class NotExistingCoveredElementTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers NotExistingClass
     */
    public function testOne()
    {
    }

    /**
     * @covers NotExistingClass::notExistingMethod
     */
    public function testTwo()
    {
    }

    /**
     * @covers NotExistingClass::<public>
     */
    public function testThree()
    {
    }
}
<?php
class CoverageNotPublicTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers CoveredClass::<!public>
     */
    public function testSomething()
    {
        $o = new CoveredClass;
        $o->publicMethod();
    }
}
<?php
class NamespaceCoveragePrivateTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers Foo\CoveredClass::<private>
     */
    public function testSomething()
    {
        $o = new Foo\CoveredClass;
        $o->publicMethod();
    }
}
<?php
class NamespaceCoverageNotProtectedTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers Foo\CoveredClass::<!protected>
     */
    public function testSomething()
    {
        $o = new Foo\CoveredClass;
        $o->publicMethod();
    }
}
<?php
class CoverageFunctionParenthesesWhitespaceTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers ::globalFunction ( ) 
     */
    public function testSomething()
    {
        globalFunction();
    }
}
<?php
class CoverageFunctionParenthesesTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers ::globalFunction()
     */
    public function testSomething()
    {
        globalFunction();
    }
}
<?php
namespace Foo;

class CoveredParentClass
{
    private function privateMethod()
    {
    }

    protected function protectedMethod()
    {
        $this->privateMethod();
    }

    public function publicMethod()
    {
        $this->protectedMethod();
    }
}

class CoveredClass extends CoveredParentClass
{
    private function privateMethod()
    {
    }

    protected function protectedMethod()
    {
        parent::protectedMethod();
        $this->privateMethod();
    }

    public function publicMethod()
    {
        parent::publicMethod();
        $this->protectedMethod();
    }
}
<?php
class CoverageNotProtectedTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers CoveredClass::<!protected>
     */
    public function testSomething()
    {
        $o = new CoveredClass;
        $o->publicMethod();
    }
}
<?php
class CoverageMethodParenthesesTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers CoveredClass::publicMethod()
     */
    public function testSomething()
    {
        $o = new CoveredClass;
        $o->publicMethod();
    }
}
<?php

/**
 * @coversDefaultClass \NamespaceOne
 * @coversDefaultClass \AnotherDefault\Name\Space\Does\Not\Work
 */
class CoverageTwoDefaultClassAnnotations
{

    /**
     * @covers Foo\CoveredClass::<public>
     */
    public function testSomething()
    {
        $o = new Foo\CoveredClass;
        $o->publicMethod();
    }

}
<?php
/**
 * @coversDefaultClass \Foo\CoveredClass
 */
class NamespaceCoverageCoversClassPublicTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers ::publicMethod
     */
    public function testSomething()
    {
        $o = new Foo\CoveredClass;
        $o->publicMethod();
    }
}

<?php
class NamespaceCoverageNotPrivateTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers Foo\CoveredClass::<!private>
     */
    public function testSomething()
    {
        $o = new Foo\CoveredClass;
        $o->publicMethod();
    }
}
<?php

class CoverageMethodOneLineAnnotationTest extends PHPUnit_Framework_TestCase
{
    /** @covers CoveredClass::publicMethod */
    public function testSomething()
    {
        $o = new CoveredClass;
        $o->publicMethod();
    }
}

<?php
class NamespaceCoverageMethodTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers Foo\CoveredClass::publicMethod
     */
    public function testSomething()
    {
        $o = new Foo\CoveredClass;
        $o->publicMethod();
    }
}
<?php
class CoverageProtectedTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers CoveredClass::<protected>
     */
    public function testSomething()
    {
        $o = new CoveredClass;
        $o->publicMethod();
    }
}
<?php
namespace bar\baz;

/**
 * Represents foo.
 */
class Foo
{
}

/**
 * @param mixed $bar
 */
function &foo($bar)
{
    $baz = function() {};
    $a   = TRUE ? TRUE : FALSE;
    $b = "{$a}";
    $c = "${b}";
}
<?php
class NamespaceCoveragePublicTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers Foo\CoveredClass::<public>
     */
    public function testSomething()
    {
        $o = new Foo\CoveredClass;
        $o->publicMethod();
    }
}
<?php
class BankAccount
{
    protected $balance = 0;

    public function getBalance()
    {
        return $this->balance;
    }

    protected function setBalance($balance)
    {
        if ($balance >= 0) {
            $this->balance = $balance;
        } else {
            throw new RuntimeException;
        }
    }

    public function depositMoney($balance)
    {
        $this->setBalance($this->getBalance() + $balance);

        return $this->getBalance();
    }

    public function withdrawMoney($balance)
    {
        $this->setBalance($this->getBalance() - $balance);

        return $this->getBalance();
    }
}
<?php
class NamespaceCoverageClassExtendedTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers Foo\CoveredClass<extended>
     */
    public function testSomething()
    {
        $o = new Foo\CoveredClass;
        $o->publicMethod();
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<coverage generated="%i">
  <project timestamp="%i">
    <file name="%s/source_with_ignore.php">
      <class name="Foo" namespace="global">
        <metrics methods="1" coveredmethods="0" conditionals="0" coveredconditionals="0" statements="0" coveredstatements="0" elements="1" coveredelements="0"/>
      </class>
      <class name="Bar" namespace="global">
        <metrics methods="1" coveredmethods="0" conditionals="0" coveredconditionals="0" statements="0" coveredstatements="0" elements="1" coveredelements="0"/>
      </class>
      <line num="2" type="stmt" count="1"/>
      <line num="6" type="stmt" count="0"/>
      <metrics loc="38" ncloc="26" classes="2" methods="0" coveredmethods="0" conditionals="0" coveredconditionals="0" statements="2" coveredstatements="1" elements="2" coveredelements="1"/>
    </file>
    <metrics files="1" loc="38" ncloc="26" classes="2" methods="0" coveredmethods="0" conditionals="0" coveredconditionals="0" statements="2" coveredstatements="1" elements="2" coveredelements="1"/>
  </project>
</coverage>
<?php
/**
 * @coversDefaultClass \Foo\CoveredClass
 */
class NamespaceCoverageCoversClassTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers ::privateMethod
     * @covers ::protectedMethod
     * @covers ::publicMethod
     * @covers \Foo\CoveredParentClass::privateMethod
     * @covers \Foo\CoveredParentClass::protectedMethod
     * @covers \Foo\CoveredParentClass::publicMethod
     */
    public function testSomething()
    {
        $o = new Foo\CoveredClass;
        $o->publicMethod();
    }
}

<?php
class CoverageClassTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers CoveredClass
     */
    public function testSomething()
    {
        $o = new CoveredClass;
        $o->publicMethod();
    }
}
<?php

class CoveredClassWithAnonymousFunctionInStaticMethod
{
    public static function runAnonymous()
    {
        $filter = array('abc124', 'abc123', '123');

        array_walk(
            $filter,
            function (&$val, $key) {
                $val = preg_replace('|[^0-9]|', '', $val);
            }
        );

        // Should be covered
        $extravar = true;
    }
}
<?php
class CoverageNothingTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers CoveredClass::publicMethod
     * @coversNothing
     */
    public function testSomething()
    {
        $o = new CoveredClass;
        $o->publicMethod();
    }
}
<?php
/**
 * Represents foo.
 */
class Foo
{
}

/**
 * @param mixed $bar
 */
function &foo($bar)
{
    $baz = function() {};
    $a   = TRUE ? TRUE : FALSE;
    $b = "{$a}";
    $c = "${b}";
}
<?xml version="1.0" encoding="UTF-8"?>
<coverage generated="%i">
  <project timestamp="%i">
    <file name="%s/source_with_class_and_anonymous_function.php">
      <class name="CoveredClassWithAnonymousFunctionInStaticMethod" namespace="global">
        <metrics methods="2" coveredmethods="2" conditionals="0" coveredconditionals="0" statements="12" coveredstatements="11" elements="14" coveredelements="13"/>
      </class>
      <line num="5" type="method" name="runAnonymous" crap="1.04" count="1"/>
      <line num="7" type="stmt" count="1"/>
      <line num="9" type="stmt" count="1"/>
      <line num="10" type="stmt" count="0"/>
      <line num="11" type="method" name="anonymous function" crap="1" count="1"/>
      <line num="12" type="stmt" count="1"/>
      <line num="13" type="stmt" count="1"/>
      <line num="14" type="stmt" count="1"/>
      <line num="17" type="stmt" count="1"/>
      <line num="18" type="stmt" count="1"/>
      <metrics loc="19" ncloc="17" classes="1" methods="2" coveredmethods="1" conditionals="0" coveredconditionals="0" statements="9" coveredstatements="8" elements="11" coveredelements="9"/>
    </file>
    <metrics files="1" loc="19" ncloc="17" classes="1" methods="2" coveredmethods="1" conditionals="0" coveredconditionals="0" statements="9" coveredstatements="8" elements="11" coveredelements="9"/>
  </project>
</coverage>
<?php
class CoveragePrivateTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers CoveredClass::<private>
     */
    public function testSomething()
    {
        $o = new CoveredClass;
        $o->publicMethod();
    }
}
<?php
class CoverageFunctionTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers ::globalFunction
     */
    public function testSomething()
    {
        globalFunction();
    }
}
<?php
class CoverageNoneTest extends PHPUnit_Framework_TestCase
{
    public function testSomething()
    {
        $o = new CoveredClass;
        $o->publicMethod();
    }
}
<?php
class NamespaceCoverageProtectedTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers Foo\CoveredClass::<protected>
     */
    public function testSomething()
    {
        $o = new Foo\CoveredClass;
        $o->publicMethod();
    }
}
<?php

/** Docblock */
interface Foo {
    public function bar();
}

class Foo
{
    public function bar()
    {
    }
}

function baz()
{
    // a one-line comment
    print '*'; // a one-line comment

    /* a one-line comment */
    print '*'; /* a one-line comment */

    /* a one-line comment
     */
    print '*'; /* a one-line comment
    */

    print '*'; // @codeCoverageIgnore

    print '*'; // @codeCoverageIgnoreStart
    print '*';
    print '*'; // @codeCoverageIgnoreEnd

    print '*';
}
<?php
class CoverageMethodTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers CoveredClass::publicMethod
     */
    public function testSomething()
    {
        $o = new CoveredClass;
        $o->publicMethod();
    }
}
<?php
require_once 'BankAccount.php';

class BankAccountTest extends PHPUnit_Framework_TestCase
{
    protected $ba;

    protected function setUp()
    {
        $this->ba = new BankAccount;
    }

    /**
     * @covers BankAccount::getBalance
     */
    public function testBalanceIsInitiallyZero()
    {
        $this->assertEquals(0, $this->ba->getBalance());
    }

    /**
     * @covers BankAccount::withdrawMoney
     */
    public function testBalanceCannotBecomeNegative()
    {
        try {
            $this->ba->withdrawMoney(1);
        }

        catch (RuntimeException $e) {
            $this->assertEquals(0, $this->ba->getBalance());

            return;
        }

        $this->fail();
    }

    /**
     * @covers BankAccount::depositMoney
     */
    public function testBalanceCannotBecomeNegative2()
    {
        try {
            $this->ba->depositMoney(-1);
        }

        catch (RuntimeException $e) {
            $this->assertEquals(0, $this->ba->getBalance());

            return;
        }

        $this->fail();
    }

    /**
     * @covers BankAccount::getBalance
     * @covers BankAccount::depositMoney
     * @covers BankAccount::withdrawMoney
     */
    public function testDepositWithdrawMoney()
    {
        $this->assertEquals(0, $this->ba->getBalance());
        $this->ba->depositMoney(1);
        $this->assertEquals(1, $this->ba->getBalance());
        $this->ba->withdrawMoney(1);
        $this->assertEquals(0, $this->ba->getBalance());
    }
}
<?php
if ($neverHappens) {
    // @codeCoverageIgnoreStart
    print '*';
    // @codeCoverageIgnoreEnd
}

/**
 * @codeCoverageIgnore
 */
class Foo
{
    public function bar()
    {
    }
}

class Bar
{
    /**
     * @codeCoverageIgnore
     */
    public function foo()
    {
    }
}

function baz()
{
    print '*'; // @codeCoverageIgnore
}

interface Bor {

    public function foo();

}

<?xml version="1.0" encoding="UTF-8"?>
<coverage generated="%i">
  <project timestamp="%i" name="BankAccount">
    <file name="%s/BankAccount.php">
      <class name="BankAccount" namespace="global">
        <metrics methods="4" coveredmethods="3" conditionals="0" coveredconditionals="0" statements="10" coveredstatements="5" elements="14" coveredelements="8"/>
      </class>
      <line num="6" type="method" name="getBalance" crap="1" count="2"/>
      <line num="8" type="stmt" count="2"/>
      <line num="11" type="method" name="setBalance" crap="6" count="0"/>
      <line num="13" type="stmt" count="0"/>
      <line num="14" type="stmt" count="0"/>
      <line num="15" type="stmt" count="0"/>
      <line num="16" type="stmt" count="0"/>
      <line num="18" type="stmt" count="0"/>
      <line num="20" type="method" name="depositMoney" crap="1" count="2"/>
      <line num="22" type="stmt" count="2"/>
      <line num="24" type="stmt" count="1"/>
      <line num="27" type="method" name="withdrawMoney" crap="1" count="2"/>
      <line num="29" type="stmt" count="2"/>
      <line num="31" type="stmt" count="1"/>
      <metrics loc="33" ncloc="33" classes="1" methods="4" coveredmethods="3" conditionals="0" coveredconditionals="0" statements="10" coveredstatements="5" elements="14" coveredelements="8"/>
    </file>
    <metrics files="1" loc="33" ncloc="33" classes="1" methods="4" coveredmethods="3" conditionals="0" coveredconditionals="0" statements="10" coveredstatements="5" elements="14" coveredelements="8"/>
  </project>
</coverage>
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @subpackage Tests
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.0.0
 */

if (!defined('TEST_FILES_PATH')) {
    define(
      'TEST_FILES_PATH',
      dirname(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR .
      '_files' . DIRECTORY_SEPARATOR
    );
}

/**
 * Tests for the PHP_CodeCoverage_Filter class.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @subpackage Tests
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.0.0
 */
class PHP_CodeCoverage_FilterTest extends PHPUnit_Framework_TestCase
{
    protected $filter;
    protected $files;

    protected function setUp()
    {
        $this->filter = unserialize('O:23:"PHP_CodeCoverage_Filter":0:{}');

        $this->files = array(
          TEST_FILES_PATH . 'BankAccount.php',
          TEST_FILES_PATH . 'BankAccountTest.php',
          TEST_FILES_PATH . 'CoverageClassExtendedTest.php',
          TEST_FILES_PATH . 'CoverageClassTest.php',
          TEST_FILES_PATH . 'CoverageFunctionParenthesesTest.php',
          TEST_FILES_PATH . 'CoverageFunctionParenthesesWhitespaceTest.php',
          TEST_FILES_PATH . 'CoverageFunctionTest.php',
          TEST_FILES_PATH . 'CoverageMethodOneLineAnnotationTest.php',
          TEST_FILES_PATH . 'CoverageMethodParenthesesTest.php',
          TEST_FILES_PATH . 'CoverageMethodParenthesesWhitespaceTest.php',
          TEST_FILES_PATH . 'CoverageMethodTest.php',
          TEST_FILES_PATH . 'CoverageNoneTest.php',
          TEST_FILES_PATH . 'CoverageNotPrivateTest.php',
          TEST_FILES_PATH . 'CoverageNotProtectedTest.php',
          TEST_FILES_PATH . 'CoverageNotPublicTest.php',
          TEST_FILES_PATH . 'CoverageNothingTest.php',
          TEST_FILES_PATH . 'CoveragePrivateTest.php',
          TEST_FILES_PATH . 'CoverageProtectedTest.php',
          TEST_FILES_PATH . 'CoveragePublicTest.php',
          TEST_FILES_PATH . 'CoverageTwoDefaultClassAnnotations.php',
          TEST_FILES_PATH . 'CoveredClass.php',
          TEST_FILES_PATH . 'CoveredFunction.php',
          TEST_FILES_PATH . 'NamespaceCoverageClassExtendedTest.php',
          TEST_FILES_PATH . 'NamespaceCoverageClassTest.php',
          TEST_FILES_PATH . 'NamespaceCoverageCoversClassPublicTest.php',
          TEST_FILES_PATH . 'NamespaceCoverageCoversClassTest.php',
          TEST_FILES_PATH . 'NamespaceCoverageMethodTest.php',
          TEST_FILES_PATH . 'NamespaceCoverageNotPrivateTest.php',
          TEST_FILES_PATH . 'NamespaceCoverageNotProtectedTest.php',
          TEST_FILES_PATH . 'NamespaceCoverageNotPublicTest.php',
          TEST_FILES_PATH . 'NamespaceCoveragePrivateTest.php',
          TEST_FILES_PATH . 'NamespaceCoverageProtectedTest.php',
          TEST_FILES_PATH . 'NamespaceCoveragePublicTest.php',
          TEST_FILES_PATH . 'NamespaceCoveredClass.php',
          TEST_FILES_PATH . 'NotExistingCoveredElementTest.php',
          TEST_FILES_PATH . 'source_with_class_and_anonymous_function.php',
          TEST_FILES_PATH . 'source_with_ignore.php',
          TEST_FILES_PATH . 'source_with_namespace.php',
          TEST_FILES_PATH . 'source_with_oneline_annotations.php',
          TEST_FILES_PATH . 'source_without_ignore.php',
          TEST_FILES_PATH . 'source_without_namespace.php'
        );
    }

    /**
     * @covers PHP_CodeCoverage_Filter::addFileToBlacklist
     * @covers PHP_CodeCoverage_Filter::getBlacklist
     */
    public function testAddingAFileToTheBlacklistWorks()
    {
        $this->filter->addFileToBlacklist($this->files[0]);

        $this->assertEquals(
          array($this->files[0]), $this->filter->getBlacklist()
        );
    }

    /**
     * @covers PHP_CodeCoverage_Filter::removeFileFromBlacklist
     * @covers PHP_CodeCoverage_Filter::getBlacklist
     */
    public function testRemovingAFileFromTheBlacklistWorks()
    {
        $this->filter->addFileToBlacklist($this->files[0]);
        $this->filter->removeFileFromBlacklist($this->files[0]);

        $this->assertEquals(array(), $this->filter->getBlacklist());
    }

    /**
     * @covers  PHP_CodeCoverage_Filter::addDirectoryToBlacklist
     * @covers  PHP_CodeCoverage_Filter::getBlacklist
     * @depends testAddingAFileToTheBlacklistWorks
     */
    public function testAddingADirectoryToTheBlacklistWorks()
    {
        $this->filter->addDirectoryToBlacklist(TEST_FILES_PATH);

        $blacklist = $this->filter->getBlacklist();
        sort($blacklist);

        $this->assertEquals($this->files, $blacklist);
    }

    /**
     * @covers PHP_CodeCoverage_Filter::addFilesToBlacklist
     * @covers PHP_CodeCoverage_Filter::getBlacklist
     */
    public function testAddingFilesToTheBlacklistWorks()
    {
        $facade = new File_Iterator_Facade;
        $files  = $facade->getFilesAsArray(
          TEST_FILES_PATH, $suffixes = '.php'
        );

        $this->filter->addFilesToBlacklist($files);

        $blacklist = $this->filter->getBlacklist();
        sort($blacklist);

        $this->assertEquals($this->files, $blacklist);
    }

    /**
     * @covers  PHP_CodeCoverage_Filter::removeDirectoryFromBlacklist
     * @covers  PHP_CodeCoverage_Filter::getBlacklist
     * @depends testAddingADirectoryToTheBlacklistWorks
     */
    public function testRemovingADirectoryFromTheBlacklistWorks()
    {
        $this->filter->addDirectoryToBlacklist(TEST_FILES_PATH);
        $this->filter->removeDirectoryFromBlacklist(TEST_FILES_PATH);

        $this->assertEquals(array(), $this->filter->getBlacklist());
    }

    /**
     * @covers PHP_CodeCoverage_Filter::addFileToWhitelist
     * @covers PHP_CodeCoverage_Filter::getWhitelist
     */
    public function testAddingAFileToTheWhitelistWorks()
    {
        $this->filter->addFileToWhitelist($this->files[0]);

        $this->assertEquals(
          array($this->files[0]), $this->filter->getWhitelist()
        );
    }

    /**
     * @covers PHP_CodeCoverage_Filter::removeFileFromWhitelist
     * @covers PHP_CodeCoverage_Filter::getWhitelist
     */
    public function testRemovingAFileFromTheWhitelistWorks()
    {
        $this->filter->addFileToWhitelist($this->files[0]);
        $this->filter->removeFileFromWhitelist($this->files[0]);

        $this->assertEquals(array(), $this->filter->getWhitelist());
    }

    /**
     * @covers  PHP_CodeCoverage_Filter::addDirectoryToWhitelist
     * @covers  PHP_CodeCoverage_Filter::getWhitelist
     * @depends testAddingAFileToTheWhitelistWorks
     */
    public function testAddingADirectoryToTheWhitelistWorks()
    {
        $this->filter->addDirectoryToWhitelist(TEST_FILES_PATH);

        $whitelist = $this->filter->getWhitelist();
        sort($whitelist);

        $this->assertEquals($this->files, $whitelist);
    }

    /**
     * @covers PHP_CodeCoverage_Filter::addFilesToWhitelist
     * @covers PHP_CodeCoverage_Filter::getBlacklist
     */
    public function testAddingFilesToTheWhitelistWorks()
    {
        $facade = new File_Iterator_Facade;
        $files  = $facade->getFilesAsArray(
          TEST_FILES_PATH, $suffixes = '.php'
        );

        $this->filter->addFilesToWhitelist($files);

        $whitelist = $this->filter->getWhitelist();
        sort($whitelist);

        $this->assertEquals($this->files, $whitelist);
    }

    /**
     * @covers  PHP_CodeCoverage_Filter::removeDirectoryFromWhitelist
     * @covers  PHP_CodeCoverage_Filter::getWhitelist
     * @depends testAddingADirectoryToTheWhitelistWorks
     */
    public function testRemovingADirectoryFromTheWhitelistWorks()
    {
        $this->filter->addDirectoryToWhitelist(TEST_FILES_PATH);
        $this->filter->removeDirectoryFromWhitelist(TEST_FILES_PATH);

        $this->assertEquals(array(), $this->filter->getWhitelist());
    }

    /**
     * @covers PHP_CodeCoverage_Filter::isFile
     */
    public function testIsFile()
    {
        $this->assertFalse($this->filter->isFile('eval()\'d code'));
        $this->assertFalse($this->filter->isFile('runtime-created function'));
        $this->assertFalse($this->filter->isFile('assert code'));
        $this->assertFalse($this->filter->isFile('regexp code'));
        $this->assertTrue($this->filter->isFile('filename'));
    }

    /**
     * @covers PHP_CodeCoverage_Filter::isFiltered
     */
    public function testBlacklistedFileIsFiltered()
    {
        $this->filter->addFileToBlacklist($this->files[0]);
        $this->assertTrue($this->filter->isFiltered($this->files[0]));
    }

    /**
     * @covers PHP_CodeCoverage_Filter::isFiltered
     */
    public function testWhitelistedFileIsNotFiltered()
    {
        $this->filter->addFileToWhitelist($this->files[0]);
        $this->assertFalse($this->filter->isFiltered($this->files[0]));
    }

    /**
     * @covers PHP_CodeCoverage_Filter::isFiltered
     */
    public function testNotWhitelistedFileIsFiltered()
    {
        $this->filter->addFileToWhitelist($this->files[0]);
        $this->assertTrue($this->filter->isFiltered($this->files[1]));
    }
}
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @subpackage Tests
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.0.0
 */

if (!defined('TEST_FILES_PATH')) {
    define(
      'TEST_FILES_PATH',
      dirname(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR .
      '_files' . DIRECTORY_SEPARATOR
    );
}

require_once TEST_FILES_PATH . 'CoverageClassExtendedTest.php';
require_once TEST_FILES_PATH . 'CoverageClassTest.php';
require_once TEST_FILES_PATH . 'CoverageFunctionTest.php';
require_once TEST_FILES_PATH . 'CoverageFunctionParenthesesTest.php';
require_once TEST_FILES_PATH . 'CoverageFunctionParenthesesWhitespaceTest.php';
require_once TEST_FILES_PATH . 'CoverageMethodTest.php';
require_once TEST_FILES_PATH . 'CoverageMethodOneLineAnnotationTest.php';
require_once TEST_FILES_PATH . 'CoverageMethodParenthesesTest.php';
require_once TEST_FILES_PATH . 'CoverageMethodParenthesesWhitespaceTest.php';
require_once TEST_FILES_PATH . 'CoverageNoneTest.php';
require_once TEST_FILES_PATH . 'CoverageNotPrivateTest.php';
require_once TEST_FILES_PATH . 'CoverageNotProtectedTest.php';
require_once TEST_FILES_PATH . 'CoverageNotPublicTest.php';
require_once TEST_FILES_PATH . 'CoveragePrivateTest.php';
require_once TEST_FILES_PATH . 'CoverageProtectedTest.php';
require_once TEST_FILES_PATH . 'CoveragePublicTest.php';
require_once TEST_FILES_PATH . 'CoverageTwoDefaultClassAnnotations.php';
require_once TEST_FILES_PATH . 'CoveredClass.php';
require_once TEST_FILES_PATH . 'CoveredFunction.php';
require_once TEST_FILES_PATH . 'NamespaceCoverageClassExtendedTest.php';
require_once TEST_FILES_PATH . 'NamespaceCoverageClassTest.php';
require_once TEST_FILES_PATH . 'NamespaceCoverageCoversClassTest.php';
require_once TEST_FILES_PATH . 'NamespaceCoverageCoversClassPublicTest.php';
require_once TEST_FILES_PATH . 'NamespaceCoverageMethodTest.php';
require_once TEST_FILES_PATH . 'NamespaceCoverageNotPrivateTest.php';
require_once TEST_FILES_PATH . 'NamespaceCoverageNotProtectedTest.php';
require_once TEST_FILES_PATH . 'NamespaceCoverageNotPublicTest.php';
require_once TEST_FILES_PATH . 'NamespaceCoveragePrivateTest.php';
require_once TEST_FILES_PATH . 'NamespaceCoverageProtectedTest.php';
require_once TEST_FILES_PATH . 'NamespaceCoveragePublicTest.php';
require_once TEST_FILES_PATH . 'NamespaceCoveredClass.php';
require_once TEST_FILES_PATH . 'NotExistingCoveredElementTest.php';
require_once TEST_FILES_PATH . 'CoverageNothingTest.php';
/**
 * Tests for the PHP_CodeCoverage_Util class.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @subpackage Tests
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.0.0
 */
class PHP_CodeCoverage_UtilTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers PHP_CodeCoverage_Util::getLinesToBeIgnored
     */
    public function testGetLinesToBeIgnored()
    {
        $this->assertEquals(
          array(
             1 => TRUE,
             3 => TRUE,
             4 => TRUE,
             5 => TRUE,
             7 => TRUE,
             8 => TRUE,
             9 => TRUE,
            10 => TRUE,
            11 => TRUE,
            12 => TRUE,
            13 => TRUE,
            14 => TRUE,
            15 => TRUE,
            16 => TRUE,
            17 => TRUE,
            18 => TRUE,
            19 => TRUE,
            20 => TRUE,
            21 => TRUE,
            22 => TRUE,
            23 => TRUE,
            24 => TRUE,
            25 => TRUE,
            26 => TRUE,
            27 => TRUE,
            30 => TRUE,
            32 => TRUE,
            33 => TRUE,
            34 => TRUE,
            35 => TRUE,
            36 => TRUE,
            37 => TRUE,
            38 => TRUE,
          ),
          PHP_CodeCoverage_Util::getLinesToBeIgnored(
            TEST_FILES_PATH . 'source_with_ignore.php'
          )
        );
    }

    /**
     * @covers PHP_CodeCoverage_Util::getLinesToBeIgnored
     */
    public function testGetLinesToBeIgnored2()
    {
        $this->assertEquals(
          array(1 => TRUE),
          PHP_CodeCoverage_Util::getLinesToBeIgnored(
            TEST_FILES_PATH . 'source_without_ignore.php'
          )
        );
    }

    public function testGetLinesToBeIgnored3()
    {
        $this->assertEquals(
          array(
            1 => TRUE,
            2 => TRUE,
            8 => TRUE,
            15 => TRUE,
            3 => TRUE,
            4 => TRUE,
            19 => TRUE,
            16 => TRUE
          ),
          PHP_CodeCoverage_Util::getLinesToBeIgnored(
            TEST_FILES_PATH . 'source_with_class_and_anonymous_function.php'
          )
        );
    }

    /**
     * @covers PHP_CodeCoverage_Util::getLinesToBeIgnored
     */
    public function testGetLinesToBeIgnoredOneLineAnnotations()
    {
        $this->assertEquals(
          array(
            1 => TRUE,
            2 => TRUE,
            3 => TRUE,
            4 => TRUE,
            5 => TRUE,
            6 => TRUE,
            7 => TRUE,
            8 => TRUE,
            9 => TRUE,
            10 => TRUE,
            11 => TRUE,
            12 => TRUE,
            13 => TRUE,
            14 => TRUE,
            17 => TRUE,
            19 => TRUE,
            22 => TRUE,
            23 => TRUE,
            27 => TRUE,
            28 => TRUE,
            29 => TRUE,
            30 => TRUE,
            31 => TRUE,
            32 => TRUE,
            33 => TRUE,
          ),
          PHP_CodeCoverage_Util::getLinesToBeIgnored(
            TEST_FILES_PATH . 'source_with_oneline_annotations.php'
          )
        );
    }


    /**
     * @covers PHP_CodeCoverage_Util::percent
     */
    public function testPercent()
    {
        $this->assertEquals(100, PHP_CodeCoverage_Util::percent(100, 0));
        $this->assertEquals(100, PHP_CodeCoverage_Util::percent(100, 100));
        $this->assertEquals(
          '100.00%', PHP_CodeCoverage_Util::percent(100, 100, TRUE)
        );
    }
}
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @subpackage Tests
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.0.0
 */

if (!defined('TEST_FILES_PATH')) {
    define(
      'TEST_FILES_PATH',
      dirname(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR .
      '_files' . DIRECTORY_SEPARATOR
    );
}

require_once TEST_FILES_PATH . '../TestCase.php';

/**
 * Tests for the PHP_CodeCoverage_Report_Clover class.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @subpackage Tests
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.0.0
 */
class PHP_CodeCoverage_Report_CloverTest extends PHP_CodeCoverage_TestCase
{
    /**
     * @covers PHP_CodeCoverage_Report_Clover
     */
    public function testCloverForBankAccountTest()
    {
        $clover = new PHP_CodeCoverage_Report_Clover;

        $this->assertStringMatchesFormatFile(
          TEST_FILES_PATH . 'BankAccount-clover.xml',
          $clover->process($this->getCoverageForBankAccount(), NULL, 'BankAccount')
        );
    }

    /**
     * @covers PHP_CodeCoverage_Report_Clover
     */
    public function testCloverForFileWithIgnoredLines()
    {
        $clover = new PHP_CodeCoverage_Report_Clover;

        $this->assertStringMatchesFormatFile(
          TEST_FILES_PATH . 'ignored-lines-clover.xml',
          $clover->process($this->getCoverageForFileWithIgnoredLines())
        );
    }

    /**
     * @covers PHP_CodeCoverage_Report_Clover
     */
    public function testCloverForClassWithAnonymousFunction()
    {
        $clover = new PHP_CodeCoverage_Report_Clover;

        $this->assertStringMatchesFormatFile(
          TEST_FILES_PATH . 'class-with-anonymous-function-clover.xml',
          $clover->process($this->getCoverageForClassWithAnonymousFunction())
        );
    }
}
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @subpackage Tests
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.1.0
 */

if (!defined('TEST_FILES_PATH')) {
    define(
      'TEST_FILES_PATH',
      dirname(dirname(dirname(dirname(__FILE__)))) . DIRECTORY_SEPARATOR .
      '_files' . DIRECTORY_SEPARATOR
    );
}

require_once TEST_FILES_PATH . '../TestCase.php';

/**
 * Tests for the PHP_CodeCoverage_Report_Factory class.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @subpackage Tests
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.1.0
 */
class PHP_CodeCoverage_Report_FactoryTest extends PHP_CodeCoverage_TestCase
{
    protected $factory;

    protected function setUp()
    {
        $this->factory = new PHP_CodeCoverage_Report_Factory;
    }

    public function testSomething()
    {
        $root = $this->getCoverageForBankAccount()->getReport();

        $expectedPath = rtrim(TEST_FILES_PATH, DIRECTORY_SEPARATOR);
        $this->assertEquals($expectedPath, $root->getName());
        $this->assertEquals($expectedPath, $root->getPath());
        $this->assertEquals(10, $root->getNumExecutableLines());
        $this->assertEquals(5, $root->getNumExecutedLines());
        $this->assertEquals(1, $root->getNumClasses());
        $this->assertEquals(0, $root->getNumTestedClasses());
        $this->assertEquals(4, $root->getNumMethods());
        $this->assertEquals(3, $root->getNumTestedMethods());
        $this->assertEquals('0.00%', $root->getTestedClassesPercent());
        $this->assertEquals('75.00%', $root->getTestedMethodsPercent());
        $this->assertEquals('50.00%', $root->getLineExecutedPercent());
        $this->assertEquals(0, $root->getNumFunctions());
        $this->assertEquals(0, $root->getNumTestedFunctions());
        $this->assertNull($root->getParent());
        $this->assertEquals(array(), $root->getDirectories());
        #$this->assertEquals(array(), $root->getFiles());
        #$this->assertEquals(array(), $root->getChildNodes());

        $this->assertEquals(
          array(
            'BankAccount' => array(
              'methods' => array(
                'getBalance' => array(
                  'signature' => 'getBalance()',
                  'startLine' => 6,
                  'endLine' => 9,
                  'executableLines' => 1,
                  'executedLines' => 1,
                  'ccn' => 1,
                  'coverage' => 100,
                  'crap' => '1',
                  'link' => 'BankAccount.php.html#6',
                  'methodName' => 'getBalance'
                ),
                'setBalance' => array(
                  'signature' => 'setBalance($balance)',
                  'startLine' => 11,
                  'endLine' => 18,
                  'executableLines' => 5,
                  'executedLines' => 0,
                  'ccn' => 2,
                  'coverage' => 0,
                  'crap' => 6,
                  'link' => 'BankAccount.php.html#11',
                  'methodName' => 'setBalance'
                ),
                'depositMoney' => array(
                  'signature' => 'depositMoney($balance)',
                  'startLine' => 20,
                  'endLine' => 25,
                  'executableLines' => 2,
                  'executedLines' => 2,
                  'ccn' => 1,
                  'coverage' => 100,
                  'crap' => '1',
                  'link' => 'BankAccount.php.html#20',
                  'methodName' => 'depositMoney'
                ),
                'withdrawMoney' => array(
                  'signature' => 'withdrawMoney($balance)',
                  'startLine' => 27,
                  'endLine' => 32,
                  'executableLines' => 2,
                  'executedLines' => 2,
                  'ccn' => 1,
                  'coverage' => 100,
                  'crap' => '1',
                  'link' => 'BankAccount.php.html#27',
                  'methodName' => 'withdrawMoney'
                ),
              ),
              'startLine' => 2,
              'executableLines' => 10,
              'executedLines' => 5,
              'ccn' => 5,
              'coverage' => 50,
              'crap' => '8.12',
              'package' => array(
                'namespace' => '',
                'fullPackage' => '',
                'category' => '',
                'package' => '',
                'subpackage' => ''
              ),
              'link' => 'BankAccount.php.html#2',
              'className' => 'BankAccount'
            )
          ),
          $root->getClasses()
        );

        $this->assertEquals(array(), $root->getFunctions());
    }

    /**
     * @covers PHP_CodeCoverage_Report_Factory::buildDirectoryStructure
     */
    public function testBuildDirectoryStructure()
    {
        $method = new ReflectionMethod(
          'PHP_CodeCoverage_Report_Factory', 'buildDirectoryStructure'
        );

        $method->setAccessible(TRUE);

        $this->assertEquals(
          array(
            'src' => array(
              'Money.php/f' => array(),
              'MoneyBag.php/f' => array()
            )
          ),
          $method->invoke(
            $this->factory,
            array('src/Money.php' => array(), 'src/MoneyBag.php' => array())
          )
        );
    }

    /**
     * @covers       PHP_CodeCoverage_Report_Factory::reducePaths
     * @dataProvider reducePathsProvider
     */
    public function testReducePaths($reducedPaths, $commonPath, $paths)
    {
        $method = new ReflectionMethod(
          'PHP_CodeCoverage_Report_Factory', 'reducePaths'
        );

        $method->setAccessible(TRUE);

        $_commonPath = $method->invokeArgs($this->factory, array(&$paths));

        $this->assertEquals($reducedPaths, $paths);
        $this->assertEquals($commonPath, $_commonPath);
    }

    public function reducePathsProvider()
    {
        return array(
          array(
            array(
              'Money.php' => array(),
              'MoneyBag.php' => array()
            ),
            '/home/sb/Money',
            array(
              '/home/sb/Money/Money.php' => array(),
              '/home/sb/Money/MoneyBag.php' => array()
            )
          ),
          array(
            array(
              'Money.php' => array()
            ),
            '/home/sb/Money/',
            array(
              '/home/sb/Money/Money.php' => array()
            )
          ),
          array(
            array(),
            '.',
            array()
          ),
          array(
            array(
              'Money.php' => array(),
              'MoneyBag.php' => array(),
              'Cash.phar/Cash.php' => array(),
            ),
            '/home/sb/Money',
            array(
              '/home/sb/Money/Money.php' => array(),
              '/home/sb/Money/MoneyBag.php' => array(),
              'phar:///home/sb/Money/Cash.phar/Cash.php' => array(),
            ),
          ),
        );
    }
}
<?php
/**
 * PHP_CodeCoverage
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @subpackage Tests
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      File available since Release 1.0.0
 */

if (!defined('TEST_FILES_PATH')) {
    define(
      'TEST_FILES_PATH',
      dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR .
      '_files' . DIRECTORY_SEPARATOR
    );
}

require_once TEST_FILES_PATH . '../TestCase.php';

require_once TEST_FILES_PATH . 'BankAccount.php';
require_once TEST_FILES_PATH . 'BankAccountTest.php';

/**
 * Tests for the PHP_CodeCoverage class.
 *
 * @category   PHP
 * @package    CodeCoverage
 * @subpackage Tests
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-code-coverage
 * @since      Class available since Release 1.0.0
 */
class PHP_CodeCoverageTest extends PHP_CodeCoverage_TestCase
{
    protected $coverage;
    protected $getLinesToBeCovered;

    protected function setUp()
    {
        $this->coverage = new PHP_CodeCoverage;

        $this->getLinesToBeCovered = new ReflectionMethod(
          'PHP_CodeCoverage', 'getLinesToBeCovered'
        );

        $this->getLinesToBeCovered->setAccessible(TRUE);
    }

    /**
     * @covers PHP_CodeCoverage::__construct
     * @covers PHP_CodeCoverage::filter
     */
    public function testConstructor()
    {
        $this->assertAttributeInstanceOf(
          'PHP_CodeCoverage_Driver_Xdebug', 'driver', $this->coverage
        );

        $this->assertAttributeInstanceOf(
          'PHP_CodeCoverage_Filter', 'filter', $this->coverage
        );
    }

    /**
     * @covers PHP_CodeCoverage::__construct
     * @covers PHP_CodeCoverage::filter
     */
    public function testConstructor2()
    {
        $filter   = new PHP_CodeCoverage_Filter;
        $coverage = new PHP_CodeCoverage(NULL, $filter);

        $this->assertAttributeInstanceOf(
          'PHP_CodeCoverage_Driver_Xdebug', 'driver', $coverage
        );

        $this->assertSame($filter, $coverage->filter());
    }

    /**
     * @covers            PHP_CodeCoverage::start
     * @expectedException PHP_CodeCoverage_Exception
     */
    public function testStartThrowsExceptionForInvalidArgument()
    {
        $this->coverage->start(NULL, array(), NULL);
    }

    /**
     * @covers            PHP_CodeCoverage::stop
     * @expectedException PHP_CodeCoverage_Exception
     */
    public function testStopThrowsExceptionForInvalidArgument()
    {
        $this->coverage->stop(NULL);
    }

    /**
     * @covers            PHP_CodeCoverage::append
     * @expectedException PHP_CodeCoverage_Exception
     */
    public function testAppendThrowsExceptionForInvalidArgument()
    {
        $this->coverage->append(array(), NULL);
    }

    /**
     * @covers            PHP_CodeCoverage::setCacheTokens
     * @expectedException PHP_CodeCoverage_Exception
     */
    public function testSetCacheTokensThrowsExceptionForInvalidArgument()
    {
        $this->coverage->setCacheTokens(NULL);
    }

    /**
     * @covers PHP_CodeCoverage::setCacheTokens
     */
    public function testSetCacheTokens()
    {
        $this->coverage->setCacheTokens(TRUE);
        $this->assertAttributeEquals(TRUE, 'cacheTokens', $this->coverage);
    }

    /**
     * @covers            PHP_CodeCoverage::setForceCoversAnnotation
     * @expectedException PHP_CodeCoverage_Exception
     */
    public function testSetForceCoversAnnotationThrowsExceptionForInvalidArgument()
    {
        $this->coverage->setForceCoversAnnotation(NULL);
    }

    /**
     * @covers PHP_CodeCoverage::setForceCoversAnnotation
     */
    public function testSetForceCoversAnnotation()
    {
        $this->coverage->setForceCoversAnnotation(TRUE);
        $this->assertAttributeEquals(
          TRUE, 'forceCoversAnnotation', $this->coverage
        );
    }

    /**
     * @covers            PHP_CodeCoverage::setProcessUncoveredFilesFromWhitelist
     * @expectedException PHP_CodeCoverage_Exception
     */
    public function testSetProcessUncoveredFilesFromWhitelistThrowsExceptionForInvalidArgument()
    {
        $this->coverage->setProcessUncoveredFilesFromWhitelist(NULL);
    }

    /**
     * @covers PHP_CodeCoverage::setProcessUncoveredFilesFromWhitelist
     */
    public function testSetProcessUncoveredFilesFromWhitelist()
    {
        $this->coverage->setProcessUncoveredFilesFromWhitelist(TRUE);
        $this->assertAttributeEquals(
          TRUE, 'processUncoveredFilesFromWhitelist', $this->coverage
        );
    }

    /**
     * @covers PHP_CodeCoverage::setMapTestClassNameToCoveredClassName
     */
    public function testSetMapTestClassNameToCoveredClassName()
    {
        $this->coverage->setMapTestClassNameToCoveredClassName(TRUE);
        $this->assertAttributeEquals(
          TRUE, 'mapTestClassNameToCoveredClassName', $this->coverage
        );
    }

    /**
     * @covers            PHP_CodeCoverage::setMapTestClassNameToCoveredClassName
     * @expectedException PHP_CodeCoverage_Exception
     */
    public function testSetMapTestClassNameToCoveredClassNameThrowsExceptionForInvalidArgument()
    {
        $this->coverage->setMapTestClassNameToCoveredClassName(NULL);
    }

    /**
     * @covers PHP_CodeCoverage::clear
     */
    public function testClear()
    {
        $this->coverage->clear();

        $this->assertAttributeEquals(NULL, 'currentId', $this->coverage);
        $this->assertAttributeEquals(array(), 'data', $this->coverage);
        $this->assertAttributeEquals(array(), 'tests', $this->coverage);
    }

    /**
     * @covers PHP_CodeCoverage::start
     * @covers PHP_CodeCoverage::stop
     * @covers PHP_CodeCoverage::append
     * @covers PHP_CodeCoverage::applyListsFilter
     * @covers PHP_CodeCoverage::initializeFilesThatAreSeenTheFirstTime
     * @covers PHP_CodeCoverage::applyCoversAnnotationFilter
     * @covers PHP_CodeCoverage::getTests
     */
    public function testCollect()
    {
        $coverage = $this->getCoverageForBankAccount();

        $this->assertEquals(
          $this->getExpectedDataArrayForBankAccount(), $coverage->getData()
        );

        $this->assertEquals(
          array(
            'BankAccountTest::testBalanceIsInitiallyZero' => NULL,
            'BankAccountTest::testBalanceCannotBecomeNegative' => NULL,
            'BankAccountTest::testBalanceCannotBecomeNegative2' => NULL,
            'BankAccountTest::testDepositWithdrawMoney' => NULL
          ),
          $coverage->getTests()
        );
    }

    /**
     * @covers PHP_CodeCoverage::getData
     * @covers PHP_CodeCoverage::merge
     */
    public function testMerge()
    {
        $coverage = $this->getCoverageForBankAccountForFirstTwoTests();
        $coverage->merge($this->getCoverageForBankAccountForLastTwoTests());

        $this->assertEquals(
          $this->getExpectedDataArrayForBankAccount(), $coverage->getData()
        );
    }

    /**
     * @covers PHP_CodeCoverage::getData
     * @covers PHP_CodeCoverage::merge
     */
    public function testMerge2()
    {
        $coverage = new PHP_CodeCoverage(
          $this->getMock('PHP_CodeCoverage_Driver_Xdebug'),
          new PHP_CodeCoverage_Filter
        );

        $coverage->merge($this->getCoverageForBankAccount());

        $this->assertEquals(
          $this->getExpectedDataArrayForBankAccount(), $coverage->getData()
        );
    }

    /**
     * @covers       PHP_CodeCoverage::getLinesToBeCovered
     * @covers       PHP_CodeCoverage::resolveCoversToReflectionObjects
     * @dataProvider getLinesToBeCoveredProvider
     */
    public function testGetLinesToBeCovered($test, $lines)
    {
        if (strpos($test, 'Namespace') === 0) {
            $expected = array(
              TEST_FILES_PATH . 'NamespaceCoveredClass.php' => $lines
            );
        }

        else if ($test === 'CoverageNoneTest') {
            $expected = array();
        }

        else if ($test === 'CoverageNothingTest') {
            $expected = false;
        }

        else if ($test === 'CoverageFunctionTest') {
            $expected = array(
              TEST_FILES_PATH . 'CoveredFunction.php' => $lines
            );
        }

        else {
            $expected = array(TEST_FILES_PATH . 'CoveredClass.php' => $lines);
        }

        $this->assertEquals(
          $expected,
          $this->getLinesToBeCovered->invoke(
            $this->coverage, $test, 'testSomething'
          )
        );
    }

    /**
     * @covers            PHP_CodeCoverage::getLinesToBeCovered
     * @covers            PHP_CodeCoverage::resolveCoversToReflectionObjects
     * @expectedException PHP_CodeCoverage_Exception
     */
    public function testGetLinesToBeCovered2()
    {
        $this->getLinesToBeCovered->invoke(
          $this->coverage, 'NotExistingCoveredElementTest', 'testOne'
        );
    }

    /**
     * @covers            PHP_CodeCoverage::getLinesToBeCovered
     * @covers            PHP_CodeCoverage::resolveCoversToReflectionObjects
     * @expectedException PHP_CodeCoverage_Exception
     */
    public function testGetLinesToBeCovered3()
    {
        $this->getLinesToBeCovered->invoke(
          $this->coverage, 'NotExistingCoveredElementTest', 'testTwo'
        );
    }

    /**
     * @covers            PHP_CodeCoverage::getLinesToBeCovered
     * @covers            PHP_CodeCoverage::resolveCoversToReflectionObjects
     * @expectedException PHP_CodeCoverage_Exception
     */
    public function testGetLinesToBeCovered4()
    {
        $this->getLinesToBeCovered->invoke(
          $this->coverage, 'NotExistingCoveredElementTest', 'testThree'
        );
    }

    /**
     * @covers PHP_CodeCoverage::getLinesToBeCovered
     */
    public function testGetLinesToBeCoveredSkipsNonExistantMethods()
    {
        $this->assertSame(
          array(),
          $this->getLinesToBeCovered->invoke(
            $this->coverage,
            'NotExistingCoveredElementTest',
            'methodDoesNotExist'
          )
        );
    }

    /**
     * @covers PHP_CodeCoverage::getLinesToBeCovered
     * @expectedException PHP_CodeCoverage_Exception
     */
    public function testTwoCoversDefaultClassAnnoationsAreNotAllowed()
    {
        $this->getLinesToBeCovered->invoke(
          $this->coverage,
          'CoverageTwoDefaultClassAnnotations',
          'testSomething'
        );
    }

    /**
     * @covers PHP_CodeCoverage::getLinesToBeCovered
     */
    public function testFunctionParenthesesAreAllowed()
    {
        $this->assertSame(
          array(TEST_FILES_PATH . 'CoveredFunction.php' => range(2, 4)),
          $this->getLinesToBeCovered->invoke(
            $this->coverage,
            'CoverageFunctionParenthesesTest',
            'testSomething'
          )
        );
    }

    /**
     * @covers PHP_CodeCoverage::getLinesToBeCovered
     */
    public function testFunctionParenthesesAreAllowedWithWhitespace()
    {
        $this->assertSame(
          array(TEST_FILES_PATH . 'CoveredFunction.php' => range(2, 4)),
          $this->getLinesToBeCovered->invoke(
            $this->coverage,
            'CoverageFunctionParenthesesWhitespaceTest',
            'testSomething'
          )
        );
    }

    /**
     * @covers PHP_CodeCoverage::getLinesToBeCovered
     */
    public function testMethodParenthesesAreAllowed()
    {
        $this->assertSame(
          array(TEST_FILES_PATH . 'CoveredClass.php' => range(31, 35)),
          $this->getLinesToBeCovered->invoke(
            $this->coverage,
            'CoverageMethodParenthesesTest',
            'testSomething'
          )
        );
    }

    /**
     * @covers PHP_CodeCoverage::getLinesToBeCovered
     */
    public function testMethodParenthesesAreAllowedWithWhitespace()
    {
        $this->assertSame(
          array(TEST_FILES_PATH . 'CoveredClass.php' => range(31, 35)),
          $this->getLinesToBeCovered->invoke(
            $this->coverage,
            'CoverageMethodParenthesesWhitespaceTest',
            'testSomething'
          )
        );
    }

    public function getLinesToBeCoveredProvider()
    {
        return array(
          array(
            'CoverageNoneTest',
            array()
          ),
          array(
            'CoverageClassExtendedTest',
            array_merge(range(19, 36), range(2, 17))
          ),
          array(
            'CoverageClassTest',
            range(19, 36)
          ),
          array(
            'CoverageMethodTest',
            range(31, 35)
          ),
          array(
            'CoverageMethodOneLineAnnotationTest',
            range(31, 35)
          ),
          array(
            'CoverageNotPrivateTest',
            array_merge(range(25, 29), range(31, 35))
          ),
          array(
            'CoverageNotProtectedTest',
            array_merge(range(21, 23), range(31, 35))
          ),
          array(
            'CoverageNotPublicTest',
            array_merge(range(21, 23), range(25, 29))
          ),
          array(
            'CoveragePrivateTest',
            range(21, 23)
          ),
          array(
            'CoverageProtectedTest',
            range(25, 29)
          ),
          array(
            'CoveragePublicTest',
            range(31, 35)
          ),
          array(
            'CoverageFunctionTest',
            range(2, 4)
          ),
          array(
            'NamespaceCoverageClassExtendedTest',
            array_merge(range(21, 38), range(4, 19))
          ),
          array(
            'NamespaceCoverageClassTest',
            range(21, 38)
          ),
          array(
            'NamespaceCoverageMethodTest',
            range(33, 37)
          ),
          array(
            'NamespaceCoverageNotPrivateTest',
            array_merge(range(27, 31), range(33, 37))
          ),
          array(
            'NamespaceCoverageNotProtectedTest',
            array_merge(range(23, 25), range(33, 37))
          ),
          array(
            'NamespaceCoverageNotPublicTest',
            array_merge(range(23, 25), range(27, 31))
          ),
          array(
            'NamespaceCoveragePrivateTest',
            range(23, 25)
          ),
          array(
            'NamespaceCoverageProtectedTest',
            range(27, 31)
          ),
          array(
            'NamespaceCoveragePublicTest',
            range(33, 37)
          ),
          array(
            'NamespaceCoverageCoversClassTest',
            array_merge(range(23, 25), range(27, 31), range(33, 37), range(6, 8), range(10, 13), range(15, 18))
          ),
          array(
            'NamespaceCoverageCoversClassPublicTest',
            range(33, 37)
          ),
          array(
            'CoverageNothingTest',
            false
          )
        );
    }
}
<?php
/**
 * php-file-iterator
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package   File
 * @author    Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright 2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license   http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @since     File available since Release 1.0.0
 */

/**
 * FilterIterator implementation that filters files based on prefix(es) and/or
 * suffix(es). Hidden files and files from hidden directories are also filtered.
 *
 * @author    Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright 2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license   http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version   Release: @package_version@
 * @link      http://github.com/sebastianbergmann/php-file-iterator/tree
 * @since     Class available since Release 1.0.0
 */
class File_Iterator extends FilterIterator
{
    const PREFIX = 0;
    const SUFFIX = 1;

    /**
     * @var array
     */
    protected $suffixes = array();

    /**
     * @var array
     */
    protected $prefixes = array();

    /**
     * @var array
     */
    protected $exclude = array();

    /**
     * @var string
     */
    protected $basepath;

    /**
     * @param  Iterator $iterator
     * @param  array    $suffixes
     * @param  array    $prefixes
     * @param  array    $exclude
     * @param  string   $basepath
     */
    public function __construct(Iterator $iterator, array $suffixes = array(), array $prefixes = array(), array $exclude = array(), $basepath = NULL)
    {
        $exclude = array_filter(array_map('realpath', $exclude));

        if ($basepath !== NULL) {
            $basepath = realpath($basepath);
        }

        if ($basepath === FALSE) {
            $basepath = NULL;
        } else {
            foreach ($exclude as &$_exclude) {
                $_exclude = str_replace($basepath, '', $_exclude);
            }
        }

        $this->prefixes = $prefixes;
        $this->suffixes = $suffixes;
        $this->exclude  = $exclude;
        $this->basepath = $basepath;

        parent::__construct($iterator);
    }

    /**
     * @return boolean
     */
    public function accept()
    {
        $current  = $this->getInnerIterator()->current();
        $filename = $current->getFilename();
        $realpath = $current->getRealPath();

        if ($this->basepath !== NULL) {
            $realpath = str_replace($this->basepath, '', $realpath);
        }

        // Filter files in hidden directories.
        if (preg_match('=/\.[^/]*/=', $realpath)) {
            return FALSE;
        }

        return $this->acceptPath($realpath) &&
               $this->acceptPrefix($filename) &&
               $this->acceptSuffix($filename);
    }

    /**
     * @param  string $path
     * @return boolean
     * @since  Method available since Release 1.1.0
     */
    protected function acceptPath($path)
    {
        foreach ($this->exclude as $exclude) {
            if (strpos($path, $exclude) === 0) {
                return FALSE;
            }
        }

        return TRUE;
    }

    /**
     * @param  string $filename
     * @return boolean
     * @since  Method available since Release 1.1.0
     */
    protected function acceptPrefix($filename)
    {
        return $this->acceptSubString($filename, $this->prefixes, self::PREFIX);
    }

    /**
     * @param  string $filename
     * @return boolean
     * @since  Method available since Release 1.1.0
     */
    protected function acceptSuffix($filename)
    {
        return $this->acceptSubString($filename, $this->suffixes, self::SUFFIX);
    }

    /**
     * @param  string  $filename
     * @param  array   $subString
     * @param  integer $type
     * @return boolean
     * @since  Method available since Release 1.1.0
     */
    protected function acceptSubString($filename, array $subStrings, $type)
    {
        if (empty($subStrings)) {
            return TRUE;
        }

        $matched = FALSE;

        foreach ($subStrings as $string) {
            if (($type == self::PREFIX && strpos($filename, $string) === 0) ||
                ($type == self::SUFFIX &&
                 substr($filename, -1 * strlen($string)) == $string)) {
                $matched = TRUE;
                break;
            }
        }

        return $matched;
    }
}
<?php
/**
 * php-file-iterator
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package   File
 * @author    Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright 2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license   http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @since     File available since Release 1.3.0
 */

/**
 * Façade implementation that uses File_Iterator_Factory to create a
 * File_Iterator that operates on an AppendIterator that contains an
 * RecursiveDirectoryIterator for each given path. The list of unique
 * files is returned as an array.
 *
 * @author    Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright 2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license   http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version   Release: @package_version@
 * @link      http://github.com/sebastianbergmann/php-file-iterator/tree
 * @since     Class available since Release 1.3.0
 */
class File_Iterator_Facade
{
    /**
     * @param  array|string $paths
     * @param  array|string $suffixes
     * @param  array|string $prefixes
     * @param  array        $exclude
     * @param  boolean      $commonPath
     * @return array
     */
    public function getFilesAsArray($paths, $suffixes = '', $prefixes = '', array $exclude = array(), $commonPath = FALSE)
    {
        if (is_string($paths)) {
            $paths = array($paths);
        }

        $factory  = new File_Iterator_Factory;
        $iterator = $factory->getFileIterator(
          $paths, $suffixes, $prefixes, $exclude
        );

        $files = array();

        foreach ($iterator as $file) {
            $file = $file->getRealPath();

            if ($file) {
                $files[] = $file;
            }
        }

        foreach ($paths as $path) {
            if (is_file($path)) {
                $files[] = realpath($path);
            }
        }

        $files = array_unique($files);
        sort($files);

        if ($commonPath) {
            return array(
              'commonPath' => $this->getCommonPath($files),
              'files'      => $files
            );
        } else {
            return $files;
        }
    }

    /**
     * Returns the common path of a set of files.
     *
     * @param  array $files
     * @return string
     */
    protected function getCommonPath(array $files)
    {
        $count = count($files);

        if ($count == 0) {
            return '';
        }

        if ($count == 1) {
            return dirname($files[0]) . DIRECTORY_SEPARATOR;
        }

        $_files = array();

        foreach ($files as $file) {
            $_files[] = $_fileParts = explode(DIRECTORY_SEPARATOR, $file);

            if (empty($_fileParts[0])) {
                $_fileParts[0] = DIRECTORY_SEPARATOR;
            }
        }

        $common = '';
        $done   = FALSE;
        $j      = 0;
        $count--;

        while (!$done) {
            for ($i = 0; $i < $count; $i++) {
                if ($_files[$i][$j] != $_files[$i+1][$j]) {
                    $done = TRUE;
                    break;
                }
            }

            if (!$done) {
                $common .= $_files[0][$j];

                if ($j > 0) {
                    $common .= DIRECTORY_SEPARATOR;
                }
            }

            $j++;
        }

        return DIRECTORY_SEPARATOR . $common;
    }
}
<?php
/**
 * php-file-iterator
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package   File
 * @author    Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright 2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license   http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @since     File available since Release 1.1.0
 */

/**
 * Factory Method implementation that creates a File_Iterator that operates on
 * an AppendIterator that contains an RecursiveDirectoryIterator for each given
 * path.
 *
 * @author    Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright 2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license   http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version   Release: @package_version@
 * @link      http://github.com/sebastianbergmann/php-file-iterator/tree
 * @since     Class available since Release 1.1.0
 */
class File_Iterator_Factory
{
    /**
     * @param  array|string $paths
     * @param  array|string $suffixes
     * @param  array|string $prefixes
     * @param  array        $exclude
     * @return AppendIterator
     */
    public function getFileIterator($paths, $suffixes = '', $prefixes = '', array $exclude = array())
    {
        if (is_string($paths)) {
            $paths = array($paths);
        }

        $_paths = array();

        foreach ($paths as $path) {
            if ($locals = glob($path, GLOB_ONLYDIR)) {
                $_paths = array_merge($_paths, $locals);
            } else {
                $_paths[] = $path;
            }
        }

        $paths = $_paths;
        unset($_paths);

        if (is_string($prefixes)) {
            if ($prefixes != '') {
                $prefixes = array($prefixes);
            } else {
                $prefixes = array();
            }
        }

        if (is_string($suffixes)) {
            if ($suffixes != '') {
                $suffixes = array($suffixes);
            } else {
                $suffixes = array();
            }
        }

        $iterator = new AppendIterator;

        foreach ($paths as $path) {
            if (is_dir($path)) {
                $iterator->append(
                  new File_Iterator(
                    new RecursiveIteratorIterator(
                      new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::FOLLOW_SYMLINKS)
                    ),
                    $suffixes,
                    $prefixes,
                    $exclude,
                    $path
                  )
                );
            }
        }

        return $iterator;
    }
}
<?php
/**
 * php-file-iterator
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package   File
 * @author    Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright 2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license   http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @since     File available since Release 1.3.0
 */

spl_autoload_register(
  function ($class)
  {
      static $classes = NULL;
      static $path = NULL;

      if ($classes === NULL) {
          $classes = array(
            'file_iterator' => '/Iterator.php',
            'file_iterator_facade' => '/Iterator/Facade.php',
            'file_iterator_factory' => '/Iterator/Factory.php'
          );

          $path = dirname(dirname(__FILE__));
      }

      $cn = strtolower($class);

      if (isset($classes[$cn])) {
          require $path . $classes[$cn];
      }
  }
);
<?php
/**
 * php-file-iterator
 *
 * Copyright (c) 2009-2013, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package   File
 * @author    Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright 2009-2013 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license   http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @since     File available since Release 1.3.0
 */

spl_autoload_register(
  function ($class)
  {
      static $classes = NULL;
      static $path = NULL;

      if ($classes === NULL) {
          $classes = array(
            ___CLASSLIST___
          );

          $path = dirname(dirname(__FILE__));
      }

      $cn = strtolower($class);

      if (isset($classes[$cn])) {
          require $path . $classes[$cn];
      }
  }
);
{
    "name": "phpunit/php-file-iterator",
    "description": "FilterIterator implementation that filters files based on a list of suffixes.",
    "type": "library",
    "keywords": [
        "iterator",
        "filesystem"
    ],
    "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
    "license": "BSD-3-Clause",
    "authors": [
        {
            "name": "Sebastian Bergmann",
            "email": "sb@sebastian-bergmann.de",
            "role": "lead"
        }
    ],
    "support": {
        "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
        "irc": "irc://irc.freenode.net/phpunit"
    },
    "require": {
        "php": ">=5.3.3"
    },
    "autoload": {
        "classmap": [
            "File/"
        ]
    },
    "include-path": [
        ""
    ]
}
<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.4.10" version="2.0"
  xmlns="http://pear.php.net/dtd/package-2.0"
  xmlns:tasks="http://pear.php.net/dtd/tasks-1.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
                      http://pear.php.net/dtd/tasks-1.0.xsd
                      http://pear.php.net/dtd/package-2.0
                      http://pear.php.net/dtd/package-2.0.xsd">
 <name>File_Iterator</name>
 <channel>pear.phpunit.de</channel>
 <summary>FilterIterator implementation that filters files based on a list of suffixes.</summary>
 <description>FilterIterator implementation that filters files based on a list of suffixes.</description>
 <lead>
  <name>Sebastian Bergmann</name>
  <user>sb</user>
  <email>sb@sebastian-bergmann.de</email>
  <active>yes</active>
 </lead>
 <date>2013-10-10</date>
 <version>
  <release>1.3.4</release>
  <api>1.3.0</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license>The BSD 3-Clause License</license>
 <notes>http://github.com/sebastianbergmann/php-file-iterator/tree</notes>
 <contents>
  <dir name="/">
   <dir name="File">
    <dir name="Iterator">
     <file baseinstalldir="/" name="Autoload.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="/" name="Facade.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="/" name="Factory.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
    </dir>
    <file baseinstalldir="/" name="Iterator.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
   </dir>
   <file baseinstalldir="/" name="ChangeLog.markdown" role="doc"/>
   <file baseinstalldir="/" name="LICENSE" role="doc"/>
   <file baseinstalldir="/" name="README.markdown" role="doc"/>
  </dir>
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.3.3</min>
   </php>
   <pearinstaller>
    <min>1.9.4</min>
   </pearinstaller>
  </required>
 </dependencies>
 <phprelease/>
</package>
<?xml version="1.0"?>

<ruleset name="Sebastian"
         xmlns="http://pmd.sf.net/ruleset/1.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
         xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
  <description>Sebastian Bergmann's ruleset</description>

  <rule ref="rulesets/codesize.xml/CyclomaticComplexity" />
  <rule ref="rulesets/codesize.xml/NPathComplexity" />
  <rule ref="rulesets/codesize.xml/ExcessiveClassComplexity" />
  <rule ref="rulesets/codesize.xml/ExcessiveClassLength" />
  <rule ref="rulesets/codesize.xml/ExcessiveMethodLength" />
  <rule ref="rulesets/codesize.xml/ExcessiveParameterList" />

  <rule ref="rulesets/design.xml/EvalExpression" />
  <rule ref="rulesets/design.xml/ExitExpression" />
  <rule ref="rulesets/design.xml/GotoStatement" />

  <rule ref="rulesets/naming.xml/ConstructorWithNameAsEnclosingClass" />

  <rule ref="rulesets/unusedcode.xml/UnusedFormalParameter" />
  <rule ref="rulesets/unusedcode.xml/UnusedLocalVariable" />
  <rule ref="rulesets/unusedcode.xml/UnusedPrivateField" />
  <rule ref="rulesets/unusedcode.xml/UnusedPrivateMethod" />
</ruleset>
<?php
class PHPCS_Sniffs_ControlStructures_ControlSignatureSniff extends PHP_CodeSniffer_Standards_AbstractPatternSniff
{
    public function __construct()
    {
        parent::__construct(true);
    }

    protected function getPatterns()
    {
        return array(
          'do {EOL...} while (...);EOL',
          'while (...) {EOL',
          'for (...) {EOL',
          'if (...) {EOL',
          'foreach (...) {EOL',
          '}EOLelse if (...) {EOL',
          '}EOLelse {EOL',
          'do {EOL',
        );
    }
}
<?php
class PHPCS_Sniffs_Whitespace_ConcatenationSpacingSniff implements PHP_CodeSniffer_Sniff
{
    public function register()
    {
        return array(T_STRING_CONCAT);
    }

    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE ||
            $tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) {

            $phpcsFile->addError(
              'Concatenation operator must be surrounded by whitespace',
              $stackPtr
            );
        }
    }
}
<?xml version="1.0"?>
<ruleset name="Sebastian">
 <description>Sebastian Bergmann's coding standard</description>

 <rule ref="Generic.CodeAnalysis.ForLoopShouldBeWhileLoop"/>
 <rule ref="Generic.CodeAnalysis.ForLoopWithTestFunctionCall"/>
 <rule ref="Generic.CodeAnalysis.JumbledIncrementer"/>
 <rule ref="Generic.CodeAnalysis.UnconditionalIfStatement"/>
 <rule ref="Generic.CodeAnalysis.UnnecessaryFinalModifier"/>
 <rule ref="Generic.CodeAnalysis.UselessOverridingMethod"/>

 <rule ref="Generic.Commenting.Todo"/>

 <rule ref="Generic.ControlStructures.InlineControlStructure"/>

 <rule ref="Generic.Files.LineEndings"/>

 <rule ref="Generic.Formatting.DisallowMultipleStatements"/>
 <rule ref="Generic.Formatting.NoSpaceAfterCast"/>

 <rule ref="Generic.Functions.OpeningFunctionBraceBsdAllman"/>
 <rule ref="PEAR.Functions.ValidDefaultValue"/>

 <rule ref="Generic.NamingConventions.ConstructorName"/>
 <rule ref="Generic.NamingConventions.UpperCaseConstantName"/>
 <rule ref="PEAR.NamingConventions.ValidClassName"/>

 <rule ref="Generic.PHP.DisallowShortOpenTag"/>
 <rule ref="Generic.PHP.NoSilencedErrors"/>
 <rule ref="Generic.PHP.UpperCaseConstant"/>

 <rule ref="Generic.WhiteSpace.DisallowTabIndent"/>
 <rule ref="Generic.WhiteSpace.ScopeIndent"/>
 <rule ref="Squiz.WhiteSpace.SuperfluousWhitespace"/>
</ruleset>
File_Iterator

Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.de>.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

 * Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in
   the documentation and/or other materials provided with the
   distribution.

 * Neither the name of Sebastian Bergmann nor the names of his
   contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
File_Iterator
=============

Installation
------------

File_Iterator should be installed using the [PEAR Installer](http://pear.php.net/). This installer is the backbone of PEAR, which provides a distribution system for PHP packages, and is shipped with every release of PHP since version 4.3.0.

The PEAR channel (`pear.phpunit.de`) that is used to distribute File_Iterator needs to be registered with the local PEAR environment:

    sb@ubuntu ~ % pear channel-discover pear.phpunit.de
    Adding Channel "pear.phpunit.de" succeeded
    Discovery of channel "pear.phpunit.de" succeeded

This has to be done only once. Now the PEAR Installer can be used to install packages from the PHPUnit channel:

    sb@vmware ~ % pear install phpunit/File_Iterator
    downloading File_Iterator-1.1.1.tgz ...
    Starting to download File_Iterator-1.1.1.tgz (3,173 bytes)
    ....done: 3,173 bytes
    install ok: channel://pear.phpunit.de/File_Iterator-1.1.1

After the installation you can find the File_Iterator source files inside your local PEAR directory; the path is usually `/usr/lib/php/File`.
File_Iterator 1.3
=================

This is the list of changes for the File_Iterator 1.3 release series.

File_Iterator 1.3.4
-------------------

* Symlinks are now followed.

File_Iterator 1.3.3
-------------------

* No changes.

File_Iterator 1.3.2
-------------------

* No changes.

File_Iterator 1.3.1
-------------------

* Fixed infinite loop in `File_Iterator_Facade::getCommonPath()` for empty directories.

File_Iterator 1.3.0
-------------------

* Added `File_Iterator_Facade` for the most common use case.
* Moved `File_Iterator_Factory::getFilesAsArray()` to `File_Iterator_Facade::getFilesAsArray()`.
* `File_Iterator_Factory` is no longer static.
<?xml version="1.0" encoding="UTF-8"?>

<project name="File_Iterator" default="build">
 <property name="php" value="php"/>
 <property name="phpunit" value="phpunit"/>

 <target name="build"
   depends="prepare,lint,phploc,pdepend,phpmd-ci,phpcs-ci,phpcpd,phpcb"/>

 <target name="build-parallel"
   depends="prepare,lint,tools-parallel,phpcb"/>

 <target name="tools-parallel"
         description="Run tools in parallel">
  <parallel threadCount="2">
   <sequential>
    <antcall target="pdepend"/>
    <antcall target="phpmd-ci"/>
   </sequential>
   <antcall target="phpcpd"/>
   <antcall target="phpcs-ci"/>
   <antcall target="phploc"/>
  </parallel>
 </target>

 <target name="clean" description="Cleanup build artifacts">
  <delete dir="${basedir}/build/api"/>
  <delete dir="${basedir}/build/code-browser"/>
  <delete dir="${basedir}/build/coverage"/>
  <delete dir="${basedir}/build/logs"/>
  <delete dir="${basedir}/build/pdepend"/>
 </target>

 <target name="prepare" depends="clean,phpab"
         description="Prepare for build">
  <mkdir dir="${basedir}/build/api"/>
  <mkdir dir="${basedir}/build/code-browser"/>
  <mkdir dir="${basedir}/build/coverage"/>
  <mkdir dir="${basedir}/build/logs"/>
  <mkdir dir="${basedir}/build/pdepend"/>
 </target>

 <target name="phpab" description="Generate autoloader scripts">
  <exec executable="phpab">
   <arg value="--output" />
   <arg path="File/Iterator/Autoload.php" />
   <arg value="--template" />
   <arg path="File/Iterator/Autoload.php.in" />
   <arg value="--indent" />
   <arg value="            " />
   <arg path="File" />
  </exec>
 </target>

 <target name="lint">
  <apply executable="${php}" failonerror="true">
   <arg value="-l" />

   <fileset dir="${basedir}/File">
    <include name="**/*.php" />
    <modified />
   </fileset>
<!--
   <fileset dir="${basedir}/Tests">
    <include name="**/*.php" />
    <modified />
   </fileset>
-->
  </apply>
 </target>

 <target name="phploc" description="Measure project size using PHPLOC">
  <exec executable="phploc">
   <arg value="--log-csv" />
   <arg value="${basedir}/build/logs/phploc.csv" />
   <arg path="${basedir}/File" />
  </exec>
 </target>

 <target name="pdepend"
         description="Calculate software metrics using PHP_Depend">
  <exec executable="pdepend">
   <arg value="--jdepend-xml=${basedir}/build/logs/jdepend.xml" />
   <arg value="--jdepend-chart=${basedir}/build/pdepend/dependencies.svg" />
   <arg value="--overview-pyramid=${basedir}/build/pdepend/overview-pyramid.svg" />
   <arg path="${basedir}/File" />
  </exec>
 </target>

 <target name="phpmd"
         description="Perform project mess detection using PHPMD">
  <exec executable="phpmd">
   <arg path="${basedir}/File" />
   <arg value="text" />
   <arg value="${basedir}/build/phpmd.xml" />
  </exec>
 </target>

 <target name="phpmd-ci"
         description="Perform project mess detection using PHPMD">
  <exec executable="phpmd">
   <arg path="${basedir}/File" />
   <arg value="xml" />
   <arg value="${basedir}/build/phpmd.xml" />
   <arg value="--reportfile" />
   <arg value="${basedir}/build/logs/pmd.xml" />
  </exec>
 </target>

 <target name="phpcs"
         description="Find coding standard violations using PHP_CodeSniffer">
  <exec executable="phpcs">
   <arg value="--standard=${basedir}/build/PHPCS" />
   <arg value="--extensions=php" />
   <arg value="--ignore=Autoload.php" />
   <arg path="${basedir}/File" />
  </exec>
 </target>

 <target name="phpcs-ci"
         description="Find coding standard violations using PHP_CodeSniffer">
  <exec executable="phpcs" output="/dev/null">
   <arg value="--report=checkstyle" />
   <arg value="--report-file=${basedir}/build/logs/checkstyle.xml" />
   <arg value="--standard=${basedir}/build/PHPCS" />
   <arg value="--extensions=php" />
   <arg value="--ignore=Autoload.php" />
   <arg path="${basedir}/File" />
  </exec>
 </target>

 <target name="phpcpd" description="Find duplicate code using PHPCPD">
  <exec executable="phpcpd">
   <arg value="--log-pmd" />
   <arg value="${basedir}/build/logs/pmd-cpd.xml" />
   <arg path="${basedir}/File" />
  </exec>
 </target>

 <target name="phpunit" description="Run unit tests with PHPUnit">
  <condition property="phpunit_cmd" value="${php} ${phpunit}" else="${phpunit}">
   <not>
    <equals arg1="${phpunit}" arg2="phpunit" />
   </not>
  </condition>

  <exec executable="${phpunit_cmd}" failonerror="true"/>
 </target>

 <target name="phpcb"
         description="Aggregate tool output with PHP_CodeBrowser">
  <exec executable="phpcb">
   <arg value="--log" />
   <arg path="${basedir}/build/logs" />
   <arg value="--source" />
   <arg path="${basedir}/File" />
   <arg value="--output" />
   <arg path="${basedir}/build/code-browser" />
  </exec>
 </target>
</project>
{
    "name": "phpunit/php-text-template",
    "description": "Simple template engine.",
    "type": "library",
    "keywords": [
        "template"
    ],
    "homepage": "https://github.com/sebastianbergmann/php-text-template/",
    "license": "BSD-3-Clause",
    "authors": [
        {
            "name": "Sebastian Bergmann",
            "email": "sb@sebastian-bergmann.de",
            "role": "lead"
        }
    ],
    "support": {
        "issues": "https://github.com/sebastianbergmann/php-text-template/issues",
        "irc": "irc://irc.freenode.net/phpunit"
    },
    "require": {
        "php": ">=5.3.3"
    },
    "autoload": {
        "classmap": [
            "Text/"
        ]
    },
    "include-path": [
        ""
    ]
}
<?php
/**
 * Text_Template
 *
 * Copyright (c) 2009-2012, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   Text
 * @package    Template
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2009-2012 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-text-template
 * @since      File available since Release 1.0.0
 */

/**
 * A simple template engine.
 *
 * @category   Text
 * @package    Template
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2009-2012 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/php-text-template
 * @since      Class available since Release 1.0.0
 */
class Text_Template
{
    /**
     * @var string
     */
    protected $template = '';

    /**
     * @var array
     */
    protected $values = array();

    /**
     * Constructor.
     *
     * @param  string $file
     * @throws InvalidArgumentException
     */
    public function __construct($file = '')
    {
        $this->setFile($file);
    }

    /**
     * Sets the template file.
     *
     * @param  string $file
     * @throws InvalidArgumentException
     */
    public function setFile($file)
    {
        $distFile = $file . '.dist';

        if (file_exists($file)) {
            $this->template = file_get_contents($file);
        }

        else if (file_exists($distFile)) {
            $this->template = file_get_contents($distFile);
        }

        else {
            throw new InvalidArgumentException(
              'Template file could not be loaded.'
            );
        }
    }

    /**
     * Sets one or more template variables.
     *
     * @param  array   $values
     * @param  boolean $merge
     */
    public function setVar(array $values, $merge = TRUE)
    {
        if (!$merge || empty($this->values)) {
            $this->values = $values;
        } else {
            $this->values = array_merge($this->values, $values);
        }
    }

    /**
     * Renders the template and returns the result.
     *
     * @return string
     */
    public function render()
    {
        $keys = array();

        foreach ($this->values as $key => $value) {
            $keys[] = '{' . $key . '}';
        }

        return str_replace($keys, $this->values, $this->template);
    }

    /**
     * Renders the template and writes the result to a file.
     *
     * @param string $target
     */
    public function renderTo($target)
    {
        $fp = @fopen($target, 'wt');

        if ($fp) {
            fwrite($fp, $this->render());
            fclose($fp);
        } else {
            $error = error_get_last();

            throw new RuntimeException(
              sprintf(
                'Could not write to %s: %s',
                $target,
                substr(
                  $error['message'],
                  strpos($error['message'], ':') + 2
                )
              )
            );
        }
    }
}
<?php
/**
 * Text_Template
 *
 * Copyright (c) 2009-2010, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   Text
 * @package    Template
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2009-2010 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-text-template
 * @since      File available since Release 1.1.0
 */

spl_autoload_register(
  function ($class) {
      static $classes = NULL;
      static $path = NULL;

      if ($classes === NULL) {
          $classes = array(
            'text_template' => '/Template.php'
          );

          $path = dirname(dirname(__FILE__));
      }

      $cn = strtolower($class);

      if (isset($classes[$cn])) {
          require $path . $classes[$cn];
      }
  }
);
<?php
/**
 * Text_Template
 *
 * Copyright (c) 2009-2010, Sebastian Bergmann <sb@sebastian-bergmann.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @category   Text
 * @package    Template
 * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @copyright  2009-2010 Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-text-template
 * @since      File available since Release 1.1.0
 */

spl_autoload_register(
  function ($class) {
      static $classes = NULL;
      static $path = NULL;

      if ($classes === NULL) {
          $classes = array(
            ___CLASSLIST___
          );

          $path = dirname(dirname(__FILE__));
      }

      $cn = strtolower($class);

      if (isset($classes[$cn])) {
          require $path . $classes[$cn];
      }
  }
);
<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.4.10" version="2.0"
  xmlns="http://pear.php.net/dtd/package-2.0"
  xmlns:tasks="http://pear.php.net/dtd/tasks-1.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
                      http://pear.php.net/dtd/tasks-1.0.xsd
                      http://pear.php.net/dtd/package-2.0
                      http://pear.php.net/dtd/package-2.0.xsd">
 <name>Text_Template</name>
 <channel>pear.phpunit.de</channel>
 <summary>Simple template engine.</summary>
 <description>Simple template engine.</description>
 <lead>
  <name>Sebastian Bergmann</name>
  <user>sb</user>
  <email>sb@sebastian-bergmann.de</email>
  <active>yes</active>
 </lead>
 <date>2012-10-31</date>
 <version>
  <release>1.1.4</release>
  <api>1.1.0</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license>The BSD 3-Clause License</license>
 <notes>http://github.com/sebastianbergmann/php-text-template</notes>
 <contents>
  <dir name="/">
   <dir name="Text">
    <dir name="Template">
     <file baseinstalldir="/" name="Autoload.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
    </dir>
    <file baseinstalldir="/" name="Template.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
   </dir>
   <file baseinstalldir="/" name="ChangeLog.markdown" role="doc"/>
   <file baseinstalldir="/" name="LICENSE" role="doc"/>
   <file baseinstalldir="/" name="README.markdown" role="doc"/>
  </dir>
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.3.3</min>
   </php>
   <pearinstaller>
    <min>1.9.4</min>
   </pearinstaller>
  </required>
 </dependencies>
 <phprelease/>
</package>
<?xml version="1.0"?>

<ruleset name="Sebastian"
         xmlns="http://pmd.sf.net/ruleset/1.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
         xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
  <description>Sebastian Bergmann's ruleset</description>

  <rule ref="rulesets/codesize.xml/CyclomaticComplexity" />
  <rule ref="rulesets/codesize.xml/NPathComplexity" />
  <rule ref="rulesets/codesize.xml/ExcessiveClassComplexity" />
  <rule ref="rulesets/codesize.xml/ExcessiveClassLength" />
  <rule ref="rulesets/codesize.xml/ExcessiveMethodLength" />
  <rule ref="rulesets/codesize.xml/ExcessiveParameterList" />

  <rule ref="rulesets/design.xml/EvalExpression" />
  <rule ref="rulesets/design.xml/ExitExpression" />
  <rule ref="rulesets/design.xml/GotoStatement" />

  <rule ref="rulesets/naming.xml/ConstructorWithNameAsEnclosingClass" />

  <rule ref="rulesets/unusedcode.xml/UnusedFormalParameter" />
  <rule ref="rulesets/unusedcode.xml/UnusedLocalVariable" />
  <rule ref="rulesets/unusedcode.xml/UnusedPrivateField" />
  <rule ref="rulesets/unusedcode.xml/UnusedPrivateMethod" />
</ruleset>
<?php
class PHPCS_Sniffs_ControlStructures_ControlSignatureSniff extends PHP_CodeSniffer_Standards_AbstractPatternSniff
{
    public function __construct()
    {
        parent::__construct(true);
    }

    protected function getPatterns()
    {
        return array(
          'do {EOL...} while (...);EOL',
          'while (...) {EOL',
          'for (...) {EOL',
          'if (...) {EOL',
          'foreach (...) {EOL',
          '}EOLelse if (...) {EOL',
          '}EOLelse {EOL',
          'do {EOL',
        );
    }
}
<?php
class PHPCS_Sniffs_Whitespace_ConcatenationSpacingSniff implements PHP_CodeSniffer_Sniff
{
    public function register()
    {
        return array(T_STRING_CONCAT);
    }

    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE ||
            $tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) {

            $phpcsFile->addError(
              'Concatenation operator must be surrounded by whitespace',
              $stackPtr
            );
        }
    }
}
<?xml version="1.0"?>
<ruleset name="Sebastian">
 <description>Sebastian Bergmann's coding standard</description>

 <rule ref="Generic.CodeAnalysis.ForLoopShouldBeWhileLoop"/>
 <rule ref="Generic.CodeAnalysis.ForLoopWithTestFunctionCall"/>
 <rule ref="Generic.CodeAnalysis.JumbledIncrementer"/>
 <rule ref="Generic.CodeAnalysis.UnconditionalIfStatement"/>
 <rule ref="Generic.CodeAnalysis.UnnecessaryFinalModifier"/>
 <rule ref="Generic.CodeAnalysis.UselessOverridingMethod"/>

 <rule ref="Generic.Commenting.Todo"/>

 <rule ref="Generic.ControlStructures.InlineControlStructure"/>

 <rule ref="Generic.Files.LineEndings"/>

 <rule ref="Generic.Formatting.DisallowMultipleStatements"/>
 <rule ref="Generic.Formatting.NoSpaceAfterCast"/>

 <rule ref="Generic.Functions.OpeningFunctionBraceBsdAllman"/>
 <rule ref="PEAR.Functions.ValidDefaultValue"/>

 <rule ref="Generic.NamingConventions.ConstructorName"/>
 <rule ref="Generic.NamingConventions.UpperCaseConstantName"/>
 <rule ref="PEAR.NamingConventions.ValidClassName"/>

 <rule ref="Generic.PHP.DisallowShortOpenTag"/>
 <rule ref="Generic.PHP.NoSilencedErrors"/>
 <rule ref="Generic.PHP.UpperCaseConstant"/>

 <rule ref="Generic.WhiteSpace.DisallowTabIndent"/>
 <rule ref="Generic.WhiteSpace.ScopeIndent"/>
 <rule ref="Squiz.WhiteSpace.SuperfluousWhitespace"/>
</ruleset>
Text_Template

Copyright (c) 2009-2012, Sebastian Bergmann <sb@sebastian-bergmann.de>.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

 * Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in
   the documentation and/or other materials provided with the
   distribution.

 * Neither the name of Sebastian Bergmann nor the names of his
   contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Text_Template
=============

Installation
------------

Text_Template should be installed using the [PEAR Installer](http://pear.php.net/). This installer is the backbone of PEAR, which provides a distribution system for PHP packages, and is shipped with every release of PHP since version 4.3.0.

The PEAR channel (`pear.phpunit.de`) that is used to distribute Text_Template needs to be registered with the local PEAR environment:

    sb@ubuntu ~ % pear channel-discover pear.phpunit.de
    Adding Channel "pear.phpunit.de" succeeded
    Discovery of channel "pear.phpunit.de" succeeded

This has to be done only once. Now the PEAR Installer can be used to install packages from the PHPUnit channel:

    sb@vmware ~ % pear install phpunit/Text_Template
    downloading Text_Template-1.0.0.tgz ...
    Starting to download Text_Template-1.0.0.tgz (2,493 bytes)
    ....done: 2,493 bytes
    install ok: channel://pear.phpunit.de/Text_Template-1.0.0

After the installation you can find the Text_Template source files inside your local PEAR directory; the path is usually `/usr/lib/php/Text`.
Text_Template 1.1
=================

This is the list of changes for the Text_Template 1.1 release series.

Text_Template 1.1.4
-------------------

* Improved error message in case `renderTo()` cannot write to the target file.

Text_Template 1.1.3
-------------------

* No changes.

Text_Template 1.1.2
-------------------

* No changes.

Text_Template 1.1.1
-------------------

* No changes.
<?xml version="1.0" encoding="UTF-8"?>

<project name="Text_Template" default="build">
 <property name="php" value="php"/>
 <property name="phpunit" value="phpunit"/>

 <target name="build"
   depends="prepare,lint,phploc,pdepend,phpmd-ci,phpcs-ci,phpcpd,phpcb"/>

 <target name="build-parallel"
   depends="prepare,lint,tools-parallel,phpcb"/>

 <target name="tools-parallel"
         description="Run tools in parallel">
  <parallel threadCount="2">
   <sequential>
    <antcall target="pdepend"/>
    <antcall target="phpmd-ci"/>
   </sequential>
   <antcall target="phpcpd"/>
   <antcall target="phpcs-ci"/>
   <antcall target="phploc"/>
  </parallel>
 </target>

 <target name="clean" description="Cleanup build artifacts">
  <delete dir="${basedir}/build/api"/>
  <delete dir="${basedir}/build/code-browser"/>
  <delete dir="${basedir}/build/coverage"/>
  <delete dir="${basedir}/build/logs"/>
  <delete dir="${basedir}/build/pdepend"/>
 </target>

 <target name="prepare" depends="clean,phpab"
         description="Prepare for build">
  <mkdir dir="${basedir}/build/api"/>
  <mkdir dir="${basedir}/build/code-browser"/>
  <mkdir dir="${basedir}/build/coverage"/>
  <mkdir dir="${basedir}/build/logs"/>
  <mkdir dir="${basedir}/build/pdepend"/>
 </target>

 <target name="phpab" description="Generate autoloader scripts">
  <exec executable="phpab">
   <arg value="--output" />
   <arg path="Text/Template/Autoload.php" />
   <arg value="--template" />
   <arg path="Text/Template/Autoload.php.in" />
   <arg value="--indent" />
   <arg value="            " />
   <arg path="Text" />
  </exec>
 </target>

 <target name="lint">
  <apply executable="${php}" failonerror="true">
   <arg value="-l" />

   <fileset dir="${basedir}/Text">
    <include name="**/*.php" />
    <modified />
   </fileset>
<!--
   <fileset dir="${basedir}/Tests">
    <include name="**/*.php" />
    <modified />
   </fileset>
-->
  </apply>
 </target>

 <target name="phploc" description="Measure project size using PHPLOC">
  <exec executable="phploc">
   <arg value="--log-csv" />
   <arg value="${basedir}/build/logs/phploc.csv" />
   <arg path="${basedir}/Text" />
  </exec>
 </target>

 <target name="pdepend"
         description="Calculate software metrics using PHP_Depend">
  <exec executable="pdepend">
   <arg value="--jdepend-xml=${basedir}/build/logs/jdepend.xml" />
   <arg value="--jdepend-chart=${basedir}/build/pdepend/dependencies.svg" />
   <arg value="--overview-pyramid=${basedir}/build/pdepend/overview-pyramid.svg" />
   <arg path="${basedir}/Text" />
  </exec>
 </target>

 <target name="phpmd"
         description="Perform project mess detection using PHPMD">
  <exec executable="phpmd">
   <arg path="${basedir}/Text" />
   <arg value="text" />
   <arg value="${basedir}/build/phpmd.xml" />
  </exec>
 </target>

 <target name="phpmd-ci"
         description="Perform project mess detection using PHPMD">
  <exec executable="phpmd">
   <arg path="${basedir}/Text" />
   <arg value="xml" />
   <arg value="${basedir}/build/phpmd.xml" />
   <arg value="--reportfile" />
   <arg value="${basedir}/build/logs/pmd.xml" />
  </exec>
 </target>

 <target name="phpcs"
         description="Find coding standard violations using PHP_CodeSniffer">
  <exec executable="phpcs">
   <arg value="--standard=${basedir}/build/PHPCS" />
   <arg value="--extensions=php" />
   <arg value="--ignore=Autoload.php" />
   <arg path="${basedir}/Text" />
  </exec>
 </target>

 <target name="phpcs-ci"
         description="Find coding standard violations using PHP_CodeSniffer">
  <exec executable="phpcs" output="/dev/null">
   <arg value="--report=checkstyle" />
   <arg value="--report-file=${basedir}/build/logs/checkstyle.xml" />
   <arg value="--standard=${basedir}/build/PHPCS" />
   <arg value="--extensions=php" />
   <arg value="--ignore=Autoload.php" />
   <arg path="${basedir}/Text" />
  </exec>
 </target>

 <target name="phpcpd" description="Find duplicate code using PHPCPD">
  <exec executable="phpcpd">
   <arg value="--log-pmd" />
   <arg value="${basedir}/build/logs/pmd-cpd.xml" />
   <arg path="${basedir}/Text" />
  </exec>
 </target>

 <target name="phpunit" description="Run unit tests with PHPUnit">
  <condition property="phpunit_cmd" value="${php} ${phpunit}" else="${phpunit}">
   <not>
    <equals arg1="${phpunit}" arg2="phpunit" />
   </not>
  </condition>

  <exec executable="${phpunit_cmd}" failonerror="true"/>
 </target>

 <target name="phpcb"
         description="Aggregate tool output with PHP_CodeBrowser">
  <exec executable="phpcb">
   <arg value="--log" />
   <arg path="${basedir}/build/logs" />
   <arg value="--source" />
   <arg path="${basedir}/Text" />
   <arg value="--output" />
   <arg path="${basedir}/build/code-browser" />
  </exec>
 </target>
</project>
{
    "name": "phpunit/php-timer",
    "description": "Utility class for timing",
    "type": "library",
    "keywords": [
        "timer"
    ],
    "homepage": "https://github.com/sebastianbergmann/php-timer/",
    "license": "BSD-3-Clause",
    "authors": [
        {
            "name": "Sebastian Bergmann",
            "email": "sb@sebastian-bergmann.de",
            "role": "lead"
        }
    ],
    "support": {
        "issues": "https://github.com/sebastianbergmann/php-timer/issues",
        "irc": "irc://irc.freenode.net/phpunit"
    },
    "require": {
        "php": ">=5.3.3"
    },
    "autoload": {
        "classmap": [
            "PHP/"
        ]
    },
    "include-path": [
        ""
    ]
}
<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.4.10" version="2.0"
  xmlns="http://pear.php.net/dtd/package-2.0"
  xmlns:tasks="http://pear.php.net/dtd/tasks-1.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
                      http://pear.php.net/dtd/tasks-1.0.xsd
                      http://pear.php.net/dtd/package-2.0
                      http://pear.php.net/dtd/package-2.0.xsd">
 <name>PHP_Timer</name>
 <channel>pear.phpunit.de</channel>
 <summary>Utility class for timing</summary>
 <description>Utility class for timing</description>
 <lead>
  <name>Sebastian Bergmann</name>
  <user>sb</user>
  <email>sb@sebastian-bergmann.de</email>
  <active>yes</active>
 </lead>
 <date>2013-08-02</date>
 <version>
  <release>1.0.5</release>
  <api>1.0.0</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license>The BSD 3-Clause License</license>
 <notes>http://github.com/sebastianbergmann/php-timer/blob/master/README.markdown</notes>
 <contents>
  <dir name="/">
   <dir name="PHP">
    <dir name="Timer">
     <file baseinstalldir="/" name="Autoload.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
    </dir>
    <file baseinstalldir="/" name="Timer.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
   </dir>
   <file baseinstalldir="/" name="LICENSE" role="doc"/>
   <file baseinstalldir="/" name="README.md" role="doc"/>
  </dir>
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.3.3</min>
   </php>
   <pearinstaller>
    <min>1.9.2</min>
   </pearinstaller>
  </required>
 </dependencies>
 <phprelease/>
</package>
<?xml version="1.0"?>

<ruleset name="Sebastian"
         xmlns="http://pmd.sf.net/ruleset/1.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
         xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
  <description>Sebastian Bergmann's ruleset</description>

  <rule ref="rulesets/codesize.xml/CyclomaticComplexity" />
  <rule ref="rulesets/codesize.xml/NPathComplexity" />
  <rule ref="rulesets/codesize.xml/ExcessiveClassComplexity" />
  <rule ref="rulesets/codesize.xml/ExcessiveClassLength" />
  <rule ref="rulesets/codesize.xml/ExcessiveMethodLength" />
  <rule ref="rulesets/codesize.xml/ExcessiveParameterList" />

  <rule ref="rulesets/design.xml/EvalExpression" />
  <rule ref="rulesets/design.xml/ExitExpression" />
  <rule ref="rulesets/design.xml/GotoStatement" />

  <rule ref="rulesets/naming.xml/ConstructorWithNameAsEnclosingClass" />

  <rule ref="rulesets/unusedcode.xml/UnusedFormalParameter" />
  <rule ref="rulesets/unusedcode.xml/UnusedLocalVariable" />
  <rule ref="rulesets/unusedcode.xml/UnusedPrivateField" />
  <rule ref="rulesets/unusedcode.xml/UnusedPrivateMethod" />
</ruleset>
<?php
class PHPCS_Sniffs_ControlStructures_ControlSignatureSniff extends PHP_CodeSniffer_Standards_AbstractPatternSniff
{
    public function __construct()
    {
        parent::__construct(true);
    }

    protected function getPatterns()
    {
        return array(
          'do {EOL...} while (...);EOL',
          'while (...) {EOL',
          'for (...) {EOL',
          'if (...) {EOL',
          'foreach (...) {EOL',
          '}EOLelse if (...) {EOL',
          '}EOLelse {EOL',
          'do {EOL',
        );
    }
}
<?php
class PHPCS_Sniffs_Whitespace_ConcatenationSpacingSniff implements PHP_CodeSniffer_Sniff
{
    public function register()
    {
        return array(T_STRING_CONCAT);
    }

    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE ||
            $tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) {

            $phpcsFile->addError(
              'Concatenation operator must be surrounded by whitespace',
              $stackPtr
            );
        }
    }
}
<?xml version="1.0"?>
<ruleset name="Sebastian">
 <description>Sebastian Bergmann's coding standard</description>

 <rule ref="Generic.CodeAnalysis.ForLoopShouldBeWhileLoop"/>
 <rule ref="Generic.CodeAnalysis.ForLoopWithTestFunctionCall"/>
 <rule ref="Generic.CodeAnalysis.JumbledIncrementer"/>
 <rule ref="Generic.CodeAnalysis.UnconditionalIfStatement"/>
 <rule ref="Generic.CodeAnalysis.UnnecessaryFinalModifier"/>
 <rule ref="Generic.CodeAnalysis.UselessOverridingMethod"/>

 <rule ref="Generic.Commenting.Todo"/>

 <rule ref="Generic.ControlStructures.InlineControlStructure"/>

 <rule ref="Generic.Files.LineEndings"/>

 <rule ref="Generic.Formatting.DisallowMultipleStatements"/>
 <rule ref="Generic.Formatting.NoSpaceAfterCast"/>

 <rule ref="Generic.Functions.OpeningFunctionBraceBsdAllman"/>
 <rule ref="PEAR.Functions.ValidDefaultValue"/>

 <rule ref="Generic.NamingConventions.ConstructorName"/>
 <rule ref="Generic.NamingConventions.UpperCaseConstantName"/>
 <rule ref="PEAR.NamingConventions.ValidClassName"/>

 <rule ref="Generic.PHP.DisallowShortOpenTag"/>
 <rule ref="Generic.PHP.NoSilencedErrors"/>
 <rule ref="Generic.PHP.UpperCaseConstant"/>

 <rule ref="Generic.WhiteSpace.DisallowTabIndent"/>
 <rule ref="Generic.WhiteSpace.ScopeIndent"/>
 <rule ref="Squiz.WhiteSpace.SuperfluousWhitespace"/>
</ruleset>
PHP_Timer

Copyright (c) 2010-2013, Sebastian Bergmann <sebastian@phpunit.de>.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

 * Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in
   the documentation and/or other materials provided with the
   distribution.

 * Neither the name of Sebastian Bergmann nor the names of his
   contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
<?xml version="1.0" encoding="UTF-8"?>

<project name="PHP_Timer" default="build">
 <property name="php" value="php"/>
 <property name="phpunit" value="phpunit"/>

 <target name="build"
   depends="prepare,lint,phploc,pdepend,phpmd-ci,phpcs-ci,phpcpd,phpunit,phpcb"/>

 <target name="build-parallel"
   depends="prepare,lint,tools-parallel,phpunit,phpcb"/>

 <target name="tools-parallel"
         description="Run tools in parallel">
  <parallel threadCount="2">
   <sequential>
    <antcall target="pdepend"/>
    <antcall target="phpmd-ci"/>
   </sequential>
   <antcall target="phpcpd"/>
   <antcall target="phpcs-ci"/>
   <antcall target="phploc"/>
  </parallel>
 </target>

 <target name="clean" description="Cleanup build artifacts">
  <delete dir="${basedir}/build/api"/>
  <delete dir="${basedir}/build/code-browser"/>
  <delete dir="${basedir}/build/coverage"/>
  <delete dir="${basedir}/build/logs"/>
  <delete dir="${basedir}/build/pdepend"/>
 </target>

 <target name="prepare" depends="clean,phpab"
         description="Prepare for build">
  <mkdir dir="${basedir}/build/api"/>
  <mkdir dir="${basedir}/build/code-browser"/>
  <mkdir dir="${basedir}/build/coverage"/>
  <mkdir dir="${basedir}/build/logs"/>
  <mkdir dir="${basedir}/build/pdepend"/>
 </target>

 <target name="phpab" description="Generate autoloader scripts">
  <exec executable="phpab">
   <arg value="--output" />
   <arg path="PHP/Timer/Autoload.php" />
   <arg value="--template" />
   <arg path="PHP/Timer/Autoload.php.in" />
   <arg value="--indent" />
   <arg value="            " />
   <arg path="PHP" />
  </exec>
 </target>

 <target name="lint">
  <apply executable="${php}" failonerror="true">
   <arg value="-l" />

   <fileset dir="${basedir}/PHP">
    <include name="**/*.php" />
    <modified />
   </fileset>

   <fileset dir="${basedir}/Tests">
    <include name="**/*.php" />
    <modified />
   </fileset>
  </apply>
 </target>

 <target name="phploc" description="Measure project size using PHPLOC">
  <exec executable="phploc">
   <arg value="--log-csv" />
   <arg value="${basedir}/build/logs/phploc.csv" />
   <arg path="${basedir}/PHP" />
  </exec>
 </target>

 <target name="pdepend"
         description="Calculate software metrics using PHP_Depend">
  <exec executable="pdepend">
   <arg value="--jdepend-xml=${basedir}/build/logs/jdepend.xml" />
   <arg value="--jdepend-chart=${basedir}/build/pdepend/dependencies.svg" />
   <arg value="--overview-pyramid=${basedir}/build/pdepend/overview-pyramid.svg" />
   <arg path="${basedir}/PHP" />
  </exec>
 </target>

 <target name="phpmd"
         description="Perform project mess detection using PHPMD">
  <exec executable="phpmd">
   <arg path="${basedir}/PHP" />
   <arg value="text" />
   <arg value="${basedir}/build/phpmd.xml" />
  </exec>
 </target>

 <target name="phpmd-ci"
         description="Perform project mess detection using PHPMD">
  <exec executable="phpmd">
   <arg path="${basedir}/PHP" />
   <arg value="xml" />
   <arg value="${basedir}/build/phpmd.xml" />
   <arg value="--reportfile" />
   <arg value="${basedir}/build/logs/pmd.xml" />
  </exec>
 </target>

 <target name="phpcs"
         description="Find coding standard violations using PHP_CodeSniffer">
  <exec executable="phpcs">
   <arg value="--standard=${basedir}/build/PHPCS" />
   <arg value="--extensions=php" />
   <arg value="--ignore=Autoload.php" />
   <arg path="${basedir}/PHP" />
  </exec>
 </target>

 <target name="phpcs-ci"
         description="Find coding standard violations using PHP_CodeSniffer">
  <exec executable="phpcs" output="/dev/null">
   <arg value="--report=checkstyle" />
   <arg value="--report-file=${basedir}/build/logs/checkstyle.xml" />
   <arg value="--standard=${basedir}/build/PHPCS" />
   <arg value="--extensions=php" />
   <arg value="--ignore=Autoload.php" />
   <arg path="${basedir}/PHP" />
  </exec>
 </target>

 <target name="phpcpd" description="Find duplicate code using PHPCPD">
  <exec executable="phpcpd">
   <arg value="--log-pmd" />
   <arg value="${basedir}/build/logs/pmd-cpd.xml" />
   <arg path="${basedir}/PHP" />
  </exec>
 </target>

 <target name="phpunit" description="Run unit tests with PHPUnit">
  <condition property="phpunit_cmd" value="${php} ${phpunit}" else="${phpunit}">
   <not>
    <equals arg1="${phpunit}" arg2="phpunit" />
   </not>
  </condition>

  <exec executable="${phpunit_cmd}" failonerror="true"/>
 </target>

 <target name="phpcb"
         description="Aggregate tool output with PHP_CodeBrowser">
  <exec executable="phpcb">
   <arg value="--log" />
   <arg path="${basedir}/build/logs" />
   <arg value="--source" />
   <arg path="${basedir}/PHP" />
   <arg value="--output" />
   <arg path="${basedir}/build/code-browser" />
  </exec>
 </target>
</project>
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false">
  <testsuites>
    <testsuite name="PHP_Timer">
      <directory suffix=".php">Tests</directory>
    </testsuite>
  </testsuites>

  <logging>
    <log type="coverage-html" target="build/coverage" title="PHP_Timer"
         charset="UTF-8" yui="true" highlight="true"
         lowUpperBound="35" highLowerBound="70"/>
    <log type="coverage-clover" target="build/logs/clover.xml"/>
    <log type="junit" target="build/logs/junit.xml" logIncompleteSkipped="false"/>
  </logging>

  <filter>
    <whitelist addUncoveredFilesFromWhitelist="true">
      <directory suffix=".php">PHP</directory>
      <exclude>
        <file>PHP/Timer/Autoload.php</file>
      </exclude>
    </whitelist>
  </filter>
</phpunit>
<?php
/**
 * PHP_Timer
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHP
 * @subpackage Timer
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2010-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-timer
 * @since      File available since Release 1.1.0
 */

spl_autoload_register(
  function ($class)
  {
      static $classes = NULL;
      static $path = NULL;

      if ($classes === NULL) {
          $classes = array(
            'php_timer' => '/Timer.php'
          );

          $path = dirname(dirname(__FILE__));
      }

      $cn = strtolower($class);

      if (isset($classes[$cn])) {
          require $path . $classes[$cn];
      }
  }
);
<?php
/**
 * PHP_Timer
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHP
 * @subpackage Timer
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2010-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-timer
 * @since      File available since Release 1.1.0
 */

spl_autoload_register(
  function ($class)
  {
      static $classes = NULL;
      static $path = NULL;

      if ($classes === NULL) {
          $classes = array(
            ___CLASSLIST___
          );

          $path = dirname(dirname(__FILE__));
      }

      $cn = strtolower($class);

      if (isset($classes[$cn])) {
          require $path . $classes[$cn];
      }
  }
);
<?php
/**
 * PHP_Timer
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHP
 * @subpackage Timer
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2010-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-timer
 * @since      File available since Release 1.0.0
 */

/**
 * Utility class for timing.
 *
 * @package    PHP
 * @subpackage Timer
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2010-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/php-timer
 * @since      Class available since Release 1.0.0
 */
class PHP_Timer
{
    /**
     * @var array
     */
    private static $times = array(
      'hour'   => 3600000,
      'minute' => 60000,
      'second' => 1000
    );

    /**
     * @var array
     */
    private static $startTimes = array();

    /**
     * @var float
     */
    public static $requestTime;

    /**
     * Starts the timer.
     */
    public static function start()
    {
        array_push(self::$startTimes, microtime(TRUE));
    }

    /**
     * Stops the timer and returns the elapsed time.
     *
     * @return float
     */
    public static function stop()
    {
        return microtime(TRUE) - array_pop(self::$startTimes);
    }

    /**
     * Formats the elapsed time as a string.
     *
     * @param  float $time
     * @return string
     */
    public static function secondsToTimeString($time)
    {
        $ms = round($time * 1000);

        foreach (self::$times as $unit => $value) {
            if ($ms >= $value) {
                $time = floor($ms / $value * 100.0) / 100.0;
                return $time . ' ' . ($time == 1 ? $unit : $unit . 's');
            }
        }

        return $ms . ' ms';
    }

    /**
     * Formats the elapsed time since the start of the request as a string.
     *
     * @return string
     */
    public static function timeSinceStartOfRequest()
    {
        return self::secondsToTimeString(microtime(TRUE) - self::$requestTime);
    }

    /**
     * Returns the resources (time, memory) of the request as a string.
     *
     * @return string
     */
    public static function resourceUsage()
    {
        return sprintf(
          'Time: %s, Memory: %4.2fMb',
          self::timeSinceStartOfRequest(),
          memory_get_peak_usage(TRUE) / 1048576
        );
    }
}

if (isset($_SERVER['REQUEST_TIME_FLOAT'])) {
    PHP_Timer::$requestTime = $_SERVER['REQUEST_TIME_FLOAT'];
}

else {
    PHP_Timer::$requestTime = microtime(TRUE);
}
<?php
/**
 * PHP_Timer
 *
 * Copyright (c) 2010-2013, Sebastian Bergmann <sebastian@phpunit.de>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   * Neither the name of Sebastian Bergmann nor the names of his
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * @package    PHP
 * @subpackage Timer
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2010 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @link       http://github.com/sebastianbergmann/php-timer
 * @since      File available since Release 1.0.0
 */

require_once dirname(dirname(__FILE__)) . '/PHP/Timer.php';

/**
 * Tests for PHP_Timer.
 *
 * @package    PHP
 * @subpackage Timer
 * @author     Sebastian Bergmann <sebastian@phpunit.de>
 * @copyright  2010-2013 Sebastian Bergmann <sebastian@phpunit.de>
 * @license    http://www.opensource.org/licenses/BSD-3-Clause  The BSD 3-Clause License
 * @version    Release: @package_version@
 * @link       http://github.com/sebastianbergmann/php-timer
 * @since      Class available since Release 1.0.0
 */
class PHP_TimerTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers PHP_Timer::start
     * @covers PHP_Timer::stop
     */
    public function testStartStop()
    {
        $this->assertInternalType('float', PHP_Timer::stop());
    }

    /**
     * @covers       PHP_Timer::secondsToTimeString
     * @dataProvider secondsProvider
     */
    public function testSecondsToTimeString($string, $seconds)
    {
        $this->assertEquals(
          $string, PHP_Timer::secondsToTimeString($seconds)
        );
    }

    /**
     * @covers PHP_Timer::timeSinceStartOfRequest
     */
    public function testTimeSinceStartOfRequest()
    {
        $this->assertStringMatchesFormat(
          '%f %s', PHP_Timer::timeSinceStartOfRequest()
        );
    }


    /**
     * @covers PHP_Timer::resourceUsage
     */
    public function testResourceUsage()
    {
        $this->assertStringMatchesFormat(
          'Time: %s, Memory: %s', PHP_Timer::resourceUsage()
        );
    }

    public function secondsProvider()
    {
        return array(
          array('0 ms', 0),
          array('1 ms', .001),
          array('10 ms', .01),
          array('100 ms', .1),
          array('999 ms', .999),
          array('1 second', .9999),
          array('1 second', 1),
          array('2 seconds', 2),
          array('59.9 seconds', 59.9),
          array('59.99 seconds', 59.99),
          array('59.99 seconds', 59.999),
          array('1 minute', 59.9999),
          array('59 seconds', 59.001),
          array('59.01 seconds', 59.01),
          array('1 minute', 60),
          array('1.01 minutes', 61),
          array('2 minutes', 120),
          array('2.01 minutes', 121),
          array('59.99 minutes', 3599.9),
          array('59.99 minutes', 3599.99),
          array('59.99 minutes', 3599.999),
          array('1 hour', 3599.9999),
          array('59.98 minutes', 3599.001),
          array('59.98 minutes', 3599.01),
          array('1 hour', 3600),
          array('1 hour', 3601),
          array('1 hour', 3601.9),
          array('1 hour', 3601.99),
          array('1 hour', 3601.999),
          array('1 hour', 3601.9999),
          array('1.01 hours', 3659.9999),
          array('1.01 hours', 3659.001),
          array('1.01 hours', 3659.01),
          array('2 hours', 7199.9999),
        );
    }
}
{
    "name": "zendframework/zend-json",
    "description": "provides convenience methods for serializing native PHP to JSON and decoding JSON to native PHP",
    "license": "BSD-3-Clause",
    "keywords": [
        "zf2",
        "json"
    ],
    "autoload": {
        "psr-0": {
            "Zend\\Json\\": ""
        }
    },
    "target-dir": "Zend/Json",
    "require": {
        "php": ">=5.3.3",
        "zendframework/zend-stdlib": "self.version"
    },
    "suggest": {
        "zendframework/zend-server": "Zend\\Server component"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "2.2-dev",
            "dev-develop": "2.3-dev"
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Json;

use Iterator;
use IteratorAggregate;
use ReflectionClass;
use Zend\Json\Exception\InvalidArgumentException;
use Zend\Json\Exception\RecursionException;

/**
 * Encode PHP constructs to JSON
 */
class Encoder
{
    /**
     * Whether or not to check for possible cycling
     *
     * @var bool
     */
    protected $cycleCheck;

    /**
     * Additional options used during encoding
     *
     * @var array
     */
    protected $options = array();

    /**
     * Array of visited objects; used to prevent cycling.
     *
     * @var array
     */
    protected $visited = array();

    /**
     * Constructor
     *
     * @param  bool $cycleCheck Whether or not to check for recursion when encoding
     * @param array $options Additional options used during encoding
     * @return Encoder
     */
    protected function __construct($cycleCheck = false, $options = array())
    {
        $this->cycleCheck = $cycleCheck;
        $this->options = $options;
    }

    /**
     * Use the JSON encoding scheme for the value specified
     *
     * @param mixed $value The value to be encoded
     * @param  bool $cycleCheck Whether or not to check for possible object recursion when encoding
     * @param array $options Additional options used during encoding
     * @return string  The encoded value
     */
    public static function encode($value, $cycleCheck = false, $options = array())
    {
        $encoder = new static(($cycleCheck) ? true : false, $options);

        return $encoder->_encodeValue($value);
    }

    /**
     * Recursive driver which determines the type of value to be encoded
     * and then dispatches to the appropriate method. $values are either
     *    - objects (returns from {@link _encodeObject()})
     *    - arrays (returns from {@link _encodeArray()})
     *    - basic datums (e.g. numbers or strings) (returns from {@link _encodeDatum()})
     *
     * @param $value mixed The value to be encoded
     * @return string Encoded value
     */
    protected function _encodeValue(&$value)
    {
        if (is_object($value)) {
            return $this->_encodeObject($value);
        } elseif (is_array($value)) {
            return $this->_encodeArray($value);
        }

        return $this->_encodeDatum($value);
    }


    /**
     * Encode an object to JSON by encoding each of the public properties
     *
     * A special property is added to the JSON object called '__className'
     * that contains the name of the class of $value. This is used to decode
     * the object on the client into a specific class.
     *
     * @param $value object
     * @return string
     * @throws RecursionException If recursive checks are enabled and the
     *                            object has been serialized previously
     */
    protected function _encodeObject(&$value)
    {
        if ($this->cycleCheck) {
            if ($this->_wasVisited($value)) {

                if (isset($this->options['silenceCyclicalExceptions'])
                    && $this->options['silenceCyclicalExceptions']===true) {

                    return '"* RECURSION (' . str_replace('\\', '\\\\', get_class($value)) . ') *"';

                } else {
                    throw new RecursionException(
                        'Cycles not supported in JSON encoding, cycle introduced by '
                        . 'class "' . get_class($value) . '"'
                    );
                }
            }

            $this->visited[] = $value;
        }

        $props = '';

        if (method_exists($value, 'toJson')) {
            $props =',' . preg_replace("/^\{(.*)\}$/","\\1", $value->toJson());
        } else {
            if ($value instanceof IteratorAggregate) {
                $propCollection = $value->getIterator();
            } elseif ($value instanceof Iterator) {
                $propCollection = $value;
            } else {
                $propCollection = get_object_vars($value);
            }

            foreach ($propCollection as $name => $propValue) {
                if (isset($propValue)) {
                    $props .= ','
                            . $this->_encodeValue($name)
                            . ':'
                            . $this->_encodeValue($propValue);
                }
            }
        }

        $className = get_class($value);
        return '{"__className":'
            . $this->_encodeString($className)
            . $props . '}';
    }


    /**
     * Determine if an object has been serialized already
     *
     * @param mixed $value
     * @return bool
     */
    protected function _wasVisited(&$value)
    {
        if (in_array($value, $this->visited, true)) {
            return true;
        }

        return false;
    }


    /**
     * JSON encode an array value
     *
     * Recursively encodes each value of an array and returns a JSON encoded
     * array string.
     *
     * Arrays are defined as integer-indexed arrays starting at index 0, where
     * the last index is (count($array) -1); any deviation from that is
     * considered an associative array, and will be encoded as such.
     *
     * @param $array array
     * @return string
     */
    protected function _encodeArray(&$array)
    {
        $tmpArray = array();

        // Check for associative array
        if (!empty($array) && (array_keys($array) !== range(0, count($array) - 1))) {
            // Associative array
            $result = '{';
            foreach ($array as $key => $value) {
                $key = (string) $key;
                $tmpArray[] = $this->_encodeString($key)
                            . ':'
                            . $this->_encodeValue($value);
            }
            $result .= implode(',', $tmpArray);
            $result .= '}';
        } else {
            // Indexed array
            $result = '[';
            $length = count($array);
            for ($i = 0; $i < $length; $i++) {
                $tmpArray[] = $this->_encodeValue($array[$i]);
            }
            $result .= implode(',', $tmpArray);
            $result .= ']';
        }

        return $result;
    }


    /**
     * JSON encode a basic data type (string, number, boolean, null)
     *
     * If value type is not a string, number, boolean, or null, the string
     * 'null' is returned.
     *
     * @param  mixed $value
     * @return string
     */
    protected function _encodeDatum(&$value)
    {
        $result = 'null';

        if (is_int($value) || is_float($value)) {
            $result = (string) $value;
            $result = str_replace(',', '.', $result);
        } elseif (is_string($value)) {
            $result = $this->_encodeString($value);
        } elseif (is_bool($value)) {
            $result = $value ? 'true' : 'false';
        }

        return $result;
    }


    /**
     * JSON encode a string value by escaping characters as necessary
     *
     * @param string $string
     * @return string
     */
    protected function _encodeString(&$string)
    {
        // Escape these characters with a backslash or unicode escape:
        // " \ / \n \r \t \b \f
        $search  = array('\\', "\n", "\t", "\r", "\b", "\f", '"', '\'', '&', '<', '>', '/');
        $replace = array('\\\\', '\\n', '\\t', '\\r', '\\b', '\\f', '\\u0022', '\\u0027', '\\u0026',  '\\u003C', '\\u003E', '\\/');
        $string  = str_replace($search, $replace, $string);

        // Escape certain ASCII characters:
        // 0x08 => \b
        // 0x0c => \f
        $string = str_replace(array(chr(0x08), chr(0x0C)), array('\b', '\f'), $string);
        $string = self::encodeUnicodeString($string);

        return '"' . $string . '"';
    }


    /**
     * Encode the constants associated with the ReflectionClass
     * parameter. The encoding format is based on the class2 format
     *
     * @param ReflectionClass $cls
     * @return string Encoded constant block in class2 format
     */
    private static function _encodeConstants(ReflectionClass $cls)
    {
        $result    = "constants : {";
        $constants = $cls->getConstants();

        $tmpArray = array();
        if (!empty($constants)) {
            foreach ($constants as $key => $value) {
                $tmpArray[] = "$key: " . self::encode($value);
            }

            $result .= implode(', ', $tmpArray);
        }

        return $result . "}";
    }


    /**
     * Encode the public methods of the ReflectionClass in the
     * class2 format
     *
     * @param ReflectionClass $cls
     * @return string Encoded method fragment
     *
     */
    private static function _encodeMethods(ReflectionClass $cls)
    {
        $methods = $cls->getMethods();
        $result = 'methods:{';

        $started = false;
        foreach ($methods as $method) {
            if (! $method->isPublic() || !$method->isUserDefined()) {
                continue;
            }

            if ($started) {
                $result .= ',';
            }
            $started = true;

            $result .= '' . $method->getName(). ':function(';

            if ('__construct' != $method->getName()) {
                $parameters  = $method->getParameters();
                $paramCount  = count($parameters);
                $argsStarted = false;

                $argNames = "var argNames=[";
                foreach ($parameters as $param) {
                    if ($argsStarted) {
                        $result .= ',';
                    }

                    $result .= $param->getName();

                    if ($argsStarted) {
                        $argNames .= ',';
                    }

                    $argNames .= '"' . $param->getName() . '"';

                    $argsStarted = true;
                }
                $argNames .= "];";

                $result .= "){"
                         . $argNames
                         . 'var result = ZAjaxEngine.invokeRemoteMethod('
                         . "this, '" . $method->getName()
                         . "',argNames,arguments);"
                         . 'return(result);}';
            } else {
                $result .= "){}";
            }
        }

        return $result . "}";
    }


    /**
     * Encode the public properties of the ReflectionClass in the class2
     * format.
     *
     * @param ReflectionClass $cls
     * @return string Encode properties list
     *
     */
    private static function _encodeVariables(ReflectionClass $cls)
    {
        $properties = $cls->getProperties();
        $propValues = get_class_vars($cls->getName());
        $result = "variables:{";
        $cnt = 0;

        $tmpArray = array();
        foreach ($properties as $prop) {
            if (! $prop->isPublic()) {
                continue;
            }

            $tmpArray[] = $prop->getName()
                        . ':'
                        . self::encode($propValues[$prop->getName()]);
        }
        $result .= implode(',', $tmpArray);

        return $result . "}";
    }

    /**
     * Encodes the given $className into the class2 model of encoding PHP
     * classes into JavaScript class2 classes.
     * NOTE: Currently only public methods and variables are proxied onto
     * the client machine
     *
     * @param $className string The name of the class, the class must be
     * instantiable using a null constructor
     * @param $package string Optional package name appended to JavaScript
     * proxy class name
     * @return string The class2 (JavaScript) encoding of the class
     * @throws InvalidArgumentException
     */
    public static function encodeClass($className, $package = '')
    {
        $cls = new \ReflectionClass($className);
        if (! $cls->isInstantiable()) {
            throw new InvalidArgumentException("'{$className}' must be instantiable");
        }

        return "Class.create('$package$className',{"
                . self::_encodeConstants($cls)    .","
                . self::_encodeMethods($cls)      .","
                . self::_encodeVariables($cls)    .'});';
    }


    /**
     * Encode several classes at once
     *
     * Returns JSON encoded classes, using {@link encodeClass()}.
     *
     * @param array $classNames
     * @param string $package
     * @return string
     */
    public static function encodeClasses(array $classNames, $package = '')
    {
        $result = '';
        foreach ($classNames as $className) {
            $result .= static::encodeClass($className, $package);
        }

        return $result;
    }

    /**
     * Encode Unicode Characters to \u0000 ASCII syntax.
     *
     * This algorithm was originally developed for the
     * Solar Framework by Paul M. Jones
     *
     * @link   http://solarphp.com/
     * @link   http://svn.solarphp.com/core/trunk/Solar/JSON.php
     * @param  string $value
     * @return string
     */
    public static function encodeUnicodeString($value)
    {
        $strlenVar = strlen($value);
        $ascii = "";

        /**
         * Iterate over every character in the string,
         * escaping with a slash or encoding to UTF-8 where necessary
         */
        for ($i = 0; $i < $strlenVar; $i++) {
            $ordVarC = ord($value[$i]);

            switch (true) {
                case (($ordVarC >= 0x20) && ($ordVarC <= 0x7F)):
                    // characters U-00000000 - U-0000007F (same as ASCII)
                    $ascii .= $value[$i];
                    break;

                case (($ordVarC & 0xE0) == 0xC0):
                    // characters U-00000080 - U-000007FF, mask 110XXXXX
                    // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
                    $char = pack('C*', $ordVarC, ord($value[$i + 1]));
                    $i += 1;
                    $utf16 = self::_utf82utf16($char);
                    $ascii .= sprintf('\u%04s', bin2hex($utf16));
                    break;

                case (($ordVarC & 0xF0) == 0xE0):
                    // characters U-00000800 - U-0000FFFF, mask 1110XXXX
                    // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
                    $char = pack('C*', $ordVarC,
                                 ord($value[$i + 1]),
                                 ord($value[$i + 2]));
                    $i += 2;
                    $utf16 = self::_utf82utf16($char);
                    $ascii .= sprintf('\u%04s', bin2hex($utf16));
                    break;

                case (($ordVarC & 0xF8) == 0xF0):
                    // characters U-00010000 - U-001FFFFF, mask 11110XXX
                    // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
                    $char = pack('C*', $ordVarC,
                                 ord($value[$i + 1]),
                                 ord($value[$i + 2]),
                                 ord($value[$i + 3]));
                    $i += 3;
                    $utf16 = self::_utf82utf16($char);
                    $ascii .= sprintf('\u%04s', bin2hex($utf16));
                    break;

                case (($ordVarC & 0xFC) == 0xF8):
                    // characters U-00200000 - U-03FFFFFF, mask 111110XX
                    // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
                    $char = pack('C*', $ordVarC,
                                 ord($value[$i + 1]),
                                 ord($value[$i + 2]),
                                 ord($value[$i + 3]),
                                 ord($value[$i + 4]));
                    $i += 4;
                    $utf16 = self::_utf82utf16($char);
                    $ascii .= sprintf('\u%04s', bin2hex($utf16));
                    break;

                case (($ordVarC & 0xFE) == 0xFC):
                    // characters U-04000000 - U-7FFFFFFF, mask 1111110X
                    // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
                    $char = pack('C*', $ordVarC,
                                 ord($value[$i + 1]),
                                 ord($value[$i + 2]),
                                 ord($value[$i + 3]),
                                 ord($value[$i + 4]),
                                 ord($value[$i + 5]));
                    $i += 5;
                    $utf16 = self::_utf82utf16($char);
                    $ascii .= sprintf('\u%04s', bin2hex($utf16));
                    break;
            }
        }

        return $ascii;
     }

    /**
     * Convert a string from one UTF-8 char to one UTF-16 char.
     *
     * Normally should be handled by mb_convert_encoding, but
     * provides a slower PHP-only method for installations
     * that lack the multibyte string extension.
     *
     * This method is from the Solar Framework by Paul M. Jones
     *
     * @link   http://solarphp.com
     * @param string $utf8 UTF-8 character
     * @return string UTF-16 character
     */
    protected static function _utf82utf16($utf8)
    {
        // Check for mb extension otherwise do by hand.
        if (function_exists('mb_convert_encoding')) {
            return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
        }

        switch (strlen($utf8)) {
            case 1:
                // this case should never be reached, because we are in ASCII range
                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
                return $utf8;

            case 2:
                // return a UTF-16 character from a 2-byte UTF-8 char
                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
                return chr(0x07 & (ord($utf8{0}) >> 2))
                     . chr((0xC0 & (ord($utf8{0}) << 6))
                         | (0x3F & ord($utf8{1})));

            case 3:
                // return a UTF-16 character from a 3-byte UTF-8 char
                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
                return chr((0xF0 & (ord($utf8{0}) << 4))
                         | (0x0F & (ord($utf8{1}) >> 2)))
                     . chr((0xC0 & (ord($utf8{1}) << 6))
                         | (0x7F & ord($utf8{2})));
        }

        // ignoring UTF-32 for now, sorry
        return '';
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Json;

/**
 * Class for Zend\Json\Json encode method.
 *
 * This class simply holds a string with a native Javascript Expression,
 * so objects | arrays to be encoded with Zend\Json\Json can contain native
 * Javascript Expressions.
 *
 * Example:
 * <code>
 * $foo = array(
 *     'integer'  => 9,
 *     'string'   => 'test string',
 *     'function' => Zend\Json\Expr(
 *         'function () { window.alert("javascript function encoded by Zend\Json\Json") }'
 *     ),
 * );
 *
 * Zend\Json\Json::encode($foo, false, array('enableJsonExprFinder' => true));
 * // it will returns json encoded string:
 * // {"integer":9,"string":"test string","function":function () {window.alert("javascript function encoded by Zend\Json\Json")}}
 * </code>
 */
class Expr
{
    /**
     * Storage for javascript expression.
     *
     * @var string
     */
    protected $expression;

    /**
     * Constructor
     *
     * @param  string $expression the expression to hold.
     */
    public function __construct($expression)
    {
        $this->expression = (string) $expression;
    }

    /**
     * Cast to string
     *
     * @return string holded javascript expression.
     */
    public function __toString()
    {
        return $this->expression;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Json\Exception;

class InvalidArgumentException extends \InvalidArgumentException implements
    ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Json\Exception;

class RuntimeException extends \RuntimeException implements ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Json\Exception;

interface ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Json\Exception;

class BadMethodCallException extends \BadMethodCallException implements
    ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Json\Exception;

class RecursionException extends RuntimeException
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Json;

use SimpleXMLElement;
use Zend\Json\Exception\RecursionException;
use Zend\Json\Exception\RuntimeException;

/**
 * Class for encoding to and decoding from JSON.
 */
class Json
{
    /**
     * How objects should be encoded -- arrays or as stdClass. TYPE_ARRAY is 1
     * so that it is a boolean true value, allowing it to be used with
     * ext/json's functions.
     */
    const TYPE_ARRAY  = 1;
    const TYPE_OBJECT = 0;

     /**
      * To check the allowed nesting depth of the XML tree during xml2json conversion.
      *
      * @var int
      */
    public static $maxRecursionDepthAllowed = 25;

    /**
     * @var bool
     */
    public static $useBuiltinEncoderDecoder = false;

    /**
     * Decodes the given $encodedValue string which is
     * encoded in the JSON format
     *
     * Uses ext/json's json_decode if available.
     *
     * @param string $encodedValue Encoded in JSON format
     * @param int $objectDecodeType Optional; flag indicating how to decode
     * objects. See {@link Zend\Json\Decoder::decode()} for details.
     * @return mixed
     * @throws RuntimeException
     */
    public static function decode($encodedValue, $objectDecodeType = self::TYPE_OBJECT)
    {
        $encodedValue = (string) $encodedValue;
        if (function_exists('json_decode') && static::$useBuiltinEncoderDecoder !== true) {
            $decode = json_decode($encodedValue, $objectDecodeType);

            switch (json_last_error()) {
                case JSON_ERROR_NONE:
                    break;
                case JSON_ERROR_DEPTH:
                    throw new RuntimeException('Decoding failed: Maximum stack depth exceeded');
                case JSON_ERROR_CTRL_CHAR:
                    throw new RuntimeException('Decoding failed: Unexpected control character found');
                case JSON_ERROR_SYNTAX:
                    throw new RuntimeException('Decoding failed: Syntax error');
                default:
                    throw new RuntimeException('Decoding failed');
            }

            return $decode;
        }

        return Decoder::decode($encodedValue, $objectDecodeType);
    }

    /**
     * Encode the mixed $valueToEncode into the JSON format
     *
     * Encodes using ext/json's json_encode() if available.
     *
     * NOTE: Object should not contain cycles; the JSON format
     * does not allow object reference.
     *
     * NOTE: Only public variables will be encoded
     *
     * NOTE: Encoding native javascript expressions are possible using Zend\Json\Expr.
     *       You can enable this by setting $options['enableJsonExprFinder'] = true
     *
     * @see Zend\Json\Expr
     *
     * @param  mixed $valueToEncode
     * @param  bool $cycleCheck Optional; whether or not to check for object recursion; off by default
     * @param  array $options Additional options used during encoding
     * @return string JSON encoded object
     */
    public static function encode($valueToEncode, $cycleCheck = false, $options = array())
    {
        if (is_object($valueToEncode)) {
            if (method_exists($valueToEncode, 'toJson')) {
                return $valueToEncode->toJson();
            } elseif (method_exists($valueToEncode, 'toArray')) {
                return static::encode($valueToEncode->toArray(), $cycleCheck, $options);
            }
        }

        // Pre-encoding look for Zend\Json\Expr objects and replacing by tmp ids
        $javascriptExpressions = array();
        if (isset($options['enableJsonExprFinder'])
           && ($options['enableJsonExprFinder'] == true)
        ) {
            $valueToEncode = static::_recursiveJsonExprFinder($valueToEncode, $javascriptExpressions);
        }

        // Encoding
        if (function_exists('json_encode') && static::$useBuiltinEncoderDecoder !== true) {
            $encodedResult = json_encode(
                $valueToEncode,
                JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP
            );
        } else {
            $encodedResult = Encoder::encode($valueToEncode, $cycleCheck, $options);
        }

        //only do post-processing to revert back the Zend\Json\Expr if any.
        if (count($javascriptExpressions) > 0) {
            $count = count($javascriptExpressions);
            for ($i = 0; $i < $count; $i++) {
                $magicKey = $javascriptExpressions[$i]['magicKey'];
                $value    = $javascriptExpressions[$i]['value'];

                $encodedResult = str_replace(
                    //instead of replacing "key:magicKey", we replace directly magicKey by value because "key" never changes.
                    '"' . $magicKey . '"',
                    $value,
                    $encodedResult
                );
            }
        }

        return $encodedResult;
    }

    /**
     * Check & Replace Zend\Json\Expr for tmp ids in the valueToEncode
     *
     * Check if the value is a Zend\Json\Expr, and if replace its value
     * with a magic key and save the javascript expression in an array.
     *
     * NOTE this method is recursive.
     *
     * NOTE: This method is used internally by the encode method.
     *
     * @see encode
     * @param mixed $value a string - object property to be encoded
     * @param array $javascriptExpressions
     * @param null|string|int $currentKey
     * @return mixed
     */
    protected static function _recursiveJsonExprFinder(
        &$value, array &$javascriptExpressions, $currentKey = null
    ) {
         if ($value instanceof Expr) {
            // TODO: Optimize with ascii keys, if performance is bad
            $magicKey = "____" . $currentKey . "_" . (count($javascriptExpressions));
            $javascriptExpressions[] = array(

                //if currentKey is integer, encodeUnicodeString call is not required.
                "magicKey" => (is_int($currentKey)) ? $magicKey : Encoder::encodeUnicodeString($magicKey),
                "value"    => $value->__toString(),
            );
            $value = $magicKey;
        } elseif (is_array($value)) {
            foreach ($value as $k => $v) {
                $value[$k] = static::_recursiveJsonExprFinder($value[$k], $javascriptExpressions, $k);
            }
        } elseif (is_object($value)) {
            foreach ($value as $k => $v) {
                $value->$k = static::_recursiveJsonExprFinder($value->$k, $javascriptExpressions, $k);
            }
        }
        return $value;
    }
    /**
     * Return the value of an XML attribute text or the text between
     * the XML tags
     *
     * In order to allow Zend\Json\Expr from xml, we check if the node
     * matches the pattern that try to detect if it is a new Zend\Json\Expr
     * if it matches, we return a new Zend\Json\Expr instead of a text node
     *
     * @param SimpleXMLElement $simpleXmlElementObject
     * @return Expr|string
     */
    protected static function _getXmlValue($simpleXmlElementObject)
    {
        $pattern   = '/^[\s]*new Zend[_\\]Json[_\\]Expr[\s]*\([\s]*[\"\']{1}(.*)[\"\']{1}[\s]*\)[\s]*$/';
        $matchings = array();
        $match     = preg_match($pattern, $simpleXmlElementObject, $matchings);
        if ($match) {
            return new Expr($matchings[1]);
        }
        return (trim(strval($simpleXmlElementObject)));
    }

    /**
     * _processXml - Contains the logic for xml2json
     *
     * The logic in this function is a recursive one.
     *
     * The main caller of this function (i.e. fromXml) needs to provide
     * only the first two parameters i.e. the SimpleXMLElement object and
     * the flag for ignoring or not ignoring XML attributes. The third parameter
     * will be used internally within this function during the recursive calls.
     *
     * This function converts the SimpleXMLElement object into a PHP array by
     * calling a recursive (protected static) function in this class. Once all
     * the XML elements are stored in the PHP array, it is returned to the caller.
     *
     * @param SimpleXMLElement $simpleXmlElementObject
     * @param  bool $ignoreXmlAttributes
     * @param int $recursionDepth
     * @throws Exception\RecursionException if the XML tree is deeper than the allowed limit.
     * @return array
     */
    protected static function _processXml($simpleXmlElementObject, $ignoreXmlAttributes, $recursionDepth = 0)
    {
        // Keep an eye on how deeply we are involved in recursion.
        if ($recursionDepth > static::$maxRecursionDepthAllowed) {
            // XML tree is too deep. Exit now by throwing an exception.
            throw new RecursionException(
                "Function _processXml exceeded the allowed recursion depth of "
                .  static::$maxRecursionDepthAllowed
            );
        }

        $children   = $simpleXmlElementObject->children();
        $name       = $simpleXmlElementObject->getName();
        $value      = static::_getXmlValue($simpleXmlElementObject);
        $attributes = (array) $simpleXmlElementObject->attributes();

        if (!count($children)) {
            if (!empty($attributes) && !$ignoreXmlAttributes) {
                foreach ($attributes['@attributes'] as $k => $v) {
                    $attributes['@attributes'][$k] = static::_getXmlValue($v);
                }
                if (!empty($value)) {
                    $attributes['@text'] = $value;
                }
                return array($name => $attributes);
            }

            return array($name => $value);
        }

        $childArray = array();
        foreach ($children as $child) {
            $childname = $child->getName();
            $element   = static::_processXml($child, $ignoreXmlAttributes, $recursionDepth + 1);
            if (array_key_exists($childname, $childArray)) {
                if (empty($subChild[$childname])) {
                    $childArray[$childname] = array($childArray[$childname]);
                    $subChild[$childname]   = true;
                }
                $childArray[$childname][] = $element[$childname];
            } else {
                $childArray[$childname] = $element[$childname];
            }
        }

        if (!empty($attributes) && !$ignoreXmlAttributes) {
            foreach ($attributes['@attributes'] as $k => $v) {
                $attributes['@attributes'][$k] = static::_getXmlValue($v);
            }
            $childArray['@attributes'] = $attributes['@attributes'];
        }

        if (!empty($value)) {
            $childArray['@text'] = $value;
        }

        return array($name => $childArray);
    }

    /**
     * fromXml - Converts XML to JSON
     *
     * Converts a XML formatted string into a JSON formatted string.
     * The value returned will be a string in JSON format.
     *
     * The caller of this function needs to provide only the first parameter,
     * which is an XML formatted String. The second parameter is optional, which
     * lets the user to select if the XML attributes in the input XML string
     * should be included or ignored in xml2json conversion.
     *
     * This function converts the XML formatted string into a PHP array by
     * calling a recursive (protected static) function in this class. Then, it
     * converts that PHP array into JSON by calling the "encode" static function.
     *
     * NOTE: Encoding native javascript expressions via Zend\Json\Expr is not possible.
     *
     * @static
     * @access public
     * @param string $xmlStringContents XML String to be converted
     * @param  bool $ignoreXmlAttributes Include or exclude XML attributes in
     * the xml2json conversion process.
     * @return mixed - JSON formatted string on success
     * @throws \Zend\Json\Exception\RuntimeException if the input not a XML formatted string
     */
    public static function fromXml($xmlStringContents, $ignoreXmlAttributes = true)
    {
        // Load the XML formatted string into a Simple XML Element object.
        $simpleXmlElementObject = simplexml_load_string($xmlStringContents);

        // If it is not a valid XML content, throw an exception.
        if ($simpleXmlElementObject == null) {
            throw new RuntimeException('Function fromXml was called with an invalid XML formatted string.');
        } // End of if ($simpleXmlElementObject == null)

        $resultArray = null;

        // Call the recursive function to convert the XML into a PHP array.
        $resultArray = static::_processXml($simpleXmlElementObject, $ignoreXmlAttributes);

        // Convert the PHP array to JSON using Zend\Json\Json encode method.
        // It is just that simple.
        $jsonStringOutput = static::encode($resultArray);
        return($jsonStringOutput);
    }

    /**
     * Pretty-print JSON string
     *
     * Use 'indent' option to select indentation string - by default it's a tab
     *
     * @param string $json Original JSON string
     * @param array $options Encoding options
     * @return string
     */
    public static function prettyPrint($json, $options = array())
    {
        $tokens = preg_split('|([\{\}\]\[,])|', $json, -1, PREG_SPLIT_DELIM_CAPTURE);
        $result = "";
        $indent = 0;

        $ind = "\t";
        if (isset($options['indent'])) {
            $ind = $options['indent'];
        }

        $inLiteral = false;
        foreach ($tokens as $token) {
            if ($token == "") continue;

            $prefix = str_repeat($ind, $indent);
            if (!$inLiteral && ($token == "{" || $token == "[")) {
                $indent++;
                if ($result != "" && $result[strlen($result)-1] == "\n") {
                    $result .= $prefix;
                }
                $result .= "$token\n";
            } elseif (!$inLiteral && ($token == "}" || $token == "]")) {
                $indent--;
                $prefix = str_repeat($ind, $indent);
                $result .= "\n$prefix$token";
            } elseif (!$inLiteral && $token == ",") {
                $result .= "$token\n";
            } else {
                $result .= ($inLiteral ?  '' : $prefix) . $token;

                // Count # of unescaped double-quotes in token, subtract # of
                // escaped double-quotes and if the result is odd then we are
                // inside a string literal
                if ((substr_count($token, "\"")-substr_count($token, "\\\"")) % 2 != 0) {
                    $inLiteral = !$inLiteral;
                }
            }
        }
        return $result;
   }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Json;

use stdClass;
use Zend\Json\Exception\InvalidArgumentException;
use Zend\Json\Exception\RuntimeException;

/**
 * Decode JSON encoded string to PHP variable constructs
 */
class Decoder
{

    /**
     * Parse tokens used to decode the JSON object. These are not
     * for public consumption, they are just used internally to the
     * class.
     */
    const EOF       = 0;
    const DATUM     = 1;
    const LBRACE    = 2;
    const LBRACKET  = 3;
    const RBRACE    = 4;
    const RBRACKET  = 5;
    const COMMA     = 6;
    const COLON     = 7;

    /**
     * Use to maintain a "pointer" to the source being decoded
     *
     * @var string
     */
    protected $source;

    /**
     * Caches the source length
     *
     * @var int
     */
    protected $sourceLength;

    /**
     * The offset within the source being decoded
     *
     * @var int
     *
     */
    protected $offset;

    /**
     * The current token being considered in the parser cycle
     *
     * @var int
     */
    protected $token;

    /**
     * Flag indicating how objects should be decoded
     *
     * @var int
     * @access protected
     */
    protected $decodeType;

    /**
     * @var $_tokenValue
     */
    protected $tokenValue;

    /**
     * Constructor
     *
     * @param string $source     String source to decode
     * @param int    $decodeType How objects should be decoded -- see
     * {@link Zend\Json\Json::TYPE_ARRAY} and {@link Zend\Json\Json::TYPE_OBJECT} for
     * valid values
     * @throws InvalidArgumentException
     */
    protected function __construct($source, $decodeType)
    {
        // Set defaults
        $this->source       = self::decodeUnicodeString($source);
        $this->sourceLength = strlen($this->source);
        $this->token        = self::EOF;
        $this->offset       = 0;

        switch ($decodeType) {
            case Json::TYPE_ARRAY:
            case Json::TYPE_OBJECT:
                $this->decodeType = $decodeType;
                break;
            default:
                throw new InvalidArgumentException("Unknown decode type '{$decodeType}', please use one of the constants Json::TYPE_*");
        }

        // Set pointer at first token
        $this->_getNextToken();
    }

    /**
     * Decode a JSON source string
     *
     * Decodes a JSON encoded string. The value returned will be one of the
     * following:
     *        - integer
     *        - float
     *        - boolean
     *        - null
     *      - stdClass
     *      - array
     *         - array of one or more of the above types
     *
     * By default, decoded objects will be returned as associative arrays; to
     * return a stdClass object instead, pass {@link Zend\Json\Json::TYPE_OBJECT} to
     * the $objectDecodeType parameter.
     *
     * @static
     * @access public
     * @param string $source String to be decoded
     * @param int $objectDecodeType How objects should be decoded; should be
     * either or {@link Zend\Json\Json::TYPE_ARRAY} or
     * {@link Zend\Json\Json::TYPE_OBJECT}; defaults to TYPE_ARRAY
     * @return mixed
     */
    public static function decode($source, $objectDecodeType = Json::TYPE_OBJECT)
    {
        $decoder = new static($source, $objectDecodeType);
        return $decoder->_decodeValue();
    }

    /**
     * Recursive driving routine for supported toplevel tops
     *
     * @return mixed
     */
    protected function _decodeValue()
    {
        switch ($this->token) {
            case self::DATUM:
                $result  = $this->tokenValue;
                $this->_getNextToken();
                return($result);
                break;
            case self::LBRACE:
                return($this->_decodeObject());
                break;
            case self::LBRACKET:
                return($this->_decodeArray());
                break;
            default:
                return null;
                break;
        }
    }

    /**
     * Decodes an object of the form:
     *  { "attribute: value, "attribute2" : value,...}
     *
     * If Zend\Json\Encoder was used to encode the original object then
     * a special attribute called __className which specifies a class
     * name that should wrap the data contained within the encoded source.
     *
     * Decodes to either an array or stdClass object, based on the value of
     * {@link $decodeType}. If invalid $decodeType present, returns as an
     * array.
     *
     * @return array|stdClass
     * @throws RuntimeException
     */
    protected function _decodeObject()
    {
        $members = array();
        $tok = $this->_getNextToken();

        while ($tok && $tok != self::RBRACE) {
            if ($tok != self::DATUM || ! is_string($this->tokenValue)) {
                throw new RuntimeException('Missing key in object encoding: ' . $this->source);
            }

            $key = $this->tokenValue;
            $tok = $this->_getNextToken();

            if ($tok != self::COLON) {
                throw new RuntimeException('Missing ":" in object encoding: ' . $this->source);
            }

            $tok = $this->_getNextToken();
            $members[$key] = $this->_decodeValue();
            $tok = $this->token;

            if ($tok == self::RBRACE) {
                break;
            }

            if ($tok != self::COMMA) {
                throw new RuntimeException('Missing "," in object encoding: ' . $this->source);
            }

            $tok = $this->_getNextToken();
        }

        switch ($this->decodeType) {
            case Json::TYPE_OBJECT:
                // Create new stdClass and populate with $members
                $result = new stdClass();
                foreach ($members as $key => $value) {
                    if ($key === '') {
                        $key = '_empty_';
                    }
                    $result->$key = $value;
                }
                break;
            case Json::TYPE_ARRAY:
            default:
                $result = $members;
                break;
        }

        $this->_getNextToken();
        return $result;
    }

    /**
     * Decodes a JSON array format:
     *    [element, element2,...,elementN]
     *
     * @return array
     * @throws RuntimeException
     */
    protected function _decodeArray()
    {
        $result = array();
        $tok = $this->_getNextToken(); // Move past the '['
        $index  = 0;

        while ($tok && $tok != self::RBRACKET) {
            $result[$index++] = $this->_decodeValue();

            $tok = $this->token;

            if ($tok == self::RBRACKET || !$tok) {
                break;
            }

            if ($tok != self::COMMA) {
                throw new RuntimeException('Missing "," in array encoding: ' . $this->source);
            }

            $tok = $this->_getNextToken();
        }

        $this->_getNextToken();
        return $result;
    }


    /**
     * Removes whitespace characters from the source input
     */
    protected function _eatWhitespace()
    {
        if (preg_match(
                '/([\t\b\f\n\r ])*/s',
                $this->source,
                $matches,
                PREG_OFFSET_CAPTURE,
                $this->offset)
            && $matches[0][1] == $this->offset)
        {
            $this->offset += strlen($matches[0][0]);
        }
    }


    /**
     * Retrieves the next token from the source stream
     *
     * @return int Token constant value specified in class definition
     * @throws RuntimeException
     */
    protected function _getNextToken()
    {
        $this->token      = self::EOF;
        $this->tokenValue = null;
        $this->_eatWhitespace();

        if ($this->offset >= $this->sourceLength) {
            return(self::EOF);
        }

        $str       = $this->source;
        $strLength = $this->sourceLength;
        $i         = $this->offset;
        $start     = $i;

        switch ($str{$i}) {
            case '{':
               $this->token = self::LBRACE;
               break;
            case '}':
                $this->token = self::RBRACE;
                break;
            case '[':
                $this->token = self::LBRACKET;
                break;
            case ']':
                $this->token = self::RBRACKET;
                break;
            case ',':
                $this->token = self::COMMA;
                break;
            case ':':
                $this->token = self::COLON;
                break;
            case  '"':
                $result = '';
                do {
                    $i++;
                    if ($i >= $strLength) {
                        break;
                    }

                    $chr = $str{$i};

                    if ($chr == '\\') {
                        $i++;
                        if ($i >= $strLength) {
                            break;
                        }
                        $chr = $str{$i};
                        switch ($chr) {
                            case '"' :
                                $result .= '"';
                                break;
                            case '\\':
                                $result .= '\\';
                                break;
                            case '/' :
                                $result .= '/';
                                break;
                            case 'b' :
                                $result .= "\x08";
                                break;
                            case 'f' :
                                $result .= "\x0c";
                                break;
                            case 'n' :
                                $result .= "\x0a";
                                break;
                            case 'r' :
                                $result .= "\x0d";
                                break;
                            case 't' :
                                $result .= "\x09";
                                break;
                            case '\'' :
                                $result .= '\'';
                                break;
                            default:
                                throw new RuntimeException("Illegal escape sequence '{$chr}'");
                        }
                    } elseif ($chr == '"') {
                        break;
                    } else {
                        $result .= $chr;
                    }
                } while ($i < $strLength);

                $this->token = self::DATUM;
                //$this->tokenValue = substr($str, $start + 1, $i - $start - 1);
                $this->tokenValue = $result;
                break;
            case 't':
                if (($i+ 3) < $strLength && substr($str, $start, 4) == "true") {
                    $this->token = self::DATUM;
                }
                $this->tokenValue = true;
                $i += 3;
                break;
            case 'f':
                if (($i+ 4) < $strLength && substr($str, $start, 5) == "false") {
                    $this->token = self::DATUM;
                }
                $this->tokenValue = false;
                $i += 4;
                break;
            case 'n':
                if (($i+ 3) < $strLength && substr($str, $start, 4) == "null") {
                    $this->token = self::DATUM;
                }
                $this->tokenValue = NULL;
                $i += 3;
                break;
        }

        if ($this->token != self::EOF) {
            $this->offset = $i + 1; // Consume the last token character
            return($this->token);
        }

        $chr = $str{$i};
        if ($chr == '-' || $chr == '.' || ($chr >= '0' && $chr <= '9')) {
            if (preg_match('/-?([0-9])*(\.[0-9]*)?((e|E)((-|\+)?)[0-9]+)?/s',
                $str, $matches, PREG_OFFSET_CAPTURE, $start) && $matches[0][1] == $start) {

                $datum = $matches[0][0];

                if (is_numeric($datum)) {
                    if (preg_match('/^0\d+$/', $datum)) {
                        throw new RuntimeException("Octal notation not supported by JSON (value: {$datum})");
                    } else {
                        $val  = intval($datum);
                        $fVal = floatval($datum);
                        $this->tokenValue = ($val == $fVal ? $val : $fVal);
                    }
                } else {
                    throw new RuntimeException("Illegal number format: {$datum}");
                }

                $this->token = self::DATUM;
                $this->offset = $start + strlen($datum);
            }
        } else {
            throw new RuntimeException('Illegal Token');
        }

        return $this->token;
    }

    /**
     * Decode Unicode Characters from \u0000 ASCII syntax.
     *
     * This algorithm was originally developed for the
     * Solar Framework by Paul M. Jones
     *
     * @link   http://solarphp.com/
     * @link   http://svn.solarphp.com/core/trunk/Solar/Json.php
     * @param  string $chrs
     * @return string
     */
    public static function decodeUnicodeString($chrs)
    {
        $chrs       = (string) $chrs;
        $utf8       = '';
        $strlenChrs = strlen($chrs);

        for ($i = 0; $i < $strlenChrs; $i++) {
            $ordChrsC = ord($chrs[$i]);

            switch (true) {
                case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $i, 6)):
                    // single, escaped unicode character
                    $utf16 = chr(hexdec(substr($chrs, ($i + 2), 2)))
                           . chr(hexdec(substr($chrs, ($i + 4), 2)));
                    $utf8char = self::_utf162utf8($utf16);
                    $search  = array('\\', "\n", "\t", "\r", chr(0x08), chr(0x0C), '"', '\'', '/');
                    if (in_array($utf8char, $search)) {
                        $replace = array('\\\\', '\\n', '\\t', '\\r', '\\b', '\\f', '\\"', '\\\'', '\\/');
                        $utf8char  = str_replace($search, $replace, $utf8char);
                    }
                    $utf8 .= $utf8char;
                    $i += 5;
                    break;
                case ($ordChrsC >= 0x20) && ($ordChrsC <= 0x7F):
                    $utf8 .= $chrs{$i};
                    break;
                case ($ordChrsC & 0xE0) == 0xC0:
                    // characters U-00000080 - U-000007FF, mask 110XXXXX
                    //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
                    $utf8 .= substr($chrs, $i, 2);
                    ++$i;
                    break;
                case ($ordChrsC & 0xF0) == 0xE0:
                    // characters U-00000800 - U-0000FFFF, mask 1110XXXX
                    // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
                    $utf8 .= substr($chrs, $i, 3);
                    $i += 2;
                    break;
                case ($ordChrsC & 0xF8) == 0xF0:
                    // characters U-00010000 - U-001FFFFF, mask 11110XXX
                    // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
                    $utf8 .= substr($chrs, $i, 4);
                    $i += 3;
                    break;
                case ($ordChrsC & 0xFC) == 0xF8:
                    // characters U-00200000 - U-03FFFFFF, mask 111110XX
                    // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
                    $utf8 .= substr($chrs, $i, 5);
                    $i += 4;
                    break;
                case ($ordChrsC & 0xFE) == 0xFC:
                    // characters U-04000000 - U-7FFFFFFF, mask 1111110X
                    // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
                    $utf8 .= substr($chrs, $i, 6);
                    $i += 5;
                    break;
            }
        }

        return $utf8;
    }

    /**
     * Convert a string from one UTF-16 char to one UTF-8 char.
     *
     * Normally should be handled by mb_convert_encoding, but
     * provides a slower PHP-only method for installations
     * that lack the multibyte string extension.
     *
     * This method is from the Solar Framework by Paul M. Jones
     *
     * @link   http://solarphp.com
     * @param  string $utf16 UTF-16 character
     * @return string UTF-8 character
     */
    protected static function _utf162utf8($utf16)
    {
        // Check for mb extension otherwise do by hand.
        if (function_exists('mb_convert_encoding')) {
            return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
        }

        $bytes = (ord($utf16{0}) << 8) | ord($utf16{1});

        switch (true) {
            case ((0x7F & $bytes) == $bytes):
                // this case should never be reached, because we are in ASCII range
                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
                return chr(0x7F & $bytes);

            case (0x07FF & $bytes) == $bytes:
                // return a 2-byte UTF-8 character
                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
                return chr(0xC0 | (($bytes >> 6) & 0x1F))
                     . chr(0x80 | ($bytes & 0x3F));

            case (0xFFFF & $bytes) == $bytes:
                // return a 3-byte UTF-8 character
                // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
                return chr(0xE0 | (($bytes >> 12) & 0x0F))
                     . chr(0x80 | (($bytes >> 6) & 0x3F))
                     . chr(0x80 | ($bytes & 0x3F));
        }

        // ignoring UTF-32 for now, sorry
        return '';
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Json\Server\Request;

use Zend\Json\Server\Request as JsonRequest;

class Http extends JsonRequest
{
    /**
     * Raw JSON pulled from POST body
     * @var string
     */
    protected $rawJson;

    /**
     * Constructor
     *
     * Pull JSON request from raw POST body and use to populate request.
     *
     */
    public function __construct()
    {
        $json = file_get_contents('php://input');
        $this->rawJson = $json;
        if (!empty($json)) {
            $this->loadJson($json);
        }
    }

    /**
     * Get JSON from raw POST body
     *
     * @return string
     */
    public function getRawJson()
    {
        return $this->rawJson;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Json\Server;

class Error
{
    const ERROR_PARSE           = -32700;
    const ERROR_INVALID_REQUEST = -32600;
    const ERROR_INVALID_METHOD  = -32601;
    const ERROR_INVALID_PARAMS  = -32602;
    const ERROR_INTERNAL        = -32603;
    const ERROR_OTHER           = -32000;

    /**
     * Allowed error codes
     * @var array
     */
    protected $allowedCodes = array(
        self::ERROR_PARSE,
        self::ERROR_INVALID_REQUEST,
        self::ERROR_INVALID_METHOD,
        self::ERROR_INVALID_PARAMS,
        self::ERROR_INTERNAL,
        self::ERROR_OTHER,
    );

    /**
     * Current code
     * @var int
     */
    protected $code = -32000;

    /**
     * Error data
     * @var mixed
     */
    protected $data;

    /**
     * Error message
     * @var string
     */
    protected $message;

    /**
     * Constructor
     *
     * @param  string $message
     * @param  int $code
     * @param  mixed $data
     */
    public function __construct($message = null, $code = -32000, $data = null)
    {
        $this->setMessage($message)
             ->setCode($code)
             ->setData($data);
    }

    /**
     * Set error code
     *
     * @param  int $code
     * @return \Zend\Json\Server\Error
     */
    public function setCode($code)
    {
        if (!is_scalar($code)) {
            return $this;
        }

        $code = (int) $code;
        if (in_array($code, $this->allowedCodes)) {
            $this->code = $code;
        } elseif (in_array($code, range(-32099, -32000))) {
            $this->code = $code;
        }

        return $this;
    }

    /**
     * Get error code
     *
     * @return int|null
     */
    public function getCode()
    {
        return $this->code;
    }

    /**
     * Set error message
     *
     * @param  string $message
     * @return \Zend\Json\Server\Error
     */
    public function setMessage($message)
    {
        if (!is_scalar($message)) {
            return $this;
        }

        $this->message = (string) $message;
        return $this;
    }

    /**
     * Get error message
     *
     * @return string
     */
    public function getMessage()
    {
        return $this->message;
    }

    /**
     * Set error data
     *
     * @param  mixed $data
     * @return \Zend\Json\Server\Error
     */
    public function setData($data)
    {
        $this->data = $data;
        return $this;
    }

    /**
     * Get error data
     *
     * @return mixed
     */
    public function getData()
    {
        return $this->data;
    }

    /**
     * Cast error to array
     *
     * @return array
     */
    public function toArray()
    {
        return array(
            'code'    => $this->getCode(),
            'message' => $this->getMessage(),
            'data'    => $this->getData(),
        );
    }

    /**
     * Cast error to JSON
     *
     * @return string
     */
    public function toJson()
    {
        return \Zend\Json\Json::encode($this->toArray());
    }

    /**
     * Cast to string (JSON)
     *
     * @return string
     */
    public function __toString()
    {
        return $this->toJson();
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Json\Server;

use Zend\Server\Cache as ServerCache;
use Zend\Stdlib\ErrorHandler;

/**
 * Zend\Json\Server\Cache: cache Zend\Json\Server\Server server definition and SMD
 */
class Cache extends ServerCache
{
    /**
     * Cache a service map description (SMD) to a file
     *
     * Returns true on success, false on failure
     *
     * @param  string $filename
     * @param  \Zend\Json\Server\Server $server
     * @return bool
     */
    public static function saveSmd($filename, Server $server)
    {
        if (!is_string($filename)
            || (!file_exists($filename) && !is_writable(dirname($filename))))
        {
            return false;
        }

        ErrorHandler::start();
        $test = file_put_contents($filename, $server->getServiceMap()->toJson());
        ErrorHandler::stop();

        if (0 === $test) {
            return false;
        }

        return true;
    }

    /**
     * Retrieve a cached SMD
     *
     * On success, returns the cached SMD (a JSON string); an failure, returns
     * boolean false.
     *
     * @param  string $filename
     * @return string|false
     */
    public static function getSmd($filename)
    {
        if (!is_string($filename)
            || !file_exists($filename)
            || !is_readable($filename))
        {
            return false;
        }

        ErrorHandler::start();
        $smd = file_get_contents($filename);
        ErrorHandler::stop();

        if (false === $smd) {
            return false;
        }

        return $smd;
    }

    /**
     * Delete a file containing a cached SMD
     *
     * @param  string $filename
     * @return bool
     */
    public static function deleteSmd($filename)
    {
        if (is_string($filename) && file_exists($filename)) {
            unlink($filename);
            return true;
        }

        return false;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Json\Server;

use Zend\Json\Server\Exception\InvalidArgumentException;
use Zend\Json\Server\Exception\RuntimeException;

class Smd
{
    const ENV_JSONRPC_1 = 'JSON-RPC-1.0';
    const ENV_JSONRPC_2 = 'JSON-RPC-2.0';
    const SMD_VERSION   = '2.0';

    /**
     * Content type
     * @var string
     */
    protected $contentType = 'application/json';

    /**
     * Content type regex
     * @var string
     */
    protected $contentTypeRegex = '#[a-z]+/[a-z][a-z-]+#i';

    /**
     * Service description
     * @var string
     */
    protected $description;

    /**
     * Generate Dojo-compatible SMD
     * @var bool
     */
    protected $dojoCompatible = false;

    /**
     * Current envelope
     * @var string
     */
    protected $envelope = self::ENV_JSONRPC_1;

    /**
     * Allowed envelope types
     * @var array
     */
    protected $envelopeTypes = array(
        self::ENV_JSONRPC_1,
        self::ENV_JSONRPC_2,
    );

    /**
     * Service id
     * @var string
     */
    protected $id;

    /**
     * Services offered
     * @var array
     */
    protected $services = array();

    /**
     * Service target
     * @var string
     */
    protected $target;

    /**
     * Global transport
     * @var string
     */
    protected $transport = 'POST';

    /**
     * Allowed transport types
     * @var array
     */
    protected $transportTypes = array('POST');

    /**
     * Set object state via options
     *
     * @param  array $options
     * @return Smd
     */
    public function setOptions(array $options)
    {
        foreach ($options as $key => $value) {
            $method = 'set' . ucfirst($key);
            if (method_exists($this, $method)) {
                $this->$method($value);
            }
        }
        return $this;
    }

    /**
     * Set transport
     *
     * @param  string $transport
     * @throws Exception\InvalidArgumentException
     * @return \Zend\Json\Server\Smd
     */
    public function setTransport($transport)
    {
        if (!in_array($transport, $this->transportTypes)) {
            throw new InvalidArgumentException("Invalid transport '{$transport}' specified");
        }
        $this->transport = $transport;
        return $this;
    }

    /**
     * Get transport
     *
     * @return string
     */
    public function getTransport()
    {
        return $this->transport;
    }

    /**
     * Set envelope
     *
     * @param  string $envelopeType
     * @throws Exception\InvalidArgumentException
     * @return Smd
     */
    public function setEnvelope($envelopeType)
    {
        if (!in_array($envelopeType, $this->envelopeTypes)) {
            throw new InvalidArgumentException("Invalid envelope type '{$envelopeType}'");
        }
        $this->envelope = $envelopeType;
        return $this;
    }

    /**
     * Retrieve envelope
     *
     * @return string
     */
    public function getEnvelope()
    {
        return $this->envelope;
    }

    // Content-Type of response; default to application/json
    /**
     * Set content type
     *
     * @param  string $type
     * @throws Exception\InvalidArgumentException
     * @return \Zend\Json\Server\Smd
     */
    public function setContentType($type)
    {
        if (!preg_match($this->contentTypeRegex, $type)) {
            throw new InvalidArgumentException("Invalid content type '{$type}' specified");
        }
        $this->contentType = $type;
        return $this;
    }

    /**
     * Retrieve content type
     *
     * @return string
     */
    public function getContentType()
    {
        return $this->contentType;
    }

    /**
     * Set service target
     *
     * @param  string $target
     * @return Smd
     */
    public function setTarget($target)
    {
        $this->target = (string) $target;
        return $this;
    }

    /**
     * Retrieve service target
     *
     * @return string
     */
    public function getTarget()
    {
        return $this->target;
    }

    /**
     * Set service ID
     *
     * @param  string $id
     * @return Smd
     */
    public function setId($id)
    {
        $this->id = (string) $id;
        return $this->id;
    }

    /**
     * Get service id
     *
     * @return string
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set service description
     *
     * @param  string $description
     * @return Smd
     */
    public function setDescription($description)
    {
        $this->description = (string) $description;
        return $this->description;
    }

    /**
     * Get service description
     *
     * @return string
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     * Indicate whether or not to generate Dojo-compatible SMD
     *
     * @param  bool $flag
     * @return Smd
     */
    public function setDojoCompatible($flag)
    {
        $this->dojoCompatible = (bool) $flag;
        return $this;
    }

    /**
     * Is this a Dojo compatible SMD?
     *
     * @return bool
     */
    public function isDojoCompatible()
    {
        return $this->dojoCompatible;
    }

    /**
     * Add Service
     *
     * @param Smd\Service|array $service
     * @throws Exception\RuntimeException
     * @throws Exception\InvalidArgumentException
     * @return Smd
     */
    public function addService($service)
    {
        if ($service instanceof Smd\Service) {
            $name = $service->getName();
        } elseif (is_array($service)) {
            $service = new Smd\Service($service);
            $name = $service->getName();
        } else {
            throw new InvalidArgumentException('Invalid service passed to addService()');
        }

        if (array_key_exists($name, $this->services)) {
            throw new RuntimeException('Attempt to register a service already registered detected');
        }
        $this->services[$name] = $service;
        return $this;
    }

    /**
     * Add many services
     *
     * @param  array $services
     * @return Smd
     */
    public function addServices(array $services)
    {
        foreach ($services as $service) {
            $this->addService($service);
        }
        return $this;
    }

    /**
     * Overwrite existing services with new ones
     *
     * @param  array $services
     * @return Smd
     */
    public function setServices(array $services)
    {
        $this->services = array();
        return $this->addServices($services);
    }

    /**
     * Get service object
     *
     * @param  string $name
     * @return bool|Smd\Service
     */
    public function getService($name)
    {
        if (array_key_exists($name, $this->services)) {
            return $this->services[$name];
        }
        return false;
    }

    /**
     * Return services
     *
     * @return array
     */
    public function getServices()
    {
        return $this->services;
    }

    /**
     * Remove service
     *
     * @param  string $name
     * @return bool
     */
    public function removeService($name)
    {
        if (array_key_exists($name, $this->services)) {
            unset($this->services[$name]);
            return true;
        }
        return false;
    }

    /**
     * Cast to array
     *
     * @return array
     */
    public function toArray()
    {
        if ($this->isDojoCompatible()) {
            return $this->toDojoArray();
        }

        $transport   = $this->getTransport();
        $envelope    = $this->getEnvelope();
        $contentType = $this->getContentType();
        $SMDVersion  = static::SMD_VERSION;
        $service = compact('transport', 'envelope', 'contentType', 'SMDVersion');

        if (null !== ($target = $this->getTarget())) {
            $service['target']     = $target;
        }
        if (null !== ($id = $this->getId())) {
            $service['id'] = $id;
        }

        $services = $this->getServices();
        if (!empty($services)) {
            $service['services'] = array();
            foreach ($services as $name => $svc) {
                $svc->setEnvelope($envelope);
                $service['services'][$name] = $svc->toArray();
            }
            $service['methods'] = $service['services'];
        }

        return $service;
    }

    /**
     * Export to DOJO-compatible SMD array
     *
     * @return array
     */
    public function toDojoArray()
    {
        $SMDVersion  = '.1';
        $serviceType = 'JSON-RPC';
        $service = compact('SMDVersion', 'serviceType');

        $target = $this->getTarget();

        $services = $this->getServices();
        if (!empty($services)) {
            $service['methods'] = array();
            foreach ($services as $name => $svc) {
                $method = array(
                    'name'       => $name,
                    'serviceURL' => $target,
                );
                $params = array();
                foreach ($svc->getParams() as $param) {
                    $paramName = array_key_exists('name', $param) ? $param['name'] : $param['type'];
                    $params[] = array(
                        'name' => $paramName,
                        'type' => $param['type'],
                    );
                }
                if (!empty($params)) {
                    $method['parameters'] = $params;
                }
                $service['methods'][] = $method;
            }
        }

        return $service;
    }

    /**
     * Cast to JSON
     *
     * @return string
     */
    public function toJson()
    {
        return \Zend\Json\Json::encode($this->toArray());
    }

    /**
     * Cast to string (JSON)
     *
     * @return string
     */
    public function __toString()
    {
        return $this->toJson();
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Json\Server\Smd;

use Zend\Json\Server;
use Zend\Json\Server\Exception\InvalidArgumentException;
use Zend\Json\Server\Smd;

/**
 * Create Service Mapping Description for a method
 *
 * @todo       Revised method regex to allow NS; however, should SMD be revised to strip PHP NS instead when attaching functions?
 */
class Service
{
    /**#@+
     * Service metadata
     * @var string
     */
    protected $envelope  = Smd::ENV_JSONRPC_1;
    protected $name;
    protected $return;
    protected $target;
    protected $transport = 'POST';
    /**#@-*/

    /**
     * Allowed envelope types
     * @var array
     */
    protected $envelopeTypes = array(
        Smd::ENV_JSONRPC_1,
        Smd::ENV_JSONRPC_2,
    );

    /**
     * Regex for names
     * @var string
     */
    protected $nameRegex = '/^[a-z][a-z0-9.\\\\_]+$/i';

    /**
     * Parameter option types
     * @var array
     */
    protected $paramOptionTypes = array(
        'name'        => 'is_string',
        'optional'    => 'is_bool',
        'default'     => null,
        'description' => 'is_string',
    );

    /**
     * Service params
     * @var array
     */
    protected $params = array();

    /**
     * Mapping of parameter types to JSON-RPC types
     * @var array
     */
    protected $paramMap = array(
        'any'     => 'any',
        'arr'     => 'array',
        'array'   => 'array',
        'assoc'   => 'object',
        'bool'    => 'boolean',
        'boolean' => 'boolean',
        'dbl'     => 'float',
        'double'  => 'float',
        'false'   => 'boolean',
        'float'   => 'float',
        'hash'    => 'object',
        'integer' => 'integer',
        'int'     => 'integer',
        'mixed'   => 'any',
        'nil'     => 'null',
        'null'    => 'null',
        'object'  => 'object',
        'string'  => 'string',
        'str'     => 'string',
        'struct'  => 'object',
        'true'    => 'boolean',
        'void'    => 'null',
    );

    /**
     * Allowed transport types
     * @var array
     */
    protected $transportTypes = array(
        'POST',
    );

    /**
     * Constructor
     *
     * @param  string|array $spec
     * @throws InvalidArgumentException if no name provided
     */
    public function __construct($spec)
    {
        if (is_string($spec)) {
            $this->setName($spec);
        } elseif (is_array($spec)) {
            $this->setOptions($spec);
        }

        if (null == $this->getName()) {
            throw new InvalidArgumentException('SMD service description requires a name; none provided');
        }
    }

    /**
     * Set object state
     *
     * @param  array $options
     * @return Service
     */
    public function setOptions(array $options)
    {
        $methods = get_class_methods($this);
        foreach ($options as $key => $value) {
            if ('options' == strtolower($key)) {
                continue;
            }
            $method = 'set' . ucfirst($key);
            if (in_array($method, $methods)) {
                $this->$method($value);
            }
        }
        return $this;
    }

    /**
     * Set service name
     *
     * @param  string $name
     * @return Service
     * @throws InvalidArgumentException
     */
    public function setName($name)
    {
        $name = (string) $name;
        if (!preg_match($this->nameRegex, $name)) {
            throw new InvalidArgumentException("Invalid name '{$name} provided for service; must follow PHP method naming conventions");
        }
        $this->name = $name;
        return $this;
    }

    /**
     * Retrieve name
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Set Transport
     *
     * Currently limited to POST
     *
     * @param  string $transport
     * @throws InvalidArgumentException
     * @return Service
     */
    public function setTransport($transport)
    {
        if (!in_array($transport, $this->transportTypes)) {
            throw new InvalidArgumentException("Invalid transport '{$transport}'; please select one of (" . implode(', ', $this->transportTypes) . ')');
        }

        $this->transport = $transport;
        return $this;
    }

    /**
     * Get transport
     *
     * @return string
     */
    public function getTransport()
    {
        return $this->transport;
    }

    /**
     * Set service target
     *
     * @param  string $target
     * @return Service
     */
    public function setTarget($target)
    {
        $this->target = (string) $target;
        return $this;
    }

    /**
     * Get service target
     *
     * @return string
     */
    public function getTarget()
    {
        return $this->target;
    }

    /**
     * Set envelope type
     *
     * @param  string $envelopeType
     * @throws InvalidArgumentException
     * @return Service
     */
    public function setEnvelope($envelopeType)
    {
        if (!in_array($envelopeType, $this->envelopeTypes)) {
            throw new InvalidArgumentException("Invalid envelope type '{$envelopeType}'; please specify one of (" . implode(', ', $this->envelopeTypes) . ')');
        }

        $this->envelope = $envelopeType;
        return $this;
    }

    /**
     * Get envelope type
     *
     * @return string
     */
    public function getEnvelope()
    {
        return $this->envelope;
    }

    /**
     * Add a parameter to the service
     *
     * @param  string|array $type
     * @param  array $options
     * @param  int|null $order
     * @throws InvalidArgumentException
     * @return Service
     */
    public function addParam($type, array $options = array(), $order = null)
    {
        if (is_string($type)) {
            $type = $this->_validateParamType($type);
        } elseif (is_array($type)) {
            foreach ($type as $key => $paramType) {
                $type[$key] = $this->_validateParamType($paramType);
            }
        } else {
            throw new InvalidArgumentException('Invalid param type provided');
        }

        $paramOptions = array(
            'type' => $type,
        );
        foreach ($options as $key => $value) {
            if (in_array($key, array_keys($this->paramOptionTypes))) {
                if (null !== ($callback = $this->paramOptionTypes[$key])) {
                    if (!$callback($value)) {
                        continue;
                    }
                }
                $paramOptions[$key] = $value;
            }
        }

        $this->params[] = array(
            'param' => $paramOptions,
            'order' => $order,
        );

        return $this;
    }

    /**
     * Add params
     *
     * Each param should be an array, and should include the key 'type'.
     *
     * @param  array $params
     * @return Service
     */
    public function addParams(array $params)
    {
        ksort($params);
        foreach ($params as $options) {
            if (!is_array($options)) {
                continue;
            }
            if (!array_key_exists('type', $options)) {
                continue;
            }
            $type  = $options['type'];
            $order = (array_key_exists('order', $options)) ? $options['order'] : null;
            $this->addParam($type, $options, $order);
        }
        return $this;
    }

    /**
     * Overwrite all parameters
     *
     * @param  array $params
     * @return Service
     */
    public function setParams(array $params)
    {
        $this->params = array();
        return $this->addParams($params);
    }

    /**
     * Get all parameters
     *
     * Returns all params in specified order.
     *
     * @return array
     */
    public function getParams()
    {
        $params = array();
        $index  = 0;
        foreach ($this->params as $param) {
            if (null === $param['order']) {
                if (array_search($index, array_keys($params), true)) {
                    ++$index;
                }
                $params[$index] = $param['param'];
                ++$index;
            } else {
                $params[$param['order']] = $param['param'];
            }
        }
        ksort($params);
        return $params;
    }

    /**
     * Set return type
     *
     * @param  string|array $type
     * @throws InvalidArgumentException
     * @return Service
     */
    public function setReturn($type)
    {
        if (is_string($type)) {
            $type = $this->_validateParamType($type, true);
        } elseif (is_array($type)) {
            foreach ($type as $key => $returnType) {
                $type[$key] = $this->_validateParamType($returnType, true);
            }
        } else {
            throw new InvalidArgumentException("Invalid param type provided ('" . gettype($type) . "')");
        }
        $this->return = $type;
        return $this;
    }

    /**
     * Get return type
     *
     * @return string|array
     */
    public function getReturn()
    {
        return $this->return;
    }

    /**
     * Cast service description to array
     *
     * @return array
     */
    public function toArray()
    {
        $envelope   = $this->getEnvelope();
        $target     = $this->getTarget();
        $transport  = $this->getTransport();
        $parameters = $this->getParams();
        $returns    = $this->getReturn();

        if (empty($target)) {
            return compact('envelope', 'transport', 'parameters', 'returns');
        }

        return $paramInfo = compact('envelope', 'target', 'transport', 'parameters', 'returns');
    }

    /**
     * Return JSON encoding of service
     *
     * @return string
     */
    public function toJson()
    {
        $service = array($this->getName() => $this->toArray());
        return \Zend\Json\Json::encode($service);
    }

    /**
     * Cast to string
     *
     * @return string
     */
    public function __toString()
    {
        return $this->toJson();
    }

    /**
     * Validate parameter type
     *
     * @param string  $type
     * @param  bool $isReturn
     * @return string
     * @throws InvalidArgumentException
     */
    protected function _validateParamType($type, $isReturn = false)
    {
        if (!is_string($type)) {
            throw new InvalidArgumentException("Invalid param type provided ('{$type}')");
        }

        if (!array_key_exists($type, $this->paramMap)) {
            $type = 'object';
        }

        $paramType = $this->paramMap[$type];
        if (!$isReturn && ('null' == $paramType)) {
            throw new InvalidArgumentException("Invalid param type provided ('{$type}')");
        }

        return $paramType;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Json\Server;

use ReflectionFunction;
use ReflectionMethod;
use Zend\Server\AbstractServer;
use Zend\Server\Definition;
use Zend\Server\Method;
use Zend\Server\Reflection;

class Server extends AbstractServer
{
    /**#@+
     * Version Constants
     */
    const VERSION_1 = '1.0';
    const VERSION_2 = '2.0';
    /**#@-*/

    /**
     * Flag: whether or not to auto-emit the response
     * @var bool
     */
    protected $returnResponse = false;

    /**
     * Inherited from Zend\Server\AbstractServer
     *
     * @var bool Flag; allow overwriting existing methods when creating server definition
     */
    protected $overwriteExistingMethods = true;

    /**
     * Request object
     * @var Request
     */
    protected $request;

    /**
     * Response object
     * @var Response
     */
    protected $response;

    /**
     * SMD object
     * @var Smd
     */
    protected $serviceMap;

    /**
     * SMD class accessors
     * @var array
     */
    protected $smdMethods;

    /**
     * Attach a function or callback to the server
     *
     * @param  string|array|callable $function   Valid PHP callback
     * @param  string                $namespace  Ignored
     * @throws Exception\InvalidArgumentException if function invalid or not callable
     * @return Server
     */
    public function addFunction($function, $namespace = '')
    {
        if (!is_string($function) && (!is_array($function) || (2 > count($function)))) {
            throw new Exception\InvalidArgumentException('Unable to attach function; invalid');
        }

        if (!is_callable($function)) {
            throw new Exception\InvalidArgumentException('Unable to attach function; does not exist');
        }

        $argv = null;
        if (2 < func_num_args()) {
            $argv = func_get_args();
            $argv = array_slice($argv, 2);
        }

        if (is_string($function)) {
            $method = Reflection::reflectFunction($function, $argv, $namespace);
        } else {
            $class  = array_shift($function);
            $action = array_shift($function);
            $reflection = Reflection::reflectClass($class, $argv, $namespace);
            $methods = $reflection->getMethods();
            $found   = false;
            foreach ($methods as $method) {
                if ($action == $method->getName()) {
                    $found = true;
                    break;
                }
            }
            if (!$found) {
                $this->fault('Method not found', Error::ERROR_INVALID_METHOD);
                return $this;
            }
        }

        $definition = $this->_buildSignature($method);
        $this->_addMethodServiceMap($definition);

        return $this;
    }

    /**
     * Register a class with the server
     *
     * @param  string $class
     * @param  string $namespace Ignored
     * @param  mixed $argv Ignored
     * @return Server
     */
    public function setClass($class, $namespace = '', $argv = null)
    {
        if (2 < func_num_args()) {
            $argv = func_get_args();
            $argv = array_slice($argv, 2);
        }

        $reflection = Reflection::reflectClass($class, $argv, $namespace);

        foreach ($reflection->getMethods() as $method) {
            $definition = $this->_buildSignature($method, $class);
            $this->_addMethodServiceMap($definition);
        }
        return $this;
    }

    /**
     * Indicate fault response
     *
     * @param  string $fault
     * @param  int $code
     * @param  mixed $data
     * @return Error
     */
    public function fault($fault = null, $code = 404, $data = null)
    {
        $error = new Error($fault, $code, $data);
        $this->getResponse()->setError($error);
        return $error;
    }

    /**
     * Handle request
     *
     * @param  Request $request
     * @return null|Response
     * @throws Exception\InvalidArgumentException
     */
    public function handle($request = false)
    {
        if ((false !== $request) && (!$request instanceof Request)) {
            throw new Exception\InvalidArgumentException('Invalid request type provided; cannot handle');
        } elseif ($request) {
            $this->setRequest($request);
        }

        // Handle request
        $this->_handle();

        // Get response
        $response = $this->_getReadyResponse();

        // Emit response?
        if (!$this->returnResponse) {
            echo $response;
            return;
        }

        // or return it?
        return $response;
    }

    /**
     * Load function definitions
     *
     * @param  array|Definition $definition
     * @throws Exception\InvalidArgumentException
     * @return void
     */
    public function loadFunctions($definition)
    {
        if (!is_array($definition) && (!$definition instanceof Definition)) {
            throw new Exception\InvalidArgumentException('Invalid definition provided to loadFunctions()');
        }

        foreach ($definition as $key => $method) {
            $this->table->addMethod($method, $key);
            $this->_addMethodServiceMap($method);
        }
    }

    public function setPersistence($mode)
    {
    }

    /**
     * Set request object
     *
     * @param  Request $request
     * @return Server
     */
    public function setRequest(Request $request)
    {
        $this->request = $request;
        return $this;
    }

    /**
     * Get JSON-RPC request object
     *
     * @return Request
     */
    public function getRequest()
    {
        if (null === ($request = $this->request)) {
            $this->setRequest(new Request\Http());
        }
        return $this->request;
    }

    /**
     * Set response object
     *
     * @param  Response $response
     * @return Server
     */
    public function setResponse(Response $response)
    {
        $this->response = $response;
        return $this;
    }

    /**
     * Get response object
     *
     * @return Response
     */
    public function getResponse()
    {
        if (null === ($response = $this->response)) {
            $this->setResponse(new Response\Http());
        }
        return $this->response;
    }

    /**
     * Set return response flag
     *
     * If true, {@link handle()} will return the response instead of
     * automatically sending it back to the requesting client.
     *
     * The response is always available via {@link getResponse()}.
     *
     * @param  bool $flag
     * @return Server
     */
    public function setReturnResponse($flag = true)
    {
        $this->returnResponse = ($flag) ? true : false;
        return $this;
    }

    /**
     * Retrieve return response flag
     *
     * @return bool
     */
    public function getReturnResponse()
    {
        return $this->returnResponse;
    }

    // overloading for SMD metadata
    /**
     * Overload to accessors of SMD object
     *
     * @param  string $method
     * @param  array $args
     * @return mixed
     */
    public function __call($method, $args)
    {
        if (preg_match('/^(set|get)/', $method, $matches)) {
            if (in_array($method, $this->_getSmdMethods())) {
                if ('set' == $matches[1]) {
                    $value = array_shift($args);
                    $this->getServiceMap()->$method($value);
                    return $this;
                } else {
                    return $this->getServiceMap()->$method();
                }
            }
        }
        return null;
    }

    /**
     * Retrieve SMD object
     *
     * @return Smd
     */
    public function getServiceMap()
    {
        if (null === $this->serviceMap) {
            $this->serviceMap = new Smd();
        }
        return $this->serviceMap;
    }

    /**
     * Add service method to service map
     *
     * @param  Method\Definition $method
     * @return void
     */
    protected function _addMethodServiceMap(Method\Definition $method)
    {
        $serviceInfo = array(
            'name'   => $method->getName(),
            'return' => $this->_getReturnType($method),
        );
        $params = $this->_getParams($method);
        $serviceInfo['params'] = $params;
        $serviceMap = $this->getServiceMap();
        if (false !== $serviceMap->getService($serviceInfo['name'])) {
            $serviceMap->removeService($serviceInfo['name']);
        }
        $serviceMap->addService($serviceInfo);
    }

    /**
     * Translate PHP type to JSON type
     *
     * @param  string $type
     * @return string
     */
    protected function _fixType($type)
    {
        return $type;
    }

    /**
     * Get default params from signature
     *
     * @param  array $args
     * @param  array $params
     * @return array
     */
    protected function _getDefaultParams(array $args, array $params)
    {
        $defaultParams = array_slice($params, count($args));
        foreach ($defaultParams as $param) {
            $value = null;
            if (array_key_exists('default', $param)) {
                $value = $param['default'];
            }
            $args[$param['name']] = $value;
        }
        return $args;
    }

    /**
     * Get method param type
     *
     * @param  Method\Definition $method
     * @return string|array
     */
    protected function _getParams(Method\Definition $method)
    {
        $params = array();
        foreach ($method->getPrototypes() as $prototype) {
            foreach ($prototype->getParameterObjects() as $key => $parameter) {
                if (!isset($params[$key])) {
                    $params[$key] = array(
                        'type'     => $parameter->getType(),
                        'name'     => $parameter->getName(),
                        'optional' => $parameter->isOptional(),
                    );
                    if (null !== ($default = $parameter->getDefaultValue())) {
                        $params[$key]['default'] = $default;
                    }
                    $description = $parameter->getDescription();
                    if (!empty($description)) {
                        $params[$key]['description'] = $description;
                    }
                    continue;
                }
                $newType = $parameter->getType();
                if (!is_array($params[$key]['type'])) {
                    if ($params[$key]['type'] == $newType) {
                        continue;
                    }
                    $params[$key]['type'] = (array) $params[$key]['type'];
                } elseif (in_array($newType, $params[$key]['type'])) {
                    continue;
                }
                array_push($params[$key]['type'], $parameter->getType());
            }
        }
        return $params;
    }

    /**
     * Set response state
     *
     * @return Response
     */
    protected function _getReadyResponse()
    {
        $request  = $this->getRequest();
        $response = $this->getResponse();

        $response->setServiceMap($this->getServiceMap());
        if (null !== ($id = $request->getId())) {
            $response->setId($id);
        }
        if (null !== ($version = $request->getVersion())) {
            $response->setVersion($version);
        }

        return $response;
    }

    /**
     * Get method return type
     *
     * @param  Method\Definition $method
     * @return string|array
     */
    protected function _getReturnType(Method\Definition $method)
    {
        $return = array();
        foreach ($method->getPrototypes() as $prototype) {
            $return[] = $prototype->getReturnType();
        }
        if (1 == count($return)) {
            return $return[0];
        }
        return $return;
    }

    /**
     * Retrieve list of allowed SMD methods for proxying
     *
     * @return array
     */
    protected function _getSmdMethods()
    {
        if (null === $this->smdMethods) {
            $this->smdMethods = array();
            $methods = get_class_methods('Zend\\Json\\Server\\Smd');
            foreach ($methods as $method) {
                if (!preg_match('/^(set|get)/', $method)) {
                    continue;
                }
                if (strstr($method, 'Service')) {
                    continue;
                }
                $this->smdMethods[] = $method;
            }
        }
        return $this->smdMethods;
    }

    /**
     * Internal method for handling request
     *
     * @return void
     */
    protected function _handle()
    {
        $request = $this->getRequest();

        if($request->isParseError()){
            return $this->fault('Parse error', Error::ERROR_PARSE);
        }

        if (!$request->isMethodError() && (null === $request->getMethod())) {
            return $this->fault('Invalid Request', Error::ERROR_INVALID_REQUEST);
        }

        if ($request->isMethodError()) {
            return $this->fault('Invalid Request', Error::ERROR_INVALID_REQUEST);
        }

        $method = $request->getMethod();
        if (!$this->table->hasMethod($method)) {
            return $this->fault('Method not found', Error::ERROR_INVALID_METHOD);
        }

        $params        = $request->getParams();
        $invokable     = $this->table->getMethod($method);
        $serviceMap    = $this->getServiceMap();
        $service       = $serviceMap->getService($method);
        $serviceParams = $service->getParams();

        if (count($params) < count($serviceParams)) {
            $params = $this->_getDefaultParams($params, $serviceParams);
        }

        //Make sure named parameters are passed in correct order
        if (is_string(key($params))) {
            $callback = $invokable->getCallback();
            if ('function' == $callback->getType()) {
                $reflection = new ReflectionFunction($callback->getFunction());
            } else {

                $reflection = new ReflectionMethod(
                    $callback->getClass(),
                    $callback->getMethod()
                );
            }

            $orderedParams = array();
            foreach ($reflection->getParameters() as $refParam) {
                if (array_key_exists($refParam->getName(), $params)) {
                    $orderedParams[$refParam->getName()] = $params[$refParam->getName()];
                } elseif ($refParam->isOptional()) {
                    $orderedParams[$refParam->getName()] = null;
                } else {
                    return $this->fault('Invalid params', Error::ERROR_INVALID_PARAMS);
                }
            }
            $params = $orderedParams;
        }

        try {
            $result = $this->_dispatch($invokable, $params);
        } catch (\Exception $e) {
            return $this->fault($e->getMessage(), $e->getCode(), $e);
        }

        $this->getResponse()->setResult($result);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Json\Server\Exception;

use Zend\Json\Exception;

class InvalidArgumentException extends Exception\InvalidArgumentException implements
    ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Json\Server\Exception;

use Zend\Json\Exception;

class RuntimeException extends Exception\RuntimeException implements
    ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Json\Server\Exception;

use Zend\Json\Exception\ExceptionInterface as Exception;

interface ExceptionInterface extends Exception
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Json\Server\Exception;

use Zend\Json\Exception;

/**
 * Thrown by Zend\Json\Server\Client when an JSON-RPC fault response is returned.
 */
class ErrorException extends Exception\BadMethodCallException implements
    ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Json\Server\Exception;

/**
 * Thrown by Zend\Json\Server\Client when an HTTP error occurs during an
 * JSON-RPC method call.
 */
class HttpException extends RuntimeException
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Json\Server;

use Zend\Json;

/**
 * @todo       Revised method regex to allow NS; however, should SMD be revised to strip PHP NS instead when attaching functions?
 */
class Request
{
    /**
     * Request ID
     * @var mixed
     */
    protected $id;

    /**
     * Flag
     * @var bool
     */
    protected $isMethodError = false;

    /**
     * Flag
     * @var bool
     */
    protected $isParseError = false;

    /**
     * Requested method
     * @var string
     */
    protected $method;

    /**
     * Regex for method
     * @var string
     */
    protected $methodRegex = '/^[a-z][a-z0-9\\\\_.]*$/i';

    /**
     * Request parameters
     * @var array
     */
    protected $params = array();

    /**
     * JSON-RPC version of request
     * @var string
     */
    protected $version = '1.0';

    /**
     * Set request state
     *
     * @param  array $options
     * @return \Zend\Json\Server\Request
     */
    public function setOptions(array $options)
    {
        $methods = get_class_methods($this);
        foreach ($options as $key => $value) {
            $method = 'set' . ucfirst($key);
            if (in_array($method, $methods)) {
                $this->$method($value);
            } elseif ($key == 'jsonrpc') {
                $this->setVersion($value);
            }
        }
        return $this;
    }

    /**
     * Add a parameter to the request
     *
     * @param  mixed $value
     * @param  string $key
     * @return \Zend\Json\Server\Request
     */
    public function addParam($value, $key = null)
    {
        if ((null === $key) || !is_string($key)) {
            $index = count($this->params);
            $this->params[$index] = $value;
        } else {
            $this->params[$key] = $value;
        }

        return $this;
    }

    /**
     * Add many params
     *
     * @param  array $params
     * @return \Zend\Json\Server\Request
     */
    public function addParams(array $params)
    {
        foreach ($params as $key => $value) {
            $this->addParam($value, $key);
        }
        return $this;
    }

    /**
     * Overwrite params
     *
     * @param  array $params
     * @return \Zend\Json\Server\Request
     */
    public function setParams(array $params)
    {
        $this->params = array();
        return $this->addParams($params);
    }

    /**
     * Retrieve param by index or key
     *
     * @param  int|string $index
     * @return mixed|null Null when not found
     */
    public function getParam($index)
    {
        if (array_key_exists($index, $this->params)) {
            return $this->params[$index];
        }

        return null;
    }

    /**
     * Retrieve parameters
     *
     * @return array
     */
    public function getParams()
    {
        return $this->params;
    }

    /**
     * Set request method
     *
     * @param  string $name
     * @return \Zend\Json\Server\Request
     */
    public function setMethod($name)
    {
        if (!preg_match($this->methodRegex, $name)) {
            $this->isMethodError = true;
        } else {
            $this->method = $name;
        }
        return $this;
    }

    /**
     * Get request method name
     *
     * @return string
     */
    public function getMethod()
    {
        return $this->method;
    }

    /**
     * Was a bad method provided?
     *
     * @return bool
     */
    public function isMethodError()
    {
        return $this->isMethodError;
    }

    /**
     * Was a malformed JSON provided?
     *
     * @return bool
     */
    public function isParseError()
    {
        return $this->isParseError;
    }

    /**
     * Set request identifier
     *
     * @param  mixed $name
     * @return \Zend\Json\Server\Request
     */
    public function setId($name)
    {
        $this->id = (string) $name;
        return $this;
    }

    /**
     * Retrieve request identifier
     *
     * @return mixed
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set JSON-RPC version
     *
     * @param  string $version
     * @return \Zend\Json\Server\Request
     */
    public function setVersion($version)
    {
        if ('2.0' == $version) {
            $this->version = '2.0';
        } else {
            $this->version = '1.0';
        }
        return $this;
    }

    /**
     * Retrieve JSON-RPC version
     *
     * @return string
     */
    public function getVersion()
    {
        return $this->version;
    }

    /**
     * Set request state based on JSON
     *
     * @param  string $json
     * @return void
     */
    public function loadJson($json)
    {
        try {
            $options = Json\Json::decode($json, Json\Json::TYPE_ARRAY);
            $this->setOptions($options);
        } catch(\Exception $e) {
            $this->isParseError = true;
        }
    }

    /**
     * Cast request to JSON
     *
     * @return string
     */
    public function toJson()
    {
        $jsonArray = array(
            'method' => $this->getMethod()
        );
        if (null !== ($id = $this->getId())) {
            $jsonArray['id'] = $id;
        }
        $params = $this->getParams();
        if (!empty($params)) {
            $jsonArray['params'] = $params;
        }
        if ('2.0' == $this->getVersion()) {
            $jsonArray['jsonrpc'] = '2.0';
        }

        return Json\Json::encode($jsonArray);
    }

    /**
     * Cast request to string (JSON)
     *
     * @return string
     */
    public function __toString()
    {
        return $this->toJson();
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Json\Server\Response;

use Zend\Json\Server\Response as JsonResponse;

class Http extends JsonResponse
{
    /**
     * Emit JSON
     *
     * Send appropriate HTTP headers. If no Id, then return an empty string.
     *
     * @return string
     */
    public function toJson()
    {
        $this->sendHeaders();
        if (!$this->isError() && null === $this->getId()) {
            return '';
        }

        return parent::toJson();
    }

    /**
     * Send headers
     *
     * If headers are already sent, do nothing. If null ID, send HTTP 204
     * header. Otherwise, send content type header based on content type of
     * service map.
     *
     * @return void
     */
    public function sendHeaders()
    {
        if (headers_sent()) {
            return;
        }

        if (!$this->isError() && (null === $this->getId())) {
            header('HTTP/1.1 204 No Content');
            return;
        }

        if (null === ($smd = $this->getServiceMap())) {
            return;
        }

        $contentType = $smd->getContentType();
        if (!empty($contentType)) {
            header('Content-Type: ' . $contentType);
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Json\Server;

use Zend\Json\Json;

class Response
{
    /**
     * Response error
     * @var null|Error
     */
    protected $error;

    /**
     * Request ID
     * @var mixed
     */
    protected $id;

    /**
     * Result
     * @var mixed
     */
    protected $result;

    /**
     * Service map
     * @var Smd
     */
    protected $serviceMap;

    /**
     * JSON-RPC version
     * @var string
     */
    protected $version;

    /**
     * @var $args
     */
    protected $args;

    /**
     * Set response state
     *
     * @param  array $options
     * @return Response
     */
    public function setOptions(array $options)
    {
        // re-produce error state
        if (isset($options['error']) && is_array($options['error'])) {
            $error = $options['error'];
            $options['error'] = new Error($error['message'], $error['code'], $error['data']);
        }

        $methods = get_class_methods($this);
        foreach ($options as $key => $value) {
            $method = 'set' . ucfirst($key);
            if (in_array($method, $methods)) {
                $this->$method($value);
            } elseif ($key == 'jsonrpc') {
                $this->setVersion($value);
            }
        }
        return $this;
    }

    /**
     * Set response state based on JSON
     *
     * @param  string $json
     * @return void
     */
    public function loadJson($json)
    {
        $options = Json::decode($json, Json::TYPE_ARRAY);
        $this->setOptions($options);
    }

    /**
     * Set result
     *
     * @param  mixed $value
     * @return Response
     */
    public function setResult($value)
    {
        $this->result = $value;
        return $this;
    }

    /**
     * Get result
     *
     * @return mixed
     */
    public function getResult()
    {
        return $this->result;
    }

    // RPC error, if response results in fault
    /**
     * Set result error
     *
     * @param  mixed $error
     * @return Response
     */
    public function setError(Error $error = null)
    {
        $this->error = $error;
        return $this;
    }

    /**
     * Get response error
     *
     * @return null|Error
     */
    public function getError()
    {
        return $this->error;
    }

    /**
     * Is the response an error?
     *
     * @return bool
     */
    public function isError()
    {
        return $this->getError() instanceof Error;
    }

    /**
     * Set request ID
     *
     * @param  mixed $name
     * @return Response
     */
    public function setId($name)
    {
        $this->id = $name;
        return $this;
    }

    /**
     * Get request ID
     *
     * @return mixed
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set JSON-RPC version
     *
     * @param  string $version
     * @return Response
     */
    public function setVersion($version)
    {
        $version = (string) $version;
        if ('2.0' == $version) {
            $this->version = '2.0';
        } else {
            $this->version = null;
        }

        return $this;
    }

    /**
     * Retrieve JSON-RPC version
     *
     * @return string
     */
    public function getVersion()
    {
        return $this->version;
    }

    /**
     * Cast to JSON
     *
     * @return string
     */
    public function toJson()
    {
        if ($this->isError()) {
            $response = array(
                'error'  => $this->getError()->toArray(),
                'id'     => $this->getId(),
            );
        } else {
            $response = array(
                'result' => $this->getResult(),
                'id'     => $this->getId(),
            );
        }

        if (null !== ($version = $this->getVersion())) {
            $response['jsonrpc'] = $version;
        }

        return \Zend\Json\Json::encode($response);
    }

    /**
     * Retrieve args
     *
     * @return mixed
     */
    public function getArgs()
    {
        return $this->args;
    }

    /**
     * Set args
     *
     * @param mixed $args
     * @return self
     */
    public function setArgs($args)
    {
        $this->args = $args;
        return $this;
    }

    /**
     * Set service map object
     *
     * @param  Smd $serviceMap
     * @return Response
     */
    public function setServiceMap($serviceMap)
    {
        $this->serviceMap = $serviceMap;
        return $this;
    }

    /**
     * Retrieve service map
     *
     * @return Smd|null
     */
    public function getServiceMap()
    {
        return $this->serviceMap;
    }

    /**
     * Cast to string (JSON)
     *
     * @return string
     */
    public function __toString()
    {
        return $this->toJson();
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Json\Server;

use Zend\Http\Client as HttpClient;
use Zend\Server\Client as ServerClient;

class Client implements ServerClient
{
    /**
     * Full address of the JSON-RPC service.
     *
     * @var string
     */
    protected $serverAddress;

    /**
     * HTTP Client to use for requests.
     *
     * @var HttpClient
     */
    protected $httpClient;

    /**
     * Request of the last method call.
     *
     * @var Request
     */
    protected $lastRequest;

    /**
     * Response received from the last method call.
     *
     * @var Response
     */
    protected $lastResponse;

    /**
     * Request ID counter.
     *
     * @var int
     */
    protected $id = 0;

    /**
     * Create a new JSON-RPC client to a remote server.
     *
     * @param string $server Full address of the JSON-RPC service.
     * @param HttpClient $httpClient HTTP Client to use for requests.
     */
    public function __construct($server, HttpClient $httpClient = null)
    {
        $this->httpClient = $httpClient ?: new HttpClient();
        $this->serverAddress = $server;
    }

    /**
     * Sets the HTTP client object to use for connecting the JSON-RPC server.
     *
     * @param  HttpClient $httpClient New HTTP client to use.
     * @return Client Self instance.
     */
    public function setHttpClient(HttpClient $httpClient)
    {
        $this->httpClient = $httpClient;
        return $this;
    }

    /**
     * Gets the HTTP client object.
     *
     * @return HttpClient HTTP client.
     */
    public function getHttpClient()
    {
        return $this->httpClient;
    }

    /**
     * The request of the last method call.
     *
     * @return Request Request instance.
     */
    public function getLastRequest()
    {
        return $this->lastRequest;
    }

    /**
     * The response received from the last method call.
     *
     * @return Response Response instance.
     */
    public function getLastResponse()
    {
        return $this->lastResponse;
    }

    /**
     * Perform an JSOC-RPC request and return a response.
     *
     * @param  Request $request Request.
     * @return Response Response.
     * @throws Exception\HttpException When HTTP communication fails.
     */
    public function doRequest($request)
    {
        $this->lastRequest = $request;

        $httpRequest = $this->httpClient->getRequest();
        if ($httpRequest->getUriString() === null) {
            $this->httpClient->setUri($this->serverAddress);
        }

        $headers = $httpRequest->getHeaders();
        $headers->addHeaders(array(
            'Content-Type' => 'application/json',
            'Accept'       => 'application/json',
        ));

        if (!$headers->get('User-Agent')) {
            $headers->addHeaderLine('User-Agent', 'Zend_Json_Server_Client');
        }

        $this->httpClient->setRawBody($request->__toString());
        $this->httpClient->setMethod('POST');
        $httpResponse = $this->httpClient->send();

        if (!$httpResponse->isSuccess()) {
            throw new Exception\HttpException(
                $httpResponse->getReasonPhrase(),
                $httpResponse->getStatusCode()
            );
        }

        $response = new Response();

        $this->lastResponse = $response;

        // import all response data form JSON HTTP response
        $response->loadJson($httpResponse->getBody());

        return $response;
    }

    /**
     * Send an JSON-RPC request to the service (for a specific method).
     *
     * @param  string $method Name of the method we want to call.
     * @param  array $params Array of parameters for the method.
     * @return mixed Method call results.
     * @throws Exception\ErrorException When remote call fails.
     */
    public function call($method, $params = array())
    {
        $request = $this->createRequest($method, $params);

        $response = $this->doRequest($request);

        if ($response->isError()) {
            $error = $response->getError();
            throw new Exception\ErrorException(
                $error->getMessage(),
                $error->getCode()
            );
        }

        return $response->getResult();
    }

    /**
     * Create request object.
     *
     * @param  string $method Method to call.
     * @param  array $params List of arguments.
     * @return Request Created request.
     */
    protected function createRequest($method, array $params)
    {
        $request = new Request();
        $request->setMethod($method)
            ->setParams($params)
            ->setId(++$this->id);
        return $request;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib;

interface ArraySerializableInterface
{
    /**
     * Exchange internal values from provided array
     *
     * @param  array $array
     * @return void
     */
    public function exchangeArray(array $array);

    /**
     * Return an array representation of the object
     *
     * @return array
     */
    public function getArrayCopy();
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib;

use ArrayAccess;
use Countable;
use Serializable;
use Traversable;

/*
 * Basically, an ArrayObject. You could simply define something like:
 *     class QueryParams extends ArrayObject implements Parameters {}
 * and have 90% of the functionality
 */
interface ParametersInterface extends ArrayAccess, Countable, Serializable, Traversable
{
    /**
     * Constructor
     *
     * @param array $values
     */
    public function __construct(array $values = null);

    /**
     * From array
     *
     * Allow deserialization from standard array
     *
     * @param array $values
     * @return mixed
     */
    public function fromArray(array $values);

    /**
     * From string
     *
     * Allow deserialization from raw body; e.g., for PUT requests
     *
     * @param $string
     * @return mixed
     */
    public function fromString($string);

    /**
     * To array
     *
     * Allow serialization back to standard array
     *
     * @return mixed
     */
    public function toArray();

    /**
     * To string
     *
     * Allow serialization to query format; e.g., for PUT or POST requests
     *
     * @return mixed
     */
    public function toString();

    /**
     * Get
     *
     * @param string $name
     * @param mixed|null $default
     * @return mixed
     */
    public function get($name, $default = null);

    /**
     * Set
     *
     * @param string $name
     * @param mixed $value
     * @return ParametersInterface
     */
    public function set($name, $value);
}
{
    "name": "zendframework/zend-stdlib",
    "description": " ",
    "license": "BSD-3-Clause",
    "keywords": [
        "zf2",
        "stdlib"
    ],
    "autoload": {
        "psr-0": {
            "Zend\\Stdlib\\": ""
        }
    },
    "target-dir": "Zend/Stdlib",
    "suggest": {
        "zendframework/zend-servicemanager": "To support hydrator plugin manager usage",
        "zendframework/zend-eventmanager":   "To support aggregate hydrator usage"
    },
    "require": {
        "php": ">=5.3.3"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "2.2-dev",
            "dev-develop": "2.3-dev"
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib;

use Traversable;

class Message implements MessageInterface
{
    /**
     * @var array
     */
    protected $metadata = array();

    /**
     * @var string
     */
    protected $content = '';

    /**
     * Set message metadata
     *
     * Non-destructive setting of message metadata; always adds to the metadata, never overwrites
     * the entire metadata container.
     *
     * @param  string|int|array|Traversable $spec
     * @param  mixed $value
     * @throws Exception\InvalidArgumentException
     * @return Message
     */
    public function setMetadata($spec, $value = null)
    {
        if (is_scalar($spec)) {
            $this->metadata[$spec] = $value;
            return $this;
        }
        if (!is_array($spec) && !$spec instanceof Traversable) {
            throw new Exception\InvalidArgumentException(sprintf(
                'Expected a string, array, or Traversable argument in first position; received "%s"',
                (is_object($spec) ? get_class($spec) : gettype($spec))
            ));
        }
        foreach ($spec as $key => $value) {
            $this->metadata[$key] = $value;
        }
        return $this;
    }

    /**
     * Retrieve all metadata or a single metadatum as specified by key
     *
     * @param  null|string|int $key
     * @param  null|mixed $default
     * @throws Exception\InvalidArgumentException
     * @return mixed
     */
    public function getMetadata($key = null, $default = null)
    {
        if (null === $key) {
            return $this->metadata;
        }

        if (!is_scalar($key)) {
            throw new Exception\InvalidArgumentException('Non-scalar argument provided for key');
        }

        if (array_key_exists($key, $this->metadata)) {
            return $this->metadata[$key];
        }

        return $default;
    }

    /**
     * Set message content
     *
     * @param  mixed $value
     * @return Message
     */
    public function setContent($value)
    {
        $this->content = $value;
        return $this;
    }

    /**
     * Get message content
     *
     * @return mixed
     */
    public function getContent()
    {
        return $this->content;
    }

    /**
     * @return string
     */
    public function toString()
    {
        $request = '';
        foreach ($this->getMetadata() as $key => $value) {
            $request .= sprintf(
                "%s: %s\r\n",
                (string) $key,
                (string) $value
            );
        }
        $request .= "\r\n" . $this->getContent();
        return $request;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\StringWrapper;

use Zend\Stdlib\Exception;

class Iconv extends AbstractStringWrapper
{
    /**
     * List of supported character sets (upper case)
     *
     * @var string[]
     * @link http://www.gnu.org/software/libiconv/
     */
    protected static $encodings = array(
        // European languages
        'ASCII',
        'ISO-8859-1',
        'ISO-8859-2',
        'ISO-8859-3',
        'ISO-8859-4',
        'ISO-8859-5',
        'ISO-8859-7',
        'ISO-8859-9',
        'ISO-8859-10',
        'ISO-8859-13',
        'ISO-8859-14',
        'ISO-8859-15',
        'ISO-8859-16',
        'KOI8-R',
        'KOI8-U',
        'KOI8-RU',
        'CP1250',
        'CP1251',
        'CP1252',
        'CP1253',
        'CP1254',
        'CP1257',
        'CP850',
        'CP866',
        'CP1131',
        'MACROMAN',
        'MACCENTRALEUROPE',
        'MACICELAND',
        'MACCROATIAN',
        'MACROMANIA',
        'MACCYRILLIC',
        'MACUKRAINE',
        'MACGREEK',
        'MACTURKISH',
        'MACINTOSH',

        // Semitic languages
        'ISO-8859-6',
        'ISO-8859-8',
        'CP1255',
        'CP1256',
        'CP862',
        'MACHEBREW',
        'MACARABIC',

        // Japanese
        'EUC-JP',
        'SHIFT_JIS',
        'CP932',
        'ISO-2022-JP',
        'ISO-2022-JP-2',
        'ISO-2022-JP-1',

        // Chinese
        'EUC-CN',
        'HZ',
        'GBK',
        'CP936',
        'GB18030',
        'EUC-TW',
        'BIG5',
        'CP950',
        'BIG5-HKSCS',
        'BIG5-HKSCS:2004',
        'BIG5-HKSCS:2001',
        'BIG5-HKSCS:1999',
        'ISO-2022-CN',
        'ISO-2022-CN-EXT',

        // Korean
        'EUC-KR',
        'CP949',
        'ISO-2022-KR',
        'JOHAB',

        // Armenian
        'ARMSCII-8',

        // Georgian
        'GEORGIAN-ACADEMY',
        'GEORGIAN-PS',

        // Tajik
        'KOI8-T',

        // Kazakh
        'PT154',
        'RK1048',

        // Thai
        'ISO-8859-11',
        'TIS-620',
        'CP874',
        'MACTHAI',

        // Laotian
        'MULELAO-1',
        'CP1133',

        // Vietnamese
        'VISCII',
        'TCVN',
        'CP1258',

        // Platform specifics
        'HP-ROMAN8',
        'NEXTSTEP',

        // Full Unicode
        'UTF-8',
        'UCS-2',
        'UCS-2BE',
        'UCS-2LE',
        'UCS-4',
        'UCS-4BE',
        'UCS-4LE',
        'UTF-16',
        'UTF-16BE',
        'UTF-16LE',
        'UTF-32',
        'UTF-32BE',
        'UTF-32LE',
        'UTF-7',
        'C99',
        'JAVA',

        /* Commented out because that's internal encodings not existing in real world
        // Full Unicode, in terms of uint16_t or uint32_t (with machine dependent endianness and alignment)
        'UCS-2-INTERNAL',
        'UCS-4-INTERNAL',

        // Locale dependent, in terms of `char' or `wchar_t' (with machine dependent endianness and alignment,
        // and with OS and locale dependent semantics)
        'char',
        'wchar_t',
        '', // The empty encoding name is equivalent to "char": it denotes the locale dependent character encoding.
        */

        // When configured with the option --enable-extra-encodings,
        // it also provides support for a few extra encodings:

        // European languages
        'CP437',
        'CP737',
        'CP775',
        'CP852',
        'CP853',
        'CP855',
        'CP857',
        'CP858',
        'CP860',
        'CP861',
        'CP863',
        'CP865',
        'CP869',
        'CP1125',

        // Semitic languages
        'CP864',

        // Japanese
        'EUC-JISX0213',
        'Shift_JISX0213',
        'ISO-2022-JP-3',

        // Chinese
        'BIG5-2003', // (experimental)

        // Turkmen
        'TDS565',

        // Platform specifics
        'ATARIST',
        'RISCOS-LATIN1',
    );

    /**
     * Get a list of supported character encodings
     *
     * @return string[]
     */
    public static function getSupportedEncodings()
    {
        return static::$encodings;
    }

    /**
     * Constructor
     *
     * @throws Exception\ExtensionNotLoadedException
     */
    public function __construct()
    {
        if (!extension_loaded('iconv')) {
            throw new Exception\ExtensionNotLoadedException(
                'PHP extension "iconv" is required for this wrapper'
            );
        }
    }

    /**
     * Returns the length of the given string
     *
     * @param string $str
     * @return int|false
     */
    public function strlen($str)
    {
        return iconv_strlen($str, $this->getEncoding());
    }

    /**
     * Returns the portion of string specified by the start and length parameters
     *
     * @param string   $str
     * @param int      $offset
     * @param int|null $length
     * @return string|false
     */
    public function substr($str, $offset = 0, $length = null)
    {
        return iconv_substr($str, $offset, $length, $this->getEncoding());
    }

    /**
     * Find the position of the first occurrence of a substring in a string
     *
     * @param string $haystack
     * @param string $needle
     * @param int    $offset
     * @return int|false
     */
    public function strpos($haystack, $needle, $offset = 0)
    {
        return iconv_strpos($haystack, $needle, $offset, $this->getEncoding());
    }

    /**
     * Convert a string from defined encoding to the defined convert encoding
     *
     * @param string  $str
     * @param bool $reverse
     * @return string|false
     */
    public function convert($str, $reverse = false)
    {
        $encoding        = $this->getEncoding();
        $convertEncoding = $this->getConvertEncoding();
        if ($convertEncoding === null) {
            throw new Exception\LogicException(
                'No convert encoding defined'
            );
        }

        if ($encoding === $convertEncoding) {
            return $str;
        }

        $fromEncoding = $reverse ? $convertEncoding : $encoding;
        $toEncoding   = $reverse ? $encoding : $convertEncoding;

        // automatically add "//IGNORE" to not stop converting on invalid characters
        // invalid characters triggers a notice anyway
        return iconv($fromEncoding, $toEncoding . '//IGNORE', $str);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\StringWrapper;

use Zend\Stdlib\Exception;
use Zend\Stdlib\StringUtils;

abstract class AbstractStringWrapper implements StringWrapperInterface
{
    /**
     * The character encoding working on
     * @var string|null
     */
    protected $encoding = 'UTF-8';

    /**
     * An optionally character encoding to convert to
     * @var string|null
     */
    protected $convertEncoding;

    /**
     * Check if the given character encoding is supported by this wrapper
     * and the character encoding to convert to is also supported.
     *
     * @param  string      $encoding
     * @param  string|null $convertEncoding
     * @return bool
     */
    public static function isSupported($encoding, $convertEncoding = null)
    {
        $supportedEncodings = static::getSupportedEncodings();

        if (!in_array(strtoupper($encoding), $supportedEncodings)) {
            return false;
        }

        if ($convertEncoding !== null && !in_array(strtoupper($convertEncoding), $supportedEncodings)) {
            return false;
        }

        return true;
    }

    /**
     * Set character encoding working with and convert to
     *
     * @param string      $encoding         The character encoding to work with
     * @param string|null $convertEncoding  The character encoding to convert to
     * @return StringWrapperInterface
     */
    public function setEncoding($encoding, $convertEncoding = null)
    {
        $supportedEncodings = static::getSupportedEncodings();

        $encodingUpper = strtoupper($encoding);
        if (!in_array($encodingUpper, $supportedEncodings)) {
            throw new Exception\InvalidArgumentException(
                'Wrapper doesn\'t support character encoding "' . $encoding . '"'
            );
        }


        if ($convertEncoding !== null) {
            $convertEncodingUpper = strtoupper($convertEncoding);
            if (!in_array($convertEncodingUpper, $supportedEncodings)) {
                throw new Exception\InvalidArgumentException(
                    'Wrapper doesn\'t support character encoding "' . $convertEncoding . '"'
                );
            }

            $this->convertEncoding = $convertEncodingUpper;
        } else {
            $this->convertEncoding = null;
        }
        $this->encoding = $encodingUpper;

        return $this;
    }

    /**
     * Get the defined character encoding to work with
     *
     * @return string
     * @throws Exception\LogicException If no encoding was defined
     */
    public function getEncoding()
    {
        return $this->encoding;
    }

    /**
     * Get the defined character encoding to convert to
     *
     * @return string|null
    */
    public function getConvertEncoding()
    {
        return $this->convertEncoding;
    }

    /**
     * Convert a string from defined character encoding to the defined convert encoding
     *
     * @param string  $str
     * @param bool $reverse
     * @return string|false
     */
    public function convert($str, $reverse = false)
    {
        $encoding        = $this->getEncoding();
        $convertEncoding = $this->getConvertEncoding();
        if ($convertEncoding === null) {
            throw new Exception\LogicException(
                'No convert encoding defined'
            );
        }

        if ($encoding === $convertEncoding) {
            return $str;
        }

        $from = $reverse ? $convertEncoding : $encoding;
        $to   = $reverse ? $encoding : $convertEncoding;
        throw new Exception\RuntimeException(sprintf(
            'Converting from "%s" to "%s" isn\'t supported by this string wrapper',
            $from,
            $to
        ));
    }

    /**
     * Wraps a string to a given number of characters
     *
     * @param  string  $string
     * @param  int $width
     * @param  string  $break
     * @param  bool $cut
     * @return string|false
     */
    public function wordWrap($string, $width = 75, $break = "\n", $cut = false)
    {
        $string = (string) $string;
        if ($string === '') {
            return '';
        }

        $break = (string) $break;
        if ($break === '') {
            throw new Exception\InvalidArgumentException('Break string cannot be empty');
        }

        $width = (int) $width;
        if ($width === 0 && $cut) {
            throw new Exception\InvalidArgumentException('Cannot force cut when width is zero');
        }

        if (StringUtils::isSingleByteEncoding($this->getEncoding())) {
            return wordwrap($string, $width, $break, $cut);
        }

        $stringWidth = $this->strlen($string);
        $breakWidth  = $this->strlen($break);

        $result    = '';
        $lastStart = $lastSpace = 0;

        for ($current = 0; $current < $stringWidth; $current++) {
            $char = $this->substr($string, $current, 1);

            $possibleBreak = $char;
            if ($breakWidth !== 1) {
                $possibleBreak = $this->substr($string, $current, $breakWidth);
            }

            if ($possibleBreak === $break) {
                $result    .= $this->substr($string, $lastStart, $current - $lastStart + $breakWidth);
                $current   += $breakWidth - 1;
                $lastStart  = $lastSpace = $current + 1;
                continue;
            }

            if ($char === ' ') {
                if ($current - $lastStart >= $width) {
                    $result    .= $this->substr($string, $lastStart, $current - $lastStart) . $break;
                    $lastStart  = $current + 1;
                }

                $lastSpace = $current;
                continue;
            }

            if ($current - $lastStart >= $width && $cut && $lastStart >= $lastSpace) {
                $result    .= $this->substr($string, $lastStart, $current - $lastStart) . $break;
                $lastStart  = $lastSpace = $current;
                continue;
            }

            if ($current - $lastStart >= $width && $lastStart < $lastSpace) {
                $result    .= $this->substr($string, $lastStart, $lastSpace - $lastStart) . $break;
                $lastStart  = $lastSpace = $lastSpace + 1;
                continue;
            }
        }

        if ($lastStart !== $current) {
            $result .= $this->substr($string, $lastStart, $current - $lastStart);
        }

        return $result;
    }

    /**
     * Pad a string to a certain length with another string
     *
     * @param  string  $input
     * @param  int $padLength
     * @param  string  $padString
     * @param  int $padType
     * @return string
     */
    public function strPad($input, $padLength, $padString = ' ', $padType = STR_PAD_RIGHT)
    {
        if (StringUtils::isSingleByteEncoding($this->getEncoding())) {
            return str_pad($input, $padLength, $padString, $padType);
        }

        $lengthOfPadding = $padLength - $this->strlen($input);
        if ($lengthOfPadding <= 0) {
            return $input;
        }

        $padStringLength = $this->strlen($padString);
        if ($padStringLength === 0) {
            return $input;
        }

        $repeatCount = floor($lengthOfPadding / $padStringLength);

        if ($padType === STR_PAD_BOTH) {
            $lastStringLeft  = '';
            $lastStringRight = '';
            $repeatCountLeft = $repeatCountRight = ($repeatCount - $repeatCount % 2) / 2;

            $lastStringLength       = $lengthOfPadding - 2 * $repeatCountLeft * $padStringLength;
            $lastStringLeftLength   = $lastStringRightLength = floor($lastStringLength / 2);
            $lastStringRightLength += $lastStringLength % 2;

            $lastStringLeft  = $this->substr($padString, 0, $lastStringLeftLength);
            $lastStringRight = $this->substr($padString, 0, $lastStringRightLength);

            return str_repeat($padString, $repeatCountLeft) . $lastStringLeft
                . $input
                . str_repeat($padString, $repeatCountRight) . $lastStringRight;
        }

        $lastString = $this->substr($padString, 0, $lengthOfPadding % $padStringLength);

        if ($padType === STR_PAD_LEFT) {
            return str_repeat($padString, $repeatCount) . $lastString . $input;
        }

        return $input . str_repeat($padString, $repeatCount) . $lastString;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\StringWrapper;

interface StringWrapperInterface
{
    /**
     * Check if the given character encoding is supported by this wrapper
     * and the character encoding to convert to is also supported.
     *
     * @param string      $encoding
     * @param string|null $convertEncoding
     */
    public static function isSupported($encoding, $convertEncoding = null);

    /**
     * Get a list of supported character encodings
     *
     * @return string[]
     */
    public static function getSupportedEncodings();

    /**
     * Set character encoding working with and convert to
     *
     * @param string      $encoding         The character encoding to work with
     * @param string|null $convertEncoding  The character encoding to convert to
     * @return StringWrapperInterface
     */
    public function setEncoding($encoding, $convertEncoding = null);

    /**
     * Get the defined character encoding to work with (upper case)
     *
     * @return string
     */
    public function getEncoding();

    /**
     * Get the defined character encoding to convert to (upper case)
     *
     * @return string|null
     */
    public function getConvertEncoding();

    /**
     * Returns the length of the given string
     *
     * @param string $str
     * @return int|false
     */
    public function strlen($str);

    /**
     * Returns the portion of string specified by the start and length parameters
     *
     * @param string   $str
     * @param int      $offset
     * @param int|null $length
     * @return string|false
     */
    public function substr($str, $offset = 0, $length = null);

    /**
     * Find the position of the first occurrence of a substring in a string
     *
     * @param string $haystack
     * @param string $needle
     * @param int    $offset
     * @return int|false
     */
    public function strpos($haystack, $needle, $offset = 0);

    /**
     * Convert a string from defined encoding to the defined convert encoding
     *
     * @param string  $str
     * @param bool $reverse
     * @return string|false
     */
    public function convert($str, $reverse = false);

    /**
     * Wraps a string to a given number of characters
     *
     * @param  string  $str
     * @param  int $width
     * @param  string  $break
     * @param  bool $cut
     * @return string
     */
    public function wordWrap($str, $width = 75, $break = "\n", $cut = false);

    /**
     * Pad a string to a certain length with another string
     *
     * @param  string  $input
     * @param  int $padLength
     * @param  string  $padString
     * @param  int $padType
     * @return string
     */
    public function strPad($input, $padLength, $padString = ' ', $padType = STR_PAD_RIGHT);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\StringWrapper;

use Zend\Stdlib\Exception;

class Intl extends AbstractStringWrapper
{
    /**
     * List of supported character sets (upper case)
     *
     * @var string[]
     */
    protected static $encodings = array('UTF-8');

    /**
     * Get a list of supported character encodings
     *
     * @return string[]
     */
    public static function getSupportedEncodings()
    {
        return static::$encodings;
    }

    /**
     * Constructor
     *
     * @throws Exception\ExtensionNotLoadedException
     */
    public function __construct()
    {
        if (!extension_loaded('intl')) {
            throw new Exception\ExtensionNotLoadedException(
                'PHP extension "intl" is required for this wrapper'
            );
        }
    }

    /**
     * Returns the length of the given string
     *
     * @param string $str
     * @return int|false
     */
    public function strlen($str)
    {
        return grapheme_strlen($str);
    }

    /**
     * Returns the portion of string specified by the start and length parameters
     *
     * @param string   $str
     * @param int      $offset
     * @param int|null $length
     * @return string|false
     */
    public function substr($str, $offset = 0, $length = null)
    {
        return grapheme_substr($str, $offset, $length);
    }

    /**
     * Find the position of the first occurrence of a substring in a string
     *
     * @param string $haystack
     * @param string $needle
     * @param int    $offset
     * @return int|false
     */
    public function strpos($haystack, $needle, $offset = 0)
    {
        return grapheme_strpos($haystack, $needle, $offset);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\StringWrapper;

use Zend\Stdlib\Exception;
use Zend\Stdlib\StringUtils;

class Native extends AbstractStringWrapper
{
    /**
     * The character encoding working on
     * (overwritten to change defaut encoding)
     *
     * @var string
     */
    protected $encoding = 'ASCII';

    /**
     * Check if the given character encoding is supported by this wrapper
     * and the character encoding to convert to is also supported.
     *
     * @param  string      $encoding
     * @param  string|null $convertEncoding
     * @return bool
     */
    public static function isSupported($encoding, $convertEncoding = null)
    {
        $encodingUpper      = strtoupper($encoding);
        $supportedEncodings = static::getSupportedEncodings();

        if (!in_array($encodingUpper, $supportedEncodings)) {
            return false;
        }

        // This adapter doesn't support to convert between encodings
        if ($convertEncoding !== null && $encodingUpper !== strtoupper($convertEncoding)) {
            return false;
        }

        return true;
    }

    /**
     * Get a list of supported character encodings
     *
     * @return string[]
     */
    public static function getSupportedEncodings()
    {
        return StringUtils::getSingleByteEncodings();
    }

    /**
     * Set character encoding working with and convert to
     *
     * @param string      $encoding         The character encoding to work with
     * @param string|null $convertEncoding  The character encoding to convert to
     * @return StringWrapperInterface
     */
    public function setEncoding($encoding, $convertEncoding = null)
    {
        $supportedEncodings = static::getSupportedEncodings();

        $encodingUpper = strtoupper($encoding);
        if (!in_array($encodingUpper, $supportedEncodings)) {
            throw new Exception\InvalidArgumentException(
                'Wrapper doesn\'t support character encoding "' . $encoding . '"'
            );
        }

        if ($encodingUpper !== strtoupper($convertEncoding)) {
            $this->convertEncoding = $encodingUpper;
        }

        if ($convertEncoding !== null) {
            if ($encodingUpper !== strtoupper($convertEncoding)) {
                throw new Exception\InvalidArgumentException(
                    'Wrapper doesn\'t support to convert between character encodings'
                );
            }

            $this->convertEncoding = $encodingUpper;
        } else {
            $this->convertEncoding = null;
        }
        $this->encoding = $encodingUpper;

        return $this;
    }

    /**
     * Returns the length of the given string
     *
     * @param string $str
     * @return int|false
     */
    public function strlen($str)
    {
        return strlen($str);
    }

    /**
     * Returns the portion of string specified by the start and length parameters
     *
     * @param string   $str
     * @param int      $offset
     * @param int|null $length
     * @return string|false
     */
    public function substr($str, $offset = 0, $length = null)
    {
        return substr($str, $offset, $length);
    }

    /**
     * Find the position of the first occurrence of a substring in a string
     *
     * @param string $haystack
     * @param string $needle
     * @param int    $offset
     * @return int|false
     */
    public function strpos($haystack, $needle, $offset = 0)
    {
        return strpos($haystack, $needle, $offset);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\StringWrapper;

use Zend\Stdlib\Exception;

class MbString extends AbstractStringWrapper
{
    /**
     * List of supported character sets (upper case)
     *
     * @var null|string[]
     * @link http://php.net/manual/mbstring.supported-encodings.php
     */
    protected static $encodings = null;

    /**
     * Get a list of supported character encodings
     *
     * @return string[]
     */
    public static function getSupportedEncodings()
    {
        if (static::$encodings === null) {
            static::$encodings = array_map('strtoupper', mb_list_encodings());

            // FIXME: Converting € (UTF-8) to ISO-8859-16 gives a wrong result
            $indexIso885916 = array_search('ISO-8859-16', static::$encodings, true);
            if ($indexIso885916 !== false) {
                unset(static::$encodings[$indexIso885916]);
            }
        }

        return static::$encodings;
    }

    /**
     * Constructor
     *
     * @throws Exception\ExtensionNotLoadedException
     */
    public function __construct()
    {
        if (!extension_loaded('mbstring')) {
            throw new Exception\ExtensionNotLoadedException(
                'PHP extension "mbstring" is required for this wrapper'
            );
        }
    }

    /**
     * Returns the length of the given string
     *
     * @param string $str
     * @return int|false
     */
    public function strlen($str)
    {
        return mb_strlen($str, $this->getEncoding());
    }

    /**
     * Returns the portion of string specified by the start and length parameters
     *
     * @param string   $str
     * @param int      $offset
     * @param int|null $length
     * @return string|false
     */
    public function substr($str, $offset = 0, $length = null)
    {
        return mb_substr($str, $offset, $length, $this->getEncoding());
    }

    /**
     * Find the position of the first occurrence of a substring in a string
     *
     * @param string $haystack
     * @param string $needle
     * @param int    $offset
     * @return int|false
     */
    public function strpos($haystack, $needle, $offset = 0)
    {
        return mb_strpos($haystack, $needle, $offset, $this->getEncoding());
    }

    /**
     * Convert a string from defined encoding to the defined convert encoding
     *
     * @param string  $str
     * @param bool $reverse
     * @return string|false
     */
    public function convert($str, $reverse = false)
    {
        $encoding        = $this->getEncoding();
        $convertEncoding = $this->getConvertEncoding();

        if ($convertEncoding === null) {
            throw new Exception\LogicException(
                'No convert encoding defined'
            );
        }

        if ($encoding === $convertEncoding) {
            return $str;
        }

        $fromEncoding = $reverse ? $convertEncoding : $encoding;
        $toEncoding   = $reverse ? $encoding : $convertEncoding;
        return mb_convert_encoding($str, $toEncoding, $fromEncoding);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib;

interface ResponseInterface extends MessageInterface
{

}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib;

use Serializable;

/**
 * Serializable version of SplPriorityQueue
 *
 * Also, provides predictable heap order for datums added with the same priority
 * (i.e., they will be emitted in the same order they are enqueued).
 */
class SplPriorityQueue extends \SplPriorityQueue implements Serializable
{
    /**
     * @var int Seed used to ensure queue order for items of the same priority
     */
    protected $serial = PHP_INT_MAX;

    /**
     * Insert a value with a given priority
     *
     * Utilizes {@var $serial} to ensure that values of equal priority are
     * emitted in the same order in which they are inserted.
     *
     * @param  mixed $datum
     * @param  mixed $priority
     * @return void
     */
    public function insert($datum, $priority)
    {
        if (!is_array($priority)) {
            $priority = array($priority, $this->serial--);
        }
        parent::insert($datum, $priority);
    }


    /**
     * Serialize to an array
     *
     * Array will be priority => data pairs
     *
     * @return array
     */
    public function toArray()
    {
        $array = array();
        foreach (clone $this as $item) {
            $array[] = $item;
        }
        return $array;
    }


    /**
     * Serialize
     *
     * @return string
     */
    public function serialize()
    {
        $clone = clone $this;
        $clone->setExtractFlags(self::EXTR_BOTH);

        $data = array();
        foreach ($clone as $item) {
            $data[] = $item;
        }

        return serialize($data);
    }

    /**
     * Deserialize
     *
     * @param  string $data
     * @return void
     */
    public function unserialize($data)
    {
        foreach (unserialize($data) as $item) {
            $this->insert($item['data'], $item['priority']);
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib;

use ArrayObject as PhpArrayObject;

class Parameters extends PhpArrayObject implements ParametersInterface
{
    /**
     * Constructor
     *
     * Enforces that we have an array, and enforces parameter access to array
     * elements.
     *
     * @param  array $values
     */
    public function __construct(array $values = null)
    {
        if (null === $values) {
            $values = array();
        }
        parent::__construct($values, ArrayObject::ARRAY_AS_PROPS);
    }

    /**
     * Populate from native PHP array
     *
     * @param  array $values
     * @return void
     */
    public function fromArray(array $values)
    {
        $this->exchangeArray($values);
    }

    /**
     * Populate from query string
     *
     * @param  string $string
     * @return void
     */
    public function fromString($string)
    {
        $array = array();
        parse_str($string, $array);
        $this->fromArray($array);
    }

    /**
     * Serialize to native PHP array
     *
     * @return array
     */
    public function toArray()
    {
        return $this->getArrayCopy();
    }

    /**
     * Serialize to query string
     *
     * @return string
     */
    public function toString()
    {
        return http_build_query($this);
    }

    /**
     * Retrieve by key
     *
     * Returns null if the key does not exist.
     *
     * @param  string $name
     * @return mixed
     */
    public function offsetGet($name)
    {
        if (isset($this[$name])) {
            return parent::offsetGet($name);
        }
        return null;
    }

    /**
     * @param string $name
     * @param mixed $default optional default value
     * @return mixed
     */
    public function get($name, $default = null)
    {
        if (isset($this[$name])) {
            return parent::offsetGet($name);
        }
        return $default;
    }

    /**
     * @param string $name
     * @param mixed $value
     * @return Parameters
     */
    public function set($name, $value)
    {
        $this[$name] = $value;
        return $this;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib;

interface ParameterObjectInterface
{
    /**
     * @param string $key
     * @param mixed $value
     * @return void
     */
    public function __set($key, $value);

    /**
     * @param string $key
     * @return mixed
     */
    public function __get($key);

    /**
     * @param string $key
     * @return bool
     */
    public function __isset($key);

    /**
     * @param string $key
     * @return void
     */
    public function __unset($key);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib;

use Serializable;

/**
 * Serializable version of SplQueue
 */
class SplQueue extends \SplQueue implements Serializable
{
    /**
     * Return an array representing the queue
     *
     * @return array
     */
    public function toArray()
    {
        $array = array();
        foreach ($this as $item) {
            $array[] = $item;
        }
        return $array;
    }

    /**
     * Serialize
     *
     * @return string
     */
    public function serialize()
    {
        return serialize($this->toArray());
    }

    /**
     * Unserialize
     *
     * @param  string $data
     * @return void
     */
    public function unserialize($data)
    {
        foreach (unserialize($data) as $item) {
            $this->push($item);
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib;

interface RequestInterface extends MessageInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 * @deprecated
 */

/**
 * Legacy purposes only, to prevent code that references it from breaking.
 */
trigger_error('Polyfill autoload support (file library/Zend/Stdlib/compatibility/autoload.php) is no longer necessary; please remove your require statement referencing this file', E_USER_DEPRECATED);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib;

use Traversable;

abstract class AbstractOptions implements ParameterObjectInterface
{
    /**
     * We use the __ prefix to avoid collisions with properties in
     * user-implementations.
     *
     * @var bool
     */
    protected $__strictMode__ = true;

    /**
     * Constructor
     *
     * @param  array|Traversable|null $options
     */
    public function __construct($options = null)
    {
        if (null !== $options) {
            $this->setFromArray($options);
        }
    }

    /**
     * Set one or more configuration properties
     *
     * @param  array|Traversable|AbstractOptions $options
     * @throws Exception\InvalidArgumentException
     * @return AbstractOptions Provides fluent interface
     */
    public function setFromArray($options)
    {
        if ($options instanceof self) {
            $options = $options->toArray();
        }

        if (!is_array($options) && !$options instanceof Traversable) {
            throw new Exception\InvalidArgumentException(sprintf(
                'Parameter provided to %s must be an %s, %s or %s',
                __METHOD__, 'array', 'Traversable', 'Zend\Stdlib\AbstractOptions'
            ));
        }

        foreach ($options as $key => $value) {
            $this->__set($key, $value);
        }

        return $this;
    }

    /**
     * Cast to array
     *
     * @return array
     */
    public function toArray()
    {
        $array = array();
        $transform = function ($letters) {
            $letter = array_shift($letters);
            return '_' . strtolower($letter);
        };
        foreach ($this as $key => $value) {
            if ($key === '__strictMode__') continue;
            $normalizedKey = preg_replace_callback('/([A-Z])/', $transform, $key);
            $array[$normalizedKey] = $value;
        }
        return $array;
    }

    /**
     * Set a configuration property
     *
     * @see ParameterObject::__set()
     * @param string $key
     * @param mixed $value
     * @throws Exception\BadMethodCallException
     * @return void
     */
    public function __set($key, $value)
    {
        $setter = 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key)));
        if ($this->__strictMode__ && !method_exists($this, $setter)) {
            throw new Exception\BadMethodCallException(
                'The option "' . $key . '" does not '
                . 'have a matching ' . $setter . ' setter method '
                . 'which must be defined'
            );
        } elseif (!$this->__strictMode__ && !method_exists($this, $setter)) {
            return;
        }
        $this->{$setter}($value);
    }

    /**
     * Get a configuration property
     *
     * @see ParameterObject::__get()
     * @param string $key
     * @throws Exception\BadMethodCallException
     * @return mixed
     */
    public function __get($key)
    {
        $getter = 'get' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key)));
        if (!method_exists($this, $getter)) {
            throw new Exception\BadMethodCallException(
                'The option "' . $key . '" does not '
                . 'have a matching ' . $getter . ' getter method '
                . 'which must be defined'
            );
        }

        return $this->{$getter}();
    }

    /**
     * Test if a configuration property is null
     * @see ParameterObject::__isset()
     * @param string $key
     * @return bool
     */
    public function __isset($key)
    {
        return null !== $this->__get($key);
    }

    /**
     * Set a configuration property to NULL
     *
     * @see ParameterObject::__unset()
     * @param string $key
     * @throws Exception\InvalidArgumentException
     * @return void
     */
    public function __unset($key)
    {
        try {
            $this->__set($key, null);
        } catch (Exception\BadMethodCallException $e) {
            throw new Exception\InvalidArgumentException(
                'The class property $' . $key . ' cannot be unset as'
                    . ' NULL is an invalid value for it',
                0,
                $e
            );
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib;

use Zend\Stdlib\ErrorHandler;
use Zend\Stdlib\StringWrapper\StringWrapperInterface;

/**
 * Utility class for handling strings of different character encodings
 * using available PHP extensions.
 *
 * Declared abstract, as we have no need for instantiation.
 */
abstract class StringUtils
{

    /**
     * Ordered list of registered string wrapper instances
     *
     * @var StringWrapperInterface[]
     */
    protected static $wrapperRegistry = null;

    /**
     * A list of known single-byte character encodings (upper-case)
     *
     * @var string[]
     */
    protected static $singleByteEncodings = array(
        'ASCII', '7BIT', '8BIT',
        'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3', 'ISO-8859-4', 'ISO-8859-5',
        'ISO-8859-6', 'ISO-8859-7', 'ISO-8859-8', 'ISO-8859-9', 'ISO-8859-10',
        'ISO-8859-11', 'ISO-8859-13', 'ISO-8859-14', 'ISO-8859-15', 'ISO-8859-16',
        'CP-1251', 'CP-1252',
        // TODO
    );

    /**
     * Is PCRE compiled with Unicode support?
     *
     * @var bool
     **/
    protected static $hasPcreUnicodeSupport = null;

    /**
     * Get registered wrapper classes
     *
     * @return string[]
     */
    public static function getRegisteredWrappers()
    {
        if (static::$wrapperRegistry === null) {
            static::$wrapperRegistry = array();

            if (extension_loaded('intl')) {
                static::$wrapperRegistry[] = 'Zend\Stdlib\StringWrapper\Intl';
            }

            if (extension_loaded('mbstring')) {
                static::$wrapperRegistry[] = 'Zend\Stdlib\StringWrapper\MbString';
            }

            if (extension_loaded('iconv')) {
                static::$wrapperRegistry[] = 'Zend\Stdlib\StringWrapper\Iconv';
            }

            static::$wrapperRegistry[] = 'Zend\Stdlib\StringWrapper\Native';
        }

        return static::$wrapperRegistry;
    }

    /**
     * Register a string wrapper class
     *
     * @param string $wrapper
     * @return void
     */
    public static function registerWrapper($wrapper)
    {
        $wrapper = (string) $wrapper;
        if (!in_array($wrapper, static::$wrapperRegistry, true)) {
            static::$wrapperRegistry[] = $wrapper;
        }
    }

    /**
     * Unregister a string wrapper class
     *
     * @param string $wrapper
     * @return void
     */
    public static function unregisterWrapper($wrapper)
    {
        $index = array_search((string) $wrapper, static::$wrapperRegistry, true);
        if ($index !== false) {
            unset(static::$wrapperRegistry[$index]);
        }
    }

    /**
     * Reset all registered wrappers so the default wrappers will be used
     *
     * @return void
     */
    public static function resetRegisteredWrappers()
    {
        static::$wrapperRegistry = null;
    }

    /**
     * Get the first string wrapper supporting the given character encoding
     * and supports to convert into the given convert encoding.
     *
     * @param string      $encoding        Character encoding to support
     * @param string|null $convertEncoding OPTIONAL character encoding to convert in
     * @return StringWrapperInterface
     * @throws Exception\RuntimeException If no wrapper supports given character encodings
     */
    public static function getWrapper($encoding = 'UTF-8', $convertEncoding = null)
    {
        foreach (static::getRegisteredWrappers() as $wrapperClass) {
            if ($wrapperClass::isSupported($encoding, $convertEncoding)) {
                $wrapper = new $wrapperClass($encoding, $convertEncoding);
                $wrapper->setEncoding($encoding, $convertEncoding);
                return $wrapper;
            }
        }

        throw new Exception\RuntimeException(
            'No wrapper found supporting "' . $encoding . '"'
            . (($convertEncoding !== null) ? ' and "' . $convertEncoding . '"' : '')
        );
    }

    /**
     * Get a list of all known single-byte character encodings
     *
     * @return string[]
     */
    public static function getSingleByteEncodings()
    {
        return static::$singleByteEncodings;
    }

    /**
     * Check if a given encoding is a known single-byte character encoding
     *
     * @param string $encoding
     * @return bool
     */
    public static function isSingleByteEncoding($encoding)
    {
        return in_array(strtoupper($encoding), static::$singleByteEncodings);
    }

    /**
     * Check if a given string is valid UTF-8 encoded
     *
     * @param string $str
     * @return bool
     */
    public static function isValidUtf8($str)
    {
        return is_string($str) && ($str === '' || preg_match('/^./su', $str) == 1);
    }

    /**
     * Is PCRE compiled with Unicode support?
     *
     * @return bool
     */
    public static function hasPcreUnicodeSupport()
    {
        if (static::$hasPcreUnicodeSupport === null) {
            ErrorHandler::start();
            static::$hasPcreUnicodeSupport = defined('PREG_BAD_UTF8_OFFSET_ERROR') && preg_match('/\pL/u', 'a') == 1;
            ErrorHandler::stop();
        }
        return static::$hasPcreUnicodeSupport;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib;

use Zend\Stdlib\Exception;
use Zend\Stdlib\ErrorHandler;

/**
 * Wrapper for glob with fallback if GLOB_BRACE is not available.
 */
abstract class Glob
{
    /**#@+
     * Glob constants.
     */
    const GLOB_MARK     = 0x01;
    const GLOB_NOSORT   = 0x02;
    const GLOB_NOCHECK  = 0x04;
    const GLOB_NOESCAPE = 0x08;
    const GLOB_BRACE    = 0x10;
    const GLOB_ONLYDIR  = 0x20;
    const GLOB_ERR      = 0x40;
    /**#@-*/

    /**
     * Find pathnames matching a pattern.
     *
     * @see    http://docs.php.net/glob
     * @param  string  $pattern
     * @param  int $flags
     * @param  bool $forceFallback
     * @return array
     * @throws Exception\RuntimeException
     */
    public static function glob($pattern, $flags = 0, $forceFallback = false)
    {
        if (!defined('GLOB_BRACE') || $forceFallback) {
            return static::fallbackGlob($pattern, $flags);
        }

        return static::systemGlob($pattern, $flags);
    }

    /**
     * Use the glob function provided by the system.
     *
     * @param  string  $pattern
     * @param  int     $flags
     * @return array
     * @throws Exception\RuntimeException
     */
    protected static function systemGlob($pattern, $flags)
    {
        if ($flags) {
            $flagMap = array(
                self::GLOB_MARK     => GLOB_MARK,
                self::GLOB_NOSORT   => GLOB_NOSORT,
                self::GLOB_NOCHECK  => GLOB_NOCHECK,
                self::GLOB_NOESCAPE => GLOB_NOESCAPE,
                self::GLOB_BRACE    => GLOB_BRACE,
                self::GLOB_ONLYDIR  => GLOB_ONLYDIR,
                self::GLOB_ERR      => GLOB_ERR,
            );

            $globFlags = 0;

            foreach ($flagMap as $internalFlag => $globFlag) {
                if ($flags & $internalFlag) {
                    $globFlags |= $globFlag;
                }
            }
        } else {
            $globFlags = 0;
        }

        ErrorHandler::start();
        $res = glob($pattern, $globFlags);
        $err = ErrorHandler::stop();
        if ($res === false) {
            throw new Exception\RuntimeException("glob('{$pattern}', {$globFlags}) failed", 0, $err);
        }
        return $res;
    }

    /**
     * Expand braces manually, then use the system glob.
     *
     * @param  string  $pattern
     * @param  int     $flags
     * @return array
     * @throws Exception\RuntimeException
     */
    protected static function fallbackGlob($pattern, $flags)
    {
        if (!$flags & self::GLOB_BRACE) {
            return static::systemGlob($pattern, $flags);
        }

        $flags &= ~self::GLOB_BRACE;
        $length = strlen($pattern);
        $paths  = array();

        if ($flags & self::GLOB_NOESCAPE) {
            $begin = strpos($pattern, '{');
        } else {
            $begin = 0;

            while (true) {
                if ($begin === $length) {
                    $begin = false;
                    break;
                } elseif ($pattern[$begin] === '\\' && ($begin + 1) < $length) {
                    $begin++;
                } elseif ($pattern[$begin] === '{') {
                    break;
                }

                $begin++;
            }
        }

        if ($begin === false) {
            return static::systemGlob($pattern, $flags);
        }

        $next = static::nextBraceSub($pattern, $begin + 1, $flags);

        if ($next === null) {
            return static::systemGlob($pattern, $flags);
        }

        $rest = $next;

        while ($pattern[$rest] !== '}') {
            $rest = static::nextBraceSub($pattern, $rest + 1, $flags);

            if ($rest === null) {
                return static::systemGlob($pattern, $flags);
            }
        }

        $p = $begin + 1;

        while (true) {
            $subPattern = substr($pattern, 0, $begin)
                        . substr($pattern, $p, $next - $p)
                        . substr($pattern, $rest + 1);

            $result = static::fallbackGlob($subPattern, $flags | self::GLOB_BRACE);

            if ($result) {
                $paths = array_merge($paths, $result);
            }

            if ($pattern[$next] === '}') {
                break;
            }

            $p    = $next + 1;
            $next = static::nextBraceSub($pattern, $p, $flags);
        }

        return array_unique($paths);
    }

    /**
     * Find the end of the sub-pattern in a brace expression.
     *
     * @param  string  $pattern
     * @param  int $begin
     * @param  int $flags
     * @return int|null
     */
    protected static function nextBraceSub($pattern, $begin, $flags)
    {
        $length  = strlen($pattern);
        $depth   = 0;
        $current = $begin;

        while ($current < $length) {
            if (!$flags & self::GLOB_NOESCAPE && $pattern[$current] === '\\') {
                if (++$current === $length) {
                    break;
                }

                $current++;
            } else {
                if (($pattern[$current] === '}' && $depth-- === 0) || ($pattern[$current] === ',' && $depth === 0)) {
                    break;
                } elseif ($pattern[$current++] === '{') {
                    $depth++;
                }
            }
        }

        return ($current < $length ? $current : null);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib;

interface MessageInterface
{
    /**
     * Set metadata
     *
     * @param  string|int|array|\Traversable $spec
     * @param  mixed $value
     */
    public function setMetadata($spec, $value = null);

    /**
     * Get metadata
     *
     * @param  null|string|int $key
     * @return mixed
     */
    public function getMetadata($key = null);

    /**
     * Set content
     *
     * @param  mixed $content
     * @return mixed
     */
    public function setContent($content);

    /**
     * Get content
     *
     * @return mixed
     */
    public function getContent();

}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib;

use Serializable;

/**
 * Serializable version of SplStack
 */
class SplStack extends \SplStack implements Serializable
{
    /**
     * Serialize to an array representing the stack
     *
     * @return array
     */
    public function toArray()
    {
        $array = array();
        foreach ($this as $item) {
            $array[] = $item;
        }
        return $array;
    }

    /**
     * Serialize
     *
     * @return string
     */
    public function serialize()
    {
        return serialize($this->toArray());
    }

    /**
     * Unserialize
     *
     * @param  string $data
     * @return void
     */
    public function unserialize($data)
    {
        foreach (unserialize($data) as $item) {
            $this->unshift($item);
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib;

use Countable;
use IteratorAggregate;
use Serializable;

/**
 * Re-usable, serializable priority queue implementation
 *
 * SplPriorityQueue acts as a heap; on iteration, each item is removed from the
 * queue. If you wish to re-use such a queue, you need to clone it first. This
 * makes for some interesting issues if you wish to delete items from the queue,
 * or, as already stated, iterate over it multiple times.
 *
 * This class aggregates items for the queue itself, but also composes an
 * "inner" iterator in the form of an SplPriorityQueue object for performing
 * the actual iteration.
 */
class PriorityQueue implements Countable, IteratorAggregate, Serializable
{
    const EXTR_DATA     = 0x00000001;
    const EXTR_PRIORITY = 0x00000002;
    const EXTR_BOTH     = 0x00000003;

    /**
     * Inner queue class to use for iteration
     * @var string
     */
    protected $queueClass = 'Zend\Stdlib\SplPriorityQueue';

    /**
     * Actual items aggregated in the priority queue. Each item is an array
     * with keys "data" and "priority".
     * @var array
     */
    protected $items      = array();

    /**
     * Inner queue object
     * @var SplPriorityQueue
     */
    protected $queue;

    /**
     * Insert an item into the queue
     *
     * Priority defaults to 1 (low priority) if none provided.
     *
     * @param  mixed $data
     * @param  int $priority
     * @return PriorityQueue
     */
    public function insert($data, $priority = 1)
    {
        $priority = (int) $priority;
        $this->items[] = array(
            'data'     => $data,
            'priority' => $priority,
        );
        $this->getQueue()->insert($data, $priority);
        return $this;
    }

    /**
     * Remove an item from the queue
     *
     * This is different than {@link extract()}; its purpose is to dequeue an
     * item.
     *
     * This operation is potentially expensive, as it requires
     * re-initialization and re-population of the inner queue.
     *
     * Note: this removes the first item matching the provided item found. If
     * the same item has been added multiple times, it will not remove other
     * instances.
     *
     * @param  mixed $datum
     * @return bool False if the item was not found, true otherwise.
     */
    public function remove($datum)
    {
        $found = false;
        foreach ($this->items as $key => $item) {
            if ($item['data'] === $datum) {
                $found = true;
                break;
            }
        }
        if ($found) {
            unset($this->items[$key]);
            $this->queue = null;

            if (!$this->isEmpty()) {
                $queue = $this->getQueue();
                foreach ($this->items as $item) {
                    $queue->insert($item['data'], $item['priority']);
                }
            }
            return true;
        }
        return false;
    }

    /**
     * Is the queue empty?
     *
     * @return bool
     */
    public function isEmpty()
    {
        return (0 === $this->count());
    }

    /**
     * How many items are in the queue?
     *
     * @return int
     */
    public function count()
    {
        return count($this->items);
    }

    /**
     * Peek at the top node in the queue, based on priority.
     *
     * @return mixed
     */
    public function top()
    {
        return $this->getIterator()->top();
    }

    /**
     * Extract a node from the inner queue and sift up
     *
     * @return mixed
     */
    public function extract()
    {
        return $this->getQueue()->extract();
    }

    /**
     * Retrieve the inner iterator
     *
     * SplPriorityQueue acts as a heap, which typically implies that as items
     * are iterated, they are also removed. This does not work for situations
     * where the queue may be iterated multiple times. As such, this class
     * aggregates the values, and also injects an SplPriorityQueue. This method
     * retrieves the inner queue object, and clones it for purposes of
     * iteration.
     *
     * @return SplPriorityQueue
     */
    public function getIterator()
    {
        $queue = $this->getQueue();
        return clone $queue;
    }

    /**
     * Serialize the data structure
     *
     * @return string
     */
    public function serialize()
    {
        return serialize($this->items);
    }

    /**
     * Unserialize a string into a PriorityQueue object
     *
     * Serialization format is compatible with {@link Zend\Stdlib\SplPriorityQueue}
     *
     * @param  string $data
     * @return void
     */
    public function unserialize($data)
    {
        foreach (unserialize($data) as $item) {
            $this->insert($item['data'], $item['priority']);
        }
    }

    /**
     * Serialize to an array
     *
     * By default, returns only the item data, and in the order registered (not
     * sorted). You may provide one of the EXTR_* flags as an argument, allowing
     * the ability to return priorities or both data and priority.
     *
     * @param  int $flag
     * @return array
     */
    public function toArray($flag = self::EXTR_DATA)
    {
        switch ($flag) {
            case self::EXTR_BOTH:
                return $this->items;
                break;
            case self::EXTR_PRIORITY:
                return array_map(function ($item) {
                    return $item['priority'];
                }, $this->items);
            case self::EXTR_DATA:
            default:
                return array_map(function ($item) {
                    return $item['data'];
                }, $this->items);
        }
    }

    /**
     * Specify the internal queue class
     *
     * Please see {@link getIterator()} for details on the necessity of an
     * internal queue class. The class provided should extend SplPriorityQueue.
     *
     * @param  string $class
     * @return PriorityQueue
     */
    public function setInternalQueueClass($class)
    {
        $this->queueClass = (string) $class;
        return $this;
    }

    /**
     * Does the queue contain the given datum?
     *
     * @param  mixed $datum
     * @return bool
     */
    public function contains($datum)
    {
        foreach ($this->items as $item) {
            if ($item['data'] === $datum) {
                return true;
            }
        }
        return false;
    }

    /**
     * Does the queue have an item with the given priority?
     *
     * @param  int $priority
     * @return bool
     */
    public function hasPriority($priority)
    {
        foreach ($this->items as $item) {
            if ($item['priority'] === $priority) {
                return true;
            }
        }
        return false;
    }

    /**
     * Get the inner priority queue instance
     *
     * @throws Exception\DomainException
     * @return SplPriorityQueue
     */
    protected function getQueue()
    {
        if (null === $this->queue) {
            $this->queue = new $this->queueClass();
            if (!$this->queue instanceof \SplPriorityQueue) {
                throw new Exception\DomainException(sprintf(
                    'PriorityQueue expects an internal queue of type SplPriorityQueue; received "%s"',
                    get_class($this->queue)
                ));
            }
        }
        return $this->queue;
    }

    /**
     * Add support for deep cloning
     *
     * @return void
     */
    public function __clone()
    {
        if (null !== $this->queue) {
            $this->queue = clone $this->queue;
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib;

use ArrayIterator;
use ArrayObject as PhpArrayObject;

/**
 * ArrayObject that acts as a stack with regards to iteration
 */
class ArrayStack extends PhpArrayObject
{
    /**
     * Retrieve iterator
     *
     * Retrieve an array copy of the object, reverse its order, and return an
     * ArrayIterator with that reversed array.
     *
     * @return ArrayIterator
     */
    public function getIterator()
    {
        $array = $this->getArrayCopy();
        return new ArrayIterator(array_reverse($array));
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\ArrayObject;

use ArrayAccess;
use Countable;
use IteratorAggregate;
use Serializable;
use Zend\Stdlib\Exception;

/**
 * ArrayObject
 *
 * This ArrayObject is a rewrite of the implementation to fix
 * issues with php's implementation of ArrayObject where you
 * are unable to unset multi-dimensional arrays because you
 * need to fetch the properties / lists as references.
 */
abstract class PhpReferenceCompatibility implements IteratorAggregate, ArrayAccess, Serializable, Countable
{
    /**
     * Properties of the object have their normal functionality
     * when accessed as list (var_dump, foreach, etc.).
     */
    const STD_PROP_LIST = 1;

    /**
     * Entries can be accessed as properties (read and write).
     */
    const ARRAY_AS_PROPS = 2;

    /**
     * @var array
     */
    protected $storage;

    /**
     * @var int
     */
    protected $flag;

    /**
     * @var string
     */
    protected $iteratorClass;

    /**
     * @var array
     */
    protected $protectedProperties;

    /**
     * Constructor
     *
     * @param array  $input
     * @param int    $flags
     * @param string $iteratorClass
     */
    public function __construct($input = array(), $flags = self::STD_PROP_LIST, $iteratorClass = 'ArrayIterator')
    {
        $this->setFlags($flags);
        $this->storage = $input;
        $this->setIteratorClass($iteratorClass);
        $this->protectedProperties = array_keys(get_object_vars($this));
    }

    /**
     * Returns whether the requested key exists
     *
     * @param  mixed $key
     * @return bool
     */
    public function __isset($key)
    {
        if ($this->flag == self::ARRAY_AS_PROPS) {
            return $this->offsetExists($key);
        }
        if (in_array($key, $this->protectedProperties)) {
            throw new Exception\InvalidArgumentException('$key is a protected property, use a different key');
        }

        return isset($this->$key);
    }

    /**
     * Sets the value at the specified key to value
     *
     * @param  mixed $key
     * @param  mixed $value
     * @return void
     */
    public function __set($key, $value)
    {
        if ($this->flag == self::ARRAY_AS_PROPS) {
            return $this->offsetSet($key, $value);
        }
        if (in_array($key, $this->protectedProperties)) {
            throw new Exception\InvalidArgumentException('$key is a protected property, use a different key');
        }
        $this->$key = $value;
    }

    /**
     * Unsets the value at the specified key
     *
     * @param  mixed $key
     * @return void
     */
    public function __unset($key)
    {
        if ($this->flag == self::ARRAY_AS_PROPS) {
            return $this->offsetUnset($key);
        }
        if (in_array($key, $this->protectedProperties)) {
            throw new Exception\InvalidArgumentException('$key is a protected property, use a different key');
        }
        unset($this->$key);
    }

    /**
     * Returns the value at the specified key by reference
     *
     * @param  mixed $key
     * @return mixed
     */
    public function &__get($key)
    {
        $ret = null;
        if ($this->flag == self::ARRAY_AS_PROPS) {
            $ret =& $this->offsetGet($key);

            return $ret;
        }
        if (in_array($key, $this->protectedProperties)) {
            throw new Exception\InvalidArgumentException('$key is a protected property, use a different key');
        }

        return $this->$key;
    }

    /**
     * Appends the value
     *
     * @param  mixed $value
     * @return void
     */
    public function append($value)
    {
        $this->storage[] = $value;
    }

    /**
     * Sort the entries by value
     *
     * @return void
     */
    public function asort()
    {
        asort($this->storage);
    }

    /**
     * Get the number of public properties in the ArrayObject
     *
     * @return int
     */
    public function count()
    {
        return count($this->storage);
    }

    /**
     * Exchange the array for another one.
     *
     * @param  array|ArrayObject $data
     * @return array
     */
    public function exchangeArray($data)
    {
        if (!is_array($data) && !is_object($data)) {
            throw new Exception\InvalidArgumentException('Passed variable is not an array or object, using empty array instead');
        }

        if (is_object($data) && ($data instanceof self || $data instanceof \ArrayObject)) {
            $data = $data->getArrayCopy();
        }
        if (!is_array($data)) {
            $data = (array) $data;
        }

        $storage = $this->storage;

        $this->storage = $data;

        return $storage;
    }

    /**
     * Creates a copy of the ArrayObject.
     *
     * @return array
     */
    public function getArrayCopy()
    {
        return $this->storage;
    }

    /**
     * Gets the behavior flags.
     *
     * @return int
     */
    public function getFlags()
    {
        return $this->flag;
    }

    /**
     * Create a new iterator from an ArrayObject instance
     *
     * @return \Iterator
     */
    public function getIterator()
    {
        $class = $this->iteratorClass;

        return new $class($this->storage);
    }

    /**
     * Gets the iterator classname for the ArrayObject.
     *
     * @return string
     */
    public function getIteratorClass()
    {
        return $this->iteratorClass;
    }

    /**
     * Sort the entries by key
     *
     * @return void
     */
    public function ksort()
    {
        ksort($this->storage);
    }

    /**
     * Sort an array using a case insensitive "natural order" algorithm
     *
     * @return void
     */
    public function natcasesort()
    {
        natcasesort($this->storage);
    }

    /**
     * Sort entries using a "natural order" algorithm
     *
     * @return void
     */
    public function natsort()
    {
        natsort($this->storage);
    }

    /**
     * Returns whether the requested key exists
     *
     * @param  mixed $key
     * @return bool
     */
    public function offsetExists($key)
    {
        return isset($this->storage[$key]);
    }

    /**
     * Returns the value at the specified key
     *
     * @param  mixed $key
     * @return mixed
     */
    public function &offsetGet($key)
    {
        $ret = null;
        if (!$this->offsetExists($key)) {
            return $ret;
        }
        $ret =& $this->storage[$key];

        return $ret;
    }

    /**
     * Sets the value at the specified key to value
     *
     * @param  mixed $key
     * @param  mixed $value
     * @return void
     */
    public function offsetSet($key, $value)
    {
        $this->storage[$key] = $value;
    }

    /**
     * Unsets the value at the specified key
     *
     * @param  mixed $key
     * @return void
     */
    public function offsetUnset($key)
    {
        if ($this->offsetExists($key)) {
            unset($this->storage[$key]);
        }
    }

    /**
     * Serialize an ArrayObject
     *
     * @return string
     */
    public function serialize()
    {
        return serialize(get_object_vars($this));
    }

    /**
     * Sets the behavior flags
     *
     * @param  int  $flags
     * @return void
     */
    public function setFlags($flags)
    {
        $this->flag = $flags;
    }

    /**
     * Sets the iterator classname for the ArrayObject
     *
     * @param  string $class
     * @return void
     */
    public function setIteratorClass($class)
    {
        if (class_exists($class)) {
            $this->iteratorClass = $class;

            return ;
        }

        if (strpos($class, '\\') === 0) {
            $class = '\\' . $class;
            if (class_exists($class)) {
                $this->iteratorClass = $class;

                return ;
            }
        }

        throw new Exception\InvalidArgumentException('The iterator class does not exist');
    }

    /**
     * Sort the entries with a user-defined comparison function and maintain key association
     *
     * @param  callable $function
     * @return void
     */
    public function uasort($function)
    {
        if (is_callable($function)) {
            uasort($this->storage, $function);
        }
    }

    /**
     * Sort the entries by keys using a user-defined comparison function
     *
     * @param  callable $function
     * @return void
     */
    public function uksort($function)
    {
        if (is_callable($function)) {
            uksort($this->storage, $function);
        }
    }

    /**
     * Unserialize an ArrayObject
     *
     * @param  string $data
     * @return void
     */
    public function unserialize($data)
    {
        $ar = unserialize($data);
        $this->setFlags($ar['flag']);
        $this->exchangeArray($ar['storage']);
        $this->setIteratorClass($ar['iteratorClass']);
        foreach ($ar as $k => $v) {
            switch ($k) {
                case 'flag':
                    $this->setFlags($v);
                    break;
                case 'storage':
                    $this->exchangeArray($v);
                    break;
                case 'iteratorClass':
                    $this->setIteratorClass($v);
                    break;
                case 'protectedProperties':
                    continue;
                default:
                    $this->__set($k, $v);
            }
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\ArrayObject;

use ArrayObject as PhpArrayObject;

/**
 * ArrayObject
 *
 * Since we need to substitute an alternate ArrayObject implementation for
 * versions > 5.3.3, we need to provide a stub for 5.3.3. This stub
 * simply extends the PHP ArrayObject implementation, and provides default
 * behavior in the constructor.
 */
abstract class PhpLegacyCompatibility extends PhpArrayObject
{
    /**
     * Constructor
     *
     * @param array  $input
     * @param int    $flags
     * @param string $iteratorClass
     */
    public function __construct($input = array(), $flags = self::STD_PROP_LIST, $iteratorClass = 'ArrayIterator')
    {
        parent::__construct($input, $flags, $iteratorClass);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Hydrator;

use ArrayObject;
use Zend\Stdlib\Exception;
use Zend\Stdlib\Hydrator\Filter\FilterComposite;
use Zend\Stdlib\Hydrator\StrategyEnabledInterface;
use Zend\Stdlib\Hydrator\Strategy\StrategyInterface;

abstract class AbstractHydrator implements HydratorInterface, StrategyEnabledInterface
{
    /**
     * The list with strategies that this hydrator has.
     *
     * @var ArrayObject
     */
    protected $strategies;

    /**
     * Composite to filter the methods, that need to be hydrated
     * @var Filter\FilterComposite
     */
    protected $filterComposite;

    /**
     * Initializes a new instance of this class.
     */
    public function __construct()
    {
        $this->strategies = new ArrayObject();
        $this->filterComposite = new FilterComposite();
    }

    /**
     * Gets the strategy with the given name.
     *
     * @param string $name The name of the strategy to get.
     * @return StrategyInterface
     */
    public function getStrategy($name)
    {
        if (isset($this->strategies[$name])) {
            return $this->strategies[$name];
        }

        if (!isset($this->strategies['*'])) {
            throw new Exception\InvalidArgumentException(sprintf(
                '%s: no strategy by name of "%s", and no wildcard strategy present',
                __METHOD__,
                $name
            ));
        }

        return $this->strategies['*'];
    }

    /**
     * Checks if the strategy with the given name exists.
     *
     * @param string $name The name of the strategy to check for.
     * @return bool
     */
    public function hasStrategy($name)
    {
        return array_key_exists($name, $this->strategies)
               || array_key_exists('*', $this->strategies);
    }

    /**
     * Adds the given strategy under the given name.
     *
     * @param string $name The name of the strategy to register.
     * @param StrategyInterface $strategy The strategy to register.
     * @return HydratorInterface
     */
    public function addStrategy($name, StrategyInterface $strategy)
    {
        $this->strategies[$name] = $strategy;
        return $this;
    }

    /**
     * Removes the strategy with the given name.
     *
     * @param string $name The name of the strategy to remove.
     * @return HydratorInterface
     */
    public function removeStrategy($name)
    {
        unset($this->strategies[$name]);
        return $this;
    }

    /**
     * Converts a value for extraction. If no strategy exists the plain value is returned.
     *
     * @param  string $name  The name of the strategy to use.
     * @param  mixed  $value  The value that should be converted.
     * @param  array  $object The object is optionally provided as context.
     * @return mixed
     */
    public function extractValue($name, $value, $object = null)
    {
        if ($this->hasStrategy($name)) {
            $strategy = $this->getStrategy($name);
            $value = $strategy->extract($value, $object);
        }
        return $value;
    }

    /**
     * Converts a value for hydration. If no strategy exists the plain value is returned.
     *
     * @param string $name The name of the strategy to use.
     * @param mixed $value The value that should be converted.
     * @param array $data The whole data is optionally provided as context.
     * @return mixed
     */
    public function hydrateValue($name, $value, $data = null)
    {
        if ($this->hasStrategy($name)) {
            $strategy = $this->getStrategy($name);
            $value = $strategy->hydrate($value, $data);
        }
        return $value;
    }

    /**
     * Get the filter instance
     *
     * @return Filter\FilterComposite
     */
    public function getFilter()
    {
        return $this->filterComposite;
    }

    /**
     * Add a new filter to take care of what needs to be hydrated.
     * To exclude e.g. the method getServiceLocator:
     *
     * <code>
     * $composite->addFilter("servicelocator",
     *     function ($property) {
     *         list($class, $method) = explode('::', $property);
     *         if ($method === 'getServiceLocator') {
     *             return false;
     *         }
     *         return true;
     *     }, FilterComposite::CONDITION_AND
     * );
     * </code>
     *
     * @param string $name Index in the composite
     * @param callable|Filter\FilterInterface $filter
     * @param int $condition
     * @return Filter\FilterComposite
     */
    public function addFilter($name, $filter, $condition = FilterComposite::CONDITION_OR)
    {
        return $this->filterComposite->addFilter($name, $filter, $condition);
    }

    /**
     * Check whether a specific filter exists at key $name or not
     *
     * @param string $name Index in the composite
     * @return bool
     */
    public function hasFilter($name)
    {
        return $this->filterComposite->hasFilter($name);
    }

    /**
     * Remove a filter from the composition.
     * To not extract "has" methods, you simply need to unregister it
     *
     * <code>
     * $filterComposite->removeFilter('has');
     * </code>
     *
     * @param $name
     * @return Filter\FilterComposite
     */
    public function removeFilter($name)
    {
        return $this->filterComposite->removeFilter($name);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Hydrator\Aggregate;


use Zend\EventManager\Event;

/**
 * Event triggered when the {@see \Zend\Stdlib\Hydrator\Aggregate\AggregateHydrator} extracts
 * data from an object
 */
class ExtractEvent extends Event
{
    const EVENT_EXTRACT = 'extract';

    /**
     * {@inheritDoc}
     */
    protected $name = self::EVENT_EXTRACT;

    /**
     * @var object
     */
    protected $extractionObject;

    /**
     * @var array
     */
    protected $extractedData = array();

    /**
     * @param object $target
     * @param object $extractionObject
     */
    public function __construct($target, $extractionObject)
    {
        $this->target           = $target;
        $this->extractionObject = $extractionObject;
    }

    /**
     * Retrieves the object from which data is extracted
     *
     * @return object
     */
    public function getExtractionObject()
    {
        return $this->extractionObject;
    }

    /**
     * @param object $extractionObject
     *
     * @return void
     */
    public function setExtractionObject($extractionObject)
    {
        $this->extractionObject = $extractionObject;
    }

    /**
     * Retrieves the data that has been extracted
     *
     * @return array
     */
    public function getExtractedData()
    {
        return $this->extractedData;
    }

    /**
     * @param array $extractedData
     *
     * @return void
     */
    public function setExtractedData(array $extractedData)
    {
        $this->extractedData = $extractedData;
    }

    /**
     * Merge provided data with the extracted data
     *
     * @param array $additionalData
     *
     * @return void
     */
    public function mergeExtractedData(array $additionalData)
    {
        $this->extractedData = array_merge($this->extractedData, $additionalData);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Hydrator\Aggregate;


use Zend\EventManager\Event;

/**
 * Event triggered when the {@see \Zend\Stdlib\Hydrator\Aggregate\AggregateHydrator} hydrates
 * data into an object
 */
class HydrateEvent extends Event
{
    const EVENT_HYDRATE = 'hydrate';

    /**
     * {@inheritDoc}
     */
    protected $name = self::EVENT_HYDRATE;

    /**
     * @var object
     */
    protected $hydratedObject;

    /**
     * @var array
     */
    protected $hydrationData;

    /**
     * @param object $target
     * @param object $hydratedObject
     * @param array  $hydrationData
     */
    public function __construct($target, $hydratedObject, array $hydrationData)
    {
        $this->target         = $target;
        $this->hydratedObject = $hydratedObject;
        $this->hydrationData  = $hydrationData;
    }

    /**
     * Retrieves the object that is being hydrated
     *
     * @return object
     */
    public function getHydratedObject()
    {
        return $this->hydratedObject;
    }

    /**
     * @param object $hydratedObject
     */
    public function setHydratedObject($hydratedObject)
    {
        $this->hydratedObject = $hydratedObject;
    }

    /**
     * Retrieves the data that is being used for hydration
     *
     * @return array
     */
    public function getHydrationData()
    {
        return $this->hydrationData;
    }

    /**
     * @param array $hydrationData
     */
    public function setHydrationData(array $hydrationData)
    {
        $this->hydrationData = $hydrationData;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Hydrator\Aggregate;

use Zend\EventManager\EventManager;
use Zend\EventManager\EventManagerAwareInterface;
use Zend\EventManager\EventManagerInterface;
use Zend\Stdlib\Exception;
use Zend\Stdlib\Hydrator\Filter\FilterComposite;
use Zend\Stdlib\Hydrator\HydratorInterface;

/**
 * Aggregate hydrator that composes multiple hydrators via events
 */
class AggregateHydrator implements HydratorInterface, EventManagerAwareInterface
{
    const DEFAULT_PRIORITY = 1;

    /**
     * @var \Zend\EventManager\EventManagerInterface|null
     */
    protected $eventManager;

    /**
     * Attaches the provided hydrator to the list of hydrators to be used while hydrating/extracting data
     *
     * @param \Zend\Stdlib\Hydrator\HydratorInterface $hydrator
     * @param int                                     $priority
     */
    public function add(HydratorInterface $hydrator, $priority = self::DEFAULT_PRIORITY)
    {
        $this->getEventManager()->attachAggregate(new HydratorListener($hydrator), $priority);
    }

    /**
     * {@inheritDoc}
     */
    public function extract($object)
    {
        $event = new ExtractEvent($this, $object);

        $this->getEventManager()->trigger($event);

        return $event->getExtractedData();
    }

    /**
     * {@inheritDoc}
     */
    public function hydrate(array $data, $object)
    {
        $event = new HydrateEvent($this, $object, $data);

        $this->getEventManager()->trigger($event);

        return $event->getHydratedObject();
    }

    /**
     * {@inheritDoc}
     */
    public function setEventManager(EventManagerInterface $eventManager)
    {
        $eventManager->setIdentifiers(array(__CLASS__, get_class($this)));

        $this->eventManager = $eventManager;
    }

    /**
     * {@inheritDoc}
     */
    public function getEventManager()
    {
        if (null === $this->eventManager) {
            $this->setEventManager(new EventManager());
        }

        return $this->eventManager;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Hydrator\Aggregate;


use Zend\EventManager\AbstractListenerAggregate;
use Zend\EventManager\EventManagerInterface;
use Zend\Stdlib\Hydrator\HydratorInterface;

/**
 * Aggregate listener wrapping around a hydrator. Listens
 * to {@see \Zend\Stdlib\Hydrator\Aggregate::EVENT_HYDRATE} and
 * {@see \Zend\Stdlib\Hydrator\Aggregate::EVENT_EXTRACT}
 */
class HydratorListener extends AbstractListenerAggregate
{
    /**
     * @var \Zend\Stdlib\Hydrator\HydratorInterface
     */
    protected $hydrator;

    /**
     * @param \Zend\Stdlib\Hydrator\HydratorInterface $hydrator
     */
    public function __construct(HydratorInterface $hydrator)
    {
        $this->hydrator = $hydrator;
    }

    /**
     * {@inheritDoc}
     */
    public function attach(EventManagerInterface $events, $priority = 1)
    {
        $this->listeners[] = $events->attach(HydrateEvent::EVENT_HYDRATE, array($this, 'onHydrate'), $priority);
        $this->listeners[] = $events->attach(ExtractEvent::EVENT_EXTRACT, array($this, 'onExtract'), $priority);
    }

    /**
     * Callback to be used when {@see \Zend\Stdlib\Hydrator\Aggregate\HydrateEvent::EVENT_HYDRATE} is triggered
     *
     * @param \Zend\Stdlib\Hydrator\Aggregate\HydrateEvent $event
     *
     * @return object
     *
     * @internal
     */
    public function onHydrate(HydrateEvent $event)
    {
        $object = $this->hydrator->hydrate($event->getHydrationData(), $event->getHydratedObject());

        $event->setHydratedObject($object);

        return $object;
    }

    /**
     * Callback to be used when {@see \Zend\Stdlib\Hydrator\Aggregate\ExtractEvent::EVENT_EXTRACT} is triggered
     *
     * @param \Zend\Stdlib\Hydrator\Aggregate\ExtractEvent $event
     *
     * @return array
     *
     * @internal
     */
    public function onExtract(ExtractEvent $event)
    {
        $data = $this->hydrator->extract($event->getExtractionObject());

        $event->mergeExtractedData($data);

        return $data;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Hydrator;

use Zend\Stdlib\Exception;

class ObjectProperty extends AbstractHydrator
{
    /**
     * Extract values from an object
     *
     * Extracts the accessible non-static properties of the given $object.
     *
     * @param  object $object
     * @return array
     * @throws Exception\BadMethodCallException for a non-object $object
     */
    public function extract($object)
    {
        if (!is_object($object)) {
            throw new Exception\BadMethodCallException(sprintf(
                '%s expects the provided $object to be a PHP object)', __METHOD__
            ));
        }

        $data = get_object_vars($object);

        $filter = $this->getFilter();
        foreach ($data as $name => $value) {
            // Filter keys, removing any we don't want
            if (!$filter->filter($name)) {
                unset($data[$name]);
                continue;
            }
            // Extract data
            $data[$name] = $this->extractValue($name, $value);
        }

        return $data;
    }

    /**
     * Hydrate an object by populating public properties
     *
     * Hydrates an object by setting public properties of the object.
     *
     * @param  array $data
     * @param  object $object
     * @return object
     * @throws Exception\BadMethodCallException for a non-object $object
     */
    public function hydrate(array $data, $object)
    {
        if (!is_object($object)) {
            throw new Exception\BadMethodCallException(sprintf(
                '%s expects the provided $object to be a PHP object)', __METHOD__
            ));
        }
        foreach ($data as $property => $value) {
            $object->$property = $this->hydrateValue($property, $value, $data);
        }
        return $object;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Hydrator;

use Zend\Stdlib\Exception;

class ArraySerializable extends AbstractHydrator
{

    /**
     * Extract values from the provided object
     *
     * Extracts values via the object's getArrayCopy() method.
     *
     * @param  object $object
     * @return array
     * @throws Exception\BadMethodCallException for an $object not implementing getArrayCopy()
     */
    public function extract($object)
    {
        if (!is_callable(array($object, 'getArrayCopy'))) {
            throw new Exception\BadMethodCallException(sprintf(
                '%s expects the provided object to implement getArrayCopy()', __METHOD__
            ));
        }

        $data = $object->getArrayCopy();

        foreach ($data as $name => $value) {
            if (!$this->getFilter()->filter($name)) {
                unset($data[$name]);
                continue;
            }

            $data[$name] = $this->extractValue($name, $value);
        }

        return $data;
    }

    /**
     * Hydrate an object
     *
     * Hydrates an object by passing $data to either its exchangeArray() or
     * populate() method.
     *
     * @param  array $data
     * @param  object $object
     * @return object
     * @throws Exception\BadMethodCallException for an $object not implementing exchangeArray() or populate()
     */
    public function hydrate(array $data, $object)
    {
        $self = $this;
        array_walk($data, function (&$value, $name) use ($self) {
            $value = $self->hydrateValue($name, $value);
        });

        if (is_callable(array($object, 'exchangeArray'))) {
            $object->exchangeArray($data);
        } elseif (is_callable(array($object, 'populate'))) {
            $object->populate($data);
        } else {
            throw new Exception\BadMethodCallException(sprintf(
                '%s expects the provided object to implement exchangeArray() or populate()', __METHOD__
            ));
        }
        return $object;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Hydrator;

use Zend\ServiceManager\AbstractPluginManager;
use Zend\Stdlib\Exception;

/**
 * Plugin manager implementation for hydrators.
 *
 * Enforces that adapters retrieved are instances of HydratorInterface
 */
class HydratorPluginManager extends AbstractPluginManager
{
    /**
     * Whether or not to share by default
     *
     * @var bool
     */
    protected $shareByDefault = false;

    /**
     * Default set of adapters
     *
     * @var array
     */
    protected $invokableClasses = array(
        'arrayserializable' => 'Zend\Stdlib\Hydrator\ArraySerializable',
        'classmethods'      => 'Zend\Stdlib\Hydrator\ClassMethods',
        'objectproperty'    => 'Zend\Stdlib\Hydrator\ObjectProperty',
        'reflection'        => 'Zend\Stdlib\Hydrator\Reflection'
    );

    /**
     * {@inheritDoc}
     */
    public function validatePlugin($plugin)
    {
        if ($plugin instanceof HydratorInterface) {
            // we're okay
            return;
        }

        throw new Exception\RuntimeException(sprintf(
            'Plugin of type %s is invalid; must implement Zend\Stdlib\Hydrator\HydratorInterface',
            (is_object($plugin) ? get_class($plugin) : gettype($plugin))
        ));
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Hydrator;

use ReflectionClass;
use Zend\Stdlib\Exception;

class Reflection extends AbstractHydrator
{
    /**
     * Simple in-memory array cache of ReflectionProperties used.
     * @var array
     */
    protected static $reflProperties = array();

    /**
     * Extract values from an object
     *
     * @param  object $object
     * @return array
     */
    public function extract($object)
    {
        $result = array();
        foreach (self::getReflProperties($object) as $property) {
            $propertyName = $property->getName();
            if (!$this->filterComposite->filter($propertyName)) {
                continue;
            }

            $value = $property->getValue($object);
            $result[$propertyName] = $this->extractValue($propertyName, $value, $object);
        }

        return $result;
    }

    /**
     * Hydrate $object with the provided $data.
     *
     * @param  array $data
     * @param  object $object
     * @return object
     */
    public function hydrate(array $data, $object)
    {
        $reflProperties = self::getReflProperties($object);
        foreach ($data as $key => $value) {
            if (isset($reflProperties[$key])) {
                $reflProperties[$key]->setValue($object, $this->hydrateValue($key, $value, $data));
            }
        }
        return $object;
    }

    /**
     * Get a reflection properties from in-memory cache and lazy-load if
     * class has not been loaded.
     *
     * @param  string|object $input
     * @throws Exception\InvalidArgumentException
     * @return array
     */
    protected static function getReflProperties($input)
    {
        if (is_object($input)) {
            $input = get_class($input);
        } elseif (!is_string($input)) {
            throw new Exception\InvalidArgumentException('Input must be a string or an object.');
        }

        if (isset(static::$reflProperties[$input])) {
            return static::$reflProperties[$input];
        }

        static::$reflProperties[$input] = array();
        $reflClass                      = new ReflectionClass($input);
        $reflProperties                 = $reflClass->getProperties();

        foreach ($reflProperties as $property) {
            $property->setAccessible(true);
            static::$reflProperties[$input][$property->getName()] = $property;
        }

        return static::$reflProperties[$input];
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Hydrator;

use Zend\Stdlib\Hydrator\Strategy\StrategyInterface;

interface StrategyEnabledInterface
{
    /**
     * Adds the given strategy under the given name.
     *
     * @param string $name The name of the strategy to register.
     * @param StrategyInterface $strategy The strategy to register.
     * @return StrategyEnabledInterface
     */
    public function addStrategy($name, StrategyInterface $strategy);

    /**
     * Gets the strategy with the given name.
     *
     * @param string $name The name of the strategy to get.
     * @return StrategyInterface
     */
    public function getStrategy($name);

    /**
     * Checks if the strategy with the given name exists.
     *
     * @param string $name The name of the strategy to check for.
     * @return bool
     */
    public function hasStrategy($name);

    /**
     * Removes the strategy with the given name.
     *
     * @param string $name The name of the strategy to remove.
     * @return StrategyEnabledInterface
     */
    public function removeStrategy($name);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link           http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright      Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license        http://framework.zend.com/license/new-bsd New BSD License
 */
namespace Zend\Stdlib\Hydrator\Filter;

class MethodMatchFilter implements FilterInterface
{
    /**
     * The method to exclude
     * @var string
     */
    protected $method = null;

    /**
     * Either an exclude or an include
     * @var bool
     */
    protected $exclude = null;

    /**
     * @param string $method The method to exclude or include
     * @param bool $exclude If the method should be excluded
     */
    public function __construct($method, $exclude = true)
    {
        $this->method = $method;
        $this->exclude = $exclude;
    }

    public function filter($property)
    {
        $pos = strpos($property, '::');
        if ($pos !== false) {
            $pos += 2;
        } else {
            $pos = 0;
        }
        if (substr($property, $pos) === $this->method) {
            return $this->exclude ? false : true;
        }
        return $this->exclude ? true : false;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link           http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright      Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license        http://framework.zend.com/license/new-bsd New BSD License
 */
namespace Zend\Stdlib\Hydrator\Filter;

class IsFilter implements FilterInterface
{
    public function filter($property)
    {
        $pos = strpos($property, '::');
        if ($pos !== false) {
            $pos += 2;
        } else {
            $pos = 0;
        }

        if (substr($property, $pos, 2) === 'is') {
            return true;
        }
        return false;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link           http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright      Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license        http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Hydrator\Filter;

use ReflectionException;
use ReflectionMethod;
use Zend\Stdlib\Exception\InvalidArgumentException;
use Zend\Stdlib\Hydrator\Filter\FilterInterface;

class NumberOfParameterFilter implements FilterInterface
{
    /**
     * The number of parameters beeing accepted
     * @var int
     */
    protected $numberOfParameters = null;

    /**
     * @param int $numberOfParameters Number of accepted parameters
     */
    public function __construct($numberOfParameters = 0)
    {
        $this->numberOfParameters = 0;
    }

    /**
     * @param string $property the name of the property
     * @return bool
     * @throws InvalidArgumentException
     */
    public function filter($property)
    {
        try {
            $reflectionMethod = new ReflectionMethod($property);
        } catch (ReflectionException $exception) {
            throw new InvalidArgumentException(
                "Method $property doesn't exist"
            );
        }

        if ($reflectionMethod->getNumberOfParameters() !== $this->numberOfParameters) {
            return false;
        }

        return true;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link           http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright      Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license        http://framework.zend.com/license/new-bsd New BSD License
 */
namespace Zend\Stdlib\Hydrator\Filter;

use ArrayObject;
use Zend\Stdlib\Exception\InvalidArgumentException;

class FilterComposite implements FilterInterface
{
    /**
     * @var ArrayObject
     */
    protected $orFilter;

    /**
     * @var ArrayObject
     */
    protected $andFilter;

    /**
     * Constant to add with "or" conditition
     */
    const CONDITION_OR = 1;

    /**
     * Constant to add with "and" conditition
     */
    const CONDITION_AND = 2;

    /**
     * Define default Filter
     *
     * @throws InvalidArgumentException
     */
    public function __construct($orFilter = array(), $andFilter = array())
    {
        array_walk($orFilter,
            function ($value, $key) {
                if (
                    !is_callable($value)
                    && !$value instanceof FilterInterface
                ) {
                    throw new InvalidArgumentException(
                        'The value of ' . $key . ' should be either a callable or ' .
                        'an instance of Zend\Stdlib\Hydrator\Filter\FilterInterface'
                    );
                }
            }
        );

        array_walk($andFilter,
            function ($value, $key) {
                if (
                    !is_callable($value)
                    && !$value instanceof FilterInterface
                ) {
                    throw new InvalidArgumentException(
                        'The value of ' . $key . '  should be either a callable or ' .
                        'an instance of Zend\Stdlib\Hydrator\Filter\FilterInterface'
                    );
                }
            }
        );

        $this->orFilter = new ArrayObject($orFilter);
        $this->andFilter = new ArrayObject($andFilter);
    }

    /**
     * Add a filter to the composite. Has to be indexed with $name in
     * order to identify a specific filter.
     *
     * This example will exclude all methods from the hydration, that starts with 'getService'
     * <code>
     * $composite->addFilter('exclude',
     *     function ($method) {
     *         if (preg_match('/^getService/', $method) {
     *             return false;
     *         }
     *         return true;
     *     }, FilterComposite::CONDITION_AND
     * );
     * </code>
     *
     * @param  string                   $name
     * @param  callable|FilterInterface $filter
     * @param  int                      $condition Can be either FilterComposite::CONDITION_OR or FilterComposite::CONDITION_AND
     * @throws InvalidArgumentException
     * @return FilterComposite
     */
    public function addFilter($name, $filter, $condition = self::CONDITION_OR)
    {
        if (!is_callable($filter) && !($filter instanceof FilterInterface)) {
            throw new InvalidArgumentException(
                'The value of ' . $name . ' should be either a callable or ' .
                'an instance of Zend\Stdlib\Hydrator\Filter\FilterInterface'
            );
        }

        if ($condition === self::CONDITION_OR) {
            $this->orFilter[$name] = $filter;
        } elseif ($condition === self::CONDITION_AND) {
            $this->andFilter[$name] = $filter;
        }

        return $this;
    }

    /**
     * Remove a filter from the composition
     *
     * @param $name string Identifier for the filter
     * @return FilterComposite
     */
    public function removeFilter($name)
    {
        if (isset($this->orFilter[$name])) {
            unset($this->orFilter[$name]);
        }

        if (isset($this->andFilter[$name])) {
            unset($this->andFilter[$name]);
        }

        return $this;
    }

    /**
     * Check if $name has a filter registered
     *
     * @param $name string Identifier for the filter
     * @return bool
     */
    public function hasFilter($name)
    {
        return isset($this->orFilter[$name]) || isset($this->andFilter[$name]);
    }

    /**
     * Filter the composite based on the AND and OR condition
     * Will return true if one from the "or conditions" and all from
     * the "and condition" returns true. Otherwise false
     *
     * @param $property string Parameter will be e.g. Parent\Namespace\Class::method
     * @return bool
     */
    public function filter($property)
    {
        $andCount = count($this->andFilter);
        $orCount = count($this->orFilter);
        // return true if no filters are registered
        if ($orCount === 0 && $andCount === 0) {
            return true;
        } elseif ($orCount === 0 && $andCount !== 0) {
            $returnValue = true;
        } else {
            $returnValue = false;
        }

        // Check if 1 from the or filters return true
        foreach ($this->orFilter as $filter) {
            if (is_callable($filter)) {
                if ($filter($property) === true) {
                    $returnValue = true;
                    break;
                }
                continue;
            } else {
                if ($filter->filter($property) === true) {
                    $returnValue = true;
                    break;
                }
            }
        }

        // Check if all of the and condition return true
        foreach ($this->andFilter as $filter) {
            if (is_callable($filter)) {
                if ($filter($property) === false) {
                    return false;
                }
                continue;
            } else {
                if ($filter->filter($property) === false) {
                    return false;
                }
            }
        }

        return $returnValue;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link           http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright      Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license        http://framework.zend.com/license/new-bsd New BSD License
 */
namespace Zend\Stdlib\Hydrator\Filter;

use InvalidArgumentException;
use ReflectionException;
use ReflectionMethod;
use ReflectionParameter;

/**
 * Filter that includes methods which have no parameters or only optional parameters
 */
class OptionalParametersFilter implements FilterInterface
{
    /**
     * Map of methods already analyzed
     * by {@see \Zend\Stdlib\Hydrator\Filter\OptionalParametersFilter::filter()},
     * cached for performance reasons
     *
     * @var bool[]
     */
    private static $propertiesCache = array();

    /**
     * {@inheritDoc}
     */
    public function filter($property)
    {
        if (isset(static::$propertiesCache[$property])) {
            return static::$propertiesCache[$property];
        }

        try {
            $reflectionMethod = new ReflectionMethod($property);
        } catch (ReflectionException $exception) {
            throw new InvalidArgumentException(sprintf('Method %s doesn\'t exist', $property));
        }

        $mandatoryParameters = array_filter(
            $reflectionMethod->getParameters(),
            function (ReflectionParameter $parameter) {
                return ! $parameter->isOptional();
            }
        );

        return static::$propertiesCache[$property] = empty($mandatoryParameters);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link           http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright      Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license        http://framework.zend.com/license/new-bsd New BSD License
 */
namespace Zend\Stdlib\Hydrator\Filter;

interface FilterProviderInterface
{
    /**
     * Provides a filter for hydration
     *
     * @return FilterInterface
     */
    public function getFilter();
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link           http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright      Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license        http://framework.zend.com/license/new-bsd New BSD License
 */
namespace Zend\Stdlib\Hydrator\Filter;

class HasFilter implements FilterInterface
{
    public function filter($property)
    {
        $pos = strpos($property, '::');
        if ($pos !== false) {
            $pos += 2;
        } else {
            $pos = 0;
        }

        if (substr($property, $pos, 3) === 'has') {
            return true;
        }
        return false;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link           http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright      Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license        http://framework.zend.com/license/new-bsd New BSD License
 */
namespace Zend\Stdlib\Hydrator\Filter;

interface FilterInterface
{
    /**
     * Should return true, if the given filter
     * does not match
     *
     * @param string $property The name of the property
     * @return bool
     */
    public function filter($property);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link           http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright      Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license        http://framework.zend.com/license/new-bsd New BSD License
 */
namespace Zend\Stdlib\Hydrator\Filter;

class GetFilter implements FilterInterface
{
    public function filter($property)
    {
        $pos = strpos($property, '::');
        if ($pos !== false) {
            $pos += 2;
        } else {
            $pos = 0;
        }

        if (substr($property, $pos, 3) === 'get') {
            return true;
        }
        return false;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Hydrator;

use ReflectionMethod;
use Traversable;
use Zend\Stdlib\Exception;
use Zend\Stdlib\ArrayUtils;
use Zend\Stdlib\Hydrator\Filter\FilterComposite;
use Zend\Stdlib\Hydrator\Filter\FilterProviderInterface;
use Zend\Stdlib\Hydrator\Filter\GetFilter;
use Zend\Stdlib\Hydrator\Filter\HasFilter;
use Zend\Stdlib\Hydrator\Filter\IsFilter;
use Zend\Stdlib\Hydrator\Filter\MethodMatchFilter;
use Zend\Stdlib\Hydrator\Filter\OptionalParametersFilter;

class ClassMethods extends AbstractHydrator implements HydratorOptionsInterface
{
    /**
     * Flag defining whether array keys are underscore-separated (true) or camel case (false)
     * @var bool
     */
    protected $underscoreSeparatedKeys = true;

    /**
     * @var \Zend\Stdlib\Hydrator\Filter\FilterInterface
     */
    private $callableMethodFilter;

    /**
     * Define if extract values will use camel case or name with underscore
     * @param bool|array $underscoreSeparatedKeys
     */
    public function __construct($underscoreSeparatedKeys = true)
    {
        parent::__construct();
        $this->setUnderscoreSeparatedKeys($underscoreSeparatedKeys);

        $this->callableMethodFilter = new OptionalParametersFilter();

        $this->filterComposite->addFilter("is", new IsFilter());
        $this->filterComposite->addFilter("has", new HasFilter());
        $this->filterComposite->addFilter("get", new GetFilter());
        $this->filterComposite->addFilter("parameter", new OptionalParametersFilter(), FilterComposite::CONDITION_AND);
    }

    /**
     * @param  array|Traversable                 $options
     * @return ClassMethods
     * @throws Exception\InvalidArgumentException
     */
    public function setOptions($options)
    {
        if ($options instanceof Traversable) {
            $options = ArrayUtils::iteratorToArray($options);
        } elseif (!is_array($options)) {
            throw new Exception\InvalidArgumentException(
                'The options parameter must be an array or a Traversable'
            );
        }
        if (isset($options['underscoreSeparatedKeys'])) {
            $this->setUnderscoreSeparatedKeys($options['underscoreSeparatedKeys']);
        }

        return $this;
    }

    /**
     * @param  bool      $underscoreSeparatedKeys
     * @return ClassMethods
     */
    public function setUnderscoreSeparatedKeys($underscoreSeparatedKeys)
    {
        $this->underscoreSeparatedKeys = $underscoreSeparatedKeys;

        return $this;
    }

    /**
     * @return bool
     */
    public function getUnderscoreSeparatedKeys()
    {
        return $this->underscoreSeparatedKeys;
    }

    /**
     * Extract values from an object with class methods
     *
     * Extracts the getter/setter of the given $object.
     *
     * @param  object                           $object
     * @return array
     * @throws Exception\BadMethodCallException for a non-object $object
     */
    public function extract($object)
    {
        if (!is_object($object)) {
            throw new Exception\BadMethodCallException(sprintf(
                '%s expects the provided $object to be a PHP object)', __METHOD__
            ));
        }

        $filter = null;
        if ($object instanceof FilterProviderInterface) {
            $filter = new FilterComposite(
                array($object->getFilter()),
                array(new MethodMatchFilter("getFilter"))
            );
        } else {
            $filter = $this->filterComposite;
        }

        $transform = function ($letters) {
            $letter = array_shift($letters);

            return '_' . strtolower($letter);
        };
        $attributes = array();
        $methods = get_class_methods($object);

        foreach ($methods as $method) {
            if (
                !$filter->filter(
                    get_class($object) . '::' . $method
                )
            ) {
                continue;
            }

            if (!$this->callableMethodFilter->filter(get_class($object) . '::' . $method)) {
                continue;
            }

            $attribute = $method;
            if (preg_match('/^get/', $method)) {
                $attribute = substr($method, 3);
                if (!property_exists($object, $attribute)) {
                    $attribute = lcfirst($attribute);
                }
            }

            if ($this->underscoreSeparatedKeys) {
                $attribute = preg_replace_callback('/([A-Z])/', $transform, $attribute);
            }
            $attributes[$attribute] = $this->extractValue($attribute, $object->$method(), $object);
        }

        return $attributes;
    }

    /**
     * Hydrate an object by populating getter/setter methods
     *
     * Hydrates an object by getter/setter methods of the object.
     *
     * @param  array                            $data
     * @param  object                           $object
     * @return object
     * @throws Exception\BadMethodCallException for a non-object $object
     */
    public function hydrate(array $data, $object)
    {
        if (!is_object($object)) {
            throw new Exception\BadMethodCallException(sprintf(
                '%s expects the provided $object to be a PHP object)', __METHOD__
            ));
        }

        $transform = function ($letters) {
            $letter = substr(array_shift($letters), 1, 1);

            return ucfirst($letter);
        };

        foreach ($data as $property => $value) {
            $method = 'set' . ucfirst($property);
            if ($this->underscoreSeparatedKeys) {
                $method = preg_replace_callback('/(_[a-z])/i', $transform, $method);
            }
            if (is_callable(array($object, $method))) {
                $value = $this->hydrateValue($property, $value, $data);
                $object->$method($value);
            }
        }

        return $object;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Hydrator;

interface HydratorAwareInterface
{
    /**
     * Set hydrator
     *
     * @param  HydratorInterface $hydrator
     * @return HydratorAwareInterface
     */
    public function setHydrator(HydratorInterface $hydrator);

    /**
     * Retrieve hydrator
     *
     * @return HydratorInterface
     */
    public function getHydrator();
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Hydrator;

interface HydratorOptionsInterface
{
    /**
     * @param  array|\Traversable $options
     * @return HydratorOptionsInterface
     */
    public function setOptions($options);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Hydrator;

interface HydratorInterface
{
    /**
     * Extract values from an object
     *
     * @param  object $object
     * @return array
     */
    public function extract($object);

    /**
     * Hydrate $object with the provided $data.
     *
     * @param  array $data
     * @param  object $object
     * @return object
     */
    public function hydrate(array $data, $object);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Hydrator\Strategy;

/**
 * @todo v3.0, add optional object/data to extract/hydrate.
 */
interface StrategyInterface
{
    /**
     * Converts the given value so that it can be extracted by the hydrator.
     *
     * @param mixed   $value The original value.
     * @param object $object (optional) The original object for context.
     * @return mixed Returns the value that should be extracted.
     */
    public function extract($value);

    /**
     * Converts the given value so that it can be hydrated by the hydrator.
     *
     * @param mixed $value The original value.
     * @param array  $data (optional) The original data for context.
     * @return mixed Returns the value that should be hydrated.
     */
    public function hydrate($value);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Hydrator\Strategy;

class ClosureStrategy implements StrategyInterface
{
    /**
     * Function, used in extract method, default:
     * function ($value) {
     *     return $value;
     * };
     * @var callable
     */
    protected $extractFunc = null;

    /**
     * Function, used in hydrate method, default:
     * function ($value) {
     *     return $value;
     * };
     * @var callable
     */
    protected $hydrateFunc = null;

    /**
     * You can describe how your values will extract and hydrate, like this:
     * $hydrator->addStrategy('category', new ClosureStrategy(
     *     function (Category $value) {
     *         return (int) $value->id;
     *     },
     *     function ($value) {
     *         return new Category((int) $value);
     *     }
     * ));
     *
     * @param callable $extractFunc - anonymous function, that extract values
     * from object
     * @param callable $hydrateFunc - anonymous function, that hydrate values
     * into object
     */
    public function __construct($extractFunc = null, $hydrateFunc = null)
    {
        if (isset($extractFunc)) {
            if (!is_callable($extractFunc)) {
                throw new \Exception('$extractFunc must be callable');
            }

            $this->extractFunc = $extractFunc;
        } else {
            $this->extractFunc = function ($value) {
                return $value;
            };
        }

        if (isset($hydrateFunc)) {
            if (!is_callable($hydrateFunc)) {
                throw new \Exception('$hydrateFunc must be callable');
            }

            $this->hydrateFunc = $hydrateFunc;
        } else {
            $this->hydrateFunc = function ($value) {
                return $value;
            };
        }
    }

    /**
     * Converts the given value so that it can be extracted by the hydrator.
     *
     * @param mixed $value The original value.
     * @return mixed Returns the value that should be extracted.
     */
    public function extract($value)
    {
        $func = $this->extractFunc;

        return $func($value);
    }

    /**
     * Converts the given value so that it can be hydrated by the hydrator.
     *
     * @param mixed $value The original value.
     * @return mixed Returns the value that should be hydrated.
     */
    public function hydrate($value)
    {
        $func = $this->hydrateFunc;

        return $func($value);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Hydrator\Strategy;

use Zend\Stdlib\Exception\InvalidArgumentException;
use Zend\Serializer\Adapter\AdapterInterface as SerializerAdapter;
use Zend\Serializer\Serializer as SerializerFactory;

class SerializableStrategy implements StrategyInterface
{
    /**
     * @var string|SerializerAdapter
     */
    protected $serializer;

    /**
     * @var array
     */
    protected $serializerOptions = array();

    /**
     *
     * @param mixed $serializer string or SerializerAdapter
     * @param mixed $serializerOptions
     */
    public function __construct($serializer, $serializerOptions = null)
    {
        $this->setSerializer($serializer);
        if ($serializerOptions) {
            $this->setSerializerOptions($serializerOptions);
        }
    }

    /**
     * Serialize the given value so that it can be extracted by the hydrator.
     *
     * @param mixed $value The original value.
     * @return mixed Returns the value that should be extracted.
     */
    public function extract($value)
    {
        $serializer = $this->getSerializer();
        return $serializer->serialize($value);
    }

    /**
     * Unserialize the given value so that it can be hydrated by the hydrator.
     *
     * @param mixed $value The original value.
     * @return mixed Returns the value that should be hydrated.
     */
    public function hydrate($value)
    {
        $serializer = $this->getSerializer();
        return $serializer->unserialize($value);
    }

    /**
     * Set serializer
     *
     * @param  string|SerializerAdapter $serializer
     * @return SerializableStrategy
     */
    public function setSerializer($serializer)
    {
        if (!is_string($serializer) && !$serializer instanceof SerializerAdapter) {
            throw new InvalidArgumentException(sprintf(
                '%s expects either a string serializer name or Zend\Serializer\Adapter\AdapterInterface instance; '
                . 'received "%s"',
                __METHOD__,
                (is_object($serializer) ? get_class($serializer) : gettype($serializer))
            ));
        }
        $this->serializer = $serializer;
        return $this;
    }

    /**
     * Get serializer
     *
     * @return SerializerAdapter
     */
    public function getSerializer()
    {
        if (is_string($this->serializer)) {
            $options = $this->getSerializerOptions();
            $this->setSerializer(SerializerFactory::factory($this->serializer, $options));
        } elseif (null === $this->serializer) {
            $this->setSerializer(SerializerFactory::getDefaultAdapter());
        }

        return $this->serializer;
    }

    /**
     * Set configuration options for instantiating a serializer adapter
     *
     * @param  mixed $serializerOptions
     * @return SerializableStrategy
     */
    public function setSerializerOptions($serializerOptions)
    {
        $this->serializerOptions = $serializerOptions;
        return $this;
    }

    /**
     * Get configuration options for instantiating a serializer adapter
     *
     * @return mixed
     */
    public function getSerializerOptions()
    {
        return $this->serializerOptions;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Hydrator\Strategy;

class DefaultStrategy implements StrategyInterface
{
    /**
     * Converts the given value so that it can be extracted by the hydrator.
     *
     * @param mixed $value The original value.
     * @return mixed Returns the value that should be extracted.
     */
    public function extract($value)
    {
        return $value;
    }

    /**
     * Converts the given value so that it can be hydrated by the hydrator.
     *
     * @param mixed $value The original value.
     * @return mixed Returns the value that should be hydrated.
     */
    public function hydrate($value)
    {
        return $value;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib;

use ErrorException;

/**
 * ErrorHandler that can be used to catch internal PHP errors
 * and convert to a ErrorException instance.
 */
abstract class ErrorHandler
{
    /**
     * Active stack
     *
     * @var array
     */
    protected static $stack = array();

    /**
     * Check if this error handler is active
     *
     * @return bool
     */
    public static function started()
    {
        return (bool) static::getNestedLevel();
    }

    /**
     * Get the current nested level
     *
     * @return int
     */
    public static function getNestedLevel()
    {
        return count(static::$stack);
    }

    /**
     * Starting the error handler
     *
     * @param int $errorLevel
     */
    public static function start($errorLevel = \E_WARNING)
    {
        if (!static::$stack) {
            set_error_handler(array(get_called_class(), 'addError'), $errorLevel);
        }

        static::$stack[] = null;
    }

    /**
     * Stopping the error handler
     *
     * @param  bool $throw Throw the ErrorException if any
     * @return null|ErrorException
     * @throws ErrorException If an error has been catched and $throw is true
     */
    public static function stop($throw = false)
    {
        $errorException = null;

        if (static::$stack) {
            $errorException = array_pop(static::$stack);

            if (!static::$stack) {
                restore_error_handler();
            }

            if ($errorException && $throw) {
                throw $errorException;
            }
        }

        return $errorException;
    }

    /**
     * Stop all active handler
     *
     * @return void
     */
    public static function clean()
    {
        if (static::$stack) {
            restore_error_handler();
        }

        static::$stack = array();
    }

    /**
     * Add an error to the stack
     *
     * @param int    $errno
     * @param string $errstr
     * @param string $errfile
     * @param int    $errline
     * @return void
     */
    public static function addError($errno, $errstr = '', $errfile = '', $errline = 0)
    {
        $stack = & static::$stack[count(static::$stack) - 1];
        $stack = new ErrorException($errstr, 0, $errno, $errfile, $errline, $stack);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Exception;

/**
 * Extension not loaded exception
 */
class ExtensionNotLoadedException extends RuntimeException
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Exception;

/**
 * Invalid Argument Exception
 */
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Exception;

/**
 * Runtime exception
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Exception;

/**
 * Invalid callback exception
 */
class InvalidCallbackException extends DomainException implements ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Exception;

/**
 * Logic exception
 */
class LogicException extends \LogicException implements ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Exception;

/**
 * Domain exception
 */
class DomainException extends \DomainException implements ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Exception;

/**
 * Exception marker interface
 */
interface ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib\Exception;

/**
 * Bad method call exception
 */
class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib;

use Zend\Stdlib\RequestInterface as Request;
use Zend\Stdlib\ResponseInterface as Response;

interface DispatchableInterface
{
    /**
     * Dispatch a request
     *
     * @param Request $request
     * @param null|Response $response
     * @return Response|mixed
     */
    public function dispatch(Request $request, Response $response = null);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib;

/**
 * If the version is less than 5.3.4, we'll use Zend\Stdlib\ArrayObject\PhpLegacyCompatibility
 * which extends the native PHP ArrayObject implementation. For versions greater than or equal
 * to 5.3.4, we'll use Zend\Stdlib\ArrayObject\PhpReferenceCompatibility, which corrects
 * issues with how PHP handles references inside ArrayObject.
 *
 * class_alias is a global construct, so we can alias either one to Zend\Stdlib\ArrayObject,
 * and from this point forward, that alias will be used.
 */
if (version_compare(PHP_VERSION, '5.3.4', 'lt')) {
    class_alias('Zend\Stdlib\ArrayObject\PhpLegacyCompatibility', 'Zend\Stdlib\AbstractArrayObject');
} else {
    class_alias('Zend\Stdlib\ArrayObject\PhpReferenceCompatibility', 'Zend\Stdlib\AbstractArrayObject');
}

/**
 * Custom framework ArrayObject implementation
 *
 * Extends version-specific "abstract" implementation.
 */
class ArrayObject extends AbstractArrayObject
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib;

use Closure;
use ReflectionClass;

/**
 * CallbackHandler
 *
 * A handler for a event, event, filterchain, etc. Abstracts PHP callbacks,
 * primarily to allow for lazy-loading and ensuring availability of default
 * arguments (currying).
 */
class CallbackHandler
{
    /**
     * @var string|array|callable PHP callback to invoke
     */
    protected $callback;

    /**
     * Callback metadata, if any
     * @var array
     */
    protected $metadata;

    /**
     * PHP version is greater as 5.4rc1?
     * @var bool
     */
    protected static $isPhp54;

    /**
     * Constructor
     *
     * @param  string|array|object|callable $callback PHP callback
     * @param  array                        $metadata  Callback metadata
     */
    public function __construct($callback, array $metadata = array())
    {
        $this->metadata  = $metadata;
        $this->registerCallback($callback);
    }

    /**
     * Registers the callback provided in the constructor
     *
     * @param  callable $callback
     * @throws Exception\InvalidCallbackException
     * @return void
     */
    protected function registerCallback($callback)
    {
        if (!is_callable($callback)) {
            throw new Exception\InvalidCallbackException('Invalid callback provided; not callable');
        }

        $this->callback = $callback;
    }

    /**
     * Retrieve registered callback
     *
     * @return callable
     */
    public function getCallback()
    {
        return $this->callback;
    }

    /**
     * Invoke handler
     *
     * @param  array $args Arguments to pass to callback
     * @return mixed
     */
    public function call(array $args = array())
    {
        $callback = $this->getCallback();

        // Minor performance tweak, if the callback gets called more than once
        if (!isset(static::$isPhp54)) {
            static::$isPhp54 = version_compare(PHP_VERSION, '5.4.0rc1', '>=');
        }

        $argCount = count($args);

        if (static::$isPhp54 && is_string($callback)) {
            $result = $this->validateStringCallbackFor54($callback);

            if ($result !== true && $argCount <= 3) {
                $callback       = $result;
                // Minor performance tweak, if the callback gets called more
                // than once
                $this->callback = $result;
            }
        }

        // Minor performance tweak; use call_user_func() until > 3 arguments
        // reached
        switch ($argCount) {
            case 0:
                if (static::$isPhp54) {
                    return $callback();
                }
                return call_user_func($callback);
            case 1:
                if (static::$isPhp54) {
                    return $callback(array_shift($args));
                }
                return call_user_func($callback, array_shift($args));
            case 2:
                $arg1 = array_shift($args);
                $arg2 = array_shift($args);
                if (static::$isPhp54) {
                    return $callback($arg1, $arg2);
                }
                return call_user_func($callback, $arg1, $arg2);
            case 3:
                $arg1 = array_shift($args);
                $arg2 = array_shift($args);
                $arg3 = array_shift($args);
                if (static::$isPhp54) {
                    return $callback($arg1, $arg2, $arg3);
                }
                return call_user_func($callback, $arg1, $arg2, $arg3);
            default:
                return call_user_func_array($callback, $args);
        }
    }

    /**
     * Invoke as functor
     *
     * @return mixed
     */
    public function __invoke()
    {
        return $this->call(func_get_args());
    }

    /**
     * Get all callback metadata
     *
     * @return array
     */
    public function getMetadata()
    {
        return $this->metadata;
    }

    /**
     * Retrieve a single metadatum
     *
     * @param  string $name
     * @return mixed
     */
    public function getMetadatum($name)
    {
        if (array_key_exists($name, $this->metadata)) {
            return $this->metadata[$name];
        }
        return null;
    }

    /**
     * Validate a static method call
     *
     * Validates that a static method call in PHP 5.4 will actually work
     *
     * @param  string $callback
     * @return true|array
     * @throws Exception\InvalidCallbackException if invalid
     */
    protected function validateStringCallbackFor54($callback)
    {
        if (!strstr($callback, '::')) {
            return true;
        }

        list($class, $method) = explode('::', $callback, 2);

        if (!class_exists($class)) {
            throw new Exception\InvalidCallbackException(sprintf(
                'Static method call "%s" refers to a class that does not exist',
                $callback
            ));
        }

        $r = new ReflectionClass($class);
        if (!$r->hasMethod($method)) {
            throw new Exception\InvalidCallbackException(sprintf(
                'Static method call "%s" refers to a method that does not exist',
                $callback
            ));
        }
        $m = $r->getMethod($method);
        if (!$m->isStatic()) {
            throw new Exception\InvalidCallbackException(sprintf(
                'Static method call "%s" refers to a method that is not static',
                $callback
            ));
        }

        // returning a non boolean value may not be nice for a validate method,
        // but that allows the usage of a static string callback without using
        // the call_user_func function.
        return array($class, $method);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib;

/**
 * Interface to allow objects to have initialization logic
 */
interface InitializableInterface
{
    /**
     * Init an object
     *
     * @return void
     */
    public function init();
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib;

class Request extends Message implements RequestInterface
{
    // generic request implementation
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib;

class Response extends Message implements ResponseInterface
{
    // generic response implementation
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib;

use Traversable;

/**
 * Utility class for testing and manipulation of PHP arrays.
 *
 * Declared abstract, as we have no need for instantiation.
 */
abstract class ArrayUtils
{
    /**
     * Test whether an array contains one or more string keys
     *
     * @param  mixed $value
     * @param  bool  $allowEmpty    Should an empty array() return true
     * @return bool
     */
    public static function hasStringKeys($value, $allowEmpty = false)
    {
        if (!is_array($value)) {
            return false;
        }

        if (!$value) {
            return $allowEmpty;
        }

        return count(array_filter(array_keys($value), 'is_string')) > 0;
    }

    /**
     * Test whether an array contains one or more integer keys
     *
     * @param  mixed $value
     * @param  bool  $allowEmpty    Should an empty array() return true
     * @return bool
     */
    public static function hasIntegerKeys($value, $allowEmpty = false)
    {
        if (!is_array($value)) {
            return false;
        }

        if (!$value) {
            return $allowEmpty;
        }

        return count(array_filter(array_keys($value), 'is_int')) > 0;
    }

    /**
     * Test whether an array contains one or more numeric keys.
     *
     * A numeric key can be one of the following:
     * - an integer 1,
     * - a string with a number '20'
     * - a string with negative number: '-1000'
     * - a float: 2.2120, -78.150999
     * - a string with float:  '4000.99999', '-10.10'
     *
     * @param  mixed $value
     * @param  bool  $allowEmpty    Should an empty array() return true
     * @return bool
     */
    public static function hasNumericKeys($value, $allowEmpty = false)
    {
        if (!is_array($value)) {
            return false;
        }

        if (!$value) {
            return $allowEmpty;
        }

        return count(array_filter(array_keys($value), 'is_numeric')) > 0;
    }

    /**
     * Test whether an array is a list
     *
     * A list is a collection of values assigned to continuous integer keys
     * starting at 0 and ending at count() - 1.
     *
     * For example:
     * <code>
     * $list = array('a', 'b', 'c', 'd');
     * $list = array(
     *     0 => 'foo',
     *     1 => 'bar',
     *     2 => array('foo' => 'baz'),
     * );
     * </code>
     *
     * @param  mixed $value
     * @param  bool  $allowEmpty    Is an empty list a valid list?
     * @return bool
     */
    public static function isList($value, $allowEmpty = false)
    {
        if (!is_array($value)) {
            return false;
        }

        if (!$value) {
            return $allowEmpty;
        }

        return (array_values($value) === $value);
    }

    /**
     * Test whether an array is a hash table.
     *
     * An array is a hash table if:
     *
     * 1. Contains one or more non-integer keys, or
     * 2. Integer keys are non-continuous or misaligned (not starting with 0)
     *
     * For example:
     * <code>
     * $hash = array(
     *     'foo' => 15,
     *     'bar' => false,
     * );
     * $hash = array(
     *     1995  => 'Birth of PHP',
     *     2009  => 'PHP 5.3.0',
     *     2012  => 'PHP 5.4.0',
     * );
     * $hash = array(
     *     'formElement,
     *     'options' => array( 'debug' => true ),
     * );
     * </code>
     *
     * @param  mixed $value
     * @param  bool  $allowEmpty    Is an empty array() a valid hash table?
     * @return bool
     */
    public static function isHashTable($value, $allowEmpty = false)
    {
        if (!is_array($value)) {
            return false;
        }

        if (!$value) {
            return $allowEmpty;
        }

        return (array_values($value) !== $value);
    }

    /**
     * Checks if a value exists in an array.
     *
     * Due to "foo" == 0 === TRUE with in_array when strict = false, an option
     * has been added to prevent this. When $strict = 0/false, the most secure
     * non-strict check is implemented. if $strict = -1, the default in_array
     * non-strict behaviour is used.
     *
     * @param mixed $needle
     * @param array $haystack
     * @param int|bool $strict
     * @return bool
     */
    public static function inArray($needle, array $haystack, $strict = false)
    {
        if (!$strict) {
            if (is_int($needle) || is_float($needle)) {
                $needle = (string) $needle;
            }
            if (is_string($needle)) {
                foreach ($haystack as &$h) {
                    if (is_int($h) || is_float($h)) {
                        $h = (string) $h;
                    }
                }
            }
        }
        return in_array($needle, $haystack, $strict);
    }

    /**
     * Convert an iterator to an array.
     *
     * Converts an iterator to an array. The $recursive flag, on by default,
     * hints whether or not you want to do so recursively.
     *
     * @param  array|Traversable  $iterator     The array or Traversable object to convert
     * @param  bool               $recursive    Recursively check all nested structures
     * @throws Exception\InvalidArgumentException if $iterator is not an array or a Traversable object
     * @return array
     */
    public static function iteratorToArray($iterator, $recursive = true)
    {
        if (!is_array($iterator) && !$iterator instanceof Traversable) {
            throw new Exception\InvalidArgumentException(__METHOD__ . ' expects an array or Traversable object');
        }

        if (!$recursive) {
            if (is_array($iterator)) {
                return $iterator;
            }

            return iterator_to_array($iterator);
        }

        if (method_exists($iterator, 'toArray')) {
            return $iterator->toArray();
        }

        $array = array();
        foreach ($iterator as $key => $value) {
            if (is_scalar($value)) {
                $array[$key] = $value;
                continue;
            }

            if ($value instanceof Traversable) {
                $array[$key] = static::iteratorToArray($value, $recursive);
                continue;
            }

            if (is_array($value)) {
                $array[$key] = static::iteratorToArray($value, $recursive);
                continue;
            }

            $array[$key] = $value;
        }

        return $array;
    }

    /**
     * Merge two arrays together.
     *
     * If an integer key exists in both arrays, the value from the second array
     * will be appended the the first array. If both values are arrays, they
     * are merged together, else the value of the second array overwrites the
     * one of the first array.
     *
     * @param  array $a
     * @param  array $b
     * @return array
     */
    public static function merge(array $a, array $b)
    {
        foreach ($b as $key => $value) {
            if (array_key_exists($key, $a)) {
                if (is_int($key)) {
                    $a[] = $value;
                } elseif (is_array($value) && is_array($a[$key])) {
                    $a[$key] = static::merge($a[$key], $value);
                } else {
                    $a[$key] = $value;
                }
            } else {
                $a[$key] = $value;
            }
        }

        return $a;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Stdlib;

use DateTimeZone;

trigger_error('DateTime extension deprecated as of ZF 2.1.4; use the \DateTime constructor to parse extended ISO8601 dates instead', E_USER_DEPRECATED);

/**
 * DateTime
 *
 * An extension of the \DateTime object.
 *
 * @deprecated
 */
class DateTime extends \DateTime
{
    /**
     * The DateTime::ISO8601 constant used by php's native DateTime object does
     * not allow for fractions of a second. This function better handles ISO8601
     * formatted date strings.
     *
     * @param  string       $time
     * @param  DateTimeZone $timezone
     * @return mixed
     */
    public static function createFromISO8601($time, DateTimeZone $timezone = null)
    {
        $format = self::ISO8601;
        if (isset($time[19]) && $time[19] === '.') {
            $format = 'Y-m-d\TH:i:s.uO';
        }

        if ($timezone !== null) {
            return self::createFromFormat($format, $time, $timezone);
        }

        return self::createFromFormat($format, $time);
    }
}
{
    "name": "zendframework/zend-config",
    "description": "provides a nested object property based user interface for accessing this configuration data within application code",
    "license": "BSD-3-Clause",
    "keywords": [
        "zf2",
        "config"
    ],
    "autoload": {
        "psr-0": {
            "Zend\\Config\\": ""
        }
    },
    "target-dir": "Zend/Config",
    "require": {
        "php": ">=5.3.3",
        "zendframework/zend-stdlib": "self.version"
    },
    "suggest": {
        "zendframework/zend-json": "Zend\\Json to use the Json reader or writer classes",
        "zendframework/zend-servicemanager": "Zend\\ServiceManager for use with the Config Factory to retrieve reader and writer instances"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "2.2-dev",
            "dev-develop": "2.3-dev"
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Config;

use Zend\ServiceManager\AbstractPluginManager;

class WriterPluginManager extends AbstractPluginManager
{
    protected $invokableClasses = array(
        'php'  => 'Zend\Config\Writer\PhpArray',
        'ini'  => 'Zend\Config\Writer\Ini',
        'json' => 'Zend\Config\Writer\Json',
        'yaml' => 'Zend\Config\Writer\Yaml',
        'xml'  => 'Zend\Config\Writer\Xml',
    );

    public function validatePlugin($plugin)
    {
        if ($plugin instanceOf Writer\AbstractWriter) {
            return;
        }

        $type = is_object($plugin) ? get_class($plugin) : gettype($plugin);

        throw new Exception\InvalidArgumentException(
            "Plugin of type {$type} is invalid. Plugin must extend ".
                __NAMESPACE__.'\Writer\AbstractWriter'
        );
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Config\Processor;

use Zend\Config\Config;

interface ProcessorInterface
{
    /**
     * Process the whole Config structure and recursively parse all its values.
     *
     * @param  Config $value
     * @return Config
     */
    public function process(Config $value);

    /**
     * Process a single value
     *
     * @param  mixed $value
     * @return mixed
     */
    public function processValue($value);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Config\Processor;

use Zend\Config\Config;
use Zend\Config\Exception;
use Zend\I18n\Translator\Translator as ZendTranslator;

class Translator implements ProcessorInterface
{
    /**
     * @var ZendTranslator
     */
    protected $translator;

    /**
     * @var string|null
     */
    protected $locale = null;

    /**
     * @var string
     */
    protected $textDomain = 'default';

    /**
     * Translator uses the supplied Zend\I18n\Translator\Translator to find
     * and translate language strings in config.
     *
     * @param  ZendTranslator $translator
     * @param  string $textDomain
     * @param  string|null $locale
     */
    public function __construct(ZendTranslator $translator, $textDomain = 'default', $locale = null)
    {
        $this->setTranslator($translator);
        $this->setTextDomain($textDomain);
        $this->setLocale($locale);
    }

    /**
     * @param  ZendTranslator $translator
     * @return Translator
     */
    public function setTranslator(ZendTranslator $translator)
    {
        $this->translator = $translator;
        return $this;
    }

    /**
     * @return ZendTranslator
     */
    public function getTranslator()
    {
        return $this->translator;
    }

    /**
     * @param  string|null $locale
     * @return Translator
     */
    public function setLocale($locale)
    {
        $this->locale = $locale;
        return $this;
    }

    /**
     * @return string|null
     */
    public function getLocale()
    {
        return $this->locale;
    }

    /**
     * @param  string $textDomain
     * @return Translator
     */
    public function setTextDomain($textDomain)
    {
        $this->textDomain = $textDomain;
        return $this;
    }

    /**
     * @return string
     */
    public function getTextDomain()
    {
        return $this->textDomain;
    }

    /**
     * Process
     *
     * @param  Config $config
     * @return Config
     * @throws Exception\InvalidArgumentException
     */
    public function process(Config $config)
    {
        if ($config->isReadOnly()) {
            throw new Exception\InvalidArgumentException('Cannot process config because it is read-only');
        }

        /**
         * Walk through config and replace values
         */
        foreach ($config as $key => $val) {
            if ($val instanceof Config) {
                $this->process($val);
            } else {
                $config->{$key} = $this->translator->translate($val, $this->textDomain, $this->locale);
            }
        }

        return $config;
    }

    /**
     * Process a single value
     *
     * @param $value
     * @return mixed
     */
    public function processValue($value)
    {
        return $this->translator->translate($value, $this->textDomain, $this->locale);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Config\Processor;

class Constant extends Token implements ProcessorInterface
{
    /**
     * Replace only user-defined tokens
     *
     * @var bool
     */
    protected $userOnly = true;

    /**
     * Constant Processor walks through a Config structure and replaces all
     * PHP constants with their respective values
     *
     * @param bool   $userOnly              True to process only user-defined constants, false to process all PHP constants
     * @param string $prefix                Optional prefix
     * @param string $suffix                Optional suffix
     * @return \Zend\Config\Processor\Constant
     */
    public function __construct($userOnly = true, $prefix = '', $suffix = '')
    {
        $this->setUserOnly($userOnly);
        $this->setPrefix($prefix);
        $this->setSuffix($suffix);

        $this->loadConstants();
    }

    /**
     * @return bool
     */
    public function getUserOnly()
    {
        return $this->userOnly;
    }

    /**
     * Should we use only user-defined constants?
     *
     * @param  bool $userOnly
     * @return Constant
     */
    public function setUserOnly($userOnly)
    {
        $this->userOnly = (bool) $userOnly;
        return $this;
    }

    /**
     * Load all currently defined constants into parser.
     *
     * @return void
     */
    public function loadConstants()
    {
        if ($this->userOnly) {
            $constants = get_defined_constants(true);
            $constants = isset($constants['user']) ? $constants['user'] : array();
            $this->setTokens($constants);
        } else {
            $this->setTokens(get_defined_constants());
        }
    }

    /**
     * Get current token registry.
     * @return array
     */
    public function getTokens()
    {
        return $this->tokens;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Config\Processor;

use Traversable;
use Zend\Config\Config;
use Zend\Config\Exception;

class Token implements ProcessorInterface
{
    /**
     * Token prefix.
     *
     * @var string
     */
    protected $prefix = '';

    /**
     * Token suffix.
     *
     * @var string
     */
    protected $suffix = '';

    /**
     * The registry of tokens
     *
     * @var array
     */
    protected $tokens = array();

    /**
     * Replacement map
     *
     * @var array
     */
    protected $map = null;

    /**
     * Token Processor walks through a Config structure and replaces all
     * occurrences of tokens with supplied values.
     *
     * @param  array|Config|Traversable   $tokens  Associative array of TOKEN => value
     *                                             to replace it with
     * @param    string $prefix
     * @param    string $suffix
     * @internal param array $options
     * @return   Token
     */
    public function __construct($tokens = array(), $prefix = '', $suffix = '')
    {
        $this->setTokens($tokens);
        $this->setPrefix($prefix);
        $this->setSuffix($suffix);
    }

    /**
     * @param  string $prefix
     * @return Token
     */
    public function setPrefix($prefix)
    {
        // reset map
        $this->map = null;
        $this->prefix = $prefix;
        return $this;
    }

    /**
     * @return string
     */
    public function getPrefix()
    {
        return $this->prefix;
    }

    /**
     * @param  string $suffix
     * @return Token
     */
    public function setSuffix($suffix)
    {
        // reset map
        $this->map = null;
        $this->suffix = $suffix;

        return $this;
    }

    /**
     * @return string
     */
    public function getSuffix()
    {
        return $this->suffix;
    }

    /**
     * Set token registry.
     *
     * @param  array|Config|Traversable  $tokens  Associative array of TOKEN => value
     *                                            to replace it with
     * @return Token
     * @throws Exception\InvalidArgumentException
     */
    public function setTokens($tokens)
    {
        if (is_array($tokens)) {
            $this->tokens = $tokens;
        } elseif ($tokens instanceof Config) {
            $this->tokens = $tokens->toArray();
        } elseif ($tokens instanceof Traversable) {
            $this->tokens = array();
            foreach ($tokens as $key => $val) {
                $this->tokens[$key] = $val;
            }
        } else {
            throw new Exception\InvalidArgumentException('Cannot use ' . gettype($tokens) . ' as token registry.');
        }

        // reset map
        $this->map = null;

        return $this;
    }

    /**
     * Get current token registry.
     *
     * @return array
     */
    public function getTokens()
    {
        return $this->tokens;
    }

    /**
     * Add new token.
     *
     * @param  string $token
     * @param  mixed $value
     * @return Token
     * @throws Exception\InvalidArgumentException
     */
    public function addToken($token, $value)
    {
        if (!is_scalar($token)) {
            throw new Exception\InvalidArgumentException('Cannot use ' . gettype($token) . ' as token name.');
        }
        $this->tokens[$token] = $value;

        // reset map
        $this->map = null;

        return $this;
    }

    /**
     * Add new token.
     *
     * @param string $token
     * @param mixed $value
     * @return Token
     */
    public function setToken($token, $value)
    {
        return $this->addToken($token, $value);
    }

    /**
     * Build replacement map
     */
    protected function buildMap()
    {
        if (!$this->suffix && !$this->prefix) {
            $this->map = $this->tokens;
        } else {
            $this->map = array();
            foreach ($this->tokens as $token => $value) {
                $this->map[$this->prefix . $token . $this->suffix] = $value;
            }
        }
    }

    /**
     * Process
     *
     * @param  Config $config
     * @return Config
     * @throws Exception\InvalidArgumentException
     */
    public function process(Config $config)
    {
        if ($config->isReadOnly()) {
            throw new Exception\InvalidArgumentException('Cannot process config because it is read-only');
        }

        if ($this->map === null) {
            $this->buildMap();
        }

        /**
         * Walk through config and replace values
         */
        $keys = array_keys($this->map);
        $values = array_values($this->map);
        foreach ($config as $key => $val) {
            if ($val instanceof Config) {
                $this->process($val);
            } else {
                $config->$key = str_replace($keys, $values, $val);
            }
        }

        return $config;
    }

    /**
     * Process a single value
     *
     * @param $value
     * @return mixed
     */
    public function processValue($value)
    {
        if ($this->map === null) {
            $this->buildMap();
        }
        $keys = array_keys($this->map);
        $values = array_values($this->map);

        return str_replace($keys, $values, $value);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Config\Processor;

use Zend\Config\Config;
use Zend\Config\Exception;
use Zend\Filter\FilterInterface as ZendFilter;

class Filter implements ProcessorInterface
{
    /**
     * @var ZendFilter
     */
    protected $filter;

    /**
     * Filter all config values using the supplied Zend\Filter
     *
     * @param ZendFilter $filter
     */
    public function __construct(ZendFilter $filter)
    {
        $this->setFilter($filter);
    }

    /**
     * @param  ZendFilter $filter
     * @return Filter
     */
    public function setFilter(ZendFilter $filter)
    {
        $this->filter = $filter;
        return $this;
    }

    /**
     * @return ZendFilter
     */
    public function getFilter()
    {
        return $this->filter;
    }

    /**
     * Process
     *
     * @param  Config $config
     * @return Config
     * @throws Exception\InvalidArgumentException
     */
    public function process(Config $config)
    {
        if ($config->isReadOnly()) {
            throw new Exception\InvalidArgumentException('Cannot process config because it is read-only');
        }

        /**
         * Walk through config and replace values
         */
        foreach ($config as $key => $val) {
            if ($val instanceof Config) {
                $this->process($val);
            } else {
                $config->$key = $this->filter->filter($val);
            }
        }

        return $config;
    }

    /**
     * Process a single value
     *
     * @param  mixed $value
     * @return mixed
     */
    public function processValue($value)
    {
        return $this->filter->filter($value);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Config\Processor;

use Zend\Config\Config;
use Zend\Config\Exception;
use Zend\Stdlib\PriorityQueue;

class Queue extends PriorityQueue implements ProcessorInterface
{
    /**
     * Process the whole config structure with each parser in the queue.
     *
     * @param  Config $config
     * @return Config
     * @throws Exception\InvalidArgumentException
     */
    public function process(Config $config)
    {
        if ($config->isReadOnly()) {
            throw new Exception\InvalidArgumentException('Cannot process config because it is read-only');
        }

        foreach ($this as $parser) {
            /** @var $parser ProcessorInterface */
            $parser->process($config);
        }
    }

    /**
     * Process a single value
     *
     * @param  mixed $value
     * @return mixed
     */
    public function processValue($value)
    {
        foreach ($this as $parser) {
            /** @var $parser ProcessorInterface */
            $value = $parser->processValue($value);
        }

        return $value;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Config;

use ArrayAccess;
use Countable;
use Iterator;

/**
 * Provides a property based interface to an array.
 * The data are read-only unless $allowModifications is set to true
 * on construction.
 *
 * Implements Countable, Iterator and ArrayAccess
 * to facilitate easy access to the data.
 */
class Config implements Countable, Iterator, ArrayAccess
{
    /**
     * Whether modifications to configuration data are allowed.
     *
     * @var bool
     */
    protected $allowModifications;

    /**
     * Number of elements in configuration data.
     *
     * @var int
     */
    protected $count;

    /**
     * Data within the configuration.
     *
     * @var array
     */
    protected $data = array();

    /**
     * Used when unsetting values during iteration to ensure we do not skip
     * the next element.
     *
     * @var bool
     */
    protected $skipNextIteration;

    /**
     * Constructor.
     *
     * Data is read-only unless $allowModifications is set to true
     * on construction.
     *
     * @param  array   $array
     * @param  bool $allowModifications
     */
    public function __construct(array $array, $allowModifications = false)
    {
        $this->allowModifications = (bool) $allowModifications;

        foreach ($array as $key => $value) {
            if (is_array($value)) {
                $this->data[$key] = new static($value, $this->allowModifications);
            } else {
                $this->data[$key] = $value;
            }

            $this->count++;
        }
    }

    /**
     * Retrieve a value and return $default if there is no element set.
     *
     * @param  string $name
     * @param  mixed  $default
     * @return mixed
     */
    public function get($name, $default = null)
    {
        if (array_key_exists($name, $this->data)) {
            return $this->data[$name];
        }

        return $default;
    }

    /**
     * Magic function so that $obj->value will work.
     *
     * @param  string $name
     * @return mixed
     */
    public function __get($name)
    {
        return $this->get($name);
    }

    /**
     * Set a value in the config.
     *
     * Only allow setting of a property if $allowModifications  was set to true
     * on construction. Otherwise, throw an exception.
     *
     * @param  string $name
     * @param  mixed  $value
     * @return void
     * @throws Exception\RuntimeException
     */
    public function __set($name, $value)
    {
        if ($this->allowModifications) {

            if (is_array($value)) {
                $value = new static($value, true);
            }

            if (null === $name) {
                $this->data[] = $value;
            } else {
                $this->data[$name] = $value;
            }

            $this->count++;
        } else {
            throw new Exception\RuntimeException('Config is read only');
        }
    }

    /**
     * Deep clone of this instance to ensure that nested Zend\Configs are also
     * cloned.
     *
     * @return void
     */
    public function __clone()
    {
        $array = array();

        foreach ($this->data as $key => $value) {
            if ($value instanceof self) {
                $array[$key] = clone $value;
            } else {
                $array[$key] = $value;
            }
        }

        $this->data = $array;
    }

    /**
     * Return an associative array of the stored data.
     *
     * @return array
     */
    public function toArray()
    {
        $array = array();
        $data  = $this->data;

        /** @var self $value */
        foreach ($data as $key => $value) {
            if ($value instanceof self) {
                $array[$key] = $value->toArray();
            } else {
                $array[$key] = $value;
            }
        }

        return $array;
    }

    /**
     * isset() overloading
     *
     * @param  string $name
     * @return bool
     */
    public function __isset($name)
    {
        return isset($this->data[$name]);
    }

    /**
     * unset() overloading
     *
     * @param  string $name
     * @return void
     * @throws Exception\InvalidArgumentException
     */
    public function __unset($name)
    {
        if (!$this->allowModifications) {
            throw new Exception\InvalidArgumentException('Config is read only');
        } elseif (isset($this->data[$name])) {
            unset($this->data[$name]);
            $this->count--;
            $this->skipNextIteration = true;
        }
    }

    /**
     * count(): defined by Countable interface.
     *
     * @see    Countable::count()
     * @return int
     */
    public function count()
    {
        return $this->count;
    }

    /**
     * current(): defined by Iterator interface.
     *
     * @see    Iterator::current()
     * @return mixed
     */
    public function current()
    {
        $this->skipNextIteration = false;
        return current($this->data);
    }

    /**
     * key(): defined by Iterator interface.
     *
     * @see    Iterator::key()
     * @return mixed
     */
    public function key()
    {
        return key($this->data);
    }

    /**
     * next(): defined by Iterator interface.
     *
     * @see    Iterator::next()
     * @return void
     */
    public function next()
    {
        if ($this->skipNextIteration) {
            $this->skipNextIteration = false;
            return;
        }

        next($this->data);
    }

    /**
     * rewind(): defined by Iterator interface.
     *
     * @see    Iterator::rewind()
     * @return void
     */
    public function rewind()
    {
        $this->skipNextIteration = false;
        reset($this->data);
    }

    /**
     * valid(): defined by Iterator interface.
     *
     * @see    Iterator::valid()
     * @return bool
     */
    public function valid()
    {
        return ($this->key() !== null);
    }

    /**
     * offsetExists(): defined by ArrayAccess interface.
     *
     * @see    ArrayAccess::offsetExists()
     * @param  mixed $offset
     * @return bool
     */
    public function offsetExists($offset)
    {
        return $this->__isset($offset);
    }

    /**
     * offsetGet(): defined by ArrayAccess interface.
     *
     * @see    ArrayAccess::offsetGet()
     * @param  mixed $offset
     * @return mixed
     */
    public function offsetGet($offset)
    {
        return $this->__get($offset);
    }

    /**
     * offsetSet(): defined by ArrayAccess interface.
     *
     * @see    ArrayAccess::offsetSet()
     * @param  mixed $offset
     * @param  mixed $value
     * @return void
     */
    public function offsetSet($offset, $value)
    {
        $this->__set($offset, $value);
    }

    /**
     * offsetUnset(): defined by ArrayAccess interface.
     *
     * @see    ArrayAccess::offsetUnset()
     * @param  mixed $offset
     * @return void
     */
    public function offsetUnset($offset)
    {
        $this->__unset($offset);
    }

    /**
     * Merge another Config with this one.
     *
     * For duplicate keys, the following will be performed:
     * - Nested Configs will be recursively merged.
     * - Items in $merge with INTEGER keys will be appended.
     * - Items in $merge with STRING keys will overwrite current values.
     *
     * @param  Config $merge
     * @return Config
     */
    public function merge(Config $merge)
    {
        /** @var Config $value */
        foreach ($merge as $key => $value) {
            if (array_key_exists($key, $this->data)) {
                if (is_int($key)) {
                    $this->data[] = $value;
                } elseif ($value instanceof self && $this->data[$key] instanceof self) {
                    $this->data[$key]->merge($value);
                } else {
                    if ($value instanceof self) {
                        $this->data[$key] = new static($value->toArray(), $this->allowModifications);
                    } else {
                        $this->data[$key] = $value;
                    }
                }
            } else {
                if ($value instanceof self) {
                    $this->data[$key] = new static($value->toArray(), $this->allowModifications);
                } else {
                    $this->data[$key] = $value;
                }

                $this->count++;
            }
        }

        return $this;
    }

    /**
     * Prevent any more modifications being made to this instance.
     *
     * Useful after merge() has been used to merge multiple Config objects
     * into one object which should then not be modified again.
     *
     * @return void
     */
    public function setReadOnly()
    {
        $this->allowModifications = false;

        /** @var Config $value */
        foreach ($this->data as $value) {
            if ($value instanceof self) {
                $value->setReadOnly();
            }
        }
    }

    /**
     * Returns whether this Config object is read only or not.
     *
     * @return bool
     */
    public function isReadOnly()
    {
        return !$this->allowModifications;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Config;

use Zend\Stdlib\ArrayUtils;

class Factory
{
    /**
     * Plugin manager for loading readers
     *
     * @var null|ReaderPluginManager
     */
    public static $readers = null;

    /**
     * Plugin manager for loading writers
     *
     * @var null|WriterPluginManager
     */
    public static $writers = null;

    /**
     * Registered config file extensions.
     * key is extension, value is reader instance or plugin name
     *
     * @var array
     */
    protected static $extensions = array(
        'ini'  => 'ini',
        'json' => 'json',
        'xml'  => 'xml',
        'yaml' => 'yaml',
    );

    /**
     * Register config file extensions for writing
     * key is extension, value is writer instance or plugin name
     *
     * @var array
     */
    protected static $writerExtensions = array(
        'php'  => 'php',
        'ini'  => 'ini',
        'json' => 'json',
        'xml'  => 'xml',
        'yaml' => 'yaml',
    );

    /**
     * Read a config from a file.
     *
     * @param  string  $filename
     * @param  bool $returnConfigObject
     * @return array|Config
     * @throws Exception\InvalidArgumentException
     * @throws Exception\RuntimeException
     */
    public static function fromFile($filename, $returnConfigObject = false)
    {
        $pathinfo = pathinfo($filename);

        if (!isset($pathinfo['extension'])) {
            throw new Exception\RuntimeException(sprintf(
                'Filename "%s" is missing an extension and cannot be auto-detected',
                $filename
            ));
        }

        $extension = strtolower($pathinfo['extension']);

        if ($extension === 'php') {
            if (!is_file($filename) || !is_readable($filename)) {
                throw new Exception\RuntimeException(sprintf(
                    "File '%s' doesn't exist or not readable",
                    $filename
                ));
            }

            $config = include $filename;
        } elseif (isset(static::$extensions[$extension])) {
            $reader = static::$extensions[$extension];
            if (!$reader instanceof Reader\ReaderInterface) {
                $reader = static::getReaderPluginManager()->get($reader);
                static::$extensions[$extension] = $reader;
            }

            /** @var Reader\ReaderInterface $reader  */
            $config = $reader->fromFile($filename);
        } else {
            throw new Exception\RuntimeException(sprintf(
                'Unsupported config file extension: .%s',
                $pathinfo['extension']
            ));
        }

        return ($returnConfigObject) ? new Config($config) : $config;
    }

    /**
     * Read configuration from multiple files and merge them.
     *
     * @param  array   $files
     * @param  bool $returnConfigObject
     * @return array|Config
     */
    public static function fromFiles(array $files, $returnConfigObject = false)
    {
        $config = array();

        foreach ($files as $file) {
            $config = ArrayUtils::merge($config, static::fromFile($file));
        }

        return ($returnConfigObject) ? new Config($config) : $config;
    }

    /**
     * Writes a config to a file
     *
     * @param string $filename
     * @param array|Config $config
     * @return bool TRUE on success | FALSE on failure
     * @throws Exception\RuntimeException
     * @throws Exception\InvalidArgumentException
     */
    public static function toFile($filename, $config)
    {
        if (
            (is_object($config) && !($config instanceOf Config)) ||
            (!is_object($config) && !is_array($config))
        ) {
            throw new Exception\InvalidArgumentException(
                __METHOD__." \$config should be an array or instance of Zend\\Config\\Config"
            );
        }

        $extension = substr(strrchr($filename, '.'), 1);
        $directory = dirname($filename);

        if (!is_dir($directory)) {
            throw new Exception\RuntimeException(
                "Directory '{$directory}' does not exists!"
            );
        }

        if (!is_writable($directory)) {
            throw new Exception\RuntimeException(
                "Cannot write in directory '{$directory}'"
            );
        }

        if (!isset(static::$writerExtensions[$extension])) {
            throw new Exception\RuntimeException(
                "Unsupported config file extension: '.{$extension}' for writing."
            );
        }

        $writer = static::$writerExtensions[$extension];
        if (($writer instanceOf Writer\AbstractWriter) === false) {
            $writer = self::getWriterPluginManager()->get($writer);
            static::$writerExtensions[$extension] = $writer;
        }

        if (is_object($config)) {
            $config = $config->toArray();
        }

        $content = $writer->processConfig($config);

        return (bool) (file_put_contents($filename, $content) !== false);
    }

    /**
     * Set reader plugin manager
     *
     * @param ReaderPluginManager $readers
     * @return void
     */
    public static function setReaderPluginManager(ReaderPluginManager $readers)
    {
        static::$readers = $readers;
    }

    /**
     * Get the reader plugin manager
     *
     * @return ReaderPluginManager
     */
    public static function getReaderPluginManager()
    {
        if (static::$readers === null) {
            static::$readers = new ReaderPluginManager();
        }
        return static::$readers;
    }

    /**
     * Set writer plugin manager
     *
     * @param WriterPluginManager $writers
     * @return void
     */
    public static function setWriterPluginManager(WriterPluginManager $writers)
    {
        static::$writers = $writers;
    }

    /**
     * Get the writer plugin manager
     *
     * @return WriterPluginManager
     */
    public static function getWriterPluginManager()
    {
        if (static::$writers === null) {
            static::$writers = new WriterPluginManager();
        }

        return static::$writers;
    }

    /**
     * Set config reader for file extension
     *
     * @param  string $extension
     * @param  string|Reader\ReaderInterface $reader
     * @throws Exception\InvalidArgumentException
     * @return void
     */
    public static function registerReader($extension, $reader)
    {
        $extension = strtolower($extension);

        if (!is_string($reader) && !$reader instanceof Reader\ReaderInterface) {
            throw new Exception\InvalidArgumentException(sprintf(
                'Reader should be plugin name, class name or ' .
                'instance of %s\Reader\ReaderInterface; received "%s"',
                __NAMESPACE__,
                (is_object($reader) ? get_class($reader) : gettype($reader))
            ));
        }

        static::$extensions[$extension] = $reader;
    }

    /**
     * Set config writer for file extension
     *
     * @param string $extension
     * @param string|Writer\AbstractWriter $writer
     * @throws Exception\InvalidArgumentException
     * @return void
     */
    public static function registerWriter($extension, $writer)
    {
        $extension = strtolower($extension);

        if (!is_string($writer) && !$writer instanceof Writer\AbstractWriter) {
            throw new Exception\InvalidArgumentException(sprintf(
                'Writer should be plugin name, class name or ' .
                'instance of %s\Writer\AbstractWriter; received "%s"',
                __NAMESPACE__,
                (is_object($writer) ? get_class($writer) : gettype($writer))
            ));
        }

        static::$writerExtensions[$extension] = $writer;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Config;

use Zend\ServiceManager\AbstractPluginManager;

class ReaderPluginManager extends AbstractPluginManager
{
    /**
     * Default set of readers
     *
     * @var array
     */
    protected $invokableClasses = array(
        'ini'  => 'Zend\Config\Reader\Ini',
        'json' => 'Zend\Config\Reader\Json',
        'xml'  => 'Zend\Config\Reader\Xml',
        'yaml' => 'Zend\Config\Reader\Yaml',
    );

    /**
     * Validate the plugin
     * Checks that the reader loaded is an instance of Reader\ReaderInterface.
     *
     * @param  Reader\ReaderInterface $plugin
     * @return void
     * @throws Exception\InvalidArgumentException if invalid
     */
    public function validatePlugin($plugin)
    {
        if ($plugin instanceof Reader\ReaderInterface) {
            // we're okay
            return;
        }

        throw new Exception\InvalidArgumentException(sprintf(
            'Plugin of type %s is invalid; must implement %s\Reader\ReaderInterface',
            (is_object($plugin) ? get_class($plugin) : gettype($plugin)),
            __NAMESPACE__
        ));
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Config\Exception;

class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Config\Exception;

class RuntimeException extends \RuntimeException implements ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Config\Exception;

interface ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Config\Writer;

interface WriterInterface
{
    /**
     * Write a config object to a file.
     *
     * @param  string  $filename
     * @param  mixed   $config
     * @param  bool $exclusiveLock
     * @return void
     */
    public function toFile($filename, $config, $exclusiveLock = true);

    /**
     * Write a config object to a string.
     *
     * @param  mixed $config
     * @return string
     */
    public function toString($config);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Config\Writer;

use Zend\Config\Exception;

class Yaml extends AbstractWriter
{
    /**
     * YAML encoder callback
     *
     * @var callable
     */
    protected $yamlEncoder;

    /**
     * Constructor
     *
     * @param callable|string|null $yamlEncoder
     */
    public function __construct($yamlEncoder = null)
    {
        if ($yamlEncoder !== null) {
            $this->setYamlEncoder($yamlEncoder);
        } else {
            if (function_exists('yaml_emit')) {
                $this->setYamlEncoder('yaml_emit');
            }
        }
    }

    /**
     * Get callback for decoding YAML
     *
     * @return callable
     */
    public function getYamlEncoder()
    {
        return $this->yamlEncoder;
    }

    /**
     * Set callback for decoding YAML
     *
     * @param  callable $yamlEncoder the decoder to set
     * @return Yaml
     * @throws Exception\InvalidArgumentException
     */
    public function setYamlEncoder($yamlEncoder)
    {
        if (!is_callable($yamlEncoder)) {
            throw new Exception\InvalidArgumentException('Invalid parameter to setYamlEncoder() - must be callable');
        }
        $this->yamlEncoder = $yamlEncoder;
        return $this;
    }

    /**
     * processConfig(): defined by AbstractWriter.
     *
     * @param  array $config
     * @return string
     * @throws Exception\RuntimeException
     */
    public function processConfig(array $config)
    {
        if (null === $this->getYamlEncoder()) {
             throw new Exception\RuntimeException("You didn't specify a Yaml callback encoder");
        }

        $config = call_user_func($this->getYamlEncoder(), $config);
        if (null === $config) {
            throw new Exception\RuntimeException("Error generating YAML data");
        }

        return $config;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Config\Writer;

use Zend\Config\Exception;

class Ini extends AbstractWriter
{
    /**
     * Separator for nesting levels of configuration data identifiers.
     *
     * @var string
     */
    protected $nestSeparator = '.';

    /**
     * If true the INI string is rendered in the global namespace without
     * sections.
     *
     * @var bool
     */
    protected $renderWithoutSections = false;

    /**
     * Set nest separator.
     *
     * @param  string $separator
     * @return self
     */
    public function setNestSeparator($separator)
    {
        $this->nestSeparator = $separator;
        return $this;
    }

    /**
     * Get nest separator.
     *
     * @return string
     */
    public function getNestSeparator()
    {
        return $this->nestSeparator;
    }

    /**
     * Set if rendering should occur without sections or not.
     *
     * If set to true, the INI file is rendered without sections completely
     * into the global namespace of the INI file.
     *
     * @param  bool $withoutSections
     * @return Ini
     */
    public function setRenderWithoutSectionsFlags($withoutSections)
    {
        $this->renderWithoutSections = (bool) $withoutSections;
        return $this;
    }

    /**
     * Return whether the writer should render without sections.
     *
     * @return bool
     */
    public function shouldRenderWithoutSections()
    {
        return $this->renderWithoutSections;
    }

    /**
     * processConfig(): defined by AbstractWriter.
     *
     * @param  array $config
     * @return string
     */
    public function processConfig(array $config)
    {
        $iniString = '';

        if ($this->shouldRenderWithoutSections()) {
            $iniString .= $this->addBranch($config);
        } else {
            $config = $this->sortRootElements($config);

            foreach ($config as $sectionName => $data) {
                if (!is_array($data)) {
                    $iniString .= $sectionName
                               .  ' = '
                               .  $this->prepareValue($data)
                               .  "\n";
                } else {
                    $iniString .= '[' . $sectionName . ']' . "\n"
                               .  $this->addBranch($data)
                               .  "\n";
                }
            }
        }

        return $iniString;
    }

    /**
     * Add a branch to an INI string recursively.
     *
     * @param  array $config
     * @param  array $parents
     * @return string
     */
    protected function addBranch(array $config, $parents = array())
    {
        $iniString = '';

        foreach ($config as $key => $value) {
            $group = array_merge($parents, array($key));

            if (is_array($value)) {
                $iniString .= $this->addBranch($value, $group);
            } else {
                $iniString .= implode($this->nestSeparator, $group)
                           .  ' = '
                           .  $this->prepareValue($value)
                           .  "\n";
            }
        }

        return $iniString;
    }

    /**
     * Prepare a value for INI.
     *
     * @param  mixed $value
     * @return string
     * @throws Exception\RuntimeException
     */
    protected function prepareValue($value)
    {
        if (is_int($value) || is_float($value)) {
            return $value;
        } elseif (is_bool($value)) {
            return ($value ? 'true' : 'false');
        } elseif (false === strpos($value, '"')) {
            return '"' . $value .  '"';
        } else {
            throw new Exception\RuntimeException('Value can not contain double quotes');
        }
    }

    /**
     * Root elements that are not assigned to any section needs to be on the
     * top of config.
     *
     * @param  array $config
     * @return array
     */
    protected function sortRootElements(array $config)
    {
        $sections = array();

        // Remove sections from config array.
        foreach ($config as $key => $value) {
            if (is_array($value)) {
                $sections[$key] = $value;
                unset($config[$key]);
            }
        }

        // Read sections to the end.
        foreach ($sections as $key => $value) {
            $config[$key] = $value;
        }

        return $config;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Config\Writer;

use Traversable;
use Zend\Config\Exception;
use Zend\Stdlib\ArrayUtils;

abstract class AbstractWriter implements WriterInterface
{
    /**
     * toFile(): defined by Writer interface.
     *
     * @see    WriterInterface::toFile()
     * @param  string  $filename
     * @param  mixed   $config
     * @param  bool $exclusiveLock
     * @return void
     * @throws Exception\InvalidArgumentException
     * @throws Exception\RuntimeException
     */
    public function toFile($filename, $config, $exclusiveLock = true)
    {
        if (empty($filename)) {
            throw new Exception\InvalidArgumentException('No file name specified');
        }

        $flags = 0;
        if ($exclusiveLock) {
            $flags |= LOCK_EX;
        }

        set_error_handler(
            function ($error, $message = '', $file = '', $line = 0) use ($filename) {
                throw new Exception\RuntimeException(sprintf(
                    'Error writing to "%s": %s',
                    $filename, $message
                ), $error);
            }, E_WARNING
        );

        try {
            file_put_contents($filename, $this->toString($config), $flags);
        } catch (\Exception $e) {
            restore_error_handler();
            throw $e;
        }

        restore_error_handler();
    }

    /**
     * toString(): defined by Writer interface.
     *
     * @see    WriterInterface::toString()
     * @param  mixed   $config
     * @return string
     * @throws Exception\InvalidArgumentException
     */
    public function toString($config)
    {
        if ($config instanceof Traversable) {
            $config = ArrayUtils::iteratorToArray($config);
        } elseif (!is_array($config)) {
            throw new Exception\InvalidArgumentException(__METHOD__ . ' expects an array or Traversable config');
        }

        return $this->processConfig($config);
    }

    /**
     * @param array $config
     * @return string
     */
    abstract protected function processConfig(array $config);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Config\Writer;

class PhpArray extends AbstractWriter
{
    /**
     * processConfig(): defined by AbstractWriter.
     *
     * @param  array $config
     * @return string
     */
    public function processConfig(array $config)
    {
        $arrayString = "<?php\n"
                     . "return " . var_export($config, true) . ";\n";

        return $arrayString;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Config\Writer;

use Zend\Json\Json as JsonFormat;

class Json extends AbstractWriter
{
    /**
     * processConfig(): defined by AbstractWriter.
     *
     * @param  array $config
     * @return string
     */
    public function processConfig(array $config)
    {
        return JsonFormat::encode($config);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Config\Writer;

use XMLWriter;
use Zend\Config\Exception;

class Xml extends AbstractWriter
{
    /**
     * processConfig(): defined by AbstractWriter.
     *
     * @param  array $config
     * @return string
     */
    public function processConfig(array $config)
    {
        $writer = new XMLWriter('UTF-8');
        $writer->openMemory();
        $writer->setIndent(true);
        $writer->setIndentString(str_repeat(' ', 4));

        $writer->startDocument('1.0', 'UTF-8');
        $writer->startElement('zend-config');

        foreach ($config as $sectionName => $data) {
            if (!is_array($data)) {
                $writer->writeElement($sectionName, (string) $data);
            } else {
                $this->addBranch($sectionName, $data, $writer);
            }
        }

        $writer->endElement();
        $writer->endDocument();

        return $writer->outputMemory();
    }

    /**
     * Add a branch to an XML object recursively.
     *
     * @param  string    $branchName
     * @param  array     $config
     * @param  XMLWriter $writer
     * @return void
     * @throws Exception\RuntimeException
     */
    protected function addBranch($branchName, array $config, XMLWriter $writer)
    {
        $branchType = null;

        foreach ($config as $key => $value) {
            if ($branchType === null) {
                if (is_numeric($key)) {
                    $branchType = 'numeric';
                } else {
                    $writer->startElement($branchName);
                    $branchType = 'string';
                }
            } elseif ($branchType !== (is_numeric($key) ? 'numeric' : 'string')) {
                throw new Exception\RuntimeException('Mixing of string and numeric keys is not allowed');
            }

            if ($branchType === 'numeric') {
                if (is_array($value)) {
                    $this->addBranch($value, $value, $writer);
                } else {
                    $writer->writeElement($branchName, (string) $value);
                }
            } else {
                if (is_array($value)) {
                    $this->addBranch($key, $value, $writer);
                } else {
                    $writer->writeElement($key, (string) $value);
                }
            }
        }

        if ($branchType === 'string') {
            $writer->endElement();
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Config\Reader;

use Zend\Config\Exception;

/**
 * YAML config reader.
 */
class Yaml implements ReaderInterface
{
    /**
     * Directory of the YAML file
     *
     * @var string
     */
    protected $directory;

    /**
     * YAML decoder callback
     *
     * @var callable
     */
    protected $yamlDecoder;

    /**
     * Constructor
     *
     * @param callable $yamlDecoder
     */
    public function __construct($yamlDecoder = null)
    {
        if ($yamlDecoder !== null) {
            $this->setYamlDecoder($yamlDecoder);
        } else {
            if (function_exists('yaml_parse')) {
                $this->setYamlDecoder('yaml_parse');
            }
        }
    }

    /**
     * Set callback for decoding YAML
     *
     * @param  string|callable $yamlDecoder the decoder to set
     * @return Yaml
     * @throws Exception\RuntimeException
     */
    public function setYamlDecoder($yamlDecoder)
    {
        if (!is_callable($yamlDecoder)) {
            throw new Exception\RuntimeException(
                'Invalid parameter to setYamlDecoder() - must be callable'
            );
        }
        $this->yamlDecoder = $yamlDecoder;
        return $this;
    }

    /**
     * Get callback for decoding YAML
     *
     * @return callable
     */
    public function getYamlDecoder()
    {
        return $this->yamlDecoder;
    }

    /**
     * fromFile(): defined by Reader interface.
     *
     * @see    ReaderInterface::fromFile()
     * @param  string $filename
     * @return array
     * @throws Exception\RuntimeException
     */
    public function fromFile($filename)
    {
        if (!is_file($filename) || !is_readable($filename)) {
            throw new Exception\RuntimeException(sprintf(
                "File '%s' doesn't exist or not readable",
                $filename
            ));
        }

        if (null === $this->getYamlDecoder()) {
             throw new Exception\RuntimeException("You didn't specify a Yaml callback decoder");
        }

        $this->directory = dirname($filename);

        $config = call_user_func($this->getYamlDecoder(), file_get_contents($filename));
        if (null === $config) {
            throw new Exception\RuntimeException("Error parsing YAML data");
        }

        return $this->process($config);
    }

    /**
     * fromString(): defined by Reader interface.
     *
     * @see    ReaderInterface::fromString()
     * @param  string $string
     * @return array|bool
     * @throws Exception\RuntimeException
     */
    public function fromString($string)
    {
        if (null === $this->getYamlDecoder()) {
             throw new Exception\RuntimeException("You didn't specify a Yaml callback decoder");
        }
        if (empty($string)) {
            return array();
        }

        $this->directory = null;

        $config = call_user_func($this->getYamlDecoder(), $string);
        if (null === $config) {
            throw new Exception\RuntimeException("Error parsing YAML data");
        }

        return $this->process($config);
    }

    /**
     * Process the array for @include
     *
     * @param  array $data
     * @return array
     * @throws Exception\RuntimeException
     */
    protected function process(array $data)
    {
        foreach ($data as $key => $value) {
            if (is_array($value)) {
                $data[$key] = $this->process($value);
            }
            if (trim($key) === '@include') {
                if ($this->directory === null) {
                    throw new Exception\RuntimeException('Cannot process @include statement for a json string');
                }
                $reader = clone $this;
                unset($data[$key]);
                $data = array_replace_recursive($data, $reader->fromFile($this->directory . '/' . $value));
            }
        }
        return $data;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Config\Reader;

use Zend\Config\Exception;

/**
 * INI config reader.
 */
class Ini implements ReaderInterface
{
    /**
     * Separator for nesting levels of configuration data identifiers.
     *
     * @var string
     */
    protected $nestSeparator = '.';

    /**
     * Directory of the file to process.
     *
     * @var string
     */
    protected $directory;

    /**
     * Set nest separator.
     *
     * @param  string $separator
     * @return self
     */
    public function setNestSeparator($separator)
    {
        $this->nestSeparator = $separator;
        return $this;
    }

    /**
     * Get nest separator.
     *
     * @return string
     */
    public function getNestSeparator()
    {
        return $this->nestSeparator;
    }

    /**
     * fromFile(): defined by Reader interface.
     *
     * @see    ReaderInterface::fromFile()
     * @param  string $filename
     * @return array
     * @throws Exception\RuntimeException
     */
    public function fromFile($filename)
    {
        if (!is_file($filename) || !is_readable($filename)) {
            throw new Exception\RuntimeException(sprintf(
                "File '%s' doesn't exist or not readable",
                $filename
            ));
        }

        $this->directory = dirname($filename);

        set_error_handler(
            function ($error, $message = '', $file = '', $line = 0) use ($filename) {
                throw new Exception\RuntimeException(sprintf(
                    'Error reading INI file "%s": %s',
                    $filename, $message
                ), $error);
            }, E_WARNING
        );
        $ini = parse_ini_file($filename, true);
        restore_error_handler();

        return $this->process($ini);
    }

    /**
     * fromString(): defined by Reader interface.
     *
     * @param  string $string
     * @return array|bool
     * @throws Exception\RuntimeException
     */
    public function fromString($string)
    {
        if (empty($string)) {
            return array();
        }
        $this->directory = null;

        set_error_handler(
            function ($error, $message = '', $file = '', $line = 0) {
                throw new Exception\RuntimeException(sprintf(
                    'Error reading INI string: %s',
                    $message
                ), $error);
            }, E_WARNING
        );
        $ini = parse_ini_string($string, true);
        restore_error_handler();

        return $this->process($ini);
    }

    /**
     * Process data from the parsed ini file.
     *
     * @param  array $data
     * @return array
     */
    protected function process(array $data)
    {
        $config = array();

        foreach ($data as $section => $value) {
            if (is_array($value)) {
                if (strpos($section, $this->nestSeparator) !== false) {
                    $sections = explode($this->nestSeparator, $section);
                    $config = array_merge_recursive($config, $this->buildNestedSection($sections, $value));
                } else {
                    $config[$section] = $this->processSection($value);
                }
            } else {
                $this->processKey($section, $value, $config);
            }
        }

        return $config;
    }

    /**
     * Process a nested section
     *
     * @param array $sections
     * @param mixed $value
     * @return array
     */
    private function buildNestedSection($sections, $value)
    {
        if (count($sections) == 0) {
            return $this->processSection($value);
        }

        $nestedSection = array();

        $first = array_shift($sections);
        $nestedSection[$first] = $this->buildNestedSection($sections, $value);

        return $nestedSection;
    }

    /**
     * Process a section.
     *
     * @param  array $section
     * @return array
     */
    protected function processSection(array $section)
    {
        $config = array();

        foreach ($section as $key => $value) {
            $this->processKey($key, $value, $config);
        }

        return $config;
    }

    /**
     * Process a key.
     *
     * @param  string $key
     * @param  string $value
     * @param  array  $config
     * @return array
     * @throws Exception\RuntimeException
     */
    protected function processKey($key, $value, array &$config)
    {
        if (strpos($key, $this->nestSeparator) !== false) {
            $pieces = explode($this->nestSeparator, $key, 2);

            if (!strlen($pieces[0]) || !strlen($pieces[1])) {
                throw new Exception\RuntimeException(sprintf('Invalid key "%s"', $key));
            } elseif (!isset($config[$pieces[0]])) {
                if ($pieces[0] === '0' && !empty($config)) {
                    $config = array($pieces[0] => $config);
                } else {
                    $config[$pieces[0]] = array();
                }
            } elseif (!is_array($config[$pieces[0]])) {
                throw new Exception\RuntimeException(sprintf(
                    'Cannot create sub-key for "%s", as key already exists', $pieces[0]
                ));
            }

            $this->processKey($pieces[1], $value, $config[$pieces[0]]);
        } else {
            if ($key === '@include') {
                if ($this->directory === null) {
                    throw new Exception\RuntimeException('Cannot process @include statement for a string config');
                }

                $reader  = clone $this;
                $include = $reader->fromFile($this->directory . '/' . $value);
                $config  = array_replace_recursive($config, $include);
            } else {
                $config[$key] = $value;
            }
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Config\Reader;

interface ReaderInterface
{
    /**
     * Read from a file and create an array
     *
     * @param  string $filename
     * @return array
     */
    public function fromFile($filename);

    /**
     * Read from a string and create an array
     *
     * @param  string $string
     * @return array|bool
     */
    public function fromString($string);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Config\Reader;

use Zend\Config\Exception;
use Zend\Json\Exception as JsonException;
use Zend\Json\Json as JsonFormat;

/**
 * JSON config reader.
 */
class Json implements ReaderInterface
{
    /**
     * Directory of the JSON file
     *
     * @var string
     */
    protected $directory;

    /**
     * fromFile(): defined by Reader interface.
     *
     * @see    ReaderInterface::fromFile()
     * @param  string $filename
     * @return array
     * @throws Exception\RuntimeException
     */
    public function fromFile($filename)
    {
        if (!is_file($filename) || !is_readable($filename)) {
            throw new Exception\RuntimeException(sprintf(
                "File '%s' doesn't exist or not readable",
                $filename
            ));
        }

        $this->directory = dirname($filename);

        try {
            $config = JsonFormat::decode(file_get_contents($filename), JsonFormat::TYPE_ARRAY);
        } catch (JsonException\RuntimeException $e) {
            throw new Exception\RuntimeException($e->getMessage());
        }

        return $this->process($config);
    }

    /**
     * fromString(): defined by Reader interface.
     *
     * @see    ReaderInterface::fromString()
     * @param  string $string
     * @return array|bool
     * @throws Exception\RuntimeException
     */
    public function fromString($string)
    {
        if (empty($string)) {
            return array();
        }

        $this->directory = null;

        try {
            $config = JsonFormat::decode($string, JsonFormat::TYPE_ARRAY);
        } catch (JsonException\RuntimeException $e) {
            throw new Exception\RuntimeException($e->getMessage());
        }

        return $this->process($config);
    }

    /**
     * Process the array for @include
     *
     * @param  array $data
     * @return array
     * @throws Exception\RuntimeException
     */
    protected function process(array $data)
    {
        foreach ($data as $key => $value) {
            if (is_array($value)) {
                $data[$key] = $this->process($value);
            }
            if (trim($key) === '@include') {
                if ($this->directory === null) {
                    throw new Exception\RuntimeException('Cannot process @include statement for a JSON string');
                }
                $reader = clone $this;
                unset($data[$key]);
                $data = array_replace_recursive($data, $reader->fromFile($this->directory . '/' . $value));
            }
        }
        return $data;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Config\Reader;

use XMLReader;
use Zend\Config\Exception;

/**
 * XML config reader.
 */
class Xml implements ReaderInterface
{
    /**
     * XML Reader instance.
     *
     * @var XMLReader
     */
    protected $reader;

    /**
     * Directory of the file to process.
     *
     * @var string
     */
    protected $directory;

    /**
     * Nodes to handle as plain text.
     *
     * @var array
     */
    protected $textNodes = array(
        XMLReader::TEXT,
        XMLReader::CDATA,
        XMLReader::WHITESPACE,
        XMLReader::SIGNIFICANT_WHITESPACE
    );

    /**
     * fromFile(): defined by Reader interface.
     *
     * @see    ReaderInterface::fromFile()
     * @param  string $filename
     * @return array
     * @throws Exception\RuntimeException
     */
    public function fromFile($filename)
    {
        if (!is_file($filename) || !is_readable($filename)) {
            throw new Exception\RuntimeException(sprintf(
                "File '%s' doesn't exist or not readable",
                $filename
            ));
        }

        $this->reader = new XMLReader();
        $this->reader->open($filename, null, LIBXML_XINCLUDE);

        $this->directory = dirname($filename);

        set_error_handler(
            function ($error, $message = '', $file = '', $line = 0) use ($filename) {
                throw new Exception\RuntimeException(sprintf(
                    'Error reading XML file "%s": %s',
                    $filename, $message
                ), $error);
            }, E_WARNING
        );
        $return = $this->process();
        restore_error_handler();

        return $return;
    }

    /**
     * fromString(): defined by Reader interface.
     *
     * @see    ReaderInterface::fromString()
     * @param  string $string
     * @return array|bool
     * @throws Exception\RuntimeException
     */
    public function fromString($string)
    {
        if (empty($string)) {
            return array();
        }
        $this->reader = new XMLReader();

        $this->reader->xml($string, null, LIBXML_XINCLUDE);

        $this->directory = null;

        set_error_handler(
            function ($error, $message = '', $file = '', $line = 0) {
                throw new Exception\RuntimeException(sprintf(
                    'Error reading XML string: %s',
                    $message
                ), $error);
            }, E_WARNING
        );
        $return = $this->process();
        restore_error_handler();

        return $return;
    }

    /**
     * Process data from the created XMLReader.
     *
     * @return array
     */
    protected function process()
    {
        return $this->processNextElement();
    }

    /**
     * Process the next inner element.
     *
     * @return mixed
     */
    protected function processNextElement()
    {
        $children = array();
        $text     = '';

        while ($this->reader->read()) {
            if ($this->reader->nodeType === XMLReader::ELEMENT) {
                if ($this->reader->depth === 0) {
                    return $this->processNextElement();
                }

                $attributes = $this->getAttributes();
                $name       = $this->reader->name;

                if ($this->reader->isEmptyElement) {
                    $child = array();
                } else {
                    $child = $this->processNextElement();
                }

                if ($attributes) {
                    if (!is_array($child)) {
                        $child = array();
                    }

                    $child = array_merge($child, $attributes);
                }

                if (isset($children[$name])) {
                    if (!is_array($children[$name]) || !array_key_exists(0, $children[$name])) {
                        $children[$name] = array($children[$name]);
                    }

                    $children[$name][] = $child;
                } else {
                    $children[$name] = $child;
                }
            } elseif ($this->reader->nodeType === XMLReader::END_ELEMENT) {
                break;
            } elseif (in_array($this->reader->nodeType, $this->textNodes)) {
                $text .= $this->reader->value;
            }
        }

        return $children ?: $text;
    }

    /**
     * Get all attributes on the current node.
     *
     * @return array
     */
    protected function getAttributes()
    {
        $attributes = array();

        if ($this->reader->hasAttributes) {
            while ($this->reader->moveToNextAttribute()) {
                $attributes[$this->reader->localName] = $this->reader->value;
            }

            $this->reader->moveToElement();
        }

        return $attributes;
    }
}
{
    "name": "zendframework/zend-servicemanager",
    "description": " ",
    "license": "BSD-3-Clause",
    "keywords": [
        "zf2",
        "servicemanager"
    ],
    "autoload": {
        "psr-0": {
            "Zend\\ServiceManager\\": ""
        }
    },
    "target-dir": "Zend/ServiceManager",
    "require": {
        "php": ">=5.3.3"
    },
    "suggest": {
        "zendframework/zend-di": "Zend\\Di component"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "2.2-dev",
            "dev-develop": "2.3-dev"
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager;

use Zend\ServiceManager\ServiceLocatorInterface;

trait ServiceLocatorAwareTrait
{
    /**
     * @var ServiceLocatorInterface
     */
    protected $serviceLocator = null;

    /**
     * Set service locator
     *
     * @param ServiceLocatorInterface $serviceLocator
     * @return mixed
     */
    public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
    {
        $this->serviceLocator = $serviceLocator;

        return $this;
    }

    /**
     * Get service locator
     *
     * @return ServiceLocatorInterface
     */
    public function getServiceLocator()
    {
        return $this->serviceLocator;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager;

interface MutableCreationOptionsInterface
{
    /**
     * Set creation options
     *
     * @param  array $options
     * @return void
     */
    public function setCreationOptions(array $options);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager;

use ReflectionClass;

class ServiceManager implements ServiceLocatorInterface
{

    /**@#+
     * Constants
     */
    const SCOPE_PARENT = 'parent';
    const SCOPE_CHILD = 'child';
    /**@#-*/

    /**
     * Lookup for canonicalized names.
     *
     * @var array
     */
    protected $canonicalNames = array();

    /**
     * @var bool
     */
    protected $allowOverride = false;

    /**
     * @var array
     */
    protected $invokableClasses = array();

    /**
     * @var string|callable|\Closure|FactoryInterface[]
     */
    protected $factories = array();

    /**
     * @var AbstractFactoryInterface[]
     */
    protected $abstractFactories = array();

    /**
     * @var array[]
     */
    protected $delegators = array();

    /**
     * @var array
     */
    protected $pendingAbstractFactoryRequests = array();

    /**
     * @var string
     */
    protected $lastAbstractFactoryUsed = null;

    /**
     * @var string
     */
    protected $lastCanonicalNameUsed   = null;

    /**
     * @var array
     */
    protected $shared = array();

    /**
     * Registered services and cached values
     *
     * @var array
     */
    protected $instances = array();

    /**
     * @var array
     */
    protected $aliases = array();

    /**
     * @var array
     */
    protected $initializers = array();

    /**
     * @var ServiceManager[]
     */
    protected $peeringServiceManagers = array();

    /**
     * Whether or not to share by default
     *
     * @var bool
     */
    protected $shareByDefault = true;

    /**
     * @var bool
     */
    protected $retrieveFromPeeringManagerFirst = false;

    /**
     * @var bool Track whether not to throw exceptions during create()
     */
    protected $throwExceptionInCreate = true;

    /**
     * @var array map of characters to be replaced through strtr
     */
    protected $canonicalNamesReplacements = array('-' => '', '_' => '', ' ' => '', '\\' => '', '/' => '');

    /**
     * Constructor
     *
     * @param ConfigInterface $config
     */
    public function __construct(ConfigInterface $config = null)
    {
        if ($config) {
            $config->configureServiceManager($this);
        }
    }

    /**
     * Set allow override
     *
     * @param $allowOverride
     * @return ServiceManager
     */
    public function setAllowOverride($allowOverride)
    {
        $this->allowOverride = (bool) $allowOverride;
        return $this;
    }

    /**
     * Get allow override
     *
     * @return bool
     */
    public function getAllowOverride()
    {
        return $this->allowOverride;
    }

    /**
     * Set flag indicating whether services are shared by default
     *
     * @param  bool $shareByDefault
     * @return ServiceManager
     * @throws Exception\RuntimeException if allowOverride is false
     */
    public function setShareByDefault($shareByDefault)
    {
        if ($this->allowOverride === false) {
            throw new Exception\RuntimeException(sprintf(
                '%s: cannot alter default shared service setting; container is marked immutable (allow_override is false)',
                get_class($this) . '::' . __FUNCTION__
            ));
        }
        $this->shareByDefault = (bool) $shareByDefault;
        return $this;
    }

    /**
     * Are services shared by default?
     *
     * @return bool
     */
    public function shareByDefault()
    {
        return $this->shareByDefault;
    }

    /**
     * Set throw exceptions in create
     *
     * @param  bool $throwExceptionInCreate
     * @return ServiceManager
     */
    public function setThrowExceptionInCreate($throwExceptionInCreate)
    {
        $this->throwExceptionInCreate = $throwExceptionInCreate;
        return $this;
    }

    /**
     * Get throw exceptions in create
     *
     * @return bool
     */
    public function getThrowExceptionInCreate()
    {
        return $this->throwExceptionInCreate;
    }

    /**
     * Set flag indicating whether to pull from peering manager before attempting creation
     *
     * @param  bool $retrieveFromPeeringManagerFirst
     * @return ServiceManager
     */
    public function setRetrieveFromPeeringManagerFirst($retrieveFromPeeringManagerFirst = true)
    {
        $this->retrieveFromPeeringManagerFirst = (bool) $retrieveFromPeeringManagerFirst;
        return $this;
    }

    /**
     * Should we retrieve from the peering manager prior to attempting to create a service?
     *
     * @return bool
     */
    public function retrieveFromPeeringManagerFirst()
    {
        return $this->retrieveFromPeeringManagerFirst;
    }

    /**
     * Set invokable class
     *
     * @param  string  $name
     * @param  string  $invokableClass
     * @param  bool $shared
     * @return ServiceManager
     * @throws Exception\InvalidServiceNameException
     */
    public function setInvokableClass($name, $invokableClass, $shared = null)
    {
        $cName = $this->canonicalizeName($name);

        if ($this->has(array($cName, $name), false)) {
            if ($this->allowOverride === false) {
                throw new Exception\InvalidServiceNameException(sprintf(
                    'A service by the name or alias "%s" already exists and cannot be overridden; please use an alternate name',
                    $name
                ));
            }
            $this->unregisterService($cName);
        }

        if ($shared === null) {
            $shared = $this->shareByDefault;
        }

        $this->invokableClasses[$cName] = $invokableClass;
        $this->shared[$cName]           = (bool) $shared;

        return $this;
    }

    /**
     * Set factory
     *
     * @param  string                           $name
     * @param  string|FactoryInterface|callable $factory
     * @param  bool                             $shared
     * @return ServiceManager
     * @throws Exception\InvalidArgumentException
     * @throws Exception\InvalidServiceNameException
     */
    public function setFactory($name, $factory, $shared = null)
    {
        $cName = $this->canonicalizeName($name);

        if (!($factory instanceof FactoryInterface || is_string($factory) || is_callable($factory))) {
            throw new Exception\InvalidArgumentException(
                'Provided abstract factory must be the class name of an abstract factory or an instance of an AbstractFactoryInterface.'
            );
        }

        if ($this->has(array($cName, $name), false)) {
            if ($this->allowOverride === false) {
                throw new Exception\InvalidServiceNameException(sprintf(
                    'A service by the name or alias "%s" already exists and cannot be overridden, please use an alternate name',
                    $name
                ));
            }
            $this->unregisterService($cName);
        }

        if ($shared === null) {
            $shared = $this->shareByDefault;
        }

        $this->factories[$cName] = $factory;
        $this->shared[$cName]    = (bool) $shared;

        return $this;
    }

    /**
     * Add abstract factory
     *
     * @param  AbstractFactoryInterface|string $factory
     * @param  bool                            $topOfStack
     * @return ServiceManager
     * @throws Exception\InvalidArgumentException if the abstract factory is invalid
     */
    public function addAbstractFactory($factory, $topOfStack = true)
    {
        if (!$factory instanceof AbstractFactoryInterface && is_string($factory)) {
            $factory = new $factory();
        }

        if (!$factory instanceof AbstractFactoryInterface) {
            throw new Exception\InvalidArgumentException(
                'Provided abstract factory must be the class name of an abstract'
                . ' factory or an instance of an AbstractFactoryInterface.'
            );
        }

        if ($topOfStack) {
            array_unshift($this->abstractFactories, $factory);
        } else {
            array_push($this->abstractFactories, $factory);
        }
        return $this;
    }

    /**
     * Sets the given service name as to be handled by a delegator factory
     *
     * @param  string $serviceName          name of the service being the delegate
     * @param  string $delegatorFactoryName name of the service being the delegator factory
     *
     * @return ServiceManager
     */
    public function addDelegator($serviceName, $delegatorFactoryName)
    {
        $cName = $this->canonicalizeName($serviceName);

        if (!isset($this->delegators[$cName])) {
            $this->delegators[$cName] = array();
        }

        $this->delegators[$cName][] = $delegatorFactoryName;

        return $this;
    }

    /**
     * Add initializer
     *
     * @param  callable|InitializerInterface $initializer
     * @param  bool                          $topOfStack
     * @return ServiceManager
     * @throws Exception\InvalidArgumentException
     */
    public function addInitializer($initializer, $topOfStack = true)
    {
        if (!($initializer instanceof InitializerInterface || is_callable($initializer))) {
            if (is_string($initializer)) {
                $initializer = new $initializer;
            }

            if (!($initializer instanceof InitializerInterface || is_callable($initializer))) {
                throw new Exception\InvalidArgumentException('$initializer should be callable.');
            }
        }

        if ($topOfStack) {
            array_unshift($this->initializers, $initializer);
        } else {
            array_push($this->initializers, $initializer);
        }
        return $this;
    }

    /**
     * Register a service with the locator
     *
     * @param  string  $name
     * @param  mixed   $service
     * @return ServiceManager
     * @throws Exception\InvalidServiceNameException
     */
    public function setService($name, $service)
    {
        $cName = $this->canonicalizeName($name);

        if ($this->has($cName, false)) {
            if ($this->allowOverride === false) {
                throw new Exception\InvalidServiceNameException(sprintf(
                    '%s: A service by the name "%s" or alias already exists and cannot be overridden, please use an alternate name.',
                    get_class($this) . '::' . __FUNCTION__,
                    $name
                ));
            }
            $this->unregisterService($cName);
        }

        $this->instances[$cName] = $service;

        return $this;
    }

    /**
     * @param  string $name
     * @param  bool   $isShared
     * @return ServiceManager
     * @throws Exception\ServiceNotFoundException
     */
    public function setShared($name, $isShared)
    {
        $cName = $this->canonicalizeName($name);

        if (
            !isset($this->invokableClasses[$cName])
            && !isset($this->factories[$cName])
            && !$this->canCreateFromAbstractFactory($cName, $name)
        ) {
            throw new Exception\ServiceNotFoundException(sprintf(
                '%s: A service by the name "%s" was not found and could not be marked as shared',
                get_class($this) . '::' . __FUNCTION__,
                $name
            ));
        }

        $this->shared[$cName] = (bool) $isShared;
        return $this;
    }

    /**
     * Resolve the alias for the given canonical name
     *
     * @param  string $cName The canonical name to resolve
     * @return string The resolved canonical name
     */
    protected function resolveAlias($cName)
    {
        $stack = array();

        while ($this->hasAlias($cName)) {
            if (isset($stack[$cName])) {
                throw new Exception\CircularReferenceException(sprintf(
                    'Circular alias reference: %s -> %s',
                    implode(' -> ', $stack),
                    $cName
                ));
            }

            $stack[$cName] = $cName;
            $cName = $this->aliases[$cName];
        }

        return $cName;
    }

    /**
     * Retrieve a registered instance
     *
     * @param  string  $name
     * @param  bool    $usePeeringServiceManagers
     * @throws Exception\ServiceNotFoundException
     * @return object|array
     */
    public function get($name, $usePeeringServiceManagers = true)
    {
        // inlined code from ServiceManager::canonicalizeName for performance
        if (isset($this->canonicalNames[$name])) {
            $cName = $this->canonicalNames[$name];
        } else {
            $cName = $this->canonicalizeName($name);
        }

        $isAlias = false;

        if ($this->hasAlias($cName)) {
            $isAlias = true;
            $cName = $this->resolveAlias($cName);
        }

        $instance = null;

        if ($usePeeringServiceManagers && $this->retrieveFromPeeringManagerFirst) {
            $instance = $this->retrieveFromPeeringManager($name);

            if (null !== $instance) {
                return $instance;
            }
        }

        if (isset($this->instances[$cName])) {
            return $this->instances[$cName];
        }

        if (!$instance) {
            if (
                isset($this->invokableClasses[$cName])
                || isset($this->factories[$cName])
                || isset($this->aliases[$cName])
                || $this->canCreateFromAbstractFactory($cName, $name)
            ) {
                $instance = $this->create(array($cName, $name));
            } elseif ($usePeeringServiceManagers && !$this->retrieveFromPeeringManagerFirst) {
                $instance = $this->retrieveFromPeeringManager($name);
            }
        }

        // Still no instance? raise an exception
        if ($instance === null) {
            if ($isAlias) {
                throw new Exception\ServiceNotFoundException(sprintf(
                    'An alias "%s" was requested but no service could be found.',
                    $name
                ));
            }

            throw new Exception\ServiceNotFoundException(sprintf(
                '%s was unable to fetch or create an instance for %s',
                get_class($this) . '::' . __FUNCTION__,
                $name
            ));
        }

        if (
            ($this->shareByDefault && !isset($this->shared[$cName]))
            || (isset($this->shared[$cName]) && $this->shared[$cName] === true)
        ) {
            $this->instances[$cName] = $instance;
        }

        return $instance;
    }

    /**
     * Create an instance of the requested service
     *
     * @param  string|array $name
     *
     * @return bool|object
     */
    public function create($name)
    {
        if (is_array($name)) {
            list($cName, $rName) = $name;
        } else {
            $rName = $name;

            // inlined code from ServiceManager::canonicalizeName for performance
            if (isset($this->canonicalNames[$rName])) {
                $cName = $this->canonicalNames[$name];
            } else {
                $cName = $this->canonicalizeName($name);
            }
        }

        if (isset($this->delegators[$cName])) {
            return $this->createDelegatorFromFactory($cName, $rName);
        }

        return $this->doCreate($rName, $cName);
    }

    /**
     * Creates a callback that uses a delegator to create a service
     *
     * @param DelegatorFactoryInterface|callable $delegatorFactory the delegator factory
     * @param string                             $rName            requested service name
     * @param string                             $cName            canonical service name
     * @param callable                           $creationCallback callback for instantiating the real service
     *
     * @return callable
     */
    private function createDelegatorCallback($delegatorFactory, $rName, $cName, $creationCallback)
    {
        $serviceManager  = $this;

        return function () use ($serviceManager, $delegatorFactory, $rName, $cName, $creationCallback) {
            return $delegatorFactory instanceof DelegatorFactoryInterface
                ? $delegatorFactory->createDelegatorWithName($serviceManager, $cName, $rName, $creationCallback)
                : $delegatorFactory($serviceManager, $cName, $rName, $creationCallback);
        };
    }

    /**
     * Actually creates the service
     *
     * @param string $rName real service name
     * @param string $cName canonicalized service name
     *
     * @return bool|mixed|null|object
     * @throws Exception\ServiceNotFoundException
     *
     * @internal this method is internal because of PHP 5.3 compatibility - do not explicitly use it
     */
    public function doCreate($rName, $cName)
    {
        $instance = null;

        if (isset($this->factories[$cName])) {
            $instance = $this->createFromFactory($cName, $rName);
        }

        if ($instance === null && isset($this->invokableClasses[$cName])) {
            $instance = $this->createFromInvokable($cName, $rName);
        }

        if ($instance === null && $this->canCreateFromAbstractFactory($cName, $rName)) {
            $instance = $this->createFromAbstractFactory($cName, $rName);
        }

        if ($instance === null && $this->throwExceptionInCreate) {
            throw new Exception\ServiceNotFoundException(sprintf(
                'No valid instance was found for %s%s',
                $cName,
                ($rName ? '(alias: ' . $rName . ')' : '')
            ));
        }

        // Do not call initializers if we do not have an instance
        if ($instance === null) {
            return $instance;
        }

        foreach ($this->initializers as $initializer) {
            if ($initializer instanceof InitializerInterface) {
                $initializer->initialize($instance, $this);
            } else {
                call_user_func($initializer, $instance, $this);
            }
        }

        return $instance;
    }

    /**
     * Determine if we can create an instance.
     *
     * @param  string|array $name
     * @param  bool         $checkAbstractFactories
     * @return bool
     *
     * @deprecated this method is being deprecated as of zendframework 2.2, and may be removed in future major versions
     */
    public function canCreate($name, $checkAbstractFactories = true)
    {
        if (is_array($name)) {
            list($cName, $rName) = $name;
        } else {
            $rName = $name;
            $cName = $this->canonicalizeName($rName);
        }

        return (
            isset($this->invokableClasses[$cName])
            || isset($this->factories[$cName])
            || isset($this->aliases[$cName])
            || isset($this->instances[$cName])
            || ($checkAbstractFactories && $this->canCreateFromAbstractFactory($cName, $rName))
        );
    }

    /**
     * @param  string|array  $name
     * @param  bool          $checkAbstractFactories
     * @param  bool          $usePeeringServiceManagers
     * @return bool
     */
    public function has($name, $checkAbstractFactories = true, $usePeeringServiceManagers = true)
    {
        if (is_array($name)) {
            list($cName, $rName) = $name;
        } else {
            $rName = $name;

            // inlined code from ServiceManager::canonicalizeName for performance
            if (isset($this->canonicalNames[$rName])) {
                $cName = $this->canonicalNames[$name];
            } else {
                $cName = $this->canonicalizeName($name);
            }
        }

        if (
            isset($this->invokableClasses[$cName])
            || isset($this->factories[$cName])
            || isset($this->aliases[$cName])
            || isset($this->instances[$cName])
            || ($checkAbstractFactories && $this->canCreateFromAbstractFactory($cName, $name))
        ) {
            return true;
        }

        if ($usePeeringServiceManagers) {
            foreach ($this->peeringServiceManagers as $peeringServiceManager) {
                if ($peeringServiceManager->has($rName)) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Determine if we can create an instance from an abstract factory.
     *
     * @param  string $cName
     * @param  string $rName
     * @return bool
     */
    public function canCreateFromAbstractFactory($cName, $rName)
    {
        // check abstract factories
        foreach ($this->abstractFactories as $abstractFactory) {
            $factoryClass = get_class($abstractFactory);

            if (
                isset($this->pendingAbstractFactoryRequests[$factoryClass])
                && $this->pendingAbstractFactoryRequests[$factoryClass] == $rName
            ) {
                return false;
            }

            $objectHash = spl_object_hash($abstractFactory);

            if ($this->lastAbstractFactoryUsed === $objectHash && $this->lastCanonicalNameUsed === $cName) {
                $this->lastAbstractFactoryUsed = $this->lastCanonicalNameUsed = null;
                return false;
            }

            $this->lastAbstractFactoryUsed = $objectHash;
            $this->lastCanonicalNameUsed   = $cName;

            if ($abstractFactory->canCreateServiceWithName($this, $cName, $rName)) {
                $this->lastAbstractFactoryUsed = $this->lastCanonicalNameUsed = null;
                return true;
            }
        }
        return false;
    }

    /**
     * Ensure the alias definition will not result in a circular reference
     *
     * @param  string $alias
     * @param  string $nameOrAlias
     * @throws Exception\CircularReferenceException
     * @return self
     */
    protected function checkForCircularAliasReference($alias, $nameOrAlias)
    {
        $aliases = $this->aliases;
        $aliases[$alias] = $nameOrAlias;
        $stack = array();

        while (isset($aliases[$alias])) {
            if (isset($stack[$alias])) {
                throw new Exception\CircularReferenceException(sprintf(
                    'The alias definition "%s" : "%s" results in a circular reference: "%s" -> "%s"',
                    $alias,
                    $nameOrAlias,
                    implode('" -> "', $stack),
                    $alias
                ));
            }

            $stack[$alias] = $alias;
            $alias = $aliases[$alias];
        }

        return $this;
    }

    /**
     * @param  string $alias
     * @param  string $nameOrAlias
     * @return ServiceManager
     * @throws Exception\ServiceNotFoundException
     * @throws Exception\InvalidServiceNameException
     */
    public function setAlias($alias, $nameOrAlias)
    {
        if (!is_string($alias) || !is_string($nameOrAlias)) {
            throw new Exception\InvalidServiceNameException('Service or alias names must be strings.');
        }

        $cAlias = $this->canonicalizeName($alias);
        $nameOrAlias = $this->canonicalizeName($nameOrAlias);

        if ($alias == '' || $nameOrAlias == '') {
            throw new Exception\InvalidServiceNameException('Invalid service name alias');
        }

        if ($this->allowOverride === false && $this->has(array($cAlias, $alias), false)) {
            throw new Exception\InvalidServiceNameException(sprintf(
                'An alias by the name "%s" or "%s" already exists',
                $cAlias,
                $alias
            ));
        }

        if ($this->hasAlias($alias)) {
            $this->checkForCircularAliasReference($cAlias, $nameOrAlias);
        }

        $this->aliases[$cAlias] = $nameOrAlias;
        return $this;
    }

    /**
     * Determine if we have an alias
     *
     * @param  string $alias
     * @return bool
     */
    public function hasAlias($alias)
    {
        return isset($this->aliases[$this->canonicalizeName($alias)]);
    }

    /**
     * Create scoped service manager
     *
     * @param  string $peering
     * @return ServiceManager
     */
    public function createScopedServiceManager($peering = self::SCOPE_PARENT)
    {
        $scopedServiceManager = new ServiceManager();
        if ($peering == self::SCOPE_PARENT) {
            $scopedServiceManager->peeringServiceManagers[] = $this;
        }
        if ($peering == self::SCOPE_CHILD) {
            $this->peeringServiceManagers[] = $scopedServiceManager;
        }
        return $scopedServiceManager;
    }

    /**
     * Add a peering relationship
     *
     * @param  ServiceManager $manager
     * @param  string         $peering
     * @return ServiceManager
     */
    public function addPeeringServiceManager(ServiceManager $manager, $peering = self::SCOPE_PARENT)
    {
        if ($peering == self::SCOPE_PARENT) {
            $this->peeringServiceManagers[] = $manager;
        }
        if ($peering == self::SCOPE_CHILD) {
            $manager->peeringServiceManagers[] = $this;
        }
        return $this;
    }

    /**
     * Canonicalize name
     *
     * @param  string $name
     * @return string
     */
    protected function canonicalizeName($name)
    {
        if (isset($this->canonicalNames[$name])) {
            return $this->canonicalNames[$name];
        }

        // this is just for performance instead of using str_replace
        return $this->canonicalNames[$name] = strtolower(strtr($name, $this->canonicalNamesReplacements));
    }

    /**
     * Create service via callback
     *
     * @param  callable $callable
     * @param  string   $cName
     * @param  string   $rName
     * @throws Exception\ServiceNotCreatedException
     * @throws Exception\ServiceNotFoundException
     * @throws Exception\CircularDependencyFoundException
     * @return object
     */
    protected function createServiceViaCallback($callable, $cName, $rName)
    {
        static $circularDependencyResolver = array();
        $depKey = spl_object_hash($this) . '-' . $cName;

        if (isset($circularDependencyResolver[$depKey])) {
            $circularDependencyResolver = array();
            throw new Exception\CircularDependencyFoundException('Circular dependency for LazyServiceLoader was found for instance ' . $rName);
        }

        try {
            $circularDependencyResolver[$depKey] = true;
            $instance = call_user_func($callable, $this, $cName, $rName);
            unset($circularDependencyResolver[$depKey]);
        } catch (Exception\ServiceNotFoundException $e) {
            unset($circularDependencyResolver[$depKey]);
            throw $e;
        } catch (\Exception $e) {
            unset($circularDependencyResolver[$depKey]);
            throw new Exception\ServiceNotCreatedException(
                sprintf('An exception was raised while creating "%s"; no instance returned', $rName),
                $e->getCode(),
                $e
            );
        }
        if ($instance === null) {
            throw new Exception\ServiceNotCreatedException('The factory was called but did not return an instance.');
        }

        return $instance;
    }

    /**
     * Retrieve a keyed list of all registered services. Handy for debugging!
     *
     * @return array
     */
    public function getRegisteredServices()
    {
        return array(
            'invokableClasses' => array_keys($this->invokableClasses),
            'factories' => array_keys($this->factories),
            'aliases' => array_keys($this->aliases),
            'instances' => array_keys($this->instances),
        );
    }

    /**
     * Retrieve a keyed list of all canonical names. Handy for debugging!
     *
     * @return array
     */
    public function getCanonicalNames()
    {
        return $this->canonicalNames;
    }

    /**
     * Allows to override the canonical names lookup map with predefined
     * values.
     *
     * @param array $canonicalNames
     * @return ServiceManager
     */
    public function setCanonicalNames($canonicalNames)
    {
        $this->canonicalNames = $canonicalNames;

        return $this;
    }

    /**
     * Attempt to retrieve an instance via a peering manager
     *
     * @param  string $name
     * @return mixed
     */
    protected function retrieveFromPeeringManager($name)
    {
        foreach ($this->peeringServiceManagers as $peeringServiceManager) {
            if ($peeringServiceManager->has($name)) {
                return $peeringServiceManager->get($name);
            }
        }

        $name = $this->canonicalizeName($name);

        if ($this->hasAlias($name)) {
            do {
                $name = $this->aliases[$name];
            } while ($this->hasAlias($name));
        }

        foreach ($this->peeringServiceManagers as $peeringServiceManager) {
            if ($peeringServiceManager->has($name)) {
                return $peeringServiceManager->get($name);
            }
        }

        return null;
    }

    /**
     * Attempt to create an instance via an invokable class
     *
     * @param  string $canonicalName
     * @param  string $requestedName
     * @return null|\stdClass
     * @throws Exception\ServiceNotFoundException If resolved class does not exist
     */
    protected function createFromInvokable($canonicalName, $requestedName)
    {
        $invokable = $this->invokableClasses[$canonicalName];
        if (!class_exists($invokable)) {
            throw new Exception\ServiceNotFoundException(sprintf(
                '%s: failed retrieving "%s%s" via invokable class "%s"; class does not exist',
                get_class($this) . '::' . __FUNCTION__,
                $canonicalName,
                ($requestedName ? '(alias: ' . $requestedName . ')' : ''),
                $invokable
            ));
        }
        $instance = new $invokable;
        return $instance;
    }

    /**
     * Attempt to create an instance via a factory
     *
     * @param  string $canonicalName
     * @param  string $requestedName
     * @return mixed
     * @throws Exception\ServiceNotCreatedException If factory is not callable
     */
    protected function createFromFactory($canonicalName, $requestedName)
    {
        $factory = $this->factories[$canonicalName];
        if (is_string($factory) && class_exists($factory, true)) {
            $factory = new $factory;
            $this->factories[$canonicalName] = $factory;
        }
        if ($factory instanceof FactoryInterface) {
            $instance = $this->createServiceViaCallback(array($factory, 'createService'), $canonicalName, $requestedName);
        } elseif (is_callable($factory)) {
            $instance = $this->createServiceViaCallback($factory, $canonicalName, $requestedName);
        } else {
            throw new Exception\ServiceNotCreatedException(sprintf(
                'While attempting to create %s%s an invalid factory was registered for this instance type.',
                $canonicalName,
                ($requestedName ? '(alias: ' . $requestedName . ')' : '')
            ));
        }
        return $instance;
    }

    /**
     * Attempt to create an instance via an abstract factory
     *
     * @param  string $canonicalName
     * @param  string $requestedName
     * @return object|null
     * @throws Exception\ServiceNotCreatedException If abstract factory is not callable
     */
    protected function createFromAbstractFactory($canonicalName, $requestedName)
    {
        foreach ($this->abstractFactories as $index => $abstractFactory) {
            // support factories as strings
            if (is_string($abstractFactory) && class_exists($abstractFactory, true)) {
                $this->abstractFactories[$index] = $abstractFactory = new $abstractFactory;
            } elseif (!$abstractFactory instanceof AbstractFactoryInterface) {
                throw new Exception\ServiceNotCreatedException(sprintf(
                    'While attempting to create %s%s an abstract factory could not produce a valid instance.',
                    $canonicalName,
                    ($requestedName ? '(alias: ' . $requestedName . ')' : '')
                ));
            }
            try {
                if ($abstractFactory->canCreateServiceWithName($this, $canonicalName, $requestedName)) {
                    $this->pendingAbstractFactoryRequests[get_class($abstractFactory)] = $requestedName;
                    $instance = $this->createServiceViaCallback(
                        array($abstractFactory, 'createServiceWithName'),
                        $canonicalName,
                        $requestedName
                    );
                    unset($this->pendingAbstractFactoryRequests[get_class($abstractFactory)]);
                } else {
                    $instance = null;
                }
            } catch (\Exception $e) {
                unset($this->pendingAbstractFactoryRequests[get_class($abstractFactory)]);
                throw new Exception\ServiceNotCreatedException(
                    sprintf(
                        'An abstract factory could not create an instance of %s%s.',
                        $canonicalName,
                        ($requestedName ? '(alias: ' . $requestedName . ')' : '')
                    ),
                    $e->getCode(),
                    $e
                );
            }
            if ($instance !== null) {
                return $instance;
            }
        }
    }

    /**
     * @param $canonicalName
     * @param $requestedName
     * @return mixed
     * @throws Exception\ServiceNotCreatedException
     */
    protected function createDelegatorFromFactory($canonicalName, $requestedName)
    {
        $serviceManager     = $this;
        $delegatorsCount    = count($this->delegators[$canonicalName]);
        $creationCallback   = function () use ($serviceManager, $requestedName, $canonicalName) {
            return $serviceManager->doCreate($requestedName, $canonicalName);
        };

        for ($i = 0; $i < $delegatorsCount; $i += 1) {

            $delegatorFactory = $this->delegators[$canonicalName][$i];

            if (is_string($delegatorFactory)) {
                $delegatorFactory = !$this->has($delegatorFactory) && class_exists($delegatorFactory, true) ?
                    new $delegatorFactory
                    : $this->get($delegatorFactory);
                $this->delegators[$canonicalName][$i] = $delegatorFactory;
            }

            if (!$delegatorFactory instanceof DelegatorFactoryInterface && !is_callable($delegatorFactory)) {
                throw new Exception\ServiceNotCreatedException(sprintf(
                    'While attempting to create %s%s an invalid factory was registered for this instance type.',
                    $canonicalName,
                    ($requestedName ? '(alias: ' . $requestedName . ')' : '')
                ));
            }

            $creationCallback = $this->createDelegatorCallback(
                $delegatorFactory,
                $requestedName,
                $canonicalName,
                $creationCallback
            );
        }

        return $creationCallback($serviceManager, $canonicalName, $requestedName, $creationCallback);
    }

    /**
     * Checks if the object has this class as one of its parents
     *
     * @see https://bugs.php.net/bug.php?id=53727
     * @see https://github.com/zendframework/zf2/pull/1807
     *
     * @param string $className
     * @param string $type
     * @return bool
     *
     * @deprecated this method is being deprecated as of zendframework 2.2, and may be removed in future major versions
     */
    protected static function isSubclassOf($className, $type)
    {
        if (is_subclass_of($className, $type)) {
            return true;
        }
        if (version_compare(PHP_VERSION, '5.3.7', '>=')) {
            return false;
        }
        if (!interface_exists($type)) {
            return false;
        }
        $r = new ReflectionClass($className);
        return $r->implementsInterface($type);
    }

    /**
     * Unregister a service
     *
     * Called when $allowOverride is true and we detect that a service being
     * added to the instance already exists. This will remove the duplicate
     * entry, and also any shared flags previously registered.
     *
     * @param  string $canonical
     * @return void
     */
    protected function unregisterService($canonical)
    {
        $types = array('invokableClasses', 'factories', 'aliases');
        foreach ($types as $type) {
            if (isset($this->{$type}[$canonical])) {
                unset($this->{$type}[$canonical]);
                break;
            }
        }

        if (isset($this->instances[$canonical])) {
            unset($this->instances[$canonical]);
        }

        if (isset($this->shared[$canonical])) {
            unset($this->shared[$canonical]);
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager;

interface ConfigInterface
{
    /**
     * Configure service manager
     *
     * @param ServiceManager $serviceManager
     * @return void
     */
    public function configureServiceManager(ServiceManager $serviceManager);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager;

interface ServiceLocatorAwareInterface
{
    /**
     * Set service locator
     *
     * @param ServiceLocatorInterface $serviceLocator
     */
    public function setServiceLocator(ServiceLocatorInterface $serviceLocator);

    /**
     * Get service locator
     *
     * @return ServiceLocatorInterface
     */
    public function getServiceLocator();
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager\Proxy;

use ProxyManager\Factory\LazyLoadingValueHolderFactory;

use ProxyManager\Proxy\LazyLoadingInterface;
use Zend\ServiceManager\DelegatorFactoryInterface;
use Zend\ServiceManager\Exception;
use Zend\ServiceManager\ServiceLocatorInterface;

/**
 * Delegator factory responsible of instantiating lazy loading value holder proxies of
 * given services at runtime
 *
 * @link https://github.com/Ocramius/ProxyManager/blob/master/docs/lazy-loading-value-holder.md
 */
class LazyServiceFactory implements DelegatorFactoryInterface
{
    /**
     * @var \ProxyManager\Factory\LazyLoadingValueHolderFactory
     */
    protected $proxyFactory;

    /**
     * @var string[] map of service names to class names
     */
    protected $servicesMap;

    /**
     * @param LazyLoadingValueHolderFactory $proxyFactory
     * @param string[]                      $servicesMap  a map of service names to class names of their
     *                                                    respective classes
     */
    public function __construct(LazyLoadingValueHolderFactory $proxyFactory, array $servicesMap)
    {
        $this->proxyFactory = $proxyFactory;
        $this->servicesMap  = $servicesMap;
    }

    /**
     * {@inheritDoc}
     *
     * @return object|\ProxyManager\Proxy\LazyLoadingInterface|\ProxyManager\Proxy\ValueHolderInterface
     */
    public function createDelegatorWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName, $callback)
    {
        $initializer = function (& $wrappedInstance, LazyLoadingInterface $proxy) use ($callback) {
            $proxy->setProxyInitializer(null);

            $wrappedInstance = call_user_func($callback);

            return true;
        };

        if (isset($this->servicesMap[$requestedName])) {
            return $this->proxyFactory->createProxy($this->servicesMap[$requestedName], $initializer);
        } elseif (isset($this->servicesMap[$name])) {
            return $this->proxyFactory->createProxy($this->servicesMap[$name], $initializer);
        }

        throw new Exception\InvalidServiceNameException(
            sprintf('The requested service "%s" was not found in the provided services map', $requestedName)
        );
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager\Proxy;

use ProxyManager\Configuration;
use ProxyManager\Factory\LazyLoadingValueHolderFactory;
use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\Exception;

/**
 * Service factory responsible of instantiating {@see \Zend\ServiceManager\Proxy\LazyServiceFactory}
 * and configuring it starting from application configuration
 */
class LazyServiceFactoryFactory implements FactoryInterface
{
    /**
     * {@inheritDoc}
     *
     * @return \Zend\ServiceManager\Proxy\LazyServiceFactory
     */
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $config = $serviceLocator->get('Config');

        if (!isset($config['lazy_services'])) {
            throw new Exception\InvalidArgumentException('Missing "lazy_services" config key');
        }

        $lazyServices = $config['lazy_services'];

        if (!isset($lazyServices['class_map'])) {
            throw new Exception\InvalidArgumentException('Missing "class_map" config key in "lazy_services"');
        }

        $factoryConfig = new Configuration();

        if (isset($lazyServices['proxies_target_dir'])) {
            $factoryConfig->setProxiesTargetDir($lazyServices['proxies_target_dir']);
        }

        if (!isset($lazyServices['write_proxy_files']) || ! $lazyServices['write_proxy_files']) {
            $factoryConfig->setGeneratorStrategy(new EvaluatingGeneratorStrategy());
        }

        if (isset($lazyServices['auto_generate_proxies'])) {
            $factoryConfig->setAutoGenerateProxies($lazyServices['auto_generate_proxies']);

            // register the proxy autoloader if the proxies already exist
            if (!$lazyServices['auto_generate_proxies']) {
                spl_autoload_register($factoryConfig->getProxyAutoloader());

                $factoryConfig->setGeneratorStrategy(new EvaluatingGeneratorStrategy());
            }
        }

        //if (!isset($lazyServicesConfig['runtime_evaluate_proxies']))

        if (isset($lazyServices['proxies_namespace'])) {
            $factoryConfig->setProxiesNamespace($lazyServices['proxies_namespace']);
        }

        return new LazyServiceFactory(new LazyLoadingValueHolderFactory($factoryConfig), $lazyServices['class_map']);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager;

use Zend\ServiceManager\ServiceLocatorInterface;

interface InitializerInterface
{
    /**
     * Initialize
     *
     * @param $instance
     * @param ServiceLocatorInterface $serviceLocator
     * @return mixed
     */
    public function initialize($instance, ServiceLocatorInterface $serviceLocator);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager;

interface AbstractFactoryInterface
{
    /**
     * Determine if we can create a service with name
     *
     * @param ServiceLocatorInterface $serviceLocator
     * @param $name
     * @param $requestedName
     * @return bool
     */
    public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName);

    /**
     * Create service with name
     *
     * @param ServiceLocatorInterface $serviceLocator
     * @param $name
     * @param $requestedName
     * @return mixed
     */
    public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager;

class Config implements ConfigInterface
{
    /**
     * @var array
     */
    protected $config = array();

    /**
     * Constructor
     *
     * @param array $config
     */
    public function __construct($config = array())
    {
        $this->config = $config;
    }

    /**
     * Get allow override
     *
     * @return null|bool
     */
    public function getAllowOverride()
    {
        return (isset($this->config['allow_override'])) ? $this->config['allow_override'] : null;
    }

    /**
     * Get factories
     *
     * @return array
     */
    public function getFactories()
    {
        return (isset($this->config['factories'])) ? $this->config['factories'] : array();
    }

    /**
     * Get abstract factories
     *
     * @return array
     */
    public function getAbstractFactories()
    {
        return (isset($this->config['abstract_factories'])) ? $this->config['abstract_factories'] : array();
    }

    /**
     * Get invokables
     *
     * @return array
     */
    public function getInvokables()
    {
        return (isset($this->config['invokables'])) ? $this->config['invokables'] : array();
    }

    /**
     * Get services
     *
     * @return array
     */
    public function getServices()
    {
        return (isset($this->config['services'])) ? $this->config['services'] : array();
    }

    /**
     * Get aliases
     *
     * @return array
     */
    public function getAliases()
    {
        return (isset($this->config['aliases'])) ? $this->config['aliases'] : array();
    }

    /**
     * Get initializers
     *
     * @return array
     */
    public function getInitializers()
    {
        return (isset($this->config['initializers'])) ? $this->config['initializers'] : array();
    }

    /**
     * Get shared
     *
     * @return array
     */
    public function getShared()
    {
        return (isset($this->config['shared'])) ? $this->config['shared'] : array();
    }

    /**
     * Get the delegator services map, with keys being the services acting as delegates,
     * and values being the delegator factories names
     *
     * @return array
     */
    public function getDelegators()
    {
        return (isset($this->config['delegators'])) ? $this->config['delegators'] : array();
    }

    /**
     * Configure service manager
     *
     * @param ServiceManager $serviceManager
     * @return void
     */
    public function configureServiceManager(ServiceManager $serviceManager)
    {
        if (($allowOverride = $this->getAllowOverride()) !== null) {
            $serviceManager->setAllowOverride($allowOverride);
        }

        foreach ($this->getFactories() as $name => $factory) {
            $serviceManager->setFactory($name, $factory);
        }

        foreach ($this->getAbstractFactories() as $factory) {
            $serviceManager->addAbstractFactory($factory);
        }

        foreach ($this->getInvokables() as $name => $invokable) {
            $serviceManager->setInvokableClass($name, $invokable);
        }

        foreach ($this->getServices() as $name => $service) {
            $serviceManager->setService($name, $service);
        }

        foreach ($this->getAliases() as $alias => $nameOrAlias) {
            $serviceManager->setAlias($alias, $nameOrAlias);
        }

        foreach ($this->getInitializers() as $initializer) {
            $serviceManager->addInitializer($initializer);
        }

        foreach ($this->getShared() as $name => $isShared) {
            $serviceManager->setShared($name, $isShared);
        }

        foreach ($this->getDelegators() as $originalServiceName => $delegators) {
            foreach ($delegators as $delegator) {
                $serviceManager->addDelegator($originalServiceName, $delegator);
            }
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager;

/**
 * Service locator interface
 */
interface ServiceLocatorInterface
{
    /**
     * Retrieve a registered instance
     *
     * @param  string  $name
     * @throws Exception\ServiceNotFoundException
     * @return object|array
     */
    public function get($name);

    /**
     * Check for a registered instance
     *
     * @param  string|array  $name
     * @return bool
     */
    public function has($name);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager;

interface ServiceManagerAwareInterface
{
    /**
     * Set service manager
     *
     * @param ServiceManager $serviceManager
     */
    public function setServiceManager(ServiceManager $serviceManager);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager;

/**
 * Interface for factories that can create delegates for services
 */
interface DelegatorFactoryInterface
{
    /**
     * A factory that creates delegates of a given service
     *
     * @param ServiceLocatorInterface $serviceLocator the service locator which requested the service
     * @param string                  $name           the normalized service name
     * @param string                  $requestedName  the requested service name
     * @param callable                $callback       the callback that is responsible for creating the service
     *
     * @return mixed
     */
    public function createDelegatorWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName, $callback);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager\Exception;

class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager\Exception;

class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager\Exception;

class ServiceNotFoundException extends InvalidArgumentException
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager\Exception;

interface ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager\Exception;

class CircularReferenceException extends RuntimeException
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager\Exception;

class InvalidServiceNameException extends RuntimeException
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager\Exception;

class ServiceNotCreatedException extends RuntimeException
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager\Exception;

class CircularDependencyFoundException extends RuntimeException
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager\Di;

use Zend\Di\Di;
use Zend\ServiceManager\AbstractFactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

class DiAbstractServiceFactory extends DiServiceFactory implements AbstractFactoryInterface
{
    /**
     * Constructor
     *
     * @param \Zend\Di\Di $di
     * @param null|string|\Zend\Di\InstanceManager $useServiceLocator
     */
    public function __construct(Di $di, $useServiceLocator = self::USE_SL_NONE)
    {
        $this->di = $di;
        if (in_array($useServiceLocator, array(self::USE_SL_BEFORE_DI, self::USE_SL_AFTER_DI, self::USE_SL_NONE))) {
            $this->useServiceLocator = $useServiceLocator;
        }

        // since we are using this in a proxy-fashion, localize state
        $this->definitions = $this->di->definitions;
        $this->instanceManager = $this->di->instanceManager;
    }

    /**
     * {@inheritDoc}
     */
    public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $serviceName, $requestedName)
    {
        $this->serviceLocator = $serviceLocator;
        if ($requestedName) {
            return $this->get($requestedName, array());
        }

        return $this->get($serviceName, array());
    }

    /**
     * {@inheritDoc}
     */
    public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName)
    {
        return $this->instanceManager->hasSharedInstance($requestedName)
            || $this->instanceManager->hasAlias($requestedName)
            || $this->instanceManager->hasConfig($requestedName)
            || $this->instanceManager->hasTypePreferences($requestedName)
            || $this->definitions->hasClass($requestedName);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager\Di;

use Zend\Di\InstanceManager as DiInstanceManager;
use Zend\ServiceManager\ServiceLocatorInterface;

class DiInstanceManagerProxy extends DiInstanceManager
{
    /**
     * @var DiInstanceManager
     */
    protected $diInstanceManager = null;

    /**
     * @var ServiceLocatorInterface
     */
    protected $serviceLocator = null;

    /**
     * Constructor
     *
     * @param DiInstanceManager $diInstanceManager
     * @param ServiceLocatorInterface $serviceLocator
     */
    public function __construct(DiInstanceManager $diInstanceManager, ServiceLocatorInterface $serviceLocator)
    {
        $this->diInstanceManager = $diInstanceManager;
        $this->serviceLocator = $serviceLocator;

        // localize state
        $this->aliases = &$diInstanceManager->aliases;
        $this->sharedInstances = &$diInstanceManager->sharedInstances;
        $this->sharedInstancesWithParams = &$diInstanceManager->sharedInstancesWithParams;
        $this->configurations = &$diInstanceManager->configurations;
        $this->typePreferences = &$diInstanceManager->typePreferences;
    }

    /**
     * Determine if we have a shared instance by class or alias
     *
     * @param $classOrAlias
     * @return bool
     */
    public function hasSharedInstance($classOrAlias)
    {
        return ($this->serviceLocator->has($classOrAlias) || $this->diInstanceManager->hasSharedInstance($classOrAlias));
    }

    /**
     * Get shared instance
     *
     * @param $classOrAlias
     * @return mixed
     */
    public function getSharedInstance($classOrAlias)
    {
        if ($this->serviceLocator->has($classOrAlias)) {
            return $this->serviceLocator->get($classOrAlias);
        }

        return $this->diInstanceManager->getSharedInstance($classOrAlias);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager\Di;

use Zend\Di\Di;
use Zend\Di\Exception\ClassNotFoundException as DiClassNotFoundException;
use Zend\ServiceManager\Exception;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

class DiServiceFactory extends Di implements FactoryInterface
{
    /**@#+
     * constants
     */
    const USE_SL_BEFORE_DI = 'before';
    const USE_SL_AFTER_DI  = 'after';
    const USE_SL_NONE      = 'none';
    /**@#-*/

    /**
     * @var \Zend\Di\Di
     */
    protected $di = null;

    /**
     * @var \Zend\Di\InstanceManager
     */
    protected $name = null;

    /**
     * @var array
     */
    protected $parameters = array();

    /**
     * @var string
     */
    protected $useServiceLocator = self::USE_SL_AFTER_DI;

    /**
     * @var ServiceLocatorInterface
     */
    protected $serviceLocator = null;

    /**
     * Constructor
     *
     * @param \Zend\Di\Di $di
     * @param null|\Zend\Di\InstanceManager $name
     * @param array $parameters
     * @param string $useServiceLocator
     */
    public function __construct(Di $di, $name, array $parameters = array(), $useServiceLocator = self::USE_SL_NONE)
    {
        $this->di = $di;
        $this->name = $name;
        $this->parameters = $parameters;
        if (in_array($useServiceLocator, array(self::USE_SL_BEFORE_DI, self::USE_SL_AFTER_DI, self::USE_SL_NONE))) {
            $this->useServiceLocator = $useServiceLocator;
        }

        // since we are using this in a proxy-fashion, localize state
        $this->definitions = $this->di->definitions;
        $this->instanceManager = $this->di->instanceManager;
    }

    /**
     * Create service
     *
     * @param ServiceLocatorInterface $serviceLocator
     * @return object
     */
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $this->serviceLocator = $serviceLocator;
        return $this->get($this->name, $this->parameters);
    }

    /**
     * Override, as we want it to use the functionality defined in the proxy
     *
     * @param string $name
     * @param array $params
     * @return object
     * @throws Exception\ServiceNotFoundException
     */
    public function get($name, array $params = array())
    {
        // allow this di service to get dependencies from the service locator BEFORE trying di
        if ($this->useServiceLocator == self::USE_SL_BEFORE_DI && $this->serviceLocator->has($name)) {
            return $this->serviceLocator->get($name);
        }

        try {

            $service = parent::get($name, $params);
            return $service;

        } catch (DiClassNotFoundException $e) {

            // allow this di service to get dependencies from the service locator AFTER trying di
            if ($this->useServiceLocator == self::USE_SL_AFTER_DI && $this->serviceLocator->has($name)) {
                return $this->serviceLocator->get($name);
            } else {
                throw new Exception\ServiceNotFoundException(
                    sprintf('Service %s was not found in this DI instance', $name),
                    null,
                    $e
                );
            }
        }

    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager\Di;

use Zend\Di\Di;
use Zend\ServiceManager\Exception;
use Zend\ServiceManager\InitializerInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

class DiServiceInitializer extends Di implements InitializerInterface
{
    /**
     * @var Di
     */
    protected $di = null;

    /**
     * @var DiInstanceManagerProxy
     */
    protected $diInstanceManagerProxy = null;

    /**
     * @var ServiceLocatorInterface
     */
    protected $serviceLocator = null;

    /**
     * Constructor
     *
     * @param \Zend\Di\Di $di
     * @param \Zend\ServiceManager\ServiceLocatorInterface $serviceLocator
     * @param null|DiInstanceManagerProxy $diImProxy
     */
    public function __construct(Di $di, ServiceLocatorInterface $serviceLocator, DiInstanceManagerProxy $diImProxy = null)
    {
        $this->di = $di;
        $this->serviceLocator = $serviceLocator;
        $this->diInstanceManagerProxy = ($diImProxy) ?: new DiInstanceManagerProxy($di->instanceManager(), $serviceLocator);
    }

    /**
     * Initialize
     *
     * @param $instance
     * @param ServiceLocatorInterface $serviceLocator
     * @throws \Exception
     */
    public function initialize($instance, ServiceLocatorInterface $serviceLocator)
    {
        $instanceManager = $this->di->instanceManager;
        $this->di->instanceManager = $this->diInstanceManagerProxy;
        try {
            $this->di->injectDependencies($instance);
            $this->di->instanceManager = $instanceManager;
        } catch (\Exception $e) {
            $this->di->instanceManager = $instanceManager;
            throw $e;
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager;

interface FactoryInterface
{
    /**
     * Create service
     *
     * @param ServiceLocatorInterface $serviceLocator
     * @return mixed
     */
    public function createService(ServiceLocatorInterface $serviceLocator);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\ServiceManager;

/**
 * ServiceManager implementation for managing plugins
 *
 * Automatically registers an initializer which should be used to verify that
 * a plugin instance is of a valid type. Additionally, allows plugins to accept
 * an array of options for the constructor, which can be used to configure
 * the plugin when retrieved. Finally, enables the allowOverride property by
 * default to allow registering factories, aliases, and invokables to take
 * the place of those provided by the implementing class.
 */
abstract class AbstractPluginManager extends ServiceManager implements ServiceLocatorAwareInterface
{
    /**
     * Allow overriding by default
     *
     * @var bool
     */
    protected $allowOverride = true;

    /**
     * Whether or not to auto-add a class as an invokable class if it exists
     *
     * @var bool
     */
    protected $autoAddInvokableClass = true;

    /**
     * Options to use when creating an instance
     *
     * @var mixed
     */
    protected $creationOptions = null;

    /**
     * The main service locator
     *
     * @var ServiceLocatorInterface
     */
    protected $serviceLocator;

    /**
     * Constructor
     *
     * Add a default initializer to ensure the plugin is valid after instance
     * creation.
     *
     * @param  null|ConfigInterface $configuration
     */
    public function __construct(ConfigInterface $configuration = null)
    {
        parent::__construct($configuration);
        $self = $this;
        $this->addInitializer(function ($instance) use ($self) {
            if ($instance instanceof ServiceLocatorAwareInterface) {
                $instance->setServiceLocator($self);
            }
        });
    }

    /**
     * Validate the plugin
     *
     * Checks that the filter loaded is either a valid callback or an instance
     * of FilterInterface.
     *
     * @param  mixed $plugin
     * @return void
     * @throws Exception\RuntimeException if invalid
     */
    abstract public function validatePlugin($plugin);

    /**
     * Retrieve a service from the manager by name
     *
     * Allows passing an array of options to use when creating the instance.
     * createFromInvokable() will use these and pass them to the instance
     * constructor if not null and a non-empty array.
     *
     * @param  string $name
     * @param  array $options
     * @param  bool $usePeeringServiceManagers
     * @return object
     */
    public function get($name, $options = array(), $usePeeringServiceManagers = true)
    {
        // Allow specifying a class name directly; registers as an invokable class
        if (!$this->has($name) && $this->autoAddInvokableClass && class_exists($name)) {
            $this->setInvokableClass($name, $name);
        }

        $this->creationOptions = $options;
        $instance = parent::get($name, $usePeeringServiceManagers);
        $this->creationOptions = null;
        $this->validatePlugin($instance);
        return $instance;
    }

    /**
     * Register a service with the locator.
     *
     * Validates that the service object via validatePlugin() prior to
     * attempting to register it.
     *
     * @param  string $name
     * @param  mixed $service
     * @param  bool $shared
     * @return AbstractPluginManager
     * @throws Exception\InvalidServiceNameException
     */
    public function setService($name, $service, $shared = true)
    {
        if ($service) {
            $this->validatePlugin($service);
        }
        parent::setService($name, $service, $shared);
        return $this;
    }

    /**
     * Set the main service locator so factories can have access to it to pull deps
     *
     * @param ServiceLocatorInterface $serviceLocator
     * @return AbstractPluginManager
     */
    public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
    {
        $this->serviceLocator = $serviceLocator;
        return $this;
    }

    /**
     * Get the main plugin manager. Useful for fetching dependencies from within factories.
     *
     * @return mixed
     */
    public function getServiceLocator()
    {
        return $this->serviceLocator;
    }

    /**
     * Attempt to create an instance via an invokable class
     *
     * Overrides parent implementation by passing $creationOptions to the
     * constructor, if non-null.
     *
     * @param  string $canonicalName
     * @param  string $requestedName
     * @return null|\stdClass
     * @throws Exception\ServiceNotCreatedException If resolved class does not exist
     */
    protected function createFromInvokable($canonicalName, $requestedName)
    {
        $invokable = $this->invokableClasses[$canonicalName];

        if (null === $this->creationOptions
            || (is_array($this->creationOptions) && empty($this->creationOptions))
        ) {
            $instance = new $invokable();
        } else {
            $instance = new $invokable($this->creationOptions);
        }

        return $instance;
    }

    /**
     * Attempt to create an instance via a factory class
     *
     * Overrides parent implementation by passing $creationOptions to the
     * constructor, if non-null.
     *
     * @param  string $canonicalName
     * @param  string $requestedName
     * @return mixed
     * @throws Exception\ServiceNotCreatedException If factory is not callable
     */
    protected function createFromFactory($canonicalName, $requestedName)
    {
        $factory            = $this->factories[$canonicalName];
        $hasCreationOptions = !(null === $this->creationOptions || (is_array($this->creationOptions) && empty($this->creationOptions)));

        if (is_string($factory) && class_exists($factory, true)) {
            if (!$hasCreationOptions) {
                $factory = new $factory();
            } else {
                $factory = new $factory($this->creationOptions);
            }

            $this->factories[$canonicalName] = $factory;
        }

        if ($factory instanceof FactoryInterface) {
            $instance = $this->createServiceViaCallback(array($factory, 'createService'), $canonicalName, $requestedName);
        } elseif (is_callable($factory)) {
            $instance = $this->createServiceViaCallback($factory, $canonicalName, $requestedName);
        } else {
            throw new Exception\ServiceNotCreatedException(sprintf(
                'While attempting to create %s%s an invalid factory was registered for this instance type.', $canonicalName, ($requestedName ? '(alias: ' . $requestedName . ')' : '')
            ));
        }

        return $instance;
    }

    /**
     * Create service via callback
     *
     * @param  callable $callable
     * @param  string   $cName
     * @param  string   $rName
     * @throws Exception\ServiceNotCreatedException
     * @throws Exception\ServiceNotFoundException
     * @throws Exception\CircularDependencyFoundException
     * @return object
     */
    protected function createServiceViaCallback($callable, $cName, $rName)
    {
        if (is_object($callable)) {
            $factory = $callable;
        } elseif (is_array($callable)) {
            // reset both rewinds and returns the value of the first array element
            $factory = reset($callable);
        }

        if (isset($factory)
            && ($factory instanceof MutableCreationOptionsInterface)
            && is_array($this->creationOptions)
            && !empty($this->creationOptions)
        ) {
            $factory->setCreationOptions($this->creationOptions);
        }

        return parent::createServiceViaCallback($callable, $cName, $rName);
    }
}
{
    "name": "zendframework/zend-eventmanager",
    "description": " ",
    "license": "BSD-3-Clause",
    "keywords": [
        "zf2",
        "eventmanager"
    ],
    "autoload": {
        "psr-0": {
            "Zend\\EventManager\\": ""
        }
    },
    "target-dir": "Zend/EventManager",
    "require": {
        "php": ">=5.3.3",
        "zendframework/zend-stdlib": "self.version"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "2.2-dev",
            "dev-develop": "2.3-dev"
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\EventManager;

/**
 * Interface providing events that can be attached, detached and triggered.
 */
interface EventsCapableInterface
{
    /**
     * Retrieve the event manager
     *
     * Lazy-loads an EventManager instance if none registered.
     *
     * @return EventManagerInterface
     */
    public function getEventManager();
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\EventManager;

use Zend\Stdlib\CallbackHandler;

/**
 * FilterChain: intercepting filter manager
 */
class FilterChain implements Filter\FilterInterface
{
    /**
     * @var Filter\FilterIterator All filters
     */
    protected $filters;

    /**
     * Constructor
     *
     * Initializes Filter\FilterIterator in which filters will be aggregated
     */
    public function __construct()
    {
        $this->filters = new Filter\FilterIterator();
    }

    /**
     * Apply the filters
     *
     * Begins iteration of the filters.
     *
     * @param  mixed $context Object under observation
     * @param  mixed $argv Associative array of arguments
     * @return mixed
     */
    public function run($context, array $argv = array())
    {
        $chain = clone $this->getFilters();

        if ($chain->isEmpty()) {
            return;
        }

        $next = $chain->extract();
        if (!$next instanceof CallbackHandler) {
            return;
        }

        return call_user_func($next->getCallback(), $context, $argv, $chain);
    }

    /**
     * Connect a filter to the chain
     *
     * @param  callable $callback PHP Callback
     * @param  int $priority Priority in the queue at which to execute; defaults to 1 (higher numbers == higher priority)
     * @return CallbackHandler (to allow later unsubscribe)
     * @throws Exception\InvalidCallbackException
     */
    public function attach($callback, $priority = 1)
    {
        if (empty($callback)) {
            throw new Exception\InvalidCallbackException('No callback provided');
        }
        $filter = new CallbackHandler($callback, array('priority' => $priority));
        $this->filters->insert($filter, $priority);
        return $filter;
    }

    /**
     * Detach a filter from the chain
     *
     * @param  CallbackHandler $filter
     * @return bool Returns true if filter found and unsubscribed; returns false otherwise
     */
    public function detach(CallbackHandler $filter)
    {
        return $this->filters->remove($filter);
    }

    /**
     * Retrieve all filters
     *
     * @return Filter\FilterIterator
     */
    public function getFilters()
    {
        return $this->filters;
    }

    /**
     * Clear all filters
     *
     * @return void
     */
    public function clearFilters()
    {
        $this->filters = new Filter\FilterIterator();
    }

    /**
     * Return current responses
     *
     * Only available while the chain is still being iterated. Returns the
     * current ResponseCollection.
     *
     * @return null|ResponseCollection
     */
    public function getResponses()
    {
        return null;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\EventManager;

/**
 * Interface to automate setter injection for a SharedEventManagerInterface instance
 */
interface SharedEventManagerAwareInterface
{
    /**
     * Inject a SharedEventManager instance
     *
     * @param  SharedEventManagerInterface $sharedEventManager
     * @return SharedEventManagerAwareInterface
     */
    public function setSharedManager(SharedEventManagerInterface $sharedEventManager);

    /**
     * Get shared collections container
     *
     * @return SharedEventManagerInterface
     */
    public function getSharedManager();

    /**
     * Remove any shared collections
     *
     * @return void
     */
    public function unsetSharedManager();
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\EventManager;

/**
 * Provides logic to easily create aggregate listeners, without worrying about
 * manually detaching events
 */
trait ListenerAggregateTrait
{
    /**
     * @var \Zend\Stdlib\CallbackHandler[]
     */
    protected $listeners = array();

    /**
     * {@inheritDoc}
     */
    public function detach(EventManagerInterface $events)
    {
        foreach ($this->listeners as $index => $callback) {
            if ($events->detach($callback)) {
                unset($this->listeners[$index]);
            }
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\EventManager;

use ArrayAccess;
use ArrayObject;
use Traversable;
use Zend\Stdlib\CallbackHandler;
use Zend\Stdlib\PriorityQueue;

/**
 * Event manager: notification system
 *
 * Use the EventManager when you want to create a per-instance notification
 * system for your objects.
 */
class EventManager implements EventManagerInterface
{
    /**
     * Subscribed events and their listeners
     * @var array Array of PriorityQueue objects
     */
    protected $events = array();

    /**
     * @var string Class representing the event being emitted
     */
    protected $eventClass = 'Zend\EventManager\Event';

    /**
     * Identifiers, used to pull shared signals from SharedEventManagerInterface instance
     * @var array
     */
    protected $identifiers = array();

    /**
     * Shared event manager
     * @var false|null|SharedEventManagerInterface
     */
    protected $sharedManager = null;

    /**
     * Constructor
     *
     * Allows optionally specifying identifier(s) to use to pull signals from a
     * SharedEventManagerInterface.
     *
     * @param  null|string|int|array|Traversable $identifiers
     */
    public function __construct($identifiers = null)
    {
        $this->setIdentifiers($identifiers);
    }

    /**
     * Set the event class to utilize
     *
     * @param  string $class
     * @return EventManager
     */
    public function setEventClass($class)
    {
        $this->eventClass = $class;
        return $this;
    }

    /**
     * Set shared event manager
     *
     * @param SharedEventManagerInterface $sharedEventManager
     * @return EventManager
     */
    public function setSharedManager(SharedEventManagerInterface $sharedEventManager)
    {
        $this->sharedManager = $sharedEventManager;
        StaticEventManager::setInstance($sharedEventManager);
        return $this;
    }

    /**
     * Remove any shared event manager currently attached
     *
     * @return void
     */
    public function unsetSharedManager()
    {
        $this->sharedManager = false;
    }

    /**
     * Get shared event manager
     *
     * If one is not defined, but we have a static instance in
     * StaticEventManager, that one will be used and set in this instance.
     *
     * If none is available in the StaticEventManager, a boolean false is
     * returned.
     *
     * @return false|SharedEventManagerInterface
     */
    public function getSharedManager()
    {
        // "false" means "I do not want a shared manager; don't try and fetch one"
        if (false === $this->sharedManager
            || $this->sharedManager instanceof SharedEventManagerInterface
        ) {
            return $this->sharedManager;
        }

        if (!StaticEventManager::hasInstance()) {
            return false;
        }

        $this->sharedManager = StaticEventManager::getInstance();
        return $this->sharedManager;
    }

    /**
     * Get the identifier(s) for this EventManager
     *
     * @return array
     */
    public function getIdentifiers()
    {
        return $this->identifiers;
    }

    /**
     * Set the identifiers (overrides any currently set identifiers)
     *
     * @param string|int|array|Traversable $identifiers
     * @return EventManager Provides a fluent interface
     */
    public function setIdentifiers($identifiers)
    {
        if (is_array($identifiers) || $identifiers instanceof Traversable) {
            $this->identifiers = array_unique((array) $identifiers);
        } elseif ($identifiers !== null) {
            $this->identifiers = array($identifiers);
        }
        return $this;
    }

    /**
     * Add some identifier(s) (appends to any currently set identifiers)
     *
     * @param string|int|array|Traversable $identifiers
     * @return EventManager Provides a fluent interface
     */
    public function addIdentifiers($identifiers)
    {
        if (is_array($identifiers) || $identifiers instanceof Traversable) {
            $this->identifiers = array_unique(array_merge($this->identifiers, (array) $identifiers));
        } elseif ($identifiers !== null) {
            $this->identifiers = array_unique(array_merge($this->identifiers, array($identifiers)));
        }
        return $this;
    }

    /**
     * Trigger all listeners for a given event
     *
     * Can emulate triggerUntil() if the last argument provided is a callback.
     *
     * @param  string $event
     * @param  string|object $target Object calling emit, or symbol describing target (such as static method name)
     * @param  array|ArrayAccess $argv Array of arguments; typically, should be associative
     * @param  null|callable $callback
     * @return ResponseCollection All listener return values
     * @throws Exception\InvalidCallbackException
     */
    public function trigger($event, $target = null, $argv = array(), $callback = null)
    {
        if ($event instanceof EventInterface) {
            $e        = $event;
            $event    = $e->getName();
            $callback = $target;
        } elseif ($target instanceof EventInterface) {
            $e = $target;
            $e->setName($event);
            $callback = $argv;
        } elseif ($argv instanceof EventInterface) {
            $e = $argv;
            $e->setName($event);
            $e->setTarget($target);
        } else {
            $e = new $this->eventClass();
            $e->setName($event);
            $e->setTarget($target);
            $e->setParams($argv);
        }

        if ($callback && !is_callable($callback)) {
            throw new Exception\InvalidCallbackException('Invalid callback provided');
        }

        // Initial value of stop propagation flag should be false
        $e->stopPropagation(false);

        return $this->triggerListeners($event, $e, $callback);
    }

    /**
     * Trigger listeners until return value of one causes a callback to
     * evaluate to true
     *
     * Triggers listeners until the provided callback evaluates the return
     * value of one as true, or until all listeners have been executed.
     *
     * @param  string $event
     * @param  string|object $target Object calling emit, or symbol describing target (such as static method name)
     * @param  array|ArrayAccess $argv Array of arguments; typically, should be associative
     * @param  callable $callback
     * @return ResponseCollection
     * @throws Exception\InvalidCallbackException if invalid callable provided
     */
    public function triggerUntil($event, $target, $argv = null, $callback = null)
    {
        if ($event instanceof EventInterface) {
            $e        = $event;
            $event    = $e->getName();
            $callback = $target;
        } elseif ($target instanceof EventInterface) {
            $e = $target;
            $e->setName($event);
            $callback = $argv;
        } elseif ($argv instanceof EventInterface) {
            $e = $argv;
            $e->setName($event);
            $e->setTarget($target);
        } else {
            $e = new $this->eventClass();
            $e->setName($event);
            $e->setTarget($target);
            $e->setParams($argv);
        }

        if (!is_callable($callback)) {
            throw new Exception\InvalidCallbackException('Invalid callback provided');
        }

        // Initial value of stop propagation flag should be false
        $e->stopPropagation(false);

        return $this->triggerListeners($event, $e, $callback);
    }

    /**
     * Attach a listener to an event
     *
     * The first argument is the event, and the next argument describes a
     * callback that will respond to that event. A CallbackHandler instance
     * describing the event listener combination will be returned.
     *
     * The last argument indicates a priority at which the event should be
     * executed. By default, this value is 1; however, you may set it for any
     * integer value. Higher values have higher priority (i.e., execute first).
     *
     * You can specify "*" for the event name. In such cases, the listener will
     * be triggered for every event.
     *
     * @param  string|array|ListenerAggregateInterface $event An event or array of event names. If a ListenerAggregateInterface, proxies to {@link attachAggregate()}.
     * @param  callable|int $callback If string $event provided, expects PHP callback; for a ListenerAggregateInterface $event, this will be the priority
     * @param  int $priority If provided, the priority at which to register the callable
     * @return CallbackHandler|mixed CallbackHandler if attaching callable (to allow later unsubscribe); mixed if attaching aggregate
     * @throws Exception\InvalidArgumentException
     */
    public function attach($event, $callback = null, $priority = 1)
    {
        // Proxy ListenerAggregateInterface arguments to attachAggregate()
        if ($event instanceof ListenerAggregateInterface) {
            return $this->attachAggregate($event, $callback);
        }

        // Null callback is invalid
        if (null === $callback) {
            throw new Exception\InvalidArgumentException(sprintf(
                '%s: expects a callback; none provided',
                __METHOD__
            ));
        }

        // Array of events should be registered individually, and return an array of all listeners
        if (is_array($event)) {
            $listeners = array();
            foreach ($event as $name) {
                $listeners[] = $this->attach($name, $callback, $priority);
            }
            return $listeners;
        }

        // If we don't have a priority queue for the event yet, create one
        if (empty($this->events[$event])) {
            $this->events[$event] = new PriorityQueue();
        }

        // Create a callback handler, setting the event and priority in its metadata
        $listener = new CallbackHandler($callback, array('event' => $event, 'priority' => $priority));

        // Inject the callback handler into the queue
        $this->events[$event]->insert($listener, $priority);
        return $listener;
    }

    /**
     * Attach a listener aggregate
     *
     * Listener aggregates accept an EventManagerInterface instance, and call attach()
     * one or more times, typically to attach to multiple events using local
     * methods.
     *
     * @param  ListenerAggregateInterface $aggregate
     * @param  int $priority If provided, a suggested priority for the aggregate to use
     * @return mixed return value of {@link ListenerAggregateInterface::attach()}
     */
    public function attachAggregate(ListenerAggregateInterface $aggregate, $priority = 1)
    {
        return $aggregate->attach($this, $priority);
    }

    /**
     * Unsubscribe a listener from an event
     *
     * @param  CallbackHandler|ListenerAggregateInterface $listener
     * @return bool Returns true if event and listener found, and unsubscribed; returns false if either event or listener not found
     * @throws Exception\InvalidArgumentException if invalid listener provided
     */
    public function detach($listener)
    {
        if ($listener instanceof ListenerAggregateInterface) {
            return $this->detachAggregate($listener);
        }

        if (!$listener instanceof CallbackHandler) {
            throw new Exception\InvalidArgumentException(sprintf(
                '%s: expected a ListenerAggregateInterface or CallbackHandler; received "%s"',
                __METHOD__,
                (is_object($listener) ? get_class($listener) : gettype($listener))
            ));
        }

        $event = $listener->getMetadatum('event');
        if (!$event || empty($this->events[$event])) {
            return false;
        }
        $return = $this->events[$event]->remove($listener);
        if (!$return) {
            return false;
        }
        if (!count($this->events[$event])) {
            unset($this->events[$event]);
        }
        return true;
    }

    /**
     * Detach a listener aggregate
     *
     * Listener aggregates accept an EventManagerInterface instance, and call detach()
     * of all previously attached listeners.
     *
     * @param  ListenerAggregateInterface $aggregate
     * @return mixed return value of {@link ListenerAggregateInterface::detach()}
     */
    public function detachAggregate(ListenerAggregateInterface $aggregate)
    {
        return $aggregate->detach($this);
    }

    /**
     * Retrieve all registered events
     *
     * @return array
     */
    public function getEvents()
    {
        return array_keys($this->events);
    }

    /**
     * Retrieve all listeners for a given event
     *
     * @param  string $event
     * @return PriorityQueue
     */
    public function getListeners($event)
    {
        if (!array_key_exists($event, $this->events)) {
            return new PriorityQueue();
        }
        return $this->events[$event];
    }

    /**
     * Clear all listeners for a given event
     *
     * @param  string $event
     * @return void
     */
    public function clearListeners($event)
    {
        if (!empty($this->events[$event])) {
            unset($this->events[$event]);
        }
    }

    /**
     * Prepare arguments
     *
     * Use this method if you want to be able to modify arguments from within a
     * listener. It returns an ArrayObject of the arguments, which may then be
     * passed to trigger() or triggerUntil().
     *
     * @param  array $args
     * @return ArrayObject
     */
    public function prepareArgs(array $args)
    {
        return new ArrayObject($args);
    }

    /**
     * Trigger listeners
     *
     * Actual functionality for triggering listeners, to which both trigger() and triggerUntil()
     * delegate.
     *
     * @param  string           $event Event name
     * @param  EventInterface $e
     * @param  null|callable    $callback
     * @return ResponseCollection
     */
    protected function triggerListeners($event, EventInterface $e, $callback = null)
    {
        $responses = new ResponseCollection;
        $listeners = $this->getListeners($event);

        // Add shared/wildcard listeners to the list of listeners,
        // but don't modify the listeners object
        $sharedListeners         = $this->getSharedListeners($event);
        $sharedWildcardListeners = $this->getSharedListeners('*');
        $wildcardListeners       = $this->getListeners('*');
        if (count($sharedListeners) || count($sharedWildcardListeners) || count($wildcardListeners)) {
            $listeners = clone $listeners;

            // Shared listeners on this specific event
            $this->insertListeners($listeners, $sharedListeners);

            // Shared wildcard listeners
            $this->insertListeners($listeners, $sharedWildcardListeners);

            // Add wildcard listeners
            $this->insertListeners($listeners, $wildcardListeners);
        }

        foreach ($listeners as $listener) {
            $listenerCallback = $listener->getCallback();

            // Trigger the listener's callback, and push its result onto the
            // response collection
            $responses->push(call_user_func($listenerCallback, $e));

            // If the event was asked to stop propagating, do so
            if ($e->propagationIsStopped()) {
                $responses->setStopped(true);
                break;
            }

            // If the result causes our validation callback to return true,
            // stop propagation
            if ($callback && call_user_func($callback, $responses->last())) {
                $responses->setStopped(true);
                break;
            }
        }

        return $responses;
    }

    /**
     * Get list of all listeners attached to the shared event manager for
     * identifiers registered by this instance
     *
     * @param  string $event
     * @return array
     */
    protected function getSharedListeners($event)
    {
        if (!$sharedManager = $this->getSharedManager()) {
            return array();
        }

        $identifiers     = $this->getIdentifiers();
        //Add wildcard id to the search, if not already added
        if (!in_array('*', $identifiers)) {
            $identifiers[] = '*';
        }
        $sharedListeners = array();

        foreach ($identifiers as $id) {
            if (!$listeners = $sharedManager->getListeners($id, $event)) {
                continue;
            }

            if (!is_array($listeners) && !($listeners instanceof Traversable)) {
                continue;
            }

            foreach ($listeners as $listener) {
                if (!$listener instanceof CallbackHandler) {
                    continue;
                }
                $sharedListeners[] = $listener;
            }
        }

        return $sharedListeners;
    }

    /**
     * Add listeners to the master queue of listeners
     *
     * Used to inject shared listeners and wildcard listeners.
     *
     * @param  PriorityQueue $masterListeners
     * @param  PriorityQueue $listeners
     * @return void
     */
    protected function insertListeners($masterListeners, $listeners)
    {
        foreach ($listeners as $listener) {
            $priority = $listener->getMetadatum('priority');
            if (null === $priority) {
                $priority = 1;
            } elseif (is_array($priority)) {
                // If we have an array, likely using PriorityQueue. Grab first
                // element of the array, as that's the actual priority.
                $priority = array_shift($priority);
            }
            $masterListeners->insert($listener, $priority);
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\EventManager;

/**
 * Interface to automate setter injection for an EventManager instance
 */
interface EventManagerAwareInterface extends EventsCapableInterface
{
    /**
     * Inject an EventManager instance
     *
     * @param  EventManagerInterface $eventManager
     * @return void
     */
    public function setEventManager(EventManagerInterface $eventManager);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\EventManager;

/**
 * Interface for self-registering event listeners.
 *
 * Classes implementing this interface may be registered by name or instance
 * with an SharedEventManager, without an event name. The {@link attach()} method will
 * then be called with the current SharedEventManager instance, allowing the class to
 * wire up one or more listeners.
 */
interface SharedListenerAggregateInterface
{
    /**
     * Attach one or more listeners
     *
     * Implementors may add an optional $priority argument; the SharedEventManager
     * implementation will pass this to the aggregate.
     *
     * @param SharedEventManagerInterface $events
     */
    public function attachShared(SharedEventManagerInterface $events);

    /**
     * Detach all previously attached listeners
     *
     * @param SharedEventManagerInterface $events
     */
    public function detachShared(SharedEventManagerInterface $events);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\EventManager;


/**
 * Abstract aggregate listener
 */
abstract class AbstractListenerAggregate implements ListenerAggregateInterface
{
    /**
     * @var \Zend\Stdlib\CallbackHandler[]
     */
    protected $listeners = array();

    /**
     * {@inheritDoc}
     */
    public function detach(EventManagerInterface $events)
    {
        foreach ($this->listeners as $index => $callback) {
            if ($events->detach($callback)) {
                unset($this->listeners[$index]);
            }
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\EventManager;

use Zend\Stdlib\CallbackHandler;
use Zend\Stdlib\PriorityQueue;

/**
 * Event manager: notification system
 *
 * Use the EventManager when you want to create a per-instance notification
 * system for your objects.
 */
class GlobalEventManager
{
    /**
     * @var EventManagerInterface
     */
    protected static $events;

    /**
     * Set the event collection on which this will operate
     *
     * @param  null|EventManagerInterface $events
     * @return void
     */
    public static function setEventCollection(EventManagerInterface $events = null)
    {
        static::$events = $events;
    }

    /**
     * Get event collection on which this operates
     *
     * @return EventManagerInterface
     */
    public static function getEventCollection()
    {
        if (null === static::$events) {
            static::setEventCollection(new EventManager());
        }
        return static::$events;
    }

    /**
     * Trigger an event
     *
     * @param  string $event
     * @param  object|string $context
     * @param  array|object $argv
     * @return ResponseCollection
     */
    public static function trigger($event, $context, $argv = array())
    {
        return static::getEventCollection()->trigger($event, $context, $argv);
    }

    /**
     * Trigger listeners until return value of one causes a callback to evaluate
     * to true.
     *
     * @param  string $event
     * @param  string|object $context
     * @param  array|object $argv
     * @param  callable $callback
     * @return ResponseCollection
     */
    public static function triggerUntil($event, $context, $argv, $callback)
    {
        return static::getEventCollection()->triggerUntil($event, $context, $argv, $callback);
    }

    /**
     * Attach a listener to an event
     *
     * @param  string $event
     * @param  callable $callback
     * @param  int $priority
     * @return CallbackHandler
     */
    public static function attach($event, $callback, $priority = 1)
    {
        return static::getEventCollection()->attach($event, $callback, $priority);
    }

    /**
     * Detach a callback from a listener
     *
     * @param  CallbackHandler $listener
     * @return bool
     */
    public static function detach(CallbackHandler $listener)
    {
        return static::getEventCollection()->detach($listener);
    }

    /**
     * Retrieve list of events this object manages
     *
     * @return array
     */
    public static function getEvents()
    {
        return static::getEventCollection()->getEvents();
    }

    /**
     * Retrieve all listeners for a given event
     *
     * @param  string $event
     * @return PriorityQueue|array
     */
    public static function getListeners($event)
    {
        return static::getEventCollection()->getListeners($event);
    }

    /**
     * Clear all listeners for a given event
     *
     * @param  string $event
     * @return void
     */
    public static function clearListeners($event)
    {
        static::getEventCollection()->clearListeners($event);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\EventManager;

use Zend\Stdlib\CallbackHandler;
use Zend\Stdlib\PriorityQueue;

/**
 * Interface for shared event listener collections
 */
interface SharedEventManagerInterface
{
    /**
     * Retrieve all listeners for a given identifier and event
     *
     * @param  string|int $id
     * @param  string|int $event
     * @return false|PriorityQueue
     */
    public function getListeners($id, $event);

    /**
     * Attach a listener to an event
     *
     * @param  string|array $id Identifier(s) for event emitting component(s)
     * @param  string $event
     * @param  callable $callback PHP Callback
     * @param  int $priority Priority at which listener should execute
     * @return void
     */
    public function attach($id, $event, $callback, $priority = 1);

    /**
     * Detach a listener from an event offered by a given resource
     *
     * @param  string|int $id
     * @param  CallbackHandler $listener
     * @return bool Returns true if event and listener found, and unsubscribed; returns false if either event or listener not found
     */
    public function detach($id, CallbackHandler $listener);

    /**
     * Retrieve all registered events for a given resource
     *
     * @param  string|int $id
     * @return array
     */
    public function getEvents($id);

    /**
     * Clear all listeners for a given identifier, optionally for a specific event
     *
     * @param  string|int $id
     * @param  null|string $event
     * @return bool
     */
    public function clearListeners($id, $event = null);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\EventManager\Filter;

use Zend\Stdlib\CallbackHandler;
use Zend\Stdlib\SplPriorityQueue;

/**
 * Specialized priority queue implementation for use with an intercepting
 * filter chain.
 *
 * Allows removal
 */
class FilterIterator extends SplPriorityQueue
{
    /**
     * Does the queue contain a given value?
     *
     * @param  mixed $datum
     * @return bool
     */
    public function contains($datum)
    {
        $chain = clone $this;
        foreach ($chain as $item) {
            if ($item === $datum) {
                return true;
            }
        }
        return false;
    }

    /**
     * Remove a value from the queue
     *
     * This is an expensive operation. It must first iterate through all values,
     * and then re-populate itself. Use only if absolutely necessary.
     *
     * @param  mixed $datum
     * @return bool
     */
    public function remove($datum)
    {
        $this->setExtractFlags(self::EXTR_BOTH);

        // Iterate and remove any matches
        $removed = false;
        $items   = array();
        $this->rewind();
        while (!$this->isEmpty()) {
            $item = $this->extract();
            if ($item['data'] === $datum) {
                $removed = true;
                continue;
            }
            $items[] = $item;
        }

        // Repopulate
        foreach ($items as $item) {
            $this->insert($item['data'], $item['priority']);
        }

        $this->setExtractFlags(self::EXTR_DATA);
        return $removed;
    }

    /**
     * Iterate the next filter in the chain
     *
     * Iterates and calls the next filter in the chain.
     *
     * @param  mixed $context
     * @param  array $params
     * @param  FilterIterator $chain
     * @return mixed
     */
    public function next($context = null, array $params = array(), $chain = null)
    {
        if (empty($context) || $chain->isEmpty()) {
            return;
        }

        $next = $this->extract();
        if (!$next instanceof CallbackHandler) {
            return;
        }

        $return = call_user_func($next->getCallback(), $context, $params, $chain);
        return $return;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\EventManager\Filter;

use Zend\EventManager\ResponseCollection;
use Zend\Stdlib\CallbackHandler;

/**
 * Interface for intercepting filter chains
 */
interface FilterInterface
{
    /**
     * Execute the filter chain
     *
     * @param  string|object $context
     * @param  array $params
     * @return mixed
     */
    public function run($context, array $params = array());

    /**
     * Attach an intercepting filter
     *
     * @param  callable $callback
     * @return CallbackHandler
     */
    public function attach($callback);

    /**
     * Detach an intercepting filter
     *
     * @param  CallbackHandler $filter
     * @return bool
     */
    public function detach(CallbackHandler $filter);

    /**
     * Get all intercepting filters
     *
     * @return array
     */
    public function getFilters();

    /**
     * Clear all filters
     *
     * @return void
     */
    public function clearFilters();

    /**
     * Get all filter responses
     *
     * @return ResponseCollection
     */
    public function getResponses();
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\EventManager;

use Traversable;

/**
 * A trait for objects that provide events
 */
trait ProvidesEvents
{
    /**
     * @var EventManagerInterface
     */
    protected $events;

    /**
     * Set the event manager instance used by this context
     *
     * @param  EventManagerInterface $events
     * @return mixed
     */
    public function setEventManager(EventManagerInterface $events)
    {
        $identifiers = array(__CLASS__, get_class($this));
        if (isset($this->eventIdentifier)) {
            if ((is_string($this->eventIdentifier))
                || (is_array($this->eventIdentifier))
                || ($this->eventIdentifier instanceof Traversable)
            ) {
                $identifiers = array_unique(array_merge($identifiers, (array) $this->eventIdentifier));
            } elseif (is_object($this->eventIdentifier)) {
                $identifiers[] = $this->eventIdentifier;
            }
            // silently ignore invalid eventIdentifier types
        }
        $events->setIdentifiers($identifiers);
        $this->events = $events;
        return $this;
    }

    /**
     * Retrieve the event manager
     *
     * Lazy-loads an EventManager instance if none registered.
     *
     * @return EventManagerInterface
     */
    public function getEventManager()
    {
        if (!$this->events instanceof EventManagerInterface) {
            $this->setEventManager(new EventManager());
        }
        return $this->events;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\EventManager;

use Traversable;
use Zend\Stdlib\CallbackHandler;

/**
 * Interface for messengers
 */
interface EventManagerInterface extends SharedEventManagerAwareInterface
{
    /**
     * Trigger an event
     *
     * Should allow handling the following scenarios:
     * - Passing Event object only
     * - Passing event name and Event object only
     * - Passing event name, target, and Event object
     * - Passing event name, target, and array|ArrayAccess of arguments
     *
     * Can emulate triggerUntil() if the last argument provided is a callback.
     *
     * @param  string $event
     * @param  object|string $target
     * @param  array|object $argv
     * @param  null|callable $callback
     * @return ResponseCollection
     */
    public function trigger($event, $target = null, $argv = array(), $callback = null);

    /**
     * Trigger an event until the given callback returns a boolean false
     *
     * Should allow handling the following scenarios:
     * - Passing Event object and callback only
     * - Passing event name, Event object, and callback only
     * - Passing event name, target, Event object, and callback
     * - Passing event name, target, array|ArrayAccess of arguments, and callback
     *
     * @param  string $event
     * @param  object|string $target
     * @param  array|object $argv
     * @param  callable $callback
     * @return ResponseCollection
     */
    public function triggerUntil($event, $target, $argv = null, $callback = null);

    /**
     * Attach a listener to an event
     *
     * @param  string $event
     * @param  callable $callback
     * @param  int $priority Priority at which to register listener
     * @return CallbackHandler
     */
    public function attach($event, $callback = null, $priority = 1);

    /**
     * Detach an event listener
     *
     * @param  CallbackHandler|ListenerAggregateInterface $listener
     * @return bool
     */
    public function detach($listener);

    /**
     * Get a list of events for which this collection has listeners
     *
     * @return array
     */
    public function getEvents();

    /**
     * Retrieve a list of listeners registered to a given event
     *
     * @param  string $event
     * @return array|object
     */
    public function getListeners($event);

    /**
     * Clear all listeners for a given event
     *
     * @param  string $event
     * @return void
     */
    public function clearListeners($event);

    /**
     * Set the event class to utilize
     *
     * @param  string $class
     * @return EventManagerInterface
     */
    public function setEventClass($class);

    /**
     * Get the identifier(s) for this EventManager
     *
     * @return array
     */
    public function getIdentifiers();

    /**
     * Set the identifiers (overrides any currently set identifiers)
     *
     * @param string|int|array|Traversable $identifiers
     * @return EventManagerInterface
     */
    public function setIdentifiers($identifiers);

    /**
     * Add some identifier(s) (appends to any currently set identifiers)
     *
     * @param string|int|array|Traversable $identifiers
     * @return EventManagerInterface
     */
    public function addIdentifiers($identifiers);

    /**
     * Attach a listener aggregate
     *
     * @param  ListenerAggregateInterface $aggregate
     * @param  int $priority If provided, a suggested priority for the aggregate to use
     * @return mixed return value of {@link ListenerAggregateInterface::attach()}
     */
    public function attachAggregate(ListenerAggregateInterface $aggregate, $priority = 1);

    /**
     * Detach a listener aggregate
     *
     * @param  ListenerAggregateInterface $aggregate
     * @return mixed return value of {@link ListenerAggregateInterface::detach()}
     */
    public function detachAggregate(ListenerAggregateInterface $aggregate);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\EventManager;

use Zend\Stdlib\CallbackHandler;
use Zend\Stdlib\PriorityQueue;

/**
 * Shared/contextual EventManager
 *
 * Allows attaching to EMs composed by other classes without having an instance first.
 * The assumption is that the SharedEventManager will be injected into EventManager
 * instances, and then queried for additional listeners when triggering an event.
 */
class SharedEventManager implements
    SharedEventAggregateAwareInterface,
    SharedEventManagerInterface
{
    /**
     * Identifiers with event connections
     * @var array
     */
    protected $identifiers = array();

    /**
     * Attach a listener to an event
     *
     * Allows attaching a callback to an event offered by one or more
     * identifying components. As an example, the following connects to the
     * "getAll" event of both an AbstractResource and EntityResource:
     *
     * <code>
     * $sharedEventManager = new SharedEventManager();
     * $sharedEventManager->attach(
     *     array('My\Resource\AbstractResource', 'My\Resource\EntityResource'),
     *     'getAll',
     *     function ($e) use ($cache) {
     *         if (!$id = $e->getParam('id', false)) {
     *             return;
     *         }
     *         if (!$data = $cache->load(get_class($resource) . '::getOne::' . $id )) {
     *             return;
     *         }
     *         return $data;
     *     }
     * );
     * </code>
     *
     * @param  string|array $id Identifier(s) for event emitting component(s)
     * @param  string $event
     * @param  callable $callback PHP Callback
     * @param  int $priority Priority at which listener should execute
     * @return CallbackHandler|array Either CallbackHandler or array of CallbackHandlers
     */
    public function attach($id, $event, $callback, $priority = 1)
    {
        $ids = (array) $id;
        $listeners = array();
        foreach ($ids as $id) {
            if (!array_key_exists($id, $this->identifiers)) {
                $this->identifiers[$id] = new EventManager($id);
            }
            $listeners[] = $this->identifiers[$id]->attach($event, $callback, $priority);
        }
        if (count($listeners) > 1) {
            return $listeners;
        }
        return $listeners[0];
    }

    /**
     * Attach a listener aggregate
     *
     * Listener aggregates accept an EventManagerInterface instance, and call attachShared()
     * one or more times, typically to attach to multiple events using local
     * methods.
     *
     * @param  SharedListenerAggregateInterface $aggregate
     * @param  int $priority If provided, a suggested priority for the aggregate to use
     * @return mixed return value of {@link ListenerAggregateInterface::attachShared()}
     */
    public function attachAggregate(SharedListenerAggregateInterface $aggregate, $priority = 1)
    {
        return $aggregate->attachShared($this, $priority);
    }

    /**
     * Detach a listener from an event offered by a given resource
     *
     * @param  string|int $id
     * @param  CallbackHandler $listener
     * @return bool Returns true if event and listener found, and unsubscribed; returns false if either event or listener not found
     */
    public function detach($id, CallbackHandler $listener)
    {
        if (!array_key_exists($id, $this->identifiers)) {
            return false;
        }
        return $this->identifiers[$id]->detach($listener);
    }

    /**
     * Detach a listener aggregate
     *
     * Listener aggregates accept an SharedEventManagerInterface instance, and call detachShared()
     * of all previously attached listeners.
     *
     * @param  SharedListenerAggregateInterface $aggregate
     * @return mixed return value of {@link SharedListenerAggregateInterface::detachShared()}
     */
    public function detachAggregate(SharedListenerAggregateInterface $aggregate)
    {
        return $aggregate->detachShared($this);
    }

    /**
     * Retrieve all registered events for a given resource
     *
     * @param  string|int $id
     * @return array
     */
    public function getEvents($id)
    {
        if (!array_key_exists($id, $this->identifiers)) {
            //Check if there are any id wildcards listeners
            if ('*' != $id && array_key_exists('*', $this->identifiers)) {
                return $this->identifiers['*']->getEvents();
            }
            return false;
        }
        return $this->identifiers[$id]->getEvents();
    }

    /**
     * Retrieve all listeners for a given identifier and event
     *
     * @param  string|int $id
     * @param  string|int $event
     * @return false|PriorityQueue
     */
    public function getListeners($id, $event)
    {
        if (!array_key_exists($id, $this->identifiers)) {
            return false;
        }
        return $this->identifiers[$id]->getListeners($event);
    }

    /**
     * Clear all listeners for a given identifier, optionally for a specific event
     *
     * @param  string|int $id
     * @param  null|string $event
     * @return bool
     */
    public function clearListeners($id, $event = null)
    {
        if (!array_key_exists($id, $this->identifiers)) {
            return false;
        }

        if (null === $event) {
            unset($this->identifiers[$id]);
            return true;
        }

        return $this->identifiers[$id]->clearListeners($event);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\EventManager;

use ArrayAccess;

/**
 * Representation of an event
 *
 * Encapsulates the target context and parameters passed, and provides some
 * behavior for interacting with the event manager.
 */
class Event implements EventInterface
{
    /**
     * @var string Event name
     */
    protected $name;

    /**
     * @var string|object The event target
     */
    protected $target;

    /**
     * @var array|ArrayAccess|object The event parameters
     */
    protected $params = array();

    /**
     * @var bool Whether or not to stop propagation
     */
    protected $stopPropagation = false;

    /**
     * Constructor
     *
     * Accept a target and its parameters.
     *
     * @param  string $name Event name
     * @param  string|object $target
     * @param  array|ArrayAccess $params
     */
    public function __construct($name = null, $target = null, $params = null)
    {
        if (null !== $name) {
            $this->setName($name);
        }

        if (null !== $target) {
            $this->setTarget($target);
        }

        if (null !== $params) {
            $this->setParams($params);
        }
    }

    /**
     * Get event name
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Get the event target
     *
     * This may be either an object, or the name of a static method.
     *
     * @return string|object
     */
    public function getTarget()
    {
        return $this->target;
    }

    /**
     * Set parameters
     *
     * Overwrites parameters
     *
     * @param  array|ArrayAccess|object $params
     * @return Event
     * @throws Exception\InvalidArgumentException
     */
    public function setParams($params)
    {
        if (!is_array($params) && !is_object($params)) {
            throw new Exception\InvalidArgumentException(sprintf(
                'Event parameters must be an array or object; received "%s"', gettype($params)
            ));
        }

        $this->params = $params;
        return $this;
    }

    /**
     * Get all parameters
     *
     * @return array|object|ArrayAccess
     */
    public function getParams()
    {
        return $this->params;
    }

    /**
     * Get an individual parameter
     *
     * If the parameter does not exist, the $default value will be returned.
     *
     * @param  string|int $name
     * @param  mixed $default
     * @return mixed
     */
    public function getParam($name, $default = null)
    {
        // Check in params that are arrays or implement array access
        if (is_array($this->params) || $this->params instanceof ArrayAccess) {
            if (!isset($this->params[$name])) {
                return $default;
            }

            return $this->params[$name];
        }

        // Check in normal objects
        if (!isset($this->params->{$name})) {
            return $default;
        }
        return $this->params->{$name};
    }

    /**
     * Set the event name
     *
     * @param  string $name
     * @return Event
     */
    public function setName($name)
    {
        $this->name = (string) $name;
        return $this;
    }

    /**
     * Set the event target/context
     *
     * @param  null|string|object $target
     * @return Event
     */
    public function setTarget($target)
    {
        $this->target = $target;
        return $this;
    }

    /**
     * Set an individual parameter to a value
     *
     * @param  string|int $name
     * @param  mixed $value
     * @return Event
     */
    public function setParam($name, $value)
    {
        if (is_array($this->params) || $this->params instanceof ArrayAccess) {
            // Arrays or objects implementing array access
            $this->params[$name] = $value;
        } else {
            // Objects
            $this->params->{$name} = $value;
        }
        return $this;
    }

    /**
     * Stop further event propagation
     *
     * @param  bool $flag
     * @return void
     */
    public function stopPropagation($flag = true)
    {
        $this->stopPropagation = (bool) $flag;
    }

    /**
     * Is propagation stopped?
     *
     * @return bool
     */
    public function propagationIsStopped()
    {
        return $this->stopPropagation;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\EventManager;

use SplStack;

/**
 * Collection of signal handler return values
 */
class ResponseCollection extends SplStack
{
    protected $stopped = false;

    /**
     * Did the last response provided trigger a short circuit of the stack?
     *
     * @return bool
     */
    public function stopped()
    {
        return $this->stopped;
    }

    /**
     * Mark the collection as stopped (or its opposite)
     *
     * @param  bool $flag
     * @return ResponseCollection
     */
    public function setStopped($flag)
    {
        $this->stopped = (bool) $flag;
        return $this;
    }

    /**
     * Convenient access to the first handler return value.
     *
     * @return mixed The first handler return value
     */
    public function first()
    {
        return parent::bottom();
    }

    /**
     * Convenient access to the last handler return value.
     *
     * If the collection is empty, returns null. Otherwise, returns value
     * returned by last handler.
     *
     * @return mixed The last handler return value
     */
    public function last()
    {
        if (count($this) === 0) {
            return null;
        }
        return parent::top();
    }

    /**
     * Check if any of the responses match the given value.
     *
     * @param  mixed $value The value to look for among responses
     * @return bool
     */
    public function contains($value)
    {
        foreach ($this as $response) {
            if ($response === $value) {
                return true;
            }
        }
        return false;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\EventManager;

use ArrayAccess;

/**
 * Representation of an event
 */
interface EventInterface
{
    /**
     * Get event name
     *
     * @return string
     */
    public function getName();

    /**
     * Get target/context from which event was triggered
     *
     * @return null|string|object
     */
    public function getTarget();

    /**
     * Get parameters passed to the event
     *
     * @return array|ArrayAccess
     */
    public function getParams();

    /**
     * Get a single parameter by name
     *
     * @param  string $name
     * @param  mixed $default Default value to return if parameter does not exist
     * @return mixed
     */
    public function getParam($name, $default = null);

    /**
     * Set the event name
     *
     * @param  string $name
     * @return void
     */
    public function setName($name);

    /**
     * Set the event target/context
     *
     * @param  null|string|object $target
     * @return void
     */
    public function setTarget($target);

    /**
     * Set event parameters
     *
     * @param  string $params
     * @return void
     */
    public function setParams($params);

    /**
     * Set a single parameter by key
     *
     * @param  string $name
     * @param  mixed $value
     * @return void
     */
    public function setParam($name, $value);

    /**
     * Indicate whether or not the parent EventManagerInterface should stop propagating events
     *
     * @param  bool $flag
     * @return void
     */
    public function stopPropagation($flag = true);

    /**
     * Has this event indicated event propagation should stop?
     *
     * @return bool
     */
    public function propagationIsStopped();
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\EventManager\Exception;

/**
 * Invalid argument exception
 */
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\EventManager\Exception;

/**
 * Invalid callback exception
 */
class InvalidCallbackException extends DomainException implements ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\EventManager\Exception;

class DomainException extends \DomainException implements ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\EventManager\Exception;

/**
 * Base exception interface
 */
interface ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\EventManager;

use \Zend\EventManager\ProvidesEvents;

trait EventManagerAwareTrait
{
    use ProvidesEvents;
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\EventManager;

/**
 * Interface for self-registering event listeners.
 *
 * Classes implementing this interface may be registered by name or instance
 * with an EventManager, without an event name. The {@link attach()} method will
 * then be called with the current EventManager instance, allowing the class to
 * wire up one or more listeners.
 */
interface ListenerAggregateInterface
{
    /**
     * Attach one or more listeners
     *
     * Implementors may add an optional $priority argument; the EventManager
     * implementation will pass this to the aggregate.
     *
     * @param EventManagerInterface $events
     *
     * @return void
     */
    public function attach(EventManagerInterface $events);

    /**
     * Detach all previously attached listeners
     *
     * @param EventManagerInterface $events
     *
     * @return void
     */
    public function detach(EventManagerInterface $events);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\EventManager;


/**
 * Static version of EventManager
 */
class StaticEventManager extends SharedEventManager
{
    /**
     * @var StaticEventManager
     */
    protected static $instance;

    /**
     * Singleton
     */
    protected function __construct()
    {
    }

    /**
     * Singleton
     *
     * @return void
     */
    private function __clone()
    {
    }

    /**
     * Retrieve instance
     *
     * @return StaticEventManager
     */
    public static function getInstance()
    {
        if (null === static::$instance) {
            static::setInstance(new static());
        }
        return static::$instance;
    }

    /**
     * Set the singleton to a specific SharedEventManagerInterface instance
     *
     * @param SharedEventManagerInterface $instance
     * @return void
     */
    public static function setInstance(SharedEventManagerInterface $instance)
    {
        static::$instance = $instance;
    }

    /**
     * Is a singleton instance defined?
     *
     * @return bool
     */
    public static function hasInstance()
    {
        return (static::$instance instanceof SharedEventManagerInterface);
    }

    /**
     * Reset the singleton instance
     *
     * @return void
     */
    public static function resetInstance()
    {
        static::$instance = null;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\EventManager;


/**
 * Interface for allowing attachment of shared aggregate listeners.
 */
interface SharedEventAggregateAwareInterface
{
    /**
     * Attach a listener aggregate
     *
     * @param  SharedListenerAggregateInterface $aggregate
     * @param  int $priority If provided, a suggested priority for the aggregate to use
     * @return mixed return value of {@link SharedListenerAggregateInterface::attachShared()}
     */
    public function attachAggregate(SharedListenerAggregateInterface $aggregate, $priority = 1);

    /**
     * Detach a listener aggregate
     *
     * @param  SharedListenerAggregateInterface $aggregate
     * @return mixed return value of {@link SharedListenerAggregateInterface::detachShared()}
    */
    public function detachAggregate(SharedListenerAggregateInterface $aggregate);
}
{
    "name": "zendframework/zend-serializer",
    "description": "provides an adapter based interface to simply generate storable representation of PHP types by different facilities, and recover",
    "license": "BSD-3-Clause",
    "keywords": [
        "zf2",
        "serializer"
    ],
    "autoload": {
        "psr-0": {
            "Zend\\Serializer\\": ""
        }
    },
    "target-dir": "Zend/Serializer",
    "require": {
        "php": ">=5.3.3",
        "zendframework/zend-stdlib": "self.version",
        "zendframework/zend-json": "self.version",
        "zendframework/zend-math": "self.version"
    },
    "suggest": {
        "zendframework/zend-servicemanager": "To support plugin manager support"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "2.2-dev",
            "dev-develop": "2.3-dev"
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Serializer;

use Zend\Serializer\Adapter\AdapterInterface as Adapter;

abstract class Serializer
{
    /**
     * Plugin manager for loading adapters
     *
     * @var null|AdapterPluginManager
     */
    private static $adapters = null;

    /**
     * The default adapter.
     *
     * @var string|Adapter
     */
    protected static $defaultAdapter = 'PhpSerialize';

    /**
     * Create a serializer adapter instance.
     *
     * @param  string|Adapter $adapterName Name of the adapter class
     * @param  array |\Traversable|null $adapterOptions Serializer options
     * @return Adapter
     */
    public static function factory($adapterName, $adapterOptions = null)
    {
        if ($adapterName instanceof Adapter) {
            return $adapterName; // $adapterName is already an adapter object
        }

        return static::getAdapterPluginManager()->get($adapterName, $adapterOptions);
    }

    /**
     * Change the adapter plugin manager
     *
     * @param  AdapterPluginManager $adapters
     * @return void
     */
    public static function setAdapterPluginManager(AdapterPluginManager $adapters)
    {
        static::$adapters = $adapters;
    }

    /**
     * Get the adapter plugin manager
     *
     * @return AdapterPluginManager
     */
    public static function getAdapterPluginManager()
    {
        if (static::$adapters === null) {
            static::$adapters = new AdapterPluginManager();
        }
        return static::$adapters;
    }

    /**
     * Resets the internal adapter plugin manager
     *
     * @return AdapterPluginManager
     */
    public static function resetAdapterPluginManager()
    {
        static::$adapters = new AdapterPluginManager();
        return static::$adapters;
    }

    /**
     * Change the default adapter.
     *
     * @param string|Adapter $adapter
     * @param array|\Traversable|null $adapterOptions
     */
    public static function setDefaultAdapter($adapter, $adapterOptions = null)
    {
        static::$defaultAdapter = static::factory($adapter, $adapterOptions);
    }

    /**
     * Get the default adapter.
     *
     * @return Adapter
     */
    public static function getDefaultAdapter()
    {
        if (!static::$defaultAdapter instanceof Adapter) {
            static::setDefaultAdapter(static::$defaultAdapter);
        }
        return static::$defaultAdapter;
    }

    /**
     * Generates a storable representation of a value using the default adapter.
     * Optionally different adapter could be provided as second argument
     *
     * @param  mixed $value
     * @param  string|Adapter $adapter
     * @param  array|\Traversable|null $adapterOptions Adapter constructor options
     *                                                 only used to create adapter instance
     * @return string
     */
    public static function serialize($value, $adapter = null, $adapterOptions = null)
    {
        if ($adapter !== null) {
            $adapter = static::factory($adapter, $adapterOptions);
        } else {
            $adapter = static::getDefaultAdapter();
        }

        return $adapter->serialize($value);
    }

    /**
     * Creates a PHP value from a stored representation using the default adapter.
     * Optionally different adapter could be provided as second argument
     *
     * @param  string $serialized
     * @param  string|Adapter $adapter
     * @param  array|\Traversable|null $adapterOptions Adapter constructor options
     *                                                 only used to create adapter instance
     * @return mixed
     */
    public static function unserialize($serialized, $adapter = null, $adapterOptions = null)
    {
        if ($adapter !== null) {
            $adapter = static::factory($adapter, $adapterOptions);
        } else {
            $adapter = static::getDefaultAdapter();
        }

        return $adapter->unserialize($serialized);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Serializer\Exception;

class ExtensionNotLoadedException extends RuntimeException
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Serializer\Exception;

/**
 * @used       InvalidArgumentException
 */
class InvalidArgumentException extends \InvalidArgumentException implements
    ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Serializer\Exception;

/**
 * @used       RuntimeException
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Serializer\Exception;

interface ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Serializer;

use Zend\ServiceManager\AbstractPluginManager;

/**
 * Plugin manager implementation for serializer adapters.
 *
 * Enforces that adapters retrieved are instances of
 * Adapter\AdapterInterface. Additionally, it registers a number of default
 * adapters available.
 */
class AdapterPluginManager extends AbstractPluginManager
{
    /**
     * Default set of adapters
     *
     * @var array
     */
    protected $invokableClasses = array(
        'igbinary'     => 'Zend\Serializer\Adapter\IgBinary',
        'json'         => 'Zend\Serializer\Adapter\Json',
        'msgpack'      => 'Zend\Serializer\Adapter\MsgPack',
        'phpcode'      => 'Zend\Serializer\Adapter\PhpCode',
        'phpserialize' => 'Zend\Serializer\Adapter\PhpSerialize',
        'pythonpickle' => 'Zend\Serializer\Adapter\PythonPickle',
        'wddx'         => 'Zend\Serializer\Adapter\Wddx',
    );

    /**
     * Validate the plugin
     *
     * Checks that the adapter loaded is an instance
     * of Adapter\AdapterInterface.
     *
     * @param  mixed $plugin
     * @return void
     * @throws Exception\RuntimeException if invalid
     */
    public function validatePlugin($plugin)
    {
        if ($plugin instanceof Adapter\AdapterInterface) {
            // we're okay
            return;
        }

        throw new Exception\RuntimeException(sprintf(
            'Plugin of type %s is invalid; must implement %s\Adapter\AdapterInterface',
            (is_object($plugin) ? get_class($plugin) : gettype($plugin)),
            __NAMESPACE__
        ));
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Serializer\Adapter;

use Zend\Stdlib\AbstractOptions;

class AdapterOptions extends AbstractOptions
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Serializer\Adapter;

use Zend\Json\Json as ZendJson;
use Zend\Serializer\Exception;

class JsonOptions extends AdapterOptions
{
    /**
     * @var int
     */
    protected $cycleCheck = false;

    protected $enableJsonExprFinder = false;

    protected $objectDecodeType = ZendJson::TYPE_ARRAY;

    /**
     * @param  bool $flag
     * @return JsonOptions
     */
    public function setCycleCheck($flag)
    {
        $this->cycleCheck = (bool) $flag;
        return $this;
    }

    /**
     * @return bool
     */
    public function getCycleCheck()
    {
        return $this->cycleCheck;
    }

    /**
     * @param  bool $flag
     * @return JsonOptions
     */
    public function setEnableJsonExprFinder($flag)
    {
        $this->enableJsonExprFinder = (bool) $flag;
        return $this;
    }

    /**
     * @return bool
     */
    public function getEnableJsonExprFinder()
    {
        return $this->enableJsonExprFinder;
    }

    /**
     * @param  int $type
     * @return JsonOptions
     * @throws Exception\InvalidArgumentException
     */
    public function setObjectDecodeType($type)
    {
        if ($type != ZendJson::TYPE_ARRAY && $type != ZendJson::TYPE_OBJECT) {
            throw new Exception\InvalidArgumentException(
                'Unknown decode type: ' . $type
            );
        }

        $this->objectDecodeType = (int) $type;

        return $this;
    }

    /**
     * @return int
     */
    public function getObjectDecodeType()
    {
        return $this->objectDecodeType;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Serializer\Adapter;

use Zend\Serializer\Exception;
use Zend\Stdlib\ErrorHandler;

class PhpCode extends AbstractAdapter
{
    /**
     * Serialize PHP using var_export
     *
     * @param  mixed $value
     * @return string
     */
    public function serialize($value)
    {
        return var_export($value, true);
    }

    /**
     * Deserialize PHP string
     *
     * Warning: this uses eval(), and should likely be avoided.
     *
     * @param  string $code
     * @return mixed
     * @throws Exception\RuntimeException on eval error
     */
    public function unserialize($code)
    {
        ErrorHandler::start(E_ALL);
        $ret  = null;
        // This suppression is due to the fact that the ErrorHandler cannot
        // catch syntax errors, and is intentionally left in place.
        $eval = @eval('$ret=' . $code . ';');
        $err  = ErrorHandler::stop();

        if ($eval === false || $err) {

            $msg = 'eval failed';

            // Error handler doesn't catch syntax errors
            if ($eval === false) {
                $lastErr = error_get_last();
                $msg    .= ': ' . $lastErr['message'];
            }

            throw new Exception\RuntimeException($msg, 0, $err);
        }

        return $ret;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Serializer\Adapter;

use stdClass;
use Traversable;
use Zend\Math\BigInteger;
use Zend\Serializer\Exception;
use Zend\Stdlib\ArrayUtils;

/**
 * @link       http://www.python.org
 * @see        Phython3.1/Lib/pickle.py
 * @see        Phython3.1/Modules/_pickle.c
 * @link       http://pickle-js.googlecode.com
 */
class PythonPickle extends AbstractAdapter
{
    /**
     * Pickle opcodes. See pickletools.py for extensive docs.
     * @link http://hg.python.org/cpython/file/2.7/Lib/pickletools.py
     * The listing here is in kind-of alphabetical order of 1-character pickle code.
     * pickletools groups them by purpose.
     */
    const OP_MARK            = '(';     // push special markobject on stack
    const OP_STOP            = '.';     // every pickle ends with STOP
    const OP_POP             = '0';     // discard topmost stack item
    const OP_POP_MARK        = '1';     // discard stack top through topmost markobject
    const OP_DUP             = '2';     // duplicate top stack item
    const OP_FLOAT           = 'F';     // push float object; decimal string argument
    const OP_INT             = 'I';     // push integer or bool; decimal string argument
    const OP_BININT          = 'J';     // push four-byte signed int
    const OP_BININT1         = 'K';     // push 1-byte unsigned int
    const OP_LONG            = 'L';     // push long; decimal string argument
    const OP_BININT2         = 'M';     // push 2-byte unsigned int
    const OP_NONE            = 'N';     // push None
    const OP_PERSID          = 'P';     // push persistent object; id is taken from string arg
    const OP_BINPERSID       = 'Q';     //  "       "         "  ;  "  "   "     "  stack
    const OP_REDUCE          = 'R';     // apply callable to argtuple, both on stack
    const OP_STRING          = 'S';     // push string; NL-terminated string argument
    const OP_BINSTRING       = 'T';     // push string; counted binary string argument
    const OP_SHORT_BINSTRING = 'U';     //  "     "   ;    "      "       "      " < 256 bytes
    const OP_UNICODE         = 'V';     // push Unicode string; raw-unicode-escaped'd argument
    const OP_BINUNICODE      = 'X';     //   "     "       "  ; counted UTF-8 string argument
    const OP_APPEND          = 'a';     // append stack top to list below it
    const OP_BUILD           = 'b';     // call __setstate__ or __dict__.update()
    const OP_GLOBAL          = 'c';     // push self.find_class(modname, name); 2 string args
    const OP_DICT            = 'd';     // build a dict from stack items
    const OP_EMPTY_DICT      = '}';     // push empty dict
    const OP_APPENDS         = 'e';     // extend list on stack by topmost stack slice
    const OP_GET             = 'g';     // push item from memo on stack; index is string arg
    const OP_BINGET          = 'h';     //   "    "    "    "   "   "  ;   "    " 1-byte arg
    const OP_INST            = 'i';     // build & push class instance
    const OP_LONG_BINGET     = 'j';     // push item from memo on stack; index is 4-byte arg
    const OP_LIST            = 'l';     // build list from topmost stack items
    const OP_EMPTY_LIST      = ']';     // push empty list
    const OP_OBJ             = 'o';     // build & push class instance
    const OP_PUT             = 'p';     // store stack top in memo; index is string arg
    const OP_BINPUT          = 'q';     //   "     "    "   "   " ;   "    " 1-byte arg
    const OP_LONG_BINPUT     = 'r';     //   "     "    "   "   " ;   "    " 4-byte arg
    const OP_SETITEM         = 's';     // add key+value pair to dict
    const OP_TUPLE           = 't';     // build tuple from topmost stack items
    const OP_EMPTY_TUPLE     = ')';     // push empty tuple
    const OP_SETITEMS        = 'u';     // modify dict by adding topmost key+value pairs
    const OP_BINFLOAT        = 'G';     // push float; arg is 8-byte float encoding

    /* Protocol 2 */
    const OP_PROTO           = "\x80";  // identify pickle protocol
    const OP_NEWOBJ          = "\x81";  // build object by applying cls.__new__ to argtuple
    const OP_EXT1            = "\x82";  // push object from extension registry; 1-byte index
    const OP_EXT2            = "\x83";  // ditto, but 2-byte index
    const OP_EXT4            = "\x84";  // ditto, but 4-byte index
    const OP_TUPLE1          = "\x85";  // build 1-tuple from stack top
    const OP_TUPLE2          = "\x86";  // build 2-tuple from two topmost stack items
    const OP_TUPLE3          = "\x87";  // build 3-tuple from three topmost stack items
    const OP_NEWTRUE         = "\x88";  // push True
    const OP_NEWFALSE        = "\x89";  // push False
    const OP_LONG1           = "\x8a";  // push long from < 256 bytes
    const OP_LONG4           = "\x8b";  // push really big long

    /* Protocol 3 (Python 3.x) */
    const OP_BINBYTES        = 'B';     // push bytes; counted binary string argument
    const OP_SHORT_BINBYTES  = 'C';     //  "     "   ;    "      "       "      " < 256 bytes

    /**
     * Whether or not the system is little-endian
     *
     * @var bool
     */
    protected static $isLittleEndian = null;

    /**
     * @var array Strings representing quotes
     */
    protected static $quoteString = array(
        '\\' => '\\\\',
        "\x00" => '\\x00', "\x01" => '\\x01', "\x02" => '\\x02', "\x03" => '\\x03',
        "\x04" => '\\x04', "\x05" => '\\x05', "\x06" => '\\x06', "\x07" => '\\x07',
        "\x08" => '\\x08', "\x09" => '\\t',   "\x0a" => '\\n',   "\x0b" => '\\x0b',
        "\x0c" => '\\x0c', "\x0d" => '\\r',   "\x0e" => '\\x0e', "\x0f" => '\\x0f',
        "\x10" => '\\x10', "\x11" => '\\x11', "\x12" => '\\x12', "\x13" => '\\x13',
        "\x14" => '\\x14', "\x15" => '\\x15', "\x16" => '\\x16', "\x17" => '\\x17',
        "\x18" => '\\x18', "\x19" => '\\x19', "\x1a" => '\\x1a', "\x1b" => '\\x1b',
        "\x1c" => '\\x1c', "\x1d" => '\\x1d', "\x1e" => '\\x1e', "\x1f" => '\\x1f',
        "\xff" => '\\xff'
    );

    // process vars
    protected $protocol  = null;
    protected $memo      = array();
    protected $pickle    = '';
    protected $pickleLen = 0;
    protected $pos       = 0;
    protected $stack     = array();
    protected $marker    = null;

    /**
     * @var BigInteger\Adapter\AdapterInterface
     */
    protected $bigIntegerAdapter = null;

    /**
     * @var PythonPickleOptions
     */
    protected $options = null;

    /**
     * Constructor.
     *
     * @param  array|Traversable|PythonPickleOptions $options Optional
     */
    public function __construct($options = null)
    {
        // init
        if (static::$isLittleEndian === null) {
            static::$isLittleEndian = (pack('l', 1) === "\x01\x00\x00\x00");
        }

        $this->marker = new stdClass();

        parent::__construct($options);
    }

    /**
     * Set options
     *
     * @param  array|Traversable|PythonPickleOptions $options
     * @return PythonPickle
     */
    public function setOptions($options)
    {
        if (!$options instanceof PythonPickleOptions) {
            $options = new PythonPickleOptions($options);
        }

        $this->options = $options;
        return $this;
    }

    /**
     * Get options
     *
     * @return PythonPickleOptions
     */
    public function getOptions()
    {
        if ($this->options === null) {
            $this->options = new PythonPickleOptions();
        }
        return $this->options;
    }

    /* serialize */

    /**
     * Serialize PHP to PythonPickle format
     *
     * @param  mixed $value
     * @return string
     */
    public function serialize($value)
    {
        $this->clearProcessVars();
        $this->protocol = $this->getOptions()->getProtocol();

        // write
        if ($this->protocol >= 2) {
            $this->writeProto($this->protocol);
        }
        $this->write($value);
        $this->writeStop();

        $pickle = $this->pickle;
        $this->clearProcessVars();

        return $pickle;
    }

    /**
     * Write a value
     *
     * @param  mixed $value
     * @throws Exception\RuntimeException on invalid or unrecognized value type
     */
    protected function write($value)
    {
        if ($value === null) {
            $this->writeNull();
        } elseif (is_bool($value)) {
            $this->writeBool($value);
        } elseif (is_int($value)) {
            $this->writeInt($value);
        } elseif (is_float($value)) {
            $this->writeFloat($value);
        } elseif (is_string($value)) {
            // TODO: write unicode / binary
            $this->writeString($value);
        } elseif (is_array($value)) {
            if (ArrayUtils::isList($value)) {
                $this->writeArrayList($value);
            } else {
                $this->writeArrayDict($value);
            }
        } elseif (is_object($value)) {
            $this->writeObject($value);
        } else {
            throw new Exception\RuntimeException(sprintf(
                'PHP-Type "%s" can not be serialized by %s',
                gettype($value),
                get_class($this)
            ));
        }
    }

    /**
     * Write pickle protocol
     *
     * @param int $protocol
     */
    protected function writeProto($protocol)
    {
        $this->pickle .= self::OP_PROTO . $protocol;
    }

    /**
     * Write a get
     *
     * @param  int $id Id of memo
     */
    protected function writeGet($id)
    {
        if ($this->protocol == 0) {
            $this->pickle .= self::OP_GET . $id . "\r\n";
        } elseif ($id <= 0xFF) {
            // BINGET + chr(i)
            $this->pickle .= self::OP_BINGET . chr($id);
        } else {
            // LONG_BINGET + pack("<i", i)
            $bin = pack('l', $id);
            if (static::$isLittleEndian === false) {
                $bin = strrev($bin);
            }
            $this->pickle .= self::OP_LONG_BINGET . $bin;
        }
    }

    /**
     * Write a put
     *
     * @param  int $id Id of memo
     */
    protected function writePut($id)
    {
        if ($this->protocol == 0) {
            $this->pickle .= self::OP_PUT . $id . "\r\n";
        } elseif ($id <= 0xff) {
            // BINPUT + chr(i)
            $this->pickle .= self::OP_BINPUT . chr($id);
        } else {
            // LONG_BINPUT + pack("<i", i)
            $bin = pack('l', $id);
            if (static::$isLittleEndian === false) {
                $bin = strrev($bin);
            }
            $this->pickle .= self::OP_LONG_BINPUT . $bin;
        }
    }

    /**
     * Write a null as None
     *
     */
    protected function writeNull()
    {
        $this->pickle .= self::OP_NONE;
    }

    /**
     * Write boolean value
     *
     * @param bool $value
     */
    protected function writeBool($value)
    {
        if ($this->protocol >= 2) {
            $this->pickle .= ($value === true) ? self::OP_NEWTRUE : self::OP_NEWFALSE;
        } else {
            $this->pickle .= self::OP_INT . (($value === true) ? '01' : '00') . "\r\n";
        }
    }

    /**
     * Write an integer value
     *
     * @param  int $value
     */
    protected function writeInt($value)
    {
        if ($this->protocol == 0) {
            $this->pickle .= self::OP_INT . $value . "\r\n";
            return;
        }

        if ($value >= 0) {
            if ($value <= 0xFF) {
                // self.write(BININT1 + chr(obj))
                $this->pickle .= self::OP_BININT1 . chr($value);
            } elseif ($value <= 0xFFFF) {
                // self.write("%c%c%c" % (BININT2, obj&0xff, obj>>8))
                $this->pickle .= self::OP_BININT2 . pack('v', $value);
            }
            return;
        }

        // Next check for 4-byte signed ints:
        $highBits = $value >> 31;  // note that Python shift sign-extends
        if ($highBits == 0 || $highBits == -1) {
            // All high bits are copies of bit 2**31, so the value
            // fits in a 4-byte signed int.
            // self.write(BININT + pack("<i", obj))
            $bin = pack('l', $value);
            if (static::$isLittleEndian === false) {
                $bin = strrev($bin);
            }
            $this->pickle .= self::OP_BININT . $bin;
            return;
        }
    }

    /**
     * Write a float value
     *
     * @param  float $value
     */
    protected function writeFloat($value)
    {
        if ($this->protocol == 0) {
            $this->pickle .= self::OP_FLOAT . $value . "\r\n";
        } else {
            // self.write(BINFLOAT + pack('>d', obj))
            $bin = pack('d', $value);
            if (static::$isLittleEndian === true) {
                $bin = strrev($bin);
            }
            $this->pickle .= self::OP_BINFLOAT . $bin;
        }
    }

    /**
     * Write a string value
     *
     * @param  string $value
     */
    protected function writeString($value)
    {
        if (($id = $this->searchMemo($value)) !== false) {
            $this->writeGet($id);
            return;
        }

        if ($this->protocol == 0) {
            $this->pickle .= self::OP_STRING . $this->quoteString($value) . "\r\n";
        } else {
            $n = strlen($value);
            if ($n <= 0xFF) {
                // self.write(SHORT_BINSTRING + chr(n) + obj)
                $this->pickle .= self::OP_SHORT_BINSTRING . chr($n) . $value;
            } else {
                // self.write(BINSTRING + pack("<i", n) + obj)
                $binLen = pack('l', $n);
                if (static::$isLittleEndian === false) {
                    $binLen = strrev($binLen);
                }
                $this->pickle .= self::OP_BINSTRING . $binLen . $value;
            }
        }

        $this->memorize($value);
    }

    /**
     * Write an associative array value as dictionary
     *
     * @param  array|Traversable $value
     */
    protected function writeArrayDict($value)
    {
        if (($id = $this->searchMemo($value)) !== false) {
            $this->writeGet($id);
            return;
        }

        $this->pickle .= self::OP_MARK . self::OP_DICT;
        $this->memorize($value);

        foreach ($value as $k => $v) {
            $this->write($k);
            $this->write($v);
            $this->pickle .= self::OP_SETITEM;
        }
    }

    /**
     * Write a simple array value as list
     *
     * @param  array $value
     */
    protected function writeArrayList(array $value)
    {
        if (($id = $this->searchMemo($value)) !== false) {
            $this->writeGet($id);
            return;
        }

        $this->pickle .= self::OP_MARK . self::OP_LIST;
        $this->memorize($value);

        foreach ($value as $v) {
            $this->write($v);
            $this->pickle .= self::OP_APPEND;
        }
    }

    /**
     * Write an object as an dictionary
     *
     * @param  object $value
     */
    protected function writeObject($value)
    {
        // The main differences between a SplFixedArray and a normal PHP array is
        // that the SplFixedArray is of fixed length and allows only integers
        // within the range as indexes.
        if ($value instanceof \SplFixedArray) {
            $this->writeArrayList($value->toArray());

        // Use the object method toArray if available
        } elseif (method_exists($value, 'toArray')) {
            $this->writeArrayDict($value->toArray());

        // If the object is an iterator simply iterate it
        // and convert it to an dictionary
        } elseif ($value instanceof Traversable) {
            $this->writeArrayDict($value);

        // other objects are simply converted by using its properties
        } else {
            $this->writeArrayDict(get_object_vars($value));
        }
    }

    /**
     * Write stop
     */
    protected function writeStop()
    {
        $this->pickle .= self::OP_STOP;
    }

    /* serialize helper */

    /**
     * Add a value to the memo and write the id
     *
     * @param mixed $value
     */
    protected function memorize($value)
    {
        $id = count($this->memo);
        $this->memo[$id] = $value;
        $this->writePut($id);
    }

    /**
     * Search a value in the memo and return  the id
     *
     * @param  mixed $value
     * @return int|bool The id or false
     */
    protected function searchMemo($value)
    {
        return array_search($value, $this->memo, true);
    }

    /**
     * Quote/Escape a string
     *
     * @param  string $str
     * @return string quoted string
     */
    protected function quoteString($str)
    {
        $quoteArr = static::$quoteString;

        if (($cntSingleQuote = substr_count($str, "'"))
            && ($cntDoubleQuote = substr_count($str, '"'))
            && ($cntSingleQuote < $cntDoubleQuote)
        ) {
            $quoteArr['"'] = '\\"';
            $enclosure     = '"';
        } else {
            $quoteArr["'"] = "\\'";
            $enclosure     = "'";
        }

        return $enclosure . strtr($str, $quoteArr) . $enclosure;
    }

    /* unserialize */

    /**
     * Unserialize from Python Pickle format to PHP
     *
     * @param  string $pickle
     * @return mixed
     * @throws Exception\RuntimeException on invalid Pickle string
     */
    public function unserialize($pickle)
    {
        // init process vars
        $this->clearProcessVars();
        $this->pickle    = $pickle;
        $this->pickleLen = strlen($this->pickle);

        // read pickle string
        while (($op = $this->read(1)) !== self::OP_STOP) {
            $this->load($op);
        }

        if (!count($this->stack)) {
            throw new Exception\RuntimeException('No data found');
        }

        $ret = array_pop($this->stack);

        // clear process vars
        $this->clearProcessVars();

        return $ret;
    }

    /**
     * Clear temp variables needed for processing
     */
    protected function clearProcessVars()
    {
        $this->pos       = 0;
        $this->pickle    = '';
        $this->pickleLen = 0;
        $this->memo      = array();
        $this->stack     = array();
    }

    /**
     * Load a pickle opcode
     *
     * @param  string $op
     * @throws Exception\RuntimeException on invalid opcode
     */
    protected function load($op)
    {
        switch ($op) {
            case self::OP_PUT:
                $this->loadPut();
                break;
            case self::OP_BINPUT:
                $this->loadBinPut();
                break;
            case self::OP_LONG_BINPUT:
                $this->loadLongBinPut();
                break;
            case self::OP_GET:
                $this->loadGet();
                break;
            case self::OP_BINGET:
                $this->loadBinGet();
                break;
            case self::OP_LONG_BINGET:
                $this->loadLongBinGet();
                break;
            case self::OP_NONE:
                $this->loadNone();
                break;
            case self::OP_NEWTRUE:
                $this->loadNewTrue();
                break;
            case self::OP_NEWFALSE:
                $this->loadNewFalse();
                break;
            case self::OP_INT:
                $this->loadInt();
                break;
            case self::OP_BININT:
                $this->loadBinInt();
                break;
            case self::OP_BININT1:
                $this->loadBinInt1();
                break;
            case self::OP_BININT2:
                $this->loadBinInt2();
                break;
            case self::OP_LONG:
                $this->loadLong();
                break;
            case self::OP_LONG1:
                $this->loadLong1();
                break;
            case self::OP_LONG4:
                $this->loadLong4();
                break;
            case self::OP_FLOAT:
                $this->loadFloat();
                break;
            case self::OP_BINFLOAT:
                $this->loadBinFloat();
                break;
            case self::OP_STRING:
                $this->loadString();
                break;
            case self::OP_BINSTRING:
                $this->loadBinString();
                break;
            case self::OP_SHORT_BINSTRING:
                $this->loadShortBinString();
                break;
            case self::OP_BINBYTES:
                $this->loadBinBytes();
                break;
            case self::OP_SHORT_BINBYTES:
                $this->loadShortBinBytes();
                break;
            case self::OP_UNICODE:
                $this->loadUnicode();
                break;
            case self::OP_BINUNICODE:
                $this->loadBinUnicode();
                break;
            case self::OP_MARK:
                $this->loadMark();
                break;
            case self::OP_LIST:
                $this->loadList();
                break;
            case self::OP_EMPTY_LIST:
                $this->loadEmptyList();
                break;
            case self::OP_APPEND:
                $this->loadAppend();
                break;
            case self::OP_APPENDS:
                $this->loadAppends();
                break;
            case self::OP_DICT:
                $this->loadDict();
                break;
            case self::OP_EMPTY_DICT:
                $this->_loadEmptyDict();
                break;
            case self::OP_SETITEM:
                $this->loadSetItem();
                break;
            case self::OP_SETITEMS:
                $this->loadSetItems();
                break;
            case self::OP_TUPLE:
                $this->loadTuple();
                break;
            case self::OP_TUPLE1:
                $this->loadTuple1();
                break;
            case self::OP_TUPLE2:
                $this->loadTuple2();
                break;
            case self::OP_TUPLE3:
                $this->loadTuple3();
                break;
            case self::OP_PROTO:
                $this->loadProto();
                break;
            default:
                throw new Exception\RuntimeException("Invalid or unknown opcode '{$op}'");
        }
    }

    /**
     * Load a PUT opcode
     *
     * @throws Exception\RuntimeException on missing stack
     */
    protected function loadPut()
    {
        $id = (int) $this->readline();

        $lastStack = count($this->stack) - 1;
        if (!isset($this->stack[$lastStack])) {
            throw new Exception\RuntimeException('No stack exist');
        }
        $this->memo[$id] =& $this->stack[$lastStack];
    }

    /**
     * Load a binary PUT
     *
     * @throws Exception\RuntimeException on missing stack
     */
    protected function loadBinPut()
    {
        $id = ord($this->read(1));

        $lastStack = count($this->stack)-1;
        if (!isset($this->stack[$lastStack])) {
            throw new Exception\RuntimeException('No stack exist');
        }
        $this->memo[$id] =& $this->stack[$lastStack];
    }

    /**
     * Load a long binary PUT
     *
     * @throws Exception\RuntimeException on missing stack
     */
    protected function loadLongBinPut()
    {
        $bin = $this->read(4);
        if (static::$isLittleEndian === false) {
            $bin = strrev($bin);
        }
        list(, $id) = unpack('l', $bin);

        $lastStack = count($this->stack)-1;
        if (!isset($this->stack[$lastStack])) {
            throw new Exception\RuntimeException('No stack exist');
        }
        $this->memo[$id] =& $this->stack[$lastStack];
    }

    /**
     * Load a GET operation
     *
     * @throws Exception\RuntimeException on missing GET identifier
     */
    protected function loadGet()
    {
        $id = (int) $this->readline();

        if (!array_key_exists($id, $this->memo)) {
            throw new Exception\RuntimeException('Get id "' . $id . '" not found in memo');
        }
        $this->stack[] =& $this->memo[$id];
    }

    /**
     * Load a binary GET operation
     *
     * @throws Exception\RuntimeException on missing GET identifier
     */
    protected function loadBinGet()
    {
        $id = ord($this->read(1));

        if (!array_key_exists($id, $this->memo)) {
            throw new Exception\RuntimeException('Get id "' . $id . '" not found in memo');
        }
        $this->stack[] =& $this->memo[$id];
    }

    /**
     * Load a long binary GET operation
     *
     * @throws Exception\RuntimeException on missing GET identifier
     */
    protected function loadLongBinGet()
    {
        $bin = $this->read(4);
        if (static::$isLittleEndian === false) {
            $bin = strrev($bin);
        }
        list(, $id) = unpack('l', $bin);

        if (!array_key_exists($id, $this->memo)) {
            throw new Exception\RuntimeException('Get id "' . $id . '" not found in memo');
        }
        $this->stack[] =& $this->memo[$id];
    }

    /**
     * Load a NONE operator
     */
    protected function loadNone()
    {
        $this->stack[] = null;
    }

    /**
     * Load a boolean TRUE operator
     */
    protected function loadNewTrue()
    {
        $this->stack[] = true;
    }

    /**
     * Load a boolean FALSE operator
     */
    protected function loadNewFalse()
    {
        $this->stack[] = false;
    }

    /**
     * Load an integer operator
     */
    protected function loadInt()
    {
        $line = $this->readline();
        if ($line === '01') {
            $this->stack[] = true;
        } elseif ($line === '00') {
            $this->stack[] = false;
        } else {
            $this->stack[] = (int) $line;
        }
    }

    /**
     * Load a binary integer operator
     */
    protected function loadBinInt()
    {
        $bin = $this->read(4);
        if (static::$isLittleEndian === false) {
            $bin = strrev($bin);
        }
        list(, $int)   = unpack('l', $bin);
        $this->stack[] = $int;
    }

    /**
     * Load the first byte of a binary integer
     */
    protected function loadBinInt1()
    {
        $this->stack[] = ord($this->read(1));
    }

    /**
     * Load the second byte of a binary integer
     */
    protected function loadBinInt2()
    {
        $bin = $this->read(2);
        list(, $int)   = unpack('v', $bin);
        $this->stack[] = $int;
    }

    /**
     * Load a long (float) operator
     */
    protected function loadLong()
    {
        $data = rtrim($this->readline(), 'L');
        if ($data === '') {
            $this->stack[] = 0;
        } else {
            $this->stack[] = $data;
        }
    }

    /**
     * Load a one byte long integer
     */
    protected function loadLong1()
    {
        $n    = ord($this->read(1));
        $data = $this->read($n);
        $this->stack[] = $this->decodeBinLong($data);
    }

    /**
     * Load a 4 byte long integer
     *
     */
    protected function loadLong4()
    {
        $nBin = $this->read(4);
        if (static::$isLittleEndian === false) {
            $nBin = strrev($$nBin);
        }
        list(, $n) = unpack('l', $nBin);
        $data = $this->read($n);

        $this->stack[] = $this->decodeBinLong($data);
    }

    /**
     * Load a float value
     *
     */
    protected function loadFloat()
    {
        $float = (float) $this->readline();
        $this->stack[] = $float;
    }

    /**
     * Load a binary float value
     *
     */
    protected function loadBinFloat()
    {
        $bin = $this->read(8);
        if (static::$isLittleEndian === true) {
            $bin = strrev($bin);
        }
        list(, $float) = unpack('d', $bin);
        $this->stack[] = $float;
    }

    /**
     * Load a string
     *
     */
    protected function loadString()
    {
        $this->stack[] = $this->unquoteString((string) $this->readline());
    }

    /**
     * Load a binary string
     *
     */
    protected function loadBinString()
    {
        $bin = $this->read(4);
        if (!static::$isLittleEndian) {
            $bin = strrev($bin);
        }
        list(, $len)   = unpack('l', $bin);
        $this->stack[] = (string) $this->read($len);
    }

    /**
     * Load a short binary string
     *
     */
    protected function loadShortBinString()
    {
        $len           = ord($this->read(1));
        $this->stack[] = (string) $this->read($len);
    }

    /**
     * Load arbitrary binary bytes
     */
    protected function loadBinBytes()
    {
        // read byte length
        $nBin = $this->read(4);
        if (static::$isLittleEndian === false) {
            $nBin = strrev($$nBin);
        }
        list(, $n)     = unpack('l', $nBin);
        $this->stack[] = $this->read($n);
    }

    /**
     * Load a single binary byte
     */
    protected function loadShortBinBytes()
    {
        $n             = ord($this->read(1));
        $this->stack[] = $this->read($n);
    }

    /**
     * Load a unicode string
     */
    protected function loadUnicode()
    {
        $data    = $this->readline();
        $pattern = '/\\\\u([a-fA-F0-9]{4})/u'; // \uXXXX
        $data    = preg_replace_callback($pattern, array($this, '_convertMatchingUnicodeSequence2Utf8'), $data);

        $this->stack[] = $data;
    }

    /**
     * Convert a unicode sequence to UTF-8
     *
     * @param  array $match
     * @return string
     */
    protected function _convertMatchingUnicodeSequence2Utf8(array $match)
    {
        return $this->hex2Utf8($match[1]);
    }

    /**
     * Convert a hex string to a UTF-8 string
     *
     * @param  string $hex
     * @return string
     * @throws Exception\RuntimeException on unmatched unicode sequence
     */
    protected function hex2Utf8($hex)
    {
        $uniCode = hexdec($hex);

        if ($uniCode < 0x80) { // 1Byte
            $utf8Char = chr($uniCode);

        } elseif ($uniCode < 0x800) { // 2Byte
            $utf8Char = chr(0xC0 | $uniCode >> 6)
                      . chr(0x80 | $uniCode & 0x3F);

        } elseif ($uniCode < 0x10000) { // 3Byte
            $utf8Char = chr(0xE0 | $uniCode >> 12)
                      . chr(0x80 | $uniCode >> 6 & 0x3F)
                      . chr(0x80 | $uniCode & 0x3F);

        } elseif ($uniCode < 0x110000) { // 4Byte
            $utf8Char  = chr(0xF0 | $uniCode >> 18)
                       . chr(0x80 | $uniCode >> 12 & 0x3F)
                       . chr(0x80 | $uniCode >> 6 & 0x3F)
                       . chr(0x80 | $uniCode & 0x3F);
        } else {
            throw new Exception\RuntimeException(sprintf(
                'Unsupported unicode character found "%s"', dechex($uniCode)
            ));
        }

        return $utf8Char;
    }

    /**
     * Load binary unicode sequence
     */
    protected function loadBinUnicode()
    {
        // read byte length
        $n = $this->read(4);
        if (static::$isLittleEndian === false) {
            $n = strrev($n);
        }
        list(, $n) = unpack('l', $n);
        $data      = $this->read($n);

        $this->stack[] = $data;
    }

    /**
     * Load a marker sequence
     */
    protected function loadMark()
    {
        $this->stack[] = $this->marker;
    }

    /**
     * Load an array (list)
     */
    protected function loadList()
    {
        $k = $this->lastMarker();
        $this->stack[$k] = array();

        // remove all elements after marker
        for ($i = $k + 1, $max = count($this->stack); $i < $max; $i++) {
            unset($this->stack[$i]);
        }
    }

    /**
     * Load an append (to list) sequence
     */
    protected function loadAppend()
    {
        $value  =  array_pop($this->stack);
        $list   =& $this->stack[count($this->stack) - 1];
        $list[] =  $value;
    }

    /**
     * Load an empty list sequence
     */
    protected function loadEmptyList()
    {
        $this->stack[] = array();
    }

    /**
     * Load multiple append (to list) sequences at once
     */
    protected function loadAppends()
    {
        $k    =  $this->lastMarker();
        $list =& $this->stack[$k - 1];
        $max  =  count($this->stack);
        for ($i = $k + 1; $i < $max; $i++) {
            $list[] = $this->stack[$i];
            unset($this->stack[$i]);
        }
        unset($this->stack[$k]);
    }

    /**
     * Load an associative array (Python dictionary)
     */
    protected function loadDict()
    {
        $k = $this->lastMarker();
        $this->stack[$k] = array();

        // remove all elements after marker
        $max = count($this->stack);
        for ($i = $k + 1; $i < $max; $i++) {
            unset($this->stack[$i]);
        }
    }

    /**
     * Load an item from a set
     */
    protected function loadSetItem()
    {
        $value =  array_pop($this->stack);
        $key   =  array_pop($this->stack);
        $dict  =& $this->stack[count($this->stack) - 1];
        $dict[$key] = $value;
    }

    /**
     * Load an empty dictionary
     */
    protected function _loadEmptyDict()
    {
        $this->stack[] = array();
    }

    /**
     * Load set items
     */
    protected function loadSetItems()
    {
        $k    =  $this->lastMarker();
        $dict =& $this->stack[$k - 1];
        $max  =  count($this->stack);
        for ($i = $k + 1; $i < $max; $i += 2) {
            $key        = $this->stack[$i];
            $value      = $this->stack[$i + 1];
            $dict[$key] = $value;
            unset($this->stack[$i], $this->stack[$i+1]);
        }
        unset($this->stack[$k]);
    }

    /**
     * Load a tuple
     */
    protected function loadTuple()
    {
        $k                =  $this->lastMarker();
        $this->stack[$k]  =  array();
        $tuple            =& $this->stack[$k];
        $max              =  count($this->stack);
        for ($i = $k + 1; $i < $max; $i++) {
            $tuple[] = $this->stack[$i];
            unset($this->stack[$i]);
        }
    }

    /**
     * Load single item tuple
     */
    protected function loadTuple1()
    {
        $value1        = array_pop($this->stack);
        $this->stack[] = array($value1);
    }

    /**
     * Load two item tuple
     *
     */
    protected function loadTuple2()
    {
        $value2 = array_pop($this->stack);
        $value1 = array_pop($this->stack);
        $this->stack[] = array($value1, $value2);
    }

    /**
     * Load three item tuple
     *
     */
    protected function loadTuple3()
    {
        $value3 = array_pop($this->stack);
        $value2 = array_pop($this->stack);
        $value1 = array_pop($this->stack);
        $this->stack[] = array($value1, $value2, $value3);
    }

    /**
     * Load a proto value
     *
     * @throws Exception\RuntimeException if Pickle version does not support this feature
     */
    protected function loadProto()
    {
        $proto = ord($this->read(1));
        if ($proto < 2 || $proto > 3) {
            throw new Exception\RuntimeException(
                "Invalid or unknown protocol version '{$proto}' detected"
            );
        }
        $this->protocol = $proto;
    }

    /* unserialize helper */

    /**
     * Read a segment of the pickle
     *
     * @param  mixed $len
     * @return string
     * @throws Exception\RuntimeException if position matches end of data
     */
    protected function read($len)
    {
        if (($this->pos + $len) > $this->pickleLen) {
            throw new Exception\RuntimeException('End of data');
        }

        $this->pos += $len;
        return substr($this->pickle, ($this->pos - $len), $len);
    }

    /**
     * Read a line of the pickle at once
     *
     * @return string
     * @throws Exception\RuntimeException if no EOL character found
     */
    protected function readline()
    {
        $eolLen = 2;
        $eolPos = strpos($this->pickle, "\r\n", $this->pos);
        if ($eolPos === false) {
            $eolPos = strpos($this->pickle, "\n", $this->pos);
            $eolLen = 1;
        }

        if ($eolPos === false) {
            throw new Exception\RuntimeException('No new line found');
        }
        $ret       = substr($this->pickle, $this->pos, $eolPos-$this->pos);
        $this->pos = $eolPos + $eolLen;

        return $ret;
    }

    /**
     * Unquote/Unescape a quoted string
     *
     * @param  string $str quoted string
     * @return string unquoted string
     */
    protected function unquoteString($str)
    {
        $quoteArr = array_flip(static::$quoteString);

        if ($str[0] == '"') {
            $quoteArr['\\"'] = '"';
        } else {
            $quoteArr["\\'"] = "'";
        }

        return strtr(substr(trim($str), 1, -1), $quoteArr);
    }

    /**
     * Return last marker position in stack
     *
     * @return int
     */
    protected function lastMarker()
    {
        for ($k = count($this->stack)-1; $k >= 0; $k -= 1) {
            if ($this->stack[$k] === $this->marker) {
                break;
            }
        }
        return $k;
    }

    /**
     * Decode a binary long sequence
     *
     * @param  string $data
     * @return int|float|string
     */
    protected function decodeBinLong($data)
    {
        $nbytes = strlen($data);

        if ($nbytes == 0) {
            return 0;
        }

        $long = 0;
        if ($nbytes > 7) {
            if ($this->bigIntegerAdapter === null) {
                $this->bigIntegerAdapter = BigInteger\BigInteger::getDefaultAdapter();
            }
            if (static::$isLittleEndian === true) {
                $data = strrev($data);
            }
            $long = $this->bigIntegerAdapter->binToInt($data, true);
        } else {
            for ($i = 0; $i < $nbytes; $i++) {
                $long += ord($data[$i]) * pow(256, $i);
            }
            if (0x80 <= ord($data[$nbytes - 1])) {
                $long -= pow(2, $nbytes * 8);
                // $long-= 1 << ($nbytes * 8);
            }
        }

        return $long;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Serializer\Adapter;


class WddxOptions extends AdapterOptions
{
    /**
     * Wddx packet header comment
     *
     * @var string
     */
    protected $comment = '';

    /**
     * Set WDDX header comment
     *
     * @param  string $comment
     * @return WddxOptions
     */
    public function setComment($comment)
    {
        $this->comment = (string) $comment;
        return $this;
    }

    /**
     * Get WDDX header comment
     *
     * @return string
     */
    public function getComment()
    {
        return $this->comment;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Serializer\Adapter;

use Zend\Serializer\Exception;
use Zend\Stdlib\ErrorHandler;

class PhpSerialize extends AbstractAdapter
{
    /**
     * Serialized boolean false value
     *
     * @var null|string
     */
    private static $serializedFalse = null;

    /**
     * Constructor
     */
    public function __construct($options = null)
    {
        // needed to check if a returned false is based on a serialize false
        // or based on failure (igbinary can overwrite [un]serialize functions)
        if (static::$serializedFalse === null) {
            static::$serializedFalse = serialize(false);
        }

        parent::__construct($options);
    }

    /**
     * Serialize using serialize()
     *
     * @param  mixed $value
     * @return string
     * @throws Exception\RuntimeException On serialize error
     */
    public function serialize($value)
    {
        ErrorHandler::start();
        $ret = serialize($value);
        $err = ErrorHandler::stop();
        if ($err) {
            throw new Exception\RuntimeException(
                'Serialization failed', 0, $err
            );
        }

        return $ret;
    }

    /**
     * Unserialize
     *
     * @todo   Allow integration with unserialize_callback_func
     * @param  string $serialized
     * @return mixed
     * @throws Exception\RuntimeException on unserialize error
     */
    public function unserialize($serialized)
    {
        if (!is_string($serialized) || !preg_match('/^((s|i|d|b|a|O|C):|N;)/', $serialized)) {
            return $serialized;
        }

        // If we have a serialized boolean false value, just return false;
        // prevents the unserialize handler from creating an error.
        if ($serialized === static::$serializedFalse) {
            return false;
        }

        ErrorHandler::start(E_NOTICE);
        $ret = unserialize($serialized);
        $err = ErrorHandler::stop();
        if ($ret === false) {
            throw new Exception\RuntimeException('Unserialization failed', 0, $err);
        }

        return $ret;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Serializer\Adapter;

interface AdapterInterface
{
    /**
     * Generates a storable representation of a value.
     *
     * @param  mixed $value Data to serialize
     * @return string
     * @throws \Zend\Serializer\Exception\ExceptionInterface
     */
    public function serialize($value);

    /**
     * Creates a PHP value from a stored representation.
     *
     * @param  string $serialized Serialized string
     * @return mixed
     * @throws \Zend\Serializer\Exception\ExceptionInterface
     */
    public function unserialize($serialized);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Serializer\Adapter;

use Zend\Serializer\Exception;
use Zend\Stdlib\ErrorHandler;

/**
 * @link       http://www.infoloom.com/gcaconfs/WEB/chicago98/simeonov.HTM
 * @link       http://en.wikipedia.org/wiki/WDDX
 */
class Wddx extends AbstractAdapter
{
    /**
     * @var WddxOptions
     */
    protected $options = null;

    /**
     * Constructor
     *
     * @param  array|\Traversable|WddxOptions $options
     * @throws Exception\ExtensionNotLoadedException if wddx extension not found
     */
    public function __construct($options = null)
    {
        if (!extension_loaded('wddx')) {
            throw new Exception\ExtensionNotLoadedException(
                'PHP extension "wddx" is required for this adapter'
            );
        }

        parent::__construct($options);
    }

    /**
     * Set options
     *
     * @param  array|\Traversable|WddxOptions $options
     * @return Wddx
     */
    public function setOptions($options)
    {
        if (!$options instanceof WddxOptions) {
            $options = new WddxOptions($options);
        }

        $this->options = $options;
        return $this;
    }

    /**
     * Get options
     *
     * @return WddxOptions
     */
    public function getOptions()
    {
        if ($this->options === null) {
            $this->options = new WddxOptions();
        }
        return $this->options;
    }

    /**
     * Serialize PHP to WDDX
     *
     * @param  mixed $value
     * @return string
     * @throws Exception\RuntimeException on wddx error
     */
    public function serialize($value)
    {
        $comment = $this->getOptions()->getComment();

        ErrorHandler::start();
        if ($comment !== '') {
            $wddx = wddx_serialize_value($value, $comment);
        } else {
            $wddx = wddx_serialize_value($value);
        }
        $error = ErrorHandler::stop();

        if ($wddx === false) {
            throw new Exception\RuntimeException('Serialization failed', 0, $error);
        }

        return $wddx;
    }

    /**
     * Unserialize from WDDX to PHP
     *
     * @param  string $wddx
     * @return mixed
     * @throws Exception\RuntimeException on wddx error
     * @throws Exception\InvalidArgumentException if invalid xml
     */
    public function unserialize($wddx)
    {
        $ret = wddx_deserialize($wddx);

        if ($ret === null && class_exists('SimpleXMLElement', false)) {
            // check if the returned NULL is valid
            // or based on an invalid wddx string
            try {
                $oldLibxmlDisableEntityLoader = libxml_disable_entity_loader(true);
                $dom = new \DOMDocument;
                $dom->loadXML($wddx);
                foreach ($dom->childNodes as $child) {
                    if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) {
                        throw new Exception\InvalidArgumentException(
                            'Invalid XML: Detected use of illegal DOCTYPE'
                        );
                    }
                }
                $simpleXml = simplexml_import_dom($dom);
                //$simpleXml = new \SimpleXMLElement($wddx);
                libxml_disable_entity_loader($oldLibxmlDisableEntityLoader);
                if (isset($simpleXml->data[0]->null[0])) {
                    return null; // valid null
                }
                throw new Exception\RuntimeException('Unserialization failed: Invalid wddx packet');
            } catch (\Exception $e) {
                throw new Exception\RuntimeException('Unserialization failed: ' . $e->getMessage(), 0, $e);
            }
        }

        return $ret;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Serializer\Adapter;

use Zend\Serializer\Exception;
use Zend\Stdlib\ErrorHandler;

class IgBinary extends AbstractAdapter
{
    /**
     * @var string Serialized null value
     */
    private static $serializedNull = null;

    /**
     * Constructor
     *
     * @throws Exception\ExtensionNotLoadedException If igbinary extension is not present
     */
    public function __construct($options = null)
    {
        if (!extension_loaded('igbinary')) {
            throw new Exception\ExtensionNotLoadedException(
                'PHP extension "igbinary" is required for this adapter'
            );
        }

        if (static::$serializedNull === null) {
            static::$serializedNull = igbinary_serialize(null);
        }

        parent::__construct($options);
    }

    /**
     * Serialize PHP value to igbinary
     *
     * @param  mixed $value
     * @return string
     * @throws Exception\RuntimeException on igbinary error
     */
    public function serialize($value)
    {
        ErrorHandler::start();
        $ret = igbinary_serialize($value);
        $err = ErrorHandler::stop();

        if ($ret === false) {
            throw new Exception\RuntimeException('Serialization failed', 0, $err);
        }

        return $ret;
    }

    /**
     * Deserialize igbinary string to PHP value
     *
     * @param  string $serialized
     * @return mixed
     * @throws Exception\RuntimeException on igbinary error
     */
    public function unserialize($serialized)
    {
        if ($serialized === static::$serializedNull) {
            return null;
        }

        ErrorHandler::start();
        $ret = igbinary_unserialize($serialized);
        $err = ErrorHandler::stop();

        if ($ret === null) {
            throw new Exception\RuntimeException('Unserialization failed', 0, $err);
        }

        return $ret;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Serializer\Adapter;

use Zend\Serializer\Exception;
use Zend\Stdlib\ErrorHandler;

class MsgPack extends AbstractAdapter
{
    /**
     * @var string Serialized 0 value
     */
    private static $serialized0 = null;

    /**
     * Constructor
     *
     * @throws Exception\ExtensionNotLoadedException If msgpack extension is not present
     */
    public function __construct($options = null)
    {
        if (!extension_loaded('msgpack')) {
            throw new Exception\ExtensionNotLoadedException(
                'PHP extension "msgpack" is required for this adapter'
            );
        }

        if (static::$serialized0 === null) {
            static::$serialized0 = msgpack_serialize(0);
        }

        parent::__construct($options);
    }

    /**
     * Serialize PHP value to msgpack
     *
     * @param  mixed $value
     * @return string
     * @throws Exception\RuntimeException on msgpack error
     */
    public function serialize($value)
    {
        ErrorHandler::start();
        $ret = msgpack_serialize($value);
        $err = ErrorHandler::stop();

        if ($ret === false) {
            throw new Exception\RuntimeException('Serialization failed', 0, $err);
        }

        return $ret;
    }

    /**
     * Deserialize msgpack string to PHP value
     *
     * @param  string $serialized
     * @return mixed
     * @throws Exception\RuntimeException on msgpack error
     */
    public function unserialize($serialized)
    {
        if ($serialized === static::$serialized0) {
            return 0;
        }

        ErrorHandler::start();
        $ret = msgpack_unserialize($serialized);
        $err = ErrorHandler::stop();

        if ($ret === 0) {
            throw new Exception\RuntimeException('Unserialization failed', 0, $err);
        }

        return $ret;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Serializer\Adapter;

use Zend\Serializer\Exception;

class PythonPickleOptions extends AdapterOptions
{
    /**
     * Pickle protocol version to serialize data
     *
     * @var int
     */
    protected $protocol = 0;

    /**
     * Set pickle protocol version to serialize data
     *
     * Supported versions are 0, 1, 2 and 3
     *
     * @param  int $protocol
     * @return PythonPickleOptions
     * @throws Exception\InvalidArgumentException
     */
    public function setProtocol($protocol)
    {
        $protocol = (int) $protocol;
        if ($protocol < 0 || $protocol > 3) {
            throw new Exception\InvalidArgumentException(
                "Invalid or unknown protocol version '{$protocol}'"
            );
        }

        $this->protocol = $protocol;

        return $this;
    }

    /**
     * Get pickle protocol version to serialize data
     *
     * @return int
     */
    public function getProtocol()
    {
        return $this->protocol;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Serializer\Adapter;

abstract class AbstractAdapter implements AdapterInterface
{
    /**
     * @var AdapterOptions
     */
    protected $options = null;

    /**
     * Constructor
     *
     * @param array|\Traversable|AdapterOptions $options
     */
    public function __construct($options = null)
    {
        if ($options !== null) {
            $this->setOptions($options);
        }
    }

    /**
     * Set adapter options
     *
     * @param  array|\Traversable|AdapterOptions $options
     * @return AbstractAdapter
     */
    public function setOptions($options)
    {
        if (!$options instanceof AdapterOptions) {
            $options = new AdapterOptions($options);
        }

        $this->options = $options;
        return $this;
    }

    /**
     * Get adapter options
     *
     * @return AdapterOptions
     */
    public function getOptions()
    {
        if ($this->options === null) {
            $this->options = new AdapterOptions();
        }
        return $this->options;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Serializer\Adapter;

use Zend\Json\Json as ZendJson;
use Zend\Serializer\Exception;

class Json extends AbstractAdapter
{
    /**
     * @var JsonOptions
     */
    protected $options = null;

    /**
     * Set options
     *
     * @param  array|\Traversable|JsonOptions $options
     * @return Json
     */
    public function setOptions($options)
    {
        if (!$options instanceof JsonOptions) {
            $options = new JsonOptions($options);
        }

        $this->options = $options;
        return $this;
    }

    /**
     * Get options
     *
     * @return JsonOptions
     */
    public function getOptions()
    {
        if ($this->options === null) {
            $this->options = new JsonOptions();
        }
        return $this->options;
    }

    /**
     * Serialize PHP value to JSON
     *
     * @param  mixed $value
     * @return string
     * @throws Exception\InvalidArgumentException
     * @throws Exception\RuntimeException
     */
    public function serialize($value)
    {
        $options    = $this->getOptions();
        $cycleCheck = $options->getCycleCheck();
        $opts = array(
            'enableJsonExprFinder' => $options->getEnableJsonExprFinder(),
            'objectDecodeType'     => $options->getObjectDecodeType(),
        );

        try {
            return ZendJson::encode($value, $cycleCheck, $opts);
        } catch (\InvalidArgumentException $e) {
            throw new Exception\InvalidArgumentException('Serialization failed: ' . $e->getMessage(), 0, $e);
        } catch (\Exception $e) {
            throw new Exception\RuntimeException('Serialization failed: ' . $e->getMessage(), 0, $e);
        }
    }

    /**
     * Deserialize JSON to PHP value
     *
     * @param  string $json
     * @return mixed
     * @throws Exception\InvalidArgumentException
     * @throws Exception\RuntimeException
     */
    public function unserialize($json)
    {
        try {
            $ret = ZendJson::decode($json, $this->getOptions()->getObjectDecodeType());
        } catch (\InvalidArgumentException $e) {
            throw new Exception\InvalidArgumentException('Unserialization failed: ' . $e->getMessage(), 0, $e);
        } catch (\Exception $e) {
            throw new Exception\RuntimeException('Unserialization failed: ' . $e->getMessage(), 0, $e);
        }

        return $ret;
    }
}
{
    "name": "zendframework/zend-i18n",
    "description": " ",
    "license": "BSD-3-Clause",
    "keywords": [
        "zf2",
        "i18n"
    ],
    "autoload": {
        "psr-0": {
            "Zend\\I18n\\": ""
        }
    },
    "target-dir": "Zend/I18n",
    "require": {
        "php": ">=5.3.3",
        "zendframework/zend-stdlib": "self.version"
    },
    "suggest": {
        "ext-intl": "Required for most features of Zend\\I18n; included in default builds of PHP",
        "zendframework/zend-eventmanager": "You should install this package to use the events in the translator",
        "zendframework/zend-filter": "You should install this package to use the provided filters",
        "zendframework/zend-validator": "You should install this package to use the provided validators",
        "zendframework/zend-view": "You should install this package to use the provided view helpers",
        "zendframework/zend-resources": "Translation resources"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "2.2-dev",
            "dev-develop": "2.3-dev"
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Translator;

interface TranslatorAwareInterface
{
    /**
     * Sets translator to use in helper
     *
     * @param  Translator $translator  [optional] translator.
     *                                 Default is null, which sets no translator.
     * @param  string     $textDomain  [optional] text domain
     *                                 Default is null, which skips setTranslatorTextDomain
     * @return TranslatorAwareInterface
     */
    public function setTranslator(Translator $translator = null, $textDomain = null);

    /**
     * Returns translator used in object
     *
     * @return Translator|null
     */
    public function getTranslator();

    /**
     * Checks if the object has a translator
     *
     * @return bool
     */
    public function hasTranslator();

    /**
     * Sets whether translator is enabled and should be used
     *
     * @param  bool $enabled [optional] whether translator should be used.
     *                       Default is true.
     * @return TranslatorAwareInterface
     */
    public function setTranslatorEnabled($enabled = true);

    /**
     * Returns whether translator is enabled and should be used
     *
     * @return bool
     */
    public function isTranslatorEnabled();

    /**
     * Set translation text domain
     *
     * @param  string $textDomain
     * @return TranslatorAwareInterface
     */
    public function setTranslatorTextDomain($textDomain = 'default');

    /**
     * Return the translation text domain
     *
     * @return string
     */
    public function getTranslatorTextDomain();

}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Translator\Plural;

use Zend\I18n\Exception;

/**
 * Plural rule parser.
 *
 * This plural rule parser is implemented after the article "Top Down Operator
 * Precedence" described in <http://javascript.crockford.com/tdop/tdop.html>.
 */
class Parser
{
    /**
     * String to parse.
     *
     * @var string
     */
    protected $string;

    /**
     * Current lexer position in the string.
     *
     * @var int
     */
    protected $currentPos;

    /**
     * Current token.
     *
     * @var Symbol
     */
    protected $currentToken;

    /**
     * Table of symbols.
     *
     * @var array
     */
    protected $symbolTable = array();

    /**
     * Create a new plural parser.
     *
     */
    public function __construct()
    {
        $this->populateSymbolTable();
    }

    /**
     * Populate the symbol table.
     *
     * @return void
     */
    protected function populateSymbolTable()
    {
        // Ternary operators
        $this->registerSymbol('?', 20)->setLeftDenotationGetter(
            function (Symbol $self, Symbol $left) {
                $self->first  = $left;
                $self->second = $self->parser->expression();
                $self->parser->advance(':');
                $self->third  = $self->parser->expression();
                return $self;
            }
        );
        $this->registerSymbol(':');

        // Boolean operators
        $this->registerLeftInfixSymbol('||', 30);
        $this->registerLeftInfixSymbol('&&', 40);

        // Equal operators
        $this->registerLeftInfixSymbol('==', 50);
        $this->registerLeftInfixSymbol('!=', 50);

        // Compare operators
        $this->registerLeftInfixSymbol('>', 50);
        $this->registerLeftInfixSymbol('<', 50);
        $this->registerLeftInfixSymbol('>=', 50);
        $this->registerLeftInfixSymbol('<=', 50);

        // Add operators
        $this->registerLeftInfixSymbol('-', 60);
        $this->registerLeftInfixSymbol('+', 60);

        // Multiply operators
        $this->registerLeftInfixSymbol('*', 70);
        $this->registerLeftInfixSymbol('/', 70);
        $this->registerLeftInfixSymbol('%', 70);

        // Not operator
        $this->registerPrefixSymbol('!', 80);

        // Literals
        $this->registerSymbol('n')->setNullDenotationGetter(
            function (Symbol $self) {
                return $self;
            }
        );
        $this->registerSymbol('number')->setNullDenotationGetter(
            function (Symbol $self) {
                return $self;
            }
        );

        // Parentheses
        $this->registerSymbol('(')->setNullDenotationGetter(
            function (Symbol $self) {
                $expression = $self->parser->expression();
                $self->parser->advance(')');
                return $expression;
            }
        );
        $this->registerSymbol(')');

        // Eof
        $this->registerSymbol('eof');
    }

    /**
     * Register a left infix symbol.
     *
     * @param  string  $id
     * @param  int $leftBindingPower
     * @return void
     */
    protected function registerLeftInfixSymbol($id, $leftBindingPower)
    {
        $this->registerSymbol($id, $leftBindingPower)->setLeftDenotationGetter(
            function (Symbol $self, Symbol $left) use ($leftBindingPower) {
                $self->first  = $left;
                $self->second = $self->parser->expression($leftBindingPower);
                return $self;
            }
        );
    }

    /**
     * Register a right infix symbol.
     *
     * @param  string  $id
     * @param  int $leftBindingPower
     * @return void
     */
    protected function registerRightInfixSymbol($id, $leftBindingPower)
    {
        $this->registerSymbol($id, $leftBindingPower)->setLeftDenotationGetter(
            function (Symbol $self, Symbol $left) use ($leftBindingPower) {
                $self->first  = $left;
                $self->second = $self->parser->expression($leftBindingPower - 1);
                return $self;
            }
        );
    }

    /**
     * Register a prefix symbol.
     *
     * @param  string  $id
     * @param  int $leftBindingPower
     * @return void
     */
    protected function registerPrefixSymbol($id, $leftBindingPower)
    {
        $this->registerSymbol($id, $leftBindingPower)->setNullDenotationGetter(
            function (Symbol $self) use ($leftBindingPower) {
                $self->first  = $self->parser->expression($leftBindingPower);
                $self->second = null;
                return $self;
            }
        );
    }

    /**
     * Register a symbol.
     *
     * @param  string  $id
     * @param  int $leftBindingPower
     * @return Symbol
     */
    protected function registerSymbol($id, $leftBindingPower = 0)
    {
        if (isset($this->symbolTable[$id])) {
            $symbol = $this->symbolTable[$id];
            $symbol->leftBindingPower = max(
                $symbol->leftBindingPower,
                $leftBindingPower
            );
        } else {
            $symbol = new Symbol($this, $id, $leftBindingPower);
            $this->symbolTable[$id] = $symbol;
        }

        return $symbol;
    }

    /**
     * Get a new symbol.
     *
     * @param string $id
     */
    protected function getSymbol($id)
    {
        if (!isset($this->symbolTable[$id])) {
            // Unkown symbol exception
        }

        return clone $this->symbolTable[$id];
    }

    /**
     * Parse a string.
     *
     * @param  string $string
     * @return array
     */
    public function parse($string)
    {
        $this->string       = $string . "\0";
        $this->currentPos   = 0;
        $this->currentToken = $this->getNextToken();

        return $this->expression();
    }

    /**
     * Parse an expression.
     *
     * @param  int $rightBindingPower
     * @return Symbol
     */
    public function expression($rightBindingPower = 0)
    {
        $token              = $this->currentToken;
        $this->currentToken = $this->getNextToken();
        $left               = $token->getNullDenotation();

        while ($rightBindingPower < $this->currentToken->leftBindingPower) {
            $token              = $this->currentToken;
            $this->currentToken = $this->getNextToken();
            $left               = $token->getLeftDenotation($left);
        }

        return $left;
    }

    /**
     * Advance the current token and optionally check the old token id.
     *
     * @param  string $id
     * @return void
     * @throws Exception\ParseException
     */
    public function advance($id = null)
    {
        if ($id !== null && $this->currentToken->id !== $id) {
            throw new Exception\ParseException(sprintf(
                'Expected token with id %s but received %s',
                $id, $this->currentToken->id
            ));
        }

        $this->currentToken = $this->getNextToken();
    }

    /**
     * Get the next token.
     *
     * @return array
     * @throws Exception\ParseException
     */
    protected function getNextToken()
    {
        while ($this->string[$this->currentPos] === ' ' || $this->string[$this->currentPos] === "\t") {
            $this->currentPos++;
        }

        $result = $this->string[$this->currentPos++];
        $value  = null;

        switch ($result) {
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
                while (ctype_digit($this->string[$this->currentPos])) {
                    $result .= $this->string[$this->currentPos++];
                }

                $id    = 'number';
                $value = (int) $result;
                break;

            case '=':
            case '&':
            case '|':
                if ($this->string[$this->currentPos] === $result) {
                    $this->currentPos++;
                    $id = $result . $result;
                } else {
                    // Yield error
                }
                break;

            case '!':
            case '<':
            case '>':
                if ($this->string[$this->currentPos] === '=') {
                    $this->currentPos++;
                    $result .= '=';
                }

                $id = $result;
                break;

            case '*':
            case '/':
            case '%':
            case '+':
            case '-':
            case 'n':
            case '?':
            case ':':
            case '(':
            case ')':
                $id = $result;
                break;

            case ';':
            case "\n":
            case "\0":
                $id = 'eof';
                $this->currentPos--;
                break;

            default:
                throw new Exception\ParseException(sprintf(
                    'Found invalid character "%s" in input stream',
                    $result
                ));
                break;
        }

        $token = $this->getSymbol($id);
        $token->value = $value;

        return $token;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Translator\Plural;

use Zend\I18n\Exception;

/**
 * Plural rule evaluator.
 */
class Rule
{
    /**
     * Parser instance.
     *
     * @var Parser
     */
    protected static $parser;

    /**
     * Abstract syntax tree.
     *
     * @var array
     */
    protected $ast;

    /**
     * Number of plurals in this rule.
     *
     * @var int
     */
    protected $numPlurals;

    /**
     * Create a new plural rule.
     *
     * @param  int $numPlurals
     * @param  array   $ast
     * @return Rule
     */
    protected function __construct($numPlurals, array $ast)
    {
        $this->numPlurals = $numPlurals;
        $this->ast        = $ast;
    }

    /**
     * Evaluate a number and return the plural index.
     *
     * @param  int $number
     * @return int
     * @throws Exception\RangeException
     */
    public function evaluate($number)
    {
        $result = $this->evaluateAstPart($this->ast, abs((int) $number));

        if ($result < 0 || $result >= $this->numPlurals) {
            throw new Exception\RangeException(sprintf(
                'Calculated result %s is between 0 and %d',
                $result, ($this->numPlurals - 1)
            ));
        }

        return $result;
    }

    /**
     * Get number of possible plural forms.
     *
     * @return int
     */
    public function getNumPlurals()
    {
        return $this->numPlurals;
    }

    /**
     * Evaluate a part of an ast.
     *
     * @param  array   $ast
     * @param  int $number
     * @return int
     * @throws Exception\ParseException
     */
    protected function evaluateAstPart(array $ast, $number)
    {
        switch ($ast['id']) {
            case 'number':
                return $ast['arguments'][0];

            case 'n':
                return $number;

            case '+':
                return $this->evaluateAstPart($ast['arguments'][0], $number)
                       + $this->evaluateAstPart($ast['arguments'][1], $number);

            case '-':
                return $this->evaluateAstPart($ast['arguments'][0], $number)
                       - $this->evaluateAstPart($ast['arguments'][1], $number);

            case '/':
                // Integer division
                return floor(
                    $this->evaluateAstPart($ast['arguments'][0], $number)
                    / $this->evaluateAstPart($ast['arguments'][1], $number)
                );

            case '*':
                return $this->evaluateAstPart($ast['arguments'][0], $number)
                       * $this->evaluateAstPart($ast['arguments'][1], $number);

            case '%':
                return $this->evaluateAstPart($ast['arguments'][0], $number)
                       % $this->evaluateAstPart($ast['arguments'][1], $number);

            case '>':
                return $this->evaluateAstPart($ast['arguments'][0], $number)
                       > $this->evaluateAstPart($ast['arguments'][1], $number)
                       ? 1 : 0;

            case '>=':
                return $this->evaluateAstPart($ast['arguments'][0], $number)
                       >= $this->evaluateAstPart($ast['arguments'][1], $number)
                       ? 1 : 0;

            case '<':
                return $this->evaluateAstPart($ast['arguments'][0], $number)
                       < $this->evaluateAstPart($ast['arguments'][1], $number)
                       ? 1 : 0;

            case '<=':
                return $this->evaluateAstPart($ast['arguments'][0], $number)
                       <= $this->evaluateAstPart($ast['arguments'][1], $number)
                       ? 1 : 0;

            case '==':
                return $this->evaluateAstPart($ast['arguments'][0], $number)
                       == $this->evaluateAstPart($ast['arguments'][1], $number)
                       ? 1 : 0;

            case '!=':
                return $this->evaluateAstPart($ast['arguments'][0], $number)
                       != $this->evaluateAstPart($ast['arguments'][1], $number)
                       ? 1 : 0;

            case '&&':
                return $this->evaluateAstPart($ast['arguments'][0], $number)
                       && $this->evaluateAstPart($ast['arguments'][1], $number)
                       ? 1 : 0;

            case '||':
                return $this->evaluateAstPart($ast['arguments'][0], $number)
                       || $this->evaluateAstPart($ast['arguments'][1], $number)
                       ? 1 : 0;

            case '!':
                return !$this->evaluateAstPart($ast['arguments'][0], $number)
                       ? 1 : 0;

            case '?':
                return $this->evaluateAstPart($ast['arguments'][0], $number)
                       ? $this->evaluateAstPart($ast['arguments'][1], $number)
                       : $this->evaluateAstPart($ast['arguments'][2], $number);

            default:
                throw new Exception\ParseException(sprintf(
                    'Unknown token: %s',
                    $ast['id']
                ));
        }
    }

    /**
     * Create a new rule from a string.
     *
     * @param  string $string
     * @throws Exception\ParseException
     * @return Rule
     */
    public static function fromString($string)
    {
        if (static::$parser === null) {
            static::$parser = new Parser();
        }

        if (!preg_match('(nplurals=(?P<nplurals>\d+))', $string, $match)) {
            throw new Exception\ParseException(sprintf(
                'Unknown or invalid parser rule: %s',
                $string
            ));
        }

        $numPlurals = (int) $match['nplurals'];

        if (!preg_match('(plural=(?P<plural>[^;\n]+))', $string, $match)) {
            throw new Exception\ParseException(sprintf(
                'Unknown or invalid parser rule: %s',
                $string
            ));
        }

        $tree = static::$parser->parse($match['plural']);
        $ast  = static::createAst($tree);

        return new static($numPlurals, $ast);
    }

    /**
     * Create an AST from a tree.
     *
     * Theoretically we could just use the given Symbol, but that one is not
     * so easy to serialize and also takes up more memory.
     *
     * @param  Symbol $symbol
     * @return array
     */
    protected static function createAst(Symbol $symbol)
    {
        $ast = array('id' => $symbol->id, 'arguments' => array());

        switch ($symbol->id) {
            case 'n':
                break;

            case 'number':
                $ast['arguments'][] = $symbol->value;
                break;

            case '!':
                $ast['arguments'][] = static::createAst($symbol->first);
                break;

            case '?':
                $ast['arguments'][] = static::createAst($symbol->first);
                $ast['arguments'][] = static::createAst($symbol->second);
                $ast['arguments'][] = static::createAst($symbol->third);
                break;

            default:
                $ast['arguments'][] = static::createAst($symbol->first);
                $ast['arguments'][] = static::createAst($symbol->second);
                break;
        }

        return $ast;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Translator\Plural;

use Closure;
use Zend\I18n\Exception;

/**
 * Parser symbol.
 *
 * All properties in the symbol are defined as public for easier and faster
 * access from the applied closures. An exception are the closure properties
 * themselves, as they have to be accessed via the appropriate getter and
 * setter methods.
 */
class Symbol
{
    /**
     * Parser instance.
     *
     * @var Parser
     */
    public $parser;

    /**
     * Node or token type name.
     *
     * @var string
     */
    public $id;

    /**
     * Left binding power (precedence).
     *
     * @var int
     */
    public $leftBindingPower;

    /**
     * Getter for null denotation.
     *
     * @var callable
     */
    protected $nullDenotationGetter;

    /**
     * Getter for left denotation.
     *
     * @var callable
     */
    protected $leftDenotationGetter;

    /**
     * Value used by literals.
     *
     * @var mixed
     */
    public $value;

    /**
     * First node value.
     *
     * @var Symbol
     */
    public $first;

    /**
     * Second node value.
     *
     * @var Symbol
     */
    public $second;

    /**
     * Third node value.
     *
     * @var Symbol
     */
    public $third;

    /**
     * Create a new symbol.
     *
     * @param  Parser  $parser
     * @param  string  $id
     * @param  int $leftBindingPower
     */
    public function __construct(Parser $parser, $id, $leftBindingPower)
    {
        $this->parser               = $parser;
        $this->id                   = $id;
        $this->leftBindingPower     = $leftBindingPower;
    }

    /**
     * Set the null denotation getter.
     *
     * @param  Closure $getter
     * @return Symbol
     */
    public function setNullDenotationGetter(Closure $getter)
    {
        $this->nullDenotationGetter = $getter;
        return $this;
    }

    /**
     * Set the left denotation getter.
     *
     * @param  Closure $getter
     * @return Symbol
     */
    public function setLeftDenotationGetter(Closure $getter)
    {
        $this->leftDenotationGetter = $getter;
        return $this;
    }

    /**
     * Get null denotation.
     *
     * @throws Exception\ParseException
     * @return Symbol
     */
    public function getNullDenotation()
    {
        if ($this->nullDenotationGetter === null) {
            throw new Exception\ParseException(sprintf(
                'Syntax error: %s', $this->id
            ));
        }

        /** @var callable $function  */
        $function = $this->nullDenotationGetter;
        return $function($this);
    }

    /**
     * Get left denotation.
     *
     * @param  Symbol $left
     * @throws Exception\ParseException
     * @return Symbol
     */
    public function getLeftDenotation($left)
    {
        if ($this->leftDenotationGetter === null) {
            throw new Exception\ParseException(sprintf(
                'Unknown operator: %s', $this->id
            ));
        }

        /** @var callable $function  */
        $function = $this->leftDenotationGetter;
        return $function($this, $left);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Translator;

use Zend\I18n\Translator\Translator;

trait TranslatorAwareTrait
{
    /**
     * @var Translator
     */
    protected $translator = null;

    /**
     * @var bool
     */
    protected $translatorEnabled = true;

    /**
     * @var string
     */
    protected $translatorTextDomain = 'default';

    /**
     * Sets translator to use in helper
     *
     * @param Translator $translator
     * @param string $textDomain
     * @return mixed
     */
    public function setTranslator(Translator $translator = null, $textDomain = null)
    {
        $this->translator = $translator;

        if (!is_null($textDomain)) {
            $this->setTranslatorTextDomain($textDomain);
        }

        return $this;
    }

    /**
     * Returns translator used in object
     *
     * @return Translator
     */
    public function getTranslator()
    {
        return $this->translator;
    }

    /**
     * Checks if the object has a translator
     *
     * @return bool
     */
    public function hasTranslator()
    {
        return !is_null($this->translator);
    }

    /**
     * Sets whether translator is enabled and should be used
     *
     * @param bool $enabled
     * @return mixed
     */
    public function setTranslatorEnabled($enabled = true)
    {
        $this->translatorEnabled = $enabled;

        return $this;
    }

    /**
     * Returns whether translator is enabled and should be used
     *
     * @return bool
     */
    public function isTranslatorEnabled()
    {
        return $this->translatorEnabled;
    }

    /**
     * Set translation text domain
     *
     * @param string $textDomain
     * @return mixed
     */
    public function setTranslatorTextDomain($textDomain = 'default')
    {
        $this->translatorTextDomain = $textDomain;

        return $this;
    }

    /**
     * Return the translation text domain
     *
     * @return string
     */
    public function getTranslatorTextDomain()
    {
        return $this->translatorTextDomain;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Translator;

use Locale;
use Traversable;
use Zend\Cache;
use Zend\Cache\Storage\StorageInterface as CacheStorage;
use Zend\EventManager\EventManager;
use Zend\EventManager\EventManagerInterface;
use Zend\I18n\Exception;
use Zend\I18n\Translator\Loader\FileLoaderInterface;
use Zend\I18n\Translator\Loader\RemoteLoaderInterface;
use Zend\Stdlib\ArrayUtils;

/**
 * Translator.
 */
class Translator
{
    /**
     * Event fired when the translation for a message is missing.
     */
    const EVENT_MISSING_TRANSLATION = 'missingTranslation';

    /**
     * Event fired when no messages were loaded for a locale/text-domain combination.
     */
    const EVENT_NO_MESSAGES_LOADED = 'noMessagesLoaded';

    /**
     * Messages loaded by the translator.
     *
     * @var array
     */
    protected $messages = array();

    /**
     * Files used for loading messages.
     *
     * @var array
     */
    protected $files = array();

    /**
     * Patterns used for loading messages.
     *
     * @var array
     */
    protected $patterns = array();

    /**
     * Remote locations for loading messages.
     *
     * @var array
     */
    protected $remote = array();

    /**
     * Default locale.
     *
     * @var string
     */
    protected $locale;

    /**
     * Locale to use as fallback if there is no translation.
     *
     * @var string
     */
    protected $fallbackLocale;

    /**
     * Translation cache.
     *
     * @var CacheStorage
     */
    protected $cache;

    /**
     * Plugin manager for translation loaders.
     *
     * @var LoaderPluginManager
     */
    protected $pluginManager;

    /**
     * Event manager for triggering translator events.
     *
     * @var EventManagerInterface
     */
    protected $events;

    /**
     * Whether events are enabled
     *
     * @var bool
     */
    protected $eventsEnabled = false;

    /**
     * Instantiate a translator
     *
     * @param  array|Traversable                  $options
     * @return Translator
     * @throws Exception\InvalidArgumentException
     */
    public static function factory($options)
    {
        if ($options instanceof Traversable) {
            $options = ArrayUtils::iteratorToArray($options);
        } elseif (!is_array($options)) {
            throw new Exception\InvalidArgumentException(sprintf(
                '%s expects an array or Traversable object; received "%s"',
                __METHOD__,
                (is_object($options) ? get_class($options) : gettype($options))
            ));
        }

        $translator = new static();

        // locales
        if (isset($options['locale'])) {
            $locales = (array) $options['locale'];
            $translator->setLocale(array_shift($locales));
            if (count($locales) > 0) {
                $translator->setFallbackLocale(array_shift($locales));
            }
        }

        // file patterns
        if (isset($options['translation_file_patterns'])) {
            if (!is_array($options['translation_file_patterns'])) {
                throw new Exception\InvalidArgumentException(
                    '"translation_file_patterns" should be an array'
                );
            }

            $requiredKeys = array('type', 'base_dir', 'pattern');
            foreach ($options['translation_file_patterns'] as $pattern) {
                foreach ($requiredKeys as $key) {
                    if (!isset($pattern[$key])) {
                        throw new Exception\InvalidArgumentException(
                            "'{$key}' is missing for translation pattern options"
                        );
                    }
                }

                $translator->addTranslationFilePattern(
                    $pattern['type'],
                    $pattern['base_dir'],
                    $pattern['pattern'],
                    isset($pattern['text_domain']) ? $pattern['text_domain'] : 'default'
                );
            }
        }

        // files
        if (isset($options['translation_files'])) {
            if (!is_array($options['translation_files'])) {
                throw new Exception\InvalidArgumentException(
                    '"translation_files" should be an array'
                );
            }

            $requiredKeys = array('type', 'filename');
            foreach ($options['translation_files'] as $file) {
                foreach ($requiredKeys as $key) {
                    if (!isset($file[$key])) {
                        throw new Exception\InvalidArgumentException(
                            "'{$key}' is missing for translation file options"
                        );
                    }
                }

                $translator->addTranslationFile(
                    $file['type'],
                    $file['filename'],
                    isset($file['text_domain']) ? $file['text_domain'] : 'default',
                    isset($file['locale']) ? $file['locale'] : null
                );
            }
        }

        // remote
        if (isset($options['remote_translation'])) {
            if (!is_array($options['remote_translation'])) {
                throw new Exception\InvalidArgumentException(
                    '"remote_translation" should be an array'
                );
            }

            $requiredKeys = array('type');
            foreach ($options['remote_translation'] as $remote) {
                foreach ($requiredKeys as $key) {
                    if (!isset($remote[$key])) {
                        throw new Exception\InvalidArgumentException(
                            "'{$key}' is missing for remote translation options"
                        );
                    }
                }

                $translator->addRemoteTranslations(
                    $remote['type'],
                    isset($remote['text_domain']) ? $remote['text_domain'] : 'default'
                );
            }
        }

        // cache
        if (isset($options['cache'])) {
            if ($options['cache'] instanceof CacheStorage) {
                $translator->setCache($options['cache']);
            } else {
                $translator->setCache(Cache\StorageFactory::factory($options['cache']));
            }
        }

        // event manager enabled
        if (isset($options['event_manager_enabled']) && $options['event_manager_enabled']) {
            $translator->enableEventManager();
        }

        return $translator;
    }

    /**
     * Set the default locale.
     *
     * @param  string     $locale
     * @return Translator
     */
    public function setLocale($locale)
    {
        $this->locale = $locale;

        return $this;
    }

    /**
     * Get the default locale.
     *
     * @return string
     * @throws Exception\ExtensionNotLoadedException if ext/intl is not present and no locale set
     */
    public function getLocale()
    {
        if ($this->locale === null) {
            if (!extension_loaded('intl')) {
                throw new Exception\ExtensionNotLoadedException(sprintf(
                    '%s component requires the intl PHP extension',
                    __NAMESPACE__
                ));
            }
            $this->locale = Locale::getDefault();
        }

        return $this->locale;
    }

    /**
     * Set the fallback locale.
     *
     * @param  string     $locale
     * @return Translator
     */
    public function setFallbackLocale($locale)
    {
        $this->fallbackLocale = $locale;

        return $this;
    }

    /**
     * Get the fallback locale.
     *
     * @return string
     */
    public function getFallbackLocale()
    {
        return $this->fallbackLocale;
    }

    /**
     * Sets a cache
     *
     * @param  CacheStorage $cache
     * @return Translator
     */
    public function setCache(CacheStorage $cache = null)
    {
        $this->cache = $cache;

        return $this;
    }

    /**
     * Returns the set cache
     *
     * @return CacheStorage The set cache
     */
    public function getCache()
    {
        return $this->cache;
    }

    /**
     * Set the plugin manager for translation loaders
     *
     * @param  LoaderPluginManager $pluginManager
     * @return Translator
     */
    public function setPluginManager(LoaderPluginManager $pluginManager)
    {
        $this->pluginManager = $pluginManager;

        return $this;
    }

    /**
     * Retrieve the plugin manager for translation loaders.
     *
     * Lazy loads an instance if none currently set.
     *
     * @return LoaderPluginManager
     */
    public function getPluginManager()
    {
        if (!$this->pluginManager instanceof LoaderPluginManager) {
            $this->setPluginManager(new LoaderPluginManager());
        }

        return $this->pluginManager;
    }

    /**
     * Translate a message.
     *
     * @param  string $message
     * @param  string $textDomain
     * @param  string $locale
     * @return string
     */
    public function translate($message, $textDomain = 'default', $locale = null)
    {
        $locale      = ($locale ?: $this->getLocale());
        $translation = $this->getTranslatedMessage($message, $locale, $textDomain);

        if ($translation !== null && $translation !== '') {
            return $translation;
        }

        if (null !== ($fallbackLocale = $this->getFallbackLocale())
            && $locale !== $fallbackLocale
        ) {
            return $this->translate($message, $textDomain, $fallbackLocale);
        }

        return $message;
    }

    /**
     * Translate a plural message.
     *
     * @param  string                         $singular
     * @param  string                         $plural
     * @param  int                            $number
     * @param  string                         $textDomain
     * @param  string|null                    $locale
     * @return string
     * @throws Exception\OutOfBoundsException
     */
    public function translatePlural(
        $singular,
        $plural,
        $number,
        $textDomain = 'default',
        $locale = null
    ) {
        $locale      = $locale ?: $this->getLocale();
        $translation = $this->getTranslatedMessage($singular, $locale, $textDomain);

        if ($translation === null || $translation === '') {
            if (null !== ($fallbackLocale = $this->getFallbackLocale())
                && $locale !== $fallbackLocale
            ) {
                return $this->translatePlural(
                    $singular,
                    $plural,
                    $number,
                    $textDomain,
                    $fallbackLocale
                );
            }

            return ($number == 1 ? $singular : $plural);
        }

        $index = $this->messages[$textDomain][$locale]
                      ->getPluralRule()
                      ->evaluate($number);

        if (!isset($translation[$index])) {
            throw new Exception\OutOfBoundsException(sprintf(
                'Provided index %d does not exist in plural array', $index
            ));
        }

        return $translation[$index];
    }

    /**
     * Get a translated message.
     *
     * @triggers getTranslatedMessage.missing-translation
     * @param    string $message
     * @param    string $locale
     * @param    string $textDomain
     * @return   string|null
     */
    protected function getTranslatedMessage(
        $message,
        $locale,
        $textDomain = 'default'
    ) {
        if ($message === '') {
            return '';
        }

        if (!isset($this->messages[$textDomain][$locale])) {
            $this->loadMessages($textDomain, $locale);
        }

        if (isset($this->messages[$textDomain][$locale][$message])) {
            return $this->messages[$textDomain][$locale][$message];
        }

        if ($this->isEventManagerEnabled()) {
            $results = $this->getEventManager()->trigger(
                self::EVENT_MISSING_TRANSLATION,
                $this,
                array(
                    'message'     => $message,
                    'locale'      => $locale,
                    'text_domain' => $textDomain,
                ),
                function ($r) {
                    return is_string($r);
                }
            );
            $last = $results->last();
            if (is_string($last)) {
                return $last;
            }
        }

        return null;
    }

    /**
     * Add a translation file.
     *
     * @param  string     $type
     * @param  string     $filename
     * @param  string     $textDomain
     * @param  string     $locale
     * @return Translator
     */
    public function addTranslationFile(
        $type,
        $filename,
        $textDomain = 'default',
        $locale = null
    ) {
        $locale = $locale ?: '*';

        if (!isset($this->files[$textDomain])) {
            $this->files[$textDomain] = array();
        }

        $this->files[$textDomain][$locale][] = array(
            'type' => $type,
            'filename' => $filename,
        );

        return $this;
    }

    /**
     * Add multiple translations with a file pattern.
     *
     * @param  string     $type
     * @param  string     $baseDir
     * @param  string     $pattern
     * @param  string     $textDomain
     * @return Translator
     */
    public function addTranslationFilePattern(
        $type,
        $baseDir,
        $pattern,
        $textDomain = 'default'
    ) {
        if (!isset($this->patterns[$textDomain])) {
            $this->patterns[$textDomain] = array();
        }

        $this->patterns[$textDomain][] = array(
            'type'    => $type,
            'baseDir' => rtrim($baseDir, '/'),
            'pattern' => $pattern,
        );

        return $this;
    }

    /**
     * Add remote translations.
     *
     * @param  string     $type
     * @param  string     $textDomain
     * @return Translator
     */
    public function addRemoteTranslations($type, $textDomain = 'default')
    {
        if (!isset($this->remote[$textDomain])) {
            $this->remote[$textDomain] = array();
        }

        $this->remote[$textDomain][] = $type;

        return $this;
    }

    /**
     * Load messages for a given language and domain.
     *
     * @triggers loadMessages.no-messages-loaded
     * @param    string $textDomain
     * @param    string $locale
     * @throws   Exception\RuntimeException
     * @return   void
     */
    protected function loadMessages($textDomain, $locale)
    {
        if (!isset($this->messages[$textDomain])) {
            $this->messages[$textDomain] = array();
        }

        if (null !== ($cache = $this->getCache())) {
            $cacheId = 'Zend_I18n_Translator_Messages_' . md5($textDomain . $locale);

            if (null !== ($result = $cache->getItem($cacheId))) {
                $this->messages[$textDomain][$locale] = $result;

                return;
            }
        }

        $messagesLoaded  = false;
        $messagesLoaded |= $this->loadMessagesFromRemote($textDomain, $locale);
        $messagesLoaded |= $this->loadMessagesFromPatterns($textDomain, $locale);
        $messagesLoaded |= $this->loadMessagesFromFiles($textDomain, $locale);

        if (!$messagesLoaded) {
            $discoveredTextDomain = null;
            if ($this->isEventManagerEnabled()) {
                $results = $this->getEventManager()->trigger(
                    self::EVENT_NO_MESSAGES_LOADED,
                    $this,
                    array(
                        'locale'      => $locale,
                        'text_domain' => $textDomain,
                    ),
                    function ($r) {
                        return ($r instanceof TextDomain);
                    }
                );
                $last = $results->last();
                if ($last instanceof TextDomain) {
                    $discoveredTextDomain = $last;
                }
            }

            $this->messages[$textDomain][$locale] = $discoveredTextDomain;
            $messagesLoaded = true;
        }

        if ($messagesLoaded && $cache !== null) {
            $cache->setItem($cacheId, $this->messages[$textDomain][$locale]);
        }
    }

    /**
     * Load messages from remote sources.
     *
     * @param  string $textDomain
     * @param  string $locale
     * @return bool
     * @throws Exception\RuntimeException When specified loader is not a remote loader
     */
    protected function loadMessagesFromRemote($textDomain, $locale)
    {
        $messagesLoaded = false;

        if (isset($this->remote[$textDomain])) {
            foreach ($this->remote[$textDomain] as $loaderType) {
                $loader = $this->getPluginManager()->get($loaderType);

                if (!$loader instanceof RemoteLoaderInterface) {
                    throw new Exception\RuntimeException('Specified loader is not a remote loader');
                }

                if (isset($this->messages[$textDomain][$locale])) {
                    $this->messages[$textDomain][$locale]->merge($loader->load($locale, $textDomain));
                } else {
                    $this->messages[$textDomain][$locale] = $loader->load($locale, $textDomain);
                }

                $messagesLoaded = true;
            }
        }

        return $messagesLoaded;
    }

    /**
     * Load messages from patterns.
     *
     * @param  string $textDomain
     * @param  string $locale
     * @return bool
     * @throws Exception\RuntimeException When specified loader is not a file loader
     */
    protected function loadMessagesFromPatterns($textDomain, $locale)
    {
        $messagesLoaded = false;

        if (isset($this->patterns[$textDomain])) {
            foreach ($this->patterns[$textDomain] as $pattern) {
                $filename = $pattern['baseDir'] . '/' . sprintf($pattern['pattern'], $locale);

                if (is_file($filename)) {
                    $loader = $this->getPluginManager()->get($pattern['type']);

                    if (!$loader instanceof FileLoaderInterface) {
                        throw new Exception\RuntimeException('Specified loader is not a file loader');
                    }

                    if (isset($this->messages[$textDomain][$locale])) {
                        $this->messages[$textDomain][$locale]->merge($loader->load($locale, $filename));
                    } else {
                        $this->messages[$textDomain][$locale] = $loader->load($locale, $filename);
                    }

                    $messagesLoaded = true;
                }
            }
        }

        return $messagesLoaded;
    }

    /**
     * Load messages from files.
     *
     * @param  string $textDomain
     * @param  string $locale
     * @return bool
     * @throws Exception\RuntimeException When specified loader is not a file loader
     */
    protected function loadMessagesFromFiles($textDomain, $locale)
    {
        $messagesLoaded = false;

        foreach (array($locale, '*') as $currentLocale) {
            if (!isset($this->files[$textDomain][$currentLocale])) {
                continue;
            }

            foreach ($this->files[$textDomain][$currentLocale] as $file) {
                $loader = $this->getPluginManager()->get($file['type']);

                if (!$loader instanceof FileLoaderInterface) {
                    throw new Exception\RuntimeException('Specified loader is not a file loader');
                }

                if (isset($this->messages[$textDomain][$locale])) {
                    $this->messages[$textDomain][$locale]->merge($loader->load($locale, $file['filename']));
                } else {
                    $this->messages[$textDomain][$locale] = $loader->load($locale, $file['filename']);
                }

                $messagesLoaded = true;
            }

            unset($this->files[$textDomain][$currentLocale]);
        }

        return $messagesLoaded;
    }

    /**
     * Get the event manager.
     *
     * @return EventManagerInterface|null
     */
    public function getEventManager()
    {
        if (!$this->events instanceof EventManagerInterface) {
            $this->setEventManager(new EventManager());
        }

        return $this->events;
    }

    /**
     * Set the event manager instance used by this translator.
     *
     * @param  EventManagerInterface $events
     * @return Translator
     */
    public function setEventManager(EventManagerInterface $events)
    {
        $events->setIdentifiers(array(
            __CLASS__,
            get_class($this),
            'translator',
        ));
        $this->events = $events;
        return $this;
    }

    /**
     * Check whether the event manager is enabled.
     *
     * @return boolean
     */
    public function isEventManagerEnabled()
    {
        return $this->eventsEnabled;
    }

    /**
     * Enable the event manager.
     *
     * @return Translator
     */
    public function enableEventManager()
    {
        $this->eventsEnabled = true;
        return $this;
    }

    /**
     * Disable the event manager.
     *
     * @return Translator
     */
    public function disableEventManager()
    {
        $this->eventsEnabled = false;
        return $this;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Translator\Loader;

/**
 * Remote loader interface.
 */
interface RemoteLoaderInterface
{
    /**
     * Load translations from a remote source.
     *
     * @param  string $locale
     * @param  string $textDomain
     * @return \Zend\I18n\Translator\TextDomain|null
     */
    public function load($locale, $textDomain);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Translator\Loader;

use Zend\I18n\Exception;
use Zend\I18n\Translator\Plural\Rule as PluralRule;
use Zend\I18n\Translator\TextDomain;
use Zend\Stdlib\ErrorHandler;

/**
 * Gettext loader.
 */
class Gettext implements FileLoaderInterface
{
    /**
     * Current file pointer.
     *
     * @var resource
     */
    protected $file;

    /**
     * Whether the current file is little endian.
     *
     * @var bool
     */
    protected $littleEndian;

    /**
     * load(): defined by FileLoaderInterface.
     *
     * @see    FileLoaderInterface::load()
     * @param  string $locale
     * @param  string $filename
     * @return TextDomain
     * @throws Exception\InvalidArgumentException
     */
    public function load($locale, $filename)
    {
        if (!is_file($filename) || !is_readable($filename)) {
            throw new Exception\InvalidArgumentException(sprintf(
                'Could not open file %s for reading',
                $filename
            ));
        }

        $textDomain = new TextDomain();

        ErrorHandler::start();
        $this->file = fopen($filename, 'rb');
        $error = ErrorHandler::stop();
        if (false === $this->file) {
            throw new Exception\InvalidArgumentException(sprintf(
                'Could not open file %s for reading',
                $filename
            ), 0, $error);
        }

        // Verify magic number
        $magic = fread($this->file, 4);

        if ($magic == "\x95\x04\x12\xde") {
            $this->littleEndian = false;
        } elseif ($magic == "\xde\x12\x04\x95") {
            $this->littleEndian = true;
        } else {
            fclose($this->file);
            throw new Exception\InvalidArgumentException(sprintf(
                '%s is not a valid gettext file',
                $filename
            ));
        }

        // Verify major revision (only 0 and 1 supported)
        $majorRevision = ($this->readInteger() >> 16);

        if ($majorRevision !== 0 && $majorRevision !== 1) {
            fclose($this->file);
            throw new Exception\InvalidArgumentException(sprintf(
                '%s has an unknown major revision',
                $filename
            ));
        }

        // Gather main information
        $numStrings                   = $this->readInteger();
        $originalStringTableOffset    = $this->readInteger();
        $translationStringTableOffset = $this->readInteger();

        // Usually there follow size and offset of the hash table, but we have
        // no need for it, so we skip them.
        fseek($this->file, $originalStringTableOffset);
        $originalStringTable = $this->readIntegerList(2 * $numStrings);

        fseek($this->file, $translationStringTableOffset);
        $translationStringTable = $this->readIntegerList(2 * $numStrings);

        // Read in all translations
        for ($current = 0; $current < $numStrings; $current++) {
            $sizeKey                 = $current * 2 + 1;
            $offsetKey               = $current * 2 + 2;
            $originalStringSize      = $originalStringTable[$sizeKey];
            $originalStringOffset    = $originalStringTable[$offsetKey];
            $translationStringSize   = $translationStringTable[$sizeKey];
            $translationStringOffset = $translationStringTable[$offsetKey];

            $originalString = array('');
            if ($originalStringSize > 0) {
                fseek($this->file, $originalStringOffset);
                $originalString = explode("\0", fread($this->file, $originalStringSize));
            }

            if ($translationStringSize > 0) {
                fseek($this->file, $translationStringOffset);
                $translationString = explode("\0", fread($this->file, $translationStringSize));

                if (count($originalString) > 1 && count($translationString) > 1) {
                    $textDomain[$originalString[0]] = $translationString;

                    array_shift($originalString);

                    foreach ($originalString as $string) {
                        $textDomain[$string] = '';
                    }
                } else {
                    $textDomain[$originalString[0]] = $translationString[0];
                }
            }
        }

        // Read header entries
        if (array_key_exists('', $textDomain)) {
            $rawHeaders = explode("\n", trim($textDomain['']));

            foreach ($rawHeaders as $rawHeader) {
                list($header, $content) = explode(':', $rawHeader, 2);

                if (trim(strtolower($header)) === 'plural-forms') {
                    $textDomain->setPluralRule(PluralRule::fromString($content));
                }
            }

            unset($textDomain['']);
        }

        fclose($this->file);

        return $textDomain;
    }

    /**
     * Read a single integer from the current file.
     *
     * @return int
     */
    protected function readInteger()
    {
        if ($this->littleEndian) {
            $result = unpack('Vint', fread($this->file, 4));
        } else {
            $result = unpack('Nint', fread($this->file, 4));
        }

        return $result['int'];
    }

    /**
     * Read an integer from the current file.
     *
     * @param  int $num
     * @return int
     */
    protected function readIntegerList($num)
    {
        if ($this->littleEndian) {
            return unpack('V' . $num, fread($this->file, 4 * $num));
        }

        return unpack('N' . $num, fread($this->file, 4 * $num));
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Translator\Loader;

use Zend\Config\Reader\Ini as IniReader;
use Zend\I18n\Exception;
use Zend\I18n\Translator\Plural\Rule as PluralRule;
use Zend\I18n\Translator\TextDomain;

/**
 * PHP INI format loader.
 */
class Ini implements FileLoaderInterface
{
    /**
     * load(): defined by FileLoaderInterface.
     *
     * @see    FileLoaderInterface::load()
     * @param  string $locale
     * @param  string $filename
     * @return TextDomain|null
     * @throws Exception\InvalidArgumentException
     */
    public function load($locale, $filename)
    {
        if (!is_file($filename) || !is_readable($filename)) {
            throw new Exception\InvalidArgumentException(sprintf(
                'Could not open file %s for reading',
                $filename
            ));
        }

        $messages           = array();
        $iniReader          = new IniReader();
        $messagesNamespaced = $iniReader->fromFile($filename);

        $list = $messagesNamespaced;
        if (isset($messagesNamespaced['translation'])) {
           $list = $messagesNamespaced['translation'];
        }

        foreach ($list as $message) {
            if (!is_array($message) || count($message) < 2) {
                throw new Exception\InvalidArgumentException(
                    'Each INI row must be an array with message and translation'
                );
            }
            if (isset($message['message']) && isset($message['translation'])) {
                $messages[$message['message']] = $message['translation'];
                continue;
            }
            $messages[array_shift($message)] = array_shift($message);
        }

        if (!is_array($messages)) {
            throw new Exception\InvalidArgumentException(sprintf(
                'Expected an array, but received %s',
                gettype($messages)
            ));
        }

        $textDomain = new TextDomain($messages);

        if (array_key_exists('plural', $messagesNamespaced)
            && isset($messagesNamespaced['plural']['plural_forms'])
        ) {
            $textDomain->setPluralRule(
                PluralRule::fromString($messagesNamespaced['plural']['plural_forms'])
            );
        }

        return $textDomain;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Translator\Loader;

use Zend\I18n\Exception;
use Zend\I18n\Translator\Plural\Rule as PluralRule;
use Zend\I18n\Translator\TextDomain;

/**
 * PHP array loader.
 */
class PhpArray implements FileLoaderInterface
{
    /**
     * load(): defined by FileLoaderInterface.
     *
     * @see    FileLoaderInterface::load()
     * @param  string $locale
     * @param  string $filename
     * @return TextDomain|null
     * @throws Exception\InvalidArgumentException
     */
    public function load($locale, $filename)
    {
        if (!is_file($filename) || !is_readable($filename)) {
            throw new Exception\InvalidArgumentException(sprintf(
                'Could not open file %s for reading',
                $filename
            ));
        }

        $messages = include $filename;

        if (!is_array($messages)) {
            throw new Exception\InvalidArgumentException(sprintf(
                'Expected an array, but received %s',
                gettype($messages)
            ));
        }

        $textDomain = new TextDomain($messages);

        if (array_key_exists('', $textDomain)) {
            if (isset($textDomain['']['plural_forms'])) {
                $textDomain->setPluralRule(
                    PluralRule::fromString($textDomain['']['plural_forms'])
                );
            }

            unset($textDomain['']);
        }

        return $textDomain;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Translator\Loader;

/**
 * File loader interface.
 */
interface FileLoaderInterface
{
    /**
     * Load translations from a file.
     *
     * @param  string $locale
     * @param  string $filename
     * @return \Zend\I18n\Translator\TextDomain|null
     */
    public function load($locale, $filename);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Translator;

use Zend\I18n\Exception;
use Zend\ServiceManager\AbstractPluginManager;

/**
 * Plugin manager implementation for translation loaders.
 *
 * Enforces that loaders retrieved are either instances of
 * Loader\FileLoaderInterface or Loader\RemoteLoaderInterface. Additionally,
 * it registers a number of default loaders.
 */
class LoaderPluginManager extends AbstractPluginManager
{
    /**
     * Default set of loaders.
     *
     * @var array
     */
    protected $invokableClasses = array(
        'gettext'  => 'Zend\I18n\Translator\Loader\Gettext',
        'ini'      => 'Zend\I18n\Translator\Loader\Ini',
        'phparray' => 'Zend\I18n\Translator\Loader\PhpArray',
    );

    /**
     * Validate the plugin.
     *
     * Checks that the filter loaded is an instance of
     * Loader\FileLoaderInterface or Loader\RemoteLoaderInterface.
     *
     * @param  mixed $plugin
     * @return void
     * @throws Exception\RuntimeException if invalid
     */
    public function validatePlugin($plugin)
    {
        if ($plugin instanceof Loader\FileLoaderInterface || $plugin instanceof Loader\RemoteLoaderInterface) {
            // we're okay
            return;
        }

        throw new Exception\RuntimeException(sprintf(
            'Plugin of type %s is invalid; must implement %s\Loader\FileLoaderInterface or %s\Loader\RemoteLoaderInterface',
            (is_object($plugin) ? get_class($plugin) : gettype($plugin)),
            __NAMESPACE__
        ));
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Translator;

use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

/**
 * Translator.
 */
class TranslatorServiceFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        // Configure the translator
        $config = $serviceLocator->get('Config');
        $trConfig = isset($config['translator']) ? $config['translator'] : array();
        $translator = Translator::factory($trConfig);
        return $translator;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Translator;

use ArrayObject;
use Zend\I18n\Exception;
use Zend\I18n\Translator\Plural\Rule as PluralRule;

/**
 * Text domain.
 */
class TextDomain extends ArrayObject
{
    /**
     * Plural rule.
     *
     * @var PluralRule
     */
    protected $pluralRule;

    /**
     * Set the plural rule
     *
     * @param  PluralRule $rule
     * @return TextDomain
     */
    public function setPluralRule(PluralRule $rule)
    {
        $this->pluralRule = $rule;
        return $this;
    }

    /**
     * Get the plural rule.
     *
     * Lazy loads a default rule if none already registered
     *
     * @return PluralRule
     */
    public function getPluralRule()
    {
        if ($this->pluralRule === null) {
            $this->setPluralRule(PluralRule::fromString('nplurals=2; plural=n != 1;'));
        }

        return $this->pluralRule;
    }

    /**
     * Merge another text domain with the current one.
     *
     * The plural rule of both text domains must be compatible for a successful
     * merge. We are only validating the number of plural forms though, as the
     * same rule could be made up with different expression.
     *
     * @param  TextDomain $textDomain
     * @return TextDomain
     * @throws Exception\RuntimeException
     */
    public function merge(TextDomain $textDomain)
    {
        if ($this->getPluralRule()->getNumPlurals() !== $textDomain->getPluralRule()->getNumPlurals()) {
            throw new Exception\RuntimeException('Plural rule of merging text domain is not compatible with the current one');
        }

        $this->exchangeArray(
            array_replace(
                $this->getArrayCopy(),
                $textDomain->getArrayCopy()
            )
        );

        return $this;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Validator;

use Locale;
use NumberFormatter;
use Traversable;
use Zend\I18n\Exception as I18nException;
use Zend\Stdlib\ArrayUtils;
use Zend\Validator\AbstractValidator;
use Zend\Validator\Exception;

class Int extends AbstractValidator
{
    const INVALID = 'intInvalid';
    const NOT_INT = 'notInt';

    /**
     * @var array
     */
    protected $messageTemplates = array(
        self::INVALID => "Invalid type given. String or integer expected",
        self::NOT_INT => "The input does not appear to be an integer",
    );

    /**
     * Optional locale
     *
     * @var string|null
     */
    protected $locale;

    /**
     * Constructor for the integer validator
     *
     * @param  array|Traversable $options
     * @throws Exception\ExtensionNotLoadedException if ext/intl is not present
     */
    public function __construct($options = array())
    {
        if (!extension_loaded('intl')) {
            throw new I18nException\ExtensionNotLoadedException(sprintf(
                '%s component requires the intl PHP extension',
                __NAMESPACE__
            ));
        }

        if ($options instanceof Traversable) {
            $options = ArrayUtils::iteratorToArray($options);
        }

        if (array_key_exists('locale', $options)) {
            $this->setLocale($options['locale']);
        }

        parent::__construct($options);
    }

    /**
     * Returns the set locale
     */
    public function getLocale()
    {
        if (null === $this->locale) {
            $this->locale = Locale::getDefault();
        }
        return $this->locale;
    }

    /**
     * Sets the locale to use
     *
     * @param  string $locale
     * @return Int
     */
    public function setLocale($locale)
    {
        $this->locale = $locale;
        return $this;
    }

    /**
     * Returns true if and only if $value is a valid integer
     *
     * @param  string|int $value
     * @return bool
     * @throws Exception\InvalidArgumentException
     */
    public function isValid($value)
    {
        if (!is_string($value) && !is_int($value) && !is_float($value)) {
            $this->error(self::INVALID);
            return false;
        }

        if (is_int($value)) {
            return true;
        }

        $this->setValue($value);

        $locale = $this->getLocale();
        $format = new NumberFormatter($locale, NumberFormatter::DECIMAL);
        if (intl_is_failure($format->getErrorCode())) {
            throw new Exception\InvalidArgumentException("Invalid locale string given");
        }

        $parsedInt = $format->parse($value, NumberFormatter::TYPE_INT64);
        if (intl_is_failure($format->getErrorCode())) {
            $this->error(self::NOT_INT);
            return false;
        }

        $decimalSep  = $format->getSymbol(NumberFormatter::DECIMAL_SEPARATOR_SYMBOL);
        $groupingSep = $format->getSymbol(NumberFormatter::GROUPING_SEPARATOR_SYMBOL);

        $valueFiltered = str_replace($groupingSep, '', $value);
        $valueFiltered = str_replace($decimalSep, '.', $valueFiltered);

        if (strval($parsedInt) !== $valueFiltered) {
            $this->error(self::NOT_INT);
            return false;
        }

        return true;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Validator;

use Locale;
use NumberFormatter;
use Traversable;
use Zend\I18n\Exception as I18nException;
use Zend\Stdlib\ArrayUtils;
use Zend\Validator\AbstractValidator;
use Zend\Validator\Exception;

class Float extends AbstractValidator
{
    const INVALID   = 'floatInvalid';
    const NOT_FLOAT = 'notFloat';

    /**
     * @var array
     */
    protected $messageTemplates = array(
        self::INVALID   => "Invalid type given. String, integer or float expected",
        self::NOT_FLOAT => "The input does not appear to be a float",
    );

    /**
     * Optional locale
     *
     * @var string|null
     */
    protected $locale;

    /**
     * Constructor for the integer validator
     *
     * @param array|Traversable $options
     * @throws Exception\ExtensionNotLoadedException if ext/intl is not present
     */
    public function __construct($options = array())
    {
        if (!extension_loaded('intl')) {
            throw new I18nException\ExtensionNotLoadedException(sprintf(
                '%s component requires the intl PHP extension',
                __NAMESPACE__
            ));
        }

        if ($options instanceof Traversable) {
            $options = ArrayUtils::iteratorToArray($options);
        }

        if (array_key_exists('locale', $options)) {
            $this->setLocale($options['locale']);
        }

        parent::__construct($options);
    }

    /**
     * Returns the set locale
     *
     * @return string
     */
    public function getLocale()
    {
        if (null === $this->locale) {
            $this->locale = Locale::getDefault();
        }
        return $this->locale;
    }

    /**
     * Sets the locale to use
     *
     * @param string|null $locale
     * @return Float
     */
    public function setLocale($locale)
    {
        $this->locale = $locale;
        return $this;
    }


    /**
     * Returns true if and only if $value is a floating-point value
     *
     * @param  string $value
     * @return bool
     * @throws Exception\InvalidArgumentException
     */
    public function isValid($value)
    {
        if (!is_string($value) && !is_int($value) && !is_float($value)) {
            $this->error(self::INVALID);
            return false;
        }

        $this->setValue($value);

        if (is_float($value)) {
            return true;
        }

        $locale = $this->getLocale();
        $format = new NumberFormatter($locale, NumberFormatter::DECIMAL);
        if (intl_is_failure($format->getErrorCode())) {
            throw new Exception\InvalidArgumentException("Invalid locale string given");
        }

        $parsedFloat = $format->parse($value, NumberFormatter::TYPE_DOUBLE);
        if (intl_is_failure($format->getErrorCode())) {
            $this->error(self::NOT_FLOAT);
            return false;
        }

        $decimalSep  = $format->getSymbol(NumberFormatter::DECIMAL_SEPARATOR_SYMBOL);
        $groupingSep = $format->getSymbol(NumberFormatter::GROUPING_SEPARATOR_SYMBOL);

        $valueFiltered = str_replace($groupingSep, '', $value);
        $valueFiltered = str_replace($decimalSep, '.', $valueFiltered);

        while (strpos($valueFiltered, '.') !== false
               && (substr($valueFiltered, -1) == '0' || substr($valueFiltered, -1) == '.')
        ) {
            $valueFiltered = substr($valueFiltered, 0, strlen($valueFiltered) - 1);
        }

        if (strval($parsedFloat) !== $valueFiltered) {
            $this->error(self::NOT_FLOAT);
            return false;
        }

        return true;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Validator;

use Zend\I18n\Filter\Alnum as AlnumFilter;
use Zend\Validator\AbstractValidator;

class Alnum extends AbstractValidator
{
    const INVALID      = 'alnumInvalid';
    const NOT_ALNUM    = 'notAlnum';
    const STRING_EMPTY = 'alnumStringEmpty';

    /**
     * Alphanumeric filter used for validation
     *
     * @var AlnumFilter
     */
    protected static $filter = null;

    /**
     * Validation failure message template definitions
     *
     * @var array
     */
    protected $messageTemplates = array(
        self::INVALID      => "Invalid type given. String, integer or float expected",
        self::NOT_ALNUM    => "The input contains characters which are non alphabetic and no digits",
        self::STRING_EMPTY => "The input is an empty string",
    );

    /**
     * Options for this validator
     *
     * @var array
     */
    protected $options = array(
        'allowWhiteSpace' => false,  // Whether to allow white space characters; off by default
    );

    /**
     * Sets default option values for this instance
     *
     * @param bool $allowWhiteSpace
     */
    public function __construct($allowWhiteSpace = false)
    {
        $options = is_array($allowWhiteSpace) ? $allowWhiteSpace : null;
        parent::__construct($options);

        if (is_scalar($allowWhiteSpace)) {
            $this->options['allowWhiteSpace'] = (bool) $allowWhiteSpace;
        }
    }

    /**
     * Returns the allowWhiteSpace option
     *
     * @return bool
     */
    public function getAllowWhiteSpace()
    {
        return $this->options['allowWhiteSpace'];
    }

    /**
     * Sets the allowWhiteSpace option
     *
     * @param  bool $allowWhiteSpace
     * @return AlnumFilter Provides a fluent interface
     */
    public function setAllowWhiteSpace($allowWhiteSpace)
    {
        $this->options['allowWhiteSpace'] = (bool) $allowWhiteSpace;
        return $this;
    }

    /**
     * Returns true if and only if $value contains only alphabetic and digit characters
     *
     * @param  string $value
     * @return bool
     */
    public function isValid($value)
    {
        if (!is_string($value) && !is_int($value) && !is_float($value)) {
            $this->error(self::INVALID);
            return false;
        }

        $this->setValue($value);
        if ('' === $value) {
            $this->error(self::STRING_EMPTY);
            return false;
        }

        if (null === static::$filter) {
            static::$filter = new AlnumFilter();
        }

        static::$filter->setAllowWhiteSpace($this->options['allowWhiteSpace']);

        if ($value != static::$filter->filter($value)) {
            $this->error(self::NOT_ALNUM);
            return false;
        }

        return true;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Validator;

use Locale;
use Traversable;
use Zend\I18n\Exception as I18nException;
use Zend\Stdlib\ArrayUtils;
use Zend\Validator\AbstractValidator;
use Zend\Validator\Callback;
use Zend\Validator\Exception;

class PostCode extends AbstractValidator
{
    const INVALID        = 'postcodeInvalid';
    const NO_MATCH       = 'postcodeNoMatch';
    const SERVICE        = 'postcodeService';
    const SERVICEFAILURE = 'postcodeServiceFailure';

    /**
     * @var array
     */
    protected $messageTemplates = array(
        self::INVALID        => "Invalid type given. String or integer expected",
        self::NO_MATCH       => "The input does not appear to be a postal code",
        self::SERVICE        => "The input does not appear to be a postal code",
        self::SERVICEFAILURE => "An exception has been raised while validating the input",
    );

    /**
     * Optional Locale to use
     *
     * @var string|null
     */
    protected $locale;

    /**
     * Optional Manual postal code format
     *
     * @var string|null
     */
    protected $format;

    /**
     * Optional Service callback for additional validation
     *
     * @var mixed|null
     */
    protected $service;

    /**
     * Postal Code regexes by territory
     *
     * @var array
     */
    protected static $postCodeRegex = array(
        'GB' => 'GIR[ ]?0AA|((AB|AL|B|BA|BB|BD|BH|BL|BN|BR|BS|BT|CA|CB|CF|CH|CM|CO|CR|CT|CV|CW|DA|DD|DE|DG|DH|DL|DN|DT|DY|E|EC|EH|EN|EX|FK|FY|G|GL|GY|GU|HA|HD|HG|HP|HR|HS|HU|HX|IG|IM|IP|IV|JE|KA|KT|KW|KY|L|LA|LD|LE|LL|LN|LS|LU|M|ME|MK|ML|N|NE|NG|NN|NP|NR|NW|OL|OX|PA|PE|PH|PL|PO|PR|RG|RH|RM|S|SA|SE|SG|SK|SL|SM|SN|SO|SP|SR|SS|ST|SW|SY|TA|TD|TF|TN|TQ|TR|TS|TW|UB|W|WA|WC|WD|WF|WN|WR|WS|WV|YO|ZE)(\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}))|BFPO[ ]?\d{1,4}',
        'JE' => 'JE\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}',
        'GG' => 'GY\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}',
        'IM' => 'IM\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}',
        'US' => '\d{5}([ \-]\d{4})?',
        'CA' => '[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJ-NPRSTV-Z][ ]?\d[ABCEGHJ-NPRSTV-Z]\d',
        'DE' => '\d{5}',
        'JP' => '\d{3}-\d{4}',
        'FR' => '\d{2}[ ]?\d{3}',
        'AU' => '\d{4}',
        'IT' => '\d{5}',
        'CH' => '\d{4}',
        'AT' => '\d{4}',
        'ES' => '\d{5}',
        'NL' => '\d{4}[ ]?[A-Z]{2}',
        'BE' => '\d{4}',
        'DK' => '\d{4}',
        'SE' => '\d{3}[ ]?\d{2}',
        'NO' => '\d{4}',
        'BR' => '\d{5}[\-]?\d{3}',
        'PT' => '\d{4}([\-]\d{3})?',
        'FI' => '\d{5}',
        'AX' => '22\d{3}',
        'KR' => '\d{3}[\-]\d{3}',
        'CN' => '\d{6}',
        'TW' => '\d{3}(\d{2})?',
        'SG' => '\d{6}',
        'DZ' => '\d{5}',
        'AD' => 'AD\d{3}',
        'AR' => '([A-HJ-NP-Z])?\d{4}([A-Z]{3})?',
        'AM' => '(37)?\d{4}',
        'AZ' => '\d{4}',
        'BH' => '((1[0-2]|[2-9])\d{2})?',
        'BD' => '\d{4}',
        'BB' => '(BB\d{5})?',
        'BY' => '\d{6}',
        'BM' => '[A-Z]{2}[ ]?[A-Z0-9]{2}',
        'BA' => '\d{5}',
        'IO' => 'BBND 1ZZ',
        'BN' => '[A-Z]{2}[ ]?\d{4}',
        'BG' => '\d{4}',
        'KH' => '\d{5}',
        'CV' => '\d{4}',
        'CL' => '\d{7}',
        'CR' => '\d{4,5}|\d{3}-\d{4}',
        'HR' => '\d{5}',
        'CY' => '\d{4}',
        'CZ' => '\d{3}[ ]?\d{2}',
        'DO' => '\d{5}',
        'EC' => '([A-Z]\d{4}[A-Z]|(?:[A-Z]{2})?\d{6})?',
        'EG' => '\d{5}',
        'EE' => '\d{5}',
        'FO' => '\d{3}',
        'GE' => '\d{4}',
        'GR' => '\d{3}[ ]?\d{2}',
        'GL' => '39\d{2}',
        'GT' => '\d{5}',
        'HT' => '\d{4}',
        'HN' => '(?:\d{5})?',
        'HU' => '\d{4}',
        'IS' => '\d{3}',
        'IN' => '\d{6}',
        'ID' => '\d{5}',
        'IE' => '((D|DUBLIN)?([1-9]|6[wW]|1[0-8]|2[024]))?',
        'IL' => '\d{5}',
        'JO' => '\d{5}',
        'KZ' => '\d{6}',
        'KE' => '\d{5}',
        'KW' => '\d{5}',
        'LA' => '\d{5}',
        'LV' => '\d{4}',
        'LB' => '(\d{4}([ ]?\d{4})?)?',
        'LI' => '(948[5-9])|(949[0-7])',
        'LT' => '\d{5}',
        'LU' => '\d{4}',
        'MK' => '\d{4}',
        'MY' => '\d{5}',
        'MV' => '\d{5}',
        'MT' => '[A-Z]{3}[ ]?\d{2,4}',
        'MU' => '(\d{3}[A-Z]{2}\d{3})?',
        'MX' => '\d{5}',
        'MD' => '\d{4}',
        'MC' => '980\d{2}',
        'MA' => '\d{5}',
        'NP' => '\d{5}',
        'NZ' => '\d{4}',
        'NI' => '((\d{4}-)?\d{3}-\d{3}(-\d{1})?)?',
        'NG' => '(\d{6})?',
        'OM' => '(PC )?\d{3}',
        'PK' => '\d{5}',
        'PY' => '\d{4}',
        'PH' => '\d{4}',
        'PL' => '\d{2}-\d{3}',
        'PR' => '00[679]\d{2}([ \-]\d{4})?',
        'RO' => '\d{6}',
        'RU' => '\d{6}',
        'SM' => '4789\d',
        'SA' => '\d{5}',
        'SN' => '\d{5}',
        'SK' => '\d{3}[ ]?\d{2}',
        'SI' => '\d{4}',
        'ZA' => '\d{4}',
        'LK' => '\d{5}',
        'TJ' => '\d{6}',
        'TH' => '\d{5}',
        'TN' => '\d{4}',
        'TR' => '\d{5}',
        'TM' => '\d{6}',
        'UA' => '\d{5}',
        'UY' => '\d{5}',
        'UZ' => '\d{6}',
        'VA' => '00120',
        'VE' => '\d{4}',
        'ZM' => '\d{5}',
        'AS' => '96799',
        'CC' => '6799',
        'CK' => '\d{4}',
        'RS' => '\d{6}',
        'ME' => '8\d{4}',
        'CS' => '\d{5}',
        'YU' => '\d{5}',
        'CX' => '6798',
        'ET' => '\d{4}',
        'FK' => 'FIQQ 1ZZ',
        'NF' => '2899',
        'FM' => '(9694[1-4])([ \-]\d{4})?',
        'GF' => '9[78]3\d{2}',
        'GN' => '\d{3}',
        'GP' => '9[78][01]\d{2}',
        'GS' => 'SIQQ 1ZZ',
        'GU' => '969[123]\d([ \-]\d{4})?',
        'GW' => '\d{4}',
        'HM' => '\d{4}',
        'IQ' => '\d{5}',
        'KG' => '\d{6}',
        'LR' => '\d{4}',
        'LS' => '\d{3}',
        'MG' => '\d{3}',
        'MH' => '969[67]\d([ \-]\d{4})?',
        'MN' => '\d{6}',
        'MP' => '9695[012]([ \-]\d{4})?',
        'MQ' => '9[78]2\d{2}',
        'NC' => '988\d{2}',
        'NE' => '\d{4}',
        'VI' => '008(([0-4]\d)|(5[01]))([ \-]\d{4})?',
        'PF' => '987\d{2}',
        'PG' => '\d{3}',
        'PM' => '9[78]5\d{2}',
        'PN' => 'PCRN 1ZZ',
        'PW' => '96940',
        'RE' => '9[78]4\d{2}',
        'SH' => '(ASCN|STHL) 1ZZ',
        'SJ' => '\d{4}',
        'SO' => '\d{5}',
        'SZ' => '[HLMS]\d{3}',
        'TC' => 'TKCA 1ZZ',
        'WF' => '986\d{2}',
        'YT' => '976\d{2}',
    );

    /**
     * Constructor for the PostCode validator
     *
     * Accepts a string locale and/or "format".
     *
     * @param  array|Traversable $options
     * @throws Exception\ExtensionNotLoadedException if ext/intl is not present
     */
    public function __construct($options = array())
    {
        if (!extension_loaded('intl')) {
            throw new I18nException\ExtensionNotLoadedException(sprintf(
                '%s component requires the intl PHP extension',
                __NAMESPACE__
            ));
        }

        if ($options instanceof Traversable) {
            $options = ArrayUtils::iteratorToArray($options);
        }

        if (array_key_exists('locale', $options)) {
            $this->setLocale($options['locale']);
        } else {
            $this->setLocale(Locale::getDefault());
        }
        if (array_key_exists('format', $options)) {
            $this->setFormat($options['format']);
        }
        if (array_key_exists('service', $options)) {
            $this->setService($options['service']);
        }

        parent::__construct($options);
    }

    /**
     * Returns the set locale
     *
     * @return string|null The set locale
     */
    public function getLocale()
    {
        return $this->locale;
    }

    /**
     * Sets the locale to use
     *
     * @param  string|null $locale
     * @return PostCode  Provides fluid interface
     */
    public function setLocale($locale)
    {
        $this->locale = $locale;
        return $this;
    }

    /**
     * Returns the set postal code format
     *
     * @return string|null
     */
    public function getFormat()
    {
        return $this->format;
    }

    /**
     * Sets a self defined postal format as regex
     *
     * @param  string $format
     * @return PostCode  Provides fluid interface
     */
    public function setFormat($format)
    {
        $this->format = $format;
        return $this;
    }

    /**
     * Returns the actual set service
     *
     * @return mixed|null
     */
    public function getService()
    {
        return $this->service;
    }

    /**
     * Sets a new callback for service validation
     *
     * @param mixed $service
     * @return PostCode  Provides fluid interface
     */
    public function setService($service)
    {
        $this->service = $service;
        return $this;
    }

    /**
     * Returns true if and only if $value is a valid postalcode
     *
     * @param  string $value
     * @return bool
     * @throws Exception\InvalidArgumentException
     */
    public function isValid($value)
    {
        if (!is_string($value) && !is_int($value)) {
            $this->error(self::INVALID);
            return false;
        }

        $this->setValue($value);

        $service = $this->getService();
        $locale  = $this->getLocale();
        $format  = $this->getFormat();
        if ((null === $format || '' === $format) && !empty($locale)) {
            $region = Locale::getRegion($locale);
            if ('' === $region) {
                throw new Exception\InvalidArgumentException("Locale must contain a region");
            }
            if (isset(static::$postCodeRegex[$region])) {
                $format = static::$postCodeRegex[$region];
            }
        }
        if (null === $format || '' === $format) {
            throw new Exception\InvalidArgumentException("A postcode-format string has to be given for validation");
        }

        if ($format[0] !== '/') {
            $format = '/^' . $format;
        }
        if ($format[strlen($format) - 1] !== '/') {
            $format .= '$/';
        }

        if (!empty($service)) {
            if (!is_callable($service)) {
                throw new Exception\InvalidArgumentException('Invalid callback given');
            }

            try {
                $callback = new Callback($service);
                $callback->setOptions(array(
                    'format' => $format,
                    'locale' => $locale,
                ));
                if (!$callback->isValid($value)) {
                    $this->error(self::SERVICE, $value);
                    return false;
                }
            } catch (\Exception $e) {
                $this->error(self::SERVICEFAILURE, $value);
                return false;
            }
        }

        if (!preg_match($format, $value)) {
            $this->error(self::NO_MATCH);
            return false;
        }

        return true;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Validator;

use Traversable;
use Zend\Stdlib\ArrayUtils;
use Zend\Validator\AbstractValidator;

class PhoneNumber extends AbstractValidator
{

    const NO_MATCH    = 'phoneNumberNoMatch';
    const UNSUPPORTED = 'phoneNumberUnsupported';
    const INVALID     = 'phoneNumberInvalid';

    /**
     * Validation failure message template definitions
     *
     * @var array
     */
    protected $messageTemplates = array(
        self::NO_MATCH    => 'The input does not match a phone number format',
        self::UNSUPPORTED => 'The country provided is currently unsupported',
        self::INVALID     => 'Invalid type given. String expected',
    );

    /**
     * Phone Number Patterns
     *
     * @link http://code.google.com/p/libphonenumber/source/browse/trunk/resources/PhoneNumberMetadata.xml
     * @var array
     */
    protected static $phone = array();

    /**
     * ISO 3611 Country Code
     *
     * @var string
     */
    protected $country;

    /**
     * Allow Possible Matches
     *
     * @var bool
     */
    protected $allowPossible = false;

    /**
     * Allowed Types
     *
     * @var array
     */
    protected $allowedTypes = array(
        'general',
        'fixed',
        'tollfree',
        'personal',
        'mobile',
        'voip',
        'uan',
    );

    /**
     * Constructor for the PhoneNumber validator
     *
     * Options
     * - country | string | field or value
     * - allowed_types | array | array of allowed types
     * - allow_possible | boolean | allow possible matches aka non-strict
     *
     * @param array|Traversable $options
     */
    public function __construct($options = array())
    {
        if ($options instanceof Traversable) {
            $options = ArrayUtils::iteratorToArray($options);
        }

        if (array_key_exists('country', $options)) {
            $this->setCountry($options['country']);
        }

        if (array_key_exists('allowed_types', $options)) {
            $this->allowedTypes($options['allowed_types']);
        }

        if (array_key_exists('allow_possible', $options)) {
            $this->allowPossible($options['allow_possible']);
        }

        parent::__construct($options);
    }

    /**
     * Allowed Types
     *
     * @param  array|null $types
     * @return self|array
     */
    public function allowedTypes(array $types = null)
    {
        if (null !== $types) {
            $this->allowedTypes = $types;

            return $this;
        }

        return $this->allowedTypes;
    }

    /**
     * Allow Possible
     *
     * @param  bool|null $possible
     * @return self|bool
     */
    public function allowPossible($possible = null)
    {
        if (null !== $possible) {
            $this->allowPossible = (bool) $possible;

            return $this;
        }

        return $this->allowPossible;
    }

    /**
     * Get Country
     *
     * @return string
     */
    public function getCountry()
    {
        return $this->country;
    }

    /**
     * Set Country
     *
     * @param  string $country
     * @return self
     */
    public function setCountry($country)
    {
        $this->country = $country;

        return $this;
    }

    /**
     * Load Pattern
     *
     * @param  string        $code
     * @return array[]|false
     */
    protected function loadPattern($code)
    {
        if (!isset(static::$phone[$code])) {
            if (!preg_match('/^[A-Z]{2}$/D', $code)) {
                return false;
            }

            $file = __DIR__ . '/PhoneNumber/' . $code . '.php';
            if (!file_exists($file)) {
                return false;
            }

            static::$phone[$code] = include $file;
        }

        return static::$phone[$code];
    }

    /**
     * Returns true if and only if $value matches phone number format
     *
     * @param  string $value
     * @param  array  $context
     * @return bool
     */
    public function isValid($value = null, $context = null)
    {
        if (!is_scalar($value)) {
            $this->error(self::INVALID);

            return false;
        }
        $this->setValue($value);

        $country = $this->getCountry();

        if (!$countryPattern = $this->loadPattern($country)) {
            if (isset($context[$country])) {
                $country = $context[$country];
            }

            if (!$countryPattern = $this->loadPattern($country)) {
                $this->error(self::UNSUPPORTED);

                return false;
            }
        }

        $codeLength = strlen($countryPattern['code']);

        /*
         * Check for existence of either:
         *   1) E.123/E.164 international prefix
         *   2) International double-O prefix
         *   3) Bare country prefix
         */
        if (('+' . $countryPattern['code']) == substr($value, 0, $codeLength + 1)) {
            $valueNoCountry = substr($value, $codeLength + 1);
        } elseif (('00' . $countryPattern['code']) == substr($value, 0, $codeLength + 2)) {
            $valueNoCountry = substr($value, $codeLength + 2);
        } elseif ($countryPattern['code'] == substr($value, 0, $codeLength)) {
            $valueNoCountry = substr($value, $codeLength);
        }

        // check against allowed types strict match:
        foreach ($countryPattern['patterns']['national'] as $type => $pattern) {
            if (in_array($type, $this->allowedTypes)) {
                // check pattern:
                if (preg_match($pattern, $value)) {
                    return true;
                } elseif (isset($valueNoCountry) && preg_match($pattern, $valueNoCountry)) {
                    // this handles conditions where the country code and prefix are the same
                    return true;
                }
            }
        }

        // check for possible match:
        if ($this->allowPossible()) {
            foreach ($countryPattern['patterns']['possible'] as $type => $pattern) {
                if (in_array($type, $this->allowedTypes)) {
                    // check pattern:
                    if (preg_match($pattern, $value)) {
                        return true;
                    } elseif (isset($valueNoCountry) && preg_match($pattern, $valueNoCountry)) {
                        // this handles conditions where the country code and prefix are the same
                        return true;
                    }
                }
            }
        }

        $this->error(self::NO_MATCH);

        return false;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Validator;

use Zend\I18n\Filter\Alpha as AlphaFilter;

class Alpha extends Alnum
{
    const INVALID      = 'alphaInvalid';
    const NOT_ALPHA    = 'notAlpha';
    const STRING_EMPTY = 'alphaStringEmpty';

    /**
     * Alphabetic filter used for validation
     *
     * @var AlphaFilter
     */
    protected static $filter = null;

    /**
     * Validation failure message template definitions
     *
     * @var array
     */
    protected $messageTemplates = array(
        self::INVALID      => "Invalid type given. String expected",
        self::NOT_ALPHA    => "The input contains non alphabetic characters",
        self::STRING_EMPTY => "The input is an empty string"
    );

    /**
     * Options for this validator
     *
     * @var array
     */
    protected $options = array(
        'allowWhiteSpace' => false,  // Whether to allow white space characters; off by default
    );

    /**
     * Returns true if and only if $value contains only alphabetic characters
     *
     * @param  string $value
     * @return bool
     */
    public function isValid($value)
    {
        if (!is_string($value)) {
            $this->error(self::INVALID);
            return false;
        }

        $this->setValue($value);

        if ('' === $value) {
            $this->error(self::STRING_EMPTY);
            return false;
        }

        if (null === static::$filter) {
            static::$filter = new AlphaFilter();
        }

        //static::$filter->setAllowWhiteSpace($this->allowWhiteSpace);
        static::$filter->setAllowWhiteSpace($this->options['allowWhiteSpace']);

        if ($value !== static::$filter->filter($value)) {
            $this->error(self::NOT_ALPHA);
            return false;
        }

        return true;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '501',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-8]\\d{6}|0\\d{10}$/',
            'fixed' => '/^[234578][02]\\d{5}$/',
            'mobile' => '/^6[0-367]\\d{5}$/',
            'tollfree' => '/^0800\\d{7}$/',
            'emergency' => '/^9(?:0|11)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}(?:\\d{4})?$/',
            'fixed' => '/^\\d{7}$/',
            'mobile' => '/^\\d{7}$/',
            'tollfree' => '/^\\d{11}$/',
            'emergency' => '/^\\d{2,3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '502',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-7]\\d{7}|1[89]\\d{9}$/',
            'fixed' => '/^[267][2-9]\\d{6}$/',
            'mobile' => '/^[345]\\d{7}$/',
            'tollfree' => '/^18[01]\\d{8}$/',
            'premium' => '/^19\\d{9}$/',
            'shortcode' => '/^1(?:2[124-9]|[57]\\d{2})$/',
            'emergency' => '/^1(?:10|2[03])$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}(?:\\d{3})?$/',
            'fixed' => '/^\\d{8}$/',
            'mobile' => '/^\\d{8}$/',
            'tollfree' => '/^\\d{11}$/',
            'premium' => '/^\\d{11}$/',
            'shortcode' => '/^\\d{3,4}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '239',
    'patterns' => array(
        'national' => array(
            'general' => '/^[29]\\d{6}$/',
            'fixed' => '/^22\\d{5}$/',
            'mobile' => '/^9[89]\\d{5}$/',
            'emergency' => '/^112$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '44',
    'patterns' => array(
        'national' => array(
            'general' => '/^\\d{7,10}$/',
            'fixed' => '/^2(?:0[01378]|3[0189]|4[017]|8[0-46-9]|9[012])\\d{7}|1(?:(?:1(?:3[0-48]|[46][0-4]|5[012789]|7[0-49]|8[01349])|21[0-7]|31[0-8]|[459]1\\d|61[0-46-9]))\\d{6}|1(?:2(?:0[024-9]|2[3-9]|3[3-79]|4[1-689]|[58][02-9]|6[0-4789]|7[013-9]|9\\d)|3(?:0\\d|[25][02-9]|3[02-579]|[468][0-46-9]|7[1235679]|9[24578])|4(?:0[03-9]|[28][02-5789]|[37]\\d|4[02-69]|5[0-8]|[69][0-79])|5(?:0[1235-9]|2[024-9]|3[015689]|4[02-9]|5[03-9]|6\\d|7[0-35-9]|8[0-468]|9[0-5789])|6(?:0[034689]|2[0-35689]|[38][013-9]|4[1-467]|5[0-69]|6[13-9]|7[0-8]|9[0124578])|7(?:0[0246-9]|2\\d|3[023678]|4[03-9]|5[0-46-9]|6[013-9]|7[0-35-9]|8[024-9]|9[02-9])|8(?:0[35-9]|2[1-5789]|3[02-578]|4[0-578]|5[124-9]|6[2-69]|7\\d|8[02-9]|9[02569])|9(?:0[02-589]|2[02-689]|3[1-5789]|4[2-9]|5[0-579]|6[234789]|7[0124578]|8\\d|9[2-57]))\\d{6}|1(?:2(?:0(?:46[1-4]|87[2-9])|545[1-79]|76(?:2\\d|3[1-8]|6[1-6])|9(?:7(?:2[0-4]|3[2-5])|8(?:2[2-8]|7[0-4789]|8[345])))|3(?:638[2-5]|647[23]|8(?:47[04-9]|64[015789]))|4(?:044[1-7]|20(?:2[23]|8\\d)|6(?:0(?:30|5[2-57]|6[1-8]|7[2-8])|140)|8(?:052|87[123]))|5(?:24(?:3[2-79]|6\\d)|276\\d|6(?:26[06-9]|686))|6(?:06(?:4\\d|7[4-79])|295[567]|35[34]\\d|47(?:24|61)|59(?:5[08]|6[67]|74)|955[0-4])|7(?:26(?:6[13-9]|7[0-7])|442\\d|50(?:2[0-3]|[3-68]2|76))|8(?:27[56]\\d|37(?:5[2-5]|8[239])|84(?:3[2-58]))|9(?:0(?:0(?:6[1-8]|85)|52\\d)|3583|4(?:66[1-8]|9(?:2[01]|81))|63(?:23|3[1-4])|9561))\\d{3}|176888[234678]\\d{2}|16977[23]\\d{3}$/',
            'mobile' => '/^7(?:[1-4]\\d\\d|5(?:0[0-8]|[13-9]\\d|2[0-35-9])|7(?:0[1-9]|[1-7]\\d|8[02-9]|9[0-689])|8(?:[014-9]\\d|[23][0-8])|9(?:[04-9]\\d|1[02-9]|2[0-35-9]|3[0-689]))\\d{6}$/',
            'pager' => '/^76(?:0[012]|2[356]|4[0134]|5[49]|6[0-369]|77|81|9[39])\\d{6}$/',
            'tollfree' => '/^80(?:0(?:1111|\\d{6,7})|8\\d{7})|500\\d{6}$/',
            'premium' => '/^(?:87[123]|9(?:[01]\\d|8[2349]))\\d{7}$/',
            'shared' => '/^8(?:4(?:5464\\d|[2-5]\\d{7})|70\\d{7})$/',
            'personal' => '/^70\\d{8}$/',
            'voip' => '/^56\\d{8}$/',
            'uan' => '/^(?:3[0347]|55)\\d{8}$/',
            'shortcode' => '/^1(?:0[01]|1(?:1|[68]\\d{3})|2[123]|33|4(?:1|7\\d)|5\\d|70\\d|800\\d|9[15])|2(?:02|2(?:02|11|2)|3(?:02|45)|425)|3[13]3|4(?:0[02]|35[01]|44[45]|5\\d)|650|789|901$/',
            'emergency' => '/^112|999$/',
        ),
        'possible' => array(
            'general' => '/^\\d{4,10}$/',
            'mobile' => '/^\\d{10}$/',
            'pager' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{7}(?:\\d{2,3})?$/',
            'premium' => '/^\\d{10}$/',
            'shared' => '/^\\d{7}(?:\\d{3})?$/',
            'personal' => '/^\\d{10}$/',
            'voip' => '/^\\d{10}$/',
            'uan' => '/^\\d{10}$/',
            'shortcode' => '/^\\d{3,6}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '51',
    'patterns' => array(
        'national' => array(
            'general' => '/^[14-9]\\d{7,8}$/',
            'fixed' => '/^(?:1\\d|4[1-4]|5[1-46]|6[1-7]|7[2-46]|8[2-4])\\d{6}$/',
            'mobile' => '/^9\\d{8}$/',
            'tollfree' => '/^800\\d{5}$/',
            'premium' => '/^805\\d{5}$/',
            'shared' => '/^801\\d{5}$/',
            'personal' => '/^80[24]\\d{5}$/',
            'emergency' => '/^1(?:05|1[67])$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,9}$/',
            'fixed' => '/^\\d{6,8}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{8}$/',
            'premium' => '/^\\d{8}$/',
            'shared' => '/^\\d{8}$/',
            'personal' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '236',
    'patterns' => array(
        'national' => array(
            'general' => '/^[278]\\d{7}$/',
            'fixed' => '/^2[12]\\d{6}$/',
            'mobile' => '/^7[0257]\\d{6}$/',
            'premium' => '/^8776\\d{4}$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '56',
    'patterns' => array(
        'national' => array(
            'general' => '/^(?:[2-9]|600|123)\\d{7,8}$/',
            'fixed' => '/^(?:[23]2|41|58)\\d{7}|(?:3[3-5]|4[235]|5[1-357]|6[13-57]|7[1-35])\\d{6,7}$/',
            'mobile' => '/^9[5-9]\\d{7}$/',
            'tollfree' => '/^800\\d{6}|1230\\d{7}$/',
            'shared' => '/^600\\d{7,8}$/',
            'voip' => '/^44\\d{7}$/',
            'emergency' => '/^13[123]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,11}$/',
            'fixed' => '/^\\d{6,9}$/',
            'mobile' => '/^\\d{8,9}$/',
            'tollfree' => '/^\\d{9,11}$/',
            'shared' => '/^\\d{10,11}$/',
            'voip' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '670',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-489]\\d{6}|7\\d{6,7}$/',
            'fixed' => '/^(?:2[1-5]|3[1-9]|4[1-4])\\d{5}$/',
            'mobile' => '/^7[78]\\d{6}$/',
            'tollfree' => '/^80\\d{5}$/',
            'premium' => '/^90\\d{5}$/',
            'personal' => '/^70\\d{5}$/',
            'shortcode' => '/^1(?:0[02]|2[0138]|72|9[07])$/',
            'emergency' => '/^11[25]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,8}$/',
            'fixed' => '/^\\d{7}$/',
            'mobile' => '/^\\d{8}$/',
            'tollfree' => '/^\\d{7}$/',
            'premium' => '/^\\d{7}$/',
            'personal' => '/^\\d{7}$/',
            'shortcode' => '/^\\d{3}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '44',
    'patterns' => array(
        'national' => array(
            'general' => '/^[135789]\\d{6,9}$/',
            'fixed' => '/^1534\\d{6}$/',
            'mobile' => '/^7(?:509|7(?:00|97)|829|937)\\d{6}$/',
            'pager' => '/^76(?:0[012]|2[356]|4[0134]|5[49]|6[0-369]|77|81|9[39])\\d{6}$/',
            'tollfree' => '/^80(?:07(?:35|81)|8901)\\d{4}$/',
            'premium' => '/^(?:871206|90(?:066[59]|1810|71(?:07|55)))\\d{4}$/',
            'shared' => '/^8(?:4(?:4(?:4(?:05|42|69)|703)|5(?:041|800))|70002)\\d{4}$/',
            'personal' => '/^701511\\d{4}$/',
            'voip' => '/^56\\d{8}$/',
            'uan' => '/^3(?:0(?:07(?:35|81)|8901)|3\\d{4}|4(?:4(?:4(?:05|42|69)|703)|5(?:041|800))|7(?:0002|1206))\\d{4}|55\\d{8}$/',
            'shortcode' => '/^1(?:00|18\\d{3}|23|4(?:[14]|28|7\\d)|5\\d|7(?:0[12]|[128]|35?)|808|9[135])|23[234]$/',
            'emergency' => '/^112|999$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,10}$/',
            'mobile' => '/^\\d{10}$/',
            'pager' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'shared' => '/^\\d{10}$/',
            'personal' => '/^\\d{10}$/',
            'voip' => '/^\\d{10}$/',
            'uan' => '/^\\d{10}$/',
            'shortcode' => '/^\\d{3,6}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '63',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-9]\\d{7,9}|1800\\d{7,9}$/',
            'fixed' => '/^(?:2|3[2-68]|4[2-9]|5[2-6]|6[2-58]|7[24578]|8[2-8])\\d{7}$/',
            'mobile' => '/^9(?:0[5-9]|1[025-9]|2[0-36-9]|3[02-9]|4[236-9]|7[349]|89|9[49])\\d{7}$/',
            'tollfree' => '/^1800\\d{7,9}$/',
            'emergency' => '/^11[27]|911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,13}$/',
            'fixed' => '/^\\d{7,9}$/',
            'mobile' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{11,13}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '356',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2579]\\d{7}$/',
            'fixed' => '/^2(?:0(?:1[0-6]|[69]\\d)|[1-357]\\d{2})\\d{4}$/',
            'mobile' => '/^(?:7(?:210|[79]\\d{2})|9(?:2[13]\\d|696|8(?:1[1-3]|89|97)|9\\d{2}))\\d{4}$/',
            'pager' => '/^7117\\d{4}$/',
            'premium' => '/^50(?:0(?:3[1679]|4\\d)|[169]\\d{2}|7[06]\\d)\\d{3}$/',
            'emergency' => '/^112$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '226',
    'patterns' => array(
        'national' => array(
            'general' => '/^[24-7]\\d{7}$/',
            'fixed' => '/^(?:20(?:49|5[23]|9[016-9])|40(?:4[56]|5[4-6]|7[0179])|50[34]\\d)\\d{4}$/',
            'mobile' => '/^(?:6(?:[056]\\d|1[0-3]|8[0-2]|90)|7(?:[02-68]\\d|1[0-4689]|7[0-69]|9[0-689]))\\d{5}$/',
            'emergency' => '/^1[78]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
            'emergency' => '/^\\d{2}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '62',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-9]\\d{6,10}$/',
            'fixed' => '/^2(?:1(?:[0-8]\\d{6,7}|9\\d{6})|[24]\\d{7,8})|(?:2(?:[35][1-4]|6[0-8]|7[1-6]|8\\d|9[1-8])|3(?:1|2[1-578]|3[1-68]|4[1-3]|5[1-8]|6[1-3568]|7[0-46]|8\\d)|4(?:0[1-589]|1[01347-9]|2[0-36-8]|3[0-24-68]|5[1-378]|6[1-5]|7[134]|8[1245])|5(?:1[1-35-9]|2[25-8]|3[1246-9]|4[1-3589]|5[1-46]|6[1-8])|6(?:19?|[25]\\d|3[1-469]|4[1-6])|7(?:1[1-46-9]|2[14-9]|[36]\\d|4[1-8]|5[1-9]|7[0-36-9])|9(?:0[12]|1[013-8]|2[0-479]|5[125-8]|6[23679]|7[159]|8[01346]))\\d{5,8}$/',
            'mobile' => '/^(?:2(?:1(?:3[145]|4[01]|5[1-469]|60|8[0359]|9\\d)|2(?:88|9[1256])|3[1-4]9|4(?:36|91)|5(?:1[349]|[2-4]9)|6[0-7]9|7(?:[1-36]9|4[39])|8[1-5]9|9[1-48]9)|3(?:19[1-3]|2[12]9|3[13]9|4(?:1[69]|39)|5[14]9|6(?:1[69]|2[89])|709)|4[13]19|5(?:1(?:19|8[39])|4[129]9|6[12]9)|6(?:19[12]|2(?:[23]9|77))|7(?:1[13]9|2[15]9|419|5(?:1[89]|29)|6[15]9|7[178]9))\\d{5,6}|8[1-35-9]\\d{7,9}$/',
            'tollfree' => '/^177\\d{6,8}|800\\d{5,7}$/',
            'premium' => '/^809\\d{7}$/',
            'emergency' => '/^11[02389]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5,11}$/',
            'fixed' => '/^\\d{5,10}$/',
            'mobile' => '/^\\d{9,11}$/',
            'tollfree' => '/^\\d{8,11}$/',
            'premium' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '31',
    'patterns' => array(
        'national' => array(
            'general' => '/^1\\d{4,8}|[2-7]\\d{8}|[89]\\d{6,9}$/',
            'fixed' => '/^(?:1[0135-8]|2[02-69]|3[0-68]|4[0135-9]|[57]\\d|8[478])\\d{7}$/',
            'mobile' => '/^6[1-58]\\d{7}$/',
            'pager' => '/^66\\d{7}$/',
            'tollfree' => '/^800\\d{4,7}$/',
            'premium' => '/^90[069]\\d{4,7}$/',
            'voip' => '/^85\\d{7}$/',
            'uan' => '/^140(?:1(?:[035]|[16-8]\\d)|2(?:[0346]|[259]\\d)|3(?:[03568]|[124]\\d)|4(?:[0356]|[17-9]\\d)|5(?:[0358]|[124679]\\d)|7\\d|8[458])$/',
            'shortcode' => '/^18\\d{2}$/',
            'emergency' => '/^112|911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5,10}$/',
            'fixed' => '/^\\d{9}$/',
            'mobile' => '/^\\d{9}$/',
            'pager' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{7,10}$/',
            'premium' => '/^\\d{7,10}$/',
            'voip' => '/^\\d{9}$/',
            'uan' => '/^\\d{5,6}$/',
            'shortcode' => '/^\\d{4}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '267',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-79]\\d{6,7}$/',
            'fixed' => '/^(?:2(?:4[0-48]|6[0-24]|9[0578])|3(?:1[0235-9]|55|6\\d|7[01]|9[0-57])|4(?:6[03]|7[1267]|9[0-5])|5(?:3[0389]|4[0489]|7[1-47]|88|9[0-49])|6(?:2[1-35]|5[149]|8[067]))\\d{4}$/',
            'mobile' => '/^7(?:[1-35]\\d{6}|[46][0-7]\\d{5}|7[01]\\d{5})$/',
            'premium' => '/^90\\d{5}$/',
            'voip' => '/^79[12][01]\\d{4}$/',
            'emergency' => '/^99[789]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,8}$/',
            'fixed' => '/^\\d{7}$/',
            'mobile' => '/^\\d{8}$/',
            'premium' => '/^\\d{7}$/',
            'voip' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '263',
    'patterns' => array(
        'national' => array(
            'general' => '/^2(?:[012457-9]\\d{3,8}|6\\d{3,6})|[13-79]\\d{4,8}|86\\d{8}$/',
            'fixed' => '/^(?:1[3-9]|2(?:0[45]|[16]|2[28]|[49]8?|58[23]|7[246]|8[1346-9])|3(?:08?|17?|3[78]|[2456]|7[1569]|8[379])|5(?:[07-9]|1[78]|483|5(?:7?|8))|6(?:0|28|37?|[45][68][78]|98?)|848)\\d{3,6}|(?:2(?:27|5|7[135789]|8[25])|3[39]|5[1-46]|6[126-8])\\d{4,6}|2(?:0|70)\\d{5,6}|(?:4\\d|9[2-8])\\d{4,7}$/',
            'mobile' => '/^7[137]\\d{7}|86(?:22|44)\\d{6}$/',
            'voip' => '/^86(?:1[12]|30|8[367]|99)\\d{6}$/',
            'emergency' => '/^(?:112|99[3459])$/',
        ),
        'possible' => array(
            'general' => '/^\\d{3,10}$/',
            'mobile' => '/^\\d{9,10}$/',
            'voip' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '378',
    'patterns' => array(
        'national' => array(
            'general' => '/^[05-7]\\d{7,9}$/',
            'fixed' => '/^0549(?:8[0157-9]|9\\d)\\d{4}$/',
            'mobile' => '/^6[16]\\d{6}$/',
            'premium' => '/^7[178]\\d{6}$/',
            'voip' => '/^5[158]\\d{6}$/',
            'emergency' => '/^11[358]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,10}$/',
            'mobile' => '/^\\d{8}$/',
            'premium' => '/^\\d{8}$/',
            'voip' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '252',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-79]\\d{6,8}$/',
            'fixed' => '/^(?:[134]\\d|2[0-79]|5[57-9])\\d{5}$/',
            'mobile' => '/^(?:15\\d|2(?:4\\d|8)|6[17-9]?\\d{2}|7\\d{2}|9[01]\\d)\\d{5}$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,9}$/',
            'fixed' => '/^\\d{7}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '352',
    'patterns' => array(
        'national' => array(
            'general' => '/^[24-9]\\d{3,10}|3(?:[0-46-9]\\d{2,9}|5[013-9]\\d{1,8})$/',
            'fixed' => '/^(?:2(?:2\\d{1,2}|3[2-9]|[67]\\d|4[1-8]\\d?|5[1-5]\\d?|9[0-24-9]\\d?)|3(?:[059][05-9]|[13]\\d|[26][015-9]|4[0-26-9]|7[0-389]|8[08])\\d?|4\\d{2,3}|5(?:[01458]\\d|[27][0-69]|3[0-3]|[69][0-7])\\d?|7(?:1[019]|2[05-9]|3[05]|[45][07-9]|[679][089]|8[06-9])\\d?|8(?:0[2-9]|1[0-36-9]|3[3-9]|[469]9|[58][7-9]|7[89])\\d?|9(?:0[89]|2[0-49]|37|49|5[0-27-9]|7[7-9]|9[0-478])\\d?)\\d{1,7}$/',
            'mobile' => '/^6[269][18]\\d{6}$/',
            'tollfree' => '/^800\\d{5}$/',
            'premium' => '/^90[01]\\d{5}$/',
            'shared' => '/^801\\d{5}$/',
            'personal' => '/^70\\d{6}$/',
            'voip' => '/^20\\d{2,8}$/',
            'shortcode' => '/^12\\d{3}$/',
            'emergency' => '/^11[23]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{4,11}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{8}$/',
            'premium' => '/^\\d{8}$/',
            'shared' => '/^\\d{8}$/',
            'personal' => '/^\\d{8}$/',
            'voip' => '/^\\d{4,10}$/',
            'shortcode' => '/^\\d{3,5}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '968',
    'patterns' => array(
        'national' => array(
            'general' => '/^(?:2[2-6]|5|9[1-9])\\d{6}|800\\d{5,6}$/',
            'fixed' => '/^2[2-6]\\d{6}$/',
            'mobile' => '/^9[1-9]\\d{6}$/',
            'tollfree' => '/^8007\\d{4,5}|500\\d{4}$/',
            'emergency' => '/^9999$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,9}$/',
            'fixed' => '/^\\d{8}$/',
            'mobile' => '/^\\d{8}$/',
            'tollfree' => '/^\\d{7,9}$/',
            'emergency' => '/^\\d{4}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '351',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-46-9]\\d{8}$/',
            'fixed' => '/^2(?:[12]\\d|[35][1-689]|4[1-59]|6[1-35689]|7[1-9]|8[1-69]|9[1256])\\d{6}$/',
            'mobile' => '/^9(?:[136]\\d{2}|2[0-79]\\d|480)\\d{5}$/',
            'tollfree' => '/^80[02]\\d{6}$/',
            'premium' => '/^76(?:0[1-57]|1[2-47]|2[237])\\d{5}$/',
            'shared' => '/^80(?:8\\d|9[1579])\\d{5}$/',
            'personal' => '/^884[128]\\d{5}$/',
            'voip' => '/^30\\d{7}$/',
            'uan' => '/^70(?:7\\d|8[17])\\d{5}$/',
            'emergency' => '/^112$/',
        ),
        'possible' => array(
            'general' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '223',
    'patterns' => array(
        'national' => array(
            'general' => '/^[246-8]\\d{7}$/',
            'fixed' => '/^(?:2(?:0(?:2[0-589]|7[027-9])|1(?:2[5-7]|[3-689]\\d))|44[239]\\d)\\d{4}$/',
            'mobile' => '/^(?:6[3569]|7\\d)\\d{6}$/',
            'tollfree' => '/^800\\d{5}$/',
            'emergency' => '/^1[578]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
            'emergency' => '/^\\d{2}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '33',
    'patterns' => array(
        'national' => array(
            'general' => '/^[124-9]\\d{8}|3\\d{3}(?:\\d{5})?$/',
            'fixed' => '/^[1-5]\\d{8}$/',
            'mobile' => '/^6\\d{8}|7[5-9]\\d{7}$/',
            'tollfree' => '/^80\\d{7}$/',
            'premium' => '/^3\\d{3}|89[1-37-9]\\d{6}$/',
            'shared' => '/^8(?:1[019]|2[0156]|84|90)\\d{6}$/',
            'voip' => '/^9\\d{8}$/',
            'emergency' => '/^1(?:[578]|12)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{4}(?:\\d{5})?$/',
            'fixed' => '/^\\d{9}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{9}$/',
            'premium' => '/^\\d{4}(?:\\d{5})?$/',
            'shared' => '/^\\d{9}$/',
            'voip' => '/^\\d{9}$/',
            'emergency' => '/^\\d{2,3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '298',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-9]\\d{5}$/',
            'fixed' => '/^(?:20|[3-4]\\d|8[19])\\d{4}$/',
            'mobile' => '/^(?:2[1-9]|5\\d|7[1-79])\\d{4}$/',
            'tollfree' => '/^80[257-9]\\d{3}$/',
            'premium' => '/^90(?:[1345][15-7]|2[125-7]|99)\\d{2}$/',
            'voip' => '/^(?:6[0-36]|88)\\d{4}$/',
            'shortcode' => '/^1(?:1[48]|4[124]\\d|71\\d|8[7-9]\\d)$/',
            'emergency' => '/^112$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6}$/',
            'shortcode' => '/^\\d{3,4}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '227',
    'patterns' => array(
        'national' => array(
            'general' => '/^[029]\\d{7}$/',
            'fixed' => '/^2(?:0(?:20|3[1-7]|4[134]|5[14]|6[14578]|7[1-578])|1(?:4[145]|5[14]|6[14-68]|7[169]|88))\\d{4}$/',
            'mobile' => '/^9[0-46-9]\\d{6}$/',
            'tollfree' => '/^08\\d{6}$/',
            'premium' => '/^09\\d{6}$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '1',
    'patterns' => array(
        'national' => array(
            'general' => '/^[5789]\\d{9}$/',
            'fixed' => '/^7215(?:4[2-8]|8[239]|9[056])\\d{4}$/',
            'mobile' => '/^7215(?:1[02]|2\\d|5[034679]|8[014-8])\\d{4}$/',
            'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\\d{6}$/',
            'premium' => '/^900[2-9]\\d{6}$/',
            'personal' => '/^5(?:00|33|44)[2-9]\\d{6}$/',
            'emergency' => '/^919$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}(?:\\d{3})?$/',
            'mobile' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'personal' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '220',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-9]\\d{6}$/',
            'fixed' => '/^(?:4(?:[23]\\d{2}|4(?:1[024679]|[6-9]\\d))|5(?:54[0-7]|6(?:[67]\\d)|7(?:1[04]|2[035]|3[58]|48))|8\\d{3})\\d{3}$/',
            'mobile' => '/^(?:2[0-2]|[3679]\\d)\\d{5}$/',
            'emergency' => '/^1?1[678]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}$/',
            'emergency' => '/^\\d{2,3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '686',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-689]\\d{4}$/',
            'fixed' => '/^(?:[234]\\d|50|8[1-5])\\d{3}$/',
            'mobile' => '/^6\\d{4}|9(?:[0-8]\\d|9[015-8])\\d{2}$/',
            'shortcode' => '/^10(?:[0-8]|5[01259])$/',
            'emergency' => '/^99[2349]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5}$/',
            'shortcode' => '/^\\d{3,4}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '30',
    'patterns' => array(
        'national' => array(
            'general' => '/^[26-9]\\d{9}$/',
            'fixed' => '/^2(?:1\\d{2}|2(?:3[1-8]|4[1-7]|5[1-4]|6[1-8]|7[1-5]|[289][1-9])|3(?:1\\d|2[1-57]|3[1-4]|[45][1-3]|7[1-7]|8[1-6]|9[1-79])|4(?:1\\d|2[1-8]|3[1-4]|4[13-5]|6[1-578]|9[1-5])|5(?:1\\d|[239][1-4]|4[124]|5[1-6])|6(?:1\\d|3[124]|4[1-7]|5[13-9]|[269][1-6]|7[14]|8[1-5])|7(?:1\\d|2[1-5]|3[1-6]|4[1-7]|5[1-57]|6[134]|9[15-7])|8(?:1\\d|2[1-5]|[34][1-4]|9[1-7]))\\d{6}$/',
            'mobile' => '/^69\\d{8}$/',
            'tollfree' => '/^800\\d{7}$/',
            'premium' => '/^90[19]\\d{7}$/',
            'shared' => '/^8(?:0[16]|12|25)\\d{7}$/',
            'personal' => '/^70\\d{8}$/',
            'emergency' => '/^1(?:00|12|66|99)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '420',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-8]\\d{8}|9\\d{8,11}$/',
            'fixed' => '/^2\\d{8}|(?:3[1257-9]|4[16-9]|5[13-9])\\d{7}$/',
            'mobile' => '/^(?:60[1-8]|7(?:0[2-5]|[2379]\\d))\\d{6}$/',
            'tollfree' => '/^800\\d{6}$/',
            'premium' => '/^9(?:0[05689]|76)\\d{6}$/',
            'shared' => '/^8[134]\\d{7}$/',
            'personal' => '/^70[01]\\d{6}$/',
            'voip' => '/^9[17]0\\d{6}$/',
            'uan' => '/^9(?:5[056]|7[234])\\d{6}$/',
            'voicemail' => '/^9(?:3\\d{9}|6\\d{7,10})$/',
            'shortcode' => '/^1(?:1(?:6\\d{3}|8\\d)|2\\d{2,3}|3\\d{3,4}|4\\d{3}|99)$/',
            'emergency' => '/^1(?:12|5[058])$/',
        ),
        'possible' => array(
            'general' => '/^\\d{9,12}$/',
            'voicemail' => '/^\\d{9,12}$/',
            'shortcode' => '/^\\d{4,6}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '679',
    'patterns' => array(
        'national' => array(
            'general' => '/^[36-9]\\d{6}|0\\d{10}$/',
            'fixed' => '/^(?:3[0-5]|6[25-7]|8[58])\\d{5}$/',
            'mobile' => '/^(?:7[0-467]|8[367]|9[02346-9])\\d{5}$/',
            'tollfree' => '/^0800\\d{7}$/',
            'shortcode' => '/^0(?:04|1[34]|8[1-4])|1(?:0[1-3]|[25]9)|2[289]|30|[45]4|75|913$/',
            'emergency' => '/^91[17]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}(?:\\d{4})?$/',
            'fixed' => '/^\\d{7}$/',
            'mobile' => '/^\\d{7}$/',
            'tollfree' => '/^\\d{11}$/',
            'shortcode' => '/^\\d{2,3}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '98',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-6]\\d{4,9}|9(?:[1-4]\\d{8}|9\\d{2,8})|[178]\\d{9}$/',
            'fixed' => '/^2(?:1[2-9]\\d{2,7}|51\\d{3,7})|(?:241|3(?:11|51)|441|5[14]1)\\d{4,7}|(?:3(?:34|41)|6(?:11|52))\\d{6,7}|(?:1(?:[134589][12]|[27][1-4])|2(?:2[189]|[389][12]|42|5[256]|6[1-59]|7[34])|3(?:12|2[1-4]|3[125]|4[24-9]|5[23]|[6-9][12])|4(?:[135-9][12]|2[1-467]|4[2-4])|5(?:12|2[89]|3[1-5]|4[2-8]|[5-7][12]|8[1245])|6(?:12|[347-9][12]|51|6[1-6])|7(?:[13589][12]|2[1289]|4[1-4]|6[1-6]|7[1-3])|8(?:[145][12]|3[124578]|6[1256]|7[1245]))\\d{7}$/',
            'mobile' => '/^9(?:1(?:[039]\\d|[16][1-35-9]|2[1-8]|4[013-9]|[57][1-9]|8[13-9])|2[01]\\d|3(?:[035-9]\\d|13|2[1-579]|47))\\d{6}$/',
            'pager' => '/^943[24678]\\d{6}$/',
            'voip' => '/^993[12]\\d{6}$/',
            'uan' => '/^9990\\d{0,6}$/',
            'emergency' => '/^1(?:1[025]|25)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{4,10}$/',
            'fixed' => '/^\\d{5,10}$/',
            'mobile' => '/^\\d{10}$/',
            'pager' => '/^\\d{10}$/',
            'voip' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '269',
    'patterns' => array(
        'national' => array(
            'general' => '/^[379]\\d{6}$/',
            'fixed' => '/^7(?:6[0-37-9]|7[0-57-9])\\d{4}$/',
            'mobile' => '/^3[234]\\d{5}$/',
            'premium' => '/^(?:39[01]|9[01]0)\\d{4}$/',
            'emergency' => '/^1[78]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}$/',
            'emergency' => '/^\\d{2}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '595',
    'patterns' => array(
        'national' => array(
            'general' => '/^5[0-5]\\d{4,7}|[2-46-9]\\d{5,8}$/',
            'fixed' => '/^(?:[26]1|3[289]|4[124678]|7[123]|8[1236])\\d{5,7}|(?:2(?:2[4568]|7[15]|9[1-5])|3(?:18|3[167]|4[2357]|51)|4(?:18|2[45]|3[12]|5[13]|64|71|9[1-47])|5(?:[1-4]\\d|5[0234])|6(?:3[1-3]|44|7[1-4678])|7(?:17|4[0-4]|6[1-578]|75|8[0-8])|858)\\d{5,6}$/',
            'mobile' => '/^9(?:61|[78][1-6]|9[1-5])\\d{6}$/',
            'voip' => '/^8700[0-4]\\d{4}$/',
            'uan' => '/^[2-9]0\\d{4,7}$/',
            'shortcode' => '/^1[1-4]\\d$/',
            'emergency' => '/^128|911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5,9}$/',
            'mobile' => '/^\\d{9}$/',
            'voip' => '/^\\d{9}$/',
            'uan' => '/^\\d{6,9}$/',
            'shortcode' => '/^\\d{3}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '593',
    'patterns' => array(
        'national' => array(
            'general' => '/^1\\d{9,10}|[2-8]\\d{7}|9\\d{8}$/',
            'fixed' => '/^[2-7][2-7]\\d{6}$/',
            'mobile' => '/^9(?:[2-7]9|[89]\\d)\\d{6}$/',
            'tollfree' => '/^1800\\d{6,7}$/',
            'voip' => '/^[2-7]890\\d{4}$/',
            'emergency' => '/^1(?:0[12]|12)|911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,11}$/',
            'fixed' => '/^\\d{7,8}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{10,11}$/',
            'voip' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '389',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-578]\\d{7}$/',
            'fixed' => '/^(?:2(?:[23]\\d|5[124578]|6[01])|3(?:1[3-6]|[23][2-6]|4[2356])|4(?:[23][2-6]|4[3-6]|5[256]|6[25-8]|7[24-6]|8[4-6]))\\d{5}$/',
            'mobile' => '/^7(?:[0-25-8]\\d|33)\\d{5}$/',
            'tollfree' => '/^800\\d{5}$/',
            'premium' => '/^5[02-9]\\d{6}$/',
            'shared' => '/^8(?:0[1-9]|[1-9]\\d)\\d{5}$/',
            'emergency' => '/^1(?:12|9[234])$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
            'fixed' => '/^\\d{6,8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '268',
    'patterns' => array(
        'national' => array(
            'general' => '/^[027]\\d{7}$/',
            'fixed' => '/^2(?:2(?:0[07]|[13]7|2[57])|3(?:0[34]|[1278]3|3[23]|[46][34])|(?:40[4-69]|67)|5(?:0[5-7]|1[6-9]|[23][78]|48|5[01]))\\d{4}$/',
            'mobile' => '/^7[6-8]\\d{6}$/',
            'tollfree' => '/^0800\\d{4}$/',
            'emergency' => '/^999$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '507',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-9]\\d{6,7}$/',
            'fixed' => '/^(?:1(?:0[02-579]|19|2[37]|3[03]|4[479]|57|65|7[016-8]|8[58]|9[134])|2(?:[0235679]\\d|1[0-7]|4[04-9]|8[028])|3(?:0[0-7]|1[14-7]|2[0-3]|3[03]|4[0457]|5[56]|6[068]|7[078]|80|9\\d)|4(?:3[013-59]|4\\d|7[0-689])|5(?:[01]\\d|2[0-7]|[56]0|79)|7(?:0[09]|2[0-267]|[349]0|5[6-9]|7[0-24-7]|8[89])|8(?:[34]\\d|5[0-4]|8[02])|9(?:0[78]|1[0178]|2[0378]|3[379]|40|5[0489]|6[06-9]|7[046-9]|8[36-8]|9[1-9]))\\d{4}$/',
            'mobile' => '/^(?:1[16]1|21[89]|8(?:1[01]|7[23]))\\d{4}|6(?:[04-9]\\d|1[0-5]|2[0-7]|3[5-9])\\d{5}$/',
            'tollfree' => '/^80[09]\\d{4}$/',
            'premium' => '/^(?:779|8(?:2[235]|55|60|7[578]|86|95)|9(?:0[0-2]|81))\\d{4}$/',
            'shortcode' => '/^10[2-4]$/',
            'emergency' => '/^911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,8}$/',
            'fixed' => '/^\\d{7}$/',
            'tollfree' => '/^\\d{7}$/',
            'premium' => '/^\\d{7}$/',
            'shortcode' => '/^\\d{3}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '967',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-7]\\d{6,8}$/',
            'fixed' => '/^(?:1(?:7\\d|[2-68])|2[2-68]|3[2358]|4[2-58]|5[2-6]|6[3-58]|7[24-68])\\d{5}$/',
            'mobile' => '/^7[0137]\\d{7}$/',
            'emergency' => '/^19[1459]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,9}$/',
            'fixed' => '/^\\d{6,8}$/',
            'mobile' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '970',
    'patterns' => array(
        'national' => array(
            'general' => '/^[24589]\\d{7,8}|1(?:[78]\\d{8}|[49]\\d{2,3})$/',
            'fixed' => '/^(?:22[234789]|42[45]|82[01458]|92[369])\\d{5}$/',
            'mobile' => '/^5[69]\\d{7}$/',
            'tollfree' => '/^1800\\d{6}$/',
            'premium' => '/^1(?:4|9\\d)\\d{2}$/',
            'shared' => '/^1700\\d{6}$/',
        ),
        'possible' => array(
            'general' => '/^\\d{4,10}$/',
            'fixed' => '/^\\d{7,8}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{4,5}$/',
            'shared' => '/^\\d{10}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '960',
    'patterns' => array(
        'national' => array(
            'general' => '/^[3467]\\d{6}|9(?:00\\d{7}|\\d{6})$/',
            'fixed' => '/^(?:3(?:0[01]|3[0-59])|6(?:[567][02468]|8[024689]|90))\\d{4}$/',
            'mobile' => '/^(?:46[46]|7[3-9]\\d|9[6-9]\\d)\\d{4}$/',
            'pager' => '/^781\\d{4}$/',
            'premium' => '/^900\\d{7}$/',
            'shortcode' => '/^1(?:[19]0|23)$/',
            'emergency' => '/^1(?:02|19)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,10}$/',
            'fixed' => '/^\\d{7}$/',
            'mobile' => '/^\\d{7}$/',
            'pager' => '/^\\d{7}$/',
            'premium' => '/^\\d{10}$/',
            'shortcode' => '/^\\d{3}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '256',
    'patterns' => array(
        'national' => array(
            'general' => '/^\\d{9}$/',
            'fixed' => '/^20(?:[014]\\d{2}|2(?:40|[5-9]\\d)|3[23]\\d|5[0-4]\\d)\\d{4}|[34]\\d{8}$/',
            'mobile' => '/^7(?:0[0-7]|[15789]\\d|20|[46][0-4])\\d{6}$/',
            'tollfree' => '/^800[123]\\d{5}$/',
            'premium' => '/^90[123]\\d{6}$/',
            'emergency' => '/^999$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5,9}$/',
            'fixed' => '/^\\d{5,9}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{9}$/',
            'premium' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '49',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-35-9]\\d{3,14}|4(?:[0-8]\\d{4,12}|9(?:[0-37]\\d|4(?:[1-35-8]|4\\d?)|5\\d{1,2}|6[1-8]\\d?)\\d{2,7})$/',
            'fixed' => '/^[246]\\d{5,13}|3(?:[03-9]\\d{4,13}|2\\d{9})|5(?:0[2-8]|[1256]\\d|[38][0-8]|4\\d{0,2}|[79][0-7])\\d{3,11}|7(?:0[2-8]|[1-9]\\d)\\d{3,10}|8(?:0[2-9]|[1-9]\\d)\\d{3,10}|9(?:0[6-9]|[1-9]\\d)\\d{3,10}$/',
            'mobile' => '/^1(?:5[0-2579]\\d{8}|6[023]\\d{7,8}|7(?:[0-57-9]\\d?|6\\d)\\d{7})$/',
            'pager' => '/^16(?:4\\d{1,10}|[89]\\d{1,11})$/',
            'tollfree' => '/^800\\d{7,10}$/',
            'premium' => '/^900(?:[135]\\d{6}|9\\d{7})$/',
            'shared' => '/^180\\d{5,11}$/',
            'personal' => '/^700\\d{8}$/',
            'uan' => '/^18(?:1\\d{5,11}|[2-9]\\d{8})$/',
            'voicemail' => '/^17799\\d{7,8}$/',
            'shortcode' => '/^115$/',
            'emergency' => '/^11[02]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{2,15}$/',
            'mobile' => '/^\\d{10,11}$/',
            'pager' => '/^\\d{4,14}$/',
            'tollfree' => '/^\\d{10,13}$/',
            'premium' => '/^\\d{10,11}$/',
            'shared' => '/^\\d{8,14}$/',
            'personal' => '/^\\d{11}$/',
            'uan' => '/^\\d{8,14}$/',
            'voicemail' => '/^\\d{12,13}$/',
            'shortcode' => '/^\\d{3}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '40',
    'patterns' => array(
        'national' => array(
            'general' => '/^2\\d{5,8}|[37-9]\\d{8}$/',
            'fixed' => '/^2(?:1(?:\\d{7}|9\\d{3})|[3-6](?:\\d{7}|\\d9\\d{2}))|3[13-6]\\d{7}$/',
            'mobile' => '/^7[1-8]\\d{7}$/',
            'tollfree' => '/^800\\d{6}$/',
            'premium' => '/^90[036]\\d{6}$/',
            'shared' => '/^801\\d{6}$/',
            'personal' => '/^802\\d{6}$/',
            'uan' => '/^37\\d{7}$/',
            'emergency' => '/^112$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,9}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{9}$/',
            'premium' => '/^\\d{9}$/',
            'shared' => '/^\\d{9}$/',
            'personal' => '/^\\d{9}$/',
            'uan' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '291',
    'patterns' => array(
        'national' => array(
            'general' => '/^[178]\\d{6}$/',
            'fixed' => '/^1(?:1[12568]|20|40|55|6[146])\\d{4}|8\\d{6}$/',
            'mobile' => '/^17[1-3]\\d{4}|7\\d{6}$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,7}$/',
            'mobile' => '/^\\d{7}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '676',
    'patterns' => array(
        'national' => array(
            'general' => '/^[02-8]\\d{4,6}$/',
            'fixed' => '/^(?:2\\d|3[1-8]|4[1-4]|[56]0|7[0149]|8[05])\\d{3}$/',
            'mobile' => '/^(?:7[578]|8[7-9])\\d{5}$/',
            'tollfree' => '/^0800\\d{3}$/',
            'emergency' => '/^9(?:11|22|33|99)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5,7}$/',
            'fixed' => '/^\\d{5}$/',
            'mobile' => '/^\\d{7}$/',
            'tollfree' => '/^\\d{7}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '225',
    'patterns' => array(
        'national' => array(
            'general' => '/^[02-6]\\d{7}$/',
            'fixed' => '/^(?:2(?:0[023]|1[02357]|[23][045]|4[03-5])|3(?:0[06]|1[069]|[2-4][07]|5[09]|6[08]))\\d{5}$/',
            'mobile' => '/^(?:0[1-9]|4[0-24-9]|5[057-9]|6[05679])\\d{6}$/',
            'emergency' => '/^1(?:1[01]|[78]0)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '591',
    'patterns' => array(
        'national' => array(
            'general' => '/^[23467]\\d{7}$/',
            'fixed' => '/^(?:2(?:2\\d{2}|5(?:11|[258]\\d|9[67])|6(?:12|2\\d|9[34])|8(?:2[34]|39|62))|3(?:3\\d{2}|4(?:6\\d|8[24])|8(?:25|42|5[257]|86|9[25])|9(?:2\\d|3[234]|4[248]|5[24]|6[2-6]|7\\d))|4(?:4\\d{2}|6(?:11|[24689]\\d|72)))\\d{4}$/',
            'mobile' => '/^[67]\\d{7}$/',
            'emergency' => '/^11[089]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,8}$/',
            'fixed' => '/^\\d{7,8}$/',
            'mobile' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '234',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-69]\\d{5,8}|[78]\\d{5,13}$/',
            'fixed' => '/^[12]\\d{6,7}|9\\d{7}|(?:3\\d|4[023568]|5[02368]|6[02-469]|7[4-69]|8[2-9])\\d{6}|(?:4[47]|5[14579]|6[1578]|7[0-357])\\d{5,6}|(?:78|41)\\d{5}$/',
            'mobile' => '/^(?:1(?:7[34]\\d|8(?:04|[124579]\\d|8[0-3])|95\\d)|287[0-7]|3(?:18[1-8]|88[0-7]|9(?:8[5-9]|6[1-5]))|4(?:28[0-2]|6(?:7[1-9]|8[02-47])|88[0-2])|5(?:2(?:7[7-9]|8\\d)|38[1-79]|48[0-7]|68[4-7])|6(?:2(?:7[7-9]|8\\d)|4(?:3[7-9]|[68][129]|7[04-69]|9[1-8])|58[0-2]|98[7-9])|7(?:38[0-7]|69[1-8]|78[2-4])|8(?:28[3-9]|38[0-2]|4(?:2[12]|3[147-9]|5[346]|7[4-9]|8[014-689]|90)|58[1-8]|78[2-9]|88[5-7])|98[07]\\d)\\d{4}|(?:70(?:[3-9]\\d|2[1-9])|8(?:0[2-9]|1\\d)\\d)\\d{6}$/',
            'tollfree' => '/^800\\d{7,11}$/',
            'uan' => '/^700\\d{7,11}$/',
            'emergency' => '/^199$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5,14}$/',
            'fixed' => '/^\\d{5,9}$/',
            'mobile' => '/^\\d{8,10}$/',
            'tollfree' => '/^\\d{10,14}$/',
            'uan' => '/^\\d{10,14}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '254',
    'patterns' => array(
        'national' => array(
            'general' => '/^20\\d{6,7}|[4-9]\\d{6,9}$/',
            'fixed' => '/^20\\d{6,7}|4(?:[013]\\d{7}|[24-6]\\d{5,7})|5(?:[0-36-8]\\d{5,7}|[459]\\d{5})|6(?:[08]\\d{5}|[14-79]\\d{5,7}|2\\d{7})$/',
            'mobile' => '/^7(?:0[0-8]|[123]\\d|5[0-6]|7[0-5]|8[5-9])\\d{6}$/',
            'tollfree' => '/^800[24-8]\\d{5,6}$/',
            'premium' => '/^900[02-578]\\d{5}$/',
            'shortcode' => '/^1(?:0[09]|1(?:[06]|9[0-2579])|2[13]|3[01])$/',
            'emergency' => '/^112|999$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5,10}$/',
            'fixed' => '/^\\d{5,9}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{9,10}$/',
            'premium' => '/^\\d{9}$/',
            'shortcode' => '/^\\d{3,4}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '253',
    'patterns' => array(
        'national' => array(
            'general' => '/^[27]\\d{7}$/',
            'fixed' => '/^2(?:1[2-5]|7[45])\\d{5}$/',
            'mobile' => '/^77[6-8]\\d{5}$/',
            'emergency' => '/^1[78]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
            'emergency' => '/^\\d{2}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '590',
    'patterns' => array(
        'national' => array(
            'general' => '/^[56]\\d{8}$/',
            'fixed' => '/^590(?:2[7-9]|5[12]|87)\\d{4}$/',
            'mobile' => '/^690(?:10|2[27]|66|77|8[78])\\d{4}$/',
            'emergency' => '/^18$/',
        ),
        'possible' => array(
            'general' => '/^\\d{9}$/',
            'emergency' => '/^\\d{2}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '1',
    'patterns' => array(
        'national' => array(
            'general' => '/^[5689]\\d{9}$/',
            'fixed' => '/^664491\\d{4}$/',
            'mobile' => '/^66449[2-6]\\d{4}$/',
            'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\\d{6}$/',
            'premium' => '/^900[2-9]\\d{6}$/',
            'personal' => '/^5(?:00|33|44)[2-9]\\d{6}$/',
            'emergency' => '/^9(?:11|99)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}(?:\\d{3})?$/',
            'mobile' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'personal' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '1',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2589]\d{9}$/',
            'fixed' => '/^2644(?:6[12]|9[78])\d{4}$/',
            'mobile' => '/^264(?:235|476|5(?:3[6-9]|8[1-4])|7(?:29|72))\d{4}$/',
            'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\d{6}$/',
            'premium' => '/^900[2-9]\d{6}$/',
            'personal' => '/^5(?:00|33|44)[2-9]\d{6}$/',
            'emergency' => '/^911$/',
        ),
        'possible' => array(
            'general' => '/^\d{7}(?:\d{3})?$/',
            'mobile' => '/^\d{10}$/',
            'tollfree' => '/^\d{10}$/',
            'premium' => '/^\d{10}$/',
            'personal' => '/^\d{10}$/',
            'emergency' => '/^\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '1',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2589]\\d{9}$/',
            'fixed' => '/^284(?:(?:229|4(?:22|9[45])|774|8(?:52|6[459]))\\d{4}|496[0-5]\\d{3})$/',
            'mobile' => '/^284(?:(?:3(?:0[0-3]|4[0-367])|4(?:4[0-6]|68|99)|54[0-57])\\d{4}|496[6-9]\\d{3})$/',
            'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\\d{6}$/',
            'premium' => '/^900[2-9]\\d{6}$/',
            'personal' => '/^5(?:00|33|44)[2-9]\\d{6}$/',
            'emergency' => '/^9(?:11|99)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}(?:\\d{3})?$/',
            'mobile' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'personal' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '235',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2679]\\d{7}$/',
            'fixed' => '/^22(?:[3789]0|5[0-5]|6[89])\\d{4}$/',
            'mobile' => '/^(?:6[36]\\d|77\\d|9(?:5[0-4]|9\\d))\\d{5}$/',
            'emergency' => '/^1[78]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
            'emergency' => '/^\\d{2}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '1',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2589]\\d{9}$/',
            'fixed' => '/^246[2-9]\\d{6}$/',
            'mobile' => '/^246(?:(?:2[346]|45|82)\\d|25[0-4])\\d{4}$/',
            'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\\d{6}$/',
            'premium' => '/^900[2-9]\\d{6}$/',
            'personal' => '/^5(?:00|33|44)[2-9]\\d{6}$/',
            'emergency' => '/^[235]11$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}(?:\\d{3})?$/',
            'mobile' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'personal' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '963',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-59]\\d{7,8}$/',
            'fixed' => '/^(?:1(?:1\\d?|4\\d|[2356])|2[1-35]|3(?:[13]\\d|4)|4[13]|5[1-3])\\d{6}$/',
            'mobile' => '/^9(?:22|[35][0-8]|4\\d|6[024-9]|88|9[0-489])\\d{6}$/',
            'emergency' => '/^11[023]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,9}$/',
            'mobile' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '1',
    'patterns' => array(
        'national' => array(
            'general' => '/^[589]\\d{9}$/',
            'fixed' => '/^868(?:2(?:01|2[1-5])|6(?:07|1[4-6]|2[1-9]|[3-6]\\d|7[0-79]|9[0-8])|82[12])\\d{4}$/',
            'mobile' => '/^868(?:29\\d|3(?:0[1-9]|1[02-9]|[2-9]\\d)|4(?:[679]\\d|8[0-4])|6(?:20|78|8\\d)|7(?:03|1[02-9]|[2-9]\\d))\\d{4}$/',
            'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\\d{6}$/',
            'premium' => '/^900[2-9]\\d{6}$/',
            'personal' => '/^5(?:00|33|44)[2-9]\\d{6}$/',
            'emergency' => '/^99[09]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}(?:\\d{3})?$/',
            'mobile' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'personal' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '243',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-6]\\d{6}|8\\d{6,8}|9\\d{8}$/',
            'fixed' => '/^[1-6]\\d{6}$/',
            'mobile' => '/^8(?:[0-259]\\d{2}|[48])\\d{5}|9[7-9]\\d{7}$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,9}$/',
            'fixed' => '/^\\d{7}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '996',
    'patterns' => array(
        'national' => array(
            'general' => '/^[35-8]\\d{8,9}$/',
            'fixed' => '/^(?:3(?:1(?:2\\d|3[1-9]|47|5[02]|6[1-8])|2(?:22|3[0-479]|6[0-7])|4(?:22|5[6-9]|6[0-4])|5(?:22|3[4-7]|59|6[0-5])|6(?:22|5[35-7]|6[0-3])|7(?:22|3[468]|4[1-9]|59|6\\d|7[5-7])|9(?:22|4[1-8]|6[0-8]))|6(?:09|12|2[2-4])\\d)\\d{5}$/',
            'mobile' => '/^5[124-7]\\d{7}|7(?:0[0-357-9]|7\\d)\\d{6}$/',
            'tollfree' => '/^800\\d{6,7}$/',
            'emergency' => '/^10[123]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5,10}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{9,10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '590',
    'patterns' => array(
        'national' => array(
            'general' => '/^[56]\\d{8}$/',
            'fixed' => '/^590(?:1[12]|2[0-68]|3[28]|4[126-8]|5[067]|6[018]|[89]\\d)\\d{4}$/',
            'mobile' => '/^690(?:00|1[1-9]|2[013-5]|[3-5]\\d|6[0-57-9]|7[1-6]|8[0-6]|9[09])\\d{4}$/',
            'emergency' => '/^1[578]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{9}$/',
            'emergency' => '/^\\d{2}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '90',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-589]\\d{9}|444\\d{4}$/',
            'fixed' => '/^(?:2(?:[13][26]|[28][2468]|[45][268]|[67][246])|3(?:[13][28]|[24-6][2468]|[78][02468]|92)|4(?:[16][246]|[23578][2468]|4[26]))\\d{7}$/',
            'mobile' => '/^5(?:0[1-7]|22|[34]\\d|5[1-59]|9[246])\\d{7}$/',
            'pager' => '/^512\\d{7}$/',
            'tollfree' => '/^800\\d{7}$/',
            'premium' => '/^900\\d{7}$/',
            'uan' => '/^444\\d{4}|850\\d{7}$/',
            'emergency' => '/^1(?:1[02]|55)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,10}$/',
            'fixed' => '/^\\d{10}$/',
            'mobile' => '/^\\d{10}$/',
            'pager' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'uan' => '/^\\d{7,10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '385',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-7]\\d{5,8}|[89]\\d{6,11}$/',
            'fixed' => '/^1\\d{7}|(?:2[0-3]|3[1-5]|4[02-47-9]|5[1-3])\\d{6}$/',
            'uan' => '/^62\\d{6,7}$/',
            'mobile' => '/^9[1257-9]\\d{6,10}$/',
            'tollfree' => '/^80[01]\\d{4,7}$/',
            'premium' => '/^6(?:[09]\\d{7}|[145]\\d{4,7})$/',
            'personal' => '/^7[45]\\d{4,7}$/',
            'emergency' => '/^1(?:12|92)|9[34]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,12}$/',
            'fixed' => '/^\\d{6,8}$/',
            'uan' => '/^\\d{8,9}$/',
            'mobile' => '/^\\d{8,12}$/',
            'tollfree' => '/^\\d{7,10}$/',
            'premium' => '/^\\d{6,9}$/',
            'personal' => '/^\\d{6,9}$/',
            'emergency' => '/^\\d{2,3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '233',
    'patterns' => array(
        'national' => array(
            'general' => '/^[235]\\d{8}|8\\d{7}$/',
            'fixed' => '/^3(?:0[237]\\d|[167](?:2[0-6]|7\\d)|2(?:2[0-5]|7\\d)|3(?:2[0-3]|7\\d)|4(?:2[013-9]|3[01]|7\\d)|5(?:2[0-7]|7\\d)|8(?:2[0-2]|7\\d)|9(?:20|7\\d))\\d{5}$/',
            'mobile' => '/^(?:2[034678]|5[047])\\d{7}$/',
            'tollfree' => '/^800\\d{5}$/',
            'emergency' => '/^19[123]|999$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,9}$/',
            'fixed' => '/^\\d{7,9}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '250',
    'patterns' => array(
        'national' => array(
            'general' => '/^[027-9]\\d{7,8}$/',
            'fixed' => '/^2[258]\\d{7}|06\\d{6}$/',
            'mobile' => '/^7[238]\\d{7}$/',
            'tollfree' => '/^800\\d{6}$/',
            'premium' => '/^900\\d{6}$/',
            'emergency' => '/^112$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8,9}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{9}$/',
            'premium' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '692',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-6]\\d{6}$/',
            'fixed' => '/^(?:247|528|625)\\d{4}$/',
            'mobile' => '/^(?:235|329|45[56]|545)\\d{4}$/',
            'voip' => '/^635\\d{4}$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '977',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-8]\\d{7}|9(?:[1-69]\\d{6}|7[2-6]\\d{5,7}|8\\d{8})$/',
            'fixed' => '/^(?:1[0124-6]|2[13-79]|3[135-8]|4[146-9]|5[135-7]|6[13-9]|7[15-9]|8[1-46-9]|9[1-79])\\d{6}$/',
            'mobile' => '/^9(?:7[45]|8[0145])\\d{7}$/',
            'emergency' => '/^1(?:0[0-3]|12)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,10}$/',
            'fixed' => '/^\\d{6,8}$/',
            'mobile' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '673',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-578]\\d{6}$/',
            'fixed' => '/^[2-5]\\d{6}$/',
            'mobile' => '/^[78]\\d{6}$/',
            'emergency' => '/^99[135]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '290',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-9]\\d{3}$/',
            'fixed' => '/^(?:[2-468]\\d|7[01])\\d{2}$/',
            'premium' => '/^(?:[59]\\d|7[2-9])\\d{2}$/',
            'shortcode' => '/^1\\d{2,3}$/',
            'emergency' => '/^9(?:11|99)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{4}$/',
            'shortcode' => '/^\\d{3,4}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '353',
    'patterns' => array(
        'national' => array(
            'general' => '/^[124-9]\\d{6,9}$/',
            'fixed' => '/^1\\d{7,8}|2(?:1\\d{6,7}|3\\d{7}|[24-9]\\d{5})|4(?:0[24]\\d{5}|[1-469]\\d{7}|5\\d{6}|7\\d{5}|8[0-46-9]\\d{7})|5(?:0[45]\\d{5}|1\\d{6}|[23679]\\d{7}|8\\d{5})|6(?:1\\d{6}|[237-9]\\d{5}|[4-6]\\d{7})|7[14]\\d{7}|9(?:1\\d{6}|[04]\\d{7}|[35-9]\\d{5})$/',
            'mobile' => '/^8(?:22\\d{6}|[35-9]\\d{7})$/',
            'tollfree' => '/^1800\\d{6}$/',
            'premium' => '/^15(?:1[2-8]|[2-8]0|9[089])\\d{6}$/',
            'shared' => '/^18[59]0\\d{6}$/',
            'personal' => '/^700\\d{6}$/',
            'voip' => '/^76\\d{7}$/',
            'uan' => '/^818\\d{6}$/',
            'voicemail' => '/^8[35-9]\\d{8}$/',
            'emergency' => '/^112|999$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5,10}$/',
            'fixed' => '/^\\d{5,10}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'shared' => '/^\\d{10}$/',
            'personal' => '/^\\d{9}$/',
            'voip' => '/^\\d{9}$/',
            'uan' => '/^\\d{9}$/',
            'voicemail' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '251',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-59]\\d{8}$/',
            'fixed' => '/^(?:11(?:1(?:1[124]|2[2-57]|3[1-5]|5[5-8]|8[6-8])|2(?:13|3[6-8]|5[89]|7[05-9]|8[2-6])|3(?:2[01]|3[0-289]|4[1289]|7[1-4]|87)|4(?:1[69]|3[2-49]|4[0-3]|6[5-8])|5(?:1[57]|44|5[0-4])|6(?:18|2[69]|4[5-7]|5[1-5]|6[0-59]|8[015-8]))|2(?:2(?:11[1-9]|22[0-7]|33\\d|44[1467]|66[1-68])|5(?:11[124-6]|33[2-8]|44[1467]|55[14]|66[1-3679]|77[124-79]|880))|3(?:3(?:11[0-46-8]|22[0-6]|33[0134689]|44[04]|55[0-6]|66[01467])|4(?:44[0-8]|55[0-69]|66[0-3]|77[1-5]))|4(?:6(?:22[0-24-7]|33[1-5]|44[13-69]|55[14-689]|660|88[1-4])|7(?:11[1-9]|22[1-9]|33[13-7]|44[13-6]|55[1-689]))|5(?:7(?:227|55[05]|(?:66|77)[14-8])|8(?:11[149]|22[013-79]|33[0-68]|44[013-8]|550|66[1-5]|77\\d)))\\d{4}$/',
            'mobile' => '/^9(?:[1-3]\\d|5[89])\\d{6}$/',
            'emergency' => '/^9(?:11?|[23]|9[17])$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,9}$/',
            'mobile' => '/^\\d{9}$/',
            'emergency' => '/^\\d{2,3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '506',
    'patterns' => array(
        'national' => array(
            'general' => '/^[24-9]\\d{7,9}$/',
            'fixed' => '/^2[24-7]\\d{6}$/',
            'mobile' => '/^5(?:0[0-4]|7[01])\\d{5}|[67][0-2]\\d{6}|8[3-9]\\d{6}$/',
            'tollfree' => '/^800\\d{7}$/',
            'premium' => '/^90[059]\\d{7}$/',
            'voip' => '/^210[0-6]\\d{4}|4(?:0(?:[04]0\\d{4}|10[0-3]\\d{3}|2(?:00\\d|900)\\d{2}|3[01]\\d{4}|5\\d{5}|70[01]\\d{3})|1[01]\\d{5}|400\\d{4})|5100\\d{4}$/',
            'shortcode' => '/^1(?:0(?:00|15|2[2-4679])|1(?:1[0-35-9]|37|[46]6|75|8[79]|9[0-379])|2(?:00|[12]2|34|55)|333|400|5(?:15|5[15])|693|7(?:00|1[789]|2[02]|[67]7))$/',
            'emergency' => '/^112|911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8,10}$/',
            'fixed' => '/^\\d{8}$/',
            'mobile' => '/^\\d{8}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'voip' => '/^\\d{8}$/',
            'shortcode' => '/^\\d{4}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '52',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-9]\\d{9,10}$/',
            'fixed' => '/^(?:33|55|81)\\d{8}|(?:2(?:2[2-9]|3[1-35-8]|4[13-9]|7[1-689]|8[1-578]|9[467])|3(?:1[1-79]|[2458][1-9]|7[1-8]|9[1-5])|4(?:1[1-57-9]|[24-6][1-9]|[37][1-8]|8[1-35-9]|9[2-689])|5(?:88|9[1-79])|6(?:1[2-68]|[234][1-9]|5[1-3689]|6[12457-9]|7[1-7]|8[67]|9[4-8])|7(?:[13467][1-9]|2[1-8]|5[13-9]|8[1-69]|9[17])|8(?:2[13-689]|3[1-6]|4[124-6]|6[1246-9]|7[1-378]|9[12479])|9(?:1[346-9]|2[1-4]|3[2-46-8]|5[1348]|[69][1-9]|7[12]|8[1-8]))\\d{7}$/',
            'mobile' => '/^1(?:(?:33|55|81)\\d{8}|(?:2(?:2[2-9]|3[1-35-8]|4[13-9]|7[1-689]|8[1-578]|9[467])|3(?:1[1-79]|[2458][1-9]|7[1-8]|9[1-5])|4(?:1[1-57-9]|[24-6][1-9]|[37][1-8]|8[1-35-9]|9[2-689])|5(?:88|9[1-79])|6(?:1[2-68]|[2-4][1-9]|5[1-3689]|6[12457-9]|7[1-7]|8[67]|9[4-8])|7(?:[13467][1-9]|2[1-8]|5[13-9]|8[1-69]|9[17])|8(?:2[13-689]|3[1-6]|4[124-6]|6[1246-9]|7[1-378]|9[12479])|9(?:1[346-9]|2[1-4]|3[2-46-8]|5[1348]|[69][1-9]|7[12]|8[1-8]))\\d{7})$/',
            'tollfree' => '/^800\\d{7}$/',
            'premium' => '/^900\\d{7}$/',
            'emergency' => '/^06[568]|911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,11}$/',
            'fixed' => '/^\\d{7,10}$/',
            'mobile' => '/^\\d{11}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '359',
    'patterns' => array(
        'national' => array(
            'general' => '/^[23567]\\d{5,7}|[489]\\d{6,8}$/',
            'fixed' => '/^2(?:[0-8]\\d{5,6}|9\\d{4,6})|(?:[36]\\d|5[1-9]|8[1-6]|9[1-7])\\d{5,6}|(?:4(?:[124-7]\\d|3[1-6])|7(?:0[1-9]|[1-9]\\d))\\d{4,5}$/',
            'mobile' => '/^(?:8[7-9]|98)\\d{7}|4(?:3[0789]|8\\d)\\d{5}$/',
            'tollfree' => '/^800\\d{5}$/',
            'premium' => '/^90\\d{6}$/',
            'personal' => '/^700\\d{5}$/',
            'emergency' => '/^1(?:12|50|6[06])$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5,9}$/',
            'fixed' => '/^\\d{5,8}$/',
            'mobile' => '/^\\d{8,9}$/',
            'tollfree' => '/^\\d{8}$/',
            'premium' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '224',
    'patterns' => array(
        'national' => array(
            'general' => '/^[23567]\\d{7,8}$/',
            'fixed' => '/^30(?:24|3[12]|4[1-35-7]|5[13]|6[189]|[78]1|9[1478])\\d{4}$/',
            'mobile' => '/^(?:24|55)\\d{6}|6(?:0(?:2[0-35-9]|3[3467]|5[2457-9])|1[0-5]\\d|2\\d{2,3}|[4-9]\\d{2}|3(?:[14]0|35))\\d{4}$/',
            'voip' => '/^78\\d{6}$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8,9}$/',
            'fixed' => '/^\\d{8}$/',
            'voip' => '/^\\d{8}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '687',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-47-9]\\d{5}$/',
            'fixed' => '/^(?:2[03-9]|3[0-5]|4[1-7]|88)\\d{4}$/',
            'mobile' => '/^(?:[79]\\d|8[0-79])\\d{4}$/',
            'premium' => '/^36\\d{4}$/',
            'shortcode' => '/^10(?:0[06]|1[02-46]|20|3[0125]|42|5[058]|77)$/',
            'emergency' => '/^1[5-8]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6}$/',
            'shortcode' => '/^\\d{4}$/',
            'emergency' => '/^\\d{2}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '84',
    'patterns' => array(
        'national' => array(
            'general' => '/^[17]\\d{6,9}|[2-69]\\d{7,9}|8\\d{6,8}$/',
            'fixed' => '/^(?:2(?:[025-79]|1[0189]|[348][01])|3(?:[0136-9]|[25][01])|4\\d|5(?:[01][01]|[2-9])|6(?:[0-46-8]|5[01])|7(?:[02-79]|[18][01])|8[1-9])\\d{7}$/',
            'mobile' => '/^(?:9\\d|1(?:2\\d|6[2-9]|8[68]|99))\\d{7}$/',
            'tollfree' => '/^1800\\d{4,6}$/',
            'premium' => '/^1900\\d{4,6}$/',
            'uan' => '/^[17]99\\d{4}|69\\d{5,6}|80\\d{5}$/',
            'emergency' => '/^11[345]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,10}$/',
            'fixed' => '/^\\d{9,10}$/',
            'mobile' => '/^\\d{9,10}$/',
            'tollfree' => '/^\\d{8,10}$/',
            'premium' => '/^\\d{8,10}$/',
            'uan' => '/^\\d{7,8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '421',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-689]\\d{8}$/',
            'fixed' => '/^[2-5]\\d{8}$/',
            'mobile' => '/^9(?:0[1-8]|1[0-24-9]|4[0489])\\d{6}$/',
            'tollfree' => '/^800\\d{6}$/',
            'premium' => '/^9(?:[78]\\d{7}|00\\d{6})$/',
            'shared' => '/^8[5-9]\\d{7}$/',
            'voip' => '/^6(?:5[0-4]|9[0-6])\\d{6}$/',
            'uan' => '/^96\\d{7}$/',
            'emergency' => '/^1(?:12|5[058])$/',
        ),
        'possible' => array(
            'general' => '/^\\d{9}$/',
            'uan' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '47',
    'patterns' => array(
        'national' => array(
            'general' => '/^0\\d{4}|[4789]\\d{7}$/',
            'fixed' => '/^79\\d{6}$/',
            'mobile' => '/^(?:4[015-8]|5[89]|9\\d)\\d{6}$/',
            'tollfree' => '/^80[01]\\d{5}$/',
            'premium' => '/^82[09]\\d{5}$/',
            'shared' => '/^810(?:0[0-6]|[2-8]\\d)\\d{3}$/',
            'personal' => '/^880\\d{5}$/',
            'voip' => '/^85[0-5]\\d{5}$/',
            'uan' => '/^0\\d{4}|81(?:0(?:0[7-9]|1\\d)|5\\d{2})\\d{3}$/',
            'voicemail' => '/^81[23]\\d{5}$/',
            'emergency' => '/^11[023]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5}(?:\\d{3})?$/',
            'fixed' => '/^\\d{8}$/',
            'mobile' => '/^\\d{8}$/',
            'tollfree' => '/^\\d{8}$/',
            'premium' => '/^\\d{8}$/',
            'shared' => '/^\\d{8}$/',
            'personal' => '/^\\d{8}$/',
            'voip' => '/^\\d{8}$/',
            'voicemail' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '64',
    'patterns' => array(
        'national' => array(
            'general' => '/^6[235-9]\\d{6}|[2-57-9]\\d{7,10}$/',
            'fixed' => '/^(?:3[2-79]|[49][2-689]|6[235-9]|7[2-589])\\d{6}|24099\\d{3}$/',
            'mobile' => '/^2(?:[028]\\d{7,8}|1(?:0\\d{5,7}|[12]\\d{5,6}|[3-9]\\d{5})|[79]\\d{7})$/',
            'pager' => '/^[28]6\\d{6,7}$/',
            'tollfree' => '/^508\\d{6,7}|80\\d{6,8}$/',
            'premium' => '/^90\\d{7,9}$/',
            'emergency' => '/^111$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,11}$/',
            'fixed' => '/^\\d{7,8}$/',
            'mobile' => '/^\\d{8,10}$/',
            'pager' => '/^\\d{8,9}$/',
            'tollfree' => '/^\\d{8,10}$/',
            'premium' => '/^\\d{9,11}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '682',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-57]\\d{4}$/',
            'fixed' => '/^(?:2\\d|3[13-7]|4[1-5])\\d{3}$/',
            'mobile' => '/^(?:5[0-68]|7\\d)\\d{3}$/',
            'emergency' => '/^99[689]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '258',
    'patterns' => array(
        'national' => array(
            'general' => '/^[28]\\d{7,8}$/',
            'fixed' => '/^2(?:[1346]\\d|5[0-2]|[78][12]|93)\\d{5}$/',
            'mobile' => '/^8[246]\\d{7}$/',
            'tollfree' => '/^800\\d{6}$/',
            'shortcode' => '/^1[0234]\\d$/',
            'emergency' => '/^1(?:1[79]|9[78])$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8,9}$/',
            'fixed' => '/^\\d{8}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{9}$/',
            'shortcode' => '/^\\d{3}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '246',
    'patterns' => array(
        'national' => array(
            'general' => '/^3\\d{6}$/',
            'fixed' => '/^37\\d{5}$/',
            'mobile' => '/^38\\d{5}$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '504',
    'patterns' => array(
        'national' => array(
            'general' => '/^[237-9]\\d{7}$/',
            'fixed' => '/^2(?:2(?:0[019]|1[1-36]|[23]\\d|4[056]|5[57]|8[0146-9]|9[012])|4(?:2|3-59]|3[13-689]|4[0-68]|5[1-35])|5(?:4[3-5]|5\\d|6[56]|74)|6(?:4[0-378]|[56]\\d|[78][0-8]|9[01])|7(?:6[46-9]|7[02-9]|8[34])|8(?:79|8[0-35789]|9[1-57-9]))\\d{4}$/',
            'mobile' => '/^[37-9]\\d{7}$/',
            'emergency' => '/^199$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '382',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-9]\\d{7,8}$/',
            'fixed' => '/^(?:20[2-8]|3(?:0[2-7]|1[35-7]|2[3567]|3[4-7])|4(?:0[237]|1[27])|5(?:0[47]|1[27]|2[378]))\\d{5}$/',
            'mobile' => '/^6(?:32\\d|[89]\\d{2}|7(?:[0-8]\\d|9(?:[3-9]|[0-2]\\d)))\\d{4}$/',
            'tollfree' => '/^800[28]\\d{4}$/',
            'premium' => '/^(?:88\\d|9(?:4[13-8]|5[16-8]))\\d{5}$/',
            'voip' => '/^78[1-9]\\d{5}$/',
            'uan' => '/^77\\d{6}$/',
            'shortcode' => '/^1(?:16\\d{3}|2(?:[015-9]|\\d{2})|[0135]\\d{2}|4\\d{2,3}|9\\d{3})$/',
            'emergency' => '/^1(?:12|2[234])$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,9}$/',
            'fixed' => '/^\\d{6,8}$/',
            'mobile' => '/^\\d{8,9}$/',
            'tollfree' => '/^\\d{8}$/',
            'premium' => '/^\\d{8}$/',
            'voip' => '/^\\d{8}$/',
            'uan' => '/^\\d{8}$/',
            'shortcode' => '/^\\d{3,6}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '7',
    'patterns' => array(
        'national' => array(
            'general' => '/^[3489]\\d{9}$/',
            'fixed' => '/^(?:3(?:0[12]|4[1-35-79]|5[1-3]|8[1-58]|9[0145])|4(?:01|1[1356]|2[13467]|7[1-5]|8[1-7]|9[1-689])|8(?:1[1-8]|2[01]|3[13-6]|4[0-8]|5[15]|6[1-35-7]|7[1-37-9]))\\d{7}$/',
            'mobile' => '/^9\\d{9}$/',
            'tollfree' => '/^80[04]\\d{7}$/',
            'premium' => '/^80[39]\\d{7}$/',
            'emergency' => '/^0[123]|112$/',
        ),
        'possible' => array(
            'general' => '/^\\d{10}$/',
            'emergency' => '/^\\d{2,3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '961',
    'patterns' => array(
        'national' => array(
            'general' => '/^[13-9]\\d{6,7}$/',
            'fixed' => '/^(?:[14-6]\\d{2}|7(?:[2-579]\\d|62|8[0-7])|[89][2-9]\\d)\\d{4}$/',
            'mobile' => '/^(?:3\\d|7(?:[01]\\d|6[013-9]|8[89]|91))\\d{5}$/',
            'premium' => '/^9[01]\\d{6}$/',
            'shared' => '/^8[01]\\d{6}$/',
            'emergency' => '/^1(?:12|40|75)|999$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,8}$/',
            'fixed' => '/^\\d{7}$/',
            'mobile' => '/^\\d{7,8}$/',
            'premium' => '/^\\d{8}$/',
            'shared' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '1',
    'patterns' => array(
        'national' => array(
            'general' => '/^[5689]\\d{9}$/',
            'fixed' => '/^670(?:2(?:3[3-7]|56|8[5-8])|32[1238]|4(?:33|8[348])|5(?:32|55|88)|6(?:64|70|82)|78[589]|8[3-9]8|989)\\d{4}$/',
            'mobile' => '/^670(?:2(?:3[3-7]|56|8[5-8])|32[1238]|4(?:33|8[348])|5(?:32|55|88)|6(?:64|70|82)|78[589]|8[3-9]8|989)\\d{4}$/',
            'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\\d{6}$/',
            'premium' => '/^900[2-9]\\d{6}$/',
            'personal' => '/^5(?:00|33|44)[2-9]\\d{6}$/',
            'emergency' => '/^911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}(?:\\d{3})?$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'personal' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '850',
    'patterns' => array(
        'national' => array(
            'general' => '/^1\\d{9}|[28]\\d{7}$/',
            'fixed' => '/^2\\d{7}|85\\d{6}$/',
            'mobile' => '/^19[123]\\d{7}$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,8}|\\d{10}$/',
            'fixed' => '/^\\d{6,8}$/',
            'mobile' => '/^\\d{10}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '48',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-58]\\d{6,8}|9\\d{8}|[67]\\d{5,8}$/',
            'fixed' => '/^(?:1[2-8]|2[2-59]|3[2-4]|4[1-468]|5[24-689]|6[1-3578]|7[14-6]|8[1-7])\\d{5,7}|77\\d{4,7}|(?:89|9[145])\\d{7}$/',
            'mobile' => '/^(?:5[013]|6[069]|7[2389]|88)\\d{7}$/',
            'pager' => '/^642\\d{3,6}$/',
            'tollfree' => '/^800\\d{6}$/',
            'premium' => '/^70\\d{7}$/',
            'shared' => '/^801\\d{6}$/',
            'voip' => '/^39\\d{7}$/',
            'emergency' => '/^112|99[789]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,9}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{9}$/',
            'premium' => '/^\\d{9}$/',
            'shared' => '/^\\d{9}$/',
            'voip' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '34',
    'patterns' => array(
        'national' => array(
            'general' => '/^[5-9]\\d{8}$/',
            'fixed' => '/^8(?:[13]0|[28][0-8]|[47][1-9]|5[01346-9]|6[0457-9])\\d{6}|9(?:[1238][0-8]\\d{6}|4[1-9]\\d{6}|5\\d{7}|6(?:[0-8]\\d{6}|9(?:0(?:[0-57-9]\\d{4}|6(?:0[0-8]|1[1-9]|[2-9]\\d)\\d{2})|[1-9]\\d{5}))|7(?:[124-9]\\d{2}|3(?:[0-8]\\d|9[1-9]))\\d{4})$/',
            'mobile' => '/^(?:6\\d{6}|7[1-4]\\d{5}|9(?:6906(?:09|10)|7390\\d{2}))\\d{2}$/',
            'tollfree' => '/^[89]00\\d{6}$/',
            'premium' => '/^80[367]\\d{6}$/',
            'shared' => '/^90[12]\\d{6}$/',
            'personal' => '/^70\\d{7}$/',
            'uan' => '/^51\\d{7}$/',
            'emergency' => '/^0(?:[69][12]|8[05])|112$/',
        ),
        'possible' => array(
            'general' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '503',
    'patterns' => array(
        'national' => array(
            'general' => '/^[267]\\d{7}|[89]\\d{6}(?:\\d{4})?$/',
            'fixed' => '/^2[1-6]\\d{6}$/',
            'mobile' => '/^[67]\\d{7}$/',
            'tollfree' => '/^800\\d{4}(?:\\d{4})?$/',
            'premium' => '/^900\\d{4}(?:\\d{4})?$/',
            'emergency' => '/^911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,8}|\\d{11}$/',
            'fixed' => '/^\\d{8}$/',
            'mobile' => '/^\\d{8}$/',
            'tollfree' => '/^\\d{7}(?:\\d{4})?$/',
            'premium' => '/^\\d{7}(?:\\d{4})?$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '681',
    'patterns' => array(
        'national' => array(
            'general' => '/^[5-7]\\d{5}$/',
            'fixed' => '/^(?:50|68|72)\\d{4}$/',
            'mobile' => '/^(?:50|68|72)\\d{4}$/',
            'emergency' => '/^1[578]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6}$/',
            'emergency' => '/^\\d{2}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '358',
    'patterns' => array(
        'national' => array(
            'general' => '/^[135]\\d{5,9}|[27]\\d{4,9}|4\\d{5,10}|6\\d{7,8}|8\\d{6,9}$/',
            'fixed' => '/^18[1-8]\\d{3,9}$/',
            'mobile' => '/^4\\d{5,10}|50\\d{4,8}$/',
            'tollfree' => '/^800\\d{4,7}$/',
            'premium' => '/^[67]00\\d{5,6}$/',
            'uan' => '/^[13]0\\d{4,8}|2(?:0(?:[016-8]\\d{3,7}|[2-59]\\d{2,7})|9\\d{4,8})|60(?:[12]\\d{5,6}|6\\d{7})|7(?:1\\d{7}|3\\d{8}|5[03-9]\\d{2,7})$/',
            'emergency' => '/^112$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5,12}$/',
            'fixed' => '/^\\d{6,12}$/',
            'mobile' => '/^\\d{6,11}$/',
            'tollfree' => '/^\\d{7,10}$/',
            'premium' => '/^\\d{8,9}$/',
            'uan' => '/^\\d{5,10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '61',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1458]\\d{5,9}$/',
            'fixed' => '/^89164\\d{4}$/',
            'mobile' => '/^4(?:[0-2]\\d|3[0-57-9]|4[47-9]|5[0-37-9]|6[6-9]|7[07-9]|8[7-9])\\d{6}$/',
            'tollfree' => '/^1(?:80(?:0\\d{2})?|3(?:00\\d{2})?)\\d{4}$/',
            'premium' => '/^190[0126]\\d{6}$/',
            'personal' => '/^500\\d{6}$/',
            'voip' => '/^550\\d{6}$/',
            'emergency' => '/^000|112$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,10}$/',
            'fixed' => '/^\\d{8,9}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{6,10}$/',
            'premium' => '/^\\d{10}$/',
            'personal' => '/^\\d{9}$/',
            'voip' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '82',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-7]\\d{3,9}|8\\d{8}$/',
            'fixed' => '/^(?:2|[34][1-3]|5[1-5]|6[1-4])(?:1\\d{2,3}|[2-9]\\d{6,7})$/',
            'mobile' => '/^1[0-25-9]\\d{7,8}$/',
            'tollfree' => '/^80\\d{7}$/',
            'premium' => '/^60[2-9]\\d{6}$/',
            'personal' => '/^50\\d{8}$/',
            'voip' => '/^70\\d{8}$/',
            'uan' => '/^1(?:5(?:44|66|77|88|99)|6(?:00|44|6[16]|70|88))\\d{4}$/',
            'emergency' => '/^11[29]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{4,10}$/',
            'fixed' => '/^\\d{4,10}$/',
            'mobile' => '/^\\d{9,10}$/',
            'tollfree' => '/^\\d{9}$/',
            'premium' => '/^\\d{9}$/',
            'personal' => '/^\\d{10}$/',
            'voip' => '/^\\d{10}$/',
            'uan' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '230',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-9]\\d{6}$/',
            'fixed' => '/^(?:2(?:[034789]\\d|1[0-7]|6[1-69])|4(?:[013-8]\\d|2[4-7])|[56]\\d{2}|8(?:14|3[129]))\\d{4}$/',
            'mobile' => '/^(?:25\\d|4(?:2[12389]|9\\d)|7\\d{2}|8(?:20|7[15-8])|9[1-8]\\d)\\d{4}$/',
            'pager' => '/^2(?:1[89]|2\\d)\\d{4}$/',
            'tollfree' => '/^80[012]\\d{4}$/',
            'premium' => '/^30\\d{5}$/',
            'voip' => '/^3(?:20|9\\d)\\d{4}$/',
            'shortcode' => '/^1(?:1[0-36-9]|[02-9]\\d|\\d{3,4})|8\\d{3}$/',
            'emergency' => '/^11[45]|99\\d$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}$/',
            'shortcode' => '/^\\d{3,5}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '1',
    'patterns' => array(
        'national' => array(
            'general' => '/^[4589]\\d{9}$/',
            'fixed' => '/^473(?:2(?:3[0-2]|69)|3(?:2[89]|86)|4(?:[06]8|3[5-9]|4[0-49]|5[5-79]|68|73|90)|63[68]|7(?:58|84)|938)\\d{4}$/',
            'mobile' => '/^473(?:4(?:0[3-79]|1[04-9]|20|58)|53[3-8])\\d{4}$/',
            'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\\d{6}$/',
            'premium' => '/^900[2-9]\\d{6}$/',
            'personal' => '/^5(?:00|33|44)[2-9]\\d{6}$/',
            'emergency' => '/^911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}(?:\\d{3})?$/',
            'mobile' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'personal' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '962',
    'patterns' => array(
        'national' => array(
            'general' => '/^[235-9]\\d{7,8}$/',
            'fixed' => '/^(?:2(?:6(?:2[0-35-9]|3[0-57-8]|4[24-7]|5[0-24-8]|[6-9][02])|7(?:0[1-79]|10|2[014-7]|3[0-689]|4[019]|5[0-3578]))|32(?:0[1-69]|1[1-35-7]|2[024-7]|3\\d|[457][02]|60)|53(?:[013][02]|2[0-59]|49|5[0-35-9]|6[15]|7[45]|8[1-6]|9[0-36-9])|6(?:2[50]0|300|4(?:0[0125]|1[2-7]|2[0569]|[38][07-9]|4[025689]|6[0-589]|7\\d|9[0-2])|5(?:[01][056]|2[034]|3[0-57-9]|4[17-8]|5[0-69]|6[0-35-9]|7[1-379]|8[0-68]|9[02-39]))|87(?:[02]0|7[08]|9[09]))\\d{4}$/',
            'mobile' => '/^7(?:55|7[25-9]|8[5-9]|9[05-9])\\d{6}$/',
            'pager' => '/^74(?:66|77)\\d{5}$/',
            'tollfree' => '/^80\\d{6}$/',
            'premium' => '/^900\\d{5}$/',
            'shared' => '/^85\\d{6}$/',
            'personal' => '/^70\\d{7}$/',
            'uan' => '/^8(?:10|8\\d)\\d{5}$/',
            'shortcode' => '/^1(?:09|1[01]|9[024-79])$/',
            'emergency' => '/^1(?:12|91)|911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,9}$/',
            'fixed' => '/^\\d{7,8}$/',
            'mobile' => '/^\\d{9}$/',
            'pager' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{8}$/',
            'premium' => '/^\\d{8}$/',
            'shared' => '/^\\d{8}$/',
            'personal' => '/^\\d{9}$/',
            'uan' => '/^\\d{8}$/',
            'shortcode' => '/^\\d{3}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '86',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-7]\\d{7,11}|8[0-357-9]\\d{6,9}|9(?:5\\d{3}|\\d{9})$/',
            'fixed' => '/^21\\d{8,10}|(?:10|2[02-57-9]|3(?:11|7[179])|4(?:[15]1|3[12])|5(?:1\\d|2[37]|3[12]|51|7[13-79]|9[15])|7(?:31|5[457]|6[09]|91)|898)\\d{8}|(?:3(?:1[02-9]|35|49|5\\d|7[02-68]|9[1-68])|4(?:1[02-9]|2[179]|3[3-9]|5[2-9]|6[4789]|7\\d|8[23])|5(?:3[03-9]|4[36]|5[02-9]|6[1-46]|7[028]|80|9[2-46-9])|6(?:3[1-5]|6[0238]|9[12])|7(?:01|[17]\\d|2[248]|3[04-9]|4[3-6]|5[0-3689]|6[2368]|9[02-9])|8(?:1[236-8]|2[5-7]|[37]\\d|5[1-9]|8[3678]|9[1-7])|9(?:0[1-3689]|1[1-79]|[379]\\d|4[13]|5[1-5]))\\d{7}|80(?:29|6[03578]|7[018]|81)\\d{4}$/',
            'mobile' => '/^1(?:3\\d|4[57]|[58][0-35-9])\\d{8}$/',
            'tollfree' => '/^(?:10)?800\\d{7}$/',
            'premium' => '/^16[08]\\d{5}$/',
            'shared' => '/^400\\d{7}|95\\d{3}$/',
            'emergency' => '/^1(?:1[09]|20)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{4,12}$/',
            'mobile' => '/^\\d{11}$/',
            'tollfree' => '/^\\d{10,12}$/',
            'premium' => '/^\\d{8}$/',
            'shared' => '/^\\d{5}(?:\\d{5})?$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '357',
    'patterns' => array(
        'national' => array(
            'general' => '/^[257-9]\\d{7}$/',
            'fixed' => '/^2[2-6]\\d{6}$/',
            'mobile' => '/^9[5-79]\\d{6}$/',
            'tollfree' => '/^800\\d{5}$/',
            'premium' => '/^90[09]\\d{5}$/',
            'shared' => '/^80[1-9]\\d{5}$/',
            'personal' => '/^700\\d{5}$/',
            'uan' => '/^(?:50|77)\\d{6}$/',
            'emergency' => '/^1(?:12|99)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '1',
    'patterns' => array(
        'national' => array(
            'general' => '/^[5689]\\d{9}$/',
            'fixed' => '/^671(?:3(?:00|3[39]|4[349]|55|6[26])|4(?:56|7[1-9]|8[23678])|5(?:55|6[2-5]|88)|6(?:3[2-578]|4[24-9]|5[34]|78|8[5-9])|7(?:[079]7|2[0167]|3[45]|8[789])|8(?:[2-5789]8|6[48])|9(?:2[29]|6[79]|7[179]|8[789]|9[78]))\\d{4}$/',
            'mobile' => '/^671(?:3(?:00|3[39]|4[349]|55|6[26])|4(?:56|7[1-9]|8[23678])|5(?:55|6[2-5]|88)|6(?:3[2-578]|4[24-9]|5[34]|78|8[5-9])|7(?:[079]7|2[0167]|3[45]|8[789])|8(?:[2-5789]8|6[48])|9(?:2[29]|6[79]|7[179]|8[789]|9[78]))\\d{4}$/',
            'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\\d{6}$/',
            'premium' => '/^900[2-9]\\d{6}$/',
            'personal' => '/^5(?:00|33|44)[2-9]\\d{6}$/',
            'emergency' => '/^911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}(?:\\d{3})?$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'personal' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '596',
    'patterns' => array(
        'national' => array(
            'general' => '/^[56]\\d{8}$/',
            'fixed' => '/^596(?:0[2-5]|[12]0|3[05-9]|4[024-8]|[5-7]\\d|89|9[4-8])\\d{4}$/',
            'mobile' => '/^696(?:[0-479]\\d|5[01]|8[0-689])\\d{4}$/',
            'emergency' => '/^1(?:12|[578])$/',
        ),
        'possible' => array(
            'general' => '/^\\d{9}$/',
            'emergency' => '/^\\d{2,3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '43',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-9]\d{3,12}$/',
            'fixed' => '/^1\d{3,12}|(?:2(?:1[467]|2[13-8]|5[2357]|6[1-46-8]|7[1-8]|8[124-7]|9[1458])|3(?:1[1-8]|3[23568]|4[5-7]|5[1378]|6[1-38]|8[3-68])|4(?:2[1-8]|35|63|7[1368]|8[2457])|5(?:12|2[1-8]|3[357]|4[147]|5[12578]|6[37])|6(?:13|2[1-47]|4[1-35-8]|5[468]|62)|7(?:2[1-8]|3[25]|4[13478]|5[68]|6[16-8]|7[1-6]|9[45]))\d{3,10}$/',
            'mobile' => '/^6(?:44|5[0-3579]|6[013-9]|[7-9]\d)\d{4,10}$/',
            'tollfree' => '/^80[02]\d{6,10}$/',
            'premium' => '/^(?:711|9(?:0[01]|3[019]))\d{6,10}$/',
            'shared' => '/^8(?:10|2[018])\d{6,10}$/',
            'voip' => '/^780\d{6,10}$/',
            'uan' => '/^5(?:(?:0[1-9]|17)\d{2,10}|[79]\d{3,11})|720\d{6,10}$/',
            'emergency' => '/^1(?:[12]2|33|44)$/',
        ),
        'possible' => array(
            'general' => '/^\d{3,13}$/',
            'mobile' => '/^\d{7,13}$/',
            'tollfree' => '/^\d{9,13}$/',
            'premium' => '/^\d{9,13}$/',
            'shared' => '/^\d{9,13}$/',
            'voip' => '/^\d{9,13}$/',
            'uan' => '/^\d{5,13}$/',
            'emergency' => '/^\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '247',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-467]\d{3}$/',
            'fixed' => '/^(?:[267]\d|3[0-5]|4[4-69])\d{2}$/',
            'emergency' => '/^911$/',
        ),
        'possible' => array(
            'general' => '/^\d{4}$/',
            'fixed' => '/^\d{4}$/',
            'emergency' => '/^\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '386',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-7]\\d{6,7}|[89]\\d{4,7}$/',
            'fixed' => '/^(?:1\\d|[25][2-8]|3[4-8]|4[24-8]|7[3-8])\\d{6}$/',
            'mobile' => '/^(?:[37][01]|4[019]|51|6[48])\\d{6}$/',
            'tollfree' => '/^80\\d{4,6}$/',
            'premium' => '/^90\\d{4,6}|89[1-3]\\d{2,5}$/',
            'voip' => '/^(?:59|8[1-3])\\d{6}$/',
            'emergency' => '/^11[23]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5,8}$/',
            'fixed' => '/^\\d{7,8}$/',
            'mobile' => '/^\\d{8}$/',
            'tollfree' => '/^\\d{6,8}$/',
            'premium' => '/^\\d{5,8}$/',
            'voip' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '1',
    'patterns' => array(
        'national' => array(
            'general' => '/^[57-9]\\d{9}$/',
            'fixed' => '/^767(?:2(?:55|66)|4(?:2[01]|4[0-25-9])|50[0-4])\\d{4}$/',
            'mobile' => '/^767(?:2(?:[234689]5|7[5-7])|31[5-7]|61[2-7])\\d{4}$/',
            'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\\d{6}$/',
            'premium' => '/^900[2-9]\\d{6}$/',
            'personal' => '/^5(?:00|33|44)[2-9]\\d{6}$/',
            'emergency' => '/^333|9(?:11|99)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}(?:\\d{3})?$/',
            'mobile' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'personal' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '1',
    'patterns' => array(
        'national' => array(
            'general' => '/^[3589]\\d{9}$/',
            'fixed' => '/^345(?:2(?:22|44)|444|6(?:23|38|40)|7(?:4[35-79]|6[6-9]|77)|8(?:00|1[45]|25|[48]8)|9(?:14|4[035-9]))\\d{4}$/',
            'mobile' => '/^345(?:32[1-9]|5(?:1[67]|2[5-7]|4[6-8]|76)|9(?:1[67]|2[3-9]|3[689]))\\d{4}$/',
            'pager' => '/^345849\\d{4}$/',
            'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\\d{6}$/',
            'premium' => '/^900[2-9]\\d{6}|345976\\d{4}$/',
            'personal' => '/^5(?:00|33|44)[2-9]\\d{6}$/',
            'emergency' => '/^911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}(?:\\d{3})?$/',
            'mobile' => '/^\\d{10}$/',
            'pager' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'personal' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '690',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-5]\\d{3}$/',
            'fixed' => '/^[2-4]\\d{3}$/',
            'mobile' => '/^5\\d{3}$/',
        ),
        'possible' => array(
            'general' => '/^\\d{4}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '261',
    'patterns' => array(
        'national' => array(
            'general' => '/^[23]\\d{8}$/',
            'fixed' => '/^2(?:0(?:(?:2\\d|4[47]|5[3467]|6[279]|8[268]|9[245])\\d|7(?:2[29]|[35]\\d))|210\\d)\\d{4}$/',
            'mobile' => '/^3[02-4]\\d{7}$/',
            'emergency' => '/^11?[78]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,9}$/',
            'mobile' => '/^\\d{9}$/',
            'emergency' => '/^\\d{2,3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '688',
    'patterns' => array(
        'national' => array(
            'general' => '/^[29]\\d{4,5}$/',
            'fixed' => '/^2[02-9]\\d{3}$/',
            'mobile' => '/^90\\d{4}$/',
            'emergency' => '/^911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5,6}$/',
            'fixed' => '/^\\d{5}$/',
            'mobile' => '/^\\d{6}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '245',
    'patterns' => array(
        'national' => array(
            'general' => '/^[3567]\\d{6}$/',
            'fixed' => '/^3(?:2[0125]|3[1245]|4[12]|5[1-4]|70|9[1-467])\\d{4}$/',
            'mobile' => '/^[5-7]\\d{6}$/',
            'emergency' => '/^11[378]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '678',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-57-9]\\d{4,6}$/',
            'fixed' => '/^(?:2[2-9]\\d|3(?:[5-7]\\d|8[0-8])|48[4-9]|88\\d)\\d{2}$/',
            'mobile' => '/^(?:5(?:7[2-5]|[3-69]\\d)|7[013-7]\\d)\\d{4}$/',
            'uan' => '/^3[03]\\d{3}|900\\d{4}$/',
            'emergency' => '/^112$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5,7}$/',
            'fixed' => '/^\\d{5}$/',
            'mobile' => '/^\\d{7}$/',
            'uan' => '/^\\d{5,7}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '61',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-578]\d{5,9}$/',
            'fixed' => '/^[237]\d{8}|8(?:[68]\d{3}|7[0-69]\d{2}|9(?:[02-9]\d{2}|1(?:[0-57-9]\d|6[0135-9])))\d{4}$/',
            'mobile' => '/^14(?:5\d|71)\d{5}|4(?:[0-2]\d|3[0-57-9]|4[47-9]|5[0-35-9]|6[6-9]|[79][07-9]|8[17-9])\d{6}$/',
            'pager' => '/^16\d{3,7}$/',
            'tollfree' => '/^180(?:0\d{3}|2)\d{3}$/',
            'premium' => '/^19(?:0[0126]\d{6}|[13-5]\d{3}|[679]\d{5})$/',
            'shared' => '/^13(?:00\d{2})?\d{4}$/',
            'personal' => '/^500\d{6}$/',
            'voip' => '/^550\d{6}$/',
            'emergency' => '/^000|112$/',
        ),
        'possible' => array(
            'general' => '/^\d{6,10}$/',
            'fixed' => '/^\d{8,9}$/',
            'mobile' => '/^\d{9}$/',
            'pager' => '/^\d{5,9}$/',
            'tollfree' => '/^\d{7,10}$/',
            'premium' => '/^\d{6,10}$/',
            'shared' => '/^\d{6,10}$/',
            'personal' => '/^\d{9}$/',
            'voip' => '/^\d{9}$/',
            'emergency' => '/^\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '299',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-689]\\d{5}$/',
            'fixed' => '/^(?:19|3[1-6]|6[14689]|8[14-79]|9\\d)\\d{4}$/',
            'mobile' => '/^[245][2-9]\\d{4}$/',
            'tollfree' => '/^80\\d{4}$/',
            'voip' => '/^3[89]\\d{4}$/',
            'emergency' => '/^112$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '262',
    'patterns' => array(
        'national' => array(
            'general' => '/^[268]\\d{8}$/',
            'fixed' => '/^262\\d{6}$/',
            'mobile' => '/^6(?:9[23]|47)\\d{6}$/',
            'tollfree' => '/^80\\d{7}$/',
            'premium' => '/^89[1-37-9]\\d{6}$/',
            'shared' => '/^8(?:1[019]|2[0156]|84|90)\\d{6}$/',
            'emergency' => '/^1(?:12|[578])$/',
        ),
        'possible' => array(
            'general' => '/^\\d{9}$/',
            'mobile' => '/^\\d{9}$/',
            'emergency' => '/^\\d{2,3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '264',
    'patterns' => array(
        'national' => array(
            'general' => '/^[68]\\d{7,8}$/',
            'fixed' => '/^6(?:1(?:17|2(?:[0189]\\d|[2-6]|7\\d?)|3(?:2\\d|3[378])|4[01]|69|7[014])|2(?:17|25|5(?:[0-36-8]|4\\d?)|69|70)|3(?:17|2(?:[0237]\\d?|[14-689])|34|6[29]|7[01]|81)|4(?:17|2(?:[012]|7?)|4(?:[06]|1\\d)|5(?:[01357]|[25]\\d?)|69|7[01])|5(?:17|2(?:[0459]|[23678]\\d?)|69|7[01])|6(?:17|2(?:5|6\\d?)|38|42|69|7[01])|7(?:17|2(?:[569]|[234]\\d?)|3(?:0\\d?|[13])|69|7[01]))\\d{4}$/',
            'mobile' => '/^(?:60|8[125])\\d{7}$/',
            'premium' => '/^8701\\d{5}$/',
            'voip' => '/^8(3\\d{2}|86)\\d{5}$/',
            'shortcode' => '/^1\\d{3}|9(?:3111|\\d{2})$/',
            'emergency' => '/^10111$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8,9}$/',
            'mobile' => '/^\\d{9}$/',
            'premium' => '/^\\d{9}$/',
            'shortcode' => '/^\\d{3,5}$/',
            'emergency' => '/^\\d{5}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '92',
    'patterns' => array(
        'national' => array(
            'general' => '/^1\\d{8}|[2-8]\\d{5,11}|9(?:[013-9]\\d{4,9}|2\\d(?:111\\d{6}|\\d{3,7}))$/',
            'fixed' => '/^(?:21|42)[2-9]\\d{7}|(?:2[25]|4[0146-9]|5[1-35-7]|6[1-8]|7[14]|8[16]|91)[2-9]\\d{6}|(?:2(?:3[2358]|4[2-4]|9[2-8])|45[3479]|54[2-467]|60[468]|72[236]|8(?:2[2-689]|3[23578]|4[3478]|5[2356])|9(?:1|2[2-8]|3[27-9]|4[2-6]|6[3569]|9[25-8]))[2-9]\\d{5,6}|58[126]\\d{7}$/',
            'mobile' => '/^3(?:0\\d|1[1-5]|2[0-5]|3[1-6]|4[1-7]|55|64)\\d{7}$/',
            'tollfree' => '/^800\\d{5}$/',
            'premium' => '/^900\\d{5}$/',
            'personal' => '/^122\\d{6}$/',
            'uan' => '/^(?:2(?:[125]|3[2358]|4[2-4]|9[2-8])|4(?:[0-246-9]|5[3479])|5(?:[1-35-7]|4[2-467])|6(?:[1-8]|0[468])|7(?:[14]|2[236])|8(?:[16]|2[2-689]|3[23578]|4[3478]|5[2356])|9(?:1|22|3[27-9]|4[2-6]|6[3569]|9[2-7]))111\\d{6}$/',
            'emergency' => '/^1(?:1(?:22?|5)|[56])$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,12}$/',
            'fixed' => '/^\\d{6,10}$/',
            'mobile' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{8}$/',
            'premium' => '/^\\d{8}$/',
            'personal' => '/^\\d{9}$/',
            'uan' => '/^\\d{11,12}$/',
            'emergency' => '/^\\d{2,4}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '266',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2568]\\d{7}$/',
            'fixed' => '/^2\\d{7}$/',
            'mobile' => '/^[56]\\d{7}$/',
            'tollfree' => '/^800[256]\\d{4}$/',
            'emergency' => '/^11[257]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '238',
    'patterns' => array(
        'national' => array(
            'general' => '/^[259]\\d{6}$/',
            'fixed' => '/^2(?:2[1-7]|3[0-8]|4[12]|5[1256]|6\\d|7[1-3]|8[1-5])\\d{4}$/',
            'mobile' => '/^(?:9\\d|59)\\d{5}$/',
            'emergency' => '/^13[012]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '1',
    'patterns' => array(
        'national' => array(
            'general' => '/^[589]\\d{9}$/',
            'fixed' => '/^876(?:5(?:0[12]|1[0-468]|2[35]|63)|6(?:0[1-3579]|1[027-9]|[23]\\d|40|5[06]|6[2-489]|7[05]|8[04]|9[4-9])|7(?:0[2-689]|[1-6]\\d|8[056]|9[45])|9(?:0[1-8]|1[02378]|[2-8]\\d|9[2-468]))\\d{4}$/',
            'mobile' => '/^876(?:2[1789]\\d|[348]\\d{2}|5(?:08|27|6[0-24-9]|[3-578]\\d)|7(?:0[07]|7\\d|8[1-47-9]|9[0-36-9])|9(?:[01]9|9[0579]))\\d{4}$/',
            'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\\d{6}$/',
            'premium' => '/^900[2-9]\\d{6}$/',
            'personal' => '/^5(?:00|33|44)[2-9]\\d{6}$/',
            'emergency' => '/^11[09]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}(?:\\d{3})?$/',
            'mobile' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'personal' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '36',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-9]\\d{7,8}$/',
            'fixed' => '/^(?:1\\d|2(?:1\\d|[2-9])|3[2-7]|4[24-9]|5[2-79]|6[23689]|7(?:1\\d|[2-9])|8[2-57-9]|9[2-69])\\d{6}$/',
            'mobile' => '/^(?:[27]0|3[01])\\d{7}$/',
            'tollfree' => '/^80\\d{6}$/',
            'premium' => '/^9[01]\\d{6}$/',
            'shared' => '/^40\\d{6}$/',
            'emergency' => '/^1(?:0[457]|12)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,9}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{8}$/',
            'premium' => '/^\\d{8}$/',
            'shared' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '974',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-8]\\d{6,7}$/',
            'fixed' => '/^4[04]\\d{6}$/',
            'mobile' => '/^[3567]\\d{7}$/',
            'pager' => '/^2(?:[12]\\d|61)\\d{4}$/',
            'tollfree' => '/^800\\d{4}$/',
            'shortcode' => '/^(?:1|20|9[27]\\d)\\d{2}$/',
            'emergency' => '/^999$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,8}$/',
            'pager' => '/^\\d{7}$/',
            'shortcode' => '/^\\d{3,4}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '677',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-9]\\d{4,6}$/',
            'fixed' => '/^(?:1[4-79]|[23]\\d|4[01]|5[03]|6[0-37])\\d{3}$/',
            'mobile' => '/^48\\d{3}|7(?:[46-8]\\d|5[025-9]|90)\\d{4}|8[4-8]\\d{5}|9(?:[46]\\d|5[0-46-9]|7[0-689]|8[0-79]|9[0-8])\\d{4}$/',
            'tollfree' => '/^1[38]\\d{3}$/',
            'voip' => '/^5[12]\\d{3}$/',
            'shortcode' => '/^1(?:0[02-79]|1[12]|2[0-26]|4[189]|68)|9(?:[01]1|22|33|55|77|88)$/',
            'emergency' => '/^999$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5,7}$/',
            'fixed' => '/^\\d{5}$/',
            'tollfree' => '/^\\d{5}$/',
            'voip' => '/^\\d{5}$/',
            'shortcode' => '/^\\d{3}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '1',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2589]\\d{9}$/',
            'fixed' => '/^242(?:3(?:02|[236][1-9]|4[0-24-9]|5[0-68]|7[3467]|8[0-4]|9[2-467])|461|502|6(?:12|7[67]|8[78]|9[89])|702)\\d{4}$/',
            'mobile' => '/^242(?:3(?:5[79]|[79]5)|4(?:[2-4][1-9]|5[1-8]|6[2-8]|7\\d|81)|5(?:2[45]|3[35]|44|5[1-9]|65|77)|6[34]6|727)\\d{4}$/',
            'tollfree' => '/^242300\\d{4}|8(?:00|55|66|77|88)[2-9]\\d{6}$/',
            'premium' => '/^900[2-9]\\d{6}$/',
            'personal' => '/^5(?:00|33|44)[2-9]\\d{6}$/',
            'emergency' => '/^91[19]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}(?:\\d{3})?$/',
            'mobile' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'personal' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '242',
    'patterns' => array(
        'national' => array(
            'general' => '/^[028]\\d{8}$/',
            'fixed' => '/^222[1-589]\\d{5}$/',
            'mobile' => '/^0[14-6]\\d{7}$/',
            'tollfree' => '/^800\\d{6}$/',
        ),
        'possible' => array(
            'general' => '/^\\d{9}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '880',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-79]\\d{5,9}|1\\d{9}|8[0-7]\\d{4,8}$/',
            'fixed' => '/^2(?:7(?:1[0-267]|2[0-289]|3[0-29]|[46][01]|5[1-3]|7[017]|91)|8(?:0[125]|[139][1-6]|2[0157-9]|6[1-35]|7[1-5]|8[1-8])|9(?:0[0-2]|1[1-4]|2[568]|3[3-6]|5[5-7]|6[0167]|7[15]|8[016-8]))\\d{4}|3(?:12?[5-7]\\d{2}|0(?:2(?:[025-79]\\d|[348]\\d{1,2})|3(?:[2-4]\\d|[56]\\d?))|2(?:1\\d{2}|2(?:[12]\\d|[35]\\d{1,2}|4\\d?))|3(?:1\\d{2}|2(?:[2356]\\d|4\\d{1,2}))|4(?:1\\d{2}|2(?:2\\d{1,2}|[47]|5\\d{2}))|5(?:1\\d{2}|29)|[67]1\\d{2}|8(?:1\\d{2}|2(?:2\\d{2}|3|4\\d))|)\\d{3}|4(?:0(?:2(?:[09]\\d|7)|33\\d{2})|1\\d{3}|2(?:1\\d{2}|2(?:[25]\\d?|[348]\\d|[67]\\d{1,2}))|3(?:1\\d{2}(?:\\d{2})?|2(?:[045]\\d|[236-9]\\d{1,2})|32\\d{2})|4(?:[18]\\d{2}|2(?:[2-46]\\d{2}|3)|5[25]\\d{2})|5(?:1\\d{2}|2(?:3\\d|5))|6(?:[18]\\d{2}|2(?:3(?:\\d{2})?|[46]\\d{1,2}|5\\d{2}|7\\d)|5(?:3\\d?|4\\d|[57]\\d{1,2}|6\\d{2}|8))|71\\d{2}|8(?:[18]\\d{2}|23\\d{2}|54\\d{2})|9(?:[18]\\d{2}|2[2-5]\\d{2}|53\\d{1,2}))\\d{3}|5(?:02[03489]\\d{2}|1\\d{2}|2(?:1\\d{2}|2(?:2(?:\\d{2})?|[457]\\d{2}))|3(?:1\\d{2}|2(?:[37](?:\\d{2})?|[569]\\d{2}))|4(?:1\\d{2}|2[46]\\d{2})|5(?:1\\d{2}|26\\d{1,2})|6(?:[18]\\d{2}|2|53\\d{2})|7(?:1|24)\\d{2}|8(?:1|26)\\d{2}|91\\d{2})\\d{3}|6(?:0(?:1\\d{2}|2(?:3\\d{2}|4\\d{1,2}))|2(?:2[2-5]\\d{2}|5(?:[3-5]\\d{2}|7)|8\\d{2})|3(?:1|2[3478])\\d{2}|4(?:1|2[34])\\d{2}|5(?:1|2[47])\\d{2}|6(?:[18]\\d{2}|6(?:2(?:2\\d|[34]\\d{2})|5(?:[24]\\d{2}|3\\d|5\\d{1,2})))|72[2-5]\\d{2}|8(?:1\\d{2}|2[2-5]\\d{2})|9(?:1\\d{2}|2[2-6]\\d{2}))\\d{3}|7(?:(?:02|[3-589]1|6[12]|72[24])\\d{2}|21\\d{3}|32)\\d{3}|8(?:(?:4[12]|[5-7]2|1\\d?)|(?:0|3[12]|[5-7]1|217)\\d)\\d{4}|9(?:[35]1|(?:[024]2|81)\\d|(?:1|[24]1)\\d{2})\\d{3}$/',
            'mobile' => '/^(?:1[13-9]\\d|(?:3[78]|44)[02-9]|6(?:44|6[02-9]))\\d{7}$/',
            'tollfree' => '/^80[03]\\d{7}$/',
            'voip' => '/^96(?:0[49]|1[0-4]|6[69])\\d{6}$/',
            'shortcode' => '/^1(?:0(?:[39]|5(?:0\\d|[1-4])|6\\d{2}|7[0-4]|8[0-29])|1[6-9]|2(?:2[0-5]|[34])|3(?:1\\d?|3\\d|6[3-6])|4(?:0\\d|1\\d{2})|5[2-9])$/',
            'emergency' => '/^10[0-2]|999$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,10}$/',
            'fixed' => '/^\\d{6,9}$/',
            'mobile' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{10}$/',
            'voip' => '/^\\d{10}$/',
            'shortcode' => '/^\\d{3,5}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '221',
    'patterns' => array(
        'national' => array(
            'general' => '/^[37]\\d{8}$/',
            'fixed' => '/^3(?:0(?:1[01]|80)|3(?:8[1-9]|9[2-9]))\\d{5}$/',
            'mobile' => '/^7(?:0(?:[01279]0|3[03]|4[05]|5[06]|6[03-5]|8[029])|6(?:1[23]|2[89]|3[3489]|4[6-9]|5\\d|6[3-9]|7[45]|8[3-8])|7\\d{2}|8(?:01|1[01]))\\d{5}$/',
            'voip' => '/^33301\\d{4}$/',
        ),
        'possible' => array(
            'general' => '/^\\d{9}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '94',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-9]\\d{8}$/',
            'fixed' => '/^(?:[189]1|2[13-7]|3[1-8]|4[157]|5[12457]|6[35-7])[2-57]\\d{6}$/',
            'mobile' => '/^7[125-8]\\d{7}$/',
            'emergency' => '/^11[0189]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,9}$/',
            'mobile' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '1',
    'patterns' => array(
        'national' => array(
            'general' => '/^[5789]\\d{9}$/',
            'fixed' => '/^784(?:266|3(?:6[6-9]|7\\d|8[0-24-6])|4(?:38|5[0-36-8]|8\\d|9[01])|555|638|784)\\d{4}$/',
            'mobile' => '/^784(?:4(?:3[0-4]|5[45]|9[2-5])|5(?:2[6-9]|3[0-4]|93))\\d{4}$/',
            'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\\d{6}$/',
            'premium' => '/^900[2-9]\\d{6}$/',
            'personal' => '/^5(?:00|33|44)[2-9]\\d{6}$/',
            'emergency' => '/^9(?:11|99)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}(?:\\d{3})?$/',
            'mobile' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'personal' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '66',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-9]\\d{7,8}|1\\d{3}(?:\\d{6})?$/',
            'fixed' => '/^(?:2[1-9]|3[2-9]|4[2-5]|5[2-6]|7[3-7])\\d{6}$/',
            'mobile' => '/^[89]\\d{8}$/',
            'tollfree' => '/^1800\\d{6}$/',
            'premium' => '/^1900\\d{6}$/',
            'voip' => '/^60\\d{7}$/',
            'uan' => '/^1\\d{3}$/',
            'emergency' => '/^1(?:669|9[19])$/',
        ),
        'possible' => array(
            'general' => '/^\\d{4}|\\d{8,10}$/',
            'fixed' => '/^\\d{8}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'voip' => '/^\\d{9}$/',
            'uan' => '/^\\d{4}$/',
            'emergency' => '/^\\d{3,4}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '20',
    'patterns' => array(
        'national' => array(
            'general' => '/^1\\d{4,9}|[2456]\\d{8}|3\\d{7}|[89]\\d{8,9}$/',
            'fixed' => '/^(?:1(3[23]\\d|5[23])|2[2-4]\\d{2}|3\\d{2}|4(?:0[2-5]|[578][23]|64)\\d|5(?:0[2-7]|[57][23])\\d|6[24-689]3\\d|8(?:2[2-57]|4[26]|6[237]|8[2-4])\\d|9(?:2[27]|3[24]|52|6[2356]|7[2-4])\\d)\\d{5}|1[69]\\d{3}$/',
            'mobile' => '/^1(?:0[01269]|1[1245]|2[0-278])\\d{7}$/',
            'tollfree' => '/^800\\d{7}$/',
            'premium' => '/^900\\d{7}$/',
            'emergency' => '/^1(?:2[23]|80)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5,10}$/',
            'fixed' => '/^\\d{5,9}$/',
            'mobile' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '240',
    'patterns' => array(
        'national' => array(
            'general' => '/^[23589]\\d{8}$/',
            'fixed' => '/^3(?:3(?:3\\d[7-9]|[0-24-9]\\d[46])|5\\d{2}[7-9])\\d{4}$/',
            'mobile' => '/^(?:222|551)\\d{6}$/',
            'tollfree' => '/^80\\d[1-9]\\d{5}$/',
            'premium' => '/^90\\d[1-9]\\d{5}$/',
        ),
        'possible' => array(
            'general' => '/^\\d{9}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '508',
    'patterns' => array(
        'national' => array(
            'general' => '/^[45]\\d{5}$/',
            'fixed' => '/^41\\d{4}$/',
            'mobile' => '/^55\\d{4}$/',
            'emergency' => '/^1[578]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6}$/',
            'emergency' => '/^\\d{2}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '44',
    'patterns' => array(
        'national' => array(
            'general' => '/^[135789]\\d{6,9}$/',
            'fixed' => '/^1481\\d{6}$/',
            'mobile' => '/^7(?:781|839|911)\\d{6}$/',
            'pager' => '/^76(?:0[012]|2[356]|4[0134]|5[49]|6[0-369]|77|81|9[39])\\d{6}$/',
            'tollfree' => '/^80(?:0(?:1111|\\d{6,7})|8\\d{7})|500\\d{6}$/',
            'premium' => '/^(?:87[123]|9(?:[01]\\d|8[0-3]))\\d{7}$/',
            'shared' => '/^8(?:4(?:5464\\d|[2-5]\\d{7})|70\\d{7})$/',
            'personal' => '/^70\\d{8}$/',
            'voip' => '/^56\\d{8}$/',
            'uan' => '/^(?:3[0347]|55)\\d{8}$/',
            'shortcode' => '/^1(?:0[01]|1(?:1|[68]\\d{3})|23|4(?:1|7\\d)|55|800\\d|95)$/',
            'emergency' => '/^112|999$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,10}$/',
            'mobile' => '/^\\d{10}$/',
            'pager' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{7}(?:\\d{2,3})?$/',
            'premium' => '/^\\d{10}$/',
            'shared' => '/^\\d{7}(?:\\d{3})?$/',
            'personal' => '/^\\d{10}$/',
            'voip' => '/^\\d{10}$/',
            'uan' => '/^\\d{10}$/',
            'shortcode' => '/^\\d{3,6}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '1',
    'patterns' => array(
        'national' => array(
            'general' => '/^[3589]\\d{9}$/',
            'fixed' => '/^340(?:2(?:01|2[067]|36|44|77)|3(?:32|44)|4(?:4[38]|7[34])|5(?:1[34]|55)|6(?:26|4[23]|9[023])|7(?:[17]\\d|27)|884|998)\\d{4}$/',
            'mobile' => '/^340(?:2(?:01|2[067]|36|44|77)|3(?:32|44)|4(?:4[38]|7[34])|5(?:1[34]|55)|6(?:26|4[23]|9[023])|7(?:[17]\\d|27)|884|998)\\d{4}$/',
            'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\\d{6}$/',
            'premium' => '/^900[2-9]\\d{6}$/',
            'personal' => '/^5(?:00|33|44)[2-9]\\d{6}$/',
            'emergency' => '/^911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}(?:\\d{3})?$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'personal' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '61',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1458]\\d{5,9}$/',
            'fixed' => '/^89162\\d{4}$/',
            'mobile' => '/^4(?:[0-2]\\d|3[0-57-9]|4[47-9]|5[0-37-9]|6[6-9]|7[07-9]|8[7-9])\\d{6}$/',
            'tollfree' => '/^1(?:80(?:0\\d{2})?|3(?:00\\d{2})?)\\d{4}$/',
            'premium' => '/^190[0126]\\d{6}$/',
            'personal' => '/^500\\d{6}$/',
            'voip' => '/^550\\d{6}$/',
            'emergency' => '/^000|112$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,10}$/',
            'fixed' => '/^\\d{8,9}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{6,10}$/',
            'premium' => '/^\\d{10}$/',
            'personal' => '/^\\d{9}$/',
            'voip' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '509',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-489]\\d{7}$/',
            'fixed' => '/^2(?:[24]\\d|5[1-5]|94)\\d{5}$/',
            'mobile' => '/^(?:3[1-9]|4\\d)\\d{6}$/',
            'tollfree' => '/^8\\d{7}$/',
            'voip' => '/^98[89]\\d{5}$/',
            'shortcode' => '/^1\\d{2}$/',
            'emergency' => '/^11[48]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
            'tollfree' => '/^\\d{8}$/',
            'voip' => '/^\\d{8}$/',
            'shortcode' => '/^\\d{3}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '57',
    'patterns' => array(
        'national' => array(
            'general' => '/^(?:[13]\\d{0,3}|[24-8])\\d{7}$/',
            'fixed' => '/^[124-8][2-9]\\d{6}$/',
            'mobile' => '/^3(?:0[0-24]|1\\d|2[01])\\d{7}$/',
            'tollfree' => '/^1800\\d{7}$/',
            'premium' => '/^19(?:0[01]|4[78])\\d{7}$/',
            'emergency' => '/^1(?:1[29]|23|32|56)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,11}$/',
            'fixed' => '/^\\d{8}$/',
            'mobile' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{11}$/',
            'premium' => '/^\\d{11}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '376',
    'patterns' => array(
        'national' => array(
            'general' => '/^(?:[346-9]|180)\d{5}$/',
            'fixed' => '/^[78]\d{5}$/',
            'mobile' => '/^[346]\d{5}$/',
            'tollfree' => '/^180[02]\d{4}$/',
            'premium' => '/^9\d{5}$/',
            'emergency' => '/^11[0268]$/',
        ),
        'possible' => array(
            'general' => '/^\d{6,8}$/',
            'fixed' => '/^\d{6}$/',
            'mobile' => '/^\d{6}$/',
            'tollfree' => '/^\d{8}$/',
            'premium' => '/^\d{6}$/',
            'emergency' => '/^\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '992',
    'patterns' => array(
        'national' => array(
            'general' => '/^[3-59]\\d{8}$/',
            'fixed' => '/^(?:3(?:1[3-5]|2[245]|3[12]|4[24-7]|5[25]|72)|4(?:46|74|87))\\d{6}$/',
            'mobile' => '/^(?:505|9[0-35-9]\\d)\\d{6}$/',
            'emergency' => '/^1(?:0[1-3]|12)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{3,9}$/',
            'mobile' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '1',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2589]\d{9}$/',
            'fixed' => '/^268(?:4(?:6[0-38]|84)|56[0-2])\d{4}$/',
            'mobile' => '/^268(?:464|7(?:2[0-9]|64|7[0-689]|8[02-68]))\d{4}$/',
            'pager' => '/^26840[69]\d{4}$/',
            'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\d{6}$/',
            'premium' => '/^900[2-9]\d{6}$/',
            'personal' => '/^5(?:00|33|44)[2-9]\d{6}$/',
            'voip' => '/^26848[01]\d{4}$/',
            'emergency' => '/^9(?:11|99)$/',
        ),
        'possible' => array(
            'general' => '/^\d{7}(?:\d{3})?$/',
            'mobile' => '/^\d{10}$/',
            'pager' => '/^\d{10}$/',
            'tollfree' => '/^\d{10}$/',
            'premium' => '/^\d{10}$/',
            'personal' => '/^\d{10}$/',
            'voip' => '/^\d{10}$/',
            'emergency' => '/^\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '371',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2689]\\d{7}$/',
            'fixed' => '/^6[3-8]\\d{6}$/',
            'mobile' => '/^2\\d{7}$/',
            'tollfree' => '/^80\\d{6}$/',
            'premium' => '/^90\\d{6}$/',
            'shared' => '/^81\\d{6}$/',
            'emergency' => '/^0[123]|112$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
            'emergency' => '/^\\d{2,3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '53',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-57]\\d{5,7}$/',
            'fixed' => '/^2[1-4]\\d{5,6}|3(?:1\\d{6}|[23]\\d{4,6})|4(?:[125]\\d{5,6}|[36]\\d{6}|[78]\\d{4,6})|7\\d{6,7}$/',
            'mobile' => '/^5\\d{7}$/',
            'shortcode' => '/^1(?:1(?:6111|8)|40)$/',
            'emergency' => '/^10[456]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{4,8}$/',
            'mobile' => '/^\\d{8}$/',
            'shortcode' => '/^\\d{3,6}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '966',
    'patterns' => array(
        'national' => array(
            'general' => '/^(?:[1-467]|92)\\d{7}|5\\d{8}|8\\d{9}$/',
            'fixed' => '/^(?:[12][24-8]|3[35-8]|4[3-68]|6[2-5]|7[235-7])\\d{6}$/',
            'mobile' => '/^(?:5[013-689]\\d|8111)\\d{6}$/',
            'tollfree' => '/^800\\d{7}$/',
            'uan' => '/^9200\\d{5}$/',
            'shortcode' => '/^9(0[24-79]|33|40|66|8[59]|9[02-6])$/',
            'emergency' => '/^99[7-9]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,10}$/',
            'fixed' => '/^\\d{7,8}$/',
            'mobile' => '/^\\d{9,10}$/',
            'tollfree' => '/^\\d{10}$/',
            'uan' => '/^\\d{9}$/',
            'shortcode' => '/^\\d{3}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '1',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-9]\\d{9}|3\\d{6}$/',
            'fixed' => '/^(?:2(?:04|[23]6|[48]9|50)|3(?:06|43|65)|4(?:03|1[68]|3[178]|5[06])|5(?:0[06]|1[49]|79|8[17])|6(?:0[04]|13|39|47)|7(?:0[059]|80|78)|8(?:[06]7|19|73)|90[25])[2-9]\\d{6}|310\\d{4}$/',
            'mobile' => '/^(?:2(?:04|[23]6|[48]9|50)|3(?:06|43|65)|4(?:03|1[68]|3[178]|5[06])|5(?:0[06]|1[49]|79|8[17])|6(?:0[04]|13|39|47)|7(?:0[059]|80|78)|8(?:[06]7|19|73)|90[25])[2-9]\\d{6}$/',
            'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\\d{6}|310\\d{4}$/',
            'premium' => '/^900[2-9]\\d{6}$/',
            'personal' => '/^5(?:00|33|44)[2-9]\\d{6}$/',
            'emergency' => '/^112|911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}(?:\\d{3})?$/',
            'premium' => '/^\\d{10}$/',
            'personal' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '971',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-79]\d{7,8}|800\d{2,9}$/',
            'fixed' => '/^[2-4679][2-8]\d{6}$/',
            'mobile' => '/^5[0256]\d{7}$/',
            'tollfree' => '/^400\d{6}|800\d{2,9}$/',
            'premium' => '/^900[02]\d{5}$/',
            'shared' => '/^700[05]\d{5}$/',
            'uan' => '/^600[25]\d{5}$/',
            'emergency' => '/^112|99[789]$/',
        ),
        'possible' => array(
            'general' => '/^\d{5,12}$/',
            'fixed' => '/^\d{7,8}$/',
            'mobile' => '/^\d{9}$/',
            'tollfree' => '/^\d{5,12}$/',
            'premium' => '/^\d{9}$/',
            'shared' => '/^\d{9}$/',
            'uan' => '/^\d{9}$/',
            'emergency' => '/^\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '350',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2568]\\d{7}$/',
            'fixed' => '/^2(?:00\\d|16[0-7]|22[2457])\\d{4}$/',
            'mobile' => '/^(?:5[4-8]|60)\\d{6}$/',
            'tollfree' => '/^80\\d{6}$/',
            'premium' => '/^8[1-689]\\d{6}$/',
            'shared' => '/^87\\d{6}$/',
            'shortcode' => '/^1(?:00|1(?:6(?:00[06]|11[17])|8\\d{2})|23|4(?:1|7[014])|5[015]|9[34])|8(?:00|4[0-2]|8\\d)$/',
            'emergency' => '/^1(?:12|9[09])$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
            'shortcode' => '/^\\d{3,6}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '65',
    'patterns' => array(
        'national' => array(
            'general' => '/^[36]\\d{7}|[17-9]\\d{7,10}$/',
            'fixed' => '/^6[1-9]\\d{6}$/',
            'mobile' => '/^(?:8[1-7]|9[0-8])\\d{6}$/',
            'tollfree' => '/^1?800\\d{7}$/',
            'premium' => '/^1900\\d{7}$/',
            'voip' => '/^3[12]\\d{6}$/',
            'uan' => '/^7000\\d{7}$/',
            'shortcode' => '/^1(?:[0136]\\d{2}|[89](?:[1-9]\\d|0[1-9])|[57]\\d{2,3})|99[0246-8]$/',
            'emergency' => '/^99[359]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8,11}$/',
            'fixed' => '/^\\d{8}$/',
            'mobile' => '/^\\d{8}$/',
            'tollfree' => '/^\\d{10,11}$/',
            'premium' => '/^\\d{11}$/',
            'voip' => '/^\\d{8}$/',
            'uan' => '/^\\d{11}$/',
            'shortcode' => '/^\\d{3,5}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '500',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-7]\\d{4}$/',
            'fixed' => '/^[2-47]\\d{4}$/',
            'mobile' => '/^[56]\\d{4}$/',
            'shortcode' => '/^1\\d{2}$/',
            'emergency' => '/^999$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5}$/',
            'shortcode' => '/^\\d{3}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '675',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-9]\\d{6,7}$/',
            'fixed' => '/^(?:3\\d{2}|4[257]\\d|5[34]\\d|6(?:29|4[1-9])|85[02-46-9]|9[78]\\d)\\d{4}$/',
            'mobile' => '/^(?:68|7[0-36]\\d)\\d{5}$/',
            'tollfree' => '/^180\\d{4}$/',
            'voip' => '/^275\\d{4}$/',
            'emergency' => '/^000$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,8}$/',
            'fixed' => '/^\\d{7}$/',
            'mobile' => '/^\\d{7,8}$/',
            'tollfree' => '/^\\d{7}$/',
            'voip' => '/^\\d{7}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '387',
    'patterns' => array(
        'national' => array(
            'general' => '/^[3-9]\\d{7,8}$/',
            'fixed' => '/^(?:[35]\\d|49)\\d{6}$/',
            'mobile' => '/^6(?:03|44|71|[1-356])\\d{6}$/',
            'tollfree' => '/^8[08]\\d{6}$/',
            'premium' => '/^9[0246]\\d{6}$/',
            'shared' => '/^8[12]\\d{6}$/',
            'uan' => '/^70[23]\\d{5}$/',
            'emergency' => '/^12[234]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,9}$/',
            'fixed' => '/^\\d{6,8}$/',
            'mobile' => '/^\\d{8,9}$/',
            'tollfree' => '/^\\d{8}$/',
            'premium' => '/^\\d{8}$/',
            'shared' => '/^\\d{8}$/',
            'uan' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '81',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-9]\\d{8,9}|0(?:[36]\\d{7,14}|7\\d{5,7}|8\\d{7})$/',
            'fixed' => '/^(?:1(?:1[235-8]|2[3-6]|3[3-9]|4[2-6]|[58][2-8]|6[2-7]|7[2-9]|9[1-9])|2[2-9]\\d|[36][1-9]\\d|4(?:6[02-8]|[2-578]\\d|9[2-59])|5(?:6[1-9]|7[2-8]|[2-589]\\d)|7(?:3[4-9]|4[02-9]|[25-9]\\d)|8(?:3[2-9]|4[5-9]|5[1-9]|8[03-9]|[2679]\\d)|9(?:[679][1-9]|[2-58]\\d))\\d{6}$/',
            'mobile' => '/^(?:[79]0\\d|80[1-9])\\d{7}$/',
            'pager' => '/^20\\d{8}$/',
            'tollfree' => '/^120\\d{6}|800\\d{7}|0(?:37\\d{6,13}|66\\d{6,13}|777(?:[01]\\d{2}|5\\d{3}|8\\d{4})|882[1245]\\d{4})$/',
            'premium' => '/^990\\d{6}$/',
            'personal' => '/^60\\d{7}$/',
            'voip' => '/^50\\d{8}$/',
            'uan' => '/^570\\d{6}$/',
            'emergency' => '/^11[09]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,16}$/',
            'fixed' => '/^\\d{9}$/',
            'mobile' => '/^\\d{10}$/',
            'pager' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{7,16}$/',
            'premium' => '/^\\d{9}$/',
            'personal' => '/^\\d{9}$/',
            'voip' => '/^\\d{10}$/',
            'uan' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '32',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-9]\\d{7,8}$/',
            'fixed' => '/^(?:1[0-69]|[23][2-8]|[49][23]|5\\d|6[013-57-9]|71)\\d{6}|8(?:0[1-9]|[1-79]\\d)\\d{5}$/',
            'mobile' => '/^4(?:[679]\\d|8[03-9])\\d{6}$/',
            'tollfree' => '/^800\\d{5}$/',
            'premium' => '/^(?:90|7[07])\\d{6}$/',
            'uan' => '/^78\\d{6}$/',
            'emergency' => '/^1(?:0[01]|12)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8,9}$/',
            'fixed' => '/^\\d{8}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{8}$/',
            'premium' => '/^\\d{8}$/',
            'uan' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '683',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-5]\\d{3}$/',
            'fixed' => '/^[34]\\d{3}$/',
            'mobile' => '/^[125]\\d{3}$/',
            'emergency' => '/^999$/',
        ),
        'possible' => array(
            'general' => '/^\\d{4}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '228',
    'patterns' => array(
        'national' => array(
            'general' => '/^[29]\\d{7}$/',
            'fixed' => '/^2(?:2[2-7]|3[23]|44|55|66|77)\\d{5}$/',
            'mobile' => '/^9[0-289]\\d{6}$/',
            'emergency' => '/^1(?:01|1[78]|7[17])$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '211',
    'patterns' => array(
        'national' => array(
            'general' => '/^[19]\\d{8}$/',
            'fixed' => '/^18\\d{7}$/',
            'mobile' => '/^(?:12|9[1257])\\d{7}$/',
        ),
        'possible' => array(
            'general' => '/^\\d{9}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '355',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-57]\d{7}|6\d{8}|8\d{5,7}|9\d{5}$/',
            'fixed' => '/^(?:2(?:[168][1-9]|[247]\d|9[1-7])|3(?:1[1-3]|[2-6]\d|[79][1-8]|8[1-9])|4\d{2}|5(?:1[1-4]|[2-578]\d|6[1-5]|9[1-7])|8(?:[19][1-5]|[2-6]\d|[78][1-7]))\d{5}$/',
            'mobile' => '/^6[6-9]\d{7}$/',
            'tollfree' => '/^800\d{4}$/',
            'premium' => '/^900\d{3}$/',
            'shared' => '/^808\d{3}$/',
            'personal' => '/^700\d{5}$/',
            'emergency' => '/^12[789]$/',
        ),
        'possible' => array(
            'general' => '/^\d{5,9}$/',
            'fixed' => '/^\d{5,8}$/',
            'mobile' => '/^\d{9}$/',
            'tollfree' => '/^\d{7}$/',
            'premium' => '/^\d{6}$/',
            'shared' => '/^\d{6}$/',
            'personal' => '/^\d{8}$/',
            'emergency' => '/^\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '237',
    'patterns' => array(
        'national' => array(
            'general' => '/^[237-9]\\d{7}$/',
            'fixed' => '/^(?:22|33)\\d{6}$/',
            'mobile' => '/^[79]\\d{7}$/',
            'tollfree' => '/^800\\d{5}$/',
            'premium' => '/^88\\d{6}$/',
            'emergency' => '/^1?1[37]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
            'emergency' => '/^\\d{2,3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '46',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-9]\\d{6,9}$/',
            'fixed' => '/^1(?:0[1-8]\\d{6}|[136]\\d{5,7}|(?:2[0-35]|4[0-4]|5[0-25-9]|7[13-6]|[89]\\d)\\d{5,6})|2(?:[136]\\d{5,7}|(?:2[0-7]|4[0136-8]|5[0138]|7[018]|8[01]|9[0-57])\\d{5,6})|3(?:[356]\\d{5,7}|(?:0[0-4]|1\\d|2[0-25]|4[056]|7[0-2]|8[0-3]|9[023])\\d{5,6})|4(?:[0246]\\d{5,7}|(?:1[0-8]|3[0135]|5[14-79]|7[0-246-9]|8[0156]|9[0-689])\\d{5,6})|5(?:0[0-6]|[15][0-5]|2[0-68]|3[0-4]|4\\d|6[03-5]|7[013]|8[0-79]|9[01])\\d{5,6}|6(?:[03]\\d{5,7}|(?:1[1-3]|2[0-4]|4[02-57]|5[0-37]|6[0-3]|7[0-2]|8[0247]|9[0-356])\\d{5,6})|8\\d{6,8}|9(?:0\\d{5,7}|(?:1[0-68]|2\\d|3[02-59]|[45][0-4]|[68][01]|7[0135-8])\\d{5,6})$/',
            'mobile' => '/^7[0236]\\d{7}$/',
            'pager' => '/^74\\d{7}$/',
            'tollfree' => '/^20\\d{4,7}$/',
            'premium' => '/^9(?:00|39|44)\\d{7}$/',
            'shared' => '/^77\\d{7}$/',
            'personal' => '/^75\\d{7}$/',
            'emergency' => '/^112|90000$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5,10}$/',
            'fixed' => '/^\\d{5,9}$/',
            'mobile' => '/^\\d{9}$/',
            'pager' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{6,9}$/',
            'premium' => '/^\\d{10}$/',
            'shared' => '/^\\d{9}$/',
            'personal' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3,5}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '265',
    'patterns' => array(
        'national' => array(
            'general' => '/^(?:1(?:\\d{2})?|[2789]\\d{2})\\d{6}$/',
            'fixed' => '/^(?:1[2-9]|21\\d{2})\\d{5}$/',
            'mobile' => '/^(?:111|77\\d|88\\d|99\\d)\\d{6}$/',
            'emergency' => '/^199|99[789]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,9}$/',
            'mobile' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '358',
    'patterns' => array(
        'national' => array(
            'general' => '/^1\\d{4,11}|[2-9]\\d{4,10}$/',
            'fixed' => '/^1(?:[3569][1-8]\\d{3,9}|[47]\\d{5,10})|2[1-8]\\d{3,9}|3(?:[1-8]\\d{3,9}|9\\d{4,8})|[5689][1-8]\\d{3,9}$/',
            'mobile' => '/^4\\d{5,10}|50\\d{4,8}$/',
            'tollfree' => '/^800\\d{4,7}$/',
            'premium' => '/^[67]00\\d{5,6}$/',
            'uan' => '/^[13]0\\d{4,8}|2(?:0(?:[016-8]\\d{3,7}|[2-59]\\d{2,7})|9\\d{4,8})|60(?:[12]\\d{5,6}|6\\d{7})|7(?:1\\d{7}|3\\d{8}|5[03-9]\\d{2,7})$/',
            'emergency' => '/^112$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5,12}$/',
            'mobile' => '/^\\d{6,11}$/',
            'tollfree' => '/^\\d{7,10}$/',
            'premium' => '/^\\d{8,9}$/',
            'uan' => '/^\\d{5,10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '1',
    'patterns' => array(
        'national' => array(
            'general' => '/^[5789]\\d{9}$/',
            'fixed' => '/^758(?:234|4(?:30|5[0-9]|6[2-9]|8[0-2])|572|638|758)\\d{4}$/',
            'mobile' => '/^758(?:28[4-7]|384|4(?:6[01]|8[4-9])|5(?:1[89]|20|84)|7(?:1[2-9]|2[0-6]))\\d{4}$/',
            'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\\d{6}$/',
            'premium' => '/^900[2-9]\\d{6}$/',
            'personal' => '/^5(?:00|33|44)[2-9]\\d{6}$/',
            'emergency' => '/^9(?:11|99)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}(?:\\d{3})?$/',
            'mobile' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'personal' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '972',
    'patterns' => array(
        'national' => array(
            'general' => '/^[17]\\d{6,9}|[2-589]\\d{3}(?:\\d{3,6})?|6\\d{3}$/',
            'fixed' => '/^[2-489]\\d{7}$/',
            'mobile' => '/^5(?:[02347-9]\\d{2}|5(?:2[23]|3[34]|4[45]|5[5689]|6[67]|7[78]|8[89])|6[2-9]\\d)\\d{5}$/',
            'tollfree' => '/^1(?:80[019]\\d{3}|255)\\d{3}$/',
            'premium' => '/^1(?:212|(?:9(?:0[01]|19)|200)\\d{2})\\d{4}$/',
            'shared' => '/^1700\\d{6}$/',
            'voip' => '/^7(?:2[23]\\d|3[237]\\d|47\\d|6(?:5\\d|8[08])|7\\d{2}|8(?:33|55|77|81))\\d{5}$/',
            'uan' => '/^[2-689]\\d{3}$/',
            'voicemail' => '/^1599\\d{6}$/',
            'shortcode' => '/^1\\d{3}$/',
            'emergency' => '/^1(?:0[012]|12)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{4,10}$/',
            'fixed' => '/^\\d{7,8}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{7,10}$/',
            'premium' => '/^\\d{8,10}$/',
            'shared' => '/^\\d{10}$/',
            'voip' => '/^\\d{9}$/',
            'uan' => '/^\\d{4}$/',
            'voicemail' => '/^\\d{10}$/',
            'shortcode' => '/^\\d{4}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '993',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-6]\\d{7}$/',
            'fixed' => '/^(?:1(?:2\\d|3[1-9])|2(?:22|4[0-35-8])|3(?:22|4[03-9])|4(?:22|3[128]|4\\d|6[15])|5(?:22|5[7-9]|6[014-689]))\\d{5}$/',
            'mobile' => '/^6[3-8]\\d{6}$/',
            'emergency' => '/^0[1-3]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
            'emergency' => '/^\\d{2}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '60',
    'patterns' => array(
        'national' => array(
            'general' => '/^[13-9]\\d{7,9}$/',
            'fixed' => '/^(?:3[2-9]\\d|[4-9][2-9])\\d{6}$/',
            'mobile' => '/^1(?:1[1-3]\\d{2}|[02-4679][2-9]\\d|8(?:1[23]|[2-9]\\d))\\d{5}$/',
            'tollfree' => '/^1[38]00\\d{6}$/',
            'premium' => '/^1600\\d{6}$/',
            'personal' => '/^1700\\d{6}$/',
            'voip' => '/^154\\d{7}$/',
            'emergency' => '/^112|999$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,10}$/',
            'fixed' => '/^\\d{6,9}$/',
            'mobile' => '/^\\d{9,10}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'personal' => '/^\\d{10}$/',
            'voip' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '248',
    'patterns' => array(
        'national' => array(
            'general' => '/^[24689]\\d{5,6}$/',
            'fixed' => '/^4[2-46]\\d{5}$/',
            'mobile' => '/^2[5-8]\\d{5}$/',
            'tollfree' => '/^8000\\d{2}$/',
            'premium' => '/^98\\d{4}$/',
            'voip' => '/^64\\d{5}$/',
            'shortcode' => '/^1(?:0\\d|1[027]|2[0-8]|3[13]|4[0-2]|[59][15]|6[1-9]|7[124-6]|8[158])|96\\d{2}$/',
            'emergency' => '/^999$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,7}$/',
            'fixed' => '/^\\d{7}$/',
            'mobile' => '/^\\d{7}$/',
            'tollfree' => '/^\\d{6}$/',
            'premium' => '/^\\d{6}$/',
            'voip' => '/^\\d{7}$/',
            'shortcode' => '/^\\d{3,4}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '672',
    'patterns' => array(
        'national' => array(
            'general' => '/^[13]\\d{5}$/',
            'fixed' => '/^(?:1(?:06|17|28|39)|3[012]\\d)\\d{3}$/',
            'mobile' => '/^38\\d{4}$/',
            'emergency' => '/^9(?:11|55|77)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5,6}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '58',
    'patterns' => array(
        'national' => array(
            'general' => '/^[24589]\\d{9}$/',
            'fixed' => '/^(?:2(?:12|3[457-9]|[58][1-9]|[467]\\d|9[1-6])|50[01])\\d{7}$/',
            'mobile' => '/^4(?:1[24-8]|2[46])\\d{7}$/',
            'tollfree' => '/^800\\d{7}$/',
            'premium' => '/^900\\d{7}$/',
            'emergency' => '/^171$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,10}$/',
            'mobile' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '379',
    'patterns' => array(
        'national' => array(
            'general' => '/^06\\d{8}$/',
            'fixed' => '/^06698\\d{5}$/',
            'mobile' => '/^N/A$/',
            'emergency' => '/^11[2358]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{10}$/',
            'mobile' => '/^N/A$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '1',
    'patterns' => array(
        'national' => array(
            'general' => '/^[589]\\d{9}$/',
            'fixed' => '/^869(?:2(?:29|36)|302|4(?:6[5-9]|70))\\d{4}$/',
            'mobile' => '/^869(?:5(?:5[6-8]|6[5-7])|66\\d|76[02-6])\\d{4}$/',
            'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\\d{6}$/',
            'premium' => '/^900[2-9]\\d{6}$/',
            'personal' => '/^5(?:00|33|44)[2-9]\\d{6}$/',
            'emergency' => '/^333|9(?:11|99)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}(?:\\d{3})?$/',
            'mobile' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'personal' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '212',
    'patterns' => array(
        'national' => array(
            'general' => '/^[5689]\\d{8}$/',
            'fixed' => '/^5(?:2(?:(?:[015-7]\\d|2[2-9]|3[2-57]|4[2-8]|8[235-7])\\d|9(?:0\\d|[89]0))|3(?:(?:[0-4]\\d|[57][2-9]|6[235-8]|9[3-9])\\d|8(?:0\\d|[89]0)))\\d{4}$/',
            'mobile' => '/^6(?:0[0-6]|[14-7]\\d|2[2-46-9]|3[03-8]|8[01]|99)\\d{6}$/',
            'tollfree' => '/^80\\d{7}$/',
            'premium' => '/^89\\d{7}$/',
            'emergency' => '/^1(?:[59]|77)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{9}$/',
            'emergency' => '/^\\d{2,3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '599',
    'patterns' => array(
        'national' => array(
            'general' => '/^[169]\\d{6,7}$/',
            'fixed' => '/^9(?:[48]\\d{2}|50\\d|7(?:2[0-2]|[34]\\d|6[35-7]|77))\\d{4}$/',
            'mobile' => '/^9(?:5(?:[1246]\\d|3[01])|6(?:[1679]\\d|3[01]))\\d{4}$/',
            'pager' => '/^955\\d{5}$/',
            'shared' => '/^(?:10|69)\\d{5}$/',
            'emergency' => '/^112|911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,8}$/',
            'shared' => '/^\\d{7}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '998',
    'patterns' => array(
        'national' => array(
            'general' => '/^[679]\\d{8}$/',
            'fixed' => '/^(?:6(?:1(?:22|3[124]|4[1-4]|5[123578]|64)|2(?:22|3[0-57-9]|41)|5(?:22|3[3-7]|5[024-8])|6\\d{2}|7(?:[23]\\d|7[69])|9(?:22|4[1-8]|6[135]))|7(?:0(?:5[4-9]|6[0146]|7[12456]|9[135-8])|1[12]\\d|2(?:22|3[1345789]|4[123579]|5[14])|3(?:2\\d|3[1578]|4[1-35-7]|5[1-57]|61)|4(?:2\\d|3[1-579]|7[1-79])|5(?:22|5[1-9]|6[1457])|6(?:22|3[12457]|4[13-8])|9(?:22|5[1-9])))\\d{5}$/',
            'mobile' => '/^6(?:1(?:2(?:98|2[01])|35[0-4]|50\\d|61[23]|7(?:[01][017]|4\\d|55|9[5-9]))|2(?:11\\d|2(?:[12]1|9[01379])|5(?:[126]\\d|3[0-4])|7\\d{2})|5(?:19[01]|2(?:27|9[26])|30\\d|59\\d|7\\d{2})|6(?:2(?:1[5-9]|2[0367]|38|41|52|60)|3[79]\\d|4(?:56|83)|7(?:[07]\\d|1[017]|3[07]|4[047]|5[057]|67|8[0178]|9[79])|9[0-3]\\d)|7(?:2(?:24|3[237]|4[5-9]|7[15-8])|5(?:7[12]|8[0589])|7(?:0\\d|[39][07])|9(?:0\\d|7[079]))|9(2(?:1[1267]|5\\d|3[01]|7[0-4])|5[67]\\d|6(?:2[0-26]|8\\d)|7\\d{2}))\\d{4}|7(?:0\\d{3}|1(?:13[01]|6(?:0[47]|1[67]|66)|71[3-69]|98\\d)|2(?:2(?:2[79]|95)|3(?:2[5-9]|6[0-6])|57\\d|7(?:0\\d|1[17]|2[27]|3[37]|44|5[057]|66|88))|3(?:2(?:1[0-6]|21|3[469]|7[159])|33\\d|5(?:0[0-4]|5[579]|9\\d)|7(?:[0-3579]\\d|4[0467]|6[67]|8[078])|9[4-6]\\d)|4(?:2(?:29|5[0257]|6[0-7]|7[1-57])|5(?:1[0-4]|8\\d|9[5-9])|7(?:0\\d|1[024589]|2[0127]|3[0137]|[46][07]|5[01]|7[5-9]|9[079])|9(?:7[015-9]|[89]\\d))|5(?:112|2(?:0\\d|2[29]|[49]4)|3[1568]\\d|52[6-9]|7(?:0[01578]|1[017]|[23]7|4[047]|[5-7]\\d|8[78]|9[079]))|6(?:2(?:2[1245]|4[2-4])|39\\d|41[179]|5(?:[349]\\d|5[0-2])|7(?:0[017]|[13]\\d|22|44|55|67|88))|9(?:22[128]|3(?:2[0-4]|7\\d)|57[05629]|7(?:2[05-9]|3[37]|4\\d|60|7[2579]|87|9[07])))\\d{4}|9[0-57-9]\\d{7}$/',
            'emergency' => '/^0(?:0[123]|[123]|50)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,9}$/',
            'emergency' => '/^\\d{2,3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '374',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-9]\d{7}$/',
            'fixed' => '/^(?:10\d|2(?:2[2-46]|3[1-8]|4[2-69]|5[2-7]|6[1-9]|8[1-7])|3[12]2|47\d)\d{5}$/',
            'mobile' => '/^(?:55|77|9[1-9])\d{6}$/',
            'tollfree' => '/^800\d{5}$/',
            'premium' => '/^90[016]\d{5}$/',
            'shared' => '/^80[1-4]\d{5}$/',
            'voip' => '/^60[2-6]\d{5}$/',
            'shortcode' => '/^8[1-7]\d{2}|1(?:0[04-9]|[1-9]\d)$/',
            'emergency' => '/^10[123]$/',
        ),
        'possible' => array(
            'general' => '/^\d{5,8}$/',
            'mobile' => '/^\d{8}$/',
            'tollfree' => '/^\d{8}$/',
            'premium' => '/^\d{8}$/',
            'shared' => '/^\d{8}$/',
            'voip' => '/^\d{8}$/',
            'shortcode' => '/^\d{3,4}$/',
            'emergency' => '/^\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '55',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-46-9]\\d{7,10}|5\\d{8,9}$/',
            'fixed' => '/^1[1-9][2-5]\\d{7}|(?:[4689][1-9]|2[12478]|3[1-578]|5[13-5]|7[13-579])[2-5]\\d{7}$/',
            'mobile' => '/^1(?:1(?:5[347]|[6-8]\\d|9\\d{1,2})|[2-9][6-9]\\d)\\d{6}|(?:[4689][1-9]|2[12478]|3[1-578]|5[13-5]|7[13-579])[6-9]\\d{7}$/',
            'tollfree' => '/^800\\d{6,7}$/',
            'premium' => '/^[359]00\\d{6,7}$/',
            'shared' => '/^[34]00\\d{5}$/',
            'emergency' => '/^1(?:12|28|9[023])|911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8,11}$/',
            'mobile' => '/^\\d{10,11}$/',
            'shared' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '229',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2689]\\d{7}|7\\d{3}$/',
            'fixed' => '/^2(?:02|1[037]|2[45]|3[68])\\d{5}$/',
            'mobile' => '/^(?:6[46]|9[03-8])\\d{6}$/',
            'tollfree' => '/^7[3-5]\\d{2}$/',
            'voip' => '/^857[58]\\d{4}$/',
            'uan' => '/^81\\d{6}$/',
            'emergency' => '/^11[78]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{4,8}$/',
            'fixed' => '/^\\d{8}$/',
            'mobile' => '/^\\d{8}$/',
            'tollfree' => '/^\\d{4}$/',
            'voip' => '/^\\d{8}$/',
            'uan' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '218',
    'patterns' => array(
        'national' => array(
            'general' => '/^[25679]\\d{8}$/',
            'fixed' => '/^(?:2[1345]|5[1347]|6[123479]|71)\\d{7}$/',
            'mobile' => '/^9[1-6]\\d{7}$/',
            'emergency' => '/^19[013]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,9}$/',
            'mobile' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '54',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-368]\d{9}|9\d{10}$/',
            'fixed' => '/^11\d{8}|(?:2(?:2(?:[013]\d|2[13-79]|4[1-6]|5[2457]|6[124-8]|7[1-4]|8[13-6]|9[1267])|3(?:1[467]|2[03-6]|3[13-8]|[49][2-6]|5[2-8]|[067]\d)|4(?:7[3-8]|9\d)|6(?:[01346]\d|2[24-6]|5[15-8])|80\d|9(?:[0124789]\d|3[1-6]|5[234]|6[2-46]))|3(?:3(?:2[79]|6\d|8[2578])|4(?:[78]\d|0[0124-9]|[1-35]\d|4[24-7]|6[02-9]|9[123678])|5(?:[138]\d|2[1245]|4[1-9]|6[2-4]|7[1-6])|6[24]\d|7(?:[0469]\d|1[1568]|2[013-9]|3[145]|5[14-8]|7[2-57]|8[0-24-9])|8(?:[013578]\d|2[15-7]|4[13-6]|6[1-357-9]|9[124]))|670\d)\d{6}$/',
            'mobile' => '/^675\d{7}|9(?:11[2-9]\d{7}|(?:2(?:2[013]|3[067]|49|6[01346]|80|9[147-9])|3(?:36|4[12358]|5[138]|6[24]|7[069]|8[013578]))[2-9]\d{6}|\d{4}[2-9]\d{5})$/',
            'tollfree' => '/^800\d{7}$/',
            'premium' => '/^60[04579]\d{7}$/',
            'uan' => '/^810\d{7}$/',
            'shortcode' => '/^1(?:0[2356]|1[02-5]|21)$/',
            'emergency' => '/^1(?:0[017]|28)$/',
        ),
        'possible' => array(
            'general' => '/^\d{6,11}$/',
            'fixed' => '/^\d{6,10}$/',
            'mobile' => '/^\d{6,11}$/',
            'tollfree' => '/^\d{10}$/',
            'premium' => '/^\d{10}$/',
            'uan' => '/^\d{10}$/',
            'shortcode' => '/^\d{3}$/',
            'emergency' => '/^\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '262',
    'patterns' => array(
        'national' => array(
            'general' => '/^[268]\\d{8}$/',
            'fixed' => '/^2696[0-4]\\d{4}$/',
            'mobile' => '/^639\\d{6}$/',
            'tollfree' => '/^80\\d{7}$/',
            'emergency' => '/^1(?:12|5)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{9}$/',
            'emergency' => '/^\\d{2,3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '27',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-79]\\d{8}|8(?:[067]\\d{7}|[1-4]\\d{3,7})$/',
            'fixed' => '/^(?:1[0-8]|2[0-378]|3[1-69]|4\\d|5[1346-8])\\d{7}$/',
            'mobile' => '/^(?:6[0-5]|7[0-46-9])\\d{7}|8[1-4]\\d{3,7}$/',
            'tollfree' => '/^80\\d{7}$/',
            'premium' => '/^86[2-9]\\d{6}|90\\d{7}$/',
            'shared' => '/^860\\d{6}$/',
            'voip' => '/^87\\d{7}$/',
            'uan' => '/^861\\d{6}$/',
            'emergency' => '/^1(?:01(?:11|77)|12)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5,9}$/',
            'fixed' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{9}$/',
            'premium' => '/^\\d{9}$/',
            'shared' => '/^\\d{9}$/',
            'voip' => '/^\\d{9}$/',
            'uan' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3,5}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '856',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-8]\\d{7,9}$/',
            'fixed' => '/^(?:2[13]|[35-7][14]|41|8[1468])\\d{6}$/',
            'mobile' => '/^20(?:2[2389]|5[4-689]|7[6-8]|9[57-9])\\d{6}$/',
            'emergency' => '/^19[015]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,10}$/',
            'fixed' => '/^\\d{6,8}$/',
            'mobile' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '592',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-4679]\\d{6}$/',
            'fixed' => '/^(?:2(?:1[6-9]|2[0-35-9]|3[1-4]|5[3-9]|6\\d|7[0-24-79])|3(?:2[25-9]|3\\d)|4(?:4[0-24]|5[56])|77[1-57])\\d{4}$/',
            'mobile' => '/^6\\d{6}$/',
            'tollfree' => '/^(?:289|862)\\d{4}$/',
            'premium' => '/^9008\\d{3}$/',
            'shortcode' => '/^0(?:02|171|444|7[67]7|801|9(?:0[78]|[2-47]))$/',
            'emergency' => '/^91[123]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}$/',
            'shortcode' => '/^\\d{3,4}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '91',
    'patterns' => array(
        'national' => array(
            'general' => '/^1\\d{7,12}|[2-9]\\d{9,10}$/',
            'fixed' => '/^(?:11|2[02]|33|4[04]|79)[2-7]\\d{7}|80[2-467]\\d{7}|(?:1(?:2[0-249]|3[0-25]|4[145]|[59][14]|6[014]|7[1257]|8[01346])|2(?:1[257]|3[013]|4[01]|5[0137]|6[0158]|78|8[1568]|9[14])|3(?:26|4[1-3]|5[34]|6[01489]|7[02-46]|8[159])|4(?:1[36]|2[1-47]|3[15]|5[12]|6[126-9]|7[0-24-9]|8[013-57]|9[014-7])|5(?:[136][25]|22|4[28]|5[12]|[78]1|9[15])|6(?:12|[2345]1|57|6[13]|7[14]|80)|7(?:12|2[14]|3[134]|4[47]|5[15]|[67]1|88)|8(?:16|2[014]|3[126]|6[136]|7[078]|8[34]|91))[2-7]\\d{6}|(?:(?:1(?:2[35-8]|3[346-9]|4[236-9]|[59][0235-9]|6[235-9]|7[34689]|8[257-9])|2(?:1[134689]|3[24-8]|4[2-8]|5[25689]|6[2-4679]|7[13-79]|8[2-479]|9[235-9])|3(?:01|1[79]|2[1-5]|4[25-8]|5[125689]|6[235-7]|7[157-9]|8[2-467])|4(?:1[14578]|2[5689]|3[2-467]|5[4-7]|6[35]|73|8[2689]|9[2389])|5(?:[16][146-9]|2[14-8]|3[1346]|4[14-69]|5[46]|7[2-4]|8[2-8]|9[246])|6(?:1[1358]|2[2457]|3[2-4]|4[235-7]|[57][2-689]|6[24-58]|8[1-6])|8(?:1[1357-9]|2[235-8]|3[03-57-9]|4[0-24-9]|5\\d|6[2457-9]|7[1-6]|8[1256]|9[2-4]))\\d|7(?:(?:1[013-9]|2[0235-9]|3[2679]|4[1-35689]|5[2-46-9]|[67][02-9]|9\\d)\\d|8(?:2[0-6]|[013-8]\\d)))[2-7]\\d{5}$/',
            'mobile' => '/^(?:7(?:2(?:0[04-9]|5[09]|7[5-8]|9[389])|3(?:0[1-9]|[58]\\d|7[3679]|9[689])|4(?:0[1-9]|1[15-9]|[29][89]|39|8[389])|5(?:0\\d|[47]9|[25]0|6[6-9]|[89][7-9])|6(?:0[027]|12|20|3[19]|5[45]|6[5-9]|7[679]|9[6-9])|7(?:0[27-9]|3[5-9]|42|60|7[7-9]|8[1-9]|9[05-9])|8(?:[03][07-9]|14|2[7-9]|[4-7]\\d|9[013-9]))|8(?:0(?:[01589]\\d|6[67])|1(?:[02-589]\\d|1[0135-9]|7[0-79])|2(?:[236-9]\\d|5[1-9])|3(?:[037-9]\\d|4[1-9]|5[0-37-9])|[45]\\d{2}|6[02457-9]\\d|7[1-69]\\d|8(?:[0-26-9]\\d|44|5[2-9])|9(?:[035-9]\\d|2[2-9]|4[0-8]))|9\\d{3})\\d{6}$/',
            'tollfree' => '/^1(?:600\\d{6}|80(?:0\\d{4,8}|3\\d{9}))$/',
            'premium' => '/^186[12]\\d{9}$/',
            'uan' => '/^1860\\d{7}$/',
            'emergency' => '/^1(?:0[0128]|12|298)|2611$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,13}$/',
            'fixed' => '/^\\d{6,10}$/',
            'mobile' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{8,13}$/',
            'premium' => '/^\\d{13}$/',
            'uan' => '/^\\d{11}$/',
            'emergency' => '/^\\d{3,4}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '93',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-7]\d{8}$/',
            'fixed' => '/^(?:[25][0-8]|[34][0-4]|6[0-5])[2-9]\d{6}$/',
            'mobile' => '/^7[057-9]\d{7}$/',
            'emergency' => '/^1(?:02|19)$/',
        ),
        'possible' => array(
            'general' => '/^\d{7,9}$/',
            'mobile' => '/^\d{9}$/',
            'emergency' => '/^\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '855',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-9]\\d{7,9}$/',
            'fixed' => '/^(?:2[3-6]|3[2-6]|4[2-4]|[567][2-5])(?:[2-47-9]|5\\d|6\\d?)\\d{5}$/',
            'mobile' => '/^(?:(?:1\\d|6[06-9]|7(?:[07-9]|6\\d))[1-9]|8(?:0[89]|[134679]\\d|5[2-689]|8\\d{2})|9(?:[0-589][1-9]|[67][1-9]\\d?))\\d{5}$/',
            'tollfree' => '/^1800(?:1\\d|2[019])\\d{4}$/',
            'premium' => '/^1900(?:1\\d|2[09])\\d{4}$/',
            'emergency' => '/^11[789]|666$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,10}$/',
            'fixed' => '/^\\d{6,9}$/',
            'mobile' => '/^\\d{8,9}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '973',
    'patterns' => array(
        'national' => array(
            'general' => '/^[136-9]\\d{7}$/',
            'fixed' => '/^(?:1(?:3[3-6]|6[0156]|7\\d)\\d|6(?:1[16]\\d|6(?:0\\d|3[12]|44)|9(?:69|9[6-9]))|77\\d{2})\\d{4}$/',
            'mobile' => '/^(?:3(?:[23469]\\d|5[35]|77|8[348])\\d|6(?:1[16]\\d|6(?:[06]\\d|3[03-9]|44)|9(?:69|9[6-9]))|77\\d{2})\\d{4}$/',
            'tollfree' => '/^80\\d{6}$/',
            'premium' => '/^(?:87|9[014578])\\d{6}$/',
            'shared' => '/^84\\d{6}$/',
            'emergency' => '/^999$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '423',
    'patterns' => array(
        'national' => array(
            'general' => '/^6\\d{8}|[23789]\\d{6}$/',
            'fixed' => '/^(?:2(?:01|1[27]|3\\d|6[02-578]|96)|3(?:7[0135-7]|8[048]|9[0269]))\\d{4}$/',
            'mobile' => '/^6(?:51[01]|6(?:[01][0-4]|2[016-9]|88)|710)\\d{5}|7(?:36|4[25]|56|[7-9]\\d)\\d{4}$/',
            'tollfree' => '/^80(?:0(?:2[238]|79)|9\\d{2})\\d{2}$/',
            'premium' => '/^90(?:0(?:2[278]|79)|1(?:23|3[012])|6(?:4\\d|6[0126]))\\d{2}$/',
            'uan' => '/^87(?:0[128]|7[0-4])\\d{3}$/',
            'voicemail' => '/^697(?:[35]6|4[25]|[7-9]\\d)\\d{4}$/',
            'personal' => '/^701\\d{4}$/',
            'shortcode' => '/^1(?:145|4(?:[0357]|14)|50\\d{4}|6(?:00|[1-4])|75|8(?:1[128]|7))$/',
            'emergency' => '/^1(?:1[278]|44)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,9}$/',
            'fixed' => '/^\\d{7}$/',
            'tollfree' => '/^\\d{7}$/',
            'premium' => '/^\\d{7}$/',
            'uan' => '/^\\d{7}$/',
            'voicemail' => '/^\\d{9}$/',
            'personal' => '/^\\d{7}$/',
            'shortcode' => '/^\\d{7}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '231',
    'patterns' => array(
        'national' => array(
            'general' => '/^(?:[29]\\d|[4-6]|7\\d{1,2}|[38]\\d{2})\\d{6}$/',
            'fixed' => '/^2\\d{7}$/',
            'mobile' => '/^(?:4[67]|5\\d|6[4-8]|7(?:7[67]\\d|\\d{2})|88\\d{2})\\d{5}$/',
            'premium' => '/^90\\d{6}$/',
            'voip' => '/^33200\\d{4}$/',
            'emergency' => '/^355|911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,9}$/',
            'fixed' => '/^\\d{8}$/',
            'premium' => '/^\\d{8}$/',
            'voip' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '244',
    'patterns' => array(
        'national' => array(
            'general' => '/^[29]\d{8}$/',
            'fixed' => '/^2\d(?:[26-9]\d|\d[26-9])\d{5}$/',
            'mobile' => '/^9[1-4]\d{7}$/',
            'emergency' => '/^11[235]$/',
        ),
        'possible' => array(
            'general' => '/^\d{9}$/',
            'emergency' => '/^\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '1',
    'patterns' => array(
        'national' => array(
            'general' => '/^[589]\\d{9}$/',
            'fixed' => '/^8(?:[04]9[2-9]\\d{6}|29(?:2(?:[0-59]\\d|6[04-9]|7[0-27]|8[0237-9])|3(?:[0-35-9]\\d|4[7-9])|[45]\\d{2}|6(?:[0-27-9]\\d|[3-5][1-9]|6[0135-8])|7(?:0[013-9]|[1-37]\\d|4[1-35689]|5[1-4689]|6[1-57-9]|8[1-79]|9[1-8])|8(?:0[146-9]|1[0-48]|[248]\\d|3[1-79]|5[01589]|6[013-68]|7[124-8]|9[0-8])|9(?:[0-24]\\d|3[02-46-9]|5[0-79]|60|7[0169]|8[57-9]|9[02-9]))\\d{4})$/',
            'mobile' => '/^8[024]9[2-9]\\d{6}$/',
            'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\\d{6}$/',
            'premium' => '/^900[2-9]\\d{6}$/',
            'personal' => '/^5(?:00|33|44)[2-9]\\d{6}$/',
            'emergency' => '/^112|911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}(?:\\d{3})?$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'personal' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '377',
    'patterns' => array(
        'national' => array(
            'general' => '/^[4689]\\d{7,8}$/',
            'fixed' => '/^9[2-47-9]\\d{6}$/',
            'mobile' => '/^6\\d{8}|4\\d{7}$/',
            'tollfree' => '/^(?:8\\d|90)\\d{6}$/',
            'emergency' => '/^1(?:12|[578])$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8,9}$/',
            'fixed' => '/^\\d{8}$/',
            'tollfree' => '/^\\d{8}$/',
            'emergency' => '/^\\d{2,3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '372',
    'patterns' => array(
        'national' => array(
            'general' => '/^1\\d{3,4}|[3-9]\\d{6,7}|800\\d{6,7}$/',
            'fixed' => '/^(?:3[23589]|4(?:0\\d|[3-8])|6\\d|7[1-9]|88)\\d{5}$/',
            'mobile' => '/^(?:5\\d|8[1-5])\\d{6}|5(?:[02]\\d{2}|1(?:[0-8]\\d|95)|5[0-478]\\d|64[0-4]|65[1-589])\\d{3}$/',
            'tollfree' => '/^800(?:0\\d{3}|1\\d|[2-9])\\d{3}$/',
            'premium' => '/^900\\d{4}$/',
            'personal' => '/^70[0-2]\\d{5}$/',
            'uan' => '/^1(?:2[01245]|3[0-6]|4[1-489]|5[0-59]|6[1-46-9]|7[0-27-9]|8[189]|9[012])\\d{1,2}$/',
            'shortcode' => '/^1(?:1[13-9]|[2-9]\\d)$/',
            'emergency' => '/^11[02]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{4,10}$/',
            'fixed' => '/^\\d{7,8}$/',
            'mobile' => '/^\\d{7,8}$/',
            'tollfree' => '/^\\d{7,10}$/',
            'premium' => '/^\\d{7}$/',
            'personal' => '/^\\d{8}$/',
            'uan' => '/^\\d{4,5}$/',
            'shortcode' => '/^\\d{3}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '994',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-9]\\d{8}$/',
            'fixed' => '/^(?:1[28]\\d|2(?:02|1[24]|2[2-4]|33|[45]2|6[23])|365)\\d{6}$/',
            'mobile' => '/^(?:4[04]|5[015]|60|7[07])\\d{7}$/',
            'tollfree' => '/^88\\d{7}$/',
            'premium' => '/^900200\\d{3}$/',
            'emergency' => '/^1(?:0[123]|12)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,9}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{9}$/',
            'premium' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '212',
    'patterns' => array(
        'national' => array(
            'general' => '/^[5689]\\d{8}$/',
            'fixed' => '/^528[89]\\d{5}$/',
            'mobile' => '/^6(?:0[0-6]|[14-7]\\d|2[2-46-9]|3[03-8]|8[01]|99)\\d{6}$/',
            'tollfree' => '/^80\\d{7}$/',
            'premium' => '/^89\\d{7}$/',
            'emergency' => '/^1(?:[59]|77)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{9}$/',
            'emergency' => '/^\\d{2,3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '505',
    'patterns' => array(
        'national' => array(
            'general' => '/^[128]\\d{7}$/',
            'fixed' => '/^2\\d{7}$/',
            'mobile' => '/^8\\d{7}$/',
            'tollfree' => '/^1800\\d{4}$/',
            'emergency' => '/^118$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '297',
    'patterns' => array(
        'national' => array(
            'general' => '/^[25-9]\\d{6}$/',
            'fixed' => '/^5(?:2\\d|8[1-9])\\d{4}$/',
            'mobile' => '/^(?:5(?:6\\d|9[2-478])|6(?:[039]0|22|4[01]|6[0-2])|7[34]\\d|9(?:6[45]|9[4-8]))\\d{4}$/',
            'tollfree' => '/^800\\d{4}$/',
            'premium' => '/^900\\d{4}$/',
            'voip' => '/^28\\d{5}|501\\d{4}$/',
            'emergency' => '/^100|911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '257',
    'patterns' => array(
        'national' => array(
            'general' => '/^[27]\\d{7}$/',
            'fixed' => '/^22(?:2[0-7]|[3-5]0)\\d{4}$/',
            'mobile' => '/^(?:29\\d|7(?:1[1-3]|[4-9]\\d))\\d{5}$/',
            'emergency' => '/^11[78]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '7',
    'patterns' => array(
        'national' => array(
            'general' => '/^(?:33\\d|7\\d{2}|80[09])\\d{7}$/',
            'fixed' => '/^33622\\d{5}|7(?:1(?:0(?:[23]\\d|4[023]|59|63)|1(?:[23]\\d|4[0-79]|59)|2(?:[23]\\d|59)|3(?:2\\d|3[1-79]|4[0-35-9]|59)|4(?:2\\d|3[013-79]|4[0-8]|5[1-79])|5(?:2\\d|3[1-8]|4[1-7]|59)|6(?:[234]\\d|5[19]|61)|72\\d|8(?:[27]\\d|3[1-46-9]|4[0-5]))|2(?:1(?:[23]\\d|4[46-9]|5[3469])|2(?:2\\d|3[0679]|46|5[12679])|3(?:[234]\\d|5[139])|4(?:2\\d|3[1235-9]|59)|5(?:[23]\\d|4[01246-8]|59|61)|6(?:2\\d|3[1-9]|4[0-4]|59)|7(?:[237]\\d|40|5[279])|8(?:[23]\\d|4[0-3]|59)|9(?:2\\d|3[124578]|59)))\\d{5}$/',
            'mobile' => '/^7(?:0[01257]|6[02-4]|7[1578]|85)\\d{7}$/',
            'tollfree' => '/^800\\d{7}$/',
            'premium' => '/^809\\d{7}$/',
            'voip' => '/^751\\d{7}$/',
            'emergency' => '/^1(?:0[123]|12)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '965',
    'patterns' => array(
        'national' => array(
            'general' => '/^[12569]\\d{6,7}$/',
            'fixed' => '/^(?:18\\d|2(?:[23]\\d{2}|4(?:[1-35-9]\\d|44)|5(?:0[034]|[2-46]\\d|5[1-3]|7[1-7])))\\d{4}$/',
            'mobile' => '/^(?:5(?:11|[05]\\d)|6(?:0[034679]|5[015-9]|6\\d|7[067]|9[069])|9(?:0[09]|4[049]|6[69]|[79]\\d))\\d{5}$/',
            'shortcode' => '/^1(?:[02-9]\\d|1[013-9])$/',
            'emergency' => '/^112$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,8}$/',
            'fixed' => '/^\\d{7,8}$/',
            'mobile' => '/^\\d{8}$/',
            'shortcode' => '/^\\d{3}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '232',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-578]\\d{7}$/',
            'fixed' => '/^[235]2[2-4][2-9]\\d{4}$/',
            'mobile' => '/^(?:2[15]|3[034]|4[04]|5[05]|7[6-9]|88)\\d{6}$/',
            'emergency' => '/^(?:01|99)9$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '995',
    'patterns' => array(
        'national' => array(
            'general' => '/^[3458]\\d{8}$/',
            'fixed' => '/^(?:3(?:[256]\\d|4[124-9]|7[0-4])|4(?:1\\d|2[2-7]|3[1-79]|4[2-8]|7[239]|9[1-7]))\\d{6}$/',
            'mobile' => '/^5(?:14|5[01578]|68|7[0147-9]|9[0-35-9])\\d{6}$/',
            'tollfree' => '/^800\\d{6}$/',
            'emergency' => '/^0(?:11|22|33)|1(?:1[123]|22)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,9}$/',
            'fixed' => '/^\\d{6,9}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '95',
    'patterns' => array(
        'national' => array(
            'general' => '/^[14578]\\d{5,7}|[26]\\d{5,8}|9(?:[258]|4\\d{1,2}|[679]\\d?)\\d{6}$/',
            'fixed' => '/^1(?:2\\d{1,2}|[3-5]\\d|6\\d?|[89][0-6]\\d)\\d{4}|2(?:[236-9]\\d{4}|4(?:0\\d{5}|\\d{4})|5(?:1\\d{3,6}|[02-9]\\d{3,5}))|4(?:2[245-8]|[346][2-6]|5[3-5])\\d{4}|5(?:2(?:20?|[3-8])|3[2-68]|4(?:21?|[4-8])|5[23]|6[2-4]|7[2-8]|8[24-7]|9[2-7])\\d{4}|6(?:0[23]|1[2356]|[24][2-6]|3[24-6]|5[2-4]|6[2-8]|7(?:[2367]|4\\d|5\\d?|8[145]\\d)|8[245]|9[24])\\d{4}|7(?:[04][24-8]|[15][2-7]|22|3[2-4])\\d{4}|8(?:1(?:2\\d?|[3-689])|2[2-8]|3[24]|4[24-7]|5[245]|6[23])\\d{4}$/',
            'mobile' => '/^17[01]\\d{4}|9(?:2[0-4]|4(?:0[0-4]\\d|[1379]\\d|[24][0-589]\\d|5\\d{2}|88)|5[0-6]|61?\\d|73\\d|8\\d|9(?:1\\d|[089]))\\d{5}$/',
            'voip' => '/^1333\\d{4}$/',
            'emergency' => '/^199$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5,10}$/',
            'fixed' => '/^\\d{5,9}$/',
            'mobile' => '/^\\d{7,10}$/',
            'voip' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '680',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-8]\\d{6}$/',
            'fixed' => '/^2552255|(?:277|345|488|5(?:35|44|87)|6(?:22|54|79)|7(?:33|47)|8(?:24|55|76))\\d{4}$/',
            'mobile' => '/^(?:6[234689]0|77[45789])\\d{4}$/',
            'emergency' => '/^911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '886',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-9]\\d{7,8}$/',
            'fixed' => '/^[2-8]\\d{7,8}$/',
            'mobile' => '/^9\\d{8}$/',
            'tollfree' => '/^800\\d{6}$/',
            'premium' => '/^900\\d{6}$/',
            'emergency' => '/^11[029]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8,9}$/',
            'fixed' => '/^\\d{8,9}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{9}$/',
            'premium' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '976',
    'patterns' => array(
        'national' => array(
            'general' => '/^[12]\\d{7,9}|[57-9]\\d{7}$/',
            'fixed' => '/^[12](?:1\\d|2(?:[1-3]\\d?|7\\d)|3[2-8]\\d{1,2}|4[2-68]\\d{1,2}|5[1-4689]\\d{1,2})\\d{5}|5[0568]\\d{6}$/',
            'mobile' => '/^(?:8[89]|9[013-9])\\d{6}$/',
            'voip' => '/^7[05-8]\\d{6}$/',
            'emergency' => '/^10[0-3]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,10}$/',
            'mobile' => '/^\\d{8}$/',
            'voip' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '674',
    'patterns' => array(
        'national' => array(
            'general' => '/^[458]\\d{6}$/',
            'fixed' => '/^(?:444|888)\\d{4}$/',
            'mobile' => '/^55[5-9]\\d{4}$/',
            'shortcode' => '/^1(?:23|92)$/',
            'emergency' => '/^11[0-2]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}$/',
            'shortcode' => '/^\\d{3}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '590',
    'patterns' => array(
        'national' => array(
            'general' => '/^[56]\\d{8}$/',
            'fixed' => '/^590(?:10|2[79]|5[128]|[78]7)\\d{4}$/',
            'mobile' => '/^690(?:10|2[27]|66|77|8[78])\\d{4}$/',
            'emergency' => '/^1[578]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{9}$/',
            'emergency' => '/^\\d{2}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '213',
    'patterns' => array(
        'national' => array(
            'general' => '/^(?:[1-4]|[5-9]\\d)\\d{7}$/',
            'fixed' => '/^(?:1\\d|2[014-79]|3[0-8]|4[0135689])\\d{6}|9619\\d{5}$/',
            'mobile' => '/^(?:5[56]|7[7-9])\\d{7}|6(?:[569]\\d|70)\\d{6}$/',
            'tollfree' => '/^800\\d{6}$/',
            'premium' => '/^80[3-689]1\\d{5}$/',
            'shared' => '/^80[12]1\\d{5}$/',
            'voip' => '/^98[23]\\d{6}$/',
            'emergency' => '/^1[47]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8,9}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{9}$/',
            'premium' => '/^\\d{9}$/',
            'shared' => '/^\\d{9}$/',
            'voip' => '/^\\d{9}$/',
            'emergency' => '/^\\d{2}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '597',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-8]\\d{5,6}$/',
            'fixed' => '/^(?:2[1-3]|3[0-7]|4\\d|5[2-58]|68\\d)\\d{4}$/',
            'mobile' => '/^(?:7[1-57]|8[1-9])\\d{5}$/',
            'voip' => '/^56\\d{4}$/',
            'shortcode' => '/^1(?:[02-9]\\d|1[0-46-9]|\\d{3})$/',
            'emergency' => '/^115$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,7}$/',
            'mobile' => '/^\\d{7}$/',
            'voip' => '/^\\d{6}$/',
            'shortcode' => '/^\\d{3,4}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '1',
    'patterns' => array(
        'national' => array(
            'general' => '/^[5689]\\d{9}$/',
            'fixed' => '/^649(?:712|9(?:4\\d|50))\\d{4}$/',
            'mobile' => '/^649(?:2(?:3[129]|4[1-7])|3(?:3[1-39]|4[1-7])|4[34][12])\\d{4}$/',
            'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\\d{6}$/',
            'premium' => '/^900[2-9]\\d{6}$/',
            'personal' => '/^5(?:00|33|44)[2-9]\\d{6}$/',
            'voip' => '/^64971[01]\\d{4}$/',
            'emergency' => '/^9(?:11|99)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}(?:\\d{3})?$/',
            'mobile' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'personal' => '/^\\d{10}$/',
            'voip' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '1',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-9]\\d{9}$/',
            'fixed' => '/^(?:2(?:0[1-35-9]|1[02-9]|2[4589]|3[149]|4[08]|5[1-46]|6[0279]|7[06]|8[13])|3(?:0[1-57-9]|1[02-9]|2[0135]|3[014679]|47|5[12]|6[01]|8[056])|4(?:0[124-9]|1[02-579]|2[3-5]|3[0245]|4[0235]|58|69|7[0589]|8[04])|5(?:0[1-57-9]|1[0235-8]|20|3[0149]|4[01]|5[19]|6[1-37]|7[013-5]|8[056])|6(?:0[1-35-9]|1[024-9]|2[036]|3[016]|4[16]|5[017]|6[0-279]|78|8[12])|7(?:0[1-46-8]|1[02-9]|2[047]|3[124]|4[07]|5[47]|6[02359]|7[02-59]|8[156])|8(?:0[1-68]|1[02-8]|28|3[0-25]|4[3578]|5[06-9]|6[02-5]|7[028])|9(?:0[1346-9]|1[02-9]|2[0589]|3[1678]|4[0179]|5[1246]|7[0-3589]|8[0459]))[2-9]\\d{6}$/',
            'mobile' => '/^(?:2(?:0[1-35-9]|1[02-9]|2[4589]|3[149]|4[08]|5[1-46]|6[0279]|7[06]|8[13])|3(?:0[1-57-9]|1[02-9]|2[0135]|3[014679]|47|5[12]|6[01]|8[056])|4(?:0[124-9]|1[02-579]|2[3-5]|3[0245]|4[0235]|58|69|7[0589]|8[04])|5(?:0[1-57-9]|1[0235-8]|20|3[0149]|4[01]|5[19]|6[1-37]|7[013-5]|8[056])|6(?:0[1-35-9]|1[024-9]|2[036]|3[016]|4[16]|5[017]|6[0-279]|78|8[12])|7(?:0[1-46-8]|1[02-9]|2[047]|3[124]|4[07]|5[47]|6[02359]|7[02-59]|8[156])|8(?:0[1-68]|1[02-8]|28|3[0-25]|4[3578]|5[06-9]|6[02-5]|7[028])|9(?:0[1346-9]|1[02-9]|2[0589]|3[1678]|4[0179]|5[1246]|7[0-3589]|8[0459]))[2-9]\\d{6}$/',
            'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\\d{6}$/',
            'premium' => '/^900[2-9]\\d{6}$/',
            'personal' => '/^5(?:00|33|44)[2-9]\\d{6}$/',
            'emergency' => '/^112|911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}(?:\\d{3})?$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'personal' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '260',
    'patterns' => array(
        'national' => array(
            'general' => '/^[289]\\d{8}$/',
            'fixed' => '/^21[1-8]\\d{6}$/',
            'mobile' => '/^9(?:5[05]|6\\d|7[13-9])\\d{6}$/',
            'tollfree' => '/^800\\d{6}$/',
            'emergency' => '/^(?:112|99[139])$/',
        ),
        'possible' => array(
            'general' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '45',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-9]\\d{7}$/',
            'fixed' => '/^(?:[2-7]\\d|8[126-9]|9[126-9])\\d{6}$/',
            'mobile' => '/^(?:[2-7]\\d|8[126-9]|9[126-9])\\d{6}$/',
            'tollfree' => '/^80\\d{6}$/',
            'premium' => '/^90\\d{6}$/',
            'emergency' => '/^112$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '964',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-7]\\d{7,9}$/',
            'fixed' => '/^1\\d{7}|(?:2[13-5]|3[02367]|4[023]|5[03]|6[026])\\d{6,7}$/',
            'mobile' => '/^7[3-9]\\d{8}$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,10}$/',
            'fixed' => '/^\\d{6,9}$/',
            'mobile' => '/^\\d{10}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '373',
    'patterns' => array(
        'national' => array(
            'general' => '/^[235-9]\\d{7}$/',
            'fixed' => '/^(?:2(?:1[0569]|2\\d|3[015-7]|4[1-46-9]|5[0-24689]|6[2-589]|7[1-37]|9[1347-9])|5(?:33|5[257]))\\d{5}$/',
            'mobile' => '/^(?:562|6(?:50|7[1-5]|[089]\\d)|7(?:7[47-9]|[89]\\d))\\d{5}$/',
            'tollfree' => '/^800\\d{5}$/',
            'premium' => '/^90[056]\\d{5}$/',
            'shared' => '/^808\\d{5}$/',
            'uan' => '/^8(?:03|14)\\d{5}$/',
            'voip' => '/^3[08]\\d{6}$/',
            'shortcode' => '/^1(?:1(?:[79]|6(?:000|1(?:11|23))|8\\d)|4\\d{3}|5[0-3]\\d|6[0-389]\\d|8\\d{2}|9(?:0[04-9]|[1-4]\\d))$/',
            'emergency' => '/^112|90[123]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
            'shortcode' => '/^\\d{3,6}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '41',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-9]\\d{8}|860\\d{9}$/',
            'fixed' => '/^(?:2[12467]|3[1-4]|4[134]|5[12568]|6[12]|[7-9]1)\\d{7}$/',
            'mobile' => '/^7[46-9]\\d{7}$/',
            'tollfree' => '/^800\\d{6}$/',
            'premium' => '/^90[016]\\d{6}$/',
            'shared' => '/^84[0248]\\d{6}$/',
            'personal' => '/^878\\d{6}$/',
            'voicemail' => '/^860\\d{9}$/',
            'emergency' => '/^1(?:1[278]|44)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{9}(?:\\d{3})?$/',
            'fixed' => '/^\\d{9}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{9}$/',
            'premium' => '/^\\d{9}$/',
            'shared' => '/^\\d{9}$/',
            'personal' => '/^\\d{9}$/',
            'voicemail' => '/^\\d{12}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '47',
    'patterns' => array(
        'national' => array(
            'general' => '/^0\\d{4}|[2-9]\\d{7}$/',
            'fixed' => '/^(?:2[1-4]|3[1-3578]|5[1-35-7]|6[1-4679]|7[0-8])\\d{6}$/',
            'mobile' => '/^(?:4[015-8]|5[89]|9\\d)\\d{6}$/',
            'tollfree' => '/^80[01]\\d{5}$/',
            'premium' => '/^82[09]\\d{5}$/',
            'shared' => '/^810(?:0[0-6]|[2-8]\\d)\\d{3}$/',
            'personal' => '/^880\\d{5}$/',
            'voip' => '/^85[0-5]\\d{5}$/',
            'uan' => '/^0\\d{4}|81(?:0(?:0[7-9]|1\\d)|5\\d{2})\\d{3}$/',
            'voicemail' => '/^81[23]\\d{5}$/',
            'emergency' => '/^11[023]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5}(?:\\d{3})?$/',
            'fixed' => '/^\\d{8}$/',
            'mobile' => '/^\\d{8}$/',
            'tollfree' => '/^\\d{8}$/',
            'premium' => '/^\\d{8}$/',
            'shared' => '/^\\d{8}$/',
            'personal' => '/^\\d{8}$/',
            'voip' => '/^\\d{8}$/',
            'voicemail' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '39',
    'patterns' => array(
        'national' => array(
            'general' => '/^[01589]\\d{5,10}|3(?:[12457-9]\\d{8}|[36]\\d{7,9})$/',
            'fixed' => '/^0(?:[26]\\d{4,9}|(?:1(?:[0159]\\d|[27][1-5]|31|4[1-4]|6[1356]|8[2-57])|3(?:[0159]\\d|2[1-4]|3[12]|[48][1-6]|6[2-59]|7[1-7])|4(?:[0159]\\d|[23][1-9]|4[245]|6[1-5]|7[1-4]|81)|5(?:[0159]\\d|2[1-5]|3[2-6]|4[1-79]|6[4-6]|7[1-578]|8[3-8])|7(?:[0159]\\d|2[12]|3[1-7]|4[2346]|6[13569]|7[13-6]|8[1-59])|8(?:[0159]\\d|2[34578]|3[1-356]|[6-8][1-5])|9(?:[0159]\\d|[238][1-5]|4[12]|6[1-8]|7[1-6]))\\d{2,7})$/',
            'mobile' => '/^3(?:[12457-9]\\d{8}|6\\d{7,8}|3\\d{7,9})$/',
            'tollfree' => '/^80(?:0\\d{6}|3\\d{3})$/',
            'premium' => '/^0878\\d{5}|1(?:44|6[346])\\d{6}|89(?:2\\d{3}|4(?:[0-4]\\d{2}|[5-9]\\d{4})|5(?:[0-4]\\d{2}|[5-9]\\d{6})|9\\d{6})$/',
            'shared' => '/^84(?:[08]\\d{6}|[17]\\d{3})$/',
            'personal' => '/^1(?:78\\d|99)\\d{6}$/',
            'voip' => '/^55\\d{8}$/',
            'shortcode' => '/^1(?:1(?:[47]|6\\d{3})|2\\d{2}|4(?:82|9\\d{1,3})|5(?:00|1[58]|2[25]|3[03]|44)|86|9(?:2(?:[01]\\d{2}|[2-9]\\d)|4\\d|696))$/',
            'emergency' => '/^11[2358]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,11}$/',
            'fixed' => '/^\\d{6,11}$/',
            'mobile' => '/^\\d{9,11}$/',
            'tollfree' => '/^\\d{6,9}$/',
            'premium' => '/^\\d{6,10}$/',
            'shared' => '/^\\d{6,9}$/',
            'personal' => '/^\\d{9,10}$/',
            'voip' => '/^\\d{10}$/',
            'shortcode' => '/^\\d{3,6}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '598',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2489]\\d{6,7}$/',
            'fixed' => '/^2\\d{7}|4[2-7]\\d{6}$/',
            'mobile' => '/^9[13-9]\\d{6}$/',
            'tollfree' => '/^80[05]\\d{4}$/',
            'premium' => '/^90[0-8]\\d{4}$/',
            'shortcode' => '/^1(?:0[4-9]|1[2368]|2[0-3568])$/',
            'emergency' => '/^128|911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,8}$/',
            'mobile' => '/^\\d{8}$/',
            'tollfree' => '/^\\d{7}$/',
            'premium' => '/^\\d{7}$/',
            'shortcode' => '/^\\d{3}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '689',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-9]\\d{5}$/',
            'fixed' => '/^(?:4(?:[02-9]\\d|1[02-9])|[5689]\\d{2})\\d{3}$/',
            'mobile' => '/^(?:[27]\\d{2}|3[0-79]\\d|411)\\d{3}$/',
            'emergency' => '/^1[578]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6}$/',
            'emergency' => '/^\\d{2}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '375',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-4]\\d{8}|[89]\\d{9,10}$/',
            'fixed' => '/^(?:1(?:5(?:1[1-5]|2\\d|6[2-4]|9[1-7])|6(?:[235]\\d|4[1-7])|7\\d{2})|2(?:1(?:[246]\\d|3[0-35-9]|5[1-9])|2(?:[235]\\d|4[0-8])|3(?:2\\d|3[02-79]|4[024-7]|5[0-7])))\\d{5}$/',
            'mobile' => '/^(?:2(?:5[5679]|9[1-9])|33\\d|44\\d)\\d{6}$/',
            'tollfree' => '/^8(?:0[13]|20\\d)\\d{7}$/',
            'premium' => '/^(?:810|902)\\d{7}$/',
            'emergency' => '/^1(?:0[123]|12)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,11}$/',
            'fixed' => '/^\\d{7,9}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{10,11}$/',
            'premium' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '1',
    'patterns' => array(
        'national' => array(
            'general' => '/^[5689]\d{9}$/',
            'fixed' => '/^6846(?:22|33|44|55|77|88|9[19])\d{4}$/',
            'mobile' => '/^684(?:733|258)\d{4}$/',
            'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\d{6}$/',
            'premium' => '/^900[2-9]\d{6}$/',
            'personal' => '/^5(?:00|33|44)[2-9]\d{6}$/',
            'emergency' => '/^911$/',
        ),
        'possible' => array(
            'general' => '/^\d{7}(?:\d{3})?$/',
            'mobile' => '/^\d{10}$/',
            'tollfree' => '/^\d{10}$/',
            'premium' => '/^\d{10}$/',
            'personal' => '/^\d{10}$/',
            'emergency' => '/^\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '255',
    'patterns' => array(
        'national' => array(
            'general' => '/^\\d{9}$/',
            'fixed' => '/^2[2-8]\\d{7}$/',
            'mobile' => '/^(?:6[158]|7[1-9])\\d{7}$/',
            'tollfree' => '/^80[08]\\d{6}$/',
            'premium' => '/^90\\d{7}$/',
            'shared' => '/^8(?:40|6[01])\\d{6}$/',
            'voip' => '/^41\\d{7}$/',
            'emergency' => '/^11[12]|999$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,9}$/',
            'fixed' => '/^\\d{7,9}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{9}$/',
            'premium' => '/^\\d{9}$/',
            'shared' => '/^\\d{9}$/',
            'voip' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '381',
    'patterns' => array(
        'national' => array(
            'general' => '/^[126-9]\\d{4,11}|3(?:[0-79]\\d{3,10}|8[2-9]\\d{2,9})$/',
            'fixed' => '/^(?:1(?:[02-9][2-9]|1[1-9])\\d|2(?:[0-24-7][2-9]\\d|[389](?:0[2-9]|[2-9]\\d))|3(?:[0-8][2-9]\\d|9(?:[2-9]\\d|0[2-9])))\\d{3,8}$/',
            'mobile' => '/^6(?:[0-689]|7\\d)\\d{6,7}$/',
            'tollfree' => '/^800\\d{3,9}$/',
            'premium' => '/^(?:90[0169]|78\\d)\\d{3,7}$/',
            'uan' => '/^7[06]\\d{4,10}$/',
            'shortcode' => '/^1(?:1(?:[013-9]|\\d(2,4))|[89]\\d{1,4})$/',
            'emergency' => '/^112|9[234]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5,12}$/',
            'fixed' => '/^\\d{5,12}$/',
            'mobile' => '/^\\d{8,10}$/',
            'tollfree' => '/^\\d{6,12}$/',
            'premium' => '/^\\d{6,12}$/',
            'uan' => '/^\\d{6,12}$/',
            'shortcode' => '/^\\d{3,6}$/',
            'emergency' => '/^\\d{2,3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '853',
    'patterns' => array(
        'national' => array(
            'general' => '/^[268]\\d{7}$/',
            'fixed' => '/^(?:28[2-57-9]|8[2-57-9]\\d)\\d{5}$/',
            'mobile' => '/^6[236]\\d{6}$/',
            'emergency' => '/^999$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '691',
    'patterns' => array(
        'national' => array(
            'general' => '/^[39]\\d{6}$/',
            'fixed' => '/^3[2357]0[1-9]\\d{3}|9[2-6]\\d{5}$/',
            'mobile' => '/^3[2357]0[1-9]\\d{3}|9[2-7]\\d{5}$/',
            'emergency' => '/^911|320221$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}$/',
            'emergency' => '/^\\d{3}(?:\\d{3})?$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '1',
    'patterns' => array(
        'national' => array(
            'general' => '/^[5789]\\d{9}$/',
            'fixed' => '/^(?:787|939)[2-9]\\d{6}$/',
            'mobile' => '/^(?:787|939)[2-9]\\d{6}$/',
            'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\\d{6}$/',
            'premium' => '/^900[2-9]\\d{6}$/',
            'personal' => '/^5(?:00|33|44)[2-9]\\d{6}$/',
            'emergency' => '/^911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}(?:\\d{3})?$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'personal' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '370',
    'patterns' => array(
        'national' => array(
            'general' => '/^[3-9]\\d{7}$/',
            'fixed' => '/^(?:3[1478]|4[124-6]|52)\\d{6}$/',
            'mobile' => '/^6\\d{7}$/',
            'tollfree' => '/^800\\d{5}$/',
            'premium' => '/^9(?:0[0239]|10)\\d{5}$/',
            'personal' => '/^700\\d{5}$/',
            'shared' => '/^808\\d{5}$/',
            'uan' => '/^70[67]\\d{5}$/',
            'emergency' => '/^0(?:11?|22?|33?)|1(?:0[123]|12)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
            'emergency' => '/^\\d{2,3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '241',
    'patterns' => array(
        'national' => array(
            'general' => '/^[01]\\d{6,7}$/',
            'fixed' => '/^1\\d{6}$/',
            'mobile' => '/^0[2-7]\\d{6}$/',
            'emergency' => '/^1730|18|13\\d{2}$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,8}$/',
            'emergency' => '/^\\d{2,4}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '975',
    'patterns' => array(
        'national' => array(
            'general' => '/^[1-8]\\d{6,7}$/',
            'fixed' => '/^(?:2[3-6]|[34][5-7]|5[236]|6[2-46]|7[246]|8[2-4])\\d{5}$/',
            'mobile' => '/^[17]7\\d{6}$/',
            'emergency' => '/^11[023]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,8}$/',
            'fixed' => '/^\\d{6,7}$/',
            'mobile' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '594',
    'patterns' => array(
        'national' => array(
            'general' => '/^[56]\\d{8}$/',
            'fixed' => '/^594(?:10|2[012457-9]|3[0-57-9]|4[3-9]|5[7-9]|6[0-3]|9[014])\\d{4}$/',
            'mobile' => '/^694(?:[04][0-7]|1[0-5]|2[0-46-9]|38|9\\d)\\d{4}$/',
            'emergency' => '/^1[578]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{9}$/',
            'emergency' => '/^\\d{2}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '354',
    'patterns' => array(
        'national' => array(
            'general' => '/^[4-9]\\d{6}|38\\d{7}$/',
            'fixed' => '/^(?:4(?:[14][0-245]|2[0-7]|[37][0-8]|5[0-3568]|6\\d|8[0-36-8])|5(?:05|[156]\\d|2[02578]|3[013-7]|4[03-7]|7[0-2578]|8[0-35-9]|9[013-689])|87[23])\\d{4}$/',
            'mobile' => '/^38[59]\\d{6}|(?:6(?:1[0-8]|3[0-27-9]|4[0-27]|5[0-29]|[67][0-69]|9\\d)|7(?:5[057]|7\\d|8[0-3])|8(?:2[0-5]|[469]\\d|5[1-9]))\\d{4}$/',
            'tollfree' => '/^800\\d{4}$/',
            'premium' => '/^90\\d{5}$/',
            'voip' => '/^49[0-24-79]\\d{4}$/',
            'voicemail' => '/^388\\d{6}|(?:6(?:2[0-8]|49|8\\d)|8(?:2[6-9]|[38]\\d|50|7[014-9])|95[48])\\d{4}$/',
            'emergency' => '/^112$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7,9}$/',
            'fixed' => '/^\\d{7}$/',
            'tollfree' => '/^\\d{7}$/',
            'premium' => '/^\\d{7}$/',
            'voip' => '/^\\d{7}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '249',
    'patterns' => array(
        'national' => array(
            'general' => '/^[19]\\d{8}$/',
            'fixed' => '/^1(?:[125]\\d|8[3567])\\d{6}$/',
            'mobile' => '/^9[012569]\\d{7}$/',
            'emergency' => '/^999$/',
        ),
        'possible' => array(
            'general' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '599',
    'patterns' => array(
        'national' => array(
            'general' => '/^[347]\\d{6}$/',
            'fixed' => '/^(?:318[023]|416[0239]|7(?:1[578]|50)\\d)\\d{3}$/',
            'mobile' => '/^(?:318[1456]|416[15-8]|7(?:0[01]|[89]\\d)\\d)\\d{3}|$/',
            'emergency' => '/^112|911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '216',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-57-9]\\d{7}$/',
            'fixed' => '/^(?:3[012]|7\\d)\\d{6}$/',
            'mobile' => '/^(?:[259]\\d|4[0-2])\\d{6}$/',
            'premium' => '/^8[0128]\\d{6}$/',
            'emergency' => '/^19[078]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '1',
    'patterns' => array(
        'national' => array(
            'general' => '/^[4589]\\d{9}$/',
            'fixed' => '/^441(?:2(?:02|23|61|[3479]\\d)|[46]\\d{2}|5(?:4\\d|60|89)|824)\\d{4}$/',
            'mobile' => '/^441(?:[37]\\d|5[0-39])\\d{5}$/',
            'tollfree' => '/^8(?:00|55|66|77|88)[2-9]\\d{6}$/',
            'premium' => '/^900[2-9]\\d{6}$/',
            'personal' => '/^5(?:00|33|44)[2-9]\\d{6}$/',
            'emergency' => '/^911$/',
        ),
        'possible' => array(
            'general' => '/^\\d{7}(?:\\d{3})?$/',
            'mobile' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'personal' => '/^\\d{10}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '852',
    'patterns' => array(
        'national' => array(
            'general' => '/^[235-7]\\d{7}|8\\d{7,8}|9\\d{4,10}$/',
            'fixed' => '/^(?:[23]\\d|5[78])\\d{6}$/',
            'mobile' => '/^(?:5[1-69]\\d|6\\d{2}|9(?:0[1-9]|[1-8]\\d))\\d{5}$/',
            'pager' => '/^7\\d{7}$/',
            'tollfree' => '/^800\\d{6}$/',
            'premium' => '/^900(?:[0-24-9]\\d{7}|3\\d{1,4})$/',
            'personal' => '/^8[1-3]\\d{6}$/',
            'emergency' => '/^112|99[29]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5,11}$/',
            'fixed' => '/^\\d{8}$/',
            'mobile' => '/^\\d{8}$/',
            'pager' => '/^\\d{8}$/',
            'tollfree' => '/^\\d{9}$/',
            'premium' => '/^\\d{5,11}$/',
            'personal' => '/^\\d{8}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '44',
    'patterns' => array(
        'national' => array(
            'general' => '/^[135789]\\d{6,9}$/',
            'fixed' => '/^1624\\d{6}$/',
            'mobile' => '/^7[569]24\\d{6}$/',
            'tollfree' => '/^808162\\d{4}$/',
            'premium' => '/^(?:872299|90[0167]624)\\d{4}$/',
            'shared' => '/^8(?:4(?:40[49]06|5624\\d)|70624\\d)\\d{3}$/',
            'personal' => '/^70\\d{8}$/',
            'voip' => '/^56\\d{8}$/',
            'uan' => '/^3(?:08162\\d|3\\d{5}|4(?:40[49]06|5624\\d)|7(?:0624\\d|2299\\d))\\d{3}|55\\d{8}$/',
            'shortcode' => '/^1\\d{2}(?:\\d{3})?$/',
            'emergency' => '/^999$/',
        ),
        'possible' => array(
            'general' => '/^\\d{6,10}$/',
            'mobile' => '/^\\d{10}$/',
            'tollfree' => '/^\\d{10}$/',
            'premium' => '/^\\d{10}$/',
            'shared' => '/^\\d{10}$/',
            'personal' => '/^\\d{10}$/',
            'voip' => '/^\\d{10}$/',
            'uan' => '/^\\d{10}$/',
            'shortcode' => '/^\\d{3,6}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '380',
    'patterns' => array(
        'national' => array(
            'general' => '/^[3-689]\\d{8}$/',
            'fixed' => '/^(?:3[1-8]|4[13-8]|5[1-7]|6[12459])\\d{7}$/',
            'mobile' => '/^(?:39|50|6[36-8]|9[1-9])\\d{7}$/',
            'tollfree' => '/^800\\d{6}$/',
            'premium' => '/^900\\d{6}$/',
            'emergency' => '/^1(?:0[123]|12)$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5,9}$/',
            'mobile' => '/^\\d{9}$/',
            'tollfree' => '/^\\d{9}$/',
            'premium' => '/^\\d{9}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '222',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-48]\\d{7}$/',
            'fixed' => '/^25[08]\\d{5}|35\\d{6}|45[1-7]\\d{5}$/',
            'mobile' => '/^(?:2(?:2\\d|70)|3(?:3\\d|6[1-36]|7[1-3])|4(?:4\\d|6[0457-9]|7[4-9]))\\d{5}$/',
            'tollfree' => '/^800\\d{5}$/',
            'emergency' => '/^1[78]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{8}$/',
            'emergency' => '/^\\d{2}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

return array(
    'code' => '685',
    'patterns' => array(
        'national' => array(
            'general' => '/^[2-8]\\d{4,6}$/',
            'fixed' => '/^(?:[2-5]\\d|6[1-9]|84\\d{2})\\d{3}$/',
            'mobile' => '/^(?:60|7[25-7]\\d)\\d{4}$/',
            'tollfree' => '/^800\\d{3}$/',
            'emergency' => '/^99[4-6]$/',
        ),
        'possible' => array(
            'general' => '/^\\d{5,7}$/',
            'fixed' => '/^\\d{5,7}$/',
            'mobile' => '/^\\d{6,7}$/',
            'tollfree' => '/^\\d{6}$/',
            'emergency' => '/^\\d{3}$/',
        ),
    ),
);
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Validator;

use Locale;
use IntlDateFormatter;
use Traversable;
use Zend\I18n\Exception as I18nException;
use Zend\Validator\AbstractValidator;
use Zend\Validator\Exception as ValidatorException;

class DateTime extends AbstractValidator
{
    const INVALID           = 'datetimeInvalid';
    const INVALID_DATETIME  = 'datetimeInvalidDateTime';

    /**
     * @var array
     */
    protected $messageTemplates = array(
        self::INVALID           => "Invalid type given. String expected",
        self::INVALID_DATETIME  => "The input does not appear to be a valid datetime",
    );

    /**
     * Optional locale
     *
     * @var string|null
     */
    protected $locale;

    /**
     * @var int
     */
    protected $dateType;

    /**
     * @var int
     */
    protected $timeType;

    /**
     * Optional timezone
     *
     * @var string
     */
    protected $timezone;

    /**
     * @var string
     */
    protected $pattern;

    /**
     * @var int
     */
    protected $calendar;

    /**
     * @var IntlDateFormatter
     */
    protected $formatter;

    /**
     * Is the formatter invalidated
     *
     * Invalidation occurs when immutable properties are changed
     *
     * @var bool
     */
    protected $invalidateFormatter = false;

    /**
     * Constructor for the Date validator
     *
     * @param array|Traversable $options
     * @throws I18nException\ExtensionNotLoadedException if ext/intl is not present
     */
    public function __construct($options = array())
    {
        if (!extension_loaded('intl')) {
            throw new I18nException\ExtensionNotLoadedException(sprintf(
                '%s component requires the intl PHP extension',
                __NAMESPACE__
            ));
        }

        // Delaying initialization until we know ext/intl is available
        $this->dateType = IntlDateFormatter::NONE;
        $this->timeType = IntlDateFormatter::NONE;
        $this->calendar = IntlDateFormatter::GREGORIAN;

        parent::__construct($options);

        if (null === $this->locale) {
            $this->locale = Locale::getDefault();
        }
        if (null === $this->timezone) {
            $this->timezone = date_default_timezone_get();
        }
    }

    /**
     * Sets the calendar to be used by the IntlDateFormatter
     *
     * @param int|null $calendar
     * @return DateTime provides fluent interface
     */
    public function setCalendar($calendar)
    {
        $this->calendar = $calendar;

        return $this;
    }

    /**
     * Returns the calendar to by the IntlDateFormatter
     *
     * @return int
     */
    public function getCalendar()
    {
        return ($this->formatter && !$this->invalidateFormatter) ? $this->getIntlDateFormatter()->getCalendar() : $this->calendar;
    }

    /**
     * Sets the date format to be used by the IntlDateFormatter
     *
     * @param int|null $dateType
     * @return DateTime provides fluent interface
     */
    public function setDateType($dateType)
    {
        $this->dateType          = $dateType;
        $this->invalidateFormatter = true;

        return $this;
    }

    /**
     * Returns the date format used by the IntlDateFormatter
     *
     * @return int
     */
    public function getDateType()
    {
        return $this->dateType;
    }

    /**
     * Sets the pattern to be used by the IntlDateFormatter
     *
     * @param string|null $pattern
     * @return DateTime provides fluent interface
     */
    public function setPattern($pattern)
    {
        $this->pattern = $pattern;

        return $this;
    }

    /**
     * Returns the pattern used by the IntlDateFormatter
     *
     * @return string
     */
    public function getPattern()
    {
        return ($this->formatter && !$this->invalidateFormatter) ? $this->getIntlDateFormatter()->getPattern() : $this->pattern;
    }

    /**
     * Sets the time format to be used by the IntlDateFormatter
     *
     * @param int|null $timeType
     * @return DateTime provides fluent interface
     */
    public function setTimeType($timeType)
    {
        $this->timeType          = $timeType;
        $this->invalidateFormatter = true;

        return $this;
    }

    /**
     * Returns the time format used by the IntlDateFormatter
     *
     * @return int
     */
    public function getTimeType()
    {
        return $this->timeType;
    }

    /**
     * Sets the timezone to be used by the IntlDateFormatter
     *
     * @param string|null $timezone
     * @return DateTime provides fluent interface
     */
    public function setTimezone($timezone)
    {
        $this->timezone = $timezone;

        return $this;
    }

    /**
     * Returns the timezone used by the IntlDateFormatter or the system default if none given
     *
     * @return string
     */
    public function getTimezone()
    {
        return ($this->formatter && !$this->invalidateFormatter) ? $this->getIntlDateFormatter()->getTimeZoneId() : $this->timezone;
    }

    /**
     * Sets the locale to be used by the IntlDateFormatter
     *
     * @param string|null $locale
     * @return DateTime provides fluent interface
     */
    public function setLocale($locale)
    {
        $this->locale              = $locale;
        $this->invalidateFormatter = true;

        return $this;
    }

    /**
     * Returns the locale used by the IntlDateFormatter or the system default if none given
     *
     * @return string
     */
    public function getLocale()
    {
        return $this->locale;
    }

    /**
     * Returns true if and only if $value is a floating-point value
     *
     * @param  string                             $value
     * @return bool
     * @throws ValidatorException\InvalidArgumentException
     */
    public function isValid($value)
    {
        if (!is_string($value)) {
            $this->error(self::INVALID);

            return false;
        }

        $this->setValue($value);

        $formatter = $this->getIntlDateFormatter();

        if (intl_is_failure($formatter->getErrorCode())) {
            throw new ValidatorException\InvalidArgumentException("Invalid locale string given");
        }

        $position   = 0;
        $parsedDate = $formatter->parse($value, $position);

        if (intl_is_failure($formatter->getErrorCode())) {
            $this->error(self::INVALID_DATETIME);

            return false;
        }

        if ($position != strlen($value)) {
            $this->error(self::INVALID_DATETIME);

            return false;
        }

        return true;
    }

    /**
     * Returns a non lenient configured IntlDateFormatter
     *
     * @return IntlDateFormatter
     */
    protected function getIntlDateFormatter()
    {
        if ($this->formatter == null || $this->invalidateFormatter) {
            $this->formatter = new IntlDateFormatter($this->getLocale(), $this->getDateType(), $this->getTimeType(),
                $this->getTimezone(), $this->getCalendar(), $this->getPattern());

            $this->formatter->setLenient(false);

            $this->invalidateFormatter = false;
        }

        return $this->formatter;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\View;

use Zend\ServiceManager\ConfigInterface;
use Zend\ServiceManager\ServiceManager;

/**
 * Service manager configuration for i18n view helpers.
 */
class HelperConfig implements ConfigInterface
{
    /**
     * Pre-aliased view helpers
     *
     * @var array
     */
    protected $invokables = array(
        'currencyformat'  => 'Zend\I18n\View\Helper\CurrencyFormat',
        'dateformat'      => 'Zend\I18n\View\Helper\DateFormat',
        'numberformat'    => 'Zend\I18n\View\Helper\NumberFormat',
        'plural'          => 'Zend\I18n\View\Helper\Plural',
        'translate'       => 'Zend\I18n\View\Helper\Translate',
        'translateplural' => 'Zend\I18n\View\Helper\TranslatePlural',
    );

    /**
     * Configure the provided service manager instance with the configuration
     * in this class.
     *
     * @param  ServiceManager $serviceManager
     * @return void
     */
    public function configureServiceManager(ServiceManager $serviceManager)
    {
        foreach ($this->invokables as $name => $service) {
            $serviceManager->setInvokableClass($name, $service);
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\View\Helper;

use Locale;
use NumberFormatter;
use Zend\I18n\Exception;
use Zend\View\Helper\AbstractHelper;

/**
 * View helper for formatting dates.
 */
class NumberFormat extends AbstractHelper
{
    /**
     * number of decimals to use.
     *
     * @var int
     */
    protected $decimals;

    /**
     * NumberFormat style to use
     *
     * @var int
     */
    protected $formatStyle;

    /**
     * NumberFormat type to use
     *
     * @var int
     */
    protected $formatType;

    /**
     * Formatter instances
     *
     * @var array
     */
    protected $formatters = array();

    /**
     * Locale to use instead of the default
     *
     * @var string
     */
    protected $locale;

    /**
     * @throws Exception\ExtensionNotLoadedException if ext/intl is not present
     */
    public function __construct()
    {
        if (!extension_loaded('intl')) {
            throw new Exception\ExtensionNotLoadedException(sprintf(
                '%s component requires the intl PHP extension',
                __NAMESPACE__
            ));
        }
    }

    /**
     * Format a number
     *
     * @param  int|float $number
     * @param  int       $formatStyle
     * @param  int       $formatType
     * @param  string    $locale
     * @param  int       $decimals
     * @return string
     */
    public function __invoke(
        $number,
        $formatStyle = null,
        $formatType  = null,
        $locale      = null,
        $decimals    = null
    ) {
        if (null === $locale) {
            $locale = $this->getLocale();
        }
        if (null === $formatStyle) {
            $formatStyle = $this->getFormatStyle();
        }
        if (null === $formatType) {
            $formatType = $this->getFormatType();
        }
        if (!is_int($decimals) || $decimals < 0) {
            $decimals = $this->getDecimals();
        }

        $formatterId = md5($formatStyle . "\0" . $locale . "\0" . $decimals);

        if (!isset($this->formatters[$formatterId])) {
            $this->formatters[$formatterId] = new NumberFormatter(
                $locale,
                $formatStyle
            );

            if ($decimals !== null) {
                $this->formatters[$formatterId]->setAttribute(NumberFormatter::MIN_FRACTION_DIGITS, $decimals);
                $this->formatters[$formatterId]->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, $decimals);
            }
        }

        return $this->formatters[$formatterId]->format($number, $formatType);
    }

    /**
     * Set format style to use instead of the default
     *
     * @param  int $formatStyle
     * @return NumberFormat
     */
    public function setFormatStyle($formatStyle)
    {
        $this->formatStyle = (int) $formatStyle;
        return $this;
    }

    /**
     * Get the format style to use
     *
     * @return int
     */
    public function getFormatStyle()
    {
        if (null === $this->formatStyle) {
            $this->formatStyle = NumberFormatter::DECIMAL;
        }

        return $this->formatStyle;
    }

    /**
     * Set format type to use instead of the default
     *
     * @param  int $formatType
     * @return NumberFormat
     */
    public function setFormatType($formatType)
    {
        $this->formatType = (int) $formatType;
        return $this;
    }

    /**
     * Get the format type to use
     *
     * @return int
     */
    public function getFormatType()
    {
        if (null === $this->formatType) {
            $this->formatType = NumberFormatter::TYPE_DEFAULT;
        }
        return $this->formatType;
    }

    /**
     * Set number of decimals to use instead of the default.
     *
     * @param  int $decimals
     * @return NumberFormat
     */
    public function setDecimals($decimals)
    {
        $this->decimals = $decimals;
        return $this;
    }

    /**
     * Get number of decimals.
     *
     * @return int
     */
    public function getDecimals()
    {
        return $this->decimals;
    }

    /**
     * Set locale to use instead of the default.
     *
     * @param  string $locale
     * @return NumberFormat
     */
    public function setLocale($locale)
    {
        $this->locale = (string) $locale;
        return $this;
    }

    /**
     * Get the locale to use
     *
     * @return string|null
     */
    public function getLocale()
    {
        if ($this->locale === null) {
            $this->locale = Locale::getDefault();
        }

        return $this->locale;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\View\Helper;

use Locale;
use NumberFormatter;
use Zend\I18n\Exception;
use Zend\View\Helper\AbstractHelper;

/**
 * View helper for formatting currency.
 */
class CurrencyFormat extends AbstractHelper
{
    /**
     * The 3-letter ISO 4217 currency code indicating the currency to use
     *
     * @var string
     */
    protected $currencyCode;

    /**
     * Formatter instances
     *
     * @var array
     */
    protected $formatters = array();

    /**
     * Locale to use instead of the default
     *
     * @var string
     */
    protected $locale;

    /**
     * Currency pattern
     *
     * @var string
     */
    protected $currencyPattern;

    /**
     * If set to true, the currency will be returned with two decimals
     *
     * @var bool
     */
    protected $showDecimals = true;

    /**
     * @throws Exception\ExtensionNotLoadedException if ext/intl is not present
     */
    public function __construct()
    {
        if (!extension_loaded('intl')) {
            throw new Exception\ExtensionNotLoadedException(sprintf(
                '%s component requires the intl PHP extension',
                __NAMESPACE__
            ));
        }
    }

    /**
     * Format a number
     *
     * @param  float  $number
     * @param  string $currencyCode
     * @param  bool   $showDecimals
     * @param  string $locale
     * @param  string $pattern
     * @return string
     */
    public function __invoke(
        $number,
        $currencyCode = null,
        $showDecimals = null,
        $locale       = null,
        $pattern      = null
    ) {
        if (null === $locale) {
            $locale = $this->getLocale();
        }
        if (null === $currencyCode) {
            $currencyCode = $this->getCurrencyCode();
        }
        if (null === $showDecimals) {
            $showDecimals = $this->shouldShowDecimals();
        }
        if (null === $pattern) {
            $pattern = $this->getCurrencyPattern();
        }

        return $this->formatCurrency($number, $currencyCode, $showDecimals, $locale, $pattern);
    }

    /**
     * Format a number
     *
     * @param  float  $number
     * @param  string $currencyCode
     * @param  bool   $showDecimals
     * @param  string $locale
     * @param  string $pattern
     * @return string
     */
    protected function formatCurrency(
        $number,
        $currencyCode,
        $showDecimals,
        $locale,
        $pattern
    ) {
        $formatterId = md5($locale);

        if (!isset($this->formatters[$formatterId])) {
            $this->formatters[$formatterId] = new NumberFormatter(
                $locale,
                NumberFormatter::CURRENCY
            );
        }

        if ($pattern !== null) {
            $this->formatters[$formatterId]->setPattern($pattern);
        }

        if ($showDecimals) {
            $this->formatters[$formatterId]->setAttribute(NumberFormatter::FRACTION_DIGITS, 2);
        } else {
            $this->formatters[$formatterId]->setAttribute(NumberFormatter::FRACTION_DIGITS, 0);
        }

        return $this->formatters[$formatterId]->formatCurrency(
            $number, $currencyCode
        );
    }

    /**
     * The 3-letter ISO 4217 currency code indicating the currency to use
     *
     * @param  string $currencyCode
     * @return CurrencyFormat
     */
    public function setCurrencyCode($currencyCode)
    {
        $this->currencyCode = $currencyCode;
        return $this;
    }

    /**
     * Get the 3-letter ISO 4217 currency code indicating the currency to use
     *
     * @return string
     */
    public function getCurrencyCode()
    {
        return $this->currencyCode;
    }


    /**
     * Set the currency pattern
     *
     * @param  string $currencyPattern
     * @return CurrencyFormat
     */
    public function setCurrencyPattern($currencyPattern)
    {
        $this->currencyPattern = $currencyPattern;
        return $this;
    }

    /**
     * Get the currency pattern
     *
     * @return string
     */
    public function getCurrencyPattern()
    {
        return $this->currencyPattern;
    }

    /**
     * Set locale to use instead of the default
     *
     * @param  string $locale
     * @return CurrencyFormat
     */
    public function setLocale($locale)
    {
        $this->locale = (string) $locale;
        return $this;
    }

    /**
     * Get the locale to use
     *
     * @return string|null
     */
    public function getLocale()
    {
        if ($this->locale === null) {
            $this->locale = Locale::getDefault();
        }

        return $this->locale;
    }

    /**
     * Set if the view helper should show two decimals
     *
     * @param  bool $showDecimals
     * @return CurrencyFormat
     */
    public function setShouldShowDecimals($showDecimals)
    {
        $this->showDecimals = (bool) $showDecimals;
        return $this;
    }

    /**
     * Get if the view helper should show two decimals
     *
     * @return bool
     */
    public function shouldShowDecimals()
    {
        return $this->showDecimals;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\View\Helper;

use Zend\I18n\Exception;

/**
 * View helper for translating plural messages.
 */
class TranslatePlural extends AbstractTranslatorHelper
{
    /**
     * Translate a plural message
     *
     * @param  string  $singular
     * @param  string  $plural
     * @param  int $number
     * @param  string  $textDomain
     * @param  string  $locale
     * @throws Exception\RuntimeException
     * @return string
     */
    public function __invoke(
        $singular,
        $plural,
        $number,
        $textDomain = null,
        $locale = null
    )
    {
        $translator = $this->getTranslator();
        if (null === $translator) {
            throw new Exception\RuntimeException('Translator has not been set');
        }
        if (null === $textDomain) {
            $textDomain = $this->getTranslatorTextDomain();
        }

        return $translator->translatePlural($singular, $plural, $number, $textDomain, $locale);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\View\Helper;

use DateTime;
use IntlDateFormatter;
use Locale;
use Zend\I18n\Exception;
use Zend\View\Helper\AbstractHelper;

/**
 * View helper for formatting dates.
 */
class DateFormat extends AbstractHelper
{
    /**
     * Locale to use instead of the default
     *
     * @var string
     */
    protected $locale;

    /**
     * Timezone to use
     *
     * @var string
     */
    protected $timezone;

    /**
     * Formatter instances
     *
     * @var array
     */
    protected $formatters = array();

    /**
     * @throws Exception\ExtensionNotLoadedException if ext/intl is not present
     */
    public function __construct()
    {
        if (!extension_loaded('intl')) {
            throw new Exception\ExtensionNotLoadedException(sprintf(
                '%s component requires the intl PHP extension',
                __NAMESPACE__
            ));
        }
    }

    /**
     * Format a date
     *
     * @param  DateTime|int|array $date
     * @param  int                    $dateType
     * @param  int                    $timeType
     * @param  string                 $locale
     * @param  string|null            $pattern
     * @return string
     */
    public function __invoke(
        $date,
        $dateType = IntlDateFormatter::NONE,
        $timeType = IntlDateFormatter::NONE,
        $locale   = null,
        $pattern  = null
    ) {
        if ($locale === null) {
            $locale = $this->getLocale();
        }

        $timezone    = $this->getTimezone();
        $formatterId = md5($dateType . "\0" . $timeType . "\0" . $locale ."\0" . $pattern);

        if (!isset($this->formatters[$formatterId])) {
            $this->formatters[$formatterId] = new IntlDateFormatter(
                $locale,
                $dateType,
                $timeType,
                $timezone,
                IntlDateFormatter::GREGORIAN,
                $pattern
            );
        }

        // DateTime support for IntlDateFormatter::format() was only added in 5.3.4
        if ($date instanceof DateTime && (PHP_VERSION_ID < 50304)) {
            $date = $date->getTimestamp();
        }

        return $this->formatters[$formatterId]->format($date);
    }

    /**
     * Set locale to use instead of the default
     *
     * @param  string $locale
     * @return DateFormat
     */
    public function setLocale($locale)
    {
        $this->locale = (string) $locale;
        return $this;
    }

    /**
     * Get the locale to use
     *
     * @return string|null
     */
    public function getLocale()
    {
        if ($this->locale === null) {
            $this->locale = Locale::getDefault();
        }

        return $this->locale;
    }

    /**
     * Set timezone to use instead of the default
     *
     * @param  string $timezone
     * @return DateFormat
     */
    public function setTimezone($timezone)
    {
        $this->timezone = (string) $timezone;

        // The method setTimeZoneId is deprecated as of PHP 5.5.0
        $setTimeZoneMethodName = (PHP_VERSION_ID < 50500) ? 'setTimeZoneId' : 'setTimeZone';

        foreach ($this->formatters as $formatter) {
            $formatter->$setTimeZoneMethodName($this->timezone);
        }

        return $this;
    }

    /**
     * Get the timezone to use
     *
     * @return string|null
     */
    public function getTimezone()
    {
        if (!$this->timezone) {
            return date_default_timezone_get();
        }

        return $this->timezone;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\View\Helper;

use Zend\I18n\Exception;
use Zend\I18n\Translator\Plural\Rule as PluralRule;
use Zend\View\Helper\AbstractHelper;

/**
 * Helper for rendering text based on a count number (like the I18n plural translation helper, but when translation
 * is not needed).
 *
 * Please note that we did not write any hard-coded rules for languages, as languages can evolve, we prefered to
 * let the developer define the rules himself, instead of potentially break applications if we change rules in the
 * future.
 *
 * However, you can find most of the up-to-date plural rules for most languages in those links:
 *      - http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html
 *      - https://developer.mozilla.org/en-US/docs/Localization_and_Plurals
 */
class Plural extends AbstractHelper
{
    /**
     * Plural rule to use
     *
     * @var PluralRule
     */
    protected $rule;

    /**
     * @throws Exception\ExtensionNotLoadedException if ext/intl is not present
     */
    public function __construct()
    {
        if (!extension_loaded('intl')) {
            throw new Exception\ExtensionNotLoadedException(sprintf(
                '%s component requires the intl PHP extension',
                __NAMESPACE__
            ));
        }
    }

    /**
     * Given an array of strings, a number and, if wanted, an optional locale (the default one is used
     * otherwise), this picks the right string according to plural rules of the locale
     *
     * @param  array|string $strings
     * @param  int          $number
     * @throws Exception\InvalidArgumentException
     * @return string
     */
    public function __invoke($strings, $number)
    {
        if (null === $this->getPluralRule()) {
            throw new Exception\InvalidArgumentException(sprintf(
                'No plural rule was set'
            ));
        }

        if (!is_array($strings)) {
            $strings = (array) $strings;
        }

        $pluralIndex = $this->getPluralRule()->evaluate($number);

        return $strings[$pluralIndex];
    }

    /**
     * Set the plural rule to use
     *
     * @param  PluralRule|string $pluralRule
     * @return Plural
     */
    public function setPluralRule($pluralRule)
    {
        if (!$pluralRule instanceof PluralRule) {
            $pluralRule = PluralRule::fromString($pluralRule);
        }

        $this->rule = $pluralRule;

        return $this;
    }

    /**
     * Get the plural rule to  use
     *
     * @return PluralRule
     */
    public function getPluralRule()
    {
        return $this->rule;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\View\Helper;

use Zend\I18n\Translator\Translator;
use Zend\I18n\Translator\TranslatorAwareInterface;
use Zend\View\Helper\AbstractHelper;

abstract class AbstractTranslatorHelper extends AbstractHelper implements
    TranslatorAwareInterface
{
    /**
     * Translator (optional)
     *
     * @var Translator
     */
    protected $translator;

    /**
     * Translator text domain (optional)
     *
     * @var string
     */
    protected $translatorTextDomain = 'default';

    /**
     * Whether translator should be used
     *
     * @var bool
     */
    protected $translatorEnabled = true;

    /**
     * Sets translator to use in helper
     *
     * @param  Translator $translator  [optional] translator.
     *                                 Default is null, which sets no translator.
     * @param  string     $textDomain  [optional] text domain
     *                                 Default is null, which skips setTranslatorTextDomain
     * @return AbstractTranslatorHelper
     */
    public function setTranslator(Translator $translator = null, $textDomain = null)
    {
        $this->translator = $translator;
        if (null !== $textDomain) {
            $this->setTranslatorTextDomain($textDomain);
        }

        return $this;
    }

    /**
     * Returns translator used in helper
     *
     * @return Translator|null
     */
    public function getTranslator()
    {
        if (! $this->isTranslatorEnabled()) {
            return null;
        }

        return $this->translator;
    }

    /**
     * Checks if the helper has a translator
     *
     * @return bool
     */
    public function hasTranslator()
    {
        return (bool) $this->getTranslator();
    }

    /**
     * Sets whether translator is enabled and should be used
     *
     * @param  bool $enabled
     * @return AbstractTranslatorHelper
     */
    public function setTranslatorEnabled($enabled = true)
    {
        $this->translatorEnabled = (bool) $enabled;
        return $this;
    }

    /**
     * Returns whether translator is enabled and should be used
     *
     * @return bool
     */
    public function isTranslatorEnabled()
    {
        return $this->translatorEnabled;
    }

    /**
     * Set translation text domain
     *
     * @param  string $textDomain
     * @return AbstractTranslatorHelper
     */
    public function setTranslatorTextDomain($textDomain = 'default')
    {
        $this->translatorTextDomain = $textDomain;
        return $this;
    }

    /**
     * Return the translation text domain
     *
     * @return string
     */
    public function getTranslatorTextDomain()
    {
        return $this->translatorTextDomain;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\View\Helper;

use Zend\I18n\Exception;

/**
 * View helper for translating messages.
 */
class Translate extends AbstractTranslatorHelper
{
    /**
     * Translate a message
     *
     * @param  string $message
     * @param  string $textDomain
     * @param  string $locale
     * @throws Exception\RuntimeException
     * @return string
     */
    public function __invoke($message, $textDomain = null, $locale = null)
    {
        $translator = $this->getTranslator();
        if (null === $translator) {
            throw new Exception\RuntimeException('Translator has not been set');
        }
        if (null === $textDomain) {
            $textDomain = $this->getTranslatorTextDomain();
        }

        return $translator->translate($message, $textDomain, $locale);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Filter;

use Locale;
use Zend\Filter\AbstractFilter;
use Zend\I18n\Exception;

abstract class AbstractLocale extends AbstractFilter
{
    /**
     * @throws Exception\ExtensionNotLoadedException if ext/intl is not present
     */
    public function __construct()
    {
        if (!extension_loaded('intl')) {
            throw new Exception\ExtensionNotLoadedException(sprintf(
                '%s component requires the intl PHP extension',
                __NAMESPACE__
            ));
        }
    }

    /**
     * Sets the locale option
     *
     * @param  string|null $locale
     * @return AbstractLocale
     */
    public function setLocale($locale = null)
    {
        $this->options['locale'] = $locale;
        return $this;
    }

    /**
     * Returns the locale option
     *
     * @return string
     */
    public function getLocale()
    {
        if (!isset($this->options['locale'])) {
            $this->options['locale'] = Locale::getDefault();
        }
        return $this->options['locale'];
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Filter;

use NumberFormatter;
use Traversable;
use Zend\I18n\Exception;
use Zend\Stdlib\ErrorHandler;

class NumberFormat extends AbstractLocale
{
    protected $options = array(
        'locale' => null,
        'style'  => NumberFormatter::DEFAULT_STYLE,
        'type'   => NumberFormatter::TYPE_DOUBLE
    );

    /**
     * @var NumberFormatter
     */
    protected $formatter = null;

    /**
     * @param array|Traversable|string|null $localeOrOptions
     * @param int  $style
     * @param int  $type
     */
    public function __construct(
        $localeOrOptions = null,
        $style = NumberFormatter::DEFAULT_STYLE,
        $type = NumberFormatter::TYPE_DOUBLE)
    {
        parent::__construct();
        if ($localeOrOptions !== null) {
            if ($localeOrOptions instanceof Traversable) {
                $localeOrOptions = iterator_to_array($localeOrOptions);
            }

            if (!is_array($localeOrOptions)) {
                $this->setLocale($localeOrOptions);
                $this->setStyle($style);
                $this->setType($type);
            } else {
                $this->setOptions($localeOrOptions);
            }
        }
    }

    /**
     * @param  string|null $locale
     * @return NumberFormat
     */
    public function setLocale($locale = null)
    {
        $this->options['locale'] = $locale;
        $this->formatter = null;
        return $this;
    }

    /**
     * @param  int $style
     * @return NumberFormat
     */
    public function setStyle($style)
    {
        $this->options['style'] = (int) $style;
        $this->formatter = null;
        return $this;
    }

    /**
     * @return int
     */
    public function getStyle()
    {
        return $this->options['style'];
    }

    /**
     * @param  int $type
     * @return NumberFormat
     */
    public function setType($type)
    {
        $this->options['type'] = (int) $type;
        return $this;
    }

    /**
     * @return int
     */
    public function getType()
    {
        return $this->options['type'];
    }

    /**
     * @param  NumberFormatter $formatter
     * @return NumberFormat
     */
    public function setFormatter(NumberFormatter $formatter)
    {
        $this->formatter = $formatter;
        return $this;
    }

    /**
     * @return NumberFormatter
     * @throws Exception\RuntimeException
     */
    public function getFormatter()
    {
        if ($this->formatter === null) {
            $formatter = NumberFormatter::create($this->getLocale(), $this->getStyle());
            if (!$formatter) {
                throw new Exception\RuntimeException(
                    'Can not create NumberFormatter instance; ' . intl_get_error_message()
                );
            }

            $this->formatter = $formatter;
        }

        return $this->formatter;
    }

    /**
     * Defined by Zend\Filter\FilterInterface
     *
     * @see    Zend\Filter\FilterInterface::filter()
     * @param  mixed $value
     * @return mixed
     */
    public function filter($value)
    {
        $formatter = $this->getFormatter();
        $type      = $this->getType();

        if (is_int($value) || is_float($value)) {
            ErrorHandler::start();
            $result = $formatter->format($value, $type);
            ErrorHandler::stop();
        } else {
            $value = str_replace(array("\xC2\xA0", ' '), '', $value);
            ErrorHandler::start();
            $result = $formatter->parse($value, $type);
            ErrorHandler::stop();
        }

        if ($result === false) {
            return $value;
        }

        return str_replace("\xC2\xA0", ' ', $result);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Filter;

use Locale;
use Traversable;

class Alnum extends AbstractLocale
{
    /**
     * @var array
     */
    protected $options = array(
        'locale'            => null,
        'allow_white_space' => false,
    );

    /**
     * Sets default option values for this instance
     *
     * @param array|Traversable|bool|null $allowWhiteSpaceOrOptions
     * @param string|null $locale
     */
    public function __construct($allowWhiteSpaceOrOptions = null, $locale = null)
    {
        parent::__construct();
        if ($allowWhiteSpaceOrOptions !== null) {
            if (static::isOptions($allowWhiteSpaceOrOptions)) {
                $this->setOptions($allowWhiteSpaceOrOptions);
            } else {
                $this->setAllowWhiteSpace($allowWhiteSpaceOrOptions);
                $this->setLocale($locale);
            }
        }
    }

    /**
     * Sets the allowWhiteSpace option
     *
     * @param  bool $flag
     * @return Alnum Provides a fluent interface
     */
    public function setAllowWhiteSpace($flag = true)
    {
        $this->options['allow_white_space'] = (bool) $flag;
        return $this;
    }

    /**
     * Whether white space is allowed
     *
     * @return bool
     */
    public function getAllowWhiteSpace()
    {
        return $this->options['allow_white_space'];
    }

    /**
     * Defined by Zend\Filter\FilterInterface
     *
     * Returns $value as string with all non-alphanumeric characters removed
     *
     * @param  mixed $value
     * @return string
     */
    public function filter($value)
    {
        $whiteSpace = $this->options['allow_white_space'] ? '\s' : '';
        $language   = Locale::getPrimaryLanguage($this->getLocale());

        if (!static::hasPcreUnicodeSupport()) {
            // POSIX named classes are not supported, use alternative a-zA-Z0-9 match
            $pattern = '/[^a-zA-Z0-9' . $whiteSpace . ']/';
        } elseif ($language == 'ja'|| $language == 'ko' || $language == 'zh') {
            // Use english alphabet
            $pattern = '/[^a-zA-Z0-9'  . $whiteSpace . ']/u';
        } else {
            // Use native language alphabet
            $pattern = '/[^\p{L}\p{N}' . $whiteSpace . ']/u';
        }

        return preg_replace($pattern, '', (string) $value);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Filter;

use Locale;

class Alpha extends Alnum
{
    /**
     * Defined by Zend\Filter\FilterInterface
     *
     * Returns the string $value, removing all but alphabetic characters
     *
     * @param  string $value
     * @return string
     */
    public function filter($value)
    {
        $whiteSpace = $this->options['allow_white_space'] ? '\s' : '';
        $language   = Locale::getPrimaryLanguage($this->getLocale());

        if (!static::hasPcreUnicodeSupport()) {
            // POSIX named classes are not supported, use alternative [a-zA-Z] match
            $pattern = '/[^a-zA-Z' . $whiteSpace . ']/';
        } elseif ($language == 'ja' || $language == 'ko' || $language == 'zh') {
            // Use english alphabet
            $pattern = '/[^a-zA-Z'  . $whiteSpace . ']/u';
        } else {
            // Use native language alphabet
            $pattern = '/[^\p{L}' . $whiteSpace . ']/u';
        }

        return preg_replace($pattern, '', (string) $value);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Exception;

use DomainException;

class ExtensionNotLoadedException extends DomainException implements
    ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Exception;

class OutOfBoundsException extends \OutOfBoundsException implements
    ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Exception;

class InvalidArgumentException extends \InvalidArgumentException implements
    ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Exception;

class RuntimeException extends \RuntimeException implements ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Exception;

interface ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Exception;

class ParseException extends RuntimeException implements ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\I18n\Exception;

class RangeException extends \RangeException implements ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\File;

use Zend\Filter\Exception;
use Zend\Filter\StringToLower;

class LowerCase extends StringToLower
{
    /**
     * Defined by Zend\Filter\Filter
     *
     * Does a lowercase on the content of the given file
     *
     * @param  string|array $value Full path of file to change or $_FILES data array
     * @return string|array The given $value
     * @throws Exception\InvalidArgumentException
     * @throws Exception\RuntimeException
     */
    public function filter($value)
    {
        // An uploaded file? Retrieve the 'tmp_name'
        $isFileUpload = (is_array($value) && isset($value['tmp_name']));
        if ($isFileUpload) {
            $uploadData = $value;
            $value      = $value['tmp_name'];
        }

        if (!file_exists($value)) {
            throw new Exception\InvalidArgumentException("File '$value' not found");
        }

        if (!is_writable($value)) {
            throw new Exception\RuntimeException("File '$value' is not writable");
        }

        $content = file_get_contents($value);
        if (!$content) {
            throw new Exception\RuntimeException("Problem while reading file '$value'");
        }

        $content = parent::filter($content);
        $result  = file_put_contents($value, $content);

        if (!$result) {
            throw new Exception\RuntimeException("Problem while writing file '$value'");
        }

        if ($isFileUpload) {
            return $uploadData;
        }
        return $value;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\File;

use Traversable;
use Zend\Filter;
use Zend\Filter\Exception;
use Zend\Stdlib\ArrayUtils;

class Rename extends Filter\AbstractFilter
{
    /**
     * Internal array of array(source, target, overwrite)
     */
    protected $files = array();

    /**
     * Class constructor
     *
     * Options argument may be either a string, a Zend\Config\Config object, or an array.
     * If an array or Zend\Config\Config object, it accepts the following keys:
     * 'source'    => Source filename or directory which will be renamed
     * 'target'    => Target filename or directory, the new name of the source file
     * 'overwrite' => Shall existing files be overwritten ?
     * 'randomize' => Shall target files have a random postfix attached?
     *
     * @param  string|array|Traversable $options Target file or directory to be renamed
     * @throws Exception\InvalidArgumentException
     */
    public function __construct($options)
    {
        if ($options instanceof Traversable) {
            $options = ArrayUtils::iteratorToArray($options);
        } elseif (is_string($options)) {
            $options = array('target' => $options);
        } elseif (!is_array($options)) {
            throw new Exception\InvalidArgumentException(
                'Invalid options argument provided to filter'
            );
        }

        $this->setFile($options);
    }

    /**
     * Returns the files to rename and their new name and location
     *
     * @return array
     */
    public function getFile()
    {
        return $this->files;
    }

    /**
     * Sets a new file or directory as target, deleting existing ones
     *
     * Array accepts the following keys:
     * 'source'    => Source filename or directory which will be renamed
     * 'target'    => Target filename or directory, the new name of the sourcefile
     * 'overwrite' => Shall existing files be overwritten?
     * 'randomize' => Shall target files have a random postfix attached?
     *
     * @param  string|array $options Old file or directory to be rewritten
     * @return self
     */
    public function setFile($options)
    {
        $this->files = array();
        $this->addFile($options);

        return $this;
    }

    /**
     * Adds a new file or directory as target to the existing ones
     *
     * Array accepts the following keys:
     * 'source'    => Source filename or directory which will be renamed
     * 'target'    => Target filename or directory, the new name of the sourcefile
     * 'overwrite' => Shall existing files be overwritten?
     * 'randomize' => Shall target files have a random postfix attached?
     *
     * @param  string|array $options Old file or directory to be rewritten
     * @return Rename
     * @throws Exception\InvalidArgumentException
     */
    public function addFile($options)
    {
        if (is_string($options)) {
            $options = array('target' => $options);
        } elseif (!is_array($options)) {
            throw new Exception\InvalidArgumentException(
                'Invalid options to rename filter provided'
            );
        }

        $this->_convertOptions($options);

        return $this;
    }

    /**
     * Returns only the new filename without moving it
     * But existing files will be erased when the overwrite option is true
     *
     * @param  string  $value  Full path of file to change
     * @param  bool $source Return internal informations
     * @return string The new filename which has been set
     * @throws Exception\InvalidArgumentException If the target file already exists.
     */
    public function getNewName($value, $source = false)
    {
        $file = $this->_getFileName($value);
        if (!is_array($file)) {
            return $file;
        }

        if ($file['source'] == $file['target']) {
            return $value;
        }

        if (!file_exists($file['source'])) {
            return $value;
        }

        if ($file['overwrite'] && file_exists($file['target'])) {
            unlink($file['target']);
        }

        if (file_exists($file['target'])) {
            throw new Exception\InvalidArgumentException(
                sprintf("File '%s' could not be renamed. It already exists.", $value)
            );
        }

        if ($source) {
            return $file;
        }

        return $file['target'];
    }

    /**
     * Defined by Zend\Filter\Filter
     *
     * Renames the file $value to the new name set before
     * Returns the file $value, removing all but digit characters
     *
     * @param  string|array $value Full path of file to change or $_FILES data array
     * @throws Exception\RuntimeException
     * @return string|array The new filename which has been set
     */
    public function filter($value)
    {
        // An uploaded file? Retrieve the 'tmp_name'
        $isFileUpload = (is_array($value) && isset($value['tmp_name']));
        if ($isFileUpload) {
            $uploadData = $value;
            $value      = $value['tmp_name'];
        }

        $file = $this->getNewName($value, true);
        if (is_string($file)) {
            if ($isFileUpload) {
                return $uploadData;
            } else {
                return $file;
            }
        }

        $result = rename($file['source'], $file['target']);

        if ($result !== true) {
            throw new Exception\RuntimeException(
                sprintf(
                    "File '%s' could not be renamed. " .
                    "An error occurred while processing the file.",
                    $value
                )
            );
        }

        if ($isFileUpload) {
            $uploadData['tmp_name'] = $file['target'];
            return $uploadData;
        }
        return $file['target'];
    }

    /**
     * Internal method for creating the file array
     * Supports single and nested arrays
     *
     * @param  array $options
     * @return array
     */
    protected function _convertOptions($options)
    {
        $files = array();
        foreach ($options as $key => $value) {
            if (is_array($value)) {
                $this->_convertOptions($value);
                continue;
            }

            switch ($key) {
                case "source":
                    $files['source'] = (string) $value;
                    break;

                case 'target' :
                    $files['target'] = (string) $value;
                    break;

                case 'overwrite' :
                    $files['overwrite'] = (bool) $value;
                    break;

                case 'randomize' :
                    $files['randomize'] = (bool) $value;
                    break;

                default:
                    break;
            }
        }

        if (empty($files)) {
            return $this;
        }

        if (empty($files['source'])) {
            $files['source'] = '*';
        }

        if (empty($files['target'])) {
            $files['target'] = '*';
        }

        if (empty($files['overwrite'])) {
            $files['overwrite'] = false;
        }

        if (empty($files['randomize'])) {
            $files['randomize'] = false;
        }

        $found = false;
        foreach ($this->files as $key => $value) {
            if ($value['source'] == $files['source']) {
                $this->files[$key] = $files;
                $found             = true;
            }
        }

        if (!$found) {
            $count               = count($this->files);
            $this->files[$count] = $files;
        }

        return $this;
    }

    /**
     * Internal method to resolve the requested source
     * and return all other related parameters
     *
     * @param  string $file Filename to get the informations for
     * @return array|string
     */
    protected function _getFileName($file)
    {
        $rename = array();
        foreach ($this->files as $value) {
            if ($value['source'] == '*') {
                if (!isset($rename['source'])) {
                    $rename           = $value;
                    $rename['source'] = $file;
                }
            }

            if ($value['source'] == $file) {
                $rename = $value;
                break;
            }
        }

        if (!isset($rename['source'])) {
            return $file;
        }

        if (!isset($rename['target']) || $rename['target'] == '*') {
            $rename['target'] = $rename['source'];
        }

        if (is_dir($rename['target'])) {
            $name = basename($rename['source']);
            $last = $rename['target'][strlen($rename['target']) - 1];
            if (($last != '/') && ($last != '\\')) {
                $rename['target'] .= DIRECTORY_SEPARATOR;
            }

            $rename['target'] .= $name;
        }

        if ($rename['randomize']) {
            $info = pathinfo($rename['target']);
            $newTarget = $info['dirname'] . DIRECTORY_SEPARATOR .
                $info['filename'] . uniqid('_');
            if (isset($info['extension'])) {
                $newTarget .= '.' . $info['extension'];
            }
            $rename['target'] = $newTarget;
        }

        return $rename;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\File;

use Zend\Filter\AbstractFilter;
use Zend\Filter\Exception;
use Zend\Stdlib\ErrorHandler;

class RenameUpload extends AbstractFilter
{
    /**
     * @var array
     */
    protected $options = array(
        'target'               => null,
        'use_upload_name'      => false,
        'use_upload_extension' => false,
        'overwrite'            => false,
        'randomize'            => false,
    );

    /**
     * Store already filtered values, so we can filter multiple
     * times the same file without being block by move_uploaded_file
     * internal checks
     *
     * @var array
     */
    protected $alreadyFiltered = array();

    /**
     * Constructor
     *
     * @param array|string $targetOrOptions The target file path or an options array
     */
    public function __construct($targetOrOptions)
    {
        if (is_array($targetOrOptions)) {
            $this->setOptions($targetOrOptions);
        } else {
            $this->setTarget($targetOrOptions);
        }
    }

    /**
     * @param  string $target Target file path or directory
     * @return self
     */
    public function setTarget($target)
    {
        if (!is_string($target)) {
            throw new Exception\InvalidArgumentException(
                'Invalid target, must be a string'
            );
        }
        $this->options['target'] = $target;
        return $this;
    }

    /**
     * @return string Target file path or directory
     */
    public function getTarget()
    {
        return $this->options['target'];
    }

    /**
     * @param  bool $flag When true, this filter will use the $_FILES['name']
     *                       as the target filename.
     *                       Otherwise, it uses the default 'target' rules.
     * @return self
     */
    public function setUseUploadName($flag = true)
    {
        $this->options['use_upload_name'] = (bool) $flag;
        return $this;
    }

    /**
     * @return bool
     */
    public function getUseUploadName()
    {
        return $this->options['use_upload_name'];
    }

    /**
     * @param  bool $flag When true, this filter will use the original file
     *                    extension for the target filename
     * @return self
     */
    public function setUseUploadExtension($flag = true)
    {
        $this->options['use_upload_extension'] = (bool) $flag;
        return $this;
    }

    /**
     * @return bool
     */
    public function getUseUploadExtension()
    {
        return $this->options['use_upload_extension'];
    }

    /**
     * @param  bool $flag Shall existing files be overwritten?
     * @return self
     */
    public function setOverwrite($flag = true)
    {
        $this->options['overwrite'] = (bool) $flag;
        return $this;
    }

    /**
     * @return bool
     */
    public function getOverwrite()
    {
        return $this->options['overwrite'];
    }

    /**
     * @param  bool $flag Shall target files have a random postfix attached?
     * @return self
     */
    public function setRandomize($flag = true)
    {
        $this->options['randomize'] = (bool) $flag;
        return $this;
    }

    /**
     * @return bool
     */
    public function getRandomize()
    {
        return $this->options['randomize'];
    }

    /**
     * Defined by Zend\Filter\Filter
     *
     * Renames the file $value to the new name set before
     * Returns the file $value, removing all but digit characters
     *
     * @param  string|array $value Full path of file to change or $_FILES data array
     * @throws Exception\RuntimeException
     * @return string|array The new filename which has been set, or false when there were errors
     */
    public function filter($value)
    {
        // An uploaded file? Retrieve the 'tmp_name'
        $isFileUpload = (is_array($value) && isset($value['tmp_name']));
        if ($isFileUpload) {
            $uploadData = $value;
            $sourceFile = $value['tmp_name'];
        } else {
            $uploadData = array(
                'tmp_name' => $value,
                'name'     => $value,
            );
            $sourceFile = $value;
        }

        if (isset($this->alreadyFiltered[$sourceFile])) {
            return $this->alreadyFiltered[$sourceFile];
        }

        $targetFile = $this->getFinalTarget($uploadData);
        if (!file_exists($sourceFile) || $sourceFile == $targetFile) {
            return $value;
        }

        $this->checkFileExists($targetFile);
        $this->moveUploadedFile($sourceFile, $targetFile);

        $return = $targetFile;
        if ($isFileUpload) {
            $return = $uploadData;
            $return['tmp_name'] = $targetFile;
        }

        $this->alreadyFiltered[$sourceFile] = $return;

        return $return;
    }

    /**
     * @param  string $sourceFile Source file path
     * @param  string $targetFile Target file path
     * @throws Exception\RuntimeException
     * @return bool
     */
    protected function moveUploadedFile($sourceFile, $targetFile)
    {
        ErrorHandler::start();
        $result = move_uploaded_file($sourceFile, $targetFile);
        $warningException = ErrorHandler::stop();
        if (!$result || null !== $warningException) {
            throw new Exception\RuntimeException(
                sprintf("File '%s' could not be renamed. An error occurred while processing the file.", $sourceFile),
                0, $warningException
            );
        }

        return $result;
    }

    /**
     * @param  string $targetFile Target file path
     * @throws Exception\InvalidArgumentException
     */
    protected function checkFileExists($targetFile)
    {
        if (file_exists($targetFile)) {
            if ($this->getOverwrite()) {
                unlink($targetFile);
            } else {
                throw new Exception\InvalidArgumentException(
                    sprintf("File '%s' could not be renamed. It already exists.", $targetFile)
                );
            }
        }
    }

    /**
     * @param  array $uploadData $_FILES array
     * @return string
     */
    protected function getFinalTarget($uploadData)
    {
        $source = $uploadData['tmp_name'];
        $target = $this->getTarget();
        if (!isset($target) || $target == '*') {
            $target = $source;
        }

        // Get the target directory
        if (is_dir($target)) {
            $targetDir = $target;
            $last      = $target[strlen($target) - 1];
            if (($last != '/') && ($last != '\\')) {
                $targetDir .= DIRECTORY_SEPARATOR;
            }
        } else {
            $info      = pathinfo($target);
            $targetDir = $info['dirname'] . DIRECTORY_SEPARATOR;
        }

        // Get the target filename
        if ($this->getUseUploadName()) {
            $targetFile = basename($uploadData['name']);
        } elseif (!is_dir($target)) {
            $targetFile = basename($target);
            if ($this->getUseUploadExtension() && !$this->getRandomize()) {
                $targetInfo = pathinfo($targetFile);
                $sourceinfo = pathinfo($uploadData['name']);
                if (isset($sourceinfo['extension'])) {
                    $targetFile = $targetInfo['filename'] . '.' . $sourceinfo['extension'];
                }
            }
        } else {
            $targetFile = basename($source);
        }

        if ($this->getRandomize()) {
            $targetFile = $this->applyRandomToFilename($uploadData['name'], $targetFile);
        }

        return $targetDir . $targetFile;
    }

    /**
     * @param  string $source
     * @param  string $filename
     * @return string
     */
    protected function applyRandomToFilename($source, $filename)
    {
        $info = pathinfo($filename);
        $filename = $info['filename'] . uniqid('_');

        $sourceinfo = pathinfo($source);

        $extension = '';
        if ($this->getUseUploadExtension() === true && isset($sourceinfo['extension'])) {
            $extension .= '.' . $sourceinfo['extension'];
        } elseif (isset($info['extension'])) {
            $extension .= '.' . $info['extension'];
        }

        return $filename . $extension;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\File;

use Zend\Filter\Exception;
use Zend\Filter\StringToUpper;

class UpperCase extends StringToUpper
{
    /**
     * Defined by Zend\Filter\FilterInterface
     *
     * Does a lowercase on the content of the given file
     *
     * @param  string|array $value Full path of file to change or $_FILES data array
     * @return string|array The given $value
     * @throws Exception\RuntimeException
     * @throws Exception\InvalidArgumentException
     */
    public function filter($value)
    {
        // An uploaded file? Retrieve the 'tmp_name'
        $isFileUpload = (is_array($value) && isset($value['tmp_name']));
        if ($isFileUpload) {
            $uploadData = $value;
            $value      = $value['tmp_name'];
        }

        if (!file_exists($value)) {
            throw new Exception\InvalidArgumentException("File '$value' not found");
        }

        if (!is_writable($value)) {
            throw new Exception\InvalidArgumentException("File '$value' is not writable");
        }

        $content = file_get_contents($value);
        if (!$content) {
            throw new Exception\RuntimeException("Problem while reading file '$value'");
        }

        $content = parent::filter($content);
        $result  = file_put_contents($value, $content);

        if (!$result) {
            throw new Exception\RuntimeException("Problem while writing file '$value'");
        }

        if ($isFileUpload) {
            return $uploadData;
        }
        return $value;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\File;

use Zend\Filter;
use Zend\Filter\Exception;

/**
 * Encrypts a given file and stores the encrypted file content
 */
class Encrypt extends Filter\Encrypt
{
    /**
     * New filename to set
     *
     * @var string
     */
    protected $filename;

    /**
     * Returns the new filename where the content will be stored
     *
     * @return string
     */
    public function getFilename()
    {
        return $this->filename;
    }

    /**
     * Sets the new filename where the content will be stored
     *
     * @param  string $filename (Optional) New filename to set
     * @return self
     */
    public function setFilename($filename = null)
    {
        $this->filename = $filename;
        return $this;
    }

    /**
     * Defined by Zend\Filter\Filter
     *
     * Encrypts the file $value with the defined settings
     *
     * @param  string|array $value Full path of file to change or $_FILES data array
     * @return string|array The filename which has been set, or false when there were errors
     * @throws Exception\InvalidArgumentException
     * @throws Exception\RuntimeException
     */
    public function filter($value)
    {
        // An uploaded file? Retrieve the 'tmp_name'
        $isFileUpload = (is_array($value) && isset($value['tmp_name']));
        if ($isFileUpload) {
            $uploadData = $value;
            $value      = $value['tmp_name'];
        }

        if (!file_exists($value)) {
            throw new Exception\InvalidArgumentException("File '$value' not found");
        }

        if (!isset($this->filename)) {
            $this->filename = $value;
        }

        if (file_exists($this->filename) and !is_writable($this->filename)) {
            throw new Exception\RuntimeException("File '{$this->filename}' is not writable");
        }

        $content = file_get_contents($value);
        if (!$content) {
            throw new Exception\RuntimeException("Problem while reading file '$value'");
        }

        $encrypted = parent::filter($content);
        $result    = file_put_contents($this->filename, $encrypted);

        if (!$result) {
            throw new Exception\RuntimeException("Problem while writing file '{$this->filename}'");
        }

        if ($isFileUpload) {
            $uploadData['tmp_name'] = $this->filename;
            return $uploadData;
        }
        return $this->filename;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\File;

use Zend\Filter;
use Zend\Filter\Exception;

/**
 * Decrypts a given file and stores the decrypted file content
 */
class Decrypt extends Filter\Decrypt
{
    /**
     * New filename to set
     *
     * @var string
     */
    protected $filename;

    /**
     * Returns the new filename where the content will be stored
     *
     * @return string
     */
    public function getFilename()
    {
        return $this->filename;
    }

    /**
     * Sets the new filename where the content will be stored
     *
     * @param  string $filename (Optional) New filename to set
     * @return self
     */
    public function setFilename($filename = null)
    {
        $this->filename = $filename;
        return $this;
    }

    /**
     * Defined by Zend\Filter\FilterInterface
     *
     * Decrypts the file $value with the defined settings
     *
     * @param  string|array $value Full path of file to change or $_FILES data array
     * @return string|array The filename which has been set
     * @throws Exception\InvalidArgumentException
     * @throws Exception\RuntimeException
     */
    public function filter($value)
    {
        // An uploaded file? Retrieve the 'tmp_name'
        $isFileUpload = (is_array($value) && isset($value['tmp_name']));
        if ($isFileUpload) {
            $uploadData = $value;
            $value      = $value['tmp_name'];
        }

        if (!file_exists($value)) {
            throw new Exception\InvalidArgumentException("File '$value' not found");
        }

        if (!isset($this->filename)) {
            $this->filename = $value;
        }

        if (file_exists($this->filename) and !is_writable($this->filename)) {
            throw new Exception\RuntimeException("File '{$this->filename}' is not writable");
        }

        $content = file_get_contents($value);
        if (!$content) {
            throw new Exception\RuntimeException("Problem while reading file '$value'");
        }

        $decrypted = parent::filter($content);
        $result    = file_put_contents($this->filename, $decrypted);

        if (!$result) {
            throw new Exception\RuntimeException("Problem while writing file '{$this->filename}'");
        }

        if ($isFileUpload) {
            $uploadData['tmp_name'] = $this->filename;
            return $uploadData;
        }
        return $this->filename;
    }
}
{
    "name": "zendframework/zend-filter",
    "description": "provides a set of commonly needed data filters",
    "license": "BSD-3-Clause",
    "keywords": [
        "zf2",
        "filter"
    ],
    "autoload": {
        "psr-0": {
            "Zend\\Filter\\": ""
        }
    },
    "target-dir": "Zend/Filter",
    "require": {
        "php": ">=5.3.3",
        "zendframework/zend-stdlib": "self.version"
    },
    "require-dev": {
        "zendframework/zend-crypt": "self.version"
    },
    "suggest": {
        "zendframework/zend-i18n": "Zend\\I18n component",
        "zendframework/zend-uri": "Zend\\Uri component for UriNormalize filter",
        "zendframework/zend-validator": "Zend\\Validator component",
        "zendframework/zend-crypt": "Zend\\Crypt component",
        "zendframework/zend-stdlib": "Zend\\Stdlib component"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "2.2-dev",
            "dev-develop": "2.3-dev"
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

/**
 * Decompresses a given string
 */
class Decompress extends Compress
{
    /**
     * Use filter as functor
     *
     * Decompresses the content $value with the defined settings
     *
     * @param  string $value Content to decompress
     * @return string The decompressed content
     */
    public function __invoke($value)
    {
        return $this->getAdapter()->decompress($value);
    }

    /**
     * Defined by FilterInterface
     *
     * Decompresses the content $value with the defined settings
     *
     * @param  string $value Content to decompress
     * @return string The decompressed content
     */
    public function filter($value)
    {
        return $this->getAdapter()->decompress($value);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

use Traversable;
use Zend\Stdlib\ArrayUtils;

class StripTags extends AbstractFilter
{
    /**
     * Unique ID prefix used for allowing comments
     */
    const UNIQUE_ID_PREFIX = '__Zend_Filter_StripTags__';

    /**
     * Array of allowed tags and allowed attributes for each allowed tag
     *
     * Tags are stored in the array keys, and the array values are themselves
     * arrays of the attributes allowed for the corresponding tag.
     *
     * @var array
     */
    protected $tagsAllowed = array();

    /**
     * Array of allowed attributes for all allowed tags
     *
     * Attributes stored here are allowed for all of the allowed tags.
     *
     * @var array
     */
    protected $attributesAllowed = array();

    /**
     * Sets the filter options
     * Allowed options are
     *     'allowTags'     => Tags which are allowed
     *     'allowAttribs'  => Attributes which are allowed
     *     'allowComments' => Are comments allowed ?
     *
     * @param  string|array|Traversable $options
     */
    public function __construct($options = null)
    {
        if ($options instanceof Traversable) {
            $options = ArrayUtils::iteratorToArray($options);
        }
        if ((!is_array($options)) || (is_array($options) && !array_key_exists('allowTags', $options) &&
            !array_key_exists('allowAttribs', $options) && !array_key_exists('allowComments', $options))) {
            $options = func_get_args();
            $temp['allowTags'] = array_shift($options);
            if (!empty($options)) {
                $temp['allowAttribs'] = array_shift($options);
            }

            if (!empty($options)) {
                $temp['allowComments'] = array_shift($options);
            }

            $options = $temp;
        }

        if (array_key_exists('allowTags', $options)) {
            $this->setTagsAllowed($options['allowTags']);
        }

        if (array_key_exists('allowAttribs', $options)) {
            $this->setAttributesAllowed($options['allowAttribs']);
        }
    }

    /**
     * Returns the tagsAllowed option
     *
     * @return array
     */
    public function getTagsAllowed()
    {
        return $this->tagsAllowed;
    }

    /**
     * Sets the tagsAllowed option
     *
     * @param  array|string $tagsAllowed
     * @return self Provides a fluent interface
     */
    public function setTagsAllowed($tagsAllowed)
    {
        if (!is_array($tagsAllowed)) {
            $tagsAllowed = array($tagsAllowed);
        }

        foreach ($tagsAllowed as $index => $element) {
            // If the tag was provided without attributes
            if (is_int($index) && is_string($element)) {
                // Canonicalize the tag name
                $tagName = strtolower($element);
                // Store the tag as allowed with no attributes
                $this->tagsAllowed[$tagName] = array();
            }
            // Otherwise, if a tag was provided with attributes
            elseif (is_string($index) && (is_array($element) || is_string($element))) {
                // Canonicalize the tag name
                $tagName = strtolower($index);
                // Canonicalize the attributes
                if (is_string($element)) {
                    $element = array($element);
                }
                // Store the tag as allowed with the provided attributes
                $this->tagsAllowed[$tagName] = array();
                foreach ($element as $attribute) {
                    if (is_string($attribute)) {
                        // Canonicalize the attribute name
                        $attributeName = strtolower($attribute);
                        $this->tagsAllowed[$tagName][$attributeName] = null;
                    }
                }
            }
        }

        return $this;
    }

    /**
     * Returns the attributesAllowed option
     *
     * @return array
     */
    public function getAttributesAllowed()
    {
        return $this->attributesAllowed;
    }

    /**
     * Sets the attributesAllowed option
     *
     * @param  array|string $attributesAllowed
     * @return self Provides a fluent interface
     */
    public function setAttributesAllowed($attributesAllowed)
    {
        if (!is_array($attributesAllowed)) {
            $attributesAllowed = array($attributesAllowed);
        }

        // Store each attribute as allowed
        foreach ($attributesAllowed as $attribute) {
            if (is_string($attribute)) {
                // Canonicalize the attribute name
                $attributeName = strtolower($attribute);
                $this->attributesAllowed[$attributeName] = null;
            }
        }

        return $this;
    }

    /**
     * Defined by Zend\Filter\FilterInterface
     *
     * If the value provided is non-scalar, the value will remain unfiltered
     * and an E_USER_WARNING will be raised indicating it's unfilterable.
     *
     * @todo   improve docblock descriptions
     * @param  string $value
     * @return string|mixed
     */
    public function filter($value)
    {
        if (null === $value) {
            return null;
        }

        if (!is_scalar($value)) {
            trigger_error(
                sprintf(
                    '%s expects parameter to be scalar, "%s" given; cannot filter',
                    __METHOD__,
                    (is_object($value) ? get_class($value) : gettype($value))
                ),
                E_USER_WARNING
            );
            return $value;
        }

        $value = (string) $value;

        // Strip HTML comments first
        while (strpos($value, '<!--') !== false) {
            $pos   = strrpos($value, '<!--');
            $start = substr($value, 0, $pos);
            $value = substr($value, $pos);

            // If there is no comment closing tag, strip whole text
            if (!preg_match('/--\s*>/s', $value)) {
                $value = '';
            } else {
                $value = preg_replace('/<(?:!(?:--[\s\S]*?--\s*)?(>))/s', '',  $value);
            }

            $value = $start . $value;
        }

        // Initialize accumulator for filtered data
        $dataFiltered = '';
        // Parse the input data iteratively as regular pre-tag text followed by a
        // tag; either may be empty strings
        preg_match_all('/([^<]*)(<?[^>]*>?)/', (string) $value, $matches);

        // Iterate over each set of matches
        foreach ($matches[1] as $index => $preTag) {
            // If the pre-tag text is non-empty, strip any ">" characters from it
            if (strlen($preTag)) {
                $preTag = str_replace('>', '', $preTag);
            }
            // If a tag exists in this match, then filter the tag
            $tag = $matches[2][$index];
            if (strlen($tag)) {
                $tagFiltered = $this->_filterTag($tag);
            } else {
                $tagFiltered = '';
            }
            // Add the filtered pre-tag text and filtered tag to the data buffer
            $dataFiltered .= $preTag . $tagFiltered;
        }

        // Return the filtered data
        return $dataFiltered;
    }

    /**
     * Filters a single tag against the current option settings
     *
     * @param  string $tag
     * @return string
     */
    protected function _filterTag($tag)
    {
        // Parse the tag into:
        // 1. a starting delimiter (mandatory)
        // 2. a tag name (if available)
        // 3. a string of attributes (if available)
        // 4. an ending delimiter (if available)
        $isMatch = preg_match('~(</?)(\w*)((/(?!>)|[^/>])*)(/?>)~', $tag, $matches);

        // If the tag does not match, then strip the tag entirely
        if (!$isMatch) {
            return '';
        }

        // Save the matches to more meaningfully named variables
        $tagStart      = $matches[1];
        $tagName       = strtolower($matches[2]);
        $tagAttributes = $matches[3];
        $tagEnd        = $matches[5];

        // If the tag is not an allowed tag, then remove the tag entirely
        if (!isset($this->tagsAllowed[$tagName])) {
            return '';
        }

        // Trim the attribute string of whitespace at the ends
        $tagAttributes = trim($tagAttributes);

        // If there are non-whitespace characters in the attribute string
        if (strlen($tagAttributes)) {
            // Parse iteratively for well-formed attributes
            preg_match_all('/([\w-]+)\s*=\s*(?:(")(.*?)"|(\')(.*?)\')/s', $tagAttributes, $matches);

            // Initialize valid attribute accumulator
            $tagAttributes = '';

            // Iterate over each matched attribute
            foreach ($matches[1] as $index => $attributeName) {
                $attributeName      = strtolower($attributeName);
                $attributeDelimiter = empty($matches[2][$index]) ? $matches[4][$index] : $matches[2][$index];
                $attributeValue     = empty($matches[3][$index]) ? $matches[5][$index] : $matches[3][$index];

                // If the attribute is not allowed, then remove it entirely
                if (!array_key_exists($attributeName, $this->tagsAllowed[$tagName])
                    && !array_key_exists($attributeName, $this->attributesAllowed)) {
                    continue;
                }
                // Add the attribute to the accumulator
                $tagAttributes .= " $attributeName=" . $attributeDelimiter
                                . $attributeValue . $attributeDelimiter;
            }
        }

        // Reconstruct tags ending with "/>" as backwards-compatible XHTML tag
        if (strpos($tagEnd, '/') !== false) {
            $tagEnd = " $tagEnd";
        }

        // Return the filtered tag
        return $tagStart . $tagName . $tagAttributes . $tagEnd;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

use Traversable;

class PregReplace extends AbstractFilter
{
    protected $options = array(
        'pattern'     => null,
        'replacement' => '',
    );

    /**
     * Constructor
     * Supported options are
     *     'pattern'     => matching pattern
     *     'replacement' => replace with this
     *
     * @param  array|Traversable|string|null $options
     */
    public function __construct($options = null)
    {
        if ($options instanceof Traversable) {
            $options = iterator_to_array($options);
        }

        if (!is_array($options)
            || (!isset($options['pattern']) && !isset($options['replacement'])))
        {
            $args = func_get_args();
            if (isset($args[0])) {
                $this->setPattern($args[0]);
            }
            if (isset($args[1])) {
                $this->setReplacement($args[1]);
            }
        } else {
            $this->setOptions($options);
        }
    }

    /**
     * Set the regex pattern to search for
     * @see preg_replace()
     *
     * @param  string|array $pattern - same as the first argument of preg_replace
     * @return self
     * @throws Exception\InvalidArgumentException
     */
    public function setPattern($pattern)
    {
        if (!is_array($pattern) && !is_string($pattern)) {
            throw new Exception\InvalidArgumentException(sprintf(
                '%s expects pattern to be array or string; received "%s"',
                __METHOD__,
                (is_object($pattern) ? get_class($pattern) : gettype($pattern))
            ));
        }

        if (is_array($pattern)) {
            foreach ($pattern as $p) {
                $this->validatePattern($p);
            }
        }

        if (is_string($pattern)) {
            $this->validatePattern($pattern);
        }

        $this->options['pattern'] = $pattern;
        return $this;
    }

    /**
     * Get currently set match pattern
     *
     * @return string|array
     */
    public function getPattern()
    {
        return $this->options['pattern'];
    }

    /**
     * Set the replacement array/string
     * @see preg_replace()
     *
     * @param  array|string $replacement - same as the second argument of preg_replace
     * @return self
     * @throws Exception\InvalidArgumentException
     */
    public function setReplacement($replacement)
    {
        if (!is_array($replacement) && !is_string($replacement)) {
            throw new Exception\InvalidArgumentException(sprintf(
                '%s expects replacement to be array or string; received "%s"',
                __METHOD__,
                (is_object($replacement) ? get_class($replacement) : gettype($replacement))
            ));
        }
        $this->options['replacement'] = $replacement;
        return $this;
    }

    /**
     * Get currently set replacement value
     *
     * @return string|array
     */
    public function getReplacement()
    {
        return $this->options['replacement'];
    }

    /**
     * Perform regexp replacement as filter
     *
     * @param  mixed $value
     * @return mixed
     * @throws Exception\RuntimeException
     */
    public function filter($value)
    {
        if ($this->options['pattern'] === null) {
            throw new Exception\RuntimeException(sprintf(
                'Filter %s does not have a valid pattern set',
                get_class($this)
            ));
        }

        return preg_replace($this->options['pattern'], $this->options['replacement'], $value);
    }

    /**
     * Validate a pattern and ensure it does not contain the "e" modifier
     *
     * @param  string $pattern
     * @return bool
     * @throws Exception\InvalidArgumentException
     */
    protected function validatePattern($pattern)
    {
        if (!preg_match('/(?<modifier>[imsxeADSUXJu]+)$/', $pattern, $matches)) {
            return true;
        }

        if (false !== strstr($matches['modifier'], 'e')) {
            throw new Exception\InvalidArgumentException(sprintf(
                'Pattern for a PregReplace filter may not contain the "e" pattern modifier; received "%s"',
                $pattern
            ));
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

class Int extends AbstractFilter
{
    /**
     * Defined by Zend\Filter\FilterInterface
     *
     * Returns (int) $value
     *
     * If the value provided is non-scalar, the value will remain unfiltered
     * and an E_USER_WARNING will be raised indicating it's unfilterable.
     *
     * @param  string $value
     * @return int|mixed
     */
    public function filter($value)
    {
        if (null === $value) {
            return null;
        }

        if (!is_scalar($value)) {
            trigger_error(
                sprintf(
                    '%s expects parameter to be scalar, "%s" given; cannot filter',
                    __METHOD__,
                    (is_object($value) ? get_class($value) : gettype($value))
                ),
                E_USER_WARNING
            );
            return $value;
        }

        return (int) ((string) $value);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

use Countable;
use Zend\Stdlib\PriorityQueue;

class FilterChain extends AbstractFilter implements Countable
{
    /**
     * Default priority at which filters are added
     */
    const DEFAULT_PRIORITY = 1000;

    /**
     * @var FilterPluginManager
     */
    protected $plugins;

    /**
     * Filter chain
     *
     * @var PriorityQueue
     */
    protected $filters;

    /**
     * Initialize filter chain
     *
     * @param null|array|Traversable $options
     */
    public function __construct($options = null)
    {
        $this->filters = new PriorityQueue();

        if (null !== $options) {
            $this->setOptions($options);
        }
    }

    /**
     * @param  array|Traversable $options
     * @return self
     * @throws Exception\InvalidArgumentException
     */
    public function setOptions($options)
    {
        if (!is_array($options) && !$options instanceof \Traversable) {
            throw new Exception\InvalidArgumentException(sprintf(
                'Expected array or Traversable; received "%s"',
                (is_object($options) ? get_class($options) : gettype($options))
            ));
        }

        foreach ($options as $key => $value) {
            switch (strtolower($key)) {
                case 'callbacks':
                    foreach ($value as $spec) {
                        $callback = isset($spec['callback']) ? $spec['callback'] : false;
                        $priority = isset($spec['priority']) ? $spec['priority'] : static::DEFAULT_PRIORITY;
                        if ($callback) {
                            $this->attach($callback, $priority);
                        }
                    }
                    break;
                case 'filters':
                    foreach ($value as $spec) {
                        $name     = isset($spec['name'])     ? $spec['name']     : false;
                        $options  = isset($spec['options'])  ? $spec['options']  : array();
                        $priority = isset($spec['priority']) ? $spec['priority'] : static::DEFAULT_PRIORITY;
                        if ($name) {
                            $this->attachByName($name, $options, $priority);
                        }
                    }
                    break;
                default:
                    // ignore other options
                    break;
            }
        }

        return $this;
    }

    /**
     * Return the count of attached filters
     *
     * @return int
     */
    public function count()
    {
        return count($this->filters);
    }

    /**
     * Get plugin manager instance
     *
     * @return FilterPluginManager
     */
    public function getPluginManager()
    {
        if (!$this->plugins) {
            $this->setPluginManager(new FilterPluginManager());
        }
        return $this->plugins;
    }

    /**
     * Set plugin manager instance
     *
     * @param  FilterPluginManager $plugins
     * @return self
     */
    public function setPluginManager(FilterPluginManager $plugins)
    {
        $this->plugins = $plugins;
        return $this;
    }

    /**
     * Retrieve a filter plugin by name
     *
     * @param  mixed $name
     * @param  array $options
     * @return FilterInterface
     */
    public function plugin($name, array $options = array())
    {
        $plugins = $this->getPluginManager();
        return $plugins->get($name, $options);
    }

    /**
     * Attach a filter to the chain
     *
     * @param  callable|FilterInterface $callback A Filter implementation or valid PHP callback
     * @param  int $priority Priority at which to enqueue filter; defaults to 1000 (higher executes earlier)
     * @throws Exception\InvalidArgumentException
     * @return self
     */
    public function attach($callback, $priority = self::DEFAULT_PRIORITY)
    {
        if (!is_callable($callback)) {
            if (!$callback instanceof FilterInterface) {
                throw new Exception\InvalidArgumentException(sprintf(
                    'Expected a valid PHP callback; received "%s"',
                    (is_object($callback) ? get_class($callback) : gettype($callback))
                ));
            }
            $callback = array($callback, 'filter');
        }
        $this->filters->insert($callback, $priority);
        return $this;
    }

    /**
     * Attach a filter to the chain using a short name
     *
     * Retrieves the filter from the attached plugin manager, and then calls attach()
     * with the retrieved instance.
     *
     * @param  string $name
     * @param  mixed $options
     * @param  int $priority Priority at which to enqueue filter; defaults to 1000 (higher executes earlier)
     * @return self
     */
    public function attachByName($name, $options = array(), $priority = self::DEFAULT_PRIORITY)
    {
        if (!is_array($options)) {
            $options = (array) $options;
        } elseif (empty($options)) {
            $options = null;
        }
        $filter = $this->getPluginManager()->get($name, $options);
        return $this->attach($filter, $priority);
    }

    /**
     * Merge the filter chain with the one given in parameter
     *
     * @param FilterChain $filterChain
     * @return self
     */
    public function merge(FilterChain $filterChain)
    {
        foreach ($filterChain->filters->toArray(PriorityQueue::EXTR_BOTH) as $item) {
            $this->attach($item['data'], $item['priority']);
        }

        return $this;
    }

    /**
     * Get all the filters
     *
     * @return PriorityQueue
     */
    public function getFilters()
    {
        return $this->filters;
    }

    /**
     * Returns $value filtered through each filter in the chain
     *
     * Filters are run in the order in which they were added to the chain (FIFO)
     *
     * @param  mixed $value
     * @return mixed
     */
    public function filter($value)
    {
        $chain = clone $this->filters;

        $valueFiltered = $value;
        foreach ($chain as $filter) {
            $valueFiltered = call_user_func($filter, $valueFiltered);
        }

        return $valueFiltered;
    }

    /**
     * Clone filters
     */
    public function __clone()
    {
        $this->filters = clone $this->filters;
    }

    /**
     * Prepare filter chain for serialization
     *
     * Plugin manager (property 'plugins') cannot
     * be serialized. On wakeup the property remains unset
     * and next invokation to getPluginManager() sets
     * the default plugin manager instance (FilterPluginManager).
     */
    public function __sleep()
    {
        return array('filters');
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Compress;

use Zend\Filter\Exception;

/**
 * Compression adapter for Rar
 */
class Rar extends AbstractCompressionAlgorithm
{
    /**
     * Compression Options
     * array(
     *     'callback' => Callback for compression
     *     'archive'  => Archive to use
     *     'password' => Password to use
     *     'target'   => Target to write the files to
     * )
     *
     * @var array
     */
    protected $options = array(
        'callback' => null,
        'archive'  => null,
        'password' => null,
        'target'   => '.',
    );

    /**
     * Class constructor
     *
     * @param array $options (Optional) Options to set
     * @throws Exception\ExtensionNotLoadedException if rar extension not loaded
     */
    public function __construct($options = null)
    {
        if (!extension_loaded('rar')) {
            throw new Exception\ExtensionNotLoadedException('This filter needs the rar extension');
        }
        parent::__construct($options);
    }

    /**
     * Returns the set callback for compression
     *
     * @return string
     */
    public function getCallback()
    {
        return $this->options['callback'];
    }

    /**
     * Sets the callback to use
     *
     * @param  string $callback
     * @return self
     * @throws Exception\InvalidArgumentException if invalid callback provided
     */
    public function setCallback($callback)
    {
        if (!is_callable($callback)) {
            throw new Exception\InvalidArgumentException('Invalid callback provided');
        }

        $this->options['callback'] = $callback;
        return $this;
    }

    /**
     * Returns the set archive
     *
     * @return string
     */
    public function getArchive()
    {
        return $this->options['archive'];
    }

    /**
     * Sets the archive to use for de-/compression
     *
     * @param  string $archive Archive to use
     * @return self
     */
    public function setArchive($archive)
    {
        $archive = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $archive);
        $this->options['archive'] = (string) $archive;

        return $this;
    }

    /**
     * Returns the set password
     *
     * @return string
     */
    public function getPassword()
    {
        return $this->options['password'];
    }

    /**
     * Sets the password to use
     *
     * @param  string $password
     * @return self
     */
    public function setPassword($password)
    {
        $this->options['password'] = (string) $password;
        return $this;
    }

    /**
     * Returns the set targetpath
     *
     * @return string
     */
    public function getTarget()
    {
        return $this->options['target'];
    }

    /**
     * Sets the targetpath to use
     *
     * @param  string $target
     * @return self
     * @throws Exception\InvalidArgumentException if specified target directory does not exist
     */
    public function setTarget($target)
    {
        if (!file_exists(dirname($target))) {
            throw new Exception\InvalidArgumentException("The directory '$target' does not exist");
        }

        $target = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, (string) $target);
        $this->options['target'] = $target;
        return $this;
    }

    /**
     * Compresses the given content
     *
     * @param  string|array $content
     * @return string
     * @throws Exception\RuntimeException if no callback available, or error during compression
     */
    public function compress($content)
    {
        $callback = $this->getCallback();
        if ($callback === null) {
            throw new Exception\RuntimeException('No compression callback available');
        }

        $options = $this->getOptions();
        unset($options['callback']);

        $result = call_user_func($callback, $options, $content);
        if ($result !== true) {
            throw new Exception\RuntimeException('Error compressing the RAR Archive');
        }

        return $this->getArchive();
    }

    /**
     * Decompresses the given content
     *
     * @param  string $content
     * @return bool
     * @throws Exception\RuntimeException if archive not found, cannot be opened,
     *                                    or error during decompression
     */
    public function decompress($content)
    {
        if (!file_exists($content)) {
            throw new Exception\RuntimeException('RAR Archive not found');
        }

        $archive  = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, realpath($content));
        $password = $this->getPassword();
        if ($password !== null) {
            $archive = rar_open($archive, $password);
        } else {
            $archive = rar_open($archive);
        }

        if (!$archive) {
            throw new Exception\RuntimeException("Error opening the RAR Archive");
        }

        $target = $this->getTarget();
        if (!is_dir($target)) {
            $target = dirname($target);
        }

        $filelist = rar_list($archive);
        if (!$filelist) {
            throw new Exception\RuntimeException("Error reading the RAR Archive");
        }

        foreach ($filelist as $file) {
            $file->extract($target);
        }

        rar_close($archive);
        return true;
    }

    /**
     * Returns the adapter name
     *
     * @return string
     */
    public function toString()
    {
        return 'Rar';
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Compress;

use Zend\Filter\Exception;

/**
 * Compression adapter for Lzf
 */
class Lzf implements CompressionAlgorithmInterface
{
    /**
     * Class constructor
     *
     * @param  null $options
     * @throws Exception\ExtensionNotLoadedException if lzf extension missing
     */
    public function __construct($options = null)
    {
        if (!extension_loaded('lzf')) {
            throw new Exception\ExtensionNotLoadedException('This filter needs the lzf extension');
        }
    }

    /**
     * Compresses the given content
     *
     * @param  string $content
     * @return string
     * @throws Exception\RuntimeException if error occurs during compression
     */
    public function compress($content)
    {
        $compressed = lzf_compress($content);
        if (!$compressed) {
            throw new Exception\RuntimeException('Error during compression');
        }

        return $compressed;
    }

    /**
     * Decompresses the given content
     *
     * @param  string $content
     * @return string
     * @throws Exception\RuntimeException if error occurs during decompression
     */
    public function decompress($content)
    {
        $compressed = lzf_decompress($content);
        if (!$compressed) {
            throw new Exception\RuntimeException('Error during decompression');
        }

        return $compressed;
    }

    /**
     * Returns the adapter name
     *
     * @return string
     */
    public function toString()
    {
        return 'Lzf';
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Compress;

use Zend\Filter\Exception;

/**
 * Compression adapter for php snappy (http://code.google.com/p/php-snappy/)
 */
class Snappy implements CompressionAlgorithmInterface
{
    /**
     * Class constructor
     *
     * @param null|array|\Traversable $options (Optional) Options to set
     * @throws Exception\ExtensionNotLoadedException if snappy extension not loaded
     */
    public function __construct($options = null)
    {
        if (!extension_loaded('snappy')) {
            throw new Exception\ExtensionNotLoadedException('This filter needs the snappy extension');
        }
    }

    /**
     * Compresses the given content
     *
     * @param  string $content
     * @return string
     * @throws Exception\RuntimeException on memory, output length or data warning
     */
    public function compress($content)
    {
        $compressed = snappy_compress($content);

        if ($compressed === false) {
            throw new Exception\RuntimeException('Error while compressing.');
        }

        return $compressed;
    }

    /**
     * Decompresses the given content
     *
     * @param  string $content
     * @return string
     * @throws Exception\RuntimeException on memory, output length or data warning
     */
    public function decompress($content)
    {
        $compressed = snappy_uncompress($content);

        if ($compressed === false) {
            throw new Exception\RuntimeException('Error while decompressing.');
        }

        return $compressed;
    }

    /**
     * Returns the adapter name
     *
     * @return string
     */
    public function toString()
    {
        return 'Snappy';
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Compress;

use Traversable;
use Zend\Stdlib\ArrayUtils;

/**
 * Abstract compression adapter
 */
abstract class AbstractCompressionAlgorithm implements CompressionAlgorithmInterface
{
    /**
     * @var array
     */
    protected $options = array();

    /**
     * Class constructor
     *
     * @param null|array|Traversable $options (Optional) Options to set
     */
    public function __construct($options = null)
    {
        if ($options instanceof Traversable) {
            $options = ArrayUtils::iteratorToArray($options);
        }

        if (is_array($options)) {
            $this->setOptions($options);
        }
    }

    /**
     * Returns one or all set options
     *
     * @param  string $option (Optional) Option to return
     * @return mixed
     */
    public function getOptions($option = null)
    {
        if ($option === null) {
            return $this->options;
        }

        if (!array_key_exists($option, $this->options)) {
            return null;
        }

        return $this->options[$option];
    }

    /**
     * Sets all or one option
     *
     * @param  array $options
     * @return self
     */
    public function setOptions(array $options)
    {
        foreach ($options as $key => $option) {
            $method = 'set' . $key;
            if (method_exists($this, $method)) {
                $this->$method($option);
            }
        }

        return $this;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Compress;

use Archive_Tar;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use Zend\Filter\Exception;

/**
 * Compression adapter for Tar
 */
class Tar extends AbstractCompressionAlgorithm
{
    /**
     * Compression Options
     * array(
     *     'archive'  => Archive to use
     *     'target'   => Target to write the files to
     * )
     *
     * @var array
     */
    protected $options = array(
        'archive'  => null,
        'target'   => '.',
        'mode'     => null,
    );

    /**
     * Class constructor
     *
     * @param array $options (Optional) Options to set
     * @throws Exception\ExtensionNotLoadedException if Archive_Tar component not available
     */
    public function __construct($options = null)
    {
        if (!class_exists('Archive_Tar')) {
            throw new Exception\ExtensionNotLoadedException(
                'This filter needs PEAR\'s Archive_Tar component. '
                . 'Ensure loading Archive_Tar (registering autoload or require_once)');
        }

        parent::__construct($options);
    }

    /**
     * Returns the set archive
     *
     * @return string
     */
    public function getArchive()
    {
        return $this->options['archive'];
    }

    /**
     * Sets the archive to use for de-/compression
     *
     * @param  string $archive Archive to use
     * @return self
     */
    public function setArchive($archive)
    {
        $archive = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, (string) $archive);
        $this->options['archive'] = $archive;

        return $this;
    }

    /**
     * Returns the set target path
     *
     * @return string
     */
    public function getTarget()
    {
        return $this->options['target'];
    }

    /**
     * Sets the target path to use
     *
     * @param  string $target
     * @return self
     * @throws Exception\InvalidArgumentException if target path does not exist
     */
    public function setTarget($target)
    {
        if (!file_exists(dirname($target))) {
            throw new Exception\InvalidArgumentException("The directory '$target' does not exist");
        }

        $target = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, (string) $target);
        $this->options['target'] = $target;
        return $this;
    }

    /**
     * Returns the set compression mode
     *
     * @return string
     */
    public function getMode()
    {
        return $this->options['mode'];
    }

    /**
     * Compression mode to use
     *
     * Either Gz or Bz2.
     *
     * @param string $mode
     * @return self
     * @throws Exception\InvalidArgumentException for invalid $mode values
     * @throws Exception\ExtensionNotLoadedException if bz2 mode selected but extension not loaded
     * @throws Exception\ExtensionNotLoadedException if gz mode selected but extension not loaded
     */
    public function setMode($mode)
    {
        $mode = ucfirst(strtolower($mode));
        if (($mode != 'Bz2') && ($mode != 'Gz')) {
            throw new Exception\InvalidArgumentException("The mode '$mode' is unknown");
        }

        if (($mode == 'Bz2') && (!extension_loaded('bz2'))) {
            throw new Exception\ExtensionNotLoadedException('This mode needs the bz2 extension');
        }

        if (($mode == 'Gz') && (!extension_loaded('zlib'))) {
            throw new Exception\ExtensionNotLoadedException('This mode needs the zlib extension');
        }

        $this->options['mode'] = $mode;
        return $this;
    }

    /**
     * Compresses the given content
     *
     * @param  string $content
     * @return string
     * @throws Exception\RuntimeException if unable to create temporary file
     * @throws Exception\RuntimeException if unable to create archive
     */
    public function compress($content)
    {
        $archive = new Archive_Tar($this->getArchive(), $this->getMode());
        if (!file_exists($content)) {
            $file = $this->getTarget();
            if (is_dir($file)) {
                $file .= DIRECTORY_SEPARATOR . "tar.tmp";
            }

            $result = file_put_contents($file, $content);
            if ($result === false) {
                throw new Exception\RuntimeException('Error creating the temporary file');
            }

            $content = $file;
        }

        if (is_dir($content)) {
            // collect all file infos
            foreach (new RecursiveIteratorIterator(
                        new RecursiveDirectoryIterator($content, RecursiveDirectoryIterator::KEY_AS_PATHNAME),
                        RecursiveIteratorIterator::SELF_FIRST
                    ) as $directory => $info
            ) {
                if ($info->isFile()) {
                    $file[] = $directory;
                }
            }

            $content = $file;
        }

        $result  = $archive->create($content);
        if ($result === false) {
            throw new Exception\RuntimeException('Error creating the Tar archive');
        }

        return $this->getArchive();
    }

    /**
     * Decompresses the given content
     *
     * @param  string $content
     * @return string
     * @throws Exception\RuntimeException if unable to find archive
     * @throws Exception\RuntimeException if error occurs decompressing archive
     */
    public function decompress($content)
    {
        $archive = $this->getArchive();
        if (empty($archive) || !file_exists($archive)) {
            throw new Exception\RuntimeException('Tar Archive not found');
        }

        $archive = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, realpath($content));
        $archive = new Archive_Tar($archive, $this->getMode());
        $target  = $this->getTarget();
        if (!is_dir($target)) {
            $target = dirname($target) . DIRECTORY_SEPARATOR;
        }

        $result = $archive->extract($target);
        if ($result === false) {
            throw new Exception\RuntimeException('Error while extracting the Tar archive');
        }

        return $target;
    }

    /**
     * Returns the adapter name
     *
     * @return string
     */
    public function toString()
    {
        return 'Tar';
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Compress;

/**
 * Compression interface
 */
interface CompressionAlgorithmInterface
{
    /**
     * Compresses $value with the defined settings
     *
     * @param  string $value Data to compress
     * @return string The compressed data
     */
    public function compress($value);

    /**
     * Decompresses $value with the defined settings
     *
     * @param  string $value Data to decompress
     * @return string The decompressed data
     */
    public function decompress($value);

    /**
     * Return the adapter name
     *
     * @return string
     */
    public function toString();
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Compress;

use Zend\Filter\Exception;
use ZipArchive;

/**
 * Compression adapter for zip
 */
class Zip extends AbstractCompressionAlgorithm
{
    /**
     * Compression Options
     * array(
     *     'archive'  => Archive to use
     *     'password' => Password to use
     *     'target'   => Target to write the files to
     * )
     *
     * @var array
     */
    protected $options = array(
        'archive' => null,
        'target'  => null,
    );

    /**
     * Class constructor
     *
     * @param  null|array|\Traversable $options (Optional) Options to set
     * @throws Exception\ExtensionNotLoadedException if zip extension not loaded
     */
    public function __construct($options = null)
    {
        if (!extension_loaded('zip')) {
            throw new Exception\ExtensionNotLoadedException('This filter needs the zip extension');
        }
        parent::__construct($options);
    }

    /**
     * Returns the set archive
     *
     * @return string
     */
    public function getArchive()
    {
        return $this->options['archive'];
    }

    /**
     * Sets the archive to use for de-/compression
     *
     * @param  string $archive Archive to use
     * @return self
     */
    public function setArchive($archive)
    {
        $archive = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, (string) $archive);
        $this->options['archive'] = $archive;

        return $this;
    }

    /**
     * Returns the set targetpath
     *
     * @return string
     */
    public function getTarget()
    {
        return $this->options['target'];
    }

    /**
     * Sets the target to use
     *
     * @param  string $target
     * @throws Exception\InvalidArgumentException
     * @return self
     */
    public function setTarget($target)
    {
        if (!file_exists(dirname($target))) {
            throw new Exception\InvalidArgumentException("The directory '$target' does not exist");
        }

        $target = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, (string) $target);
        $this->options['target'] = $target;
        return $this;
    }

    /**
     * Compresses the given content
     *
     * @param  string $content
     * @return string Compressed archive
     * @throws Exception\RuntimeException if unable to open zip archive, or error during compression
     */
    public function compress($content)
    {
        $zip = new ZipArchive();
        $res = $zip->open($this->getArchive(), ZipArchive::CREATE | ZipArchive::OVERWRITE);

        if ($res !== true) {
            throw new Exception\RuntimeException($this->errorString($res));
        }

        if (file_exists($content)) {
            $content  = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, realpath($content));
            $basename = substr($content, strrpos($content, DIRECTORY_SEPARATOR) + 1);
            if (is_dir($content)) {
                $index    = strrpos($content, DIRECTORY_SEPARATOR) + 1;
                $content .= DIRECTORY_SEPARATOR;
                $stack    = array($content);
                while (!empty($stack)) {
                    $current = array_pop($stack);
                    $files   = array();

                    $dir = dir($current);
                    while (false !== ($node = $dir->read())) {
                        if (($node == '.') || ($node == '..')) {
                            continue;
                        }

                        if (is_dir($current . $node)) {
                            array_push($stack, $current . $node . DIRECTORY_SEPARATOR);
                        }

                        if (is_file($current . $node)) {
                            $files[] = $node;
                        }
                    }

                    $local = substr($current, $index);
                    $zip->addEmptyDir(substr($local, 0, -1));

                    foreach ($files as $file) {
                        $zip->addFile($current . $file, $local . $file);
                        if ($res !== true) {
                            throw new Exception\RuntimeException($this->errorString($res));
                        }
                    }
                }
            } else {
                $res = $zip->addFile($content, $basename);
                if ($res !== true) {
                    throw new Exception\RuntimeException($this->errorString($res));
                }
            }
        } else {
            $file = $this->getTarget();
            if (!is_dir($file)) {
                $file = basename($file);
            } else {
                $file = "zip.tmp";
            }

            $res = $zip->addFromString($file, $content);
            if ($res !== true) {
                throw new Exception\RuntimeException($this->errorString($res));
            }
        }

        $zip->close();
        return $this->options['archive'];
    }

    /**
     * Decompresses the given content
     *
     * @param  string $content
     * @return string
     * @throws Exception\RuntimeException If archive file not found, target directory not found,
     *                                    or error during decompression
     */
    public function decompress($content)
    {
        $archive = $this->getArchive();

        if (empty($archive) || !file_exists($archive)) {
            throw new Exception\RuntimeException('ZIP Archive not found');
        }

        $archive = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, realpath($content));
        $zip     = new ZipArchive();
        $res     = $zip->open($archive);

        $target = $this->getTarget();
        if (!empty($target) && !is_dir($target)) {
            $target = dirname($target);
        }

        if (!empty($target)) {
            $target = rtrim($target, '/\\') . DIRECTORY_SEPARATOR;
        }

        if (empty($target) || !is_dir($target)) {
            throw new Exception\RuntimeException('No target for ZIP decompression set');
        }

        if ($res !== true) {
            throw new Exception\RuntimeException($this->errorString($res));
        }

        $res = $zip->extractTo($target);
        if ($res !== true) {
            throw new Exception\RuntimeException($this->errorString($res));
        }

        $zip->close();
        return $target;
    }

    /**
     * Returns the proper string based on the given error constant
     *
     * @param  string $error
     * @return string
     */
    public function errorString($error)
    {
        switch ($error) {
            case ZipArchive::ER_MULTIDISK :
                return 'Multidisk ZIP Archives not supported';

            case ZipArchive::ER_RENAME :
                return 'Failed to rename the temporary file for ZIP';

            case ZipArchive::ER_CLOSE :
                return 'Failed to close the ZIP Archive';

            case ZipArchive::ER_SEEK :
                return 'Failure while seeking the ZIP Archive';

            case ZipArchive::ER_READ :
                return 'Failure while reading the ZIP Archive';

            case ZipArchive::ER_WRITE :
                return 'Failure while writing the ZIP Archive';

            case ZipArchive::ER_CRC :
                return 'CRC failure within the ZIP Archive';

            case ZipArchive::ER_ZIPCLOSED :
                return 'ZIP Archive already closed';

            case ZipArchive::ER_NOENT :
                return 'No such file within the ZIP Archive';

            case ZipArchive::ER_EXISTS :
                return 'ZIP Archive already exists';

            case ZipArchive::ER_OPEN :
                return 'Can not open ZIP Archive';

            case ZipArchive::ER_TMPOPEN :
                return 'Failure creating temporary ZIP Archive';

            case ZipArchive::ER_ZLIB :
                return 'ZLib Problem';

            case ZipArchive::ER_MEMORY :
                return 'Memory allocation problem while working on a ZIP Archive';

            case ZipArchive::ER_CHANGED :
                return 'ZIP Entry has been changed';

            case ZipArchive::ER_COMPNOTSUPP :
                return 'Compression method not supported within ZLib';

            case ZipArchive::ER_EOF :
                return 'Premature EOF within ZIP Archive';

            case ZipArchive::ER_INVAL :
                return 'Invalid argument for ZLIB';

            case ZipArchive::ER_NOZIP :
                return 'Given file is no zip archive';

            case ZipArchive::ER_INTERNAL :
                return 'Internal error while working on a ZIP Archive';

            case ZipArchive::ER_INCONS :
                return 'Inconsistent ZIP archive';

            case ZipArchive::ER_REMOVE :
                return 'Can not remove ZIP Archive';

            case ZipArchive::ER_DELETED :
                return 'ZIP Entry has been deleted';

            default :
                return 'Unknown error within ZIP Archive';
        }
    }

    /**
     * Returns the adapter name
     *
     * @return string
     */
    public function toString()
    {
        return 'Zip';
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Compress;

use Zend\Filter\Exception;

/**
 * Compression adapter for Bz2
 */
class Bz2 extends AbstractCompressionAlgorithm
{
    /**
     * Compression Options
     * array(
     *     'blocksize' => Blocksize to use from 0-9
     *     'archive'   => Archive to use
     * )
     *
     * @var array
     */
    protected $options = array(
        'blocksize' => 4,
        'archive'   => null,
    );

    /**
     * Class constructor
     *
     * @param null|array|\Traversable $options (Optional) Options to set
     * @throws Exception\ExtensionNotLoadedException if bz2 extension not loaded
     */
    public function __construct($options = null)
    {
        if (!extension_loaded('bz2')) {
            throw new Exception\ExtensionNotLoadedException('This filter needs the bz2 extension');
        }
        parent::__construct($options);
    }

    /**
     * Returns the set blocksize
     *
     * @return int
     */
    public function getBlocksize()
    {
        return $this->options['blocksize'];
    }

    /**
     * Sets a new blocksize
     *
     * @param  int $blocksize
     * @throws Exception\InvalidArgumentException
     * @return self
     */
    public function setBlocksize($blocksize)
    {
        if (($blocksize < 0) || ($blocksize > 9)) {
            throw new Exception\InvalidArgumentException('Blocksize must be between 0 and 9');
        }

        $this->options['blocksize'] = (int) $blocksize;
        return $this;
    }

    /**
     * Returns the set archive
     *
     * @return string
     */
    public function getArchive()
    {
        return $this->options['archive'];
    }

    /**
     * Sets the archive to use for de-/compression
     *
     * @param  string $archive Archive to use
     * @return self
     */
    public function setArchive($archive)
    {
        $this->options['archive'] = (string) $archive;
        return $this;
    }

    /**
     * Compresses the given content
     *
     * @param  string $content
     * @return string
     * @throws Exception\RuntimeException
     */
    public function compress($content)
    {
        $archive = $this->getArchive();
        if (!empty($archive)) {
            $file = bzopen($archive, 'w');
            if (!$file) {
                throw new Exception\RuntimeException("Error opening the archive '" . $archive . "'");
            }

            bzwrite($file, $content);
            bzclose($file);
            $compressed = true;
        } else {
            $compressed = bzcompress($content, $this->getBlocksize());
        }

        if (is_int($compressed)) {
            throw new Exception\RuntimeException('Error during compression');
        }

        return $compressed;
    }

    /**
     * Decompresses the given content
     *
     * @param  string $content
     * @return string
     * @throws Exception\RuntimeException
     */
    public function decompress($content)
    {
        $archive = $this->getArchive();
        if (file_exists($content)) {
            $archive = $content;
        }

        if (file_exists($archive)) {
            $file = bzopen($archive, 'r');
            if (!$file) {
                throw new Exception\RuntimeException("Error opening the archive '" . $content . "'");
            }

            $compressed = bzread($file);
            bzclose($file);
        } else {
            $compressed = bzdecompress($content);
        }

        if (is_int($compressed)) {
            throw new Exception\RuntimeException('Error during decompression');
        }

        return $compressed;
    }

    /**
     * Returns the adapter name
     *
     * @return string
     */
    public function toString()
    {
        return 'Bz2';
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Compress;

use Zend\Filter\Exception;

/**
 * Compression adapter for Gzip (ZLib)
 */
class Gz extends AbstractCompressionAlgorithm
{
    /**
     * Compression Options
     * array(
     *     'level'    => Compression level 0-9
     *     'mode'     => Compression mode, can be 'compress', 'deflate'
     *     'archive'  => Archive to use
     * )
     *
     * @var array
     */
    protected $options = array(
        'level'   => 9,
        'mode'    => 'compress',
        'archive' => null,
    );

    /**
     * Class constructor
     *
     * @param null|array|\Traversable $options (Optional) Options to set
     * @throws Exception\ExtensionNotLoadedException if zlib extension not loaded
     */
    public function __construct($options = null)
    {
        if (!extension_loaded('zlib')) {
            throw new Exception\ExtensionNotLoadedException('This filter needs the zlib extension');
        }
        parent::__construct($options);
    }

    /**
     * Returns the set compression level
     *
     * @return int
     */
    public function getLevel()
    {
        return $this->options['level'];
    }

    /**
     * Sets a new compression level
     *
     * @param int $level
     * @throws Exception\InvalidArgumentException
     * @return self
     */
    public function setLevel($level)
    {
        if (($level < 0) || ($level > 9)) {
            throw new Exception\InvalidArgumentException('Level must be between 0 and 9');
        }

        $this->options['level'] = (int) $level;
        return $this;
    }

    /**
     * Returns the set compression mode
     *
     * @return string
     */
    public function getMode()
    {
        return $this->options['mode'];
    }

    /**
     * Sets a new compression mode
     *
     * @param  string $mode Supported are 'compress', 'deflate' and 'file'
     * @return self
     * @throws Exception\InvalidArgumentException for invalid $mode value
     */
    public function setMode($mode)
    {
        if (($mode != 'compress') && ($mode != 'deflate')) {
            throw new Exception\InvalidArgumentException('Given compression mode not supported');
        }

        $this->options['mode'] = $mode;
        return $this;
    }

    /**
     * Returns the set archive
     *
     * @return string
     */
    public function getArchive()
    {
        return $this->options['archive'];
    }

    /**
     * Sets the archive to use for de-/compression
     *
     * @param  string $archive Archive to use
     * @return self
     */
    public function setArchive($archive)
    {
        $this->options['archive'] = (string) $archive;
        return $this;
    }

    /**
     * Compresses the given content
     *
     * @param  string $content
     * @return string
     * @throws Exception\RuntimeException if unable to open archive or error during decompression
     */
    public function compress($content)
    {
        $archive = $this->getArchive();
        if (!empty($archive)) {
            $file = gzopen($archive, 'w' . $this->getLevel());
            if (!$file) {
                throw new Exception\RuntimeException("Error opening the archive '" . $this->options['archive'] . "'");
            }

            gzwrite($file, $content);
            gzclose($file);
            $compressed = true;
        } elseif ($this->options['mode'] == 'deflate') {
            $compressed = gzdeflate($content, $this->getLevel());
        } else {
            $compressed = gzcompress($content, $this->getLevel());
        }

        if (!$compressed) {
            throw new Exception\RuntimeException('Error during compression');
        }

        return $compressed;
    }

    /**
     * Decompresses the given content
     *
     * @param  string $content
     * @return string
     * @throws Exception\RuntimeException if unable to open archive or error during decompression
     */
    public function decompress($content)
    {
        $archive = $this->getArchive();
        $mode    = $this->getMode();
        if (file_exists($content)) {
            $archive = $content;
        }

        if (file_exists($archive)) {
            $handler = fopen($archive, "rb");
            if (!$handler) {
                throw new Exception\RuntimeException("Error opening the archive '" . $archive . "'");
            }

            fseek($handler, -4, SEEK_END);
            $packet = fread($handler, 4);
            $bytes  = unpack("V", $packet);
            $size   = end($bytes);
            fclose($handler);

            $file       = gzopen($archive, 'r');
            $compressed = gzread($file, $size);
            gzclose($file);
        } elseif ($mode == 'deflate') {
            $compressed = gzinflate($content);
        } else {
            $compressed = gzuncompress($content);
        }

        if (!$compressed) {
            throw new Exception\RuntimeException('Error during decompression');
        }

        return $compressed;
    }

    /**
     * Returns the adapter name
     *
     * @return string
     */
    public function toString()
    {
        return 'Gz';
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

class StripNewlines extends AbstractFilter
{

    /**
     * Defined by Zend\Filter\FilterInterface
     *
     * Returns $value without newline control characters
     *
     * @param  string $value
     * @return string
     */
    public function filter($value)
    {
        return str_replace(array("\n", "\r"), '', $value);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

use Traversable;
use Zend\Stdlib\ArrayUtils;

/**
 * Filter chain for string inflection
 */
class Inflector extends AbstractFilter
{
    /**
     * @var FilterPluginManager
     */
    protected $pluginManager = null;

    /**
     * @var string
     */
    protected $target = null;

    /**
     * @var bool
     */
    protected $throwTargetExceptionsOn = true;

    /**
     * @var string
     */
    protected $targetReplacementIdentifier = ':';

    /**
     * @var array
     */
    protected $rules = array();

    /**
     * Constructor
     *
     * @param string|array|Traversable $options Options to set
     */
    public function __construct($options = null)
    {
        if ($options instanceof Traversable) {
            $options = ArrayUtils::iteratorToArray($options);
        }
        if (!is_array($options)) {
            $options = func_get_args();
            $temp    = array();

            if (!empty($options)) {
                $temp['target'] = array_shift($options);
            }

            if (!empty($options)) {
                $temp['rules'] = array_shift($options);
            }

            if (!empty($options)) {
                $temp['throwTargetExceptionsOn'] = array_shift($options);
            }

            if (!empty($options)) {
                $temp['targetReplacementIdentifier'] = array_shift($options);
            }

            $options = $temp;
        }

        $this->setOptions($options);
    }

    /**
     * Retrieve plugin manager
     *
     * @return FilterPluginManager
     */
    public function getPluginManager()
    {
        if (!$this->pluginManager instanceof FilterPluginManager) {
            $this->setPluginManager(new FilterPluginManager());
        }

        return $this->pluginManager;
    }

    /**
     * Set plugin manager
     *
     * @param  FilterPluginManager $manager
     * @return self
     */
    public function setPluginManager(FilterPluginManager $manager)
    {
        $this->pluginManager = $manager;
        return $this;
    }

    /**
     * Set options
     *
     * @param  array|Traversable $options
     * @return self
     */
    public function setOptions($options)
    {
        if ($options instanceof Traversable) {
            $options = ArrayUtils::iteratorToArray($options);
        }

        // Set plugin manager
        if (array_key_exists('pluginManager', $options)) {
            if (is_scalar($options['pluginManager']) && class_exists($options['pluginManager'])) {
                $options['pluginManager'] = new $options['pluginManager'];
            }
            $this->setPluginManager($options['pluginManager']);
        }

        if (array_key_exists('throwTargetExceptionsOn', $options)) {
            $this->setThrowTargetExceptionsOn($options['throwTargetExceptionsOn']);
        }

        if (array_key_exists('targetReplacementIdentifier', $options)) {
            $this->setTargetReplacementIdentifier($options['targetReplacementIdentifier']);
        }

        if (array_key_exists('target', $options)) {
            $this->setTarget($options['target']);
        }

        if (array_key_exists('rules', $options)) {
            $this->addRules($options['rules']);
        }

        return $this;
    }

    /**
     * Set Whether or not the inflector should throw an exception when a replacement
     * identifier is still found within an inflected target.
     *
     * @param  bool $throwTargetExceptionsOn
     * @return self
     */
    public function setThrowTargetExceptionsOn($throwTargetExceptionsOn)
    {
        $this->throwTargetExceptionsOn = ($throwTargetExceptionsOn == true) ? true : false;
        return $this;
    }

    /**
     * Will exceptions be thrown?
     *
     * @return bool
     */
    public function isThrowTargetExceptionsOn()
    {
        return $this->throwTargetExceptionsOn;
    }

    /**
     * Set the Target Replacement Identifier, by default ':'
     *
     * @param  string $targetReplacementIdentifier
     * @return self
     */
    public function setTargetReplacementIdentifier($targetReplacementIdentifier)
    {
        if ($targetReplacementIdentifier) {
            $this->targetReplacementIdentifier = (string) $targetReplacementIdentifier;
        }

        return $this;
    }

    /**
     * Get Target Replacement Identifier
     *
     * @return string
     */
    public function getTargetReplacementIdentifier()
    {
        return $this->targetReplacementIdentifier;
    }

    /**
     * Set a Target
     * ex: 'scripts/:controller/:action.:suffix'
     *
     * @param  string $target
     * @return self
     */
    public function setTarget($target)
    {
        $this->target = (string) $target;
        return $this;
    }

    /**
     * Retrieve target
     *
     * @return string
     */
    public function getTarget()
    {
        return $this->target;
    }

    /**
     * Set Target Reference
     *
     * @param  reference $target
     * @return self
     */
    public function setTargetReference(&$target)
    {
        $this->target =& $target;
        return $this;
    }

    /**
     * Is the same as calling addRules() with the exception that it
     * clears the rules before adding them.
     *
     * @param  array $rules
     * @return self
     */
    public function setRules(array $rules)
    {
        $this->clearRules();
        $this->addRules($rules);
        return $this;
    }

    /**
     * Multi-call to setting filter rules.
     *
     * If prefixed with a ":" (colon), a filter rule will be added.  If not
     * prefixed, a static replacement will be added.
     *
     * ex:
     * array(
     *     ':controller' => array('CamelCaseToUnderscore', 'StringToLower'),
     *     ':action'     => array('CamelCaseToUnderscore', 'StringToLower'),
     *     'suffix'      => 'phtml'
     *     );
     *
     * @param  array $rules
     * @return self
     */
    public function addRules(array $rules)
    {
        $keys = array_keys($rules);
        foreach ($keys as $spec) {
            if ($spec[0] == ':') {
                $this->addFilterRule($spec, $rules[$spec]);
            } else {
                $this->setStaticRule($spec, $rules[$spec]);
            }
        }

        return $this;
    }

    /**
     * Get rules
     *
     * By default, returns all rules. If a $spec is provided, will return those
     * rules if found, false otherwise.
     *
     * @param  string $spec
     * @return array|false
     */
    public function getRules($spec = null)
    {
        if (null !== $spec) {
            $spec = $this->_normalizeSpec($spec);
            if (isset($this->rules[$spec])) {
                return $this->rules[$spec];
            }
            return false;
        }

        return $this->rules;
    }

    /**
     * Returns a rule set by setFilterRule(), a numeric index must be provided
     *
     * @param  string $spec
     * @param  int $index
     * @return FilterInterface|false
     */
    public function getRule($spec, $index)
    {
        $spec = $this->_normalizeSpec($spec);
        if (isset($this->rules[$spec]) && is_array($this->rules[$spec])) {
            if (isset($this->rules[$spec][$index])) {
                return $this->rules[$spec][$index];
            }
        }
        return false;
    }

    /**
     * Clears the rules currently in the inflector
     *
     * @return self
     */
    public function clearRules()
    {
        $this->rules = array();
        return $this;
    }

    /**
     * Set a filtering rule for a spec.  $ruleSet can be a string, Filter object
     * or an array of strings or filter objects.
     *
     * @param  string $spec
     * @param  array|string|\Zend\Filter\FilterInterface $ruleSet
     * @return self
     */
    public function setFilterRule($spec, $ruleSet)
    {
        $spec = $this->_normalizeSpec($spec);
        $this->rules[$spec] = array();
        return $this->addFilterRule($spec, $ruleSet);
    }

    /**
     * Add a filter rule for a spec
     *
     * @param  mixed $spec
     * @param  mixed $ruleSet
     * @return self
     */
    public function addFilterRule($spec, $ruleSet)
    {
        $spec = $this->_normalizeSpec($spec);
        if (!isset($this->rules[$spec])) {
            $this->rules[$spec] = array();
        }

        if (!is_array($ruleSet)) {
            $ruleSet = array($ruleSet);
        }

        if (is_string($this->rules[$spec])) {
            $temp = $this->rules[$spec];
            $this->rules[$spec] = array();
            $this->rules[$spec][] = $temp;
        }

        foreach ($ruleSet as $rule) {
            $this->rules[$spec][] = $this->_getRule($rule);
        }

        return $this;
    }

    /**
     * Set a static rule for a spec.  This is a single string value
     *
     * @param  string $name
     * @param  string $value
     * @return self
     */
    public function setStaticRule($name, $value)
    {
        $name = $this->_normalizeSpec($name);
        $this->rules[$name] = (string) $value;
        return $this;
    }

    /**
     * Set Static Rule Reference.
     *
     * This allows a consuming class to pass a property or variable
     * in to be referenced when its time to build the output string from the
     * target.
     *
     * @param  string $name
     * @param  mixed $reference
     * @return self
     */
    public function setStaticRuleReference($name, &$reference)
    {
        $name = $this->_normalizeSpec($name);
        $this->rules[$name] =& $reference;
        return $this;
    }

    /**
     * Inflect
     *
     * @param  string|array $source
     * @throws Exception\RuntimeException
     * @return string
     */
    public function filter($source)
    {
        // clean source
        foreach ((array) $source as $sourceName => $sourceValue) {
            $source[ltrim($sourceName, ':')] = $sourceValue;
        }

        $pregQuotedTargetReplacementIdentifier = preg_quote($this->targetReplacementIdentifier, '#');
        $processedParts = array();

        foreach ($this->rules as $ruleName => $ruleValue) {
            if (isset($source[$ruleName])) {
                if (is_string($ruleValue)) {
                    // overriding the set rule
                    $processedParts['#' . $pregQuotedTargetReplacementIdentifier . $ruleName . '#'] = str_replace('\\', '\\\\', $source[$ruleName]);
                } elseif (is_array($ruleValue)) {
                    $processedPart = $source[$ruleName];
                    foreach ($ruleValue as $ruleFilter) {
                        $processedPart = $ruleFilter($processedPart);
                    }
                    $processedParts['#' . $pregQuotedTargetReplacementIdentifier . $ruleName . '#'] = str_replace('\\', '\\\\', $processedPart);
                }
            } elseif (is_string($ruleValue)) {
                $processedParts['#' . $pregQuotedTargetReplacementIdentifier . $ruleName . '#'] = str_replace('\\', '\\\\', $ruleValue);
            }
        }

        // all of the values of processedParts would have been str_replace('\\', '\\\\', ..)'d to disable preg_replace backreferences
        $inflectedTarget = preg_replace(array_keys($processedParts), array_values($processedParts), $this->target);

        if ($this->throwTargetExceptionsOn && (preg_match('#(?=' . $pregQuotedTargetReplacementIdentifier.'[A-Za-z]{1})#', $inflectedTarget) == true)) {
            throw new Exception\RuntimeException('A replacement identifier ' . $this->targetReplacementIdentifier . ' was found inside the inflected target, perhaps a rule was not satisfied with a target source?  Unsatisfied inflected target: ' . $inflectedTarget);
        }

        return $inflectedTarget;
    }

    /**
     * Normalize spec string
     *
     * @param  string $spec
     * @return string
     */
    protected function _normalizeSpec($spec)
    {
        return ltrim((string) $spec, ':&');
    }

    /**
     * Resolve named filters and convert them to filter objects.
     *
     * @param  string $rule
     * @return FilterInterface
     */
    protected function _getRule($rule)
    {
        if ($rule instanceof FilterInterface) {
            return $rule;
        }

        $rule = (string) $rule;
        return $this->getPluginManager()->get($rule);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

use Traversable;
use Zend\Stdlib\StringUtils;

abstract class AbstractFilter implements FilterInterface
{
    /**
     * Filter options
     *
     * @var array
     */
    protected $options = array();

    /**
     * @return bool
     * @deprecated Since 2.1.0
     */
    public static function hasPcreUnicodeSupport()
    {
        return StringUtils::hasPcreUnicodeSupport();
    }

    /**
     * @param  array|Traversable $options
     * @return self
     * @throws Exception\InvalidArgumentException
     */
    public function setOptions($options)
    {
        if (!is_array($options) && !$options instanceof Traversable) {
            throw new Exception\InvalidArgumentException(sprintf(
                '"%s" expects an array or Traversable; received "%s"',
                __METHOD__,
                (is_object($options) ? get_class($options) : gettype($options))
            ));
        }

        foreach ($options as $key => $value) {
            $setter = 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key)));
            if (method_exists($this, $setter)) {
                $this->{$setter}($value);
            } elseif (array_key_exists($key, $this->options)) {
                $this->options[$key] = $value;
            } else {
                throw new Exception\InvalidArgumentException(sprintf(
                    'The option "%s" does not have a matching %s setter method or options[%s] array key',
                    $key, $setter, $key
                ));
            }
        }
        return $this;
    }

    /**
     * Retrieve options representing object state
     *
     * @return array
     */
    public function getOptions()
    {
        return $this->options;
    }

    /**
     * Invoke filter as a command
     *
     * Proxies to {@link filter()}
     *
     * @param  mixed $value
     * @throws Exception\ExceptionInterface If filtering $value is impossible
     * @return mixed
     */
    public function __invoke($value)
    {
        return $this->filter($value);
    }

    /**
     * @param  mixed $options
     * @return bool
     */
    protected static function isOptions($options)
    {
        return (is_array($options) || $options instanceof Traversable);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

abstract class AbstractUnicode extends AbstractFilter
{
    /**
     * Set the input encoding for the given string
     *
     * @param  string|null $encoding
     * @return self
     * @throws Exception\InvalidArgumentException
     * @throws Exception\ExtensionNotLoadedException
     */
    public function setEncoding($encoding = null)
    {
        if ($encoding !== null) {
            if (!function_exists('mb_strtolower')) {
                throw new Exception\ExtensionNotLoadedException(sprintf(
                    '%s requires mbstring extension to be loaded',
                    get_class($this)
                ));
            }

            $encoding    = strtolower($encoding);
            $mbEncodings = array_map('strtolower', mb_list_encodings());
            if (!in_array($encoding, $mbEncodings)) {
                throw new Exception\InvalidArgumentException(sprintf(
                    "Encoding '%s' is not supported by mbstring extension",
                    $encoding
                ));
            }
        }

        $this->options['encoding'] = $encoding;
        return $this;
    }

    /**
     * Returns the set encoding
     *
     * @return string
     */
    public function getEncoding()
    {
        if ($this->options['encoding'] === null && function_exists('mb_internal_encoding')) {
            $this->options['encoding'] = mb_internal_encoding();
        }

        return $this->options['encoding'];
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Word;

class UnderscoreToCamelCase extends SeparatorToCamelCase
{
    /**
     * Constructor
     *
     */
    public function __construct()
    {
        parent::__construct('_');
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Word;

class DashToUnderscore extends SeparatorToSeparator
{
    /**
     * Constructor
     */
    public function __construct()
    {
        parent::__construct('-', '_');
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Word;

class CamelCaseToDash extends CamelCaseToSeparator
{
    /**
     * Constructor
     *
     */
    public function __construct()
    {
        parent::__construct('-');
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Word;

use Zend\Stdlib\StringUtils;

class CamelCaseToSeparator extends AbstractSeparator
{
    /**
     * Defined by Zend\Filter\Filter
     *
     * @param  string $value
     * @return string
     */
    public function filter($value)
    {
        if (StringUtils::hasPcreUnicodeSupport()) {
            $pattern     = array('#(?<=(?:\p{Lu}))(\p{Lu}\p{Ll})#', '#(?<=(?:\p{Ll}|\p{Nd}))(\p{Lu})#');
            $replacement = array($this->separator . '\1', $this->separator . '\1');
        } else {
            $pattern     = array('#(?<=(?:[A-Z]))([A-Z]+)([A-Z][A-z])#', '#(?<=(?:[a-z0-9]))([A-Z])#');
            $replacement = array('\1' . $this->separator . '\2', $this->separator . '\1');
        }

        return preg_replace($pattern, $replacement, $value);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Word;

class CamelCaseToUnderscore extends CamelCaseToSeparator
{
    /**
     * Constructor
     *
     */
    public function __construct()
    {
        parent::__construct('_');
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Word;

use Zend\Stdlib\StringUtils;

class SeparatorToCamelCase extends AbstractSeparator
{
    /**
     * Defined by Zend\Filter\Filter
     *
     * @param  string $value
     * @return string
     */
    public function filter($value)
    {
        // a unicode safe way of converting characters to \x00\x00 notation
        $pregQuotedSeparator = preg_quote($this->separator, '#');

        if (StringUtils::hasPcreUnicodeSupport()) {
            $patterns = array(
                '#(' . $pregQuotedSeparator.')(\p{L}{1})#u',
                '#(^\p{Ll}{1})#u',
            );
            if (!extension_loaded('mbstring')) {
                $replacements = array(
                    function ($matches) {
                        return strtoupper($matches[2]);
                    },
                    function ($matches) {
                        return strtoupper($matches[1]);
                    },
                );
            } else {
                $replacements = array(
                    function ($matches) {
                        return mb_strtoupper($matches[2], 'UTF-8');
                    },
                    function ($matches) {
                        return mb_strtoupper($matches[1], 'UTF-8');
                    },
                );
            }
        } else {
            $patterns = array(
                '#(' . $pregQuotedSeparator.')([A-Za-z]{1})#',
                '#(^[A-Za-z]{1})#',
            );
            $replacements = array(
                function ($matches) {
                    return strtoupper($matches[2]);
                },
                function ($matches) {
                    return strtoupper($matches[1]);
                },
            );
        }

        $filtered = $value;
        foreach ($patterns as $index => $pattern) {
            $filtered = preg_replace_callback($pattern, $replacements[$index], $filtered);
        }
        return $filtered;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Word;

class UnderscoreToDash extends SeparatorToSeparator
{
    /**
     * Constructor
     *
     */
    public function __construct()
    {
        parent::__construct('_', '-');
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Word;

class UnderscoreToSeparator extends SeparatorToSeparator
{
    /**
     * Constructor
     *
     * @param  string $replacementSeparator Space by default
     */
    public function __construct($replacementSeparator = ' ')
    {
        parent::__construct('_', $replacementSeparator);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Word;

class DashToCamelCase extends SeparatorToCamelCase
{
    /**
     * Constructor
     *
     */
    public function __construct()
    {
        parent::__construct('-');
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Word;

use Zend\Filter\AbstractFilter;
use Zend\Filter\Exception;

abstract class AbstractSeparator extends AbstractFilter
{

    protected $separator = ' ';

    /**
     * Constructor
     *
     * @param  string $separator Space by default
     */
    public function __construct($separator = ' ')
    {
        if (is_array($separator)) {
            $temp = ' ';
            if (isset($separator['separator']) && is_string($separator['separator'])) {
                $temp = $separator['separator'];
            }
            $separator = $temp;
        }
        $this->setSeparator($separator);
    }

    /**
     * Sets a new separator
     *
     * @param  string $separator Separator
     * @return self
     * @throws Exception\InvalidArgumentException
     */
    public function setSeparator($separator)
    {
        if (!is_string($separator)) {
            throw new Exception\InvalidArgumentException('"' . $separator . '" is not a valid separator.');
        }
        $this->separator = $separator;
        return $this;
    }

    /**
     * Returns the actual set separator
     *
     * @return string
     */
    public function getSeparator()
    {
        return $this->separator;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Word;

use Zend\Filter\AbstractFilter;
use Zend\Filter\Exception;

class SeparatorToSeparator extends AbstractFilter
{
    protected $searchSeparator = null;
    protected $replacementSeparator = null;

    /**
     * Constructor
     *
     * @param  string $searchSeparator      Separator to search for
     * @param  string $replacementSeparator Separator to replace with
     */
    public function __construct($searchSeparator = ' ', $replacementSeparator = '-')
    {
        $this->setSearchSeparator($searchSeparator);
        $this->setReplacementSeparator($replacementSeparator);
    }

    /**
     * Sets a new seperator to search for
     *
     * @param  string $separator Seperator to search for
     * @return self
     */
    public function setSearchSeparator($separator)
    {
        $this->searchSeparator = $separator;
        return $this;
    }

    /**
     * Returns the actual set separator to search for
     *
     * @return string
     */
    public function getSearchSeparator()
    {
        return $this->searchSeparator;
    }

    /**
     * Sets a new separator which replaces the searched one
     *
     * @param  string $separator Separator which replaces the searched one
     * @return self
     */
    public function setReplacementSeparator($separator)
    {
        $this->replacementSeparator = $separator;
        return $this;
    }

    /**
     * Returns the actual set separator which replaces the searched one
     *
     * @return string
     */
    public function getReplacementSeparator()
    {
        return $this->replacementSeparator;
    }

    /**
     * Defined by Zend\Filter\Filter
     *
     * Returns the string $value, replacing the searched separators with the defined ones
     *
     * @param  string $value
     * @return string
     */
    public function filter($value)
    {
        if ($this->searchSeparator == null) {
            throw new Exception\RuntimeException('You must provide a search separator for this filter to work.');
        }

        $pattern = '#' . preg_quote($this->searchSeparator, '#') . '#';
        return preg_replace($pattern, $this->replacementSeparator, $value);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Word;

class SeparatorToDash extends SeparatorToSeparator
{
    /**
     * Constructor
     *
     * @param string $searchSeparator Separator to search for change
     */
    public function __construct($searchSeparator = ' ')
    {
        parent::__construct($searchSeparator, '-');
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Word;

class DashToSeparator extends AbstractSeparator
{
    /**
     * Defined by Zend\Filter\Filter
     *
     * @param  string $value
     * @return string
     */
    public function filter($value)
    {
        return preg_replace('#-#', $this->separator, $value);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

class Dir extends AbstractFilter
{
    /**
     * Defined by Zend\Filter\FilterInterface
     *
     * Returns dirname($value)
     *
     * @param  string $value
     * @return string
     */
    public function filter($value)
    {
        return dirname((string) $value);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

class StaticFilter
{
    /**
     * @var FilterPluginManager
     */
    protected static $plugins;

    /**
     * Set plugin manager for resolving filter classes
     *
     * @param  FilterPluginManager $manager
     * @return void
     */
    public static function setPluginManager(FilterPluginManager $manager = null)
    {
        // Don't share by default to allow different arguments on subsequent calls
        if ($manager instanceof FilterPluginManager) {
            $manager->setShareByDefault(false);
        }
        static::$plugins = $manager;
    }

    /**
     * Get plugin manager for loading filter classes
     *
     * @return FilterPluginManager
     */
    public static function getPluginManager()
    {
        if (null === static::$plugins) {
            static::setPluginManager(new FilterPluginManager());
        }
        return static::$plugins;
    }

    /**
     * Returns a value filtered through a specified filter class, without requiring separate
     * instantiation of the filter object.
     *
     * The first argument of this method is a data input value, that you would have filtered.
     * The second argument is a string, which corresponds to the basename of the filter class,
     * relative to the Zend\Filter namespace. This method automatically loads the class,
     * creates an instance, and applies the filter() method to the data input. You can also pass
     * an array of constructor arguments, if they are needed for the filter class.
     *
     * @param  mixed        $value
     * @param  string       $classBaseName
     * @param  array        $args          OPTIONAL
     * @return mixed
     * @throws Exception\ExceptionInterface
     */
    public static function execute($value, $classBaseName, array $args = array())
    {
        $plugins = static::getPluginManager();

        $filter = $plugins->get($classBaseName, $args);
        return $filter->filter($value);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Encrypt;

use Traversable;
use Zend\Filter\Compress;
use Zend\Filter\Decompress;
use Zend\Filter\Exception;
use Zend\Stdlib\ArrayUtils;

/**
 * Encryption adapter for openssl
 */
class Openssl implements EncryptionAlgorithmInterface
{
    /**
     * Definitions for encryption
     * array(
     *     'public'   => public keys
     *     'private'  => private keys
     *     'envelope' => resulting envelope keys
     * )
     */
    protected $keys = array(
        'public'   => array(),
        'private'  => array(),
        'envelope' => array(),
    );

    /**
     * Internal passphrase
     *
     * @var string
     */
    protected $passphrase;

    /**
     * Internal compression
     *
     * @var array
     */
    protected $compression;

    /**
     * Internal create package
     *
     * @var bool
     */
    protected $package = false;

    /**
     * Class constructor
     * Available options
     *   'public'      => public key
     *   'private'     => private key
     *   'envelope'    => envelope key
     *   'passphrase'  => passphrase
     *   'compression' => compress value with this compression adapter
     *   'package'     => pack envelope keys into encrypted string, simplifies decryption
     *
     * @param string|array|Traversable $options Options for this adapter
     * @throws Exception\ExtensionNotLoadedException
     */
    public function __construct($options = array())
    {
        if (!extension_loaded('openssl')) {
            throw new Exception\ExtensionNotLoadedException('This filter needs the openssl extension');
        }

        if ($options instanceof Traversable) {
            $options = ArrayUtils::iteratorToArray($options);
        }

        if (!is_array($options)) {
            $options = array('public' => $options);
        }

        if (array_key_exists('passphrase', $options)) {
            $this->setPassphrase($options['passphrase']);
            unset($options['passphrase']);
        }

        if (array_key_exists('compression', $options)) {
            $this->setCompression($options['compression']);
            unset($options['compress']);
        }

        if (array_key_exists('package', $options)) {
            $this->setPackage($options['package']);
            unset($options['package']);
        }

        $this->_setKeys($options);
    }

    /**
     * Sets the encryption keys
     *
     * @param  string|array $keys Key with type association
     * @return self
     * @throws Exception\InvalidArgumentException
     */
    protected function _setKeys($keys)
    {
        if (!is_array($keys)) {
            throw new Exception\InvalidArgumentException('Invalid options argument provided to filter');
        }

        foreach ($keys as $type => $key) {
            if (is_file($key) and is_readable($key)) {
                $file = fopen($key, 'r');
                $cert = fread($file, 8192);
                fclose($file);
            } else {
                $cert = $key;
                $key  = count($this->keys[$type]);
            }

            switch ($type) {
                case 'public':
                    $test = openssl_pkey_get_public($cert);
                    if ($test === false) {
                        throw new Exception\InvalidArgumentException("Public key '{$cert}' not valid");
                    }

                    openssl_free_key($test);
                    $this->keys['public'][$key] = $cert;
                    break;
                case 'private':
                    $test = openssl_pkey_get_private($cert, $this->passphrase);
                    if ($test === false) {
                        throw new Exception\InvalidArgumentException("Private key '{$cert}' not valid");
                    }

                    openssl_free_key($test);
                    $this->keys['private'][$key] = $cert;
                    break;
                case 'envelope':
                    $this->keys['envelope'][$key] = $cert;
                    break;
                default:
                    break;
            }
        }

        return $this;
    }

    /**
     * Returns all public keys
     *
     * @return array
     */
    public function getPublicKey()
    {
        $key = $this->keys['public'];
        return $key;
    }

    /**
     * Sets public keys
     *
     * @param  string|array $key Public keys
     * @return self
     */
    public function setPublicKey($key)
    {
        if (is_array($key)) {
            foreach ($key as $type => $option) {
                if ($type !== 'public') {
                    $key['public'] = $option;
                    unset($key[$type]);
                }
            }
        } else {
            $key = array('public' => $key);
        }

        return $this->_setKeys($key);
    }

    /**
     * Returns all private keys
     *
     * @return array
     */
    public function getPrivateKey()
    {
        $key = $this->keys['private'];
        return $key;
    }

    /**
     * Sets private keys
     *
     * @param  string $key Private key
     * @param  string $passphrase
     * @return self
     */
    public function setPrivateKey($key, $passphrase = null)
    {
        if (is_array($key)) {
            foreach ($key as $type => $option) {
                if ($type !== 'private') {
                    $key['private'] = $option;
                    unset($key[$type]);
                }
            }
        } else {
            $key = array('private' => $key);
        }

        if ($passphrase !== null) {
            $this->setPassphrase($passphrase);
        }

        return $this->_setKeys($key);
    }

    /**
     * Returns all envelope keys
     *
     * @return array
     */
    public function getEnvelopeKey()
    {
        $key = $this->keys['envelope'];
        return $key;
    }

    /**
     * Sets envelope keys
     *
     * @param  string|array $key Envelope keys
     * @return self
     */
    public function setEnvelopeKey($key)
    {
        if (is_array($key)) {
            foreach ($key as $type => $option) {
                if ($type !== 'envelope') {
                    $key['envelope'] = $option;
                    unset($key[$type]);
                }
            }
        } else {
            $key = array('envelope' => $key);
        }

        return $this->_setKeys($key);
    }

    /**
     * Returns the passphrase
     *
     * @return string
     */
    public function getPassphrase()
    {
        return $this->passphrase;
    }

    /**
     * Sets a new passphrase
     *
     * @param string $passphrase
     * @return self
     */
    public function setPassphrase($passphrase)
    {
        $this->passphrase = $passphrase;
        return $this;
    }

    /**
     * Returns the compression
     *
     * @return array
     */
    public function getCompression()
    {
        return $this->compression;
    }

    /**
     * Sets a internal compression for values to encrypt
     *
     * @param string|array $compression
     * @return self
     */
    public function setCompression($compression)
    {
        if (is_string($this->compression)) {
            $compression = array('adapter' => $compression);
        }

        $this->compression = $compression;
        return $this;
    }

    /**
     * Returns if header should be packaged
     *
     * @return bool
     */
    public function getPackage()
    {
        return $this->package;
    }

    /**
     * Sets if the envelope keys should be included in the encrypted value
     *
     * @param  bool $package
     * @return self
     */
    public function setPackage($package)
    {
        $this->package = (bool) $package;
        return $this;
    }

    /**
     * Encrypts $value with the defined settings
     * Note that you also need the "encrypted" keys to be able to decrypt
     *
     * @param  string $value Content to encrypt
     * @return string The encrypted content
     * @throws Exception\RuntimeException
     */
    public function encrypt($value)
    {
        $encrypted     = array();
        $encryptedkeys = array();

        if (count($this->keys['public']) == 0) {
            throw new Exception\RuntimeException('Openssl can not encrypt without public keys');
        }

        $keys         = array();
        $fingerprints = array();
        $count        = -1;
        foreach ($this->keys['public'] as $key => $cert) {
            $keys[$key] = openssl_pkey_get_public($cert);
            if ($this->package) {
                $details = openssl_pkey_get_details($keys[$key]);
                if ($details === false) {
                    $details = array('key' => 'ZendFramework');
                }

                ++$count;
                $fingerprints[$count] = md5($details['key']);
            }
        }

        // compress prior to encryption
        if (!empty($this->compression)) {
            $compress = new Compress($this->compression);
            $value    = $compress($value);
        }

        $crypt  = openssl_seal($value, $encrypted, $encryptedkeys, $keys);
        foreach ($keys as $key) {
            openssl_free_key($key);
        }

        if ($crypt === false) {
            throw new Exception\RuntimeException('Openssl was not able to encrypt your content with the given options');
        }

        $this->keys['envelope'] = $encryptedkeys;

        // Pack data and envelope keys into single string
        if ($this->package) {
            $header = pack('n', count($this->keys['envelope']));
            foreach ($this->keys['envelope'] as $key => $envKey) {
                $header .= pack('H32n', $fingerprints[$key], strlen($envKey)) . $envKey;
            }

            $encrypted = $header . $encrypted;
        }

        return $encrypted;
    }

    /**
     * Defined by Zend\Filter\FilterInterface
     *
     * Decrypts $value with the defined settings
     *
     * @param  string $value Content to decrypt
     * @return string The decrypted content
     * @throws Exception\RuntimeException
     */
    public function decrypt($value)
    {
        $decrypted = "";
        $envelope  = current($this->getEnvelopeKey());

        if (count($this->keys['private']) !== 1) {
            throw new Exception\RuntimeException('Please give a private key for decryption with Openssl');
        }

        if (!$this->package && empty($envelope)) {
            throw new Exception\RuntimeException('Please give an envelope key for decryption with Openssl');
        }

        foreach ($this->keys['private'] as $cert) {
            $keys = openssl_pkey_get_private($cert, $this->getPassphrase());
        }

        if ($this->package) {
            $details = openssl_pkey_get_details($keys);
            if ($details !== false) {
                $fingerprint = md5($details['key']);
            } else {
                $fingerprint = md5("ZendFramework");
            }

            $count = unpack('ncount', $value);
            $count = $count['count'];
            $length  = 2;
            for ($i = $count; $i > 0; --$i) {
                $header = unpack('H32print/nsize', substr($value, $length, 18));
                $length  += 18;
                if ($header['print'] == $fingerprint) {
                    $envelope = substr($value, $length, $header['size']);
                }

                $length += $header['size'];
            }

            // remainder of string is the value to decrypt
            $value = substr($value, $length);
        }

        $crypt  = openssl_open($value, $decrypted, $envelope, $keys);
        openssl_free_key($keys);

        if ($crypt === false) {
            throw new Exception\RuntimeException('Openssl was not able to decrypt you content with the given options');
        }

        // decompress after decryption
        if (!empty($this->compression)) {
            $decompress = new Decompress($this->compression);
            $decrypted  = $decompress($decrypted);
        }

        return $decrypted;
    }

    /**
     * Returns the adapter name
     *
     * @return string
     */
    public function toString()
    {
        return 'Openssl';
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Encrypt;

/**
 * Encryption interface
 */
interface EncryptionAlgorithmInterface
{
    /**
     * Encrypts $value with the defined settings
     *
     * @param  string $value Data to encrypt
     * @return string The encrypted data
     */
    public function encrypt($value);

    /**
     * Decrypts $value with the defined settings
     *
     * @param  string $value Data to decrypt
     * @return string The decrypted data
     */
    public function decrypt($value);

    /**
     * Return the adapter name
     *
     * @return string
     */
    public function toString();
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Encrypt;

use Traversable;
use Zend\Filter\Compress;
use Zend\Filter\Decompress;
use Zend\Filter\Exception;
use Zend\Stdlib\ArrayUtils;
use Zend\Crypt\BlockCipher as CryptBlockCipher;
use Zend\Crypt\Exception as CryptException;
use Zend\Crypt\Symmetric\Exception as SymmetricException;

/**
 * Encryption adapter for Zend\Crypt\BlockCipher
 */
class BlockCipher implements EncryptionAlgorithmInterface
{
    /**
     * Definitions for encryption
     * array(
     *     'key'           => encryption key string
     *     'key_iteration' => the number of iterations for the PBKDF2 key generation
     *     'algorithm      => cipher algorithm to use
     *     'hash'          => algorithm to use for the authentication
     *     'vector'        => initialization vector
     * )
     */
    protected $encryption = array(
        'key_iteration'       => 5000,
        'algorithm'           => 'aes',
        'hash'                => 'sha256',
    );

    /**
     * BlockCipher
     *
     * @var BlockCipher
     */
    protected $blockCipher;

    /**
     * Internal compression
     *
     * @var array
     */
    protected $compression;

    /**
     * Class constructor
     *
     * @param  string|array|Traversable $options Encryption Options
     * @throws Exception\RuntimeException
     * @throws Exception\InvalidArgumentException
     */
    public function __construct($options)
    {
        try {
            $this->blockCipher = CryptBlockCipher::factory('mcrypt', $this->encryption);
        } catch (SymmetricException\RuntimeException $e) {
            throw new Exception\RuntimeException('The BlockCipher cannot be used without the Mcrypt extension');
        }

        if ($options instanceof Traversable) {
            $options = ArrayUtils::iteratorToArray($options);
        } elseif (is_string($options)) {
            $options = array('key' => $options);
        } elseif (!is_array($options)) {
            throw new Exception\InvalidArgumentException('Invalid options argument provided to filter');
        }

        if (array_key_exists('compression', $options)) {
            $this->setCompression($options['compression']);
            unset($options['compress']);
        }

        $this->setEncryption($options);
    }

    /**
     * Returns the set encryption options
     *
     * @return array
     */
    public function getEncryption()
    {
        return $this->encryption;
    }

    /**
     * Sets new encryption options
     *
     * @param  string|array $options Encryption options
     * @return self
     * @throws Exception\InvalidArgumentException
     */
    public function setEncryption($options)
    {
        if (is_string($options)) {
            $this->blockCipher->setKey($options);
            $this->encryption['key'] = $options;
            return $this;
        }

        if (!is_array($options)) {
            throw new Exception\InvalidArgumentException('Invalid options argument provided to filter');
        }

        $options = $options + $this->encryption;

        if (isset($options['key'])) {
            $this->blockCipher->setKey($options['key']);
        }

        if (isset($options['algorithm'])) {
            try {
                $this->blockCipher->setCipherAlgorithm($options['algorithm']);
            } catch (CryptException\InvalidArgumentException $e) {
                throw new Exception\InvalidArgumentException("The algorithm '{$options['algorithm']}' is not supported");
            }
        }

        if (isset($options['hash'])) {
            try {
                $this->blockCipher->setHashAlgorithm($options['hash']);
            } catch (CryptException\InvalidArgumentException $e) {
                throw new Exception\InvalidArgumentException("The algorithm '{$options['hash']}' is not supported");
            }
        }

        if (isset($options['vector'])) {
            $this->setVector($options['vector']);
        }

        if (isset($options['key_iteration'])) {
            $this->blockCipher->setKeyIteration($options['key_iteration']);
        }

        $this->encryption = $options;

        return $this;
    }

    /**
     * Returns the initialization vector
     *
     * @return string
     */
    public function getVector()
    {
        return $this->encryption['vector'];
    }

    /**
     * Set the inizialization vector
     *
     * @param  string $vector
     * @return self
     * @throws Exception\InvalidArgumentException
     */
    public function setVector($vector)
    {
        try {
            $this->blockCipher->setSalt($vector);
        } catch (CryptException\InvalidArgumentException $e) {
            throw new Exception\InvalidArgumentException($e->getMessage());
        }
        $this->encryption['vector'] = $vector;
        return $this;
    }

    /**
     * Set the encryption key
     *
     * @param  string $key
     * @return self
     * @throws Exception\InvalidArgumentException
     */
    public function setKey($key)
    {
        try {
            $this->blockCipher->setKey($key);
        } catch (CryptException\InvalidArgumentException $e) {
            throw new Exception\InvalidArgumentException($e->getMessage());
        }
        $this->encryption['key'] = $key;
        return $this;
    }

    /**
     * Get the encryption key
     *
     * @return string
     */
    public function getKey()
    {
        return $this->encryption['key'];
    }

    /**
     * Returns the compression
     *
     * @return array
     */
    public function getCompression()
    {
        return $this->compression;
    }

    /**
     * Sets a internal compression for values to encrypt
     *
     * @param  string|array $compression
     * @return self
     */
    public function setCompression($compression)
    {
        if (is_string($this->compression)) {
            $compression = array('adapter' => $compression);
        }

        $this->compression = $compression;
        return $this;
    }

    /**
     * Defined by Zend\Filter\FilterInterface
     *
     * Encrypts $value with the defined settings
     *
     * @param  string $value The content to encrypt
     * @throws Exception\InvalidArgumentException
     * @return string The encrypted content
     */
    public function encrypt($value)
    {
        // compress prior to encryption
        if (!empty($this->compression)) {
            $compress = new Compress($this->compression);
            $value    = $compress($value);
        }

        try {
            $encrypted = $this->blockCipher->encrypt($value);
        } catch (CryptException\InvalidArgumentException $e) {
            throw new Exception\InvalidArgumentException($e->getMessage());
        }
        return $encrypted;
    }

    /**
     * Defined by Zend\Filter\FilterInterface
     *
     * Decrypts $value with the defined settings
     *
     * @param  string $value Content to decrypt
     * @return string The decrypted content
     */
    public function decrypt($value)
    {
        $decrypted = $this->blockCipher->decrypt($value);

        // decompress after decryption
        if (!empty($this->compression)) {
            $decompress = new Decompress($this->compression);
            $decrypted  = $decompress($decrypted);
        }

        return $decrypted;
    }

    /**
     * Returns the adapter name
     *
     * @return string
     */
    public function toString()
    {
        return 'BlockCipher';
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

use Traversable;
use Zend\Stdlib\ArrayUtils;

/**
 * Compresses a given string
 */
class Compress extends AbstractFilter
{
    /**
     * Compression adapter
     */
    protected $adapter = 'Gz';

    /**
     * Compression adapter constructor options
     */
    protected $adapterOptions = array();

    /**
     * Class constructor
     *
     * @param string|array|Traversable $options (Optional) Options to set
     */
    public function __construct($options = null)
    {
        if ($options instanceof Traversable) {
            $options = ArrayUtils::iteratorToArray($options);
        }
        if (is_string($options)) {
            $this->setAdapter($options);
        } elseif ($options instanceof Compress\CompressionAlgorithmInterface) {
            $this->setAdapter($options);
        } elseif (is_array($options)) {
            $this->setOptions($options);
        }
    }

    /**
     * Set filter setate
     *
     * @param  array $options
     * @throws Exception\InvalidArgumentException if options is not an array or Traversable
     * @return self
     */
    public function setOptions($options)
    {
        if (!is_array($options) && !$options instanceof Traversable) {
            throw new Exception\InvalidArgumentException(sprintf(
                '"%s" expects an array or Traversable; received "%s"',
                __METHOD__,
                (is_object($options) ? get_class($options) : gettype($options))
            ));
        }

        foreach ($options as $key => $value) {
            if ($key == 'options') {
                $key = 'adapterOptions';
            }
            $method = 'set' . ucfirst($key);
            if (method_exists($this, $method)) {
                $this->$method($value);
            }
        }
        return $this;
    }

    /**
     * Returns the current adapter, instantiating it if necessary
     *
     * @throws Exception\RuntimeException
     * @throws Exception\InvalidArgumentException
     * @return Compress\CompressionAlgorithmInterface
     */
    public function getAdapter()
    {
        if ($this->adapter instanceof Compress\CompressionAlgorithmInterface) {
            return $this->adapter;
        }

        $adapter = $this->adapter;
        $options = $this->getAdapterOptions();
        if (!class_exists($adapter)) {
            $adapter = 'Zend\\Filter\\Compress\\' . ucfirst($adapter);
            if (!class_exists($adapter)) {
                throw new Exception\RuntimeException(sprintf(
                    '%s unable to load adapter; class "%s" not found',
                    __METHOD__,
                    $this->adapter
                ));
            }
        }

        $this->adapter = new $adapter($options);
        if (!$this->adapter instanceof Compress\CompressionAlgorithmInterface) {
            throw new Exception\InvalidArgumentException("Compression adapter '" . $adapter . "' does not implement Zend\\Filter\\Compress\\CompressionAlgorithmInterface");
        }
        return $this->adapter;
    }

    /**
     * Retrieve adapter name
     *
     * @return string
     */
    public function getAdapterName()
    {
        return $this->getAdapter()->toString();
    }

    /**
     * Sets compression adapter
     *
     * @param  string|Compress\CompressionAlgorithmInterface $adapter Adapter to use
     * @return self
     * @throws Exception\InvalidArgumentException
     */
    public function setAdapter($adapter)
    {
        if ($adapter instanceof Compress\CompressionAlgorithmInterface) {
            $this->adapter = $adapter;
            return $this;
        }
        if (!is_string($adapter)) {
            throw new Exception\InvalidArgumentException('Invalid adapter provided; must be string or instance of Zend\\Filter\\Compress\\CompressionAlgorithmInterface');
        }
        $this->adapter = $adapter;

        return $this;
    }

    /**
     * Retrieve adapter options
     *
     * @return array
     */
    public function getAdapterOptions()
    {
        return $this->adapterOptions;
    }

    /**
     * Set adapter options
     *
     * @param  array $options
     * @return self
     */
    public function setAdapterOptions(array $options)
    {
        $this->adapterOptions = $options;
        return $this;
    }

    /**
     * Get individual or all options from underlying adapter
     *
     * @param  null|string $option
     * @return mixed
     */
    public function getOptions($option = null)
    {
        $adapter = $this->getAdapter();
        return $adapter->getOptions($option);
    }

    /**
     * Calls adapter methods
     *
     * @param string       $method  Method to call
     * @param string|array $options Options for this method
     * @return mixed
     * @throws Exception\BadMethodCallException
     */
    public function __call($method, $options)
    {
        $adapter = $this->getAdapter();
        if (!method_exists($adapter, $method)) {
            throw new Exception\BadMethodCallException("Unknown method '{$method}'");
        }

        return call_user_func_array(array($adapter, $method), $options);
    }

    /**
     * Defined by Zend\Filter\FilterInterface
     *
     * Compresses the content $value with the defined settings
     *
     * @param  string $value Content to compress
     * @return string The compressed content
     */
    public function filter($value)
    {
        return $this->getAdapter()->compress($value);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

use Traversable;

class Callback extends AbstractFilter
{
    /**
     * @var array
     */
    protected $options = array(
        'callback'        => null,
        'callback_params' => array()
    );

    /**
     * @param callable|array|Traversable $callbackOrOptions
     * @param array $callbackParams
     */
    public function __construct($callbackOrOptions, $callbackParams = array())
    {
        if (is_callable($callbackOrOptions)) {
            $this->setCallback($callbackOrOptions);
            $this->setCallbackParams($callbackParams);
        } else {
            $this->setOptions($callbackOrOptions);
        }
    }

    /**
     * Sets a new callback for this filter
     *
     * @param  callable $callback
     * @throws Exception\InvalidArgumentException
     * @return self
     */
    public function setCallback($callback)
    {
        if (!is_callable($callback)) {
            throw new Exception\InvalidArgumentException(
                'Invalid parameter for callback: must be callable'
            );
        }

        $this->options['callback'] = $callback;
        return $this;
    }

    /**
     * Returns the set callback
     *
     * @return callable
     */
    public function getCallback()
    {
        return $this->options['callback'];
    }

    /**
     * Sets parameters for the callback
     *
     * @param  mixed $params
     * @return self
     */
    public function setCallbackParams($params)
    {
        $this->options['callback_params'] = (array) $params;
        return $this;
    }

    /**
     * Get parameters for the callback
     *
     * @return array
     */
    public function getCallbackParams()
    {
        return $this->options['callback_params'];
    }

    /**
     * Calls the filter per callback
     *
     * @param  mixed $value Options for the set callable
     * @return mixed Result from the filter which was called
     */
    public function filter($value)
    {
        $params = (array) $this->options['callback_params'];
        array_unshift($params, $value);

        return call_user_func_array($this->options['callback'], $params);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

use Zend\ServiceManager\AbstractPluginManager;

/**
 * Plugin manager implementation for the filter chain.
 *
 * Enforces that filters retrieved are either callbacks or instances of
 * FilterInterface. Additionally, it registers a number of default filters
 * available, as well as aliases for them.
 */
class FilterPluginManager extends AbstractPluginManager
{
    /**
     * Default set of filters
     *
     * @var array
     */
    protected $invokableClasses = array(
        'alnum'                     => 'Zend\I18n\Filter\Alnum',
        'alpha'                     => 'Zend\I18n\Filter\Alpha',
        'basename'                  => 'Zend\Filter\BaseName',
        'boolean'                   => 'Zend\Filter\Boolean',
        'callback'                  => 'Zend\Filter\Callback',
        'compress'                  => 'Zend\Filter\Compress',
        'compressbz2'               => 'Zend\Filter\Compress\Bz2',
        'compressgz'                => 'Zend\Filter\Compress\Gz',
        'compresslzf'               => 'Zend\Filter\Compress\Lzf',
        'compressrar'               => 'Zend\Filter\Compress\Rar',
        'compresssnappy'            => 'Zend\Filter\Compress\Snappy',
        'compresstar'               => 'Zend\Filter\Compress\Tar',
        'compresszip'               => 'Zend\Filter\Compress\Zip',
        'datetimeformatter'         => 'Zend\Filter\DateTimeFormatter',
        'decompress'                => 'Zend\Filter\Decompress',
        'decrypt'                   => 'Zend\Filter\Decrypt',
        'digits'                    => 'Zend\Filter\Digits',
        'dir'                       => 'Zend\Filter\Dir',
        'encrypt'                   => 'Zend\Filter\Encrypt',
        'encryptblockcipher'        => 'Zend\Filter\Encrypt\BlockCipher',
        'encryptopenssl'            => 'Zend\Filter\Encrypt\Openssl',
        'filedecrypt'               => 'Zend\Filter\File\Decrypt',
        'fileencrypt'               => 'Zend\Filter\File\Encrypt',
        'filelowercase'             => 'Zend\Filter\File\LowerCase',
        'filerename'                => 'Zend\Filter\File\Rename',
        'filerenameupload'          => 'Zend\Filter\File\RenameUpload',
        'fileuppercase'             => 'Zend\Filter\File\UpperCase',
        'htmlentities'              => 'Zend\Filter\HtmlEntities',
        'inflector'                 => 'Zend\Filter\Inflector',
        'int'                       => 'Zend\Filter\Int',
        'null'                      => 'Zend\Filter\Null',
        'numberformat'              => 'Zend\I18n\Filter\NumberFormat',
        'pregreplace'               => 'Zend\Filter\PregReplace',
        'realpath'                  => 'Zend\Filter\RealPath',
        'stringtolower'             => 'Zend\Filter\StringToLower',
        'stringtoupper'             => 'Zend\Filter\StringToUpper',
        'stringtrim'                => 'Zend\Filter\StringTrim',
        'stripnewlines'             => 'Zend\Filter\StripNewlines',
        'striptags'                 => 'Zend\Filter\StripTags',
        'urinormalize'              => 'Zend\Filter\UriNormalize',
        'wordcamelcasetodash'       => 'Zend\Filter\Word\CamelCaseToDash',
        'wordcamelcasetoseparator'  => 'Zend\Filter\Word\CamelCaseToSeparator',
        'wordcamelcasetounderscore' => 'Zend\Filter\Word\CamelCaseToUnderscore',
        'worddashtocamelcase'       => 'Zend\Filter\Word\DashToCamelCase',
        'worddashtoseparator'       => 'Zend\Filter\Word\DashToSeparator',
        'worddashtounderscore'      => 'Zend\Filter\Word\DashToUnderscore',
        'wordseparatortocamelcase'  => 'Zend\Filter\Word\SeparatorToCamelCase',
        'wordseparatortodash'       => 'Zend\Filter\Word\SeparatorToDash',
        'wordseparatortoseparator'  => 'Zend\Filter\Word\SeparatorToSeparator',
        'wordunderscoretocamelcase' => 'Zend\Filter\Word\UnderscoreToCamelCase',
        'wordunderscoretodash'      => 'Zend\Filter\Word\UnderscoreToDash',
        'wordunderscoretoseparator' => 'Zend\Filter\Word\UnderscoreToSeparator',
    );

    /**
     * Whether or not to share by default; default to false
     *
     * @var bool
     */
    protected $shareByDefault = false;

    /**
     * Validate the plugin
     *
     * Checks that the filter loaded is either a valid callback or an instance
     * of FilterInterface.
     *
     * @param  mixed $plugin
     * @return void
     * @throws Exception\RuntimeException if invalid
     */
    public function validatePlugin($plugin)
    {
        if ($plugin instanceof FilterInterface) {
            // we're okay
            return;
        }
        if (is_callable($plugin)) {
            // also okay
            return;
        }

        throw new Exception\RuntimeException(sprintf(
            'Plugin of type %s is invalid; must implement %s\FilterInterface or be callable',
            (is_object($plugin) ? get_class($plugin) : gettype($plugin)),
            __NAMESPACE__
        ));
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

class BaseName extends AbstractFilter
{
    /**
     * Defined by Zend\Filter\FilterInterface
     *
     * Returns basename($value).
     *
     * If the value provided is non-scalar, the value will remain unfiltered
     * and an E_USER_WARNING will be raised indicating it's unfilterable.
     *
     * @param  string $value
     * @return string|mixed
     */
    public function filter($value)
    {
        if (null === $value) {
            return null;
        }

        if (!is_scalar($value)) {
            trigger_error(
                sprintf(
                    '%s expects parameter to be scalar, "%s" given; cannot filter',
                    __METHOD__,
                    (is_object($value) ? get_class($value) : gettype($value))
                ),
                E_USER_WARNING
            );
            return $value;
        }

        return basename((string) $value);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

use Zend\Stdlib\StringUtils;

class Digits extends AbstractFilter
{
    /**
     * Defined by Zend\Filter\FilterInterface
     *
     * Returns the string $value, removing all but digit characters
     *
     * If the value provided is non-scalar, the value will remain unfiltered
     * and an E_USER_WARNING will be raised indicating it's unfilterable.
     *
     * @param  string $value
     * @return string|mixed
     */
    public function filter($value)
    {
        if (null === $value) {
            return null;
        }

        if (!is_scalar($value)) {
            trigger_error(
                sprintf(
                    '%s expects parameter to be scalar, "%s" given; cannot filter',
                    __METHOD__,
                    (is_object($value) ? get_class($value) : gettype($value))
                ),
                E_USER_WARNING
            );
            return $value;
        }

        if (!StringUtils::hasPcreUnicodeSupport()) {
            // POSIX named classes are not supported, use alternative 0-9 match
            $pattern = '/[^0-9]/';
        } elseif (extension_loaded('mbstring')) {
            // Filter for the value with mbstring
            $pattern = '/[^[:digit:]]/';
        } else {
            // Filter for the value without mbstring
            $pattern = '/[\p{^N}]/';
        }

        return preg_replace($pattern, '', (string) $value);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

use Traversable;

class StringToLower extends AbstractUnicode
{
    /**
     * @var array
     */
    protected $options = array(
        'encoding' => null,
    );

    /**
     * Constructor
     *
     * @param string|array|Traversable $encodingOrOptions OPTIONAL
     */
    public function __construct($encodingOrOptions = null)
    {
        if ($encodingOrOptions !== null) {
            if (!static::isOptions($encodingOrOptions)) {
                $this->setEncoding($encodingOrOptions);
            } else {
                $this->setOptions($encodingOrOptions);
            }
        }
    }

    /**
     * Defined by Zend\Filter\FilterInterface
     *
     * Returns the string $value, converting characters to lowercase as necessary
     *
     * If the value provided is non-scalar, the value will remain unfiltered
     * and an E_USER_WARNING will be raised indicating it's unfilterable.
     *
     * @param  string $value
     * @return string|mixed
     */
    public function filter($value)
    {
        if (null === $value) {
            return null;
        }

        if (!is_scalar($value)) {
            trigger_error(
                sprintf(
                    '%s expects parameter to be scalar, "%s" given; cannot filter',
                    __METHOD__,
                    (is_object($value) ? get_class($value) : gettype($value))
                ),
                E_USER_WARNING
            );
            return $value;
        }

        if ($this->options['encoding'] !== null) {
            return mb_strtolower((string) $value,  $this->options['encoding']);
        }

        return strtolower((string) $value);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

use Traversable;

class Null extends AbstractFilter
{
    const TYPE_BOOLEAN      = 1;
    const TYPE_INTEGER      = 2;
    const TYPE_EMPTY_ARRAY  = 4;
    const TYPE_STRING       = 8;
    const TYPE_ZERO_STRING  = 16;
    const TYPE_FLOAT        = 32;
    const TYPE_ALL          = 63;

    /**
     * @var array
     */
    protected $constants = array(
        self::TYPE_BOOLEAN     => 'boolean',
        self::TYPE_INTEGER     => 'integer',
        self::TYPE_EMPTY_ARRAY => 'array',
        self::TYPE_STRING      => 'string',
        self::TYPE_ZERO_STRING => 'zero',
        self::TYPE_FLOAT       => 'float',
        self::TYPE_ALL         => 'all',
    );

    /**
     * @var array
     */
    protected $options = array(
        'type' => self::TYPE_ALL,
    );

    /**
     * Constructor
     *
     * @param string|array|Traversable $typeOrOptions OPTIONAL
     */
    public function __construct($typeOrOptions = null)
    {
        if ($typeOrOptions !== null) {
            if ($typeOrOptions instanceof Traversable) {
                $typeOrOptions = iterator_to_array($typeOrOptions);
            }

            if (is_array($typeOrOptions)) {
                if (isset($typeOrOptions['type'])) {
                    $this->setOptions($typeOrOptions);
                } else {
                    $this->setType($typeOrOptions);
                }
            } else {
                $this->setType($typeOrOptions);
            }
        }
    }

    /**
     * Set boolean types
     *
     * @param  int|array $type
     * @throws Exception\InvalidArgumentException
     * @return self
     */
    public function setType($type = null)
    {
        if (is_array($type)) {
            $detected = 0;
            foreach ($type as $value) {
                if (is_int($value)) {
                    $detected += $value;
                } elseif (in_array($value, $this->constants)) {
                    $detected += array_search($value, $this->constants);
                }
            }

            $type = $detected;
        } elseif (is_string($type) && in_array($type, $this->constants)) {
            $type = array_search($type, $this->constants);
        }

        if (!is_int($type) || ($type < 0) || ($type > self::TYPE_ALL)) {
            throw new Exception\InvalidArgumentException(sprintf(
                'Unknown type value "%s" (%s)',
                $type,
                gettype($type)
            ));
        }

        $this->options['type'] = $type;
        return $this;
    }

    /**
     * Returns defined boolean types
     *
     * @return int
     */
    public function getType()
    {
        return $this->options['type'];
    }

    /**
     * Defined by Zend\Filter\FilterInterface
     *
     * Returns null representation of $value, if value is empty and matches
     * types that should be considered null.
     *
     * @param  string $value
     * @return string
     */
    public function filter($value)
    {
        $type = $this->getType();

        // FLOAT (0.0)
        if ($type >= self::TYPE_FLOAT) {
            $type -= self::TYPE_FLOAT;
            if (is_float($value) && ($value == 0.0)) {
                return null;
            }
        }

        // STRING ZERO ('0')
        if ($type >= self::TYPE_ZERO_STRING) {
            $type -= self::TYPE_ZERO_STRING;
            if (is_string($value) && ($value == '0')) {
                return null;
            }
        }

        // STRING ('')
        if ($type >= self::TYPE_STRING) {
            $type -= self::TYPE_STRING;
            if (is_string($value) && ($value == '')) {
                return null;
            }
        }

        // EMPTY_ARRAY (array())
        if ($type >= self::TYPE_EMPTY_ARRAY) {
            $type -= self::TYPE_EMPTY_ARRAY;
            if (is_array($value) && ($value == array())) {
                return null;
            }
        }

        // INTEGER (0)
        if ($type >= self::TYPE_INTEGER) {
            $type -= self::TYPE_INTEGER;
            if (is_int($value) && ($value == 0)) {
                return null;
            }
        }

        // BOOLEAN (false)
        if ($type >= self::TYPE_BOOLEAN) {
            $type -= self::TYPE_BOOLEAN;
            if (is_bool($value) && ($value == false)) {
                return null;
            }
        }

        return $value;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

use Traversable;
use Zend\Stdlib\ErrorHandler;

class RealPath extends AbstractFilter
{
    /**
     * @var array $options
     */
    protected $options = array(
        'exists' => true
    );

    /**
     * Class constructor
     *
     * @param  bool|Traversable $existsOrOptions Options to set
     */
    public function __construct($existsOrOptions = true)
    {
        if ($existsOrOptions !== null) {
            if (!static::isOptions($existsOrOptions)) {
                $this->setExists($existsOrOptions);
            } else {
                $this->setOptions($existsOrOptions);
            }
        }
    }

    /**
     * Sets if the path has to exist
     * TRUE when the path must exist
     * FALSE when not existing paths can be given
     *
     * @param  bool $flag Path must exist
     * @return self
     */
    public function setExists($flag = true)
    {
        $this->options['exists'] = (bool) $flag;
        return $this;
    }

    /**
     * Returns true if the filtered path must exist
     *
     * @return bool
     */
    public function getExists()
    {
        return $this->options['exists'];
    }

    /**
     * Defined by Zend\Filter\FilterInterface
     *
     * Returns realpath($value)
     *
     * If the value provided is non-scalar, the value will remain unfiltered
     * and an E_USER_WARNING will be raised indicating it's unfilterable.
     *
     * @param  string $value
     * @return string|mixed
     */
    public function filter($value)
    {
        if (null === $value) {
            return null;
        }

        if (!is_scalar($value)) {
            trigger_error(
                sprintf(
                    '%s expects parameter to be scalar, "%s" given; cannot filter',
                    __METHOD__,
                    (is_object($value) ? get_class($value) : gettype($value))
                ),
                E_USER_WARNING
            );
            return $value;
        }

        $path = (string) $value;
        if ($this->options['exists']) {
            return realpath($path);
        }

        ErrorHandler::start();
        $realpath = realpath($path);
        ErrorHandler::stop();
        if ($realpath) {
            return $realpath;
        }

        $drive = '';
        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
            $path = preg_replace('/[\\\\\/]/', DIRECTORY_SEPARATOR, $path);
            if (preg_match('/([a-zA-Z]\:)(.*)/', $path, $matches)) {
                list(, $drive, $path) = $matches;
            } else {
                $cwd   = getcwd();
                $drive = substr($cwd, 0, 2);
                if (substr($path, 0, 1) != DIRECTORY_SEPARATOR) {
                    $path = substr($cwd, 3) . DIRECTORY_SEPARATOR . $path;
                }
            }
        } elseif (substr($path, 0, 1) != DIRECTORY_SEPARATOR) {
            $path = getcwd() . DIRECTORY_SEPARATOR . $path;
        }

        $stack = array();
        $parts = explode(DIRECTORY_SEPARATOR, $path);
        foreach ($parts as $dir) {
            if (strlen($dir) && $dir !== '.') {
                if ($dir == '..') {
                    array_pop($stack);
                } else {
                    array_push($stack, $dir);
                }
            }
        }

        return $drive . DIRECTORY_SEPARATOR . implode(DIRECTORY_SEPARATOR, $stack);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

use Traversable;

class StringTrim extends AbstractFilter
{
    /**
     * @var array
     */
    protected $options = array(
        'charlist' => null,
    );

    /**
     * Sets filter options
     *
     * @param  string|array|Traversable $charlistOrOptions
     */
    public function __construct($charlistOrOptions = null)
    {
        if ($charlistOrOptions !== null) {
            if (!is_array($charlistOrOptions)
                && !$charlistOrOptions  instanceof Traversable)
            {
                $this->setCharList($charlistOrOptions);
            } else {
                $this->setOptions($charlistOrOptions);
            }
        }
    }

    /**
     * Sets the charList option
     *
     * @param  string $charList
     * @return self Provides a fluent interface
     */
    public function setCharList($charList)
    {
        if (empty($charList)) {
            $charList = null;
        }
        $this->options['charlist'] = $charList;
        return $this;
    }

    /**
     * Returns the charList option
     *
     * @return string|null
     */
    public function getCharList()
    {
        return $this->options['charlist'];
    }

    /**
     * Defined by Zend\Filter\FilterInterface
     *
     * Returns the string $value with characters stripped from the beginning and end
     *
     * @param  string $value
     * @return string
     */
    public function filter($value)
    {
        // Do not filter non-string values
        if (!is_string($value)) {
            return $value;
        }

        if (null === $this->options['charlist']) {
            return $this->unicodeTrim((string) $value);
        }

        return $this->unicodeTrim((string) $value, $this->options['charlist']);
    }

    /**
     * Unicode aware trim method
     * Fixes a PHP problem
     *
     * @param string $value
     * @param string $charlist
     * @return string
     */
    protected function unicodeTrim($value, $charlist = '\\\\s')
    {
        $chars = preg_replace(
            array('/[\^\-\]\\\]/S', '/\\\{4}/S', '/\//'),
            array('\\\\\\0', '\\', '\/'),
            $charlist
        );

        $pattern = '/^[' . $chars . ']+|[' . $chars . ']+$/usSD';

        return preg_replace($pattern, '', $value);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

use Zend\Filter\AbstractFilter;
use Zend\Filter\Exception\InvalidArgumentException;
use Zend\Uri\Exception\ExceptionInterface as UriException;
use Zend\Uri\UriFactory;
use Zend\Uri\Uri;

class UriNormalize extends AbstractFilter
{
    /**
     * The default scheme to use when parsing scheme-less URIs
     *
     * @var string
     */
    protected $defaultScheme = null;

    /**
     * Enforced scheme for scheme-less URIs. See setEnforcedScheme docs for info
     *
     * @var string
     */
    protected $enforcedScheme = null;

    /**
     * Sets filter options
     *
     * @param array|\Traversable|null $options
     */
    public function __construct($options = null)
    {
        if ($options) {
            $this->setOptions($options);
        }
    }

    /**
     * Set the default scheme to use when parsing scheme-less URIs
     *
     * The scheme used when parsing URIs may affect the specific object used to
     * normalize the URI and thus may affect the resulting normalize URI.
     *
     * @param  string $defaultScheme
     * @return self
     */
    public function setDefaultScheme($defaultScheme)
    {
        $this->defaultScheme = $defaultScheme;
        return $this;
    }

    /**
     * Set a URI scheme to enforce on schemeless URIs
     *
     * This allows forcing input values such as 'www.example.com/foo' into
     * 'http://www.example.com/foo'.
     *
     * This should be used with caution, as a standard-compliant URI parser
     * would regard 'www.example.com' in the above input URI to be the path and
     * not host part of the URI. While this option can assist in solving
     * real-world user mishaps, it may yield unexpected results at times.
     *
     * @param  string $enforcedScheme
     * @return self
     */
    public function setEnforcedScheme($enforcedScheme)
    {
        $this->enforcedScheme = $enforcedScheme;
        return $this;
    }

    /**
     * Filter the URL by normalizing it and applying a default scheme if set
     *
     * @param  string $value
     * @return string
     */
    public function filter($value)
    {
        $defaultScheme = $this->defaultScheme ?: $this->enforcedScheme;

        // Reset default scheme if it is not a known scheme
        if (!UriFactory::getRegisteredSchemeClass($defaultScheme)) {
            $defaultScheme = null;
        }

        try {
            $uri = UriFactory::factory($value, $defaultScheme);
            if ($this->enforcedScheme && (!$uri->getScheme())) {
                $this->enforceScheme($uri);
            }

        } catch (UriException $ex) {
            // We are unable to parse / enfore scheme with the given config and input
            return $value;
        }

        $uri->normalize();

        if (!$uri->isValid()) {
            return $value;
        }

        return $uri->toString();
    }

    /**
     * Enforce the defined scheme on the URI
     *
     * This will also adjust the host and path parts of the URI as expected in
     * the case of scheme-less network URIs
     *
     * @param Uri $uri
     */
    protected function enforceScheme(Uri $uri)
    {
        $path = $uri->getPath();
        if (strpos($path, '/') !== false) {
            list($host, $path) = explode('/', $path, 2);
            $path = '/' . $path;
        } else {
            $host = $path;
            $path = '';
        }

        // We have nothing to do if we have no host
        if (!$host) {
            return;
        }

        $uri->setScheme($this->enforcedScheme)
            ->setHost($host)
            ->setPath($path);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

use Traversable;
use Zend\Stdlib\ArrayUtils;

class HtmlEntities extends AbstractFilter
{
    /**
     * Corresponds to the second htmlentities() argument
     *
     * @var int
     */
    protected $quoteStyle;

    /**
     * Corresponds to the third htmlentities() argument
     *
     * @var string
     */
    protected $encoding;

    /**
     * Corresponds to the forth htmlentities() argument
     *
     * @var bool
     */
    protected $doubleQuote;

    /**
     * Sets filter options
     *
     * @param array|Traversable $options
     */
    public function __construct($options = array())
    {
        if ($options instanceof Traversable) {
            $options = ArrayUtils::iteratorToArray($options);
        }
        if (!is_array($options)) {
            $options = func_get_args();
            $temp['quotestyle'] = array_shift($options);
            if (!empty($options)) {
                $temp['charset'] = array_shift($options);
            }

            $options = $temp;
        }

        if (!isset($options['quotestyle'])) {
            $options['quotestyle'] = ENT_QUOTES;
        }

        if (!isset($options['encoding'])) {
            $options['encoding'] = 'UTF-8';
        }
        if (isset($options['charset'])) {
            $options['encoding'] = $options['charset'];
        }

        if (!isset($options['doublequote'])) {
            $options['doublequote'] = true;
        }

        $this->setQuoteStyle($options['quotestyle']);
        $this->setEncoding($options['encoding']);
        $this->setDoubleQuote($options['doublequote']);
    }

    /**
     * Returns the quoteStyle option
     *
     * @return int
     */
    public function getQuoteStyle()
    {
        return $this->quoteStyle;
    }

    /**
     * Sets the quoteStyle option
     *
     * @param  int $quoteStyle
     * @return self Provides a fluent interface
     */
    public function setQuoteStyle($quoteStyle)
    {
        $this->quoteStyle = $quoteStyle;
        return $this;
    }


    /**
     * Get encoding
     *
     * @return string
     */
    public function getEncoding()
    {
         return $this->encoding;
    }

    /**
     * Set encoding
     *
     * @param  string $value
     * @return self
     */
    public function setEncoding($value)
    {
        $this->encoding = (string) $value;
        return $this;
    }

    /**
     * Returns the charSet option
     *
     * Proxies to {@link getEncoding()}
     *
     * @return string
     */
    public function getCharSet()
    {
        return $this->getEncoding();
    }

    /**
     * Sets the charSet option
     *
     * Proxies to {@link setEncoding()}
     *
     * @param  string $charSet
     * @return self Provides a fluent interface
     */
    public function setCharSet($charSet)
    {
        return $this->setEncoding($charSet);
    }

    /**
     * Returns the doubleQuote option
     *
     * @return bool
     */
    public function getDoubleQuote()
    {
        return $this->doubleQuote;
    }

    /**
     * Sets the doubleQuote option
     *
     * @param  bool $doubleQuote
     * @return self Provides a fluent interface
     */
    public function setDoubleQuote($doubleQuote)
    {
        $this->doubleQuote = (bool) $doubleQuote;
        return $this;
    }

    /**
     * Defined by Zend\Filter\FilterInterface
     *
     * Returns the string $value, converting characters to their corresponding HTML entity
     * equivalents where they exist
     *
     * If the value provided is non-scalar, the value will remain unfiltered
     * and an E_USER_WARNING will be raised indicating it's unfilterable.
     *
     * @param  string $value
     * @return string|mixed
     * @throws Exception\DomainException on encoding mismatches
     */
    public function filter($value)
    {
        if (null === $value) {
            return null;
        }

        if (!is_scalar($value)) {
            trigger_error(
                sprintf(
                    '%s expects parameter to be scalar, "%s" given; cannot filter',
                    __METHOD__,
                    (is_object($value) ? get_class($value) : gettype($value))
                ),
                E_USER_WARNING
            );
            return $value;
        }

        $filtered = htmlentities((string) $value, $this->getQuoteStyle(), $this->getEncoding(), $this->getDoubleQuote());
        if (strlen((string) $value) && !strlen($filtered)) {
            if (!function_exists('iconv')) {
                throw new Exception\DomainException('Encoding mismatch has resulted in htmlentities errors');
            }
            $enc      = $this->getEncoding();
            $value    = iconv('', $this->getEncoding() . '//IGNORE', (string) $value);
            $filtered = htmlentities($value, $this->getQuoteStyle(), $enc, $this->getDoubleQuote());
            if (!strlen($filtered)) {
                throw new Exception\DomainException('Encoding mismatch has resulted in htmlentities errors');
            }
        }
        return $filtered;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

use Traversable;
use Zend\Stdlib\ArrayUtils;

/**
 * Encrypts a given string
 */
class Encrypt extends AbstractFilter
{
    /**
     * Encryption adapter
     */
    protected $adapter;

    /**
     * Class constructor
     *
     * @param string|array|Traversable $options (Optional) Options to set, if null mcrypt is used
     */
    public function __construct($options = null)
    {
        if ($options instanceof Traversable) {
            $options = ArrayUtils::iteratorToArray($options);
        }

        $this->setAdapter($options);
    }

    /**
     * Returns the name of the set adapter
     *
     * @return string
     */
    public function getAdapter()
    {
        return $this->adapter->toString();
    }

    /**
     * Sets new encryption options
     *
     * @param  string|array $options (Optional) Encryption options
     * @return self
     * @throws Exception\DomainException
     * @throws Exception\InvalidArgumentException
     */
    public function setAdapter($options = null)
    {
        if (is_string($options)) {
            $adapter = $options;
        } elseif (isset($options['adapter'])) {
            $adapter = $options['adapter'];
            unset($options['adapter']);
        } else {
            $adapter = 'BlockCipher';
        }

        if (!is_array($options)) {
            $options = array();
        }

        if (class_exists('Zend\Filter\Encrypt\\' . ucfirst($adapter))) {
            $adapter = 'Zend\Filter\Encrypt\\' . ucfirst($adapter);
        } elseif (!class_exists($adapter)) {
            throw new Exception\DomainException(
                sprintf('%s expects a valid registry class name; received "%s", which did not resolve',
                    __METHOD__,
                    $adapter
            ));
        }

        $this->adapter = new $adapter($options);
        if (!$this->adapter instanceof Encrypt\EncryptionAlgorithmInterface) {
            throw new Exception\InvalidArgumentException(
                "Encoding adapter '" . $adapter
                . "' does not implement Zend\\Filter\\Encrypt\\EncryptionAlgorithmInterface");
        }

        return $this;
    }

    /**
     * Calls adapter methods
     *
     * @param string       $method  Method to call
     * @param string|array $options Options for this method
     * @return mixed
     * @throws Exception\BadMethodCallException
     */
    public function __call($method, $options)
    {
        $part = substr($method, 0, 3);
        if ((($part != 'get') && ($part != 'set')) || !method_exists($this->adapter, $method)) {
            throw new Exception\BadMethodCallException("Unknown method '{$method}'");
        }

        return call_user_func_array(array($this->adapter, $method), $options);
    }

    /**
     * Defined by Zend\Filter\Filter
     *
     * Encrypts the content $value with the defined settings
     *
     * @param  string $value Content to encrypt
     * @return string The encrypted content
     */
    public function filter($value)
    {
        return $this->adapter->encrypt($value);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Exception;

class ExtensionNotLoadedException extends RuntimeException
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Exception;

class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Exception;

class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Exception;

class DomainException extends \DomainException implements ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Exception;

interface ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter\Exception;

class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

/**
 * Decrypts a given string
 */
class Decrypt extends Encrypt
{
    /**
     * Defined by Zend\Filter\Filter
     *
     * Decrypts the content $value with the defined settings
     *
     * @param  string $value Content to decrypt
     * @return string The decrypted content
     */
    public function filter($value)
    {
        return $this->adapter->decrypt($value);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

use DateTime;

class DateTimeFormatter extends AbstractFilter
{
    /**
     * A valid format string accepted by date()
     *
     * @var string
     */
    protected $format = DateTime::ISO8601;

    /**
     * Sets filter options
     *
     * @param array|Traversable $options
     */
    public function __construct($options = null)
    {
        if ($options) {
            $this->setOptions($options);
        }
    }

    /**
     * Set the format string accepted by date() to use when formatting a string
     *
     * @param  string $format
     * @return self
     */
    public function setFormat($format)
    {
        $this->format = $format;
        return $this;
    }

    /**
     * Filter a datetime string by normalizing it to the filters specified format
     *
     * @param  string $value
     * @throws Exception\InvalidArgumentException
     * @return string
     */
    public function filter($value)
    {
        try {
            $result = $this->normalizeDateTime($value);
        } catch (\Exception $e) {
            // DateTime threw an exception, an invalid date string was provided
            throw new Exception\InvalidArgumentException('Invalid date string provided', $e->getCode(), $e);
        }

        return $result;
    }

    /**
     * Normalize the provided value to a formatted string
     *
     * @param  string|int|DateTime $value
     * @return string
     */
    protected function normalizeDateTime($value)
    {
        if ($value === '' || $value === null) {
            return $value;
        } elseif (is_int($value)) {
            $value = new DateTime('@' . $value);
        } elseif (!$value instanceof DateTime) {
            $value = new DateTime($value);
        }

        return $value->format($this->format);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

use Traversable;
use Zend\Stdlib\ArrayUtils;

class Boolean extends AbstractFilter
{
    const TYPE_BOOLEAN        = 1;
    const TYPE_INTEGER        = 2;
    const TYPE_FLOAT          = 4;
    const TYPE_STRING         = 8;
    const TYPE_ZERO_STRING    = 16;
    const TYPE_EMPTY_ARRAY    = 32;
    const TYPE_NULL           = 64;
    const TYPE_PHP            = 127;
    const TYPE_FALSE_STRING   = 128;
    const TYPE_LOCALIZED      = 256;
    const TYPE_ALL            = 511;

    /**
     * @var array
     */
    protected $constants = array(
        self::TYPE_BOOLEAN       => 'boolean',
        self::TYPE_INTEGER       => 'integer',
        self::TYPE_FLOAT         => 'float',
        self::TYPE_STRING        => 'string',
        self::TYPE_ZERO_STRING   => 'zero',
        self::TYPE_EMPTY_ARRAY   => 'array',
        self::TYPE_NULL          => 'null',
        self::TYPE_PHP           => 'php',
        self::TYPE_FALSE_STRING  => 'false',
        self::TYPE_LOCALIZED     => 'localized',
        self::TYPE_ALL           => 'all',
    );

    /**
     * @var array
     */
    protected $options = array(
        'type'         => self::TYPE_PHP,
        'casting'      => true,
        'translations' => array(),
    );

    /**
     * Constructor
     *
     * @param array|Traversable|int|null  $typeOrOptions
     * @param bool  $casting
     * @param array $translations
     */
    public function __construct($typeOrOptions = null, $casting = true, $translations = array())
    {
        if ($typeOrOptions !== null) {
            if ($typeOrOptions instanceof Traversable) {
                $typeOrOptions = ArrayUtils::iteratorToArray($typeOrOptions);
            }

            if (is_array($typeOrOptions)) {
                if (isset($typeOrOptions['type'])
                    || isset($typeOrOptions['casting'])
                    || isset($typeOrOptions['translations']))
                {
                    $this->setOptions($typeOrOptions);
                } else {
                    $this->setType($typeOrOptions);
                    $this->setCasting($casting);
                    $this->setTranslations($translations);
                }
            } else {
                $this->setType($typeOrOptions);
                $this->setCasting($casting);
                $this->setTranslations($translations);
            }
        }
    }

    /**
     * Set boolean types
     *
     * @param  int|array $type
     * @throws Exception\InvalidArgumentException
     * @return self
     */
    public function setType($type = null)
    {
        if (is_array($type)) {
            $detected = 0;
            foreach ($type as $value) {
                if (is_int($value)) {
                    $detected += $value;
                } elseif (in_array($value, $this->constants)) {
                    $detected += array_search($value, $this->constants);
                }
            }

            $type = $detected;
        } elseif (is_string($type) && in_array($type, $this->constants)) {
            $type = array_search($type, $this->constants);
        }

        if (!is_int($type) || ($type < 0) || ($type > self::TYPE_ALL)) {
            throw new Exception\InvalidArgumentException(sprintf(
                'Unknown type value "%s" (%s)',
                $type,
                gettype($type)
            ));
        }

        $this->options['type'] = $type;
        return $this;
    }

    /**
     * Returns defined boolean types
     *
     * @return int
     */
    public function getType()
    {
        return $this->options['type'];
    }

    /**
     * Set the working mode
     *
     * @param  bool $flag When true this filter works like cast
     *                       When false it recognises only true and false
     *                       and all other values are returned as is
     * @return self
     */
    public function setCasting($flag = true)
    {
        $this->options['casting'] = (bool) $flag;
        return $this;
    }

    /**
     * Returns the casting option
     *
     * @return bool
     */
    public function getCasting()
    {
        return $this->options['casting'];
    }

    /**
     * @param  array|Traversable $translations
     * @throws Exception\InvalidArgumentException
     * @return self
     */
    public function setTranslations($translations)
    {
        if (!is_array($translations) && !$translations instanceof Traversable) {
            throw new Exception\InvalidArgumentException(sprintf(
                '"%s" expects an array or Traversable; received "%s"',
                __METHOD__,
                (is_object($translations) ? get_class($translations) : gettype($translations))
            ));
        }

        foreach ($translations as $message => $flag) {
            $this->options['translations'][$message] = (bool) $flag;
        }

        return $this;
    }

    /**
     * @return array
     */
    public function getTranslations()
    {
        return $this->options['translations'];
    }

    /**
     * Defined by Zend\Filter\FilterInterface
     *
     * Returns a boolean representation of $value
     *
     * @param  string $value
     * @return string
     */
    public function filter($value)
    {
        $type    = $this->getType();
        $casting = $this->getCasting();

        // LOCALIZED
        if ($type >= self::TYPE_LOCALIZED) {
            $type -= self::TYPE_LOCALIZED;
            if (is_string($value)) {
                if (isset($this->options['translations'][$value])) {
                    return (bool) $this->options['translations'][$value];
                }
            }
        }

        // FALSE_STRING ('false')
        if ($type >= self::TYPE_FALSE_STRING) {
            $type -= self::TYPE_FALSE_STRING;
            if (is_string($value) && (strtolower($value) == 'false')) {
                return false;
            }

            if (!$casting && is_string($value) && (strtolower($value) == 'true')) {
                return true;
            }
        }

        // NULL (null)
        if ($type >= self::TYPE_NULL) {
            $type -= self::TYPE_NULL;
            if ($value === null) {
                return false;
            }
        }

        // EMPTY_ARRAY (array())
        if ($type >= self::TYPE_EMPTY_ARRAY) {
            $type -= self::TYPE_EMPTY_ARRAY;
            if (is_array($value) && ($value == array())) {
                return false;
            }
        }

        // ZERO_STRING ('0')
        if ($type >= self::TYPE_ZERO_STRING) {
            $type -= self::TYPE_ZERO_STRING;
            if (is_string($value) && ($value == '0')) {
                return false;
            }

            if (!$casting && (is_string($value)) && ($value == '1')) {
                return true;
            }
        }

        // STRING ('')
        if ($type >= self::TYPE_STRING) {
            $type -= self::TYPE_STRING;
            if (is_string($value) && ($value == '')) {
                return false;
            }
        }

        // FLOAT (0.0)
        if ($type >= self::TYPE_FLOAT) {
            $type -= self::TYPE_FLOAT;
            if (is_float($value) && ($value == 0.0)) {
                return false;
            }

            if (!$casting && is_float($value) && ($value == 1.0)) {
                return true;
            }
        }

        // INTEGER (0)
        if ($type >= self::TYPE_INTEGER) {
            $type -= self::TYPE_INTEGER;
            if (is_int($value) && ($value == 0)) {
                return false;
            }

            if (!$casting && is_int($value) && ($value == 1)) {
                return true;
            }
        }

        // BOOLEAN (false)
        if ($type >= self::TYPE_BOOLEAN) {
            $type -= self::TYPE_BOOLEAN;
            if (is_bool($value)) {
                return $value;
            }
        }

        if ($casting) {
            return true;
        }

        return $value;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

use Traversable;

class StringToUpper extends AbstractUnicode
{
    /**
     * @var array
     */
    protected $options = array(
        'encoding' => null,
    );

    /**
     * Constructor
     *
     * @param string|array|Traversable $encodingOrOptions OPTIONAL
     */
    public function __construct($encodingOrOptions = null)
    {
        if ($encodingOrOptions !== null) {
            if (!static::isOptions($encodingOrOptions)) {
                $this->setEncoding($encodingOrOptions);
            } else {
                $this->setOptions($encodingOrOptions);
            }
        }
    }

    /**
     * Defined by Zend\Filter\FilterInterface
     *
     * Returns the string $value, converting characters to uppercase as necessary
     *
     * If the value provided is non-scalar, the value will remain unfiltered
     * and an E_USER_WARNING will be raised indicating it's unfilterable.
     *
     * @param  string $value
     * @return string|mixed
     */
    public function filter($value)
    {
        if (null === $value) {
            return null;
        }

        if (!is_scalar($value)) {
            trigger_error(
                sprintf(
                    '%s expects parameter to be scalar, "%s" given; cannot filter',
                    __METHOD__,
                    (is_object($value) ? get_class($value) : gettype($value))
                ),
                E_USER_WARNING
            );
            return $value;
        }

        if ($this->options['encoding'] !== null) {
            return mb_strtoupper((string) $value,  $this->options['encoding']);
        }

        return strtoupper((string) $value);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Filter;

interface FilterInterface
{
    /**
     * Returns the result of filtering $value
     *
     * @param  mixed $value
     * @throws Exception\RuntimeException If filtering $value is impossible
     * @return mixed
     */
    public function filter($value);
}
{
    "name": "zendframework/zend-math",
    "description": " ",
    "license": "BSD-3-Clause",
    "keywords": [
        "zf2",
        "math"
    ],
    "autoload": {
        "psr-0": {
            "Zend\\Math\\": ""
        }
    },
    "target-dir": "Zend/Math",
    "require": {
        "php": ">=5.3.3"
    },
    "suggest": {
        "ircmaxell/random-lib": "Fallback random byte generator for Zend\\Math\\Rand if OpenSSL/Mcrypt extensions are unavailable"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "2.2-dev",
            "dev-develop": "2.3-dev"
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */
namespace Zend\Math\Source;

use RandomLib;
use SecurityLib\Strength;

/**
 * Author:
 * George Argyros <argyros.george@gmail.com>
 *
 * Copyright (c) 2012, George Argyros
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * * Neither the name of the <organization> nor the
 * names of its contributors may be used to endorse or promote products
 * derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL GEORGE ARGYROS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 *
 * The function is providing, at least at the systems tested :),
 * $len bytes of entropy under any PHP installation or operating system.
 * The execution time should be at most 10-20 ms in any system.
 *
 * Modified by Padraic Brady as part of Zend Framework to use 25% of the
 * original version's iterations.
 */
class HashTiming implements RandomLib\Source
{

    /**
     * Return an instance of Strength indicating the strength of the source
     *
     * @return Strength An instance of one of the strength classes
     */
    public static function getStrength()
    {
        return new Strength(Strength::VERYLOW);
    }

    /**
     * Generate a random string of the specified size
     *
     * @param int $size The size of the requested random string
     *
     * @return string A string of the requested size
     */
    public function generate($size)
    {
        $result         = '';
        $entropy        = '';
        $msec_per_round = 400;
        $bits_per_round = 2;
        $total          = $size;
        $bytes          = 0;
        $hash_length    = 20;
        $rounds         = 0;
        while (strlen($result) < $size) {
            $bytes  = ($total > $hash_length)? $hash_length : $total;
            $total -= $bytes;
            for ($i=1; $i < 3; $i++) {
                $t1   = microtime(true);
                $seed = mt_rand();
                for ($j=1; $j < 50; $j++) {
                    $seed = sha1($seed);
                }
                $t2 = microtime(true);
                $entropy .= $t1 . $t2;
            }
            $div = (int) (($t2 - $t1) * 1000000);
            if ($div <= 0) {
                $div = 400;
            }
            $rounds = (int) ($msec_per_round * 50 / $div);
            $iter = $bytes * (int) (ceil(8 / $bits_per_round));
            for ($i = 0; $i < $iter; $i ++) {
                $t1 = microtime();
                $seed = sha1(mt_rand());
                for ($j = 0; $j < $rounds; $j++) {
                   $seed = sha1($seed);
                }
                $t2 = microtime();
                $entropy .= $t1 . $t2;
            }
            $result .= sha1($entropy, true);
        }
        return substr($result, 0, $size);
    }

}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Math\BigInteger;

abstract class BigInteger
{
    /**
     * Plugin manager for loading adapters
     *
     * @var null|AdapterPluginManager
     */
    protected static $adapters = null;

    /**
     * The default adapter.
     *
     * @var Adapter\AdapterInterface
     */
    protected static $defaultAdapter = null;

    /**
     * Create a BigInteger adapter instance
     *
     * @param  string|Adapter\AdapterInterface|null $adapterName
     * @return Adapter\AdapterInterface
     */
    public static function factory($adapterName = null)
    {
        if (null === $adapterName) {
            return static::getAvailableAdapter();
        } elseif ($adapterName instanceof Adapter\AdapterInterface) {
            return $adapterName;
        }

        return static::getAdapterPluginManager()->get($adapterName);
    }

    /**
     * Set adapter plugin manager
     *
     * @param AdapterPluginManager $adapters
     */
    public static function setAdapterPluginManager(AdapterPluginManager $adapters)
    {
        static::$adapters = $adapters;
    }

    /**
     * Get the adapter plugin manager
     *
     * @return AdapterPluginManager
     */
    public static function getAdapterPluginManager()
    {
        if (static::$adapters === null) {
            static::$adapters = new AdapterPluginManager();
        }
        return static::$adapters;
    }

    /**
     * Set default BigInteger adapter
     *
     * @param string|Adapter\AdapterInterface $adapter
     */
    public static function setDefaultAdapter($adapter)
    {
        static::$defaultAdapter = static::factory($adapter);
    }

    /**
     * Get default BigInteger adapter
     *
     * @return null|Adapter\AdapterInterface
     */
    public static function getDefaultAdapter()
    {
        if (null === static::$defaultAdapter) {
            static::$defaultAdapter = static::getAvailableAdapter();
        }
        return static::$defaultAdapter;
    }

    /**
     * Determine and return available adapter
     *
     * @return Adapter\AdapterInterface
     * @throws Exception\RuntimeException
     */
    public static function getAvailableAdapter()
    {
        if (extension_loaded('gmp')) {
            $adapterName = 'Gmp';
        } elseif (extension_loaded('bcmath')) {
            $adapterName = 'Bcmath';
        } else {
            throw new Exception\RuntimeException('Big integer math support is not detected');
        }
        return static::factory($adapterName);
    }

    /**
     * Call adapter methods statically
     *
     * @param  string $method
     * @param  mixed $args
     * @return mixed
     */
    public static function __callStatic($method, $args)
    {
        $adapter = static::getDefaultAdapter();
        return call_user_func_array(array($adapter, $method), $args);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Math\BigInteger\Exception;

use Zend\Math\Exception;

/**
 * Invalid argument exception
 */
class InvalidArgumentException extends Exception\InvalidArgumentException implements ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Math\BigInteger\Exception;

use Zend\Math\Exception;

/**
 * Runtime exception
 */
class RuntimeException extends Exception\RuntimeException implements ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Math\BigInteger\Exception;

use Zend\Math\Exception;

/**
 * Invalid argument exception
 */
interface ExceptionInterface extends Exception\ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Math\BigInteger\Exception;

/**
 * Division by zero exception
 */
class DivisionByZeroException extends RuntimeException implements ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Math\BigInteger;

use Zend\ServiceManager\AbstractPluginManager;

/**
 * Plugin manager implementation for BigInteger adapters.
 *
 * Enforces that adapters retrieved are instances of
 * Adapter\AdapterInterface. Additionally, it registers a number of default
 * adapters available.
 */
class AdapterPluginManager extends AbstractPluginManager
{
    /**
     * Default set of adapters
     *
     * @var array
     */
    protected $invokableClasses = array(
        'bcmath' => 'Zend\Math\BigInteger\Adapter\Bcmath',
        'gmp'    => 'Zend\Math\BigInteger\Adapter\Gmp',
    );

    /**
     * Validate the plugin
     *
     * Checks that the adapter loaded is an instance of Adapter\AdapterInterface.
     *
     * @param  mixed $plugin
     * @return void
     * @throws Exception\RuntimeException if invalid
     */
    public function validatePlugin($plugin)
    {
        if ($plugin instanceof Adapter\AdapterInterface) {
            // we're okay
            return;
        }

        throw new Exception\RuntimeException(sprintf(
            'Plugin of type %s is invalid; must implement %s\Adapter\AdapterInterface',
            (is_object($plugin) ? get_class($plugin) : gettype($plugin)),
            __NAMESPACE__
        ));
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Math\BigInteger\Adapter;

use Zend\Math\BigInteger\Exception;

/**
 * Bcmath extension adapter
 */
class Bcmath implements AdapterInterface
{
    /**
     * Constructor
     * Sets Bcmath scale factor to zero
     */
    public function __construct()
    {
        bcscale(0);
    }

    /**
     * Create string representing big integer in decimal form from arbitrary integer format
     *
     * @param  string $operand
     * @param  int|null $base
     * @return bool|string
     */
    public function init($operand, $base = null)
    {
        $sign    = (strpos($operand, '-') === 0) ? '-' : '';
        $operand = ltrim($operand, '-+');

        if (null === $base) {
            // decimal
            if (preg_match('#^([1-9][0-9]*)$#', $operand, $m)) {
                $base    = 10;
                $operand = $m[1];
            // octal
            } elseif (preg_match('#^(0[0-7]+)$#', $operand, $m)) {
                $base    = 8;
                $operand = $m[1];
            // hex
            } elseif (preg_match('#^(?:0x)?([0-9a-f]+)$#', strtolower($operand), $m)) {
                $base    = 16;
                $operand = $m[1];
            // scientific notation
            } elseif (preg_match('#^([1-9]?\.?[0-9]+)[eE]\+?([0-9]+)$#', $operand, $m)) {
                $base    = 10;
                $operand = bcmul($m[1], bcpow('10', $m[2]));
            } else {
                return false;
            }
        }

        if ($base != 10) {
            $operand = $this->baseConvert($operand, $base, 10);
        }

        $prod = bcmul($operand, '1');
        if (bccomp($operand, $prod) !== 0) {
            return false;
        }

        return $sign . $operand;
    }

    /**
     * Add two big integers
     *
     * @param  string $leftOperand
     * @param  string $rightOperand
     * @return string
     */
    public function add($leftOperand, $rightOperand)
    {
        return bcadd($leftOperand, $rightOperand);
    }

    /**
     * Subtract two big integers
     *
     * @param  string $leftOperand
     * @param  string $rightOperand
     * @return string
     */
    public function sub($leftOperand, $rightOperand)
    {
        return bcsub($leftOperand, $rightOperand);
    }

    /**
     * Multiply two big integers
     *
     * @param string $leftOperand
     * @param string $rightOperand
     * @return string
     */
    public function mul($leftOperand, $rightOperand)
    {
        return bcmul($leftOperand, $rightOperand);
    }

    /**
     * Divide two big integers and return integer part result.
     * Raises exception if the divisor is zero.
     *
     * @param string $leftOperand
     * @param string $rightOperand
     * @return string
     * @throws Exception\DivisionByZeroException
     */
    public function div($leftOperand, $rightOperand)
    {
        if ($rightOperand == 0) {
            throw new Exception\DivisionByZeroException(
                "Division by zero; divisor = {$rightOperand}"
            );
        }

        $result = bcdiv($leftOperand, $rightOperand);

        return $result;
    }

    /**
     * Raise a big integers to another
     *
     * @param  string $operand
     * @param  string $exp
     * @return string
     */
    public function pow($operand, $exp)
    {
        return bcpow($operand, $exp);
    }

    /**
     * Get the square root of a big integer
     *
     * @param  string $operand
     * @return string
     */
    public function sqrt($operand)
    {
        return bcsqrt($operand);
    }

    /**
     * Get absolute value of a big integer
     *
     * @param  string $operand
     * @return string
     */
    public function abs($operand)
    {
        return ltrim($operand, '-');
    }

    /**
     * Get modulus of a big integer
     *
     * @param  string $leftOperand
     * @param  string $rightOperand
     * @return string
     */
    public function mod($leftOperand, $rightOperand)
    {
        return bcmod($leftOperand, $rightOperand);
    }

    /**
     * Raise a big integer to another, reduced by a specified modulus
     *
     * @param  string $leftOperand
     * @param  string $rightOperand
     * @param  string $modulus
     * @return string
     */
    public function powmod($leftOperand, $rightOperand, $modulus)
    {
        return bcpowmod($leftOperand, $rightOperand, $modulus);
    }

    /**
     * Compare two big integers and returns result as an integer where
     * Returns < 0 if leftOperand is less than rightOperand;
     * > 0 if leftOperand is greater than rightOperand, and 0 if they are equal.
     *
     * @param  string $leftOperand
     * @param  string $rightOperand
     * @return int
     */
    public function comp($leftOperand, $rightOperand)
    {
        return bccomp($leftOperand, $rightOperand);
    }

    /**
     * Convert big integer into it's binary number representation
     *
     * @param  string $operand
     * @param  bool $twoc return in two's complement form
     * @return string
     */
    public function intToBin($operand, $twoc = false)
    {
        $nb = chr(0);
        $isNegative = (strpos($operand, '-') === 0) ? true : false;
        $operand    = ltrim($operand, '+-0');

        if (empty($operand)) {
            return $nb;
        }

        if ($isNegative && $twoc) {
            $operand = bcsub($operand, '1');
        }

        $bytes = '';
        while (bccomp($operand, '0', 0) > 0) {
            $temp    = bcmod($operand, '16777216');
            $bytes   = chr($temp >> 16) . chr($temp >> 8) . chr($temp) . $bytes;
            $operand = bcdiv($operand, '16777216');
        }
        $bytes = ltrim($bytes, $nb);

        if ($twoc) {
            if (ord($bytes[0]) & 0x80) {
                $bytes = $nb . $bytes;
            }
            return $isNegative ? ~$bytes : $bytes;
        }

        return $bytes;
    }

    /**
     * Convert big integer into it's binary number representation
     *
     * @param  string $bytes
     * @param  bool   $twoc whether binary number is in twos' complement form
     * @return string
     */
    public function binToInt($bytes, $twoc = false)
    {
        $isNegative = ((ord($bytes[0]) & 0x80) && $twoc);

        if ($isNegative) {
            $bytes = ~$bytes;
        }

        $len = (strlen($bytes) + 3) & 0xfffffffc;
        $bytes = str_pad($bytes, $len, chr(0), STR_PAD_LEFT);

        $result = '0';
        for ($i = 0; $i < $len; $i += 4) {
            $result = bcmul($result, '4294967296'); // 2**32
            $result = bcadd($result, 0x1000000 * ord($bytes[$i]) +
                    ((ord($bytes[$i + 1]) << 16) |
                     (ord($bytes[$i + 2]) << 8) |
                      ord($bytes[$i + 3])));
        }

        if ($isNegative) {
            $result = bcsub('-' . $result, '1');
        }

        return $result;
    }

    /**
     * Base conversion. Bases 2..62 are supported
     *
     * @param  string $operand
     * @param  int    $fromBase
     * @param  int    $toBase
     * @return string
     * @throws Exception\InvalidArgumentException
     */
    public function baseConvert($operand, $fromBase, $toBase = 10)
    {
        if ($fromBase == $toBase) {
            return $operand;
        }

        if ($fromBase < 2 || $fromBase > 62) {
            throw new Exception\InvalidArgumentException(
                "Unsupported base: {$fromBase}, should be 2..62"
            );
        }
        if ($toBase < 2 || $toBase > 62) {
            throw new Exception\InvalidArgumentException(
                "Unsupported base: {$toBase}, should be 2..62"
            );
        }

        $sign    = (strpos($operand, '-') === 0) ? '-' : '';
        $operand = ltrim($operand, '-+');

        $chars = self::BASE62_ALPHABET;

        // convert to decimal
        if ($fromBase == 10) {
            $decimal = $operand;
        } else {
            $decimal = '0';
            for ($i = 0, $len  = strlen($operand); $i < $len; $i++) {
                $decimal = bcmul($decimal, $fromBase);
                $decimal = bcadd($decimal, strpos($chars, $operand[$i]));
            }
        }

        if ($toBase == 10) {
            return $decimal;
        }

        // convert decimal to base
        $result = '';
        do {
            $remainder = bcmod($decimal, $toBase);
            $decimal   = bcdiv($decimal, $toBase);
            $result    = $chars[$remainder] . $result;
        } while (bccomp($decimal, '0'));

        return $sign . $result;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Math\BigInteger\Adapter;

interface AdapterInterface
{
    /**
     * Base62 alphabet for arbitrary base conversion
     */
    const BASE62_ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

    /**
     * Create adapter-specific representation of a big integer
     *
     * @param  string $operand
     * @param  int|null $base
     * @return mixed
     */
    public function init($operand, $base = null);

    /**
     * Add two big integers
     *
     * @param  string $leftOperand
     * @param  string $rightOperand
     * @return string
     */
    public function add($leftOperand, $rightOperand);

    /**
     * Subtract two big integers
     *
     * @param  string $leftOperand
     * @param  string $rightOperand
     * @return string
     */
    public function sub($leftOperand, $rightOperand);

    /**
     * Multiply two big integers
     *
     * @param  string $leftOperand
     * @param  string $rightOperand
     * @return string
     */
    public function mul($leftOperand, $rightOperand);

    /**
     * Divide two big integers
     * (this method returns only int part of result)
     *
     * @param  string $leftOperand
     * @param  string $rightOperand
     * @return string
     */
    public function div($leftOperand, $rightOperand);

    /**
     * Raise a big integers to another
     *
     * @param  string $operand
     * @param  string $exp
     * @return string
     */
    public function pow($operand, $exp);

    /**
     * Get the square root of a big integer
     *
     * @param  string $operand
     * @return string
     */
    public function sqrt($operand);

    /**
     * Get absolute value of a big integer
     *
     * @param  string $operand
     * @return string
     */
    public function abs($operand);

    /**
     * Get modulus of a big integer
     *
     * @param  string $leftOperand
     * @param  string $modulus
     * @return string
     */
    public function mod($leftOperand, $modulus);

    /**
     * Raise a big integer to another, reduced by a specified modulus
     *
     * @param  string $leftOperand
     * @param  string $rightOperand
     * @param  string $modulus
     * @return string
     */
    public function powmod($leftOperand, $rightOperand, $modulus);

    /**
     * Compare two big integers
     * Returns < 0 if leftOperand is less than rightOperand;
     * > 0 if leftOperand is greater than rightOperand, and 0 if they are equal.
     *
     * @param  string $leftOperand
     * @param  string $rightOperand
     * @return int
     */
    public function comp($leftOperand, $rightOperand);

    /**
     * Convert big integer into it's binary number representation
     *
     * @param  string $int
     * @param  bool $twoc
     * @return string
     */
    public function intToBin($int, $twoc = false);

    /**
     * Convert binary number into big integer
     *
     * @param  string $bytes
     * @param  bool $twoc
     * @return string
     */
    public function binToInt($bytes, $twoc = false);

    /**
     * Convert a number between arbitrary bases
     *
     * @param  string $operand
     * @param  int $fromBase
     * @param  int $toBase
     * @return string
     */
    public function baseConvert($operand, $fromBase, $toBase = 10);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Math\BigInteger\Adapter;

use Zend\Math\BigInteger\Exception;

/**
 * GMP extension adapter
 */
class Gmp implements AdapterInterface
{
    /**
     * Create string representing big integer in decimal form from arbitrary integer format
     *
     * @param  string $operand
     * @param  int|null $base
     * @return bool|string
     */
    public function init($operand, $base = null)
    {
        $sign    = (strpos($operand, '-') === 0) ? '-' : '';
        $operand = ltrim($operand, '-+');

        if (null === $base) {
            // scientific notation
            if (preg_match('#^(?:([1-9])\.)?([0-9]+)[eE]\+?([0-9]+)$#', $operand, $m)) {
                if (!empty($m[1])) {
                    if ($m[3] < strlen($m[2])) {
                        return false;
                    }
                } else {
                    $m[1] = '';
                }
                $operand = str_pad(($m[1] . $m[2]), ($m[3] + 1), '0', STR_PAD_RIGHT);
            } else {
                // let GMP guess base
                $base = 0;
            }
        }

        $res = gmp_init($sign . $operand, $base);
        if ($res === false) {
            return false;
        }

        return gmp_strval($res);
    }

    /**
     * Add two big integers
     *
     * @param  string $leftOperand
     * @param  string $rightOperand
     * @return string
     */
    public function add($leftOperand, $rightOperand)
    {
        $result = gmp_add($leftOperand, $rightOperand);
        return gmp_strval($result);
    }

    /**
     * Subtract two big integers
     *
     * @param  string $leftOperand
     * @param  string $rightOperand
     * @return string
     */
    public function sub($leftOperand, $rightOperand)
    {
        $result = gmp_sub($leftOperand, $rightOperand);
        return gmp_strval($result);
    }

    /**
     * Multiply two big integers
     *
     * @param  string $leftOperand
     * @param  string $rightOperand
     * @return string
     */
    public function mul($leftOperand, $rightOperand)
    {
        $result = gmp_mul($leftOperand, $rightOperand);
        return gmp_strval($result);
    }

    /**
     * Divide two big integers and return integer part result.
     * Raises exception if the divisor is zero.
     *
     * @param  string $leftOperand
     * @param  string $rightOperand
     * @return string|null
     * @throws Exception\DivisionByZeroException
     */
    public function div($leftOperand, $rightOperand)
    {
        if ($rightOperand == 0) {
            throw new Exception\DivisionByZeroException(
                "Division by zero; divisor = {$rightOperand}"
            );
        }

        $result = gmp_div_q($leftOperand, $rightOperand);
        return gmp_strval($result);
    }

    /**
     * Raise a big integers to another
     *
     * @param  string $operand
     * @param  string $exp
     * @return string
     */
    public function pow($operand, $exp)
    {
        $result = gmp_pow($operand, $exp);
        return gmp_strval($result);
    }

    /**
     * Get the square root of a big integer
     *
     * @param  string $operand
     * @return string
     */
    public function sqrt($operand)
    {
        $result = gmp_sqrt($operand);
        return gmp_strval($result);
    }

    /**
     * Get absolute value of a big integer
     *
     * @param  string $operand
     * @return string
     */
    public function abs($operand)
    {
        $result = gmp_abs($operand);
        return gmp_strval($result);
    }

    /**
     * Get modulus of a big integer
     *
     * @param  string $leftOperand
     * @param  string $modulus
     * @return string
     */
    public function mod($leftOperand, $modulus)
    {
        $result = gmp_mod($leftOperand, $modulus);
        return gmp_strval($result);
    }

    /**
     * Raise a big integer to another, reduced by a specified modulus
     *
     * @param  string $leftOperand
     * @param  string $rightOperand
     * @param  string $modulus
     * @return string
     */
    public function powmod($leftOperand, $rightOperand, $modulus)
    {
        $result = gmp_powm($leftOperand, $rightOperand, $modulus);
        return gmp_strval($result);
    }

    /**
     * Compare two big integers and returns result as an integer where
     * Returns < 0 if leftOperand is less than rightOperand;
     * > 0 if leftOperand is greater than rightOperand, and 0 if they are equal.
     *
     * @param  string $leftOperand
     * @param  string $rightOperand
     * @return int
     */
    public function comp($leftOperand, $rightOperand)
    {
        return gmp_cmp($leftOperand, $rightOperand);
    }

    /**
     * Convert big integer into it's binary number representation
     *
     * @param  string $int
     * @param  bool $twoc  return in twos' complement form
     * @return string
     */
    public function intToBin($int, $twoc = false)
    {
        $nb         = chr(0);
        $isNegative = (strpos($int, '-') === 0) ? true : false;
        $int        = ltrim($int, '+-0');

        if (empty($int)) {
            return $nb;
        }

        if ($isNegative && $twoc) {
            $int = gmp_sub($int, '1');
        }

        $hex  = gmp_strval($int, 16);
        if (strlen($hex) & 1) {
            $hex = '0' . $hex;
        }

        $bytes = pack('H*', $hex);
        $bytes = ltrim($bytes, $nb);

        if ($twoc) {
            if (ord($bytes[0]) & 0x80) {
                $bytes = $nb . $bytes;
            }
            return $isNegative ? ~$bytes : $bytes;
        }

        return $bytes;
    }

    /**
     * Convert binary number into big integer
     *
     * @param  string $bytes
     * @param  bool $twoc  whether binary number is in twos' complement form
     * @return string
     */
    public function binToInt($bytes, $twoc = false)
    {
        $isNegative = ((ord($bytes[0]) & 0x80) && $twoc);

        $sign = '';
        if ($isNegative) {
            $bytes = ~$bytes;
            $sign  = '-';
        }

        $result = gmp_init($sign . bin2hex($bytes), 16);

        if ($isNegative) {
            $result = gmp_sub($result, '1');
        }

        return gmp_strval($result);
    }

    /**
     * Base conversion. Bases 2..62 are supported
     *
     * @param  string $operand
     * @param  int    $fromBase
     * @param  int    $toBase
     * @return string
     * @throws Exception\InvalidArgumentException
     */
    public function baseConvert($operand, $fromBase, $toBase = 10)
    {
        if ($fromBase == $toBase) {
            return $operand;
        }

        if ($fromBase < 2 || $fromBase > 62) {
            throw new Exception\InvalidArgumentException(
                "Unsupported base: {$fromBase}, should be 2..62"
            );
        }
        if ($toBase < 2 || $toBase > 62) {
            throw new Exception\InvalidArgumentException(
                "Unsupported base: {$toBase}, should be 2..62"
            );
        }

        if ($fromBase <= 36 && $toBase <= 36) {
            return gmp_strval(gmp_init($operand, $fromBase), $toBase);
        }

        $sign    = (strpos($operand, '-') === 0) ? '-' : '';
        $operand = ltrim($operand, '-+');

        $chars = self::BASE62_ALPHABET;

        // convert operand to decimal
        if ($fromBase !== 10) {
            $decimal = '0';
            for ($i = 0, $len = strlen($operand); $i < $len; $i++) {
                $decimal = gmp_mul($decimal, $fromBase);
                $decimal = gmp_add($decimal, strpos($chars, $operand[$i]));
            }
        } else {
            $decimal = gmp_init($operand);
        }

        if ($toBase == 10) {
            return gmp_strval($decimal);
        }

        // convert decimal to base
        $result = '';
        do {
            list($decimal, $remainder) = gmp_div_qr($decimal, $toBase);
            $pos    = gmp_strval($remainder);
            $result = $chars[$pos] . $result;
        } while (gmp_cmp($decimal, '0'));

        return $sign . $result;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Math;

use RandomLib;

/**
 * Pseudorandom number generator (PRNG)
 */
abstract class Rand
{

    /**
     * Alternative random byte generator using RandomLib
     *
     * @var RandomLib\Generator
     */
    protected static $generator = null;

    /**
     * Generate random bytes using OpenSSL or Mcrypt and mt_rand() as fallback
     *
     * @param  int $length
     * @param  bool $strong true if you need a strong random generator (cryptography)
     * @return string
     * @throws Exception\RuntimeException
     */
    public static function getBytes($length, $strong = false)
    {
        if ($length <= 0) {
            return false;
        }
        $bytes = '';
        if (function_exists('openssl_random_pseudo_bytes')
            && (version_compare(PHP_VERSION, '5.3.4') >= 0
            || strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')
        ) {
            $bytes = openssl_random_pseudo_bytes($length, $usable);
            if (true === $usable) {
                return $bytes;
            }
        }
        if (function_exists('mcrypt_create_iv')
            && (version_compare(PHP_VERSION, '5.3.7') >= 0
            || strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')
        ) {
            $bytes = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
            if ($bytes !== false && strlen($bytes) === $length) {
                return $bytes;
            }
        }
        $checkAlternatives = (file_exists('/dev/urandom') && is_readable('/dev/urandom'))
            || class_exists('\\COM', false);
        if (true === $strong && false === $checkAlternatives) {
            throw new Exception\RuntimeException (
                'This PHP environment doesn\'t support secure random number generation. ' .
                'Please consider installing the OpenSSL and/or Mcrypt extensions'
            );
        }
        $generator = self::getAlternativeGenerator();
        return $generator->generate($length);
    }

    /**
     * Retrieve a fallback/alternative RNG generator
     *
     * @return RandomLib\Generator
     */
    public static function getAlternativeGenerator()
    {
        if (!is_null(static::$generator)) {
            return static::$generator;
        }
        if (!class_exists('RandomLib\\Factory')) {
            throw new Exception\RuntimeException(
                'The RandomLib fallback pseudorandom number generator (PRNG) '
                . ' must be installed in the absence of the OpenSSL and '
                . 'Mcrypt extensions'
            );
        }
        $factory = new RandomLib\Factory;
        $factory->registerSource(
            'HashTiming',
            'Zend\Math\Source\HashTiming'
        );
        static::$generator = $factory->getMediumStrengthGenerator();
        return static::$generator;
    }

    /**
     * Generate random boolean
     *
     * @param  bool $strong true if you need a strong random generator (cryptography)
     * @return bool
     */
    public static function getBoolean($strong = false)
    {
        $byte = static::getBytes(1, $strong);
        return (bool) (ord($byte) % 2);
    }

    /**
     * Generate a random integer between $min and $max
     *
     * @param  int $min
     * @param  int $max
     * @param  bool $strong true if you need a strong random generator (cryptography)
     * @return int
     * @throws Exception\DomainException
     */
    public static function getInteger($min, $max, $strong = false)
    {
        if ($min > $max) {
            throw new Exception\DomainException(
                'The min parameter must be lower than max parameter'
            );
        }
        $range = $max - $min;
        if ($range == 0) {
            return $max;
        } elseif ($range > PHP_INT_MAX || is_float($range)) {
            throw new Exception\DomainException(
                'The supplied range is too great to generate'
            );
        }
        $log    = log($range, 2);
        $bytes  = (int) ($log / 8) + 1;
        $bits   = (int) $log + 1;
        $filter = (int) (1 << $bits) - 1;
        do {
            $rnd = hexdec(bin2hex(self::getBytes($bytes, $strong)));
            $rnd = $rnd & $filter;
        } while ($rnd > $range);

        return ($min + $rnd);
    }

    /**
     * Generate random float (0..1)
     * This function generates floats with platform-dependent precision
     *
     * PHP uses double precision floating-point format (64-bit) which has
     * 52-bits of significand precision. We gather 7 bytes of random data,
     * and we fix the exponent to the bias (1023). In this way we generate
     * a float of 1.mantissa.
     *
     * @param  bool $strong  true if you need a strong random generator (cryptography)
     * @return float
     */
    public static function getFloat($strong = false)
    {
        $bytes    = static::getBytes(7, $strong);
        $bytes[6] = $bytes[6] | chr(0xF0);
        $bytes   .= chr(63); // exponent bias (1023)
        list(, $float) = unpack('d', $bytes);

        return ($float - 1);
    }

    /**
     * Generate a random string of specified length.
     *
     * Uses supplied character list for generating the new string.
     * If no character list provided - uses Base 64 character set.
     *
     * @param  int $length
     * @param  string|null $charlist
     * @param  bool $strong  true if you need a strong random generator (cryptography)
     * @return string
     * @throws Exception\DomainException
     */
    public static function getString($length, $charlist = null, $strong = false)
    {
        if ($length < 1) {
            throw new Exception\DomainException('Length should be >= 1');
        }

        // charlist is empty or not provided
        if (empty($charlist)) {
            $numBytes = ceil($length * 0.75);
            $bytes    = static::getBytes($numBytes, $strong);
            return substr(rtrim(base64_encode($bytes), '='), 0, $length);
        }

        $listLen = strlen($charlist);

        if ($listLen == 1) {
            return str_repeat($charlist, $length);
        }

        $bytes  = static::getBytes($length, $strong);
        $pos    = 0;
        $result = '';
        for ($i = 0; $i < $length; $i++) {
            $pos     = ($pos + ord($bytes[$i])) % $listLen;
            $result .= $charlist[$pos];
        }

        return $result;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Math\Exception;

/**
 * Invalid argument exception
 */
class InvalidArgumentException extends \InvalidArgumentException implements
    ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Math\Exception;

/**
 * Runtime argument exception
 */
class RuntimeException extends \RuntimeException implements
    ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Math\Exception;

/**
 * Invalid argument exception
 */
class DomainException extends \DomainException implements ExceptionInterface
{}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Math\Exception;

interface ExceptionInterface
{}
{
    "name": "zendframework/zend-cache",
    "description": "provides a generic way to cache any data",
    "license": "BSD-3-Clause",
    "keywords": [
        "zf2",
        "cache"
    ],
    "autoload": {
        "psr-0": {
            "Zend\\Cache\\": ""
        }
    },
    "target-dir": "Zend/Cache",
    "require": {
        "php": ">=5.3.3",
        "zendframework/zend-stdlib": "self.version",
        "zendframework/zend-servicemanager": "self.version",
        "zendframework/zend-eventmanager": "self.version"
    },
    "require-dev": {
        "zendframework/zend-serializer": "self.version"
    },
    "suggest": {
        "zendframework/zend-serializer": "Zend\\Serializer component",
        "zendframework/zend-session": "Zend\\Session component",
        "ext-apc": "APC >= 3.1.6 to use the APC storage adapter",
        "ext-dba": "DBA, to use the DBA storage adapter",
        "ext-memcached": "Memcached >= 1.0.0 to use the Memcached storage adapter",
        "ext-wincache": "WinCache, to use the WinCache storage adapter"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "2.2-dev",
            "dev-develop": "2.3-dev"
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage;

interface ClearExpiredInterface
{
    /**
     * Remove expired items
     *
     * @return bool
     */
    public function clearExpired();
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage;

use ArrayObject;
use Exception;

class ExceptionEvent extends PostEvent
{
    /**
     * The exception to be thrown
     *
     * @var Exception
     */
    protected $exception;

    /**
     * Throw the exception or use the result
     *
     * @var bool
     */
    protected $throwException = true;

    /**
     * Constructor
     *
     * Accept a target and its parameters.
     *
     * @param  string $name
     * @param  StorageInterface $storage
     * @param  ArrayObject $params
     * @param  mixed $result
     * @param  Exception $exception
     */
    public function __construct($name, StorageInterface $storage, ArrayObject $params, & $result, Exception $exception)
    {
        parent::__construct($name, $storage, $params, $result);
        $this->setException($exception);
    }

    /**
     * Set the exception to be thrown
     *
     * @param  Exception $exception
     * @return ExceptionEvent
     */
    public function setException(Exception $exception)
    {
        $this->exception = $exception;
        return $this;
    }

    /**
     * Get the exception to be thrown
     *
     * @return Exception
     */
    public function getException()
    {
        return $this->exception;
    }

    /**
     * Throw the exception or use the result
     *
     * @param  bool $flag
     * @return ExceptionEvent
     */
    public function setThrowException($flag)
    {
        $this->throwException = (bool) $flag;
        return $this;
    }

    /**
     * Throw the exception or use the result
     *
     * @return bool
     */
    public function getThrowException()
    {
        return $this->throwException;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage;

interface ClearByNamespaceInterface
{
    /**
     * Remove items of given namespace
     *
     * @param string $namespace
     * @return bool
     */
    public function clearByNamespace($namespace);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage;

use IteratorAggregate;

/**
 *
 * @method IteratorInterface getIterator() Get the storage iterator
 */
interface IterableInterface extends IteratorAggregate
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage;

interface AvailableSpaceCapableInterface
{
    /**
     * Get available space in bytes
     *
     * @return int|float
     */
    public function getAvailableSpace();
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage;

interface TaggableInterface
{
    /**
     * Set tags to an item by given key.
     * An empty array will remove all tags.
     *
     * @param string   $key
     * @param string[] $tags
     * @return bool
     */
    public function setTags($key, array $tags);

    /**
     * Get tags of an item by given key
     *
     * @param string $key
     * @return string[]|FALSE
     */
    public function getTags($key);

    /**
     * Remove items matching given tags.
     *
     * If $disjunction only one of the given tags must match
     * else all given tags must match.
     *
     * @param string[] $tags
     * @param  bool  $disjunction
     * @return bool
     */
    public function clearByTags(array $tags, $disjunction = false);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage;

use Zend\Cache\Exception;
use Zend\ServiceManager\AbstractPluginManager;

/**
 * Plugin manager implementation for cache plugins
 *
 * Enforces that plugins retrieved are instances of
 * Plugin\PluginInterface. Additionally, it registers a number of default
 * plugins available.
 */
class PluginManager extends AbstractPluginManager
{
    /**
     * Default set of plugins
     *
     * @var array
     */
    protected $invokableClasses = array(
        'clearexpiredbyfactor' => 'Zend\Cache\Storage\Plugin\ClearExpiredByFactor',
        'exceptionhandler'     => 'Zend\Cache\Storage\Plugin\ExceptionHandler',
        'ignoreuserabort'      => 'Zend\Cache\Storage\Plugin\IgnoreUserAbort',
        'optimizebyfactor'     => 'Zend\Cache\Storage\Plugin\OptimizeByFactor',
        'serializer'           => 'Zend\Cache\Storage\Plugin\Serializer',
    );

    /**
     * Do not share by default
     *
     * @var array
     */
    protected $shareByDefault = false;

    /**
     * Validate the plugin
     *
     * Checks that the plugin loaded is an instance of Plugin\PluginInterface.
     *
     * @param  mixed $plugin
     * @return void
     * @throws Exception\RuntimeException if invalid
     */
    public function validatePlugin($plugin)
    {
        if ($plugin instanceof Plugin\PluginInterface) {
            // we're okay
            return;
        }

        throw new Exception\RuntimeException(sprintf(
            'Plugin of type %s is invalid; must implement %s\Plugin\PluginInterface',
            (is_object($plugin) ? get_class($plugin) : gettype($plugin)),
            __NAMESPACE__
        ));
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage;

interface FlushableInterface
{
    /**
     * Flush the whole storage
     *
     * @return bool
     */
    public function flush();
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage;

interface OptimizableInterface
{
    /**
     * Optimize the storage
     *
     * @return bool
     */
    public function optimize();
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage;

use ArrayObject;

class PostEvent extends Event
{
    /**
     * The result/return value
     *
     * @var mixed
     */
    protected $result;

    /**
     * Constructor
     *
     * Accept a target and its parameters.
     *
     * @param  string           $name
     * @param  StorageInterface $storage
     * @param  ArrayObject      $params
     * @param  mixed            $result
     */
    public function __construct($name, StorageInterface $storage, ArrayObject $params, & $result)
    {
        parent::__construct($name, $storage, $params);
        $this->setResult($result);
    }

    /**
     * Set the result/return value
     *
     * @param  mixed $value
     * @return PostEvent
     */
    public function setResult(& $value)
    {
        $this->result = & $value;
        return $this;
    }

    /**
     * Get the result/return value
     *
     * @return mixed
     */
    public function & getResult()
    {
        return $this->result;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage;

interface ClearByPrefixInterface
{
    /**
     * Remove items matching given prefix
     *
     * @param string $prefix
     * @return bool
     */
    public function clearByPrefix($prefix);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage;

use Iterator;

interface IteratorInterface extends Iterator
{

    const CURRENT_AS_SELF     = 0;
    const CURRENT_AS_KEY      = 1;
    const CURRENT_AS_VALUE    = 2;
    const CURRENT_AS_METADATA = 3;

    /**
     * Get storage instance
     *
     * @return StorageInterface
     */
    public function getStorage();

    /**
     * Get iterator mode
     *
     * @return int Value of IteratorInterface::CURRENT_AS_*
     */
    public function getMode();

    /**
     * Set iterator mode
     *
     * @param int $mode Value of IteratorInterface::CURRENT_AS_*
     * @return IteratorInterface Fluent interface
     */
    public function setMode($mode);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage;

use ArrayObject;
use Zend\EventManager\Event as BaseEvent;

class Event extends BaseEvent
{
    /**
     * Constructor
     *
     * Accept a storage adapter and its parameters.
     *
     * @param  string           $name Event name
     * @param  StorageInterface $storage
     * @param  ArrayObject      $params
     */
    public function __construct($name, StorageInterface $storage, ArrayObject $params)
    {
        parent::__construct($name, $storage, $params);
    }

    /**
     * Set the event target/context
     *
     * @param  StorageInterface $target
     * @return Event
     * @see    Zend\EventManager\Event::setTarget()
     */
    public function setTarget($target)
    {
        return $this->setStorage($target);
    }

    /**
     * Alias of setTarget
     *
     * @param  StorageInterface $storage
     * @return Event
     * @see    Zend\EventManager\Event::setTarget()
     */
    public function setStorage(StorageInterface $storage)
    {
        $this->target = $storage;
        return $this;
    }

    /**
     * Alias of getTarget
     *
     * @return StorageInterface
     */
    public function getStorage()
    {
        return $this->getTarget();
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage;

use Traversable;

interface StorageInterface
{
    /**
     * Set options.
     *
     * @param array|Traversable|Adapter\AdapterOptions $options
     * @return StorageInterface Fluent interface
     */
    public function setOptions($options);

    /**
     * Get options
     *
     * @return Adapter\AdapterOptions
     */
    public function getOptions();

    /* reading */

    /**
     * Get an item.
     *
     * @param  string  $key
     * @param  bool $success
     * @param  mixed   $casToken
     * @return mixed Data on success, null on failure
     * @throws \Zend\Cache\Exception\ExceptionInterface
     */
    public function getItem($key, & $success = null, & $casToken = null);

    /**
     * Get multiple items.
     *
     * @param  array $keys
     * @return array Associative array of keys and values
     * @throws \Zend\Cache\Exception\ExceptionInterface
     */
    public function getItems(array $keys);

    /**
     * Test if an item exists.
     *
     * @param  string $key
     * @return bool
     * @throws \Zend\Cache\Exception\ExceptionInterface
     */
    public function hasItem($key);

    /**
     * Test multiple items.
     *
     * @param  array $keys
     * @return array Array of found keys
     * @throws \Zend\Cache\Exception\ExceptionInterface
     */
    public function hasItems(array $keys);

    /**
     * Get metadata of an item.
     *
     * @param  string $key
     * @return array|bool Metadata on success, false on failure
     * @throws \Zend\Cache\Exception\ExceptionInterface
     */
    public function getMetadata($key);

    /**
     * Get multiple metadata
     *
     * @param  array $keys
     * @return array Associative array of keys and metadata
     * @throws \Zend\Cache\Exception\ExceptionInterface
     */
    public function getMetadatas(array $keys);

    /* writing */

    /**
     * Store an item.
     *
     * @param  string $key
     * @param  mixed  $value
     * @return bool
     * @throws \Zend\Cache\Exception\ExceptionInterface
     */
    public function setItem($key, $value);

    /**
     * Store multiple items.
     *
     * @param  array $keyValuePairs
     * @return array Array of not stored keys
     * @throws \Zend\Cache\Exception\ExceptionInterface
     */
    public function setItems(array $keyValuePairs);

    /**
     * Add an item.
     *
     * @param  string $key
     * @param  mixed  $value
     * @return bool
     * @throws \Zend\Cache\Exception\ExceptionInterface
     */
    public function addItem($key, $value);

    /**
     * Add multiple items.
     *
     * @param  array $keyValuePairs
     * @return array Array of not stored keys
     * @throws \Zend\Cache\Exception\ExceptionInterface
     */
    public function addItems(array $keyValuePairs);

    /**
     * Replace an existing item.
     *
     * @param  string $key
     * @param  mixed  $value
     * @return bool
     * @throws \Zend\Cache\Exception\ExceptionInterface
     */
    public function replaceItem($key, $value);

    /**
     * Replace multiple existing items.
     *
     * @param  array $keyValuePairs
     * @return array Array of not stored keys
     * @throws \Zend\Cache\Exception\ExceptionInterface
     */
    public function replaceItems(array $keyValuePairs);

    /**
     * Set an item only if token matches
     *
     * It uses the token received from getItem() to check if the item has
     * changed before overwriting it.
     *
     * @param  mixed  $token
     * @param  string $key
     * @param  mixed  $value
     * @return bool
     * @throws \Zend\Cache\Exception\ExceptionInterface
     * @see    getItem()
     * @see    setItem()
     */
    public function checkAndSetItem($token, $key, $value);

    /**
     * Reset lifetime of an item
     *
     * @param  string $key
     * @return bool
     * @throws \Zend\Cache\Exception\ExceptionInterface
     */
    public function touchItem($key);

    /**
     * Reset lifetime of multiple items.
     *
     * @param  array $keys
     * @return array Array of not updated keys
     * @throws \Zend\Cache\Exception\ExceptionInterface
     */
    public function touchItems(array $keys);

    /**
     * Remove an item.
     *
     * @param  string $key
     * @return bool
     * @throws \Zend\Cache\Exception\ExceptionInterface
     */
    public function removeItem($key);

    /**
     * Remove multiple items.
     *
     * @param  array $keys
     * @return array Array of not removed keys
     * @throws \Zend\Cache\Exception\ExceptionInterface
     */
    public function removeItems(array $keys);

    /**
     * Increment an item.
     *
     * @param  string $key
     * @param  int    $value
     * @return int|bool The new value on success, false on failure
     * @throws \Zend\Cache\Exception\ExceptionInterface
     */
    public function incrementItem($key, $value);

    /**
     * Increment multiple items.
     *
     * @param  array $keyValuePairs
     * @return array Associative array of keys and new values
     * @throws \Zend\Cache\Exception\ExceptionInterface
     */
    public function incrementItems(array $keyValuePairs);

    /**
     * Decrement an item.
     *
     * @param  string $key
     * @param  int    $value
     * @return int|bool The new value on success, false on failure
     * @throws \Zend\Cache\Exception\ExceptionInterface
     */
    public function decrementItem($key, $value);

    /**
     * Decrement multiple items.
     *
     * @param  array $keyValuePairs
     * @return array Associative array of keys and new values
     * @throws \Zend\Cache\Exception\ExceptionInterface
     */
    public function decrementItems(array $keyValuePairs);

    /* status */

    /**
     * Capabilities of this storage
     *
     * @return Capabilities
     */
    public function getCapabilities();
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage;

interface TotalSpaceCapableInterface
{
    /**
     * Get total space in bytes
     *
     * @return int|float
     */
    public function getTotalSpace();
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage;

use Zend\Cache\Exception;
use Zend\ServiceManager\AbstractPluginManager;

/**
 * Plugin manager implementation for cache storage adapters
 *
 * Enforces that adapters retrieved are instances of
 * StorageInterface. Additionally, it registers a number of default
 * adapters available.
 */
class AdapterPluginManager extends AbstractPluginManager
{
    /**
     * Default set of adapters
     *
     * @var array
     */
    protected $invokableClasses = array(
        'apc'            => 'Zend\Cache\Storage\Adapter\Apc',
        'dba'            => 'Zend\Cache\Storage\Adapter\Dba',
        'filesystem'     => 'Zend\Cache\Storage\Adapter\Filesystem',
        'memcached'      => 'Zend\Cache\Storage\Adapter\Memcached',
        'memory'         => 'Zend\Cache\Storage\Adapter\Memory',
        'redis'          => 'Zend\Cache\Storage\Adapter\Redis',
        'session'        => 'Zend\Cache\Storage\Adapter\Session',
        'xcache'         => 'Zend\Cache\Storage\Adapter\XCache',
        'wincache'       => 'Zend\Cache\Storage\Adapter\WinCache',
        'zendserverdisk' => 'Zend\Cache\Storage\Adapter\ZendServerDisk',
        'zendservershm'  => 'Zend\Cache\Storage\Adapter\ZendServerShm',
    );

    /**
     * Do not share by default
     *
     * @var array
     */
    protected $shareByDefault = false;

    /**
     * Validate the plugin
     *
     * Checks that the adapter loaded is an instance of StorageInterface.
     *
     * @param  mixed $plugin
     * @return void
     * @throws Exception\RuntimeException if invalid
     */
    public function validatePlugin($plugin)
    {
        if ($plugin instanceof StorageInterface) {
            // we're okay
            return;
        }

        throw new Exception\RuntimeException(sprintf(
            'Plugin of type %s is invalid; must implement %s\StorageInterface',
            (is_object($plugin) ? get_class($plugin) : gettype($plugin)),
            __NAMESPACE__
        ));
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Plugin;

use Zend\EventManager\AbstractListenerAggregate;

abstract class AbstractPlugin extends AbstractListenerAggregate implements PluginInterface
{
    /**
     * @var PluginOptions
     */
    protected $options;

    /**
     * Set pattern options
     *
     * @param  PluginOptions $options
     * @return AbstractPlugin
     */
    public function setOptions(PluginOptions $options)
    {
        $this->options = $options;
        return $this;
    }

    /**
     * Get all pattern options
     *
     * @return PluginOptions
     */
    public function getOptions()
    {
        if (null === $this->options) {
            $this->setOptions(new PluginOptions());
        }
        return $this->options;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Plugin;

use Zend\Cache\Exception;
use Zend\Cache\Storage\OptimizableInterface;
use Zend\Cache\Storage\PostEvent;
use Zend\EventManager\EventManagerInterface;

class OptimizeByFactor extends AbstractPlugin
{
    /**
     * {@inheritDoc}
     */
    public function attach(EventManagerInterface $events, $priority = 1)
    {
        $callback          = array($this, 'optimizeByFactor');
        $this->listeners[] = $events->attach('removeItem.post',  $callback, $priority);
        $this->listeners[] = $events->attach('removeItems.post', $callback, $priority);
    }

    /**
     * Optimize by factor on a success _RESULT_
     *
     * @param  PostEvent $event
     * @return void
     */
    public function optimizeByFactor(PostEvent $event)
    {
        $storage = $event->getStorage();
        if (!($storage instanceof OptimizableInterface)) {
            return;
        }

        $factor = $this->getOptions()->getOptimizingFactor();
        if ($factor && mt_rand(1, $factor) == 1) {
            $storage->optimize();
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Plugin;

use Zend\Cache\Exception;
use Zend\Cache\Storage\ExceptionEvent;
use Zend\EventManager\EventManagerInterface;

class ExceptionHandler extends AbstractPlugin
{
    /**
     * {@inheritDoc}
     */
    public function attach(EventManagerInterface $events, $priority = 1)
    {
        $callback = array($this, 'onException');

        // read
        $this->listeners[] = $events->attach('getItem.exception', $callback, $priority);
        $this->listeners[] = $events->attach('getItems.exception', $callback, $priority);

        $this->listeners[] = $events->attach('hasItem.exception', $callback, $priority);
        $this->listeners[] = $events->attach('hasItems.exception', $callback, $priority);

        $this->listeners[] = $events->attach('getMetadata.exception', $callback, $priority);
        $this->listeners[] = $events->attach('getMetadatas.exception', $callback, $priority);

        // write
        $this->listeners[] = $events->attach('setItem.exception', $callback, $priority);
        $this->listeners[] = $events->attach('setItems.exception', $callback, $priority);

        $this->listeners[] = $events->attach('addItem.exception', $callback, $priority);
        $this->listeners[] = $events->attach('addItems.exception', $callback, $priority);

        $this->listeners[] = $events->attach('replaceItem.exception', $callback, $priority);
        $this->listeners[] = $events->attach('replaceItems.exception', $callback, $priority);

        $this->listeners[] = $events->attach('touchItem.exception', $callback, $priority);
        $this->listeners[] = $events->attach('touchItems.exception', $callback, $priority);

        $this->listeners[] = $events->attach('removeItem.exception', $callback, $priority);
        $this->listeners[] = $events->attach('removeItems.exception', $callback, $priority);

        $this->listeners[] = $events->attach('checkAndSetItem.exception', $callback, $priority);

        // increment / decrement item(s)
        $this->listeners[] = $events->attach('incrementItem.exception', $callback, $priority);
        $this->listeners[] = $events->attach('incrementItems.exception', $callback, $priority);

        $this->listeners[] = $events->attach('decrementItem.exception', $callback, $priority);
        $this->listeners[] = $events->attach('decrementItems.exception', $callback, $priority);
    }

    /**
     * On exception
     *
     * @param  ExceptionEvent $event
     * @return void
     */
    public function onException(ExceptionEvent $event)
    {
        $options  = $this->getOptions();
        $callback = $options->getExceptionCallback();
        if ($callback) {
            call_user_func($callback, $event->getException());
        }

        $event->setThrowException($options->getThrowExceptions());
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Plugin;

use Zend\Cache\Exception;
use Zend\Cache\Storage\Event;
use Zend\EventManager\EventManagerInterface;

class IgnoreUserAbort extends AbstractPlugin
{
    /**
     * The storage who activated ignore_user_abort.
     *
     * @var null|\Zend\Cache\Storage\StorageInterface
     */
    protected $activatedTarget = null;

    /**
     * {@inheritDoc}
     */
    public function attach(EventManagerInterface $events, $priority = 1)
    {
        $cbOnBefore = array($this, 'onBefore');
        $cbOnAfter  = array($this, 'onAfter');

        $this->listeners[] = $events->attach('setItem.pre',       $cbOnBefore, $priority);
        $this->listeners[] = $events->attach('setItem.post',      $cbOnAfter, $priority);
        $this->listeners[] = $events->attach('setItem.exception', $cbOnAfter, $priority);

        $this->listeners[] = $events->attach('setItems.pre',       $cbOnBefore, $priority);
        $this->listeners[] = $events->attach('setItems.post',      $cbOnAfter, $priority);
        $this->listeners[] = $events->attach('setItems.exception', $cbOnAfter, $priority);

        $this->listeners[] = $events->attach('addItem.pre',       $cbOnBefore, $priority);
        $this->listeners[] = $events->attach('addItem.post',      $cbOnAfter, $priority);
        $this->listeners[] = $events->attach('addItem.exception', $cbOnAfter, $priority);

        $this->listeners[] = $events->attach('addItems.pre',       $cbOnBefore, $priority);
        $this->listeners[] = $events->attach('addItems.post',      $cbOnAfter, $priority);
        $this->listeners[] = $events->attach('addItems.exception', $cbOnAfter, $priority);

        $this->listeners[] = $events->attach('replaceItem.pre',       $cbOnBefore, $priority);
        $this->listeners[] = $events->attach('replaceItem.post',      $cbOnAfter, $priority);
        $this->listeners[] = $events->attach('replaceItem.exception', $cbOnAfter, $priority);

        $this->listeners[] = $events->attach('replaceItems.pre',       $cbOnBefore, $priority);
        $this->listeners[] = $events->attach('replaceItems.post',      $cbOnAfter, $priority);
        $this->listeners[] = $events->attach('replaceItems.exception', $cbOnAfter, $priority);

        $this->listeners[] = $events->attach('checkAndSetItem.pre',       $cbOnBefore, $priority);
        $this->listeners[] = $events->attach('checkAndSetItem.post',      $cbOnAfter, $priority);
        $this->listeners[] = $events->attach('checkAndSetItem.exception', $cbOnAfter, $priority);

        // increment / decrement item(s)
        $this->listeners[] = $events->attach('incrementItem.pre',       $cbOnBefore, $priority);
        $this->listeners[] = $events->attach('incrementItem.post',      $cbOnAfter, $priority);
        $this->listeners[] = $events->attach('incrementItem.exception', $cbOnAfter, $priority);

        $this->listeners[] = $events->attach('incrementItems.pre',       $cbOnBefore, $priority);
        $this->listeners[] = $events->attach('incrementItems.post',      $cbOnAfter, $priority);
        $this->listeners[] = $events->attach('incrementItems.exception', $cbOnAfter, $priority);

        $this->listeners[] = $events->attach('decrementItem.pre',       $cbOnBefore, $priority);
        $this->listeners[] = $events->attach('decrementItem.post',      $cbOnAfter, $priority);
        $this->listeners[] = $events->attach('decrementItem.exception', $cbOnAfter, $priority);

        $this->listeners[] = $events->attach('decrementItems.pre',       $cbOnBefore, $priority);
        $this->listeners[] = $events->attach('decrementItems.post',      $cbOnAfter, $priority);
        $this->listeners[] = $events->attach('decrementItems.exception', $cbOnAfter, $priority);
    }

    /**
     * Activate ignore_user_abort if not already done
     * and save the target who activated it.
     *
     * @param  Event $event
     * @return void
     */
    public function onBefore(Event $event)
    {
        if ($this->activatedTarget === null && !ignore_user_abort(true)) {
            $this->activatedTarget = $event->getTarget();
        }
    }

    /**
     * Reset ignore_user_abort if it's activated and if it's the same target
     * who activated it.
     *
     * If exit_on_abort is enabled and the connection has been aborted
     * exit the script.
     *
     * @param  Event $event
     * @return void
     */
    public function onAfter(Event $event)
    {
        if ($this->activatedTarget === $event->getTarget()) {
            // exit if connection aborted
            if ($this->getOptions()->getExitOnAbort() && connection_aborted()) {
                exit;
            }

            // reset ignore_user_abort
            ignore_user_abort(false);

            // remove activated target
            $this->activatedTarget = null;
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Plugin;

use Zend\Cache\Exception;
use Zend\Cache\Storage\ClearExpiredInterface;
use Zend\Cache\Storage\PostEvent;
use Zend\EventManager\EventManagerInterface;

class ClearExpiredByFactor extends AbstractPlugin
{
    /**
     * {@inheritDoc}
     */
    public function attach(EventManagerInterface $events, $priority = 1)
    {
        $callback = array($this, 'clearExpiredByFactor');

        $this->listeners[] = $events->attach('setItem.post',  $callback, $priority);
        $this->listeners[] = $events->attach('setItems.post', $callback, $priority);
        $this->listeners[] = $events->attach('addItem.post',  $callback, $priority);
        $this->listeners[] = $events->attach('addItems.post', $callback, $priority);
    }

    /**
     * Clear expired items by factor after writing new item(s)
     *
     * @param  PostEvent $event
     * @return void
     */
    public function clearExpiredByFactor(PostEvent $event)
    {
        $storage = $event->getStorage();
        if (!($storage instanceof ClearExpiredInterface)) {
            return;
        }

        $factor = $this->getOptions()->getClearingFactor();
        if ($factor && mt_rand(1, $factor) == 1) {
            $storage->clearExpired();
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Plugin;

use stdClass;
use Zend\Cache\Exception;
use Zend\Cache\Storage\Capabilities;
use Zend\Cache\Storage\Event;
use Zend\Cache\Storage\PostEvent;
use Zend\EventManager\EventManagerInterface;

class Serializer extends AbstractPlugin
{
    /**
     * @var array
     */
    protected $capabilities = array();

    /**
     * {@inheritDoc}
     */
    public function attach(EventManagerInterface $events, $priority = 1)
    {
        // The higher the priority the sooner the plugin will be called on pre events
        // but the later it will be called on post events.
        $prePriority  = $priority;
        $postPriority = -$priority;

        // read
        $this->listeners[] = $events->attach('getItem.post',  array($this, 'onReadItemPost'), $postPriority);
        $this->listeners[] = $events->attach('getItems.post', array($this, 'onReadItemsPost'), $postPriority);

        // write
        $this->listeners[] = $events->attach('setItem.pre',  array($this, 'onWriteItemPre'), $prePriority);
        $this->listeners[] = $events->attach('setItems.pre', array($this, 'onWriteItemsPre'), $prePriority);

        $this->listeners[] = $events->attach('addItem.pre',  array($this, 'onWriteItemPre'), $prePriority);
        $this->listeners[] = $events->attach('addItems.pre', array($this, 'onWriteItemsPre'), $prePriority);

        $this->listeners[] = $events->attach('replaceItem.pre',  array($this, 'onWriteItemPre'), $prePriority);
        $this->listeners[] = $events->attach('replaceItems.pre', array($this, 'onWriteItemsPre'), $prePriority);

        $this->listeners[] = $events->attach('checkAndSetItem.pre', array($this, 'onWriteItemPre'), $prePriority);

        // increment / decrement item(s)
        $this->listeners[] = $events->attach('incrementItem.pre', array($this, 'onIncrementItemPre'), $prePriority);
        $this->listeners[] = $events->attach('incrementItems.pre', array($this, 'onIncrementItemsPre'), $prePriority);

        $this->listeners[] = $events->attach('decrementItem.pre', array($this, 'onDecrementItemPre'), $prePriority);
        $this->listeners[] = $events->attach('decrementItems.pre', array($this, 'onDecrementItemsPre'), $prePriority);

        // overwrite capabilities
        $this->listeners[] = $events->attach('getCapabilities.post',  array($this, 'onGetCapabilitiesPost'), $postPriority);
    }

    /**
     * On read item post
     *
     * @param  PostEvent $event
     * @return void
     */
    public function onReadItemPost(PostEvent $event)
    {
        $serializer = $this->getOptions()->getSerializer();
        $result     = $event->getResult();
        $result     = $serializer->unserialize($result);
        $event->setResult($result);
    }

    /**
     * On read items post
     *
     * @param  PostEvent $event
     * @return void
     */
    public function onReadItemsPost(PostEvent $event)
    {
        $serializer = $this->getOptions()->getSerializer();
        $result     = $event->getResult();
        foreach ($result as &$value) {
            $value = $serializer->unserialize($value);
        }
        $event->setResult($result);
    }

    /**
     * On write item pre
     *
     * @param  Event $event
     * @return void
     */
    public function onWriteItemPre(Event $event)
    {
        $serializer = $this->getOptions()->getSerializer();
        $params     = $event->getParams();
        $params['value'] = $serializer->serialize($params['value']);
    }

    /**
     * On write items pre
     *
     * @param  Event $event
     * @return void
     */
    public function onWriteItemsPre(Event $event)
    {
        $serializer = $this->getOptions()->getSerializer();
        $params     = $event->getParams();
        foreach ($params['keyValuePairs'] as &$value) {
            $value = $serializer->serialize($value);
        }
    }

    /**
     * On increment item pre
     *
     * @param  Event $event
     * @return mixed
     */
    public function onIncrementItemPre(Event $event)
    {
        $storage  = $event->getTarget();
        $params   = $event->getParams();
        $casToken = null;
        $success  = null;
        $oldValue = $storage->getItem($params['key'], $success, $casToken);
        $newValue = $oldValue + $params['value'];

        if ($success) {
            $storage->checkAndSetItem($casToken, $params['key'], $oldValue + $params['value']);
            $result = $newValue;
        } else {
            $result = false;
        }

        $event->stopPropagation(true);
        return $result;
    }

    /**
     * On increment items pre
     *
     * @param  Event $event
     * @return mixed
     */
    public function onIncrementItemsPre(Event $event)
    {
        $storage       = $event->getTarget();
        $params        = $event->getParams();
        $keyValuePairs = $storage->getItems(array_keys($params['keyValuePairs']));
        foreach ($params['keyValuePairs'] as $key => & $value) {
            if (isset($keyValuePairs[$key])) {
                $keyValuePairs[$key]+= $value;
            } else {
                $keyValuePairs[$key] = $value;
            }
        }

        $failedKeys = $storage->setItems($keyValuePairs);
        foreach ($failedKeys as $failedKey) {
            unset($keyValuePairs[$failedKey]);
        }

        $event->stopPropagation(true);
        return $keyValuePairs;
    }

    /**
     * On decrement item pre
     *
     * @param  Event $event
     * @return mixed
     */
    public function onDecrementItemPre(Event $event)
    {
        $storage  = $event->getTarget();
        $params   = $event->getParams();
        $success  = null;
        $casToken = null;
        $oldValue = $storage->getItem($params['key'], $success, $casToken);
        $newValue = $oldValue - $params['value'];

        if ($success) {
            $storage->checkAndSetItem($casToken, $params['key'], $oldValue + $params['value']);
            $result = $newValue;
        } else {
            $result = false;
        }

        $event->stopPropagation(true);
        return $result;
    }

    /**
     * On decrement items pre
     *
     * @param  Event $event
     * @return mixed
     */
    public function onDecrementItemsPre(Event $event)
    {
        $storage       = $event->getTarget();
        $params        = $event->getParams();
        $keyValuePairs = $storage->getItems(array_keys($params['keyValuePairs']));
        foreach ($params['keyValuePairs'] as $key => &$value) {
            if (isset($keyValuePairs[$key])) {
                $keyValuePairs[$key]-= $value;
            } else {
                $keyValuePairs[$key] = -$value;
            }
        }

        $failedKeys = $storage->setItems($keyValuePairs);
        foreach ($failedKeys as $failedKey) {
            unset($keyValuePairs[$failedKey]);
        }

        $event->stopPropagation(true);
        return $keyValuePairs;
    }

    /**
     * On get capabilities
     *
     * @param  PostEvent $event
     * @return void
     */
    public function onGetCapabilitiesPost(PostEvent $event)
    {
        $baseCapabilities = $event->getResult();
        $index = spl_object_hash($baseCapabilities);

        if (!isset($this->capabilities[$index])) {
            $this->capabilities[$index] = new Capabilities(
                $baseCapabilities->getAdapter(),
                new stdClass(), // marker
                array('supportedDatatypes' => array(
                    'NULL'     => true,
                    'boolean'  => true,
                    'integer'  => true,
                    'double'   => true,
                    'string'   => true,
                    'array'    => true,
                    'object'   => 'object',
                    'resource' => false,
                )),
                $baseCapabilities
            );
        }

        $event->setResult($this->capabilities[$index]);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Plugin;

use Zend\EventManager\ListenerAggregateInterface;

interface PluginInterface extends ListenerAggregateInterface
{
    /**
     * Set options
     *
     * @param  PluginOptions $options
     * @return PluginInterface
     */
    public function setOptions(PluginOptions $options);

    /**
     * Get options
     *
     * @return PluginOptions
     */
    public function getOptions();
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Plugin;

use Zend\Cache\Exception;
use Zend\Serializer\Adapter\AdapterInterface as SerializerAdapter;
use Zend\Serializer\Serializer as SerializerFactory;
use Zend\Stdlib\AbstractOptions;

class PluginOptions extends AbstractOptions
{
    /**
     * Used by:
     * - ClearByFactor
     * @var int
     */
    protected $clearingFactor = 0;

    /**
     * Used by:
     * - ExceptionHandler
     * @var callable
     */
    protected $exceptionCallback;

    /**
     * Used by:
     * - IgnoreUserAbort
     * @var bool
     */
    protected $exitOnAbort = true;

    /**
     * Used by:
     * - OptimizeByFactor
     * @var int
     */
    protected $optimizingFactor = 0;

    /**
     * Used by:
     * - Serializer
     * @var string|SerializerAdapter
     */
    protected $serializer;

    /**
     * Used by:
     * - Serializer
     * @var array
     */
    protected $serializerOptions = array();

    /**
     * Used by:
     * - ExceptionHandler
     * @var bool
     */
    protected $throwExceptions = true;

    /**
     * Set automatic clearing factor
     *
     * Used by:
     * - ClearExpiredByFactor
     *
     * @param  int $clearingFactor
     * @return PluginOptions
     */
    public function setClearingFactor($clearingFactor)
    {
        $this->clearingFactor = $this->normalizeFactor($clearingFactor);
        return $this;
    }

    /**
     * Get automatic clearing factor
     *
     * Used by:
     * - ClearExpiredByFactor
     *
     * @return int
     */
    public function getClearingFactor()
    {
        return $this->clearingFactor;
    }

    /**
     * Set callback to call on intercepted exception
     *
     * Used by:
     * - ExceptionHandler
     *
     * @param  callable $exceptionCallback
     * @throws Exception\InvalidArgumentException
     * @return PluginOptions
     */
    public function setExceptionCallback($exceptionCallback)
    {
        if ($exceptionCallback !== null && !is_callable($exceptionCallback, true)) {
            throw new Exception\InvalidArgumentException('Not a valid callback');
        }
        $this->exceptionCallback = $exceptionCallback;
        return $this;
    }

    /**
     * Get callback to call on intercepted exception
     *
     * Used by:
     * - ExceptionHandler
     *
     * @return null|callable
     */
    public function getExceptionCallback()
    {
        return $this->exceptionCallback;
    }

    /**
     * Exit if connection aborted and ignore_user_abort is disabled.
     *
     * @param  bool $exitOnAbort
     * @return PluginOptions
     */
    public function setExitOnAbort($exitOnAbort)
    {
        $this->exitOnAbort = (bool) $exitOnAbort;
        return $this;
    }

    /**
     * Exit if connection aborted and ignore_user_abort is disabled.
     *
     * @return bool
     */
    public function getExitOnAbort()
    {
        return $this->exitOnAbort;
    }

    /**
     * Set automatic optimizing factor
     *
     * Used by:
     * - OptimizeByFactor
     *
     * @param  int $optimizingFactor
     * @return PluginOptions
     */
    public function setOptimizingFactor($optimizingFactor)
    {
        $this->optimizingFactor = $this->normalizeFactor($optimizingFactor);
        return $this;
    }

    /**
     * Set automatic optimizing factor
     *
     * Used by:
     * - OptimizeByFactor
     *
     * @return int
     */
    public function getOptimizingFactor()
    {
        return $this->optimizingFactor;
    }

    /**
     * Set serializer
     *
     * Used by:
     * - Serializer
     *
     * @param  string|SerializerAdapter $serializer
     * @throws Exception\InvalidArgumentException
     * @return Serializer
     */
    public function setSerializer($serializer)
    {
        if (!is_string($serializer) && !$serializer instanceof SerializerAdapter) {
            throw new Exception\InvalidArgumentException(sprintf(
                '%s expects either a string serializer name or Zend\Serializer\Adapter\AdapterInterface instance; '
                . 'received "%s"',
                __METHOD__,
                (is_object($serializer) ? get_class($serializer) : gettype($serializer))
            ));
        }
        $this->serializer = $serializer;
        return $this;
    }

    /**
     * Get serializer
     *
     * Used by:
     * - Serializer
     *
     * @return SerializerAdapter
     */
    public function getSerializer()
    {
        if (!$this->serializer instanceof SerializerAdapter) {
            // use default serializer
            if (!$this->serializer) {
                $this->setSerializer(SerializerFactory::getDefaultAdapter());
            // instantiate by class name + serializer_options
            } else {
                $options = $this->getSerializerOptions();
                $this->setSerializer(SerializerFactory::factory($this->serializer, $options));
            }
        }
        return $this->serializer;
    }

    /**
     * Set configuration options for instantiating a serializer adapter
     *
     * Used by:
     * - Serializer
     *
     * @param  mixed $serializerOptions
     * @return PluginOptions
     */
    public function setSerializerOptions($serializerOptions)
    {
        $this->serializerOptions = $serializerOptions;
        return $this;
    }

    /**
     * Get configuration options for instantiating a serializer adapter
     *
     * Used by:
     * - Serializer
     *
     * @return array
     */
    public function getSerializerOptions()
    {
        return $this->serializerOptions;
    }

    /**
     * Set flag indicating we should re-throw exceptions
     *
     * Used by:
     * - ExceptionHandler
     *
     * @param  bool $throwExceptions
     * @return PluginOptions
     */
    public function setThrowExceptions($throwExceptions)
    {
        $this->throwExceptions = (bool) $throwExceptions;
        return $this;
    }

    /**
     * Should we re-throw exceptions?
     *
     * Used by:
     * - ExceptionHandler
     *
     * @return bool
     */
    public function getThrowExceptions()
    {
        return $this->throwExceptions;
    }

    /**
     * Normalize a factor
     *
     * Cast to int and ensure we have a value greater than zero.
     *
     * @param  int $factor
     * @return int
     * @throws Exception\InvalidArgumentException
     */
    protected function normalizeFactor($factor)
    {
        $factor = (int) $factor;
        if ($factor < 0) {
            throw new Exception\InvalidArgumentException(
                "Invalid factor '{$factor}': must be greater or equal 0"
            );
        }
        return $factor;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage;

use ArrayObject;
use stdClass;
use Zend\Cache\Exception;
use Zend\EventManager\EventsCapableInterface;

class Capabilities
{
    /**
     * The storage instance
     *
     * @var StorageInterface
     */
    protected $storage;

    /**
     * A marker to set/change capabilities
     *
     * @var stdClass
     */
    protected $marker;

    /**
     * Base capabilities
     *
     * @var null|Capabilities
     */
    protected $baseCapabilities;

    /**
     * Expire read
     *
    * If it's NULL the capability isn't set and the getter
    * returns the base capability or the default value.
     *
     * @var null|bool
     */
    protected $expiredRead;

    /**
     * Max. key length
     *
    * If it's NULL the capability isn't set and the getter
    * returns the base capability or the default value.
     *
     * @var null|int
     */
    protected $maxKeyLength;

    /**
     * Min. TTL (0 means items never expire)
     *
    * If it's NULL the capability isn't set and the getter
    * returns the base capability or the default value.
     *
     * @var null|int
     */
    protected $minTtl;

    /**
     * Max. TTL (0 means infinite)
     *
    * If it's NULL the capability isn't set and the getter
    * returns the base capability or the default value.
     *
     * @var null|int
     */
    protected $maxTtl;

    /**
     * Namespace is prefix
     *
    * If it's NULL the capability isn't set and the getter
    * returns the base capability or the default value.
     *
     * @var null|bool
     */
    protected $namespaceIsPrefix;

    /**
     * Namespace separator
     *
    * If it's NULL the capability isn't set and the getter
    * returns the base capability or the default value.
     *
     * @var null|string
     */
    protected $namespaceSeparator;

    /**
     * Static ttl
     *
    * If it's NULL the capability isn't set and the getter
    * returns the base capability or the default value.
     *
     * @var null|bool
     */
    protected $staticTtl;

   /**
    * Supported datatypes
    *
    * If it's NULL the capability isn't set and the getter
    * returns the base capability or the default value.
    *
    * @var null|array
    */
    protected $supportedDatatypes;

    /**
     * Supported metdata
     *
    * If it's NULL the capability isn't set and the getter
    * returns the base capability or the default value.
     *
     * @var null|array
     */
    protected $supportedMetadata;

    /**
     * TTL precision
     *
    * If it's NULL the capability isn't set and the getter
    * returns the base capability or the default value.
     *
     * @var null|int
     */
    protected $ttlPrecision;

    /**
     * Use request time
     *
    * If it's NULL the capability isn't set and the getter
    * returns the base capability or the default value.
     *
     * @var null|bool
     */
    protected $useRequestTime;

    /**
     * Constructor
     *
     * @param StorageInterface  $storage
     * @param stdClass          $marker
     * @param array             $capabilities
     * @param null|Capabilities $baseCapabilities
     */
    public function __construct(
        StorageInterface $storage,
        stdClass $marker,
        array $capabilities = array(),
        Capabilities $baseCapabilities = null
    ) {
        $this->storage = $storage;
        $this->marker  = $marker;
        $this->baseCapabilities = $baseCapabilities;

        foreach ($capabilities as $name => $value) {
            $this->setCapability($marker, $name, $value);
        }
    }

    /**
     * Get the storage adapter
     *
     * @return StorageInterface
     */
    public function getAdapter()
    {
        return $this->storage;
    }

    /**
     * Get supported datatypes
     *
     * @return array
     */
    public function getSupportedDatatypes()
    {
        return $this->getCapability('supportedDatatypes', array(
            'NULL'     => false,
            'boolean'  => false,
            'integer'  => false,
            'double'   => false,
            'string'   => true,
            'array'    => false,
            'object'   => false,
            'resource' => false,
        ));
    }

    /**
     * Set supported datatypes
     *
     * @param  stdClass $marker
     * @param  array $datatypes
     * @throws Exception\InvalidArgumentException
     * @return Capabilities Fluent interface
     */
    public function setSupportedDatatypes(stdClass $marker, array $datatypes)
    {
        $allTypes = array(
            'array',
            'boolean',
            'double',
            'integer',
            'NULL',
            'object',
            'resource',
            'string',
        );

        // check/normalize datatype values
        foreach ($datatypes as $type => &$toType) {
            if (!in_array($type, $allTypes)) {
                throw new Exception\InvalidArgumentException("Unknown datatype '{$type}'");
            }

            if (is_string($toType)) {
                $toType = strtolower($toType);
                if (!in_array($toType, $allTypes)) {
                    throw new Exception\InvalidArgumentException("Unknown datatype '{$toType}'");
                }
            } else {
                $toType = (bool) $toType;
            }
        }

        // add missing datatypes as not supported
        $missingTypes = array_diff($allTypes, array_keys($datatypes));
        foreach ($missingTypes as $type) {
            $datatypes[$type] = false;
        }

        return $this->setCapability($marker, 'supportedDatatypes', $datatypes);
    }

    /**
     * Get supported metadata
     *
     * @return array
     */
    public function getSupportedMetadata()
    {
        return $this->getCapability('supportedMetadata', array());
    }

    /**
     * Set supported metadata
     *
     * @param  stdClass $marker
     * @param  string[] $metadata
     * @throws Exception\InvalidArgumentException
     * @return Capabilities Fluent interface
     */
    public function setSupportedMetadata(stdClass $marker, array $metadata)
    {
        foreach ($metadata as $name) {
            if (!is_string($name)) {
                throw new Exception\InvalidArgumentException('$metadata must be an array of strings');
            }
        }
        return $this->setCapability($marker, 'supportedMetadata', $metadata);
    }

    /**
     * Get minimum supported time-to-live
     *
     * @return int 0 means items never expire
     */
    public function getMinTtl()
    {
        return $this->getCapability('minTtl', 0);
    }

    /**
     * Set minimum supported time-to-live
     *
     * @param  stdClass $marker
     * @param  int $minTtl
     * @throws Exception\InvalidArgumentException
     * @return Capabilities Fluent interface
     */
    public function setMinTtl(stdClass $marker, $minTtl)
    {
        $minTtl = (int) $minTtl;
        if ($minTtl < 0) {
            throw new Exception\InvalidArgumentException('$minTtl must be greater or equal 0');
        }
        return $this->setCapability($marker, 'minTtl', $minTtl);
    }

    /**
     * Get maximum supported time-to-live
     *
     * @return int 0 means infinite
     */
    public function getMaxTtl()
    {
        return $this->getCapability('maxTtl', 0);
    }

    /**
     * Set maximum supported time-to-live
     *
     * @param  stdClass $marker
     * @param  int $maxTtl
     * @throws Exception\InvalidArgumentException
     * @return Capabilities Fluent interface
     */
    public function setMaxTtl(stdClass $marker, $maxTtl)
    {
        $maxTtl = (int) $maxTtl;
        if ($maxTtl < 0) {
            throw new Exception\InvalidArgumentException('$maxTtl must be greater or equal 0');
        }
        return $this->setCapability($marker, 'maxTtl', $maxTtl);
    }

    /**
     * Is the time-to-live handled static (on write)
     * or dynamic (on read)
     *
     * @return bool
     */
    public function getStaticTtl()
    {
        return $this->getCapability('staticTtl', false);
    }

    /**
     * Set if the time-to-live handled static (on write) or dynamic (on read)
     *
     * @param  stdClass $marker
     * @param  bool $flag
     * @return Capabilities Fluent interface
     */
    public function setStaticTtl(stdClass $marker, $flag)
    {
        return $this->setCapability($marker, 'staticTtl', (bool) $flag);
    }

    /**
     * Get time-to-live precision
     *
     * @return float
     */
    public function getTtlPrecision()
    {
        return $this->getCapability('ttlPrecision', 1);
    }

    /**
     * Set time-to-live precision
     *
     * @param  stdClass $marker
     * @param  float $ttlPrecision
     * @throws Exception\InvalidArgumentException
     * @return Capabilities Fluent interface
     */
    public function setTtlPrecision(stdClass $marker, $ttlPrecision)
    {
        $ttlPrecision = (float) $ttlPrecision;
        if ($ttlPrecision <= 0) {
            throw new Exception\InvalidArgumentException('$ttlPrecision must be greater than 0');
        }
        return $this->setCapability($marker, 'ttlPrecision', $ttlPrecision);
    }

    /**
     * Get use request time
     *
     * @return bool
     */
    public function getUseRequestTime()
    {
        return $this->getCapability('useRequestTime', false);
    }

    /**
     * Set use request time
     *
     * @param  stdClass $marker
     * @param  bool $flag
     * @return Capabilities Fluent interface
     */
    public function setUseRequestTime(stdClass $marker, $flag)
    {
        return $this->setCapability($marker, 'useRequestTime', (bool) $flag);
    }

    /**
     * Get if expired items are readable
     *
     * @return bool
     */
    public function getExpiredRead()
    {
        return $this->getCapability('expiredRead', false);
    }

    /**
     * Set if expired items are readable
     *
     * @param  stdClass $marker
     * @param  bool $flag
     * @return Capabilities Fluent interface
     */
    public function setExpiredRead(stdClass $marker, $flag)
    {
        return $this->setCapability($marker, 'expiredRead', (bool) $flag);
    }

    /**
     * Get maximum key lenth
     *
     * @return int -1 means unknown, 0 means infinite
     */
    public function getMaxKeyLength()
    {
        return $this->getCapability('maxKeyLength', -1);
    }

    /**
     * Set maximum key length
     *
     * @param  stdClass $marker
     * @param  int $maxKeyLength
     * @throws Exception\InvalidArgumentException
     * @return Capabilities Fluent interface
     */
    public function setMaxKeyLength(stdClass $marker, $maxKeyLength)
    {
        $maxKeyLength = (int) $maxKeyLength;
        if ($maxKeyLength < -1) {
            throw new Exception\InvalidArgumentException('$maxKeyLength must be greater or equal than -1');
        }
        return $this->setCapability($marker, 'maxKeyLength', $maxKeyLength);
    }

    /**
     * Get if namespace support is implemented as prefix
     *
     * @return bool
     */
    public function getNamespaceIsPrefix()
    {
        return $this->getCapability('namespaceIsPrefix', true);
    }

    /**
     * Set if namespace support is implemented as prefix
     *
     * @param  stdClass $marker
     * @param  bool $flag
     * @return Capabilities Fluent interface
     */
    public function setNamespaceIsPrefix(stdClass $marker, $flag)
    {
        return $this->setCapability($marker, 'namespaceIsPrefix', (bool) $flag);
    }

    /**
     * Get namespace separator if namespace is implemented as prefix
     *
     * @return string
     */
    public function getNamespaceSeparator()
    {
        return $this->getCapability('namespaceSeparator', '');
    }

    /**
     * Set the namespace separator if namespace is implemented as prefix
     *
     * @param  stdClass $marker
     * @param  string $separator
     * @return Capabilities Fluent interface
     */
    public function setNamespaceSeparator(stdClass $marker, $separator)
    {
        return $this->setCapability($marker, 'namespaceSeparator', (string) $separator);
    }

    /**
     * Get a capability
     *
     * @param  string $property
     * @param  mixed $default
     * @return mixed
     */
    protected function getCapability($property, $default = null)
    {
        if ($this->$property !== null) {
            return $this->$property;
        } elseif ($this->baseCapabilities) {
            $getMethod = 'get' . $property;
            return $this->baseCapabilities->$getMethod();
        }
        return $default;
    }

    /**
     * Change a capability
     *
     * @param  stdClass $marker
     * @param  string $property
     * @param  mixed $value
     * @return Capabilities Fluent interface
     * @throws Exception\InvalidArgumentException
     */
    protected function setCapability(stdClass $marker, $property, $value)
    {
        if ($this->marker !== $marker) {
            throw new Exception\InvalidArgumentException('Invalid marker');
        }

        if ($this->$property !== $value) {
            $this->$property = $value;

            // trigger event
            if ($this->storage instanceof EventsCapableInterface) {
                $this->storage->getEventManager()->trigger('capability', $this->storage, new ArrayObject(array(
                    $property => $value
                )));
            }
        }

        return $this;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

use ArrayObject;
use Zend\Cache\Exception;
use Zend\Cache\Storage\Event;
use Zend\Cache\Storage\StorageInterface;
use Zend\EventManager\EventsCapableInterface;
use Zend\Stdlib\AbstractOptions;
use Zend\Stdlib\ErrorHandler;

/**
 * Unless otherwise marked, all options in this class affect all adapters.
 */
class AdapterOptions extends AbstractOptions
{

    /**
     * The adapter using these options
     *
     * @var null|Filesystem
     */
    protected $adapter;

    /**
     * Validate key against pattern
     *
     * @var string
     */
    protected $keyPattern = '';

    /**
     * Namespace option
     *
     * @var string
     */
    protected $namespace = 'zfcache';

    /**
     * Readable option
     *
     * @var bool
     */
    protected $readable = true;

    /**
     * TTL option
     *
     * @var int|float 0 means infinite or maximum of adapter
     */
    protected $ttl = 0;

    /**
     * Writable option
     *
     * @var bool
     */
    protected $writable = true;

    /**
     * Adapter using this instance
     *
     * @param  StorageInterface|null $adapter
     * @return AdapterOptions
     */
    public function setAdapter(StorageInterface $adapter = null)
    {
        $this->adapter = $adapter;
        return $this;
    }

    /**
     * Set key pattern
     *
     * @param  null|string $keyPattern
     * @throws Exception\InvalidArgumentException
     * @return AdapterOptions
     */
    public function setKeyPattern($keyPattern)
    {
        $keyPattern = (string) $keyPattern;
        if ($this->keyPattern !== $keyPattern) {
            // validate pattern
            if ($keyPattern !== '') {
                ErrorHandler::start(E_WARNING);
                $result = preg_match($keyPattern, '');
                $error = ErrorHandler::stop();
                if ($result === false) {
                    throw new Exception\InvalidArgumentException(sprintf(
                        'Invalid pattern "%s"%s',
                        $keyPattern,
                        ($error ? ': ' . $error->getMessage() : '')
                    ), 0, $error);
                }
            }

            $this->triggerOptionEvent('key_pattern', $keyPattern);
            $this->keyPattern = $keyPattern;
        }

        return $this;
    }

    /**
     * Get key pattern
     *
     * @return string
     */
    public function getKeyPattern()
    {
        return $this->keyPattern;
    }

    /**
     * Set namespace.
     *
     * @param  string $namespace
     * @return AdapterOptions
     */
    public function setNamespace($namespace)
    {
        $namespace = (string) $namespace;
        if ($this->namespace !== $namespace) {
            $this->triggerOptionEvent('namespace', $namespace);
            $this->namespace = $namespace;
        }

        return $this;
    }

    /**
     * Get namespace
     *
     * @return string
     */
    public function getNamespace()
    {
        return $this->namespace;
    }

    /**
     * Enable/Disable reading data from cache.
     *
     * @param  bool $readable
     * @return AbstractAdapter
     */
    public function setReadable($readable)
    {
        $readable = (bool) $readable;
        if ($this->readable !== $readable) {
            $this->triggerOptionEvent('readable', $readable);
            $this->readable = $readable;
        }
        return $this;
    }

    /**
     * If reading data from cache enabled.
     *
     * @return bool
     */
    public function getReadable()
    {
        return $this->readable;
    }

    /**
     * Set time to live.
     *
     * @param  int|float $ttl
     * @return AdapterOptions
     */
    public function setTtl($ttl)
    {
        $this->normalizeTtl($ttl);
        if ($this->ttl !== $ttl) {
            $this->triggerOptionEvent('ttl', $ttl);
            $this->ttl = $ttl;
        }
        return $this;
    }

    /**
     * Get time to live.
     *
     * @return float
     */
    public function getTtl()
    {
        return $this->ttl;
    }

    /**
     * Enable/Disable writing data to cache.
     *
     * @param  bool $writable
     * @return AdapterOptions
     */
    public function setWritable($writable)
    {
        $writable = (bool) $writable;
        if ($this->writable !== $writable) {
            $this->triggerOptionEvent('writable', $writable);
            $this->writable = $writable;
        }
        return $this;
    }

    /**
     * If writing data to cache enabled.
     *
     * @return bool
     */
    public function getWritable()
    {
        return $this->writable;
    }

    /**
     * Triggers an option event if this options instance has a connection to
     * an adapter implements EventsCapableInterface.
     *
     * @param string $optionName
     * @param mixed  $optionValue
     * @return void
     */
    protected function triggerOptionEvent($optionName, $optionValue)
    {
        if ($this->adapter instanceof EventsCapableInterface) {
            $event = new Event('option', $this->adapter, new ArrayObject(array($optionName => $optionValue)));
            $this->adapter->getEventManager()->trigger($event);
        }
    }

    /**
     * Validates and normalize a TTL.
     *
     * @param  int|float $ttl
     * @throws Exception\InvalidArgumentException
     * @return void
     */
    protected function normalizeTtl(&$ttl)
    {
        if (!is_int($ttl)) {
            $ttl = (float) $ttl;

            // convert to int if possible
            if ($ttl === (float) (int) $ttl) {
                $ttl = (int) $ttl;
            }
        }

        if ($ttl < 0) {
             throw new Exception\InvalidArgumentException("TTL can't be negative");
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

use APCIterator as BaseApcIterator;
use stdClass;
use Traversable;
use Zend\Cache\Exception;
use Zend\Cache\Storage\AvailableSpaceCapableInterface;
use Zend\Cache\Storage\Capabilities;
use Zend\Cache\Storage\ClearByNamespaceInterface;
use Zend\Cache\Storage\ClearByPrefixInterface;
use Zend\Cache\Storage\FlushableInterface;
use Zend\Cache\Storage\IterableInterface;
use Zend\Cache\Storage\TotalSpaceCapableInterface;

class Apc extends AbstractAdapter implements
    AvailableSpaceCapableInterface,
    ClearByNamespaceInterface,
    ClearByPrefixInterface,
    FlushableInterface,
    IterableInterface,
    TotalSpaceCapableInterface
{
    /**
     * Buffered total space in bytes
     *
     * @var null|int|float
     */
    protected $totalSpace;

    /**
     * Constructor
     *
     * @param  null|array|Traversable|ApcOptions $options
     * @throws Exception\ExceptionInterface
     */
    public function __construct($options = null)
    {
        if (version_compare('3.1.6', phpversion('apc')) > 0) {
            throw new Exception\ExtensionNotLoadedException("Missing ext/apc >= 3.1.6");
        }

        $enabled = ini_get('apc.enabled');
        if (PHP_SAPI == 'cli') {
            $enabled = $enabled && (bool) ini_get('apc.enable_cli');
        }

        if (!$enabled) {
            throw new Exception\ExtensionNotLoadedException(
                "ext/apc is disabled - see 'apc.enabled' and 'apc.enable_cli'"
            );
        }

        parent::__construct($options);
    }

    /* options */

    /**
     * Set options.
     *
     * @param  array|Traversable|ApcOptions $options
     * @return Apc
     * @see    getOptions()
     */
    public function setOptions($options)
    {
        if (!$options instanceof ApcOptions) {
            $options = new ApcOptions($options);
        }

        return parent::setOptions($options);
    }

    /**
     * Get options.
     *
     * @return ApcOptions
     * @see    setOptions()
     */
    public function getOptions()
    {
        if (!$this->options) {
            $this->setOptions(new ApcOptions());
        }
        return $this->options;
    }

    /* TotalSpaceCapableInterface */

    /**
     * Get total space in bytes
     *
     * @return int|float
     */
    public function getTotalSpace()
    {
        if ($this->totalSpace === null) {
            $smaInfo = apc_sma_info(true);
            $this->totalSpace = $smaInfo['num_seg'] * $smaInfo['seg_size'];
        }

        return $this->totalSpace;
    }

    /* AvailableSpaceCapableInterface */

    /**
     * Get available space in bytes
     *
     * @return int|float
     */
    public function getAvailableSpace()
    {
        $smaInfo = apc_sma_info(true);
        return $smaInfo['avail_mem'];
    }

    /* IterableInterface */

    /**
     * Get the storage iterator
     *
     * @return ApcIterator
     */
    public function getIterator()
    {
        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        $prefix    = '';
        $pattern   = null;
        if ($namespace !== '') {
            $prefix  = $namespace . $options->getNamespaceSeparator();
            $pattern = '/^' . preg_quote($prefix, '/') . '/';
        }

        $baseIt = new BaseApcIterator('user', $pattern, 0, 1, APC_LIST_ACTIVE);
        return new ApcIterator($this, $baseIt, $prefix);
    }

    /* FlushableInterface */

    /**
     * Flush the whole storage
     *
     * @return bool
     */
    public function flush()
    {
        return apc_clear_cache('user');
    }

    /* ClearByNamespaceInterface */

    /**
     * Remove items by given namespace
     *
     * @param string $namespace
     * @return bool
     */
    public function clearByNamespace($namespace)
    {
        $namespace = (string) $namespace;
        if ($namespace === '') {
            throw new Exception\InvalidArgumentException('No namespace given');
        }

        $options = $this->getOptions();
        $prefix  = $namespace . $options->getNamespaceSeparator();
        $pattern = '/^' . preg_quote($prefix, '/') . '/';
        return apc_delete(new BaseApcIterator('user', $pattern, 0, 1, APC_LIST_ACTIVE));
    }

    /* ClearByPrefixInterface */

    /**
     * Remove items matching given prefix
     *
     * @param string $prefix
     * @return bool
     */
    public function clearByPrefix($prefix)
    {
        $prefix = (string) $prefix;
        if ($prefix === '') {
            throw new Exception\InvalidArgumentException('No prefix given');
        }

        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        $nsPrefix  = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $pattern = '/^' . preg_quote($nsPrefix . $prefix, '/') . '/';
        return apc_delete(new BaseApcIterator('user', $pattern, 0, 1, APC_LIST_ACTIVE));
    }

    /* reading */

    /**
     * Internal method to get an item.
     *
     * @param  string  $normalizedKey
     * @param  bool $success
     * @param  mixed   $casToken
     * @return mixed Data on success, null on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null)
    {
        $options     = $this->getOptions();
        $namespace   = $options->getNamespace();
        $prefix      = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $internalKey = $prefix . $normalizedKey;
        $result      = apc_fetch($internalKey, $success);

        if (!$success) {
            return null;
        }

        $casToken = $result;
        return $result;
    }

    /**
     * Internal method to get multiple items.
     *
     * @param  array $normalizedKeys
     * @return array Associative array of keys and values
     * @throws Exception\ExceptionInterface
     */
    protected function internalGetItems(array & $normalizedKeys)
    {
        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        if ($namespace === '') {
            return apc_fetch($normalizedKeys);
        }

        $prefix       = $namespace . $options->getNamespaceSeparator();
        $internalKeys = array();
        foreach ($normalizedKeys as $normalizedKey) {
            $internalKeys[] = $prefix . $normalizedKey;
        }

        $fetch = apc_fetch($internalKeys);

        // remove namespace prefix
        $prefixL = strlen($prefix);
        $result  = array();
        foreach ($fetch as $internalKey => & $value) {
            $result[substr($internalKey, $prefixL)] = $value;
        }

        return $result;
    }

    /**
     * Internal method to test if an item exists.
     *
     * @param  string $normalizedKey
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalHasItem(& $normalizedKey)
    {
        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        $prefix    = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        return apc_exists($prefix . $normalizedKey);
    }

    /**
     * Internal method to test multiple items.
     *
     * @param  array $normalizedKeys
     * @return array Array of found keys
     * @throws Exception\ExceptionInterface
     */
    protected function internalHasItems(array & $normalizedKeys)
    {
        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        if ($namespace === '') {
            // array_filter with no callback will remove entries equal to FALSE
            return array_keys(array_filter(apc_exists($normalizedKeys)));
        }

        $prefix       = $namespace . $options->getNamespaceSeparator();
        $internalKeys = array();
        foreach ($normalizedKeys as $normalizedKey) {
            $internalKeys[] = $prefix . $normalizedKey;
        }

        $exists  = apc_exists($internalKeys);
        $result  = array();
        $prefixL = strlen($prefix);
        foreach ($exists as $internalKey => $bool) {
            if ($bool === true) {
                $result[] = substr($internalKey, $prefixL);
            }
        }

        return $result;
    }

    /**
     * Get metadata of an item.
     *
     * @param  string $normalizedKey
     * @return array|bool Metadata on success, false on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalGetMetadata(& $normalizedKey)
    {
        $options     = $this->getOptions();
        $namespace   = $options->getNamespace();
        $prefix      = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $internalKey = $prefix . $normalizedKey;

        // @see http://pecl.php.net/bugs/bug.php?id=22564
        if (!apc_exists($internalKey)) {
            $metadata = false;
        } else {
            $format   = APC_ITER_ALL ^ APC_ITER_VALUE ^ APC_ITER_TYPE ^ APC_ITER_REFCOUNT;
            $regexp   = '/^' . preg_quote($internalKey, '/') . '$/';
            $it       = new BaseApcIterator('user', $regexp, $format, 100, APC_LIST_ACTIVE);
            $metadata = $it->current();
        }

        if (!$metadata) {
            return false;
        }

        $this->normalizeMetadata($metadata);
        return $metadata;
    }

    /**
     * Get metadata of multiple items
     *
     * @param  array $normalizedKeys
     * @return array Associative array of keys and metadata
     *
     * @triggers getMetadatas.pre(PreEvent)
     * @triggers getMetadatas.post(PostEvent)
     * @triggers getMetadatas.exception(ExceptionEvent)
     */
    protected function internalGetMetadatas(array & $normalizedKeys)
    {
        $keysRegExp = array();
        foreach ($normalizedKeys as $normalizedKey) {
            $keysRegExp[] = preg_quote($normalizedKey, '/');
        }

        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        if ($namespace === '') {
            $pattern = '/^(' . implode('|', $keysRegExp) . ')' . '$/';
        } else {
            $prefix  = $namespace . $options->getNamespaceSeparator();
            $pattern = '/^' . preg_quote($prefix, '/') . '(' . implode('|', $keysRegExp) . ')' . '$/';
        }
        $format  = APC_ITER_ALL ^ APC_ITER_VALUE ^ APC_ITER_TYPE ^ APC_ITER_REFCOUNT;
        $it      = new BaseApcIterator('user', $pattern, $format, 100, APC_LIST_ACTIVE);
        $result  = array();
        $prefixL = strlen($prefix);
        foreach ($it as $internalKey => $metadata) {
            // @see http://pecl.php.net/bugs/bug.php?id=22564
            if (!apc_exists($internalKey)) {
                continue;
            }

            $this->normalizeMetadata($metadata);
            $result[substr($internalKey, $prefixL)] = & $metadata;
        }

        return $result;
    }

    /* writing */

    /**
     * Internal method to store an item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalSetItem(& $normalizedKey, & $value)
    {
        $options     = $this->getOptions();
        $namespace   = $options->getNamespace();
        $prefix      = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $internalKey = $prefix . $normalizedKey;
        $ttl         = $options->getTtl();

        if (!apc_store($internalKey, $value, $ttl)) {
            $type = is_object($value) ? get_class($value) : gettype($value);
            throw new Exception\RuntimeException(
                "apc_store('{$internalKey}', <{$type}>, {$ttl}) failed"
            );
        }

        return true;
    }

    /**
     * Internal method to store multiple items.
     *
     * @param  array $normalizedKeyValuePairs
     * @return array Array of not stored keys
     * @throws Exception\ExceptionInterface
     */
    protected function internalSetItems(array & $normalizedKeyValuePairs)
    {
        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        if ($namespace === '') {
            return array_keys(apc_store($normalizedKeyValuePairs, null, $options->getTtl()));
        }

        $prefix                = $namespace . $options->getNamespaceSeparator();
        $internalKeyValuePairs = array();
        foreach ($normalizedKeyValuePairs as $normalizedKey => &$value) {
            $internalKey = $prefix . $normalizedKey;
            $internalKeyValuePairs[$internalKey] = &$value;
        }

        $failedKeys = apc_store($internalKeyValuePairs, null, $options->getTtl());
        $failedKeys = array_keys($failedKeys);

        // remove prefix
        $prefixL = strlen($prefix);
        foreach ($failedKeys as & $key) {
            $key = substr($key, $prefixL);
        }

        return $failedKeys;
    }

    /**
     * Add an item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalAddItem(& $normalizedKey, & $value)
    {
        $options     = $this->getOptions();
        $namespace   = $options->getNamespace();
        $prefix      = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $internalKey = $prefix . $normalizedKey;
        $ttl         = $options->getTtl();

        if (!apc_add($internalKey, $value, $ttl)) {
            if (apc_exists($internalKey)) {
                return false;
            }

            $type = is_object($value) ? get_class($value) : gettype($value);
            throw new Exception\RuntimeException(
                "apc_add('{$internalKey}', <{$type}>, {$ttl}) failed"
            );
        }

        return true;
    }

    /**
     * Internal method to add multiple items.
     *
     * @param  array $normalizedKeyValuePairs
     * @return array Array of not stored keys
     * @throws Exception\ExceptionInterface
     */
    protected function internalAddItems(array & $normalizedKeyValuePairs)
    {
        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        if ($namespace === '') {
            return array_keys(apc_add($normalizedKeyValuePairs, null, $options->getTtl()));
        }

        $prefix                = $namespace . $options->getNamespaceSeparator();
        $internalKeyValuePairs = array();
        foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
            $internalKey = $prefix . $normalizedKey;
            $internalKeyValuePairs[$internalKey] = $value;
        }

        $failedKeys = apc_add($internalKeyValuePairs, null, $options->getTtl());
        $failedKeys = array_keys($failedKeys);

        // remove prefix
        $prefixL = strlen($prefix);
        foreach ($failedKeys as & $key) {
            $key = substr($key, $prefixL);
        }

        return $failedKeys;
    }

    /**
     * Internal method to replace an existing item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalReplaceItem(& $normalizedKey, & $value)
    {
        $options     = $this->getOptions();
        $namespace   = $options->getNamespace();
        $prefix      = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $internalKey = $prefix . $normalizedKey;

        if (!apc_exists($internalKey)) {
            return false;
        }

        $ttl = $options->getTtl();
        if (!apc_store($internalKey, $value, $ttl)) {
            $type = is_object($value) ? get_class($value) : gettype($value);
            throw new Exception\RuntimeException(
                "apc_store('{$internalKey}', <{$type}>, {$ttl}) failed"
            );
        }

        return true;
    }

    /**
     * Internal method to remove an item.
     *
     * @param  string $normalizedKey
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalRemoveItem(& $normalizedKey)
    {
        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        $prefix    = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        return apc_delete($prefix . $normalizedKey);
    }

    /**
     * Internal method to remove multiple items.
     *
     * @param  array $normalizedKeys
     * @return array Array of not removed keys
     * @throws Exception\ExceptionInterface
     */
    protected function internalRemoveItems(array & $normalizedKeys)
    {
        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        if ($namespace === '') {
            return apc_delete($normalizedKeys);
        }

        $prefix       = $namespace . $options->getNamespaceSeparator();
        $internalKeys = array();
        foreach ($normalizedKeys as $normalizedKey) {
            $internalKeys[] = $prefix . $normalizedKey;
        }

        $failedKeys = apc_delete($internalKeys);

        // remove prefix
        $prefixL = strlen($prefix);
        foreach ($failedKeys as & $key) {
            $key = substr($key, $prefixL);
        }

        return $failedKeys;
    }

    /**
     * Internal method to increment an item.
     *
     * @param  string $normalizedKey
     * @param  int    $value
     * @return int|bool The new value on success, false on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalIncrementItem(& $normalizedKey, & $value)
    {
        $options     = $this->getOptions();
        $namespace   = $options->getNamespace();
        $prefix      = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $internalKey = $prefix . $normalizedKey;
        $ttl         = $options->getTtl();
        $value       = (int) $value;
        $newValue    = apc_inc($internalKey, $value);

        // initial value
        if ($newValue === false) {
            $ttl      = $options->getTtl();
            $newValue = $value;
            if (!apc_add($internalKey, $newValue, $ttl)) {
                throw new Exception\RuntimeException(
                    "apc_add('{$internalKey}', {$newValue}, {$ttl}) failed"
                );
            }
        }

        return $newValue;
    }

    /**
     * Internal method to decrement an item.
     *
     * @param  string $normalizedKey
     * @param  int    $value
     * @return int|bool The new value on success, false on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalDecrementItem(& $normalizedKey, & $value)
    {
        $options     = $this->getOptions();
        $namespace   = $options->getNamespace();
        $prefix      = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $internalKey = $prefix . $normalizedKey;
        $value       = (int) $value;
        $newValue    = apc_dec($internalKey, $value);

        // initial value
        if ($newValue === false) {
            $ttl      = $options->getTtl();
            $newValue = -$value;
            if (!apc_add($internalKey, $newValue, $ttl)) {
                throw new Exception\RuntimeException(
                    "apc_add('{$internalKey}', {$newValue}, {$ttl}) failed"
                );
            }
        }

        return $newValue;
    }

    /* status */

    /**
     * Internal method to get capabilities of this adapter
     *
     * @return Capabilities
     */
    protected function internalGetCapabilities()
    {
        if ($this->capabilities === null) {
            $marker       = new stdClass();
            $capabilities = new Capabilities(
                $this,
                $marker,
                array(
                    'supportedDatatypes' => array(
                        'NULL'     => true,
                        'boolean'  => true,
                        'integer'  => true,
                        'double'   => true,
                        'string'   => true,
                        'array'    => true,
                        'object'   => 'object',
                        'resource' => false,
                    ),
                    'supportedMetadata' => array(
                        'internal_key',
                        'atime', 'ctime', 'mtime', 'rtime',
                        'size', 'hits', 'ttl',
                    ),
                    'minTtl'             => 1,
                    'maxTtl'             => 0,
                    'staticTtl'          => true,
                    'ttlPrecision'       => 1,
                    'useRequestTime'     => (bool) ini_get('apc.use_request_time'),
                    'expiredRead'        => false,
                    'maxKeyLength'       => 5182,
                    'namespaceIsPrefix'  => true,
                    'namespaceSeparator' => $this->getOptions()->getNamespaceSeparator(),
                )
            );

            // update namespace separator on change option
            $this->getEventManager()->attach('option', function ($event) use ($capabilities, $marker) {
                $params = $event->getParams();

                if (isset($params['namespace_separator'])) {
                    $capabilities->setNamespaceSeparator($marker, $params['namespace_separator']);
                }
            });

            $this->capabilities     = $capabilities;
            $this->capabilityMarker = $marker;
        }

        return $this->capabilities;
    }

    /* internal */

    /**
     * Normalize metadata to work with APC
     *
     * @param  array $metadata
     * @return void
     */
    protected function normalizeMetadata(array & $metadata)
    {
        $metadata['internal_key'] = $metadata['key'];
        $metadata['ctime']        = $metadata['creation_time'];
        $metadata['atime']        = $metadata['access_time'];
        $metadata['rtime']        = $metadata['deletion_time'];
        $metadata['size']         = $metadata['mem_size'];
        $metadata['hits']         = $metadata['num_hits'];

        unset(
            $metadata['key'],
            $metadata['creation_time'],
            $metadata['access_time'],
            $metadata['deletion_time'],
            $metadata['mem_size'],
            $metadata['num_hits']
        );
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

use Countable;
use Zend\Cache\Storage\IteratorInterface;
use Zend\Cache\Storage\StorageInterface;

class KeyListIterator implements IteratorInterface, Countable
{

    /**
     * The storage instance
     *
     * @var StorageInterface
     */
    protected $storage;

    /**
     * The iterator mode
     *
     * @var int
     */
    protected $mode = IteratorInterface::CURRENT_AS_KEY;

    /**
     * Keys to iterate over
     *
     * @var string[]
     */
    protected $keys;

    /**
     * Number of keys
     *
     * @var int
     */
    protected $count;

    /**
     * Current iterator position
     *
     * @var int
     */
    protected $position = 0;

    /**
     * Constructor
     *
     * @param StorageInterface $storage
     * @param array            $keys
     */
    public function __construct(StorageInterface $storage, array $keys)
    {
        $this->storage = $storage;
        $this->keys    = $keys;
        $this->count   = count($keys);
    }

    /**
     * Get storage instance
     *
     * @return StorageInterface
     */
    public function getStorage()
    {
        return $this->storage;
    }

    /**
     * Get iterator mode
     *
     * @return int Value of IteratorInterface::CURRENT_AS_*
     */
    public function getMode()
    {
        return $this->mode;
    }

    /**
     * Set iterator mode
     *
     * @param int $mode
     * @return KeyListIterator Fluent interface
     */
    public function setMode($mode)
    {
        $this->mode = (int) $mode;
        return $this;
    }

    /**
     * Get current key, value or metadata.
     *
     * @return mixed
     */
    public function current()
    {
        if ($this->mode == IteratorInterface::CURRENT_AS_SELF) {
            return $this;
        }

        $key = $this->key();

        if ($this->mode == IteratorInterface::CURRENT_AS_METADATA) {
            return $this->storage->getMetadata($key);
        } elseif ($this->mode == IteratorInterface::CURRENT_AS_VALUE) {
            return $this->storage->getItem($key);
        }

        return $key;
    }

    /**
     * Get current key
     *
     * @return string
     */
    public function key()
    {
        return $this->keys[$this->position];
    }

    /**
     * Checks if current position is valid
     *
     * @return bool
     */
    public function valid()
    {
        return $this->position < $this->count;
    }

    /**
     * Move forward to next element
     *
     * @return void
     */
    public function next()
    {
        $this->position++;
    }

    /**
     * Rewind the Iterator to the first element.
     *
     * @return void
     */
    public function rewind()
    {
        $this->position = 0;
    }

    /**
     * Count number of items
     *
     * @return int
     */
    public function count()
    {
        return $this->count;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

use Exception as BaseException;
use GlobIterator;
use stdClass;
use Zend\Cache\Exception;
use Zend\Cache\Storage;
use Zend\Cache\Storage\AvailableSpaceCapableInterface;
use Zend\Cache\Storage\Capabilities;
use Zend\Cache\Storage\ClearByNamespaceInterface;
use Zend\Cache\Storage\ClearByPrefixInterface;
use Zend\Cache\Storage\ClearExpiredInterface;
use Zend\Cache\Storage\FlushableInterface;
use Zend\Cache\Storage\IterableInterface;
use Zend\Cache\Storage\OptimizableInterface;
use Zend\Cache\Storage\TaggableInterface;
use Zend\Cache\Storage\TotalSpaceCapableInterface;
use Zend\Stdlib\ErrorHandler;

class Filesystem extends AbstractAdapter implements
    AvailableSpaceCapableInterface,
    ClearByNamespaceInterface,
    ClearByPrefixInterface,
    ClearExpiredInterface,
    FlushableInterface,
    IterableInterface,
    OptimizableInterface,
    TaggableInterface,
    TotalSpaceCapableInterface
{

    /**
     * Buffered total space in bytes
     *
     * @var null|int|float
     */
    protected $totalSpace;

    /**
     * An identity for the last filespec
     * (cache directory + namespace prefix + key + directory level)
     *
     * @var string
     */
    protected $lastFileSpecId = '';

    /**
     * The last used filespec
     *
     * @var string
     */
    protected $lastFileSpec = '';

    /**
     * Set options.
     *
     * @param  array|\Traversable|FilesystemOptions $options
     * @return Filesystem
     * @see    getOptions()
     */
    public function setOptions($options)
    {
        if (!$options instanceof FilesystemOptions) {
            $options = new FilesystemOptions($options);
        }

        return parent::setOptions($options);
    }

    /**
     * Get options.
     *
     * @return FilesystemOptions
     * @see setOptions()
     */
    public function getOptions()
    {
        if (!$this->options) {
            $this->setOptions(new FilesystemOptions());
        }
        return $this->options;
    }

    /* FlushableInterface */

    /**
     * Flush the whole storage
     *
     * @throws Exception\RuntimeException
     * @return bool
     */
    public function flush()
    {
        $flags = GlobIterator::SKIP_DOTS | GlobIterator::CURRENT_AS_PATHNAME;
        $dir   = $this->getOptions()->getCacheDir();
        $clearFolder = null;
        $clearFolder = function ($dir) use (& $clearFolder, $flags) {
            $it = new GlobIterator($dir . DIRECTORY_SEPARATOR . '*', $flags);
            foreach ($it as $pathname) {
                if ($it->isDir()) {
                    $clearFolder($pathname);
                    rmdir($pathname);
                } else {
                    unlink($pathname);
                }
            }
        };

        ErrorHandler::start();
        $clearFolder($dir);
        $error = ErrorHandler::stop();
        if ($error) {
            throw new Exception\RuntimeException("Flushing directory '{$dir}' failed", 0, $error);
        }

        return true;
    }

    /* ClearExpiredInterface */

    /**
     * Remove expired items
     *
     * @return bool
     */
    public function clearExpired()
    {
        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        $prefix    = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();

        $flags = GlobIterator::SKIP_DOTS | GlobIterator::CURRENT_AS_FILEINFO;
        $path  = $options->getCacheDir()
            . str_repeat(DIRECTORY_SEPARATOR . $prefix . '*', $options->getDirLevel())
            . DIRECTORY_SEPARATOR . $prefix . '*.dat';
        $glob = new GlobIterator($path, $flags);
        $time = time();
        $ttl  = $options->getTtl();

        ErrorHandler::start();
        foreach ($glob as $entry) {
            $mtime = $entry->getMTime();
            if ($time >= $mtime + $ttl) {
                $pathname = $entry->getPathname();
                unlink($pathname);

                $tagPathname = substr($pathname, 0, -4) . '.tag';
                if (file_exists($tagPathname)) {
                    unlink($tagPathname);
                }
            }
        }
        $error = ErrorHandler::stop();
        if ($error) {
            throw new Exception\RuntimeException("Failed to clear expired items", 0, $error);
        }

        return true;
    }

    /* ClearByNamespaceInterface */

    /**
     * Remove items by given namespace
     *
     * @param string $namespace
     * @throws Exception\RuntimeException
     * @return bool
     */
    public function clearByNamespace($namespace)
    {
        $namespace = (string) $namespace;
        if ($namespace === '') {
            throw new Exception\InvalidArgumentException('No namespace given');
        }

        $options = $this->getOptions();
        $prefix  = $namespace . $options->getNamespaceSeparator();

        $flags = GlobIterator::SKIP_DOTS | GlobIterator::CURRENT_AS_PATHNAME;
        $path = $options->getCacheDir()
            . str_repeat(DIRECTORY_SEPARATOR . $prefix . '*', $options->getDirLevel())
            . DIRECTORY_SEPARATOR . $prefix . '*';
        $glob = new GlobIterator($path, $flags);

        ErrorHandler::start();
        foreach ($glob as $pathname) {
            unlink($pathname);
        }
        $error = ErrorHandler::stop();
        if ($error) {
            throw new Exception\RuntimeException("Failed to remove files of '{$path}'", 0, $error);
        }

        return true;
    }

    /* ClearByPrefixInterface */

    /**
     * Remove items matching given prefix
     *
     * @param string $prefix
     * @throws Exception\RuntimeException
     * @return bool
     */
    public function clearByPrefix($prefix)
    {
        $prefix = (string) $prefix;
        if ($prefix === '') {
            throw new Exception\InvalidArgumentException('No prefix given');
        }

        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        $nsPrefix  = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();

        $flags = GlobIterator::SKIP_DOTS | GlobIterator::CURRENT_AS_PATHNAME;
        $path = $options->getCacheDir()
            . str_repeat(DIRECTORY_SEPARATOR . $nsPrefix . '*', $options->getDirLevel())
            . DIRECTORY_SEPARATOR . $nsPrefix . $prefix . '*';
        $glob = new GlobIterator($path, $flags);

        ErrorHandler::start();
        foreach ($glob as $pathname) {
            unlink($pathname);
        }
        $error = ErrorHandler::stop();
        if ($error) {
            throw new Exception\RuntimeException("Failed to remove files of '{$path}'", 0, $error);
        }

        return true;
    }

    /* TaggableInterface  */

    /**
     * Set tags to an item by given key.
     * An empty array will remove all tags.
     *
     * @param string   $key
     * @param string[] $tags
     * @return bool
     */
    public function setTags($key, array $tags)
    {
        $this->normalizeKey($key);
        if (!$this->internalHasItem($key)) {
            return false;
        }

        $filespec = $this->getFileSpec($key);

        if (!$tags) {
            $this->unlink($filespec . '.tag');
            return true;
        }

        $this->putFileContent($filespec . '.tag', implode("\n", $tags));
        return true;
    }

    /**
     * Get tags of an item by given key
     *
     * @param string $key
     * @return string[]|FALSE
     */
    public function getTags($key)
    {
        $this->normalizeKey($key);
        if (!$this->internalHasItem($key)) {
            return false;
        }

        $filespec = $this->getFileSpec($key);
        $tags     = array();
        if (file_exists($filespec . '.tag')) {
            $tags = explode("\n", $this->getFileContent($filespec . '.tag'));
        }

        return $tags;
    }

    /**
     * Remove items matching given tags.
     *
     * If $disjunction only one of the given tags must match
     * else all given tags must match.
     *
     * @param string[] $tags
     * @param  bool  $disjunction
     * @return bool
     */
    public function clearByTags(array $tags, $disjunction = false)
    {
        if (!$tags) {
            return true;
        }

        $tagCount  = count($tags);
        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        $prefix    = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();

        $flags = GlobIterator::SKIP_DOTS | GlobIterator::CURRENT_AS_PATHNAME;
        $path  = $options->getCacheDir()
            . str_repeat(DIRECTORY_SEPARATOR . $prefix . '*', $options->getDirLevel())
            . DIRECTORY_SEPARATOR . $prefix . '*.tag';
        $glob = new GlobIterator($path, $flags);

        foreach ($glob as $pathname) {
            $diff = array_diff($tags, explode("\n", $this->getFileContent($pathname)));

            $rem  = false;
            if ($disjunction && count($diff) < $tagCount) {
                $rem = true;
            } elseif (!$disjunction && !$diff) {
                $rem = true;
            }

            if ($rem) {
                unlink($pathname);

                $datPathname = substr($pathname, 0, -4) . '.dat';
                if (file_exists($datPathname)) {
                    unlink($datPathname);
                }
            }
        }

        return true;
    }

    /* IterableInterface */

    /**
     * Get the storage iterator
     *
     * @return FilesystemIterator
     */
    public function getIterator()
    {
        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        $prefix    = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $path      = $options->getCacheDir()
            . str_repeat(DIRECTORY_SEPARATOR . $prefix . '*', $options->getDirLevel())
            . DIRECTORY_SEPARATOR . $prefix . '*.dat';
        return new FilesystemIterator($this, $path, $prefix);
    }

    /* OptimizableInterface */

    /**
     * Optimize the storage
     *
     * @return bool
     * @return Exception\RuntimeException
     */
    public function optimize()
    {
        $options = $this->getOptions();
        if ($options->getDirLevel()) {
            $namespace = $options->getNamespace();
            $prefix    = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();

            // removes only empty directories
            $this->rmDir($options->getCacheDir(), $prefix);
        }
        return true;
    }

    /* TotalSpaceCapableInterface */

    /**
     * Get total space in bytes
     *
     * @throws Exception\RuntimeException
     * @return int|float
     */
    public function getTotalSpace()
    {
        if ($this->totalSpace === null) {
            $path = $this->getOptions()->getCacheDir();

            ErrorHandler::start();
            $total = disk_total_space($path);
            $error = ErrorHandler::stop();
            if ($total === false) {
                throw new Exception\RuntimeException("Can't detect total space of '{$path}'", 0, $error);
            }
            $this->totalSpace = $total;

            // clean total space buffer on change cache_dir
            $events     = $this->getEventManager();
            $handle     = null;
            $totalSpace = & $this->totalSpace;
            $callback   = function ($event) use (& $events, & $handle, & $totalSpace) {
                $params = $event->getParams();
                if (isset($params['cache_dir'])) {
                    $totalSpace = null;
                    $events->detach($handle);
                }
            };
            $handle = $events->attach('option', $callback);
        }

        return $this->totalSpace;
    }

    /* AvailableSpaceCapableInterface */

    /**
     * Get available space in bytes
     *
     * @throws Exception\RuntimeException
     * @return int|float
     */
    public function getAvailableSpace()
    {
        $path = $this->getOptions()->getCacheDir();

        ErrorHandler::start();
        $avail = disk_free_space($path);
        $error = ErrorHandler::stop();
        if ($avail === false) {
            throw new Exception\RuntimeException("Can't detect free space of '{$path}'", 0, $error);
        }

        return $avail;
    }

    /* reading */

    /**
     * Get an item.
     *
     * @param  string  $key
     * @param  bool $success
     * @param  mixed   $casToken
     * @return mixed Data on success, null on failure
     * @throws Exception\ExceptionInterface
     *
     * @triggers getItem.pre(PreEvent)
     * @triggers getItem.post(PostEvent)
     * @triggers getItem.exception(ExceptionEvent)
     */
    public function getItem($key, & $success = null, & $casToken = null)
    {
        $options = $this->getOptions();
        if ($options->getReadable() && $options->getClearStatCache()) {
            clearstatcache();
        }

        $argn = func_num_args();
        if ($argn > 2) {
            return parent::getItem($key, $success, $casToken);
        } elseif ($argn > 1) {
            return parent::getItem($key, $success);
        }

        return parent::getItem($key);
    }

    /**
     * Get multiple items.
     *
     * @param  array $keys
     * @return array Associative array of keys and values
     * @throws Exception\ExceptionInterface
     *
     * @triggers getItems.pre(PreEvent)
     * @triggers getItems.post(PostEvent)
     * @triggers getItems.exception(ExceptionEvent)
     */
    public function getItems(array $keys)
    {
        $options = $this->getOptions();
        if ($options->getReadable() && $options->getClearStatCache()) {
            clearstatcache();
        }

        return parent::getItems($keys);
    }

    /**
     * Internal method to get an item.
     *
     * @param  string  $normalizedKey
     * @param  bool $success
     * @param  mixed   $casToken
     * @return mixed Data on success, null on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null)
    {
        if (!$this->internalHasItem($normalizedKey)) {
            $success = false;
            return null;
        }

        try {
            $filespec = $this->getFileSpec($normalizedKey);
            $data     = $this->getFileContent($filespec . '.dat');

            // use filemtime + filesize as CAS token
            if (func_num_args() > 2) {
                $casToken = filemtime($filespec . '.dat') . filesize($filespec . '.dat');
            }
            $success  = true;
            return $data;

        } catch (BaseException $e) {
            $success = false;
            throw $e;
        }
    }

    /**
     * Internal method to get multiple items.
     *
     * @param  array $normalizedKeys
     * @return array Associative array of keys and values
     * @throws Exception\ExceptionInterface
     */
    protected function internalGetItems(array & $normalizedKeys)
    {
        $options = $this->getOptions();
        $keys    = $normalizedKeys; // Don't change argument passed by reference
        $result  = array();
        while ($keys) {

            // LOCK_NB if more than one items have to read
            $nonBlocking = count($keys) > 1;
            $wouldblock  = null;

            // read items
            foreach ($keys as $i => $key) {
                if (!$this->internalHasItem($key)) {
                    unset($keys[$i]);
                    continue;
                }

                $filespec = $this->getFileSpec($key);
                $data     = $this->getFileContent($filespec . '.dat', $nonBlocking, $wouldblock);
                if ($nonBlocking && $wouldblock) {
                    continue;
                } else {
                    unset($keys[$i]);
                }

                $result[$key] = $data;
            }

            // TODO: Don't check ttl after first iteration
            // $options['ttl'] = 0;
        }

        return $result;
    }

    /**
     * Test if an item exists.
     *
     * @param  string $key
     * @return bool
     * @throws Exception\ExceptionInterface
     *
     * @triggers hasItem.pre(PreEvent)
     * @triggers hasItem.post(PostEvent)
     * @triggers hasItem.exception(ExceptionEvent)
     */
    public function hasItem($key)
    {
        $options = $this->getOptions();
        if ($options->getReadable() && $options->getClearStatCache()) {
            clearstatcache();
        }

        return parent::hasItem($key);
    }

    /**
     * Test multiple items.
     *
     * @param  array $keys
     * @return array Array of found keys
     * @throws Exception\ExceptionInterface
     *
     * @triggers hasItems.pre(PreEvent)
     * @triggers hasItems.post(PostEvent)
     * @triggers hasItems.exception(ExceptionEvent)
     */
    public function hasItems(array $keys)
    {
        $options = $this->getOptions();
        if ($options->getReadable() && $options->getClearStatCache()) {
            clearstatcache();
        }

        return parent::hasItems($keys);
    }

    /**
     * Internal method to test if an item exists.
     *
     * @param  string $normalizedKey
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalHasItem(& $normalizedKey)
    {
        $file = $this->getFileSpec($normalizedKey) . '.dat';
        if (!file_exists($file)) {
            return false;
        }

        $ttl = $this->getOptions()->getTtl();
        if ($ttl) {
            ErrorHandler::start();
            $mtime = filemtime($file);
            $error = ErrorHandler::stop();
            if (!$mtime) {
                throw new Exception\RuntimeException(
                    "Error getting mtime of file '{$file}'", 0, $error
                );
            }

            if (time() >= ($mtime + $ttl)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Get metadata
     *
     * @param string $key
     * @return array|bool Metadata on success, false on failure
     */
    public function getMetadata($key)
    {
        $options = $this->getOptions();
        if ($options->getReadable() && $options->getClearStatCache()) {
            clearstatcache();
        }

        return parent::getMetadata($key);
    }

    /**
     * Get metadatas
     *
     * @param array $keys
     * @param array $options
     * @return array Associative array of keys and metadata
     */
    public function getMetadatas(array $keys, array $options = array())
    {
        $options = $this->getOptions();
        if ($options->getReadable() && $options->getClearStatCache()) {
            clearstatcache();
        }

        return parent::getMetadatas($keys);
    }

    /**
     * Get info by key
     *
     * @param string $normalizedKey
     * @return array|bool Metadata on success, false on failure
     */
    protected function internalGetMetadata(& $normalizedKey)
    {
        if (!$this->internalHasItem($normalizedKey)) {
            return false;
        }

        $options  = $this->getOptions();
        $filespec = $this->getFileSpec($normalizedKey);
        $file     = $filespec . '.dat';

        $metadata = array(
            'filespec' => $filespec,
            'mtime'    => filemtime($file)
        );

        if (!$options->getNoCtime()) {
            $metadata['ctime'] = filectime($file);
        }

        if (!$options->getNoAtime()) {
            $metadata['atime'] = fileatime($file);
        }

        return $metadata;
    }

    /**
     * Internal method to get multiple metadata
     *
     * @param  array $normalizedKeys
     * @return array Associative array of keys and metadata
     * @throws Exception\ExceptionInterface
     */
    protected function internalGetMetadatas(array & $normalizedKeys)
    {
        $options = $this->getOptions();
        $result  = array();

        foreach ($normalizedKeys as $normalizedKey) {
            $filespec = $this->getFileSpec($normalizedKey);
            $file     = $filespec . '.dat';

            $metadata = array(
                'filespec' => $filespec,
                'mtime'    => filemtime($file),
            );

            if (!$options->getNoCtime()) {
                $metadata['ctime'] = filectime($file);
            }

            if (!$options->getNoAtime()) {
                $metadata['atime'] = fileatime($file);
            }

            $result[$normalizedKey] = $metadata;
        }

        return $result;
    }

    /* writing */

    /**
     * Store an item.
     *
     * @param  string $key
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     *
     * @triggers setItem.pre(PreEvent)
     * @triggers setItem.post(PostEvent)
     * @triggers setItem.exception(ExceptionEvent)
     */
    public function setItem($key, $value)
    {
        $options = $this->getOptions();
        if ($options->getWritable() && $options->getClearStatCache()) {
            clearstatcache();
        }
        return parent::setItem($key, $value);
    }

    /**
     * Store multiple items.
     *
     * @param  array $keyValuePairs
     * @return array Array of not stored keys
     * @throws Exception\ExceptionInterface
     *
     * @triggers setItems.pre(PreEvent)
     * @triggers setItems.post(PostEvent)
     * @triggers setItems.exception(ExceptionEvent)
     */
    public function setItems(array $keyValuePairs)
    {
        $options = $this->getOptions();
        if ($options->getWritable() && $options->getClearStatCache()) {
            clearstatcache();
        }

        return parent::setItems($keyValuePairs);
    }

    /**
     * Add an item.
     *
     * @param  string $key
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     *
     * @triggers addItem.pre(PreEvent)
     * @triggers addItem.post(PostEvent)
     * @triggers addItem.exception(ExceptionEvent)
     */
    public function addItem($key, $value)
    {
        $options = $this->getOptions();
        if ($options->getWritable() && $options->getClearStatCache()) {
            clearstatcache();
        }

        return parent::addItem($key, $value);
    }

    /**
     * Add multiple items.
     *
     * @param  array $keyValuePairs
     * @return bool
     * @throws Exception\ExceptionInterface
     *
     * @triggers addItems.pre(PreEvent)
     * @triggers addItems.post(PostEvent)
     * @triggers addItems.exception(ExceptionEvent)
     */
    public function addItems(array $keyValuePairs)
    {
        $options = $this->getOptions();
        if ($options->getWritable() && $options->getClearStatCache()) {
            clearstatcache();
        }

        return parent::addItems($keyValuePairs);
    }

    /**
     * Replace an existing item.
     *
     * @param  string $key
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     *
     * @triggers replaceItem.pre(PreEvent)
     * @triggers replaceItem.post(PostEvent)
     * @triggers replaceItem.exception(ExceptionEvent)
     */
    public function replaceItem($key, $value)
    {
        $options = $this->getOptions();
        if ($options->getWritable() && $options->getClearStatCache()) {
            clearstatcache();
        }

        return parent::replaceItem($key, $value);
    }

    /**
     * Replace multiple existing items.
     *
     * @param  array $keyValuePairs
     * @return bool
     * @throws Exception\ExceptionInterface
     *
     * @triggers replaceItems.pre(PreEvent)
     * @triggers replaceItems.post(PostEvent)
     * @triggers replaceItems.exception(ExceptionEvent)
     */
    public function replaceItems(array $keyValuePairs)
    {
        $options = $this->getOptions();
        if ($options->getWritable() && $options->getClearStatCache()) {
            clearstatcache();
        }

        return parent::replaceItems($keyValuePairs);
    }

    /**
     * Internal method to store an item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalSetItem(& $normalizedKey, & $value)
    {
        $filespec = $this->getFileSpec($normalizedKey);
        $this->prepareDirectoryStructure($filespec);

        // write data in non-blocking mode
        $wouldblock = null;
        $this->putFileContent($filespec . '.dat', $value, true, $wouldblock);

        // delete related tag file (if present)
        $this->unlink($filespec . '.tag');

        // Retry writing data in blocking mode if it was blocked before
        if ($wouldblock) {
            $this->putFileContent($filespec . '.dat', $value);
        }

        return true;
    }

    /**
     * Internal method to store multiple items.
     *
     * @param  array $normalizedKeyValuePairs
     * @return array Array of not stored keys
     * @throws Exception\ExceptionInterface
     */
    protected function internalSetItems(array & $normalizedKeyValuePairs)
    {
        $oldUmask    = null;

        // create an associated array of files and contents to write
        $contents = array();
        foreach ($normalizedKeyValuePairs as $key => & $value) {
            $filespec = $this->getFileSpec($key);
            $this->prepareDirectoryStructure($filespec);

            // *.dat file
            $contents[$filespec . '.dat'] = & $value;

            // *.tag file
            $this->unlink($filespec . '.tag');
        }

        // write to disk
        while ($contents) {
            $nonBlocking = count($contents) > 1;
            $wouldblock  = null;

            foreach ($contents as $file => & $content) {
                $this->putFileContent($file, $content, $nonBlocking, $wouldblock);
                if (!$nonBlocking || !$wouldblock) {
                    unset($contents[$file]);
                }
            }
        }

        // return OK
        return array();
    }

    /**
     * Set an item only if token matches
     *
     * It uses the token received from getItem() to check if the item has
     * changed before overwriting it.
     *
     * @param  mixed  $token
     * @param  string $key
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     * @see    getItem()
     * @see    setItem()
     */
    public function checkAndSetItem($token, $key, $value)
    {
        $options = $this->getOptions();
        if ($options->getWritable() && $options->getClearStatCache()) {
            clearstatcache();
        }

        return parent::checkAndSetItem($token, $key, $value);
    }

    /**
     * Internal method to set an item only if token matches
     *
     * @param  mixed  $token
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     * @see    getItem()
     * @see    setItem()
     */
    protected function internalCheckAndSetItem(& $token, & $normalizedKey, & $value)
    {
        if (!$this->internalHasItem($normalizedKey)) {
            return false;
        }

        // use filemtime + filesize as CAS token
        $file  = $this->getFileSpec($normalizedKey) . '.dat';
        $check = filemtime($file) . filesize($file);
        if ($token !== $check) {
            return false;
        }

        return $this->internalSetItem($normalizedKey, $value);
    }

    /**
     * Reset lifetime of an item
     *
     * @param  string $key
     * @return bool
     * @throws Exception\ExceptionInterface
     *
     * @triggers touchItem.pre(PreEvent)
     * @triggers touchItem.post(PostEvent)
     * @triggers touchItem.exception(ExceptionEvent)
     */
    public function touchItem($key)
    {
        $options = $this->getOptions();
        if ($options->getWritable() && $options->getClearStatCache()) {
            clearstatcache();
        }

        return parent::touchItem($key);
    }

    /**
     * Reset lifetime of multiple items.
     *
     * @param  array $keys
     * @return array Array of not updated keys
     * @throws Exception\ExceptionInterface
     *
     * @triggers touchItems.pre(PreEvent)
     * @triggers touchItems.post(PostEvent)
     * @triggers touchItems.exception(ExceptionEvent)
     */
    public function touchItems(array $keys)
    {
        $options = $this->getOptions();
        if ($options->getWritable() && $options->getClearStatCache()) {
            clearstatcache();
        }

        return parent::touchItems($keys);
    }

    /**
     * Internal method to reset lifetime of an item
     *
     * @param  string $normalizedKey
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalTouchItem(& $normalizedKey)
    {
        if (!$this->internalHasItem($normalizedKey)) {
            return false;
        }

        $filespec = $this->getFileSpec($normalizedKey);

        ErrorHandler::start();
        $touch = touch($filespec . '.dat');
        $error = ErrorHandler::stop();
        if (!$touch) {
            throw new Exception\RuntimeException(
                "Error touching file '{$filespec}.dat'", 0, $error
            );
        }

        return true;
    }

    /**
     * Remove an item.
     *
     * @param  string $key
     * @return bool
     * @throws Exception\ExceptionInterface
     *
     * @triggers removeItem.pre(PreEvent)
     * @triggers removeItem.post(PostEvent)
     * @triggers removeItem.exception(ExceptionEvent)
     */
    public function removeItem($key)
    {
        $options = $this->getOptions();
        if ($options->getWritable() && $options->getClearStatCache()) {
            clearstatcache();
        }

        return parent::removeItem($key);
    }

    /**
     * Remove multiple items.
     *
     * @param  array $keys
     * @return array Array of not removed keys
     * @throws Exception\ExceptionInterface
     *
     * @triggers removeItems.pre(PreEvent)
     * @triggers removeItems.post(PostEvent)
     * @triggers removeItems.exception(ExceptionEvent)
     */
    public function removeItems(array $keys)
    {
        $options = $this->getOptions();
        if ($options->getWritable() && $options->getClearStatCache()) {
            clearstatcache();
        }

        return parent::removeItems($keys);
    }

    /**
     * Internal method to remove an item.
     *
     * @param  string $normalizedKey
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalRemoveItem(& $normalizedKey)
    {
        $filespec = $this->getFileSpec($normalizedKey);
        if (!file_exists($filespec . '.dat')) {
            return false;
        } else {
            $this->unlink($filespec . '.dat');
            $this->unlink($filespec . '.tag');
        }
        return true;
    }

    /* status */

    /**
     * Internal method to get capabilities of this adapter
     *
     * @return Capabilities
     */
    protected function internalGetCapabilities()
    {
        if ($this->capabilities === null) {
            $marker  = new stdClass();
            $options = $this->getOptions();

            // detect metadata
            $metadata = array('mtime', 'filespec');
            if (!$options->getNoAtime()) {
                $metadata[] = 'atime';
            }
            if (!$options->getNoCtime()) {
                $metadata[] = 'ctime';
            }

            $capabilities = new Capabilities(
                $this,
                $marker,
                array(
                    'supportedDatatypes' => array(
                        'NULL'     => 'string',
                        'boolean'  => 'string',
                        'integer'  => 'string',
                        'double'   => 'string',
                        'string'   => true,
                        'array'    => false,
                        'object'   => false,
                        'resource' => false,
                    ),
                    'supportedMetadata'  => $metadata,
                    'minTtl'             => 1,
                    'maxTtl'             => 0,
                    'staticTtl'          => false,
                    'ttlPrecision'       => 1,
                    'expiredRead'        => true,
                    'maxKeyLength'       => 251, // 255 - strlen(.dat | .tag)
                    'namespaceIsPrefix'  => true,
                    'namespaceSeparator' => $options->getNamespaceSeparator(),
                )
            );

            // update capabilities on change options
            $this->getEventManager()->attach('option', function ($event) use ($capabilities, $marker) {
                $params = $event->getParams();

                if (isset($params['namespace_separator'])) {
                    $capabilities->setNamespaceSeparator($marker, $params['namespace_separator']);
                }

                if (isset($params['no_atime']) || isset($params['no_ctime'])) {
                    $metadata = $capabilities->getSupportedMetadata();

                    if (isset($params['no_atime']) && !$params['no_atime']) {
                        $metadata[] = 'atime';
                    } elseif (isset($params['no_atime']) && ($index = array_search('atime', $metadata)) !== false) {
                        unset($metadata[$index]);
                    }

                    if (isset($params['no_ctime']) && !$params['no_ctime']) {
                        $metadata[] = 'ctime';
                    } elseif (isset($params['no_ctime']) && ($index = array_search('ctime', $metadata)) !== false) {
                        unset($metadata[$index]);
                    }

                    $capabilities->setSupportedMetadata($marker, $metadata);
                }
            });

            $this->capabilityMarker = $marker;
            $this->capabilities     = $capabilities;
        }

        return $this->capabilities;
    }

    /* internal */

    /**
     * Removes directories recursive by namespace
     *
     * @param  string $dir    Directory to delete
     * @param  string $prefix Namespace + Separator
     * @return bool
     */
    protected function rmDir($dir, $prefix)
    {
        $glob = glob(
            $dir . DIRECTORY_SEPARATOR . $prefix  . '*',
            GLOB_ONLYDIR | GLOB_NOESCAPE | GLOB_NOSORT
        );
        if (!$glob) {
            // On some systems glob returns false even on empty result
            return true;
        }

        $ret = true;
        foreach ($glob as $subdir) {
            // skip removing current directory if removing of sub-directory failed
            if ($this->rmDir($subdir, $prefix)) {
                // ignore not empty directories
                ErrorHandler::start();
                $ret = rmdir($subdir) && $ret;
                ErrorHandler::stop();
            } else {
                $ret = false;
            }
        }

        return $ret;
    }

    /**
     * Get file spec of the given key and namespace
     *
     * @param  string $normalizedKey
     * @return string
     */
    protected function getFileSpec($normalizedKey)
    {
        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        $prefix    = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $path      = $options->getCacheDir() . DIRECTORY_SEPARATOR;
        $level     = $options->getDirLevel();

        $fileSpecId = $path . $prefix . $normalizedKey . '/' . $level;
        if ($this->lastFileSpecId !== $fileSpecId) {
            if ($level > 0) {
                // create up to 256 directories per directory level
                $hash = md5($normalizedKey);
                for ($i = 0, $max = ($level * 2); $i < $max; $i+= 2) {
                    $path .= $prefix . $hash[$i] . $hash[$i+1] . DIRECTORY_SEPARATOR;
                }
            }

            $this->lastFileSpecId = $fileSpecId;
            $this->lastFileSpec   = $path . $prefix . $normalizedKey;
        }

        return $this->lastFileSpec;
    }

    /**
     * Read info file
     *
     * @param  string  $file
     * @param  bool $nonBlocking Don't block script if file is locked
     * @param  bool $wouldblock  The optional argument is set to TRUE if the lock would block
     * @return array|bool The info array or false if file wasn't found
     * @throws Exception\RuntimeException
     */
    protected function readInfoFile($file, $nonBlocking = false, & $wouldblock = null)
    {
        if (!file_exists($file)) {
            return false;
        }

        $content = $this->getFileContent($file, $nonBlocking, $wouldblock);
        if ($nonBlocking && $wouldblock) {
            return false;
        }

        ErrorHandler::start();
        $ifo = unserialize($content);
        $err = ErrorHandler::stop();
        if (!is_array($ifo)) {
            throw new Exception\RuntimeException(
                "Corrupted info file '{$file}'", 0, $err
            );
        }

        return $ifo;
    }

    /**
     * Read a complete file
     *
     * @param  string  $file        File complete path
     * @param  bool $nonBlocking Don't block script if file is locked
     * @param  bool $wouldblock  The optional argument is set to TRUE if the lock would block
     * @return string
     * @throws Exception\RuntimeException
     */
    protected function getFileContent($file, $nonBlocking = false, & $wouldblock = null)
    {
        $locking    = $this->getOptions()->getFileLocking();
        $wouldblock = null;

        ErrorHandler::start();

        // if file locking enabled -> file_get_contents can't be used
        if ($locking) {
            $fp = fopen($file, 'rb');
            if ($fp === false) {
                $err = ErrorHandler::stop();
                throw new Exception\RuntimeException(
                    "Error opening file '{$file}'", 0, $err
                );
            }

            if ($nonBlocking) {
                $lock = flock($fp, LOCK_SH | LOCK_NB, $wouldblock);
                if ($wouldblock) {
                    fclose($fp);
                    ErrorHandler::stop();
                    return;
                }
            } else {
                $lock = flock($fp, LOCK_SH);
            }

            if (!$lock) {
                fclose($fp);
                $err = ErrorHandler::stop();
                throw new Exception\RuntimeException(
                    "Error locking file '{$file}'", 0, $err
                );
            }

            $res = stream_get_contents($fp);
            if ($res === false) {
                flock($fp, LOCK_UN);
                fclose($fp);
                $err = ErrorHandler::stop();
                throw new Exception\RuntimeException(
                    'Error getting stream contents', 0, $err
                );
            }

            flock($fp, LOCK_UN);
            fclose($fp);

        // if file locking disabled -> file_get_contents can be used
        } else {
            $res = file_get_contents($file, false);
            if ($res === false) {
                $err = ErrorHandler::stop();
                throw new Exception\RuntimeException(
                    "Error getting file contents for file '{$file}'", 0, $err
                );
            }
        }

        ErrorHandler::stop();
        return $res;
    }

    /**
     * Prepares a directory structure for the given file(spec)
     * using the configured directory level.
     *
     * @param string $file
     * @return void
     * @throws Exception\RuntimeException
     */
    protected function prepareDirectoryStructure($file)
    {
        $options = $this->getOptions();
        $level   = $options->getDirLevel();

        // Directory structure is required only if directory level > 0
        if (!$level) {
            return;
        }

        // Directory structure already exists
        $pathname = dirname($file);
        if (file_exists($pathname)) {
            return;
        }

        $perm     = $options->getDirPermission();
        $umask    = $options->getUmask();
        if ($umask !== false && $perm !== false) {
            $perm = $perm & ~$umask;
        }

        ErrorHandler::start();

        if ($perm === false || $level == 1) {
            // build-in mkdir function is enough

            $umask = ($umask !== false) ? umask($umask) : false;
            $res   = mkdir($pathname, ($perm !== false) ? $perm : 0777, true);

            if ($umask !== false) {
                umask($umask);
            }

            if (!$res) {
                $oct = ($perm === false) ? '777' : decoct($perm);
                $err = ErrorHandler::stop();
                throw new Exception\RuntimeException(
                    "mkdir('{$pathname}', 0{$oct}, true) failed", 0, $err
                );
            }

            if ($perm !== false && !chmod($pathname, $perm)) {
                $oct = decoct($perm);
                $err = ErrorHandler::stop();
                throw new Exception\RuntimeException(
                    "chmod('{$pathname}', 0{$oct}) failed", 0, $err
                );
            }

        } else {
            // build-in mkdir function sets permission together with current umask
            // which doesn't work well on multo threaded webservers
            // -> create directories one by one and set permissions

            // find existing path and missing path parts
            $parts = array();
            $path  = $pathname;
            while (!file_exists($path)) {
                array_unshift($parts, basename($path));
                $nextPath = dirname($path);
                if ($nextPath === $path) {
                    break;
                }
                $path = $nextPath;
            }

            // make all missing path parts
            foreach ($parts as $part) {
                $path.= DIRECTORY_SEPARATOR . $part;

                // create a single directory, set and reset umask immediately
                $umask = ($umask !== false) ? umask($umask) : false;
                $res   = mkdir($path, ($perm === false) ? 0777 : $perm, false);
                if ($umask !== false) {
                    umask($umask);
                }

                if (!$res) {
                    $oct = ($perm === false) ? '777' : decoct($perm);
                    $err = ErrorHandler::stop();
                    throw new Exception\RuntimeException(
                        "mkdir('{$path}', 0{$oct}, false) failed"
                    );
                }

                if ($perm !== false && !chmod($path, $perm)) {
                    $oct = decoct($perm);
                    $err = ErrorHandler::stop();
                    throw new Exception\RuntimeException(
                        "chmod('{$path}', 0{$oct}) failed"
                    );
                }
            }
        }

        ErrorHandler::stop();
    }

    /**
     * Write content to a file
     *
     * @param  string  $file        File complete path
     * @param  string  $data        Data to write
     * @param  bool $nonBlocking Don't block script if file is locked
     * @param  bool $wouldblock  The optional argument is set to TRUE if the lock would block
     * @return void
     * @throws Exception\RuntimeException
     */
    protected function putFileContent($file, $data, $nonBlocking = false, & $wouldblock = null)
    {
        $options     = $this->getOptions();
        $locking     = $options->getFileLocking();
        $nonBlocking = $locking && $nonBlocking;
        $wouldblock  = null;

        $umask = $options->getUmask();
        $perm  = $options->getFilePermission();
        if ($umask !== false && $perm !== false) {
            $perm = $perm & ~$umask;
        }

        ErrorHandler::start();

        // if locking and non blocking is enabled -> file_put_contents can't used
        if ($locking && $nonBlocking) {

            $umask = ($umask !== false) ? umask($umask) : false;

            $fp = fopen($file, 'cb');

            if ($umask) {
                umask($umask);
            }

            if (!$fp) {
                $err = ErrorHandler::stop();
                throw new Exception\RuntimeException(
                    "Error opening file '{$file}'", 0, $err
                );
            }

            if ($perm !== false && !chmod($file, $perm)) {
                fclose($fp);
                $oct = decoct($perm);
                $err = ErrorHandler::stop();
                throw new Exception\RuntimeException("chmod('{$file}', 0{$oct}) failed", 0, $err);
            }

            if (!flock($fp, LOCK_EX | LOCK_NB, $wouldblock)) {
                fclose($fp);
                $err = ErrorHandler::stop();
                if ($wouldblock) {
                    return;
                } else {
                    throw new Exception\RuntimeException("Error locking file '{$file}'", 0, $err);
                }
            }

            if (fwrite($fp, $data) === false) {
                flock($fp, LOCK_UN);
                fclose($fp);
                $err = ErrorHandler::stop();
                throw new Exception\RuntimeException("Error writing file '{$file}'", 0, $err);
            }

            if (!ftruncate($fp, strlen($data))) {
                flock($fp, LOCK_UN);
                fclose($fp);
                $err = ErrorHandler::stop();
                throw new Exception\RuntimeException("Error truncating file '{$file}'", 0, $err);
            }

            flock($fp, LOCK_UN);
            fclose($fp);

        // else -> file_put_contents can be used
        } else {
            $flags = 0;
            if ($locking) {
                $flags = $flags | LOCK_EX;
            }

            $umask = ($umask !== false) ? umask($umask) : false;

            $rs = file_put_contents($file, $data, $flags);

            if ($umask) {
                umask($umask);
            }

            if ($rs === false) {
                $err = ErrorHandler::stop();
                throw new Exception\RuntimeException(
                    "Error writing file '{$file}'", 0, $err
                );
            }

            if ($perm !== false && !chmod($file, $perm)) {
                $oct = decoct($perm);
                $err = ErrorHandler::stop();
                throw new Exception\RuntimeException("chmod('{$file}', 0{$oct}) failed", 0, $err);
            }
        }

        ErrorHandler::stop();
    }

    /**
     * Unlink a file
     *
     * @param string $file
     * @return void
     * @throws RuntimeException
     */
    protected function unlink($file)
    {
        ErrorHandler::start();
        $res = unlink($file);
        $err = ErrorHandler::stop();

        // only throw exception if file still exists after deleting
        if (!$res && file_exists($file)) {
            throw new Exception\RuntimeException(
                "Error unlinking file '{$file}'; file still exists", 0, $err
            );
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

use stdClass;
use Zend\Cache\Exception;
use Zend\Cache\Storage\Capabilities;

abstract class AbstractZendServer extends AbstractAdapter
{
    /**
     * The namespace separator used on Zend Data Cache functions
     *
     * @var string
     */
    const NAMESPACE_SEPARATOR = '::';

    /* reading */

    /**
     * Internal method to get an item.
     *
     * @param  string  $normalizedKey
     * @param  bool $success
     * @param  mixed   $casToken
     * @return mixed Data on success, null on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null)
    {
        $namespace   = $this->getOptions()->getNamespace();
        $prefix      = ($namespace === '') ? '' : $namespace . self::NAMESPACE_SEPARATOR;

        $result = $this->zdcFetch($prefix . $normalizedKey);
        if ($result === false) {
            $success = false;
            $result  = null;
        } else {
            $success  = true;
            $casToken = $result;
        }

        return $result;
    }

    /**
     * Internal method to get multiple items.
     *
     * @param  array $normalizedKeys
     * @return array Associative array of keys and values
     * @throws Exception\ExceptionInterface
     */
    protected function internalGetItems(array & $normalizedKeys)
    {
        $namespace = $this->getOptions()->getNamespace();
        if ($namespace === '') {
            return $this->zdcFetchMulti($normalizedKeys);
        }

        $prefix       = $namespace . self::NAMESPACE_SEPARATOR;
        $internalKeys = array();
        foreach ($normalizedKeys as $normalizedKey) {
            $internalKeys[] = $prefix . $normalizedKey;
        }

        $fetch   = $this->zdcFetchMulti($internalKeys);
        $result  = array();
        $prefixL = strlen($prefix);
        foreach ($fetch as $k => & $v) {
            $result[substr($k, $prefixL)] = $v;
        }

        return $result;
    }

    /**
     * Internal method to test if an item exists.
     *
     * @param  string $normalizedKey
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalHasItem(& $normalizedKey)
    {
        $namespace = $this->getOptions()->getNamespace();
        $prefix    = ($namespace === '') ? '' : $namespace . self::NAMESPACE_SEPARATOR;
        return  ($this->zdcFetch($prefix . $normalizedKey) !== false);
    }

    /**
     * Internal method to test multiple items.
     *
     * @param  array $normalizedKeys
     * @return array Array of found keys
     * @throws Exception\ExceptionInterface
     */
    protected function internalHasItems(array & $normalizedKeys)
    {
        $namespace = $this->getOptions()->getNamespace();
        if ($namespace === '') {
            return array_keys($this->zdcFetchMulti($normalizedKeys));
        }

        $prefix       = $namespace . self::NAMESPACE_SEPARATOR;
        $internalKeys = array();
        foreach ($normalizedKeys as $normalizedKey) {
            $internalKeys[] = $prefix . $normalizedKey;
        }

        $fetch   = $this->zdcFetchMulti($internalKeys);
        $result  = array();
        $prefixL = strlen($prefix);
        foreach ($fetch as $internalKey => & $value) {
            $result[] = substr($internalKey, $prefixL);
        }

        return $result;
    }

    /**
     * Get metadata for multiple items
     *
     * @param  array $normalizedKeys
     * @return array Associative array of keys and metadata
     *
     * @triggers getMetadatas.pre(PreEvent)
     * @triggers getMetadatas.post(PostEvent)
     * @triggers getMetadatas.exception(ExceptionEvent)
     */
    protected function internalGetMetadatas(array & $normalizedKeys)
    {
        $namespace = $this->getOptions()->getNamespace();
        if ($namespace === '') {
            $result = $this->zdcFetchMulti($normalizedKeys);
            return array_fill_keys(array_keys($result), array());
        }

        $prefix       = $namespace . self::NAMESPACE_SEPARATOR;
        $internalKeys = array();
        foreach ($normalizedKeys as $normalizedKey) {
            $internalKeys[] = $prefix . $normalizedKey;
        }

        $fetch   = $this->zdcFetchMulti($internalKeys);
        $result  = array();
        $prefixL = strlen($prefix);
        foreach ($fetch as $internalKey => $value) {
            $result[substr($internalKey, $prefixL)] = array();
        }

        return $result;
    }

    /* writing */

    /**
     * Internal method to store an item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalSetItem(& $normalizedKey, & $value)
    {
        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        $prefix    = ($namespace === '') ? '' : $namespace . self::NAMESPACE_SEPARATOR;
        $this->zdcStore($prefix . $normalizedKey, $value, $options->getTtl());
        return true;
    }

    /**
     * Internal method to remove an item.
     *
     * @param  string $normalizedKey
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalRemoveItem(& $normalizedKey)
    {
        $namespace = $this->getOptions()->getNamespace();
        $prefix    = ($namespace === '') ? '' : $namespace . self::NAMESPACE_SEPARATOR;
        return $this->zdcDelete($prefix . $normalizedKey);
    }

    /* status */

    /**
     * Internal method to get capabilities of this adapter
     *
     * @return Capabilities
     */
    protected function internalGetCapabilities()
    {
        if ($this->capabilities === null) {
            $this->capabilityMarker = new stdClass();
            $this->capabilities     = new Capabilities(
                $this,
                $this->capabilityMarker,
                array(
                    'supportedDatatypes' => array(
                        'NULL'     => true,
                        'boolean'  => true,
                        'integer'  => true,
                        'double'   => true,
                        'string'   => true,
                        'array'    => true,
                        'object'   => 'object',
                        'resource' => false,
                    ),
                    'supportedMetadata'  => array(),
                    'maxTtl'             => 0,
                    'staticTtl'          => true,
                    'ttlPrecision'       => 1,
                    'useRequestTime'     => false,
                    'expiredRead'        => false,
                    'maxKeyLength'       => 0,
                    'namespaceIsPrefix'  => true,
                    'namespaceSeparator' => self::NAMESPACE_SEPARATOR,
                )
            );
        }

        return $this->capabilities;
    }

    /* internal wrapper of zend_[disk|shm]_cache_* functions */

    /**
     * Store data into Zend Data Cache (zdc)
     *
     * @param  string $internalKey
     * @param  mixed  $value
     * @param  int    $ttl
     * @return void
     * @throws Exception\RuntimeException
     */
    abstract protected function zdcStore($internalKey, $value, $ttl);

    /**
     * Fetch a single item from Zend Data Cache (zdc)
     *
     * @param  string $internalKey
     * @return mixed The stored value or FALSE if item wasn't found
     * @throws Exception\RuntimeException
     */
    abstract protected function zdcFetch($internalKey);

    /**
     * Fetch multiple items from Zend Data Cache (zdc)
     *
     * @param  array $internalKeys
     * @return array All found items
     * @throws Exception\RuntimeException
     */
    abstract protected function zdcFetchMulti(array $internalKeys);

    /**
     * Delete data from Zend Data Cache (zdc)
     *
     * @param  string $internalKey
     * @return bool
     * @throws Exception\RuntimeException
     */
    abstract protected function zdcDelete($internalKey);
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

use Redis as RedisResource;
use RedisException as RedisResourceException;
use ReflectionClass;
use Traversable;
use Zend\Cache\Exception;
use Zend\Stdlib\ArrayUtils;

/**
 * This is a resource manager for redis
 */
class RedisResourceManager
{

    /**
     * Registered resources
     *
     * @var array
     */
    protected $resources = array();

    /**
     * Check if a resource exists
     *
     * @param string $id
     * @return bool
     */
    public function hasResource($id)
    {
        return isset($this->resources[$id]);
    }

    /**
     * Gets a redis resource
     *
     * @param string $id
     * @return RedisResource
     * @throws Exception\RuntimeException
     */
    public function getResource($id)
    {
        if (!$this->hasResource($id)) {
            throw new Exception\RuntimeException("No resource with id '{$id}'");
        }

        $resource = & $this->resources[$id];
        if ($resource['resource'] instanceof RedisResource) {
            //in case new server was set then connect
            if (!$resource['initialized']) {
                $this->connect($resource);
            }
            $info = $resource['resource']->info();
            $resource['version'] = $info['redis_version'];
            return $resource['resource'];
        }

        $redis = new RedisResource();

        $resource['resource'] = $redis;
        $this->connect($resource);

        foreach ($resource['lib_options'] as $k => $v) {
            $redis->setOption($k, $v);
        }

        $info = $redis->info();
        $resource['version'] = $info['redis_version'];
        $this->resources[$id]['resource'] = $redis;
        return $redis;
    }

    /**
     * Connects to redis server
     *
     *
     * @param array & $resource
     *
     * @return null
     * @throws Exception\RuntimeException
     */
    protected function connect(array & $resource)
    {
        $server = $resource['server'];
        $redis  = $resource['resource'];
        if ($resource['persistent_id'] !== '') {
            //connect or reuse persistent connection
            $success = $redis->pconnect($server['host'], $server['port'], $server['timeout'], $server['persistend_id']);
        } elseif ($server['port']) {
            $success = $redis->connect($server['host'], $server['port'], $server['timeout']);
        } elseif ($server['timeout']) {
            //connect through unix domain socket
            $success = $redis->connect($server['host'], $server['timeout']);
        } else {
            $success = $redis->connect($server['host']);
        }

        if (!$success) {
            throw new Exception\RuntimeException('Could not estabilish connection with Redis instance');
        }

        $resource['initialized'] = true;
        if ($resource['password']) {
            $redis->auth($resource['password']);
        }
        $redis->select($resource['database']);
    }

    /**
     * Set a resource
     *
     * @param string $id
     * @param array|Traversable|RedisResource $resource
     * @return RedisResourceManager Fluent interface
     */
    public function setResource($id, $resource)
    {
        $id = (string) $id;
        //TODO: how to get back redis connection info from resource?
        $defaults = array(
            'persistent_id' => '',
            'lib_options'   => array(),
            'server'        => array(),
            'password'      => '',
            'database'      => 0,
            'resource'      => null,
            'initialized'   => false,
            'version'       => 0,
        );
        if (!$resource instanceof RedisResource) {
            if ($resource instanceof Traversable) {
                $resource = ArrayUtils::iteratorToArray($resource);
            } elseif (!is_array($resource)) {
                throw new Exception\InvalidArgumentException(
                    'Resource must be an instance of an array or Traversable'
                );
            }

            $resource = array_merge($defaults, $resource);
            // normalize and validate params
            $this->normalizePersistentId($resource['persistent_id']);
            $this->normalizeLibOptions($resource['lib_options']);
            $this->normalizeServer($resource['server']);
        } else {
            //there are two ways of determining if redis is already initialized
            //with connect function:
            //1) pinging server
            //2) checking undocummented property socket which is available only
            //after successfull connect
            $resource = array_merge($defaults, array(
                    'resource' => $resource,
                    'initialized' => isset($resource->socket),
                )
            );
        }
        $this->resources[$id] = $resource;
        return $this;
    }

    /**
     * Remove a resource
     *
     * @param string $id
     * @return RedisResourceManager Fluent interface
     */
    public function removeResource($id)
    {
        unset($this->resources[$id]);
        return $this;
    }

    /**
     * Set the persistent id
     *
     * @param string $id
     * @param string $persistentId
     * @return RedisResourceManager Fluent interface
     * @throws Exception\RuntimeException
     */
    public function setPersistentId($id, $persistentId)
    {
        if (!$this->hasResource($id)) {
            return $this->setResource($id, array(
                'persistent_id' => $persistentId
            ));
        }

        $resource = & $this->resources[$id];
        if ($resource instanceof RedisResource) {
            throw new Exception\RuntimeException(
                "Can't change persistent id of resource {$id} after instanziation"
            );
        }

        $this->normalizePersistentId($persistentId);
        $resource['persistent_id'] = $persistentId;

        return $this;
    }

    /**
     * Get the persistent id
     *
     * @param string $id
     * @return string
     * @throws Exception\RuntimeException
     */
    public function getPersistentId($id)
    {
        if (!$this->hasResource($id)) {
            throw new Exception\RuntimeException("No resource with id '{$id}'");
        }

        $resource = & $this->resources[$id];

        if ($resource instanceof RedisResource) {
            throw new Exception\RuntimeException(
                "Can't get persistent id of an instantiated redis resource"
            );
        }

        return $resource['persistent_id'];
    }

    /**
     * Normalize the persistent id
     *
     * @param string $persistentId
     */
    protected function normalizePersistentId(& $persistentId)
    {
        $persistentId = (string) $persistentId;
    }

    /**
     * Set Redis options
     *
     * @param string $id
     * @param array  $libOptions
     * @return RedisResourceManager Fluent interface
     */
    public function setLibOptions($id, array $libOptions)
    {
        if (!$this->hasResource($id)) {
            return $this->setResource($id, array(
                'lib_options' => $libOptions
            ));
        }

        $this->normalizeLibOptions($libOptions);
        $resource = & $this->resources[$id];

        $resource['lib_options'] = $libOptions;

        if ($resource['resource'] instanceof RedisResource) {
            $redis = & $resource['resource'];
            if (method_exists($redis, 'setOptions')) {
                $redis->setOptions($libOptions);
            } else {
                foreach ($libOptions as $key => $value) {
                    $redis->setOption($key, $value);
                }
            }
        }

        return $this;
    }

    /**
     * Get Redis options
     *
     * @param string $id
     * @return array
     * @throws Exception\RuntimeException
     */
    public function getLibOptions($id)
    {
        if (!$this->hasResource($id)) {
            throw new Exception\RuntimeException("No resource with id '{$id}'");
        }

        $resource = & $this->resources[$id];

        if ($resource instanceof RedisResource) {
            $libOptions = array();
            $reflection = new ReflectionClass('Redis');
            $constants  = $reflection->getConstants();
            foreach ($constants as $constName => $constValue) {
                if (substr($constName, 0, 4) == 'OPT_') {
                    $libOptions[$constValue] = $resource->getOption($constValue);
                }
            }
            return $libOptions;
        }
        return $resource['lib_options'];
    }

    /**
     * Set one Redis option
     *
     * @param string     $id
     * @param string|int $key
     * @param mixed      $value
     * @return RedisResourceManager Fluent interface
     */
    public function setLibOption($id, $key, $value)
    {
        return $this->setLibOptions($id, array($key => $value));
    }

    /**
     * Get one Redis option
     *
     * @param string     $id
     * @param string|int $key
     * @return mixed
     * @throws Exception\RuntimeException
     */
    public function getLibOption($id, $key)
    {
        if (!$this->hasResource($id)) {
            throw new Exception\RuntimeException("No resource with id '{$id}'");
        }

        $this->normalizeLibOptionKey($key);
        $resource   = & $this->resources[$id];

        if ($resource instanceof RedisResource) {
            return $resource->getOption($key);
        }

        return isset($resource['lib_options'][$key]) ? $resource['lib_options'][$key] : null;
    }

    /**
     * Normalize Redis options
     *
     * @param array|Traversable $libOptions
     * @throws Exception\InvalidArgumentException
     */
    protected function normalizeLibOptions(& $libOptions)
    {
        if (!is_array($libOptions) && !($libOptions instanceof Traversable)) {
            throw new Exception\InvalidArgumentException(
                "Lib-Options must be an array or an instance of Traversable"
            );
        }

        $result = array();
        foreach ($libOptions as $key => $value) {
            $this->normalizeLibOptionKey($key);
            $result[$key] = $value;
        }

        $libOptions = $result;
    }

    /**
     * Convert option name into it's constant value
     *
     * @param string|int $key
     * @throws Exception\InvalidArgumentException
     */
    protected function normalizeLibOptionKey(& $key)
    {
        // convert option name into it's constant value
        if (is_string($key)) {
            $const = 'Redis::OPT_' . str_replace(array(' ', '-'), '_', strtoupper($key));
            if (!defined($const)) {
                throw new Exception\InvalidArgumentException("Unknown redis option '{$key}' ({$const})");
            }
            $key = constant($const);
        } else {
            $key = (int) $key;
        }
    }

    /**
     * Set server
     *
     * Server can be described as follows:
     * - URI:   /path/to/sock.sock
     * - Assoc: array('host' => <host>[, 'port' => <port>[, 'timeout' => <timeout>]])
     * - List:  array(<host>[, <port>, [, <timeout>]])
     *
     * @param string       $id
     * @param string|array $server
     * @return RedisResourceManager
     */
    public function setServer($id, $server)
    {
        if (!$this->hasResource($id)) {
            return $this->setResource($id, array(
                'server' => $server
            ));
        }

        $this->normalizeServer($server);

        $resource = & $this->resources[$id];
        if ($resource['resource'] instanceof RedisResource) {
            $this->setResource($id, array('server' => $server));
        } else {
            $resource['server'] = $server;
        }
        return $this;
    }

    /**
     * Get server
     * @param string $id
     * @throws Exception\RuntimeException
     * @return array array('host' => <host>[, 'port' => <port>[, 'timeout' => <timeout>]])
     */
    public function getServer($id)
    {
        if (!$this->hasResource($id)) {
            throw new Exception\RuntimeException("No resource with id '{$id}'");
        }

        $resource = & $this->resources[$id];
        return $resource['server'];
    }

    /**
     * Set redis password
     *
     * @param string $id
     * @param string $password
     * @return RedisResource
     */
    public function setPassword($id, $password)
    {
        if (!$this->hasResource($id)) {
            return $this->setResource($id, array(
                'password' => $password,
            ));
        }

        $resource = & $this->resources[$id];
        $resource['password']    = $password;
        $resource['initialized'] = false;
        return $this;
    }

    /**
     * Get redis resource password
     *
     * @param string $id
     * @return string
     */
    public function getPassword($id)
    {
        if (!$this->hasResource($id)) {
            throw new Exception\RuntimeException("No resource with id '{$id}'");
        }

        $resource = & $this->resources[$id];
        return $resource['password'];
    }

    /**
     * Set redis database number
     *
     * @param string $id
     * @param int $database
     * @return RedisResource
     */
    public function setDatabase($id, $database)
    {
        if (!$this->hasResource($id)) {
            return $this->setResource($id, array(
                'database' => (int) $database,
            ));
        }

        $resource = & $this->resources[$id];
        $resource['database']    = $database;
        $resource['initialized'] = false;
        return $this;
    }

    /**
     * Get redis resource database
     *
     * @param string $id
     * @return string
     */
    public function getDatabase($id)
    {
        if (!$this->hasResource($id)) {
            throw new Exception\RuntimeException("No resource with id '{$id}'");
        }

        $resource = & $this->resources[$id];
        return $resource['database'];
    }

    /**
     * Get redis server version
     *
     * @deprecated 2.2.2 Use getMajorVersion instead
     *
     * @param string $id
     * @return int
     * @throws Exception\RuntimeException
     */
    public function getMayorVersion($id)
    {
        return $this->getMajorVersion($id);
    }

    /**
     * Get redis server version
     *
     * @param string $id
     * @return int
     * @throws Exception\RuntimeException
     */
    public function getMajorVersion($id)
    {
        if (!$this->hasResource($id)) {
            throw new Exception\RuntimeException("No resource with id '{$id}'");
        }

        $resource = & $this->resources[$id];
        return (int) $resource['version'];
    }

    /**
     * Normalize one server into the following format:
     * array('host' => <host>[, 'port' => <port>[, 'timeout' => <timeout>]])
     *
     * @param string|array $server
     * @throws Exception\InvalidArgumentException
     */
    protected function normalizeServer(& $server)
    {
        $host    = null;
        $port    = null;
        $timeout = 0;
        // convert a single server into an array
        if ($server instanceof Traversable) {
            $server = ArrayUtils::iteratorToArray($server);
        }

        if (is_array($server)) {
            // array(<host>[, <port>[, <timeout>]])
            if (isset($server[0])) {
                $host    = (string) $server[0];
                $port    = isset($server[1]) ? (int) $server[1] : $port;
                $timeout = isset($server[2]) ? (int) $server[2] : $timeout;
            }

            // array('host' => <host>[, 'port' => <port>, ['timeout' => <timeout>]])
            if (!isset($server[0]) && isset($server['host'])) {
                $host    = (string) $server['host'];
                $port    = isset($server['port'])    ? (int) $server['port']    : $port;
                $timeout = isset($server['timeout']) ? (int) $server['timeout'] : $timeout;
            }

        } else {
            // parse server from URI host{:?port}
            $server = trim($server);
            if (!strpos($server, '/') === 0) {
                //non unix domain socket connection
                $server = parse_url($server);
            } else {
                $server = array('host' => $server);
            }
            if (!$server) {
                throw new Exception\InvalidArgumentException("Invalid server given");
            }

            $host    = $server['host'];
            $port    = isset($server['port'])    ? (int) $server['port']    : $port;
            $timeout = isset($server['timeout']) ? (int) $server['timeout'] : $timeout;
        }

        if (!$host) {
            throw new Exception\InvalidArgumentException('Missing required server host');
        }

        $server = array(
            'host'    => $host,
            'port'    => $port,
            'timeout' => $timeout,
        );
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

use Redis as RedisResource;
use RedisException as RedisResourceException;
use stdClass;
use Zend\Cache\Storage\Adapter\AbstractAdapter;
use Zend\Cache\Exception;
use Zend\Cache\Storage\AvailableSpaceCapableInterface;
use Zend\Cache\Storage\Capabilities;
use Zend\Cache\Storage\FlushableInterface;
use Zend\Cache\Storage\TotalSpaceCapableInterface;

class Redis extends AbstractAdapter implements
    FlushableInterface,
    TotalSpaceCapableInterface
{

    /**
     * Has this instance be initialized
     *
     * @var bool
     */
    protected $initialized = false;

    /**
     * The redis resource manager
     *
     * @var null|RedisResourceManager
     */
    protected $resourceManager;

    /**
     * The redis resource id
     *
     * @var null|string
     */
    protected $resourceId;

    /**
     * The namespace prefix
     *
     * @var string
     */
    protected $namespacePrefix = '';

    /**
     * Create new Adapter for redis storage
     *
     * @param null|array|Traversable|RedisOptions $options
     * @see \Zend\Cache\Storage\Adapter\Abstract
     */
    public function __construct($options = null)
    {
        if (!extension_loaded('redis')) {
            throw new Exception\ExtensionNotLoadedException("Redis extension is not loaded");
        }

        parent::__construct($options);

        // reset initialized flag on update option(s)
        $initialized = & $this->initialized;
        $this->getEventManager()->attach('option', function ($event) use (& $initialized) {
            $initialized = false;
        });
    }

    /**
     * Get Redis resource
     *
     * @return RedisResource
     */
    protected function getRedisResource()
    {
        if (!$this->initialized) {
            $options = $this->getOptions();

            // get resource manager and resource id
            $this->resourceManager = $options->getResourceManager();
            $this->resourceId      = $options->getResourceId();

            // init namespace prefix
            $namespace = $options->getNamespace();
            if ($namespace !== '') {
                $this->namespacePrefix = $namespace . $options->getNamespaceSeparator();
            } else {
                $this->namespacePrefix = '';
            }

            // update initialized flag
            $this->initialized = true;
        }

        return $this->resourceManager->getResource($this->resourceId);
    }

    /* options */

    /**
     * Set options.
     *
     * @param  array|Traversable|RedisOptions $options
     * @return Redis
     * @see    getOptions()
     */
    public function setOptions($options)
    {
        if (!$options instanceof RedisOptions) {
            $options = new RedisOptions($options);
        }
        return parent::setOptions($options);
    }

    /**
     * Get options.
     *
     * @return RedisOptions
     * @see setOptions()
     */
    public function getOptions()
    {
        if (!$this->options) {
            $this->setOptions(new RedisOptions());
        }
        return $this->options;
    }

    /**
     * Internal method to get an item.
     *
     * @param string  &$normalizedKey Key where to store data
     * @param bool &$success       If the operation was successfull
     * @param mixed   &$casToken      Token
     * @return mixed Data on success, false on key not found
     * @throws Exception\RuntimeException
     */
    protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null)
    {
        $redis = $this->getRedisResource();
        try {
            $value = $redis->get($this->namespacePrefix . $normalizedKey);
        } catch (RedisResourceException $e) {
            throw new Exception\RuntimeException($redis->getLastError(), $e->getCode(), $e);
        }

        if ($value === false) {
            $success = false;
            return null;
        }

        $success = true;
        $casToken = $value;
        return $value;
    }

     /**
     * Internal method to get multiple items.
     *
     * @param array &$normalizedKeys Array of keys to be obtained
     *
     * @return array Associative array of keys and values
     * @throws Exception\RuntimeException
     */
    protected function internalGetItems(array & $normalizedKeys)
    {
        $redis = $this->getRedisResource();

        $namespacedKeys = array();
        foreach ($normalizedKeys as & $normalizedKey) {
            $namespacedKeys[] = $this->namespacePrefix . $normalizedKey;
        }

        try {
            $results = $redis->mGet($namespacedKeys);
        } catch (RedisResourceException $e) {
            throw new Exception\RuntimeException($redis->getLastError(), $e->getCode(), $e);
        }
        //combine the key => value pairs and remove all missing values
        return array_filter(
            array_combine($normalizedKeys, $results),
            function ($value) {
                return $value !== false;
            }
        );
    }

    /**
     * Internal method to test if an item exists.
     *
     * @param string &$normalizedKey Normalized key which will be checked
     *
     * @return bool
     * @throws Exception\RuntimeException
     */
    protected function internalHasItem(& $normalizedKey)
    {
        $redis = $this->getRedisResource();
        try {
            return $redis->exists($this->namespacePrefix . $normalizedKey);
        } catch (RedisResourceException $e) {
            throw new Exception\RuntimeException($redis->getLastError(), $e->getCode(), $e);
        }
    }

    /**
     * Internal method to store an item.
     *
     * @param string &$normalizedKey Key in Redis under which value will be saved
     * @param mixed  &$value         Value to store under cache key
     *
     * @return bool
     * @throws Exception\RuntimeException
     */
    protected function internalSetItem(& $normalizedKey, & $value)
    {
        $redis = $this->getRedisResource();
        $ttl = $this->getOptions()->getTtl();

        try {
            if ($ttl) {
                if ($this->resourceManager->getMajorVersion($this->resourceId) < 2) {
                    throw new Exception\UnsupportedMethodCallException("To use ttl you need version >= 2.0.0");
                }
                $success = $redis->setex($this->namespacePrefix . $normalizedKey, $ttl, $value);
            } else {
                $success = $redis->set($this->namespacePrefix . $normalizedKey, $value);
            }
        } catch (RedisResourceException $e) {
            throw new Exception\RuntimeException($redis->getLastError(), $e->getCode(), $e);
        }

        return $success;
    }

     /**
     * Internal method to store multiple items.
     *
     * @param array &$normalizedKeyValuePairs An array of normalized key/value pairs
     *
     * @return array Array of not stored keys
     * @throws Exception\RuntimeException
     */
    protected function internalSetItems(array & $normalizedKeyValuePairs)
    {
        $redis = $this->getRedisResource();
        $ttl   = $this->getOptions()->getTtl();

        $namespacedKeyValuePairs = array();
        foreach ($normalizedKeyValuePairs as $normalizedKey => & $value) {
            $namespacedKeyValuePairs[$this->namespacePrefix . $normalizedKey] = & $value;
        }
        try {
            if ($ttl > 0) {
                //check if ttl is supported
                if ($this->resourceManager->getMajorVersion($this->resourceId) < 2) {
                    throw new Exception\UnsupportedMethodCallException("To use ttl you need version >= 2.0.0");
                }
                //mSet does not allow ttl, so use transaction
                $transaction = $redis->multi();
                foreach ($namespacedKeyValuePairs as $key => $value) {
                    $transaction->setex($key, $ttl, $value);
                }
                $success = $transaction->exec();
            } else {
                $success = $redis->mSet($namespacedKeyValuePairs);
            }

        } catch (RedisResourceException $e) {
            throw new Exception\RuntimeException($redis->getLastError(), $e->getCode(), $e);
        }
        if (!$success) {
            throw new Exception\RuntimeException($redis->getLastError());
        }

        return array();
    }

    /**
     * Add an item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\RuntimeException
     */
    protected function internalAddItem(& $normalizedKey, & $value)
    {
        $redis = $this->getRedisResource();
        try {
            return $redis->setnx($this->namespacePrefix . $normalizedKey, $value);
        } catch (RedisResourceException $e) {
            throw new Exception\RuntimeException($redis->getLastError(), $e->getCode(), $e);
        }
    }

    /**
     * Internal method to remove an item.
     *
     * @param string &$normalizedKey Key which will be removed
     *
     * @return bool
     * @throws Exception\RuntimeException
     */
    protected function internalRemoveItem(& $normalizedKey)
    {
        $redis = $this->getRedisResource();
        try {
            return (bool) $redis->delete($this->namespacePrefix . $normalizedKey);
        } catch (RedisResourceException $e) {
            throw new Exception\RuntimeException($redis->getLastError(), $e->getCode(), $e);
        }
    }

    /**
     * Internal method to increment an item.
     *
     * @param  string $normalizedKey
     * @param  int    $value
     * @return int|bool The new value on success, false on failure
     * @throws Exception\RuntimeException
     */
    protected function internalIncrementItem(& $normalizedKey, & $value)
    {
        $redis = $this->getRedisResource();
        try {
            return $redis->incrBy($this->namespacePrefix . $normalizedKey, $value);
        } catch (RedisResourceException $e) {
            throw new Exception\RuntimeException($redis->getLastError(), $e->getCode(), $e);
        }
    }

    /**
     * Internal method to decrement an item.
     *
     * @param  string $normalizedKey
     * @param  int    $value
     * @return int|bool The new value on success, false on failure
     * @throws Exception\RuntimeException
     */
    protected function internalDecrementItem(& $normalizedKey, & $value)
    {
        $redis = $this->getRedisResource();
        try {
            return $redis->decrBy($this->namespacePrefix . $normalizedKey, $value);
        } catch (RedisResourceException $e) {
            throw new Exception\RuntimeException($redis->getLastError(), $e->getCode(), $e);
        }
    }

    /**
     * Flush currently set DB
     *
     * @return bool
     * @throws Exception\RuntimeException
     */
    public function flush()
    {
        $redis = $this->getRedisResource();
        try {
            return $redis->flushDB();
        } catch (RedisResourceException $e) {
            throw new Exception\RuntimeException($redis->getLastError(), $e->getCode(), $e);
        }
    }

    /* TotalSpaceCapableInterface */

    /**
     * Get total space in bytes
     *
     * @return int|float
     */
    public function getTotalSpace()
    {
        $redis  = $this->getRedisResource();
        try {
            $info = $redis->info();
        } catch (RedisResourceException $e) {
            throw new Exception\RuntimeException($redis->getLastError(), $e->getCode(), $e);
        }

        return $info['used_memory'];

    }

    /* status */

    /**
     * Internal method to get capabilities of this adapter
     *
     * @return Capabilities
     */
    protected function internalGetCapabilities()
    {
        if ($this->capabilities === null) {
            $this->capabilityMarker = new stdClass();
            $minTtl = $this->resourceManager->getMajorVersion($this->resourceId) < 2 ? 0 : 1;
            //without serialization redis supports only strings for simple
            //get/set methods
            $this->capabilities     = new Capabilities(
                $this,
                $this->capabilityMarker,
                array(
                    'supportedDatatypes' => array(
                        'NULL'     => 'string',
                        'boolean'  => 'string',
                        'integer'  => 'string',
                        'double'   => 'string',
                        'string'   => true,
                        'array'    => false,
                        'object'   => false,
                        'resource' => false,
                    ),
                    'supportedMetadata'  => array(),
                    'minTtl'             => $minTtl,
                    'maxTtl'             => 0,
                    'staticTtl'          => true,
                    'ttlPrecision'       => 1,
                    'useRequestTime'     => false,
                    'expiredRead'        => false,
                    'maxKeyLength'       => 255,
                    'namespaceIsPrefix'  => true,
                )
            );
        }

        return $this->capabilities;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

use GlobIterator;
use Zend\Cache\Storage\IteratorInterface;

class FilesystemIterator implements IteratorInterface
{

    /**
     * The Filesystem storage instance
     *
     * @var Filesystem
     */
    protected $storage;

    /**
     * The iterator mode
     *
     * @var int
     */
    protected $mode = IteratorInterface::CURRENT_AS_KEY;

    /**
     * The GlobIterator instance
     *
     * @var GlobIterator
     */
    protected $globIterator;

    /**
     * The namespace sprefix
     *
     * @var string
     */
    protected $prefix;

    /**
     * String length of namespace prefix
     *
     * @var int
     */
    protected $prefixLength;

    /**
     * Constructor
     *
     * @param Filesystem  $storage
     * @param string      $path
     * @param string      $prefix
     */
    public function __construct(Filesystem $storage, $path, $prefix)
    {
        $this->storage      = $storage;
        $this->globIterator = new GlobIterator($path, GlobIterator::KEY_AS_FILENAME);
        $this->prefix       = $prefix;
        $this->prefixLength = strlen($prefix);
    }

    /**
     * Get storage instance
     *
     * @return Filesystem
     */
    public function getStorage()
    {
        return $this->storage;
    }

    /**
     * Get iterator mode
     *
     * @return int Value of IteratorInterface::CURRENT_AS_*
     */
    public function getMode()
    {
        return $this->mode;
    }

    /**
     * Set iterator mode
     *
     * @param int $mode
     * @return FilesystemIterator Fluent interface
     */
    public function setMode($mode)
    {
        $this->mode = (int) $mode;
        return $this;
    }

    /* Iterator */

    /**
     * Get current key, value or metadata.
     *
     * @return mixed
     */
    public function current()
    {
        if ($this->mode == IteratorInterface::CURRENT_AS_SELF) {
            return $this;
        }

        $key = $this->key();

        if ($this->mode == IteratorInterface::CURRENT_AS_VALUE) {
            return $this->storage->getItem($key);
        } elseif ($this->mode == IteratorInterface::CURRENT_AS_METADATA) {
            return $this->storage->getMetadata($key);
        }

        return $key;
    }

    /**
     * Get current key
     *
     * @return string
     */
    public function key()
    {
        $filename = $this->globIterator->key();

        // return without namespace prefix and file suffix
        return substr($filename, $this->prefixLength, -4);
    }

    /**
     * Move forward to next element
     *
     * @return void
     */
    public function next()
    {
        $this->globIterator->next();
    }

    /**
     * Checks if current position is valid
     *
     * @return bool
     */
    public function valid()
    {
        try {
            return $this->globIterator->valid();
        } catch (\LogicException $e) {
            // @link https://bugs.php.net/bug.php?id=55701
            // GlobIterator throws LogicException with message
            // 'The parent constructor was not called: the object is in an invalid state'
            return false;
        }
    }

    /**
     * Rewind the Iterator to the first element.
     *
     * @return bool false if the operation failed.
     */
    public function rewind()
    {
        try {
            return $this->globIterator->rewind();
        } catch (\LogicException $e) {
            // @link https://bugs.php.net/bug.php?id=55701
            // GlobIterator throws LogicException with message
            // 'The parent constructor was not called: the object is in an invalid state'
            return false;
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

use Memcached as MemcachedResource;
use ReflectionClass;
use Traversable;
use Zend\Cache\Exception;
use Zend\Stdlib\ArrayUtils;

/**
 * This is a resource manager for memcached
 */
class MemcachedResourceManager
{

    /**
     * Registered resources
     *
     * @var array
     */
    protected $resources = array();

    /**
     * Check if a resource exists
     *
     * @param string $id
     * @return bool
     */
    public function hasResource($id)
    {
        return isset($this->resources[$id]);
    }

    /**
     * Gets a memcached resource
     *
     * @param string $id
     * @return MemcachedResource
     * @throws Exception\RuntimeException
     */
    public function getResource($id)
    {
        if (!$this->hasResource($id)) {
            throw new Exception\RuntimeException("No resource with id '{$id}'");
        }

        $resource = $this->resources[$id];
        if ($resource instanceof MemcachedResource) {
            return $resource;
        }

        if ($resource['persistent_id'] !== '') {
            $memc = new MemcachedResource($resource['persistent_id']);
        } else {
            $memc = new MemcachedResource();
        }

        if (method_exists($memc, 'setOptions')) {
            $memc->setOptions($resource['lib_options']);
        } else {
            foreach ($resource['lib_options'] as $k => $v) {
                $memc->setOption($k, $v);
            }
        }

        // merge and add servers (with persistence id servers could be added already)
        $servers = array_udiff($resource['servers'], $memc->getServerList(), array($this, 'compareServers'));
        if ($servers) {
            $memc->addServers($servers);
        }

        // buffer and return
        $this->resources[$id] = $memc;
        return $memc;
    }

    /**
     * Set a resource
     *
     * @param string $id
     * @param array|Traversable|MemcachedResource $resource
     * @return MemcachedResourceManager Fluent interface
     */
    public function setResource($id, $resource)
    {
        $id = (string) $id;

        if (!($resource instanceof MemcachedResource)) {
            if ($resource instanceof Traversable) {
                $resource = ArrayUtils::iteratorToArray($resource);
            } elseif (!is_array($resource)) {
                throw new Exception\InvalidArgumentException(
                    'Resource must be an instance of Memcached or an array or Traversable'
                );
            }

            $resource = array_merge(array(
                'persistent_id' => '',
                'lib_options'   => array(),
                'servers'       => array(),
            ), $resource);

            // normalize and validate params
            $this->normalizePersistentId($resource['persistent_id']);
            $this->normalizeLibOptions($resource['lib_options']);
            $this->normalizeServers($resource['servers']);
        }

        $this->resources[$id] = $resource;
        return $this;
    }

    /**
     * Remove a resource
     *
     * @param string $id
     * @return MemcachedResourceManager Fluent interface
     */
    public function removeResource($id)
    {
        unset($this->resources[$id]);
        return $this;
    }

    /**
     * Set the persistent id
     *
     * @param string $id
     * @param string $persistentId
     * @return MemcachedResourceManager Fluent interface
     * @throws Exception\RuntimeException
     */
    public function setPersistentId($id, $persistentId)
    {
        if (!$this->hasResource($id)) {
            return $this->setResource($id, array(
                'persistent_id' => $persistentId
            ));
        }

        $resource = & $this->resources[$id];
        if ($resource instanceof MemcachedResource) {
            throw new Exception\RuntimeException(
                "Can't change persistent id of resource {$id} after instanziation"
            );
        }

        $this->normalizePersistentId($persistentId);
        $resource['persistent_id'] = $persistentId;

        return $this;
    }

    /**
     * Get the persistent id
     *
     * @param string $id
     * @return string
     * @throws Exception\RuntimeException
     */
    public function getPersistentId($id)
    {
        if (!$this->hasResource($id)) {
            throw new Exception\RuntimeException("No resource with id '{$id}'");
        }

        $resource = & $this->resources[$id];

        if ($resource instanceof MemcachedResource) {
            throw new Exception\RuntimeException(
                "Can't get persistent id of an instantiated memcached resource"
            );
        }

        return $resource['persistent_id'];
    }

    /**
     * Normalize the persistent id
     *
     * @param string $persistentId
     */
    protected function normalizePersistentId(& $persistentId)
    {
        $persistentId = (string) $persistentId;
    }

    /**
     * Set Libmemcached options
     *
     * @param string $id
     * @param array  $libOptions
     * @return MemcachedResourceManager Fluent interface
     */
    public function setLibOptions($id, array $libOptions)
    {
        if (!$this->hasResource($id)) {
            return $this->setResource($id, array(
                'lib_options' => $libOptions
            ));
        }

        $this->normalizeLibOptions($libOptions);

        $resource = & $this->resources[$id];
        if ($resource instanceof MemcachedResource) {
            if (method_exists($resource, 'setOptions')) {
                $resource->setOptions($libOptions);
            } else {
                foreach ($libOptions as $key => $value) {
                    $resource->setOption($key, $value);
                }
            }
        } else {
            $resource['lib_options'] = $libOptions;
        }

        return $this;
    }

    /**
     * Get Libmemcached options
     *
     * @param string $id
     * @return array
     * @throws Exception\RuntimeException
     */
    public function getLibOptions($id)
    {
        if (!$this->hasResource($id)) {
            throw new Exception\RuntimeException("No resource with id '{$id}'");
        }

        $resource = & $this->resources[$id];

        if ($resource instanceof MemcachedResource) {
            $libOptions = array();
            $reflection = new ReflectionClass('Memcached');
            $constants  = $reflection->getConstants();
            foreach ($constants as $constName => $constValue) {
                if (substr($constName, 0, 4) == 'OPT_') {
                    $libOptions[$constValue] = $resource->getOption($constValue);
                }
            }
            return $libOptions;
        }
        return $resource['lib_options'];
    }

    /**
     * Set one Libmemcached option
     *
     * @param string     $id
     * @param string|int $key
     * @param mixed      $value
     * @return MemcachedResourceManager Fluent interface
     */
    public function setLibOption($id, $key, $value)
    {
        return $this->setLibOptions($id, array($key => $value));
    }

    /**
     * Get one Libmemcached option
     *
     * @param string     $id
     * @param string|int $key
     * @return mixed
     * @throws Exception\RuntimeException
     */
    public function getLibOption($id, $key)
    {
        if (!$this->hasResource($id)) {
            throw new Exception\RuntimeException("No resource with id '{$id}'");
        }

        $this->normalizeLibOptionKey($key);
        $resource   = & $this->resources[$id];

        if ($resource instanceof MemcachedResource) {
            return $resource->getOption($key);
        }

        return isset($resource['lib_options'][$key]) ? $resource['lib_options'][$key] : null;
    }

    /**
     * Normalize libmemcached options
     *
     * @param array|Traversable $libOptions
     * @throws Exception\InvalidArgumentException
     */
    protected function normalizeLibOptions(& $libOptions)
    {
        if (!is_array($libOptions) && !($libOptions instanceof Traversable)) {
            throw new Exception\InvalidArgumentException(
                "Lib-Options must be an array or an instance of Traversable"
            );
        }

        $result = array();
        foreach ($libOptions as $key => $value) {
            $this->normalizeLibOptionKey($key);
            $result[$key] = $value;
        }

        $libOptions = $result;
    }

    /**
     * Convert option name into it's constant value
     *
     * @param string|int $key
     * @throws Exception\InvalidArgumentException
     */
    protected function normalizeLibOptionKey(& $key)
    {
        // convert option name into it's constant value
        if (is_string($key)) {
            $const = 'Memcached::OPT_' . str_replace(array(' ', '-'), '_', strtoupper($key));
            if (!defined($const)) {
                throw new Exception\InvalidArgumentException("Unknown libmemcached option '{$key}' ({$const})");
            }
            $key = constant($const);
        } else {
            $key = (int) $key;
        }
    }

    /**
     * Set servers
     *
     * $servers can be an array list or a comma separated list of servers.
     * One server in the list can be descripted as follows:
     * - URI:   [tcp://]<host>[:<port>][?weight=<weight>]
     * - Assoc: array('host' => <host>[, 'port' => <port>][, 'weight' => <weight>])
     * - List:  array(<host>[, <port>][, <weight>])
     *
     * @param string       $id
     * @param string|array $servers
     * @return MemcachedResourceManager
     */
    public function setServers($id, $servers)
    {
        if (!$this->hasResource($id)) {
            return $this->setResource($id, array(
                'servers' => $servers
            ));
        }

        $this->normalizeServers($servers);

        $resource = & $this->resources[$id];
        if ($resource instanceof MemcachedResource) {
            // don't add servers twice
            $servers = array_udiff($servers, $resource->getServerList(), array($this, 'compareServers'));
            if ($servers) {
                $resource->addServers($servers);
            }
        } else {
            $resource['servers'] = $servers;
        }

        return $this;
    }

    /**
     * Get servers
     * @param string $id
     * @throws Exception\RuntimeException
     * @return array array('host' => <host>, 'port' => <port>, 'weight' => <weight>)
     */
    public function getServers($id)
    {
        if (!$this->hasResource($id)) {
            throw new Exception\RuntimeException("No resource with id '{$id}'");
        }

        $resource = & $this->resources[$id];

        if ($resource instanceof MemcachedResource) {
            return $resource->getServerList();
        }
        return $resource['servers'];
    }

    /**
     * Add servers
     *
     * @param string       $id
     * @param string|array $servers
     * @return MemcachedResourceManager
     */
    public function addServers($id, $servers)
    {
        if (!$this->hasResource($id)) {
            return $this->setResource($id, array(
                'servers' => $servers
            ));
        }

        $this->normalizeServers($servers);

        $resource = & $this->resources[$id];
        if ($resource instanceof MemcachedResource) {
            // don't add servers twice
            $servers = array_udiff($servers, $resource->getServerList(), array($this, 'compareServers'));
            if ($servers) {
                $resource->addServers($servers);
            }
        } else {
            // don't add servers twice
            $resource['servers'] = array_merge(
                $resource['servers'],
                array_udiff($servers, $resource['servers'], array($this, 'compareServers'))
            );
        }

        return $this;
    }

    /**
     * Add one server
     *
     * @param string       $id
     * @param string|array $server
     * @return MemcachedResourceManager
     */
    public function addServer($id, $server)
    {
        return $this->addServers($id, array($server));
    }

    /**
     * Normalize a list of servers into the following format:
     * array(array('host' => <host>, 'port' => <port>, 'weight' => <weight>)[, ...])
     *
     * @param string|array $servers
     */
    protected function normalizeServers(& $servers)
    {
        if (!is_array($servers) && !$servers instanceof Traversable) {
            // Convert string into a list of servers
            $servers = explode(',', $servers);
        }

        $result = array();
        foreach ($servers as $server) {
            $this->normalizeServer($server);
            $result[$server['host'] . ':' . $server['port']] = $server;
        }

        $servers = array_values($result);
    }

    /**
     * Normalize one server into the following format:
     * array('host' => <host>, 'port' => <port>, 'weight' => <weight>)
     *
     * @param string|array $server
     * @throws Exception\InvalidArgumentException
     */
    protected function normalizeServer(& $server)
    {
        $host   = null;
        $port   = 11211;
        $weight = 0;

        // convert a single server into an array
        if ($server instanceof Traversable) {
            $server = ArrayUtils::iteratorToArray($server);
        }

        if (is_array($server)) {
            // array(<host>[, <port>[, <weight>]])
            if (isset($server[0])) {
                $host   = (string) $server[0];
                $port   = isset($server[1]) ? (int) $server[1] : $port;
                $weight = isset($server[2]) ? (int) $server[2] : $weight;
            }

            // array('host' => <host>[, 'port' => <port>[, 'weight' => <weight>]])
            if (!isset($server[0]) && isset($server['host'])) {
                $host   = (string) $server['host'];
                $port   = isset($server['port'])   ? (int) $server['port']   : $port;
                $weight = isset($server['weight']) ? (int) $server['weight'] : $weight;
            }

        } else {
            // parse server from URI host{:?port}{?weight}
            $server = trim($server);
            if (strpos($server, '://') === false) {
                $server = 'tcp://' . $server;
            }

            $server = parse_url($server);
            if (!$server) {
                throw new Exception\InvalidArgumentException("Invalid server given");
            }

            $host = $server['host'];
            $port = isset($server['port']) ? (int) $server['port'] : $port;

            if (isset($server['query'])) {
                $query = null;
                parse_str($server['query'], $query);
                if (isset($query['weight'])) {
                    $weight = (int) $query['weight'];
                }
            }
        }

        if (!$host) {
            throw new Exception\InvalidArgumentException('Missing required server host');
        }

        $server = array(
            'host'   => $host,
            'port'   => $port,
            'weight' => $weight,
        );
    }

    /**
     * Compare 2 normalized server arrays
     * (Compares only the host and the port)
     *
     * @param array $serverA
     * @param array $serverB
     * @return int
     */
    protected function compareServers(array $serverA, array $serverB)
    {
        $keyA = $serverA['host'] . ':' . $serverA['port'];
        $keyB = $serverB['host'] . ':' . $serverB['port'];
        if ($keyA === $keyB) {
            return 0;
        }
        return $keyA > $keyB ? 1 : -1;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

use stdClass;
use Traversable;
use Zend\Cache\Exception;
use Zend\Cache\Storage\AvailableSpaceCapableInterface;
use Zend\Cache\Storage\Capabilities;
use Zend\Cache\Storage\ClearByNamespaceInterface;
use Zend\Cache\Storage\ClearByPrefixInterface;
use Zend\Cache\Storage\FlushableInterface;
use Zend\Cache\Storage\IterableInterface;
use Zend\Cache\Storage\OptimizableInterface;
use Zend\Cache\Storage\TotalSpaceCapableInterface;
use Zend\Stdlib\ErrorHandler;

class Dba extends AbstractAdapter implements
    AvailableSpaceCapableInterface,
    ClearByNamespaceInterface,
    ClearByPrefixInterface,
    FlushableInterface,
    IterableInterface,
    OptimizableInterface,
    TotalSpaceCapableInterface
{
    /**
     * The DBA resource handle
     *
     * @var null|resource
     */
    protected $handle;

    /**
     * Buffered total space in bytes
     *
     * @var null|int|float
     */
    protected $totalSpace;

    /**
     * Constructor
     *
     * @param  null|array|Traversable|DbaOptions $options
     * @throws Exception\ExceptionInterface
     */
    public function __construct($options = null)
    {
        if (!extension_loaded('dba')) {
            throw new Exception\ExtensionNotLoadedException('Missing ext/dba');
        }

        parent::__construct($options);
    }

    /**
     * Destructor
     *
     * Closes an open dba resource
     *
     * @see AbstractAdapter::__destruct()
     * @return void
     */
    public function __destruct()
    {
        $this->_close();

        parent::__destruct();
    }

    /* options */

    /**
     * Set options.
     *
     * @param  array|Traversable|DbaOptions $options
     * @return Apc
     * @see    getOptions()
     */
    public function setOptions($options)
    {
        if (!$options instanceof DbaOptions) {
            $options = new DbaOptions($options);
        }

        return parent::setOptions($options);
    }

    /**
     * Get options.
     *
     * @return DbaOptions
     * @see    setOptions()
     */
    public function getOptions()
    {
        if (!$this->options) {
            $this->setOptions(new DbaOptions());
        }
        return $this->options;
    }

    /* TotalSpaceCapableInterface */

    /**
     * Get total space in bytes
     *
     * @return int|float
     */
    public function getTotalSpace()
    {
        if ($this->totalSpace === null) {
            $pathname = $this->getOptions()->getPathname();

            if ($pathname === '') {
                throw new Exception\LogicException('No pathname to database file');
            }

            ErrorHandler::start();
            $total = disk_total_space(dirname($pathname));
            $error = ErrorHandler::stop();
            if ($total === false) {
                throw new Exception\RuntimeException("Can't detect total space of '{$pathname}'", 0, $error);
            }
            $this->totalSpace = $total;

            // clean total space buffer on change pathname
            $events     = $this->getEventManager();
            $handle     = null;
            $totalSpace = & $this->totalSpace;
            $callback   = function ($event) use (& $events, & $handle, & $totalSpace) {
                $params = $event->getParams();
                if (isset($params['pathname'])) {
                    $totalSpace = null;
                    $events->detach($handle);
                }
            };
            $handle = $events->attach('option', $callback);
        }

        return $this->totalSpace;
    }

    /* AvailableSpaceCapableInterface */

    /**
     * Get available space in bytes
     *
     * @return int|float
     */
    public function getAvailableSpace()
    {
        $pathname = $this->getOptions()->getPathname();

        if ($pathname === '') {
            throw new Exception\LogicException('No pathname to database file');
        }

        ErrorHandler::start();
        $avail = disk_free_space(dirname($pathname));
        $error = ErrorHandler::stop();
        if ($avail === false) {
            throw new Exception\RuntimeException("Can't detect free space of '{$pathname}'", 0, $error);
        }

        return $avail;
    }

    /* FlushableInterface */

    /**
     * Flush the whole storage
     *
     * @return bool
     */
    public function flush()
    {
        $pathname = $this->getOptions()->getPathname();

        if ($pathname === '') {
            throw new Exception\LogicException('No pathname to database file');
        }

        if (file_exists($pathname)) {

            // close the dba file before delete
            // and reopen (create) on next use
            $this->_close();

            ErrorHandler::start();
            $result = unlink($pathname);
            $error  = ErrorHandler::stop();
            if (!$result) {
                throw new Exception\RuntimeException("unlink('{$pathname}') failed", 0, $error);
            }
        }

        return true;
    }

    /* ClearByNamespaceInterface */

    /**
     * Remove items by given namespace
     *
     * @param string $namespace
     * @return bool
     */
    public function clearByNamespace($namespace)
    {
        $namespace = (string) $namespace;
        if ($namespace === '') {
            throw new Exception\InvalidArgumentException('No namespace given');
        }

        $prefix  = $namespace . $this->getOptions()->getNamespaceSeparator();
        $prefixl = strlen($prefix);
        $result  = true;

        $this->_open();

        do { // Workaround for PHP-Bug #62491 & #62492
            $recheck     = false;
            $internalKey = dba_firstkey($this->handle);
            while ($internalKey !== false && $internalKey !== null) {
                if (substr($internalKey, 0, $prefixl) === $prefix) {
                    $result = dba_delete($internalKey, $this->handle) && $result;
                }

                $internalKey = dba_nextkey($this->handle);
            }
        } while ($recheck);

        return $result;
    }

    /* ClearByPrefixInterface */

    /**
     * Remove items matching given prefix
     *
     * @param string $prefix
     * @return bool
     */
    public function clearByPrefix($prefix)
    {
        $prefix = (string) $prefix;
        if ($prefix === '') {
            throw new Exception\InvalidArgumentException('No prefix given');
        }

        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        $prefix    = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator() . $prefix;
        $prefixL   = strlen($prefix);
        $result    = true;

        $this->_open();

        do { // Workaround for PHP-Bug #62491 & #62492
            $recheck     = false;
            $internalKey = dba_firstkey($this->handle);
            while ($internalKey !== false && $internalKey !== null) {
                if (substr($internalKey, 0, $prefixL) === $prefix) {
                    $result = dba_delete($internalKey, $this->handle) && $result;
                    $recheck = true;
                }

                $internalKey = dba_nextkey($this->handle);
            }
        } while ($recheck);

        return $result;
    }

    /* IterableInterface */

    /**
     * Get the storage iterator
     *
     * @return ApcIterator
     */
    public function getIterator()
    {
        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        $prefix    = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();

        return new DbaIterator($this, $this->handle, $prefix);
    }

    /* OptimizableInterface */

    /**
     * Optimize the storage
     *
     * @return bool
     * @return Exception\RuntimeException
     */
    public function optimize()
    {
        $this->_open();
        if (!dba_optimize($this->handle)) {
            throw new Exception\RuntimeException('dba_optimize failed');
        }
        return true;
    }

    /* reading */

    /**
     * Internal method to get an item.
     *
     * @param  string  $normalizedKey
     * @param  bool $success
     * @param  mixed   $casToken
     * @return mixed Data on success, null on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null)
    {
        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        $prefix    = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();

        $this->_open();
        $value = dba_fetch($prefix . $normalizedKey, $this->handle);

        if ($value === false) {
            $success = false;
            return null;
        }

        $success = true;
        $casToken = $value;
        return $value;
    }

    /**
     * Internal method to test if an item exists.
     *
     * @param  string $normalizedKey
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalHasItem(& $normalizedKey)
    {
        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        $prefix    = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();

        $this->_open();
        return dba_exists($prefix . $normalizedKey, $this->handle);
    }

    /* writing */

    /**
     * Internal method to store an item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalSetItem(& $normalizedKey, & $value)
    {
        $options     = $this->getOptions();
        $namespace   = $options->getNamespace();
        $prefix      = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $internalKey = $prefix . $normalizedKey;

        $this->_open();
        if (!dba_replace($internalKey, $value, $this->handle)) {
            throw new Exception\RuntimeException("dba_replace('{$internalKey}', ...) failed");
        }

        return true;
    }

    /**
     * Add an item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalAddItem(& $normalizedKey, & $value)
    {
        $options     = $this->getOptions();
        $namespace   = $options->getNamespace();
        $prefix      = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $internalKey = $prefix . $normalizedKey;

        $this->_open();

        // Workaround for PHP-Bug #54242 & #62489
        if (dba_exists($internalKey, $this->handle)) {
            return false;
        }

        // Workaround for PHP-Bug #54242 & #62489
        // dba_insert returns true if key already exists
        ErrorHandler::start();
        $result = dba_insert($internalKey, $value, $this->handle);
        $error  = ErrorHandler::stop();
        if (!$result || $error) {
            return false;
        }

        return true;
    }

    /**
     * Internal method to remove an item.
     *
     * @param  string $normalizedKey
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalRemoveItem(& $normalizedKey)
    {
        $options     = $this->getOptions();
        $namespace   = $options->getNamespace();
        $prefix      = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $internalKey = $prefix . $normalizedKey;

        $this->_open();

        // Workaround for PHP-Bug #62490
        if (!dba_exists($internalKey, $this->handle)) {
            return false;
        }

        return dba_delete($internalKey, $this->handle);
    }

    /* status */

    /**
     * Internal method to get capabilities of this adapter
     *
     * @return Capabilities
     */
    protected function internalGetCapabilities()
    {
        if ($this->capabilities === null) {
            $marker       = new stdClass();
            $capabilities = new Capabilities(
                $this,
                $marker,
                array(
                    'supportedDatatypes' => array(
                        'NULL'     => 'string',
                        'boolean'  => 'string',
                        'integer'  => 'string',
                        'double'   => 'string',
                        'string'   => true,
                        'array'    => false,
                        'object'   => false,
                        'resource' => false,
                    ),
                    'minTtl'             => 0,
                    'supportedMetadata'  => array(),
                    'maxKeyLength'       => 0, // TODO: maxKeyLength ????
                    'namespaceIsPrefix'  => true,
                    'namespaceSeparator' => $this->getOptions()->getNamespaceSeparator(),
                )
            );

            // update namespace separator on change option
            $this->getEventManager()->attach('option', function ($event) use ($capabilities, $marker) {
                $params = $event->getParams();

                if (isset($params['namespace_separator'])) {
                    $capabilities->setNamespaceSeparator($marker, $params['namespace_separator']);
                }
            });

            $this->capabilities     = $capabilities;
            $this->capabilityMarker = $marker;
        }

        return $this->capabilities;
    }

    /**
     * Open the database if not already done.
     *
     * @return void
     * @throws Exception\LogicException
     * @throws Exception\RuntimeException
     */
    protected function _open()
    {
        if (!$this->handle) {
            $options = $this->getOptions();
            $pathname = $options->getPathname();
            $mode     = $options->getMode();
            $handler  = $options->getHandler();

            if ($pathname === '') {
                throw new Exception\LogicException('No pathname to database file');
            }

            ErrorHandler::start();
            $dba =  dba_open($pathname, $mode, $handler);
            $err = ErrorHandler::stop();
            if (!$dba) {
                throw new Exception\RuntimeException(
                    "dba_open('{$pathname}', '{$mode}', '{$handler}') failed", 0, $err
                );
            }
            $this->handle = $dba;
        }
    }

    /**
     * Close database file if opened
     *
     * @return void
     */
    protected function _close()
    {
        if ($this->handle) {
            ErrorHandler::start(E_NOTICE);
            dba_close($this->handle);
            ErrorHandler::stop();
            $this->handle = null;
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

use Zend\Cache\Exception;
use Zend\Session\Container as SessionContainer;

/**
 * These are options specific to the APC adapter
 */
class SessionOptions extends AdapterOptions
{
    /**
     * The session container
     *
     * @var null|SessionContainer
     */
    protected $sessionContainer = null;

    /**
     * Set the session container
     *
     * @param  null|SessionContainer $sessionContainer
     * @return SessionOptions
     */
    public function setSessionContainer(SessionContainer $sessionContainer = null)
    {
        if ($this->sessionContainer != $sessionContainer) {
            $this->triggerOptionEvent('session_container', $sessionContainer);
            $this->sessionContainer = $sessionContainer;
        }

        return $this;
    }

    /**
     * Get the session container
     *
     * @return null|SessionContainer
     */
    public function getSessionContainer()
    {
        return $this->sessionContainer;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

use Zend\Cache\Exception;
use Zend\Cache\Storage\ClearByNamespaceInterface;
use Zend\Cache\Storage\FlushableInterface;
use Zend\Cache\Storage\TotalSpaceCapableInterface;

class ZendServerShm extends AbstractZendServer implements
    ClearByNamespaceInterface,
    FlushableInterface,
    TotalSpaceCapableInterface
{

    /**
     * Constructor
     *
     * @param  null|array|\Traversable|AdapterOptions $options
     * @throws Exception\ExtensionNotLoadedException
     */
    public function __construct($options = array())
    {
        if (!function_exists('zend_shm_cache_store')) {
            throw new Exception\ExtensionNotLoadedException("Missing 'zend_shm_cache_*' functions");
        } elseif (PHP_SAPI == 'cli') {
            throw new Exception\ExtensionNotLoadedException("Zend server data cache isn't available on cli");
        }

        parent::__construct($options);
    }

    /* FlushableInterface */

    /**
     * Flush the whole storage
     *
     * @return bool
     */
    public function flush()
    {
        return zend_shm_cache_clear();
    }

    /* ClearByNamespaceInterface */

    /**
     * Remove items of given namespace
     *
     * @param string $namespace
     * @return bool
     */
    public function clearByNamespace($namespace)
    {
        $namespace = (string) $namespace;
        if ($namespace === '') {
            throw new Exception\InvalidArgumentException('No namespace given');
        }

        return zend_shm_cache_clear($namespace);
    }

    /* TotalSpaceCapableInterface */

    /**
     * Get total space in bytes
     *
     * @return int|float
     */
    public function getTotalSpace()
    {
        return (int) ini_get('zend_datacache.shm.memory_cache_size') * 1048576;
    }

    /* internal */

    /**
     * Store data into Zend Data SHM Cache
     *
     * @param  string $internalKey
     * @param  mixed  $value
     * @param  int    $ttl
     * @return void
     * @throws Exception\RuntimeException
     */
    protected function zdcStore($internalKey, $value, $ttl)
    {
        if (!zend_shm_cache_store($internalKey, $value, $ttl)) {
            $valueType = gettype($value);
            throw new Exception\RuntimeException(
                "zend_shm_cache_store($internalKey, <{$valueType}>, {$ttl}) failed"
            );
        }
    }

    /**
     * Fetch a single item from Zend Data SHM Cache
     *
     * @param  string $internalKey
     * @return mixed The stored value or FALSE if item wasn't found
     * @throws Exception\RuntimeException
     */
    protected function zdcFetch($internalKey)
    {
        return zend_shm_cache_fetch((string) $internalKey);
    }

    /**
     * Fetch multiple items from Zend Data SHM Cache
     *
     * @param  array $internalKeys
     * @return array All found items
     * @throws Exception\RuntimeException
     */
    protected function zdcFetchMulti(array $internalKeys)
    {
        $items = zend_shm_cache_fetch($internalKeys);
        if ($items === false) {
            throw new Exception\RuntimeException("zend_shm_cache_fetch(<array>) failed");
        }
        return $items;
    }

    /**
     * Delete data from Zend Data SHM Cache
     *
     * @param  string $internalKey
     * @return bool
     * @throws Exception\RuntimeException
     */
    protected function zdcDelete($internalKey)
    {
        return zend_shm_cache_delete($internalKey);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

use stdClass;
use Traversable;
use Zend\Cache\Exception;
use Zend\Cache\Storage\AvailableSpaceCapableInterface;
use Zend\Cache\Storage\Capabilities;
use Zend\Cache\Storage\ClearByNamespaceInterface;
use Zend\Cache\Storage\ClearByPrefixInterface;
use Zend\Cache\Storage\FlushableInterface;
use Zend\Cache\Storage\IterableInterface;
use Zend\Cache\Storage\TotalSpaceCapableInterface;

class XCache extends AbstractAdapter implements
    AvailableSpaceCapableInterface,
    ClearByNamespaceInterface,
    ClearByPrefixInterface,
    FlushableInterface,
    IterableInterface,
    TotalSpaceCapableInterface
{

    /**
     * Backup HTTP authentication properties of $_SERVER array
     *
     * @var array
     */
    protected $backupAuth = array();

    /**
     * Total space in bytes
     *
     * @var int|float
     */
    protected $totalSpace;

    /**
     * Constructor
     *
     * @param  null|array|Traversable|ApcOptions $options
     * @throws Exception\ExceptionInterface
     */
    public function __construct($options = null)
    {
        if (!extension_loaded('xcache')) {
            throw new Exception\ExtensionNotLoadedException('Missing ext/xcache');
        }

        if (PHP_SAPI == 'cli') {
            throw new Exception\ExtensionNotLoadedException(
                "ext/xcache isn't available on SAPI 'cli'"
            );
        }

        if (ini_get('xcache.var_size') <= 0) {
            throw new Exception\ExtensionNotLoadedException(
                "ext/xcache is disabled - see 'xcache.var_size'"
            );
        }

        parent::__construct($options);
    }

    /* options */

    /**
     * Set options.
     *
     * @param  array|Traversable|ApcOptions $options
     * @return XCache
     * @see    getOptions()
     */
    public function setOptions($options)
    {
        if (!$options instanceof XCacheOptions) {
            $options = new XCacheOptions($options);
        }

        return parent::setOptions($options);
    }

    /**
     * Get options.
     *
     * @return XCacheOptions
     * @see    setOptions()
     */
    public function getOptions()
    {
        if (!$this->options) {
            $this->setOptions(new XCacheOptions());
        }
        return $this->options;
    }

    /* TotalSpaceCapableInterface */

    /**
     * Get total space in bytes
     *
     * @return int|float
     */
    public function getTotalSpace()
    {
        if ($this->totalSpace === null) {
            $this->totalSpace = 0;

            $this->initAdminAuth();
            $cnt = xcache_count(XC_TYPE_VAR);
            for ($i=0; $i < $cnt; $i++) {
                $info = xcache_info(XC_TYPE_VAR, $i);
                $this->totalSpace+= $info['size'];
            }
            $this->resetAdminAuth();
        }

        return $this->totalSpace;
    }

    /* AvailableSpaceCapableInterface */

    /**
     * Get available space in bytes
     *
     * @return int|float
     */
    public function getAvailableSpace()
    {
        $availableSpace = 0;

        $this->initAdminAuth();
        $cnt = xcache_count(XC_TYPE_VAR);
        for ($i = 0; $i < $cnt; $i++) {
            $info = xcache_info(XC_TYPE_VAR, $i);
            $availableSpace+= $info['avail'];
        }
        $this->resetAdminAuth();

        return $availableSpace;
    }


    /* ClearByNamespaceInterface */

    /**
     * Remove items by given namespace
     *
     * @param string $namespace
     * @return bool
     */
    public function clearByNamespace($namespace)
    {
        $namespace = (string) $namespace;
        if ($namespace === '') {
            throw new Exception\InvalidArgumentException('No namespace given');
        }

        $options = $this->getOptions();
        $prefix  = $namespace . $options->getNamespaceSeparator();

        xcache_unset_by_prefix($prefix);
        return true;
    }

    /* ClearByPrefixInterface */

    /**
     * Remove items matching given prefix
     *
     * @param string $prefix
     * @return bool
     */
    public function clearByPrefix($prefix)
    {
        $prefix = (string) $prefix;
        if ($prefix === '') {
            throw new Exception\InvalidArgumentException('No prefix given');
        }

        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        $prefix    = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator() . $prefix;

        xcache_unset_by_prefix($prefix);
        return true;
    }

    /* FlushableInterface */

    /**
     * Flush the whole storage
     *
     * @return bool
     */
    public function flush()
    {
        $this->initAdminAuth();
        $cnt = xcache_count(XC_TYPE_VAR);
        for ($i = 0; $i < $cnt; $i++) {
            xcache_clear_cache(XC_TYPE_VAR, $i);
        }
        $this->resetAdminAuth();

        return true;
    }

    /* IterableInterface */

    /**
     * Get the storage iterator
     *
     * @return KeyListIterator
     */
    public function getIterator()
    {

        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        $keys      = array();

        $this->initAdminAuth();

        if ($namespace === '') {
            $cnt = xcache_count(XC_TYPE_VAR);
            for ($i=0; $i < $cnt; $i++) {
                $list = xcache_list(XC_TYPE_VAR, $i);
                foreach ($list['cache_list'] as & $item) {
                    $keys[] = $item['name'];
                }
            }
        } else {

            $prefix  = $namespace . $options->getNamespaceSeparator();
            $prefixL = strlen($prefix);

            $cnt = xcache_count(XC_TYPE_VAR);
            for ($i=0; $i < $cnt; $i++) {
                $list = xcache_list(XC_TYPE_VAR, $i);
                foreach ($list['cache_list'] as & $item) {
                    $keys[] = substr($item['name'], $prefixL);
                }
            }
        }

        $this->resetAdminAuth();

        return new KeyListIterator($this, $keys);
    }

    /* reading */

    /**
     * Internal method to get an item.
     *
     * @param  string  $normalizedKey
     * @param  bool $success
     * @param  mixed   $casToken
     * @return mixed Data on success, null on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null)
    {
        $options     = $this->getOptions();
        $namespace   = $options->getNamespace();
        $prefix      = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $internalKey = $prefix . $normalizedKey;

        $result  = xcache_get($internalKey);
        $success = ($result !== null);

        if ($success) {
            $casToken = $result;
        }

        return $result;
    }

    /**
     * Internal method to test if an item exists.
     *
     * @param  string $normalizedKey
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalHasItem(& $normalizedKey)
    {
        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        $prefix    = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        return xcache_isset($prefix . $normalizedKey);
    }

    /**
     * Get metadata of an item.
     *
     * @param  string $normalizedKey
     * @return array|bool Metadata on success, false on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalGetMetadata(& $normalizedKey)
    {
        $options     = $this->getOptions();
        $namespace   = $options->getNamespace();
        $prefix      = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $internalKey = $prefix . $normalizedKey;

        if (xcache_isset($internalKey)) {

            $this->initAdminAuth();
            $cnt = xcache_count(XC_TYPE_VAR);
            for ($i=0; $i < $cnt; $i++) {
                $list = xcache_list(XC_TYPE_VAR, $i);
                foreach ($list['cache_list'] as & $metadata) {
                    if ($metadata['name'] === $internalKey) {
                        $this->normalizeMetadata($metadata);
                        return $metadata;
                    }
                }
            }
            $this->resetAdminAuth();
        }

        return false;
    }

    /* writing */

    /**
     * Internal method to store an item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalSetItem(& $normalizedKey, & $value)
    {
        $options     = $this->getOptions();
        $namespace   = $options->getNamespace();
        $prefix      = ($options === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $internalKey = $prefix . $normalizedKey;
        $ttl         = $options->getTtl();

        if (!xcache_set($internalKey, $value, $ttl)) {
            $type = is_object($value) ? get_class($value) : gettype($value);
            throw new Exception\RuntimeException(
                "xcache_set('{$internalKey}', <{$type}>, {$ttl}) failed"
            );
        }

        return true;
    }

    /**
     * Internal method to remove an item.
     *
     * @param  string $normalizedKey
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalRemoveItem(& $normalizedKey)
    {
        $options     = $this->getOptions();
        $namespace   = $options->getNamespace();
        $prefix      = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $internalKey = $prefix . $normalizedKey;

        return xcache_unset($internalKey);
    }

    /**
     * Internal method to increment an item.
     *
     * @param  string $normalizedKey
     * @param  int    $value
     * @return int|bool The new value on success, false on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalIncrementItem(& $normalizedKey, & $value)
    {
        $options     = $this->getOptions();
        $namespace   = $options->getNamespace();
        $prefix      = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $internalKey = $prefix . $normalizedKey;
        $ttl         = $options->getTtl();
        $value       = (int) $value;

        return xcache_inc($internalKey, $value, $ttl);
    }

    /**
     * Internal method to decrement an item.
     *
     * @param  string $normalizedKey
     * @param  int    $value
     * @return int|bool The new value on success, false on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalDecrementItem(& $normalizedKey, & $value)
    {
        $options     = $this->getOptions();
        $namespace   = $options->getNamespace();
        $prefix      = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $internalKey = $prefix . $normalizedKey;
        $ttl         = $options->getTtl();
        $value       = (int) $value;

        return xcache_dec($internalKey, $value, $ttl);
    }

    /* status */

    /**
     * Internal method to get capabilities of this adapter
     *
     * @return Capabilities
     */
    protected function internalGetCapabilities()
    {
        if ($this->capabilities === null) {
            $marker       = new stdClass();
            $capabilities = new Capabilities(
                $this,
                $marker,
                array(
                    'supportedDatatypes' => array(
                        'NULL'     => false,
                        'boolean'  => true,
                        'integer'  => true,
                        'double'   => true,
                        'string'   => true,
                        'array'    => true,
                        'object'   => 'object',
                        'resource' => false,
                    ),
                    'supportedMetadata' => array(
                        'internal_key',
                        'size', 'refcount', 'hits',
                        'ctime', 'atime', 'hvalue',
                    ),
                    'minTtl'             => 1,
                    'maxTtl'             => (int)ini_get('xcache.var_maxttl'),
                    'staticTtl'          => true,
                    'ttlPrecision'       => 1,
                    'useRequestTime'     => true,
                    'expiredRead'        => false,
                    'maxKeyLength'       => 5182,
                    'namespaceIsPrefix'  => true,
                    'namespaceSeparator' => $this->getOptions()->getNamespaceSeparator(),
                )
            );

            // update namespace separator on change option
            $this->getEventManager()->attach('option', function ($event) use ($capabilities, $marker) {
                $params = $event->getParams();

                if (isset($params['namespace_separator'])) {
                    $capabilities->setNamespaceSeparator($marker, $params['namespace_separator']);
                }
            });

            $this->capabilities     = $capabilities;
            $this->capabilityMarker = $marker;
        }

        return $this->capabilities;
    }

    /* internal */

    /**
     * Init authentication before calling admin functions
     *
     * @return void
     */
    protected function initAdminAuth()
    {
        $options = $this->getOptions();

        if ($options->getAdminAuth()) {
            $adminUser = $options->getAdminUser();
            $adminPass = $options->getAdminPass();

            // backup HTTP authentication properties
            if (isset($_SERVER['PHP_AUTH_USER'])) {
                $this->backupAuth['PHP_AUTH_USER'] = $_SERVER['PHP_AUTH_USER'];
            }
            if (isset($_SERVER['PHP_AUTH_PW'])) {
                $this->backupAuth['PHP_AUTH_PW'] = $_SERVER['PHP_AUTH_PW'];
            }

            // set authentication
            $_SERVER['PHP_AUTH_USER'] = $adminUser;
            $_SERVER['PHP_AUTH_PW']   = $adminPass;
        }
    }

    /**
     * Reset authentication after calling admin functions
     *
     * @return void
     */
    protected function resetAdminAuth()
    {
        unset($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']);
        $_SERVER = $this->backupAuth + $_SERVER;
        $this->backupAuth = array();
    }

    /**
     * Normalize metadata to work with XCache
     *
     * @param  array $metadata
     */
    protected function normalizeMetadata(array & $metadata)
    {
        $metadata['internal_key'] = &$metadata['name'];
        unset($metadata['name']);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

use Memcached as MemcachedResource;
use stdClass;
use Traversable;
use Zend\Cache\Exception;
use Zend\Cache\Storage\AvailableSpaceCapableInterface;
use Zend\Cache\Storage\Capabilities;
use Zend\Cache\Storage\FlushableInterface;
use Zend\Cache\Storage\TotalSpaceCapableInterface;

class Memcached extends AbstractAdapter implements
    AvailableSpaceCapableInterface,
    FlushableInterface,
    TotalSpaceCapableInterface
{
    /**
     * Major version of ext/memcached
     *
     * @var null|int
     */
    protected static $extMemcachedMajorVersion;

    /**
     * Has this instance be initialized
     *
     * @var bool
     */
    protected $initialized = false;

    /**
     * The memcached resource manager
     *
     * @var null|MemcachedResourceManager
     */
    protected $resourceManager;

    /**
     * The memcached resource id
     *
     * @var null|string
     */
    protected $resourceId;

    /**
     * The namespace prefix
     *
     * @var string
     */
    protected $namespacePrefix = '';

    /**
     * Constructor
     *
     * @param  null|array|Traversable|MemcachedOptions $options
     * @throws Exception\ExceptionInterface
     */
    public function __construct($options = null)
    {
        if (static::$extMemcachedMajorVersion === null) {
            $v = (string) phpversion('memcached');
            static::$extMemcachedMajorVersion = ($v !== '') ? (int) $v[0] : 0;
        }

        if (static::$extMemcachedMajorVersion < 1) {
            throw new Exception\ExtensionNotLoadedException('Need ext/memcached version >= 1.0.0');
        }

        parent::__construct($options);

        // reset initialized flag on update option(s)
        $initialized = & $this->initialized;
        $this->getEventManager()->attach('option', function ($event) use (& $initialized) {
            $initialized = false;
        });
    }

    /**
     * Initialize the internal memcached resource
     *
     * @return MemcachedResource
     */
    protected function getMemcachedResource()
    {
        if (!$this->initialized) {
            $options = $this->getOptions();

            // get resource manager and resource id
            $this->resourceManager = $options->getResourceManager();
            $this->resourceId      = $options->getResourceId();

            // init namespace prefix
            $namespace = $options->getNamespace();
            if ($namespace !== '') {
                $this->namespacePrefix = $namespace . $options->getNamespaceSeparator();
            } else {
                $this->namespacePrefix = '';
            }

            // update initialized flag
            $this->initialized = true;
        }

        return $this->resourceManager->getResource($this->resourceId);
    }

    /* options */

    /**
     * Set options.
     *
     * @param  array|Traversable|MemcachedOptions $options
     * @return Memcached
     * @see    getOptions()
     */
    public function setOptions($options)
    {
        if (!$options instanceof MemcachedOptions) {
            $options = new MemcachedOptions($options);
        }

        return parent::setOptions($options);
    }

    /**
     * Get options.
     *
     * @return MemcachedOptions
     * @see setOptions()
     */
    public function getOptions()
    {
        if (!$this->options) {
            $this->setOptions(new MemcachedOptions());
        }
        return $this->options;
    }

    /* FlushableInterface */

    /**
     * Flush the whole storage
     *
     * @return bool
     */
    public function flush()
    {
        $memc = $this->getMemcachedResource();
        if (!$memc->flush()) {
            throw $this->getExceptionByResultCode($memc->getResultCode());
        }
        return true;
    }

    /* TotalSpaceCapableInterface */

    /**
     * Get total space in bytes
     *
     * @return int|float
     */
    public function getTotalSpace()
    {
        $memc  = $this->getMemcachedResource();
        $stats = $memc->getStats();
        if ($stats === false) {
            throw new Exception\RuntimeException($memc->getResultMessage());
        }

        $mem = array_pop($stats);
        return $mem['limit_maxbytes'];
    }

    /* AvailableSpaceCapableInterface */

    /**
     * Get available space in bytes
     *
     * @return int|float
     */
    public function getAvailableSpace()
    {
        $memc  = $this->getMemcachedResource();
        $stats = $memc->getStats();
        if ($stats === false) {
            throw new Exception\RuntimeException($memc->getResultMessage());
        }

        $mem = array_pop($stats);
        return $mem['limit_maxbytes'] - $mem['bytes'];
    }

    /* reading */

    /**
     * Internal method to get an item.
     *
     * @param  string  $normalizedKey
     * @param  bool $success
     * @param  mixed   $casToken
     * @return mixed Data on success, null on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null)
    {
        $memc        = $this->getMemcachedResource();
        $internalKey = $this->namespacePrefix . $normalizedKey;

        if (func_num_args() > 2) {
            $result = $memc->get($internalKey, null, $casToken);
        } else {
            $result = $memc->get($internalKey);
        }

        $success = true;
        if ($result === false || $result === null) {
            $rsCode = $memc->getResultCode();
            if ($rsCode == MemcachedResource::RES_NOTFOUND) {
                $result = null;
                $success = false;
            } elseif ($rsCode) {
                $success = false;
                throw $this->getExceptionByResultCode($rsCode);
            }
        }

        return $result;
    }

    /**
     * Internal method to get multiple items.
     *
     * @param  array $normalizedKeys
     * @return array Associative array of keys and values
     * @throws Exception\ExceptionInterface
     */
    protected function internalGetItems(array & $normalizedKeys)
    {
        $memc = $this->getMemcachedResource();

        foreach ($normalizedKeys as & $normalizedKey) {
            $normalizedKey = $this->namespacePrefix . $normalizedKey;
        }

        $result = $memc->getMulti($normalizedKeys);
        if ($result === false) {
            throw $this->getExceptionByResultCode($memc->getResultCode());
        }

        // remove namespace prefix from result
        if ($result && $this->namespacePrefix !== '') {
            $tmp            = array();
            $nsPrefixLength = strlen($this->namespacePrefix);
            foreach ($result as $internalKey => & $value) {
                $tmp[substr($internalKey, $nsPrefixLength)] = & $value;
            }
            $result = $tmp;
        }

        return $result;
    }

    /**
     * Internal method to test if an item exists.
     *
     * @param  string $normalizedKey
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalHasItem(& $normalizedKey)
    {
        $memc  = $this->getMemcachedResource();
        $value = $memc->get($this->namespacePrefix . $normalizedKey);
        if ($value === false || $value === null) {
            $rsCode = $memc->getResultCode();
            if ($rsCode == MemcachedResource::RES_SUCCESS) {
                return true;
            } elseif ($rsCode == MemcachedResource::RES_NOTFOUND) {
                return false;
            } else {
                throw $this->getExceptionByResultCode($rsCode);
            }
        }

        return true;
    }

    /**
     * Internal method to test multiple items.
     *
     * @param  array $normalizedKeys
     * @return array Array of found keys
     * @throws Exception\ExceptionInterface
     */
    protected function internalHasItems(array & $normalizedKeys)
    {
        $memc = $this->getMemcachedResource();

        foreach ($normalizedKeys as & $normalizedKey) {
            $normalizedKey = $this->namespacePrefix . $normalizedKey;
        }

        $result = $memc->getMulti($normalizedKeys);
        if ($result === false) {
            throw $this->getExceptionByResultCode($memc->getResultCode());
        }

        // Convert to a simgle list
        $result = array_keys($result);

        // remove namespace prefix
        if ($result && $this->namespacePrefix !== '') {
            $nsPrefixLength = strlen($this->namespacePrefix);
            foreach ($result as & $internalKey) {
                $internalKey = substr($internalKey, $nsPrefixLength);
            }
        }

        return $result;
    }

    /**
     * Get metadata of multiple items
     *
     * @param  array $normalizedKeys
     * @return array Associative array of keys and metadata
     * @throws Exception\ExceptionInterface
     */
    protected function internalGetMetadatas(array & $normalizedKeys)
    {
        $memc = $this->getMemcachedResource();

        foreach ($normalizedKeys as & $normalizedKey) {
            $normalizedKey = $this->namespacePrefix . $normalizedKey;
        }

        $result = $memc->getMulti($normalizedKeys);
        if ($result === false) {
            throw $this->getExceptionByResultCode($memc->getResultCode());
        }

        // remove namespace prefix and use an empty array as metadata
        if ($this->namespacePrefix !== '') {
            $tmp            = array();
            $nsPrefixLength = strlen($this->namespacePrefix);
            foreach (array_keys($result) as $internalKey) {
                $tmp[substr($internalKey, $nsPrefixLength)] = array();
            }
            $result = $tmp;
        } else {
            foreach ($result as & $value) {
                $value = array();
            }
        }

        return $result;
    }

    /* writing */

    /**
     * Internal method to store an item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalSetItem(& $normalizedKey, & $value)
    {
        $memc       = $this->getMemcachedResource();
        $expiration = $this->expirationTime();
        if (!$memc->set($this->namespacePrefix . $normalizedKey, $value, $expiration)) {
            throw $this->getExceptionByResultCode($memc->getResultCode());
        }

        return true;
    }

    /**
     * Internal method to store multiple items.
     *
     * @param  array $normalizedKeyValuePairs
     * @return array Array of not stored keys
     * @throws Exception\ExceptionInterface
     */
    protected function internalSetItems(array & $normalizedKeyValuePairs)
    {
        $memc       = $this->getMemcachedResource();
        $expiration = $this->expirationTime();

        $namespacedKeyValuePairs = array();
        foreach ($normalizedKeyValuePairs as $normalizedKey => & $value) {
            $namespacedKeyValuePairs[$this->namespacePrefix . $normalizedKey] = & $value;
        }

        if (!$memc->setMulti($namespacedKeyValuePairs, $expiration)) {
            throw $this->getExceptionByResultCode($memc->getResultCode());
        }

        return array();
    }

    /**
     * Add an item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalAddItem(& $normalizedKey, & $value)
    {
        $memc       = $this->getMemcachedResource();
        $expiration = $this->expirationTime();
        if (!$memc->add($this->namespacePrefix . $normalizedKey, $value, $expiration)) {
            if ($memc->getResultCode() == MemcachedResource::RES_NOTSTORED) {
                return false;
            }
            throw $this->getExceptionByResultCode($memc->getResultCode());
        }

        return true;
    }

    /**
     * Internal method to replace an existing item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalReplaceItem(& $normalizedKey, & $value)
    {
        $memc       = $this->getMemcachedResource();
        $expiration = $this->expirationTime();
        if (!$memc->replace($this->namespacePrefix . $normalizedKey, $value, $expiration)) {
            $rsCode = $memc->getResultCode();
            if ($rsCode == MemcachedResource::RES_NOTSTORED) {
                return false;
            }
            throw $this->getExceptionByResultCode($rsCode);
        }

        return true;
    }

    /**
     * Internal method to set an item only if token matches
     *
     * @param  mixed  $token
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     * @see    getItem()
     * @see    setItem()
     */
    protected function internalCheckAndSetItem(& $token, & $normalizedKey, & $value)
    {
        $memc       = $this->getMemcachedResource();
        $expiration = $this->expirationTime();
        $result     = $memc->cas($token, $this->namespacePrefix . $normalizedKey, $value, $expiration);

        if ($result === false) {
            $rsCode = $memc->getResultCode();
            if ($rsCode !== 0 && $rsCode != MemcachedResource::RES_DATA_EXISTS) {
                throw $this->getExceptionByResultCode($rsCode);
            }
        }


        return $result;
    }

    /**
     * Internal method to remove an item.
     *
     * @param  string $normalizedKey
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalRemoveItem(& $normalizedKey)
    {
        $memc   = $this->getMemcachedResource();
        $result = $memc->delete($this->namespacePrefix . $normalizedKey);

        if ($result === false) {
            $rsCode = $memc->getResultCode();
            if ($rsCode == MemcachedResource::RES_NOTFOUND) {
                return false;
            } elseif ($rsCode != MemcachedResource::RES_SUCCESS) {
                throw $this->getExceptionByResultCode($rsCode);
            }
        }

        return true;
    }

    /**
     * Internal method to remove multiple items.
     *
     * @param  array $normalizedKeys
     * @return array Array of not removed keys
     * @throws Exception\ExceptionInterface
     */
    protected function internalRemoveItems(array & $normalizedKeys)
    {
        // support for removing multiple items at once has been added in ext/memcached-2.0.0
        if (static::$extMemcachedMajorVersion < 2) {
            return parent::internalRemoveItems($normalizedKeys);
        }

        $memc = $this->getMemcachedResource();

        foreach ($normalizedKeys as & $normalizedKey) {
            $normalizedKey = $this->namespacePrefix . $normalizedKey;
        }

        $rsCodes = $memc->deleteMulti($normalizedKeys);

        $missingKeys = array();
        foreach ($rsCodes as $key => $rsCode) {
            if ($rsCode !== true && $rsCode != MemcachedResource::RES_SUCCESS) {
                if ($rsCode != MemcachedResource::RES_NOTFOUND) {
                    throw $this->getExceptionByResultCode($rsCode);
                }
                $missingKeys[] = $key;
            }
        }

        // remove namespace prefix
        if ($missingKeys && $this->namespacePrefix !== '') {
            $nsPrefixLength = strlen($this->namespacePrefix);
            foreach ($missingKeys as & $missingKey) {
                $missingKey = substr($missingKey, $nsPrefixLength);
            }
        }

        return $missingKeys;
    }

    /**
     * Internal method to increment an item.
     *
     * @param  string $normalizedKey
     * @param  int    $value
     * @return int|bool The new value on success, false on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalIncrementItem(& $normalizedKey, & $value)
    {
        $memc        = $this->getMemcachedResource();
        $internalKey = $this->namespacePrefix . $normalizedKey;
        $value       = (int) $value;
        $newValue    = $memc->increment($internalKey, $value);

        if ($newValue === false) {
            $rsCode = $memc->getResultCode();

            // initial value
            if ($rsCode == MemcachedResource::RES_NOTFOUND) {
                $newValue = $value;
                $memc->add($internalKey, $newValue, $this->expirationTime());
                $rsCode = $memc->getResultCode();
            }

            if ($rsCode) {
                throw $this->getExceptionByResultCode($rsCode);
            }
        }

        return $newValue;
    }

    /**
     * Internal method to decrement an item.
     *
     * @param  string $normalizedKey
     * @param  int    $value
     * @return int|bool The new value on success, false on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalDecrementItem(& $normalizedKey, & $value)
    {
        $memc        = $this->getMemcachedResource();
        $internalKey = $this->namespacePrefix . $normalizedKey;
        $value       = (int) $value;
        $newValue    = $memc->decrement($internalKey, $value);

        if ($newValue === false) {
            $rsCode = $memc->getResultCode();

            // initial value
            if ($rsCode == MemcachedResource::RES_NOTFOUND) {
                $newValue = -$value;
                $memc->add($internalKey, $newValue, $this->expirationTime());
                $rsCode = $memc->getResultCode();
            }

            if ($rsCode) {
                throw $this->getExceptionByResultCode($rsCode);
            }
        }

        return $newValue;
    }

    /* status */

    /**
     * Internal method to get capabilities of this adapter
     *
     * @return Capabilities
     */
    protected function internalGetCapabilities()
    {
        if ($this->capabilities === null) {
            $this->capabilityMarker = new stdClass();
            $this->capabilities     = new Capabilities(
                $this,
                $this->capabilityMarker,
                array(
                    'supportedDatatypes' => array(
                        'NULL'     => true,
                        'boolean'  => true,
                        'integer'  => true,
                        'double'   => true,
                        'string'   => true,
                        'array'    => true,
                        'object'   => 'object',
                        'resource' => false,
                    ),
                    'supportedMetadata'  => array(),
                    'minTtl'             => 1,
                    'maxTtl'             => 0,
                    'staticTtl'          => true,
                    'ttlPrecision'       => 1,
                    'useRequestTime'     => false,
                    'expiredRead'        => false,
                    'maxKeyLength'       => 255,
                    'namespaceIsPrefix'  => true,
                )
            );
        }

        return $this->capabilities;
    }

    /* internal */

    /**
     * Get expiration time by ttl
     *
     * Some storage commands involve sending an expiration value (relative to
     * an item or to an operation requested by the client) to the server. In
     * all such cases, the actual value sent may either be Unix time (number of
     * seconds since January 1, 1970, as an integer), or a number of seconds
     * starting from current time. In the latter case, this number of seconds
     * may not exceed 60*60*24*30 (number of seconds in 30 days); if the
     * expiration value is larger than that, the server will consider it to be
     * real Unix time value rather than an offset from current time.
     *
     * @return int
     */
    protected function expirationTime()
    {
        $ttl = $this->getOptions()->getTtl();
        if ($ttl > 2592000) {
            return time() + $ttl;
        }
        return $ttl;
    }

    /**
     * Generate exception based of memcached result code
     *
     * @param int $code
     * @return Exception\RuntimeException
     * @throws Exception\InvalidArgumentException On success code
     */
    protected function getExceptionByResultCode($code)
    {
        switch ($code) {
            case MemcachedResource::RES_SUCCESS:
                throw new Exception\InvalidArgumentException(
                    "The result code '{$code}' (SUCCESS) isn't an error"
                );

            default:
                return new Exception\RuntimeException($this->getMemcachedResource()->getResultMessage());
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

use Zend\Cache\Exception;
use Zend\Cache\Storage\IteratorInterface;

class DbaIterator implements IteratorInterface
{
    /**
     * The apc storage instance
     *
     * @var Apc
     */
    protected $storage;

    /**
     * The iterator mode
     *
     * @var int
     */
    protected $mode = IteratorInterface::CURRENT_AS_KEY;

    /**
     * The dba resource handle
     *
     * @var resource
     */
    protected $handle;

    /**
     * The length of the namespace prefix
     *
     * @var int
     */
    protected $prefixLength;

    /**
     * The current internal key
     *
     * @var string|bool
     */
    protected $currentInternalKey;

    /**
     * Constructor
     *
     * @param Dba      $storage
     * @param resource $handle
     * @param string   $prefix
     */
    public function __construct(Dba $storage, $handle, $prefix)
    {
        $this->storage      = $storage;
        $this->handle       = $handle;
        $this->prefixLength = strlen($prefix);

        $this->rewind();
    }

    /**
     * Get storage instance
     *
     * @return Dba
     */
    public function getStorage()
    {
        return $this->storage;
    }

    /**
     * Get iterator mode
     *
     * @return int Value of IteratorInterface::CURRENT_AS_*
     */
    public function getMode()
    {
        return $this->mode;
    }

    /**
     * Set iterator mode
     *
     * @param int $mode
     * @return ApcIterator Fluent interface
     */
    public function setMode($mode)
    {
        $this->mode = (int) $mode;
        return $this;
    }

    /* Iterator */

    /**
     * Get current key, value or metadata.
     *
     * @return mixed
     * @throws Exception\RuntimeException
     */
    public function current()
    {
        if ($this->mode == IteratorInterface::CURRENT_AS_SELF) {
            return $this;
        }

        $key = $this->key();

        if ($this->mode == IteratorInterface::CURRENT_AS_VALUE) {
            return $this->storage->getItem($key);
        } elseif ($this->mode == IteratorInterface::CURRENT_AS_METADATA) {
            return $this->storage->getMetadata($key);
        }

        return $key;
    }

    /**
     * Get current key
     *
     * @return string
     * @throws Exception\RuntimeException
     */
    public function key()
    {
        if ($this->currentInternalKey === false) {
            throw new Exception\RuntimeException("Iterator is on an invalid state");
        }

        // remove namespace prefix
        return substr($this->currentInternalKey, $this->prefixLength);
    }

    /**
     * Move forward to next element
     *
     * @return void
     * @throws Exception\RuntimeException
     */
    public function next()
    {
        if ($this->currentInternalKey === false) {
            throw new Exception\RuntimeException("Iterator is on an invalid state");
        }

        $this->currentInternalKey = dba_nextkey($this->handle);

        // Workaround for PHP-Bug #62492
        if ($this->currentInternalKey === null) {
            $this->currentInternalKey = false;
        }
    }

    /**
     * Checks if current position is valid
     *
     * @return bool
     */
    public function valid()
    {
        return ($this->currentInternalKey !== false);
    }

    /**
     * Rewind the Iterator to the first element.
     *
     * @return void
     * @throws Exception\RuntimeException
     */
    public function rewind()
    {
        if ($this->currentInternalKey === false) {
            throw new Exception\RuntimeException("Iterator is on an invalid state");
        }

        $this->currentInternalKey = dba_firstkey($this->handle);

        // Workaround for PHP-Bug #62492
        if ($this->currentInternalKey === null) {
            $this->currentInternalKey = false;
        }
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

use Traversable;
use Zend\Cache\Exception;

/**
 * These are options specific to the Filesystem adapter
 */
class FilesystemOptions extends AdapterOptions
{

    /**
     * Directory to store cache files
     *
     * @var null|string The cache directory
     *                  or NULL for the systems temporary directory
     */
    protected $cacheDir = null;

    /**
     * Call clearstatcache enabled?
     *
     * @var bool
     */
    protected $clearStatCache = true;

    /**
     * How much sub-directaries should be created?
     *
     * @var int
     */
    protected $dirLevel = 1;

    /**
     * Permission creating new directories
     *
     * @var false|int
     */
    protected $dirPermission = 0700;

    /**
     * Lock files on writing
     *
     * @var bool
     */
    protected $fileLocking = true;

    /**
     * Permission creating new files
     *
     * @var false|int
     */
    protected $filePermission = 0600;

    /**
     * Overwrite default key pattern
     *
     * Defined in AdapterOptions
     *
     * @var string
     */
    protected $keyPattern = '/^[a-z0-9_\+\-]*$/Di';

    /**
     * Namespace separator
     *
     * @var string
     */
    protected $namespaceSeparator = '-';

    /**
     * Don't get 'fileatime' as 'atime' on metadata
     *
     * @var bool
     */
    protected $noAtime = true;

    /**
     * Don't get 'filectime' as 'ctime' on metadata
     *
     * @var bool
     */
    protected $noCtime = true;

    /**
     * Umask to create files and directories
     *
     * @var false|int
     */
    protected $umask = false;

    /**
     * Constructor
     *
     * @param  array|Traversable|null $options
     * @return FilesystemOptions
     * @throws Exception\InvalidArgumentException
     */
    public function __construct($options = null)
    {
        // disable file/directory permissions by default on windows systems
        if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
            $this->filePermission = false;
            $this->dirPermission = false;
        }

        parent::__construct($options);
    }

    /**
     * Set cache dir
     *
     * @param  string $cacheDir
     * @return FilesystemOptions
     * @throws Exception\InvalidArgumentException
     */
    public function setCacheDir($cacheDir)
    {
        if ($cacheDir !== null) {
            if (!is_dir($cacheDir)) {
                throw new Exception\InvalidArgumentException(
                    "Cache directory '{$cacheDir}' not found or not a directory"
                );
            } elseif (!is_writable($cacheDir)) {
                throw new Exception\InvalidArgumentException(
                    "Cache directory '{$cacheDir}' not writable"
                );
            } elseif (!is_readable($cacheDir)) {
                throw new Exception\InvalidArgumentException(
                    "Cache directory '{$cacheDir}' not readable"
                );
            }

            $cacheDir = rtrim(realpath($cacheDir), DIRECTORY_SEPARATOR);
        } else {
            $cacheDir = sys_get_temp_dir();
        }

        $this->triggerOptionEvent('cache_dir', $cacheDir);
        $this->cacheDir = $cacheDir;
        return $this;
    }

    /**
     * Get cache dir
     *
     * @return null|string
     */
    public function getCacheDir()
    {
        if ($this->cacheDir === null) {
            $this->setCacheDir(null);
        }

        return $this->cacheDir;
    }

    /**
     * Set clear stat cache
     *
     * @param  bool $clearStatCache
     * @return FilesystemOptions
     */
    public function setClearStatCache($clearStatCache)
    {
        $clearStatCache = (bool) $clearStatCache;
        $this->triggerOptionEvent('clear_stat_cache', $clearStatCache);
        $this->clearStatCache = $clearStatCache;
        return $this;
    }

    /**
     * Get clear stat cache
     *
     * @return bool
     */
    public function getClearStatCache()
    {
        return $this->clearStatCache;
    }

    /**
     * Set dir level
     *
     * @param  int $dirLevel
     * @return FilesystemOptions
     * @throws Exception\InvalidArgumentException
     */
    public function setDirLevel($dirLevel)
    {
        $dirLevel = (int) $dirLevel;
        if ($dirLevel < 0 || $dirLevel > 16) {
            throw new Exception\InvalidArgumentException(
                "Directory level '{$dirLevel}' must be between 0 and 16"
            );
        }
        $this->triggerOptionEvent('dir_level', $dirLevel);
        $this->dirLevel = $dirLevel;
        return $this;
    }

    /**
     * Get dir level
     *
     * @return int
     */
    public function getDirLevel()
    {
        return $this->dirLevel;
    }

    /**
     * Set permission to create directories on unix systems
     *
     * @param false|string|int $dirPermission FALSE to disable explicit permission or an octal number
     * @return FilesystemOptions
     * @see setUmask
     * @see setFilePermission
     * @link http://php.net/manual/function.chmod.php
     */
    public function setDirPermission($dirPermission)
    {
        if ($dirPermission !== false) {
            if (is_string($dirPermission)) {
                $dirPermission = octdec($dirPermission);
            } else {
                $dirPermission = (int) $dirPermission;
            }

            // validate
            if (($dirPermission & 0700) != 0700) {
                throw new Exception\InvalidArgumentException(
                    'Invalid directory permission: need permission to execute, read and write by owner'
                );
            }
        }

        if ($this->dirPermission !== $dirPermission) {
            $this->triggerOptionEvent('dir_permission', $dirPermission);
            $this->dirPermission = $dirPermission;
        }

        return $this;
    }

    /**
     * Get permission to create directories on unix systems
     *
     * @return false|int
     */
    public function getDirPermission()
    {
        return $this->dirPermission;
    }

    /**
     * Set file locking
     *
     * @param  bool $fileLocking
     * @return FilesystemOptions
     */
    public function setFileLocking($fileLocking)
    {
        $fileLocking = (bool) $fileLocking;
        $this->triggerOptionEvent('file_locking', $fileLocking);
        $this->fileLocking = $fileLocking;
        return $this;
    }

    /**
     * Get file locking
     *
     * @return bool
     */
    public function getFileLocking()
    {
        return $this->fileLocking;
    }

    /**
     * Set permission to create files on unix systems
     *
     * @param false|string|int $filePermission FALSE to disable explicit permission or an octal number
     * @return FilesystemOptions
     * @see setUmask
     * @see setDirPermission
     * @link http://php.net/manual/function.chmod.php
     */
    public function setFilePermission($filePermission)
    {
        if ($filePermission !== false) {
            if (is_string($filePermission)) {
                $filePermission = octdec($filePermission);
            } else {
                $filePermission = (int) $filePermission;
            }

            // validate
            if (($filePermission & 0600) != 0600) {
                throw new Exception\InvalidArgumentException(
                    'Invalid file permission: need permission to read and write by owner'
                );
            } elseif ($filePermission & 0111) {
                throw new Exception\InvalidArgumentException(
                    "Invalid file permission: Cache files shoudn't be executable"
                );
            }
        }

        if ($this->filePermission !== $filePermission) {
            $this->triggerOptionEvent('file_permission', $filePermission);
            $this->filePermission = $filePermission;
        }

        return $this;
    }

    /**
     * Get permission to create files on unix systems
     *
     * @return false|int
     */
    public function getFilePermission()
    {
        return $this->filePermission;
    }

    /**
     * Set namespace separator
     *
     * @param  string $namespaceSeparator
     * @return FilesystemOptions
     */
    public function setNamespaceSeparator($namespaceSeparator)
    {
        $namespaceSeparator = (string) $namespaceSeparator;
        $this->triggerOptionEvent('namespace_separator', $namespaceSeparator);
        $this->namespaceSeparator = $namespaceSeparator;
        return $this;
    }

    /**
     * Get namespace separator
     *
     * @return string
     */
    public function getNamespaceSeparator()
    {
        return $this->namespaceSeparator;
    }

    /**
     * Set no atime
     *
     * @param  bool $noAtime
     * @return FilesystemOptions
     */
    public function setNoAtime($noAtime)
    {
        $noAtime = (bool) $noAtime;
        $this->triggerOptionEvent('no_atime', $noAtime);
        $this->noAtime = $noAtime;
        return $this;
    }

    /**
     * Get no atime
     *
     * @return bool
     */
    public function getNoAtime()
    {
        return $this->noAtime;
    }

    /**
     * Set no ctime
     *
     * @param  bool $noCtime
     * @return FilesystemOptions
     */
    public function setNoCtime($noCtime)
    {
        $noCtime = (bool) $noCtime;
        $this->triggerOptionEvent('no_ctime', $noCtime);
        $this->noCtime = $noCtime;
        return $this;
    }

    /**
     * Get no ctime
     *
     * @return bool
     */
    public function getNoCtime()
    {
        return $this->noCtime;
    }

    /**
     * Set the umask to create files and directories on unix systems
     *
     * Note: On multithreaded webservers it's better to explicit set file and dir permission.
     *
     * @param false|string|int $umask FALSE to disable umask or an octal number
     * @return FilesystemOptions
     * @see setFilePermission
     * @see setDirPermission
     * @link http://php.net/manual/function.umask.php
     * @link http://en.wikipedia.org/wiki/Umask
     */
    public function setUmask($umask)
    {
        if ($umask !== false) {
            if (is_string($umask)) {
                $umask = octdec($umask);
            } else {
                $umask = (int) $umask;
            }

            // validate
            if ($umask & 0700) {
                throw new Exception\InvalidArgumentException(
                    'Invalid umask: need permission to execute, read and write by owner'
                );
            }

            // normalize
            $umask = $umask & 0777;
        }

        if ($this->umask !== $umask) {
            $this->triggerOptionEvent('umask', $umask);
            $this->umask = $umask;
        }

        return $this;
    }

    /**
     * Get the umask to create files and directories on unix systems
     *
     * @return false|int
     */
    public function getUmask()
    {
        return $this->umask;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

use Zend\Cache\Exception;
use Zend\Cache\Storage\AvailableSpaceCapableInterface;
use Zend\Cache\Storage\ClearByNamespaceInterface;
use Zend\Cache\Storage\FlushableInterface;
use Zend\Cache\Storage\TotalSpaceCapableInterface;
use Zend\Stdlib\ErrorHandler;

class ZendServerDisk extends AbstractZendServer implements
    AvailableSpaceCapableInterface,
    ClearByNamespaceInterface,
    FlushableInterface,
    TotalSpaceCapableInterface
{

    /**
     * Buffered total space in bytes
     *
     * @var null|int|float
     */
    protected $totalSpace;

    /**
     * Constructor
     *
     * @param  null|array|\Traversable|AdapterOptions $options
     * @throws Exception\ExtensionNotLoadedException
     */
    public function __construct($options = array())
    {
        if (!function_exists('zend_disk_cache_store')) {
            throw new Exception\ExtensionNotLoadedException("Missing 'zend_disk_cache_*' functions");
        } elseif (PHP_SAPI == 'cli') {
            throw new Exception\ExtensionNotLoadedException("Zend server data cache isn't available on cli");
        }

        parent::__construct($options);
    }

    /* FlushableInterface */

    /**
     * Flush the whole storage
     *
     * @return bool
     */
    public function flush()
    {
        return zend_disk_cache_clear();
    }

    /* ClearByNamespaceInterface */

    /**
     * Remove items of given namespace
     *
     * @param string $namespace
     * @return bool
     */
    public function clearByNamespace($namespace)
    {
        $namespace = (string) $namespace;
        if ($namespace === '') {
            throw new Exception\InvalidArgumentException('No namespace given');
        }

        return zend_disk_cache_clear($namespace);
    }

    /* TotalSpaceCapableInterface */

    /**
     * Get total space in bytes
     *
     * @throws Exception\RuntimeException
     * @return int|float
     */
    public function getTotalSpace()
    {
        if ($this->totalSpace === null) {
            $path = ini_get('zend_datacache.disk.save_path');

            ErrorHandler::start();
            $total = disk_total_space($path);
            $error = ErrorHandler::stop();
            if ($total === false) {
                throw new Exception\RuntimeException("Can't detect total space of '{$path}'", 0, $error);
            }

            $this->totalSpace = $total;
        }
        return $this->totalSpace;
    }

    /* AvailableSpaceCapableInterface */

    /**
     * Get available space in bytes
     *
     * @throws Exception\RuntimeException
     * @return int|float
     */
    public function getAvailableSpace()
    {
        $path = ini_get('zend_datacache.disk.save_path');

        ErrorHandler::start();
        $avail = disk_free_space($path);
        $error = ErrorHandler::stop();
        if ($avail === false) {
            throw new Exception\RuntimeException("Can't detect free space of '{$path}'", 0, $error);
        }

        return $avail;
    }

    /* internal  */

    /**
     * Store data into Zend Data Disk Cache
     *
     * @param  string $internalKey
     * @param  mixed  $value
     * @param  int    $ttl
     * @return void
     * @throws Exception\RuntimeException
     */
    protected function zdcStore($internalKey, $value, $ttl)
    {
        if (!zend_disk_cache_store($internalKey, $value, $ttl)) {
            $valueType = gettype($value);
            throw new Exception\RuntimeException(
                "zend_disk_cache_store($internalKey, <{$valueType}>, {$ttl}) failed"
            );
        }
    }

    /**
     * Fetch a single item from Zend Data Disk Cache
     *
     * @param  string $internalKey
     * @return mixed The stored value or FALSE if item wasn't found
     * @throws Exception\RuntimeException
     */
    protected function zdcFetch($internalKey)
    {
        return zend_disk_cache_fetch((string) $internalKey);
    }

    /**
     * Fetch multiple items from Zend Data Disk Cache
     *
     * @param  array $internalKeys
     * @return array All found items
     * @throws Exception\RuntimeException
     */
    protected function zdcFetchMulti(array $internalKeys)
    {
        $items = zend_disk_cache_fetch($internalKeys);
        if ($items === false) {
            throw new Exception\RuntimeException("zend_disk_cache_fetch(<array>) failed");
        }
        return $items;
    }

    /**
     * Delete data from Zend Data Disk Cache
     *
     * @param  string $internalKey
     * @return bool
     * @throws Exception\RuntimeException
     */
    protected function zdcDelete($internalKey)
    {
        return zend_disk_cache_delete($internalKey);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

use ArrayObject;
use SplObjectStorage;
use stdClass;
use Traversable;
use Zend\Cache\Exception;
use Zend\Cache\Storage\Capabilities;
use Zend\Cache\Storage\Event;
use Zend\Cache\Storage\ExceptionEvent;
use Zend\Cache\Storage\Plugin;
use Zend\Cache\Storage\PostEvent;
use Zend\Cache\Storage\StorageInterface;
use Zend\EventManager\EventManager;
use Zend\EventManager\EventManagerInterface;
use Zend\EventManager\EventsCapableInterface;

abstract class AbstractAdapter implements StorageInterface, EventsCapableInterface
{
    /**
     * The used EventManager if any
     *
     * @var null|EventManagerInterface
     */
    protected $events = null;

    /**
     * Event handles of this adapter
     * @var array
     */
    protected $eventHandles = array();

    /**
     * The plugin registry
     *
     * @var SplObjectStorage Registered plugins
     */
    protected $pluginRegistry;

    /**
     * Capabilities of this adapter
     *
     * @var null|Capabilities
     */
    protected $capabilities = null;

    /**
     * Marker to change capabilities
     *
     * @var null|object
     */
    protected $capabilityMarker;

    /**
     * options
     *
     * @var mixed
     */
    protected $options;

    /**
     * Constructor
     *
     * @param  null|array|Traversable|AdapterOptions $options
     * @throws Exception\ExceptionInterface
     */
    public function __construct($options = null)
    {
        if ($options) {
            $this->setOptions($options);
        }
    }

    /**
     * Destructor
     *
     * detach all registered plugins to free
     * event handles of event manager
     *
     * @return void
     */
    public function __destruct()
    {
        foreach ($this->getPluginRegistry() as $plugin) {
            $this->removePlugin($plugin);
        }

        if ($this->eventHandles) {
            $events = $this->getEventManager();
            foreach ($this->eventHandles as $handle) {
                $events->detach($handle);
            }
        }
    }

    /* configuration */

    /**
     * Set options.
     *
     * @param  array|Traversable|AdapterOptions $options
     * @return AbstractAdapter
     * @see    getOptions()
     */
    public function setOptions($options)
    {
        if ($this->options !== $options) {
            if (!$options instanceof AdapterOptions) {
                $options = new AdapterOptions($options);
            }

            if ($this->options) {
                $this->options->setAdapter(null);
            }
            $options->setAdapter($this);
            $this->options = $options;

            $event = new Event('option', $this, new ArrayObject($options->toArray()));
            $this->getEventManager()->trigger($event);
        }
        return $this;
    }

    /**
     * Get options.
     *
     * @return AdapterOptions
     * @see setOptions()
     */
    public function getOptions()
    {
        if (!$this->options) {
            $this->setOptions(new AdapterOptions());
        }
        return $this->options;
    }

    /**
     * Enable/Disable caching.
     *
     * Alias of setWritable and setReadable.
     *
     * @see    setWritable()
     * @see    setReadable()
     * @param  bool $flag
     * @return AbstractAdapter
     */
    public function setCaching($flag)
    {
        $flag    = (bool) $flag;
        $options = $this->getOptions();
        $options->setWritable($flag);
        $options->setReadable($flag);
        return $this;
    }

    /**
     * Get caching enabled.
     *
     * Alias of getWritable and getReadable.
     *
     * @see    getWritable()
     * @see    getReadable()
     * @return bool
     */
    public function getCaching()
    {
        $options = $this->getOptions();
        return ($options->getWritable() && $options->getReadable());
    }

    /* Event/Plugin handling */

    /**
     * Get the event manager
     *
     * @return EventManagerInterface
     */
    public function getEventManager()
    {
        if ($this->events === null) {
            $this->events = new EventManager(array(__CLASS__, get_class($this)));
        }
        return $this->events;
    }

    /**
     * Trigger an pre event and return the event response collection
     *
     * @param  string $eventName
     * @param  ArrayObject $args
     * @return \Zend\EventManager\ResponseCollection All handler return values
     */
    protected function triggerPre($eventName, ArrayObject $args)
    {
        return $this->getEventManager()->trigger(new Event($eventName . '.pre', $this, $args));
    }

    /**
     * Triggers the PostEvent and return the result value.
     *
     * @param  string      $eventName
     * @param  ArrayObject $args
     * @param  mixed       $result
     * @return mixed
     */
    protected function triggerPost($eventName, ArrayObject $args, & $result)
    {
        $postEvent = new PostEvent($eventName . '.post', $this, $args, $result);
        $eventRs   = $this->getEventManager()->trigger($postEvent);
        if ($eventRs->stopped()) {
            return $eventRs->last();
        }

        return $postEvent->getResult();
    }

    /**
     * Trigger an exception event
     *
     * If the ExceptionEvent has the flag "throwException" enabled throw the
     * exception after trigger else return the result.
     *
     * @param  string      $eventName
     * @param  ArrayObject $args
     * @param  mixed       $result
     * @param  \Exception  $exception
     * @throws Exception\ExceptionInterface
     * @return mixed
     */
    protected function triggerException($eventName, ArrayObject $args, & $result, \Exception $exception)
    {
        $exceptionEvent = new ExceptionEvent($eventName . '.exception', $this, $args, $result, $exception);
        $eventRs        = $this->getEventManager()->trigger($exceptionEvent);

        if ($exceptionEvent->getThrowException()) {
            throw $exceptionEvent->getException();
        }

        if ($eventRs->stopped()) {
            return $eventRs->last();
        }

        return $exceptionEvent->getResult();
    }

    /**
     * Check if a plugin is registered
     *
     * @param  Plugin\PluginInterface $plugin
     * @return bool
     */
    public function hasPlugin(Plugin\PluginInterface $plugin)
    {
        $registry = $this->getPluginRegistry();
        return $registry->contains($plugin);
    }

    /**
     * Register a plugin
     *
     * @param  Plugin\PluginInterface $plugin
     * @param  int                    $priority
     * @return AbstractAdapter Fluent interface
     * @throws Exception\LogicException
     */
    public function addPlugin(Plugin\PluginInterface $plugin, $priority = 1)
    {
        $registry = $this->getPluginRegistry();
        if ($registry->contains($plugin)) {
            throw new Exception\LogicException(sprintf(
                'Plugin of type "%s" already registered',
                get_class($plugin)
            ));
        }

        $plugin->attach($this->getEventManager(), $priority);
        $registry->attach($plugin);

        return $this;
    }

    /**
     * Unregister an already registered plugin
     *
     * @param  Plugin\PluginInterface $plugin
     * @return AbstractAdapter Fluent interface
     * @throws Exception\LogicException
     */
    public function removePlugin(Plugin\PluginInterface $plugin)
    {
        $registry = $this->getPluginRegistry();
        if ($registry->contains($plugin)) {
            $plugin->detach($this->getEventManager());
            $registry->detach($plugin);
        }
        return $this;
    }

    /**
     * Return registry of plugins
     *
     * @return SplObjectStorage
     */
    public function getPluginRegistry()
    {
        if (!$this->pluginRegistry instanceof SplObjectStorage) {
            $this->pluginRegistry = new SplObjectStorage();
        }
        return $this->pluginRegistry;
    }

    /* reading */

    /**
     * Get an item.
     *
     * @param  string  $key
     * @param  bool $success
     * @param  mixed   $casToken
     * @return mixed Data on success, null on failure
     * @throws Exception\ExceptionInterface
     *
     * @triggers getItem.pre(PreEvent)
     * @triggers getItem.post(PostEvent)
     * @triggers getItem.exception(ExceptionEvent)
     */
    public function getItem($key, & $success = null, & $casToken = null)
    {
        if (!$this->getOptions()->getReadable()) {
            $success = false;
            return null;
        }

        $this->normalizeKey($key);

        $argn = func_num_args();
        $args = array(
            'key' => & $key,
        );
        if ($argn > 1) {
            $args['success'] = & $success;
        }
        if ($argn > 2) {
            $args['casToken'] = & $casToken;
        }
        $args = new ArrayObject($args);

        try {
            $eventRs = $this->triggerPre(__FUNCTION__, $args);
            if ($eventRs->stopped()) {
                return $eventRs->last();
            }

            if ($args->offsetExists('success') && $args->offsetExists('casToken')) {
                $result = $this->internalGetItem($args['key'], $args['success'], $args['casToken']);
            } elseif ($args->offsetExists('success')) {
                $result = $this->internalGetItem($args['key'], $args['success']);
            } else {
                $result = $this->internalGetItem($args['key']);
            }
            return $this->triggerPost(__FUNCTION__, $args, $result);
        } catch (\Exception $e) {
            $result = false;
            return $this->triggerException(__FUNCTION__, $args, $result, $e);
        }
    }

    /**
     * Internal method to get an item.
     *
     * @param  string  $normalizedKey
     * @param  bool $success
     * @param  mixed   $casToken
     * @return mixed Data on success, null on failure
     * @throws Exception\ExceptionInterface
     */
    abstract protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null);

    /**
     * Get multiple items.
     *
     * @param  array $keys
     * @return array Associative array of keys and values
     * @throws Exception\ExceptionInterface
     *
     * @triggers getItems.pre(PreEvent)
     * @triggers getItems.post(PostEvent)
     * @triggers getItems.exception(ExceptionEvent)
     */
    public function getItems(array $keys)
    {
        if (!$this->getOptions()->getReadable()) {
            return array();
        }

        $this->normalizeKeys($keys);
        $args = new ArrayObject(array(
            'keys' => & $keys,
        ));

        try {
            $eventRs = $this->triggerPre(__FUNCTION__, $args);
            if ($eventRs->stopped()) {
                return $eventRs->last();
            }

            $result = $this->internalGetItems($args['keys']);
            return $this->triggerPost(__FUNCTION__, $args, $result);
        } catch (\Exception $e) {
            $result = array();
            return $this->triggerException(__FUNCTION__, $args, $result, $e);
        }
    }

    /**
     * Internal method to get multiple items.
     *
     * @param  array $normalizedKeys
     * @return array Associative array of keys and values
     * @throws Exception\ExceptionInterface
     */
    protected function internalGetItems(array & $normalizedKeys)
    {
        $success = null;
        $result  = array();
        foreach ($normalizedKeys as $normalizedKey) {
            $value = $this->internalGetItem($normalizedKey, $success);
            if ($success) {
                $result[$normalizedKey] = $value;
            }
        }

        return $result;
    }

    /**
     * Test if an item exists.
     *
     * @param  string $key
     * @return bool
     * @throws Exception\ExceptionInterface
     *
     * @triggers hasItem.pre(PreEvent)
     * @triggers hasItem.post(PostEvent)
     * @triggers hasItem.exception(ExceptionEvent)
     */
    public function hasItem($key)
    {
        if (!$this->getOptions()->getReadable()) {
            return false;
        }

        $this->normalizeKey($key);
        $args = new ArrayObject(array(
            'key' => & $key,
        ));

        try {
            $eventRs = $this->triggerPre(__FUNCTION__, $args);
            if ($eventRs->stopped()) {
                return $eventRs->last();
            }

            $result = $this->internalHasItem($args['key']);
            return $this->triggerPost(__FUNCTION__, $args, $result);
        } catch (\Exception $e) {
            $result = false;
            return $this->triggerException(__FUNCTION__, $args, $result, $e);
        }
    }

    /**
     * Internal method to test if an item exists.
     *
     * @param  string $normalizedKey
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalHasItem(& $normalizedKey)
    {
        $success = null;
        $this->internalGetItem($normalizedKey, $success);
        return $success;
    }

    /**
     * Test multiple items.
     *
     * @param  array $keys
     * @return array Array of found keys
     * @throws Exception\ExceptionInterface
     *
     * @triggers hasItems.pre(PreEvent)
     * @triggers hasItems.post(PostEvent)
     * @triggers hasItems.exception(ExceptionEvent)
     */
    public function hasItems(array $keys)
    {
        if (!$this->getOptions()->getReadable()) {
            return array();
        }

        $this->normalizeKeys($keys);
        $args = new ArrayObject(array(
            'keys' => & $keys,
        ));

        try {
            $eventRs = $this->triggerPre(__FUNCTION__, $args);
            if ($eventRs->stopped()) {
                return $eventRs->last();
            }

            $result = $this->internalHasItems($args['keys']);
            return $this->triggerPost(__FUNCTION__, $args, $result);
        } catch (\Exception $e) {
            $result = array();
            return $this->triggerException(__FUNCTION__, $args, $result, $e);
        }
    }

    /**
     * Internal method to test multiple items.
     *
     * @param  array $normalizedKeys
     * @return array Array of found keys
     * @throws Exception\ExceptionInterface
     */
    protected function internalHasItems(array & $normalizedKeys)
    {
        $result = array();
        foreach ($normalizedKeys as $normalizedKey) {
            if ($this->internalHasItem($normalizedKey)) {
                $result[] = $normalizedKey;
            }
        }
        return $result;
    }

    /**
     * Get metadata of an item.
     *
     * @param  string $key
     * @return array|bool Metadata on success, false on failure
     * @throws Exception\ExceptionInterface
     *
     * @triggers getMetadata.pre(PreEvent)
     * @triggers getMetadata.post(PostEvent)
     * @triggers getMetadata.exception(ExceptionEvent)
     */
    public function getMetadata($key)
    {
        if (!$this->getOptions()->getReadable()) {
            return false;
        }

        $this->normalizeKey($key);
        $args = new ArrayObject(array(
            'key' => & $key,
        ));

        try {
            $eventRs = $this->triggerPre(__FUNCTION__, $args);
            if ($eventRs->stopped()) {
                return $eventRs->last();
            }

            $result = $this->internalGetMetadata($args['key']);
            return $this->triggerPost(__FUNCTION__, $args, $result);
        } catch (\Exception $e) {
            $result = false;
            return $this->triggerException(__FUNCTION__, $args, $result, $e);
        }
    }

    /**
     * Internal method to get metadata of an item.
     *
     * @param  string $normalizedKey
     * @return array|bool Metadata on success, false on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalGetMetadata(& $normalizedKey)
    {
        if (!$this->internalHasItem($normalizedKey)) {
            return false;
        }

        return array();
    }

    /**
     * Get multiple metadata
     *
     * @param  array $keys
     * @return array Associative array of keys and metadata
     * @throws Exception\ExceptionInterface
     *
     * @triggers getMetadatas.pre(PreEvent)
     * @triggers getMetadatas.post(PostEvent)
     * @triggers getMetadatas.exception(ExceptionEvent)
     */
    public function getMetadatas(array $keys)
    {
        if (!$this->getOptions()->getReadable()) {
            return array();
        }

        $this->normalizeKeys($keys);
        $args = new ArrayObject(array(
            'keys' => & $keys,
        ));

        try {
            $eventRs = $this->triggerPre(__FUNCTION__, $args);
            if ($eventRs->stopped()) {
                return $eventRs->last();
            }

            $result = $this->internalGetMetadatas($args['keys']);
            return $this->triggerPost(__FUNCTION__, $args, $result);
        } catch (\Exception $e) {
            $result = array();
            return $this->triggerException(__FUNCTION__, $args, $result, $e);
        }
    }

    /**
     * Internal method to get multiple metadata
     *
     * @param  array $normalizedKeys
     * @return array Associative array of keys and metadata
     * @throws Exception\ExceptionInterface
     */
    protected function internalGetMetadatas(array & $normalizedKeys)
    {
        $result = array();
        foreach ($normalizedKeys as $normalizedKey) {
            $metadata = $this->internalGetMetadata($normalizedKey);
            if ($metadata !== false) {
                $result[$normalizedKey] = $metadata;
            }
        }
        return $result;
    }

    /* writing */

    /**
     * Store an item.
     *
     * @param  string $key
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     *
     * @triggers setItem.pre(PreEvent)
     * @triggers setItem.post(PostEvent)
     * @triggers setItem.exception(ExceptionEvent)
     */
    public function setItem($key, $value)
    {
        if (!$this->getOptions()->getWritable()) {
            return false;
        }

        $this->normalizeKey($key);
        $args = new ArrayObject(array(
            'key'   => & $key,
            'value' => & $value,
        ));

        try {
            $eventRs = $this->triggerPre(__FUNCTION__, $args);
            if ($eventRs->stopped()) {
                return $eventRs->last();
            }

            $result = $this->internalSetItem($args['key'], $args['value']);
            return $this->triggerPost(__FUNCTION__, $args, $result);
        } catch (\Exception $e) {
            $result = false;
            return $this->triggerException(__FUNCTION__, $args, $result, $e);
        }
    }

    /**
     * Internal method to store an item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    abstract protected function internalSetItem(& $normalizedKey, & $value);

    /**
     * Store multiple items.
     *
     * @param  array $keyValuePairs
     * @return array Array of not stored keys
     * @throws Exception\ExceptionInterface
     *
     * @triggers setItems.pre(PreEvent)
     * @triggers setItems.post(PostEvent)
     * @triggers setItems.exception(ExceptionEvent)
     */
    public function setItems(array $keyValuePairs)
    {
        if (!$this->getOptions()->getWritable()) {
            return array_keys($keyValuePairs);
        }

        $this->normalizeKeyValuePairs($keyValuePairs);
        $args = new ArrayObject(array(
            'keyValuePairs' => & $keyValuePairs,
        ));

        try {
            $eventRs = $this->triggerPre(__FUNCTION__, $args);
            if ($eventRs->stopped()) {
                return $eventRs->last();
            }

            $result = $this->internalSetItems($args['keyValuePairs']);
            return $this->triggerPost(__FUNCTION__, $args, $result);
        } catch (\Exception $e) {
            $result = array_keys($keyValuePairs);
            return $this->triggerException(__FUNCTION__, $args, $result, $e);
        }
    }

    /**
     * Internal method to store multiple items.
     *
     * @param  array $normalizedKeyValuePairs
     * @return array Array of not stored keys
     * @throws Exception\ExceptionInterface
     */
    protected function internalSetItems(array & $normalizedKeyValuePairs)
    {
        $failedKeys = array();
        foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
            if (!$this->internalSetItem($normalizedKey, $value)) {
                $failedKeys[] = $normalizedKey;
            }
        }
        return $failedKeys;
    }

    /**
     * Add an item.
     *
     * @param  string $key
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     *
     * @triggers addItem.pre(PreEvent)
     * @triggers addItem.post(PostEvent)
     * @triggers addItem.exception(ExceptionEvent)
     */
    public function addItem($key, $value)
    {
        if (!$this->getOptions()->getWritable()) {
            return false;
        }

        $this->normalizeKey($key);
        $args = new ArrayObject(array(
            'key'   => & $key,
            'value' => & $value,
        ));

        try {
            $eventRs = $this->triggerPre(__FUNCTION__, $args);
            if ($eventRs->stopped()) {
                return $eventRs->last();
            }

            $result = $this->internalAddItem($args['key'], $args['value']);
            return $this->triggerPost(__FUNCTION__, $args, $result);
        } catch (\Exception $e) {
            $result = false;
            return $this->triggerException(__FUNCTION__, $args, $result, $e);
        }
    }

    /**
     * Internal method to add an item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalAddItem(& $normalizedKey, & $value)
    {
        if ($this->internalHasItem($normalizedKey)) {
            return false;
        }
        return $this->internalSetItem($normalizedKey, $value);
    }

    /**
     * Add multiple items.
     *
     * @param  array $keyValuePairs
     * @return array Array of not stored keys
     * @throws Exception\ExceptionInterface
     *
     * @triggers addItems.pre(PreEvent)
     * @triggers addItems.post(PostEvent)
     * @triggers addItems.exception(ExceptionEvent)
     */
    public function addItems(array $keyValuePairs)
    {
        if (!$this->getOptions()->getWritable()) {
            return array_keys($keyValuePairs);
        }

        $this->normalizeKeyValuePairs($keyValuePairs);
        $args = new ArrayObject(array(
            'keyValuePairs' => & $keyValuePairs,
        ));

        try {
            $eventRs = $this->triggerPre(__FUNCTION__, $args);
            if ($eventRs->stopped()) {
                return $eventRs->last();
            }

            $result = $this->internalAddItems($args['keyValuePairs']);
            return $this->triggerPost(__FUNCTION__, $args, $result);
        } catch (\Exception $e) {
            $result = array_keys($keyValuePairs);
            return $this->triggerException(__FUNCTION__, $args, $result, $e);
        }
    }

    /**
     * Internal method to add multiple items.
     *
     * @param  array $normalizedKeyValuePairs
     * @return array Array of not stored keys
     * @throws Exception\ExceptionInterface
     */
    protected function internalAddItems(array & $normalizedKeyValuePairs)
    {
        $result = array();
        foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
            if (!$this->internalAddItem($normalizedKey, $value)) {
                $result[] = $normalizedKey;
            }
        }
        return $result;
    }

    /**
     * Replace an existing item.
     *
     * @param  string $key
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     *
     * @triggers replaceItem.pre(PreEvent)
     * @triggers replaceItem.post(PostEvent)
     * @triggers replaceItem.exception(ExceptionEvent)
     */
    public function replaceItem($key, $value)
    {
        if (!$this->getOptions()->getWritable()) {
            return false;
        }

        $this->normalizeKey($key);
        $args = new ArrayObject(array(
            'key'   => & $key,
            'value' => & $value,
        ));

        try {
            $eventRs = $this->triggerPre(__FUNCTION__, $args);
            if ($eventRs->stopped()) {
                return $eventRs->last();
            }

            $result = $this->internalReplaceItem($args['key'], $args['value']);
            return $this->triggerPost(__FUNCTION__, $args, $result);
        } catch (\Exception $e) {
            $result = false;
            return $this->triggerException(__FUNCTION__, $args, $result, $e);
        }
    }

    /**
     * Internal method to replace an existing item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalReplaceItem(& $normalizedKey, & $value)
    {
        if (!$this->internalhasItem($normalizedKey)) {
            return false;
        }

        return $this->internalSetItem($normalizedKey, $value);
    }

    /**
     * Replace multiple existing items.
     *
     * @param  array $keyValuePairs
     * @return array Array of not stored keys
     * @throws Exception\ExceptionInterface
     *
     * @triggers replaceItems.pre(PreEvent)
     * @triggers replaceItems.post(PostEvent)
     * @triggers replaceItems.exception(ExceptionEvent)
     */
    public function replaceItems(array $keyValuePairs)
    {
        if (!$this->getOptions()->getWritable()) {
            return array_keys($keyValuePairs);
        }

        $this->normalizeKeyValuePairs($keyValuePairs);
        $args = new ArrayObject(array(
            'keyValuePairs' => & $keyValuePairs,
        ));

        try {
            $eventRs = $this->triggerPre(__FUNCTION__, $args);
            if ($eventRs->stopped()) {
                return $eventRs->last();
            }

            $result = $this->internalReplaceItems($args['keyValuePairs']);
            return $this->triggerPost(__FUNCTION__, $args, $result);
        } catch (\Exception $e) {
            $result = array_keys($keyValuePairs);
            return $this->triggerException(__FUNCTION__, $args, $result, $e);
        }
    }

    /**
     * Internal method to replace multiple existing items.
     *
     * @param  array $normalizedKeyValuePairs
     * @return array Array of not stored keys
     * @throws Exception\ExceptionInterface
     */
    protected function internalReplaceItems(array & $normalizedKeyValuePairs)
    {
        $result = array();
        foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
            if (!$this->internalReplaceItem($normalizedKey, $value)) {
                $result[] = $normalizedKey;
            }
        }
        return $result;
    }

    /**
     * Set an item only if token matches
     *
     * It uses the token received from getItem() to check if the item has
     * changed before overwriting it.
     *
     * @param  mixed  $token
     * @param  string $key
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     * @see    getItem()
     * @see    setItem()
     */
    public function checkAndSetItem($token, $key, $value)
    {
        if (!$this->getOptions()->getWritable()) {
            return false;
        }

        $this->normalizeKey($key);
        $args = new ArrayObject(array(
            'token' => & $token,
            'key'   => & $key,
            'value' => & $value,
        ));

        try {
            $eventRs = $this->triggerPre(__FUNCTION__, $args);
            if ($eventRs->stopped()) {
                return $eventRs->last();
            }

            $result = $this->internalCheckAndSetItem($args['token'], $args['key'], $args['value']);
            return $this->triggerPost(__FUNCTION__, $args, $result);
        } catch (\Exception $e) {
            $result = false;
            return $this->triggerException(__FUNCTION__, $args, $result, $e);
        }
    }

    /**
     * Internal method to set an item only if token matches
     *
     * @param  mixed  $token
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     * @see    getItem()
     * @see    setItem()
     */
    protected function internalCheckAndSetItem(& $token, & $normalizedKey, & $value)
    {
        $oldValue = $this->internalGetItem($normalizedKey);
        if ($oldValue !== $token) {
            return false;
        }

        return $this->internalSetItem($normalizedKey, $value);
    }

    /**
     * Reset lifetime of an item
     *
     * @param  string $key
     * @return bool
     * @throws Exception\ExceptionInterface
     *
     * @triggers touchItem.pre(PreEvent)
     * @triggers touchItem.post(PostEvent)
     * @triggers touchItem.exception(ExceptionEvent)
     */
    public function touchItem($key)
    {
        if (!$this->getOptions()->getWritable()) {
            return false;
        }

        $this->normalizeKey($key);
        $args = new ArrayObject(array(
            'key' => & $key,
        ));

        try {
            $eventRs = $this->triggerPre(__FUNCTION__, $args);
            if ($eventRs->stopped()) {
                return $eventRs->last();
            }

            $result = $this->internalTouchItem($args['key']);
            return $this->triggerPost(__FUNCTION__, $args, $result);
        } catch (\Exception $e) {
            $result = false;
            return $this->triggerException(__FUNCTION__, $args, $result, $e);
        }
    }

    /**
     * Internal method to reset lifetime of an item
     *
     * @param  string $normalizedKey
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalTouchItem(& $normalizedKey)
    {
        $success = null;
        $value   = $this->internalGetItem($normalizedKey, $success);
        if (!$success) {
            return false;
        }

        return $this->internalReplaceItem($normalizedKey, $value);
    }

    /**
     * Reset lifetime of multiple items.
     *
     * @param  array $keys
     * @return array Array of not updated keys
     * @throws Exception\ExceptionInterface
     *
     * @triggers touchItems.pre(PreEvent)
     * @triggers touchItems.post(PostEvent)
     * @triggers touchItems.exception(ExceptionEvent)
     */
    public function touchItems(array $keys)
    {
        if (!$this->getOptions()->getWritable()) {
            return $keys;
        }

        $this->normalizeKeys($keys);
        $args = new ArrayObject(array(
            'keys' => & $keys,
        ));

        try {
            $eventRs = $this->triggerPre(__FUNCTION__, $args);
            if ($eventRs->stopped()) {
                return $eventRs->last();
            }

            $result = $this->internalTouchItems($args['keys']);
            return $this->triggerPost(__FUNCTION__, $args, $result);
        } catch (\Exception $e) {
            return $this->triggerException(__FUNCTION__, $args, $keys, $e);
        }
    }

    /**
     * Internal method to reset lifetime of multiple items.
     *
     * @param  array $normalizedKeys
     * @return array Array of not updated keys
     * @throws Exception\ExceptionInterface
     */
    protected function internalTouchItems(array & $normalizedKeys)
    {
        $result = array();
        foreach ($normalizedKeys as $normalizedKey) {
            if (!$this->internalTouchItem($normalizedKey)) {
                $result[] = $normalizedKey;
            }
        }
        return $result;
    }

    /**
     * Remove an item.
     *
     * @param  string $key
     * @return bool
     * @throws Exception\ExceptionInterface
     *
     * @triggers removeItem.pre(PreEvent)
     * @triggers removeItem.post(PostEvent)
     * @triggers removeItem.exception(ExceptionEvent)
     */
    public function removeItem($key)
    {
        if (!$this->getOptions()->getWritable()) {
            return false;
        }

        $this->normalizeKey($key);
        $args = new ArrayObject(array(
            'key' => & $key,
        ));

        try {
            $eventRs = $this->triggerPre(__FUNCTION__, $args);
            if ($eventRs->stopped()) {
                return $eventRs->last();
            }

            $result = $this->internalRemoveItem($args['key']);
            return $this->triggerPost(__FUNCTION__, $args, $result);
        } catch (\Exception $e) {
            $result = false;
            return $this->triggerException(__FUNCTION__, $args, $result, $e);
        }
    }

    /**
     * Internal method to remove an item.
     *
     * @param  string $normalizedKey
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    abstract protected function internalRemoveItem(& $normalizedKey);

    /**
     * Remove multiple items.
     *
     * @param  array $keys
     * @return array Array of not removed keys
     * @throws Exception\ExceptionInterface
     *
     * @triggers removeItems.pre(PreEvent)
     * @triggers removeItems.post(PostEvent)
     * @triggers removeItems.exception(ExceptionEvent)
     */
    public function removeItems(array $keys)
    {
        if (!$this->getOptions()->getWritable()) {
            return $keys;
        }

        $this->normalizeKeys($keys);
        $args = new ArrayObject(array(
            'keys' => & $keys,
        ));

        try {
            $eventRs = $this->triggerPre(__FUNCTION__, $args);
            if ($eventRs->stopped()) {
                return $eventRs->last();
            }

            $result = $this->internalRemoveItems($args['keys']);
            return $this->triggerPost(__FUNCTION__, $args, $result);
        } catch (\Exception $e) {
            return $this->triggerException(__FUNCTION__, $args, $keys, $e);
        }
    }

    /**
     * Internal method to remove multiple items.
     *
     * @param  array $normalizedKeys
     * @return array Array of not removed keys
     * @throws Exception\ExceptionInterface
     */
    protected function internalRemoveItems(array & $normalizedKeys)
    {
        $result = array();
        foreach ($normalizedKeys as $normalizedKey) {
            if (!$this->internalRemoveItem($normalizedKey)) {
                $result[] = $normalizedKey;
            }
        }
        return $result;
    }

    /**
     * Increment an item.
     *
     * @param  string $key
     * @param  int    $value
     * @return int|bool The new value on success, false on failure
     * @throws Exception\ExceptionInterface
     *
     * @triggers incrementItem.pre(PreEvent)
     * @triggers incrementItem.post(PostEvent)
     * @triggers incrementItem.exception(ExceptionEvent)
     */
    public function incrementItem($key, $value)
    {
        if (!$this->getOptions()->getWritable()) {
            return false;
        }

        $this->normalizeKey($key);
        $args = new ArrayObject(array(
            'key'   => & $key,
            'value' => & $value,
        ));

        try {
            $eventRs = $this->triggerPre(__FUNCTION__, $args);
            if ($eventRs->stopped()) {
                return $eventRs->last();
            }

            $result = $this->internalIncrementItem($args['key'], $args['value']);
            return $this->triggerPost(__FUNCTION__, $args, $result);
        } catch (\Exception $e) {
            $result = false;
            return $this->triggerException(__FUNCTION__, $args, $result, $e);
        }
    }

    /**
     * Internal method to increment an item.
     *
     * @param  string $normalizedKey
     * @param  int    $value
     * @return int|bool The new value on success, false on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalIncrementItem(& $normalizedKey, & $value)
    {
        $success  = null;
        $value    = (int) $value;
        $get      = (int) $this->internalGetItem($normalizedKey, $success);
        $newValue = $get + $value;

        if ($success) {
            $this->internalReplaceItem($normalizedKey, $newValue);
        } else {
            $this->internalAddItem($normalizedKey, $newValue);
        }

        return $newValue;
    }

    /**
     * Increment multiple items.
     *
     * @param  array $keyValuePairs
     * @return array Associative array of keys and new values
     * @throws Exception\ExceptionInterface
     *
     * @triggers incrementItems.pre(PreEvent)
     * @triggers incrementItems.post(PostEvent)
     * @triggers incrementItems.exception(ExceptionEvent)
     */
    public function incrementItems(array $keyValuePairs)
    {
        if (!$this->getOptions()->getWritable()) {
            return array();
        }

        $this->normalizeKeyValuePairs($keyValuePairs);
        $args = new ArrayObject(array(
            'keyValuePairs' => & $keyValuePairs,
        ));

        try {
            $eventRs = $this->triggerPre(__FUNCTION__, $args);
            if ($eventRs->stopped()) {
                return $eventRs->last();
            }

            $result = $this->internalIncrementItems($args['keyValuePairs']);
            return $this->triggerPost(__FUNCTION__, $args, $result);
        } catch (\Exception $e) {
            $result = array();
            return $this->triggerException(__FUNCTION__, $args, $result, $e);
        }
    }

    /**
     * Internal method to increment multiple items.
     *
     * @param  array $normalizedKeyValuePairs
     * @return array Associative array of keys and new values
     * @throws Exception\ExceptionInterface
     */
    protected function internalIncrementItems(array & $normalizedKeyValuePairs)
    {
        $result = array();
        foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
            $newValue = $this->internalIncrementItem($normalizedKey, $value);
            if ($newValue !== false) {
                $result[$normalizedKey] = $newValue;
            }
        }
        return $result;
    }

    /**
     * Decrement an item.
     *
     * @param  string $key
     * @param  int    $value
     * @return int|bool The new value on success, false on failure
     * @throws Exception\ExceptionInterface
     *
     * @triggers decrementItem.pre(PreEvent)
     * @triggers decrementItem.post(PostEvent)
     * @triggers decrementItem.exception(ExceptionEvent)
     */
    public function decrementItem($key, $value)
    {
        if (!$this->getOptions()->getWritable()) {
            return false;
        }

        $this->normalizeKey($key);
        $args = new ArrayObject(array(
            'key'   => & $key,
            'value' => & $value,
        ));

        try {
            $eventRs = $this->triggerPre(__FUNCTION__, $args);
            if ($eventRs->stopped()) {
                return $eventRs->last();
            }

            $result = $this->internalDecrementItem($args['key'], $args['value']);
            return $this->triggerPost(__FUNCTION__, $args, $result);
        } catch (\Exception $e) {
            $result = false;
            return $this->triggerException(__FUNCTION__, $args, $result, $e);
        }
    }

    /**
     * Internal method to decrement an item.
     *
     * @param  string $normalizedKey
     * @param  int    $value
     * @return int|bool The new value on success, false on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalDecrementItem(& $normalizedKey, & $value)
    {
        $success  = null;
        $value    = (int) $value;
        $get      = (int) $this->internalGetItem($normalizedKey, $success);
        $newValue = $get - $value;

        if ($success) {
            $this->internalReplaceItem($normalizedKey, $newValue);
        } else {
            $this->internalAddItem($normalizedKey, $newValue);
        }

        return $newValue;
    }

    /**
     * Decrement multiple items.
     *
     * @param  array $keyValuePairs
     * @return array Associative array of keys and new values
     * @throws Exception\ExceptionInterface
     *
     * @triggers incrementItems.pre(PreEvent)
     * @triggers incrementItems.post(PostEvent)
     * @triggers incrementItems.exception(ExceptionEvent)
     */
    public function decrementItems(array $keyValuePairs)
    {
        if (!$this->getOptions()->getWritable()) {
            return array();
        }

        $this->normalizeKeyValuePairs($keyValuePairs);
        $args = new ArrayObject(array(
            'keyValuePairs' => & $keyValuePairs,
        ));

        try {
            $eventRs = $this->triggerPre(__FUNCTION__, $args);
            if ($eventRs->stopped()) {
                return $eventRs->last();
            }

            $result = $this->internalDecrementItems($args['keyValuePairs']);
            return $this->triggerPost(__FUNCTION__, $args, $result);
        } catch (\Exception $e) {
            $result = array();
            return $this->triggerException(__FUNCTION__, $args, $result, $e);
        }
    }

    /**
     * Internal method to decrement multiple items.
     *
     * @param  array $normalizedKeyValuePairs
     * @return array Associative array of keys and new values
     * @throws Exception\ExceptionInterface
     */
    protected function internalDecrementItems(array & $normalizedKeyValuePairs)
    {
        $result = array();
        foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
            $newValue = $this->decrementItem($normalizedKey, $value);
            if ($newValue !== false) {
                $result[$normalizedKey] = $newValue;
            }
        }
        return $result;
    }

    /* status */

    /**
     * Get capabilities of this adapter
     *
     * @return Capabilities
     * @triggers getCapabilities.pre(PreEvent)
     * @triggers getCapabilities.post(PostEvent)
     * @triggers getCapabilities.exception(ExceptionEvent)
     */
    public function getCapabilities()
    {
        $args = new ArrayObject();

        try {
            $eventRs = $this->triggerPre(__FUNCTION__, $args);
            if ($eventRs->stopped()) {
                return $eventRs->last();
            }

            $result = $this->internalGetCapabilities();
            return $this->triggerPost(__FUNCTION__, $args, $result);
        } catch (\Exception $e) {
            $result = false;
            return $this->triggerException(__FUNCTION__, $args, $result, $e);
        }
    }

    /**
     * Internal method to get capabilities of this adapter
     *
     * @return Capabilities
     */
    protected function internalGetCapabilities()
    {
        if ($this->capabilities === null) {
            $this->capabilityMarker = new stdClass();
            $this->capabilities     = new Capabilities($this, $this->capabilityMarker);
        }
        return $this->capabilities;
    }

    /* internal */

    /**
     * Validates and normalizes a key
     *
     * @param  string $key
     * @return void
     * @throws Exception\InvalidArgumentException On an invalid key
     */
    protected function normalizeKey(& $key)
    {
        $key = (string) $key;

        if ($key === '') {
            throw new Exception\InvalidArgumentException(
                "An empty key isn't allowed"
            );
        } elseif (($p = $this->getOptions()->getKeyPattern()) && !preg_match($p, $key)) {
            throw new Exception\InvalidArgumentException(
                "The key '{$key}' doesn't match agains pattern '{$p}'"
            );
        }
    }

    /**
     * Validates and normalizes multiple keys
     *
     * @param  array $keys
     * @return void
     * @throws Exception\InvalidArgumentException On an invalid key
     */
    protected function normalizeKeys(array & $keys)
    {
        if (!$keys) {
            throw new Exception\InvalidArgumentException(
                "An empty list of keys isn't allowed"
            );
        }

        array_walk($keys, array($this, 'normalizeKey'));
        $keys = array_values(array_unique($keys));
    }

    /**
     * Validates and normalizes an array of key-value pairs
     *
     * @param  array $keyValuePairs
     * @return void
     * @throws Exception\InvalidArgumentException On an invalid key
     */
    protected function normalizeKeyValuePairs(array & $keyValuePairs)
    {
        $normalizedKeyValuePairs = array();
        foreach ($keyValuePairs as $key => $value) {
            $this->normalizeKey($key);
            $normalizedKeyValuePairs[$key] = $value;
        }
        $keyValuePairs = $normalizedKeyValuePairs;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;


/**
 * These are options specific to the APC adapter
 */
class WinCacheOptions extends AdapterOptions
{
    /**
     * Namespace separator
     *
     * @var string
     */
    protected $namespaceSeparator = ':';

    /**
     * Set namespace separator
     *
     * @param  string $namespaceSeparator
     * @return WinCacheOptions
     */
    public function setNamespaceSeparator($namespaceSeparator)
    {
        $namespaceSeparator = (string) $namespaceSeparator;
        $this->triggerOptionEvent('namespace_separator', $namespaceSeparator);
        $this->namespaceSeparator = $namespaceSeparator;
        return $this;
    }

    /**
     * Get namespace separator
     *
     * @return string
     */
    public function getNamespaceSeparator()
    {
        return $this->namespaceSeparator;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

/**
 * These are options specific to the XCache adapter
 */
class XCacheOptions extends AdapterOptions
{
    /**
     * Namespace separator
     *
     * @var string
     */
    protected $namespaceSeparator = ':';

    /**
     * Handle admin authentication
     *
     * @var bool
     */
    protected $adminAuth = false;

    /**
     * Username to call admin functions
     *
     * @var null|string
     */
    protected $adminUser;

    /**
     * Password to call admin functions
     *
     * @var null|string
     */
    protected $adminPass;

    /**
     * Set namespace separator
     *
     * @param  string $namespaceSeparator
     * @return XCacheOptions
     */
    public function setNamespaceSeparator($namespaceSeparator)
    {
        $namespaceSeparator = (string) $namespaceSeparator;
        $this->triggerOptionEvent('namespace_separator', $namespaceSeparator);
        $this->namespaceSeparator = $namespaceSeparator;
        return $this;
    }

    /**
     * Get namespace separator
     *
     * @return string
     */
    public function getNamespaceSeparator()
    {
        return $this->namespaceSeparator;
    }

    /**
     * Set username to call admin functions
     *
     * @param  null|string $adminUser
     * @return XCacheOptions
     */
    public function setAdminUser($adminUser)
    {
        $adminUser = ($adminUser === null) ? null : (string) $adminUser;
        if ($this->adminUser !== $adminUser) {
            $this->triggerOptionEvent('admin_user', $adminUser);
            $this->adminUser = $adminUser;
        }
        return $this;
    }

    /**
     * Get username to call admin functions
     *
     * @return string
     */
    public function getAdminUser()
    {
        return $this->adminUser;
    }

    /**
     * Enable/Disable admin authentication handling
     *
     * @param  bool $adminAuth
     * @return XCacheOptions
     */
    public function setAdminAuth($adminAuth)
    {
        $adminAuth = (bool) $adminAuth;
        if ($this->adminAuth !== $adminAuth) {
            $this->triggerOptionEvent('admin_auth', $adminAuth);
            $this->adminAuth = $adminAuth;
        }
        return $this;
    }

    /**
     * Get admin authentication enabled
     *
     * @return bool
     */
    public function getAdminAuth()
    {
        return $this->adminAuth;
    }

    /**
     * Set password to call admin functions
     *
     * @param  null|string $adminPass
     * @return XCacheOptions
     */
    public function setAdminPass($adminPass)
    {
        $adminPass = ($adminPass === null) ? null : (string) $adminPass;
        if ($this->adminPass !== $adminPass) {
            $this->triggerOptionEvent('admin_pass', $adminPass);
            $this->adminPass = $adminPass;
        }
        return $this;
    }

    /**
     * Get password to call admin functions
     *
     * @return string
     */
    public function getAdminPass()
    {
        return $this->adminPass;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

use Redis as RedisResource;
use Zend\Cache\Exception;
use Zend\Cache\Storage\Adapter\AdapterOptions;

class RedisOptions extends AdapterOptions
{
    /**
     * The namespace separator
     * @var string
     */
    protected $namespaceSeparator = ':';

    /**
     * The redis resource manager
     *
     * @var null|RedisResourceManager
     */
    protected $resourceManager;

    /**
     * The resource id of the resource manager
     *
     * @var string
     */
    protected $resourceId = 'default';

    /**
     * Set namespace.
     *
     * The option Redis::OPT_PREFIX will be used as the namespace.
     * It can't be longer than 128 characters.
     *
     * @param string $namespace Prefix for each key stored in redis
     * @return \Zend\Cache\Storage\Adapter\RedisOptions
     *
     * @see AdapterOptions::setNamespace()
     * @see RedisOptions::setPrefixKey()
     */
    public function setNamespace($namespace)
    {
        $namespace = (string) $namespace;

        if (128 < strlen($namespace)) {
            throw new Exception\InvalidArgumentException(sprintf(
                '%s expects a prefix key of no longer than 128 characters',
                __METHOD__
            ));
        }

        return parent::setNamespace($namespace);
    }

    /**
     * Set namespace separator
     *
     * @param  string $namespaceSeparator
     * @return RedisOptions
     */
    public function setNamespaceSeparator($namespaceSeparator)
    {
        $namespaceSeparator = (string) $namespaceSeparator;
        if ($this->namespaceSeparator !== $namespaceSeparator) {
            $this->triggerOptionEvent('namespace_separator', $namespaceSeparator);
            $this->namespaceSeparator = $namespaceSeparator;
        }
        return $this;
    }

    /**
     * Get namespace separator
     *
     * @return string
     */
    public function getNamespaceSeparator()
    {
        return $this->namespaceSeparator;
    }

    /**
     * Set the redis resource manager to use
     *
     * @param null|RedisResourceManager $resourceManager
     * @return RedisOptions
     */
    public function setResourceManager(RedisResourceManager $resourceManager = null)
    {
        if ($this->resourceManager !== $resourceManager) {
            $this->triggerOptionEvent('resource_manager', $resourceManager);
            $this->resourceManager = $resourceManager;
        }
        return $this;
    }

    /**
     * Get the redis resource manager
     *
     * @return RedisResourceManager
     */
    public function getResourceManager()
    {
        if (!$this->resourceManager) {
            $this->resourceManager = new RedisResourceManager();
        }
        return $this->resourceManager;
    }

    /**
     * Get the redis resource id
     *
     * @return string
     */
    public function getResourceId()
    {
        return $this->resourceId;
    }

    /**
     * Set the redis resource id
     *
     * @param string $resourceId
     * @return RedisOptions
     */
    public function setResourceId($resourceId)
    {
        $resourceId = (string) $resourceId;
        if ($this->resourceId !== $resourceId) {
            $this->triggerOptionEvent('resource_id', $resourceId);
            $this->resourceId = $resourceId;
        }
        return $this;
    }

    /**
     * Get the persistent id
     *
     * @return string
     */
    public function getPersistentId()
    {
        return $this->getResourceManager()->getPersistentId($this->getResourceId());
    }

    /**
     * Set the persistent id
     *
     * @param string $persistentId
     * @return RedisOptions
     */
    public function setPersistentId($persistentId)
    {
        $this->triggerOptionEvent('persistent_id', $persistentId);
        $this->getResourceManager()->setPersistentId($this->getResourceId(), $persistentId);
        return $this;
    }

     /**
    * Set redis options
    *
    * @param array $libOptions
    * @return RedisOptions
    * @link http://github.com/nicolasff/phpredis#setoption
    */
    public function setLibOptions(array $libOptions)
    {
        $this->triggerOptionEvent('lib_option', $libOptions);
        $this->getResourceManager()->setLibOptions($this->getResourceId(), $libOptions);
        return $this;
    }

    /**
     * Get redis options
     *
     * @return array
     * @link http://github.com/nicolasff/phpredis#setoption
     */
    public function getLibOptions()
    {
        return $this->getResourceManager()->getLibOptions($this->getResourceId());
    }

    /**
     * Set server
     *
     * Server can be described as follows:
     * - URI:   /path/to/sock.sock
     * - Assoc: array('host' => <host>[, 'port' => <port>[, 'timeout' => <timeout>]])
     * - List:  array(<host>[, <port>, [, <timeout>]])
     *
     * @param string|array $server
     *
     * @return RedisOptions
     */
    public function setServer($server)
    {
        $this->getResourceManager()->setServer($this->getResourceId(), $server);
        return $this;
    }

    /**
     * Get server
     *
     * @return array array('host' => <host>[, 'port' => <port>[, 'timeout' => <timeout>]])
     */
    public function getServer()
    {
        return $this->getResourceManager()->getServer($this->getResourceId());
    }

    /**
     * Set resource database number
     *
     * @param int $database Database number
     *
     * @return RedisOptions
     */
    public function setDatabase($database)
    {
        $this->getResourceManager()->setDatabase($this->getResourceId(), $database);
        return $this;
    }

    /**
     * Get resource database number
     *
     * @return int Database number
     */
    public function getDatabase()
    {
        return $this->getResourceManager()->getDatabase($this->getResourceId());
    }

    /**
     * Set resource password
     *
     * @param string $password Password
     *
     * @return RedisOptions
     */
    public function setPassword($password)
    {
        $this->getResourceManager()->setPassword($this->getResourceId(), $password);
        return $this;
    }

    /**
     * Get resource password
     *
     * @return string
     */
    public function getPassword()
    {
        return $this->getResourceManager()->getPassword($this->getResourceId());
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

use Memcached as MemcachedResource;
use Zend\Cache\Exception;

/**
 * These are options specific to the APC adapter
 */
class MemcachedOptions extends AdapterOptions
{
    /**
     * The namespace separator
     * @var string
     */
    protected $namespaceSeparator = ':';

    /**
     * The memcached resource manager
     *
     * @var null|MemcachedResourceManager
     */
    protected $resourceManager;

    /**
     * The resource id of the resource manager
     *
     * @var string
     */
    protected $resourceId = 'default';

    /**
     * Set namespace.
     *
     * The option Memcached::OPT_PREFIX_KEY will be used as the namespace.
     * It can't be longer than 128 characters.
     *
     * @see AdapterOptions::setNamespace()
     * @see MemcachedOptions::setPrefixKey()
     */
    public function setNamespace($namespace)
    {
        $namespace = (string) $namespace;

        if (128 < strlen($namespace)) {
            throw new Exception\InvalidArgumentException(sprintf(
                '%s expects a prefix key of no longer than 128 characters',
                __METHOD__
            ));
        }

        return parent::setNamespace($namespace);
    }

    /**
     * Set namespace separator
     *
     * @param  string $namespaceSeparator
     * @return MemcachedOptions
     */
    public function setNamespaceSeparator($namespaceSeparator)
    {
        $namespaceSeparator = (string) $namespaceSeparator;
        if ($this->namespaceSeparator !== $namespaceSeparator) {
            $this->triggerOptionEvent('namespace_separator', $namespaceSeparator);
            $this->namespaceSeparator = $namespaceSeparator;
        }
        return $this;
    }

    /**
     * Get namespace separator
     *
     * @return string
     */
    public function getNamespaceSeparator()
    {
        return $this->namespaceSeparator;
    }

    /**
     * A memcached resource to share
     *
     * @param null|MemcachedResource $memcachedResource
     * @return MemcachedOptions
     * @deprecated Please use the resource manager instead
     */
    public function setMemcachedResource(MemcachedResource $memcachedResource = null)
    {
        trigger_error(
            'This method is deprecated and will be removed in the feature'
            . ', please use the resource manager instead',
            E_USER_DEPRECATED
        );

        if ($memcachedResource !== null) {
            $this->triggerOptionEvent('memcached_resource', $memcachedResource);
            $resourceManager = $this->getResourceManager();
            $resourceId      = $this->getResourceId();
            $resourceManager->setResource($resourceId, $memcachedResource);
        }
        return $this;
    }

    /**
     * Get memcached resource to share
     *
     * @return MemcachedResource
     * @deprecated Please use the resource manager instead
     */
    public function getMemcachedResource()
    {
        trigger_error(
            'This method is deprecated and will be removed in the feature'
            . ', please use the resource manager instead',
            E_USER_DEPRECATED
        );

        return $this->resourceManager->getResource($this->getResourceId());
    }

    /**
     * Set the memcached resource manager to use
     *
     * @param null|MemcachedResourceManager $resourceManager
     * @return MemcachedOptions
     */
    public function setResourceManager(MemcachedResourceManager $resourceManager = null)
    {
        if ($this->resourceManager !== $resourceManager) {
            $this->triggerOptionEvent('resource_manager', $resourceManager);
            $this->resourceManager = $resourceManager;
        }
        return $this;
    }

    /**
     * Get the memcached resource manager
     *
     * @return MemcachedResourceManager
     */
    public function getResourceManager()
    {
        if (!$this->resourceManager) {
            $this->resourceManager = new MemcachedResourceManager();
        }
        return $this->resourceManager;
    }

    /**
     * Get the memcached resource id
     *
     * @return string
     */
    public function getResourceId()
    {
        return $this->resourceId;
    }

    /**
     * Set the memcached resource id
     *
     * @param string $resourceId
     * @return MemcachedOptions
     */
    public function setResourceId($resourceId)
    {
        $resourceId = (string) $resourceId;
        if ($this->resourceId !== $resourceId) {
            $this->triggerOptionEvent('resource_id', $resourceId);
            $this->resourceId = $resourceId;
        }
        return $this;
    }

    /**
     * Get the persistent id
     *
     * @return string
     */
    public function getPersistentId()
    {
        return $this->getResourceManager()->getPersistentId($this->getResourceId());
    }

    /**
     * Set the persistent id
     *
     * @param string $persistentId
     * @return MemcachedOptions
     */
    public function setPersistentId($persistentId)
    {
        $this->triggerOptionEvent('persistent_id', $persistentId);
        $this->getResourceManager()->setPersistentId($this->getPersistentId(), $persistentId);
        return $this;
    }

    /**
     * Add a server to the list
     *
     * @param string $host
     * @param int $port
     * @param int $weight
     * @return MemcachedOptions
     * @deprecated Please use the resource manager instead
     */
    public function addServer($host, $port = 11211, $weight = 0)
    {
        trigger_error(
            'This method is deprecated and will be removed in the feature'
            . ', please use the resource manager instead',
            E_USER_DEPRECATED
        );

        $this->getResourceManager()->addServer($this->getResourceId(), array(
            'host'   => $host,
            'port'   => $port,
            'weight' => $weight
        ));

        return $this;
    }

    /**
    * Set a list of memcached servers to add on initialize
    *
    * @param string|array $servers list of servers
    * @return MemcachedOptions
    * @throws Exception\InvalidArgumentException
    */
    public function setServers($servers)
    {
        $this->getResourceManager()->setServers($this->getResourceId(), $servers);
        return $this;
    }

    /**
     * Get Servers
     *
     * @return array
     */
    public function getServers()
    {
        return $this->getResourceManager()->getServers($this->getResourceId());
    }

    /**
    * Set libmemcached options
    *
    * @param array $libOptions
    * @return MemcachedOptions
    * @link http://php.net/manual/memcached.constants.php
    */
    public function setLibOptions(array $libOptions)
    {
        $this->getResourceManager()->setLibOptions($this->getResourceId(), $libOptions);
        return $this;
    }

    /**
     * Set libmemcached option
     *
     * @param string|int $key
     * @param mixed $value
     * @return MemcachedOptions
     * @link http://php.net/manual/memcached.constants.php
     * @deprecated Please use lib_options or the resource manager instead
     */
    public function setLibOption($key, $value)
    {
        trigger_error(
            'This method is deprecated and will be removed in the feature'
            . ', please use "lib_options" or the resource manager instead',
            E_USER_DEPRECATED
        );

        $this->getResourceManager()->setLibOption($this->getResourceId(), $key, $value);
        return $this;
    }

    /**
     * Get libmemcached options
     *
     * @return array
     * @link http://php.net/manual/memcached.constants.php
     */
    public function getLibOptions()
    {
        return $this->getResourceManager()->getLibOptions($this->getResourceId());
    }

    /**
    * Get libmemcached option
    *
    * @param string|int $key
    * @return mixed
    * @link http://php.net/manual/memcached.constants.php
    * @deprecated Please use lib_options or the resource manager instead
    */
    public function getLibOption($key)
    {
        trigger_error(
            'This method is deprecated and will be removed in the feature'
            . ', please use "lib_options" or the resource manager instead',
            E_USER_DEPRECATED
        );

        return $this->getResourceManager()->getLibOption($this->getResourceId(), $key);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

use APCIterator as BaseApcIterator;
use Zend\Cache\Storage\IteratorInterface;

class ApcIterator implements IteratorInterface
{

    /**
     * The apc storage instance
     *
     * @var Apc
     */
    protected $storage;

    /**
     * The iterator mode
     *
     * @var int
     */
    protected $mode = IteratorInterface::CURRENT_AS_KEY;

    /**
     * The base APCIterator instance
     *
     * @var BaseApcIterator
     */
    protected $baseIterator;

    /**
     * The length of the namespace prefix
     *
     * @var int
     */
    protected $prefixLength;

    /**
     * Constructor
     *
     * @param Apc             $storage
     * @param BaseApcIterator $baseIterator
     * @param string          $prefix
     */
    public function __construct(Apc $storage, BaseApcIterator $baseIterator, $prefix)
    {
        $this->storage      = $storage;
        $this->baseIterator = $baseIterator;
        $this->prefixLength = strlen($prefix);
    }

    /**
     * Get storage instance
     *
     * @return Apc
     */
    public function getStorage()
    {
        return $this->storage;
    }

    /**
     * Get iterator mode
     *
     * @return int Value of IteratorInterface::CURRENT_AS_*
     */
    public function getMode()
    {
        return $this->mode;
    }

    /**
     * Set iterator mode
     *
     * @param int $mode
     * @return ApcIterator Fluent interface
     */
    public function setMode($mode)
    {
        $this->mode = (int) $mode;
        return $this;
    }

    /* Iterator */

    /**
     * Get current key, value or metadata.
     *
     * @return mixed
     */
    public function current()
    {
        if ($this->mode == IteratorInterface::CURRENT_AS_SELF) {
            return $this;
        }

        $key = $this->key();

        if ($this->mode == IteratorInterface::CURRENT_AS_VALUE) {
            return $this->storage->getItem($key);
        } elseif ($this->mode == IteratorInterface::CURRENT_AS_METADATA) {
            return $this->storage->getMetadata($key);
        }

        return $key;
    }

    /**
     * Get current key
     *
     * @return string
     */
    public function key()
    {
        $key = $this->baseIterator->key();

        // remove namespace prefix
        return substr($key, $this->prefixLength);
    }

    /**
     * Move forward to next element
     *
     * @return void
     */
    public function next()
    {
        $this->baseIterator->next();
    }

    /**
     * Checks if current position is valid
     *
     * @return bool
     */
    public function valid()
    {
        return $this->baseIterator->valid();
    }

    /**
     * Rewind the Iterator to the first element.
     *
     * @return void
     */
    public function rewind()
    {
        return $this->baseIterator->rewind();
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

use stdClass;
use Zend\Cache\Exception;
use Zend\Cache\Storage\Capabilities;
use Zend\Cache\Storage\ClearByPrefixInterface;
use Zend\Cache\Storage\FlushableInterface;
use Zend\Cache\Storage\IterableInterface;
use Zend\Session\Container as SessionContainer;

class Session extends AbstractAdapter implements
    ClearByPrefixInterface,
    FlushableInterface,
    IterableInterface
{

    /**
     * Set options.
     *
     * @param  array|\Traversable|SessionOptions $options
     * @return Memory
     * @see    getOptions()
     */
    public function setOptions($options)
    {
        if (!$options instanceof SessionOptions) {
            $options = new SessionOptions($options);
        }

        return parent::setOptions($options);
    }

    /**
     * Get options.
     *
     * @return SessionOptions
     * @see setOptions()
     */
    public function getOptions()
    {
        if (!$this->options) {
            $this->setOptions(new SessionOptions());
        }
        return $this->options;
    }

    /**
     * Get the session container
     *
     * @return SessionContainer
     */
    protected function getSessionContainer()
    {
        $sessionContainer = $this->getOptions()->getSessionContainer();
        if (!$sessionContainer) {
            throw new Exception\RuntimeException("No session container configured");
        }
        return $sessionContainer;
    }

    /* IterableInterface */

    /**
     * Get the storage iterator
     *
     * @return KeyListIterator
     */
    public function getIterator()
    {
        $cntr = $this->getSessionContainer();
        $ns   = $this->getOptions()->getNamespace();

        if ($cntr->offsetExists($ns)) {
            $keys = array_keys($cntr->offsetGet($ns));
        } else {
            $keys = array();
        }

        return new KeyListIterator($this, $keys);
    }

    /* FlushableInterface */

    /**
     * Flush the whole session container
     *
     * @return bool
     */
    public function flush()
    {
        $this->getSessionContainer()->exchangeArray(array());
        return true;
    }

    /* ClearByPrefixInterface */

    /**
     * Remove items matching given prefix
     *
     * @param string $prefix
     * @return bool
     */
    public function clearByPrefix($prefix)
    {
        $prefix = (string) $prefix;
        if ($prefix === '') {
            throw new Exception\InvalidArgumentException('No prefix given');
        }

        $cntr = $this->getSessionContainer();
        $ns   = $this->getOptions()->getNamespace();

        if (!$cntr->offsetExists($ns)) {
            return true;
        }

        $data    = $cntr->offsetGet($ns);
        $prefixL = strlen($prefix);
        foreach ($data as $key => & $item) {
            if (substr($key, 0, $prefixL) === $prefix) {
                unset($data[$key]);
            }
        }
        $cntr->offsetSet($ns, $data);

        return true;
    }

    /* reading */

    /**
     * Internal method to get an item.
     *
     * @param  string  $normalizedKey
     * @param  bool $success
     * @param  mixed   $casToken
     * @return mixed Data on success, null on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null)
    {
        $cntr    = $this->getSessionContainer();
        $ns      = $this->getOptions()->getNamespace();

        if (!$cntr->offsetExists($ns)) {
            $success = false;
            return null;
        }

        $data    = $cntr->offsetGet($ns);
        $success = array_key_exists($normalizedKey, $data);
        if (!$success) {
            return null;
        }

        $casToken = $value = $data[$normalizedKey];
        return $value;
    }

    /**
     * Internal method to get multiple items.
     *
     * @param  array $normalizedKeys
     * @return array Associative array of keys and values
     * @throws Exception\ExceptionInterface
     */
    protected function internalGetItems(array & $normalizedKeys)
    {
        $cntr = $this->getSessionContainer();
        $ns   = $this->getOptions()->getNamespace();

        if (!$cntr->offsetExists($ns)) {
            return array();
        }

        $data   = $cntr->offsetGet($ns);
        $result = array();
        foreach ($normalizedKeys as $normalizedKey) {
            if (array_key_exists($normalizedKey, $data)) {
                $result[$normalizedKey] = $data[$normalizedKey];
            }
        }

        return $result;
    }

    /**
     * Internal method to test if an item exists.
     *
     * @param  string $normalizedKey
     * @return bool
     */
    protected function internalHasItem(& $normalizedKey)
    {
        $cntr = $this->getSessionContainer();
        $ns   = $this->getOptions()->getNamespace();

        if (!$cntr->offsetExists($ns)) {
            return false;
        }

        $data = $cntr->offsetGet($ns);
        return array_key_exists($normalizedKey, $data);
    }

    /**
     * Internal method to test multiple items.
     *
     * @param array $normalizedKeys
     * @return array Array of found keys
     */
    protected function internalHasItems(array & $normalizedKeys)
    {
        $cntr = $this->getSessionContainer();
        $ns   = $this->getOptions()->getNamespace();

        if (!$cntr->offsetExists($ns)) {
            return array();
        }

        $data   = $cntr->offsetGet($ns);
        $result = array();
        foreach ($normalizedKeys as $normalizedKey) {
            if (array_key_exists($normalizedKey, $data)) {
                $result[] = $normalizedKey;
            }
        }

        return $result;
    }

    /**
     * Get metadata of an item.
     *
     * @param  string $normalizedKey
     * @return array|bool Metadata on success, false on failure
     * @throws Exception\ExceptionInterface
     *
     * @triggers getMetadata.pre(PreEvent)
     * @triggers getMetadata.post(PostEvent)
     * @triggers getMetadata.exception(ExceptionEvent)
     */
    protected function internalGetMetadata(& $normalizedKey)
    {
        return $this->internalHasItem($normalizedKey) ? array() : false;
    }

    /* writing */

    /**
     * Internal method to store an item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalSetItem(& $normalizedKey, & $value)
    {
        $cntr = $this->getSessionContainer();
        $ns   = $this->getOptions()->getNamespace();
        $data = $cntr->offsetExists($ns) ? $cntr->offsetGet($ns) : array();
        $data[$normalizedKey] = $value;
        $cntr->offsetSet($ns, $data);
        return true;
    }

    /**
     * Internal method to store multiple items.
     *
     * @param  array $normalizedKeyValuePairs
     * @return array Array of not stored keys
     * @throws Exception\ExceptionInterface
     */
    protected function internalSetItems(array & $normalizedKeyValuePairs)
    {
        $cntr = $this->getSessionContainer();
        $ns   = $this->getOptions()->getNamespace();

        if ($cntr->offsetExists($ns)) {
            $data = array_merge($cntr->offsetGet($ns), $normalizedKeyValuePairs);
        } else {
            $data = $normalizedKeyValuePairs;
        }
        $cntr->offsetSet($ns, $data);

        return array();
    }

    /**
     * Add an item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalAddItem(& $normalizedKey, & $value)
    {
        $cntr = $this->getSessionContainer();
        $ns   = $this->getOptions()->getNamespace();

        if ($cntr->offsetExists($ns)) {
            $data = $cntr->offsetGet($ns);

            if (array_key_exists($normalizedKey, $data)) {
                return false;
            }

            $data[$normalizedKey] = $value;
        } else {
            $data = array($normalizedKey => $value);
        }

        $cntr->offsetSet($ns, $data);
        return true;
    }

    /**
     * Internal method to add multiple items.
     *
     * @param  array $normalizedKeyValuePairs
     * @return array Array of not stored keys
     * @throws Exception\ExceptionInterface
     */
    protected function internalAddItems(array & $normalizedKeyValuePairs)
    {
        $cntr = $this->getSessionContainer();
        $ns   = $this->getOptions()->getNamespace();

        $result = array();
        if ($cntr->offsetExists($ns)) {
            $data = $cntr->offsetGet($ns);

            foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
                if (array_key_exists($normalizedKey, $data)) {
                    $result[] = $normalizedKey;
                } else {
                    $data[$normalizedKey] = $value;
                }
            }
        } else {
            $data = $normalizedKeyValuePairs;
        }

        $cntr->offsetSet($ns, $data);
        return $result;
    }

    /**
     * Internal method to replace an existing item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalReplaceItem(& $normalizedKey, & $value)
    {
        $cntr = $this->getSessionContainer();
        $ns   = $this->getOptions()->getNamespace();

        if (!$cntr->offsetExists($ns)) {
            return false;
        }

        $data = $cntr->offsetGet($ns);
        if (!array_key_exists($normalizedKey, $data)) {
            return false;
        }
        $data[$normalizedKey] = $value;
        $cntr->offsetSet($ns, $data);

        return true;
    }

    /**
     * Internal method to replace multiple existing items.
     *
     * @param  array $normalizedKeyValuePairs
     * @return array Array of not stored keys
     * @throws Exception\ExceptionInterface
     */
    protected function internalReplaceItems(array & $normalizedKeyValuePairs)
    {
        $cntr = $this->getSessionContainer();
        $ns   = $this->getOptions()->getNamespace();
        if (!$cntr->offsetExists($ns)) {
            return array_keys($normalizedKeyValuePairs);
        }

        $data   = $cntr->offsetGet($ns);
        $result = array();
        foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
            if (!array_key_exists($normalizedKey, $data)) {
                $result[] = $normalizedKey;
            } else {
                $data[$normalizedKey] = $value;
            }
        }
        $cntr->offsetSet($ns, $data);

        return $result;
    }

    /**
     * Internal method to remove an item.
     *
     * @param  string $normalizedKey
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalRemoveItem(& $normalizedKey)
    {
        $cntr = $this->getSessionContainer();
        $ns   = $this->getOptions()->getNamespace();

        if (!$cntr->offsetExists($ns)) {
            return false;
        }

        $data = $cntr->offsetGet($ns);
        if (!array_key_exists($normalizedKey, $data)) {
            return false;
        }

        unset($data[$normalizedKey]);

        if (!$data) {
            $cntr->offsetUnset($ns);
        } else {
            $cntr->offsetSet($ns, $data);
        }

        return true;
    }

    /**
     * Internal method to increment an item.
     *
     * @param  string $normalizedKey
     * @param  int    $value
     * @return int|bool The new value on success, false on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalIncrementItem(& $normalizedKey, & $value)
    {
        $cntr = $this->getSessionContainer();
        $ns   = $this->getOptions()->getNamespace();

        if ($cntr->offsetExists($ns)) {
            $data = $cntr->offsetGet($ns);
        } else {
            $data = array();
        }

        if (array_key_exists($normalizedKey, $data)) {
            $data[$normalizedKey]+= $value;
            $newValue = $data[$normalizedKey];
        } else {
            // initial value
            $newValue             = $value;
            $data[$normalizedKey] = $newValue;
        }

        $cntr->offsetSet($ns, $data);
        return $newValue;
    }

    /**
     * Internal method to decrement an item.
     *
     * @param  string $normalizedKey
     * @param  int    $value
     * @return int|bool The new value on success, false on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalDecrementItem(& $normalizedKey, & $value)
    {
        $cntr = $this->getSessionContainer();
        $ns   = $this->getOptions()->getNamespace();

        if ($cntr->offsetExists($ns)) {
            $data = $cntr->offsetGet($ns);
        } else {
            $data = array();
        }

        if (array_key_exists($normalizedKey, $data)) {
            $data[$normalizedKey]-= $value;
            $newValue = $data[$normalizedKey];
        } else {
            // initial value
            $newValue             = -$value;
            $data[$normalizedKey] = $newValue;
        }

        $cntr->offsetSet($ns, $data);
        return $newValue;
    }

    /* status */

    /**
     * Internal method to get capabilities of this adapter
     *
     * @return Capabilities
     */
    protected function internalGetCapabilities()
    {
        if ($this->capabilities === null) {
            $this->capabilityMarker = new stdClass();
                $this->capabilities = new Capabilities(
                $this,
                $this->capabilityMarker,
                array(
                    'supportedDatatypes' => array(
                        'NULL'     => true,
                        'boolean'  => true,
                        'integer'  => true,
                        'double'   => true,
                        'string'   => true,
                        'array'    => 'array',
                        'object'   => 'object',
                        'resource' => false,
                    ),
                    'supportedMetadata'  => array(),
                    'minTtl'             => 0,
                    'maxKeyLength'       => 0,
                    'namespaceIsPrefix'  => false,
                    'namespaceSeparator' => '',
                )
            );
        }

        return $this->capabilities;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

/**
 * These are options specific to the APC adapter
 */
class ApcOptions extends AdapterOptions
{
    /**
     * Namespace separator
     *
     * @var string
     */
    protected $namespaceSeparator = ':';

    /**
     * Set namespace separator
     *
     * @param  string $namespaceSeparator
     * @return ApcOptions
     */
    public function setNamespaceSeparator($namespaceSeparator)
    {
        $namespaceSeparator = (string) $namespaceSeparator;
        $this->triggerOptionEvent('namespace_separator', $namespaceSeparator);
        $this->namespaceSeparator = $namespaceSeparator;
        return $this;
    }

    /**
     * Get namespace separator
     *
     * @return string
     */
    public function getNamespaceSeparator()
    {
        return $this->namespaceSeparator;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

use Zend\Cache\Exception;

/**
 * These are options specific to the APC adapter
 */
class MemoryOptions extends AdapterOptions
{
    /**
     * memory limit
     *
     * @var null|int
     */
    protected $memoryLimit = null;

    /**
     * Set memory limit
     *
     * - A number less or equal 0 will disable the memory limit
     * - When a number is used, the value is measured in bytes. Shorthand notation may also be used.
     * - If the used memory of PHP exceeds this limit an OutOfSpaceException
     *   will be thrown.
     *
     * @link http://php.net/manual/faq.using.php#faq.using.shorthandbytes
     * @param  string|int $memoryLimit
     * @return MemoryOptions
     */
    public function setMemoryLimit($memoryLimit)
    {
        $memoryLimit = $this->normalizeMemoryLimit($memoryLimit);

        if ($this->memoryLimit != $memoryLimit) {
            $this->triggerOptionEvent('memory_limit', $memoryLimit);
            $this->memoryLimit = $memoryLimit;
        }

        return $this;
    }

    /**
     * Get memory limit
     *
     * If the used memory of PHP exceeds this limit an OutOfSpaceException
     * will be thrown.
     *
     * @return int
     */
    public function getMemoryLimit()
    {
        if ($this->memoryLimit === null) {
            // By default use half of PHP's memory limit if possible
            $memoryLimit = $this->normalizeMemoryLimit(ini_get('memory_limit'));
            if ($memoryLimit >= 0) {
                $this->memoryLimit = (int) ($memoryLimit / 2);
            } else {
                // disable memory limit
                $this->memoryLimit = 0;
            }
        }

        return $this->memoryLimit;
    }

    /**
     * Normalized a given value of memory limit into the number of bytes
     *
     * @param string|int $value
     * @throws Exception\InvalidArgumentException
     * @return int
     */
    protected function normalizeMemoryLimit($value)
    {
        if (is_numeric($value)) {
            return (int) $value;
        }

        if (!preg_match('/(\-?\d+)\s*(\w*)/', ini_get('memory_limit'), $matches)) {
            throw new Exception\InvalidArgumentException("Invalid  memory limit '{$value}'");
        }

        $value = (int) $matches[1];
        if ($value <= 0) {
            return 0;
        }

        switch (strtoupper($matches[2])) {
            case 'G':
                $value*= 1024;
                // no break

            case 'M':
                $value*= 1024;
                // no break

            case 'K':
                $value*= 1024;
                // no break
        }

        return $value;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

use stdClass;
use Zend\Cache\Exception;
use Zend\Cache\Storage\AvailableSpaceCapableInterface;
use Zend\Cache\Storage\Capabilities;
use Zend\Cache\Storage\ClearByNamespaceInterface;
use Zend\Cache\Storage\ClearByPrefixInterface;
use Zend\Cache\Storage\ClearExpiredInterface;
use Zend\Cache\Storage\FlushableInterface;
use Zend\Cache\Storage\IterableInterface;
use Zend\Cache\Storage\TaggableInterface;
use Zend\Cache\Storage\TotalSpaceCapableInterface;

class Memory extends AbstractAdapter implements
    AvailableSpaceCapableInterface,
    ClearByPrefixInterface,
    ClearByNamespaceInterface,
    ClearExpiredInterface,
    FlushableInterface,
    IterableInterface,
    TaggableInterface,
    TotalSpaceCapableInterface
{
    /**
     * Data Array
     *
     * Format:
     * array(
     *     <NAMESPACE> => array(
     *         <KEY> => array(
     *             0 => <VALUE>
     *             1 => <MICROTIME>
     *             ['tags' => <TAGS>]
     *         )
     *     )
     * )
     *
     * @var array
     */
    protected $data = array();

    /**
     * Set options.
     *
     * @param  array|\Traversable|MemoryOptions $options
     * @return Memory
     * @see    getOptions()
     */
    public function setOptions($options)
    {
        if (!$options instanceof MemoryOptions) {
            $options = new MemoryOptions($options);
        }

        return parent::setOptions($options);
    }

    /**
     * Get options.
     *
     * @return MemoryOptions
     * @see setOptions()
     */
    public function getOptions()
    {
        if (!$this->options) {
            $this->setOptions(new MemoryOptions());
        }
        return $this->options;
    }

    /* TotalSpaceCapableInterface */

    /**
     * Get total space in bytes
     *
     * @return int|float
     */
    public function getTotalSpace()
    {
        return $this->getOptions()->getMemoryLimit();
    }

    /* AvailableSpaceCapableInterface */

    /**
     * Get available space in bytes
     *
     * @return int|float
     */
    public function getAvailableSpace()
    {
        $total = $this->getOptions()->getMemoryLimit();
        $avail = $total - (float) memory_get_usage(true);
        return ($avail > 0) ? $avail : 0;
    }

    /* IterableInterface */

    /**
     * Get the storage iterator
     *
     * @return KeyListIterator
     */
    public function getIterator()
    {
        $ns   = $this->getOptions()->getNamespace();
        $keys = array();

        if (isset($this->data[$ns])) {
            foreach ($this->data[$ns] as $key => & $tmp) {
                if ($this->internalHasItem($key)) {
                    $keys[] = $key;
                }
            }
        }

        return new KeyListIterator($this, $keys);
    }

    /* FlushableInterface */

    /**
     * Flush the whole storage
     *
     * @return bool
     */
    public function flush()
    {
        $this->data = array();
        return true;
    }

    /* ClearExpiredInterface */

    /**
     * Remove expired items
     *
     * @return bool
     */
    public function clearExpired()
    {
        $ttl = $this->getOptions()->getTtl();
        if ($ttl <= 0) {
            return true;
        }

        $ns = $this->getOptions()->getNamespace();
        if (!isset($this->data[$ns])) {
            return true;
        }

        $data = & $this->data[$ns];
        foreach ($data as $key => & $item) {
            if (microtime(true) >= $data[$key][1] + $ttl) {
                unset($data[$key]);
            }
        }

        return true;
    }

    /* ClearByNamespaceInterface */

    public function clearByNamespace($namespace)
    {
        $namespace = (string) $namespace;
        if ($namespace === '') {
            throw new Exception\InvalidArgumentException('No namespace given');
        }

        unset($this->data[$namespace]);
        return true;
    }

    /* ClearByPrefixInterface */

    /**
     * Remove items matching given prefix
     *
     * @param string $prefix
     * @return bool
     */
    public function clearByPrefix($prefix)
    {
        $prefix = (string) $prefix;
        if ($prefix === '') {
            throw new Exception\InvalidArgumentException('No prefix given');
        }

        $ns = $this->getOptions()->getNamespace();
        if (!isset($this->data[$ns])) {
            return true;
        }

        $prefixL = strlen($prefix);
        $data    = & $this->data[$ns];
        foreach ($data as $key => & $item) {
            if (substr($key, 0, $prefixL) === $prefix) {
                unset($data[$key]);
            }
        }

        return true;
    }

    /* TaggableInterface */

    /**
     * Set tags to an item by given key.
     * An empty array will remove all tags.
     *
     * @param string   $key
     * @param string[] $tags
     * @return bool
     */
    public function setTags($key, array $tags)
    {
        $ns = $this->getOptions()->getNamespace();
        if (!$this->data[$ns]) {
            return false;
        }

        $data = & $this->data[$ns];
        if (isset($data[$key])) {
            $data[$key]['tags'] = $tags;
            return true;
        }

        return false;
    }

    /**
     * Get tags of an item by given key
     *
     * @param string $key
     * @return string[]|FALSE
    */
    public function getTags($key)
    {
        $ns = $this->getOptions()->getNamespace();
        if (!$this->data[$ns]) {
            return false;
        }

        $data = & $this->data[$ns];
        if (!isset($data[$key])) {
            return false;
        }

        return isset($data[$key]['tags']) ? $data[$key]['tags'] : array();
    }

    /**
     * Remove items matching given tags.
     *
     * If $disjunction only one of the given tags must match
     * else all given tags must match.
     *
     * @param string[] $tags
     * @param  bool  $disjunction
     * @return bool
    */
    public function clearByTags(array $tags, $disjunction = false)
    {
        $ns = $this->getOptions()->getNamespace();
        if (!$this->data[$ns]) {
            return true;
        }

        $tagCount = count($tags);
        $data     = & $this->data[$ns];
        foreach ($data as $key => & $item) {
            if (isset($item['tags'])) {
                $diff = array_diff($tags, $item['tags']);
                if (($disjunction && count($diff) < $tagCount) || (!$disjunction && !$diff)) {
                    unset($data[$key]);
                }
            }
        }

        return true;
    }

    /* reading */

    /**
     * Internal method to get an item.
     *
     * @param  string  $normalizedKey
     * @param  bool $success
     * @param  mixed   $casToken
     * @return mixed Data on success, null on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null)
    {
        $options = $this->getOptions();
        $ns      = $options->getNamespace();
        $success = isset($this->data[$ns][$normalizedKey]);
        if ($success) {
            $data = & $this->data[$ns][$normalizedKey];
            $ttl  = $options->getTtl();
            if ($ttl && microtime(true) >= ($data[1] + $ttl)) {
                $success = false;
            }
        }

        if (!$success) {
            return null;
        }

        $casToken = $data[0];
        return $data[0];
    }

    /**
     * Internal method to get multiple items.
     *
     * @param  array $normalizedKeys
     * @return array Associative array of keys and values
     * @throws Exception\ExceptionInterface
     */
    protected function internalGetItems(array & $normalizedKeys)
    {
        $options = $this->getOptions();
        $ns      = $options->getNamespace();
        if (!isset($this->data[$ns])) {
            return array();
        }

        $data = & $this->data[$ns];
        $ttl  = $options->getTtl();
        $now  = microtime(true);

        $result = array();
        foreach ($normalizedKeys as $normalizedKey) {
            if (isset($data[$normalizedKey])) {
                if (!$ttl || $now < ($data[$normalizedKey][1] + $ttl)) {
                    $result[$normalizedKey] = $data[$normalizedKey][0];
                }
            }
        }

        return $result;
    }

    /**
     * Internal method to test if an item exists.
     *
     * @param  string $normalizedKey
     * @return bool
     */
    protected function internalHasItem(& $normalizedKey)
    {
        $options = $this->getOptions();
        $ns      = $options->getNamespace();
        if (!isset($this->data[$ns][$normalizedKey])) {
            return false;
        }

        // check if expired
        $ttl = $options->getTtl();
        if ($ttl && microtime(true) >= ($this->data[$ns][$normalizedKey][1] + $ttl)) {
            return false;
        }

        return true;
    }

    /**
     * Internal method to test multiple items.
     *
     * @param array $normalizedKeys
     * @return array Array of found keys
     */
    protected function internalHasItems(array & $normalizedKeys)
    {
        $options = $this->getOptions();
        $ns      = $options->getNamespace();
        if (!isset($this->data[$ns])) {
            return array();
        }

        $data = & $this->data[$ns];
        $ttl  = $options->getTtl();
        $now  = microtime(true);

        $result = array();
        foreach ($normalizedKeys as $normalizedKey) {
            if (isset($data[$normalizedKey])) {
                if (!$ttl || $now < ($data[$normalizedKey][1] + $ttl)) {
                    $result[] = $normalizedKey;
                }
            }
        }

        return $result;
    }

    /**
     * Get metadata of an item.
     *
     * @param  string $normalizedKey
     * @return array|bool Metadata on success, false on failure
     * @throws Exception\ExceptionInterface
     *
     * @triggers getMetadata.pre(PreEvent)
     * @triggers getMetadata.post(PostEvent)
     * @triggers getMetadata.exception(ExceptionEvent)
     */
    protected function internalGetMetadata(& $normalizedKey)
    {
        if (!$this->internalHasItem($normalizedKey)) {
            return false;
        }

        $ns = $this->getOptions()->getNamespace();
        return array(
            'mtime' => $this->data[$ns][$normalizedKey][1],
        );
    }

    /* writing */

    /**
     * Internal method to store an item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalSetItem(& $normalizedKey, & $value)
    {
        $options = $this->getOptions();

        if (!$this->hasAvailableSpace()) {
            $memoryLimit = $options->getMemoryLimit();
            throw new Exception\OutOfSpaceException(
                "Memory usage exceeds limit ({$memoryLimit})."
            );
        }

        $ns = $options->getNamespace();
        $this->data[$ns][$normalizedKey] = array($value, microtime(true));

        return true;
    }

    /**
     * Internal method to store multiple items.
     *
     * @param  array $normalizedKeyValuePairs
     * @return array Array of not stored keys
     * @throws Exception\ExceptionInterface
     */
    protected function internalSetItems(array & $normalizedKeyValuePairs)
    {
        $options = $this->getOptions();

        if (!$this->hasAvailableSpace()) {
            $memoryLimit = $options->getMemoryLimit();
            throw new Exception\OutOfSpaceException(
                "Memory usage exceeds limit ({$memoryLimit})."
            );
        }

        $ns = $options->getNamespace();
        if (!isset($this->data[$ns])) {
            $this->data[$ns] = array();
        }

        $data = & $this->data[$ns];
        $now  = microtime(true);
        foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
            $data[$normalizedKey] = array($value, $now);
        }

        return array();
    }

    /**
     * Add an item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalAddItem(& $normalizedKey, & $value)
    {
        $options = $this->getOptions();

        if (!$this->hasAvailableSpace()) {
            $memoryLimit = $options->getMemoryLimit();
            throw new Exception\OutOfSpaceException(
                "Memory usage exceeds limit ({$memoryLimit})."
            );
        }

        $ns = $options->getNamespace();
        if (isset($this->data[$ns][$normalizedKey])) {
            return false;
        }

        $this->data[$ns][$normalizedKey] = array($value, microtime(true));
        return true;
    }

    /**
     * Internal method to add multiple items.
     *
     * @param  array $normalizedKeyValuePairs
     * @return array Array of not stored keys
     * @throws Exception\ExceptionInterface
     */
    protected function internalAddItems(array & $normalizedKeyValuePairs)
    {
        $options = $this->getOptions();

        if (!$this->hasAvailableSpace()) {
            $memoryLimit = $options->getMemoryLimit();
            throw new Exception\OutOfSpaceException(
                "Memory usage exceeds limit ({$memoryLimit})."
            );
        }

        $ns = $options->getNamespace();
        if (!isset($this->data[$ns])) {
            $this->data[$ns] = array();
        }

        $result = array();
        $data   = & $this->data[$ns];
        $now    = microtime(true);
        foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
            if (isset($data[$normalizedKey])) {
                $result[] = $normalizedKey;
            } else {
                $data[$normalizedKey] = array($value, $now);
            }
        }

        return $result;
    }

    /**
     * Internal method to replace an existing item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalReplaceItem(& $normalizedKey, & $value)
    {
        $ns = $this->getOptions()->getNamespace();
        if (!isset($this->data[$ns][$normalizedKey])) {
            return false;
        }
        $this->data[$ns][$normalizedKey] = array($value, microtime(true));

        return true;
    }

    /**
     * Internal method to replace multiple existing items.
     *
     * @param  array $normalizedKeyValuePairs
     * @return array Array of not stored keys
     * @throws Exception\ExceptionInterface
     */
    protected function internalReplaceItems(array & $normalizedKeyValuePairs)
    {
        $ns = $this->getOptions()->getNamespace();
        if (!isset($this->data[$ns])) {
            return array_keys($normalizedKeyValuePairs);
        }

        $result = array();
        $data   = & $this->data[$ns];
        foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
            if (!isset($data[$normalizedKey])) {
                $result[] = $normalizedKey;
            } else {
                $data[$normalizedKey] = array($value, microtime(true));
            }
        }

        return $result;
    }

    /**
     * Internal method to reset lifetime of an item
     *
     * @param  string $normalizedKey
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalTouchItem(& $normalizedKey)
    {
        $ns = $this->getOptions()->getNamespace();

        if (!isset($this->data[$ns][$normalizedKey])) {
            return false;
        }

        $this->data[$ns][$normalizedKey][1] = microtime(true);
        return true;
    }

    /**
     * Internal method to remove an item.
     *
     * @param  string $normalizedKey
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalRemoveItem(& $normalizedKey)
    {
        $ns = $this->getOptions()->getNamespace();
        if (!isset($this->data[$ns][$normalizedKey])) {
            return false;
        }

        unset($this->data[$ns][$normalizedKey]);

        // remove empty namespace
        if (!$this->data[$ns]) {
            unset($this->data[$ns]);
        }

        return true;
    }

    /**
     * Internal method to increment an item.
     *
     * @param  string $normalizedKey
     * @param  int    $value
     * @return int|bool The new value on success, false on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalIncrementItem(& $normalizedKey, & $value)
    {
        $ns   = $this->getOptions()->getNamespace();
        $data = & $this->data[$ns];
        if (isset($data[$normalizedKey])) {
            $data[$normalizedKey][0]+= $value;
            $data[$normalizedKey][1] = microtime(true);
            $newValue = $data[$normalizedKey][0];
        } else {
            // initial value
            $newValue             = $value;
            $data[$normalizedKey] = array($newValue, microtime(true));
        }

        return $newValue;
    }

    /**
     * Internal method to decrement an item.
     *
     * @param  string $normalizedKey
     * @param  int    $value
     * @return int|bool The new value on success, false on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalDecrementItem(& $normalizedKey, & $value)
    {
        $ns   = $this->getOptions()->getNamespace();
        $data = & $this->data[$ns];
        if (isset($data[$normalizedKey])) {
            $data[$normalizedKey][0]-= $value;
            $data[$normalizedKey][1] = microtime(true);
            $newValue = $data[$normalizedKey][0];
        } else {
            // initial value
            $newValue             = -$value;
            $data[$normalizedKey] = array($newValue, microtime(true));
        }

        return $newValue;
    }

    /* status */

    /**
     * Internal method to get capabilities of this adapter
     *
     * @return Capabilities
     */
    protected function internalGetCapabilities()
    {
        if ($this->capabilities === null) {
            $this->capabilityMarker = new stdClass();
                $this->capabilities = new Capabilities(
                $this,
                $this->capabilityMarker,
                array(
                    'supportedDatatypes' => array(
                        'NULL'     => true,
                        'boolean'  => true,
                        'integer'  => true,
                        'double'   => true,
                        'string'   => true,
                        'array'    => true,
                        'object'   => true,
                        'resource' => true,
                    ),
                    'supportedMetadata'  => array('mtime'),
                    'minTtl'             => 1,
                    'maxTtl'             => PHP_INT_MAX,
                    'staticTtl'          => false,
                    'ttlPrecision'       => 0.05,
                    'expiredRead'        => true,
                    'maxKeyLength'       => 0,
                    'namespaceIsPrefix'  => false,
                    'namespaceSeparator' => '',
                )
            );
        }

        return $this->capabilities;
    }

    /* internal */

    /**
     * Has space available to store items?
     *
     * @return bool
     */
    protected function hasAvailableSpace()
    {
        $total = $this->getOptions()->getMemoryLimit();

        // check memory limit disabled
        if ($total <= 0) {
            return true;
        }

        $free = $total - (float) memory_get_usage(true);
        return ($free > 0);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

use Zend\Cache\Exception;

/**
 * These are options specific to the APC adapter
 */
class DbaOptions extends AdapterOptions
{
    /**
     * Namespace separator
     *
     * @var string
     */
    protected $namespaceSeparator = ':';

    /**
     * Pathname to the database file
     *
     * @var string
     */
    protected $pathname = '';

    /**
     * The mode to open the database
     *
     * @var string
     */
    protected $mode = 'c';

    /**
     * The name of the handler which shall be used for accessing the database.
     *
     * @var string
     */
    protected $handler = 'flatfile';

    /**
     * Set namespace separator
     *
     * @param  string $namespaceSeparator
     * @return DbaOptions
     */
    public function setNamespaceSeparator($namespaceSeparator)
    {
        $namespaceSeparator = (string) $namespaceSeparator;
        $this->triggerOptionEvent('namespace_separator', $namespaceSeparator);
        $this->namespaceSeparator = $namespaceSeparator;
        return $this;
    }

    /**
     * Get namespace separator
     *
     * @return string
     */
    public function getNamespaceSeparator()
    {
        return $this->namespaceSeparator;
    }

    /**
     * Set pathname to database file
     *
     * @param string $pathname
     * @return DbaOptions
     */
    public function setPathname($pathname)
    {
        $this->pathname = (string) $pathname;
        $this->triggerOptionEvent('pathname', $pathname);
        return $this;
    }

    /**
     * Get pathname to database file
     *
     * @return string
     */
    public function getPathname()
    {
        return $this->pathname;
    }

    /**
     *
     *
     * @param string $mode
     * @return \Zend\Cache\Storage\Adapter\DbaOptions
     */
    public function setMode($mode)
    {
        $this->mode = (string) $mode;
        $this->triggerOptionEvent('mode', $mode);
        return $this;
    }

    public function getMode()
    {
        return $this->mode;
    }

    public function setHandler($handler)
    {
        $handler = (string) $handler;

        if (!function_exists('dba_handlers') || !in_array($handler, dba_handlers())) {
            throw new Exception\ExtensionNotLoadedException("DBA-Handler '{$handler}' not supported");
        }

        $this->triggerOptionEvent('handler', $handler);
        $this->handler = $handler;
        return $this;
    }

    public function getHandler()
    {
        return $this->handler;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Storage\Adapter;

use stdClass;
use Traversable;
use Zend\Cache\Exception;
use Zend\Cache\Storage\AvailableSpaceCapableInterface;
use Zend\Cache\Storage\Capabilities;
use Zend\Cache\Storage\FlushableInterface;
use Zend\Cache\Storage\TotalSpaceCapableInterface;

class WinCache extends AbstractAdapter implements
    AvailableSpaceCapableInterface,
    FlushableInterface,
    TotalSpaceCapableInterface
{

    /**
     * Constructor
     *
     * @param  array|Traversable|WinCacheOptions $options
     * @throws Exception\ExceptionInterface
     */
    public function __construct($options = null)
    {
        if (!extension_loaded('wincache')) {
            throw new Exception\ExtensionNotLoadedException("WinCache extension is not loaded");
        }

        $enabled = ini_get('wincache.ucenabled');
        if (PHP_SAPI == 'cli') {
            $enabled = $enabled && (bool) ini_get('wincache.enablecli');
        }

        if (!$enabled) {
            throw new Exception\ExtensionNotLoadedException(
                "WinCache is disabled - see 'wincache.ucenabled' and 'wincache.enablecli'"
            );
        }

        parent::__construct($options);
    }

    /* options */

    /**
     * Set options.
     *
     * @param  array|Traversable|WinCacheOptions $options
     * @return WinCache
     * @see    getOptions()
     */
    public function setOptions($options)
    {
        if (!$options instanceof WinCacheOptions) {
            $options = new WinCacheOptions($options);
        }

        return parent::setOptions($options);
    }

    /**
     * Get options.
     *
     * @return WinCacheOptions
     * @see setOptions()
     */
    public function getOptions()
    {
        if (!$this->options) {
            $this->setOptions(new WinCacheOptions());
        }
        return $this->options;
    }

    /* TotalSpaceCapableInterface */

    /**
     * Get total space in bytes
     *
     * @return int|float
     */
    public function getTotalSpace()
    {
        $mem = wincache_ucache_meminfo();
        return $mem['memory_total'];
    }

    /* AvailableSpaceCapableInterface */

    /**
     * Get available space in bytes
     *
     * @return int|float
     */
    public function getAvailableSpace()
    {
        $mem = wincache_ucache_meminfo();
        return $mem['memory_free'];
    }

    /* FlushableInterface */

    /**
     * Flush the whole storage
     *
     * @return bool
     */
    public function flush()
    {
        return wincache_ucache_clear();
    }

    /* reading */

    /**
     * Internal method to get an item.
     *
     * @param  string  $normalizedKey
     * @param  bool $success
     * @param  mixed   $casToken
     * @return mixed Data on success, null on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null)
    {
        $options     = $this->getOptions();
        $namespace   = $options->getNamespace();
        $prefix      = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $internalKey = $prefix . $normalizedKey;
        $result      = wincache_ucache_get($internalKey, $success);

        if ($success) {
            $casToken = $result;
        } else {
            $result = null;
        }

        return $result;
    }

    /**
     * Internal method to get multiple items.
     *
     * @param  array $normalizedKeys
     * @return array Associative array of keys and values
     * @throws Exception\ExceptionInterface
     */
    protected function internalGetItems(array & $normalizedKeys)
    {
        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        if ($namespace === '') {
            return wincache_ucache_get($normalizedKeys);
        }

        $prefix       = $namespace . $options->getNamespaceSeparator();
        $internalKeys = array();
        foreach ($normalizedKeys as $normalizedKey) {
            $internalKeys[] = $prefix . $normalizedKey;
        }

        $fetch = wincache_ucache_get($internalKeys);

        // remove namespace prefix
        $prefixL = strlen($prefix);
        $result  = array();
        foreach ($fetch as $internalKey => & $value) {
            $result[substr($internalKey, $prefixL)] = & $value;
        }

        return $result;
    }

    /**
     * Internal method to test if an item exists.
     *
     * @param  string $normalizedKey
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalHasItem(& $normalizedKey)
    {
        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        $prefix    = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        return wincache_ucache_exists($prefix . $normalizedKey);
    }

    /**
     * Get metadata of an item.
     *
     * @param  string $normalizedKey
     * @return array|bool Metadata on success, false on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalGetMetadata(& $normalizedKey)
    {
        $options     = $this->getOptions();
        $namespace   = $options->getNamespace();
        $prefix      = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $internalKey = $prefix . $normalizedKey;

        $info = wincache_ucache_info(true, $internalKey);
        if (isset($info['ucache_entries'][1])) {
            $metadata = $info['ucache_entries'][1];
            $this->normalizeMetadata($metadata);
            return $metadata;
        }

        return false;
    }

    /* writing */

    /**
     * Internal method to store an item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalSetItem(& $normalizedKey, & $value)
    {
        $options     = $this->getOptions();
        $namespace   = $options->getNamespace();
        $prefix      = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $internalKey = $prefix . $normalizedKey;
        $ttl         = $options->getTtl();

        if (!wincache_ucache_set($internalKey, $value, $ttl)) {
            $type = is_object($value) ? get_class($value) : gettype($value);
            throw new Exception\RuntimeException(
                "wincache_ucache_set('{$internalKey}', <{$type}>, {$ttl}) failed"
            );
        }

        return true;
    }

    /**
     * Internal method to store multiple items.
     *
     * @param  array $normalizedKeyValuePairs
     * @return array Array of not stored keys
     * @throws Exception\ExceptionInterface
     */
    protected function internalSetItems(array & $normalizedKeyValuePairs)
    {
        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        if ($namespace === '') {
            return wincache_ucache_set($normalizedKeyValuePairs, null, $options->getTtl());
        }

        $prefix                = $namespace . $options->getNamespaceSeparator();
        $internalKeyValuePairs = array();
        foreach ($normalizedKeyValuePairs as $normalizedKey => & $value) {
            $internalKey = $prefix . $normalizedKey;
            $internalKeyValuePairs[$internalKey] = & $value;
        }

        $result = wincache_ucache_set($internalKeyValuePairs, null, $options->getTtl());

        // remove key prefic
        $prefixL = strlen($prefix);
        foreach ($result as & $key) {
            $key = substr($key, $prefixL);
        }

        return $result;
    }

    /**
     * Add an item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalAddItem(& $normalizedKey, & $value)
    {
        $options     = $this->getOptions();
        $namespace   = $options->getNamespace();
        $prefix      = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $internalKey = $prefix . $normalizedKey;
        $ttl         = $options->getTtl();

        if (!wincache_ucache_add($internalKey, $value, $ttl)) {
            $type = is_object($value) ? get_class($value) : gettype($value);
            throw new Exception\RuntimeException(
                "wincache_ucache_add('{$internalKey}', <{$type}>, {$ttl}) failed"
            );
        }

        return true;
    }

    /**
     * Internal method to add multiple items.
     *
     * @param  array $normalizedKeyValuePairs
     * @return array Array of not stored keys
     * @throws Exception\ExceptionInterface
     */
    protected function internalAddItems(array & $normalizedKeyValuePairs)
    {
        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        if ($namespace === '') {
            return wincache_ucache_add($normalizedKeyValuePairs, null, $options->getTtl());
        }

        $prefix                = $namespace . $options->getNamespaceSeparator();
        $internalKeyValuePairs = array();
        foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
            $internalKey = $prefix . $normalizedKey;
            $internalKeyValuePairs[$internalKey] = $value;
        }

        $result = wincache_ucache_add($internalKeyValuePairs, null, $options->getTtl());

        // remove key prefic
        $prefixL = strlen($prefix);
        foreach ($result as & $key) {
            $key = substr($key, $prefixL);
        }

        return $result;
    }

    /**
     * Internal method to replace an existing item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalReplaceItem(& $normalizedKey, & $value)
    {
        $options     = $this->getOptions();
        $namespace   = $options->getNamespace();
        $prefix      = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $internalKey = $prefix . $normalizedKey;
        if (!wincache_ucache_exists($internalKey)) {
            return false;
        }

        $ttl = $options->getTtl();
        if (!wincache_ucache_set($internalKey, $value, $ttl)) {
            $type = is_object($value) ? get_class($value) : gettype($value);
            throw new Exception\RuntimeException(
                "wincache_ucache_set('{$internalKey}', <{$type}>, {$ttl}) failed"
            );
        }

        return true;
    }

    /**
     * Internal method to remove an item.
     *
     * @param  string $normalizedKey
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    protected function internalRemoveItem(& $normalizedKey)
    {
        $options     = $this->getOptions();
        $namespace   = $options->getNamespace();
        $prefix      = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $internalKey = $prefix . $normalizedKey;
        return wincache_ucache_delete($internalKey);
    }

    /**
     * Internal method to remove multiple items.
     *
     * @param  array $normalizedKeys
     * @return array Array of not removed keys
     * @throws Exception\ExceptionInterface
     */
    protected function internalRemoveItems(array & $normalizedKeys)
    {
        $options   = $this->getOptions();
        $namespace = $options->getNamespace();
        if ($namespace === '') {
            $result = wincache_ucache_delete($normalizedKeys);
            return ($result === false) ? $normalizedKeys : $result;
        }

        $prefix       = $namespace . $options->getNamespaceSeparator();
        $internalKeys = array();
        foreach ($normalizedKeys as $normalizedKey) {
            $internalKeys[] = $prefix . $normalizedKey;
        }

        $result = wincache_ucache_delete($internalKeys);
        if ($result === false) {
            return $normalizedKeys;
        } elseif ($result) {
            // remove key prefix
            $prefixL = strlen($prefix);
            foreach ($result as & $key) {
                $key = substr($key, $prefixL);
            }
        }

        return $result;
    }

    /**
     * Internal method to increment an item.
     *
     * @param  string $normalizedKey
     * @param  int    $value
     * @return int|bool The new value on success, false on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalIncrementItem(& $normalizedKey, & $value)
    {
        $options     = $this->getOptions();
        $namespace   = $options->getNamespace();
        $prefix      = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $internalKey = $prefix . $normalizedKey;
        return wincache_ucache_inc($internalKey, (int) $value);
    }

    /**
     * Internal method to decrement an item.
     *
     * @param  string $normalizedKey
     * @param  int    $value
     * @return int|bool The new value on success, false on failure
     * @throws Exception\ExceptionInterface
     */
    protected function internalDecrementItem(& $normalizedKey, & $value)
    {
        $options     = $this->getOptions();
        $namespace   = $options->getNamespace();
        $prefix      = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
        $internalKey = $prefix . $normalizedKey;
        return wincache_ucache_dec($internalKey, (int) $value);
    }

    /* status */

    /**
     * Internal method to get capabilities of this adapter
     *
     * @return Capabilities
     */
    protected function internalGetCapabilities()
    {
        if ($this->capabilities === null) {
            $marker       = new stdClass();
            $capabilities = new Capabilities(
                $this,
                $marker,
                array(
                    'supportedDatatypes' => array(
                        'NULL'     => true,
                        'boolean'  => true,
                        'integer'  => true,
                        'double'   => true,
                        'string'   => true,
                        'array'    => true,
                        'object'   => 'object',
                        'resource' => false,
                    ),
                    'supportedMetadata' => array(
                        'internal_key', 'ttl', 'hits', 'size'
                    ),
                    'minTtl'             => 1,
                    'maxTtl'             => 0,
                    'staticTtl'          => true,
                    'ttlPrecision'       => 1,
                    'useRequestTime'     => false,
                    'expiredRead'        => false,
                    'namespaceIsPrefix'  => true,
                    'namespaceSeparator' => $this->getOptions()->getNamespaceSeparator(),
                )
            );

            // update namespace separator on change option
            $this->getEventManager()->attach('option', function ($event) use ($capabilities, $marker) {
                $params = $event->getParams();

                if (isset($params['namespace_separator'])) {
                    $capabilities->setNamespaceSeparator($marker, $params['namespace_separator']);
                }
            });

            $this->capabilities     = $capabilities;
            $this->capabilityMarker = $marker;
        }

        return $this->capabilities;
    }

    /* internal */

    /**
     * Normalize metadata to work with WinCache
     *
     * @param  array $metadata
     * @return void
     */
    protected function normalizeMetadata(array & $metadata)
    {
        $metadata['internal_key'] = $metadata['key_name'];
        $metadata['hits']         = $metadata['hitcount'];
        $metadata['ttl']          = $metadata['ttl_seconds'];
        $metadata['size']         = $metadata['value_size'];

        unset(
            $metadata['key_name'],
            $metadata['hitcount'],
            $metadata['ttl_seconds'],
            $metadata['value_size']
        );
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache;

use Traversable;
use Zend\Stdlib\ArrayUtils;

abstract class StorageFactory
{
    /**
     * Plugin manager for loading adapters
     *
     * @var null|Storage\AdapterPluginManager
     */
    protected static $adapters = null;

    /**
     * Plugin manager for loading plugins
     *
     * @var null|Storage\PluginManager
     */
    protected static $plugins = null;

    /**
     * The storage factory
     * This can instantiate storage adapters and plugins.
     *
     * @param array|Traversable $cfg
     * @return Storage\StorageInterface
     * @throws Exception\InvalidArgumentException
     */
    public static function factory($cfg)
    {
        if ($cfg instanceof Traversable) {
            $cfg = ArrayUtils::iteratorToArray($cfg);
        }

        if (!is_array($cfg)) {
            throw new Exception\InvalidArgumentException(
                'The factory needs an associative array '
                . 'or a Traversable object as an argument'
            );
        }

        // instantiate the adapter
        if (!isset($cfg['adapter'])) {
            throw new Exception\InvalidArgumentException('Missing "adapter"');
        }
        $adapterName    = $cfg['adapter'];
        $adapterOptions = array();
        if (is_array($cfg['adapter'])) {
            if (!isset($cfg['adapter']['name'])) {
                throw new Exception\InvalidArgumentException('Missing "adapter.name"');
            }

            $adapterName    = $cfg['adapter']['name'];
            $adapterOptions = isset($cfg['adapter']['options']) ? $cfg['adapter']['options'] : array();
        }
        if (isset($cfg['options'])) {
            $adapterOptions = array_merge($adapterOptions, $cfg['options']);
        }

        $adapter = static::adapterFactory((string) $adapterName, $adapterOptions);

        // add plugins
        if (isset($cfg['plugins'])) {
            if (!is_array($cfg['plugins'])) {
                throw new Exception\InvalidArgumentException(
                    'Plugins needs to be an array'
                );
            }

            foreach ($cfg['plugins'] as $k => $v) {
                $pluginPrio = 1; // default priority

                if (is_string($k)) {
                    if (!is_array($v)) {
                        throw new Exception\InvalidArgumentException(
                            "'plugins.{$k}' needs to be an array"
                        );
                    }
                    $pluginName    = $k;
                    $pluginOptions = $v;
                } elseif (is_array($v)) {
                    if (!isset($v['name'])) {
                        throw new Exception\InvalidArgumentException("Invalid plugins[{$k}] or missing plugins[{$k}].name");
                    }
                    $pluginName = (string) $v['name'];

                    if (isset($v['options'])) {
                        $pluginOptions = $v['options'];
                    } else {
                        $pluginOptions = array();
                    }

                    if (isset($v['priority'])) {
                        $pluginPrio = $v['priority'];
                    }
                } else {
                    $pluginName    = $v;
                    $pluginOptions = array();
                }

                $plugin = static::pluginFactory($pluginName, $pluginOptions);
                $adapter->addPlugin($plugin, $pluginPrio);
            }
        }

        return $adapter;
    }

    /**
     * Instantiate a storage adapter
     *
     * @param  string|Storage\StorageInterface                  $adapterName
     * @param  array|Traversable|Storage\Adapter\AdapterOptions $options
     * @return Storage\StorageInterface
     * @throws Exception\RuntimeException
     */
    public static function adapterFactory($adapterName, $options = array())
    {
        if ($adapterName instanceof Storage\StorageInterface) {
            // $adapterName is already an adapter object
            $adapter = $adapterName;
        } else {
            $adapter = static::getAdapterPluginManager()->get($adapterName);
        }

        if ($options) {
            $adapter->setOptions($options);
        }

        return $adapter;
    }

    /**
     * Get the adapter plugin manager
     *
     * @return Storage\AdapterPluginManager
     */
    public static function getAdapterPluginManager()
    {
        if (static::$adapters === null) {
            static::$adapters = new Storage\AdapterPluginManager();
        }
        return static::$adapters;
    }

    /**
     * Change the adapter plugin manager
     *
     * @param  Storage\AdapterPluginManager $adapters
     * @return void
     */
    public static function setAdapterPluginManager(Storage\AdapterPluginManager $adapters)
    {
        static::$adapters = $adapters;
    }

    /**
     * Resets the internal adapter plugin manager
     *
     * @return void
     */
    public static function resetAdapterPluginManager()
    {
        static::$adapters = null;
    }

    /**
     * Instantiate a storage plugin
     *
     * @param string|Storage\Plugin\PluginInterface     $pluginName
     * @param array|Traversable|Storage\Plugin\PluginOptions $options
     * @return Storage\Plugin\PluginInterface
     * @throws Exception\RuntimeException
     */
    public static function pluginFactory($pluginName, $options = array())
    {
        if ($pluginName instanceof Storage\Plugin\PluginInterface) {
            // $pluginName is already an plugin object
            $plugin = $pluginName;
        } else {
            $plugin = static::getPluginManager()->get($pluginName);
        }

        if (!$options instanceof Storage\Plugin\PluginOptions) {
            $options = new Storage\Plugin\PluginOptions($options);
        }

        if ($options) {
            $plugin->setOptions($options);
        }

        return $plugin;
    }

    /**
     * Get the plugin manager
     *
     * @return Storage\PluginManager
     */
    public static function getPluginManager()
    {
        if (static::$plugins === null) {
            static::$plugins = new Storage\PluginManager();
        }
        return static::$plugins;
    }

    /**
     * Change the plugin manager
     *
     * @param  Storage\PluginManager $plugins
     * @return void
     */
    public static function setPluginManager(Storage\PluginManager $plugins)
    {
        static::$plugins = $plugins;
    }

    /**
     * Resets the internal plugin manager
     *
     * @return void
     */
    public static function resetPluginManager()
    {
        static::$plugins = null;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Pattern;

use Zend\Cache\Exception;
use Zend\Stdlib\ErrorHandler;

class CaptureCache extends AbstractPattern
{
    /**
     * Start the cache
     *
     * @param  string $pageId  Page identifier
     * @return void
     */
    public function start($pageId = null)
    {
        if ($pageId === null) {
            $pageId = $this->detectPageId();
        }

        $that = $this;
        ob_start(function ($content) use ($that, $pageId) {
            $that->set($content, $pageId);

            // http://php.net/manual/function.ob-start.php
            // -> If output_callback  returns FALSE original input is sent to the browser.
            return false;
        });

        ob_implicit_flush(false);
    }

    /**
     * Write content to page identity
     *
     * @param string      $content
     * @param null|string $pageId
     * @throws Exception\LogicException
     */
    public function set($content, $pageId = null)
    {
        $publicDir = $this->getOptions()->getPublicDir();
        if ($publicDir === null) {
            throw new Exception\LogicException("Option 'public_dir' no set");
        }

        if ($pageId === null) {
            $pageId = $this->detectPageId();
        }

        $path = $this->pageId2Path($pageId);
        $file = $path . DIRECTORY_SEPARATOR . $this->pageId2Filename($pageId);

        $this->createDirectoryStructure($publicDir . DIRECTORY_SEPARATOR . $path);
        $this->putFileContent($publicDir . DIRECTORY_SEPARATOR . $file, $content);
    }

    /**
     * Get from cache
     *
     * @param  null|string $pageId
     * @return bool|string
     * @throws Exception\LogicException
     * @throws Exception\RuntimeException
     */
    public function get($pageId = null)
    {
        $publicDir = $this->getOptions()->getPublicDir();
        if ($publicDir === null) {
            throw new Exception\LogicException("Option 'public_dir' no set");
        }

        if ($pageId === null) {
            $pageId = $this->detectPageId();
        }

        $file = $publicDir
            . DIRECTORY_SEPARATOR . $this->pageId2Path($pageId)
            . DIRECTORY_SEPARATOR . $this->pageId2Filename($pageId);

        if (file_exists($file)) {
            ErrorHandler::start();
            $content = file_get_contents($file);
            $error   = ErrorHandler::stop();
            if ($content === false) {
                throw new Exception\RuntimeException(
                    "Failed to read cached pageId '{$pageId}'", 0, $error
                );
            }
            return $content;
        }
    }

    /**
     * Checks if a cache with given id exists
     *
     * @param  null|string $pageId
     * @throws Exception\LogicException
     * @return bool
     */
    public function has($pageId = null)
    {
        $publicDir = $this->getOptions()->getPublicDir();
        if ($publicDir === null) {
            throw new Exception\LogicException("Option 'public_dir' no set");
        }

        if ($pageId === null) {
            $pageId = $this->detectPageId();
        }

        $file = $publicDir
            . DIRECTORY_SEPARATOR . $this->pageId2Path($pageId)
            . DIRECTORY_SEPARATOR . $this->pageId2Filename($pageId);

        return file_exists($file);
    }

    /**
     * Remove from cache
     *
     * @param  null|string $pageId
     * @throws Exception\LogicException
     * @throws Exception\RuntimeException
     * @return bool
     */
    public function remove($pageId = null)
    {
        $publicDir = $this->getOptions()->getPublicDir();
        if ($publicDir === null) {
            throw new Exception\LogicException("Option 'public_dir' no set");
        }

        if ($pageId === null) {
            $pageId = $this->detectPageId();
        }

        $file = $publicDir
            . DIRECTORY_SEPARATOR . $this->pageId2Path($pageId)
            . DIRECTORY_SEPARATOR . $this->pageId2Filename($pageId);

        if (file_exists($file)) {
            ErrorHandler::start();
            $res = unlink($file);
            $err = ErrorHandler::stop();
            if (!$res) {
                throw new Exception\RuntimeException(
                    "Failed to remove cached pageId '{$pageId}'", 0, $err
                );
            }
            return true;
        }

        return false;
    }

    /**
     * Clear cached pages matching glob pattern
     *
     * @param string $pattern
     * @throws Exception\LogicException
     */
    public function clearByGlob($pattern = '**')
    {
        $publicDir = $this->getOptions()->getPublicDir();
        if ($publicDir === null) {
            throw new Exception\LogicException("Option 'public_dir' no set");
        }

        $it = new \GlobIterator(
            $publicDir . '/' . $pattern,
            \GlobIterator::CURRENT_AS_SELF | \GlobIterator::SKIP_DOTS | \GlobIterator::UNIX_PATHS
        );
        foreach ($it as $pathname => $entry) {
            if ($entry->isFile()) {
                unlink($pathname);
            }
        }
    }

    /**
     * Determine the page to save from the request
     *
     * @throws Exception\RuntimeException
     * @return string
     */
    protected function detectPageId()
    {
        if (!isset($_SERVER['REQUEST_URI'])) {
            throw new Exception\RuntimeException("Can't auto-detect current page identity");
        }

        return $_SERVER['REQUEST_URI'];
    }

    /**
     * Get filename for page id
     *
     * @param string $pageId
     * @return string
     */
    protected function pageId2Filename($pageId)
    {
        if (substr($pageId, -1) === '/') {
            return $this->getOptions()->getIndexFilename();
        }

        return basename($pageId);
    }

    /**
     * Get path for page id
     *
     * @param string $pageId
     * @return string
     */
    protected function pageId2Path($pageId)
    {
        if (substr($pageId, -1) == '/') {
            $path = rtrim($pageId, '/');
        } else {
            $path = dirname($pageId);
        }

        // convert requested "/" to the valid local directory separator
        if ('/' != DIRECTORY_SEPARATOR) {
            $path = str_replace('/', DIRECTORY_SEPARATOR, $path);
        }

        return $path;
    }

    /**
     * Write content to a file
     *
     * @param  string  $file File complete path
     * @param  string  $data Data to write
     * @return void
     * @throws Exception\RuntimeException
     */
    protected function putFileContent($file, $data)
    {
        $options = $this->getOptions();
        $locking = $options->getFileLocking();
        $perm    = $options->getFilePermission();
        $umask   = $options->getUmask();
        if ($umask !== false && $perm !== false) {
            $perm = $perm & ~$umask;
        }

        ErrorHandler::start();

        $umask = ($umask !== false) ? umask($umask) : false;
        $rs    = file_put_contents($file, $data, $locking ? LOCK_EX : 0);
        if ($umask) {
            umask($umask);
        }

        if ($rs === false) {
            $err = ErrorHandler::stop();
            throw new Exception\RuntimeException(
                "Error writing file '{$file}'", 0, $err
            );
        }

        if ($perm !== false && !chmod($file, $perm)) {
            $oct = decoct($perm);
            $err = ErrorHandler::stop();
            throw new Exception\RuntimeException("chmod('{$file}', 0{$oct}) failed", 0, $err);
        }

        ErrorHandler::stop();
    }

    /**
     * Creates directory if not already done.
     *
     * @param string $pathname
     * @return void
     * @throws Exception\RuntimeException
     */
    protected function createDirectoryStructure($pathname)
    {
        // Directory structure already exists
        if (file_exists($pathname)) {
            return;
        }

        $options = $this->getOptions();
        $perm    = $options->getDirPermission();
        $umask   = $options->getUmask();
        if ($umask !== false && $perm !== false) {
            $perm = $perm & ~$umask;
        }

        ErrorHandler::start();

        if ($perm === false) {
            // build-in mkdir function is enough

            $umask = ($umask !== false) ? umask($umask) : false;
            $res   = mkdir($pathname, ($perm !== false) ? $perm : 0777, true);

            if ($umask !== false) {
                umask($umask);
            }

            if (!$res) {
                $oct = ($perm === false) ? '777' : decoct($perm);
                $err = ErrorHandler::stop();
                throw new Exception\RuntimeException(
                    "mkdir('{$pathname}', 0{$oct}, true) failed", 0, $err
                );
            }

            if ($perm !== false && !chmod($pathname, $perm)) {
                $oct = decoct($perm);
                $err = ErrorHandler::stop();
                throw new Exception\RuntimeException(
                    "chmod('{$pathname}', 0{$oct}) failed", 0, $err
                );
            }

        } else {
            // build-in mkdir function sets permission together with current umask
            // which doesn't work well on multo threaded webservers
            // -> create directories one by one and set permissions

            // find existing path and missing path parts
            $parts = array();
            $path  = $pathname;
            while (!file_exists($path)) {
                array_unshift($parts, basename($path));
                $nextPath = dirname($path);
                if ($nextPath === $path) {
                    break;
                }
                $path = $nextPath;
            }

            // make all missing path parts
            foreach ($parts as $part) {
                $path.= DIRECTORY_SEPARATOR . $part;

                // create a single directory, set and reset umask immediately
                $umask = ($umask !== false) ? umask($umask) : false;
                $res   = mkdir($path, ($perm === false) ? 0777 : $perm, false);
                if ($umask !== false) {
                    umask($umask);
                }

                if (!$res) {
                    $oct = ($perm === false) ? '777' : decoct($perm);
                    $err = ErrorHandler::stop();
                    throw new Exception\RuntimeException(
                        "mkdir('{$path}', 0{$oct}, false) failed"
                    );
                }

                if ($perm !== false && !chmod($path, $perm)) {
                    $oct = decoct($perm);
                    $err = ErrorHandler::stop();
                    throw new Exception\RuntimeException(
                        "chmod('{$path}', 0{$oct}) failed"
                    );
                }
            }
        }

        ErrorHandler::stop();
    }

    /**
     * Returns the generated file name.
     *
     * @param null|string $pageId
     * @return string
     */
    public function getFilename($pageId = null)
    {
        if ($pageId === null) {
            $pageId = $this->detectPageId();
        }

        $publicDir = $this->getOptions()->getPublicDir();
        $path      = $this->pageId2Path($pageId);
        $file      = $path . DIRECTORY_SEPARATOR . $this->pageId2Filename($pageId);

        return $publicDir . $file;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Pattern;

use Traversable;
use Zend\Cache\Exception;

abstract class AbstractPattern implements PatternInterface
{
    /**
     * @var PatternOptions
     */
    protected $options;

    /**
     * Set pattern options
     *
     * @param  array|Traversable|PatternOptions $options
     * @return AbstractPattern
     * @throws Exception\InvalidArgumentException
     */
    public function setOptions(PatternOptions $options)
    {
        if (!$options instanceof PatternOptions) {
            $options = new PatternOptions($options);
        }

        $this->options = $options;
        return $this;
    }

    /**
     * Get all pattern options
     *
     * @return PatternOptions
     */
    public function getOptions()
    {
        if (null === $this->options) {
            $this->setOptions(new PatternOptions());
        }
        return $this->options;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Pattern;

use Zend\Cache\Exception;

class OutputCache extends AbstractPattern
{
    /**
     * The key stack
     *
     * @var array
     */
    protected $keyStack = array();

    /**
     * Set options
     *
     * @param  PatternOptions $options
     * @return OutputCache
     * @throws Exception\InvalidArgumentException
     */
    public function setOptions(PatternOptions $options)
    {
        parent::setOptions($options);

        if (!$options->getStorage()) {
            throw new Exception\InvalidArgumentException("Missing option 'storage'");
        }

        return $this;
    }

    /**
     * if there is a cached item with the given key display it's data and return true
     * else start buffering output until end() is called or the script ends.
     *
     * @param  string  $key Key
     * @throws Exception\MissingKeyException if key is missing
     * @return bool
     */
    public function start($key)
    {
        if (($key = (string) $key) === '') {
            throw new Exception\MissingKeyException('Missing key to read/write output from cache');
        }

        $success = null;
        $data    = $this->getOptions()->getStorage()->getItem($key, $success);
        if ($success) {
            echo $data;
            return true;
        }

        ob_start();
        ob_implicit_flush(false);
        $this->keyStack[] = $key;
        return false;
    }

    /**
     * Stops buffering output, write buffered data to cache using the given key on start()
     * and displays the buffer.
     *
     * @throws Exception\RuntimeException if output cache not started or buffering not active
     * @return bool TRUE on success, FALSE on failure writing to cache
     */
    public function end()
    {
        $key = array_pop($this->keyStack);
        if ($key === null) {
            throw new Exception\RuntimeException('Output cache not started');
        }

        $output = ob_get_flush();
        if ($output === false) {
            throw new Exception\RuntimeException('Output buffering not active');
        }

        return $this->getOptions()->getStorage()->setItem($key, $output);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Pattern;

interface PatternInterface
{
    /**
     * Set pattern options
     *
     * @param  PatternOptions $options
     * @return PatternInterface
     */
    public function setOptions(PatternOptions $options);

    /**
     * Get all pattern options
     *
     * @return array
     */
    public function getOptions();
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Pattern;

use Zend\Cache\Exception;
use Zend\Stdlib\ErrorHandler;

class CallbackCache extends AbstractPattern
{
    /**
     * Set options
     *
     * @param  PatternOptions $options
     * @return CallbackCache
     * @throws Exception\InvalidArgumentException if missing storage option
     */
    public function setOptions(PatternOptions $options)
    {
        parent::setOptions($options);

        if (!$options->getStorage()) {
            throw new Exception\InvalidArgumentException("Missing option 'storage'");
        }
        return $this;
    }

    /**
     * Call the specified callback or get the result from cache
     *
     * @param  callable   $callback  A valid callback
     * @param  array      $args      Callback arguments
     * @return mixed Result
     * @throws Exception\RuntimeException if invalid cached data
     * @throws \Exception
     */
    public function call($callback, array $args = array())
    {
        $options = $this->getOptions();
        $storage = $options->getStorage();
        $success = null;
        $key     = $this->generateCallbackKey($callback, $args);
        $result  = $storage->getItem($key, $success);
        if ($success) {
            if (!array_key_exists(0, $result)) {
                throw new Exception\RuntimeException("Invalid cached data for key '{$key}'");
            }

            echo isset($result[1]) ? $result[1] : '';
            return $result[0];
        }

        $cacheOutput = $options->getCacheOutput();
        if ($cacheOutput) {
            ob_start();
            ob_implicit_flush(false);
        }

        // TODO: do not cache on errors using [set|restore]_error_handler

        try {
            if ($args) {
                $ret = call_user_func_array($callback, $args);
            } else {
                $ret = call_user_func($callback);
            }
        } catch (\Exception $e) {
            if ($cacheOutput) {
                ob_end_flush();
            }
            throw $e;
        }

        if ($cacheOutput) {
            $data = array($ret, ob_get_flush());
        } else {
            $data = array($ret);
        }

        $storage->setItem($key, $data);

        return $ret;
    }

    /**
     * function call handler
     *
     * @param  string $function  Function name to call
     * @param  array  $args      Function arguments
     * @return mixed
     * @throws Exception\RuntimeException
     * @throws \Exception
     */
    public function __call($function, array $args)
    {
        return $this->call($function, $args);
    }

    /**
     * Generate a unique key in base of a key representing the callback part
     * and a key representing the arguments part.
     *
     * @param  callable   $callback  A valid callback
     * @param  array      $args      Callback arguments
     * @return string
     * @throws Exception\RuntimeException
     * @throws Exception\InvalidArgumentException
     */
    public function generateKey($callback, array $args = array())
    {
        return $this->generateCallbackKey($callback, $args);
    }

    /**
     * Generate a unique key in base of a key representing the callback part
     * and a key representing the arguments part.
     *
     * @param  callable   $callback  A valid callback
     * @param  array      $args      Callback arguments
     * @throws Exception\RuntimeException if callback not serializable
     * @throws Exception\InvalidArgumentException if invalid callback
     * @return string
     */
    protected function generateCallbackKey($callback, array $args)
    {
        if (!is_callable($callback, false, $callbackKey)) {
            throw new Exception\InvalidArgumentException('Invalid callback');
        }

        // functions, methods and classnames are case-insensitive
        $callbackKey = strtolower($callbackKey);

        // generate a unique key of object callbacks
        if (is_object($callback)) { // Closures & __invoke
            $object = $callback;
        } elseif (isset($callback[0])) { // array($object, 'method')
            $object = $callback[0];
        }
        if (isset($object)) {
            ErrorHandler::start();
            try {
                $serializedObject = serialize($object);
            } catch (\Exception $e) {
                ErrorHandler::stop();
                throw new Exception\RuntimeException(
                    "Can't serialize callback: see previous exception", 0, $e
                );
            }
            $error = ErrorHandler::stop();

            if (!$serializedObject) {
                throw new Exception\RuntimeException(sprintf(
                    'Cannot serialize callback%s',
                    ($error ? ': ' . $error->getMessage() : '')
                ), 0, $error);
            }
            $callbackKey.= $serializedObject;
        }

        return md5($callbackKey) . $this->generateArgumentsKey($args);
    }

    /**
     * Generate a unique key of the argument part.
     *
     * @param  array $args
     * @throws Exception\RuntimeException
     * @return string
     */
    protected function generateArgumentsKey(array $args)
    {
        if (!$args) {
            return '';
        }

        ErrorHandler::start();
        try {
            $serializedArgs = serialize(array_values($args));
        } catch (\Exception $e) {
            ErrorHandler::stop();
            throw new Exception\RuntimeException(
                "Can't serialize arguments: see previous exception"
            , 0, $e);
        }
        $error = ErrorHandler::stop();

        if (!$serializedArgs) {
            throw new Exception\RuntimeException(sprintf(
                'Cannot serialize arguments%s',
                ($error ? ': ' . $error->getMessage() : '')
            ), 0, $error);
        }

        return md5($serializedArgs);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Pattern;

use Zend\Cache\Exception;

class ObjectCache extends CallbackCache
{
    /**
     * Set options
     *
     * @param  PatternOptions $options
     * @return void
     * @throws Exception\InvalidArgumentException
     */
    public function setOptions(PatternOptions $options)
    {
        parent::setOptions($options);

        if (!$options->getObject()) {
            throw new Exception\InvalidArgumentException("Missing option 'object'");
        } elseif (!$options->getStorage()) {
            throw new Exception\InvalidArgumentException("Missing option 'storage'");
        }
    }

    /**
     * Call and cache a class method
     *
     * @param  string $method  Method name to call
     * @param  array  $args    Method arguments
     * @return mixed
     * @throws Exception\RuntimeException
     * @throws \Exception
     */
    public function call($method, array $args = array())
    {
        $options = $this->getOptions();
        $object  = $options->getObject();
        $method  = strtolower($method);

        // handle magic methods
        switch ($method) {
            case '__set':
                $property = array_shift($args);
                $value    = array_shift($args);

                $object->{$property} = $value;

                if (!$options->getObjectCacheMagicProperties()
                    || property_exists($object, $property)
                ) {
                    // no caching if property isn't magic
                    // or caching magic properties is disabled
                    return;
                }

                // remove cached __get and __isset
                $removeKeys = null;
                if (method_exists($object, '__get')) {
                    $removeKeys[] = $this->generateKey('__get', array($property));
                }
                if (method_exists($object, '__isset')) {
                    $removeKeys[] = $this->generateKey('__isset', array($property));
                }
                if ($removeKeys) {
                    $options->getStorage()->removeItems($removeKeys);
                }
                return;

            case '__get':
                $property = array_shift($args);

                if (!$options->getObjectCacheMagicProperties()
                    || property_exists($object, $property)
                ) {
                    // no caching if property isn't magic
                    // or caching magic properties is disabled
                    return $object->{$property};
                }

                array_unshift($args, $property);
                return parent::call(array($object, '__get'), $args);

           case '__isset':
                $property = array_shift($args);

                if (!$options->getObjectCacheMagicProperties()
                    || property_exists($object, $property)
                ) {
                    // no caching if property isn't magic
                    // or caching magic properties is disabled
                    return isset($object->{$property});
                }

                return parent::call(array($object, '__isset'), array($property));

            case '__unset':
                $property = array_shift($args);

                unset($object->{$property});

                if (!$options->getObjectCacheMagicProperties()
                    || property_exists($object, $property)
                ) {
                    // no caching if property isn't magic
                    // or caching magic properties is disabled
                    return;
                }

                // remove previous cached __get and __isset calls
                $removeKeys = null;
                if (method_exists($object, '__get')) {
                    $removeKeys[] = $this->generateKey('__get', array($property));
                }
                if (method_exists($object, '__isset')) {
                    $removeKeys[] = $this->generateKey('__isset', array($property));
                }
                if ($removeKeys) {
                    $options->getStorage()->removeItems($removeKeys);
                }
                return;
        }

        $cache = $options->getCacheByDefault();
        if ($cache) {
            $cache = !in_array($method, $options->getObjectNonCacheMethods());
        } else {
            $cache = in_array($method, $options->getObjectCacheMethods());
        }

        if (!$cache) {
            if ($args) {
                return call_user_func_array(array($object, $method), $args);
            }
            return $object->{$method}();
        }

        return parent::call(array($object, $method), $args);
    }

    /**
     * Generate a unique key in base of a key representing the callback part
     * and a key representing the arguments part.
     *
     * @param  string     $method  The method
     * @param  array      $args    Callback arguments
     * @return string
     * @throws Exception\RuntimeException
     */
    public function generateKey($method, array $args = array())
    {
        return $this->generateCallbackKey(
            array($this->getOptions()->getObject(), $method),
            $args
        );
    }

    /**
     * Generate a unique key in base of a key representing the callback part
     * and a key representing the arguments part.
     *
     * @param  callable   $callback  A valid callback
     * @param  array      $args      Callback arguments
     * @return string
     * @throws Exception\RuntimeException
     */
    protected function generateCallbackKey($callback, array $args = array())
    {
        $callbackKey = md5($this->getOptions()->getObjectKey() . '::' . strtolower($callback[1]));
        $argumentKey = $this->generateArgumentsKey($args);
        return $callbackKey . $argumentKey;
    }

    /**
     * Class method call handler
     *
     * @param  string $method  Method name to call
     * @param  array  $args    Method arguments
     * @return mixed
     * @throws Exception\RuntimeException
     * @throws \Exception
     */
    public function __call($method, array $args)
    {
        return $this->call($method, $args);
    }

    /**
     * Writing data to properties.
     *
     * NOTE:
     * Magic properties will be cached too if the option cacheMagicProperties
     * is enabled and the property doesn't exist in real. If so it calls __set
     * and removes cached data of previous __get and __isset calls.
     *
     * @param  string $name
     * @param  mixed  $value
     * @return void
     * @see    http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members
     */
    public function __set($name, $value)
    {
        return $this->call('__set', array($name, $value));
    }

    /**
     * Reading data from properties.
     *
     * NOTE:
     * Magic properties will be cached too if the option cacheMagicProperties
     * is enabled and the property doesn't exist in real. If so it calls __get.
     *
     * @param  string $name
     * @return mixed
     * @see http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members
     */
    public function __get($name)
    {
        return $this->call('__get', array($name));
    }

    /**
     * Checking existing properties.
     *
     * NOTE:
     * Magic properties will be cached too if the option cacheMagicProperties
     * is enabled and the property doesn't exist in real. If so it calls __get.
     *
     * @param  string $name
     * @return bool
     * @see    http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members
     */
    public function __isset($name)
    {
        return $this->call('__isset', array($name));
    }

    /**
     * Unseting a property.
     *
     * NOTE:
     * Magic properties will be cached too if the option cacheMagicProperties
     * is enabled and the property doesn't exist in real. If so it removes
     * previous cached __isset and __get calls.
     *
     * @param  string $name
     * @return void
     * @see    http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members
     */
    public function __unset($name)
    {
        return $this->call('__unset', array($name));
    }

    /**
     * Handle casting to string
     *
     * @return string
     * @see    http://php.net/manual/language.oop5.magic.php#language.oop5.magic.tostring
     */
    public function __toString()
    {
        return $this->call('__toString');
    }

    /**
     * Handle invoke calls
     *
     * @return mixed
     * @see    http://php.net/manual/language.oop5.magic.php#language.oop5.magic.invoke
     */
    public function __invoke()
    {
        return $this->call('__invoke', func_get_args());
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Pattern;

use Zend\Cache;
use Zend\Cache\Exception;

class ClassCache extends CallbackCache
{
    /**
     * Set options
     *
     * @param  PatternOptions $options
     * @return ClassCache
     * @throws Exception\InvalidArgumentException if missing 'class' or 'storage' options
     */
    public function setOptions(PatternOptions $options)
    {
        parent::setOptions($options);

        if (!$options->getClass()) {
            throw new Exception\InvalidArgumentException("Missing option 'class'");
        } elseif (!$options->getStorage()) {
            throw new Exception\InvalidArgumentException("Missing option 'storage'");
        }
        return $this;
    }

    /**
     * Call and cache a class method
     *
     * @param  string $method  Method name to call
     * @param  array  $args    Method arguments
     * @return mixed
     * @throws Exception\RuntimeException
     * @throws \Exception
     */
    public function call($method, array $args = array())
    {
        $options   = $this->getOptions();
        $classname = $options->getClass();
        $method    = strtolower($method);
        $callback  = $classname . '::' . $method;

        $cache = $options->getCacheByDefault();
        if ($cache) {
            $cache = !in_array($method, $options->getClassNonCacheMethods());
        } else {
            $cache = in_array($method, $options->getClassCacheMethods());
        }

        if (!$cache) {
            if ($args) {
                return call_user_func_array($callback, $args);
            } else {
                return $classname::$method();
            }
        }

        return parent::call($callback, $args);
    }

    /**
     * Generate a unique key in base of a key representing the callback part
     * and a key representing the arguments part.
     *
     * @param  string     $method  The method
     * @param  array      $args    Callback arguments
     * @return string
     * @throws Exception\RuntimeException
     */
    public function generateKey($method, array $args = array())
    {
        return $this->generateCallbackKey(
            $this->getOptions()->getClass() . '::' . $method,
            $args
        );
    }

    /**
     * Generate a unique key in base of a key representing the callback part
     * and a key representing the arguments part.
     *
     * @param  callable   $callback  A valid callback
     * @param  array      $args      Callback arguments
     * @return string
     * @throws Exception\RuntimeException
     */
    protected function generateCallbackKey($callback, array $args)
    {
        $callbackKey = md5(strtolower($callback));
        $argumentKey = $this->generateArgumentsKey($args);
        return $callbackKey . $argumentKey;
    }

    /**
     * Calling a method of the entity.
     *
     * @param  string $method  Method name to call
     * @param  array  $args    Method arguments
     * @return mixed
     * @throws Exception\RuntimeException
     * @throws \Exception
     */
    public function __call($method, array $args)
    {
        return $this->call($method, $args);
    }

    /**
     * Set a static property
     *
     * @param  string $name
     * @param  mixed  $value
     * @return void
     * @see   http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members
     */
    public function __set($name, $value)
    {
        $class = $this->getOptions()->getClass();
        $class::$name = $value;
    }

    /**
     * Get a static property
     *
     * @param  string $name
     * @return mixed
     * @see    http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members
     */
    public function __get($name)
    {
        $class = $this->getOptions()->getClass();
        return $class::$name;
    }

    /**
     * Is a static property exists.
     *
     * @param  string $name
     * @return bool
     */
    public function __isset($name)
    {
        $class = $this->getOptions()->getClass();
        return isset($class::$name);
    }

    /**
     * Unset a static property
     *
     * @param  string $name
     * @return void
     */
    public function __unset($name)
    {
        $class = $this->getOptions()->getClass();
        unset($class::$name);
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Pattern;

use Traversable;
use Zend\Cache\Exception;
use Zend\Cache\StorageFactory;
use Zend\Cache\Storage\StorageInterface as Storage;
use Zend\Stdlib\AbstractOptions;

class PatternOptions extends AbstractOptions
{
    /**
     * Used by:
     * - ClassCache
     * - ObjectCache
     * @var bool
     */
    protected $cacheByDefault = true;

    /**
     * Used by:
     * - CallbackCache
     * - ClassCache
     * - ObjectCache
     * @var bool
     */
    protected $cacheOutput = true;

    /**
     * Used by:
     * - ClassCache
     * @var null|string
     */
    protected $class;

    /**
     * Used by:
     * - ClassCache
     * @var array
     */
    protected $classCacheMethods = array();

    /**
     * Used by:
     * - ClassCache
     * @var array
     */
    protected $classNonCacheMethods = array();

    /**
     * Used by:
     * - CaptureCache
     * @var false|int
     */
    protected $umask = false;

    /**
     * Used by:
     * - CaptureCache
     * @var false|int
     */
    protected $dirPermission = 0700;

    /**
     * Used by:
     * - CaptureCache
     * @var false|int
     */
    protected $filePermission = 0600;

    /**
     * Used by:
     * - CaptureCache
     * @var bool
     */
    protected $fileLocking = true;

    /**
     * Used by:
     * - CaptureCache
     * @var string
     */
    protected $indexFilename = 'index.html';

    /**
     * Used by:
     * - ObjectCache
     * @var null|object
     */
    protected $object;

    /**
     * Used by:
     * - ObjectCache
     * @var bool
     */
    protected $objectCacheMagicProperties = false;

    /**
     * Used by:
     * - ObjectCache
     * @var array
     */
    protected $objectCacheMethods = array();

    /**
     * Used by:
     * - ObjectCache
     * @var null|string
     */
    protected $objectKey;

    /**
     * Used by:
     * - ObjectCache
     * @var array
     */
    protected $objectNonCacheMethods = array('__tostring');

    /**
     * Used by:
     * - CaptureCache
     * @var null|string
     */
    protected $publicDir;

    /**
     * Used by:
     * - CallbackCache
     * - ClassCache
     * - ObjectCache
     * - OutputCache
     * @var null|Storage
     */
    protected $storage;

    /**
     * Constructor
     *
     * @param  array|Traversable|null $options
     * @return PatternOptions
     * @throws Exception\InvalidArgumentException
     */
    public function __construct($options = null)
    {
        // disable file/directory permissions by default on windows systems
        if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
            $this->filePermission = false;
            $this->dirPermission = false;
        }

        parent::__construct($options);
    }

    /**
     * Set flag indicating whether or not to cache by default
     *
     * Used by:
     * - ClassCache
     * - ObjectCache
     *
     * @param  bool $cacheByDefault
     * @return PatternOptions
     */
    public function setCacheByDefault($cacheByDefault)
    {
        $this->cacheByDefault = $cacheByDefault;
        return $this;
    }

    /**
     * Do we cache by default?
     *
     * Used by:
     * - ClassCache
     * - ObjectCache
     *
     * @return bool
     */
    public function getCacheByDefault()
    {
        return $this->cacheByDefault;
    }

    /**
     * Set whether or not to cache output
     *
     * Used by:
     * - CallbackCache
     * - ClassCache
     * - ObjectCache
     *
     * @param  bool $cacheOutput
     * @return PatternOptions
     */
    public function setCacheOutput($cacheOutput)
    {
        $this->cacheOutput = (bool) $cacheOutput;
        return $this;
    }

    /**
     * Will we cache output?
     *
     * Used by:
     * - CallbackCache
     * - ClassCache
     * - ObjectCache
     *
     * @return bool
     */
    public function getCacheOutput()
    {
        return $this->cacheOutput;
    }

    /**
     * Set class name
     *
     * Used by:
     * - ClassCache
     *
     * @param  string $class
     * @throws Exception\InvalidArgumentException
     * @return PatternOptions
     */
    public function setClass($class)
    {
        if (!is_string($class)) {
            throw new Exception\InvalidArgumentException('Invalid classname provided; must be a string');
        }
        $this->class = $class;
        return $this;
    }

    /**
     * Get class name
     *
     * Used by:
     * - ClassCache
     *
     * @return null|string
     */
    public function getClass()
    {
        return $this->class;
    }

    /**
     * Set list of method return values to cache
     *
     * Used by:
     * - ClassCache
     *
     * @param  array $classCacheMethods
     * @return PatternOptions
     */
    public function setClassCacheMethods(array $classCacheMethods)
    {
        $this->classCacheMethods = $this->recursiveStrtolower($classCacheMethods);
        return $this;
    }

    /**
     * Get list of methods from which to cache return values
     *
     * Used by:
     * - ClassCache
     *
     * @return array
     */
    public function getClassCacheMethods()
    {
        return $this->classCacheMethods;
    }

    /**
     * Set list of method return values NOT to cache
     *
     * Used by:
     * - ClassCache
     *
     * @param  array $classNonCacheMethods
     * @return PatternOptions
     */
    public function setClassNonCacheMethods(array $classNonCacheMethods)
    {
        $this->classNonCacheMethods = $this->recursiveStrtolower($classNonCacheMethods);
        return $this;
    }

    /**
     * Get list of methods from which NOT to cache return values
     *
     * Used by:
     * - ClassCache
     *
     * @return array
     */
    public function getClassNonCacheMethods()
    {
        return $this->classNonCacheMethods;
    }

    /**
     * Set directory permission
     *
     * @param  false|int $dirPermission
     * @throws Exception\InvalidArgumentException
     * @return PatternOptions
     */
    public function setDirPermission($dirPermission)
    {
        if ($dirPermission !== false) {
            if (is_string($dirPermission)) {
                $dirPermission = octdec($dirPermission);
            } else {
                $dirPermission = (int) $dirPermission;
            }

            // validate
            if (($dirPermission & 0700) != 0700) {
                throw new Exception\InvalidArgumentException(
                    'Invalid directory permission: need permission to execute, read and write by owner'
                );
            }
        }

        $this->dirPermission = $dirPermission;
        return $this;
    }

    /**
     * Gets directory permission
     *
     * @return false|int
     */
    public function getDirPermission()
    {
        return $this->dirPermission;
    }

    /**
     * Set umask
     *
     * Used by:
     * - CaptureCache
     *
     * @param  false|int $umask
     * @throws Exception\InvalidArgumentException
     * @return PatternOptions
     */
    public function setUmask($umask)
    {
        if ($umask !== false) {
            if (is_string($umask)) {
                $umask = octdec($umask);
            } else {
                $umask = (int) $umask;
            }

            // validate
            if ($umask & 0700) {
                throw new Exception\InvalidArgumentException(
                    'Invalid umask: need permission to execute, read and write by owner'
                );
            }

            // normalize
            $umask = $umask & 0777;
        }

        $this->umask = $umask;
        return $this;
    }

    /**
     * Get umask
     *
     * Used by:
     * - CaptureCache
     *
     * @return false|int
     */
    public function getUmask()
    {
        return $this->umask;
    }

    /**
     * Set whether or not file locking should be used
     *
     * Used by:
     * - CaptureCache
     *
     * @param  bool $fileLocking
     * @return PatternOptions
     */
    public function setFileLocking($fileLocking)
    {
        $this->fileLocking = (bool) $fileLocking;
        return $this;
    }

    /**
     * Is file locking enabled?
     *
     * Used by:
     * - CaptureCache
     *
     * @return bool
     */
    public function getFileLocking()
    {
        return $this->fileLocking;
    }

    /**
     * Set file permission
     *
     * @param  false|int $filePermission
     * @throws Exception\InvalidArgumentException
     * @return PatternOptions
     */
    public function setFilePermission($filePermission)
    {
        if ($filePermission !== false) {
            if (is_string($filePermission)) {
                $filePermission = octdec($filePermission);
            } else {
                $filePermission = (int) $filePermission;
            }

            // validate
            if (($filePermission & 0600) != 0600) {
                throw new Exception\InvalidArgumentException(
                    'Invalid file permission: need permission to read and write by owner'
                );
            } elseif ($filePermission & 0111) {
                throw new Exception\InvalidArgumentException(
                    "Invalid file permission: Files shoudn't be executable"
                );
            }
        }

        $this->filePermission = $filePermission;
        return $this;
    }

    /**
     * Gets file permission
     *
     * @return false|int
     */
    public function getFilePermission()
    {
        return $this->filePermission;
    }

    /**
     * Set value for index filename
     *
     * @param  string $indexFilename
     * @return PatternOptions
     */
    public function setIndexFilename($indexFilename)
    {
        $this->indexFilename = (string) $indexFilename;
        return $this;
    }

    /**
     * Get value for index filename
     *
     * @return string
     */
    public function getIndexFilename()
    {
        return $this->indexFilename;
    }

    /**
     * Set object to cache
     *
     * @param  mixed $object
     * @throws Exception\InvalidArgumentException
     * @return PatternOptions
     */
    public function setObject($object)
    {
        if (!is_object($object)) {
            throw new Exception\InvalidArgumentException(sprintf(
                '%s expects an object; received "%s"', __METHOD__, gettype($object)
            ));
        }
        $this->object = $object;
        return $this;
    }

    /**
     * Get object to cache
     *
     * @return null|object
     */
    public function getObject()
    {
        return $this->object;
    }

    /**
     * Set flag indicating whether or not to cache magic properties
     *
     * Used by:
     * - ObjectCache
     *
     * @param  bool $objectCacheMagicProperties
     * @return PatternOptions
     */
    public function setObjectCacheMagicProperties($objectCacheMagicProperties)
    {
        $this->objectCacheMagicProperties = (bool) $objectCacheMagicProperties;
        return $this;
    }

    /**
     * Should we cache magic properties?
     *
     * Used by:
     * - ObjectCache
     *
     * @return bool
     */
    public function getObjectCacheMagicProperties()
    {
        return $this->objectCacheMagicProperties;
    }

    /**
     * Set list of object methods for which to cache return values
     *
     * @param  array $objectCacheMethods
     * @return PatternOptions
     * @throws Exception\InvalidArgumentException
     */
    public function setObjectCacheMethods(array $objectCacheMethods)
    {
        $this->objectCacheMethods = $this->normalizeObjectMethods($objectCacheMethods);
        return $this;
    }

    /**
     * Get list of object methods for which to cache return values
     *
     * @return array
     */
    public function getObjectCacheMethods()
    {
        return $this->objectCacheMethods;
    }

    /**
     * Set the object key part.
     *
     * Used to generate a callback key in order to speed up key generation.
     *
     * Used by:
     * - ObjectCache
     *
     * @param  mixed $objectKey
     * @return PatternOptions
     */
    public function setObjectKey($objectKey)
    {
        if ($objectKey !== null) {
            $this->objectKey = (string) $objectKey;
        } else {
            $this->objectKey = null;
        }
        return $this;
    }

    /**
     * Get object key
     *
     * Used by:
     * - ObjectCache
     *
     * @return mixed
     */
    public function getObjectKey()
    {
        if (!$this->objectKey) {
            return get_class($this->getObject());
        }
        return $this->objectKey;
    }

    /**
     * Set list of object methods for which NOT to cache return values
     *
     * @param  array $objectNonCacheMethods
     * @return PatternOptions
     * @throws Exception\InvalidArgumentException
     */
    public function setObjectNonCacheMethods(array $objectNonCacheMethods)
    {
        $this->objectNonCacheMethods = $this->normalizeObjectMethods($objectNonCacheMethods);
        return $this;
    }

    /**
     * Get list of object methods for which NOT to cache return values
     *
     * @return array
     */
    public function getObjectNonCacheMethods()
    {
        return $this->objectNonCacheMethods;
    }

    /**
     * Set location of public directory
     *
     * Used by:
     * - CaptureCache
     *
     * @param  string $publicDir
     * @throws Exception\InvalidArgumentException
     * @return PatternOptions
     */
    public function setPublicDir($publicDir)
    {
        $publicDir = (string) $publicDir;

        if (!is_dir($publicDir)) {
            throw new Exception\InvalidArgumentException(
                "Public directory '{$publicDir}' not found or not a directory"
            );
        } elseif (!is_writable($publicDir)) {
            throw new Exception\InvalidArgumentException(
                "Public directory '{$publicDir}' not writable"
            );
        } elseif (!is_readable($publicDir)) {
            throw new Exception\InvalidArgumentException(
                "Public directory '{$publicDir}' not readable"
            );
        }

        $this->publicDir = rtrim(realpath($publicDir), DIRECTORY_SEPARATOR);
        return $this;
    }

    /**
     * Get location of public directory
     *
     * Used by:
     * - CaptureCache
     *
     * @return null|string
     */
    public function getPublicDir()
    {
        return $this->publicDir;
    }

    /**
     * Set storage adapter
     *
     * Required for the following Pattern classes:
     * - CallbackCache
     * - ClassCache
     * - ObjectCache
     * - OutputCache
     *
     * @param  string|array|Storage $storage
     * @return PatternOptions
     */
    public function setStorage($storage)
    {
        $this->storage = $this->storageFactory($storage);
        return $this;
    }

    /**
     * Get storage adapter
     *
     * Used by:
     * - CallbackCache
     * - ClassCache
     * - ObjectCache
     * - OutputCache
     *
     * @return null|Storage
     */
    public function getStorage()
    {
        return $this->storage;
    }

    /**
     * Recursively apply strtolower on all values of an array, and return as a
     * list of unique values
     *
     * @param  array $array
     * @return array
     */
    protected function recursiveStrtolower(array $array)
    {
        return array_values(array_unique(array_map('strtolower', $array)));
    }

    /**
     * Normalize object methods
     *
     * Recursively casts values to lowercase, then determines if any are in a
     * list of methods not handled, raising an exception if so.
     *
     * @param  array $methods
     * @return array
     * @throws Exception\InvalidArgumentException
     */
    protected function normalizeObjectMethods(array $methods)
    {
        $methods   = $this->recursiveStrtolower($methods);
        $intersect = array_intersect(array('__set', '__get', '__unset', '__isset'), $methods);
        if (!empty($intersect)) {
            throw new Exception\InvalidArgumentException(
                "Magic properties are handled by option 'cache_magic_properties'"
            );
        }
        return $methods;
    }

    /**
     * Create a storage object from a given specification
     *
     * @param  array|string|Storage $storage
     * @throws Exception\InvalidArgumentException
     * @return Storage
     */
    protected function storageFactory($storage)
    {
        if (is_array($storage)) {
            $storage = StorageFactory::factory($storage);
        } elseif (is_string($storage)) {
            $storage = StorageFactory::adapterFactory($storage);
        } elseif (!($storage instanceof Storage)) {
            throw new Exception\InvalidArgumentException(
                'The storage must be an instanceof Zend\Cache\Storage\StorageInterface '
                . 'or an array passed to Zend\Cache\Storage::factory '
                . 'or simply the name of the storage adapter'
            );
        }

        return $storage;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache;

use Zend\ServiceManager\AbstractPluginManager;

/**
 * Plugin manager implementation for cache pattern adapters
 *
 * Enforces that adatpers retrieved are instances of
 * Pattern\PatternInterface. Additionally, it registers a number of default
 * patterns available.
 */
class PatternPluginManager extends AbstractPluginManager
{
    /**
     * Default set of adapters
     *
     * @var array
     */
    protected $invokableClasses = array(
        'callback' => 'Zend\Cache\Pattern\CallbackCache',
        'capture'  => 'Zend\Cache\Pattern\CaptureCache',
        'class'    => 'Zend\Cache\Pattern\ClassCache',
        'object'   => 'Zend\Cache\Pattern\ObjectCache',
        'output'   => 'Zend\Cache\Pattern\OutputCache',
        'page'     => 'Zend\Cache\Pattern\PageCache',
    );

    /**
     * Don't share by default
     *
     * @var array
     */
    protected $shareByDefault = false;

    /**
     * Validate the plugin
     *
     * Checks that the pattern adapter loaded is an instance of Pattern\PatternInterface.
     *
     * @param  mixed $plugin
     * @return void
     * @throws Exception\RuntimeException if invalid
     */
    public function validatePlugin($plugin)
    {
        if ($plugin instanceof Pattern\PatternInterface) {
            // we're okay
            return;
        }

        throw new Exception\RuntimeException(sprintf(
            'Plugin of type %s is invalid; must implement %s\Pattern\PatternInterface',
            (is_object($plugin) ? get_class($plugin) : gettype($plugin)),
            __NAMESPACE__
        ));
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Exception;

class ExtensionNotLoadedException extends RuntimeException
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Exception;

class InvalidArgumentException extends \InvalidArgumentException implements
    ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Exception;

class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Exception;

class OutOfSpaceException extends \OverflowException implements ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Exception;

class UnsupportedMethodCallException extends \BadMethodCallException implements
    ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Exception;

class LogicException extends \LogicException implements ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Exception;

class MissingKeyException extends RuntimeException
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Exception;

interface ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Exception;

class MissingDependencyException extends RuntimeException
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Exception;

class BadMethodCallException extends \BadMethodCallException implements
    ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Exception;

class UnexpectedValueException extends \UnexpectedValueException implements
    ExceptionInterface
{
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Service;

use Zend\Cache\StorageFactory;
use Zend\ServiceManager\AbstractFactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

/**
 * Storage cache factory for multiple caches.
 */
class StorageCacheAbstractServiceFactory implements AbstractFactoryInterface
{
    /**
     * @var array
     */
    protected $config;

    /**
     * Configuration key for cache objects
     *
     * @var string
     */
    protected $configKey = 'caches';

    /**
     * @param  ServiceLocatorInterface $services
     * @param  string                  $name
     * @param  string                  $requestedName
     * @return bool
     */
    public function canCreateServiceWithName(ServiceLocatorInterface $services, $name, $requestedName)
    {
        $config = $this->getConfig($services);
        if (empty($config)) {
            return false;
        }

        return (isset($config[$requestedName]) && is_array($config[$requestedName]));
    }

    /**
     * @param  ServiceLocatorInterface              $services
     * @param  string                               $name
     * @param  string                               $requestedName
     * @return \Zend\Cache\Storage\StorageInterface
     */
    public function createServiceWithName(ServiceLocatorInterface $services, $name, $requestedName)
    {
        $config = $this->getConfig($services);
        $config = $config[$requestedName];
        return StorageFactory::factory($config);
    }

    /**
     * Retrieve cache configuration, if any
     *
     * @param  ServiceLocatorInterface $services
     * @return array
     */
    protected function getConfig(ServiceLocatorInterface $services)
    {
        if ($this->config !== null) {
            return $this->config;
        }

        if (!$services->has('Config')) {
            $this->config = array();
            return $this->config;
        }

        $config = $services->get('Config');
        if (!isset($config[$this->configKey])) {
            $this->config = array();
            return $this->config;
        }

        $this->config = $config[$this->configKey];
        return $this->config;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache\Service;

use Zend\Cache\StorageFactory;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

/**
 * Storage cache factory.
 */
class StorageCacheFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        // Configure the cache
        $config = $serviceLocator->get('Config');
        $cacheConfig = isset($config['cache']) ? $config['cache'] : array();
        $cache = StorageFactory::factory($cacheConfig);

        return $cache;
    }
}
<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Cache;

use Traversable;
use Zend\Stdlib\ArrayUtils;

abstract class PatternFactory
{
    /**
     * The pattern manager
     *
     * @var null|PatternPluginManager
     */
    protected static $plugins = null;

    /**
     * Instantiate a cache pattern
     *
     * @param  string|Pattern\PatternInterface $patternName
     * @param  array|Traversable|Pattern\PatternOptions $options
     * @return Pattern\PatternInterface
     * @throws Exception\InvalidArgumentException
     */
    public static function factory($patternName, $options = array())
    {
        if ($options instanceof Traversable) {
            $options = ArrayUtils::iteratorToArray($options);
        }
        if (is_array($options)) {
            $options = new Pattern\PatternOptions($options);
        } elseif (!$options instanceof Pattern\PatternOptions) {
            throw new Exception\InvalidArgumentException(sprintf(
                '%s expects an array, Traversable object, or %s\Pattern\PatternOptions object; received "%s"',
                __METHOD__,
                __NAMESPACE__,
                (is_object($options) ? get_class($options) : gettype($options))
            ));
        }

        if ($patternName instanceof Pattern\PatternInterface) {
            $patternName->setOptions($options);
            return $patternName;
        }

        $pattern = static::getPluginManager()->get($patternName);
        $pattern->setOptions($options);
        return $pattern;
    }

    /**
     * Get the pattern plugin manager
     *
     * @return PatternPluginManager
     */
    public static function getPluginManager()
    {
        if (static::$plugins === null) {
            static::$plugins = new PatternPluginManager();
        }

        return static::$plugins;
    }

    /**
     * Set the pattern plugin manager
     *
     * @param  PatternPluginManager $plugins
     * @return void
     */
    public static function setPluginManager(PatternPluginManager $plugins)
    {
        static::$plugins = $plugins;
    }

    /**
     * Reset pattern plugin manager to default
     *
     * @return void
     */
    public static function resetPluginManager()
    {
        static::$plugins = null;
    }
}
<?php

// autoload.php @generated by Composer

require_once __DIR__ . '/composer' . '/autoload_real.php';

return ComposerAutoloaderInit687aaa93da4df781853324a5163d1fd6::getLoader();
{
    "name": "phpoption/phpoption",
    "description": "Option Type for PHP",
    "keywords": ["php","option","language","type"],
    "type": "library",
    "license": "Apache2",
    "authors": [
        {
            "name": "Johannes M. Schmitt",
            "email": "schmittjoh@gmail.com"
        }
    ],
    "require": {
        "php": ">=5.3.0"
    },
    "autoload": {
        "psr-0": { "PhpOption\\": "src/" }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.3-dev"
        }
    }
}
<?php

/*
 * Copyright 2012 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace PhpOption;

/**
 * Base Option Class.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
abstract class Option
{
    /**
     * Creates an option given a return value.
     *
     * This is intended for consuming existing APIs and allows you to easily
     * convert them to an option. By default, we treat ``null`` as the None case,
     * and everything else as Some.
     *
     * @param mixed $value The actual return value.
     * @param mixed $noneValue The value which should be considered "None"; null
     *                         by default.
     *
     * @return Option
     */
    public static function fromValue($value, $noneValue = null)
    {
        if ($value === $noneValue) {
            return None::create();
        }

        return new Some($value);
    }

    /**
     * Creates a lazy-option with the given callback.
     *
     * This is also a helper constructor for lazy-consuming existing APIs where
     * the return value is not yet an option. By default, we treat ``null`` as
     * None case, and everything else as Some.
     *
     * @param callable $callback The callback to evaluate.
     * @param array $arguments
     * @param mixed $noneValue The value which should be considered "None"; null
     *                         by default.
     *
     * @return Option
     */
    public static function fromReturn($callback, array $arguments = array(), $noneValue = null)
    {
        return new LazyOption(function() use ($callback, $arguments, $noneValue) {
            $return = call_user_func_array($callback, $arguments);

            if ($return === $noneValue) {
                return None::create();
            }

            return new Some($return);
        });
    }

    /**
     * Returns the value if available, or throws an exception otherwise.
     *
     * @throws \RuntimeException if value is not available
     *
     * @return mixed
     */
    abstract public function get();

    /**
     * Returns the value if available, or the default value if not.
     *
     * @param mixed $default
     *
     * @return mixed
     */
    abstract public function getOrElse($default);

    /**
     * Returns the value if available, or the results of the callable.
     *
     * This is preferable over ``getOrElse`` if the computation of the default
     * value is expensive.
     *
     * @param callable $callable
     *
     * @return mixed
     */
    abstract public function getOrCall($callable);

    /**
     * Returns the value if available, or throws the passed exception.
     *
     * @param \Exception $ex
     *
     * @return mixed
     */
    abstract public function getOrThrow(\Exception $ex);

    /**
     * Returns true if no value is available, false otherwise.
     *
     * @return boolean
     */
    abstract public function isEmpty();

    /**
     * Returns true if a value is available, false otherwise.
     *
     * @return boolean
     */
    abstract public function isDefined();

    /**
     * Returns this option if non-empty, or the passed option otherwise.
     *
     * This can be used to try multiple alternatives, and is especially useful
     * with lazy evaluating options:
     *
     * ```php
     *     $repo->findSomething()
     *         ->orElse(new LazyOption(array($repo, 'findSomethingElse')))
     *         ->orElse(new LazyOption(array($repo, 'createSomething')));
     * ```
     *
     * @param Option $else
     *
     * @return Option
     */
    abstract public function orElse(Option $else);

    /**
     * This is similar to map() below except that the return value has no meaning;
     * the passed callable is simply executed if the option is non-empty, and
     * ignored if the option is empty.
     *
     * In all cases, the return value of the callable is discarded.
     *
     * ```php
     *     $comment->getMaybeFile()->ifDefined(function($file) {
     *         // Do something with $file here.
     *     });
     * ```
     *
     * If you're looking for something like ``ifEmpty``, you can use ``getOrCall``
     * and ``getOrElse`` in these cases.
     *
     * @deprecated Use forAll() instead.
     *
     * @param callable $callable
     *
     * @return void
     */
    abstract public function ifDefined($callable);

    /**
     * This is similar to map() except that the return value of the callable has no meaning.
     *
     * The passed callable is simply executed if the option is non-empty, and ignored if the
     * option is empty. This method is preferred for callables with side-effects, while map()
     * is intended for callables without side-effects.
     *
     * @param callable $callable
     *
     * @return Option
     */
    abstract public function forAll($callable);

    /**
     * Applies the callable to the value of the option if it is non-empty,
     * and returns the return value of the callable wrapped in Some().
     *
     * If the option is empty, then the callable is not applied.
     *
     * ```php
     *     (new Some("foo"))->map('strtoupper')->get(); // "FOO"
     * ```
     *
     * @param callable $callable
     *
     * @return Option
     */
    abstract public function map($callable);

    /**
     * Applies the callable to the value of the option if it is non-empty, and
     * returns the return value of the callable directly.
     *
     * In contrast to ``map``, the return value of the callable is expected to
     * be an Option itself; it is not automatically wrapped in Some().
     *
     * @param callable $callable must return an Option
     *
     * @return Option
     */
    abstract public function flatMap($callable);

    /**
     * If the option is empty, it is returned immediately without applying the callable.
     *
     * If the option is non-empty, the callable is applied, and if it returns true,
     * the option itself is returned; otherwise, None is returned.
     *
     * @param callable $callable
     *
     * @return Option
     */
    abstract public function filter($callable);

    /**
     * If the option is empty, it is returned immediately without applying the callable.
     *
     * If the option is non-empty, the callable is applied, and if it returns false,
     * the option itself is returned; otherwise, None is returned.
     *
     * @param callable $callable
     *
     * @return Option
     */
    abstract public function filterNot($callable);

    /**
     * If the option is empty, it is returned immediately.
     *
     * If the option is non-empty, and its value does not equal the passed value
     * (via a shallow comparison ===), then None is returned. Otherwise, the
     * Option is returned.
     *
     * In other words, this will filter all but the passed value.
     *
     * @param mixed $value
     *
     * @return Option
     */
    abstract public function select($value);

    /**
     * If the option is empty, it is returned immediately.
     *
     * If the option is non-empty, and its value does equal the passed value (via
     * a shallow comparison ===), then None is returned; otherwise, the Option is
     * returned.
     *
     * In other words, this will let all values through expect the passed value.
     * 
     * @param mixed $value
     *
     * @return Option
     */
    abstract public function reject($value);
}
<?php

/*
 * Copyright 2012 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace PhpOption;

final class None extends Option
{
    private static $instance;

    public static function create()
    {
        if (null === self::$instance) {
            self::$instance = new self();
        }

        return self::$instance;
    }

    public function get()
    {
        throw new \RuntimeException('None has no value.');
    }

    public function getOrCall($callable)
    {
        return call_user_func($callable);
    }

    public function getOrElse($default)
    {
        return $default;
    }

    public function getOrThrow(\Exception $ex)
    {
        throw $ex;
    }

    public function isEmpty()
    {
        return true;
    }

    public function isDefined()
    {
        return false;
    }

    public function orElse(Option $else)
    {
        return $else;
    }

    /**
     * @deprecated Use forAll() instead.
     */
    public function ifDefined($callable)
    {
        // Just do nothing in that case.
    }

    public function forAll($callable)
    {
        return $this;
    }

    public function map($callable)
    {
        return $this;
    }

    public function flatMap($callable)
    {
        return $this;
    }

    public function filter($callable)
    {
        return $this;
    }

    public function filterNot($callable)
    {
        return $this;
    }

    public function select($value)
    {
        return $this;
    }

    public function reject($value)
    {
        return $this;
    }

    private function __construct() { }
}<?php

/*
 * Copyright 2012 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace PhpOption;

final class LazyOption extends Option
{
    /** @var callable */
    private $callback;

    /** @var array */
    private $arguments;

    /** @var Option|null */
    private $option;

    /**
     * Helper Constructor.
     *
     * @param callable $callback
     * @param array $arguments
     *
     * @return LazyOption
     */
    public static function create($callback, array $arguments = array())
    {
        return new self($callback, $arguments);
    }

    /**
     * Constructor.
     *
     * @param callable $callback
     * @param array $arguments
     */
    public function __construct($callback, array $arguments = array())
    {
        if (!is_callable($callback)) {
            throw new \InvalidArgumentException('Invalid callback given');
        }

        $this->callback = $callback;
        $this->arguments = $arguments;
    }

    public function isDefined()
    {
        return $this->option()->isDefined();
    }

    public function isEmpty()
    {
        return $this->option()->isEmpty();
    }

    public function get()
    {
        return $this->option()->get();
    }

    public function getOrElse($default)
    {
        return $this->option()->getOrElse($default);
    }

    public function getOrCall($callable)
    {
        return $this->option()->getOrCall($callable);
    }

    public function getOrThrow(\Exception $ex)
    {
        return $this->option()->getOrThrow($ex);
    }

    public function orElse(Option $else)
    {
        return $this->option()->orElse($else);
    }

    /**
     * @deprecated Use forAll() instead.
     */
    public function ifDefined($callable)
    {
        $this->option()->ifDefined($callable);
    }

    public function forAll($callable)
    {
        return $this->option()->forAll($callable);
    }

    public function map($callable)
    {
        return $this->option()->map($callable);
    }

    public function flatMap($callable)
    {
        return $this->option()->flatMap($callable);
    }

    public function filter($callable)
    {
        return $this->option()->filter($callable);
    }

    public function filterNot($callable)
    {
        return $this->option()->filterNot($callable);
    }

    public function select($value)
    {
        return $this->option()->select($value);
    }

    public function reject($value)
    {
        return $this->option()->reject($value);
    }

    /**
     * @return Option
     */
    private function option()
    {
        if ($this->option === null) {
            $this->option = call_user_func_array($this->callback, $this->arguments);
            if (!$this->option instanceof Option) {
                $this->option = null;
                throw new \RuntimeException('Expected instance of \PhpOption\Option');
            }
        }

        return $this->option;
    }
}
<?php

/*
 * Copyright 2012 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace PhpOption;

final class Some extends Option
{
    private $value;

    public function __construct($value)
    {
        $this->value = $value;
    }

    public static function create($value)
    {
        return new self($value);
    }

    public function isDefined()
    {
        return true;
    }

    public function isEmpty()
    {
        return false;
    }

    public function get()
    {
        return $this->value;
    }

    public function getOrElse($default)
    {
        return $this->value;
    }

    public function getOrCall($callable)
    {
        return $this->value;
    }

    public function getOrThrow(\Exception $ex)
    {
        return $this->value;
    }

    public function orElse(Option $else)
    {
        return $this;
    }

    /**
     * @deprecated Use forAll() instead.
     */
    public function ifDefined($callable)
    {
        call_user_func($callable, $this->value);
    }

    public function forAll($callable)
    {
        call_user_func($callable, $this->value);

        return $this;
    }

    public function map($callable)
    {
        return new self(call_user_func($callable, $this->value));
    }

    public function flatMap($callable)
    {
        $rs = call_user_func($callable, $this->value);
        if ( ! $rs instanceof Option) {
            throw new \RuntimeException('Callables passed to flatMap() must return an Option. Maybe you should use map() instead?');
        }

        return $rs;
    }

    public function filter($callable)
    {
        if (true === call_user_func($callable, $this->value)) {
            return $this;
        }

        return None::create();
    }

    public function filterNot($callable)
    {
        if (false === call_user_func($callable, $this->value)) {
            return $this;
        }

        return None::create();
    }

    public function select($value)
    {
        if ($this->value === $value) {
            return $this;
        }

        return None::create();
    }

    public function reject($value)
    {
        if ($this->value === $value) {
            return None::create();
        }

        return $this;
    }
}
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.<?php

namespace PhpOption\Tests;

use PhpOption\Some;

class SomeTest extends \PHPUnit_Framework_TestCase
{
    public function testGet()
    {
        $some = new \PhpOption\Some('foo');
        $this->assertEquals('foo', $some->get());
        $this->assertEquals('foo', $some->getOrElse(null));
        $this->assertEquals('foo', $some->getOrCall('does_not_exist'));
        $this->assertEquals('foo', $some->getOrThrow(new \RuntimeException('Not found')));
        $this->assertFalse($some->isEmpty());
    }

    public function testCreate()
    {
        $some = \PhpOption\Some::create('foo');
        $this->assertEquals('foo', $some->get());
        $this->assertEquals('foo', $some->getOrElse(null));
        $this->assertEquals('foo', $some->getOrCall('does_not_exist'));
        $this->assertEquals('foo', $some->getOrThrow(new \RuntimeException('Not found')));
        $this->assertFalse($some->isEmpty());
    }

    public function testOrElse()
    {
        $some = \PhpOption\Some::create('foo');
        $this->assertSame($some, $some->orElse(\PhpOption\None::create()));
        $this->assertSame($some, $some->orElse(\PhpOption\Some::create('bar')));
    }

    public function testifDefined()
    {
        $called = false;
        $self = $this;
        $some = new Some('foo');
        $this->assertNull($some->ifDefined(function($v) use (&$called, $self) {
            $called = true;
            $self->assertEquals('foo', $v);
        }));
        $this->assertTrue($called);
    }

    public function testForAll()
    {
        $called = false;
        $self = $this;
        $some = new Some('foo');
        $this->assertSame($some, $some->forAll(function($v) use (&$called, $self) {
            $called = true;
            $self->assertEquals('foo', $v);
        }));
        $this->assertTrue($called);
    }

    public function testMap()
    {
        $some = new Some('foo');
        $this->assertEquals('o', $some->map(function($v) { return substr($v, 1, 1); })->get());
    }

    public function testFlatMap()
    {
        $repo = new Repository(array('foo'));

        $this->assertEquals(array('name' => 'foo'), $repo->getLastRegisteredUsername()
                                                        ->flatMap(array($repo, 'getUser'))
                                                        ->getOrCall(array($repo, 'getDefaultUser')));
    }

    public function testFilter()
    {
        $some = new Some('foo');

        $this->assertInstanceOf('PhpOption\None', $some->filter(function($v) { return 0 === strlen($v); }));
        $this->assertSame($some, $some->filter(function($v) { return strlen($v) > 0; }));
    }

    public function testFilterNot()
    {
        $some = new Some('foo');

        $this->assertInstanceOf('PhpOption\None', $some->filterNot(function($v) { return strlen($v) > 0; }));
        $this->assertSame($some, $some->filterNot(function($v) { return strlen($v) === 0; }));
    }

    public function testSelect()
    {
        $some = new Some('foo');

        $this->assertSame($some, $some->select('foo'));
        $this->assertInstanceOf('PhpOption\None', $some->select('bar'));
        $this->assertInstanceOf('PhpOption\None', $some->select(true));
    }

    public function testReject()
    {
        $some = new Some('foo');

        $this->assertSame($some, $some->reject(null));
        $this->assertSame($some, $some->reject(true));
        $this->assertInstanceOf('PhpOption\None', $some->reject('foo'));
    }
}

// For the interested reader of these tests, we have gone some great lengths
// to come up with a non-contrived example that might also be used in the
// real-world, and not only for testing purposes :)
class Repository
{
    private $users;

    public function __construct(array $users = array())
    {
        $this->users = $users;
    }

    // A fast ID lookup, probably cached, sometimes we might not need the entire user.
    public function getLastRegisteredUsername()
    {
        if (empty($this->users)) {
            return \PhpOption\None::create();
        }

        return new Some(end($this->users));
    }

    // Returns a user object (we will live with an array here).
    public function getUser($name)
    {
        if (in_array($name, $this->users, true)) {
            return new Some(array('name' => $name));
        }

        return \PhpOption\None::create();
    }

    public function getDefaultUser()
    {
        return array('name' => 'muhuhu');
    }
}
<?php

namespace PhpOption\Tests;

class OptionTest extends \PHPUnit_Framework_TestCase
{
    public function testfromValueWithDefaultNoneValue()
    {
        $this->assertInstanceOf('PhpOption\None', \PhpOption\Option::fromValue(null));
        $this->assertInstanceOf('PhpOption\Some', \PhpOption\Option::fromValue('value'));
    }

    public function testFromValueWithFalseNoneValue()
    {
        $this->assertInstanceOf('PhpOption\None', \PhpOption\Option::fromValue(false, false));
        $this->assertInstanceOf('PhpOption\Some', \PhpOption\Option::fromValue('value', false));
        $this->assertInstanceOf('PhpOption\Some', \PhpOption\Option::fromValue(null, false));
    }

    public function testFromReturn()
    {
        $null = function() { return null; };
        $false = function() { return false; };
        $some = function() { return 'foo'; };

        $this->assertTrue(\PhpOption\Option::fromReturn($null)->isEmpty());
        $this->assertFalse(\PhpOption\Option::fromReturn($false)->isEmpty());
        $this->assertTrue(\PhpOption\Option::fromReturn($false, array(), false)->isEmpty());
        $this->assertTrue(\PhpOption\Option::fromReturn($some)->isDefined());
        $this->assertFalse(\PhpOption\Option::fromReturn($some, array(), 'foo')->isDefined());
    }

    public function testOrElse()
    {
        $a = new \PhpOption\Some('a');
        $b = new \PhpOption\Some('b');

        $this->assertEquals('a', $a->orElse($b)->get());
    }

    public function testOrElseWithNoneAsFirst()
    {
        $a = \PhpOption\None::create();
        $b = new \PhpOption\Some('b');

        $this->assertEquals('b', $a->orElse($b)->get());
    }

    public function testOrElseWithLazyOptions()
    {
        $throws = function() { throw new \LogicException('Should never be called.'); };

        $a = new \PhpOption\Some('a');
        $b = new \PhpOption\LazyOption($throws);

        $this->assertEquals('a', $a->orElse($b)->get());
    }

    public function testOrElseWithMultipleAlternatives()
    {
        $throws = new \PhpOption\LazyOption(function() { throw new \LogicException('Should never be called.'); });
        $returns = new \PhpOption\LazyOption(function() { return new \PhpOption\Some('foo'); });

        $a = \PhpOption\None::create();

        $this->assertEquals('foo', $a->orElse($returns)->orElse($throws)->get());
    }
}<?php

namespace PhpOption\Tests;

use PhpOption\None;

class NoneTest extends \PHPUnit_Framework_TestCase
{
    private $none;

    /**
     * @expectedException \RuntimeException
     */
    public function testGet()
    {
        $none = \PhpOption\None::create();
        $none->get();
    }

    public function testGetOrElse()
    {
        $none = \PhpOption\None::create();
        $this->assertEquals('foo', $none->getOrElse('foo'));
    }

    public function testGetOrCall()
    {
        $none = \PhpOption\None::create();
        $this->assertEquals('foo', $none->getOrCall(function() { return 'foo'; }));
    }

    /**
     * @expectedException \RuntimeException
     * @expectedExceptionMessage Not Found!
     */
    public function testGetOrThrow()
    {
        None::create()->getOrThrow(new \RuntimeException('Not Found!'));
    }

    public function testIsEmpty()
    {
        $none = \PhpOption\None::create();
        $this->assertTrue($none->isEmpty());
    }

    public function testOrElse()
    {
        $option = \PhpOption\Some::create('foo');
        $this->assertSame($option, \PhpOption\None::create()->orElse($option));
    }

    public function testifDefined()
    {
        $this->assertNull($this->none->ifDefined(function() {
            throw new \LogicException('Should never be called.');
        }));
    }

    public function testForAll()
    {
        $this->assertSame($this->none, $this->none->forAll(function() {
            throw new \LogicException('Should never be called.');
        }));
    }

    public function testMap()
    {
        $this->assertSame($this->none, $this->none->map(function() {
            throw new \LogicException('Should not be called.');
        }));
    }

    public function testFlatMap()
    {
        $this->assertSame($this->none, $this->none->flatMap(function() {
            throw new \LogicException('Should not be called.');
        }));
    }

    public function testFilter()
    {
        $this->assertSame($this->none, $this->none->filter(function() {
            throw new \LogicException('Should not be called.');
        }));
    }

    public function testFilterNot()
    {
        $this->assertSame($this->none, $this->none->filterNot(function() {
            throw new \LogicException('Should not be called.');
        }));
    }

    public function testSelect()
    {
        $this->assertSame($this->none, $this->none->select(null));
    }

    public function testReject()
    {
        $this->assertSame($this->none, $this->none->reject(null));
    }

    protected function setUp()
    {
        $this->none = None::create();
    }
}<?php

namespace PhpOption\Tests;

/**
 * @group performance
 */
class PerformanceTest extends \PHPUnit_Framework_TestCase
{
    private $traditionalRepo;
    private $phpOptionRepo;

    public function testSomeCase()
    {
        $traditionalTime = microtime(true);
        for ($i=0; $i<10000; $i++) {
            if (null === $rs = $this->traditionalRepo->findMaybe(true)) {
                $rs = new \stdClass();
            }
        }
        $traditionalTime = microtime(true) - $traditionalTime;

        $phpOptionTime = microtime(true);
        for ($i=0; $i<10000; $i++) {
            $rs = $this->phpOptionRepo->findMaybe(true)->getOrElse(new \stdClass);
        }
        $phpOptionTime = microtime(true) - $phpOptionTime;

        $overheadPerInvocation = ($phpOptionTime - $traditionalTime) / 10000;
        printf("Overhead per invocation (some case): %.9fs\n", $overheadPerInvocation);
    }

    public function testNoneCase()
    {
        $traditionalTime = microtime(true);
        for ($i=0; $i<10000; $i++) {
            if (null === $rs = $this->traditionalRepo->findMaybe(false)) {
                $rs = new \stdClass();
            }
        }
        $traditionalTime = microtime(true) - $traditionalTime;

        $phpOptionTime = microtime(true);
        for ($i=0; $i<10000; $i++) {
            $rs = $this->phpOptionRepo->findMaybe(false)->getOrElse(new \stdClass);
        }
        $phpOptionTime = microtime(true) - $phpOptionTime;

        $overheadPerInvocation = ($phpOptionTime - $traditionalTime) / 10000;
        printf("Overhead per invocation (none case): %.9fs\n", $overheadPerInvocation);
    }

    protected function setUp()
    {
        $this->traditionalRepo = new TraditionalRepo();
        $this->phpOptionRepo = new PhpOptionRepo();
    }
}

class TraditionalRepo
{
    public function findMaybe($success)
    {
        if ($success) {
            return new \stdClass;
        }

        return null;
    }
}

class PhpOptionRepo
{
    public function findMaybe($success)
    {
        if ($success) {
            return new \PhpOption\Some(new \stdClass);
        }

        return \PhpOption\None::create();
    }
}<?php

namespace PhpOption\Tests;

use PhpOption\LazyOption;

class LazyOptionTest extends \PHPUnit_Framework_TestCase
{
    private $subject;

    public function setUp()
    {
        $this->subject = $this
            ->getMockBuilder('Subject')
            ->setMethods(array('execute'))
            ->getMock();
    }

    public function testGetWithArgumentsAndConstructor()
    {
        $some = \PhpOption\LazyOption::create(array($this->subject, 'execute'), array('foo'));

        $this->subject
            ->expects($this->once())
            ->method('execute')
            ->with('foo')
            ->will($this->returnValue(\PhpOption\Some::create('foo')));

        $this->assertEquals('foo', $some->get());
        $this->assertEquals('foo', $some->getOrElse(null));
        $this->assertEquals('foo', $some->getOrCall('does_not_exist'));
        $this->assertEquals('foo', $some->getOrThrow(new \RuntimeException('does_not_exist')));
        $this->assertFalse($some->isEmpty());
    }

    public function testGetWithArgumentsAndCreate()
    {
        $some = new \PhpOption\LazyOption(array($this->subject, 'execute'), array('foo'));

        $this->subject
            ->expects($this->once())
            ->method('execute')
            ->with('foo')
            ->will($this->returnValue(\PhpOption\Some::create('foo')));

        $this->assertEquals('foo', $some->get());
        $this->assertEquals('foo', $some->getOrElse(null));
        $this->assertEquals('foo', $some->getOrCall('does_not_exist'));
        $this->assertEquals('foo', $some->getOrThrow(new \RuntimeException('does_not_exist')));
        $this->assertFalse($some->isEmpty());
    }

    public function testGetWithoutArgumentsAndConstructor()
    {
        $some = new \PhpOption\LazyOption(array($this->subject, 'execute'));

        $this->subject
            ->expects($this->once())
            ->method('execute')
            ->will($this->returnValue(\PhpOption\Some::create('foo')));

        $this->assertEquals('foo', $some->get());
        $this->assertEquals('foo', $some->getOrElse(null));
        $this->assertEquals('foo', $some->getOrCall('does_not_exist'));
        $this->assertEquals('foo', $some->getOrThrow(new \RuntimeException('does_not_exist')));
        $this->assertFalse($some->isEmpty());
    }

    public function testGetWithoutArgumentsAndCreate()
    {
        $option = \PhpOption\LazyOption::create(array($this->subject, 'execute'));

        $this->subject
            ->expects($this->once())
            ->method('execute')
            ->will($this->returnValue(\PhpOption\Some::create('foo')));

        $this->assertTrue($option->isDefined());
        $this->assertFalse($option->isEmpty());
        $this->assertEquals('foo', $option->get());
        $this->assertEquals('foo', $option->getOrElse(null));
        $this->assertEquals('foo', $option->getOrCall('does_not_exist'));
        $this->assertEquals('foo', $option->getOrThrow(new \RuntimeException('does_not_exist')));
    }

    /**
     * @expectedException \RuntimeException
     * @expectedExceptionMessage None has no value
     */
    public function testCallbackReturnsNull()
    {
        $option = \PhpOption\LazyOption::create(array($this->subject, 'execute'));

        $this->subject
            ->expects($this->once())
            ->method('execute')
            ->will($this->returnValue(\PhpOption\None::create()));

        $this->assertFalse($option->isDefined());
        $this->assertTrue($option->isEmpty());
        $this->assertEquals('alt', $option->getOrElse('alt'));
        $this->assertEquals('alt', $option->getOrCall(function(){return 'alt';}));

        $option->get();
    }

    /**
     * @expectedException \RuntimeException
     * @expectedExceptionMessage Expected instance of \PhpOption\Option
     */
    public function testExceptionIsThrownIfCallbackReturnsNonOption()
    {
        $option = \PhpOption\LazyOption::create(array($this->subject, 'execute'));

        $this->subject
            ->expects($this->once())
            ->method('execute')
            ->will($this->returnValue(null));

        $this->assertFalse($option->isDefined());
    }

    /**
     * @expectedException InvalidArgumentException
     * @expectedExceptionMessage Invalid callback given
     */
    public function testInvalidCallbackAndConstructor()
    {
        new \PhpOption\LazyOption('invalidCallback');
    }

    /**
     * @expectedException InvalidArgumentException
     * @expectedExceptionMessage Invalid callback given
     */
    public function testInvalidCallbackAndCreate()
    {
        \PhpOption\LazyOption::create('invalidCallback');
    }

    public function testifDefined()
    {
        $called = false;
        $self = $this;
        $this->assertNull(LazyOption::fromValue('foo')->ifDefined(function($v) use (&$called, $self) {
            $called = true;
            $self->assertEquals('foo', $v);
        }));
        $this->assertTrue($called);
    }

    public function testForAll()
    {
        $called = false;
        $self = $this;
        $this->assertInstanceOf('PhpOption\Some', LazyOption::fromValue('foo')->forAll(function($v) use (&$called, $self) {
            $called = true;
            $self->assertEquals('foo', $v);
        }));
        $this->assertTrue($called);
    }

    public function testOrElse()
    {
        $some = \PhpOption\Some::create('foo');
        $lazy = \PhpOption\LazyOption::create(function() use ($some) {return $some;});
        $this->assertSame($some, $lazy->orElse(\PhpOption\None::create()));
        $this->assertSame($some, $lazy->orElse(\PhpOption\Some::create('bar')));
    }
}
<?php

if ( ! is_file($autoloadFile = __DIR__.'/../vendor/autoload.php')) {
    echo 'Could not find "vendor/autoload.php". Did you forget to run "composer install --dev"?'.PHP_EOL;
    exit(1);
}

require_once $autoloadFile;<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="tests/bootstrap.php"
>
    <testsuites>
        <testsuite name="PhpOption Type Test Suite">
            <directory>./tests/PhpOption/</directory>
        </testsuite>
    </testsuites>

    <groups>
        <exclude>
            <group>performance</group>
        </exclude>
    </groups>
</phpunit>
{
    "name": "doctrine/annotations",
    "type": "library",
    "description": "Docblock Annotations Parser",
    "keywords": ["annotations", "docblock", "parser"],
    "homepage": "http://www.doctrine-project.org",
    "license": "MIT",
    "authors": [
        {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"},
        {"name": "Roman Borschel", "email": "roman@code-factory.org"},
        {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"},
        {"name": "Jonathan Wage", "email": "jonwage@gmail.com"},
        {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"}
    ],
    "require": {
        "php": ">=5.3.2",
        "doctrine/lexer": "1.*"
    },
    "require-dev": {
        "doctrine/cache": "1.*"
    },
    "autoload": {
        "psr-0": { "Doctrine\\Common\\Annotations\\": "lib/" }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.0.x-dev"
        }
    }
}
<?php
/*
 * This file bootstraps the test environment.
 */
namespace Doctrine\Tests;

error_reporting(E_ALL | E_STRICT);

// register silently failing autoloader
spl_autoload_register(function($class)
{
    if (0 === strpos($class, 'Doctrine\Tests\\')) {
        $path = __DIR__.'/../../'.strtr($class, '\\', '/').'.php';
        if (is_file($path) && is_readable($path)) {
            require_once $path;

            return true;
        }
    }
});

require_once __DIR__ . "/../../../vendor/autoload.php";

\Doctrine\Common\Annotations\AnnotationRegistry::registerAutoloadNamespace(
    'Doctrine\Tests\Common\Annotations\Fixtures', __DIR__ . '/../../'
);
<?php

use Doctrine\Common\Annotations\Annotation;

/** @Annotation */
class TopLevelAnnotation extends Annotation
{
}
<?php
// Some class named Entity in the global namespace
/**
 * @Annotation
 */
class Entity
{
}
<?php

namespace Doctrine\Tests\Common\Annotations\Ticket;

use Doctrine\Tests\Common\Annotations\Fixtures\Controller;

/**
 * @group
 */
class DCOM55Test extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     * @expectedExceptionMessage [Semantical Error] The class "Doctrine\Tests\Common\Annotations\Fixtures\Controller" is not annotated with @Annotation. Are you sure this class can be used as annotation? If so, then you need to add @Annotation to the _class_ doc comment of "Doctrine\Tests\Common\Annotations\Fixtures\Controller". If it is indeed no annotation, then you need to add @IgnoreAnnotation("Controller") to the _class_ doc comment of class Doctrine\Tests\Common\Annotations\Ticket\Dummy.
     */
    public function testIssue()
    {
        $class = new \ReflectionClass(__NAMESPACE__ . '\\Dummy');
        $reader = new \Doctrine\Common\Annotations\AnnotationReader();
        $reader->getClassAnnotations($class);
    }

    public function testAnnotation()
    {
        $class = new \ReflectionClass(__NAMESPACE__ . '\\DCOM55Consumer');
        $reader = new \Doctrine\Common\Annotations\AnnotationReader();
        $annots = $reader->getClassAnnotations($class);

        $this->assertEquals(1, count($annots));
        $this->assertInstanceOf(__NAMESPACE__.'\\DCOM55Annotation', $annots[0]);
    }

    public function testParseAnnotationDocblocks()
    {
        $class = new \ReflectionClass(__NAMESPACE__ . '\\DCOM55Annotation');
        $reader = new \Doctrine\Common\Annotations\AnnotationReader();
        $annots = $reader->getClassAnnotations($class);

        $this->assertEquals(0, count($annots));
    }
}

/**
 * @Controller
 */
class Dummy
{

}

/**
 * @Annotation
 */
class DCOM55Annotation
{

}

/**
 * @DCOM55Annotation
 */
class DCOM55Consumer
{

}<?php
namespace Doctrine\Tests\Common\Annotations\Ticket;

//Some class named Entity in the global namespace
include __DIR__ .'/DCOM58Entity.php';

/**
 * @group DCOM58
 */
class DCOM58Test extends \PHPUnit_Framework_TestCase
{
    public function testIssue()
    {
        $reader     = new \Doctrine\Common\Annotations\AnnotationReader();
        $result     = $reader->getClassAnnotations(new \ReflectionClass(__NAMESPACE__."\MappedClass"));

        foreach ($result as $annot) {
            $classAnnotations[get_class($annot)] = $annot;
        }

        $this->assertTrue(!isset($classAnnotations['']), 'Class "xxx" is not a valid entity or mapped super class.');
    }

    public function testIssueGlobalNamespace()
    {
        $docblock   = "@Entity";
        $parser     = new \Doctrine\Common\Annotations\DocParser();
        $parser->setImports(array(
            "__NAMESPACE__" =>"Doctrine\Tests\Common\Annotations\Ticket\Doctrine\ORM\Mapping"
        ));

        $annots     = $parser->parse($docblock);

        $this->assertEquals(1, count($annots));
        $this->assertInstanceOf("Doctrine\Tests\Common\Annotations\Ticket\Doctrine\ORM\Mapping\Entity", $annots[0]);
    }

    public function testIssueNamespaces()
    {
        $docblock   = "@Entity";
        $parser     = new \Doctrine\Common\Annotations\DocParser();
        $parser->addNamespace("Doctrine\Tests\Common\Annotations\Ticket\Doctrine\ORM");

        $annots     = $parser->parse($docblock);

        $this->assertEquals(1, count($annots));
        $this->assertInstanceOf("Doctrine\Tests\Common\Annotations\Ticket\Doctrine\ORM\Entity", $annots[0]);
    }

    public function testIssueMultipleNamespaces()
    {
        $docblock   = "@Entity";
        $parser     = new \Doctrine\Common\Annotations\DocParser();
        $parser->addNamespace("Doctrine\Tests\Common\Annotations\Ticket\Doctrine\ORM\Mapping");
        $parser->addNamespace("Doctrine\Tests\Common\Annotations\Ticket\Doctrine\ORM");

        $annots     = $parser->parse($docblock);

        $this->assertEquals(1, count($annots));
        $this->assertInstanceOf("Doctrine\Tests\Common\Annotations\Ticket\Doctrine\ORM\Mapping\Entity", $annots[0]);
    }

    public function testIssueWithNamespacesOrImports()
    {
        $docblock   = "@Entity";
        $parser     = new \Doctrine\Common\Annotations\DocParser();
        $annots     = $parser->parse($docblock);

        $this->assertEquals(1, count($annots));
        $this->assertInstanceOf("Entity", $annots[0]);
        $this->assertEquals(1, count($annots));
    }


    public function testIssueSimpleAnnotationReader()
    {
        $reader     = new \Doctrine\Common\Annotations\SimpleAnnotationReader();
        $reader->addNamespace('Doctrine\Tests\Common\Annotations\Ticket\Doctrine\ORM\Mapping');
        $annots     = $reader->getClassAnnotations(new \ReflectionClass(__NAMESPACE__."\MappedClass"));

        $this->assertEquals(1, count($annots));
        $this->assertInstanceOf("Doctrine\Tests\Common\Annotations\Ticket\Doctrine\ORM\Mapping\Entity", $annots[0]);
    }

}

/**
 * @Entity
 */
class MappedClass
{

}


namespace Doctrine\Tests\Common\Annotations\Ticket\Doctrine\ORM\Mapping;
/**
* @Annotation
*/
class Entity
{

}

namespace Doctrine\Tests\Common\Annotations\Ticket\Doctrine\ORM;
/**
* @Annotation
*/
class Entity
{

}
<?php

namespace Doctrine\Tests\Common\Annotations;

use Doctrine\Common\Annotations\FileCacheReader;
use Doctrine\Common\Cache\ArrayCache;
use Doctrine\Common\Annotations\CachedReader;
use Doctrine\Common\Annotations\DocLexer;
use Doctrine\Common\Annotations\DocParser;
use Doctrine\Common\Annotations\PhpParser;
use Doctrine\Common\Annotations\AnnotationReader;

require_once __DIR__ . '/Fixtures/Annotation/Route.php';
require_once __DIR__ . '/Fixtures/Annotation/Template.php';
require_once __DIR__ . '/Fixtures/Annotation/Secure.php';
require_once __DIR__ . '/Fixtures/SingleClassLOC1000.php';

class PerformanceTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @group performance
     */
    public function testCachedReadPerformanceWithInMemory()
    {
        $reader = new CachedReader(new AnnotationReader(), new ArrayCache());
        $method = $this->getMethod();

        $time = microtime(true);
        for ($i=0,$c=500; $i<$c; $i++) {
            $reader->getMethodAnnotations($method);
        }
        $time = microtime(true) - $time;

        $this->printResults('cached reader (in-memory)', $time, $c);
    }

    /**
     * @group performance
     */
    public function testCachedReadPerformanceWithFileCache()
    {
        $method = $this->getMethod();

        // prime cache
        $reader = new FileCacheReader(new AnnotationReader(), sys_get_temp_dir());
        $reader->getMethodAnnotations($method);

        $time = microtime(true);
        for ($i=0,$c=500; $i<$c; $i++) {
            $reader = new FileCacheReader(new AnnotationReader(), sys_get_temp_dir());
            $reader->getMethodAnnotations($method);
            clearstatcache();
        }
        $time = microtime(true) - $time;

        $this->printResults('cached reader (file)', $time, $c);
    }

    /**
     * @group performance
     */
    public function testReadPerformance()
    {
        $method = $this->getMethod();

        $time = microtime(true);
        for ($i=0,$c=150; $i<$c; $i++) {
            $reader = new AnnotationReader();
            $reader->getMethodAnnotations($method);
        }
        $time = microtime(true) - $time;

        $this->printResults('reader', $time, $c);
    }

    /**
     * @group performance
     */
    public function testDocParsePerformance()
    {
        $imports = array(
            'ignorephpdoc'     => 'Annotations\Annotation\IgnorePhpDoc',
            'ignoreannotation' => 'Annotations\Annotation\IgnoreAnnotation',
            'route'            => 'Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Route',
            'template'         => 'Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Template',
            '__NAMESPACE__'    => 'Doctrine\Tests\Common\Annotations\Fixtures',
        );
        $ignored = array(
            'access', 'author', 'copyright', 'deprecated', 'example', 'ignore',
            'internal', 'link', 'see', 'since', 'tutorial', 'version', 'package',
            'subpackage', 'name', 'global', 'param', 'return', 'staticvar',
            'static', 'var', 'throws', 'inheritdoc',
        );

        $method = $this->getMethod();
        $methodComment = $method->getDocComment();
        $classComment = $method->getDeclaringClass()->getDocComment();

        $time = microtime(true);
        for ($i=0,$c=200; $i<$c; $i++) {
            $parser = new DocParser();
            $parser->setImports($imports);
            $parser->setIgnoredAnnotationNames($ignored);
            $parser->setIgnoreNotImportedAnnotations(true);

            $parser->parse($methodComment);
            $parser->parse($classComment);
        }
        $time = microtime(true) - $time;

        $this->printResults('doc-parser', $time, $c);
    }

    /**
     * @group performance
     */
    public function testDocLexerPerformance()
    {
        $method = $this->getMethod();
        $methodComment = $method->getDocComment();
        $classComment = $method->getDeclaringClass()->getDocComment();

        $time = microtime(true);
        for ($i=0,$c=500; $i<$c; $i++) {
            $lexer = new DocLexer();
            $lexer->setInput($methodComment);
            $lexer->setInput($classComment);
        }
        $time = microtime(true) - $time;

        $this->printResults('doc-lexer', $time, $c);
    }

    /**
     * @group performance
     */
    public function testPhpParserPerformanceWithShortCut()
    {
        $class = new \ReflectionClass('Doctrine\Tests\Common\Annotations\Fixtures\NamespacedSingleClassLOC1000');

        $time = microtime(true);
        for ($i=0,$c=500; $i<$c; $i++) {
            $parser = new PhpParser();
            $parser->parseClass($class);
        }
        $time = microtime(true) - $time;

        $this->printResults('doc-parser-with-short-cut', $time, $c);
    }

    /**
     * @group performance
     */
    public function testPhpParserPerformanceWithoutShortCut()
    {
        $class = new \ReflectionClass('SingleClassLOC1000');

        $time = microtime(true);
        for ($i=0,$c=500; $i<$c; $i++) {
            $parser = new PhpParser();
            $parser->parseClass($class);
        }
        $time = microtime(true) - $time;

        $this->printResults('doc-parser-without-short-cut', $time, $c);
    }

    private function getMethod()
    {
        return new \ReflectionMethod('Doctrine\Tests\Common\Annotations\Fixtures\Controller', 'helloAction');
    }

    private function printResults($test, $time, $iterations)
    {
        if (0 == $iterations) {
            throw new \InvalidArgumentException('$iterations cannot be zero.');
        }

        $title = $test." results:\n";
        $iterationsText = sprintf("Iterations:         %d\n", $iterations);
        $totalTime      = sprintf("Total Time:         %.3f s\n", $time);
        $iterationTime  = sprintf("Time per iteration: %.3f ms\n", $time/$iterations * 1000);

        $max = max(strlen($title), strlen($iterationTime)) - 1;

        echo "\n".str_repeat('-', $max)."\n";
        echo $title;
        echo str_repeat('=', $max)."\n";
        echo $iterationsText;
        echo $totalTime;
        echo $iterationTime;
        echo str_repeat('-', $max)."\n";
    }
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

use Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetClass;
use Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAnnotation;

/**
 * @AnnotationTargetClass("Some data")
 */
class ClassWithInvalidAnnotationTargetAtProperty
{

    /**
     * @AnnotationTargetClass("Bar")
     */
    public $foo;


    /**
     * @AnnotationTargetAnnotation("Foo")
     */
    public $bar;
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;


/**
 * @Annotation
 * @Target("METHOD")
 */
final class AnnotationTargetMethod
{
    public $data;
    public $name;
    public $target;
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

/**
 * @Annotation
 * @Target({ "ANNOTATION" })
 */
final class AnnotationTargetAnnotation
{
    public $data;
    public $name;
    public $target;
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

/**
 * @Annotation
 * @Target("ALL")
 * @Attributes({
      @Attribute("mixed",                type = "mixed"),
      @Attribute("boolean",              type = "boolean"),
      @Attribute("bool",                 type = "bool"),
      @Attribute("float",                type = "float"),
      @Attribute("string",               type = "string"),
      @Attribute("integer",              type = "integer"),
      @Attribute("array",                type = "array"),
      @Attribute("arrayOfIntegers",      type = "array<integer>"),
      @Attribute("annotation",           type = "Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll"),
      @Attribute("arrayOfAnnotations",   type = "array<Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll>"),
  })
 */
final class AnnotationWithAttributes
{

    public final function __construct(array $data)
    {
        foreach ($data as $key => $value) {
            $this->$key = $value;
        }
    }

    private $mixed;
    private $boolean;
    private $bool;
    private $float;
    private $string;
    private $integer;
    private $array;
    private $annotation;
    private $arrayOfIntegers;
    private $arrayOfAnnotations;

    /**
     * @return mixed
     */
    public function getMixed()
    {
        return $this->mixed;
    }

    /**
     * @return boolean
     */
    public function getBoolean()
    {
        return $this->boolean;
    }

    /**
     * @return bool
     */
    public function getBool()
    {
        return $this->bool;
    }

    /**
     * @return float
     */
    public function getFloat()
    {
        return $this->float;
    }

    /**
     * @return string
     */
    public function getString()
    {
        return $this->string;
    }

    public function getInteger()
    {
        return $this->integer;
    }

    /**
     * @return array
     */
    public function getArray()
    {
        return $this->array;
    }

    /**
     * @return Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll
     */
    public function getAnnotation()
    {
        return $this->annotation;
    }

    /**
     * @return array<integer>
     */
    public function getArrayOfIntegers()
    {
        return $this->arrayOfIntegers;
    }

    /**
     * @return array<Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll>
     */
    public function getArrayOfAnnotations()
    {
        return $this->arrayOfAnnotations;
    }

}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

/**
 * @Annotation
 * @Target("ALL")
 */
final class AnnotationWithRequiredAttributesWithoutContructor
{

    /**
     * @Required
     * @var string
     */
    public $value;

    /**
     * @Required
     * @var Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAnnotation
     */
    public $annot;

}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

use Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetClass;

/**
 * @AnnotationTargetClass("Some data")
 */
class ClassWithInvalidAnnotationTargetAtMethod
{

    /**
     * @AnnotationTargetClass("functionName")
     */
    public function functionName($param)
    {

    }
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

/**
 * @Annotation
 * @Target("ALL")
 */
final class AnnotationWithConstants
{

    const INTEGER = 1;
    const FLOAT   = 1.2;
    const STRING  = '1.2.3';

    /**
     * @var mixed
     */
    public $value;
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

/**
 * @Annotation
 * @Target("ALL")
 */
final class AnnotationEnumLiteralInvalid
{
    const ONE   = 1;
    const TWO   = 2;
    const THREE = 3;

    /**
     * @var mixed
     *
     * @Enum(
     *      value = {
     *          1,
     *          2
     *      },
     *      literal = {
     *          1 : "AnnotationEnumLiteral::ONE",
     *          2 : "AnnotationEnumLiteral::TWO",
     *          3 : "AnnotationEnumLiteral::THREE"
     *      }
     * )
     */
    public $value;
}<?php

use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Template;
use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Route;

/**
 * @Route("foo")
 * @Template
 */
class AnnotationsTestsFixturesNonNamespacedClass { }<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

// Include a class named Api
require_once(__DIR__ . '/Api.php');

use Doctrine\Tests\Common\Annotations\DummyAnnotationWithIgnoredAnnotation;

/**
 * @DummyAnnotationWithIgnoredAnnotation(dummyValue="hello")
 */
class ClassWithRequire
{
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

use Doctrine\Tests\Common\Annotations\Fixtures\AnnotationEnum;

class ClassWithAnnotationEnum
{
    /**
     * @AnnotationEnum(AnnotationEnum::ONE)
     */
    public $foo;

    /**
     * @AnnotationEnum("TWO")
     */
    public function bar(){}


    /**
     * @AnnotationEnum("FOUR")
     */
    public $invalidProperty;

    /**
     * @AnnotationEnum(5)
     */
    public function invalidMethod(){}
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures\Annotation;

/** @Annotation */
class Secure
{
    private $roles;

    public function __construct(array $values)
    {
        if (is_string($values['value'])) {
            $values['value'] = array($values['value']);
        }

        $this->roles = $values['value'];
    }
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures\Annotation;

/** @Annotation */
class Route
{
    /** @var string @Required */
    public $pattern;
    public $name;
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures\Annotation;

/** @Annotation */
class AnnotWithDefaultValue
{
    /** @var string */
    public $foo = 'bar';
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures\Annotation;

/** @Annotation */
class Template
{
    private $name;

    public function __construct(array $values)
    {
        $this->name = isset($values['value']) ? $values['value'] : null;
    }
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures\Annotation;

/**
 * @Annotation
 * @Target("PROPERTY")
 */
final class Version
{
}
<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures\Annotation;

/**
 * @Annotation
 */
class Autoload
{
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

use Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetClass;
use Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll;
use Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetPropertyMethod;
use Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetNestedAnnotation;

/**
 * @AnnotationTargetClass("Some data")
 */
class ClassWithValidAnnotationTarget
{

    /**
     * @AnnotationTargetPropertyMethod("Some data")
     */
    public $foo;


    /**
     * @AnnotationTargetAll("Some data",name="Some name")
     */
    public $name;

    /**
     * @AnnotationTargetPropertyMethod("Some data",name="Some name")
     */
    public function someFunction()
    {

    }


    /**
     * @AnnotationTargetAll(@AnnotationTargetAnnotation)
     */
    public $nested;

}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

/**
 * @NoAnnotation
 */
class InvalidAnnotationUsageClass
{
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

use Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetPropertyMethod;

/**
 * @AnnotationTargetPropertyMethod("Some data")
 */
class ClassWithInvalidAnnotationTargetAtClass
{

    /**
     * @AnnotationTargetPropertyMethod("Bar")
     */
    public $foo;
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Secure;
use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Route;

class AnotherClass { }
class MultipleClassesInFile { }
<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures {
    use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Secure;

    class DifferentNamespacesPerFileWithClassAsFirst {}
}

namespace {
    use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Route;
}

namespace Doctrine\Tests\Common\Annotations\Fixtures\Foo {
    use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Template;
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

class NoAnnotation {}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Template;
use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Route;

/**
 * @Route("/someprefix")
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class Controller
{
    /**
     * @Route("/", name="_demo")
     * @Template()
     */
    public function indexAction()
    {
        return array();
    }

    /**
     * @Route("/hello/{name}", name="_demo_hello")
     * @Template()
     */
    public function helloAction($name)
    {
        return array('name' => $name);
    }

    /**
     * @Route("/contact", name="_demo_contact")
     * @Template()
     */
    public function contactAction()
    {
        $form = ContactForm::create($this->get('form.context'), 'contact');

        $form->bind($this->container->get('request'), $form);
        if ($form->isValid()) {
            $form->send($this->get('mailer'));

            $this->get('session')->setFlash('notice', 'Message sent!');

            return new RedirectResponse($this->generateUrl('_demo'));
        }

        return array('form' => $form);
    }

    /**
     * Creates the ACL for the passed object identity
     *
     * @param ObjectIdentityInterface $oid
     * @return void
     */
    private function createObjectIdentity(ObjectIdentityInterface $oid)
    {
        $classId = $this->createOrRetrieveClassId($oid->getType());

        $this->connection->executeQuery($this->getInsertObjectIdentitySql($oid->getIdentifier(), $classId, true));
    }

    /**
     * Returns the primary key for the passed class type.
     *
     * If the type does not yet exist in the database, it will be created.
     *
     * @param string $classType
     * @return integer
     */
    private function createOrRetrieveClassId($classType)
    {
        if (false !== $id = $this->connection->executeQuery($this->getSelectClassIdSql($classType))->fetchColumn()) {
            return $id;
        }

        $this->connection->executeQuery($this->getInsertClassSql($classType));

        return $this->connection->executeQuery($this->getSelectClassIdSql($classType))->fetchColumn();
    }

    /**
     * Returns the primary key for the passed security identity.
     *
     * If the security identity does not yet exist in the database, it will be
     * created.
     *
     * @param SecurityIdentityInterface $sid
     * @return integer
     */
    private function createOrRetrieveSecurityIdentityId(SecurityIdentityInterface $sid)
    {
        if (false !== $id = $this->connection->executeQuery($this->getSelectSecurityIdentityIdSql($sid))->fetchColumn()) {
            return $id;
        }

        $this->connection->executeQuery($this->getInsertSecurityIdentitySql($sid));

        return $this->connection->executeQuery($this->getSelectSecurityIdentityIdSql($sid))->fetchColumn();
    }

    /**
     * Deletes all ACEs for the given object identity primary key.
     *
     * @param integer $oidPK
     * @return void
     */
    private function deleteAccessControlEntries($oidPK)
    {
        $this->connection->executeQuery($this->getDeleteAccessControlEntriesSql($oidPK));
    }

    /**
     * Deletes the object identity from the database.
     *
     * @param integer $pk
     * @return void
     */
    private function deleteObjectIdentity($pk)
    {
        $this->connection->executeQuery($this->getDeleteObjectIdentitySql($pk));
    }

    /**
     * Deletes all entries from the relations table from the database.
     *
     * @param integer $pk
     * @return void
     */
    private function deleteObjectIdentityRelations($pk)
    {
        $this->connection->executeQuery($this->getDeleteObjectIdentityRelationsSql($pk));
    }

    /**
     * This regenerates the ancestor table which is used for fast read access.
     *
     * @param AclInterface $acl
     * @return void
     */
    private function regenerateAncestorRelations(AclInterface $acl)
    {
        $pk = $acl->getId();
        $this->connection->executeQuery($this->getDeleteObjectIdentityRelationsSql($pk));
        $this->connection->executeQuery($this->getInsertObjectIdentityRelationSql($pk, $pk));

        $parentAcl = $acl->getParentAcl();
        while (null !== $parentAcl) {
            $this->connection->executeQuery($this->getInsertObjectIdentityRelationSql($pk, $parentAcl->getId()));

            $parentAcl = $parentAcl->getParentAcl();
        }
    }

    /**
     * This processes changes on an ACE related property (classFieldAces, or objectFieldAces).
     *
     * @param string $name
     * @param array $changes
     * @return void
     */
    private function updateFieldAceProperty($name, array $changes)
    {
        $sids = new \SplObjectStorage();
        $classIds = new \SplObjectStorage();
        $currentIds = array();
        foreach ($changes[1] as $field => $new) {
            for ($i=0,$c=count($new); $i<$c; $i++) {
                $ace = $new[$i];

                if (null === $ace->getId()) {
                    if ($sids->contains($ace->getSecurityIdentity())) {
                        $sid = $sids->offsetGet($ace->getSecurityIdentity());
                    } else {
                        $sid = $this->createOrRetrieveSecurityIdentityId($ace->getSecurityIdentity());
                    }

                    $oid = $ace->getAcl()->getObjectIdentity();
                    if ($classIds->contains($oid)) {
                        $classId = $classIds->offsetGet($oid);
                    } else {
                        $classId = $this->createOrRetrieveClassId($oid->getType());
                    }

                    $objectIdentityId = $name === 'classFieldAces' ? null : $ace->getAcl()->getId();

                    $this->connection->executeQuery($this->getInsertAccessControlEntrySql($classId, $objectIdentityId, $field, $i, $sid, $ace->getStrategy(), $ace->getMask(), $ace->isGranting(), $ace->isAuditSuccess(), $ace->isAuditFailure()));
                    $aceId = $this->connection->executeQuery($this->getSelectAccessControlEntryIdSql($classId, $objectIdentityId, $field, $i))->fetchColumn();
                    $this->loadedAces[$aceId] = $ace;

                    $aceIdProperty = new \ReflectionProperty('Symfony\Component\Security\Acl\Domain\Entry', 'id');
                    $aceIdProperty->setAccessible(true);
                    $aceIdProperty->setValue($ace, intval($aceId));
                } else {
                    $currentIds[$ace->getId()] = true;
                }
            }
        }

        foreach ($changes[0] as $old) {
            for ($i=0,$c=count($old); $i<$c; $i++) {
                $ace = $old[$i];

                if (!isset($currentIds[$ace->getId()])) {
                    $this->connection->executeQuery($this->getDeleteAccessControlEntrySql($ace->getId()));
                    unset($this->loadedAces[$ace->getId()]);
                }
            }
        }
    }

    /**
     * This processes changes on an ACE related property (classAces, or objectAces).
     *
     * @param string $name
     * @param array $changes
     * @return void
     */
    private function updateAceProperty($name, array $changes)
    {
        list($old, $new) = $changes;

        $sids = new \SplObjectStorage();
        $classIds = new \SplObjectStorage();
        $currentIds = array();
        for ($i=0,$c=count($new); $i<$c; $i++) {
            $ace = $new[$i];

            if (null === $ace->getId()) {
                if ($sids->contains($ace->getSecurityIdentity())) {
                    $sid = $sids->offsetGet($ace->getSecurityIdentity());
                } else {
                    $sid = $this->createOrRetrieveSecurityIdentityId($ace->getSecurityIdentity());
                }

                $oid = $ace->getAcl()->getObjectIdentity();
                if ($classIds->contains($oid)) {
                    $classId = $classIds->offsetGet($oid);
                } else {
                    $classId = $this->createOrRetrieveClassId($oid->getType());
                }

                $objectIdentityId = $name === 'classAces' ? null : $ace->getAcl()->getId();

                $this->connection->executeQuery($this->getInsertAccessControlEntrySql($classId, $objectIdentityId, null, $i, $sid, $ace->getStrategy(), $ace->getMask(), $ace->isGranting(), $ace->isAuditSuccess(), $ace->isAuditFailure()));
                $aceId = $this->connection->executeQuery($this->getSelectAccessControlEntryIdSql($classId, $objectIdentityId, null, $i))->fetchColumn();
                $this->loadedAces[$aceId] = $ace;

                $aceIdProperty = new \ReflectionProperty($ace, 'id');
                $aceIdProperty->setAccessible(true);
                $aceIdProperty->setValue($ace, intval($aceId));
            } else {
                $currentIds[$ace->getId()] = true;
            }
        }

        for ($i=0,$c=count($old); $i<$c; $i++) {
            $ace = $old[$i];

            if (!isset($currentIds[$ace->getId()])) {
                $this->connection->executeQuery($this->getDeleteAccessControlEntrySql($ace->getId()));
                unset($this->loadedAces[$ace->getId()]);
            }
        }
    }

    /**
     * Persists the changes which were made to ACEs to the database.
     *
     * @param \SplObjectStorage $aces
     * @return void
     */
    private function updateAces(\SplObjectStorage $aces)
    {
        foreach ($aces as $ace) {
            $propertyChanges = $aces->offsetGet($ace);
            $sets = array();

            if (isset($propertyChanges['mask'])) {
                $sets[] = sprintf('mask = %d', $propertyChanges['mask'][1]);
            }
            if (isset($propertyChanges['strategy'])) {
                $sets[] = sprintf('granting_strategy = %s', $this->connection->quote($propertyChanges['strategy']));
            }
            if (isset($propertyChanges['aceOrder'])) {
                $sets[] = sprintf('ace_order = %d', $propertyChanges['aceOrder'][1]);
            }
            if (isset($propertyChanges['auditSuccess'])) {
                $sets[] = sprintf('audit_success = %s', $this->connection->getDatabasePlatform()->convertBooleans($propertyChanges['auditSuccess'][1]));
            }
            if (isset($propertyChanges['auditFailure'])) {
                $sets[] = sprintf('audit_failure = %s', $this->connection->getDatabasePlatform()->convertBooleans($propertyChanges['auditFailure'][1]));
            }

            $this->connection->executeQuery($this->getUpdateAccessControlEntrySql($ace->getId(), $sets));
        }
    }
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

/**
 * @Annotation
 * @Target("ALL")
 */
class AnnotationTargetAll
{
    public $data;
    public $name;
    public $target;
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

/**
 * @Annotation
 * @Target(@)
 */
final class AnnotationWithTargetSyntaxError
{
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Route;

/**
 * @NoAnnotation
 * @IgnoreAnnotation("NoAnnotation")
 * @Route("foo")
 */
class InvalidAnnotationUsageButIgnoredClass
{
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

use Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll;
use Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAnnotation;

/**
 * @AnnotationTargetAll("Foo")
 */
final class ClassWithClosure
{

    /**
     * @AnnotationTargetAll(@AnnotationTargetAnnotation)
     * @var string
     */
    public $value;

    /**
     * @AnnotationTargetAll(@AnnotationTargetAnnotation)
     *
     * @param   \Closure $callback
     * @return  \Closure
     */
    public function methodName(\Closure $callback)
    {
        $self = $this;
        return function() use ($self, $callback) {
            return $callback;
        };
    }

    /**
     * @param   integer $year
     * @param   integer $month
     * @param   integer $day
     * @return  \Doctrine\Common\Collections\ArrayCollection
     */
    public function getEventsForDate($year, $month, $day){
        $extractEvents  = null; // check if date of item is inside day given
        $extractEvents  = $this->events->filter(function ($item) use ($year, $month, $day) {
            $leftDate   = new \DateTime($year.'-'.$month.'-'.$day.' 00:00');
            $rigthDate  = new \DateTime($year.'-'.$month.'-'.$day.' +1 day 00:00');
            return ( ( $leftDate <= $item->getDateStart() ) && ( $item->getDateStart() < $rigthDate ) );

            }
        );
        return $extractEvents;
    }

}<?php

// namespace Doctrine\Tests\Common\Annotations\Fixtures;
namespace Doctrine\Tests\Common\Annotations\Fixtures\Foo {

    use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Secure;

    // class NamespaceAndClassCommentedOut {}
}

namespace Doctrine\Tests\Common\Annotations\Fixtures {

    // class NamespaceAndClassCommentedOut {}
    use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Route;

    // namespace Doctrine\Tests\Common\Annotations\Fixtures;
    use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Template;

    class NamespaceAndClassCommentedOut {}
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

use Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithTargetSyntaxError;

/**
 * @AnnotationWithTargetSyntaxError()
 */
class ClassWithAnnotationWithTargetSyntaxError
{
    /**
     * @AnnotationWithTargetSyntaxError()
     */
    public $foo;

    /**
     * @AnnotationWithTargetSyntaxError()
     */
    public function bar(){}
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Secure;
use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Route;
use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Template;

$var = 1;
function () use ($var) {};

class NamespaceWithClosureDeclaration {}
<?php

/**
 * This class is not an annotation
 * It's a class build to test ClassWithInclude
 */
class Api
{
	
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

interface IntefaceWithConstants
{

    const SOME_VALUE = 'IntefaceWithConstants.SOME_VALUE';
    const SOME_KEY   = 'IntefaceWithConstants.SOME_KEY';
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

use ReflectionClass, ReflectionProperty, ReflectionMethod;
use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Secure;
use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Route;

class NamespacedSingleClassLOC1000
{
    const TEST1 = 1234567890;
    const TEST2 = 1234567890;
    const TEST3 = 1234567890;
    const TEST4 = 1234567890;
    const TEST5 = 1234567890;
    const TEST6 = 1234567890;
    const TEST7 = 1234567890;
    const TEST8 = 1234567890;
    const TEST9 = 1234567890;

    private $test1 = null;
    private $test2 = null;
    private $test3 = null;
    private $test4 = null;
    private $test5 = null;
    private $test6 = null;
    private $test7 = null;
    private $test8 = null;
    private $test9 = null;

    public function test1()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test2()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test3()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test4()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test5()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test6()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test7()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test8()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;

    }

    public function test9()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test10()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test11()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test12()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test13()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test14()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test15()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test16()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test17()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;

    }

    public function test18()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test19()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test20()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test21()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test22()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test23()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test24()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test25()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test26()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test27()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;

    }

    public function test28()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test29()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test30()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test31()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test32()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test33()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test34()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test35()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test36()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test37()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;

    }

    public function test38()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test39()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;


/**
 * @Annotation
 * @Target("CLASS")
 */
final class AnnotationTargetClass
{
    public $data;
    public $name;
    public $target;
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

class ClassWithConstants
{

    const SOME_VALUE = 'ClassWithConstants.SOME_VALUE';
    const SOME_KEY   = 'ClassWithConstants.SOME_KEY';
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

/**
 * @since 2.0
 * @version $Id: SomeEntityClass.php 509 2012-02-03 09:38:48Z mf $
 */
class ClassDDC1660
{

    /**
     * @var     string
     * @since   2.0
     * @version 1
     */
    public $foo;

    /**
     * @param   string
     * @return  string
     * @since   2.0
     * @version 1
     */
    public function bar($param)
    {
        return null;
    }

}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Secure;
use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Route;

class EqualNamespacesPerFileWithClassAsFirst {}


namespace Doctrine\Tests\Common\Annotations\Fixtures;

use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Template;<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

/**
 * @Annotation
 * @Target("ALL")
 * @Attributes({
      @Attribute("value",   required = true ,   type = "string"),
      @Attribute("annot",   required = true ,   type = "Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAnnotation"),
   })
 */
final class AnnotationWithRequiredAttributes
{

    public final function __construct(array $data)
    {
        foreach ($data as $key => $value) {
            $this->$key = $value;
        }
    }

    /**
     * @var string
     */
    private $value;

    /**
     *
     * @var Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAnnotation
     */
    private $annot;

    /**
     * @return string
     */
    public function getValue()
    {
        return $this->value;
    }

    /**
     * @return Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAnnotation
     */
    public function getAnnot()
    {
        return $this->annot;
    }

}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

use Doctrine\Tests\Common\Annotations\Fixtures\AnnotationEnumLiteral as SelfEnum;

/**
 * @Annotation
 * @Target("ALL")
 */
final class AnnotationEnumLiteral
{
    const ONE   = 1;
    const TWO   = 2;
    const THREE = 3;

    /**
     * @var mixed
     *
     * @Enum(
     *      value = {
     *          1,
     *          2,
     *          3,
     *      },
     *      literal = {
     *          1 : "AnnotationEnumLiteral::ONE",
     *          2 : "AnnotationEnumLiteral::TWO",
     *          3 : "AnnotationEnumLiteral::THREE",
     *      }
     * )
     */
    public $value;
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Secure;

interface TestInterface
{
    /**
     * @Secure
     */
    function foo();
}<?php

use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Secure;
use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Route;

class SingleClassLOC1000
{
    const TEST1 = 1234567890;
    const TEST2 = 1234567890;
    const TEST3 = 1234567890;
    const TEST4 = 1234567890;
    const TEST5 = 1234567890;
    const TEST6 = 1234567890;
    const TEST7 = 1234567890;
    const TEST8 = 1234567890;
    const TEST9 = 1234567890;

    private $test1 = null;
    private $test2 = null;
    private $test3 = null;
    private $test4 = null;
    private $test5 = null;
    private $test6 = null;
    private $test7 = null;
    private $test8 = null;
    private $test9 = null;

    public function test1()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test2()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test3()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test4()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test5()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test6()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test7()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test8()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;

    }

    public function test9()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test10()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test11()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test12()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test13()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test14()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test15()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test16()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test17()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;

    }

    public function test18()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test19()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test20()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test21()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test22()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test23()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test24()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test25()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test26()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test27()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;

    }

    public function test28()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test29()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test30()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test31()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test32()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test33()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test34()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test35()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test36()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test37()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;

    }

    public function test38()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }

    public function test39()
    {
        echo $this->test1;
        echo $this->test2;
        echo $this->test3;
        $array = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        foreach ($array as $key => $value) {
            echo $key . ' => ' . $value;
        }

        $val = (string)self::TEST1;
        $val .= (string)self::TEST2;
        $val .= (string)self::TEST3;
        $val .= (string)self::TEST4;
        $val .= (string)self::TEST5;
        $val .= (string)self::TEST6;
        $val .= (string)self::TEST7;
        $val .= (string)self::TEST8;
        $val .= (string)self::TEST9;

        strtolower($val);

        return $val;
    }
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

use
    Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Route,
    Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Secure
;

class MultipleImportsInUseStatement {}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures\Foo {
    use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Secure;
}

namespace {
    use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Route;
}

namespace Doctrine\Tests\Common\Annotations\Fixtures {
    use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Template;

    class DifferentNamespacesPerFileWithClassAsLast {}
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

/**
 * @Annotation
 * @Target("ALL")
 */
final class AnnotationEnumInvalid
{
    /**
     * @var mixed
     *
     * @Enum({1, 2, "foo", "bar", {"foo":"bar"}})
     */
    public $value;
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

/**
 * @Annotation
 * @Target({ "METHOD", "PROPERTY" })
 */
final class AnnotationTargetPropertyMethod
{
    public $data;
    public $name;
    public $target;
}<?php

namespace {
	use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Secure;
}

namespace {
	use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Route;
	use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Template;

	class GlobalNamespacesPerFileWithClassAsLast {}
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

/**
 * @Annotation
 * @Target("ALL")
 */
final class AnnotationEnum
{
    const ONE   = 'ONE';
    const TWO   = 'TWO';
    const THREE = 'THREE';

    /**
     * @var mixed
     *
     * @Enum({"ONE","TWO","THREE"})
     */
    public $value;
}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

/**
 * @Annotation
 * @Target("ALL")
 */
final class AnnotationWithVarType
{

    /**
     * @var mixed
     */
    public $mixed;

    /**
     * @var boolean
     */
    public $boolean;

    /**
     * @var bool
     */
    public $bool;

    /**
     * @var float
     */
    public $float;

    /**
     * @var string
     */
    public $string;

    /**
     * @var integer
     */
    public $integer;

    /**
     * @var array
     */
    public $array;

    /**
     * @var Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll
     */
    public $annotation;

    /**
     * @var array<integer>
     */
    public $arrayOfIntegers;

    /**
     * @var array<Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll>
     */
    public $arrayOfAnnotations;

}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

use
    \Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Secure,
    \Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Route
;
use \Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Template;

class ClassWithFullyQualifiedUseStatements {}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Secure;

namespace Doctrine\Tests\Common\Annotations\Fixtures;

use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Route;
use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Template;

class EqualNamespacesPerFileWithClassAsLast {}<?php

namespace Doctrine\Tests\Common\Annotations\Fixtures;

use Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithVarType;
use Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll;
use Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAnnotation;

class ClassWithAnnotationWithVarType
{
    /**
     * @AnnotationWithVarType(string = "String Value")
     */
    public $foo;

    /**
     * @AnnotationWithVarType(annotation = @AnnotationTargetAll)
     */
    public function bar(){}


    /**
     * @AnnotationWithVarType(string = 123)
     */
    public $invalidProperty;

    /**
     * @AnnotationWithVarType(annotation = @AnnotationTargetAnnotation)
     */
    public function invalidMethod(){}
}<?php

namespace {
	use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Secure;
	use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Route;

	class GlobalNamespacesPerFileWithClassAsFirst {}
}

namespace {
	use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Template;
}<?php

namespace Doctrine\Tests\Common\Annotations;

use Doctrine\Common\Annotations\Annotation\IgnorePhpDoc;
use Doctrine\Common\Annotations\Annotation\IgnoreAnnotation;
use Doctrine\Common\Annotations\DocParser;
use Doctrine\Common\Annotations\AnnotationRegistry;
use Doctrine\Common\Annotations\Annotation\Target;
use Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithConstants;
use Doctrine\Tests\Common\Annotations\Fixtures\ClassWithConstants;
use Doctrine\Tests\Common\Annotations\Fixtures\IntefaceWithConstants;

class DocParserTest extends \PHPUnit_Framework_TestCase
{
    public function testNestedArraysWithNestedAnnotation()
    {
        $parser = $this->createTestParser();

        // Nested arrays with nested annotations
        $result = $parser->parse('@Name(foo={1,2, {"key"=@Name}})');
        $annot = $result[0];

        $this->assertTrue($annot instanceof Name);
        $this->assertNull($annot->value);
        $this->assertEquals(3, count($annot->foo));
        $this->assertEquals(1, $annot->foo[0]);
        $this->assertEquals(2, $annot->foo[1]);
        $this->assertTrue(is_array($annot->foo[2]));

        $nestedArray = $annot->foo[2];
        $this->assertTrue(isset($nestedArray['key']));
        $this->assertTrue($nestedArray['key'] instanceof Name);
    }

    public function testBasicAnnotations()
    {
        $parser = $this->createTestParser();

        // Marker annotation
        $result = $parser->parse("@Name");
        $annot = $result[0];
        $this->assertTrue($annot instanceof Name);
        $this->assertNull($annot->value);
        $this->assertNull($annot->foo);

        // Associative arrays
        $result = $parser->parse('@Name(foo={"key1" = "value1"})');
        $annot = $result[0];
        $this->assertNull($annot->value);
        $this->assertTrue(is_array($annot->foo));
        $this->assertTrue(isset($annot->foo['key1']));

        // Numerical arrays
        $result = $parser->parse('@Name({2="foo", 4="bar"})');
        $annot = $result[0];
        $this->assertTrue(is_array($annot->value));
        $this->assertEquals('foo', $annot->value[2]);
        $this->assertEquals('bar', $annot->value[4]);
        $this->assertFalse(isset($annot->value[0]));
        $this->assertFalse(isset($annot->value[1]));
        $this->assertFalse(isset($annot->value[3]));

        // Multiple values
        $result = $parser->parse('@Name(@Name, @Name)');
        $annot = $result[0];

        $this->assertTrue($annot instanceof Name);
        $this->assertTrue(is_array($annot->value));
        $this->assertTrue($annot->value[0] instanceof Name);
        $this->assertTrue($annot->value[1] instanceof Name);

        // Multiple types as values
        $result = $parser->parse('@Name(foo="Bar", @Name, {"key1"="value1", "key2"="value2"})');
        $annot = $result[0];

        $this->assertTrue($annot instanceof Name);
        $this->assertTrue(is_array($annot->value));
        $this->assertTrue($annot->value[0] instanceof Name);
        $this->assertTrue(is_array($annot->value[1]));
        $this->assertEquals('value1', $annot->value[1]['key1']);
        $this->assertEquals('value2', $annot->value[1]['key2']);

        // Complete docblock
        $docblock = <<<DOCBLOCK
/**
 * Some nifty class.
 *
 * @author Mr.X
 * @Name(foo="bar")
 */
DOCBLOCK;

        $result = $parser->parse($docblock);
        $this->assertEquals(1, count($result));
        $annot = $result[0];
        $this->assertTrue($annot instanceof Name);
        $this->assertEquals("bar", $annot->foo);
        $this->assertNull($annot->value);
   }

    public function testNamespacedAnnotations()
    {
        $parser = new DocParser;
        $parser->setIgnoreNotImportedAnnotations(true);

        $docblock = <<<DOCBLOCK
/**
 * Some nifty class.
 *
 * @package foo
 * @subpackage bar
 * @author Mr.X <mr@x.com>
 * @Doctrine\Tests\Common\Annotations\Name(foo="bar")
 * @ignore
 */
DOCBLOCK;

        $result = $parser->parse($docblock);
        $this->assertEquals(1, count($result));
        $annot = $result[0];
        $this->assertTrue($annot instanceof Name);
        $this->assertEquals("bar", $annot->foo);
    }

    /**
     * @group debug
     */
    public function testTypicalMethodDocBlock()
    {
        $parser = $this->createTestParser();

        $docblock = <<<DOCBLOCK
/**
 * Some nifty method.
 *
 * @since 2.0
 * @Doctrine\Tests\Common\Annotations\Name(foo="bar")
 * @param string \$foo This is foo.
 * @param mixed \$bar This is bar.
 * @return string Foo and bar.
 * @This is irrelevant
 * @Marker
 */
DOCBLOCK;

        $result = $parser->parse($docblock);
        $this->assertEquals(2, count($result));
        $this->assertTrue(isset($result[0]));
        $this->assertTrue(isset($result[1]));
        $annot = $result[0];
        $this->assertTrue($annot instanceof Name);
        $this->assertEquals("bar", $annot->foo);
        $marker = $result[1];
        $this->assertTrue($marker instanceof Marker);
    }


    public function testAnnotationWithoutConstructor()
    {
        $parser = $this->createTestParser();


        $docblock = <<<DOCBLOCK
/**
 * @SomeAnnotationClassNameWithoutConstructor("Some data")
 */
DOCBLOCK;

        $result     = $parser->parse($docblock);
        $this->assertEquals(count($result), 1);
        $annot      = $result[0];

        $this->assertNotNull($annot);
        $this->assertTrue($annot instanceof SomeAnnotationClassNameWithoutConstructor);

        $this->assertNull($annot->name);
        $this->assertNotNull($annot->data);
        $this->assertEquals($annot->data, "Some data");




$docblock = <<<DOCBLOCK
/**
 * @SomeAnnotationClassNameWithoutConstructor(name="Some Name", data = "Some data")
 */
DOCBLOCK;


        $result     = $parser->parse($docblock);
        $this->assertEquals(count($result), 1);
        $annot      = $result[0];

        $this->assertNotNull($annot);
        $this->assertTrue($annot instanceof SomeAnnotationClassNameWithoutConstructor);

        $this->assertEquals($annot->name, "Some Name");
        $this->assertEquals($annot->data, "Some data");




$docblock = <<<DOCBLOCK
/**
 * @SomeAnnotationClassNameWithoutConstructor(data = "Some data")
 */
DOCBLOCK;

        $result     = $parser->parse($docblock);
        $this->assertEquals(count($result), 1);
        $annot      = $result[0];

        $this->assertEquals($annot->data, "Some data");
        $this->assertNull($annot->name);


        $docblock = <<<DOCBLOCK
/**
 * @SomeAnnotationClassNameWithoutConstructor(name = "Some name")
 */
DOCBLOCK;

        $result     = $parser->parse($docblock);
        $this->assertEquals(count($result), 1);
        $annot      = $result[0];

        $this->assertEquals($annot->name, "Some name");
        $this->assertNull($annot->data);

        $docblock = <<<DOCBLOCK
/**
 * @SomeAnnotationClassNameWithoutConstructor("Some data")
 */
DOCBLOCK;

        $result     = $parser->parse($docblock);
        $this->assertEquals(count($result), 1);
        $annot      = $result[0];

        $this->assertEquals($annot->data, "Some data");
        $this->assertNull($annot->name);



        $docblock = <<<DOCBLOCK
/**
 * @SomeAnnotationClassNameWithoutConstructor("Some data",name = "Some name")
 */
DOCBLOCK;

        $result     = $parser->parse($docblock);
        $this->assertEquals(count($result), 1);
        $annot      = $result[0];

        $this->assertEquals($annot->name, "Some name");
        $this->assertEquals($annot->data, "Some data");


        $docblock = <<<DOCBLOCK
/**
 * @SomeAnnotationWithConstructorWithoutParams(name = "Some name")
 */
DOCBLOCK;

        $result     = $parser->parse($docblock);
        $this->assertEquals(count($result), 1);
        $annot      = $result[0];

        $this->assertEquals($annot->name, "Some name");
        $this->assertEquals($annot->data, "Some data");

        $docblock = <<<DOCBLOCK
/**
 * @SomeAnnotationClassNameWithoutConstructorAndProperties()
 */
DOCBLOCK;

        $result     = $parser->parse($docblock);
        $this->assertEquals(count($result), 1);
        $this->assertTrue($result[0] instanceof SomeAnnotationClassNameWithoutConstructorAndProperties);
    }

    public function testAnnotationTarget()
    {

        $parser = new DocParser;
        $parser->setImports(array(
            '__NAMESPACE__' => 'Doctrine\Tests\Common\Annotations\Fixtures',
        ));
        $class  = new \ReflectionClass('Doctrine\Tests\Common\Annotations\Fixtures\ClassWithValidAnnotationTarget');


        $context    = 'class ' . $class->getName();
        $docComment = $class->getDocComment();

        $parser->setTarget(Target::TARGET_CLASS);
        $this->assertNotNull($parser->parse($docComment,$context));


        $property   = $class->getProperty('foo');
        $docComment = $property->getDocComment();
        $context    = 'property ' . $class->getName() . "::\$" . $property->getName();

        $parser->setTarget(Target::TARGET_PROPERTY);
        $this->assertNotNull($parser->parse($docComment,$context));



        $method     = $class->getMethod('someFunction');
        $docComment = $property->getDocComment();
        $context    = 'method ' . $class->getName() . '::' . $method->getName() . '()';

        $parser->setTarget(Target::TARGET_METHOD);
        $this->assertNotNull($parser->parse($docComment,$context));


        try {
            $class      = new \ReflectionClass('Doctrine\Tests\Common\Annotations\Fixtures\ClassWithInvalidAnnotationTargetAtClass');
            $context    = 'class ' . $class->getName();
            $docComment = $class->getDocComment();

            $parser->setTarget(Target::TARGET_CLASS);
            $parser->parse($class->getDocComment(),$context);

            $this->fail();
        } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
            $this->assertNotNull($exc->getMessage());
        }


        try {

            $class      = new \ReflectionClass('Doctrine\Tests\Common\Annotations\Fixtures\ClassWithInvalidAnnotationTargetAtMethod');
            $method     = $class->getMethod('functionName');
            $docComment = $method->getDocComment();
            $context    = 'method ' . $class->getName() . '::' . $method->getName() . '()';

            $parser->setTarget(Target::TARGET_METHOD);
            $parser->parse($docComment,$context);

            $this->fail();
        } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
            $this->assertNotNull($exc->getMessage());
        }


        try {
            $class      = new \ReflectionClass('Doctrine\Tests\Common\Annotations\Fixtures\ClassWithInvalidAnnotationTargetAtProperty');
            $property   = $class->getProperty('foo');
            $docComment = $property->getDocComment();
            $context    = 'property ' . $class->getName() . "::\$" . $property->getName();

            $parser->setTarget(Target::TARGET_PROPERTY);
            $parser->parse($docComment,$context);

            $this->fail();
        } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
            $this->assertNotNull($exc->getMessage());
        }

    }

    public function getAnnotationVarTypeProviderValid()
    {
        //({attribute name}, {attribute value})
         return array(
            // mixed type
            array('mixed', '"String Value"'),
            array('mixed', 'true'),
            array('mixed', 'false'),
            array('mixed', '1'),
            array('mixed', '1.2'),
            array('mixed', '@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll'),

            // boolean type
            array('boolean', 'true'),
            array('boolean', 'false'),

            // alias for internal type boolean
            array('bool', 'true'),
            array('bool', 'false'),

            // integer type
            array('integer', '0'),
            array('integer', '1'),
            array('integer', '123456789'),
            array('integer', '9223372036854775807'),

            // alias for internal type double
            array('float', '0.1'),
            array('float', '1.2'),
            array('float', '123.456'),

            // string type
            array('string', '"String Value"'),
            array('string', '"true"'),
            array('string', '"123"'),

              // array type
            array('array', '{@AnnotationExtendsAnnotationTargetAll}'),
            array('array', '{@AnnotationExtendsAnnotationTargetAll,@AnnotationExtendsAnnotationTargetAll}'),

            array('arrayOfIntegers', '1'),
            array('arrayOfIntegers', '{1}'),
            array('arrayOfIntegers', '{1,2,3,4}'),
            array('arrayOfAnnotations', '@AnnotationExtendsAnnotationTargetAll'),
            array('arrayOfAnnotations', '{@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll}'),
            array('arrayOfAnnotations', '{@AnnotationExtendsAnnotationTargetAll, @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll}'),

            // annotation instance
            array('annotation', '@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll'),
            array('annotation', '@AnnotationExtendsAnnotationTargetAll'),
        );
    }

    public function getAnnotationVarTypeProviderInvalid()
    {
         //({attribute name}, {type declared type}, {attribute value} , {given type or class})
         return array(
            // boolean type
            array('boolean','boolean','1','integer'),
            array('boolean','boolean','1.2','double'),
            array('boolean','boolean','"str"','string'),
            array('boolean','boolean','{1,2,3}','array'),
            array('boolean','boolean','@Name', 'an instance of Doctrine\Tests\Common\Annotations\Name'),

            // alias for internal type boolean
            array('bool','bool', '1','integer'),
            array('bool','bool', '1.2','double'),
            array('bool','bool', '"str"','string'),
            array('bool','bool', '{"str"}','array'),

            // integer type
            array('integer','integer', 'true','boolean'),
            array('integer','integer', 'false','boolean'),
            array('integer','integer', '1.2','double'),
            array('integer','integer', '"str"','string'),
            array('integer','integer', '{"str"}','array'),
            array('integer','integer', '{1,2,3,4}','array'),

            // alias for internal type double
            array('float','float', 'true','boolean'),
            array('float','float', 'false','boolean'),
            array('float','float', '123','integer'),
            array('float','float', '"str"','string'),
            array('float','float', '{"str"}','array'),
            array('float','float', '{12.34}','array'),
            array('float','float', '{1,2,3}','array'),

            // string type
            array('string','string', 'true','boolean'),
            array('string','string', 'false','boolean'),
            array('string','string', '12','integer'),
            array('string','string', '1.2','double'),
            array('string','string', '{"str"}','array'),
            array('string','string', '{1,2,3,4}','array'),

             // annotation instance
            array('annotation','Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', 'true','boolean'),
            array('annotation','Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', 'false','boolean'),
            array('annotation','Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', '12','integer'),
            array('annotation','Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', '1.2','double'),
            array('annotation','Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', '{"str"}','array'),
            array('annotation','Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', '{1,2,3,4}','array'),
            array('annotation','Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', '@Name','an instance of Doctrine\Tests\Common\Annotations\Name'),
        );
    }

    public function getAnnotationVarTypeArrayProviderInvalid()
    {
         //({attribute name}, {type declared type}, {attribute value} , {given type or class})
         return array(
            array('arrayOfIntegers','integer', 'true','boolean'),
            array('arrayOfIntegers','integer', 'false','boolean'),
            array('arrayOfIntegers','integer', '{true,true}','boolean'),
            array('arrayOfIntegers','integer', '{1,true}','boolean'),
            array('arrayOfIntegers','integer', '{1,2,1.2}','double'),
            array('arrayOfIntegers','integer', '{1,2,"str"}','string'),


            array('arrayOfAnnotations','Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', 'true','boolean'),
            array('arrayOfAnnotations','Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', 'false','boolean'),
            array('arrayOfAnnotations','Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', '{@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll,true}','boolean'),
            array('arrayOfAnnotations','Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', '{@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll,true}','boolean'),
            array('arrayOfAnnotations','Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', '{@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll,1.2}','double'),
            array('arrayOfAnnotations','Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', '{@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll,@AnnotationExtendsAnnotationTargetAll,"str"}','string'),
        );
    }

    /**
     * @dataProvider getAnnotationVarTypeProviderValid
     */
    public function testAnnotationWithVarType($attribute, $value)
    {
        $parser     = $this->createTestParser();
        $context    = 'property SomeClassName::$invalidProperty.';
        $docblock   = sprintf('@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithVarType(%s = %s)',$attribute, $value);
        $parser->setTarget(Target::TARGET_PROPERTY);

        $result = $parser->parse($docblock, $context);

        $this->assertTrue(sizeof($result) === 1);
        $this->assertInstanceOf('Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithVarType', $result[0]);
        $this->assertNotNull($result[0]->$attribute);
    }

    /**
     * @dataProvider getAnnotationVarTypeProviderInvalid
     */
    public function testAnnotationWithVarTypeError($attribute,$type,$value,$given)
    {
        $parser     = $this->createTestParser();
        $context    = 'property SomeClassName::invalidProperty.';
        $docblock   = sprintf('@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithVarType(%s = %s)',$attribute, $value);
        $parser->setTarget(Target::TARGET_PROPERTY);

        try {
            $parser->parse($docblock, $context);
            $this->fail();
        } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
            $this->assertContains("[Type Error] Attribute \"$attribute\" of @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithVarType declared on property SomeClassName::invalidProperty. expects a(n) $type, but got $given.", $exc->getMessage());
        }
    }


    /**
     * @dataProvider getAnnotationVarTypeArrayProviderInvalid
     */
    public function testAnnotationWithVarTypeArrayError($attribute,$type,$value,$given)
    {
        $parser     = $this->createTestParser();
        $context    = 'property SomeClassName::invalidProperty.';
        $docblock   = sprintf('@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithVarType(%s = %s)',$attribute, $value);
        $parser->setTarget(Target::TARGET_PROPERTY);

        try {
            $parser->parse($docblock, $context);
            $this->fail();
        } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
            $this->assertContains("[Type Error] Attribute \"$attribute\" of @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithVarType declared on property SomeClassName::invalidProperty. expects either a(n) $type, or an array of {$type}s, but got $given.", $exc->getMessage());
        }
    }

    /**
     * @dataProvider getAnnotationVarTypeProviderValid
     */
    public function testAnnotationWithAttributes($attribute, $value)
    {
        $parser     = $this->createTestParser();
        $context    = 'property SomeClassName::$invalidProperty.';
        $docblock   = sprintf('@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithAttributes(%s = %s)',$attribute, $value);
        $parser->setTarget(Target::TARGET_PROPERTY);

        $result = $parser->parse($docblock, $context);

        $this->assertTrue(sizeof($result) === 1);
        $this->assertInstanceOf('Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithAttributes', $result[0]);
        $getter = "get".ucfirst($attribute);
        $this->assertNotNull($result[0]->$getter());
    }

   /**
     * @dataProvider getAnnotationVarTypeProviderInvalid
     */
    public function testAnnotationWithAttributesError($attribute,$type,$value,$given)
    {
        $parser     = $this->createTestParser();
        $context    = 'property SomeClassName::invalidProperty.';
        $docblock   = sprintf('@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithAttributes(%s = %s)',$attribute, $value);
        $parser->setTarget(Target::TARGET_PROPERTY);

        try {
            $parser->parse($docblock, $context);
            $this->fail();
        } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
            $this->assertContains("[Type Error] Attribute \"$attribute\" of @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithAttributes declared on property SomeClassName::invalidProperty. expects a(n) $type, but got $given.", $exc->getMessage());
        }
    }


   /**
     * @dataProvider getAnnotationVarTypeArrayProviderInvalid
     */
    public function testAnnotationWithAttributesWithVarTypeArrayError($attribute,$type,$value,$given)
    {
        $parser     = $this->createTestParser();
        $context    = 'property SomeClassName::invalidProperty.';
        $docblock   = sprintf('@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithAttributes(%s = %s)',$attribute, $value);
        $parser->setTarget(Target::TARGET_PROPERTY);

        try {
            $parser->parse($docblock, $context);
            $this->fail();
        } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
            $this->assertContains("[Type Error] Attribute \"$attribute\" of @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithAttributes declared on property SomeClassName::invalidProperty. expects either a(n) $type, or an array of {$type}s, but got $given.", $exc->getMessage());
        }
    }

    public function testAnnotationWithRequiredAttributes()
    {
        $parser     = $this->createTestParser();
        $context    = 'property SomeClassName::invalidProperty.';
        $parser->setTarget(Target::TARGET_PROPERTY);


        $docblock   = '@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithRequiredAttributes("Some Value", annot = @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAnnotation)';
        $result     = $parser->parse($docblock);

        $this->assertTrue(sizeof($result) === 1);
        $this->assertInstanceOf('Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithRequiredAttributes', $result[0]);
        $this->assertEquals("Some Value",$result[0]->getValue());
        $this->assertInstanceOf('Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAnnotation', $result[0]->getAnnot());


        $docblock   = '@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithRequiredAttributes("Some Value")';
        try {
            $result = $parser->parse($docblock,$context);
            $this->fail();
        } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
            $this->assertContains('Attribute "annot" of @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithRequiredAttributes declared on property SomeClassName::invalidProperty. expects a(n) Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAnnotation. This value should not be null.', $exc->getMessage());
        }

        $docblock   = '@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithRequiredAttributes(annot = @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAnnotation)';
        try {
            $result = $parser->parse($docblock,$context);
            $this->fail();
        } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
            $this->assertContains('Attribute "value" of @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithRequiredAttributes declared on property SomeClassName::invalidProperty. expects a(n) string. This value should not be null.', $exc->getMessage());
        }

    }

    public function testAnnotationWithRequiredAttributesWithoutContructor()
    {
        $parser     = $this->createTestParser();
        $context    = 'property SomeClassName::invalidProperty.';
        $parser->setTarget(Target::TARGET_PROPERTY);


        $docblock   = '@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithRequiredAttributesWithoutContructor("Some Value", annot = @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAnnotation)';
        $result     = $parser->parse($docblock);

        $this->assertTrue(sizeof($result) === 1);
        $this->assertInstanceOf('Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithRequiredAttributesWithoutContructor', $result[0]);
        $this->assertEquals("Some Value", $result[0]->value);
        $this->assertInstanceOf('Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAnnotation', $result[0]->annot);


        $docblock   = '@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithRequiredAttributesWithoutContructor("Some Value")';
        try {
            $result = $parser->parse($docblock,$context);
            $this->fail();
        } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
            $this->assertContains('Attribute "annot" of @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithRequiredAttributesWithoutContructor declared on property SomeClassName::invalidProperty. expects a(n) Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAnnotation. This value should not be null.', $exc->getMessage());
        }

        $docblock   = '@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithRequiredAttributesWithoutContructor(annot = @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAnnotation)';
        try {
            $result = $parser->parse($docblock,$context);
            $this->fail();
        } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
            $this->assertContains('Attribute "value" of @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithRequiredAttributesWithoutContructor declared on property SomeClassName::invalidProperty. expects a(n) string. This value should not be null.', $exc->getMessage());
        }

    }

    /**
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     * @expectedExceptionMessage Attribute "value" of @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationEnum declared on property SomeClassName::invalidProperty. accept only [ONE, TWO, THREE], but got FOUR.
     */
    public function testAnnotationEnumeratorException()
    {
        $parser     = $this->createTestParser();
        $context    = 'property SomeClassName::invalidProperty.';
        $docblock   = '@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationEnum("FOUR")';

        $parser->setIgnoreNotImportedAnnotations(false);
        $parser->setTarget(Target::TARGET_PROPERTY);
        $parser->parse($docblock, $context);
    }

    /**
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     * @expectedExceptionMessage Attribute "value" of @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationEnumLiteral declared on property SomeClassName::invalidProperty. accept only [AnnotationEnumLiteral::ONE, AnnotationEnumLiteral::TWO, AnnotationEnumLiteral::THREE], but got 4.
     */
    public function testAnnotationEnumeratorLiteralException()
    {
        $parser     = $this->createTestParser();
        $context    = 'property SomeClassName::invalidProperty.';
        $docblock   = '@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationEnumLiteral(4)';

        $parser->setIgnoreNotImportedAnnotations(false);
        $parser->setTarget(Target::TARGET_PROPERTY);
        $parser->parse($docblock, $context);
    }
   
    /**
     * @expectedException \InvalidArgumentException
     * @expectedExceptionMessage @Enum supports only scalar values "array" given.
     */
    public function testAnnotationEnumInvalidTypeDeclarationException()
    {
        $parser     = $this->createTestParser();
        $docblock   = '@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationEnumInvalid("foo")';

        $parser->setIgnoreNotImportedAnnotations(false);
        $parser->parse($docblock);
    }

    /**
     * @expectedException \InvalidArgumentException
     * @expectedExceptionMessage Undefined enumerator value "3" for literal "AnnotationEnumLiteral::THREE".
     */
    public function testAnnotationEnumInvalidLiteralDeclarationException()
    {
        $parser     = $this->createTestParser();
        $docblock   = '@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationEnumLiteralInvalid("foo")';

        $parser->setIgnoreNotImportedAnnotations(false);
        $parser->parse($docblock);
    }
    
    public function getConstantsProvider()
    {
        $provider[] = array(
            '@AnnotationWithConstants(PHP_EOL)',
            PHP_EOL
        );
        $provider[] = array(
            '@AnnotationWithConstants(AnnotationWithConstants::INTEGER)',
            AnnotationWithConstants::INTEGER
        );
        $provider[] = array(
            '@Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithConstants(AnnotationWithConstants::STRING)',
            AnnotationWithConstants::STRING
        );
        $provider[] = array(
            '@AnnotationWithConstants(Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithConstants::FLOAT)',
            AnnotationWithConstants::FLOAT
        );
        $provider[] = array(
            '@AnnotationWithConstants(ClassWithConstants::SOME_VALUE)',
            ClassWithConstants::SOME_VALUE
        );
        $provider[] = array(
            '@AnnotationWithConstants(Doctrine\Tests\Common\Annotations\Fixtures\ClassWithConstants::SOME_VALUE)',
            ClassWithConstants::SOME_VALUE
        );
        $provider[] = array(
            '@AnnotationWithConstants(IntefaceWithConstants::SOME_VALUE)',
            IntefaceWithConstants::SOME_VALUE
        );
        $provider[] = array(
            '@AnnotationWithConstants(\Doctrine\Tests\Common\Annotations\Fixtures\IntefaceWithConstants::SOME_VALUE)',
            IntefaceWithConstants::SOME_VALUE
        );
        $provider[] = array(
            '@AnnotationWithConstants({AnnotationWithConstants::STRING, AnnotationWithConstants::INTEGER, AnnotationWithConstants::FLOAT})',
            array(AnnotationWithConstants::STRING, AnnotationWithConstants::INTEGER, AnnotationWithConstants::FLOAT)
        );
        $provider[] = array(
            '@AnnotationWithConstants({
                AnnotationWithConstants::STRING = AnnotationWithConstants::INTEGER
             })',
            array(AnnotationWithConstants::STRING => AnnotationWithConstants::INTEGER)
        );
        $provider[] = array(
            '@AnnotationWithConstants({
                Doctrine\Tests\Common\Annotations\Fixtures\IntefaceWithConstants::SOME_KEY = AnnotationWithConstants::INTEGER
             })',
            array(IntefaceWithConstants::SOME_KEY => AnnotationWithConstants::INTEGER)
        );
        $provider[] = array(
            '@AnnotationWithConstants({
                \Doctrine\Tests\Common\Annotations\Fixtures\IntefaceWithConstants::SOME_KEY = AnnotationWithConstants::INTEGER
             })',
            array(IntefaceWithConstants::SOME_KEY => AnnotationWithConstants::INTEGER)
        );
        $provider[] = array(
            '@AnnotationWithConstants({
                AnnotationWithConstants::STRING = AnnotationWithConstants::INTEGER,
                ClassWithConstants::SOME_KEY = ClassWithConstants::SOME_VALUE,
                Doctrine\Tests\Common\Annotations\Fixtures\ClassWithConstants::SOME_KEY = IntefaceWithConstants::SOME_VALUE
             })',
            array(
                AnnotationWithConstants::STRING => AnnotationWithConstants::INTEGER,
                ClassWithConstants::SOME_KEY    => ClassWithConstants::SOME_VALUE,
                ClassWithConstants::SOME_KEY    => IntefaceWithConstants::SOME_VALUE
            )
        );
        return $provider;
    }

    /**
     * @dataProvider getConstantsProvider
     */
    public function testSupportClassConstants($docblock, $expected)
    {
        $parser = $this->createTestParser();
        $parser->setImports(array(
            'classwithconstants'        => 'Doctrine\Tests\Common\Annotations\Fixtures\ClassWithConstants',
            'intefacewithconstants'     => 'Doctrine\Tests\Common\Annotations\Fixtures\IntefaceWithConstants',
            'annotationwithconstants'   => 'Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithConstants'
        ));
        
        $result = $parser->parse($docblock);
        $this->assertInstanceOf('\Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithConstants', $annotation = $result[0]);
        $this->assertEquals($expected, $annotation->value);
    }

    /**
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     * @expectedExceptionMessage The annotation @SomeAnnotationClassNameWithoutConstructorAndProperties declared on  does not accept any values, but got {"value":"Foo"}.
     */
    public function testWithoutConstructorWhenIsNotDefaultValue()
    {
        $parser     = $this->createTestParser();
        $docblock   = <<<DOCBLOCK
/**
 * @SomeAnnotationClassNameWithoutConstructorAndProperties("Foo")
 */
DOCBLOCK;


        $parser->setTarget(Target::TARGET_CLASS);
        $parser->parse($docblock);
    }

    /**
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     * @expectedExceptionMessage The annotation @SomeAnnotationClassNameWithoutConstructorAndProperties declared on  does not accept any values, but got {"value":"Foo"}.
     */
    public function testWithoutConstructorWhenHasNoProperties()
    {
        $parser     = $this->createTestParser();
        $docblock   = <<<DOCBLOCK
/**
 * @SomeAnnotationClassNameWithoutConstructorAndProperties(value = "Foo")
 */
DOCBLOCK;

        $parser->setTarget(Target::TARGET_CLASS);
        $parser->parse($docblock);
    }

    /**
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     * @expectedExceptionMessage Expected namespace separator or identifier, got ')' at position 24 in class @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithTargetSyntaxError.
     */
    public function testAnnotationTargetSyntaxError()
    {
        $parser     = $this->createTestParser();
        $context    = 'class ' . 'SomeClassName';
        $docblock   = <<<DOCBLOCK
/**
 * @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithTargetSyntaxError()
 */
DOCBLOCK;

        $parser->setTarget(Target::TARGET_CLASS);
        $parser->parse($docblock,$context);
    }

    /**
     * @expectedException \InvalidArgumentException
     * @expectedExceptionMessage Invalid Target "Foo". Available targets: [ALL, CLASS, METHOD, PROPERTY, ANNOTATION]
     */
    public function testAnnotationWithInvalidTargetDeclarationError()
    {
        $parser     = $this->createTestParser();
        $context    = 'class ' . 'SomeClassName';
        $docblock   = <<<DOCBLOCK
/**
 * @AnnotationWithInvalidTargetDeclaration()
 */
DOCBLOCK;

        $parser->setTarget(Target::TARGET_CLASS);
        $parser->parse($docblock,$context);
    }

    /**
     * @expectedException \InvalidArgumentException
     * @expectedExceptionMessage @Target expects either a string value, or an array of strings, "NULL" given.
     */
    public function testAnnotationWithTargetEmptyError()
    {
        $parser     = $this->createTestParser();
        $context    = 'class ' . 'SomeClassName';
        $docblock   = <<<DOCBLOCK
/**
 * @AnnotationWithTargetEmpty()
 */
DOCBLOCK;

        $parser->setTarget(Target::TARGET_CLASS);
        $parser->parse($docblock,$context);
    }

    /**
     * @group DDC-575
     */
    public function testRegressionDDC575()
    {
        $parser = $this->createTestParser();

        $docblock = <<<DOCBLOCK
/**
 * @Name
 *
 * Will trigger error.
 */
DOCBLOCK;

        $result = $parser->parse($docblock);

        $this->assertInstanceOf("Doctrine\Tests\Common\Annotations\Name", $result[0]);

        $docblock = <<<DOCBLOCK
/**
 * @Name
 * @Marker
 *
 * Will trigger error.
 */
DOCBLOCK;

        $result = $parser->parse($docblock);

        $this->assertInstanceOf("Doctrine\Tests\Common\Annotations\Name", $result[0]);
    }

    /**
     * @group DDC-77
     */
    public function testAnnotationWithoutClassIsIgnoredWithoutWarning()
    {
        $parser = new DocParser();
        $parser->setIgnoreNotImportedAnnotations(true);
        $result = $parser->parse("@param");

        $this->assertEquals(0, count($result));
    }

    /**
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     * @expectedExceptionMessage Expected PlainValue, got ''' at position 10.
     */
    public function testAnnotationDontAcceptSingleQuotes()
    {
        $parser = $this->createTestParser();
        $parser->parse("@Name(foo='bar')");
    }

    /**
     * @group DCOM-41
     */
    public function testAnnotationDoesntThrowExceptionWhenAtSignIsNotFollowedByIdentifier()
    {
        $parser = new DocParser();
        $result = $parser->parse("'@'");

        $this->assertEquals(0, count($result));
    }

    /**
     * @group DCOM-41
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     */
    public function testAnnotationThrowsExceptionWhenAtSignIsNotFollowedByIdentifierInNestedAnnotation()
    {
        $parser = new DocParser();
        $result = $parser->parse("@Doctrine\Tests\Common\Annotations\Name(@')");
    }

    /**
     * @group DCOM-56
     */
    public function testAutoloadAnnotation()
    {
        $this->assertFalse(class_exists('Doctrine\Tests\Common\Annotations\Fixture\Annotation\Autoload', false), 'Pre-condition: Doctrine\Tests\Common\Annotations\Fixture\Annotation\Autoload not allowed to be loaded.');

        $parser = new DocParser();

        AnnotationRegistry::registerAutoloadNamespace('Doctrine\Tests\Common\Annotations\Fixtures\Annotation', __DIR__ . '/../../../../');

        $parser->setImports(array(
            'autoload' => 'Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Autoload',
        ));
        $annotations = $parser->parse('@Autoload');

        $this->assertEquals(1, count($annotations));
        $this->assertInstanceOf('Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Autoload', $annotations[0]);
    }

    public function createTestParser()
    {
        $parser = new DocParser();
        $parser->setIgnoreNotImportedAnnotations(true);
        $parser->setImports(array(
            'name' => 'Doctrine\Tests\Common\Annotations\Name',
            '__NAMESPACE__' => 'Doctrine\Tests\Common\Annotations',
        ));

        return $parser;
    }

    /**
     * @group DDC-78
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     * @expectedExceptionMessage Expected PlainValue, got ''' at position 10 in class \Doctrine\Tests\Common\Annotations\Name
     */
    public function testSyntaxErrorWithContextDescription()
    {
        $parser = $this->createTestParser();
        $parser->parse("@Name(foo='bar')", "class \Doctrine\Tests\Common\Annotations\Name");
    }

    /**
     * @group DDC-183
     */
    public function testSyntaxErrorWithUnknownCharacters()
    {
        $docblock = <<<DOCBLOCK
/**
 * @test at.
 */
class A {
}
DOCBLOCK;

        //$lexer = new \Doctrine\Common\Annotations\Lexer();
        //$lexer->setInput(trim($docblock, '/ *'));
        //var_dump($lexer);

        try {
            $parser = $this->createTestParser();
            $result = $parser->parse($docblock);
        } catch (Exception $e) {
            $this->fail($e->getMessage());
        }
    }

    /**
     * @group DCOM-14
     */
    public function testIgnorePHPDocThrowTag()
    {
        $docblock = <<<DOCBLOCK
/**
 * @throws \RuntimeException
 */
class A {
}
DOCBLOCK;

        try {
            $parser = $this->createTestParser();
            $result = $parser->parse($docblock);
        } catch (Exception $e) {
            $this->fail($e->getMessage());
        }
    }

    /**
     * @group DCOM-38
     */
    public function testCastInt()
    {
        $parser = $this->createTestParser();

        $result = $parser->parse("@Name(foo=1234)");
        $annot = $result[0];
        $this->assertInternalType('int', $annot->foo);
    }

    /**
     * @group DCOM-38
     */
    public function testCastNegativeInt()
    {
        $parser = $this->createTestParser();

        $result = $parser->parse("@Name(foo=-1234)");
        $annot = $result[0];
        $this->assertInternalType('int', $annot->foo);
    }

    /**
     * @group DCOM-38
     */
    public function testCastFloat()
    {
        $parser = $this->createTestParser();

        $result = $parser->parse("@Name(foo=1234.345)");
        $annot = $result[0];
        $this->assertInternalType('float', $annot->foo);
    }

    /**
     * @group DCOM-38
     */
    public function testCastNegativeFloat()
    {
        $parser = $this->createTestParser();

        $result = $parser->parse("@Name(foo=-1234.345)");
        $annot = $result[0];
        $this->assertInternalType('float', $annot->foo);

        $result = $parser->parse("@Marker(-1234.345)");
        $annot = $result[0];
        $this->assertInternalType('float', $annot->value);
    }

    public function testReservedKeywordsInAnnotations()
    {
        $parser = $this->createTestParser();

        $result = $parser->parse('@Doctrine\Tests\Common\Annotations\True');
        $this->assertTrue($result[0] instanceof True);
        $result = $parser->parse('@Doctrine\Tests\Common\Annotations\False');
        $this->assertTrue($result[0] instanceof False);
        $result = $parser->parse('@Doctrine\Tests\Common\Annotations\Null');
        $this->assertTrue($result[0] instanceof Null);

        $result = $parser->parse('@True');
        $this->assertTrue($result[0] instanceof True);
        $result = $parser->parse('@False');
        $this->assertTrue($result[0] instanceof False);
        $result = $parser->parse('@Null');
        $this->assertTrue($result[0] instanceof Null);
    }

     /**
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     * @expectedExceptionMessage [Creation Error] The annotation @SomeAnnotationClassNameWithoutConstructor declared on some class does not have a property named "invalidaProperty". Available properties: data, name
     */
    public function testSetValuesExeption()
    {
        $docblock = <<<DOCBLOCK
/**
 * @SomeAnnotationClassNameWithoutConstructor(invalidaProperty = "Some val")
 */
DOCBLOCK;

        $this->createTestParser()->parse($docblock, 'some class');
    }

    /**
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     * @expectedExceptionMessage [Syntax Error] Expected Doctrine\Common\Annotations\DocLexer::T_IDENTIFIER or Doctrine\Common\Annotations\DocLexer::T_TRUE or Doctrine\Common\Annotations\DocLexer::T_FALSE or Doctrine\Common\Annotations\DocLexer::T_NULL, got '3.42' at position 5.
     */
    public function testInvalidIdentifierInAnnotation()
    {
        $parser = $this->createTestParser();
        $parser->parse('@Foo\3.42');
    }

    public function testTrailingCommaIsAllowed()
    {
        $parser = $this->createTestParser();

        $annots = $parser->parse('@Name({
            "Foo",
            "Bar",
        })');
        $this->assertEquals(1, count($annots));
        $this->assertEquals(array('Foo', 'Bar'), $annots[0]->value);
    }

    public function testDefaultAnnotationValueIsNotOverwritten()
    {
        $parser = $this->createTestParser();

        $annots = $parser->parse('@Doctrine\Tests\Common\Annotations\Fixtures\Annotation\AnnotWithDefaultValue');
        $this->assertEquals(1, count($annots));
        $this->assertEquals('bar', $annots[0]->foo);
    }

    public function testArrayWithColon()
    {
        $parser = $this->createTestParser();

        $annots = $parser->parse('@Name({"foo": "bar"})');
        $this->assertEquals(1, count($annots));
        $this->assertEquals(array('foo' => 'bar'), $annots[0]->value);
    }

    /**
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     * @expectedExceptionMessage [Semantical Error] Couldn't find constant foo.
     */
    public function testInvalidContantName()
    {
        $parser = $this->createTestParser();
        $parser->parse('@Name(foo: "bar")');
    }

    /**
     * Tests parsing empty arrays.
     */
    public function testEmptyArray()
    {
        $parser = $this->createTestParser();

        $annots = $parser->parse('@Name({"foo": {}})');
        $this->assertEquals(1, count($annots));
        $this->assertEquals(array('foo' => array()), $annots[0]->value);
    }
}

/** @Annotation */
class SomeAnnotationClassNameWithoutConstructor
{
    public $data;
    public $name;
}

/** @Annotation */
class SomeAnnotationWithConstructorWithoutParams
{
    function __construct()
    {
        $this->data = "Some data";
    }
    public $data;
    public $name;
}

/** @Annotation */
class SomeAnnotationClassNameWithoutConstructorAndProperties{}

/**
 * @Annotation
 * @Target("Foo")
 */
class AnnotationWithInvalidTargetDeclaration{}

/**
 * @Annotation
 * @Target
 */
class AnnotationWithTargetEmpty{}

/** @Annotation */
class AnnotationExtendsAnnotationTargetAll extends \Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll
{
}

/** @Annotation */
class Name extends \Doctrine\Common\Annotations\Annotation {
    public $foo;
}

/** @Annotation */
class Marker {
    public $value;
}

/** @Annotation */
class True {}

/** @Annotation */
class False {}

/** @Annotation */
class Null {}

namespace Doctrine\Tests\Common\Annotations\FooBar;

/** @Annotation */
class Name extends \Doctrine\Common\Annotations\Annotation {
}
<?php

namespace Doctrine\Tests\Common\Annotations;

use Doctrine\Common\Annotations\AnnotationReader;

class AnnotationReaderTest extends AbstractReaderTest
{
    protected function getReader()
    {
        return new AnnotationReader();
    }
}<?php

namespace Doctrine\Tests\Common\Annotations;

use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\FileCacheReader;

class FileCacheReaderTest extends AbstractReaderTest
{
    private $cacheDir;

    protected function getReader()
    {
        $this->cacheDir = sys_get_temp_dir() . "/annotations_". uniqid();
        @mkdir($this->cacheDir);
        return new FileCacheReader(new AnnotationReader(), $this->cacheDir);
    }

    public function tearDown()
    {
        foreach (glob($this->cacheDir.'/*.php') AS $file) {
            unlink($file);
        }
        rmdir($this->cacheDir);
    }

    /**
     * @group DCOM-81
     */
    public function testAttemptToCreateAnnotationCacheDir()
    {
        $this->cacheDir = sys_get_temp_dir() . "/not_existed_dir_". uniqid();

        $this->assertFalse(is_dir($this->cacheDir));

        $cache = new FileCacheReader(new AnnotationReader(), $this->cacheDir);

        $this->assertTrue(is_dir($this->cacheDir));
    }
}<?php

namespace Doctrine\Tests\Common\Annotations;

use ReflectionClass;
use Doctrine\Common\Annotations\PhpParser;

require_once __DIR__.'/Fixtures/NonNamespacedClass.php';
require_once __DIR__.'/Fixtures/GlobalNamespacesPerFileWithClassAsFirst.php';
require_once __DIR__.'/Fixtures/GlobalNamespacesPerFileWithClassAsLast.php';

class PhpParserTest extends \PHPUnit_Framework_TestCase
{
    public function testParseClassWithMultipleClassesInFile()
    {
        $class = new ReflectionClass(__NAMESPACE__ . '\Fixtures\MultipleClassesInFile');
        $parser = new PhpParser();

        $this->assertEquals(array(
            'route'  => __NAMESPACE__ . '\Fixtures\Annotation\Route',
            'secure' => __NAMESPACE__ . '\Fixtures\Annotation\Secure',
        ), $parser->parseClass($class));
    }

    public function testParseClassWithMultipleImportsInUseStatement()
    {
        $class = new ReflectionClass(__NAMESPACE__ . '\Fixtures\MultipleImportsInUseStatement');
        $parser = new PhpParser();

        $this->assertEquals(array(
            'route'  => __NAMESPACE__ . '\Fixtures\Annotation\Route',
            'secure' => __NAMESPACE__ . '\Fixtures\Annotation\Secure',
        ), $parser->parseClass($class));
    }

    public function testParseClassWhenNotUserDefined()
    {
        $parser = new PhpParser();
        $this->assertEquals(array(), $parser->parseClass(new \ReflectionClass('\stdClass')));
    }

    public function testClassFileDoesNotExist()
    {
        $class = $this->getMockBuilder('\ReflectionClass')
                ->disableOriginalConstructor()
                          ->getMock();
        $class->expects($this->once())
             ->method('getFilename')
             ->will($this->returnValue('/valid/class/Fake.php(35) : eval()d code'));

        $parser = new PhpParser();
        $this->assertEquals(array(), $parser->parseClass($class));
    }

    public function testParseClassWhenClassIsNotNamespaced()
    {
        $parser = new PhpParser();
        $class = new ReflectionClass('\AnnotationsTestsFixturesNonNamespacedClass');

        $this->assertEquals(array(
            'route'    => __NAMESPACE__ . '\Fixtures\Annotation\Route',
            'template' => __NAMESPACE__ . '\Fixtures\Annotation\Template',
        ), $parser->parseClass($class));
    }

    public function testParseClassWhenClassIsInterface()
    {
        $parser = new PhpParser();
        $class = new ReflectionClass(__NAMESPACE__ . '\Fixtures\TestInterface');

        $this->assertEquals(array(
            'secure' => __NAMESPACE__ . '\Fixtures\Annotation\Secure',
        ), $parser->parseClass($class));
    }

    public function testClassWithFullyQualifiedUseStatements()
    {
        $parser = new PhpParser();
        $class = new ReflectionClass(__NAMESPACE__ . '\Fixtures\ClassWithFullyQualifiedUseStatements');

        $this->assertEquals(array(
            'secure'   => '\\' . __NAMESPACE__ . '\Fixtures\Annotation\Secure',
            'route'    => '\\' . __NAMESPACE__ . '\Fixtures\Annotation\Route',
            'template' => '\\' . __NAMESPACE__ . '\Fixtures\Annotation\Template',
        ), $parser->parseClass($class));
    }

    public function testNamespaceAndClassCommentedOut()
    {
        $parser = new PhpParser();
        $class = new ReflectionClass(__NAMESPACE__ . '\Fixtures\NamespaceAndClassCommentedOut');

        $this->assertEquals(array(
            'route'    => __NAMESPACE__ . '\Fixtures\Annotation\Route',
            'template' => __NAMESPACE__ . '\Fixtures\Annotation\Template',
        ), $parser->parseClass($class));
	}

    public function testEqualNamespacesPerFileWithClassAsFirst()
    {
        $parser = new PhpParser();
        $class = new ReflectionClass(__NAMESPACE__ . '\Fixtures\EqualNamespacesPerFileWithClassAsFirst');

        $this->assertEquals(array(
            'secure'   => __NAMESPACE__ . '\Fixtures\Annotation\Secure',
            'route'    => __NAMESPACE__ . '\Fixtures\Annotation\Route',
        ), $parser->parseClass($class));
    }

    public function testEqualNamespacesPerFileWithClassAsLast()
    {
        $parser = new PhpParser();
        $class = new ReflectionClass(__NAMESPACE__ . '\Fixtures\EqualNamespacesPerFileWithClassAsLast');

        $this->assertEquals(array(
            'route'    => __NAMESPACE__ . '\Fixtures\Annotation\Route',
            'template' => __NAMESPACE__ . '\Fixtures\Annotation\Template',
        ), $parser->parseClass($class));
    }

    public function testDifferentNamespacesPerFileWithClassAsFirst()
    {
        $parser = new PhpParser();
        $class = new ReflectionClass(__NAMESPACE__ . '\Fixtures\DifferentNamespacesPerFileWithClassAsFirst');

        $this->assertEquals(array(
            'secure'   => __NAMESPACE__ . '\Fixtures\Annotation\Secure',
        ), $parser->parseClass($class));
    }

    public function testDifferentNamespacesPerFileWithClassAsLast()
    {
        $parser = new PhpParser();
        $class = new ReflectionClass(__NAMESPACE__ . '\Fixtures\DifferentNamespacesPerFileWithClassAsLast');

        $this->assertEquals(array(
            'template' => __NAMESPACE__ . '\Fixtures\Annotation\Template',
        ), $parser->parseClass($class));
    }

    public function testGlobalNamespacesPerFileWithClassAsFirst()
    {
        $parser = new PhpParser();
        $class = new \ReflectionClass('\GlobalNamespacesPerFileWithClassAsFirst');

        $this->assertEquals(array(
            'secure'   => __NAMESPACE__ . '\Fixtures\Annotation\Secure',
            'route'    => __NAMESPACE__ . '\Fixtures\Annotation\Route',
        ), $parser->parseClass($class));
    }

    public function testGlobalNamespacesPerFileWithClassAsLast()
    {
        $parser = new PhpParser();
        $class = new ReflectionClass('\GlobalNamespacesPerFileWithClassAsLast');

        $this->assertEquals(array(
            'route'    => __NAMESPACE__ . '\Fixtures\Annotation\Route',
            'template' => __NAMESPACE__ . '\Fixtures\Annotation\Template',
        ), $parser->parseClass($class));
    }

    public function testNamespaceWithClosureDeclaration()
    {
        $parser = new PhpParser();
        $class = new ReflectionClass(__NAMESPACE__ . '\Fixtures\NamespaceWithClosureDeclaration');

        $this->assertEquals(array(
            'secure'   => __NAMESPACE__ . '\Fixtures\Annotation\Secure',
            'route'    => __NAMESPACE__ . '\Fixtures\Annotation\Route',
            'template' => __NAMESPACE__ . '\Fixtures\Annotation\Template',
        ), $parser->parseClass($class));
    }

    public function testIfPointerResetsOnMultipleParsingTries()
    {
        $parser = new PhpParser();
        $class = new ReflectionClass(__NAMESPACE__ . '\Fixtures\NamespaceWithClosureDeclaration');

        $this->assertEquals(array(
            'secure'   => __NAMESPACE__ . '\Fixtures\Annotation\Secure',
            'route'    => __NAMESPACE__ . '\Fixtures\Annotation\Route',
            'template' => __NAMESPACE__ . '\Fixtures\Annotation\Template',
        ), $parser->parseClass($class));

        $this->assertEquals(array(
            'secure'   => __NAMESPACE__ . '\Fixtures\Annotation\Secure',
            'route'    => __NAMESPACE__ . '\Fixtures\Annotation\Route',
            'template' => __NAMESPACE__ . '\Fixtures\Annotation\Template',
        ), $parser->parseClass($class));
    }

    /**
     * @group DCOM-97
     * @group regression
     */
    public function testClassWithClosure()
    {
        $parser = new PhpParser();
        $class  = new ReflectionClass(__NAMESPACE__ . '\Fixtures\ClassWithClosure');

        $this->assertEquals(array(
          'annotationtargetall'         => __NAMESPACE__ . '\Fixtures\AnnotationTargetAll',
          'annotationtargetannotation'  => __NAMESPACE__ . '\Fixtures\AnnotationTargetAnnotation',
        ), $parser->parseClass($class));
    }
}<?php

namespace Doctrine\Tests\Common\Annotations;

use Doctrine\Common\Annotations\DoctrineReader;
use Doctrine\Common\Annotations\Annotation\IgnoreAnnotation;
use Doctrine\Common\Annotations\Annotation\IgnorePhpDoc;
use ReflectionClass, Doctrine\Common\Annotations\AnnotationReader;

use Doctrine\Tests\Common\Annotations\DummyAnnotation;
use Doctrine\Tests\Common\Annotations\Name;
use Doctrine\Tests\Common\Annotations\DummyId;
use Doctrine\Tests\Common\Annotations\DummyJoinTable;
use Doctrine\Tests\Common\Annotations\DummyJoinColumn;
use Doctrine\Tests\Common\Annotations\DummyColumn;
use Doctrine\Tests\Common\Annotations\DummyGeneratedValue;

require_once __DIR__ . '/TopLevelAnnotation.php';

abstract class AbstractReaderTest extends \PHPUnit_Framework_TestCase
{
    public function getReflectionClass()
    {
        $className = 'Doctrine\Tests\Common\Annotations\DummyClass';
        return new ReflectionClass($className);
    }

    public function testAnnotations()
    {
        $class = $this->getReflectionClass();
        $reader = $this->getReader();

        $this->assertEquals(1, count($reader->getClassAnnotations($class)));
        $this->assertInstanceOf($annotName = 'Doctrine\Tests\Common\Annotations\DummyAnnotation', $annot = $reader->getClassAnnotation($class, $annotName));
        $this->assertEquals("hello", $annot->dummyValue);

        $field1Prop = $class->getProperty('field1');
        $propAnnots = $reader->getPropertyAnnotations($field1Prop);
        $this->assertEquals(1, count($propAnnots));
        $this->assertInstanceOf($annotName, $annot = $reader->getPropertyAnnotation($field1Prop, $annotName));
        $this->assertEquals("fieldHello", $annot->dummyValue);

        $getField1Method = $class->getMethod('getField1');
        $methodAnnots = $reader->getMethodAnnotations($getField1Method);
        $this->assertEquals(1, count($methodAnnots));
        $this->assertInstanceOf($annotName, $annot = $reader->getMethodAnnotation($getField1Method, $annotName));
        $this->assertEquals(array(1, 2, "three"), $annot->value);

        $field2Prop = $class->getProperty('field2');
        $propAnnots = $reader->getPropertyAnnotations($field2Prop);
        $this->assertEquals(1, count($propAnnots));
        $this->assertInstanceOf($annotName = 'Doctrine\Tests\Common\Annotations\DummyJoinTable', $joinTableAnnot = $reader->getPropertyAnnotation($field2Prop, $annotName));
        $this->assertEquals(1, count($joinTableAnnot->joinColumns));
        $this->assertEquals(1, count($joinTableAnnot->inverseJoinColumns));
        $this->assertTrue($joinTableAnnot->joinColumns[0] instanceof DummyJoinColumn);
        $this->assertTrue($joinTableAnnot->inverseJoinColumns[0] instanceof DummyJoinColumn);
        $this->assertEquals('col1', $joinTableAnnot->joinColumns[0]->name);
        $this->assertEquals('col2', $joinTableAnnot->joinColumns[0]->referencedColumnName);
        $this->assertEquals('col3', $joinTableAnnot->inverseJoinColumns[0]->name);
        $this->assertEquals('col4', $joinTableAnnot->inverseJoinColumns[0]->referencedColumnName);

        $dummyAnnot = $reader->getMethodAnnotation($class->getMethod('getField1'), 'Doctrine\Tests\Common\Annotations\DummyAnnotation');
        $this->assertEquals('', $dummyAnnot->dummyValue);
        $this->assertEquals(array(1, 2, 'three'), $dummyAnnot->value);

        $dummyAnnot = $reader->getPropertyAnnotation($class->getProperty('field1'), 'Doctrine\Tests\Common\Annotations\DummyAnnotation');
        $this->assertEquals('fieldHello', $dummyAnnot->dummyValue);

        $classAnnot = $reader->getClassAnnotation($class, 'Doctrine\Tests\Common\Annotations\DummyAnnotation');
        $this->assertEquals('hello', $classAnnot->dummyValue);
    }

    public function testAnnotationsWithValidTargets()
    {
        $reader = $this->getReader();
        $class  = new ReflectionClass('Doctrine\Tests\Common\Annotations\Fixtures\ClassWithValidAnnotationTarget');

        $this->assertEquals(1,count($reader->getClassAnnotations($class)));
        $this->assertEquals(1,count($reader->getPropertyAnnotations($class->getProperty('foo'))));
        $this->assertEquals(1,count($reader->getMethodAnnotations($class->getMethod('someFunction'))));
        $this->assertEquals(1,count($reader->getPropertyAnnotations($class->getProperty('nested'))));
    }

    public function testAnnotationsWithVarType()
    {
        $reader = $this->getReader();
        $class  = new ReflectionClass('Doctrine\Tests\Common\Annotations\Fixtures\ClassWithAnnotationWithVarType');

        $this->assertEquals(1,count($fooAnnot = $reader->getPropertyAnnotations($class->getProperty('foo'))));
        $this->assertEquals(1,count($barAnnot = $reader->getMethodAnnotations($class->getMethod('bar'))));

        $this->assertInternalType('string',  $fooAnnot[0]->string);
        $this->assertInstanceOf('Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll', $barAnnot[0]->annotation);
    }

     /**
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     * @expectedExceptionMessage [Semantical Error] Annotation @AnnotationTargetPropertyMethod is not allowed to be declared on class Doctrine\Tests\Common\Annotations\Fixtures\ClassWithInvalidAnnotationTargetAtClass. You may only use this annotation on these code elements: METHOD, PROPERTY
     */
    public function testClassWithInvalidAnnotationTargetAtClassDocBlock()
    {
        $reader  = $this->getReader();
        $reader->getClassAnnotations(new \ReflectionClass('Doctrine\Tests\Common\Annotations\Fixtures\ClassWithInvalidAnnotationTargetAtClass'));
    }

    public function testClassWithWithInclude()
    {
        $reader = $this->getReader();
        $annots = $reader->getClassAnnotations(new \ReflectionClass('Doctrine\Tests\Common\Annotations\Fixtures\ClassWithRequire'));
        $this->assertCount(1, $annots);
    }

     /**
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     * @expectedExceptionMessage [Semantical Error] Annotation @AnnotationTargetClass is not allowed to be declared on property Doctrine\Tests\Common\Annotations\Fixtures\ClassWithInvalidAnnotationTargetAtProperty::$foo. You may only use this annotation on these code elements: CLASS
     */
    public function testClassWithInvalidAnnotationTargetAtPropertyDocBlock()
    {
        $reader  = $this->getReader();
        $reader->getPropertyAnnotations(new \ReflectionProperty('Doctrine\Tests\Common\Annotations\Fixtures\ClassWithInvalidAnnotationTargetAtProperty', 'foo'));
    }

     /**
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     * @expectedExceptionMessage [Semantical Error] Annotation @AnnotationTargetAnnotation is not allowed to be declared on property Doctrine\Tests\Common\Annotations\Fixtures\ClassWithInvalidAnnotationTargetAtProperty::$bar. You may only use this annotation on these code elements: ANNOTATION
     */
    public function testClassWithInvalidNestedAnnotationTargetAtPropertyDocBlock()
    {
        $reader  = $this->getReader();
        $reader->getPropertyAnnotations(new \ReflectionProperty('Doctrine\Tests\Common\Annotations\Fixtures\ClassWithInvalidAnnotationTargetAtProperty', 'bar'));
    }

     /**
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     * @expectedExceptionMessage [Semantical Error] Annotation @AnnotationTargetClass is not allowed to be declared on method Doctrine\Tests\Common\Annotations\Fixtures\ClassWithInvalidAnnotationTargetAtMethod::functionName(). You may only use this annotation on these code elements: CLASS
     */
    public function testClassWithInvalidAnnotationTargetAtMethodDocBlock()
    {
        $reader  = $this->getReader();
        $reader->getMethodAnnotations(new \ReflectionMethod('Doctrine\Tests\Common\Annotations\Fixtures\ClassWithInvalidAnnotationTargetAtMethod', 'functionName'));
    }

    /**
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     * @expectedExceptionMessage Expected namespace separator or identifier, got ')' at position 24 in class @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithTargetSyntaxError.
     */
    public function testClassWithAnnotationWithTargetSyntaxErrorAtClassDocBlock()
    {
        $reader  = $this->getReader();
        $reader->getClassAnnotations(new \ReflectionClass('Doctrine\Tests\Common\Annotations\Fixtures\ClassWithAnnotationWithTargetSyntaxError'));
    }

    /**
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     * @expectedExceptionMessage Expected namespace separator or identifier, got ')' at position 24 in class @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithTargetSyntaxError.
     */
    public function testClassWithAnnotationWithTargetSyntaxErrorAtPropertyDocBlock()
    {
        $reader  = $this->getReader();
        $reader->getPropertyAnnotations(new \ReflectionProperty('Doctrine\Tests\Common\Annotations\Fixtures\ClassWithAnnotationWithTargetSyntaxError','foo'));
    }

    /**
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     * @expectedExceptionMessage Expected namespace separator or identifier, got ')' at position 24 in class @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationWithTargetSyntaxError.
     */
    public function testClassWithAnnotationWithTargetSyntaxErrorAtMethodDocBlock()
    {
        $reader  = $this->getReader();
        $reader->getMethodAnnotations(new \ReflectionMethod('Doctrine\Tests\Common\Annotations\Fixtures\ClassWithAnnotationWithTargetSyntaxError','bar'));
    }

    /**
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     * @expectedExceptionMessage [Type Error] Attribute "string" of @AnnotationWithVarType declared on property Doctrine\Tests\Common\Annotations\Fixtures\ClassWithAnnotationWithVarType::$invalidProperty expects a(n) string, but got integer.
     */
    public function testClassWithPropertyInvalidVarTypeError()
    {
        $reader = $this->getReader();
        $class  = new ReflectionClass('Doctrine\Tests\Common\Annotations\Fixtures\ClassWithAnnotationWithVarType');

        $reader->getPropertyAnnotations($class->getProperty('invalidProperty'));
    }

    /**
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     * @expectedExceptionMessage [Type Error] Attribute "annotation" of @AnnotationWithVarType declared on method Doctrine\Tests\Common\Annotations\Fixtures\ClassWithAnnotationWithVarType::invalidMethod() expects a(n) Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAll, but got an instance of Doctrine\Tests\Common\Annotations\Fixtures\AnnotationTargetAnnotation.
     */
    public function testClassWithMethodInvalidVarTypeError()
    {
        $reader = $this->getReader();
        $class  = new ReflectionClass('Doctrine\Tests\Common\Annotations\Fixtures\ClassWithAnnotationWithVarType');

        $reader->getMethodAnnotations($class->getMethod('invalidMethod'));
    }

    /**
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     * @expectedExceptionMessage Expected namespace separator or identifier, got ')' at position 18 in class Doctrine\Tests\Common\Annotations\DummyClassSyntaxError.
     */
    public function testClassSyntaxErrorContext()
    {
        $reader = $this->getReader();
        $reader->getClassAnnotations(new \ReflectionClass('Doctrine\Tests\Common\Annotations\DummyClassSyntaxError'));
    }

    /**
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     * @expectedExceptionMessage Expected namespace separator or identifier, got ')' at position 18 in method Doctrine\Tests\Common\Annotations\DummyClassMethodSyntaxError::foo().
     */
    public function testMethodSyntaxErrorContext()
    {
        $reader = $this->getReader();
        $reader->getMethodAnnotations(new \ReflectionMethod('Doctrine\Tests\Common\Annotations\DummyClassMethodSyntaxError', 'foo'));
    }

    /**
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     * @expectedExceptionMessage Expected namespace separator or identifier, got ')' at position 18 in property Doctrine\Tests\Common\Annotations\DummyClassPropertySyntaxError::$foo.
     */
    public function testPropertySyntaxErrorContext()
    {
        $reader = $this->getReader();
        $reader->getPropertyAnnotations(new \ReflectionProperty('Doctrine\Tests\Common\Annotations\DummyClassPropertySyntaxError', 'foo'));
    }

    /**
     * @group regression
     */
    public function testMultipleAnnotationsOnSameLine()
    {
        $reader = $this->getReader();
        $annots = $reader->getPropertyAnnotations(new \ReflectionProperty('Doctrine\Tests\Common\Annotations\DummyClass2', 'id'));
        $this->assertEquals(3, count($annots));
    }

    public function testNonAnnotationProblem()
    {
        $reader = $this->getReader();

        $this->assertNotNull($annot = $reader->getPropertyAnnotation(new \ReflectionProperty('Doctrine\Tests\Common\Annotations\DummyClassNonAnnotationProblem', 'foo'), $name = 'Doctrine\Tests\Common\Annotations\DummyAnnotation'));
        $this->assertInstanceOf($name, $annot);
    }

    public function testImportWithConcreteAnnotation()
    {
        $reader = $this->getReader();
        $property = new \ReflectionProperty('Doctrine\Tests\Common\Annotations\TestImportWithConcreteAnnotation', 'field');
        $annotations = $reader->getPropertyAnnotations($property);
        $this->assertEquals(1, count($annotations));
        $this->assertNotNull($reader->getPropertyAnnotation($property, 'Doctrine\Tests\Common\Annotations\DummyAnnotation'));
    }

    public function testImportWithInheritance()
    {
        $reader = $this->getReader();

        $class = new TestParentClass();
        $ref = new \ReflectionClass($class);

        $childAnnotations = $reader->getPropertyAnnotations($ref->getProperty('child'));
        $this->assertEquals(1, count($childAnnotations));
        $this->assertInstanceOf('Doctrine\Tests\Common\Annotations\Foo\Name', reset($childAnnotations));

        $parentAnnotations = $reader->getPropertyAnnotations($ref->getProperty('parent'));
        $this->assertEquals(1, count($parentAnnotations));
        $this->assertInstanceOf('Doctrine\Tests\Common\Annotations\Bar\Name', reset($parentAnnotations));
    }

    /**
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     * @expectedExceptionMessage The annotation "@NameFoo" in property Doctrine\Tests\Common\Annotations\TestAnnotationNotImportedClass::$field was never imported.
     */
    public function testImportDetectsNotImportedAnnotation()
    {
        $reader = $this->getReader();
        $reader->getPropertyAnnotations(new \ReflectionProperty('Doctrine\Tests\Common\Annotations\TestAnnotationNotImportedClass', 'field'));
    }

    /**
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     * @expectedExceptionMessage The annotation "@Foo\Bar\Name" in property Doctrine\Tests\Common\Annotations\TestNonExistentAnnotationClass::$field was never imported.
     */
    public function testImportDetectsNonExistentAnnotation()
    {
        $reader = $this->getReader();
        $reader->getPropertyAnnotations(new \ReflectionProperty('Doctrine\Tests\Common\Annotations\TestNonExistentAnnotationClass', 'field'));
    }

    public function testTopLevelAnnotation()
    {
        $reader = $this->getReader();
        $annotations = $reader->getPropertyAnnotations(new \ReflectionProperty('Doctrine\Tests\Common\Annotations\TestTopLevelAnnotationClass', 'field'));

        $this->assertEquals(1, count($annotations));
        $this->assertInstanceOf('\TopLevelAnnotation', reset($annotations));
    }

    public function testIgnoresAnnotationsNotPrefixedWithWhitespace()
    {
        $reader = $this->getReader();

        $annotation = $reader->getClassAnnotation(new \ReflectionClass(new TestIgnoresNonAnnotationsClass()), 'Doctrine\Tests\Common\Annotations\Name');
        $this->assertInstanceOf('Doctrine\Tests\Common\Annotations\Name', $annotation);
    }

    /**
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     * @expectedExceptionMessage The class "Doctrine\Tests\Common\Annotations\Fixtures\NoAnnotation" is not annotated with @Annotation. Are you sure this class can be used as annotation? If so, then you need to add @Annotation to the _class_ doc comment of "Doctrine\Tests\Common\Annotations\Fixtures\NoAnnotation". If it is indeed no annotation, then you need to add @IgnoreAnnotation("NoAnnotation") to the _class_ doc comment of class Doctrine\Tests\Common\Annotations\Fixtures\InvalidAnnotationUsageClass.
     */
    public function testErrorWhenInvalidAnnotationIsUsed()
    {
        $reader = $this->getReader();
        $ref = new \ReflectionClass('Doctrine\Tests\Common\Annotations\Fixtures\InvalidAnnotationUsageClass');
        $reader->getClassAnnotations($ref);
    }

    public function testInvalidAnnotationUsageButIgnoredClass()
    {
        $reader = $this->getReader();
        $ref = new \ReflectionClass('Doctrine\Tests\Common\Annotations\Fixtures\InvalidAnnotationUsageButIgnoredClass');
        $annots = $reader->getClassAnnotations($ref);

        $this->assertEquals(2, count($annots));
    }

    /**
     * @group DDC-1660
     * @group regression
     */
    public function testInvalidAnnotationButIgnored()
    {
        $reader = $this->getReader();
        $class  = new \ReflectionClass('Doctrine\Tests\Common\Annotations\Fixtures\ClassDDC1660');

        $this->assertTrue(class_exists('Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Version'));
        $this->assertCount(0, $reader->getClassAnnotations($class));
        $this->assertCount(0, $reader->getMethodAnnotations($class->getMethod('bar')));
        $this->assertCount(0, $reader->getPropertyAnnotations($class->getProperty('foo')));
    }

    public function testAnnotationEnumeratorException()
    {
        $reader     = $this->getReader();
        $class      = new \ReflectionClass('Doctrine\Tests\Common\Annotations\Fixtures\ClassWithAnnotationEnum');

        $this->assertCount(1, $bar = $reader->getMethodAnnotations($class->getMethod('bar')));
        $this->assertCount(1, $foo = $reader->getPropertyAnnotations($class->getProperty('foo')));

        $this->assertInstanceOf('Doctrine\Tests\Common\Annotations\Fixtures\AnnotationEnum', $bar[0]);
        $this->assertInstanceOf('Doctrine\Tests\Common\Annotations\Fixtures\AnnotationEnum', $foo[0]);

        try {
            $reader->getPropertyAnnotations($class->getProperty('invalidProperty'));
            $this->fail();
        } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
            $this->assertEquals('[Enum Error] Attribute "value" of @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationEnum declared on property Doctrine\Tests\Common\Annotations\Fixtures\ClassWithAnnotationEnum::$invalidProperty accept only [ONE, TWO, THREE], but got FOUR.', $exc->getMessage());
        }

        try {
            $reader->getMethodAnnotations($class->getMethod('invalidMethod'));
            $this->fail();
        } catch (\Doctrine\Common\Annotations\AnnotationException $exc) {
            $this->assertEquals('[Enum Error] Attribute "value" of @Doctrine\Tests\Common\Annotations\Fixtures\AnnotationEnum declared on method Doctrine\Tests\Common\Annotations\Fixtures\ClassWithAnnotationEnum::invalidMethod() accept only [ONE, TWO, THREE], but got 5.', $exc->getMessage());
        }
    }

    /**
     * @group DCOM-106
     */
    public function testIgnoreFixMeAndUpperCaseToDo()
    {
        $reader = $this->getReader();
        $ref = new \ReflectionClass('Doctrine\Tests\Common\Annotations\DCOM106');
        $reader->getClassAnnotations($ref);
    }
    
    /**
     * @return AnnotationReader
     */
    abstract protected function getReader();
}

/**
 * @parseAnnotation("var")
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 */
class TestParseAnnotationClass
{
    /**
     * @var
     */
    private $field;
}

/**
 * @Name
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class TestIgnoresNonAnnotationsClass
{
}

class TestTopLevelAnnotationClass
{
    /**
     * @\TopLevelAnnotation
     */
    private $field;
}

class TestNonExistentAnnotationClass
{
    /**
     * @Foo\Bar\Name
     */
    private $field;
}

class TestAnnotationNotImportedClass
{
    /**
     * @NameFoo
     */
    private $field;
}

class TestChildClass
{
    /**
     * @\Doctrine\Tests\Common\Annotations\Foo\Name(name = "foo")
     */
    protected $child;
}

class TestParentClass extends TestChildClass
{
    /**
     * @\Doctrine\Tests\Common\Annotations\Bar\Name(name = "bar")
     */
    private $parent;
}

class TestImportWithConcreteAnnotation
{
    /**
     * @DummyAnnotation(dummyValue = "bar")
     */
    private $field;
}

/**
 * @ignoreAnnotation("var")
 */
class DummyClass2 {
    /**
     * @DummyId @DummyColumn(type="integer") @DummyGeneratedValue
     * @var integer
     */
    private $id;
}

/** @Annotation */
class DummyId extends \Doctrine\Common\Annotations\Annotation {}
/** @Annotation */
class DummyColumn extends \Doctrine\Common\Annotations\Annotation {
    public $type;
}
/** @Annotation */
class DummyGeneratedValue extends \Doctrine\Common\Annotations\Annotation {}
/** @Annotation */
class DummyAnnotation extends \Doctrine\Common\Annotations\Annotation {
    public $dummyValue;
}

/**
 * @api
 * @Annotation
 */
class DummyAnnotationWithIgnoredAnnotation extends \Doctrine\Common\Annotations\Annotation {
    public $dummyValue;
}

/** @Annotation */
class DummyJoinColumn extends \Doctrine\Common\Annotations\Annotation {
    public $name;
    public $referencedColumnName;
}
/** @Annotation */
class DummyJoinTable extends \Doctrine\Common\Annotations\Annotation {
    public $name;
    public $joinColumns;
    public $inverseJoinColumns;
}

/**
 * @DummyAnnotation(@)
 */
class DummyClassSyntaxError
{

}

class DummyClassMethodSyntaxError
{
    /**
     * @DummyAnnotation(@)
     */
    public function foo()
    {

    }
}

class DummyClassPropertySyntaxError
{
    /**
     * @DummyAnnotation(@)
     */
    public $foo;
}

/**
 * @ignoreAnnotation({"since", "var"})
 */
class DummyClassNonAnnotationProblem
{
    /**
     * @DummyAnnotation
     *
     * @var \Test
     * @since 0.1
     */
    public $foo;
}


/**
* @DummyAnnotation Foo bar <foobar@1domain.com>
*/
class DummyClassWithEmail
{

}


/**
 * @fixme public
 * @TODO
 */
class DCOM106
{
    
}

namespace Doctrine\Tests\Common\Annotations\Foo;

/** @Annotation */
class Name extends \Doctrine\Common\Annotations\Annotation
{
    public $name;
}

namespace Doctrine\Tests\Common\Annotations\Bar;

/** @Annotation */
class Name extends \Doctrine\Common\Annotations\Annotation
{
    public $name;
}
<?php

namespace Doctrine\Tests\Common\Annotations;

use Doctrine\Tests\Common\Annotations\DummyAnnotation;
use Doctrine\Tests\Common\Annotations\Name;
use Doctrine\Tests\Common\Annotations\DummyJoinTable;
use Doctrine\Tests\Common\Annotations\DummyJoinColumn;

/**
 * A description of this class.
 *
 * Let's see if the parser recognizes that this @ is not really referring to an
 * annotation. Also make sure that @var \ is not concated to "@var\is".
 *
 * @author robo
 * @since 2.0
 * @DummyAnnotation(dummyValue="hello")
 */
class DummyClass
{
    /**
     * A nice property.
     *
     * @var mixed
     * @DummyAnnotation(dummyValue="fieldHello")
     */
    private $field1;

    /**
     * @DummyJoinTable(name="join_table",
     *      joinColumns={@DummyJoinColumn(name="col1", referencedColumnName="col2")},
     *      inverseJoinColumns={
     *          @DummyJoinColumn(name="col3", referencedColumnName="col4")
     *      })
     */
    private $field2;

    /**
     * Gets the value of field1.
     *
     * @return mixed
     * @DummyAnnotation({1,2,"three"})
     */
    public function getField1()
    {
    }
}
<?php

namespace Doctrine\Tests\Common\Annotations;

use Doctrine\Common\Annotations\SimpleAnnotationReader;

class SimpleAnnotationReaderTest extends AbstractReaderTest
{
    /**
     * Contrary to the behavior of the default annotation reader, we do just ignore
     * these in the simple annotation reader (so, no expected exception here).
     */
    public function testImportDetectsNotImportedAnnotation()
    {
        parent::testImportDetectsNotImportedAnnotation();
    }

    /**
     * Contrary to the behavior of the default annotation reader, we do just ignore
     * these in the simple annotation reader (so, no expected exception here).
     */
    public function testImportDetectsNonExistentAnnotation()
    {
        parent::testImportDetectsNonExistentAnnotation();
    }

    /**
     * Contrary to the behavior of the default annotation reader, we do just ignore
     * these in the simple annotation reader (so, no expected exception here).
     */
    public function testClassWithInvalidAnnotationTargetAtClassDocBlock()
    {
        parent::testClassWithInvalidAnnotationTargetAtClassDocBlock();
    }

    /**
     * Contrary to the behavior of the default annotation reader, we do just ignore
     * these in the simple annotation reader (so, no expected exception here).
     */
    public function testClassWithInvalidAnnotationTargetAtPropertyDocBlock()
    {
        parent::testClassWithInvalidAnnotationTargetAtPropertyDocBlock();
    }

    /**
     * Contrary to the behavior of the default annotation reader, we do just ignore
     * these in the simple annotation reader (so, no expected exception here).
     */
    public function testClassWithInvalidNestedAnnotationTargetAtPropertyDocBlock()
    {
        parent::testClassWithInvalidNestedAnnotationTargetAtPropertyDocBlock();
    }

    /**
     * Contrary to the behavior of the default annotation reader, we do just ignore
     * these in the simple annotation reader (so, no expected exception here).
     */
    public function testClassWithInvalidAnnotationTargetAtMethodDocBlock()
    {
        parent::testClassWithInvalidAnnotationTargetAtMethodDocBlock();
    }

    /**
     * @expectedException Doctrine\Common\Annotations\AnnotationException
     */
    public function testInvalidAnnotationUsageButIgnoredClass()
    {
        parent::testInvalidAnnotationUsageButIgnoredClass();
    }

    /**
     * @group DDC-1660
     * @group regression
     *
     * Contrary to the behavior of the default annotation reader, @version is not ignored
     */
    public function testInvalidAnnotationButIgnored()
    {
        $reader = $this->getReader();
        $class  = new \ReflectionClass('Doctrine\Tests\Common\Annotations\Fixtures\ClassDDC1660');

        $this->assertTrue(class_exists('Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Version'));
        $this->assertCount(1, $reader->getClassAnnotations($class));
        $this->assertCount(1, $reader->getMethodAnnotations($class->getMethod('bar')));
        $this->assertCount(1, $reader->getPropertyAnnotations($class->getProperty('foo')));
    }
    
    protected function getReader()
    {
        $reader = new SimpleAnnotationReader();
        $reader->addNamespace(__NAMESPACE__);
        $reader->addNamespace(__NAMESPACE__ . '\Fixtures');
        $reader->addNamespace(__NAMESPACE__ . '\Fixtures\Annotation');

        return $reader;
    }
}<?php

namespace Doctrine\Tests\Common\Annotations;

use Doctrine\Common\Annotations\DocLexer;

class DocLexerTest extends \PHPUnit_Framework_TestCase
{
    public function testMarkerAnnotation()
    {
        $lexer = new DocLexer;

        $lexer->setInput("@Name");
        $this->assertNull($lexer->token);
        $this->assertNull($lexer->lookahead);

        $this->assertTrue($lexer->moveNext());
        $this->assertNull($lexer->token);
        $this->assertEquals('@', $lexer->lookahead['value']);

        $this->assertTrue($lexer->moveNext());
        $this->assertEquals('@', $lexer->token['value']);
        $this->assertEquals('Name', $lexer->lookahead['value']);

        $this->assertFalse($lexer->moveNext());
    }

    public function testScannerTokenizesDocBlockWhitConstants()
    {
        $lexer      = new DocLexer();
        $docblock   = '@AnnotationWithConstants(PHP_EOL, ClassWithConstants::SOME_VALUE, \Doctrine\Tests\Common\Annotations\Fixtures\IntefaceWithConstants::SOME_VALUE)';

        $tokens = array (
            array(
                'value'     => '@',
                'position'  => 0,
                'type'      => DocLexer::T_AT,
            ),
            array(
                'value'     => 'AnnotationWithConstants',
                'position'  => 1,
                'type'      => DocLexer::T_IDENTIFIER,
            ),
            array(
                'value'     => '(',
                'position'  => 24,
                'type'      => DocLexer::T_OPEN_PARENTHESIS,
            ),
            array(
                'value'     => 'PHP_EOL',
                'position'  => 25,
                'type'      => DocLexer::T_IDENTIFIER,
            ),
            array(
                'value'     => ',',
                'position'  => 32,
                'type'      => DocLexer::T_COMMA,
            ),
            array(
                'value'     => 'ClassWithConstants::SOME_VALUE',
                'position'  => 34,
                'type'      => DocLexer::T_IDENTIFIER,
            ),
            array(
                'value'     => ',',
                'position'  => 64,
                'type'      => DocLexer::T_COMMA,
            ),
            array(
                'value'     => '\\Doctrine\\Tests\\Common\\Annotations\\Fixtures\\IntefaceWithConstants::SOME_VALUE',
                'position'  => 66,
                'type'      => DocLexer::T_IDENTIFIER,
            ),
            array(
                'value'     => ')',
                'position'  => 143,
                'type'      => DocLexer::T_CLOSE_PARENTHESIS,
            )

        );

        $lexer->setInput($docblock);

        foreach ($tokens as $expected) {
            $lexer->moveNext();
            $lookahead = $lexer->lookahead;
            $this->assertEquals($expected['value'],     $lookahead['value']);
            $this->assertEquals($expected['type'],      $lookahead['type']);
            $this->assertEquals($expected['position'],  $lookahead['position']);
        }

        $this->assertFalse($lexer->moveNext());
    }


    public function testScannerTokenizesDocBlockWhitInvalidIdentifier()
    {
        $lexer      = new DocLexer();
        $docblock   = '@Foo\3.42';

        $tokens = array (
            array(
                'value'     => '@',
                'position'  => 0,
                'type'      => DocLexer::T_AT,
            ),
            array(
                'value'     => 'Foo',
                'position'  => 1,
                'type'      => DocLexer::T_IDENTIFIER,
            ),
            array(
                'value'     => '\\',
                'position'  => 4,
                'type'      => DocLexer::T_NAMESPACE_SEPARATOR,
            ),
            array(
                'value'     => 3.42,
                'position'  => 5,
                'type'      => DocLexer::T_FLOAT,
            )
        );

        $lexer->setInput($docblock);

        foreach ($tokens as $expected) {
            $lexer->moveNext();
            $lookahead = $lexer->lookahead;
            $this->assertEquals($expected['value'],     $lookahead['value']);
            $this->assertEquals($expected['type'],      $lookahead['type']);
            $this->assertEquals($expected['position'],  $lookahead['position']);
        }

        $this->assertFalse($lexer->moveNext());
    }

}<?php

namespace Doctrine\Tests\Common\Annotations;

use Doctrine\Tests\Common\Annotations\Fixtures\Annotation\Route;
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\CachedReader;
use Doctrine\Common\Cache\ArrayCache;

class CachedReaderTest extends AbstractReaderTest
{
    private $cache;

    public function testIgnoresStaleCache()
    {
        $file = __DIR__.'/Fixtures/Controller.php';
        touch($file);
        $name = 'Doctrine\Tests\Common\Annotations\Fixtures\Controller';
        $cacheKey = $name.'@[Annot]';

        $cache = $this->getMock('Doctrine\Common\Cache\Cache');
        $cache
            ->expects($this->at(0))
            ->method('fetch')
            ->with($this->equalTo($cacheKey))
            ->will($this->returnValue(array()))
        ;
        $cache
            ->expects($this->at(1))
            ->method('fetch')
            ->with($this->equalTo('[C]'.$cacheKey))
            ->will($this->returnValue(time() - 10))
        ;
        $cache
            ->expects($this->at(2))
            ->method('save')
            ->with($this->equalTo($cacheKey))
        ;
        $cache
            ->expects($this->at(3))
            ->method('save')
            ->with($this->equalTo('[C]'.$cacheKey))
        ;

        $reader = new CachedReader(new AnnotationReader(), $cache, true);
        $route = new Route();
        $route->pattern = '/someprefix';
        $this->assertEquals(array($route), $reader->getClassAnnotations(new \ReflectionClass($name)));
    }

    protected function getReader()
    {
        $this->cache = new ArrayCache();
        return new CachedReader(new AnnotationReader(), $this->cache);
    }
}<?php

namespace Doctrine\Tests;

/**
 * Base testcase class for all Doctrine testcases.
 */
abstract class DoctrineTestCase extends \PHPUnit_Framework_TestCase
{
}<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="./tests/Doctrine/Tests/TestInit.php"
>
    <testsuites>
        <testsuite name="Doctrine Annotations Test Suite">
            <directory>./tests/Doctrine/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./lib/Doctrine/</directory>
        </whitelist>
    </filter>
    
    <groups>
        <exclude>
            <group>performance</group>
        </exclude>
    </groups>
</phpunit>
<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations;


/**
 * File cache reader for annotations.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 */
class FileCacheReader implements Reader
{
    /**
     * @var Reader
     */
    private $reader;

    /**
     * @var string
     */
    private $dir;

    /**
     * @var bool
     */
    private $debug;

    /**
     * @var array
     */
    private $loadedAnnotations = array();

    private $classNameHashes = array();

    /**
     * Constructor
     *
     * @param Reader $reader
     * @param string $cacheDir
     * @param bool $debug
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(Reader $reader, $cacheDir, $debug = false)
    {
        $this->reader = $reader;
        if (!is_dir($cacheDir) && !@mkdir($cacheDir, 0777, true)) {
            throw new \InvalidArgumentException(sprintf('The directory "%s" does not exist and could not be created.', $cacheDir));
        }
        if (!is_writable($cacheDir)) {
            throw new \InvalidArgumentException(sprintf('The directory "%s" is not writable. Both, the webserver and the console user need access. You can manage access rights for multiple users with "chmod +a". If your system does not support this, check out the acl package.', $cacheDir));
        }

        $this->dir   = rtrim($cacheDir, '\\/');
        $this->debug = $debug;
    }

    /**
     * Retrieve annotations for class
     *
     * @param \ReflectionClass $class
     * @return array
     */
    public function getClassAnnotations(\ReflectionClass $class)
    {
        if ( ! isset($this->classNameHashes[$class->name])) {
            $this->classNameHashes[$class->name] = sha1($class->name);
        }
        $key = $this->classNameHashes[$class->name];

        if (isset($this->loadedAnnotations[$key])) {
            return $this->loadedAnnotations[$key];
        }

        $path = $this->dir.'/'.strtr($key, '\\', '-').'.cache.php';
        if (!is_file($path)) {
            $annot = $this->reader->getClassAnnotations($class);
            $this->saveCacheFile($path, $annot);
            return $this->loadedAnnotations[$key] = $annot;
        }

        if ($this->debug
            && (false !== $filename = $class->getFilename())
            && filemtime($path) < filemtime($filename)) {
            @unlink($path);

            $annot = $this->reader->getClassAnnotations($class);
            $this->saveCacheFile($path, $annot);
            return $this->loadedAnnotations[$key] = $annot;
        }

        return $this->loadedAnnotations[$key] = include $path;
    }

    /**
     * Get annotations for property
     *
     * @param \ReflectionProperty $property
     * @return array
     */
    public function getPropertyAnnotations(\ReflectionProperty $property)
    {
        $class = $property->getDeclaringClass();
        if ( ! isset($this->classNameHashes[$class->name])) {
            $this->classNameHashes[$class->name] = sha1($class->name);
        }
        $key = $this->classNameHashes[$class->name].'$'.$property->getName();

        if (isset($this->loadedAnnotations[$key])) {
            return $this->loadedAnnotations[$key];
        }

        $path = $this->dir.'/'.strtr($key, '\\', '-').'.cache.php';
        if (!is_file($path)) {
            $annot = $this->reader->getPropertyAnnotations($property);
            $this->saveCacheFile($path, $annot);
            return $this->loadedAnnotations[$key] = $annot;
        }

        if ($this->debug
            && (false !== $filename = $class->getFilename())
            && filemtime($path) < filemtime($filename)) {
            @unlink($path);

            $annot = $this->reader->getPropertyAnnotations($property);
            $this->saveCacheFile($path, $annot);
            return $this->loadedAnnotations[$key] = $annot;
        }

        return $this->loadedAnnotations[$key] = include $path;
    }

    /**
     * Retrieve annotations for method
     *
     * @param \ReflectionMethod $method
     * @return array
     */
    public function getMethodAnnotations(\ReflectionMethod $method)
    {
        $class = $method->getDeclaringClass();
        if ( ! isset($this->classNameHashes[$class->name])) {
            $this->classNameHashes[$class->name] = sha1($class->name);
        }
        $key = $this->classNameHashes[$class->name].'#'.$method->getName();

        if (isset($this->loadedAnnotations[$key])) {
            return $this->loadedAnnotations[$key];
        }

        $path = $this->dir.'/'.strtr($key, '\\', '-').'.cache.php';
        if (!is_file($path)) {
            $annot = $this->reader->getMethodAnnotations($method);
            $this->saveCacheFile($path, $annot);
            return $this->loadedAnnotations[$key] = $annot;
        }

        if ($this->debug
            && (false !== $filename = $class->getFilename())
            && filemtime($path) < filemtime($filename)) {
            @unlink($path);

            $annot = $this->reader->getMethodAnnotations($method);
            $this->saveCacheFile($path, $annot);
            return $this->loadedAnnotations[$key] = $annot;
        }

        return $this->loadedAnnotations[$key] = include $path;
    }

    /**
     * Save cache file
     *
     * @param string $path
     * @param mixed $data
     */
    private function saveCacheFile($path, $data)
    {
        file_put_contents($path, '<?php return unserialize('.var_export(serialize($data), true).');');
    }

    /**
     * Gets a class annotation.
     *
     * @param \ReflectionClass $class The ReflectionClass of the class from which
     *                               the class annotations should be read.
     * @param string $annotationName The name of the annotation.
     *
     * @return mixed The Annotation or NULL, if the requested annotation does not exist.
     */
    public function getClassAnnotation(\ReflectionClass $class, $annotationName)
    {
        $annotations = $this->getClassAnnotations($class);

        foreach ($annotations as $annotation) {
            if ($annotation instanceof $annotationName) {
                return $annotation;
            }
        }

        return null;
    }

    /**
     * Gets a method annotation.
     *
     * @param \ReflectionMethod $method
     * @param string $annotationName The name of the annotation.
     * @return mixed The Annotation or NULL, if the requested annotation does not exist.
     */
    public function getMethodAnnotation(\ReflectionMethod $method, $annotationName)
    {
        $annotations = $this->getMethodAnnotations($method);

        foreach ($annotations as $annotation) {
            if ($annotation instanceof $annotationName) {
                return $annotation;
            }
        }

        return null;
    }

    /**
     * Gets a property annotation.
     *
     * @param \ReflectionProperty $property
     * @param string $annotationName The name of the annotation.
     * @return mixed The Annotation or NULL, if the requested annotation does not exist.
     */
    public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName)
    {
        $annotations = $this->getPropertyAnnotations($property);

        foreach ($annotations as $annotation) {
            if ($annotation instanceof $annotationName) {
                return $annotation;
            }
        }

        return null;
    }

    /**
     * Clear stores annotations
     */
    public function clearLoadedAnnotations()
    {
        $this->loadedAnnotations = array();
    }
}
<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations;

/**
 * Interface for annotation readers.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface Reader
{
    /**
     * @param \ReflectionClass $class
     * @return mixed
     */
    function getClassAnnotations(\ReflectionClass $class);

    /**
     * @param \ReflectionClass $class
     * @param string $annotationName
     * @return mixed
     */
    function getClassAnnotation(\ReflectionClass $class, $annotationName);

    /**
     * @param \ReflectionMethod $method
     * @return mixed
     */
    function getMethodAnnotations(\ReflectionMethod $method);

    /**
     * @param \ReflectionMethod $method
     * @param string $annotationName
     * @return mixed
     */
    function getMethodAnnotation(\ReflectionMethod $method, $annotationName);

    /**
     * @param \ReflectionProperty $property
     * @return mixed
     */
    function getPropertyAnnotations(\ReflectionProperty $property);

    /**
     * @param \ReflectionProperty $property
     * @param string $annotationName
     * @return mixed
     */
    function getPropertyAnnotation(\ReflectionProperty $property, $annotationName);
}
<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations;

use Closure;
use ReflectionClass;
use Doctrine\Common\Annotations\Annotation\Enum;
use Doctrine\Common\Annotations\Annotation\Target;
use Doctrine\Common\Annotations\Annotation\Attribute;
use Doctrine\Common\Annotations\Annotation\Attributes;

/**
 * A parser for docblock annotations.
 *
 * It is strongly discouraged to change the default annotation parsing process.
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author Jonathan Wage <jonwage@gmail.com>
 * @author Roman Borschel <roman@code-factory.org>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Fabio B. Silva <fabio.bat.silva@gmail.com>
 */
final class DocParser
{
    /**
     * An array of all valid tokens for a class name.
     *
     * @var array
     */
    private static $classIdentifiers = array(DocLexer::T_IDENTIFIER, DocLexer::T_TRUE, DocLexer::T_FALSE, DocLexer::T_NULL);

    /**
     * The lexer.
     *
     * @var \Doctrine\Common\Annotations\DocLexer
     */
    private $lexer;

    /**
     * Current target context
     *
     * @var string
     */
    private $target;

    /**
     * Doc Parser used to collect annotation target
     *
     * @var \Doctrine\Common\Annotations\DocParser
     */
    private static $metadataParser;

    /**
     * Flag to control if the current annotation is nested or not.
     *
     * @var boolean
     */
    private $isNestedAnnotation = false;

    /**
     * Hashmap containing all use-statements that are to be used when parsing
     * the given doc block.
     *
     * @var array
     */
    private $imports = array();

    /**
     * This hashmap is used internally to cache results of class_exists()
     * look-ups.
     *
     * @var array
     */
    private $classExists = array();

    /**
     * Whether annotations that have not been imported should be ignored.
     *
     * @var boolean
     */
    private $ignoreNotImportedAnnotations = false;

    /**
     * An array of default namespaces if operating in simple mode.
     *
     * @var array
     */
    private $namespaces = array();

    /**
     * A list with annotations that are not causing exceptions when not resolved to an annotation class.
     *
     * The names must be the raw names as used in the class, not the fully qualified
     * class names.
     *
     * @var array
     */
    private $ignoredAnnotationNames = array();

    /**
     * @var string
     */
    private $context = '';

    /**
     * Hash-map for caching annotation metadata
     * @var array
     */
    private static $annotationMetadata = array(
        'Doctrine\Common\Annotations\Annotation\Target' => array(
            'is_annotation'    => true,
            'has_constructor'  => true,
            'properties'       => array(),
            'targets_literal'  => 'ANNOTATION_CLASS',
            'targets'          => Target::TARGET_CLASS,
            'default_property' => 'value',
            'attribute_types'  => array(
                'value'  => array(
                    'required'  => false,
                    'type'      =>'array',
                    'array_type'=>'string',
                    'value'     =>'array<string>'
                )
             ),
        ),
        'Doctrine\Common\Annotations\Annotation\Attribute' => array(
            'is_annotation'    => true,
            'has_constructor'  => false,
            'targets_literal'  => 'ANNOTATION_ANNOTATION',
            'targets'          => Target::TARGET_ANNOTATION,
            'default_property' => 'name',
            'properties'       => array(
                'name'      => 'name',
                'type'      => 'type',
                'required'  => 'required'
            ),
            'attribute_types'  => array(
                'value'  => array(
                    'required'  => true,
                    'type'      =>'string',
                    'value'     =>'string'
                ),
                'type'  => array(
                    'required'  =>true,
                    'type'      =>'string',
                    'value'     =>'string'
                ),
                'required'  => array(
                    'required'  =>false,
                    'type'      =>'boolean',
                    'value'     =>'boolean'
                )
             ),
        ),
        'Doctrine\Common\Annotations\Annotation\Attributes' => array(
            'is_annotation'    => true,
            'has_constructor'  => false,
            'targets_literal'  => 'ANNOTATION_CLASS',
            'targets'          => Target::TARGET_CLASS,
            'default_property' => 'value',
            'properties'       => array(
                'value' => 'value'
            ),
            'attribute_types'  => array(
                'value' => array(
                    'type'      =>'array',
                    'required'  =>true,
                    'array_type'=>'Doctrine\Common\Annotations\Annotation\Attribute',
                    'value'     =>'array<Doctrine\Common\Annotations\Annotation\Attribute>'
                )
             ),
        ),
        'Doctrine\Common\Annotations\Annotation\Enum' => array(
            'is_annotation'    => true,
            'has_constructor'  => true,
            'targets_literal'  => 'ANNOTATION_PROPERTY',
            'targets'          => Target::TARGET_PROPERTY,
            'default_property' => 'value',
            'properties'       => array(
                'value' => 'value'
            ),
            'attribute_types'  => array(
                'value' => array(
                    'type'      => 'array',
                    'required'  => true,
                ),
                'literal' => array(
                    'type'      => 'array',
                    'required'  => false,
                ),
             ),
        ),
    );

    /**
     * Hash-map for handle types declaration
     *
     * @var array
     */
    private static $typeMap = array(
        'float'     => 'double',
        'bool'      => 'boolean',
        // allow uppercase Boolean in honor of George Boole
        'Boolean'   => 'boolean',
        'int'       => 'integer',
    );

    /**
     * Constructs a new DocParser.
     */
    public function __construct()
    {
        $this->lexer = new DocLexer;
    }

    /**
     * Sets the annotation names that are ignored during the parsing process.
     *
     * The names are supposed to be the raw names as used in the class, not the
     * fully qualified class names.
     *
     * @param array $names
     */
    public function setIgnoredAnnotationNames(array $names)
    {
        $this->ignoredAnnotationNames = $names;
    }

    /**
     * Sets ignore on not-imported annotations
     *
     * @param $bool
     */
    public function setIgnoreNotImportedAnnotations($bool)
    {
        $this->ignoreNotImportedAnnotations = (Boolean) $bool;
    }

    /**
     * Sets the default namespaces.
     *
     * @param array $namespace
     *
     * @throws \RuntimeException
     */
    public function addNamespace($namespace)
    {
        if ($this->imports) {
            throw new \RuntimeException('You must either use addNamespace(), or setImports(), but not both.');
        }
        $this->namespaces[] = $namespace;
    }

    /**
     * Sets the imports
     *
     * @param array $imports
     * @throws \RuntimeException
     */
    public function setImports(array $imports)
    {
        if ($this->namespaces) {
            throw new \RuntimeException('You must either use addNamespace(), or setImports(), but not both.');
        }
        $this->imports = $imports;
    }

     /**
     * Sets current target context as bitmask.
     *
     * @param integer $target
     */
    public function setTarget($target)
    {
        $this->target = $target;
    }

    /**
     * Parses the given docblock string for annotations.
     *
     * @param string $input The docblock string to parse.
     * @param string $context The parsing context.
     * @return array Array of annotations. If no annotations are found, an empty array is returned.
     */
    public function parse($input, $context = '')
    {
        if (false === $pos = strpos($input, '@')) {
            return array();
        }

        // also parse whatever character is before the @
        if ($pos > 0) {
            $pos -= 1;
        }

        $this->context = $context;
        $this->lexer->setInput(trim(substr($input, $pos), '* /'));
        $this->lexer->moveNext();

        return $this->Annotations();
    }

    /**
     * Attempts to match the given token with the current lookahead token.
     * If they match, updates the lookahead token; otherwise raises a syntax error.
     *
     * @param int $token type of Token.
     * @return bool True if tokens match; false otherwise.
     */
    private function match($token)
    {
        if ( ! $this->lexer->isNextToken($token) ) {
            $this->syntaxError($this->lexer->getLiteral($token));
        }

        return $this->lexer->moveNext();
    }

    /**
     * Attempts to match the current lookahead token with any of the given tokens.
     *
     * If any of them matches, this method updates the lookahead token; otherwise
     * a syntax error is raised.
     *
     * @param array $tokens
     * @return bool
     */
    private function matchAny(array $tokens)
    {
        if ( ! $this->lexer->isNextTokenAny($tokens)) {
            $this->syntaxError(implode(' or ', array_map(array($this->lexer, 'getLiteral'), $tokens)));
        }

        return $this->lexer->moveNext();
    }

    /**
     * Generates a new syntax error.
     *
     * @param string $expected Expected string.
     * @param array $token Optional token.
     *
     * @throws AnnotationException
     */
    private function syntaxError($expected, $token = null)
    {
        if ($token === null) {
            $token = $this->lexer->lookahead;
        }

        $message =  "Expected {$expected}, got ";

        if ($this->lexer->lookahead === null) {
            $message .= 'end of string';
        } else {
            $message .= "'{$token['value']}' at position {$token['position']}";
        }

        if (strlen($this->context)) {
            $message .= ' in ' . $this->context;
        }

        $message .= '.';

        throw AnnotationException::syntaxError($message);
    }

    /**
     * Attempt to check if a class exists or not. This never goes through the PHP autoloading mechanism
     * but uses the {@link AnnotationRegistry} to load classes.
     *
     * @param string $fqcn
     * @return boolean
     */
    private function classExists($fqcn)
    {
        if (isset($this->classExists[$fqcn])) {
            return $this->classExists[$fqcn];
        }

        // first check if the class already exists, maybe loaded through another AnnotationReader
        if (class_exists($fqcn, false)) {
            return $this->classExists[$fqcn] = true;
        }

        // final check, does this class exist?
        return $this->classExists[$fqcn] = AnnotationRegistry::loadAnnotationClass($fqcn);
    }

    /**
     * Collects parsing metadata for a given annotation class
     *
     * @param string $name The annotation name
     */
    private function collectAnnotationMetadata($name)
    {
        if (self::$metadataParser == null){
            self::$metadataParser = new self();
            self::$metadataParser->setIgnoreNotImportedAnnotations(true);
            self::$metadataParser->setIgnoredAnnotationNames($this->ignoredAnnotationNames);
            self::$metadataParser->setImports(array(
                'enum'          => 'Doctrine\Common\Annotations\Annotation\Enum',
                'target'        => 'Doctrine\Common\Annotations\Annotation\Target',
                'attribute'     => 'Doctrine\Common\Annotations\Annotation\Attribute',
                'attributes'    => 'Doctrine\Common\Annotations\Annotation\Attributes'
            ));
            AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Enum.php');
            AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Target.php');
            AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Attribute.php');
            AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Attributes.php');
        }

        $class      = new \ReflectionClass($name);
        $docComment = $class->getDocComment();

        // Sets default values for annotation metadata
        $metadata = array(
            'default_property' => null,
            'has_constructor'  => (null !== $constructor = $class->getConstructor()) && $constructor->getNumberOfParameters() > 0,
            'properties'       => array(),
            'property_types'   => array(),
            'attribute_types'  => array(),
            'targets_literal'  => null,
            'targets'          => Target::TARGET_ALL,
            'is_annotation'    => false !== strpos($docComment, '@Annotation'),
        );

        // verify that the class is really meant to be an annotation
        if ($metadata['is_annotation']) {

            self::$metadataParser->setTarget(Target::TARGET_CLASS);

            foreach (self::$metadataParser->parse($docComment, 'class @' . $name) as $annotation) {
                if ($annotation instanceof Target) {
                    $metadata['targets']         = $annotation->targets;
                    $metadata['targets_literal'] = $annotation->literal;

                } elseif ($annotation instanceof Attributes) {
                    foreach ($annotation->value as $attrib) {
                        // handle internal type declaration
                        $type = isset(self::$typeMap[$attrib->type]) ? self::$typeMap[$attrib->type] : $attrib->type;

                        // handle the case if the property type is mixed
                        if ('mixed' !== $type) {
                            // Checks if the property has array<type>
                            if (false !== $pos = strpos($type, '<')) {
                                $arrayType  = substr($type, $pos+1, -1);
                                $type       = 'array';

                                if (isset(self::$typeMap[$arrayType])) {
                                    $arrayType = self::$typeMap[$arrayType];
                                }

                                $metadata['attribute_types'][$attrib->name]['array_type'] = $arrayType;
                            }

                            $metadata['attribute_types'][$attrib->name]['type']     = $type;
                            $metadata['attribute_types'][$attrib->name]['value']    = $attrib->type;
                            $metadata['attribute_types'][$attrib->name]['required'] = $attrib->required;
                        }
                    }
                }
            }

            // if not has a constructor will inject values into public properties
            if (false === $metadata['has_constructor']) {
                // collect all public properties
                foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) {
                    $metadata['properties'][$property->name] = $property->name;
                    
                    if(false === ($propertyComment = $property->getDocComment())) {
                        continue;
                    }

                    // checks if the property has @var annotation
                    if (false !== strpos($propertyComment, '@var')
                        && preg_match('/@var\s+([^\s]+)/',$propertyComment, $matches)) {
                        // literal type declaration
                        $value = $matches[1];

                        // handle internal type declaration
                        $type = isset(self::$typeMap[$value]) ? self::$typeMap[$value] : $value;

                        // handle the case if the property type is mixed
                        if ('mixed' !== $type) {
                            // Checks if the property has @var array<type> annotation
                            if (false !== $pos = strpos($type, '<')) {
                                $arrayType = substr($type, $pos+1, -1);
                                $type = 'array';

                                if (isset(self::$typeMap[$arrayType])) {
                                    $arrayType = self::$typeMap[$arrayType];
                                }

                                $metadata['attribute_types'][$property->name]['array_type'] = $arrayType;
                            }

                            $metadata['attribute_types'][$property->name]['type']       = $type;
                            $metadata['attribute_types'][$property->name]['value']      = $value;
                            $metadata['attribute_types'][$property->name]['required']   = false !== strpos($propertyComment, '@Required');
                        }
                    }

                    // checks if the property has @Enum
                    if (false !== strpos($propertyComment, '@Enum')){

                        $context = 'property ' . $class->name . "::\$" . $property->name;
                        self::$metadataParser->setTarget(Target::TARGET_PROPERTY);

                        foreach (self::$metadataParser->parse($propertyComment, $context) as $annotation) {
                            if($annotation instanceof Enum) {
                                $metadata['enum'][$property->name]['value']   = $annotation->value;
                                $metadata['enum'][$property->name]['literal'] = ! empty($annotation->literal) ? $annotation->literal : $annotation->value;
                            }
                        }
                    }
                }

                // choose the first property as default property
                $metadata['default_property'] = reset($metadata['properties']);
            }
        }

        self::$annotationMetadata[$name] = $metadata;
    }

    /**
     * Annotations ::= Annotation {[ "*" ]* [Annotation]}*
     *
     * @return array
     */
    private function Annotations()
    {
        $annotations = array();

        while (null !== $this->lexer->lookahead) {
            if (DocLexer::T_AT !== $this->lexer->lookahead['type']) {
                $this->lexer->moveNext();
                continue;
            }

            // make sure the @ is preceded by non-catchable pattern
            if (null !== $this->lexer->token && $this->lexer->lookahead['position'] === $this->lexer->token['position'] + strlen($this->lexer->token['value'])) {
                $this->lexer->moveNext();
                continue;
            }

            // make sure the @ is followed by either a namespace separator, or
            // an identifier token
            if ((null === $peek = $this->lexer->glimpse())
                || (DocLexer::T_NAMESPACE_SEPARATOR !== $peek['type'] && !in_array($peek['type'], self::$classIdentifiers, true))
                || $peek['position'] !== $this->lexer->lookahead['position'] + 1) {
                $this->lexer->moveNext();
                continue;
            }

            $this->isNestedAnnotation = false;
            if (false !== $annot = $this->Annotation()) {
                $annotations[] = $annot;
            }
        }

        return $annotations;
    }

    /**
     * Annotation     ::= "@" AnnotationName ["(" [Values] ")"]
     * AnnotationName ::= QualifiedName | SimpleName
     * QualifiedName  ::= NameSpacePart "\" {NameSpacePart "\"}* SimpleName
     * NameSpacePart  ::= identifier | null | false | true
     * SimpleName     ::= identifier | null | false | true
     *
     * @throws AnnotationException
     * @return mixed False if it is not a valid annotation.
     */
    private function Annotation()
    {
        $this->match(DocLexer::T_AT);

        // check if we have an annotation
        $name = $this->Identifier();

        // only process names which are not fully qualified, yet
        // fully qualified names must start with a \
        $originalName = $name;
        if ('\\' !== $name[0]) {
            $alias = (false === $pos = strpos($name, '\\'))? $name : substr($name, 0, $pos);

            $found = false;
            if ($this->namespaces) {
                foreach ($this->namespaces as $namespace) {
                    if ($this->classExists($namespace.'\\'.$name)) {
                        $name = $namespace.'\\'.$name;
                        $found = true;
                        break;
                    }
                }
            } elseif (isset($this->imports[$loweredAlias = strtolower($alias)])) {
                if (false !== $pos) {
                    $name = $this->imports[$loweredAlias].substr($name, $pos);
                } else {
                    $name = $this->imports[$loweredAlias];
                }
                $found = true;
            } elseif (isset($this->imports['__NAMESPACE__']) && $this->classExists($this->imports['__NAMESPACE__'].'\\'.$name)) {
                 $name = $this->imports['__NAMESPACE__'].'\\'.$name;
                 $found = true;
            } elseif ($this->classExists($name)) {
                $found = true;
            }

            if (!$found) {
                if ($this->ignoreNotImportedAnnotations || isset($this->ignoredAnnotationNames[$name])) {
                    return false;
                }

                throw AnnotationException::semanticalError(sprintf('The annotation "@%s" in %s was never imported. Did you maybe forget to add a "use" statement for this annotation?', $name, $this->context));
            }
        }

        if (!$this->classExists($name)) {
            throw AnnotationException::semanticalError(sprintf('The annotation "@%s" in %s does not exist, or could not be auto-loaded.', $name, $this->context));
        }

        // at this point, $name contains the fully qualified class name of the
        // annotation, and it is also guaranteed that this class exists, and
        // that it is loaded


        // collects the metadata annotation only if there is not yet
        if (!isset(self::$annotationMetadata[$name])) {
            $this->collectAnnotationMetadata($name);
        }

        // verify that the class is really meant to be an annotation and not just any ordinary class
        if (self::$annotationMetadata[$name]['is_annotation'] === false) {
            if (isset($this->ignoredAnnotationNames[$originalName])) {
                return false;
            }

            throw AnnotationException::semanticalError(sprintf('The class "%s" is not annotated with @Annotation. Are you sure this class can be used as annotation? If so, then you need to add @Annotation to the _class_ doc comment of "%s". If it is indeed no annotation, then you need to add @IgnoreAnnotation("%s") to the _class_ doc comment of %s.', $name, $name, $originalName, $this->context));
        }

        //if target is nested annotation
        $target = $this->isNestedAnnotation ? Target::TARGET_ANNOTATION : $this->target;

        // Next will be nested
        $this->isNestedAnnotation = true;

        //if annotation does not support current target
        if (0 === (self::$annotationMetadata[$name]['targets'] & $target) && $target) {
            throw AnnotationException::semanticalError(
                sprintf('Annotation @%s is not allowed to be declared on %s. You may only use this annotation on these code elements: %s.',
                     $originalName, $this->context, self::$annotationMetadata[$name]['targets_literal'])
            );
        }

        $values = array();
        if ($this->lexer->isNextToken(DocLexer::T_OPEN_PARENTHESIS)) {
            $this->match(DocLexer::T_OPEN_PARENTHESIS);

            if ( ! $this->lexer->isNextToken(DocLexer::T_CLOSE_PARENTHESIS)) {
                $values = $this->Values();
            }

            $this->match(DocLexer::T_CLOSE_PARENTHESIS);
        }

        if (isset(self::$annotationMetadata[$name]['enum'])) {
            // checks all declared attributes
            foreach (self::$annotationMetadata[$name]['enum'] as $property => $enum) {
                // checks if the attribute is a valid enumerator
                if (isset($values[$property]) && ! in_array($values[$property], $enum['value'])) {
                    throw AnnotationException::enumeratorError($property, $name, $this->context, $enum['literal'], $values[$property]);
                }
            }
        }

        // checks all declared attributes
        foreach (self::$annotationMetadata[$name]['attribute_types'] as $property => $type) {
            if ($property === self::$annotationMetadata[$name]['default_property']
                && !isset($values[$property]) && isset($values['value'])) {
                $property = 'value';
            }

            // handle a not given attribute or null value
            if (!isset($values[$property])) {
                if ($type['required']) {
                    throw AnnotationException::requiredError($property, $originalName, $this->context, 'a(n) '.$type['value']);
                }

                continue;
            }

            if ($type['type'] === 'array') {
                // handle the case of a single value
                if ( ! is_array($values[$property])) {
                    $values[$property] = array($values[$property]);
                }

                // checks if the attribute has array type declaration, such as "array<string>"
                if (isset($type['array_type'])) {
                    foreach ($values[$property] as $item) {
                        if (gettype($item) !== $type['array_type'] && !$item instanceof $type['array_type']) {
                            throw AnnotationException::typeError($property, $originalName, $this->context, 'either a(n) '.$type['array_type'].', or an array of '.$type['array_type'].'s', $item);
                        }
                    }
                }
            } elseif (gettype($values[$property]) !== $type['type'] && !$values[$property] instanceof $type['type']) {
                throw AnnotationException::typeError($property, $originalName, $this->context, 'a(n) '.$type['value'], $values[$property]);
            }
        }

        // check if the annotation expects values via the constructor,
        // or directly injected into public properties
        if (self::$annotationMetadata[$name]['has_constructor'] === true) {
            return new $name($values);
        }

        $instance = new $name();
        foreach ($values as $property => $value) {
            if (!isset(self::$annotationMetadata[$name]['properties'][$property])) {
                if ('value' !== $property) {
                    throw AnnotationException::creationError(sprintf('The annotation @%s declared on %s does not have a property named "%s". Available properties: %s', $originalName, $this->context, $property, implode(', ', self::$annotationMetadata[$name]['properties'])));
                }

                // handle the case if the property has no annotations
                if (!$property = self::$annotationMetadata[$name]['default_property']) {
                    throw AnnotationException::creationError(sprintf('The annotation @%s declared on %s does not accept any values, but got %s.', $originalName, $this->context, json_encode($values)));
                }
            }

            $instance->{$property} = $value;
        }

        return $instance;
    }

    /**
     * Values ::= Array | Value {"," Value}*
     *
     * @return array
     */
    private function Values()
    {
        $values = array();

        // Handle the case of a single array as value, i.e. @Foo({....})
        if ($this->lexer->isNextToken(DocLexer::T_OPEN_CURLY_BRACES)) {
            $values['value'] = $this->Value();
            return $values;
        }

        $values[] = $this->Value();

        while ($this->lexer->isNextToken(DocLexer::T_COMMA)) {
            $this->match(DocLexer::T_COMMA);
            $token = $this->lexer->lookahead;
            $value = $this->Value();

            if ( ! is_object($value) && ! is_array($value)) {
                $this->syntaxError('Value', $token);
            }

            $values[] = $value;
        }

        foreach ($values as $k => $value) {
            if (is_object($value) && $value instanceof \stdClass) {
                $values[$value->name] = $value->value;
            } else if ( ! isset($values['value'])){
                $values['value'] = $value;
            } else {
                if ( ! is_array($values['value'])) {
                    $values['value'] = array($values['value']);
                }

                $values['value'][] = $value;
            }

            unset($values[$k]);
        }

        return $values;
    }

    /**
     * Constant ::= integer | string | float | boolean
     *
     * @throws AnnotationException
     * @return mixed
     */
    private function Constant()
    {
        $identifier = $this->Identifier();

        if (!defined($identifier) && false !== strpos($identifier, '::') && '\\' !== $identifier[0]) {

            list($className, $const) = explode('::', $identifier);
            $alias = (false === $pos = strpos($className, '\\'))? $className : substr($className, 0, $pos);

            $found = false;
            switch (true) {
                case !empty ($this->namespaces):
                    foreach ($this->namespaces as $ns) {
                        if (class_exists($ns.'\\'.$className) || interface_exists($ns.'\\'.$className)) {
                             $className = $ns.'\\'.$className;
                             $found = true;
                             break;
                        }
                    }
                    break;

                case isset($this->imports[$loweredAlias = strtolower($alias)]):
                    $found = true;
                    if (false !== $pos) {
                        $className = $this->imports[$loweredAlias].substr($className, $pos);
                    } else {
                        $className = $this->imports[$loweredAlias];
                    }
                    break;

                default:
                    if(isset($this->imports['__NAMESPACE__'])) {
                        $ns = $this->imports['__NAMESPACE__'];
                        if (class_exists($ns.'\\'.$className) || interface_exists($ns.'\\'.$className)) {
                             $className = $ns.'\\'.$className;
                             $found = true;
                        }
                    }
                    break;
            }

            if ($found) {
                 $identifier = $className . '::' . $const;
            }
        }

        if (!defined($identifier)) {
            throw AnnotationException::semanticalErrorConstants($identifier, $this->context);
        }

        return constant($identifier);
    }

    /**
     * Identifier ::= string
     *
     * @return string
     */
    private function Identifier()
    {
        // check if we have an annotation
        if ($this->lexer->isNextTokenAny(self::$classIdentifiers)) {
            $this->lexer->moveNext();
            $className = $this->lexer->token['value'];
        } else {
            $this->syntaxError('namespace separator or identifier');
        }

        while ($this->lexer->lookahead['position'] === ($this->lexer->token['position'] + strlen($this->lexer->token['value']))
                && $this->lexer->isNextToken(DocLexer::T_NAMESPACE_SEPARATOR)) {

            $this->match(DocLexer::T_NAMESPACE_SEPARATOR);
            $this->matchAny(self::$classIdentifiers);
            $className .= '\\' . $this->lexer->token['value'];
        }

        return $className;
    }

    /**
     * Value ::= PlainValue | FieldAssignment
     *
     * @return mixed
     */
    private function Value()
    {
        $peek = $this->lexer->glimpse();

        if (DocLexer::T_EQUALS === $peek['type']) {
            return $this->FieldAssignment();
        }

        return $this->PlainValue();
    }

    /**
     * PlainValue ::= integer | string | float | boolean | Array | Annotation
     *
     * @return mixed
     */
    private function PlainValue()
    {
        if ($this->lexer->isNextToken(DocLexer::T_OPEN_CURLY_BRACES)) {
            return $this->Arrayx();
        }

        if ($this->lexer->isNextToken(DocLexer::T_AT)) {
            return $this->Annotation();
        }

        if ($this->lexer->isNextToken(DocLexer::T_IDENTIFIER)) {
            return $this->Constant();
        }

        switch ($this->lexer->lookahead['type']) {
            case DocLexer::T_STRING:
                $this->match(DocLexer::T_STRING);
                return $this->lexer->token['value'];

            case DocLexer::T_INTEGER:
                $this->match(DocLexer::T_INTEGER);
                return (int)$this->lexer->token['value'];

            case DocLexer::T_FLOAT:
                $this->match(DocLexer::T_FLOAT);
                return (float)$this->lexer->token['value'];

            case DocLexer::T_TRUE:
                $this->match(DocLexer::T_TRUE);
                return true;

            case DocLexer::T_FALSE:
                $this->match(DocLexer::T_FALSE);
                return false;

            case DocLexer::T_NULL:
                $this->match(DocLexer::T_NULL);
                return null;

            default:
                $this->syntaxError('PlainValue');
        }
    }

    /**
     * FieldAssignment ::= FieldName "=" PlainValue
     * FieldName ::= identifier
     *
     * @return array
     */
    private function FieldAssignment()
    {
        $this->match(DocLexer::T_IDENTIFIER);
        $fieldName = $this->lexer->token['value'];

        $this->match(DocLexer::T_EQUALS);

        $item = new \stdClass();
        $item->name  = $fieldName;
        $item->value = $this->PlainValue();

        return $item;
    }

    /**
     * Array ::= "{" ArrayEntry {"," ArrayEntry}* [","] "}"
     *
     * @return array
     */
    private function Arrayx()
    {
        $array = $values = array();

        $this->match(DocLexer::T_OPEN_CURLY_BRACES);

        // If the array is empty, stop parsing and return.
        if ($this->lexer->isNextToken(DocLexer::T_CLOSE_CURLY_BRACES)) {
            $this->match(DocLexer::T_CLOSE_CURLY_BRACES);

            return $array;
        }

        $values[] = $this->ArrayEntry();

        while ($this->lexer->isNextToken(DocLexer::T_COMMA)) {
            $this->match(DocLexer::T_COMMA);

            // optional trailing comma
            if ($this->lexer->isNextToken(DocLexer::T_CLOSE_CURLY_BRACES)) {
                break;
            }

            $values[] = $this->ArrayEntry();
        }

        $this->match(DocLexer::T_CLOSE_CURLY_BRACES);

        foreach ($values as $value) {
            list ($key, $val) = $value;

            if ($key !== null) {
                $array[$key] = $val;
            } else {
                $array[] = $val;
            }
        }

        return $array;
    }

    /**
     * ArrayEntry ::= Value | KeyValuePair
     * KeyValuePair ::= Key ("=" | ":") PlainValue | Constant
     * Key ::= string | integer | Constant
     *
     * @return array
     */
    private function ArrayEntry()
    {
        $peek = $this->lexer->glimpse();

        if (DocLexer::T_EQUALS === $peek['type']
                || DocLexer::T_COLON === $peek['type']) {

            if ($this->lexer->isNextToken(DocLexer::T_IDENTIFIER)) {
                $key = $this->Constant();
            } else {
                $this->matchAny(array(DocLexer::T_INTEGER, DocLexer::T_STRING));
                $key = $this->lexer->token['value'];
            }

            $this->matchAny(array(DocLexer::T_EQUALS, DocLexer::T_COLON));

            return array($key, $this->PlainValue());
        }

        return array(null, $this->Value());
    }
}
<?php

/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations\Annotation;

/**
 * Annotation that can be used to signal to the parser
 * to check the attribute type during the parsing process.
 *
 * @author Fabio B. Silva <fabio.bat.silva@gmail.com>
 *
 * @Annotation
 */
final class Attribute
{
    /**
     * @var string
     */
    public $name;

    /**
     * @var string
     */
    public $type;

    /**
     * @var boolean
     */
    public $required = false;
}
<?php

/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations\Annotation;

/**
 * Annotation that can be used to signal to the parser
 * to check if that attribute is required during the parsing process.
 *
 * @author Fabio B. Silva <fabio.bat.silva@gmail.com>
 *
 * @Annotation
 */
final class Required
{
}
<?php

/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations\Annotation;

/**
 * Annotation that can be used to signal to the parser
 * to check the available values during the parsing process.
 *
 * @since  2.4
 * @author Fabio B. Silva <fabio.bat.silva@gmail.com>
 *
 * @Annotation
 * @Attributes({
 *    @Attribute("value",   required = true,  type = "array"),
 *    @Attribute("literal", required = false, type = "array")
 * })
 */
final class Enum
{
    /**
     * @var array
     */
    public $value;

    /**
     * Literal target declaration.
     *
     * @var array
     */
    public $literal;

    /**
     * Annotation construct
     *
     * @param array $values
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(array $values)
    {
        if ( ! isset($values['literal'])) {
            $values['literal'] = array();
        }

        foreach ($values['value'] as $var) {
            if( ! is_scalar($var)) {
                throw new \InvalidArgumentException(sprintf(
                    '@Enum supports only scalar values "%s" given.',
                    is_object($var) ? get_class($var) : gettype($var)
                ));
            }
        }

        foreach ($values['literal'] as $key => $var) {
            if( ! in_array($key, $values['value'])) {
                throw new \InvalidArgumentException(sprintf(
                    'Undefined enumerator value "%s" for literal "%s".',
                    $key , $var
                ));
            }
        }

        $this->value    = $values['value'];
        $this->literal  = $values['literal'];
    }

}<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations\Annotation;

/**
 * Annotation that can be used to signal to the parser to ignore specific
 * annotations during the parsing process.
 *
 * @Annotation
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
final class IgnoreAnnotation
{
    /**
     * @var array
     */
    public $names;

    /**
     * Constructor
     *
     * @param array $values
     *
     * @throws \RuntimeException
     */
    public function __construct(array $values)
    {
        if (is_string($values['value'])) {
            $values['value'] = array($values['value']);
        }
        if (!is_array($values['value'])) {
            throw new \RuntimeException(sprintf('@IgnoreAnnotation expects either a string name, or an array of strings, but got %s.', json_encode($values['value'])));
        }

        $this->names = $values['value'];
    }
}
<?php

/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations\Annotation;

/**
 * Annotation that can be used to signal to the parser
 * to check the types of all declared attributes during the parsing process.
 *
 * @author Fabio B. Silva <fabio.bat.silva@gmail.com>
 *
 * @Annotation
 */
final class Attributes
{
    /**
     * @var array<Doctrine\Common\Annotations\Annotation\Attribute>
     */
    public $value;
}
<?php

/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations\Annotation;

/**
 * Annotation that can be used to signal to the parser
 * to check the annotation target during the parsing process.
 *
 * @author Fabio B. Silva <fabio.bat.silva@gmail.com>
 *
 * @Annotation
 */
final class Target
{
    const TARGET_CLASS              = 1;
    const TARGET_METHOD             = 2;
    const TARGET_PROPERTY           = 4;
    const TARGET_ANNOTATION         = 8;
    const TARGET_ALL                = 15;

    /**
     * @var array
     */
    private static $map = array(
        'ALL'         => self::TARGET_ALL,
        'CLASS'       => self::TARGET_CLASS,
        'METHOD'      => self::TARGET_METHOD,
        'PROPERTY'    => self::TARGET_PROPERTY,
        'ANNOTATION'  => self::TARGET_ANNOTATION,
    );

    /**
     * @var array
     */
    public $value;

    /**
     * Targets as bitmask.
     *
     * @var integer
     */
    public $targets;

    /**
     * Literal target declaration.
     *
     * @var integer
     */
    public $literal;

    /**
     * Annotation construct
     *
     * @param array $values
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(array $values)
    {
        if (!isset($values['value'])){
            $values['value'] = null;
        }
        if (is_string($values['value'])){
            $values['value'] = array($values['value']);
        }
        if (!is_array($values['value'])){
            throw new \InvalidArgumentException(
                sprintf('@Target expects either a string value, or an array of strings, "%s" given.',
                    is_object($values['value']) ? get_class($values['value']) : gettype($values['value'])
                )
            );
        }

        $bitmask = 0;
        foreach ($values['value'] as $literal) {
            if(!isset(self::$map[$literal])){
                throw new \InvalidArgumentException(
                    sprintf('Invalid Target "%s". Available targets: [%s]',
                            $literal,  implode(', ', array_keys(self::$map)))
                );
            }
            $bitmask += self::$map[$literal];
        }

        $this->targets  = $bitmask;
        $this->value    = $values['value'];
        $this->literal  = implode(', ', $this->value);
    }
}
<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations;

use Doctrine\Common\Annotations\Annotation\Target;

/**
 * Simple Annotation Reader.
 *
 * This annotation reader is intended to be used in projects where you have
 * full-control over all annotations that are available.
 *
 * @since  2.2
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Fabio B. Silva <fabio.bat.silva@gmail.com>
 */
class SimpleAnnotationReader implements Reader
{
    /**
     * @var DocParser
     */
    private $parser;

    /**
     * Constructor.
     *
     * Initializes a new SimpleAnnotationReader.
     */
    public function __construct()
    {
        $this->parser = new DocParser();
        $this->parser->setIgnoreNotImportedAnnotations(true);
    }

    /**
     * Adds a namespace in which we will look for annotations.
     *
     * @param string $namespace
     */
    public function addNamespace($namespace)
    {
        $this->parser->addNamespace($namespace);
    }

    /**
     * Gets the annotations applied to a class.
     *
     * @param \ReflectionClass $class The ReflectionClass of the class from which
     *                               the class annotations should be read.
     *
     * @return array An array of Annotations.
     */
    public function getClassAnnotations(\ReflectionClass $class)
    {
        return $this->parser->parse($class->getDocComment(), 'class '.$class->getName());
    }

    /**
     * Gets the annotations applied to a method.
     *
     * @param \ReflectionMethod $method The ReflectionMethod of the method from which
     *                                   the annotations should be read.
     *
     * @return array An array of Annotations.
     */
    public function getMethodAnnotations(\ReflectionMethod $method)
    {
        return $this->parser->parse($method->getDocComment(), 'method '.$method->getDeclaringClass()->name.'::'.$method->getName().'()');
    }

    /**
     * Gets the annotations applied to a property.
     *
     * @param \ReflectionProperty $property The ReflectionProperty of the property
     *                                     from which the annotations should be read.
     *
     * @return array An array of Annotations.
     */
    public function getPropertyAnnotations(\ReflectionProperty $property)
    {
        return $this->parser->parse($property->getDocComment(), 'property '.$property->getDeclaringClass()->name.'::$'.$property->getName());
    }

    /**
     * Gets a class annotation.
     *
     * @param \ReflectionClass $class The ReflectionClass of the class from which
     *                               the class annotations should be read.
     * @param string $annotationName The name of the annotation.
     *
     * @return mixed The Annotation or NULL, if the requested annotation does not exist.
     */
    public function getClassAnnotation(\ReflectionClass $class, $annotationName)
    {
        foreach ($this->getClassAnnotations($class) as $annot) {
            if ($annot instanceof $annotationName) {
                return $annot;
            }
        }

        return null;
    }

    /**
     * Gets a method annotation.
     *
     * @param \ReflectionMethod $method
     * @param string $annotationName The name of the annotation.
     *
     * @return mixed The Annotation or NULL, if the requested annotation does not exist.
     */
    public function getMethodAnnotation(\ReflectionMethod $method, $annotationName)
    {
        foreach ($this->getMethodAnnotations($method) as $annot) {
            if ($annot instanceof $annotationName) {
                return $annot;
            }
        }

        return null;
    }

    /**
     * Gets a property annotation.
     *
     * @param \ReflectionProperty $property
     * @param string $annotationName The name of the annotation.
     * @return mixed The Annotation or NULL, if the requested annotation does not exist.
     */
    public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName)
    {
        foreach ($this->getPropertyAnnotations($property) as $annot) {
            if ($annot instanceof $annotationName) {
                return $annot;
            }
        }

        return null;
    }
}
<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations;

/**
 * Annotations class
 *
 * @author  Benjamin Eberlei <kontakt@beberlei.de>
 * @author  Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author  Jonathan Wage <jonwage@gmail.com>
 * @author  Roman Borschel <roman@code-factory.org>
 */
class Annotation
{
    /**
     * Value property. Common among all derived classes.
     *
     * @var string
     */
    public $value;

    /**
     * Constructor
     *
     * @param array $data Key-value for properties to be defined in this class
     */
    public final function __construct(array $data)
    {
        foreach ($data as $key => $value) {
            $this->$key = $value;
        }
    }

    /**
     * Error handler for unknown property accessor in Annotation class.
     *
     * @param string $name Unknown property name
     *
     * @throws \BadMethodCallException
     */
    public function __get($name)
    {
        throw new \BadMethodCallException(
            sprintf("Unknown property '%s' on annotation '%s'.", $name, get_class($this))
        );
    }

    /**
     * Error handler for unknown property mutator in Annotation class.
     *
     * @param string $name Unkown property name
     * @param mixed $value Property value
     *
     * @throws \BadMethodCallException
     */
    public function __set($name, $value)
    {
        throw new \BadMethodCallException(
            sprintf("Unknown property '%s' on annotation '%s'.", $name, get_class($this))
        );
    }
}
<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations;

/**
 * Description of AnnotationException
 *
 * @since   2.0
 * @author  Benjamin Eberlei <kontakt@beberlei.de>
 * @author  Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author  Jonathan Wage <jonwage@gmail.com>
 * @author  Roman Borschel <roman@code-factory.org>
 */
class AnnotationException extends \Exception
{
    /**
     * Creates a new AnnotationException describing a Syntax error.
     *
     * @param string $message Exception message
     * @return AnnotationException
     */
    public static function syntaxError($message)
    {
        return new self('[Syntax Error] ' . $message);
    }

    /**
     * Creates a new AnnotationException describing a Semantical error.
     *
     * @param string $message Exception message
     * @return AnnotationException
     */
    public static function semanticalError($message)
    {
        return new self('[Semantical Error] ' . $message);
    }

    /**
     * Creates a new AnnotationException describing a constant semantical error.
     *
     * @since 2.3
     * @param string $identifier
     * @param string $context
     * @return AnnotationException
     */
    public static function semanticalErrorConstants($identifier, $context = null)
    {
        return self::semanticalError(sprintf(
            "Couldn't find constant %s%s", $identifier,
            $context ? ", $context." : "."
        ));
    }

    /**
     * Creates a new AnnotationException describing an error which occurred during
     * the creation of the annotation.
     *
     * @since 2.2
     * @param string $message
     * @return AnnotationException
     */
    public static function creationError($message)
    {
        return new self('[Creation Error] ' . $message);
    }

    /**
     * Creates a new AnnotationException describing an type error of an attribute.
     *
     * @since 2.2
     * @param string $attributeName
     * @param string $annotationName
     * @param string $context
     * @param string $expected
     * @param mixed $actual
     * @return AnnotationException
     */
    public static function typeError($attributeName, $annotationName, $context, $expected, $actual)
    {
        return new self(sprintf(
            '[Type Error] Attribute "%s" of @%s declared on %s expects %s, but got %s.',
            $attributeName,
            $annotationName,
            $context,
            $expected,
            is_object($actual) ? 'an instance of '.get_class($actual) : gettype($actual)
        ));
    }

    /**
     * Creates a new AnnotationException describing an required error of an attribute.
     *
     * @since 2.2
     * @param string $attributeName
     * @param string $annotationName
     * @param string $context
     * @param string $expected
     * @return AnnotationException
     */
    public static function requiredError($attributeName, $annotationName, $context, $expected)
    {
        return new self(sprintf(
            '[Type Error] Attribute "%s" of @%s declared on %s expects %s. This value should not be null.',
            $attributeName,
            $annotationName,
            $context,
            $expected
        ));
    }

    /**
     * Creates a new AnnotationException describing a invalid enummerator.
     *
     * @since 2.4
     * @param string $attributeName
     * @param string $annotationName
     * @param string $context
     * @param array  $available
     * @param mixed  $given
     * @return AnnotationException
     */
    public static function enumeratorError($attributeName, $annotationName, $context, $available, $given)
    {
        throw new self(sprintf(
            '[Enum Error] Attribute "%s" of @%s declared on %s accept only [%s], but got %s.',
            $attributeName, 
            $annotationName,
            $context,
            implode(', ', $available),
            is_object($given) ? get_class($given) : $given
        ));
    }

    /**
     * @return AnnotationException
     */
    public static function optimizerPlusSaveComments()
    {
        throw new self("You have to enable opcache.save_comments=1 or zend_optimizerplus.save_comments=1.");
    }
}
<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations;

use SplFileObject;

/**
 * Parses a file for namespaces/use/class declarations.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Christian Kaps <christian.kaps@mohiva.com>
 */
final class PhpParser
{
    /**
     * Parses a class.
     *
     * @param  \ReflectionClass $class A <code>ReflectionClass</code> object.
     * @return array            A list with use statements in the form (Alias => FQN).
     */
    public function parseClass(\ReflectionClass $class)
    {
        if (method_exists($class, 'getUseStatements')) {
            return $class->getUseStatements();
        }

        if (false === $filename = $class->getFilename()) {
            return array();
        }

        $content = $this->getFileContent($filename, $class->getStartLine());

        if (null === $content) {
            return array();
        }

        $namespace = preg_quote($class->getNamespaceName());
        $content = preg_replace('/^.*?(\bnamespace\s+' . $namespace . '\s*[;{].*)$/s', '\\1', $content);
        $tokenizer = new TokenParser('<?php ' . $content);

        $statements = $tokenizer->parseUseStatements($class->getNamespaceName());

        return $statements;
    }

    /**
     * Get the content of the file right up to the given line number.
     *
     * @param  string $filename   The name of the file to load.
     * @param  int    $lineNumber The number of lines to read from file.
     * @return string The content of the file.
     */
    private function getFileContent($filename, $lineNumber)
    {
        if ( ! is_file($filename)) {
            return null;
        }

        $content = '';
        $lineCnt = 0;
        $file = new SplFileObject($filename);
        while (!$file->eof()) {
            if ($lineCnt++ == $lineNumber) {
                break;
            }

            $content .= $file->fgets();
        }

        return $content;
    }
}
<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations;

use Doctrine\Common\Annotations\Reader;

/**
 * Allows the reader to be used in-place of Doctrine's reader.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class IndexedReader implements Reader
{
    /**
     * @var Reader
     */
    private $delegate;

    /**
     * Constructor
     *
     * @param Reader $reader
     */
    public function __construct(Reader $reader)
    {
        $this->delegate = $reader;
    }

    /**
     * Get Annotations for class
     *
     * @param \ReflectionClass $class
     * @return array
     */
    public function getClassAnnotations(\ReflectionClass $class)
    {
        $annotations = array();
        foreach ($this->delegate->getClassAnnotations($class) as $annot) {
            $annotations[get_class($annot)] = $annot;
        }

        return $annotations;
    }

    /**
     * Get selected annotation for class
     *
     * @param \ReflectionClass $class
     * @param string $annotation
     * @return mixed
     */
    public function getClassAnnotation(\ReflectionClass $class, $annotation)
    {
        return $this->delegate->getClassAnnotation($class, $annotation);
    }

    /**
     * Get Annotations for method
     *
     * @param \ReflectionMethod $method
     * @return array
     */
    public function getMethodAnnotations(\ReflectionMethod $method)
    {
        $annotations = array();
        foreach ($this->delegate->getMethodAnnotations($method) as $annot) {
            $annotations[get_class($annot)] = $annot;
        }

        return $annotations;
    }

    /**
     * Get selected annotation for method
     *
     * @param \ReflectionMethod $method
     * @param string $annotation
     * @return mixed
     */
    public function getMethodAnnotation(\ReflectionMethod $method, $annotation)
    {
        return $this->delegate->getMethodAnnotation($method, $annotation);
    }

    /**
     * Get annotations for property
     *
     * @param \ReflectionProperty $property
     * @return array
     */
    public function getPropertyAnnotations(\ReflectionProperty $property)
    {
        $annotations = array();
        foreach ($this->delegate->getPropertyAnnotations($property) as $annot) {
            $annotations[get_class($annot)] = $annot;
        }

        return $annotations;
    }

    /**
     * Get selected annotation for property
     *
     * @param \ReflectionProperty $property
     * @param string $annotation
     * @return mixed
     */
    public function getPropertyAnnotation(\ReflectionProperty $property, $annotation)
    {
        return $this->delegate->getPropertyAnnotation($property, $annotation);
    }

    /**
     * Proxy all methods to the delegate.
     *
     * @param string $method
     * @param array $args
     * @return mixed
     */
    public function __call($method, $args)
    {
        return call_user_func_array(array($this->delegate, $method), $args);
    }
}
<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations;

use Doctrine\Common\Annotations\Annotation\IgnoreAnnotation;
use Doctrine\Common\Annotations\Annotation\Target;
use Closure;
use ReflectionClass;
use ReflectionMethod;
use ReflectionProperty;

/**
 * A reader for docblock annotations.
 *
 * @author  Benjamin Eberlei <kontakt@beberlei.de>
 * @author  Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author  Jonathan Wage <jonwage@gmail.com>
 * @author  Roman Borschel <roman@code-factory.org>
 * @author  Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class AnnotationReader implements Reader
{
    /**
     * Global map for imports.
     *
     * @var array
     */
    private static $globalImports = array(
        'ignoreannotation' => 'Doctrine\Common\Annotations\Annotation\IgnoreAnnotation',
    );

    /**
     * A list with annotations that are not causing exceptions when not resolved to an annotation class.
     *
     * The names are case sensitive.
     *
     * @var array
     */
    private static $globalIgnoredNames = array(
        'access'=> true, 'author'=> true, 'copyright'=> true, 'deprecated'=> true,
        'example'=> true, 'ignore'=> true, 'internal'=> true, 'link'=> true, 'see'=> true,
        'since'=> true, 'tutorial'=> true, 'version'=> true, 'package'=> true,
        'subpackage'=> true, 'name'=> true, 'global'=> true, 'param'=> true,
        'return'=> true, 'staticvar'=> true, 'category'=> true, 'staticVar'=> true,
        'static'=> true, 'var'=> true, 'throws'=> true, 'inheritdoc'=> true,
        'inheritDoc'=> true, 'license'=> true, 'todo'=> true, 'TODO'=> true,
        'deprec'=> true, 'property' => true, 'method' => true,
        'abstract'=> true, 'exception'=> true, 'magic' => true, 'api' => true,
        'final'=> true, 'filesource'=> true, 'throw' => true, 'uses' => true,
        'usedby'=> true, 'private' => true, 'Annotation' => true, 'override' => true,
        'codeCoverageIgnore' => true, 'codeCoverageIgnoreStart' => true, 'codeCoverageIgnoreEnd' => true,
        'Required' => true, 'Attribute' => true, 'Attributes' => true,
        'Target' => true, 'SuppressWarnings' => true,
        'ingroup' => true, 'code' => true, 'endcode' => true,
        'package_version' => true, 'fixme' => true
    );

    /**
     * Add a new annotation to the globally ignored annotation names with regard to exception handling.
     *
     * @param string $name
     */
    static public function addGlobalIgnoredName($name)
    {
        self::$globalIgnoredNames[$name] = true;
    }

    /**
     * Annotations Parser
     *
     * @var \Doctrine\Common\Annotations\DocParser
     */
    private $parser;

    /**
     * Annotations Parser used to collect parsing metadata
     *
     * @var \Doctrine\Common\Annotations\DocParser
     */
    private $preParser;

    /**
     * PHP Parser used to collect imports.
     *
     * @var \Doctrine\Common\Annotations\PhpParser
     */
    private $phpParser;

    /**
     * In-memory cache mechanism to store imported annotations per class.
     *
     * @var array
     */
    private $imports = array();

    /**
     * In-memory cache mechanism to store ignored annotations per class.
     *
     * @var array
     */
    private $ignoredAnnotationNames = array();

    /**
     * Constructor.
     *
     * Initializes a new AnnotationReader.
     */
    public function __construct()
    {
        if (extension_loaded('Zend Optimizer+') && (ini_get('zend_optimizerplus.save_comments') === "0" || ini_get('opcache.save_comments') === "0")) {
            throw AnnotationException::optimizerPlusSaveComments();
        }

        if (extension_loaded('opcache') && ini_get('opcache.save_comments') == 0) {
            throw AnnotationException::optimizerPlusSaveComments();
        }

        AnnotationRegistry::registerFile(__DIR__ . '/Annotation/IgnoreAnnotation.php');

        $this->parser = new DocParser;

        $this->preParser = new DocParser;
        $this->preParser->setImports(self::$globalImports);
        $this->preParser->setIgnoreNotImportedAnnotations(true);

        $this->phpParser = new PhpParser;
    }

    /**
     * Gets the annotations applied to a class.
     *
     * @param ReflectionClass $class The ReflectionClass of the class from which
     *                               the class annotations should be read.
     * @return array An array of Annotations.
     */
    public function getClassAnnotations(ReflectionClass $class)
    {
        $this->parser->setTarget(Target::TARGET_CLASS);
        $this->parser->setImports($this->getImports($class));
        $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class));

        return $this->parser->parse($class->getDocComment(), 'class ' . $class->getName());
    }

    /**
     * Gets a class annotation.
     *
     * @param ReflectionClass $class The ReflectionClass of the class from which
     *                               the class annotations should be read.
     * @param string $annotationName The name of the annotation.
     * @return mixed The Annotation or NULL, if the requested annotation does not exist.
     */
    public function getClassAnnotation(ReflectionClass $class, $annotationName)
    {
        $annotations = $this->getClassAnnotations($class);

        foreach ($annotations as $annotation) {
            if ($annotation instanceof $annotationName) {
                return $annotation;
            }
        }

        return null;
    }

    /**
     * Gets the annotations applied to a property.
     *
     * @param ReflectionProperty $property The ReflectionProperty of the property
     *                                     from which the annotations should be read.
     * @return array An array of Annotations.
     */
    public function getPropertyAnnotations(ReflectionProperty $property)
    {
        $class = $property->getDeclaringClass();
        $context = 'property ' . $class->getName() . "::\$" . $property->getName();
        $this->parser->setTarget(Target::TARGET_PROPERTY);
        $this->parser->setImports($this->getImports($class));
        $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class));

        return $this->parser->parse($property->getDocComment(), $context);
    }

    /**
     * Gets a property annotation.
     *
     * @param ReflectionProperty $property
     * @param string $annotationName The name of the annotation.
     * @return mixed The Annotation or NULL, if the requested annotation does not exist.
     */
    public function getPropertyAnnotation(ReflectionProperty $property, $annotationName)
    {
        $annotations = $this->getPropertyAnnotations($property);

        foreach ($annotations as $annotation) {
            if ($annotation instanceof $annotationName) {
                return $annotation;
            }
        }

        return null;
    }

    /**
     * Gets the annotations applied to a method.
     *
     * @param \ReflectionMethod $method The ReflectionMethod of the method from which
     *                                   the annotations should be read.
     *
     * @return array An array of Annotations.
     */
    public function getMethodAnnotations(ReflectionMethod $method)
    {
        $class = $method->getDeclaringClass();
        $context = 'method ' . $class->getName() . '::' . $method->getName() . '()';
        $this->parser->setTarget(Target::TARGET_METHOD);
        $this->parser->setImports($this->getImports($class));
        $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class));

        return $this->parser->parse($method->getDocComment(), $context);
    }

    /**
     * Gets a method annotation.
     *
     * @param ReflectionMethod $method
     * @param string $annotationName The name of the annotation.
     * @return mixed The Annotation or NULL, if the requested annotation does not exist.
     */
    public function getMethodAnnotation(ReflectionMethod $method, $annotationName)
    {
        $annotations = $this->getMethodAnnotations($method);

        foreach ($annotations as $annotation) {
            if ($annotation instanceof $annotationName) {
                return $annotation;
            }
        }

        return null;
    }

    /**
     * Returns the ignored annotations for the given class.
     *
     * @param ReflectionClass $class
     * @return array
     */
    private function getIgnoredAnnotationNames(ReflectionClass $class)
    {
        if (isset($this->ignoredAnnotationNames[$name = $class->getName()])) {
            return $this->ignoredAnnotationNames[$name];
        }
        $this->collectParsingMetadata($class);

        return $this->ignoredAnnotationNames[$name];
    }

    /**
     * Retrieve imports
     *
     * @param \ReflectionClass $class
     * @return array
     */
    private function getImports(ReflectionClass $class)
    {
        if (isset($this->imports[$name = $class->getName()])) {
            return $this->imports[$name];
        }
        $this->collectParsingMetadata($class);

        return $this->imports[$name];
    }

    /**
     * Collects parsing metadata for a given class
     *
     * @param ReflectionClass $class
     */
    private function collectParsingMetadata(ReflectionClass $class)
    {
        $ignoredAnnotationNames = self::$globalIgnoredNames;

        $annotations = $this->preParser->parse($class->getDocComment(), 'class '.$class->name);
        foreach ($annotations as $annotation) {
            if ($annotation instanceof IgnoreAnnotation) {
                foreach ($annotation->names AS $annot) {
                    $ignoredAnnotationNames[$annot] = true;
                }
            }
        }

        $name = $class->getName();
        $this->imports[$name] = array_merge(
            self::$globalImports,
            $this->phpParser->parseClass($class),
            array('__NAMESPACE__' => $class->getNamespaceName())
        );
        $this->ignoredAnnotationNames[$name] = $ignoredAnnotationNames;
    }
}
<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations;

/**
 * Parses a file for namespaces/use/class declarations.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Christian Kaps <christian.kaps@mohiva.com>
 */
class TokenParser
{
    /**
     * The token list.
     *
     * @var array
     */
    private $tokens;

    /**
     * The number of tokens.
     *
     * @var int
     */
    private $numTokens = 0;

    /**
     * The current array pointer.
     *
     * @var int
     */
    private $pointer = 0;

    public function __construct($contents)
    {
        $this->tokens = token_get_all($contents);
        $this->numTokens = count($this->tokens);
        $this->pointer = 0;
    }

    /**
     * Gets the next non whitespace and non comment token.
     *
     * @param $docCommentIsComment
     *     If TRUE then a doc comment is considered a comment and skipped.
     *     If FALSE then only whitespace and normal comments are skipped.
     *
     * @return array The token if exists, null otherwise.
     */
    public function next($docCommentIsComment = TRUE)
    {
        for ($i = $this->pointer; $i < $this->numTokens; $i++) {
            $this->pointer++;
            if ($this->tokens[$i][0] === T_WHITESPACE ||
                $this->tokens[$i][0] === T_COMMENT ||
                ($docCommentIsComment && $this->tokens[$i][0] === T_DOC_COMMENT)) {

                continue;
            }

            return $this->tokens[$i];
        }

        return null;
    }

    /**
     * Parse a single use statement.
     *
     * @return array A list with all found class names for a use statement.
     */
    public function parseUseStatement()
    {
        $class = '';
        $alias = '';
        $statements = array();
        $explicitAlias = false;
        while (($token = $this->next())) {
            $isNameToken = $token[0] === T_STRING || $token[0] === T_NS_SEPARATOR;
            if (!$explicitAlias && $isNameToken) {
                $class .= $token[1];
                $alias = $token[1];
            } else if ($explicitAlias && $isNameToken) {
                $alias .= $token[1];
            } else if ($token[0] === T_AS) {
                $explicitAlias = true;
                $alias = '';
            } else if ($token === ',') {
                $statements[strtolower($alias)] = $class;
                $class = '';
                $alias = '';
                $explicitAlias = false;
            } else if ($token === ';') {
                $statements[strtolower($alias)] = $class;
                break;
            } else {
                break;
            }
        }

        return $statements;
    }

    /**
     * Get all use statements.
     *
     * @param string $namespaceName The namespace name of the reflected class.
     * @return array A list with all found use statements.
     */
    public function parseUseStatements($namespaceName)
    {
        $statements = array();
        while (($token = $this->next())) {
            if ($token[0] === T_USE) {
                $statements = array_merge($statements, $this->parseUseStatement());
                continue;
            }
            if ($token[0] !== T_NAMESPACE || $this->parseNamespace() != $namespaceName) {
                continue;
            }

            // Get fresh array for new namespace. This is to prevent the parser to collect the use statements
            // for a previous namespace with the same name. This is the case if a namespace is defined twice
            // or if a namespace with the same name is commented out.
            $statements = array();
        }

        return $statements;
    }

    /**
     * Get the namespace.
     *
     * @return string The found namespace.
     */
    public function parseNamespace()
    {
        $name = '';
        while (($token = $this->next()) && ($token[0] === T_STRING || $token[0] === T_NS_SEPARATOR)) {
            $name .= $token[1];
        }

        return $name;
    }

    /**
     * Get the class name.
     *
     * @return string The foundclass name.
     */
    public function parseClass()
    {
        // Namespaces and class names are tokenized the same: T_STRINGs
        // separated by T_NS_SEPARATOR so we can use one function to provide
        // both.
        return $this->parseNamespace();
    }
}
<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations;

/**
 * AnnotationRegistry
 */
final class AnnotationRegistry
{
    /**
     * A map of namespaces to use for autoloading purposes based on a PSR-0 convention.
     *
     * Contains the namespace as key and an array of directories as value. If the value is NULL
     * the include path is used for checking for the corresponding file.
     *
     * This autoloading mechanism does not utilize the PHP autoloading but implements autoloading on its own.
     *
     * @var array
     */
    static private $autoloadNamespaces = array();

    /**
     * A map of autoloader callables.
     *
     * @var array
     */
    static private $loaders = array();

    static public function reset()
    {
        self::$autoloadNamespaces = array();
        self::$loaders = array();
    }

    /**
     * Register file
     *
     * @param string $file
     */
    static public function registerFile($file)
    {
        require_once $file;
    }

    /**
     * Add a namespace with one or many directories to look for files or null for the include path.
     *
     * Loading of this namespaces will be done with a PSR-0 namespace loading algorithm.
     *
     * @param string $namespace
     * @param string|array|null $dirs
     */
    static public function registerAutoloadNamespace($namespace, $dirs = null)
    {
        self::$autoloadNamespaces[$namespace] = $dirs;
    }

    /**
     * Register multiple namespaces
     *
     * Loading of this namespaces will be done with a PSR-0 namespace loading algorithm.
     *
     * @param array $namespaces
     */
    static public function registerAutoloadNamespaces(array $namespaces)
    {
        self::$autoloadNamespaces = array_merge(self::$autoloadNamespaces, $namespaces);
    }

    /**
     * Register an autoloading callable for annotations, much like spl_autoload_register().
     *
     * NOTE: These class loaders HAVE to be silent when a class was not found!
     * IMPORTANT: Loaders have to return true if they loaded a class that could contain the searched annotation class.
     *
     * @param callable $callable
     *
     * @throws \InvalidArgumentException
     */
    static public function registerLoader($callable)
    {
        if (!is_callable($callable)) {
            throw new \InvalidArgumentException("A callable is expected in AnnotationRegistry::registerLoader().");
        }
        self::$loaders[] = $callable;
    }

    /**
     * Autoload an annotation class silently.
     *
     * @param string $class
     * @return boolean
     */
    static public function loadAnnotationClass($class)
    {
        foreach (self::$autoloadNamespaces AS $namespace => $dirs) {
            if (strpos($class, $namespace) === 0) {
                $file = str_replace("\\", DIRECTORY_SEPARATOR, $class) . ".php";
                if ($dirs === null) {
                    if ($path = stream_resolve_include_path($file)) {
                        require $path;
                        return true;
                    }
                } else {
                    foreach((array)$dirs AS $dir) {
                        if (is_file($dir . DIRECTORY_SEPARATOR . $file)) {
                            require $dir . DIRECTORY_SEPARATOR . $file;
                            return true;
                        }
                    }
                }
            }
        }

        foreach (self::$loaders AS $loader) {
            if (call_user_func($loader, $class) === true) {
                return true;
            }
        }
        return false;
    }
}
<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations;

use Doctrine\Common\Cache\Cache;

/**
 * A cache aware annotation reader.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 */
final class CachedReader implements Reader
{
    /**
     * @var string
     */
    private static $CACHE_SALT = '@[Annot]';

    /**
     * @var Reader
     */
    private $delegate;

    /**
     * @var Cache
     */
    private $cache;

    /**
     * @var boolean
     */
    private $debug;

    /**
     * @var array
     */
    private $loadedAnnotations;

    /**
     * Constructor
     *
     * @param Reader $reader
     * @param Cache $cache
     * @param bool $debug
     */
    public function __construct(Reader $reader, Cache $cache, $debug = false)
    {
        $this->delegate = $reader;
        $this->cache = $cache;
        $this->debug = (Boolean) $debug;
    }

    /**
     * Get annotations for class
     *
     * @param \ReflectionClass $class
     * @return array
     */
    public function getClassAnnotations(\ReflectionClass $class)
    {
        $cacheKey = $class->getName();

        if (isset($this->loadedAnnotations[$cacheKey])) {
            return $this->loadedAnnotations[$cacheKey];
        }

        if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) {
            $annots = $this->delegate->getClassAnnotations($class);
            $this->saveToCache($cacheKey, $annots);
        }

        return $this->loadedAnnotations[$cacheKey] = $annots;
    }

    /**
     * Get selected annotation for class
     *
     * @param \ReflectionClass $class
     * @param string $annotationName
     * @return null
     */
    public function getClassAnnotation(\ReflectionClass $class, $annotationName)
    {
        foreach ($this->getClassAnnotations($class) as $annot) {
            if ($annot instanceof $annotationName) {
                return $annot;
            }
        }

        return null;
    }

    /**
     * Get annotations for property
     *
     * @param \ReflectionProperty $property
     * @return array
     */
    public function getPropertyAnnotations(\ReflectionProperty $property)
    {
        $class = $property->getDeclaringClass();
        $cacheKey = $class->getName().'$'.$property->getName();

        if (isset($this->loadedAnnotations[$cacheKey])) {
            return $this->loadedAnnotations[$cacheKey];
        }

        if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) {
            $annots = $this->delegate->getPropertyAnnotations($property);
            $this->saveToCache($cacheKey, $annots);
        }

        return $this->loadedAnnotations[$cacheKey] = $annots;
    }

    /**
     * Get selected annotation for property
     *
     * @param \ReflectionProperty $property
     * @param string $annotationName
     * @return null
     */
    public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName)
    {
        foreach ($this->getPropertyAnnotations($property) as $annot) {
            if ($annot instanceof $annotationName) {
                return $annot;
            }
        }

        return null;
    }

    /**
     * Get method annotations
     *
     * @param \ReflectionMethod $method
     * @return array
     */
    public function getMethodAnnotations(\ReflectionMethod $method)
    {
        $class = $method->getDeclaringClass();
        $cacheKey = $class->getName().'#'.$method->getName();

        if (isset($this->loadedAnnotations[$cacheKey])) {
            return $this->loadedAnnotations[$cacheKey];
        }

        if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) {
            $annots = $this->delegate->getMethodAnnotations($method);
            $this->saveToCache($cacheKey, $annots);
        }

        return $this->loadedAnnotations[$cacheKey] = $annots;
    }

    /**
     * Get selected method annotation
     *
     * @param \ReflectionMethod $method
     * @param string $annotationName
     * @return null
     */
    public function getMethodAnnotation(\ReflectionMethod $method, $annotationName)
    {
        foreach ($this->getMethodAnnotations($method) as $annot) {
            if ($annot instanceof $annotationName) {
                return $annot;
            }
        }

        return null;
    }

    /**
     * Clear loaded annotations
     */
    public function clearLoadedAnnotations()
    {
        $this->loadedAnnotations = array();
    }

    /**
     * Fetches a value from the cache.
     *
     * @param string           $rawCacheKey The cache key.
     * @param \ReflectionClass $class       The related class.
     * @return mixed|boolean The cached value or false when the value is not in cache.
     */
    private function fetchFromCache($rawCacheKey, \ReflectionClass $class)
    {
        $cacheKey = $rawCacheKey . self::$CACHE_SALT;
        if (($data = $this->cache->fetch($cacheKey)) !== false) {
            if (!$this->debug || $this->isCacheFresh($cacheKey, $class)) {
                return $data;
            }
        }

        return false;
    }

    /**
     * Saves a value to the cache
     *
     * @param string $rawCacheKey The cache key.
     * @param mixed  $value       The value.
     */
    private function saveToCache($rawCacheKey, $value)
    {
        $cacheKey = $rawCacheKey . self::$CACHE_SALT;
        $this->cache->save($cacheKey, $value);
        if ($this->debug) {
            $this->cache->save('[C]'.$cacheKey, time());
        }
    }

    /**
     * Check if cache is fresh
     *
     * @param string $cacheKey
     * @param \ReflectionClass $class
     * @return bool
     */
    private function isCacheFresh($cacheKey, \ReflectionClass $class)
    {
        if (false === $filename = $class->getFilename()) {
            return true;
        }

        return $this->cache->fetch('[C]'.$cacheKey) >= filemtime($filename);
    }
}
<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations;

use Doctrine\Common\Lexer\AbstractLexer;

/**
 * Simple lexer for docblock annotations.
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author Jonathan Wage <jonwage@gmail.com>
 * @author Roman Borschel <roman@code-factory.org>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
final class DocLexer extends AbstractLexer
{
    const T_NONE                = 1;
    const T_INTEGER             = 2;
    const T_STRING              = 3;
    const T_FLOAT               = 4;

    // All tokens that are also identifiers should be >= 100
    const T_IDENTIFIER          = 100;
    const T_AT                  = 101;
    const T_CLOSE_CURLY_BRACES  = 102;
    const T_CLOSE_PARENTHESIS   = 103;
    const T_COMMA               = 104;
    const T_EQUALS              = 105;
    const T_FALSE               = 106;
    const T_NAMESPACE_SEPARATOR = 107;
    const T_OPEN_CURLY_BRACES   = 108;
    const T_OPEN_PARENTHESIS    = 109;
    const T_TRUE                = 110;
    const T_NULL                = 111;
    const T_COLON               = 112;

    protected $noCase = array(
        '@'  => self::T_AT,
        ','  => self::T_COMMA,
        '('  => self::T_OPEN_PARENTHESIS,
        ')'  => self::T_CLOSE_PARENTHESIS,
        '{'  => self::T_OPEN_CURLY_BRACES,
        '}'  => self::T_CLOSE_CURLY_BRACES,
        '='  => self::T_EQUALS,
        ':'  => self::T_COLON,
        '\\' => self::T_NAMESPACE_SEPARATOR
    );

    protected $withCase = array(
        'true'  => self::T_TRUE,
        'false' => self::T_FALSE,
        'null'  => self::T_NULL
    );

    /**
     * {@inheritdoc}
     */
    protected function getCatchablePatterns()
    {
        return array(
            '[a-z_\\\][a-z0-9_\:\\\]*[a-z]{1}',
            '(?:[+-]?[0-9]+(?:[\.][0-9]+)*)(?:[eE][+-]?[0-9]+)?',
            '"(?:[^"]|"")*"',
        );
    }

    /**
     * {@inheritdoc}
     */
    protected function getNonCatchablePatterns()
    {
        return array('\s+', '\*+', '(.)');
    }

    /**
     * {@inheritdoc}
     *
     * @param string $value
     *
     * @return int
     */
    protected function getType(&$value)
    {
        $type = self::T_NONE;

        if ($value[0] === '"') {
            $value = str_replace('""', '"', substr($value, 1, strlen($value) - 2));

            return self::T_STRING;
        }

        if (isset($this->noCase[$value])) {
            return $this->noCase[$value];
        }

        if ($value[0] === '_' || $value[0] === '\\' || ctype_alpha($value[0])) {
            return self::T_IDENTIFIER;
        }

        $lowerValue = strtolower($value);

        if (isset($this->withCase[$lowerValue])) {
            return $this->withCase[$lowerValue];
        }

        // Checking numeric value
        if (is_numeric($value)) {
            return (strpos($value, '.') !== false || stripos($value, 'e') !== false)
                ? self::T_FLOAT : self::T_INTEGER;
        }

        return $type;
    }
}
{
    "name": "doctrine/lexer",
    "type": "library",
    "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.",
    "keywords": ["lexer", "parser"],
    "homepage": "http://www.doctrine-project.org",
    "license": "MIT",
    "authors": [
        {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"},
        {"name": "Roman Borschel", "email": "roman@code-factory.org"},
        {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"}
    ],
    "require": {
        "php": ">=5.3.2"
    },
    "autoload": {
        "psr-0": { "Doctrine\\Common\\Lexer\\": "lib/" }
    }
}
<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Lexer;

/**
 * Base class for writing simple lexers, i.e. for creating small DSLs.
 *
 * @since   2.0
 * @author  Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author  Jonathan Wage <jonwage@gmail.com>
 * @author  Roman Borschel <roman@code-factory.org>
 */
abstract class AbstractLexer
{
    /**
     * @var array Array of scanned tokens
     */
    private $tokens = array();

    /**
     * @var integer Current lexer position in input string
     */
    private $position = 0;

    /**
     * @var integer Current peek of current lexer position
     */
    private $peek = 0;

    /**
     * @var array The next token in the input.
     */
    public $lookahead;

    /**
     * @var array The last matched/seen token.
     */
    public $token;

    /**
     * Sets the input data to be tokenized.
     *
     * The Lexer is immediately reset and the new input tokenized.
     * Any unprocessed tokens from any previous input are lost.
     *
     * @param string $input The input to be tokenized.
     */
    public function setInput($input)
    {
        $this->tokens = array();
        $this->reset();
        $this->scan($input);
    }

    /**
     * Resets the lexer.
     */
    public function reset()
    {
        $this->lookahead = null;
        $this->token = null;
        $this->peek = 0;
        $this->position = 0;
    }

    /**
     * Resets the peek pointer to 0.
     */
    public function resetPeek()
    {
        $this->peek = 0;
    }

    /**
     * Resets the lexer position on the input to the given position.
     *
     * @param integer $position Position to place the lexical scanner
     */
    public function resetPosition($position = 0)
    {
        $this->position = $position;
    }

    /**
     * Checks whether a given token matches the current lookahead.
     *
     * @param integer|string $token
     * @return boolean
     */
    public function isNextToken($token)
    {
        return null !== $this->lookahead && $this->lookahead['type'] === $token;
    }

    /**
     * Checks whether any of the given tokens matches the current lookahead
     *
     * @param array $tokens
     * @return boolean
     */
    public function isNextTokenAny(array $tokens)
    {
        return null !== $this->lookahead && in_array($this->lookahead['type'], $tokens, true);
    }

    /**
     * Moves to the next token in the input string.
     *
     * A token is an associative array containing three items:
     *  - 'value'    : the string value of the token in the input string
     *  - 'type'     : the type of the token (identifier, numeric, string, input
     *                 parameter, none)
     *  - 'position' : the position of the token in the input string
     *
     * @return array|null the next token; null if there is no more tokens left
     */
    public function moveNext()
    {
        $this->peek = 0;
        $this->token = $this->lookahead;
        $this->lookahead = (isset($this->tokens[$this->position]))
            ? $this->tokens[$this->position++] : null;

        return $this->lookahead !== null;
    }

    /**
     * Tells the lexer to skip input tokens until it sees a token with the given value.
     *
     * @param string $type The token type to skip until.
     */
    public function skipUntil($type)
    {
        while ($this->lookahead !== null && $this->lookahead['type'] !== $type) {
            $this->moveNext();
        }
    }

    /**
     * Checks if given value is identical to the given token
     *
     * @param mixed $value
     * @param integer $token
     * @return boolean
     */
    public function isA($value, $token)
    {
        return $this->getType($value) === $token;
    }

    /**
     * Moves the lookahead token forward.
     *
     * @return array | null The next token or NULL if there are no more tokens ahead.
     */
    public function peek()
    {
        if (isset($this->tokens[$this->position + $this->peek])) {
            return $this->tokens[$this->position + $this->peek++];
        } else {
            return null;
        }
    }

    /**
     * Peeks at the next token, returns it and immediately resets the peek.
     *
     * @return array|null The next token or NULL if there are no more tokens ahead.
     */
    public function glimpse()
    {
        $peek = $this->peek();
        $this->peek = 0;
        return $peek;
    }

    /**
     * Scans the input string for tokens.
     *
     * @param string $input a query string
     */
    protected function scan($input)
    {
        static $regex;

        if ( ! isset($regex)) {
            $regex = '/(' . implode(')|(', $this->getCatchablePatterns()) . ')|'
                   . implode('|', $this->getNonCatchablePatterns()) . '/i';
        }

        $flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE;
        $matches = preg_split($regex, $input, -1, $flags);

        foreach ($matches as $match) {
            // Must remain before 'value' assignment since it can change content
            $type = $this->getType($match[0]);

            $this->tokens[] = array(
                'value' => $match[0],
                'type'  => $type,
                'position' => $match[1],
            );
        }
    }

    /**
     * Gets the literal for a given token.
     *
     * @param integer $token
     * @return string
     */
    public function getLiteral($token)
    {
        $className = get_class($this);
        $reflClass = new \ReflectionClass($className);
        $constants = $reflClass->getConstants();

        foreach ($constants as $name => $value) {
            if ($value === $token) {
                return $className . '::' . $name;
            }
        }

        return $token;
    }

    /**
     * Lexical catchable patterns.
     *
     * @return array
     */
    abstract protected function getCatchablePatterns();

    /**
     * Lexical non-catchable patterns.
     *
     * @return array
     */
    abstract protected function getNonCatchablePatterns();

    /**
     * Retrieve token type. Also processes the token value if necessary.
     *
     * @param string $value
     * @return integer
     */
    abstract protected function getType(&$value);
}
{
    "name": "mikey179/vfsStream",
    "type": "library",
    "homepage": "http://vfs.bovigo.org/",
    "license": "BSD",
    "require": {
        "php": ">=5.3.0"
    },
    "autoload": {
        "psr-0": { "org\\bovigo\\vfs\\": "src/main/php" }
    }
}<?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Base stream contents container.
 */
abstract class vfsStreamAbstractContent implements vfsStreamContent
{
    /**
     * name of the container
     *
     * @type  string
     */
    protected $name;
    /**
     * type of the container
     *
     * @type  string
     */
    protected $type;
    /**
     * timestamp of last access
     *
     * @type  int
     */
    protected $lastAccessed;
    /**
     * timestamp of last attribute modification
     *
     * @type  int
     */
    protected $lastAttributeModified;
    /**
     * timestamp of last modification
     *
     * @type  int
     */
    protected $lastModified;
    /**
     * permissions for content
     *
     * @type  int
     */
    protected $permissions;
    /**
     * owner of the file
     *
     * @type  int
     */
    protected $user;
    /**
     * owner group of the file
     *
     * @type  int
     */
    protected $group;
    /**
     * path to to this content
     *
     * @type  string
     */
    private $parentPath;

    /**
     * constructor
     *
     * @param  string  $name
     * @param  int     $permissions  optional
     */
    public function __construct($name, $permissions = null)
    {
        $this->name = $name;
        $time       = time();
        if (null === $permissions) {
            $permissions = $this->getDefaultPermissions() & ~vfsStream::umask();
        }

        $this->lastAccessed          = $time;
        $this->lastAttributeModified = $time;
        $this->lastModified          = $time;
        $this->permissions           = $permissions;
        $this->user                  = vfsStream::getCurrentUser();
        $this->group                 = vfsStream::getCurrentGroup();
    }

    /**
     * returns default permissions for concrete implementation
     *
     * @return  int
     * @since   0.8.0
     */
    protected abstract function getDefaultPermissions();

    /**
     * returns the file name of the content
     *
     * @return  string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * renames the content
     *
     * @param  string  $newName
     */
    public function rename($newName)
    {
        $this->name = $newName;
    }

    /**
     * checks whether the container can be applied to given name
     *
     * @param   string  $name
     * @return  bool
     */
    public function appliesTo($name)
    {
        if ($name === $this->name) {
            return true;
        }

        $segment_name = $this->name.'/';
        return (strncmp($segment_name, $name, strlen($segment_name)) == 0);
    }

    /**
     * returns the type of the container
     *
     * @return  int
     */
    public function getType()
    {
        return $this->type;
    }

    /**
     * sets the last modification time of the stream content
     *
     * @param   int  $filemtime
     * @return  vfsStreamContent
     */
    public function lastModified($filemtime)
    {
        $this->lastModified = $filemtime;
        return $this;
    }

    /**
     * returns the last modification time of the stream content
     *
     * @return  int
     */
    public function filemtime()
    {
        return $this->lastModified;
    }

    /**
     * sets last access time of the stream content
     *
     * @param   int  $fileatime
     * @return  vfsStreamContent
     * @since   0.9
     */
    public function lastAccessed($fileatime)
    {
        $this->lastAccessed = $fileatime;
        return $this;
    }

    /**
     * returns the last access time of the stream content
     *
     * @return  int
     * @since   0.9
     */
    public function fileatime()
    {
        return $this->lastAccessed;
    }

    /**
     * sets the last attribute modification time of the stream content
     *
     * @param   int  $filectime
     * @return  vfsStreamContent
     * @since   0.9
     */
    public function lastAttributeModified($filectime)
    {
        $this->lastAttributeModified = $filectime;
        return $this;
    }

    /**
     * returns the last attribute modification time of the stream content
     *
     * @return  int
     * @since   0.9
     */
    public function filectime()
    {
        return $this->lastAttributeModified;
    }

    /**
     * adds content to given container
     *
     * @param   vfsStreamContainer  $container
     * @return  vfsStreamContent
     */
    public function at(vfsStreamContainer $container)
    {
        $container->addChild($this);
        return $this;
    }

    /**
     * change file mode to given permissions
     *
     * @param   int  $permissions
     * @return  vfsStreamContent
     */
    public function chmod($permissions)
    {
        $this->permissions           = $permissions;
        $this->lastAttributeModified = time();
        clearstatcache();
        return $this;
    }

    /**
     * returns permissions
     *
     * @return  int
     */
    public function getPermissions()
    {
        return $this->permissions;
    }

    /**
     * checks whether content is readable
     *
     * @param   int   $user   id of user to check for
     * @param   int   $group  id of group to check for
     * @return  bool
     */
    public function isReadable($user, $group)
    {
        if ($this->user === $user) {
            $check = 0400;
        } elseif ($this->group === $group) {
            $check = 0040;
        } else {
            $check = 0004;
        }

        return (bool) ($this->permissions & $check);
    }

    /**
     * checks whether content is writable
     *
     * @param   int   $user   id of user to check for
     * @param   int   $group  id of group to check for
     * @return  bool
     */
    public function isWritable($user, $group)
    {
        if ($this->user === $user) {
            $check = 0200;
        } elseif ($this->group === $group) {
            $check = 0020;
        } else {
            $check = 0002;
        }

        return (bool) ($this->permissions & $check);
    }

    /**
     * checks whether content is executable
     *
     * @param   int   $user   id of user to check for
     * @param   int   $group  id of group to check for
     * @return  bool
     */
    public function isExecutable($user, $group)
    {
        if ($this->user === $user) {
            $check = 0100;
        } elseif ($this->group === $group) {
            $check = 0010;
        } else {
            $check = 0001;
        }

        return (bool) ($this->permissions & $check);
    }

    /**
     * change owner of file to given user
     *
     * @param   int  $user
     * @return  vfsStreamContent
     */
    public function chown($user)
    {
        $this->user                  = $user;
        $this->lastAttributeModified = time();
        return $this;
    }

    /**
     * checks whether file is owned by given user
     *
     * @param   int  $user
     * @return  bool
     */
    public function isOwnedByUser($user)
    {
        return $this->user === $user;
    }

    /**
     * returns owner of file
     *
     * @return  int
     */
    public function getUser()
    {
        return $this->user;
    }

    /**
     * change owner group of file to given group
     *
     * @param   int  $group
     * @return  vfsStreamContent
     */
    public function chgrp($group)
    {
        $this->group                 = $group;
        $this->lastAttributeModified = time();
        return $this;
    }

    /**
     * checks whether file is owned by group
     *
     * @param   int   $group
     * @return  bool
     */
    public function isOwnedByGroup($group)
    {
        return $this->group === $group;
    }

    /**
     * returns owner group of file
     *
     * @return  int
     */
    public function getGroup()
    {
        return $this->group;
    }

    /**
     * sets parent path
     *
     * @param  string  $parentPath
     * @internal  only to be set by parent
     * @since   1.2.0
     */
    public function setParentPath($parentPath)
    {
        $this->parentPath = $parentPath;
    }

    /**
     * returns path to this content
     *
     * @return  string
     * @since   1.2.0
     */
    public function path()
    {
        if (null === $this->parentPath) {
            return $this->name;
        }

        return $this->parentPath . '/' . $this->name;
    }

    /**
     * returns complete vfsStream url for this content
     *
     * @return  string
     * @since   1.2.0
     */
    public function url()
    {
        return vfsStream::url($this->path());
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Iterator for children of a directory container.
 */
class vfsStreamContainerIterator implements \Iterator
{
    /**
     * list of children from container to iterate over
     *
     * @type  vfsStreamContent[]
     */
    protected $children;

    /**
     * constructor
     *
     * @param  vfsStreamContent[]  $children
     */
    public function __construct(array $children)
    {
        $this->children = $children;
        reset($this->children);
    }

    /**
     * resets children pointer
     */
    public function rewind()
    {
        reset($this->children);
    }

    /**
     * returns the current child
     *
     * @return  vfsStreamContent
     */
    public function current()
    {
        $child = current($this->children);
        if (false === $child) {
            return null;
        }

        return $child;
    }

    /**
     * returns the name of the current child
     *
     * @return  string
     */
    public function key()
    {
        $child = current($this->children);
        if (false === $child) {
            return null;
        }

        return $child->getName();
    }

    /**
     * iterates to next child
     */
    public function next()
    {
        next($this->children);
    }

    /**
     * checks if the current value is valid
     *
     * @return  bool
     */
    public function valid()
    {
        return (false !== current($this->children));
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs\visitor;
use org\bovigo\vfs\vfsStreamContent;
/**
 * Abstract base class providing an implementation for the visit() method.
 *
 * @since  0.10.0
 * @see    https://github.com/mikey179/vfsStream/issues/10
 */
abstract class vfsStreamAbstractVisitor implements vfsStreamVisitor
{
    /**
     * visit a content and process it
     *
     * @param   vfsStreamContent  $content
     * @return  vfsStreamVisitor
     * @throws  \InvalidArgumentException
     */
    public function visit(vfsStreamContent $content)
    {
        switch ($content->getType()) {
            case vfsStreamContent::TYPE_FILE:
                $this->visitFile($content);
                break;

            case vfsStreamContent::TYPE_DIR:
                $this->visitDirectory($content);
                break;

            default:
                throw new \InvalidArgumentException('Unknown content type ' . $content->getType() . ' for ' . $content->getName());
        }

        return $this;
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs\visitor;
use org\bovigo\vfs\vfsStreamContent;
use org\bovigo\vfs\vfsStreamDirectory;
use org\bovigo\vfs\vfsStreamFile;
/**
 * Visitor which traverses a content structure recursively to print it to an output stream.
 *
 * @since  0.10.0
 * @see    https://github.com/mikey179/vfsStream/issues/10
 */
class vfsStreamPrintVisitor extends vfsStreamAbstractVisitor
{
    /**
     * target to write output to
     *
     * @type  resource
     */
    protected $out;
    /**
     * current depth in directory tree
     *
     * @type  int
     */
    protected $depth;

    /**
     * constructor
     *
     * If no file pointer given it will fall back to STDOUT.
     *
     * @param   resource  $out  optional
     * @throws  \InvalidArgumentException
     * @api
     */
    public function __construct($out = STDOUT)
    {
        if (is_resource($out) === false || get_resource_type($out) !== 'stream') {
            throw new \InvalidArgumentException('Given filepointer is not a resource of type stream');
        }

        $this->out = $out;
    }

    /**
     * visit a file and process it
     *
     * @param   vfsStreamFile  $file
     * @return  vfsStreamPrintVisitor
     */
    public function visitFile(vfsStreamFile $file)
    {
        $this->printContent($file);
        return $this;
    }

    /**
     * visit a directory and process it
     *
     * @param   vfsStreamDirectory  $dir
     * @return  vfsStreamPrintVisitor
     */
    public function visitDirectory(vfsStreamDirectory $dir)
    {
        $this->printContent($dir);
        $this->depth++;
        foreach ($dir as $child) {
            $this->visit($child);
        }

        $this->depth--;
        return $this;
    }

    /**
     * helper method to print the content
     *
     * @param  vfsStreamContent  $content
     */
    protected function printContent(vfsStreamContent $content)
    {
        fwrite($this->out, str_repeat('  ', $this->depth) . '- ' . $content->getName() . "\n");
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs\visitor;
use org\bovigo\vfs\vfsStreamDirectory;
use org\bovigo\vfs\vfsStreamFile;
/**
 * Visitor which traverses a content structure recursively to create an array structure from it.
 *
 * @since  0.10.0
 * @see    https://github.com/mikey179/vfsStream/issues/10
 */
class vfsStreamStructureVisitor extends vfsStreamAbstractVisitor
{
    /**
     * collected structure
     *
     * @type  array
     */
    protected $structure = array();
    /**
     * poiting to currently iterated directory
     *
     * @type  array
     */
    protected $current;

    /**
     * constructor
     *
     * @api
     */
    public function __construct()
    {
        $this->reset();
    }

    /**
     * visit a file and process it
     *
     * @param   vfsStreamFile  $file
     * @return  vfsStreamStructureVisitor
     */
    public function visitFile(vfsStreamFile $file)
    {
        $this->current[$file->getName()] = $file->getContent();
        return $this;
    }

    /**
     * visit a directory and process it
     *
     * @param   vfsStreamDirectory  $dir
     * @return  vfsStreamStructureVisitor
     */
    public function visitDirectory(vfsStreamDirectory $dir)
    {
        $this->current[$dir->getName()] = array();
        $tmp           =& $this->current;
        $this->current =& $tmp[$dir->getName()];
        foreach ($dir as $child) {
            $this->visit($child);
        }

        $this->current =& $tmp;
        return $this;
    }

    /**
     * returns structure of visited contents
     *
     * @return  array
     * @api
     */
    public function getStructure()
    {
        return $this->structure;
    }

    /**
     * resets structure so visitor could be reused
     *
     * @return  vfsStreamStructureVisitor
     */
    public function reset()
    {
        $this->structure = array();
        $this->current   =& $this->structure;
        return $this;
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs\visitor;
use org\bovigo\vfs\vfsStreamContent;
use org\bovigo\vfs\vfsStreamDirectory;
use org\bovigo\vfs\vfsStreamFile;
/**
 * Interface for a visitor to work on a vfsStream content structure.
 *
 * @since  0.10.0
 * @see    https://github.com/mikey179/vfsStream/issues/10
 */
interface vfsStreamVisitor
{
    /**
     * visit a content and process it
     *
     * @param   vfsStreamContent  $content
     * @return  vfsStreamVisitor
     */
    public function visit(vfsStreamContent $content);

    /**
     * visit a file and process it
     *
     * @param   vfsStreamFile  $file
     * @return  vfsStreamVisitor
     */
    public function visitFile(vfsStreamFile $file);

    /**
     * visit a directory and process it
     *
     * @param   vfsStreamDirectory  $dir
     * @return  vfsStreamVisitor
     */
    public function visitDirectory(vfsStreamDirectory $dir);
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Interface for stream contents.
 */
interface vfsStreamContent
{
    /**
     * stream content type: file
     *
     * @see  getType()
     */
    const TYPE_FILE = 0100000;
    /**
     * stream content type: directory
     *
     * @see  getType()
     */
    const TYPE_DIR  = 0040000;
    /**
     * stream content type: symbolic link
     *
     * @see  getType();
     */
    #const TYPE_LINK = 0120000;

    /**
     * returns the file name of the content
     *
     * @return  string
     */
    public function getName();

    /**
     * renames the content
     *
     * @param  string  $newName
     */
    public function rename($newName);

    /**
     * checks whether the container can be applied to given name
     *
     * @param   string  $name
     * @return  bool
     */
    public function appliesTo($name);

    /**
     * returns the type of the container
     *
     * @return  int
     */
    public function getType();

    /**
     * returns size of content
     *
     * @return  int
     */
    public function size();

    /**
     * sets the last modification time of the stream content
     *
     * @param   int  $filemtime
     * @return  vfsStreamContent
     */
    public function lastModified($filemtime);

    /**
     * returns the last modification time of the stream content
     *
     * @return  int
     */
    public function filemtime();

    /**
     * adds content to given container
     *
     * @param   vfsStreamContainer  $container
     * @return  vfsStreamContent
     */
    public function at(vfsStreamContainer $container);

    /**
     * change file mode to given permissions
     *
     * @param   int  $permissions
     * @return  vfsStreamContent
     */
    public function chmod($permissions);

    /**
     * returns permissions
     *
     * @return  int
     */
    public function getPermissions();

    /**
     * checks whether content is readable
     *
     * @param   int   $user   id of user to check for
     * @param   int   $group  id of group to check for
     * @return  bool
     */
    public function isReadable($user, $group);

    /**
     * checks whether content is writable
     *
     * @param   int   $user   id of user to check for
     * @param   int   $group  id of group to check for
     * @return  bool
     */
    public function isWritable($user, $group);

    /**
     * checks whether content is executable
     *
     * @param   int   $user   id of user to check for
     * @param   int   $group  id of group to check for
     * @return  bool
     */
    public function isExecutable($user, $group);

    /**
     * change owner of file to given user
     *
     * @param   int  $user
     * @return  vfsStreamContent
     */
    public function chown($user);

    /**
     * checks whether file is owned by given user
     *
     * @param   int  $user
     * @return  bool
     */
    public function isOwnedByUser($user);

    /**
     * returns owner of file
     *
     * @return  int
     */
    public function getUser();

    /**
     * change owner group of file to given group
     *
     * @param   int  $group
     * @return  vfsStreamContent
     */
    public function chgrp($group);

    /**
     * checks whether file is owned by group
     *
     * @param   int   $group
     * @return  bool
     */
    public function isOwnedByGroup($group);

    /**
     * returns owner group of file
     *
     * @return  int
     */
    public function getGroup();

    /**
     * sets parent path
     *
     * @param  string  $parentPath
     * @internal  only to be set by parent
     * @since   1.2.0
     */
    public function setParentPath($parentPath);

    /**
     * returns path to this content
     *
     * @return  string
     * @since   1.2.0
     */
    public function path();

    /**
     * returns complete vfsStream url for this content
     *
     * @return  string
     * @since   1.2.0
     */
    public function url();
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Interface for stream contents that are able to store other stream contents.
 */
interface vfsStreamContainer extends \IteratorAggregate
{
    /**
     * adds child to the directory
     *
     * @param  vfsStreamContent  $child
     */
    public function addChild(vfsStreamContent $child);

    /**
     * removes child from the directory
     *
     * @param   string  $name
     * @return  bool
     */
    public function removeChild($name);

    /**
     * checks whether the container contains a child with the given name
     *
     * @param   string  $name
     * @return  bool
     */
    public function hasChild($name);

    /**
     * returns the child with the given name
     *
     * @param   string  $name
     * @return  vfsStreamContent
     */
    public function getChild($name);

    /**
     * checks whether directory contains any children
     *
     * @return  bool
     * @since   0.10.0
     */
    public function hasChildren();

    /**
     * returns a list of children for this directory
     *
     * @return  vfsStreamContent[]
     */
    public function getChildren();
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Represents a quota for disk space.
 *
 * @since     1.1.0
 * @internal
 */
class Quota
{
    /**
     * unlimited quota
     */
    const UNLIMITED   = -1;
    /**
     * quota in bytes
     *
     * A value of -1 is treated as unlimited.
     *
     * @type  int
     */
    private $amount;

    /**
     * constructor
     *
     * @param  int  $amount  quota in bytes
     */
    public function __construct($amount)
    {
        $this->amount = $amount;
    }

    /**
     * create with unlimited space
     *
     * @return  Quota
     */
    public static function unlimited()
    {
        return new self(self::UNLIMITED);
    }

    /**
     * checks if a quota is set
     *
     * @return  bool
     */
    public function isLimited()
    {
        return self::UNLIMITED < $this->amount;
    }

    /**
     * checks if given used space exceeda quota limit
     *
     *
     * @param     int   $usedSpace
     * @return    int
     */
    public function spaceLeft($usedSpace)
    {
        if (self::UNLIMITED === $this->amount) {
            return $usedSpace;
        }

        if ($usedSpace >= $this->amount) {
            return 0;
        }

        $spaceLeft = $this->amount - $usedSpace;
        if (0 >= $spaceLeft) {
            return 0;
        }

        return $spaceLeft;
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Exception for vfsStream errors.
 *
 * @api
 */
class vfsStreamException extends \Exception
{
    // intentionally empty
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Stream wrapper to mock file system requests.
 */
class vfsStreamWrapper
{
    /**
     * open file for reading
     */
    const READ                   = 'r';
    /**
     * truncate file
     */
    const TRUNCATE               = 'w';
    /**
     * set file pointer to end, append new data
     */
    const APPEND                 = 'a';
    /**
     * set file pointer to start, overwrite existing data
     */
    const WRITE                  = 'x';
    /**
     * set file pointer to start, overwrite existing data; or create file if
     * does not exist
     */
    const WRITE_NEW              = 'c';
    /**
     * file mode: read only
     */
    const READONLY               = 0;
    /**
     * file mode: write only
     */
    const WRITEONLY              = 1;
    /**
     * file mode: read and write
     */
    const ALL                    = 2;
    /**
     * switch whether class has already been registered as stream wrapper or not
     *
     * @type  bool
     */
    protected static $registered = false;
    /**
     * root content
     *
     * @type  vfsStreamContent
     */
    protected static $root;
    /**
     * disk space quota
     *
     * @type  Quota
     */
    private static $quota;
    /**
     * file mode: read only, write only, all
     *
     * @type  int
     */
    protected $mode;
    /**
     * shortcut to file container
     *
     * @type  vfsStreamFile
     */
    protected $content;
    /**
     * shortcut to directory container
     *
     * @type  vfsStreamDirectory
     */
    protected $dir;
    /**
     * shortcut to directory container iterator
     *
     * @type  vfsStreamDirectory
     */
    protected $dirIterator;

    /**
     * method to register the stream wrapper
     *
     * Please be aware that a call to this method will reset the root element
     * to null.
     * If the stream is already registered the method returns silently. If there
     * is already another stream wrapper registered for the scheme used by
     * vfsStream a vfsStreamException will be thrown.
     *
     * @throws  vfsStreamException
     */
    public static function register()
    {
        self::$root  = null;
        self::$quota = Quota::unlimited();
        if (true === self::$registered) {
            return;
        }

        if (@stream_wrapper_register(vfsStream::SCHEME, __CLASS__) === false) {
            throw new vfsStreamException('A handler has already been registered for the ' . vfsStream::SCHEME . ' protocol.');
        }

        self::$registered = true;
    }

    /**
     * sets the root content
     *
     * @param   vfsStreamContainer  $root
     * @return  vfsStreamContainer
     */
    public static function setRoot(vfsStreamContainer $root)
    {
        self::$root = $root;
        return self::$root;
    }

    /**
     * returns the root content
     *
     * @return  vfsStreamContainer
     */
    public static function getRoot()
    {
        return self::$root;
    }

    /**
     * sets quota for disk space
     *
     * @param  Quota  $quota
     * @since  1.1.0
     */
    public static function setQuota(Quota $quota)
    {
        self::$quota = $quota;
    }

    /**
     * returns content for given path
     *
     * @param   string  $path
     * @return  vfsStreamContent
     */
    protected function getContent($path)
    {
        if (null === self::$root) {
            return null;
        }

        if (self::$root->getName() === $path) {
            return self::$root;
        }

        if ($this->isInRoot($path) && self::$root->hasChild($path) === true) {
            return self::$root->getChild($path);
        }

        return null;
    }

    /**
     * helper method to detect whether given path is in root path
     *
     * @param   string  $path
     * @return  bool
     */
    private function isInRoot($path)
    {
        return substr($path, 0, strlen(self::$root->getName())) === self::$root->getName();
    }

    /**
     * returns content for given path but only when it is of given type
     *
     * @param   string  $path
     * @param   int     $type
     * @return  vfsStreamContent
     */
    protected function getContentOfType($path, $type)
    {
        $content = $this->getContent($path);
        if (null !== $content && $content->getType() === $type) {
            return $content;
        }

        return null;
    }

    /**
     * splits path into its dirname and the basename
     *
     * @param   string  $path
     * @return  string[]
     */
    protected function splitPath($path)
    {
        $lastSlashPos = strrpos($path, '/');
        if (false === $lastSlashPos) {
            return array('dirname' => '', 'basename' => $path);
        }

        return array('dirname'  => substr($path, 0, $lastSlashPos),
                     'basename' => substr($path, $lastSlashPos + 1)
               );
    }

    /**
     * helper method to resolve a path from /foo/bar/. to /foo/bar
     *
     * @param   string  $path
     * @return  string
     */
    protected function resolvePath($path)
    {
        $newPath  = array();
        foreach (explode('/', $path) as $pathPart) {
            if ('.' !== $pathPart) {
                if ('..' !== $pathPart) {
                    $newPath[] = $pathPart;
                } else {
                    array_pop($newPath);
                }
            }
        }

        return implode('/', $newPath);
    }

    /**
     * open the stream
     *
     * @param   string  $path         the path to open
     * @param   string  $mode         mode for opening
     * @param   string  $options      options for opening
     * @param   string  $opened_path  full path that was actually opened
     * @return  bool
     */
    public function stream_open($path, $mode, $options, $opened_path)
    {
        $extended = ((strstr($mode, '+') !== false) ? (true) : (false));
        $mode     = str_replace(array('b', '+'), '', $mode);
        if (in_array($mode, array('r', 'w', 'a', 'x', 'c')) === false) {
            if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) {
                trigger_error('Illegal mode ' . $mode . ', use r, w, a, x  or c, flavoured with b and/or +', E_USER_WARNING);
            }

            return false;
        }

        $this->mode    = $this->calculateMode($mode, $extended);
        $path          = $this->resolvePath(vfsStream::path($path));
        $this->content = $this->getContentOfType($path, vfsStreamContent::TYPE_FILE);
        if (null !== $this->content) {
            if (self::WRITE === $mode) {
                if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) {
                    trigger_error('File ' . $path . ' already exists, can not open with mode x', E_USER_WARNING);
                }

                return false;
            }

            if (
                (self::TRUNCATE === $mode || self::APPEND === $mode) &&
                $this->content->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false
            ) {
                return false;
            }

            if (self::TRUNCATE === $mode) {
                $this->content->openWithTruncate();
            } elseif (self::APPEND === $mode) {
                $this->content->openForAppend();
            } else {
                if (!$this->content->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup())) {
                    if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) {
                        trigger_error('Permission denied', E_USER_WARNING);
                    }
                    return false;
                }
                $this->content->open();
            }

            return true;
        }

        $content = $this->createFile($path, $mode, $options);
        if (false === $content) {
            return false;
        }

        $this->content = $content;
        return true;
    }

    /**
     * creates a file at given path
     *
     * @param   string  $path     the path to open
     * @param   string  $mode     mode for opening
     * @param   string  $options  options for opening
     * @return  bool
     */
    private function createFile($path, $mode = null, $options = null)
    {
        $names = $this->splitPath($path);
        if (empty($names['dirname']) === true) {
            if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) {
                trigger_error('File ' . $names['basename'] . ' does not exist', E_USER_WARNING);
            }

            return false;
        }

        $dir = $this->getContentOfType($names['dirname'], vfsStreamContent::TYPE_DIR);
        if (null === $dir) {
            if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) {
                trigger_error('Directory ' . $names['dirname'] . ' does not exist', E_USER_WARNING);
            }

            return false;
        } elseif ($dir->hasChild($names['basename']) === true) {
            if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) {
                trigger_error('Directory ' . $names['dirname'] . ' already contains a director named ' . $names['basename'], E_USER_WARNING);
            }

            return false;
        }

        if (self::READ === $mode) {
            if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) {
                trigger_error('Can not open non-existing file ' . $path . ' for reading', E_USER_WARNING);
            }

            return false;
        }

        if ($dir->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) {
            if (($options & STREAM_REPORT_ERRORS) === STREAM_REPORT_ERRORS) {
                trigger_error('Can not create new file in non-writable path ' . $names['dirname'], E_USER_WARNING);
            }

            return false;
        }

        return vfsStream::newFile($names['basename'])->at($dir);
    }

    /**
     * calculates the file mode
     *
     * @param   string  $mode      opening mode: r, w, a or x
     * @param   bool    $extended  true if + was set with opening mode
     * @return  int
     */
    protected function calculateMode($mode, $extended)
    {
        if (true === $extended) {
            return self::ALL;
        }

        if (self::READ === $mode) {
            return self::READONLY;
        }

        return self::WRITEONLY;
    }

    /**
     * closes the stream
     *
     * @see     https://github.com/mikey179/vfsStream/issues/40
     */
    public function stream_close()
    {
        $this->content->lock($this, LOCK_UN);
    }

    /**
     * read the stream up to $count bytes
     *
     * @param   int     $count  amount of bytes to read
     * @return  string
     */
    public function stream_read($count)
    {
        if (self::WRITEONLY === $this->mode) {
            return '';
        }

        if ($this->content->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) {
            return '';
        }

        return $this->content->read($count);
    }

    /**
     * writes data into the stream
     *
     * @param   string  $data
     * @return  int     amount of bytes written
     */
    public function stream_write($data)
    {
        if (self::READONLY === $this->mode) {
            return 0;
        }

        if ($this->content->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) {
            return 0;
        }

        if (self::$quota->isLimited()) {
            $data = substr($data, 0, self::$quota->spaceLeft(self::$root->sizeSummarized()));
        }

        return $this->content->write($data);
    }

    /**
     * truncates a file to a given length
     *
     * @param   int  $size  length to truncate file to
     * @return  bool
     * @since   1.1.0
     */
    public function stream_truncate($size)
    {
        if (self::READONLY === $this->mode) {
            return false;
        }

        if ($this->content->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) {
            return false;
        }

        if ($this->content->getType() !== vfsStreamContent::TYPE_FILE) {
            return false;
        }

        if (self::$quota->isLimited() && $this->content->size() < $size) {
            $maxSize = self::$quota->spaceLeft(self::$root->sizeSummarized());
            if (0 === $maxSize) {
                return false;
            }

            if ($size > $maxSize) {
                $size = $maxSize;
            }
        }

        return $this->content->truncate($size);
    }

    /**
     * sets metadata like owner, user or permissions
     *
     * @param   string  $path
     * @param   int     $option
     * @param   mixed   $var
     * @return  bool
     * @since   1.1.0
     */
    public function stream_metadata($path, $option, $var)
    {
        $path    = $this->resolvePath(vfsStream::path($path));
        $content = $this->getContent($path);
        switch ($option) {
            case STREAM_META_TOUCH:
                if (null === $content) {
                    $content = $this->createFile($path);
                }

                if (isset($var[0])) {
                    $content->lastModified($var[0]);
                }

                if (isset($var[1])) {
                    $content->lastAccessed($var[1]);
                }

                return true;

            case STREAM_META_OWNER_NAME:
                return false;

            case STREAM_META_OWNER:
                if (null === $content) {
                    return false;
                }

                return $this->doPermChange($path,
                                           $content,
                                           function() use ($content, $var)
                                           {
                                               $content->chown($var);
                                           }
                );

            case STREAM_META_GROUP_NAME:
                return false;

            case STREAM_META_GROUP:
                if (null === $content) {
                    return false;
                }

                return $this->doPermChange($path,
                                           $content,
                                           function() use ($content, $var)
                                           {
                                               $content->chgrp($var);
                                           }
                );

            case STREAM_META_ACCESS:
                if (null === $content) {
                    return false;
                }

                return $this->doPermChange($path,
                                           $content,
                                           function() use ($content, $var)
                                           {
                                               $content->chmod($var);
                                           }
                );

            default:
                return false;
        }
    }

    /**
     * executes given permission change when necessary rights allow such a change
     *
     * @param   string                    $path
     * @param   vfsStreamAbstractContent  $content
     * @param   Closure                   $change
     * @return  bool
     */
    private function doPermChange($path, vfsStreamAbstractContent $content, \Closure $change)
    {
        if (!$content->isOwnedByUser(vfsStream::getCurrentUser())) {
            return false;
        }

        if (self::$root->getName() !== $path) {
            $names   = $this->splitPath($path);
            $parent = $this->getContent($names['dirname']);
            if (!$parent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup())) {
                return false;
            }
        }

        $change();
        return true;
    }

    /**
     * checks whether stream is at end of file
     *
     * @return  bool
     */
    public function stream_eof()
    {
        return $this->content->eof();
    }

    /**
     * returns the current position of the stream
     *
     * @return  int
     */
    public function stream_tell()
    {
        return $this->content->getBytesRead();
    }

    /**
     * seeks to the given offset
     *
     * @param   int   $offset
     * @param   int   $whence
     * @return  bool
     */
    public function stream_seek($offset, $whence)
    {
        return $this->content->seek($offset, $whence);
    }

    /**
     * flushes unstored data into storage
     *
     * @return  bool
     */
    public function stream_flush()
    {
        return true;
    }

    /**
     * returns status of stream
     *
     * @return  array
     */
    public function stream_stat()
    {
        $fileStat = array('dev'     => 0,
                          'ino'     => 0,
                          'mode'    => $this->content->getType() | $this->content->getPermissions(),
                          'nlink'   => 0,
                          'uid'     => $this->content->getUser(),
                          'gid'     => $this->content->getGroup(),
                          'rdev'    => 0,
                          'size'    => $this->content->size(),
                          'atime'   => $this->content->fileatime(),
                          'mtime'   => $this->content->filemtime(),
                          'ctime'   => $this->content->filectime(),
                          'blksize' => -1,
                          'blocks'  => -1
                    );
        return array_merge(array_values($fileStat), $fileStat);
    }

    /**
     * retrieve the underlaying resource
     *
     * Please note that this method always returns false as there is no
     * underlaying resource to return.
     *
     * @param   int  $cast_as
     * @since   0.9.0
     * @see     https://github.com/mikey179/vfsStream/issues/3
     * @return  bool
     */
    public function stream_cast($cast_as)
    {
        return false;
    }

    /**
     * set lock status for stream
     *
     * @param   int   $operation
     * @return  bool
     * @since   0.10.0
     * @see     https://github.com/mikey179/vfsStream/issues/6
     * @see     https://github.com/mikey179/vfsStream/issues/31
     * @see     https://github.com/mikey179/vfsStream/issues/40
     */
    public function stream_lock($operation)
    {
        if ((LOCK_NB & $operation) == LOCK_NB) {
            $operation = $operation - LOCK_NB;
        }

        return $this->content->lock($this, $operation);
    }

    /**
     * sets options on the stream
     *
     * @param   int   $option  key of option to set
     * @param   int   $arg1
     * @param   int   $arg2
     * @return  bool
     * @since   0.10.0
     * @see     https://github.com/mikey179/vfsStream/issues/15
     * @see     http://www.php.net/manual/streamwrapper.stream-set-option.php
     */
    public function stream_set_option($option, $arg1, $arg2)
    {
        switch ($option) {
            case STREAM_OPTION_BLOCKING:
                // break omitted

            case STREAM_OPTION_READ_TIMEOUT:
                // break omitted

            case STREAM_OPTION_WRITE_BUFFER:
                // break omitted

            default:
                // nothing to do here
        }

        return false;
    }

    /**
     * remove the data under the given path
     *
     * @param   string  $path
     * @return  bool
     */
    public function unlink($path)
    {
        $realPath = $this->resolvePath(vfsStream::path($path));
        $content  = $this->getContent($realPath);
        if (null === $content) {
            return false;
        }

        if ($content->getType() !== vfsStreamContent::TYPE_FILE) {
            trigger_error('unlink(' . $path . '): Operation not permitted', E_USER_WARNING);
            return false;
        }

        return $this->doUnlink($realPath);
    }

    /**
     * removes a path
     *
     * @param   string  $path
     * @return  bool
     */
    protected function doUnlink($path)
    {
        if (self::$root->getName() === $path) {
            // delete root? very brave. :)
            self::$root = null;
            clearstatcache();
            return true;
        }

        $names   = $this->splitPath($path);
        $content = $this->getContent($names['dirname']);
        if (!$content->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup())) {
            return false;
        }

        clearstatcache();
        return $content->removeChild($names['basename']);
    }

    /**
     * rename from one path to another
     *
     * @param   string  $path_from
     * @param   string  $path_to
     * @return  bool
     * @author  Benoit Aubuchon
     */
    public function rename($path_from, $path_to)
    {
        $srcRealPath = $this->resolvePath(vfsStream::path($path_from));
        $dstRealPath = $this->resolvePath(vfsStream::path($path_to));
        $srcContent  = $this->getContent($srcRealPath);
        if (null == $srcContent) {
            trigger_error(' No such file or directory', E_USER_WARNING);
            return false;
        }
        $dstNames = $this->splitPath($dstRealPath);
        $dstParentContent = $this->getContent($dstNames['dirname']);
        if (null == $dstParentContent) {
            trigger_error('No such file or directory', E_USER_WARNING);
            return false;
        }
        if (!$dstParentContent->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup())) {
            trigger_error('Permission denied', E_USER_WARNING);
            return false;
        }
        if ($dstParentContent->getType() !== vfsStreamContent::TYPE_DIR) {
            trigger_error('Target is not a directory', E_USER_WARNING);
            return false;
        }

        // remove old source first, so we can rename later
        // (renaming first would lead to not being able to remove the old path)
        if (!$this->doUnlink($srcRealPath)) {
            return false;
        }

        $dstContent = $srcContent;
        // Renaming the filename
        $dstContent->rename($dstNames['basename']);
        // Copying to the destination
        $dstParentContent->addChild($dstContent);
        return true;
    }

    /**
     * creates a new directory
     *
     * @param   string  $path
     * @param   int     $mode
     * @param   int     $options
     * @return  bool
     */
    public function mkdir($path, $mode, $options)
    {
        $umask = vfsStream::umask();
        if (0 < $umask) {
            $permissions = $mode & ~$umask;
        } else {
            $permissions = $mode;
        }

        $path = $this->resolvePath(vfsStream::path($path));
        if (null !== $this->getContent($path)) {
            trigger_error('mkdir(): Path vfs://' . $path . ' exists', E_USER_WARNING);
            return false;
        }

        if (null === self::$root) {
            self::$root = vfsStream::newDirectory($path, $permissions);
            return true;
        }

        $maxDepth = count(explode('/', $path));
        $names    = $this->splitPath($path);
        $newDirs  = $names['basename'];
        $dir      = null;
        $i        = 0;
        while ($dir === null && $i < $maxDepth) {
            $dir     = $this->getContent($names['dirname']);
            $names   = $this->splitPath($names['dirname']);
            if (null == $dir) {
                $newDirs = $names['basename'] . '/' . $newDirs;
            }

            $i++;
        }

        if (null === $dir
          || $dir->getType() !== vfsStreamContent::TYPE_DIR
          || $dir->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) {
            return false;
        }

        $recursive = ((STREAM_MKDIR_RECURSIVE & $options) !== 0) ? (true) : (false);
        if (strpos($newDirs, '/') !== false && false === $recursive) {
            return false;
        }

        vfsStream::newDirectory($newDirs, $permissions)->at($dir);
        return true;
    }

    /**
     * removes a directory
     *
     * @param   string  $path
     * @param   int     $options
     * @return  bool
     * @todo    consider $options with STREAM_MKDIR_RECURSIVE
     */
    public function rmdir($path, $options)
    {
        $path  = $this->resolvePath(vfsStream::path($path));
        $child = $this->getContentOfType($path, vfsStreamContent::TYPE_DIR);
        if (null === $child) {
            return false;
        }

        // can only remove empty directories
        if (count($child->getChildren()) > 0) {
            return false;
        }

        if (self::$root->getName() === $path) {
            // delete root? very brave. :)
            self::$root = null;
            clearstatcache();
            return true;
        }

        $names = $this->splitPath($path);
        $dir   = $this->getContentOfType($names['dirname'], vfsStreamContent::TYPE_DIR);
        if ($dir->isWritable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) {
            return false;
        }

        clearstatcache();
        return $dir->removeChild($child->getName());
    }

    /**
     * opens a directory
     *
     * @param   string  $path
     * @param   int     $options
     * @return  bool
     */
    public function dir_opendir($path, $options)
    {
        $path      = $this->resolvePath(vfsStream::path($path));
        $this->dir = $this->getContentOfType($path, vfsStreamContent::TYPE_DIR);
        if (null === $this->dir || $this->dir->isReadable(vfsStream::getCurrentUser(), vfsStream::getCurrentGroup()) === false) {
            return false;
        }

        $this->dirIterator = $this->dir->getIterator();
        return true;
    }

    /**
     * reads directory contents
     *
     * @return  string
     */
    public function dir_readdir()
    {
        $dir = $this->dirIterator->current();
        if (null === $dir) {
            return false;
        }

        $this->dirIterator->next();
        return $dir->getName();
    }

    /**
     * reset directory iteration
     *
     * @return  bool
     */
    public function dir_rewinddir()
    {
        return $this->dirIterator->rewind();
    }

    /**
     * closes directory
     *
     * @return  bool
     */
    public function dir_closedir()
    {
        $this->dirIterator = null;
        return true;
    }

    /**
     * returns status of url
     *
     * @param   string  $path   path of url to return status for
     * @param   int     $flags  flags set by the stream API
     * @return  array
     */
    public function url_stat($path, $flags)
    {
        $content = $this->getContent($this->resolvePath(vfsStream::path($path)));
        if (null === $content) {
            if (($flags & STREAM_URL_STAT_QUIET) != STREAM_URL_STAT_QUIET) {
                trigger_error(' No such file or directory: ' . $path, E_USER_WARNING);
            }

            return false;

        }

        $fileStat = array('dev'     => 0,
                          'ino'     => 0,
                          'mode'    => $content->getType() | $content->getPermissions(),
                          'nlink'   => 0,
                          'uid'     => $content->getUser(),
                          'gid'     => $content->getGroup(),
                          'rdev'    => 0,
                          'size'    => $content->size(),
                          'atime'   => $content->fileatime(),
                          'mtime'   => $content->filemtime(),
                          'ctime'   => $content->filectime(),
                          'blksize' => -1,
                          'blocks'  => -1
                    );
        return array_merge(array_values($fileStat), $fileStat);
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
use org\bovigo\vfs\visitor\vfsStreamVisitor;
/**
 * Some utility methods for vfsStream.
 *
 * @api
 */
class vfsStream
{
    /**
     * url scheme
     */
    const SCHEME           = 'vfs';
    /**
     * owner: root
     */
    const OWNER_ROOT       = 0;
    /**
     * owner: user 1
     */
    const OWNER_USER_1      = 1;
    /**
     * owner: user 2
     */
    const OWNER_USER_2      = 2;
    /**
     * group: root
     */
    const GROUP_ROOT        = 0;
    /**
     * group: user 1
     */
    const GROUP_USER_1      = 1;
    /**
     * group: user 2
     */
    const GROUP_USER_2      = 2;
    /**
     * initial umask setting
     *
     * @type  int
     */
    protected static $umask = 0000;

    /**
     * prepends the scheme to the given URL
     *
     * @param   string  $path  path to translate to vfsStream url
     * @return  string
     */
    public static function url($path)
    {
        return self::SCHEME . '://' . str_replace('\\', '/', $path);
    }

    /**
     * restores the path from the url
     *
     * @param   string  $url  vfsStream url to translate into path
     * @return  string
     */
    public static function path($url)
    {
        // remove line feeds and trailing whitespaces
        $path = trim($url, " \t\r\n\0\x0B/");
        $path = substr($path, strlen(self::SCHEME . '://'));
        $path = str_replace('\\', '/', $path);
        // replace double slashes with single slashes
        $path = str_replace('//', '/', $path);
        return $path;
    }

    /**
     * sets new umask setting and returns previous umask setting
     *
     * If no value is given only the current umask setting is returned.
     *
     * @param   int  $umask  new umask setting
     * @return  int
     * @since   0.8.0
     */
    public static function umask($umask = null)
    {
        $oldUmask = self::$umask;
        if (null !== $umask) {
            self::$umask = $umask;
        }

        return $oldUmask;
    }

    /**
     * helper method for setting up vfsStream in unit tests
     *
     * Instead of
     * vfsStreamWrapper::register();
     * vfsStreamWrapper::setRoot(vfsStream::newDirectory('root'));
     * you can simply do
     * vfsStream::setup()
     * which yields the same result. Additionally, the method returns the
     * freshly created root directory which you can use to make further
     * adjustments to it.
     *
     * Assumed $structure contains an array like this:
     * <code>
     * array('Core' = array('AbstractFactory' => array('test.php'    => 'some text content',
     *                                                 'other.php'   => 'Some more text content',
     *                                                 'Invalid.csv' => 'Something else',
     *                                           ),
     *                      'AnEmptyFolder'   => array(),
     *                      'badlocation.php' => 'some bad content',
     *                )
     * )
     * </code>
     * the resulting directory tree will look like this:
     * <pre>
     * root
     * \- Core
     *  |- badlocation.php
     *  |- AbstractFactory
     *  | |- test.php
     *  | |- other.php
     *  | \- Invalid.csv
     *  \- AnEmptyFolder
     * </pre>
     * Arrays will become directories with their key as directory name, and
     * strings becomes files with their key as file name and their value as file
     * content.
     *
     * @param   string  $rootDirName  name of root directory
     * @param   int     $permissions  file permissions of root directory
     * @param   array   $structure    directory structure to add under root directory
     * @return  \org\bovigo\vfs\vfsStreamDirectory
     * @since   0.7.0
     * @see     https://github.com/mikey179/vfsStream/issues/14
     * @see     https://github.com/mikey179/vfsStream/issues/20
     */
    public static function setup($rootDirName = 'root', $permissions = null, array $structure = array())
    {
        vfsStreamWrapper::register();
        return self::create($structure, vfsStreamWrapper::setRoot(self::newDirectory($rootDirName, $permissions)));
    }

    /**
     * creates vfsStream directory structure from an array and adds it to given base dir
     *
     * Assumed $structure contains an array like this:
     * <code>
     * array('Core' = array('AbstractFactory' => array('test.php'    => 'some text content',
     *                                                 'other.php'   => 'Some more text content',
     *                                                 'Invalid.csv' => 'Something else',
     *                                           ),
     *                      'AnEmptyFolder'   => array(),
     *                      'badlocation.php' => 'some bad content',
     *                )
     * )
     * </code>
     * the resulting directory tree will look like this:
     * <pre>
     * baseDir
     * \- Core
     *  |- badlocation.php
     *  |- AbstractFactory
     *  | |- test.php
     *  | |- other.php
     *  | \- Invalid.csv
     *  \- AnEmptyFolder
     * </pre>
     * Arrays will become directories with their key as directory name, and
     * strings becomes files with their key as file name and their value as file
     * content.
     *
     * If no baseDir is given it will try to add the structure to the existing
     * root directory without replacing existing childs except those with equal
     * names.
     *
     * @param   array               $structure  directory structure to add under root directory
     * @param   vfsStreamDirectory  $baseDir    base directory to add structure to
     * @return  vfsStreamDirectory
     * @throws  \InvalidArgumentException
     * @since   0.10.0
     * @see     https://github.com/mikey179/vfsStream/issues/14
     * @see     https://github.com/mikey179/vfsStream/issues/20
     */
    public static function create(array $structure, vfsStreamDirectory $baseDir = null)
    {
        if (null === $baseDir) {
            $baseDir = vfsStreamWrapper::getRoot();
        }

        if (null === $baseDir) {
            throw new \InvalidArgumentException('No baseDir given and no root directory set.');
        }

        return self::addStructure($structure, $baseDir);
    }

    /**
     * helper method to create subdirectories recursively
     *
     * @param   array               $structure  subdirectory structure to add
     * @param   vfsStreamDirectory  $baseDir    directory to add the structure to
     * @return  vfsStreamDirectory
     */
    protected static function addStructure(array $structure, vfsStreamDirectory $baseDir)
    {
        foreach ($structure as $name => $data) {
            $name = (string) $name;
            if (is_array($data) === true) {
                self::addStructure($data, self::newDirectory($name)->at($baseDir));
            } elseif (is_string($data) === true) {
                self::newFile($name)->withContent($data)->at($baseDir);
            }
        }

        return $baseDir;
    }

    /**
     * copies the file system structure from given path into the base dir
     *
     * If no baseDir is given it will try to add the structure to the existing
     * root directory without replacing existing childs except those with equal
     * names.
     * File permissions are copied as well.
     * Please note that file contents will only be copied if their file size
     * does not exceed the given $maxFileSize which is 1024 KB.
     *
     * @param   string              $path         path to copy the structure from
     * @param   vfsStreamDirectory  $baseDir      directory to add the structure to
     * @param   int                 $maxFileSize  maximum file size of files to copy content from
     * @return  vfsStreamDirectory
     * @throws  \InvalidArgumentException
     * @since   0.11.0
     * @see     https://github.com/mikey179/vfsStream/issues/4
     */
    public static function copyFromFileSystem($path, vfsStreamDirectory $baseDir = null, $maxFileSize = 1048576)
    {
        if (null === $baseDir) {
            $baseDir = vfsStreamWrapper::getRoot();
        }

        if (null === $baseDir) {
            throw new \InvalidArgumentException('No baseDir given and no root directory set.');
        }

        $dir = new \DirectoryIterator($path);
        foreach ($dir as $fileinfo) {
            if ($fileinfo->isFile() === true) {
                if ($fileinfo->getSize() <= $maxFileSize) {
                    $content = file_get_contents($fileinfo->getPathname());
                } else {
                    $content = '';
                }

                self::newFile($fileinfo->getFilename(),
                              octdec(substr(sprintf('%o', $fileinfo->getPerms()), -4))
                      )
                    ->withContent($content)
                    ->at($baseDir);
            } elseif ($fileinfo->isDir() === true && $fileinfo->isDot() === false) {
                self::copyFromFileSystem($fileinfo->getPathname(),
                                         self::newDirectory($fileinfo->getFilename(),
                                                            octdec(substr(sprintf('%o', $fileinfo->getPerms()), -4))
                                               )
                                             ->at($baseDir),
                                         $maxFileSize
                );
            }
        }

        return $baseDir;
    }

    /**
     * returns a new file with given name
     *
     * @param   string  $name         name of file to create
     * @param   int     $permissions  permissions of file to create
     * @return  vfsStreamFile
     */
    public static function newFile($name, $permissions = null)
    {
        return new vfsStreamFile($name, $permissions);
    }

    /**
     * returns a new directory with given name
     *
     * If the name contains slashes, a new directory structure will be created.
     * The returned directory will always be the parent directory of this
     * directory structure.
     *
     * @param   string  $name         name of directory to create
     * @param   int     $permissions  permissions of directory to create
     * @return  vfsStreamDirectory
     */
    public static function newDirectory($name, $permissions = null)
    {
        if ('/' === $name{0}) {
            $name = substr($name, 1);
        }

        $firstSlash = strpos($name, '/');
        if (false === $firstSlash) {
            return new vfsStreamDirectory($name, $permissions);
        }

        $ownName   = substr($name, 0, $firstSlash);
        $subDirs   = substr($name, $firstSlash + 1);
        $directory = new vfsStreamDirectory($ownName, $permissions);
        self::newDirectory($subDirs, $permissions)->at($directory);
        return $directory;
    }

    /**
     * returns current user
     *
     * If the system does not support posix_getuid() the current user will be root (0).
     *
     * @return  int
     */
    public static function getCurrentUser()
    {
        return function_exists('posix_getuid') ? posix_getuid() : self::OWNER_ROOT;
    }

    /**
     * returns current group
     *
     * If the system does not support posix_getgid() the current group will be root (0).
     *
     * @return  int
     */
    public static function getCurrentGroup()
    {
        return function_exists('posix_getgid') ? posix_getgid() : self::GROUP_ROOT;
    }

    /**
     * use visitor to inspect a content structure
     *
     * If the given content is null it will fall back to use the current root
     * directory of the stream wrapper.
     *
     * Returns given visitor for method chaining comfort.
     *
     * @param   vfsStreamVisitor  $visitor  the visitor who inspects
     * @param   vfsStreamContent  $content  directory structure to inspect
     * @return  vfsStreamVisitor
     * @throws  \InvalidArgumentException
     * @since   0.10.0
     * @see     https://github.com/mikey179/vfsStream/issues/10
     */
    public static function inspect(vfsStreamVisitor $visitor, vfsStreamContent $content = null)
    {
        if (null !== $content) {
            return $visitor->visit($content);
        }

        $root = vfsStreamWrapper::getRoot();
        if (null === $root) {
            throw new \InvalidArgumentException('No content given and no root directory set.');
        }

        return $visitor->visitDirectory($root);
    }

    /**
     * sets quota to given amount of bytes
     *
     * @param  int  $bytes
     * @since  1.1.0
     */
    public static function setQuota($bytes)
    {
        vfsStreamWrapper::setQuota(new Quota($bytes));
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Directory container.
 *
 * @api
 */
class vfsStreamDirectory extends vfsStreamAbstractContent implements vfsStreamContainer
{
    /**
     * list of directory children
     *
     * @type  vfsStreamContent[]
     */
    protected $children = array();

    /**
     * constructor
     *
     * @param   string  $name
     * @param   int     $permissions  optional
     * @throws  vfsStreamException
     */
    public function __construct($name, $permissions = null)
    {
        if (strstr($name, '/') !== false) {
            throw new vfsStreamException('Directory name can not contain /.');
        }

        $this->type = vfsStreamContent::TYPE_DIR;
        parent::__construct($name, $permissions);
    }

    /**
     * returns default permissions for concrete implementation
     *
     * @return  int
     * @since   0.8.0
     */
    protected function getDefaultPermissions()
    {
        return 0777;
    }

    /**
     * returns size of directory
     *
     * The size of a directory is always 0 bytes. To calculate the summarized
     * size of all children in the directory use sizeSummarized().
     *
     * @return  int
     */
    public function size()
    {
        return 0;
    }

    /**
     * returns summarized size of directory and its children
     *
     * @return  int
     */
    public function sizeSummarized()
    {
        $size = 0;
        foreach ($this->children as $child) {
            if ($child->getType() === vfsStreamContent::TYPE_DIR) {
                $size += $child->sizeSummarized();
            } else {
                $size += $child->size();
            }
        }

        return $size;
    }

    /**
     * renames the content
     *
     * @param   string  $newName
     * @throws  vfsStreamException
     */
    public function rename($newName)
    {
        if (strstr($newName, '/') !== false) {
            throw new vfsStreamException('Directory name can not contain /.');
        }

        parent::rename($newName);
    }


    /**
     * sets parent path
     *
     * @param  string  $parentPath
     * @internal  only to be set by parent
     * @since   1.2.0
     */
    public function setParentPath($parentPath)
    {
        parent::setParentPath($parentPath);
        foreach ($this->children as $child) {
            $child->setParentPath($this->path());
        }
    }

    /**
     * adds child to the directory
     *
     * @param  vfsStreamContent  $child
     */
    public function addChild(vfsStreamContent $child)
    {
        $child->setParentPath($this->path());
        $this->children[$child->getName()] = $child;
        $this->updateModifications();
    }

    /**
     * removes child from the directory
     *
     * @param   string  $name
     * @return  bool
     */
    public function removeChild($name)
    {
        foreach ($this->children as $key => $child) {
            if ($child->appliesTo($name)) {
                $child->setParentPath(null);
                unset($this->children[$key]);
                $this->updateModifications();
                return true;
            }
        }

        return false;
    }

    /**
     * updates internal timestamps
     */
    protected function updateModifications()
    {
        $time = time();
        $this->lastAttributeModified = $time;
        $this->lastModified          = $time;
    }

    /**
     * checks whether the container contains a child with the given name
     *
     * @param   string  $name
     * @return  bool
     */
    public function hasChild($name)
    {
        return ($this->getChild($name) !== null);
    }

    /**
     * returns the child with the given name
     *
     * @param   string  $name
     * @return  vfsStreamContent
     */
    public function getChild($name)
    {
        $childName = $this->getRealChildName($name);
        foreach ($this->children as $child) {
            if ($child->getName() === $childName) {
                return $child;
            }

            if ($child->appliesTo($childName) === true && $child->hasChild($childName) === true) {
                return $child->getChild($childName);
            }
        }

        return null;
    }

    /**
     * helper method to detect the real child name
     *
     * @param   string  $name
     * @return  string
     */
    protected function getRealChildName($name)
    {
        if ($this->appliesTo($name) === true) {
            return self::getChildName($name, $this->name);
        }

        return $name;
    }

    /**
     * helper method to calculate the child name
     *
     * @param   string  $name
     * @param   string  $ownName
     * @return  string
     */
    protected static function getChildName($name, $ownName)
    {
        if ($name === $ownName) {
            return $name;
        }

        return substr($name, strlen($ownName) + 1);
    }

    /**
     * checks whether directory contains any children
     *
     * @return  bool
     * @since   0.10.0
     */
    public function hasChildren()
    {
        return (count($this->children) > 0);
    }

    /**
     * returns a list of children for this directory
     *
     * @return  vfsStreamContent[]
     */
    public function getChildren()
    {
        return array_values($this->children);
    }

    /**
     * returns iterator for the children
     *
     * @return  vfsStreamContainerIterator
     */
    public function getIterator()
    {
        return new vfsStreamContainerIterator($this->children);
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * File container.
 *
 * @api
 */
class vfsStreamFile extends vfsStreamAbstractContent
{
    /**
     * the real content of the file
     *
     * @type  string
     */
    protected $content;
    /**
     * amount of read bytes
     *
     * @type  int
     */
    protected $bytes_read = 0;
    /**
     * Resource id which exclusively locked this file
     *
     * @type  string
     */
    protected $exclusiveLock;
    /**
     * Resources ids which currently holds shared lock to this file
     *
     * @type  bool[string]
     */
    protected $sharedLock = array();

    /**
     * constructor
     *
     * @param  string  $name
     * @param  int     $permissions  optional
     */
    public function __construct($name, $permissions = null)
    {
        $this->type = vfsStreamContent::TYPE_FILE;
        parent::__construct($name, $permissions);
    }

    /**
     * returns default permissions for concrete implementation
     *
     * @return  int
     * @since   0.8.0
     */
    protected function getDefaultPermissions()
    {
        return 0666;
    }

    /**
     * checks whether the container can be applied to given name
     *
     * @param   string  $name
     * @return  bool
     */
    public function appliesTo($name)
    {
        return ($name === $this->name);
    }

    /**
     * alias for withContent()
     *
     * @param   string  $content
     * @return  vfsStreamFile
     * @see     withContent()
     */
    public function setContent($content)
    {
        return $this->withContent($content);
    }

    /**
     * sets the contents of the file
     *
     * Setting content with this method does not change the time when the file
     * was last modified.
     *
     * @param   string  $content
     * @return  vfsStreamFile
     */
    public function withContent($content)
    {
        $this->content = $content;
        return $this;
    }

    /**
     * returns the contents of the file
     *
     * Getting content does not change the time when the file
     * was last accessed.
     *
     * @return  string
     */
    public function getContent()
    {
        return $this->content;
    }

    /**
     * simply open the file
     *
     * @since  0.9
     */
    public function open()
    {
        $this->seek(0, SEEK_SET);
        $this->lastAccessed = time();
    }

    /**
     * open file and set pointer to end of file
     *
     * @since  0.9
     */
    public function openForAppend()
    {
        $this->seek(0, SEEK_END);
        $this->lastAccessed = time();
    }

    /**
     * open file and truncate content
     *
     * @since  0.9
     */
    public function openWithTruncate()
    {
        $this->open();
        $this->content      = '';
        $time               = time();
        $this->lastAccessed = $time;
        $this->lastModified = $time;
    }

    /**
     * reads the given amount of bytes from content
     *
     * Using this method changes the time when the file was last accessed.
     *
     * @param   int     $count
     * @return  string
     */
    public function read($count)
    {
        $data = substr($this->content, $this->bytes_read, $count);
        $this->bytes_read  += $count;
        $this->lastAccessed = time();
        return $data;
    }

    /**
     * returns the content until its end from current offset
     *
     * Using this method changes the time when the file was last accessed.
     *
     * @return  string
     */
    public function readUntilEnd()
    {
        $this->lastAccessed = time();
        return substr($this->content, $this->bytes_read);
    }

    /**
     * writes an amount of data
     *
     * Using this method changes the time when the file was last modified.
     *
     * @param   string  $data
     * @return  amount of written bytes
     */
    public function write($data)
    {
        $dataLen            = strlen($data);
        $this->content      = substr($this->content, 0, $this->bytes_read) . $data . substr($this->content, $this->bytes_read + $dataLen);
        $this->bytes_read  += $dataLen;
        $this->lastModified = time();
        return $dataLen;
    }

    /**
     * Truncates a file to a given length
     *
     * @param   int  $size length to truncate file to
     * @return  bool
     * @since   1.1.0
     */
    public function truncate($size) {
        if ($size > $this->size()) {
            // Pad with null-chars if we're "truncating up"
            $this->setContent($this->getContent() . str_repeat("\0", $size - $this->size()));
        } else {
            $this->setContent(substr($this->getContent(), 0, $size));
        }

        $this->lastModified = time();
        return true;
    }

    /**
     * checks whether pointer is at end of file
     *
     * @return  bool
     */
    public function eof()
    {
        return $this->bytes_read >= strlen($this->content);
    }

    /**
     * returns the current position within the file
     *
     * @return  int
     */
    public function getBytesRead()
    {
        return $this->bytes_read;
    }

    /**
     * seeks to the given offset
     *
     * @param   int   $offset
     * @param   int   $whence
     * @return  bool
     */
    public function seek($offset, $whence)
    {
        switch ($whence) {
            case SEEK_CUR:
                $this->bytes_read += $offset;
                return true;

            case SEEK_END:
                $this->bytes_read = strlen($this->content) + $offset;
                return true;

            case SEEK_SET:
                $this->bytes_read = $offset;
                return true;

            default:
                return false;
        }

        return false;
    }

    /**
     * returns size of content
     *
     * @return  int
     */
    public function size()
    {
        return strlen($this->content);
    }


    /**
     * locks file for
     *
     * @param   resource|vfsStreamWrapper $resource
     * @param   int  $operation
     * @return  bool
     * @since   0.10.0
     * @see     https://github.com/mikey179/vfsStream/issues/6
     * @see     https://github.com/mikey179/vfsStream/issues/40
     */
    public function lock($resource, $operation)
    {
        if ((LOCK_NB & $operation) == LOCK_NB) {
            $operation = $operation - LOCK_NB;
        }

        // call to lock file on the same file handler firstly releases the lock
        $this->unlock($resource);

        if (LOCK_EX === $operation) {
            if ($this->isLocked()) {
                return false;
            }

            $this->setExclusiveLock($resource);
        } elseif(LOCK_SH === $operation) {
            if ($this->hasExclusiveLock()) {
                return false;
            }
            
            $this->addSharedLock($resource);
        }

        return true;
    }

    /**
     * Removes lock from file acquired by given resource
     * 
     * @param   resource|vfsStreamWrapper $resource
     * @see     https://github.com/mikey179/vfsStream/issues/40
     */
    public function unlock($resource) {
        if ($this->hasExclusiveLock($resource)) {
            $this->exclusiveLock = null;
        }
        if ($this->hasSharedLock($resource)) {
            unset($this->sharedLock[$this->getResourceId($resource)]);
        }
    }

    /**
     * Set exlusive lock on file by given resource
     *
     * @param   resource|vfsStreamWrapper $resource
     * @see     https://github.com/mikey179/vfsStream/issues/40
     */
    protected function setExclusiveLock($resource) {
        $this->exclusiveLock = $this->getResourceId($resource);
    }

    /**
     * Add shared lock on file by given resource
     *
     * @param   resource|vfsStreamWrapper $resource
     * @see     https://github.com/mikey179/vfsStream/issues/40
     */
    protected function addSharedLock($resource) {
        $this->sharedLock[$this->getResourceId($resource)] = true;
    }

    /**
     * checks whether file is locked
     *
     * @param   resource|vfsStreamWrapper $resource
     * @return  bool
     * @since   0.10.0
     * @see     https://github.com/mikey179/vfsStream/issues/6
     * @see     https://github.com/mikey179/vfsStream/issues/40
     */
    public function isLocked($resource = null)
    {
        return $this->hasSharedLock($resource) || $this->hasExclusiveLock($resource);
    }

    /**
     * checks whether file is locked in shared mode
     *
     * @param   resource|vfsStreamWrapper $resource
     * @return  bool
     * @since   0.10.0
     * @see     https://github.com/mikey179/vfsStream/issues/6
     * @see     https://github.com/mikey179/vfsStream/issues/40
     */
    public function hasSharedLock($resource = null)
    {
        if (null !== $resource) {
            return isset($this->sharedLock[$this->getResourceId($resource)]);
        }

        return !empty($this->sharedLock);
    }

    /**
     * Returns unique resource id
     *
     * @param   resource|vfsStreamWrapper $resource
     * @return  string
     * @see     https://github.com/mikey179/vfsStream/issues/40
     */
    public function getResourceId($resource) {
        if (is_resource($resource)) {
            $data = stream_get_meta_data($resource);
            $resource = $data['wrapper_data'];
        }

        return spl_object_hash($resource);
    }

    /**
     * checks whether file is locked in exclusive mode
     *
     * @param   resource|vfsStreamWrapper $resource
     * @return  bool
     * @since   0.10.0
     * @see     https://github.com/mikey179/vfsStream/issues/6
     * @see     https://github.com/mikey179/vfsStream/issues/40
     */
    public function hasExclusiveLock($resource = null)
    {
        if (null !== $resource) {
            return $this->exclusiveLock === $this->getResourceId($resource);
        }

        return null !== $this->exclusiveLock;
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Test for org\bovigo\vfs\vfsStream.
 *
 * @since  0.9.0
 * @group  issue_5
 */
class vfsStreamResolveIncludePathTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * include path to restore after test run
     *
     * @var  string
     */
    protected $backupIncludePath;

    /**
     * set up test environment
     */
    public function setUp()
    {
        $this->backupIncludePath = get_include_path();
        vfsStream::setup();
        mkdir('vfs://root/a/path', 0777, true);
        set_include_path('vfs://root/a' . PATH_SEPARATOR . $this->backupIncludePath);
    }

    /**
     * clean up test environment
     */
    public function tearDown()
    {
        set_include_path($this->backupIncludePath);
    }

    /**
     * @test
     */
    public function knownFileCanBeResolved()
    {
        file_put_contents('vfs://root/a/path/knownFile.php', '<?php ?>');
        $this->assertEquals('vfs://root/a/path/knownFile.php', stream_resolve_include_path('path/knownFile.php'));
    }

    /**
     * @test
     */
    public function unknownFileCanNotBeResolvedYieldsFalse()
    {
        $this->assertFalse(@stream_resolve_include_path('path/unknownFile.php'));
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Test for org\bovigo\vfs\vfsStreamWrapper.
 */
abstract class vfsStreamWrapperBaseTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * root directory
     *
     * @var  vfsStreamDirectory
     */
    protected $foo;
    /**
     * URL of root directory
     *
     * @var  string
     */
    protected $fooURL;
    /**
     * sub directory
     *
     * @var  vfsStreamDirectory
     */
    protected $bar;
    /**
     * URL of sub directory
     *
     * @var  string
     */
    protected $barURL;
    /**
     * a file
     *
     * @var  vfsStreamFile
     */
    protected $baz1;
    /**
     * URL of file 1
     *
     * @var  string
     */
    protected $baz1URL;
    /**
     * another file
     *
     * @var  vfsStreamFile
     */
    protected $baz2;
    /**
     * URL of file 2
     *
     * @var  string
     */
    protected $baz2URL;

    /**
     * set up test environment
     */
    public function setUp()
    {
        $this->fooURL  = vfsStream::url('foo');
        $this->barURL  = vfsStream::url('foo/bar');
        $this->baz1URL = vfsStream::url('foo/bar/baz1');
        $this->baz2URL = vfsStream::url('foo/baz2');
        $this->foo     = new vfsStreamDirectory('foo');
        $this->bar     = new vfsStreamDirectory('bar');
        $this->baz1    = vfsStream::newFile('baz1')
                                  ->lastModified(300)
                                  ->lastAccessed(300)
                                  ->lastAttributeModified(300)
                                  ->withContent('baz 1');
        $this->baz2    = vfsStream::newFile('baz2')
                                  ->withContent('baz2')
                                  ->lastModified(400)
                                  ->lastAccessed(400)
                                  ->lastAttributeModified(400);
        $this->bar->addChild($this->baz1);
        $this->foo->addChild($this->bar);
        $this->foo->addChild($this->baz2);
        $this->foo->lastModified(100)
                  ->lastAccessed(100)
                  ->lastAttributeModified(100);
        $this->bar->lastModified(200)
                  ->lastAccessed(100)
                  ->lastAttributeModified(100);
        vfsStreamWrapper::register();
        vfsStreamWrapper::setRoot($this->foo);
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Test for org\bovigo\vfs\vfsStreamDirectory.
 */
class vfsStreamDirectoryTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * instance to test
     *
     * @var  vfsStreamDirectory
     */
    protected $dir;

    /**
     * set up test environment
     */
    public function setUp()
    {
        $this->dir = new vfsStreamDirectory('foo');
    }

    /**
     * assure that a directory seperator inside the name throws an exception
     *
     * @test
     * @expectedException  org\bovigo\vfs\vfsStreamException
     */
    public function invalidCharacterInName()
    {
        $dir = new vfsStreamDirectory('foo/bar');
    }

    /**
     * test default values and methods
     *
     * @test
     */
    public function defaultValues()
    {
        $this->assertEquals(vfsStreamContent::TYPE_DIR, $this->dir->getType());
        $this->assertEquals('foo', $this->dir->getName());
        $this->assertTrue($this->dir->appliesTo('foo'));
        $this->assertTrue($this->dir->appliesTo('foo/bar'));
        $this->assertFalse($this->dir->appliesTo('bar'));
        $this->assertEquals(array(), $this->dir->getChildren());
    }

    /**
     * test renaming the directory
     *
     * @test
     */
    public function rename()
    {
        $this->dir->rename('bar');
        $this->assertEquals('bar', $this->dir->getName());
        $this->assertFalse($this->dir->appliesTo('foo'));
        $this->assertFalse($this->dir->appliesTo('foo/bar'));
        $this->assertTrue($this->dir->appliesTo('bar'));
    }

    /**
     * renaming the directory to an invalid name throws a vfsStreamException
     *
     * @test
     * @expectedException  org\bovigo\vfs\vfsStreamException
     */
    public function renameToInvalidNameThrowsvfsStreamException()
    {
        $this->dir->rename('foo/baz');
    }

    /**
     * @test
     * @since  0.10.0
     */
    public function hasNoChildrenByDefault()
    {
        $this->assertFalse($this->dir->hasChildren());
    }

    /**
     * @test
     * @since  0.10.0
     */
    public function hasChildrenReturnsTrueIfAtLeastOneChildPresent()
    {
        $mockChild = $this->getMock('org\\bovigo\\vfs\\vfsStreamContent');
        $mockChild->expects($this->any())
                  ->method('appliesTo')
                  ->will($this->returnValue(false));
        $mockChild->expects($this->any())
                  ->method('getName')
                  ->will($this->returnValue('baz'));
        $this->dir->addChild($mockChild);
        $this->assertTrue($this->dir->hasChildren());
    }

    /**
     * @test
     */
    public function hasChildReturnsFalseForNonExistingChild()
    {
        $this->assertFalse($this->dir->hasChild('bar'));
    }

    /**
     * @test
     */
    public function getChildReturnsNullForNonExistingChild()
    {
        $this->assertNull($this->dir->getChild('bar'));
    }

    /**
     * @test
     */
    public function removeChildReturnsFalseForNonExistingChild()
    {
        $this->assertFalse($this->dir->removeChild('bar'));
    }

    /**
     * @test
     */
    public function nonExistingChild()
    {
        $mockChild = $this->getMock('org\\bovigo\\vfs\\vfsStreamContent');
        $mockChild->expects($this->any())
                  ->method('appliesTo')
                  ->will($this->returnValue(false));
        $mockChild->expects($this->any())
                  ->method('getName')
                  ->will($this->returnValue('baz'));
        $this->dir->addChild($mockChild);
        $this->assertFalse($this->dir->removeChild('bar'));
    }

    /**
     * test that adding, handling and removing of a child works as expected
     *
     * @test
     */
    public function childHandling()
    {
        $mockChild = $this->getMock('org\\bovigo\\vfs\\vfsStreamContent');
        $mockChild->expects($this->any())
                  ->method('getType')
                  ->will($this->returnValue(vfsStreamContent::TYPE_FILE));
        $mockChild->expects($this->any())
                  ->method('getName')
                  ->will($this->returnValue('bar'));
        $mockChild->expects($this->any())
                  ->method('appliesTo')
                  ->with($this->equalTo('bar'))
                  ->will($this->returnValue(true));
        $mockChild->expects($this->once())
                  ->method('size')
                  ->will($this->returnValue(5));
        $this->dir->addChild($mockChild);
        $this->assertTrue($this->dir->hasChild('bar'));
        $bar = $this->dir->getChild('bar');
        $this->assertSame($mockChild, $bar);
        $this->assertEquals(array($mockChild), $this->dir->getChildren());
        $this->assertEquals(0, $this->dir->size());
        $this->assertEquals(5, $this->dir->sizeSummarized());
        $this->assertTrue($this->dir->removeChild('bar'));
        $this->assertEquals(array(), $this->dir->getChildren());
        $this->assertEquals(0, $this->dir->size());
        $this->assertEquals(0, $this->dir->sizeSummarized());
    }

    /**
     * test that adding, handling and removing of a child works as expected
     *
     * @test
     */
    public function childHandlingWithSubdirectory()
    {
        $mockChild = $this->getMock('org\\bovigo\\vfs\\vfsStreamContent');
        $mockChild->expects($this->any())
                  ->method('getType')
                  ->will($this->returnValue(vfsStreamContent::TYPE_FILE));
        $mockChild->expects($this->any())
                  ->method('getName')
                  ->will($this->returnValue('bar'));
        $mockChild->expects($this->once())
                  ->method('size')
                  ->will($this->returnValue(5));
        $subdir = new vfsStreamDirectory('subdir');
        $subdir->addChild($mockChild);
        $this->dir->addChild($subdir);
        $this->assertTrue($this->dir->hasChild('subdir'));
        $this->assertSame($subdir, $this->dir->getChild('subdir'));
        $this->assertEquals(array($subdir), $this->dir->getChildren());
        $this->assertEquals(0, $this->dir->size());
        $this->assertEquals(5, $this->dir->sizeSummarized());
        $this->assertTrue($this->dir->removeChild('subdir'));
        $this->assertEquals(array(), $this->dir->getChildren());
        $this->assertEquals(0, $this->dir->size());
        $this->assertEquals(0, $this->dir->sizeSummarized());
    }

    /**
     * dd
     *
     * @test
     * @group  regression
     * @group  bug_5
     */
    public function addChildReplacesChildWithSameName_Bug_5()
    {
        $mockChild1 = $this->getMock('org\\bovigo\\vfs\\vfsStreamContent');
        $mockChild1->expects($this->any())
                   ->method('getType')
                   ->will($this->returnValue(vfsStreamContent::TYPE_FILE));
        $mockChild1->expects($this->any())
                   ->method('getName')
                   ->will($this->returnValue('bar'));
        $mockChild2 = $this->getMock('org\\bovigo\\vfs\\vfsStreamContent');
        $mockChild2->expects($this->any())
                   ->method('getType')
                   ->will($this->returnValue(vfsStreamContent::TYPE_FILE));
        $mockChild2->expects($this->any())
                   ->method('getName')
                   ->will($this->returnValue('bar'));
        $this->dir->addChild($mockChild1);
        $this->assertTrue($this->dir->hasChild('bar'));
        $this->assertSame($mockChild1, $this->dir->getChild('bar'));
        $this->dir->addChild($mockChild2);
        $this->assertTrue($this->dir->hasChild('bar'));
        $this->assertSame($mockChild2, $this->dir->getChild('bar'));
    }

    /**
     * When testing for a nested path, verify that directory separators are respected properly
     * so that subdir1/subdir2 is not considered equal to subdir1Xsubdir2.
     *
     * @test
     * @group bug_24
     * @group regression
     */
    public function explicitTestForSeparatorWithNestedPaths_Bug_24()
    {
        $mockChild = $this->getMock('org\\bovigo\\vfs\\vfsStreamContent');
        $mockChild->expects($this->any())
                  ->method('getType')
                  ->will($this->returnValue(vfsStreamContent::TYPE_FILE));
        $mockChild->expects($this->any())
                  ->method('getName')
                  ->will($this->returnValue('bar'));

        $subdir1 = new vfsStreamDirectory('subdir1');
        $this->dir->addChild($subdir1);

        $subdir2 = new vfsStreamDirectory('subdir2');
        $subdir1->addChild($subdir2);

        $subdir2->addChild($mockChild);

        $this->assertTrue($this->dir->hasChild('subdir1'), "Level 1 path with separator exists");
        $this->assertTrue($this->dir->hasChild('subdir1/subdir2'), "Level 2 path with separator exists");
        $this->assertTrue($this->dir->hasChild('subdir1/subdir2/bar'), "Level 3 path with separator exists");
        $this->assertFalse($this->dir->hasChild('subdir1.subdir2'), "Path with period does not exist");
        $this->assertFalse($this->dir->hasChild('subdir1.subdir2/bar'), "Nested path with period does not exist");
    }


    /**
     * setting and retrieving permissions for a directory
     *
     * @test
     * @group  permissions
     */
    public function permissions()
    {
        $this->assertEquals(0777, $this->dir->getPermissions());
        $this->assertSame($this->dir, $this->dir->chmod(0755));
        $this->assertEquals(0755, $this->dir->getPermissions());
    }

    /**
     * setting and retrieving permissions for a directory
     *
     * @test
     * @group  permissions
     */
    public function permissionsSet()
    {
        $this->dir = new vfsStreamDirectory('foo', 0755);
        $this->assertEquals(0755, $this->dir->getPermissions());
        $this->assertSame($this->dir, $this->dir->chmod(0700));
        $this->assertEquals(0700, $this->dir->getPermissions());
    }

    /**
     * setting and retrieving owner of a file
     *
     * @test
     * @group  permissions
     */
    public function owner()
    {
        $this->assertEquals(vfsStream::getCurrentUser(), $this->dir->getUser());
        $this->assertTrue($this->dir->isOwnedByUser(vfsStream::getCurrentUser()));
        $this->assertSame($this->dir, $this->dir->chown(vfsStream::OWNER_USER_1));
        $this->assertEquals(vfsStream::OWNER_USER_1, $this->dir->getUser());
        $this->assertTrue($this->dir->isOwnedByUser(vfsStream::OWNER_USER_1));
    }

    /**
     * setting and retrieving owner group of a file
     *
     * @test
     * @group  permissions
     */
    public function group()
    {
        $this->assertEquals(vfsStream::getCurrentGroup(), $this->dir->getGroup());
        $this->assertTrue($this->dir->isOwnedByGroup(vfsStream::getCurrentGroup()));
        $this->assertSame($this->dir, $this->dir->chgrp(vfsStream::GROUP_USER_1));
        $this->assertEquals(vfsStream::GROUP_USER_1, $this->dir->getGroup());
        $this->assertTrue($this->dir->isOwnedByGroup(vfsStream::GROUP_USER_1));
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Test for quota related functionality of org\bovigo\vfs\vfsStreamWrapper.
 *
 * @group  issue_35
 */
class vfsStreamWrapperQuotaTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * access to root
     *
     * @type  vfsStreamDirectory
     */
    private $root;

    /**
     * set up test environment
     */
    public function setUp()
    {
        $this->root = vfsStream::setup();
        vfsStream::setQuota(10);
    }

    /**
     * @test
     */
    public function writeLessThanQuotaWritesEverything()
    {
        $this->assertEquals(9, file_put_contents(vfsStream::url('root/file.txt'), '123456789'));
        $this->assertEquals('123456789', $this->root->getChild('file.txt')->getContent());
    }

    /**
     * @test
     */
    public function writeUpToQotaWritesEverything()
    {
        $this->assertEquals(10, file_put_contents(vfsStream::url('root/file.txt'), '1234567890'));
        $this->assertEquals('1234567890', $this->root->getChild('file.txt')->getContent());
    }

    /**
     * @test
     */
    public function writeMoreThanQotaWritesOnlyUpToQuota()
    {
        try {
            file_put_contents(vfsStream::url('root/file.txt'), '12345678901');
        } catch (\PHPUnit_Framework_Error $e) {
            $this->assertEquals('file_put_contents(): Only 10 of 11 bytes written, possibly out of free disk space',
                                $e->getMessage()
            );
        }

        $this->assertEquals('1234567890', $this->root->getChild('file.txt')->getContent());
    }

    /**
     * @test
     */
    public function considersAllFilesForQuota()
    {
        vfsStream::newFile('foo.txt')
                 ->withContent('foo')
                 ->at(vfsStream::newDirectory('bar')
                               ->at($this->root)
                   );
        try {
            file_put_contents(vfsStream::url('root/file.txt'), '12345678901');
        } catch (\PHPUnit_Framework_Error $e) {
            $this->assertEquals('file_put_contents(): Only 7 of 11 bytes written, possibly out of free disk space',
                                $e->getMessage()
            );
        }

        $this->assertEquals('1234567', $this->root->getChild('file.txt')->getContent());
    }

    /**
     * @test
     * @group  issue_33
     */
    public function truncateToLessThanQuotaWritesEverything()
    {
        if (version_compare(PHP_VERSION, '5.4.0', '<')) {
            $this->markTestSkipped('Requires PHP 5.4');
        }

        $fp = fopen(vfsStream::url('root/file.txt'), 'w+');
        $this->assertTrue(ftruncate($fp, 9));
        fclose($fp);
        $this->assertEquals(9,
                            $this->root->getChild('file.txt')->size()
        );
        $this->assertEquals("\0\0\0\0\0\0\0\0\0",
                            $this->root->getChild('file.txt')->getContent()
        );
    }

    /**
     * @test
     * @group  issue_33
     */
    public function truncateUpToQotaWritesEverything()
    {
        if (version_compare(PHP_VERSION, '5.4.0', '<')) {
            $this->markTestSkipped('Requires PHP 5.4');
        }

        $fp = fopen(vfsStream::url('root/file.txt'), 'w+');
        $this->assertTrue(ftruncate($fp, 10));
        fclose($fp);
        $this->assertEquals(10,
                            $this->root->getChild('file.txt')->size()
        );
        $this->assertEquals("\0\0\0\0\0\0\0\0\0\0",
                            $this->root->getChild('file.txt')->getContent()
        );
    }

    /**
     * @test
     * @group  issue_33
     */
    public function truncateToMoreThanQotaWritesOnlyUpToQuota()
    {
        if (version_compare(PHP_VERSION, '5.4.0', '<')) {
            $this->markTestSkipped('Requires PHP 5.4');
        }

        $fp = fopen(vfsStream::url('root/file.txt'), 'w+');
        $this->assertTrue(ftruncate($fp, 11));
        fclose($fp);
        $this->assertEquals(10,
                            $this->root->getChild('file.txt')->size()
        );
        $this->assertEquals("\0\0\0\0\0\0\0\0\0\0",
                            $this->root->getChild('file.txt')->getContent()
        );
    }

    /**
     * @test
     * @group  issue_33
     */
    public function truncateConsidersAllFilesForQuota()
    {
        if (version_compare(PHP_VERSION, '5.4.0', '<')) {
            $this->markTestSkipped('Requires PHP 5.4');
        }

        vfsStream::newFile('bar.txt')
                 ->withContent('bar')
                 ->at(vfsStream::newDirectory('bar')
                               ->at($this->root)
                   );
        $fp = fopen(vfsStream::url('root/file.txt'), 'w+');
        $this->assertTrue(ftruncate($fp, 11));
        fclose($fp);
        $this->assertEquals(7,
                            $this->root->getChild('file.txt')->size()
        );
        $this->assertEquals("\0\0\0\0\0\0\0",
                            $this->root->getChild('file.txt')->getContent()
        );
    }

    /**
     * @test
     * @group  issue_33
     */
    public function canNotTruncateToGreaterLengthWhenDiscQuotaReached()
    {
        if (version_compare(PHP_VERSION, '5.4.0', '<')) {
            $this->markTestSkipped('Requires PHP 5.4');
        }

        vfsStream::newFile('bar.txt')
                 ->withContent('1234567890')
                 ->at(vfsStream::newDirectory('bar')
                               ->at($this->root)
                   );
        $fp = fopen(vfsStream::url('root/file.txt'), 'w+');
        $this->assertFalse(ftruncate($fp, 11));
        fclose($fp);
        $this->assertEquals(0,
                            $this->root->getChild('file.txt')->size()
        );
        $this->assertEquals('',
                            $this->root->getChild('file.txt')->getContent()
        );
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Test that using windows directory separator works correct.
 *
 * @since  0.9.0
 * @group  issue_8
 */
class vfsStreamWrapperDirSeparatorTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * root diretory
     *
     * @var  vfsStreamDirectory
     */
    protected $root;

    /**
     * set up test environment
     */
    public function setUp()
    {
        $this->root = vfsStream::setup();
    }

    /**
     * @test
     */
    public function fileCanBeAccessedUsingWinDirSeparator()
    {
        vfsStream::newFile('foo/bar/baz.txt')
                 ->at($this->root)
                 ->withContent('test');
        $this->assertEquals('test', file_get_contents('vfs://root/foo\bar\baz.txt'));
    }


    /**
     * @test
     */
    public function directoryCanBeCreatedUsingWinDirSeparator()
    {
        mkdir('vfs://root/dir\bar\foo', true, 0777);
        $this->assertTrue($this->root->hasChild('dir'));
        $this->assertTrue($this->root->getChild('dir')->hasChild('bar'));
        $this->assertTrue($this->root->getChild('dir/bar')->hasChild('foo'));
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs\visitor;
use org\bovigo\vfs\vfsStreamDirectory;
use org\bovigo\vfs\vfsStreamFile;
/**
 * Test for org\bovigo\vfs\visitor\vfsStreamAbstractVisitor.
 *
 * @since  0.10.0
 * @see    https://github.com/mikey179/vfsStream/issues/10
 * @group  issue_10
 */
class vfsStreamAbstractVisitorTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * instance to test
     *
     * @var  vfsStreamAbstractVisitor
     */
    protected $abstractVisitor;

    /**
     * set up test environment
     */
    public function setUp()
    {
        $this->abstractVisitor = $this->getMock('org\\bovigo\\vfs\\visitor\\vfsStreamAbstractVisitor',
                                                array('visitFile', 'visitDirectory')
                                 );
    }

    /**
     * @test
     * @expectedException  \InvalidArgumentException
     */
    public function visitThrowsInvalidArgumentExceptionOnUnknownContentType()
    {
        $mockContent = $this->getMock('org\\bovigo\\vfs\\vfsStreamContent');
        $mockContent->expects($this->any())
                    ->method('getType')
                    ->will($this->returnValue('invalid'));
        $this->assertSame($this->abstractVisitor,
                          $this->abstractVisitor->visit($mockContent)
        );
    }

    /**
     * @test
     */
    public function visitWithFileCallsVisitFile()
    {
        $file = new vfsStreamFile('foo.txt');
        $this->abstractVisitor->expects($this->once())
                              ->method('visitFile')
                              ->with($this->equalTo($file));
        $this->assertSame($this->abstractVisitor,
                          $this->abstractVisitor->visit($file)
        );
    }

    /**
     * @test
     */
    public function visitWithDirectoryCallsVisitDirectory()
    {
        $dir = new vfsStreamDirectory('bar');
        $this->abstractVisitor->expects($this->once())
                              ->method('visitDirectory')
                              ->with($this->equalTo($dir));
        $this->assertSame($this->abstractVisitor,
                          $this->abstractVisitor->visit($dir)
        );
    }
}
?>
<?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs\visitor;
use org\bovigo\vfs\vfsStream;
use org\bovigo\vfs\vfsStreamDirectory;
use org\bovigo\vfs\vfsStreamFile;
/**
 * Test for org\bovigo\vfs\visitor\vfsStreamPrintVisitor.
 *
 * @since  0.10.0
 * @see    https://github.com/mikey179/vfsStream/issues/10
 * @group  issue_10
 */
class vfsStreamPrintVisitorTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * @test
     * @expectedException  \InvalidArgumentException
     */
    public function constructWithNonResourceThrowsInvalidArgumentException()
    {
        new vfsStreamPrintVisitor('invalid');
    }

    /**
     * @test
     * @expectedException  \InvalidArgumentException
     */
    public function constructWithNonStreamResourceThrowsInvalidArgumentException()
    {
        new vfsStreamPrintVisitor(xml_parser_create());
    }

    /**
     * @test
     */
    public function visitFileWritesFileNameToStream()
    {
        $output       = vfsStream::newFile('foo.txt')
                                       ->at(vfsStream::setup());
        $printVisitor = new vfsStreamPrintVisitor(fopen('vfs://root/foo.txt', 'wb'));
        $this->assertSame($printVisitor,
                          $printVisitor->visitFile(vfsStream::newFile('bar.txt'))
        );
        $this->assertEquals("- bar.txt\n", $output->getContent());
    }

    /**
     * @test
     */
    public function visitDirectoryWritesDirectoryNameToStream()
    {
        $output       = vfsStream::newFile('foo.txt')
                                       ->at(vfsStream::setup());
        $printVisitor = new vfsStreamPrintVisitor(fopen('vfs://root/foo.txt', 'wb'));
        $this->assertSame($printVisitor,
                          $printVisitor->visitDirectory(vfsStream::newDirectory('baz'))
        );
        $this->assertEquals("- baz\n", $output->getContent());
    }

    /**
     * @test
     */
    public function visitRecursiveDirectoryStructure()
    {
        $root         = vfsStream::setup('root',
                                         null,
                                         array('test' => array('foo'     => array('test.txt' => 'hello'),
                                                               'baz.txt' => 'world'
                                                           ),
                                               'foo.txt' => ''
                                         )
                        );
        $printVisitor = new vfsStreamPrintVisitor(fopen('vfs://root/foo.txt', 'wb'));
        $this->assertSame($printVisitor,
                          $printVisitor->visitDirectory($root)
        );
        $this->assertEquals("- root\n  - test\n    - foo\n      - test.txt\n    - baz.txt\n  - foo.txt\n", file_get_contents('vfs://root/foo.txt'));
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs\visitor;
use org\bovigo\vfs\vfsStream;
/**
 * Test for org\bovigo\vfs\visitor\vfsStreamStructureVisitor.
 *
 * @since  0.10.0
 * @see    https://github.com/mikey179/vfsStream/issues/10
 * @group  issue_10
 */
class vfsStreamStructureVisitorTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * @test
     */
    public function visitFileCreatesStructureForFile()
    {
        $structureVisitor = new vfsStreamStructureVisitor();
        $this->assertEquals(array('foo.txt' => 'test'),
                            $structureVisitor->visitFile(vfsStream::newFile('foo.txt')
                                                                  ->withContent('test')
                                               )
                                             ->getStructure()
        );
    }

    /**
     * @test
     */
    public function visitDirectoryCreatesStructureForDirectory()
    {
        $structureVisitor = new vfsStreamStructureVisitor();
        $this->assertEquals(array('baz' => array()),
                            $structureVisitor->visitDirectory(vfsStream::newDirectory('baz'))
                                             ->getStructure()
        );
    }

    /**
     * @test
     */
    public function visitRecursiveDirectoryStructure()
    {
        $root         = vfsStream::setup('root',
                                         null,
                                         array('test' => array('foo'     => array('test.txt' => 'hello'),
                                                               'baz.txt' => 'world'
                                                         ),
                                               'foo.txt' => ''
                                         )
                        );
        $structureVisitor = new vfsStreamStructureVisitor();
        $this->assertEquals(array('root' => array('test' => array('foo'     => array('test.txt' => 'hello'),
                                                                  'baz.txt' => 'world'
                                                                               ),
                                                                  'foo.txt' => ''
                                            ),
                            ),
                            $structureVisitor->visitDirectory($root)
                                             ->getStructure()
        );
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Test for org\bovigo\vfs\vfsStreamFile.
 */
class vfsStreamFileTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * instance to test
     *
     * @var  vfsStreamFile
     */
    protected $file;

    /**
     * set up test environment
     */
    public function setUp()
    {
        $this->file = new vfsStreamFile('foo');
    }

    /**
     * test default values and methods
     *
     * @test
     */
    public function defaultValues()
    {
        $this->assertEquals(vfsStreamContent::TYPE_FILE, $this->file->getType());
        $this->assertEquals('foo', $this->file->getName());
        $this->assertTrue($this->file->appliesTo('foo'));
        $this->assertFalse($this->file->appliesTo('foo/bar'));
        $this->assertFalse($this->file->appliesTo('bar'));
    }

    /**
     * test setting and getting the content of a file
     *
     * @test
     */
    public function content()
    {
        $this->assertNull($this->file->getContent());
        $this->assertSame($this->file, $this->file->setContent('bar'));
        $this->assertEquals('bar', $this->file->getContent());
        $this->assertSame($this->file, $this->file->withContent('baz'));
        $this->assertEquals('baz', $this->file->getContent());
    }

    /**
     * test renaming the directory
     *
     * @test
     */
    public function rename()
    {
        $this->file->rename('bar');
        $this->assertEquals('bar', $this->file->getName());
        $this->assertFalse($this->file->appliesTo('foo'));
        $this->assertFalse($this->file->appliesTo('foo/bar'));
        $this->assertTrue($this->file->appliesTo('bar'));
    }

    /**
     * test reading contents from the file
     *
     * @test
     */
    public function readEmptyFile()
    {
        $this->assertTrue($this->file->eof());
        $this->assertEquals(0, $this->file->size());
        $this->assertEquals('', $this->file->read(5));
        $this->assertEquals(5, $this->file->getBytesRead());
        $this->assertTrue($this->file->eof());
    }

    /**
     * test reading contents from the file
     *
     * @test
     */
    public function read()
    {
        $this->file->setContent('foobarbaz');
        $this->assertFalse($this->file->eof());
        $this->assertEquals(9, $this->file->size());
        $this->assertEquals('foo', $this->file->read(3));
        $this->assertEquals(3, $this->file->getBytesRead());
        $this->assertFalse($this->file->eof());
        $this->assertEquals(9, $this->file->size());
        $this->assertEquals('bar', $this->file->read(3));
        $this->assertEquals(6, $this->file->getBytesRead());
        $this->assertFalse($this->file->eof());
        $this->assertEquals(9, $this->file->size());
        $this->assertEquals('baz', $this->file->read(3));
        $this->assertEquals(9, $this->file->getBytesRead());
        $this->assertEquals(9, $this->file->size());
        $this->assertTrue($this->file->eof());
        $this->assertEquals('', $this->file->read(3));
    }

    /**
     * test seeking to offset
     *
     * @test
     */
    public function seekEmptyFile()
    {
        $this->assertFalse($this->file->seek(0, 55));
        $this->assertTrue($this->file->seek(0, SEEK_SET));
        $this->assertEquals(0, $this->file->getBytesRead());
        $this->assertTrue($this->file->seek(5, SEEK_SET));
        $this->assertEquals(5, $this->file->getBytesRead());
        $this->assertTrue($this->file->seek(0, SEEK_CUR));
        $this->assertEquals(5, $this->file->getBytesRead());
        $this->assertTrue($this->file->seek(2, SEEK_CUR));
        $this->assertEquals(7, $this->file->getBytesRead());
        $this->assertTrue($this->file->seek(0, SEEK_END));
        $this->assertEquals(0, $this->file->getBytesRead());
        $this->assertTrue($this->file->seek(2, SEEK_END));
        $this->assertEquals(2, $this->file->getBytesRead());
    }

    /**
     * test seeking to offset
     *
     * @test
     */
    public function seekRead()
    {
        $this->file->setContent('foobarbaz');
        $this->assertFalse($this->file->seek(0, 55));
        $this->assertTrue($this->file->seek(0, SEEK_SET));
        $this->assertEquals('foobarbaz', $this->file->readUntilEnd());
        $this->assertEquals(0, $this->file->getBytesRead());
        $this->assertTrue($this->file->seek(5, SEEK_SET));
        $this->assertEquals('rbaz', $this->file->readUntilEnd());
        $this->assertEquals(5, $this->file->getBytesRead());
        $this->assertTrue($this->file->seek(0, SEEK_CUR));
        $this->assertEquals('rbaz', $this->file->readUntilEnd());
        $this->assertEquals(5, $this->file->getBytesRead(), 5);
        $this->assertTrue($this->file->seek(2, SEEK_CUR));
        $this->assertEquals('az', $this->file->readUntilEnd());
        $this->assertEquals(7, $this->file->getBytesRead());
        $this->assertTrue($this->file->seek(0, SEEK_END));
        $this->assertEquals('', $this->file->readUntilEnd());
        $this->assertEquals(9, $this->file->getBytesRead());
        $this->assertTrue($this->file->seek(2, SEEK_END));
        $this->assertEquals('', $this->file->readUntilEnd());
        $this->assertEquals(11, $this->file->getBytesRead());
    }

    /**
     * test writing data into the file
     *
     * @test
     */
    public function writeEmptyFile()
    {
        $this->assertEquals(3, $this->file->write('foo'));
        $this->assertEquals('foo', $this->file->getContent());
        $this->assertEquals(3, $this->file->size());
        $this->assertEquals(3, $this->file->write('bar'));
        $this->assertEquals('foobar', $this->file->getContent());
        $this->assertEquals(6, $this->file->size());
    }

    /**
     * test writing data into the file
     *
     * @test
     */
    public function write()
    {
        $this->file->setContent('foobarbaz');
        $this->assertTrue($this->file->seek(3, SEEK_SET));
        $this->assertEquals(3, $this->file->write('foo'));
        $this->assertEquals('foofoobaz', $this->file->getContent());
        $this->assertEquals(9, $this->file->size());
        $this->assertEquals(3, $this->file->write('bar'));
        $this->assertEquals('foofoobar', $this->file->getContent());
        $this->assertEquals(9, $this->file->size());
    }

    /**
     * setting and retrieving permissions for a file
     *
     * @test
     * @group  permissions
     */
    public function permissions()
    {
        $this->assertEquals(0666, $this->file->getPermissions());
        $this->assertSame($this->file, $this->file->chmod(0644));
        $this->assertEquals(0644, $this->file->getPermissions());
    }

    /**
     * setting and retrieving permissions for a file
     *
     * @test
     * @group  permissions
     */
    public function permissionsSet()
    {
        $this->file = new vfsStreamFile('foo', 0644);
        $this->assertEquals(0644, $this->file->getPermissions());
        $this->assertSame($this->file, $this->file->chmod(0600));
        $this->assertEquals(0600, $this->file->getPermissions());
    }

    /**
     * setting and retrieving owner of a file
     *
     * @test
     * @group  permissions
     */
    public function owner()
    {
        $this->assertEquals(vfsStream::getCurrentUser(), $this->file->getUser());
        $this->assertTrue($this->file->isOwnedByUser(vfsStream::getCurrentUser()));
        $this->assertSame($this->file, $this->file->chown(vfsStream::OWNER_USER_1));
        $this->assertEquals(vfsStream::OWNER_USER_1, $this->file->getUser());
        $this->assertTrue($this->file->isOwnedByUser(vfsStream::OWNER_USER_1));
    }

    /**
     * setting and retrieving owner group of a file
     *
     * @test
     * @group  permissions
     */
    public function group()
    {
        $this->assertEquals(vfsStream::getCurrentGroup(), $this->file->getGroup());
        $this->assertTrue($this->file->isOwnedByGroup(vfsStream::getCurrentGroup()));
        $this->assertSame($this->file, $this->file->chgrp(vfsStream::GROUP_USER_1));
        $this->assertEquals(vfsStream::GROUP_USER_1, $this->file->getGroup());
        $this->assertTrue($this->file->isOwnedByGroup(vfsStream::GROUP_USER_1));
    }

    /**
     * @test
     * @group  issue_33
     * @since  1.1.0
     */
    public function truncateRemovesSuperflouosContent()
    {
        $this->assertEquals(11, $this->file->write("lorem ipsum"));
        $this->assertTrue($this->file->truncate(5));
        $this->assertEquals(5, $this->file->size());
        $this->assertEquals('lorem', $this->file->getContent());
    }

    /**
     * @test
     * @group  issue_33
     * @since  1.1.0
     */
    public function truncateToGreaterSizeAddsZeroBytes()
    {
        $this->assertEquals(11, $this->file->write("lorem ipsum"));
        $this->assertTrue($this->file->truncate(25));
        $this->assertEquals(25, $this->file->size());
        $this->assertEquals("lorem ipsum\0\0\0\0\0\0\0\0\0\0\0\0\0\0", $this->file->getContent());
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Test for flock() implementation.
 *
 * @package     bovigo_vfs
 * @subpackage  test
 * @since       0.10.0
 * @see         https://github.com/mikey179/vfsStream/issues/6
 * @group       issue_6
 */
class vfsStreamWrapperFlockTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * root directory
     *
     * @var  vfsStreamContainer
     */
    protected $root;

    /**
     * set up test environment
     */
    public function setUp()
    {
        $this->root = vfsStream::setup();
    }

    /**
     * @test
     */
    public function fileIsNotLockedByDefault()
    {
        $this->assertFalse(vfsStream::newFile('foo.txt')->isLocked());
    }

    /**
     * @test
     */
    public function streamIsNotLockedByDefault()
    {
        file_put_contents(vfsStream::url('root/foo.txt'), 'content');
        $this->assertFalse($this->root->getChild('foo.txt')->isLocked());
    }

    /**
     * @test
     */
    public function canAquireSharedLock()
    {
        $file = vfsStream::newFile('foo.txt')->at($this->root);
        $fp   = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $this->assertTrue(flock($fp, LOCK_SH));
        $this->assertTrue($file->isLocked());
        $this->assertTrue($file->hasSharedLock());
        $this->assertFalse($file->hasExclusiveLock());
        fclose($fp);

    }

    /**
     * @test
     */
    public function canAquireSharedLockWithNonBlockingFlockCall()
    {
        $file = vfsStream::newFile('foo.txt')->at($this->root);
        $fp   = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $this->assertTrue(flock($fp, LOCK_SH | LOCK_NB));
        $this->assertTrue($file->isLocked());
        $this->assertTrue($file->hasSharedLock());
        $this->assertFalse($file->hasExclusiveLock());
        fclose($fp);

    }

    /**
     * @test
     */
    public function canAquireEclusiveLock()
    {
        $file = vfsStream::newFile('foo.txt')->at($this->root);
        $fp   = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $this->assertTrue(flock($fp, LOCK_EX));
        $this->assertTrue($file->isLocked());
        $this->assertFalse($file->hasSharedLock());
        $this->assertTrue($file->hasExclusiveLock());
        fclose($fp);
    }

    /**
     * @test
     */
    public function canAquireEclusiveLockWithNonBlockingFlockCall()
    {
        $file = vfsStream::newFile('foo.txt')->at($this->root);
        $fp   = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $this->assertTrue(flock($fp, LOCK_EX | LOCK_NB));
        $this->assertTrue($file->isLocked());
        $this->assertFalse($file->hasSharedLock());
        $this->assertTrue($file->hasExclusiveLock());
        fclose($fp);
    }

    /**
     * @test
     */
    public function canRemoveLock()
    {
        $file = vfsStream::newFile('foo.txt')->at($this->root);
        $fp   = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $file->lock($fp, LOCK_EX);
        $this->assertTrue(flock($fp, LOCK_UN));
        $this->assertFalse($file->isLocked());
        $this->assertFalse($file->hasSharedLock());
        $this->assertFalse($file->hasExclusiveLock());
        fclose($fp);
    }

    /**
     * @see    https://github.com/mikey179/vfsStream/issues/40
     * @test
     * @group  issue_40
     */
    public function canRemoveLockWhenNotLocked()
    {
        $file = vfsStream::newFile('foo.txt')->at($this->root);
        $fp   = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $this->assertTrue(flock($fp, LOCK_UN));
        $this->assertFalse($file->isLocked());
        $this->assertFalse($file->hasSharedLock());
        $this->assertFalse($file->hasSharedLock($fp));
        $this->assertFalse($file->hasExclusiveLock());
        $this->assertFalse($file->hasExclusiveLock($fp));
        fclose($fp);
    }

    /**
     * @see    https://github.com/mikey179/vfsStream/issues/40
     * @test
     * @group  issue_40
     */
    public function canRemoveSharedLockWithoutRemovingSharedLockOnOtherFileHandler()
    {
        $file = vfsStream::newFile('foo.txt')->at($this->root);
        $fp1   = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $fp2   = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $file->lock($fp1, LOCK_SH);
        $file->lock($fp2, LOCK_SH);
        $this->assertTrue(flock($fp1, LOCK_UN));
        $this->assertTrue($file->hasSharedLock());
        $this->assertFalse($file->hasSharedLock($fp1));
        $this->assertTrue($file->hasSharedLock($fp2));
        fclose($fp1);
        fclose($fp2);
    }

    /**
     * @see    https://github.com/mikey179/vfsStream/issues/40
     * @test
     * @group  issue_40
     */
    public function canNotRemoveSharedLockAcquiredOnOtherFileHandler()
    {
        $file = vfsStream::newFile('foo.txt')->at($this->root);
        $fp1   = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $fp2   = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $file->lock($fp1, LOCK_SH);
        $this->assertTrue(flock($fp2, LOCK_UN));
        $this->assertTrue($file->isLocked());
        $this->assertTrue($file->hasSharedLock());
        $this->assertFalse($file->hasExclusiveLock());
        fclose($fp1);
        fclose($fp2);
    }

    /**
     * @see    https://github.com/mikey179/vfsStream/issues/40
     * @test
     * @group  issue_40
     */
    public function canNotRemoveExlusiveLockAcquiredOnOtherFileHandler()
    {
        $file = vfsStream::newFile('foo.txt')->at($this->root);
        $fp1   = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $fp2   = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $file->lock($fp1, LOCK_EX);
        $this->assertTrue(flock($fp2, LOCK_UN));
        $this->assertTrue($file->isLocked());
        $this->assertFalse($file->hasSharedLock());
        $this->assertTrue($file->hasExclusiveLock());
        fclose($fp1);
        fclose($fp2);
    }

    /**
     * @test
     */
    public function canRemoveLockWithNonBlockingFlockCall()
    {
        $file = vfsStream::newFile('foo.txt')->at($this->root);
        $fp   = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $file->lock($fp, LOCK_EX);
        $this->assertTrue(flock($fp, LOCK_UN | LOCK_NB));
        $this->assertFalse($file->isLocked());
        $this->assertFalse($file->hasSharedLock());
        $this->assertFalse($file->hasExclusiveLock());
        fclose($fp);
    }

    /**
     * @see    https://github.com/mikey179/vfsStream/issues/40
     * @test
     * @group  issue_40
     */
    public function canNotAquireExclusiveLockIfAlreadyExclusivelyLockedOnOtherFileHandler()
    {
        $file = vfsStream::newFile('foo.txt')->at($this->root);
        $fp1   = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $fp2   = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $file->lock($fp1, LOCK_EX);
        $this->assertFalse(flock($fp2, LOCK_EX + LOCK_NB));
        $this->assertTrue($file->isLocked());
        $this->assertFalse($file->hasSharedLock());
        $this->assertTrue($file->hasExclusiveLock());
        $this->assertTrue($file->hasExclusiveLock($fp1));
        $this->assertFalse($file->hasExclusiveLock($fp2));
        fclose($fp1);
        fclose($fp2);
    }

    /**
     * @see    https://github.com/mikey179/vfsStream/issues/40
     * @test
     * @group  issue_40
     */
    public function canAquireExclusiveLockIfAlreadySelfExclusivelyLocked()
    {
        $file = vfsStream::newFile('foo.txt')->at($this->root);
        $fp   = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $file->lock($fp, LOCK_EX);
        $this->assertTrue(flock($fp, LOCK_EX + LOCK_NB));
        $this->assertTrue($file->isLocked());
        $this->assertFalse($file->hasSharedLock());
        $this->assertTrue($file->hasExclusiveLock());
        fclose($fp);
    }

    /**
     * @see    https://github.com/mikey179/vfsStream/issues/40
     * @test
     * @group  issue_40
     */
    public function canNotAquireExclusiveLockIfAlreadySharedLockedOnOtherFileHandler()
    {
        $file = vfsStream::newFile('foo.txt')->at($this->root);
        $fp1   = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $fp2   = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $file->lock($fp1, LOCK_SH);
        $this->assertFalse(flock($fp2, LOCK_EX));
        $this->assertTrue($file->isLocked());
        $this->assertTrue($file->hasSharedLock());
        $this->assertFalse($file->hasExclusiveLock());
        fclose($fp1);
        fclose($fp2);
    }

    /**
     * @see    https://github.com/mikey179/vfsStream/issues/40
     * @test
     * @group  issue_40
     */
    public function canAquireExclusiveLockIfAlreadySelfSharedLocked()
    {
        $file = vfsStream::newFile('foo.txt')->at($this->root);
        $fp   = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $file->lock($fp, LOCK_SH);
        $this->assertTrue(flock($fp, LOCK_EX));
        $this->assertTrue($file->isLocked());
        $this->assertFalse($file->hasSharedLock());
        $this->assertTrue($file->hasExclusiveLock());
        fclose($fp);
    }

    /**
     * @see    https://github.com/mikey179/vfsStream/issues/40
     * @test
     * @group  issue_40
     */
    public function canNotAquireSharedLockIfAlreadyExclusivelyLockedOnOtherFileHandler()
    {
        $file = vfsStream::newFile('foo.txt')->at($this->root);
        $fp1   = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $fp2   = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $file->lock($fp1, LOCK_EX);
        $this->assertFalse(flock($fp2, LOCK_SH + LOCK_NB));
        $this->assertTrue($file->isLocked());
        $this->assertFalse($file->hasSharedLock());
        $this->assertTrue($file->hasExclusiveLock());
        fclose($fp1);
        fclose($fp2);
    }

    /**
     * @see    https://github.com/mikey179/vfsStream/issues/40
     * @test
     * @group  issue_40
     */
    public function canAquireSharedLockIfAlreadySelfExclusivelyLocked()
    {
        $file = vfsStream::newFile('foo.txt')->at($this->root);
        $fp   = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $file->lock($fp, LOCK_EX);
        $this->assertTrue(flock($fp, LOCK_SH + LOCK_NB));
        $this->assertTrue($file->isLocked());
        $this->assertTrue($file->hasSharedLock());
        $this->assertFalse($file->hasExclusiveLock());
        fclose($fp);
    }

    /**
     * @see    https://github.com/mikey179/vfsStream/issues/40
     * @test
     * @group  issue_40
     */
    public function canAquireSharedLockIfAlreadySelfSharedLocked()
    {
        $file = vfsStream::newFile('foo.txt')->at($this->root);
        $fp   = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $file->lock($fp, LOCK_SH);
        $this->assertTrue(flock($fp, LOCK_SH));
        $this->assertTrue($file->isLocked());
        $this->assertTrue($file->hasSharedLock());
        $this->assertFalse($file->hasExclusiveLock());
        fclose($fp);
    }

    /**
     * @see    https://github.com/mikey179/vfsStream/issues/40
     * @test
     * @group  issue_40
     */
    public function canAquireSharedLockIfAlreadySharedLockedOnOtherFileHandler()
    {
        $file = vfsStream::newFile('foo.txt')->at($this->root);
        $fp1   = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $fp2   = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $file->lock($fp1, LOCK_SH);
        $this->assertTrue(flock($fp2, LOCK_SH));
        $this->assertTrue($file->isLocked());
        $this->assertTrue($file->hasSharedLock());
        $this->assertTrue($file->hasSharedLock($fp1));
        $this->assertTrue($file->hasSharedLock($fp2));
        $this->assertFalse($file->hasExclusiveLock());
        fclose($fp1);
        fclose($fp2);
    }

    /**
     * @see    https://github.com/mikey179/vfsStream/issues/31
     * @see    https://github.com/mikey179/vfsStream/issues/40
     * @test
     * @group  issue_31
     * @group  issue_40
     */
    public function removesExclusiveLockOnStreamClose()
    {
        $file = vfsStream::newFile('foo.txt')->at($this->root);
        $fp = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $file->lock($fp, LOCK_EX);
        fclose($fp);
        $this->assertFalse($file->isLocked());
        $this->assertFalse($file->hasSharedLock());
        $this->assertFalse($file->hasExclusiveLock());
    }

    /**
     * @see    https://github.com/mikey179/vfsStream/issues/31
     * @see    https://github.com/mikey179/vfsStream/issues/40
     * @test
     * @group  issue_31
     * @group  issue_40
     */
    public function removesSharedLockOnStreamClose()
    {
        $file = vfsStream::newFile('foo.txt')->at($this->root);
        $fp = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $file->lock($fp, LOCK_SH);
        fclose($fp);
        $this->assertFalse($file->isLocked());
        $this->assertFalse($file->hasSharedLock());
        $this->assertFalse($file->hasExclusiveLock());
    }

    /**
     * @see    https://github.com/mikey179/vfsStream/issues/40
     * @test
     * @group  issue_40
     */
    public function notRemovesExclusiveLockOnStreamCloseIfExclusiveLockAcquiredOnOtherFileHandler()
    {
        $file = vfsStream::newFile('foo.txt')->at($this->root);
        $fp1 = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $fp2 = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $file->lock($fp2, LOCK_EX);
        fclose($fp1);
        $this->assertTrue($file->isLocked());
        $this->assertFalse($file->hasSharedLock());
        $this->assertTrue($file->hasExclusiveLock());
        $this->assertTrue($file->hasExclusiveLock($fp2));
        fclose($fp2);
    }

    /**
     * @see    https://github.com/mikey179/vfsStream/issues/40
     * @test
     * @group  issue_40
     */
    public function notRemovesSharedLockOnStreamCloseIfSharedLockAcquiredOnOtherFileHandler()
    {
        $file = vfsStream::newFile('foo.txt')->at($this->root);
        $fp1 = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $fp2 = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $file->lock($fp2, LOCK_SH);
        fclose($fp1);
        $this->assertTrue($file->isLocked());
        $this->assertTrue($file->hasSharedLock());
        $this->assertTrue($file->hasSharedLock($fp2));
        $this->assertFalse($file->hasExclusiveLock());
        fclose($fp2);
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Stream wrapper to mock file system requests.
 *
 * @since  0.10.0
 */
class vfsStreamWrapperRecordingProxy extends vfsStreamWrapper
{
    /**
     * list of called methods for a stream
     *
     * @var  array
     */
    protected static $calledMethods = array();
    /**
     * currently opened path
     *
     * @var  string
     */
    protected $path;

    /**
     * records method call for given path
     *
     * @param  string  $method
     * @param  string  $path
     */
    protected static function recordMethodCall($method, $path)
    {
        if (isset(self::$calledMethods[$path]) === false) {
            self::$calledMethods[$path] = array();
        }

        self::$calledMethods[$path][] = $method;
    }

    /**
     * returns recorded method calls for given path
     *
     * @param   string         $path
     * @return  array<string>
     */
    public static function getMethodCalls($path)
    {
        if (isset(self::$calledMethods[$path]) === true) {
            return self::$calledMethods[$path];
        }

        return array();
    }

    /**
     * helper method for setting up vfsStream with the proxy
     *
     * @param   string              $rootDirName  optional  name of root directory
     * @param   int                 $permissions  optional  file permissions of root directory
     * @return  vfsStreamDirectory
     * @throws  vfsStreamException
     */
    public static function setup($rootDirName = 'root', $permissions = null)
    {
        self::$root = vfsStream::newDirectory($rootDirName, $permissions);
        if (true === self::$registered) {
            return self::$root;
        }

        if (@stream_wrapper_register(vfsStream::SCHEME, __CLASS__) === false) {
            throw new vfsStreamException('A handler has already been registered for the ' . vfsStream::SCHEME . ' protocol.');
        }

        self::$registered = true;
        return self::$root;
    }

    /**
     * open the stream
     *
     * @param   string  $path         the path to open
     * @param   string  $mode         mode for opening
     * @param   string  $options      options for opening
     * @param   string  $opened_path  full path that was actually opened
     * @return  bool
     */
    public function stream_open($path, $mode, $options, $opened_path)
    {
        $this->path = $path;
        self::recordMethodCall('stream_open', $this->path);
        return parent::stream_open($path, $mode, $options, $opened_path);
    }

    /**
     * closes the stream
     */
    public function stream_close()
    {
        self::recordMethodCall('stream_close', $this->path);
        return parent::stream_close();
    }

    /**
     * read the stream up to $count bytes
     *
     * @param   int     $count  amount of bytes to read
     * @return  string
     */
    public function stream_read($count)
    {
        self::recordMethodCall('stream_read', $this->path);
        return parent::stream_read($count);
    }

    /**
     * writes data into the stream
     *
     * @param   string  $data
     * @return  int     amount of bytes written
     */
    public function stream_write($data)
    {
        self::recordMethodCall('stream_write', $this->path);
        return parent::stream_write($data);
    }

    /**
     * checks whether stream is at end of file
     *
     * @return  bool
     */
    public function stream_eof()
    {
        self::recordMethodCall('stream_eof', $this->path);
        return parent::stream_eof();
    }

    /**
     * returns the current position of the stream
     *
     * @return  int
     */
    public function stream_tell()
    {
        self::recordMethodCall('stream_tell', $this->path);
        return parent::stream_tell();
    }

    /**
     * seeks to the given offset
     *
     * @param   int   $offset
     * @param   int   $whence
     * @return  bool
     */
    public function stream_seek($offset, $whence)
    {
        self::recordMethodCall('stream_seek', $this->path);
        return parent::stream_seek($offset, $whence);
    }

    /**
     * flushes unstored data into storage
     *
     * @return  bool
     */
    public function stream_flush()
    {
        self::recordMethodCall('stream_flush', $this->path);
        return parent::stream_flush();
    }

    /**
     * returns status of stream
     *
     * @return  array
     */
    public function stream_stat()
    {
        self::recordMethodCall('stream_stat', $this->path);
        return parent::stream_stat();
    }

    /**
     * retrieve the underlaying resource
     *
     * @param   int  $cast_as
     * @return  bool
     */
    public function stream_cast($cast_as)
    {
        self::recordMethodCall('stream_cast', $this->path);
        return parent::stream_cast($cast_as);
    }

    /**
     * set lock status for stream
     *
     * @param   int   $operation
     * @return  bool
     */
    public function stream_lock($operation)
    {
        self::recordMethodCall('stream_link', $this->path);
        return parent::stream_lock($operation);
    }

    /**
     * remove the data under the given path
     *
     * @param   string  $path
     * @return  bool
     */
    public function unlink($path)
    {
        self::recordMethodCall('unlink', $path);
        return parent::unlink($path);
    }

    /**
     * rename from one path to another
     *
     * @param   string  $path_from
     * @param   string  $path_to
     * @return  bool
     */
    public function rename($path_from, $path_to)
    {
        self::recordMethodCall('rename', $path_from);
        return parent::rename($path_from, $path_to);
    }

    /**
     * creates a new directory
     *
     * @param   string  $path
     * @param   int     $mode
     * @param   int     $options
     * @return  bool
     */
    public function mkdir($path, $mode, $options)
    {
        self::recordMethodCall('mkdir', $path);
        return parent::mkdir($path, $mode, $options);
    }

    /**
     * removes a directory
     *
     * @param   string  $path
     * @param   int     $options
     * @return  bool
     */
    public function rmdir($path, $options)
    {
        self::recordMethodCall('rmdir', $path);
        return parent::rmdir($path, $options);
    }

    /**
     * opens a directory
     *
     * @param   string  $path
     * @param   int     $options
     * @return  bool
     */
    public function dir_opendir($path, $options)
    {
        $this->path = $path;
        self::recordMethodCall('dir_opendir', $this->path);
        return parent::dir_opendir($path, $options);
    }

    /**
     * reads directory contents
     *
     * @return  string
     */
    public function dir_readdir()
    {
        self::recordMethodCall('dir_readdir', $this->path);
        return parent::dir_readdir();
    }

    /**
     * reset directory iteration
     *
     * @return  bool
     */
    public function dir_rewinddir()
    {
        self::recordMethodCall('dir_rewinddir', $this->path);
        return parent::dir_rewinddir();
    }

    /**
     * closes directory
     *
     * @return  bool
     */
    public function dir_closedir()
    {
        self::recordMethodCall('dir_closedir', $this->path);
        return parent::dir_closedir();
    }

    /**
     * returns status of url
     *
     * @param   string  $path   path of url to return status for
     * @param   int     $flags  flags set by the stream API
     * @return  array
     */
    public function url_stat($path, $flags)
    {
        self::recordMethodCall('url_stat', $path);
        return parent::url_stat($path, $flags);
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Test for unlink() functionality.
 *
 * @group  unlink
 */
class UnlinkTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * @test
     * @group  issue_51
     */
    public function canRemoveNonWritableFileFromWritableDirectory()
    {
        $structure = array('test_directory' => array('test.file' => ''));
        $root = vfsStream::setup('root', null, $structure);
        $root->getChild('test_directory')->chmod(0777);
        $root->getChild('test_directory')->getChild('test.file')->chmod(0444);
        $this->assertTrue(@unlink(vfsStream::url('root/test_directory/test.file')));
    }

    /**
     * @test
     * @group  issue_51
     */
    public function canNotRemoveWritableFileFromNonWritableDirectory()
    {
        $structure = array('test_directory' => array('test.file' => ''));
        $root = vfsStream::setup('root', null, $structure);
        $root->getChild('test_directory')->chmod(0444);
        $root->getChild('test_directory')->getChild('test.file')->chmod(0777);
        $this->assertFalse(@unlink(vfsStream::url('root/test_directory/test.file')));
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
require_once __DIR__ . '/vfsStreamWrapperBaseTestCase.php';
/**
 * Test for org\bovigo\vfs\vfsStreamWrapper.
 */
class vfsStreamWrapperTestCase extends vfsStreamWrapperBaseTestCase
{
    /**
     * ensure that a call to vfsStreamWrapper::register() resets the stream
     *
     * Implemented after a request by David Zülke.
     *
     * @test
     */
    public function resetByRegister()
    {
        $this->assertSame($this->foo, vfsStreamWrapper::getRoot());
        vfsStreamWrapper::register();
        $this->assertNull(vfsStreamWrapper::getRoot());
    }

    /**
     * @test
     * @since  0.11.0
     */
    public function setRootReturnsRoot()
    {
        vfsStreamWrapper::register();
        $root = vfsStream::newDirectory('root');
        $this->assertSame($root, vfsStreamWrapper::setRoot($root));
    }

    /**
     * assure that filesize is returned correct
     *
     * @test
     */
    public function filesize()
    {
        $this->assertEquals(0, filesize($this->fooURL));
        $this->assertEquals(0, filesize($this->fooURL . '/.'));
        $this->assertEquals(0, filesize($this->barURL));
        $this->assertEquals(0, filesize($this->barURL . '/.'));
        $this->assertEquals(4, filesize($this->baz2URL));
        $this->assertEquals(5, filesize($this->baz1URL));
    }

    /**
     * assert that file_exists() delivers correct result
     *
     * @test
     */
    public function file_exists()
    {
        $this->assertTrue(file_exists($this->fooURL));
        $this->assertTrue(file_exists($this->fooURL . '/.'));
        $this->assertTrue(file_exists($this->barURL));
        $this->assertTrue(file_exists($this->barURL . '/.'));
        $this->assertTrue(file_exists($this->baz1URL));
        $this->assertTrue(file_exists($this->baz2URL));
        $this->assertFalse(file_exists($this->fooURL . '/another'));
        $this->assertFalse(file_exists(vfsStream::url('another')));
    }

    /**
     * assert that filemtime() delivers correct result
     *
     * @test
     */
    public function filemtime()
    {
        $this->assertEquals(100, filemtime($this->fooURL));
        $this->assertEquals(100, filemtime($this->fooURL . '/.'));
        $this->assertEquals(200, filemtime($this->barURL));
        $this->assertEquals(200, filemtime($this->barURL . '/.'));
        $this->assertEquals(300, filemtime($this->baz1URL));
        $this->assertEquals(400, filemtime($this->baz2URL));
    }

    /**
     * @test
     * @group  issue_23
     */
    public function unlinkRemovesFilesOnly()
    {
        $this->assertTrue(unlink($this->baz2URL));
        $this->assertFalse(file_exists($this->baz2URL)); // make sure statcache was cleared
        $this->assertEquals(array($this->bar), $this->foo->getChildren());
        $this->assertFalse(unlink($this->fooURL . '/another'));
        $this->assertFalse(unlink(vfsStream::url('another')));
        $this->assertEquals(array($this->bar), $this->foo->getChildren());
    }

    /**
     * @test
     * @group  issue_49
     */
    public function unlinkReturnsFalseWhenFileDoesNotExist()
    {
        vfsStream::setup()->addChild(vfsStream::newFile('foo.blubb'));
        $this->assertFalse(unlink(vfsStream::url('foo.blubb2')));
    }

    /**
     * @test
     * @group  issue_49
     */
    public function unlinkReturnsFalseWhenFileDoesNotExistAndFileWithSameNameExistsInRoot()
    {
        vfsStream::setup()->addChild(vfsStream::newFile('foo.blubb'));
        $this->assertFalse(unlink(vfsStream::url('foo.blubb')));
    }

    /**
     * assert dirname() returns correct directory name
     *
     * @test
     */
    public function dirname()
    {
        $this->assertEquals($this->fooURL, dirname($this->barURL));
        $this->assertEquals($this->barURL, dirname($this->baz1URL));
        # returns "vfs:" instead of "."
        # however this seems not to be fixable because dirname() does not
        # call the stream wrapper
        #$this->assertEquals(dirname(vfsStream::url('doesNotExist')), '.');
    }

    /**
     * assert basename() returns correct file name
     *
     * @test
     */
    public function basename()
    {
        $this->assertEquals('bar', basename($this->barURL));
        $this->assertEquals('baz1', basename($this->baz1URL));
        $this->assertEquals('doesNotExist', basename(vfsStream::url('doesNotExist')));
    }

    /**
     * assert is_readable() works correct
     *
     * @test
     */
    public function is_readable()
    {
        $this->assertTrue(is_readable($this->fooURL));
        $this->assertTrue(is_readable($this->fooURL . '/.'));
        $this->assertTrue(is_readable($this->barURL));
        $this->assertTrue(is_readable($this->barURL . '/.'));
        $this->assertTrue(is_readable($this->baz1URL));
        $this->assertTrue(is_readable($this->baz2URL));
        $this->assertFalse(is_readable($this->fooURL . '/another'));
        $this->assertFalse(is_readable(vfsStream::url('another')));

        $this->foo->chmod(0222);
        $this->assertFalse(is_readable($this->fooURL));

        $this->baz1->chmod(0222);
        $this->assertFalse(is_readable($this->baz1URL));
    }

    /**
     * assert is_writable() works correct
     *
     * @test
     */
    public function is_writable()
    {
        $this->assertTrue(is_writable($this->fooURL));
        $this->assertTrue(is_writable($this->fooURL . '/.'));
        $this->assertTrue(is_writable($this->barURL));
        $this->assertTrue(is_writable($this->barURL . '/.'));
        $this->assertTrue(is_writable($this->baz1URL));
        $this->assertTrue(is_writable($this->baz2URL));
        $this->assertFalse(is_writable($this->fooURL . '/another'));
        $this->assertFalse(is_writable(vfsStream::url('another')));

        $this->foo->chmod(0444);
        $this->assertFalse(is_writable($this->fooURL));

        $this->baz1->chmod(0444);
        $this->assertFalse(is_writable($this->baz1URL));
    }

    /**
     * assert is_executable() works correct
     *
     * @test
     */
    public function is_executable()
    {
        $this->assertFalse(is_executable($this->baz1URL));
        $this->baz1->chmod(0766);
        $this->assertTrue(is_executable($this->baz1URL));
        $this->assertFalse(is_executable($this->baz2URL));
    }

    /**
     * assert is_executable() works correct
     *
     * @test
     */
    public function directoriesAndNonExistingFilesAreNeverExecutable()
    {
        $this->assertFalse(is_executable($this->fooURL));
        $this->assertFalse(is_executable($this->fooURL . '/.'));
        $this->assertFalse(is_executable($this->barURL));
        $this->assertFalse(is_executable($this->barURL . '/.'));
        $this->assertFalse(is_executable($this->fooURL . '/another'));
        $this->assertFalse(is_executable(vfsStream::url('another')));
    }

    /**
     * file permissions
     *
     * @test
     * @group  permissions
     */
    public function chmod()
    {
        $this->assertEquals(40777, decoct(fileperms($this->fooURL)));
        $this->assertEquals(40777, decoct(fileperms($this->fooURL . '/.')));
        $this->assertEquals(40777, decoct(fileperms($this->barURL)));
        $this->assertEquals(40777, decoct(fileperms($this->barURL . '/.')));
        $this->assertEquals(100666, decoct(fileperms($this->baz1URL)));
        $this->assertEquals(100666, decoct(fileperms($this->baz2URL)));

        $this->foo->chmod(0755);
        $this->bar->chmod(0700);
        $this->baz1->chmod(0644);
        $this->baz2->chmod(0600);
        $this->assertEquals(40755, decoct(fileperms($this->fooURL)));
        $this->assertEquals(40755, decoct(fileperms($this->fooURL . '/.')));
        $this->assertEquals(40700, decoct(fileperms($this->barURL)));
        $this->assertEquals(40700, decoct(fileperms($this->barURL . '/.')));
        $this->assertEquals(100644, decoct(fileperms($this->baz1URL)));
        $this->assertEquals(100600, decoct(fileperms($this->baz2URL)));
    }

    /**
     * @test
     * @group  issue_11
     * @group  permissions
     */
    public function chmodModifiesPermissions()
    {
        if (version_compare(phpversion(), '5.4.0', '<')) {
            $this->assertFalse(@chmod($this->fooURL, 0755));
            $this->assertFalse(@chmod($this->barURL, 0711));
            $this->assertFalse(@chmod($this->baz1URL, 0644));
            $this->assertFalse(@chmod($this->baz2URL, 0664));
            $this->assertEquals(40777, decoct(fileperms($this->fooURL)));
            $this->assertEquals(40777, decoct(fileperms($this->barURL)));
            $this->assertEquals(100666, decoct(fileperms($this->baz1URL)));
            $this->assertEquals(100666, decoct(fileperms($this->baz2URL)));
        } else {
            $this->assertTrue(chmod($this->fooURL, 0755));
            $this->assertTrue(chmod($this->barURL, 0711));
            $this->assertTrue(chmod($this->baz1URL, 0644));
            $this->assertTrue(chmod($this->baz2URL, 0664));
            $this->assertEquals(40755, decoct(fileperms($this->fooURL)));
            $this->assertEquals(40711, decoct(fileperms($this->barURL)));
            $this->assertEquals(100644, decoct(fileperms($this->baz1URL)));
            $this->assertEquals(100664, decoct(fileperms($this->baz2URL)));
        }
    }

    /**
     * @test
     * @group  permissions
     */
    public function fileownerIsCurrentUserByDefault()
    {
        $this->assertEquals(vfsStream::getCurrentUser(), fileowner($this->fooURL));
        $this->assertEquals(vfsStream::getCurrentUser(), fileowner($this->fooURL . '/.'));
        $this->assertEquals(vfsStream::getCurrentUser(), fileowner($this->barURL));
        $this->assertEquals(vfsStream::getCurrentUser(), fileowner($this->barURL . '/.'));
        $this->assertEquals(vfsStream::getCurrentUser(), fileowner($this->baz1URL));
        $this->assertEquals(vfsStream::getCurrentUser(), fileowner($this->baz2URL));
    }

    /**
     * @test
     * @group  issue_11
     * @group  permissions
     */
    public function chownChangesUser()
    {
        if (version_compare(phpversion(), '5.4.0', '<')) {
            $this->foo->chown(vfsStream::OWNER_USER_1);
            $this->bar->chown(vfsStream::OWNER_USER_1);
            $this->baz1->chown(vfsStream::OWNER_USER_2);
            $this->baz2->chown(vfsStream::OWNER_USER_2);
        } else {
            chown($this->fooURL, vfsStream::OWNER_USER_1);
            chown($this->barURL, vfsStream::OWNER_USER_1);
            chown($this->baz1URL, vfsStream::OWNER_USER_2);
            chown($this->baz2URL, vfsStream::OWNER_USER_2);
        }

        $this->assertEquals(vfsStream::OWNER_USER_1, fileowner($this->fooURL));
        $this->assertEquals(vfsStream::OWNER_USER_1, fileowner($this->fooURL . '/.'));
        $this->assertEquals(vfsStream::OWNER_USER_1, fileowner($this->barURL));
        $this->assertEquals(vfsStream::OWNER_USER_1, fileowner($this->barURL . '/.'));
        $this->assertEquals(vfsStream::OWNER_USER_2, fileowner($this->baz1URL));
        $this->assertEquals(vfsStream::OWNER_USER_2, fileowner($this->baz2URL));
    }

    /**
     * @test
     * @group  issue_11
     * @group  permissions
     */
    public function chownDoesNotWorkOnVfsStreamUrls()
    {
        if (version_compare(phpversion(), '5.4.0', '<')) {
            $this->assertFalse(@chown($this->fooURL, vfsStream::OWNER_USER_2));
            $this->assertEquals(vfsStream::getCurrentUser(), fileowner($this->fooURL));
        }
    }

    /**
     * @test
     * @group  issue_11
     * @group  permissions
     */
    public function groupIsCurrentGroupByDefault()
    {
        $this->assertEquals(vfsStream::getCurrentGroup(), filegroup($this->fooURL));
        $this->assertEquals(vfsStream::getCurrentGroup(), filegroup($this->fooURL . '/.'));
        $this->assertEquals(vfsStream::getCurrentGroup(), filegroup($this->barURL));
        $this->assertEquals(vfsStream::getCurrentGroup(), filegroup($this->barURL . '/.'));
        $this->assertEquals(vfsStream::getCurrentGroup(), filegroup($this->baz1URL));
        $this->assertEquals(vfsStream::getCurrentGroup(), filegroup($this->baz2URL));
    }

    /**
     * @test
     * @group  issue_11
     * @group  permissions
     */
    public function chgrp()
    {
        if (version_compare(phpversion(), '5.4.0', '<')) {
            $this->foo->chgrp(vfsStream::GROUP_USER_1);
            $this->bar->chgrp(vfsStream::GROUP_USER_1);
            $this->baz1->chgrp(vfsStream::GROUP_USER_2);
            $this->baz2->chgrp(vfsStream::GROUP_USER_2);
        } else {
            chgrp($this->fooURL, vfsStream::GROUP_USER_1);
            chgrp($this->barURL, vfsStream::GROUP_USER_1);
            chgrp($this->baz1URL, vfsStream::GROUP_USER_2);
            chgrp($this->baz2URL, vfsStream::GROUP_USER_2);
        }

        $this->assertEquals(vfsStream::GROUP_USER_1, filegroup($this->fooURL));
        $this->assertEquals(vfsStream::GROUP_USER_1, filegroup($this->fooURL . '/.'));
        $this->assertEquals(vfsStream::GROUP_USER_1, filegroup($this->barURL));
        $this->assertEquals(vfsStream::GROUP_USER_1, filegroup($this->barURL . '/.'));
        $this->assertEquals(vfsStream::GROUP_USER_2, filegroup($this->baz1URL));
        $this->assertEquals(vfsStream::GROUP_USER_2, filegroup($this->baz2URL));
    }

    /**
     * @test
     * @group  issue_11
     * @group  permissions
     */
    public function chgrpDoesNotWorkOnVfsStreamUrls()
    {
        if (version_compare(phpversion(), '5.4.0', '<')) {
            $this->assertFalse(@chgrp($this->fooURL, vfsStream::GROUP_USER_2));
            $this->assertEquals(vfsStream::getCurrentGroup(), filegroup($this->fooURL));
        }
    }

    /**
     * @test
     * @author  Benoit Aubuchon
     */
    public function renameDirectory()
    {
        // move foo/bar to foo/baz3
        $baz3URL = vfsStream::url('foo/baz3');
        $this->assertTrue(rename($this->barURL, $baz3URL));
        $this->assertFileExists($baz3URL);
        $this->assertFileNotExists($this->barURL);
    }

    /**
     * @test
     */
    public function renameDirectoryWithDots()
    {
        // move foo/bar to foo/baz3
        $baz3URL = vfsStream::url('foo/baz3');
        $this->assertTrue(rename($this->barURL . '/.', $baz3URL));
        $this->assertFileExists($baz3URL);
        $this->assertFileNotExists($this->barURL);
    }

    /**
     * @test
     * @group  issue_9
     * @since  0.9.0
     */
    public function renameDirectoryWithDotsInTarget()
    {
        // move foo/bar to foo/baz3
        $baz3URL = vfsStream::url('foo/../foo/baz3/.');
        $this->assertTrue(rename($this->barURL . '/.', $baz3URL));
        $this->assertFileExists($baz3URL);
        $this->assertFileNotExists($this->barURL);
    }

    /**
     * @test
     * @author  Benoit Aubuchon
     */
    public function renameDirectoryOverwritingExistingFile()
    {
        // move foo/bar to foo/baz2
        $this->assertTrue(rename($this->barURL, $this->baz2URL));
        $this->assertFileExists(vfsStream::url('foo/baz2/baz1'));
        $this->assertFileNotExists($this->barURL);
    }

    /**
     * @test
     * @expectedException  PHPUnit_Framework_Error
     */
    public function renameFileIntoFile()
    {
        // foo/baz2 is a file, so it can not be turned into a directory
        $baz3URL = vfsStream::url('foo/baz2/baz3');
        $this->assertTrue(rename($this->baz1URL, $baz3URL));
        $this->assertFileExists($baz3URL);
        $this->assertFileNotExists($this->baz1URL);
    }

    /**
     * @test
     * @author  Benoit Aubuchon
     */
    public function renameFileToDirectory()
    {
        // move foo/bar/baz1 to foo/baz3
        $baz3URL = vfsStream::url('foo/baz3');
        $this->assertTrue(rename($this->baz1URL, $baz3URL));
        $this->assertFileExists($this->barURL);
        $this->assertFileExists($baz3URL);
        $this->assertFileNotExists($this->baz1URL);
    }

    /**
     * assert that trying to rename from a non existing file trigger a warning
     *
     * @expectedException PHPUnit_Framework_Error
     * @test
     */
    public function renameOnSourceFileNotFound()
    {
        rename(vfsStream::url('notfound'), $this->baz1URL);
    }
    /**
     * assert that trying to rename to a directory that is not found trigger a warning

     * @expectedException PHPUnit_Framework_Error
     * @test
     */
    public function renameOnDestinationDirectoryFileNotFound()
    {
        rename($this->baz1URL, vfsStream::url('foo/notfound/file2'));
    }
    /**
     * stat() and fstat() should return the same result
     *
     * @test
     */
    public function statAndFstatReturnSameResult()
    {
        $fp = fopen($this->baz2URL, 'r');
        $this->assertEquals(stat($this->baz2URL),
                            fstat($fp)
        );
        fclose($fp);
    }

    /**
     * stat() returns full data
     *
     * @test
     */
    public function statReturnsFullDataForFiles()
    {
        $this->assertEquals(array(0         => 0,
                                  1         => 0,
                                  2         => 0100666,
                                  3         => 0,
                                  4         => vfsStream::getCurrentUser(),
                                  5         => vfsStream::getCurrentGroup(),
                                  6         => 0,
                                  7         => 4,
                                  8         => 400,
                                  9         => 400,
                                  10        => 400,
                                  11        => -1,
                                  12        => -1,
                                  'dev'     => 0,
                                  'ino'     => 0,
                                  'mode'    => 0100666,
                                  'nlink'   => 0,
                                  'uid'     => vfsStream::getCurrentUser(),
                                  'gid'     => vfsStream::getCurrentGroup(),
                                  'rdev'    => 0,
                                  'size'    => 4,
                                  'atime'   => 400,
                                  'mtime'   => 400,
                                  'ctime'   => 400,
                                  'blksize' => -1,
                                  'blocks'  => -1
                            ),
                            stat($this->baz2URL)
        );
    }

    /**
     * @test
     */
    public function statReturnsFullDataForDirectories()
    {
        $this->assertEquals(array(0         => 0,
                                  1         => 0,
                                  2         => 0040777,
                                  3         => 0,
                                  4         => vfsStream::getCurrentUser(),
                                  5         => vfsStream::getCurrentGroup(),
                                  6         => 0,
                                  7         => 0,
                                  8         => 100,
                                  9         => 100,
                                  10        => 100,
                                  11        => -1,
                                  12        => -1,
                                  'dev'     => 0,
                                  'ino'     => 0,
                                  'mode'    => 0040777,
                                  'nlink'   => 0,
                                  'uid'     => vfsStream::getCurrentUser(),
                                  'gid'     => vfsStream::getCurrentGroup(),
                                  'rdev'    => 0,
                                  'size'    => 0,
                                  'atime'   => 100,
                                  'mtime'   => 100,
                                  'ctime'   => 100,
                                  'blksize' => -1,
                                  'blocks'  => -1
                            ),
                            stat($this->fooURL)
        );
    }

    /**
     * @test
     */
    public function statReturnsFullDataForDirectoriesWithDot()
    {
        $this->assertEquals(array(0         => 0,
                                  1         => 0,
                                  2         => 0040777,
                                  3         => 0,
                                  4         => vfsStream::getCurrentUser(),
                                  5         => vfsStream::getCurrentGroup(),
                                  6         => 0,
                                  7         => 0,
                                  8         => 100,
                                  9         => 100,
                                  10        => 100,
                                  11        => -1,
                                  12        => -1,
                                  'dev'     => 0,
                                  'ino'     => 0,
                                  'mode'    => 0040777,
                                  'nlink'   => 0,
                                  'uid'     => vfsStream::getCurrentUser(),
                                  'gid'     => vfsStream::getCurrentGroup(),
                                  'rdev'    => 0,
                                  'size'    => 0,
                                  'atime'   => 100,
                                  'mtime'   => 100,
                                  'ctime'   => 100,
                                  'blksize' => -1,
                                  'blocks'  => -1
                            ),
                            stat($this->fooURL . '/.')
        );
    }

    /**
     * @test
     * @expectedException PHPUnit_Framework_Error
     */
    public function openFileWithoutDirectory()
    {
        vfsStreamWrapper::register();
        $this->assertFalse(file_get_contents(vfsStream::url('file.txt')));
    }

    /**
     * @test
     * @group  issue_33
     * @since  1.1.0
     */
    public function truncateRemovesSuperflouosContent()
    {
        if (version_compare(PHP_VERSION, '5.4.0', '<')) {
            $this->markTestSkipped('Requires PHP 5.4');
        }

        $handle = fopen($this->baz1URL, "r+");
        $this->assertTrue(ftruncate($handle, 0));
        $this->assertEquals(0, filesize($this->baz1URL));
        $this->assertEquals('', file_get_contents($this->baz1URL));
        fclose($handle);
    }

    /**
     * @test
     * @group  issue_33
     * @since  1.1.0
     */
    public function truncateToGreaterSizeAddsZeroBytes()
    {
        if (version_compare(PHP_VERSION, '5.4.0', '<')) {
            $this->markTestSkipped('Requires PHP 5.4');
        }

        $handle = fopen($this->baz1URL, "r+");
        $this->assertTrue(ftruncate($handle, 25));
        $this->assertEquals(25, filesize($this->baz1URL));
        $this->assertEquals("baz 1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
                            file_get_contents($this->baz1URL));
        fclose($handle);
    }

    /**
     * @test
     * @group  issue_11
     */
    public function touchCreatesNonExistingFile()
    {
        if (version_compare(PHP_VERSION, '5.4.0', '<')) {
            $this->markTestSkipped('Requires PHP 5.4');
        }

        $this->assertTrue(touch($this->fooURL . '/new.txt'));
        $this->assertTrue($this->foo->hasChild('new.txt'));
    }

    /**
     * @test
     * @group  issue_11
     */
    public function touchChangesAccessAndModificationTimeForFile()
    {
        if (version_compare(PHP_VERSION, '5.4.0', '<')) {
            $this->markTestSkipped('Requires PHP 5.4');
        }

        $this->assertTrue(touch($this->baz1URL, 303, 313));
        $this->assertEquals(303, $this->baz1->filemtime());
        $this->assertEquals(313, $this->baz1->fileatime());
    }

    /**
     * @test
     * @group  issue_11
     */
    public function touchDoesNotChangeTimesWhenNoTimesGiven()
    {
        if (version_compare(PHP_VERSION, '5.4.0', '<')) {
            $this->markTestSkipped('Requires PHP 5.4');
        }

        $this->assertTrue(touch($this->baz1URL));
        $this->assertEquals(300, $this->baz1->filemtime());
        $this->assertEquals(300, $this->baz1->fileatime());
    }

    /**
     * @test
     * @group  issue_11
     */
    public function touchWithModifiedTimeChangesAccessAndModifiedTime()
    {
        if (version_compare(PHP_VERSION, '5.4.0', '<')) {
            $this->markTestSkipped('Requires PHP 5.4');
        }

        $this->assertTrue(touch($this->baz1URL, 303));
        $this->assertEquals(303, $this->baz1->filemtime());
        $this->assertEquals(303, $this->baz1->fileatime());
    }

    /**
     * @test
     * @group  issue_11
     */
    public function touchChangesAccessAndModificationTimeForDirectory()
    {
        if (version_compare(PHP_VERSION, '5.4.0', '<')) {
            $this->markTestSkipped('Requires PHP 5.4');
        }

        $this->assertTrue(touch($this->fooURL, 303, 313));
        $this->assertEquals(303, $this->foo->filemtime());
        $this->assertEquals(313, $this->foo->fileatime());
    }

    /**
     * @test
     * @group  issue_34
     * @since  1.2.0
     */
    public function pathesAreCorrectlySet()
    {
        $this->assertEquals(vfsStream::path($this->fooURL), $this->foo->path());
        $this->assertEquals(vfsStream::path($this->barURL), $this->bar->path());
        $this->assertEquals(vfsStream::path($this->baz1URL), $this->baz1->path());
        $this->assertEquals(vfsStream::path($this->baz2URL), $this->baz2->path());
    }

    /**
     * @test
     * @group  issue_34
     * @since  1.2.0
     */
    public function urlsAreCorrectlySet()
    {
        $this->assertEquals($this->fooURL, $this->foo->url());
        $this->assertEquals($this->barURL, $this->bar->url());
        $this->assertEquals($this->baz1URL, $this->baz1->url());
        $this->assertEquals($this->baz2URL, $this->baz2->url());
    }

    /**
     * @test
     * @group  issue_34
     * @since  1.2.0
     */
    public function pathIsUpdatedAfterMove()
    {
        // move foo/bar/baz1 to foo/baz3
        $baz3URL = vfsStream::url('foo/baz3');
        $this->assertTrue(rename($this->baz1URL, $baz3URL));
        $this->assertEquals(vfsStream::path($baz3URL), $this->baz1->path());
    }

    /**
     * @test
     * @group  issue_34
     * @since  1.2.0
     */
    public function urlIsUpdatedAfterMove()
    {
        // move foo/bar/baz1 to foo/baz3
        $baz3URL = vfsStream::url('foo/baz3');
        $this->assertTrue(rename($this->baz1URL, $baz3URL));
        $this->assertEquals($baz3URL, $this->baz1->url());
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Helper class for the test.
 */
class TestvfsStreamAbstractContent extends vfsStreamAbstractContent
{
    /**
     * returns default permissions for concrete implementation
     *
     * @return  int
     * @since   0.8.0
     */
    protected function getDefaultPermissions()
    {
        return 0777;
    }

    /**
     * returns size of content
     *
     * @return  int
     */
    public function size()
    {
        return 0;
    }
}
/**
 * Test for org\bovigo\vfs\vfsStreamAbstractContent.
 */
class vfsStreamAbstractContentTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function noPermissionsForEveryone()
    {
        $abstractContent = new TestvfsStreamAbstractContent('foo', 0000);
        $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          -1
                                             )
               );
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function executePermissionsForUser()
    {
        $abstractContent = new TestvfsStreamAbstractContent('foo', 0100);
        $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        -1
                                             )
               );
        $this->assertTrue($abstractContent->isExecutable(vfsStream::getCurrentUser(),
                                                         vfsStream::getCurrentGroup()
                                            )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          -1
                                             )
               );
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function executePermissionsForGroup()
    {
        $abstractContent = new TestvfsStreamAbstractContent('foo', 0010);
        $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(),
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertTrue($abstractContent->isExecutable(-1,
                                                         vfsStream::getCurrentGroup()
                                            )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          -1
                                             )
               );
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function executePermissionsForOther()
    {
        $abstractContent = new TestvfsStreamAbstractContent('foo', 0001);
        $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(),
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertTrue($abstractContent->isExecutable(-1,
                                                         -1
                                            )
               );
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function writePermissionsForUser()
    {
        $abstractContent = new TestvfsStreamAbstractContent('foo', 0200);
        $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        -1
                                             )
               );
        $this->assertTrue($abstractContent->isWritable(vfsStream::getCurrentUser(),
                                                       vfsStream::getCurrentGroup()
                                            )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(),
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          -1
                                             )
               );
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function writePermissionsForGroup()
    {
        $abstractContent = new TestvfsStreamAbstractContent('foo', 0020);
        $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertTrue($abstractContent->isWritable(-1,
                                                       vfsStream::getCurrentGroup()
                                            )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(),
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          -1
                                             )
               );
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function writePermissionsForOther()
    {
        $abstractContent = new TestvfsStreamAbstractContent('foo', 0002);
        $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertTrue($abstractContent->isWritable(-1,
                                                       -1
                                            )
               );
        $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(),
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          -1
                                             )
               );
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function executeAndWritePermissionsForUser()
    {
        $abstractContent = new TestvfsStreamAbstractContent('foo', 0300);
        $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        -1
                                             )
               );
        $this->assertTrue($abstractContent->isWritable(vfsStream::getCurrentUser(),
                                                       vfsStream::getCurrentGroup()
                                            )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        -1
                                             )
               );
        $this->assertTrue($abstractContent->isExecutable(vfsStream::getCurrentUser(),
                                                         vfsStream::getCurrentGroup()
                                            )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          -1
                                             )
               );
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function executeAndWritePermissionsForGroup()
    {
        $abstractContent = new TestvfsStreamAbstractContent('foo', 0030);
        $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertTrue($abstractContent->isWritable(-1,
                                                       vfsStream::getCurrentGroup()
                                            )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(),
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertTrue($abstractContent->isExecutable(-1,
                                                         vfsStream::getCurrentGroup()
                                            )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          -1
                                             )
               );
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function executeAndWritePermissionsForOther()
    {
        $abstractContent = new TestvfsStreamAbstractContent('foo', 0003);
        $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertTrue($abstractContent->isWritable(-1,
                                                       -1
                                            )
               );
        $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(),
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertTrue($abstractContent->isExecutable(-1,
                                                         -1
                                            )
               );
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function readPermissionsForUser()
    {
        $abstractContent = new TestvfsStreamAbstractContent('foo', 0400);
        $this->assertTrue($abstractContent->isReadable(vfsStream::getCurrentUser(),
                                                       vfsStream::getCurrentGroup()
                                            )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(),
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          -1
                                             )
               );
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function readPermissionsForGroup()
    {
        $abstractContent = new TestvfsStreamAbstractContent('foo', 0040);
        $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertTrue($abstractContent->isReadable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(),
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          -1
                                             )
               );
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function readPermissionsForOther()
    {
        $abstractContent = new TestvfsStreamAbstractContent('foo', 0004);
        $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertTrue($abstractContent->isReadable(-1,
                                                       -1
                                            )
               );
        $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(),
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          -1
                                             )
               );
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function readAndExecutePermissionsForUser()
    {
        $abstractContent = new TestvfsStreamAbstractContent('foo', 0500);
        $this->assertTrue($abstractContent->isReadable(vfsStream::getCurrentUser(),
                                                       vfsStream::getCurrentGroup()
                                            )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        -1
                                             )
               );
        $this->assertTrue($abstractContent->isExecutable(vfsStream::getCurrentUser(),
                                                         vfsStream::getCurrentGroup()
                                            )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          -1
                                             )
               );
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function readAndExecutePermissionsForGroup()
    {
        $abstractContent = new TestvfsStreamAbstractContent('foo', 0050);
        $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertTrue($abstractContent->isReadable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(),
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertTrue($abstractContent->isExecutable(-1,
                                                         vfsStream::getCurrentGroup()
                                            )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          -1
                                             )
               );
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function readAndExecutePermissionsForOther()
    {
        $abstractContent = new TestvfsStreamAbstractContent('foo', 0005);
        $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertTrue($abstractContent->isReadable(-1,
                                                       -1
                                            )
               );
        $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(),
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertTrue($abstractContent->isExecutable(-1,
                                                         -1
                                            )
               );
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function readAndWritePermissionsForUser()
    {
        $abstractContent = new TestvfsStreamAbstractContent('foo', 0600);
        $this->assertTrue($abstractContent->isReadable(vfsStream::getCurrentUser(),
                                                       vfsStream::getCurrentGroup()
                                            )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        -1
                                             )
               );
        $this->assertTrue($abstractContent->isWritable(vfsStream::getCurrentUser(),
                                                       vfsStream::getCurrentGroup()
                                            )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(),
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          -1
                                             )
               );
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function readAndWritePermissionsForGroup()
    {
        $abstractContent = new TestvfsStreamAbstractContent('foo', 0060);
        $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertTrue($abstractContent->isReadable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertTrue($abstractContent->isWritable(-1,
                                                       vfsStream::getCurrentGroup()
                                            )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(),
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          -1
                                             )
               );
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function readAndWritePermissionsForOther()
    {
        $abstractContent = new TestvfsStreamAbstractContent('foo', 0006);
        $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertTrue($abstractContent->isReadable(-1,
                                                       -1
                                            )
               );
        $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertTrue($abstractContent->isWritable(-1,
                                                       -1
                                            )
               );
        $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(),
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          -1
                                             )
               );
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function allPermissionsForUser()
    {
        $abstractContent = new TestvfsStreamAbstractContent('foo', 0700);
        $this->assertTrue($abstractContent->isReadable(vfsStream::getCurrentUser(),
                                                       vfsStream::getCurrentGroup()
                                            )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        -1
                                             )
               );
        $this->assertTrue($abstractContent->isWritable(vfsStream::getCurrentUser(),
                                                       vfsStream::getCurrentGroup()
                                            )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        -1
                                             )
               );
        $this->assertTrue($abstractContent->isExecutable(vfsStream::getCurrentUser(),
                                                         vfsStream::getCurrentGroup()
                                            )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          -1
                                             )
               );
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function allPermissionsForGroup()
    {
        $abstractContent = new TestvfsStreamAbstractContent('foo', 0070);
        $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertTrue($abstractContent->isReadable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertTrue($abstractContent->isWritable(-1,
                                                       vfsStream::getCurrentGroup()
                                            )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        -1
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(),
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertTrue($abstractContent->isExecutable(-1,
                                                         vfsStream::getCurrentGroup()
                                            )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          -1
                                             )
               );
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function allPermissionsForOther()
    {
        $abstractContent = new TestvfsStreamAbstractContent('foo', 0007);
        $this->assertFalse($abstractContent->isReadable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isReadable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertTrue($abstractContent->isReadable(-1,
                                                       -1
                                            )
               );
        $this->assertFalse($abstractContent->isWritable(vfsStream::getCurrentUser(),
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isWritable(-1,
                                                        vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertTrue($abstractContent->isWritable(-1,
                                                       -1
                                            )
               );
        $this->assertFalse($abstractContent->isExecutable(vfsStream::getCurrentUser(),
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertFalse($abstractContent->isExecutable(-1,
                                                          vfsStream::getCurrentGroup()
                                             )
               );
        $this->assertTrue($abstractContent->isExecutable(-1,
                                                         -1
                                            )
               );
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
require_once __DIR__ . '/vfsStreamWrapperBaseTestCase.php';
/**
 * Test for org\bovigo\vfs\vfsStreamWrapper around mkdir().
 *
 * @package     bovigo_vfs
 * @subpackage  test
 */
class vfsStreamWrapperMkDirTestCase extends vfsStreamWrapperBaseTestCase
{
    /**
     * mkdir() should not overwrite existing root
     *
     * @test
     */
    public function mkdirNoNewRoot()
    {
        $this->assertFalse(mkdir(vfsStream::url('another')));
        $this->assertEquals(2, count($this->foo->getChildren()));
        $this->assertSame($this->foo, vfsStreamWrapper::getRoot());
    }

    /**
     * mkdir() should not overwrite existing root
     *
     * @test
     */
    public function mkdirNoNewRootRecursively()
    {
        $this->assertFalse(mkdir(vfsStream::url('another/more'), 0777, true));
        $this->assertEquals(2, count($this->foo->getChildren()));
        $this->assertSame($this->foo, vfsStreamWrapper::getRoot());
    }

    /**
     * assert that mkdir() creates the correct directory structure
     *
     * @test
     * @group  permissions
     */
    public function mkdirNonRecursively()
    {
        $this->assertFalse(mkdir($this->barURL . '/another/more'));
        $this->assertEquals(2, count($this->foo->getChildren()));
        $this->assertTrue(mkdir($this->fooURL . '/another'));
        $this->assertEquals(3, count($this->foo->getChildren()));
        $this->assertEquals(0777, $this->foo->getChild('another')->getPermissions());
    }

    /**
     * assert that mkdir() creates the correct directory structure
     *
     * @test
     * @group  permissions
     */
    public function mkdirRecursively()
    {
        $this->assertTrue(mkdir($this->fooURL . '/another/more', 0777, true));
        $this->assertEquals(3, count($this->foo->getChildren()));
        $another = $this->foo->getChild('another');
        $this->assertTrue($another->hasChild('more'));
        $this->assertEquals(0777, $this->foo->getChild('another')->getPermissions());
        $this->assertEquals(0777, $this->foo->getChild('another')->getChild('more')->getPermissions());
    }

    /**
     * @test
     * @group  issue_9
     * @since  0.9.0
     */
    public function mkdirWithDots()
    {
        $this->assertTrue(mkdir($this->fooURL . '/another/../more/.', 0777, true));
        $this->assertEquals(3, count($this->foo->getChildren()));
        $this->assertTrue($this->foo->hasChild('more'));
    }

    /**
     * no root > new directory becomes root
     *
     * @test
     * @group  permissions
     */
    public function mkdirWithoutRootCreatesNewRoot()
    {
        vfsStreamWrapper::register();
        $this->assertTrue(@mkdir(vfsStream::url('foo')));
        $this->assertEquals(vfsStreamContent::TYPE_DIR, vfsStreamWrapper::getRoot()->getType());
        $this->assertEquals('foo', vfsStreamWrapper::getRoot()->getName());
        $this->assertEquals(0777, vfsStreamWrapper::getRoot()->getPermissions());
    }

    /**
     * trying to create a subdirectory of a file should not work
     *
     * @test
     */
    public function mkdirOnFileReturnsFalse()
    {
        $this->assertFalse(mkdir($this->baz1URL . '/another/more', 0777, true));
    }

    /**
     * assert that mkdir() creates the correct directory structure
     *
     * @test
     * @group  permissions
     */
    public function mkdirNonRecursivelyDifferentPermissions()
    {
        $this->assertTrue(mkdir($this->fooURL . '/another', 0755));
        $this->assertEquals(0755, $this->foo->getChild('another')->getPermissions());
    }

    /**
     * assert that mkdir() creates the correct directory structure
     *
     * @test
     * @group  permissions
     */
    public function mkdirRecursivelyDifferentPermissions()
    {
        $this->assertTrue(mkdir($this->fooURL . '/another/more', 0755, true));
        $this->assertEquals(3, count($this->foo->getChildren()));
        $another = $this->foo->getChild('another');
        $this->assertTrue($another->hasChild('more'));
        $this->assertEquals(0755, $this->foo->getChild('another')->getPermissions());
        $this->assertEquals(0755, $this->foo->getChild('another')->getChild('more')->getPermissions());
    }

    /**
     * assert that mkdir() creates the correct directory structure
     *
     * @test
     * @group  permissions
     */
    public function mkdirRecursivelyUsesDefaultPermissions()
    {
        $this->foo->chmod(0700);
        $this->assertTrue(mkdir($this->fooURL . '/another/more', 0777, true));
        $this->assertEquals(3, count($this->foo->getChildren()));
        $another = $this->foo->getChild('another');
        $this->assertTrue($another->hasChild('more'));
        $this->assertEquals(0777, $this->foo->getChild('another')->getPermissions());
        $this->assertEquals(0777, $this->foo->getChild('another')->getChild('more')->getPermissions());
    }

    /**
     * no root > new directory becomes root
     *
     * @test
     * @group  permissions
     */
    public function mkdirWithoutRootCreatesNewRootDifferentPermissions()
    {
        vfsStreamWrapper::register();
        $this->assertTrue(@mkdir(vfsStream::url('foo'), 0755));
        $this->assertEquals(vfsStreamContent::TYPE_DIR, vfsStreamWrapper::getRoot()->getType());
        $this->assertEquals('foo', vfsStreamWrapper::getRoot()->getName());
        $this->assertEquals(0755, vfsStreamWrapper::getRoot()->getPermissions());
    }

    /**
     * no root > new directory becomes root
     *
     * @test
     * @group  permissions
     */
    public function mkdirWithoutRootCreatesNewRootWithDefaultPermissions()
    {
        vfsStreamWrapper::register();
        $this->assertTrue(@mkdir(vfsStream::url('foo')));
        $this->assertEquals(vfsStreamContent::TYPE_DIR, vfsStreamWrapper::getRoot()->getType());
        $this->assertEquals('foo', vfsStreamWrapper::getRoot()->getName());
        $this->assertEquals(0777, vfsStreamWrapper::getRoot()->getPermissions());
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function mkdirDirCanNotCreateNewDirInNonWritingDirectory()
    {
        vfsStreamWrapper::register();
        vfsStreamWrapper::setRoot(new vfsStreamDirectory('root'));
        vfsStreamWrapper::getRoot()->addChild(new vfsStreamDirectory('restrictedFolder', 0000));
        $this->assertFalse(is_writable(vfsStream::url('root/restrictedFolder/')));
        $this->assertFalse(mkdir(vfsStream::url('root/restrictedFolder/newFolder')));
        $this->assertFalse(vfsStreamWrapper::getRoot()->hasChild('restrictedFolder/newFolder'));
    }

    /**
     * @test
     * @group  issue_28
     */
    public function mkDirShouldNotOverwriteExistingDirectories()
    {
        vfsStream::setup('root');
        $dir = vfsStream::url('root/dir');
        $this->assertTrue(mkdir($dir));
        $this->assertFalse(@mkdir($dir));
    }

    /**
     * @test
     * @group  issue_28
     * @expectedException PHPUnit_Framework_Error
     * @expectedExceptionMessage  mkdir(): Path vfs://root/dir exists
     */
    public function mkDirShouldNotOverwriteExistingDirectoriesAndTriggerE_USER_WARNING()
    {
        vfsStream::setup('root');
        $dir = vfsStream::url('root/dir');
        $this->assertTrue(mkdir($dir));
        $this->assertFalse(mkdir($dir));
    }

    /**
     * @test
     * @group  issue_28
     */
    public function mkDirShouldNotOverwriteExistingFiles()
    {
        $root = vfsStream::setup('root');
        vfsStream::newFile('test.txt')->at($root);
        $this->assertFalse(@mkdir(vfsStream::url('root/test.txt')));
    }

    /**
     * @test
     * @group  issue_28
     * @expectedException PHPUnit_Framework_Error
     * @expectedExceptionMessage  mkdir(): Path vfs://root/test.txt exists
     */
    public function mkDirShouldNotOverwriteExistingFilesAndTriggerE_USER_WARNING()
    {
        $root = vfsStream::setup('root');
        vfsStream::newFile('test.txt')->at($root);
        $this->assertFalse(mkdir(vfsStream::url('root/test.txt')));
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function canNotIterateOverNonReadableDirectory()
    {
        vfsStreamWrapper::register();
        vfsStreamWrapper::setRoot(new vfsStreamDirectory('root', 0000));
        $this->assertFalse(@opendir(vfsStream::url('root')));
        $this->assertFalse(@dir(vfsStream::url('root')));
    }

    /**
     * @test
     */
    public function directoryIteration()
    {
        $dir = dir($this->fooURL);
        $i   = 0;
        while (false !== ($entry = $dir->read())) {
            $i++;
            $this->assertTrue('bar' === $entry || 'baz2' === $entry);
        }

        $this->assertEquals(2, $i, 'Directory foo contains two children, but got ' . $i . ' children while iterating over directory contents');
        $dir->rewind();
        $i   = 0;
        while (false !== ($entry = $dir->read())) {
            $i++;
            $this->assertTrue('bar' === $entry || 'baz2' === $entry);
        }

        $this->assertEquals(2, $i, 'Directory foo contains two children, but got ' . $i . ' children while iterating over directory contents');
        $dir->close();
    }

    /**
     * @test
     */
    public function directoryIterationWithDot()
    {
        $dir = dir($this->fooURL . '/.');
        $i   = 0;
        while (false !== ($entry = $dir->read())) {
            $i++;
            $this->assertTrue('bar' === $entry || 'baz2' === $entry);
        }

        $this->assertEquals(2, $i, 'Directory foo contains two children, but got ' . $i . ' children while iterating over directory contents');
        $dir->rewind();
        $i   = 0;
        while (false !== ($entry = $dir->read())) {
            $i++;
            $this->assertTrue('bar' === $entry || 'baz2' === $entry);
        }

        $this->assertEquals(2, $i, 'Directory foo contains two children, but got ' . $i . ' children while iterating over directory contents');
        $dir->close();
    }

    /**
     * assure that a directory iteration works as expected
     *
     * @test
     * @group  regression
     * @group  bug_2
     */
    public function directoryIterationWithOpenDir_Bug_2()
    {
        $handle = opendir($this->fooURL);
        $i   = 0;
        while (false !== ($entry = readdir($handle))) {
            $i++;
            $this->assertTrue('bar' === $entry || 'baz2' === $entry);
        }

        $this->assertEquals(2, $i, 'Directory foo contains two children, but got ' . $i . ' children while iterating over directory contents');

        rewind($handle);
        $i   = 0;
        while (false !== ($entry = readdir($handle))) {
            $i++;
            $this->assertTrue('bar' === $entry || 'baz2' === $entry);
        }

        $this->assertEquals(2, $i, 'Directory foo contains two children, but got ' . $i . ' children while iterating over directory contents');
        closedir($handle);
    }

    /**
     * assure that a directory iteration works as expected
     *
     * @author  Christoph Bloemer
     * @test
     * @group  regression
     * @group  bug_4
     */
    public function directoryIteration_Bug_4()
    {
        $dir   = $this->fooURL;
        $list1 = array();
        if ($handle = opendir($dir)) {
            while (false !== ($listItem = readdir($handle))) {
                if ('.'  != $listItem && '..' != $listItem) {
                    if (is_file($dir . '/' . $listItem) === true) {
                        $list1[] = 'File:[' . $listItem . ']';
                    } elseif (is_dir($dir . '/' . $listItem) === true) {
                        $list1[] = 'Folder:[' . $listItem . ']';
                    }
                }
            }

            closedir($handle);
        }

        $list2 = array();
        if ($handle = opendir($dir)) {
            while (false !== ($listItem = readdir($handle))) {
                if ('.'  != $listItem && '..' != $listItem) {
                    if (is_file($dir . '/' . $listItem) === true) {
                        $list2[] = 'File:[' . $listItem . ']';
                    } elseif (is_dir($dir . '/' . $listItem) === true) {
                        $list2[] = 'Folder:[' . $listItem . ']';
                    }
                }
            }

            closedir($handle);
        }

        $this->assertEquals($list1, $list2);
        $this->assertEquals(2, count($list1));
        $this->assertEquals(2, count($list2));
    }

    /**
     * assure that a directory iteration works as expected
     *
     * @test
     */
    public function directoryIterationShouldBeIndependent()
    {
        $list1   = array();
        $list2   = array();
        $handle1 = opendir($this->fooURL);
        if (false !== ($listItem = readdir($handle1))) {
            $list1[] = $listItem;
        }

        $handle2 = opendir($this->fooURL);
        if (false !== ($listItem = readdir($handle2))) {
            $list2[] = $listItem;
        }

        if (false !== ($listItem = readdir($handle1))) {
            $list1[] = $listItem;
        }

        if (false !== ($listItem = readdir($handle2))) {
            $list2[] = $listItem;
        }

        closedir($handle1);
        closedir($handle2);
        $this->assertEquals($list1, $list2);
        $this->assertEquals(2, count($list1));
        $this->assertEquals(2, count($list2));
    }

    /**
     * assert is_dir() returns correct result
     *
     * @test
     */
    public function is_dir()
    {
        $this->assertTrue(is_dir($this->fooURL));
        $this->assertTrue(is_dir($this->fooURL . '/.'));
        $this->assertTrue(is_dir($this->barURL));
        $this->assertTrue(is_dir($this->barURL . '/.'));
        $this->assertFalse(is_dir($this->baz1URL));
        $this->assertFalse(is_dir($this->baz2URL));
        $this->assertFalse(is_dir($this->fooURL . '/another'));
        $this->assertFalse(is_dir(vfsStream::url('another')));
    }

    /**
     * can not unlink without root
     *
     * @test
     */
    public function canNotUnlinkDirectoryWithoutRoot()
    {
        vfsStreamWrapper::register();
        $this->assertFalse(@rmdir(vfsStream::url('foo')));
    }

    /**
     * rmdir() can not remove files
     *
     * @test
     */
    public function rmdirCanNotRemoveFiles()
    {
        $this->assertFalse(rmdir($this->baz1URL));
        $this->assertFalse(rmdir($this->baz2URL));
    }

    /**
     * rmdir() can not remove a non-existing directory
     *
     * @test
     */
    public function rmdirCanNotRemoveNonExistingDirectory()
    {
        $this->assertFalse(rmdir($this->fooURL . '/another'));
    }

    /**
     * rmdir() can not remove non-empty directories
     *
     * @test
     */
    public function rmdirCanNotRemoveNonEmptyDirectory()
    {
        $this->assertFalse(rmdir($this->fooURL));
        $this->assertFalse(rmdir($this->barURL));
    }

    /**
     * @test
     */
    public function rmdirCanRemoveEmptyDirectory()
    {
        vfsStream::newDirectory('empty')->at($this->foo);
        $this->assertTrue($this->foo->hasChild('empty'));
        $this->assertTrue(rmdir($this->fooURL . '/empty'));
        $this->assertFalse($this->foo->hasChild('empty'));
    }

    /**
     * @test
     */
    public function rmdirCanRemoveEmptyDirectoryWithDot()
    {
        vfsStream::newDirectory('empty')->at($this->foo);
        $this->assertTrue($this->foo->hasChild('empty'));
        $this->assertTrue(rmdir($this->fooURL . '/empty/.'));
        $this->assertFalse($this->foo->hasChild('empty'));
    }

    /**
     * rmdir() can remove empty directories
     *
     * @test
     */
    public function rmdirCanRemoveEmptyRoot()
    {
        $this->foo->removeChild('bar');
        $this->foo->removeChild('baz2');
        $this->assertTrue(rmdir($this->fooURL));
        $this->assertFalse(file_exists($this->fooURL)); // make sure statcache was cleared
        $this->assertNull(vfsStreamWrapper::getRoot());
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function rmdirDirCanNotRemoveDirFromNonWritingDirectory()
    {
        vfsStreamWrapper::register();
        vfsStreamWrapper::setRoot(new vfsStreamDirectory('root', 0000));
        vfsStreamWrapper::getRoot()->addChild(new vfsStreamDirectory('nonRemovableFolder'));
        $this->assertFalse(is_writable(vfsStream::url('root')));
        $this->assertFalse(rmdir(vfsStream::url('root/nonRemovableFolder')));
        $this->assertTrue(vfsStreamWrapper::getRoot()->hasChild('nonRemovableFolder'));
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_17
     */
    public function issue17()
    {
        vfsStreamWrapper::register();
        vfsStreamWrapper::setRoot(new vfsStreamDirectory('root', 0770));
        vfsStreamWrapper::getRoot()->chgrp(vfsStream::GROUP_USER_1)
                                   ->chown(vfsStream::OWNER_USER_1);
        $this->assertFalse(mkdir(vfsStream::url('root/doesNotWork')));
        $this->assertFalse(vfsStreamWrapper::getRoot()->hasChild('doesNotWork'));
    }

    /**
     * @test
     * @group  bug_19
     */
    public function accessWithDoubleDotReturnsCorrectContent()
    {
        $this->assertEquals('baz2',
                file_get_contents(vfsStream::url('foo/bar/../baz2'))
        );
    }

    /**
     * @test
     * @since  0.11.0
     * @group  issue_23
     */
    public function unlinkCanNotRemoveNonEmptyDirectory()
    {
        try {
            $this->assertFalse(unlink($this->barURL));
        } catch (\PHPUnit_Framework_Error $fe) {
            $this->assertEquals('unlink(vfs://foo/bar): Operation not permitted', $fe->getMessage());
        }

        $this->assertTrue($this->foo->hasChild('bar'));
        $this->assertFileExists($this->barURL);
    }

    /**
     * @test
     * @since  0.11.0
     * @group  issue_23
     */
    public function unlinkCanNotRemoveEmptyDirectory()
    {
        vfsStream::newDirectory('empty')->at($this->foo);
        try {
            $this->assertTrue(unlink($this->fooURL . '/empty'));
        } catch (\PHPUnit_Framework_Error $fe) {
            $this->assertEquals('unlink(vfs://foo/empty): Operation not permitted', $fe->getMessage());
        }

        $this->assertTrue($this->foo->hasChild('empty'));
        $this->assertFileExists($this->fooURL . '/empty');
    }

    /**
     * @test
     * @group  issue_32
     */
    public function canCreateFolderOfSameNameAsParentFolder()
    {
        $root = vfsStream::setup('testFolder');
        mkdir(vfsStream::url('testFolder') . '/testFolder/subTestFolder', 0777, true);
        $this->assertTrue(file_exists(vfsStream::url('testFolder/testFolder/subTestFolder/.')));
    }

    /**
     * @test
     * @group  issue_32
     */
    public function canRetrieveFolderOfSameNameAsParentFolder()
    {
        $root = vfsStream::setup('testFolder');
        mkdir(vfsStream::url('testFolder') . '/testFolder/subTestFolder', 0777, true);
        $this->assertTrue($root->hasChild('testFolder'));
        $this->assertNotNull($root->getChild('testFolder'));
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Test for umask settings.
 *
 * @group  permissions
 * @group  umask
 * @since  0.8.0
 */
class vfsStreamUmaskTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * set up test environment
     */
    public function setUp()
    {
        vfsStream::umask(0000);
    }

    /**
     * clean up test environment
     */
    public function tearDown()
    {
        vfsStream::umask(0000);
    }

    /**
     * @test
     */
    public function gettingUmaskSettingDoesNotChangeUmaskSetting()
    {
        $this->assertEquals(vfsStream::umask(),
                            vfsStream::umask()
        );
        $this->assertEquals(0000,
                            vfsStream::umask()
        );
    }

    /**
     * @test
     */
    public function changingUmaskSettingReturnsOldUmaskSetting()
    {
        $this->assertEquals(0000,
                            vfsStream::umask(0022)
        );
        $this->assertEquals(0022,
                            vfsStream::umask()
        );
    }

    /**
     * @test
     */
    public function createFileWithDefaultUmaskSetting()
    {
        $file = new vfsStreamFile('foo');
        $this->assertEquals(0666, $file->getPermissions());
    }

    /**
     * @test
     */
    public function createFileWithDifferentUmaskSetting()
    {
        vfsStream::umask(0022);
        $file = new vfsStreamFile('foo');
        $this->assertEquals(0644, $file->getPermissions());
    }

    /**
     * @test
     */
    public function createDirectoryWithDefaultUmaskSetting()
    {
        $directory = new vfsStreamDirectory('foo');
        $this->assertEquals(0777, $directory->getPermissions());
    }

    /**
     * @test
     */
    public function createDirectoryWithDifferentUmaskSetting()
    {
        vfsStream::umask(0022);
        $directory = new vfsStreamDirectory('foo');
        $this->assertEquals(0755, $directory->getPermissions());
    }

    /**
     * @test
     */
    public function createFileUsingStreamWithDefaultUmaskSetting()
    {
        $root = vfsStream::setup();
        file_put_contents(vfsStream::url('root/newfile.txt'), 'file content');
        $this->assertEquals(0666, $root->getChild('newfile.txt')->getPermissions());
    }

    /**
     * @test
     */
    public function createFileUsingStreamWithDifferentUmaskSetting()
    {
        $root = vfsStream::setup();
        vfsStream::umask(0022);
        file_put_contents(vfsStream::url('root/newfile.txt'), 'file content');
        $this->assertEquals(0644, $root->getChild('newfile.txt')->getPermissions());
    }

    /**
     * @test
     */
    public function createDirectoryUsingStreamWithDefaultUmaskSetting()
    {
        $root = vfsStream::setup();
        mkdir(vfsStream::url('root/newdir'));
        $this->assertEquals(0777, $root->getChild('newdir')->getPermissions());
    }

    /**
     * @test
     */
    public function createDirectoryUsingStreamWithDifferentUmaskSetting()
    {
        $root = vfsStream::setup();
        vfsStream::umask(0022);
        mkdir(vfsStream::url('root/newdir'));
        $this->assertEquals(0755, $root->getChild('newdir')->getPermissions());
    }

    /**
     * @test
     */
    public function createDirectoryUsingStreamWithExplicit0()
    {
        $root = vfsStream::setup();
        vfsStream::umask(0022);
        mkdir(vfsStream::url('root/newdir'), null);
        $this->assertEquals(0000, $root->getChild('newdir')->getPermissions());
    }

    /**
     * @test
     *
     */
    public function createDirectoryUsingStreamWithDifferentUmaskSettingButExplicit0777()
    {
        $root = vfsStream::setup();
        vfsStream::umask(0022);
        mkdir(vfsStream::url('root/newdir'), 0777);
        $this->assertEquals(0755, $root->getChild('newdir')->getPermissions());
    }

    /**
     * @test
     */
    public function createDirectoryUsingStreamWithDifferentUmaskSettingButExplicitModeRequestedByCall()
    {
        $root = vfsStream::setup();
        vfsStream::umask(0022);
        mkdir(vfsStream::url('root/newdir'), 0700);
        $this->assertEquals(0700, $root->getChild('newdir')->getPermissions());
    }

    /**
     * @test
     */
    public function defaultUmaskSettingDoesNotInfluenceSetup()
    {
        $root = vfsStream::setup();
        $this->assertEquals(0777, $root->getPermissions());
    }

    /**
     * @test
     */
    public function umaskSettingShouldBeRespectedBySetup()
    {
        vfsStream::umask(0022);
        $root = vfsStream::setup();
        $this->assertEquals(0755, $root->getPermissions());
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Test for LOCK_EX behaviour related to file_put_contents().
 *
 * @group   lock_fpc
 * @author  https://github.com/iwyg
 */
class vfsStreamExLockTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * set up test environment
     */
    protected function setUp()
    {
        $root = vfsStream::setup();
        vfsStream::newFile('testfile')->at($root);

    }

    /**
     * This test verifies the current behaviour where vfsStream URLs do not work
     * with file_put_contents() and LOCK_EX. The test is intended to break once
     * PHP changes this so we get notified about the change.
     *
     * @test
     */
    public function filePutContentsLockShouldReportError()
    {
        @file_put_contents(vfsStream::url('root/testfile'), "some string\n", LOCK_EX);
        $php_error = error_get_last();
        $this->assertEquals("file_put_contents(): Exclusive locks may only be set for regular files", $php_error['message']);
    }

    /**
     * @test
     */
    public function flockSouldPass()
    {
        $fp = fopen(vfsStream::url('root/testfile'), 'w');
        flock($fp, LOCK_EX);
        fwrite($fp, "another string\n");
        flock($fp, LOCK_UN);
        fclose($fp);
        $this->assertEquals("another string\n", file_get_contents(vfsStream::url('root/testfile')));
    }
}

<?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Test for org\bovigo\vfs\vfsStreamDirectory.
 *
 * @group  bug_18
 */
class vfsStreamDirectoryIssue18TestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * access to root directory
     *
     * @var  vfsStreamDirectory
     */
    protected $rootDirectory;

    /**
     * set up test environment
     */
    public function setUp()
    {
        $this->rootDirectory = vfsStream::newDirectory('/');
        $this->rootDirectory->addChild(vfsStream::newDirectory('var/log/app'));
        $dir = $this->rootDirectory->getChild('var/log/app');
        $dir->addChild(vfsStream::newDirectory('app1'));
        $dir->addChild(vfsStream::newDirectory('app2'));
        $dir->addChild(vfsStream::newDirectory('foo'));
    }

    /**
     * @test
     */
    public function shouldContainThreeSubdirectories()
    {
        $this->assertEquals(3,
                            count($this->rootDirectory->getChild('var/log/app')->getChildren())
        );
    }

    /**
     * @test
     */
    public function shouldContainSubdirectoryFoo()
    {
        $this->assertTrue($this->rootDirectory->getChild('var/log/app')->hasChild('foo'));
        $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory',
                                $this->rootDirectory->getChild('var/log/app')->getChild('foo')
        );
    }

    /**
     * @test
     */
    public function shouldContainSubdirectoryApp1()
    {
        $this->assertTrue($this->rootDirectory->getChild('var/log/app')->hasChild('app1'));
        $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory',
                                $this->rootDirectory->getChild('var/log/app')->getChild('app1')
        );
    }

    /**
     * @test
     */
    public function shouldContainSubdirectoryApp2()
    {
        $this->assertTrue($this->rootDirectory->getChild('var/log/app')->hasChild('app2'));
        $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory',
                                $this->rootDirectory->getChild('var/log/app')->getChild('app2')
        );
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Test for org\bovigo\vfs\vfsStreamContainerIterator.
 */
class vfsStreamContainerIteratorTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * test method to be used for iterating
     *
     * @test
     */
    public function iteration()
    {
        $dir = new vfsStreamDirectory('foo');
        $mockChild1 = $this->getMock('org\\bovigo\\vfs\\vfsStreamContent');
        $mockChild1->expects($this->any())
                   ->method('getName')
                   ->will($this->returnValue('bar'));
        $dir->addChild($mockChild1);
        $mockChild2 = $this->getMock('org\\bovigo\\vfs\\vfsStreamContent');
        $mockChild2->expects($this->any())
                   ->method('getName')
                   ->will($this->returnValue('baz'));
        $dir->addChild($mockChild2);
        $dirIterator = $dir->getIterator();
        $this->assertEquals('bar', $dirIterator->key());
        $this->assertTrue($dirIterator->valid());
        $bar = $dirIterator->current();
        $this->assertSame($mockChild1, $bar);
        $dirIterator->next();
        $this->assertEquals('baz', $dirIterator->key());
        $this->assertTrue($dirIterator->valid());
        $baz = $dirIterator->current();
        $this->assertSame($mockChild2, $baz);
        $dirIterator->next();
        $this->assertFalse($dirIterator->valid());
        $this->assertNull($dirIterator->key());
        $this->assertNull($dirIterator->current());
        $dirIterator->rewind();
        $this->assertTrue($dirIterator->valid());
        $this->assertEquals('bar', $dirIterator->key());
        $bar2 = $dirIterator->current();
        $this->assertSame($mockChild1, $bar2);
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Test for org\bovigo\vfs\vfsStreamWrapper.
 *
 * @since  0.9.0
 * @group  issue_3
 */
class vfsStreamWrapperSelectStreamTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * @test
     * @expectedException \PHPUnit_Framework_Error
     */
    public function selectStream()
    {
        $root = vfsStream::setup();
        $file = vfsStream::newFile('foo.txt')->at($root)->withContent('testContent');

        $fp = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $readarray   = array($fp);
        $writearray  = array();
        $exceptarray = array();
        stream_select($readarray, $writearray, $exceptarray, 1);
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Test for org\bovigo\vfs\Quota.
 *
 * @group  issue_35
 */
class QuotaTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * instance to test
     *
     * @type  Quota
     */
    private $quota;

    /**
     * set up test environment
     */
    public function setUp()
    {
        $this->quota = new Quota(10);
    }

    /**
     * @test
     */
    public function unlimitedQuotaIsNotLimited()
    {
        $this->assertFalse(Quota::unlimited()->isLimited());
    }

    /**
     * @test
     */
    public function limitedQuotaIsLimited()
    {
        $this->assertTrue($this->quota->isLimited());
    }

    /**
     * @test
     */
    public function unlimitedQuotaHasAlwaysSpaceLeft()
    {
        $this->assertEquals(303, Quota::unlimited()->spaceLeft(303));
    }

    /**
     * @test
     */
    public function hasNoSpaceLeftWhenUsedSpaceIsLargerThanQuota()
    {
        $this->assertEquals(0, $this->quota->spaceLeft(11));
    }

    /**
     * @test
     */
    public function hasNoSpaceLeftWhenUsedSpaceIsEqualToQuota()
    {
        $this->assertEquals(0, $this->quota->spaceLeft(10));
    }

    /**
     * @test
     */
    public function hasSpaceLeftWhenUsedSpaceIsLowerThanQuota()
    {
        $this->assertEquals(1, $this->quota->spaceLeft(9));
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Test for stream_set_option() implementation.
 *
 * @since  0.10.0
 * @see    https://github.com/mikey179/vfsStream/issues/15
 * @group  issue_15
 */
class vfsStreamWrapperSetOptionTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * root directory
     *
     * @var  vfsStreamContainer
     */
    protected $root;

    /**
     * set up test environment
     */
    public function setUp()
    {
        $this->root = vfsStream::setup();
        vfsStream::newFile('foo.txt')->at($this->root);
    }

    /**
     * @test
     */
    public function setBlockingDoesNotWork()
    {
        $fp = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $this->assertFalse(stream_set_blocking($fp, 1));
        fclose($fp);
    }

    /**
     * @test
     */
    public function removeBlockingDoesNotWork()
    {
        $fp = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $this->assertFalse(stream_set_blocking($fp, 0));
        fclose($fp);
    }

    /**
     * @test
     */
    public function setTimeoutDoesNotWork()
    {
        $fp = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $this->assertFalse(stream_set_timeout($fp, 1));
        fclose($fp);
    }

    /**
     * @test
     */
    public function setWriteBufferDoesNotWork()
    {
        $fp = fopen(vfsStream::url('root/foo.txt'), 'rb');
        $this->assertEquals(-1, stream_set_write_buffer($fp, 512));
        fclose($fp);
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Test for org\bovigo\vfs\vfsStreamWrapper in conjunction with ext/zip.
 *
 * @group  zip
 */
class vfsStreamZipTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * set up test environment
     */
    public function setUp()
    {
        if (extension_loaded('zip') === false) {
            $this->markTestSkipped('No ext/zip installed, skipping test.');
        }

        $this->markTestSkipped('Zip extension can not work with vfsStream urls.');

        vfsStreamWrapper::register();
        vfsStreamWrapper::setRoot(vfsStream::newDirectory('root'));

    }

    /**
     * @test
     */
    public function createZipArchive()
    {
        $zip = new ZipArchive();
        $this->assertTrue($zip->open(vfsStream::url('root/test.zip'), ZIPARCHIVE::CREATE));
        $this->assertTrue($zip->addFromString("testfile1.txt", "#1 This is a test string added as testfile1.txt.\n"));
        $this->assertTrue($zip->addFromString("testfile2.txt", "#2 This is a test string added as testfile2.txt.\n"));
        $zip->setArchiveComment('a test');
        var_dump($zip);
        $this->assertTrue($zip->close());
        var_dump($zip->getStatusString());
        var_dump($zip->close());
        var_dump($zip->getStatusString());
        var_dump($zip);
        var_dump(file_exists(vfsStream::url('root/test.zip')));
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
require_once __DIR__ . '/vfsStreamWrapperBaseTestCase.php';
/**
 * Test for org\bovigo\vfs\vfsStreamWrapper.
 */
class vfsStreamWrapperFileTestCase extends vfsStreamWrapperBaseTestCase
{
    /**
     * assert that file_get_contents() delivers correct file contents
     *
     * @test
     */
    public function file_get_contents()
    {
        $this->assertEquals('baz2', file_get_contents($this->baz2URL));
        $this->assertEquals('baz 1', file_get_contents($this->baz1URL));
        $this->assertFalse(@file_get_contents($this->barURL));
        $this->assertFalse(@file_get_contents($this->fooURL));
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function file_get_contentsNonReadableFile()
    {
        vfsStreamWrapper::register();
        vfsStreamWrapper::setRoot(new vfsStreamDirectory('root'));
        vfsStream::newFile('new.txt', 0000)->at(vfsStreamWrapper::getRoot())->withContent('content');
        $this->assertEquals('', @file_get_contents(vfsStream::url('root/new.txt')));
    }

    /**
     * assert that file_put_contents() delivers correct file contents
     *
     * @test
     */
    public function file_put_contentsExistingFile()
    {
        $this->assertEquals(14, file_put_contents($this->baz2URL, 'baz is not bar'));
        $this->assertEquals('baz is not bar', $this->baz2->getContent());
        $this->assertEquals(6, file_put_contents($this->baz1URL, 'foobar'));
        $this->assertEquals('foobar', $this->baz1->getContent());
        $this->assertFalse(@file_put_contents($this->barURL, 'This does not work.'));
        $this->assertFalse(@file_put_contents($this->fooURL, 'This does not work, too.'));
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function file_put_contentsExistingFileNonWritableDirectory()
    {
        vfsStreamWrapper::register();
        vfsStreamWrapper::setRoot(new vfsStreamDirectory('root', 0000));
        vfsStream::newFile('new.txt')->at(vfsStreamWrapper::getRoot())->withContent('content');
        $this->assertEquals(15, @file_put_contents(vfsStream::url('root/new.txt'), 'This does work.'));
        $this->assertEquals('This does work.', file_get_contents(vfsStream::url('root/new.txt')));

    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function file_put_contentsExistingNonWritableFile()
    {
        vfsStreamWrapper::register();
        vfsStreamWrapper::setRoot(new vfsStreamDirectory('root'));
        vfsStream::newFile('new.txt', 0400)->at(vfsStreamWrapper::getRoot())->withContent('content');
        $this->assertFalse(@file_put_contents(vfsStream::url('root/new.txt'), 'This does not work.'));
        $this->assertEquals('content', file_get_contents(vfsStream::url('root/new.txt')));
    }

    /**
     * assert that file_put_contents() delivers correct file contents
     *
     * @test
     */
    public function file_put_contentsNonExistingFile()
    {
        $this->assertEquals(14, file_put_contents($this->fooURL . '/baznot.bar', 'baz is not bar'));
        $this->assertEquals(3, count($this->foo->getChildren()));
        $this->assertEquals(14, file_put_contents($this->barURL . '/baznot.bar', 'baz is not bar'));
        $this->assertEquals(2, count($this->bar->getChildren()));
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function file_put_contentsNonExistingFileNonWritableDirectory()
    {
        vfsStreamWrapper::register();
        vfsStreamWrapper::setRoot(new vfsStreamDirectory('root', 0000));
        $this->assertFalse(@file_put_contents(vfsStream::url('root/new.txt'), 'This does not work.'));
        $this->assertFalse(file_exists(vfsStream::url('root/new.txt')));

    }

    /**
     * using a file pointer should work without any problems
     *
     * @test
     */
    public function usingFilePointer()
    {
        $fp = fopen($this->baz1URL, 'r');
        $this->assertEquals(0, ftell($fp));
        $this->assertFalse(feof($fp));
        $this->assertEquals(0, fseek($fp, 2));
        $this->assertEquals(2, ftell($fp));
        $this->assertEquals(0, fseek($fp, 1, SEEK_CUR));
        $this->assertEquals(3, ftell($fp));
        $this->assertEquals(0, fseek($fp, 1, SEEK_END));
        $this->assertEquals(6, ftell($fp));
        $this->assertTrue(feof($fp));
        $this->assertEquals(0, fseek($fp, 2));
        $this->assertFalse(feof($fp));
        $this->assertEquals(2, ftell($fp));
        $this->assertEquals('z', fread($fp, 1));
        $this->assertEquals(3, ftell($fp));
        $this->assertEquals(' 1', fread($fp, 8092));
        $this->assertEquals(5, ftell($fp));
        $this->assertTrue(fclose($fp));
    }

    /**
     * assert is_file() returns correct result
     *
     * @test
     */
    public function is_file()
    {
        $this->assertFalse(is_file($this->fooURL));
        $this->assertFalse(is_file($this->barURL));
        $this->assertTrue(is_file($this->baz1URL));
        $this->assertTrue(is_file($this->baz2URL));
        $this->assertFalse(is_file($this->fooURL . '/another'));
        $this->assertFalse(is_file(vfsStream::url('another')));
    }

    /**
     * @test
     * @group  issue7
     * @group  issue13
     */
    public function issue13CanNotOverwriteFiles()
    {
        $vfsFile = vfsStream::url('foo/overwrite.txt');
        file_put_contents($vfsFile, 'test');
        file_put_contents($vfsFile, 'd');
        $this->assertEquals('d', file_get_contents($vfsFile));
    }

    /**
     * @test
     * @group  issue7
     * @group  issue13
     */
    public function appendContentIfOpenedWithModeA()
    {
        $vfsFile = vfsStream::url('foo/overwrite.txt');
        file_put_contents($vfsFile, 'test');
        $fp = fopen($vfsFile, 'ab');
        fwrite($fp, 'd');
        fclose($fp);
        $this->assertEquals('testd', file_get_contents($vfsFile));
    }

    /**
     * @test
     * @group  issue7
     * @group  issue13
     */
    public function canOverwriteNonExistingFileWithModeX()
    {
        $vfsFile = vfsStream::url('foo/overwrite.txt');
        $fp = fopen($vfsFile, 'xb');
        fwrite($fp, 'test');
        fclose($fp);
        $this->assertEquals('test', file_get_contents($vfsFile));
    }

    /**
     * @test
     * @group  issue7
     * @group  issue13
     */
    public function canNotOverwriteExistingFileWithModeX()
    {
        $vfsFile = vfsStream::url('foo/overwrite.txt');
        file_put_contents($vfsFile, 'test');
        $this->assertFalse(@fopen($vfsFile, 'xb'));
        $this->assertEquals('test', file_get_contents($vfsFile));
    }

    /**
     * @test
     * @group  issue7
     * @group  issue13
     */
    public function canNotOpenNonExistingFileReadonly()
    {
        $this->assertFalse(@fopen(vfsStream::url('foo/doesNotExist.txt'), 'rb'));
    }

    /**
     * @test
     * @group  issue7
     * @group  issue13
     */
    public function canNotOpenNonExistingFileReadAndWrite()
    {
        $this->assertFalse(@fopen(vfsStream::url('foo/doesNotExist.txt'), 'rb+'));
    }

    /**
     * @test
     * @group  issue7
     * @group  issue13
     */
    public function canNotOpenWithIllegalMode()
    {
        $this->assertFalse(@fopen($this->baz2URL, 'invalid'));
    }

    /**
     * @test
     * @group  issue7
     * @group  issue13
     */
    public function canNotWriteToReadOnlyFile()
    {
        $fp = fopen($this->baz2URL, 'rb');
        $this->assertEquals('baz2', fread($fp, 4096));
        $this->assertEquals(0, fwrite($fp, 'foo'));
        fclose($fp);
        $this->assertEquals('baz2', file_get_contents($this->baz2URL));
    }

    /**
     * @test
     * @group  issue7
     * @group  issue13
     */
    public function canNotReadFromWriteOnlyFileWithModeW()
    {
        $fp = fopen($this->baz2URL, 'wb');
        $this->assertEquals('', fread($fp, 4096));
        $this->assertEquals(3, fwrite($fp, 'foo'));
        fseek($fp, 0);
        $this->assertEquals('', fread($fp, 4096));
        fclose($fp);
        $this->assertEquals('foo', file_get_contents($this->baz2URL));
    }

    /**
     * @test
     * @group  issue7
     * @group  issue13
     */
    public function canNotReadFromWriteOnlyFileWithModeA()
    {
        $fp = fopen($this->baz2URL, 'ab');
        $this->assertEquals('', fread($fp, 4096));
        $this->assertEquals(3, fwrite($fp, 'foo'));
        fseek($fp, 0);
        $this->assertEquals('', fread($fp, 4096));
        fclose($fp);
        $this->assertEquals('baz2foo', file_get_contents($this->baz2URL));
    }

    /**
     * @test
     * @group  issue7
     * @group  issue13
     */
    public function canNotReadFromWriteOnlyFileWithModeX()
    {
        $vfsFile = vfsStream::url('foo/modeXtest.txt');
        $fp = fopen($vfsFile, 'xb');
        $this->assertEquals('', fread($fp, 4096));
        $this->assertEquals(3, fwrite($fp, 'foo'));
        fseek($fp, 0);
        $this->assertEquals('', fread($fp, 4096));
        fclose($fp);
        $this->assertEquals('foo', file_get_contents($vfsFile));
    }

    /**
     * @test
     * @group  permissions
     * @group  bug_15
     */
    public function canNotRemoveFileFromDirectoryWithoutWritePermissions()
    {
        vfsStreamWrapper::register();
        vfsStreamWrapper::setRoot(new vfsStreamDirectory('root', 0000));
        vfsStream::newFile('new.txt')->at(vfsStreamWrapper::getRoot());
        $this->assertFalse(unlink(vfsStream::url('root/new.txt')));
        $this->assertTrue(file_exists(vfsStream::url('root/new.txt')));
    }

    /**
     * @test
     * @group  issue_30
     */
    public function truncatesFileWhenOpenedWithModeW()
    {
        $vfsFile = vfsStream::url('foo/overwrite.txt');
        file_put_contents($vfsFile, 'test');
        $fp = fopen($vfsFile, 'wb');
        $this->assertEquals('', file_get_contents($vfsFile));
        fclose($fp);
    }

    /**
     * @test
     * @group  issue_30
     */
    public function createsNonExistingFileWhenOpenedWithModeC()
    {
        $vfsFile = vfsStream::url('foo/tobecreated.txt');
        $fp = fopen($vfsFile, 'cb');
        fwrite($fp, 'some content');
        $this->assertTrue($this->foo->hasChild('tobecreated.txt'));
        fclose($fp);
        $this->assertEquals('some content', file_get_contents($vfsFile));
    }

    /**
     * @test
     * @group  issue_30
     */
    public function createsNonExistingFileWhenOpenedWithModeCplus()
    {
        $vfsFile = vfsStream::url('foo/tobecreated.txt');
        $fp = fopen($vfsFile, 'cb+');
        fwrite($fp, 'some content');
        $this->assertTrue($this->foo->hasChild('tobecreated.txt'));
        fclose($fp);
        $this->assertEquals('some content', file_get_contents($vfsFile));
    }

    /**
     * @test
     * @group  issue_30
     */
    public function doesNotTruncateFileWhenOpenedWithModeC()
    {
        $vfsFile = vfsStream::url('foo/overwrite.txt');
        file_put_contents($vfsFile, 'test');
        $fp = fopen($vfsFile, 'cb');
        $this->assertEquals('test', file_get_contents($vfsFile));
        fclose($fp);
    }

    /**
     * @test
     * @group  issue_30
     */
    public function setsPointerToStartWhenOpenedWithModeC()
    {
        $vfsFile = vfsStream::url('foo/overwrite.txt');
        file_put_contents($vfsFile, 'test');
        $fp = fopen($vfsFile, 'cb');
        $this->assertEquals(0, ftell($fp));
        fclose($fp);
    }

    /**
     * @test
     * @group  issue_30
     */
    public function doesNotTruncateFileWhenOpenedWithModeCplus()
    {
        $vfsFile = vfsStream::url('foo/overwrite.txt');
        file_put_contents($vfsFile, 'test');
        $fp = fopen($vfsFile, 'cb+');
        $this->assertEquals('test', file_get_contents($vfsFile));
        fclose($fp);
    }

    /**
     * @test
     * @group  issue_30
     */
    public function setsPointerToStartWhenOpenedWithModeCplus()
    {
        $vfsFile = vfsStream::url('foo/overwrite.txt');
        file_put_contents($vfsFile, 'test');
        $fp = fopen($vfsFile, 'cb+');
        $this->assertEquals(0, ftell($fp));
        fclose($fp);
    }

    /**
     * @test
     */
    public function cannotOpenExistingNonwritableFileWithModeA()
    {
        $this->baz1->chmod(0400);
        $this->assertFalse(@fopen($this->baz1URL, 'a'));
    }

    /**
     * @test
     */
    public function cannotOpenExistingNonwritableFileWithModeW()
    {
        $this->baz1->chmod(0400);
        $this->assertFalse(@fopen($this->baz1URL, 'w'));
    }

    /**
     * @test
     */
    public function cannotOpenNonReadableFileWithModeR()
    {
        $this->baz1->chmod(0);
        $this->assertFalse(@fopen($this->baz1URL, 'r'));
    }

    /**
     * @test
     */
    public function cannotRenameToNonWritableDir()
    {
        $this->bar->chmod(0);
        $this->assertFalse(@rename($this->baz2URL, vfsStream::url('foo/bar/baz3')));
    }

    /**
     * @test
     * @group issue_38
     */
    public function cannotReadFileFromNonReadableDir()
    {
        $this->markTestSkipped("Issue #38.");
        $this->bar->chmod(0);
        $this->assertFalse(@file_get_contents($this->baz1URL));
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Test for permissions related functionality.
 *
 * @group  permissions
 */
class PermissionsTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * @type  vfsStreamDirectory
     */
    private $root;

    /**
     * set up test environment
     */
    public function setup()
    {
        $structure = array('test_directory' => array('test.file' => ''));
        $this->root = vfsStream::setup('root', null, $structure);
    }

    /**
     * @test
     * @group  issue_52
     */
    public function canNotChangePermissionWhenDirectoryNotWriteable()
    {
        $this->root->getChild('test_directory')->chmod(0444);
        $this->assertFalse(@chmod(vfsStream::url('root/test_directory/test.file'), 0777));
    }

    /**
     * @test
     * @group  issue_53
     */
    public function canNotChangePermissionWhenFileNotOwned()
    {
        $this->root->getChild('test_directory')->getChild('test.file')->chown(vfsStream::OWNER_USER_1);
        $this->assertFalse(@chmod(vfsStream::url('root/test_directory/test.file'), 0777));
    }

    /**
     * @test
     * @group  issue_52
     */
    public function canNotChangeOwnerWhenDirectoryNotWriteable()
    {
        $this->root->getChild('test_directory')->chmod(0444);
        $this->assertFalse(@chown(vfsStream::url('root/test_directory/test.file'), vfsStream::OWNER_USER_2));
    }

    /**
     * @test
     * @group  issue_53
     */
    public function canNotChangeOwnerWhenFileNotOwned()
    {
        $this->root->getChild('test_directory')->getChild('test.file')->chown(vfsStream::OWNER_USER_1);
        $this->assertFalse(@chown(vfsStream::url('root/test_directory/test.file'), vfsStream::OWNER_USER_2));
    }

    /**
     * @test
     * @group  issue_52
     */
    public function canNotChangeGroupWhenDirectoryNotWriteable()
    {
        $this->root->getChild('test_directory')->chmod(0444);
        $this->assertFalse(@chgrp(vfsStream::url('root/test_directory/test.file'), vfsStream::GROUP_USER_2));
    }

    /**
     * @test
     * @group  issue_53
     */
    public function canNotChangeGroupWhenFileNotOwned()
    {
        $this->root->getChild('test_directory')->getChild('test.file')->chown(vfsStream::OWNER_USER_1);
        $this->assertFalse(@chgrp(vfsStream::url('root/test_directory/test.file'), vfsStream::GROUP_USER_2));
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Test for org\bovigo\vfs\vfsStreamWrapper.
 *
 * @since  0.9.0
 */
class vfsStreamWrapperFileTimesTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * URL of foo.txt file
     *
     * @var  string
     */
    protected $fooUrl;
    /**
     * URL of bar directory
     *
     * @var  string
     */
    protected $barUrl;
    /**
     * URL of baz.txt file
     *
     * @var  string
     */
    protected $bazUrl;

    /**
     * set up test environment
     */
    public function setUp()
    {
        vfsStream::setup()
                 ->lastModified(50)
                 ->lastAccessed(50)
                 ->lastAttributeModified(50);
        $this->fooUrl = vfsStream::url('root/foo.txt');
        $this->barUrl = vfsStream::url('root/bar');
        $this->bazUrl = vfsStream::url('root/bar/baz.txt');
    }

    /**
     * helper assertion for the tests
     *
     * @param  string            $url      url to check
     * @param  vfsStreamContent  $content  content to compare
     */
    protected function assertFileTimesEqualStreamTimes($url, vfsStreamContent $content)
    {
        $this->assertEquals(filemtime($url), $content->filemtime());
        $this->assertEquals(fileatime($url), $content->fileatime());
        $this->assertEquals(filectime($url), $content->filectime());
    }

    /**
     * @test
     * @group  issue_7
     * @group  issue_26
     */
    public function openFileChangesAttributeTimeOnly()
    {
        $file = vfsStream::newFile('foo.txt')
                         ->withContent('test')
                         ->at(vfsStreamWrapper::getRoot())
                         ->lastModified(100)
                         ->lastAccessed(100)
                         ->lastAttributeModified(100);
        fclose(fopen($this->fooUrl, 'rb'));
        $this->assertGreaterThan(time() - 2, fileatime($this->fooUrl));
        $this->assertLessThanOrEqual(time(), fileatime($this->fooUrl));
        $this->assertLessThanOrEqual(100, filemtime($this->fooUrl));
        $this->assertEquals(100, filectime($this->fooUrl));
        $this->assertFileTimesEqualStreamTimes($this->fooUrl, $file);
    }

    /**
     * @test
     * @group  issue_7
     * @group  issue_26
     */
    public function fileGetContentsChangesAttributeTimeOnly()
    {
        $file = vfsStream::newFile('foo.txt')
                         ->withContent('test')
                         ->at(vfsStreamWrapper::getRoot())
                         ->lastModified(100)
                         ->lastAccessed(100)
                         ->lastAttributeModified(100);
        file_get_contents($this->fooUrl);
        $this->assertGreaterThan(time() - 2, fileatime($this->fooUrl));
        $this->assertLessThanOrEqual(time(), fileatime($this->fooUrl));
        $this->assertLessThanOrEqual(100, filemtime($this->fooUrl));
        $this->assertEquals(100, filectime($this->fooUrl));
        $this->assertFileTimesEqualStreamTimes($this->fooUrl, $file);
    }

    /**
     * @test
     * @group  issue_7
     * @group  issue_26
     */
    public function openFileWithTruncateChangesAttributeAndModificationTime()
    {
        $file = vfsStream::newFile('foo.txt')
                         ->withContent('test')
                         ->at(vfsStreamWrapper::getRoot())
                         ->lastModified(100)
                         ->lastAccessed(100)
                         ->lastAttributeModified(100);
        fclose(fopen($this->fooUrl, 'wb'));
        $this->assertGreaterThan(time() - 2, filemtime($this->fooUrl));
        $this->assertGreaterThan(time() - 2, fileatime($this->fooUrl));
        $this->assertLessThanOrEqual(time(), filemtime($this->fooUrl));
        $this->assertLessThanOrEqual(time(), fileatime($this->fooUrl));
        $this->assertEquals(100, filectime($this->fooUrl));
        $this->assertFileTimesEqualStreamTimes($this->fooUrl, $file);
    }

    /**
     * @test
     * @group  issue_7
     */
    public function readFileChangesAccessTime()
    {
        $file = vfsStream::newFile('foo.txt')
                         ->withContent('test')
                         ->at(vfsStreamWrapper::getRoot())
                         ->lastModified(100)
                         ->lastAccessed(100)
                         ->lastAttributeModified(100);
        $fp = fopen($this->fooUrl, 'rb');
        $openTime = time();
        sleep(3);
        fread($fp, 1024);
        fclose($fp);
        $this->assertLessThanOrEqual($openTime, filemtime($this->fooUrl));
        $this->assertLessThanOrEqual($openTime + 3, fileatime($this->fooUrl));
        $this->assertEquals(100, filectime($this->fooUrl));
        $this->assertFileTimesEqualStreamTimes($this->fooUrl, $file);
    }

    /**
     * @test
     * @group  issue_7
     */
    public function writeFileChangesModificationTime()
    {
        $file = vfsStream::newFile('foo.txt')
                         ->at(vfsStreamWrapper::getRoot())
                         ->lastModified(100)
                         ->lastAccessed(100)
                         ->lastAttributeModified(100);
        $fp = fopen($this->fooUrl, 'wb');
        $openTime = time();
        sleep(3);
        fwrite($fp, 'test');
        fclose($fp);
        $this->assertLessThanOrEqual($openTime + 3, filemtime($this->fooUrl));
        $this->assertLessThanOrEqual($openTime, fileatime($this->fooUrl));
        $this->assertEquals(100, filectime($this->fooUrl));
        $this->assertFileTimesEqualStreamTimes($this->fooUrl, $file);

    }

    /**
     * @test
     * @group  issue_7
     */
    public function createNewFileSetsAllTimesToCurrentTime()
    {
        file_put_contents($this->fooUrl, 'test');
        $this->assertLessThanOrEqual(time(), filemtime($this->fooUrl));
        $this->assertEquals(fileatime($this->fooUrl), filectime($this->fooUrl));
        $this->assertEquals(fileatime($this->fooUrl), filemtime($this->fooUrl));
        $this->assertFileTimesEqualStreamTimes($this->fooUrl, vfsStreamWrapper::getRoot()->getChild('foo.txt'));
    }

    /**
     * @test
     * @group  issue_7
     */
    public function createNewFileChangesAttributeAndModificationTimeOfContainingDirectory()
    {
        $dir = vfsStream::newDirectory('bar')
                        ->at(vfsStreamWrapper::getRoot())
                        ->lastModified(100)
                        ->lastAccessed(100)
                        ->lastAttributeModified(100);
        file_put_contents($this->bazUrl, 'test');
        $this->assertLessThanOrEqual(time(), filemtime($this->barUrl));
        $this->assertLessThanOrEqual(time(), filectime($this->barUrl));
        $this->assertEquals(100, fileatime($this->barUrl));
        $this->assertFileTimesEqualStreamTimes($this->barUrl, $dir);
    }

    /**
     * @test
     * @group  issue_7
     */
    public function addNewFileNameWithLinkFunctionChangesAttributeTimeOfOriginalFile()
    {
        $this->markTestSkipped('Links are currently not supported by vfsStream.');
    }

    /**
     * @test
     * @group  issue_7
     */
    public function addNewFileNameWithLinkFunctionChangesAttributeAndModificationTimeOfDirectoryContainingLink()
    {
        $this->markTestSkipped('Links are currently not supported by vfsStream.');
    }

    /**
     * @test
     * @group  issue_7
     */
    public function removeFileChangesAttributeAndModificationTimeOfContainingDirectory()
    {
        $dir = vfsStream::newDirectory('bar')
                        ->at(vfsStreamWrapper::getRoot());
        $file = vfsStream::newFile('baz.txt')
                         ->at($dir)
                         ->lastModified(100)
                         ->lastAccessed(100)
                         ->lastAttributeModified(100);
        $dir->lastModified(100)
            ->lastAccessed(100)
            ->lastAttributeModified(100);
        unlink($this->bazUrl);
        $this->assertLessThanOrEqual(time(), filemtime($this->barUrl));
        $this->assertLessThanOrEqual(time(), filectime($this->barUrl));
        $this->assertEquals(100, fileatime($this->barUrl));
        $this->assertFileTimesEqualStreamTimes($this->barUrl, $dir);
    }

    /**
     * @test
     * @group  issue_7
     */
    public function renameFileChangesAttributeAndModificationTimeOfAffectedDirectories()
    {
        $target = vfsStream::newDirectory('target')
                           ->at(vfsStreamWrapper::getRoot())
                           ->lastModified(200)
                           ->lastAccessed(200)
                           ->lastAttributeModified(200);
        $source = vfsStream::newDirectory('bar')
                           ->at(vfsStreamWrapper::getRoot());
        $file = vfsStream::newFile('baz.txt')
                         ->at($source)
                         ->lastModified(300)
                         ->lastAccessed(300)
                         ->lastAttributeModified(300);
        $source->lastModified(100)
               ->lastAccessed(100)
               ->lastAttributeModified(100);
        rename($this->bazUrl, vfsStream::url('root/target/baz.txt'));
        $this->assertLessThanOrEqual(time(), filemtime($this->barUrl));
        $this->assertLessThanOrEqual(time(), filectime($this->barUrl));
        $this->assertEquals(100, fileatime($this->barUrl));
        $this->assertFileTimesEqualStreamTimes($this->barUrl, $source);
        $this->assertLessThanOrEqual(time(), filemtime(vfsStream::url('root/target')));
        $this->assertLessThanOrEqual(time(), filectime(vfsStream::url('root/target')));
        $this->assertEquals(200, fileatime(vfsStream::url('root/target')));
        $this->assertFileTimesEqualStreamTimes(vfsStream::url('root/target'), $target);
    }

    /**
     * @test
     * @group  issue_7
     */
    public function renameFileDoesNotChangeFileTimesOfFileItself()
    {
        $target = vfsStream::newDirectory('target')
                           ->at(vfsStreamWrapper::getRoot())
                           ->lastModified(200)
                           ->lastAccessed(200)
                           ->lastAttributeModified(200);
        $source = vfsStream::newDirectory('bar')
                           ->at(vfsStreamWrapper::getRoot());
        $file = vfsStream::newFile('baz.txt')
                         ->at($source)
                         ->lastModified(300)
                         ->lastAccessed(300)
                         ->lastAttributeModified(300);
        $source->lastModified(100)
               ->lastAccessed(100)
               ->lastAttributeModified(100);
        rename($this->bazUrl, vfsStream::url('root/target/baz.txt'));
        $this->assertEquals(300, filemtime(vfsStream::url('root/target/baz.txt')));
        $this->assertEquals(300, filectime(vfsStream::url('root/target/baz.txt')));
        $this->assertEquals(300, fileatime(vfsStream::url('root/target/baz.txt')));
        $this->assertFileTimesEqualStreamTimes(vfsStream::url('root/target/baz.txt'), $file);
    }

    /**
     * @test
     * @group  issue_7
     */
    public function changeFileAttributesChangesAttributeTimeOfFileItself()
    {
        $this->markTestSkipped('Changing file attributes via stream wrapper for self-defined streams is not supported by PHP.');
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Test for org\bovigo\vfs\vfsStream.
 */
class vfsStreamTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * set up test environment
     */
    public function setUp()
    {
        vfsStreamWrapper::register();
    }

    /**
     * assure that path2url conversion works correct
     *
     * @test
     */
    public function url()
    {
        $this->assertEquals('vfs://foo', vfsStream::url('foo'));
        $this->assertEquals('vfs://foo/bar.baz', vfsStream::url('foo/bar.baz'));
        $this->assertEquals('vfs://foo/bar.baz', vfsStream::url('foo\bar.baz'));
    }

    /**
     * assure that url2path conversion works correct
     *
     * @test
     */
    public function path()
    {
        $this->assertEquals('foo', vfsStream::path('vfs://foo'));
        $this->assertEquals('foo/bar.baz', vfsStream::path('vfs://foo/bar.baz'));
        $this->assertEquals('foo/bar.baz', vfsStream::path('vfs://foo\bar.baz'));
    }

    /**
     * windows directory separators are converted into default separator
     *
     * @author  Gabriel Birke
     * @test
     */
    public function pathConvertsWindowsDirectorySeparators()
    {
        $this->assertEquals('foo/bar', vfsStream::path('vfs://foo\\bar'));
    }

    /**
     * trailing whitespace should be removed
     *
     * @author  Gabriel Birke
     * @test
     */
    public function pathRemovesTrailingWhitespace()
    {
        $this->assertEquals('foo/bar', vfsStream::path('vfs://foo/bar '));
    }

    /**
     * trailing slashes are removed
     *
     * @author  Gabriel Birke
     * @test
     */
    public function pathRemovesTrailingSlash()
    {
        $this->assertEquals('foo/bar', vfsStream::path('vfs://foo/bar/'));
    }

    /**
     * trailing slash and whitespace should be removed
     *
     * @author  Gabriel Birke
     * @test
     */
    public function pathRemovesTrailingSlashAndWhitespace()
    {
        $this->assertEquals('foo/bar', vfsStream::path('vfs://foo/bar/ '));
    }

    /**
     * double slashes should be replaced by single slash
     *
     * @author  Gabriel Birke
     * @test
     */
    public function pathRemovesDoubleSlashes()
    {
        // Regular path
        $this->assertEquals('my/path', vfsStream::path('vfs://my/path'));
        // Path with double slashes
        $this->assertEquals('my/path', vfsStream::path('vfs://my//path'));
    }

    /**
     * test to create a new file
     *
     * @test
     */
    public function newFile()
    {
        $file = vfsStream::newFile('filename.txt');
        $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamFile', $file);
        $this->assertEquals('filename.txt', $file->getName());
        $this->assertEquals(0666, $file->getPermissions());
    }

    /**
     * test to create a new file with non-default permissions
     *
     * @test
     * @group  permissions
     */
    public function newFileWithDifferentPermissions()
    {
        $file = vfsStream::newFile('filename.txt', 0644);
        $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamFile', $file);
        $this->assertEquals('filename.txt', $file->getName());
        $this->assertEquals(0644, $file->getPermissions());
    }

    /**
     * test to create a new directory structure
     *
     * @test
     */
    public function newSingleDirectory()
    {
        $foo = vfsStream::newDirectory('foo');
        $this->assertEquals('foo', $foo->getName());
        $this->assertEquals(0, count($foo->getChildren()));
        $this->assertEquals(0777, $foo->getPermissions());
    }

    /**
     * test to create a new directory structure with non-default permissions
     *
     * @test
     * @group  permissions
     */
    public function newSingleDirectoryWithDifferentPermissions()
    {
        $foo = vfsStream::newDirectory('foo', 0755);
        $this->assertEquals('foo', $foo->getName());
        $this->assertEquals(0, count($foo->getChildren()));
        $this->assertEquals(0755, $foo->getPermissions());
    }

    /**
     * test to create a new directory structure
     *
     * @test
     */
    public function newDirectoryStructure()
    {
        $foo = vfsStream::newDirectory('foo/bar/baz');
        $this->assertEquals('foo', $foo->getName());
        $this->assertEquals(0777, $foo->getPermissions());
        $this->assertTrue($foo->hasChild('bar'));
        $this->assertTrue($foo->hasChild('bar/baz'));
        $this->assertFalse($foo->hasChild('baz'));
        $bar = $foo->getChild('bar');
        $this->assertEquals('bar', $bar->getName());
        $this->assertEquals(0777, $bar->getPermissions());
        $this->assertTrue($bar->hasChild('baz'));
        $baz1 = $bar->getChild('baz');
        $this->assertEquals('baz', $baz1->getName());
        $this->assertEquals(0777, $baz1->getPermissions());
        $baz2 = $foo->getChild('bar/baz');
        $this->assertSame($baz1, $baz2);
    }

    /**
     * test that correct directory structure is created
     *
     * @test
     */
    public function newDirectoryWithSlashAtStart()
    {
        $foo = vfsStream::newDirectory('/foo/bar/baz', 0755);
        $this->assertEquals('foo', $foo->getName());
        $this->assertEquals(0755, $foo->getPermissions());
        $this->assertTrue($foo->hasChild('bar'));
        $this->assertTrue($foo->hasChild('bar/baz'));
        $this->assertFalse($foo->hasChild('baz'));
        $bar = $foo->getChild('bar');
        $this->assertEquals('bar', $bar->getName());
        $this->assertEquals(0755, $bar->getPermissions());
        $this->assertTrue($bar->hasChild('baz'));
        $baz1 = $bar->getChild('baz');
        $this->assertEquals('baz', $baz1->getName());
        $this->assertEquals(0755, $baz1->getPermissions());
        $baz2 = $foo->getChild('bar/baz');
        $this->assertSame($baz1, $baz2);
    }

    /**
     * @test
     * @group  setup
     * @since  0.7.0
     */
    public function setupRegistersStreamWrapperAndCreatesRootDirectoryWithDefaultNameAndPermissions()
    {
        $root = vfsStream::setup();
        $this->assertSame($root, vfsStreamWrapper::getRoot());
        $this->assertEquals('root', $root->getName());
        $this->assertEquals(0777, $root->getPermissions());
    }

    /**
     * @test
     * @group  setup
     * @since  0.7.0
     */
    public function setupRegistersStreamWrapperAndCreatesRootDirectoryWithGivenNameAndDefaultPermissions()
    {
        $root = vfsStream::setup('foo');
        $this->assertSame($root, vfsStreamWrapper::getRoot());
        $this->assertEquals('foo', $root->getName());
        $this->assertEquals(0777, $root->getPermissions());
    }

    /**
     * @test
     * @group  setup
     * @since  0.7.0
     */
    public function setupRegistersStreamWrapperAndCreatesRootDirectoryWithGivenNameAndPermissions()
    {
        $root = vfsStream::setup('foo', 0444);
        $this->assertSame($root, vfsStreamWrapper::getRoot());
        $this->assertEquals('foo', $root->getName());
        $this->assertEquals(0444, $root->getPermissions());
    }

    /**
     * @test
     * @group  issue_14
     * @group  issue_20
     * @since  0.10.0
     */
    public function setupWithEmptyArrayIsEqualToSetup()
    {
        $root = vfsStream::setup('example',
                                 0755,
                                 array()
                );
        $this->assertEquals('example', $root->getName());
        $this->assertEquals(0755, $root->getPermissions());
        $this->assertFalse($root->hasChildren());
    }

    /**
     * @test
     * @group  issue_14
     * @group  issue_20
     * @since  0.10.0
     */
    public function setupArraysAreTurnedIntoSubdirectories()
    {
        $root = vfsStream::setup('root',
                                 null,
                                 array('test' => array())
                );
        $this->assertTrue($root->hasChildren());
        $this->assertTrue($root->hasChild('test'));
        $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory',
                                $root->getChild('test')
        );
        $this->assertFalse($root->getChild('test')->hasChildren());
    }

    /**
     * @test
     * @group  issue_14
     * @group  issue_20
     * @since  0.10.0
     */
    public function setupStringsAreTurnedIntoFilesWithContent()
    {
        $root = vfsStream::setup('root',
                                 null,
                                 array('test.txt' => 'some content')
                );
        $this->assertTrue($root->hasChildren());
        $this->assertTrue($root->hasChild('test.txt'));
        $this->assertVfsFile($root->getChild('test.txt'), 'some content');
    }

    /**
     * @test
     * @group  issue_14
     * @group  issue_20
     * @since  0.10.0
     */
    public function setupWorksRecursively()
    {
        $root = vfsStream::setup('root',
                                 null,
                                 array('test' => array('foo'     => array('test.txt' => 'hello'),
                                                       'baz.txt' => 'world'
                                                 )
                                 )
                );
        $this->assertTrue($root->hasChildren());
        $this->assertTrue($root->hasChild('test'));
        $test = $root->getChild('test');
        $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', $test);
        $this->assertTrue($test->hasChildren());
        $this->assertTrue($test->hasChild('baz.txt'));
        $this->assertVfsFile($test->getChild('baz.txt'), 'world');

        $this->assertTrue($test->hasChild('foo'));
        $foo = $test->getChild('foo');
        $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', $foo);
        $this->assertTrue($foo->hasChildren());
        $this->assertTrue($foo->hasChild('test.txt'));
        $this->assertVfsFile($foo->getChild('test.txt'), 'hello');
    }

    /**
    * @test
    * @group  issue_17
    * @group  issue_20
    */
    public function setupCastsNumericDirectoriesToStrings()
    {
        $root = vfsStream::setup('root',
                                 null,
                                 array(2011 => array ('test.txt' => 'some content'))
                );
        $this->assertTrue($root->hasChild('2011'));

        $directory = $root->getChild('2011');
        $this->assertVfsFile($directory->getChild('test.txt'), 'some content');

        $this->assertTrue(file_exists('vfs://root/2011/test.txt'));
    }

    /**
     * @test
     * @group  issue_20
     * @since  0.11.0
     */
    public function createArraysAreTurnedIntoSubdirectories()
    {
        $baseDir = vfsStream::create(array('test' => array()), new vfsStreamDirectory('baseDir'));
        $this->assertTrue($baseDir->hasChildren());
        $this->assertTrue($baseDir->hasChild('test'));
        $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory',
                                $baseDir->getChild('test')
        );
        $this->assertFalse($baseDir->getChild('test')->hasChildren());
    }

    /**
     * @test
     * @group  issue_20
     * @since  0.11.0
     */
    public function createArraysAreTurnedIntoSubdirectoriesOfRoot()
    {
        $root = vfsStream::setup();
        $this->assertSame($root, vfsStream::create(array('test' => array())));
        $this->assertTrue($root->hasChildren());
        $this->assertTrue($root->hasChild('test'));
        $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory',
                                $root->getChild('test')
        );
        $this->assertFalse($root->getChild('test')->hasChildren());
    }

    /**
     * @test
     * @group  issue_20
     * @expectedException  \InvalidArgumentException
     * @since  0.11.0
     */
    public function createThrowsExceptionIfNoBaseDirGivenAndNoRootSet()
    {
        vfsStream::create(array('test' => array()));
    }

    /**
     * @test
     * @group  issue_20
     * @since  0.11.0
     */
    public function createWorksRecursively()
    {
        $baseDir = vfsStream::create(array('test' => array('foo'     => array('test.txt' => 'hello'),
                                                           'baz.txt' => 'world'
                                                     )
                                     ),
                                     new vfsStreamDirectory('baseDir')
                   );
        $this->assertTrue($baseDir->hasChildren());
        $this->assertTrue($baseDir->hasChild('test'));
        $test = $baseDir->getChild('test');
        $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', $test);
        $this->assertTrue($test->hasChildren());
        $this->assertTrue($test->hasChild('baz.txt'));
        $this->assertVfsFile($test->getChild('baz.txt'), 'world');

        $this->assertTrue($test->hasChild('foo'));
        $foo = $test->getChild('foo');
        $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', $foo);
        $this->assertTrue($foo->hasChildren());
        $this->assertTrue($foo->hasChild('test.txt'));
        $this->assertVfsFile($foo->getChild('test.txt'), 'hello');
    }

    /**
     * @test
     * @group  issue_20
     * @since  0.11.0
     */
    public function createWorksRecursivelyWithRoot()
    {
        $root = vfsStream::setup();
        $this->assertSame($root,
                          vfsStream::create(array('test' => array('foo'     => array('test.txt' => 'hello'),
                                                                  'baz.txt' => 'world'
                                                            )
                                            )
                          )
        );
        $this->assertTrue($root->hasChildren());
        $this->assertTrue($root->hasChild('test'));
        $test = $root->getChild('test');
        $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', $test);
        $this->assertTrue($test->hasChildren());
        $this->assertTrue($test->hasChild('baz.txt'));
        $this->assertVfsFile($test->getChild('baz.txt'), 'world');

        $this->assertTrue($test->hasChild('foo'));
        $foo = $test->getChild('foo');
        $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamDirectory', $foo);
        $this->assertTrue($foo->hasChildren());
        $this->assertTrue($foo->hasChild('test.txt'));
        $this->assertVfsFile($foo->getChild('test.txt'), 'hello');
    }

    /**
     * @test
     * @group  issue_20
     * @since  0.10.0
     */
    public function createStringsAreTurnedIntoFilesWithContent()
    {
        $baseDir = vfsStream::create(array('test.txt' => 'some content'), new vfsStreamDirectory('baseDir'));
        $this->assertTrue($baseDir->hasChildren());
        $this->assertTrue($baseDir->hasChild('test.txt'));
        $this->assertVfsFile($baseDir->getChild('test.txt'), 'some content');
    }

    /**
     * @test
     * @group  issue_20
     * @since  0.11.0
     */
    public function createStringsAreTurnedIntoFilesWithContentWithRoot()
    {
        $root = vfsStream::setup();
        $this->assertSame($root,
                          vfsStream::create(array('test.txt' => 'some content'))
        );
        $this->assertTrue($root->hasChildren());
        $this->assertTrue($root->hasChild('test.txt'));
        $this->assertVfsFile($root->getChild('test.txt'), 'some content');
    }

    /**
    * @test
    * @group  issue_20
    * @since  0.11.0
    */
    public function createCastsNumericDirectoriesToStrings()
    {
        $baseDir = vfsStream::create(array(2011 => array ('test.txt' => 'some content')), new vfsStreamDirectory('baseDir'));
        $this->assertTrue($baseDir->hasChild('2011'));

        $directory = $baseDir->getChild('2011');
        $this->assertVfsFile($directory->getChild('test.txt'), 'some content');
    }

    /**
    * @test
    * @group  issue_20
    * @since  0.11.0
    */
    public function createCastsNumericDirectoriesToStringsWithRoot()
    {
        $root = vfsStream::setup();
        $this->assertSame($root,
                          vfsStream::create(array(2011 => array ('test.txt' => 'some content')))
        );
        $this->assertTrue($root->hasChild('2011'));

        $directory = $root->getChild('2011');
        $this->assertVfsFile($directory->getChild('test.txt'), 'some content');
    }

    /**
     * helper function for assertions on vfsStreamFile
     *
     * @param  vfsStreamFile  $file
     * @param  string         $content
     */
    protected function assertVfsFile(vfsStreamFile $file, $content)
    {
        $this->assertInstanceOf('org\\bovigo\\vfs\\vfsStreamFile',
                                $file
        );
        $this->assertEquals($content,
                            $file->getContent()
        );
    }

    /**
     * @test
     * @group  issue_10
     * @since  0.10.0
     */
    public function inspectWithContentGivesContentToVisitor()
    {
        $mockContent = $this->getMock('org\\bovigo\\vfs\\vfsStreamContent');
        $mockVisitor = $this->getMock('org\\bovigo\\vfs\\visitor\\vfsStreamVisitor');
        $mockVisitor->expects($this->once())
                    ->method('visit')
                    ->with($this->equalTo($mockContent))
                    ->will($this->returnValue($mockVisitor));
        $this->assertSame($mockVisitor, vfsStream::inspect($mockVisitor, $mockContent));
    }

    /**
     * @test
     * @group  issue_10
     * @since  0.10.0
     */
    public function inspectWithoutContentGivesRootToVisitor()
    {
        $root = vfsStream::setup();
        $mockVisitor = $this->getMock('org\\bovigo\\vfs\\visitor\\vfsStreamVisitor');
        $mockVisitor->expects($this->once())
                    ->method('visitDirectory')
                    ->with($this->equalTo($root))
                    ->will($this->returnValue($mockVisitor));
        $this->assertSame($mockVisitor, vfsStream::inspect($mockVisitor));
    }

    /**
     * @test
     * @group  issue_10
     * @expectedException  \InvalidArgumentException
     * @since  0.10.0
     */
    public function inspectWithoutContentAndWithoutRootThrowsInvalidArgumentException()
    {
        $mockVisitor = $this->getMock('org\\bovigo\\vfs\\visitor\\vfsStreamVisitor');
        $mockVisitor->expects($this->never())
                    ->method('visit');
        $mockVisitor->expects($this->never())
                    ->method('visitDirectory');
        vfsStream::inspect($mockVisitor);
    }

    /**
     * returns path to file system copy resource directory
     *
     * @return  string
     */
    protected function getFileSystemCopyDir()
    {
        return realpath(dirname(__FILE__) . '/../../../../resources/filesystemcopy');
    }

    /**
     * @test
     * @group  issue_4
     * @expectedException  \InvalidArgumentException
     * @since  0.11.0
     */
    public function copyFromFileSystemThrowsExceptionIfNoBaseDirGivenAndNoRootSet()
    {
        vfsStream::copyFromFileSystem($this->getFileSystemCopyDir());
    }

    /**
     * @test
     * @group  issue_4
     * @since  0.11.0
     */
    public function copyFromEmptyFolder()
    {
        $baseDir = vfsStream::copyFromFileSystem($this->getFileSystemCopyDir() . '/emptyFolder',
                                                 vfsStream::newDirectory('test')
                   );
        $baseDir->removeChild('.gitignore');
        $this->assertFalse($baseDir->hasChildren());
    }

    /**
     * @test
     * @group  issue_4
     * @since  0.11.0
     */
    public function copyFromEmptyFolderWithRoot()
    {
        $root = vfsStream::setup();
        $this->assertEquals($root,
                            vfsStream::copyFromFileSystem($this->getFileSystemCopyDir() . '/emptyFolder')
        );
        $root->removeChild('.gitignore');
        $this->assertFalse($root->hasChildren());
    }

    /**
     * @test
     * @group  issue_4
     * @since  0.11.0
     */
    public function copyFromWithSubFolders()
    {
        $baseDir = vfsStream::copyFromFileSystem($this->getFileSystemCopyDir(),
                                                 vfsStream::newDirectory('test'),
                                                 3
                   );
        $this->assertTrue($baseDir->hasChildren());
        $this->assertTrue($baseDir->hasChild('emptyFolder'));
        $this->assertTrue($baseDir->hasChild('withSubfolders'));
        $subfolderDir = $baseDir->getChild('withSubfolders');
        $this->assertTrue($subfolderDir->hasChild('subfolder1'));
        $this->assertTrue($subfolderDir->getChild('subfolder1')->hasChild('file1.txt'));
        $this->assertVfsFile($subfolderDir->getChild('subfolder1/file1.txt'), '');
        $this->assertTrue($subfolderDir->hasChild('subfolder2'));
        $this->assertTrue($subfolderDir->hasChild('aFile.txt'));
        $this->assertVfsFile($subfolderDir->getChild('aFile.txt'), 'foo');
    }

    /**
     * @test
     * @group  issue_4
     * @since  0.11.0
     */
    public function copyFromWithSubFoldersWithRoot()
    {
        $root = vfsStream::setup();
        $this->assertEquals($root,
                            vfsStream::copyFromFileSystem($this->getFileSystemCopyDir(),
                                                          null,
                                                          3
                            )
        );
        $this->assertTrue($root->hasChildren());
        $this->assertTrue($root->hasChild('emptyFolder'));
        $this->assertTrue($root->hasChild('withSubfolders'));
        $subfolderDir = $root->getChild('withSubfolders');
        $this->assertTrue($subfolderDir->hasChild('subfolder1'));
        $this->assertTrue($subfolderDir->getChild('subfolder1')->hasChild('file1.txt'));
        $this->assertVfsFile($subfolderDir->getChild('subfolder1/file1.txt'), '');
        $this->assertTrue($subfolderDir->hasChild('subfolder2'));
        $this->assertTrue($subfolderDir->hasChild('aFile.txt'));
        $this->assertVfsFile($subfolderDir->getChild('aFile.txt'), 'foo');
    }

    /**
     * @test
     * @group  issue_4
     * @group  issue_29
     * @since  0.11.2
     */
    public function copyFromPreservesFilePermissions()
    {
        if (DIRECTORY_SEPARATOR !== '/') {
            $this->markTestSkipped('Only applicable on Linux style systems.');
        }

        $copyDir = $this->getFileSystemCopyDir();
        $root    = vfsStream::setup();
        $this->assertEquals($root,
                            vfsStream::copyFromFileSystem($copyDir,
                                                          null
                            )
        );
        $this->assertEquals(fileperms($copyDir . '/withSubfolders') - vfsStreamContent::TYPE_DIR,
                            $root->getChild('withSubfolders')
                                 ->getPermissions()
        );
        $this->assertEquals(fileperms($copyDir . '/withSubfolders/aFile.txt') - vfsStreamContent::TYPE_FILE,
                            $root->getChild('withSubfolders/aFile.txt')
                                 ->getPermissions()
        );
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Test for org\bovigo\vfs\vfsStreamWrapper.
 */
class vfsStreamWrapperWithoutRootTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * set up test environment
     */
    public function setUp()
    {
        vfsStreamWrapper::register();
    }

    /**
     * no root > no directory to open
     *
     * @test
     */
    public function canNotOpenDirectory()
    {
        $this->assertFalse(@dir(vfsStream::url('foo')));
    }

    /**
     * can not unlink without root
     *
     * @test
     */
    public function canNotUnlink()
    {
        $this->assertFalse(@unlink(vfsStream::url('foo')));
    }

    /**
     * can not open a file without root
     *
     * @test
     */
    public function canNotOpen()
    {
        $this->assertFalse(@fopen(vfsStream::url('foo')));
    }

    /**
     * can not rename a file without root
     *
     * @test
     */
    public function canNotRename()
    {
        $this->assertFalse(@rename(vfsStream::url('foo'), vfsStream::url('bar')));
    }
}
?>
<?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Test for org\bovigo\vfs\vfsStream.
 *
 * @since       0.9.0
 * @group       issue_2
 */
class vfsStreamGlobTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * @test
     */
    public function globDoesNotWorkWithVfsStreamUrls()
    {
        $root = vfsStream::setup('example');
        mkdir(vfsStream::url('example/test/'), 0777, true);
        $this->assertEmpty(glob(vfsStream::url('example'), GLOB_MARK));
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs;
/**
 * Helper class for the test.
 */
class TestvfsStreamWrapper extends vfsStreamWrapper
{
    /**
     * unregisters vfsStreamWrapper
     */
    public static function unregister()
    {
        if (in_array(vfsStream::SCHEME, stream_get_wrappers()) === true) {
            stream_wrapper_unregister(vfsStream::SCHEME);
        }

        self::$registered = false;
    }
}
/**
 * Test for org\bovigo\vfs\vfsStreamWrapper.
 */
class vfsStreamWrapperAlreadyRegisteredTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * set up test environment
     */
    public function setUp()
    {
        TestvfsStreamWrapper::unregister();
        $mock = $this->getMock('org\\bovigo\\vfs\\vfsStreamWrapper');
        stream_wrapper_register(vfsStream::SCHEME, get_class($mock));
    }

    /**
     * clean up test environment
     */
    public function tearDown()
    {
        TestvfsStreamWrapper::unregister();
    }

    /**
     * registering the stream wrapper when another stream wrapper is already
     * registered for the vfs scheme should throw an exception
     *
     * @test
     * @expectedException  org\bovigo\vfs\vfsStreamException
     */
    public function registerOverAnotherStreamWrapper()
    {
        vfsStreamWrapper::register();
    }
}
?>foofoobarCopyright (c) 2007-2013, Frank Kleine
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

* Redistributions of source code must retain the above copyright
  notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
  notice, this list of conditions and the following disclaimer in the
  documentation and/or other materials provided with the distribution.
* Neither the name of Stubbles nor the names of its
  contributors may be used to endorse or promote products derived
  from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         bootstrap="vendor/autoload.php"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         forceCoversAnnotation="false"
         mapTestClassNameToCoveredClassName="false"
         printerClass="PHPUnit_TextUI_ResultPrinter"
         processIsolation="false"
         stopOnError="false"
         stopOnFailure="false"
         stopOnIncomplete="false"
         stopOnSkipped="false"
         strict="false"
         verbose="true">
  <testsuites>
    <testsuite>
      <directory suffix="TestCase.php">./src/test/php</directory>
    </testsuite>
  </testsuites>

  <filter>
    <whitelist>
      <directory>src/main/php</directory>
    </whitelist>
  </filter>

  <logging>
    <log type="coverage-html" target="docs/coverage" charset="UTF-8"
         yui="true" highlight="false"
         lowUpperBound="35" highLowerBound="70"/>
    <log type="junit" target="docs/phpunit/junit.xml" logIncompleteSkipped="false"/>
    <log type="testdox-html" target="docs/phpunit/testdox.html"/>
  </logging>

  <php>
    <ini name="memory_limit" value="-1"/>
  </php>
</phpunit>1.2.0, 2013-04-01
==================
- implemented issue #34: provide url() method on all vfsStreamContent instances
    - added org\bovigo\vfs\vfsStreamContent::url()
    - added org\bovigo\vfs\vfsStreamContent::path()
- fixed issue #40: flock implementation doesn't work correctly, patch provided
  by Kamil Dziedzic
- fixed issue #49: call to member function on a non-object when trying to delete
  a file one above root where a file with same name in root exists
- fixed issue #51: unlink() must consider permissions of directory where file is
  inside, not of the file to unlink itself
- fixed issue #52: chmod(), chown() and chgrp() must consider permissions of
  directory where file/directory is inside
- fixed issue #53: chmod(), chown() and chgrp() must consider current user and
  current owner of file/directoy to change


1.1.0, 2012-08-25
==================
- implemented issue #11: add support for streamWrapper::stream_metadata()
  vfsStream now supports touch(), chown(), chgrp() and chmod()
- implemented issue #33: add support for stream_truncate
  (provided by https://github.com/nikcorg)
- implemented issue #35: size limit (quota) for VFS


1.0.0, 2012-05-15
==================
- raised requirement for PHP version to 5.3.0
- migrated codebase to use namespaces
- changed distribution from PEAR to Composer
- implemented issue #30: support "c" mode for fopen()
- fixed issue #31: prohibit aquiring locks when already locked / release lock on
  fclose()
- fixed issue #32: problems when subfolder has same name as folder
- fixed issue #36: vfsStreamWrapper::stream_open should return false while
  trying to open existing non-writable file, patch provided by Alexander Peresypkin


0.11.2, 2012-01-14
==================
- fixed issue #29: set permissions properly when using
  vfsStream::copyFromFileSystem(), patch provided by predakanga
- fixed failing tests under PHP > 5.3.2


0.11.1, 2011-12-04
==================
- fixed issue #28: mkdir overwrites existing directories/files


0.11.0, 2011-11-29
==================
- implemented issue #20: vfsStream::create() removes old structure
- implemented issue #4: possibility to copy structure from existing file system
- fixed issue #23: unlink should not remove any directory
- fixed issue #25: vfsStreamDirectory::hasChild() gives false positives for
  nested paths, patch provided by Andrew Coulton
- fixed issue #26: opening a file for reading only should not update its
  modification time, reported and initial patch provided by Ludovic Chabant


0.10.1, 2011-08-22
==================
- fixed issue #16: replace vfsStreamContent to vfsStreamContainer for
  autocompletion
- fixed issue #17: vfsStream::create() has issues with numeric directories,
  patch provided by mathieuk


0.10.0, 2011-07-22
==================
- added new method vfsStreamContainer::hasChildren() and
  vfsStreamDirectory::hasChildren()
- implemented issue #14: less verbose way to initialize vfsStream
- implemented issue #13: remove deprecated method vfsStreamContent::setFilemtime()
- implemented issue #6: locking meachanism for files
- ensured that stream_set_blocking(), stream_set_timeout() and
  stream_set_write_buffer() on vfsStream urls have the same behaviour
  with PHP 5.2 and 5.3
- implemented issue #10: method to print directory structure


0.9.0, 2011-07-13
=================
- implemented feature request issue #7: add support for fileatime() and filectime()
- fixed issue #3: add support for streamWrapper::stream_cast()
- fixed issue #9: resolve path not called everywhere its needed
- deprecated vfsStreamAbstractContent::setFilemtime(), use
  vfsStreamAbstractContent::lastModified() instead, will be removed with 0.10.0


0.8.0, 2010-10-08
=================
- implemented enhancement #6: use vfsStream::umask() to influence initial file
  mode for files and directories
- implemented enhancement #19: support of .. in the url, patch provided by
  Guislain Duthieuw
- fixed issue #18: getChild() returns NULL when child's name contains parent name
- fixed bug with incomplete error message when accessing non-existing files on
  root level


0.7.0, 2010-06-08
=================
- added new vfsStream::setup() method to simplify vfsStream usage
- fixed issue #15: mkdir creates a subfolder in a folder without permissions


0.6.0, 2010-02-15
=================
- added support for $mode param when opening files, implements enhancement #7
  and fixes issue #13
- vfsStreamWrapper::stream_open() now evaluates $options for STREAM_REPORT_ERRORS


0.5.0, 2010-01-25
=================
- added support for rename(), patch provided by Benoit Aubuchon
- added support for . as directory alias so that vfs://foo/. resolves to
  vfs://foo, can be used as workaround for bug #8


0.4.0, 2009-07-13
=================
- added support for file modes, users and groups (with restrictions, see
  http://code.google.com/p/bovigo/wiki/vfsStreamDocsKnownIssues)
- fixed bug #5: vfsStreamDirectory::addChild() does not replace child with same
  name
- fixed bug with is_writable() because of missing stat() fields, patch provided
  by Sergey Galkin


0.3.2, 2009-02-16
=================
- support trailing slashes on directories in vfsStream urls, patch provided by
  Gabriel Birke
- fixed bug #4: vfsstream can only be read once, reported by Christoph Bloemer
- enabled multiple iterations at the same time over the same directory


0.3.1, 2008-02-18
=================
- fixed path/directory separator issues under linux systems
- fixed uid/gid issues under linux systems


0.3.0, 2008-01-02
=================
- added support for rmdir()
- added vfsStream::newDirectory(), dropped vfsStreamDirectory::ceate()
- added new interface vfsStreamContainer
- added vfsStreamContent::at() which allows code like
  $file = vfsStream::newFile('file.txt.')->withContent('foo')->at($otherDir);
- added vfsStreamContent::lastModified(), made vfsStreamContent::setFilemtime()
  an alias for this
- moved from Stubbles development environment to bovigo
- refactorings to reduce crap index of various methods


0.2.0, 2007-12-29
=================
- moved vfsStreamWrapper::PROTOCOL to vfsStream::SCHEME
- added new vfsStream::url() method to assist in creating correct vfsStream urls
- added vfsStream::path() method as opposite to vfsStream::url()
- a call to vfsStreamWrapper::register() will now reset the root to null,
  implemented on request from David Zuelke
- added support for is_readable(), is_dir(), is_file()
- added vfsStream::newFile() to be able to do
  $file = vfsStream::newFile("foo.txt")->withContent("bar");


0.1.0, 2007-12-14
=================
Initial release.
<?xml version="1.0" encoding="UTF-8" ?>
<phpdoc>
  <title>vfsStream API Doc</title>
  <parser>
    <target>docs/api</target>
    <default-package-name>org\bovigo\vfs</default-package-name>
  </parser>
  <transformer>
    <target>docs/api</target>
  </transformer>
  <files>
    <directory>src/main/php</directory>
  </files>
</phpdoc><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs\example;
/**
 * Example class.
 */
class FilemodeExample
{
    /**
     * id of the example
     *
     * @type  string
     */
    protected $id;
    /**
     * a directory where we do something..
     *
     * @type  string
     */
    protected $directory;
    /**
     * file mode for newly created directories
     *
     * @type  int
     */
    protected $fileMode;

    /**
     * constructor
     *
     * @param  string  $id
     * @param  int     $fileMode  optional
     */
    public function __construct($id,  $fileMode = 0700)
    {
        $this->id       = $id;
        $this->fileMode = $fileMode;
    }

    /**
     * sets the directory
     *
     * @param  string  $directory
     */
    public function setDirectory($directory)
    {
        $this->directory = $directory . DIRECTORY_SEPARATOR . $this->id;
        if (file_exists($this->directory) === false) {
            mkdir($this->directory, $this->fileMode, true);
        }
    }

    // more source code here...
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs\example;
require_once 'FilemodeExample.php';
/**
 * Test case for class FilemodeExample.
 */
class FilemodeExampleTestCaseOldWay extends \PHPUnit_Framework_TestCase
{
    /**
     * set up test environmemt
     */
    public function setUp()
    {
        if (file_exists(__DIR__ . '/id') === true) {
            rmdir(__DIR__ . '/id');
        }
    }

    /**
     * clear up test environment
     */
    public function tearDown()
    {
        if (file_exists(__DIR__ . '/id') === true) {
            rmdir(__DIR__ . '/id');
        }
    }

    /**
     * test correct file mode for created directory
     */
    public function testDirectoryHasCorrectDefaultFilePermissions()
    {
        $example = new FilemodeExample('id');
        $example->setDirectory(__DIR__);
        if (DIRECTORY_SEPARATOR === '\\') {
            // can not really test on windows, filemode from mkdir() is ignored
            $this->assertEquals(40777, decoct(fileperms(__DIR__ . '/id')));
        } else {
            $this->assertEquals(40700, decoct(fileperms(__DIR__ . '/id')));
        }
    }

    /**
     * test correct file mode for created directory
     */
    public function testDirectoryHasCorrectDifferentFilePermissions()
    {
        $example = new FilemodeExample('id', 0755);
        $example->setDirectory(__DIR__);
        if (DIRECTORY_SEPARATOR === '\\') {
            // can not really test on windows, filemode from mkdir() is ignored
            $this->assertEquals(40777, decoct(fileperms(__DIR__ . '/id')));
        } else {
            $this->assertEquals(40755, decoct(fileperms(__DIR__ . '/id')));
        }
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs\example;
/**
 * Example showing correct file permission support introduced with 0.7.0.
 */
class FilePermissionsExample
{
    /**
     * reads configuration from given config file
     *
     * @param  mixed   $config
     * @param  string  $configFile
     */
    public function writeConfig($config, $configFile)
    {
        @file_put_contents($configFile, serialize($config));
    }

    // more methods here
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs\example;
use org\bovigo\vfs\vfsStream;
require_once 'FilemodeExample.php';
/**
 * Test case for class FilemodeExample.
 */
class FilemodeExampleTestCaseWithVfsStream extends \PHPUnit_Framework_TestCase
{
    /**
     * root directory
     *
     * @type  vfsStreamDirectory
     */
    protected $root;

    /**
     * set up test environmemt
     */
    public function setUp()
    {
        $this->root = vfsStream::setup('exampleDir');
    }

    /**
     * test that the directory is created
     */
    public function testDirectoryIsCreatedWithDefaultPermissions()
    {
        $example = new FilemodeExample('id');
        $example->setDirectory(vfsStream::url('exampleDir'));
        $this->assertEquals(0700, $this->root->getChild('id')->getPermissions());
    }

    /**
     * test that the directory is created
     */
    public function testDirectoryIsCreatedWithGivenPermissions()
    {
        $example = new FilemodeExample('id', 0755);
        $example->setDirectory(vfsStream::url('exampleDir'));
        $this->assertEquals(0755, $this->root->getChild('id')->getPermissions());
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs\example;
use org\bovigo\vfs\vfsStream;
require_once 'FailureExample.php';
/**
 * Test case for class FailureExample.
 */
class FailureExampleTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * root directory
     *
     * @type  vfsStreamDirectory
     */
    protected $root;

    /**
     * set up test environmemt
     */
    public function setUp()
    {
        $this->root = vfsStream::setup('exampleDir');
    }

    /**
     * @test
     */
    public function returnsOkOnNoFailure()
    {
        $example = new FailureExample(vfsStream::url('exampleDir/test.txt'));
        $this->assertSame('ok', $example->writeData('testdata'));
        $this->assertTrue($this->root->hasChild('test.txt'));
        $this->assertSame('testdata', $this->root->getChild('test.txt')->getContent());
    }

    /**
     * @test
     */
    public function returnsErrorMessageIfWritingToFileFails()
    {
        $file = vfsStream::newFile('test.txt', 0000)
                         ->withContent('notoverwritten')
                         ->at($this->root);
        $example = new FailureExample(vfsStream::url('exampleDir/test.txt'));
        $this->assertSame('could not write data', $example->writeData('testdata'));
        $this->assertTrue($this->root->hasChild('test.txt'));
        $this->assertSame('notoverwritten', $this->root->getChild('test.txt')->getContent());
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs\example;
/**
 * Example class to demonstrate testing of failure behaviour with vfsStream.
 */
class FailureExample
{
    /**
     * filename to write data
     *
     * @type  string
     */
    protected $filename;

    /**
     * constructor
     *
     * @param  string  $id
     */
    public function __construct($filename)
    {
        $this->filename = $filename;
    }

    /**
     * sets the directory
     *
     * @param  string  $directory
     */
    public function writeData($data)
    {
        $bytes = @file_put_contents($this->filename, $data);
        if (false === $bytes) {
            return 'could not write data';
        }

        return 'ok';
    }

    // more source code here...
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs\example;
/**
 * Example class.
 */
class Example
{
    /**
     * id of the example
     *
     * @type  string
     */
    protected $id;
    /**
     * a directory where we do something..
     *
     * @type  string
     */
    protected $directory;

    /**
     * constructor
     *
     * @param  string  $id
     */
    public function __construct($id)
    {
        $this->id = $id;
    }

    /**
     * sets the directory
     *
     * @param  string  $directory
     */
    public function setDirectory($directory)
    {
        $this->directory = $directory . DIRECTORY_SEPARATOR . $this->id;
        if (file_exists($this->directory) === false) {
            mkdir($this->directory, 0700, true);
        }
    }

    // more source code here...
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs\example;
use org\bovigo\vfs\vfsStream;
require_once 'Example.php';
/**
 * Test case for class Example.
 *
 * @package     bovigo_vfs
 * @subpackage  examples
 */
class ExampleTestCaseWithVfsStream extends \PHPUnit_Framework_TestCase
{
    /**
     * root directory
     *
     * @type  vfsStreamDirectory
     */
    protected $root;

    /**
     * set up test environmemt
     */
    public function setUp()
    {
        $this->root = vfsStream::setup('exampleDir');
    }

    /**
     * @test
     */
    public function directoryIsCreated()
    {
        $example = new Example('id');
        $this->assertFalse($this->root->hasChild('id'));
        $example->setDirectory(vfsStream::url('exampleDir'));
        $this->assertTrue($this->root->hasChild('id'));
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs\example;
use org\bovigo\vfs\vfsStream;
require_once 'FilePermissionsExample.php';
/**
 * Test for FilePermissionsExample.
 */
class FilePermissionsExampleTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * @test
     */
    public function directoryWritable()
    {
        vfsStream::setup('exampleDir');
        $example = new FilePermissionsExample();
        $example->writeConfig(array('foo' => 'bar'),
                              vfsStream::url('exampleDir/writable.ini')
        );

        // assertions here
    }

    /**
     * @test
     */
    public function directoryNotWritable()
    {
        vfsStream::setup('exampleDir', 0444);
        $example = new FilePermissionsExample();
        $example->writeConfig(array('foo' => 'bar'),
                              vfsStream::url('exampleDir/notWritable.ini')
        );
    }
}
?><?php
/**
 * This file is part of vfsStream.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @package  org\bovigo\vfs
 */
namespace org\bovigo\vfs\example;
require_once 'Example.php';
/**
 * Test case for class Example.
 */
class ExampleTestCaseOldWay extends \PHPUnit_Framework_TestCase
{
    /**
     * set up test environmemt
     */
    public function setUp()
    {
        if (file_exists(__DIR__ . '/id') === true) {
            rmdir(__DIR__ . '/id');
        }
    }

    /**
     * clear up test environment
     */
    public function tearDown()
    {
        if (file_exists(__DIR__ . '/id') === true) {
            rmdir(__DIR__ . '/id');
        }
    }

    /**
     * @test
     */
    public function directoryIsCreated()
    {
        $example = new Example('id');
        $this->assertFalse(file_exists(__DIR__ . '/id'));
        $example->setDirectory(__DIR__);
        $this->assertTrue(file_exists(__DIR__ . '/id'));
    }
}
?><?php
require __DIR__ . '/../vendor/.composer/autoload.php';
?>{
    "name": "twig/twig",
    "type": "library",
    "description": "Twig, the flexible, fast, and secure template language for PHP",
    "keywords": ["templating"],
    "homepage": "http://twig.sensiolabs.org",
    "license": "BSD-3-Clause",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Armin Ronacher",
            "email": "armin.ronacher@active-4.com"
        }
    ],
    "require": {
        "php": ">=5.2.4"
    },
    "autoload": {
        "psr-0" : {
            "Twig_" : "lib/"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.14-dev"
        }
    }
}
Copyright (c) 2009-2013 by the Twig Team, see AUTHORS for more details.

Some rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above
      copyright notice, this list of conditions and the following
      disclaimer in the documentation and/or other materials provided
      with the distribution.

    * The names of the contributors may not be used to endorse or
      promote products derived from this software without specific
      prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Twig, the flexible, fast, and secure template language for PHP
==============================================================

Twig is a template language for PHP, released under the new BSD license (code
and documentation).

Twig uses a syntax similar to the Django and Jinja template languages which
inspired the Twig runtime environment.

More Information
----------------

Read the [documentation][1] for more information.

[1]: http://twig.sensiolabs.org/documentation
Twig is written and maintained by the Twig Team:

Lead Developer:

- Fabien Potencier <fabien.potencier@symfony-project.org>

C Extension Developer:

- Derick Rethans <derick@derickrethans.nl>

Project Founder:

- Armin Ronacher <armin.ronacher@active-4.com>
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="test/bootstrap.php"
>
  <testsuites>
    <testsuite name="Twig Test Suite">
      <directory>./test/Twig/</directory>
    </testsuite>
  </testsuites>

  <filter>
    <whitelist>
      <directory suffix=".php">./lib/Twig/</directory>
    </whitelist>
  </filter>
</phpunit>
dnl config.m4 for extension twig

PHP_ARG_ENABLE(twig, whether to enable twig support,
[  --enable-twig           Enable twig support])

if test "$PHP_TWIG" != "no"; then
  PHP_NEW_EXTENSION(twig, twig.c, $ext_shared)
fi
// vim:ft=javascript

ARG_ENABLE("twig", "Twig support", "no");

if (PHP_TWIG != "no") {
	AC_DEFINE('HAVE_TWIG', 1);
	EXTENSION('twig', 'twig.c');
}
Copyright (c) 2009-2013 by the Twig Team, see AUTHORS for more details.

Some rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above
      copyright notice, this list of conditions and the following
      disclaimer in the documentation and/or other materials provided
      with the distribution.

    * The names of the contributors may not be used to endorse or
      promote products derived from this software without specific
      prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
   +----------------------------------------------------------------------+
   | Twig Extension                                                       |
   +----------------------------------------------------------------------+
   | Copyright (c) 2011 Derick Rethans                                    |
   +----------------------------------------------------------------------+
   | Redistribution and use in source and binary forms, with or without   |
   | modification, are permitted provided that the conditions mentioned   |
   | in the accompanying LICENSE file are met (BSD-3-Clause).             |
   +----------------------------------------------------------------------+
   | Author: Derick Rethans <derick@derickrethans.nl>                     |
   +----------------------------------------------------------------------+
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "php_twig.h"
#include "ext/standard/php_string.h"
#include "ext/standard/php_smart_str.h"

#include "Zend/zend_object_handlers.h"
#include "Zend/zend_interfaces.h"
#include "Zend/zend_exceptions.h"

#ifndef Z_ADDREF_P
#define Z_ADDREF_P(pz)                (pz)->refcount++
#endif

#define FREE_DTOR(z) 	\
	zval_dtor(z); 		\
	efree(z);

#if PHP_VERSION_ID >= 50300
	#define APPLY_TSRMLS_DC TSRMLS_DC
	#define APPLY_TSRMLS_CC TSRMLS_CC
	#define APPLY_TSRMLS_FETCH()
#else
	#define APPLY_TSRMLS_DC
	#define APPLY_TSRMLS_CC
	#define APPLY_TSRMLS_FETCH() TSRMLS_FETCH()
#endif

ZEND_BEGIN_ARG_INFO_EX(twig_template_get_attribute_args, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 6)
	ZEND_ARG_INFO(0, template)
	ZEND_ARG_INFO(0, object)
	ZEND_ARG_INFO(0, item)
	ZEND_ARG_INFO(0, arguments)
	ZEND_ARG_INFO(0, type)
	ZEND_ARG_INFO(0, isDefinedTest)
ZEND_END_ARG_INFO()

zend_function_entry twig_functions[] = {
	PHP_FE(twig_template_get_attributes, twig_template_get_attribute_args)
	{NULL, NULL, NULL}
};


zend_module_entry twig_module_entry = {
	STANDARD_MODULE_HEADER,
	"twig",
	twig_functions,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
	PHP_TWIG_VERSION,
	STANDARD_MODULE_PROPERTIES
};


#ifdef COMPILE_DL_TWIG
ZEND_GET_MODULE(twig)
#endif

int TWIG_ARRAY_KEY_EXISTS(zval *array, zval *key)
{
	if (Z_TYPE_P(array) != IS_ARRAY) {
		return 0;
	}

	switch (Z_TYPE_P(key)) {
		case IS_NULL:
			return zend_hash_exists(Z_ARRVAL_P(array), "", 1);

		case IS_BOOL:
		case IS_DOUBLE:
			convert_to_long(key);
		case IS_LONG:
			return zend_hash_index_exists(Z_ARRVAL_P(array), Z_LVAL_P(key));

		default:
			convert_to_string(key);
			return zend_symtable_exists(Z_ARRVAL_P(array), Z_STRVAL_P(key), Z_STRLEN_P(key) + 1);
	}
}

int TWIG_INSTANCE_OF(zval *object, zend_class_entry *interface TSRMLS_DC)
{
	if (Z_TYPE_P(object) != IS_OBJECT) {
		return 0;
	}
	return instanceof_function(Z_OBJCE_P(object), interface TSRMLS_CC);
}

int TWIG_INSTANCE_OF_USERLAND(zval *object, char *interface TSRMLS_DC)
{
	zend_class_entry **pce;
	if (Z_TYPE_P(object) != IS_OBJECT) {
		return 0;
	}
	if (zend_lookup_class(interface, strlen(interface), &pce TSRMLS_CC) == FAILURE) {
		return 0;
	}
	return instanceof_function(Z_OBJCE_P(object), *pce TSRMLS_CC);
}

zval *TWIG_GET_ARRAYOBJECT_ELEMENT(zval *object, zval *offset TSRMLS_DC)
{
	zend_class_entry *ce = Z_OBJCE_P(object);
	zval *retval;

	if (Z_TYPE_P(object) == IS_OBJECT) {
		SEPARATE_ARG_IF_REF(offset);
		zend_call_method_with_1_params(&object, ce, NULL, "offsetget", &retval, offset);

		zval_ptr_dtor(&offset);

		if (!retval) {
			if (!EG(exception)) {
				zend_error(E_ERROR, "Undefined offset for object of type %s used as array", ce->name);
			}
			return NULL;
		}

		return retval;
	}
	return NULL;
}

int TWIG_ISSET_ARRAYOBJECT_ELEMENT(zval *object, zval *offset TSRMLS_DC)
{
	zend_class_entry *ce = Z_OBJCE_P(object);
	zval *retval;

	if (Z_TYPE_P(object) == IS_OBJECT) {
		SEPARATE_ARG_IF_REF(offset);
		zend_call_method_with_1_params(&object, ce, NULL, "offsetexists", &retval, offset);

		zval_ptr_dtor(&offset);

		if (!retval) {
			if (!EG(exception)) {
				zend_error(E_ERROR, "Undefined offset for object of type %s used as array", ce->name);
			}
			return 0;
		}

		return (retval && Z_TYPE_P(retval) == IS_BOOL && Z_LVAL_P(retval));
	}
	return 0;
}

char *TWIG_STRTOLOWER(const char *str, int str_len)
{
	char *item_dup;

	item_dup = estrndup(str, str_len);
	php_strtolower(item_dup, str_len);
	return item_dup;
}

zval *TWIG_CALL_USER_FUNC_ARRAY(zval *object, char *function, zval *arguments TSRMLS_DC)
{
	zend_fcall_info fci;
	zval ***args = NULL;
	int arg_count = 0;
	HashTable *table;
	HashPosition pos;
	int i = 0;
	zval *retval_ptr;
	zval *zfunction;

	if (arguments) {
		table = HASH_OF(arguments);
		args = safe_emalloc(sizeof(zval **), table->nNumOfElements, 0);

		zend_hash_internal_pointer_reset_ex(table, &pos);

		while (zend_hash_get_current_data_ex(table, (void **)&args[i], &pos) == SUCCESS) {
			i++;
			zend_hash_move_forward_ex(table, &pos);
		}
		arg_count = table->nNumOfElements;
	}

	MAKE_STD_ZVAL(zfunction);
	ZVAL_STRING(zfunction, function, 1);
	fci.size = sizeof(fci);
	fci.function_table = EG(function_table);
	fci.function_name = zfunction;
	fci.symbol_table = NULL;
#if PHP_VERSION_ID >= 50300
	fci.object_ptr = object;
#else
	fci.object_pp = &object;
#endif
	fci.retval_ptr_ptr = &retval_ptr;
	fci.param_count = arg_count;
	fci.params = args;
	fci.no_separation = 0;

	if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE) {
		ALLOC_INIT_ZVAL(retval_ptr);
		ZVAL_BOOL(retval_ptr, 0);
	}

	if (args) {
		efree(fci.params);
	}
	FREE_DTOR(zfunction);
	return retval_ptr;
}

int TWIG_CALL_BOOLEAN(zval *object, char *functionName TSRMLS_DC)
{
	zval *ret;
	int   res;

	ret = TWIG_CALL_USER_FUNC_ARRAY(object, functionName, NULL TSRMLS_CC);
	res = Z_LVAL_P(ret);
	zval_ptr_dtor(&ret);
	return res;
}

zval *TWIG_GET_STATIC_PROPERTY(zval *class, char *prop_name TSRMLS_DC)
{
	zval **tmp_zval;
	zend_class_entry *ce;

	if (class == NULL || Z_TYPE_P(class) != IS_OBJECT) {
		return NULL;
	}

	ce = zend_get_class_entry(class TSRMLS_CC);
#if PHP_VERSION_ID >= 50400
	tmp_zval = zend_std_get_static_property(ce, prop_name, strlen(prop_name), 0, NULL TSRMLS_CC);
#else
	tmp_zval = zend_std_get_static_property(ce, prop_name, strlen(prop_name), 0 TSRMLS_CC);
#endif
	return *tmp_zval;
}

zval *TWIG_GET_ARRAY_ELEMENT_ZVAL(zval *class, zval *prop_name TSRMLS_DC)
{
	zval **tmp_zval;

	if (class == NULL || Z_TYPE_P(class) != IS_ARRAY) {
		if (class != NULL && Z_TYPE_P(class) == IS_OBJECT && TWIG_INSTANCE_OF(class, zend_ce_arrayaccess TSRMLS_CC)) {
			// array access object
			return TWIG_GET_ARRAYOBJECT_ELEMENT(class, prop_name TSRMLS_CC);
		}
		return NULL;
	}

	switch(Z_TYPE_P(prop_name)) {
		case IS_NULL:
			zend_hash_find(HASH_OF(class), "", 1, (void**) &tmp_zval);
			return *tmp_zval;

		case IS_BOOL:
		case IS_DOUBLE:
			convert_to_long(prop_name);
		case IS_LONG:
			zend_hash_index_find(HASH_OF(class), Z_LVAL_P(prop_name), (void **) &tmp_zval);
			return *tmp_zval;

		case IS_STRING:
			zend_symtable_find(HASH_OF(class), Z_STRVAL_P(prop_name), Z_STRLEN_P(prop_name) + 1, (void**) &tmp_zval);
			return *tmp_zval;
	}

	return NULL;
}

zval *TWIG_GET_ARRAY_ELEMENT(zval *class, char *prop_name, int prop_name_length TSRMLS_DC)
{
	zval **tmp_zval;

	if (class == NULL/* || Z_TYPE_P(class) != IS_ARRAY*/) {
		return NULL;
	}

	if (class != NULL && Z_TYPE_P(class) == IS_OBJECT && TWIG_INSTANCE_OF(class, zend_ce_arrayaccess TSRMLS_CC)) {
		// array access object
		zval *tmp_name_zval;
		zval *tmp_ret_zval;

		ALLOC_INIT_ZVAL(tmp_name_zval);
		ZVAL_STRING(tmp_name_zval, prop_name, 1);
		tmp_ret_zval = TWIG_GET_ARRAYOBJECT_ELEMENT(class, tmp_name_zval TSRMLS_CC);
		FREE_DTOR(tmp_name_zval);
		return tmp_ret_zval;
	}

	if (zend_symtable_find(HASH_OF(class), prop_name, prop_name_length+1, (void**)&tmp_zval) == SUCCESS) {
		return *tmp_zval;
	}
	return NULL;
}

zval *TWIG_PROPERTY(zval *object, zval *propname TSRMLS_DC)
{
	zval *tmp = NULL;

	if (Z_OBJ_HT_P(object)->read_property) {
#if PHP_VERSION_ID >= 50400
		tmp = Z_OBJ_HT_P(object)->read_property(object, propname, BP_VAR_IS, NULL TSRMLS_CC);
#else
		tmp = Z_OBJ_HT_P(object)->read_property(object, propname, BP_VAR_IS TSRMLS_CC);
#endif
		if (tmp != EG(uninitialized_zval_ptr)) {
			return tmp;
		} else {
			return NULL;
		}
	}
	return tmp;
}

int TWIG_HAS_PROPERTY(zval *object, zval *propname TSRMLS_DC)
{
	if (Z_OBJ_HT_P(object)->has_property) {
#if PHP_VERSION_ID >= 50400
		return Z_OBJ_HT_P(object)->has_property(object, propname, 0, NULL TSRMLS_CC);
#else
		return Z_OBJ_HT_P(object)->has_property(object, propname, 0 TSRMLS_CC);
#endif
	}
	return 0;
}

int TWIG_HAS_DYNAMIC_PROPERTY(zval *object, char *prop, int prop_len TSRMLS_DC)
{
	if (Z_OBJ_HT_P(object)->get_properties) {
		return zend_hash_quick_exists(
				Z_OBJ_HT_P(object)->get_properties(object TSRMLS_CC), // the properties hash
				prop,                                                 // property name
				prop_len + 1,                                         // property length
				zend_get_hash_value(prop, prop_len + 1)               // hash value
			);
	}
	return 0;
}

zval *TWIG_PROPERTY_CHAR(zval *object, char *propname TSRMLS_DC)
{
	zval *tmp_name_zval, *tmp;

	ALLOC_INIT_ZVAL(tmp_name_zval);
	ZVAL_STRING(tmp_name_zval, propname, 1);
	tmp = TWIG_PROPERTY(object, tmp_name_zval TSRMLS_CC);
	FREE_DTOR(tmp_name_zval);
	return tmp;
}

int TWIG_CALL_B_0(zval *object, char *method)
{
	return 0;
}

zval *TWIG_CALL_S(zval *object, char *method, char *arg0 TSRMLS_DC)
{
	zend_fcall_info fci;
	zval **args[1];
	zval *argument;
	zval *zfunction;
	zval *retval_ptr;

	MAKE_STD_ZVAL(argument);
	ZVAL_STRING(argument, arg0, 1);
	args[0] = &argument;

	MAKE_STD_ZVAL(zfunction);
	ZVAL_STRING(zfunction, method, 1);
	fci.size = sizeof(fci);
	fci.function_table = EG(function_table);
	fci.function_name = zfunction;
	fci.symbol_table = NULL;
#if PHP_VERSION_ID >= 50300
	fci.object_ptr = object;
#else
	fci.object_pp = &object;
#endif
	fci.retval_ptr_ptr = &retval_ptr;
	fci.param_count = 1;
	fci.params = args;
	fci.no_separation = 0;

	if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE) {
		FREE_DTOR(zfunction);
		zval_ptr_dtor(&argument);
		return 0;
	}
	FREE_DTOR(zfunction);
	zval_ptr_dtor(&argument);
	return retval_ptr;
}

int TWIG_CALL_SB(zval *object, char *method, char *arg0 TSRMLS_DC)
{
	zval *retval_ptr;
	int success;

	retval_ptr = TWIG_CALL_S(object, method, arg0 TSRMLS_CC);
	success = (retval_ptr && (Z_TYPE_P(retval_ptr) == IS_BOOL) && Z_LVAL_P(retval_ptr));

	if (retval_ptr) {
		zval_ptr_dtor(&retval_ptr);
	}

	return success;
}

int TWIG_CALL_Z(zval *object, char *method, zval *arg1 TSRMLS_DC)
{
	zend_fcall_info fci;
	zval **args[1];
	zval *zfunction;
	zval *retval_ptr;
	int   success;

	args[0] = &arg1;

	MAKE_STD_ZVAL(zfunction);
	ZVAL_STRING(zfunction, method, 1);
	fci.size = sizeof(fci);
	fci.function_table = EG(function_table);
	fci.function_name = zfunction;
	fci.symbol_table = NULL;
#if PHP_VERSION_ID >= 50300
	fci.object_ptr = object;
#else
	fci.object_pp = &object;
#endif
	fci.retval_ptr_ptr = &retval_ptr;
	fci.param_count = 1;
	fci.params = args;
	fci.no_separation = 0;

	if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE) {
		FREE_DTOR(zfunction);
		if (retval_ptr) {
			zval_ptr_dtor(&retval_ptr);
		}
		return 0;
	}

	FREE_DTOR(zfunction);

	success = (retval_ptr && (Z_TYPE_P(retval_ptr) == IS_BOOL) && Z_LVAL_P(retval_ptr));
	if (retval_ptr) {
		zval_ptr_dtor(&retval_ptr);
	}

	return success;
}

int TWIG_CALL_ZZ(zval *object, char *method, zval *arg1, zval *arg2 TSRMLS_DC)
{
	zend_fcall_info fci;
	zval **args[2];
	zval *zfunction;
	zval *retval_ptr;
	int   success;

	args[0] = &arg1;
	args[1] = &arg2;

	MAKE_STD_ZVAL(zfunction);
	ZVAL_STRING(zfunction, method, 1);
	fci.size = sizeof(fci);
	fci.function_table = EG(function_table);
	fci.function_name = zfunction;
	fci.symbol_table = NULL;
#if PHP_VERSION_ID >= 50300
	fci.object_ptr = object;
#else
	fci.object_pp = &object;
#endif
	fci.retval_ptr_ptr = &retval_ptr;
	fci.param_count = 2;
	fci.params = args;
	fci.no_separation = 0;

	if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE) {
		FREE_DTOR(zfunction);
		return 0;
	}

	FREE_DTOR(zfunction);

	success = (retval_ptr && (Z_TYPE_P(retval_ptr) == IS_BOOL) && Z_LVAL_P(retval_ptr));
	if (retval_ptr) {
		zval_ptr_dtor(&retval_ptr);
	}

	return success;
}

#ifndef Z_SET_REFCOUNT_P
# define Z_SET_REFCOUNT_P(pz, rc)  pz->refcount = rc
# define Z_UNSET_ISREF_P(pz) pz->is_ref = 0
#endif

void TWIG_NEW(zval *object, char *class, zval *arg0, zval *arg1 TSRMLS_DC)
{
	zend_class_entry **pce;

	if (zend_lookup_class(class, strlen(class), &pce TSRMLS_CC) == FAILURE) {
		return;
	}

	Z_TYPE_P(object) = IS_OBJECT;
	object_init_ex(object, *pce);
	Z_SET_REFCOUNT_P(object, 1);
	Z_UNSET_ISREF_P(object);

	TWIG_CALL_ZZ(object, "__construct", arg0, arg1 TSRMLS_CC);
}

static int twig_add_array_key_to_string(void *pDest APPLY_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
{
	smart_str *buf;
	char *joiner;
	APPLY_TSRMLS_FETCH();

	buf = va_arg(args, smart_str*);
	joiner = va_arg(args, char*);

	if (buf->len != 0) {
		smart_str_appends(buf, joiner);
	}

	if (hash_key->nKeyLength == 0) {
		smart_str_append_long(buf, (long) hash_key->h);
	} else {
		char *key, *tmp_str;
		int key_len, tmp_len;
		key = php_addcslashes(hash_key->arKey, hash_key->nKeyLength - 1, &key_len, 0, "'\\", 2 TSRMLS_CC);
		tmp_str = php_str_to_str_ex(key, key_len, "\0", 1, "' . \"\\0\" . '", 12, &tmp_len, 0, NULL);

		smart_str_appendl(buf, tmp_str, tmp_len);
		efree(key);
		efree(tmp_str);
	}

	return 0;
}

char *TWIG_IMPLODE_ARRAY_KEYS(char *joiner, zval *array TSRMLS_DC)
{
	smart_str collector = { 0, 0, 0 };

	smart_str_appendl(&collector, "", 0);
	zend_hash_apply_with_arguments(HASH_OF(array) APPLY_TSRMLS_CC, twig_add_array_key_to_string, 2, &collector, joiner);
	smart_str_0(&collector);

	return collector.c;
}

static void TWIG_THROW_EXCEPTION(char *exception_name TSRMLS_DC, char *message, ...)
{
	char *buffer;
	va_list args;
	zend_class_entry **pce;

	if (zend_lookup_class(exception_name, strlen(exception_name), &pce TSRMLS_CC) == FAILURE) {
		return;
	}

	va_start(args, message);
	vspprintf(&buffer, 0, message, args);
	va_end(args);

	zend_throw_exception_ex(*pce, 0 TSRMLS_CC, buffer);
	efree(buffer);
}

static void TWIG_RUNTIME_ERROR(zval *template TSRMLS_DC, char *message, ...)
{
	char *buffer;
	va_list args;
	zend_class_entry **pce;
	zval *ex;
	zval *constructor;
	zval *zmessage;
	zval *lineno;
	zval *filename_func;
	zval *filename;
	zval *constructor_args[3];
	zval *constructor_retval;

	if (zend_lookup_class("Twig_Error_Runtime", strlen("Twig_Error_Runtime"), &pce TSRMLS_CC) == FAILURE) {
		return;
	}

	va_start(args, message);
	vspprintf(&buffer, 0, message, args);
	va_end(args);

	MAKE_STD_ZVAL(ex);
	object_init_ex(ex, *pce);

	// Call Twig_Error constructor
	MAKE_STD_ZVAL(constructor);
	MAKE_STD_ZVAL(zmessage);
	MAKE_STD_ZVAL(lineno);
	MAKE_STD_ZVAL(filename);
	MAKE_STD_ZVAL(filename_func);
	MAKE_STD_ZVAL(constructor_retval);

	ZVAL_STRINGL(constructor, "__construct", sizeof("__construct")-1, 1);
	ZVAL_STRING(zmessage, buffer, 1);
	ZVAL_LONG(lineno, -1);

	// Get template filename
	ZVAL_STRINGL(filename_func, "getTemplateName", sizeof("getTemplateName")-1, 1);
	call_user_function(EG(function_table), &template, filename_func, filename, 0, 0 TSRMLS_CC);

	constructor_args[0] = zmessage;
	constructor_args[1] = lineno;
	constructor_args[2] = filename;
	call_user_function(EG(function_table), &ex, constructor, constructor_retval, 3, constructor_args TSRMLS_CC);

	zval_ptr_dtor(&constructor_retval);
	zval_ptr_dtor(&zmessage);
	zval_ptr_dtor(&lineno);
	zval_ptr_dtor(&filename);
	FREE_DTOR(constructor);
	FREE_DTOR(filename_func);
	efree(buffer);

	zend_throw_exception_object(ex TSRMLS_CC);
}

static char *TWIG_GET_CLASS_NAME(zval *object TSRMLS_DC)
{
	char *class_name;
	zend_uint class_name_len;

	if (Z_TYPE_P(object) != IS_OBJECT) {
		return "";
	}
#if PHP_API_VERSION >= 20100412
	zend_get_object_classname(object, (const char **) &class_name, &class_name_len TSRMLS_CC);
#else
	zend_get_object_classname(object, &class_name, &class_name_len TSRMLS_CC);
#endif
	return class_name;
}

static int twig_add_method_to_class(void *pDest APPLY_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
{
	zval *retval;
	char *item;
	size_t item_len;
	zend_function *mptr = (zend_function *) pDest;
	APPLY_TSRMLS_FETCH();

	if (!(mptr->common.fn_flags & ZEND_ACC_PUBLIC)) {
		return 0;
	}

	retval = va_arg(args, zval*);

	item_len = strlen(mptr->common.function_name);
	item = estrndup(mptr->common.function_name, item_len);
	php_strtolower(item, item_len);

	add_assoc_stringl_ex(retval, item, item_len+1, item, item_len, 0);

	return 0;
}

static int twig_add_property_to_class(void *pDest APPLY_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
{
	zend_class_entry *ce;
	zval *retval;
	char *class_name, *prop_name;
	zend_property_info *pptr = (zend_property_info *) pDest;
	APPLY_TSRMLS_FETCH();

	if (!(pptr->flags & ZEND_ACC_PUBLIC) || (pptr->flags & ZEND_ACC_STATIC)) {
		return 0;
	}

	ce = *va_arg(args, zend_class_entry**);
	retval = va_arg(args, zval*);

#if PHP_API_VERSION >= 20100412
	zend_unmangle_property_name(pptr->name, pptr->name_length, (const char **) &class_name, (const char **) &prop_name);
#else
	zend_unmangle_property_name(pptr->name, pptr->name_length, &class_name, &prop_name);
#endif

	add_assoc_string(retval, prop_name, prop_name, 1);

	return 0;
}

static void twig_add_class_to_cache(zval *cache, zval *object, char *class_name TSRMLS_DC)
{
	zval *class_info, *class_methods, *class_properties;
	zend_class_entry *class_ce;

	class_ce = zend_get_class_entry(object TSRMLS_CC);

	ALLOC_INIT_ZVAL(class_info);
	ALLOC_INIT_ZVAL(class_methods);
	ALLOC_INIT_ZVAL(class_properties);
	array_init(class_info);
	array_init(class_methods);
	array_init(class_properties);
	// add all methods to self::cache[$class]['methods']
	zend_hash_apply_with_arguments(&class_ce->function_table APPLY_TSRMLS_CC, twig_add_method_to_class, 1, class_methods);
	zend_hash_apply_with_arguments(&class_ce->properties_info APPLY_TSRMLS_CC, twig_add_property_to_class, 2, &class_ce, class_properties);

	add_assoc_zval(class_info, "methods", class_methods);
	add_assoc_zval(class_info, "properties", class_properties);
	add_assoc_zval(cache, class_name, class_info);
}

/* {{{ proto mixed twig_template_get_attributes(TwigTemplate template, mixed object, mixed item, array arguments, string type, boolean isDefinedTest, boolean ignoreStrictCheck)
   A C implementation of TwigTemplate::getAttribute() */
PHP_FUNCTION(twig_template_get_attributes)
{
	zval *template;
	zval *object;
	char *item;
	int  item_len;
	zval *zitem, ztmpitem;
	zval *arguments = NULL;
	zval *ret = NULL;
	char *type = NULL;
	int   type_len = 0;
	zend_bool isDefinedTest = 0;
	zend_bool ignoreStrictCheck = 0;
	int free_ret = 0;
	zval *tmp_self_cache;
	char *class_name = NULL;
	zval *tmp_class;
	char *type_name;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ozz|asbb", &template, &object, &zitem, &arguments, &type, &type_len, &isDefinedTest, &ignoreStrictCheck) == FAILURE) {
		return;
	}

	// convert the item to a string
	ztmpitem = *zitem;
	zval_copy_ctor(&ztmpitem);
	convert_to_string(&ztmpitem);
	item_len = Z_STRLEN(ztmpitem);
	item = estrndup(Z_STRVAL(ztmpitem), item_len);
	zval_dtor(&ztmpitem);

	if (!type) {
		type = "any";
	}

/*
	// array
	if (Twig_Template::METHOD_CALL !== $type) {
		$arrayItem = is_bool($item) || is_float($item) ? (int) $item : $item;

		if ((is_array($object) && array_key_exists($arrayItem, $object))
			|| ($object instanceof ArrayAccess && isset($object[$arrayItem]))
		) {
			if ($isDefinedTest) {
				return true;
			}

			return $object[$arrayItem];
		}
*/


	if (strcmp("method", type) != 0) {
		if ((TWIG_ARRAY_KEY_EXISTS(object, zitem))
			|| (TWIG_INSTANCE_OF(object, zend_ce_arrayaccess TSRMLS_CC) && TWIG_ISSET_ARRAYOBJECT_ELEMENT(object, zitem TSRMLS_CC))
		) {

			if (isDefinedTest) {
				RETURN_TRUE;
			}

			ret = TWIG_GET_ARRAY_ELEMENT_ZVAL(object, zitem TSRMLS_CC);

			if (!ret) {
				ret = &EG(uninitialized_zval);
			}
			RETVAL_ZVAL(ret, 1, 0);
			if (free_ret) {
				zval_ptr_dtor(&ret);
			}
			return;
		}
/*
		if (Twig_Template::ARRAY_CALL === $type) {
			if ($isDefinedTest) {
				return false;
			}
			if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
				return null;
			}
*/
		if (strcmp("array", type) == 0 || Z_TYPE_P(object) != IS_OBJECT) {
			if (isDefinedTest) {
				RETURN_FALSE;
			}
			if (ignoreStrictCheck || !TWIG_CALL_BOOLEAN(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "isStrictVariables" TSRMLS_CC)) {
				return;
			}
/*
			if (is_object($object)) {
				throw new Twig_Error_Runtime(sprintf('Key "%s" in object (with ArrayAccess) of type "%s" does not exist', $arrayItem, get_class($object)), -1, $this->getTemplateName());
			} elseif (is_array($object)) {
				throw new Twig_Error_Runtime(sprintf('Key "%s" for array with keys "%s" does not exist', $arrayItem, implode(', ', array_keys($object))), -1, $this->getTemplateName());
			} elseif (Twig_Template::ARRAY_CALL === $type) {
				throw new Twig_Error_Runtime(sprintf('Impossible to access a key ("%s") on a %s variable ("%s")', $item, gettype($object), $object), -1, $this->getTemplateName());
			} else {
				throw new Twig_Error_Runtime(sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s")', $item, gettype($object), $object), -1, $this->getTemplateName());
			}
		}
	}
*/
			if (Z_TYPE_P(object) == IS_OBJECT) {
				TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Key \"%s\" in object (with ArrayAccess) of type \"%s\" does not exist", item, TWIG_GET_CLASS_NAME(object TSRMLS_CC));
			} else if (Z_TYPE_P(object) == IS_ARRAY) {
				TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Key \"%s\" for array with keys \"%s\" does not exist", item, TWIG_IMPLODE_ARRAY_KEYS(", ", object TSRMLS_CC));
			} else {
				char *type_name = zend_zval_type_name(object);
				Z_ADDREF_P(object);
				convert_to_string(object);
				TWIG_RUNTIME_ERROR(template TSRMLS_CC,
					(strcmp("array", type) == 0)
						? "Impossible to access a key (\"%s\") on a %s variable (\"%s\")"
						: "Impossible to access an attribute (\"%s\") on a %s variable (\"%s\")",
					item, type_name, Z_STRVAL_P(object));
				zval_ptr_dtor(&object);
			}
			return;
		}
	}

/*
	if (!is_object($object)) {
		if ($isDefinedTest) {
			return false;
		}
*/

	if (Z_TYPE_P(object) != IS_OBJECT) {
		if (isDefinedTest) {
			RETURN_FALSE;
		}
/*
		if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
			return null;
		}
		throw new Twig_Error_Runtime(sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s")', $item, gettype($object), $object), -1, $this->getTemplateName());
	}
*/
		if (ignoreStrictCheck || !TWIG_CALL_BOOLEAN(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "isStrictVariables" TSRMLS_CC)) {
			return;
		}

		type_name = zend_zval_type_name(object);
		Z_ADDREF_P(object);
		convert_to_string_ex(&object);

		TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Impossible to invoke a method (\"%s\") on a %s variable (\"%s\")", item, type_name, Z_STRVAL_P(object));

		zval_ptr_dtor(&object);

		return;
	}
/*
	$class = get_class($object);
*/

	class_name = TWIG_GET_CLASS_NAME(object TSRMLS_CC);
	tmp_self_cache = TWIG_GET_STATIC_PROPERTY(template, "cache" TSRMLS_CC);
	tmp_class = TWIG_GET_ARRAY_ELEMENT(tmp_self_cache, class_name, strlen(class_name) TSRMLS_CC);

	if (!tmp_class) {
		twig_add_class_to_cache(tmp_self_cache, object, class_name TSRMLS_CC);
		tmp_class = TWIG_GET_ARRAY_ELEMENT(tmp_self_cache, class_name, strlen(class_name) TSRMLS_CC);
	}
	efree(class_name);

/*
	// object property
	if (Twig_Template::METHOD_CALL !== $type) {
		if (isset($object->$item) || array_key_exists((string) $item, $object)) {
			if ($isDefinedTest) {
				return true;
			}

			if ($this->env->hasExtension('sandbox')) {
				$this->env->getExtension('sandbox')->checkPropertyAllowed($object, $item);
			}

			return $object->$item;
		}
	}
*/
	if (strcmp("method", type) != 0) {
		zval *tmp_properties, *tmp_item;

		tmp_properties = TWIG_GET_ARRAY_ELEMENT(tmp_class, "properties", strlen("properties") TSRMLS_CC);
		tmp_item = TWIG_GET_ARRAY_ELEMENT(tmp_properties, item, item_len TSRMLS_CC);

		if (tmp_item || TWIG_HAS_PROPERTY(object, zitem TSRMLS_CC) || TWIG_HAS_DYNAMIC_PROPERTY(object, item, item_len TSRMLS_CC)) {
			if (isDefinedTest) {
				RETURN_TRUE;
			}
			if (TWIG_CALL_SB(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "hasExtension", "sandbox" TSRMLS_CC)) {
				TWIG_CALL_ZZ(TWIG_CALL_S(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "getExtension", "sandbox" TSRMLS_CC), "checkPropertyAllowed", object, zitem TSRMLS_CC);
			}
			if (EG(exception)) {
				return;
			}

			ret = TWIG_PROPERTY(object, zitem TSRMLS_CC);
			RETURN_ZVAL(ret, 1, 0);
		}
	}
/*
	// object method
	if (!isset(self::$cache[$class]['methods'])) {
		self::$cache[$class]['methods'] = array_change_key_case(array_flip(get_class_methods($object)));
	}

	$lcItem = strtolower($item);
	if (isset(self::$cache[$class]['methods'][$lcItem])) {
		$method = (string) $item;
	} elseif (isset(self::$cache[$class]['methods']['get'.$lcItem])) {
		$method = 'get'.$item;
	} elseif (isset(self::$cache[$class]['methods']['is'.$lcItem])) {
		$method = 'is'.$item;
	} elseif (isset(self::$cache[$class]['methods']['__call'])) {
		$method = (string) $item;
*/
	{
		char *lcItem = TWIG_STRTOLOWER(item, item_len);
		int   lcItem_length;
		char *method = NULL;
		char *tmp_method_name_get;
		char *tmp_method_name_is;
		zval *tmp_methods;

		lcItem_length = strlen(lcItem);
		tmp_method_name_get = emalloc(4 + lcItem_length);
		tmp_method_name_is  = emalloc(3 + lcItem_length);

		sprintf(tmp_method_name_get, "get%s", lcItem);
		sprintf(tmp_method_name_is, "is%s", lcItem);

		tmp_methods = TWIG_GET_ARRAY_ELEMENT(tmp_class, "methods", strlen("methods") TSRMLS_CC);

		if (TWIG_GET_ARRAY_ELEMENT(tmp_methods, lcItem, lcItem_length TSRMLS_CC)) {
			method = item;
		} else if (TWIG_GET_ARRAY_ELEMENT(tmp_methods, tmp_method_name_get, lcItem_length + 3 TSRMLS_CC)) {
			method = tmp_method_name_get;
		} else if (TWIG_GET_ARRAY_ELEMENT(tmp_methods, tmp_method_name_is, lcItem_length + 2 TSRMLS_CC)) {
			method = tmp_method_name_is;
		} else if (TWIG_GET_ARRAY_ELEMENT(tmp_methods, "__call", 6 TSRMLS_CC)) {
			method = item;
/*
	} else {
		if ($isDefinedTest) {
			return false;
		}

		if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
			return null;
		}

		throw new Twig_Error_Runtime(sprintf('Method "%s" for object "%s" does not exist', $item, get_class($object)), -1, $this->getTemplateName());
	}

	if ($isDefinedTest) {
		return true;
	}
*/
		} else {
			efree(tmp_method_name_get);
			efree(tmp_method_name_is);
			efree(lcItem);

			if (isDefinedTest) {
				RETURN_FALSE;
			}
			if (ignoreStrictCheck || !TWIG_CALL_BOOLEAN(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "isStrictVariables" TSRMLS_CC)) {
				return;
			}
			TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Method \"%s\" for object \"%s\" does not exist", item, TWIG_GET_CLASS_NAME(object TSRMLS_CC));
			return;
		}

		if (isDefinedTest) {
			efree(tmp_method_name_get);
			efree(tmp_method_name_is);
			efree(lcItem);
			RETURN_TRUE;
		}
/*
	if ($this->env->hasExtension('sandbox')) {
		$this->env->getExtension('sandbox')->checkMethodAllowed($object, $method);
	}
*/
		if (TWIG_CALL_SB(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "hasExtension", "sandbox" TSRMLS_CC)) {
			TWIG_CALL_ZZ(TWIG_CALL_S(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "getExtension", "sandbox" TSRMLS_CC), "checkMethodAllowed", object, zitem TSRMLS_CC);
		}
		if (EG(exception)) {
			efree(tmp_method_name_get);
			efree(tmp_method_name_is);
			efree(lcItem);
			return;
		}
/*
	$ret = call_user_func_array(array($object, $method), $arguments);
*/
		ret = TWIG_CALL_USER_FUNC_ARRAY(object, method, arguments TSRMLS_CC);
		free_ret = 1;
		efree(tmp_method_name_get);
		efree(tmp_method_name_is);
		efree(lcItem);
	}
/*
	// useful when calling a template method from a template
	// this is not supported but unfortunately heavily used in the Symfony profiler
	if ($object instanceof Twig_TemplateInterface) {
		return $ret === '' ? '' : new Twig_Markup($ret, $this->env->getCharset());
	}

	return $ret;
*/
	// ret can be null, if e.g. the called method throws an exception
	if (ret) {
		if (TWIG_INSTANCE_OF_USERLAND(object, "Twig_TemplateInterface" TSRMLS_CC)) {
			if (Z_STRLEN_P(ret) != 0) {
				zval *charset = TWIG_CALL_USER_FUNC_ARRAY(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "getCharset", NULL TSRMLS_CC);
				TWIG_NEW(return_value, "Twig_Markup", ret, charset TSRMLS_CC);
				zval_ptr_dtor(&charset);
				if (ret) {
					zval_ptr_dtor(&ret);
				}
				return;
			}
		}

		RETVAL_ZVAL(ret, 1, 0);
		if (free_ret) {
			zval_ptr_dtor(&ret);
		}
	}
}
/*
   +----------------------------------------------------------------------+
   | Twig Extension                                                       |
   +----------------------------------------------------------------------+
   | Copyright (c) 2011 Derick Rethans                                    |
   +----------------------------------------------------------------------+
   | Redistribution and use in source and binary forms, with or without   |
   | modification, are permitted provided that the conditions mentioned   |
   | in the accompanying LICENSE file are met (BSD-3-Clause).             |
   +----------------------------------------------------------------------+
   | Author: Derick Rethans <derick@derickrethans.nl>                     |
   +----------------------------------------------------------------------+
 */

#ifndef PHP_TWIG_H
#define PHP_TWIG_H

#define PHP_TWIG_VERSION "1.14.2"

#include "php.h"

extern zend_module_entry twig_module_entry;
#define phpext_twig_ptr &twig_module_entry

#ifdef ZTS
#include "TSRM.h"
#endif

PHP_FUNCTION(twig_template_get_attributes);

#endif
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Extension_Optimizer extends Twig_Extension
{
    protected $optimizers;

    public function __construct($optimizers = -1)
    {
        $this->optimizers = $optimizers;
    }

    /**
     * {@inheritdoc}
     */
    public function getNodeVisitors()
    {
        return array(new Twig_NodeVisitor_Optimizer($this->optimizers));
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'optimizer';
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2011 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Extension_Debug extends Twig_Extension
{
    /**
     * Returns a list of global functions to add to the existing list.
     *
     * @return array An array of global functions
     */
    public function getFunctions()
    {
        // dump is safe if var_dump is overridden by xdebug
        $isDumpOutputHtmlSafe = extension_loaded('xdebug')
            // false means that it was not set (and the default is on) or it explicitly enabled
            && (false === ini_get('xdebug.overload_var_dump') || ini_get('xdebug.overload_var_dump'))
            // false means that it was not set (and the default is on) or it explicitly enabled
            // xdebug.overload_var_dump produces HTML only when html_errors is also enabled
            && (false === ini_get('html_errors') || ini_get('html_errors'))
            || 'cli' === php_sapi_name()
        ;

        return array(
            new Twig_SimpleFunction('dump', 'twig_var_dump', array('is_safe' => $isDumpOutputHtmlSafe ? array('html') : array(), 'needs_context' => true, 'needs_environment' => true)),
        );
    }

    /**
     * Returns the name of the extension.
     *
     * @return string The extension name
     */
    public function getName()
    {
        return 'debug';
    }
}

function twig_var_dump(Twig_Environment $env, $context)
{
    if (!$env->isDebug()) {
        return;
    }

    ob_start();

    $count = func_num_args();
    if (2 === $count) {
        $vars = array();
        foreach ($context as $key => $value) {
            if (!$value instanceof Twig_Template) {
                $vars[$key] = $value;
            }
        }

        var_dump($vars);
    } else {
        for ($i = 2; $i < $count; $i++) {
            var_dump(func_get_arg($i));
        }
    }

    return ob_get_clean();
}
<?php

if (!defined('ENT_SUBSTITUTE')) {
    // use 0 as hhvm does not support several flags yet
    define('ENT_SUBSTITUTE', 0);
}

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Extension_Core extends Twig_Extension
{
    protected $dateFormats = array('F j, Y H:i', '%d days');
    protected $numberFormat = array(0, '.', ',');
    protected $timezone = null;
    protected $escapers = array();

    /**
     * Defines a new escaper to be used via the escape filter.
     *
     * @param string   $strategy The strategy name that should be used as a strategy in the escape call
     * @param callable $callable A valid PHP callable
     */
    public function setEscaper($strategy, $callable)
    {
        $this->escapers[$strategy] = $callable;
    }

    /**
     * Gets all defined escapers.
     *
     * @return array An array of escapers
     */
    public function getEscapers()
    {
        return $this->escapers;
    }

    /**
     * Sets the default format to be used by the date filter.
     *
     * @param string $format             The default date format string
     * @param string $dateIntervalFormat The default date interval format string
     */
    public function setDateFormat($format = null, $dateIntervalFormat = null)
    {
        if (null !== $format) {
            $this->dateFormats[0] = $format;
        }

        if (null !== $dateIntervalFormat) {
            $this->dateFormats[1] = $dateIntervalFormat;
        }
    }

    /**
     * Gets the default format to be used by the date filter.
     *
     * @return array The default date format string and the default date interval format string
     */
    public function getDateFormat()
    {
        return $this->dateFormats;
    }

    /**
     * Sets the default timezone to be used by the date filter.
     *
     * @param DateTimeZone|string $timezone The default timezone string or a DateTimeZone object
     */
    public function setTimezone($timezone)
    {
        $this->timezone = $timezone instanceof DateTimeZone ? $timezone : new DateTimeZone($timezone);
    }

    /**
     * Gets the default timezone to be used by the date filter.
     *
     * @return DateTimeZone The default timezone currently in use
     */
    public function getTimezone()
    {
        if (null === $this->timezone) {
            $this->timezone = new DateTimeZone(date_default_timezone_get());
        }

        return $this->timezone;
    }

    /**
     * Sets the default format to be used by the number_format filter.
     *
     * @param integer $decimal      The number of decimal places to use.
     * @param string  $decimalPoint The character(s) to use for the decimal point.
     * @param string  $thousandSep  The character(s) to use for the thousands separator.
     */
    public function setNumberFormat($decimal, $decimalPoint, $thousandSep)
    {
        $this->numberFormat = array($decimal, $decimalPoint, $thousandSep);
    }

    /**
     * Get the default format used by the number_format filter.
     *
     * @return array The arguments for number_format()
     */
    public function getNumberFormat()
    {
        return $this->numberFormat;
    }

    /**
     * Returns the token parser instance to add to the existing list.
     *
     * @return array An array of Twig_TokenParser instances
     */
    public function getTokenParsers()
    {
        return array(
            new Twig_TokenParser_For(),
            new Twig_TokenParser_If(),
            new Twig_TokenParser_Extends(),
            new Twig_TokenParser_Include(),
            new Twig_TokenParser_Block(),
            new Twig_TokenParser_Use(),
            new Twig_TokenParser_Filter(),
            new Twig_TokenParser_Macro(),
            new Twig_TokenParser_Import(),
            new Twig_TokenParser_From(),
            new Twig_TokenParser_Set(),
            new Twig_TokenParser_Spaceless(),
            new Twig_TokenParser_Flush(),
            new Twig_TokenParser_Do(),
            new Twig_TokenParser_Embed(),
        );
    }

    /**
     * Returns a list of filters to add to the existing list.
     *
     * @return array An array of filters
     */
    public function getFilters()
    {
        $filters = array(
            // formatting filters
            new Twig_SimpleFilter('date', 'twig_date_format_filter', array('needs_environment' => true)),
            new Twig_SimpleFilter('date_modify', 'twig_date_modify_filter', array('needs_environment' => true)),
            new Twig_SimpleFilter('format', 'sprintf'),
            new Twig_SimpleFilter('replace', 'strtr'),
            new Twig_SimpleFilter('number_format', 'twig_number_format_filter', array('needs_environment' => true)),
            new Twig_SimpleFilter('abs', 'abs'),

            // encoding
            new Twig_SimpleFilter('url_encode', 'twig_urlencode_filter'),
            new Twig_SimpleFilter('json_encode', 'twig_jsonencode_filter'),
            new Twig_SimpleFilter('convert_encoding', 'twig_convert_encoding'),

            // string filters
            new Twig_SimpleFilter('title', 'twig_title_string_filter', array('needs_environment' => true)),
            new Twig_SimpleFilter('capitalize', 'twig_capitalize_string_filter', array('needs_environment' => true)),
            new Twig_SimpleFilter('upper', 'strtoupper'),
            new Twig_SimpleFilter('lower', 'strtolower'),
            new Twig_SimpleFilter('striptags', 'strip_tags'),
            new Twig_SimpleFilter('trim', 'trim'),
            new Twig_SimpleFilter('nl2br', 'nl2br', array('pre_escape' => 'html', 'is_safe' => array('html'))),

            // array helpers
            new Twig_SimpleFilter('join', 'twig_join_filter'),
            new Twig_SimpleFilter('split', 'twig_split_filter'),
            new Twig_SimpleFilter('sort', 'twig_sort_filter'),
            new Twig_SimpleFilter('merge', 'twig_array_merge'),
            new Twig_SimpleFilter('batch', 'twig_array_batch'),

            // string/array filters
            new Twig_SimpleFilter('reverse', 'twig_reverse_filter', array('needs_environment' => true)),
            new Twig_SimpleFilter('length', 'twig_length_filter', array('needs_environment' => true)),
            new Twig_SimpleFilter('slice', 'twig_slice', array('needs_environment' => true)),
            new Twig_SimpleFilter('first', 'twig_first', array('needs_environment' => true)),
            new Twig_SimpleFilter('last', 'twig_last', array('needs_environment' => true)),

            // iteration and runtime
            new Twig_SimpleFilter('default', '_twig_default_filter', array('node_class' => 'Twig_Node_Expression_Filter_Default')),
            new Twig_SimpleFilter('keys', 'twig_get_array_keys_filter'),

            // escaping
            new Twig_SimpleFilter('escape', 'twig_escape_filter', array('needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe')),
            new Twig_SimpleFilter('e', 'twig_escape_filter', array('needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe')),
        );

        if (function_exists('mb_get_info')) {
            $filters[] = new Twig_SimpleFilter('upper', 'twig_upper_filter', array('needs_environment' => true));
            $filters[] = new Twig_SimpleFilter('lower', 'twig_lower_filter', array('needs_environment' => true));
        }

        return $filters;
    }

    /**
     * Returns a list of global functions to add to the existing list.
     *
     * @return array An array of global functions
     */
    public function getFunctions()
    {
        return array(
            new Twig_SimpleFunction('range', 'range'),
            new Twig_SimpleFunction('constant', 'twig_constant'),
            new Twig_SimpleFunction('cycle', 'twig_cycle'),
            new Twig_SimpleFunction('random', 'twig_random', array('needs_environment' => true)),
            new Twig_SimpleFunction('date', 'twig_date_converter', array('needs_environment' => true)),
            new Twig_SimpleFunction('include', 'twig_include', array('needs_environment' => true, 'needs_context' => true, 'is_safe' => array('all'))),
        );
    }

    /**
     * Returns a list of tests to add to the existing list.
     *
     * @return array An array of tests
     */
    public function getTests()
    {
        return array(
            new Twig_SimpleTest('even', null, array('node_class' => 'Twig_Node_Expression_Test_Even')),
            new Twig_SimpleTest('odd', null, array('node_class' => 'Twig_Node_Expression_Test_Odd')),
            new Twig_SimpleTest('defined', null, array('node_class' => 'Twig_Node_Expression_Test_Defined')),
            new Twig_SimpleTest('sameas', null, array('node_class' => 'Twig_Node_Expression_Test_Sameas')),
            new Twig_SimpleTest('same as', null, array('node_class' => 'Twig_Node_Expression_Test_Sameas')),
            new Twig_SimpleTest('none', null, array('node_class' => 'Twig_Node_Expression_Test_Null')),
            new Twig_SimpleTest('null', null, array('node_class' => 'Twig_Node_Expression_Test_Null')),
            new Twig_SimpleTest('divisibleby', null, array('node_class' => 'Twig_Node_Expression_Test_Divisibleby')),
            new Twig_SimpleTest('divisible by', null, array('node_class' => 'Twig_Node_Expression_Test_Divisibleby')),
            new Twig_SimpleTest('constant', null, array('node_class' => 'Twig_Node_Expression_Test_Constant')),
            new Twig_SimpleTest('empty', 'twig_test_empty'),
            new Twig_SimpleTest('iterable', 'twig_test_iterable'),
        );
    }

    /**
     * Returns a list of operators to add to the existing list.
     *
     * @return array An array of operators
     */
    public function getOperators()
    {
        return array(
            array(
                'not' => array('precedence' => 50, 'class' => 'Twig_Node_Expression_Unary_Not'),
                '-'   => array('precedence' => 500, 'class' => 'Twig_Node_Expression_Unary_Neg'),
                '+'   => array('precedence' => 500, 'class' => 'Twig_Node_Expression_Unary_Pos'),
            ),
            array(
                'or'          => array('precedence' => 10, 'class' => 'Twig_Node_Expression_Binary_Or', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                'and'         => array('precedence' => 15, 'class' => 'Twig_Node_Expression_Binary_And', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                'b-or'        => array('precedence' => 16, 'class' => 'Twig_Node_Expression_Binary_BitwiseOr', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                'b-xor'       => array('precedence' => 17, 'class' => 'Twig_Node_Expression_Binary_BitwiseXor', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                'b-and'       => array('precedence' => 18, 'class' => 'Twig_Node_Expression_Binary_BitwiseAnd', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                '=='          => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Equal', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                '!='          => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                '<'           => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Less', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                '>'           => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Greater', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                '>='          => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_GreaterEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                '<='          => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_LessEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                'not in'      => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotIn', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                'in'          => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_In', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                'matches'     => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Matches', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                'starts with' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_StartsWith', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                'ends with'   => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_EndsWith', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                '..'          => array('precedence' => 25, 'class' => 'Twig_Node_Expression_Binary_Range', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                '+'           => array('precedence' => 30, 'class' => 'Twig_Node_Expression_Binary_Add', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                '-'           => array('precedence' => 30, 'class' => 'Twig_Node_Expression_Binary_Sub', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                '~'           => array('precedence' => 40, 'class' => 'Twig_Node_Expression_Binary_Concat', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                '*'           => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mul', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                '/'           => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Div', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                '//'          => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_FloorDiv', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                '%'           => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mod', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                'is'          => array('precedence' => 100, 'callable' => array($this, 'parseTestExpression'), 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                'is not'      => array('precedence' => 100, 'callable' => array($this, 'parseNotTestExpression'), 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
                '**'          => array('precedence' => 200, 'class' => 'Twig_Node_Expression_Binary_Power', 'associativity' => Twig_ExpressionParser::OPERATOR_RIGHT),
            ),
        );
    }

    public function parseNotTestExpression(Twig_Parser $parser, Twig_NodeInterface $node)
    {
        return new Twig_Node_Expression_Unary_Not($this->parseTestExpression($parser, $node), $parser->getCurrentToken()->getLine());
    }

    public function parseTestExpression(Twig_Parser $parser, Twig_NodeInterface $node)
    {
        $stream = $parser->getStream();
        $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
        $class = $this->getTestNodeClass($parser, $name, $node->getLine());
        $arguments = null;
        if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
            $arguments = $parser->getExpressionParser()->parseArguments(true);
        }

        return new $class($node, $name, $arguments, $parser->getCurrentToken()->getLine());
    }

    protected function getTestNodeClass(Twig_Parser $parser, $name, $line)
    {
        $env = $parser->getEnvironment();
        $testMap = $env->getTests();
        $testName = null;
        if (isset($testMap[$name])) {
            $testName = $name;
        } elseif ($parser->getStream()->test(Twig_Token::NAME_TYPE)) {
            // try 2-words tests
            $name = $name.' '.$parser->getCurrentToken()->getValue();

            if (isset($testMap[$name])) {
                $parser->getStream()->next();

                $testName = $name;
            }
        }

        if (null === $testName) {
            $message = sprintf('The test "%s" does not exist', $name);
            if ($alternatives = $env->computeAlternatives($name, array_keys($env->getTests()))) {
                $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
            }

            throw new Twig_Error_Syntax($message, $line, $parser->getFilename());
        }

        if ($testMap[$name] instanceof Twig_SimpleTest) {
            return $testMap[$name]->getNodeClass();
        }

        return $testMap[$name] instanceof Twig_Test_Node ? $testMap[$name]->getClass() : 'Twig_Node_Expression_Test';
    }

    /**
     * Returns the name of the extension.
     *
     * @return string The extension name
     */
    public function getName()
    {
        return 'core';
    }
}

/**
 * Cycles over a value.
 *
 * @param ArrayAccess|array $values   An array or an ArrayAccess instance
 * @param integer           $position The cycle position
 *
 * @return string The next value in the cycle
 */
function twig_cycle($values, $position)
{
    if (!is_array($values) && !$values instanceof ArrayAccess) {
        return $values;
    }

    return $values[$position % count($values)];
}

/**
 * Returns a random value depending on the supplied parameter type:
 * - a random item from a Traversable or array
 * - a random character from a string
 * - a random integer between 0 and the integer parameter
 *
 * @param Twig_Environment                 $env    A Twig_Environment instance
 * @param Traversable|array|integer|string $values The values to pick a random item from
 *
 * @throws Twig_Error_Runtime When $values is an empty array (does not apply to an empty string which is returned as is).
 *
 * @return mixed A random value from the given sequence
 */
function twig_random(Twig_Environment $env, $values = null)
{
    if (null === $values) {
        return mt_rand();
    }

    if (is_int($values) || is_float($values)) {
        return $values < 0 ? mt_rand($values, 0) : mt_rand(0, $values);
    }

    if (is_object($values) && $values instanceof Traversable) {
        $values = iterator_to_array($values);
    } elseif (is_string($values)) {
        if ('' === $values) {
            return '';
        }
        if (null !== $charset = $env->getCharset()) {
            if ('UTF-8' != $charset) {
                $values = twig_convert_encoding($values, 'UTF-8', $charset);
            }

            // unicode version of str_split()
            // split at all positions, but not after the start and not before the end
            $values = preg_split('/(?<!^)(?!$)/u', $values);

            if ('UTF-8' != $charset) {
                foreach ($values as $i => $value) {
                    $values[$i] = twig_convert_encoding($value, $charset, 'UTF-8');
                }
            }
        } else {
            return $values[mt_rand(0, strlen($values) - 1)];
        }
    }

    if (!is_array($values)) {
        return $values;
    }

    if (0 === count($values)) {
        throw new Twig_Error_Runtime('The random function cannot pick from an empty array.');
    }

    return $values[array_rand($values, 1)];
}

/**
 * Converts a date to the given format.
 *
 * <pre>
 *   {{ post.published_at|date("m/d/Y") }}
 * </pre>
 *
 * @param Twig_Environment             $env      A Twig_Environment instance
 * @param DateTime|DateInterval|string $date     A date
 * @param string                       $format   A format
 * @param DateTimeZone|string          $timezone A timezone
 *
 * @return string The formatted date
 */
function twig_date_format_filter(Twig_Environment $env, $date, $format = null, $timezone = null)
{
    if (null === $format) {
        $formats = $env->getExtension('core')->getDateFormat();
        $format = $date instanceof DateInterval ? $formats[1] : $formats[0];
    }

    if ($date instanceof DateInterval) {
        return $date->format($format);
    }

    return twig_date_converter($env, $date, $timezone)->format($format);
}

/**
 * Returns a new date object modified
 *
 * <pre>
 *   {{ post.published_at|date_modify("-1day")|date("m/d/Y") }}
 * </pre>
 *
 * @param Twig_Environment  $env      A Twig_Environment instance
 * @param DateTime|string   $date     A date
 * @param string            $modifier A modifier string
 *
 * @return DateTime A new date object
 */
function twig_date_modify_filter(Twig_Environment $env, $date, $modifier)
{
    $date = twig_date_converter($env, $date, false);
    $date->modify($modifier);

    return $date;
}

/**
 * Converts an input to a DateTime instance.
 *
 * <pre>
 *    {% if date(user.created_at) < date('+2days') %}
 *      {# do something #}
 *    {% endif %}
 * </pre>
 *
 * @param Twig_Environment    $env      A Twig_Environment instance
 * @param DateTime|string     $date     A date
 * @param DateTimeZone|string $timezone A timezone
 *
 * @return DateTime A DateTime instance
 */
function twig_date_converter(Twig_Environment $env, $date = null, $timezone = null)
{
    // determine the timezone
    if (!$timezone) {
        $defaultTimezone = $env->getExtension('core')->getTimezone();
    } elseif (!$timezone instanceof DateTimeZone) {
        $defaultTimezone = new DateTimeZone($timezone);
    } else {
        $defaultTimezone = $timezone;
    }

    if ($date instanceof DateTime || $date instanceof DateTimeInterface) {
        $returningDate = new DateTime($date->format('c'));
        if (false !== $timezone) {
            $returningDate->setTimezone($defaultTimezone);
        } else {
            $returningDate->setTimezone($date->getTimezone());
        }

        return $returningDate;
    }

    $asString = (string) $date;
    if (ctype_digit($asString) || (!empty($asString) && '-' === $asString[0] && ctype_digit(substr($asString, 1)))) {
        $date = '@'.$date;
    }

    $date = new DateTime($date, $defaultTimezone);
    if (false !== $timezone) {
        $date->setTimezone($defaultTimezone);
    }

    return $date;
}

/**
 * Number format filter.
 *
 * All of the formatting options can be left null, in that case the defaults will
 * be used.  Supplying any of the parameters will override the defaults set in the
 * environment object.
 *
 * @param Twig_Environment    $env          A Twig_Environment instance
 * @param mixed               $number       A float/int/string of the number to format
 * @param integer             $decimal      The number of decimal points to display.
 * @param string              $decimalPoint The character(s) to use for the decimal point.
 * @param string              $thousandSep  The character(s) to use for the thousands separator.
 *
 * @return string The formatted number
 */
function twig_number_format_filter(Twig_Environment $env, $number, $decimal = null, $decimalPoint = null, $thousandSep = null)
{
    $defaults = $env->getExtension('core')->getNumberFormat();
    if (null === $decimal) {
        $decimal = $defaults[0];
    }

    if (null === $decimalPoint) {
        $decimalPoint = $defaults[1];
    }

    if (null === $thousandSep) {
        $thousandSep = $defaults[2];
    }

    return number_format((float) $number, $decimal, $decimalPoint, $thousandSep);
}

/**
 * URL encodes a string as a path segment or an array as a query string.
 *
 * @param string|array $url A URL or an array of query parameters
 * @param bool         $raw true to use rawurlencode() instead of urlencode
 *
 * @return string The URL encoded value
 */
function twig_urlencode_filter($url, $raw = false)
{
    if (is_array($url)) {
        return http_build_query($url, '', '&');
    }

    if ($raw) {
        return rawurlencode($url);
    }

    return urlencode($url);
}

if (version_compare(PHP_VERSION, '5.3.0', '<')) {
    /**
     * JSON encodes a variable.
     *
     * @param mixed   $value   The value to encode.
     * @param integer $options Not used on PHP 5.2.x
     *
     * @return mixed The JSON encoded value
     */
    function twig_jsonencode_filter($value, $options = 0)
    {
        if ($value instanceof Twig_Markup) {
            $value = (string) $value;
        } elseif (is_array($value)) {
            array_walk_recursive($value, '_twig_markup2string');
        }

        return json_encode($value);
    }
} else {
    /**
     * JSON encodes a variable.
     *
     * @param mixed   $value   The value to encode.
     * @param integer $options Bitmask consisting of JSON_HEX_QUOT, JSON_HEX_TAG, JSON_HEX_AMP, JSON_HEX_APOS, JSON_NUMERIC_CHECK, JSON_PRETTY_PRINT, JSON_UNESCAPED_SLASHES, JSON_FORCE_OBJECT
     *
     * @return mixed The JSON encoded value
     */
    function twig_jsonencode_filter($value, $options = 0)
    {
        if ($value instanceof Twig_Markup) {
            $value = (string) $value;
        } elseif (is_array($value)) {
            array_walk_recursive($value, '_twig_markup2string');
        }

        return json_encode($value, $options);
    }
}

function _twig_markup2string(&$value)
{
    if ($value instanceof Twig_Markup) {
        $value = (string) $value;
    }
}

/**
 * Merges an array with another one.
 *
 * <pre>
 *  {% set items = { 'apple': 'fruit', 'orange': 'fruit' } %}
 *
 *  {% set items = items|merge({ 'peugeot': 'car' }) %}
 *
 *  {# items now contains { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'car' } #}
 * </pre>
 *
 * @param array $arr1 An array
 * @param array $arr2 An array
 *
 * @return array The merged array
 */
function twig_array_merge($arr1, $arr2)
{
    if (!is_array($arr1) || !is_array($arr2)) {
        throw new Twig_Error_Runtime('The merge filter only works with arrays or hashes.');
    }

    return array_merge($arr1, $arr2);
}

/**
 * Slices a variable.
 *
 * @param Twig_Environment $env          A Twig_Environment instance
 * @param mixed            $item         A variable
 * @param integer          $start        Start of the slice
 * @param integer          $length       Size of the slice
 * @param Boolean          $preserveKeys Whether to preserve key or not (when the input is an array)
 *
 * @return mixed The sliced variable
 */
function twig_slice(Twig_Environment $env, $item, $start, $length = null, $preserveKeys = false)
{
    if (is_object($item) && $item instanceof Traversable) {
        $item = iterator_to_array($item, false);
    }

    if (is_array($item)) {
        return array_slice($item, $start, $length, $preserveKeys);
    }

    $item = (string) $item;

    if (function_exists('mb_get_info') && null !== $charset = $env->getCharset()) {
        return mb_substr($item, $start, null === $length ? mb_strlen($item, $charset) - $start : $length, $charset);
    }

    return null === $length ? substr($item, $start) : substr($item, $start, $length);
}

/**
 * Returns the first element of the item.
 *
 * @param Twig_Environment $env  A Twig_Environment instance
 * @param mixed            $item A variable
 *
 * @return mixed The first element of the item
 */
function twig_first(Twig_Environment $env, $item)
{
    $elements = twig_slice($env, $item, 0, 1, false);

    return is_string($elements) ? $elements[0] : current($elements);
}

/**
 * Returns the last element of the item.
 *
 * @param Twig_Environment $env  A Twig_Environment instance
 * @param mixed            $item A variable
 *
 * @return mixed The last element of the item
 */
function twig_last(Twig_Environment $env, $item)
{
    $elements = twig_slice($env, $item, -1, 1, false);

    return is_string($elements) ? $elements[0] : current($elements);
}

/**
 * Joins the values to a string.
 *
 * The separator between elements is an empty string per default, you can define it with the optional parameter.
 *
 * <pre>
 *  {{ [1, 2, 3]|join('|') }}
 *  {# returns 1|2|3 #}
 *
 *  {{ [1, 2, 3]|join }}
 *  {# returns 123 #}
 * </pre>
 *
 * @param array  $value An array
 * @param string $glue  The separator
 *
 * @return string The concatenated string
 */
function twig_join_filter($value, $glue = '')
{
    if (is_object($value) && $value instanceof Traversable) {
        $value = iterator_to_array($value, false);
    }

    return implode($glue, (array) $value);
}

/**
 * Splits the string into an array.
 *
 * <pre>
 *  {{ "one,two,three"|split(',') }}
 *  {# returns [one, two, three] #}
 *
 *  {{ "one,two,three,four,five"|split(',', 3) }}
 *  {# returns [one, two, "three,four,five"] #}
 *
 *  {{ "123"|split('') }}
 *  {# returns [1, 2, 3] #}
 *
 *  {{ "aabbcc"|split('', 2) }}
 *  {# returns [aa, bb, cc] #}
 * </pre>
 *
 * @param string  $value     A string
 * @param string  $delimiter The delimiter
 * @param integer $limit     The limit
 *
 * @return array The split string as an array
 */
function twig_split_filter($value, $delimiter, $limit = null)
{
    if (empty($delimiter)) {
        return str_split($value, null === $limit ? 1 : $limit);
    }

    return null === $limit ? explode($delimiter, $value) : explode($delimiter, $value, $limit);
}

// The '_default' filter is used internally to avoid using the ternary operator
// which costs a lot for big contexts (before PHP 5.4). So, on average,
// a function call is cheaper.
function _twig_default_filter($value, $default = '')
{
    if (twig_test_empty($value)) {
        return $default;
    }

    return $value;
}

/**
 * Returns the keys for the given array.
 *
 * It is useful when you want to iterate over the keys of an array:
 *
 * <pre>
 *  {% for key in array|keys %}
 *      {# ... #}
 *  {% endfor %}
 * </pre>
 *
 * @param array $array An array
 *
 * @return array The keys
 */
function twig_get_array_keys_filter($array)
{
    if (is_object($array) && $array instanceof Traversable) {
        return array_keys(iterator_to_array($array));
    }

    if (!is_array($array)) {
        return array();
    }

    return array_keys($array);
}

/**
 * Reverses a variable.
 *
 * @param Twig_Environment         $env          A Twig_Environment instance
 * @param array|Traversable|string $item         An array, a Traversable instance, or a string
 * @param Boolean                  $preserveKeys Whether to preserve key or not
 *
 * @return mixed The reversed input
 */
function twig_reverse_filter(Twig_Environment $env, $item, $preserveKeys = false)
{
    if (is_object($item) && $item instanceof Traversable) {
        return array_reverse(iterator_to_array($item), $preserveKeys);
    }

    if (is_array($item)) {
        return array_reverse($item, $preserveKeys);
    }

    if (null !== $charset = $env->getCharset()) {
        $string = (string) $item;

        if ('UTF-8' != $charset) {
            $item = twig_convert_encoding($string, 'UTF-8', $charset);
        }

        preg_match_all('/./us', $item, $matches);

        $string = implode('', array_reverse($matches[0]));

        if ('UTF-8' != $charset) {
            $string = twig_convert_encoding($string, $charset, 'UTF-8');
        }

        return $string;
    }

    return strrev((string) $item);
}

/**
 * Sorts an array.
 *
 * @param array $array An array
 */
function twig_sort_filter($array)
{
    asort($array);

    return $array;
}

/* used internally */
function twig_in_filter($value, $compare)
{
    if (is_array($compare)) {
        return in_array($value, $compare, is_object($value));
    } elseif (is_string($compare)) {
        if (!strlen($value)) {
            return empty($compare);
        }

        return false !== strpos($compare, (string) $value);
    } elseif (is_object($compare) && $compare instanceof Traversable) {
        return in_array($value, iterator_to_array($compare, false), is_object($value));
    }

    return false;
}

/**
 * Escapes a string.
 *
 * @param Twig_Environment $env        A Twig_Environment instance
 * @param string           $string     The value to be escaped
 * @param string           $strategy   The escaping strategy
 * @param string           $charset    The charset
 * @param Boolean          $autoescape Whether the function is called by the auto-escaping feature (true) or by the developer (false)
 */
function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html', $charset = null, $autoescape = false)
{
    if ($autoescape && $string instanceof Twig_Markup) {
        return $string;
    }

    if (!is_string($string)) {
        if (is_object($string) && method_exists($string, '__toString')) {
            $string = (string) $string;
        } else {
            return $string;
        }
    }

    if (null === $charset) {
        $charset = $env->getCharset();
    }

    switch ($strategy) {
        case 'html':
            // see http://php.net/htmlspecialchars

            // Using a static variable to avoid initializing the array
            // each time the function is called. Moving the declaration on the
            // top of the function slow downs other escaping strategies.
            static $htmlspecialcharsCharsets;

            if (null === $htmlspecialcharsCharsets) {
                if ('hiphop' === substr(PHP_VERSION, -6)) {
                    $htmlspecialcharsCharsets = array('utf-8' => true, 'UTF-8' => true);
                } else {
                    $htmlspecialcharsCharsets = array(
                        'ISO-8859-1' => true, 'ISO8859-1' => true,
                        'ISO-8859-15' => true, 'ISO8859-15' => true,
                        'utf-8' => true, 'UTF-8' => true,
                        'CP866' => true, 'IBM866' => true, '866' => true,
                        'CP1251' => true, 'WINDOWS-1251' => true, 'WIN-1251' => true,
                        '1251' => true,
                        'CP1252' => true, 'WINDOWS-1252' => true, '1252' => true,
                        'KOI8-R' => true, 'KOI8-RU' => true, 'KOI8R' => true,
                        'BIG5' => true, '950' => true,
                        'GB2312' => true, '936' => true,
                        'BIG5-HKSCS' => true,
                        'SHIFT_JIS' => true, 'SJIS' => true, '932' => true,
                        'EUC-JP' => true, 'EUCJP' => true,
                        'ISO8859-5' => true, 'ISO-8859-5' => true, 'MACROMAN' => true,
                    );
                }
            }

            if (isset($htmlspecialcharsCharsets[$charset])) {
                return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset);
            }

            if (isset($htmlspecialcharsCharsets[strtoupper($charset)])) {
                // cache the lowercase variant for future iterations
                $htmlspecialcharsCharsets[$charset] = true;

                return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset);
            }

            $string = twig_convert_encoding($string, 'UTF-8', $charset);
            $string = htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');

            return twig_convert_encoding($string, $charset, 'UTF-8');

        case 'js':
            // escape all non-alphanumeric characters
            // into their \xHH or \uHHHH representations
            if ('UTF-8' != $charset) {
                $string = twig_convert_encoding($string, 'UTF-8', $charset);
            }

            if (0 == strlen($string) ? false : (1 == preg_match('/^./su', $string) ? false : true)) {
                throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
            }

            $string = preg_replace_callback('#[^a-zA-Z0-9,\._]#Su', '_twig_escape_js_callback', $string);

            if ('UTF-8' != $charset) {
                $string = twig_convert_encoding($string, $charset, 'UTF-8');
            }

            return $string;

        case 'css':
            if ('UTF-8' != $charset) {
                $string = twig_convert_encoding($string, 'UTF-8', $charset);
            }

            if (0 == strlen($string) ? false : (1 == preg_match('/^./su', $string) ? false : true)) {
                throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
            }

            $string = preg_replace_callback('#[^a-zA-Z0-9]#Su', '_twig_escape_css_callback', $string);

            if ('UTF-8' != $charset) {
                $string = twig_convert_encoding($string, $charset, 'UTF-8');
            }

            return $string;

        case 'html_attr':
            if ('UTF-8' != $charset) {
                $string = twig_convert_encoding($string, 'UTF-8', $charset);
            }

            if (0 == strlen($string) ? false : (1 == preg_match('/^./su', $string) ? false : true)) {
                throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
            }

            $string = preg_replace_callback('#[^a-zA-Z0-9,\.\-_]#Su', '_twig_escape_html_attr_callback', $string);

            if ('UTF-8' != $charset) {
                $string = twig_convert_encoding($string, $charset, 'UTF-8');
            }

            return $string;

        case 'url':
            // hackish test to avoid version_compare that is much slower, this works unless PHP releases a 5.10.*
            // at that point however PHP 5.2.* support can be removed
            if (PHP_VERSION < '5.3.0') {
                return str_replace('%7E', '~', rawurlencode($string));
            }

            return rawurlencode($string);

        default:
            static $escapers;

            if (null === $escapers) {
                $escapers = $env->getExtension('core')->getEscapers();
            }

            if (isset($escapers[$strategy])) {
                return call_user_func($escapers[$strategy], $env, $string, $charset);
            }

            $validStrategies = implode(', ', array_merge(array('html', 'js', 'url', 'css', 'html_attr'), array_keys($escapers)));

            throw new Twig_Error_Runtime(sprintf('Invalid escaping strategy "%s" (valid ones: %s).', $strategy, $validStrategies));
    }
}

/* used internally */
function twig_escape_filter_is_safe(Twig_Node $filterArgs)
{
    foreach ($filterArgs as $arg) {
        if ($arg instanceof Twig_Node_Expression_Constant) {
            return array($arg->getAttribute('value'));
        }

        return array();
    }

    return array('html');
}

if (function_exists('mb_convert_encoding')) {
    function twig_convert_encoding($string, $to, $from)
    {
        return mb_convert_encoding($string, $to, $from);
    }
} elseif (function_exists('iconv')) {
    function twig_convert_encoding($string, $to, $from)
    {
        return iconv($from, $to, $string);
    }
} else {
    function twig_convert_encoding($string, $to, $from)
    {
        throw new Twig_Error_Runtime('No suitable convert encoding function (use UTF-8 as your encoding or install the iconv or mbstring extension).');
    }
}

function _twig_escape_js_callback($matches)
{
    $char = $matches[0];

    // \xHH
    if (!isset($char[1])) {
        return '\\x'.strtoupper(substr('00'.bin2hex($char), -2));
    }

    // \uHHHH
    $char = twig_convert_encoding($char, 'UTF-16BE', 'UTF-8');

    return '\\u'.strtoupper(substr('0000'.bin2hex($char), -4));
}

function _twig_escape_css_callback($matches)
{
    $char = $matches[0];

    // \xHH
    if (!isset($char[1])) {
        $hex = ltrim(strtoupper(bin2hex($char)), '0');
        if (0 === strlen($hex)) {
            $hex = '0';
        }

        return '\\'.$hex.' ';
    }

    // \uHHHH
    $char = twig_convert_encoding($char, 'UTF-16BE', 'UTF-8');

    return '\\'.ltrim(strtoupper(bin2hex($char)), '0').' ';
}

/**
 * This function is adapted from code coming from Zend Framework.
 *
 * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */
function _twig_escape_html_attr_callback($matches)
{
    /*
     * While HTML supports far more named entities, the lowest common denominator
     * has become HTML5's XML Serialisation which is restricted to the those named
     * entities that XML supports. Using HTML entities would result in this error:
     *     XML Parsing Error: undefined entity
     */
    static $entityMap = array(
        34 => 'quot', /* quotation mark */
        38 => 'amp',  /* ampersand */
        60 => 'lt',   /* less-than sign */
        62 => 'gt',   /* greater-than sign */
    );

    $chr = $matches[0];
    $ord = ord($chr);

    /**
     * The following replaces characters undefined in HTML with the
     * hex entity for the Unicode replacement character.
     */
    if (($ord <= 0x1f && $chr != "\t" && $chr != "\n" && $chr != "\r") || ($ord >= 0x7f && $ord <= 0x9f)) {
        return '&#xFFFD;';
    }

    /**
     * Check if the current character to escape has a name entity we should
     * replace it with while grabbing the hex value of the character.
     */
    if (strlen($chr) == 1) {
        $hex = strtoupper(substr('00'.bin2hex($chr), -2));
    } else {
        $chr = twig_convert_encoding($chr, 'UTF-16BE', 'UTF-8');
        $hex = strtoupper(substr('0000'.bin2hex($chr), -4));
    }

    $int = hexdec($hex);
    if (array_key_exists($int, $entityMap)) {
        return sprintf('&%s;', $entityMap[$int]);
    }

    /**
     * Per OWASP recommendations, we'll use hex entities for any other
     * characters where a named entity does not exist.
     */

    return sprintf('&#x%s;', $hex);
}

// add multibyte extensions if possible
if (function_exists('mb_get_info')) {
    /**
     * Returns the length of a variable.
     *
     * @param Twig_Environment $env   A Twig_Environment instance
     * @param mixed            $thing A variable
     *
     * @return integer The length of the value
     */
    function twig_length_filter(Twig_Environment $env, $thing)
    {
        return is_scalar($thing) ? mb_strlen($thing, $env->getCharset()) : count($thing);
    }

    /**
     * Converts a string to uppercase.
     *
     * @param Twig_Environment $env    A Twig_Environment instance
     * @param string           $string A string
     *
     * @return string The uppercased string
     */
    function twig_upper_filter(Twig_Environment $env, $string)
    {
        if (null !== ($charset = $env->getCharset())) {
            return mb_strtoupper($string, $charset);
        }

        return strtoupper($string);
    }

    /**
     * Converts a string to lowercase.
     *
     * @param Twig_Environment $env    A Twig_Environment instance
     * @param string           $string A string
     *
     * @return string The lowercased string
     */
    function twig_lower_filter(Twig_Environment $env, $string)
    {
        if (null !== ($charset = $env->getCharset())) {
            return mb_strtolower($string, $charset);
        }

        return strtolower($string);
    }

    /**
     * Returns a titlecased string.
     *
     * @param Twig_Environment $env    A Twig_Environment instance
     * @param string           $string A string
     *
     * @return string The titlecased string
     */
    function twig_title_string_filter(Twig_Environment $env, $string)
    {
        if (null !== ($charset = $env->getCharset())) {
            return mb_convert_case($string, MB_CASE_TITLE, $charset);
        }

        return ucwords(strtolower($string));
    }

    /**
     * Returns a capitalized string.
     *
     * @param Twig_Environment $env    A Twig_Environment instance
     * @param string           $string A string
     *
     * @return string The capitalized string
     */
    function twig_capitalize_string_filter(Twig_Environment $env, $string)
    {
        if (null !== ($charset = $env->getCharset())) {
            return mb_strtoupper(mb_substr($string, 0, 1, $charset), $charset).
                         mb_strtolower(mb_substr($string, 1, mb_strlen($string, $charset), $charset), $charset);
        }

        return ucfirst(strtolower($string));
    }
}
// and byte fallback
else {
    /**
     * Returns the length of a variable.
     *
     * @param Twig_Environment $env   A Twig_Environment instance
     * @param mixed            $thing A variable
     *
     * @return integer The length of the value
     */
    function twig_length_filter(Twig_Environment $env, $thing)
    {
        return is_scalar($thing) ? strlen($thing) : count($thing);
    }

    /**
     * Returns a titlecased string.
     *
     * @param Twig_Environment $env    A Twig_Environment instance
     * @param string           $string A string
     *
     * @return string The titlecased string
     */
    function twig_title_string_filter(Twig_Environment $env, $string)
    {
        return ucwords(strtolower($string));
    }

    /**
     * Returns a capitalized string.
     *
     * @param Twig_Environment $env    A Twig_Environment instance
     * @param string           $string A string
     *
     * @return string The capitalized string
     */
    function twig_capitalize_string_filter(Twig_Environment $env, $string)
    {
        return ucfirst(strtolower($string));
    }
}

/* used internally */
function twig_ensure_traversable($seq)
{
    if ($seq instanceof Traversable || is_array($seq)) {
        return $seq;
    }

    return array();
}

/**
 * Checks if a variable is empty.
 *
 * <pre>
 * {# evaluates to true if the foo variable is null, false, or the empty string #}
 * {% if foo is empty %}
 *     {# ... #}
 * {% endif %}
 * </pre>
 *
 * @param mixed $value A variable
 *
 * @return Boolean true if the value is empty, false otherwise
 */
function twig_test_empty($value)
{
    if ($value instanceof Countable) {
        return 0 == count($value);
    }

    return '' === $value || false === $value || null === $value || array() === $value;
}

/**
 * Checks if a variable is traversable.
 *
 * <pre>
 * {# evaluates to true if the foo variable is an array or a traversable object #}
 * {% if foo is traversable %}
 *     {# ... #}
 * {% endif %}
 * </pre>
 *
 * @param mixed $value A variable
 *
 * @return Boolean true if the value is traversable
 */
function twig_test_iterable($value)
{
    return $value instanceof Traversable || is_array($value);
}

/**
 * Renders a template.
 *
 * @param string|array $template       The template to render or an array of templates to try consecutively
 * @param array        $variables      The variables to pass to the template
 * @param Boolean      $with_context   Whether to pass the current context variables or not
 * @param Boolean      $ignore_missing Whether to ignore missing templates or not
 * @param Boolean      $sandboxed      Whether to sandbox the template or not
 *
 * @return string The rendered template
 */
function twig_include(Twig_Environment $env, $context, $template, $variables = array(), $withContext = true, $ignoreMissing = false, $sandboxed = false)
{
    if ($withContext) {
        $variables = array_merge($context, $variables);
    }

    if ($isSandboxed = $sandboxed && $env->hasExtension('sandbox')) {
        $sandbox = $env->getExtension('sandbox');
        if (!$alreadySandboxed = $sandbox->isSandboxed()) {
            $sandbox->enableSandbox();
        }
    }

    try {
        return $env->resolveTemplate($template)->render($variables);
    } catch (Twig_Error_Loader $e) {
        if (!$ignoreMissing) {
            throw $e;
        }
    }

    if ($isSandboxed && !$alreadySandboxed) {
        $sandbox->disableSandbox();
    }
}

/**
 * Provides the ability to get constants from instances as well as class/global constants.
 *
 * @param string      $constant The name of the constant
 * @param null|object $object   The object to get the constant from
 *
 * @return string
 */
function twig_constant($constant, $object = null)
{
    if (null !== $object) {
        $constant = get_class($object).'::'.$constant;
    }

    return constant($constant);
}

/**
 * Batches item.
 *
 * @param array   $items An array of items
 * @param integer $size  The size of the batch
 * @param mixed   $fill  A value used to fill missing items
 *
 * @return array
 */
function twig_array_batch($items, $size, $fill = null)
{
    if (is_object($items) && $items instanceof Traversable) {
        $items = iterator_to_array($items, false);
    }

    $size = ceil($size);

    $result = array_chunk($items, $size, true);

    if (null !== $fill) {
        $last = count($result) - 1;
        if ($fillCount = $size - count($result[$last])) {
            $result[$last] = array_merge(
                $result[$last],
                array_fill(0, $fillCount, $fill)
            );
        }
    }

    return $result;
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2012 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Internal class.
 *
 * This class is used by Twig_Environment as a staging area and must not be used directly.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Extension_Staging extends Twig_Extension
{
    protected $functions = array();
    protected $filters = array();
    protected $visitors = array();
    protected $tokenParsers = array();
    protected $globals = array();
    protected $tests = array();

    public function addFunction($name, $function)
    {
        $this->functions[$name] = $function;
    }

    /**
     * {@inheritdoc}
     */
    public function getFunctions()
    {
        return $this->functions;
    }

    public function addFilter($name, $filter)
    {
        $this->filters[$name] = $filter;
    }

    /**
     * {@inheritdoc}
     */
    public function getFilters()
    {
        return $this->filters;
    }

    public function addNodeVisitor(Twig_NodeVisitorInterface $visitor)
    {
        $this->visitors[] = $visitor;
    }

    /**
     * {@inheritdoc}
     */
    public function getNodeVisitors()
    {
        return $this->visitors;
    }

    public function addTokenParser(Twig_TokenParserInterface $parser)
    {
        $this->tokenParsers[] = $parser;
    }

    /**
     * {@inheritdoc}
     */
    public function getTokenParsers()
    {
        return $this->tokenParsers;
    }

    public function addGlobal($name, $value)
    {
        $this->globals[$name] = $value;
    }

    /**
     * {@inheritdoc}
     */
    public function getGlobals()
    {
        return $this->globals;
    }

    public function addTest($name, $test)
    {
        $this->tests[$name] = $test;
    }

    /**
     * {@inheritdoc}
     */
    public function getTests()
    {
        return $this->tests;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'staging';
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Extension_Escaper extends Twig_Extension
{
    protected $defaultStrategy;

    public function __construct($defaultStrategy = 'html')
    {
        $this->setDefaultStrategy($defaultStrategy);
    }

    /**
     * Returns the token parser instances to add to the existing list.
     *
     * @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
     */
    public function getTokenParsers()
    {
        return array(new Twig_TokenParser_AutoEscape());
    }

    /**
     * Returns the node visitor instances to add to the existing list.
     *
     * @return array An array of Twig_NodeVisitorInterface instances
     */
    public function getNodeVisitors()
    {
        return array(new Twig_NodeVisitor_Escaper());
    }

    /**
     * Returns a list of filters to add to the existing list.
     *
     * @return array An array of filters
     */
    public function getFilters()
    {
        return array(
            new Twig_SimpleFilter('raw', 'twig_raw_filter', array('is_safe' => array('all'))),
        );
    }

    /**
     * Sets the default strategy to use when not defined by the user.
     *
     * The strategy can be a valid PHP callback that takes the template
     * "filename" as an argument and returns the strategy to use.
     *
     * @param mixed $defaultStrategy An escaping strategy
     */
    public function setDefaultStrategy($defaultStrategy)
    {
        // for BC
        if (true === $defaultStrategy) {
            $defaultStrategy = 'html';
        }

        $this->defaultStrategy = $defaultStrategy;
    }

    /**
     * Gets the default strategy to use when not defined by the user.
     *
     * @param string $filename The template "filename"
     *
     * @return string The default strategy to use for the template
     */
    public function getDefaultStrategy($filename)
    {
        // disable string callables to avoid calling a function named html or js,
        // or any other upcoming escaping strategy
        if (!is_string($this->defaultStrategy) && is_callable($this->defaultStrategy)) {
            return call_user_func($this->defaultStrategy, $filename);
        }

        return $this->defaultStrategy;
    }

    /**
     * Returns the name of the extension.
     *
     * @return string The extension name
     */
    public function getName()
    {
        return 'escaper';
    }
}

/**
 * Marks a variable as being safe.
 *
 * @param string $string A PHP variable
 */
function twig_raw_filter($string)
{
    return $string;
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Extension_Sandbox extends Twig_Extension
{
    protected $sandboxedGlobally;
    protected $sandboxed;
    protected $policy;

    public function __construct(Twig_Sandbox_SecurityPolicyInterface $policy, $sandboxed = false)
    {
        $this->policy            = $policy;
        $this->sandboxedGlobally = $sandboxed;
    }

    /**
     * Returns the token parser instances to add to the existing list.
     *
     * @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
     */
    public function getTokenParsers()
    {
        return array(new Twig_TokenParser_Sandbox());
    }

    /**
     * Returns the node visitor instances to add to the existing list.
     *
     * @return array An array of Twig_NodeVisitorInterface instances
     */
    public function getNodeVisitors()
    {
        return array(new Twig_NodeVisitor_Sandbox());
    }

    public function enableSandbox()
    {
        $this->sandboxed = true;
    }

    public function disableSandbox()
    {
        $this->sandboxed = false;
    }

    public function isSandboxed()
    {
        return $this->sandboxedGlobally || $this->sandboxed;
    }

    public function isSandboxedGlobally()
    {
        return $this->sandboxedGlobally;
    }

    public function setSecurityPolicy(Twig_Sandbox_SecurityPolicyInterface $policy)
    {
        $this->policy = $policy;
    }

    public function getSecurityPolicy()
    {
        return $this->policy;
    }

    public function checkSecurity($tags, $filters, $functions)
    {
        if ($this->isSandboxed()) {
            $this->policy->checkSecurity($tags, $filters, $functions);
        }
    }

    public function checkMethodAllowed($obj, $method)
    {
        if ($this->isSandboxed()) {
            $this->policy->checkMethodAllowed($obj, $method);
        }
    }

    public function checkPropertyAllowed($obj, $method)
    {
        if ($this->isSandboxed()) {
            $this->policy->checkPropertyAllowed($obj, $method);
        }
    }

    public function ensureToStringAllowed($obj)
    {
        if (is_object($obj)) {
            $this->policy->checkMethodAllowed($obj, '__toString');
        }

        return $obj;
    }

    /**
     * Returns the name of the extension.
     *
     * @return string The extension name
     */
    public function getName()
    {
        return 'sandbox';
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2012 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Extension_StringLoader extends Twig_Extension
{
    /**
     * {@inheritdoc}
     */
    public function getFunctions()
    {
        return array(
            new Twig_SimpleFunction('template_from_string', 'twig_template_from_string', array('needs_environment' => true)),
        );
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'string_loader';
    }
}

/**
 * Loads a template from a string.
 *
 * <pre>
 * {{ include(template_from_string("Hello {{ name }}")) }}
 * </pre>
 *
 * @param Twig_Environment $env      A Twig_Environment instance
 * @param string           $template A template as a string
 *
 * @return Twig_Template A Twig_Template instance
 */
function twig_template_from_string(Twig_Environment $env, $template)
{
    $name = sprintf('__string_template__%s', hash('sha256', uniqid(mt_rand(), true), false));

    $loader = new Twig_Loader_Chain(array(
        new Twig_Loader_Array(array($name => $template)),
        $current = $env->getLoader(),
    ));

    $env->setLoader($loader);
    try {
        $template = $env->loadTemplate($name);
    } catch (Exception $e) {
        $env->setLoader($current);

        throw $e;
    }
    $env->setLoader($current);

    return $template;
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Interface all loaders must implement.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface Twig_LoaderInterface
{
    /**
     * Gets the source code of a template, given its name.
     *
     * @param string $name The name of the template to load
     *
     * @return string The template source code
     *
     * @throws Twig_Error_Loader When $name is not found
     */
    public function getSource($name);

    /**
     * Gets the cache key to use for the cache for a given template name.
     *
     * @param string $name The name of the template to load
     *
     * @return string The cache key
     *
     * @throws Twig_Error_Loader When $name is not found
     */
    public function getCacheKey($name);

    /**
     * Returns true if the template is still fresh.
     *
     * @param string    $name The template name
     * @param timestamp $time The last modification time of the cached template
     *
     * @return Boolean true if the template is fresh, false otherwise
     *
     * @throws Twig_Error_Loader When $name is not found
     */
    public function isFresh($name, $time);
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Stores the Twig configuration.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Environment
{
    const VERSION = '1.14.2';

    protected $charset;
    protected $loader;
    protected $debug;
    protected $autoReload;
    protected $cache;
    protected $lexer;
    protected $parser;
    protected $compiler;
    protected $baseTemplateClass;
    protected $extensions;
    protected $parsers;
    protected $visitors;
    protected $filters;
    protected $tests;
    protected $functions;
    protected $globals;
    protected $runtimeInitialized;
    protected $extensionInitialized;
    protected $loadedTemplates;
    protected $strictVariables;
    protected $unaryOperators;
    protected $binaryOperators;
    protected $templateClassPrefix = '__TwigTemplate_';
    protected $functionCallbacks;
    protected $filterCallbacks;
    protected $staging;
    protected $templateClasses;

    /**
     * Constructor.
     *
     * Available options:
     *
     *  * debug: When set to true, it automatically set "auto_reload" to true as
     *           well (default to false).
     *
     *  * charset: The charset used by the templates (default to UTF-8).
     *
     *  * base_template_class: The base template class to use for generated
     *                         templates (default to Twig_Template).
     *
     *  * cache: An absolute path where to store the compiled templates, or
     *           false to disable compilation cache (default).
     *
     *  * auto_reload: Whether to reload the template if the original source changed.
     *                 If you don't provide the auto_reload option, it will be
     *                 determined automatically based on the debug value.
     *
     *  * strict_variables: Whether to ignore invalid variables in templates
     *                      (default to false).
     *
     *  * autoescape: Whether to enable auto-escaping (default to html):
     *                  * false: disable auto-escaping
     *                  * true: equivalent to html
     *                  * html, js: set the autoescaping to one of the supported strategies
     *                  * PHP callback: a PHP callback that returns an escaping strategy based on the template "filename"
     *
     *  * optimizations: A flag that indicates which optimizations to apply
     *                   (default to -1 which means that all optimizations are enabled;
     *                   set it to 0 to disable).
     *
     * @param Twig_LoaderInterface $loader  A Twig_LoaderInterface instance
     * @param array                $options An array of options
     */
    public function __construct(Twig_LoaderInterface $loader = null, $options = array())
    {
        if (null !== $loader) {
            $this->setLoader($loader);
        }

        $options = array_merge(array(
            'debug'               => false,
            'charset'             => 'UTF-8',
            'base_template_class' => 'Twig_Template',
            'strict_variables'    => false,
            'autoescape'          => 'html',
            'cache'               => false,
            'auto_reload'         => null,
            'optimizations'       => -1,
        ), $options);

        $this->debug              = (bool) $options['debug'];
        $this->charset            = strtoupper($options['charset']);
        $this->baseTemplateClass  = $options['base_template_class'];
        $this->autoReload         = null === $options['auto_reload'] ? $this->debug : (bool) $options['auto_reload'];
        $this->strictVariables    = (bool) $options['strict_variables'];
        $this->runtimeInitialized = false;
        $this->setCache($options['cache']);
        $this->functionCallbacks = array();
        $this->filterCallbacks = array();
        $this->templateClasses = array();

        $this->addExtension(new Twig_Extension_Core());
        $this->addExtension(new Twig_Extension_Escaper($options['autoescape']));
        $this->addExtension(new Twig_Extension_Optimizer($options['optimizations']));
        $this->extensionInitialized = false;
        $this->staging = new Twig_Extension_Staging();
    }

    /**
     * Gets the base template class for compiled templates.
     *
     * @return string The base template class name
     */
    public function getBaseTemplateClass()
    {
        return $this->baseTemplateClass;
    }

    /**
     * Sets the base template class for compiled templates.
     *
     * @param string $class The base template class name
     */
    public function setBaseTemplateClass($class)
    {
        $this->baseTemplateClass = $class;
    }

    /**
     * Enables debugging mode.
     */
    public function enableDebug()
    {
        $this->debug = true;
    }

    /**
     * Disables debugging mode.
     */
    public function disableDebug()
    {
        $this->debug = false;
    }

    /**
     * Checks if debug mode is enabled.
     *
     * @return Boolean true if debug mode is enabled, false otherwise
     */
    public function isDebug()
    {
        return $this->debug;
    }

    /**
     * Enables the auto_reload option.
     */
    public function enableAutoReload()
    {
        $this->autoReload = true;
    }

    /**
     * Disables the auto_reload option.
     */
    public function disableAutoReload()
    {
        $this->autoReload = false;
    }

    /**
     * Checks if the auto_reload option is enabled.
     *
     * @return Boolean true if auto_reload is enabled, false otherwise
     */
    public function isAutoReload()
    {
        return $this->autoReload;
    }

    /**
     * Enables the strict_variables option.
     */
    public function enableStrictVariables()
    {
        $this->strictVariables = true;
    }

    /**
     * Disables the strict_variables option.
     */
    public function disableStrictVariables()
    {
        $this->strictVariables = false;
    }

    /**
     * Checks if the strict_variables option is enabled.
     *
     * @return Boolean true if strict_variables is enabled, false otherwise
     */
    public function isStrictVariables()
    {
        return $this->strictVariables;
    }

    /**
     * Gets the cache directory or false if cache is disabled.
     *
     * @return string|false
     */
    public function getCache()
    {
        return $this->cache;
    }

     /**
      * Sets the cache directory or false if cache is disabled.
      *
      * @param string|false $cache The absolute path to the compiled templates,
      *                            or false to disable cache
      */
    public function setCache($cache)
    {
        $this->cache = $cache ? $cache : false;
    }

    /**
     * Gets the cache filename for a given template.
     *
     * @param string $name The template name
     *
     * @return string|false The cache file name or false when caching is disabled
     */
    public function getCacheFilename($name)
    {
        if (false === $this->cache) {
            return false;
        }

        $class = substr($this->getTemplateClass($name), strlen($this->templateClassPrefix));

        return $this->getCache().'/'.substr($class, 0, 2).'/'.substr($class, 2, 2).'/'.substr($class, 4).'.php';
    }

    /**
     * Gets the template class associated with the given string.
     *
     * @param string  $name  The name for which to calculate the template class name
     * @param integer $index The index if it is an embedded template
     *
     * @return string The template class name
     */
    public function getTemplateClass($name, $index = null)
    {
        $suffix = null === $index ? '' : '_'.$index;
        $cls = $name.$suffix;
        if (isset($this->templateClasses[$cls])) {
            return $this->templateClasses[$cls];
        }

        return $this->templateClasses[$cls] = $this->templateClassPrefix.hash('sha256', $this->getLoader()->getCacheKey($name)).$suffix;
    }

    /**
     * Gets the template class prefix.
     *
     * @return string The template class prefix
     */
    public function getTemplateClassPrefix()
    {
        return $this->templateClassPrefix;
    }

    /**
     * Renders a template.
     *
     * @param string $name    The template name
     * @param array  $context An array of parameters to pass to the template
     *
     * @return string The rendered template
     *
     * @throws Twig_Error_Loader  When the template cannot be found
     * @throws Twig_Error_Syntax  When an error occurred during compilation
     * @throws Twig_Error_Runtime When an error occurred during rendering
     */
    public function render($name, array $context = array())
    {
        return $this->loadTemplate($name)->render($context);
    }

    /**
     * Displays a template.
     *
     * @param string $name    The template name
     * @param array  $context An array of parameters to pass to the template
     *
     * @throws Twig_Error_Loader  When the template cannot be found
     * @throws Twig_Error_Syntax  When an error occurred during compilation
     * @throws Twig_Error_Runtime When an error occurred during rendering
     */
    public function display($name, array $context = array())
    {
        $this->loadTemplate($name)->display($context);
    }

    /**
     * Loads a template by name.
     *
     * @param string  $name  The template name
     * @param integer $index The index if it is an embedded template
     *
     * @return Twig_TemplateInterface A template instance representing the given template name
     *
     * @throws Twig_Error_Loader When the template cannot be found
     * @throws Twig_Error_Syntax When an error occurred during compilation
     */
    public function loadTemplate($name, $index = null)
    {
        $cls = $this->getTemplateClass($name, $index);

        if (isset($this->loadedTemplates[$cls])) {
            return $this->loadedTemplates[$cls];
        }

        if (!class_exists($cls, false)) {
            if (false === $cache = $this->getCacheFilename($name)) {
                eval('?>'.$this->compileSource($this->getLoader()->getSource($name), $name));
            } else {
                if (!is_file($cache) || ($this->isAutoReload() && !$this->isTemplateFresh($name, filemtime($cache)))) {
                    $this->writeCacheFile($cache, $this->compileSource($this->getLoader()->getSource($name), $name));
                }

                require_once $cache;
            }
        }

        if (!$this->runtimeInitialized) {
            $this->initRuntime();
        }

        return $this->loadedTemplates[$cls] = new $cls($this);
    }

    /**
     * Returns true if the template is still fresh.
     *
     * Besides checking the loader for freshness information,
     * this method also checks if the enabled extensions have
     * not changed.
     *
     * @param string    $name The template name
     * @param timestamp $time The last modification time of the cached template
     *
     * @return Boolean true if the template is fresh, false otherwise
     */
    public function isTemplateFresh($name, $time)
    {
        foreach ($this->extensions as $extension) {
            $r = new ReflectionObject($extension);
            if (filemtime($r->getFileName()) > $time) {
                return false;
            }
        }

        return $this->getLoader()->isFresh($name, $time);
    }

    /**
     * Tries to load a template consecutively from an array.
     *
     * Similar to loadTemplate() but it also accepts Twig_TemplateInterface instances and an array
     * of templates where each is tried to be loaded.
     *
     * @param string|Twig_Template|array $names A template or an array of templates to try consecutively
     *
     * @return Twig_Template
     *
     * @throws Twig_Error_Loader When none of the templates can be found
     * @throws Twig_Error_Syntax When an error occurred during compilation
     */
    public function resolveTemplate($names)
    {
        if (!is_array($names)) {
            $names = array($names);
        }

        foreach ($names as $name) {
            if ($name instanceof Twig_Template) {
                return $name;
            }

            try {
                return $this->loadTemplate($name);
            } catch (Twig_Error_Loader $e) {
            }
        }

        if (1 === count($names)) {
            throw $e;
        }

        throw new Twig_Error_Loader(sprintf('Unable to find one of the following templates: "%s".', implode('", "', $names)));
    }

    /**
     * Clears the internal template cache.
     */
    public function clearTemplateCache()
    {
        $this->loadedTemplates = array();
    }

    /**
     * Clears the template cache files on the filesystem.
     */
    public function clearCacheFiles()
    {
        if (false === $this->cache) {
            return;
        }

        foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->cache), RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
            if ($file->isFile()) {
                @unlink($file->getPathname());
            }
        }
    }

    /**
     * Gets the Lexer instance.
     *
     * @return Twig_LexerInterface A Twig_LexerInterface instance
     */
    public function getLexer()
    {
        if (null === $this->lexer) {
            $this->lexer = new Twig_Lexer($this);
        }

        return $this->lexer;
    }

    /**
     * Sets the Lexer instance.
     *
     * @param Twig_LexerInterface A Twig_LexerInterface instance
     */
    public function setLexer(Twig_LexerInterface $lexer)
    {
        $this->lexer = $lexer;
    }

    /**
     * Tokenizes a source code.
     *
     * @param string $source The template source code
     * @param string $name   The template name
     *
     * @return Twig_TokenStream A Twig_TokenStream instance
     *
     * @throws Twig_Error_Syntax When the code is syntactically wrong
     */
    public function tokenize($source, $name = null)
    {
        return $this->getLexer()->tokenize($source, $name);
    }

    /**
     * Gets the Parser instance.
     *
     * @return Twig_ParserInterface A Twig_ParserInterface instance
     */
    public function getParser()
    {
        if (null === $this->parser) {
            $this->parser = new Twig_Parser($this);
        }

        return $this->parser;
    }

    /**
     * Sets the Parser instance.
     *
     * @param Twig_ParserInterface A Twig_ParserInterface instance
     */
    public function setParser(Twig_ParserInterface $parser)
    {
        $this->parser = $parser;
    }

    /**
     * Converts a token stream to a node tree.
     *
     * @param Twig_TokenStream $stream A token stream instance
     *
     * @return Twig_Node_Module A node tree
     *
     * @throws Twig_Error_Syntax When the token stream is syntactically or semantically wrong
     */
    public function parse(Twig_TokenStream $stream)
    {
        return $this->getParser()->parse($stream);
    }

    /**
     * Gets the Compiler instance.
     *
     * @return Twig_CompilerInterface A Twig_CompilerInterface instance
     */
    public function getCompiler()
    {
        if (null === $this->compiler) {
            $this->compiler = new Twig_Compiler($this);
        }

        return $this->compiler;
    }

    /**
     * Sets the Compiler instance.
     *
     * @param Twig_CompilerInterface $compiler A Twig_CompilerInterface instance
     */
    public function setCompiler(Twig_CompilerInterface $compiler)
    {
        $this->compiler = $compiler;
    }

    /**
     * Compiles a node and returns the PHP code.
     *
     * @param Twig_NodeInterface $node A Twig_NodeInterface instance
     *
     * @return string The compiled PHP source code
     */
    public function compile(Twig_NodeInterface $node)
    {
        return $this->getCompiler()->compile($node)->getSource();
    }

    /**
     * Compiles a template source code.
     *
     * @param string $source The template source code
     * @param string $name   The template name
     *
     * @return string The compiled PHP source code
     *
     * @throws Twig_Error_Syntax When there was an error during tokenizing, parsing or compiling
     */
    public function compileSource($source, $name = null)
    {
        try {
            return $this->compile($this->parse($this->tokenize($source, $name)));
        } catch (Twig_Error $e) {
            $e->setTemplateFile($name);
            throw $e;
        } catch (Exception $e) {
            throw new Twig_Error_Syntax(sprintf('An exception has been thrown during the compilation of a template ("%s").', $e->getMessage()), -1, $name, $e);
        }
    }

    /**
     * Sets the Loader instance.
     *
     * @param Twig_LoaderInterface $loader A Twig_LoaderInterface instance
     */
    public function setLoader(Twig_LoaderInterface $loader)
    {
        $this->loader = $loader;
    }

    /**
     * Gets the Loader instance.
     *
     * @return Twig_LoaderInterface A Twig_LoaderInterface instance
     */
    public function getLoader()
    {
        if (null === $this->loader) {
            throw new LogicException('You must set a loader first.');
        }

        return $this->loader;
    }

    /**
     * Sets the default template charset.
     *
     * @param string $charset The default charset
     */
    public function setCharset($charset)
    {
        $this->charset = strtoupper($charset);
    }

    /**
     * Gets the default template charset.
     *
     * @return string The default charset
     */
    public function getCharset()
    {
        return $this->charset;
    }

    /**
     * Initializes the runtime environment.
     */
    public function initRuntime()
    {
        $this->runtimeInitialized = true;

        foreach ($this->getExtensions() as $extension) {
            $extension->initRuntime($this);
        }
    }

    /**
     * Returns true if the given extension is registered.
     *
     * @param string $name The extension name
     *
     * @return Boolean Whether the extension is registered or not
     */
    public function hasExtension($name)
    {
        return isset($this->extensions[$name]);
    }

    /**
     * Gets an extension by name.
     *
     * @param string $name The extension name
     *
     * @return Twig_ExtensionInterface A Twig_ExtensionInterface instance
     */
    public function getExtension($name)
    {
        if (!isset($this->extensions[$name])) {
            throw new Twig_Error_Runtime(sprintf('The "%s" extension is not enabled.', $name));
        }

        return $this->extensions[$name];
    }

    /**
     * Registers an extension.
     *
     * @param Twig_ExtensionInterface $extension A Twig_ExtensionInterface instance
     */
    public function addExtension(Twig_ExtensionInterface $extension)
    {
        if ($this->extensionInitialized) {
            throw new LogicException(sprintf('Unable to register extension "%s" as extensions have already been initialized.', $extension->getName()));
        }

        $this->extensions[$extension->getName()] = $extension;
    }

    /**
     * Removes an extension by name.
     *
     * This method is deprecated and you should not use it.
     *
     * @param string $name The extension name
     *
     * @deprecated since 1.12 (to be removed in 2.0)
     */
    public function removeExtension($name)
    {
        if ($this->extensionInitialized) {
            throw new LogicException(sprintf('Unable to remove extension "%s" as extensions have already been initialized.', $name));
        }

        unset($this->extensions[$name]);
    }

    /**
     * Registers an array of extensions.
     *
     * @param array $extensions An array of extensions
     */
    public function setExtensions(array $extensions)
    {
        foreach ($extensions as $extension) {
            $this->addExtension($extension);
        }
    }

    /**
     * Returns all registered extensions.
     *
     * @return array An array of extensions
     */
    public function getExtensions()
    {
        return $this->extensions;
    }

    /**
     * Registers a Token Parser.
     *
     * @param Twig_TokenParserInterface $parser A Twig_TokenParserInterface instance
     */
    public function addTokenParser(Twig_TokenParserInterface $parser)
    {
        if ($this->extensionInitialized) {
            throw new LogicException('Unable to add a token parser as extensions have already been initialized.');
        }

        $this->staging->addTokenParser($parser);
    }

    /**
     * Gets the registered Token Parsers.
     *
     * @return Twig_TokenParserBrokerInterface A broker containing token parsers
     */
    public function getTokenParsers()
    {
        if (!$this->extensionInitialized) {
            $this->initExtensions();
        }

        return $this->parsers;
    }

    /**
     * Gets registered tags.
     *
     * Be warned that this method cannot return tags defined by Twig_TokenParserBrokerInterface classes.
     *
     * @return Twig_TokenParserInterface[] An array of Twig_TokenParserInterface instances
     */
    public function getTags()
    {
        $tags = array();
        foreach ($this->getTokenParsers()->getParsers() as $parser) {
            if ($parser instanceof Twig_TokenParserInterface) {
                $tags[$parser->getTag()] = $parser;
            }
        }

        return $tags;
    }

    /**
     * Registers a Node Visitor.
     *
     * @param Twig_NodeVisitorInterface $visitor A Twig_NodeVisitorInterface instance
     */
    public function addNodeVisitor(Twig_NodeVisitorInterface $visitor)
    {
        if ($this->extensionInitialized) {
            throw new LogicException('Unable to add a node visitor as extensions have already been initialized.');
        }

        $this->staging->addNodeVisitor($visitor);
    }

    /**
     * Gets the registered Node Visitors.
     *
     * @return Twig_NodeVisitorInterface[] An array of Twig_NodeVisitorInterface instances
     */
    public function getNodeVisitors()
    {
        if (!$this->extensionInitialized) {
            $this->initExtensions();
        }

        return $this->visitors;
    }

    /**
     * Registers a Filter.
     *
     * @param string|Twig_SimpleFilter               $name   The filter name or a Twig_SimpleFilter instance
     * @param Twig_FilterInterface|Twig_SimpleFilter $filter A Twig_FilterInterface instance or a Twig_SimpleFilter instance
     */
    public function addFilter($name, $filter = null)
    {
        if (!$name instanceof Twig_SimpleFilter && !($filter instanceof Twig_SimpleFilter || $filter instanceof Twig_FilterInterface)) {
            throw new LogicException('A filter must be an instance of Twig_FilterInterface or Twig_SimpleFilter');
        }

        if ($name instanceof Twig_SimpleFilter) {
            $filter = $name;
            $name = $filter->getName();
        }

        if ($this->extensionInitialized) {
            throw new LogicException(sprintf('Unable to add filter "%s" as extensions have already been initialized.', $name));
        }

        $this->staging->addFilter($name, $filter);
    }

    /**
     * Get a filter by name.
     *
     * Subclasses may override this method and load filters differently;
     * so no list of filters is available.
     *
     * @param string $name The filter name
     *
     * @return Twig_Filter|false A Twig_Filter instance or false if the filter does not exist
     */
    public function getFilter($name)
    {
        if (!$this->extensionInitialized) {
            $this->initExtensions();
        }

        if (isset($this->filters[$name])) {
            return $this->filters[$name];
        }

        foreach ($this->filters as $pattern => $filter) {
            $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count);

            if ($count) {
                if (preg_match('#^'.$pattern.'$#', $name, $matches)) {
                    array_shift($matches);
                    $filter->setArguments($matches);

                    return $filter;
                }
            }
        }

        foreach ($this->filterCallbacks as $callback) {
            if (false !== $filter = call_user_func($callback, $name)) {
                return $filter;
            }
        }

        return false;
    }

    public function registerUndefinedFilterCallback($callable)
    {
        $this->filterCallbacks[] = $callable;
    }

    /**
     * Gets the registered Filters.
     *
     * Be warned that this method cannot return filters defined with registerUndefinedFunctionCallback.
     *
     * @return Twig_FilterInterface[] An array of Twig_FilterInterface instances
     *
     * @see registerUndefinedFilterCallback
     */
    public function getFilters()
    {
        if (!$this->extensionInitialized) {
            $this->initExtensions();
        }

        return $this->filters;
    }

    /**
     * Registers a Test.
     *
     * @param string|Twig_SimpleTest             $name The test name or a Twig_SimpleTest instance
     * @param Twig_TestInterface|Twig_SimpleTest $test A Twig_TestInterface instance or a Twig_SimpleTest instance
     */
    public function addTest($name, $test = null)
    {
        if (!$name instanceof Twig_SimpleTest && !($test instanceof Twig_SimpleTest || $test instanceof Twig_TestInterface)) {
            throw new LogicException('A test must be an instance of Twig_TestInterface or Twig_SimpleTest');
        }

        if ($name instanceof Twig_SimpleTest) {
            $test = $name;
            $name = $test->getName();
        }

        if ($this->extensionInitialized) {
            throw new LogicException(sprintf('Unable to add test "%s" as extensions have already been initialized.', $name));
        }

        $this->staging->addTest($name, $test);
    }

    /**
     * Gets the registered Tests.
     *
     * @return Twig_TestInterface[] An array of Twig_TestInterface instances
     */
    public function getTests()
    {
        if (!$this->extensionInitialized) {
            $this->initExtensions();
        }

        return $this->tests;
    }

    /**
     * Gets a test by name.
     *
     * @param string $name The test name
     *
     * @return Twig_Test|false A Twig_Test instance or false if the test does not exist
     */
    public function getTest($name)
    {
        if (!$this->extensionInitialized) {
            $this->initExtensions();
        }

        if (isset($this->tests[$name])) {
            return $this->tests[$name];
        }

        return false;
    }

    /**
     * Registers a Function.
     *
     * @param string|Twig_SimpleFunction                 $name     The function name or a Twig_SimpleFunction instance
     * @param Twig_FunctionInterface|Twig_SimpleFunction $function A Twig_FunctionInterface instance or a Twig_SimpleFunction instance
     */
    public function addFunction($name, $function = null)
    {
        if (!$name instanceof Twig_SimpleFunction && !($function instanceof Twig_SimpleFunction || $function instanceof Twig_FunctionInterface)) {
            throw new LogicException('A function must be an instance of Twig_FunctionInterface or Twig_SimpleFunction');
        }

        if ($name instanceof Twig_SimpleFunction) {
            $function = $name;
            $name = $function->getName();
        }

        if ($this->extensionInitialized) {
            throw new LogicException(sprintf('Unable to add function "%s" as extensions have already been initialized.', $name));
        }

        $this->staging->addFunction($name, $function);
    }

    /**
     * Get a function by name.
     *
     * Subclasses may override this method and load functions differently;
     * so no list of functions is available.
     *
     * @param string $name function name
     *
     * @return Twig_Function|false A Twig_Function instance or false if the function does not exist
     */
    public function getFunction($name)
    {
        if (!$this->extensionInitialized) {
            $this->initExtensions();
        }

        if (isset($this->functions[$name])) {
            return $this->functions[$name];
        }

        foreach ($this->functions as $pattern => $function) {
            $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count);

            if ($count) {
                if (preg_match('#^'.$pattern.'$#', $name, $matches)) {
                    array_shift($matches);
                    $function->setArguments($matches);

                    return $function;
                }
            }
        }

        foreach ($this->functionCallbacks as $callback) {
            if (false !== $function = call_user_func($callback, $name)) {
                return $function;
            }
        }

        return false;
    }

    public function registerUndefinedFunctionCallback($callable)
    {
        $this->functionCallbacks[] = $callable;
    }

    /**
     * Gets registered functions.
     *
     * Be warned that this method cannot return functions defined with registerUndefinedFunctionCallback.
     *
     * @return Twig_FunctionInterface[] An array of Twig_FunctionInterface instances
     *
     * @see registerUndefinedFunctionCallback
     */
    public function getFunctions()
    {
        if (!$this->extensionInitialized) {
            $this->initExtensions();
        }

        return $this->functions;
    }

    /**
     * Registers a Global.
     *
     * New globals can be added before compiling or rendering a template;
     * but after, you can only update existing globals.
     *
     * @param string $name  The global name
     * @param mixed  $value The global value
     */
    public function addGlobal($name, $value)
    {
        if ($this->extensionInitialized || $this->runtimeInitialized) {
            if (null === $this->globals) {
                $this->globals = $this->initGlobals();
            }

            /* This condition must be uncommented in Twig 2.0
            if (!array_key_exists($name, $this->globals)) {
                throw new LogicException(sprintf('Unable to add global "%s" as the runtime or the extensions have already been initialized.', $name));
            }
            */
        }

        if ($this->extensionInitialized || $this->runtimeInitialized) {
            // update the value
            $this->globals[$name] = $value;
        } else {
            $this->staging->addGlobal($name, $value);
        }
    }

    /**
     * Gets the registered Globals.
     *
     * @return array An array of globals
     */
    public function getGlobals()
    {
        if (!$this->runtimeInitialized && !$this->extensionInitialized) {
            return $this->initGlobals();
        }

        if (null === $this->globals) {
            $this->globals = $this->initGlobals();
        }

        return $this->globals;
    }

    /**
     * Merges a context with the defined globals.
     *
     * @param array $context An array representing the context
     *
     * @return array The context merged with the globals
     */
    public function mergeGlobals(array $context)
    {
        // we don't use array_merge as the context being generally
        // bigger than globals, this code is faster.
        foreach ($this->getGlobals() as $key => $value) {
            if (!array_key_exists($key, $context)) {
                $context[$key] = $value;
            }
        }

        return $context;
    }

    /**
     * Gets the registered unary Operators.
     *
     * @return array An array of unary operators
     */
    public function getUnaryOperators()
    {
        if (!$this->extensionInitialized) {
            $this->initExtensions();
        }

        return $this->unaryOperators;
    }

    /**
     * Gets the registered binary Operators.
     *
     * @return array An array of binary operators
     */
    public function getBinaryOperators()
    {
        if (!$this->extensionInitialized) {
            $this->initExtensions();
        }

        return $this->binaryOperators;
    }

    public function computeAlternatives($name, $items)
    {
        $alternatives = array();
        foreach ($items as $item) {
            $lev = levenshtein($name, $item);
            if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) {
                $alternatives[$item] = $lev;
            }
        }
        asort($alternatives);

        return array_keys($alternatives);
    }

    protected function initGlobals()
    {
        $globals = array();
        foreach ($this->extensions as $extension) {
            $extGlob = $extension->getGlobals();
            if (!is_array($extGlob)) {
                throw new UnexpectedValueException(sprintf('"%s::getGlobals()" must return an array of globals.', get_class($extension)));
            }

            $globals[] = $extGlob;
        }

        $globals[] = $this->staging->getGlobals();

        return call_user_func_array('array_merge', $globals);
    }

    protected function initExtensions()
    {
        if ($this->extensionInitialized) {
            return;
        }

        $this->extensionInitialized = true;
        $this->parsers = new Twig_TokenParserBroker();
        $this->filters = array();
        $this->functions = array();
        $this->tests = array();
        $this->visitors = array();
        $this->unaryOperators = array();
        $this->binaryOperators = array();

        foreach ($this->extensions as $extension) {
            $this->initExtension($extension);
        }
        $this->initExtension($this->staging);
    }

    protected function initExtension(Twig_ExtensionInterface $extension)
    {
        // filters
        foreach ($extension->getFilters() as $name => $filter) {
            if ($name instanceof Twig_SimpleFilter) {
                $filter = $name;
                $name = $filter->getName();
            } elseif ($filter instanceof Twig_SimpleFilter) {
                $name = $filter->getName();
            }

            $this->filters[$name] = $filter;
        }

        // functions
        foreach ($extension->getFunctions() as $name => $function) {
            if ($name instanceof Twig_SimpleFunction) {
                $function = $name;
                $name = $function->getName();
            } elseif ($function instanceof Twig_SimpleFunction) {
                $name = $function->getName();
            }

            $this->functions[$name] = $function;
        }

        // tests
        foreach ($extension->getTests() as $name => $test) {
            if ($name instanceof Twig_SimpleTest) {
                $test = $name;
                $name = $test->getName();
            } elseif ($test instanceof Twig_SimpleTest) {
                $name = $test->getName();
            }

            $this->tests[$name] = $test;
        }

        // token parsers
        foreach ($extension->getTokenParsers() as $parser) {
            if ($parser instanceof Twig_TokenParserInterface) {
                $this->parsers->addTokenParser($parser);
            } elseif ($parser instanceof Twig_TokenParserBrokerInterface) {
                $this->parsers->addTokenParserBroker($parser);
            } else {
                throw new LogicException('getTokenParsers() must return an array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances');
            }
        }

        // node visitors
        foreach ($extension->getNodeVisitors() as $visitor) {
            $this->visitors[] = $visitor;
        }

        // operators
        if ($operators = $extension->getOperators()) {
            if (2 !== count($operators)) {
                throw new InvalidArgumentException(sprintf('"%s::getOperators()" does not return a valid operators array.', get_class($extension)));
            }

            $this->unaryOperators = array_merge($this->unaryOperators, $operators[0]);
            $this->binaryOperators = array_merge($this->binaryOperators, $operators[1]);
        }
    }

    protected function writeCacheFile($file, $content)
    {
        $dir = dirname($file);
        if (!is_dir($dir)) {
            if (false === @mkdir($dir, 0777, true) && !is_dir($dir)) {
                throw new RuntimeException(sprintf("Unable to create the cache directory (%s).", $dir));
            }
        } elseif (!is_writable($dir)) {
            throw new RuntimeException(sprintf("Unable to write in the cache directory (%s).", $dir));
        }

        $tmpFile = tempnam($dir, basename($file));
        if (false !== @file_put_contents($tmpFile, $content)) {
            // rename does not work on Win32 before 5.2.6
            if (@rename($tmpFile, $file) || (@copy($tmpFile, $file) && unlink($tmpFile))) {
                @chmod($file, 0666 & ~umask());

                return;
            }
        }

        throw new RuntimeException(sprintf('Failed to write cache file "%s".', $file));
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010-2012 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a template function.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_SimpleFunction
{
    protected $name;
    protected $callable;
    protected $options;
    protected $arguments = array();

    public function __construct($name, $callable, array $options = array())
    {
        $this->name = $name;
        $this->callable = $callable;
        $this->options = array_merge(array(
            'needs_environment' => false,
            'needs_context'     => false,
            'is_safe'           => null,
            'is_safe_callback'  => null,
            'node_class'        => 'Twig_Node_Expression_Function',
        ), $options);
    }

    public function getName()
    {
        return $this->name;
    }

    public function getCallable()
    {
        return $this->callable;
    }

    public function getNodeClass()
    {
        return $this->options['node_class'];
    }

    public function setArguments($arguments)
    {
        $this->arguments = $arguments;
    }

    public function getArguments()
    {
        return $this->arguments;
    }

    public function needsEnvironment()
    {
        return $this->options['needs_environment'];
    }

    public function needsContext()
    {
        return $this->options['needs_context'];
    }

    public function getSafe(Twig_Node $functionArgs)
    {
        if (null !== $this->options['is_safe']) {
            return $this->options['is_safe'];
        }

        if (null !== $this->options['is_safe_callback']) {
            return call_user_func($this->options['is_safe_callback'], $functionArgs);
        }

        return array();
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Default parser implementation.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Parser implements Twig_ParserInterface
{
    protected $stack = array();
    protected $stream;
    protected $parent;
    protected $handlers;
    protected $visitors;
    protected $expressionParser;
    protected $blocks;
    protected $blockStack;
    protected $macros;
    protected $env;
    protected $reservedMacroNames;
    protected $importedSymbols;
    protected $traits;
    protected $embeddedTemplates = array();

    /**
     * Constructor.
     *
     * @param Twig_Environment $env A Twig_Environment instance
     */
    public function __construct(Twig_Environment $env)
    {
        $this->env = $env;
    }

    public function getEnvironment()
    {
        return $this->env;
    }

    public function getVarName()
    {
        return sprintf('__internal_%s', hash('sha256', uniqid(mt_rand(), true), false));
    }

    public function getFilename()
    {
        return $this->stream->getFilename();
    }

    /**
     * {@inheritdoc}
     */
    public function parse(Twig_TokenStream $stream, $test = null, $dropNeedle = false)
    {
        // push all variables into the stack to keep the current state of the parser
        $vars = get_object_vars($this);
        unset($vars['stack'], $vars['env'], $vars['handlers'], $vars['visitors'], $vars['expressionParser']);
        $this->stack[] = $vars;

        // tag handlers
        if (null === $this->handlers) {
            $this->handlers = $this->env->getTokenParsers();
            $this->handlers->setParser($this);
        }

        // node visitors
        if (null === $this->visitors) {
            $this->visitors = $this->env->getNodeVisitors();
        }

        if (null === $this->expressionParser) {
            $this->expressionParser = new Twig_ExpressionParser($this, $this->env->getUnaryOperators(), $this->env->getBinaryOperators());
        }

        $this->stream = $stream;
        $this->parent = null;
        $this->blocks = array();
        $this->macros = array();
        $this->traits = array();
        $this->blockStack = array();
        $this->importedSymbols = array(array());
        $this->embeddedTemplates = array();

        try {
            $body = $this->subparse($test, $dropNeedle);

            if (null !== $this->parent) {
                if (null === $body = $this->filterBodyNodes($body)) {
                    $body = new Twig_Node();
                }
            }
        } catch (Twig_Error_Syntax $e) {
            if (!$e->getTemplateFile()) {
                $e->setTemplateFile($this->getFilename());
            }

            if (!$e->getTemplateLine()) {
                $e->setTemplateLine($this->stream->getCurrent()->getLine());
            }

            throw $e;
        }

        $node = new Twig_Node_Module(new Twig_Node_Body(array($body)), $this->parent, new Twig_Node($this->blocks), new Twig_Node($this->macros), new Twig_Node($this->traits), $this->embeddedTemplates, $this->getFilename());

        $traverser = new Twig_NodeTraverser($this->env, $this->visitors);

        $node = $traverser->traverse($node);

        // restore previous stack so previous parse() call can resume working
        foreach (array_pop($this->stack) as $key => $val) {
            $this->$key = $val;
        }

        return $node;
    }

    public function subparse($test, $dropNeedle = false)
    {
        $lineno = $this->getCurrentToken()->getLine();
        $rv = array();
        while (!$this->stream->isEOF()) {
            switch ($this->getCurrentToken()->getType()) {
                case Twig_Token::TEXT_TYPE:
                    $token = $this->stream->next();
                    $rv[] = new Twig_Node_Text($token->getValue(), $token->getLine());
                    break;

                case Twig_Token::VAR_START_TYPE:
                    $token = $this->stream->next();
                    $expr = $this->expressionParser->parseExpression();
                    $this->stream->expect(Twig_Token::VAR_END_TYPE);
                    $rv[] = new Twig_Node_Print($expr, $token->getLine());
                    break;

                case Twig_Token::BLOCK_START_TYPE:
                    $this->stream->next();
                    $token = $this->getCurrentToken();

                    if ($token->getType() !== Twig_Token::NAME_TYPE) {
                        throw new Twig_Error_Syntax('A block must start with a tag name', $token->getLine(), $this->getFilename());
                    }

                    if (null !== $test && call_user_func($test, $token)) {
                        if ($dropNeedle) {
                            $this->stream->next();
                        }

                        if (1 === count($rv)) {
                            return $rv[0];
                        }

                        return new Twig_Node($rv, array(), $lineno);
                    }

                    $subparser = $this->handlers->getTokenParser($token->getValue());
                    if (null === $subparser) {
                        if (null !== $test) {
                            $error = sprintf('Unexpected tag name "%s"', $token->getValue());
                            if (is_array($test) && isset($test[0]) && $test[0] instanceof Twig_TokenParserInterface) {
                                $error .= sprintf(' (expecting closing tag for the "%s" tag defined near line %s)', $test[0]->getTag(), $lineno);
                            }

                            throw new Twig_Error_Syntax($error, $token->getLine(), $this->getFilename());
                        }

                        $message = sprintf('Unknown tag name "%s"', $token->getValue());
                        if ($alternatives = $this->env->computeAlternatives($token->getValue(), array_keys($this->env->getTags()))) {
                            $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
                        }

                        throw new Twig_Error_Syntax($message, $token->getLine(), $this->getFilename());
                    }

                    $this->stream->next();

                    $node = $subparser->parse($token);
                    if (null !== $node) {
                        $rv[] = $node;
                    }
                    break;

                default:
                    throw new Twig_Error_Syntax('Lexer or parser ended up in unsupported state.', 0, $this->getFilename());
            }
        }

        if (1 === count($rv)) {
            return $rv[0];
        }

        return new Twig_Node($rv, array(), $lineno);
    }

    public function addHandler($name, $class)
    {
        $this->handlers[$name] = $class;
    }

    public function addNodeVisitor(Twig_NodeVisitorInterface $visitor)
    {
        $this->visitors[] = $visitor;
    }

    public function getBlockStack()
    {
        return $this->blockStack;
    }

    public function peekBlockStack()
    {
        return $this->blockStack[count($this->blockStack) - 1];
    }

    public function popBlockStack()
    {
        array_pop($this->blockStack);
    }

    public function pushBlockStack($name)
    {
        $this->blockStack[] = $name;
    }

    public function hasBlock($name)
    {
        return isset($this->blocks[$name]);
    }

    public function getBlock($name)
    {
        return $this->blocks[$name];
    }

    public function setBlock($name, Twig_Node_Block $value)
    {
        $this->blocks[$name] = new Twig_Node_Body(array($value), array(), $value->getLine());
    }

    public function hasMacro($name)
    {
        return isset($this->macros[$name]);
    }

    public function setMacro($name, Twig_Node_Macro $node)
    {
        if (null === $this->reservedMacroNames) {
            $this->reservedMacroNames = array();
            $r = new ReflectionClass($this->env->getBaseTemplateClass());
            foreach ($r->getMethods() as $method) {
                $this->reservedMacroNames[] = $method->getName();
            }
        }

        if (in_array($name, $this->reservedMacroNames)) {
            throw new Twig_Error_Syntax(sprintf('"%s" cannot be used as a macro name as it is a reserved keyword', $name), $node->getLine(), $this->getFilename());
        }

        $this->macros[$name] = $node;
    }

    public function addTrait($trait)
    {
        $this->traits[] = $trait;
    }

    public function hasTraits()
    {
        return count($this->traits) > 0;
    }

    public function embedTemplate(Twig_Node_Module $template)
    {
        $template->setIndex(mt_rand());

        $this->embeddedTemplates[] = $template;
    }

    public function addImportedSymbol($type, $alias, $name = null, Twig_Node_Expression $node = null)
    {
        $this->importedSymbols[0][$type][$alias] = array('name' => $name, 'node' => $node);
    }

    public function getImportedSymbol($type, $alias)
    {
        foreach ($this->importedSymbols as $functions) {
            if (isset($functions[$type][$alias])) {
                return $functions[$type][$alias];
            }
        }
    }

    public function isMainScope()
    {
        return 1 === count($this->importedSymbols);
    }

    public function pushLocalScope()
    {
        array_unshift($this->importedSymbols, array());
    }

    public function popLocalScope()
    {
        array_shift($this->importedSymbols);
    }

    /**
     * Gets the expression parser.
     *
     * @return Twig_ExpressionParser The expression parser
     */
    public function getExpressionParser()
    {
        return $this->expressionParser;
    }

    public function getParent()
    {
        return $this->parent;
    }

    public function setParent($parent)
    {
        $this->parent = $parent;
    }

    /**
     * Gets the token stream.
     *
     * @return Twig_TokenStream The token stream
     */
    public function getStream()
    {
        return $this->stream;
    }

    /**
     * Gets the current token.
     *
     * @return Twig_Token The current token
     */
    public function getCurrentToken()
    {
        return $this->stream->getCurrent();
    }

    protected function filterBodyNodes(Twig_NodeInterface $node)
    {
        // check that the body does not contain non-empty output nodes
        if (
            ($node instanceof Twig_Node_Text && !ctype_space($node->getAttribute('data')))
            ||
            (!$node instanceof Twig_Node_Text && !$node instanceof Twig_Node_BlockReference && $node instanceof Twig_NodeOutputInterface)
        ) {
            if (false !== strpos((string) $node, chr(0xEF).chr(0xBB).chr(0xBF))) {
                throw new Twig_Error_Syntax('A template that extends another one cannot have a body but a byte order mark (BOM) has been detected; it must be removed.', $node->getLine(), $this->getFilename());
            }

            throw new Twig_Error_Syntax('A template that extends another one cannot have a body.', $node->getLine(), $this->getFilename());
        }

        // bypass "set" nodes as they "capture" the output
        if ($node instanceof Twig_Node_Set) {
            return $node;
        }

        if ($node instanceof Twig_NodeOutputInterface) {
            return;
        }

        foreach ($node as $k => $n) {
            if (null !== $n && null === $n = $this->filterBodyNodes($n)) {
                $node->removeNode($k);
            }
        }

        return $node;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010-2012 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a template test.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_SimpleTest
{
    protected $name;
    protected $callable;
    protected $options;

    public function __construct($name, $callable, array $options = array())
    {
        $this->name = $name;
        $this->callable = $callable;
        $this->options = array_merge(array(
            'node_class' => 'Twig_Node_Expression_Test',
        ), $options);
    }

    public function getName()
    {
        return $this->name;
    }

    public function getCallable()
    {
        return $this->callable;
    }

    public function getNodeClass()
    {
        return $this->options['node_class'];
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Twig base exception.
 *
 * This exception class and its children must only be used when
 * an error occurs during the loading of a template, when a syntax error
 * is detected in a template, or when rendering a template. Other
 * errors must use regular PHP exception classes (like when the template
 * cache directory is not writable for instance).
 *
 * To help debugging template issues, this class tracks the original template
 * name and line where the error occurred.
 *
 * Whenever possible, you must set these information (original template name
 * and line number) yourself by passing them to the constructor. If some or all
 * these information are not available from where you throw the exception, then
 * this class will guess them automatically (when the line number is set to -1
 * and/or the filename is set to null). As this is a costly operation, this
 * can be disabled by passing false for both the filename and the line number
 * when creating a new instance of this class.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Error extends Exception
{
    protected $lineno;
    protected $filename;
    protected $rawMessage;
    protected $previous;

    /**
     * Constructor.
     *
     * Set both the line number and the filename to false to
     * disable automatic guessing of the original template name
     * and line number.
     *
     * Set the line number to -1 to enable its automatic guessing.
     * Set the filename to null to enable its automatic guessing.
     *
     * By default, automatic guessing is enabled.
     *
     * @param string    $message  The error message
     * @param integer   $lineno   The template line where the error occurred
     * @param string    $filename The template file name where the error occurred
     * @param Exception $previous The previous exception
     */
    public function __construct($message, $lineno = -1, $filename = null, Exception $previous = null)
    {
        if (version_compare(PHP_VERSION, '5.3.0', '<')) {
            $this->previous = $previous;
            parent::__construct('');
        } else {
            parent::__construct('', 0, $previous);
        }

        $this->lineno = $lineno;
        $this->filename = $filename;

        if (-1 === $this->lineno || null === $this->filename) {
            $this->guessTemplateInfo();
        }

        $this->rawMessage = $message;

        $this->updateRepr();
    }

    /**
     * Gets the raw message.
     *
     * @return string The raw message
     */
    public function getRawMessage()
    {
        return $this->rawMessage;
    }

    /**
     * Gets the filename where the error occurred.
     *
     * @return string The filename
     */
    public function getTemplateFile()
    {
        return $this->filename;
    }

    /**
     * Sets the filename where the error occurred.
     *
     * @param string $filename The filename
     */
    public function setTemplateFile($filename)
    {
        $this->filename = $filename;

        $this->updateRepr();
    }

    /**
     * Gets the template line where the error occurred.
     *
     * @return integer The template line
     */
    public function getTemplateLine()
    {
        return $this->lineno;
    }

    /**
     * Sets the template line where the error occurred.
     *
     * @param integer $lineno The template line
     */
    public function setTemplateLine($lineno)
    {
        $this->lineno = $lineno;

        $this->updateRepr();
    }

    public function guess()
    {
        $this->guessTemplateInfo();
        $this->updateRepr();
    }

    /**
     * For PHP < 5.3.0, provides access to the getPrevious() method.
     *
     * @param string $method    The method name
     * @param array  $arguments The parameters to be passed to the method
     *
     * @return Exception The previous exception or null
     *
     * @throws BadMethodCallException
     */
    public function __call($method, $arguments)
    {
        if ('getprevious' == strtolower($method)) {
            return $this->previous;
        }

        throw new BadMethodCallException(sprintf('Method "Twig_Error::%s()" does not exist.', $method));
    }

    protected function updateRepr()
    {
        $this->message = $this->rawMessage;

        $dot = false;
        if ('.' === substr($this->message, -1)) {
            $this->message = substr($this->message, 0, -1);
            $dot = true;
        }

        if ($this->filename) {
            if (is_string($this->filename) || (is_object($this->filename) && method_exists($this->filename, '__toString'))) {
                $filename = sprintf('"%s"', $this->filename);
            } else {
                $filename = json_encode($this->filename);
            }
            $this->message .= sprintf(' in %s', $filename);
        }

        if ($this->lineno && $this->lineno >= 0) {
            $this->message .= sprintf(' at line %d', $this->lineno);
        }

        if ($dot) {
            $this->message .= '.';
        }
    }

    protected function guessTemplateInfo()
    {
        $template = null;
        $templateClass = null;

        if (version_compare(phpversion(), '5.3.6', '>=')) {
            $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT);
        } else {
            $backtrace = debug_backtrace();
        }

        foreach ($backtrace as $trace) {
            if (isset($trace['object']) && $trace['object'] instanceof Twig_Template && 'Twig_Template' !== get_class($trace['object'])) {
                $currentClass = get_class($trace['object']);
                $isEmbedContainer = 0 === strpos($templateClass, $currentClass);
                if (null === $this->filename || ($this->filename == $trace['object']->getTemplateName() && !$isEmbedContainer)) {
                    $template = $trace['object'];
                    $templateClass = get_class($trace['object']);
                }
            }
        }

        // update template filename
        if (null !== $template && null === $this->filename) {
            $this->filename = $template->getTemplateName();
        }

        if (null === $template || $this->lineno > -1) {
            return;
        }

        $r = new ReflectionObject($template);
        $file = $r->getFileName();

        // hhvm has a bug where eval'ed files comes out as the current directory
        if (is_dir($file)) {
            $file = '';
        }

        $exceptions = array($e = $this);
        while (($e instanceof self || method_exists($e, 'getPrevious')) && $e = $e->getPrevious()) {
            $exceptions[] = $e;
        }

        while ($e = array_pop($exceptions)) {
            $traces = $e->getTrace();
            while ($trace = array_shift($traces)) {
                if (!isset($trace['file']) || !isset($trace['line']) || $file != $trace['file']) {
                    continue;
                }

                foreach ($template->getDebugInfo() as $codeLine => $templateLine) {
                    if ($codeLine <= $trace['line']) {
                        // update template line
                        $this->lineno = $templateLine;

                        return;
                    }
                }
            }
        }
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Autoloads Twig classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Autoloader
{
    /**
     * Registers Twig_Autoloader as an SPL autoloader.
     *
     * @param Boolean $prepend Whether to prepend the autoloader or not.
     */
    public static function register($prepend = false)
    {
        if (version_compare(phpversion(), '5.3.0', '>=')) {
            spl_autoload_register(array(new self, 'autoload'), true, $prepend);
        } else {
            spl_autoload_register(array(new self, 'autoload'));
        }
    }

    /**
     * Handles autoloading of classes.
     *
     * @param string $class A class name.
     */
    public static function autoload($class)
    {
        if (0 !== strpos($class, 'Twig')) {
            return;
        }

        if (is_file($file = dirname(__FILE__).'/../'.str_replace(array('_', "\0"), array('/', ''), $class).'.php')) {
            require $file;
        }
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a node in the AST.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node implements Twig_NodeInterface
{
    protected $nodes;
    protected $attributes;
    protected $lineno;
    protected $tag;

    /**
     * Constructor.
     *
     * The nodes are automatically made available as properties ($this->node).
     * The attributes are automatically made available as array items ($this['name']).
     *
     * @param array   $nodes      An array of named nodes
     * @param array   $attributes An array of attributes (should not be nodes)
     * @param integer $lineno     The line number
     * @param string  $tag        The tag name associated with the Node
     */
    public function __construct(array $nodes = array(), array $attributes = array(), $lineno = 0, $tag = null)
    {
        $this->nodes = $nodes;
        $this->attributes = $attributes;
        $this->lineno = $lineno;
        $this->tag = $tag;
    }

    public function __toString()
    {
        $attributes = array();
        foreach ($this->attributes as $name => $value) {
            $attributes[] = sprintf('%s: %s', $name, str_replace("\n", '', var_export($value, true)));
        }

        $repr = array(get_class($this).'('.implode(', ', $attributes));

        if (count($this->nodes)) {
            foreach ($this->nodes as $name => $node) {
                $len = strlen($name) + 4;
                $noderepr = array();
                foreach (explode("\n", (string) $node) as $line) {
                    $noderepr[] = str_repeat(' ', $len).$line;
                }

                $repr[] = sprintf('  %s: %s', $name, ltrim(implode("\n", $noderepr)));
            }

            $repr[] = ')';
        } else {
            $repr[0] .= ')';
        }

        return implode("\n", $repr);
    }

    public function toXml($asDom = false)
    {
        $dom = new DOMDocument('1.0', 'UTF-8');
        $dom->formatOutput = true;
        $dom->appendChild($xml = $dom->createElement('twig'));

        $xml->appendChild($node = $dom->createElement('node'));
        $node->setAttribute('class', get_class($this));

        foreach ($this->attributes as $name => $value) {
            $node->appendChild($attribute = $dom->createElement('attribute'));
            $attribute->setAttribute('name', $name);
            $attribute->appendChild($dom->createTextNode($value));
        }

        foreach ($this->nodes as $name => $n) {
            if (null === $n) {
                continue;
            }

            $child = $n->toXml(true)->getElementsByTagName('node')->item(0);
            $child = $dom->importNode($child, true);
            $child->setAttribute('name', $name);

            $node->appendChild($child);
        }

        return $asDom ? $dom : $dom->saveXml();
    }

    public function compile(Twig_Compiler $compiler)
    {
        foreach ($this->nodes as $node) {
            $node->compile($compiler);
        }
    }

    public function getLine()
    {
        return $this->lineno;
    }

    public function getNodeTag()
    {
        return $this->tag;
    }

    /**
     * Returns true if the attribute is defined.
     *
     * @param  string  The attribute name
     *
     * @return Boolean true if the attribute is defined, false otherwise
     */
    public function hasAttribute($name)
    {
        return array_key_exists($name, $this->attributes);
    }

    /**
     * Gets an attribute.
     *
     * @param  string The attribute name
     *
     * @return mixed The attribute value
     */
    public function getAttribute($name)
    {
        if (!array_key_exists($name, $this->attributes)) {
            throw new LogicException(sprintf('Attribute "%s" does not exist for Node "%s".', $name, get_class($this)));
        }

        return $this->attributes[$name];
    }

    /**
     * Sets an attribute.
     *
     * @param string The attribute name
     * @param mixed  The attribute value
     */
    public function setAttribute($name, $value)
    {
        $this->attributes[$name] = $value;
    }

    /**
     * Removes an attribute.
     *
     * @param string The attribute name
     */
    public function removeAttribute($name)
    {
        unset($this->attributes[$name]);
    }

    /**
     * Returns true if the node with the given identifier exists.
     *
     * @param  string  The node name
     *
     * @return Boolean true if the node with the given name exists, false otherwise
     */
    public function hasNode($name)
    {
        return array_key_exists($name, $this->nodes);
    }

    /**
     * Gets a node by name.
     *
     * @param  string The node name
     *
     * @return Twig_Node A Twig_Node instance
     */
    public function getNode($name)
    {
        if (!array_key_exists($name, $this->nodes)) {
            throw new LogicException(sprintf('Node "%s" does not exist for Node "%s".', $name, get_class($this)));
        }

        return $this->nodes[$name];
    }

    /**
     * Sets a node.
     *
     * @param string    The node name
     * @param Twig_Node A Twig_Node instance
     */
    public function setNode($name, $node = null)
    {
        $this->nodes[$name] = $node;
    }

    /**
     * Removes a node by name.
     *
     * @param string The node name
     */
    public function removeNode($name)
    {
        unset($this->nodes[$name]);
    }

    public function count()
    {
        return count($this->nodes);
    }

    public function getIterator()
    {
        return new ArrayIterator($this->nodes);
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Interface implemented by extension classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface Twig_ExtensionInterface
{
    /**
     * Initializes the runtime environment.
     *
     * This is where you can load some file that contains filter functions for instance.
     *
     * @param Twig_Environment $environment The current Twig_Environment instance
     */
    public function initRuntime(Twig_Environment $environment);

    /**
     * Returns the token parser instances to add to the existing list.
     *
     * @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
     */
    public function getTokenParsers();

    /**
     * Returns the node visitor instances to add to the existing list.
     *
     * @return array An array of Twig_NodeVisitorInterface instances
     */
    public function getNodeVisitors();

    /**
     * Returns a list of filters to add to the existing list.
     *
     * @return array An array of filters
     */
    public function getFilters();

    /**
     * Returns a list of tests to add to the existing list.
     *
     * @return array An array of tests
     */
    public function getTests();

    /**
     * Returns a list of functions to add to the existing list.
     *
     * @return array An array of functions
     */
    public function getFunctions();

    /**
     * Returns a list of operators to add to the existing list.
     *
     * @return array An array of operators
     */
    public function getOperators();

    /**
     * Returns a list of global variables to add to the existing list.
     *
     * @return array An array of global variables
     */
    public function getGlobals();

    /**
     * Returns the name of the extension.
     *
     * @return string The extension name
     */
    public function getName();
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Parses expressions.
 *
 * This parser implements a "Precedence climbing" algorithm.
 *
 * @see http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm
 * @see http://en.wikipedia.org/wiki/Operator-precedence_parser
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_ExpressionParser
{
    const OPERATOR_LEFT = 1;
    const OPERATOR_RIGHT = 2;

    protected $parser;
    protected $unaryOperators;
    protected $binaryOperators;

    public function __construct(Twig_Parser $parser, array $unaryOperators, array $binaryOperators)
    {
        $this->parser = $parser;
        $this->unaryOperators = $unaryOperators;
        $this->binaryOperators = $binaryOperators;
    }

    public function parseExpression($precedence = 0)
    {
        $expr = $this->getPrimary();
        $token = $this->parser->getCurrentToken();
        while ($this->isBinary($token) && $this->binaryOperators[$token->getValue()]['precedence'] >= $precedence) {
            $op = $this->binaryOperators[$token->getValue()];
            $this->parser->getStream()->next();

            if (isset($op['callable'])) {
                $expr = call_user_func($op['callable'], $this->parser, $expr);
            } else {
                $expr1 = $this->parseExpression(self::OPERATOR_LEFT === $op['associativity'] ? $op['precedence'] + 1 : $op['precedence']);
                $class = $op['class'];
                $expr = new $class($expr, $expr1, $token->getLine());
            }

            $token = $this->parser->getCurrentToken();
        }

        if (0 === $precedence) {
            return $this->parseConditionalExpression($expr);
        }

        return $expr;
    }

    protected function getPrimary()
    {
        $token = $this->parser->getCurrentToken();

        if ($this->isUnary($token)) {
            $operator = $this->unaryOperators[$token->getValue()];
            $this->parser->getStream()->next();
            $expr = $this->parseExpression($operator['precedence']);
            $class = $operator['class'];

            return $this->parsePostfixExpression(new $class($expr, $token->getLine()));
        } elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
            $this->parser->getStream()->next();
            $expr = $this->parseExpression();
            $this->parser->getStream()->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'An opened parenthesis is not properly closed');

            return $this->parsePostfixExpression($expr);
        }

        return $this->parsePrimaryExpression();
    }

    protected function parseConditionalExpression($expr)
    {
        while ($this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '?')) {
            $this->parser->getStream()->next();
            if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, ':')) {
                $expr2 = $this->parseExpression();
                if ($this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, ':')) {
                    $this->parser->getStream()->next();
                    $expr3 = $this->parseExpression();
                } else {
                    $expr3 = new Twig_Node_Expression_Constant('', $this->parser->getCurrentToken()->getLine());
                }
            } else {
                $this->parser->getStream()->next();
                $expr2 = $expr;
                $expr3 = $this->parseExpression();
            }

            $expr = new Twig_Node_Expression_Conditional($expr, $expr2, $expr3, $this->parser->getCurrentToken()->getLine());
        }

        return $expr;
    }

    protected function isUnary(Twig_Token $token)
    {
        return $token->test(Twig_Token::OPERATOR_TYPE) && isset($this->unaryOperators[$token->getValue()]);
    }

    protected function isBinary(Twig_Token $token)
    {
        return $token->test(Twig_Token::OPERATOR_TYPE) && isset($this->binaryOperators[$token->getValue()]);
    }

    public function parsePrimaryExpression()
    {
        $token = $this->parser->getCurrentToken();
        switch ($token->getType()) {
            case Twig_Token::NAME_TYPE:
                $this->parser->getStream()->next();
                switch ($token->getValue()) {
                    case 'true':
                    case 'TRUE':
                        $node = new Twig_Node_Expression_Constant(true, $token->getLine());
                        break;

                    case 'false':
                    case 'FALSE':
                        $node = new Twig_Node_Expression_Constant(false, $token->getLine());
                        break;

                    case 'none':
                    case 'NONE':
                    case 'null':
                    case 'NULL':
                        $node = new Twig_Node_Expression_Constant(null, $token->getLine());
                        break;

                    default:
                        if ('(' === $this->parser->getCurrentToken()->getValue()) {
                            $node = $this->getFunctionNode($token->getValue(), $token->getLine());
                        } else {
                            $node = new Twig_Node_Expression_Name($token->getValue(), $token->getLine());
                        }
                }
                break;

            case Twig_Token::NUMBER_TYPE:
                $this->parser->getStream()->next();
                $node = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
                break;

            case Twig_Token::STRING_TYPE:
            case Twig_Token::INTERPOLATION_START_TYPE:
                $node = $this->parseStringExpression();
                break;

            case Twig_Token::OPERATOR_TYPE:
                if (preg_match(Twig_Lexer::REGEX_NAME, $token->getValue(), $matches) && $matches[0] == $token->getValue()) {
                    // in this context, string operators are variable names
                    $this->parser->getStream()->next();
                    $node = new Twig_Node_Expression_Name($token->getValue(), $token->getLine());
                    break;
                }

            default:
                if ($token->test(Twig_Token::PUNCTUATION_TYPE, '[')) {
                    $node = $this->parseArrayExpression();
                } elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '{')) {
                    $node = $this->parseHashExpression();
                } else {
                    throw new Twig_Error_Syntax(sprintf('Unexpected token "%s" of value "%s"', Twig_Token::typeToEnglish($token->getType(), $token->getLine()), $token->getValue()), $token->getLine(), $this->parser->getFilename());
                }
        }

        return $this->parsePostfixExpression($node);
    }

    public function parseStringExpression()
    {
        $stream = $this->parser->getStream();

        $nodes = array();
        // a string cannot be followed by another string in a single expression
        $nextCanBeString = true;
        while (true) {
            if ($stream->test(Twig_Token::STRING_TYPE) && $nextCanBeString) {
                $token = $stream->next();
                $nodes[] = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
                $nextCanBeString = false;
            } elseif ($stream->test(Twig_Token::INTERPOLATION_START_TYPE)) {
                $stream->next();
                $nodes[] = $this->parseExpression();
                $stream->expect(Twig_Token::INTERPOLATION_END_TYPE);
                $nextCanBeString = true;
            } else {
                break;
            }
        }

        $expr = array_shift($nodes);
        foreach ($nodes as $node) {
            $expr = new Twig_Node_Expression_Binary_Concat($expr, $node, $node->getLine());
        }

        return $expr;
    }

    public function parseArrayExpression()
    {
        $stream = $this->parser->getStream();
        $stream->expect(Twig_Token::PUNCTUATION_TYPE, '[', 'An array element was expected');

        $node = new Twig_Node_Expression_Array(array(), $stream->getCurrent()->getLine());
        $first = true;
        while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) {
            if (!$first) {
                $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'An array element must be followed by a comma');

                // trailing ,?
                if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) {
                    break;
                }
            }
            $first = false;

            $node->addElement($this->parseExpression());
        }
        $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']', 'An opened array is not properly closed');

        return $node;
    }

    public function parseHashExpression()
    {
        $stream = $this->parser->getStream();
        $stream->expect(Twig_Token::PUNCTUATION_TYPE, '{', 'A hash element was expected');

        $node = new Twig_Node_Expression_Array(array(), $stream->getCurrent()->getLine());
        $first = true;
        while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, '}')) {
            if (!$first) {
                $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'A hash value must be followed by a comma');

                // trailing ,?
                if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '}')) {
                    break;
                }
            }
            $first = false;

            // a hash key can be:
            //
            //  * a number -- 12
            //  * a string -- 'a'
            //  * a name, which is equivalent to a string -- a
            //  * an expression, which must be enclosed in parentheses -- (1 + 2)
            if ($stream->test(Twig_Token::STRING_TYPE) || $stream->test(Twig_Token::NAME_TYPE) || $stream->test(Twig_Token::NUMBER_TYPE)) {
                $token = $stream->next();
                $key = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
            } elseif ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
                $key = $this->parseExpression();
            } else {
                $current = $stream->getCurrent();

                throw new Twig_Error_Syntax(sprintf('A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s"', Twig_Token::typeToEnglish($current->getType(), $current->getLine()), $current->getValue()), $current->getLine(), $this->parser->getFilename());
            }

            $stream->expect(Twig_Token::PUNCTUATION_TYPE, ':', 'A hash key must be followed by a colon (:)');
            $value = $this->parseExpression();

            $node->addElement($value, $key);
        }
        $stream->expect(Twig_Token::PUNCTUATION_TYPE, '}', 'An opened hash is not properly closed');

        return $node;
    }

    public function parsePostfixExpression($node)
    {
        while (true) {
            $token = $this->parser->getCurrentToken();
            if ($token->getType() == Twig_Token::PUNCTUATION_TYPE) {
                if ('.' == $token->getValue() || '[' == $token->getValue()) {
                    $node = $this->parseSubscriptExpression($node);
                } elseif ('|' == $token->getValue()) {
                    $node = $this->parseFilterExpression($node);
                } else {
                    break;
                }
            } else {
                break;
            }
        }

        return $node;
    }

    public function getFunctionNode($name, $line)
    {
        switch ($name) {
            case 'parent':
                $args = $this->parseArguments();
                if (!count($this->parser->getBlockStack())) {
                    throw new Twig_Error_Syntax('Calling "parent" outside a block is forbidden', $line, $this->parser->getFilename());
                }

                if (!$this->parser->getParent() && !$this->parser->hasTraits()) {
                    throw new Twig_Error_Syntax('Calling "parent" on a template that does not extend nor "use" another template is forbidden', $line, $this->parser->getFilename());
                }

                return new Twig_Node_Expression_Parent($this->parser->peekBlockStack(), $line);
            case 'block':
                return new Twig_Node_Expression_BlockReference($this->parseArguments()->getNode(0), false, $line);
            case 'attribute':
                $args = $this->parseArguments();
                if (count($args) < 2) {
                    throw new Twig_Error_Syntax('The "attribute" function takes at least two arguments (the variable and the attributes)', $line, $this->parser->getFilename());
                }

                return new Twig_Node_Expression_GetAttr($args->getNode(0), $args->getNode(1), count($args) > 2 ? $args->getNode(2) : new Twig_Node_Expression_Array(array(), $line), Twig_Template::ANY_CALL, $line);
            default:
                if (null !== $alias = $this->parser->getImportedSymbol('function', $name)) {
                    $arguments = new Twig_Node_Expression_Array(array(), $line);
                    foreach ($this->parseArguments() as $n) {
                        $arguments->addElement($n);
                    }

                    $node = new Twig_Node_Expression_MethodCall($alias['node'], $alias['name'], $arguments, $line);
                    $node->setAttribute('safe', true);

                    return $node;
                }

                $args = $this->parseArguments(true);
                $class = $this->getFunctionNodeClass($name, $line);

                return new $class($name, $args, $line);
        }
    }

    public function parseSubscriptExpression($node)
    {
        $stream = $this->parser->getStream();
        $token = $stream->next();
        $lineno = $token->getLine();
        $arguments = new Twig_Node_Expression_Array(array(), $lineno);
        $type = Twig_Template::ANY_CALL;
        if ($token->getValue() == '.') {
            $token = $stream->next();
            if (
                $token->getType() == Twig_Token::NAME_TYPE
                ||
                $token->getType() == Twig_Token::NUMBER_TYPE
                ||
                ($token->getType() == Twig_Token::OPERATOR_TYPE && preg_match(Twig_Lexer::REGEX_NAME, $token->getValue()))
            ) {
                $arg = new Twig_Node_Expression_Constant($token->getValue(), $lineno);

                if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
                    $type = Twig_TemplateInterface::METHOD_CALL;
                    foreach ($this->parseArguments() as $n) {
                        $arguments->addElement($n);
                    }
                }
            } else {
                throw new Twig_Error_Syntax('Expected name or number', $lineno, $this->parser->getFilename());
            }

            if ($node instanceof Twig_Node_Expression_Name && null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) {
                if (!$arg instanceof Twig_Node_Expression_Constant) {
                    throw new Twig_Error_Syntax(sprintf('Dynamic macro names are not supported (called on "%s")', $node->getAttribute('name')), $token->getLine(), $this->parser->getFilename());
                }

                $node = new Twig_Node_Expression_MethodCall($node, 'get'.$arg->getAttribute('value'), $arguments, $lineno);
                $node->setAttribute('safe', true);

                return $node;
            }
        } else {
            $type = Twig_Template::ARRAY_CALL;

            // slice?
            $slice = false;
            if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ':')) {
                $slice = true;
                $arg = new Twig_Node_Expression_Constant(0, $token->getLine());
            } else {
                $arg = $this->parseExpression();
            }

            if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ':')) {
                $slice = true;
                $stream->next();
            }

            if ($slice) {
                if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) {
                    $length = new Twig_Node_Expression_Constant(null, $token->getLine());
                } else {
                    $length = $this->parseExpression();
                }

                $class = $this->getFilterNodeClass('slice', $token->getLine());
                $arguments = new Twig_Node(array($arg, $length));
                $filter = new $class($node, new Twig_Node_Expression_Constant('slice', $token->getLine()), $arguments, $token->getLine());

                $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']');

                return $filter;
            }

            $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']');
        }

        return new Twig_Node_Expression_GetAttr($node, $arg, $arguments, $type, $lineno);
    }

    public function parseFilterExpression($node)
    {
        $this->parser->getStream()->next();

        return $this->parseFilterExpressionRaw($node);
    }

    public function parseFilterExpressionRaw($node, $tag = null)
    {
        while (true) {
            $token = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE);

            $name = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
            if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
                $arguments = new Twig_Node();
            } else {
                $arguments = $this->parseArguments(true);
            }

            $class = $this->getFilterNodeClass($name->getAttribute('value'), $token->getLine());

            $node = new $class($node, $name, $arguments, $token->getLine(), $tag);

            if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '|')) {
                break;
            }

            $this->parser->getStream()->next();
        }

        return $node;
    }

    /**
     * Parses arguments.
     *
     * @param Boolean $namedArguments Whether to allow named arguments or not
     * @param Boolean $definition     Whether we are parsing arguments for a function definition
     */
    public function parseArguments($namedArguments = false, $definition = false)
    {
        $args = array();
        $stream = $this->parser->getStream();

        $stream->expect(Twig_Token::PUNCTUATION_TYPE, '(', 'A list of arguments must begin with an opening parenthesis');
        while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ')')) {
            if (!empty($args)) {
                $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'Arguments must be separated by a comma');
            }

            if ($definition) {
                $token = $stream->expect(Twig_Token::NAME_TYPE, null, 'An argument must be a name');
                $value = new Twig_Node_Expression_Name($token->getValue(), $this->parser->getCurrentToken()->getLine());
            } else {
                $value = $this->parseExpression();
            }

            $name = null;
            if ($namedArguments && $stream->test(Twig_Token::OPERATOR_TYPE, '=')) {
                $token = $stream->next();
                if (!$value instanceof Twig_Node_Expression_Name) {
                    throw new Twig_Error_Syntax(sprintf('A parameter name must be a string, "%s" given', get_class($value)), $token->getLine(), $this->parser->getFilename());
                }
                $name = $value->getAttribute('name');

                if ($definition) {
                    $value = $this->parsePrimaryExpression();

                    if (!$this->checkConstantExpression($value)) {
                        throw new Twig_Error_Syntax(sprintf('A default value for an argument must be a constant (a boolean, a string, a number, or an array).'), $token->getLine(), $this->parser->getFilename());
                    }
                } else {
                    $value = $this->parseExpression();
                }
            }

            if ($definition) {
                if (null === $name) {
                    $name = $value->getAttribute('name');
                    $value = new Twig_Node_Expression_Constant(null, $this->parser->getCurrentToken()->getLine());
                }
                $args[$name] = $value;
            } else {
                if (null === $name) {
                    $args[] = $value;
                } else {
                    $args[$name] = $value;
                }
            }
        }
        $stream->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'A list of arguments must be closed by a parenthesis');

        return new Twig_Node($args);
    }

    public function parseAssignmentExpression()
    {
        $targets = array();
        while (true) {
            $token = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE, null, 'Only variables can be assigned to');
            if (in_array($token->getValue(), array('true', 'false', 'none'))) {
                throw new Twig_Error_Syntax(sprintf('You cannot assign a value to "%s"', $token->getValue()), $token->getLine(), $this->parser->getFilename());
            }
            $targets[] = new Twig_Node_Expression_AssignName($token->getValue(), $token->getLine());

            if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, ',')) {
                break;
            }
            $this->parser->getStream()->next();
        }

        return new Twig_Node($targets);
    }

    public function parseMultitargetExpression()
    {
        $targets = array();
        while (true) {
            $targets[] = $this->parseExpression();
            if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, ',')) {
                break;
            }
            $this->parser->getStream()->next();
        }

        return new Twig_Node($targets);
    }

    protected function getFunctionNodeClass($name, $line)
    {
        $env = $this->parser->getEnvironment();

        if (false === $function = $env->getFunction($name)) {
            $message = sprintf('The function "%s" does not exist', $name);
            if ($alternatives = $env->computeAlternatives($name, array_keys($env->getFunctions()))) {
                $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
            }

            throw new Twig_Error_Syntax($message, $line, $this->parser->getFilename());
        }

        if ($function instanceof Twig_SimpleFunction) {
            return $function->getNodeClass();
        }

        return $function instanceof Twig_Function_Node ? $function->getClass() : 'Twig_Node_Expression_Function';
    }

    protected function getFilterNodeClass($name, $line)
    {
        $env = $this->parser->getEnvironment();

        if (false === $filter = $env->getFilter($name)) {
            $message = sprintf('The filter "%s" does not exist', $name);
            if ($alternatives = $env->computeAlternatives($name, array_keys($env->getFilters()))) {
                $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
            }

            throw new Twig_Error_Syntax($message, $line, $this->parser->getFilename());
        }

        if ($filter instanceof Twig_SimpleFilter) {
            return $filter->getNodeClass();
        }

        return $filter instanceof Twig_Filter_Node ? $filter->getClass() : 'Twig_Node_Expression_Filter';
    }

    // checks that the node only contains "constant" elements
    protected function checkConstantExpression(Twig_NodeInterface $node)
    {
        if (!($node instanceof Twig_Node_Expression_Constant || $node instanceof Twig_Node_Expression_Array)) {
            return false;
        }

        foreach ($node as $n) {
            if (!$this->checkConstantExpression($n)) {
                return false;
            }
        }

        return true;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Twig_NodeVisitorInterface is the interface the all node visitor classes must implement.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface Twig_NodeVisitorInterface
{
    /**
     * Called before child nodes are visited.
     *
     * @param Twig_NodeInterface $node The node to visit
     * @param Twig_Environment   $env  The Twig environment instance
     *
     * @return Twig_NodeInterface The modified node
     */
    public function enterNode(Twig_NodeInterface $node, Twig_Environment $env);

    /**
     * Called after child nodes are visited.
     *
     * @param Twig_NodeInterface $node The node to visit
     * @param Twig_Environment   $env  The Twig environment instance
     *
     * @return Twig_NodeInterface|false The modified node or false if the node must be removed
     */
    public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env);

    /**
     * Returns the priority for this visitor.
     *
     * Priority should be between -10 and 10 (0 is the default).
     *
     * @return integer The priority level
     */
    public function getPriority();
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 * (c) 2010 Arnaud Le Blanc
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a template function.
 *
 * Use Twig_SimpleFunction instead.
 *
 * @author Arnaud Le Blanc <arnaud.lb@gmail.com>
 * @deprecated since 1.12 (to be removed in 2.0)
 */
interface Twig_FunctionInterface
{
    /**
     * Compiles a function.
     *
     * @return string The PHP code for the function
     */
    public function compile();

    public function needsEnvironment();

    public function needsContext();

    public function getSafe(Twig_Node $filterArgs);

    public function setArguments($arguments);

    public function getArguments();
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Interface implemented by compiler classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @deprecated since 1.12 (to be removed in 2.0)
 */
interface Twig_CompilerInterface
{
    /**
     * Compiles a node.
     *
     * @param Twig_NodeInterface $node The node to compile
     *
     * @return Twig_CompilerInterface The current compiler instance
     */
    public function compile(Twig_NodeInterface $node);

    /**
     * Gets the current PHP code after compilation.
     *
     * @return string The PHP code
     */
    public function getSource();
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Twig_NodeVisitor_Optimizer tries to optimizes the AST.
 *
 * This visitor is always the last registered one.
 *
 * You can configure which optimizations you want to activate via the
 * optimizer mode.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_NodeVisitor_Optimizer implements Twig_NodeVisitorInterface
{
    const OPTIMIZE_ALL         = -1;
    const OPTIMIZE_NONE        = 0;
    const OPTIMIZE_FOR         = 2;
    const OPTIMIZE_RAW_FILTER  = 4;
    const OPTIMIZE_VAR_ACCESS  = 8;

    protected $loops = array();
    protected $optimizers;
    protected $prependedNodes = array();
    protected $inABody = false;

    /**
     * Constructor.
     *
     * @param integer $optimizers The optimizer mode
     */
    public function __construct($optimizers = -1)
    {
        if (!is_int($optimizers) || $optimizers > 2) {
            throw new InvalidArgumentException(sprintf('Optimizer mode "%s" is not valid.', $optimizers));
        }

        $this->optimizers = $optimizers;
    }

    /**
     * {@inheritdoc}
     */
    public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
    {
        if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) {
            $this->enterOptimizeFor($node, $env);
        }

        if (!version_compare(phpversion(), '5.4.0RC1', '>=') && self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('sandbox')) {
            if ($this->inABody) {
                if (!$node instanceof Twig_Node_Expression) {
                    if (get_class($node) !== 'Twig_Node') {
                        array_unshift($this->prependedNodes, array());
                    }
                } else {
                    $node = $this->optimizeVariables($node, $env);
                }
            } elseif ($node instanceof Twig_Node_Body) {
                $this->inABody = true;
            }
        }

        return $node;
    }

    /**
     * {@inheritdoc}
     */
    public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
    {
        $expression = $node instanceof Twig_Node_Expression;

        if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) {
            $this->leaveOptimizeFor($node, $env);
        }

        if (self::OPTIMIZE_RAW_FILTER === (self::OPTIMIZE_RAW_FILTER & $this->optimizers)) {
            $node = $this->optimizeRawFilter($node, $env);
        }

        $node = $this->optimizePrintNode($node, $env);

        if (self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('sandbox')) {
            if ($node instanceof Twig_Node_Body) {
                $this->inABody = false;
            } elseif ($this->inABody) {
                if (!$expression && get_class($node) !== 'Twig_Node' && $prependedNodes = array_shift($this->prependedNodes)) {
                    $nodes = array();
                    foreach (array_unique($prependedNodes) as $name) {
                        $nodes[] = new Twig_Node_SetTemp($name, $node->getLine());
                    }

                    $nodes[] = $node;
                    $node = new Twig_Node($nodes);
                }
            }
        }

        return $node;
    }

    protected function optimizeVariables(Twig_NodeInterface $node, Twig_Environment $env)
    {
        if ('Twig_Node_Expression_Name' === get_class($node) && $node->isSimple()) {
            $this->prependedNodes[0][] = $node->getAttribute('name');

            return new Twig_Node_Expression_TempName($node->getAttribute('name'), $node->getLine());
        }

        return $node;
    }

    /**
     * Optimizes print nodes.
     *
     * It replaces:
     *
     *   * "echo $this->render(Parent)Block()" with "$this->display(Parent)Block()"
     *
     * @param Twig_NodeInterface $node A Node
     * @param Twig_Environment   $env  The current Twig environment
     */
    protected function optimizePrintNode(Twig_NodeInterface $node, Twig_Environment $env)
    {
        if (!$node instanceof Twig_Node_Print) {
            return $node;
        }

        if (
            $node->getNode('expr') instanceof Twig_Node_Expression_BlockReference ||
            $node->getNode('expr') instanceof Twig_Node_Expression_Parent
        ) {
            $node->getNode('expr')->setAttribute('output', true);

            return $node->getNode('expr');
        }

        return $node;
    }

    /**
     * Removes "raw" filters.
     *
     * @param Twig_NodeInterface $node A Node
     * @param Twig_Environment   $env  The current Twig environment
     */
    protected function optimizeRawFilter(Twig_NodeInterface $node, Twig_Environment $env)
    {
        if ($node instanceof Twig_Node_Expression_Filter && 'raw' == $node->getNode('filter')->getAttribute('value')) {
            return $node->getNode('node');
        }

        return $node;
    }

    /**
     * Optimizes "for" tag by removing the "loop" variable creation whenever possible.
     *
     * @param Twig_NodeInterface $node A Node
     * @param Twig_Environment   $env  The current Twig environment
     */
    protected function enterOptimizeFor(Twig_NodeInterface $node, Twig_Environment $env)
    {
        if ($node instanceof Twig_Node_For) {
            // disable the loop variable by default
            $node->setAttribute('with_loop', false);
            array_unshift($this->loops, $node);
        } elseif (!$this->loops) {
            // we are outside a loop
            return;
        }

        // when do we need to add the loop variable back?

        // the loop variable is referenced for the current loop
        elseif ($node instanceof Twig_Node_Expression_Name && 'loop' === $node->getAttribute('name')) {
            $this->addLoopToCurrent();
        }

        // block reference
        elseif ($node instanceof Twig_Node_BlockReference || $node instanceof Twig_Node_Expression_BlockReference) {
            $this->addLoopToCurrent();
        }

        // include without the only attribute
        elseif ($node instanceof Twig_Node_Include && !$node->getAttribute('only')) {
            $this->addLoopToAll();
        }

        // the loop variable is referenced via an attribute
        elseif ($node instanceof Twig_Node_Expression_GetAttr
            && (!$node->getNode('attribute') instanceof Twig_Node_Expression_Constant
                || 'parent' === $node->getNode('attribute')->getAttribute('value')
               )
            && (true === $this->loops[0]->getAttribute('with_loop')
                || ($node->getNode('node') instanceof Twig_Node_Expression_Name
                    && 'loop' === $node->getNode('node')->getAttribute('name')
                   )
               )
        ) {
            $this->addLoopToAll();
        }
    }

    /**
     * Optimizes "for" tag by removing the "loop" variable creation whenever possible.
     *
     * @param Twig_NodeInterface $node A Node
     * @param Twig_Environment   $env  The current Twig environment
     */
    protected function leaveOptimizeFor(Twig_NodeInterface $node, Twig_Environment $env)
    {
        if ($node instanceof Twig_Node_For) {
            array_shift($this->loops);
        }
    }

    protected function addLoopToCurrent()
    {
        $this->loops[0]->setAttribute('with_loop', true);
    }

    protected function addLoopToAll()
    {
        foreach ($this->loops as $loop) {
            $loop->setAttribute('with_loop', true);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function getPriority()
    {
        return 255;
    }
}
<?php

class Twig_NodeVisitor_SafeAnalysis implements Twig_NodeVisitorInterface
{
    protected $data = array();
    protected $safeVars = array();

    public function setSafeVars($safeVars)
    {
        $this->safeVars = $safeVars;
    }

    public function getSafe(Twig_NodeInterface $node)
    {
        $hash = spl_object_hash($node);
        if (!isset($this->data[$hash])) {
            return;
        }

        foreach ($this->data[$hash] as $bucket) {
            if ($bucket['key'] !== $node) {
                continue;
            }

            if (in_array('html_attr', $bucket['value'])) {
                $bucket['value'][] = 'html';
            }

            return $bucket['value'];
        }
    }

    protected function setSafe(Twig_NodeInterface $node, array $safe)
    {
        $hash = spl_object_hash($node);
        if (isset($this->data[$hash])) {
            foreach ($this->data[$hash] as &$bucket) {
                if ($bucket['key'] === $node) {
                    $bucket['value'] = $safe;

                    return;
                }
            }
        }
        $this->data[$hash][] = array(
            'key' => $node,
            'value' => $safe,
        );
    }

    public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
    {
        return $node;
    }

    public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
    {
        if ($node instanceof Twig_Node_Expression_Constant) {
            // constants are marked safe for all
            $this->setSafe($node, array('all'));
        } elseif ($node instanceof Twig_Node_Expression_BlockReference) {
            // blocks are safe by definition
            $this->setSafe($node, array('all'));
        } elseif ($node instanceof Twig_Node_Expression_Parent) {
            // parent block is safe by definition
            $this->setSafe($node, array('all'));
        } elseif ($node instanceof Twig_Node_Expression_Conditional) {
            // intersect safeness of both operands
            $safe = $this->intersectSafe($this->getSafe($node->getNode('expr2')), $this->getSafe($node->getNode('expr3')));
            $this->setSafe($node, $safe);
        } elseif ($node instanceof Twig_Node_Expression_Filter) {
            // filter expression is safe when the filter is safe
            $name = $node->getNode('filter')->getAttribute('value');
            $args = $node->getNode('arguments');
            if (false !== $filter = $env->getFilter($name)) {
                $safe = $filter->getSafe($args);
                if (null === $safe) {
                    $safe = $this->intersectSafe($this->getSafe($node->getNode('node')), $filter->getPreservesSafety());
                }
                $this->setSafe($node, $safe);
            } else {
                $this->setSafe($node, array());
            }
        } elseif ($node instanceof Twig_Node_Expression_Function) {
            // function expression is safe when the function is safe
            $name = $node->getAttribute('name');
            $args = $node->getNode('arguments');
            $function = $env->getFunction($name);
            if (false !== $function) {
                $this->setSafe($node, $function->getSafe($args));
            } else {
                $this->setSafe($node, array());
            }
        } elseif ($node instanceof Twig_Node_Expression_MethodCall) {
            if ($node->getAttribute('safe')) {
                $this->setSafe($node, array('all'));
            } else {
                $this->setSafe($node, array());
            }
        } elseif ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name) {
            $name = $node->getNode('node')->getAttribute('name');
            // attributes on template instances are safe
            if ('_self' == $name || in_array($name, $this->safeVars)) {
                $this->setSafe($node, array('all'));
            } else {
                $this->setSafe($node, array());
            }
        } else {
            $this->setSafe($node, array());
        }

        return $node;
    }

    protected function intersectSafe(array $a = null, array $b = null)
    {
        if (null === $a || null === $b) {
            return array();
        }

        if (in_array('all', $a)) {
            return $b;
        }

        if (in_array('all', $b)) {
            return $a;
        }

        return array_intersect($a, $b);
    }

    /**
     * {@inheritdoc}
     */
    public function getPriority()
    {
        return 0;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Twig_NodeVisitor_Escaper implements output escaping.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_NodeVisitor_Escaper implements Twig_NodeVisitorInterface
{
    protected $statusStack = array();
    protected $blocks = array();
    protected $safeAnalysis;
    protected $traverser;
    protected $defaultStrategy = false;
    protected $safeVars = array();

    public function __construct()
    {
        $this->safeAnalysis = new Twig_NodeVisitor_SafeAnalysis();
    }

    /**
     * Called before child nodes are visited.
     *
     * @param Twig_NodeInterface $node The node to visit
     * @param Twig_Environment   $env  The Twig environment instance
     *
     * @return Twig_NodeInterface The modified node
     */
    public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
    {
        if ($node instanceof Twig_Node_Module) {
            if ($env->hasExtension('escaper') && $defaultStrategy = $env->getExtension('escaper')->getDefaultStrategy($node->getAttribute('filename'))) {
                $this->defaultStrategy = $defaultStrategy;
            }
            $this->safeVars = array();
        } elseif ($node instanceof Twig_Node_AutoEscape) {
            $this->statusStack[] = $node->getAttribute('value');
        } elseif ($node instanceof Twig_Node_Block) {
            $this->statusStack[] = isset($this->blocks[$node->getAttribute('name')]) ? $this->blocks[$node->getAttribute('name')] : $this->needEscaping($env);
        } elseif ($node instanceof Twig_Node_Import) {
            $this->safeVars[] = $node->getNode('var')->getAttribute('name');
        }

        return $node;
    }

    /**
     * Called after child nodes are visited.
     *
     * @param Twig_NodeInterface $node The node to visit
     * @param Twig_Environment   $env  The Twig environment instance
     *
     * @return Twig_NodeInterface The modified node
     */
    public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
    {
        if ($node instanceof Twig_Node_Module) {
            $this->defaultStrategy = false;
            $this->safeVars = array();
        } elseif ($node instanceof Twig_Node_Expression_Filter) {
            return $this->preEscapeFilterNode($node, $env);
        } elseif ($node instanceof Twig_Node_Print) {
            return $this->escapePrintNode($node, $env, $this->needEscaping($env));
        }

        if ($node instanceof Twig_Node_AutoEscape || $node instanceof Twig_Node_Block) {
            array_pop($this->statusStack);
        } elseif ($node instanceof Twig_Node_BlockReference) {
            $this->blocks[$node->getAttribute('name')] = $this->needEscaping($env);
        }

        return $node;
    }

    protected function escapePrintNode(Twig_Node_Print $node, Twig_Environment $env, $type)
    {
        if (false === $type) {
            return $node;
        }

        $expression = $node->getNode('expr');

        if ($this->isSafeFor($type, $expression, $env)) {
            return $node;
        }

        $class = get_class($node);

        return new $class(
            $this->getEscaperFilter($type, $expression),
            $node->getLine()
        );
    }

    protected function preEscapeFilterNode(Twig_Node_Expression_Filter $filter, Twig_Environment $env)
    {
        $name = $filter->getNode('filter')->getAttribute('value');

        $type = $env->getFilter($name)->getPreEscape();
        if (null === $type) {
            return $filter;
        }

        $node = $filter->getNode('node');
        if ($this->isSafeFor($type, $node, $env)) {
            return $filter;
        }

        $filter->setNode('node', $this->getEscaperFilter($type, $node));

        return $filter;
    }

    protected function isSafeFor($type, Twig_NodeInterface $expression, $env)
    {
        $safe = $this->safeAnalysis->getSafe($expression);

        if (null === $safe) {
            if (null === $this->traverser) {
                $this->traverser = new Twig_NodeTraverser($env, array($this->safeAnalysis));
            }

            $this->safeAnalysis->setSafeVars($this->safeVars);

            $this->traverser->traverse($expression);
            $safe = $this->safeAnalysis->getSafe($expression);
        }

        return in_array($type, $safe) || in_array('all', $safe);
    }

    protected function needEscaping(Twig_Environment $env)
    {
        if (count($this->statusStack)) {
            return $this->statusStack[count($this->statusStack) - 1];
        }

        return $this->defaultStrategy ? $this->defaultStrategy : false;
    }

    protected function getEscaperFilter($type, Twig_NodeInterface $node)
    {
        $line = $node->getLine();
        $name = new Twig_Node_Expression_Constant('escape', $line);
        $args = new Twig_Node(array(new Twig_Node_Expression_Constant((string) $type, $line), new Twig_Node_Expression_Constant(null, $line), new Twig_Node_Expression_Constant(true, $line)));

        return new Twig_Node_Expression_Filter($node, $name, $args, $line);
    }

    /**
     * {@inheritdoc}
     */
    public function getPriority()
    {
        return 0;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Twig_NodeVisitor_Sandbox implements sandboxing.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_NodeVisitor_Sandbox implements Twig_NodeVisitorInterface
{
    protected $inAModule = false;
    protected $tags;
    protected $filters;
    protected $functions;

    /**
     * Called before child nodes are visited.
     *
     * @param Twig_NodeInterface $node The node to visit
     * @param Twig_Environment   $env  The Twig environment instance
     *
     * @return Twig_NodeInterface The modified node
     */
    public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
    {
        if ($node instanceof Twig_Node_Module) {
            $this->inAModule = true;
            $this->tags = array();
            $this->filters = array();
            $this->functions = array();

            return $node;
        } elseif ($this->inAModule) {
            // look for tags
            if ($node->getNodeTag()) {
                $this->tags[] = $node->getNodeTag();
            }

            // look for filters
            if ($node instanceof Twig_Node_Expression_Filter) {
                $this->filters[] = $node->getNode('filter')->getAttribute('value');
            }

            // look for functions
            if ($node instanceof Twig_Node_Expression_Function) {
                $this->functions[] = $node->getAttribute('name');
            }

            // wrap print to check __toString() calls
            if ($node instanceof Twig_Node_Print) {
                return new Twig_Node_SandboxedPrint($node->getNode('expr'), $node->getLine(), $node->getNodeTag());
            }
        }

        return $node;
    }

    /**
     * Called after child nodes are visited.
     *
     * @param Twig_NodeInterface $node The node to visit
     * @param Twig_Environment   $env  The Twig environment instance
     *
     * @return Twig_NodeInterface The modified node
     */
    public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
    {
        if ($node instanceof Twig_Node_Module) {
            $this->inAModule = false;

            return new Twig_Node_SandboxedModule($node, array_unique($this->filters), array_unique($this->tags), array_unique($this->functions));
        }

        return $node;
    }

    /**
     * {@inheritdoc}
     */
    public function getPriority()
    {
        return 0;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2011 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a template filter as a node.
 *
 * Use Twig_SimpleFilter instead.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @deprecated since 1.12 (to be removed in 2.0)
 */
class Twig_Filter_Node extends Twig_Filter
{
    protected $class;

    public function __construct($class, array $options = array())
    {
        parent::__construct($options);

        $this->class = $class;
    }

    public function getClass()
    {
        return $this->class;
    }

    public function compile()
    {
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a function template filter.
 *
 * Use Twig_SimpleFilter instead.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @deprecated since 1.12 (to be removed in 2.0)
 */
class Twig_Filter_Function extends Twig_Filter
{
    protected $function;

    public function __construct($function, array $options = array())
    {
        $options['callable'] = $function;

        parent::__construct($options);

        $this->function = $function;
    }

    public function compile()
    {
        return $this->function;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a method template filter.
 *
 * Use Twig_SimpleFilter instead.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @deprecated since 1.12 (to be removed in 2.0)
 */
class Twig_Filter_Method extends Twig_Filter
{
    protected $extension;
    protected $method;

    public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array())
    {
        $options['callable'] = array($extension, $method);

        parent::__construct($options);

        $this->extension = $extension;
        $this->method = $method;
    }

    public function compile()
    {
        return sprintf('$this->env->getExtension(\'%s\')->%s', $this->extension->getName(), $this->method);
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a Token.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Token
{
    protected $value;
    protected $type;
    protected $lineno;

    const EOF_TYPE                  = -1;
    const TEXT_TYPE                 = 0;
    const BLOCK_START_TYPE          = 1;
    const VAR_START_TYPE            = 2;
    const BLOCK_END_TYPE            = 3;
    const VAR_END_TYPE              = 4;
    const NAME_TYPE                 = 5;
    const NUMBER_TYPE               = 6;
    const STRING_TYPE               = 7;
    const OPERATOR_TYPE             = 8;
    const PUNCTUATION_TYPE          = 9;
    const INTERPOLATION_START_TYPE  = 10;
    const INTERPOLATION_END_TYPE    = 11;

    /**
     * Constructor.
     *
     * @param integer $type   The type of the token
     * @param string  $value  The token value
     * @param integer $lineno The line position in the source
     */
    public function __construct($type, $value, $lineno)
    {
        $this->type   = $type;
        $this->value  = $value;
        $this->lineno = $lineno;
    }

    /**
     * Returns a string representation of the token.
     *
     * @return string A string representation of the token
     */
    public function __toString()
    {
        return sprintf('%s(%s)', self::typeToString($this->type, true, $this->lineno), $this->value);
    }

    /**
     * Tests the current token for a type and/or a value.
     *
     * Parameters may be:
     * * just type
     * * type and value (or array of possible values)
     * * just value (or array of possible values) (NAME_TYPE is used as type)
     *
     * @param array|integer     $type   The type to test
     * @param array|string|null $values The token value
     *
     * @return Boolean
     */
    public function test($type, $values = null)
    {
        if (null === $values && !is_int($type)) {
            $values = $type;
            $type = self::NAME_TYPE;
        }

        return ($this->type === $type) && (
            null === $values ||
            (is_array($values) && in_array($this->value, $values)) ||
            $this->value == $values
        );
    }

    /**
     * Gets the line.
     *
     * @return integer The source line
     */
    public function getLine()
    {
        return $this->lineno;
    }

    /**
     * Gets the token type.
     *
     * @return integer The token type
     */
    public function getType()
    {
        return $this->type;
    }

    /**
     * Gets the token value.
     *
     * @return string The token value
     */
    public function getValue()
    {
        return $this->value;
    }

    /**
     * Returns the constant representation (internal) of a given type.
     *
     * @param integer $type  The type as an integer
     * @param Boolean $short Whether to return a short representation or not
     *
     * @return string The string representation
     */
    public static function typeToString($type, $short = false)
    {
        switch ($type) {
            case self::EOF_TYPE:
                $name = 'EOF_TYPE';
                break;
            case self::TEXT_TYPE:
                $name = 'TEXT_TYPE';
                break;
            case self::BLOCK_START_TYPE:
                $name = 'BLOCK_START_TYPE';
                break;
            case self::VAR_START_TYPE:
                $name = 'VAR_START_TYPE';
                break;
            case self::BLOCK_END_TYPE:
                $name = 'BLOCK_END_TYPE';
                break;
            case self::VAR_END_TYPE:
                $name = 'VAR_END_TYPE';
                break;
            case self::NAME_TYPE:
                $name = 'NAME_TYPE';
                break;
            case self::NUMBER_TYPE:
                $name = 'NUMBER_TYPE';
                break;
            case self::STRING_TYPE:
                $name = 'STRING_TYPE';
                break;
            case self::OPERATOR_TYPE:
                $name = 'OPERATOR_TYPE';
                break;
            case self::PUNCTUATION_TYPE:
                $name = 'PUNCTUATION_TYPE';
                break;
            case self::INTERPOLATION_START_TYPE:
                $name = 'INTERPOLATION_START_TYPE';
                break;
            case self::INTERPOLATION_END_TYPE:
                $name = 'INTERPOLATION_END_TYPE';
                break;
            default:
                throw new LogicException(sprintf('Token of type "%s" does not exist.', $type));
        }

        return $short ? $name : 'Twig_Token::'.$name;
    }

    /**
     * Returns the english representation of a given type.
     *
     * @param integer $type The type as an integer
     *
     * @return string The string representation
     */
    public static function typeToEnglish($type)
    {
        switch ($type) {
            case self::EOF_TYPE:
                return 'end of template';
            case self::TEXT_TYPE:
                return 'text';
            case self::BLOCK_START_TYPE:
                return 'begin of statement block';
            case self::VAR_START_TYPE:
                return 'begin of print statement';
            case self::BLOCK_END_TYPE:
                return 'end of statement block';
            case self::VAR_END_TYPE:
                return 'end of print statement';
            case self::NAME_TYPE:
                return 'name';
            case self::NUMBER_TYPE:
                return 'number';
            case self::STRING_TYPE:
                return 'string';
            case self::OPERATOR_TYPE:
                return 'operator';
            case self::PUNCTUATION_TYPE:
                return 'punctuation';
            case self::INTERPOLATION_START_TYPE:
                return 'begin of string interpolation';
            case self::INTERPOLATION_END_TYPE:
                return 'end of string interpolation';
            default:
                throw new LogicException(sprintf('Token of type "%s" does not exist.', $type));
        }
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 * (c) 2010 Arnaud Le Blanc
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Default implementation of a token parser broker.
 *
 * @author Arnaud Le Blanc <arnaud.lb@gmail.com>
 * @deprecated since 1.12 (to be removed in 2.0)
 */
class Twig_TokenParserBroker implements Twig_TokenParserBrokerInterface
{
    protected $parser;
    protected $parsers = array();
    protected $brokers = array();

    /**
     * Constructor.
     *
     * @param array|Traversable $parsers A Traversable of Twig_TokenParserInterface instances
     * @param array|Traversable $brokers A Traversable of Twig_TokenParserBrokerInterface instances
     */
    public function __construct($parsers = array(), $brokers = array())
    {
        foreach ($parsers as $parser) {
            if (!$parser instanceof Twig_TokenParserInterface) {
                throw new LogicException('$parsers must a an array of Twig_TokenParserInterface');
            }
            $this->parsers[$parser->getTag()] = $parser;
        }
        foreach ($brokers as $broker) {
            if (!$broker instanceof Twig_TokenParserBrokerInterface) {
                throw new LogicException('$brokers must a an array of Twig_TokenParserBrokerInterface');
            }
            $this->brokers[] = $broker;
        }
    }

    /**
     * Adds a TokenParser.
     *
     * @param Twig_TokenParserInterface $parser A Twig_TokenParserInterface instance
     */
    public function addTokenParser(Twig_TokenParserInterface $parser)
    {
        $this->parsers[$parser->getTag()] = $parser;
    }

    /**
     * Removes a TokenParser.
     *
     * @param Twig_TokenParserInterface $parser A Twig_TokenParserInterface instance
     */
    public function removeTokenParser(Twig_TokenParserInterface $parser)
    {
        $name = $parser->getTag();
        if (isset($this->parsers[$name]) && $parser === $this->parsers[$name]) {
            unset($this->parsers[$name]);
        }
    }

    /**
     * Adds a TokenParserBroker.
     *
     * @param Twig_TokenParserBroker $broker A Twig_TokenParserBroker instance
     */
    public function addTokenParserBroker(Twig_TokenParserBroker $broker)
    {
        $this->brokers[] = $broker;
    }

    /**
     * Removes a TokenParserBroker.
     *
     * @param Twig_TokenParserBroker $broker A Twig_TokenParserBroker instance
     */
    public function removeTokenParserBroker(Twig_TokenParserBroker $broker)
    {
        if (false !== $pos = array_search($broker, $this->brokers)) {
            unset($this->brokers[$pos]);
        }
    }

    /**
     * Gets a suitable TokenParser for a tag.
     *
     * First looks in parsers, then in brokers.
     *
     * @param string $tag A tag name
     *
     * @return null|Twig_TokenParserInterface A Twig_TokenParserInterface or null if no suitable TokenParser was found
     */
    public function getTokenParser($tag)
    {
        if (isset($this->parsers[$tag])) {
            return $this->parsers[$tag];
        }
        $broker = end($this->brokers);
        while (false !== $broker) {
            $parser = $broker->getTokenParser($tag);
            if (null !== $parser) {
                return $parser;
            }
            $broker = prev($this->brokers);
        }
    }

    public function getParsers()
    {
        return $this->parsers;
    }

    public function getParser()
    {
        return $this->parser;
    }

    public function setParser(Twig_ParserInterface $parser)
    {
        $this->parser = $parser;
        foreach ($this->parsers as $tokenParser) {
            $tokenParser->setParser($parser);
        }
        foreach ($this->brokers as $broker) {
            $broker->setParser($parser);
        }
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a security policy which need to be enforced when sandbox mode is enabled.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Sandbox_SecurityPolicy implements Twig_Sandbox_SecurityPolicyInterface
{
    protected $allowedTags;
    protected $allowedFilters;
    protected $allowedMethods;
    protected $allowedProperties;
    protected $allowedFunctions;

    public function __construct(array $allowedTags = array(), array $allowedFilters = array(), array $allowedMethods = array(), array $allowedProperties = array(), array $allowedFunctions = array())
    {
        $this->allowedTags = $allowedTags;
        $this->allowedFilters = $allowedFilters;
        $this->setAllowedMethods($allowedMethods);
        $this->allowedProperties = $allowedProperties;
        $this->allowedFunctions = $allowedFunctions;
    }

    public function setAllowedTags(array $tags)
    {
        $this->allowedTags = $tags;
    }

    public function setAllowedFilters(array $filters)
    {
        $this->allowedFilters = $filters;
    }

    public function setAllowedMethods(array $methods)
    {
        $this->allowedMethods = array();
        foreach ($methods as $class => $m) {
            $this->allowedMethods[$class] = array_map('strtolower', is_array($m) ? $m : array($m));
        }
    }

    public function setAllowedProperties(array $properties)
    {
        $this->allowedProperties = $properties;
    }

    public function setAllowedFunctions(array $functions)
    {
        $this->allowedFunctions = $functions;
    }

    public function checkSecurity($tags, $filters, $functions)
    {
        foreach ($tags as $tag) {
            if (!in_array($tag, $this->allowedTags)) {
                throw new Twig_Sandbox_SecurityError(sprintf('Tag "%s" is not allowed.', $tag));
            }
        }

        foreach ($filters as $filter) {
            if (!in_array($filter, $this->allowedFilters)) {
                throw new Twig_Sandbox_SecurityError(sprintf('Filter "%s" is not allowed.', $filter));
            }
        }

        foreach ($functions as $function) {
            if (!in_array($function, $this->allowedFunctions)) {
                throw new Twig_Sandbox_SecurityError(sprintf('Function "%s" is not allowed.', $function));
            }
        }
    }

    public function checkMethodAllowed($obj, $method)
    {
        if ($obj instanceof Twig_TemplateInterface || $obj instanceof Twig_Markup) {
            return true;
        }

        $allowed = false;
        $method = strtolower($method);
        foreach ($this->allowedMethods as $class => $methods) {
            if ($obj instanceof $class) {
                $allowed = in_array($method, $methods);

                break;
            }
        }

        if (!$allowed) {
            throw new Twig_Sandbox_SecurityError(sprintf('Calling "%s" method on a "%s" object is not allowed.', $method, get_class($obj)));
        }
    }

    public function checkPropertyAllowed($obj, $property)
    {
        $allowed = false;
        foreach ($this->allowedProperties as $class => $properties) {
            if ($obj instanceof $class) {
                $allowed = in_array($property, is_array($properties) ? $properties : array($properties));

                break;
            }
        }

        if (!$allowed) {
            throw new Twig_Sandbox_SecurityError(sprintf('Calling "%s" property on a "%s" object is not allowed.', $property, get_class($obj)));
        }
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Interfaces that all security policy classes must implements.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface Twig_Sandbox_SecurityPolicyInterface
{
    public function checkSecurity($tags, $filters, $functions);

    public function checkMethodAllowed($obj, $method);

    public function checkPropertyAllowed($obj, $method);
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Exception thrown when a security error occurs at runtime.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Sandbox_SecurityError extends Twig_Error
{
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a template test as a Node.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @deprecated since 1.12 (to be removed in 2.0)
 */
class Twig_Test_Node extends Twig_Test
{
    protected $class;

    public function __construct($class, array $options = array())
    {
        parent::__construct($options);

        $this->class = $class;
    }

    public function getClass()
    {
        return $this->class;
    }

    public function compile()
    {
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Integration test helper
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Karma Dordrak <drak@zikula.org>
 */
abstract class Twig_Test_IntegrationTestCase extends PHPUnit_Framework_TestCase
{
    abstract protected function getExtensions();
    abstract protected function getFixturesDir();

    /**
     * @dataProvider getTests
     */
    public function testIntegration($file, $message, $condition, $templates, $exception, $outputs)
    {
        $this->doIntegrationTest($file, $message, $condition, $templates, $exception, $outputs);
    }

    public function getTests()
    {
        $fixturesDir = realpath($this->getFixturesDir());
        $tests = array();

        foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($fixturesDir), RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
            if (!preg_match('/\.test$/', $file)) {
                continue;
            }

            $test = file_get_contents($file->getRealpath());

            if (preg_match('/
                    --TEST--\s*(.*?)\s*(?:--CONDITION--\s*(.*))?\s*((?:--TEMPLATE(?:\(.*?\))?--(?:.*?))+)\s*(?:--DATA--\s*(.*))?\s*--EXCEPTION--\s*(.*)/sx', $test, $match)) {
                $message = $match[1];
                $condition = $match[2];
                $templates = $this->parseTemplates($match[3]);
                $exception = $match[5];
                $outputs = array(array(null, $match[4], null, ''));
            } elseif (preg_match('/--TEST--\s*(.*?)\s*(?:--CONDITION--\s*(.*))?\s*((?:--TEMPLATE(?:\(.*?\))?--(?:.*?))+)--DATA--.*?--EXPECT--.*/s', $test, $match)) {
                $message = $match[1];
                $condition = $match[2];
                $templates = $this->parseTemplates($match[3]);
                $exception = false;
                preg_match_all('/--DATA--(.*?)(?:--CONFIG--(.*?))?--EXPECT--(.*?)(?=\-\-DATA\-\-|$)/s', $test, $outputs, PREG_SET_ORDER);
            } else {
                throw new InvalidArgumentException(sprintf('Test "%s" is not valid.', str_replace($fixturesDir.'/', '', $file)));
            }

            $tests[] = array(str_replace($fixturesDir.'/', '', $file), $message, $condition, $templates, $exception, $outputs);
        }

        return $tests;
    }

    protected function doIntegrationTest($file, $message, $condition, $templates, $exception, $outputs)
    {
        if ($condition) {
            eval('$ret = '.$condition.';');
            if (!$ret) {
                $this->markTestSkipped($condition);
            }
        }

        $loader = new Twig_Loader_Array($templates);

        foreach ($outputs as $match) {
            $config = array_merge(array(
                'cache' => false,
                'strict_variables' => true,
            ), $match[2] ? eval($match[2].';') : array());
            $twig = new Twig_Environment($loader, $config);
            $twig->addGlobal('global', 'global');
            foreach ($this->getExtensions() as $extension) {
                $twig->addExtension($extension);
            }

            try {
                $template = $twig->loadTemplate('index.twig');
            } catch (Exception $e) {
                if (false !== $exception) {
                    $this->assertEquals(trim($exception), trim(sprintf('%s: %s', get_class($e), $e->getMessage())));

                    return;
                }

                if ($e instanceof Twig_Error_Syntax) {
                    $e->setTemplateFile($file);

                    throw $e;
                }

                throw new Twig_Error(sprintf('%s: %s', get_class($e), $e->getMessage()), -1, $file, $e);
            }

            try {
                $output = trim($template->render(eval($match[1].';')), "\n ");
            } catch (Exception $e) {
                if (false !== $exception) {
                    $this->assertEquals(trim($exception), trim(sprintf('%s: %s', get_class($e), $e->getMessage())));

                    return;
                }

                if ($e instanceof Twig_Error_Syntax) {
                    $e->setTemplateFile($file);
                } else {
                    $e = new Twig_Error(sprintf('%s: %s', get_class($e), $e->getMessage()), -1, $file, $e);
                }

                $output = trim(sprintf('%s: %s', get_class($e), $e->getMessage()));
            }

            if (false !== $exception) {
                list($class, ) = explode(':', $exception);
                $this->assertThat(NULL, new PHPUnit_Framework_Constraint_Exception($class));
            }

            $expected = trim($match[3], "\n ");

            if ($expected != $output) {
                echo 'Compiled template that failed:';

                foreach (array_keys($templates) as $name) {
                    echo "Template: $name\n";
                    $source = $loader->getSource($name);
                    echo $twig->compile($twig->parse($twig->tokenize($source, $name)));
                }
            }
            $this->assertEquals($expected, $output, $message.' (in '.$file.')');
        }
    }

    protected static function parseTemplates($test)
    {
        $templates = array();
        preg_match_all('/--TEMPLATE(?:\((.*?)\))?--(.*?)(?=\-\-TEMPLATE|$)/s', $test, $matches, PREG_SET_ORDER);
        foreach ($matches as $match) {
            $templates[($match[1] ? $match[1] : 'index.twig')] = $match[2];
        }

        return $templates;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a function template test.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @deprecated since 1.12 (to be removed in 2.0)
 */
class Twig_Test_Function extends Twig_Test
{
    protected $function;

    public function __construct($function, array $options = array())
    {
        $options['callable'] = $function;

        parent::__construct($options);

        $this->function = $function;
    }

    public function compile()
    {
        return $this->function;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a method template test.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @deprecated since 1.12 (to be removed in 2.0)
 */
class Twig_Test_Method extends Twig_Test
{
    protected $extension;
    protected $method;

    public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array())
    {
        $options['callable'] = array($extension, $method);

        parent::__construct($options);

        $this->extension = $extension;
        $this->method = $method;
    }

    public function compile()
    {
        return sprintf('$this->env->getExtension(\'%s\')->%s', $this->extension->getName(), $this->method);
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
abstract class Twig_Test_NodeTestCase extends PHPUnit_Framework_TestCase
{
    abstract public function getTests();

    /**
     * @dataProvider getTests
     */
    public function testCompile($node, $source, $environment = null)
    {
        $this->assertNodeCompilation($source, $node, $environment);
    }

    public function assertNodeCompilation($source, Twig_Node $node, Twig_Environment $environment = null)
    {
        $compiler = $this->getCompiler($environment);
        $compiler->compile($node);

        $this->assertEquals($source, trim($compiler->getSource()));
    }

    protected function getCompiler(Twig_Environment $environment = null)
    {
        return new Twig_Compiler(null === $environment ? $this->getEnvironment() : $environment);
    }

    protected function getEnvironment()
    {
        return new Twig_Environment();
    }

    protected function getVariableGetter($name)
    {
        if (version_compare(phpversion(), '5.4.0RC1', '>=')) {
            return sprintf('(isset($context["%s"]) ? $context["%s"] : null)', $name, $name);
        }

        return sprintf('$this->getContext($context, "%s")', $name);
    }

    protected function getAttributeGetter()
    {
        if (function_exists('twig_template_get_attributes')) {
            return 'twig_template_get_attributes($this, ';
        }

        return '$this->getAttribute(';
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a node in the AST.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @deprecated since 1.12 (to be removed in 2.0)
 */
interface Twig_NodeInterface extends Countable, IteratorAggregate
{
    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler);

    public function getLine();

    public function getNodeTag();
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
abstract class Twig_Extension implements Twig_ExtensionInterface
{
    /**
     * Initializes the runtime environment.
     *
     * This is where you can load some file that contains filter functions for instance.
     *
     * @param Twig_Environment $environment The current Twig_Environment instance
     */
    public function initRuntime(Twig_Environment $environment)
    {
    }

    /**
     * Returns the token parser instances to add to the existing list.
     *
     * @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
     */
    public function getTokenParsers()
    {
        return array();
    }

    /**
     * Returns the node visitor instances to add to the existing list.
     *
     * @return array An array of Twig_NodeVisitorInterface instances
     */
    public function getNodeVisitors()
    {
        return array();
    }

    /**
     * Returns a list of filters to add to the existing list.
     *
     * @return array An array of filters
     */
    public function getFilters()
    {
        return array();
    }

    /**
     * Returns a list of tests to add to the existing list.
     *
     * @return array An array of tests
     */
    public function getTests()
    {
        return array();
    }

    /**
     * Returns a list of functions to add to the existing list.
     *
     * @return array An array of functions
     */
    public function getFunctions()
    {
        return array();
    }

    /**
     * Returns a list of operators to add to the existing list.
     *
     * @return array An array of operators
     */
    public function getOperators()
    {
        return array();
    }

    /**
     * Returns a list of global variables to add to the existing list.
     *
     * @return array An array of global variables
     */
    public function getGlobals()
    {
        return array();
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a template function.
 *
 * Use Twig_SimpleFunction instead.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @deprecated since 1.12 (to be removed in 2.0)
 */
abstract class Twig_Function implements Twig_FunctionInterface, Twig_FunctionCallableInterface
{
    protected $options;
    protected $arguments = array();

    public function __construct(array $options = array())
    {
        $this->options = array_merge(array(
            'needs_environment' => false,
            'needs_context'     => false,
            'callable'          => null,
        ), $options);
    }

    public function setArguments($arguments)
    {
        $this->arguments = $arguments;
    }

    public function getArguments()
    {
        return $this->arguments;
    }

    public function needsEnvironment()
    {
        return $this->options['needs_environment'];
    }

    public function needsContext()
    {
        return $this->options['needs_context'];
    }

    public function getSafe(Twig_Node $functionArgs)
    {
        if (isset($this->options['is_safe'])) {
            return $this->options['is_safe'];
        }

        if (isset($this->options['is_safe_callback'])) {
            return call_user_func($this->options['is_safe_callback'], $functionArgs);
        }

        return array();
    }

    public function getCallable()
    {
        return $this->options['callable'];
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a displayable node in the AST.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface Twig_NodeOutputInterface
{
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Interface implemented by token parsers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface Twig_TokenParserInterface
{
    /**
     * Sets the parser associated with this token parser
     *
     * @param $parser A Twig_Parser instance
     */
    public function setParser(Twig_Parser $parser);

    /**
     * Parses a token and returns a node.
     *
     * @param Twig_Token $token A Twig_Token instance
     *
     * @return Twig_NodeInterface A Twig_NodeInterface instance
     *
     * @throws Twig_Error_Syntax
     */
    public function parse(Twig_Token $token);

    /**
     * Gets the tag name associated with this token parser.
     *
     * @return string The tag name
     */
    public function getTag();
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a template filter.
 *
 * Use Twig_SimpleFilter instead.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @deprecated since 1.12 (to be removed in 2.0)
 */
abstract class Twig_Filter implements Twig_FilterInterface, Twig_FilterCallableInterface
{
    protected $options;
    protected $arguments = array();

    public function __construct(array $options = array())
    {
        $this->options = array_merge(array(
            'needs_environment' => false,
            'needs_context'     => false,
            'pre_escape'        => null,
            'preserves_safety'  => null,
            'callable'          => null,
        ), $options);
    }

    public function setArguments($arguments)
    {
        $this->arguments = $arguments;
    }

    public function getArguments()
    {
        return $this->arguments;
    }

    public function needsEnvironment()
    {
        return $this->options['needs_environment'];
    }

    public function needsContext()
    {
        return $this->options['needs_context'];
    }

    public function getSafe(Twig_Node $filterArgs)
    {
        if (isset($this->options['is_safe'])) {
            return $this->options['is_safe'];
        }

        if (isset($this->options['is_safe_callback'])) {
            return call_user_func($this->options['is_safe_callback'], $filterArgs);
        }
    }

    public function getPreservesSafety()
    {
        return $this->options['preserves_safety'];
    }

    public function getPreEscape()
    {
        return $this->options['pre_escape'];
    }

    public function getCallable()
    {
        return $this->options['callable'];
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a token stream.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_TokenStream
{
    protected $tokens;
    protected $current;
    protected $filename;

    /**
     * Constructor.
     *
     * @param array  $tokens   An array of tokens
     * @param string $filename The name of the filename which tokens are associated with
     */
    public function __construct(array $tokens, $filename = null)
    {
        $this->tokens     = $tokens;
        $this->current    = 0;
        $this->filename   = $filename;
    }

    /**
     * Returns a string representation of the token stream.
     *
     * @return string
     */
    public function __toString()
    {
        return implode("\n", $this->tokens);
    }

    public function injectTokens(array $tokens)
    {
        $this->tokens = array_merge(array_slice($this->tokens, 0, $this->current), $tokens, array_slice($this->tokens, $this->current));
    }

    /**
     * Sets the pointer to the next token and returns the old one.
     *
     * @return Twig_Token
     */
    public function next()
    {
        if (!isset($this->tokens[++$this->current])) {
            throw new Twig_Error_Syntax('Unexpected end of template', $this->tokens[$this->current - 1]->getLine(), $this->filename);
        }

        return $this->tokens[$this->current - 1];
    }

    /**
     * Tests a token and returns it or throws a syntax error.
     *
     * @return Twig_Token
     */
    public function expect($type, $value = null, $message = null)
    {
        $token = $this->tokens[$this->current];
        if (!$token->test($type, $value)) {
            $line = $token->getLine();
            throw new Twig_Error_Syntax(sprintf('%sUnexpected token "%s" of value "%s" ("%s" expected%s)',
                $message ? $message.'. ' : '',
                Twig_Token::typeToEnglish($token->getType(), $line), $token->getValue(),
                Twig_Token::typeToEnglish($type, $line), $value ? sprintf(' with value "%s"', $value) : ''),
                $line,
                $this->filename
            );
        }
        $this->next();

        return $token;
    }

    /**
     * Looks at the next token.
     *
     * @param integer $number
     *
     * @return Twig_Token
     */
    public function look($number = 1)
    {
        if (!isset($this->tokens[$this->current + $number])) {
            throw new Twig_Error_Syntax('Unexpected end of template', $this->tokens[$this->current + $number - 1]->getLine(), $this->filename);
        }

        return $this->tokens[$this->current + $number];
    }

    /**
     * Tests the current token
     *
     * @return bool
     */
    public function test($primary, $secondary = null)
    {
        return $this->tokens[$this->current]->test($primary, $secondary);
    }

    /**
     * Checks if end of stream was reached
     *
     * @return bool
     */
    public function isEOF()
    {
        return $this->tokens[$this->current]->getType() === Twig_Token::EOF_TYPE;
    }

    /**
     * Gets the current token
     *
     * @return Twig_Token
     */
    public function getCurrent()
    {
        return $this->tokens[$this->current];
    }

    /**
     * Gets the filename associated with this stream
     *
     * @return string
     */
    public function getFilename()
    {
        return $this->filename;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Default base class for compiled templates.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Twig_Template implements Twig_TemplateInterface
{
    protected static $cache = array();

    protected $parent;
    protected $parents;
    protected $env;
    protected $blocks;
    protected $traits;

    /**
     * Constructor.
     *
     * @param Twig_Environment $env A Twig_Environment instance
     */
    public function __construct(Twig_Environment $env)
    {
        $this->env = $env;
        $this->blocks = array();
        $this->traits = array();
    }

    /**
     * Returns the template name.
     *
     * @return string The template name
     */
    abstract public function getTemplateName();

    /**
     * {@inheritdoc}
     */
    public function getEnvironment()
    {
        return $this->env;
    }

    /**
     * Returns the parent template.
     *
     * This method is for internal use only and should never be called
     * directly.
     *
     * @return Twig_TemplateInterface|false The parent template or false if there is no parent
     */
    public function getParent(array $context)
    {
        if (null !== $this->parent) {
            return $this->parent;
        }

        $parent = $this->doGetParent($context);
        if (false === $parent) {
            return false;
        } elseif ($parent instanceof Twig_Template) {
            $name = $parent->getTemplateName();
            $this->parents[$name] = $parent;
            $parent = $name;
        } elseif (!isset($this->parents[$parent])) {
            $this->parents[$parent] = $this->env->loadTemplate($parent);
        }

        return $this->parents[$parent];
    }

    protected function doGetParent(array $context)
    {
        return false;
    }

    public function isTraitable()
    {
        return true;
    }

    /**
     * Displays a parent block.
     *
     * This method is for internal use only and should never be called
     * directly.
     *
     * @param string $name    The block name to display from the parent
     * @param array  $context The context
     * @param array  $blocks  The current set of blocks
     */
    public function displayParentBlock($name, array $context, array $blocks = array())
    {
        $name = (string) $name;

        if (isset($this->traits[$name])) {
            $this->traits[$name][0]->displayBlock($name, $context, $blocks);
        } elseif (false !== $parent = $this->getParent($context)) {
            $parent->displayBlock($name, $context, $blocks);
        } else {
            throw new Twig_Error_Runtime(sprintf('The template has no parent and no traits defining the "%s" block', $name), -1, $this->getTemplateName());
        }
    }

    /**
     * Displays a block.
     *
     * This method is for internal use only and should never be called
     * directly.
     *
     * @param string $name    The block name to display
     * @param array  $context The context
     * @param array  $blocks  The current set of blocks
     */
    public function displayBlock($name, array $context, array $blocks = array())
    {
        $name = (string) $name;

        $template = null;
        if (isset($blocks[$name])) {
            $template = $blocks[$name][0];
            $block = $blocks[$name][1];
            unset($blocks[$name]);
        } elseif (isset($this->blocks[$name])) {
            $template = $this->blocks[$name][0];
            $block = $this->blocks[$name][1];
        }

        if (null !== $template) {
            try {
                $template->$block($context, $blocks);
            } catch (Twig_Error $e) {
                throw $e;
            } catch (Exception $e) {
                throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $template->getTemplateName(), $e);
            }
        } elseif (false !== $parent = $this->getParent($context)) {
            $parent->displayBlock($name, $context, array_merge($this->blocks, $blocks));
        }
    }

    /**
     * Renders a parent block.
     *
     * This method is for internal use only and should never be called
     * directly.
     *
     * @param string $name    The block name to render from the parent
     * @param array  $context The context
     * @param array  $blocks  The current set of blocks
     *
     * @return string The rendered block
     */
    public function renderParentBlock($name, array $context, array $blocks = array())
    {
        ob_start();
        $this->displayParentBlock($name, $context, $blocks);

        return ob_get_clean();
    }

    /**
     * Renders a block.
     *
     * This method is for internal use only and should never be called
     * directly.
     *
     * @param string $name    The block name to render
     * @param array  $context The context
     * @param array  $blocks  The current set of blocks
     *
     * @return string The rendered block
     */
    public function renderBlock($name, array $context, array $blocks = array())
    {
        ob_start();
        $this->displayBlock($name, $context, $blocks);

        return ob_get_clean();
    }

    /**
     * Returns whether a block exists or not.
     *
     * This method is for internal use only and should never be called
     * directly.
     *
     * This method does only return blocks defined in the current template
     * or defined in "used" traits.
     *
     * It does not return blocks from parent templates as the parent
     * template name can be dynamic, which is only known based on the
     * current context.
     *
     * @param string $name The block name
     *
     * @return Boolean true if the block exists, false otherwise
     */
    public function hasBlock($name)
    {
        return isset($this->blocks[(string) $name]);
    }

    /**
     * Returns all block names.
     *
     * This method is for internal use only and should never be called
     * directly.
     *
     * @return array An array of block names
     *
     * @see hasBlock
     */
    public function getBlockNames()
    {
        return array_keys($this->blocks);
    }

    /**
     * Returns all blocks.
     *
     * This method is for internal use only and should never be called
     * directly.
     *
     * @return array An array of blocks
     *
     * @see hasBlock
     */
    public function getBlocks()
    {
        return $this->blocks;
    }

    /**
     * {@inheritdoc}
     */
    public function display(array $context, array $blocks = array())
    {
        $this->displayWithErrorHandling($this->env->mergeGlobals($context), $blocks);
    }

    /**
     * {@inheritdoc}
     */
    public function render(array $context)
    {
        $level = ob_get_level();
        ob_start();
        try {
            $this->display($context);
        } catch (Exception $e) {
            while (ob_get_level() > $level) {
                ob_end_clean();
            }

            throw $e;
        }

        return ob_get_clean();
    }

    protected function displayWithErrorHandling(array $context, array $blocks = array())
    {
        try {
            $this->doDisplay($context, $blocks);
        } catch (Twig_Error $e) {
            if (!$e->getTemplateFile()) {
                $e->setTemplateFile($this->getTemplateName());
            }

            // this is mostly useful for Twig_Error_Loader exceptions
            // see Twig_Error_Loader
            if (false === $e->getTemplateLine()) {
                $e->setTemplateLine(-1);
                $e->guess();
            }

            throw $e;
        } catch (Exception $e) {
            throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $this->getTemplateName(), $e);
        }
    }

    /**
     * Auto-generated method to display the template with the given context.
     *
     * @param array $context An array of parameters to pass to the template
     * @param array $blocks  An array of blocks to pass to the template
     */
    abstract protected function doDisplay(array $context, array $blocks = array());

    /**
     * Returns a variable from the context.
     *
     * This method is for internal use only and should never be called
     * directly.
     *
     * This method should not be overridden in a sub-class as this is an
     * implementation detail that has been introduced to optimize variable
     * access for versions of PHP before 5.4. This is not a way to override
     * the way to get a variable value.
     *
     * @param array   $context           The context
     * @param string  $item              The variable to return from the context
     * @param Boolean $ignoreStrictCheck Whether to ignore the strict variable check or not
     *
     * @return The content of the context variable
     *
     * @throws Twig_Error_Runtime if the variable does not exist and Twig is running in strict mode
     */
    final protected function getContext($context, $item, $ignoreStrictCheck = false)
    {
        if (!array_key_exists($item, $context)) {
            if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
                return null;
            }

            throw new Twig_Error_Runtime(sprintf('Variable "%s" does not exist', $item), -1, $this->getTemplateName());
        }

        return $context[$item];
    }

    /**
     * Returns the attribute value for a given array/object.
     *
     * @param mixed   $object            The object or array from where to get the item
     * @param mixed   $item              The item to get from the array or object
     * @param array   $arguments         An array of arguments to pass if the item is an object method
     * @param string  $type              The type of attribute (@see Twig_Template constants)
     * @param Boolean $isDefinedTest     Whether this is only a defined check
     * @param Boolean $ignoreStrictCheck Whether to ignore the strict attribute check or not
     *
     * @return mixed The attribute value, or a Boolean when $isDefinedTest is true, or null when the attribute is not set and $ignoreStrictCheck is true
     *
     * @throws Twig_Error_Runtime if the attribute does not exist and Twig is running in strict mode and $isDefinedTest is false
     */
    protected function getAttribute($object, $item, array $arguments = array(), $type = Twig_Template::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false)
    {
        // array
        if (Twig_Template::METHOD_CALL !== $type) {
            $arrayItem = is_bool($item) || is_float($item) ? (int) $item : $item;

            if ((is_array($object) && array_key_exists($arrayItem, $object))
                || ($object instanceof ArrayAccess && isset($object[$arrayItem]))
            ) {
                if ($isDefinedTest) {
                    return true;
                }

                return $object[$arrayItem];
            }

            if (Twig_Template::ARRAY_CALL === $type || !is_object($object)) {
                if ($isDefinedTest) {
                    return false;
                }

                if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
                    return null;
                }

                if (is_object($object)) {
                    throw new Twig_Error_Runtime(sprintf('Key "%s" in object (with ArrayAccess) of type "%s" does not exist', $arrayItem, get_class($object)), -1, $this->getTemplateName());
                } elseif (is_array($object)) {
                    throw new Twig_Error_Runtime(sprintf('Key "%s" for array with keys "%s" does not exist', $arrayItem, implode(', ', array_keys($object))), -1, $this->getTemplateName());
                } elseif (Twig_Template::ARRAY_CALL === $type) {
                    throw new Twig_Error_Runtime(sprintf('Impossible to access a key ("%s") on a %s variable ("%s")', $item, gettype($object), $object), -1, $this->getTemplateName());
                } else {
                    throw new Twig_Error_Runtime(sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s")', $item, gettype($object), $object), -1, $this->getTemplateName());
                }
            }
        }

        if (!is_object($object)) {
            if ($isDefinedTest) {
                return false;
            }

            if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
                return null;
            }

            throw new Twig_Error_Runtime(sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s")', $item, gettype($object), $object), -1, $this->getTemplateName());
        }

        $class = get_class($object);

        // object property
        if (Twig_Template::METHOD_CALL !== $type) {
            if (isset($object->$item) || array_key_exists((string) $item, $object)) {
                if ($isDefinedTest) {
                    return true;
                }

                if ($this->env->hasExtension('sandbox')) {
                    $this->env->getExtension('sandbox')->checkPropertyAllowed($object, $item);
                }

                return $object->$item;
            }
        }

        // object method
        if (!isset(self::$cache[$class]['methods'])) {
            self::$cache[$class]['methods'] = array_change_key_case(array_flip(get_class_methods($object)));
        }

        $lcItem = strtolower($item);
        if (isset(self::$cache[$class]['methods'][$lcItem])) {
            $method = (string) $item;
        } elseif (isset(self::$cache[$class]['methods']['get'.$lcItem])) {
            $method = 'get'.$item;
        } elseif (isset(self::$cache[$class]['methods']['is'.$lcItem])) {
            $method = 'is'.$item;
        } elseif (isset(self::$cache[$class]['methods']['__call'])) {
            $method = (string) $item;
        } else {
            if ($isDefinedTest) {
                return false;
            }

            if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
                return null;
            }

            throw new Twig_Error_Runtime(sprintf('Method "%s" for object "%s" does not exist', $item, get_class($object)), -1, $this->getTemplateName());
        }

        if ($isDefinedTest) {
            return true;
        }

        if ($this->env->hasExtension('sandbox')) {
            $this->env->getExtension('sandbox')->checkMethodAllowed($object, $method);
        }

        $ret = call_user_func_array(array($object, $method), $arguments);

        // useful when calling a template method from a template
        // this is not supported but unfortunately heavily used in the Symfony profiler
        if ($object instanceof Twig_TemplateInterface) {
            return $ret === '' ? '' : new Twig_Markup($ret, $this->env->getCharset());
        }

        return $ret;
    }

    /**
     * This method is only useful when testing Twig. Do not use it.
     */
    public static function clearCache()
    {
        self::$cache = array();
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Loads a template from a string.
 *
 * This loader should only be used for unit testing as it has many limitations
 * (for instance, the include or extends tag does not make any sense for a string
 * loader).
 *
 * When using this loader with a cache mechanism, you should know that a new cache
 * key is generated each time a template content "changes" (the cache key being the
 * source code of the template). If you don't want to see your cache grows out of
 * control, you need to take care of clearing the old cache file by yourself.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Loader_String implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
{
    /**
     * {@inheritdoc}
     */
    public function getSource($name)
    {
        return $name;
    }

    /**
     * {@inheritdoc}
     */
    public function exists($name)
    {
        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function getCacheKey($name)
    {
        return $name;
    }

    /**
     * {@inheritdoc}
     */
    public function isFresh($name, $time)
    {
        return true;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Loads a template from an array.
 *
 * When using this loader with a cache mechanism, you should know that a new cache
 * key is generated each time a template content "changes" (the cache key being the
 * source code of the template). If you don't want to see your cache grows out of
 * control, you need to take care of clearing the old cache file by yourself.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
{
    protected $templates = array();

    /**
     * Constructor.
     *
     * @param array $templates An array of templates (keys are the names, and values are the source code)
     *
     * @see Twig_Loader
     */
    public function __construct(array $templates)
    {
        $this->templates = $templates;
    }

    /**
     * Adds or overrides a template.
     *
     * @param string $name     The template name
     * @param string $template The template source
     */
    public function setTemplate($name, $template)
    {
        $this->templates[(string) $name] = $template;
    }

    /**
     * {@inheritdoc}
     */
    public function getSource($name)
    {
        $name = (string) $name;
        if (!isset($this->templates[$name])) {
            throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
        }

        return $this->templates[$name];
    }

    /**
     * {@inheritdoc}
     */
    public function exists($name)
    {
        return isset($this->templates[(string) $name]);
    }

    /**
     * {@inheritdoc}
     */
    public function getCacheKey($name)
    {
        $name = (string) $name;
        if (!isset($this->templates[$name])) {
            throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
        }

        return $this->templates[$name];
    }

    /**
     * {@inheritdoc}
     */
    public function isFresh($name, $time)
    {
        $name = (string) $name;
        if (!isset($this->templates[$name])) {
            throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
        }

        return true;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Loads template from the filesystem.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
{
    /** Identifier of the main namespace. */
    const MAIN_NAMESPACE = '__main__';

    protected $paths = array();
    protected $cache = array();

    /**
     * Constructor.
     *
     * @param string|array $paths A path or an array of paths where to look for templates
     */
    public function __construct($paths = array())
    {
        if ($paths) {
            $this->setPaths($paths);
        }
    }

    /**
     * Returns the paths to the templates.
     *
     * @param string $namespace A path namespace
     *
     * @return array The array of paths where to look for templates
     */
    public function getPaths($namespace = self::MAIN_NAMESPACE)
    {
        return isset($this->paths[$namespace]) ? $this->paths[$namespace] : array();
    }

    /**
     * Returns the path namespaces.
     *
     * The main namespace is always defined.
     *
     * @return array The array of defined namespaces
     */
    public function getNamespaces()
    {
        return array_keys($this->paths);
    }

    /**
     * Sets the paths where templates are stored.
     *
     * @param string|array $paths     A path or an array of paths where to look for templates
     * @param string       $namespace A path namespace
     */
    public function setPaths($paths, $namespace = self::MAIN_NAMESPACE)
    {
        if (!is_array($paths)) {
            $paths = array($paths);
        }

        $this->paths[$namespace] = array();
        foreach ($paths as $path) {
            $this->addPath($path, $namespace);
        }
    }

    /**
     * Adds a path where templates are stored.
     *
     * @param string $path      A path where to look for templates
     * @param string $namespace A path name
     *
     * @throws Twig_Error_Loader
     */
    public function addPath($path, $namespace = self::MAIN_NAMESPACE)
    {
        // invalidate the cache
        $this->cache = array();

        if (!is_dir($path)) {
            throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path));
        }

        $this->paths[$namespace][] = rtrim($path, '/\\');
    }

    /**
     * Prepends a path where templates are stored.
     *
     * @param string $path      A path where to look for templates
     * @param string $namespace A path name
     *
     * @throws Twig_Error_Loader
     */
    public function prependPath($path, $namespace = self::MAIN_NAMESPACE)
    {
        // invalidate the cache
        $this->cache = array();

        if (!is_dir($path)) {
            throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path));
        }

        $path = rtrim($path, '/\\');

        if (!isset($this->paths[$namespace])) {
            $this->paths[$namespace][] = $path;
        } else {
            array_unshift($this->paths[$namespace], $path);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function getSource($name)
    {
        return file_get_contents($this->findTemplate($name));
    }

    /**
     * {@inheritdoc}
     */
    public function getCacheKey($name)
    {
        return $this->findTemplate($name);
    }

    /**
     * {@inheritdoc}
     */
    public function exists($name)
    {
        $name = (string) $name;
        if (isset($this->cache[$name])) {
            return true;
        }

        try {
            $this->findTemplate($name);

            return true;
        } catch (Twig_Error_Loader $exception) {
            return false;
        }
    }

    /**
     * {@inheritdoc}
     */
    public function isFresh($name, $time)
    {
        return filemtime($this->findTemplate($name)) <= $time;
    }

    protected function findTemplate($name)
    {
        $name = (string) $name;

        // normalize name
        $name = preg_replace('#/{2,}#', '/', strtr($name, '\\', '/'));

        if (isset($this->cache[$name])) {
            return $this->cache[$name];
        }

        $this->validateName($name);

        $namespace = self::MAIN_NAMESPACE;
        $shortname = $name;
        if (isset($name[0]) && '@' == $name[0]) {
            if (false === $pos = strpos($name, '/')) {
                throw new Twig_Error_Loader(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name));
            }

            $namespace = substr($name, 1, $pos - 1);
            $shortname = substr($name, $pos + 1);
        }

        if (!isset($this->paths[$namespace])) {
            throw new Twig_Error_Loader(sprintf('There are no registered paths for namespace "%s".', $namespace));
        }

        foreach ($this->paths[$namespace] as $path) {
            if (is_file($path.'/'.$shortname)) {
                return $this->cache[$name] = $path.'/'.$shortname;
            }
        }

        throw new Twig_Error_Loader(sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths[$namespace])));
    }

    protected function validateName($name)
    {
        if (false !== strpos($name, "\0")) {
            throw new Twig_Error_Loader('A template name cannot contain NUL bytes.');
        }

        $name = ltrim($name, '/');
        $parts = explode('/', $name);
        $level = 0;
        foreach ($parts as $part) {
            if ('..' === $part) {
                --$level;
            } elseif ('.' !== $part) {
                ++$level;
            }

            if ($level < 0) {
                throw new Twig_Error_Loader(sprintf('Looks like you try to load a template outside configured directories (%s).', $name));
            }
        }
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2011 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Loads templates from other loaders.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
{
    private $hasSourceCache = array();
    protected $loaders = array();

    /**
     * Constructor.
     *
     * @param Twig_LoaderInterface[] $loaders An array of loader instances
     */
    public function __construct(array $loaders = array())
    {
        foreach ($loaders as $loader) {
            $this->addLoader($loader);
        }
    }

    /**
     * Adds a loader instance.
     *
     * @param Twig_LoaderInterface $loader A Loader instance
     */
    public function addLoader(Twig_LoaderInterface $loader)
    {
        $this->loaders[] = $loader;
        $this->hasSourceCache = array();
    }

    /**
     * {@inheritdoc}
     */
    public function getSource($name)
    {
        $exceptions = array();
        foreach ($this->loaders as $loader) {
            if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
                continue;
            }

            try {
                return $loader->getSource($name);
            } catch (Twig_Error_Loader $e) {
                $exceptions[] = $e->getMessage();
            }
        }

        throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(', ', $exceptions)));
    }

    /**
     * {@inheritdoc}
     */
    public function exists($name)
    {
        $name = (string) $name;

        if (isset($this->hasSourceCache[$name])) {
            return $this->hasSourceCache[$name];
        }

        foreach ($this->loaders as $loader) {
            if ($loader instanceof Twig_ExistsLoaderInterface) {
                if ($loader->exists($name)) {
                    return $this->hasSourceCache[$name] = true;
                }

                continue;
            }

            try {
                $loader->getSource($name);

                return $this->hasSourceCache[$name] = true;
            } catch (Twig_Error_Loader $e) {
            }
        }

        return $this->hasSourceCache[$name] = false;
    }

    /**
     * {@inheritdoc}
     */
    public function getCacheKey($name)
    {
        $exceptions = array();
        foreach ($this->loaders as $loader) {
            if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
                continue;
            }

            try {
                return $loader->getCacheKey($name);
            } catch (Twig_Error_Loader $e) {
                $exceptions[] = get_class($loader).': '.$e->getMessage();
            }
        }

        throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(' ', $exceptions)));
    }

    /**
     * {@inheritdoc}
     */
    public function isFresh($name, $time)
    {
        $exceptions = array();
        foreach ($this->loaders as $loader) {
            if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
                continue;
            }

            try {
                return $loader->isFresh($name, $time);
            } catch (Twig_Error_Loader $e) {
                $exceptions[] = get_class($loader).': '.$e->getMessage();
            }
        }

        throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(' ', $exceptions)));
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2012 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a callable template test.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @deprecated since 1.12 (to be removed in 2.0)
 */
interface Twig_TestCallableInterface
{
    public function getCallable();
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Adds an exists() method for loaders.
 *
 * @author Florin Patan <florinpatan@gmail.com>
 * @deprecated since 1.12 (to be removed in 2.0)
 */
interface Twig_ExistsLoaderInterface
{
    /**
     * Check if we have the source code of a template, given its name.
     *
     * @param string $name The name of the template to check if we can load
     *
     * @return boolean If the template source code is handled by this loader or not
     */
    public function exists($name);
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Base class for all token parsers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Twig_TokenParser implements Twig_TokenParserInterface
{
    /**
     * @var Twig_Parser
     */
    protected $parser;

    /**
     * Sets the parser associated with this token parser
     *
     * @param $parser A Twig_Parser instance
     */
    public function setParser(Twig_Parser $parser)
    {
        $this->parser = $parser;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009-2012 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a template filter.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_SimpleFilter
{
    protected $name;
    protected $callable;
    protected $options;
    protected $arguments = array();

    public function __construct($name, $callable, array $options = array())
    {
        $this->name = $name;
        $this->callable = $callable;
        $this->options = array_merge(array(
            'needs_environment' => false,
            'needs_context'     => false,
            'is_safe'           => null,
            'is_safe_callback'  => null,
            'pre_escape'        => null,
            'preserves_safety'  => null,
            'node_class'        => 'Twig_Node_Expression_Filter',
        ), $options);
    }

    public function getName()
    {
        return $this->name;
    }

    public function getCallable()
    {
        return $this->callable;
    }

    public function getNodeClass()
    {
        return $this->options['node_class'];
    }

    public function setArguments($arguments)
    {
        $this->arguments = $arguments;
    }

    public function getArguments()
    {
        return $this->arguments;
    }

    public function needsEnvironment()
    {
        return $this->options['needs_environment'];
    }

    public function needsContext()
    {
        return $this->options['needs_context'];
    }

    public function getSafe(Twig_Node $filterArgs)
    {
        if (null !== $this->options['is_safe']) {
            return $this->options['is_safe'];
        }

        if (null !== $this->options['is_safe_callback']) {
            return call_user_func($this->options['is_safe_callback'], $filterArgs);
        }
    }

    public function getPreservesSafety()
    {
        return $this->options['preserves_safety'];
    }

    public function getPreEscape()
    {
        return $this->options['pre_escape'];
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2012 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a template test.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @deprecated since 1.12 (to be removed in 2.0)
 */
abstract class Twig_Test implements Twig_TestInterface, Twig_TestCallableInterface
{
    protected $options;
    protected $arguments = array();

    public function __construct(array $options = array())
    {
        $this->options = array_merge(array(
            'callable' => null,
        ), $options);
    }

    public function getCallable()
    {
        return $this->options['callable'];
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2012 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a callable template function.
 *
 * Use Twig_SimpleFunction instead.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @deprecated since 1.12 (to be removed in 2.0)
 */
interface Twig_FunctionCallableInterface
{
    public function getCallable();
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Imports macros.
 *
 * <pre>
 *   {% from 'forms.html' import forms %}
 * </pre>
 */
class Twig_TokenParser_From extends Twig_TokenParser
{
    /**
     * Parses a token and returns a node.
     *
     * @param Twig_Token $token A Twig_Token instance
     *
     * @return Twig_NodeInterface A Twig_NodeInterface instance
     */
    public function parse(Twig_Token $token)
    {
        $macro = $this->parser->getExpressionParser()->parseExpression();
        $stream = $this->parser->getStream();
        $stream->expect('import');

        $targets = array();
        do {
            $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();

            $alias = $name;
            if ($stream->test('as')) {
                $stream->next();

                $alias = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
            }

            $targets[$name] = $alias;

            if (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ',')) {
                break;
            }

            $stream->next();
        } while (true);

        $stream->expect(Twig_Token::BLOCK_END_TYPE);

        $node = new Twig_Node_Import($macro, new Twig_Node_Expression_AssignName($this->parser->getVarName(), $token->getLine()), $token->getLine(), $this->getTag());

        foreach ($targets as $name => $alias) {
            $this->parser->addImportedSymbol('function', $alias, 'get'.$name, $node->getNode('var'));
        }

        return $node;
    }

    /**
     * Gets the tag name associated with this token parser.
     *
     * @return string The tag name
     */
    public function getTag()
    {
        return 'from';
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Remove whitespaces between HTML tags.
 *
 * <pre>
 * {% spaceless %}
 *      <div>
 *          <strong>foo</strong>
 *      </div>
 * {% endspaceless %}
 *
 * {# output will be <div><strong>foo</strong></div> #}
 * </pre>
 */
class Twig_TokenParser_Spaceless extends Twig_TokenParser
{
    /**
     * Parses a token and returns a node.
     *
     * @param Twig_Token $token A Twig_Token instance
     *
     * @return Twig_NodeInterface A Twig_NodeInterface instance
     */
    public function parse(Twig_Token $token)
    {
        $lineno = $token->getLine();

        $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
        $body = $this->parser->subparse(array($this, 'decideSpacelessEnd'), true);
        $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);

        return new Twig_Node_Spaceless($body, $lineno, $this->getTag());
    }

    public function decideSpacelessEnd(Twig_Token $token)
    {
        return $token->test('endspaceless');
    }

    /**
     * Gets the tag name associated with this token parser.
     *
     * @return string The tag name
     */
    public function getTag()
    {
        return 'spaceless';
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Extends a template by another one.
 *
 * <pre>
 *  {% extends "base.html" %}
 * </pre>
 */
class Twig_TokenParser_Extends extends Twig_TokenParser
{
    /**
     * Parses a token and returns a node.
     *
     * @param Twig_Token $token A Twig_Token instance
     *
     * @return Twig_NodeInterface A Twig_NodeInterface instance
     */
    public function parse(Twig_Token $token)
    {
        if (!$this->parser->isMainScope()) {
            throw new Twig_Error_Syntax('Cannot extend from a block', $token->getLine(), $this->parser->getFilename());
        }

        if (null !== $this->parser->getParent()) {
            throw new Twig_Error_Syntax('Multiple extends tags are forbidden', $token->getLine(), $this->parser->getFilename());
        }
        $this->parser->setParent($this->parser->getExpressionParser()->parseExpression());

        $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
    }

    /**
     * Gets the tag name associated with this token parser.
     *
     * @return string The tag name
     */
    public function getTag()
    {
        return 'extends';
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Imports macros.
 *
 * <pre>
 *   {% import 'forms.html' as forms %}
 * </pre>
 */
class Twig_TokenParser_Import extends Twig_TokenParser
{
    /**
     * Parses a token and returns a node.
     *
     * @param Twig_Token $token A Twig_Token instance
     *
     * @return Twig_NodeInterface A Twig_NodeInterface instance
     */
    public function parse(Twig_Token $token)
    {
        $macro = $this->parser->getExpressionParser()->parseExpression();
        $this->parser->getStream()->expect('as');
        $var = new Twig_Node_Expression_AssignName($this->parser->getStream()->expect(Twig_Token::NAME_TYPE)->getValue(), $token->getLine());
        $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);

        $this->parser->addImportedSymbol('template', $var->getAttribute('name'));

        return new Twig_Node_Import($macro, $var, $token->getLine(), $this->getTag());
    }

    /**
     * Gets the tag name associated with this token parser.
     *
     * @return string The tag name
     */
    public function getTag()
    {
        return 'import';
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Tests a condition.
 *
 * <pre>
 * {% if users %}
 *  <ul>
 *    {% for user in users %}
 *      <li>{{ user.username|e }}</li>
 *    {% endfor %}
 *  </ul>
 * {% endif %}
 * </pre>
 */
class Twig_TokenParser_If extends Twig_TokenParser
{
    /**
     * Parses a token and returns a node.
     *
     * @param Twig_Token $token A Twig_Token instance
     *
     * @return Twig_NodeInterface A Twig_NodeInterface instance
     */
    public function parse(Twig_Token $token)
    {
        $lineno = $token->getLine();
        $expr = $this->parser->getExpressionParser()->parseExpression();
        $stream = $this->parser->getStream();
        $stream->expect(Twig_Token::BLOCK_END_TYPE);
        $body = $this->parser->subparse(array($this, 'decideIfFork'));
        $tests = array($expr, $body);
        $else = null;

        $end = false;
        while (!$end) {
            switch ($stream->next()->getValue()) {
                case 'else':
                    $stream->expect(Twig_Token::BLOCK_END_TYPE);
                    $else = $this->parser->subparse(array($this, 'decideIfEnd'));
                    break;

                case 'elseif':
                    $expr = $this->parser->getExpressionParser()->parseExpression();
                    $stream->expect(Twig_Token::BLOCK_END_TYPE);
                    $body = $this->parser->subparse(array($this, 'decideIfFork'));
                    $tests[] = $expr;
                    $tests[] = $body;
                    break;

                case 'endif':
                    $end = true;
                    break;

                default:
                    throw new Twig_Error_Syntax(sprintf('Unexpected end of template. Twig was looking for the following tags "else", "elseif", or "endif" to close the "if" block started at line %d)', $lineno), $stream->getCurrent()->getLine(), $stream->getFilename());
            }
        }

        $stream->expect(Twig_Token::BLOCK_END_TYPE);

        return new Twig_Node_If(new Twig_Node($tests), $else, $lineno, $this->getTag());
    }

    public function decideIfFork(Twig_Token $token)
    {
        return $token->test(array('elseif', 'else', 'endif'));
    }

    public function decideIfEnd(Twig_Token $token)
    {
        return $token->test(array('endif'));
    }

    /**
     * Gets the tag name associated with this token parser.
     *
     * @return string The tag name
     */
    public function getTag()
    {
        return 'if';
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Marks a section of a template to be escaped or not.
 *
 * <pre>
 * {% autoescape true %}
 *   Everything will be automatically escaped in this block
 * {% endautoescape %}
 *
 * {% autoescape false %}
 *   Everything will be outputed as is in this block
 * {% endautoescape %}
 *
 * {% autoescape true js %}
 *   Everything will be automatically escaped in this block
 *   using the js escaping strategy
 * {% endautoescape %}
 * </pre>
 */
class Twig_TokenParser_AutoEscape extends Twig_TokenParser
{
    /**
     * Parses a token and returns a node.
     *
     * @param Twig_Token $token A Twig_Token instance
     *
     * @return Twig_NodeInterface A Twig_NodeInterface instance
     */
    public function parse(Twig_Token $token)
    {
        $lineno = $token->getLine();
        $stream = $this->parser->getStream();

        if ($stream->test(Twig_Token::BLOCK_END_TYPE)) {
            $value = 'html';
        } else {
            $expr = $this->parser->getExpressionParser()->parseExpression();
            if (!$expr instanceof Twig_Node_Expression_Constant) {
                throw new Twig_Error_Syntax('An escaping strategy must be a string or a Boolean.', $stream->getCurrent()->getLine(), $stream->getFilename());
            }
            $value = $expr->getAttribute('value');

            $compat = true === $value || false === $value;

            if (true === $value) {
                $value = 'html';
            }

            if ($compat && $stream->test(Twig_Token::NAME_TYPE)) {
                if (false === $value) {
                    throw new Twig_Error_Syntax('Unexpected escaping strategy as you set autoescaping to false.', $stream->getCurrent()->getLine(), $stream->getFilename());
                }

                $value = $stream->next()->getValue();
            }
        }

        $stream->expect(Twig_Token::BLOCK_END_TYPE);
        $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
        $stream->expect(Twig_Token::BLOCK_END_TYPE);

        return new Twig_Node_AutoEscape($value, $body, $lineno, $this->getTag());
    }

    public function decideBlockEnd(Twig_Token $token)
    {
        return $token->test('endautoescape');
    }

    /**
     * Gets the tag name associated with this token parser.
     *
     * @return string The tag name
     */
    public function getTag()
    {
        return 'autoescape';
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2011 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Imports blocks defined in another template into the current template.
 *
 * <pre>
 * {% extends "base.html" %}
 *
 * {% use "blocks.html" %}
 *
 * {% block title %}{% endblock %}
 * {% block content %}{% endblock %}
 * </pre>
 *
 * @see http://www.twig-project.org/doc/templates.html#horizontal-reuse for details.
 */
class Twig_TokenParser_Use extends Twig_TokenParser
{
    /**
     * Parses a token and returns a node.
     *
     * @param Twig_Token $token A Twig_Token instance
     *
     * @return Twig_NodeInterface A Twig_NodeInterface instance
     */
    public function parse(Twig_Token $token)
    {
        $template = $this->parser->getExpressionParser()->parseExpression();
        $stream = $this->parser->getStream();

        if (!$template instanceof Twig_Node_Expression_Constant) {
            throw new Twig_Error_Syntax('The template references in a "use" statement must be a string.', $stream->getCurrent()->getLine(), $stream->getFilename());
        }

        $targets = array();
        if ($stream->test('with')) {
            $stream->next();

            do {
                $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();

                $alias = $name;
                if ($stream->test('as')) {
                    $stream->next();

                    $alias = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
                }

                $targets[$name] = new Twig_Node_Expression_Constant($alias, -1);

                if (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ',')) {
                    break;
                }

                $stream->next();
            } while (true);
        }

        $stream->expect(Twig_Token::BLOCK_END_TYPE);

        $this->parser->addTrait(new Twig_Node(array('template' => $template, 'targets' => new Twig_Node($targets))));
    }

    /**
     * Gets the tag name associated with this token parser.
     *
     * @return string The tag name
     */
    public function getTag()
    {
        return 'use';
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Includes a template.
 *
 * <pre>
 *   {% include 'header.html' %}
 *     Body
 *   {% include 'footer.html' %}
 * </pre>
 */
class Twig_TokenParser_Include extends Twig_TokenParser
{
    /**
     * Parses a token and returns a node.
     *
     * @param Twig_Token $token A Twig_Token instance
     *
     * @return Twig_NodeInterface A Twig_NodeInterface instance
     */
    public function parse(Twig_Token $token)
    {
        $expr = $this->parser->getExpressionParser()->parseExpression();

        list($variables, $only, $ignoreMissing) = $this->parseArguments();

        return new Twig_Node_Include($expr, $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag());
    }

    protected function parseArguments()
    {
        $stream = $this->parser->getStream();

        $ignoreMissing = false;
        if ($stream->test(Twig_Token::NAME_TYPE, 'ignore')) {
            $stream->next();
            $stream->expect(Twig_Token::NAME_TYPE, 'missing');

            $ignoreMissing = true;
        }

        $variables = null;
        if ($stream->test(Twig_Token::NAME_TYPE, 'with')) {
            $stream->next();

            $variables = $this->parser->getExpressionParser()->parseExpression();
        }

        $only = false;
        if ($stream->test(Twig_Token::NAME_TYPE, 'only')) {
            $stream->next();

            $only = true;
        }

        $stream->expect(Twig_Token::BLOCK_END_TYPE);

        return array($variables, $only, $ignoreMissing);
    }

    /**
     * Gets the tag name associated with this token parser.
     *
     * @return string The tag name
     */
    public function getTag()
    {
        return 'include';
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Loops over each item of a sequence.
 *
 * <pre>
 * <ul>
 *  {% for user in users %}
 *    <li>{{ user.username|e }}</li>
 *  {% endfor %}
 * </ul>
 * </pre>
 */
class Twig_TokenParser_For extends Twig_TokenParser
{
    /**
     * Parses a token and returns a node.
     *
     * @param Twig_Token $token A Twig_Token instance
     *
     * @return Twig_NodeInterface A Twig_NodeInterface instance
     */
    public function parse(Twig_Token $token)
    {
        $lineno = $token->getLine();
        $stream = $this->parser->getStream();
        $targets = $this->parser->getExpressionParser()->parseAssignmentExpression();
        $stream->expect(Twig_Token::OPERATOR_TYPE, 'in');
        $seq = $this->parser->getExpressionParser()->parseExpression();

        $ifexpr = null;
        if ($stream->test(Twig_Token::NAME_TYPE, 'if')) {
            $stream->next();
            $ifexpr = $this->parser->getExpressionParser()->parseExpression();
        }

        $stream->expect(Twig_Token::BLOCK_END_TYPE);
        $body = $this->parser->subparse(array($this, 'decideForFork'));
        if ($stream->next()->getValue() == 'else') {
            $stream->expect(Twig_Token::BLOCK_END_TYPE);
            $else = $this->parser->subparse(array($this, 'decideForEnd'), true);
        } else {
            $else = null;
        }
        $stream->expect(Twig_Token::BLOCK_END_TYPE);

        if (count($targets) > 1) {
            $keyTarget = $targets->getNode(0);
            $keyTarget = new Twig_Node_Expression_AssignName($keyTarget->getAttribute('name'), $keyTarget->getLine());
            $valueTarget = $targets->getNode(1);
            $valueTarget = new Twig_Node_Expression_AssignName($valueTarget->getAttribute('name'), $valueTarget->getLine());
        } else {
            $keyTarget = new Twig_Node_Expression_AssignName('_key', $lineno);
            $valueTarget = $targets->getNode(0);
            $valueTarget = new Twig_Node_Expression_AssignName($valueTarget->getAttribute('name'), $valueTarget->getLine());
        }

        if ($ifexpr) {
            $this->checkLoopUsageCondition($stream, $ifexpr);
            $this->checkLoopUsageBody($stream, $body);
        }

        return new Twig_Node_For($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, $lineno, $this->getTag());
    }

    public function decideForFork(Twig_Token $token)
    {
        return $token->test(array('else', 'endfor'));
    }

    public function decideForEnd(Twig_Token $token)
    {
        return $token->test('endfor');
    }

    // the loop variable cannot be used in the condition
    protected function checkLoopUsageCondition(Twig_TokenStream $stream, Twig_NodeInterface $node)
    {
        if ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name && 'loop' == $node->getNode('node')->getAttribute('name')) {
            throw new Twig_Error_Syntax('The "loop" variable cannot be used in a looping condition', $node->getLine(), $stream->getFilename());
        }

        foreach ($node as $n) {
            if (!$n) {
                continue;
            }

            $this->checkLoopUsageCondition($stream, $n);
        }
    }

    // check usage of non-defined loop-items
    // it does not catch all problems (for instance when a for is included into another or when the variable is used in an include)
    protected function checkLoopUsageBody(Twig_TokenStream $stream, Twig_NodeInterface $node)
    {
        if ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name && 'loop' == $node->getNode('node')->getAttribute('name')) {
            $attribute = $node->getNode('attribute');
            if ($attribute instanceof Twig_Node_Expression_Constant && in_array($attribute->getAttribute('value'), array('length', 'revindex0', 'revindex', 'last'))) {
                throw new Twig_Error_Syntax(sprintf('The "loop.%s" variable is not defined when looping with a condition', $attribute->getAttribute('value')), $node->getLine(), $stream->getFilename());
            }
        }

        // should check for parent.loop.XXX usage
        if ($node instanceof Twig_Node_For) {
            return;
        }

        foreach ($node as $n) {
            if (!$n) {
                continue;
            }

            $this->checkLoopUsageBody($stream, $n);
        }
    }

    /**
     * Gets the tag name associated with this token parser.
     *
     * @return string The tag name
     */
    public function getTag()
    {
        return 'for';
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2011 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Evaluates an expression, discarding the returned value.
 */
class Twig_TokenParser_Do extends Twig_TokenParser
{
    /**
     * Parses a token and returns a node.
     *
     * @param Twig_Token $token A Twig_Token instance
     *
     * @return Twig_NodeInterface A Twig_NodeInterface instance
     */
    public function parse(Twig_Token $token)
    {
        $expr = $this->parser->getExpressionParser()->parseExpression();

        $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);

        return new Twig_Node_Do($expr, $token->getLine(), $this->getTag());
    }

    /**
     * Gets the tag name associated with this token parser.
     *
     * @return string The tag name
     */
    public function getTag()
    {
        return 'do';
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Filters a section of a template by applying filters.
 *
 * <pre>
 * {% filter upper %}
 *  This text becomes uppercase
 * {% endfilter %}
 * </pre>
 */
class Twig_TokenParser_Filter extends Twig_TokenParser
{
    /**
     * Parses a token and returns a node.
     *
     * @param Twig_Token $token A Twig_Token instance
     *
     * @return Twig_NodeInterface A Twig_NodeInterface instance
     */
    public function parse(Twig_Token $token)
    {
        $name = $this->parser->getVarName();
        $ref = new Twig_Node_Expression_BlockReference(new Twig_Node_Expression_Constant($name, $token->getLine()), true, $token->getLine(), $this->getTag());

        $filter = $this->parser->getExpressionParser()->parseFilterExpressionRaw($ref, $this->getTag());
        $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);

        $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
        $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);

        $block = new Twig_Node_Block($name, $body, $token->getLine());
        $this->parser->setBlock($name, $block);

        return new Twig_Node_Print($filter, $token->getLine(), $this->getTag());
    }

    public function decideBlockEnd(Twig_Token $token)
    {
        return $token->test('endfilter');
    }

    /**
     * Gets the tag name associated with this token parser.
     *
     * @return string The tag name
     */
    public function getTag()
    {
        return 'filter';
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Defines a variable.
 *
 * <pre>
 *  {% set foo = 'foo' %}
 *
 *  {% set foo = [1, 2] %}
 *
 *  {% set foo = {'foo': 'bar'} %}
 *
 *  {% set foo = 'foo' ~ 'bar' %}
 *
 *  {% set foo, bar = 'foo', 'bar' %}
 *
 *  {% set foo %}Some content{% endset %}
 * </pre>
 */
class Twig_TokenParser_Set extends Twig_TokenParser
{
    /**
     * Parses a token and returns a node.
     *
     * @param Twig_Token $token A Twig_Token instance
     *
     * @return Twig_NodeInterface A Twig_NodeInterface instance
     */
    public function parse(Twig_Token $token)
    {
        $lineno = $token->getLine();
        $stream = $this->parser->getStream();
        $names = $this->parser->getExpressionParser()->parseAssignmentExpression();

        $capture = false;
        if ($stream->test(Twig_Token::OPERATOR_TYPE, '=')) {
            $stream->next();
            $values = $this->parser->getExpressionParser()->parseMultitargetExpression();

            $stream->expect(Twig_Token::BLOCK_END_TYPE);

            if (count($names) !== count($values)) {
                throw new Twig_Error_Syntax("When using set, you must have the same number of variables and assignments.", $stream->getCurrent()->getLine(), $stream->getFilename());
            }
        } else {
            $capture = true;

            if (count($names) > 1) {
                throw new Twig_Error_Syntax("When using set with a block, you cannot have a multi-target.", $stream->getCurrent()->getLine(), $stream->getFilename());
            }

            $stream->expect(Twig_Token::BLOCK_END_TYPE);

            $values = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
            $stream->expect(Twig_Token::BLOCK_END_TYPE);
        }

        return new Twig_Node_Set($capture, $names, $values, $lineno, $this->getTag());
    }

    public function decideBlockEnd(Twig_Token $token)
    {
        return $token->test('endset');
    }

    /**
     * Gets the tag name associated with this token parser.
     *
     * @return string The tag name
     */
    public function getTag()
    {
        return 'set';
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Marks a section of a template as being reusable.
 *
 * <pre>
 *  {% block head %}
 *    <link rel="stylesheet" href="style.css" />
 *    <title>{% block title %}{% endblock %} - My Webpage</title>
 *  {% endblock %}
 * </pre>
 */
class Twig_TokenParser_Block extends Twig_TokenParser
{
    /**
     * Parses a token and returns a node.
     *
     * @param Twig_Token $token A Twig_Token instance
     *
     * @return Twig_NodeInterface A Twig_NodeInterface instance
     */
    public function parse(Twig_Token $token)
    {
        $lineno = $token->getLine();
        $stream = $this->parser->getStream();
        $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
        if ($this->parser->hasBlock($name)) {
            throw new Twig_Error_Syntax(sprintf("The block '$name' has already been defined line %d", $this->parser->getBlock($name)->getLine()), $stream->getCurrent()->getLine(), $stream->getFilename());
        }
        $this->parser->setBlock($name, $block = new Twig_Node_Block($name, new Twig_Node(array()), $lineno));
        $this->parser->pushLocalScope();
        $this->parser->pushBlockStack($name);

        if ($stream->test(Twig_Token::BLOCK_END_TYPE)) {
            $stream->next();

            $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
            if ($stream->test(Twig_Token::NAME_TYPE)) {
                $value = $stream->next()->getValue();

                if ($value != $name) {
                    throw new Twig_Error_Syntax(sprintf("Expected endblock for block '$name' (but %s given)", $value), $stream->getCurrent()->getLine(), $stream->getFilename());
                }
            }
        } else {
            $body = new Twig_Node(array(
                new Twig_Node_Print($this->parser->getExpressionParser()->parseExpression(), $lineno),
            ));
        }
        $stream->expect(Twig_Token::BLOCK_END_TYPE);

        $block->setNode('body', $body);
        $this->parser->popBlockStack();
        $this->parser->popLocalScope();

        return new Twig_Node_BlockReference($name, $lineno, $this->getTag());
    }

    public function decideBlockEnd(Twig_Token $token)
    {
        return $token->test('endblock');
    }

    /**
     * Gets the tag name associated with this token parser.
     *
     * @return string The tag name
     */
    public function getTag()
    {
        return 'block';
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Defines a macro.
 *
 * <pre>
 * {% macro input(name, value, type, size) %}
 *    <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" />
 * {% endmacro %}
 * </pre>
 */
class Twig_TokenParser_Macro extends Twig_TokenParser
{
    /**
     * Parses a token and returns a node.
     *
     * @param Twig_Token $token A Twig_Token instance
     *
     * @return Twig_NodeInterface A Twig_NodeInterface instance
     */
    public function parse(Twig_Token $token)
    {
        $lineno = $token->getLine();
        $stream = $this->parser->getStream();
        $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();

        $arguments = $this->parser->getExpressionParser()->parseArguments(true, true);

        $stream->expect(Twig_Token::BLOCK_END_TYPE);
        $this->parser->pushLocalScope();
        $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
        if ($stream->test(Twig_Token::NAME_TYPE)) {
            $value = $stream->next()->getValue();

            if ($value != $name) {
                throw new Twig_Error_Syntax(sprintf("Expected endmacro for macro '$name' (but %s given)", $value), $stream->getCurrent()->getLine(), $stream->getFilename());
            }
        }
        $this->parser->popLocalScope();
        $stream->expect(Twig_Token::BLOCK_END_TYPE);

        $this->parser->setMacro($name, new Twig_Node_Macro($name, new Twig_Node_Body(array($body)), $arguments, $lineno, $this->getTag()));
    }

    public function decideBlockEnd(Twig_Token $token)
    {
        return $token->test('endmacro');
    }

    /**
     * Gets the tag name associated with this token parser.
     *
     * @return string The tag name
     */
    public function getTag()
    {
        return 'macro';
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Marks a section of a template as untrusted code that must be evaluated in the sandbox mode.
 *
 * <pre>
 * {% sandbox %}
 *     {% include 'user.html' %}
 * {% endsandbox %}
 * </pre>
 *
 * @see http://www.twig-project.org/doc/api.html#sandbox-extension for details
 */
class Twig_TokenParser_Sandbox extends Twig_TokenParser
{
    /**
     * Parses a token and returns a node.
     *
     * @param Twig_Token $token A Twig_Token instance
     *
     * @return Twig_NodeInterface A Twig_NodeInterface instance
     */
    public function parse(Twig_Token $token)
    {
        $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
        $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true);
        $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);

        // in a sandbox tag, only include tags are allowed
        if (!$body instanceof Twig_Node_Include) {
            foreach ($body as $node) {
                if ($node instanceof Twig_Node_Text && ctype_space($node->getAttribute('data'))) {
                    continue;
                }

                if (!$node instanceof Twig_Node_Include) {
                    throw new Twig_Error_Syntax('Only "include" tags are allowed within a "sandbox" section', $node->getLine(), $this->parser->getFilename());
                }
            }
        }

        return new Twig_Node_Sandbox($body, $token->getLine(), $this->getTag());
    }

    public function decideBlockEnd(Twig_Token $token)
    {
        return $token->test('endsandbox');
    }

    /**
     * Gets the tag name associated with this token parser.
     *
     * @return string The tag name
     */
    public function getTag()
    {
        return 'sandbox';
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2012 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Embeds a template.
 */
class Twig_TokenParser_Embed extends Twig_TokenParser_Include
{
    /**
     * Parses a token and returns a node.
     *
     * @param Twig_Token $token A Twig_Token instance
     *
     * @return Twig_NodeInterface A Twig_NodeInterface instance
     */
    public function parse(Twig_Token $token)
    {
        $stream = $this->parser->getStream();

        $parent = $this->parser->getExpressionParser()->parseExpression();

        list($variables, $only, $ignoreMissing) = $this->parseArguments();

        // inject a fake parent to make the parent() function work
        $stream->injectTokens(array(
            new Twig_Token(Twig_Token::BLOCK_START_TYPE, '', $token->getLine()),
            new Twig_Token(Twig_Token::NAME_TYPE, 'extends', $token->getLine()),
            new Twig_Token(Twig_Token::STRING_TYPE, '__parent__', $token->getLine()),
            new Twig_Token(Twig_Token::BLOCK_END_TYPE, '', $token->getLine()),
        ));

        $module = $this->parser->parse($stream, array($this, 'decideBlockEnd'), true);

        // override the parent with the correct one
        $module->setNode('parent', $parent);

        $this->parser->embedTemplate($module);

        $stream->expect(Twig_Token::BLOCK_END_TYPE);

        return new Twig_Node_Embed($module->getAttribute('filename'), $module->getAttribute('index'), $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag());
    }

    public function decideBlockEnd(Twig_Token $token)
    {
        return $token->test('endembed');
    }

    /**
     * Gets the tag name associated with this token parser.
     *
     * @return string The tag name
     */
    public function getTag()
    {
        return 'embed';
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2011 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Flushes the output to the client.
 *
 * @see flush()
 */
class Twig_TokenParser_Flush extends Twig_TokenParser
{
    /**
     * Parses a token and returns a node.
     *
     * @param Twig_Token $token A Twig_Token instance
     *
     * @return Twig_NodeInterface A Twig_NodeInterface instance
     */
    public function parse(Twig_Token $token)
    {
        $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);

        return new Twig_Node_Flush($token->getLine(), $this->getTag());
    }

    /**
     * Gets the tag name associated with this token parser.
     *
     * @return string The tag name
     */
    public function getTag()
    {
        return 'flush';
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Twig_NodeTraverser is a node traverser.
 *
 * It visits all nodes and their children and call the given visitor for each.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_NodeTraverser
{
    protected $env;
    protected $visitors;

    /**
     * Constructor.
     *
     * @param Twig_Environment $env      A Twig_Environment instance
     * @param array            $visitors An array of Twig_NodeVisitorInterface instances
     */
    public function __construct(Twig_Environment $env, array $visitors = array())
    {
        $this->env = $env;
        $this->visitors = array();
        foreach ($visitors as $visitor) {
            $this->addVisitor($visitor);
        }
    }

    /**
     * Adds a visitor.
     *
     * @param Twig_NodeVisitorInterface $visitor A Twig_NodeVisitorInterface instance
     */
    public function addVisitor(Twig_NodeVisitorInterface $visitor)
    {
        if (!isset($this->visitors[$visitor->getPriority()])) {
            $this->visitors[$visitor->getPriority()] = array();
        }

        $this->visitors[$visitor->getPriority()][] = $visitor;
    }

    /**
     * Traverses a node and calls the registered visitors.
     *
     * @param Twig_NodeInterface $node A Twig_NodeInterface instance
     */
    public function traverse(Twig_NodeInterface $node)
    {
        ksort($this->visitors);
        foreach ($this->visitors as $visitors) {
            foreach ($visitors as $visitor) {
                $node = $this->traverseForVisitor($visitor, $node);
            }
        }

        return $node;
    }

    protected function traverseForVisitor(Twig_NodeVisitorInterface $visitor, Twig_NodeInterface $node = null)
    {
        if (null === $node) {
            return null;
        }

        $node = $visitor->enterNode($node, $this->env);

        foreach ($node as $k => $n) {
            if (false !== $n = $this->traverseForVisitor($visitor, $n)) {
                $node->setNode($k, $n);
            } else {
                $node->removeNode($k);
            }
        }

        return $visitor->leaveNode($node, $this->env);
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a template test.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @deprecated since 1.12 (to be removed in 2.0)
 */
interface Twig_TestInterface
{
    /**
     * Compiles a test.
     *
     * @return string The PHP code for the test
     */
    public function compile();
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2011 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a template function as a node.
 *
 * Use Twig_SimpleFunction instead.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @deprecated since 1.12 (to be removed in 2.0)
 */
class Twig_Function_Node extends Twig_Function
{
    protected $class;

    public function __construct($class, array $options = array())
    {
        parent::__construct($options);

        $this->class = $class;
    }

    public function getClass()
    {
        return $this->class;
    }

    public function compile()
    {
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2010 Arnaud Le Blanc
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a function template function.
 *
 * Use Twig_SimpleFunction instead.
 *
 * @author Arnaud Le Blanc <arnaud.lb@gmail.com>
 * @deprecated since 1.12 (to be removed in 2.0)
 */
class Twig_Function_Function extends Twig_Function
{
    protected $function;

    public function __construct($function, array $options = array())
    {
        $options['callable'] = $function;

        parent::__construct($options);

        $this->function = $function;
    }

    public function compile()
    {
        return $this->function;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2010 Arnaud Le Blanc
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a method template function.
 *
 * Use Twig_SimpleFunction instead.
 *
 * @author Arnaud Le Blanc <arnaud.lb@gmail.com>
 * @deprecated since 1.12 (to be removed in 2.0)
 */
class Twig_Function_Method extends Twig_Function
{
    protected $extension;
    protected $method;

    public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array())
    {
        $options['callable'] = array($extension, $method);

        parent::__construct($options);

        $this->extension = $extension;
        $this->method = $method;
    }

    public function compile()
    {
        return sprintf('$this->env->getExtension(\'%s\')->%s', $this->extension->getName(), $this->method);
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2012 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a callable template filter.
 *
 * Use Twig_SimpleFilter instead.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @deprecated since 1.12 (to be removed in 2.0)
 */
interface Twig_FilterCallableInterface
{
    public function getCallable();
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Exception thrown when an error occurs during template loading.
 *
 * Automatic template information guessing is always turned off as
 * if a template cannot be loaded, there is nothing to guess.
 * However, when a template is loaded from another one, then, we need
 * to find the current context and this is automatically done by
 * Twig_Template::displayWithErrorHandling().
 *
 * This strategy makes Twig_Environment::resolveTemplate() much faster.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Error_Loader extends Twig_Error
{
    public function __construct($message, $lineno = -1, $filename = null, Exception $previous = null)
    {
        parent::__construct($message, false, false, $previous);
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Exception thrown when an error occurs at runtime.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Error_Runtime extends Twig_Error
{
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Exception thrown when a syntax error occurs during lexing or parsing of a template.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Error_Syntax extends Twig_Error
{
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2011 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Internal node used by the for node.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_ForLoop extends Twig_Node
{
    public function __construct($lineno, $tag = null)
    {
        parent::__construct(array(), array('with_loop' => false, 'ifexpr' => false, 'else' => false), $lineno, $tag);
    }

    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        if ($this->getAttribute('else')) {
            $compiler->write("\$context['_iterated'] = true;\n");
        }

        if ($this->getAttribute('with_loop')) {
            $compiler
                ->write("++\$context['loop']['index0'];\n")
                ->write("++\$context['loop']['index'];\n")
                ->write("\$context['loop']['first'] = false;\n")
            ;

            if (!$this->getAttribute('ifexpr')) {
                $compiler
                    ->write("if (isset(\$context['loop']['length'])) {\n")
                    ->indent()
                    ->write("--\$context['loop']['revindex0'];\n")
                    ->write("--\$context['loop']['revindex'];\n")
                    ->write("\$context['loop']['last'] = 0 === \$context['loop']['revindex0'];\n")
                    ->outdent()
                    ->write("}\n")
                ;
            }
        }
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a spaceless node.
 *
 * It removes spaces between HTML tags.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_Spaceless extends Twig_Node
{
    public function __construct(Twig_NodeInterface $body, $lineno, $tag = 'spaceless')
    {
        parent::__construct(array('body' => $body), array(), $lineno, $tag);
    }

    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->addDebugInfo($this)
            ->write("ob_start();\n")
            ->subcompile($this->getNode('body'))
            ->write("echo trim(preg_replace('/>\s+</', '><', ob_get_clean()));\n")
        ;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a block call node.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_BlockReference extends Twig_Node implements Twig_NodeOutputInterface
{
    public function __construct($name, $lineno, $tag = null)
    {
        parent::__construct(array(), array('name' => $name), $lineno, $tag);
    }

    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->addDebugInfo($this)
            ->write(sprintf("\$this->displayBlock('%s', \$context, \$blocks);\n", $this->getAttribute('name')))
        ;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a module node.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_Module extends Twig_Node
{
    public function __construct(Twig_NodeInterface $body, Twig_Node_Expression $parent = null, Twig_NodeInterface $blocks, Twig_NodeInterface $macros, Twig_NodeInterface $traits, $embeddedTemplates, $filename)
    {
        // embedded templates are set as attributes so that they are only visited once by the visitors
        parent::__construct(array('parent' => $parent, 'body' => $body, 'blocks' => $blocks, 'macros' => $macros, 'traits' => $traits), array('filename' => $filename, 'index' => null, 'embedded_templates' => $embeddedTemplates), 1);
    }

    public function setIndex($index)
    {
        $this->setAttribute('index', $index);
    }

    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        $this->compileTemplate($compiler);

        foreach ($this->getAttribute('embedded_templates') as $template) {
            $compiler->subcompile($template);
        }
    }

    protected function compileTemplate(Twig_Compiler $compiler)
    {
        if (!$this->getAttribute('index')) {
            $compiler->write('<?php');
        }

        $this->compileClassHeader($compiler);

        if (count($this->getNode('blocks')) || count($this->getNode('traits')) || null === $this->getNode('parent') || $this->getNode('parent') instanceof Twig_Node_Expression_Constant) {
            $this->compileConstructor($compiler);
        }

        $this->compileGetParent($compiler);

        $this->compileDisplayHeader($compiler);

        $this->compileDisplayBody($compiler);

        $this->compileDisplayFooter($compiler);

        $compiler->subcompile($this->getNode('blocks'));

        $this->compileMacros($compiler);

        $this->compileGetTemplateName($compiler);

        $this->compileIsTraitable($compiler);

        $this->compileDebugInfo($compiler);

        $this->compileClassFooter($compiler);
    }

    protected function compileGetParent(Twig_Compiler $compiler)
    {
        if (null === $this->getNode('parent')) {
            return;
        }

        $compiler
            ->write("protected function doGetParent(array \$context)\n", "{\n")
            ->indent()
            ->write("return ")
        ;

        if ($this->getNode('parent') instanceof Twig_Node_Expression_Constant) {
            $compiler->subcompile($this->getNode('parent'));
        } else {
            $compiler
                ->raw("\$this->env->resolveTemplate(")
                ->subcompile($this->getNode('parent'))
                ->raw(")")
            ;
        }

        $compiler
            ->raw(";\n")
            ->outdent()
            ->write("}\n\n")
        ;
    }

    protected function compileDisplayBody(Twig_Compiler $compiler)
    {
        $compiler->subcompile($this->getNode('body'));

        if (null !== $this->getNode('parent')) {
            if ($this->getNode('parent') instanceof Twig_Node_Expression_Constant) {
                $compiler->write("\$this->parent");
            } else {
                $compiler->write("\$this->getParent(\$context)");
            }
            $compiler->raw("->display(\$context, array_merge(\$this->blocks, \$blocks));\n");
        }
    }

    protected function compileClassHeader(Twig_Compiler $compiler)
    {
        $compiler
            ->write("\n\n")
            // if the filename contains */, add a blank to avoid a PHP parse error
            ->write("/* ".str_replace('*/', '* /', $this->getAttribute('filename'))." */\n")
            ->write('class '.$compiler->getEnvironment()->getTemplateClass($this->getAttribute('filename'), $this->getAttribute('index')))
            ->raw(sprintf(" extends %s\n", $compiler->getEnvironment()->getBaseTemplateClass()))
            ->write("{\n")
            ->indent()
        ;
    }

    protected function compileConstructor(Twig_Compiler $compiler)
    {
        $compiler
            ->write("public function __construct(Twig_Environment \$env)\n", "{\n")
            ->indent()
            ->write("parent::__construct(\$env);\n\n")
        ;

        // parent
        if (null === $this->getNode('parent')) {
            $compiler->write("\$this->parent = false;\n\n");
        } elseif ($this->getNode('parent') instanceof Twig_Node_Expression_Constant) {
            $compiler
                ->write("\$this->parent = \$this->env->loadTemplate(")
                ->subcompile($this->getNode('parent'))
                ->raw(");\n\n")
            ;
        }

        $countTraits = count($this->getNode('traits'));
        if ($countTraits) {
            // traits
            foreach ($this->getNode('traits') as $i => $trait) {
                $this->compileLoadTemplate($compiler, $trait->getNode('template'), sprintf('$_trait_%s', $i));

                $compiler
                    ->addDebugInfo($trait->getNode('template'))
                    ->write(sprintf("if (!\$_trait_%s->isTraitable()) {\n", $i))
                    ->indent()
                    ->write("throw new Twig_Error_Runtime('Template \"'.")
                    ->subcompile($trait->getNode('template'))
                    ->raw(".'\" cannot be used as a trait.');\n")
                    ->outdent()
                    ->write("}\n")
                    ->write(sprintf("\$_trait_%s_blocks = \$_trait_%s->getBlocks();\n\n", $i, $i))
                ;

                foreach ($trait->getNode('targets') as $key => $value) {
                    $compiler
                        ->write(sprintf("\$_trait_%s_blocks[", $i))
                        ->subcompile($value)
                        ->raw(sprintf("] = \$_trait_%s_blocks[", $i))
                        ->string($key)
                        ->raw(sprintf("]; unset(\$_trait_%s_blocks[", $i))
                        ->string($key)
                        ->raw("]);\n\n")
                    ;
                }
            }

            if ($countTraits > 1) {
                $compiler
                    ->write("\$this->traits = array_merge(\n")
                    ->indent()
                ;

                for ($i = 0; $i < $countTraits; $i++) {
                    $compiler
                        ->write(sprintf("\$_trait_%s_blocks".($i == $countTraits - 1 ? '' : ',')."\n", $i))
                    ;
                }

                $compiler
                    ->outdent()
                    ->write(");\n\n")
                ;
            } else {
                $compiler
                    ->write("\$this->traits = \$_trait_0_blocks;\n\n")
                ;
            }

            $compiler
                ->write("\$this->blocks = array_merge(\n")
                ->indent()
                ->write("\$this->traits,\n")
                ->write("array(\n")
            ;
        } else {
            $compiler
                ->write("\$this->blocks = array(\n")
            ;
        }

        // blocks
        $compiler
            ->indent()
        ;

        foreach ($this->getNode('blocks') as $name => $node) {
            $compiler
                ->write(sprintf("'%s' => array(\$this, 'block_%s'),\n", $name, $name))
            ;
        }

        if ($countTraits) {
            $compiler
                ->outdent()
                ->write(")\n")
            ;
        }

        $compiler
            ->outdent()
            ->write(");\n")
            ->outdent()
            ->write("}\n\n");
        ;
    }

    protected function compileDisplayHeader(Twig_Compiler $compiler)
    {
        $compiler
            ->write("protected function doDisplay(array \$context, array \$blocks = array())\n", "{\n")
            ->indent()
        ;
    }

    protected function compileDisplayFooter(Twig_Compiler $compiler)
    {
        $compiler
            ->outdent()
            ->write("}\n\n")
        ;
    }

    protected function compileClassFooter(Twig_Compiler $compiler)
    {
        $compiler
            ->outdent()
            ->write("}\n")
        ;
    }

    protected function compileMacros(Twig_Compiler $compiler)
    {
        $compiler->subcompile($this->getNode('macros'));
    }

    protected function compileGetTemplateName(Twig_Compiler $compiler)
    {
        $compiler
            ->write("public function getTemplateName()\n", "{\n")
            ->indent()
            ->write('return ')
            ->repr($this->getAttribute('filename'))
            ->raw(";\n")
            ->outdent()
            ->write("}\n\n")
        ;
    }

    protected function compileIsTraitable(Twig_Compiler $compiler)
    {
        // A template can be used as a trait if:
        //   * it has no parent
        //   * it has no macros
        //   * it has no body
        //
        // Put another way, a template can be used as a trait if it
        // only contains blocks and use statements.
        $traitable = null === $this->getNode('parent') && 0 === count($this->getNode('macros'));
        if ($traitable) {
            if ($this->getNode('body') instanceof Twig_Node_Body) {
                $nodes = $this->getNode('body')->getNode(0);
            } else {
                $nodes = $this->getNode('body');
            }

            if (!count($nodes)) {
                $nodes = new Twig_Node(array($nodes));
            }

            foreach ($nodes as $node) {
                if (!count($node)) {
                    continue;
                }

                if ($node instanceof Twig_Node_Text && ctype_space($node->getAttribute('data'))) {
                    continue;
                }

                if ($node instanceof Twig_Node_BlockReference) {
                    continue;
                }

                $traitable = false;
                break;
            }
        }

        if ($traitable) {
            return;
        }

        $compiler
            ->write("public function isTraitable()\n", "{\n")
            ->indent()
            ->write(sprintf("return %s;\n", $traitable ? 'true' : 'false'))
            ->outdent()
            ->write("}\n\n")
        ;
    }

    protected function compileDebugInfo(Twig_Compiler $compiler)
    {
        $compiler
            ->write("public function getDebugInfo()\n", "{\n")
            ->indent()
            ->write(sprintf("return %s;\n", str_replace("\n", '', var_export(array_reverse($compiler->getDebugInfo(), true), true))))
            ->outdent()
            ->write("}\n")
        ;
    }

    protected function compileLoadTemplate(Twig_Compiler $compiler, $node, $var)
    {
        if ($node instanceof Twig_Node_Expression_Constant) {
            $compiler
                ->write(sprintf("%s = \$this->env->loadTemplate(", $var))
                ->subcompile($node)
                ->raw(");\n")
            ;
        } else {
            $compiler
                ->write(sprintf("%s = ", $var))
                ->subcompile($node)
                ->raw(";\n")
                ->write(sprintf("if (!%s", $var))
                ->raw(" instanceof Twig_Template) {\n")
                ->indent()
                ->write(sprintf("%s = \$this->env->loadTemplate(%s);\n", $var, $var))
                ->outdent()
                ->write("}\n")
            ;
        }
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a text node.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_Text extends Twig_Node implements Twig_NodeOutputInterface
{
    public function __construct($data, $lineno)
    {
        parent::__construct(array(), array('data' => $data), $lineno);
    }

    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->addDebugInfo($this)
            ->write('echo ')
            ->string($this->getAttribute('data'))
            ->raw(";\n")
        ;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents an import node.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_Import extends Twig_Node
{
    public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $var, $lineno, $tag = null)
    {
        parent::__construct(array('expr' => $expr, 'var' => $var), array(), $lineno, $tag);
    }

    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->addDebugInfo($this)
            ->write('')
            ->subcompile($this->getNode('var'))
            ->raw(' = ')
        ;

        if ($this->getNode('expr') instanceof Twig_Node_Expression_Name && '_self' === $this->getNode('expr')->getAttribute('name')) {
            $compiler->raw("\$this");
        } else {
            $compiler
                ->raw('$this->env->loadTemplate(')
                ->subcompile($this->getNode('expr'))
                ->raw(")")
            ;
        }

        $compiler->raw(";\n");
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents an if node.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_If extends Twig_Node
{
    public function __construct(Twig_NodeInterface $tests, Twig_NodeInterface $else = null, $lineno, $tag = null)
    {
        parent::__construct(array('tests' => $tests, 'else' => $else), array(), $lineno, $tag);
    }

    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        $compiler->addDebugInfo($this);
        for ($i = 0, $count = count($this->getNode('tests')); $i < $count; $i += 2) {
            if ($i > 0) {
                $compiler
                    ->outdent()
                    ->write("} elseif (")
                ;
            } else {
                $compiler
                    ->write('if (')
                ;
            }

            $compiler
                ->subcompile($this->getNode('tests')->getNode($i))
                ->raw(") {\n")
                ->indent()
                ->subcompile($this->getNode('tests')->getNode($i + 1))
            ;
        }

        if ($this->hasNode('else') && null !== $this->getNode('else')) {
            $compiler
                ->outdent()
                ->write("} else {\n")
                ->indent()
                ->subcompile($this->getNode('else'))
            ;
        }

        $compiler
            ->outdent()
            ->write("}\n");
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a module node.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_SandboxedModule extends Twig_Node_Module
{
    protected $usedFilters;
    protected $usedTags;
    protected $usedFunctions;

    public function __construct(Twig_Node_Module $node, array $usedFilters, array $usedTags, array $usedFunctions)
    {
        parent::__construct($node->getNode('body'), $node->getNode('parent'), $node->getNode('blocks'), $node->getNode('macros'), $node->getNode('traits'), $node->getAttribute('embedded_templates'), $node->getAttribute('filename'), $node->getLine(), $node->getNodeTag());

        $this->setAttribute('index', $node->getAttribute('index'));

        $this->usedFilters = $usedFilters;
        $this->usedTags = $usedTags;
        $this->usedFunctions = $usedFunctions;
    }

    protected function compileDisplayBody(Twig_Compiler $compiler)
    {
        $compiler->write("\$this->checkSecurity();\n");

        parent::compileDisplayBody($compiler);
    }

    protected function compileDisplayFooter(Twig_Compiler $compiler)
    {
        parent::compileDisplayFooter($compiler);

        $compiler
            ->write("protected function checkSecurity()\n", "{\n")
            ->indent()
            ->write("\$this->env->getExtension('sandbox')->checkSecurity(\n")
            ->indent()
            ->write(!$this->usedTags ? "array(),\n" : "array('".implode('\', \'', $this->usedTags)."'),\n")
            ->write(!$this->usedFilters ? "array(),\n" : "array('".implode('\', \'', $this->usedFilters)."'),\n")
            ->write(!$this->usedFunctions ? "array()\n" : "array('".implode('\', \'', $this->usedFunctions)."')\n")
            ->outdent()
            ->write(");\n")
            ->outdent()
            ->write("}\n\n")
        ;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a node that outputs an expression.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_Print extends Twig_Node implements Twig_NodeOutputInterface
{
    public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null)
    {
        parent::__construct(array('expr' => $expr), array(), $lineno, $tag);
    }

    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->addDebugInfo($this)
            ->write('echo ')
            ->subcompile($this->getNode('expr'))
            ->raw(";\n")
        ;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents an autoescape node.
 *
 * The value is the escaping strategy (can be html, js, ...)
 *
 * The true value is equivalent to html.
 *
 * If autoescaping is disabled, then the value is false.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_AutoEscape extends Twig_Node
{
    public function __construct($value, Twig_NodeInterface $body, $lineno, $tag = 'autoescape')
    {
        parent::__construct(array('body' => $body), array('value' => $value), $lineno, $tag);
    }

    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        $compiler->subcompile($this->getNode('body'));
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents an include node.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_Include extends Twig_Node implements Twig_NodeOutputInterface
{
    public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null)
    {
        parent::__construct(array('expr' => $expr, 'variables' => $variables), array('only' => (Boolean) $only, 'ignore_missing' => (Boolean) $ignoreMissing), $lineno, $tag);
    }

    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        $compiler->addDebugInfo($this);

        if ($this->getAttribute('ignore_missing')) {
            $compiler
                ->write("try {\n")
                ->indent()
            ;
        }

        $this->addGetTemplate($compiler);

        $compiler->raw('->display(');

        $this->addTemplateArguments($compiler);

        $compiler->raw(");\n");

        if ($this->getAttribute('ignore_missing')) {
            $compiler
                ->outdent()
                ->write("} catch (Twig_Error_Loader \$e) {\n")
                ->indent()
                ->write("// ignore missing template\n")
                ->outdent()
                ->write("}\n\n")
            ;
        }
    }

    protected function addGetTemplate(Twig_Compiler $compiler)
    {
        if ($this->getNode('expr') instanceof Twig_Node_Expression_Constant) {
            $compiler
                ->write("\$this->env->loadTemplate(")
                ->subcompile($this->getNode('expr'))
                ->raw(")")
            ;
        } else {
            $compiler
                ->write("\$template = \$this->env->resolveTemplate(")
                ->subcompile($this->getNode('expr'))
                ->raw(");\n")
                ->write('$template')
            ;
        }
    }

    protected function addTemplateArguments(Twig_Compiler $compiler)
    {
        if (false === $this->getAttribute('only')) {
            if (null === $this->getNode('variables')) {
                $compiler->raw('$context');
            } else {
                $compiler
                    ->raw('array_merge($context, ')
                    ->subcompile($this->getNode('variables'))
                    ->raw(')')
                ;
            }
        } else {
            if (null === $this->getNode('variables')) {
                $compiler->raw('array()');
            } else {
                $compiler->subcompile($this->getNode('variables'));
            }
        }
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a for node.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_For extends Twig_Node
{
    protected $loop;

    public function __construct(Twig_Node_Expression_AssignName $keyTarget, Twig_Node_Expression_AssignName $valueTarget, Twig_Node_Expression $seq, Twig_Node_Expression $ifexpr = null, Twig_NodeInterface $body, Twig_NodeInterface $else = null, $lineno, $tag = null)
    {
        $body = new Twig_Node(array($body, $this->loop = new Twig_Node_ForLoop($lineno, $tag)));

        if (null !== $ifexpr) {
            $body = new Twig_Node_If(new Twig_Node(array($ifexpr, $body)), null, $lineno, $tag);
        }

        parent::__construct(array('key_target' => $keyTarget, 'value_target' => $valueTarget, 'seq' => $seq, 'body' => $body, 'else' => $else), array('with_loop' => true, 'ifexpr' => null !== $ifexpr), $lineno, $tag);
    }

    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->addDebugInfo($this)
            // the (array) cast bypasses a PHP 5.2.6 bug
            ->write("\$context['_parent'] = (array) \$context;\n")
            ->write("\$context['_seq'] = twig_ensure_traversable(")
            ->subcompile($this->getNode('seq'))
            ->raw(");\n")
        ;

        if (null !== $this->getNode('else')) {
            $compiler->write("\$context['_iterated'] = false;\n");
        }

        if ($this->getAttribute('with_loop')) {
            $compiler
                ->write("\$context['loop'] = array(\n")
                ->write("  'parent' => \$context['_parent'],\n")
                ->write("  'index0' => 0,\n")
                ->write("  'index'  => 1,\n")
                ->write("  'first'  => true,\n")
                ->write(");\n")
            ;

            if (!$this->getAttribute('ifexpr')) {
                $compiler
                    ->write("if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_seq'] instanceof Countable)) {\n")
                    ->indent()
                    ->write("\$length = count(\$context['_seq']);\n")
                    ->write("\$context['loop']['revindex0'] = \$length - 1;\n")
                    ->write("\$context['loop']['revindex'] = \$length;\n")
                    ->write("\$context['loop']['length'] = \$length;\n")
                    ->write("\$context['loop']['last'] = 1 === \$length;\n")
                    ->outdent()
                    ->write("}\n")
                ;
            }
        }

        $this->loop->setAttribute('else', null !== $this->getNode('else'));
        $this->loop->setAttribute('with_loop', $this->getAttribute('with_loop'));
        $this->loop->setAttribute('ifexpr', $this->getAttribute('ifexpr'));

        $compiler
            ->write("foreach (\$context['_seq'] as ")
            ->subcompile($this->getNode('key_target'))
            ->raw(" => ")
            ->subcompile($this->getNode('value_target'))
            ->raw(") {\n")
            ->indent()
            ->subcompile($this->getNode('body'))
            ->outdent()
            ->write("}\n")
        ;

        if (null !== $this->getNode('else')) {
            $compiler
                ->write("if (!\$context['_iterated']) {\n")
                ->indent()
                ->subcompile($this->getNode('else'))
                ->outdent()
                ->write("}\n")
            ;
        }

        $compiler->write("\$_parent = \$context['_parent'];\n");

        // remove some "private" loop variables (needed for nested loops)
        $compiler->write('unset($context[\'_seq\'], $context[\'_iterated\'], $context[\''.$this->getNode('key_target')->getAttribute('name').'\'], $context[\''.$this->getNode('value_target')->getAttribute('name').'\'], $context[\'_parent\'], $context[\'loop\']);'."\n");

        // keep the values set in the inner context for variables defined in the outer context
        $compiler->write("\$context = array_intersect_key(\$context, \$_parent) + \$_parent;\n");
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2011 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a body node.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_Body extends Twig_Node
{
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2011 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a do node.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_Do extends Twig_Node
{
    public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null)
    {
        parent::__construct(array('expr' => $expr), array(), $lineno, $tag);
    }

    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->addDebugInfo($this)
            ->write('')
            ->subcompile($this->getNode('expr'))
            ->raw(";\n")
        ;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2011 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

class Twig_Node_SetTemp extends Twig_Node
{
    public function __construct($name, $lineno)
    {
        parent::__construct(array(), array('name' => $name), $lineno);
    }

    public function compile(Twig_Compiler $compiler)
    {
        $name = $this->getAttribute('name');
        $compiler
            ->addDebugInfo($this)
            ->write('if (isset($context[')
            ->string($name)
            ->raw('])) { $_')
            ->raw($name)
            ->raw('_ = $context[')
            ->repr($name)
            ->raw(']; } else { $_')
            ->raw($name)
            ->raw("_ = null; }\n")
        ;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a set node.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_Set extends Twig_Node
{
    public function __construct($capture, Twig_NodeInterface $names, Twig_NodeInterface $values, $lineno, $tag = null)
    {
        parent::__construct(array('names' => $names, 'values' => $values), array('capture' => $capture, 'safe' => false), $lineno, $tag);

        /*
         * Optimizes the node when capture is used for a large block of text.
         *
         * {% set foo %}foo{% endset %} is compiled to $context['foo'] = new Twig_Markup("foo");
         */
        if ($this->getAttribute('capture')) {
            $this->setAttribute('safe', true);

            $values = $this->getNode('values');
            if ($values instanceof Twig_Node_Text) {
                $this->setNode('values', new Twig_Node_Expression_Constant($values->getAttribute('data'), $values->getLine()));
                $this->setAttribute('capture', false);
            }
        }
    }

    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        $compiler->addDebugInfo($this);

        if (count($this->getNode('names')) > 1) {
            $compiler->write('list(');
            foreach ($this->getNode('names') as $idx => $node) {
                if ($idx) {
                    $compiler->raw(', ');
                }

                $compiler->subcompile($node);
            }
            $compiler->raw(')');
        } else {
            if ($this->getAttribute('capture')) {
                $compiler
                    ->write("ob_start();\n")
                    ->subcompile($this->getNode('values'))
                ;
            }

            $compiler->subcompile($this->getNode('names'), false);

            if ($this->getAttribute('capture')) {
                $compiler->raw(" = ('' === \$tmp = ob_get_clean()) ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset())");
            }
        }

        if (!$this->getAttribute('capture')) {
            $compiler->raw(' = ');

            if (count($this->getNode('names')) > 1) {
                $compiler->write('array(');
                foreach ($this->getNode('values') as $idx => $value) {
                    if ($idx) {
                        $compiler->raw(', ');
                    }

                    $compiler->subcompile($value);
                }
                $compiler->raw(')');
            } else {
                if ($this->getAttribute('safe')) {
                    $compiler
                        ->raw("('' === \$tmp = ")
                        ->subcompile($this->getNode('values'))
                        ->raw(") ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset())")
                    ;
                } else {
                    $compiler->subcompile($this->getNode('values'));
                }
            }
        }

        $compiler->raw(";\n");
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a block node.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_Block extends Twig_Node
{
    public function __construct($name, Twig_NodeInterface $body, $lineno, $tag = null)
    {
        parent::__construct(array('body' => $body), array('name' => $name), $lineno, $tag);
    }

    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->addDebugInfo($this)
            ->write(sprintf("public function block_%s(\$context, array \$blocks = array())\n", $this->getAttribute('name')), "{\n")
            ->indent()
        ;

        $compiler
            ->subcompile($this->getNode('body'))
            ->outdent()
            ->write("}\n\n")
        ;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Twig_Node_SandboxedPrint adds a check for the __toString() method
 * when the variable is an object and the sandbox is activated.
 *
 * When there is a simple Print statement, like {{ article }},
 * and if the sandbox is enabled, we need to check that the __toString()
 * method is allowed if 'article' is an object.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_SandboxedPrint extends Twig_Node_Print
{
    public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null)
    {
        parent::__construct($expr, $lineno, $tag);
    }

    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->addDebugInfo($this)
            ->write('echo $this->env->getExtension(\'sandbox\')->ensureToStringAllowed(')
            ->subcompile($this->getNode('expr'))
            ->raw(");\n")
        ;
    }

    /**
     * Removes node filters.
     *
     * This is mostly needed when another visitor adds filters (like the escaper one).
     *
     * @param Twig_Node $node A Node
     */
    protected function removeNodeFilter($node)
    {
        if ($node instanceof Twig_Node_Expression_Filter) {
            return $this->removeNodeFilter($node->getNode('node'));
        }

        return $node;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a macro node.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_Macro extends Twig_Node
{
    public function __construct($name, Twig_NodeInterface $body, Twig_NodeInterface $arguments, $lineno, $tag = null)
    {
        parent::__construct(array('body' => $body, 'arguments' => $arguments), array('name' => $name), $lineno, $tag);
    }

    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->addDebugInfo($this)
            ->write(sprintf("public function get%s(", $this->getAttribute('name')))
        ;

        $count = count($this->getNode('arguments'));
        $pos = 0;
        foreach ($this->getNode('arguments') as $name => $default) {
            $compiler
                ->raw('$_'.$name.' = ')
                ->subcompile($default)
            ;

            if (++$pos < $count) {
                $compiler->raw(', ');
            }
        }

        $compiler
            ->raw(")\n")
            ->write("{\n")
            ->indent()
        ;

        if (!count($this->getNode('arguments'))) {
            $compiler->write("\$context = \$this->env->getGlobals();\n\n");
        } else {
            $compiler
                ->write("\$context = \$this->env->mergeGlobals(array(\n")
                ->indent()
            ;

            foreach ($this->getNode('arguments') as $name => $default) {
                $compiler
                    ->write('')
                    ->string($name)
                    ->raw(' => $_'.$name)
                    ->raw(",\n")
                ;
            }

            $compiler
                ->outdent()
                ->write("));\n\n")
            ;
        }

        $compiler
            ->write("\$blocks = array();\n\n")
            ->write("ob_start();\n")
            ->write("try {\n")
            ->indent()
            ->subcompile($this->getNode('body'))
            ->outdent()
            ->write("} catch (Exception \$e) {\n")
            ->indent()
            ->write("ob_end_clean();\n\n")
            ->write("throw \$e;\n")
            ->outdent()
            ->write("}\n\n")
            ->write("return ('' === \$tmp = ob_get_clean()) ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset());\n")
            ->outdent()
            ->write("}\n\n")
        ;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Array extends Twig_Node_Expression
{
    protected $index;

    public function __construct(array $elements, $lineno)
    {
        parent::__construct($elements, array(), $lineno);

        $this->index = -1;
        foreach ($this->getKeyValuePairs() as $pair) {
            if ($pair['key'] instanceof Twig_Node_Expression_Constant && ctype_digit((string) $pair['key']->getAttribute('value')) && $pair['key']->getAttribute('value') > $this->index) {
                $this->index = $pair['key']->getAttribute('value');
            }
        }
    }

    public function getKeyValuePairs()
    {
        $pairs = array();

        foreach (array_chunk($this->nodes, 2) as $pair) {
            $pairs[] = array(
                'key' => $pair[0],
                'value' => $pair[1],
            );
        }

        return $pairs;
    }

    public function hasElement(Twig_Node_Expression $key)
    {
        foreach ($this->getKeyValuePairs() as $pair) {
            // we compare the string representation of the keys
            // to avoid comparing the line numbers which are not relevant here.
            if ((string) $key == (string) $pair['key']) {
                return true;
            }
        }

        return false;
    }

    public function addElement(Twig_Node_Expression $value, Twig_Node_Expression $key = null)
    {
        if (null === $key) {
            $key = new Twig_Node_Expression_Constant(++$this->index, $value->getLine());
        }

        array_push($this->nodes, $key, $value);
    }

    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        $compiler->raw('array(');
        $first = true;
        foreach ($this->getKeyValuePairs() as $pair) {
            if (!$first) {
                $compiler->raw(', ');
            }
            $first = false;

            $compiler
                ->subcompile($pair['key'])
                ->raw(' => ')
                ->subcompile($pair['value'])
            ;
        }
        $compiler->raw(')');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a block call node.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_Expression_BlockReference extends Twig_Node_Expression
{
    public function __construct(Twig_NodeInterface $name, $asString = false, $lineno, $tag = null)
    {
        parent::__construct(array('name' => $name), array('as_string' => $asString, 'output' => false), $lineno, $tag);
    }

    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        if ($this->getAttribute('as_string')) {
            $compiler->raw('(string) ');
        }

        if ($this->getAttribute('output')) {
            $compiler
                ->addDebugInfo($this)
                ->write("\$this->displayBlock(")
                ->subcompile($this->getNode('name'))
                ->raw(", \$context, \$blocks);\n")
            ;
        } else {
            $compiler
                ->raw("\$this->renderBlock(")
                ->subcompile($this->getNode('name'))
                ->raw(", \$context, \$blocks)")
            ;
        }
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a parent node.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_Expression_Parent extends Twig_Node_Expression
{
    public function __construct($name, $lineno, $tag = null)
    {
        parent::__construct(array(), array('output' => false, 'name' => $name), $lineno, $tag);
    }

    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        if ($this->getAttribute('output')) {
            $compiler
                ->addDebugInfo($this)
                ->write("\$this->displayParentBlock(")
                ->string($this->getAttribute('name'))
                ->raw(", \$context, \$blocks);\n")
            ;
        } else {
            $compiler
                ->raw("\$this->renderParentBlock(")
                ->string($this->getAttribute('name'))
                ->raw(", \$context, \$blocks)")
            ;
        }
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
abstract class Twig_Node_Expression_Binary extends Twig_Node_Expression
{
    public function __construct(Twig_NodeInterface $left, Twig_NodeInterface $right, $lineno)
    {
        parent::__construct(array('left' => $left, 'right' => $right), array(), $lineno);
    }

    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->raw('(')
            ->subcompile($this->getNode('left'))
            ->raw(' ')
        ;
        $this->operator($compiler);
        $compiler
            ->raw(' ')
            ->subcompile($this->getNode('right'))
            ->raw(')')
        ;
    }

    abstract public function operator(Twig_Compiler $compiler);
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Constant extends Twig_Node_Expression
{
    public function __construct($value, $lineno)
    {
        parent::__construct(array(), array('value' => $value), $lineno);
    }

    public function compile(Twig_Compiler $compiler)
    {
        $compiler->repr($this->getAttribute('value'));
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2011 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Returns the value or the default value when it is undefined or empty.
 *
 * <pre>
 *  {{ var.foo|default('foo item on var is not defined') }}
 * </pre>
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_Expression_Filter_Default extends Twig_Node_Expression_Filter
{
    public function __construct(Twig_NodeInterface $node, Twig_Node_Expression_Constant $filterName, Twig_NodeInterface $arguments, $lineno, $tag = null)
    {
        $default = new Twig_Node_Expression_Filter($node, new Twig_Node_Expression_Constant('default', $node->getLine()), $arguments, $node->getLine());

        if ('default' === $filterName->getAttribute('value') && ($node instanceof Twig_Node_Expression_Name || $node instanceof Twig_Node_Expression_GetAttr)) {
            $test = new Twig_Node_Expression_Test_Defined(clone $node, 'defined', new Twig_Node(), $node->getLine());
            $false = count($arguments) ? $arguments->getNode(0) : new Twig_Node_Expression_Constant('', $node->getLine());

            $node = new Twig_Node_Expression_Conditional($test, $default, $false, $node->getLine());
        } else {
            $node = $default;
        }

        parent::__construct($node, $filterName, $arguments, $lineno, $tag);
    }

    public function compile(Twig_Compiler $compiler)
    {
        $compiler->subcompile($this->getNode('node'));
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2011 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Checks if a number is odd.
 *
 * <pre>
 *  {{ var is odd }}
 * </pre>
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_Expression_Test_Odd extends Twig_Node_Expression_Test
{
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->raw('(')
            ->subcompile($this->getNode('node'))
            ->raw(' % 2 == 1')
            ->raw(')')
        ;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2011 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Checks if a variable is the exact same value as a constant.
 *
 * <pre>
 *  {% if post.status is constant('Post::PUBLISHED') %}
 *    the status attribute is exactly the same as Post::PUBLISHED
 *  {% endif %}
 * </pre>
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_Expression_Test_Constant extends Twig_Node_Expression_Test
{
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->raw('(')
            ->subcompile($this->getNode('node'))
            ->raw(' === constant(')
        ;

        if ($this->getNode('arguments')->hasNode(1)) {
            $compiler
                ->raw('get_class(')
                ->subcompile($this->getNode('arguments')->getNode(1))
                ->raw(')."::".')
            ;
        }

        $compiler
            ->subcompile($this->getNode('arguments')->getNode(0))
            ->raw('))')
        ;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2011 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Checks if a variable is divisible by a number.
 *
 * <pre>
 *  {% if loop.index is divisibleby(3) %}
 * </pre>
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_Expression_Test_Divisibleby extends Twig_Node_Expression_Test
{
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->raw('(0 == ')
            ->subcompile($this->getNode('node'))
            ->raw(' % ')
            ->subcompile($this->getNode('arguments')->getNode(0))
            ->raw(')')
        ;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2011 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Checks that a variable is null.
 *
 * <pre>
 *  {{ var is none }}
 * </pre>
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_Expression_Test_Null extends Twig_Node_Expression_Test
{
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->raw('(null === ')
            ->subcompile($this->getNode('node'))
            ->raw(')')
        ;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2011 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Checks if a number is even.
 *
 * <pre>
 *  {{ var is even }}
 * </pre>
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_Expression_Test_Even extends Twig_Node_Expression_Test
{
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->raw('(')
            ->subcompile($this->getNode('node'))
            ->raw(' % 2 == 0')
            ->raw(')')
        ;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2011 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Checks if a variable is the same as another one (=== in PHP).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_Expression_Test_Sameas extends Twig_Node_Expression_Test
{
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->raw('(')
            ->subcompile($this->getNode('node'))
            ->raw(' === ')
            ->subcompile($this->getNode('arguments')->getNode(0))
            ->raw(')')
        ;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2011 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Checks if a variable is defined in the current context.
 *
 * <pre>
 * {# defined works with variable names and variable attributes #}
 * {% if foo is defined %}
 *     {# ... #}
 * {% endif %}
 * </pre>
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_Expression_Test_Defined extends Twig_Node_Expression_Test
{
    public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno)
    {
        parent::__construct($node, $name, $arguments, $lineno);

        if ($node instanceof Twig_Node_Expression_Name) {
            $node->setAttribute('is_defined_test', true);
        } elseif ($node instanceof Twig_Node_Expression_GetAttr) {
            $node->setAttribute('is_defined_test', true);

            $this->changeIgnoreStrictCheck($node);
        } else {
            throw new Twig_Error_Syntax('The "defined" test only works with simple variables', $this->getLine());
        }
    }

    protected function changeIgnoreStrictCheck(Twig_Node_Expression_GetAttr $node)
    {
        $node->setAttribute('ignore_strict_check', true);

        if ($node->getNode('node') instanceof Twig_Node_Expression_GetAttr) {
            $this->changeIgnoreStrictCheck($node->getNode('node'));
        }
    }

    public function compile(Twig_Compiler $compiler)
    {
        $compiler->subcompile($this->getNode('node'));
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Binary_BitwiseXor extends Twig_Node_Expression_Binary
{
    public function operator(Twig_Compiler $compiler)
    {
        return $compiler->raw('^');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Binary_LessEqual extends Twig_Node_Expression_Binary
{
    public function operator(Twig_Compiler $compiler)
    {
        return $compiler->raw('<=');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Binary_Power extends Twig_Node_Expression_Binary
{
    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->raw('pow(')
            ->subcompile($this->getNode('left'))
            ->raw(', ')
            ->subcompile($this->getNode('right'))
            ->raw(')')
        ;
    }

    public function operator(Twig_Compiler $compiler)
    {
        return $compiler->raw('**');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Binary_Mod extends Twig_Node_Expression_Binary
{
    public function operator(Twig_Compiler $compiler)
    {
        return $compiler->raw('%');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Binary_NotIn extends Twig_Node_Expression_Binary
{
    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->raw('!twig_in_filter(')
            ->subcompile($this->getNode('left'))
            ->raw(', ')
            ->subcompile($this->getNode('right'))
            ->raw(')')
        ;
    }

    public function operator(Twig_Compiler $compiler)
    {
        return $compiler->raw('not in');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Binary_FloorDiv extends Twig_Node_Expression_Binary
{
    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        $compiler->raw('intval(floor(');
        parent::compile($compiler);
        $compiler->raw('))');
    }

    public function operator(Twig_Compiler $compiler)
    {
        return $compiler->raw('/');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2013 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Binary_Matches extends Twig_Node_Expression_Binary
{
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->raw('preg_match(')
            ->subcompile($this->getNode('right'))
            ->raw(', ')
            ->subcompile($this->getNode('left'))
            ->raw(')')
        ;
    }

    public function operator(Twig_Compiler $compiler)
    {
        return $compiler->raw('');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Binary_Div extends Twig_Node_Expression_Binary
{
    public function operator(Twig_Compiler $compiler)
    {
        return $compiler->raw('/');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Binary_Mul extends Twig_Node_Expression_Binary
{
    public function operator(Twig_Compiler $compiler)
    {
        return $compiler->raw('*');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Binary_Equal extends Twig_Node_Expression_Binary
{
    public function operator(Twig_Compiler $compiler)
    {
        return $compiler->raw('==');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Binary_And extends Twig_Node_Expression_Binary
{
    public function operator(Twig_Compiler $compiler)
    {
        return $compiler->raw('&&');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Binary_Add extends Twig_Node_Expression_Binary
{
    public function operator(Twig_Compiler $compiler)
    {
        return $compiler->raw('+');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Binary_Or extends Twig_Node_Expression_Binary
{
    public function operator(Twig_Compiler $compiler)
    {
        return $compiler->raw('||');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Binary_In extends Twig_Node_Expression_Binary
{
    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->raw('twig_in_filter(')
            ->subcompile($this->getNode('left'))
            ->raw(', ')
            ->subcompile($this->getNode('right'))
            ->raw(')')
        ;
    }

    public function operator(Twig_Compiler $compiler)
    {
        return $compiler->raw('in');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Binary_GreaterEqual extends Twig_Node_Expression_Binary
{
    public function operator(Twig_Compiler $compiler)
    {
        return $compiler->raw('>=');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Binary_Greater extends Twig_Node_Expression_Binary
{
    public function operator(Twig_Compiler $compiler)
    {
        return $compiler->raw('>');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Binary_Sub extends Twig_Node_Expression_Binary
{
    public function operator(Twig_Compiler $compiler)
    {
        return $compiler->raw('-');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Binary_Concat extends Twig_Node_Expression_Binary
{
    public function operator(Twig_Compiler $compiler)
    {
        return $compiler->raw('.');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2013 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Binary_EndsWith extends Twig_Node_Expression_Binary
{
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->raw('(0 === substr_compare(')
            ->subcompile($this->getNode('left'))
            ->raw(', ')
            ->subcompile($this->getNode('right'))
            ->raw(', -strlen(')
            ->subcompile($this->getNode('right'))
            ->raw(')))')
        ;
    }

    public function operator(Twig_Compiler $compiler)
    {
        return $compiler->raw('');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2013 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Binary_StartsWith extends Twig_Node_Expression_Binary
{
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->raw('(0 === strpos(')
            ->subcompile($this->getNode('left'))
            ->raw(', ')
            ->subcompile($this->getNode('right'))
            ->raw('))')
        ;
    }

    public function operator(Twig_Compiler $compiler)
    {
        return $compiler->raw('');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Binary_BitwiseOr extends Twig_Node_Expression_Binary
{
    public function operator(Twig_Compiler $compiler)
    {
        return $compiler->raw('|');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Binary_BitwiseAnd extends Twig_Node_Expression_Binary
{
    public function operator(Twig_Compiler $compiler)
    {
        return $compiler->raw('&');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Binary_Less extends Twig_Node_Expression_Binary
{
    public function operator(Twig_Compiler $compiler)
    {
        return $compiler->raw('<');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Binary_NotEqual extends Twig_Node_Expression_Binary
{
    public function operator(Twig_Compiler $compiler)
    {
        return $compiler->raw('!=');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Binary_Range extends Twig_Node_Expression_Binary
{
    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->raw('range(')
            ->subcompile($this->getNode('left'))
            ->raw(', ')
            ->subcompile($this->getNode('right'))
            ->raw(')')
        ;
    }

    public function operator(Twig_Compiler $compiler)
    {
        return $compiler->raw('..');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Function extends Twig_Node_Expression_Call
{
    public function __construct($name, Twig_NodeInterface $arguments, $lineno)
    {
        parent::__construct(array('arguments' => $arguments), array('name' => $name), $lineno);
    }

    public function compile(Twig_Compiler $compiler)
    {
        $name = $this->getAttribute('name');
        $function = $compiler->getEnvironment()->getFunction($name);

        $this->setAttribute('name', $name);
        $this->setAttribute('type', 'function');
        $this->setAttribute('thing', $function);
        $this->setAttribute('needs_environment', $function->needsEnvironment());
        $this->setAttribute('needs_context', $function->needsContext());
        $this->setAttribute('arguments', $function->getArguments());
        if ($function instanceof Twig_FunctionCallableInterface || $function instanceof Twig_SimpleFunction) {
            $this->setAttribute('callable', $function->getCallable());
        }

        $this->compileCallable($compiler);
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_GetAttr extends Twig_Node_Expression
{
    public function __construct(Twig_Node_Expression $node, Twig_Node_Expression $attribute, Twig_Node_Expression_Array $arguments, $type, $lineno)
    {
        parent::__construct(array('node' => $node, 'attribute' => $attribute, 'arguments' => $arguments), array('type' => $type, 'is_defined_test' => false, 'ignore_strict_check' => false, 'disable_c_ext' => false), $lineno);
    }

    public function compile(Twig_Compiler $compiler)
    {
        if (function_exists('twig_template_get_attributes') && !$this->getAttribute('disable_c_ext')) {
            $compiler->raw('twig_template_get_attributes($this, ');
        } else {
            $compiler->raw('$this->getAttribute(');
        }

        if ($this->getAttribute('ignore_strict_check')) {
            $this->getNode('node')->setAttribute('ignore_strict_check', true);
        }

        $compiler->subcompile($this->getNode('node'));

        $compiler->raw(', ')->subcompile($this->getNode('attribute'));

        if (count($this->getNode('arguments')) || Twig_Template::ANY_CALL !== $this->getAttribute('type') || $this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) {
            $compiler->raw(', ')->subcompile($this->getNode('arguments'));

            if (Twig_Template::ANY_CALL !== $this->getAttribute('type') || $this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) {
                $compiler->raw(', ')->repr($this->getAttribute('type'));
            }

            if ($this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) {
                $compiler->raw(', '.($this->getAttribute('is_defined_test') ? 'true' : 'false'));
            }

            if ($this->getAttribute('ignore_strict_check')) {
                $compiler->raw(', '.($this->getAttribute('ignore_strict_check') ? 'true' : 'false'));
            }
        }

        $compiler->raw(')');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Name extends Twig_Node_Expression
{
    protected $specialVars = array(
        '_self'    => '$this',
        '_context' => '$context',
        '_charset' => '$this->env->getCharset()',
    );

    public function __construct($name, $lineno)
    {
        parent::__construct(array(), array('name' => $name, 'is_defined_test' => false, 'ignore_strict_check' => false, 'always_defined' => false), $lineno);
    }

    public function compile(Twig_Compiler $compiler)
    {
        $name = $this->getAttribute('name');

        if ($this->getAttribute('is_defined_test')) {
            if ($this->isSpecial()) {
                $compiler->repr(true);
            } else {
                $compiler->raw('array_key_exists(')->repr($name)->raw(', $context)');
            }
        } elseif ($this->isSpecial()) {
            $compiler->raw($this->specialVars[$name]);
        } elseif ($this->getAttribute('always_defined')) {
            $compiler
                ->raw('$context[')
                ->string($name)
                ->raw(']')
            ;
        } else {
            // remove the non-PHP 5.4 version when PHP 5.3 support is dropped
            // as the non-optimized version is just a workaround for slow ternary operator
            // when the context has a lot of variables
            if (version_compare(phpversion(), '5.4.0RC1', '>=')) {
                // PHP 5.4 ternary operator performance was optimized
                $compiler
                    ->raw('(isset($context[')
                    ->string($name)
                    ->raw(']) ? $context[')
                    ->string($name)
                    ->raw('] : ')
                ;

                if ($this->getAttribute('ignore_strict_check') || !$compiler->getEnvironment()->isStrictVariables()) {
                    $compiler->raw('null)');
                } else {
                    $compiler->raw('$this->getContext($context, ')->string($name)->raw('))');
                }
            } else {
                $compiler
                    ->raw('$this->getContext($context, ')
                    ->string($name)
                ;

                if ($this->getAttribute('ignore_strict_check')) {
                    $compiler->raw(', true');
                }

                $compiler
                    ->raw(')')
                ;
            }
        }
    }

    public function isSpecial()
    {
        return isset($this->specialVars[$this->getAttribute('name')]);
    }

    public function isSimple()
    {
        return !$this->isSpecial() && !$this->getAttribute('is_defined_test');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Filter extends Twig_Node_Expression_Call
{
    public function __construct(Twig_NodeInterface $node, Twig_Node_Expression_Constant $filterName, Twig_NodeInterface $arguments, $lineno, $tag = null)
    {
        parent::__construct(array('node' => $node, 'filter' => $filterName, 'arguments' => $arguments), array(), $lineno, $tag);
    }

    public function compile(Twig_Compiler $compiler)
    {
        $name = $this->getNode('filter')->getAttribute('value');
        $filter = $compiler->getEnvironment()->getFilter($name);

        $this->setAttribute('name', $name);
        $this->setAttribute('type', 'filter');
        $this->setAttribute('thing', $filter);
        $this->setAttribute('needs_environment', $filter->needsEnvironment());
        $this->setAttribute('needs_context', $filter->needsContext());
        $this->setAttribute('arguments', $filter->getArguments());
        if ($filter instanceof Twig_FilterCallableInterface || $filter instanceof Twig_SimpleFilter) {
            $this->setAttribute('callable', $filter->getCallable());
        }

        $this->compileCallable($compiler);
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2012 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
{
    protected function compileCallable(Twig_Compiler $compiler)
    {
        $callable = $this->getAttribute('callable');

        $closingParenthesis = false;
        if ($callable) {
            if (is_string($callable)) {
                $compiler->raw($callable);
            } elseif (is_array($callable) && $callable[0] instanceof Twig_ExtensionInterface) {
                $compiler->raw(sprintf('$this->env->getExtension(\'%s\')->%s', $callable[0]->getName(), $callable[1]));
            } else {
                $type = ucfirst($this->getAttribute('type'));
                $compiler->raw(sprintf('call_user_func_array($this->env->get%s(\'%s\')->getCallable(), array', $type, $this->getAttribute('name')));
                $closingParenthesis = true;
            }
        } else {
            $compiler->raw($this->getAttribute('thing')->compile());
        }

        $this->compileArguments($compiler);

        if ($closingParenthesis) {
            $compiler->raw(')');
        }
    }

    protected function compileArguments(Twig_Compiler $compiler)
    {
        $compiler->raw('(');

        $first = true;

        if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) {
            $compiler->raw('$this->env');
            $first = false;
        }

        if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) {
            if (!$first) {
                $compiler->raw(', ');
            }
            $compiler->raw('$context');
            $first = false;
        }

        if ($this->hasAttribute('arguments')) {
            foreach ($this->getAttribute('arguments') as $argument) {
                if (!$first) {
                    $compiler->raw(', ');
                }
                $compiler->string($argument);
                $first = false;
            }
        }

        if ($this->hasNode('node')) {
            if (!$first) {
                $compiler->raw(', ');
            }
            $compiler->subcompile($this->getNode('node'));
            $first = false;
        }

        if ($this->hasNode('arguments') && null !== $this->getNode('arguments')) {
            $callable = $this->hasAttribute('callable') ? $this->getAttribute('callable') : null;

            $arguments = $this->getArguments($callable, $this->getNode('arguments'));

            foreach ($arguments as $node) {
                if (!$first) {
                    $compiler->raw(', ');
                }
                $compiler->subcompile($node);
                $first = false;
            }
        }

        $compiler->raw(')');
    }

    protected function getArguments($callable, $arguments)
    {
        $parameters = array();
        $named = false;
        foreach ($arguments as $name => $node) {
            if (!is_int($name)) {
                $named = true;
                $name = $this->normalizeName($name);
            } elseif ($named) {
                throw new Twig_Error_Syntax(sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $this->getAttribute('type'), $this->getAttribute('name')));
            }

            $parameters[$name] = $node;
        }

        if (!$named) {
            return $parameters;
        }

        if (!$callable) {
            throw new LogicException(sprintf('Named arguments are not supported for %s "%s".', $this->getAttribute('type'), $this->getAttribute('name')));
        }

        // manage named arguments
        if (is_array($callable)) {
            $r = new ReflectionMethod($callable[0], $callable[1]);
        } elseif (is_object($callable) && !$callable instanceof Closure) {
            $r = new ReflectionObject($callable);
            $r = $r->getMethod('__invoke');
        } else {
            $r = new ReflectionFunction($callable);
        }

        $definition = $r->getParameters();
        if ($this->hasNode('node')) {
            array_shift($definition);
        }
        if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) {
            array_shift($definition);
        }
        if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) {
            array_shift($definition);
        }
        if ($this->hasAttribute('arguments') && null !== $this->getAttribute('arguments')) {
            foreach ($this->getAttribute('arguments') as $argument) {
                array_shift($definition);
            }
        }

        $arguments = array();
        $pos = 0;
        foreach ($definition as $param) {
            $name = $this->normalizeName($param->name);

            if (array_key_exists($name, $parameters)) {
                if (array_key_exists($pos, $parameters)) {
                    throw new Twig_Error_Syntax(sprintf('Argument "%s" is defined twice for %s "%s".', $name, $this->getAttribute('type'), $this->getAttribute('name')));
                }

                $arguments[] = $parameters[$name];
                unset($parameters[$name]);
            } elseif (array_key_exists($pos, $parameters)) {
                $arguments[] = $parameters[$pos];
                unset($parameters[$pos]);
                ++$pos;
            } elseif ($param->isDefaultValueAvailable()) {
                $arguments[] = new Twig_Node_Expression_Constant($param->getDefaultValue(), -1);
            } elseif ($param->isOptional()) {
                break;
            } else {
                throw new Twig_Error_Syntax(sprintf('Value for argument "%s" is required for %s "%s".', $name, $this->getAttribute('type'), $this->getAttribute('name')));
            }
        }

        if (!empty($parameters)) {
            throw new Twig_Error_Syntax(sprintf('Unknown argument%s "%s" for %s "%s".', count($parameters) > 1 ? 's' : '' , implode('", "', array_keys($parameters)), $this->getAttribute('type'), $this->getAttribute('name')));
        }

        return $arguments;
    }

    protected function normalizeName($name)
    {
        return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), $name));
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Conditional extends Twig_Node_Expression
{
    public function __construct(Twig_Node_Expression $expr1, Twig_Node_Expression $expr2, Twig_Node_Expression $expr3, $lineno)
    {
        parent::__construct(array('expr1' => $expr1, 'expr2' => $expr2, 'expr3' => $expr3), array(), $lineno);
    }

    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->raw('((')
            ->subcompile($this->getNode('expr1'))
            ->raw(') ? (')
            ->subcompile($this->getNode('expr2'))
            ->raw(') : (')
            ->subcompile($this->getNode('expr3'))
            ->raw('))')
        ;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
abstract class Twig_Node_Expression_Unary extends Twig_Node_Expression
{
    public function __construct(Twig_NodeInterface $node, $lineno)
    {
        parent::__construct(array('node' => $node), array(), $lineno);
    }

    public function compile(Twig_Compiler $compiler)
    {
        $compiler->raw('(');
        $this->operator($compiler);
        $compiler
            ->subcompile($this->getNode('node'))
            ->raw(')')
        ;
    }

    abstract public function operator(Twig_Compiler $compiler);
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Test extends Twig_Node_Expression_Call
{
    public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno)
    {
        parent::__construct(array('node' => $node, 'arguments' => $arguments), array('name' => $name), $lineno);
    }

    public function compile(Twig_Compiler $compiler)
    {
        $name = $this->getAttribute('name');
        $test = $compiler->getEnvironment()->getTest($name);

        $this->setAttribute('name', $name);
        $this->setAttribute('type', 'test');
        $this->setAttribute('thing', $test);
        if ($test instanceof Twig_TestCallableInterface || $test instanceof Twig_SimpleTest) {
            $this->setAttribute('callable', $test->getCallable());
        }

        $this->compileCallable($compiler);
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

class Twig_Node_Expression_AssignName extends Twig_Node_Expression_Name
{
    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->raw('$context[')
            ->string($this->getAttribute('name'))
            ->raw(']')
        ;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Unary_Not extends Twig_Node_Expression_Unary
{
    public function operator(Twig_Compiler $compiler)
    {
        $compiler->raw('!');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Unary_Pos extends Twig_Node_Expression_Unary
{
    public function operator(Twig_Compiler $compiler)
    {
        $compiler->raw('+');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_Unary_Neg extends Twig_Node_Expression_Unary
{
    public function operator(Twig_Compiler $compiler)
    {
        $compiler->raw('-');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents an extension call node.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_Expression_ExtensionReference extends Twig_Node_Expression
{
    public function __construct($name, $lineno, $tag = null)
    {
        parent::__construct(array(), array('name' => $name), $lineno, $tag);
    }

    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        $compiler->raw(sprintf("\$this->env->getExtension('%s')", $this->getAttribute('name')));
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2011 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_TempName extends Twig_Node_Expression
{
    public function __construct($name, $lineno)
    {
        parent::__construct(array(), array('name' => $name), $lineno);
    }

    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->raw('$_')
            ->raw($this->getAttribute('name'))
            ->raw('_')
        ;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2012 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class Twig_Node_Expression_MethodCall extends Twig_Node_Expression
{
    public function __construct(Twig_Node_Expression $node, $method, Twig_Node_Expression_Array $arguments, $lineno)
    {
        parent::__construct(array('node' => $node, 'arguments' => $arguments), array('method' => $method, 'safe' => false), $lineno);

        if ($node instanceof Twig_Node_Expression_Name) {
            $node->setAttribute('always_defined', true);
        }
    }

    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->subcompile($this->getNode('node'))
            ->raw('->')
            ->raw($this->getAttribute('method'))
            ->raw('(')
        ;
        $first = true;
        foreach ($this->getNode('arguments')->getKeyValuePairs() as $pair) {
            if (!$first) {
                $compiler->raw(', ');
            }
            $first = false;

            $compiler->subcompile($pair['value']);
        }
        $compiler->raw(')');
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a sandbox node.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_Sandbox extends Twig_Node
{
    public function __construct(Twig_NodeInterface $body, $lineno, $tag = null)
    {
        parent::__construct(array('body' => $body), array(), $lineno, $tag);
    }

    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->addDebugInfo($this)
            ->write("\$sandbox = \$this->env->getExtension('sandbox');\n")
            ->write("if (!\$alreadySandboxed = \$sandbox->isSandboxed()) {\n")
            ->indent()
            ->write("\$sandbox->enableSandbox();\n")
            ->outdent()
            ->write("}\n")
            ->subcompile($this->getNode('body'))
            ->write("if (!\$alreadySandboxed) {\n")
            ->indent()
            ->write("\$sandbox->disableSandbox();\n")
            ->outdent()
            ->write("}\n")
        ;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2012 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents an embed node.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_Embed extends Twig_Node_Include
{
    // we don't inject the module to avoid node visitors to traverse it twice (as it will be already visited in the main module)
    public function __construct($filename, $index, Twig_Node_Expression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null)
    {
        parent::__construct(new Twig_Node_Expression_Constant('not_used', $lineno), $variables, $only, $ignoreMissing, $lineno, $tag);

        $this->setAttribute('filename', $filename);
        $this->setAttribute('index', $index);
    }

    protected function addGetTemplate(Twig_Compiler $compiler)
    {
        $compiler
            ->write("\$this->env->loadTemplate(")
            ->string($this->getAttribute('filename'))
            ->raw(', ')
            ->string($this->getAttribute('index'))
            ->raw(")")
        ;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Abstract class for all nodes that represents an expression.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Twig_Node_Expression extends Twig_Node
{
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2011 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a flush node.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Node_Flush extends Twig_Node
{
    public function __construct($lineno, $tag)
    {
        parent::__construct(array(), array(), $lineno, $tag);
    }

    /**
     * Compiles the node to PHP.
     *
     * @param Twig_Compiler A Twig_Compiler instance
     */
    public function compile(Twig_Compiler $compiler)
    {
        $compiler
            ->addDebugInfo($this)
            ->write("flush();\n")
        ;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Marks a content as safe.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Markup implements Countable
{
    protected $content;
    protected $charset;

    public function __construct($content, $charset)
    {
        $this->content = (string) $content;
        $this->charset = $charset;
    }

    public function __toString()
    {
        return $this->content;
    }

    public function count()
    {
        return function_exists('mb_get_info') ? mb_strlen($this->content, $this->charset) : strlen($this->content);
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 * (c) 2010 Arnaud Le Blanc
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Interface implemented by token parser brokers.
 *
 * Token parser brokers allows to implement custom logic in the process of resolving a token parser for a given tag name.
 *
 * @author Arnaud Le Blanc <arnaud.lb@gmail.com>
 * @deprecated since 1.12 (to be removed in 2.0)
 */
interface Twig_TokenParserBrokerInterface
{
    /**
     * Gets a TokenParser suitable for a tag.
     *
     * @param string $tag A tag name
     *
     * @return null|Twig_TokenParserInterface A Twig_TokenParserInterface or null if no suitable TokenParser was found
     */
    public function getTokenParser($tag);

    /**
     * Calls Twig_TokenParserInterface::setParser on all parsers the implementation knows of.
     *
     * @param Twig_ParserInterface $parser A Twig_ParserInterface interface
     */
    public function setParser(Twig_ParserInterface $parser);

    /**
     * Gets the Twig_ParserInterface.
     *
     * @return null|Twig_ParserInterface A Twig_ParserInterface instance or null
     */
    public function getParser();
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Lexes a template string.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Lexer implements Twig_LexerInterface
{
    protected $tokens;
    protected $code;
    protected $cursor;
    protected $lineno;
    protected $end;
    protected $state;
    protected $states;
    protected $brackets;
    protected $env;
    protected $filename;
    protected $options;
    protected $regexes;
    protected $position;
    protected $positions;
    protected $currentVarBlockLine;

    const STATE_DATA            = 0;
    const STATE_BLOCK           = 1;
    const STATE_VAR             = 2;
    const STATE_STRING          = 3;
    const STATE_INTERPOLATION   = 4;

    const REGEX_NAME            = '/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A';
    const REGEX_NUMBER          = '/[0-9]+(?:\.[0-9]+)?/A';
    const REGEX_STRING          = '/"([^#"\\\\]*(?:\\\\.[^#"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'/As';
    const REGEX_DQ_STRING_DELIM = '/"/A';
    const REGEX_DQ_STRING_PART  = '/[^#"\\\\]*(?:(?:\\\\.|#(?!\{))[^#"\\\\]*)*/As';
    const PUNCTUATION           = '()[]{}?:.,|';

    public function __construct(Twig_Environment $env, array $options = array())
    {
        $this->env = $env;

        $this->options = array_merge(array(
            'tag_comment'     => array('{#', '#}'),
            'tag_block'       => array('{%', '%}'),
            'tag_variable'    => array('{{', '}}'),
            'whitespace_trim' => '-',
            'interpolation'   => array('#{', '}'),
        ), $options);

        $this->regexes = array(
            'lex_var'             => '/\s*'.preg_quote($this->options['whitespace_trim'].$this->options['tag_variable'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_variable'][1], '/').'/A',
            'lex_block'           => '/\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')\n?/A',
            'lex_raw_data'        => '/('.preg_quote($this->options['tag_block'][0].$this->options['whitespace_trim'], '/').'|'.preg_quote($this->options['tag_block'][0], '/').')\s*(?:end%s)\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/s',
            'operator'            => $this->getOperatorRegex(),
            'lex_comment'         => '/(?:'.preg_quote($this->options['whitespace_trim'], '/').preg_quote($this->options['tag_comment'][1], '/').'\s*|'.preg_quote($this->options['tag_comment'][1], '/').')\n?/s',
            'lex_block_raw'       => '/\s*(raw|verbatim)\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/As',
            'lex_block_line'      => '/\s*line\s+(\d+)\s*'.preg_quote($this->options['tag_block'][1], '/').'/As',
            'lex_tokens_start'    => '/('.preg_quote($this->options['tag_variable'][0], '/').'|'.preg_quote($this->options['tag_block'][0], '/').'|'.preg_quote($this->options['tag_comment'][0], '/').')('.preg_quote($this->options['whitespace_trim'], '/').')?/s',
            'interpolation_start' => '/'.preg_quote($this->options['interpolation'][0], '/').'\s*/A',
            'interpolation_end'   => '/\s*'.preg_quote($this->options['interpolation'][1], '/').'/A',
        );
    }

    /**
     * {@inheritdoc}
     */
    public function tokenize($code, $filename = null)
    {
        if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) {
            $mbEncoding = mb_internal_encoding();
            mb_internal_encoding('ASCII');
        }

        $this->code = str_replace(array("\r\n", "\r"), "\n", $code);
        $this->filename = $filename;
        $this->cursor = 0;
        $this->lineno = 1;
        $this->end = strlen($this->code);
        $this->tokens = array();
        $this->state = self::STATE_DATA;
        $this->states = array();
        $this->brackets = array();
        $this->position = -1;

        // find all token starts in one go
        preg_match_all($this->regexes['lex_tokens_start'], $this->code, $matches, PREG_OFFSET_CAPTURE);
        $this->positions = $matches;

        while ($this->cursor < $this->end) {
            // dispatch to the lexing functions depending
            // on the current state
            switch ($this->state) {
                case self::STATE_DATA:
                    $this->lexData();
                    break;

                case self::STATE_BLOCK:
                    $this->lexBlock();
                    break;

                case self::STATE_VAR:
                    $this->lexVar();
                    break;

                case self::STATE_STRING:
                    $this->lexString();
                    break;

                case self::STATE_INTERPOLATION:
                    $this->lexInterpolation();
                    break;
            }
        }

        $this->pushToken(Twig_Token::EOF_TYPE);

        if (!empty($this->brackets)) {
            list($expect, $lineno) = array_pop($this->brackets);
            throw new Twig_Error_Syntax(sprintf('Unclosed "%s"', $expect), $lineno, $this->filename);
        }

        if (isset($mbEncoding)) {
            mb_internal_encoding($mbEncoding);
        }

        return new Twig_TokenStream($this->tokens, $this->filename);
    }

    protected function lexData()
    {
        // if no matches are left we return the rest of the template as simple text token
        if ($this->position == count($this->positions[0]) - 1) {
            $this->pushToken(Twig_Token::TEXT_TYPE, substr($this->code, $this->cursor));
            $this->cursor = $this->end;

            return;
        }

        // Find the first token after the current cursor
        $position = $this->positions[0][++$this->position];
        while ($position[1] < $this->cursor) {
            if ($this->position == count($this->positions[0]) - 1) {
                return;
            }
            $position = $this->positions[0][++$this->position];
        }

        // push the template text first
        $text = $textContent = substr($this->code, $this->cursor, $position[1] - $this->cursor);
        if (isset($this->positions[2][$this->position][0])) {
            $text = rtrim($text);
        }
        $this->pushToken(Twig_Token::TEXT_TYPE, $text);
        $this->moveCursor($textContent.$position[0]);

        switch ($this->positions[1][$this->position][0]) {
            case $this->options['tag_comment'][0]:
                $this->lexComment();
                break;

            case $this->options['tag_block'][0]:
                // raw data?
                if (preg_match($this->regexes['lex_block_raw'], $this->code, $match, null, $this->cursor)) {
                    $this->moveCursor($match[0]);
                    $this->lexRawData($match[1]);
                // {% line \d+ %}
                } elseif (preg_match($this->regexes['lex_block_line'], $this->code, $match, null, $this->cursor)) {
                    $this->moveCursor($match[0]);
                    $this->lineno = (int) $match[1];
                } else {
                    $this->pushToken(Twig_Token::BLOCK_START_TYPE);
                    $this->pushState(self::STATE_BLOCK);
                    $this->currentVarBlockLine = $this->lineno;
                }
                break;

            case $this->options['tag_variable'][0]:
                $this->pushToken(Twig_Token::VAR_START_TYPE);
                $this->pushState(self::STATE_VAR);
                $this->currentVarBlockLine = $this->lineno;
                break;
        }
    }

    protected function lexBlock()
    {
        if (empty($this->brackets) && preg_match($this->regexes['lex_block'], $this->code, $match, null, $this->cursor)) {
            $this->pushToken(Twig_Token::BLOCK_END_TYPE);
            $this->moveCursor($match[0]);
            $this->popState();
        } else {
            $this->lexExpression();
        }
    }

    protected function lexVar()
    {
        if (empty($this->brackets) && preg_match($this->regexes['lex_var'], $this->code, $match, null, $this->cursor)) {
            $this->pushToken(Twig_Token::VAR_END_TYPE);
            $this->moveCursor($match[0]);
            $this->popState();
        } else {
            $this->lexExpression();
        }
    }

    protected function lexExpression()
    {
        // whitespace
        if (preg_match('/\s+/A', $this->code, $match, null, $this->cursor)) {
            $this->moveCursor($match[0]);

            if ($this->cursor >= $this->end) {
                throw new Twig_Error_Syntax(sprintf('Unclosed "%s"', $this->state === self::STATE_BLOCK ? 'block' : 'variable'), $this->currentVarBlockLine, $this->filename);
            }
        }

        // operators
        if (preg_match($this->regexes['operator'], $this->code, $match, null, $this->cursor)) {
            $this->pushToken(Twig_Token::OPERATOR_TYPE, preg_replace('/\s+/', ' ', $match[0]));
            $this->moveCursor($match[0]);
        }
        // names
        elseif (preg_match(self::REGEX_NAME, $this->code, $match, null, $this->cursor)) {
            $this->pushToken(Twig_Token::NAME_TYPE, $match[0]);
            $this->moveCursor($match[0]);
        }
        // numbers
        elseif (preg_match(self::REGEX_NUMBER, $this->code, $match, null, $this->cursor)) {
            $number = (float) $match[0];  // floats
            if (ctype_digit($match[0]) && $number <= PHP_INT_MAX) {
                $number = (int) $match[0]; // integers lower than the maximum
            }
            $this->pushToken(Twig_Token::NUMBER_TYPE, $number);
            $this->moveCursor($match[0]);
        }
        // punctuation
        elseif (false !== strpos(self::PUNCTUATION, $this->code[$this->cursor])) {
            // opening bracket
            if (false !== strpos('([{', $this->code[$this->cursor])) {
                $this->brackets[] = array($this->code[$this->cursor], $this->lineno);
            }
            // closing bracket
            elseif (false !== strpos(')]}', $this->code[$this->cursor])) {
                if (empty($this->brackets)) {
                    throw new Twig_Error_Syntax(sprintf('Unexpected "%s"', $this->code[$this->cursor]), $this->lineno, $this->filename);
                }

                list($expect, $lineno) = array_pop($this->brackets);
                if ($this->code[$this->cursor] != strtr($expect, '([{', ')]}')) {
                    throw new Twig_Error_Syntax(sprintf('Unclosed "%s"', $expect), $lineno, $this->filename);
                }
            }

            $this->pushToken(Twig_Token::PUNCTUATION_TYPE, $this->code[$this->cursor]);
            ++$this->cursor;
        }
        // strings
        elseif (preg_match(self::REGEX_STRING, $this->code, $match, null, $this->cursor)) {
            $this->pushToken(Twig_Token::STRING_TYPE, stripcslashes(substr($match[0], 1, -1)));
            $this->moveCursor($match[0]);
        }
        // opening double quoted string
        elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, null, $this->cursor)) {
            $this->brackets[] = array('"', $this->lineno);
            $this->pushState(self::STATE_STRING);
            $this->moveCursor($match[0]);
        }
        // unlexable
        else {
            throw new Twig_Error_Syntax(sprintf('Unexpected character "%s"', $this->code[$this->cursor]), $this->lineno, $this->filename);
        }
    }

    protected function lexRawData($tag)
    {
        if (!preg_match(str_replace('%s', $tag, $this->regexes['lex_raw_data']), $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) {
            throw new Twig_Error_Syntax(sprintf('Unexpected end of file: Unclosed "%s" block', $tag), $this->lineno, $this->filename);
        }

        $text = substr($this->code, $this->cursor, $match[0][1] - $this->cursor);
        $this->moveCursor($text.$match[0][0]);

        if (false !== strpos($match[1][0], $this->options['whitespace_trim'])) {
            $text = rtrim($text);
        }

        $this->pushToken(Twig_Token::TEXT_TYPE, $text);
    }

    protected function lexComment()
    {
        if (!preg_match($this->regexes['lex_comment'], $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) {
            throw new Twig_Error_Syntax('Unclosed comment', $this->lineno, $this->filename);
        }

        $this->moveCursor(substr($this->code, $this->cursor, $match[0][1] - $this->cursor).$match[0][0]);
    }

    protected function lexString()
    {
        if (preg_match($this->regexes['interpolation_start'], $this->code, $match, null, $this->cursor)) {
            $this->brackets[] = array($this->options['interpolation'][0], $this->lineno);
            $this->pushToken(Twig_Token::INTERPOLATION_START_TYPE);
            $this->moveCursor($match[0]);
            $this->pushState(self::STATE_INTERPOLATION);

        } elseif (preg_match(self::REGEX_DQ_STRING_PART, $this->code, $match, null, $this->cursor) && strlen($match[0]) > 0) {
            $this->pushToken(Twig_Token::STRING_TYPE, stripcslashes($match[0]));
            $this->moveCursor($match[0]);

        } elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, null, $this->cursor)) {

            list($expect, $lineno) = array_pop($this->brackets);
            if ($this->code[$this->cursor] != '"') {
                throw new Twig_Error_Syntax(sprintf('Unclosed "%s"', $expect), $lineno, $this->filename);
            }

            $this->popState();
            ++$this->cursor;
        }
    }

    protected function lexInterpolation()
    {
        $bracket = end($this->brackets);
        if ($this->options['interpolation'][0] === $bracket[0] && preg_match($this->regexes['interpolation_end'], $this->code, $match, null, $this->cursor)) {
            array_pop($this->brackets);
            $this->pushToken(Twig_Token::INTERPOLATION_END_TYPE);
            $this->moveCursor($match[0]);
            $this->popState();
        } else {
            $this->lexExpression();
        }
    }

    protected function pushToken($type, $value = '')
    {
        // do not push empty text tokens
        if (Twig_Token::TEXT_TYPE === $type && '' === $value) {
            return;
        }

        $this->tokens[] = new Twig_Token($type, $value, $this->lineno);
    }

    protected function moveCursor($text)
    {
        $this->cursor += strlen($text);
        $this->lineno += substr_count($text, "\n");
    }

    protected function getOperatorRegex()
    {
        $operators = array_merge(
            array('='),
            array_keys($this->env->getUnaryOperators()),
            array_keys($this->env->getBinaryOperators())
        );

        $operators = array_combine($operators, array_map('strlen', $operators));
        arsort($operators);

        $regex = array();
        foreach ($operators as $operator => $length) {
            // an operator that ends with a character must be followed by
            // a whitespace or a parenthesis
            if (ctype_alpha($operator[$length - 1])) {
                $r = preg_quote($operator, '/').'(?=[\s()])';
            } else {
                $r = preg_quote($operator, '/');
            }

            // an operator with a space can be any amount of whitespaces
            $r = preg_replace('/\s+/', '\s+', $r);

            $regex[] = $r;
        }

        return '/'.implode('|', $regex).'/A';
    }

    protected function pushState($state)
    {
        $this->states[] = $this->state;
        $this->state = $state;
    }

    protected function popState()
    {
        if (0 === count($this->states)) {
            throw new Exception('Cannot pop state without a previous state');
        }

        $this->state = array_pop($this->states);
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Interface implemented by all compiled templates.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @deprecated since 1.12 (to be removed in 2.0)
 */
interface Twig_TemplateInterface
{
    const ANY_CALL    = 'any';
    const ARRAY_CALL  = 'array';
    const METHOD_CALL = 'method';

    /**
     * Renders the template with the given context and returns it as string.
     *
     * @param array $context An array of parameters to pass to the template
     *
     * @return string The rendered template
     */
    public function render(array $context);

    /**
     * Displays the template with the given context.
     *
     * @param array $context An array of parameters to pass to the template
     * @param array $blocks  An array of blocks to pass to the template
     */
    public function display(array $context, array $blocks = array());

    /**
     * Returns the bound environment for this template.
     *
     * @return Twig_Environment The current environment
     */
    public function getEnvironment();
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Interface implemented by parser classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @deprecated since 1.12 (to be removed in 2.0)
 */
interface Twig_ParserInterface
{
    /**
     * Converts a token stream to a node tree.
     *
     * @param Twig_TokenStream $stream A token stream instance
     *
     * @return Twig_Node_Module A node tree
     *
     * @throws Twig_Error_Syntax When the token stream is syntactically or semantically wrong
     */
    public function parse(Twig_TokenStream $stream);
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 * (c) 2009 Armin Ronacher
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Compiles a node to PHP code.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Twig_Compiler implements Twig_CompilerInterface
{
    protected $lastLine;
    protected $source;
    protected $indentation;
    protected $env;
    protected $debugInfo;
    protected $sourceOffset;
    protected $sourceLine;
    protected $filename;

    /**
     * Constructor.
     *
     * @param Twig_Environment $env The twig environment instance
     */
    public function __construct(Twig_Environment $env)
    {
        $this->env = $env;
        $this->debugInfo = array();
    }

    public function getFilename()
    {
        return $this->filename;
    }

    /**
     * Returns the environment instance related to this compiler.
     *
     * @return Twig_Environment The environment instance
     */
    public function getEnvironment()
    {
        return $this->env;
    }

    /**
     * Gets the current PHP code after compilation.
     *
     * @return string The PHP code
     */
    public function getSource()
    {
        return $this->source;
    }

    /**
     * Compiles a node.
     *
     * @param Twig_NodeInterface $node        The node to compile
     * @param integer            $indentation The current indentation
     *
     * @return Twig_Compiler The current compiler instance
     */
    public function compile(Twig_NodeInterface $node, $indentation = 0)
    {
        $this->lastLine = null;
        $this->source = '';
        $this->sourceOffset = 0;
        // source code starts at 1 (as we then increment it when we encounter new lines)
        $this->sourceLine = 1;
        $this->indentation = $indentation;

        if ($node instanceof Twig_Node_Module) {
            $this->filename = $node->getAttribute('filename');
        }

        $node->compile($this);

        return $this;
    }

    public function subcompile(Twig_NodeInterface $node, $raw = true)
    {
        if (false === $raw) {
            $this->addIndentation();
        }

        $node->compile($this);

        return $this;
    }

    /**
     * Adds a raw string to the compiled code.
     *
     * @param string $string The string
     *
     * @return Twig_Compiler The current compiler instance
     */
    public function raw($string)
    {
        $this->source .= $string;

        return $this;
    }

    /**
     * Writes a string to the compiled code by adding indentation.
     *
     * @return Twig_Compiler The current compiler instance
     */
    public function write()
    {
        $strings = func_get_args();
        foreach ($strings as $string) {
            $this->addIndentation();
            $this->source .= $string;
        }

        return $this;
    }

    /**
     * Appends an indentation to the current PHP code after compilation.
     *
     * @return Twig_Compiler The current compiler instance
     */
    public function addIndentation()
    {
        $this->source .= str_repeat(' ', $this->indentation * 4);

        return $this;
    }

    /**
     * Adds a quoted string to the compiled code.
     *
     * @param string $value The string
     *
     * @return Twig_Compiler The current compiler instance
     */
    public function string($value)
    {
        $this->source .= sprintf('"%s"', addcslashes($value, "\0\t\"\$\\"));

        return $this;
    }

    /**
     * Returns a PHP representation of a given value.
     *
     * @param mixed $value The value to convert
     *
     * @return Twig_Compiler The current compiler instance
     */
    public function repr($value)
    {
        if (is_int($value) || is_float($value)) {
            if (false !== $locale = setlocale(LC_NUMERIC, 0)) {
                setlocale(LC_NUMERIC, 'C');
            }

            $this->raw($value);

            if (false !== $locale) {
                setlocale(LC_NUMERIC, $locale);
            }
        } elseif (null === $value) {
            $this->raw('null');
        } elseif (is_bool($value)) {
            $this->raw($value ? 'true' : 'false');
        } elseif (is_array($value)) {
            $this->raw('array(');
            $first = true;
            foreach ($value as $key => $value) {
                if (!$first) {
                    $this->raw(', ');
                }
                $first = false;
                $this->repr($key);
                $this->raw(' => ');
                $this->repr($value);
            }
            $this->raw(')');
        } else {
            $this->string($value);
        }

        return $this;
    }

    /**
     * Adds debugging information.
     *
     * @param Twig_NodeInterface $node The related twig node
     *
     * @return Twig_Compiler The current compiler instance
     */
    public function addDebugInfo(Twig_NodeInterface $node)
    {
        if ($node->getLine() != $this->lastLine) {
            $this->write("// line {$node->getLine()}\n");

            // when mbstring.func_overload is set to 2
            // mb_substr_count() replaces substr_count()
            // but they have different signatures!
            if (((int) ini_get('mbstring.func_overload')) & 2) {
                // this is much slower than the "right" version
                $this->sourceLine += mb_substr_count(mb_substr($this->source, $this->sourceOffset), "\n");
            } else {
                $this->sourceLine += substr_count($this->source, "\n", $this->sourceOffset);
            }
            $this->sourceOffset = strlen($this->source);
            $this->debugInfo[$this->sourceLine] = $node->getLine();

            $this->lastLine = $node->getLine();
        }

        return $this;
    }

    public function getDebugInfo()
    {
        return $this->debugInfo;
    }

    /**
     * Indents the generated code.
     *
     * @param integer $step The number of indentation to add
     *
     * @return Twig_Compiler The current compiler instance
     */
    public function indent($step = 1)
    {
        $this->indentation += $step;

        return $this;
    }

    /**
     * Outdents the generated code.
     *
     * @param integer $step The number of indentation to remove
     *
     * @return Twig_Compiler The current compiler instance
     *
     * @throws LogicException When trying to outdent too much so the indentation would become negative
     */
    public function outdent($step = 1)
    {
        // can't outdent by more steps than the current indentation level
        if ($this->indentation < $step) {
            throw new LogicException('Unable to call outdent() as the indentation would become negative');
        }

        $this->indentation -= $step;

        return $this;
    }
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2010 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Represents a template filter.
 *
 * Use Twig_SimpleFilter instead.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @deprecated since 1.12 (to be removed in 2.0)
 */
interface Twig_FilterInterface
{
    /**
     * Compiles a filter.
     *
     * @return string The PHP code for the filter
     */
    public function compile();

    public function needsEnvironment();

    public function needsContext();

    public function getSafe(Twig_Node $filterArgs);

    public function getPreservesSafety();

    public function getPreEscape();

    public function setArguments($arguments);

    public function getArguments();
}
<?php

/*
 * This file is part of Twig.
 *
 * (c) 2009 Fabien Potencier
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * Interface implemented by lexer classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @deprecated since 1.12 (to be removed in 2.0)
 */
interface Twig_LexerInterface
{
    /**
     * Tokenizes a source code.
     *
     * @param string $code     The source code
     * @param string $filename A unique identifier for the source code
     *
     * @return Twig_TokenStream A token stream instance
     *
     * @throws Twig_Error_Syntax When the code is syntactically wrong
     */
    public function tokenize($code, $filename = null);
}
* 1.14.2 (2013-10-30)

 * fixed error filename/line when an error occurs in an included file
 * allowed operators that contain whitespaces to have more than one whitespace
 * allowed tests to be made of 1 or 2 words (like "same as" or "divisible by")

* 1.14.1 (2013-10-15)

 * made it possible to use named operators as variables
 * fixed the possibility to have a variable named 'matches'
 * added support for PHP 5.5 DateTimeInterface

* 1.14.0 (2013-10-03)

 * fixed usage of the html_attr escaping strategy to avoid double-escaping with the html strategy
 * added new operators: ends with, starts with, and matches
 * fixed some compatibility issues with HHVM
 * added a way to add custom escaping strategies
 * fixed the C extension compilation on Windows
 * fixed the batch filter when using a fill argument with an exact match of elements to batch
 * fixed the filesystem loader cache when a template name exists in several namespaces
 * fixed template_from_string when the template includes or extends other ones
 * fixed a crash of the C extension on an edge case

* 1.13.2 (2013-08-03)

 * fixed the error line number for an error occurs in and embedded template
 * fixed crashes of the C extension on some edge cases

* 1.13.1 (2013-06-06)

 * added the possibility to ignore the filesystem constructor argument in Twig_Loader_Filesystem
 * fixed Twig_Loader_Chain::exists() for a loader which implements Twig_ExistsLoaderInterface
 * adjusted backtrace call to reduce memory usage when an error occurs
 * added support for object instances as the second argument of the constant test
 * fixed the include function when used in an assignment

* 1.13.0 (2013-05-10)

 * fixed getting a numeric-like item on a variable ('09' for instance)
 * fixed getting a boolean or float key on an array, so it is consistent with PHP's array access:
   `{{ array[false] }}` behaves the same as `echo $array[false];` (equals `$array[0]`)
 * made the escape filter 20% faster for happy path (escaping string for html with UTF-8)
 * changed ☃ to § in tests
 * enforced usage of named arguments after positional ones

* 1.12.3 (2013-04-08)

 * fixed a security issue in the filesystem loader where it was possible to include a template one
   level above the configured path
 * fixed fatal error that should be an exception when adding a filter/function/test too late
 * added a batch filter
 * added support for encoding an array as query string in the url_encode filter

* 1.12.2 (2013-02-09)

 * fixed the timezone used by the date filter and function when the given date contains a timezone (like 2010-01-28T15:00:00+02:00)
 * fixed globals when getGlobals is called early on
 * added the first and last filter

* 1.12.1 (2013-01-15)

 * added support for object instances as the second argument of the constant function
 * relaxed globals management to avoid a BC break
 * added support for {{ some_string[:2] }}

* 1.12.0 (2013-01-08)

 * added verbatim as an alias for the raw tag to avoid confusion with the raw filter
 * fixed registration of tests and functions as anonymous functions
 * fixed globals management

* 1.12.0-RC1 (2012-12-29)

 * added an include function (does the same as the include tag but in a more flexible way)
 * added the ability to use any PHP callable to define filters, functions, and tests
 * added a syntax error when using a loop variable that is not defined
 * added the ability to set default values for macro arguments
 * added support for named arguments for filters, tests, and functions
 * moved filters/functions/tests syntax errors to the parser
 * added support for extended ternary operator syntaxes

* 1.11.1 (2012-11-11)

 * fixed debug info line numbering (was off by 2)
 * fixed escaping when calling a macro inside another one (regression introduced in 1.9.1)
 * optimized variable access on PHP 5.4
 * fixed a crash of the C extension when an exception was thrown from a macro called without being imported (using _self.XXX)

* 1.11.0 (2012-11-07)

 * fixed macro compilation when a variable name is a PHP reserved keyword
 * changed the date filter behavior to always apply the default timezone, except if false is passed as the timezone
 * fixed bitwise operator precedences
 * added the template_from_string function
 * fixed default timezone usage for the date function
 * optimized the way Twig exceptions are managed (to make them faster)
 * added Twig_ExistsLoaderInterface (implementing this interface in your loader make the chain loader much faster)

* 1.10.3 (2012-10-19)

 * fixed wrong template location in some error messages
 * reverted a BC break introduced in 1.10.2
 * added a split filter

* 1.10.2 (2012-10-15)

 * fixed macro calls on PHP 5.4

* 1.10.1 (2012-10-15)

 * made a speed optimization to macro calls when imported via the "import" tag
 * fixed C extension compilation on Windows
 * fixed a segfault in the C extension when using DateTime objects

* 1.10.0 (2012-09-28)

 * extracted functional tests framework to make it reusable for third-party extensions
 * added namespaced templates support in Twig_Loader_Filesystem
 * added Twig_Loader_Filesystem::prependPath()
 * fixed an error when a token parser pass a closure as a test to the subparse() method

* 1.9.2 (2012-08-25)

 * fixed the in operator for objects that contain circular references
 * fixed the C extension when accessing a public property of an object implementing the \ArrayAccess interface

* 1.9.1 (2012-07-22)

 * optimized macro calls when auto-escaping is on
 * fixed wrong parent class for Twig_Function_Node
 * made Twig_Loader_Chain more explicit about problems

* 1.9.0 (2012-07-13)

 * made the parsing independent of the template loaders
 * fixed exception trace when an error occurs when rendering a child template
 * added escaping strategies for CSS, URL, and HTML attributes
 * fixed nested embed tag calls
 * added the date_modify filter

* 1.8.3 (2012-06-17)

 * fixed paths in the filesystem loader when passing a path that ends with a slash or a backslash
 * fixed escaping when a project defines a function named html or js
 * fixed chmod mode to apply the umask correctly

* 1.8.2 (2012-05-30)

 * added the abs filter
 * fixed a regression when using a number in template attributes
 * fixed compiler when mbstring.func_overload is set to 2
 * fixed DateTimeZone support in date filter

* 1.8.1 (2012-05-17)

 * fixed a regression when dealing with SimpleXMLElement instances in templates
 * fixed "is_safe" value for the "dump" function when "html_errors" is not defined in php.ini
 * switched to use mbstring whenever possible instead of iconv (you might need to update your encoding as mbstring and iconv encoding names sometimes differ)

* 1.8.0 (2012-05-08)

 * enforced interface when adding tests, filters, functions, and node visitors from extensions
 * fixed a side-effect of the date filter where the timezone might be changed
 * simplified usage of the autoescape tag; the only (optional) argument is now the escaping strategy or false (with a BC layer)
 * added a way to dynamically change the auto-escaping strategy according to the template "filename"
 * changed the autoescape option to also accept a supported escaping strategy (for BC, true is equivalent to html)
 * added an embed tag

* 1.7.0 (2012-04-24)

 * fixed a PHP warning when using CIFS
 * fixed template line number in some exceptions
 * added an iterable test
 * added an error when defining two blocks with the same name in a template
 * added the preserves_safety option for filters
 * fixed a PHP notice when trying to access a key on a non-object/array variable
 * enhanced error reporting when the template file is an instance of SplFileInfo
 * added Twig_Environment::mergeGlobals()
 * added compilation checks to avoid misuses of the sandbox tag
 * fixed filesystem loader freshness logic for high traffic websites
 * fixed random function when charset is null

* 1.6.5 (2012-04-11)

 * fixed a regression when a template only extends another one without defining any blocks

* 1.6.4 (2012-04-02)

 * fixed PHP notice in Twig_Error::guessTemplateLine() introduced in 1.6.3
 * fixed performance when compiling large files
 * optimized parent template creation when the template does not use dynamic inheritance

* 1.6.3 (2012-03-22)

 * fixed usage of Z_ADDREF_P for PHP 5.2 in the C extension
 * fixed compilation of numeric values used in templates when using a locale where the decimal separator is not a dot
 * made the strategy used to guess the real template file name and line number in exception messages much faster and more accurate

* 1.6.2 (2012-03-18)

 * fixed sandbox mode when used with inheritance
 * added preserveKeys support for the slice filter
 * fixed the date filter when a DateTime instance is passed with a specific timezone
 * added a trim filter

* 1.6.1 (2012-02-29)

 * fixed Twig C extension
 * removed the creation of Twig_Markup instances when not needed
 * added a way to set the default global timezone for dates
 * fixed the slice filter on strings when the length is not specified
 * fixed the creation of the cache directory in case of a race condition

* 1.6.0 (2012-02-04)

 * fixed raw blocks when used with the whitespace trim option
 * made a speed optimization to macro calls when imported via the "from" tag
 * fixed globals, parsers, visitors, filters, tests, and functions management in Twig_Environment when a new one or new extension is added
 * fixed the attribute function when passing arguments
 * added slice notation support for the [] operator (syntactic sugar for the slice operator)
 * added a slice filter
 * added string support for the reverse filter
 * fixed the empty test and the length filter for Twig_Markup instances
 * added a date function to ease date comparison
 * fixed unary operators precedence
 * added recursive parsing support in the parser
 * added string and integer handling for the random function

* 1.5.1 (2012-01-05)

 * fixed a regression when parsing strings

* 1.5.0 (2012-01-04)

 * added Traversable objects support for the join filter

* 1.5.0-RC2 (2011-12-30)

 * added a way to set the default global date interval format
 * fixed the date filter for DateInterval instances (setTimezone() does not exist for them)
 * refactored Twig_Template::display() to ease its extension
 * added a number_format filter

* 1.5.0-RC1 (2011-12-26)

 * removed the need to quote hash keys
 * allowed hash keys to be any expression
 * added a do tag
 * added a flush tag
 * added support for dynamically named filters and functions
 * added a dump function to help debugging templates
 * added a nl2br filter
 * added a random function
 * added a way to change the default format for the date filter
 * fixed the lexer when an operator ending with a letter ends a line
 * added string interpolation support
 * enhanced exceptions for unknown filters, functions, tests, and tags

* 1.4.0 (2011-12-07)

 * fixed lexer when using big numbers (> PHP_INT_MAX)
 * added missing preserveKeys argument to the reverse filter
 * fixed macros containing filter tag calls

* 1.4.0-RC2 (2011-11-27)

 * removed usage of Reflection in Twig_Template::getAttribute()
 * added a C extension that can optionally replace Twig_Template::getAttribute()
 * added negative timestamp support to the date filter

* 1.4.0-RC1 (2011-11-20)

 * optimized variable access when using PHP 5.4
 * changed the precedence of the .. operator to be more consistent with languages that implements such a feature like Ruby
 * added an Exception to Twig_Loader_Array::isFresh() method when the template does not exist to be consistent with other loaders
 * added Twig_Function_Node to allow more complex functions to have their own Node class
 * added Twig_Filter_Node to allow more complex filters to have their own Node class
 * added Twig_Test_Node to allow more complex tests to have their own Node class
 * added a better error message when a template is empty but contain a BOM
 * fixed "in" operator for empty strings
 * fixed the "defined" test and the "default" filter (now works with more than one call (foo.bar.foo) and for both values of the strict_variables option)
 * changed the way extensions are loaded (addFilter/addFunction/addGlobal/addTest/addNodeVisitor/addTokenParser/addExtension can now be called in any order)
 * added Twig_Environment::display()
 * made the escape filter smarter when the encoding is not supported by PHP
 * added a convert_encoding filter
 * moved all node manipulations outside the compile() Node method
 * made several speed optimizations

* 1.3.0 (2011-10-08)

no changes

* 1.3.0-RC1 (2011-10-04)

 * added an optimization for the parent() function
 * added cache reloading when auto_reload is true and an extension has been modified
 * added the possibility to force the escaping of a string already marked as safe (instance of Twig_Markup)
 * allowed empty templates to be used as traits
 * added traits support for the "parent" function

* 1.2.0 (2011-09-13)

no changes

* 1.2.0-RC1 (2011-09-10)

 * enhanced the exception when a tag remains unclosed
 * added support for empty Countable objects for the "empty" test
 * fixed algorithm that determines if a template using inheritance is valid (no output between block definitions)
 * added better support for encoding problems when escaping a string (available as of PHP 5.4)
 * added a way to ignore a missing template when using the "include" tag ({% include "foo" ignore missing %})
 * added support for an array of templates to the "include" and "extends" tags ({% include ['foo', 'bar'] %})
 * added support for bitwise operators in expressions
 * added the "attribute" function to allow getting dynamic attributes on variables
 * added Twig_Loader_Chain
 * added Twig_Loader_Array::setTemplate()
 * added an optimization for the set tag when used to capture a large chunk of static text
 * changed name regex to match PHP one "[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*" (works for blocks, tags, functions, filters, and macros)
 * removed the possibility to use the "extends" tag from a block
 * added "if" modifier support to "for" loops

* 1.1.2 (2011-07-30)

 * fixed json_encode filter on PHP 5.2
 * fixed regression introduced in 1.1.1 ({{ block(foo|lower) }})
 * fixed inheritance when using conditional parents
 * fixed compilation of templates when the body of a child template is not empty
 * fixed output when a macro throws an exception
 * fixed a parsing problem when a large chunk of text is enclosed in a comment tag
 * added PHPDoc for all Token parsers and Core extension functions

* 1.1.1 (2011-07-17)

 * added a performance optimization in the Optimizer (also helps to lower the number of nested level calls)
 * made some performance improvement for some edge cases

* 1.1.0 (2011-06-28)

 * fixed json_encode filter

* 1.1.0-RC3 (2011-06-24)

 * fixed method case-sensitivity when using the sandbox mode
 * added timezone support for the date filter
 * fixed possible security problems with NUL bytes

* 1.1.0-RC2 (2011-06-16)

 * added an exception when the template passed to "use" is not a string
 * made 'a.b is defined' not throw an exception if a is not defined (in strict mode)
 * added {% line \d+ %} directive

* 1.1.0-RC1 (2011-05-28)

Flush your cache after upgrading.

 * fixed date filter when using a timestamp
 * fixed the defined test for some cases
 * fixed a parsing problem when a large chunk of text is enclosed in a raw tag
 * added support for horizontal reuse of template blocks (see docs for more information)
 * added whitespace control modifier to all tags (see docs for more information)
 * added null as an alias for none (the null test is also an alias for the none test now)
 * made TRUE, FALSE, NONE equivalent to their lowercase counterparts
 * wrapped all compilation and runtime exceptions with Twig_Error_Runtime and added logic to guess the template name and line
 * moved display() method to Twig_Template (generated templates should now use doDisplay() instead)

* 1.0.0 (2011-03-27)

 * fixed output when using mbstring
 * fixed duplicate call of methods when using the sandbox
 * made the charset configurable for the escape filter

* 1.0.0-RC2 (2011-02-21)

 * changed the way {% set %} works when capturing (the content is now marked as safe)
 * added support for macro name in the endmacro tag
 * make Twig_Error compatible with PHP 5.3.0 >
 * fixed an infinite loop on some Windows configurations
 * fixed the "length" filter for numbers
 * fixed Template::getAttribute() as properties in PHP are case sensitive
 * removed coupling between Twig_Node and Twig_Template
 * fixed the ternary operator precedence rule

* 1.0.0-RC1 (2011-01-09)

Backward incompatibilities:

 * the "items" filter, which has been deprecated for quite a long time now, has been removed
 * the "range" filter has been converted to a function: 0|range(10) -> range(0, 10)
 * the "constant" filter has been converted to a function: {{ some_date|date('DATE_W3C'|constant) }} -> {{ some_date|date(constant('DATE_W3C')) }}
 * the "cycle" filter has been converted to a function: {{ ['odd', 'even']|cycle(i) }} -> {{ cycle(['odd', 'even'], i) }}
 * the "for" tag does not support "joined by" anymore
 * the "autoescape" first argument is now "true"/"false" (instead of "on"/"off")
 * the "parent" tag has been replaced by a "parent" function ({{ parent() }} instead of {% parent %})
 * the "display" tag has been replaced by a "block" function ({{ block('title') }} instead of {% display title %})
 * removed the grammar and simple token parser (moved to the Twig Extensions repository)

Changes:

 * added "needs_context" option for filters and functions (the context is then passed as a first argument)
 * added global variables support
 * made macros return their value instead of echoing directly (fixes calling a macro in sandbox mode)
 * added the "from" tag to import macros as functions
 * added support for functions (a function is just syntactic sugar for a getAttribute() call)
 * made macros callable when sandbox mode is enabled
 * added an exception when a macro uses a reserved name
 * the "default" filter now uses the "empty" test instead of just checking for null
 * added the "empty" test

* 0.9.10 (2010-12-16)

Backward incompatibilities:

 * The Escaper extension is enabled by default, which means that all displayed
   variables are now automatically escaped. You can revert to the previous
   behavior by removing the extension via $env->removeExtension('escaper')
   or just set the 'autoescape' option to 'false'.
 * removed the "without loop" attribute for the "for" tag (not needed anymore
   as the Optimizer take care of that for most cases)
 * arrays and hashes have now a different syntax
     * arrays keep the same syntax with square brackets: [1, 2]
     * hashes now use curly braces (["a": "b"] should now be written as {"a": "b"})
     * support for "arrays with keys" and "hashes without keys" is not supported anymore ([1, "foo": "bar"] or {"foo": "bar", 1})
 * the i18n extension is now part of the Twig Extensions repository

Changes:

 * added the merge filter
 * removed 'is_escaper' option for filters (a left over from the previous version) -- you must use 'is_safe' now instead
 * fixed usage of operators as method names (like is, in, and not)
 * changed the order of execution for node visitors
 * fixed default() filter behavior when used with strict_variables set to on
 * fixed filesystem loader compatibility with PHAR files
 * enhanced error messages when an unexpected token is parsed in an expression
 * fixed filename not being added to syntax error messages
 * added the autoescape option to enable/disable autoescaping
 * removed the newline after a comment (mimics PHP behavior)
 * added a syntax error exception when parent block is used on a template that does not extend another one
 * made the Escaper extension enabled by default
 * fixed sandbox extension when used with auto output escaping
 * fixed escaper when wrapping a Twig_Node_Print (the original class must be preserved)
 * added an Optimizer extension (enabled by default; optimizes "for" loops and "raw" filters)
 * added priority to node visitors

* 0.9.9 (2010-11-28)

Backward incompatibilities:
 * the self special variable has been renamed to _self
 * the odd and even filters are now tests:
     {{ foo|odd }} must now be written {{ foo is odd }}
 * the "safe" filter has been renamed to "raw"
 * in Node classes,
        sub-nodes are now accessed via getNode() (instead of property access)
        attributes via getAttribute() (instead of array access)
 * the urlencode filter had been renamed to url_encode
 * the include tag now merges the passed variables with the current context by default
   (the old behavior is still possible by adding the "only" keyword)
 * moved Exceptions to Twig_Error_* (Twig_SyntaxError/Twig_RuntimeError are now Twig_Error_Syntax/Twig_Error_Runtime)
 * removed support for {{ 1 < i < 3 }} (use {{ i > 1 and i < 3 }} instead)
 * the "in" filter has been removed ({{ a|in(b) }} should now be written {{ a in b }})

Changes:
 * added file and line to Twig_Error_Runtime exceptions thrown from Twig_Template
 * changed trans tag to accept any variable for the plural count
 * fixed sandbox mode (__toString() method check was not enforced if called implicitly from complex statements)
 * added the ** (power) operator
 * changed the algorithm used for parsing expressions
 * added the spaceless tag
 * removed trim_blocks option
 * added support for is*() methods for attributes (foo.bar now looks for foo->getBar() or foo->isBar())
 * changed all exceptions to extend Twig_Error
 * fixed unary expressions ({{ not(1 or 0) }})
 * fixed child templates (with an extend tag) that uses one or more imports
 * added support for {{ 1 not in [2, 3] }} (more readable than the current {{ not (1 in [2, 3]) }})
 * escaping has been rewritten
 * the implementation of template inheritance has been rewritten
   (blocks can now be called individually and still work with inheritance)
 * fixed error handling for if tag when a syntax error occurs within a subparse process
 * added a way to implement custom logic for resolving token parsers given a tag name
 * fixed js escaper to be stricter (now uses a whilelist-based js escaper)
 * added the following filers: "constant", "trans", "replace", "json_encode"
 * added a "constant" test
 * fixed objects with __toString() not being autoescaped
 * fixed subscript expressions when calling __call() (methods now keep the case)
 * added "test" feature (accessible via the "is" operator)
 * removed the debug tag (should be done in an extension)
 * fixed trans tag when no vars are used in plural form
 * fixed race condition when writing template cache
 * added the special _charset variable to reference the current charset
 * added the special _context variable to reference the current context
 * renamed self to _self (to avoid conflict)
 * fixed Twig_Template::getAttribute() for protected properties

* 0.9.8 (2010-06-28)

Backward incompatibilities:
 * the trans tag plural count is now attached to the plural tag:
    old: `{% trans count %}...{% plural %}...{% endtrans %}`
    new: `{% trans %}...{% plural count %}...{% endtrans %}`

 * added a way to translate strings coming from a variable ({% trans var %})
 * fixed trans tag when used with the Escaper extension
 * fixed default cache umask
 * removed Twig_Template instances from the debug tag output
 * fixed objects with __isset() defined
 * fixed set tag when used with a capture
 * fixed type hinting for Twig_Environment::addFilter() method

* 0.9.7 (2010-06-12)

Backward incompatibilities:
 * changed 'as' to '=' for the set tag ({% set title as "Title" %} must now be {% set title = "Title" %})
 * removed the sandboxed attribute of the include tag (use the new sandbox tag instead)
 * refactored the Node system (if you have custom nodes, you will have to update them to use the new API)

 * added self as a special variable that refers to the current template (useful for importing macros from the current template)
 * added Twig_Template instance support to the include tag
 * added support for dynamic and conditional inheritance ({% extends some_var %} and {% extends standalone ? "minimum" : "base" %})
 * added a grammar sub-framework to ease the creation of custom tags
 * fixed the for tag for large arrays (some loop variables are now only available for arrays and objects that implement the Countable interface)
 * removed the Twig_Resource::resolveMissingFilter() method
 * fixed the filter tag which did not apply filtering to included files
 * added a bunch of unit tests
 * added a bunch of phpdoc
 * added a sandbox tag in the sandbox extension
 * changed the date filter to support any date format supported by DateTime
 * added strict_variable setting to throw an exception when an invalid variable is used in a template (disabled by default)
 * added the lexer, parser, and compiler as arguments to the Twig_Environment constructor
 * changed the cache option to only accepts an explicit path to a cache directory or false
 * added a way to add token parsers, filters, and visitors without creating an extension
 * added three interfaces: Twig_NodeInterface, Twig_TokenParserInterface, and Twig_FilterInterface
 * changed the generated code to match the new coding standards
 * fixed sandbox mode (__toString() method check was not enforced if called implicitly from a simple statement like {{ article }})
 * added an exception when a child template has a non-empty body (as it is always ignored when rendering)

* 0.9.6 (2010-05-12)

 * fixed variables defined outside a loop and for which the value changes in a for loop
 * fixed the test suite for PHP 5.2 and older versions of PHPUnit
 * added support for __call() in expression resolution
 * fixed node visiting for macros (macros are now visited by visitors as any other node)
 * fixed nested block definitions with a parent call (rarely useful but nonetheless supported now)
 * added the cycle filter
 * fixed the Lexer when mbstring.func_overload is used with an mbstring.internal_encoding different from ASCII
 * added a long-syntax for the set tag ({% set foo %}...{% endset %})
 * unit tests are now powered by PHPUnit
 * added support for gettext via the `i18n` extension
 * fixed twig_capitalize_string_filter() and fixed twig_length_filter() when used with UTF-8 values
 * added a more useful exception if an if tag is not closed properly
 * added support for escaping strategy in the autoescape tag
 * fixed lexer when a template has a big chunk of text between/in a block

* 0.9.5 (2010-01-20)

As for any new release, don't forget to remove all cached templates after
upgrading.

If you have defined custom filters, you MUST upgrade them for this release. To
upgrade, replace "array" with "new Twig_Filter_Function", and replace the
environment constant by the "needs_environment" option:

  // before
  'even'   => array('twig_is_even_filter', false),
  'escape' => array('twig_escape_filter', true),

  // after
  'even'   => new Twig_Filter_Function('twig_is_even_filter'),
  'escape' => new Twig_Filter_Function('twig_escape_filter', array('needs_environment' => true)),

If you have created NodeTransformer classes, you will need to upgrade them to
the new interface (please note that the interface is not yet considered
stable).

 * fixed list nodes that did not extend the Twig_NodeListInterface
 * added the "without loop" option to the for tag (it disables the generation of the loop variable)
 * refactored node transformers to node visitors
 * fixed automatic-escaping for blocks
 * added a way to specify variables to pass to an included template
 * changed the automatic-escaping rules to be more sensible and more configurable in custom filters (the documentation lists all the rules)
 * improved the filter system to allow object methods to be used as filters
 * changed the Array and String loaders to actually make use of the cache mechanism
 * included the default filter function definitions in the extension class files directly (Core, Escaper)
 * added the // operator (like the floor() PHP function)
 * added the .. operator (as a syntactic sugar for the range filter when the step is 1)
 * added the in operator (as a syntactic sugar for the in filter)
 * added the following filters in the Core extension: in, range
 * added support for arrays (same behavior as in PHP, a mix between lists and dictionaries, arrays and hashes)
 * enhanced some error messages to provide better feedback in case of parsing errors

* 0.9.4 (2009-12-02)

If you have custom loaders, you MUST upgrade them for this release: The
Twig_Loader base class has been removed, and the Twig_LoaderInterface has also
been changed (see the source code for more information or the documentation).

 * added support for DateTime instances for the date filter
 * fixed loop.last when the array only has one item
 * made it possible to insert newlines in tag and variable blocks
 * fixed a bug when a literal '\n' were present in a template text
 * fixed bug when the filename of a template contains */
 * refactored loaders

* 0.9.3 (2009-11-11)

This release is NOT backward compatible with the previous releases.

  The loaders do not take the cache and autoReload arguments anymore. Instead,
  the Twig_Environment class has two new options: cache and auto_reload.
  Upgrading your code means changing this kind of code:

      $loader = new Twig_Loader_Filesystem('/path/to/templates', '/path/to/compilation_cache', true);
      $twig = new Twig_Environment($loader);

  to something like this:

      $loader = new Twig_Loader_Filesystem('/path/to/templates');
      $twig = new Twig_Environment($loader, array(
        'cache' => '/path/to/compilation_cache',
        'auto_reload' => true,
      ));

 * deprecated the "items" filter as it is not needed anymore
 * made cache and auto_reload options of Twig_Environment instead of arguments of Twig_Loader
 * optimized template loading speed
 * removed output when an error occurs in a template and render() is used
 * made major speed improvements for loops (up to 300% on even the smallest loops)
 * added properties as part of the sandbox mode
 * added public properties support (obj.item can now be the item property on the obj object)
 * extended set tag to support expression as value ({% set foo as 'foo' ~ 'bar' %} )
 * fixed bug when \ was used in HTML

* 0.9.2 (2009-10-29)

 * made some speed optimizations
 * changed the cache extension to .php
 * added a js escaping strategy
 * added support for short block tag
 * changed the filter tag to allow chained filters
 * made lexer more flexible as you can now change the default delimiters
 * added set tag
 * changed default directory permission when cache dir does not exist (more secure)
 * added macro support
 * changed filters first optional argument to be a Twig_Environment instance instead of a Twig_Template instance
 * made Twig_Autoloader::autoload() a static method
 * avoid writing template file if an error occurs
 * added $ escaping when outputting raw strings
 * enhanced some error messages to ease debugging
 * fixed empty cache files when the template contains an error

* 0.9.1 (2009-10-14)

  * fixed a bug in PHP 5.2.6
  * fixed numbers with one than one decimal
  * added support for method calls with arguments ({{ foo.bar('a', 43) }})
  * made small speed optimizations
  * made minor tweaks to allow better extensibility and flexibility

* 0.9.0 (2009-10-12)

 * Initial release
{
    "name": "phpcollection/phpcollection",
    "description": "General-Purpose Collection Library for PHP",
    "keywords": ["collection", "list", "sequence", "map", "set"],
    "license": "Apache2",
    "authors": [
        {"name": "Johannes M. Schmitt", "email": "schmittjoh@gmail.com"}
    ],
    "require": {
        "phpoption/phpoption": "1.*"
    },
    "autoload": {
        "psr-0": {
            "PhpCollection": "src/"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "0.2-dev"
        }
    }
}<?php

/*
 * Copyright 2012 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace PhpCollection;

use PhpOption\Some;
use PhpOption\None;

/**
 * A simple map implementation which basically wraps an array with an object oriented interface.
 *
 * @IgnoreAnnotation("template")
 * @template {K extends string} This implementation only supports strings as keys.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class AbstractMap extends AbstractCollection implements \IteratorAggregate, MapInterface
{
    protected $elements;

    public function __construct(array $elements = array())
    {
        $this->elements = $elements;
    }

    public function set($key, $value)
    {
        $this->elements[$key] = $value;
    }

    /**
     * Sets all key/value pairs in the map.
     *
     * @param array<string,T> $kvMap
     *
     * @return void
     */
    public function setAll(array $kvMap)
    {
        $this->elements = array_merge($this->elements, $kvMap);
    }

    public function addMap(MapInterface $map)
    {
        foreach ($map as $k => $v) {
            $this->elements[$k] = $v;
        }
    }

    public function get($key)
    {
        if (isset($this->elements[$key])) {
            return new Some($this->elements[$key]);
        }

        return None::create();
    }

    public function remove($key)
    {
        if ( ! isset($this->elements[$key])) {
            throw new \InvalidArgumentException(sprintf('The map has no key named "%s".', $key));
        }

        $element = $this->elements[$key];
        unset($this->elements[$key]);

        return $element;
    }

    public function clear()
    {
        $this->elements = array();
    }

    public function first()
    {
        if (empty($this->elements)) {
            return None::create();
        }

        $elem = reset($this->elements);

        return new Some(array(key($this->elements), $elem));
    }

    public function last()
    {
        if (empty($this->elements)) {
            return None::create();
        }

        $elem = end($this->elements);

        return new Some(array(key($this->elements), $elem));
    }

    public function contains($elem)
    {
        foreach ($this->elements as $existingElem) {
            if ($existingElem === $elem) {
                return true;
            }
        }

        return false;
    }

    public function containsKey($key)
    {
        return isset($this->elements[$key]);
    }

    public function isEmpty()
    {
        return empty($this->elements);
    }

    public function dropWhile($callable)
    {
        $newElements = array();
        $stopped = false;
        foreach ($this->elements as $k => $v) {
            if ( ! $stopped) {
                if (call_user_func($callable, $k, $v) === true) {
                    continue;
                }

                $stopped = true;
            }

            $newElements[$k] = $v;
        }

        return $this->createNew($newElements);
    }

    public function drop($number)
    {
        if ($number <= 0) {
            throw new \InvalidArgumentException(sprintf('The number must be greater than 0, but got %d.', $number));
        }

        return $this->createNew(array_slice($this->elements, $number, null, true));
    }

    public function dropRight($number)
    {
        if ($number <= 0) {
            throw new \InvalidArgumentException(sprintf('The number must be greater than 0, but got %d.', $number));
        }

        return $this->createNew(array_slice($this->elements, 0, -1 * $number, true));
    }

    public function take($number)
    {
        if ($number <= 0) {
            throw new \InvalidArgumentException(sprintf('The number must be greater than 0, but got %d.', $number));
        }

        return $this->createNew(array_slice($this->elements, 0, $number, true));
    }

    public function takeWhile($callable)
    {
        $newElements = array();
        foreach ($this->elements as $k => $v) {
            if (call_user_func($callable, $k, $v) !== true) {
                break;
            }

            $newElements[$k] = $v;
        }

        return $this->createNew($newElements);
    }

    public function find($callable)
    {
        foreach ($this->elements as $k => $v) {
            if (call_user_func($callable, $k, $v) === true) {
                return new Some(array($k, $v));
            }
        }

        return None::create();
    }

    public function keys()
    {
        return array_keys($this->elements);
    }

    public function values()
    {
        return array_values($this->elements);
    }

    public function count()
    {
        return count($this->elements);
    }

    public function getIterator()
    {
        return new \ArrayIterator($this->elements);
    }

    protected function createNew(array $elements)
    {
        return new static($elements);
    }
}<?php

/*
 * Copyright 2012 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace PhpCollection;

/**
 * Interface for sortable collections.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface SortableInterface
{
    public function sortWith($callable);
}<?php

/*
 * Copyright 2012 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace PhpCollection;

/**
 * Unsorted sequence implementation.
 *
 * Characteristics:
 *
 *     - Keys: consequentially numbered, without gaps
 *     - Values: anything, duplicates allowed
 *     - Ordering: same as input unless when explicitly sorted
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class Sequence extends AbstractSequence implements SortableInterface
{
    public function sortWith($callable)
    {
        usort($this->elements, $callable);
    }
}<?php

/*
 * Copyright 2012 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace PhpCollection;

/**
 * A sequence with a fixed sort-order.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class SortedSequence extends AbstractSequence
{
    private $sortFunc;

    public function __construct($sortFunc, array $elements = array())
    {
        usort($elements, $sortFunc);
        parent::__construct($elements);

        $this->sortFunc = $sortFunc;
    }

    public function add($newElement)
    {
        $added = false;
        $newElements = array();
        foreach ($this->elements as $element) {
            // We insert the new element before the first element that is greater than itself.
            if ( ! $added && (integer) call_user_func($this->sortFunc, $newElement, $element) < 0) {
                $newElements[] = $newElement;
                $added = true;
            }

            $newElements[] = $element;
        }

        if ( ! $added) {
            $newElements[] = $newElement;
        }
        $this->elements = $newElements;
    }

    public function addAll(array $addedElements)
    {
        usort($addedElements, $this->sortFunc);

        $newElements = array();
        foreach ($this->elements as $element) {
            if ( ! empty($addedElements)) {
                foreach ($addedElements as $i => $newElement) {
                    // If the currently looked at $newElement is not smaller than $element, then we can also conclude
                    // that all other new elements are also not smaller than $element as we have ordered them before.
                    if ((integer) call_user_func($this->sortFunc, $newElement, $element) > -1) {
                        break;
                    }

                    $newElements[] = $newElement;
                    unset($addedElements[$i]);
                }
            }

            $newElements[] = $element;
        }

        if ( ! empty($addedElements)) {
            foreach ($addedElements as $newElement) {
                $newElements[] = $newElement;
            }
        }

        $this->elements = $newElements;
    }

    protected function createNew(array $elements)
    {
        return new static($this->sortFunc, $elements);
    }
}<?php

/*
 * Copyright 2012 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace PhpCollection;

use PhpOption\Some;
use PhpOption\None;
use PhpOption\Option;
use OutOfBoundsException;

/**
 * A sequence with numerically indexed elements.
 *
 * This is rawly equivalent to an array with only numeric keys.
 * There are no restrictions on how many same values may occur in the sequence.
 *
 * This sequence is mutable.
 *
 * @IgnoreAnnotation("template")
 * @template T The type that this sequence contains.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class AbstractSequence extends AbstractCollection implements \IteratorAggregate, SequenceInterface
{
    protected $elements;

    /**
     * @param array<T> $elements
     */
    public function __construct(array $elements = array())
    {
        $this->elements = array_values($elements);
    }

    public function addSequence(SequenceInterface $seq)
    {
        $this->addAll($seq->all());
    }

    public function indexOf($searchedElement)
    {
        foreach ($this->elements as $i => $element) {
            if ($searchedElement === $element) {
                return $i;
            }
        }

        return -1;
    }

    public function lastIndexOf($searchedElement)
    {
        for ($i=count($this->elements)-1; $i>=0; $i--) {
            if ($this->elements[$i] === $searchedElement) {
                return $i;
            }
        }

        return -1;
    }

    public function isDefinedAt($index)
    {
        return isset($this->elements[$index]);
    }

    /**
     * Finds the first index where the given callable returns true.
     *
     * @param callable $callable
     *
     * @return integer the index, or -1 if the predicate is not true for any element.
     */
    public function indexWhere($callable)
    {
        foreach ($this->elements as $i => $element) {
            if (call_user_func($callable, $element) === true) {
                return $i;
            }
        }

        return -1;
    }

    public function lastIndexWhere($callable)
    {
        for ($i=count($this->elements)-1; $i>=0; $i--) {
            if (call_user_func($callable, $this->elements[$i]) === true) {
                return $i;
            }
        }

        return -1;
    }

    public function last()
    {
        if (empty($this->elements)) {
            return None::create();
        }

        return new Some(end($this->elements));
    }

    public function first()
    {
        if (empty($this->elements)) {
            return None::create();
        }

        return new Some(reset($this->elements));
    }

    public function indices()
    {
        return array_keys($this->elements);
    }

    /**
     * Returns an element based on its index (0-based).
     *
     * @param integer $index
     *
     * @return T
     */
    public function get($index)
    {
        if ( ! isset($this->elements[$index])) {
            throw new OutOfBoundsException(sprintf('The index "%s" does not exist in this sequence.', $index));
        }

        return $this->elements[$index];
    }

    /**
     * Removes the element at the given index, and returns it.
     *
     * @param int $index
     *
     * @return T
     *
     * @throws \OutOfBoundsException If there is no element at the given index.
     */
    public function remove($index)
    {
        if ( ! isset($this->elements[$index])) {
            throw new OutOfBoundsException(sprintf('The index "%d" is not in the interval [0, %d).', $index, count($this->elements)));
        }

        $element = $this->elements[$index];
        unset($this->elements[$index]);
        $this->elements = array_values($this->elements);

        return $element;
    }

    /**
     * Updates the element at the given index (0-based).
     *
     * @param integer $index
     * @param T $value
     */
    public function update($index, $value)
    {
        if ( ! isset($this->elements[$index])) {
            throw new \InvalidArgumentException(sprintf('There is no element at index "%d".', $index));
        }

        $this->elements[$index] = $value;
    }

    public function isEmpty()
    {
        return empty($this->elements);
    }

    public function all()
    {
        return $this->elements;
    }

    public function add($newElement)
    {
        $this->elements[] = $newElement;
    }

    public function addAll(array $addedElements)
    {
        foreach ($addedElements as $newElement) {
            $this->elements[] = $newElement;
        }
    }

    public function take($number)
    {
        if ($number <= 0) {
            throw new \InvalidArgumentException(sprintf('$number must be greater than 0, but got %d.', $number));
        }

        return $this->createNew(array_slice($this->elements, 0, $number));
    }

    /**
     * Extracts element from the head while the passed callable returns true.
     *
     * @param callable $callable receives elements of this sequence as first argument, and returns true/false.
     *
     * @return Sequence<T>
     */
    public function takeWhile($callable)
    {
        $newElements = array();

        for ($i=0,$c=count($this->elements); $i<$c; $i++) {
            if (call_user_func($callable, $this->elements[$i]) !== true) {
                break;
            }

            $newElements[] = $this->elements[$i];
        }

        return $this->createNew($newElements);
    }

    public function drop($number)
    {
        if ($number <= 0) {
            throw new \InvalidArgumentException(sprintf('The number must be greater than 0, but got %d.', $number));
        }

        return $this->createNew(array_slice($this->elements, $number));
    }

    public function dropRight($number)
    {
        if ($number <= 0) {
            throw new \InvalidArgumentException(sprintf('The number must be greater than 0, but got %d.', $number));
        }

        return $this->createNew(array_slice($this->elements, 0, -1 * $number));
    }

    public function dropWhile($callable)
    {
        for ($i=0,$c=count($this->elements); $i<$c; $i++) {
            if (true !== call_user_func($callable, $this->elements[$i])) {
                break;
            }
        }

        return $this->createNew(array_slice($this->elements, $i));
    }

    public function count()
    {
        return count($this->elements);
    }

    public function getIterator()
    {
        return new \ArrayIterator($this->elements);
    }

    protected function createNew(array $elements)
    {
        return new static($elements);
    }
}<?php

/*
 * Copyright 2012 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace PhpCollection;

class Map extends AbstractMap implements SortableInterface
{
    public function sortWith($callable)
    {
        uksort($this->elements, $callable);
    }
}<?php

/*
 * Copyright 2012 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace PhpCollection;

/**
 * Basic map interface.
 *
 * @IgnoreAnnotation("template")
 * @template K the type of the keys
 * @template V the type of the values
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface MapInterface extends CollectionInterface
{
    /**
     * Returns the first element in the collection if available.
     *
     * @return Option<array<K,V>>
     */
    public function first();

    /**
     * Returns the last element in the collection if available.
     *
     * @return Option<array<K,V>>
     */
    public function last();

    /**
     * Searches the collection for an element.
     *
     * @param callable $callable receives the element as first argument, and returns true, or false
     *
     * @return Option<array<K,V>>
     */
    public function find($callable);

    /**
     * Returns the value associated with the given key.
     *
     * @param K $key
     *
     * @return Option<V>
     */
    public function get($key);

    /**
     * Returns whether this map contains a given key.
     *
     * @param K $key
     *
     * @return boolean
     */
    public function containsKey($key);

    /**
     * Puts a new element in the map.
     *
     * @param K $key
     * @param V $value
     *
     * @return void
     */
    public function set($key, $value);

    /**
     * Removes an element from the map.
     *
     * @param K $key
     *
     * @return V
     */
    public function remove($key);

    /**
     * Adds all another map to this map, and returns itself.
     *
     * @param MapInterface<K,V> $map
     *
     * @return MapInterface<K,V>
     */
    public function addMap(MapInterface $map);

    /**
     * Returns an array with the keys.
     *
     * @return array<K>
     */
    public function keys();

    /**
     * Returns an array with the values.
     *
     * @return array<V>
     */
    public function values();

    /**
     * Returns a new sequence by omitting the given number of elements from the beginning.
     *
     * If the passed number is greater than the available number of elements, all will be removed.
     *
     * @param integer $number
     *
     * @return MapInterface<K,V>
     */
    public function drop($number);

    /**
     * Returns a new sequence by omitting the given number of elements from the end.
     *
     * If the passed number is greater than the available number of elements, all will be removed.
     *
     * @param integer $number
     *
     * @return MapInterface<K,V>
     */
    public function dropRight($number);

    /**
     * Returns a new sequence by omitting elements from the beginning for as long as the callable returns true.
     *
     * @param callable $callable Receives the element to drop as first argument, and returns true (drop), or false (stop).
     *
     * @return MapInterface<K,V>
     */
    public function dropWhile($callable);

    /**
     * Creates a new collection by taking the given number of elements from the beginning
     * of the current collection.
     *
     * If the passed number is greater than the available number of elements, then all elements
     * will be returned as a new collection.
     *
     * @param integer $number
     *
     * @return MapInterface<K,V>
     */
    public function take($number);

    /**
     * Creates a new collection by taking elements from the current collection
     * for as long as the callable returns true.
     *
     * @param callable $callable
     *
     * @return MapInterface<K,V>
     */
    public function takeWhile($callable);
}
<?php

/*
 * Copyright 2012 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace PhpCollection;

/**
 * Interface for mutable sequences.
 *
 * Equality of elements in the sequence is established via a shallow comparison (===).
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface SequenceInterface extends CollectionInterface
{
    /**
     * Returns the first element in the collection if available.
     *
     * @return Option<T>
     */
    public function first();

    /**
     * Returns the last element in the collection if available.
     *
     * @return Option<T>
     */
    public function last();

    /**
     * Returns all elements in this sequence.
     *
     * @return array<T>
     */
    public function all();

    /**
     * Adds the elements of another sequence to this sequence.
     *
     * @param SequenceInterface<T> $seq
     *
     * @return SequenceInterface<T>
     */
    public function addSequence(SequenceInterface $seq);

    /**
     * Returns the index of the passed element.
     *
     * @param T $elem
     *
     * @return integer the index (0-based), or -1 if not found
     */
    public function indexOf($elem);

    /**
     * Returns the last index of the passed element.
     *
     * @param T $elem
     * @return integer the index (0-based), or -1 if not found
     */
    public function lastIndexOf($elem);

    /**
     * Returns whether the given index is defined in the sequence.
     *
     * @param integer $index (0-based)
     * @return boolean
     */
    public function isDefinedAt($index);

    /**
     * Returns the first index where the given callable returns true.
     *
     * @param callable $callable receives the element as first argument, and returns true, or false
     *
     * @return integer the index (0-based), or -1 if the callable returns false for all elements
     */
    public function indexWhere($callable);

    /**
     * Returns the last index where the given callable returns true.
     *
     * @param callable $callable receives the element as first argument, and returns true, or false
     *
     * @return integer the index (0-based), or -1 if the callable returns false for all elements
     */
    public function lastIndexWhere($callable);

    /**
     * Returns all indices of this collection.
     *
     * @return array<integer>
     */
    public function indices();

    /**
     * Returns the element at the given index.
     *
     * @param integer $index (0-based)
     *
     * @return T
     */
    public function get($index);

    /**
     * Adds an element to the sequence.
     *
     * @param T $elem
     *
     * @return void
     */
    public function add($elem);

    /**
     * Removes the element at the given index, and returns it.
     *
     * @param integer $index
     *
     * @return T
     */
    public function remove($index);

    /**
     * Adds all elements to the sequence.
     *
     * @param array<T> $elements
     *
     * @return void
     */
    public function addAll(array $elements);

    /**
     * Updates the value at the given index.
     *
     * @param integer $index
     * @param T $value
     *
     * @return void
     */
    public function update($index, $value);

    /**
     * Returns a new sequence by omitting the given number of elements from the beginning.
     *
     * If the passed number is greater than the available number of elements, all will be removed.
     *
     * @param integer $number
     *
     * @return SequenceInterface
     */
    public function drop($number);

    /**
     * Returns a new sequence by omitting the given number of elements from the end.
     *
     * If the passed number is greater than the available number of elements, all will be removed.
     *
     * @param integer $number
     *
     * @return SequenceInterface
     */
    public function dropRight($number);

    /**
     * Returns a new sequence by omitting elements from the beginning for as long as the callable returns true.
     *
     * @param callable $callable Receives the element to drop as first argument, and returns true (drop), or false (stop).
     *
     * @return SequenceInterface
     */
    public function dropWhile($callable);

    /**
     * Creates a new collection by taking the given number of elements from the beginning
     * of the current collection.
     *
     * If the passed number is greater than the available number of elements, then all elements
     * will be returned as a new collection.
     *
     * @param integer $number
     *
     * @return CollectionInterface<T>
     */
    public function take($number);

    /**
     * Creates a new collection by taking elements from the current collection
     * for as long as the callable returns true.
     *
     * @param callable $callable
     *
     * @return CollectionInterface<T>
     */
    public function takeWhile($callable);
}
<?php

/*
 * Copyright 2012 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace PhpCollection;

use PhpOption\LazyOption;
use PhpOption\Some;
use PhpOption\None;

abstract class AbstractCollection
{
    public function contains($searchedElem)
    {
        foreach ($this as $elem) {
            if ($elem === $searchedElem) {
                return true;
            }
        }

        return false;
    }

    public function find($callable)
    {
        $self = $this;

        return new LazyOption(function() use ($callable, $self) {
            foreach ($self as $elem) {
                if (call_user_func($callable, $elem) === true) {
                    return new Some($elem);
                }
            }

            return None::create();
        });
    }
}<?php

/*
 * Copyright 2012 Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace PhpCollection;

/**
 * Basic interface which adds some behaviors, and a few methods common to all collections.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface CollectionInterface extends \Traversable, \Countable
{
    /**
     * Returns whether this collection contains the passed element.
     *
     * @param mixed $elem
     *
     * @return boolean
     */
    public function contains($elem);

    /**
     * Returns whether the collection is empty.
     *
     * @return boolean
     */
    public function isEmpty();
}                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.<?php

if ( ! is_file($autoloadFile = __DIR__.'/../vendor/autoload.php')) {
    echo 'Could not find "vendor/autoload.php". Did you forget to run "composer install --dev"?'.PHP_EOL;
    exit(1);
}

require_once $autoloadFile;<?php

namespace PhpCollection\Tests;

use PhpCollection\SortedSequence;

class SortedSequenceTest extends \PHPUnit_Framework_TestCase
{
    private $seq;
    private $a;
    private $b;

    public function testAdd()
    {
        $this->seq->add(1);
        $this->assertSame(array(0, 0, 1, $this->a, $this->b), $this->seq->all());

        $this->seq->add(2);
        $this->assertSame(array(0, 0, 1, 2, $this->a, $this->b), $this->seq->all());
    }

    public function testAddAll()
    {
        $this->seq->addAll(array(2, 1, 3));
        $this->assertSame(array(0, 0, 1, 2, 3, $this->a, $this->b), $this->seq->all());

        $this->seq->addAll(array(2, 3, 1, 2));
        $this->assertSame(array(0, 0, 1, 1, 2, 2, 2, 3, 3, $this->a, $this->b), $this->seq->all());
    }

    public function testTake()
    {
        $seq = $this->seq->take(2);
        $this->assertInstanceOf('PhpCollection\SortedSequence', $seq);
        $this->assertSame(array(0, 0), $seq->all());
    }

    protected function setUp()
    {
        $this->seq = new SortedSequence(function($a, $b) {
            if (is_integer($a)) {
                if ( ! is_integer($b)) {
                    return -1;
                }

                return $a - $b;
            }

            if (is_integer($b)) {
                return 1;
            }

            return -1;
        });
        $this->seq->addAll(array(
            0,
            $this->a = new \stdClass,
            $this->b = new \stdClass,
            0,
        ));
    }
}<?php

namespace PhpCollection\Tests;

use PhpCollection\Map;

class MapTest extends \PHPUnit_Framework_TestCase
{
    private $map;

    public function testSet()
    {
        $this->assertTrue($this->map->get('asdf')->isEmpty());
        $this->map->set('asdf', 'foo');
        $this->assertEquals('foo', $this->map->get('asdf')->get());

        $this->assertEquals('bar', $this->map->get('foo')->get());
        $this->map->set('foo', 'asdf');
        $this->assertEquals('asdf', $this->map->get('foo')->get());
    }

    public function testSetSetAll()
    {
        $this->map->setAll(array('foo' => 'asdf', 'bar' => array('foo')));
        $this->assertEquals(array('foo' => 'asdf', 'bar' => array('foo'), 'baz' => 'boo'), iterator_to_array($this->map));
    }

    public function testAddMap()
    {
        $map = new Map();
        $map->set('foo', array('bar'));
        $this->map->addMap($map);

        $this->assertEquals(array('foo' => array('bar'), 'bar' => 'baz', 'baz' => 'boo'), iterator_to_array($this->map));
    }

    public function testRemove()
    {
        $this->assertTrue($this->map->get('foo')->isDefined());
        $this->assertEquals('bar', $this->map->remove('foo'));
        $this->assertFalse($this->map->get('foo')->isDefined());
    }

    public function testClear()
    {
        $this->assertCount(3, $this->map);
        $this->map->clear();
        $this->assertCount(0, $this->map);
    }

    /**
     * @expectedException InvalidArgumentException
     * @expectedExceptionMessage The map has no key named "asdfasdf".
     */
    public function testRemoveWithUnknownIndex()
    {
        $this->map->remove('asdfasdf');
    }

    public function testFirst()
    {
        $this->assertEquals(array('foo', 'bar'), $this->map->first()->get());
        $this->map->clear();
        $this->assertTrue($this->map->first()->isEmpty());
    }

    public function testLast()
    {
        $this->assertEquals(array('baz', 'boo'), $this->map->last()->get());
        $this->map->clear();
        $this->assertTrue($this->map->last()->isEmpty());
    }

    public function testContains()
    {
        $this->assertTrue($this->map->contains('boo'));
        $this->assertFalse($this->map->contains('asdf'));
    }

    public function testContainsKey()
    {
        $this->assertTrue($this->map->containsKey('foo'));
        $this->assertFalse($this->map->containsKey('boo'));
    }

    public function testIsEmpty()
    {
        $this->assertFalse($this->map->isEmpty());
        $this->map->clear();
        $this->assertTrue($this->map->isEmpty());
    }

    public function testDropWhile()
    {
        $newMap = $this->map->dropWhile(function($k, $v) { return 'foo' === $k || 'baz' === $v; });
        $this->assertEquals(array('baz' => 'boo'), iterator_to_array($newMap));
        $this->assertCount(3, $this->map);
    }

    public function testDrop()
    {
        $newMap = $this->map->drop(2);
        $this->assertEquals(array('baz' => 'boo'), iterator_to_array($newMap));
        $this->assertCount(3, $this->map);
    }

    /**
     * @expectedException InvalidArgumentException
     * @expectedExceptionMessage The number must be greater than 0, but got -4.
     */
    public function testDropWithNegativeNumber()
    {
        $this->map->drop(-4);
    }

    public function testDropRight()
    {
        $newMap = $this->map->dropRight(2);
        $this->assertEquals(array('foo' => 'bar'), iterator_to_array($newMap));
        $this->assertCount(3, $this->map);
    }

    /**
     * @expectedException InvalidArgumentException
     * @expectedExceptionMessage The number must be greater than 0, but got -5.
     */
    public function testDropRightWithNegativeNumber()
    {
        $this->map->dropRight(-5);
    }

    public function testTake()
    {
        $newMap = $this->map->take(1);
        $this->assertEquals(array('foo' => 'bar'), iterator_to_array($newMap));
        $this->assertCount(3, $this->map);
    }

    /**
     * @expectedException InvalidArgumentException
     * @expectedExceptionMessage The number must be greater than 0, but got -5.
     */
    public function testTakeWithNegativeNumber()
    {
        $this->map->take(-5);
    }

    public function testTakeWhile()
    {
        $newMap = $this->map->takeWhile(function($k, $v) { return 'foo' === $k || 'baz' === $v; });
        $this->assertEquals(array('foo' => 'bar', 'bar' => 'baz'), iterator_to_array($newMap));
        $this->assertCount(3, $this->map);
    }

    public function testFind()
    {
        $foundElem = $this->map->find(function($k, $v) { return 'foo' === $k && 'bar' === $v; });
        $this->assertEquals(array('foo', 'bar'), $foundElem->get());

        $this->assertTrue($this->map->find(function() { return false; })->isEmpty());
    }

    public function testKeys()
    {
        $this->assertEquals(array('foo', 'bar', 'baz'), $this->map->keys());
    }

    public function testValues()
    {
        $this->assertEquals(array('bar', 'baz', 'boo'), $this->map->values());
    }

    protected function setUp()
    {
        $this->map = new Map();
        $this->map->setAll(array(
            'foo' => 'bar',
            'bar' => 'baz',
            'baz' => 'boo',
        ));
    }
}<?php

namespace PhpCollection\Tests;

use PhpCollection\Sequence;
use OutOfBoundsException;
use stdClass;

class SequenceTest extends \PHPUnit_Framework_TestCase
{
    private $seq;
    private $a;
    private $b;

    public function testGet()
    {
        $this->assertSame(0, $this->seq->get(0));
        $this->assertSame($this->a, $this->seq->get(1));
    }

    public function testIndexOf()
    {
        $this->assertSame(0, $this->seq->indexOf(0));
        $this->assertSame(1, $this->seq->indexOf($this->a));
        $this->assertSame(2, $this->seq->indexOf($this->b));
        $this->assertSame(-1, $this->seq->indexOf(1));
    }

    public function testLastIndexOf()
    {
        $this->assertSame(3, $this->seq->lastIndexOf(0));
        $this->assertSame(1, $this->seq->lastIndexOf($this->a));
        $this->assertSame(2, $this->seq->lastIndexOf($this->b));
        $this->assertSame(-1, $this->seq->lastIndexOf(1));
    }

    public function testAddSequence()
    {
        $seq = new Sequence();
        $seq->add(1);
        $seq->add(0);

        $this->seq->addSequence($seq);

        $this->assertSame(array(
            0,
            $this->a,
            $this->b,
            0,
            1,
            0,
        ), $this->seq->all());
    }

    public function testIsDefinedAt()
    {
        $this->assertTrue($this->seq->isDefinedAt(0));
        $this->assertTrue($this->seq->isDefinedAt(1));
        $this->assertFalse($this->seq->isDefinedAt(9999999));
    }

    public function testIndexWhere()
    {
        $this->assertSame(-1, $this->seq->indexWhere(function() { return false; }));
        $this->assertSame(0, $this->seq->indexWhere(function() { return true; }));
    }

    public function testLastIndexWhere()
    {
        $this->assertSame(-1, $this->seq->lastIndexWhere(function() { return false; }));
        $this->assertSame(3, $this->seq->lastIndexWhere(function() { return true; }));
    }

    public function testFirst()
    {
        $this->assertSame(0, $this->seq->first()->get());
        $this->assertSame(0, $this->seq->last()->get());
    }

    public function testIndices()
    {
        $this->assertSame(array(0, 1, 2, 3), $this->seq->indices());
    }

    public function testContains()
    {
        $this->assertTrue($this->seq->contains(0));
        $this->assertTrue($this->seq->contains($this->a));
        $this->assertFalse($this->seq->contains(9999));
        $this->assertFalse($this->seq->contains(new stdClass()));
    }

    public function testFind()
    {
        $a = $this->a;

        $this->assertSame($this->a, $this->seq->find(function($x) use ($a) { return $a === $x; })->get());
        $this->assertFalse($this->seq->find(function() { return false; })->isDefined());
    }

    public function testIsEmpty()
    {
        $this->assertFalse($this->seq->isEmpty());
        $seq = new Sequence();
        $this->assertTrue($seq->isEmpty());
    }

    public function testAdd()
    {
        $this->seq->add(1);
        $this->assertSame(array(0, $this->a, $this->b, 0, 1), $this->seq->all());

        $this->seq->sortWith(function($a, $b) {
            if (is_integer($a)) {
                if ( ! is_integer($b)) {
                    return -1;
                }

                return $a > $b ? 1 : -1;
            }

            if (is_integer($b)) {
                return 1;
            }

            return 1;
        });

        $this->assertSame(array(0, 0, 1, $this->a, $this->b), $this->seq->all());
    }

    public function testUpdate()
    {
        $this->assertSame(0, $this->seq->get(0));
        $this->seq->update(0, 5);
        $this->assertSame(5, $this->seq->get(0));
    }

    /**
     * @expectedException InvalidArgumentException
     * @expectedExceptionMessage There is no element at index "99999".
     */
    public function testUpdateWithNonExistentIndex()
    {
        $this->seq->update(99999, 0);
    }

    public function testAddAll()
    {
        $this->seq->addAll(array(2, 1, 3));
        $this->assertSame(array(0, $this->a, $this->b, 0, 2, 1, 3), $this->seq->all());

        $this->seq->sortWith(function($a, $b) {
            if (is_integer($a)) {
                if ( ! is_integer($b)) {
                    return -1;
                }

                return $a > $b ? 1 : -1;
            }

            if (is_integer($b)) {
                return 1;
            }

            return -1;
        });

        $this->assertSame(array(0, 0, 1, 2, 3, $this->a, $this->b), $this->seq->all());
    }

    public function testTake()
    {
        $this->assertSame(array(0), $this->seq->take(1)->all());
        $this->assertSame(array(0, $this->a), $this->seq->take(2)->all());
        $this->assertSame(array(0, $this->a, $this->b, 0), $this->seq->take(9999)->all());
    }

    /**
     * @expectedException InvalidArgumentException
     * @expectedExceptionMessage $number must be greater than 0, but got -5.
     */
    public function testTakeWithNegativeNumber()
    {
        $this->seq->take(-5);
    }

    public function testTakeWhile()
    {
        $this->assertSame(array(0), $this->seq->takeWhile('is_integer')->all());
    }

    public function testCount()
    {
        $this->assertCount(4, $this->seq);
    }

    public function testTraverse()
    {
        $this->assertSame(array(0, $this->a, $this->b, 0), iterator_to_array($this->seq));
    }

    public function testDrop()
    {
        $this->assertSame(array($this->a, $this->b, 0), $this->seq->drop(1)->all());
        $this->assertSame(array($this->b, 0), $this->seq->drop(2)->all());
        $this->assertSame(array(), $this->seq->drop(9999)->all());
    }

    /**
     * @expectedException InvalidArgumentException
     * @expectedExceptionMessage The number must be greater than 0, but got -5.
     */
    public function testDropWithNegativeIndex()
    {
        $this->seq->drop(-5);
    }

    public function testDropRight()
    {
        $this->assertSame(array(0, $this->a, $this->b), $this->seq->dropRight(1)->all());
        $this->assertSame(array(0, $this->a), $this->seq->dropRight(2)->all());
        $this->assertSame(array(), $this->seq->dropRight(9999)->all());
    }

    /**
     * @expectedException InvalidArgumentException
     * @expectedExceptionMessage The number must be greater than 0, but got -5.
     */
    public function testDropRightWithNegativeIndex()
    {
        $this->seq->dropRight(-5);
    }

    public function testDropWhile()
    {
        $this->assertSame(array(0, $this->a, $this->b, 0), $this->seq->dropWhile(function() { return false; })->all());
        $this->assertSame(array(), $this->seq->dropWhile(function() { return true; })->all());
    }

    public function testRemove()
    {
        $this->assertSame(0, $this->seq->remove(0));
        $this->assertSame($this->a, $this->seq->remove(0));
        $this->assertSame(0, $this->seq->remove(1));
    }

    /**
     * @expectedException OutOfBoundsException
     * @expectedExceptionMessage The index "9999" is not in the interval [0, 4).
     */
    public function testRemoveWithInvalidIndex()
    {
        $this->seq->remove(9999);
    }

    protected function setUp()
    {
        $this->seq = new Sequence();
        $this->seq->addAll(array(
            0,
            $this->a = new \stdClass(),
            $this->b = new \stdClass(),
            0
        ));
    }
}{
    "hash": "02937754d829ce8d6ca657debd7324ad",
    "packages": [
        {
            "name": "phpoption/phpoption",
            "version": "0.9.0",
            "source": {
                "type": "git",
                "url": "git://github.com/schmittjoh/php-option",
                "reference": "0.9.0"
            },
            "dist": {
                "type": "zip",
                "url": "https://github.com/schmittjoh/php-option/archive/0.9.0.zip",
                "reference": "0.9.0",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.0"
            },
            "require-dev": {
                "phpunit/phpunit": "3.7.*"
            },
            "time": "2012-11-12 08:25:35",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-0": {
                    "PhpOption\\": "src/"
                }
            },
            "license": [
                "Apache2"
            ],
            "authors": [
                {
                    "name": "Johannes M. Schmitt",
                    "email": "schmittjoh@gmail.com",
                    "homepage": "https://github.com/schmittjoh",
                    "role": "Developer of wrapped JMSSerializerBundle"
                }
            ],
            "description": "Option Type for PHP",
            "keywords": [
                "php",
                "language",
                "type",
                "option"
            ]
        }
    ],
    "packages-dev": [

    ],
    "aliases": [

    ],
    "minimum-stability": "stable",
    "stability-flags": [

    ]
}
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="tests/bootstrap.php"
>
    <testsuites>
        <testsuite name="PhpCollection Test Suite">
            <directory>./tests/PhpCollection/</directory>
        </testsuite>
    </testsuites>

    <groups>
        <exclude>
            <group>performance</group>
        </exclude>
    </groups>
</phpunit>
THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.

BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.

1. Definitions

    "Adaptation" means a work based upon the Work, or upon the Work and other pre-existing works, such as a translation, adaptation, derivative work, arrangement of music or other alterations of a literary or artistic work, or phonogram or performance and includes cinematographic adaptations or any other form in which the Work may be recast, transformed, or adapted including in any form recognizably derived from the original, except that a work that constitutes a Collection will not be considered an Adaptation for the purpose of this License. For the avoidance of doubt, where the Work is a musical work, performance or phonogram, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered an Adaptation for the purpose of this License.
    "Collection" means a collection of literary or artistic works, such as encyclopedias and anthologies, or performances, phonograms or broadcasts, or other works or subject matter other than works listed in Section 1(f) below, which, by reason of the selection and arrangement of their contents, constitute intellectual creations, in which the Work is included in its entirety in unmodified form along with one or more other contributions, each constituting separate and independent works in themselves, which together are assembled into a collective whole. A work that constitutes a Collection will not be considered an Adaptation (as defined above) for the purposes of this License.
    "Distribute" means to make available to the public the original and copies of the Work through sale or other transfer of ownership.
    "Licensor" means the individual, individuals, entity or entities that offer(s) the Work under the terms of this License.
    "Original Author" means, in the case of a literary or artistic work, the individual, individuals, entity or entities who created the Work or if no individual or entity can be identified, the publisher; and in addition (i) in the case of a performance the actors, singers, musicians, dancers, and other persons who act, sing, deliver, declaim, play in, interpret or otherwise perform literary or artistic works or expressions of folklore; (ii) in the case of a phonogram the producer being the person or legal entity who first fixes the sounds of a performance or other sounds; and, (iii) in the case of broadcasts, the organization that transmits the broadcast.
    "Work" means the literary and/or artistic work offered under the terms of this License including without limitation any production in the literary, scientific and artistic domain, whatever may be the mode or form of its expression including digital form, such as a book, pamphlet and other writing; a lecture, address, sermon or other work of the same nature; a dramatic or dramatico-musical work; a choreographic work or entertainment in dumb show; a musical composition with or without words; a cinematographic work to which are assimilated works expressed by a process analogous to cinematography; a work of drawing, painting, architecture, sculpture, engraving or lithography; a photographic work to which are assimilated works expressed by a process analogous to photography; a work of applied art; an illustration, map, plan, sketch or three-dimensional work relative to geography, topography, architecture or science; a performance; a broadcast; a phonogram; a compilation of data to the extent it is protected as a copyrightable work; or a work performed by a variety or circus performer to the extent it is not otherwise considered a literary or artistic work.
    "You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation.
    "Publicly Perform" means to perform public recitations of the Work and to communicate to the public those public recitations, by any means or process, including by wire or wireless means or public digital performances; to make available to the public Works in such a way that members of the public may access these Works from a place and at a place individually chosen by them; to perform the Work to the public by any means or process and the communication to the public of the performances of the Work, including by public digital performance; to broadcast and rebroadcast the Work by any means including signs, sounds or images.
    "Reproduce" means to make copies of the Work by any means including without limitation by sound or visual recordings and the right of fixation and reproducing fixations of the Work, including storage of a protected performance or phonogram in digital form or other electronic medium.

2. Fair Dealing Rights. Nothing in this License is intended to reduce, limit, or restrict any uses free from copyright or rights arising from limitations or exceptions that are provided for in connection with the copyright protection under copyright law or other applicable laws.

3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below:

    to Reproduce the Work, to incorporate the Work into one or more Collections, and to Reproduce the Work as incorporated in the Collections; and,
    to Distribute and Publicly Perform the Work including as incorporated in Collections.

The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats, but otherwise you have no rights to make Adaptations. Subject to 8(f), all rights not expressly granted by Licensor are hereby reserved, including but not limited to the rights set forth in Section 4(d).

4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions:

    You may Distribute or Publicly Perform the Work only under the terms of this License. You must include a copy of, or the Uniform Resource Identifier (URI) for, this License with every copy of the Work You Distribute or Publicly Perform. You may not offer or impose any terms on the Work that restrict the terms of this License or the ability of the recipient of the Work to exercise the rights granted to that recipient under the terms of the License. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties with every copy of the Work You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Work, You may not impose any effective technological measures on the Work that restrict the ability of a recipient of the Work from You to exercise the rights granted to that recipient under the terms of the License. This Section 4(a) applies to the Work as incorporated in a Collection, but this does not require the Collection apart from the Work itself to be made subject to the terms of this License. If You create a Collection, upon notice from any Licensor You must, to the extent practicable, remove from the Collection any credit as required by Section 4(c), as requested.
    You may not exercise any of the rights granted to You in Section 3 above in any manner that is primarily intended for or directed toward commercial advantage or private monetary compensation. The exchange of the Work for other copyrighted works by means of digital file-sharing or otherwise shall not be considered to be intended for or directed toward commercial advantage or private monetary compensation, provided there is no payment of any monetary compensation in connection with the exchange of copyrighted works.
    If You Distribute, or Publicly Perform the Work or Collections, You must, unless a request has been made pursuant to Section 4(a), keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or if the Original Author and/or Licensor designate another party or parties (e.g., a sponsor institute, publishing entity, journal) for attribution ("Attribution Parties") in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; (ii) the title of the Work if supplied; (iii) to the extent reasonably practicable, the URI, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work. The credit required by this Section 4(c) may be implemented in any reasonable manner; provided, however, that in the case of a Collection, at a minimum such credit will appear, if a credit for all contributing authors of Collection appears, then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors. For the avoidance of doubt, You may only use the credit required by this Section for the purpose of attribution in the manner set out above and, by exercising Your rights under this License, You may not implicitly or explicitly assert or imply any connection with, sponsorship or endorsement by the Original Author, Licensor and/or Attribution Parties, as appropriate, of You or Your use of the Work, without the separate, express prior written permission of the Original Author, Licensor and/or Attribution Parties.

    For the avoidance of doubt:
        Non-waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme cannot be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License;
        Waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme can be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License if Your exercise of such rights is for a purpose or use which is otherwise than noncommercial as permitted under Section 4(b) and otherwise waives the right to collect royalties through any statutory or compulsory licensing scheme; and,
        Voluntary License Schemes. The Licensor reserves the right to collect royalties, whether individually or, in the event that the Licensor is a member of a collecting society that administers voluntary licensing schemes, via that society, from any exercise by You of the rights granted under this License that is for a purpose or use which is otherwise than noncommercial as permitted under Section 4(b).
    Except as otherwise agreed in writing by the Licensor or as may be otherwise permitted by applicable law, if You Reproduce, Distribute or Publicly Perform the Work either by itself or as part of any Collections, You must not distort, mutilate, modify or take other derogatory action in relation to the Work which would be prejudicial to the Original Author's honor or reputation.

5. Representations, Warranties and Disclaimer

UNLESS OTHERWISE MUTUALLY AGREED BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.

6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

7. Termination

    This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Collections from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License.
    Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above.

8. Miscellaneous

    Each time You Distribute or Publicly Perform the Work or a Collection, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License.
    If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
    No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent.
    This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You.
    The rights granted under, and the subject matter referenced, in this License were drafted utilizing the terminology of the Berne Convention for the Protection of Literary and Artistic Works (as amended on September 28, 1979), the Rome Convention of 1961, the WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and the Universal Copyright Convention (as revised on July 24, 1971). These rights and subject matter take effect in the relevant jurisdiction in which the License terms are sought to be enforced according to the corresponding provisions of the implementation of those treaty provisions in the applicable national law. If the standard suite of rights granted under applicable copyright law includes additional rights not granted under this License, such additional rights are deemed to be included in the License; this License is not intended to restrict the license of any rights under applicable law.
{
    "name":        "cilex/console-service-provider",
    "description": "Console Service Provider",
    "keywords":    ["pimple", "cilex", "silex", "console", "service-provider"],
    "license":     "MIT",
    "authors": [
        { "name":  "Mike van Riel", "email": "mike.vanriel@naenius.com" },
        { "name": "Beau Simensen",  "email": "beau@dflydev.com" }
    ],
    "require": {
        "php":             ">=5.3.3",
        "pimple/pimple":   "1.*@dev",
        "symfony/console": "~2.1"
    },
    "require-dev": {
        "cilex/cilex": "1.*@dev",
        "silex/silex": "1.*@dev"
    },
    "autoload": {
        "psr-0": { "Cilex\\Provider\\Console": "src" }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.0-dev"
        }
    }
}
<?php

/*
 * This file is part of the Cilex framework.
 *
 * (c) Mike van Riel <mike.vanriel@naenius.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Cilex\Provider\Console;

/**
 * Pimple Console Service Provider
 *
 * @author Beau Simensen <beau@dflydev.com>
 */
class BaseConsoleServiceProvider
{
    /**
     * {@inheritdoc}
     */
    public function register(\Pimple $container)
    {
        foreach ($this->getDefaults() as $key => $value) {
            if (!isset($container[$key])) {
                $container[$key] = $value;
            }
        }

        $container['console'] = $container->share(function() use ($container) {
            $class    = $container['console.class'];
            $instance = new $class(
                isset($container['console.name']) ? $container['console.name'] : '',
                isset($container['console.version']) ? $container['console.version'] : null
            );

            if ($instance instanceof ContainerAwareApplication) {
                $instance->setContainer($container);
            }

            return $instance;
        });
    }

    protected function getDefaults()
    {
        return array(
            'console.name' => 'Cilex Application',
            'console.class' => 'Cilex\Provider\Console\ContainerAwareApplication',
        );
    }
}
<?php

/*
 * This file is part of the Cilex framework.
 *
 * (c) Mike van Riel <mike.vanriel@naenius.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Cilex\Provider\Console;

use Symfony\Component\Console\Application;

/**
 * Cilex Pimple Console Application
 *
 * @author Beau Simensen <beau@dflydev.com>
 */
class ContainerAwareApplication extends Application
{
    /** @var \Pimple */
    private $container;

    /**
     * Constructor
     *
     * @param string  $name      The name of the application
     * @param string  $version   The version of the application
     */
    public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
    {
        parent::__construct($name, $version);
    }

    /**
     * Sets a container instance onto this application.
     *
     * @param \Pimple $container
     *
     * @return void
     */
    public function setContainer(\Pimple $container)
    {
        $this->container = $container;
    }

    /**
     * Get the Container.
     *
     * @return \Pimple
     */
    public function getContainer()
    {
        return $this->container;
    }

    /**
     * Returns a service contained in the application container or null if none is found with that name.
     *
     * This is a convenience method used to retrieve an element from the Application container without having to assign
     * the results of the getContainer() method in every call.
     *
     * @param string $name Name of the service.
     *
     * @see self::getContainer()
     *
     * @api
     *
     * @return mixed|null
     */
    public function getService($name)
    {
        return isset($this->container[$name]) ? $this->container[$name] : null;
    }
}
<?php

/*
 * This file is part of the Cilex framework.
 *
 * (c) Mike van Riel <mike.vanriel@naenius.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Cilex\Provider\Console;

use Cilex\Application;
use Cilex\ServiceProviderInterface;

/**
 * Cilex Console Service Provider
 *
 * @author Beau Simensen <beau@dflydev.com>
 */
class ConsoleServiceProvider implements ServiceProviderInterface
{
    /**
     * {@inheritdoc}
     */
    public function register(Application $app)
    {
        $serviceProvider = new BaseConsoleServiceProvider();
        $serviceProvider->register($app);
    }
}
<?php

/*
 * This file is part of the Cilex framework.
 *
 * (c) Mike van Riel <mike.vanriel@naenius.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Cilex\Provider\Console\Adapter\Silex;

use Cilex\Provider\Console\BaseConsoleServiceProvider;
use Silex\Application;
use Silex\ServiceProviderInterface;

/**
 * Silex Console Service Provider adapter
 *
 * @author Beau Simensen <beau@dflydev.com>
 */
class ConsoleServiceProvider implements ServiceProviderInterface
{
    /**
     * {@inheritdoc}
     */
    public function boot(Application $app)
    {
    }

    /**
     * {@inheritdoc}
     */
    public function register(Application $app)
    {
        $serviceProvider = new BaseConsoleServiceProvider;
        $serviceProvider->register($app);
    }
}
{
    "hash": "52d1f50b5bb3e0f2626a352a0ed2a947",
    "packages": [
        {
            "name": "pimple/pimple",
            "version": "dev-master",
            "source": {
                "type": "git",
                "url": "git://github.com/fabpot/Pimple.git",
                "reference": "v1.0.1"
            },
            "dist": {
                "type": "zip",
                "url": "https://github.com/fabpot/Pimple/archive/v1.0.1.zip",
                "reference": "v1.0.1",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.0"
            },
            "time": "2012-11-11 08:32:34",
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.0.x-dev"
                }
            },
            "installation-source": "source",
            "autoload": {
                "psr-0": {
                    "Pimple": "lib/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                }
            ],
            "description": "Pimple is a simple Dependency Injection Container for PHP 5.3",
            "homepage": "http://pimple.sensiolabs.org",
            "keywords": [
                "dependency injection",
                "container"
            ]
        },
        {
            "name": "symfony/console",
            "version": "v2.1.4",
            "target-dir": "Symfony/Component/Console",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Console",
                "reference": "v2.1.4"
            },
            "dist": {
                "type": "zip",
                "url": "https://github.com/symfony/Console/archive/v2.1.4.zip",
                "reference": "v2.1.4",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "time": "2012-11-09 08:52:51",
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.1-dev"
                }
            },
            "installation-source": "dist",
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Console": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Console Component",
            "homepage": "http://symfony.com"
        }
    ],
    "packages-dev": null,
    "aliases": [

    ],
    "minimum-stability": "stable",
    "stability-flags": {
        "pimple/pimple": 20,
        "cilex/cilex": 20,
        "silex/silex": 20
    }
}
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant::Config.run do |config|
  config.vm.box     = "precise64"
  config.vm.box_url = "http://files.vagrantup.com/precise64.box"

  config.vm.provision :puppet do |puppet|
     puppet.manifests_path = ".puppet/manifests"
     puppet.manifest_file  = "manifest.pp"
     puppet.options        = [ '--verbose' ]
  end
end
{
    "name":        "cilex/cilex",
    "description": "The PHP micro-framework for Command line tools based on the Symfony2 Components",
    "keywords":    ["microframework","cli"],
    "homepage":    "http://cilex.github.com",
    "license":     "MIT",
    "autoload":{
        "psr-0":{ "Cilex": "src/" }
    },
    "authors":[
        { "name":  "Mike van Riel", "email": "mike.vanriel@naenius.com" }
    ],
    "require":{
        "php":                            ">=5.3.3",
        "pimple/pimple":                  "1.0.*",
        "symfony/process":                "~2.1",
        "symfony/finder":                 "~2.1",
        "cilex/console-service-provider": "1.*"
    },
    "require-dev":{
        "symfony/validator": "~2.1",
        "phpunit/phpunit":   "3.7.*"
    },
    "suggest":{
        "monolog/monolog":   ">=1.0.0",
        "symfony/yaml":      ">=1.0.0",
        "symfony/validator": ">=1.0.0"
    },
    "extra":{
        "branch-alias": { "dev-master": "1.0-dev" }
    }
}
<?php

/*
 * This file is part of the Cilex framework.
 *
 * (c) Mike van Riel <mike.vanriel@naenius.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Cilex\Command;

use \Symfony\Component\Console;

/**
 * Base class for Cilex commands.
 *
 * @author Mike van Riel <mike.vanriel@naenius.com>
 *
 * @api
 */
abstract class Command extends Console\Command\Command
{
    /**
     * Returns the application container.
     *
     * @return \Cilex\Application
     */
    public function getContainer()
    {
        return $this->getApplication()->getContainer();
    }

    /**
     * Returns a service contained in the application container or null if none
     * is found with that name.
     *
     * This is a convenience method used to retrieve an element from the
     * Application container without having to assign the results of the
     * getContainer() method in every call.
     *
     * @param string $name Name of the service
     *
     * @see self::getContainer()
     *
     * @api
     *
     * @return \stdClass|null
     */
    public function getService($name)
    {
        return $this->getApplication()->getService($name);
    }
}
<?php

/*
 * This file is part of the Cilex framework.
 *
 * (c) Mike van Riel <mike.vanriel@naenius.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Cilex\Command;

use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * Example command for testing purposes.
 */
class GreetCommand extends Command
{
    protected function configure()
    {
        $this
            ->setName('demo:greet')
            ->setDescription('Greet someone')
            ->addArgument('name', InputArgument::OPTIONAL, 'Who do you want to greet?')
            ->addOption('yell', null, InputOption::VALUE_NONE, 'If set, the task will yell in uppercase letters');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $text = 'Hello';
        $name = $input->getArgument('name');
        if ($name) {
            $text .= ' '.$name;
        }

        if ($input->getOption('yell')) {
            $text = strtoupper($text);
        }

        $output->writeln($text);
    }
}
<?php

/*
 * This file is part of the Cilex framework.
 *
 * (c) Mike van Riel <mike.vanriel@naenius.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Cilex\Command;

use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Command\Command as BaseCommand;

/**
 * Example command for testing purposes.
 */
class DemoInfoCommand extends BaseCommand
{
    protected function configure()
    {
        $this
            ->setName('demo:info')
            ->setDescription('Get Application Information');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        // This is a contrived example to show accessing services
        // from the container without needing the command itself
        // to extend from anything but Symfony Console's base Command.

        $app = $this->getApplication()->getService('console');

        $output->writeln('Name: ' . $app->getName());
        $output->writeln('Version: ' . $app->getVersion());
    }
}
<?php

/*
 * This file is part of the Cilex framework.
 *
 * (c) Mike van Riel <mike.vanriel@naenius.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Cilex;

use \Symfony\Component\Console;
use \Cilex\Provider\Console\ConsoleServiceProvider;

/**
 * The Cilex framework class.
 *
 * @author Mike van Riel <mike.vanriel@naenius.com>
 *
 * @api
 */
class Application extends \Pimple
{
    /**
     * Version number for Cilex
     */
    const VERSION = '1.0.0';

    /**
     * Registers the autoloader and necessary components.
     *
     * @param string      $name    Name for this application.
     * @param string|null $version Version number for this application.
     */
    public function __construct($name, $version = null, array $values = array())
    {
        parent::__construct();

        $consoleConfig = array('console.name' => $name);
        if (null !== $version) {
            $consoleConfig['console.version'] = $version;
        }
        $this->register(new ConsoleServiceProvider(), $consoleConfig);

        foreach ($values as $key => $value) {
            $this[$key] = $value;
        }
    }

    /**
     * Executes this application.
     *
     * @param bool $interactive runs in an interactive shell if true.
     *
     * @return void
     */
    public function run($interactive = false)
    {
        $app = $this['console'];
        if ($interactive) {
            $app = new Console\Shell($app);
        }

        $app->run();
    }

    /**
     * Adds a command object.
     *
     * If a command with the same name already exists, it will be overridden.
     *
     * @param \Cilex\Command\Command $command A Command object
     *
     * @api
     *
     * @return void
     */
    public function command(Console\Command\Command $command)
    {
        $this['console']->add($command);
    }

    /**
     * Registers a service provider.
     *
     * @param \Cilex\ServiceProviderInterface|\Silex\ServiceProviderInterface $provider
     *     A ServiceProviderInterface instance
     * @param mixed[]                                                         $values
     *     An array of values that customizes the provider
     *
     * @return void
     */
    public function register($provider, array $values = array())
    {
        if ((!$provider instanceof \Cilex\ServiceProviderInterface)
            && (!$provider instanceof \Silex\ServiceProviderInterface)
        ) {
            throw new \InvalidArgumentException(
                'Extensions should implement either Cilex or Silex\' ServiceProviderInterface'
            );
        }

        $provider->register($this);

        foreach ($values as $key => $value) {
            $this[$key] = $value;
        }
    }
}
<?php

/*
 * This file is part of the Cilex framework.
 *
 * (c) Mike van Riel <mike.vanriel@naenius.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Cilex;

/**
 * Interface that must implement all Cilex service providers.
 *
 * @author Mike van Riel <mike.vanriel@naenius.com>
 */
interface ServiceProviderInterface
{
    /**
     * Registers services on the given app.
     *
     * @param Application $app An Application instance
     */
    public function register(Application $app);
}
<?php

/*
 * This file is part of the Cilex framework.
 *
 * (c) Mike van Riel <mike.vanriel@naenius.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Cilex\Provider;

use Cilex\Application;
use Cilex\ServiceProviderInterface;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Configuration;
use Doctrine\Common\EventManager;

/**
 * Doctrine DBAL Provider.
 *
 * This Service Provider is an adaptation of the DoctrineServiceProvider for
 * Silex written by Fabien Potencier.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Mike van Riel <mike.vanriel@naenius.com>
 */
class DoctrineServiceProvider implements ServiceProviderInterface
{
    public function register(Application $app)
    {
        $app['db.default_options'] = array(
            'driver'   => 'pdo_mysql',
            'dbname'   => null,
            'host'     => 'localhost',
            'user'     => 'root',
            'password' => null,
        );

        $app['dbs.options.initializer'] = $app->protect(
            function () use ($app) {
                static $initialized = false;

                if ($initialized) {
                    return;
                }

                $initialized = true;

                if (!isset($app['dbs.options'])) {
                    $app['dbs.options'] = array('default' => isset($app['db.options']) ? $app['db.options'] : array());
                }

                $tmp = $app['dbs.options'];
                foreach ($tmp as $name => &$options) {
                    $options = array_replace($app['db.default_options'], $options);

                    if (!isset($app['dbs.default'])) {
                        $app['dbs.default'] = $name;
                    }
                }
                $app['dbs.options'] = $tmp;
            }
        );

        $app['dbs'] = $app->share(
            function () use ($app) {
                $app['dbs.options.initializer']();

                $dbs = new \Pimple();
                foreach ($app['dbs.options'] as $name => $options) {
                    if ($app['dbs.default'] === $name) {
                        // we use shortcuts here in case the default has been overriden
                        $config = $app['db.config'];
                        $manager = $app['db.event_manager'];
                    } else {
                        $config = $app['dbs.config'][$name];
                        $manager = $app['dbs.event_manager'][$name];
                    }

                    $dbs[$name] = DriverManager::getConnection($options, $config, $manager);
                }

                return $dbs;
            }
        );

        $app['dbs.config'] = $app->share(
            function () use ($app) {
                $app['dbs.options.initializer']();

                $configs = new \Pimple();
                foreach ($app['dbs.options'] as $name => $options) {
                    $configs[$name] = new Configuration();
                }

                return $configs;
            }
        );

        $app['dbs.event_manager'] = $app->share(
            function () use ($app) {
                $app['dbs.options.initializer']();

                $managers = new \Pimple();
                foreach ($app['dbs.options'] as $name => $options) {
                    $managers[$name] = new EventManager();
                }

                return $managers;
            }
        );

        // shortcuts for the "first" DB
        $app['db'] = $app->share(
            function () use ($app) {
                $dbs = $app['dbs'];

                return $dbs[$app['dbs.default']];
            }
        );

        $app['db.config'] = $app->share(
            function () use ($app) {
                $dbs = $app['dbs.config'];

                return $dbs[$app['dbs.default']];
            }
        );

        $app['db.event_manager'] = $app->share(
            function () use ($app) {
                $dbs = $app['dbs.event_manager'];

                return $dbs[$app['dbs.default']];
            }
        );

        if (isset($app['db.dbal.class_path'])) {
            $app['autoloader']->registerNamespace('Doctrine\\DBAL', $app['db.dbal.class_path']);
        }

        if (isset($app['db.common.class_path'])) {
            $app['autoloader']->registerNamespace('Doctrine\\Common', $app['db.common.class_path']);
        }
    }
}
<?php

/*
 * This file is part of the Cilex framework.
 *
 * (c) Mike van Riel <mike.vanriel@naenius.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Cilex\Provider;

use Cilex\Application;
use Cilex\ServiceProviderInterface;
use Symfony\Component\Yaml;

class ConfigServiceProvider implements ServiceProviderInterface
{
    public function register(Application $app)
    {
        $app['config'] = $app->share(
            function () use ($app) {
                if (!file_exists($app['config.path'])) {
                    throw new \InvalidArgumentException(
                        $app['config.path'] . ' is not a valid path to the '
                        .'configuration'
                    );
                }

                $fullpath = explode('.', $app['config.path']);

                switch (strtolower(end($fullpath))) {
                    case 'php':
                        $result = include($app['config.path']);
                        break;
                    case 'yml':
                        $parser = new Yaml\Parser();
                        $result = new \ArrayObject(
                            $parser->parse(file_get_contents($app['config.path']))
                        );
                        break;
                    case 'xml':
                        $result = simplexml_load_file($app['config.path']);
                        break;
                    case 'json':
                        $result = json_decode(file_get_contents($app['config.path']));

                        if (null == $result) {

                            throw new \InvalidArgumentException(
                                'Unable to decode the configuration file: ' . $app['config.path']
                            );
                        }
                        break;
                    default:
                        throw new \InvalidArgumentException(
                            'Unable to load configuration; the provided file extension was not recognized. '
                            .'Only yml, xml or json allowed'
                        );
                        break;
                }

                return $result;
            }
        );
    }
}
<?php

/*
 * This file is part of the Cilex framework.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Cilex\Provider;

use Cilex\Application;
use Cilex\ServiceProviderInterface;

use Symfony\Component\Validator\Validator;
use Symfony\Component\Validator\Mapping\ClassMetadataFactory;
use Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader;
use Symfony\Component\Validator\ConstraintValidatorFactory;
use Symfony\Component\Validator\DefaultTranslator;

/**
 * Symfony Validator component Provider.
 *
 * This class is an adaptation of the Silex MonologServiceProvider written by
 * Fabien Potencier.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Mike van Riel <mike.vanvriel@naenius.com>
 */
class ValidatorServiceProvider implements ServiceProviderInterface
{
    public function register(Application $app)
    {
        $app['validator'] = $app->share(
            function () use ($app) {
                return new Validator(
                    $app['validator.mapping.class_metadata_factory'],
                    $app['validator.validator_factory'],
                    $app['validator.default_translator']
                );
            }
        );

        $app['validator.mapping.class_metadata_factory'] = $app->share(
            function () use ($app) {
                return new ClassMetadataFactory(new StaticMethodLoader());
            }
        );

        $app['validator.validator_factory'] = $app->share(
            function () {
                return new ConstraintValidatorFactory();
            }
        );

        $app['validator.default_translator'] = $app->share(
            function () {
                if (!class_exists('Symfony\\Component\\Validator\\DefaultTranslator')){
                    return array();
                }
                
                return new DefaultTranslator();
            }
        );

        if (isset($app['validator.class_path'])) {
            $app['autoloader']->registerNamespace('Symfony\\Component\\Validator', $app['validator.class_path']);
        }
    }
}
<?php

/*
 * This file is part of the Cilex framework.
 *
 * (c) Mike van Riel <mike.vanriel@naenius.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Cilex\Provider;

use Monolog\Logger;
use Monolog\Handler\StreamHandler;

use Cilex\Application;
use Cilex\ServiceProviderInterface;

/**
 * Monolog Provider.
 *
 * This class is an adaptation of the Silex MonologServiceProvider written by
 * Fabien Potencier.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Mike van Riel <mike.vanvriel@naenius.com>
 */
class MonologServiceProvider implements ServiceProviderInterface
{
    public function register(Application $app)
    {
        $app['monolog'] = $app->share(
            function () use ($app) {
                $log = new Logger(isset($app['monolog.name']) ? $app['monolog.name'] : 'myapp');
                $app['monolog.configure']($log);

                return $log;
            }
        );

        $app['monolog.configure'] = $app->protect(
            function ($log) use ($app) {
                $log->pushHandler($app['monolog.handler']);
            }
        );

        $app['monolog.handler'] = function () use ($app) {
            return new StreamHandler($app['monolog.logfile'], $app['monolog.level']);
        };

        if (!isset($app['monolog.level'])) {
            $app['monolog.level'] = function () {
                return Logger::DEBUG;
            };
        }

        if (isset($app['monolog.class_path'])) {
            $app['autoloader']->registerNamespace('Monolog', $app['monolog.class_path']);
        }
    }
}
<?php

/*
 * This file is part of the Cilex framework.
 *
 * (c) Mike van Riel <mike.vanriel@naenius.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Cilex;

use Symfony\Component\Finder\Finder;
use Symfony\Component\Process\Process;

/**
 * The Compiler class compiles the Cilex framework.
 *
 * This is an adapted version of the Silex\Compiler class.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Mike van Riel <mike.vanriel@naenius.com>
 */
class Compiler
{
    protected $version;

    /**
     * Compiles the Cilex source code into one single Phar file.
     *
     * @param string $pharFile Name of the output Phar file
     */
    public function compile($pharFile = 'cilex.phar')
    {
        if (file_exists($pharFile)) {
            unlink($pharFile);
        }

        $process = new Process('git log --pretty="%h %ci" -n1 HEAD');
        if ($process->run() > 0) {
            throw new \RuntimeException('The git binary cannot be found.');
        }
        $this->version = trim($process->getOutput());

        $phar = new \Phar($pharFile, 0, 'cilex.phar');
        $phar->setSignatureAlgorithm(\Phar::SHA1);

        $phar->startBuffering();

        $finder = new Finder();
        $finder->files()
            ->ignoreVCS(true)
            ->name('*.php')
            ->notName('Compiler.php')
            ->in(__DIR__.'/..')
            ->in(__DIR__.'/../../vendor/pimple/pimple/lib')
            ->in(__DIR__.'/../../vendor/cilex/console-service-provider')
            ->in(__DIR__.'/../../vendor/symfony/console/Symfony/Component/Console');

        foreach ($finder as $file) {
            $this->addFile($phar, $file);
        }

        $this->addFile($phar, new \SplFileInfo(__DIR__.'/../../LICENSE'), false);

        $this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/autoload.php'));
        $this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/ClassLoader.php'));
        $this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/autoload_real.php'));
        $this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/autoload_namespaces.php'));
        $this->addFile($phar, new \SplFileInfo(__DIR__.'/../../vendor/composer/autoload_classmap.php'));

        // Stubs
        $phar->setStub($this->getStub());

        $phar->stopBuffering();

        // $phar->compressFiles(\Phar::GZ);

        unset($phar);
    }

    protected function addFile(\Phar $phar, \splFileInfo $file, $strip = true)
    {
        $path = str_replace(dirname(dirname(__DIR__)).DIRECTORY_SEPARATOR, '', $file->getRealPath());

        $content = file_get_contents($file);
        if ($strip) {
            $content = self::stripWhitespace($content);
        }
        $content = str_replace('@package_version@', $this->version, $content);

        $phar->addFromString($path, $content);
    }

    protected function getStub()
    {
        return <<<'EOF'
<?php

/*
 * This file is part of the Cilex framework.
 *
 * (c) Mike van Riel <mike.vanriel@naenius.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

Phar::mapPhar('cilex.phar');

require_once 'phar://cilex.phar/vendor/autoload.php';

if ('cli' === php_sapi_name() && basename(__FILE__) === basename($_SERVER['argv'][0]) && isset($_SERVER['argv'][1])) {
    switch ($_SERVER['argv'][1]) {
        case 'update':
            $remoteFilename = 'http://cilex.github.com/get/cilex.phar';
            $localFilename = __DIR__.'/cilex.phar';

            file_put_contents($localFilename, file_get_contents($remoteFilename));
            break;

        case 'check':
            $latest = trim(file_get_contents('http://cilex.github.com/get/version'));

            if ($latest != Cilex\Application::VERSION) {
                printf("A newer Cilex version is available (%s).\n", $latest);
            } else {
                print("You are using the latest Cilex version.\n");
            }
            break;

        case 'version':
            printf("Cilex version %s\n", Cilex\Application::VERSION);
            break;

        default:
            printf("Unknown command '%s' (available commands: version, check, and update).\n", $_SERVER['argv'][1]);
    }

    exit(0);
}

__HALT_COMPILER();
EOF;
    }

    /**
     * Removes whitespace from a PHP source string while preserving line numbers.
     *
     * Based on Kernel::stripComments(), but keeps line numbers intact.
     *
     * @param string $source A PHP string
     *
     * @return string The PHP string with the whitespace removed
     */
    public static function stripWhitespace($source)
    {
        if (!function_exists('token_get_all')) {
            return $source;
        }

        $output = '';
        foreach (token_get_all($source) as $token) {
            if (is_string($token)) {
                $output .= $token;
            } elseif (in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) {
                $output .= str_repeat("\n", substr_count($token[1], "\n"));
            } elseif (T_WHITESPACE === $token[0]) {
                // reduce wide spaces
                $whitespace = preg_replace('{[ \t]+}', ' ', $token[1]);
                // normalize newlines to \n
                $whitespace = preg_replace('{(?:\r\n|\r|\n)}', "\n", $whitespace);
                // trim leading spaces
                $whitespace = preg_replace('{\n +}', "\n", $whitespace);
                $output .= $whitespace;
            } else {
                $output .= $token[1];
            }
        }

        return $output;
    }
}

<?php
$autoload = __DIR__ . '/../vendor/autoload.php';
if (!file_exists($autoload)) {
    echo "Please run `php composer.phar install` first." . PHP_EOL;
    exit(1);
}
require_once $autoload;

use Cilex\Compiler;

$compiler = new Compiler();
$compiler->compile();
import sys, os

templates_path = ['.templates']
source_suffix = '.rst'
master_doc = 'index'
project = u'Cilex'
copyright = u'2013, Mike van Riel'

version = '1.0'
release = '1.0.0-alpha1'
pygments_style = 'sphinx'

html_theme = 'agogo'
html_static_path = ['.static']
htmlhelp_basename = 'Cilexdoc'

# -- Options for LaTeX output --------------------------------------------------

latex_elements = {
    'papersize': 'a4paper',
    'pointsize': '10pt',
}

# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
  ('index', 'Cilex.tex', u'Cilex Documentation', u'Mike van Riel', 'manual'),
]

latex_logo = '.static/logo.png'

# -- Options for manual page output --------------------------------------------

# (source start file, name, description, authors, manual section).
man_pages = [
    ('index', 'cilex', u'Cilex Documentation', [u'Mike van Riel'], 1)
]

# -- Options for Texinfo output ------------------------------------------------

# (source start file, target name, title, author, dir menu entry, description,
# category)
texinfo_documents = [
  ('index', 'Cilex', u'Cilex Documentation', u'Mike van Riel', 'Cilex', 'One line description of project.',
   'Miscellaneous'),
]# Makefile for Sphinx documentation
#

# You can set these variables from the command line.
SPHINXOPTS    =
SPHINXBUILD   = sphinx-build
PAPER         =
BUILDDIR      = .build

# Internal variables.
PAPEROPT_a4     = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source

.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext

help:
	@echo "Please use \`make <target>' where <target> is one of"
	@echo "  html       to make standalone HTML files"
	@echo "  dirhtml    to make HTML files named index.html in directories"
	@echo "  singlehtml to make a single large HTML file"
	@echo "  pickle     to make pickle files"
	@echo "  json       to make JSON files"
	@echo "  htmlhelp   to make HTML files and a HTML help project"
	@echo "  qthelp     to make HTML files and a qthelp project"
	@echo "  devhelp    to make HTML files and a Devhelp project"
	@echo "  epub       to make an epub"
	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
	@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
	@echo "  text       to make text files"
	@echo "  man        to make manual pages"
	@echo "  texinfo    to make Texinfo files"
	@echo "  info       to make Texinfo files and run them through makeinfo"
	@echo "  gettext    to make PO message catalogs"
	@echo "  changes    to make an overview of all changed/added/deprecated items"
	@echo "  linkcheck  to check all external links for integrity"
	@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"

clean:
	-rm -rf $(BUILDDIR)/*

html:
	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
	@echo
	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."

dirhtml:
	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
	@echo
	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."

singlehtml:
	$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
	@echo
	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."

pickle:
	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
	@echo
	@echo "Build finished; now you can process the pickle files."

json:
	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
	@echo
	@echo "Build finished; now you can process the JSON files."

htmlhelp:
	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
	@echo
	@echo "Build finished; now you can run HTML Help Workshop with the" \
	      ".hhp project file in $(BUILDDIR)/htmlhelp."

qthelp:
	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
	@echo
	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Cilex.qhcp"
	@echo "To view the help file:"
	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Cilex.qhc"

devhelp:
	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
	@echo
	@echo "Build finished."
	@echo "To view the help file:"
	@echo "# mkdir -p $$HOME/.local/share/devhelp/Cilex"
	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Cilex"
	@echo "# devhelp"

epub:
	$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
	@echo
	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."

latex:
	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
	@echo
	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
	@echo "Run \`make' in that directory to run these through (pdf)latex" \
	      "(use \`make latexpdf' here to do that automatically)."

latexpdf:
	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
	@echo "Running LaTeX files through pdflatex..."
	$(MAKE) -C $(BUILDDIR)/latex all-pdf
	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."

text:
	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
	@echo
	@echo "Build finished. The text files are in $(BUILDDIR)/text."

man:
	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
	@echo
	@echo "Build finished. The manual pages are in $(BUILDDIR)/man."

texinfo:
	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
	@echo
	@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
	@echo "Run \`make' in that directory to run these through makeinfo" \
	      "(use \`make info' here to do that automatically)."

info:
	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
	@echo "Running Texinfo files through makeinfo..."
	make -C $(BUILDDIR)/texinfo info
	@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."

gettext:
	$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
	@echo
	@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."

changes:
	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
	@echo
	@echo "The overview file is in $(BUILDDIR)/changes."

linkcheck:
	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
	@echo
	@echo "Link check complete; look for any errors in the above output " \
	      "or in $(BUILDDIR)/linkcheck/output.txt."

doctest:
	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
	@echo "Testing of doctests in the sources finished, look at the " \
	      "results in $(BUILDDIR)/doctest/output.txt."
Copyright (c) 2012 Mike van Riel

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.<?php
require_once __DIR__ . '/vendor/autoload.php';

$app = new \Cilex\Application('Cilex');
//$app->command(new \Cilex\Command\GreetCommand());
$app->run();{
    "_readme": [
        "This file locks the dependencies of your project to a known state",
        "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
    ],
    "hash": "ea3c59deb9972f6262fb17f3b25e0d45",
    "packages": [
        {
            "name": "cilex/console-service-provider",
            "version": "1.0.0",
            "source": {
                "type": "git",
                "url": "https://github.com/Cilex/console-service-provider.git",
                "reference": "1.0.0"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/Cilex/console-service-provider/zipball/1.0.0",
                "reference": "1.0.0",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3",
                "pimple/pimple": "1.*@dev",
                "symfony/console": "~2.1"
            },
            "require-dev": {
                "cilex/cilex": "1.*@dev",
                "silex/silex": "1.*@dev"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.0-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Cilex\\Provider\\Console": "src"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Beau Simensen",
                    "email": "beau@dflydev.com",
                    "homepage": "http://beausimensen.com"
                },
                {
                    "name": "Mike van Riel",
                    "email": "mike.vanriel@naenius.com"
                }
            ],
            "description": "Console Service Provider",
            "keywords": [
                "cilex",
                "console",
                "pimple",
                "service-provider",
                "silex"
            ],
            "time": "2012-12-19 10:50:58"
        },
        {
            "name": "pimple/pimple",
            "version": "v1.0.2",
            "source": {
                "type": "git",
                "url": "https://github.com/fabpot/Pimple.git",
                "reference": "v1.0.2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/fabpot/Pimple/zipball/v1.0.2",
                "reference": "v1.0.2",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.0"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.0.x-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Pimple": "lib/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                }
            ],
            "description": "Pimple is a simple Dependency Injection Container for PHP 5.3",
            "homepage": "http://pimple.sensiolabs.org",
            "keywords": [
                "container",
                "dependency injection"
            ],
            "time": "2013-03-08 08:21:40"
        },
        {
            "name": "symfony/console",
            "version": "v2.3.2",
            "target-dir": "Symfony/Component/Console",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Console.git",
                "reference": "v2.3.2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Console/zipball/v2.3.2",
                "reference": "v2.3.2",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "require-dev": {
                "symfony/event-dispatcher": "~2.1"
            },
            "suggest": {
                "symfony/event-dispatcher": ""
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Console\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Console Component",
            "homepage": "http://symfony.com",
            "time": "2013-07-11 19:36:36"
        },
        {
            "name": "symfony/finder",
            "version": "v2.3.2",
            "target-dir": "Symfony/Component/Finder",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Finder.git",
                "reference": "v2.3.2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Finder/zipball/v2.3.2",
                "reference": "v2.3.2",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Finder\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Finder Component",
            "homepage": "http://symfony.com",
            "time": "2013-07-01 12:17:23"
        },
        {
            "name": "symfony/process",
            "version": "v2.3.2",
            "target-dir": "Symfony/Component/Process",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Process.git",
                "reference": "v2.3.2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Process/zipball/v2.3.2",
                "reference": "v2.3.2",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Process\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Process Component",
            "homepage": "http://symfony.com",
            "time": "2013-07-01 12:24:43"
        }
    ],
    "packages-dev": [
        {
            "name": "phpunit/php-code-coverage",
            "version": "1.2.12",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
                "reference": "1.2.12"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/1.2.12",
                "reference": "1.2.12",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3",
                "phpunit/php-file-iterator": ">=1.3.0@stable",
                "phpunit/php-text-template": ">=1.1.1@stable",
                "phpunit/php-token-stream": ">=1.1.3@stable"
            },
            "require-dev": {
                "phpunit/phpunit": "3.7.*@dev"
            },
            "suggest": {
                "ext-dom": "*",
                "ext-xdebug": ">=2.0.5"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.2.x-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "PHP/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
            "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
            "keywords": [
                "coverage",
                "testing",
                "xunit"
            ],
            "time": "2013-07-06 06:26:16"
        },
        {
            "name": "phpunit/php-file-iterator",
            "version": "1.3.3",
            "source": {
                "type": "git",
                "url": "git://github.com/sebastianbergmann/php-file-iterator.git",
                "reference": "1.3.3"
            },
            "dist": {
                "type": "zip",
                "url": "https://github.com/sebastianbergmann/php-file-iterator/zipball/1.3.3",
                "reference": "1.3.3",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "File/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "FilterIterator implementation that filters files based on a list of suffixes.",
            "homepage": "http://www.phpunit.de/",
            "keywords": [
                "filesystem",
                "iterator"
            ],
            "time": "2012-10-11 04:44:38"
        },
        {
            "name": "phpunit/php-text-template",
            "version": "1.1.4",
            "source": {
                "type": "git",
                "url": "git://github.com/sebastianbergmann/php-text-template.git",
                "reference": "1.1.4"
            },
            "dist": {
                "type": "zip",
                "url": "https://github.com/sebastianbergmann/php-text-template/zipball/1.1.4",
                "reference": "1.1.4",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "Text/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Simple template engine.",
            "homepage": "https://github.com/sebastianbergmann/php-text-template/",
            "keywords": [
                "template"
            ],
            "time": "2012-10-31 11:15:28"
        },
        {
            "name": "phpunit/php-timer",
            "version": "1.0.4",
            "source": {
                "type": "git",
                "url": "git://github.com/sebastianbergmann/php-timer.git",
                "reference": "1.0.4"
            },
            "dist": {
                "type": "zip",
                "url": "https://github.com/sebastianbergmann/php-timer/zipball/1.0.4",
                "reference": "1.0.4",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "PHP/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Utility class for timing",
            "homepage": "http://www.phpunit.de/",
            "keywords": [
                "timer"
            ],
            "time": "2012-10-11 04:45:58"
        },
        {
            "name": "phpunit/php-token-stream",
            "version": "1.1.7",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/php-token-stream.git",
                "reference": "1.1.7"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1.1.7",
                "reference": "1.1.7",
                "shasum": ""
            },
            "require": {
                "ext-tokenizer": "*",
                "php": ">=5.3.3"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "PHP/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Wrapper around PHP's tokenizer extension.",
            "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
            "keywords": [
                "tokenizer"
            ],
            "time": "2013-07-29 14:27:06"
        },
        {
            "name": "phpunit/phpunit",
            "version": "3.7.22",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/phpunit.git",
                "reference": "3.7.22"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3.7.22",
                "reference": "3.7.22",
                "shasum": ""
            },
            "require": {
                "ext-dom": "*",
                "ext-pcre": "*",
                "ext-reflection": "*",
                "ext-spl": "*",
                "php": ">=5.3.3",
                "phpunit/php-code-coverage": "~1.2.1",
                "phpunit/php-file-iterator": ">=1.3.1",
                "phpunit/php-text-template": ">=1.1.1",
                "phpunit/php-timer": "~1.0.2",
                "phpunit/phpunit-mock-objects": "~1.2.0",
                "symfony/yaml": "~2.0"
            },
            "require-dev": {
                "pear-pear/pear": "1.9.4"
            },
            "suggest": {
                "ext-json": "*",
                "ext-simplexml": "*",
                "ext-tokenizer": "*",
                "phpunit/php-invoker": ">=1.1.0,<1.2.0"
            },
            "bin": [
                "composer/bin/phpunit"
            ],
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "3.7.x-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "PHPUnit/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                "",
                "../../symfony/yaml/"
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de",
                    "role": "lead"
                }
            ],
            "description": "The PHP Unit Testing framework.",
            "homepage": "http://www.phpunit.de/",
            "keywords": [
                "phpunit",
                "testing",
                "xunit"
            ],
            "time": "2013-07-06 06:29:15"
        },
        {
            "name": "phpunit/phpunit-mock-objects",
            "version": "1.2.3",
            "source": {
                "type": "git",
                "url": "git://github.com/sebastianbergmann/phpunit-mock-objects.git",
                "reference": "1.2.3"
            },
            "dist": {
                "type": "zip",
                "url": "https://github.com/sebastianbergmann/phpunit-mock-objects/archive/1.2.3.zip",
                "reference": "1.2.3",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3",
                "phpunit/php-text-template": ">=1.1.1@stable"
            },
            "suggest": {
                "ext-soap": "*"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "PHPUnit/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Mock Object library for PHPUnit",
            "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
            "keywords": [
                "mock",
                "xunit"
            ],
            "time": "2013-01-13 10:24:48"
        },
        {
            "name": "symfony/translation",
            "version": "v2.3.2",
            "target-dir": "Symfony/Component/Translation",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Translation.git",
                "reference": "v2.3.2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Translation/zipball/v2.3.2",
                "reference": "v2.3.2",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "require-dev": {
                "symfony/config": "~2.0",
                "symfony/yaml": "~2.2"
            },
            "suggest": {
                "symfony/config": "",
                "symfony/yaml": ""
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Translation\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Translation Component",
            "homepage": "http://symfony.com",
            "time": "2013-05-13 14:36:40"
        },
        {
            "name": "symfony/validator",
            "version": "v2.3.2",
            "target-dir": "Symfony/Component/Validator",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Validator.git",
                "reference": "v2.3.2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Validator/zipball/v2.3.2",
                "reference": "v2.3.2",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3",
                "symfony/translation": "~2.0"
            },
            "require-dev": {
                "symfony/config": "~2.2",
                "symfony/http-foundation": "~2.1",
                "symfony/intl": "~2.3",
                "symfony/yaml": "~2.0"
            },
            "suggest": {
                "doctrine/common": "",
                "symfony/config": "",
                "symfony/http-foundation": "",
                "symfony/intl": "",
                "symfony/yaml": ""
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Validator\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Validator Component",
            "homepage": "http://symfony.com",
            "time": "2013-07-08 13:36:15"
        },
        {
            "name": "symfony/yaml",
            "version": "v2.3.2",
            "target-dir": "Symfony/Component/Yaml",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Yaml.git",
                "reference": "v2.3.2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Yaml/zipball/v2.3.2",
                "reference": "v2.3.2",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Yaml\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Yaml Component",
            "homepage": "http://symfony.com",
            "time": "2013-07-11 19:36:36"
        }
    ],
    "aliases": [

    ],
    "minimum-stability": "stable",
    "stability-flags": [

    ],
    "platform": {
        "php": ">=5.3.3"
    },
    "platform-dev": [

    ]
}
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
    backupStaticAttributes="false"
    colors="true"
    convertErrorsToExceptions="true"
    convertNoticesToExceptions="true"
    convertWarningsToExceptions="true"
    processIsolation="false"
    stopOnFailure="false"
    syntaxCheck="false"
    bootstrap="vendor/autoload.php"
    >
    <testsuites>
        <testsuite name="Cilex Test Suite">
            <directory>./tests/Cilex/</directory>
        </testsuite>
    </testsuites>
</phpunit>{
    "name": "phpdocumentor/fileset",
    "description": "Fileset component for collecting a set of files given directories and file paths",
    "keywords": ["phpdoc", "files", "fileset"],
    "homepage": "http://www.phpdoc.org",
    "license": "MIT",
    "autoload": { "psr-0":{ "phpDocumentor": ["src/", "tests/unit/"] } },
    "require": {
        "php": ">=5.3.3",
        "symfony/finder": "~2.1"
    },
    "require-dev": {
        "phpunit/phpunit": "~3.7"
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Fileset;

/**
 * Files container handling directory scanning, project root detection and ignores.
 *
 * Always set any filtering options (extensions, ignore patterns, hidden files, symlinks)
 * _before_ adding any directories or files.  Such filtering is done immediately
 * upon loading the directory/file.  As such, setting filtering options
 * _after_ adding directories/files will seem as though your filters were ignored.
 *
 * @author  Mike van Riel <mike.vanriel@naenius.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class Collection extends \ArrayObject
{
    /** @var bool Whether to follow symlinks*/
    protected $follow_symlinks = false;

    /** @var bool Whether to ignore hidden files and folders */
    protected $ignore_hidden = false;

    /** @var Collection\IgnorePatterns */
    protected $ignore_patterns = array();

    /** @var \ArrayObject Array containing a list of allowed line endings */
    protected $allowed_extensions = null;

    /** @var string[] An array containing file names */
    protected $files = array();

    /**
     * Initializes the finding component.
     */
    public function __construct()
    {
        $this->ignore_patterns = new Collection\IgnorePatterns();
        $this->allowed_extensions = new \ArrayObject(
            array('php', 'php3', 'phtml')
        );
    }

    /**
     * Sets the patterns by which to detect which files to ignore.
     *
     * @param array $patterns Glob-like patterns to filter files.
     *
     * @return void
     */
    public function setIgnorePatterns(array $patterns)
    {
        $this->ignore_patterns = new Collection\IgnorePatterns($patterns);
    }

    /**
     * Returns the ignore patterns.
     *
     * @return Collection\IgnorePatterns
     */
    public function getIgnorePatterns()
    {
        return $this->ignore_patterns;
    }

    /**
     * Sets a list of allowed extensions; if not used php, php3 and phtml
     * is assumed.
     *
     * @param array $extensions An array containing extensions to match for.
     *
     * @return void
     */
    public function setAllowedExtensions(array $extensions)
    {
        $this->allowed_extensions = new \ArrayObject($extensions);
    }

    /**
     * Adds a file extension to the list of allowed extensions.
     *
     * No dot is necessary and will even prevent the extension from being
     * picked up.
     *
     * @param string $extension Allowed file Extension to add (i.e. php).
     *
     * @return void
     */
    public function addAllowedExtension($extension)
    {
        $this->allowed_extensions->append($extension);
    }

    /**
     * Adds the content of a set of directories to the list of files to parse.
     *
     * @param array $paths The paths whose contents to add to the collection.
     *
     * @return void
     */
    public function addDirectories(array $paths)
    {
        foreach ($paths as $path) {
            $this->addDirectory($path);
        }
    }

    /**
     * Retrieve all files in the given directory and add them to the parsing list.
     *
     * @param string $path A path to a folder, may be relative, absolute or
     *  even phar.
     *
     * @return void
     */
    public function addDirectory($path)
    {
        $finder = new \Symfony\Component\Finder\Finder();

        $patterns = $this->getIgnorePatterns()->getRegularExpression();

        if ($this->follow_symlinks) {
            $finder->followLinks();
        }

        // restrict names to those ending in the given extensions
        $finder
            ->files()
            ->in($path)
            ->name(
                '/\.('.implode('|', $this->allowed_extensions->getArrayCopy()).')$/'
            )
            ->ignoreDotFiles($this->getIgnoreHidden())
            ->filter(
                function(\SplFileInfo $file) use ($patterns) {
                    if (!$patterns) {
                        return true;
                    }

                    // apply ignore list on path instead of file, finder
                    // can't do that by default
                    return !preg_match($patterns, $file->getPathname());
                }
            );

        try {
            /** @var \SplFileInfo $file */
            foreach ($finder as $file) {
                $file = new File($file);
                $path = $file->getRealPath()
                    ? $file->getRealPath()
                    : $file->getPathname();

                $this[$path] = $file;
            }
        } catch(\LogicException $e)
        {
            // if a logic exception is thrown then no folders were included
            // for phpDocumentor this is not an issue since we accept separate
            // files as well
        }
    }

    /**
     * Adds a list of individual files to the collection.
     *
     * @param array $paths File locations, may be absolute, relative or even phar.
     *
     * @return void
     */
    public function addFiles(array $paths)
    {
        foreach ($paths as $path) {
            $this->addFile($path);
        }
    }

    /**
     * Adds a file to the collection.
     *
     * @param string $path File location, may be absolute, relative or even phar.
     *
     * @return void
     */
    public function addFile($path)
    {
        $paths = $this->getGlobbedPaths($path);
        foreach ($paths as $path) {
            $file = new File($path);
            $path = $file->getRealPath()
                ? $file->getRealPath()
                : $file->getPathname();

            $this[$path] = $file;
        }
    }

    /**
     * Get a globbed list out of the given path.
     *
     * This wrapper method normalizes for OS-divergent behavior of the native glob() function.
     * @param string $path
     * @return array
     */
    protected function getGlobbedPaths($path)
    {
        $paths = glob($path);

        /*
         * Windows glob('') returns an array with one empty member...
         * 'nix glob('') returns an empty array...
         * we'd prefer to have the File('') constructor throw the exception in this edge case,
         * so keep the Windows behavior.
         */
        $result = (array() === $paths) ? array('') : $paths;

        return $result;
    }

    /**
     * Returns a list of file paths that are ready to be parsed.
     *
     * Please note that the ignore pattern will be applied and all files are
     * converted to absolute paths.
     *
     * @return string[]
     */
    public function getFilenames()
    {
        return array_keys($this->getArrayCopy());
    }

    /**
     * Calculates the project root from the given files by determining their
     * highest common path.
     *
     * @return string
     */
    public function getProjectRoot()
    {
        $base = '';
        $files = array_keys($this->getArrayCopy());
        $parts = explode(DIRECTORY_SEPARATOR, reset($files));

        foreach ($parts as $part) {
            $base_part = $base . $part . DIRECTORY_SEPARATOR;
            foreach ($files as $dir) {
                if (substr($dir, 0, strlen($base_part)) != $base_part) {
                    return $base;
                }
            }

            $base = $base_part;
        }

        return $base;
    }

    /**
     * Sets whether to ignore hidden files and folders.
     *
     * @param boolean $ignore_hidden if true skips hidden files and folders.
     *
     * @return void
     */
    public function setIgnoreHidden($ignore_hidden)
    {
        $this->ignore_hidden = $ignore_hidden;
    }

    /**
     * Returns whether files and folders that are hidden are ignored.
     *
     * @return boolean
     */
    public function getIgnoreHidden()
    {
        return $this->ignore_hidden;
    }

    /**
     * Sets whether to follow symlinks.
     *
     * PHP version 5.2.11 is at least required since the
     * RecursiveDirectoryIterator does not support the FOLLOW_SYMLINKS
     * constant before that version.
     *
     * @param boolean $follow_symlinks
     *
     * @return void
     */
    public function setFollowSymlinks($follow_symlinks)
    {
        $this->follow_symlinks = $follow_symlinks;
    }

    /**
     * Returns whether to follow symlinks.
     *
     * @return boolean
     */
    public function getFollowSymlinks()
    {
        return $this->follow_symlinks;
    }

}
<?php

namespace phpDocumentor\Fileset;

class File extends \SplFileInfo
{
    /**
     * Open file for reading, and if it doesn't exist create it.
     *
     * @param string|\SplFileInfo $file
     *
     * @throws \InvalidArgumentException if an invalid type was passed
     */
    public function __construct($file)
    {
        if ($file instanceof \SplFileInfo) {
            $file = $file->getPathname();
        }

        if (!is_string($file)) {
            throw new \InvalidArgumentException(
                'Expected filename or object of type SplFileInfo but received '
                . get_class($file)
            );
        }

        if (empty($file)) {
            throw new \InvalidArgumentException(
                'Expected filename or object of type SplFileInfo but received nothing at all'
            );
        }

        parent::__construct($file);
    }

    /**
     * Returns the mime type for this file.
     *
     * @throws \RuntimeException if finfo failed to load
     *                           and/or mime_content_type is unavailable
     * @throws \LogicException if the mime type could not be interpreted
     *                         from the output of finfo_file
     *
     * @return string
     */
    public function getMimeType()
    {
        if (function_exists('finfo_open')) {
            $finfo = finfo_open(FILEINFO_MIME);
            if (!$finfo) {
                throw new \RuntimeException('Failed to open finfo');
            }

            $actualInfo = @finfo_file($finfo, $this->getPathname());
            if (false === $actualInfo) {
                throw new \RuntimeException('Failed to read file info via finfo');
            }
            $mime = strtolower($actualInfo);
            finfo_close($finfo);

            if (!preg_match(
                '/^([a-z0-9]+\/[a-z0-9\-\.]+);\s+charset=(.*)$/', $mime, $matches
            )) {
                throw new \LogicException(
                    'An error parsing the MIME type "'.$mime.'".'
                );
            }

            return $matches[1];
        } elseif (function_exists('mime_content_type')) {
            return mime_content_type($this->getPathname());
        }

        throw new \RuntimeException(
            'The finfo extension or mime_content_type function are needed to '
            .'determine the Mime Type for this file.'
        );
    }

    /**
     * Returns the file contents as a string.
     *
     * @return string
     * @throws \RuntimeException if unable to open the file
     */
    public function fread()
    {
        try {
            $file = $this->openFile('r');
        } catch (\Exception $exc) {
            throw new \RuntimeException('Unable to open file', 0, $exc);
        }

        $result = '';
        foreach ($file as $line) {
            $result .= $line;
        }

        return $result;
    }

    /**
     * Returns the filename, relative to the given root.
     *
     * @param string $root_path The root_path of which this file is composed.
     *
     * @throws \InvalidArgumentException if file is not in the project root.
     *
     * @return string
     *
     * @todo this protected method is unused in this class... can it be removed?
     */
    protected function getFilenameRelativeToRoot($root_path)
    {
        // strip path from filename
        $result = ltrim(
            substr($this->getPathname(), strlen($root_path)),
            DIRECTORY_SEPARATOR
        );

        if ($result === '') {
            throw new \InvalidArgumentException(
                'File "' . $this->getPathname() . '" is not present in the '
                .'given root: ' . $root_path
            );
        }

        return $result;
    }

}
<?php

namespace phpDocumentor\Fileset\Collection;

class IgnorePatterns extends \ArrayObject
{
    public function getRegularExpression()
    {
        $pattern = '';

        if ($this->count() > 0) {
            $patterns = array();
            foreach ($this as $item) {
                $this->convertToPregCompliant($item);
                $patterns[] = $item;
            }

            $pattern = '/('.implode('|', $patterns).')$/';
        }

        return $pattern;
    }

    /**
     * Converts $string into a string that can be used with preg_match.
     *
     * @param string &$string Glob-like pattern with wildcards ? and *.
     *
     * @author Greg Beaver <cellog@php.net>
     * @author mike van Riel <mike.vanriel@naenius.com>
     *
     * @see PhpDocumentor/phpDocumentor/Io.php
     *
     * @return void
     */
    protected function convertToPregCompliant(&$string)
    {
        $y = (DIRECTORY_SEPARATOR == '\\') ? '\\\\' : '\/';
        $string = str_replace('/', DIRECTORY_SEPARATOR, $string);
        $x = strtr(
            $string,
            array(
                 '?' => '.',
                 '*' => '.*',
                 '.' => '\\.',
                 '\\' => '\\\\',
                 '/' => '\\/',
                 '[' => '\\[',
                 ']' => '\\]',
                 '-' => '\\-'
            )
        );

        if ((strpos($string, DIRECTORY_SEPARATOR) !== false)
            && (strrpos($string, DIRECTORY_SEPARATOR) === strlen($string) - 1)
        ) {
            $x = "(?:.*$y$x?.*|$x.*)";
        }

        $string = $x;
    }

}
Copyright (c) 2010 Mike van Riel

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.{
    "_readme": [
        "This file locks the dependencies of your project to a known state",
        "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
    ],
    "hash": "191f6b1a1c9063b3a1215ba4d0fbe3dc",
    "packages": [
        {
            "name": "symfony/finder",
            "version": "v2.3.2",
            "target-dir": "Symfony/Component/Finder",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Finder.git",
                "reference": "v2.3.2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Finder/zipball/v2.3.2",
                "reference": "v2.3.2",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Finder\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Finder Component",
            "homepage": "http://symfony.com",
            "time": "2013-07-01 12:17:23"
        }
    ],
    "packages-dev": [
        {
            "name": "phpunit/php-code-coverage",
            "version": "1.2.12",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
                "reference": "1.2.12"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/1.2.12",
                "reference": "1.2.12",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3",
                "phpunit/php-file-iterator": ">=1.3.0@stable",
                "phpunit/php-text-template": ">=1.1.1@stable",
                "phpunit/php-token-stream": ">=1.1.3@stable"
            },
            "require-dev": {
                "phpunit/phpunit": "3.7.*@dev"
            },
            "suggest": {
                "ext-dom": "*",
                "ext-xdebug": ">=2.0.5"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.2.x-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "PHP/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
            "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
            "keywords": [
                "coverage",
                "testing",
                "xunit"
            ],
            "time": "2013-07-06 06:26:16"
        },
        {
            "name": "phpunit/php-file-iterator",
            "version": "1.3.3",
            "source": {
                "type": "git",
                "url": "git://github.com/sebastianbergmann/php-file-iterator.git",
                "reference": "1.3.3"
            },
            "dist": {
                "type": "zip",
                "url": "https://github.com/sebastianbergmann/php-file-iterator/zipball/1.3.3",
                "reference": "1.3.3",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "File/"
                ]
            },
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "FilterIterator implementation that filters files based on a list of suffixes.",
            "homepage": "http://www.phpunit.de/",
            "keywords": [
                "filesystem",
                "iterator"
            ],
            "time": "2012-10-11 04:44:38"
        },
        {
            "name": "phpunit/php-text-template",
            "version": "1.1.4",
            "source": {
                "type": "git",
                "url": "git://github.com/sebastianbergmann/php-text-template.git",
                "reference": "1.1.4"
            },
            "dist": {
                "type": "zip",
                "url": "https://github.com/sebastianbergmann/php-text-template/zipball/1.1.4",
                "reference": "1.1.4",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "Text/"
                ]
            },
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Simple template engine.",
            "homepage": "https://github.com/sebastianbergmann/php-text-template/",
            "keywords": [
                "template"
            ],
            "time": "2012-10-31 11:15:28"
        },
        {
            "name": "phpunit/php-timer",
            "version": "1.0.5",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/php-timer.git",
                "reference": "1.0.5"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/1.0.5",
                "reference": "1.0.5",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "PHP/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Utility class for timing",
            "homepage": "https://github.com/sebastianbergmann/php-timer/",
            "keywords": [
                "timer"
            ],
            "time": "2013-08-02 07:42:54"
        },
        {
            "name": "phpunit/php-token-stream",
            "version": "1.2.0",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/php-token-stream.git",
                "reference": "1.2.0"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1.2.0",
                "reference": "1.2.0",
                "shasum": ""
            },
            "require": {
                "ext-tokenizer": "*",
                "php": ">=5.3.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.2-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "PHP/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Wrapper around PHP's tokenizer extension.",
            "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
            "keywords": [
                "tokenizer"
            ],
            "time": "2013-08-04 05:57:48"
        },
        {
            "name": "phpunit/phpunit",
            "version": "3.7.23",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/phpunit.git",
                "reference": "3.7.23"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3.7.23",
                "reference": "3.7.23",
                "shasum": ""
            },
            "require": {
                "ext-dom": "*",
                "ext-pcre": "*",
                "ext-reflection": "*",
                "ext-spl": "*",
                "php": ">=5.3.3",
                "phpunit/php-code-coverage": "~1.2.1",
                "phpunit/php-file-iterator": ">=1.3.1",
                "phpunit/php-text-template": ">=1.1.1",
                "phpunit/php-timer": ">=1.0.4",
                "phpunit/phpunit-mock-objects": "~1.2.0",
                "symfony/yaml": "~2.0"
            },
            "require-dev": {
                "pear-pear/pear": "1.9.4"
            },
            "suggest": {
                "ext-json": "*",
                "ext-simplexml": "*",
                "ext-tokenizer": "*",
                "phpunit/php-invoker": ">=1.1.0,<1.2.0"
            },
            "bin": [
                "composer/bin/phpunit"
            ],
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "3.7.x-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "PHPUnit/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                "",
                "../../symfony/yaml/"
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de",
                    "role": "lead"
                }
            ],
            "description": "The PHP Unit Testing framework.",
            "homepage": "http://www.phpunit.de/",
            "keywords": [
                "phpunit",
                "testing",
                "xunit"
            ],
            "time": "2013-08-02 19:14:44"
        },
        {
            "name": "phpunit/phpunit-mock-objects",
            "version": "1.2.3",
            "source": {
                "type": "git",
                "url": "git://github.com/sebastianbergmann/phpunit-mock-objects.git",
                "reference": "1.2.3"
            },
            "dist": {
                "type": "zip",
                "url": "https://github.com/sebastianbergmann/phpunit-mock-objects/archive/1.2.3.zip",
                "reference": "1.2.3",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3",
                "phpunit/php-text-template": ">=1.1.1@stable"
            },
            "suggest": {
                "ext-soap": "*"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "PHPUnit/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Mock Object library for PHPUnit",
            "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
            "keywords": [
                "mock",
                "xunit"
            ],
            "time": "2013-01-13 10:24:48"
        },
        {
            "name": "symfony/yaml",
            "version": "v2.3.2",
            "target-dir": "Symfony/Component/Yaml",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Yaml.git",
                "reference": "v2.3.2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Yaml/zipball/v2.3.2",
                "reference": "v2.3.2",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Yaml\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Yaml Component",
            "homepage": "http://symfony.com",
            "time": "2013-07-11 19:36:36"
        }
    ],
    "aliases": [

    ],
    "minimum-stability": "stable",
    "stability-flags": [

    ],
    "platform": {
        "php": ">=5.3.3"
    },
    "platform-dev": [

    ]
}
<?xml version="1.0" encoding="utf-8"?>

<phpunit bootstrap="vendor/autoload.php" colors="true" strict="true">
    <testsuites>
        <testsuite name="phpDocumentor Fileset">
            <directory>./tests/</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist>
            <directory suffix=".php">.</directory>
            <exclude>
                <directory suffix=".php">build</directory>
                <directory suffix=".php">tests</directory>
                <directory suffix=".php">vendor</directory>
            </exclude>
        </whitelist>
    </filter>
    <logging>
        <log type="coverage-html"
            title="phpDocumentor Fileset"
            target="build/coverage"
            charset="UTF-8"
            yui="true"
            highlight="false"
            lowUpperBound="35"
            highLowerBound="70" />
        <log type="coverage-clover" target="build/logs/clover.xml" />
        <log type="junit" target="build/logs/junit.xml" logIncompleteSkipped="false" />
    </logging>
</phpunit>
{
    "name": "phpdocumentor/reflection",
    "description": "Reflection library to do Static Analysis for PHP Projects",
    "keywords": ["phpdoc", "phpDocumentor", "reflection", "static analysis"],
    "homepage": "http://www.phpdoc.org",
    "license": "MIT",
    "autoload": {
        "psr-0": {
            "phpDocumentor": ["src/", "tests/unit/", "tests/mocks/"]
        }
    },
    "require": {
        "php": ">=5.3.3",
        "psr/log": "~1.0",
        "nikic/php-parser": ">=0.9",
        "phpdocumentor/reflection-docblock": "2.*@dev"
    },
    "suggests": {
        "symfony/event-dispatcher": "~2.1"
    },
    "require-dev": {
        "behat/behat": "~2.4",
        "phpunit/phpunit": "~3.7",
        "mockery/mockery": ">=0.7.0"
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection;

use PHPParser_Error;
use PHPParser_NodeTraverser;
use PHPParser_NodeVisitor;
use PHPParser_NodeVisitor_NameResolver;
use PHPParser_NodeVisitorAbstract;
use PHPParser_Parser;

/**
 * The source code traverser that scans the given source code and transforms
 * it into tokens.
 *
 * @author  Mike van Riel <mike.vanriel@naenius.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class Traverser
{
    /**
     * List of visitors to apply upon traversing.
     *
     * @see traverse()
     *
     * @var PHPParser_NodeVisitorAbstract[]
     */
    public $visitors = array();

    /**
     * Traverses the given contents and builds an AST.
     *
     * @param string $contents The source code of the file that is to be scanned
     *
     * @return void
     */
    public function traverse($contents)
    {
        try {
            $this->createTraverser()->traverse(
                $this->createParser()->parse($contents)
            );
        } catch (PHPParser_Error $e) {
            echo 'Parse Error: ', $e->getMessage();
        }
    }

    /**
     * Adds a visitor object to the traversal process.
     *
     * With visitors it is possible to extend the traversal process and
     * modify the found tokens.
     *
     * @param PHPParser_NodeVisitor $visitor
     *
     * @return void
     */
    public function addVisitor(PHPParser_NodeVisitor $visitor)
    {
        $this->visitors[] = $visitor;
    }

    /**
     * Creates a parser object using our own Lexer.
     *
     * @return PHPParser_Parser
     */
    protected function createParser()
    {
        return new PHPParser_Parser(new Lexer());
    }

    /**
     * Creates a new traverser object and adds visitors.
     *
     * @return PHPParser_NodeTraverser
     */
    protected function createTraverser()
    {
        $node_traverser = new PHPParser_NodeTraverser();
        $node_traverser->addVisitor(new PHPParser_NodeVisitor_NameResolver());

        foreach ($this->visitors as $visitor) {
            $node_traverser->addVisitor($visitor);
        }

        return $node_traverser;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Reflection;

/**
 * An exception specifically originating from the Reflection component.
 *
 * @author  Mike van Riel <mike.vanriel@naenius.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class Exception extends \Exception
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection;

use PHPParser_Node_Name;
use PHPParser_Node_Stmt_Class;
use PHPParser_Node_Stmt_Interface;

class InterfaceReflector extends BaseReflector
{
    /** @var PHPParser_Node_Stmt_Interface|PHPParser_Node_Stmt_Class */
    protected $node;

    protected $constants = array();
    protected $properties = array();
    protected $methods = array();

    public function parseSubElements()
    {
        foreach ($this->node->stmts as $stmt) {
            switch (get_class($stmt)) {
                case 'PHPParser_Node_Stmt_Property':
                    foreach ($stmt->props as $property) {
                        $this->properties[] = new ClassReflector\PropertyReflector(
                            $stmt,
                            $this->context,
                            $property
                        );
                    }
                    break;
                case 'PHPParser_Node_Stmt_ClassMethod':
                    $this->methods[] = new ClassReflector\MethodReflector(
                        $stmt,
                        $this->context
                    );
                    break;
                case 'PHPParser_Node_Stmt_ClassConst':
                    foreach ($stmt->consts as $constant) {
                        $this->constants[] = new ClassReflector\ConstantReflector(
                            $stmt,
                            $this->context,
                            $constant
                        );
                    }
                    break;
            }
        }
    }

    public function getParentInterfaces()
    {
        $names = array();
        if ($this->node instanceof PHPParser_Node_Stmt_Interface
            && $this->node->extends
        ) {
            /** @var PHPParser_Node_Name */
            foreach ($this->node->extends as $node) {
                $names[] = '\\'.(string) $node;
            }
        }

        return $names;
    }

    public function getConstants()
    {
        return $this->constants;
    }

    public function getProperties()
    {
        return $this->properties;
    }

    public function getMethods()
    {
        return $this->methods;
    }

    public function getMethod($name)
    {
        return $this->methods[$name];
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection;

use PHPParser_Node_Scalar_String;
use PHPParser_PrettyPrinter_Zend;

/**
 * Custom PrettyPrinter for phpDocumentor.
 *
 * phpDocumentor has a custom PrettyPrinter for PHP-Parser because it needs the
 * unmodified value for Scalar variables instead of an interpreted version.
 *
 * If the interpreted version was to be used then the XML interpretation would
 * fail because of special characters.
 *
 * @author  Mike van Riel <mike.vanriel@naenius.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class PrettyPrinter extends PHPParser_PrettyPrinter_Zend
{
    /**
     * Converts the string into it's original representation without converting
     * the special character combinations.
     *
     * This method is overridden from the original Zend Pretty Printer because
     * the original returns the strings as interpreted by PHP-Parser.
     * Since we do not want such conversions we take the original that is
     * injected by our own custom Lexer.
     *
     * @param PHPParser_Node_Scalar_String $node The node to return a string
     *     representation of.
     *
     * @see Lexer where the originalValue is injected.
     *
     * @return string
     */
    public function pScalar_String(PHPParser_Node_Scalar_String $node)
    {
        return $this->pNoIndent($node->getAttribute('originalValue'));
    }

    /**
     * Work around PHPParser_PrettyPrinterAbstract::__construct's call to
     * uniqid() until https://github.com/nikic/PHP-Parser/pull/65 has been
     * merged in.
     */
    public function __construct()
    {
        $this->noIndentToken = mt_rand();
    }

}
<?php
namespace phpDocumentor\Reflection\Event;

use phpDocumentor\Event\EventAbstract;
use phpDocumentor\Reflection\DocBlock;

class PostDocBlockExtractionEvent extends EventAbstract
{
    /** @var DocBlock */
    protected $docblock = null;

    /**
     * @param DocBlock $docblock
     *
     * @return $this
     */
    public function setDocblock(DocBlock $docblock = null)
    {
        $this->docblock = $docblock;

        return $this;
    }

    /**
     * @return DocBlock|null
     */
    public function getDocblock()
    {
        return $this->docblock;
    }
}
<?php
namespace phpDocumentor\Reflection\Event;

use DOMNode;
use phpDocumentor\Event\EventAbstract;
use phpDocumentor\Reflection\DocBlock\Tag;

class ExportDocBlockTagEvent extends EventAbstract
{
    /** @var DOMNode */
    protected $xml = null;

    /** @var Tag */
    protected $object = null;

    /**
     * @return DOMNode|null
     */
    public function getXml()
    {
        return $this->xml;
    }

    /**
     * @return Tag|null
     */
    public function getObject()
    {
        return $this->object;
    }

    /**
     * @param Tag $object
     *
     * @return ExportDocBlockTagEvent
     */
    public function setObject(Tag $object = null)
    {
        $this->object = $object;

        return $this;
    }

    /**
     * @param DOMNode $xml
     *
     * @return ExportDocBlockTagEvent
     */
    public function setXml(DOMNode $xml = null)
    {
        $this->xml = $xml;

        return $this;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection;

use Exception;
use PHPParser_Node_Expr_Include;

class IncludeReflector extends BaseReflector
{
    /** @var PHPParser_Node_Expr_Include */
    protected $node;

    /**
     * Returns the type of this include.
     *
     * Valid types are:
     * - Include
     * - Include Once
     * - Require
     * - Require Once
     *
     * @throws Exception if the include is of an unknown type
     *
     * @return string
     */
    public function getType()
    {
        switch ($this->node->type) {
            case PHPParser_Node_Expr_Include::TYPE_INCLUDE:
                return 'Include';
            case PHPParser_Node_Expr_Include::TYPE_INCLUDE_ONCE:
                return 'Include Once';
            case PHPParser_Node_Expr_Include::TYPE_REQUIRE:
                return 'Require';
            case PHPParser_Node_Expr_Include::TYPE_REQUIRE_ONCE:
                return 'Require Once';
            default:
                throw new Exception(
                    'Unknown include type detected: '.$this->node->type
                );
        }
    }

    public function getShortName()
    {
        return (string) $this->node->expr->value;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection;

use phpDocumentor\Reflection\BaseReflector;
use phpDocumentor\Reflection\DocBlock\Context;
use PHPParser_Node_Param;
use PHPParser_Node_Stmt;
use PHPParser_Node_Stmt_Function;

/**
 * Provides Static Reflection for functions.
 *
 * @author  Mike van Riel <mike.vanriel@naenius.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class FunctionReflector extends BaseReflector
{
    /** @var PHPParser_Node_Stmt_Function */
    protected $node;

    /** @var FunctionReflector\ArgumentReflector[] */
    protected $arguments = array();

    /**
     * Initializes the reflector using the function statement object of
     * PHP-Parser.
     *
     * @param PHPParser_Node_Stmt $node    Function object coming from PHP-Parser.
     * @param Context             $context The context in which the node occurs.
     */
    public function __construct(PHPParser_Node_Stmt $node, Context $context)
    {
        parent::__construct($node, $context);

        /** @var PHPParser_Node_Param $param  */
        foreach ($node->params as $param) {
            $reflector = new FunctionReflector\ArgumentReflector(
                $param,
                $context
            );
            $this->arguments[$reflector->getName()] = $reflector;
        }
    }

    /**
     * Checks whether the function returns a value by reference.
     *
     * @return bool TRUE if the return value is by reference, FALSE otherwise.
     */
    public function isByRef()
    {
        return $this->node->byRef;
    }

    /**
     * Returns a list of Argument objects.
     *
     * @return FunctionReflector\ArgumentReflector[]
     */
    public function getArguments()
    {
        return $this->arguments;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection;

use Exception;
use InvalidArgumentException;
use phpDocumentor\Event\Dispatcher;
use phpDocumentor\Reflection\DocBlock;
use phpDocumentor\Reflection\DocBlock\Context;
use phpDocumentor\Reflection\DocBlock\Location;
use phpDocumentor\Reflection\Event\PostDocBlockExtractionEvent;
use Psr\Log\LogLevel;
use PHPParser_Node_Expr;
use PHPParser_Node_Stmt;
use PHPParser_NodeAbstract;
use PHPParser_PrettyPrinterAbstract;

/**
 * Basic reflection providing support for events and basic properties as a
 * DocBlock and names.
 *
 * @author  Mike van Riel <mike.vanriel@naenius.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
abstract class BaseReflector extends ReflectionAbstract
{
    /** @var PHPParser_Node_Stmt */
    protected $node;

    /**
     * The package name that is passed on by the parent Reflector.
     *
     * May be overwritten and should be passed on to children supporting
     * packages.
     *
     * @var string
     */
    protected $default_package_name = '';

    /**
     * PHP AST pretty printer used to get representations of values.
     *
     * @var PHPParser_PrettyPrinterAbstract
     */
    protected static $prettyPrinter = null;

    /**
     * Initializes this reflector with the correct node as produced by
     * PHP-Parser.
     *
     * @param PHPParser_NodeAbstract $node
     * @param Context                $context
     *
     * @link http://github.com/nikic/PHP-Parser
     */
    public function __construct(PHPParser_NodeAbstract $node, Context $context)
    {
        $this->node = $node;
        $context->setLSEN($this->getLSEN());
        $this->context = $context;
    }

    /**
     * Sets the name for the namespace.
     *
     * @param string $namespace
     *
     * @throws InvalidArgumentException if something other than a string is
     *     passed.
     *
     * @return void
     */
    public function setNamespace($namespace)
    {
        if (!is_string($namespace)) {
            throw new InvalidArgumentException(
                'Expected a string for the namespace'
            );
        }

        $this->context->setNamespace($namespace);
    }

    /**
     * Returns the parsed DocBlock.
     *
     * @return DocBlock|null
     */
    public function getDocBlock()
    {
        return $this->extractDocBlock($this->node);
    }

    /**
     * Extracts a parsed DocBlock from an object.
     *
     * @param object $node Any object with a "getDocComment()" method.
     *
     * @return DocBlock|null
     */
    protected function extractDocBlock($node)
    {
        $doc_block = null;
        $comment = $node->getDocComment();
        if ($comment) {
            try {
                $doc_block = new DocBlock(
                    (string) $comment,
                    $this->context,
                    new Location($comment->getLine())
                );
            } catch (Exception $e) {
                $this->log($e->getMessage(), LogLevel::CRITICAL);
            }
        }

        if (class_exists('phpDocumentor\Event\Dispatcher')) {
            Dispatcher::getInstance()->dispatch(
                'reflection.docblock-extraction.post',
                PostDocBlockExtractionEvent
                ::createInstance($this)->setDocblock($doc_block)
            );
        }

        return $doc_block;
    }

    /**
     * Returns the name for this Reflector instance.
     *
     * @return string
     */
    public function getName()
    {
        if (isset($this->node->namespacedName)) {
            return '\\'.implode('\\', $this->node->namespacedName->parts);
        }

        return $this->getShortName();
    }

    /**
     * Returns the last component of a namespaced name as a short form.
     *
     * @return string
     */
    public function getShortName()
    {
        return isset($this->node->name)
            ? $this->node->name
            : (string) $this->node;
    }

    /**
     * Gets the LSEN.
     *
     * Returns this element's Local Structural Element Name (LSEN). This name
     * consistents of the element's short name, along with punctuation that
     * hints at the kind of structural element. If the structural element is
     * part of a type (i.e. an interface/trait/class' property/method/constant),
     * it also contains the name of the owning type.
     *
     * @return string
     */
    public function getLSEN()
    {
        return '';
    }

    /**
     * Returns the namespace name for this object.
     *
     * If this object does not have a namespace then the word 'global' is
     * returned to indicate a global namespace.
     *
     * @return string
     */
    public function getNamespace()
    {
        if (!$this->node->namespacedName) {
            return $this->context->getNamespace();
        }

        $parts = $this->node->namespacedName->parts;
        array_pop($parts);

        $namespace = implode('\\', $parts);

        return $namespace ? $namespace : 'global';
    }

    /**
     * Returns a listing of namespace aliases where the key represents the alias
     * and the value the Fully Qualified Namespace Name.
     *
     * @return string[]
     */
    public function getNamespaceAliases()
    {
        return $this->context->getNamespaceAliases();
    }

    /**
     * Sets a listing of namespace aliases.
     *
     * The keys represents the alias name and the value the
     * Fully Qualified Namespace Name (FQNN).
     *
     * @param string[] $aliases
     *
     * @return void
     */
    public function setNamespaceAliases(array $aliases)
    {
        $this->context->setNamespaceAliases($aliases);
    }

    /**
     * Sets the Fully Qualified Namespace Name (FQNN) for an alias.
     *
     * @param string $alias
     * @param string $fqnn
     *
     * @return void
     */
    public function setNamespaceAlias($alias, $fqnn)
    {
        $this->context->setNamespaceAlias($alias, $fqnn);
    }

    /**
     * Returns the line number where this object starts.
     *
     * @return int
     */
    public function getLinenumber()
    {
        return $this->node->getLine();
    }

    /**
     * Sets the default package name for this object.
     *
     * If the DocBlock contains a different package name then that overrides
     * this package name.
     *
     * @param string $default_package_name The name of the package as defined
     *     in the PHPDoc Standard.
     *
     * @return void
     */
    public function setDefaultPackageName($default_package_name)
    {
        $this->default_package_name = $default_package_name;
    }

    /**
     * Returns the package name that is default for this element.
     *
     * This value may change after the DocBlock is interpreted. If that contains
     * a package tag then that tag overrides the Default package name.
     *
     * @return string
     */
    public function getDefaultPackageName()
    {
        return $this->default_package_name;
    }

    /**
     * Returns a simple human readable output for a value.
     *
     * @param PHPParser_Node_Expr $value The value node as provided by
     *     PHP-Parser.
     *
     * @return string
     */
    protected function getRepresentationOfValue(
        PHPParser_Node_Expr $value = null
    ) {
        if (null === $value) {
            return '';
        }

        if (!self::$prettyPrinter) {
            self::$prettyPrinter = new PrettyPrinter();
        }

        return self::$prettyPrinter->prettyPrintExpr($value);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection;

use phpDocumentor\Event\Dispatcher;
use phpDocumentor\Parser\Event\LogEvent;
use phpDocumentor\Reflection\DocBlock;
use phpDocumentor\Reflection\DocBlock\Context;
use phpDocumentor\Reflection\DocBlock\Location;
use phpDocumentor\Reflection\Event\PostDocBlockExtractionEvent;
use phpDocumentor\Reflection\Exception;
use Psr\Log\LogLevel;
use PHPParser_Comment_Doc;
use PHPParser_Node;
use PHPParser_Node_Const;
use PHPParser_Node_Expr_FuncCall;
use PHPParser_Node_Expr_Include;
use PHPParser_Node_Name;
use PHPParser_Node_Stmt_Class;
use PHPParser_Node_Stmt_ClassConst;
use PHPParser_Node_Stmt_ClassMethod;
use PHPParser_Node_Stmt_Const;
use PHPParser_Node_Stmt_Function;
use PHPParser_Node_Stmt_InlineHTML;
use PHPParser_Node_Stmt_Interface;
use PHPParser_Node_Stmt_Property;
use PHPParser_Node_Stmt_PropertyProperty;
use PHPParser_Node_Stmt_Trait;
use PHPParser_Node_Stmt_UseUse;
use PHPParser_NodeVisitor;

/**
 * Reflection class for a full file.
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
class FileReflector extends ReflectionAbstract implements PHPParser_NodeVisitor
{
    protected $hash;
    protected $contents = 1;
    protected $includes = array();
    protected $constants = array();
    protected $classes = array();
    protected $traits = array();
    protected $interfaces = array();
    protected $functions = array();
    protected $filename = '';
    protected $doc_block;
    protected $default_package_name = 'Default';

    /** @var string[] A list of markers contained in this file. */
    protected $markers = array();

    /** @var string[] A list of errors during processing */
    protected $parse_markers = array();

    /** @var string[] A list of all marker types to search for in this file. */
    protected $marker_terms = array('TODO', 'FIXME');

    protected $namespace_aliases = array();
    protected $current_namespace = '';

    /**
     * Opens the file and retrieves its contents.
     *
     * During construction the given file is checked whether it is readable and
     * if the $validate argument is true a PHP Lint action is executed to
     * check whether the there are no parse errors.
     *
     * By default the Lint check is disabled because of the performance hit
     * introduced by this action.
     *
     * If the validation checks out, the file's contents are read, converted to
     * UTF-8 and the object is created from those contents.
     *
     * @param string  $file     Name of the file.
     * @param boolean $validate Whether to check the file using PHP Lint.
     * @param string  $encoding The encoding of the file.
     *
     * @throws Exception\UnreadableFile If the filename is incorrect or
     *   the file cannot be opened
     * @throws Exception\UnparsableFile If the file fails PHP lint checking
     *   (this can only happen when $validate is set to true)
     */
    public function __construct($file, $validate = false, $encoding = 'utf-8')
    {
        if (!is_string($file) || (!is_readable($file))) {
            throw new Exception\UnreadableFile(
                'The given file should be a string, should exist on the filesystem and should be readable'
            );
        }

        if ($validate) {
            exec('php -l ' . escapeshellarg($file), $output, $result);
            if ($result != 0) {
                throw new Exception\UnparsableFile(
                    'The given file could not be interpreted as it contains errors: '
                    . implode(PHP_EOL, $output)
                );
            }
        }

        $this->filename = $file;
        $this->contents = file_get_contents($file);
        $this->context = new Context();

        if (strtolower($encoding) !== 'utf-8') {
            $this->contents = iconv(
                strtolower($encoding),
                'utf-8//IGNORE//TRANSLIT',
                $this->contents
            );
        }

        // filemtime($file) is sometimes between 0.00001 and 0.00005 seconds
        // faster but md5 is more accurate. It can also result in false
        // positives or false negatives after copying or checking out a codebase.
        $this->hash = md5($this->contents);
    }

    public function process()
    {
        // with big fluent interfaces it can happen that PHP-Parser's Traverser
        // exceeds the 100 recursions limit; we set it to 5000 to be sure.
        ini_set('xdebug.max_nesting_level', 10000);

        $traverser = new Traverser();
        $traverser->addVisitor($this);
        $traverser->traverse($this->contents);

        $this->scanForMarkers();
    }

    public function getClasses()
    {
        return $this->classes;
    }

    public function getTraits()
    {
        return $this->traits;
    }

    public function getConstants()
    {
        return $this->constants;
    }

    public function getFunctions()
    {
        return $this->functions;
    }

    public function getIncludes()
    {
        return $this->includes;
    }

    public function getInterfaces()
    {
        return $this->interfaces;
    }

    public function beforeTraverse(array $nodes)
    {
        $node = null;
        $key = 0;
        foreach ($nodes as $k => $n) {
            if (!$n instanceof PHPParser_Node_Stmt_InlineHTML) {
                $node = $n;
                $key = $k;
                break;
            }
        }

        if ($node) {
            $comments = (array) $node->getAttribute('comments');

            // remove non-DocBlock comments
            $comments = array_values(
                array_filter(
                    $comments,
                    function ($comment) {
                        return $comment instanceof PHPParser_Comment_Doc;
                    }
                )
            );

            if (!empty($comments)) {
                try {
                    $docblock = new DocBlock(
                        (string) $comments[0],
                        null,
                        new Location($comments[0]->getLine())
                    );

                    // the first DocBlock in a file documents the file if
                    // * it precedes another DocBlock or
                    // * it contains a @package tag and doesn't precede a class
                    //   declaration or
                    // * it precedes a non-documentable element (thus no include,
                    //   require, class, function, define, const)
                    if (count($comments) > 1
                        || (!$node instanceof PHPParser_Node_Stmt_Class
                        && !$node instanceof PHPParser_Node_Stmt_Interface
                        && $docblock->hasTag('package'))
                        || !$this->isNodeDocumentable($node)
                    ) {
                        $this->doc_block = $docblock;

                        // remove the file level DocBlock from the node's comments
                        array_shift($comments);
                    }
                } catch (\Exception $e) {
                    $this->log($e->getMessage(), LogLevel::CRITICAL);
                }
            }

            // always update the comments attribute so that standard comments
            // do not stop DocBlock from being attached to an element
            $node->setAttribute('comments', $comments);
            $nodes[$key] = $node;
        }

        if (class_exists('phpDocumentor\Event\Dispatcher')) {
            Dispatcher::getInstance()->dispatch(
                'reflection.docblock-extraction.post',
                PostDocBlockExtractionEvent
                ::createInstance($this)->setDocblock($this->doc_block)
            );
        }

        return $nodes;
    }

    /**
     * Checks whether the given node is recogized by phpDocumentor as a
     * documentable element.
     *
     * The following elements are recognized:
     *
     * - Trait
     * - Class
     * - Interface
     * - Class constant
     * - Class method
     * - Property
     * - Include/Require
     * - Constant, both const and define
     * - Function
     *
     * @param PHPParser_Node $node
     *
     * @return bool
     */
    protected function isNodeDocumentable(PHPParser_Node $node)
    {
        return ($node instanceof PHPParser_Node_Stmt_Class)
            || ($node instanceof PHPParser_Node_Stmt_Interface)
            || ($node instanceof PHPParser_Node_Stmt_ClassConst)
            || ($node instanceof PHPParser_Node_Stmt_ClassMethod)
            || ($node instanceof PHPParser_Node_Stmt_Const)
            || ($node instanceof PHPParser_Node_Stmt_Function)
            || ($node instanceof PHPParser_Node_Stmt_Property)
            || ($node instanceof PHPParser_Node_Stmt_PropertyProperty)
            || ($node instanceof PHPParser_Node_Stmt_Trait)
            || ($node instanceof PHPParser_Node_Expr_Include)
            || ($node instanceof PHPParser_Node_Expr_FuncCall
            && ($node->name instanceof PHPParser_Node_Name)
            && $node->name == 'define');
    }

    public function enterNode(PHPParser_Node $node)
    {
    }

    public function getName()
    {
        return $this->filename;
    }

    public function getFilename()
    {
        return $this->filename;
    }

    public function getHash()
    {
        return $this->hash;
    }

    public function getDocBlock()
    {
        return $this->doc_block;
    }

    public function getLineNumber()
    {
        return 0;
    }

    public function getDefaultPackageName()
    {
        return $this->default_package_name;
    }

    /**
     * Adds a marker to scan the contents of this file for.
     *
     * @param string $name The Marker term, e.g. FIXME or TODO.
     *
     * @return void
     */
    public function addMarker($name)
    {
        $this->marker_terms[] = $name;
    }

    /**
     * Sets a list of markers to search for.
     *
     * @param string[] $markers A list of marker terms to scan for.
     *
     * @see phpDocumentor\Reflection\FileReflector::addMarker()
     *
     * @return void
     */
    public function setMarkers(array $markers)
    {
        $this->marker_terms = array();

        foreach ($markers as $marker) {
            $this->addMarker($marker);
        }
    }

    public function getMarkers()
    {
        return $this->markers;
    }

    /**
     * Adds a parse error to the system
     *
     * @param LogEvent $data Contains the type,
     *     message, line and code element.
     *
     * @return void
     */
    public function addParserMarker($data)
    {
        $this->parse_markers[] = array(
            $data->getType(),
            $data->getMessage(),
            $data->getLine(),
            $data->getCode()
        );
    }

    /**
     * Scans the file for markers and records them in the markers property.
     *
     * @see getMarkers()
     *
     * @todo this method may incur a performance penalty while the AST also
     * contains the comments. This method should be replaced by a piece of
     * code that interprets the comments in the AST.
     * This has not been done since that may be an extensive refactoring (each
     * PHPParser_Node* contains a 'comments' attribute and must thus recursively
     * be discovered)
     *
     * @return void
     */
    public function scanForMarkers()
    {
        // find all markers, get the entire file and check for marker terms.
        $marker_data = array();
        foreach (explode("\n", $this->contents) as $line_number => $line) {
            preg_match_all(
                '~//[\s]*(' . implode('|', $this->marker_terms) . ')\:?[\s]*(.*)~',
                $line,
                $matches,
                PREG_SET_ORDER
            );
            foreach ($matches as &$match) {
                $match[3] = $line_number + 1;
            }
            $marker_data = array_merge($marker_data, $matches);
        }

        // store marker results and remove first entry (entire match),
        // this results in an array with 2 entries:
        // marker name and content
        $this->markers = $marker_data;
        foreach ($this->markers as &$marker) {
            array_shift($marker);
        }
    }

    public function getParseErrors()
    {
        return $this->parse_markers;
    }

    public function getNamespace()
    {
        return $this->current_namespace;
    }

    public function getNamespaceAliases()
    {
        return $this->namespace_aliases;
    }

    public function getContents()
    {
        return $this->contents;
    }

    public function setDefaultPackageName($default_package_name)
    {
        $this->default_package_name = $default_package_name;
    }

    public function setFilename($filename)
    {
        $this->filename = $filename;
    }

    public function leaveNode(PHPParser_Node $node)
    {
        $prettyPrinter = new PrettyPrinter;

        switch (get_class($node)) {
            case 'PHPParser_Node_Stmt_Use':
                /** @var PHPParser_Node_Stmt_UseUse $use */
                foreach ($node->uses as $use) {
                    $this->context->setNamespaceAlias(
                        $use->alias,
                        implode('\\', $use->name->parts)
                    );
                }
                break;
            case 'PHPParser_Node_Stmt_Namespace':
                $this->context->setNamespace(implode('\\', $node->name->parts));
                break;
            case 'PHPParser_Node_Stmt_Class':
                $class = new ClassReflector($node, $this->context);
                $class->parseSubElements();
                $this->classes[] = $class;
                break;
            case 'PHPParser_Node_Stmt_Trait':
                $trait = new TraitReflector($node, $this->context);
                $trait->parseSubElements();
                $this->traits[] = $trait;
                break;
            case 'PHPParser_Node_Stmt_Interface':
                $interface = new InterfaceReflector($node, $this->context);
                $interface->parseSubElements();
                $this->interfaces[] = $interface;
                break;
            case 'PHPParser_Node_Stmt_Function':
                $function = new FunctionReflector($node, $this->context);
                $this->functions[] = $function;
                break;
            case 'PHPParser_Node_Stmt_Const':
                foreach ($node->consts as $constant) {
                    $reflector = new ConstantReflector(
                        $node,
                        $this->context,
                        $constant
                    );
                    $this->constants[] = $reflector;
                }
                break;
            case 'PHPParser_Node_Expr_FuncCall':
                if ($node->name instanceof PHPParser_Node_Name && $node->name == 'define') {
                    // transform the first argument of the define function call into a constant name
                    $name = str_replace(
                        array('\\\\', '"', "'"),
                        array('\\', '', ''),
                        trim($prettyPrinter->prettyPrintExpr($node->args[0]->value), '\'')
                    );
                    $nameParts = explode('\\', $name);
                    $shortName = end($nameParts);

                    $constant = new PHPParser_Node_Const($shortName, $node->args[1]->value, $node->getAttributes());
                    $constant->namespacedName = new PHPParser_Node_Name($name);

                    $constant_statement = new \PHPParser_Node_Stmt_Const(array($constant));
                    $constant_statement->setAttribute('comments', array($node->getDocComment()));
                    $this->constants[] = new ConstantReflector($constant_statement, $this->context, $constant);
                }
                break;
            case 'PHPParser_Node_Expr_Include':
                $include = new IncludeReflector($node, $this->context);
                $this->includes[] = $include;
                break;
        }
    }

    public function afterTraverse(array $nodes)
    {
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection;

class TraitReflector extends ClassReflector
{
    /** @var \PHPParser_Node_Stmt_Trait */
    protected $node;
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\FunctionReflector;

use phpDocumentor\Reflection\BaseReflector;

class ArgumentReflector extends BaseReflector
{
    /** @var \PHPParser_Node_Param */
    protected $node;

    /**
     * Checks whether the argument is passed by reference.
     *
     * @return bool TRUE if the argument is by reference, FALSE otherwise.
     */
    public function isByRef()
    {
        return $this->node->byRef;
    }

    /**
     * Returns the default value or null is none is set.
     *
     * @return string|null
     */
    public function getDefault()
    {
        $result = null;
        if ($this->node->default) {
            $result = $this->getRepresentationOfValue($this->node->default);
        }

        return $result;
    }

    /**
     * Returns the typehint, or null if none is set.
     *
     * @return string|null
     */
    public function getType()
    {
        $type = (string) $this->node->type;

        // in case of the callable of array keyword; do not prefix with a \
        if ($type == 'callable' || $type == 'array'
            || $type == 'self' || $type == '$this'
        ) {
            return $type;
        }

        return $type ? '\\'.$type : '';
    }

    public function getName()
    {
        return '$'.parent::getName();
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection;

use phpDocumentor\Event\DebugEvent;
use phpDocumentor\Event\Dispatcher;
use phpDocumentor\Event\LogEvent;

/**
 * Provides basic event logging and dispatching for every reflection class.
 *
 * @author  Mike van Riel <mike.vanriel@naenius.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
abstract class ReflectionAbstract
{
    /**
     * The context (namespace, aliases) for the reflection.
     *
     * @var \phpDocumentor\Reflection\DocBlock\Context
     */
    protected $context = null;

    /**
     * Dispatches a logging request.
     *
     * @param string $message  The message to log.
     * @param int    $priority The logging priority, the lower,
     *  the more important. Ranges from 1 to 7
     *
     * @return void
     */
    public function log($message, $priority = 6)
    {
        if (class_exists('phpDocumentor\Event\Dispatcher')) {
            Dispatcher::getInstance()->dispatch(
                'system.log',
                LogEvent::createInstance($this)
                ->setMessage($message)->setPriority($priority)
            );
        }
    }

    /**
     * Dispatches a logging request to log a debug message.
     *
     * @param string $message The message to log.
     *
     * @return void
     */
    public function debug($message)
    {
        if (class_exists('phpDocumentor\Event\Dispatcher')) {
            Dispatcher::getInstance()->dispatch(
                'system.debug',
                DebugEvent::createInstance($this)
                ->setMessage($message)
            );
        }
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\Exception;

/**
 * Exception representing any situation where the file is not parsable.
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
class UnparsableFile extends \phpDocumentor\Reflection\Exception
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\Exception;

/**
 * Exception representing any error in the Reflection library due to a file not
 * being readable or accessible.
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
class UnreadableFile extends \phpDocumentor\Reflection\Exception
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\ClassReflector;

use phpDocumentor\Reflection\FunctionReflector;
use PHPParser_Node_Stmt_Class;
use PHPParser_Node_Stmt_ClassMethod;

class MethodReflector extends FunctionReflector
{
    /** @var PHPParser_Node_Stmt_ClassMethod */
    protected $node;

    /**
     * Returns the visibility for this item.
     *
     * The returned value should match either of the following:
     *
     * * public
     * * protected
     * * private
     *
     * If a method has no visibility set in the class definition this method
     * will return 'public'.
     *
     * @return string
     */
    public function getVisibility()
    {
        if ($this->node->type & PHPParser_Node_Stmt_Class::MODIFIER_PROTECTED) {
            return 'protected';
        }
        if ($this->node->type & PHPParser_Node_Stmt_Class::MODIFIER_PRIVATE) {
            return 'private';
        }

        return 'public';
    }

    /**
     * Returns whether this method is static.
     *
     * @return bool
     */
    public function isAbstract()
    {
        return (bool) ($this->node->type & PHPParser_Node_Stmt_Class::MODIFIER_ABSTRACT);
    }

    /**
     * Returns whether this method is static.
     *
     * @return bool
     */
    public function isStatic()
    {
        return (bool) ($this->node->type & PHPParser_Node_Stmt_Class::MODIFIER_STATIC);
    }

    /**
     * Returns whether this method is final.
     *
     * @return bool
     */
    public function isFinal()
    {
        return (bool) ($this->node->type & PHPParser_Node_Stmt_Class::MODIFIER_FINAL);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\ClassReflector;

use phpDocumentor\Reflection\BaseReflector;
use phpDocumentor\Reflection\DocBlock;
use phpDocumentor\Reflection\DocBlock\Context;
use PHPParser_Node_Stmt_Class;
use PHPParser_Node_Stmt_Property;
use PHPParser_Node_Stmt_PropertyProperty;

class PropertyReflector extends BaseReflector
{
    /** @var PHPParser_Node_Stmt_Property */
    protected $property;

    /** @var PHPParser_Node_Stmt_PropertyProperty */
    protected $node;

    public function __construct(
        PHPParser_Node_Stmt_Property $property,
        Context $context,
        PHPParser_Node_Stmt_PropertyProperty $node
    ) {
        parent::__construct($node, $context);
        $this->property = $property;
    }

    public function getName()
    {
        return '$'.parent::getName();
    }

    /**
     * Returns the default value or null if none found.
     *
     * Please note that if the default value is null that this method returns
     * string 'null'.
     *
     * @return null|string
     */
    public function getDefault()
    {
        $result = null;
        if ($this->node->default) {
            $result = $this->getRepresentationOfValue($this->node->default);
        }

        return $result;
    }

    /**
     * Returns whether this method is static.
     *
     * @return bool
     */
    public function isAbstract()
    {
        return (bool) ($this->property->type & PHPParser_Node_Stmt_Class::MODIFIER_ABSTRACT);
    }

    /**
     * Returns the visibility for this item.
     *
     * The returned value should match either of the following:
     *
     * * public
     * * protected
     * * private
     *
     * If a method has no visibility set in the class definition this method
     * will return 'public'.
     *
     * @return string
     */
    public function getVisibility()
    {
        if ($this->property->type & PHPParser_Node_Stmt_Class::MODIFIER_PROTECTED) {
            return 'protected';
        }
        if ($this->property->type & PHPParser_Node_Stmt_Class::MODIFIER_PRIVATE) {
            return 'private';
        }

        return 'public';
    }

    /**
     * Returns whether this method is static.
     *
     * @return bool
     */
    public function isStatic()
    {
        return (bool) ($this->property->type & PHPParser_Node_Stmt_Class::MODIFIER_STATIC);
    }

    /**
     * Returns whether this method is final.
     *
     * @return bool
     */
    public function isFinal()
    {
        return (bool) ($this->property->type & PHPParser_Node_Stmt_Class::MODIFIER_FINAL);
    }

    /**
     * Returns the parsed DocBlock.
     *
     * @return DocBlock|null
     */
    public function getDocBlock()
    {
        return $this->extractDocBlock($this->property);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\ClassReflector;

use phpDocumentor\Reflection\BaseReflector;
use phpDocumentor\Reflection\ConstantReflector as BaseConstantReflector;
use phpDocumentor\Reflection\DocBlock\Context;
use PHPParser_Node_Const;
use PHPParser_Node_Stmt_ClassConst;

class ConstantReflector extends BaseConstantReflector
{
    /** @var PHPParser_Node_Stmt_ClassConst */
    protected $constant;

    /**
     * Registers the Constant Statement and Node with this reflector.
     *
     * @param PHPParser_Node_Stmt_Const $stmt
     * @param Context                   $context
     * @param PHPParser_Node_Const      $node
     */
    public function __construct(
        PHPParser_Node_Stmt_ClassConst $stmt,
        Context $context,
        PHPParser_Node_Const $node
    ) {
        BaseReflector::__construct($node, $context);
        $this->constant = $stmt;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection;

use PHPParser_Node_Name;
use PHPParser_Node_Stmt_Class;
use PHPParser_Node_Stmt_TraitUse;

/**
 * Provides static reflection for a class.
 *
 * @author  Mike van Riel <mike.vanriel@naenius.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class ClassReflector extends InterfaceReflector
{
    /** @var \PHPParser_Node_Stmt_Class */
    protected $node;

    /** @var string[] */
    protected $traits = array();

    public function parseSubElements()
    {
        /** @var \PHPParser_Node_Stmt_TraitUse $stmt  */
        foreach ($this->node->stmts as $stmt) {
            if ($stmt instanceof \PHPParser_Node_Stmt_TraitUse) {
                foreach ($stmt->traits as $trait) {
                    $this->traits[] = '\\' . (string) $trait;
                }
            }
        }

        parent::parseSubElements();
    }

    /**
     * Returns whether this is an abstract class.
     *
     * @return bool
     */
    public function isAbstract()
    {
        return (bool) ($this->node->type & PHPParser_Node_Stmt_Class::MODIFIER_ABSTRACT);
    }

    /**
     * Returns whether this class is final and thus cannot be extended.
     *
     * @return bool
     */
    public function isFinal()
    {
        return (bool) ($this->node->type & PHPParser_Node_Stmt_Class::MODIFIER_FINAL);
    }

    /**
     * Returns a list of the names of traits used in this class.
     *
     * @return string[]
     */
    public function getTraits()
    {
        return $this->traits;
    }

    public function getParentClass()
    {
        return $this->node->extends ? '\\'.(string) $this->node->extends : '';
    }

    /**
     * BC Break: used to be getParentInterfaces
     *
     * @return string[] Names of interfaces the class implements.
     */
    public function getInterfaces()
    {
        $names = array();
        if ($this->node->implements) {
            /** @var PHPParser_Node_Name */
            foreach ($this->node->implements as $node) {
                $names[] = '\\'.(string) $node;
            }
        }

        return $names;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2012 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection;

use phpDocumentor\Reflection\DocBlock;
use phpDocumentor\Reflection\DocBlock\Context;
use PHPParser_Node_Const;
use PHPParser_Node_Stmt_Const;

/**
 * Provides Static Reflection for file-level constants.
 *
 * @author  Mike van Riel <mike.vanriel@naenius.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class ConstantReflector extends BaseReflector
{
    /** @var PHPParser_Node_Stmt_Const */
    protected $constant;

    /** @var PHPParser_Node_Const */
    protected $node;

    /**
     * Registers the Constant Statement and Node with this reflector.
     *
     * @param PHPParser_Node_Stmt_Const $stmt
     * @param PHPParser_Node_Const      $node
     */
    public function __construct(
        PHPParser_Node_Stmt_Const $stmt,
        Context $context,
        PHPParser_Node_Const $node
    ) {
        parent::__construct($node, $context);
        $this->constant = $stmt;
    }

    /**
     * Returns the value contained in this Constant.
     *
     * @return string
     */
    public function getValue()
    {
        return $this->getRepresentationOfValue($this->node->value);
    }

    /**
     * Returns the parsed DocBlock.
     *
     * @return DocBlock|null
     */
    public function getDocBlock()
    {
        return $this->extractDocBlock($this->constant);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection;

use PHPParser_Lexer;
use PHPParser_Parser;

/**
 * Custom lexer for phpDocumentor.
 *
 * phpDocumentor has a custom Lexer for PHP-Parser because it needs
 * unmodified value for Scalar variables instead of an interpreted version.
 *
 * If the interpreted version was to be used then the XML interpretation would
 * fail because of special characters.
 *
 * @author  Mike van Riel <mike.vanriel@naenius.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class Lexer extends PHPParser_Lexer
{
    /**
     * Retrieves the next token and determines the associated attributes and
     * returns the token id.
     *
     * @param string   $value
     * @param string[] $startAttributes
     * @param string[] $endAttributes
     *
     * @return int
     */
    public function getNextToken(
        &$value = null,
        &$startAttributes = null,
        &$endAttributes = null
    ) {
        $tokenId = parent::getNextToken($value, $startAttributes, $endAttributes);

        if ($this->isTokenScalar($tokenId)) {
            // store original value because the value itself will be interpreted
            // by PHP_Parser and we want the unformatted value
            $endAttributes['originalValue'] = $value;
        }

        return $tokenId;
    }

    /**
     * Returns whether the given token id is a scalar that will be interpreted
     * by PHP-Parser.
     *
     * @param int $tokenId The id to check, must match a \PHPParser_Parser::T_*
     *     constant.
     *
     * @return bool
     */
    protected function isTokenScalar($tokenId)
    {
        return $tokenId == PHPParser_Parser::T_CONSTANT_ENCAPSED_STRING
            || $tokenId == PHPParser_Parser::T_LNUMBER
            || $tokenId == PHPParser_Parser::T_DNUMBER;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5
 *
 * @author    Erik Baars <baarserik@hotmail.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Reflection;

use phpDocumentor\Reflection\DocBlock\Context;
use PHPParser_Node_Stmt_Class;
use PHPUnit_Framework_TestCase;

/**
 * Class for testing ClassReflector.
 *
 * @author    Erik Baars <baarserik@hotmail.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
class ClassReflectorTest extends PHPUnit_Framework_TestCase
{
    /**
     * Tests the parseSubElements method
     *
     * @covers \phpDocumentor\Reflection\ClassReflector::parseSubElements
     *
     * @return void
     */
    public function testParseSubElements()
    {
        $this->markTestIncomplete();
    }

    /**
     * Tests the parseSubElements method
     *
     * @covers \phpDocumentor\Reflection\ClassReflector::isAbstract
     *
     * @return void
     */
    public function testIsAbstract()
    {
        //$this->markTestSkipped();
        $node = new NodeStmtMock2();
        $class_reflector = new ClassReflector(
            $node,
            new Context()
        );

        $this->assertFalse($class_reflector->isAbstract());

        $node->type = PHPParser_Node_Stmt_Class::MODIFIER_ABSTRACT;
        $this->assertTrue($class_reflector->isAbstract());
    }

    /**
     * Tests the parseSubElements method
     *
     * @covers \phpDocumentor\Reflection\ClassReflector::isFinal
     *
     * @return void
     */
    public function testIsFinal()
    {
        $node = new NodeStmtMock2();
        $class_reflector = new ClassReflector(
            $node,
            new Context()
        );

        $this->assertFalse($class_reflector->isFinal());

        $node->type = PHPParser_Node_Stmt_Class::MODIFIER_FINAL;
        $this->assertTrue($class_reflector->isFinal());
    }

    /**
     * Tests the parseSubElements method
     *
     * @covers \phpDocumentor\Reflection\ClassReflector::getTraits
     *
     * @return void
     */
    public function testGetTraits()
    {
        $node = new NodeStmtMock();
        $class_reflector = new ClassReflectorMock(
            $node,
            new Context()
        );

        $traits = $class_reflector->getTraits();
        $this->assertInternalType('array', $traits);
        $this->assertEmpty($traits);

        $class_reflector->setTraits(array('trait1', 'trait2'));
        $traits = $class_reflector->getTraits();

        $this->assertCount(2, $traits);
        $this->assertEquals('trait1', reset($traits));
    }

    /**
     * Tests the parseSubElements method
     *
     * @covers \phpDocumentor\Reflection\ClassReflector::getParentClass
     *
     * @return void
     */
    public function testGetParentClass()
    {
        $node = new NodeStmtMock();
        $class_reflector = new ClassReflectorMock(
            $node,
            new Context()
        );

        $this->assertEquals('', $class_reflector->getParentClass());

        $node->extends = 'dummy';

        $this->assertEquals('\dummy', $class_reflector->getParentClass());
    }

    /**
     * Tests the parseSubElements method
     *
     * @covers \phpDocumentor\Reflection\ClassReflector::getInterfaces
     *
     * @return void
     */
    public function testGetInterfaces()
    {
        $node = new NodeStmtMock();
        $class_reflector = new ClassReflectorMock(
            $node,
            new Context()
        );

        $this->assertEquals(array(), $class_reflector->getInterfaces());

        $node->implements = array('dummy');

        $this->assertEquals(array('\dummy'), $class_reflector->getInterfaces());
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5
 *
 * @author    Vasil Rangelov <boen.robot@gmail.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Reflection;

use PHPParser_Node_Scalar_String;
use PHPUnit_Framework_TestCase;

/**
 * Class for testing the PrettyPrinter.
 *
 * @author    Vasil Rangelov <boen.robot@gmail.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
class PrettyPrinterTest extends PHPUnit_Framework_TestCase
{
    /**
     * @covers \phpDocumentor\Reflection\PrettyPrinter::pScalar_String
     *
     * @return void
     */
    public function testScalarStringPrinting()
    {
        $object = new PrettyPrinter();
        $this->assertEquals(
            'Another value',
            $object->pScalar_String(
                new PHPParser_Node_Scalar_String(
                    'Value',
                    array('originalValue' => 'Another value')
                )
            )
        );
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5
 *
 * @author    Erik Baars <baarserik@hotmail.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Reflection;

use phpDocumentor\Reflection\DocBlock\Context;
use PHPUnit_Framework_TestCase;

/**
 * Class for testing base reflector.
 *
 * @author    Erik Baars <baarserik@hotmail.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
class BaseReflectorTest extends PHPUnit_Framework_TestCase
{
    /**
     * Tests the setNameSpace method
     *
     * @covers \phpDocumentor\Reflection\BaseReflector::setNameSpace
     * @covers \phpDocumentor\Reflection\BaseReflector::getNameSpace
     *
     * @return void
     */
    public function testSetNameSpace()
    {
        /** @var BaseReflector $base_reflector  */
        $base_reflector = new BaseReflectorMock(
            $this->getMock('PHPParser_Node_Stmt'),
            new Context()
        );
        $base_reflector->setNamespace('namespace_name');

        $this->assertEquals('namespace_name', $base_reflector->getNameSpace());
    }

    /**
     * Tests the setNameSpace method when an invalid argument is passed
     *
     * @covers \phpDocumentor\Reflection\BaseReflector::setNameSpace
     *
     * @expectedException \InvalidArgumentException
     *
     * @return void
     */
    public function testSetNameSpaceInvalidArgument()
    {
        /** @var BaseReflector $base_reflector  */
        $base_reflector = new BaseReflectorMock(
            $this->getMock('PHPParser_Node_Stmt'),
            new Context()
        );
        $base_reflector->setNamespace(null);
    }

    /**
     * Tests the getDocblock method
     *
     * @covers \phpDocumentor\Reflection\BaseReflector::getDocBlock
     *
     * @return void
     */
    public function testGetDocBlock()
    {
        $this->markTestIncomplete();
    }

    /**
     * Tests the getName method
     *
     * @covers \phpDocumentor\Reflection\BaseReflector::getName
     *
     * @return void
     */
    public function testGetName()
    {
        $this->markTestIncomplete();
    }

    /**
     * Tests the getShortName method
     *
     * @covers \phpDocumentor\Reflection\BaseReflector::getShortName
     *
     * @return void
     */
    public function testGetShortName()
    {
        $node = new NodeStmtMock();
        $base_reflector = new BaseReflectorMock(
            $node,
            new Context()
        );

        $this->assertEquals($node->__toString(), $base_reflector->getShortName());

        $node->setName('test_name');

        $this->assertEquals('test_name', $base_reflector->getShortName());
    }

    /**
     * Tests the getNameSpaceAlias method
     *
     * @covers \phpDocumentor\Reflection\BaseReflector::getNamespaceAliases
     * @covers \phpDocumentor\Reflection\BaseReflector::setNamespaceAliases
     *
     * @return void
     */
    public function testGetNamespaceAliases()
    {
        $node = new NodeStmtMock();
        $base_reflector = new BaseReflectorMock(
            $node,
            new Context()
        );

        $this->assertEquals(array(), $base_reflector->getNamespaceAliases());

        $base_reflector->setNamespaceAliases(
            array('test_namespace', 'test_namespace_2')
        );

        $this->assertCount(2, $base_reflector->getNamespaceAliases());
        $this->assertEquals(
            array('\test_namespace', '\test_namespace_2'),
            $base_reflector->getNamespaceAliases()
        );
    }

    /**
     * Tests the getNameSpaceAlias method
     *
     * Tests the following scenarios:
     * - no namespace aliases set yet
     * - overwrite the current namespace alias
     * - add another namespace alias without overwriting the already set alias
     *
     * @covers \phpDocumentor\Reflection\BaseReflector::getNamespaceAliases
     * @covers \phpDocumentor\Reflection\BaseReflector::setNamespaceAlias
     *
     * @return void
     */
    public function testsetNamespaceAlias()
    {
        $node = new NodeStmtMock();

        $base_reflector = new BaseReflectorMock(
            $node,
            new Context()
        );

        $this->assertEquals(array(), $base_reflector->getNamespaceAliases());

        $base_reflector->setNamespaceAlias('test_alias', 'test_namespace');

        $namespace_aliases = $base_reflector->getNamespaceAliases();
        $this->assertCount(1, $namespace_aliases);
        $this->assertArrayHasKey('test_alias', $namespace_aliases);
        $this->assertEquals('\test_namespace', $namespace_aliases['test_alias']);

        $base_reflector->setNamespaceAlias('test_alias', 'test_namespace_2');

        $namespace_aliases = $base_reflector->getNamespaceAliases();
        $this->assertCount(1, $namespace_aliases);
        $this->assertArrayHasKey('test_alias', $namespace_aliases);
        $this->assertEquals('\test_namespace_2', $namespace_aliases['test_alias']);

        $base_reflector->setNamespaceAlias('test_alias2', 'test_namespace');

        $namespace_aliases = $base_reflector->getNamespaceAliases();
        $this->assertCount(2, $namespace_aliases);
        $this->assertArrayHasKey('test_alias', $namespace_aliases);
        $this->assertArrayHasKey('test_alias2', $namespace_aliases);
        $this->assertEquals('\test_namespace_2', $namespace_aliases['test_alias']);
        $this->assertEquals('\test_namespace', $namespace_aliases['test_alias2']);
    }

    /**
     * Tests the getLinenumber method
     *
     * @covers \phpDocumentor\Reflection\BaseReflector::getLinenumber
     *
     * @return void
     */
    public function testGetLinenumber()
    {
        $node = new NodeStmtMock();

        $base_reflector = new BaseReflectorMock(
            $node,
            new Context()
        );

        $this->assertEquals($node->getLine(), $base_reflector->getLinenumber());

        $node->setLine(123);

        $this->assertEquals(123, $base_reflector->getLinenumber());
    }

    /**
     * Tests the setDefaultPackageName method
     *
     * @covers \phpDocumentor\Reflection\BaseReflector::setDefaultPackageName
     * @covers \phpDocumentor\Reflection\BaseReflector::getDefaultPackageName
     *
     * @return void
     */
    public function testSetDefaultPackageName()
    {
        $node = new NodeStmtMock();

        $base_reflector = new BaseReflectorMock(
            $node,
            new Context()
        );

        $this->assertInternalType(
            'string',
            $base_reflector->getDefaultPackageName()
        );
        $this->assertEquals('', $base_reflector->getDefaultPackageName());

        $base_reflector->setDefaultPackageName('test_name');

        $this->assertEquals('test_name', $base_reflector->getDefaultPackageName());
    }

    /**
     * Tests the setDefaultPackageName method
     *
     * @covers \phpDocumentor\Reflection\BaseReflector::getRepresentationOfValue
     *
     * @return void
     */
    public function testGetRepresentationOfValue()
    {
        $node = new NodeStmtMock();
        $base_reflector = new BaseReflectorMock(
            $node,
            new Context()
        );

        $this->assertEquals('', $base_reflector->getRepresentationOfValueMock(null));

        $pretty_printer = $this->getMock(
            '\phpDocumentor\Reflection\PrettyPrinter',
            array('prettyPrintExpr')
        );
        $base_reflector->setPrettyPrinter($pretty_printer);
        $pretty_printer
            ->expects($this->once())
            ->method('prettyPrintExpr')
            ->will($this->returnValue('test_output'));

        $this->assertEquals(
            'test_output',
            $base_reflector->getRepresentationOfValueMock(new NodeExprMock())
        );
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5
 *
 * @author    Erik Baars <baarserik@hotmail.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Reflection;

/**
 * Class for testing ClassReflector.
 *
 * Extends the ClassReflector so properties and abstract methods can be mocked,
 * and therefore tested.
 *
 * @author    Erik Baars <baarserik@hotmail.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
class ClassReflectorMock extends ClassReflector
{
    public function setTraits(array $val)
    {
        $this->traits = $val;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5
 *
 * @author    Erik Baars <baarserik@hotmail.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Reflection;

use PHPParser_Node_Stmt;

/**
 * Class for testing PHPParser_Node_Stmt.
 *
 * Extends the PHPParser_Node_Stmt so properties and abstract methods can be mocked,
 * and therefore tested.
 *
 * @author    Erik Baars <baarserik@hotmail.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
class NodeStmtMock2 extends PHPParser_Node_Stmt
{
    public $type = null;

    public $implements = array();

    public $extends = null;
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5
 *
 * @author    Erik Baars <baarserik@hotmail.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Reflection;

use PHPParser_Node_Expr;

/**
 * Class for testing base reflector.
 *
 * Extends the baseReflector so properties and abstract methods can be mocked,
 * and therefore tested.
 *
 * @author    Erik Baars <baarserik@hotmail.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
class BaseReflectorMock extends BaseReflector
{
    /**
     * Overload method so we can test the protected method
     *
     * @param PHPParser_Node_Expr $value
     *
     * @return string
     */
    public function getRepresentationOfValueMock(
        PHPParser_Node_Expr $value = null
    ) {
        return parent::getRepresentationOfValue($value);
    }

    /**
     * @param $val
     *
     * @return void
     */
    public function setPrettyPrinter($val)
    {
        self::$prettyPrinter = $val;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5
 *
 * @author    Vasil Rangelov <boen.robot@gmail.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Reflection;

use PHPParser_Node_Expr;

/**
 * Class for testing PHPParser_Node_Expr.
 *
 * Extends the PHPParser_Node_Expr so properties and abstract methods can be mocked,
 * and therefore tested.
 *
 * @author    Vasil Rangelov <boen.robot@gmail.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
class NodeExprMock extends PHPParser_Node_Expr
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5
 *
 * @author    Erik Baars <baarserik@hotmail.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
namespace phpDocumentor\Reflection;

use PHPParser_Node_Stmt;

/**
 * Class for testing PHPParser_Node_Stmt.
 *
 * Extends the PHPParser_Node_Stmt so properties and abstract methods can be mocked,
 * and therefore tested.
 *
 * @author    Erik Baars <baarserik@hotmail.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
class NodeStmtMock extends PHPParser_Node_Stmt
{
    public $name = null;

    public function setName($val)
    {
        $this->name = $val;
    }

    public function __toString()
    {
        return 'testNodeMock';
    }
}
{
    "_readme": [
        "This file locks the dependencies of your project to a known state",
        "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
    ],
    "hash": "efd30a8d97ddf4064ac8666e21239547",
    "packages": [
        {
            "name": "dflydev/markdown",
            "version": "v1.0.2",
            "source": {
                "type": "git",
                "url": "https://github.com/dflydev/dflydev-markdown.git",
                "reference": "v1.0.2"
            },
            "dist": {
                "type": "zip",
                "url": "https://github.com/dflydev/dflydev-markdown/zipball/v1.0.2",
                "reference": "v1.0.2",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3"
            },
            "type": "library",
            "autoload": {
                "psr-0": {
                    "dflydev\\markdown": "src"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "New BSD License"
            ],
            "authors": [
                {
                    "name": "Dragonfly Development Inc.",
                    "email": "info@dflydev.com",
                    "homepage": "http://dflydev.com"
                },
                {
                    "name": "Beau Simensen",
                    "email": "beau@dflydev.com",
                    "homepage": "http://beausimensen.com"
                },
                {
                    "name": "Michel Fortin",
                    "homepage": "http://michelf.com"
                },
                {
                    "name": "John Gruber",
                    "homepage": "http://daringfireball.net"
                }
            ],
            "description": "PHP Markdown & Extra",
            "homepage": "http://github.com/dflydev/dflydev-markdown",
            "keywords": [
                "markdown"
            ],
            "time": "2012-01-15 19:36:37"
        },
        {
            "name": "nikic/php-parser",
            "version": "v0.9.3",
            "source": {
                "type": "git",
                "url": "https://github.com/nikic/PHP-Parser",
                "reference": "v0.9.3"
            },
            "dist": {
                "type": "zip",
                "url": "https://github.com/nikic/PHP-Parser/archive/v0.9.3.zip",
                "reference": "v0.9.3",
                "shasum": ""
            },
            "require": {
                "php": ">=5.2"
            },
            "type": "library",
            "autoload": {
                "psr-0": {
                    "PHPParser": "lib/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Nikita Popov"
                }
            ],
            "description": "A PHP parser written in PHP",
            "keywords": [
                "parser",
                "php"
            ],
            "time": "2012-11-22 18:54:05"
        },
        {
            "name": "phpdocumentor/reflection-docblock",
            "version": "2.0.0a3",
            "source": {
                "type": "git",
                "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
                "reference": "2.0.0a3"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/2.0.0a3",
                "reference": "2.0.0a3",
                "shasum": ""
            },
            "require": {
                "dflydev/markdown": "1.0.*",
                "php": ">=5.3.3"
            },
            "require-dev": {
                "phpunit/phpunit": "3.7.*@stable"
            },
            "type": "library",
            "autoload": {
                "psr-0": {
                    "phpDocumentor": [
                        "src/"
                    ]
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Mike van Riel",
                    "email": "mike.vanriel@naenius.com"
                }
            ],
            "time": "2013-04-16 14:22:15"
        }
    ],
    "packages-dev": [
        {
            "name": "behat/behat",
            "version": "v2.4.6",
            "source": {
                "type": "git",
                "url": "https://github.com/Behat/Behat.git",
                "reference": "v2.4.6"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/Behat/Behat/zipball/v2.4.6",
                "reference": "v2.4.6",
                "shasum": ""
            },
            "require": {
                "behat/gherkin": ">=2.2.9,<2.3",
                "php": ">=5.3.1",
                "symfony/config": ">=2.0,<3.0",
                "symfony/console": ">=2.0,<3.0",
                "symfony/dependency-injection": ">=2.0,<3.0",
                "symfony/event-dispatcher": ">=2.0,<3.0",
                "symfony/finder": ">=2.0,<3.0",
                "symfony/translation": ">=2.0,<3.0",
                "symfony/yaml": ">=2.0,<3.0"
            },
            "require-dev": {
                "phpunit/phpunit": ">=3.7.19.0,<3.8"
            },
            "suggest": {
                "behat/mink-extension": "for integration with Mink testing framework",
                "behat/symfony2-extension": "for integration with Symfony2 web framework",
                "behat/yii-extension": "for integration with Yii web framework"
            },
            "bin": [
                "bin/behat"
            ],
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-develop": "2.4-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Behat\\Behat": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Konstantin Kudryashov",
                    "email": "ever.zet@gmail.com",
                    "homepage": "http://everzet.com"
                }
            ],
            "description": "Scenario-oriented BDD framework for PHP 5.3",
            "homepage": "http://behat.org/",
            "keywords": [
                "BDD",
                "Behat",
                "Symfony2"
            ],
            "time": "2013-06-06 10:46:48"
        },
        {
            "name": "behat/gherkin",
            "version": "v2.2.9",
            "source": {
                "type": "git",
                "url": "https://github.com/Behat/Gherkin.git",
                "reference": "v2.2.9"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/Behat/Gherkin/zipball/v2.2.9",
                "reference": "v2.2.9",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.1",
                "symfony/finder": ">=2.0,<2.4-dev"
            },
            "require-dev": {
                "symfony/config": ">=2.0,<2.4-dev",
                "symfony/translation": ">=2.0,<2.4-dev",
                "symfony/yaml": ">=2.0,<2.4-dev"
            },
            "suggest": {
                "symfony/config": "If you want to use Config component to manage resources",
                "symfony/translation": "If you want to use Symfony2 translations adapter",
                "symfony/yaml": "If you want to parse features, represented in YAML files"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-develop": "2.2-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Behat\\Gherkin": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Konstantin Kudryashov",
                    "email": "ever.zet@gmail.com",
                    "homepage": "http://everzet.com"
                }
            ],
            "description": "Gherkin DSL parser for PHP 5.3",
            "homepage": "http://behat.org/",
            "keywords": [
                "BDD",
                "Behat",
                "DSL",
                "Symfony2",
                "parser"
            ],
            "time": "2013-03-02 10:38:40"
        },
        {
            "name": "mockery/mockery",
            "version": "0.8.0",
            "source": {
                "type": "git",
                "url": "https://github.com/padraic/mockery.git",
                "reference": "0.8.0"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/padraic/mockery/zipball/0.8.0",
                "reference": "0.8.0",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.2"
            },
            "require-dev": {
                "hamcrest/hamcrest": "1.1.0"
            },
            "type": "library",
            "autoload": {
                "psr-0": {
                    "Mockery": "library/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Pádraic Brady",
                    "email": "padraic.brady@gmail.com",
                    "homepage": "http://blog.astrumfutura.com"
                }
            ],
            "description": "Mockery is a simple yet flexible PHP mock object framework for use in unit testing with PHPUnit, PHPSpec or any other testing framework. Its core goal is to offer a test double framework with a succint API capable of clearly defining all possible object operations and interactions using a human readable Domain Specific Language (DSL). Designed as a drop in alternative to PHPUnit's phpunit-mock-objects library, Mockery is easy to integrate with PHPUnit and can operate alongside phpunit-mock-objects without the World ending.",
            "homepage": "http://github.com/padraic/mockery",
            "keywords": [
                "BDD",
                "TDD",
                "library",
                "mock",
                "mock objects",
                "mockery",
                "stub",
                "test",
                "test double",
                "testing"
            ],
            "time": "2013-04-01 12:13:17"
        },
        {
            "name": "phpunit/php-code-coverage",
            "version": "1.2.12",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
                "reference": "1.2.12"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/1.2.12",
                "reference": "1.2.12",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3",
                "phpunit/php-file-iterator": ">=1.3.0@stable",
                "phpunit/php-text-template": ">=1.1.1@stable",
                "phpunit/php-token-stream": ">=1.1.3@stable"
            },
            "require-dev": {
                "phpunit/phpunit": "3.7.*@dev"
            },
            "suggest": {
                "ext-dom": "*",
                "ext-xdebug": ">=2.0.5"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.2.x-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "PHP/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
            "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
            "keywords": [
                "coverage",
                "testing",
                "xunit"
            ],
            "time": "2013-07-06 06:26:16"
        },
        {
            "name": "phpunit/php-file-iterator",
            "version": "1.3.3",
            "source": {
                "type": "git",
                "url": "git://github.com/sebastianbergmann/php-file-iterator.git",
                "reference": "1.3.3"
            },
            "dist": {
                "type": "zip",
                "url": "https://github.com/sebastianbergmann/php-file-iterator/zipball/1.3.3",
                "reference": "1.3.3",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "File/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "FilterIterator implementation that filters files based on a list of suffixes.",
            "homepage": "http://www.phpunit.de/",
            "keywords": [
                "filesystem",
                "iterator"
            ],
            "time": "2012-10-11 04:44:38"
        },
        {
            "name": "phpunit/php-text-template",
            "version": "1.1.4",
            "source": {
                "type": "git",
                "url": "git://github.com/sebastianbergmann/php-text-template.git",
                "reference": "1.1.4"
            },
            "dist": {
                "type": "zip",
                "url": "https://github.com/sebastianbergmann/php-text-template/zipball/1.1.4",
                "reference": "1.1.4",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "Text/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Simple template engine.",
            "homepage": "https://github.com/sebastianbergmann/php-text-template/",
            "keywords": [
                "template"
            ],
            "time": "2012-10-31 11:15:28"
        },
        {
            "name": "phpunit/php-timer",
            "version": "1.0.4",
            "source": {
                "type": "git",
                "url": "git://github.com/sebastianbergmann/php-timer.git",
                "reference": "1.0.4"
            },
            "dist": {
                "type": "zip",
                "url": "https://github.com/sebastianbergmann/php-timer/zipball/1.0.4",
                "reference": "1.0.4",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "PHP/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Utility class for timing",
            "homepage": "http://www.phpunit.de/",
            "keywords": [
                "timer"
            ],
            "time": "2012-10-11 04:45:58"
        },
        {
            "name": "phpunit/php-token-stream",
            "version": "1.1.7",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/php-token-stream.git",
                "reference": "1.1.7"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1.1.7",
                "reference": "1.1.7",
                "shasum": ""
            },
            "require": {
                "ext-tokenizer": "*",
                "php": ">=5.3.3"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "PHP/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Wrapper around PHP's tokenizer extension.",
            "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
            "keywords": [
                "tokenizer"
            ],
            "time": "2013-07-29 14:27:06"
        },
        {
            "name": "phpunit/phpunit",
            "version": "3.7.22",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/phpunit.git",
                "reference": "3.7.22"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3.7.22",
                "reference": "3.7.22",
                "shasum": ""
            },
            "require": {
                "ext-dom": "*",
                "ext-pcre": "*",
                "ext-reflection": "*",
                "ext-spl": "*",
                "php": ">=5.3.3",
                "phpunit/php-code-coverage": "~1.2.1",
                "phpunit/php-file-iterator": ">=1.3.1",
                "phpunit/php-text-template": ">=1.1.1",
                "phpunit/php-timer": "~1.0.2",
                "phpunit/phpunit-mock-objects": "~1.2.0",
                "symfony/yaml": "~2.0"
            },
            "require-dev": {
                "pear-pear/pear": "1.9.4"
            },
            "suggest": {
                "ext-json": "*",
                "ext-simplexml": "*",
                "ext-tokenizer": "*",
                "phpunit/php-invoker": ">=1.1.0,<1.2.0"
            },
            "bin": [
                "composer/bin/phpunit"
            ],
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "3.7.x-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "PHPUnit/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                "",
                "../../symfony/yaml/"
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de",
                    "role": "lead"
                }
            ],
            "description": "The PHP Unit Testing framework.",
            "homepage": "http://www.phpunit.de/",
            "keywords": [
                "phpunit",
                "testing",
                "xunit"
            ],
            "time": "2013-07-06 06:29:15"
        },
        {
            "name": "phpunit/phpunit-mock-objects",
            "version": "1.2.3",
            "source": {
                "type": "git",
                "url": "git://github.com/sebastianbergmann/phpunit-mock-objects.git",
                "reference": "1.2.3"
            },
            "dist": {
                "type": "zip",
                "url": "https://github.com/sebastianbergmann/phpunit-mock-objects/archive/1.2.3.zip",
                "reference": "1.2.3",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3",
                "phpunit/php-text-template": ">=1.1.1@stable"
            },
            "suggest": {
                "ext-soap": "*"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "PHPUnit/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Mock Object library for PHPUnit",
            "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
            "keywords": [
                "mock",
                "xunit"
            ],
            "time": "2013-01-13 10:24:48"
        },
        {
            "name": "symfony/config",
            "version": "v2.3.2",
            "target-dir": "Symfony/Component/Config",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Config.git",
                "reference": "v2.3.2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Config/zipball/v2.3.2",
                "reference": "v2.3.2",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3",
                "symfony/filesystem": "~2.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Config\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Config Component",
            "homepage": "http://symfony.com",
            "time": "2013-07-11 19:36:36"
        },
        {
            "name": "symfony/console",
            "version": "v2.3.2",
            "target-dir": "Symfony/Component/Console",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Console.git",
                "reference": "v2.3.2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Console/zipball/v2.3.2",
                "reference": "v2.3.2",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "require-dev": {
                "symfony/event-dispatcher": "~2.1"
            },
            "suggest": {
                "symfony/event-dispatcher": ""
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Console\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Console Component",
            "homepage": "http://symfony.com",
            "time": "2013-07-11 19:36:36"
        },
        {
            "name": "symfony/dependency-injection",
            "version": "v2.3.2",
            "target-dir": "Symfony/Component/DependencyInjection",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/DependencyInjection.git",
                "reference": "v2.3.2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/v2.3.2",
                "reference": "v2.3.2",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "require-dev": {
                "symfony/config": "~2.2",
                "symfony/yaml": "~2.0"
            },
            "suggest": {
                "symfony/config": "",
                "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them",
                "symfony/yaml": ""
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\DependencyInjection\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony DependencyInjection Component",
            "homepage": "http://symfony.com",
            "time": "2013-07-07 15:47:47"
        },
        {
            "name": "symfony/event-dispatcher",
            "version": "v2.3.2",
            "target-dir": "Symfony/Component/EventDispatcher",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/EventDispatcher.git",
                "reference": "v2.3.2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/v2.3.2",
                "reference": "v2.3.2",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "require-dev": {
                "symfony/dependency-injection": "~2.0"
            },
            "suggest": {
                "symfony/dependency-injection": "",
                "symfony/http-kernel": ""
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\EventDispatcher\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony EventDispatcher Component",
            "homepage": "http://symfony.com",
            "time": "2013-05-13 14:36:40"
        },
        {
            "name": "symfony/filesystem",
            "version": "v2.3.2",
            "target-dir": "Symfony/Component/Filesystem",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Filesystem.git",
                "reference": "v2.3.2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Filesystem/zipball/v2.3.2",
                "reference": "v2.3.2",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Filesystem\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Filesystem Component",
            "homepage": "http://symfony.com",
            "time": "2013-06-04 15:02:05"
        },
        {
            "name": "symfony/finder",
            "version": "v2.3.2",
            "target-dir": "Symfony/Component/Finder",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Finder.git",
                "reference": "v2.3.2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Finder/zipball/v2.3.2",
                "reference": "v2.3.2",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Finder\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Finder Component",
            "homepage": "http://symfony.com",
            "time": "2013-07-01 12:17:23"
        },
        {
            "name": "symfony/translation",
            "version": "v2.3.2",
            "target-dir": "Symfony/Component/Translation",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Translation.git",
                "reference": "v2.3.2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Translation/zipball/v2.3.2",
                "reference": "v2.3.2",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "require-dev": {
                "symfony/config": "~2.0",
                "symfony/yaml": "~2.2"
            },
            "suggest": {
                "symfony/config": "",
                "symfony/yaml": ""
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Translation\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Translation Component",
            "homepage": "http://symfony.com",
            "time": "2013-05-13 14:36:40"
        },
        {
            "name": "symfony/yaml",
            "version": "v2.3.2",
            "target-dir": "Symfony/Component/Yaml",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Yaml.git",
                "reference": "v2.3.2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Yaml/zipball/v2.3.2",
                "reference": "v2.3.2",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Yaml\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Yaml Component",
            "homepage": "http://symfony.com",
            "time": "2013-07-11 19:36:36"
        }
    ],
    "aliases": [

    ],
    "minimum-stability": "stable",
    "stability-flags": {
        "phpdocumentor/reflection-docblock": 20
    },
    "platform": {
        "php": ">=5.3.3"
    },
    "platform-dev": [

    ]
}
<?xml version="1.0" encoding="utf-8"?>

<phpunit bootstrap="vendor/autoload.php" colors="true" strict="true">
    <testsuites>
        <testsuite name="phpDocumentor">
            <directory>./tests/unit/</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist>
            <directory suffix=".php">src/phpDocumentor</directory>
        </whitelist>
    </filter>
    <listeners>
        <listener class="Mockery\Adapter\Phpunit\TestListener"
            file="vendor/mockery/mockery/library/Mockery/Adapter/Phpunit/TestListener.php"></listener>
    </listeners>
</phpunit>
{
    "name":    "phpdocumentor/graphviz",
    "type":    "library",
    "license": "MIT",
    "authors": [
        {"name": "Mike van Riel", "email": "mike.vanriel@naenius.com"}
    ],
    "require": {
        "php": ">=5.3.3"
    },
    "require-dev": {
        "phpunit/phpunit": "~3.7"
    },
    "autoload": {
        "psr-0": {"phpDocumentor": ["src/", "tests/unit"]}
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\GraphViz;

/**
 * Class representing a single GraphViz attribute.
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
class Attribute
{
    /** @var string The name of this attribute */
    protected $key = '';

    /** @var string The value of this attribute*/
    protected $value = '';

    /**
     * Creating a new attribute.
     *
     * @param string $key   Id for the new attribute.
     * @param string $value Value for this attribute,
     */
    public function __construct($key, $value)
    {
        $this->key = $key;
        $this->value = $value;
    }

    /**
     * Sets the key for this attribute.
     *
     * @param string $key The new name of this attribute.
     *
     * @return \phpDocumentor\GraphViz\Attribute
     */
    public function setKey($key)
    {
        $this->key = $key;
        return $this;
    }

    /**
     * Returns the name for this attribute.
     *
     * @return string
     */
    public function getKey()
    {
        return $this->key;
    }

    /**
     * Sets the value for this attribute.
     *
     * @param string $value The new value.
     *
     * @return \phpDocumentor\GraphViz\Attribute
     */
    public function setValue($value)
    {
        $this->value = $value;
        return $this;
    }

    /**
     * Returns the value for this attribute.
     *
     * @return string
     */
    public function getValue()
    {
        return $this->value;
    }

    /**
     * Returns whether the value contains HTML.
     *
     * @return bool
     */
    public function isValueInHtml()
    {
        $value = $this->getValue();
        return (bool)(isset($value[0]) && ($value[0] == '<'));
    }

    public function isValueContainingSpecials()
    {
        return strstr($this->value, "\l") !== false;
    }

    /**
     * Returns the attribute definition as is requested by GraphViz.
     *
     * @return string
     */
    function __toString()
    {
        $key = $this->getKey();
        if ($key == 'url') {
            $key = 'URL';
        }

        $value = $this->getValue();
        if (!$this->isValueInHtml() && !$this->isValueContainingSpecials()) {
            $value = '"' . addslashes($value) . '"';
        }
        return $key . '=' . $value;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\GraphViz;

/**
 * Class representing an exception in this GraphViz component.
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
class Exception extends \Exception
{

}<?php
/**
 * phpDocumentor
 *
 * PHP Version 5
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\GraphViz;

/**
 * Class representing a node / element in a graph.
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 *
 * @method void setLabel(string $name) Sets the label for this node.
 */
class Node
{

    /** @var string Name for this node */
    protected $name = '';

    /** @var \phpDocumentor\GraphViz\Attribute[] List of attributes for this node */
    protected $attributes = array();

    /**
     * Creates a new node with name and optional label.
     *
     * @param string      $name  Name of the new node.
     * @param string|null $label Optional label text.
     */
    function __construct($name, $label = null)
    {
        $this->setName($name);
        if ($label !== null) {
            $this->setLabel($label);
        }
    }

    /**
     * Factory method used to assist with fluent interface handling.
     *
     * See the examples for more details.
     *
     * @param string      $name  Name of the new node.
     * @param string|null $label Optional label text.
     *
     * @return \phpDocumentor\GraphViz\Node
     */
    public static function create($name, $label = null)
    {
        return new self($name, $label);
    }

    /**
     * Sets the name for this node.
     *
     * Not to confuse with the label.
     *
     * @param string $name Name for this node.
     *
     * @return \phpDocumentor\GraphViz\Node
     */
    public function setName($name)
    {
        $this->name = $name;
        return $this;
    }

    /**
     * Returns the name for this node.
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Magic method to provide a getter/setter to add attributes on the Node.
     *
     * Using this method we make sure that we support any attribute without
     * too much hassle. If the name for this method does not start with get or
     * set we return null.
     *
     * Set methods return this graph (fluent interface) whilst get methods
     * return the attribute value.
     *
     * @param string  $name      Method name; either getX or setX is expected.
     * @param mixed[] $arguments List of arguments; only 1 is expected for setX.
     *
     * @return \phpDocumentor\GraphViz\Attribute[]|\phpDocumentor\GraphViz\Node|null
     */
    function __call($name, $arguments)
    {
        $key = strtolower(substr($name, 3));
        if (strtolower(substr($name, 0, 3)) == 'set') {
            $this->attributes[$key] = new Attribute($key, $arguments[0]);
            return $this;
        }

        if (strtolower(substr($name, 0, 3)) == 'get') {
            return $this->attributes[$key];
        }

        return null;
    }

    /**
     * Returns the node definition as is requested by GraphViz.
     *
     * @return string
     */
    public function __toString()
    {
        $attributes = array();
        foreach ($this->attributes as $value) {
            $attributes[] = (string)$value;
        }
        $attributes = implode("\n", $attributes);

        $name = addslashes($this->getName());

        return <<<DOT
"{$name}" [
$attributes
]
DOT;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\GraphViz;

/**
 * Class representing a graph; this may be a main graph but also a subgraph.
 *
 * In case of a subgraph:
 * When the name of the subgraph is prefixed with _cluster_ then the contents
 * of this graph will be grouped and a border will be added. Otherwise it is
 * used as logical container to place defaults in.
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
class Graph
{

    /** @var string Name of this graph */
    protected $name = 'G';

    /** @var string Type of this graph; may be digraph, graph or subgraph */
    protected $type = 'digraph';

    /** @var \phpDocumentor\GraphViz\Attribute[] A list of attributes for this Graph */
    protected $attributes = array();

    /** @var \phpDocumentor\GraphViz\Graph[] A list of subgraphs for this Graph */
    protected $graphs = array();

    /** @var \phpDocumentor\GraphViz\Node[] A list of nodes for this Graph */
    protected $nodes = array();

    /** @var \phpDocumentor\GraphViz\Edge[] A list of edges / arrows for this Graph */
    protected $edges = array();

    /**
     * Factory method to instantiate a Graph so that you can use fluent coding
     * to chain everything.
     *
     * @param string $name        The name for this graph.
     * @param bool   $directional Whether this is a directed or undirected graph.
     *
     * @return \phpDocumentor\GraphViz\Graph
     */
    public static function create($name = 'G', $directional = true)
    {
        $graph = new self();
        $graph
            ->setName($name)
            ->setType($directional ? 'digraph' : 'graph');

        return $graph;
    }

    /**
     * Sets the name for this graph.
     *
     * If this is a subgraph you can prefix the name with _cluster_ to group all
     * contained nodes and add a border.
     *
     * @param string $name The new name for this graph.
     *
     * @return \phpDocumentor\GraphViz\Graph
     */
    public function setName($name)
    {
        $this->name = $name;
        return $this;
    }

    /**
     * Returns the name for this Graph.
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Sets the type for this graph.
     *
     * @param string $type Must be either "digraph", "graph" or "subgraph".
     *
     * @throws \InvalidArgumentException if $type is not "digraph", "graph" or
     *  "subgraph".
     *
     * @return \phpDocumentor\GraphViz\Graph
     */
    public function setType($type)
    {
        if (!in_array($type, array('digraph', 'graph', 'subgraph'))) {
            throw new \InvalidArgumentException(
                'The type for a graph must be either "digraph", "graph" or '
                . '"subgraph"'
            );
        }

        $this->type = $type;
        return $this;
    }

    /**
     * Returns the type of this Graph.
     *
     * @return string
     */
    public function getType()
    {
        return $this->type;
    }

    /**
     * Magic method to provide a getter/setter to add attributes on the Graph.
     *
     * Using this method we make sure that we support any attribute without
     * too much hassle. If the name for this method does not start with get
     * or set we return null.
     *
     * Set methods return this graph (fluent interface) whilst get methods
     * return the attribute value.
     *
     * @param string  $name      Name of the method including get/set
     * @param mixed[] $arguments The arguments, should be 1: the value
     *
     * @return \phpDocumentor\GraphViz\Attribute[]|\phpDocumentor\GraphViz\Graph|null
     */
    function __call($name, $arguments)
    {
        $key = strtolower(substr($name, 3));
        if (strtolower(substr($name, 0, 3)) == 'set') {
            $this->attributes[$key] = new Attribute($key, $arguments[0]);

            return $this;
        }
        if (strtolower(substr($name, 0, 3)) == 'get') {
            return $this->attributes[$key];
        }

        return null;
    }

    /**
     * Adds a subgraph to this graph; automatically changes the type to subgraph.
     *
     * Please note that an index is maintained using the name of the subgraph.
     * Thus if you have 2 subgraphs with the same name that the first will be
     * overwritten by the latter.
     *
     * @param \phpDocumentor\GraphViz\Graph $graph The graph to add onto this graph as
     *  subgraph.
     *
     * @see \phpDocumentor\GraphViz\Graph::create()
     *
     * @return \phpDocumentor\GraphViz\Graph
     */
    public function addGraph(\phpDocumentor\GraphViz\Graph $graph)
    {
        $graph->setType('subgraph');
        $this->graphs[$graph->getName()] = $graph;
        return $this;
    }

    /**
     * Checks whether a graph with a certain name already exists.
     *
     * @param string $name Name of the graph to find.
     *
     * @return bool
     */
    public function hasGraph($name)
    {
        return isset($this->graphs[$name]);
    }

    /**
     * Returns the subgraph with a given name.
     *
     * @param string $name Name of the requested graph.
     *
     * @return \phpDocumentor\GraphViz\Graph
     */
    public function getGraph($name)
    {
        return $this->graphs[$name];
    }

    /**
     * Sets a node in the $nodes array; uses the name of the node as index.
     *
     * Nodes can be retrieved by retrieving the property with the same name.
     * Thus 'node1' can be retrieved by invoking: $graph->node1
     *
     * @param \phpDocumentor\GraphViz\Node $node The node to set onto this Graph.
     *
     * @see \phpDocumentor\GraphViz\Node::create()
     *
     * @return \phpDocumentor\GraphViz\Graph
     */
    public function setNode(Node $node)
    {
        $this->nodes[$node->getName()] = $node;
        return $this;
    }

    /**
     * Finds a node in this graph or any of its subgraphs.
     *
     * @param string $name Name of the node to find.
     *
     * @return \phpDocumentor\GraphViz\Node
     */
    public function findNode($name)
    {
        if (isset($this->nodes[$name])) {
            return $this->nodes[$name];
        }

        foreach ($this->graphs as $graph) {
            $node = $graph->findNode($name);
            if ($node) {
                return $node;
            }
        }

        return null;
    }

    /**
     * Sets a node using a custom name.
     *
     * @param string                       $name  Name of the node.
     * @param \phpDocumentor\GraphViz\Node $value Node to set on the given name.
     *
     * @see \phpDocumentor\GraphViz\Graph::setNode()
     *
     * @return \phpDocumentor\GraphViz\Graph
     */
    function __set($name, $value)
    {
        $this->nodes[$name] = $value;
        return $this;
    }


    /**
     * Returns the requested node by its name.
     *
     * @param string $name The name of the node to retrieve.
     *
     * @see \phpDocumentor\GraphViz\Graph::setNode()
     *
     * @return \phpDocumentor\GraphViz\Node
     */
    function __get($name)
    {
        return isset($this->nodes[$name]) ? $this->nodes[$name] : null;
    }

    /**
     * Links two nodes to eachother and registers the Edge onto this graph.
     *
     * @param \phpDocumentor\GraphViz\Edge $edge The link between two classes.
     *
     * @see \phpDocumentor\GraphViz\Edge::create()
     *
     * @return \phpDocumentor\GraphViz\Graph
     */
    public function link(Edge $edge)
    {
        $this->edges[] = $edge;
        return $this;
    }

    /**
     * Exports this graph to a generated image.
     *
     * This is the only method that actually requires GraphViz.
     *
     * @param string $type     The type to export to; see the link above for a
     *  list of supported types.
     * @param string $filename The path to write to.
     *
     * @uses GraphViz/dot
     *
     * @link http://www.graphviz.org/content/output-formats
     *
     * @throws \phpDocumentor\GraphViz\Exception if an error occurred in GraphViz.
     *
     * @return \phpDocumentor\GraphViz\Graph
     */
    public function export($type, $filename)
    {
        $type = escapeshellarg($type);
        $filename = escapeshellarg($filename);

        // write the dot file to a temporary file
        $tmpfile = tempnam(sys_get_temp_dir(), 'gvz');
        file_put_contents($tmpfile, (string)$this);

        // escape the temp file for use as argument
        $tmpfile_arg = escapeshellarg($tmpfile);

        // create the dot output
        $output = array();
        $code = 0;
        exec("dot -T$type -o$filename < $tmpfile_arg 2>&1", $output, $code);
        unlink($tmpfile);

        if ($code != 0) {
            throw new Exception(
                'An error occurred while creating the graph; GraphViz returned: '
                . implode(PHP_EOL, $output)
            );
        }

        return $this;
    }

    /**
     * Generates a DOT file for use with GraphViz.
     *
     * GraphViz is not used in this method; it is safe to call it even without
     * GraphViz installed.
     *
     * @return string
     */
    public function __toString()
    {
        $elements = array_merge(
            $this->graphs, $this->attributes, $this->edges, $this->nodes
        );

        $attributes = array();
        foreach ($elements as $value) {
            $attributes[] = (string)$value;
        }
        $attributes = implode(PHP_EOL, $attributes);

        return <<<DOT
{$this->getType()} "{$this->getName()}" {
$attributes
}
DOT;
    }

}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\GraphViz;

/**
 * Class representing an edge (arrow, line).
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
class Edge
{
    /** @var \phpDocumentor\GraphViz\Node Node from where to link */
    protected $from = null;

    /** @var \phpDocumentor\GraphViz\Node Node where to to link */
    protected $to = null;

    /** @var \phpDocumentor\GraphViz\Attribute List of attributes for this edge */
    protected $attributes = array();

    /**
     * Creates a new Edge / Link between the given nodes.
     *
     * @param \phpDocumentor\GraphViz\Node $from Starting node to create an Edge from.
     * @param \phpDocumentor\GraphViz\Node $to   Destination node where to create and
     *  edge to.
     */
    function __construct(Node $from, Node $to)
    {
        $this->from = $from;
        $this->to   = $to;
    }

    /**
     * Factory method used to assist with fluent interface handling.
     *
     * See the examples for more details.
     *
     * @param \phpDocumentor\GraphViz\Node $from Starting node to create an Edge from.
     * @param \phpDocumentor\GraphViz\Node $to   Destination node where to create and
     *  edge to.
     *
     * @return \phpDocumentor\GraphViz\Edge
     */
    public static function create(Node $from, Node $to) {
        return new self($from, $to);
    }

    /**
     * Returns the source Node for this Edge.
     *
     * @return \phpDocumentor\GraphViz\Node
     */
    public function getFrom()
    {
        return $this->from;
    }

    /**
     * Returns the destination Node for this Edge.
     *
     * @return \phpDocumentor\GraphViz\Node
     */
    public function getTo()
    {
        return $this->to;
    }

    /**
     * Magic method to provide a getter/setter to add attributes on the edge.
     *
     * Using this method we make sure that we support any attribute without too
     * much hassle. If the name for this method does not start with get or set
     * we return null.
     *
     * Set methods return this graph (fluent interface) whilst get methods
     * return the attribute value.
     *
     * @param string  $name      name of the invoked method, expect it to be
     *  setX or getX.
     * @param mixed[] $arguments Arguments for the setter, only 1 is expected: value
     *
     * @return \phpDocumentor\GraphViz\Attribute[]|\phpDocumentor\GraphViz\Edge|null
     */
    function __call($name, $arguments)
    {
        $key = strtolower(substr($name, 3));
        if (strtolower(substr($name, 0, 3)) == 'set') {
            $this->attributes[$key] = new Attribute($key, $arguments[0]);

            return $this;
        }
        if (strtolower(substr($name, 0, 3)) == 'get') {
            return $this->attributes[$key];
        }

        return null;
    }

    /**
     * Returns the edge definition as is requested by GraphViz.
     *
     * @return string
     */
    public function __toString()
    {
        $attributes = array();
        foreach ($this->attributes as $value) {
            $attributes[] = (string)$value;
        }
        $attributes = implode("\n", $attributes);

        $from_name = addslashes($this->getFrom()->getName());
        $to_name   = addslashes($this->getTo()->getName());

        return <<<DOT
"$from_name" -> "$to_name" [
$attributes
]
DOT;
    }
}
{
    "_readme": [
        "This file locks the dependencies of your project to a known state",
        "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
    ],
    "hash": "640a388e152afedda1b1cc14ba5b277c",
    "packages": [

    ],
    "packages-dev": [
        {
            "name": "phpunit/php-code-coverage",
            "version": "1.2.12",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
                "reference": "1.2.12"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/1.2.12",
                "reference": "1.2.12",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3",
                "phpunit/php-file-iterator": ">=1.3.0@stable",
                "phpunit/php-text-template": ">=1.1.1@stable",
                "phpunit/php-token-stream": ">=1.1.3@stable"
            },
            "require-dev": {
                "phpunit/phpunit": "3.7.*@dev"
            },
            "suggest": {
                "ext-dom": "*",
                "ext-xdebug": ">=2.0.5"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.2.x-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "PHP/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
            "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
            "keywords": [
                "coverage",
                "testing",
                "xunit"
            ],
            "time": "2013-07-06 06:26:16"
        },
        {
            "name": "phpunit/php-file-iterator",
            "version": "1.3.3",
            "source": {
                "type": "git",
                "url": "git://github.com/sebastianbergmann/php-file-iterator.git",
                "reference": "1.3.3"
            },
            "dist": {
                "type": "zip",
                "url": "https://github.com/sebastianbergmann/php-file-iterator/zipball/1.3.3",
                "reference": "1.3.3",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "File/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "FilterIterator implementation that filters files based on a list of suffixes.",
            "homepage": "http://www.phpunit.de/",
            "keywords": [
                "filesystem",
                "iterator"
            ],
            "time": "2012-10-11 04:44:38"
        },
        {
            "name": "phpunit/php-text-template",
            "version": "1.1.4",
            "source": {
                "type": "git",
                "url": "git://github.com/sebastianbergmann/php-text-template.git",
                "reference": "1.1.4"
            },
            "dist": {
                "type": "zip",
                "url": "https://github.com/sebastianbergmann/php-text-template/zipball/1.1.4",
                "reference": "1.1.4",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "Text/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Simple template engine.",
            "homepage": "https://github.com/sebastianbergmann/php-text-template/",
            "keywords": [
                "template"
            ],
            "time": "2012-10-31 11:15:28"
        },
        {
            "name": "phpunit/php-timer",
            "version": "1.0.5",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/php-timer.git",
                "reference": "1.0.5"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/1.0.5",
                "reference": "1.0.5",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "PHP/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Utility class for timing",
            "homepage": "https://github.com/sebastianbergmann/php-timer/",
            "keywords": [
                "timer"
            ],
            "time": "2013-08-02 07:42:54"
        },
        {
            "name": "phpunit/php-token-stream",
            "version": "1.2.0",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/php-token-stream.git",
                "reference": "1.2.0"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1.2.0",
                "reference": "1.2.0",
                "shasum": ""
            },
            "require": {
                "ext-tokenizer": "*",
                "php": ">=5.3.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.2-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "PHP/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Wrapper around PHP's tokenizer extension.",
            "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
            "keywords": [
                "tokenizer"
            ],
            "time": "2013-08-04 05:57:48"
        },
        {
            "name": "phpunit/phpunit",
            "version": "3.7.23",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/phpunit.git",
                "reference": "3.7.23"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3.7.23",
                "reference": "3.7.23",
                "shasum": ""
            },
            "require": {
                "ext-dom": "*",
                "ext-pcre": "*",
                "ext-reflection": "*",
                "ext-spl": "*",
                "php": ">=5.3.3",
                "phpunit/php-code-coverage": "~1.2.1",
                "phpunit/php-file-iterator": ">=1.3.1",
                "phpunit/php-text-template": ">=1.1.1",
                "phpunit/php-timer": ">=1.0.4",
                "phpunit/phpunit-mock-objects": "~1.2.0",
                "symfony/yaml": "~2.0"
            },
            "require-dev": {
                "pear-pear/pear": "1.9.4"
            },
            "suggest": {
                "ext-json": "*",
                "ext-simplexml": "*",
                "ext-tokenizer": "*",
                "phpunit/php-invoker": ">=1.1.0,<1.2.0"
            },
            "bin": [
                "composer/bin/phpunit"
            ],
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "3.7.x-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "PHPUnit/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                "",
                "../../symfony/yaml/"
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de",
                    "role": "lead"
                }
            ],
            "description": "The PHP Unit Testing framework.",
            "homepage": "http://www.phpunit.de/",
            "keywords": [
                "phpunit",
                "testing",
                "xunit"
            ],
            "time": "2013-08-02 19:14:44"
        },
        {
            "name": "phpunit/phpunit-mock-objects",
            "version": "1.2.3",
            "source": {
                "type": "git",
                "url": "git://github.com/sebastianbergmann/phpunit-mock-objects.git",
                "reference": "1.2.3"
            },
            "dist": {
                "type": "zip",
                "url": "https://github.com/sebastianbergmann/phpunit-mock-objects/archive/1.2.3.zip",
                "reference": "1.2.3",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3",
                "phpunit/php-text-template": ">=1.1.1@stable"
            },
            "suggest": {
                "ext-soap": "*"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "PHPUnit/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Mock Object library for PHPUnit",
            "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
            "keywords": [
                "mock",
                "xunit"
            ],
            "time": "2013-01-13 10:24:48"
        },
        {
            "name": "symfony/yaml",
            "version": "v2.3.2",
            "target-dir": "Symfony/Component/Yaml",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Yaml.git",
                "reference": "v2.3.2"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Yaml/zipball/v2.3.2",
                "reference": "v2.3.2",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Yaml\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Yaml Component",
            "homepage": "http://symfony.com",
            "time": "2013-07-11 19:36:36"
        }
    ],
    "aliases": [

    ],
    "minimum-stability": "stable",
    "stability-flags": [

    ],
    "platform": {
        "php": ">=5.3.3"
    },
    "platform-dev": [

    ]
}
<?xml version="1.0" encoding="utf-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="true"
         syntaxCheck="true"
         bootstrap="vendor/autoload.php"
         strict="true"
>
    <testsuites>
        <testsuite name="phpDocumentor\GraphViz">
            <directory>./tests/</directory>
        </testsuite>
    </testsuites>
    <logging>
        <log type="coverage-clover" target="build/logs/clover.xml" />
        <log type="junit" target="build/logs/junit.xml" logIncompleteSkipped="false" />
    </logging>
    <filter>
        <whitelist>
            <directory>./src/</directory>
        </whitelist>
    </filter>
</phpunit>
{
    "name":    "phpdocumentor/reflection-docblock",
    "type":    "library",
    "license": "MIT",
    "authors": [
        {"name": "Mike van Riel", "email": "mike.vanriel@naenius.com"}
    ],
    "require": {
        "php": ">=5.3.3"
    },
    "autoload": {
        "psr-0": {"phpDocumentor": ["src/"]}
    },
    "require-dev": {
        "phpunit/phpunit": "3.7.*@stable"
    },
    "suggest": {
        "dflydev/markdown": "1.0.*",
        "erusev/parsedown": "~0.7"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "2.0.x-dev"
        }
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Vasil Rangelov <boen.robot@gmail.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\DocBlock;

/**
 * The context in which a DocBlock occurs.
 *
 * @author  Vasil Rangelov <boen.robot@gmail.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class Context
{
    /** @var string The current namespace. */
    protected $namespace = '';

    /** @var array List of namespace aliases => Fully Qualified Namespace. */
    protected $namespace_aliases = array();
    
    /** @var string Name of the structural element, within the namespace. */
    protected $lsen = '';
    
    /**
     * Cteates a new context.
     * @param string $namespace         The namespace where this DocBlock
     *     resides in.
     * @param array  $namespace_aliases List of namespace aliases => Fully
     *     Qualified Namespace.
     * @param string $lsen              Name of the structural element, within
     *     the namespace.
     */
    public function __construct(
        $namespace = '',
        array $namespace_aliases = array(),
        $lsen = ''
    ) {
        if (!empty($namespace)) {
            $this->setNamespace($namespace);
        }
        $this->setNamespaceAliases($namespace_aliases);
        $this->setLSEN($lsen);
    }

    /**
     * @return string The namespace where this DocBlock resides in.
     */
    public function getNamespace()
    {
        return $this->namespace;
    }

    /**
     * @return array List of namespace aliases => Fully Qualified Namespace.
     */
    public function getNamespaceAliases()
    {
        return $this->namespace_aliases;
    }
    
    /**
     * Returns the Local Structural Element Name.
     * 
     * @return string Name of the structural element, within the namespace.
     */
    public function getLSEN()
    {
        return $this->lsen;
    }
    
    /**
     * Sets a new namespace.
     * 
     * Sets a new namespace for the context. Leading and trailing slashes are
     * trimmed, and the keywords "global" and "default" are treated as aliases
     * to no namespace.
     * 
     * @param string $namespace The new namespace to set.
     * 
     * @return $this
     */
    public function setNamespace($namespace)
    {
        if ('global' !== $namespace
            && 'default' !== $namespace
        ) {
            // Srip leading and trailing slash
            $this->namespace = trim((string)$namespace, '\\');
        } else {
            $this->namespace = '';
        }
        return $this;
    }
    
    /**
     * Sets the namespace aliases, replacing all previous ones.
     * 
     * @param array $namespace_aliases List of namespace aliases => Fully
     *     Qualified Namespace.
     * 
     * @return $this
     */
    public function setNamespaceAliases(array $namespace_aliases)
    {
        $this->namespace_aliases = array();
        foreach ($namespace_aliases as $alias => $fqnn) {
            $this->setNamespaceAlias($alias, $fqnn);
        }
        return $this;
    }
    
    /**
     * Adds a namespace alias to the context.
     * 
     * @param string $alias The alias name (the part after "as", or the last
     *     part of the Fully Qualified Namespace Name) to add.
     * @param string $fqnn  The Fully Qualified Namespace Name for this alias.
     *     Any form of leading/trailing slashes are accepted, but what will be
     *     stored is a name, prefixed with a slash, and no trailing slash.
     * 
     * @return $this
     */
    public function setNamespaceAlias($alias, $fqnn)
    {
        $this->namespace_aliases[$alias] = '\\' . trim((string)$fqnn, '\\');
        return $this;
    }
    
    /**
     * Sets a new Local Structural Element Name.
     * 
     * Sets a new Local Structural Element Name. A local name also contains
     * punctuation determining the kind of structural element (e.g. trailing "("
     * and ")" for functions and methods).
     * 
     * @param string $lsen The new local name of a structural element.
     * 
     * @return $this
     */
    public function setLSEN($lsen)
    {
        $this->lsen = (string)$lsen;
        return $this;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Barry vd. Heuvel <barryvdh@gmail.com>
 * @copyright 2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\DocBlock;

use phpDocumentor\Reflection\DocBlock;

/**
 * Serializes a DocBlock instance.
 *
 * @author  Barry vd. Heuvel <barryvdh@gmail.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class Serializer
{

    /** @var string The string to indent the comment with. */
    protected $indentString = ' ';

    /** @var int The number of times the indent string is repeated. */
    protected $indent = 0;

    /** @var bool Whether to indent the first line. */
    protected $isFirstLineIndented = true;

    /** @var int|null The max length of a line. */
    protected $lineLength = null;

    /**
     * Create a Serializer instance.
     *
     * @param int      $indent          The number of times the indent string is
     *     repeated.
     * @param string   $indentString    The string to indent the comment with.
     * @param bool     $indentFirstLine Whether to indent the first line.
     * @param int|null $lineLength      The max length of a line or NULL to
     *     disable line wrapping.
     */
    public function __construct(
        $indent = 0,
        $indentString = ' ',
        $indentFirstLine = true,
        $lineLength = null
    ) {
        $this->setIndentationString($indentString);
        $this->setIndent($indent);
        $this->setIsFirstLineIndented($indentFirstLine);
        $this->setLineLength($lineLength);
    }

    /**
     * Sets the string to indent comments with.
     * 
     * @param string $indentationString The string to indent comments with.
     * 
     * @return $this This serializer object.
     */
    public function setIndentationString($indentString)
    {
        $this->indentString = (string)$indentString;
        return $this;
    }

    /**
     * Gets the string to indent comments with.
     * 
     * @return string The indent string.
     */
    public function getIndentationString()
    {
        return $this->indentString;
    }

    /**
     * Sets the number of indents.
     * 
     * @param int $indent The number of times the indent string is repeated.
     * 
     * @return $this This serializer object.
     */
    public function setIndent($indent)
    {
        $this->indent = (int)$indent;
        return $this;
    }

    /**
     * Gets the number of indents.
     * 
     * @return int The number of times the indent string is repeated.
     */
    public function getIndent()
    {
        return $this->indent;
    }

    /**
     * Sets whether or not the first line should be indented.
     * 
     * Sets whether or not the first line (the one with the "/**") should be
     * indented.
     * 
     * @param bool $indentFirstLine The new value for this setting.
     * 
     * @return $this This serializer object.
     */
    public function setIsFirstLineIndented($indentFirstLine)
    {
        $this->isFirstLineIndented = (bool)$indentFirstLine;
        return $this;
    }

    /**
     * Gets whether or not the first line should be indented.
     * 
     * @return bool Whether or not the first line should be indented.
     */
    public function isFirstLineIndented()
    {
        return $this->isFirstLineIndented;
    }

    /**
     * Sets the line length.
     * 
     * Sets the length of each line in the serialization. Content will be
     * wrapped within this limit.
     * 
     * @param int|null $lineLength The length of each line. NULL to disable line
     *     wrapping altogether.
     * 
     * @return $this This serializer object.
     */
    public function setLineLength($lineLength)
    {
        $this->lineLength = null === $lineLength ? null : (int)$lineLength;
        return $this;
    }

    /**
     * Gets the line length.
     * 
     * @return int|null The length of each line or NULL if line wrapping is
     *     disabled.
     */
    public function getLineLength()
    {
        return $this->lineLength;
    }

    /**
     * Generate a DocBlock comment.
     *
     * @param DocBlock The DocBlock to serialize.
     * 
     * @return string The serialized doc block.
     */
    public function getDocComment(DocBlock $docblock)
    {
        $indent = str_repeat($this->indentString, $this->indent);
        $firstIndent = $this->isFirstLineIndented ? $indent : '';

        $text = $docblock->getText();
        if ($this->lineLength) {
            //3 === strlen(' * ')
            $wrapLength = $this->lineLength - strlen($indent) - 3;
            $text = wordwrap($text, $wrapLength);
        }
        $text = str_replace("\n", "\n{$indent} * ", $text);

        $comment = "{$firstIndent}/**\n{$indent} * {$text}\n{$indent} *\n";

        /** @var Tag $tag */
        foreach ($docblock->getTags() as $tag) {
            $tagText = (string) $tag;
            if ($this->lineLength) {
                $tagText = wordwrap($tagText, $wrapLength);
            }
            $tagText = str_replace("\n", "\n{$indent} * ", $tagText);

            $comment .= "{$indent} * {$tagText}\n";
        }

        $comment .= $indent . ' */';

        return $comment;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\DocBlock;

use phpDocumentor\Reflection\DocBlock;

/**
 * Parses a Description of a DocBlock or tag.
 *
 * @author  Mike van Riel <mike.vanriel@naenius.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class Description implements \Reflector
{
    /** @var string */
    protected $contents = '';

    /** @var array The contents, as an array of strings and Tag objects. */
    protected $parsedContents = null;

    /** @var DocBlock The DocBlock which this description belongs to. */
    protected $docblock = null;

    /**
     * Populates the fields of a description.
     *
     * @param string   $content  The description's conetnts.
     * @param DocBlock $docblock The DocBlock which this description belongs to.
     */
    public function __construct($content, DocBlock $docblock = null)
    {
        $this->setContent($content)->setDocBlock($docblock);
    }

    /**
     * Gets the text of this description.
     *
     * @return string
     */
    public function getContents()
    {
        return $this->contents;
    }

    /**
     * Sets the text of this description.
     *
     * @param string $content The new text of this description.
     *
     * @return $this
     */
    public function setContent($content)
    {
        $this->contents = trim($content);

        $this->parsedContents = null;
        return $this;
    }

    /**
     * Returns the parsed text of this description.
     *
     * @return array An array of strings and tag objects, in the order they
     *     occur within the description.
     */
    public function getParsedContents()
    {
        if (null === $this->parsedContents) {
            $this->parsedContents = preg_split(
                '/\{
                    # "{@}" is not a valid inline tag. This ensures that
                    # we do not treat it as one, but treat it literally.
                    (?!@\})
                    # We want to capture the whole tag line, but without the
                    # inline tag delimiters.
                    (\@
                        # Match everything up to the next delimiter.
                        [^{}]*
                        # Nested inline tag content should not be captured, or
                        # it will appear in the result separately.
                        (?:
                            # Match nested inline tags.
                            (?:
                                # Because we did not catch the tag delimiters
                                # earlier, we must be explicit with them here.
                                # Notice that this also matches "{}", as a way
                                # to later introduce it as an escape sequence.
                                \{(?1)?\}
                                |
                                # Make sure we match hanging "{".
                                \{
                            )
                            # Match content after the nested inline tag.
                            [^{}]*
                        )* # If there are more inline tags, match them as well.
                           # We use "*" since there may not be any nested inline
                           # tags.
                    )
                \}/Sux',
                $this->contents,
                null,
                PREG_SPLIT_DELIM_CAPTURE
            );

            $count = count($this->parsedContents);
            for ($i=1; $i<$count; $i += 2) {
                $this->parsedContents[$i] = Tag::createInstance(
                    $this->parsedContents[$i],
                    $this->docblock
                );
            }

            //In order to allow "literal" inline tags, the otherwise invalid
            //sequence "{@}" is changed to "@", and "{}" is changed to "}".
            //See unit tests for examples.
            for ($i=0; $i<$count; $i += 2) {
                $this->parsedContents[$i] = str_replace(
                    array('{@}', '{}'),
                    array('@', '}'),
                    $this->parsedContents[$i]
                );
            }
        }
        return $this->parsedContents;
    }

    /**
     * Return a formatted variant of the Long Description using MarkDown.
     *
     * @todo this should become a more intelligent piece of code where the
     *     configuration contains a setting what format long descriptions are.
     *
     * @codeCoverageIgnore Will be removed soon, in favor of adapters at
     *     PhpDocumentor itself that will process text in various formats.
     *
     * @return string
     */
    public function getFormattedContents()
    {
        $result = $this->contents;

        // if the long description contains a plain HTML <code> element, surround
        // it with a pre element. Please note that we explicitly used str_replace
        // and not preg_replace to gain performance
        if (strpos($result, '<code>') !== false) {
            $result = str_replace(
                array('<code>', "<code>\r\n", "<code>\n", "<code>\r", '</code>'),
                array('<pre><code>', '<code>', '<code>', '<code>', '</code></pre>'),
                $result
            );
        }

        if (class_exists('Parsedown')) {
            $markdown = \Parsedown::instance();
            $result = $markdown->parse($result);
        } elseif (class_exists('dflydev\markdown\MarkdownExtraParser')) {
            $markdown = new \dflydev\markdown\MarkdownExtraParser();
            $result = $markdown->transformMarkdown($result);
        }

        return trim($result);
    }

    /**
     * Gets the docblock this tag belongs to.
     *
     * @return DocBlock The docblock this description belongs to.
     */
    public function getDocBlock()
    {
        return $this->docblock;
    }

    /**
     * Sets the docblock this tag belongs to.
     *
     * @param DocBlock $docblock The new docblock this description belongs to.
     *     Setting NULL removes any association.
     *
     * @return $this
     */
    public function setDocBlock(DocBlock $docblock = null)
    {
        $this->docblock = $docblock;

        return $this;
    }

    /**
     * Builds a string representation of this object.
     *
     * @todo determine the exact format as used by PHP Reflection
     *     and implement it.
     *
     * @return void
     * @codeCoverageIgnore Not yet implemented
     */
    public static function export()
    {
        throw new \Exception('Not yet implemented');
    }

    /**
     * Returns the long description as a string.
     *
     * @return string
     */
    public function __toString()
    {
        return $this->getContents();
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\DocBlock\Type;

use phpDocumentor\Reflection\DocBlock\Context;

/**
 * Collection
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */
class Collection extends \ArrayObject
{
    /** @var string Definition of the OR operator for types */
    const OPERATOR_OR = '|';

    /** @var string Definition of the ARRAY operator for types */
    const OPERATOR_ARRAY = '[]';

    /** @var string Definition of the NAMESPACE operator in PHP */
    const OPERATOR_NAMESPACE = '\\';

    /** @var string[] List of recognized keywords */
    protected static $keywords = array(
        'string', 'int', 'integer', 'bool', 'boolean', 'float', 'double',
        'object', 'mixed', 'array', 'resource', 'void', 'null', 'scalar',
        'callback', 'callable', 'false', 'true', 'self', '$this', 'static'
    );

    /**
     * Current invoking location.
     *
     * This is used to prepend to type with a relative location.
     * May also be 'default' or 'global', in which case they are ignored.
     *
     * @var Context
     */
    protected $context = null;

    /**
     * Registers the namespace and aliases; uses that to add and expand the
     * given types.
     *
     * @param string[] $types    Array containing a list of types to add to this
     *     container.
     * @param Context  $location The current invoking location.
     */
    public function __construct(
        array $types = array(),
        Context $context = null
    ) {
        $this->context = null === $context ? new Context() : $context;

        foreach ($types as $type) {
            $this->add($type);
        }
    }

    /**
     * Returns the current invoking location.
     *
     * @return Context
     */
    public function getContext()
    {
        return $this->context;
    }

    /**
     * Adds a new type to the collection and expands it if it contains a
     * relative namespace.
     *
     * If a class in the type contains a relative namespace than this collection
     * will try to expand that into a FQCN.
     *
     * @param string $type A 'Type' as defined in the phpDocumentor
     *     documentation.
     *
     * @throws \InvalidArgumentException if a non-string argument is passed.
     *
     * @see http://phpdoc.org/docs/latest/for-users/types.html for the
     *     definition of a type.
     *
     * @return void
     */
    public function add($type)
    {
        if (!is_string($type)) {
            throw new \InvalidArgumentException(
                'A type should be represented by a string, received: '
                .var_export($type, true)
            );
        }

        // separate the type by the OR operator
        $type_parts = explode(self::OPERATOR_OR, $type);
        foreach ($type_parts as $part) {
            $expanded_type = $this->expand($part);
            if ($expanded_type) {
                $this[] = $expanded_type;
            }
        }
    }
    
    /**
     * Returns a string representation of the collection.
     * 
     * @return string The resolved types across the collection, separated with
     *     {@link self::OPERATOR_OR}.
     */
    public function __toString()
    {
        return implode(self::OPERATOR_OR, $this->getArrayCopy());
    }

    /**
     * Analyzes the given type and returns the FQCN variant.
     *
     * When a type is provided this method checks whether it is not a keyword or
     * Fully Qualified Class Name. If so it will use the given namespace and
     * aliases to expand the type to a FQCN representation.
     *
     * This method only works as expected if the namespace and aliases are set;
     * no dynamic reflection is being performed here.
     *
     * @param string $type The relative or absolute type.
     *
     * @uses getNamespace to determine with what to prefix the type name.
     * @uses getNamespaceAliases to check whether the first part of the relative
     *     type name should not be replaced with another namespace.
     *
     * @return string
     */
    protected function expand($type)
    {
        $type = trim($type);
        if (!$type) {
            return '';
        }

        if ($this->isTypeAnArray($type)) {
            return $this->expand(substr($type, 0, -2)) . self::OPERATOR_ARRAY;
        }

        if ($this->isRelativeType($type) && !$this->isTypeAKeyword($type)) {
            $type_parts = explode(self::OPERATOR_NAMESPACE, $type, 2);

            $namespace_aliases = $this->context->getNamespaceAliases();
            // if the first segment is not an alias; prepend namespace name and
            // return
            if (!isset($namespace_aliases[$type_parts[0]])) {
                $namespace = $this->context->getNamespace();
                if ('' !== $namespace) {
                    $namespace .= self::OPERATOR_NAMESPACE;
                }
                return self::OPERATOR_NAMESPACE . $namespace . $type;
            }

            $type_parts[0] = $namespace_aliases[$type_parts[0]];
            $type = implode(self::OPERATOR_NAMESPACE, $type_parts);
        }

        return $type;
    }

    /**
     * Detects whether the given type represents an array.
     *
     * @param string $type A relative or absolute type as defined in the
     *     phpDocumentor documentation.
     *
     * @return bool
     */
    protected function isTypeAnArray($type)
    {
        return substr($type, -2) === self::OPERATOR_ARRAY;
    }

    /**
     * Detects whether the given type represents a PHPDoc keyword.
     *
     * @param string $type A relative or absolute type as defined in the
     *     phpDocumentor documentation.
     *
     * @return bool
     */
    protected function isTypeAKeyword($type)
    {
        return in_array(strtolower($type), static::$keywords, true);
    }

    /**
     * Detects whether the given type represents a relative or absolute path.
     *
     * This method will detect keywords as being absolute; even though they are
     * not preceeded by a namespace separator.
     *
     * @param string $type A relative or absolute type as defined in the
     *     phpDocumentor documentation.
     *
     * @return bool
     */
    protected function isRelativeType($type)
    {
        return ($type[0] !== self::OPERATOR_NAMESPACE)
            || $this->isTypeAKeyword($type);
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Vasil Rangelov <boen.robot@gmail.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\DocBlock;

/**
 * The location a DocBlock occurs within a file.
 *
 * @author  Vasil Rangelov <boen.robot@gmail.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class Location
{
    /** @var int Line where the DocBlock text starts. */
    protected $lineNumber = 0;

    /** @var int Column where the DocBlock text starts. */
    protected $columnNumber = 0;
    
    public function __construct(
        $lineNumber = 0,
        $columnNumber = 0
    ) {
        $this->setLineNumber($lineNumber)->setColumnNumber($columnNumber);
    }

    /**
     * @return int Line where the DocBlock text starts.
     */
    public function getLineNumber()
    {
        return $this->lineNumber;
    }

    /**
     * 
     * @param type $lineNumber
     * @return $this
     */
    public function setLineNumber($lineNumber)
    {
        $this->lineNumber = (int)$lineNumber;

        return $this;
    }

    /**
     * @return int Column where the DocBlock text starts.
     */
    public function getColumnNumber()
    {
        return $this->columnNumber;
    }

    /**
     * 
     * @param int $columnNumber
     * @return $this
     */
    public function setColumnNumber($columnNumber)
    {
        $this->columnNumber = (int)$columnNumber;

        return $this;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\DocBlock\Tag;

/**
 * Reflection class for a @covers tag in a Docblock.
 *
 * @author  Mike van Riel <mike.vanriel@naenius.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class CoversTag extends SeeTag
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\DocBlock\Tag;

use phpDocumentor\Reflection\DocBlock\Tag;

/**
 * Reflection class for a @param tag in a Docblock.
 *
 * @author  Mike van Riel <mike.vanriel@naenius.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class ParamTag extends ReturnTag
{
    /**
     * @var string
     */
    protected $variableName = '';

    /**
     * {@inheritdoc}
     */
    public function getContent()
    {
        if (null === $this->content) {
            $this->content
                = "{$this->type} {$this->variableName} {$this->description}";
        }
        return $this->content;
    }
    /**
     * {@inheritdoc}
     */
    public function setContent($content)
    {
        Tag::setContent($content);
        $parts = preg_split(
            '/(\s+)/Su',
            $this->description,
            3,
            PREG_SPLIT_DELIM_CAPTURE
        );

        // if the first item that is encountered is not a variable; it is a type
        if (isset($parts[0])
            && (strlen($parts[0]) > 0)
            && ($parts[0][0] !== '$')
        ) {
            $this->type = array_shift($parts);
            array_shift($parts);
        }

        // if the next item starts with a $ it must be the variable name
        if (isset($parts[0])
            && (strlen($parts[0]) > 0)
            && ($parts[0][0] == '$')
        ) {
            $this->variableName = array_shift($parts);
            array_shift($parts);
        }

        $this->setDescription(implode('', $parts));

        $this->content = $content;
        return $this;
    }

    /**
     * Returns the variable's name.
     *
     * @return string
     */
    public function getVariableName()
    {
        return $this->variableName;
    }

    /**
     * Sets the variable's name.
     *
     * @param string $name The new name for this variable.
     *
     * @return $this
     */
    public function setVariableName($name)
    {
        $this->variableName = $name;

        $this->content = null;
        return $this;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\DocBlock\Tag;

/**
 * Reflection class for a @property tag in a Docblock.
 *
 * @author  Mike van Riel <mike.vanriel@naenius.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class PropertyTag extends ParamTag
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\DocBlock\Tag;

use phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Reflection\DocBlock\Type\Collection;

/**
 * Reflection class for a @return tag in a Docblock.
 *
 * @author  Mike van Riel <mike.vanriel@naenius.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class ReturnTag extends Tag
{
    /** @var string The raw type component. */
    protected $type = '';
    
    /** @var Collection The parsed type component. */
    protected $types = null;

    /**
     * {@inheritdoc}
     */
    public function getContent()
    {
        if (null === $this->content) {
            $this->content = "{$this->type} {$this->description}";
        }

        return $this->content;
    }

    /**
     * {@inheritdoc}
     */
    public function setContent($content)
    {
        parent::setContent($content);

        $parts = preg_split('/\s+/Su', $this->description, 2);

        // any output is considered a type
        $this->type = $parts[0];
        $this->types = null;

        $this->setDescription(isset($parts[1]) ? $parts[1] : '');

        $this->content = $content;
        return $this;
    }

    /**
     * Returns the unique types of the variable.
     *
     * @return string[]
     */
    public function getTypes()
    {
        return $this->getTypesCollection()->getArrayCopy();
    }

    /**
     * Returns the type section of the variable.
     *
     * @return string
     */
    public function getType()
    {
        return (string) $this->getTypesCollection();
    }

    /**
     * Returns the type collection.
     * 
     * @return void
     */
    protected function getTypesCollection()
    {
        if (null === $this->types) {
            $this->types = new Collection(
                array($this->type),
                $this->docblock ? $this->docblock->getContext() : null
            );
        }
        return $this->types;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Vasil Rangelov <boen.robot@gmail.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\DocBlock\Tag;

use phpDocumentor\Reflection\DocBlock\Tag\VersionTag;

/**
 * Reflection class for a @deprecated tag in a Docblock.
 *
 * @author  Vasil Rangelov <boen.robot@gmail.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class DeprecatedTag extends VersionTag
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\DocBlock\Tag;

use phpDocumentor\Reflection\DocBlock\Tag;

/**
 * Reflection class for a @see tag in a Docblock.
 *
 * @author  Mike van Riel <mike.vanriel@naenius.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class SeeTag extends Tag
{
    /** @var string */
    protected $refers = null;

    /**
     * {@inheritdoc}
     */
    public function getContent()
    {
        if (null === $this->content) {
            $this->content = "{$this->refers} {$this->description}";
        }
        return $this->content;
    }

    /**
     * {@inheritdoc}
     */
    public function setContent($content)
    {
        parent::setContent($content);
        $parts = preg_split('/\s+/Su', $this->description, 2);

        // any output is considered a type
        $this->refers = $parts[0];

        $this->setDescription(isset($parts[1]) ? $parts[1] : '');

        $this->content = $content;
        return $this;
    }

    /**
     * Gets the structural element this tag refers to.
     *
     * @return string
     */
    public function getReference()
    {
        return $this->refers;
    }

    /**
     * Sets the structural element this tag refers to.
     * 
     * @param string $refers The new type this tag refers to.
     * 
     * @return $this
     */
    public function setReference($refers)
    {
        $this->refers = $refers;

        $this->content = null;
        return $this;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\DocBlock\Tag;

/**
 * Reflection class for a @uses tag in a Docblock.
 *
 * @author  Mike van Riel <mike.vanriel@naenius.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class UsesTag extends SeeTag
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Vasil Rangelov <boen.robot@gmail.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\DocBlock\Tag;

use phpDocumentor\Reflection\DocBlock\Tag;

/**
 * Reflection class for a @source tag in a Docblock.
 *
 * @author  Vasil Rangelov <boen.robot@gmail.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class SourceTag extends Tag
{
    /**
     * @var int The starting line, relative to the structural element's
     *     location.
     */
    protected $startingLine = 1;

    /** 
     * @var int|null The number of lines, relative to the starting line. NULL
     *     means "to the end".
     */
    protected $lineCount = null;

    /**
     * {@inheritdoc}
     */
    public function getContent()
    {
        if (null === $this->content) {
            $this->content
                = "{$this->startingLine} {$this->lineCount} {$this->description}";
        }

        return $this->content;
    }

    /**
     * {@inheritdoc}
     */
    public function setContent($content)
    {
        parent::setContent($content);
        if (preg_match(
            '/^
                # Starting line
                ([1-9]\d*)
                \s*
                # Number of lines
                (?:
                    ((?1))
                    \s+
                )?
                # Description
                (.*)
            $/sux',
            $this->description,
            $matches
        )) {
            $this->startingLine = (int)$matches[1];
            if (isset($matches[2]) && '' !== $matches[2]) {
                $this->lineCount = (int)$matches[2];
            }
            $this->setDescription($matches[3]);
            $this->content = $content;
        }

        return $this;
    }

    /**
     * Gets the starting line.
     *
     * @return int The starting line, relative to the structural element's
     *     location.
     */
    public function getStartingLine()
    {
        return $this->startingLine;
    }

    /**
     * Sets the starting line.
     * 
     * @param int $startingLine The new starting line, relative to the
     *     structural element's location.
     * 
     * @return $this
     */
    public function setStartingLine($startingLine)
    {
        $this->startingLine = $startingLine;

        $this->content = null;
        return $this;
    }

    /**
     * Returns the number of lines.
     *
     * @return int|null The number of lines, relative to the starting line. NULL
     *     means "to the end".
     */
    public function getLineCount()
    {
        return $this->lineCount;
    }

    /**
     * Sets the number of lines.
     * 
     * @param int|null $lineCount The new number of lines, relative to the
     *     starting line. NULL means "to the end".
     * 
     * @return $this
     */
    public function setLineCount($lineCount)
    {
        $this->lineCount = $lineCount;

        $this->content = null;
        return $this;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Vasil Rangelov <boen.robot@gmail.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\DocBlock\Tag;

use phpDocumentor\Reflection\DocBlock\Tag;

/**
 * Reflection class for an @author tag in a Docblock.
 *
 * @author  Mike van Riel <mike.vanriel@naenius.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class AuthorTag extends Tag
{
    /**
     * PCRE regular expression matching any valid value for the name component.
     */
    const REGEX_AUTHOR_NAME = '[^\<]*';

    /**
     * PCRE regular expression matching any valid value for the email component.
     */
    const REGEX_AUTHOR_EMAIL = '[^\>]*';

    /** @var string The name of the author */
    protected $authorName = '';

    /** @var string The email of the author */
    protected $authorEmail = '';
    
    public function getContent()
    {
        if (null === $this->content) {
            $this->content = $this->authorName;
            if ('' != $this->authorEmail) {
                $this->content .= "<{$this->authorEmail}>";
            }
        }

        return $this->content;
    }

    /**
     * {@inheritdoc}
     */
    public function setContent($content)
    {
        parent::setContent($content);
        if (preg_match(
            '/^(' . self::REGEX_AUTHOR_NAME .
            ')(\<(' . self::REGEX_AUTHOR_EMAIL .
            ')\>)?$/u',
            $this->description,
            $matches
        )) {
            $this->authorName = trim($matches[1]);
            if (isset($matches[3])) {
                $this->authorEmail = trim($matches[3]);
            }
        }

        return $this;
    }

    /**
     * Gets the author's name.
     * 
     * @return string The author's name.
     */
    public function getAuthorName()
    {
        return $this->authorName;
    }
    
    /**
     * Sets the author's name.
     * 
     * @param string $authorName The new author name.
     *     An invalid value will set an empty string.
     * 
     * @return $this
     */
    public function setAuthorName($authorName)
    {
        $this->content = null;
        $this->authorName
            = preg_match('/^' . self::REGEX_AUTHOR_NAME . '$/u', $authorName)
            ? $authorName : '';

        return $this;
    }

    /**
     * Gets the author's email.
     * 
     * @return string The author's email.
     */
    public function getAuthorEmail()
    {
        return $this->authorEmail;
    }
    
    /**
     * Sets the author's email.
     * 
     * @param string $authorEmail The new author email.
     *     An invalid value will set an empty string.
     * 
     * @return $this
     */
    public function setAuthorEmail($authorEmail)
    {
        $this->authorEmail
            = preg_match('/^' . self::REGEX_AUTHOR_EMAIL . '$/u', $authorEmail)
            ? $authorEmail : '';

        $this->content = null;
        return $this;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\DocBlock\Tag;

/**
 * Reflection class for a @property-read tag in a Docblock.
 *
 * @author  Mike van Riel <mike.vanriel@naenius.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class PropertyReadTag extends PropertyTag
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\DocBlock\Tag;

/**
 * Reflection class for a @throws tag in a Docblock.
 *
 * @author  Mike van Riel <mike.vanriel@naenius.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class ThrowsTag extends ReturnTag
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Vasil Rangelov <boen.robot@gmail.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\DocBlock\Tag;

use phpDocumentor\Reflection\DocBlock\Tag;

/**
 * Reflection class for a @example tag in a Docblock.
 *
 * @author  Vasil Rangelov <boen.robot@gmail.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class ExampleTag extends SourceTag
{
    /** 
     * @var string Path to a file to use as an example.
     *     May also be an absolute URI.
     */
    protected $filePath = '';

    /**
     * @var bool Whether the file path component represents an URI.
     *     This determines how the file portion appears at {@link getContent()}.
     */
    protected $isURI = false;

    /**
     * {@inheritdoc}
     */
    public function getContent()
    {
        if (null === $this->content) {
            $filePath = '';
            if ($this->isURI) {
                if (false === strpos($this->filePath, ':')) {
                    $filePath = str_replace(
                        '%2F',
                        '/',
                        rawurlencode($this->filePath)
                    );
                } else {
                    $filePath = $this->filePath;
                }
            } else {
                $filePath = '"' . $this->filePath . '"';
            }

            $this->content = $filePath . ' ' . $this->getContent();
        }

        return $this->content;
    }
    /**
     * {@inheritdoc}
     */
    public function setContent($content)
    {
        Tag::setContent($content);
        if (preg_match(
            '/^
                # File component
                (?:
                    # File path in quotes
                    \"([^\"]+)\"
                    |
                    # File URI
                    (\S+)
                )
                # Remaining content (parsed by SourceTag)
                (?:\s+(.*))?
            $/sux',
            $this->description,
            $matches
        )) {
            if ('' !== $matches[1]) {
                $this->setFilePath($matches[1]);
            } else {
                $this->setFileURI($matches[2]);
            }

            if (isset($matches[3])) {
                parent::setContent($matches[3]);
            } else {
                $this->setDescription('');
            }
            $this->content = $content;
        }

        return $this;
    }

    /**
     * Returns the file path.
     *
     * @return string Path to a file to use as an example.
     *     May also be an absolute URI.
     */
    public function getFilePath()
    {
        return $this->filePath;
    }
    
    /**
     * Sets the file path.
     * 
     * @param string $filePath The new file path to use for the example.
     * 
     * @return $this
     */
    public function setFilePath($filePath)
    {
        $this->isURI = false;
        $this->filePath = trim($filePath);

        $this->content = null;
        return $this;
    }
    
    /**
     * Sets the file path as an URI.
     * 
     * This function is equivalent to {@link setFilePath()}, except that it
     * convers an URI to a file path before that.
     * 
     * There is no getFileURI(), as {@link getFilePath()} is compatible.
     * 
     * @param type $uri The new file URI to use as an example.
     */
    public function setFileURI($uri)
    {
        $this->isURI = true;
        if (false === strpos($uri, ':')) {
            //Relative URL
            $this->filePath = rawurldecode(
                str_replace(array('/', '\\'), '%2F', $uri)
            );
        } else {
            //Absolute URL or URI.
            $this->filePath = $uri;
        }

        $this->content = null;
        return $this;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Ben Selby <benmatselby@gmail.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\DocBlock\Tag;

use phpDocumentor\Reflection\DocBlock\Tag;

/**
 * Reflection class for a @link tag in a Docblock.
 *
 * @author  Ben Selby <benmatselby@gmail.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class LinkTag extends Tag
{
    /** @var string */
    protected $link = '';

    /**
     * {@inheritdoc}
     */
    public function getContent()
    {
        if (null === $this->content) {
            $this->content = "{$this->link} {$this->description}";
        }

        return $this->content;
    }

    /**
     * {@inheritdoc}
     */
    public function setContent($content)
    {
        parent::setContent($content);
        $parts = preg_split('/\s+/Su', $this->description, 2);

        $this->link = $parts[0];

        $this->setDescription(isset($parts[1]) ? $parts[1] : $parts[0]);

        $this->content = $content;
        return $this;
    }

    /**
    * Gets the link
    *
    * @return string
    */
    public function getLink()
    {
        return $this->link;
    }

    /**
    * Sets the link
    *
    * @param string $link The link
    *
    * @return $this
    */
    public function setLink($link)
    {
        $this->link = $link;

        $this->content = null;
        return $this;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\DocBlock\Tag;

use phpDocumentor\Reflection\DocBlock\Tag;

/**
 * Reflection class for a @method in a Docblock.
 *
 * @author  Mike van Riel <mike.vanriel@naenius.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class MethodTag extends ReturnTag
{

    /** @var string */
    protected $method_name = '';

    /** @var string */
    protected $arguments = '';
    
    /** @var bool */
    protected $isStatic = false;

    /**
     * {@inheritdoc}
     */
    public function getContent()
    {
        if (null === $this->content) {
            $this->content = '';
            if ($this->isStatic) {
                $this->content .= 'static ';
            }
            $this->content .= $this->type .
                " {$this->method_name}({$this->arguments}) " .
                $this->description;
        }

        return $this->content;
    }

    /**
     * {@inheritdoc}
     */
    public function setContent($content)
    {
        Tag::setContent($content);
        // 1. none or more whitespace
        // 2. optionally the keyword "static" followed by whitespace
        // 3. optionally a word with underscores followed by whitespace : as
        //    type for the return value
        // 4. then optionally a word with underscores followed by () and
        //    whitespace : as method name as used by phpDocumentor
        // 5. then a word with underscores, followed by ( and any character
        //    until a ) and whitespace : as method name with signature
        // 6. any remaining text : as description
        if (preg_match(
            '/^
                # Static keyword
                # Declates a static method ONLY if type is also present
                (?:
                    (static)
                    \s+
                )?
                # Return type
                (?:
                    ([\w\|_\\\\]+)
                    \s+
                )?
                # Legacy method name (not captured)
                (?:
                    [\w_]+\(\)\s+
                )?
                # Method name
                ([\w\|_\\\\]+)
                # Arguments
                \(([^\)]*)\)
                \s*
                # Description
                (.*)
            $/sux',
            $this->description,
            $matches
        )) {
            list(
                ,
                $static,
                $this->type,
                $this->method_name,
                $this->arguments,
                $this->description
            ) = $matches;
            if ($static) {
                if (!$this->type) {
                    $this->type = 'static';
                } else {
                    $this->isStatic = true;
                }
            } else {
                if (!$this->type) {
                    $this->type = 'void';
                }
            }
            $this->parsedDescription = null;
        } else {
            echo date('c') . ' ERR (3): @method contained invalid contents: '
                . $this->content . PHP_EOL;
        }

        return $this;
    }

    /**
     * Sets the name of this method.
     *
     * @param string $method_name The name of the method.
     *
     * @return $this
     */
    public function setMethodName($method_name)
    {
        $this->method_name = $method_name;

        $this->content = null;
        return $this;
    }

    /**
     * Retrieves the method name.
     *
     * @return string
     */
    public function getMethodName()
    {
        return $this->method_name;
    }

    /**
     * Sets the arguments for this method.
     *
     * @param string $arguments A comma-separated arguments line.
     *
     * @return void
     */
    public function setArguments($arguments)
    {
        $this->arguments = $arguments;

        $this->content = null;
        return $this;
    }

    /**
     * Returns an array containing each argument as array of type and name.
     *
     * Please note that the argument sub-array may only contain 1 element if no
     * type was specified.
     *
     * @return string[]
     */
    public function getArguments()
    {
        if (empty($this->arguments)) {
            return array();
        }

        $arguments = explode(',', $this->arguments);
        foreach ($arguments as $key => $value) {
            $arguments[$key] = explode(' ', trim($value));
        }

        return $arguments;
    }
    
    /**
     * Checks whether the method tag describes a static method or not.
     * 
     * @return bool TRUE if the method declaration is for a static method, FALSE
     *     otherwise.
     */
    public function isStatic()
    {
        return $this->isStatic;
    }
    
    /**
     * Sets a new value for whether the method is static or not.
     * 
     * @param bool $isStatic The new value to set.
     * 
     * @return $this
     */
    public function setIsStatic($isStatic)
    {
        $this->isStatic = $isStatic;

        $this->content = null;
        return $this;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\DocBlock\Tag;

/**
 * Reflection class for a @property-write tag in a Docblock.
 *
 * @author  Mike van Riel <mike.vanriel@naenius.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class PropertyWriteTag extends PropertyTag
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Vasil Rangelov <boen.robot@gmail.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\DocBlock\Tag;

use phpDocumentor\Reflection\DocBlock\Tag\VersionTag;

/**
 * Reflection class for a @since tag in a Docblock.
 *
 * @author  Vasil Rangelov <boen.robot@gmail.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class SinceTag extends VersionTag
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Vasil Rangelov <boen.robot@gmail.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\DocBlock\Tag;

use phpDocumentor\Reflection\DocBlock\Tag;

/**
 * Reflection class for a @version tag in a Docblock.
 *
 * @author  Vasil Rangelov <boen.robot@gmail.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class VersionTag extends Tag
{
    /**
     * PCRE regular expression matching a version vector.
     * Assumes the "x" modifier.
     */
    const REGEX_VECTOR = '(?:
        # Normal release vectors.
        \d\S*
        |
        # VCS version vectors. Per PHPCS, they are expected to
        # follow the form of the VCS name, followed by ":", followed
        # by the version vector itself.
        # By convention, popular VCSes like CVS, SVN and GIT use "$"
        # around the actual version vector.
        [^\s\:]+\:\s*\$[^\$]+\$
    )';

    /** @var string The version vector. */
    protected $version = '';
    
    public function getContent()
    {
        if (null === $this->content) {
            $this->content = "{$this->version} {$this->description}";
        }

        return $this->content;
    }

    /**
     * {@inheritdoc}
     */
    public function setContent($content)
    {
        parent::setContent($content);

        if (preg_match(
            '/^
                # The version vector
                (' . self::REGEX_VECTOR . ')
                \s*
                # The description
                (.+)?
            $/sux',
            $this->description,
            $matches
        )) {
            $this->version = $matches[1];
            $this->setDescription(isset($matches[2]) ? $matches[2] : '');
            $this->content = $content;
        }

        return $this;
    }

    /**
     * Gets the version section of the tag.
     *
     * @return string The version section of the tag.
     */
    public function getVersion()
    {
        return $this->version;
    }
    
    /**
     * Sets the version section of the tag.
     * 
     * @param string $version The new version section of the tag.
     *     An invalid value will set an empty string.
     * 
     * @return $this
     */
    public function setVersion($version)
    {
        $this->version
            = preg_match('/^' . self::REGEX_VECTOR . '$/ux', $version)
            ? $version
            : '';

        $this->content = null;
        return $this;
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\DocBlock\Tag;

/**
 * Reflection class for a @var tag in a Docblock.
 *
 * @author  Mike van Riel <mike.vanriel@naenius.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class VarTag extends ParamTag
{
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection\DocBlock;

use phpDocumentor\Reflection\DocBlock;

/**
 * Parses a tag definition for a DocBlock.
 *
 * @author  Mike van Riel <mike.vanriel@naenius.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class Tag implements \Reflector
{
    /**
     * PCRE regular expression matching a tag name.
     */
    const REGEX_TAGNAME = '[\w\-\_\\\\]+';

    /** @var string Name of the tag */
    protected $tag = '';

    /**
     * @var string|null Content of the tag.
     *     When set to NULL, it means it needs to be regenerated.
     */
    protected $content = '';

    /** @var string Description of the content of this tag */
    protected $description = '';

    /**
     * @var array|null The description, as an array of strings and Tag objects.
     *     When set to NULL, it means it needs to be regenerated.
     */
    protected $parsedDescription = null;

    /** @var Location Location of the tag. */
    protected $location = null;

    /** @var DocBlock The DocBlock which this tag belongs to. */
    protected $docblock = null;
    
    /**
     * @var array An array with a tag as a key, and an FQCN to a class that
     *     handles it as an array value. The class is expected to inherit this
     *     class.
     */
    private static $tagHandlerMappings = array(
        'author'
            => '\phpDocumentor\Reflection\DocBlock\Tag\AuthorTag',
        'covers'
            => '\phpDocumentor\Reflection\DocBlock\Tag\CoversTag',
        'deprecated'
            => '\phpDocumentor\Reflection\DocBlock\Tag\DeprecatedTag',
        'example'
            => '\phpDocumentor\Reflection\DocBlock\Tag\ExampleTag',
        'link'
            => '\phpDocumentor\Reflection\DocBlock\Tag\LinkTag',
        'method'
            => '\phpDocumentor\Reflection\DocBlock\Tag\MethodTag',
        'param'
            => '\phpDocumentor\Reflection\DocBlock\Tag\ParamTag',
        'property-read'
            => '\phpDocumentor\Reflection\DocBlock\Tag\PropertyReadTag',
        'property'
            => '\phpDocumentor\Reflection\DocBlock\Tag\PropertyTag',
        'property-write'
            => '\phpDocumentor\Reflection\DocBlock\Tag\PropertyWriteTag',
        'return'
            => '\phpDocumentor\Reflection\DocBlock\Tag\ReturnTag',
        'see'
            => '\phpDocumentor\Reflection\DocBlock\Tag\SeeTag',
        'since'
            => '\phpDocumentor\Reflection\DocBlock\Tag\SinceTag',
        'source'
            => '\phpDocumentor\Reflection\DocBlock\Tag\SourceTag',
        'throw'
            => '\phpDocumentor\Reflection\DocBlock\Tag\ThrowsTag',
        'throws'
            => '\phpDocumentor\Reflection\DocBlock\Tag\ThrowsTag',
        'uses'
            => '\phpDocumentor\Reflection\DocBlock\Tag\UsesTag',
        'var'
            => '\phpDocumentor\Reflection\DocBlock\Tag\VarTag',
        'version'
            => '\phpDocumentor\Reflection\DocBlock\Tag\VersionTag'
    );

    /**
     * Factory method responsible for instantiating the correct sub type.
     *
     * @param string   $tag_line The text for this tag, including description.
     * @param DocBlock $docblock The DocBlock which this tag belongs to.
     * @param Location $location Location of the tag.
     *
     * @throws \InvalidArgumentException if an invalid tag line was presented.
     *
     * @return static A new tag object.
     */
    final public static function createInstance(
        $tag_line,
        DocBlock $docblock = null,
        Location $location = null
    ) {
        if (!preg_match(
            '/^@(' . self::REGEX_TAGNAME . ')(?:\s*([^\s].*)|$)?/us',
            $tag_line,
            $matches
        )) {
            throw new \InvalidArgumentException(
                'Invalid tag_line detected: ' . $tag_line
            );
        }

        $handler = __CLASS__;
        if (isset(self::$tagHandlerMappings[$matches[1]])) {
            $handler = self::$tagHandlerMappings[$matches[1]];
        } elseif (isset($docblock)) {
            $tagName = (string)new Type\Collection(
                array($matches[1]),
                $docblock->getContext()
            );

            if (isset(self::$tagHandlerMappings[$tagName])) {
                $handler = self::$tagHandlerMappings[$tagName];
            }
        }

        return new $handler(
            $matches[1],
            isset($matches[2]) ? $matches[2] : '',
            $docblock,
            $location
        );
    }

    /**
     * Registers a handler for tags.
     * 
     * Registers a handler for tags. The class specified is autoloaded if it's
     * not available. It must inherit from this class.
     * 
     * @param string      $tag     Name of tag to regiser a handler for. When
     *     registering a namespaced tag, the full name, along with a prefixing
     *     slash MUST be provided.
     * @param string|null $handler FQCN of handler. Specifing NULL removes the
     *     handler for the specified tag, if any.
     * 
     * @return bool TRUE on success, FALSE on failure.
     */
    final public static function registerTagHandler($tag, $handler)
    {
        $tag = trim((string)$tag);

        if (null === $handler) {
            unset(self::$tagHandlerMappings[$tag]);
            return true;
        }

        if ('' !== $tag
            && class_exists($handler, true)
            && is_subclass_of($handler, __CLASS__)
            && !strpos($tag, '\\') //Accept no slash, and 1st slash at offset 0.
        ) {
            self::$tagHandlerMappings[$tag] = $handler;
            return true;
        }

        return false;
    }

    /**
     * Parses a tag and populates the member variables.
     *
     * @param string   $name     Name of the tag.
     * @param string   $content  The contents of the given tag.
     * @param DocBlock $docblock The DocBlock which this tag belongs to.
     * @param Location $location Location of the tag.
     */
    public function __construct(
        $name,
        $content,
        DocBlock $docblock = null,
        Location $location = null
    ) {
        $this
            ->setName($name)
            ->setContent($content)
            ->setDocBlock($docblock)
            ->setLocation($location);
    }

    /**
     * Gets the name of this tag.
     *
     * @return string The name of this tag.
     */
    public function getName()
    {
        return $this->tag;
    }

    /**
     * Sets the name of this tag.
     * 
     * @param string $name The new name of this tag.
     * 
     * @return $this
     * @throws \InvalidArgumentException When an invalid tag name is provided.
     */
    public function setName($name)
    {
        if (!preg_match('/^' . self::REGEX_TAGNAME . '$/u', $name)) {
            throw new \InvalidArgumentException(
                'Invalid tag name supplied: ' . $name
            );
        }

        $this->tag = $name;

        return $this;
    }

    /**
     * Gets the content of this tag.
     *
     * @return string
     */
    public function getContent()
    {
        if (null === $this->content) {
            $this->content = $this->description;
        }

        return $this->content;
    }

    /**
     * Sets the content of this tag.
     * 
     * @param string $content The new content of this tag.
     * 
     * @return $this
     */
    public function setContent($content)
    {
        $this->setDescription($content);
        $this->content = $content;

        return $this;
    }

    /**
     * Gets the description component of this tag.
     *
     * @return string
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     * Sets the description component of this tag.
     * 
     * @param string $description The new description component of this tag.
     * 
     * @return $this
     */
    public function setDescription($description)
    {
        $this->content = null;
        $this->parsedDescription = null;
        $this->description = trim($description);

        return $this;
    }

    /**
     * Gets the parsed text of this description.
     * 
     * @return array An array of strings and tag objects, in the order they
     *     occur within the description.
     */
    public function getParsedDescription()
    {
        if (null === $this->parsedDescription) {
            $description = new Description($this->description, $this->docblock);
            $this->parsedDescription = $description->getParsedContents();
        }
        return $this->parsedDescription;
    }

    /**
     * Gets the docblock this tag belongs to.
     * 
     * @return DocBlock The docblock this tag belongs to.
     */
    public function getDocBlock()
    {
        return $this->docblock;
    }

    /**
     * Sets the docblock this tag belongs to.
     * 
     * @param DocBlock $docblock The new docblock this tag belongs to. Setting
     *     NULL removes any association.
     * 
     * @return $this
     */
    public function setDocBlock(DocBlock $docblock = null)
    {
        $this->docblock = $docblock;

        return $this;
    }

    /**
     * Gets the location of the tag.
     *
     * @return Location The tag's location.
     */
    public function getLocation()
    {
        return $this->location;
    }
    
    /**
     * Sets the location of the tag.
     * 
     * @param Location $location The new location of the tag.
     * 
     * @return $this
     */
    public function setLocation(Location $location = null)
    {
        $this->location = $location;

        return $this;
    }

    /**
     * Builds a string representation of this object.
     *
     * @todo determine the exact format as used by PHP Reflection and implement it.
     *
     * @return void
     * @codeCoverageIgnore Not yet implemented
     */
    public static function export()
    {
        throw new \Exception('Not yet implemented');
    }

    /**
     * Returns the tag as a serialized string
     *
     * @return string
     */
    public function __toString()
    {
        return "@{$this->getName()} {$this->getContent()}";
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5.3
 *
 * @author    Mike van Riel <mike.vanriel@naenius.com>
 * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Reflection;

use phpDocumentor\Reflection\DocBlock\Tag;
use phpDocumentor\Reflection\DocBlock\Context;
use phpDocumentor\Reflection\DocBlock\Location;

/**
 * Parses the DocBlock for any structure.
 *
 * @author  Mike van Riel <mike.vanriel@naenius.com>
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link    http://phpdoc.org
 */
class DocBlock implements \Reflector
{
    /** @var string The opening line for this docblock. */
    protected $short_description = '';

    /**
     * @var DocBlock\Description The actual
     *     description for this docblock.
     */
    protected $long_description = null;

    /**
     * @var Tag[] An array containing all
     *     the tags in this docblock; except inline.
     */
    protected $tags = array();

    /** @var Context Information about the context of this DocBlock. */
    protected $context = null;

    /** @var Location Information about the location of this DocBlock. */
    protected $location = null;

    /**
     * Parses the given docblock and populates the member fields.
     *
     * The constructor may also receive namespace information such as the
     * current namespace and aliases. This information is used by some tags
     * (e.g. @return, @param, etc.) to turn a relative Type into a FQCN.
     *
     * @param \Reflector|string $docblock A docblock comment (including
     *     asterisks) or reflector supporting the getDocComment method.
     * @param Context           $context  The context in which the DocBlock
     *     occurs.
     * @param Location          $location The location within the file that this
     *     DocBlock occurs in.
     *
     * @throws \InvalidArgumentException if the given argument does not have the
     *     getDocComment method.
     */
    public function __construct(
        $docblock,
        Context $context = null,
        Location $location = null
    ) {
        if (is_object($docblock)) {
            if (!method_exists($docblock, 'getDocComment')) {
                throw new \InvalidArgumentException(
                    'Invalid object passed; the given reflector must support '
                    . 'the getDocComment method'
                );
            }

            $docblock = $docblock->getDocComment();
        }

        $docblock = $this->cleanInput($docblock);

        list($short, $long, $tags) = $this->splitDocBlock($docblock);
        $this->short_description = $short;
        $this->long_description = new DocBlock\Description($long, $this);
        $this->parseTags($tags);

        $this->context  = $context;
        $this->location = $location;
    }

    /**
     * Strips the asterisks from the DocBlock comment.
     *
     * @param string $comment String containing the comment text.
     *
     * @return string
     */
    protected function cleanInput($comment)
    {
        $comment = trim(
            preg_replace(
                '#[ \t]*(?:\/\*\*|\*\/|\*)?[ \t]{0,1}(.*)?#u',
                '$1',
                $comment
            )
        );

        // reg ex above is not able to remove */ from a single line docblock
        if (substr($comment, -2) == '*/') {
            $comment = trim(substr($comment, 0, -2));
        }

        // normalize strings
        $comment = str_replace(array("\r\n", "\r"), "\n", $comment);

        return $comment;
    }

    /**
     * Splits the DocBlock into a short description, long description and
     * block of tags.
     *
     * @param string $comment Comment to split into the sub-parts.
     *
     * @author RichardJ Special thanks to RichardJ for the regex responsible
     *     for the split.
     *
     * @return string[] containing the short-, long description and an element
     *     containing the tags.
     */
    protected function splitDocBlock($comment)
    {
        if (strpos($comment, '@') === 0) {
            $matches = array('', '', $comment);
        } else {
            // clears all extra horizontal whitespace from the line endings
            // to prevent parsing issues
            $comment = preg_replace('/\h*$/Sum', '', $comment);

            /*
             * Splits the docblock into a short description, long description and
             * tags section
             * - The short description is started from the first character until
             *   a dot is encountered followed by a newline OR
             *   two consecutive newlines (horizontal whitespace is taken into
             *   account to consider spacing errors)
             * - The long description, any character until a new line is
             *   encountered followed by an @ and word characters (a tag).
             *   This is optional.
             * - Tags; the remaining characters
             *
             * Big thanks to RichardJ for contributing this Regular Expression
             */
            preg_match(
                '/
        \A (
          [^\n.]+
          (?:
            (?! \. \n | \n{2} ) # disallow the first seperator here
            [\n.] (?! [ \t]* @\pL ) # disallow second seperator
            [^\n.]+
          )*
          \.?
        )
        (?:
          \s* # first seperator (actually newlines but it\'s all whitespace)
          (?! @\pL ) # disallow the rest, to make sure this one doesn\'t match,
          #if it doesn\'t exist
          (
            [^\n]+
            (?: \n+
              (?! [ \t]* @\pL ) # disallow second seperator (@param)
              [^\n]+
            )*
          )
        )?
        (\s+ [\s\S]*)? # everything that follows
        /ux',
                $comment,
                $matches
            );
            array_shift($matches);
        }

        while (count($matches) < 3) {
            $matches[] = '';
        }
        return $matches;
    }

    /**
     * Creates the tag objects.
     *
     * @param string $tags Tag block to parse.
     *
     * @return void
     */
    protected function parseTags($tags)
    {
        $result = array();
        $tags = trim($tags);
        if ('' !== $tags) {
            if ('@' !== $tags[0]) {
                throw new \LogicException(
                    'A tag block started with text instead of an actual tag,'
                    . ' this makes the tag block invalid: ' . $tags
                );
            }
            foreach (explode("\n", $tags) as $tag_line) {
                if (trim($tag_line) === '') {
                    continue;
                }

                if (isset($tag_line[0]) && ($tag_line[0] === '@')) {
                    $result[] = $tag_line;
                } else {
                    $result[count($result) - 1] .= PHP_EOL . $tag_line;
                }
            }

            // create proper Tag objects
            foreach ($result as $key => $tag_line) {
                $result[$key] = Tag::createInstance($tag_line, $this);
            }
        }

        $this->tags = $result;
    }

    /**
     * Gets the text portion of the doc block.
     * 
     * Gets the text portion (short and long description combined) of the doc
     * block.
     * 
     * @return string The text portion of the doc block.
     */
    public function getText()
    {
        $short = $this->getShortDescription();
        $long = $this->getLongDescription()->getContents();

        if ($long) {
            return "{$short}\n\n{$long}";
        } else {
            return $short;
        }
    }

    /**
     * Set the text portion of the doc block.
     * 
     * Sets the text portion (short and long description combined) of the doc
     * block.
     *
     * @param string $docblock The new text portion of the doc block.
     * 
     * @return $this This doc block.
     */
    public function setText($comment)
    {
        list($short, $long) = $this->splitDocBlock($comment);
        $this->short_description = $short;
        $this->long_description = new DocBlock\Description($long, $this);
        return $this;
    }
    /**
     * Returns the opening line or also known as short description.
     *
     * @return string
     */
    public function getShortDescription()
    {
        return $this->short_description;
    }

    /**
     * Returns the full description or also known as long description.
     *
     * @return DocBlock\Description
     */
    public function getLongDescription()
    {
        return $this->long_description;
    }

    /**
     * Returns the current context.
     *
     * @return Context
     */
    public function getContext()
    {
        return $this->context;
    }

    /**
     * Returns the current location.
     *
     * @return Location
     */
    public function getLocation()
    {
        return $this->location;
    }

    /**
     * Returns the tags for this DocBlock.
     *
     * @return Tag[]
     */
    public function getTags()
    {
        return $this->tags;
    }

    /**
     * Returns an array of tags matching the given name. If no tags are found
     * an empty array is returned.
     *
     * @param string $name String to search by.
     *
     * @return Tag[]
     */
    public function getTagsByName($name)
    {
        $result = array();

        /** @var Tag $tag */
        foreach ($this->getTags() as $tag) {
            if ($tag->getName() != $name) {
                continue;
            }

            $result[] = $tag;
        }

        return $result;
    }

    /**
     * Checks if a tag of a certain type is present in this DocBlock.
     *
     * @param string $name Tag name to check for.
     *
     * @return bool
     */
    public function hasTag($name)
    {
        /** @var Tag $tag */
        foreach ($this->getTags() as $tag) {
            if ($tag->getName() == $name) {
                return true;
            }
        }

        return false;
    }

    /**
     * Appends a tag at the end of the list of tags.
     *
     * @param Tag $tag The tag to add.
     *
     * @return Tag The newly added tag.
     *
     * @throws \LogicException When the tag belongs to a different DocBlock.
     */
    public function appendTag(Tag $tag)
    {
        if (null === $tag->getDocBlock()) {
            $tag->setDocBlock($this);
        }

        if ($tag->getDocBlock() === $this) {
            $this->tags[] = $tag;
        } else {
            throw new \LogicException(
                'This tag belongs to a different DocBlock object.'
            );
        }

        return $tag;
    }


    /**
     * Builds a string representation of this object.
     *
     * @todo determine the exact format as used by PHP Reflection and
     *     implement it.
     *
     * @return string
     * @codeCoverageIgnore Not yet implemented
     */
    public static function export()
    {
        throw new \Exception('Not yet implemented');
    }

    /**
     * Returns the exported information (we should use the export static method
     * BUT this throws an exception at this point).
     *
     * @return string
     * @codeCoverageIgnore Not yet implemented
     */
    public function __toString()
    {
        return 'Not yet implemented';
    }
}
{
    "_readme": [
        "This file locks the dependencies of your project to a known state",
        "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
    ],
    "hash": "f55ecb41312789bb8b3fa8b4f659952f",
    "packages": [

    ],
    "packages-dev": [
        {
            "name": "phpunit/php-code-coverage",
            "version": "1.2.13",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
                "reference": "466e7cd2554b4e264c9e3f31216d25ac0e5f3d94"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/466e7cd2554b4e264c9e3f31216d25ac0e5f3d94",
                "reference": "466e7cd2554b4e264c9e3f31216d25ac0e5f3d94",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3",
                "phpunit/php-file-iterator": ">=1.3.0@stable",
                "phpunit/php-text-template": ">=1.1.1@stable",
                "phpunit/php-token-stream": ">=1.1.3@stable"
            },
            "require-dev": {
                "phpunit/phpunit": "3.7.*@dev"
            },
            "suggest": {
                "ext-dom": "*",
                "ext-xdebug": ">=2.0.5"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.2.x-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "PHP/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
            "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
            "keywords": [
                "coverage",
                "testing",
                "xunit"
            ],
            "time": "2013-09-10 08:14:32"
        },
        {
            "name": "phpunit/php-file-iterator",
            "version": "1.3.4",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
                "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb",
                "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "File/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "FilterIterator implementation that filters files based on a list of suffixes.",
            "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
            "keywords": [
                "filesystem",
                "iterator"
            ],
            "time": "2013-10-10 15:34:57"
        },
        {
            "name": "phpunit/php-text-template",
            "version": "1.1.4",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/php-text-template.git",
                "reference": "5180896f51c5b3648ac946b05f9ec02be78a0b23"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5180896f51c5b3648ac946b05f9ec02be78a0b23",
                "reference": "5180896f51c5b3648ac946b05f9ec02be78a0b23",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "Text/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Simple template engine.",
            "homepage": "https://github.com/sebastianbergmann/php-text-template/",
            "keywords": [
                "template"
            ],
            "time": "2012-10-31 18:15:28"
        },
        {
            "name": "phpunit/php-timer",
            "version": "1.0.5",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/php-timer.git",
                "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c",
                "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "PHP/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Utility class for timing",
            "homepage": "https://github.com/sebastianbergmann/php-timer/",
            "keywords": [
                "timer"
            ],
            "time": "2013-08-02 07:42:54"
        },
        {
            "name": "phpunit/php-token-stream",
            "version": "1.2.1",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/php-token-stream.git",
                "reference": "5220af2a7929aa35cf663d97c89ad3d50cf5fa3e"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/5220af2a7929aa35cf663d97c89ad3d50cf5fa3e",
                "reference": "5220af2a7929aa35cf663d97c89ad3d50cf5fa3e",
                "shasum": ""
            },
            "require": {
                "ext-tokenizer": "*",
                "php": ">=5.3.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.2-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "PHP/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Wrapper around PHP's tokenizer extension.",
            "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
            "keywords": [
                "tokenizer"
            ],
            "time": "2013-09-13 04:58:23"
        },
        {
            "name": "phpunit/phpunit",
            "version": "3.7.28",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/phpunit.git",
                "reference": "3b97c8492bcafbabe6b6fbd2ab35f2f04d932a8d"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3b97c8492bcafbabe6b6fbd2ab35f2f04d932a8d",
                "reference": "3b97c8492bcafbabe6b6fbd2ab35f2f04d932a8d",
                "shasum": ""
            },
            "require": {
                "ext-dom": "*",
                "ext-pcre": "*",
                "ext-reflection": "*",
                "ext-spl": "*",
                "php": ">=5.3.3",
                "phpunit/php-code-coverage": "~1.2.1",
                "phpunit/php-file-iterator": ">=1.3.1",
                "phpunit/php-text-template": ">=1.1.1",
                "phpunit/php-timer": ">=1.0.4",
                "phpunit/phpunit-mock-objects": "~1.2.0",
                "symfony/yaml": "~2.0"
            },
            "require-dev": {
                "pear-pear/pear": "1.9.4"
            },
            "suggest": {
                "ext-json": "*",
                "ext-simplexml": "*",
                "ext-tokenizer": "*",
                "phpunit/php-invoker": ">=1.1.0,<1.2.0"
            },
            "bin": [
                "composer/bin/phpunit"
            ],
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "3.7.x-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "PHPUnit/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                "",
                "../../symfony/yaml/"
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de",
                    "role": "lead"
                }
            ],
            "description": "The PHP Unit Testing framework.",
            "homepage": "http://www.phpunit.de/",
            "keywords": [
                "phpunit",
                "testing",
                "xunit"
            ],
            "time": "2013-10-17 07:27:40"
        },
        {
            "name": "phpunit/phpunit-mock-objects",
            "version": "1.2.3",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
                "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/5794e3c5c5ba0fb037b11d8151add2a07fa82875",
                "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3",
                "phpunit/php-text-template": ">=1.1.1@stable"
            },
            "suggest": {
                "ext-soap": "*"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "PHPUnit/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Mock Object library for PHPUnit",
            "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
            "keywords": [
                "mock",
                "xunit"
            ],
            "time": "2013-01-13 10:24:48"
        },
        {
            "name": "symfony/yaml",
            "version": "v2.4.0",
            "target-dir": "Symfony/Component/Yaml",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Yaml.git",
                "reference": "1ae235a1b9d3ad3d9f3860ff20acc072df95b7f5"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Yaml/zipball/1ae235a1b9d3ad3d9f3860ff20acc072df95b7f5",
                "reference": "1ae235a1b9d3ad3d9f3860ff20acc072df95b7f5",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.4-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Yaml\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Yaml Component",
            "homepage": "http://symfony.com",
            "time": "2013-11-26 16:40:27"
        }
    ],
    "aliases": [

    ],
    "minimum-stability": "stable",
    "stability-flags": {
        "phpunit/phpunit": 0
    },
    "platform": {
        "php": ">=5.3.3"
    },
    "platform-dev": [

    ]
}
<?xml version="1.0" encoding="utf-8"?>

<phpunit colors="true" strict="true" bootstrap="vendor/autoload.php">
  <testsuites>
    <testsuite name="phpDocumentor\Reflection\DocBlock">
      <directory>./tests/</directory>
    </testsuite>
  </testsuites>
  <filter>
    <whitelist>
        <directory suffix=".php">./src/</directory>
    </whitelist>
  </filter>
</phpunit>
{
    "name": "phpdocumentor/unified-asset-installer",
    "description": "Asset installer for phpDocumentor",
    "type": "composer-installer",
    "keywords": ["assets", "installer", "templates", "plugins"],
    "homepage": "http://www.phpdoc.org",
    "license": "MIT",
    "autoload": {
        "psr-0": {"phpDocumentor\\Composer": ["src/", "test/unit/"]}
    },
    "extra": {
        "class": "\\phpDocumentor\\Composer\\UnifiedAssetInstaller"
    },
    "require": {
        "composer-plugin-api": "1.0.0"
    },
    "require-dev": {
        "phpunit/phpunit":   "~3.7",
        "composer/composer": "~1.0@dev"
    }
}
<?php
/**
 * phpDocumentor
 *
 * PHP Version 5
 *
 * @copyright 2010-2013 Mike van Riel / Naenius (http://www.naenius.com)
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
 * @link      http://phpdoc.org
 */

namespace phpDocumentor\Composer;

use Composer\Installer\LibraryInstaller;
use Composer\Package\PackageInterface;

class UnifiedAssetInstaller extends LibraryInstaller
{
    /**
     * Determines the install path for templates,
     *
     * The installation path is determined by checking whether the package is included in another composer configuration
     * or installed as part of the normal phpDocumentor installation.
     *
     * When the package is included as part of a different project it will be installed in the `data/templates` folder
     * of phpDocumentor (thus `/phpdocumentor/phpdocumentor/data/templates`); if it is installed as part of
     * phpDocumentor it will be installed in the root of the project (thus `/data/templates`).
     *
     * @param PackageInterface $package
     *
     * @throws \InvalidArgumentException if the name of the package does not start with `phpdocumentor/template-`.
     *
     * @return string a path relative to the root of the composer.json that is being installed.
     */
    public function getInstallPath(PackageInterface $package)
    {
        if ($this->extractPrefix($package) != 'phpdocumentor/template-') {
            throw new \InvalidArgumentException(
                'Unable to install template, phpdocumentor templates should '
                .'always start their package name with "phpdocumentor/template-"'
            );
        }

        return $this->getTemplateRootPath() . '/' . $this->extractShortName($package);
    }

    /**
     * Extract the first 23 characters of the package name; which is expected to be the prefix.
     *
     * @param PackageInterface $package
     *
     * @return string
     */
    protected function extractPrefix(PackageInterface $package)
    {
        return substr($package->getPrettyName(), 0, 23);
    }

    /**
     * Extract the everything after the first 23 characters of the package name; which is expected to be the short name.
     *
     * @param PackageInterface $package
     *
     * @return string
     */
    protected function extractShortName(PackageInterface $package)
    {
        return substr($package->getPrettyName(), 23);
    }

    /**
     * Returns the root installation path for templates.
     *
     * @return string a path relative to the root of the composer.json that is being installed where the templates
     *     are stored.
     */
    protected function getTemplateRootPath()
    {
        return ($this->composer->getPackage()->getName() === 'phpdocumentor/phpdocumentor')
            ? 'data/templates'
            : $this->vendorDir . '/phpdocumentor/templates'
        ;
    }

    /**
     * {@inheritDoc}
     */
    public function supports($packageType)
    {
      return (bool)('phpdocumentor-template' === $packageType);
    }
}
<?php
namespace phpDocumentor\Composer;

require __DIR__ . '/../../../../vendor/composer/composer/tests/Composer/Test/TestCase.php';

use Composer\Installer\LibraryInstaller;
use Composer\Util\Filesystem;
use Composer\Test\TestCase;
use Composer\Composer;
use Composer\Config;
use Composer\Package\RootPackage;

/**
 * @covers phpDocumentor\Composer\UnifiedAssetInstaller
 */
class UnifiedAssetInstallerTest extends TestCase
{
    protected $composer;
    protected $config;
    protected $vendorDir;
    protected $binDir;
    protected $dm;
    protected $repository;
    protected $io;
    protected $fs;
    protected $package;

    protected function setUp()
    {
        $this->fs = new Filesystem;

        $this->composer = new Composer();
        $this->config = new Config();
        $this->composer->setConfig($this->config);

        $this->package = new RootPackage('phpdocumentor/phpdocumentor', '2.0.0', '2.0.0');
        $this->composer->setPackage($this->package);

        $this->vendorDir = realpath(sys_get_temp_dir()).DIRECTORY_SEPARATOR
            .'composer-test-vendor';
        $this->ensureDirectoryExistsAndClear($this->vendorDir);

        $this->binDir = realpath(sys_get_temp_dir()).DIRECTORY_SEPARATOR
            .'composer-test-bin';
        $this->ensureDirectoryExistsAndClear($this->binDir);

        $this->config->merge(
            array(
                'config' => array(
                    'vendor-dir' => $this->vendorDir,
                    'bin-dir'    => $this->binDir,
                ),
            )
        );

        $this->dm = $this->getMockBuilder('Composer\Downloader\DownloadManager')
            ->disableOriginalConstructor()
            ->getMock();
        $this->composer->setDownloadManager($this->dm);

        $this->repository = $this->getMock(
            'Composer\Repository\InstalledRepositoryInterface'
        );
        $this->io = $this->getMock('Composer\IO\IOInterface');
    }

    protected function tearDown()
    {
        $this->fs->removeDirectory($this->vendorDir);
        $this->fs->removeDirectory($this->binDir);
    }

    /**
     * @covers phpDocumentor\Composer\UnifiedAssetInstaller::getInstallPath
     */
    public function testGetInstallPath()
    {
        $library = new UnifiedAssetInstaller($this->io, $this->composer);
        $package = $this->createPackageMock();

        // UnifiedAssetInstaller does not support targetDir
        $package
            ->expects($this->never())
            ->method('getTargetDir');

        $package
            ->expects($this->atLeastOnce())
            ->method('getPrettyName')
            ->will($this->returnValue('phpdocumentor/template-mock'));

        $this->assertEquals(
            'data/templates/mock',
            $library->getInstallPath($package)
        );
    }


    /**
     * @covers phpDocumentor\Composer\UnifiedAssetInstaller::getInstallPath
     */
    public function testGetInstallPathWhenVendored()
    {
        $composer = $this->createComposerMock();
        $rootPackage = new RootPackage('not/phpdocumentor-base-install', '1.0.0.0', '1.0.0');
        $composer->setPackage($rootPackage);

        $library = new UnifiedAssetInstaller($this->io, $composer);

        $package = $this->createPackageMock();

        $package
            ->expects($this->atLeastOnce())
            ->method('getPrettyName')
            ->will($this->returnValue('phpdocumentor/template-mock'));

        $this->assertEquals(
            $this->vendorDir.'/phpdocumentor/templates/mock',
            $library->getInstallPath($package)
        );
    }

    /**
     * @covers phpDocumentor\Composer\UnifiedAssetInstaller::getInstallPath
     * @expectedException InvalidArgumentException
     */
    public function testGetInstallPathWithInvalidPackageName()
    {
        $library = new UnifiedAssetInstaller($this->io, $this->composer);
        $package = $this->createPackageMock();

        $package
            ->expects($this->once())
            ->method('getPrettyName')
            ->will($this->returnValue('a/b'));

        $library->getInstallPath($package);
    }

    /**
     * @covers phpDocumentor\Composer\UnifiedAssetInstaller::supports
     */
    public function testSupports()
    {
        $library = new UnifiedAssetInstaller($this->io, $this->composer);

        $this->assertTrue($library->supports('phpdocumentor-template'));
        $this->assertFalse($library->supports('phpdocumentor-plugin'));
        $this->assertFalse($library->supports('library'));
    }

    protected function createPackageMock()
    {
        return $this->getMockBuilder('Composer\Package\Package')
            ->setConstructorArgs(array(md5(rand()), '1.0.0.0', '1.0.0'))
            ->getMock();
    }

    protected function createComposerMock()
    {
        $composer = new Composer();
        $composer->setConfig($this->config);
        $composer->setDownloadManager($this->dm);

        return $composer;
    }
}
<?php

/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

error_reporting(E_ALL);

$loader = require __DIR__.'/../vendor/autoload.php';
$loader->add('Composer\Test', __DIR__.'/../vendor/composer/composer/tests');
$loader->add('phpDocumentor', __DIR__.'/unit');
{
    "_readme": [
        "This file locks the dependencies of your project to a known state",
        "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
    ],
    "hash": "5780f485ab3582eda65ad954ffa4ebaa",
    "packages": [

    ],
    "packages-dev": [
        {
            "name": "composer/composer",
            "version": "dev-master",
            "source": {
                "type": "git",
                "url": "https://github.com/composer/composer.git",
                "reference": "689e3056faf4a724006a97b51f0cd4777be19282"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/composer/composer/zipball/689e3056faf4a724006a97b51f0cd4777be19282",
                "reference": "689e3056faf4a724006a97b51f0cd4777be19282",
                "shasum": ""
            },
            "require": {
                "justinrainbow/json-schema": "1.1.*",
                "php": ">=5.3.2",
                "seld/jsonlint": "1.*",
                "symfony/console": "~2.3",
                "symfony/finder": "~2.2",
                "symfony/process": "~2.1"
            },
            "require-dev": {
                "phpunit/phpunit": "~3.7.10"
            },
            "suggest": {
                "ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages",
                "ext-zip": "Enabling the zip extension allows you to unzip archives, and allows gzip compression of all internet traffic"
            },
            "bin": [
                "bin/composer"
            ],
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.0-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Composer": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Jordi Boggiano",
                    "email": "j.boggiano@seld.be",
                    "homepage": "http://seld.be",
                    "role": "Developer"
                },
                {
                    "name": "Nils Adermann",
                    "email": "naderman@naderman.de",
                    "homepage": "http://www.naderman.de"
                }
            ],
            "description": "Dependency Manager",
            "homepage": "http://getcomposer.org/",
            "keywords": [
                "autoload",
                "dependency",
                "package"
            ],
            "time": "2013-09-08 16:03:05"
        },
        {
            "name": "justinrainbow/json-schema",
            "version": "1.1.0",
            "source": {
                "type": "git",
                "url": "git://github.com/justinrainbow/json-schema.git",
                "reference": "v1.1.0"
            },
            "dist": {
                "type": "zip",
                "url": "https://github.com/justinrainbow/json-schema/archive/v1.1.0.zip",
                "reference": "v1.1.0",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.0"
            },
            "type": "library",
            "autoload": {
                "psr-0": {
                    "JsonSchema": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "NewBSD"
            ],
            "authors": [
                {
                    "name": "Igor Wiedler",
                    "email": "igor@wiedler.ch",
                    "homepage": "http://wiedler.ch/igor/"
                },
                {
                    "name": "Bruno Prieto Reis",
                    "email": "bruno.p.reis@gmail.com"
                },
                {
                    "name": "Justin Rainbow",
                    "email": "justin.rainbow@gmail.com"
                },
                {
                    "name": "Robert Schönthal",
                    "email": "seroscho@googlemail.com",
                    "homepage": "http://digitalkaoz.net"
                }
            ],
            "description": "A library to validate a json schema.",
            "homepage": "https://github.com/justinrainbow/json-schema",
            "keywords": [
                "json",
                "schema"
            ],
            "time": "2012-01-03 00:33:17"
        },
        {
            "name": "phpunit/php-code-coverage",
            "version": "1.2.12",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
                "reference": "1.2.12"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/1.2.12",
                "reference": "1.2.12",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3",
                "phpunit/php-file-iterator": ">=1.3.0@stable",
                "phpunit/php-text-template": ">=1.1.1@stable",
                "phpunit/php-token-stream": ">=1.1.3@stable"
            },
            "require-dev": {
                "phpunit/phpunit": "3.7.*@dev"
            },
            "suggest": {
                "ext-dom": "*",
                "ext-xdebug": ">=2.0.5"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.2.x-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "PHP/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
            "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
            "keywords": [
                "coverage",
                "testing",
                "xunit"
            ],
            "time": "2013-07-06 06:26:16"
        },
        {
            "name": "phpunit/php-file-iterator",
            "version": "1.3.3",
            "source": {
                "type": "git",
                "url": "git://github.com/sebastianbergmann/php-file-iterator.git",
                "reference": "1.3.3"
            },
            "dist": {
                "type": "zip",
                "url": "https://github.com/sebastianbergmann/php-file-iterator/zipball/1.3.3",
                "reference": "1.3.3",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "File/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "FilterIterator implementation that filters files based on a list of suffixes.",
            "homepage": "http://www.phpunit.de/",
            "keywords": [
                "filesystem",
                "iterator"
            ],
            "time": "2012-10-11 04:44:38"
        },
        {
            "name": "phpunit/php-text-template",
            "version": "1.1.4",
            "source": {
                "type": "git",
                "url": "git://github.com/sebastianbergmann/php-text-template.git",
                "reference": "1.1.4"
            },
            "dist": {
                "type": "zip",
                "url": "https://github.com/sebastianbergmann/php-text-template/zipball/1.1.4",
                "reference": "1.1.4",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "Text/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Simple template engine.",
            "homepage": "https://github.com/sebastianbergmann/php-text-template/",
            "keywords": [
                "template"
            ],
            "time": "2012-10-31 11:15:28"
        },
        {
            "name": "phpunit/php-timer",
            "version": "1.0.5",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/php-timer.git",
                "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c",
                "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "PHP/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Utility class for timing",
            "homepage": "https://github.com/sebastianbergmann/php-timer/",
            "keywords": [
                "timer"
            ],
            "time": "2013-08-02 07:42:54"
        },
        {
            "name": "phpunit/php-token-stream",
            "version": "1.2.0",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/php-token-stream.git",
                "reference": "31babf400e5b5868573bf49a000a3519d3978233"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/31babf400e5b5868573bf49a000a3519d3978233",
                "reference": "31babf400e5b5868573bf49a000a3519d3978233",
                "shasum": ""
            },
            "require": {
                "ext-tokenizer": "*",
                "php": ">=5.3.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.2-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "PHP/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Wrapper around PHP's tokenizer extension.",
            "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
            "keywords": [
                "tokenizer"
            ],
            "time": "2013-08-04 05:57:48"
        },
        {
            "name": "phpunit/phpunit",
            "version": "3.7.24",
            "source": {
                "type": "git",
                "url": "https://github.com/sebastianbergmann/phpunit.git",
                "reference": "af7b77ccb5c64458bdfca95665d29558d1df7d08"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/af7b77ccb5c64458bdfca95665d29558d1df7d08",
                "reference": "af7b77ccb5c64458bdfca95665d29558d1df7d08",
                "shasum": ""
            },
            "require": {
                "ext-dom": "*",
                "ext-pcre": "*",
                "ext-reflection": "*",
                "ext-spl": "*",
                "php": ">=5.3.3",
                "phpunit/php-code-coverage": "~1.2.1",
                "phpunit/php-file-iterator": ">=1.3.1",
                "phpunit/php-text-template": ">=1.1.1",
                "phpunit/php-timer": ">=1.0.4",
                "phpunit/phpunit-mock-objects": "~1.2.0",
                "symfony/yaml": "~2.0"
            },
            "require-dev": {
                "pear-pear/pear": "1.9.4"
            },
            "suggest": {
                "ext-json": "*",
                "ext-simplexml": "*",
                "ext-tokenizer": "*",
                "phpunit/php-invoker": ">=1.1.0,<1.2.0"
            },
            "bin": [
                "composer/bin/phpunit"
            ],
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "3.7.x-dev"
                }
            },
            "autoload": {
                "classmap": [
                    "PHPUnit/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                "",
                "../../symfony/yaml/"
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sebastian@phpunit.de",
                    "role": "lead"
                }
            ],
            "description": "The PHP Unit Testing framework.",
            "homepage": "http://www.phpunit.de/",
            "keywords": [
                "phpunit",
                "testing",
                "xunit"
            ],
            "time": "2013-08-09 06:58:24"
        },
        {
            "name": "phpunit/phpunit-mock-objects",
            "version": "1.2.3",
            "source": {
                "type": "git",
                "url": "git://github.com/sebastianbergmann/phpunit-mock-objects.git",
                "reference": "1.2.3"
            },
            "dist": {
                "type": "zip",
                "url": "https://github.com/sebastianbergmann/phpunit-mock-objects/archive/1.2.3.zip",
                "reference": "1.2.3",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3",
                "phpunit/php-text-template": ">=1.1.1@stable"
            },
            "suggest": {
                "ext-soap": "*"
            },
            "type": "library",
            "autoload": {
                "classmap": [
                    "PHPUnit/"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "include-path": [
                ""
            ],
            "license": [
                "BSD-3-Clause"
            ],
            "authors": [
                {
                    "name": "Sebastian Bergmann",
                    "email": "sb@sebastian-bergmann.de",
                    "role": "lead"
                }
            ],
            "description": "Mock Object library for PHPUnit",
            "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
            "keywords": [
                "mock",
                "xunit"
            ],
            "time": "2013-01-13 10:24:48"
        },
        {
            "name": "seld/jsonlint",
            "version": "1.1.1",
            "source": {
                "type": "git",
                "url": "http://github.com/Seldaek/jsonlint",
                "reference": "1.1.1"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/1.1.1",
                "reference": "1.1.1",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.0"
            },
            "bin": [
                "bin/jsonlint"
            ],
            "type": "library",
            "autoload": {
                "psr-0": {
                    "Seld\\JsonLint": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Jordi Boggiano",
                    "email": "j.boggiano@seld.be",
                    "homepage": "http://seld.be",
                    "role": "Developer"
                }
            ],
            "description": "JSON Linter",
            "keywords": [
                "json",
                "linter",
                "parser",
                "validator"
            ],
            "time": "2013-02-11 23:03:12"
        },
        {
            "name": "symfony/console",
            "version": "v2.3.4",
            "target-dir": "Symfony/Component/Console",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Console.git",
                "reference": "db78f8ff7fc9e28d25ff9a0bf6ddf9f0e35fbbe3"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Console/zipball/db78f8ff7fc9e28d25ff9a0bf6ddf9f0e35fbbe3",
                "reference": "db78f8ff7fc9e28d25ff9a0bf6ddf9f0e35fbbe3",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "require-dev": {
                "symfony/event-dispatcher": "~2.1"
            },
            "suggest": {
                "symfony/event-dispatcher": ""
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Console\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Console Component",
            "homepage": "http://symfony.com",
            "time": "2013-08-17 16:34:49"
        },
        {
            "name": "symfony/finder",
            "version": "v2.3.4",
            "target-dir": "Symfony/Component/Finder",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Finder.git",
                "reference": "4a0fee5b86f5bbd9dfdc11ec124eba2915737ce1"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Finder/zipball/4a0fee5b86f5bbd9dfdc11ec124eba2915737ce1",
                "reference": "4a0fee5b86f5bbd9dfdc11ec124eba2915737ce1",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Finder\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Finder Component",
            "homepage": "http://symfony.com",
            "time": "2013-08-13 20:18:00"
        },
        {
            "name": "symfony/process",
            "version": "v2.3.4",
            "target-dir": "Symfony/Component/Process",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Process.git",
                "reference": "1e91553e1cedd0b8fb1da6ea4f89b02e21713d5b"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Process/zipball/1e91553e1cedd0b8fb1da6ea4f89b02e21713d5b",
                "reference": "1e91553e1cedd0b8fb1da6ea4f89b02e21713d5b",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Process\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Process Component",
            "homepage": "http://symfony.com",
            "time": "2013-08-22 06:42:25"
        },
        {
            "name": "symfony/yaml",
            "version": "v2.3.4",
            "target-dir": "Symfony/Component/Yaml",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/Yaml.git",
                "reference": "5a279f1b5f5e1045a6c432354d9ea727ff3a9847"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/Yaml/zipball/5a279f1b5f5e1045a6c432354d9ea727ff3a9847",
                "reference": "5a279f1b5f5e1045a6c432354d9ea727ff3a9847",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.3"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.3-dev"
                }
            },
            "autoload": {
                "psr-0": {
                    "Symfony\\Component\\Yaml\\": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Fabien Potencier",
                    "email": "fabien@symfony.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "http://symfony.com/contributors"
                }
            ],
            "description": "Symfony Yaml Component",
            "homepage": "http://symfony.com",
            "time": "2013-08-24 15:26:22"
        }
    ],
    "aliases": [

    ],
    "minimum-stability": "stable",
    "stability-flags": {
        "composer/composer": 20
    },
    "platform": [

    ],
    "platform-dev": [

    ]
}
<?xml version="1.0" encoding="utf-8"?>

<phpunit bootstrap="tests/bootstrap.php" colors="true" strict="true">
    <testsuites>
        <testsuite name="phpDocumentor">
            <directory>./tests/unit/</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist>
            <directory suffix=".php">src/phpDocumentor</directory>
        </whitelist>
    </filter>
</phpunit>
{
    "name": "squizlabs/php_codesniffer",
    "description": "PHP_CodeSniffer tokenises PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
    "type": "library",
    "keywords": [
        "phpcs",
        "standards"
    ],
    "homepage": "http://www.squizlabs.com/php-codesniffer",
    "license": "BSD-3-Clause",
    "authors": [
        {
            "name": "Greg Sherwood",
            "role": "lead"
        }
    ],
    "support": {
        "issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name%5B%5D=PHP_CodeSniffer",
        "source": "https://github.com/squizlabs/PHP_CodeSniffer"
    },
    "autoload": {
        "classmap": [
            "CodeSniffer.php",
            "CodeSniffer/CLI.php",
            "CodeSniffer/Exception.php",
            "CodeSniffer/File.php",
            "CodeSniffer/Report.php",
            "CodeSniffer/Reporting.php",
            "CodeSniffer/Sniff.php",
            "CodeSniffer/Tokens.php",
            "CodeSniffer/Reports/",
            "CodeSniffer/CommentParser/",
            "CodeSniffer/Tokenizers/",
            "CodeSniffer/DocGenerators/",
            "CodeSniffer/Standards/AbstractPatternSniff.php",
            "CodeSniffer/Standards/AbstractScopeSniff.php",
            "CodeSniffer/Standards/AbstractVariableSniff.php",
            "CodeSniffer/Standards/IncorrectPatternException.php",
            "CodeSniffer/Standards/Generic/Sniffs/",
            "CodeSniffer/Standards/MySource/Sniffs/",
            "CodeSniffer/Standards/PEAR/Sniffs/",
            "CodeSniffer/Standards/PSR1/Sniffs/",
            "CodeSniffer/Standards/PSR2/Sniffs/",
            "CodeSniffer/Standards/Squiz/Sniffs/",
            "CodeSniffer/Standards/Zend/Sniffs/"
        ]
    },
    "suggest": {
        "phpunit/php-timer": "dev-master"
    },
    "require": {
        "php": ">=5.1.2",
        "ext-tokenizer": "*"
    },
    "bin": [
        "scripts/phpcs"
    ]
}
<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.4.10" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
http://pear.php.net/dtd/tasks-1.0.xsd
http://pear.php.net/dtd/package-2.0
http://pear.php.net/dtd/package-2.0.xsd">
 <name>PHP_CodeSniffer</name>
 <channel>pear.php.net</channel>
 <summary>PHP_CodeSniffer tokenises PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.</summary>
 <description>PHP_CodeSniffer is a PHP5 script that tokenises PHP, JavaScript and CSS files to detect violations of a defined coding standard. It is an essential development tool that ensures your code remains clean and consistent. It can also help prevent some common semantic errors made by developers.
 </description>
 <lead>
  <name>Greg Sherwood</name>
  <user>squiz</user>
  <email>gsherwood@squiz.net</email>
  <active>yes</active>
 </lead>
 <date>2013-11-28</date>
 <time>09:19:00</time>
 <version>
  <release>1.5.0</release>
  <api>1.5.0</api>
 </version>
 <stability>
  <release>stable</release>
  <api>stable</api>
 </stability>
 <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD 3-Clause License</license>
 <notes>
  - Doc generation is now working again for installed standards
    -- Includes a fix for limiting the docs to specific sniffs
  - Generic ScopeIndentSniff now allows for ignored tokens to be set via ruleset.xml files
    -- E.g., to ignore comments, override a property using:
    -- name="ignoreIndentationTokens" type="array" value="T_COMMENT,T_DOC_COMMENT"
  - PSR2 standard now ignores comments when checking indentation rules
  - Generic UpperCaseConstantNameSniff no longer reports errors where constants are used (request #20090)
    -- It still reports errors where constants are defined
  - Individual messages can now be excluded in ruleset.xml files using the exclude tag (request #20091)
    -- Setting message severity to 0 continues to be supported
  - Squiz OperatorSpacingSniff no longer throws errors for the ?: short ternary operator
    -- Thanks to Antoine Musso for the patch
  - Comment parser now supports non-English characters when splitting comment lines into words
    -- Thanks to Nik Sun for the patch
  - Exit statements are now recognised as valid closers for CASE and DEFAULT blocks
    -- Thanks to Maksim Kochkin for the patch
  - PHP_CodeSniffer_CLI::process() can now be passed an incomplete array of CLI values
    -- Missing values will be set to the CLI defaults
    -- Thanks to Maksim Kochkin for the patch
  - Fixed bug #20093 : Bug with ternary operator token
  - Fixed bug #20097 : CLI.php throws error in php 5.2
  - Fixed bug #20100 : incorrect Function mysql() has been deprecated report
  - Fixed bug #20119 : PHP warning: invalid argument to str_repeat() in SVN blame report with -s
  - Fixed bug #20123 : PSR2 complains about an empty second statement in for-loop
  - Fixed bug #20131 : PHP errors in svnblame report, if there are files not under version control
  - Fixed bug #20133 : Allow "HG: hg_id" as value for @version tag
 </notes>
 <contents>
  <dir name="/">
   <file baseinstalldir="PHP" name="CodeSniffer.php" role="php">
    <tasks:replace from="@package_version@" to="version" type="package-info" />
    <tasks:replace from="@data_dir@" to="data_dir" type="pear-config" />
   </file>
   <file baseinstalldir="PHP" name="CodeSniffer.conf.dist" role="data" />
   <dir name="scripts">
    <file baseinstalldir="" name="phpcs" role="script">
     <tasks:replace from="/usr/bin/env php" to="php_bin" type="pear-config" />
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
    <file baseinstalldir="" name="phpcs-svn-pre-commit" role="script">
     <tasks:replace from="@php_bin@" to="php_bin" type="pear-config" />
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
    <file baseinstalldir="" name="phpcs.bat" role="script">
     <tasks:replace from="@php_bin@" to="php_bin" type="pear-config" />
     <tasks:replace from="@bin_dir@" to="bin_dir" type="pear-config" />
     <tasks:replace from="@php_dir@" to="php_dir" type="pear-config" />
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
   </dir>
   <dir name="tests">
    <dir name="Core">
     <dir name="File">
      <file baseinstalldir="" name="GetMethodParametersTest.php" role="test">
       <tasks:replace from="@package_version@" to="version" type="package-info" />
      </file>
     </dir>
     <file baseinstalldir="" name="AllTests.php" role="test">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="" name="ErrorSuppressionTest.php" role="test">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="" name="IsCamelCapsTest.php" role="test">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
    </dir>
    <dir name="Standards">
     <file baseinstalldir="" name="AbstractSniffUnitTest.php" role="test">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="" name="AllSniffs.php" role="test">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
    </dir>
    <file baseinstalldir="" name="AllTests.php" role="test">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
    <file baseinstalldir="" name="TestSuite.php" role="test">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
   </dir>
   <dir name="CodeSniffer">
    <dir name="CommentParser">
     <file baseinstalldir="PHP" name="AbstractDocElement.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="AbstractParser.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="ClassCommentParser.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="CommentElement.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="DocElement.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="FunctionCommentParser.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="MemberCommentParser.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="PairElement.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="ParameterElement.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="ParserException.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="SingleElement.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
    </dir>
    <dir name="DocGenerators">
     <file baseinstalldir="PHP" name="Generator.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="HTML.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="Text.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
    </dir>
    <dir name="Reports">
     <file baseinstalldir="PHP" name="Checkstyle.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="Csv.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="Emacs.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="Full.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="Gitblame.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="Hgblame.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="Json.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="Junit.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="Notifysend.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="Source.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="Summary.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="Svnblame.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="VersionControl.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="Xml.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
    </dir>
    <dir name="Standards">
     <dir name="Generic">
      <dir name="Docs">
       <dir name="Classes">
        <file baseinstalldir="PHP" name="DuplicateClassNameStandard.xml" role="php" />
       </dir>
       <dir name="Debug">
        <file baseinstalldir="PHP" name="CSSLintStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="ClosureLinterStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="JSHintStandard.xml" role="php" />
       </dir>
       <dir name="Commenting">
        <file baseinstalldir="PHP" name="FixmeStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="TodoStandard.xml" role="php" />
       </dir>
       <dir name="CodeAnalysis">
        <file baseinstalldir="PHP" name="JumbledIncrementerStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="UnusedFunctionParameterStandard.xml" role="php" />
       </dir>
       <dir name="ControlStructures">
        <file baseinstalldir="PHP" name="InlineControlStructureStandard.xml" role="php" />
       </dir>
       <dir name="CodeAnalysis">
        <file baseinstalldir="PHP" name="EmptyStatementStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="ForLoopShouldBeWhileLoopStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="ForLoopWithTestFunctionCallStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="UnconditionalIfStatementStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="UnnecessaryFinalModifierStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="UselessOverridingMethodStandard.xml" role="php" />
       </dir>
       <dir name="Files">
        <file baseinstalldir="PHP" name="ByteOrderMarkStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="EndFileNewlineStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="EndFileNoNewlineStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="InlineHTMLStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="LineEndingsStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="LineLengthStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="LowercasedFilenameStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="OneClassPerFileStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="OneInterfacePerFileStandard.xml" role="php" />
       </dir>
       <dir name="Formatting">
        <file baseinstalldir="PHP" name="DisallowMultipleStatementsStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="MultipleStatementAlignmentStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="NoSpaceAfterCastStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="SpaceAfterCastStandard.xml" role="php" />
       </dir>
       <dir name="Functions">
        <file baseinstalldir="PHP" name="CallTimePassByReferenceStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="FunctionCallArgumentSpacingStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="OpeningFunctionBraceBsdAllmanStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="OpeningFunctionBraceKernighanRitchieStandard.xml" role="php" />
       </dir>
       <dir name="Metrics">
        <file baseinstalldir="PHP" name="CyclomaticComplexityStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="NestingLevelStandard.xml" role="php" />
       </dir>
       <dir name="NamingConventions">
        <file baseinstalldir="PHP" name="CamelCapsFunctionNameStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="ConstructorNameStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="UpperCaseConstantNameStandard.xml" role="php" />
       </dir>
       <dir name="PHP">
        <file baseinstalldir="PHP" name="CharacterBeforePHPOpeningTagStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="ClosingPHPTagStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="DeprecatedFunctionsStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="DisallowShortOpenTagStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="ForbiddenFunctionsStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="LowerCaseConstantStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="LowerCaseKeywordStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="NoSilencedErrorsStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="SAPIUsageStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="UpperCaseConstantStandard.xml" role="php" />
       </dir>
       <dir name="Strings">
        <file baseinstalldir="PHP" name="UnnecessaryStringConcatStandard.xml" role="php" />
       </dir>
       <dir name="VersionControl">
        <file baseinstalldir="PHP" name="SubversionPropertiesStandard.xml" role="php" />
       </dir>
       <dir name="WhiteSpace">
        <file baseinstalldir="PHP" name="DisallowSpaceIndentStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="DisallowTabIndentStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="ScopeIndentStandard.xml" role="php" />
       </dir>
      </dir>
      <dir name="Sniffs">
       <dir name="Classes">
        <file baseinstalldir="PHP" name="DuplicateClassNameSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="CodeAnalysis">
        <file baseinstalldir="PHP" name="EmptyStatementSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ForLoopShouldBeWhileLoopSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ForLoopWithTestFunctionCallSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="JumbledIncrementerSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="UnconditionalIfStatementSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="UnnecessaryFinalModifierSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="UnusedFunctionParameterSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="UselessOverridingMethodSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Commenting">
        <file baseinstalldir="PHP" name="FixmeSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="TodoSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="ControlStructures">
        <file baseinstalldir="PHP" name="InlineControlStructureSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Debug">
        <file baseinstalldir="PHP" name="ClosureLinterSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="CSSLintSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="JSHintSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Files">
        <file baseinstalldir="PHP" name="ByteOrderMarkSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="EndFileNewlineSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="EndFileNoNewlineSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="InlineHTMLSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="LineEndingsSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="LineLengthSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="LowercasedFilenameSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="OneClassPerFileSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="OneInterfacePerFileSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Formatting">
        <file baseinstalldir="PHP" name="DisallowMultipleStatementsSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="MultipleStatementAlignmentSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="NoSpaceAfterCastSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="SpaceAfterCastSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Functions">
        <file baseinstalldir="PHP" name="CallTimePassByReferenceSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="FunctionCallArgumentSpacingSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="OpeningFunctionBraceBsdAllmanSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="OpeningFunctionBraceKernighanRitchieSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Metrics">
        <file baseinstalldir="PHP" name="CyclomaticComplexitySniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="NestingLevelSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="NamingConventions">
        <file baseinstalldir="PHP" name="CamelCapsFunctionNameSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ConstructorNameSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="UpperCaseConstantNameSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="PHP">
        <file baseinstalldir="PHP" name="CharacterBeforePHPOpeningTagSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ClosingPHPTagSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DeprecatedFunctionsSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DisallowShortOpenTagSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ForbiddenFunctionsSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="LowerCaseConstantSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="LowerCaseKeywordSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="NoSilencedErrorsSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="SAPIUsageSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="UpperCaseConstantSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Strings">
        <file baseinstalldir="PHP" name="UnnecessaryStringConcatSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="VersionControl">
        <file baseinstalldir="PHP" name="SubversionPropertiesSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="WhiteSpace">
        <file baseinstalldir="PHP" name="DisallowSpaceIndentSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DisallowTabIndentSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ScopeIndentSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
      </dir>
      <dir name="Tests">
       <dir name="Classes">
        <file baseinstalldir="PHP" name="DuplicateClassNameUnitTest.1.inc" role="test" />
        <file baseinstalldir="PHP" name="DuplicateClassNameUnitTest.2.inc" role="test" />
        <file baseinstalldir="PHP" name="DuplicateClassNameUnitTest.3.inc" role="test" />
        <file baseinstalldir="PHP" name="DuplicateClassNameUnitTest.4.inc" role="test" />
        <file baseinstalldir="PHP" name="DuplicateClassNameUnitTest.5.inc" role="test" />
        <file baseinstalldir="PHP" name="DuplicateClassNameUnitTest.6.inc" role="test" />
        <file baseinstalldir="PHP" name="DuplicateClassNameUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="CodeAnalysis">
        <file baseinstalldir="PHP" name="EmptyStatementUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="EmptyStatementUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ForLoopShouldBeWhileLoopUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ForLoopShouldBeWhileLoopUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ForLoopWithTestFunctionCallUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ForLoopWithTestFunctionCallUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="JumbledIncrementerUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="JumbledIncrementerUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="UnconditionalIfStatementUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="UnconditionalIfStatementUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="UnnecessaryFinalModifierUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="UnnecessaryFinalModifierUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="UnusedFunctionParameterUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="UnusedFunctionParameterUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="UselessOverridingMethodUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="UselessOverridingMethodUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Commenting">
        <file baseinstalldir="PHP" name="FixmeUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="FixmeUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="FixmeUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="TodoUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="TodoUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="TodoUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="ControlStructures">
        <file baseinstalldir="PHP" name="InlineControlStructureUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="InlineControlStructureUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="InlineControlStructureUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Files">
        <file baseinstalldir="PHP" name="ByteOrderMarkUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ByteOrderMarkUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="EndFileNewlineUnitTest.1.css" role="test" />
        <file baseinstalldir="PHP" name="EndFileNewlineUnitTest.1.js" role="test" />
        <file baseinstalldir="PHP" name="EndFileNewlineUnitTest.1.inc" role="test" />
        <file baseinstalldir="PHP" name="EndFileNewlineUnitTest.2.css" role="test" />
        <file baseinstalldir="PHP" name="EndFileNewlineUnitTest.2.js" role="test" />
        <file baseinstalldir="PHP" name="EndFileNewlineUnitTest.2.inc" role="test" />
        <file baseinstalldir="PHP" name="EndFileNewlineUnitTest.3.css" role="test" />
        <file baseinstalldir="PHP" name="EndFileNewlineUnitTest.3.js" role="test" />
        <file baseinstalldir="PHP" name="EndFileNewlineUnitTest.3.inc" role="test" />
        <file baseinstalldir="PHP" name="EndFileNewlineUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="EndFileNoNewlineUnitTest.1.css" role="test" />
        <file baseinstalldir="PHP" name="EndFileNoNewlineUnitTest.1.js" role="test" />
        <file baseinstalldir="PHP" name="EndFileNoNewlineUnitTest.1.inc" role="test" />
        <file baseinstalldir="PHP" name="EndFileNoNewlineUnitTest.2.css" role="test" />
        <file baseinstalldir="PHP" name="EndFileNoNewlineUnitTest.2.js" role="test" />
        <file baseinstalldir="PHP" name="EndFileNoNewlineUnitTest.2.inc" role="test" />
        <file baseinstalldir="PHP" name="EndFileNoNewlineUnitTest.3.css" role="test" />
        <file baseinstalldir="PHP" name="EndFileNoNewlineUnitTest.3.js" role="test" />
        <file baseinstalldir="PHP" name="EndFileNoNewlineUnitTest.3.inc" role="test" />
        <file baseinstalldir="PHP" name="EndFileNoNewlineUnitTest.4.inc" role="test" />
        <file baseinstalldir="PHP" name="EndFileNoNewlineUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="InlineHTMLUnitTest.1.inc" role="test" />
        <file baseinstalldir="PHP" name="InlineHTMLUnitTest.2.inc" role="test" />
        <file baseinstalldir="PHP" name="InlineHTMLUnitTest.3.inc" role="test" />
        <file baseinstalldir="PHP" name="InlineHTMLUnitTest.4.inc" role="test" />
        <file baseinstalldir="PHP" name="InlineHTMLUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="LineEndingsUnitTest.css" role="test" />
        <file baseinstalldir="PHP" name="LineEndingsUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="LineEndingsUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="LineEndingsUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="LineLengthUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="LineLengthUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="LowercasedFilenameUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="LowercasedFilenameUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="OneClassPerFileUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="OneClassPerFileUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="OneInterfacePerFileUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="OneInterfacePerFileUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Formatting">
        <file baseinstalldir="PHP" name="DisallowMultipleStatementsUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="DisallowMultipleStatementsUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="MultipleStatementAlignmentUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="MultipleStatementAlignmentUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="MultipleStatementAlignmentUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="NoSpaceAfterCastUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="NoSpaceAfterCastUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="SpaceAfterCastUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="SpaceAfterCastUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Functions">
        <file baseinstalldir="PHP" name="CallTimePassByReferenceUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="CallTimePassByReferenceUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="FunctionCallArgumentSpacingUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="FunctionCallArgumentSpacingUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="OpeningFunctionBraceBsdAllmanUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="OpeningFunctionBraceBsdAllmanUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="OpeningFunctionBraceKernighanRitchieUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="OpeningFunctionBraceKernighanRitchieUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Metrics">
        <file baseinstalldir="PHP" name="CyclomaticComplexityUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="CyclomaticComplexityUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="NestingLevelUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="NestingLevelUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="NamingConventions">
        <file baseinstalldir="PHP" name="CamelCapsFunctionNameUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="CamelCapsFunctionNameUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ConstructorNameUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ConstructorNameUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="UpperCaseConstantNameUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="UpperCaseConstantNameUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="PHP">
        <file baseinstalldir="PHP" name="CharacterBeforePHPOpeningTagUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="CharacterBeforePHPOpeningTagUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ClosingPHPTagUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ClosingPHPTagUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DisallowShortOpenTagUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="DisallowShortOpenTagUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ForbiddenFunctionsUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ForbiddenFunctionsUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="LowerCaseConstantUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="LowerCaseConstantUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="LowerCaseConstantUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="LowerCaseKeywordUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="LowerCaseKeywordUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="NoSilencedErrorsUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="NoSilencedErrorsUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="SAPIUsageUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="SAPIUsageUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="UpperCaseConstantUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="UpperCaseConstantUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Strings">
        <file baseinstalldir="PHP" name="UnnecessaryStringConcatUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="UnnecessaryStringConcatUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="UnnecessaryStringConcatUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="WhiteSpace">
        <file baseinstalldir="PHP" name="DisallowSpaceIndentUnitTest.css" role="test" />
        <file baseinstalldir="PHP" name="DisallowSpaceIndentUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="DisallowSpaceIndentUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="DisallowSpaceIndentUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DisallowTabIndentUnitTest.css" role="test" />
        <file baseinstalldir="PHP" name="DisallowTabIndentUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="DisallowTabIndentUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="DisallowTabIndentUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ScopeIndentUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ScopeIndentUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
      </dir>
      <file baseinstalldir="PHP" name="ruleset.xml" role="php" />
     </dir>
     <dir name="MySource">
      <dir name="Sniffs">
       <dir name="Channels">
        <file baseinstalldir="PHP" name="ChannelExceptionSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DisallowSelfActionsSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="IncludeOwnSystemSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="IncludeSystemSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="UnusedSystemSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Commenting">
        <file baseinstalldir="PHP" name="FunctionCommentSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="CSS">
        <file baseinstalldir="PHP" name="BrowserSpecificStylesSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Debug">
        <file baseinstalldir="PHP" name="DebugCodeSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="FirebugConsoleSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Objects">
        <file baseinstalldir="PHP" name="AssignThisSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="CreateWidgetTypeCallbackSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DisallowNewWidgetSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="PHP">
        <file baseinstalldir="PHP" name="AjaxNullComparisonSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="EvalObjectFactorySniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="GetRequestDataSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ReturnFunctionValueSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Strings">
        <file baseinstalldir="PHP" name="JoinStringsSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
      </dir>
      <dir name="Tests">
       <dir name="Channels">
        <file baseinstalldir="PHP" name="DisallowSelfActionsUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="DisallowSelfActionsUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="IncludeSystemUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="IncludeSystemUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="UnusedSystemUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="UnusedSystemUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Commenting">
        <file baseinstalldir="PHP" name="FunctionCommentUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="FunctionCommentUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="CSS">
        <file baseinstalldir="PHP" name="BrowserSpecificStylesUnitTest.css" role="test" />
        <file baseinstalldir="PHP" name="BrowserSpecificStylesUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Debug">
        <file baseinstalldir="PHP" name="DebugCodeUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="DebugCodeUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="FirebugConsoleUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="FirebugConsoleUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Objects">
        <file baseinstalldir="PHP" name="AssignThisUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="AssignThisUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="CreateWidgetTypeCallbackUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="CreateWidgetTypeCallbackUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DisallowNewWidgetUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="DisallowNewWidgetUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="PHP">
        <file baseinstalldir="PHP" name="AjaxNullComparisonUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="AjaxNullComparisonUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="EvalObjectFactoryUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="EvalObjectFactoryUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="GetRequestDataUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="GetRequestDataUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ReturnFunctionValueUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ReturnFunctionValueUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Strings">
        <file baseinstalldir="PHP" name="JoinStringsUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="JoinStringsUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
      </dir>
      <file baseinstalldir="PHP" name="ruleset.xml" role="php" />
     </dir>
     <dir name="PEAR">
      <dir name="Docs">
       <dir name="Classes">
        <file baseinstalldir="PHP" name="ClassDeclarationStandard.xml" role="php" />
       </dir>
       <dir name="Commenting">
        <file baseinstalldir="PHP" name="ClassCommentStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="FileCommentStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="FunctionCommentStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="InlineCommentStandard.xml" role="php" />
       </dir>
       <dir name="ControlStructures">
        <file baseinstalldir="PHP" name="ControlSignatureStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="MultiLineConditionStandard.xml" role="php" />
       </dir>
       <dir name="Files">
        <file baseinstalldir="PHP" name="IncludingFileStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="LineLengthStandard.xml" role="php" />
       </dir>
       <dir name="Formatting">
        <file baseinstalldir="PHP" name="MultiLineAssignmentStandard.xml" role="php" />
       </dir>
       <dir name="Functions">
        <file baseinstalldir="PHP" name="FunctionCallSignatureStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="FunctionDeclarationStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="ValidDefaultValueStandard.xml" role="php" />
       </dir>
       <dir name="NamingConventions">
        <file baseinstalldir="PHP" name="ValidClassNameStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="ValidFunctionNameStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="ValidVariableNameStandard.xml" role="php" />
       </dir>
       <dir name="WhiteSpace">
        <file baseinstalldir="PHP" name="ScopeClosingBraceStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="ScopeIndentStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="ObjectOperatorIndentStandard.xml" role="php" />
       </dir>
      </dir>
      <dir name="Sniffs">
       <dir name="Classes">
        <file baseinstalldir="PHP" name="ClassDeclarationSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Commenting">
        <file baseinstalldir="PHP" name="ClassCommentSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="FileCommentSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="FunctionCommentSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="InlineCommentSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="ControlStructures">
        <file baseinstalldir="PHP" name="ControlSignatureSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="MultiLineConditionSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Files">
        <file baseinstalldir="PHP" name="IncludingFileSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Formatting">
        <file baseinstalldir="PHP" name="MultiLineAssignmentSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Functions">
        <file baseinstalldir="PHP" name="FunctionCallSignatureSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="FunctionDeclarationSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ValidDefaultValueSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="NamingConventions">
        <file baseinstalldir="PHP" name="ValidClassNameSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ValidFunctionNameSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ValidVariableNameSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="WhiteSpace">
        <file baseinstalldir="PHP" name="ObjectOperatorIndentSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ScopeClosingBraceSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ScopeIndentSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
      </dir>
      <dir name="Tests">
       <dir name="Classes">
        <file baseinstalldir="PHP" name="ClassDeclarationUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ClassDeclarationUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Commenting">
        <file baseinstalldir="PHP" name="ClassCommentUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ClassCommentUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="FileCommentUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="FileCommentUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="FunctionCommentUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="FunctionCommentUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="InlineCommentUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="InlineCommentUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="ControlStructures">
        <file baseinstalldir="PHP" name="ControlSignatureUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ControlSignatureUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="MultiLineConditionUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="MultiLineConditionUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Files">
        <file baseinstalldir="PHP" name="IncludingFileUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="IncludingFileUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Formatting">
        <file baseinstalldir="PHP" name="MultiLineAssignmentUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="MultiLineAssignmentUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Functions">
        <file baseinstalldir="PHP" name="FunctionCallSignatureUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="FunctionCallSignatureUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="FunctionDeclarationUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="FunctionDeclarationUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ValidDefaultValueUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ValidDefaultValueUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="NamingConventions">
        <file baseinstalldir="PHP" name="ValidClassNameUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ValidClassNameUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ValidFunctionNameUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ValidFunctionNameUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ValidVariableNameUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ValidVariableNameUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="WhiteSpace">
        <file baseinstalldir="PHP" name="ObjectOperatorIndentUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ObjectOperatorIndentUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ScopeClosingBraceUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ScopeClosingBraceUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ScopeIndentUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ScopeIndentUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
      </dir>
      <file baseinstalldir="PHP" name="ruleset.xml" role="php" />
     </dir>
     <dir name="PHPCS">
      <file baseinstalldir="PHP" name="ruleset.xml" role="php" />
     </dir>
     <dir name="PSR1">
      <dir name="Docs">
       <dir name="Classes">
        <file baseinstalldir="PHP" name="ClassDeclarationStandard.xml" role="php" />
       </dir>
       <dir name="Files">
        <file baseinstalldir="PHP" name="SideEffectsStandard.xml" role="php" />
       </dir>
      </dir>
      <dir name="Sniffs">
       <dir name="Classes">
        <file baseinstalldir="PHP" name="ClassDeclarationSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Files">
        <file baseinstalldir="PHP" name="SideEffectsSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Methods">
        <file baseinstalldir="PHP" name="CamelCapsMethodNameSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
      </dir>
      <dir name="Tests">
       <dir name="Classes">
        <file baseinstalldir="PHP" name="ClassDeclarationUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ClassDeclarationUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Files">
        <file baseinstalldir="PHP" name="SideEffectsUnitTest.1.inc" role="test" />
        <file baseinstalldir="PHP" name="SideEffectsUnitTest.2.inc" role="test" />
        <file baseinstalldir="PHP" name="SideEffectsUnitTest.3.inc" role="test" />
        <file baseinstalldir="PHP" name="SideEffectsUnitTest.4.inc" role="test" />
        <file baseinstalldir="PHP" name="SideEffectsUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Methods">
        <file baseinstalldir="PHP" name="CamelCapsMethodNameUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="CamelCapsMethodNameUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
      </dir>
      <file baseinstalldir="PHP" name="ruleset.xml" role="php" />
     </dir>
     <dir name="PSR2">
      <dir name="Docs">
       <dir name="Classes">
        <file baseinstalldir="PHP" name="ClassDeclarationStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="PropertyDeclarationStandard.xml" role="php" />
       </dir>
       <dir name="ControlStructures">
        <file baseinstalldir="PHP" name="ControlStructureSpacingStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="ElseIfDeclarationStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="SwitchDeclarationStandard.xml" role="php" />
       </dir>
       <dir name="Files">
        <file baseinstalldir="PHP" name="EndFileNewlineStandard.xml" role="php" />
       </dir>
       <dir name="Methods">
        <file baseinstalldir="PHP" name="MethodDeclarationStandard.xml" role="php" />
       </dir>
       <dir name="Namespaces">
        <file baseinstalldir="PHP" name="NamespaceDeclarationStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="UseDeclarationStandard.xml" role="php" />
       </dir>
      </dir>
      <dir name="Sniffs">
       <dir name="Classes">
        <file baseinstalldir="PHP" name="ClassDeclarationSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="PropertyDeclarationSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="ControlStructures">
        <file baseinstalldir="PHP" name="ControlStructureSpacingSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ElseIfDeclarationSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="SwitchDeclarationSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Files">
        <file baseinstalldir="PHP" name="EndFileNewlineSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Methods">
        <file baseinstalldir="PHP" name="FunctionCallSignatureSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="MethodDeclarationSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Namespaces">
        <file baseinstalldir="PHP" name="NamespaceDeclarationSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="UseDeclarationSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
      </dir>
      <dir name="Tests">
       <dir name="Classes">
        <file baseinstalldir="PHP" name="ClassDeclarationUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ClassDeclarationUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="PropertyDeclarationUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="PropertyDeclarationUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="ControlStructures">
        <file baseinstalldir="PHP" name="ControlStructureSpacingUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ControlStructureSpacingUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ElseIfDeclarationUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ElseIfDeclarationUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="SwitchDeclarationUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="SwitchDeclarationUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Files">
        <file baseinstalldir="PHP" name="EndFileNewlineUnitTest.1.inc" role="test" />
        <file baseinstalldir="PHP" name="EndFileNewlineUnitTest.2.inc" role="test" />
        <file baseinstalldir="PHP" name="EndFileNewlineUnitTest.3.inc" role="test" />
        <file baseinstalldir="PHP" name="EndFileNewlineUnitTest.4.inc" role="test" />
        <file baseinstalldir="PHP" name="EndFileNewlineUnitTest.5.inc" role="test" />
        <file baseinstalldir="PHP" name="EndFileNewlineUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Methods">
        <file baseinstalldir="PHP" name="FunctionCallSignatureUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="FunctionCallSignatureUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="MethodDeclarationUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="MethodDeclarationUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Namespaces">
        <file baseinstalldir="PHP" name="NamespaceDeclarationUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="NamespaceDeclarationUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="UseDeclarationUnitTest.1.inc" role="test" />
        <file baseinstalldir="PHP" name="UseDeclarationUnitTest.2.inc" role="test" />
        <file baseinstalldir="PHP" name="UseDeclarationUnitTest.3.inc" role="test" />
        <file baseinstalldir="PHP" name="UseDeclarationUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
      </dir>
      <file baseinstalldir="PHP" name="ruleset.xml" role="php" />
     </dir>
     <dir name="Squiz">
      <dir name="Docs">
       <dir name="Arrays">
        <file baseinstalldir="PHP" name="ArrayBracketSpacingStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="ArrayDeclarationStandard.xml" role="php" />
       </dir>
       <dir name="Classes">
        <file baseinstalldir="PHP" name="LowercaseClassKeywordsStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="SelfMemberReferenceStandard.xml" role="php" />
       </dir>
       <dir name="Commenting">
        <file baseinstalldir="PHP" name="DocCommentAlignmentStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="FunctionCommentThrowTagStandard.xml" role="php" />
       </dir>
       <dir name="ControlStructures">
        <file baseinstalldir="PHP" name="ForEachLoopDeclarationStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="ForLoopDeclarationStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="LowercaseDeclarationStandard.xml" role="php" />
       </dir>
       <dir name="Functions">
        <file baseinstalldir="PHP" name="FunctionDuplicateArgumentStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="LowercaseFunctionKeywordsStandard.xml" role="php" />
       </dir>
       <dir name="Scope">
        <file baseinstalldir="PHP" name="StaticThisUsageStandard.xml" role="php" />
       </dir>
       <dir name="Strings">
        <file baseinstalldir="PHP" name="EchoedStringsStandard.xml" role="php" />
       </dir>
       <dir name="WhiteSpace">
        <file baseinstalldir="PHP" name="CastSpacingStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="FunctionOpeningBraceStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="LanguageConstructSpacingStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="ObjectOperatorSpacingStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="ScopeKeywordSpacingStandard.xml" role="php" />
        <file baseinstalldir="PHP" name="SemicolonSpacingStandard.xml" role="php" />
       </dir>
      </dir>
      <dir name="Sniffs">
       <dir name="Arrays">
        <file baseinstalldir="PHP" name="ArrayBracketSpacingSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ArrayDeclarationSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Classes">
        <file baseinstalldir="PHP" name="ClassDeclarationSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ClassFileNameSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DuplicatePropertySniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="LowercaseClassKeywordsSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="SelfMemberReferenceSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ValidClassNameSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="CodeAnalysis">
        <file baseinstalldir="PHP" name="EmptyStatementSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Commenting">
        <file baseinstalldir="PHP" name="BlockCommentSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ClassCommentSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ClosingDeclarationCommentSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DocCommentAlignmentSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="EmptyCatchCommentSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="FileCommentSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="FunctionCommentThrowTagSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="FunctionCommentSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="InlineCommentSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="LongConditionClosingCommentSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="PostStatementCommentSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="VariableCommentSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="ControlStructures">
        <file baseinstalldir="PHP" name="ControlSignatureSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ElseIfDeclarationSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ForEachLoopDeclarationSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ForLoopDeclarationSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="InlineIfDeclarationSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="LowercaseDeclarationSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="SwitchDeclarationSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="CSS">
        <file baseinstalldir="PHP" name="ClassDefinitionClosingBraceSpaceSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ClassDefinitionNameSpacingSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ClassDefinitionOpeningBraceSpaceSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ColonSpacingSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ColourDefinitionSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DisallowMultipleStyleDefinitionsSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DuplicateClassDefinitionSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DuplicateStyleDefinitionSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="EmptyClassDefinitionSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="EmptyStyleDefinitionSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ForbiddenStylesSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="IndentationSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="LowercaseStyleDefinitionSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="MissingColonSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="NamedColoursSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="OpacitySniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="SemicolonSpacingSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ShorthandSizeSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Debug">
        <file baseinstalldir="PHP" name="JavaScriptLintSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="JSLintSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Files">
        <file baseinstalldir="PHP" name="FileExtensionSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Formatting">
        <file baseinstalldir="PHP" name="OperatorBracketSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Functions">
        <file baseinstalldir="PHP" name="FunctionDeclarationArgumentSpacingSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="FunctionDeclarationSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="FunctionDuplicateArgumentSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="GlobalFunctionSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="LowercaseFunctionKeywordsSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="MultiLineFunctionDeclarationSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="NamingConventions">
        <file baseinstalldir="PHP" name="ConstantCaseSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ValidFunctionNameSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ValidVariableNameSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Objects">
        <file baseinstalldir="PHP" name="DisallowObjectStringIndexSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ObjectInstantiationSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ObjectMemberCommaSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Operators">
        <file baseinstalldir="PHP" name="ComparisonOperatorUsageSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="IncrementDecrementUsageSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ValidLogicalOperatorsSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="PHP">
        <file baseinstalldir="PHP" name="CommentedOutCodeSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DisallowBooleanStatementSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DisallowComparisonAssignmentSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DisallowInlineIfSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DisallowMultipleAssignmentsSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DisallowObEndFlushSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DisallowSizeFunctionsInLoopsSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DiscouragedFunctionsSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="EmbeddedPhpSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="EvalSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ForbiddenFunctionsSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="GlobalKeywordSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="HeredocSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="InnerFunctionsSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="LowercasePHPFunctionsSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="NonExecutableCodeSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Scope">
        <file baseinstalldir="PHP" name="MemberVarScopeSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="MethodScopeSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="StaticThisUsageSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Strings">
        <file baseinstalldir="PHP" name="ConcatenationSpacingSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DoubleQuoteUsageSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="EchoedStringsSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="WhiteSpace">
        <file baseinstalldir="PHP" name="CastSpacingSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ControlStructureSpacingSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="FunctionClosingBraceSpaceSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="FunctionOpeningBraceSpaceSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="FunctionSpacingSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="LanguageConstructSpacingSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="LogicalOperatorSpacingSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="MemberVarSpacingSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ObjectOperatorSpacingSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="OperatorSpacingSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="PropertyLabelSpacingSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ScopeClosingBraceSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ScopeKeywordSpacingSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="SemicolonSpacingSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="SuperfluousWhitespaceSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
      </dir>
      <dir name="Tests">
       <dir name="Arrays">
        <file baseinstalldir="PHP" name="ArrayBracketSpacingUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ArrayBracketSpacingUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ArrayDeclarationUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ArrayDeclarationUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Classes">
        <file baseinstalldir="PHP" name="ClassDeclarationUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ClassDeclarationUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ClassFileNameUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ClassFileNameUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DuplicatePropertyUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="DuplicatePropertyUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="LowercaseClassKeywordsUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="LowercaseClassKeywordsUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="SelfMemberReferenceUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="SelfMemberReferenceUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ValidClassNameUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ValidClassNameUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="CodeAnalysis">
        <file baseinstalldir="PHP" name="EmptyStatementUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="EmptyStatementUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Commenting">
        <file baseinstalldir="PHP" name="BlockCommentUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="BlockCommentUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ClassCommentUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ClassCommentUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ClosingDeclarationCommentUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ClosingDeclarationCommentUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DocCommentAlignmentUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="DocCommentAlignmentUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="EmptyCatchCommentUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="EmptyCatchCommentUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="FileCommentUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="FileCommentUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="FileCommentUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="FunctionCommentThrowTagUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="FunctionCommentThrowTagUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="FunctionCommentUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="FunctionCommentUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="InlineCommentUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="InlineCommentUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="InlineCommentUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="LongConditionClosingCommentUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="LongConditionClosingCommentUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="LongConditionClosingCommentUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="PostStatementCommentUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="PostStatementCommentUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="PostStatementCommentUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="VariableCommentUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="VariableCommentUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="ControlStructures">
        <file baseinstalldir="PHP" name="ControlSignatureUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ControlSignatureUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="ControlSignatureUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ElseIfDeclarationUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ElseIfDeclarationUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ForEachLoopDeclarationUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ForEachLoopDeclarationUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ForLoopDeclarationUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ForLoopDeclarationUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="ForLoopDeclarationUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="InlineIfDeclarationUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="InlineIfDeclarationUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="LowercaseDeclarationUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="LowercaseDeclarationUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="SwitchDeclarationUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="SwitchDeclarationUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="SwitchDeclarationUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="CSS">
        <file baseinstalldir="PHP" name="ClassDefinitionClosingBraceSpaceUnitTest.css" role="test" />
        <file baseinstalldir="PHP" name="ClassDefinitionClosingBraceSpaceUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ClassDefinitionNameSpacingUnitTest.css" role="test" />
        <file baseinstalldir="PHP" name="ClassDefinitionNameSpacingUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ClassDefinitionOpeningBraceSpaceUnitTest.css" role="test" />
        <file baseinstalldir="PHP" name="ClassDefinitionOpeningBraceSpaceUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ColonSpacingUnitTest.css" role="test" />
        <file baseinstalldir="PHP" name="ColonSpacingUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ColourDefinitionUnitTest.css" role="test" />
        <file baseinstalldir="PHP" name="ColourDefinitionUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DisallowMultipleStyleDefinitionsUnitTest.css" role="test" />
        <file baseinstalldir="PHP" name="DisallowMultipleStyleDefinitionsUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DuplicateClassDefinitionUnitTest.css" role="test" />
        <file baseinstalldir="PHP" name="DuplicateClassDefinitionUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DuplicateStyleDefinitionUnitTest.css" role="test" />
        <file baseinstalldir="PHP" name="DuplicateStyleDefinitionUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="EmptyClassDefinitionUnitTest.css" role="test" />
        <file baseinstalldir="PHP" name="EmptyClassDefinitionUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="EmptyStyleDefinitionUnitTest.css" role="test" />
        <file baseinstalldir="PHP" name="EmptyStyleDefinitionUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ForbiddenStylesUnitTest.css" role="test" />
        <file baseinstalldir="PHP" name="ForbiddenStylesUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="IndentationUnitTest.css" role="test" />
        <file baseinstalldir="PHP" name="IndentationUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="LowercaseStyleDefinitionUnitTest.css" role="test" />
        <file baseinstalldir="PHP" name="LowercaseStyleDefinitionUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="MissingColonUnitTest.css" role="test" />
        <file baseinstalldir="PHP" name="MissingColonUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="NamedColoursUnitTest.css" role="test" />
        <file baseinstalldir="PHP" name="NamedColoursUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="OpacityUnitTest.css" role="test" />
        <file baseinstalldir="PHP" name="OpacityUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="SemicolonSpacingUnitTest.css" role="test" />
        <file baseinstalldir="PHP" name="SemicolonSpacingUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ShorthandSizeUnitTest.css" role="test" />
        <file baseinstalldir="PHP" name="ShorthandSizeUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Debug">
        <file baseinstalldir="PHP" name="JavaScriptLintUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="JavaScriptLintUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="JSLintUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="JSLintUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Files">
        <file baseinstalldir="PHP" name="FileExtensionUnitTest.1.inc" role="test" />
        <file baseinstalldir="PHP" name="FileExtensionUnitTest.2.inc" role="test" />
        <file baseinstalldir="PHP" name="FileExtensionUnitTest.3.inc" role="test" />
        <file baseinstalldir="PHP" name="FileExtensionUnitTest.4.inc" role="test" />
        <file baseinstalldir="PHP" name="FileExtensionUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Formatting">
        <file baseinstalldir="PHP" name="OperatorBracketUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="OperatorBracketUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="OperatorBracketUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Functions">
        <file baseinstalldir="PHP" name="FunctionDeclarationArgumentSpacingUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="FunctionDeclarationArgumentSpacingUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="FunctionDeclarationUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="FunctionDeclarationUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="FunctionDuplicateArgumentUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="FunctionDuplicateArgumentUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="GlobalFunctionUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="GlobalFunctionUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="LowercaseFunctionKeywordsUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="LowercaseFunctionKeywordsUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="MultiLineFunctionDeclarationUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="MultiLineFunctionDeclarationUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="NamingConventions">
        <file baseinstalldir="PHP" name="ConstantCaseUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ConstantCaseUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="ConstantCaseUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ValidFunctionNameUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ValidFunctionNameUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ValidVariableNameUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ValidVariableNameUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Objects">
        <file baseinstalldir="PHP" name="DisallowObjectStringIndexUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="DisallowObjectStringIndexUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ObjectInstantiationUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ObjectInstantiationUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ObjectMemberCommaUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="ObjectMemberCommaUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Operators">
        <file baseinstalldir="PHP" name="ComparisonOperatorUsageUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ComparisonOperatorUsageUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="ComparisonOperatorUsageUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="IncrementDecrementUsageUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="IncrementDecrementUsageUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ValidLogicalOperatorsUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ValidLogicalOperatorsUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="PHP">
        <file baseinstalldir="PHP" name="CommentedOutCodeUnitTest.css" role="test" />
        <file baseinstalldir="PHP" name="CommentedOutCodeUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="CommentedOutCodeUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DisallowBooleanStatementUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="DisallowBooleanStatementUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DisallowComparisonAssignmentUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="DisallowComparisonAssignmentUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DisallowInlineIfUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="DisallowInlineIfUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="DisallowInlineIfUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DisallowMultipleAssignmentsUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="DisallowMultipleAssignmentsUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DisallowObEndFlushUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="DisallowObEndFlushUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DisallowSizeFunctionsInLoopsUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="DisallowSizeFunctionsInLoopsUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="DisallowSizeFunctionsInLoopsUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DiscouragedFunctionsUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="DiscouragedFunctionsUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="EmbeddedPhpUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="EmbeddedPhpUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="EvalUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="EvalUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ForbiddenFunctionsUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ForbiddenFunctionsUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="GlobalKeywordUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="GlobalKeywordUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="HeredocUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="HeredocUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="InnerFunctionsUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="InnerFunctionsUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="LowercasePHPFunctionsUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="LowercasePHPFunctionsUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="NonExecutableCodeUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="NonExecutableCodeUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Scope">
        <file baseinstalldir="PHP" name="MemberVarScopeUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="MemberVarScopeUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="MethodScopeUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="MethodScopeUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="StaticThisUsageUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="StaticThisUsageUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Strings">
        <file baseinstalldir="PHP" name="ConcatenationSpacingUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ConcatenationSpacingUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="DoubleQuoteUsageUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="DoubleQuoteUsageUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="EchoedStringsUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="EchoedStringsUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="WhiteSpace">
        <file baseinstalldir="PHP" name="CastSpacingUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="CastSpacingUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ControlStructureSpacingUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ControlStructureSpacingUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="ControlStructureSpacingUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="FunctionClosingBraceSpaceUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="FunctionClosingBraceSpaceUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="FunctionClosingBraceSpaceUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="FunctionOpeningBraceSpaceUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="FunctionOpeningBraceSpaceUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="FunctionOpeningBraceSpaceUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="FunctionSpacingUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="FunctionSpacingUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="LanguageConstructSpacingUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="LanguageConstructSpacingUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="LogicalOperatorSpacingUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="LogicalOperatorSpacingUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="LogicalOperatorSpacingUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="MemberVarSpacingUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="MemberVarSpacingUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ObjectOperatorSpacingUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ObjectOperatorSpacingUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="OperatorSpacingUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="OperatorSpacingUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="OperatorSpacingUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="PropertyLabelSpacingUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="PropertyLabelSpacingUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ScopeClosingBraceUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ScopeClosingBraceUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="ScopeKeywordSpacingUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ScopeKeywordSpacingUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="SemicolonSpacingUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="SemicolonSpacingUnitTest.js" role="test" />
        <file baseinstalldir="PHP" name="SemicolonSpacingUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
        <file baseinstalldir="PHP" name="SuperfluousWhitespaceUnitTest.1.css" role="test" />
        <file baseinstalldir="PHP" name="SuperfluousWhitespaceUnitTest.1.js" role="test" />
        <file baseinstalldir="PHP" name="SuperfluousWhitespaceUnitTest.2.css" role="test" />
        <file baseinstalldir="PHP" name="SuperfluousWhitespaceUnitTest.2.js" role="test" />
        <file baseinstalldir="PHP" name="SuperfluousWhitespaceUnitTest.3.css" role="test" />
        <file baseinstalldir="PHP" name="SuperfluousWhitespaceUnitTest.3.js" role="test" />
        <file baseinstalldir="PHP" name="SuperfluousWhitespaceUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="SuperfluousWhitespaceUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
      </dir>
      <file baseinstalldir="PHP" name="ruleset.xml" role="php" />
     </dir>
     <dir name="Zend">
      <dir name="Docs">
       <dir name="Debug">
        <file baseinstalldir="PHP" name="CodeAnalyzerStandard.xml" role="php" />
       </dir>
       <dir name="Files">
        <file baseinstalldir="PHP" name="ClosingTagStandard.xml" role="php" />
       </dir>
       <dir name="NamingConventions">
        <file baseinstalldir="PHP" name="ValidVariableNameStandard.xml" role="php" />
       </dir>
      </dir>
      <dir name="Sniffs">
       <dir name="Debug">
        <file baseinstalldir="PHP" name="CodeAnalyzerSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Files">
        <file baseinstalldir="PHP" name="ClosingTagSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="NamingConventions">
        <file baseinstalldir="PHP" name="ValidVariableNameSniff.php" role="php">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
      </dir>
      <dir name="Tests">
       <dir name="Debug">
        <file baseinstalldir="PHP" name="CodeAnalyzerUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="CodeAnalyzerUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="Files">
        <file baseinstalldir="PHP" name="ClosingTagUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ClosingTagUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
       <dir name="NamingConventions">
        <file baseinstalldir="PHP" name="ValidVariableNameUnitTest.inc" role="test" />
        <file baseinstalldir="PHP" name="ValidVariableNameUnitTest.php" role="test">
         <tasks:replace from="@package_version@" to="version" type="package-info" />
        </file>
       </dir>
      </dir>
      <file baseinstalldir="PHP" name="ruleset.xml" role="php" />
     </dir>
     <file baseinstalldir="PHP" name="AbstractPatternSniff.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="AbstractScopeSniff.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="AbstractVariableSniff.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="IncorrectPatternException.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
    </dir>
    <dir name="Tokenizers">
     <file baseinstalldir="PHP" name="CSS.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="JS.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
     <file baseinstalldir="PHP" name="PHP.php" role="php">
      <tasks:replace from="@package_version@" to="version" type="package-info" />
     </file>
    </dir>
    <file baseinstalldir="PHP" name="CLI.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
    <file baseinstalldir="PHP" name="Exception.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
    <file baseinstalldir="PHP" name="File.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
    <file baseinstalldir="PHP" name="Report.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
    <file baseinstalldir="PHP" name="Reporting.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
    <file baseinstalldir="PHP" name="Sniff.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
    <file baseinstalldir="PHP" name="Tokens.php" role="php">
     <tasks:replace from="@package_version@" to="version" type="package-info" />
    </file>
   </dir>
  </dir>
 </contents>
 <dependencies>
  <required>
   <php>
    <min>5.1.2</min>
   </php>
   <pearinstaller>
    <min>1.4.0b1</min>
   </pearinstaller>
  </required>
  <optional>
   <package>
    <name>PHP_Timer</name>
    <channel>pear.phpunit.de</channel>
   </package>
  </optional>
 </dependencies>
 <phprelease>
  <installconditions>
   <os>
    <name>windows</name>
   </os>
  </installconditions>
  <filelist>
   <install as="phpcs" name="scripts/phpcs" />
   <install as="phpcs.bat" name="scripts/phpcs.bat" />
   <install as="AllTests.php" name="tests/AllTests.php" />
   <install as="TestSuite.php" name="tests/TestSuite.php" />
   <install as="CodeSniffer/Core/AllTests.php" name="tests/Core/AllTests.php" />
   <install as="CodeSniffer/Core/IsCamelCapsTest.php" name="tests/Core/IsCamelCapsTest.php" />
   <install as="CodeSniffer/Core/ErrorSuppressionTest.php" name="tests/Core/ErrorSuppressionTest.php" />
   <install as="CodeSniffer/Core/File/GetMethodParametersTest.php" name="tests/Core/File/GetMethodParametersTest.php" />
   <install as="CodeSniffer/Standards/AllSniffs.php" name="tests/Standards/AllSniffs.php" />
   <install as="CodeSniffer/Standards/AbstractSniffUnitTest.php" name="tests/Standards/AbstractSniffUnitTest.php" />
  </filelist>
 </phprelease>
 <phprelease>
  <filelist>
   <install as="phpcs" name="scripts/phpcs" />
   <install as="AllTests.php" name="tests/AllTests.php" />
   <install as="TestSuite.php" name="tests/TestSuite.php" />
   <install as="CodeSniffer/Core/AllTests.php" name="tests/Core/AllTests.php" />
   <install as="CodeSniffer/Core/IsCamelCapsTest.php" name="tests/Core/IsCamelCapsTest.php" />
   <install as="CodeSniffer/Core/ErrorSuppressionTest.php" name="tests/Core/ErrorSuppressionTest.php" />
   <install as="CodeSniffer/Core/File/GetMethodParametersTest.php" name="tests/Core/File/GetMethodParametersTest.php" />
   <install as="CodeSniffer/Standards/AllSniffs.php" name="tests/Standards/AllSniffs.php" />
   <install as="CodeSniffer/Standards/AbstractSniffUnitTest.php" name="tests/Standards/AbstractSniffUnitTest.php" />
   <ignore name="scripts/phpcs.bat" />
  </filelist>
 </phprelease>
 <changelog>
  <release>
   <version>
    <release>1.5.0</release>
    <api>1.5.0R</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2013-11-28</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Doc generation is now working again for installed standards
      -- Includes a fix for limiting the docs to specific sniffs
    - Generic ScopeIndentSniff now allows for ignored tokens to be set via ruleset.xml files
      -- E.g., to ignore comments, override a property using:
      -- name="ignoreIndentationTokens" type="array" value="T_COMMENT,T_DOC_COMMENT"
    - PSR2 standard now ignores comments when checking indentation rules
    - Generic UpperCaseConstantNameSniff no longer reports errors where constants are used (request #20090)
      -- It still reports errors where constants are defined
    - Individual messages can now be excluded in ruleset.xml files using the exclude tag (request #20091)
      -- Setting message severity to 0 continues to be supported
    - Squiz OperatorSpacingSniff no longer throws errors for the ?: short ternary operator
      -- Thanks to Antoine Musso for the patch
    - Comment parser now supports non-English characters when splitting comment lines into words
      -- Thanks to Nik Sun for the patch
    - Exit statements are now recognised as valid closers for CASE and DEFAULT blocks
      -- Thanks to Maksim Kochkin for the patch
    - PHP_CodeSniffer_CLI::process() can now be passed an incomplete array of CLI values
      -- Missing values will be set to the CLI defaults
      -- Thanks to Maksim Kochkin for the patch
    - Fixed bug #20093 : Bug with ternary operator token
    - Fixed bug #20097 : CLI.php throws error in php 5.2
    - Fixed bug #20100 : incorrect Function mysql() has been deprecated report
    - Fixed bug #20119 : PHP warning: invalid argument to str_repeat() in SVN blame report with -s
    - Fixed bug #20123 : PSR2 complains about an empty second statement in for-loop
    - Fixed bug #20131 : PHP errors in svnblame report, if there are files not under version control
    - Fixed bug #20133 : Allow "HG: hg_id" as value for @version tag
   </notes>
  </release>
  <release>
   <version>
    <release>1.5.0RC4</release>
    <api>1.5.0RC4</api>
   </version>
   <stability>
    <release>beta</release>
    <api>beta</api>
   </stability>
   <date>2013-09-26</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - You can now restrict violations to individual sniff codes using the --sniffs command line argument
     -- Previously, this only restricted violations to an entire sniff and not individual messages
     -- If you have scripts calling PHP_CodeSniffer::process() or creating PHP_CodeSniffer_File objects, you must update your code
     -- The array of restrictions passed to PHP_CodeSniffer::process() must now be an array of sniff codes instead of class names
     -- The PHP_CodeSniffer_File::__construct() method now requires an array of restrictions to be passed
    - Doc generation is now working again
    - Progress information now shows the percentage complete at the end of each line
    - Added report type --report=junit to show the error list in a JUnit compatible format
      -- Thanks to Oleg Lobach for the contribution
    - Added support for the PHP 5.4 callable type hint
    - Fixed problem where some file content could be ignored when checking STDIN
    - Version information is now printed when installed via composer or run from a Git clone (request #20050)
    - Added Squiz DisallowBooleanStatementSniff to ban boolean operators outside of control structure conditions
    - The CSS tokenizer is now more reliable when encountering 'list' and 'break' strings
    - Coding standard ignore comments can now appear instead doc blocks as well as inline comments
      -- Thanks to Stuart Langley for the patch
    - Generic LineLengthSniff now ignores SVN URL and Head URL comments
      -- Thanks to Karl DeBisschop for the patch
    - PEAR MultiLineConditionSniff now has a setting to specify how many spaces code should be indented
      -- Default remains at 4; override the 'indent' setting in a ruleset.xml file to change
      -- Thanks to Szabolcs Sulik for the patch
    - PEAR MultiLineAssignmentSniff now has a setting to specify how many spaces code should be indented
      -- Default remains at 4; override the 'indent' setting in a ruleset.xml file to change
      -- Thanks to Szabolcs Sulik for the patch
    - PEAR FunctionDeclarationSniff now has a setting to specify how many spaces code should be indented
      -- Default remains at 4; override the 'indent' setting in a ruleset.xml file to change
      -- Thanks to Szabolcs Sulik for the patch
    - Squiz SwitchDeclarationSniff now has a setting to specify how many spaces code should be indented
      -- Default remains at 4; override the 'indent' setting in a ruleset.xml file to change
      -- Thanks to Szabolcs Sulik for the patch
    - Squiz CSS IndentationSniff now has a setting to specify how many spaces code should be indented
      -- Default remains at 4; override the 'indent' setting in a ruleset.xml file to change
      -- Thanks to Hugo Fonseca for the patch
    - Squiz and MySource File and Function comment sniffs now allow all tags and don't require a particular licence
    - Squiz standard now allows lines to be 120 characters long before warning; up from 85
    - Squiz LowercaseStyleDefinitionSniff no longer throws errors for class names in nested style definitions
    - Squiz ClassFileNameSniff no longer throws errors when checking STDIN
    - Squiz CSS sniffs no longer generate errors for IE filters
    - Squiz CSS IndentationSniff no longer sees comments as blank lines
    - Squiz LogicalOperatorSpacingSniff now ignores whitespace at the end of a line
    - Squiz.Scope.MethodScope.Missing error message now mentions 'visibility' instead of 'scope modifier'
      -- Thanks to Renat Akhmedyanov for the patch
    - Added support for the PSR2 multi-line arguments errata
    - The PSR2 standard no longer throws errors for additional spacing after a type hint
    - PSR UseDeclarationSniff no longer throws errors for USE statements inside TRAITs
    - Fixed cases where code was incorrectly assigned the T_GOTO_LABEL token when used in a complex CASE condition
    - Fixed bug #20026 : Check for multi-line arrays that should be single-line is slightly wrong
      -- Adds new error message for single-line arrays that end with a comma
    - Fixed bug #20029 : ForbiddenFunction sniff incorrectly recognizes methods in USE clauses
    - Fixed bug #20043 : Mis-interpretation of Foo::class
    - Fixed bug #20044 : PSR1 camelCase check does not ignore leading underscores
    - Fixed bug #20045 : Errors about indentation for closures with multi-line 'use' in functions
    - Fixed bug #20051 : Undefined index: scope_opener / scope_closer
      -- Thanks to Anthon Pang for the patch
   </notes>
  </release>
  <release>
   <version>
    <release>1.5.0RC3</release>
    <api>1.5.0RC3</api>
   </version>
   <stability>
    <release>beta</release>
    <api>beta</api>
   </stability>
   <date>2013-07-25</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Added report type --report=json to show the error list and total counts for all checked files
      -- Thanks to Jeffrey Fisher for the contribution
    - PHP_CodeSniffer::isCamelCaps now allows for acronyms at the start of a string if the strict flag is FALSE
      -- acronyms are defined as at least 2 uppercase characters in a row
      -- e.g., the following is now valid camel caps with strict set to FALSE: XMLParser
    - The PHP tokenizer now tokenizes goto labels as T_GOTO_LABEL instead of T_STRING followed by T_COLON
    - The JS tokenizer now has support for the T_THROW token
    - Symlinked directories inside CodeSniffer/Standards and in ruleset.xml files are now supported
      -- Only available since PHP 5.2.11 and 5.3.1
      -- Thanks to Maik Penz for the patch
    - The JS tokenizer now correctly identifies T_INLINE_ELSE tokens instead of leaving them as T_COLON
      -- Thanks to Arnout Boks for the patch
    - Explaining a standard (phpcs -e) that uses namespaces now works correctly
    - Restricting a check to specific sniffs (phpcs --sniffs=...) now works correctly with namespaced sniffs
      -- Thanks to Maik Penz for the patch
    - Docs added for the entire Generic standard, and many sniffs from other standards are now documented as well
      -- Thanks to Spencer Rinehart for the contribution
    - Clearer error message for when the sniff class name does not match the directory structure
    - Generated HTML docs now correctly show the open PHP tag in code comparison blocks
    - Added Generic InlineHTMLSniff to ensure a file only contains PHP code
    - Added Squiz ShorthandSizeSniff to check that CSS sizes are using shorthand notation only when 1 or 2 values are used
    - Added Squiz ForbiddenStylesSniff to ban the use of some deprecated browser-specific styles
    - Added Squiz NamedColoursSniff to ban the use of colour names
    - PSR2 standard no longer enforces no whitespace between the closing parenthesis of a function call and the semicolon
    - PSR2 ClassDeclarationSniff now ignores empty classes when checking the end brace position
    - PSR2 SwitchDeclarationSniff no longer reports errors for empty lines between CASE statements
    - PEAR ObjectOperatorIndentSniff now has a setting to specify how many spaces code should be indented
      -- Default remains at 4; override the indent setting in a ruleset.xml file to change
      -- Thanks to Andrey Mindubaev for the patch
    - Squiz FileExtensionSniff now supports traits
      -- Thanks to Lucas Green for the patch
    - Squiz ArrayDeclarationSniff no longer reports errors for no comma at the end of a line that contains a function call
    - Squiz SwitchDeclarationSniff now supports T_CONTINUE and T_THROW as valid case/default breaking statements
    - Squiz CommentedOutCodeSniff is now better at ignoring commented out HTML, XML and regular expressions
    - Squiz DisallowComparisonAssignmentSniff no longer throws errors for the third expression in a FOR statement
    - Squiz ColourDefinitionSniff no longer throws errors for some CSS class names
    - Squiz ControlStructureSpacingSniff now supports all types of CASE/DEFAULT breaking statements
    - Generic CallTimePassByReferenceSniff now reports errors for functions called using a variable
      -- Thanks to Maik Penz for the patch
    - Generic ConstructorNameSniff no longer throws a notice for abstract constructors inside abstract classes
      -- Thanks to Spencer Rinehart for the patch
    - Squiz ComparisonOperatorUsageSniff now checks inside elseif statements
      -- Thanks to Arnout Boks for the patch
    - Squiz OperatorSpacingSniff now reports errors for no spacing around inline then and else tokens
      -- Thanks to Arnout Boks for the patch
    - Fixed bug #19811 : Comments not ignored in all cases in AbstractPatternSniff
      -- Thanks to Erik Wiffin for the patch
    - Fixed bug #19892 : ELSE with no braces causes incorrect SWITCH break statement indentation error
    - Fixed bug #19897 : Indenting warnings in templates not consistent
    - Fixed bug #19908 : PEAR MultiLineCondition Does Not Apply elseif
    - Fixed bug #19930 : option --report-file generate an empty file
    - Fixed bug #19935 : notify-send reports do not vanish in gnome-shell
      -- Thanks to Christian Weiske for the patch
    - Fixed bug #19944 : docblock squiz sniff "return void" trips over return in lambda function
    - Fixed bug #19953 : PSR2 - Spaces before interface name for abstract class
    - Fixed bug #19956 : phpcs warns for Type Hint missing Resource
    - Fixed bug #19957 : Does not understand trait method aliasing
    - Fixed bug #19968 : Permission denied on excluded directory
    - Fixed bug #19969 : Sniffs with namespace not recognized in reports
    - Fixed bug #19997 : Class names incorrectly detected as constants
   </notes>
  </release>
  <release>
   <version>
    <release>1.5.0RC2</release>
    <api>1.5.0RC2</api>
   </version>
   <stability>
    <release>beta</release>
    <api>beta</api>
   </stability>
   <date>2013-04-04</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Ruleset processing has been rewritten to be more predictable
      -- Provides much better support for relative paths inside ruleset files
      -- May mean that sniffs that were previously ignored are now being included when importing external rulesets
      -- Ruleset processing output can be seen by using the -vv command line argument
      -- Internal sniff registering functions have all changed, so please review custom scripts
    - You can now pass multiple coding standards on the command line, comma separated (request #19144)
      -- Works with built-in or custom standards and rulesets, or a mix of both
    - You can now exclude directories or whole standards in a ruleset XML file (request #19731)
      -- e.g., exclude "Generic.Commenting" or just "Generic"
      -- You can also pass in a path to a directory instead, if you know it
    - Added Generic LowerCaseKeywordSniff to ensure all PHP keywords are defined in lowercase
      -- The PSR2 and Squiz standards now use this sniff
    - Added Generic SAPIUsageSniff to ensure the PHP_SAPI constant is used instead of php_sapi_name() (request #19863)
    - Squiz FunctionSpacingSniff now has a setting to specify how many lines there should between functions (request #19843)
      -- Default remains at 2
      -- Override the "spacing" setting in a ruleset.xml file to change
    - Squiz LowercasePHPFunctionSniff no longer throws errors for the limited set of PHP keywords it was checking
      -- Add a rule for Generic.PHP.LowerCaseKeyword to your ruleset to replicate this functionality
    - Added support for the PHP 5.4 T_CALLABLE token so it can be used in lower PHP versions
    - Generic EndFileNoNewlineSniff now supports checking of CSS and JS files
    - PSR2 SwitchDeclarationSniff now has a setting to specify how many spaces code should be indented
      -- Default remains at 4; override the indent setting in a ruleset.xml file to change
      -- Thanks to Asher Snyder for the patch
    - Generic ScopeIndentSniff now has a setting to specify a list of tokens that should be ignored
      -- The first token on the line is checked and the whole line is ignored if the token is in the array
      -- Thanks to Eloy Lafuente for the patch
    - Squiz LowercaseClassKeywordsSniff now checks for the TRAIT keyword
      -- Thanks to Anthon Pang for the patch
    - If you create your own PHP_CodeSniffer object, PHPCS will no longer exit when an unknown argument is found
      -- This allows you to create wrapper scripts for PHPCS more easily
    - PSR2 MethodDeclarationSniff no longer generates a notice for methods named "_"
      -- Thanks to Bart S for the patch
    - Squiz BlockCommentSniff no longer reports that a blank line between a scope closer and block comment is invalid
    - Generic DuplicateClassNameSniff no longer reports an invalid error if multiple PHP open tags exist in a file
    - Generic DuplicateClassNameSniff no longer reports duplicate errors if multiple PHP open tags exist in a file
    - Fixed bug #19819 : Freeze with syntax error in use statement
    - Fixed bug #19820 : Wrong message level in Generic_Sniffs_CodeAnalysis_EmptyStatementSniff
    - Fixed bug #19859 : CodeSniffer::setIgnorePatterns API changed
    - Fixed bug #19871 : findExtendedClassName doesn't return FQCN on namespaced classes
    - Fixed bug #19879 : bitwise and operator interpreted as reference by value
   </notes>
  </release>
  <release>
   <version>
    <release>1.5.0RC1</release>
    <api>1.5.0RC1</api>
   </version>
   <stability>
    <release>beta</release>
    <api>beta</api>
   </stability>
   <date>2013-02-08</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Reports have been completely rewritten to consume far less memory
      -- Each report is incrementally written to the file system during a run and then printed out when the run ends
      -- There is no longer a need to keep the list of errors and warnings in memory during a run
    - Multi-file sniff support has been removed because they are too memory intensive
      -- If you have a custom multi-file sniff, you can convert it into a standard sniff quite easily
      -- See CodeSniffer/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.php for an example
    </notes>
  </release>
  <release>
   <version>
    <release>1.4.8</release>
    <api>1.4.8</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2013-11-26</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Generic ScopeIndentSniff now allows for ignored tokens to be set via ruleset.xml files
      -- E.g., to ignore comments, override a property using:
      -- name="ignoreIndentationTokens" type="array" value="T_COMMENT,T_DOC_COMMENT"
    - PSR2 standard now ignores comments when checking indentation rules
    - Squiz OperatorSpacingSniff no longer throws errors for the ?: short ternary operator
      -- Thanks to Antoine Musso for the patch
    - Comment parser now supports non-English characters when splitting comment lines into words
      -- Thanks to Nik Sun for the patch
    - Exit statements are now recognised as valid closers for CASE and DEFAULT blocks
      -- Thanks to Maksim Kochkin for the patch
    - PHP_CodeSniffer_CLI::process() can now be passed an incomplete array of CLI values
      -- Missing values will be set to the CLI defaults
      -- Thanks to Maksim Kochkin for the patch
    - Fixed bug #20097 : CLI.php throws error in php 5.2
    - Fixed bug #20100 : incorrect Function mysql() has been deprecated report
    - Fixed bug #20119 : PHP warning: invalid argument to str_repeat() in SVN blame report with -s
    - Fixed bug #20123 : PSR2 complains about an empty second statement in for-loop
    - Fixed bug #20131 : PHP errors in svnblame report, if there are files not under version control
    - Fixed bug #20133 : Allow "HG: hg_id" as value for @version tag
   </notes>
  </release>
  <release>
   <version>
    <release>1.4.7</release>
    <api>1.4.7</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2013-09-26</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Added report type --report=junit to show the error list in a JUnit compatible format
      -- Thanks to Oleg Lobach for the contribution
    - Added support for the PHP 5.4 callable type hint
    - Fixed problem where some file content could be ignored when checking STDIN
    - Version information is now printed when installed via composer or run from a Git clone (request #20050)
    - The CSS tokenizer is now more reliable when encountering 'list' and 'break' strings
    - Coding standard ignore comments can now appear instead doc blocks as well as inline comments
      -- Thanks to Stuart Langley for the patch
    - Generic LineLengthSniff now ignores SVN URL and Head URL comments
      -- Thanks to Karl DeBisschop for the patch
    - PEAR MultiLineConditionSniff now has a setting to specify how many spaces code should be indented
      -- Default remains at 4; override the 'indent' setting in a ruleset.xml file to change
      -- Thanks to Szabolcs Sulik for the patch
    - PEAR MultiLineAssignmentSniff now has a setting to specify how many spaces code should be indented
      -- Default remains at 4; override the 'indent' setting in a ruleset.xml file to change
      -- Thanks to Szabolcs Sulik for the patch
    - PEAR FunctionDeclarationSniff now has a setting to specify how many spaces code should be indented
      -- Default remains at 4; override the 'indent' setting in a ruleset.xml file to change
      -- Thanks to Szabolcs Sulik for the patch
    - Squiz SwitchDeclarationSniff now has a setting to specify how many spaces code should be indented
      -- Default remains at 4; override the 'indent' setting in a ruleset.xml file to change
      -- Thanks to Szabolcs Sulik for the patch
    - Squiz CSS IndentationSniff now has a setting to specify how many spaces code should be indented
      -- Default remains at 4; override the 'indent' setting in a ruleset.xml file to change
      -- Thanks to Hugo Fonseca for the patch
    - Squiz and MySource File and Function comment sniffs now allow all tags and don't require a particular licence
    - Squiz LowercaseStyleDefinitionSniff no longer throws errors for class names in nested style definitions
    - Squiz ClassFileNameSniff no longer throws errors when checking STDIN
    - Squiz CSS sniffs no longer generate errors for IE filters
    - Squiz CSS IndentationSniff no longer sees comments as blank lines
    - Squiz LogicalOperatorSpacingSniff now ignores whitespace at the end of a line
    - Squiz.Scope.MethodScope.Missing error message now mentions 'visibility' instead of 'scope modifier'
      -- Thanks to Renat Akhmedyanov for the patch
    - Added support for the PSR2 multi-line arguments errata
    - The PSR2 standard no longer throws errors for additional spacing after a type hint
    - PSR UseDeclarationSniff no longer throws errors for USE statements inside TRAITs
    - Fixed bug #20026 : Check for multi-line arrays that should be single-line is slightly wrong
      -- Adds new error message for single-line arrays that end with a comma
    - Fixed bug #20029 : ForbiddenFunction sniff incorrectly recognizes methods in USE clauses
    - Fixed bug #20043 : Mis-interpretation of Foo::class
    - Fixed bug #20044 : PSR1 camelCase check does not ignore leading underscores
    - Fixed bug #20045 : Errors about indentation for closures with multi-line 'use' in functions
   </notes>
  </release>
  <release>
   <version>
    <release>1.4.6</release>
    <api>1.4.6</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2013-07-25</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Added report type --report=json to show the error list and total counts for all checked files
      -- Thanks to Jeffrey Fisher for the contribution
    - The JS tokenizer now has support for the T_THROW token
    - Symlinked directories inside CodeSniffer/Standards and in ruleset.xml files are now supported
      -- Only available since PHP 5.2.11 and 5.3.1
      -- Thanks to Maik Penz for the patch
    - The JS tokenizer now correctly identifies T_INLINE_ELSE tokens instead of leaving them as T_COLON
      -- Thanks to Arnout Boks for the patch
    - Explaining a standard (phpcs -e) that uses namespaces now works correctly
    - Restricting a check to specific sniffs (phpcs --sniffs=...) now works correctly with namespaced sniffs
      -- Thanks to Maik Penz for the patch
    - Docs added for the entire Generic standard, and many sniffs from other standards are now documented as well
      -- Thanks to Spencer Rinehart for the contribution
    - Clearer error message for when the sniff class name does not match the directory structure
    - Generated HTML docs now correctly show the open PHP tag in code comparison blocks
    - Added Generic InlineHTMLSniff to ensure a file only contains PHP code
    - Added Squiz ShorthandSizeSniff to check that CSS sizes are using shorthand notation only when 1 or 2 values are used
    - Added Squiz ForbiddenStylesSniff to ban the use of some deprecated browser-specific styles
    - Added Squiz NamedColoursSniff to ban the use of colour names
    - PSR2 standard no longer enforces no whitespace between the closing parenthesis of a function call and the semicolon
    - PSR2 ClassDeclarationSniff now ignores empty classes when checking the end brace position
    - PSR2 SwitchDeclarationSniff no longer reports errors for empty lines between CASE statements
    - PEAR ObjectOperatorIndentSniff now has a setting to specify how many spaces code should be indented
      -- Default remains at 4; override the indent setting in a ruleset.xml file to change
      -- Thanks to Andrey Mindubaev for the patch
    - Squiz FileExtensionSniff now supports traits
      -- Thanks to Lucas Green for the patch
    - Squiz ArrayDeclarationSniff no longer reports errors for no comma at the end of a line that contains a function call
    - Squiz SwitchDeclarationSniff now supports T_CONTINUE and T_THROW as valid case/default breaking statements
    - Squiz CommentedOutCodeSniff is now better at ignoring commented out HTML, XML and regular expressions
    - Squiz DisallowComparisonAssignmentSniff no longer throws errors for the third expression in a FOR statement
    - Squiz ColourDefinitionSniff no longer throws errors for some CSS class names
    - Squiz ControlStructureSpacingSniff now supports all types of CASE/DEFAULT breaking statements
    - Generic CallTimePassByReferenceSniff now reports errors for functions called using a variable
      -- Thanks to Maik Penz for the patch
    - Generic ConstructorNameSniff no longer throws a notice for abstract constructors inside abstract classes
      -- Thanks to Spencer Rinehart for the patch
    - Squiz ComparisonOperatorUsageSniff now checks inside elseif statements
      -- Thanks to Arnout Boks for the patch
    - Squiz OperatorSpacingSniff now reports errors for no spacing around inline then and else tokens
      -- Thanks to Arnout Boks for the patch
    - Fixed bug #19811 : Comments not ignored in all cases in AbstractPatternSniff
      -- Thanks to Erik Wiffin for the patch
    - Fixed bug #19892 : ELSE with no braces causes incorrect SWITCH break statement indentation error
    - Fixed bug #19897 : Indenting warnings in templates not consistent
    - Fixed bug #19908 : PEAR MultiLineCondition Does Not Apply elseif
    - Fixed bug #19913 : Running phpcs in interactive mode causes warnings
      -- Thanks to Harald Franndorfer for the patch
    - Fixed bug #19935 : notify-send reports do not vanish in gnome-shell
      -- Thanks to Christian Weiske for the patch
    - Fixed bug #19944 : docblock squiz sniff "return void" trips over return in lambda function
    - Fixed bug #19953 : PSR2 - Spaces before interface name for abstract class
    - Fixed bug #19956 : phpcs warns for Type Hint missing Resource
    - Fixed bug #19957 : Does not understand trait method aliasing
    - Fixed bug #19968 : Permission denied on excluded directory
    - Fixed bug #19969 : Sniffs with namespace not recognized in reports
    - Fixed bug #19997 : Class names incorrectly detected as constants
   </notes>
  </release>
  <release>
   <version>
    <release>1.4.5</release>
    <api>1.4.5</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2013-04-04</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Added Generic LowerCaseKeywordSniff to ensure all PHP keywords are defined in lowercase
      -- The PSR2 and Squiz standards now use this sniff
    - Added Generic SAPIUsageSniff to ensure the PHP_SAPI constant is used instead of php_sapi_name() (request #19863)
    - Squiz FunctionSpacingSniff now has a setting to specify how many lines there should between functions (request #19843)
      -- Default remains at 2
      -- Override the "spacing" setting in a ruleset.xml file to change
    - Squiz LowercasePHPFunctionSniff no longer throws errors for the limited set of PHP keywords it was checking
      -- Add a rule for Generic.PHP.LowerCaseKeyword to your ruleset to replicate this functionality
    - Added support for the PHP 5.4 T_CALLABLE token so it can be used in lower PHP versions
    - Generic EndFileNoNewlineSniff now supports checking of CSS and JS files
    - PSR2 SwitchDeclarationSniff now has a setting to specify how many spaces code should be indented
      -- Default remains at 4; override the indent setting in a ruleset.xml file to change
      -- Thanks to Asher Snyder for the patch
    - Generic ScopeIndentSniff now has a setting to specify a list of tokens that should be ignored
      -- The first token on the line is checked and the whole line is ignored if the token is in the array
      -- Thanks to Eloy Lafuente for the patch
    - Squiz LowercaseClassKeywordsSniff now checks for the TRAIT keyword
      -- Thanks to Anthon Pang for the patch
    - If you create your own PHP_CodeSniffer object, PHPCS will no longer exit when an unknown argument is found
      -- This allows you to create wrapper scripts for PHPCS more easily
    - PSR2 MethodDeclarationSniff no longer generates a notice for methods named "_"
      -- Thanks to Bart S for the patch
    - Squiz BlockCommentSniff no longer reports that a blank line between a scope closer and block comment is invalid
    - Generic DuplicateClassNameSniff no longer reports an invalid error if multiple PHP open tags exist in a file
    - Generic DuplicateClassNameSniff no longer reports duplicate errors if multiple PHP open tags exist in a file
    - Fixed bug #19819 : Freeze with syntax error in use statement
    - Fixed bug #19820 : Wrong message level in Generic_Sniffs_CodeAnalysis_EmptyStatementSniff
    - Fixed bug #19859 : CodeSniffer::setIgnorePatterns API changed
    - Fixed bug #19871 : findExtendedClassName doesn't return FQCN on namespaced classes
    - Fixed bug #19879 : bitwise and operator interpreted as reference by value
   </notes>
  </release>
  <release>
   <version>
    <release>1.4.4</release>
    <api>1.4.4</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2013-02-07</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Ignored lines no longer cause the summary report to show incorrect error and warning counts
      -- Thanks to Bert Van Hauwaert for the patch
    - Added Generic CSSLintSniff to run CSSLint over a CSS file and report warnings
      -- Set full command to run CSSLint using phpcs --config-set csslint_path /path/to/csslint
      -- Thanks to Roman Levishchenko for the contribution
    - Added PSR2 ControlStructureSpacingSniff to ensure there are no spaces before and after parenthesis in control structures
      -- Fixes bug #19732 : PSR2: some control structures errors not reported
    - Squiz commenting sniffs now support non-English characters when checking for capital letters
      -- Thanks to Roman Levishchenko for the patch
    - Generic EndFileNewlineSniff now supports JS and CSS files
      -- Thanks to Denis Ryabkov for the patch
    - PSR1 SideEffectsSniff no longer reports constant declarations as side effects
    - Notifysend report now supports notify-send versions before 0.7.3
      -- Thanks to Ken Guest for the patch
    - PEAR and Squiz FunctionCommentSniffs no longer report errors for misaligned argument comments when they are blank
      -- Thanks to Thomas Peterson for the patch
    - Squiz FunctionDeclarationArgumentSpacingSniff now works correctly for equalsSpacing values greater than 0
      -- Thanks to Klaus Purer for the patch
    - Squiz SuperfluousWhitespaceSniff no longer throws errors for CSS files with no newline at the end
    - Squiz SuperfluousWhitespaceSniff now allows a single newline at the end of JS and CSS files
    - Fixed bug #19755 : Token of T_CLASS type has no scope_opener and scope_closer keys
    - Fixed bug #19759 : Squiz.PHP.NonExecutableCode fails for return function()...
    - Fixed bug #19763 : Use statements for traits not recognised correctly for PSR2 code style
    - Fixed bug #19764 : Instead of for traits throws uppercase constant name errors
    - Fixed bug #19772 : PSR2_Sniffs_Namespaces_UseDeclarationSniff does not properly recognize last use
    - Fixed bug #19775 : False positive in NonExecutableCode sniff when not using curly braces
    - Fixed bug #19782 : Invalid found size functions in loop when using object operator
    - Fixed bug #19799 : config folder is not created automatically
    - Fixed bug #19804 : JS Tokenizer wrong /**/ parsing
   </notes>
  </release>
  <release>
   <version>
    <release>1.4.3</release>
    <api>1.4.3</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2012-12-04</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Added support for the PHP 5.5 T_FINALLY token to detect try/catch/finally statements
    - Added empty CodeSniffer.conf to enable config settings for Composer installs
    - Added Generic EndFileNoNewlineSniff to ensure there is no newline at the end of a file
    - Autoloader can now load PSR-0 compliant classes
      -- Thanks to Maik Penz for the patch
    - Squiz NonExecutableCodeSniff no longer throws error for multi-line RETURNs inside CASE statements
      -- Thanks to Marc Ypes for the patch
    - Squiz OperatorSpacingSniff no longer reports errors for negative numbers inside inline THEN statements
      -- Thanks to Klaus Purer for the patch
    - Squiz OperatorSpacingSniff no longer reports errors for the assignment of operations involving negative numbers
    - Squiz SelfMemberReferenceSniff can no longer get into an infinite loop when checking a static call with a namespace
      -- Thanks to Andy Grunwald for the patch
    - Fixed bug #19699 : Generic.Files.LineLength giving false positives when tab-width is used
    - Fixed bug #19726 : Wrong number of spaces expected after instanceof static
  - Fixed bug #19727 : PSR2: no error reported when using } elseif {
   </notes>
  </release>
  <release>
   <version>
    <release>1.4.2</release>
    <api>1.4.2</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2012-11-09</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - PHP_CodeSniffer can now be installed using Composer
      -- Require squizlabs/php_codesniffer in your composer.json file
      -- Thanks to Rob Bast, Stephen Rees-Carter, Stefano Kowalke and Ivan Habunek for help with this
    - Squiz BlockCommentSniff and InlineCommentSniff no longer report errors for trait block comments
    - Squiz SelfMemberReferenceSniff now supports namespaces
      -- Thanks to Andy Grunwald for the patch
    - Squiz FileCommentSniff now uses tag names inside the error codes for many messages
      -- This allows you to exclude specific missing, out of order etc., tags
    - Squiz SuperfluousWhitespaceSniff now has an option to ignore blank lines
      -- This will stop errors being reported for lines that contain only whitespace
      -- Set the ignoreBlankLines property to TRUE in your ruleset.xml file to enable this
    - PSR2 no longer reports errors for whitespace at the end of blank lines
    - Fixed gitblame report not working on Windows
      -- Thanks to Rogerio Prado de Jesus
    - Fixed an incorrect error in Squiz OperatorSpacingSniff for default values inside a closure definition
    - Fixed bug #19691 : SubversionPropertiesSniff fails to find missing properties
      -- Thanks to Kevin Winahradsky for the patch
    - Fixed bug #19692 : DisallowMultipleAssignments is triggered by a closure
    - Fixed bug #19693 : exclude-patterns no longer work on specific messages
    - Fixed bug #19694 : Squiz.PHP.LowercasePHPFunctions incorrectly matches return by ref functions
   </notes>
  </release>
  <release>
   <version>
    <release>1.4.1</release>
    <api>1.4.1</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2012-11-02</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - All ignore patterns have been reverted to being checked against the absolute path of a file
      -- Patterns can be specified to be relative in a rulset.xml file, but nowhere else
      -- e.g., [exclude-pattern type="relative"]^tests/*[/exclude-pattern] (with angle brackets, not square brackets)
    - Added support for PHP tokenizing of T_INLINE_ELSE colons, so this token type is now available
      -- Custom sniffs that rely on looking for T_COLON tokens inside inline if statements must be changed to use the new token
      -- Fixes bug #19666 : PSR1.Files.SideEffects throws a notice Undefined index: scope_closer
    - Messages can now be changed from errors to warnings (and vice versa) inside ruleset.xml files
      -- As you would with "message" and "severity", specify a "type" tag under a "rule" tag and set the value to "error" or "warning"
    - PHP_CodeSniffer will now generate a warning on files that it detects have mixed line endings
      -- This warning has the code Internal.LineEndings.Mixed and can be overriden in a ruleset.xml file
      -- Thanks to Vit Brunner for help with this
    - Sniffs inside PHP 5.3 namespaces are now supported, along with the existing underscore-style emulated namespaces
      -- For example: namespace MyStandard\Sniffs\Arrays; class ArrayDeclarationSniff implements \PHP_CodeSniffer_Sniff { ...
      -- Thanks to Till Klampaeckel for the patch
    - Generic DuplicateClassNameSniff is no longer a multi-file sniff, so it won't max out your memory
      -- Multi-file sniff support should be considered deprecated as standard sniffs can now do the same thing
    - Added Generic DisallowSpaceIndent to check that files are indented using tabs
    - Added Generic OneClassPerFileSniff to check that only one class is defined in each file
      -- Thanks to Andy Grunwald for the contribution
    - Added Generic OneInterfacePerFileSniff to check that only one interface is defined in each file
      -- Thanks to Andy Grunwald for the contribution
    - Added Generic LowercasedFilenameSniff to check that filenames are lowercase
      -- Thanks to Andy Grunwald for the contribution
    - Added Generic ClosingPHPTagSniff to check that each open PHP tag has a corresponding close tag
      -- Thanks to Andy Grunwald for the contribution
    - Added Generic CharacterBeforePHPOpeningTagSniff to check that the open PHP tag is the first content in a file
      -- Thanks to Andy Grunwald for the contribution
    - Fixed incorrect errors in Squiz OperatorBracketSniff and OperatorSpacingSniff for negative numbers in CASE statements
      -- Thanks to Arnout Boks for the patch
    - Generic CamelCapsFunctionNameSniff no longer enforces exact case matching for PHP magic methods
    - Generic CamelCapsFunctionNameSniff no longer throws errors for overridden SOAPClient methods prefixed with double underscores
      -- Thanks to Dorian Villet for the patch
    - PEAR ValidFunctionNameSniff now supports traits
    - PSR1 ClassDeclarationSniff no longer throws an error for non-namespaced code if PHP version is less than 5.3.0
    - Fixed bug #19616 : Nested switches cause false error in PSR2
    - Fixed bug #19629 : PSR2 error for inline comments on multi-line argument lists
    - Fixed bug #19644 : Alternative syntax, e.g. if/endif triggers Inline Control Structure error
    - Fixed bug #19655 : Closures reporting as multi-line when they are not
    - Fixed bug #19675 : Improper indent of nested anonymous function bodies in a call
    - Fixed bug #19685 : PSR2 catch-22 with empty third statement in for loop
    - Fixed bug #19687 : Anonymous functions inside arrays marked as indented incorrectly in PSR2
   </notes>
  </release>
  <release>
   <version>
    <release>1.4.0</release>
    <api>1.4.0</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2012-09-26</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Added PSR1 and PSR2 coding standards that can be used to check your code against these guidelines
    - PHP 5.4 short array syntax is now detected and tokens are assigned to the open and close characters
      -- New tokens are T_OPEN_SHORT_ARRAY and T_CLOSE_SHORT_ARRAY as PHP does not define its own
    - Added the ability to explain a coding standard by listing the sniffs that it includes
      -- The sniff list includes all imported and native sniffs
      -- Explain a standard by using the -e and --standard=[standard] command line arguments
      -- E.g., phpcs -e --standard=Squiz
      -- Thanks to Ben Selby for the idea
    - Added report to show results using notify-send
      -- Use --report=notifysend to generate the report
      -- Thanks to Christian Weiske for the contribution
    - The JS tokenizer now recognises RETURN as a valid closer for CASE and DEFAULT inside switch statements
    - AbstractPatternSniff now sets the ignoreComments option using a public var rather than through the constructor
      -- This allows the setting to be overwritten in ruleset.xml files
      -- Old method remains for backwards compatibility
    - Generic LowerCaseConstantSniff and UpperCaseConstantSniff no longer report errors on classes named True, False or Null
    - PEAR ValidFunctionNameSniff no longer enforces exact case matching for PHP magic methods
    - Squiz SwitchDeclarationSniff now allows RETURN statements to close a CASE or DEFAULT statement
    - Squiz BlockCommentSniff now correctly reports an error for blank lines before blocks at the start of a control structure
    - Fixed a PHP notice generated when loading custom array settings from a rulset.xml file
    - Fixed bug #17908 : CodeSniffer does not recognise optional @params
      -- Thanks to Pete Walker for the patch
    - Fixed bug #19538 : Function indentation code sniffer checks inside short arrays
    - Fixed bug #19565 : Non-Executable Code Sniff Broken for Case Statements with both return and break
    - Fixed bug #19612 : Invalid @package suggestion
   </notes>
  </release>
  <release>
   <version>
    <release>1.3.6</release>
    <api>1.3.6</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2012-08-08</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Memory usage has been dramatically reduced when using the summary report
      -- Reduced memory is only available when displaying a single summary report to the screen
      -- PHP_CodeSniffer will not generate any messages in this case, storing only error counts instead
      -- Impact is most notable with very high error and warning counts
    - Significantly improved the performance of Squiz NonExecutableCodeSniff
    - Ignore patterns now check the relative path of a file based on the dir being checked
      -- Allows ignore patterns to become more generic as the path to the code is no longer included when checking
      -- Thanks to Kristof Coomans for the patch
    - Sniff settings can now be changed by specifying a special comment format inside a file
      -- e.g., // @codingStandardsChangeSetting PEAR.Functions.FunctionCallSignature allowMultipleArguments false
      -- If you change a setting, don't forget to change it back
    - Added Generic EndFileNewlineSniff to ensure PHP files end with a newline character
    - PEAR FunctionCallSignatureSniff now includes a setting to force one argument per line in multi-line calls
      -- Set allowMultipleArguments to false
    - Squiz standard now enforces one argument per line in multi-line function calls
    - Squiz FunctionDeclarationArgumentSpacingSniff now supports closures
    - Squiz OperatorSpacingSniff no longer throws an error for negative values inside an inline THEN statement
      -- Thanks to Klaus Purer for the patch
    - Squiz FunctionCommentSniff now throws an error for not closing a comment with */
      -- Thanks to Klaus Purer for the patch
    - Summary report no longer shows two lines of PHP_Timer output when showing sources
    - Fixed undefined variable error in PEAR FunctionCallSignatureSniff for lines with no indent
    - Fixed bug #19502 : Generic.Files.LineEndingsSniff fails if no new-lines in file
    - Fixed bug #19508 : switch+return: Closing brace indented incorrectly
    - Fixed bug #19532 : The PSR-2 standard don't recognize Null in class names
    - Fixed bug #19546 : Error thrown for __call() method in traits
   </notes>
  </release>
  <release>
   <version>
    <release>1.3.5</release>
    <api>1.3.5</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2012-07-12</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Added Generic CamelCapsFunctionNameSniff to just check if function and method names use camel caps
      -- Does not allow underscore prefixes for private/protected methods
      -- Defaults to strict checking, where two uppercase characters can not be next to each other
      -- Strict checking can be disabled in a ruleset.xml file
    - Squiz FunctionDeclarationArgumentSpacing now has a setting to specify how many spaces should surround equals signs
      -- Default remains at 0
      -- Override the equalsSpacing setting in a ruleset.xml file to change
    - Squiz ClassDeclarationSniff now throws errors for > 1 space before extends/implements class name with ns seperator
    - Squiz standard now warns about deprecated functions using Generic DeprecatedFunctionsSniff
    - PEAR FunctionDeclarationSniff now reports an error for multiple spaces after the FUNCTION keyword and around USE
    - PEAR FunctionDeclarationSniff now supports closures
    - Squiz MultiLineFunctionDeclarationSniff now supports closures
    - Exclude rules written for Unix systems will now work correctly on Windows
      -- Thanks to Walter Tamboer for the patch
    - The PHP tokenizer now recognises T_RETURN as a valid closer for T_CASE and T_DEFAULT inside switch statements
    - Fixed duplicate message codes in Generic OpeningFunctionBraceKernighanRitchieSniff
    - Fixed bug #18651 : PHPunit Test cases for custom standards are not working on Windows
    - Fixed bug #19416 : Shorthand arrays cause bracket spacing errors
    - Fixed bug #19421 : phpcs doesn't recognize ${x} as equivalent to $x
    - Fixed bug #19428 : PHPCS Report "hgblame" doesn't support windows paths
      -- Thanks to Justin Rovang for the patch
    - Fixed bug #19448 : Problem with detecting remote standards
    - Fixed bug #19463 : Anonymous functions incorrectly being flagged by NonExecutableCodeSniff
    - Fixed bug #19469 : PHP_CodeSniffer_File::getMemberProperties() sets wrong scope
    - Fixed bug #19471 : phpcs on Windows, when using Zend standard, doesn't catch problems
      -- Thanks to Ivan Habunek for the patch
    - Fixed bug #19478 : Incorrect indent detection in PEAR standard
      -- Thanks to Shane Auckland for the patch
    - Fixed bug #19483 : Blame Reports fail with space in directory name
   </notes>
  </release>
  <release>
   <version>
    <release>1.3.4</release>
    <api>1.3.4</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2012-05-17</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Added missing package.xml entries for new Generic FixmeSniff
      -- Thanks to Jaroslav Hanslík for the patch
    - Expected indents for PEAR ScopeClosingBraceSniff and FunctionCallSignatureSniff can now be set in ruleset files
      -- Both sniffs use a variable called "indent"
      -- Thanks to Thomas Despoix for the patch
    - Standards designed to be installed in the PHPCS Standards dir will now work outside this dir as well
      -- In particular, allows the Drupal CS to work without needing to symlink it into the PHPCS install
      -- Thanks to Peter Philipp for the patch
    - Rule references for standards, directories and specific sniffs can now be relative in ruleset.xml files
      -- For example: ref="../MyStandard/Sniffs/Commenting/DisallowHashCommentsSniff.php"
    - Symlinked standards now work correctly, allowing aliasing of installed standards (request #19417)
      -- Thanks to Tom Klingenberg for the patch
    - Squiz ObjectInstantiationSniff now allows objects to be returned without assinging them to a variable
    - Added Squiz.Commenting.FileComment.MissingShort error message for file comments that only contains tags
      -- Also stops undefined index errors being generated for these comments
    - Debug option -vv now shows tokenizer status for CSS files
    - Added support for new gjslint error formats
      -- Thanks to Meck for the patch
    - Generic ScopeIndentSniff now allows comment indents to not be exact even if the exact flag is set
      -- The start of the comment is still checked for exact indentation as normal
    - Fixed an issue in AbstractPatternSniff where comments were not being ignored in some cases
    - Fixed an issue in Zend ClosingTagSniff where the closing tag was not always being detected correctly
      -- Thanks to Jonathan Robson for the patch
    - Fixed an issue in Generic FunctionCallArgumentSpacingSniff where closures could cause incorrect errors
    - Fixed an issue in Generic UpperCaseConstantNameSniff where errors were incorrectly reported on goto statements
      -- Thanks to Tom Klingenberg for the patch
    - PEAR FileCommentSniff and ClassCommentSniff now support author emails with a single character in the local part
      -- E.g., a@me.com
      -- Thanks to Denis Shapkin for the patch
    - Fixed bug #19290 : Generic indent sniffer fails for anonymous functions
    - Fixed bug #19324 : Setting show_warnings configuration option does not work
    - Fixed bug #19354 : Not recognizing references passed to method
    - Fixed bug #19361 : CSS tokenzier generates errors when PHP embedded in CSS file
    - Fixed bug #19374 : HEREDOC/NOWDOC Indentation problems
    - Fixed bug #19381 : traits and indetations in traits are not handled properly
    - Fixed bug #19394 : Notice in NonExecutableCodeSniff
    - Fixed bug #19402 : Syntax error when executing phpcs on Windows with parens in PHP path
      -- Thanks to Tom Klingenberg for the patch
    - Fixed bug #19411 : magic method error on __construct()
      -- The fix required a rewrite of AbstractScopeSniff, so please test any sniffs that extend this class
    - Fixed bug #19412 : Incorrect error about assigning objects to variables when inside inline IF
    - Fixed bug #19413 : php_cs thinks I haven't used a parameter when I have
    - Fixed bug #19414 : php_cs seems to not track variables correctly in heredocs
   </notes>
  </release>
  <release>
   <version>
    <release>1.3.3</release>
    <api>1.3.3</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2012-02-17</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Added new Generic FixmeSniff that shows error messages for all FIXME comments left in your code
      -- Thanks to Sam Graham for the contribution
    - The maxPercentage setting in the Squiz CommentedOutCodeSniff can now be overriden in a rulset.xml file
      -- Thanks to Volker Dusch for the patch
    - The Checkstyle and XML reports now use XMLWriter
      -- Only change in output is that empty file tags are no longer produced for files with no violations
      -- Thanks to Sebastian Bergmann for the patch
    - Added PHP_CodeSniffer_Tokens::$bracketTokens to give sniff writers fast access to open and close bracket tokens
    - Fixed an issue in AbstractPatternSniff where EOL tokens were not being correctly checked in some cases
    - PHP_CodeSniffer_File::getTokensAsString() now detects incorrect length value (request #19313)
    - Fixed bug #19114 : CodeSniffer checks extension even for single file
    - Fixed bug #19171 : Show sniff codes option is ignored by some report types
      -- Thanks to Dominic Scheirlinck for the patch
    - Fixed bug #19188 : Lots of PHP Notices when analyzing the Symfony framework
      -- First issue was list-style.. lines in CSS files not properly adjusting open/close bracket positions
      -- Second issue was notices caused by bug #19137
    - Fixed bug #19208 : UpperCaseConstantName reports class members
      -- Was also a problem with LowerCaseConstantName as well
    - Fixed bug #19256 : T_DOC_COMMENT in CSS files breaks ClassDefinitionNameSpacingSniff
      -- Thanks to Klaus Purer for the patch
    - Fixed bug #19264 : Squiz.PHP.NonExecutableCode does not handle RETURN in CASE without BREAK
    - Fixed bug #19270 : DuplicateClassName does not handle namespaces correctly
    - Fixed bug #19283 : CSS @media rules cause false positives
      -- Thanks to Klaus Purer for the patch
   </notes>
  </release>
  <release>
   <version>
    <release>1.3.2</release>
    <api>1.3.2</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2011-12-01</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Added Generic JSHintSniff to run jshint.js over a JS file and report warnings
      -- Set jshint path using phpcs --config-set jshint_path /path/to/jshint-rhino.js
      -- Set rhino path using phpcs --config-set rhino_path /path/to/rhino
      -- Thanks to Alexander Weiß for the contribution
    - Nowdocs are now tokenized using PHP_CodeSniffer specific T_NOWDOC tokens for easier identification
    - Generic UpperCaseConstantNameSniff no longer throws errors for namespaces
      -- Thanks to Jaroslav Hanslík for the patch
    - Squiz NonExecutableCodeSniff now detects code after thrown exceptions
      -- Thanks to Jaroslav Hanslík for the patch
    - Squiz OperatorSpacingSniff now ignores references
      -- Thanks to Jaroslav Hanslík for the patch
    - Squiz FunctionCommentSniff now reports a missing function comment if it finds a standard code comment instead
    - Squiz FunctionCommentThrownTagSniff no longer reports errors if it can't find a function comment
    - Fixed unit tests not running under Windows
      -- Thanks to Jaroslav Hanslík for the patch
    - Fixed bug #18964 : "$stackPtr must be of type T_VARIABLE" on heredocs and nowdocs
    - Fixed bug #18973 : phpcs is looking for variables in a nowdoc
    - Fixed bug #18974 : Blank line causes "Multi-line function call not indented correctly"
      -- Adds new error message to ban empty lines in multi-line function calls
    - Fixed bug #18975 : "Closing parenthesis must be on a line by itself" also causes indentation error
   </notes>
  </release>
  <release>
   <version>
    <release>1.3.1</release>
    <api>1.3.1</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2011-11-03</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - All report file command line arguments now work with relative paths (request #17240)
    - The extensions command line argument now supports multi-part file extensions (request #17227)
    - Added report type --report=hgblame to show number of errors/warnings committed by authors in a Mercurial repository
      -- Has the same functionality as the svnblame report
      -- Thanks to Ben Selby for the patch
    - Added T_BACKTICK token type to make detection of backticks easier (request #18799)
    - Added pattern matching support to Generic ForbiddenFunctionsSniff
        -- If you are extending it and overriding register() or addError() you will need to review your sniff
    - Namespaces are now recognised as scope openers, although they do not require braces (request #18043)
    - Added new ByteOrderMarkSniff to Generic standard (request #18194)
      -- Throws an error if a byte order mark is found in any PHP file
      -- Thanks to Piotr Karas for the contribution
    - PHP_Timer output is no longer included in reports when being written to a file (request #18252)
      -- Also now shown for all report types if nothing is being printed to the screen
    - Generic DeprecatedFunctionSniff now reports functions as deprecated and not simply forbidden (request #18288)
    - PHPCS now accepts file contents from STDIN (request #18447)
      -- Example usage: cat temp.php | phpcs [options]  -OR-  phpcs [options] &lt; temp.php
      -- Not every sniff will work correctly due to the lack of a valid file path
    - PHP_CodeSniffer_Exception no longer extends PEAR_Exception (request #18483)
      -- PEAR_Exception added a requirement that PEAR had to be installed
      -- PHP_CodeSniffer is not used as a library, so unlikely to have any impact
    - PEAR FileCommentSniff now allows GIT IDs in the version tag (request #14874)
    - AbstractVariableSniff now supports heredocs
      -- Also includes some variable detection fixes
      -- Thanks to Sam Graham for the patch
    - Squiz FileCommentSniff now enforces rule that package names cannot start with the word Squiz
    - MySource AssignThisSniff now allows "this" to be assigned to the private var _self
    - Fixed issue in Squiz FileCommentSniff where suggested package name was the same as the incorrect package name
    - Fixed some issues with Squiz ArrayDeclarationSniff when using function calls in array values
    - Fixed doc generation so it actually works again
      -- Also now works when being run from an SVN checkout as well as when installed as a PEAR package
      -- Should fix bug #18949 : Call to private method from static
    - PEAR ClassDeclaration sniff now supports indentation checks when using the alternate namespace syntax
      -- PEAR.Classes.ClassDeclaration.SpaceBeforeBrace message now contains 2 variables instead of 1
      -- Sniff allows overriding of the default indent level, which is set to 4
      -- Fixes bug #18933 : Alternative namespace declaration syntax confuses scope sniffs
    - Fixed bug #18465 : "self::" does not work in lambda functions
      -- Also corrects conversion of T_FUNCTION tokens to T_CLOSURE, which was not fixing token condition arrays
    - Fixed bug #18543 : CSS Tokenizer deletes too many #
    - Fixed bug #18624 : @throws namespace problem
      -- Thanks to Gavin Davies for the patch
    - Fixed bug #18628 : Generic.Files.LineLength gives incorrect results with Windows line-endings
    - Fixed bug #18633 : CSS Tokenizer doesn't replace T_LIST tokens inside some styles
    - Fixed bug #18657 : anonymous functions wrongly indented
    - Fixed bug #18670 : UpperCaseConstantNameSniff fails on dynamic retrieval of class constant
    - Fixed bug #18709 : Code sniffer sniffs file if even if it's in --ignore
      -- Thanks to Artem Lopata for the patch
    - Fixed bug #18762 : Incorrect handling of define and constant in UpperCaseConstantNameSniff
      -- Thanks to Thomas Baker for the patch
    - Fixed bug #18769 : CSS Tokenizer doesn't replace T_BREAK tokens inside some styles
    - Fixed bug #18835 : Unreachable errors of inline returns of closure functions
      -- Thanks to Patrick Schmidt for the patch
    - Fixed bug #18839 : Fix miscount of warnings in AbstractSniffUnitTest.php
      -- Thanks to Sam Graham for the patch
    - Fixed bug #18844 : Generic_Sniffs_CodeAnalysis_UnusedFunctionParameterSniff with empty body
      -- Thanks to Dmitri Medvedev for the patch
    - Fixed bug #18847 : Running Squiz_Sniffs_Classes_ClassDeclarationSniff results in PHP notice
    - Fixed bug #18868 : jslint+rhino: errors/warnings not detected
      -- Thanks to Christian Weiske for the patch
    - Fixed bug #18879 : phpcs-svn-pre-commit requires escapeshellarg
      -- Thanks to Bjorn Katuin for the patch
    - Fixed bug #18951 : weird behaviour with closures and multi-line use () params
   </notes>
  </release>
  <release>
   <version>
    <release>1.3.0</release>
    <api>1.3.0</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2011-03-17</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Add a new token T_CLOSURE that replaces T_FUNCTION if the function keyword is anonymous
    - Many Squiz sniffs no longer report errors when checking closures; they are now ignored
    - Fixed some error messages in PEAR MultiLineConditionSniff that were not using placeholders for message data
    - AbstractVariableSniff now correctly finds variable names wrapped with curly braces inside double quoted strings
    - PEAR FunctionDeclarationSniff now ignores arrays in argument default values when checking multi-line declarations
    - Fixed bug #18200 : Using custom named ruleset file as standard no longer works
    - Fixed bug #18196 : PEAR MultiLineCondition.SpaceBeforeOpenBrace not consistent with newline chars
    - Fixed bug #18204 : FunctionCommentThrowTag picks wrong exception type when throwing function call
    - Fixed bug #18222 : Add __invoke method to PEAR standard
    - Fixed bug #18235 : Invalid error generation in Squiz.Commenting.FunctionCommentThrowTag
    - Fixed bug #18250 : --standard with relative path skips Standards' "implicit" sniffs
    - Fixed bug #18274 : Multi-line IF and function call indent rules conflict
    - Fixed bug #18282 : Squiz doesn't handle final keyword before function comments
      -- Thanks to Dave Perrett for the patch
    - Fixed bug #18336 : Function isUnderscoreName gives php notices
   </notes>
  </release>
  <release>
   <version>
    <release>1.3.0RC2</release>
    <api>1.3.0RC2</api>
   </version>
   <stability>
    <release>beta</release>
    <api>beta</api>
   </stability>
   <date>2011-01-14</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - You can now print multiple reports for each run and print each to the screen or a file (request #12434)
      -- Format is --report-[report][=file] (e.g., --report-xml=out.xml)
      -- Printing to screen is done by leaving [file] empty (e.g., --report-xml)
      -- Multiple reports can be specified in this way (e.g., --report-summary --report-xml=out.xml)
      -- The standard --report and --report-file command line arguments are unchanged
    - Added -d command line argument to set php.ini settings while running (request #17244)
      -- Usage is: phpcs -d memory_limit=32M -d ...
      -- Thanks to Ben Selby for the patch
    - Added -p command line argument to show progress during a run
      -- Dot means pass, E means errors found, W means only warnings found and S means skipped file
      -- Particularly good for runs where you are checking more than 100 files
      -- Enable by default with --config-set show_progress 1
      -- Will not print anything if you are already printing verbose output
      -- This has caused a big change in the way PHP_CodeSniffer processes files (API changes around processing)
    - You can now add exclude rules for individual sniffs or error messages (request #17903)
      -- Only available when using a ruleset.xml file to specify rules
      -- Uses the same exclude-pattern tags as normal but allows them inside rule tags
    - Using the -vvv option will now print a list of sniffs executed for each file and how long they took to process
    - Added Generic ClosureLinterSniff to run Google's gjslint over your JS files
    - The XML and CSV reports now include the severity of the error (request #18165)
      -- The Severity column in the CSV report has been renamed to Type, and a new Severity column added for this
    - Fixed issue with Squiz FunctionCommentSniff reporting incorrect type hint when default value uses namespace
      -- Thanks to Anti Veeranna for the patch
    - Generic FileLengthSniff now uses iconv_strlen to check line length if an encoding is specified (request #14237)
    - Generic UnnecessaryStringConcatSniff now allows strings to be combined to form a PHP open or close tag
    - Squiz SwitchDeclarationSniff no longer reports indentation errors for BREAK statements inside IF conditions
    - Interactive mode now always prints the full error report (ignores command line)
    - Improved regular expression detection in JavaScript files
      -- Added new T_TYPEOF token that can be used to target the typeof JS operator
      -- Fixes bug #17611 : Regular expression tokens not recognised
    - Squiz ScopeIndentSniff removed
      -- Squiz standard no longer requires additional indents between ob_* methods
      -- Also removed Squiz OutputBufferingIndentSniff that was checking the same thing
    - PHP_CodeSniffer_File::getMemberProperties() performance improved significantly
      -- Improves performance of Squiz ValidVariableNameSniff significantly
    - Squiz OperatorSpacingSniff performance improved significantly
    - Squiz NonExecutableCodeSniff performance improved significantly
      -- Will throw duplicate errors in some cases now, but these should be rare
    - MySource IncludeSystemSniff performance improved significantly
    - MySource JoinStringsSniff no longer reports an error when using join() on a named JS array
    - Warnings are now reported for each file when they cannot be opened instead of stopping the script
      -- Hide warnings with the -n command line argument
      -- Can override the warnings using the code Internal.DetectLineEndings
    - Fixed bug #17693 : issue with pre-commit hook script with filenames that start with v
    - Fixed bug #17860 : isReference function fails with references in array
      -- Thanks to Lincoln Maskey for the patch
    - Fixed bug #17902 : Cannot run tests when tests are symlinked into tests dir
      -- Thanks to Matt Button for the patch
    - Fixed bug #17928 : Improve error message for Generic_Sniffs_PHP_UpperCaseConstantSniff
      -- Thanks to Stefano Kowalke for the patch
    - Fixed bug #18039 : JS Tokenizer crash when ] is last character in file
    - Fixed bug #18047 : Incorrect handling of namespace aliases as constants
      -- Thanks to Dmitri Medvedev for the patch
    - Fixed bug #18072 : Impossible to exclude path from processing when symlinked
    - Fixed bug #18073 : Squiz.PHP.NonExecutableCode fault
    - Fixed bug #18117 : PEAR coding standard: Method constructor not sniffed as a function
    - Fixed bug #18135 : Generic FunctionCallArgumentSpacingSniff reports function declaration errors
    - Fixed bug #18140 : Generic scope indent in exact mode: strange expected/found values for switch
    - Fixed bug #18145 : Sniffs are not loaded for custom ruleset file
      -- Thanks to Scott McCammon for the patch
    - Fixed bug #18152 : While and do-while with AbstractPatternSniff
    - Fixed bug #18191 : Squiz.PHP.LowercasePHPFunctions does not work with new Date()
    - Fixed bug #18193 : CodeSniffer doesn't reconize CR (\r) line endings
   </notes>
  </release>
  <release>
   <version>
    <release>1.3.0RC1</release>
    <api>1.3.0RC1</api>
   </version>
   <stability>
    <release>beta</release>
    <api>beta</api>
   </stability>
   <date>2010-09-03</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Added exclude pattern support to ruleset.xml file so you can specify ignore patterns in a standard (request #17683)
      -- Use new exclude-pattern tags to include the ignore rules into your ruleset.xml file
      -- See CodeSniffer/Standards/PHPCS/ruleset.xml for an example
    - Added new --encoding command line argument to specify the encoding of the files being checked
      -- When set to utf-8, stops the XML-based reports from double-encoding
      -- When set to something else, helps the XML-based reports encode to utf-8
      -- Default value is iso-8859-1 but can be changed with --config-set encoding [value]
    - The report is no longer printed to screen when using the --report-file command line option (request #17467)
      -- If you want to print it to screen as well, use the -v command line argument
    - The SVN and GIT blame reports now also show percentage of reported errors per author (request #17606)
      -- Thanks to Ben Selby for the patch
    - Updated the SVN pre-commit hook to work with the new severity levels feature
    - Generic SubversionPropertiesSniff now allows properties to have NULL values (request #17682)
      -- A null value indicates that the property should exist but the value should not be checked
    - Generic UpperCaseConstantName Sniff now longer complains about the PHPUnit_MAIN_METHOD constant (request #17798)
    - Squiz FileComment sniff now checks JS files as well as PHP files
    - Squiz FunctionCommentSniff now supports namespaces in type hints
    - Fixed a problem in Squiz OutputBufferingIndentSniff where block comments were reported as not indented
    - Fixed bug #17092 : Problems with utf8_encode and htmlspecialchars with non-ascii chars
      -- Use the new --encoding=utf-8 command line argument if your files are utf-8 encoded
    - Fixed bug #17629 : PHP_CodeSniffer_Tokens::$booleanOperators missing T_LOGICAL_XOR
      -- Thanks to Matthew Turland for the patch
    - Fixed bug #17699 : Fatal error generating code coverage with PHPUnit 5.3.0RC1
    - Fixed bug #17718 : Namespace 'use' statement: used global class name is recognized as constant
    - Fixed bug #17734 : Generic SubversionPropertiesSniff complains on non SVN files
    - Fixed bug #17742 : EmbeddedPhpSniff reacts negatively to file without closing php tag
    - Fixed bug #17823 : Notice: Please no longer include PHPUnit/Framework.php
   </notes>
  </release>
  <release>
   <version>
    <release>1.3.0a1</release>
    <api>1.3.0a1</api>
   </version>
   <stability>
    <release>alpha</release>
    <api>alpha</api>
   </stability>
   <date>2010-07-15</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - All CodingStandard.php files have been replaced by ruleset.xml files
      -- Custom standards will need to be converted over to this new format to continue working
    - You can specify a path to your own custom ruleset.xml file by using the --standard command line arg
      -- e.g., phpcs --standard=/path/to/my/ruleset.xml
    - Added a new report type --report=gitblame to show how many errors and warnings were committed by each author
      -- Has the same functionality as the svnblame report
      -- Thanks to Ben Selby for the patch
    - A new token type T_DOLLAR has been added to allow you to sniff for variable variables (feature request #17095)
      -- Thanks to Ian Young for the patch
    - JS tokenizer now supports T_POWER (^) and T_MOD_EQUAL (%=) tokens (feature request #17441)
    - If you have PHP_Timer installed, you'll now get a time/memory summary at the end of a script run
      -- Only happens when printing reports that are designed to be read on the command line
    - Added Generic DeprecatedFunctionsSniff to warn about the use of deprecated functions (feature request #16694)
      -- Thanks to Sebastian Bergmann for the patch
    - Added Squiz LogicalOperatorSniff to ensure that logical operators are surrounded by single spaces
    - Added MySource ChannelExceptionSniff to ensure action files only throw ChannelException
    - Added new method getClassProperties() for sniffs to use to determine if a class is abstract and/or final
      -- Thanks to Christian Kaps for the patch
    - Generic UpperCaseConstantSniff no longer throws errors about namespaces
      -- Thanks to Christian Kaps for the patch
    - Squiz OperatorBracketSniff now correctly checks value assignmnets in arrays
    - Squiz LongConditionClosingCommentSniff now requires a comment for long CASE statements that use curly braces
    - Squiz LongConditionClosingCommentSniff now requires an exact comment match on the brace
    - MySource IncludeSystemSniff now ignores DOMDocument usage
    - MySource IncludeSystemSniff no longer requires inclusion of systems that are being implemented
    - Removed found and expected messages from Squiz ConcatenationSpacingSniff because they were messy and not helpful
    - Fixed a problem where Generic CodeAnalysisSniff could show warnings if checking multi-line strings
    - Fixed error messages in Squiz ArrayDeclarationSniff reporting incorrect number of found and expected spaces
    - Fixed bug #17048 : False positive in Squiz_WhiteSpace_ScopeKeywordSpacingSniff
    - Fixed bug #17054 : phpcs more strict than PEAR CS regarding function parameter spacing
    - Fixed bug #17096 : Notice: Undefined index: scope_condition in ScopeClosingBraceSniff.php
      -- Moved PEAR.Functions.FunctionCallArgumentSpacing to Generic.Functions.FunctionCallArgumentSpacing
    - Fixed bug #17144 : Deprecated: Function eregi() is deprecated
    - Fixed bug #17236 : PHP Warning due to token_get_all() in DoubleQuoteUsageSniff
    - Fixed bug #17243 : Alternate Switch Syntax causes endless loop of Notices in SwitchDeclaration
    - Fixed bug #17313 : Bug with switch case struture
    - Fixed bug #17331 : Possible parse error: interfaces may not include member vars
    - Fixed bug #17337 : CSS tokenizer fails on quotes urls
    - Fixed bug #17420 : Uncaught exception when comment before function brace
    - Fixed bug #17503 : closures formatting is not supported
   </notes>
  </release>
  <release>
   <version>
    <release>1.2.2</release>
    <api>1.2.2</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2010-01-27</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - The core PHP_CodeSniffer_File methods now understand the concept of closures (feature request #16866)
      -- Thanks to Christian Kaps for the sample code
    - Sniffs can now specify violation codes for each error and warning they add
      -- Future versions will allow you to override messages and severities using these codes
      -- Specifying a code is optional, but will be required if you wish to support overriding
    - All reports have been broken into separate classes
      -- Command line usage and report output remains the same
      -- Thanks to Gabriele Santini for the patch
    - Added an interactive mode that can be enabled using the -a command line argument
      -- Scans files and stops when it finds a file with errors
      -- Waits for user input to recheck the file (hopefully you fixed the errors) or skip the file
      -- Useful for very large code bases where full rechecks take a while
    - The reports now show the correct number of errors and warnings found
    - The isCamelCaps method now allows numbers in class names
    - The JS tokenizer now correctly identifies boolean and bitwise AND and OR tokens
    - The JS tokenzier now correctly identifies regular expressions used in conditions
    - PEAR ValidFunctionNameSniff now ignores closures
    - Squiz standard now uses the PEAR setting of 85 chars for LineLengthSniff
    - Squiz ControlStructureSpacingSniff now ensure there are no spaces around parentheses
    - Squiz LongConditionClosingCommentSniff now checks for comments at the end of try/catch statements
    - Squiz LongConditionClosingCommentSniff now checks validity of comments for short structures if they exist
    - Squiz IncrementDecrementUsageSniff now has better checking to ensure it only looks at simple variable assignments
    - Squiz PostStatementCommentSniff no longer throws errors for end function comments
    - Squiz InlineCommentSniff no longer throws errors for end function comments
    - Squiz OperatorBracketSniff now allows simple arithmetic operations in SWITCH conditions
    - Squiz ValidFunctionNameSniff now ignores closures
    - Squiz MethodScopeSniff now ignores closures
    - Squiz ClosingDeclarationCommentSniff now ignores closures
    - Squiz GlobalFunctionSniff now ignores closures
    - Squiz DisallowComparisonAssignmentSniff now ignores the assigning of arrays
    - Squiz DisallowObjectStringIndexSniff now allows indexes that contain dots and reserved words
    - Squiz standard now throws nesting level and cyclomatic complexity errors at much higher levels
    - Squiz CommentedOutCodeSniff now ignores common comment framing chacacters
    - Squiz ClassCommentSniff now ensures the open comment tag is the only content on the first line
    - Squiz FileCommentSniff now ensures the open comment tag is the only content on the first line
    - Squiz FunctionCommentSniff now ensures the open comment tag is the only content on the first line
    - Squiz VariableCommentSniff now ensures the open comment tag is the only content on the first line
    - Squiz NonExecutableCodeSniff now warns about empty return statements that are not required
    - Removed ForbiddenStylesSniff from Squiz standard
      -- It is now in in the MySource standard as BrowserSpecificStylesSniff
      -- New BrowserSpecificStylesSniff ignores files with browser-specific suffixes
    - MySource IncludeSystemSniff no longer throws errors when extending the Exception class
    - MySource IncludeSystemSniff no longer throws errors for the abstract widget class
    - MySource IncludeSystemSniff and UnusedSystemSniff now allow includes inside IF statements
    - MySource IncludeSystemSniff no longer throws errors for included widgets inside methods
    - MySource GetRequestDataSniff now throws errors for using $_FILES
    - MySource CreateWidgetTypeCallbackSniff now allows return statements in nested functions
    - MySource DisallowSelfActionsSniff now ignores abstract classes
    - Fixed a problem with the SVN pre-commit hook for PHP versions without vertical whitespace regex support
    - Fixed bug #16740 : False positives for heredoc strings and unused parameter sniff
    - Fixed bug #16794 : ValidLogicalOperatorsSniff doesn't report operators not in lowercase
    - Fixed bug #16804 : Report filename is shortened too much
    - Fixed bug #16821 : Bug in Squiz_Sniffs_WhiteSpace_OperatorSpacingSniff
      -- Thanks to Jaroslav Hanslík for the patch
    - Fixed bug #16836 : Notice raised when using semicolon to open case
    - Fixed bug #16855 : Generic standard sniffs incorrectly for define() method
    - Fixed bug #16865 : Two bugs in Squiz_Sniffs_WhiteSpace_OperatorSpacingSniff
      -- Thanks to Jaroslav Hanslík for the patch
    - Fixed bug #16902 : Inline If Declaration bug
    - Fixed bug #16960 : False positive for late static binding in Squiz/ScopeKeywordSpacingSniff
      -- Thanks to Jakub Tománek for the patch
    - Fixed bug #16976 : The phpcs attempts to process symbolic links that don't resolve to files
    - Fixed bug #17017 : Including one file in the files sniffed alters errors reported for another file
   </notes>
  </release>
  <release>
   <version>
    <release>1.2.1</release>
    <api>1.2.1</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2009-11-17</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Added a new report type --report=svnblame to show how many errors and warnings were committed by each author
      -- Also shows the percentage of their code that are errors and warnings
      -- Requires you to have the SVN command in your path
      -- Make sure SVN is storing usernames and passwords (if required) or you will need to enter them for each file
      -- You can also use the -s command line argument to see the different types of errors authors are committing
      -- You can use the -v command line argument to see all authors, even if they have no errors or warnings
    - Added a new command line argument --report-width to allow you to set the column width of screen reports
      -- Reports wont accept values less than 70 or else they get too small
      -- Can also be set via a config var: phpcs --config-set report_width 100
    - You can now get PHP_CodeSniffer to ignore a whole file by adding @codingStandardsIgnoreFile in the content
      -- If you put it in the first two lines the file wont even be tokenized, so it will be much quicker
    - Reports now print their file lists in alphabetical order
    - PEAR FunctionDeclarationSniff now reports error for incorrect closing bracket placement in multi-line definitions
    - Added Generic CallTimePassByRefenceSniff to prohibit the passing of variables into functions by reference
      -- Thanks to Florian Grandel for the contribution
    - Added Squiz DisallowComparisonAssignmentSniff to ban the assignment of comparison values to a variable
    - Added Squiz DuplicateStyleDefinitionSniff to check for duplicate CSS styles in a single class block
    - Squiz ArrayDeclarationSniff no longer checks the case of array indexes because that is not its job
    - Squiz PostStatementCommentSniff now allows end comments for class member functions
    - Squiz InlineCommentSniff now supports the checking of JS files
    - MySource CreateWidgetTypeCallbackSniff now allows the callback to be passed to another function
    - MySource CreateWidgetTypeCallbackSniff now correctly ignores callbacks used inside conditions
    - Generic MultipleStatementAlignmentSniff now enforces a single space before equals sign if max padding is reached
    - Fixed a problem in the JS tokenizer where regular expressions containing \// were not converted correctly
    - Fixed a problem tokenizing CSS files where multiple ID targets on a line would look like comments
    - Fixed a problem tokenizing CSS files where class names containing a colon looked like style definitions
    - Fixed a problem tokenizing CSS files when style statements had empty url() calls
    - Fixed a problem tokenizing CSS colours with the letter E in first half of the code
    - Squiz ColonSpacingSniff now ensures it is only checking style definitions in CSS files and not class names
    - Squiz DisallowComparisonAssignmentSniff no longer reports errors when assigning the return value of a function
    - CSS tokenizer now correctly supports multi-line comments
    - When only the case of var names differ for function comments, the error now indicates the case is different
    - Fixed an issue with Generic UnnecessaryStringConcatSniff where it incorrectly suggested removing a concat
    - Fixed bug #16530 : ScopeIndentSniff reports false positive
    - Fixed bug #16533 : Duplicate errors and warnings
    - Fixed bug #16563 : Check file extensions problem in phpcs-svn-pre-commit
      -- Thanks to Kaijung Chen for the patch
    - Fixed bug #16592 : Object operator indentation incorrect when first operator is on a new line
    - Fixed bug #16641 : Notice output
    - Fixed bug #16682 : Squiz_Sniffs_Strings_DoubleQuoteUsageSniff reports string "\0" as invalid
    - Fixed bug #16683 : Typing error in PHP_CodeSniffer_CommentParser_AbstractParser
    - Fixed bug #16684 : Bug in Squiz_Sniffs_PHP_NonExecutableCodeSniff
    - Fixed bug #16692 : Spaces in paths in Squiz_Sniffs_Debug_JavaScriptLintSniff
      -- Thanks to Jaroslav Hanslík for the patch
    - Fixed bug #16696 : Spelling error in MultiLineConditionSniff
    - Fixed bug #16697 : MultiLineConditionSniff incorrect result with inline IF
    - Fixed bug #16698 : Notice in JavaScript Tokenizer
    - Fixed bug #16736 : Multi-files sniffs aren't processed when FILE is a single directory
      -- Thanks to Alexey Shein for the patch
    - Fixed bug #16792 : Bug in Generic_Sniffs_PHP_ForbiddenFunctionsSniff
   </notes>
  </release>
  <release>
   <version>
    <release>1.2.0</release>
    <api>1.2.0</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2009-08-17</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Installed standards are now favoured over custom standards when using the cmd line arg with relative paths
    - Unit tests now use a lot less memory while running
    - Squiz standard now uses Generic EmptyStatementSniff but throws errors instead of warnings
    - Squiz standard now uses Generic UnusedFunctionParameterSniff
    - Removed unused ValidArrayIndexNameSniff from the Squiz standard
    - Fixed bug #16424 : SubversionPropertiesSniff print PHP Warning
    - Fixed bug #16450 : Constant PHP_CODESNIFFER_VERBOSITY already defined (unit tests)
    - Fixed bug #16453 : function declaration long line splitted error
    - Fixed bug #16482 : phpcs-svn-pre-commit ignores extensions parameter
   </notes>
  </release>
  <release>
   <version>
    <release>1.2.0RC3</release>
    <api>1.2.0RC3</api>
   </version>
   <stability>
    <release>beta</release>
    <api>beta</api>
   </stability>
   <date>2009-07-07</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - You can now use @codingStandardsIgnoreStart and @...End comments to suppress messages (feature request #14002)
    - A warning is now included for files without any code when short_open_tag is set to Off (feature request #12952)
    - You can now use relative paths to your custom standards with the --standard cmd line arg (feature request #14967)
    - You can now override magic methods and functions in PEAR ValidFunctionNameSniff (feature request #15830)
    - MySource IncludeSystemSniff now recognises widget action classes
    - MySource IncludeSystemSniff now knows about unit test classes and changes rules accordingly
   </notes>
  </release>
  <release>
   <version>
    <release>1.2.0RC2</release>
    <api>1.2.0RC2</api>
   </version>
   <stability>
    <release>beta</release>
    <api>beta</api>
   </stability>
   <date>2009-05-25</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Test suite can now be run using the full path to AllTests.php (feature request #16179)
    - Fixed bug #15980 : PHP_CodeSniffer change php current directory
      -- Thanks to Dolly Aswin Harahap for the patch
    - Fixed bug #16001 : Notice triggered
    - Fixed bug #16054 : phpcs-svn-pre-commit not showing any errors
    - Fixed bug #16071 : Fatal error: Uncaught PHP_CodeSniffer_Exception
    - Fixed bug #16170 : Undefined Offset -1 in MultiLineConditionSniff.php on line 68
    - Fixed bug #16175 : Bug in Squiz-IncrementDecrementUsageSniff
   </notes>
  </release>
  <release>
   <version>
    <release>1.2.0RC1</release>
    <api>1.2.0RC1</api>
   </version>
   <stability>
    <release>beta</release>
    <api>beta</api>
   </stability>
   <date>2009-03-09</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Reports that are output to a file now include a trailing newline at the end of the file
    - Fixed sniff names not shown in -vvv token processing output
    - Added Generic SubversionPropertiesSniff to check that specific svn props are set for files
      -- Thanks to Jack Bates for the contribution
    - The PHP version check can now be overridden in classes that extend PEAR FileCommentSniff
      -- Thanks to Helgi Þormar Þorbjörnsson for the suggestion
    - Added Generic ConstructorNameSniff to check for PHP4 constructor name usage
      -- Thanks to Leif Wickland for the contribution
    - Squiz standard now supports multi-line function and condition sniffs from PEAR standard
    - Squiz standard now uses Generic ConstructorNameSniff
    - Added MySource GetRequestDataSniff to ensure REQUEST, GET and POST are not accessed directly
    - Squiz OperatorBracketSniff now allows square brackets in simple unbracketed operations
    - Fixed the incorrect tokenizing of multi-line block comments in CSS files
    - Fixed bug #15383 : Uncaught PHP_CodeSniffer_Exception
    - Fixed bug #15408 : An unexpected exception has been caught: Undefined offset: 2
    - Fixed bug #15519 : Uncaught PHP_CodeSniffer_Exception
    - Fixed bug #15624 : Pre-commit hook fails with PHP errors
    - Fixed bug #15661 : Uncaught PHP_CodeSniffer_Exception
    - Fixed bug #15722 : "declare(encoding = 'utf-8');" leads to "Missing file doc comment"
    - Fixed bug #15910 : Object operator indention not calculated correctly
   </notes>
  </release>
  <release>
   <version>
    <release>1.2.0a1</release>
    <api>1.2.0a1</api>
   </version>
   <stability>
    <release>alpha</release>
    <api>alpha</api>
   </stability>
   <date>2008-12-18</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - PHP_CodeSniffer now has a CSS tokenizer for checking CSS files
    - Added support for a new multi-file sniff that sniffs all processed files at once
    - Added new output format --report=emacs to output errors using the emacs standard compile output format
      -- Thanks to Len Trigg for the contribution
    - Reports can now be written to a file using the --report-file command line argument (feature request #14953)
      -- The report is also written to screen when using this argument
    - The CheckStyle, CSV and XML reports now include a source for each error and warning (feature request #13242)
      -- A new report type --report=source can be used to show you the most common errors in your files
    - Added new command line argument -s to show error sources in all reports
    - Added new command line argument --sniffs to specify a list of sniffs to restrict checking to
      -- Uses the sniff source codes that are optionally displayed in reports
    - Changed the max width of error lines from 80 to 79 chars to stop blank lines in the default windows cmd window
    - PHP_CodeSniffer now has a token for an asperand (@ symbol) so sniffs can listen for them
      -- Thanks to Andy Brockhurst for the patch
    - Added Generic DuplicateClassNameSniff that will warn if the same class name is used in multiple files
      -- Not currently used by any standard; more of a multi-file sniff sample than anything useful
    - Added Generic NoSilencedErrorsSniff that warns if PHP errors are being silenced using the @ symbol
      -- Thanks to Andy Brockhurst for the contribution
    - Added Generic UnnecessaryStringConcatSniff that checks for two strings being concatenated
    - Added PEAR FunctionDeclarationSniff to enforce the new multi-line function declaration PEAR standard
    - Added PEAR MultiLineAssignmentSniff to enforce the correct indentation of multi-line assignments
    - Added PEAR MultiLineConditionSniff to enforce the new multi-line condition PEAR standard
    - Added PEAR ObjectOperatorIndentSniff to enforce the new chained function call PEAR standard
    - Added MySource DisallowSelfActionSniff to ban the use of self::method() calls in Action classes
    - Added MySource DebugCodeSniff to ban the use of Debug::method() calls
    - Added MySource CreateWidgetTypeCallback sniff to check callback usage in widget type create methods
    - Added Squiz DisallowObjectStringIndexSniff that forces object dot notation in JavaScript files
      -- Thanks to Sertan Danis for the contribution
    - Added Squiz DiscouragedFunctionsSniff to warn when using debug functions
    - Added Squiz PropertyLabelSniff to check whitespace around colons in JS property and label declarations
    - Added Squiz DuplicatePropertySniff to check for duplicate property names in JS classes
    - Added Squiz ColonSpacingSniff to check for spacing around colons in CSS style definitions
    - Added Squiz SemicolonSpacingSniff to check for spacing around semicolons in CSS style definitions
    - Added Squiz IdentationSniff to check for correct indentation of CSS files
    - Added Squiz ColourDefinitionSniff to check that CSS colours are defined in uppercase and using shorthand
    - Added Squiz EmptyStyleDefinitionSniff to check for CSS style definitions without content
    - Added Squiz EmptyClassDefinitionSniff to check for CSS class definitions without content
    - Added Squiz ClassDefinitionOpeningBraceSpaceSniff to check for spaces around opening brace of CSS class definitions
    - Added Squiz ClassDefinitionClosingBraceSpaceSniff to check for a single blank line after CSS class definitions
    - Added Squiz ClassDefinitionNameSpacingSniff to check for a blank lines inside CSS class definition names
    - Added Squiz DisallowMultipleStyleDefinitionsSniff to check for multiple style definitions on a single line
    - Added Squiz DuplicateClassDefinitionSniff to check for duplicate CSS class blocks that can be merged
    - Added Squiz ForbiddenStylesSniff to check for usage of browser specific styles
    - Added Squiz OpacitySniff to check for incorrect opacity values in CSS
    - Added Squiz LowercaseStyleDefinitionSniff to check for styles that are not defined in lowercase
    - Added Squiz MissingColonSniff to check for style definitions where the colon has been forgotten
    - Added Squiz MultiLineFunctionDeclarationSniff to check that multi-line declarations contain one param per line
    - Added Squiz JSLintSniff to check for JS errors using the jslint.js script through Rhino
      -- Set jslint path using phpcs --config-set jslint_path /path/to/jslint.js
      -- Set rhino path using phpcs --config-set rhino_path /path/to/rhino
    - Added Generic TodoSniff that warns about comments that contain the word TODO
    - Removed MultipleStatementAlignmentSniff from the PEAR standard as alignment is now optional
    - Generic ForbiddenFunctionsSniff now has protected member var to specify if it should use errors or warnings
    - Generic MultipleStatementAlignmentSniff now has correct error message if assignment is on a new line
    - Generic MultipleStatementAlignmentSniff now has protected member var to allow it to ignore multi-line assignments
    - Generic LineEndingsSniff now supports checking of JS files
    - Generic LineEndingsSniff now supports checking of CSS files
    - Generic DisallowTabIndentSniff now supports checking of CSS files
    - Squiz DoubleQuoteUsageSniff now bans the use of variables in double quoted strings in favour of concatenation
    - Squiz SuperfluousWhitespaceSniff now supports checking of JS files
    - Squiz SuperfluousWhitespaceSniff now supports checking of CSS files
    - Squiz DisallowInlineIfSniff now supports checking of JS files
    - Squiz SemicolonSpacingSniff now supports checking of JS files
    - Squiz PostStatementCommentSniff now supports checking of JS files
    - Squiz FunctionOpeningBraceSpacingSniff now supports checking of JS files
    - Squiz FunctionClosingBraceSpacingSniff now supports checking of JS files
      -- Empty JS functions must have their opening and closing braces next to each other
    - Squiz ControlStructureSpacingSniff now supports checking of JS files
    - Squiz LongConditionClosingCommentSniff now supports checking of JS files
    - Squiz OperatorSpacingSniff now supports checking of JS files
    - Squiz SwitchDeclarationSniff now supports checking of JS files
    - Squiz CommentedOutCodeSniff now supports checking of CSS files
    - Squiz DisallowSizeFunctionsInLoopsSniff now supports checking of JS files for the use of object.length
    - Squiz DisallowSizeFunctionsInLoopsSniff no longer complains about size functions outside of the FOR condition
    - Squiz ControlStructureSpacingSniff now bans blank lines at the end of a control structure
    - Squiz ForLoopDeclarationSniff no longer throws errors for JS FOR loops without semicolons
    - Squiz MultipleStatementAlignmentSniff no longer throws errors if a statement would take more than 8 spaces to align
    - Squiz standard now uses Genric TodoSniff
    - Squiz standard now uses Genric UnnecessaryStringConcatSniff
    - Squiz standard now uses PEAR MultiLineAssignmentSniff
    - Squiz standard now uses PEAR MultiLineConditionSniff
    - Zend standard now uses OpeningFunctionBraceBsdAllmanSniff (feature request #14647)
    - MySource JoinStringsSniff now bans the use of inline array joins and suggests the + operator
    - Fixed incorrect errors that can be generated from abstract scope sniffs when moving to a new file
    - Core tokenizer now matches orphaned curly braces in the same way as square brackets
    - Whitespace tokens at the end of JS files are now added to the token stack
    - JavaScript tokenizer now identifies properties and labels as new token types
    - JavaScript tokenizer now identifies object definitions as a new token type and matches curly braces for them
    - JavaScript tokenizer now identifies DIV_EQUAL and MUL_EQUAL tokens
    - Improved regular expression detection in the JavaScript tokenizer
    - Improve AbstractPatternSniff support so it can listen for any token type, not just weighted tokens
    - Fixed Squiz DoubleQuoteUsageSniff so it works correctly with short_open_tag=Off
    - Fixed bug #14409 : Output of warnings to log file
    - Fixed bug #14520 : Notice: Undefined offset: 1 in /usr/share/php/PHP/CodeSniffer/File.php on line
    - Fixed bug #14637 : Call to processUnknownArguments() misses second parameter $pos
      -- Thanks to Peter Buri for the patch
    - Fixed bug #14889 : Lack of clarity: licence or license
    - Fixed bug #15008 : Nested Parentheses in Control Structure Sniffs
    - Fixed bug #15091 : pre-commit hook attempts to sniff folders
      -- Thanks to Bruce Weirdan for the patch
    - Fixed bug #15124 : AbstractParser.php uses deprecated split() function
      -- Thanks to Sebastian Bergmann for the patch
    - Fixed bug #15188 : PHPCS vs HEREDOC strings
    - Fixed bug #15231 : Notice: Uninitialized string offset: 0 in FileCommentSniff.php on line 555
    - Fixed bug #15336 : Notice: Undefined offset: 2 in /usr/share/php/PHP/CodeSniffer/File.php on line
   </notes>
  </release>
  <release>
   <version>
    <release>1.1.0</release>
    <api>1.1.0</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2008-07-14</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - PEAR FileCommentSniff now allows tag orders to be overridden in child classes
      -- Thanks to Jeff Hodsdon for the patch
    - Added Generic DisallowMultipleStatementsSniff to ensure there is only one statement per line
    - Squiz standard now uses DisallowMultipleStatementsSniff
    - Fixed error in Zend ValidVariableNameSniff when checking vars in form: $class->{$var}
    - Fixed bug #14077 : Fatal error: Uncaught PHP_CodeSniffer_Exception: $stackPtr is not a class member
    - Fixed bug #14168 : Global Function -> Static Method and __autoload()
    - Fixed bug #14238 : Line length not checket at last line of a file
    - Fixed bug #14249 : wrong detection of scope_opener
    - Fixed bug #14250 : ArrayDeclarationSniff emit warnings at malformed array
    - Fixed bug #14251 : --extensions option doesn't work
   </notes>
  </release>
  <release>
   <version>
    <release>1.1.0RC3</release>
    <api>1.1.0RC3</api>
   </version>
   <stability>
    <release>beta</release>
    <api>beta</api>
   </stability>
   <date>2008-07-03</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - PEAR FileCommentSniff now allows tag orders to be overridden in child classes
      -- Thanks to Jeff Hodsdon for the patch
    - Added Generic DisallowMultipleStatementsSniff to ensure there is only one statement per line
    - Squiz standard now uses DisallowMultipleStatementsSniff
    - Fixed error in Zend ValidVariableNameSniff when checking vars in form: $class->{$var}
    - Fixed bug #14077 : Fatal error: Uncaught PHP_CodeSniffer_Exception: $stackPtr is not a class member
    - Fixed bug #14168 : Global Function -> Static Method and __autoload()
    - Fixed bug #14238 : Line length not checket at last line of a file
    - Fixed bug #14249 : wrong detection of scope_opener
    - Fixed bug #14250 : ArrayDeclarationSniff emit warnings at malformed array
    - Fixed bug #14251 : --extensions option doesn't work
   </notes>
  </release>
  <release>
   <version>
    <release>1.1.0RC2</release>
    <api>1.1.0RC2</api>
   </version>
   <stability>
    <release>beta</release>
    <api>beta</api>
   </stability>
   <date>2008-06-13</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Permission denied errors now stop script execution but still display current errors (feature request #14076)
    - Added Squiz ValidArrayIndexNameSniff to ensure array indexes do not use camel case
    - Squiz ArrayDeclarationSniff now ensures arrays are not declared with camel case index values
    - PEAR ValidVariableNameSniff now alerts about a possible parse error for member vars inside an interface
    - Fixed bug #13921 : js parsing fails for comments on last line of file
    - Fixed bug #13922 : crash in case of malformed (but tokenized) php file
      -- PEAR and Squiz ClassDeclarationSniff now throw warnings for possible parse errors
      -- Squiz ValidClassNameSniff now throws warning for possible parse errors
      -- Squiz ClosingDeclarationCommentSniff now throws additonal warnings for parse errors
   </notes>
  </release>
  <release>
   <version>
    <release>1.1.0RC1</release>
    <api>1.1.0RC1</api>
   </version>
   <stability>
    <release>beta</release>
    <api>beta</api>
   </stability>
   <date>2008-05-13</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Added support for multiple tokenizers so PHP_CodeSniffer can check more than just PHP files
      -- PHP_CodeSniffer now has a JS tokenizer for checking JavaScript files
      -- Sniffs need to be updated to work with additional tokenizers, or new sniffs written for them
   - phpcs now exits with status 2 if the tokenier extension has been disabled (feature request #13269)
   - Added scripts/phpcs-svn-pre-commit that can be used as an SVN pre-commit hook
     -- Also reworked the way the phpcs script works to make it easier to wrap it with other functionality
     -- Thanks to Jack Bates for the contribution
   - Fixed error in phpcs error message when a supplied file does not exist
   - Fixed a cosmetic error in AbstractPatternSniff where the "found" string was missing some content
   - Added sniffs that implement part of the PMD rule catalog to the Generic standard
     -- Thanks to Manuel Pichler for the contribution of all these sniffs.
   - Squiz FunctionCommentThrowTagSniff no longer throws errors for function that only throw variables
   - Generic ScopeIndentSniff now has private member to enforce exact indent matching
   - Replaced Squiz DisallowCountInLoopsSniff with Squiz DisallowSizeFunctionsInLoopsSniff
     -- Thanks to Jan Miczaika for the sniff
   - Squiz BlockCommentSniff now checks inline doc block comments
   - Squiz InlineCommentSniff now checks inline doc block comments
   - Squiz BlockCommentSniff now checks for no blank line before first comment in a function
   - Squiz DocCommentAlignmentSniff now ignores inline doc block comments
   - Squiz ControlStructureSpacingSniff now ensures no blank lines at the start of control structures
   - Squiz ControlStructureSpacingSniff now ensures no blank lines between control structure closing braces
   - Squiz IncrementDecrementUsageSniff now ensures inc/dec ops are bracketed in string concats
   - Squiz IncrementDecrementUsageSniff now ensures inc/dec ops are not used in arithmetic operations
   - Squiz FunctionCommentSniff no longer throws errors if return value is mixed but function returns void somewhere
   - Squiz OperatorBracketSniff no allows function call brackets to count as operator brackets
   - Squiz DoubleQuoteUsageSniff now supports \x \f and \v (feature request #13365)
   - Squiz ComparisonOperatorUsageSniff now supports JS files
   - Squiz ControlSignatureSniff now supports JS files
   - Squiz ForLoopDeclarationSniff now supports JS files
   - Squiz OperatorBracketSniff now supports JS files
   - Squiz InlineControlStructureSniff now supports JS files
   - Generic LowerCaseConstantSniff now supports JS files
   - Generic DisallowTabIndentSniff now supports JS files
   - Generic MultipleStatementAlignmentSniff now supports JS files
   - Added Squiz ObjectMemberCommaSniff to ensure the last member of a JS object is not followed by a comma
   - Added Squiz ConstantCaseSniff to ensure the PHP constants are uppercase and JS lowercase
   - Added Squiz JavaScriptLintSniff to check JS files with JSL
     -- Set path using phpcs --config-set jsl_path /path/to/jsl
   - Added MySource FirebugConsoleSniff to ban the use of "console" for JS variable and function names
   - Added MySource JoinStringsSniff to enforce the use of join() to concatenate JS strings
   - Added MySource AssignThisSniff to ensure this is only assigned to a var called self
   - Added MySource DisallowNewWidgetSniff to ban manual creation of widget objects
   - Removed warning shown in Zend CodeAnalyzerSniff when the ZCA path is not set
   - Fixed error in Squiz ValidVariableNameSniff when checking vars in the form $obj->$var
   - Fixed error in Squiz DisallowMultipleAssignmentsSniff when checking vars in the form $obj->$var
   - Fixed error in Squiz InlineCommentSniff where comments for class constants were seen as inline
   - Fixed error in Squiz BlockCommentSniff where comments for class constants were not ignored
   - Fixed error in Squiz OperatorBracketSniff where negative numbers were ignored during comparisons
   - Fixed error in Squiz FunctionSpacingSniff where functions after member vars reported incorrect spacing
   - Fixed bug #13062 : Interface comments aren't handled in PEAR standard
     -- Thanks to Manuel Pichler for the path
   - Fixed bug #13119 : php minimum requirement need to be fix
   - Fixed bug #13156 : Bug in Squiz_Sniffs_PHP_NonExecutableCodeSniff
   - Fixed bug #13158 : Strange behaviour in AbstractPatternSniff
   - Fixed bug #13169 : Undefined variables
   - Fixed bug #13178 : Catch exception in File.php
   - Fixed bug #13254 : Notices output in checkstyle report causes XML issues
   - Fixed bug #13446 : crash with src of phpMyAdmin
     -- Thanks to Manuel Pichler for the path
   </notes>
  </release>
  <release>
   <version>
    <release>1.1.0a1</release>
    <api>1.1.0a1</api>
   </version>
   <stability>
    <release>alpha</release>
    <api>alpha</api>
   </stability>
   <date>2008-04-21</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Fixed error in PEAR ValidClassNameSniff when checking class names with double underscores
    - Moved Squiz InlineControlStructureSniff into Generic standard
    - PEAR standard now throws warnings for inline control structures
    - Squiz OutputBufferingIndentSniff now ignores the indentation of inline HTML
    - MySource IncludeSystemSniff now ignores usage of ZipArchive
    - Removed "function" from error messages for Generic function brace sniffs (feature request #13820)
    - Generic UpperCaseConstantSniff no longer throws errors for delcare(ticks = ...)
      -- Thanks to Josh Snyder for the patch
    - Squiz ClosingDeclarationCommentSniff and AbstractVariableSniff now throw warnings for possible parse errors
    - Fixed bug #13827 : AbstractVariableSniff throws "undefined index"
    - Fixed bug #13846 : Bug in Squiz.NonExecutableCodeSniff
    - Fixed bug #13849 : infinite loop in PHP_CodeSniffer_File::findNext()
   </notes>
  </release>
  <release>
   <version>
    <release>1.0.1</release>
    <api>1.0.1</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2008-02-04</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Squiz ArrayDeclarationSniff now throws error if the array keyword is followed by a space
    - Squiz ArrayDeclarationSniff now throws error for empty multi-line arrays
    - Squiz ArrayDeclarationSniff now throws error for multi-line arrays with a single value
    - Squiz DocCommentAlignmentSniff now checks for a single space before tags inside docblocks
    - Squiz ForbiddenFunctionsSniff now disallows is_null() to force use of (=== NULL) instead
    - Squiz VariableCommentSniff now continues throwing errors after the first one is found
    - Squiz SuperfluousWhitespaceSniff now throws errors for multiple blank lines inside functions
    - MySource IncludedSystemSniff now checks extended class names
    - MySource UnusedSystemSniff now checks extended and implemented class names
    - MySource IncludedSystemSniff now supports includeWidget()
    - MySource UnusedSystemSniff now supports includeWidget()
    - Added PEAR ValidVariableNameSniff to check that only private member vars are prefixed with an underscore
    - Added Squiz DisallowCountInLoopsSniff to check for the use of count() in FOR and WHILE loop conditions
    - Added MySource UnusedSystemSniff to check for included classes that are never used
    - Fixed a problem that caused the parentheses map to sometimes contain incorrect values
    - Fixed bug #12767 : Cant run phpcs from dir with PEAR subdir
    - Fixed bug #12773 : Reserved variables are not detected in strings
      -- Thanks to Wilfried Loche for the patch
    - Fixed bug #12832 : Tab to space conversion does not work
    - Fixed bug #12888 : extra space indentation = Notice: Uninitialized string offset...
    - Fixed bug #12909 : Default generateDocs function does not work under linux
      -- Thanks to Paul Smith for the patch
    - Fixed bug #12957 : PHP 5.3 magic method __callStatic
      -- Thanks to Manuel Pichler for the patch
   </notes>
  </release>
  <release>
   <version>
    <release>1.0.0</release>
    <api>1.0.0</api>
   </version>
   <stability>
    <release>stable</release>
    <api>stable</api>
   </stability>
   <date>2007-12-21</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - You can now specify the full path to a coding standard on the command line (feature request #11886)
      -- This allows you to use standards that are stored outside of PHP_CodeSniffer's own Standard dir
      -- You can also specify full paths in the CodingStandard.php include and exclude methods
      -- Classes, dirs and files need to be names as if the standard was part of PHP_CodeSniffer
      -- Thanks to Dirk Thomas for the doc generator patch and testing
    - Modified the scope map to keep checking after 3 lines for some tokens (feature request #12561)
      -- Those tokens that must have an opener (like T_CLASS) now keep looking until EOF
      -- Other tokens (like T_FUNCTION) still stop after 3 lines for performance
    - You can now esacpe commas in ignore patterns so they can be matched in file names
      -- Thanks to Carsten Wiedmann for the patch
    - Config data is now cached in a global var so the file system is not hit so often
      -- You can also set config data temporarily for the script if you are using your own external script
      -- Pass TRUE as the third argument to PHP_CodeSniffer::setConfigData()
    - PEAR ClassDeclarationSniff no longer throws errors for multi-line class declarations
    - Squiz ClassDeclarationSniff now ensures there is one blank line after a class closing brace
    - Squiz ClassDeclarationSniff now throws errors for a missing end PHP tag after the end class tag
    - Squiz IncrementDecrementUsageSniff no longer throws errors when -= and += are being used with vars
    - Squiz SwitchDeclarationSniff now throws errors for switch statements that do not contain a case statement
      -- Thanks to Sertan Danis for the patch
    - MySource IncludeSystemSniff no longer throws errors for the Util package
    - Fixed bug #12621 : "space after AS" check is wrong
      -- Thanks to Satoshi Oikawa for the patch
    - Fixed bug #12645 : error message is wrong
      -- Thanks to Renoiv for the patch
    - Fixed bug #12651 : Increment/Decrement Operators Usage at -1
   </notes>
  </release>
  <release>
   <version>
    <release>1.0.0RC3</release>
    <api>1.0.0RC3</api>
   </version>
   <stability>
    <release>beta</release>
    <api>beta</api>
   </stability>
   <date>2007-11-30</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Added new command line argument --tab-width that will convert tabs to spaces before testing
      -- This allows you to use the existing sniffs that check for spaces even when you use tabs
      -- Can also be set via a config var: phpcs --config-set tab_width 4
      -- A value of zero (the default) tells PHP_CodeSniffer not to replace tabs with spaces
    - You can now change the default report format from "full" to something else
        -- Run: phpcs --config-set report_format [format]
    - Improved performance by optimising the way the scope map is created during tokenising
    - Added new Squiz DisallowInlineIfSniff to disallow the usage of inline IF statements
    - Fixed incorrect errors being thrown for nested switches in Squiz SwitchDeclarationSniff
    - PEAR FunctionCommentSniff no longer complains about missing comments for @throws tags
    - PEAR FunctionCommentSniff now throws error for missing exception class name for @throws tags
    - PHP_CodeSniffer_File::isReference() now correctly returns for functions that return references
    - Generic LineLengthSniff no longer warns about @version lines with CVS or SVN id tags
    - Generic LineLengthSniff no longer warns about @license lines with long URLs
    - Squiz FunctionCommentThrowTagSniff no longer complains about throwing variables
    - Squiz ComparisonOperatorUsageSniff no longer throws incorrect errors for inline IF statements
    - Squiz DisllowMultipleAssignmentsSniff no longer throws errors for assignments in inline IF statements
    - Fixed bug #12455 : CodeSniffer treats content inside heredoc as PHP code
    - Fixed bug #12471 : Checkstyle report is broken
    - Fixed bug #12476 : PHP4 destructors are reported as error
    - Fixed bug #12513 : Checkstyle XML messages need to be utf8_encode()d
      -- Thanks to Sebastian Bergmann for the patch.
    - Fixed bug #12517 : getNewlineAfter() and dos files
   </notes>
  </release>
  <release>
   <version>
    <release>1.0.0RC2</release>
    <api>1.0.0RC2</api>
   </version>
   <stability>
    <release>beta</release>
    <api>beta</api>
   </stability>
   <date>2007-11-14</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Added a new Checkstyle report format
      -- Like the current XML format but modified to look like Checkstyle output
      -- Thanks to Manuel Pichler for helping get the format correct
    - You can now hide warnings by default
        -- Run: phpcs --config-set show_warnings 0
        -- If warnings are hidden by default, use the new -w command line argument to override
    - Added new command line argument --config-delete to delete a config value and revert to the default
    - Improved overall performance by optimising tokenising and next/prev methods (feature request #12421)
      -- Thanks to Christian Weiske for the patch
    - Added FunctionCallSignatureSniff to Squiz standard
    - Added @subpackage support to file and class comment sniffs in PEAR standard (feature request #12382)
      -- Thanks to Carsten Wiedmann for the patch
    - An error is now displayed if you use a PHP version less than 5.1.0 (feature request #12380)
      -- Thanks to Carsten Wiedmann for the patch
    - phpcs now exits with status 2 if it receives invalid input (feature request #12380)
      -- This is distinct from status 1, which indicates errors or warnings were found
    - Added new Squiz LanguageConstructSpacingSniff to throw errors for additional whitespace after echo etc.
    - Removed Squiz ValidInterfaceNameSniff
    - PEAR FunctionCommentSniff no longer complains about unknown tags
    - Fixed incorrect errors about missing function comments in PEAR FunctionCommentSniff
    - Fixed incorrect function docblock detection in Squiz FunctionCommentSniff
    - Fixed incorrect errors for list() in Squiz DisallowMultipleAssignmentsSniff
    - Errors no longer thrown if control structure is followed by a CASE's BREAK in Squiz ControlStructureSpacingSniff
    - Fixed bug #12368 : Autoloader cannot be found due to include_path override
      -- Thanks to Richard Quadling for the patch
    - Fixed bug #12378 : equal sign alignments problem with while()
   </notes>
  </release>
  <release>
   <version>
    <release>1.0.0RC1</release>
    <api>1.0.0RC1</api>
   </version>
   <stability>
    <release>beta</release>
    <api>beta</api>
   </stability>
   <date>2007-11-01</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Main phpcs script can now be run from a CVS checkout without installing the package
    - Added a new CSV report format
      -- Header row indicates what position each element is in
      -- Always use the header row to determine positions rather than assuming the format, as it may change
    - XML and CSV report formats now contain information about which column the error occurred at
      -- Useful if you want to highlight the token that caused the error in a custom application
    - Square bracket tokens now have bracket_opener and bracket_closer set
    - Added new Squiz SemicolonSpacingSniff to throw errors if whitespace is found before a semicolon
    - Added new Squiz ArrayBracketSpacingSniff to throw errors if whitespace is found around square brackets
    - Added new Squiz ObjectOperatorSpacingSniff to throw errors if whitespace is found around object operators
    - Added new Squiz DisallowMultipleAssignmentsSniff to throw errors if multiple assignments are on the same line
    - Added new Squiz ScopeKeywordSpacingSniff to throw errors if there is not a single space after a scope modifier
    - Added new Squiz ObjectInstantiationSniff to throw errors if new objects are not assigned to a variable
    - Added new Squiz FunctionDuplicateArgumentSniff to throw errors if argument is declared multiple times in a function
    - Added new Squiz FunctionOpeningBraceSpaceSniff to ensure there are no blank lines after a function open brace
    - Added new Squiz CommentedOutCodeSniff to warn about comments that looks like they are commented out code blocks
    - Added CyclomaticComplexitySniff to Squiz standard
    - Added NestingLevelSniff to Squiz standard
    - Squiz ForbiddenFunctionsSniff now recommends echo() instead of print()
    - Squiz ValidLogicalOperatorsSniff now recommends ^ instead of xor
    - Squiz SwitchDeclarationSniff now contains more checks
      -- A single space is required after the case keyword
      -- No space is allowed before the colon in a case or default statement
      -- All switch statements now require a default case
      -- Default case must contain a break statement
      -- Empty default case must contain a comment describing why the default is ignored
      -- Empty case statements are not allowed
      -- Case and default statements must not be followed by a blank line
      -- Break statements must be followed by a blank line or the closing brace
      -- There must be no blank line before a break statement
    - Squiz standard is now using the PEAR IncludingFileSniff
    - PEAR ClassCommentSniff no longer complains about unknown tags
    - PEAR FileCommentSniff no longer complains about unknown tags
    - PEAR FileCommentSniff now accepts multiple @copyright tags
    - Squiz BlockCommentSniff now checks that comment starts with a capital letter
    - Squiz InlineCommentSniff now has better checking to ensure comment starts with a capital letter
    - Squiz ClassCommentSniff now checks that short and long comments start with a capital letter
    - Squiz FunctionCommentSniff now checks that short, long and param comments start with a capital letter
    - Squiz VariableCommentSniff now checks that short and long comments start with a capital letter
    - Fixed error with multi-token array indexes in Squiz ArrayDeclarationSniff
    - Fixed error with checking shorthand IF statements without a semicolon in Squiz InlineIfDeclarationSniff
    - Fixed error where constants used as defulat values in function declarations were seen as type hints
    - Fixed bug #12316 : PEAR is no longer the default standard
    - Fixed bug #12321 : wrong detection of missing function docblock
   </notes>
  </release>
  <release>
   <version>
    <release>0.9.0</release>
    <api>0.9.0</api>
   </version>
   <stability>
    <release>beta</release>
    <api>beta</api>
   </stability>
   <date>2007-09-24</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Added a config system for setting config data across phpcs runs
    - You can now change the default coding standard from PEAR to something else
      -- Run: phpcs --config-set default_standard [standard]
    - Added new Zend coding standard to check code against the Zend Framework standards
      -- The complete standard is not yet implemented
      -- Specify --standard=Zend to use
      -- Thanks to Johann-Peter Hartmann for the contribution of some sniffs
      -- Thanks to Holger Kral for the Code Analyzer sniff
   </notes>
  </release>
  <release>
   <version>
    <release>0.8.0</release>
    <api>0.8.0</api>
   </version>
   <stability>
    <release>beta</release>
    <api>beta</api>
   </stability>
   <date>2007-08-08</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Added new XML report format; --report=xml (feature request #11535)
      -- Thanks to Brett Bieber for the patch
    - Added new command line argument --ignore to specify a list of files to skip (feature request #11556)
    - Added PHPCS and MySource coding standards into the core install
    - Scope map no longer gets confused by curly braces that act as string offsets
    - Removed CodeSniffer/SniffException.php as it is no longer used
    - Unit tests can now be run directly from a CVS checkout
    - Made private vars and functions protected in PHP_CodeSniffer class so this package can be overridden
    - Added new Metrics category to Generic coding standard
      -- Contains Cyclomatic Complexity and Nesting Level sniffs
      -- Thanks to Johann-Peter Hartmann for the contribution
    - Added new Generic DisallowTabIndentSniff to throw errors if tabs are used for indentation (feature request #11738)
      -- PEAR and Squiz standards use this new sniff to throw more specific indentation errors
    - Generic MultipleStatementAlignmentSniff has new private var to set a padding size limit (feature request #11555)
    - Generic MultipleStatementAlignmentSniff can now handle assignments that span multiple lines (feature request #11561)
    - Generic LineLengthSniff now has a max line length after which errors are thrown instead of warnings
      -- BC BREAK: Override the protected member var absoluteLineLimit and set it to zero in custom LineLength sniffs
      -- Thanks to Johann-Peter Hartmann for the contribution
    - Comment sniff errors about incorrect tag orders are now more descriptive (feature request #11693)
    - Fixed bug #11473 : Invalid CamelCaps name when numbers used in names
   </notes>
  </release>
  <release>
   <version>
    <release>0.7.0</release>
    <api>0.7.0</api>
   </version>
   <stability>
    <release>beta</release>
    <api>beta</api>
   </stability>
   <date>2007-07-02</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - BC BREAK: EOL character is now auto-detected and used instead of hard-coded \n
      -- Pattern sniffs must now specify "EOL" instead of "\n" or "\r\n" to use auto-detection
      -- Please use $phpcsFile->eolChar to check for newlines instead of hard-coding "\n" or "\r\n"
      -- Comment parser classes now require you to pass $phpcsFile as an additional argument
    - BC BREAK: Included and excluded sniffs now require .php extension
      -- Please update your coding standard classes and add ".php" to all sniff entries
      -- See CodeSniffer/Standards/PEAR/PEARCodingStandard.php for an example

    - Fixed error where including a directory of sniffs in a coding standard class did not work
    - Coding standard classes can now specify a list of sniffs to exclude as well as include (feature request #11056)
    - Two uppercase characters can now be placed side-by-side in class names in Squiz ValidClassNameSniff
    - SVN tags now allowed in PEAR file doc blocks (feature request #11038)
      -- Thanks to Torsten Roehr for the patch
    - Private methods in commenting sniffs and comment parser are now protected (feature request #11087)
    - Added Generic LineEndingsSniff to check the EOL character of a file
    - PEAR standard now only throws one error per file for incorrect line endings (eg. /r/n)
    - Command line arg -v now shows number of registered sniffs
    - Command line arg -vvv now shows list of registered sniffs
    - Squiz ControlStructureSpacingSniff no longer throws errors if the control structure is at the end of the script
    - Squiz FunctionCommentSniff now throws error for "return void" if function has return statement
    - Squiz FunctionCommentSniff now throws error for functions that return void but specify something else
    - Squiz ValidVariableNameSniff now allows multiple uppercase letters in a row
    - Squiz ForEachLoopDeclarationSniff now throws error for AS keyword not being lowercase
    - Squiz SwitchDeclarationSniff now throws errors for CASE/DEFAULT/BREAK keywords not being lowercase
    - Squiz ArrayDeclarationSniff now handles multi-token array values when checking alignment
    - Squiz standard now enforces a space after cast tokens
    - Generic MultipleStatementAlignmentSniff no longer gets confused by assignments inside FOR conditions
    - Generic MultipleStatementAlignmentSniff no longer gets confused by the use of list()
    - Added Generic SpaceAfterCastSniff to ensure there is a single space after a cast token
    - Added Generic NoSpaceAfterCastSniff to ensure there is no whitespace after a cast token
    - Added PEAR ClassDeclarationSniff to ensure the opening brace of a class is on the line after the keyword
    - Added Squiz ScopeClosingBraceSniff to ensure closing braces are aligned correctly
    - Added Squiz EvalSniff to discourage the use of eval()
    - Added Squiz LowercaseDeclarationSniff to ensure all declaration keywords are lowercase
    - Added Squiz LowercaseClassKeywordsSniff to ensure all class declaration keywords are lowercase
    - Added Squiz LowercaseFunctionKeywordsSniff to ensure all function declaration keywords are lowercase
    - Added Squiz LowercasePHPFunctionsSniff to ensure all calls to inbuilt PHP functions are lowercase
    - Added Squiz CastSpacingSniff to ensure cast statements dont contain whitespace
    - Errors no longer thrown when checking 0 length files with verbosity on
    - Fixed bug #11105 : getIncludedSniffs() not working anymore
      -- Thanks to Blair Robertson for the patch
    - Fixed bug #11120 : Uninitialized string offset in AbstractParser.php on line 200
   </notes>
  </release>
  <release>
   <version>
    <release>0.6.0</release>
    <api>0.6.0</api>
   </version>
   <stability>
    <release>beta</release>
    <api>beta</api>
   </stability>
   <date>2007-05-15</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - The number of errors and warnings found is now shown for each file while checking the file if verbosity is enabled
    - Now using PHP_EOL instead of hard-coded \n so output looks good on Windows (feature request #10761)
      - Thanks to Carsten Wiedmann for the patch.
    - phpcs now exits with status 0 (no errors) or 1 (errors found) (feature request #10348)
    - Added new -l command line argument to stop recursion into directories (feature request #10979)
    - Fixed variable name error causing incorrect error message in Squiz ValidVariableNameSniff
    - Fixed bug #10757 : Error in ControlSignatureSniff
    - Fixed bugs #10751, #10777 : Sniffer class paths handled incorrectly in Windows
      - Thanks to Carsten Wiedmann for the patch.
    - Fixed bug #10961 : Error "Last parameter comment requires a blank newline after it" thrown
    - Fixed bug #10983 : phpcs outputs notices when checking invalid PHP
    - Fixed bug #10980 : Incorrect warnings for equals sign
   </notes>
  </release>
  <release>
   <version>
    <release>0.5.0</release>
    <api>0.5.0</api>
   </version>
   <stability>
    <release>beta</release>
    <api>beta</api>
   </stability>
   <date>2007-04-17</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - BC BREAK: Coding standards now require a class to be added so PHP_CodeSniffer can get information from them
      - Please read the end user docs for info about the new class required for all coding standards

    - Coding standards can now include sniffs from other standards, or whole standards, without writing new sniff files
    - PHP_CodeSniffer_File::isReference() now correctly returns for references in function declarations
    - PHP_CodeSniffer_File::isReference() now returns false if you don't pass it a T_BITWISE_AND token
    - PHP_CodeSniffer_File now stores the absolute path to the file so sniffs can check file locations correctly
    - Fixed undefined index error in AbstractVariableSniff for variables inside an interface function definition
    - Added MemberVarSpacingSniff to Squiz standard to enforce one-line spacing between member vars
    - Add FunctionCommentThrowTagSniff to Squiz standard to check that @throws tags are correct
    - Fixed problems caused by references and type hints in Squiz FunctionDeclarationArgumentSpacingSniff
    - Fixed problems with errors not being thrown for some misaligned @param comments in Squiz FunctionCommentSniff
    - Fixed badly spaced comma error being thrown for "extends" class in Squiz ClassDeclarationSniff
    - Errors no longer thrown for class method names in Generic ForbiddenFunctionsSniff
    - Errors no longer thrown for type hints in front of references in Generic UpperCaseConstantNameSniff
    - Errors no longer thrown for correctly indented buffered lines in Squiz ScopeIndexSniff
    - Errors no longer thrown for user-defined functions named as forbidden functions in Generic ForbiddenFunctionsSniff
    - Errors no longer thrown on __autoload functions in PEAR ValidFunctionNameSniff
    - Errors now thrown for __autoload methods in PEAR ValidFunctionNameSniff
    - Errors now thrown if constructors or destructors have @return tags in Squiz FunctionCommentSniff
    - Errors now thrown if @throws tags dont start with a capital and end with a full stop in Squiz FunctionCommentSniff
    - Errors now thrown for invalid @var tag values in Squiz VariableCommentSniff
    - Errors now thrown for missing doc comment in Squiz VariableCommentSniff
    - Errors now thrown for unspaced operators in FOR loop declarations in Squiz OperatorSpacingSniff
    - Errors now thrown for using ob_get_clean/flush functions to end buffers in Squiz OutputBufferingIndentSniff
    - Errors now thrown for all missing member variable comments in Squiz VariableCommentSniff
   </notes>
  </release>
  <release>
   <version>
    <release>0.4.0</release>
    <api>0.4.0</api>
   </version>
   <stability>
    <release>beta</release>
    <api>beta</api>
   </stability>
   <date>2007-02-19</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Standard name specified with --standard command line argument is no longer case sensitive
    - Long error and warning messages are now wrapped to 80 characters in the full error report (thanks Endre Czirbesz)
    - Shortened a lot of error and warning messages so they don't take up so much room
    - Squiz FunctionCommentSniff now checks that param comments start with a capital letter and end with a full stop
    - Squiz FunctionSpacingSniff now reports incorrect lines below function on closing brace, not function keyword
    - Squiz FileCommentSniff now checks that there are no blank lines between the open PHP tag and the comment
    - PHP_CodeSniffer_File::isReference() now returns correctly when checking refs on right side of =>
    - Fixed incorrect error with switch closing brace in Squiz SwitchDeclarationSniff
    - Fixed missing error when multiple statements are not aligned correctly with object operators
    - Fixed incorrect errors for some PHP special variables in Squiz ValidVariableNameSniff
    - Fixed incorrect errors for arrays that only contain other arrays in Squiz ArrayDeclarationSniff
    - Fixed bug #9844 : throw new Exception(\n accidently reported as error but it ain't
   </notes>
  </release>
  <release>
   <version>
    <release>0.3.0</release>
    <api>0.3.0</api>
   </version>
   <stability>
    <release>beta</release>
    <api>beta</api>
   </stability>
   <date>2007-01-11</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Updated package.xml to version 2
    - Specifying coding standard on command line is now optional, even if you have multiple standards installed
      - PHP_CodeSniffer uses the PEAR coding standard by default if no standard is specified
    - New command line option, --extensions, to specify a comma separated list of file extensions to check
    - Converted all unit tests to PHPUnit 3 format
    - Added new coding standard, Squiz, that can be used as an alternative to PEAR
      - also contains more examples of sniffs
      - some may be moved into the Generic coding standard if required
    - Added MultipleStatementAlignmentSniff to Generic standard
    - Added ScopeIndentSniff to Generic standard
    - Added ForbiddenFunctionsSniff to Generic standard
    - Added FileCommentSniff to PEAR standard
    - Added ClassCommentSniff to PEAR standard
    - Added FunctionCommentSniff to PEAR standard
    - Change MultipleStatementSniff to MultipleStatementAlignmentSniff in PEAR standard
    - Replaced Methods directory with Functions directory in Generic and PEAR standards
      - also renamed some of the sniffs in those directories
    - Updated file, class and method comments for all files
    - Fixed bug #9274 : nested_parenthesis element not set for open and close parenthesis tokens
    - Fixed bug #9411 : too few pattern characters cause incorrect error report
   </notes>
  </release>
  <release>
   <version>
    <release>0.2.1</release>
    <api>0.2.1</api>
   </version>
   <stability>
    <release>alpha</release>
    <api>alpha</api>
   </stability>
   <date>2006-11-09</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Fixed bug #9274 : nested_parenthesis element not set for open and close parenthesis tokens
   </notes>
  </release>
  <release>
   <version>
    <release>0.2.0</release>
    <api>0.2.0</api>
   </version>
   <stability>
    <release>alpha</release>
    <api>alpha</api>
   </stability>
   <date>2006-10-13</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Added a generic standards package that will contain generic sniffs to be used in specific coding standards
      - thanks to Frederic Poeydomenge for the idea
    - Changed PEAR standard to use generic sniffs where available
    - Added LowerCaseConstantSniff to Generic standard
    - Added UpperCaseConstantSniff to Generic standard
    - Added DisallowShortOpenTagSniff to Generic standard
    - Added LineLengthSniff to Generic standard
    - Added UpperCaseConstantNameSniff to Generic standard
    - Added OpeningMethodBraceBsdAllmanSniff to Generic standard (contrib by Frederic Poeydomenge)
    - Added OpeningMethodBraceKernighanRitchieSniff to Generic standard (contrib by Frederic Poeydomenge)
    - Added framework for core PHP_CodeSniffer unit tests
    - Added unit test for PHP_CodeSniffer:isCamelCaps method
    - ScopeClosingBraceSniff now checks indentation of BREAK statements
    - Added new command line arg (-vv) to show developer debug output
    - Fixed some coding standard errors
    - Fixed bug #8834 : Massive memory consumption
    - Fixed bug #8836 : path case issues in package.xml
    - Fixed bug #8843 : confusion on nested switch()
    - Fixed bug #8841 : comments taken as whitespace
    - Fixed bug #8884 : another problem with nested switch() statements
   </notes>
  </release>
  <release>
   <version>
    <release>0.1.1</release>
    <api>0.1.1</api>
   </version>
   <stability>
    <release>alpha</release>
    <api>alpha</api>
   </stability>
   <date>2006-09-25</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Added unit tests for all PEAR sniffs
    - Exception class now extends from PEAR_Exception
    - Fixed summary report so files without errors but with warnings are not shown when warnings are hidden
   </notes>
  </release>
  <release>
   <version>
    <release>0.1.0</release>
    <api>0.1.0</api>
   </version>
   <stability>
    <release>alpha</release>
    <api>alpha</api>
   </stability>
   <date>2006-09-19</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Reorganised package contents to conform to PEAR standards
    - Changed version numbering to conform to PEAR standards
    - Removed duplicate require_once() of Exception.php from CodeSniffer.php
   </notes>
  </release>
  <release>
   <version>
    <release>0.0.5</release>
    <api>0.0.5</api>
   </version>
   <stability>
    <release>alpha</release>
    <api>alpha</api>
   </stability>
   <date>2006-09-18</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Fixed .bat file for situation where php.ini cannot be found so include_path is not set
   </notes>
  </release>
  <release>
   <version>
    <release>0.0.4</release>
    <api>0.0.4</api>
   </version>
   <stability>
    <release>alpha</release>
    <api>alpha</api>
   </stability>
   <date>2006-08-28</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Added .bat file for easier running of PHP_CodeSniffer on Windows
    - Sniff that checks method names now works for PHP4 style code where there is no scope keyword
    - Sniff that checks method names now works for PHP4 style constructors
    - Sniff that checks method names no longer incorrectly reports error with magic methods
    - Sniff that checks method names now reports errors with non-magic methods prefixed with __
    - Sniff that checks for constant names no longer incorrectly reports errors with heredoc strings
    - Sniff that checks for constant names no longer incorrectly reports errors with created objects
    - Sniff that checks indentation no longer incorrectly reports errors with heredoc strings
    - Sniff that checks indentation now correctly reports errors with improperly indented multi-line strings
    - Sniff that checks function declarations now checks for spaces before and after an equals sign for default values
    - Sniff that checks function declarations no longer incorrectly reports errors with multi-line declarations
    - Sniff that checks included code no longer incorrectly reports errors when return value is used conditionally
    - Sniff that checks opening brace of function no longer incorrectly reports errors with multi-line declarations
    - Sniff that checks spacing after commas in function calls no longer reports too many errors for some code
    - Sniff that checks control structure declarations now gives more descriptive error message
   </notes>
  </release>
  <release>
   <version>
    <release>0.0.3</release>
    <api>0.0.3</api>
   </version>
   <stability>
    <release>alpha</release>
    <api>alpha</api>
   </stability>
   <date>2006-08-22</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Added sniff to check for invalid class and interface names
    - Added sniff to check for invalid function and method names
    - Added sniff to warn if line is greater than 85 characters
    - Added sniff to check that function calls are in the correct format
    - Fixed error where comments were not allowed on the same line as a control structure declaration
    - Added command line arg to print current version (--version)
   </notes>
  </release>
  <release>
   <version>
    <release>0.0.2</release>
    <api>0.0.2</api>
   </version>
   <stability>
    <release>alpha</release>
    <api>alpha</api>
   </stability>
   <date>2006-07-25</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>
    - Removed the including of checked files to stop errors caused by parsing them
    - Removed the use of reflection so checked files do not have to be included
    - Memory usage has been greatly reduced
    - Much faster tokenising and checking times
    - Reworked the PEAR coding standard sniffs (much faster now)
    - Fix some bugs with the PEAR scope indentation standard
    - Better checking for installed coding standards
    - Can now accept multiple files and dirs on the command line
    - Added an option to list installed coding standards
    - Added an option to print a summary report (number of errors and warnings shown for each file)
    - Added an option to hide warnings from reports
    - Added an option to print verbose output (so you know what is going on)
    - Reordered command line args to put switches first (although order is not enforced)
    - Switches can now be specified together (eg. php -nv) as well as separately (phpcs -n -v)
   </notes>
  </release>
  <release>
   <version>
    <release>0.0.1</release>
    <api>0.0.1</api>
   </version>
   <stability>
    <release>alpha</release>
    <api>alpha</api>
   </stability>
   <date>2006-07-19</date>
   <license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD License</license>
   <notes>Initial preview release.</notes>
  </release>
 </changelog>
</package>
@echo off
REM PHP_CodeSniffer tokenises PHP code and detects violations of a
REM defined set of coding standards.
REM 
REM PHP version 5
REM 
REM @category  PHP
REM @package   PHP_CodeSniffer
REM @author    Greg Sherwood <gsherwood@squiz.net>
REM @author    Marc McIntyre <mmcintyre@squiz.net>
REM @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
REM @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
REM @version   CVS: $Id: phpcs.bat,v 1.3 2007-11-04 22:02:16 squiz Exp $
REM @link      http://pear.php.net/package/PHP_CodeSniffer

"@php_bin@" -d auto_append_file="" -d auto_prepend_file="" -d include_path="'@php_dir@'" -f "@bin_dir@\phpcs" -- %*
#!@php_bin@
<?php
/**
 * A commit hook for SVN.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Jack Bates <ms419@freezone.co.uk>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (is_file(dirname(__FILE__).'/../CodeSniffer/CLI.php') === true) {
    include_once dirname(__FILE__).'/../CodeSniffer/CLI.php';
} else {
    include_once 'PHP/CodeSniffer/CLI.php';
}

define('PHP_CODESNIFFER_SVNLOOK', '/usr/bin/svnlook');


/**
 * A class to process command line options.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Jack Bates <ms419@freezone.co.uk>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_SVN_Hook extends PHP_CodeSniffer_CLI
{


    /**
     * Get a list of default values for all possible command line arguments.
     *
     * @return array
     */
    public function getDefaults()
    {
        $defaults = parent::getDefaults();

        $defaults['svnArgs'] = array();
        return $defaults;

    }//end getDefaults()


    /**
     * Processes an unknown command line argument.
     *
     * All unknown args are sent to SVN commands.
     *
     * @param string $arg    The command line argument.
     * @param int    $pos    The position of the argument on the command line.
     * @param array  $values An array of values determined from CLI args.
     *
     * @return array The updated CLI values.
     * @see getCommandLineValues()
     */
    public function processUnknownArgument($arg, $pos, $values)
    {
        $values['svnArgs'][] = escapeshellarg($arg);
        return $values;

    }//end processUnknownArgument()


    /**
     * Runs PHP_CodeSniffer over files are directories.
     *
     * @param array $values An array of values determined from CLI args.
     *
     * @return int The number of error and warning messages shown.
     * @see getCommandLineValues()
     */
    public function process($values=array())
    {
        if (empty($values) === true) {
            $values = parent::getCommandLineValues();
        }

        // Get list of files in this transaction.
        $command = PHP_CODESNIFFER_SVNLOOK.' changed '.implode(' ', $values['svnArgs']);
        $handle  = popen($command, 'r');
        if ($handle === false) {
            echo 'ERROR: Could not execute "'.$command.'"'.PHP_EOL.PHP_EOL;
            exit(2);
        }

        $contents = stream_get_contents($handle);
        fclose($handle);

        // Do not check deleted paths.
        $contents = preg_replace('/^D.*/m', null, $contents);

        // Drop the four characters representing the action which precede the path on
        // each line.
        $contents = preg_replace('/^.{4}/m', null, $contents);

        $values['standard'] = $this->validateStandard($values['standard']);
        foreach ($values['standard'] as $standard) {
            if (PHP_CodeSniffer::isInstalledStandard($standard) === false) {
                // They didn't select a valid coding standard, so help them
                // out by letting them know which standards are installed.
                echo 'ERROR: the "'.$standard.'" coding standard is not installed. ';
                $this->printInstalledStandards();
                exit(2);
            }
        }

        $phpcs = new PHP_CodeSniffer(
            $values['verbosity'],
            $values['tabWidth'],
            $values['encoding']
        );

        // Set file extensions if they were specified. Otherwise,
        // let PHP_CodeSniffer decide on the defaults.
        if (empty($values['extensions']) === false) {
            $phpcs->setAllowedFileExtensions($values['extensions']);
        }

        // Set ignore patterns if they were specified.
        if (empty($values['ignored']) === false) {
            $phpcs->setIgnorePatterns($values['ignored']);
        }

        // Set some convenience member vars.
        if ($values['errorSeverity'] === null) {
            $this->errorSeverity = PHPCS_DEFAULT_ERROR_SEV;
        } else {
            $this->errorSeverity = $values['errorSeverity'];
        }

        if ($values['warningSeverity'] === null) {
            $this->warningSeverity = PHPCS_DEFAULT_WARN_SEV;
        } else {
            $this->warningSeverity = $values['warningSeverity'];
        }

        // Initialize PHP_CodeSniffer listeners but don't process any files.
        $phpcs->setCli($this);
        $phpcs->process(array(), $values['standard'], $values['sniffs']);

        // Need double quotes around the following regex beause the vertical whitespace
        // char is not always treated correctly for whatever reason.
        foreach (preg_split("/\v|\n/", $contents, -1, PREG_SPLIT_NO_EMPTY) as $path) {
            // No need to process folders as each changed file is checked.
            if (substr($path, -1) === '/') {
                continue;
            }

            // We need to check ignore rules ourself because they are
            // not checked when processing a single file.
            if ($phpcs->shouldProcessFile($path, dirname($path)) === false) {
                continue;
            }

            // Get the contents of each file, as it would be after this transaction.
            $command = PHP_CODESNIFFER_SVNLOOK.' cat '.implode(' ', $values['svnArgs']).' '.escapeshellarg($path);
            $handle  = popen($command, 'r');
            if ($handle === false) {
                echo 'ERROR: Could not execute "'.$command.'"'.PHP_EOL.PHP_EOL;
                exit(2);
            }

            $contents = stream_get_contents($handle);
            fclose($handle);

            $phpcs->processFile($path, $contents);
        }//end foreach

        return $this->printErrorReport(
            $phpcs,
            $values['reports'],
            $values['showSources'],
            $values['reportFile'],
            $values['reportWidth']
        );

    }//end process()


    /**
     * Prints out the usage information for this script.
     *
     * @return void
     */
    public function printUsage()
    {
        parent::printUsage();

        echo PHP_EOL;
        echo '    Each additional argument is passed to the `svnlook changed ...`'.PHP_EOL;
        echo '    and `svnlook cat ...` commands.  The report is printed on standard output,'.PHP_EOL;
        echo '    however Subversion displays only standard error to the user, so in a'.PHP_EOL;
        echo '    pre-commit hook, this script should be invoked as follows:'.PHP_EOL;
        echo PHP_EOL;
        echo '    '.basename($_SERVER['argv'][0]).' ... "$REPOS" -t "$TXN" >&2 || exit 1'.PHP_EOL;

    }//end printUsage()


}//end class

$phpcs = new PHP_CodeSniffer_SVN_Hook();
$phpcs->checkRequirements();

$numErrors = $phpcs->process();
if ($numErrors !== 0) {
    exit(1);
}

?>

<?php
/**
 * PHP_CodeSniffer tokenises PHP code and detects violations of a
 * defined set of coding standards.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

error_reporting(E_ALL | E_STRICT);

// Optionally use PHP_Timer to print time/memory stats for the run.
// Note that the reports are the ones who actually print the data
// as they decide if it is ok to print this data to screen.
@include_once 'PHP/Timer.php';
if (class_exists('PHP_Timer', false) === true) {
    PHP_Timer::start();
}

if (is_file(dirname(__FILE__).'/../CodeSniffer/CLI.php') === true) {
    include_once dirname(__FILE__).'/../CodeSniffer/CLI.php';
} else {
    include_once 'PHP/CodeSniffer/CLI.php';
}

$phpcs = new PHP_CodeSniffer_CLI();
$phpcs->checkRequirements();

$numErrors = $phpcs->process();
if ($numErrors === 0) {
    exit(0);
} else {
    exit(1);
}

?>
About
-----

PHP\_CodeSniffer is a PHP5 script that tokenises PHP, JavaScript and CSS files to detect violations of a defined coding standard. It is an essential development tool that ensures your code remains clean and consistent. It can also help prevent some common semantic errors made by developers.

[![Build Status](https://secure.travis-ci.org/squizlabs/PHP_CodeSniffer.png?branch=master)](https://travis-ci.org/squizlabs/PHP_CodeSniffer)

Requirements
------------

PHP\_CodeSniffer requires PHP version 5.1.2 or greater, although individual sniffs may have additional requirements such as external applications and scripts. See the [Configuration Options manual page](http://pear.php.net/manual/en/package.php.php-codesniffer.config-options.php) for a list of these requirements.

The SVN pre-commit hook requires PHP version 5.2.4 or greater due to its use of the vertical whitespace character.

Installation
------------

The easiest way to install PHP\_CodeSniffer is to use the PEAR installer. This will make the `phpcs` command immediately available for use. To install PHP\_CodeSniffer using the PEAR installer, first ensure you have [installed PEAR](http://pear.php.net/manual/en/installation.getting.php) and then run the following command:

    pear install PHP_CodeSniffer

If you prefer using [Composer](http://getcomposer.org/) you can easily install PHP_CodeSniffer system-wide with the following command:

    composer global require 'squizlabs/php_codesniffer=*'

Make sure you have `~/.composer/vendor/bin/` in your PATH.

Or alternatively, include a dependency for `squizlabs/php_codesniffer` in your `composer.json` file. For example:

    {
        "require": {
            "squizlabs/php_codesniffer": "1.*"
        }
    }

You will then be able to run PHP_CodeSniffer from the vendor bin directory:

    ./vendor/bin/phpcs -h

You can also download the PHP\_CodeSniffer source and run the `phpcs` command directly from the GIT checkout:

    git clone git://github.com/squizlabs/PHP_CodeSniffer.git
    cd PHP_CodeSniffer
    php scripts/phpcs -h

Documentation
-------------

The documentation for PHP\_CodeSniffer is available on the [Github wiki](https://github.com/squizlabs/PHP_CodeSniffer/wiki).

Information about upcoming features and releases is available on the [Squiz Labs blog](http://www.squizlabs.com/php-codesniffer).

Contributing
-------------

If you do contribute code to PHP\_CodeSniffer, please make sure it conforms to the PEAR coding standard and that the PHP\_CodeSniffer unit tests still pass. The easiest way to contribute is to work on a checkout of the repository, or your own fork, rather than an installed PEAR version. If you do this, you can run the following commands to check if everything is ready to submit:

    cd PHP_CodeSniffer
    php scripts/phpcs --ignore=*/tests/* . -n

Which should give you no output, indicating that there are no PEAR coding standard errors. And then:

    phpunit tests/AllTests.php

Which should give you no failures or errors. You can ignore any skipped tests as these are for external tools.

Issues
------

Bug reports and feature requests can be submitted on the [PEAR bug tracker](http://pear.php.net/package/PHP_CodeSniffer/bugs).
<?php
/**
 * Tests for the PHP_CodeSniffer_File:getMethodParameters method.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Anti Veeranna <duke@masendav.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Tests for the PHP_CodeSniffer_File:getMethodParameters method.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Anti Veeranna <duke@masendav.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Core_File_GetMethodParametersTest extends PHPUnit_Framework_TestCase
{

    /**
     * The PHP_CodeSniffer_File object containing parsed contents of this file.
     *
     * @var PHP_CodeSniffer_File
     */
    private $_phpcsFile;


    /**
     * Initialize & tokenize PHP_CodeSniffer_File with code from this file.
     *
     * Methods used for these tests can be found at the bottom of
     * this file.
     *
     * @return void
     */
    public function setUp()
    {
        $phpcs            = new PHP_CodeSniffer();
        $this->_phpcsFile = new PHP_CodeSniffer_File(
            __FILE__,
            array(),
            array(),
            array(),
            array(),
            $phpcs
        );

        $contents = file_get_contents(__FILE__);
        $this->_phpcsFile->start($contents);

    }//end setUp()


    /**
     * Clean up after finished test.
     *
     * @return void
     */
    public function tearDown()
    {
        unset($this->_phpcsFile);

    }//end tearDown()


    /**
     * Verify pass-by-reference parsing.
     *
     * @return void
     */
    public function testPassByReference()
    {
        $expected    = array();
        $expected[0] = array(
                        'name'              => '$var',
                        'pass_by_reference' => true,
                        'type_hint'         => '',
                       );

        $start    = ($this->_phpcsFile->numTokens - 1);
        $function = $this->_phpcsFile->findPrevious(
            T_COMMENT,
            $start,
            null,
            false,
            '/* testPassByReference */'
        );

        $found = $this->_phpcsFile->getMethodParameters(($function + 2));
        $this->assertSame($expected, $found);

    }//end testPassByReference()


    /**
     * Verify array hint parsing.
     *
     * @return void
     */
    public function testArrayHint()
    {
        $expected    = array();
        $expected[0] = array(
                        'name'              => '$var',
                        'pass_by_reference' => false,
                        'type_hint'         => 'array',
                       );

        $start    = ($this->_phpcsFile->numTokens - 1);
        $function = $this->_phpcsFile->findPrevious(
            T_COMMENT,
            $start,
            null,
            false,
            '/* testArrayHint */'
        );

        $found = $this->_phpcsFile->getMethodParameters(($function + 2));
        $this->assertSame($expected, $found);

    }//end testArrayHint()


    /**
     * Verify type hint parsing.
     *
     * @return void
     */
    public function testTypeHint()
    {
        $expected    = array();
        $expected[0] = array(
                        'name'              => '$var1',
                        'pass_by_reference' => false,
                        'type_hint'         => 'foo',
                       );

        $expected[1] = array(
                        'name'              => '$var2',
                        'pass_by_reference' => false,
                        'type_hint'         => 'bar',
                       );

        $start    = ($this->_phpcsFile->numTokens - 1);
        $function = $this->_phpcsFile->findPrevious(
            T_COMMENT,
            $start,
            null,
            false,
            '/* testTypeHint */'
        );

        $found = $this->_phpcsFile->getMethodParameters(($function + 2));
        $this->assertSame($expected, $found);

    }//end testTypeHint()


    /**
     * Verify variable.
     *
     * @return void
     */
    public function testVariable()
    {
        $expected    = array();
        $expected[0] = array(
                        'name'              => '$var',
                        'pass_by_reference' => false,
                        'type_hint'         => '',
                       );

        $start    = ($this->_phpcsFile->numTokens - 1);
        $function = $this->_phpcsFile->findPrevious(
            T_COMMENT,
            $start,
            null,
            false,
            '/* testVariable */'
        );

        $found = $this->_phpcsFile->getMethodParameters(($function + 2));
        $this->assertSame($expected, $found);

    }//end testVariable()


    /**
     * Verify default value parsing with a single function param.
     *
     * @return void
     */
    public function testSingleDefaultValue()
    {
        $expected    = array();
        $expected[0] = array(
                        'name'              => '$var1',
                        'default'           => 'self::CONSTANT',
                        'pass_by_reference' => false,
                        'type_hint'         => '',
                       );

        $start    = ($this->_phpcsFile->numTokens - 1);
        $function = $this->_phpcsFile->findPrevious(
            T_COMMENT,
            $start,
            null,
            false,
            '/* testSingleDefaultValue */'
        );

        $found = $this->_phpcsFile->getMethodParameters(($function + 2));
        $this->assertSame($expected, $found);

    }//end testSingleDefaultValue()


    /**
     * Verify default value parsing.
     *
     * @return void
     */
    public function testDefaultValues()
    {
        $expected    = array();
        $expected[0] = array(
                        'name'              => '$var1',
                        'default'           => '1',
                        'pass_by_reference' => false,
                        'type_hint'         => '',
                       );
        $expected[1] = array(
                        'name'              => '$var2',
                        'default'           => "'value'",
                        'pass_by_reference' => false,
                        'type_hint'         => '',
                       );

        $start    = ($this->_phpcsFile->numTokens - 1);
        $function = $this->_phpcsFile->findPrevious(
            T_COMMENT,
            $start,
            null,
            false,
            '/* testDefaultValues */'
        );

        $found = $this->_phpcsFile->getMethodParameters(($function + 2));
        $this->assertSame($expected, $found);

    }//end testDefaultValues()


}//end class

// @codingStandardsIgnoreStart
/* testPassByReference */ function passByReference(&$var) {}
/* testArrayHint */ function arrayHint(array $var) {}
/* testVariable */ function variable($var) {}
/* testSingleDefaultValue */ function defaultValue($var1=self::CONSTANT) {}
/* testDefaultValues */ function defaultValues($var1=1, $var2='value') {}
/* testTypeHint */ function typeHint(foo $var1, bar $var2) {}
// @codingStandardsIgnoreEnd

?>

<?php
/**
 * Tests for the PHP_CodeSniffer:isCamelCaps method.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Tests for the PHP_CodeSniffer:isCamelCaps method.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Core_IsCamelCapsTest extends PHPUnit_Framework_TestCase
{


    /**
     * Test valid public function/method names.
     *
     * @return void
     */
    public function testValidNotClassFormatPublic()
    {
        $this->assertTrue(PHP_CodeSniffer::isCamelCaps('thisIsCamelCaps', false, true, true));
        $this->assertTrue(PHP_CodeSniffer::isCamelCaps('thisISCamelCaps', false, true, false));

    }//end testValidNotClassFormatPublic()


    /**
     * Test invalid public function/method names.
     *
     * @return void
     */
    public function testInvalidNotClassFormatPublic()
    {
        $this->assertFalse(PHP_CodeSniffer::isCamelCaps('_thisIsCamelCaps', false, true, true));
        $this->assertFalse(PHP_CodeSniffer::isCamelCaps('thisISCamelCaps', false, true, true));
        $this->assertFalse(PHP_CodeSniffer::isCamelCaps('ThisIsCamelCaps', false, true, true));

        $this->assertFalse(PHP_CodeSniffer::isCamelCaps('3thisIsCamelCaps', false, true, true));
        $this->assertFalse(PHP_CodeSniffer::isCamelCaps('*thisIsCamelCaps', false, true, true));
        $this->assertFalse(PHP_CodeSniffer::isCamelCaps('-thisIsCamelCaps', false, true, true));

        $this->assertFalse(PHP_CodeSniffer::isCamelCaps('this*IsCamelCaps', false, true, true));
        $this->assertFalse(PHP_CodeSniffer::isCamelCaps('this-IsCamelCaps', false, true, true));
        $this->assertFalse(PHP_CodeSniffer::isCamelCaps('this_IsCamelCaps', false, true, true));
        $this->assertFalse(PHP_CodeSniffer::isCamelCaps('this_is_camel_caps', false, true, true));

    }//end testInvalidNotClassFormatPublic()


    /**
     * Test valid private method names.
     *
     * @return void
     */
    public function testValidNotClassFormatPrivate()
    {
        $this->assertTrue(PHP_CodeSniffer::isCamelCaps('_thisIsCamelCaps', false, false, true));
        $this->assertTrue(PHP_CodeSniffer::isCamelCaps('_thisISCamelCaps', false, false, false));
        $this->assertTrue(PHP_CodeSniffer::isCamelCaps('_i18N', false, false, true));
        $this->assertTrue(PHP_CodeSniffer::isCamelCaps('_i18n', false, false, true));

    }//end testValidNotClassFormatPrivate()


    /**
     * Test invalid private method names.
     *
     * @return void
     */
    public function testInvalidNotClassFormatPrivate()
    {
        $this->assertFalse(PHP_CodeSniffer::isCamelCaps('thisIsCamelCaps', false, false, true));
        $this->assertFalse(PHP_CodeSniffer::isCamelCaps('_thisISCamelCaps', false, false, true));
        $this->assertFalse(PHP_CodeSniffer::isCamelCaps('_ThisIsCamelCaps', false, false, true));
        $this->assertFalse(PHP_CodeSniffer::isCamelCaps('__thisIsCamelCaps', false, false, true));
        $this->assertFalse(PHP_CodeSniffer::isCamelCaps('__thisISCamelCaps', false, false, false));

        $this->assertFalse(PHP_CodeSniffer::isCamelCaps('3thisIsCamelCaps', false, false, true));
        $this->assertFalse(PHP_CodeSniffer::isCamelCaps('*thisIsCamelCaps', false, false, true));
        $this->assertFalse(PHP_CodeSniffer::isCamelCaps('-thisIsCamelCaps', false, false, true));
        $this->assertFalse(PHP_CodeSniffer::isCamelCaps('_this_is_camel_caps', false, false, true));

    }//end testInvalidNotClassFormatPrivate()


    /**
     * Test valid class names.
     *
     * @return void
     */
    public function testValidClassFormatPublic()
    {
        $this->assertTrue(PHP_CodeSniffer::isCamelCaps('ThisIsCamelCaps', true, true, true));
        $this->assertTrue(PHP_CodeSniffer::isCamelCaps('ThisISCamelCaps', true, true, false));
        $this->assertTrue(PHP_CodeSniffer::isCamelCaps('This3IsCamelCaps', true, true, false));

    }//end testValidClassFormatPublic()


    /**
     * Test invalid class names.
     *
     * @return void
     */
    public function testInvalidClassFormat()
    {
        $this->assertFalse(PHP_CodeSniffer::isCamelCaps('thisIsCamelCaps', true));
        $this->assertFalse(PHP_CodeSniffer::isCamelCaps('This-IsCamelCaps', true));
        $this->assertFalse(PHP_CodeSniffer::isCamelCaps('This_Is_Camel_Caps', true));

    }//end testInvalidClassFormat()


    /**
     * Test invalid class names with the private flag set.
     *
     * Note that the private flag is ignored if the class format
     * flag is set, so these names are all invalid.
     *
     * @return void
     */
    public function testInvalidClassFormatPrivate()
    {
        $this->assertFalse(PHP_CodeSniffer::isCamelCaps('_ThisIsCamelCaps', true, true));
        $this->assertFalse(PHP_CodeSniffer::isCamelCaps('_ThisIsCamelCaps', true, false));

    }//end testInvalidClassFormatPrivate()


}//end class

?>
<?php
/**
 * Tests for PHP_CodeSniffer error suppression tags.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Tests for PHP_CodeSniffer error suppression tags.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Core_ErrorSuppressionTest extends PHPUnit_Framework_TestCase
{


    /**
     * Test suppressing a single error.
     *
     * @return void
     */
    public function testSuppressError()
    {
        $phpcs = new PHP_CodeSniffer();
        $phpcs->process(array(), 'PEAR', array('Generic.PHP.LowerCaseConstant'));

        // Process without suppression.
        $content = '<?php '.PHP_EOL.'$var = FALSE;';
        $file    = $phpcs->processFile('noSuppressionTest.php', $content);

        $errors    = $file->getErrors();
        $numErrors = $file->getErrorCount();
        $this->assertEquals(1, $numErrors);
        $this->assertEquals(1, count($errors));

        // Process with suppression.
        $content = '<?php '.PHP_EOL.'// @codingStandardsIgnoreStart'.PHP_EOL.'$var = FALSE;'.PHP_EOL.'// @codingStandardsIgnoreEnd';
        $file    = $phpcs->processFile('suppressionTest.php', $content);

        $errors    = $file->getErrors();
        $numErrors = $file->getErrorCount();
        $this->assertEquals(0, $numErrors);
        $this->assertEquals(0, count($errors));

    }//end testSuppressError()


    /**
     * Test suppressing 1 out of 2 errors.
     *
     * @return void
     */
    public function testSuppressSomeErrors()
    {
        $phpcs = new PHP_CodeSniffer();
        $phpcs->process(array(), 'Generic', array('Generic.PHP.LowerCaseConstant'));

        // Process without suppression.
        $content = '<?php '.PHP_EOL.'$var = FALSE;'.PHP_EOL.'$var = TRUE;';
        $file    = $phpcs->processFile('noSuppressionTest.php', $content);

        $errors    = $file->getErrors();
        $numErrors = $file->getErrorCount();
        $this->assertEquals(2, $numErrors);
        $this->assertEquals(2, count($errors));

        // Process with suppression.
        $content = '<?php '.PHP_EOL.'// @codingStandardsIgnoreStart'.PHP_EOL.'$var = FALSE;'.PHP_EOL.'// @codingStandardsIgnoreEnd'.PHP_EOL.'$var = TRUE;';
        $file    = $phpcs->processFile('suppressionTest.php', $content);

        $errors    = $file->getErrors();
        $numErrors = $file->getErrorCount();
        $this->assertEquals(1, $numErrors);
        $this->assertEquals(1, count($errors));

    }//end testSuppressSomeErrors()


    /**
     * Test suppressing a single warning.
     *
     * @return void
     */
    public function testSuppressWarning()
    {
        $phpcs = new PHP_CodeSniffer();
        $phpcs->process(array(), 'Generic', array('Generic.Commenting.Todo'));

        // Process without suppression.
        $content = '<?php '.PHP_EOL.'//TODO: write some code';
        $file    = $phpcs->processFile('noSuppressionTest.php', $content);

        $warnings    = $file->getWarnings();
        $numWarnings = $file->getWarningCount();
        $this->assertEquals(1, $numWarnings);
        $this->assertEquals(1, count($warnings));

        // Process with suppression.
        $content = '<?php '.PHP_EOL.'// @codingStandardsIgnoreStart'.PHP_EOL.'//TODO: write some code'.PHP_EOL.'// @codingStandardsIgnoreEnd';
        $file    = $phpcs->processFile('suppressionTest.php', $content);

        $warnings    = $file->getWarnings();
        $numWarnings = $file->getWarningCount();
        $this->assertEquals(0, $numWarnings);
        $this->assertEquals(0, count($warnings));

    }//end testSuppressWarning()


    /**
     * Test suppressing a whole file.
     *
     * @return void
     */
    public function testSuppressFile()
    {
        $phpcs = new PHP_CodeSniffer();
        $phpcs->process(array(), 'Generic', array('Generic.Commenting.Todo'));

        // Process without suppression.
        $content = '<?php '.PHP_EOL.'//TODO: write some code';
        $file    = $phpcs->processFile('suppressionTest.php', $content);

        $warnings    = $file->getWarnings();
        $numWarnings = $file->getWarningCount();
        $this->assertEquals(1, $numWarnings);
        $this->assertEquals(1, count($warnings));

        // Process with suppression.
        $content = '<?php '.PHP_EOL.'// @codingStandardsIgnoreFile'.PHP_EOL.'//TODO: write some code';
        $file    = $phpcs->processFile('suppressionTest.php', $content);

        $warnings    = $file->getWarnings();
        $numWarnings = $file->getWarningCount();
        $this->assertEquals(0, $numWarnings);
        $this->assertEquals(0, count($warnings));

        // Process with a Doc Block suppression.
        $content = '<?php '.PHP_EOL.'/* @codingStandardsIgnoreFile */'.PHP_EOL.'//TODO: write some code';
        $file    = $phpcs->processFile('suppressionTest.php', $content);

        $warnings    = $file->getWarnings();
        $numWarnings = $file->getWarningCount();
        $this->assertEquals(0, $numWarnings);
        $this->assertEquals(0, count($warnings));

    }//end testSuppressFile()


}//end class

?>
<?php
/**
 * A test class for testing the core.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

require_once 'IsCamelCapsTest.php';
require_once 'ErrorSuppressionTest.php';
require_once 'File/GetMethodParametersTest.php';

if (is_file(dirname(__FILE__).'/../../CodeSniffer.php') === true) {
    // We are not installed.
    include_once dirname(__FILE__).'/../../CodeSniffer.php';
} else {
    include_once 'PHP/CodeSniffer.php';
}

/**
 * A test class for testing the core.
 *
 * Do not run this file directly. Run the AllSniffs.php file in the root
 * testing directory of PHP_CodeSniffer.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_Core_AllTests
{


    /**
     * Prepare the test runner.
     *
     * @return void
     */
    public static function main()
    {
        PHPUnit2_TextUI_TestRunner::run(self::suite());

    }//end main()


    /**
     * Add all core unit tests into a test suite.
     *
     * @return PHPUnit_Framework_TestSuite
     */
    public static function suite()
    {
        $suite = new PHPUnit_Framework_TestSuite('PHP CodeSniffer Core');
        $suite->addTestSuite('Core_IsCamelCapsTest');
        $suite->addTestSuite('Core_ErrorSuppressionTest');
        $suite->addTestSuite('Core_File_GetMethodParametersTest');
        return $suite;

    }//end suite()


}//end class

?>
<?php
/**
 * A PHP_CodeSniffer specific test suite for PHPUnit.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHPUnit_Framework_TestSuite', false) === false) {
    require_once 'PHPUnit/Framework/TestSuite.php';
}

/**
 * A PHP_CodeSniffer specific test suite for PHPUnit.
 *
 * Unregisters the PHP_CodeSniffer autoload function after the run.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_TestSuite extends PHPUnit_Framework_TestSuite
{


    /**
     * Runs the tests and collects their result in a TestResult.
     *
     * @param PHPUnit_Framework_TestResult $result A test result.
     * @param mixed                        $filter The filter passed to each test.
     *
     * @return PHPUnit_Framework_TestResult
     */
    public function run(PHPUnit_Framework_TestResult $result=null, $filter=false)
    {
        spl_autoload_register(array('PHP_CodeSniffer', 'autoload'));
        $result = parent::run($result, $filter);
        spl_autoload_unregister(array('PHP_CodeSniffer', 'autoload'));
        return $result;

    }//end run()


}//end class

?>
<?php
/**
 * A test class for running all PHP_CodeSniffer unit tests.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (defined('PHP_CODESNIFFER_IN_TESTS') === false) {
    define('PHP_CODESNIFFER_IN_TESTS', true);
}

require_once 'TestSuite.php';
if (class_exists('PHPUnit_TextUI_TestRunner', false) === false) {
    require_once 'PHPUnit/TextUI/TestRunner.php';
}

if (is_file(dirname(__FILE__).'/../CodeSniffer.php') === true) {
    // We are not installed.
    include_once 'Core/AllTests.php';
    include_once 'Standards/AllSniffs.php';
    include_once dirname(__FILE__).'/../CodeSniffer.php';
} else {
    include_once 'CodeSniffer/Core/AllTests.php';
    include_once 'CodeSniffer/Standards/AllSniffs.php';
    include_once 'PHP/CodeSniffer.php';
}

/**
 * A test class for running all PHP_CodeSniffer unit tests.
 *
 * Usage: phpunit AllTests.php
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_AllTests
{


    /**
     * Prepare the test runner.
     *
     * @return void
     */
    public static function main()
    {
        PHPUnit_TextUI_TestRunner::run(self::suite());

    }//end main()


    /**
     * Add all PHP_CodeSniffer test suites into a single test suite.
     *
     * @return PHPUnit_Framework_TestSuite
     */
    public static function suite()
    {
        // Use a special PHP_CodeSniffer test suite so that we can
        // unset our autoload function after the run.
        $suite = new PHP_CodeSniffer_TestSuite('PHP CodeSniffer');

        $suite->addTest(PHP_CodeSniffer_Core_AllTests::suite());
        $suite->addTest(PHP_CodeSniffer_Standards_AllSniffs::suite());

        // Unregister this here because the PEAR tester loads
        // all package suites before running then, so our autoloader
        // will cause problems for the packages included after us.
        spl_autoload_unregister(array('PHP_CodeSniffer', 'autoload'));

        return $suite;

    }//end suite()


}//end class

?>
<?php
/**
 * A test class for testing all sniffs for installed standards.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

// Require this here so that the unit tests don't have to try and find the
// abstract class once it is installed into the PEAR tests directory.
require_once dirname(__FILE__).'/AbstractSniffUnitTest.php';

/**
 * A test class for testing all sniffs for installed standards.
 *
 * Usage: phpunit AllSniffs.php
 *
 * This test class loads all unit tests for all installed standards into a
 * single test suite and runs them. Errors are reported on the command line.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_Standards_AllSniffs
{


    /**
     * Prepare the test runner.
     *
     * @return void
     */
    public static function main()
    {
        PHPUnit_TextUI_TestRunner::run(self::suite());

    }//end main()


    /**
     * Add all sniff unit tests into a test suite.
     *
     * Sniff unit tests are found by recursing through the 'Tests' directory
     * of each installed coding standard.
     *
     * @return PHPUnit_Framework_TestSuite
     */
    public static function suite()
    {
        $suite = new PHPUnit_Framework_TestSuite('PHP CodeSniffer Standards');

        $isInstalled = !is_file(dirname(__FILE__).'/../../CodeSniffer.php');

        if ($isInstalled === false) {
            // We have not been installed.
            $standardsDir = realpath(dirname(__FILE__).'/../../CodeSniffer/Standards');
        } else {
            $standardsDir = '';
        }

        $standards = PHP_CodeSniffer::getInstalledStandards(true, $standardsDir);

        foreach ($standards as $standard) {
            if ($isInstalled === false) {
                $standardDir = $standardsDir.DIRECTORY_SEPARATOR.$standard.DIRECTORY_SEPARATOR.'Tests'.DIRECTORY_SEPARATOR;
            } else {
                $standardDir = dirname(__FILE__).DIRECTORY_SEPARATOR.$standard.DIRECTORY_SEPARATOR.'Tests'.DIRECTORY_SEPARATOR;
            }

            if (is_dir($standardDir) === false) {
                // No tests for this standard.
                continue;
            }

            // Locate the actual directory that contains the standard's tests.
            // This is individual to each standard as they could be symlinked in.
            $baseDir = dirname(dirname($standardDir));

            $di = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($standardDir));

            foreach ($di as $file) {
                // Skip hidden files.
                if (substr($file->getFilename(), 0, 1) === '.') {
                    continue;
                }

                // Tests must have the extension 'php'.
                $parts = explode('.', $file);
                $ext   = array_pop($parts);
                if ($ext !== 'php') {
                    continue;
                }

                $filePath  = $file->getPathname();
                $className = str_replace($baseDir.DIRECTORY_SEPARATOR, '', $filePath);
                $className = substr($className, 0, -4);
                $className = str_replace(DIRECTORY_SEPARATOR, '_', $className);

                include_once $filePath;
                $class = new $className('getErrorList');
                $suite->addTest($class);
            }//end foreach
        }//end foreach

        return $suite;

    }//end suite()


}//end class

?>
<?php
/**
 * An abstract class that all sniff unit tests must extend.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * An abstract class that all sniff unit tests must extend.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings that are not found, or
 * warnings and errors that are not expected, are considered test failures.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
abstract class AbstractSniffUnitTest extends PHPUnit_Framework_TestCase
{

    /**
     * The PHP_CodeSniffer object used for testing.
     *
     * @var PHP_CodeSniffer
     */
    protected static $phpcs = null;


    /**
     * Sets up this unit test.
     *
     * @return void
     */
    protected function setUp()
    {
        if (self::$phpcs === null) {
            self::$phpcs = new PHP_CodeSniffer();
        }

    }//end setUp()


    /**
     * Should this test be skipped for some reason.
     *
     * @return void
     */
    protected function shouldSkipTest()
    {
        return false;

    }//end shouldSkipTest()


    /**
     * Tests the extending classes Sniff class.
     *
     * @return void
     * @throws PHPUnit_Framework_Error
     */
    protected final function runTest()
    {
        // Skip this test if we can't run in this environment.
        if ($this->shouldSkipTest() === true) {
            $this->markTestSkipped();
        }

        // The basis for determining file locations.
        $basename = substr(get_class($this), 0, -8);

        // The name of the coding standard we are testing.
        $standardName = substr($basename, 0, strpos($basename, '_'));

        // The code of the sniff we are testing.
        $parts     = explode('_', $basename);
        $sniffCode = $parts[0].'.'.$parts[2].'.'.$parts[3];

        if (is_file(dirname(__FILE__).'/../../CodeSniffer.php') === true) {
            // We have not been installed.
            $standardsDir = realpath(dirname(__FILE__).'/../../CodeSniffer/Standards');
            $testFileBase = $standardsDir.DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $basename).'UnitTest.';
        } else {
            // The name of the dummy file we are testing.
            $testFileBase = dirname(__FILE__).DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $basename).'UnitTest.';
        }

        // Get a list of all test files to check. These will have the same base
        // name but different extensions. We ignore the .php file as it is the class.
        $testFiles = array();

        $dir = substr($testFileBase, 0, strrpos($testFileBase, DIRECTORY_SEPARATOR));
        $di  = new DirectoryIterator($dir);

        foreach ($di as $file) {
            $path = $file->getPathname();
            if (substr($path, 0, strlen($testFileBase)) === $testFileBase) {
                if ($path !== $testFileBase.'php') {
                    $testFiles[] = $path;
                }
            }
        }

        // Get them in order.
        sort($testFiles);

        self::$phpcs->process(array(), $standardName, array($sniffCode));
        self::$phpcs->setIgnorePatterns(array());

        $failureMessages = array();
        foreach ($testFiles as $testFile) {
            try {
                $phpcsFile = self::$phpcs->processFile($testFile);
            } catch (Exception $e) {
                $this->fail('An unexpected exception has been caught: '.$e->getMessage());
            }

            $failures        = $this->generateFailureMessages($phpcsFile);
            $failureMessages = array_merge($failureMessages, $failures);
        }//end foreach

        if (empty($failureMessages) === false) {
            $this->fail(implode(PHP_EOL, $failureMessages));
        }

    }//end testSniff()


    /**
     * Generate a list of test failures for a given sniffed file.
     *
     * @param PHP_CodeSniffer_File $file The file being tested.
     *
     * @return array
     * @throws PHP_CodeSniffer_Exception
     */
    public function generateFailureMessages(PHP_CodeSniffer_File $file)
    {
        $testFile = $file->getFilename();

        $foundErrors      = $file->getErrors();
        $foundWarnings    = $file->getWarnings();
        $expectedErrors   = $this->getErrorList(basename($testFile));
        $expectedWarnings = $this->getWarningList(basename($testFile));

        if (is_array($expectedErrors) === false) {
            throw new PHP_CodeSniffer_Exception('getErrorList() must return an array');
        }

        if (is_array($expectedWarnings) === false) {
            throw new PHP_CodeSniffer_Exception('getWarningList() must return an array');
        }

        /*
         We merge errors and warnings together to make it easier
         to iterate over them and produce the errors string. In this way,
         we can report on errors and warnings in the same line even though
         it's not really structured to allow that.
        */

        $allProblems     = array();
        $failureMessages = array();

        foreach ($foundErrors as $line => $lineErrors) {
            foreach ($lineErrors as $column => $errors) {
                if (isset($allProblems[$line]) === false) {
                    $allProblems[$line] = array(
                                           'expected_errors'   => 0,
                                           'expected_warnings' => 0,
                                           'found_errors'      => array(),
                                           'found_warnings'    => array(),
                                          );
                }

                $foundErrorsTemp = array();
                foreach ($allProblems[$line]['found_errors'] as $foundError) {
                    $foundErrorsTemp[] = $foundError;
                }

                $errorsTemp = array();
                foreach ($errors as $foundError) {
                    $errorsTemp[] = $foundError['message'];
                }

                $allProblems[$line]['found_errors'] = array_merge($foundErrorsTemp, $errorsTemp);
            }

            if (isset($expectedErrors[$line]) === true) {
                $allProblems[$line]['expected_errors'] = $expectedErrors[$line];
            } else {
                $allProblems[$line]['expected_errors'] = 0;
            }

            unset($expectedErrors[$line]);
        }//end foreach

        foreach ($expectedErrors as $line => $numErrors) {
            if (isset($allProblems[$line]) === false) {
                $allProblems[$line] = array(
                                       'expected_errors'   => 0,
                                       'expected_warnings' => 0,
                                       'found_errors'      => array(),
                                       'found_warnings'    => array(),
                                      );
            }

            $allProblems[$line]['expected_errors'] = $numErrors;
        }

        foreach ($foundWarnings as $line => $lineWarnings) {
            foreach ($lineWarnings as $column => $warnings) {
                if (isset($allProblems[$line]) === false) {
                    $allProblems[$line] = array(
                                           'expected_errors'   => 0,
                                           'expected_warnings' => 0,
                                           'found_errors'      => array(),
                                           'found_warnings'    => array(),
                                          );
                }

                $foundWarningsTemp = array();
                foreach ($allProblems[$line]['found_warnings'] as $foundWarning) {
                    $foundWarningsTemp[] = $foundWarning;
                }

                $warningsTemp = array();
                foreach ($warnings as $warning) {
                    $warningsTemp[] = $warning['message'];
                }

                $allProblems[$line]['found_warnings'] = array_merge($foundWarningsTemp, $warningsTemp);
            }

            if (isset($expectedWarnings[$line]) === true) {
                $allProblems[$line]['expected_warnings'] = $expectedWarnings[$line];
            } else {
                $allProblems[$line]['expected_warnings'] = 0;
            }

            unset($expectedWarnings[$line]);
        }//end foreach

        foreach ($expectedWarnings as $line => $numWarnings) {
            if (isset($allProblems[$line]) === false) {
                $allProblems[$line] = array(
                                       'expected_errors'   => 0,
                                       'expected_warnings' => 0,
                                       'found_errors'      => array(),
                                       'found_warnings'    => array(),
                                      );
            }

            $allProblems[$line]['expected_warnings'] = $numWarnings;
        }

        // Order the messages by line number.
        ksort($allProblems);

        foreach ($allProblems as $line => $problems) {
            $numErrors        = count($problems['found_errors']);
            $numWarnings      = count($problems['found_warnings']);
            $expectedErrors   = $problems['expected_errors'];
            $expectedWarnings = $problems['expected_warnings'];

            $errors      = '';
            $foundString = '';

            if ($expectedErrors !== $numErrors || $expectedWarnings !== $numWarnings) {
                $lineMessage     = "[LINE $line]";
                $expectedMessage = 'Expected ';
                $foundMessage    = 'in '.basename($testFile).' but found ';

                if ($expectedErrors !== $numErrors) {
                    $expectedMessage .= "$expectedErrors error(s)";
                    $foundMessage    .= "$numErrors error(s)";
                    if ($numErrors !== 0) {
                        $foundString .= 'error(s)';
                        $errors      .= implode(PHP_EOL.' -> ', $problems['found_errors']);
                    }

                    if ($expectedWarnings !== $numWarnings) {
                        $expectedMessage .= ' and ';
                        $foundMessage    .= ' and ';
                        if ($numWarnings !== 0) {
                            if ($foundString !== '') {
                                $foundString .= ' and ';
                            }
                        }
                    }
                }

                if ($expectedWarnings !== $numWarnings) {
                    $expectedMessage .= "$expectedWarnings warning(s)";
                    $foundMessage    .= "$numWarnings warning(s)";
                    if ($numWarnings !== 0) {
                        $foundString .= 'warning(s)';
                        if (empty($errors) === false) {
                            $errors .= PHP_EOL.' -> ';
                        }

                        $errors .= implode(PHP_EOL.' -> ', $problems['found_warnings']);
                    }
                }

                $fullMessage = "$lineMessage $expectedMessage $foundMessage.";
                if ($errors !== '') {
                    $fullMessage .= " The $foundString found were:".PHP_EOL." -> $errors";
                }

                $failureMessages[] = $fullMessage;
            }//end if
        }//end foreach

        return $failureMessages;

    }//end generateFailureMessages()


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    protected abstract function getErrorList();


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    protected abstract function getWarningList();


}//end class

?>
<?php
/**
 * PHP_CodeSniffer tokenises PHP code and detects violations of a
 * defined set of coding standards.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

spl_autoload_register(array('PHP_CodeSniffer', 'autoload'));

if (class_exists('PHP_CodeSniffer_Exception', true) === false) {
    throw new Exception('Class PHP_CodeSniffer_Exception not found');
}

if (class_exists('PHP_CodeSniffer_File', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_File not found');
}

if (class_exists('PHP_CodeSniffer_Tokens', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_Tokens not found');
}

if (class_exists('PHP_CodeSniffer_CLI', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_CLI not found');
}

if (interface_exists('PHP_CodeSniffer_Sniff', true) === false) {
    throw new PHP_CodeSniffer_Exception('Interface PHP_CodeSniffer_Sniff not found');
}

/**
 * PHP_CodeSniffer tokenises PHP code and detects violations of a
 * defined set of coding standards.
 *
 * Standards are specified by classes that implement the PHP_CodeSniffer_Sniff
 * interface. A sniff registers what token types it wishes to listen for, then
 * PHP_CodeSniffer encounters that token, the sniff is invoked and passed
 * information about where the token was found in the stack, and the token stack
 * itself.
 *
 * Sniff files and their containing class must be prefixed with Sniff, and
 * have an extension of .php.
 *
 * Multiple PHP_CodeSniffer operations can be performed by re-calling the
 * process function with different parameters.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer
{

    /**
     * The current version.
     *
     * @var string
     */
    const VERSION = '1.5.0';

    /**
     * Package stability; either stable or beta.
     *
     * @var string
     */
    const STABILITY = 'stable';

    /**
     * The file or directory that is currently being processed.
     *
     * @var string
     */
    protected $file = '';

    /**
     * A cache of different token types, resolved into arrays.
     *
     * @var array()
     * @see standardiseToken()
     */
    private static $_resolveTokenCache = array();

    /**
     * The directories that the processed rulesets are in.
     *
     * This is declared static because it is also used in the
     * autoloader to look for sniffs outside the PHPCS install.
     * This way, standards designed to be installed inside PHPCS can
     * also be used from outside the PHPCS Standards directory.
     *
     * @var string
     */
    protected static $rulesetDirs = array();

    /**
     * The CLI object controlling the run.
     *
     * @var PHP_CodeSniffer_CLI
     */
    public $cli = null;

    /**
     * The Reporting object controlling report generation.
     *
     * @var PHP_CodeSniffer_Reporting
     */
    public $reporting = null;

    /**
     * An array of sniff objects that are being used to check files.
     *
     * @var array(PHP_CodeSniffer_Sniff)
     */
    protected $listeners = array();

    /**
     * An array of sniffs that are being used to check files.
     *
     * @var array(string)
     */
    protected $sniffs = array();

    /**
     * The listeners array, indexed by token type.
     *
     * @var array
     */
    private $_tokenListeners = array();

    /**
     * An array of rules from the ruleset.xml file.
     *
     * It may be empty, indicating that the ruleset does not override
     * any of the default sniff settings.
     *
     * @var array
     */
    protected $ruleset = array();

    /**
     * An array of patterns to use for skipping files.
     *
     * @var array
     */
    protected $ignorePatterns = array();

    /**
     * An array of extensions for files we will check.
     *
     * @var array
     */
    public $allowedFileExtensions = array(
                                     'php' => 'PHP',
                                     'inc' => 'PHP',
                                     'js'  => 'JS',
                                     'css' => 'CSS',
                                    );

    /**
     * An array of variable types for param/var we will check.
     *
     * @var array(string)
     */
    public static $allowedTypes = array(
                                   'array',
                                   'boolean',
                                   'float',
                                   'integer',
                                   'mixed',
                                   'object',
                                   'string',
                                   'resource',
                                   'callable',
                                  );


    /**
     * Constructs a PHP_CodeSniffer object.
     *
     * @param int    $verbosity   The verbosity level.
     *                            1: Print progress information.
     *                            2: Print tokenizer debug information.
     *                            3: Print sniff debug information.
     * @param int    $tabWidth    The number of spaces each tab represents.
     *                            If greater than zero, tabs will be replaced
     *                            by spaces before testing each file.
     * @param string $encoding    The charset of the sniffed files.
     *                            This is important for some reports that output
     *                            with utf-8 encoding as you don't want it double
     *                            encoding messages.
     * @param bool   $interactive If TRUE, will stop after each file with errors
     *                            and wait for user input.
     *
     * @see process()
     */
    public function __construct(
        $verbosity=0,
        $tabWidth=0,
        $encoding='iso-8859-1',
        $interactive=false
    ) {
        if (defined('PHP_CODESNIFFER_VERBOSITY') === false) {
            define('PHP_CODESNIFFER_VERBOSITY', $verbosity);
        }

        if (defined('PHP_CODESNIFFER_TAB_WIDTH') === false) {
            define('PHP_CODESNIFFER_TAB_WIDTH', $tabWidth);
        }

        if (defined('PHP_CODESNIFFER_ENCODING') === false) {
            define('PHP_CODESNIFFER_ENCODING', $encoding);
        }

        if (defined('PHP_CODESNIFFER_INTERACTIVE') === false) {
            define('PHP_CODESNIFFER_INTERACTIVE', $interactive);
        }

        if (defined('PHPCS_DEFAULT_ERROR_SEV') === false) {
            define('PHPCS_DEFAULT_ERROR_SEV', 5);
        }

        if (defined('PHPCS_DEFAULT_WARN_SEV') === false) {
            define('PHPCS_DEFAULT_WARN_SEV', 5);
        }

        // Set default CLI object in case someone is running us
        // without using the command line script.
        $this->cli = new PHP_CodeSniffer_CLI();
        $this->cli->errorSeverity   = PHPCS_DEFAULT_ERROR_SEV;
        $this->cli->warningSeverity = PHPCS_DEFAULT_WARN_SEV;
        $this->cli->dieOnUnknownArg = false;

        $this->reporting = new PHP_CodeSniffer_Reporting();

    }//end __construct()


    /**
     * Autoload static method for loading classes and interfaces.
     *
     * @param string $className The name of the class or interface.
     *
     * @return void
     */
    public static function autoload($className)
    {
        if (substr($className, 0, 4) === 'PHP_') {
            $newClassName = substr($className, 4);
        } else {
            $newClassName = $className;
        }

        $path = str_replace(array('_', '\\'), '/', $newClassName).'.php';

        if (is_file(dirname(__FILE__).'/'.$path) === true) {
            // Check standard file locations based on class name.
            include dirname(__FILE__).'/'.$path;
        } else if (is_file(dirname(__FILE__).'/CodeSniffer/Standards/'.$path) === true) {
            // Check for included sniffs.
            include dirname(__FILE__).'/CodeSniffer/Standards/'.$path;
        } else {
            // Check standard file locations based on the loaded rulesets.
            foreach (self::$rulesetDirs as $rulesetDir) {
                if (is_file(dirname($rulesetDir).'/'.$path) === true) {
                    include_once dirname($rulesetDir).'/'.$path;
                    return;
                }
            }

            // Everything else.
            @include $path;
        }

    }//end autoload()


    /**
     * Sets an array of file extensions that we will allow checking of.
     *
     * If the extension is one of the defaults, a specific tokenizer
     * will be used. Otherwise, the PHP tokenizer will be used for
     * all extensions passed.
     *
     * @param array $extensions An array of file extensions.
     *
     * @return void
     */
    public function setAllowedFileExtensions(array $extensions)
    {
        $newExtensions = array();
        foreach ($extensions as $ext) {
            if (isset($this->allowedFileExtensions[$ext]) === true) {
                $newExtensions[$ext] = $this->allowedFileExtensions[$ext];
            } else {
                $newExtensions[$ext] = 'PHP';
            }
        }

        $this->allowedFileExtensions = $newExtensions;

    }//end setAllowedFileExtensions()


    /**
     * Sets an array of ignore patterns that we use to skip files and folders.
     *
     * Patterns are not case sensitive.
     *
     * @param array $patterns An array of ignore patterns. The pattern is the key
     *                        and the value is either "absolute" or "relative",
     *                        depending on how the pattern should be applied to a
     *                        file path.
     *
     * @return void
     */
    public function setIgnorePatterns(array $patterns)
    {
        $this->ignorePatterns = $patterns;

    }//end setIgnorePatterns()


    /**
     * Gets the array of ignore patterns.
     *
     * Optionally takes a listener to get ignore patterns specified
     * for that sniff only.
     *
     * @param string $listener The listener to get patterns for. If NULL, all
     *                         patterns are returned.
     *
     * @return array
     */
    public function getIgnorePatterns($listener=null)
    {
        if ($listener === null) {
            return $this->ignorePatterns;
        }

        if (isset($this->ignorePatterns[$listener]) === true) {
            return $this->ignorePatterns[$listener];
        }

        return array();

    }//end getIgnorePatterns()


    /**
     * Sets the internal CLI object.
     *
     * @param object $cli The CLI object controlling the run.
     *
     * @return void
     */
    public function setCli($cli)
    {
        $this->cli = $cli;

    }//end setCli()


    /**
     * Processes the files/directories that PHP_CodeSniffer was constructed with.
     *
     * @param string|array $files        The files and directories to process. For
     *                                   directories, each sub directory will also
     *                                   be traversed for source files.
     * @param string|array $standards    The set of code sniffs we are testing
     *                                   against.
     * @param array        $restrictions The sniff codes to restrict the
     *                                   violations to.
     * @param boolean      $local        If true, don't recurse into directories.
     *
     * @return void
     * @throws PHP_CodeSniffer_Exception If files or standard are invalid.
     */
    public function process($files, $standards, array $restrictions=array(), $local=false)
    {
        if (is_array($files) === false) {
            $files = array($files);
        }

        if (is_array($standards) === false) {
            $standards = array($standards);
        }

        // Reset the members.
        $this->listeners       = array();
        $this->sniffs          = array();
        $this->ruleset         = array();
        $this->_tokenListeners = array();
        self::$rulesetDirs     = array();

        // Ensure this option is enabled or else line endings will not always
        // be detected properly for files created on a Mac with the /r line ending.
        ini_set('auto_detect_line_endings', true);

        $sniffs = array();
        foreach ($standards as $standard) {
            $installed = $this->getInstalledStandardPath($standard);
            if ($installed !== null) {
                $standard = $installed;
            } else if (is_dir($standard) === true
                && is_file(realpath($standard.'/ruleset.xml')) === true
            ) {
                $standard = realpath($standard.'/ruleset.xml');
            }

            if (PHP_CODESNIFFER_VERBOSITY === 1) {
                $ruleset = simplexml_load_file($standard);
                if ($ruleset !== false) {
                    $standardName = (string) $ruleset['name'];
                }

                echo "Registering sniffs in the $standardName standard... ";
                if (count($standards) > 1 || PHP_CODESNIFFER_VERBOSITY > 2) {
                    echo PHP_EOL;
                }
            }

            $sniffs = array_merge($sniffs, $this->processRuleset($standard));
        }//end foreach

        $sniffRestrictions = array();
        foreach ($restrictions as $sniffCode) {
            $parts = explode('.', strtolower($sniffCode));
            $sniffRestrictions[] = $parts[0].'_sniffs_'.$parts[1].'_'.$parts[2].'sniff';
        }

        $this->registerSniffs($sniffs, $sniffRestrictions);
        $this->populateTokenListeners();

        if (PHP_CODESNIFFER_VERBOSITY === 1) {
            $numSniffs = count($this->sniffs);
            echo "DONE ($numSniffs sniffs registered)".PHP_EOL;
        }

        // The SVN pre-commit calls process() to init the sniffs
        // and ruleset so there may not be any files to process.
        // But this has to come after that initial setup.
        if (empty($files) === true) {
            return;
        }

        $cliValues    = $this->cli->getCommandLineValues();
        $showProgress = $cliValues['showProgress'];

        if (PHP_CODESNIFFER_VERBOSITY > 0) {
            echo 'Creating file list... ';
        }

        $todo     = $this->getFilesToProcess($files, $local);
        $numFiles = count($todo);

        if (PHP_CODESNIFFER_VERBOSITY > 0) {
            echo "DONE ($numFiles files in queue)".PHP_EOL;
        }

        $numProcessed = 0;
        $dots         = 0;
        $maxLength    = strlen($numFiles);
        $lastDir      = '';
        foreach ($todo as $file) {
            $this->file = $file;
            $currDir = dirname($file);
            if ($lastDir !== $currDir) {
                if (PHP_CODESNIFFER_VERBOSITY > 0) {
                    echo 'Changing into directory '.$currDir.PHP_EOL;
                }

                $lastDir = $currDir;
            }

            $phpcsFile = $this->processFile($file, null, $restrictions);
            $numProcessed++;

            if (PHP_CODESNIFFER_VERBOSITY > 0
                || PHP_CODESNIFFER_INTERACTIVE === true
                || $showProgress === false
            ) {
                continue;
            }

            // Show progress information.
            if ($phpcsFile === null) {
                echo 'S';
            } else {
                $errors   = $phpcsFile->getErrorCount();
                $warnings = $phpcsFile->getWarningCount();
                if ($errors > 0) {
                    echo 'E';
                } else if ($warnings > 0) {
                    echo 'W';
                } else {
                    echo '.';
                }
            }

            $dots++;
            if ($dots === 60) {
                $padding = ($maxLength - strlen($numProcessed));
                echo str_repeat(' ', $padding);
                $percent = round($numProcessed / $numFiles * 100);
                echo " $numProcessed / $numFiles ($percent%)".PHP_EOL;
                $dots = 0;
            }
        }//end foreach

        if (PHP_CODESNIFFER_VERBOSITY === 0
            && PHP_CODESNIFFER_INTERACTIVE === false
            && $showProgress === true
        ) {
            echo PHP_EOL.PHP_EOL;
        }

    }//end process()


    /**
     * Processes a single ruleset and returns a list of the sniffs it represents.
     *
     * Rules founds within the ruleset are processed immediately, but sniff classes
     * are not registered by this method.
     *
     * @param string $rulesetPath The path to a ruleset XML file.
     * @param int    $depth       How many nested processing steps we are in. This
     *                            is only used for debug output.
     *
     * @return array
     * @throws PHP_CodeSniffer_Exception If the ruleset path is invalid.
     */
    public function processRuleset($rulesetPath, $depth=0)
    {
        $rulesetPath = realpath($rulesetPath);
        if (PHP_CODESNIFFER_VERBOSITY > 1) {
            echo str_repeat("\t", $depth);
            echo "Processing ruleset $rulesetPath".PHP_EOL;
        }

        $ruleset = simplexml_load_file($rulesetPath);
        if ($ruleset === false) {
            throw new PHP_CodeSniffer_Exception("Ruleset $rulesetPath is not valid");
        }

        $ownSniffs      = array();
        $includedSniffs = array();
        $excludedSniffs = array();

        $rulesetDir          = dirname($rulesetPath);
        self::$rulesetDirs[] = $rulesetDir;

        if (is_dir($rulesetDir.'/Sniffs') === true) {
            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                echo str_repeat("\t", $depth);
                echo "\tAdding sniff files from \".../".basename($rulesetDir)."/Sniffs/\" directory".PHP_EOL;
            }

            $ownSniffs = $this->_expandSniffDirectory($rulesetDir.'/Sniffs', $depth);
        }

        foreach ($ruleset->rule as $rule) {
            if (isset($rule['ref']) === false) {
                continue;
            }

            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                echo str_repeat("\t", $depth);
                echo "\tProcessing rule \"".$rule['ref'].'"'.PHP_EOL;
            }

            $includedSniffs = array_merge(
                $includedSniffs,
                $this->_expandRulesetReference($rule['ref'], $rulesetDir, $depth)
            );

            if (isset($rule->exclude) === true) {
                foreach ($rule->exclude as $exclude) {
                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        echo str_repeat("\t", $depth);
                        echo "\t\tExcluding rule \"".$exclude['name'].'"'.PHP_EOL;
                    }

                    // Check if a single code is being excluded, which is a shortcut
                    // for setting the severity of the message to 0.
                    $parts = explode('.', $exclude['name']);
                    if (count($parts) === 4) {
                        $this->ruleset[(string) $exclude['name']]['severity'] = 0;
                        if (PHP_CODESNIFFER_VERBOSITY > 1) {
                            echo str_repeat("\t", $depth);
                            echo "\t\t=> severity set to 0".PHP_EOL;
                        }
                    } else {
                        $excludedSniffs = array_merge(
                            $excludedSniffs,
                            $this->_expandRulesetReference($exclude['name'], $rulesetDir, ($depth + 1))
                        );
                    }
                }//end foreach
            }//end if

            $this->_processRule($rule, $depth);
        }//end foreach

        // Process custom ignore pattern rules.
        foreach ($ruleset->{'exclude-pattern'} as $pattern) {
            if (isset($pattern['type']) === false) {
                $pattern['type'] = 'absolute';
            }

            $this->ignorePatterns[(string) $pattern] = (string) $pattern['type'];
            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                echo str_repeat("\t", $depth);
                echo "\t=> added global ".(string) $pattern['type'].' ignore pattern: '.(string) $pattern.PHP_EOL;
            }
        }

        $includedSniffs = array_unique(array_merge($ownSniffs, $includedSniffs));
        $excludedSniffs = array_unique($excludedSniffs);

        if (PHP_CODESNIFFER_VERBOSITY > 1) {
            $included = count($includedSniffs);
            $excluded = count($excludedSniffs);
            echo str_repeat("\t", $depth);
            echo "=> Ruleset processing complete; included $included sniffs and excluded $excluded".PHP_EOL;
        }

        // Merge our own sniff list with our externally included
        // sniff list, but filter out any excluded sniffs.
        $files = array();
        foreach ($includedSniffs as $sniff) {
            if (in_array($sniff, $excludedSniffs) === true) {
                continue;
            } else {
                $files[] = realpath($sniff);
            }
        }

        return $files;

    }//end processRuleset()


    /**
     * Expands a directory into a list of sniff files within.
     *
     * @param string $directory The path to a directory.
     * @param int    $depth     How many nested processing steps we are in. This
     *                          is only used for debug output.
     *
     * @return array
     */
    private function _expandSniffDirectory($directory, $depth=0)
    {
        $sniffs = array();

        if (defined('RecursiveDirectoryIterator::FOLLOW_SYMLINKS') === true) {
            $rdi = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::FOLLOW_SYMLINKS);
        } else {
            $rdi = new RecursiveDirectoryIterator($directory);
        }

        $di = new RecursiveIteratorIterator($rdi, 0, RecursiveIteratorIterator::CATCH_GET_CHILD);

        foreach ($di as $file) {
            $fileName = $file->getFilename();

            // Skip hidden files.
            if (substr($fileName, 0, 1) === '.') {
                continue;
            }

            // We are only interested in PHP and sniff files.
            $fileParts = explode('.', $fileName);
            if (array_pop($fileParts) !== 'php') {
                continue;
            }

            $basename = basename($fileName, '.php');
            if (substr($basename, -5) !== 'Sniff') {
                continue;
            }

            $path = $file->getPathname();
            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                echo str_repeat("\t", $depth);
                echo "\t\t=> $path".PHP_EOL;
            }

            $sniffs[] = $path;
        }//end foreach

        return $sniffs;

    }//end _expandSniffDirectory()


    /**
     * Expands a ruleset reference into a list of sniff files.
     *
     * @param string $ref        The reference from the ruleset XML file.
     * @param string $rulesetDir The directory of the ruleset XML file, used to
     *                           evaluate relative paths.
     * @param int    $depth      How many nested processing steps we are in. This
     *                           is only used for debug output.
     *
     * @return array
     * @throws PHP_CodeSniffer_Exception If the reference is invalid.
     */
    private function _expandRulesetReference($ref, $rulesetDir, $depth=0)
    {
        // Ignore internal sniffs codes as they are used to only
        // hide and change internal messages.
        if (substr($ref, 0, 9) === 'Internal.') {
            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                echo str_repeat("\t", $depth);
                echo "\t\t* ignoring internal sniff code *".PHP_EOL;
            }

            return array();
        }

        // As sniffs can't begin with a full stop, assume references in
        // this format are relative paths and attempt to convert them
        // to absolute paths. If this fails, let the reference run through
        // the normal checks and have it fail as normal.
        if (substr($ref, 0, 1) === '.') {
            $realpath   = realpath($rulesetDir.'/'.$ref);
            if ($realpath !== false) {
                $ref = $realpath;
                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                    echo str_repeat("\t", $depth);
                    echo "\t\t=> $ref".PHP_EOL;
                }
            }
        }

        if (is_dir($ref) === false && is_file($ref) === false) {
            // See if this is a whole standard being referenced.
            $path = realpath(dirname(__FILE__).'/CodeSniffer/Standards/'.$ref);
            if (is_dir($path) === true) {
                $ref = $path;
                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                    echo str_repeat("\t", $depth);
                    echo "\t\t=> $ref".PHP_EOL;
                }
            } else {
                // Work out the sniff path.
                $parts = explode('.', $ref);

                if (count($parts) === 1) {
                    // A whole standard?
                    $path = '';
                } else if (count($parts) === 2) {
                    // A directory of sniffs?
                    $path = '/Sniffs/'.$parts[1];
                } else {
                    // A single sniff?
                    $path = '/Sniffs/'.$parts[1].'/'.$parts[2].'Sniff.php';
                }

                $newRef = realpath(dirname(__FILE__).'/CodeSniffer/Standards/'.$parts[0].$path);
                if ($newRef === false) {
                    // The sniff is not locally installed, so check if it is being
                    // referenced as a remote sniff outside the install. We do this
                    // by looking through all directories where we have found ruleset
                    // files before, looking for ones for this particular standard,
                    // and seeing if it is in there.
                    foreach (self::$rulesetDirs as $dir) {
                        if (basename($dir) !== $parts[0]) {
                            continue;
                        }

                        $newRef = realpath($dir.$path);
                        
                        if ($newRef !== false) {
                            $ref = $newRef;
                        }
                    }
                } else {
                    $ref = $newRef;
                }

                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                    echo str_repeat("\t", $depth);
                    echo "\t\t=> $ref".PHP_EOL;
                }
            }
        }//end if

        if (is_dir($ref) === true) {
            if (is_file($ref.'/ruleset.xml') === true) {
                // We are referencing an external coding standard.
                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                    echo str_repeat("\t", $depth);
                    echo "\t\t* rule is referencing a standard using directory name; processing *".PHP_EOL;
                }

                return $this->processRuleset($ref.'/ruleset.xml', ($depth + 2));
            } else {
                // We are referencing a whole directory of sniffs.
                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                    echo str_repeat("\t", $depth);
                    echo "\t\t* rule is referencing a directory of sniffs *".PHP_EOL;
                    echo str_repeat("\t", $depth);
                    echo "\t\tAdding sniff files from directory".PHP_EOL;
                }

                return $this->_expandSniffDirectory($ref, ($depth + 1));
            }
        } else {
            if (is_file($ref) === false) {
                $error = "Referenced sniff \"$ref\" does not exist";
                throw new PHP_CodeSniffer_Exception($error);
            }

            if (substr($ref, -9) === 'Sniff.php') {
                // A single sniff.
                return array($ref);
            } else {
                // Assume an external ruleset.xml file.
                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                    echo str_repeat("\t", $depth);
                    echo "\t\t* rule is referencing a standard using ruleset path; processing *".PHP_EOL;
                }

                return $this->processRuleset($ref, ($depth + 2));
            }
        }//end if

    }//end _expandRulesetReference()


    /**
     * Processes a rule from a ruleset XML file, overriding built-in defaults.
     *
     * @param SimpleXMLElement $rule  The rule object from a ruleset XML file.
     * @param int              $depth How many nested processing steps we are in.
     *                                This is only used for debug output.
     *
     * @return void
     */
    private function _processRule($rule, $depth=0)
    {
        $code = (string) $rule['ref'];

        // Custom severity.
        if (isset($rule->severity) === true) {
            if (isset($this->ruleset[$code]) === false) {
                $this->ruleset[$code] = array();
            }

            $this->ruleset[$code]['severity'] = (int) $rule->severity;
            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                echo str_repeat("\t", $depth);
                echo "\t\t=> severity set to ".(int) $rule->severity.PHP_EOL;
            }
        }

        // Custom message type.
        if (isset($rule->type) === true) {
            if (isset($this->ruleset[$code]) === false) {
                $this->ruleset[$code] = array();
            }

            $this->ruleset[$code]['type'] = (string) $rule->type;
            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                echo str_repeat("\t", $depth);
                echo "\t\t=> message type set to ".(string) $rule->type.PHP_EOL;
            }
        }

        // Custom message.
        if (isset($rule->message) === true) {
            if (isset($this->ruleset[$code]) === false) {
                $this->ruleset[$code] = array();
            }

            $this->ruleset[$code]['message'] = (string) $rule->message;
            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                echo str_repeat("\t", $depth);
                echo "\t\t=> message set to ".(string) $rule->message.PHP_EOL;
            }
        }

        // Custom properties.
        if (isset($rule->properties) === true) {
            foreach ($rule->properties->property as $prop) {
                if (isset($this->ruleset[$code]) === false) {
                    $this->ruleset[$code] = array(
                                             'properties' => array(),
                                            );
                } else if (isset($this->ruleset[$code]['properties']) === false) {
                    $this->ruleset[$code]['properties'] = array();
                }

                $name = (string) $prop['name'];
                if (isset($prop['type']) === true
                    && (string) $prop['type'] === 'array'
                ) {
                    $value = (string) $prop['value'];
                    $this->ruleset[$code]['properties'][$name] = explode(',', $value);
                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        echo str_repeat("\t", $depth);
                        echo "\t\t=> array property \"$name\" set to \"$value\"".PHP_EOL;
                    }
                } else {
                    $this->ruleset[$code]['properties'][$name] = (string) $prop['value'];
                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        echo str_repeat("\t", $depth);
                        echo "\t\t=> property \"$name\" set to \"".(string) $prop['value'].'"'.PHP_EOL;
                    }
                }
            }//end foreach
        }//end if

        // Ignore patterns.
        foreach ($rule->{'exclude-pattern'} as $pattern) {
            if (isset($this->ignorePatterns[$code]) === false) {
                $this->ignorePatterns[$code] = array();
            }

            if (isset($pattern['type']) === false) {
                $pattern['type'] = 'absolute';
            }

            $this->ignorePatterns[$code][(string) $pattern] = (string) $pattern['type'];
            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                echo str_repeat("\t", $depth);
                echo "\t\t=> added sniff-specific ".(string) $pattern['type'].' ignore pattern: '.(string) $pattern.PHP_EOL;
            }
        }

    }//end _processRule()


    /**
     * Loads and stores sniffs objects used for sniffing files.
     *
     * @param array $files        Paths to the sniff files to register.
     * @param array $restrictions The sniff class names to restrict the allowed
     *                            listeners to.
     *
     * @return void
     */
    public function registerSniffs($files, $restrictions)
    {
        $listeners = array();

        foreach ($files as $file) {
            // Work out where the position of /StandardName/Sniffs/... is
            // so we can determine what the class will be called.
            $sniffPos = strrpos($file, DIRECTORY_SEPARATOR.'Sniffs'.DIRECTORY_SEPARATOR);
            if ($sniffPos === false) {
                continue;
            }

            $slashPos = strrpos(substr($file, 0, $sniffPos), DIRECTORY_SEPARATOR);
            if ($slashPos === false) {
                continue;
            }

            $className = substr($file, ($slashPos + 1));
            $className = substr($className, 0, -4);
            $className = str_replace(DIRECTORY_SEPARATOR, '_', $className);

            // If they have specified a list of sniffs to restrict to, check
            // to see if this sniff is allowed.
            if (empty($restrictions) === false
                && in_array(strtolower($className), $restrictions) === false
            ) {
                continue;
            }

            include_once $file;

            // Support the use of PHP namespaces. If the class name we included
            // contains namespace separators instead of underscores, use this as the
            // class name from now on.
            $classNameNS = str_replace('_', '\\', $className);
            if (class_exists($classNameNS, false) === true) {
                $className = $classNameNS;
            }

            $listeners[$className] = $className;

            if (PHP_CODESNIFFER_VERBOSITY > 2) {
                echo "Registered $className".PHP_EOL;
            }
        }//end foreach

        $this->sniffs = $listeners;

    }//end registerSniffs()


    /**
     * Populates the array of PHP_CodeSniffer_Sniff's for this file.
     *
     * @return void
     * @throws PHP_CodeSniffer_Exception If sniff registration fails.
     */
    public function populateTokenListeners()
    {
        // Construct a list of listeners indexed by token being listened for.
        $this->_tokenListeners = array();

        foreach ($this->sniffs as $listenerClass) {
            // Work out the internal code for this sniff. Detect usage of namespace
            // separators instead of underscores to support PHP namespaces.
            if (strstr($listenerClass, '\\') === false) {
                $parts = explode('_', $listenerClass);
            } else {
                $parts = explode('\\', $listenerClass);
            }

            $code = $parts[0].'.'.$parts[2].'.'.$parts[3];
            $code = substr($code, 0, -5);

            $this->listeners[$listenerClass] = new $listenerClass();

            // Set custom properties.
            if (isset($this->ruleset[$code]['properties']) === true) {
                foreach ($this->ruleset[$code]['properties'] as $name => $value) {
                    $this->setSniffProperty($listenerClass, $name, $value);
                }
            }

            $tokenizers = array('PHP');
            $vars       = get_class_vars($listenerClass);
            if (isset($vars['supportedTokenizers']) === true) {
                $tokenizers = $vars['supportedTokenizers'];
            }

            $tokens = $this->listeners[$listenerClass]->register();
            if (is_array($tokens) === false) {
                $msg = "Sniff $listenerClass register() method must return an array";
                throw new PHP_CodeSniffer_Exception($msg);
            }

            foreach ($tokens as $token) {
                if (isset($this->_tokenListeners[$token]) === false) {
                    $this->_tokenListeners[$token] = array();
                }

                if (in_array($this->listeners[$listenerClass], $this->_tokenListeners[$token], true) === false) {
                    $this->_tokenListeners[$token][] = array(
                                                        'listener'   => $this->listeners[$listenerClass],
                                                        'class'      => $listenerClass,
                                                        'tokenizers' => $tokenizers,
                                                       );
                }
            }
        }//end foreach

    }//end populateTokenListeners()


    /**
     * Set a single property for a sniff.
     *
     * @param string $listenerClass The class name of the sniff.
     * @param string $name          The name of the property to change.
     * @param string $value         The new value of the property.
     *
     * @return void
     */
    public function setSniffProperty($listenerClass, $name, $value)
    {
        // Setting a property for a sniff we are not using.
        if (isset($this->listeners[$listenerClass]) === false) {
            return;
        }

        $name = trim($name);
        if (is_string($value) === true) {
            $value = trim($value);
        }

        // Special case for booleans.
        if ($value === 'true') {
            $value = true;
        } else if ($value === 'false') {
            $value = false;
        }

        $this->listeners[$listenerClass]->$name = $value;

    }//end setSniffProperty()


    /**
     * Get a list of files that will be processed.
     *
     * If passed directories, this method will find all files within them.
     * The method will also perform file extension and ignore pattern filtering.
     *
     * @param string  $paths A list of file or directory paths to process.
     * @param boolean $local If true, only process 1 level of files in directories
     *
     * @return array
     * @throws Exception If there was an error opening a directory.
     * @see    shouldProcessFile()
     */
    public function getFilesToProcess($paths, $local=false)
    {
        $files = array();

        foreach ($paths as $path) {
            if (is_dir($path) === true) {
                if ($local === true) {
                    $di = new DirectoryIterator($path);
                } else {
                    $di = new RecursiveIteratorIterator(
                        new RecursiveDirectoryIterator($path),
                        0,
                        RecursiveIteratorIterator::CATCH_GET_CHILD
                    );
                }

                foreach ($di as $file) {
                    // Check if the file exists after all symlinks are resolved.
                    $filePath = realpath($file->getPathname());
                    if ($filePath === false) {
                        continue;
                    }

                    if (is_dir($filePath) === true) {
                        continue;
                    }

                    if ($this->shouldProcessFile($file->getPathname(), $path) === false) {
                        continue;
                    }

                    $files[] = $file->getPathname();
                }//end foreach
            } else {
                if ($this->shouldIgnoreFile($path, dirname($path)) === true) {
                    continue;
                }

                $files[] = $path;
            }//end if
        }//end foreach

        return $files;

    }//end getFilesToProcess()


    /**
     * Checks filtering rules to see if a file should be checked.
     *
     * Checks both file extension filters and path ignore filters.
     *
     * @param string $path    The path to the file being checked.
     * @param string $basedir The directory to use for relative path checks.
     *
     * @return bool
     */
    public function shouldProcessFile($path, $basedir)
    {
        // Check that the file's extension is one we are checking.
        // We are strict about checking the extension and we don't
        // let files through with no extension or that start with a dot.
        $fileName  = basename($path);
        $fileParts = explode('.', $fileName);
        if ($fileParts[0] === $fileName || $fileParts[0] === '') {
            return false;
        }

        // Checking multi-part file extensions, so need to create a
        // complete extension list and make sure one is allowed.
        $extensions = array();
        array_shift($fileParts);
        foreach ($fileParts as $part) {
            $extensions[implode('.', $fileParts)] = 1;
            array_shift($fileParts);
        }

        $matches = array_intersect_key($extensions, $this->allowedFileExtensions);
        if (empty($matches) === true) {
            return false;
        }

        // If the file's path matches one of our ignore patterns, skip it.
        if ($this->shouldIgnoreFile($path, $basedir) === true) {
            return false;
        }

        return true;

    }//end shouldProcessFile()


    /**
     * Checks filtering rules to see if a file should be ignored.
     *
     * @param string $path    The path to the file being checked.
     * @param string $basedir The directory to use for relative path checks.
     *
     * @return bool
     */
    public function shouldIgnoreFile($path, $basedir)
    {
        $relativePath = $path;
        if (strpos($path, $basedir) === 0) {
            // The +1 cuts off the directory separator as well.
            $relativePath = substr($path, (strlen($basedir) + 1));
        }

        foreach ($this->ignorePatterns as $pattern => $type) {
            if (is_array($pattern) === true) {
                // A sniff specific ignore pattern.
                continue;
            }

            // Maintains backwards compatibility in case the ignore pattern does
            // not have a relative/absolute value.
            if (is_int($pattern) === true) {
                $pattern = $type;
                $type    = 'absolute';
            }

            $replacements = array(
                             '\\,' => ',',
                             '*'   => '.*',
                            );

            // We assume a / directory separator, as do the exclude rules
            // most developers write, so we need a special case for any system
            // that is different.
            if (DIRECTORY_SEPARATOR === '\\') {
                $replacements['/'] = '\\\\';
            }

            $pattern = strtr($pattern, $replacements);

            if ($type === 'relative') {
                $testPath = $relativePath;
            } else {
                $testPath = $path;
            }

            if (preg_match("|{$pattern}|i", $testPath) === 1) {
                return true;
            }
        }//end foreach

        return false;

    }//end shouldIgnoreFile()


    /**
     * Run the code sniffs over a single given file.
     *
     * Processes the file and runs the PHP_CodeSniffer sniffs to verify that it
     * conforms with the standard. Returns the processed file object, or NULL
     * if no file was processed due to error.
     *
     * @param string $file         The file to process.
     * @param string $contents     The contents to parse. If NULL, the content
     *                             is taken from the file system.
     * @param array  $restrictions The sniff codes to restrict the
     *                             violations to.
     *
     * @return PHP_CodeSniffer_File
     * @throws PHP_CodeSniffer_Exception If the file could not be processed.
     * @see    _processFile()
     */
    public function processFile($file, $contents=null, $restrictions=array())
    {
        if ($contents === null && file_exists($file) === false) {
            throw new PHP_CodeSniffer_Exception("Source file $file does not exist");
        }

        $filePath = realpath($file);
        if ($filePath === false) {
            $filePath = $file;
        }

        // Before we go and spend time tokenizing this file, just check
        // to see if there is a tag up top to indicate that the whole
        // file should be ignored. It must be on one of the first two lines.
        $firstContent = $contents;
        if ($contents === null && is_readable($filePath) === true) {
            $handle = fopen($filePath, 'r');
            if ($handle !== false) {
                $firstContent  = fgets($handle);
                $firstContent .= fgets($handle);
                fclose($handle);

                if (strpos($firstContent, '@codingStandardsIgnoreFile') !== false) {
                    // We are ignoring the whole file.
                    if (PHP_CODESNIFFER_VERBOSITY > 0) {
                        echo 'Ignoring '.basename($filePath).PHP_EOL;
                    }

                    return null;
                }
            }
        }//end if

        try {
            $phpcsFile = $this->_processFile($file, $contents, $restrictions);
        } catch (Exception $e) {
            $trace = $e->getTrace();

            $filename = $trace[0]['args'][0];
            if (is_object($filename) === true
                && get_class($filename) === 'PHP_CodeSniffer_File'
            ) {
                $filename = $filename->getFilename();
            } else if (is_numeric($filename) === true) {
                // See if we can find the PHP_CodeSniffer_File object.
                foreach ($trace as $data) {
                    if (isset($data['args'][0]) === true
                        && ($data['args'][0] instanceof PHP_CodeSniffer_File) === true
                    ) {
                        $filename = $data['args'][0]->getFilename();
                    }
                }
            } else if (is_string($filename) === false) {
                $filename = (string) $filename;
            }

            $error = 'An error occurred during processing; checking has been aborted. The error message was: '.$e->getMessage();

            $phpcsFile = new PHP_CodeSniffer_File(
                $filename,
                $this->_tokenListeners,
                $this->allowedFileExtensions,
                $this->ruleset,
                $restrictions,
                $this
            );

            $phpcsFile->addError($error, null);
        }//end try

        $cliValues = $this->cli->getCommandLineValues();

        if (PHP_CODESNIFFER_INTERACTIVE === false) {
            // Cache the report data for this file so we can unset it to save memory.
            $this->reporting->cacheFileReport($phpcsFile, $cliValues);
            return $phpcsFile;
        }

        /*
            Running interactively.
            Print the error report for the current file and then wait for user input.
        */

        // Get current violations and then clear the list to make sure
        // we only print violations for a single file each time.
        $numErrors = null;
        while ($numErrors !== 0) {
            $numErrors = ($phpcsFile->getErrorCount() + $phpcsFile->getWarningCount());
            if ($numErrors === 0) {
                continue;
            }

            $reportClass = $this->reporting->factory('full');
            $reportData  = $this->reporting->prepareFileReport($phpcsFile);
            $reportClass->generateFileReport($reportData, $cliValues['showSources'], $cliValues['reportWidth']);

            echo '<ENTER> to recheck, [s] to skip or [q] to quit : ';
            $input = fgets(STDIN);
            $input = trim($input);

            switch ($input) {
            case 's':
                break(2);
            case 'q':
                exit(0);
                break;
            default:
                // Repopulate the sniffs because some of them save their state
                // and only clear it when the file changes, but we are rechecking
                // the same file.
                $this->populateTokenListeners();
                $phpcsFile = $this->_processFile($file, $contents, $restrictions);
                break;
            }
        }//end while

        return $phpcsFile;

    }//end processFile()


    /**
     * Process the sniffs for a single file.
     *
     * Does raw processing only. No interactive support or error checking.
     *
     * @param string $file         The file to process.
     * @param string $contents     The contents to parse. If NULL, the content
     *                             is taken from the file system.
     * @param array  $restrictions The sniff codes to restrict the
     *                             violations to.
     *
     * @return PHP_CodeSniffer_File
     * @see    processFile()
     */
    private function _processFile($file, $contents, $restrictions)
    {
        if (PHP_CODESNIFFER_VERBOSITY > 0) {
            $startTime = time();
            echo 'Processing '.basename($file).' ';
            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                echo PHP_EOL;
            }
        }

        $phpcsFile = new PHP_CodeSniffer_File(
            $file,
            $this->_tokenListeners,
            $this->allowedFileExtensions,
            $this->ruleset,
            $restrictions,
            $this
        );

        $phpcsFile->start($contents);
        $phpcsFile->cleanUp();

        if (PHP_CODESNIFFER_VERBOSITY > 0) {
            $timeTaken = (time() - $startTime);
            if ($timeTaken === 0) {
                echo 'DONE in < 1 second';
            } else if ($timeTaken === 1) {
                echo 'DONE in 1 second';
            } else {
                echo "DONE in $timeTaken seconds";
            }

            $errors   = $phpcsFile->getErrorCount();
            $warnings = $phpcsFile->getWarningCount();
            echo " ($errors errors, $warnings warnings)".PHP_EOL;
        }

        return $phpcsFile;

    }//end _processFile()


    /**
     * Generates documentation for a coding standard.
     *
     * @param string $standard  The standard to generate docs for
     * @param array  $sniffs    A list of sniffs to limit the docs to.
     * @param string $generator The name of the generator class to use.
     *
     * @return void
     */
    public function generateDocs($standard, array $sniffs=array(), $generator='Text')
    {
        if (class_exists('PHP_CodeSniffer_DocGenerators_'.$generator, true) === false) {
            throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_DocGenerators_'.$generator.' not found');
        }

        $class     = "PHP_CodeSniffer_DocGenerators_$generator";
        $generator = new $class($standard, $sniffs);

        $generator->generate();

    }//end generateDocs()


    /**
     * Gets the array of PHP_CodeSniffer_Sniff's.
     *
     * @return array(PHP_CodeSniffer_Sniff)
     */
    public function getSniffs()
    {
        return $this->listeners;

    }//end getSniffs()


    /**
     * Gets the array of PHP_CodeSniffer_Sniff's indexed by token type.
     *
     * @return array()
     */
    public function getTokenSniffs()
    {
        return $this->_tokenListeners;

    }//end getTokenSniffs()


    /**
     * Takes a token produced from <code>token_get_all()</code> and produces a
     * more uniform token.
     *
     * Note that this method also resolves T_STRING tokens into more discrete
     * types, therefore there is no need to call resolveTstringToken()
     *
     * @param string|array $token The token to convert.
     *
     * @return array The new token.
     */
    public static function standardiseToken($token)
    {
        if (is_array($token) === false) {
            if (isset(self::$_resolveTokenCache[$token]) === true) {
                $newToken = self::$_resolveTokenCache[$token];
            } else {
                $newToken = self::resolveSimpleToken($token);
            }
        } else {
            switch ($token[0]) {
            case T_STRING:
                // Some T_STRING tokens can be more specific.
                $tokenType = strtolower($token[1]);
                if (isset(self::$_resolveTokenCache[$tokenType]) === true) {
                    $newToken = self::$_resolveTokenCache[$tokenType];
                } else {
                    $newToken = self::resolveTstringToken($tokenType);
                }

                break;
            case T_CURLY_OPEN:
                $newToken = array(
                             'code' => T_OPEN_CURLY_BRACKET,
                             'type' => 'T_OPEN_CURLY_BRACKET',
                            );
                break;
            default:
                $newToken = array(
                             'code' => $token[0],
                             'type' => token_name($token[0]),
                            );
                break;
            }//end switch

            $newToken['content'] = $token[1];
        }//end if

        return $newToken;

    }//end standardiseToken()


    /**
     * Converts T_STRING tokens into more usable token names.
     *
     * The token should be produced using the token_get_all() function.
     * Currently, not all T_STRING tokens are converted.
     *
     * @param string $token The T_STRING token to convert as constructed
     *                      by token_get_all().
     *
     * @return array The new token.
     */
    public static function resolveTstringToken($token)
    {
        $newToken = array();
        switch ($token) {
        case 'false':
            $newToken['type'] = 'T_FALSE';
            break;
        case 'true':
            $newToken['type'] = 'T_TRUE';
            break;
        case 'null':
            $newToken['type'] = 'T_NULL';
            break;
        case 'self':
            $newToken['type'] = 'T_SELF';
            break;
        case 'parent':
            $newToken['type'] = 'T_PARENT';
            break;
        default:
            $newToken['type'] = 'T_STRING';
            break;
        }

        $newToken['code'] = constant($newToken['type']);

        self::$_resolveTokenCache[$token] = $newToken;
        return $newToken;

    }//end resolveTstringToken()


    /**
     * Converts simple tokens into a format that conforms to complex tokens
     * produced by token_get_all().
     *
     * Simple tokens are tokens that are not in array form when produced from
     * token_get_all().
     *
     * @param string $token The simple token to convert.
     *
     * @return array The new token in array format.
     */
    public static function resolveSimpleToken($token)
    {
        $newToken = array();

        switch ($token) {
        case '{':
            $newToken['type'] = 'T_OPEN_CURLY_BRACKET';
            break;
        case '}':
            $newToken['type'] = 'T_CLOSE_CURLY_BRACKET';
            break;
        case '[':
            $newToken['type'] = 'T_OPEN_SQUARE_BRACKET';
            break;
        case ']':
            $newToken['type'] = 'T_CLOSE_SQUARE_BRACKET';
            break;
        case '(':
            $newToken['type'] = 'T_OPEN_PARENTHESIS';
            break;
        case ')':
            $newToken['type'] = 'T_CLOSE_PARENTHESIS';
            break;
        case ':':
            $newToken['type'] = 'T_COLON';
            break;
        case '.':
            $newToken['type'] = 'T_STRING_CONCAT';
            break;
        case '?':
            $newToken['type'] = 'T_INLINE_THEN';
            break;
        case ';':
            $newToken['type'] = 'T_SEMICOLON';
            break;
        case '=':
            $newToken['type'] = 'T_EQUAL';
            break;
        case '*':
            $newToken['type'] = 'T_MULTIPLY';
            break;
        case '/':
            $newToken['type'] = 'T_DIVIDE';
            break;
        case '+':
            $newToken['type'] = 'T_PLUS';
            break;
        case '-':
            $newToken['type'] = 'T_MINUS';
            break;
        case '%':
            $newToken['type'] = 'T_MODULUS';
            break;
        case '^':
            $newToken['type'] = 'T_POWER';
            break;
        case '&':
            $newToken['type'] = 'T_BITWISE_AND';
            break;
        case '|':
            $newToken['type'] = 'T_BITWISE_OR';
            break;
        case '<':
            $newToken['type'] = 'T_LESS_THAN';
            break;
        case '>':
            $newToken['type'] = 'T_GREATER_THAN';
            break;
        case '!':
            $newToken['type'] = 'T_BOOLEAN_NOT';
            break;
        case ',':
            $newToken['type'] = 'T_COMMA';
            break;
        case '@':
            $newToken['type'] = 'T_ASPERAND';
            break;
        case '$':
            $newToken['type'] = 'T_DOLLAR';
            break;
        case '`':
            $newToken['type'] = 'T_BACKTICK';
            break;
        default:
            $newToken['type'] = 'T_NONE';
            break;
        }//end switch

        $newToken['code']    = constant($newToken['type']);
        $newToken['content'] = $token;

        self::$_resolveTokenCache[$token] = $newToken;
        return $newToken;

    }//end resolveSimpleToken()


    /**
     * Returns true if the specified string is in the camel caps format.
     *
     * @param string  $string      The string the verify.
     * @param boolean $classFormat If true, check to see if the string is in the
     *                             class format. Class format strings must start
     *                             with a capital letter and contain no
     *                             underscores.
     * @param boolean $public      If true, the first character in the string
     *                             must be an a-z character. If false, the
     *                             character must be an underscore. This
     *                             argument is only applicable if $classFormat
     *                             is false.
     * @param boolean $strict      If true, the string must not have two capital
     *                             letters next to each other. If false, a
     *                             relaxed camel caps policy is used to allow
     *                             for acronyms.
     *
     * @return boolean
     */
    public static function isCamelCaps(
        $string,
        $classFormat=false,
        $public=true,
        $strict=true
    ) {
        // Check the first character first.
        if ($classFormat === false) {
            $legalFirstChar = '';
            if ($public === false) {
                $legalFirstChar = '[_]';
            }

            if ($strict === false) {
                // Can either start with a lowercase letter, or multiple uppercase
                // in a row, representing an acronym.
                $legalFirstChar .= '([A-Z]{2,}|[a-z])';
            } else {
                $legalFirstChar .= '[a-z]';
            }
        } else {
            $legalFirstChar = '[A-Z]';
        }

        if (preg_match("/^$legalFirstChar/", $string) === 0) {
            return false;
        }

        // Check that the name only contains legal characters.
        $legalChars = 'a-zA-Z0-9';
        if (preg_match("|[^$legalChars]|", substr($string, 1)) > 0) {
            return false;
        }

        if ($strict === true) {
            // Check that there are not two capital letters next to each other.
            $length          = strlen($string);
            $lastCharWasCaps = $classFormat;

            for ($i = 1; $i < $length; $i++) {
                $ascii = ord($string{$i});
                if ($ascii >= 48 && $ascii <= 57) {
                    // The character is a number, so it cant be a capital.
                    $isCaps = false;
                } else {
                    if (strtoupper($string{$i}) === $string{$i}) {
                        $isCaps = true;
                    } else {
                        $isCaps = false;
                    }
                }

                if ($isCaps === true && $lastCharWasCaps === true) {
                    return false;
                }

                $lastCharWasCaps = $isCaps;
            }
        }//end if

        return true;

    }//end isCamelCaps()


    /**
     * Returns true if the specified string is in the underscore caps format.
     *
     * @param string $string The string to verify.
     *
     * @return boolean
     */
    public static function isUnderscoreName($string)
    {
        // If there are space in the name, it can't be valid.
        if (strpos($string, ' ') !== false) {
            return false;
        }

        $validName = true;
        $nameBits  = explode('_', $string);

        if (preg_match('|^[A-Z]|', $string) === 0) {
            // Name does not begin with a capital letter.
            $validName = false;
        } else {
            foreach ($nameBits as $bit) {
                if ($bit === '') {
                    continue;
                }

                if ($bit{0} !== strtoupper($bit{0})) {
                    $validName = false;
                    break;
                }
            }
        }

        return $validName;

    }//end isUnderscoreName()


    /**
     * Returns a valid variable type for param/var tag.
     *
     * If type is not one of the standard type, it must be a custom type.
     * Returns the correct type name suggestion if type name is invalid.
     *
     * @param string $varType The variable type to process.
     *
     * @return string
     */
    public static function suggestType($varType)
    {
        if ($varType === '') {
            return '';
        }

        if (in_array($varType, self::$allowedTypes) === true) {
            return $varType;
        } else {
            $lowerVarType = strtolower($varType);
            switch ($lowerVarType) {
            case 'bool':
                return 'boolean';
            case 'double':
            case 'real':
                return 'float';
            case 'int':
                return 'integer';
            case 'array()':
                return 'array';
            }//end switch

            if (strpos($lowerVarType, 'array(') !== false) {
                // Valid array declaration:
                // array, array(type), array(type1 => type2).
                $matches = array();
                $pattern = '/^array\(\s*([^\s^=^>]*)(\s*=>\s*(.*))?\s*\)/i';
                if (preg_match($pattern, $varType, $matches) !== 0) {
                    $type1 = '';
                    if (isset($matches[1]) === true) {
                        $type1 = $matches[1];
                    }

                    $type2 = '';
                    if (isset($matches[3]) === true) {
                        $type2 = $matches[3];
                    }

                    $type1 = self::suggestType($type1);
                    $type2 = self::suggestType($type2);
                    if ($type2 !== '') {
                        $type2 = ' => '.$type2;
                    }

                    return "array($type1$type2)";
                } else {
                    return 'array';
                }//end if
            } else if (in_array($lowerVarType, self::$allowedTypes) === true) {
                // A valid type, but not lower cased.
                return $lowerVarType;
            } else {
                // Must be a custom type name.
                return $varType;
            }//end if
        }//end if

    }//end suggestType()


    /**
     * Get a list of all coding standards installed.
     *
     * Coding standards are directories located in the
     * CodeSniffer/Standards directory. Valid coding standards
     * include a Sniffs subdirectory.
     *
     * @param boolean $includeGeneric If true, the special "Generic"
     *                                coding standard will be included
     *                                if installed.
     * @param string  $standardsDir   A specific directory to look for standards
     *                                in. If not specified, PHP_CodeSniffer will
     *                                look in its default location.
     *
     * @return array
     * @see isInstalledStandard()
     */
    public static function getInstalledStandards(
        $includeGeneric=false,
        $standardsDir=''
    ) {
        $installedStandards = array();

        if ($standardsDir === '') {
            $standardsDir = dirname(__FILE__).'/CodeSniffer/Standards';
        }

        $di = new DirectoryIterator($standardsDir);
        foreach ($di as $file) {
            if ($file->isDir() === true && $file->isDot() === false) {
                $filename = $file->getFilename();

                // Ignore the special "Generic" standard.
                if ($includeGeneric === false && $filename === 'Generic') {
                    continue;
                }

                // Valid coding standard dirs include a standard class.
                $csFile = $file->getPathname().'/ruleset.xml';
                if (is_file($csFile) === true) {
                    // We found a coding standard directory.
                    $installedStandards[] = $filename;
                }
            }
        }

        return $installedStandards;

    }//end getInstalledStandards()


    /**
     * Determine if a standard is installed.
     *
     * Coding standards are directories located in the
     * CodeSniffer/Standards directory. Valid coding standards
     * include a Sniffs subdirectory.
     *
     * @param string $standard The name of the coding standard.
     *
     * @return boolean
     * @see getInstalledStandards()
     */
    public static function isInstalledStandard($standard)
    {
        $path = self::getInstalledStandardPath($standard);
        if ($path !== null) {
            return true;
        } else {
            // This could be a custom standard, installed outside our
            // standards directory.
            $ruleset = rtrim($standard, ' /\\').DIRECTORY_SEPARATOR.'ruleset.xml';
            if (is_file($ruleset) === true) {
                return true;
            }

            // Might also be an actual ruleset file itself.
            // If it has an XML extension, let's at least try it.
            if (is_file($standard) === true
                && substr(strtolower($standard), -4) === '.xml'
            ) {
                return true;
            }
        }

        return false;

    }//end isInstalledStandard()


    /**
     * Return the path of an installed coding standard.
     *
     * Coding standards are directories located in the
     * CodeSniffer/Standards directory. Valid coding standards
     * include a Sniffs subdirectory.
     *
     * @param string $standard The name of the coding standard.
     *
     * @return string|null
     */
    public static function getInstalledStandardPath($standard)
    {
        $path = realpath(dirname(__FILE__).'/CodeSniffer/Standards/'.$standard.'/ruleset.xml');
        if (is_file($path) === true) {
            return $path;
        }

        return null;

    }//end getInstalledStandardPath()


    /**
     * Get a single config value.
     *
     * Config data is stored in the data dir, in a file called
     * CodeSniffer.conf. It is a simple PHP array.
     *
     * @param string $key The name of the config value.
     *
     * @return string
     * @see setConfigData()
     * @see getAllConfigData()
     */
    public static function getConfigData($key)
    {
        $phpCodeSnifferConfig = self::getAllConfigData();

        if ($phpCodeSnifferConfig === null) {
            return null;
        }

        if (isset($phpCodeSnifferConfig[$key]) === false) {
            return null;
        }

        return $phpCodeSnifferConfig[$key];

    }//end getConfigData()


    /**
     * Set a single config value.
     *
     * Config data is stored in the data dir, in a file called
     * CodeSniffer.conf. It is a simple PHP array.
     *
     * @param string      $key   The name of the config value.
     * @param string|null $value The value to set. If null, the config
     *                           entry is deleted, reverting it to the
     *                           default value.
     * @param boolean     $temp  Set this config data temporarily for this
     *                           script run. This will not write the config
     *                           data to the config file.
     *
     * @return boolean
     * @see getConfigData()
     * @throws PHP_CodeSniffer_Exception If the config file can not be written.
     */
    public static function setConfigData($key, $value, $temp=false)
    {
        if ($temp === false) {
            $configFile = dirname(__FILE__).'/CodeSniffer.conf';
            if (is_file($configFile) === false
                && strpos('@data_dir@', '@data_dir') === false
            ) {
                // If data_dir was replaced, this is a PEAR install and we can
                // use the PEAR data dir to store the conf file.
                $configFile = '@data_dir@/PHP_CodeSniffer/CodeSniffer.conf';
            }

            if (is_file($configFile) === true
                && is_writable($configFile) === false
            ) {
                $error = "Config file $configFile is not writable";
                throw new PHP_CodeSniffer_Exception($error);
            }
        }

        $phpCodeSnifferConfig = self::getAllConfigData();

        if ($value === null) {
            if (isset($phpCodeSnifferConfig[$key]) === true) {
                unset($phpCodeSnifferConfig[$key]);
            }
        } else {
            $phpCodeSnifferConfig[$key] = $value;
        }

        if ($temp === false) {
            $output  = '<'.'?php'."\n".' $phpCodeSnifferConfig = ';
            $output .= var_export($phpCodeSnifferConfig, true);
            $output .= "\n?".'>';

            if (file_put_contents($configFile, $output) === false) {
                return false;
            }
        }

        $GLOBALS['PHP_CODESNIFFER_CONFIG_DATA'] = $phpCodeSnifferConfig;

        return true;

    }//end setConfigData()


    /**
     * Get all config data in an array.
     *
     * @return string
     * @see getConfigData()
     */
    public static function getAllConfigData()
    {
        if (isset($GLOBALS['PHP_CODESNIFFER_CONFIG_DATA']) === true) {
            return $GLOBALS['PHP_CODESNIFFER_CONFIG_DATA'];
        }

        $configFile = dirname(__FILE__).'/CodeSniffer.conf';
        if (is_file($configFile) === false) {
            $configFile = '@data_dir@/PHP_CodeSniffer/CodeSniffer.conf';
        }

        if (is_file($configFile) === false) {
            return null;
        }

        include $configFile;
        $GLOBALS['PHP_CODESNIFFER_CONFIG_DATA'] = $phpCodeSnifferConfig;
        return $GLOBALS['PHP_CODESNIFFER_CONFIG_DATA'];

    }//end getAllConfigData()


}//end class

?>
<?php
/**
 * An exception thrown by PHP_CodeSniffer when it encounters an unrecoverable error.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * An exception thrown by PHP_CodeSniffer when it encounters an unrecoverable error.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_Exception extends Exception
{

}//end class

?>
<?php
/**
 * Represents a PHP_CodeSniffer report.
 *
 * PHP version 5.
 * 
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Gabriele Santini <gsantini@sqli.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Represents a PHP_CodeSniffer report.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Gabriele Santini <gsantini@sqli.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
interface PHP_CodeSniffer_Report
{


    /**
     * Generate a partial report for a single processed file.
     *
     * Function should return TRUE if it printed or stored data about the file
     * and FALSE if it ignored the file. Returning TRUE indicates that the file and
     * its data should be counted in the grand totals.
     *
     * @param array   $report      Prepared report data.
     * @param boolean $showSources Show sources?
     * @param int     $width       Maximum allowed line width.
     *
     * @return boolean
     */
    public function generateFileReport(
        $report,
        $showSources=false,
        $width=80
    );


    /**
     * Generate the actual report.
     * 
     * @param string  $cachedData    Any partial report data that was returned from
     *                               generateFileReport during the run.
     * @param int     $totalFiles    Total number of files processed during the run.
     * @param int     $totalErrors   Total number of errors found during the run.
     * @param int     $totalWarnings Total number of warnings found during the run.
     * @param boolean $showSources   Show sources?
     * @param int     $width         Maximum allowed line width.
     * @param boolean $toScreen      Is the report being printed to screen?
     *
     * @return void
     */
    public function generate(
        $cachedData,
        $totalFiles,
        $totalErrors,
        $totalWarnings,
        $showSources=false,
        $width=80,
        $toScreen=true
    );


}//end interface

?>
<?php
/**
 * Full report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Gabriele Santini <gsantini@sqli.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Full report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Gabriele Santini <gsantini@sqli.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_Reports_Full implements PHP_CodeSniffer_Report
{


    /**
     * Generate a partial report for a single processed file.
     *
     * Function should return TRUE if it printed or stored data about the file
     * and FALSE if it ignored the file. Returning TRUE indicates that the file and
     * its data should be counted in the grand totals.
     *
     * @param array   $report      Prepared report data.
     * @param boolean $showSources Show sources?
     * @param int     $width       Maximum allowed line width.
     *
     * @return boolean
     */
    public function generateFileReport(
        $report,
        $showSources=false,
        $width=80
    ) {
        if ($report['errors'] === 0 && $report['warnings'] === 0) {
            // Nothing to print.
            return false;
        }

        $width = max($width, 70);
        $file  = $report['filename'];

        echo PHP_EOL.'FILE: ';
        if (strlen($file) <= ($width - 9)) {
            echo $file;
        } else {
            echo '...'.substr($file, (strlen($file) - ($width - 9)));
        }

        echo PHP_EOL;
        echo str_repeat('-', $width).PHP_EOL;

        echo 'FOUND '.$report['errors'].' ERROR(S) ';
        if ($report['warnings'] > 0) {
            echo 'AND '.$report['warnings'].' WARNING(S) ';
        }

        echo 'AFFECTING '.count($report['messages']).' LINE(S)'.PHP_EOL;
        echo str_repeat('-', $width).PHP_EOL;

        // Work out the max line number for formatting.
        $maxLine = 0;
        foreach ($report['messages'] as $line => $lineErrors) {
            if ($line > $maxLine) {
                $maxLine = $line;
            }
        }

        $maxLineLength = strlen($maxLine);

        // The length of the word ERROR or WARNING; used for padding.
        if ($report['warnings'] > 0) {
            $typeLength = 7;
        } else {
            $typeLength = 5;
        }

        // The padding that all lines will require that are
        // printing an error message overflow.
        $paddingLine2  = str_repeat(' ', ($maxLineLength + 1));
        $paddingLine2 .= ' | ';
        $paddingLine2 .= str_repeat(' ', $typeLength);
        $paddingLine2 .= ' | ';

        // The maximum amount of space an error message can use.
        $maxErrorSpace = ($width - strlen($paddingLine2) - 1);

        foreach ($report['messages'] as $line => $lineErrors) {
            foreach ($lineErrors as $column => $colErrors) {
                foreach ($colErrors as $error) {
                    $message = $error['message'];
                    if ($showSources === true) {
                        $message .= ' ('.$error['source'].')';
                    }

                    // The padding that goes on the front of the line.
                    $padding  = ($maxLineLength - strlen($line));
                    $errorMsg = wordwrap(
                        $message,
                        $maxErrorSpace,
                        PHP_EOL.$paddingLine2
                    );

                    echo ' '.str_repeat(' ', $padding).$line.' | '.$error['type'];
                    if ($error['type'] === 'ERROR') {
                        if ($report['warnings'] > 0) {
                            echo '  ';
                        }
                    }

                    echo ' | '.$errorMsg.PHP_EOL;
                }//end foreach
            }//end foreach
        }//end foreach

        echo str_repeat('-', $width).PHP_EOL.PHP_EOL;
        return true;

    }//end generateFileReport()


    /**
     * Prints all errors and warnings for each file processed.
     *
     * @param string  $cachedData    Any partial report data that was returned from
     *                               generateFileReport during the run.
     * @param int     $totalFiles    Total number of files processed during the run.
     * @param int     $totalErrors   Total number of errors found during the run.
     * @param int     $totalWarnings Total number of warnings found during the run.
     * @param boolean $showSources   Show sources?
     * @param int     $width         Maximum allowed line width.
     * @param boolean $toScreen      Is the report being printed to screen?
     *
     * @return void
     */
    public function generate(
        $cachedData,
        $totalFiles,
        $totalErrors,
        $totalWarnings,
        $showSources=false,
        $width=80,
        $toScreen=true
    ) {
        echo $cachedData;

        if ($toScreen === true
            && PHP_CODESNIFFER_INTERACTIVE === false
            && class_exists('PHP_Timer', false) === true
        ) {
            echo PHP_Timer::resourceUsage().PHP_EOL.PHP_EOL;
        }

    }//end generate()


}//end class

?>
<?php
/**
 * Csv report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Gabriele Santini <gsantini@sqli.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Csv report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Gabriele Santini <gsantini@sqli.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_Reports_Csv implements PHP_CodeSniffer_Report
{


    /**
     * Generate a partial report for a single processed file.
     *
     * Function should return TRUE if it printed or stored data about the file
     * and FALSE if it ignored the file. Returning TRUE indicates that the file and
     * its data should be counted in the grand totals.
     *
     * @param array   $report      Prepared report data.
     * @param boolean $showSources Show sources?
     * @param int     $width       Maximum allowed line width.
     *
     * @return boolean
     */
    public function generateFileReport(
        $report,
        $showSources=false,
        $width=80
    ) {
        if ($report['errors'] === 0 && $report['warnings'] === 0) {
            // Nothing to print.
            return false;
        }

        foreach ($report['messages'] as $line => $lineErrors) {
            foreach ($lineErrors as $column => $colErrors) {
                foreach ($colErrors as $error) {
                    $filename = str_replace('"', '\"', $report['filename']);
                    $message  = str_replace('"', '\"', $error['message']);
                    $type     = strtolower($error['type']);
                    $source   = $error['source'];
                    $severity = $error['severity'];
                    echo "\"$filename\",$line,$column,$type,\"$message\",$source,$severity".PHP_EOL;
                }
            }
        }

        return true;

    }//end generateFileReport()


    /**
     * Generates a csv report.
     * 
     * @param string  $cachedData    Any partial report data that was returned from
     *                               generateFileReport during the run.
     * @param int     $totalFiles    Total number of files processed during the run.
     * @param int     $totalErrors   Total number of errors found during the run.
     * @param int     $totalWarnings Total number of warnings found during the run.
     * @param boolean $showSources   Show sources?
     * @param int     $width         Maximum allowed line width.
     * @param boolean $toScreen      Is the report being printed to screen?
     *
     * @return void
     */
    public function generate(
        $cachedData,
        $totalFiles,
        $totalErrors,
        $totalWarnings,
        $showSources=false,
        $width=80,
        $toScreen=true
    ) {
        echo 'File,Line,Column,Type,Message,Source,Severity'.PHP_EOL;
        echo $cachedData;

    }//end generate()


}//end class

?>
<?php
/**
 * Notify-send report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Christian Weiske <christian.weiske@netresearch.de>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2012 Christian Weiske
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Notify-send report for PHP_CodeSniffer.
 *
 * Supported configuration parameters:
 * - notifysend_path    - Full path to notify-send cli command
 * - notifysend_timeout - Timeout in milliseconds
 * - notifysend_showok  - Show "ok, all fine" messages (0/1)
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Christian Weiske <christian.weiske@netresearch.de>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2012 Christian Weiske
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_Reports_Notifysend implements PHP_CodeSniffer_Report
{

    /**
     * Notification timeout in milliseconds.
     *
     * @var integer
     */
    protected $timeout = 3000;

    /**
     * Path to notify-send command.
     *
     * @var string
     */
    protected $path = 'notify-send';

    /**
     * Show "ok, all fine" messages.
     *
     * @var boolean
     */
    protected $showOk = true;

    /**
     * Version of installed notify-send executable.
     *
     * @var string
     */
    protected $version = null;

    /**
     * A record of the last file checked.
     *
     * This is used in case we only checked one file and need to print
     * the name/path of the file. We wont have access to the checked file list
     * after the run has been completed.
     *
     * @var string
     */
    private $_lastCheckedFile = '';


    /**
     * Load configuration data.
     *
     * @return void
     */
    public function __construct()
    {
        $path = PHP_CodeSniffer::getConfigData('notifysend_path');
        if ($path !== null) {
            $this->path = $path;
        }

        $timeout = PHP_CodeSniffer::getConfigData('notifysend_timeout');
        if ($timeout !== null) {
            $this->timeout = (int) $timeout;
        }

        $showOk = PHP_CodeSniffer::getConfigData('notifysend_showok');
        if ($showOk !== null) {
            $this->showOk = (boolean) $showOk;
        }

        $this->version = str_replace(
            'notify-send ',
            '',
            exec($this->path . ' --version')
        );

    }//end __construct()


    /**
     * Generate a partial report for a single processed file.
     *
     * Function should return TRUE if it printed or stored data about the file
     * and FALSE if it ignored the file. Returning TRUE indicates that the file and
     * its data should be counted in the grand totals.
     *
     * @param array   $report      Prepared report data.
     * @param boolean $showSources Show sources?
     * @param int     $width       Maximum allowed line width.
     *
     * @return boolean
     */
    public function generateFileReport(
        $report,
        $showSources=false,
        $width=80
    ) {
        // We don't need to print anything, but we want this file counted
        // in the total number of checked files even if it has no errors.
        $this->_lastCheckedFile = $report['filename'];
        return true;

    }//end generateFileReport()


    /**
     * Generates a summary of errors and warnings for each file processed.
     *
     * @param string  $cachedData    Any partial report data that was returned from
     *                               generateFileReport during the run.
     * @param int     $totalFiles    Total number of files processed during the run.
     * @param int     $totalErrors   Total number of errors found during the run.
     * @param int     $totalWarnings Total number of warnings found during the run.
     * @param boolean $showSources   Show sources?
     * @param int     $width         Maximum allowed line width.
     * @param boolean $toScreen      Is the report being printed to screen?
     *
     * @return void
     */
    public function generate(
        $cachedData,
        $totalFiles,
        $totalErrors,
        $totalWarnings,
        $showSources=false,
        $width=80,
        $toScreen=true
    ) {
        $msg = $this->generateMessage($totalFiles, $totalErrors, $totalWarnings);
        if ($msg === null) {
            if ($this->showOk === true) {
                $this->notifyAllFine();
            }
        } else {
            $this->notifyErrors($msg);
        }

    }//end generate()


    /**
     * Generate the error message to show to the user.
     *
     * @param int $totalFiles    Total number of files processed during the run.
     * @param int $totalErrors   Total number of errors found during the run.
     * @param int $totalWarnings Total number of warnings found during the run.
     *
     * @return string Error message or NULL if no error/warning found.
     */
    protected function generateMessage($totalFiles, $totalErrors, $totalWarnings)
    {
        if ($totalErrors === 0 && $totalWarnings === 0) {
            // Nothing to print.
            return null;
        }

        $msg = '';
        if ($totalFiles > 1) {
            $msg .= 'Checked '.$totalFiles.' files'.PHP_EOL;
        } else {
            $msg .= $this->_lastCheckedFile.PHP_EOL;
        }

        if ($totalWarnings > 0) {
            $msg .= $totalWarnings.' warnings'.PHP_EOL;
        }

        if ($totalErrors > 0) {
            $msg .= $totalErrors.' errors'.PHP_EOL;
        }

        return $msg;

    }//end generateMessage()


    /**
     * Tell the user that all is fine and no error/warning has been found.
     *
     * @return void
     */
    protected function notifyAllFine()
    {
        $cmd  = $this->getBasicCommand();
        $cmd .= ' -i info';
        $cmd .= ' "PHP CodeSniffer: Ok"';
        $cmd .= ' "All fine"';
        exec($cmd);

    }//end notifyAllFine()


    /**
     * Tell the user that errors/warnings have been found.
     *
     * @param string $msg Message to display.
     *
     * @return void
     */
    protected function notifyErrors($msg)
    {
        $cmd  = $this->getBasicCommand();
        $cmd .= ' -i error';
        $cmd .= ' "PHP CodeSniffer: Error"';
        $cmd .= ' '.escapeshellarg(trim($msg));
        exec($cmd);

    }//end notifyErrors()


    /**
     * Generate and return the basic notify-send command string to execute.
     *
     * @return string Shell command with common parameters.
     */
    protected function getBasicCommand()
    {
        $cmd  = escapeshellcmd($this->path);
        $cmd .= ' --category dev.validate';
        $cmd .= ' -h int:transient:1';
        $cmd .= ' -t '.(int) $this->timeout;
        if (version_compare($this->version, '0.7.3', '>=') === true) {
            $cmd .= ' -a phpcs';
        }

        return $cmd;

    }//end getBasicCommand()


}//end class

?>
<?php
/**
 * Summary report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Gabriele Santini <gsantini@sqli.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Summary report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Gabriele Santini <gsantini@sqli.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_Reports_Summary implements PHP_CodeSniffer_Report
{


    /**
     * Generate a partial report for a single processed file.
     *
     * If verbose output is enabled, results are shown for all files, even if
     * they have no errors or warnings. If verbose output is disabled, we only
     * show files that have at least one warning or error.
     *
     * @param array   $report      Prepared report data.
     * @param boolean $showSources Show sources?
     * @param int     $width       Maximum allowed line width.
     *
     * @return boolean
     */
    public function generateFileReport(
        $report,
        $showSources=false,
        $width=80
    ) {
        if (PHP_CODESNIFFER_VERBOSITY === 0
            && $report['errors'] === 0
            && $report['warnings'] === 0
        ) {
            // Nothing to print.
            return false;
        }

        $width = max($width, 70);
        $file  = $report['filename'];

        $padding = ($width - 18 - strlen($file));
        if ($padding < 0) {
            $file    = '...'.substr($file, (($padding * -1) + 3));
            $padding = 0;
        }

        echo $file.str_repeat(' ', $padding).'  ';
        echo $report['errors'];
        echo str_repeat(' ', (8 - strlen((string) $report['errors'])));
        echo $report['warnings'];
        echo PHP_EOL;

        return true;

    }//end generateFileReport()


    /**
     * Generates a summary of errors and warnings for each file processed.
     * 
     * @param string  $cachedData    Any partial report data that was returned from
     *                               generateFileReport during the run.
     * @param int     $totalFiles    Total number of files processed during the run.
     * @param int     $totalErrors   Total number of errors found during the run.
     * @param int     $totalWarnings Total number of warnings found during the run.
     * @param boolean $showSources   Show sources?
     * @param int     $width         Maximum allowed line width.
     * @param boolean $toScreen      Is the report being printed to screen?
     *
     * @return void
     */
    public function generate(
        $cachedData,
        $totalFiles,
        $totalErrors,
        $totalWarnings,
        $showSources=false,
        $width=80,
        $toScreen=true
    ) {
        echo PHP_EOL.'PHP CODE SNIFFER REPORT SUMMARY'.PHP_EOL;
        echo str_repeat('-', $width).PHP_EOL;
        echo 'FILE'.str_repeat(' ', ($width - 20)).'ERRORS  WARNINGS'.PHP_EOL;
        echo str_repeat('-', $width).PHP_EOL;

        echo $cachedData;

        echo str_repeat('-', $width).PHP_EOL;
        echo 'A TOTAL OF '.$totalErrors.' ERROR(S) ';
        echo 'AND '.$totalWarnings.' WARNING(S) ';

        echo 'WERE FOUND IN '.$totalFiles.' FILE(S)'.PHP_EOL;
        echo str_repeat('-', $width).PHP_EOL.PHP_EOL;

        if ($toScreen === true
            && PHP_CODESNIFFER_INTERACTIVE === false
            && class_exists('PHP_Timer', false) === true
        ) {
            echo PHP_Timer::resourceUsage().PHP_EOL.PHP_EOL;
        }

    }//end generate()


}//end class

?>
<?php
/**
 * Mercurial report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Ben Selby <benmatselby@gmail.com>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Mercurial report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Ben Selby <benmatselby@gmail.com>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_Reports_Hgblame extends PHP_CodeSniffer_Reports_VersionControl
{

    /**
     * The name of the report we want in the output
     *
     * @var string
     */
    protected $reportName = 'MERCURIAL';


    /**
     * Extract the author from a blame line.
     *
     * @param string $line Line to parse.
     *
     * @return mixed string or false if impossible to recover.
     */
    protected function getAuthor($line)
    {
        $blameParts = array();
        $line       = preg_replace('|\s+|', ' ', $line);

        preg_match(
            '|(.+[0-9]{2}:[0-9]{2}:[0-9]{2}\s[0-9]{4}\s.[0-9]{4}:)|',
            $line,
            $blameParts
        );

        if (isset($blameParts[0]) === false) {
            return false;
        }

        $parts = explode(' ', $blameParts[0]);

        if (count($parts) < 6) {
            return false;
        }

        $parts = array_slice($parts, 0, (count($parts) - 6));

        return trim(preg_replace('|<.+>|', '', implode($parts, ' ')));

    }//end getAuthor()


    /**
     * Gets the blame output.
     *
     * @param string $filename File to blame.
     *
     * @return array
     */
    protected function getBlameContent($filename)
    {
        $cwd = getcwd();

        if (PHP_CODESNIFFER_VERBOSITY > 0) {
            echo 'Getting MERCURIAL blame info for '.basename($filename).'... ';
        }

        $fileParts = explode(DIRECTORY_SEPARATOR, $filename);
        $found     = false;
        $location  = '';
        while (empty($fileParts) === false) {
            array_pop($fileParts);
            $location = implode($fileParts, DIRECTORY_SEPARATOR);
            if (is_dir($location.DIRECTORY_SEPARATOR.'.hg') === true) {
                $found = true;
                break;
            }
        }

        if ($found === true) {
            chdir($location);
        } else {
            echo 'ERROR: Could not locate .hg directory '.PHP_EOL.PHP_EOL;
            exit(2);
        }

        $command = 'hg blame -u -d -v "'.$filename.'"';
        $handle  = popen($command, 'r');
        if ($handle === false) {
            echo 'ERROR: Could not execute "'.$command.'"'.PHP_EOL.PHP_EOL;
            exit(2);
        }

        $rawContent = stream_get_contents($handle);
        fclose($handle);

        if (PHP_CODESNIFFER_VERBOSITY > 0) {
            echo 'DONE'.PHP_EOL;
        }

        $blames = explode("\n", $rawContent);
        chdir($cwd);

        return $blames;

    }//end getBlameContent()


}//end class

?>
<?php
/**
 * Version control report base class for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Ben Selby <benmatselby@gmail.com>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Version control report base class for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Ben Selby <benmatselby@gmail.com>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: 1.2.2
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
abstract class PHP_CodeSniffer_Reports_VersionControl implements PHP_CodeSniffer_Report
{

    /**
     * The name of the report we want in the output.
     *
     * @var string
     */
    protected $reportName = 'VERSION CONTROL';

    /**
     * A cache of author stats collected during the run.
     *
     * @var array
     */
    private $_authorCache = array();

    /**
     * A cache of blame stats collected during the run.
     *
     * @var array
     */
    private $_praiseCache = array();

    /**
     * A cache of source stats collected during the run.
     *
     * @var array
     */
    private $_sourceCache = array();


    /**
     * Generate a partial report for a single processed file.
     *
     * Function should return TRUE if it printed or stored data about the file
     * and FALSE if it ignored the file. Returning TRUE indicates that the file and
     * its data should be counted in the grand totals.
     *
     * @param array   $report      Prepared report data.
     * @param boolean $showSources Show sources?
     * @param int     $width       Maximum allowed line width.
     *
     * @return boolean
     */
    public function generateFileReport(
        $report,
        $showSources=false,
        $width=80
    ) {
        $blames = $this->getBlameContent($report['filename']);

        foreach ($report['messages'] as $line => $lineErrors) {
            $author = 'Unknown';
            if (isset($blames[($line - 1)]) === true) {
                $blameAuthor = $this->getAuthor($blames[($line - 1)]);
                if ($blameAuthor !== false) {
                    $author = $blameAuthor;
                }
            }

            if (isset($this->_authorCache[$author]) === false) {
                $this->_authorCache[$author] = 0;
                $this->_praiseCache[$author] = array(
                                                'good' => 0,
                                                'bad'  => 0,
                                               );
            }

            $this->_praiseCache[$author]['bad']++;

            foreach ($lineErrors as $column => $colErrors) {
                foreach ($colErrors as $error) {
                    $this->_authorCache[$author]++;

                    if ($showSources === true) {
                        $source = $error['source'];
                        if (isset($this->_sourceCache[$author][$source]) === false) {
                            $this->_sourceCache[$author][$source] = 1;
                        } else {
                            $this->_sourceCache[$author][$source]++;
                        }
                    }
                }
            }

            unset($blames[($line - 1)]);
        }//end foreach

        // No go through and give the authors some credit for
        // all the lines that do not have errors.
        foreach ($blames as $line) {
            $author = $this->getAuthor($line);
            if ($author === false) {
                $author = 'Unknown';
            }

            if (isset($this->_authorCache[$author]) === false) {
                // This author doesn't have any errors.
                if (PHP_CODESNIFFER_VERBOSITY === 0) {
                    continue;
                }

                $this->_authorCache[$author] = 0;
                $this->_praiseCache[$author] = array(
                                                'good' => 0,
                                                'bad'  => 0,
                                               );
            }

            $this->_praiseCache[$author]['good']++;
        }//end foreach

        return true;

    }//end generateFileReport()


    /**
     * Prints the author of all errors and warnings, as given by "version control blame".
     *
     * @param string  $cachedData    Any partial report data that was returned from
     *                               generateFileReport during the run.
     * @param int     $totalFiles    Total number of files processed during the run.
     * @param int     $totalErrors   Total number of errors found during the run.
     * @param int     $totalWarnings Total number of warnings found during the run.
     * @param boolean $showSources   Show sources?
     * @param int     $width         Maximum allowed line width.
     * @param boolean $toScreen      Is the report being printed to screen?
     *
     * @return void
     */
    public function generate(
        $cachedData,
        $totalFiles,
        $totalErrors,
        $totalWarnings,
        $showSources=false,
        $width=80,
        $toScreen=true
    ) {
        $errorsShown = ($totalErrors + $totalWarnings);
        if ($errorsShown === 0) {
            // Nothing to show.
            return;
        }

        $width = max($width, 70);
        arsort($this->_authorCache);

        echo PHP_EOL.'PHP CODE SNIFFER '.$this->reportName.' BLAME SUMMARY'.PHP_EOL;
        echo str_repeat('-', $width).PHP_EOL;
        if ($showSources === true) {
            echo 'AUTHOR   SOURCE'.str_repeat(' ', ($width - 43)).'(Author %) (Overall %) COUNT'.PHP_EOL;
            echo str_repeat('-', $width).PHP_EOL;
        } else {
            echo 'AUTHOR'.str_repeat(' ', ($width - 34)).'(Author %) (Overall %) COUNT'.PHP_EOL;
            echo str_repeat('-', $width).PHP_EOL;
        }

        foreach ($this->_authorCache as $author => $count) {
            if ($this->_praiseCache[$author]['good'] === 0) {
                $percent = 0;
            } else {
                $total   = ($this->_praiseCache[$author]['bad'] + $this->_praiseCache[$author]['good']);
                $percent = round(($this->_praiseCache[$author]['bad'] / $total * 100), 2);
            }

            $overallPercent = '('.round((($count / $errorsShown) * 100), 2).')';
            $authorPercent  = '('.$percent.')';
            $line = str_repeat(' ', (6 - strlen($count))).$count;
            $line = str_repeat(' ', (12 - strlen($overallPercent))).$overallPercent.$line;
            $line = str_repeat(' ', (11 - strlen($authorPercent))).$authorPercent.$line;
            $line = $author.str_repeat(' ', ($width - strlen($author) - strlen($line))).$line;

            echo $line.PHP_EOL;

            if ($showSources === true && isset($this->_sourceCache[$author]) === true) {
                $errors = $this->_sourceCache[$author];
                asort($errors);
                $errors = array_reverse($errors);

                foreach ($errors as $source => $count) {
                    if ($source === 'count') {
                        continue;
                    }

                    $line = str_repeat(' ', (5 - strlen($count))).$count;
                    echo '         '.$source.str_repeat(' ', ($width - 14 - strlen($source))).$line.PHP_EOL;
                }
            }
        }//end foreach

        echo str_repeat('-', $width).PHP_EOL;
        echo 'A TOTAL OF '.$errorsShown.' SNIFF VIOLATION(S) ';
        echo 'WERE COMMITTED BY '.count($this->_authorCache).' AUTHOR(S)'.PHP_EOL;
        echo str_repeat('-', $width).PHP_EOL.PHP_EOL;

        if ($toScreen === true
            && PHP_CODESNIFFER_INTERACTIVE === false
            && class_exists('PHP_Timer', false) === true
        ) {
            echo PHP_Timer::resourceUsage().PHP_EOL.PHP_EOL;
        }

    }//end generate()


    /**
     * Extract the author from a blame line.
     *
     * @param string $line Line to parse.
     *
     * @return mixed string or false if impossible to recover.
     */
    abstract protected function getAuthor($line);


    /**
     * Gets the blame output.
     *
     * @param string $filename File to blame.
     *
     * @return array
     */
    abstract protected function getBlameContent($filename);


}//end class

?>
<?php
/**
 * Emacs report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Gabriele Santini <gsantini@sqli.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Emacs report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Gabriele Santini <gsantini@sqli.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_Reports_Emacs implements PHP_CodeSniffer_Report
{


    /**
     * Generate a partial report for a single processed file.
     *
     * Function should return TRUE if it printed or stored data about the file
     * and FALSE if it ignored the file. Returning TRUE indicates that the file and
     * its data should be counted in the grand totals.
     *
     * @param array   $report      Prepared report data.
     * @param boolean $showSources Show sources?
     * @param int     $width       Maximum allowed line width.
     *
     * @return boolean
     */
    public function generateFileReport(
        $report,
        $showSources=false,
        $width=80
    ) {
        if ($report['errors'] === 0 && $report['warnings'] === 0) {
            // Nothing to print.
            return false;
        }

        foreach ($report['messages'] as $line => $lineErrors) {
            foreach ($lineErrors as $column => $colErrors) {
                foreach ($colErrors as $error) {
                    $message = $error['message'];
                    if ($showSources === true) {
                        $message .= ' ('.$error['source'].')';
                    }

                    $type = strtolower($error['type']);
                    echo $report['filename'].':'.$line.':'.$column.': '.$type.' - '.$message.PHP_EOL;
                }
            }
        }

        return true;

    }//end generateFileReport()


    /**
     * Generates an emacs report.
     *
     * @param string  $cachedData    Any partial report data that was returned from
     *                               generateFileReport during the run.
     * @param int     $totalFiles    Total number of files processed during the run.
     * @param int     $totalErrors   Total number of errors found during the run.
     * @param int     $totalWarnings Total number of warnings found during the run.
     * @param boolean $showSources   Show sources?
     * @param int     $width         Maximum allowed line width.
     * @param boolean $toScreen      Is the report being printed to screen?
     *
     * @return void
     */
    public function generate(
        $cachedData,
        $totalFiles,
        $totalErrors,
        $totalWarnings,
        $showSources=false,
        $width=80,
        $toScreen=true
    ) {
        echo $cachedData;

    }//end generate()


}//end class

?>
<?php
/**
 * Gitblame report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Ben Selby <benmatselby@gmail.com>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Gitblame report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Ben Selby <benmatselby@gmail.com>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: 1.2.2
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_Reports_Gitblame extends PHP_CodeSniffer_Reports_VersionControl
{

    /**
     * The name of the report we want in the output
     *
     * @var string
     */
    protected $reportName = 'GIT';


    /**
     * Extract the author from a blame line.
     *
     * @param string $line Line to parse.
     *
     * @return mixed string or false if impossible to recover.
     */
    protected function getAuthor($line)
    {
        $blameParts = array();
        $line       = preg_replace('|\s+|', ' ', $line);
        preg_match(
            '|\(.+[0-9]{4}-[0-9]{2}-[0-9]{2}\s+[0-9]+\)|',
            $line,
            $blameParts
        );

        if (isset($blameParts[0]) === false) {
            return false;
        }

        $parts = explode(' ', $blameParts[0]);

        if (count($parts) < 2) {
            return false;
        }

        $parts = array_slice($parts, 0, (count($parts) - 2));

        return preg_replace('|\(|', '', implode($parts, ' '));

    }//end getAuthor()


    /**
     * Gets the blame output.
     *
     * @param string $filename File to blame.
     *
     * @return array
     */
    protected function getBlameContent($filename)
    {
        $cwd = getcwd();

        if (PHP_CODESNIFFER_VERBOSITY > 0) {
            echo 'Getting GIT blame info for '.basename($filename).'... ';
        }

        $fileParts = explode(DIRECTORY_SEPARATOR, $filename);
        $found     = false;
        $location  = '';
        while (empty($fileParts) === false) {
            array_pop($fileParts);
            $location = implode($fileParts, DIRECTORY_SEPARATOR);
            if (is_dir($location.DIRECTORY_SEPARATOR.'.git') === true) {
                $found = true;
                break;
            }
        }

        if ($found === true) {
            chdir($location);
        } else {
            echo 'ERROR: Could not locate .git directory '.PHP_EOL.PHP_EOL;
            exit(2);
        }

        $command = 'git blame --date=short "'.$filename.'"';
        $handle  = popen($command, 'r');
        if ($handle === false) {
            echo 'ERROR: Could not execute "'.$command.'"'.PHP_EOL.PHP_EOL;
            exit(2);
        }

        $rawContent = stream_get_contents($handle);
        fclose($handle);

        if (PHP_CODESNIFFER_VERBOSITY > 0) {
            echo 'DONE'.PHP_EOL;
        }

        $blames = explode("\n", $rawContent);
        chdir($cwd);

        return $blames;

    }//end getBlameContent()


}//end class

?>
<?php
/**
 * Checkstyle report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Gabriele Santini <gsantini@sqli.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Checkstyle report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Gabriele Santini <gsantini@sqli.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_Reports_Checkstyle implements PHP_CodeSniffer_Report
{


    /**
     * Generate a partial report for a single processed file.
     *
     * Function should return TRUE if it printed or stored data about the file
     * and FALSE if it ignored the file. Returning TRUE indicates that the file and
     * its data should be counted in the grand totals.
     *
     * @param array   $report      Prepared report data.
     * @param boolean $showSources Show sources?
     * @param int     $width       Maximum allowed line width.
     *
     * @return boolean
     */
    public function generateFileReport(
        $report,
        $showSources=false,
        $width=80
    ) {
        $out = new XMLWriter;
        $out->openMemory();
        $out->setIndent(true);

        if ($report['errors'] === 0 && $report['warnings'] === 0) {
            // Nothing to print.
            return false;
        }

        $out->startElement('file');
        $out->writeAttribute('name', $report['filename']);

        foreach ($report['messages'] as $line => $lineErrors) {
            foreach ($lineErrors as $column => $colErrors) {
                foreach ($colErrors as $error) {
                    $error['type'] = strtolower($error['type']);
                    if (PHP_CODESNIFFER_ENCODING !== 'utf-8') {
                        $error['message'] = iconv(PHP_CODESNIFFER_ENCODING, 'utf-8', $error['message']);
                    }

                    $out->startElement('error');
                    $out->writeAttribute('line', $line);
                    $out->writeAttribute('column', $column);
                    $out->writeAttribute('severity', $error['type']);
                    $out->writeAttribute('message', $error['message']);
                    $out->writeAttribute('source', $error['source']);
                    $out->endElement();
                }
            }
        }//end foreach

        $out->endElement();
        echo $out->flush();

        return true;

    }//end generateFileReport()


    /**
     * Prints all violations for processed files, in a Checkstyle format.
     *
     * @param string  $cachedData    Any partial report data that was returned from
     *                               generateFileReport during the run.
     * @param int     $totalFiles    Total number of files processed during the run.
     * @param int     $totalErrors   Total number of errors found during the run.
     * @param int     $totalWarnings Total number of warnings found during the run.
     * @param boolean $showSources   Show sources?
     * @param int     $width         Maximum allowed line width.
     * @param boolean $toScreen      Is the report being printed to screen?
     *
     * @return void
     */
    public function generate(
        $cachedData,
        $totalFiles,
        $totalErrors,
        $totalWarnings,
        $showSources=false,
        $width=80,
        $toScreen=true
    ) {
        echo '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
        echo '<checkstyle version="'.PHP_CodeSniffer::VERSION.'">'.PHP_EOL;
        echo $cachedData;
        echo '</checkstyle>'.PHP_EOL;

    }//end generate()


}//end class

?>
<?php
/**
 * JUnit report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Oleg Lobach <oleg@lobach.info>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * JUnit report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Oleg Lobach <oleg@lobach.info>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_Reports_Junit implements PHP_CodeSniffer_Report
{

    /**
     * A count of tests that have been performed.
     *
     * @var int
     */
    private $_tests = 0;


    /**
     * Generate a partial report for a single processed file.
     *
     * Function should return TRUE if it printed or stored data about the file
     * and FALSE if it ignored the file. Returning TRUE indicates that the file and
     * its data should be counted in the grand totals.
     *
     * @param array   $report      Prepared report data.
     * @param boolean $showSources Show sources?
     * @param int     $width       Maximum allowed line width.
     *
     * @return boolean
     */
    public function generateFileReport(
        $report,
        $showSources=false,
        $width=80
    ) {
        if (count($report['messages']) === 0) {
            $this->_tests++;
        } else {
            $this->_tests += ($report['errors'] + $report['warnings']);
        }

        $out = new XMLWriter;
        $out->openMemory();
        $out->setIndent(true);

        $out->startElement('testsuite');
        $out->writeAttribute('name', $report['filename']);

        if (count($report['messages']) === 0) {
            $out->writeAttribute('tests', 1);
            $out->writeAttribute('failures', 0);

            $out->startElement('testcase');
            $out->writeAttribute('name', $report['filename']);
            $out->endElement();
        } else {
            $failures = ($report['errors'] + $report['warnings']);
            $out->writeAttribute('tests', $failures);
            $out->writeAttribute('failures', $failures);

            foreach ($report['messages'] as $line => $lineErrors) {
                foreach ($lineErrors as $column => $colErrors) {
                    foreach ($colErrors as $error) {
                        $out->startElement('testcase');
                        $out->writeAttribute('name', $error['source'].' at '.$report['filename']." ($line:$column)");

                        $error['type'] = strtolower($error['type']);
                        if (PHP_CODESNIFFER_ENCODING !== 'utf-8') {
                            $error['message'] = iconv(PHP_CODESNIFFER_ENCODING, 'utf-8', $error['message']);
                        }

                        $out->startElement('failure');
                        $out->writeAttribute('type', $error['type']);
                        $out->writeAttribute('message', $error['message']);
                        $out->endElement();

                        $out->endElement();
                    }
                }
            }
        }//end if

        $out->endElement();
        echo $out->flush();
        return true;

    }//end generateFileReport()


    /**
     * Prints all violations for processed files, in a proprietary XML format.
     *
     * @param string  $cachedData    Any partial report data that was returned from
     *                               generateFileReport during the run.
     * @param int     $totalFiles    Total number of files processed during the run.
     * @param int     $totalErrors   Total number of errors found during the run.
     * @param int     $totalWarnings Total number of warnings found during the run.
     * @param boolean $showSources   Show sources?
     * @param int     $width         Maximum allowed line width.
     * @param boolean $toScreen      Is the report being printed to screen?
     *
     * @return void
     */
    public function generate(
        $cachedData,
        $totalFiles,
        $totalErrors,
        $totalWarnings,
        $showSources=false,
        $width=80,
        $toScreen=true
    ) {
        $failures = ($totalErrors + $totalWarnings);
        echo '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
        echo '<testsuites name="PHP_CodeSniffer '.PHP_CodeSniffer::VERSION.'" tests="'.$this->_tests.'" failures="'.$failures.'">'.PHP_EOL;
        echo $cachedData;
        echo '</testsuites>'.PHP_EOL;

    }//end generate()


}//end class

?>
<?php
/**
 * Json report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Jeffrey Fisher <jeffslofish@gmail.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Json report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Jeffrey Fisher <jeffslofish@gmail.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_Reports_Json implements PHP_CodeSniffer_Report
{


    /**
     * Generate a partial report for a single processed file.
     *
     * Function should return TRUE if it printed or stored data about the file
     * and FALSE if it ignored the file. Returning TRUE indicates that the file and
     * its data should be counted in the grand totals.
     *
     * @param array   $report      Prepared report data.
     * @param boolean $showSources Show sources?
     * @param int     $width       Maximum allowed line width.
     *
     * @return boolean
     */
    public function generateFileReport(
        $report,
        $showSources=false,
        $width=80
    ) {

        $filename = str_replace('"', '\"', $report['filename']);
        $filename = str_replace('/', '\/', $report['filename']);
        echo "\"$filename\":{";
        echo '"errors":'.$report['errors'].',"warnings":'.$report['warnings'].',"messages":[';

        $messages = '';
        foreach ($report['messages'] as $line => $lineErrors) {
            foreach ($lineErrors as $column => $colErrors) {
                foreach ($colErrors as $error) {
                    $error['message'] = str_replace('"', '\"', $error['message']);
                    $error['message'] = str_replace('/', '\/', $error['message']);

                    $messages .= '{"message":"'.$error['message'].'",';
                    $messages .= '"source":"'.$error['source'].'",';
                    $messages .= '"severity":'.$error['severity'].',';
                    $messages .= '"type":"'.$error['type'].'",';
                    $messages .= '"line":'.$line.',"column":'.$column.'},';
                }
            }
        }

        echo rtrim($messages, ',');
        echo ']},';

        return true;

    }//end generateFileReport()


    /**
     * Generates a JSON report.
     *
     * @param string  $cachedData    Any partial report data that was returned from
     *                               generateFileReport during the run.
     * @param int     $totalFiles    Total number of files processed during the run.
     * @param int     $totalErrors   Total number of errors found during the run.
     * @param int     $totalWarnings Total number of warnings found during the run.
     * @param boolean $showSources   Show sources?
     * @param int     $width         Maximum allowed line width.
     * @param boolean $toScreen      Is the report being printed to screen?
     *
     * @return void
     */
    public function generate(
        $cachedData,
        $totalFiles,
        $totalErrors,
        $totalWarnings,
        $showSources=false,
        $width=80,
        $toScreen=true
    ) {
        echo '{"totals":{"errors":'.$totalErrors.',"warnings":'.$totalWarnings.'},"files":{';
        echo rtrim($cachedData, ',');
        echo "}}";

    }//end generate()


}//end class

?>
<?php
/**
 * Source report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Gabriele Santini <gsantini@sqli.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Source report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Gabriele Santini <gsantini@sqli.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_Reports_Source implements PHP_CodeSniffer_Report
{

    /**
     * A cache of source stats collected during the run.
     *
     * @var array
     */
    private $_sourceCache = array();


    /**
     * Generate a partial report for a single processed file.
     *
     * Function should return TRUE if it printed or stored data about the file
     * and FALSE if it ignored the file. Returning TRUE indicates that the file and
     * its data should be counted in the grand totals.
     *
     * @param array   $report      Prepared report data.
     * @param boolean $showSources Show sources?
     * @param int     $width       Maximum allowed line width.
     *
     * @return boolean
     */
    public function generateFileReport(
        $report,
        $showSources=false,
        $width=80
    ) {
        if ($report['errors'] === 0 && $report['warnings'] === 0) {
            // Nothing to print.
            return false;
        }

        foreach ($report['messages'] as $line => $lineErrors) {
            foreach ($lineErrors as $column => $colErrors) {
                foreach ($colErrors as $error) {
                    $source = $error['source'];
                    if (isset($this->_sourceCache[$source]) === false) {
                        $this->_sourceCache[$source] = 1;
                    } else {
                        $this->_sourceCache[$source]++;
                    }
                }
            }
        }

        return true;

    }//end generateFileReport()


    /**
     * Prints the source of all errors and warnings.
     *
     * @param string  $cachedData    Any partial report data that was returned from
     *                               generateFileReport during the run.
     * @param int     $totalFiles    Total number of files processed during the run.
     * @param int     $totalErrors   Total number of errors found during the run.
     * @param int     $totalWarnings Total number of warnings found during the run.
     * @param boolean $showSources   Show sources?
     * @param int     $width         Maximum allowed line width.
     * @param boolean $toScreen      Is the report being printed to screen?
     *
     * @return void
     */
    public function generate(
        $cachedData,
        $totalFiles,
        $totalErrors,
        $totalWarnings,
        $showSources=false,
        $width=80,
        $toScreen=true
    ) {
        $width = max($width, 70);

        if (empty($this->_sourceCache) === true) {
            // Nothing to show.
            return;
        }

        asort($this->_sourceCache);
        $this->_sourceCache = array_reverse($this->_sourceCache);

        echo PHP_EOL.'PHP CODE SNIFFER VIOLATION SOURCE SUMMARY'.PHP_EOL;
        echo str_repeat('-', $width).PHP_EOL;
        if ($showSources === true) {
            echo 'SOURCE'.str_repeat(' ', ($width - 11)).'COUNT'.PHP_EOL;
            echo str_repeat('-', $width).PHP_EOL;
        } else {
            echo 'STANDARD  CATEGORY            SNIFF'.str_repeat(' ', ($width - 40)).'COUNT'.PHP_EOL;
            echo str_repeat('-', $width).PHP_EOL;
        }

        foreach ($this->_sourceCache as $source => $count) {
            if ($showSources === true) {
                echo $source.str_repeat(' ', ($width - 5 - strlen($source)));
            } else {
                $parts = explode('.', $source);

                if (strlen($parts[0]) > 8) {
                    $parts[0] = substr($parts[0], 0, ((strlen($parts[0]) - 8) * -1));
                }

                echo $parts[0].str_repeat(' ', (10 - strlen($parts[0])));

                $category = $this->makeFriendlyName($parts[1]);
                if (strlen($category) > 18) {
                    $category = substr($category, 0, ((strlen($category) - 18) * -1));
                }

                echo $category.str_repeat(' ', (20 - strlen($category)));

                $sniff = $this->makeFriendlyName($parts[2]);
                if (isset($parts[3]) === true) {
                    $name    = $this->makeFriendlyName($parts[3]);
                    $name[0] = strtolower($name[0]);
                    $sniff  .= ' '.$name;
                }

                if (strlen($sniff) > ($width - 37)) {
                    $sniff = substr($sniff, 0, ($width - 37 - strlen($sniff)));
                }

                echo $sniff.str_repeat(' ', ($width - 35 - strlen($sniff)));
            }//end if

            echo $count.PHP_EOL;
        }//end foreach

        echo str_repeat('-', $width).PHP_EOL;
        echo 'A TOTAL OF '.($totalErrors + $totalWarnings).' SNIFF VIOLATION(S) ';
        echo 'WERE FOUND IN '.count($this->_sourceCache).' SOURCE(S)'.PHP_EOL;
        echo str_repeat('-', $width).PHP_EOL.PHP_EOL;

        if ($toScreen === true
            && PHP_CODESNIFFER_INTERACTIVE === false
            && class_exists('PHP_Timer', false) === true
        ) {
            echo PHP_Timer::resourceUsage().PHP_EOL.PHP_EOL;
        }

    }//end generate()


    /**
     * Converts a camel caps name into a readable string.
     *
     * @param string $name The camel caps name to convert.
     *
     * @return string
     */
    public function makeFriendlyName($name)
    {
        $friendlyName = '';
        $length       = strlen($name);

        $lastWasUpper   = false;
        $lastWasNumeric = false;
        for ($i = 0; $i < $length; $i++) {
            if (is_numeric($name[$i]) === true) {
                if ($lastWasNumeric === false) {
                    $friendlyName .= ' ';
                }

                $lastWasUpper   = false;
                $lastWasNumeric = true;
            } else {
                $lastWasNumeric = false;

                $char = strtolower($name[$i]);
                if ($char === $name[$i]) {
                    // Lowercase.
                    $lastWasUpper = false;
                } else {
                    // Uppercase.
                    if ($lastWasUpper === false) {
                        $friendlyName .= ' ';
                        $next = $name[($i + 1)];
                        if (strtolower($next) === $next) {
                            // Next char is lowercase so it is a word boundary.
                            $name[$i] = strtolower($name[$i]);
                        }
                    }

                    $lastWasUpper = true;
                }
            }//end if

            $friendlyName .= $name[$i];
        }//end for

        $friendlyName    = trim($friendlyName);
        $friendlyName[0] = strtoupper($friendlyName[0]);

        return $friendlyName;

    }//end makeFriendlyName()


}//end class

?>
<?php
/**
 * Svnblame report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Gabriele Santini <gsantini@sqli.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Svnblame report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Gabriele Santini <gsantini@sqli.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_Reports_Svnblame extends PHP_CodeSniffer_Reports_VersionControl
{

    /**
     * The name of the report we want in the output
     *
     * @var string
     */
    protected $reportName = 'SVN';


    /**
     * Extract the author from a blame line.
     *
     * @param string $line Line to parse.
     *
     * @return mixed string or false if impossible to recover.
     */
    protected function getAuthor($line)
    {
        $blameParts = array();
        preg_match('|\s*([^\s]+)\s+([^\s]+)|', $line, $blameParts);

        if (isset($blameParts[2]) === false) {
            return false;
        }

        return $blameParts[2];

    }//end getAuthor()


    /**
     * Gets the blame output.
     *
     * @param string $filename File to blame.
     *
     * @return array
     */
    protected function getBlameContent($filename)
    {
        if (PHP_CODESNIFFER_VERBOSITY > 0) {
            echo 'Getting SVN blame info for '.basename($filename).'... ';
        }

        $command = 'svn blame "'.$filename.'"';
        $handle  = popen($command, 'r');
        if ($handle === false) {
            echo 'ERROR: Could not execute "'.$command.'"'.PHP_EOL.PHP_EOL;
            exit(2);
        }

        $rawContent = stream_get_contents($handle);
        fclose($handle);

        if (PHP_CODESNIFFER_VERBOSITY > 0) {
            echo 'DONE'.PHP_EOL;
        }

        $blames = explode("\n", $rawContent);

        return $blames;

    }//end getBlameContent()


}//end class

?>
<?php
/**
 * Xml report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Gabriele Santini <gsantini@sqli.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Xml report for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Gabriele Santini <gsantini@sqli.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_Reports_Xml implements PHP_CodeSniffer_Report
{


    /**
     * Generate a partial report for a single processed file.
     *
     * Function should return TRUE if it printed or stored data about the file
     * and FALSE if it ignored the file. Returning TRUE indicates that the file and
     * its data should be counted in the grand totals.
     *
     * @param array   $report      Prepared report data.
     * @param boolean $showSources Show sources?
     * @param int     $width       Maximum allowed line width.
     *
     * @return boolean
     */
    public function generateFileReport(
        $report,
        $showSources=false,
        $width=80
    ) {
        $out = new XMLWriter;
        $out->openMemory();
        $out->setIndent(true);

        if ($report['errors'] === 0 && $report['warnings'] === 0) {
            // Nothing to print.
            return false;
        }

        $out->startElement('file');
        $out->writeAttribute('name', $report['filename']);
        $out->writeAttribute('errors', $report['errors']);
        $out->writeAttribute('warnings', $report['warnings']);

        foreach ($report['messages'] as $line => $lineErrors) {
            foreach ($lineErrors as $column => $colErrors) {
                foreach ($colErrors as $error) {
                    $error['type'] = strtolower($error['type']);
                    if (PHP_CODESNIFFER_ENCODING !== 'utf-8') {
                        $error['message'] = iconv(PHP_CODESNIFFER_ENCODING, 'utf-8', $error['message']);
                    }

                    $out->startElement($error['type']);
                    $out->writeAttribute('line', $line);
                    $out->writeAttribute('column', $column);
                    $out->writeAttribute('source', $error['source']);
                    $out->writeAttribute('severity', $error['severity']);
                    $out->text($error['message']);
                    $out->endElement();
                }
            }
        }//end foreach

        $out->endElement();
        echo $out->flush();

        return true;

    }//end generateFileReport()


    /**
     * Prints all violations for processed files, in a proprietary XML format.
     *
     * @param string  $cachedData    Any partial report data that was returned from
     *                               generateFileReport during the run.
     * @param int     $totalFiles    Total number of files processed during the run.
     * @param int     $totalErrors   Total number of errors found during the run.
     * @param int     $totalWarnings Total number of warnings found during the run.
     * @param boolean $showSources   Show sources?
     * @param int     $width         Maximum allowed line width.
     * @param boolean $toScreen      Is the report being printed to screen?
     *
     * @return void
     */
    public function generate(
        $cachedData,
        $totalFiles,
        $totalErrors,
        $totalWarnings,
        $showSources=false,
        $width=80,
        $toScreen=true
    ) {
        echo '<?xml version="1.0" encoding="UTF-8"?>'.PHP_EOL;
        echo '<phpcs version="'.PHP_CodeSniffer::VERSION.'">'.PHP_EOL;
        echo $cachedData;
        echo '</phpcs>'.PHP_EOL;

    }//end generate()


}//end class

?>
<?php
/**
 * A class to manage reporting.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Gabriele Santini <gsantini@sqli.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (is_file(dirname(__FILE__).'/../CodeSniffer.php') === true) {
    include_once dirname(__FILE__).'/../CodeSniffer.php';
} else {
    include_once 'PHP/CodeSniffer.php';
}

/**
 * A class to manage reporting.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Gabriele Santini <gsantini@sqli.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2009 SQLI <www.sqli.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_Reporting
{

    /**
     * Total number of files that contain errors or warnings.
     *
     * @var int
     */
    public $totalFiles = 0;

    /**
     * Total number of errors found during the run.
     *
     * @var int
     */
    public $totalErrors = 0;

    /**
     * Total number of warnings found during the run.
     *
     * @var int
     */
    public $totalWarnings = 0;

    /**
     * A list of reports that have written partial report output.
     *
     * @var array
     */
    private $_cachedReports = array();

    /**
     * A cache of report objects.
     *
     * @var array
     */
    private $_reports = array();


    /**
     * Produce the appropriate report object based on $type parameter.
     *
     * @param string $type The type of the report.
     *
     * @return PHP_CodeSniffer_Report
     * @throws PHP_CodeSniffer_Exception If report is not available.
     */
    public function factory($type)
    {
        $type = ucfirst($type);
        if (isset($this->_reports[$type]) === true) {
            return $this->_reports[$type];
        }

        $filename        = $type.'.php';
        $reportClassName = 'PHP_CodeSniffer_Reports_'.$type;
        if (class_exists($reportClassName, true) === false) {
            throw new PHP_CodeSniffer_Exception('Report type "'.$type.'" not found.');
        }

        $reportClass = new $reportClassName();
        if (false === ($reportClass instanceof PHP_CodeSniffer_Report)) {
            throw new PHP_CodeSniffer_Exception('Class "'.$reportClassName.'" must implement the "PHP_CodeSniffer_Report" interface.');
        }

        $this->_reports[$type] = $reportClass;
        return $this->_reports[$type];

    }//end factory()


    /**
     * Actually generates the report.
     * 
     * @param PHP_CodeSniffer_File $phpcsFile The file that has been processed.
     * @param array                $cliValues An array of command line arguments.
     * 
     * @return void
     */
    public function cacheFileReport(PHP_CodeSniffer_File $phpcsFile, array $cliValues)
    {
        if (isset($cliValues['reports']) === false) {
            // This happens during unit testing, or any time someone just wants
            // the error data and not the printed report.
            return;
        }

        $reportData  = $this->prepareFileReport($phpcsFile);
        $errorsShown = false;

        foreach ($cliValues['reports'] as $report => $output) {
            $reportClass = self::factory($report);

            ob_start();
            $result = $reportClass->generateFileReport($reportData, $cliValues['showSources'], $cliValues['reportWidth']);
            if ($result === true) {
                $errorsShown = true;
            }

            $generatedReport = ob_get_contents();
            ob_end_clean();

            if ($generatedReport !== '') {
                $flags = FILE_APPEND;
                if (in_array($report, $this->_cachedReports) === false) {
                    $this->_cachedReports[] = $report;
                    $flags = null;
                }

                if ($output === null) {
                    if ($cliValues['reportFile'] !== null) {
                        $output = $cliValues['reportFile'];
                    } else {
                        $output = sys_get_temp_dir().'/phpcs-'.$report.'.tmp';
                    }
                }

                file_put_contents($output, $generatedReport, $flags);
            }
        }//end foreach

        if ($errorsShown === true) {
            $this->totalFiles++;
            $this->totalErrors   += $reportData['errors'];
            $this->totalWarnings += $reportData['warnings'];
        }

    }//end cacheFileReport()


    /**
     * Actually generates the report.
     * 
     * @param string  $report      Report type.
     * @param boolean $showSources Show sources?
     * @param string  $reportFile  Report file to generate.
     * @param integer $reportWidth Report max width.
     * 
     * @return integer
     */
    public function printReport(
        $report,
        $showSources,
        $reportFile='',
        $reportWidth=80
    ) {
        if ($this->totalFiles === 0) {
            // No files generated errors.
            return 0;
        }

        $reportClass = self::factory($report);

        if ($reportFile !== null) {
            $filename = $reportFile;
            $toScreen = false;
            ob_start();
        } else {
            $filename = sys_get_temp_dir().'/phpcs-'.$report.'.tmp';
            $toScreen = true;
        }

        if (file_exists($filename) === true) {
            $reportCache = file_get_contents($filename);
        } else {
            $reportCache = '';
        }

        $reportClass->generate(
            $reportCache,
            $this->totalFiles,
            $this->totalErrors,
            $this->totalWarnings,
            $showSources,
            $reportWidth,
            $toScreen
        );

        if ($reportFile !== null) {
            $generatedReport = ob_get_contents();
            ob_end_clean();

            if (PHP_CODESNIFFER_VERBOSITY > 0) {
                echo $generatedReport;
            }

            $generatedReport = trim($generatedReport);
            file_put_contents($reportFile, $generatedReport.PHP_EOL);
        } else if (file_exists($filename) === true) {
            unlink($filename);
        }

        return ($this->totalErrors + $this->totalWarnings);

    }//end printReport()


    /**
     * Pre-process and package violations for all files.
     *
     * Used by error reports to get a packaged list of all errors in each file.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file that has been processed.
     *
     * @return array
     */
    public function prepareFileReport(PHP_CodeSniffer_File $phpcsFile)
    {
        $report = array(
                   'filename' => $phpcsFile->getFilename(),
                   'errors'   => $phpcsFile->getErrorCount(),
                   'warnings' => $phpcsFile->getWarningCount(),
                   'messages' => array(),
                  );

        if ($report['errors'] === 0 && $report['warnings'] === 0) {
            // Prefect score!
            return $report;
        }

        $errors = array();

        // Merge errors and warnings.
        foreach ($phpcsFile->getErrors() as $line => $lineErrors) {
            foreach ($lineErrors as $column => $colErrors) {
                $newErrors = array();
                foreach ($colErrors as $data) {
                    $newErrors[] = array(
                                    'message'  => $data['message'],
                                    'source'   => $data['source'],
                                    'severity' => $data['severity'],
                                    'type'     => 'ERROR',
                                   );
                }

                $errors[$line][$column] = $newErrors;
            }//end foreach

            ksort($errors[$line]);
        }//end foreach

        foreach ($phpcsFile->getWarnings() as $line => $lineWarnings) {
            foreach ($lineWarnings as $column => $colWarnings) {
                $newWarnings = array();
                foreach ($colWarnings as $data) {
                    $newWarnings[] = array(
                                      'message'  => $data['message'],
                                      'source'   => $data['source'],
                                      'severity' => $data['severity'],
                                      'type'     => 'WARNING',
                                     );
                }

                if (isset($errors[$line]) === false) {
                    $errors[$line] = array();
                }

                if (isset($errors[$line][$column]) === true) {
                    $errors[$line][$column] = array_merge(
                        $newWarnings,
                        $errors[$line][$column]
                    );
                } else {
                    $errors[$line][$column] = $newWarnings;
                }
            }//end foreach

            ksort($errors[$line]);
        }//end foreach

        ksort($errors);
        $report['messages'] = $errors;
        return $report;

    }//end prepareFileReport()


}//end class

?>
<?php
/**
 * A class to represent single element doc tags.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_CommentParser_AbstractDocElement', true) === false) {
    $error = 'Class PHP_CodeSniffer_CommentParser_AbstractDocElement not found';
    throw new PHP_CodeSniffer_Exception($error);
}

/**
 * A class to represent single element doc tags.
 *
 * A single element doc tag contains only one value after the tag itself. An
 * example would be the \@package tag.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_CommentParser_SingleElement extends PHP_CodeSniffer_CommentParser_AbstractDocElement
{

    /**
     * The content that exists after the tag.
     *
     * @var string
     * @see getContent()
     */
    protected $content = '';

    /**
     * The whitespace that exists before the content.
     *
     * @var string
     * @see getWhitespaceBeforeContent()
     */
    protected $contentWhitespace = '';


    /**
     * Constructs a SingleElement doc tag.
     *
     * @param PHP_CodeSniffer_CommentParser_DocElement $previousElement The element
     *                                                                  before this
     *                                                                  one.
     * @param array                                    $tokens          The tokens
     *                                                                  that comprise
     *                                                                  this element.
     * @param string                                   $tag             The tag that
     *                                                                  this element
     *                                                                  represents.
     * @param PHP_CodeSniffer_File                     $phpcsFile       The file that
     *                                                                  this element
     *                                                                  is in.
     */
    public function __construct(
        $previousElement,
        $tokens,
        $tag,
        PHP_CodeSniffer_File $phpcsFile
    ) {
        parent::__construct($previousElement, $tokens, $tag, $phpcsFile);

    }//end __construct()


    /**
     * Returns the element names that this tag is comprised of, in the order
     * that they appear in the tag.
     *
     * @return array(string)
     * @see processSubElement()
     */
    protected function getSubElements()
    {
        return array('content');

    }//end getSubElements()


    /**
     * Processes the sub element with the specified name.
     *
     * @param string $name             The name of the sub element to process.
     * @param string $content          The content of this sub element.
     * @param string $whitespaceBefore The whitespace that exists before the
     *                                 sub element.
     *
     * @return void
     * @see getSubElements()
     */
    protected function processSubElement($name, $content, $whitespaceBefore)
    {
        $this->content           = $content;
        $this->contentWhitespace = $whitespaceBefore;

    }//end processSubElement()


    /**
     * Returns the content of this tag.
     *
     * @return string
     */
    public function getContent()
    {
        return $this->content;

    }//end getContent()


    /**
     * Returns the whitespace before the content of this tag.
     *
     * @return string
     */
    public function getWhitespaceBeforeContent()
    {
        return $this->contentWhitespace;

    }//end getWhitespaceBeforeContent()


    /**
     * Processes a content check for single doc element.
     *
     * @param PHP_CodeSniffer_File $phpcsFile    The file being scanned.
     * @param int                  $commentStart The line number where
     *                                           the error occurs.
     * @param string               $docBlock     Whether this is a file or
     *                                           class comment doc.
     *
     * @return void
     */
    public function process(
        PHP_CodeSniffer_File $phpcsFile,
        $commentStart,
        $docBlock
    ) {
        if ($this->content === '') {
            $errorPos = ($commentStart + $this->getLine());
            $error    = 'Content missing for %s tag in %s comment';
            $data     = array(
                         $this->tag,
                         $docBlock,
                        );
            $phpcsFile->addError($error, $errorPos, 'EmptyTagContent', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * A class to represent Comments of a doc comment.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_CommentParser_SingleElement', true) === false) {
    $error = 'Class PHP_CodeSniffer_CommentParser_SingleElement not found';
    throw new PHP_CodeSniffer_Exception($error);
}

/**
 * A class to represent Comments of a doc comment.
 *
 * Comments are in the following format.
 * <code>
 * /** <--this is the start of the comment.
 *  * This is a short comment description
 *  *
 *  * This is a long comment description
 *  * <-- this is the end of the comment
 *  * @return something
 *  {@/}
 *  </code>
 *
 * Note that the sentence before two newlines is assumed
 * the short comment description.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_CommentParser_CommentElement extends PHP_CodeSniffer_CommentParser_SingleElement
{


    /**
     * Constructs a PHP_CodeSniffer_CommentParser_CommentElement.
     *
     * @param PHP_CodeSniffer_CommentParser_DocElement $previousElement The element
     *                                                                  that
     *                                                                  appears
     *                                                                  before this
     *                                                                  element.
     * @param array                                    $tokens          The tokens
     *                                                                  that make
     *                                                                  up this
     *                                                                  element.
     * @param PHP_CodeSniffer_File                     $phpcsFile       The file
     *                                                                  that this
     *                                                                  element is
     *                                                                  in.
     */
    public function __construct(
        $previousElement,
        $tokens,
        PHP_CodeSniffer_File $phpcsFile
    ) {
        parent::__construct($previousElement, $tokens, 'comment', $phpcsFile);

    }//end __construct()


    /**
     * Returns the short comment description.
     *
     * @return string
     * @see getLongComment()
     */
    public function getShortComment()
    {
        $pos = $this->_getShortCommentEndPos();
        if ($pos === -1) {
            return '';
        }

        return implode('', array_slice($this->tokens, 0, ($pos + 1)));

    }//end getShortComment()


    /**
     * Returns the last token position of the short comment description.
     *
     * @return int The last token position of the short comment description
     * @see _getLongCommentStartPos()
     */
    private function _getShortCommentEndPos()
    {
        $found      = false;
        $whiteSpace = array(
                       ' ',
                       "\t",
                      );

        foreach ($this->tokens as $pos => $token) {
            $token = str_replace($whiteSpace, '', $token);
            if ($token === $this->phpcsFile->eolChar) {
                if ($found === false) {
                    // Include newlines before short description.
                    continue;
                } else {
                    if (isset($this->tokens[($pos + 1)]) === true) {
                        if ($this->tokens[($pos + 1)] === $this->phpcsFile->eolChar) {
                            return ($pos - 1);
                        }
                    } else {
                        return $pos;
                    }
                }
            } else {
                $found = true;
            }
        }//end foreach

        return (count($this->tokens) - 1);

    }//end _getShortCommentEndPos()


    /**
     * Returns the long comment description.
     *
     * @return string
     * @see getShortComment
     */
    public function getLongComment()
    {
        $start = $this->_getLongCommentStartPos();
        if ($start === -1) {
            return '';
        }

        return implode('', array_slice($this->tokens, $start));

    }//end getLongComment()


    /**
     * Returns the start position of the long comment description.
     *
     * Returns -1 if there is no long comment.
     *
     * @return int The start position of the long comment description.
     * @see _getShortCommentEndPos()
     */
    private function _getLongCommentStartPos()
    {
        $pos = ($this->_getShortCommentEndPos() + 1);
        if ($pos === (count($this->tokens) - 1)) {
            return -1;
        }

        $count = count($this->tokens);
        for ($i = $pos; $i < $count; $i++) {
            $content = trim($this->tokens[$i]);
            if ($content !== '') {
                if ($content{0} === '@') {
                    return -1;
                }

                return $i;
            }
        }

        return -1;

    }//end _getLongCommentStartPos()


    /**
     * Returns the whitespace that exists between
     * the short and the long comment description.
     *
     * @return string
     */
    public function getWhiteSpaceBetween()
    {
        $endShort  = ($this->_getShortCommentEndPos() + 1);
        $startLong = ($this->_getLongCommentStartPos() - 1);
        if ($startLong === -1) {
            return '';
        }

        return implode(
            '',
            array_slice($this->tokens, $endShort, ($startLong - $endShort))
        );

    }//end getWhiteSpaceBetween()


    /**
     * Returns the number of newlines that exist before the tags.
     *
     * @return int
     */
    public function getNewlineAfter()
    {
        $long = $this->getLongComment();
        if ($long !== '') {
            $long     = rtrim($long, ' ');
            $long     = strrev($long);
            $newlines = strspn($long, $this->phpcsFile->eolChar);
        } else {
            $endShort = ($this->_getShortCommentEndPos() + 1);
            $after    = implode('', array_slice($this->tokens, $endShort));
            $after    = trim($after, ' ');
            $newlines = strspn($after, $this->phpcsFile->eolChar);
        }

        return ($newlines / strlen($this->phpcsFile->eolChar));

    }//end getNewlineAfter()


    /**
     * Returns true if there is no comment.
     *
     * @return boolean
     */
    public function isEmpty()
    {
        return (trim($this->getContent()) === '');

    }//end isEmpty()


}//end class

?>
<?php
/**
 * A DocElement represents a logical element within a Doc Comment.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * A DocElement represents a logical element within a Doc Comment.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
interface PHP_CodeSniffer_CommentParser_DocElement
{


    /**
     * Returns the name of the tag this element represents, omitting the @ symbol.
     *
     * @return string
     */
    public function getTag();


    /**
     * Returns the whitespace that exists before this element.
     *
     * @return string
     * @see getWhitespaceAfter()
     */
    public function getWhitespaceBefore();


    /**
     * Returns the whitespace that exists after this element.
     *
     * @return string
     * @see getWhitespaceBefore()
     */
    public function getWhitespaceAfter();


    /**
     * Returns the order that this element appears in the doc comment.
     *
     * The first element in the comment should have an order of 1.
     *
     * @return int
     */
    public function getOrder();


    /**
     * Returns the element that appears before this element.
     *
     * @return PHP_CodeSniffer_CommentParser_DocElement
     * @see getNextElement()
     */
    public function getPreviousElement();


    /**
     * Returns the element that appears after this element.
     *
     * @return PHP_CodeSniffer_CommentParser_DocElement
     * @see getPreviousElement()
     */
    public function getNextElement();


    /**
     * Returns the line that this element started on.
     *
     * @return int
     */
    public function getLine();


    /**
     * Returns the raw content of this element, omitting the tag.
     *
     * @return string
     */
    public function getRawContent();


}//end interface

?>
<?php
/**
 * Parses doc comments.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_CommentParser_SingleElement', true) === false) {
    $error = 'Class PHP_CodeSniffer_CommentParser_SingleElement not found';
    throw new PHP_CodeSniffer_Exception($error);
}

if (class_exists('PHP_CodeSniffer_CommentParser_CommentElement', true) === false) {
    $error = 'Class PHP_CodeSniffer_CommentParser_CommentElement not found';
    throw new PHP_CodeSniffer_Exception($error);
}

if (class_exists('PHP_CodeSniffer_CommentParser_ParserException', true) === false) {
    $error = 'Class PHP_CodeSniffer_CommentParser_ParserException not found';
    throw new PHP_CodeSniffer_Exception($error);
}

/**
 * Parses doc comments.
 *
 * This abstract parser handles the following tags:
 *
 * <ul>
 *  <li>The short description and the long description</li>
 *  <li>@see</li>
 *  <li>@link</li>
 *  <li>@deprecated</li>
 *  <li>@since</li>
 * </ul>
 *
 * Extending classes should implement the getAllowedTags() method to return the
 * tags that they wish to process, omitting the tags that this base class
 * processes. When one of these tags in encountered, the process&lt;tag_name&gt;
 * method is called on that class. For example, if a parser's getAllowedTags()
 * method returns \@param as one of its tags, the processParam method will be
 * called so that the parser can process such a tag.
 *
 * The method is passed the tokens that comprise this tag. The tokens array
 * includes the whitespace that exists between the tokens, as separate tokens.
 * It's up to the method to create a element that implements the DocElement
 * interface, which should be returned. The AbstractDocElement class is a helper
 * class that can be used to handle most of the parsing of the tokens into their
 * individual sub elements. It requires that you construct it with the element
 * previous to the element currently being processed, which can be acquired
 * with the protected $previousElement class member of this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
abstract class PHP_CodeSniffer_CommentParser_AbstractParser
{

    /**
     * The comment element that appears in the doc comment.
     *
     * @var PHP_CodeSniffer_CommentParser_CommentElement
     */
    protected $comment = null;

    /**
     * The string content of the comment.
     *
     * @var string
     */
    protected $commentString = '';

    /**
     * The file that the comment exists in.
     *
     * @var PHP_CodeSniffer_File
     */
    protected $phpcsFile = null;

    /**
     * The word tokens that appear in the comment.
     *
     * Whitespace tokens also appear in this stack, but are separate tokens
     * from words.
     *
     * @var array(string)
     */
    protected $words = array();

    /**
     * An array of all tags found in the comment.
     *
     * @var array(string)
     */
    protected $foundTags = array();

    /**
     * The previous doc element that was processed.
     *
     * null if the current element being processed is the first element in the
     * doc comment.
     *
     * @var PHP_CodeSniffer_CommentParser_DocElement
     */
    protected $previousElement = null;

    /**
     * A list of see elements that appear in this doc comment.
     *
     * @var array(PHP_CodeSniffer_CommentParser_SingleElement)
     */
    protected $sees = array();

    /**
     * A list of see elements that appear in this doc comment.
     *
     * @var array(PHP_CodeSniffer_CommentParser_SingleElement)
     */
    protected $deprecated = null;

    /**
     * A list of see elements that appear in this doc comment.
     *
     * @var array(PHP_CodeSniffer_CommentParser_SingleElement)
     */
    protected $links = array();

    /**
     * A element to represent \@since tags.
     *
     * @var PHP_CodeSniffer_CommentParser_SingleElement
     */
    protected $since = null;

    /**
     * True if the comment has been parsed.
     *
     * @var boolean
     */
    private $_hasParsed = false;

    /**
     * The tags that this class can process.
     *
     * @var array(string)
     */
    private static $_tags = array(
                             'see'        => false,
                             'link'       => false,
                             'deprecated' => true,
                             'since'      => true,
                            );

    /**
     * An array of unknown tags.
     *
     * @var array(string)
     */
    public $unknown = array();

    /**
     * The order of tags.
     *
     * @var array(string)
     */
    public $orders = array();


    /**
     * Constructs a Doc Comment Parser.
     *
     * @param string               $comment   The comment to parse.
     * @param PHP_CodeSniffer_File $phpcsFile The file that this comment is in.
     */
    public function __construct($comment, PHP_CodeSniffer_File $phpcsFile)
    {
        $this->commentString = $comment;
        $this->phpcsFile     = $phpcsFile;

    }//end __construct()


    /**
     * Initiates the parsing of the doc comment.
     *
     * @return void
     * @throws PHP_CodeSniffer_CommentParser_ParserException If the parser finds a
     *                                                       problem with the
     *                                                       comment.
     */
    public function parse()
    {
        if ($this->_hasParsed === false) {
            $this->_parse($this->commentString);
        }

    }//end parse()


    /**
     * Parse the comment.
     *
     * @param string $comment The doc comment to parse.
     *
     * @return void
     * @see _parseWords()
     */
    private function _parse($comment)
    {
        // Firstly, remove the comment tags and any stars from the left side.
        $lines = explode($this->phpcsFile->eolChar, $comment);
        foreach ($lines as &$line) {
            $line = trim($line);

            if ($line !== '') {
                if (substr($line, 0, 3) === '/**') {
                    $line = substr($line, 3);
                } else if (substr($line, -2, 2) === '*/') {
                    $line = substr($line, 0, -2);
                } else if ($line{0} === '*') {
                    $line = substr($line, 1);
                }

                // Add the words to the stack, preserving newlines. Other parsers
                // might be interested in the spaces between words, so tokenize
                // spaces as well as separate tokens.
                $flags = (PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
                $words = preg_split(
                    '|(\s+)|u',
                    $line.$this->phpcsFile->eolChar,
                    -1,
                    $flags
                );

                $this->words = array_merge($this->words, $words);
            }//end if
        }//end foreach

        $this->_parseWords();

    }//end _parse()


    /**
     * Parses each word within the doc comment.
     *
     * @return void
     * @see _parse()
     * @throws PHP_CodeSniffer_CommentParser_ParserException If more than the allowed
     *                                                       number of occurences of
     *                                                       a tag is found.
     */
    private function _parseWords()
    {
        $allowedTags     = (self::$_tags + $this->getAllowedTags());
        $allowedTagNames = array_keys($allowedTags);
        $prevTagPos      = false;
        $wordWasEmpty    = true;

        foreach ($this->words as $wordPos => $word) {
            if (trim($word) !== '') {
                $wordWasEmpty = false;
            }

            if ($word{0} === '@') {
                $tag = substr($word, 1);

                // Filter out @ tags in the comment description.
                // A real comment tag should have whitespace and a newline before it.
                if (isset($this->words[($wordPos - 1)]) === false
                    || trim($this->words[($wordPos - 1)]) !== ''
                ) {
                    continue;
                }

                if (isset($this->words[($wordPos - 2)]) === false
                    || $this->words[($wordPos - 2)] !== $this->phpcsFile->eolChar
                ) {
                    continue;
                }

                $this->foundTags[] = array(
                                      'tag'  => $tag,
                                      'line' => $this->getLine($wordPos),
                                      'pos'  => $wordPos,
                                     );

                if ($prevTagPos !== false) {
                    // There was a tag before this so let's process it.
                    $prevTag = substr($this->words[$prevTagPos], 1);
                    $this->parseTag($prevTag, $prevTagPos, ($wordPos - 1));
                } else {
                    // There must have been a comment before this tag, so
                    // let's process that.
                    $this->parseTag('comment', 0, ($wordPos - 1));
                }

                $prevTagPos = $wordPos;

                if (in_array($tag, $allowedTagNames) === false) {
                    // This is not a tag that we process, but let's check to
                    // see if it is a tag we know about. If we don't know about it,
                    // we add it to a list of unknown tags.
                    $knownTags = array(
                                  'abstract',
                                  'access',
                                  'example',
                                  'filesource',
                                  'global',
                                  'ignore',
                                  'internal',
                                  'name',
                                  'static',
                                  'staticvar',
                                  'todo',
                                  'tutorial',
                                  'uses',
                                  'package_version@',
                                 );

                    if (in_array($tag, $knownTags) === false) {
                        $this->unknown[] = array(
                                            'tag'  => $tag,
                                            'line' => $this->getLine($wordPos),
                                            'pos'  => $wordPos,
                                           );
                    }
                }//end if
            }//end if
        }//end foreach

        // Only process this tag if there was something to process.
        if ($wordWasEmpty === false) {
            if ($prevTagPos === false) {
                // There must only be a comment in this doc comment.
                $this->parseTag('comment', 0, count($this->words));
            } else {
                // Process the last tag element.
                $prevTag  = substr($this->words[$prevTagPos], 1);
                $numWords = count($this->words);
                $endPos   = $numWords;

                if ($prevTag === 'package' || $prevTag === 'subpackage') {
                    // These are single-word tags, so anything after a newline
                    // is really a comment.
                    for ($endPos = $prevTagPos; $endPos < $numWords; $endPos++) {
                        if (strpos($this->words[$endPos], $this->phpcsFile->eolChar) !== false) {
                            break;
                        }
                    }
                }

                $this->parseTag($prevTag, $prevTagPos, $endPos);

                if ($endPos !== $numWords) {
                    // Process the final comment, if it is not empty.
                    $tokens  = array_slice($this->words, ($endPos + 1), $numWords);
                    $content = implode('', $tokens);
                    if (trim($content) !== '') {
                        $this->parseTag('comment', ($endPos + 1), $numWords);
                    }
                }
            }//end if
        }//end if

    }//end _parseWords()


    /**
     * Returns the line that the token exists on in the doc comment.
     *
     * @param int $tokenPos The position in the words stack to find the line
     *                      number for.
     *
     * @return int
     */
    protected function getLine($tokenPos)
    {
        $newlines = 0;
        for ($i = 0; $i < $tokenPos; $i++) {
            $newlines += substr_count($this->phpcsFile->eolChar, $this->words[$i]);
        }

        return $newlines;

    }//end getLine()


    /**
     * Parses see tag element within the doc comment.
     *
     * @param array(string) $tokens The word tokens that comprise this element.
     *
     * @return DocElement The element that represents this see comment.
     */
    protected function parseSee($tokens)
    {
        $see = new PHP_CodeSniffer_CommentParser_SingleElement(
            $this->previousElement,
            $tokens,
            'see',
            $this->phpcsFile
        );

        $this->sees[] = $see;
        return $see;

    }//end parseSee()


    /**
     * Parses the comment element that appears at the top of the doc comment.
     *
     * @param array(string) $tokens The word tokens that comprise this element.
     *
     * @return DocElement The element that represents this comment element.
     */
    protected function parseComment($tokens)
    {
        $this->comment = new PHP_CodeSniffer_CommentParser_CommentElement(
            $this->previousElement,
            $tokens,
            $this->phpcsFile
        );

        return $this->comment;

    }//end parseComment()


    /**
     * Parses \@deprecated tags.
     *
     * @param array(string) $tokens The word tokens that comprise this element.
     *
     * @return DocElement The element that represents this deprecated tag.
     */
    protected function parseDeprecated($tokens)
    {
        $this->deprecated = new PHP_CodeSniffer_CommentParser_SingleElement(
            $this->previousElement,
            $tokens,
            'deprecated',
            $this->phpcsFile
        );

        return $this->deprecated;

    }//end parseDeprecated()


    /**
     * Parses \@since tags.
     *
     * @param array(string) $tokens The word tokens that comprise this element.
     *
     * @return SingleElement The element that represents this since tag.
     */
    protected function parseSince($tokens)
    {
        $this->since = new PHP_CodeSniffer_CommentParser_SingleElement(
            $this->previousElement,
            $tokens,
            'since',
            $this->phpcsFile
        );

        return $this->since;

    }//end parseSince()


    /**
     * Parses \@link tags.
     *
     * @param array(string) $tokens The word tokens that comprise this element.
     *
     * @return SingleElement The element that represents this link tag.
     */
    protected function parseLink($tokens)
    {
        $link = new PHP_CodeSniffer_CommentParser_SingleElement(
            $this->previousElement,
            $tokens,
            'link',
            $this->phpcsFile
        );

        $this->links[] = $link;
        return $link;

    }//end parseLink()


    /**
     * Returns the see elements that appear in this doc comment.
     *
     * @return array(SingleElement)
     */
    public function getSees()
    {
        return $this->sees;

    }//end getSees()


    /**
     * Returns the comment element that appears at the top of this doc comment.
     *
     * @return CommentElement
     */
    public function getComment()
    {
        return $this->comment;

    }//end getComment()


    /**
     * Returns the word list.
     *
     * @return array
     */
    public function getWords()
    {
        return $this->words;

    }//end getWords()


    /**
     * Returns the list of found tags.
     *
     * @return array
     */
    public function getTags()
    {
        return $this->foundTags;

    }//end getTags()


    /**
     * Returns the link elements found in this comment.
     *
     * Returns an empty array if no links are found in the comment.
     *
     * @return array(SingleElement)
     */
    public function getLinks()
    {
        return $this->links;

    }//end getLinks()


    /**
     * Returns the deprecated element found in this comment.
     *
     * Returns null if no element exists in the comment.
     *
     * @return SingleElement
     */
    public function getDeprecated()
    {
        return $this->deprecated;

    }//end getDeprecated()


    /**
     * Returns the since element found in this comment.
     *
     * Returns null if no element exists in the comment.
     *
     * @return SingleElement
     */
    public function getSince()
    {
        return $this->since;

    }//end getSince()


    /**
     * Parses the specified tag.
     *
     * @param string $tag   The tag name to parse (omitting the @ symbol from
     *                      the tag)
     * @param int    $start The position in the word tokens where this element
     *                      started.
     * @param int    $end   The position in the word tokens where this element
     *                      ended.
     *
     * @return void
     * @throws Exception If the process method for the tag cannot be found.
     */
    protected function parseTag($tag, $start, $end)
    {
        $tokens = array_slice($this->words, ($start + 1), ($end - $start));

        $allowedTags     = (self::$_tags + $this->getAllowedTags());
        $allowedTagNames = array_keys($allowedTags);
        if ($tag === 'comment' || in_array($tag, $allowedTagNames) === true) {
            $method = 'parse'.$tag;
            if (method_exists($this, $method) === false) {
                $error = 'Method '.$method.' must be implemented to process '.$tag.' tags';
                throw new Exception($error);
            }

            $this->previousElement = $this->$method($tokens);
        } else {
            $this->previousElement = new PHP_CodeSniffer_CommentParser_SingleElement(
                $this->previousElement,
                $tokens,
                $tag,
                $this->phpcsFile
            );
        }

        $this->orders[] = $tag;

        if ($this->previousElement === null
            || ($this->previousElement instanceof PHP_CodeSniffer_CommentParser_DocElement) === false
        ) {
            throw new Exception('Parse method must return a DocElement');
        }

    }//end parseTag()


    /**
     * Returns a list of tags that this comment parser allows for it's comment.
     *
     * Each tag should indicate if only one entry of this tag can exist in the
     * comment by specifying true as the array value, or false if more than one
     * is allowed. Each tag should omit the @ symbol. Only tags other than
     * the standard tags should be returned.
     *
     * @return array(string => boolean)
     */
    protected abstract function getAllowedTags();


    /**
     * Returns the tag orders (index => tagName).
     *
     * @return array
     */
    public function getTagOrders()
    {
        return $this->orders;

    }//end getTagOrders()


    /**
     * Returns the unknown tags.
     *
     * @return array
     */
    public function getUnknown()
    {
        return $this->unknown;

    }//end getUnknown()


}//end class

?>
<?php
/**
 * Parses class member comments.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_CommentParser_ClassCommentParser', true) === false) {
    $error = 'Class PHP_CodeSniffer_CommentParser_ClassCommentParser not found';
    throw new PHP_CodeSniffer_Exception($error);
}

/**
 * Parses class member comments.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_CommentParser_MemberCommentParser extends PHP_CodeSniffer_CommentParser_ClassCommentParser
{

    /**
     * Represents a \@var tag in a member comment.
     *
     * @var PHP_CodeSniffer_CommentParser_SingleElement
     */
    private $_var = null;


    /**
     * Parses Var tags.
     *
     * @param array $tokens The tokens that represent this tag.
     *
     * @return PHP_CodeSniffer_CommentParser_SingleElement
     */
    protected function parseVar($tokens)
    {
        $this->_var = new PHP_CodeSniffer_CommentParser_SingleElement(
            $this->previousElement,
            $tokens,
            'var',
            $this->phpcsFile
        );

        return $this->_var;

    }//end parseVar()


    /**
     * Returns the var tag found in the member comment.
     *
     * @return PHP_CodeSniffer_CommentParser_PairElement
     */
    public function getVar()
    {
        return $this->_var;

    }//end getVar()


    /**
     * Returns the allowed tags for this parser.
     *
     * @return array
     */
    protected function getAllowedTags()
    {
        return array('var' => true);

    }//end getAllowedTags()


}//end class

?>
<?php
/**
 * A class to handle most of the parsing operations of a doc comment element.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (interface_exists('PHP_CodeSniffer_CommentParser_DocElement', true) === false) {
    $error = 'Interface PHP_CodeSniffer_CommentParser_DocElement not found';
    throw new PHP_CodeSniffer_Exception($error);
}

/**
 * A class to handle most of the parsing operations of a doc comment element.
 *
 * Extending classes should implement the getSubElements method to return
 * a list of elements that the doc comment element contains, in the order that
 * they appear in the element. For example a function parameter element has a
 * type, a variable name and a comment. It should therefore implement the method
 * as follows:
 *
 * <code>
 *    protected function getSubElements()
 *    {
 *        return array(
 *                'type',
 *                'variable',
 *                'comment',
 *               );
 *    }
 * </code>
 *
 * The processSubElement will be called for each of the sub elements to allow
 * the extending class to process them. So for the parameter element we would
 * have:
 *
 * <code>
 *    protected function processSubElement($name, $content, $whitespaceBefore)
 *    {
 *        if ($name === 'type') {
 *            echo 'The name of the variable was '.$content;
 *        }
 *        // Process other tags.
 *    }
 * </code>
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
abstract class PHP_CodeSniffer_CommentParser_AbstractDocElement implements PHP_CodeSniffer_CommentParser_DocElement
{

    /**
     * The element previous to this element.
     *
     * @var PHP_CodeSniffer_CommentParser_DocElement
     */
    protected $previousElement = null;

    /**
     * The element proceeding this element.
     *
     * @var PHP_CodeSniffer_CommentParser_DocElement
     */
    protected $nextElement = null;

    /**
     * The whitespace the occurs after this element and its sub elements.
     *
     * @var string
     */
    protected $afterWhitespace = '';

    /**
     * The tokens that comprise this element.
     *
     * @var array(string)
     */
    protected $tokens = array();

    /**
     * The file this element is in.
     *
     * @var array(string)
     */
    protected $phpcsFile = null;

    /**
     * The tag that this element represents (omitting the @ symbol).
     *
     * @var string
     */
    protected $tag = '';


    /**
     * Constructs a Doc Element.
     *
     * @param PHP_CodeSniffer_CommentParser_DocElement $previousElement The element
     *                                                                  that ocurred
     *                                                                  before this.
     * @param array                                    $tokens          The tokens of
     *                                                                  this element.
     * @param string                                   $tag             The doc
     *                                                                  element tag
     *                                                                  this element
     *                                                                  represents.
     * @param PHP_CodeSniffer_File                     $phpcsFile       The file that
     *                                                                  this element
     *                                                                  is in.
     *
     * @throws Exception If $previousElement in not a DocElement or if
     *                   getSubElements() does not return an array.
     */
    public function __construct(
        $previousElement,
        array $tokens,
        $tag,
        PHP_CodeSniffer_File $phpcsFile
    ) {
        if ($previousElement !== null
            && ($previousElement instanceof PHP_CodeSniffer_CommentParser_DocElement) === false
        ) {
            $error = '$previousElement must be an instance of DocElement';
            throw new Exception($error);
        }

        $this->phpcsFile = $phpcsFile;

        $this->previousElement = $previousElement;
        if ($previousElement !== null) {
            $this->previousElement->nextElement = $this;
        }

        $this->tag    = $tag;
        $this->tokens = $tokens;

        $subElements = $this->getSubElements();

        if (is_array($subElements) === false) {
            throw new Exception('getSubElements() must return an array');
        }

        $whitespace            = '';
        $currElem              = 0;
        $lastElement           = '';
        $lastElementWhitespace = null;
        $numSubElements        = count($subElements);

        foreach ($this->tokens as $token) {
            if (trim($token) === '') {
                $whitespace .= $token;
            } else {
                if ($currElem < ($numSubElements - 1)) {
                    $element = $subElements[$currElem];
                    $this->processSubElement($element, $token, $whitespace);
                    $whitespace = '';
                    $currElem++;
                } else {
                    if ($lastElementWhitespace === null) {
                        $lastElementWhitespace = $whitespace;
                    }

                    $lastElement .= $whitespace.$token;
                    $whitespace   = '';
                }
            }
        }//end foreach

        $lastElement     = ltrim($lastElement);
        $lastElementName = $subElements[($numSubElements - 1)];

        // Process the last element in this tag.
        $this->processSubElement(
            $lastElementName,
            $lastElement,
            $lastElementWhitespace
        );

        $this->afterWhitespace = $whitespace;

    }//end __construct()


    /**
     * Returns the element that exists before this.
     *
     * @return PHP_CodeSniffer_CommentParser_DocElement
     */
    public function getPreviousElement()
    {
        return $this->previousElement;

    }//end getPreviousElement()


    /**
     * Returns the element that exists after this.
     *
     * @return PHP_CodeSniffer_CommentParser_DocElement
     */
    public function getNextElement()
    {
        return $this->nextElement;

    }//end getNextElement()


    /**
     * Returns the whitespace that exists before this element.
     *
     * @return string
     */
    public function getWhitespaceBefore()
    {
        if ($this->previousElement !== null) {
            return $this->previousElement->getWhitespaceAfter();
        }

        return '';

    }//end getWhitespaceBefore()


    /**
     * Returns the whitespace that exists after this element.
     *
     * @return string
     */
    public function getWhitespaceAfter()
    {
        return $this->afterWhitespace;

    }//end getWhitespaceAfter()


    /**
     * Returns the order that this element appears in the comment.
     *
     * @return int
     */
    public function getOrder()
    {
        if ($this->previousElement === null) {
            return 1;
        } else {
            return ($this->previousElement->getOrder() + 1);
        }

    }//end getOrder()


    /**
     * Returns the tag that this element represents, ommiting the @ symbol.
     *
     * @return string
     */
    public function getTag()
    {
        return $this->tag;

    }//end getTag()


    /**
     * Returns the raw content of this element, ommiting the tag.
     *
     * @return string
     */
    public function getRawContent()
    {
        return implode('', $this->tokens);

    }//end getRawContent()


    /**
     * Returns the comment tokens.
     *
     * @return array
     */
    public function getTokens()
    {
        return $this->tokens;

    }//end getTokens()


    /**
     * Returns the line in which this element first occured.
     *
     * @return int
     */
    public function getLine()
    {
        if ($this->previousElement === null) {
            // First element is on line one.
            return 1;
        } else {
            $previousContent = $this->previousElement->getRawContent();
            $previousLine    = $this->previousElement->getLine();

            return ($previousLine + substr_count($previousContent, $this->phpcsFile->eolChar));
        }

    }//end getLine()


    /**
     * Returns the sub element names that make up this element in the order they
     * appear in the element.
     *
     * @return array(string)
     * @see processSubElement()
     */
    abstract protected function getSubElements();


    /**
     * Called to process each sub element as sepcified in the return value
     * of getSubElements().
     *
     * @param string $name             The name of the element to process.
     * @param string $content          The content of the the element.
     * @param string $whitespaceBefore The whitespace found before this element.
     *
     * @return void
     * @see getSubElements()
     */
    abstract protected function processSubElement(
        $name,
        $content,
        $whitespaceBefore
    );


}//end class

?>
<?php
/**
 * Parses Class doc comments.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_CommentParser_AbstractParser', true) === false) {
    $error = 'Class PHP_CodeSniffer_CommentParser_AbstractParser not found';
    throw new PHP_CodeSniffer_Exception($error);
}

/**
 * Parses Class doc comments.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_CommentParser_ClassCommentParser extends PHP_CodeSniffer_CommentParser_AbstractParser
{

    /**
     * The package element of this class.
     *
     * @var SingleElement
     */
    private $_package = null;

    /**
     * The subpackage element of this class.
     *
     * @var SingleElement
     */
    private $_subpackage = null;

    /**
     * The version element of this class.
     *
     * @var SingleElement
     */
    private $_version = null;

    /**
     * The category element of this class.
     *
     * @var SingleElement
     */
    private $_category = null;

    /**
     * The copyright elements of this class.
     *
     * @var array(SingleElement)
     */
    private $_copyrights = array();

    /**
     * The licence element of this class.
     *
     * @var PairElement
     */
    private $_license = null;

    /**
     * The author elements of this class.
     *
     * @var array(SingleElement)
     */
    private $_authors = array();


    /**
     * Returns the allowed tags withing a class comment.
     *
     * @return array(string => int)
     */
    protected function getAllowedTags()
    {
        return array(
                'category'   => false,
                'package'    => true,
                'subpackage' => true,
                'author'     => false,
                'copyright'  => true,
                'license'    => false,
                'version'    => true,
               );

    }//end getAllowedTags()


    /**
     * Parses the license tag of this class comment.
     *
     * @param array $tokens The tokens that comprise this tag.
     *
     * @return PHP_CodeSniffer_CommentParser_PairElement
     */
    protected function parseLicense($tokens)
    {
        $this->_license = new PHP_CodeSniffer_CommentParser_PairElement(
            $this->previousElement,
            $tokens,
            'license',
            $this->phpcsFile
        );

        return $this->_license;

    }//end parseLicense()


    /**
     * Parses the copyright tags of this class comment.
     *
     * @param array $tokens The tokens that comprise this tag.
     *
     * @return PHP_CodeSniffer_CommentParser_SingleElement
     */
    protected function parseCopyright($tokens)
    {
        $copyright = new PHP_CodeSniffer_CommentParser_SingleElement(
            $this->previousElement,
            $tokens,
            'copyright',
            $this->phpcsFile
        );

        $this->_copyrights[] = $copyright;
        return $copyright;

    }//end parseCopyright()


    /**
     * Parses the category tag of this class comment.
     *
     * @param array $tokens The tokens that comprise this tag.
     *
     * @return PHP_CodeSniffer_CommentParser_SingleElement
     */
    protected function parseCategory($tokens)
    {
        $this->_category = new PHP_CodeSniffer_CommentParser_SingleElement(
            $this->previousElement,
            $tokens,
            'category',
            $this->phpcsFile
        );

        return $this->_category;

    }//end parseCategory()


    /**
     * Parses the author tag of this class comment.
     *
     * @param array $tokens The tokens that comprise this tag.
     *
     * @return array(PHP_CodeSniffer_CommentParser_SingleElement)
     */
    protected function parseAuthor($tokens)
    {
        $author = new PHP_CodeSniffer_CommentParser_SingleElement(
            $this->previousElement,
            $tokens,
            'author',
            $this->phpcsFile
        );

        $this->_authors[] = $author;
        return $author;

    }//end parseAuthor()


    /**
     * Parses the version tag of this class comment.
     *
     * @param array $tokens The tokens that comprise this tag.
     *
     * @return PHP_CodeSniffer_CommentParser_SingleElement
     */
    protected function parseVersion($tokens)
    {
        $this->_version = new PHP_CodeSniffer_CommentParser_SingleElement(
            $this->previousElement,
            $tokens,
            'version',
            $this->phpcsFile
        );

        return $this->_version;

    }//end parseVersion()


    /**
     * Parses the package tag found in this test.
     *
     * @param array $tokens The tokens that comprise this var.
     *
     * @return PHP_CodeSniffer_CommentParser_SingleElement
     */
    protected function parsePackage($tokens)
    {
        $this->_package = new PHP_CodeSniffer_CommentParser_SingleElement(
            $this->previousElement,
            $tokens,
            'package',
            $this->phpcsFile
        );

        return $this->_package;

    }//end parsePackage()


    /**
     * Parses the package tag found in this test.
     *
     * @param array $tokens The tokens that comprise this var.
     *
     * @return PHP_CodeSniffer_CommentParser_SingleElement
     */
    protected function parseSubpackage($tokens)
    {
        $this->_subpackage = new PHP_CodeSniffer_CommentParser_SingleElement(
            $this->previousElement,
            $tokens,
            'subpackage',
            $this->phpcsFile
        );

        return $this->_subpackage;

    }//end parseSubpackage()


    /**
     * Returns the authors of this class comment.
     *
     * @return array(PHP_CodeSniffer_CommentParser_SingleElement)
     */
    public function getAuthors()
    {
        return $this->_authors;

    }//end getAuthors()


    /**
     * Returns the version of this class comment.
     *
     * @return PHP_CodeSniffer_CommentParser_SingleElement
     */
    public function getVersion()
    {
        return $this->_version;

    }//end getVersion()


    /**
     * Returns the license of this class comment.
     *
     * @return PHP_CodeSniffer_CommentParser_PairElement
     */
    public function getLicense()
    {
        return $this->_license;

    }//end getLicense()


    /**
     * Returns the copyrights of this class comment.
     *
     * @return PHP_CodeSniffer_CommentParser_SingleElement
     */
    public function getCopyrights()
    {
        return $this->_copyrights;

    }//end getCopyrights()


    /**
     * Returns the category of this class comment.
     *
     * @return PHP_CodeSniffer_CommentParser_SingleElement
     */
    public function getCategory()
    {
        return $this->_category;

    }//end getCategory()


    /**
     * Returns the package that this class belongs to.
     *
     * @return PHP_CodeSniffer_CommentParser_SingleElement
     */
    public function getPackage()
    {
        return $this->_package;

    }//end getPackage()


    /**
     * Returns the subpackage that this class belongs to.
     *
     * @return PHP_CodeSniffer_CommentParser_SingleElement
     */
    public function getSubpackage()
    {
        return $this->_subpackage;

    }//end getSubpackage()


}//end class

?>
<?php
/**
 * Parses function doc comments.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_CommentParser_AbstractParser', true) === false) {
    $error = 'Class PHP_CodeSniffer_CommentParser_AbstractParser not found';
    throw new PHP_CodeSniffer_Exception($error);
}

if (class_exists('PHP_CodeSniffer_CommentParser_ParameterElement', true) === false) {
    $error = 'Class PHP_CodeSniffer_CommentParser_ParameterElement not found';
    throw new PHP_CodeSniffer_Exception($error);
}

if (class_exists('PHP_CodeSniffer_CommentParser_PairElement', true) === false) {
    $error = 'Class PHP_CodeSniffer_CommentParser_PairElement not found';
    throw new PHP_CodeSniffer_Exception($error);
}

if (class_exists('PHP_CodeSniffer_CommentParser_SingleElement', true) === false) {
    $error = 'Class PHP_CodeSniffer_CommentParser_SingleElement not found';
    throw new PHP_CodeSniffer_Exception($error);
}

/**
 * Parses function doc comments.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_CommentParser_FunctionCommentParser extends PHP_CodeSniffer_CommentParser_AbstractParser
{

    /**
     * The parameter elements within this function comment.
     *
     * @var array(PHP_CodeSniffer_CommentParser_ParameterElement)
     */
    private $_params = array();

    /**
     * The return element in this function comment.
     *
     * @var PHP_CodeSniffer_CommentParser_PairElement.
     */
    private $_return = null;

    /**
     * The throws element list for this function comment.
     *
     * @var array(PHP_CodeSniffer_CommentParser_PairElement)
     */
    private $_throws = array();


    /**
     * Constructs a PHP_CodeSniffer_CommentParser_FunctionCommentParser.
     *
     * @param string               $comment   The comment to parse.
     * @param PHP_CodeSniffer_File $phpcsFile The file that this comment is in.
     */
    public function __construct($comment, PHP_CodeSniffer_File $phpcsFile)
    {
        parent::__construct($comment, $phpcsFile);

    }//end __construct()


    /**
     * Parses parameter elements.
     *
     * @param array(string) $tokens The tokens that comprise this sub element.
     *
     * @return PHP_CodeSniffer_CommentParser_ParameterElement
     */
    protected function parseParam($tokens)
    {
        $param = new PHP_CodeSniffer_CommentParser_ParameterElement(
            $this->previousElement,
            $tokens,
            $this->phpcsFile
        );

        $this->_params[] = $param;
        return $param;

    }//end parseParam()


    /**
     * Parses return elements.
     *
     * @param array(string) $tokens The tokens that comprise this sub element.
     *
     * @return PHP_CodeSniffer_CommentParser_PairElement
     */
    protected function parseReturn($tokens)
    {
        $return = new PHP_CodeSniffer_CommentParser_PairElement(
            $this->previousElement,
            $tokens,
            'return',
            $this->phpcsFile
        );

        $this->_return = $return;
        return $return;

    }//end parseReturn()


    /**
     * Parses throws elements.
     *
     * @param array(string) $tokens The tokens that comprise this sub element.
     *
     * @return PHP_CodeSniffer_CommentParser_PairElement
     */
    protected function parseThrows($tokens)
    {
        $throws = new PHP_CodeSniffer_CommentParser_PairElement(
            $this->previousElement,
            $tokens,
            'throws',
            $this->phpcsFile
        );

        $this->_throws[] = $throws;
        return $throws;

    }//end parseThrows()


    /**
     * Returns the parameter elements that this function comment contains.
     *
     * Returns an empty array if no parameter elements are contained within
     * this function comment.
     *
     * @return array(PHP_CodeSniffer_CommentParser_ParameterElement)
     */
    public function getParams()
    {
        return $this->_params;

    }//end getParams()


    /**
     * Returns the return element in this function comment.
     *
     * Returns null if no return element exists in the comment.
     *
     * @return PHP_CodeSniffer_CommentParser_PairElement
     */
    public function getReturn()
    {
        return $this->_return;

    }//end getReturn()


    /**
     * Returns the throws elements in this function comment.
     *
     * Returns empty array if no throws elements in the comment.
     *
     * @return array(PHP_CodeSniffer_CommentParser_PairElement)
     */
    public function getThrows()
    {
        return $this->_throws;

    }//end getThrows()


    /**
     * Returns the allowed tags that can exist in a function comment.
     *
     * @return array(string => boolean)
     */
    protected function getAllowedTags()
    {
        return array(
                'param'  => false,
                'return' => true,
                'throws' => false,
               );

    }//end getAllowedTags()


}//end class

?>
<?php
/**
 * An exception to be thrown when a DocCommentParser finds an anomaly in a
 * doc comment.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * An exception to be thrown when a DocCommentParser finds an anomaly in a
 * doc comment.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_CommentParser_ParserException extends Exception
{

    /**
     * The line where the exception occurred, in relation to the doc comment.
     *
     * @var int
     */
    private $_line = 0;


    /**
     * Constructs a DocCommentParserException.
     *
     * @param string $message The message of the exception.
     * @param int    $line    The position in comment where the error occurred.
     *                        A position of 0 indicates that the error occurred
     *                        at the opening line of the doc comment.
     */
    public function __construct($message, $line)
    {
        parent::__construct($message);
        $this->_line = $line;

    }//end __construct()


    /**
     * Returns the line number within the comment where the exception occurred.
     *
     * @return int
     */
    public function getLineWithinComment()
    {
        return $this->_line;

    }//end getLineWithinComment()


}//end class

?>
<?php
/**
 * A class to represent elements that have a value => comment format.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_CommentParser_AbstractDocElement', true) === false) {
    $error = 'Class PHP_CodeSniffer_CommentParser_AbstractDocElement not found';
    throw new PHP_CodeSniffer_Exception($error);
}

/**
 * A class to represent elements that have a value => comment format.
 *
 * An example of a pair element tag is the \@throws as it has an exception type
 * and a comment on the circumstance of when the exception is thrown.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_CommentParser_PairElement extends PHP_CodeSniffer_CommentParser_AbstractDocElement
{

    /**
     * The value of the tag.
     *
     * @var string
     */
    private $_value = '';

    /**
     * The comment of the tag.
     *
     * @var string
     */
    private $_comment = '';

    /**
     * The whitespace that exists before the value elem.
     *
     * @var string
     */
    private $_valueWhitespace = '';

    /**
     * The whitespace that exists before the comment elem.
     *
     * @var string
     */
    private $_commentWhitespace = '';


    /**
     * Constructs a PHP_CodeSniffer_CommentParser_PairElement doc tag.
     *
     * @param PHP_CodeSniffer_CommentParser_DocElement $previousElement The element
     *                                                                  before this
     *                                                                  one.
     * @param array                                    $tokens          The tokens
     *                                                                  that comprise
     *                                                                  this element.
     * @param string                                   $tag             The tag that
     *                                                                  this element
     *                                                                  represents.
     * @param PHP_CodeSniffer_File                     $phpcsFile       The file that
     *                                                                  this element
     *                                                                  is in.
     */
    public function __construct(
        $previousElement,
        $tokens,
        $tag,
        PHP_CodeSniffer_File $phpcsFile
    ) {
        parent::__construct($previousElement, $tokens, $tag, $phpcsFile);

    }//end __construct()


    /**
     * Returns the element names that this tag is comprised of, in the order
     * that they appear in the tag.
     *
     * @return array(string)
     * @see processSubElement()
     */
    protected function getSubElements()
    {
        return array(
                'value',
                'comment',
               );

    }//end getSubElements()


    /**
     * Processes the sub element with the specified name.
     *
     * @param string $name             The name of the sub element to process.
     * @param string $content          The content of this sub element.
     * @param string $whitespaceBefore The whitespace that exists before the
     *                                 sub element.
     *
     * @return void
     * @see getSubElements()
     */
    protected function processSubElement($name, $content, $whitespaceBefore)
    {
        $element           = '_'.$name;
        $whitespace        = $element.'Whitespace';
        $this->$element    = $content;
        $this->$whitespace = $whitespaceBefore;

    }//end processSubElement()


    /**
     * Returns the value of the tag.
     *
     * @return string
     */
    public function getValue()
    {
        return $this->_value;

    }//end getValue()


    /**
     * Returns the comment associated with the value of this tag.
     *
     * @return string
     */
    public function getComment()
    {
        return $this->_comment;

    }//end getComment()


    /**
     * Returns the whitespace before the content of this tag.
     *
     * @return string
     */
    public function getWhitespaceBeforeValue()
    {
        return $this->_valueWhitespace;

    }//end getWhitespaceBeforeValue()


}//end class

?>
<?php
/**
 * A class to represent param tags within a function comment.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_CommentParser_AbstractDocElement', true) === false) {
    $error = 'Class PHP_CodeSniffer_CommentParser_AbstractDocElement not found';
    throw new PHP_CodeSniffer_Exception($error);
}

/**
 * A class to represent param tags within a function comment.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_CommentParser_ParameterElement extends PHP_CodeSniffer_CommentParser_AbstractDocElement
{

    /**
     * The variable name of this parameter name, including the $ sign.
     *
     * @var string
     */
    private $_varName = '';

    /**
     * The comment of this parameter tag.
     *
     * @var string
     */
    private $_comment = '';

    /**
     * The variable type of this parameter tag.
     *
     * @var string
     */
    private $_type = '';

    /**
     * The whitespace that exists before the variable name.
     *
     * @var string
     */
    private $_varNameWhitespace = '';

    /**
     * The whitespace that exists before the comment.
     *
     * @var string
     */
    private $_commentWhitespace = null;

    /**
     * The whitespace that exists before the variable type.
     *
     * @var string
     */
    private $_typeWhitespace = '';


    /**
     * Constructs a PHP_CodeSniffer_CommentParser_ParameterElement.
     *
     * @param PHP_CodeSniffer_CommentParser_DocElement $previousElement The element
     *                                                                  previous to
     *                                                                  this one.
     * @param array                                    $tokens          The tokens
     *                                                                  that make up
     *                                                                  this element.
     * @param PHP_CodeSniffer_File                     $phpcsFile       The file that
     *                                                                  this element
     *                                                                  is in.
     */
    public function __construct(
        $previousElement,
        $tokens,
        PHP_CodeSniffer_File $phpcsFile
    ) {
        parent::__construct($previousElement, $tokens, 'param', $phpcsFile);

        // Handle special variable type: array(x => y).
        $type = strtolower($this->_type);
        if ($this->_varName === '=>' && strpos($type, 'array(') !== false) {
            $rawContent = $this->getRawContent();
            $matches    = array();
            $pattern    = '/^(\s+)(array\(.*\))(\s+)(\$\S*)(\s+)(.*)/i';
            if (preg_match($pattern, $rawContent, $matches) !== 0) {
                // Process the sub elements correctly for this special case.
                if (count($matches) === 7) {
                    $this->processSubElement('type', $matches[2], $matches[1]);
                    $this->processSubElement('varName', $matches[4], $matches[3]);
                    $this->processSubElement('comment', $matches[6], $matches[5]);
                }
            }
        }

    }//end __construct()


    /**
     * Returns the element names that this tag is comprised of, in the order
     * that they appear in the tag.
     *
     * @return array(string)
     * @see processSubElement()
     */
    protected function getSubElements()
    {
        return array(
                'type',
                'varName',
                'comment',
               );

    }//end getSubElements()


    /**
     * Processes the sub element with the specified name.
     *
     * @param string $name             The name of the sub element to process.
     * @param string $content          The content of this sub element.
     * @param string $beforeWhitespace The whitespace that exists before the
     *                                 sub element.
     *
     * @return void
     * @see getSubElements()
     */
    protected function processSubElement($name, $content, $beforeWhitespace)
    {
        $element           = '_'.$name;
        $whitespace        = $element.'Whitespace';
        $this->$element    = $content;
        $this->$whitespace = $beforeWhitespace;

    }//end processSubElement()


    /**
     * Returns the variable name that this parameter tag represents.
     *
     * @return string
     */
    public function getVarName()
    {
        return $this->_varName;

    }//end getVarName()


    /**
     * Returns the variable type that this string represents.
     *
     * @return string
     */
    public function getType()
    {
        return $this->_type;

    }//end getType()


    /**
     * Returns the comment of this comment for this parameter.
     *
     * @return string
     */
    public function getComment()
    {
        return $this->_comment;

    }//end getComment()


    /**
     * Returns the whitespace before the variable type.
     *
     * @return string
     * @see getWhiteSpaceBeforeVarName()
     * @see getWhiteSpaceBeforeComment()
     */
    public function getWhiteSpaceBeforeType()
    {
        return $this->_typeWhitespace;

    }//end getWhiteSpaceBeforeType()


    /**
     * Returns the whitespace before the variable name.
     *
     * @return string
     * @see getWhiteSpaceBeforeComment()
     * @see getWhiteSpaceBeforeType()
     */
    public function getWhiteSpaceBeforeVarName()
    {
        return $this->_varNameWhitespace;

    }//end getWhiteSpaceBeforeVarName()


    /**
     * Returns the whitespace before the comment.
     *
     * @return string
     * @see getWhiteSpaceBeforeVarName()
     * @see getWhiteSpaceBeforeType()
     */
    public function getWhiteSpaceBeforeComment()
    {
        return $this->_commentWhitespace;

    }//end getWhiteSpaceBeforeComment()


    /**
     * Returns the position of this parameter are it appears in the comment.
     *
     * This method differs from getOrder as it is only relative to method
     * parameters.
     *
     * @return int
     */
    public function getPosition()
    {
        if (($this->getPreviousElement() instanceof PHP_CodeSniffer_CommentParser_ParameterElement) === false) {
            return 1;
        } else {
            return ($this->getPreviousElement()->getPosition() + 1);
        }

    }//end getPosition()


    /**
     * Returns true if this parameter's variable aligns with the other's.
     *
     * @param PHP_CodeSniffer_CommentParser_ParameterElement $other The other param
     *                                                              to check
     *                                                              alignment with.
     *
     * @return boolean
     */
    public function alignsVariableWith(
        PHP_CodeSniffer_CommentParser_ParameterElement $other
    ) {
        // Format is:
        // @param type $variable Comment.
        // @param <-a-><---b---->
        // Compares the index before param variable.
        $otherVar = (strlen($other->_type) + strlen($other->_varNameWhitespace));
        $thisVar  = (strlen($this->_type) + strlen($this->_varNameWhitespace));
        if ($otherVar !== $thisVar) {
            return false;
        }

        return true;

    }//end alignsVariableWith()


    /**
     * Returns true if this parameter's comment aligns with the other's.
     *
     * @param PHP_CodeSniffer_CommentParser_ParameterElement $other The other param
     *                                                              to check
     *                                                              alignment with.
     *
     * @return boolean
     */
    public function alignsCommentWith(
        PHP_CodeSniffer_CommentParser_ParameterElement $other
    ) {
        // Compares the index before param comment.
        if (strlen($other->_commentWhitespace) === 0 && strlen($this->_commentWhitespace) === 0) {
            return true;
        }

        $otherComment
            = (strlen($other->_varName) + strlen($other->_commentWhitespace));
        $thisComment
            = (strlen($this->_varName) + strlen($this->_commentWhitespace));

        if ($otherComment !== $thisComment) {
            return false;
        }

        return true;

    }//end alignsCommentWith()


    /**
     * Returns true if this parameter aligns with the other paramter.
     *
     * @param PHP_CodeSniffer_CommentParser_ParameterElement $other The other param
     *                                                              to check
     *                                                              alignment with.
     *
     * @return boolean
     */
    public function alignsWith(PHP_CodeSniffer_CommentParser_ParameterElement $other)
    {
        if ($this->alignsVariableWith($other) === false) {
            return false;
        }

        if ($this->alignsCommentWith($other) === false) {
            return false;
        }

        return true;

    }//end alignsWith()


}//end class

?>
<?php
/**
 * A class to process command line phpcs scripts.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (is_file(dirname(__FILE__).'/../CodeSniffer.php') === true) {
    include_once dirname(__FILE__).'/../CodeSniffer.php';
} else {
    include_once 'PHP/CodeSniffer.php';
}

/**
 * A class to process command line phpcs scripts.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_CLI
{

    /**
     * An array of all values specified on the command line.
     *
     * @var array
     */
    protected $values = array();

    /**
     * The minimum severity level errors must have to be displayed.
     *
     * @var bool
     */
    public $errorSeverity = 0;

    /**
     * The minimum severity level warnings must have to be displayed.
     *
     * @var bool
     */
    public $warningSeverity = 0;

    /**
     * Whether or not to kill the process when an unknown command line arg is found.
     *
     * If FALSE, arguments that are not command line options or file/directory paths
     * will be ignored and execution will continue.
     *
     * @var bool
     */
    public $dieOnUnknownArg = true;


    /**
     * Exits if the minimum requirements of PHP_CodSniffer are not met.
     *
     * @return array
     */
    public function checkRequirements()
    {
        // Check the PHP version.
        if (version_compare(PHP_VERSION, '5.1.2') === -1) {
            echo 'ERROR: PHP_CodeSniffer requires PHP version 5.1.2 or greater.'.PHP_EOL;
            exit(2);
        }

        if (extension_loaded('tokenizer') === false) {
            echo 'ERROR: PHP_CodeSniffer requires the tokenizer extension to be enabled.'.PHP_EOL;
            exit(2);
        }

    }//end checkRequirements()


    /**
     * Get a list of default values for all possible command line arguments.
     *
     * @return array
     */
    public function getDefaults()
    {
        // The default values for config settings.
        $defaults['files']           = array();
        $defaults['standard']        = null;
        $defaults['verbosity']       = 0;
        $defaults['interactive']     = false;
        $defaults['explain']         = false;
        $defaults['local']           = false;
        $defaults['showSources']     = false;
        $defaults['extensions']      = array();
        $defaults['sniffs']          = array();
        $defaults['ignored']         = array();
        $defaults['reportFile']      = null;
        $defaults['generator']       = '';
        $defaults['reports']         = array();
        $defaults['errorSeverity']   = null;
        $defaults['warningSeverity'] = null;

        $reportFormat = PHP_CodeSniffer::getConfigData('report_format');
        if ($reportFormat !== null) {
            $defaults['reports'][$reportFormat] = null;
        }

        $tabWidth = PHP_CodeSniffer::getConfigData('tab_width');
        if ($tabWidth === null) {
            $defaults['tabWidth'] = 0;
        } else {
            $defaults['tabWidth'] = (int) $tabWidth;
        }

        $encoding = PHP_CodeSniffer::getConfigData('encoding');
        if ($encoding === null) {
            $defaults['encoding'] = 'iso-8859-1';
        } else {
            $defaults['encoding'] = strtolower($encoding);
        }

        $severity = PHP_CodeSniffer::getConfigData('severity');
        if ($severity !== null) {
            $defaults['errorSeverity']   = (int) $severity;
            $defaults['warningSeverity'] = (int) $severity;
        }

        $severity = PHP_CodeSniffer::getConfigData('error_severity');
        if ($severity !== null) {
            $defaults['errorSeverity'] = (int) $severity;
        }

        $severity = PHP_CodeSniffer::getConfigData('warning_severity');
        if ($severity !== null) {
            $defaults['warningSeverity'] = (int) $severity;
        }

        $showWarnings = PHP_CodeSniffer::getConfigData('show_warnings');
        if ($showWarnings !== null) {
            $showWarnings = (bool) $showWarnings;
            if ($showWarnings === false) {
                $defaults['warningSeverity'] = 0;
            }
        }

        $reportWidth = PHP_CodeSniffer::getConfigData('report_width');
        if ($reportWidth === null) {
            $defaults['reportWidth'] = 80;
        } else {
            $defaults['reportWidth'] = (int) $reportWidth;
        }

        $showProgress = PHP_CodeSniffer::getConfigData('show_progress');
        if ($showProgress === null) {
            $defaults['showProgress'] = false;
        } else {
            $defaults['showProgress'] = (bool) $showProgress;
        }

        return $defaults;

    }//end getDefaults()


    /**
     * Process the command line arguments and returns the values.
     *
     * @return array
     */
    public function getCommandLineValues()
    {
        if (defined('PHP_CODESNIFFER_IN_TESTS') === true) {
            return array();
        }

        if (empty($this->values) === false) {
            return $this->values;
        }

        $values = $this->getDefaults();

        for ($i = 1; $i < $_SERVER['argc']; $i++) {
            $arg = $_SERVER['argv'][$i];
            if ($arg === '') {
                continue;
            }

            if ($arg{0} === '-') {
                if ($arg === '-' || $arg === '--') {
                    // Empty argument, ignore it.
                    continue;
                }

                if ($arg{1} === '-') {
                    $values
                        = $this->processLongArgument(substr($arg, 2), $i, $values);
                } else {
                    $switches = str_split($arg);
                    foreach ($switches as $switch) {
                        if ($switch === '-') {
                            continue;
                        }

                        $values = $this->processShortArgument($switch, $i, $values);
                    }
                }
            } else {
                $values = $this->processUnknownArgument($arg, $i, $values);
            }//end if
        }//end for

        $this->values = $values;
        return $values;

    }//end getCommandLineValues()


    /**
     * Processes a short (-e) command line argument.
     *
     * @param string $arg    The command line argument.
     * @param int    $pos    The position of the argument on the command line.
     * @param array  $values An array of values determined from CLI args.
     *
     * @return array The updated CLI values.
     * @see getCommandLineValues()
     */
    public function processShortArgument($arg, $pos, $values)
    {
        switch ($arg) {
        case 'h':
        case '?':
            $this->printUsage();
            exit(0);
            break;
        case 'i' :
            $this->printInstalledStandards();
            exit(0);
            break;
        case 'v' :
            $values['verbosity']++;
            break;
        case 'l' :
            $values['local'] = true;
            break;
        case 's' :
            $values['showSources'] = true;
            break;
        case 'a' :
            $values['interactive'] = true;
            break;
        case 'e':
            $values['explain'] = true;
            break;
        case 'p' :
            $values['showProgress'] = true;
            break;
        case 'd' :
            $ini = explode('=', $_SERVER['argv'][($pos + 1)]);
            $_SERVER['argv'][($pos + 1)] = '';
            if (isset($ini[1]) === true) {
                ini_set($ini[0], $ini[1]);
            } else {
                ini_set($ini[0], true);
            }

            break;
        case 'n' :
            $values['warningSeverity'] = 0;
            break;
        case 'w' :
            $values['warningSeverity'] = null;
            break;
        default:
            $values = $this->processUnknownArgument('-'.$arg, $pos, $values);
        }//end switch

        return $values;

    }//end processShortArgument()


    /**
     * Processes a long (--example) command line argument.
     *
     * @param string $arg    The command line argument.
     * @param int    $pos    The position of the argument on the command line.
     * @param array  $values An array of values determined from CLI args.
     *
     * @return array The updated CLI values.
     * @see getCommandLineValues()
     */
    public function processLongArgument($arg, $pos, $values)
    {
        switch ($arg) {
        case 'help':
            $this->printUsage();
            exit(0);
            break;
        case 'version':
            echo 'PHP_CodeSniffer version '.PHP_CodeSniffer::VERSION.' ('.PHP_CodeSniffer::STABILITY.') ';
            echo 'by Squiz (http://www.squiz.net)'.PHP_EOL;
            exit(0);
            break;
        case 'config-set':
            $key   = $_SERVER['argv'][($pos + 1)];
            $value = $_SERVER['argv'][($pos + 2)];
            PHP_CodeSniffer::setConfigData($key, $value);
            exit(0);
            break;
        case 'config-delete':
            $key = $_SERVER['argv'][($pos + 1)];
            PHP_CodeSniffer::setConfigData($key, null);
            exit(0);
            break;
        case 'config-show':
            $data = PHP_CodeSniffer::getAllConfigData();
            print_r($data);
            exit(0);
            break;
        default:
            if (substr($arg, 0, 7) === 'sniffs=') {
                $sniffs = substr($arg, 7);
                $values['sniffs'] = explode(',', $sniffs);
            } else if (substr($arg, 0, 12) === 'report-file=') {
                $values['reportFile'] = realpath(substr($arg, 12));

                // It may not exist and return false instead.
                if ($values['reportFile'] === false) {
                    $values['reportFile'] = substr($arg, 12);
                }

                if (is_dir($values['reportFile']) === true) {
                    echo 'ERROR: The specified report file path "'.$values['reportFile'].'" is a directory.'.PHP_EOL.PHP_EOL;
                    $this->printUsage();
                    exit(2);
                }

                $dir = dirname($values['reportFile']);
                if (is_dir($dir) === false) {
                    echo 'ERROR: The specified report file path "'.$values['reportFile'].'" points to a non-existent directory.'.PHP_EOL.PHP_EOL;
                    $this->printUsage();
                    exit(2);
                }

                if ($dir === '.') {
                    // Passed report file is a filename in the current directory.
                    $values['reportFile'] = getcwd().'/'.basename($values['reportFile']);
                } else {
                    $dir = realpath(getcwd().'/'.$dir);
                    if ($dir !== false) {
                        // Report file path is relative.
                        $values['reportFile'] = $dir.'/'.basename($values['reportFile']);
                    }
                }
            } else if (substr($arg, 0, 13) === 'report-width=') {
                $values['reportWidth'] = (int) substr($arg, 13);
            } else if (substr($arg, 0, 7) === 'report='
                || substr($arg, 0, 7) === 'report-'
            ) {
                if ($arg[6] === '-') {
                    // This is a report with file output.
                    $split = strpos($arg, '=');
                    if ($split === false) {
                        $report = substr($arg, 7);
                        $output = null;
                    } else {
                        $report = substr($arg, 7, ($split - 7));
                        $output = substr($arg, ($split + 1));
                        if ($output === false) {
                            $output = null;
                        } else {
                            $dir = dirname($output);
                            if ($dir === '.') {
                                // Passed report file is a filename in the current directory.
                                $output = getcwd().'/'.basename($output);
                            } else {
                                $dir = realpath(getcwd().'/'.$dir);
                                if ($dir !== false) {
                                    // Report file path is relative.
                                    $output = $dir.'/'.basename($output);
                                }
                            }
                        }//end if
                    }//end if
                } else {
                    // This is a single report.
                    $report = substr($arg, 7);
                    $output = null;
                }

                $validReports = array(
                                 'full',
                                 'xml',
                                 'json',
                                 'checkstyle',
                                 'junit',
                                 'csv',
                                 'emacs',
                                 'notifysend',
                                 'source',
                                 'summary',
                                 'svnblame',
                                 'gitblame',
                                 'hgblame',
                                );

                if (in_array($report, $validReports) === false) {
                    echo 'ERROR: Report type "'.$report.'" not known.'.PHP_EOL;
                    exit(2);
                }

                $values['reports'][$report] = $output;
            } else if (substr($arg, 0, 9) === 'standard=') {
                $values['standard'] = explode(',', substr($arg, 9));
            } else if (substr($arg, 0, 11) === 'extensions=') {
                $values['extensions'] = explode(',', substr($arg, 11));
            } else if (substr($arg, 0, 9) === 'severity=') {
                $values['errorSeverity']   = (int) substr($arg, 9);
                $values['warningSeverity'] = $values['errorSeverity'];
            } else if (substr($arg, 0, 15) === 'error-severity=') {
                $values['errorSeverity'] = (int) substr($arg, 15);
            } else if (substr($arg, 0, 17) === 'warning-severity=') {
                $values['warningSeverity'] = (int) substr($arg, 17);
            } else if (substr($arg, 0, 7) === 'ignore=') {
                // Split the ignore string on commas, unless the comma is escaped
                // using 1 or 3 slashes (\, or \\\,).
                $ignored = preg_split(
                    '/(?<=(?<!\\\\)\\\\\\\\),|(?<!\\\\),/',
                    substr($arg, 7)
                );
                foreach ($ignored as $pattern) {
                    $values['ignored'][$pattern] = 'absolute';
                }
            } else if (substr($arg, 0, 10) === 'generator=') {
                $values['generator'] = substr($arg, 10);
            } else if (substr($arg, 0, 9) === 'encoding=') {
                $values['encoding'] = strtolower(substr($arg, 9));
            } else if (substr($arg, 0, 10) === 'tab-width=') {
                $values['tabWidth'] = (int) substr($arg, 10);
            } else {
                $values = $this->processUnknownArgument('--'.$arg, $pos, $values);
            }//end if

            break;
        }//end switch

        return $values;

    }//end processLongArgument()


    /**
     * Processes an unknown command line argument.
     *
     * Assumes all unknown arguments are files and folders to check.
     *
     * @param string $arg    The command line argument.
     * @param int    $pos    The position of the argument on the command line.
     * @param array  $values An array of values determined from CLI args.
     *
     * @return array The updated CLI values.
     * @see getCommandLineValues()
     */
    public function processUnknownArgument($arg, $pos, $values)
    {
        // We don't know about any additional switches; just files.
        if ($arg{0} === '-') {
            if ($this->dieOnUnknownArg === false) {
                return $values;
            }

            echo 'ERROR: option "'.$arg.'" not known.'.PHP_EOL.PHP_EOL;
            $this->printUsage();
            exit(2);
        }

        $file = realpath($arg);
        if (file_exists($file) === false) {
            if ($this->dieOnUnknownArg === false) {
                return $values;
            }

            echo 'ERROR: The file "'.$arg.'" does not exist.'.PHP_EOL.PHP_EOL;
            $this->printUsage();
            exit(2);
        } else {
            $values['files'][] = $file;
        }

        return $values;

    }//end processUnknownArgument()


    /**
     * Runs PHP_CodeSniffer over files and directories.
     *
     * @param array $values An array of values determined from CLI args.
     *
     * @return int The number of error and warning messages shown.
     * @see getCommandLineValues()
     */
    public function process($values=array())
    {
        if (empty($values) === true) {
            $values = $this->getCommandLineValues();
        } else {
            $values       = array_merge($this->getDefaults(), $values);
            $this->values = $values;
        }

        if ($values['generator'] !== '') {
            $phpcs = new PHP_CodeSniffer($values['verbosity']);
            foreach ($values['standard'] as $standard) {
                $phpcs->generateDocs(
                    $standard,
                    $values['sniffs'],
                    $values['generator']
                );
            }

            exit(0);
        }

        // If no standard is supplied, get the default.
        $values['standard'] = $this->validateStandard($values['standard']);
        foreach ($values['standard'] as $standard) {
            if (PHP_CodeSniffer::isInstalledStandard($standard) === false) {
                // They didn't select a valid coding standard, so help them
                // out by letting them know which standards are installed.
                echo 'ERROR: the "'.$standard.'" coding standard is not installed. ';
                $this->printInstalledStandards();
                exit(2);
            }
        }

        if ($values['explain'] === true) {
            foreach ($values['standard'] as $standard) {
                $this->explainStandard($standard);
            }

            exit(0);
        }

        $fileContents = '';
        if (empty($values['files']) === true) {
            // Check if they are passing in the file contents.
            $handle       = fopen('php://stdin', 'r');
            $fileContents = stream_get_contents($handle);
            fclose($handle);

            if ($fileContents === '') {
                // No files and no content passed in.
                echo 'ERROR: You must supply at least one file or directory to process.'.PHP_EOL.PHP_EOL;
                $this->printUsage();
                exit(2);
            }
        }

        $phpcs = new PHP_CodeSniffer(
            $values['verbosity'],
            $values['tabWidth'],
            $values['encoding'],
            $values['interactive']
        );

        // Set file extensions if they were specified. Otherwise,
        // let PHP_CodeSniffer decide on the defaults.
        if (empty($values['extensions']) === false) {
            $phpcs->setAllowedFileExtensions($values['extensions']);
        }

        // Set ignore patterns if they were specified.
        if (empty($values['ignored']) === false) {
            $phpcs->setIgnorePatterns($values['ignored']);
        }

        // Set some convenience member vars.
        if ($values['errorSeverity'] === null) {
            $this->errorSeverity = PHPCS_DEFAULT_ERROR_SEV;
        } else {
            $this->errorSeverity = $values['errorSeverity'];
        }

        if ($values['warningSeverity'] === null) {
            $this->warningSeverity = PHPCS_DEFAULT_WARN_SEV;
        } else {
            $this->warningSeverity = $values['warningSeverity'];
        }

        if (empty($values['reports']) === true) {
            $this->values['reports']['full'] = $values['reportFile'];
        }

        $phpcs->setCli($this);

        $phpcs->process(
            $values['files'],
            $values['standard'],
            $values['sniffs'],
            $values['local']
        );

        if ($fileContents !== '') {
            $phpcs->processFile('STDIN', $fileContents);
        }

        // Interactive runs don't require a final report and it doesn't really
        // matter what the retun value is because we know it isn't being read
        // by a script.
        if ($values['interactive'] === true) {
            return 0;
        }

        return $this->printErrorReport(
            $phpcs,
            $values['reports'],
            $values['showSources'],
            $values['reportFile'],
            $values['reportWidth']
        );

    }//end process()


    /**
     * Prints the error report for the run.
     *
     * Note that this function may actually print multiple reports
     * as the user may have specified a number of output formats.
     *
     * @param PHP_CodeSniffer $phpcs       The PHP_CodeSniffer object containing
     *                                     the errors.
     * @param array           $reports     A list of reports to print.
     * @param bool            $showSources TRUE if report should show error sources
     *                                     (not used by all reports).
     * @param string          $reportFile  A default file to log report output to.
     * @param int             $reportWidth How wide the screen reports should be.
     *
     * @return int The number of error and warning messages shown.
     */
    public function printErrorReport(
        PHP_CodeSniffer $phpcs,
        $reports,
        $showSources,
        $reportFile,
        $reportWidth
    ) {
        if (empty($reports) === true) {
            $reports['full'] = $reportFile;
        }

        $errors   = 0;
        $toScreen = false;

        foreach ($reports as $report => $output) {
            if ($output === null) {
                $output = $reportFile;
            }

            if ($reportFile === null) {
                $toScreen = true;
            }

            // We don't add errors here because the number of
            // errors reported by each report type will always be the
            // same, so we really just need 1 number.
            $errors = $phpcs->reporting->printReport(
                $report,
                $showSources,
                $output,
                $reportWidth
            );
        }

        // Only print PHP_Timer output if no reports were
        // printed to the screen so we don't put additional output
        // in something like an XML report. If we are printing to screen,
        // the report types would have already worked out who should
        // print the timer info.
        if ($toScreen === false
            && PHP_CODESNIFFER_INTERACTIVE === false
            && class_exists('PHP_Timer', false) === true
        ) {
            echo PHP_Timer::resourceUsage().PHP_EOL.PHP_EOL;
        }

        // They should all return the same value, so it
        // doesn't matter which return value we end up using.
        return $errors;

    }//end printErrorReport()


    /**
     * Convert the passed standards into valid standards.
     *
     * Checks things like default values and case.
     *
     * @param array $standards The standards to validate.
     *
     * @return array
     */
    public function validateStandard($standards)
    {
        if ($standards === null) {
            // They did not supply a standard to use.
            // Try to get the default from the config system.
            $standard = PHP_CodeSniffer::getConfigData('default_standard');
            if ($standard === null) {
                // Product default standard.
                $standard = 'PEAR';
            }

            return array($standard);
        }

        $cleaned = array();

        // Check if the standard name is valid, or if the case is invalid.
        $installedStandards = PHP_CodeSniffer::getInstalledStandards();
        foreach ($standards as $standard) {
            foreach ($installedStandards as $validStandard) {
                if (strtolower($standard) === strtolower($validStandard)) {
                    $standard = $validStandard;
                    break;
                }
            }

            $cleaned[] = $standard;
        }

        return $cleaned;

    }//end validateStandard()


    /**
     * Prints a report showing the sniffs contained in a standard.
     *
     * @param string $standard The standard to validate.
     *
     * @return void
     */
    public function explainStandard($standard)
    {
        $phpcs = new PHP_CodeSniffer();
        $phpcs->process(array(), $standard);
        $sniffs = $phpcs->getSniffs();
        $sniffs = array_keys($sniffs);
        sort($sniffs);

        ob_start();

        $lastStandard = '';
        $lastCount    = '';
        $sniffCount   = count($sniffs);
        $sniffs[]     = '___';

        echo PHP_EOL."The $standard standard contains $sniffCount sniffs".PHP_EOL;

        ob_start();

        foreach ($sniffs as $sniff) {
            $parts = explode('_', str_replace('\\', '_', $sniff));
            if ($lastStandard === '') {
                $lastStandard = $parts[0];
            }

            if ($parts[0] !== $lastStandard) {
                $sniffList = ob_get_contents();
                ob_end_clean();

                echo PHP_EOL.$lastStandard.' ('.$lastCount.' sniffs)'.PHP_EOL;
                echo str_repeat('-', strlen($lastStandard.$lastCount) + 10);
                echo PHP_EOL;
                echo $sniffList;

                $lastStandard = $parts[0];
                $lastCount    = 0;

                ob_start();
            }

            echo '  '.$parts[0].'.'.$parts[2].'.'.substr($parts[3], 0, -5).PHP_EOL;
            $lastCount++;
        }//end foreach

        ob_end_clean();

    }//end explainStandard()


    /**
     * Prints out the usage information for this script.
     *
     * @return void
     */
    public function printUsage()
    {
        echo 'Usage: phpcs [-nwlsaepvi] [-d key[=value]]'.PHP_EOL;
        echo '    [--report=<report>] [--report-file=<reportfile>] [--report-<report>=<reportfile>] ...'.PHP_EOL;
        echo '    [--report-width=<reportWidth>] [--generator=<generator>] [--tab-width=<tabWidth>]'.PHP_EOL;
        echo '    [--severity=<severity>] [--error-severity=<severity>] [--warning-severity=<severity>]'.PHP_EOL;
        echo '    [--config-set key value] [--config-delete key] [--config-show]'.PHP_EOL;
        echo '    [--standard=<standard>] [--sniffs=<sniffs>] [--encoding=<encoding>]'.PHP_EOL;
        echo '    [--extensions=<extensions>] [--ignore=<patterns>] <file> ...'.PHP_EOL;
        echo '        -n            Do not print warnings (shortcut for --warning-severity=0)'.PHP_EOL;
        echo '        -w            Print both warnings and errors (on by default)'.PHP_EOL;
        echo '        -l            Local directory only, no recursion'.PHP_EOL;
        echo '        -s            Show sniff codes in all reports'.PHP_EOL;
        echo '        -a            Run interactively'.PHP_EOL;
        echo '        -e            Explain a standard by showing the sniffs it includes'.PHP_EOL;
        echo '        -p            Show progress of the run'.PHP_EOL;
        echo '        -v[v][v]      Print verbose output'.PHP_EOL;
        echo '        -i            Show a list of installed coding standards'.PHP_EOL;
        echo '        -d            Set the [key] php.ini value to [value] or [true] if value is omitted'.PHP_EOL;
        echo '        --help        Print this help message'.PHP_EOL;
        echo '        --version     Print version information'.PHP_EOL;
        echo '        <file>        One or more files and/or directories to check'.PHP_EOL;
        echo '        <extensions>  A comma separated list of file extensions to check'.PHP_EOL;
        echo '                      (only valid if checking a directory)'.PHP_EOL;
        echo '        <patterns>    A comma separated list of patterns to ignore files and directories'.PHP_EOL;
        echo '        <encoding>    The encoding of the files being checked (default is iso-8859-1)'.PHP_EOL;
        echo '        <sniffs>      A comma separated list of sniff codes to limit the check to'.PHP_EOL;
        echo '                      (all sniffs must be part of the specified standard)'.PHP_EOL;
        echo '        <severity>    The minimum severity required to display an error or warning'.PHP_EOL;
        echo '        <standard>    The name or path of the coding standard to use'.PHP_EOL;
        echo '        <tabWidth>    The number of spaces each tab represents'.PHP_EOL;
        echo '        <generator>   The name of a doc generator to use'.PHP_EOL;
        echo '                      (forces doc generation instead of checking)'.PHP_EOL;
        echo '        <report>      Print either the "full", "xml", "checkstyle", "csv", "json"'.PHP_EOL;
        echo '                      "emacs", "source", "summary", "svnblame", "gitblame", "hgblame" or'.PHP_EOL;
        echo '                      "notifysend" report'.PHP_EOL;
        echo '                      (the "full" report is printed by default)'.PHP_EOL;
        echo '        <reportfile>  Write the report to the specified file path'.PHP_EOL;
        echo '        <reportWidth> How many columns wide screen reports should be printed'.PHP_EOL;

    }//end printUsage()


    /**
     * Prints out a list of installed coding standards.
     *
     * @return void
     */
    public function printInstalledStandards()
    {
        $installedStandards = PHP_CodeSniffer::getInstalledStandards();
        $numStandards       = count($installedStandards);

        if ($numStandards === 0) {
            echo 'No coding standards are installed.'.PHP_EOL;
        } else {
            $lastStandard = array_pop($installedStandards);
            if ($numStandards === 1) {
                echo "The only coding standard installed is $lastStandard".PHP_EOL;
            } else {
                $standardList  = implode(', ', $installedStandards);
                $standardList .= ' and '.$lastStandard;
                echo 'The installed coding standards are '.$standardList.PHP_EOL;
            }
        }

    }//end printInstalledStandards()


}//end class

?>
<?php
/**
 * Tokenizes JS code.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Tokenizes JS code.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_Tokenizers_JS
{

    /**
     * A list of tokens that are allowed to open a scope.
     *
     * This array also contains information about what kind of token the scope
     * opener uses to open and close the scope, if the token strictly requires
     * an opener, if the token can share a scope closer, and who it can be shared
     * with. An example of a token that shares a scope closer is a CASE scope.
     *
     * @var array
     */
    public $scopeOpeners = array(
                            T_IF       => array(
                                           'start'  => array(T_OPEN_CURLY_BRACKET),
                                           'end'    => array(T_CLOSE_CURLY_BRACKET),
                                           'strict' => false,
                                           'shared' => false,
                                           'with'   => array(),
                                          ),
                            T_TRY      => array(
                                           'start'  => array(T_OPEN_CURLY_BRACKET),
                                           'end'    => array(T_CLOSE_CURLY_BRACKET),
                                           'strict' => true,
                                           'shared' => false,
                                           'with'   => array(),
                                          ),
                            T_CATCH    => array(
                                           'start'  => array(T_OPEN_CURLY_BRACKET),
                                           'end'    => array(T_CLOSE_CURLY_BRACKET),
                                           'strict' => true,
                                           'shared' => false,
                                           'with'   => array(),
                                          ),
                            T_ELSE     => array(
                                           'start'  => array(T_OPEN_CURLY_BRACKET),
                                           'end'    => array(T_CLOSE_CURLY_BRACKET),
                                           'strict' => false,
                                           'shared' => false,
                                           'with'   => array(),
                                          ),
                            T_FOR      => array(
                                           'start'  => array(T_OPEN_CURLY_BRACKET),
                                           'end'    => array(T_CLOSE_CURLY_BRACKET),
                                           'strict' => false,
                                           'shared' => false,
                                           'with'   => array(),
                                          ),
                            T_FUNCTION => array(
                                           'start'  => array(T_OPEN_CURLY_BRACKET),
                                           'end'    => array(T_CLOSE_CURLY_BRACKET),
                                           'strict' => false,
                                           'shared' => false,
                                           'with'   => array(),
                                          ),
                            T_WHILE    => array(
                                           'start'  => array(T_OPEN_CURLY_BRACKET),
                                           'end'    => array(T_CLOSE_CURLY_BRACKET),
                                           'strict' => false,
                                           'shared' => false,
                                           'with'   => array(),
                                          ),
                            T_DO       => array(
                                           'start'  => array(T_OPEN_CURLY_BRACKET),
                                           'end'    => array(T_CLOSE_CURLY_BRACKET),
                                           'strict' => true,
                                           'shared' => false,
                                           'with'   => array(),
                                          ),
                            T_SWITCH   => array(
                                           'start'  => array(T_OPEN_CURLY_BRACKET),
                                           'end'    => array(T_CLOSE_CURLY_BRACKET),
                                           'strict' => true,
                                           'shared' => false,
                                           'with'   => array(),
                                          ),
                            T_CASE     => array(
                                           'start'  => array(T_COLON),
                                           'end'    => array(
                                                        T_BREAK,
                                                        T_RETURN,
                                                        T_CONTINUE,
                                                        T_THROW,
                                                       ),
                                           'strict' => true,
                                           'shared' => true,
                                           'with'   => array(
                                                        T_DEFAULT,
                                                        T_CASE,
                                                        T_SWITCH,
                                                       ),
                                          ),
                            T_DEFAULT  => array(
                                           'start'  => array(T_COLON),
                                           'end'    => array(
                                                        T_BREAK,
                                                        T_RETURN,
                                                        T_CONTINUE,
                                                        T_THROW,
                                                       ),
                                           'strict' => true,
                                           'shared' => true,
                                           'with'   => array(
                                                        T_CASE,
                                                        T_SWITCH,
                                                       ),
                                          ),
                           );

    /**
     * A list of tokens that end the scope.
     *
     * This array is just a unique collection of the end tokens
     * from the _scopeOpeners array. The data is duplicated here to
     * save time during parsing of the file.
     *
     * @var array
     */
    public $endScopeTokens = array(
                              T_CLOSE_CURLY_BRACKET,
                              T_BREAK,
                             );

    /**
     * A list of special JS tokens and their types.
     *
     * @var array
     */
    protected $tokenValues = array(
                              'function'  => 'T_FUNCTION',
                              'prototype' => 'T_PROTOTYPE',
                              'try'       => 'T_TRY',
                              'catch'     => 'T_CATCH',
                              'return'    => 'T_RETURN',
                              'throw'     => 'T_THROW',
                              'break'     => 'T_BREAK',
                              'switch'    => 'T_SWITCH',
                              'continue'  => 'T_CONTINUE',
                              'if'        => 'T_IF',
                              'else'      => 'T_ELSE',
                              'do'        => 'T_DO',
                              'while'     => 'T_WHILE',
                              'for'       => 'T_FOR',
                              'var'       => 'T_VAR',
                              'case'      => 'T_CASE',
                              'default'   => 'T_DEFAULT',
                              'true'      => 'T_TRUE',
                              'false'     => 'T_FALSE',
                              'null'      => 'T_NULL',
                              'this'      => 'T_THIS',
                              'typeof'    => 'T_TYPEOF',
                              '('         => 'T_OPEN_PARENTHESIS',
                              ')'         => 'T_CLOSE_PARENTHESIS',
                              '{'         => 'T_OPEN_CURLY_BRACKET',
                              '}'         => 'T_CLOSE_CURLY_BRACKET',
                              '['         => 'T_OPEN_SQUARE_BRACKET',
                              ']'         => 'T_CLOSE_SQUARE_BRACKET',
                              '?'         => 'T_INLINE_THEN',
                              '.'         => 'T_OBJECT_OPERATOR',
                              '+'         => 'T_PLUS',
                              '-'         => 'T_MINUS',
                              '*'         => 'T_MULTIPLY',
                              '%'         => 'T_MODULUS',
                              '/'         => 'T_DIVIDE',
                              '^'         => 'T_POWER',
                              ','         => 'T_COMMA',
                              ';'         => 'T_SEMICOLON',
                              ':'         => 'T_COLON',
                              '<'         => 'T_LESS_THAN',
                              '>'         => 'T_GREATER_THAN',
                              '<='        => 'T_IS_SMALLER_OR_EQUAL',
                              '>='        => 'T_IS_GREATER_OR_EQUAL',
                              '!'         => 'T_BOOLEAN_NOT',
                              '||'        => 'T_BOOLEAN_OR',
                              '&&'        => 'T_BOOLEAN_AND',
                              '|'         => 'T_BITWISE_OR',
                              '&'         => 'T_BITWISE_AND',
                              '!='        => 'T_IS_NOT_EQUAL',
                              '!=='       => 'T_IS_NOT_IDENTICAL',
                              '='         => 'T_EQUAL',
                              '=='        => 'T_IS_EQUAL',
                              '==='       => 'T_IS_IDENTICAL',
                              '-='        => 'T_MINUS_EQUAL',
                              '+='        => 'T_PLUS_EQUAL',
                              '*='        => 'T_MUL_EQUAL',
                              '/='        => 'T_DIV_EQUAL',
                              '%='        => 'T_MOD_EQUAL',
                              '++'        => 'T_INC',
                              '--'        => 'T_DEC',
                              '//'        => 'T_COMMENT',
                              '/*'        => 'T_COMMENT',
                              '/**'       => 'T_DOC_COMMENT',
                              '*/'        => 'T_COMMENT',
                             );

    /**
     * A list string delimiters.
     *
     * @var array
     */
    protected $stringTokens = array(
                               '\'',
                               '"',
                              );

    /**
     * A list tokens that start and end comments.
     *
     * @var array
     */
    protected $commentTokens = array(
                                '//'  => null,
                                '/*'  => '*/',
                                '/**' => '*/',
                               );


    /**
     * Creates an array of tokens when given some PHP code.
     *
     * Starts by using token_get_all() but does a lot of extra processing
     * to insert information about the context of the token.
     *
     * @param string $string  The string to tokenize.
     * @param string $eolChar The EOL character to use for splitting strings.
     *
     * @return array
     */
    public function tokenizeString($string, $eolChar='\n')
    {
        if (PHP_CODESNIFFER_VERBOSITY > 1) {
            echo "\t*** START JS TOKENIZING ***".PHP_EOL;
        }

        $tokenTypes = array_keys($this->tokenValues);

        $maxTokenLength = 0;
        foreach ($tokenTypes as $token) {
            if (strlen($token) > $maxTokenLength) {
                $maxTokenLength = strlen($token);
            }
        }

        $tokens          = array();
        $inString        = '';
        $stringChar      = null;
        $inComment       = '';
        $buffer          = '';
        $preStringBuffer = '';
        $cleanBuffer     = false;

        $tokens[] = array(
                     'code'    => T_OPEN_TAG,
                     'type'    => 'T_OPEN_TAG',
                     'content' => '',
                    );

        // Convert newlines to single characters for ease of
        // processing. We will change them back later.
        $string = str_replace($eolChar, "\n", $string);

        $chars    = str_split($string);
        $numChars = count($chars);
        for ($i = 0; $i < $numChars; $i++) {
            $char = $chars[$i];

            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                $content = str_replace("\n", '\n', $char);
                $bufferContent = str_replace("\n", '\n', $buffer);
                if ($inString !== '') {
                    echo "\t";
                }

                if ($inComment !== '') {
                    echo "\t";
                }

                echo "\tProcess char $i => $content (buffer: $bufferContent)".PHP_EOL;
            }

            if ($inString === '' && $inComment === '' && $buffer !== '') {
                // If the buffer only has whitespace and we are about to
                // add a character, store the whitespace first.
                if (trim($char) !== '' && trim($buffer) === '') {
                    $tokens[] = array(
                                 'code'    => T_WHITESPACE,
                                 'type'    => 'T_WHITESPACE',
                                 'content' => str_replace("\n", $eolChar, $buffer),
                                );

                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        $content = str_replace("\n", '\n', $buffer);
                        echo "\t=> Added token T_WHITESPACE ($content)".PHP_EOL;
                    }

                    $buffer = '';
                }

                // If the buffer is not whitespace and we are about to
                // add a whitespace character, store the content first.
                if ($inString === ''
                    && $inComment === ''
                    && trim($char) === ''
                    && trim($buffer) !== ''
                ) {
                    $tokens[] = array(
                                 'code'    => T_STRING,
                                 'type'    => 'T_STRING',
                                 'content' => str_replace("\n", $eolChar, $buffer),
                                );

                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        $content = str_replace("\n", '\n', $buffer);
                        echo "\t=> Added token T_STRING ($content)".PHP_EOL;
                    }

                    $buffer = '';
                }
            }//end if

            // Process strings.
            if ($inComment === '' && in_array($char, $this->stringTokens) === true) {
                if ($inString === $char) {
                    // This could be the end of the string, but make sure it
                    // is not escaped first.
                    $escapes = 0;
                    for ($x = ($i - 1); $x >= 0; $x--) {
                        if ($chars[$x] !== '\\') {
                            break;
                        }

                        $escapes++;
                    }

                    if ($escapes === 0 || ($escapes % 2) === 0) {
                        // There is an even number escape chars,
                        // so this is not escaped, it is the end of the string.
                        $tokens[] = array(
                                     'code'    => T_CONSTANT_ENCAPSED_STRING,
                                     'type'    => 'T_CONSTANT_ENCAPSED_STRING',
                                     'content' => str_replace("\n", $eolChar, $buffer).$char,
                                    );

                        if (PHP_CODESNIFFER_VERBOSITY > 1) {
                            echo "\t\t* found end of string *".PHP_EOL;
                            $content = str_replace("\n", '\n', $buffer.$char);
                            echo "\t=> Added token T_CONSTANT_ENCAPSED_STRING ($content)".PHP_EOL;
                        }

                        $buffer          = '';
                        $preStringBuffer = '';
                        $inString        = '';
                        $stringChar      = null;
                        continue;
                    }
                } else if ($inString === '') {
                    $inString        = $char;
                    $stringChar      = $i;
                    $preStringBuffer = $buffer;

                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        echo "\t\t* looking for string closer *".PHP_EOL;
                    }
                }//end if
            }//end if

            if ($inString !== '' && $char === "\n") {
                // Unless this newline character is escaped, the string did not
                // end before the end of the line, which means it probably
                // wasn't a string at all (maybe a regex).
                if ($chars[($i - 1)] !== '\\') {
                    $i               = $stringChar;
                    $buffer          = $preStringBuffer;
                    $preStringBuffer = '';
                    $inString        = '';
                    $stringChar      = null;
                    $char            = $chars[$i];

                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        echo "\t\t* found newline before end of string, bailing *".PHP_EOL;
                    }
                }
            }

            $buffer .= $char;

            // We don't look for special tokens inside strings,
            // so if we are in a string, we can continue here now
            // that the current char is in the buffer.
            if ($inString !== '') {
                continue;
            }

            // Special case for T_DIVIDE which can actually be
            // the start of a regular expression.
            if ($char === '/') {
                $regex = $this->getRegexToken(
                    $i,
                    $string,
                    $chars,
                    $tokens,
                    $eolChar
                );

                if ($regex !== null) {
                    $tokens[] = array(
                                 'code'    => T_REGULAR_EXPRESSION,
                                 'type'    => 'T_REGULAR_EXPRESSION',
                                 'content' => $regex['content'],
                                );

                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        $content = str_replace("\n", '\n', $regex['content']);
                        echo "\t=> Added token T_REGULAR_EXPRESSION ($content)".PHP_EOL;
                    }

                    $i = $regex['end'];
                    $buffer = '';
                    $cleanBuffer = false;
                    continue;
                }
            }//end if

            // Check for known tokens, but ignore tokens found that are not at
            // the end of a string, like FOR and this.FORmat.
            if (in_array(strtolower($buffer), $tokenTypes) === true
                && (preg_match('|[a-zA-z0-9_]|', $char) === 0
                || isset($chars[($i + 1)]) === false
                || preg_match('|[a-zA-z0-9_]|', $chars[($i + 1)]) === 0)
            ) {
                $matchedToken    = false;
                $lookAheadLength = ($maxTokenLength - strlen($buffer));

                if ($lookAheadLength > 0) {
                    // The buffer contains a token type, but we need
                    // to look ahead at the next chars to see if this is
                    // actually part of a larger token. For example,
                    // FOR and FOREACH.
                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        echo "\t\t* buffer possibly contains token, looking ahead $lookAheadLength chars *".PHP_EOL;
                    }

                    $charBuffer = $buffer;
                    for ($x = 1; $x <= $lookAheadLength; $x++) {
                        if (isset($chars[($i + $x)]) === false) {
                            break;
                        }

                        $charBuffer .= $chars[($i + $x)];

                        if (PHP_CODESNIFFER_VERBOSITY > 1) {
                            $content = str_replace("\n", '\n', $charBuffer);
                            echo "\t\t=> Looking ahead $x chars => $content".PHP_EOL;
                        }

                        if (in_array(strtolower($charBuffer), $tokenTypes) === true) {
                            // We've found something larger that matches
                            // so we can ignore this char. Except for 1 very specific
                            // case where a comment like /**/ needs to tokenize as
                            // T_COMMENT and not T_DOC_COMMENT.
                            $oldType = $this->tokenValues[strtolower($buffer)];
                            $newType = $this->tokenValues[strtolower($charBuffer)];
                            if ($oldType === 'T_COMMENT'
                                && $newType === 'T_DOC_COMMENT'
                                && $chars[($i + $x + 1)] === '/'
                            ) {
                                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                                    echo "\t\t* look ahead ignored T_DOC_COMMENT, continuing *".PHP_EOL;
                                }
                            } else {
                                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                                    echo "\t\t* look ahead found more specific token ($newType), ignoring $i *".PHP_EOL;
                                }

                                $matchedToken = true;
                                break;
                            }
                        }
                    }//end for
                }//end if

                if ($matchedToken === false) {
                    if (PHP_CODESNIFFER_VERBOSITY > 1 && $lookAheadLength > 0) {
                        echo "\t\t* look ahead found nothing *".PHP_EOL;
                    }

                    $value    = $this->tokenValues[strtolower($buffer)];
                    $tokens[] = array(
                                 'code'    => constant($value),
                                 'type'    => $value,
                                 'content' => $buffer,
                                );

                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        $content = str_replace("\n", '\n', $buffer);
                        echo "\t=> Added token $value ($content)".PHP_EOL;
                    }

                    $cleanBuffer = true;
                }//end if
            } else if (in_array(strtolower($char), $tokenTypes) === true) {
                // No matter what token we end up using, we don't
                // need the content in the buffer any more because we have
                // found a valid token.
                $newContent = substr(str_replace("\n", $eolChar, $buffer), 0, -1);
                if ($newContent !== '') {
                    $tokens[] = array(
                                 'code'    => T_STRING,
                                 'type'    => 'T_STRING',
                                 'content' => $newContent,
                                );

                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        $content = str_replace("\n", '\n', substr($buffer, 0, -1));
                        echo "\t=> Added token T_STRING ($content)".PHP_EOL;
                    }
                }

                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                    echo "\t\t* char is token, looking ahead ".($maxTokenLength - 1).' chars *'.PHP_EOL;
                }

                // The char is a token type, but we need to look ahead at the
                // next chars to see if this is actually part of a larger token.
                // For example, = and ===.
                $charBuffer   = $char;
                $matchedToken = false;
                for ($x = 1; $x <= $maxTokenLength; $x++) {
                    if (isset($chars[($i + $x)]) === false) {
                        break;
                    }

                    $charBuffer .= $chars[($i + $x)];

                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        $content = str_replace("\n", '\n', $charBuffer);
                        echo "\t\t=> Looking ahead $x chars => $content".PHP_EOL;
                    }

                    if (in_array(strtolower($charBuffer), $tokenTypes) === true) {
                        // We've found something larger that matches
                        // so we can ignore this char.
                        if (PHP_CODESNIFFER_VERBOSITY > 1) {
                            $type = $this->tokenValues[strtolower($charBuffer)];
                            echo "\t\t* look ahead found more specific token ($type), ignoring $i *".PHP_EOL;
                        }

                        $matchedToken = true;
                        break;
                    }
                }//end for

                if ($matchedToken === false) {
                    $value    = $this->tokenValues[strtolower($char)];
                    $tokens[] = array(
                                 'code'    => constant($value),
                                 'type'    => $value,
                                 'content' => $char,
                                );

                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        echo "\t\t* look ahead found nothing *".PHP_EOL;
                        $content = str_replace("\n", '\n', $char);
                        echo "\t=> Added token $value ($content)".PHP_EOL;
                    }

                    $cleanBuffer = true;
                } else {
                    $buffer = $char;
                }
            }//end if

            // Keep track of content inside comments.
            if ($inComment === ''
                && array_key_exists($buffer, $this->commentTokens) === true
            ) {
                // This is not really a comment if the content
                // looks like \// (i.e., it is escaped).
                if (isset($chars[($i - 2)]) === true && $chars[($i - 2)] === '\\') {
                    $lastToken   = array_pop($tokens);
                    $lastContent = $lastToken['content'];
                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        $value   = $this->tokenValues[strtolower($lastContent)];
                        $content = str_replace("\n", '\n', $lastContent);
                        echo "\t=> Removed token $value ($content)".PHP_EOL;
                    }

                    $lastChars    = str_split($lastContent);
                    $lastNumChars = count($lastChars);
                    for ($x = 0; $x < $lastNumChars; $x++) {
                        $lastChar = $lastChars[$x];
                        $value    = $this->tokenValues[strtolower($lastChar)];
                        $tokens[] = array(
                                     'code'    => constant($value),
                                     'type'    => $value,
                                     'content' => $lastChar,
                                    );

                        if (PHP_CODESNIFFER_VERBOSITY > 1) {
                            $content = str_replace("\n", '\n', $lastChar);
                            echo "\t=> Added token $value ($content)".PHP_EOL;
                        }
                    }
                } else {
                    // We have started a comment.
                    $inComment = $buffer;

                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        echo "\t\t* looking for end of comment *".PHP_EOL;
                    }
                }
            } else if ($inComment !== '') {
                if ($this->commentTokens[$inComment] === null) {
                    // Comment ends at the next newline.
                    if (strpos($buffer, "\n") !== false) {
                        $inComment = '';
                    }
                } else {
                    if ($this->commentTokens[$inComment] === $buffer) {
                        $inComment = '';
                    }
                }

                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                    if ($inComment === '') {
                        echo "\t\t* found end of comment *".PHP_EOL;
                    }
                }

                if ($inComment === '' && $cleanBuffer === false) {
                    $tokens[] = array(
                                 'code'    => T_STRING,
                                 'type'    => 'T_STRING',
                                 'content' => str_replace("\n", $eolChar, $buffer),
                                );

                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        $content = str_replace("\n", '\n', $buffer);
                        echo "\t=> Added token T_STRING ($content)".PHP_EOL;
                    }

                    $buffer = '';
                }
            }//end if

            if ($cleanBuffer === true) {
                $buffer      = '';
                $cleanBuffer = false;
            }
        }//end foreach

        if (empty($buffer) === false) {
            // Buffer contains whitespace from the end of the file.
            $tokens[] = array(
                         'code'    => T_WHITESPACE,
                         'type'    => 'T_WHITESPACE',
                         'content' => str_replace("\n", $eolChar, $buffer),
                        );

            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                $content = str_replace($eolChar, '\n', $buffer);
                echo "\t=> Added token T_WHITESPACE ($content)".PHP_EOL;
            }
        }

        $tokens[] = array(
                     'code'    => T_CLOSE_TAG,
                     'type'    => 'T_CLOSE_TAG',
                     'content' => '',
                    );

        /*
            Now that we have done some basic tokenizing, we need to
            modify the tokens to join some together and split some apart
            so they match what the PHP tokenizer does.
        */

        $finalTokens = array();
        $newStackPtr = 0;
        $numTokens   = count($tokens);
        for ($stackPtr = 0; $stackPtr < $numTokens; $stackPtr++) {
            $token = $tokens[$stackPtr];

            /*
                Look for comments and join the tokens together.
            */

            if (array_key_exists($token['content'], $this->commentTokens) === true) {
                $newContent   = '';
                $tokenContent = $token['content'];
                $endContent   = $this->commentTokens[$tokenContent];
                while ($tokenContent !== $endContent) {
                    if ($endContent === null
                        && strpos($tokenContent, $eolChar) !== false
                    ) {
                        // A null end token means the comment ends at the end of
                        // the line so we look for newlines and split the token.
                        $tokens[$stackPtr]['content'] = substr(
                            $tokenContent,
                            (strpos($tokenContent, $eolChar) + strlen($eolChar))
                        );

                        $tokenContent = substr(
                            $tokenContent,
                            0,
                            (strpos($tokenContent, $eolChar) + strlen($eolChar))
                        );

                        // If the substr failed, skip the token as the content
                        // will now be blank.
                        if ($tokens[$stackPtr]['content'] !== false) {
                            $stackPtr--;
                        }

                        break;
                    }//end if

                    $stackPtr++;
                    $newContent  .= $tokenContent;
                    if (isset($tokens[$stackPtr]) === false) {
                        break;
                    }

                    $tokenContent = $tokens[$stackPtr]['content'];
                }//end while

                // Save the new content in the current token so
                // the code below can chop it up on newlines.
                $token['content'] = $newContent.$tokenContent;
            }//end if

            /*
                If this token has newlines in its content, split each line up
                and create a new token for each line. We do this so it's easier
                to ascertain where errors occur on a line.
                Note that $token[1] is the token's content.
            */

            if (strpos($token['content'], $eolChar) !== false) {
                $tokenLines = explode($eolChar, $token['content']);
                $numLines   = count($tokenLines);

                for ($i = 0; $i < $numLines; $i++) {
                    $newToken['content'] = $tokenLines[$i];
                    if ($i === ($numLines - 1)) {
                        if ($tokenLines[$i] === '') {
                            break;
                        }
                    } else {
                        $newToken['content'] .= $eolChar;
                    }

                    $newToken['type']          = $token['type'];
                    $newToken['code']          = $token['code'];
                    $finalTokens[$newStackPtr] = $newToken;
                    $newStackPtr++;
                }
            } else {
                $finalTokens[$newStackPtr] = $token;
                $newStackPtr++;
            }//end if

            // Convert numbers, including decimals.
            if ($token['code'] === T_STRING
                || $token['code'] === T_OBJECT_OPERATOR
            ) {
                $newContent  = '';
                $oldStackPtr = $stackPtr;
                while (preg_match('|^[0-9\.]+$|', $tokens[$stackPtr]['content']) !== 0) {
                    $newContent .= $tokens[$stackPtr]['content'];
                    $stackPtr++;
                }

                if ($newContent !== '' && $newContent !== '.') {
                    $finalTokens[($newStackPtr - 1)]['content'] = $newContent;
                    if (ctype_digit($newContent) === true) {
                        $finalTokens[($newStackPtr - 1)]['code']
                            = constant('T_LNUMBER');
                        $finalTokens[($newStackPtr - 1)]['type'] = 'T_LNUMBER';
                    } else {
                        $finalTokens[($newStackPtr - 1)]['code']
                            = constant('T_DNUMBER');
                        $finalTokens[($newStackPtr - 1)]['type'] = 'T_DNUMBER';
                    }

                    $stackPtr--;
                } else {
                    $stackPtr = $oldStackPtr;
                }
            }//end if
        }//end for

        if (PHP_CODESNIFFER_VERBOSITY > 1) {
            echo "\t*** END TOKENIZING ***".PHP_EOL;
        }

        return $finalTokens;

    }//end tokenizeString()


    /**
     * Tokenizes a regular expression if one is found.
     *
     * If a regular expression is not found, NULL is returned.
     *
     * @param string $char    The index of the possible regex start character.
     * @param string $string  The complete content of the string being tokenized.
     * @param string $chars   An array of characters being tokenized.
     * @param string $tokens  The current array of tokens found in the string.
     * @param string $eolChar The EOL character to use for splitting strings.
     *
     * @return void
     */
    public function getRegexToken($char, $string, $chars, $tokens, $eolChar)
    {
        $beforeTokens = array(
                         T_EQUAL,
                         T_OPEN_PARENTHESIS,
                         T_RETURN,
                         T_BOOLEAN_OR,
                         T_BOOLEAN_AND,
                         T_BITWISE_OR,
                         T_BITWISE_AND,
                         T_COMMA,
                         T_COLON,
                         T_TYPEOF,
                        );

        $afterTokens = array(
                        ',',
                        ')',
                        ';',
                        ' ',
                        '.',
                        $eolChar,
                       );

        // Find the last non-whitespace token that was added
        // to the tokens array.
        $numTokens = count($tokens);
        for ($prev = ($numTokens - 1); $prev >= 0; $prev--) {
            if (in_array($tokens[$prev]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
                break;
            }
        }

        if (in_array($tokens[$prev]['code'], $beforeTokens) === false) {
            return null;
        }

        // This is probably a regular expression, so look for the end of it.
        if (PHP_CODESNIFFER_VERBOSITY > 1) {
            $content = str_replace("\n", '\n', $char);
            echo "\t* token possibly starts a regular expression *".PHP_EOL;
        }

        $numChars = count($chars);
        for ($next = ($char + 1); $next < $numChars; $next++) {
            if ($chars[$next] === '/') {
                // Just make sure this is not escaped first.
                if ($chars[($next - 1)] !== '\\') {
                    // In the simple form: /.../ so we found the end.
                    break;
                } else if ($chars[($next - 2)] === '\\') {
                    // In the form: /...\\/ so we found the end.
                    break;
                }
            } else {
                $possibleEolChar = substr($string, $next, strlen($eolChar));
                if ($possibleEolChar === $eolChar) {
                    // This is the last token on the line and regular
                    // expressions need to be defined on a single line,
                    // so this is not a regular expression.
                    break;
                }
            }
        }

        if ($chars[$next] !== '/') {
            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                echo "\t* could not find end of regular expression *".PHP_EOL;
            }

            return null;
        }

        while (preg_match('|[a-zA-Z]|', $chars[($next + 1)]) !== 0) {
            // The token directly after the end of the regex can
            // be modifiers like global and case insensitive
            // (.e.g, /pattern/gi).
            $next++;
        }

        $regexEnd = $next;
        if (PHP_CODESNIFFER_VERBOSITY > 1) {
            echo "\t* found end of regular expression at token $regexEnd *".PHP_EOL;
        }

        for ($next = ($next + 1); $next < $numChars; $next++) {
            if ($chars[$next] !== ' ') {
                break;
            } else {
                $possibleEolChar = substr($string, $next, strlen($eolChar));
                if ($possibleEolChar === $eolChar) {
                    // This is the last token on the line.
                    break;
                }
            }
        }

        if (in_array($chars[$next], $afterTokens) === false) {
            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                echo "\t* tokens after regular expression do not look correct *".PHP_EOL;
            }

            return null;
        }

        // This is a regular expression, so join all the tokens together.
        $content = '';
        for ($x = $char; $x <= $regexEnd; $x++) {
            $content .= $chars[$x];
        }

        $token = array(
                  'start'   => $char,
                  'end'     => $regexEnd,
                  'content' => $content,
                 );

        return $token;

    }//end getRegexToken()


    /**
     * Performs additional processing after main tokenizing.
     *
     * This additional processing looks for properties, labels and objects.
     *
     * @param array  &$tokens The array of tokens to process.
     * @param string $eolChar The EOL character to use for splitting strings.
     *
     * @return void
     */
    public function processAdditional(&$tokens, $eolChar)
    {
        if (PHP_CODESNIFFER_VERBOSITY > 1) {
            echo "\t*** START ADDITIONAL JS PROCESSING ***".PHP_EOL;
        }

        $numTokens  = count($tokens);
        $classStack = array();

        for ($i = 0; $i < $numTokens; $i++) {
            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                $type    = $tokens[$i]['type'];
                $content = str_replace($eolChar, '\n', $tokens[$i]['content']);
                echo str_repeat("\t", count($classStack));

                echo "\tProcess token $i: $type => $content".PHP_EOL;
            }

            if ($tokens[$i]['code'] === T_OPEN_CURLY_BRACKET
                && isset($tokens[$i]['scope_condition']) === false
            ) {
                $classStack[] = $i;
                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                    echo str_repeat("\t", count($classStack));
                    echo "\t=> Found property opener".PHP_EOL;
                }

                // This could also be an object definition.
                for ($x = ($i - 1); $x >= 0; $x--) {
                    if (in_array($tokens[$x]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
                        // Non-whitespace content.
                        break;
                    }
                }

                if ($tokens[$x]['code'] === T_EQUAL) {
                    for ($x--; $x >= 0; $x--) {
                        if (in_array($tokens[$x]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
                            break;
                        }
                    }

                    if ($tokens[$x]['code'] === T_STRING
                        || $tokens[$x]['code'] === T_PROTOTYPE
                    ) {
                        // Find the first string in this definition.
                        // E.g., WantedString.DontWantThis.prototype
                        for ($x--; $x >= 0; $x--) {
                            $wantedTokens = array(
                                             T_STRING,
                                             T_PROTOTYPE,
                                             T_OBJECT_OPERATOR,
                                            );

                            if (in_array($tokens[$x]['code'], $wantedTokens) === false) {
                                $x++;
                                break;
                            }
                        }

                        $closer = $tokens[$i]['bracket_closer'];
                        $tokens[$i]['scope_condition']      = $x;
                        $tokens[$i]['scope_closer']         = $closer;
                        $tokens[$closer]['scope_condition'] = $x;
                        $tokens[$closer]['scope_opener']    = $i;
                        $tokens[$x]['scope_opener']         = $i;
                        $tokens[$x]['scope_closer']         = $closer;
                        $tokens[$x]['code']                 = T_OBJECT;
                        $tokens[$x]['type']                 = 'T_OBJECT';

                        if (PHP_CODESNIFFER_VERBOSITY > 1) {
                            echo str_repeat("\t", count($classStack));
                            echo "\t* token $x converted from T_STRING to T_OBJECT *".PHP_EOL;
                            echo str_repeat("\t", count($classStack));
                            echo "\t* set scope opener ($i) and closer ($closer) for token $x *".PHP_EOL;
                        }
                    }//end if
                }//end if
            } else if ($tokens[$i]['code'] === T_CLOSE_CURLY_BRACKET
                && (isset($tokens[$i]['scope_condition']) === false
                || $tokens[$tokens[$i]['scope_condition']]['code'] === T_OBJECT)
            ) {
                $opener = array_pop($classStack);

                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                    echo str_repeat("\t", count($classStack));
                    echo "\t\t=> Found property closer for $opener".PHP_EOL;
                }
            } else if ($tokens[$i]['code'] === T_COLON) {
                // If it is a scope opener, it belongs to a
                // DEFAULT or CASE statement.
                if (isset($tokens[$i]['scope_condition']) === true) {
                    continue;
                }

                // Make sure this is not part of an inline IF statement.
                for ($x = ($i - 1); $x >= 0; $x--) {
                    if ($tokens[$x]['code'] === T_INLINE_THEN) {
                        $tokens[$i]['code'] = T_INLINE_ELSE;
                        $tokens[$i]['type'] = 'T_INLINE_ELSE';

                        if (PHP_CODESNIFFER_VERBOSITY > 1) {
                            echo str_repeat("\t", count($classStack));
                            echo "\t* token $i converted from T_COLON to T_INLINE_THEN *".PHP_EOL;
                        }

                        continue(2);
                    } else if ($tokens[$x]['line'] < $tokens[$i]['line']) {
                        break;
                    }
                }

                // The string to the left of the colon is either a property or label.
                for ($label = ($i - 1); $label >= 0; $label--) {
                    if (in_array($tokens[$label]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
                        break;
                    }
                }

                if ($tokens[$label]['code'] !== T_STRING) {
                    continue;
                }

                if (empty($classStack) === false) {
                    $tokens[$label]['code'] = T_PROPERTY;
                    $tokens[$label]['type'] = 'T_PROPERTY';

                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        echo str_repeat("\t", count($classStack));
                        echo "\t* token $label converted from T_STRING to T_PROPERTY *".PHP_EOL;
                    }

                    // If the net token after the colon is a curly brace,
                    // this property is actually an object, so we can give it
                    // and opener and closer.
                    for ($x = ($i + 1); $x < $numTokens; $x++) {
                        if (in_array($tokens[$x]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
                            break;
                        }
                    }

                    if ($tokens[$x]['code'] === T_OPEN_CURLY_BRACKET) {
                        $closer = $tokens[$x]['bracket_closer'];
                        $tokens[$label]['scope_opener']     = $x;
                        $tokens[$label]['scope_closer']     = $closer;
                        $tokens[$x]['scope_condition']      = $label;
                        $tokens[$x]['scope_closer']         = $closer;
                        $tokens[$closer]['scope_condition'] = $label;
                        $tokens[$closer]['scope_opener']    = $x;
                        if (PHP_CODESNIFFER_VERBOSITY > 1) {
                            echo str_repeat("\t", count($classStack));
                            echo "\t* set scope opener ($x) and closer ($closer) for token $label *".PHP_EOL;
                        }
                    }
                } else {
                    $tokens[$label]['code'] = T_LABEL;
                    $tokens[$label]['type'] = 'T_LABEL';

                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        echo str_repeat("\t", count($classStack));
                        echo "\t* token $label converted from T_STRING to T_LABEL *".PHP_EOL;
                    }
                }
            }//end if
        }//end for

        if (PHP_CODESNIFFER_VERBOSITY > 1) {
            echo "\t*** END ADDITIONAL JS PROCESSING ***".PHP_EOL;
        }

    }//end processAdditional()


}//end class

?>
<?php
/**
 * Tokenizes PHP code.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Tokenizes PHP code.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_Tokenizers_PHP
{

    /**
     * A list of tokens that are allowed to open a scope.
     *
     * This array also contains information about what kind of token the scope
     * opener uses to open and close the scope, if the token strictly requires
     * an opener, if the token can share a scope closer, and who it can be shared
     * with. An example of a token that shares a scope closer is a CASE scope.
     *
     * @var array
     */
    public $scopeOpeners = array(
                            T_IF            => array(
                                                'start'  => array(
                                                             T_OPEN_CURLY_BRACKET,
                                                             T_COLON,
                                                            ),
                                                'end'    => array(
                                                             T_CLOSE_CURLY_BRACKET,
                                                             T_ENDIF,
                                                            ),
                                                'strict' => false,
                                                'shared' => false,
                                                'with'   => array(),
                                               ),
                            T_TRY           => array(
                                                'start'  => array(T_OPEN_CURLY_BRACKET),
                                                'end'    => array(T_CLOSE_CURLY_BRACKET),
                                                'strict' => true,
                                                'shared' => false,
                                                'with'   => array(),
                                               ),
                            T_CATCH         => array(
                                                'start'  => array(T_OPEN_CURLY_BRACKET),
                                                'end'    => array(T_CLOSE_CURLY_BRACKET),
                                                'strict' => true,
                                                'shared' => false,
                                                'with'   => array(),
                                               ),
                            T_FINALLY       => array(
                                                'start'  => array(T_OPEN_CURLY_BRACKET),
                                                'end'    => array(T_CLOSE_CURLY_BRACKET),
                                                'strict' => true,
                                                'shared' => false,
                                                'with'   => array(),
                                               ),
                            T_ELSE          => array(
                                                'start'  => array(T_OPEN_CURLY_BRACKET),
                                                'end'    => array(T_CLOSE_CURLY_BRACKET),
                                                'strict' => false,
                                                'shared' => false,
                                                'with'   => array(),
                                               ),
                            T_ELSEIF        => array(
                                                'start'  => array(T_OPEN_CURLY_BRACKET),
                                                'end'    => array(T_CLOSE_CURLY_BRACKET),
                                                'strict' => false,
                                                'shared' => false,
                                                'with'   => array(),
                                               ),
                            T_FOR           => array(
                                                'start'  => array(
                                                             T_OPEN_CURLY_BRACKET,
                                                             T_COLON,
                                                            ),
                                                'end'    => array(
                                                             T_CLOSE_CURLY_BRACKET,
                                                             T_ENDFOR,
                                                            ),
                                                'strict' => false,
                                                'shared' => false,
                                                'with'   => array(),
                                               ),
                            T_FOREACH       => array(
                                                'start'  => array(
                                                             T_OPEN_CURLY_BRACKET,
                                                             T_COLON,
                                                            ),
                                                'end'    => array(
                                                             T_CLOSE_CURLY_BRACKET,
                                                             T_ENDFOREACH,
                                                            ),
                                                'strict' => false,
                                                'shared' => false,
                                                'with'   => array(),
                                               ),
                            T_INTERFACE     => array(
                                                'start'  => array(T_OPEN_CURLY_BRACKET),
                                                'end'    => array(T_CLOSE_CURLY_BRACKET),
                                                'strict' => true,
                                                'shared' => false,
                                                'with'   => array(),
                                               ),
                            T_FUNCTION      => array(
                                                'start'  => array(T_OPEN_CURLY_BRACKET),
                                                'end'    => array(T_CLOSE_CURLY_BRACKET),
                                                'strict' => true,
                                                'shared' => false,
                                                'with'   => array(),
                                               ),
                            T_CLASS         => array(
                                                'start'  => array(T_OPEN_CURLY_BRACKET),
                                                'end'    => array(T_CLOSE_CURLY_BRACKET),
                                                'strict' => true,
                                                'shared' => false,
                                                'with'   => array(),
                                               ),
                            T_TRAIT         => array(
                                                'start'  => array(T_OPEN_CURLY_BRACKET),
                                                'end'    => array(T_CLOSE_CURLY_BRACKET),
                                                'strict' => true,
                                                'shared' => false,
                                                'with'   => array(),
                                               ),
                            T_NAMESPACE     => array(
                                                'start'  => array(T_OPEN_CURLY_BRACKET),
                                                'end'    => array(T_CLOSE_CURLY_BRACKET),
                                                'strict' => false,
                                                'shared' => false,
                                                'with'   => array(),
                                               ),
                            T_WHILE         => array(
                                                'start'  => array(
                                                             T_OPEN_CURLY_BRACKET,
                                                             T_COLON,
                                                            ),
                                                'end'    => array(
                                                             T_CLOSE_CURLY_BRACKET,
                                                             T_ENDWHILE,
                                                            ),
                                                'strict' => false,
                                                'shared' => false,
                                                'with'   => array(),
                                               ),
                            T_DO            => array(
                                                'start'  => array(T_OPEN_CURLY_BRACKET),
                                                'end'    => array(T_CLOSE_CURLY_BRACKET),
                                                'strict' => true,
                                                'shared' => false,
                                                'with'   => array(),
                                               ),
                            T_SWITCH        => array(
                                                'start'  => array(T_OPEN_CURLY_BRACKET),
                                                'end'    => array(T_CLOSE_CURLY_BRACKET),
                                                'strict' => true,
                                                'shared' => false,
                                                'with'   => array(),
                                               ),
                            T_CASE          => array(
                                                'start'  => array(
                                                             T_COLON,
                                                             T_SEMICOLON,
                                                            ),
                                                'end'    => array(
                                                             T_BREAK,
                                                             T_RETURN,
                                                             T_CONTINUE,
                                                             T_THROW,
                                                             T_EXIT,
                                                            ),
                                                'strict' => true,
                                                'shared' => true,
                                                'with'   => array(
                                                             T_DEFAULT,
                                                             T_CASE,
                                                             T_SWITCH,
                                                            ),
                                               ),
                            T_DEFAULT       => array(
                                                'start'  => array(T_COLON),
                                                'end'    => array(
                                                             T_BREAK,
                                                             T_RETURN,
                                                             T_CONTINUE,
                                                             T_THROW,
                                                             T_EXIT,
                                                            ),
                                                'strict' => true,
                                                'shared' => true,
                                                'with'   => array(
                                                             T_CASE,
                                                             T_SWITCH,
                                                            ),
                                               ),
                            T_START_HEREDOC => array(
                                                'start'  => array(T_START_HEREDOC),
                                                'end'    => array(T_END_HEREDOC),
                                                'strict' => true,
                                                'shared' => false,
                                                'with'   => array(),
                                               ),
                           );

    /**
     * A list of tokens that end the scope.
     *
     * This array is just a unique collection of the end tokens
     * from the _scopeOpeners array. The data is duplicated here to
     * save time during parsing of the file.
     *
     * @var array
     */
    public $endScopeTokens = array(
                              T_CLOSE_CURLY_BRACKET,
                              T_BREAK,
                              T_END_HEREDOC,
                             );


    /**
     * Creates an array of tokens when given some PHP code.
     *
     * Starts by using token_get_all() but does a lot of extra processing
     * to insert information about the context of the token.
     *
     * @param string $string  The string to tokenize.
     * @param string $eolChar The EOL character to use for splitting strings.
     *
     * @return array
     */
    public function tokenizeString($string, $eolChar='\n')
    {
        $tokens      = @token_get_all($string);
        $finalTokens = array();

        $newStackPtr = 0;
        $numTokens   = count($tokens);

        $insideInlineIf = false;

        for ($stackPtr = 0; $stackPtr < $numTokens; $stackPtr++) {
            $token        = $tokens[$stackPtr];
            $tokenIsArray = is_array($token);

            /*
                If we are using \r\n newline characters, the \r and \n are sometimes
                split over two tokens. This normally occurs after comments. We need
                to merge these two characters together so that our line endings are
                consistent for all lines.
            */

            if ($tokenIsArray === true && substr($token[1], -1) === "\r") {
                if (isset($tokens[($stackPtr + 1)]) === true
                    && is_array($tokens[($stackPtr + 1)]) === true
                    && $tokens[($stackPtr + 1)][1][0] === "\n"
                ) {
                    $token[1] .= "\n";

                    if ($tokens[($stackPtr + 1)][1] === "\n") {
                        // The next token's content has been merged into this token,
                        // so we can skip it.
                        $stackPtr++;
                    } else {
                        $tokens[($stackPtr + 1)][1]
                            = substr($tokens[($stackPtr + 1)][1], 1);
                    }
                }
            }//end if

            /*
                If this is a double quoted string, PHP will tokenise the whole
                thing which causes problems with the scope map when braces are
                within the string. So we need to merge the tokens together to
                provide a single string.
            */

            if ($tokenIsArray === false && $token === '"') {
                $tokenContent = '"';
                $nestedVars   = array();
                for ($i = ($stackPtr + 1); $i < $numTokens; $i++) {
                    $subTokenIsArray = is_array($tokens[$i]);

                    if ($subTokenIsArray === true) {
                        $tokenContent .= $tokens[$i][1];
                        if ($tokens[$i][1] === '{'
                            && $tokens[$i][0] !== T_ENCAPSED_AND_WHITESPACE
                        ) {
                            $nestedVars[] = $i;
                        }
                    } else {
                        $tokenContent .= $tokens[$i];
                        if ($tokens[$i] === '}') {
                            array_pop($nestedVars);
                        }
                    }

                    if ($subTokenIsArray === false
                        && $tokens[$i] === '"'
                        && empty($nestedVars) === true
                    ) {
                        // We found the other end of the double quoted string.
                        break;
                    }
                }

                $stackPtr = $i;

                // Convert each line within the double quoted string to a
                // new token, so it conforms with other multiple line tokens.
                $tokenLines = explode($eolChar, $tokenContent);
                $numLines   = count($tokenLines);
                $newToken   = array();

                for ($j = 0; $j < $numLines; $j++) {
                    $newToken['content'] = $tokenLines[$j];
                    if ($j === ($numLines - 1)) {
                        if ($tokenLines[$j] === '') {
                            break;
                        }
                    } else {
                        $newToken['content'] .= $eolChar;
                    }

                    $newToken['code']          = T_DOUBLE_QUOTED_STRING;
                    $newToken['type']          = 'T_DOUBLE_QUOTED_STRING';
                    $finalTokens[$newStackPtr] = $newToken;
                    $newStackPtr++;
                }

                // Continue, as we're done with this token.
                continue;
            }//end if

            /*
                If this is a heredoc, PHP will tokenise the whole
                thing which causes problems when heredocs don't
                contain real PHP code, which is almost never.
                We want to leave the start and end heredoc tokens
                alone though.
            */

            if ($tokenIsArray === true && $token[0] === T_START_HEREDOC) {
                // Add the start heredoc token to the final array.
                $finalTokens[$newStackPtr]
                    = PHP_CodeSniffer::standardiseToken($token);

                // Check if this is actually a nowdoc and use a different token
                // to help the sniffs.
                $nowdoc = false;
                if ($token[1][3] === "'") {
                    $finalTokens[$newStackPtr]['code'] = T_START_NOWDOC;
                    $finalTokens[$newStackPtr]['type'] = 'T_START_NOWDOC';
                    $nowdoc = true;
                }

                $newStackPtr++;

                $tokenContent = '';
                for ($i = ($stackPtr + 1); $i < $numTokens; $i++) {
                    $subTokenIsArray = is_array($tokens[$i]);
                    if ($subTokenIsArray === true
                        && $tokens[$i][0] === T_END_HEREDOC
                    ) {
                        // We found the other end of the heredoc.
                        break;
                    }

                    if ($subTokenIsArray === true) {
                        $tokenContent .= $tokens[$i][1];
                    } else {
                        $tokenContent .= $tokens[$i];
                    }
                }

                $stackPtr = $i;

                // Convert each line within the heredoc to a
                // new token, so it conforms with other multiple line tokens.
                $tokenLines = explode($eolChar, $tokenContent);
                $numLines   = count($tokenLines);
                $newToken   = array();

                for ($j = 0; $j < $numLines; $j++) {
                    $newToken['content'] = $tokenLines[$j];
                    if ($j === ($numLines - 1)) {
                        if ($tokenLines[$j] === '') {
                            break;
                        }
                    } else {
                        $newToken['content'] .= $eolChar;
                    }

                    if ($nowdoc === true) {
                        $newToken['code'] = T_NOWDOC;
                        $newToken['type'] = 'T_NOWDOC';
                    } else {
                        $newToken['code'] = T_HEREDOC;
                        $newToken['type'] = 'T_HEREDOC';
                    }

                    $finalTokens[$newStackPtr] = $newToken;
                    $newStackPtr++;
                }

                // Add the end heredoc token to the final array.
                $finalTokens[$newStackPtr]
                    = PHP_CodeSniffer::standardiseToken($tokens[$stackPtr]);

                if ($nowdoc === true) {
                    $finalTokens[$newStackPtr]['code'] = T_END_NOWDOC;
                    $finalTokens[$newStackPtr]['type'] = 'T_END_NOWDOC';
                    $nowdoc = true;
                }

                $newStackPtr++;

                // Continue, as we're done with this token.
                continue;
            }//end if

            /*
                PHP doesn't assign a token to goto labels, so we have to.
                These are just string tokens with a single colon after them. Double
                colons are already tokenized and so don't interfere with this check.
                But we do have to account for CASE statements, that look just like
                goto labels.
            */

            if ($tokenIsArray === true
                && $token[0] === T_STRING
                && $tokens[($stackPtr + 1)] === ':'
                && $tokens[($stackPtr - 1)][0] !== T_PAAMAYIM_NEKUDOTAYIM
            ) {
                $stopTokens = array(
                               T_CASE,
                               T_SEMICOLON,
                               T_OPEN_CURLY_BRACKET,
                               T_INLINE_THEN,
                              );

                for ($x = ($newStackPtr - 1); $x > 0; $x--) {
                    if (in_array($finalTokens[$x]['code'], $stopTokens) === true) {
                        break;
                    }
                }

                if ($finalTokens[$x]['code'] !== T_CASE
                    && $finalTokens[$x]['code'] !== T_INLINE_THEN
                ) {
                    $finalTokens[$newStackPtr] = array(
                                                  'content' => $token[1].':',
                                                  'code'    => T_GOTO_LABEL,
                                                  'type'    => 'T_GOTO_LABEL',
                                                 );
                    $newStackPtr++;
                    $stackPtr++;
                    continue;
                }
            }//end if

            /*
                If this token has newlines in its content, split each line up
                and create a new token for each line. We do this so it's easier
                to ascertain where errors occur on a line.
                Note that $token[1] is the token's content.
            */

            if ($tokenIsArray === true && strpos($token[1], $eolChar) !== false) {
                $tokenLines = explode($eolChar, $token[1]);
                $numLines   = count($tokenLines);
                $tokenName  = token_name($token[0]);

                for ($i = 0; $i < $numLines; $i++) {
                    $newToken['content'] = $tokenLines[$i];
                    if ($i === ($numLines - 1)) {
                        if ($tokenLines[$i] === '') {
                            break;
                        }
                    } else {
                        $newToken['content'] .= $eolChar;
                    }

                    $newToken['type']          = $tokenName;
                    $newToken['code']          = $token[0];
                    $finalTokens[$newStackPtr] = $newToken;
                    $newStackPtr++;
                }
            } else {
                $newToken = PHP_CodeSniffer::standardiseToken($token);

                // Convert colons that are actually the ELSE component of an
                // inline IF statement.
                if ($newToken['code'] === T_INLINE_THEN) {
                    $insideInlineIf = true;
                } else if ($insideInlineIf === true && $newToken['code'] === T_COLON) {
                    $insideInlineIf = false;
                    $newToken['code'] = T_INLINE_ELSE;
                    $newToken['type'] = 'T_INLINE_ELSE';
                }

                // This is a special condition for T_ARRAY tokens used for
                // type hinting function arguments as being arrays. We want to keep
                // the parenthesis map clean, so let's tag these tokens as
                // T_ARRAY_HINT.
                if ($newToken['code'] === T_ARRAY) {
                    // Recalculate number of tokens.
                    $numTokens = count($tokens);
                    for ($i = $stackPtr; $i < $numTokens; $i++) {
                        if (is_array($tokens[$i]) === false) {
                            if ($tokens[$i] === '(') {
                                break;
                            }
                        } else if ($tokens[$i][0] === T_VARIABLE) {
                            $newToken['code'] = T_ARRAY_HINT;
                            $newToken['type'] = 'T_ARRAY_HINT';
                            break;
                        }
                    }
                }

                $finalTokens[$newStackPtr] = $newToken;
                $newStackPtr++;
            }//end if
        }//end for

        return $finalTokens;

    }//end tokenizeString()


    /**
     * Performs additional processing after main tokenizing.
     *
     * This additional processing checks for CASE statements that are using curly
     * braces for scope openers and closers. It also turns some T_FUNCTION tokens
     * into T_CLOSURE when they are not standard function definitions. It also
     * detects short array syntax and converts those square brackets into new tokens.
     * It also corrects some usage of the static and class keywords.
     *
     * @param array  &$tokens The array of tokens to process.
     * @param string $eolChar The EOL character to use for splitting strings.
     *
     * @return void
     */
    public function processAdditional(&$tokens, $eolChar)
    {
        if (PHP_CODESNIFFER_VERBOSITY > 1) {
            echo "\t*** START ADDITIONAL PHP PROCESSING ***".PHP_EOL;
        }

        $numTokens = count($tokens);
        for ($i = ($numTokens - 1); $i >= 0; $i--) {
            // Looking for functions that are actually closures.
            if ($tokens[$i]['code'] === T_FUNCTION && isset($tokens[$i]['scope_opener']) === true) {
                for ($x = ($i + 1); $x < $numTokens; $x++) {
                    if (in_array($tokens[$x]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
                        break;
                    }
                }

                if ($tokens[$x]['code'] === T_OPEN_PARENTHESIS) {
                    $tokens[$i]['code'] = T_CLOSURE;
                    $tokens[$i]['type'] = 'T_CLOSURE';
                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        $line = $tokens[$i]['line'];
                        echo "\t* token $i on line $line changed from T_FUNCTION to T_CLOSURE".PHP_EOL;
                    }

                    for ($x = ($tokens[$i]['scope_opener'] + 1); $x < $tokens[$i]['scope_closer']; $x++) {
                        if (isset($tokens[$x]['conditions'][$i]) === false) {
                            continue;
                        }

                        $tokens[$x]['conditions'][$i] = T_CLOSURE;
                        if (PHP_CODESNIFFER_VERBOSITY > 1) {
                            $type = $tokens[$x]['type'];
                            echo "\t\t* cleaned $x ($type) *".PHP_EOL;
                        }
                    }
                }

                continue;
            } else if ($tokens[$i]['code'] === T_OPEN_SQUARE_BRACKET) {
                // Unless there is a variable or a bracket before this token,
                // it is the start of an array being defined using the short syntax.
                for ($x = ($i - 1); $x > 0; $x--) {
                    if (in_array($tokens[$x]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
                        break;
                    }
                }

                $allowed = array(
                            T_CLOSE_SQUARE_BRACKET,
                            T_CLOSE_PARENTHESIS,
                            T_VARIABLE,
                            T_STRING,
                           );

                if (in_array($tokens[$x]['code'], $allowed) === false) {
                    $tokens[$i]['code'] = T_OPEN_SHORT_ARRAY;
                    $tokens[$i]['type'] = 'T_OPEN_SHORT_ARRAY';

                    $closer                  = $tokens[$i]['bracket_closer'];
                    $tokens[$closer]['code'] = T_CLOSE_SHORT_ARRAY;
                    $tokens[$closer]['type'] = 'T_CLOSE_SHORT_ARRAY';
                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        $line = $tokens[$i]['line'];
                        echo "\t* token $i on line $line changed from T_OPEN_SQUARE_BRACKET to T_OPEN_SHORT_ARRAY".PHP_EOL;
                        $line = $tokens[$closer]['line'];
                        echo "\t* token $closer on line $line changed from T_CLOSE_SQUARE_BRACKET to T_CLOSE_SHORT_ARRAY".PHP_EOL;
                    }
                }

                continue;
            } else if ($tokens[$i]['code'] === T_STATIC) {
                for ($x = ($i - 1); $x > 0; $x--) {
                    if (in_array($tokens[$x]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
                        break;
                    }
                }

                if ($tokens[$x]['code'] === T_INSTANCEOF) {
                    $tokens[$i]['code'] = T_STRING;
                    $tokens[$i]['type'] = 'T_STRING';

                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        $line = $tokens[$i]['line'];
                        echo "\t* token $i on line $line changed from T_STATIC to T_STRING".PHP_EOL;
                    }
                }

                continue;
            } else if ($tokens[$i]['code'] === T_CLASS
                && $tokens[($i - 1)]['code'] === T_DOUBLE_COLON
            ) {
                $tokens[$i]['code'] = T_STRING;
                $tokens[$i]['type'] = 'T_STRING';

                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                    $line = $tokens[$i]['line'];
                    echo "\t* token $i on line $line changed from T_CLASS to T_STRING".PHP_EOL;
                }
            }//end if

            if (($tokens[$i]['code'] !== T_CASE
                && $tokens[$i]['code'] !== T_DEFAULT)
                || isset($tokens[$i]['scope_opener']) === false
            ) {
                // Only interested in CASE and DEFAULT statements from here on in.
                continue;
            }

            $scopeOpener = $tokens[$i]['scope_opener'];
            $scopeCloser = $tokens[$i]['scope_closer'];

            // If the first char after the opener is a curly brace
            // and that brace has been ignored, it is actually
            // opening this case statement and the opener and closer are
            // probably set incorrectly.
            for ($x = ($scopeOpener + 1); $x < $numTokens; $x++) {
                if (in_array($tokens[$x]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
                    // Non-whitespace content.
                    break;
                }
            }

            if ($tokens[$x]['code'] === T_CASE) {
                // Special case for multiple CASE statements that share the same
                // closer. Because we are going backwards through the file, this next
                // CASE statement is already fixed, so just use its closer and don't
                // worry about fixing anything.
                $newCloser = $tokens[$x]['scope_closer'];
                $tokens[$i]['scope_closer'] = $newCloser;
                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                    $oldType = $tokens[$scopeCloser]['type'];
                    $newType = $tokens[$newCloser]['type'];
                    $line    = $tokens[$i]['line'];
                    echo "\t* token $i (T_CASE) on line $line closer changed from $scopeCloser ($oldType) to $newCloser ($newType)".PHP_EOL;
                }

                continue;
            }

            if ($tokens[$x]['code'] !== T_OPEN_CURLY_BRACKET
                || isset($tokens[$x]['scope_condition']) === true
            ) {
                // Not a CASE with a curly brace opener.
                continue;
            }

            // The closer for this CASE/DEFAULT should be the closing curly brace and
            // not whatever it already is. The opener needs to be the opening curly
            // brace so everything matches up.
            $newCloser = $tokens[$x]['bracket_closer'];
            $tokens[$i]['scope_closer'] = $newCloser;
            $tokens[$x]['scope_closer'] = $newCloser;
            $tokens[$i]['scope_opener'] = $x;
            $tokens[$x]['scope_condition'] = $i;
            $tokens[$newCloser]['scope_condition'] = $i;
            $tokens[$newCloser]['scope_opener']    = $x;
            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                $line      = $tokens[$i]['line'];
                $tokenType = $tokens[$i]['type'];

                $oldType = $tokens[$scopeOpener]['type'];
                $newType = $tokens[$x]['type'];
                echo "\t* token $i ($tokenType) on line $line opener changed from $scopeOpener ($oldType) to $x ($newType)".PHP_EOL;

                $oldType = $tokens[$scopeCloser]['type'];
                $newType = $tokens[$newCloser]['type'];
                echo "\t* token $i ($tokenType) on line $line closer changed from $scopeCloser ($oldType) to $newCloser ($newType)".PHP_EOL;
            }

            // Now fix up all the tokens that think they are
            // inside the CASE/DEFAULT statement when they are really outside.
            for ($x = $newCloser; $x < $scopeCloser; $x++) {
                foreach ($tokens[$x]['conditions'] as $num => $oldCond) {
                    if ($oldCond === $tokens[$i]['code']) {
                        $oldConditions = $tokens[$x]['conditions'];
                        unset($tokens[$x]['conditions'][$num]);

                        if (PHP_CODESNIFFER_VERBOSITY > 1) {
                            $type     = $tokens[$x]['type'];
                            $oldConds = '';
                            foreach ($oldConditions as $condition) {
                                $oldConds .= token_name($condition).',';
                            }

                            $oldConds = rtrim($oldConds, ',');

                            $newConds = '';
                            foreach ($tokens[$x]['conditions'] as $condition) {
                                $newConds .= token_name($condition).',';
                            }

                            $newConds = rtrim($newConds, ',');

                            echo "\t\t* cleaned $x ($type) *".PHP_EOL;
                            echo "\t\t\t=> conditions changed from $oldConds to $newConds".PHP_EOL;
                        }

                        break;
                    }
                }
            }
        }//end for

        if (PHP_CODESNIFFER_VERBOSITY > 1) {
            echo "\t*** END ADDITIONAL PHP PROCESSING ***".PHP_EOL;
        }

    }//end processAdditional()


}//end class

?>
<?php
/**
 * Tokenizes CSS code.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_Tokenizers_PHP', true) === false) {
    throw new Exception('Class PHP_CodeSniffer_Tokenizers_PHP not found');
}

/**
 * Tokenizes CSS code.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_Tokenizers_CSS extends PHP_CodeSniffer_Tokenizers_PHP
{


    /**
     * Creates an array of tokens when given some CSS code.
     *
     * Uses the PHP tokenizer to do all the tricky work
     *
     * @param string $string  The string to tokenize.
     * @param string $eolChar The EOL character to use for splitting strings.
     *
     * @return array
     */
    public function tokenizeString($string, $eolChar='\n')
    {
        if (PHP_CODESNIFFER_VERBOSITY > 1) {
            echo "\t*** START CSS TOKENIZING ***".PHP_EOL;
        }

        // If the content doesn't have an EOl char on the end, add one so
        // the open and close tags we add are parsed correctly.
        if (substr($string, 0, (strlen($eolChar) * -1)) !== $eolChar) {
            $string .= $eolChar;
        }

        $tokens      = parent::tokenizeString('<?php '.$string.'?>', $eolChar);
        $finalTokens = array();

        $newStackPtr      = 0;
        $numTokens        = count($tokens);
        $multiLineComment = false;
        for ($stackPtr = 0; $stackPtr < $numTokens; $stackPtr++) {
            $token = $tokens[$stackPtr];

            // CSS files don't have lists or break tags, so convert these to
            // standard strings early so they can be converted into T_STYLE
            // tokens and joined with other strings if needed.
            if ($token['code'] === T_BREAK || $token['code'] === T_LIST) {
                $token['type'] = 'T_STRING';
                $token['code'] = T_STRING;
            }

            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                $type    = $token['type'];
                $content = str_replace($eolChar, '\n', $token['content']);
                echo "\tProcess token $stackPtr: $type => $content".PHP_EOL;
            }

            // Sometimes, there are PHP tags embedded in the code, which causes issues
            // with how PHP tokenizeses the string. After the first closing tag is found,
            // everything outside PHP tags is set as inline HTML tokens (1 for each line).
            // So we need to go through and find these tokens so we can re-tokenize them.
            if ($token['code'] === T_CLOSE_TAG && $stackPtr !== ($numTokens - 1)) {
                $content = '<?php ';
                for ($x = ($stackPtr + 1); $x < $numTokens; $x++) {
                    if ($tokens[$x]['code'] === T_INLINE_HTML) {
                        $content .= $tokens[$x]['content'];
                    } else {
                        $x--;
                        break;
                    }
                }

                if ($x < ($numTokens - 1)) {
                    // This is not the last closing tag in the file, so we
                    // have to add another closing tag here. If it is the last closing
                    // tag, this additional one would have been added during the
                    // original tokenize call.
                    $content .= ' ?>';
                }

                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                    echo "\t\t=> Found premature closing tag at $stackPtr".PHP_EOL;
                    $cleanContent = str_replace($eolChar, '\n', $content);
                    echo "\t\tcontent: $cleanContent".PHP_EOL;
                    $oldNumTokens = $numTokens;
                }

                // Tokenize the string and remove the extra PHP tags we don't need.
                $moreTokens = parent::tokenizeString($content, $eolChar);
                array_shift($moreTokens);
                array_pop($moreTokens);
                array_pop($moreTokens);

                // Rebuild the tokens array.
                array_splice($tokens, ($stackPtr + 1), ($x - $stackPtr), $moreTokens);
                $numTokens = count($tokens);
                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                    $count = count($moreTokens);
                    $diff  = ($x - $stackPtr);
                    echo "\t\t* added $count tokens, replaced $diff; size changed from $oldNumTokens to $numTokens *".PHP_EOL;
                }
            }//end if

            if ($token['code'] === T_GOTO_LABEL) {
                // Convert these back to T_STRING folowed by T_COLON so we can
                // more easily process style definitions.
                $finalTokens[$newStackPtr] = array(
                                              'type'    => 'T_STRING',
                                              'code'    => T_STRING,
                                              'content' => substr($token['content'], 0, -1),
                                             );
                $newStackPtr++;
                $finalTokens[$newStackPtr] = array(
                                              'type'    => 'T_COLON',
                                              'code'    => T_COLON,
                                              'content' => ':',
                                             );
                $newStackPtr++;
                continue;
            }

            if ($token['code'] === T_FUNCTION) {
                // There are no functions in CSS, so convert this to a string.
                $finalTokens[$newStackPtr] = array(
                                              'type'    => 'T_STRING',
                                              'code'    => T_STRING,
                                              'content' => $token['content'],
                                             );

                $newStackPtr++;
                continue;
            }

            if ($token['code'] === T_COMMENT
                && substr($token['content'], 0, 2) === '/*'
            ) {
                // Multi-line comment. Record it so we can ignore other
                // comment tags until we get out of this one.
                $multiLineComment = true;
            }

            if ($token['code'] === T_COMMENT
                && $multiLineComment === false
                && (substr($token['content'], 0, 2) === '//'
                || $token['content']{0} === '#')
            ) {
                $content = ltrim($token['content'], '#/');
                $commentTokens
                    = parent::tokenizeString('<?php '.$content.'?>', $eolChar);

                // The first and last tokens are the open/close tags.
                array_shift($commentTokens);
                array_pop($commentTokens);

                if ($token['content']{0} === '#') {
                    // The # character is not a comment in CSS files, so
                    // determine what it means in this context.
                    $firstContent = $commentTokens[0]['content'];

                    // If the first content is just a number, it is probably a
                    // colour like 8FB7DB, which PHP splits into 8 and FB7DB.
                    if (($commentTokens[0]['code'] === T_LNUMBER
                        || $commentTokens[0]['code'] === T_DNUMBER)
                        && $commentTokens[1]['code'] === T_STRING
                    ) {
                        $firstContent .= $commentTokens[1]['content'];
                        array_shift($commentTokens);
                    }

                    // If the first content looks like a colour and not a class
                    // definition, join the tokens together.
                    if (preg_match('/^[ABCDEF0-9]+$/i', $firstContent) === 1
                        && $commentTokens[1]['content'] !== '-'
                    ) {
                        array_shift($commentTokens);
                        // Work out what we trimmed off above and remember to re-add it.
                        $trimmed = substr($token['content'], 0, (strlen($token['content']) - strlen($content)));
                        $finalTokens[$newStackPtr] = array(
                                                      'type'    => 'T_COLOUR',
                                                      'code'    => T_COLOUR,
                                                      'content' => $trimmed.$firstContent,
                                                     );
                    } else {
                        $finalTokens[$newStackPtr] = array(
                                                      'type'    => 'T_HASH',
                                                      'code'    => T_HASH,
                                                      'content' => '#',
                                                     );
                    }
                } else {
                    $finalTokens[$newStackPtr] = array(
                                                  'type'    => 'T_STRING',
                                                  'code'    => T_STRING,
                                                  'content' => '//',
                                                 );
                }//end if

                $newStackPtr++;

                foreach ($commentTokens as $tokenData) {
                    if ($tokenData['code'] === T_COMMENT
                        && (substr($tokenData['content'], 0, 2) === '//'
                        || $tokenData['content']{0} === '#')
                    ) {
                        // This is a comment in a comment, so it needs
                        // to go through the whole process again.
                        $tokens[$stackPtr]['content'] = $tokenData['content'];
                        $stackPtr--;
                        break;
                    }

                    $finalTokens[$newStackPtr] = $tokenData;
                    $newStackPtr++;
                }

                continue;
            }//end if

            if ($token['code'] === T_COMMENT 
                && substr($token['content'], -2) === '*/'
            ) {
                // Multi-line comment is done.
                $multiLineComment = false;
            }

            $finalTokens[$newStackPtr] = $token;
            $newStackPtr++;
        }//end for

        // A flag to indicate if we are inside a style definition,
        // which is defined using curly braces. I'm assuming you can't
        // have nested curly brackets.
        $inStyleDef = false;

        $numTokens = count($finalTokens);
        for ($stackPtr = 0; $stackPtr < $numTokens; $stackPtr++) {
            $token = $finalTokens[$stackPtr];

            switch ($token['code']) {
            case T_OPEN_CURLY_BRACKET:
                $inStyleDef = true;
                break;
            case T_CLOSE_CURLY_BRACKET:
                $inStyleDef = false;
                break;
            case T_MINUS:
                // Minus signs are often used instead of spaces inside
                // class names, IDs and styles.
                if ($finalTokens[($stackPtr + 1)]['code'] === T_STRING) {
                    if ($finalTokens[($stackPtr - 1)]['code'] === T_STRING) {
                        $newContent = $finalTokens[($stackPtr - 1)]['content'].'-'.$finalTokens[($stackPtr + 1)]['content'];

                        $finalTokens[($stackPtr - 1)]['content'] = $newContent;
                        unset($finalTokens[$stackPtr]);
                        unset($finalTokens[($stackPtr + 1)]);
                        $stackPtr -= 2;
                    } else {
                        $newContent = '-'.$finalTokens[($stackPtr + 1)]['content'];

                        $finalTokens[($stackPtr + 1)]['content'] = $newContent;
                        unset($finalTokens[$stackPtr]);
                        $stackPtr--;
                    }

                    $finalTokens = array_values($finalTokens);
                    $numTokens   = count($finalTokens);
                } else if ($finalTokens[($stackPtr + 1)]['code'] === T_LNUMBER) {
                    // They can also be used to provide negative numbers.
                    $finalTokens[($stackPtr + 1)]['content']
                        = '-'.$finalTokens[($stackPtr + 1)]['content'];
                    unset($finalTokens[$stackPtr]);

                    $finalTokens = array_values($finalTokens);
                    $numTokens   = count($finalTokens);
                }

                break;
            case T_COLON:
                // Only interested in colons that are defining styles.
                if ($inStyleDef === false) {
                    break;
                }

                for ($x = ($stackPtr - 1); $x >= 0; $x--) {
                    if (in_array($finalTokens[$x]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
                        break;
                    }
                }

                $finalTokens[$x]['type'] = 'T_STYLE';
                $finalTokens[$x]['code'] = T_STYLE;
                break;
            case T_STRING:
                if (strtolower($token['content']) === 'url') {
                    // Find the next content.
                    for ($x = ($stackPtr + 1); $x < $numTokens; $x++) {
                        if (in_array($finalTokens[$x]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
                            break;
                        }
                    }

                    // Needs to be in the format "url(" for it to be a URL.
                    if ($finalTokens[$x]['code'] !== T_OPEN_PARENTHESIS) {
                        continue;
                    }

                    // Make sure the content isn't empty.
                    for ($y = ($x + 1); $y < $numTokens; $y++) {
                        if (in_array($finalTokens[$y]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
                            break;
                        }
                    }

                    if ($finalTokens[$y]['code'] === T_CLOSE_PARENTHESIS) {
                        continue;
                    }

                    // Join all the content together inside the url() statement.
                    $newContent = '';
                    for ($i = ($x + 2); $i < $numTokens; $i++) {
                        if ($finalTokens[$i]['code'] === T_CLOSE_PARENTHESIS) {
                            break;
                        }

                        $newContent .= $finalTokens[$i]['content'];
                        unset($finalTokens[$i]);
                    }

                    // If the content inside the "url()" is in double quotes
                    // there will only be one token and so we don't have to do
                    // anything except change its type. If it is not empty,
                    // we need to do some token merging.
                    $finalTokens[($x + 1)]['type'] = 'T_URL';
                    $finalTokens[($x + 1)]['code'] = T_URL;

                    if ($newContent !== '') {
                        $finalTokens[($x + 1)]['content'] .= $newContent;

                        $finalTokens = array_values($finalTokens);
                        $numTokens   = count($finalTokens);
                    }
                }//end if

                break;
            default:
                // Nothing special to be done with this token.
                break;
            }//end switch
        }//end for

        if (PHP_CODESNIFFER_VERBOSITY > 1) {
            echo "\t*** END CSS TOKENIZING ***".PHP_EOL;
        }

        return $finalTokens;

    }//end tokenizeString()


    /**
     * Performs additional processing after main tokenizing.
     *
     * @param array  &$tokens The array of tokens to process.
     * @param string $eolChar The EOL character to use for splitting strings.
     *
     * @return void
     */
    public function processAdditional(&$tokens, $eolChar)
    {
        // We override this method because we don't want the PHP version to
        // run during CSS processing because it is wasted processing time.

    }//end processAdditional()


}//end class

?>
<?php
/**
 * A PHP_CodeSniffer_File object represents a PHP source file and the tokens
 * associated with it.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * A PHP_CodeSniffer_File object represents a PHP source file and the tokens
 * associated with it.
 *
 * It provides a means for traversing the token stack, along with
 * other token related operations. If a PHP_CodeSniffer_Sniff finds and error or
 *  warning within a PHP_CodeSniffer_File, you can raise an error using the
 *  addError() or addWarning() methods.
 *
 * <b>Token Information</b>
 *
 * Each token within the stack contains information about itself:
 *
 * <code>
 *   array(
 *    'code'       => 301,       // the token type code (see token_get_all())
 *    'content'    => 'if',      // the token content
 *    'type'       => 'T_IF',    // the token name
 *    'line'       => 56,        // the line number when the token is located
 *    'column'     => 12,        // the column in the line where this token
 *                               // starts (starts from 1)
 *    'level'      => 2          // the depth a token is within the scopes open
 *    'conditions' => array(     // a list of scope condition token
 *                               // positions => codes that
 *                     2 => 50,  // openened the scopes that this token exists
 *                     9 => 353, // in (see conditional tokens section below)
 *                    ),
 *   );
 * </code>
 *
 * <b>Conditional Tokens</b>
 *
 * In addition to the standard token fields, conditions contain information to
 * determine where their scope begins and ends:
 *
 * <code>
 *   array(
 *    'scope_condition' => 38, // the token position of the condition
 *    'scope_opener'    => 41, // the token position that started the scope
 *    'scope_closer'    => 70, // the token position that ended the scope
 *   );
 * </code>
 *
 * The condition, the scope opener and the scope closer each contain this
 * information.
 *
 * <b>Parenthesis Tokens</b>
 *
 * Each parenthesis token (T_OPEN_PARENTHESIS and T_CLOSE_PARENTHESIS) has a
 * reference to their opening and closing parenthesis, one being itself, the
 * other being its opposite.
 *
 * <code>
 *   array(
 *    'parenthesis_opener' => 34,
 *    'parenthesis_closer' => 40,
 *   );
 * </code>
 *
 * Some tokens can "own" a set of parenthesis. For example a T_FUNCTION token
 * has parenthesis around its argument list. These tokens also have the
 * parenthesis_opener and and parenthesis_closer indices. Not all parenthesis
 * have owners, for example parenthesis used for arithmetic operations and
 * function calls. The parenthesis tokens that have an owner have the following
 * auxiliary array indices.
 *
 * <code>
 *   array(
 *    'parenthesis_opener' => 34,
 *    'parenthesis_closer' => 40,
 *    'parenthesis_owner'  => 33,
 *   );
 * </code>
 *
 * Each token within a set of parenthesis also has an array indice
 * 'nested_parenthesis' which is an array of the
 * left parenthesis => right parenthesis token positions.
 *
 * <code>
 *   'nested_parenthesis' => array(
 *                             12 => 15
 *                             11 => 14
 *                            );
 * </code>
 *
 * <b>Extended Tokens</b>
 *
 * PHP_CodeSniffer extends and augments some of the tokens created by
 * <i>token_get_all()</i>. A full list of these tokens can be seen in the
 * <i>Tokens.php</i> file.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_File
{

    /**
     * The absolute path to the file associated with this object.
     *
     * @var string
     */
    private $_file = '';

    /**
     * The EOL character this file uses.
     *
     * @var string
     */
    public $eolChar = '';

    /**
     * The PHP_CodeSniffer object controlling this run.
     *
     * @var PHP_CodeSniffer
     */
    public $phpcs = null;

    /**
     * The tokenizer being used for this file.
     *
     * @var object
     */
    public $tokenizer = null;

    /**
     * The tokenizer being used for this file.
     *
     * @var string
     */
    public $tokenizerType = 'PHP';

    /**
     * The number of tokens in this file.
     *
     * Stored here to save calling count() everywhere.
     *
     * @var int
     */
    public $numTokens = 0;

    /**
     * The tokens stack map.
     *
     * Note that the tokens in this array differ in format to the tokens
     * produced by token_get_all(). Tokens are initially produced with
     * token_get_all(), then augmented so that it's easier to process them.
     *
     * @var array()
     * @see Tokens.php
     */
    private $_tokens = array();

    /**
     * The errors raised from PHP_CodeSniffer_Sniffs.
     *
     * @var array()
     * @see getErrors()
     */
    private $_errors = array();

    /**
     * The warnings raised form PHP_CodeSniffer_Sniffs.
     *
     * @var array()
     * @see getWarnings()
     */
    private $_warnings = array();

    /**
     * Record the errors and warnings raised.
     *
     * @var bool
     */
    private $_recordErrors = true;

    /**
     * And array of lines being ignored by PHP_CodeSniffer.
     *
     * @var array()
     */
    private $_ignoredLines = array();

    /**
     * The total number of errors raised.
     *
     * @var int
     */
    private $_errorCount = 0;

    /**
     * The total number of warnings raised.
     *
     * @var int
     */
    private $_warningCount = 0;

    /**
     * An array of sniffs listening to this file's processing.
     *
     * @var array(PHP_CodeSniffer_Sniff)
     */
    private $_listeners = array();

    /**
     * The class name of the sniff currently processing the file.
     *
     * @var string
     */
    private $_activeListener = '';

    /**
     * An array of sniffs being processed and how long they took.
     *
     * @var array()
     */
    private $_listenerTimes = array();

    /**
     * An array of extensions mapping to the tokenizer to use.
     *
     * This value gets set by PHP_CodeSniffer when the object is created.
     *
     * @var array
     */
    protected $tokenizers = array();

    /**
     * An array of rules from the ruleset.xml file.
     *
     * This value gets set by PHP_CodeSniffer when the object is created.
     * It may be empty, indicating that the ruleset does not override
     * any of the default sniff settings.
     *
     * @var array
     */
    protected $ruleset = array();

    /**
     * An array of sniff codes to restrict violations to.
     *
     * This value gets set by PHP_CodeSniffer when the object is created.
     * It may be empty, indicating that no fitering should take place.
     *
     * @var array
     */
    protected $restrictions = array();


    /**
     * Constructs a PHP_CodeSniffer_File.
     *
     * @param string          $file         The absolute path to the file to process.
     * @param array(string)   $listeners    The initial listeners listening
     *                                      to processing of this file.
     * @param array           $tokenizers   An array of extensions mapping
     *                                      to the tokenizer to use.
     * @param array           $ruleset      An array of rules from the
     *                                      ruleset.xml file.
     * @param array           $restrictions An array of sniff codes to
     *                                      restrict violations to.
     * @param PHP_CodeSniffer $phpcs        The PHP_CodeSniffer object controlling
     *                                      this run.
     *
     * @throws PHP_CodeSniffer_Exception If the register() method does
     *                                   not return an array.
     */
    public function __construct(
        $file,
        array $listeners,
        array $tokenizers,
        array $ruleset,
        array $restrictions,
        PHP_CodeSniffer $phpcs
    ) {
        $this->_file        = trim($file);
        $this->_listeners   = $listeners;
        $this->tokenizers   = $tokenizers;
        $this->ruleset      = $ruleset;
        $this->restrictions = $restrictions;
        $this->phpcs        = $phpcs;

        $cliValues = $phpcs->cli->getCommandLineValues();
        if (isset($cliValues['showSources']) === true
            && $cliValues['showSources'] !== true
            && array_key_exists('summary', $cliValues['reports']) === true
            && count($cliValues['reports']) === 1
        ) {
            $this->_recordErrors = false;
        }

    }//end __construct()


    /**
     * Sets the name of the currently active sniff.
     *
     * @param string $activeListener The class name of the current sniff.
     *
     * @return void
     */
    public function setActiveListener($activeListener)
    {
        $this->_activeListener = $activeListener;

    }//end setActiveListener()


    /**
     * Adds a listener to the token stack that listens to the specific tokens.
     *
     * When PHP_CodeSniffer encounters on the the tokens specified in $tokens,
     * it invokes the process method of the sniff.
     *
     * @param PHP_CodeSniffer_Sniff $listener The listener to add to the
     *                                        listener stack.
     * @param array(int)            $tokens   The token types the listener wishes to
     *                                        listen to.
     *
     * @return void
     */
    public function addTokenListener(PHP_CodeSniffer_Sniff $listener, array $tokens)
    {
        foreach ($tokens as $token) {
            if (isset($this->_listeners[$token]) === false) {
                $this->_listeners[$token] = array();
            }

            if (in_array($listener, $this->_listeners[$token], true) === false) {
                $this->_listeners[$token][] = $listener;
            }
        }

    }//end addTokenListener()


    /**
     * Removes a listener from listening from the specified tokens.
     *
     * @param PHP_CodeSniffer_Sniff $listener The listener to remove from the
     *                                        listener stack.
     * @param array(int)            $tokens   The token types the listener wishes to
     *                                        stop listen to.
     *
     * @return void
     */
    public function removeTokenListener(
        PHP_CodeSniffer_Sniff $listener,
        array $tokens
    ) {
        foreach ($tokens as $token) {
            if (isset($this->_listeners[$token]) === false) {
                continue;
            }

            if (in_array($listener, $this->_listeners[$token]) === true) {
                foreach ($this->_listeners[$token] as $pos => $value) {
                    if ($value === $listener) {
                        unset($this->_listeners[$token][$pos]);
                    }
                }
            }
        }

    }//end removeTokenListener()


    /**
     * Returns the token stack for this file.
     *
     * @return array()
     */
    public function getTokens()
    {
        return $this->_tokens;

    }//end getTokens()


    /**
     * Starts the stack traversal and tells listeners when tokens are found.
     *
     * @param string $contents The contents to parse. If NULL, the content
     *                         is taken from the file system.
     *
     * @return void
     */
    public function start($contents=null)
    {
        $this->_parse($contents);

        if (PHP_CODESNIFFER_VERBOSITY > 2) {
            echo "\t*** START TOKEN PROCESSING ***".PHP_EOL;
        }

        $foundCode = false;
        $ignoring  = false;

        // Foreach of the listeners that have registered to listen for this
        // token, get them to process it.
        foreach ($this->_tokens as $stackPtr => $token) {
            // Check for ignored lines.
            if ($token['code'] === T_COMMENT || $token['code'] === T_DOC_COMMENT) {
                if (strpos($token['content'], '@codingStandardsIgnoreStart') !== false) {
                    $ignoring = true;
                } else if (strpos($token['content'], '@codingStandardsIgnoreEnd') !== false) {
                    $ignoring = false;
                    // Ignore this comment too.
                    $this->_ignoredLines[$token['line']] = true;
                } else if (strpos($token['content'], '@codingStandardsIgnoreFile') !== false) {
                    // Ignoring the whole file, just a little late.
                    $this->_errors       = array();
                    $this->_warnings     = array();
                    $this->_errorCount   = 0;
                    $this->_warningCount = 0;
                    return;
                } else if (strpos($token['content'], '@codingStandardsChangeSetting') !== false) {
                    $start         = strpos($token['content'], '@codingStandardsChangeSetting');
                    $comment       = substr($token['content'], $start + 30);
                    $parts         = explode(' ', $comment);
                    $sniffParts    = explode('.', $parts[0]);
                    $listenerClass = $sniffParts[0].'_Sniffs_'.$sniffParts[1].'_'.$sniffParts[2].'Sniff';
                    $this->phpcs->setSniffProperty($listenerClass, $parts[1], $parts[2]);
                }
            }

            if ($ignoring === true) {
                $this->_ignoredLines[$token['line']] = true;
                continue;
            }

            if (PHP_CODESNIFFER_VERBOSITY > 2) {
                $type    = $token['type'];
                $content = str_replace($this->eolChar, '\n', $token['content']);
                echo "\t\tProcess token $stackPtr: $type => $content".PHP_EOL;
            }

            $tokenType = $token['code'];
            if ($tokenType !== T_INLINE_HTML) {
                $foundCode = true;
            }

            if (isset($this->_listeners[$tokenType]) === false) {
                continue;
            }

            foreach ($this->_listeners[$tokenType] as $listenerData) {
                // Make sure this sniff supports the tokenizer
                // we are currently using.
                $listener = $listenerData['listener'];
                $class    = $listenerData['class'];

                if (in_array($this->tokenizerType, $listenerData['tokenizers']) === false) {
                    continue;
                }

                // If the file path matches one of our ignore patterns, skip it.
                $parts = explode('_', str_replace('\\', '_', $class));
                if (isset($parts[3]) === true) {
                    $source   = $parts[0].'.'.$parts[2].'.'.substr($parts[3], 0, -5);
                    $patterns = $this->phpcs->getIgnorePatterns($source);
                    foreach ($patterns as $pattern => $type) {
                        // While there is support for a type of each pattern
                        // (absolute or relative) we don't actually support it here.
                        $replacements = array(
                                         '\\,' => ',',
                                         '*'   => '.*',
                                        );

                        $pattern = strtr($pattern, $replacements);
                        if (preg_match("|{$pattern}|i", $this->_file) === 1) {
                            continue(2);
                        }
                    }
                }

                $this->setActiveListener($class);

                if (PHP_CODESNIFFER_VERBOSITY > 2) {
                    $startTime = microtime(true);
                    echo "\t\t\tProcessing ".$this->_activeListener.'... ';
                }

                $listener->process($this, $stackPtr);

                if (PHP_CODESNIFFER_VERBOSITY > 2) {
                    $timeTaken = (microtime(true) - $startTime);
                    if (isset($this->_listenerTimes[$this->_activeListener]) === false) {
                        $this->_listenerTimes[$this->_activeListener] = 0;
                    }

                    $this->_listenerTimes[$this->_activeListener] += $timeTaken;

                    $timeTaken = round(($timeTaken), 4);
                    echo "DONE in $timeTaken seconds".PHP_EOL;
                }

                $this->_activeListener = '';
            }//end foreach
        }//end foreach

        // Remove errors and warnings for ignored lines.
        foreach ($this->_ignoredLines as $line => $ignore) {
            if (isset($this->_errors[$line]) === true) {
                if ($this->_recordErrors === false) {
                    $this->_errorCount -= $this->_errors[$line];
                } else {
                    foreach ($this->_errors[$line] as $col => $errors) {
                        $this->_errorCount -= count($errors);
                    }
                }

                unset($this->_errors[$line]);
            }

            if (isset($this->_warnings[$line]) === true) {
                if ($this->_recordErrors === false) {
                    $this->_errorCount -= $this->_warnings[$line];
                } else {
                    foreach ($this->_warnings[$line] as $col => $warnings) {
                        $this->_warningCount -= count($warnings);
                    }
                }

                unset($this->_warnings[$line]);
            }
        }//end foreach

        if ($this->_recordErrors === false) {
            $this->_errors = array();
            $this->_warnings = array();
        }

        // If short open tags are off but the file being checked uses
        // short open tags, the whole content will be inline HTML
        // and nothing will be checked. So try and handle this case.
        if ($foundCode === false) {
            $shortTags = (bool) ini_get('short_open_tag');
            if ($shortTags === false) {
                $error = 'No PHP code was found in this file and short open tags are not allowed by this install of PHP. This file may be using short open tags but PHP does not allow them.';
                $this->addWarning($error, null, 'Internal.NoCodeFound');
            }
        }

        if (PHP_CODESNIFFER_VERBOSITY > 2) {
            echo "\t*** END TOKEN PROCESSING ***".PHP_EOL;
        }

        if (PHP_CODESNIFFER_VERBOSITY > 2) {
            echo "\t*** START SNIFF PROCESSING REPORT ***".PHP_EOL;

            asort($this->_listenerTimes, SORT_NUMERIC);
            $this->_listenerTimes = array_reverse($this->_listenerTimes, true);
            foreach ($this->_listenerTimes as $listener => $timeTaken) {
                echo "\t$listener: ".round(($timeTaken), 4).' secs'.PHP_EOL;
            }

            echo "\t*** END SNIFF PROCESSING REPORT ***".PHP_EOL;
        }

    }//end start()


    /**
     * Remove vars stored in this sniff that are no longer required.
     *
     * @return void
     */
    public function cleanUp()
    {
        $this->_tokens    = null;
        $this->_listeners = null;

    }//end cleanUp()


    /**
     * Tokenizes the file and prepares it for the test run.
     *
     * @param string $contents The contents to parse. If NULL, the content
     *                         is taken from the file system.
     *
     * @return void
     */
    private function _parse($contents=null)
    {
        try {
            $this->eolChar = self::detectLineEndings($this->_file, $contents);
        } catch (PHP_CodeSniffer_Exception $e) {
            $this->addWarning($e->getMessage(), null, 'Internal.DetectLineEndings');
            return;
        }

        // Determine the tokenizer from the file extension.
        $fileParts = explode('.', $this->_file);
        $extension = array_pop($fileParts);
        if (isset($this->tokenizers[$extension]) === true) {
            $tokenizerClass      = 'PHP_CodeSniffer_Tokenizers_'.$this->tokenizers[$extension];
            $this->tokenizerType = $this->tokenizers[$extension];
        } else {
            // Revert to default.
            $tokenizerClass = 'PHP_CodeSniffer_Tokenizers_'.$this->tokenizerType;
        }

        $tokenizer       = new $tokenizerClass();
        $this->tokenizer = $tokenizer;

        if ($contents === null) {
            $contents = file_get_contents($this->_file);
        }

        $this->_tokens   = self::tokenizeString($contents, $tokenizer, $this->eolChar);
        $this->numTokens = count($this->_tokens);

        // Check for mixed line endings as these can cause tokenizer errors and we
        // should let the user know that the results they get may be incorrect.
        // This is done by removing all backslashes, removing the newline char we
        // detected, then converting newlines chars into text. If any backslashes
        // are left at the end, we have additional newline chars in use.
        $contents = str_replace('\\', '', $contents);
        $contents = str_replace($this->eolChar, '', $contents);
        $contents = str_replace("\n", '\n', $contents);
        $contents = str_replace("\r", '\r', $contents);
        if (strpos($contents, '\\') !== false) {
            $error = 'File has mixed line endings; this may cause incorrect results';
            $this->addWarning($error, 0, 'Internal.LineEndings.Mixed');
        }

        if (PHP_CODESNIFFER_VERBOSITY > 0) {
            if ($this->numTokens === 0) {
                $numLines = 0;
            } else {
                $numLines = $this->_tokens[($this->numTokens - 1)]['line'];
            }

            echo "[$this->numTokens tokens in $numLines lines]... ";
            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                echo PHP_EOL;
            }
        }

    }//end _parse()


    /**
     * Opens a file and detects the EOL character being used.
     *
     * @param string $file     The full path to the file.
     * @param string $contents The contents to parse. If NULL, the content
     *                         is taken from the file system.
     *
     * @return string
     * @throws PHP_CodeSniffer_Exception If $file could not be opened.
     */
    public static function detectLineEndings($file, $contents=null)
    {
        if ($contents === null) {
            // Determine the newline character being used in this file.
            // Will be either \r, \r\n or \n.
            if (is_readable($file) === false) {
                $error = 'Error opening file; file no longer exists or you do not have access to read the file';
                throw new PHP_CodeSniffer_Exception($error);
            } else {
                $handle = fopen($file, 'r');
                if ($handle === false) {
                    $error = 'Error opening file; could not auto-detect line endings';
                    throw new PHP_CodeSniffer_Exception($error);
                }
            }

            $firstLine = fgets($handle);
            fclose($handle);

            $eolChar = substr($firstLine, -1);
            if ($eolChar === "\n") {
                $secondLastChar = substr($firstLine, -2, 1);
                if ($secondLastChar === "\r") {
                    $eolChar = "\r\n";
                }
            } else if ($eolChar !== "\r") {
                // Must not be an EOL char at the end of the line.
                // Probably a one-line file, so assume \n as it really
                // doesn't matter considering there are no newlines.
                $eolChar = "\n";
            }
        } else {
            if (preg_match("/\r\n?|\n/", $contents, $matches) !== 1) {
                // Assuming there are no newlines.
                $eolChar = "\n";
            } else {
                $eolChar = $matches[0];
            }
        }//end if

        return $eolChar;

    }//end detectLineEndings()


    /**
     * Adds an error to the error stack.
     *
     * @param string $error    The error message.
     * @param int    $stackPtr The stack position where the error occurred.
     * @param string $code     A violation code unique to the sniff message.
     * @param array  $data     Replacements for the error message.
     * @param int    $severity The severity level for this error. A value of 0
     *                         will be converted into the default severity level.
     *
     * @return void
     */
    public function addError($error, $stackPtr, $code='', $data=array(), $severity=0)
    {
        // Don't bother doing any processing if errors are just going to
        // be hidden in the reports anyway.
        if ($this->phpcs->cli->errorSeverity === 0) {
            return;
        }

        // Work out which sniff generated the error.
        if (substr($code, 0, 9) === 'Internal.') {
            // Any internal message.
            $sniff     = $code;
            $sniffCode = $code;
        } else {
            $parts = explode('_', str_replace('\\', '_', $this->_activeListener));
            if (isset($parts[3]) === true) {
                $sniff = $parts[0].'.'.$parts[2].'.'.$parts[3];

                // Remove "Sniff" from the end.
                $sniff = substr($sniff, 0, -5);
            } else {
                $sniff = 'unknownSniff';
            }

            $sniffCode = $sniff;
            if ($code !== '') {
                $sniffCode .= '.'.$code;
            }
        }//end if

        // Make sure this message type is allowed based on the --sniffs
        // command line argument values.
        if (empty($this->restrictions) === false
            && in_array($sniffCode, $this->restrictions) === false
            && in_array($sniff, $this->restrictions) === false
        ) {
            return;
        }

        // Make sure this message type has not been set to "warning".
        if (isset($this->ruleset[$sniffCode]['type']) === true
            && $this->ruleset[$sniffCode]['type'] === 'warning'
        ) {
            // Pass this off to the warning handler.
            $this->addWarning($error, $stackPtr, $code, $data, $severity);
            return;
        }

        // Make sure we are interested in this severity level.
        if (isset($this->ruleset[$sniffCode]['severity']) === true) {
            $severity = $this->ruleset[$sniffCode]['severity'];
        } else if ($severity === 0) {
            $severity = PHPCS_DEFAULT_ERROR_SEV;
        }

        if ($this->phpcs->cli->errorSeverity > $severity) {
            return;
        }

        // Make sure we are not ignoring this file.
        $patterns = $this->phpcs->getIgnorePatterns($sniffCode);
        foreach ($patterns as $pattern => $type) {
            // While there is support for a type of each pattern
            // (absolute or relative) we don't actually support it here.
            $replacements = array(
                             '\\,' => ',',
                             '*'   => '.*',
                            );

            $pattern = strtr($pattern, $replacements);
            if (preg_match("|{$pattern}|i", $this->_file) === 1) {
                return;
            }
        }

        if ($stackPtr === null) {
            $lineNum = 1;
            $column = 1;
        } else {
            $lineNum = $this->_tokens[$stackPtr]['line'];
            $column = $this->_tokens[$stackPtr]['column'];
        }

        $this->_errorCount++;
        if ($this->_recordErrors === false) {
            if (isset($this->_errors[$lineNum]) === false) {
                $this->_errors[$lineNum] = 0;
            }
            $this->_errors[$lineNum]++;
            return;
        }

        // Work out the warning message.
        if (isset($this->ruleset[$sniffCode]['message']) === true) {
            $error = $this->ruleset[$sniffCode]['message'];
        }

        if (empty($data) === true) {
            $message = $error;
        } else {
            $message = vsprintf($error, $data);
        }

        if (isset($this->_errors[$lineNum]) === false) {
            $this->_errors[$lineNum] = array();
        }

        if (isset($this->_errors[$lineNum][$column]) === false) {
            $this->_errors[$lineNum][$column] = array();
        }

        $this->_errors[$lineNum][$column][] = array(
                                               'message'  => $message,
                                               'source'   => $sniffCode,
                                               'severity' => $severity,
                                              );

    }//end addError()


    /**
     * Adds an warning to the warning stack.
     *
     * @param string $warning  The error message.
     * @param int    $stackPtr The stack position where the error occurred.
     * @param string $code     A violation code unique to the sniff message.
     * @param array  $data     Replacements for the warning message.
     * @param int    $severity The severity level for this warning. A value of 0
     *                         will be converted into the default severity level.
     *
     * @return void
     */
    public function addWarning($warning, $stackPtr, $code='', $data=array(), $severity=0)
    {
        // Don't bother doing any processing if warnings are just going to
        // be hidden in the reports anyway.
        if ($this->phpcs->cli->warningSeverity === 0) {
            return;
        }

        // Work out which sniff generated the warning.
        if (substr($code, 0, 9) === 'Internal.') {
            // Any internal message.
            $sniff     = $code;
            $sniffCode = $code;
        } else {
            $parts = explode('_', str_replace('\\', '_', $this->_activeListener));
            if (isset($parts[3]) === true) {
                $sniff = $parts[0].'.'.$parts[2].'.'.$parts[3];

                // Remove "Sniff" from the end.
                $sniff = substr($sniff, 0, -5);
            } else {
                $sniff = 'unknownSniff';
            }

            $sniffCode = $sniff;
            if ($code !== '') {
                $sniffCode .= '.'.$code;
            }
        }//end if

        // Make sure this message type is allowed based on the --sniffs
        // command line argument values.
        if (empty($this->restrictions) === false
            && in_array($sniffCode, $this->restrictions) === false
            && in_array($sniff, $this->restrictions) === false
        ) {
            return;
        }

        // Make sure this message type has not been set to "error".
        if (isset($this->ruleset[$sniffCode]['type']) === true
            && $this->ruleset[$sniffCode]['type'] === 'error'
        ) {
            // Pass this off to the error handler.
            $this->addError($warning, $stackPtr, $code, $data, $severity);
            return;
        }

        // Make sure we are interested in this severity level.
        if (isset($this->ruleset[$sniffCode]['severity']) === true) {
            $severity = $this->ruleset[$sniffCode]['severity'];
        } else if ($severity === 0) {
            $severity = PHPCS_DEFAULT_WARN_SEV;
        }

        if ($this->phpcs->cli->warningSeverity > $severity) {
            return;
        }

        // Make sure we are not ignoring this file.
        $patterns = $this->phpcs->getIgnorePatterns($sniffCode);
        foreach ($patterns as $pattern => $type) {
            // While there is support for a type of each pattern
            // (absolute or relative) we don't actually support it here.
            $replacements = array(
                             '\\,' => ',',
                             '*'   => '.*',
                            );

            $pattern = strtr($pattern, $replacements);
            if (preg_match("|{$pattern}|i", $this->_file) === 1) {
                return;
            }
        }

        if ($stackPtr === null) {
            $lineNum = 1;
            $column = 1;
        } else {
            $lineNum = $this->_tokens[$stackPtr]['line'];
            $column = $this->_tokens[$stackPtr]['column'];
        }

        $this->_warningCount++;
        if ($this->_recordErrors === false) {
            if (isset($this->_warnings[$lineNum]) === false) {
                $this->_warnings[$lineNum] = 0;
            }
            $this->_warnings[$lineNum]++;
            return;
        }

        // Work out the warning message.
        if (isset($this->ruleset[$sniffCode]['message']) === true) {
            $warning = $this->ruleset[$sniffCode]['message'];
        }

        if (empty($data) === true) {
            $message = $warning;
        } else {
            $message = vsprintf($warning, $data);
        }

        if (isset($this->_warnings[$lineNum]) === false) {
            $this->_warnings[$lineNum] = array();
        }

        if (isset($this->_warnings[$lineNum][$column]) === false) {
            $this->_warnings[$lineNum][$column] = array();
        }

        $this->_warnings[$lineNum][$column][] = array(
                                                 'message'  => $message,
                                                 'source'   => $sniffCode,
                                                 'severity' => $severity,
                                                );

    }//end addWarning()


    /**
     * Returns the number of errors raised.
     *
     * @return int
     */
    public function getErrorCount()
    {
        return $this->_errorCount;

    }//end getErrorCount()


    /**
     * Returns the number of warnings raised.
     *
     * @return int
     */
    public function getWarningCount()
    {
        return $this->_warningCount;

    }//end getWarningCount()


    /**
     * Returns the list of ignored lines.
     *
     * @return array
     */
    public function getIgnoredLines()
    {
        return $this->_ignoredLines;

    }//end getIgnoredLines()


    /**
     * Returns the errors raised from processing this file.
     *
     * @return array
     */
    public function getErrors()
    {
        return $this->_errors;

    }//end getErrors()


    /**
     * Returns the warnings raised from processing this file.
     *
     * @return array
     */
    public function getWarnings()
    {
        return $this->_warnings;

    }//end getWarnings()


    /**
     * Returns the absolute filename of this file.
     *
     * @return string
     */
    public function getFilename()
    {
        return $this->_file;

    }//end getFilename()


    /**
     * Creates an array of tokens when given some PHP code.
     *
     * Starts by using token_get_all() but does a lot of extra processing
     * to insert information about the context of the token.
     *
     * @param string $string    The string to tokenize.
     * @param object $tokenizer A tokenizer class to use to tokenize the string.
     * @param string $eolChar   The EOL character to use for splitting strings.
     *
     * @return array
     */
    public static function tokenizeString($string, $tokenizer, $eolChar='\n')
    {
        $tokens = $tokenizer->tokenizeString($string, $eolChar);

        self::_createLineMap($tokens, $tokenizer, $eolChar);
        self::_createBracketMap($tokens, $tokenizer, $eolChar);
        self::_createParenthesisMap($tokens, $tokenizer, $eolChar);
        self::_createParenthesisNestingMap($tokens, $tokenizer, $eolChar);
        self::_createScopeMap($tokens, $tokenizer, $eolChar);

        // If we know the width of each tab, convert tabs
        // into spaces so sniffs can use one method of checking.
        if (PHP_CODESNIFFER_TAB_WIDTH > 0) {
            self::_convertTabs($tokens, $tokenizer, $eolChar);
        }

        // Column map requires the line map to be complete.
        self::_createColumnMap($tokens, $tokenizer, $eolChar);
        self::_createLevelMap($tokens, $tokenizer, $eolChar);

        // Allow the tokenizer to do additional processing if required.
        $tokenizer->processAdditional($tokens, $eolChar);

        return $tokens;

    }//end tokenizeString()


    /**
     * Creates a map of tokens => line numbers for each token.
     *
     * @param array  &$tokens   The array of tokens to process.
     * @param object $tokenizer The tokenizer being used to process this file.
     * @param string $eolChar   The EOL character to use for splitting strings.
     *
     * @return void
     */
    private static function _createLineMap(&$tokens, $tokenizer, $eolChar)
    {
        $lineNumber = 1;
        $count      = count($tokens);

        for ($i = 0; $i < $count; $i++) {
            $tokens[$i]['line'] = $lineNumber;
            if ($tokens[$i]['content'] === '') {
                continue;
            }

            $lineNumber += substr_count($tokens[$i]['content'], $eolChar);
        }

    }//end _createLineMap()


    /**
     * Converts tabs into spaces.
     *
     * Each tab can represent between 1 and $width spaces, so
     * this cannot be a straight string replace.
     *
     * @param array  &$tokens   The array of tokens to process.
     * @param object $tokenizer The tokenizer being used to process this file.
     * @param string $eolChar   The EOL character to use for splitting strings.
     *
     * @return void
     */
    private static function _convertTabs(&$tokens, $tokenizer, $eolChar)
    {
        $currColumn = 1;
        $count      = count($tokens);

        for ($i = 0; $i < $count; $i++) {
            $tokenContent = $tokens[$i]['content'];

            if (strpos($tokenContent, "\t") === false) {
                // There are no tabs in this content.
                $currColumn += strlen($tokenContent);
            } else {
                // We need to determine the length of each tab.
                $tabs = preg_split(
                    "|(\t)|",
                    $tokenContent,
                    -1,
                    PREG_SPLIT_DELIM_CAPTURE
                );

                $tabNum       = 0;
                $tabsToSpaces = array();
                $newContent   = '';

                foreach ($tabs as $content) {
                    if ($content === '') {
                        continue;
                    }

                    if (strpos($content, "\t") === false) {
                        // This piece of content is not a tab.
                        $currColumn += strlen($content);
                        $newContent .= $content;
                    } else {
                        $lastCurrColumn = $currColumn;
                        $tabNum++;

                        // Move the pointer to the next tab stop.
                        if (($currColumn % PHP_CODESNIFFER_TAB_WIDTH) === 0) {
                            // This is the first tab, and we are already at a
                            // tab stop, so this tab counts as a single space.
                            $currColumn++;
                        } else {
                            $currColumn++;
                            while (($currColumn % PHP_CODESNIFFER_TAB_WIDTH) != 0) {
                                $currColumn++;
                            }

                            $currColumn++;
                        }

                        $length      = ($currColumn - $lastCurrColumn);
                        $newContent .= str_repeat(' ', $length);
                    }//end if
                }//end foreach

                $tokens[$i]['content'] = $newContent;
            }//end if

            if (isset($tokens[($i + 1)]['line']) === true
                && $tokens[($i + 1)]['line'] !== $tokens[$i]['line']
            ) {
                $currColumn = 1;
            }
        }//end for

    }//end _convertTabs()


    /**
     * Creates a column map.
     *
     * The column map indicates where the token started on the line where it
     * exists.
     *
     * @param array  &$tokens   The array of tokens to process.
     * @param object $tokenizer The tokenizer being used to process this file.
     * @param string $eolChar   The EOL character to use for splitting strings.
     *
     * @return void
     */
    private static function _createColumnMap(&$tokens, $tokenizer, $eolChar)
    {
        $currColumn = 1;
        $count      = count($tokens);

        for ($i = 0; $i < $count; $i++) {
            $tokens[$i]['column'] = $currColumn;
            if (isset($tokens[($i + 1)]['line']) === true
                && $tokens[($i + 1)]['line'] !== $tokens[$i]['line']
            ) {
                $currColumn = 1;
            } else {
                $currColumn += strlen($tokens[$i]['content']);
            }
        }

    }//end _createColumnMap()


    /**
     * Creates a map for opening and closing of square brackets.
     *
     * Each bracket token (T_OPEN_SQUARE_BRACKET and T_CLOSE_SQUARE_BRACKET)
     * has a reference to their opening and closing bracket
     * (bracket_opener and bracket_closer).
     *
     * @param array  &$tokens   The array of tokens to process.
     * @param object $tokenizer The tokenizer being used to process this file.
     * @param string $eolChar   The EOL character to use for splitting strings.
     *
     * @return void
     */
    private static function _createBracketMap(&$tokens, $tokenizer, $eolChar)
    {
        if (PHP_CODESNIFFER_VERBOSITY > 1) {
            echo "\t*** START BRACKET MAP ***".PHP_EOL;
        }

        $squareOpeners = array();
        $curlyOpeners  = array();
        $numTokens     = count($tokens);

        for ($i = 0; $i < $numTokens; $i++) {
            switch ($tokens[$i]['code']) {
            case T_OPEN_SQUARE_BRACKET:
                $squareOpeners[] = $i;

                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                    echo str_repeat("\t", count($squareOpeners));
                    echo str_repeat("\t", count($curlyOpeners));
                    echo "=> Found square bracket opener at $i".PHP_EOL;
                }

                break;
            case T_OPEN_CURLY_BRACKET:
                if (isset($tokens[$i]['scope_closer']) === false) {
                    $curlyOpeners[] = $i;

                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        echo str_repeat("\t", count($squareOpeners));
                        echo str_repeat("\t", count($curlyOpeners));
                        echo "=> Found curly bracket opener at $i".PHP_EOL;
                    }
                }
                break;
            case T_CLOSE_SQUARE_BRACKET:
                if (empty($squareOpeners) === false) {
                    $opener                            = array_pop($squareOpeners);
                    $tokens[$i]['bracket_opener']      = $opener;
                    $tokens[$i]['bracket_closer']      = $i;
                    $tokens[$opener]['bracket_opener'] = $opener;
                    $tokens[$opener]['bracket_closer'] = $i;

                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        echo str_repeat("\t", count($squareOpeners));
                        echo str_repeat("\t", count($curlyOpeners));
                        echo "\t=> Found square bracket closer at $i for $opener".PHP_EOL;
                    }
                }
                break;
            case T_CLOSE_CURLY_BRACKET:
                if (empty($curlyOpeners) === false
                    && isset($tokens[$i]['scope_opener']) === false
                ) {
                    $opener                            = array_pop($curlyOpeners);
                    $tokens[$i]['bracket_opener']      = $opener;
                    $tokens[$i]['bracket_closer']      = $i;
                    $tokens[$opener]['bracket_opener'] = $opener;
                    $tokens[$opener]['bracket_closer'] = $i;

                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        echo str_repeat("\t", count($squareOpeners));
                        echo str_repeat("\t", count($curlyOpeners));
                        echo "\t=> Found curly bracket closer at $i for $opener".PHP_EOL;
                    }
                }
                break;
            default:
                continue;
            }//end switch
        }//end for

        if (PHP_CODESNIFFER_VERBOSITY > 1) {
            echo "\t*** END BRACKET MAP ***".PHP_EOL;
        }

    }//end _createBracketMap()


    /**
     * Creates a map for opening and closing of parenthesis.
     *
     * Each parenthesis token (T_OPEN_PARENTHESIS and T_CLOSE_PARENTHESIS) has a
     * reference to their opening and closing parenthesis (parenthesis_opener
     * and parenthesis_closer).
     *
     * @param array  &$tokens   The array of tokens to process.
     * @param object $tokenizer The tokenizer being used to process this file.
     * @param string $eolChar   The EOL character to use for splitting strings.
     *
     * @return void
     */
    private static function _createParenthesisMap(&$tokens, $tokenizer, $eolChar)
    {
        $openers   = array();
        $numTokens = count($tokens);
        $openOwner = null;

        for ($i = 0; $i < $numTokens; $i++) {
            if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$parenthesisOpeners) === true) {
                $tokens[$i]['parenthesis_opener'] = null;
                $tokens[$i]['parenthesis_closer'] = null;
                $tokens[$i]['parenthesis_owner']  = $i;
                $openOwner                        = $i;
            } else if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS) {
                $openers[]                        = $i;
                $tokens[$i]['parenthesis_opener'] = $i;
                if ($openOwner !== null) {
                    $tokens[$openOwner]['parenthesis_opener'] = $i;
                    $tokens[$i]['parenthesis_owner']          = $openOwner;
                    $openOwner                                = null;
                }
            } else if ($tokens[$i]['code'] === T_CLOSE_PARENTHESIS) {
                // Did we set an owner for this set of parenthesis?
                $numOpeners = count($openers);
                if ($numOpeners !== 0) {
                    $opener = array_pop($openers);
                    if (isset($tokens[$opener]['parenthesis_owner']) === true) {
                        $owner = $tokens[$opener]['parenthesis_owner'];

                        $tokens[$owner]['parenthesis_closer'] = $i;
                        $tokens[$i]['parenthesis_owner']      = $owner;
                    }

                    $tokens[$i]['parenthesis_opener']      = $opener;
                    $tokens[$i]['parenthesis_closer']      = $i;
                    $tokens[$opener]['parenthesis_closer'] = $i;
                }
            }//end if
        }//end for

    }//end _createParenthesisMap()


    /**
     * Creates a map for the parenthesis tokens that surround other tokens.
     *
     * @param array  &$tokens   The array of tokens to process.
     * @param object $tokenizer The tokenizer being used to process this file.
     * @param string $eolChar   The EOL character to use for splitting strings.
     *
     * @return void
     */
    private static function _createParenthesisNestingMap(
        &$tokens,
        $tokenizer,
        $eolChar
    ) {
        $numTokens = count($tokens);
        $map       = array();
        for ($i = 0; $i < $numTokens; $i++) {
            if (isset($tokens[$i]['parenthesis_opener']) === true
                && $i === $tokens[$i]['parenthesis_opener']
            ) {
                if (empty($map) === false) {
                    $tokens[$i]['nested_parenthesis'] = $map;
                }

                if (isset($tokens[$i]['parenthesis_closer']) === true) {
                    $map[$tokens[$i]['parenthesis_opener']]
                        = $tokens[$i]['parenthesis_closer'];
                }
            } else if (isset($tokens[$i]['parenthesis_closer']) === true
                && $i === $tokens[$i]['parenthesis_closer']
            ) {
                array_pop($map);
                if (empty($map) === false) {
                    $tokens[$i]['nested_parenthesis'] = $map;
                }
            } else {
                if (empty($map) === false) {
                    $tokens[$i]['nested_parenthesis'] = $map;
                }
            }//end if
        }//end for

    }//end _createParenthesisNestingMap()


    /**
     * Creates a scope map of tokens that open scopes.
     *
     * @param array  &$tokens   The array of tokens to process.
     * @param object $tokenizer The tokenizer being used to process this file.
     * @param string $eolChar   The EOL character to use for splitting strings.
     *
     * @return void
     * @see _recurseScopeMap()
     */
    private static function _createScopeMap(&$tokens, $tokenizer, $eolChar)
    {
        if (PHP_CODESNIFFER_VERBOSITY > 1) {
            echo "\t*** START SCOPE MAP ***".PHP_EOL;
        }

        $numTokens = count($tokens);
        for ($i = 0; $i < $numTokens; $i++) {
            // Check to see if the current token starts a new scope.
            if (isset($tokenizer->scopeOpeners[$tokens[$i]['code']]) === true) {
                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                    $type    = $tokens[$i]['type'];
                    $content = str_replace($eolChar, '\n', $tokens[$i]['content']);
                    echo "\tStart scope map at $i: $type => $content".PHP_EOL;
                }

                $i = self::_recurseScopeMap(
                    $tokens,
                    $numTokens,
                    $tokenizer,
                    $eolChar,
                    $i
                );
            }
        }//end for

        if (PHP_CODESNIFFER_VERBOSITY > 1) {
            echo "\t*** END SCOPE MAP ***".PHP_EOL;
        }

    }//end _createScopeMap()


    /**
     * Recurses though the scope openers to build a scope map.
     *
     * @param array  &$tokens   The array of tokens to process.
     * @param int    $numTokens The size of the tokens array.
     * @param object $tokenizer The tokenizer being used to process this file.
     * @param string $eolChar   The EOL character to use for splitting strings.
     * @param int    $stackPtr  The position in the stack of the token that
     *                          opened the scope (eg. an IF token or FOR token).
     * @param int    $depth     How many scope levels down we are.
     * @param int    &$ignore   How many curly braces we are ignoring.
     *
     * @return int The position in the stack that closed the scope.
     */
    private static function _recurseScopeMap(
        &$tokens,
        $numTokens,
        $tokenizer,
        $eolChar,
        $stackPtr,
        $depth=1,
        &$ignore=0
    ) {
        $opener    = null;
        $currType  = $tokens[$stackPtr]['code'];
        $startLine = $tokens[$stackPtr]['line'];

        // We will need this to restore the value if we end up
        // returning a token ID that causes our calling function to go back
        // over already ignored braces.
        $originalIgnore = $ignore;

        // If the start token for this scope opener is the same as
        // the scope token, we have already found our opener.
        if (in_array($currType, $tokenizer->scopeOpeners[$currType]['start']) === true) {
            $opener = $stackPtr;
        }

        for ($i = ($stackPtr + 1); $i < $numTokens; $i++) {
            $tokenType = $tokens[$i]['code'];

            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                $type    = $tokens[$i]['type'];
                $content = str_replace($eolChar, '\n', $tokens[$i]['content']);
                echo str_repeat("\t", $depth);
                echo "Process token $i [";
                if ($opener !== null) {
                    echo "opener:$opener;";
                }

                if ($ignore > 0) {
                    echo "ignore=$ignore;";
                }

                echo "]: $type => $content".PHP_EOL;
            }

            // Very special case for IF statements in PHP that can be defined without
            // scope tokens. If an IF statement below this one has an opener but no
            // keyword, the opener will be incorrectly assigned to this IF statement.
            // E.g., if (1) 1; 1 ? (1 ? 1 : 1) : 1;
            if (($currType === T_IF || $currType === T_ELSE) && $opener === null && $tokens[$i]['code'] === T_SEMICOLON) {
                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                    $type = $tokens[$stackPtr]['type'];
                    echo str_repeat("\t", $depth);
                    echo "=> Found semicolon before scope opener for $stackPtr ($type), bailing".PHP_EOL;
                }

                return $i;
            }

            // Is this an opening condition ?
            if (isset($tokenizer->scopeOpeners[$tokenType]) === true) {
                if ($opener === null) {
                    // Found another opening condition but still haven't
                    // found our opener, so we are never going to find one.
                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        $type = $tokens[$stackPtr]['type'];
                        echo str_repeat("\t", $depth);
                        echo "=> Couldn't find scope opener for $stackPtr ($type), bailing".PHP_EOL;
                    }

                    return $stackPtr;
                }

                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                    echo str_repeat("\t", $depth);
                    echo '* token is an opening condition *'.PHP_EOL;
                }

                $isShared
                    = ($tokenizer->scopeOpeners[$tokenType]['shared'] === true);

                if (isset($tokens[$i]['scope_condition']) === true) {
                    // We've been here before.
                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        echo str_repeat("\t", $depth);
                        echo '* already processed, skipping *'.PHP_EOL;
                    }

                    if ($isShared === false
                        && isset($tokens[$i]['scope_closer']) === true
                    ) {
                        $i = $tokens[$i]['scope_closer'];
                    }

                    continue;
                } else if ($currType === $tokenType
                    && $isShared === false
                    && $opener === null
                ) {
                    // We haven't yet found our opener, but we have found another
                    // scope opener which is the same type as us, and we don't
                    // share openers, so we will never find one.
                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        echo str_repeat("\t", $depth);
                        echo '* it was another token\'s opener, bailing *'.PHP_EOL;
                    }

                    return $stackPtr;
                } else {
                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        echo str_repeat("\t", $depth);
                        echo '* searching for opener *'.PHP_EOL;
                    }

                    if (in_array(T_CLOSE_CURLY_BRACKET, $tokenizer->scopeOpeners[$tokenType]['end']) === true) {
                        $oldIgnore = $ignore;
                        $ignore    = 0;
                    }

                    $i = self::_recurseScopeMap(
                        $tokens,
                        $numTokens,
                        $tokenizer,
                        $eolChar,
                        $i,
                        ($depth + 1),
                        $ignore
                    );

                    if (in_array(T_CLOSE_CURLY_BRACKET, $tokenizer->scopeOpeners[$tokenType]['end']) === true) {
                        $ignore = $oldIgnore;
                    }
                }//end if
            }//end if

            if (in_array($tokenType, $tokenizer->scopeOpeners[$currType]['start']) === true
                && $opener === null
            ) {
                if ($tokenType === T_OPEN_CURLY_BRACKET) {
                    // Make sure this is actually an opener and not a
                    // string offset (e.g., $var{0}).
                    for ($x = ($i - 1); $x > 0; $x--) {
                        if (in_array($tokens[$x]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === true) {
                            continue;
                        } else {
                            // If the first non-whitespace/comment token is a
                            // variable or object operator then this is an opener
                            // for a string offset and not a scope.
                            if ($tokens[$x]['code'] === T_VARIABLE
                                || $tokens[$x]['code'] === T_OBJECT_OPERATOR
                            ) {
                                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                                    echo str_repeat("\t", $depth);
                                    echo '* ignoring curly brace *'.PHP_EOL;
                                }

                                $ignore++;
                            }//end if

                            break;
                        }//end if
                    }//end for
                }//end if

                if ($ignore === 0) {
                    // We found the opening scope token for $currType.
                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        $type = $tokens[$stackPtr]['type'];
                        echo str_repeat("\t", $depth);
                        echo "=> Found scope opener for $stackPtr ($type)".PHP_EOL;
                    }

                    $opener = $i;
                }
            } else if (in_array($tokenType, $tokenizer->scopeOpeners[$currType]['end']) === true
                && $opener !== null
            ) {
                if ($ignore > 0 && $tokenType === T_CLOSE_CURLY_BRACKET) {
                    // The last opening bracket must have been for a string
                    // offset or alike, so let's ignore it.
                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        echo str_repeat("\t", $depth);
                        echo '* finished ignoring curly brace *'.PHP_EOL;
                    }

                    $ignore--;
                } else {
                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        $type = $tokens[$stackPtr]['type'];
                        echo str_repeat("\t", $depth);
                        echo "=> Found scope closer for $stackPtr ($type)".PHP_EOL;
                    }

                    foreach (array($stackPtr, $opener, $i) as $token) {
                        $tokens[$token]['scope_condition'] = $stackPtr;
                        $tokens[$token]['scope_opener']    = $opener;
                        $tokens[$token]['scope_closer']    = $i;
                    }

                    if ($tokenizer->scopeOpeners[$tokens[$stackPtr]['code']]['shared'] === true) {
                        // As we are going back to where we started originally, restore
                        // the ignore value back to its original value.
                        $ignore = $originalIgnore;
                        return $opener;
                    } else {
                        return $i;
                    }
                }//end if
            } else if ($tokenType === T_OPEN_PARENTHESIS) {
                if (isset($tokens[$i]['parenthesis_owner']) === true) {
                    $owner = $tokens[$i]['parenthesis_owner'];
                    if (in_array($tokens[$owner]['code'], PHP_CodeSniffer_Tokens::$scopeOpeners) === true
                        && isset($tokens[$i]['parenthesis_closer']) === true
                    ) {
                        // If we get into here, then we opened a parenthesis for
                        // a scope (eg. an if or else if). We can just skip to
                        // the closing parenthesis.
                        $i = $tokens[$i]['parenthesis_closer'];

                        // Update the start of the line so that when we check to see
                        // if the closing parenthesis is more than 3 lines away from
                        // the statement, we check from the closing parenthesis.
                        $startLine
                            = $tokens[$tokens[$i]['parenthesis_closer']]['line'];

                        if (PHP_CODESNIFFER_VERBOSITY > 1) {
                            echo str_repeat("\t", $depth);
                            echo '* skipping parenthesis *'.PHP_EOL;
                        }
                    }
                }//end if
            } else if ($tokenType === T_OPEN_CURLY_BRACKET && $opener !== null) {
                // We opened something that we don't have a scope opener for.
                // Examples of this are curly brackets for string offsets etc.
                // We want to ignore this so that we don't have an invalid scope
                // map.
                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                    echo str_repeat("\t", $depth);
                    echo '* ignoring curly brace *'.PHP_EOL;
                }

                $ignore++;
            } else if ($opener === null
                && isset($tokenizer->scopeOpeners[$currType]) === true
            ) {
                // If we still haven't found the opener after 3 lines,
                // we're not going to find it, unless we know it requires
                // an opener (in which case we better keep looking) or the last
                // token was empty (in which case we'll just confirm there is
                // more code in this file and not just a big comment).
                if ($tokens[$i]['line'] >= ($startLine + 3)
                    && in_array($tokens[($i - 1)]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === false
                ) {
                    if ($tokenizer->scopeOpeners[$currType]['strict'] === true) {
                        if (PHP_CODESNIFFER_VERBOSITY > 1) {
                            $type  = $tokens[$stackPtr]['type'];
                            $lines = ($tokens[$i]['line'] - $startLine);
                            echo str_repeat("\t", $depth);
                            echo "=> Still looking for $stackPtr ($type) scope opener after $lines lines".PHP_EOL;
                        }
                    } else {
                        if (PHP_CODESNIFFER_VERBOSITY > 1) {
                            $type = $tokens[$stackPtr]['type'];
                            echo str_repeat("\t", $depth);
                            echo "=> Couldn't find scope opener for $stackPtr ($type), bailing".PHP_EOL;
                        }

                        return $stackPtr;
                    }
                }
            } else if ($opener !== null
                && $tokenType !== T_BREAK
                && in_array($tokenType, $tokenizer->endScopeTokens) === true
            ) {
                if (isset($tokens[$i]['scope_condition']) === false) {
                    if ($ignore > 0) {
                        // We found the end token for the opener we were ignoring.
                        if (PHP_CODESNIFFER_VERBOSITY > 1) {
                            echo str_repeat("\t", $depth);
                            echo '* finished ignoring curly brace *'.PHP_EOL;
                        }

                        $ignore--;
                    } else {
                        // We found a token that closes the scope but it doesn't
                        // have a condition, so it belongs to another token and
                        // our token doesn't have a closer, so pretend this is
                        // the closer.
                        if (PHP_CODESNIFFER_VERBOSITY > 1) {
                            $type = $tokens[$stackPtr]['type'];
                            echo str_repeat("\t", $depth);
                            echo "=> Found (unexpected) scope closer for $stackPtr ($type)".PHP_EOL;
                        }

                        foreach (array($stackPtr, $opener) as $token) {
                            $tokens[$token]['scope_condition'] = $stackPtr;
                            $tokens[$token]['scope_opener']    = $opener;
                            $tokens[$token]['scope_closer']    = $i;
                        }

                        return ($i - 1);
                    }//end if
                }//end if
            }//end if
        }//end for

        return $stackPtr;

    }//end _recurseScopeMap()


    /**
     * Constructs the level map.
     *
     * The level map adds a 'level' indice to each token which indicates the
     * depth that a token within a set of scope blocks. It also adds a
     * 'condition' indice which is an array of the scope conditions that opened
     * each of the scopes - position 0 being the first scope opener.
     *
     * @param array  &$tokens   The array of tokens to process.
     * @param object $tokenizer The tokenizer being used to process this file.
     * @param string $eolChar   The EOL character to use for splitting strings.
     *
     * @return void
     */
    private static function _createLevelMap(&$tokens, $tokenizer, $eolChar)
    {
        if (PHP_CODESNIFFER_VERBOSITY > 1) {
            echo "\t*** START LEVEL MAP ***".PHP_EOL;
        }

        $numTokens  = count($tokens);
        $level      = 0;
        $conditions = array();
        $lastOpener = null;
        $openers    = array();

        for ($i = 0; $i < $numTokens; $i++) {
            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                $type    = $tokens[$i]['type'];
                $line    = $tokens[$i]['line'];
                $content = str_replace($eolChar, '\n', $tokens[$i]['content']);
                echo str_repeat("\t", ($level + 1));
                echo "Process token $i on line $line [lvl:$level;";
                if (empty($conditions) !== true) {
                    $condString = 'conds;';
                    foreach ($conditions as $condition) {
                        $condString .= token_name($condition).',';
                    }

                    echo rtrim($condString, ',').';';
                }

                echo "]: $type => $content".PHP_EOL;
            }

            $tokens[$i]['level']      = $level;
            $tokens[$i]['conditions'] = $conditions;

            if (isset($tokens[$i]['scope_condition']) === true) {
                // Check to see if this token opened the scope.
                if ($tokens[$i]['scope_opener'] === $i) {
                    $stackPtr = $tokens[$i]['scope_condition'];
                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        $type = $tokens[$stackPtr]['type'];
                        echo str_repeat("\t", ($level + 1));
                        echo "=> Found scope opener for $stackPtr ($type)".PHP_EOL;
                    }

                    $stackPtr = $tokens[$i]['scope_condition'];

                    // If we find a scope opener that has a shared closer,
                    // then we need to go back over the condition map that we
                    // just created and fix ourselves as we just added some
                    // conditions where there was none. This happens for T_CASE
                    // statements that are using the same break statement.
                    if ($lastOpener !== null && $tokens[$lastOpener]['scope_closer'] === $tokens[$i]['scope_closer']) {
                        // This opener shares its closer with the previous opener,
                        // but we still need to check if the two openers share their
                        // closer with each other directly (like CASE and DEFAULT)
                        // or if they are just sharing because one doesn't have a
                        // closer (like CASE with no BREAK using a SWITCHes closer).
                        $thisType = $tokens[$tokens[$i]['scope_condition']]['code'];
                        $opener   = $tokens[$lastOpener]['scope_condition'];

                        $isShared = in_array(
                            $tokens[$opener]['code'],
                            $tokenizer->scopeOpeners[$thisType]['with']
                        );

                        $sameEnd = ($tokenizer->scopeOpeners[$thisType]['end'][0] === $tokenizer->scopeOpeners[$tokens[$opener]['code']]['end'][0]);
                        if ($isShared === true && $sameEnd === true) {
                            $badToken = $opener;
                            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                                $type = $tokens[$badToken]['type'];
                                echo str_repeat("\t", ($level + 1));
                                echo "* shared closer, cleaning up $badToken ($type) *".PHP_EOL;
                            }

                            for ($x = $tokens[$i]['scope_condition']; $x <= $i; $x++) {
                                $oldConditions = $tokens[$x]['conditions'];
                                $oldLevel      = $tokens[$x]['level'];
                                $tokens[$x]['level']--;
                                unset($tokens[$x]['conditions'][$badToken]);
                                if (PHP_CODESNIFFER_VERBOSITY > 1) {
                                    $type     = $tokens[$x]['type'];
                                    $oldConds = '';
                                    foreach ($oldConditions as $condition) {
                                        $oldConds .= token_name($condition).',';
                                    }

                                    $oldConds = rtrim($oldConds, ',');

                                    $newConds = '';
                                    foreach ($tokens[$x]['conditions'] as $condition) {
                                        $newConds .= token_name($condition).',';
                                    }

                                    $newConds = rtrim($newConds, ',');

                                    $newLevel = $tokens[$x]['level'];
                                    echo str_repeat("\t", ($level + 1));
                                    echo "* cleaned $x ($type) *".PHP_EOL;
                                    echo str_repeat("\t", ($level + 2));
                                    echo "=> level changed from $oldLevel to $newLevel".PHP_EOL;
                                    echo str_repeat("\t", ($level + 2));
                                    echo "=> conditions changed from $oldConds to $newConds".PHP_EOL;
                                }//end if
                            }//end for

                            unset($conditions[$badToken]);
                            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                                $type = $tokens[$badToken]['type'];
                                echo str_repeat("\t", ($level + 1));
                                echo "* token $badToken ($type) removed from conditions array *".PHP_EOL;
                            }

                            unset ($openers[$lastOpener]);

                            $level--;
                            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                                echo str_repeat("\t", ($level + 2));
                                echo '* level decreased *'.PHP_EOL;
                            }
                        }//end if
                    }//end if

                    $level++;
                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        echo str_repeat("\t", ($level + 1));
                        echo '* level increased *'.PHP_EOL;
                    }

                    $conditions[$stackPtr] = $tokens[$stackPtr]['code'];
                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                        $type = $tokens[$stackPtr]['type'];
                        echo str_repeat("\t", ($level + 1));
                        echo "* token $stackPtr ($type) added to conditions array *".PHP_EOL;
                    }

                    $lastOpener = $tokens[$i]['scope_opener'];
                    if ($lastOpener !== null) {
                        $openers[$lastOpener] = $lastOpener;
                    }
                } else if ($tokens[$i]['scope_closer'] === $i) {
                    foreach (array_reverse($openers) as $opener) {
                        if ($tokens[$opener]['scope_closer'] === $i) {
                            $oldOpener = array_pop($openers);
                            if (empty($openers) === false) {
                                $lastOpener           = array_pop($openers);
                                $openers[$lastOpener] = $lastOpener;
                            } else {
                                $lastOpener = null;
                            }

                            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                                $type = $tokens[$oldOpener]['type'];
                                echo str_repeat("\t", ($level + 1));
                                echo "=> Found scope closer for $oldOpener ($type)".PHP_EOL;
                            }

                            $oldCondition = array_pop($conditions);
                            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                                echo str_repeat("\t", ($level + 1));
                                echo '* token '.token_name($oldCondition).' removed from conditions array *'.PHP_EOL;
                            }

                            // Make sure this closer actually belongs to us.
                            // Either the condition also has to think this is the
                            // closer, or it has to allow sharing with us.
                            $condition
                                = $tokens[$tokens[$i]['scope_condition']]['code'];
                            if ($condition !== $oldCondition) {
                                if (in_array($condition, $tokenizer->scopeOpeners[$oldCondition]['with']) === false) {
                                    $badToken = $tokens[$oldOpener]['scope_condition'];

                                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
                                        $type = token_name($oldCondition);
                                        echo str_repeat("\t", ($level + 1));
                                        echo "* scope closer was bad, cleaning up $badToken ($type) *".PHP_EOL;
                                    }

                                    for ($x = ($oldOpener + 1); $x <= $i; $x++) {
                                        $oldConditions = $tokens[$x]['conditions'];
                                        $oldLevel      = $tokens[$x]['level'];
                                        $tokens[$x]['level']--;
                                        unset($tokens[$x]['conditions'][$badToken]);
                                        if (PHP_CODESNIFFER_VERBOSITY > 1) {
                                            $type     = $tokens[$x]['type'];
                                            $oldConds = '';
                                            foreach ($oldConditions as $condition) {
                                                $oldConds .= token_name($condition).',';
                                            }

                                            $oldConds = rtrim($oldConds, ',');

                                            $newConds = '';
                                            foreach ($tokens[$x]['conditions'] as $condition) {
                                                $newConds .= token_name($condition).',';
                                            }

                                            $newConds = rtrim($newConds, ',');

                                            $newLevel = $tokens[$x]['level'];
                                            echo str_repeat("\t", ($level + 1));
                                            echo "* cleaned $x ($type) *".PHP_EOL;
                                            echo str_repeat("\t", ($level + 2));
                                            echo "=> level changed from $oldLevel to $newLevel".PHP_EOL;
                                            echo str_repeat("\t", ($level + 2));
                                            echo "=> conditions changed from $oldConds to $newConds".PHP_EOL;
                                        }//end if
                                    }//end for
                                }//end if
                            }//end if

                            $level--;
                            if (PHP_CODESNIFFER_VERBOSITY > 1) {
                                echo str_repeat("\t", ($level + 2));
                                echo '* level decreased *'.PHP_EOL;
                            }

                            $tokens[$i]['level']      = $level;
                            $tokens[$i]['conditions'] = $conditions;
                        }//end if
                    }//end foreach
                }//end if
            }//end if
        }//end for

        if (PHP_CODESNIFFER_VERBOSITY > 1) {
            echo "\t*** END LEVEL MAP ***".PHP_EOL;
        }

    }//end _createLevelMap()


    /**
     * Returns the declaration names for T_CLASS, T_INTERFACE and T_FUNCTION tokens.
     *
     * @param int $stackPtr The position of the declaration token which
     *                      declared the class, interface or function.
     *
     * @return string|null The name of the class, interface or function.
     *                     or NULL if the function is a closure.
     * @throws PHP_CodeSniffer_Exception If the specified token is not of type
     *                                   T_FUNCTION, T_CLASS or T_INTERFACE.
     */
    public function getDeclarationName($stackPtr)
    {
        $tokenCode = $this->_tokens[$stackPtr]['code'];
        if ($tokenCode !== T_FUNCTION
            && $tokenCode !== T_CLASS
            && $tokenCode !== T_INTERFACE
            && $tokenCode !== T_TRAIT
        ) {
            throw new PHP_CodeSniffer_Exception('Token type is not T_FUNCTION, T_CLASS, T_INTERFACE or T_TRAIT');
        }

        if ($tokenCode === T_FUNCTION
            && $this->isAnonymousFunction($stackPtr) === true
        ) {
            return null;
        }

        $token = $this->findNext(T_STRING, $stackPtr);
        return $this->_tokens[$token]['content'];

    }//end getDeclarationName()


    /**
     * Check if the token at the specified position is a anonymous function.
     *
     * @param int $stackPtr The position of the declaration token which
     *                      declared the class, interface or function.
     *
     * @return boolean
     * @throws PHP_CodeSniffer_Exception If the specified token is not of type
     *                                   T_FUNCTION
     */
    public function isAnonymousFunction($stackPtr)
    {
        $tokenCode = $this->_tokens[$stackPtr]['code'];
        if ($tokenCode !== T_FUNCTION) {
            throw new PHP_CodeSniffer_Exception('Token type is not T_FUNCTION');
        }

        if (isset($this->_tokens[$stackPtr]['parenthesis_opener']) === false) {
            // Something is not right with this function.
            return false;
        }

        $name = $this->findNext(T_STRING, ($stackPtr + 1));
        if ($name === false) {
            // No name found.
            return true;
        }

        $open = $this->_tokens[$stackPtr]['parenthesis_opener'];
        if ($name > $open) {
            return true;
        }

        return false;

    }//end isAnonymousFunction()


    /**
     * Returns the method parameters for the specified T_FUNCTION token.
     *
     * Each parameter is in the following format:
     *
     * <code>
     *   0 => array(
     *         'name'              => '$var',  // The variable name.
     *         'pass_by_reference' => false,   // Passed by reference.
     *         'type_hint'         => string,  // Type hint for array or custom type
     *        )
     * </code>
     *
     * Parameters with default values have and additional array indice of
     * 'default' with the value of the default as a string.
     *
     * @param int $stackPtr The position in the stack of the T_FUNCTION token
     *                      to acquire the parameters for.
     *
     * @return array()
     * @throws PHP_CodeSniffer_Exception If the specified $stackPtr is not of
     *                                   type T_FUNCTION.
     */
    public function getMethodParameters($stackPtr)
    {
        if ($this->_tokens[$stackPtr]['code'] !== T_FUNCTION) {
            throw new PHP_CodeSniffer_Exception('$stackPtr must be of type T_FUNCTION');
        }

        $opener = $this->_tokens[$stackPtr]['parenthesis_opener'];
        $closer = $this->_tokens[$stackPtr]['parenthesis_closer'];

        $vars            = array();
        $currVar         = null;
        $defaultStart    = null;
        $paramCount      = 0;
        $passByReference = false;
        $typeHint        = '';

        for ($i = ($opener + 1); $i <= $closer; $i++) {
            // Check to see if this token has a parenthesis opener. If it does
            // its likely to be an array, which might have arguments in it, which
            // we cause problems in our parsing below, so lets just skip to the
            // end of it.
            if (isset($this->_tokens[$i]['parenthesis_opener']) === true) {
                // Don't do this if it's the close parenthesis for the method.
                if ($i !== $this->_tokens[$i]['parenthesis_closer']) {
                    $i = ($this->_tokens[$i]['parenthesis_closer'] + 1);
                }
            }

            switch ($this->_tokens[$i]['code']) {
            case T_BITWISE_AND:
                $passByReference = true;
                break;
            case T_VARIABLE:
                $currVar = $i;
                break;
            case T_ARRAY_HINT:
            case T_CALLABLE:
                $typeHint = $this->_tokens[$i]['content'];
                break;
            case T_STRING:
                // This is a string, so it may be a type hint, but it could
                // also be a constant used as a default value.
                $prevComma = $this->findPrevious(T_COMMA, $i, $opener);
                if ($prevComma !== false) {
                    $nextEquals = $this->findNext(T_EQUAL, $prevComma, $i);
                    if ($nextEquals !== false) {
                        break;
                    }
                }

                if ($defaultStart === null) {
                    $typeHint .= $this->_tokens[$i]['content'];
                }

                break;
            case T_NS_SEPARATOR:
                // Part of a type hint or default value.
                if ($defaultStart === null) {
                    $typeHint .= $this->_tokens[$i]['content'];
                }

                break;
            case T_CLOSE_PARENTHESIS:
            case T_COMMA:
                // If it's null, then there must be no parameters for this
                // method.
                if ($currVar === null) {
                    continue;
                }

                $vars[$paramCount]         = array();
                $vars[$paramCount]['name'] = $this->_tokens[$currVar]['content'];

                if ($defaultStart !== null) {
                    $vars[$paramCount]['default']
                        = $this->getTokensAsString(
                            $defaultStart,
                            ($i - $defaultStart)
                        );
                }

                $vars[$paramCount]['pass_by_reference'] = $passByReference;
                $vars[$paramCount]['type_hint']         = $typeHint;

                // Reset the vars, as we are about to process the next parameter.
                $defaultStart    = null;
                $passByReference = false;
                $typeHint        = '';

                $paramCount++;
                break;
            case T_EQUAL:
                $defaultStart = ($i + 1);
                break;
            }//end switch
        }//end for

        return $vars;

    }//end getMethodParameters()


    /**
     * Returns the visibility and implementation properties of a method.
     *
     * The format of the array is:
     * <code>
     *   array(
     *    'scope'           => 'public', // public private or protected
     *    'scope_specified' => true,     // true is scope keyword was found.
     *    'is_abstract'     => false,    // true if the abstract keyword was found.
     *    'is_final'        => false,    // true if the final keyword was found.
     *    'is_static'       => false,    // true if the static keyword was found.
     *    'is_closure'      => false,    // true if no name is found.
     *   );
     * </code>
     *
     * @param int $stackPtr The position in the stack of the T_FUNCTION token to
     *                      acquire the properties for.
     *
     * @return array
     * @throws PHP_CodeSniffer_Exception If the specified position is not a
     *                                   T_FUNCTION token.
     */
    public function getMethodProperties($stackPtr)
    {
        if ($this->_tokens[$stackPtr]['code'] !== T_FUNCTION) {
            throw new PHP_CodeSniffer_Exception('$stackPtr must be of type T_FUNCTION');
        }

        $valid = array(
                  T_PUBLIC,
                  T_PRIVATE,
                  T_PROTECTED,
                  T_STATIC,
                  T_FINAL,
                  T_ABSTRACT,
                  T_WHITESPACE,
                  T_COMMENT,
                  T_DOC_COMMENT,
                 );

        $scope          = 'public';
        $scopeSpecified = false;
        $isAbstract     = false;
        $isFinal        = false;
        $isStatic       = false;
        $isClosure      = $this->isAnonymousFunction($stackPtr);

        for ($i = ($stackPtr - 1); $i > 0; $i--) {
            if (in_array($this->_tokens[$i]['code'], $valid) === false) {
                break;
            }

            switch ($this->_tokens[$i]['code']) {
            case T_PUBLIC:
                $scope          = 'public';
                $scopeSpecified = true;
                break;
            case T_PRIVATE:
                $scope          = 'private';
                $scopeSpecified = true;
                break;
            case T_PROTECTED:
                $scope          = 'protected';
                $scopeSpecified = true;
                break;
            case T_ABSTRACT:
                $isAbstract = true;
                break;
            case T_FINAL:
                $isFinal = true;
                break;
            case T_STATIC:
                $isStatic = true;
                break;
            }//end switch
        }//end for

        return array(
                'scope'           => $scope,
                'scope_specified' => $scopeSpecified,
                'is_abstract'     => $isAbstract,
                'is_final'        => $isFinal,
                'is_static'       => $isStatic,
                'is_closure'      => $isClosure,
               );

    }//end getMethodProperties()


    /**
     * Returns the visibility and implementation properties of the class member
     * variable found at the specified position in the stack.
     *
     * The format of the array is:
     *
     * <code>
     *   array(
     *    'scope'       => 'public', // public private or protected
     *    'is_static'   => false,    // true if the static keyword was found.
     *   );
     * </code>
     *
     * @param int $stackPtr The position in the stack of the T_VARIABLE token to
     *                      acquire the properties for.
     *
     * @return array
     * @throws PHP_CodeSniffer_Exception If the specified position is not a
     *                                   T_VARIABLE token, or if the position is not
     *                                   a class member variable.
     */
    public function getMemberProperties($stackPtr)
    {
        if ($this->_tokens[$stackPtr]['code'] !== T_VARIABLE) {
            throw new PHP_CodeSniffer_Exception('$stackPtr must be of type T_VARIABLE');
        }

        $conditions = array_keys($this->_tokens[$stackPtr]['conditions']);
        $ptr        = array_pop($conditions);
        if (isset($this->_tokens[$ptr]) === false
            || $this->_tokens[$ptr]['code'] !== T_CLASS
        ) {
            if (isset($this->_tokens[$ptr]) === true
                && $this->_tokens[$ptr]['code'] === T_INTERFACE
            ) {
                // T_VARIABLEs in interfaces can actually be method arguments
                // but they wont be seen as being inside the method because there
                // are no scope openers and closers for abstract methods. If it is in
                // parentheses, we can be pretty sure it is a method argument.
                if (isset($this->_tokens[$stackPtr]['nested_parenthesis']) === false
                    || empty($this->_tokens[$stackPtr]['nested_parenthesis']) === true
                ) {
                    $error = 'Possible parse error: interfaces may not include member vars';
                    $this->addWarning($error, $stackPtr, 'Internal.ParseError.InterfaceHasMemberVar');
                    return array();
                }
            } else {
                throw new PHP_CodeSniffer_Exception('$stackPtr is not a class member var');
            }
        }

        $valid = array(
                  T_PUBLIC,
                  T_PRIVATE,
                  T_PROTECTED,
                  T_STATIC,
                  T_WHITESPACE,
                  T_COMMENT,
                  T_DOC_COMMENT,
                  T_VARIABLE,
                  T_COMMA,
                 );

        $scope          = 'public';
        $scopeSpecified = false;
        $isStatic       = false;

        for ($i = ($stackPtr - 1); $i > 0; $i--) {
            if (in_array($this->_tokens[$i]['code'], $valid) === false) {
                break;
            }

            switch ($this->_tokens[$i]['code']) {
            case T_PUBLIC:
                $scope          = 'public';
                $scopeSpecified = true;
                break;
            case T_PRIVATE:
                $scope          = 'private';
                $scopeSpecified = true;
                break;
            case T_PROTECTED:
                $scope          = 'protected';
                $scopeSpecified = true;
                break;
            case T_STATIC:
                $isStatic = true;
                break;
            }
        }//end for

        return array(
                'scope'           => $scope,
                'scope_specified' => $scopeSpecified,
                'is_static'       => $isStatic,
               );

    }//end getMemberProperties()


    /**
     * Returns the visibility and implementation properties of a class.
     *
     * The format of the array is:
     * <code>
     *   array(
     *    'is_abstract' => false, // true if the abstract keyword was found.
     *    'is_final'    => false, // true if the final keyword was found.
     *   );
     * </code>
     *
     * @param int $stackPtr The position in the stack of the T_CLASS token to
     *                      acquire the properties for.
     *
     * @return array
     * @throws PHP_CodeSniffer_Exception If the specified position is not a
     *                                   T_CLASS token.
     */
    public function getClassProperties($stackPtr)
    {
        if ($this->_tokens[$stackPtr]['code'] !== T_CLASS) {
            throw new PHP_CodeSniffer_Exception('$stackPtr must be of type T_CLASS');
        }

        $valid = array(
                  T_FINAL,
                  T_ABSTRACT,
                  T_WHITESPACE,
                  T_COMMENT,
                  T_DOC_COMMENT,
                 );

        $isAbstract = false;
        $isFinal    = false;

        for ($i = ($stackPtr - 1); $i > 0; $i--) {
            if (in_array($this->_tokens[$i]['code'], $valid) === false) {
                break;
            }

            switch ($this->_tokens[$i]['code']) {
            case T_ABSTRACT:
                $isAbstract = true;
                break;

            case T_FINAL:
                $isFinal = true;
                break;
            }
        }//end for

        return array(
                'is_abstract' => $isAbstract,
                'is_final'    => $isFinal,
               );

    }//end getClassProperties()


    /**
     * Determine if the passed token is a reference operator.
     *
     * Returns true if the specified token position represents a reference.
     * Returns false if the token represents a bitwise operator.
     *
     * @param int $stackPtr The position of the T_BITWISE_AND token.
     *
     * @return boolean
     */
    public function isReference($stackPtr)
    {
        if ($this->_tokens[$stackPtr]['code'] !== T_BITWISE_AND) {
            return false;
        }

        $tokenBefore = $this->findPrevious(
            PHP_CodeSniffer_Tokens::$emptyTokens,
            ($stackPtr - 1),
            null,
            true
        );

        if ($this->_tokens[$tokenBefore]['code'] === T_FUNCTION) {
            // Function returns a reference.
            return true;
        }

        if ($this->_tokens[$tokenBefore]['code'] === T_DOUBLE_ARROW) {
            // Inside a foreach loop, this is a reference.
            return true;
        }

        if ($this->_tokens[$tokenBefore]['code'] === T_AS) {
            // Inside a foreach loop, this is a reference.
            return true;
        }

        if (in_array($this->_tokens[$tokenBefore]['code'], PHP_CodeSniffer_Tokens::$assignmentTokens) === true) {
            // This is directly after an assignment. It's a reference. Even if
            // it is part of an operation, the other tests will handle it.
            return true;
        }

        if (isset($this->_tokens[$stackPtr]['nested_parenthesis']) === true) {
            $brackets    = $this->_tokens[$stackPtr]['nested_parenthesis'];
            $lastBracket = array_pop($brackets);
            if (isset($this->_tokens[$lastBracket]['parenthesis_owner']) === true) {
                $owner = $this->_tokens[$this->_tokens[$lastBracket]['parenthesis_owner']];
                if ($owner['code'] === T_FUNCTION
                    || $owner['code'] === T_CLOSURE
                    || $owner['code'] === T_ARRAY
                ) {
                    // Inside a function or array declaration, this is a reference.
                    return true;
                }
            } else {
                $prev = $this->findPrevious(
                    array(T_WHITESPACE),
                    ($this->_tokens[$lastBracket]['parenthesis_opener'] - 1),
                    null,
                    true
                );

                if ($prev !== false && $this->_tokens[$prev]['code'] === T_USE) {
                    return true;
                }
            }
        }

        $tokenAfter = $this->findNext(
            PHP_CodeSniffer_Tokens::$emptyTokens,
            ($stackPtr + 1),
            null,
            true
        );

        if ($this->_tokens[$tokenAfter]['code'] === T_VARIABLE
            && ($this->_tokens[$tokenBefore]['code'] === T_OPEN_PARENTHESIS
            || $this->_tokens[$tokenBefore]['code'] === T_COMMA)
        ) {
            return true;
        }

        return false;

    }//end isReference()


    /**
     * Returns the content of the tokens from the specified start position in
     * the token stack for the specified length.
     *
     * @param int $start  The position to start from in the token stack.
     * @param int $length The length of tokens to traverse from the start pos.
     *
     * @return string The token contents.
     */
    public function getTokensAsString($start, $length)
    {
        $str = '';
        $end = ($start + $length);
        if ($end > $this->numTokens) {
            $end = $this->numTokens;
        }

        for ($i = $start; $i < $end; $i++) {
            $str .= $this->_tokens[$i]['content'];
        }

        return $str;

    }//end getTokensAsString()


    /**
     * Returns the position of the next specified token(s).
     *
     * If a value is specified, the next token of the specified type(s)
     * containing the specified value will be returned.
     *
     * Returns false if no token can be found.
     *
     * @param int|array $types   The type(s) of tokens to search for.
     * @param int       $start   The position to start searching from in the
     *                           token stack.
     * @param int       $end     The end position to fail if no token is found.
     *                           if not specified or null, end will default to
     *                           the start of the token stack.
     * @param bool      $exclude If true, find the next token that are NOT of
     *                           the types specified in $types.
     * @param string    $value   The value that the token(s) must be equal to.
     *                           If value is omitted, tokens with any value will
     *                           be returned.
     * @param bool      $local   If true, tokens outside the current statement
     *                           will not be checked. IE. checking will stop
     *                           at the next semi-colon found.
     *
     * @return int | bool
     * @see findNext()
     */
    public function findPrevious(
        $types,
        $start,
        $end=null,
        $exclude=false,
        $value=null,
        $local=false
    ) {
        $types = (array) $types;

        if ($end === null) {
            $end = 0;
        }

        for ($i = $start; $i >= $end; $i--) {
            $found = (bool) $exclude;
            foreach ($types as $type) {
                if ($this->_tokens[$i]['code'] === $type) {
                    $found = !$exclude;
                    break;
                }
            }

            if ($found === true) {
                if ($value === null) {
                    return $i;
                } else if ($this->_tokens[$i]['content'] === $value) {
                    return $i;
                }
            }

            if ($local === true && $this->_tokens[$i]['code'] === T_SEMICOLON) {
                break;
            }
        }//end for

        return false;

    }//end findPrevious()


    /**
     * Returns the position of the next specified token(s).
     *
     * If a value is specified, the next token of the specified type(s)
     * containing the specified value will be returned.
     *
     * Returns false if no token can be found.
     *
     * @param int|array $types   The type(s) of tokens to search for.
     * @param int       $start   The position to start searching from in the
     *                           token stack.
     * @param int       $end     The end position to fail if no token is found.
     *                           if not specified or null, end will default to
     *                           the end of the token stack.
     * @param bool      $exclude If true, find the next token that is NOT of
     *                           a type specified in $types.
     * @param string    $value   The value that the token(s) must be equal to.
     *                           If value is omitted, tokens with any value will
     *                           be returned.
     * @param bool      $local   If true, tokens outside the current statement
     *                           will not be checked. i.e., checking will stop
     *                           at the next semi-colon found.
     *
     * @return int | bool
     * @see findPrevious()
     */
    public function findNext(
        $types,
        $start,
        $end=null,
        $exclude=false,
        $value=null,
        $local=false
    ) {
        $types = (array) $types;

        if ($end === null || $end > $this->numTokens) {
            $end = $this->numTokens;
        }

        for ($i = $start; $i < $end; $i++) {
            $found = (bool) $exclude;
            foreach ($types as $type) {
                if ($this->_tokens[$i]['code'] === $type) {
                    $found = !$exclude;
                    break;
                }
            }

            if ($found === true) {
                if ($value === null) {
                    return $i;
                } else if ($this->_tokens[$i]['content'] === $value) {
                    return $i;
                }
            }

            if ($local === true && $this->_tokens[$i]['code'] === T_SEMICOLON) {
                break;
            }
        }//end for

        return false;

    }//end findNext()


    /**
     * Returns the position of the first token on a line, matching given type.
     *
     * Returns false if no token can be found.
     *
     * @param int|array $types   The type(s) of tokens to search for.
     * @param int       $start   The position to start searching from in the
     *                           token stack. The first token matching on
     *                           this line before this token will be returned.
     * @param bool      $exclude If true, find the token that is NOT of
     *                           the types specified in $types.
     * @param string    $value   The value that the token must be equal to.
     *                           If value is omitted, tokens with any value will
     *                           be returned.
     *
     * @return int | bool
     */
    public function findFirstOnLine($types, $start, $exclude=false, $value=null)
    {
        if (is_array($types) === false) {
            $types = array($types);
        }

        $foundToken = false;

        for ($i = $start; $i >= 0; $i--) {
            if ($this->_tokens[$i]['line'] < $this->_tokens[$start]['line']) {
                break;
            }

            $found = $exclude;
            foreach ($types as $type) {
                if ($exclude === false) {
                    if ($this->_tokens[$i]['code'] === $type) {
                        $found = true;
                        break;
                    }
                } else {
                    if ($this->_tokens[$i]['code'] === $type) {
                        $found = false;
                        break;
                    }
                }
            }

            if ($found === true) {
                if ($value === null) {
                    $foundToken = $i;
                } else if ($this->_tokens[$i]['content'] === $value) {
                    $foundToken = $i;
                }
            }
        }//end for

        return $foundToken;

    }//end findFirstOnLine()


    /**
     * Determine if the passed token has a condition of one of the passed types.
     *
     * @param int       $stackPtr The position of the token we are checking.
     * @param int|array $types    The type(s) of tokens to search for.
     *
     * @return boolean
     */
    public function hasCondition($stackPtr, $types)
    {
        // Check for the existence of the token.
        if (isset($this->_tokens[$stackPtr]) === false) {
            return false;
        }

        // Make sure the token has conditions.
        if (isset($this->_tokens[$stackPtr]['conditions']) === false) {
            return false;
        }

        $types      = (array) $types;
        $conditions = $this->_tokens[$stackPtr]['conditions'];

        foreach ($types as $type) {
            if (in_array($type, $conditions) === true) {
                // We found a token with the required type.
                return true;
            }
        }

        return false;

    }//end hasCondition()


    /**
     * Return the position of the condition for the passed token.
     *
     * Returns FALSE if the token does not have the condition.
     *
     * @param int $stackPtr The position of the token we are checking.
     * @param int $type     The type of token to search for.
     *
     * @return int
     */
    public function getCondition($stackPtr, $type)
    {
        // Check for the existence of the token.
        if (isset($this->_tokens[$stackPtr]) === false) {
            return false;
        }

        // Make sure the token has conditions.
        if (isset($this->_tokens[$stackPtr]['conditions']) === false) {
            return false;
        }

        $conditions = $this->_tokens[$stackPtr]['conditions'];
        foreach ($conditions as $token => $condition) {
            if ($condition === $type) {
                return $token;
            }
        }

        return false;

    }//end getCondition()


    /**
     * Returns the name of the class that the specified class extends.
     *
     * Returns FALSE on error or if there is no extended class name.
     *
     * @param int $stackPtr The stack position of the class.
     *
     * @return string
     */
    public function findExtendedClassName($stackPtr)
    {
        // Check for the existence of the token.
        if (isset($this->_tokens[$stackPtr]) === false) {
            return false;
        }

        if ($this->_tokens[$stackPtr]['code'] !== T_CLASS) {
            return false;
        }

        if (isset($this->_tokens[$stackPtr]['scope_closer']) === false) {
            return false;
        }

        $classCloserIndex = $this->_tokens[$stackPtr]['scope_closer'];
        $extendsIndex     = $this->findNext(T_EXTENDS, $stackPtr, $classCloserIndex);
        if (false === $extendsIndex) {
            return false;
        }

        $find = array(
                 T_NS_SEPARATOR,
                 T_STRING,
                 T_WHITESPACE,
                );

        $end  = $this->findNext($find, ($extendsIndex + 1), $classCloserIndex, true);
        $name = $this->getTokensAsString(($extendsIndex + 1), ($end - $extendsIndex - 1));
        $name = trim($name);

        if ($name === '') {
            return false;
        }

        return $name;

    }//end findExtendedClassName()


}//end class

?>
<?php
/**
 * The Tokens class contains weightings for tokens based on their
 * probability of occurrence in a file.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

define('T_NONE', 0);
define('T_OPEN_CURLY_BRACKET', 1000);
define('T_CLOSE_CURLY_BRACKET', 1001);
define('T_OPEN_SQUARE_BRACKET', 1002);
define('T_CLOSE_SQUARE_BRACKET', 1003);
define('T_OPEN_PARENTHESIS', 1004);
define('T_CLOSE_PARENTHESIS', 1005);
define('T_COLON', 1006);
define('T_STRING_CONCAT', 1007);
define('T_INLINE_THEN', 1008);
define('T_INLINE_ELSE', 1009);
define('T_NULL', 1010);
define('T_FALSE', 1011);
define('T_TRUE', 1012);
define('T_SEMICOLON', 1013);
define('T_EQUAL', 1014);
define('T_MULTIPLY', 1015);
define('T_DIVIDE', 1016);
define('T_PLUS', 1017);
define('T_MINUS', 1018);
define('T_MODULUS', 1019);
define('T_POWER', 1020);
define('T_BITWISE_AND', 1021);
define('T_BITWISE_OR', 1022);
define('T_ARRAY_HINT', 1023);
define('T_GREATER_THAN', 1024);
define('T_LESS_THAN', 1025);
define('T_BOOLEAN_NOT', 1026);
define('T_SELF', 1027);
define('T_PARENT', 1028);
define('T_DOUBLE_QUOTED_STRING', 1029);
define('T_COMMA', 1030);
define('T_HEREDOC', 1031);
define('T_PROTOTYPE', 1032);
define('T_THIS', 1033);
define('T_REGULAR_EXPRESSION', 1034);
define('T_PROPERTY', 1035);
define('T_LABEL', 1036);
define('T_OBJECT', 1037);
define('T_COLOUR', 1038);
define('T_HASH', 1039);
define('T_URL', 1040);
define('T_STYLE', 1041);
define('T_ASPERAND', 1042);
define('T_DOLLAR', 1043);
define('T_TYPEOF', 1044);
define('T_CLOSURE', 1045);
define('T_BACKTICK', 1046);
define('T_START_NOWDOC', 1047);
define('T_NOWDOC', 1048);
define('T_END_NOWDOC', 1049);
define('T_OPEN_SHORT_ARRAY', 1050);
define('T_CLOSE_SHORT_ARRAY', 1051);
define('T_GOTO_LABEL', 1052);

// Some PHP 5.3 tokens, replicated for lower versions.
if (defined('T_NAMESPACE') === false) {
    define('T_NAMESPACE', 1053);
}

if (defined('T_NS_SEPARATOR') === false) {
    define('T_NS_SEPARATOR', 1054);
}

if (defined('T_GOTO') === false) {
    define('T_GOTO', 1055);
}

// Some PHP 5.4 tokens, replicated for lower versions.
if (defined('T_TRAIT') === false) {
    define('T_TRAIT', 1056);
}

if (defined('T_INSTEADOF') === false) {
    define('T_INSTEADOF', 1057);
}

if (defined('T_CALLABLE') === false) {
    define('T_CALLABLE', 1058);
}

// Some PHP 5.5 tokens, replicated for lower versions.
if (defined('T_FINALLY') === false) {
    define('T_FINALLY', 1059);
}

/**
 * The Tokens class contains weightings for tokens based on their
 * probability of occurrence in a file.
 *
 * The less the chance of a high occurrence of an arbitrary token, the higher
 * the weighting.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
final class PHP_CodeSniffer_Tokens
{

    /**
     * The token weightings.
     *
     * @var array(int => int)
     */
    public static $weightings = array(
                                 T_CLASS               => 1000,
                                 T_INTERFACE           => 1000,
                                 T_TRAIT               => 1000,
                                 T_NAMESPACE           => 1000,
                                 T_FUNCTION            => 100,
                                 T_CLOSURE             => 100,

                                 /*
                                     Conditions.
                                 */

                                 T_WHILE               => 50,
                                 T_FOR                 => 50,
                                 T_FOREACH             => 50,
                                 T_IF                  => 50,
                                 T_ELSE                => 50,
                                 T_ELSEIF              => 50,
                                 T_WHILE               => 50,
                                 T_DO                  => 50,
                                 T_TRY                 => 50,
                                 T_CATCH               => 50,
                                 T_SWITCH              => 50,

                                 T_SELF                => 25,
                                 T_PARENT              => 25,

                                 /*
                                     Operators and arithmetic.
                                 */

                                 T_BITWISE_AND         => 8,
                                 T_BITWISE_OR          => 8,

                                 T_MULTIPLY            => 5,
                                 T_DIVIDE              => 5,
                                 T_PLUS                => 5,
                                 T_MINUS               => 5,
                                 T_MODULUS             => 5,
                                 T_POWER               => 5,

                                 T_EQUAL               => 5,
                                 T_AND_EQUAL           => 5,
                                 T_CONCAT_EQUAL        => 5,
                                 T_DIV_EQUAL           => 5,
                                 T_MINUS_EQUAL         => 5,
                                 T_MOD_EQUAL           => 5,
                                 T_MUL_EQUAL           => 5,
                                 T_OR_EQUAL            => 5,
                                 T_PLUS_EQUAL          => 5,
                                 T_XOR_EQUAL           => 5,

                                 T_BOOLEAN_AND         => 5,
                                 T_BOOLEAN_OR          => 5,

                                 /*
                                     Equality.
                                 */

                                 T_IS_EQUAL            => 5,
                                 T_IS_NOT_EQUAL        => 5,
                                 T_IS_IDENTICAL        => 5,
                                 T_IS_NOT_IDENTICAL    => 5,
                                 T_IS_SMALLER_OR_EQUAL => 5,
                                 T_IS_GREATER_OR_EQUAL => 5,
                                );

    /**
     * Tokens that represent assignments.
     *
     * @var array(int)
     */
    public static $assignmentTokens = array(
                                       T_EQUAL,
                                       T_AND_EQUAL,
                                       T_CONCAT_EQUAL,
                                       T_DIV_EQUAL,
                                       T_MINUS_EQUAL,
                                       T_MOD_EQUAL,
                                       T_MUL_EQUAL,
                                       T_PLUS_EQUAL,
                                       T_XOR_EQUAL,
                                       T_DOUBLE_ARROW,
                                      );

    /**
     * Tokens that represent equality comparisons.
     *
     * @var array(int)
     */
    public static $equalityTokens = array(
                                     T_IS_EQUAL,
                                     T_IS_NOT_EQUAL,
                                     T_IS_IDENTICAL,
                                     T_IS_NOT_IDENTICAL,
                                     T_IS_SMALLER_OR_EQUAL,
                                     T_IS_GREATER_OR_EQUAL,
                                    );

    /**
     * Tokens that represent comparison operator.
     *
     * @var array(int)
     */
    public static $comparisonTokens = array(
                                       T_IS_EQUAL,
                                       T_IS_IDENTICAL,
                                       T_IS_NOT_EQUAL,
                                       T_IS_NOT_IDENTICAL,
                                       T_LESS_THAN,
                                       T_GREATER_THAN,
                                       T_IS_SMALLER_OR_EQUAL,
                                       T_IS_GREATER_OR_EQUAL,
                                      );

    /**
     * Tokens that represent arithmetic operators.
     *
     * @var array(int)
     */
    public static $arithmeticTokens = array(
                                       T_PLUS,
                                       T_MINUS,
                                       T_MULTIPLY,
                                       T_DIVIDE,
                                       T_MODULUS,
                                      );

    /**
     * Tokens that represent casting.
     *
     * @var array(int)
     */
    public static $castTokens = array(
                                 T_INT_CAST,
                                 T_STRING_CAST,
                                 T_DOUBLE_CAST,
                                 T_ARRAY_CAST,
                                 T_BOOL_CAST,
                                 T_OBJECT_CAST,
                                 T_UNSET_CAST,
                                );

    /**
     * Token types that open parenthesis.
     *
     * @var array(int)
     */
    public static $parenthesisOpeners = array(
                                         T_ARRAY,
                                         T_FUNCTION,
                                         T_CLOSURE,
                                         T_WHILE,
                                         T_FOR,
                                         T_FOREACH,
                                         T_SWITCH,
                                         T_IF,
                                         T_ELSEIF,
                                         T_CATCH,
                                        );

    /**
     * Tokens that are allowed to open scopes.
     *
     * @var array(int)
     */
    public static $scopeOpeners = array(
                                   T_CLASS,
                                   T_INTERFACE,
                                   T_TRAIT,
                                   T_NAMESPACE,
                                   T_FUNCTION,
                                   T_CLOSURE,
                                   T_IF,
                                   T_SWITCH,
                                   T_CASE,
                                   T_DEFAULT,
                                   T_WHILE,
                                   T_ELSE,
                                   T_ELSEIF,
                                   T_FOR,
                                   T_FOREACH,
                                   T_DO,
                                   T_TRY,
                                   T_CATCH,
                                  );

    /**
     * Tokens that represent scope modifiers.
     *
     * @var array(int)
     */
    public static $scopeModifiers = array(
                                     T_PRIVATE,
                                     T_PUBLIC,
                                     T_PROTECTED,
                                    );

    /**
     * Tokens that can prefix a method name
     *
     * @var array(int)
     */
    public static $methodPrefixes = array(
                                     T_PRIVATE,
                                     T_PUBLIC,
                                     T_PROTECTED,
                                     T_ABSTRACT,
                                     T_STATIC,
                                     T_FINAL,
                                    );

    /**
     * Tokens that perform operations.
     *
     * @var array(int)
     */
    public static $operators = array(
                                T_MINUS,
                                T_PLUS,
                                T_MULTIPLY,
                                T_DIVIDE,
                                T_MODULUS,
                                T_POWER,
                                T_BITWISE_AND,
                                T_BITWISE_OR,
                               );

    /**
     * Tokens that perform boolean operations.
     *
     * @var array(int)
     */
    public static $booleanOperators = array(
                                       T_BOOLEAN_AND,
                                       T_BOOLEAN_OR,
                                       T_LOGICAL_AND,
                                       T_LOGICAL_OR,
                                       T_LOGICAL_XOR,
                                      );

    /**
     * Tokens that open code blocks.
     *
     * @var array(int)
     */
    public static $blockOpeners = array(
                                   T_OPEN_CURLY_BRACKET,
                                   T_OPEN_SQUARE_BRACKET,
                                   T_OPEN_PARENTHESIS,
                                  );

    /**
     * Tokens that don't represent code.
     *
     * @var array(int)
     */
    public static $emptyTokens = array(
                                  T_WHITESPACE,
                                  T_COMMENT,
                                  T_DOC_COMMENT,
                                 );

    /**
     * Tokens that are comments.
     *
     * @var array(int)
     */
    public static $commentTokens = array(
                                    T_COMMENT,
                                    T_DOC_COMMENT,
                                   );

    /**
     * Tokens that represent strings.
     *
     * Note that T_STRINGS are NOT represented in this list.
     *
     * @var array(int)
     */
    public static $stringTokens = array(
                                   T_CONSTANT_ENCAPSED_STRING,
                                   T_DOUBLE_QUOTED_STRING,
                                  );

    /**
     * Tokens that represent brackets and parenthesis.
     *
     * @var array(int)
     */
    public static $bracketTokens = array(
                                    T_OPEN_CURLY_BRACKET,
                                    T_CLOSE_CURLY_BRACKET,
                                    T_OPEN_SQUARE_BRACKET,
                                    T_CLOSE_SQUARE_BRACKET,
                                    T_OPEN_PARENTHESIS,
                                    T_CLOSE_PARENTHESIS,
                                   );

    /**
     * Tokens that include files.
     *
     * @var array(int)
     */
    public static $includeTokens = array(
                                    T_REQUIRE_ONCE,
                                    T_REQUIRE,
                                    T_INCLUDE_ONCE,
                                    T_INCLUDE,
                                   );

    /**
     * Tokens that make up a heredoc string.
     *
     * @var array(int)
     */
    public static $heredocTokens = array(
                                    T_START_HEREDOC,
                                    T_END_HEREDOC,
                                    T_HEREDOC,
                                   );


    /**
     * A PHP_CodeSniffer_Tokens class cannot be constructed.
     *
     * Only static calls are allowed.
     */
    private function __construct()
    {

    }//end __construct()


    /**
     * Returns the highest weighted token type.
     *
     * Tokens are weighted by their approximate frequency of appearance in code
     * - the less frequently they appear in the code, the higher the weighting.
     * For example T_CLASS tokens appear very infrequently in a file, and
     * therefore have a high weighting.
     *
     * Returns false if there are no weightings for any of the specified tokens.
     *
     * @param array(int) $tokens The token types to get the highest weighted
     *                           type for.
     *
     * @return int The highest weighted token.
     */
    public static function getHighestWeightedToken(array $tokens)
    {
        $highest     = -1;
        $highestType = false;

        $weights = self::$weightings;

        foreach ($tokens as $token) {
            if (isset($weights[$token]) === true) {
                $weight = $weights[$token];
            } else {
                $weight = 0;
            }

            if ($weight > $highest) {
                $highest     = $weight;
                $highestType = $token;
            }
        }

        return $highestType;

    }//end getHighestWeightedToken()


}//end class

?>
<?php
/**
 * Represents a PHP_CodeSniffer sniff for sniffing coding standards.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Represents a PHP_CodeSniffer sniff for sniffing coding standards.
 *
 * A sniff registers what token types it wishes to listen for, then, when
 * PHP_CodeSniffer encounters that token, the sniff is invoked and passed
 * information about where the token was found in the stack, and the
 * PHP_CodeSniffer file in which the token was found.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
interface PHP_CodeSniffer_Sniff
{


    /**
     * Registers the tokens that this sniff wants to listen for.
     *
     * An example return value for a sniff that wants to listen for whitespace
     * and any comments would be:
     *
     * <code>
     *    return array(
     *            T_WHITESPACE,
     *            T_DOC_COMMENT,
     *            T_COMMENT,
     *           );
     * </code>
     *
     * @return array(int)
     * @see    Tokens.php
     */
    public function register();


    /**
     * Called when one of the token types that this sniff is listening for
     * is found.
     *
     * The stackPtr variable indicates where in the stack the token was found.
     * A sniff can acquire information this token, along with all the other
     * tokens within the stack by first acquiring the token stack:
     *
     * <code>
     *    $tokens = $phpcsFile->getTokens();
     *    echo 'Encountered a '.$tokens[$stackPtr]['type'].' token';
     *    echo 'token information: ';
     *    print_r($tokens[$stackPtr]);
     * </code>
     *
     * If the sniff discovers an anomaly in the code, they can raise an error
     * by calling addError() on the PHP_CodeSniffer_File object, specifying an error
     * message and the position of the offending token:
     *
     * <code>
     *    $phpcsFile->addError('Encountered an error', $stackPtr);
     * </code>
     *
     * @param PHP_CodeSniffer_File $phpcsFile The PHP_CodeSniffer file where the
     *                                        token was found.
     * @param int                  $stackPtr  The position in the PHP_CodeSniffer
     *                                        file's token stack where the token
     *                                        was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr);


}//end interface

?>
<?php
/**
 * A doc generator that outputs documentation in one big HTML file.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_DocGenerators_Generator', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_DocGenerators_Generator not found');
}

/**
 * A doc generator that outputs documentation in one big HTML file.
 *
 * Output is in one large HTML file and is designed for you to style with
 * your own stylesheet. It contains a table of contents at the top with anchors
 * to each sniff.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_DocGenerators_HTML extends PHP_CodeSniffer_DocGenerators_Generator
{


    /**
     * Generates the documentation for a standard.
     *
     * @return void
     * @see processSniff()
     */
    public function generate()
    {
        ob_start();
        $this->printHeader();

        $standardFiles = $this->getStandardFiles();
        $this->printToc($standardFiles);

        foreach ($standardFiles as $standard) {
            $doc = new DOMDocument();
            $doc->load($standard);
            $documentation = $doc->getElementsByTagName('documentation')->item(0);
            $this->processSniff($documentation);
        }

        $this->printFooter();

        $content = ob_get_contents();
        ob_end_clean();

        echo $content;

    }//end generate()


    /**
     * Print the header of the HTML page.
     *
     * @return void
     */
    protected function printHeader()
    {
        $standard = $this->getStandard();
        echo '<html>'.PHP_EOL;
        echo ' <head>'.PHP_EOL;
        echo "  <title>$standard Coding Standards</title>".PHP_EOL;
        echo '  <style>
                    body {
                        background-color: #FFFFFF;
                        font-size: 14px;
                        font-family: Arial, Helvetica, sans-serif;
                        color: #000000;
                    }

                    h1 {
                        color: #666666;
                        font-size: 20px;
                        font-weight: bold;
                        margin-top: 0px;
                        background-color: #E6E7E8;
                        padding: 20px;
                        border: 1px solid #BBBBBB;
                    }

                    h2 {
                        color: #00A5E3;
                        font-size: 16px;
                        font-weight: normal;
                        margin-top: 50px;
                    }

                    .code-comparison {
                        width: 100%;
                    }

                    .code-comparison td {
                        border: 1px solid #CCCCCC;
                    }

                    .code-comparison-title, .code-comparison-code {
                        font-family: Arial, Helvetica, sans-serif;
                        font-size: 12px;
                        color: #000000;
                        vertical-align: top;
                        padding: 4px;
                        width: 50%;
                        background-color: #F1F1F1;
                        line-height: 15px;
                    }

                    .code-comparison-code {
                        font-family: Courier;
                        background-color: #F9F9F9;
                    }

                    .code-comparison-highlight {
                        background-color: #DDF1F7;
                        border: 1px solid #00A5E3;
                        line-height: 15px;
                    }

                    .tag-line {
                        text-align: center;
                        width: 100%;
                        margin-top: 30px;
                        font-size: 12px;
                    }

                    .tag-line a {
                        color: #000000;
                    }
                </style>'.PHP_EOL;
        echo ' </head>'.PHP_EOL;
        echo ' <body>'.PHP_EOL;
        echo "  <h1>$standard Coding Standards</h1>".PHP_EOL;

    }//end printHeader()


    /**
     * Print the table of contents for the standard.
     *
     * The TOC is just an unordered list of bookmarks to sniffs on the page.
     *
     * @param array $standardFiles An array of paths to the XML standard files.
     *
     * @return void
     */
    protected function printToc($standardFiles)
    {
        echo '  <h2>Table of Contents</h2>'.PHP_EOL;
        echo '  <ul class="toc">'.PHP_EOL;

        foreach ($standardFiles as $standard) {
            $doc = new DOMDocument();
            $doc->load($standard);
            $documentation = $doc->getElementsByTagName('documentation')->item(0);
            $title         = $this->getTitle($documentation);
            echo '   <li><a href="#'.str_replace(' ', '-', $title)."\">$title</a></li>".PHP_EOL;
        }

        echo '  </ul>'.PHP_EOL;

    }//end printToc()


    /**
     * Print the footer of the HTML page.
     *
     * @return void
     */
    protected function printFooter()
    {
        // Turn off errors so we don't get timezone warnings if people
        // don't have their timezone set.
        error_reporting(0);
        echo '  <div class="tag-line">';
        echo 'Documentation generated on '.date('r');
        echo ' by <a href="http://pear.php.net/package/PHP_CodeSniffer">PHP_CodeSniffer '.PHP_CodeSniffer::VERSION.'</a>';
        echo '</div>'.PHP_EOL;
        error_reporting(E_ALL | E_STRICT);

        echo ' </body>'.PHP_EOL;
        echo '</html>'.PHP_EOL;

    }//end printFooter()


    /**
     * Process the documentation for a single sniff.
     *
     * @param DOMNode $doc The DOMNode object for the sniff.
     *                     It represents the "documentation" tag in the XML
     *                     standard file.
     *
     * @return void
     */
    public function processSniff(DOMNode $doc)
    {
        $title = $this->getTitle($doc);
        echo '  <a name="'.str_replace(' ', '-', $title).'" />'.PHP_EOL;
        echo "  <h2>$title</h2>".PHP_EOL;

        foreach ($doc->childNodes as $node) {
            if ($node->nodeName === 'standard') {
                $this->printTextBlock($node);
            } else if ($node->nodeName === 'code_comparison') {
                $this->printCodeComparisonBlock($node);
            }
        }

    }//end processSniff()


    /**
     * Print a text block found in a standard.
     *
     * @param DOMNode $node The DOMNode object for the text block.
     *
     * @return void
     */
    protected function printTextBlock($node)
    {
        $content = trim($node->nodeValue);
        $content = htmlspecialchars($content);

        // Allow em tags only.
        $content = str_replace('&lt;em&gt;', '<em>', $content);
        $content = str_replace('&lt;/em&gt;', '</em>', $content);

        echo "  <p class=\"text\">$content</p>".PHP_EOL;

    }//end printTextBlock()


    /**
     * Print a code comparison block found in a standard.
     *
     * @param DOMNode $node The DOMNode object for the code comparison block.
     *
     * @return void
     */
    protected function printCodeComparisonBlock($node)
    {
        $codeBlocks = $node->getElementsByTagName('code');

        $firstTitle = $codeBlocks->item(0)->getAttribute('title');
        $first = trim($codeBlocks->item(0)->nodeValue);
        $first = str_replace('<?php', '&lt;?php', $first);
        $first = str_replace("\n", '</br>', $first);
        $first = str_replace(' ', '&nbsp;', $first);
        $first = str_replace('<em>', '<span class="code-comparison-highlight">', $first);
        $first = str_replace('</em>', '</span>', $first);

        $secondTitle = $codeBlocks->item(1)->getAttribute('title');
        $second = trim($codeBlocks->item(1)->nodeValue);
        $second = str_replace('<?php', '&lt;?php', $second);
        $second = str_replace("\n", '</br>', $second);
        $second = str_replace(' ', '&nbsp;', $second);
        $second = str_replace('<em>', '<span class="code-comparison-highlight">', $second);
        $second = str_replace('</em>', '</span>', $second);

        echo '  <table class="code-comparison">'.PHP_EOL;
        echo '   <tr>'.PHP_EOL;
        echo "    <td class=\"code-comparison-title\">$firstTitle</td>".PHP_EOL;
        echo "    <td class=\"code-comparison-title\">$secondTitle</td>".PHP_EOL;
        echo '   </tr>'.PHP_EOL;
        echo '   <tr>'.PHP_EOL;
        echo "    <td class=\"code-comparison-code\">$first</td>".PHP_EOL;
        echo "    <td class=\"code-comparison-code\">$second</td>".PHP_EOL;
        echo '   </tr>'.PHP_EOL;
        echo '  </table>'.PHP_EOL;

    }//end printCodeComparisonBlock()


}//end class

?>
<?php
/**
 * A doc generator that outputs text-based documentation.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_DocGenerators_Generator', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_DocGenerators_Generator not found');
}

/**
 * A doc generator that outputs text-based documentation.
 *
 * Output is designed to be displayed in a terminal and is wrapped to 100 characters.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_DocGenerators_Text extends PHP_CodeSniffer_DocGenerators_Generator
{


    /**
     * Process the documentation for a single sniff.
     *
     * @param DOMNode $doc The DOMNode object for the sniff.
     *                     It represents the "documentation" tag in the XML
     *                     standard file.
     *
     * @return void
     */
    public function processSniff(DOMNode $doc)
    {
        $this->printTitle($doc);

        foreach ($doc->childNodes as $node) {
            if ($node->nodeName === 'standard') {
                $this->printTextBlock($node);
            } else if ($node->nodeName === 'code_comparison') {
                $this->printCodeComparisonBlock($node);
            }
        }

    }//end processSniff()


    /**
     * Prints the title area for a single sniff.
     *
     * @param DOMNode $doc The DOMNode object for the sniff.
     *                     It represents the "documentation" tag in the XML
     *                     standard file.
     *
     * @return void
     */
    protected function printTitle(DOMNode $doc)
    {
        $title    = $this->getTitle($doc);
        $standard = $this->getStandard();

        echo PHP_EOL;
        echo str_repeat('-', (strlen("$standard CODING STANDARD: $title") + 4));
        echo strtoupper(PHP_EOL."| $standard CODING STANDARD: $title |".PHP_EOL);
        echo str_repeat('-', (strlen("$standard CODING STANDARD: $title") + 4));
        echo PHP_EOL.PHP_EOL;

    }//end printTitle()


    /**
     * Print a text block found in a standard.
     *
     * @param DOMNode $node The DOMNode object for the text block.
     *
     * @return void
     */
    protected function printTextBlock($node)
    {
        $text = trim($node->nodeValue);
        $text = str_replace('<em>', '*', $text);
        $text = str_replace('</em>', '*', $text);

        $lines    = array();
        $tempLine = '';
        $words    = explode(' ', $text);

        foreach ($words as $word) {
            if (strlen($tempLine.$word) >= 99) {
                if (strlen($tempLine.$word) === 99) {
                    // Adding the extra space will push us to the edge
                    // so we are done.
                    $lines[]  = $tempLine.$word;
                    $tempLine = '';
                } else if (strlen($tempLine.$word) === 100) {
                    // We are already at the edge, so we are done.
                    $lines[]  = $tempLine.$word;
                    $tempLine = '';
                } else {
                    $lines[]  = rtrim($tempLine);
                    $tempLine = $word.' ';
                }
            } else {
                $tempLine .= $word.' ';
            }
        }//end foreach

        if ($tempLine !== '') {
            $lines[] = rtrim($tempLine);
        }

        echo implode(PHP_EOL, $lines).PHP_EOL.PHP_EOL;

    }//end printTextBlock()


    /**
     * Print a code comparison block found in a standard.
     *
     * @param DOMNode $node The DOMNode object for the code comparison block.
     *
     * @return void
     */
    protected function printCodeComparisonBlock($node)
    {
        $codeBlocks = $node->getElementsByTagName('code');
        $first      = trim($codeBlocks->item(0)->nodeValue);
        $firstTitle = $codeBlocks->item(0)->getAttribute('title');

        $firstTitleLines = array();
        $tempTitle       = '';
        $words           = explode(' ', $firstTitle);

        foreach ($words as $word) {
            if (strlen($tempTitle.$word) >= 45) {
                if (strlen($tempTitle.$word) === 45) {
                    // Adding the extra space will push us to the edge
                    // so we are done.
                    $firstTitleLines[] = $tempTitle.$word;
                    $tempTitle         = '';
                } else if (strlen($tempTitle.$word) === 46) {
                    // We are already at the edge, so we are done.
                    $firstTitleLines[] = $tempTitle.$word;
                    $tempTitle         = '';
                } else {
                    $firstTitleLines[] = $tempTitle;
                    $tempTitle         = $word;
                }
            } else {
                $tempTitle .= $word.' ';
            }
        }//end foreach

        if ($tempTitle !== '') {
            $firstTitleLines[] = $tempTitle;
        }

        $first      = str_replace('<em>', '', $first);
        $first      = str_replace('</em>', '', $first);
        $firstLines = explode("\n", $first);

        $second      = trim($codeBlocks->item(1)->nodeValue);
        $secondTitle = $codeBlocks->item(1)->getAttribute('title');

        $secondTitleLines = array();
        $tempTitle        = '';
        $words            = explode(' ', $secondTitle);

        foreach ($words as $word) {
            if (strlen($tempTitle.$word) >= 45) {
                if (strlen($tempTitle.$word) === 45) {
                    // Adding the extra space will push us to the edge
                    // so we are done.
                    $secondTitleLines[] = $tempTitle.$word;
                    $tempTitle          = '';
                } else if (strlen($tempTitle.$word) === 46) {
                    // We are already at the edge, so we are done.
                    $secondTitleLines[] = $tempTitle.$word;
                    $tempTitle          = '';
                } else {
                    $secondTitleLines[] = $tempTitle;
                    $tempTitle          = $word;
                }
            } else {
                $tempTitle .= $word.' ';
            }
        }//end foreach

        if ($tempTitle !== '') {
            $secondTitleLines[] = $tempTitle;
        }

        $second      = str_replace('<em>', '', $second);
        $second      = str_replace('</em>', '', $second);
        $secondLines = explode("\n", $second);

        $maxCodeLines  = max(count($firstLines), count($secondLines));
        $maxTitleLines = max(count($firstTitleLines), count($secondTitleLines));

        echo str_repeat('-', 41);
        echo ' CODE COMPARISON ';
        echo str_repeat('-', 42).PHP_EOL;

        for ($i = 0; $i < $maxTitleLines; $i++) {
            if (isset($firstTitleLines[$i]) === true) {
                $firstLineText = $firstTitleLines[$i];
            } else {
                $firstLineText = '';
            }

            if (isset($secondTitleLines[$i]) === true) {
                $secondLineText = $secondTitleLines[$i];
            } else {
                $secondLineText = '';
            }

            echo '| ';
            echo $firstLineText.str_repeat(' ', (46 - strlen($firstLineText)));
            echo ' | ';
            echo $secondLineText.str_repeat(' ', (47 - strlen($secondLineText)));
            echo ' |'.PHP_EOL;
        }//end for

        echo str_repeat('-', 100).PHP_EOL;

        for ($i = 0; $i < $maxCodeLines; $i++) {
            if (isset($firstLines[$i]) === true) {
                $firstLineText = $firstLines[$i];
            } else {
                $firstLineText = '';
            }

            if (isset($secondLines[$i]) === true) {
                $secondLineText = $secondLines[$i];
            } else {
                $secondLineText = '';
            }

            echo '| ';
            echo $firstLineText.str_repeat(' ', (47 - strlen($firstLineText)));
            echo '| ';
            echo $secondLineText.str_repeat(' ', (48 - strlen($secondLineText)));
            echo '|'.PHP_EOL;
        }//end for

        echo str_repeat('-', 100).PHP_EOL.PHP_EOL;

    }//end printCodeComparisonBlock()


}//end class

?>
<?php
/**
 * The base class for all PHP_CodeSniffer documentation generators.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * The base class for all PHP_CodeSniffer documentation generators.
 *
 * Documentation generators are used to print documentation about code sniffs
 * in a standard.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_DocGenerators_Generator
{

    /**
     * The name of the coding standard we are generating docs for.
     *
     * @var string
     */
    private $_standard = '';

    /**
     * An array of sniffs that we are limiting the generated docs to.
     *
     * If this array is empty, docs are generated for all sniffs in the
     * supplied coding standard.
     *
     * @var string
     */
    private $_sniffs = array();


    /**
     * Constructs a PHP_CodeSniffer_DocGenerators_Generator object.
     *
     * @param string $standard The name of the coding standard to generate
     *                         docs for.
     * @param array  $sniffs   An array of sniffs that we are limiting the
     *                         generated docs to.
     *
     * @see generate()
     */
    public function __construct($standard, array $sniffs=array())
    {
        $this->_standard = $standard;
        $this->_sniffs   = $sniffs;

    }//end __construct()


    /**
     * Retrieves the title of the sniff from the DOMNode supplied.
     *
     * @param DOMNode $doc The DOMNode object for the sniff.
     *                     It represents the "documentation" tag in the XML
     *                     standard file.
     *
     * @return string
     */
    protected function getTitle(DOMNode $doc)
    {
        return $doc->getAttribute('title');

    }//end getTitle()


    /**
     * Retrieves the name of the standard we are generating docs for.
     *
     * @return string
     */
    protected function getStandard()
    {
        return $this->_standard;

    }//end getStandard()


    /**
     * Generates the documentation for a standard.
     *
     * It's probably wise for doc generators to override this method so they
     * have control over how the docs are produced. Otherwise, the processSniff
     * method should be overridden to output content for each sniff.
     *
     * @return void
     * @see processSniff()
     */
    public function generate()
    {
        $standardFiles = $this->getStandardFiles();

        foreach ($standardFiles as $standard) {
            $doc = new DOMDocument();
            $doc->load($standard);
            $documentation = $doc->getElementsByTagName('documentation')->item(0);
            $this->processSniff($documentation);
        }

    }//end generate()


    /**
     * Returns a list of paths to XML standard files for all sniffs in a standard.
     *
     * Any sniffs that do not have an XML standard file are obviously not included
     * in the returned array. If documentation is only being generated for some
     * sniffs (ie. $this->_sniffs is not empty) then all others sniffs will
     * be filtered from the results as well.
     *
     * @return array(string)
     */
    protected function getStandardFiles()
    {
        $phpcs = new PHP_CodeSniffer();
        $phpcs->process(array(), $this->_standard);
        $sniffs = $phpcs->getSniffs();

        $standardFiles = array();
        foreach ($sniffs as $className => $sniffClass) {
            $object = new ReflectionObject($sniffClass);
            $sniff  = $object->getFilename();
            if (empty($this->_sniffs) === false) {
                // We are limiting the docs to certain sniffs only, so filter
                // out any unwanted sniffs.
                $parts     = explode('_', $className);
                $sniffName = $parts[0].'.'.$parts[2].'.'.substr($parts[3], 0, -5);
                if (in_array($sniffName, $this->_sniffs) === false) {
                    continue;
                }
            }

            $standardFile = str_replace(
                DIRECTORY_SEPARATOR.'Sniffs'.DIRECTORY_SEPARATOR,
                DIRECTORY_SEPARATOR.'Docs'.DIRECTORY_SEPARATOR,
                $sniff
            );
            $standardFile = str_replace('Sniff.php', 'Standard.xml', $standardFile);

            if (is_file($standardFile) === true) {
                $standardFiles[] = $standardFile;
            }
        }//end foreach

        return $standardFiles;

    }//end getStandardFiles()


    /**
     * Process the documentation for a single sniff.
     *
     * Doc generators should override this function to produce output.
     *
     * @param DOMNode $doc The DOMNode object for the sniff.
     *                     It represents the "documentation" tag in the XML
     *                     standard file.
     *
     * @return void
     * @see generate()
     */
    protected function processSniff(DOMNode $doc)
    {

    }//end processSniff()


}//end class

?>
<?php
/**
 * Ensures that console is not used for function or var names.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Ensures that console is not used for function or var names.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Sniffs_Debug_FirebugConsoleSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('JS');


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_STRING,
                T_PROPERTY,
                T_LABEL,
                T_OBJECT,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if (strtolower($tokens[$stackPtr]['content']) === 'console') {
            $error = 'Variables, functions and labels must not be named "console"; name may conflict with Firebug internal variable';
            $phpcsFile->addError($error, $stackPtr, 'ConflictFound');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Warns about the use of debug code.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Warns about the use of debug code.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Sniffs_Debug_DebugCodeSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_DOUBLE_COLON);

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $className = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
        if (strtolower($tokens[$className]['content']) === 'debug') {
            $method = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
            $error  = 'Call to debug function Debug::%s() must be removed';
            $data   = array($tokens[$method]['content']);
            $phpcsFile->addError($error, $stackPtr, 'Found', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Ensures that all action classes throw ChannelExceptions only.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Ensures that all action classes throw ChannelExceptions only.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Sniffs_Channels_ChannelExceptionSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_THROW);

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $fileName = strtolower($phpcsFile->getFilename());
        $matches  = array();
        if (preg_match('|/systems/(.*)/([^/]+)?actions.inc$|', $fileName, $matches) === 0) {
            // This is not an actions.inc file.
            return;
        }

        $tokens = $phpcsFile->getTokens();

        $exception     = $phpcsFile->findNext(array(T_STRING, T_VARIABLE), ($stackPtr + 1));
        $exceptionName = $tokens[$exception]['content'];

        if ($exceptionName !== 'ChannelException') {
            $data  = array($exceptionName);
            $error = 'Channel actions can only throw ChannelException; found "%s"';
            $phpcsFile->addError($error, $exception, 'WrongExceptionType', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Ensures that systems, asset types and libs are included before they are used.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Ensures that systems and asset types are used if they are included.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Sniffs_Channels_UnusedSystemSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_DOUBLE_COLON);

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Check if this is a call to includeSystem, includeAsset or includeWidget.
        $methodName = strtolower($tokens[($stackPtr + 1)]['content']);
        if (in_array($methodName, array('includesystem', 'includeasset', 'includewidget')) === true) {
            $systemName = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 3), null, true);
            if ($systemName === false || $tokens[$systemName]['code'] !== T_CONSTANT_ENCAPSED_STRING) {
                // Must be using a variable instead of a specific system name.
                // We can't accurately check that.
                return;
            }

            $systemName = trim($tokens[$systemName]['content'], " '");
        } else {
            return;
        }

        if ($methodName === 'includeasset') {
            $systemName .= 'assettype';
        } else if ($methodName === 'includewidget') {
            $systemName .= 'widgettype';
        }

        $systemName = strtolower($systemName);

        // Now check if this system is used anywhere in this scope.
        $level = $tokens[$stackPtr]['level'];
        for ($i = ($stackPtr + 1); $i < $phpcsFile->numTokens; $i++) {
            if ($tokens[$i]['level'] < $level) {
                // We have gone out of scope.
                // If the original include was inside an IF statement that
                // is checking if the system exists, check the outer scope
                // as well.
                if ($tokens[$stackPtr]['level'] === $level) {
                    // We are still in the base level, so this is the first
                    // time we have got here.
                    $conditions = array_keys($tokens[$stackPtr]['conditions']);
                    if (empty($conditions) === false) {
                        $cond = array_pop($conditions);
                        if ($tokens[$cond]['code'] === T_IF) {
                            $i = $tokens[$cond]['scope_closer'];
                            $level--;
                            continue;
                        }
                    }
                }

                break;
            }//end if

            $validTokens = array(
                            T_DOUBLE_COLON,
                            T_EXTENDS,
                            T_IMPLEMENTS,
                           );

            if (in_array($tokens[$i]['code'], $validTokens) === false) {
                continue;
            }

            switch ($tokens[$i]['code']) {
            case T_DOUBLE_COLON:
                $usedName = strtolower($tokens[($i - 1)]['content']);
                if ($usedName === $systemName) {
                    // The included system was used, so it is fine.
                    return;
                }

                break;
            case T_EXTENDS:
                $classNameToken = $phpcsFile->findNext(T_STRING, ($i + 1));
                $className      = strtolower($tokens[$classNameToken]['content']);
                if ($className === $systemName) {
                    // The included system was used, so it is fine.
                    return;
                }

                break;
            case T_IMPLEMENTS:
                $endImplements = $phpcsFile->findNext(array(T_EXTENDS, T_OPEN_CURLY_BRACKET), ($i + 1));
                for ($x = ($i + 1); $x < $endImplements; $x++) {
                    if ($tokens[$x]['code'] === T_STRING) {
                        $className = strtolower($tokens[$x]['content']);
                        if ($className === $systemName) {
                            // The included system was used, so it is fine.
                            return;
                        }
                    }
                }

                break;
            }//end switch
        }//end for

        // If we get to here, the system was not use.
        $error = 'Included system "%s" is never used';
        $data  = array($systemName);
        $phpcsFile->addError($error, $stackPtr, 'Found', $data);

    }//end process()


}//end class

?>
<?php
/**
 * Ensures that systems, asset types and libs are included before they are used.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_Standards_AbstractScopeSniff', true) === false) {
    $error = 'Class PHP_CodeSniffer_Standards_AbstractScopeSniff not found';
    throw new PHP_CodeSniffer_Exception($error);
}

/**
 * Ensures that systems, asset types and libs are included before they are used.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Sniffs_Channels_IncludeSystemSniff extends PHP_CodeSniffer_Standards_AbstractScopeSniff
{

    /**
     * A list of classes that don't need to be included.
     *
     * @var array(string)
     */
    private $_ignore = array(
                        'self',
                        'static',
                        'parent',
                        'channels',
                        'basesystem',
                        'dal',
                        'init',
                        'pdo',
                        'util',
                        'ziparchive',
                        'phpunit_framework_assert',
                        'abstractmysourceunittest',
                        'abstractdatacleanunittest',
                        'exception',
                        'abstractwidgetwidgettype',
                        'domdocument',
                       );


    /**
     * Constructs a Squiz_Sniffs_Scope_MethodScopeSniff.
     */
    public function __construct()
    {
        parent::__construct(array(T_FUNCTION), array(T_DOUBLE_COLON, T_EXTENDS), true);

    }//end __construct()


    /**
     * Processes the function tokens within the class.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
     * @param integer              $stackPtr  The position where the token was found.
     * @param integer              $currScope The current scope opener token.
     *
     * @return void
     */
    protected function processTokenWithinScope(
        PHP_CodeSniffer_File $phpcsFile,
        $stackPtr,
        $currScope
    ) {
        $tokens = $phpcsFile->getTokens();

        // Determine the name of the class that the static function
        // is being called on.
        $classNameToken = $phpcsFile->findPrevious(
            T_WHITESPACE,
            ($stackPtr - 1),
            null,
            true
        );

        // Don't process class names represented by variables as this can be
        // an inexact science.
        if ($tokens[$classNameToken]['code'] === T_VARIABLE) {
            return;
        }

        $className = $tokens[$classNameToken]['content'];
        if (in_array(strtolower($className), $this->_ignore) === true) {
            return;
        }

        $includedClasses = array();

        $fileName = strtolower($phpcsFile->getFilename());
        $matches  = array();
        if (preg_match('|/systems/(.*)/([^/]+)?actions.inc$|', $fileName, $matches) !== 0) {
            // This is an actions file, which means we don't
            // have to include the system in which it exists.
            $includedClasses[] = $matches[2];

            // Or a system it implements.
            $class      = $phpcsFile->getCondition($stackPtr, T_CLASS);
            $implements = $phpcsFile->findNext(T_IMPLEMENTS, $class, ($class + 10));
            if ($implements !== false) {
                $implementsClass     = $phpcsFile->findNext(T_STRING, $implements);
                $implementsClassName = strtolower($tokens[$implementsClass]['content']);
                if (substr($implementsClassName, -7) === 'actions') {
                    $includedClasses[] = substr($implementsClassName, 0, -7);
                }
            }
        }

        // Go searching for includeSystem and includeAsset calls within this
        // function, or the inclusion of .inc files, which
        // would be library files.
        for ($i = ($currScope + 1); $i < $stackPtr; $i++) {
            $name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i);
            if ($name !== false) {
                $includedClasses[] = $name;
                // Special case for Widgets cause they are, well, special.
            } else if (strtolower($tokens[$i]['content']) === 'includewidget') {
                $typeName          = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($i + 1));
                $typeName          = trim($tokens[$typeName]['content'], " '");
                $includedClasses[] = strtolower($typeName).'widgettype';
            }
        }

        // Now go searching for includeSystem, includeAsset or require/include
        // calls outside our scope. If we are in a class, look outside the
        // class. If we are not, look outside the function.
        $condPtr = $currScope;
        if ($phpcsFile->hasCondition($stackPtr, T_CLASS) === true) {
            foreach ($tokens[$stackPtr]['conditions'] as $condPtr => $condType) {
                if ($condType === T_CLASS) {
                    break;
                }
            }
        }

        for ($i = 0; $i < $condPtr; $i++) {
            // Skip other scopes.
            if (isset($tokens[$i]['scope_closer']) === true) {
                $i = $tokens[$i]['scope_closer'];
                continue;
            }

            $name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i);
            if ($name !== false) {
                $includedClasses[] = $name;
            }
        }

        // If we are in a testing class, we might have also included
        // some systems and classes in our setUp() method.
        $setupFunction = null;
        if ($phpcsFile->hasCondition($stackPtr, T_CLASS) === true) {
            foreach ($tokens[$stackPtr]['conditions'] as $condPtr => $condType) {
                if ($condType === T_CLASS) {
                    // Is this is a testing class?
                    $name = $phpcsFile->findNext(T_STRING, $condPtr);
                    $name = $tokens[$name]['content'];
                    if (substr($name, -8) === 'UnitTest') {
                        // Look for a method called setUp().
                        $end      = $tokens[$condPtr]['scope_closer'];
                        $function = $phpcsFile->findNext(T_FUNCTION, ($condPtr + 1), $end);
                        while ($function !== false) {
                            $name = $phpcsFile->findNext(T_STRING, $function);
                            if ($tokens[$name]['content'] === 'setUp') {
                                $setupFunction = $function;
                                break;
                            }

                            $function = $phpcsFile->findNext(T_FUNCTION, ($function + 1), $end);
                        }
                    }
                }
            }//end foreach
        }//end if

        if ($setupFunction !== null) {
            $start = ($tokens[$setupFunction]['scope_opener'] + 1);
            $end   = $tokens[$setupFunction]['scope_closer'];
            for ($i = $start; $i < $end; $i++) {
                $name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i);
                if ($name !== false) {
                    $includedClasses[] = $name;
                }
            }
        }//end if

        if (in_array(strtolower($className), $includedClasses) === false) {
            $error = 'Static method called on non-included class or system "%s"; include system with Channels::includeSystem() or include class with require_once';
            $data  = array($className);
            $phpcsFile->addError($error, $stackPtr, 'NotIncludedCall', $data);
        }

    }//end processTokenWithinScope()


    /**
     * Processes a token within the scope that this test is listening to.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        this token was found.
     *
     * @return void
     */
    protected function processTokenOutsideScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if ($tokens[$stackPtr]['code'] === T_EXTENDS) {
            // Find the class name.
            $classNameToken = $phpcsFile->findNext(T_STRING, ($stackPtr + 1));
            $className      = $tokens[$classNameToken]['content'];
        } else {
            // Determine the name of the class that the static function
            // is being called on. But don't process class names represented by
            // variables as this can be an inexact science.
            $classNameToken = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
            if ($tokens[$classNameToken]['code'] === T_VARIABLE) {
                return;
            }

            $className = $tokens[$classNameToken]['content'];
        }

        // Some systems are always available.
        if (in_array(strtolower($className), $this->_ignore) === true) {
            return;
        }

        $includedClasses = array();

        $fileName = strtolower($phpcsFile->getFilename());
        $matches  = array();
        if (preg_match('|/systems/([^/]+)/([^/]+)?actions.inc$|', $fileName, $matches) !== 0) {
            // This is an actions file, which means we don't
            // have to include the system in which it exists
            // We know the system from the path.
            $includedClasses[] = $matches[1];
        }

        // Go searching for includeSystem, includeAsset or require/include
        // calls outside our scope.
        for ($i = 0; $i < $stackPtr; $i++) {
            // Skip classes and functions as will we never get
            // into their scopes when including this file, although
            // we have a chance of getting into IF's, WHILE's etc.
            $ignoreTokens = array(
                             T_CLASS,
                             T_INTERFACE,
                             T_FUNCTION,
                            );

            if (in_array($tokens[$i]['code'], $ignoreTokens) === true
                && isset($tokens[$i]['scope_closer']) === true
            ) {
                $i = $tokens[$i]['scope_closer'];
                continue;
            }

            $name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i);
            if ($name !== false) {
                $includedClasses[] = $name;
                // Special case for Widgets cause they are, well, special.
            } else if (strtolower($tokens[$i]['content']) === 'includewidget') {
                $typeName          = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($i + 1));
                $typeName          = trim($tokens[$typeName]['content'], " '");
                $includedClasses[] = strtolower($typeName).'widgettype';
            }
        }//end for

        if (in_array(strtolower($className), $includedClasses) === false) {
            if ($tokens[$stackPtr]['code'] === T_EXTENDS) {
                $error = 'Class extends non-included class or system "%s"; include system with Channels::includeSystem() or include class with require_once';
                $data  = array($className);
                $phpcsFile->addError($error, $stackPtr, 'NotIncludedExtends', $data);
            } else {
                $error = 'Static method called on non-included class or system "%s"; include system with Channels::includeSystem() or include class with require_once';
                $data  = array($className);
                $phpcsFile->addError($error, $stackPtr, 'NotIncludedCall', $data);
            }
        }

    }//end processTokenOutsideScope()


    /**
     * Determines the included class name from given token.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
     * @param array                $tokens    The array of file tokens.
     * @param int                  $stackPtr  The position in the tokens array of the
     *                                        potentially included class.
     *
     * @return string
     */
    protected function getIncludedClassFromToken(
        PHP_CodeSniffer_File $phpcsFile,
        array $tokens,
        $stackPtr
    ) {
        if (strtolower($tokens[$stackPtr]['content']) === 'includesystem') {
            $systemName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($stackPtr + 1));
            $systemName = trim($tokens[$systemName]['content'], " '");
            return strtolower($systemName);
        } else if (strtolower($tokens[$stackPtr]['content']) === 'includeasset') {
            $typeName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($stackPtr + 1));
            $typeName = trim($tokens[$typeName]['content'], " '");
            return strtolower($typeName).'assettype';
        } else if (in_array($tokens[$stackPtr]['code'], PHP_CodeSniffer_Tokens::$includeTokens) === true) {
            $filePath = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($stackPtr + 1));
            $filePath = $tokens[$filePath]['content'];
            $filePath = trim($filePath, " '");
            $filePath = basename($filePath, '.inc');
            return strtolower($filePath);
        }

        return false;

    }//end getIncludedClassFromToken()


}//end class

?>
<?php
/**
 * Ensures that a system does not include itself.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Ensures that a system does not include itself.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Sniffs_Channels_IncludeOwnSystemSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_DOUBLE_COLON);

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $fileName = $phpcsFile->getFilename();
        $matches  = array();
        if (preg_match('|/systems/(.*)/([^/]+)?actions.inc$|i', $fileName, $matches) === 0) {
            // Not an actions file.
            return;
        }

        $ownClass = $matches[2];
        $tokens   = $phpcsFile->getTokens();

        $typeName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($stackPtr + 2), null, false, true);
        $typeName = trim($tokens[$typeName]['content'], " '");
        switch (strtolower($tokens[($stackPtr + 1)]['content'])) {
        case 'includesystem' :
            $included = strtolower($typeName);
            break;
        case 'includeasset' :
            $included = strtolower($typeName).'assettype';
            break;
        case 'includewidget' :
            $included = strtolower($typeName).'widgettype';
            break;
        default:
            return;
        }

        if ($included === strtolower($ownClass)) {
            $error = "You do not need to include \"%s\" from within the system's own actions file";
            $data  = array($ownClass);
            $phpcsFile->addError($error, $stackPtr, 'NotRequired', $data);
        }

    }//end process()


    /**
     * Determines the included class name from given token.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
     * @param array                $tokens    The array of file tokens.
     * @param int                  $stackPtr  The position in the tokens array of the
     *                                        potentially included class.
     *
     * @return string
     */
    protected function getIncludedClassFromToken(
        PHP_CodeSniffer_File $phpcsFile,
        array $tokens,
        $stackPtr
    ) {
        

        return false;

    }//end getIncludedClassFromToken()


}//end class

?>
<?php
/**
 * Ensures that self and static are not used to call public methods in action classes.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Ensures that self and static are not used to call public methods in action classes.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Sniffs_Channels_DisallowSelfActionsSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_CLASS);

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // We are not interested in abstract classes.
        $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
        if ($prev !== false && $tokens[$prev]['code'] === T_ABSTRACT) {
            return;
        }

        // We are only interested in Action classes.
        $classNameToken = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
        $className      = $tokens[$classNameToken]['content'];
        if (substr($className, -7) !== 'Actions') {
            return;
        }

        $foundFunctions = array();
        $foundCalls     = array();

        // Find all static method calls in the form self::method() in the class.
        $classEnd = $tokens[$stackPtr]['scope_closer'];
        for ($i = ($classNameToken + 1); $i < $classEnd; $i++) {
            if ($tokens[$i]['code'] !== T_DOUBLE_COLON) {
                if ($tokens[$i]['code'] === T_FUNCTION) {
                    // Cache the function information.
                    $funcName  = $phpcsFile->findNext(T_STRING, ($i + 1));
                    $funcScope = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$scopeModifiers, ($i - 1));

                    $foundFunctions[$tokens[$funcName]['content']] = strtolower($tokens[$funcScope]['content']);
                }

                continue;
            }

            $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, ($i - 1), null, true);
            if ($tokens[$prevToken]['content'] !== 'self'
                && $tokens[$prevToken]['content'] !== 'static'
            ) {
                continue;
            }

            $funcNameToken = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), null, true);
            if ($tokens[$funcNameToken]['code'] === T_VARIABLE) {
                // We are only interested in function calls.
                continue;
            }

            $funcName = $tokens[$funcNameToken]['content'];

            // We've found the function, now we need to find it and see if it is
            // public, private or protected. If it starts with an underscore we
            // can assume it is private.
            if ($funcName{0} === '_') {
                continue;
            }

            $foundCalls[$i] = array(
                               'name' => $funcName,
                               'type' => strtolower($tokens[$prevToken]['content']),
                              );
        }//end for

        $errorClassName = substr($className, 0, -7);

        foreach ($foundCalls as $token => $funcData) {
            if (isset($foundFunctions[$funcData['name']]) === false) {
                // Function was not in this class, might have come from the parent.
                // Either way, we can't really check this.
                continue;
            } else if ($foundFunctions[$funcData['name']] === 'public') {
                $type  = $funcData['type'];
                $error = "Static calls to public methods in Action classes must not use the $type keyword; use %s::%s() instead";
                $data  = array(
                          $errorClassName,
                          $funcName,
                         );
                $phpcsFile->addError($error, $token, 'Found'.ucfirst($funcData['type']), $data);
            }
        }

    }//end process()


}//end class

?>
<?php
/**
 * MySource_Sniffs_CSS_BrowserSpecificStylesSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * MySource_Sniffs_CSS_BrowserSpecificStylesSniff.
 *
 * Ensure that browser-specific styles are not used.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Sniffs_CSS_BrowserSpecificStylesSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('CSS');

    /**
     * A list of specific stylesheet suffixes we allow.
     *
     * These stylesheets contain browser specific styles
     * so this sniff ignore them files in the form:
     * *_moz.css and *_ie7.css etc.
     *
     * @var array
     */
    protected $specificStylesheets = array(
                                      'moz',
                                      'ie',
                                      'ie7',
                                      'ie8',
                                      'webkit',
                                     );


    /**
     * Returns the token types that this sniff is interested in.
     *
     * @return array(int)
     */
    public function register()
    {
        return array(T_STYLE);

    }//end register()


    /**
     * Processes the tokens that this sniff is interested in.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        the token was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        // Ignore files with browser-specific suffixes.
        $filename  = $phpcsFile->getFilename();
        $breakChar = strrpos($filename, '_');
        if ($breakChar !== false && substr($filename, -4) === '.css') {
            $specific = substr($filename, ($breakChar + 1), -4);
            if (in_array($specific, $this->specificStylesheets) === true) {
                return;
            }
        }

        $tokens  = $phpcsFile->getTokens();
        $content = $tokens[$stackPtr]['content'];

        if ($content{0} === '-') {
            $error = 'Browser-specific styles are not allowed';
            $phpcsFile->addError($error, $stackPtr, 'ForbiddenStyle');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Ensures that widgets are not manually created.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Ensures that widgets are not manually created.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Sniffs_Objects_DisallowNewWidgetSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_NEW);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $className = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
        if ($tokens[$className]['code'] !== T_STRING) {
            return;
        }

        if (substr(strtolower($tokens[$className]['content']), -10) === 'widgettype') {
            $widgetType = substr($tokens[$className]['content'], 0, -10);
            $error      = 'Manual creation of widget objects is banned; use Widget::getWidget(\'%s\'); instead';
            $data       = array($widgetType);
            $phpcsFile->addError($error, $stackPtr, 'Found', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Ensures the create() method of widget types properly uses callbacks.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Ensures the create() method of widget types properly uses callbacks.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Sniffs_Objects_CreateWidgetTypeCallbackSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('JS');


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_OBJECT);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $className = $tokens[$stackPtr]['content'];
        if (substr(strtolower($className), -10) !== 'widgettype') {
            return;
        }

        // Search for a create method.
        $start  = ($tokens[$stackPtr]['scope_opener'] + 1);
        $end    = ($tokens[$stackPtr]['scope_closer'] - 1);
        $create = $phpcsFile->findNext(T_PROPERTY, $start, $end, null, 'create');
        if ($create === false) {
            return;
        }

        $function = $phpcsFile->findNext(array(T_WHITESPACE, T_COLON), ($create + 1), null, true);
        if ($tokens[$function]['code'] !== T_FUNCTION) {
            continue;
        }

        $start = ($tokens[$function]['scope_opener'] + 1);
        $end   = ($tokens[$function]['scope_closer'] - 1);

        // Check that the first argument is called "callback".
        $arg = $phpcsFile->findNext(T_WHITESPACE, ($tokens[$function]['parenthesis_opener'] + 1), null, true);
        if ($tokens[$arg]['content'] !== 'callback') {
            $error = 'The first argument of the create() method of a widget type must be called "callback"';
            $phpcsFile->addError($error, $arg, 'FirstArgNotCallback');
        }

        /*
            Look for return statements within the function. They cannot return
            anything and must be preceded by the callback.call() line. The
            callback itself must contain "self" or "this" as the first argument
            and there needs to be a call to the callback function somewhere
            in the create method. All calls to the callback function must be
            followed by a return statement or the end of the method.
        */

        $foundCallback  = false;
        $passedCallback = false;
        $nestedFunction = null;
        for ($i = $start; $i <= $end; $i++) {
            // Keep track of nested functions.
            if ($nestedFunction !== null) {
                if ($i === $nestedFunction) {
                    $nestedFunction = null;
                    continue;
                }
            } else if ($tokens[$i]['code'] === T_FUNCTION
                && isset($tokens[$i]['scope_closer']) === true
            ) {
                $nestedFunction = $tokens[$i]['scope_closer'];
                continue;
            }

            if ($nestedFunction === null && $tokens[$i]['code'] === T_RETURN) {
                // Make sure return statements are not returning anything.
                if ($tokens[($i + 1)]['code'] !== T_SEMICOLON) {
                    $error = 'The create() method of a widget type must not return a value';
                    $phpcsFile->addError($error, $i, 'ReturnValue');
                }

                continue;
            } else if ($tokens[$i]['code'] !== T_STRING
                || $tokens[$i]['content'] !== 'callback'
            ) {
                continue;
            }

            // If this is the form "callback.call(" then it is a call
            // to the callback function.
            if ($tokens[($i + 1)]['code'] !== T_OBJECT_OPERATOR
                || $tokens[($i + 2)]['content'] !== 'call'
                || $tokens[($i + 3)]['code'] !== T_OPEN_PARENTHESIS
            ) {
                // One last chance; this might be the callback function
                // being passed to another function, like this
                // "this.init(something, callback, something)".
                if (isset($tokens[$i]['nested_parenthesis']) === false) {
                    continue;
                }

                // Just make sure those brackets dont belong to anyone,
                // like an IF or FOR statement.
                foreach ($tokens[$i]['nested_parenthesis'] as $bracket) {
                    if (isset($tokens[$bracket]['parenthesis_owner']) === true) {
                        continue(2);
                    }
                }

                // Note that we use this endBracket down further when checking
                // for a RETURN statement.
                $endBracket = end($tokens[$i]['nested_parenthesis']);
                $bracket    = key($tokens[$i]['nested_parenthesis']);

                $prev = $phpcsFile->findPrevious(
                    PHP_CodeSniffer_Tokens::$emptyTokens,
                    ($bracket - 1),
                    null,
                    true
                );

                if ($tokens[$prev]['code'] !== T_STRING) {
                    // This is not a function passing the callback.
                    continue;
                }

                $passedCallback = true;
            }//end if

            $foundCallback = true;

            if ($passedCallback === false) {
                // The first argument must be "this" or "self".
                $arg = $phpcsFile->findNext(T_WHITESPACE, ($i + 4), null, true);
                if ($tokens[$arg]['content'] !== 'this'
                    && $tokens[$arg]['content'] !== 'self'
                ) {
                    $error = 'The first argument passed to the callback function must be "this" or "self"';
                    $phpcsFile->addError($error, $arg, 'FirstArgNotSelf');
                }
            }

            // Now it must be followed by a return statement or the end of the function.
            if ($passedCallback === false) {
                $endBracket = $tokens[($i + 3)]['parenthesis_closer'];
            }

            for ($next = $endBracket; $next <= $end; $next++) {
                // Skip whitespace so we find the next content after the call.
                if (in_array($tokens[$next]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === true) {
                    continue;
                }

                // Skip closing braces like END IF because it is not executable code.
                if ($tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET) {
                    continue;
                }

                // We don't care about anything on the current line, like a
                // semicolon. It doesn't matter if there are other statements on the
                // line because another sniff will check for those.
                if ($tokens[$next]['line'] === $tokens[$endBracket]['line']) {
                    continue;
                }

                break;
            }

            if ($next !== $tokens[$function]['scope_closer']
                && $tokens[$next]['code'] !== T_RETURN
            ) {
                $error = 'The call to the callback function must be followed by a return statement if it is not the last statement in the create() method';
                $phpcsFile->addError($error, $i, 'NoReturn');
            }
        }//end for

        if ($foundCallback === false) {
            $error = 'The create() method of a widget type must call the callback function';
            $phpcsFile->addError($error, $create, 'CallbackNotCalled');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Ensures this is not assigned to any other var but self.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Ensures this is not assigned to any other var but self.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Sniffs_Objects_AssignThisSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('JS');


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_THIS);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Ignore this.something and other uses of "this" that are not
        // direct assignments.
        $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
        if ($tokens[$next]['code'] !== T_SEMICOLON) {
            if ($tokens[$next]['line'] === $tokens[$stackPtr]['line']) {
                return;
            }
        }

        // Something must be assigned to "this".
        $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
        if ($tokens[$prev]['code'] !== T_EQUAL) {
            return;
        }

        // A variable needs to be assigned to "this".
        $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($prev - 1), null, true);
        if ($tokens[$prev]['code'] !== T_STRING) {
            return;
        }

        // We can only assign "this" to a var called "self".
        if ($tokens[$prev]['content'] !== 'self' && $tokens[$prev]['content'] !== '_self') {
            $error = 'Keyword "this" can only be assigned to a variable called "self" or "_self"';
            $phpcsFile->addError($error, $prev, 'NotSelf');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Parses and verifies the doc comments for functions.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('Squiz_Sniffs_Commenting_FunctionCommentSniff', true) === false) {
    $error = 'Class Squiz_Sniffs_Commenting_FunctionCommentSniff not found';
    throw new PHP_CodeSniffer_Exception($error);
}

/**
 * Parses and verifies the doc comments for functions.
 *
 * Same as the Squiz standard, but adds support for API tags.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Sniffs_Commenting_FunctionCommentSniff extends Squiz_Sniffs_Commenting_FunctionCommentSniff
{


    /**
     * Process a list of unknown tags.
     *
     * @param int $commentStart The position in the stack where the comment started.
     * @param int $commentEnd   The position in the stack where the comment ended.
     *
     * @return void
     */
    protected function processUnknownTags($commentStart, $commentEnd)
    {
        $unknownTags = $this->commentParser->getUnknown();
        $words       = $this->commentParser->getWords();
        $hasApiTag   = false;
        $apiLength   = 3;
        foreach ($unknownTags as $errorTag) {
            $pos = $errorTag['pos'];
            if ($errorTag['tag'] === 'api') {
                if ($hasApiTag === true) {
                    // We've come across an API tag already, which means
                    // we were not the first tag in the API list.
                    $error = 'The @api tag must come first in the @api tag list in a function comment';
                    $this->currentFile->addError($error, ($commentStart + $errorTag['line']), 'ApiNotFirst');
                }

                $hasApiTag = true;

                // There needs to be a blank line before the @api tag.
                // So expect a single space before the tag, then 2 newlines before
                // that, then some content.
                if (trim($words[($pos - 2)]) !== ''
                    || strpos($words[($pos - 2)], $this->currentFile->eolChar) === false
                    || strpos($words[($pos - 3)], $this->currentFile->eolChar) === false
                    || trim($words[($pos - 4)]) === ''
                ) {
                    $error = 'There must be one blank line before the @api tag in a function comment';
                    $this->currentFile->addError($error, ($commentStart + $errorTag['line']), 'ApiSpacing');
                }
            } else if (substr($errorTag['tag'], 0, 4) === 'api-') {
                $hasApiTag = true;

                $tagLength = strlen($errorTag['tag']);
                if ($tagLength > $apiLength) {
                    $apiLength = $tagLength;
                }

                if (trim($words[($pos - 2)]) !== ''
                    || strpos($words[($pos - 2)], $this->currentFile->eolChar) === false
                    || trim($words[($pos - 3)]) === ''
                ) {
                    $error = 'There must be no blank line before the @%s tag in a function comment';
                    $data  = array($errorTag['tag']);
                    $this->currentFile->addError($error, ($commentStart + $errorTag['line']), 'ApiTagSpacing', $data);
                }
            }//end if
        }//end foreach

        if ($hasApiTag === true) {
            // API tags must be the last tags in a function comment.
            $order   = $this->commentParser->getTagOrders();
            $lastTag = array_pop($order);
            if ($lastTag !== 'api'
                && substr($lastTag, 0, 4) !== 'api-'
            ) {
                $error = 'The @api tags must be the last tags in a function comment';
                $this->currentFile->addError($error, $commentEnd, 'ApiNotLast');
            }

            // Check API tag indenting.
            foreach ($unknownTags as $errorTag) {
                if ($errorTag['tag'] === 'api'
                    || substr($errorTag['tag'], 0, 4) === 'api-'
                ) {
                    $expected = ($apiLength - strlen($errorTag['tag']) + 1);
                    $found    = strlen($words[($errorTag['pos'] + 1)]);
                    if ($found !== $expected) {
                        $error = '@%s tag indented incorrectly; expected %s spaces but found %s';
                        $data  = array(
                                  $errorTag['tag'],
                                  $expected,
                                  $found,
                                 );
                        $this->currentFile->addError($error, ($commentStart + $errorTag['line']), 'ApiTagIndent', $data);
                    }
                }
            }
        }//end if

    }//end processUnknownTags()


}//end class

?>
<?php
/**
 * Ensures that strings are not joined using array.join().
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Ensures that strings are not joined using array.join().
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Sniffs_Strings_JoinStringsSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('JS');


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_STRING);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param integer              $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if ($tokens[$stackPtr]['content'] !== 'join') {
            return;
        }

        $prev = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr - 1), null, true);
        if ($tokens[$prev]['code'] !== T_OBJECT_OPERATOR) {
            return;
        }

        $prev = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($prev - 1), null, true);
        if ($tokens[$prev]['code'] === T_CLOSE_SQUARE_BRACKET) {
            $opener = $tokens[$prev]['bracket_opener'];
            if ($tokens[($opener - 1)]['code'] !== T_STRING) {
                // This means the array is declared inline, like x = [a,b,c].join()
                // and not elsewhere, like x = y[a].join()
                // The first is not allowed while the second is.
                $error = 'Joining strings using inline arrays is not allowed; use the + operator instead';
                $phpcsFile->addError($error, $stackPtr, 'ArrayNotAllowed');
            }
        }

    }//end process()


}//end class

?>
<?php
/**
 * Ensures that getRequestData() is used to access super globals.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Ensures that getRequestData() is used to access super globals.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Sniffs_PHP_GetRequestDataSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_VARIABLE);

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $varName = $tokens[$stackPtr]['content'];
        if ($varName !== '$_REQUEST'
            && $varName !== '$_GET'
            && $varName !== '$_POST'
            && $varName !== '$_FILES'
        ) {
            return;
        }

        // The only place these super globals can be accessed directly is
        // in the getRequestData() method of the Security class.
        $inClass = false;
        foreach ($tokens[$stackPtr]['conditions'] as $i => $type) {
            if ($tokens[$i]['code'] === T_CLASS) {
                $className = $phpcsFile->findNext(T_STRING, $i);
                $className = $tokens[$className]['content'];
                if (strtolower($className) === 'security') {
                    $inClass = true;
                } else {
                    // We don't have nested classes.
                    break;
                }
            } else if ($inClass === true && $tokens[$i]['code'] === T_FUNCTION) {
                $funcName = $phpcsFile->findNext(T_STRING, $i);
                $funcName = $tokens[$funcName]['content'];
                if (strtolower($funcName) === 'getrequestdata') {
                    // This is valid.
                    return;
                } else {
                    // We don't have nested functions.
                    break;
                }
            }//end if
        }//end foreach

        // If we get to here, the super global was used incorrectly.
        // First find out how it is being used.
        $globalName = strtolower(substr($varName, 2));
        $usedVar    = '';

        $openBracket = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
        if ($tokens[$openBracket]['code'] === T_OPEN_SQUARE_BRACKET) {
            $closeBracket = $tokens[$openBracket]['bracket_closer'];
            $usedVar      = $phpcsFile->getTokensAsString(($openBracket + 1), ($closeBracket - $openBracket - 1));
        }

        $type  = 'SuperglobalAccessed';
        $error = 'The %s super global must not be accessed directly; use Security::getRequestData(';
        $data  = array($varName);
        if ($usedVar !== '') {
            $type  .= 'WithVar';
            $error .= '%s, \'%s\'';
            $data[] = $usedVar;
            $data[] = $globalName;
        }

        $error .= ') instead';
        $phpcsFile->addError($error, $stackPtr, $type, $data);

    }//end process()


}//end class

?>
<?php
/**
 * Ensures that eval() is not used to create objects.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Ensures that eval() is not used to create objects.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Sniffs_PHP_EvalObjectFactorySniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_EVAL);

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        /*
            We need to find all strings that will be in the eval
            to determine if the "new" keyword is being used.
        */

        $openBracket  = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($stackPtr + 1));
        $closeBracket = $tokens[$openBracket]['parenthesis_closer'];

        $strings = array();
        $vars    = array();

        for ($i = ($openBracket + 1); $i < $closeBracket; $i++) {
            if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$stringTokens) === true) {
                $strings[$i] = $tokens[$i]['content'];
            } else if ($tokens[$i]['code'] === T_VARIABLE) {
                $vars[$i] = $tokens[$i]['content'];
            }
        }

        /*
            We now have some variables that we need to expand into
            the strings that were assigned to them, if any.
        */

        foreach ($vars as $varPtr => $varName) {
            while (($prev = $phpcsFile->findPrevious(T_VARIABLE, ($varPtr - 1))) !== false) {
                // Make sure this is an assignment of the variable. That means
                // it will be the first thing on the line.
                $prevContent = $phpcsFile->findPrevious(T_WHITESPACE, ($prev - 1), null, true);
                if ($tokens[$prevContent]['line'] === $tokens[$prev]['line']) {
                    $varPtr = $prevContent;
                    continue;
                }

                if ($tokens[$prev]['content'] !== $varName) {
                    // This variable has a different name.
                    $varPtr = $prevContent;
                    continue;
                }

                // We found one.
                break;
            }//end while

            if ($prev !== false) {
                // Find all strings on the line.
                $lineEnd = $phpcsFile->findNext(T_SEMICOLON, ($prev + 1));
                for ($i = ($prev + 1); $i < $lineEnd; $i++) {
                    if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$stringTokens) === true) {
                        $strings[$i] = $tokens[$i]['content'];
                    }
                }
            }
        }//end foreach

        foreach ($strings as $string) {
            // If the string has "new" in it, it is not allowed.
            // We don't bother checking if the word "new" is echo'd
            // because that is unlikely to happen. We assume the use
            // of "new" is for object instantiation.
            if (strstr($string, ' new ') !== false) {
                $error = 'Do not use eval() to create objects dynamically; use reflection instead';
                $phpcsFile->addWarning($error, $stackPtr, 'Found');
            }
        }

    }//end process()


}//end class

?>
<?php
/**
 * Ensures that values submitted via JS are not compared to NULL.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Ensures that values submitted via JS are not compared to NULL.
 *
 * jQuery 1.8 changed the behaviour of ajax requests so that null values are
 * submitted as null= instead of null=null.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Sniffs_PHP_AjaxNullComparisonSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_FUNCTION);

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Make sure it is an API function. We know this by the doc comment.
        $commentEnd   = $phpcsFile->findPrevious(T_DOC_COMMENT, $stackPtr);
        $commentStart = $phpcsFile->findPrevious(T_DOC_COMMENT, ($commentEnd - 1), null, true);
        $comment = $phpcsFile->getTokensAsString($commentStart, ($commentEnd - $commentStart));
        if (strpos($comment, '* @api') === false) {
            return;
        }


        // Find all the vars passed in as we are only interested in comparisons
        // to NULL for these specific variables.
        $foundVars = array();
        $open  = $tokens[$stackPtr]['parenthesis_opener'];
        $close = $tokens[$stackPtr]['parenthesis_closer'];
        for ($i = ($open + 1); $i < $close; $i++) {
            if ($tokens[$i]['code'] === T_VARIABLE) {
                $foundVars[] = $tokens[$i]['content'];
            }
        }

        if (empty($foundVars) === true) {
            return;
        }

        $start = $tokens[$stackPtr]['scope_opener'];
        $end   = $tokens[$stackPtr]['scope_closer'];
        for ($i = ($start + 1); $i < $end; $i++) {
            if ($tokens[$i]['code'] !== T_VARIABLE
                || in_array($tokens[$i]['content'], $foundVars) === false
            ) {
                continue;
            }

            $operator = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), null, true);
            if ($tokens[$operator]['code'] !== T_IS_IDENTICAL
                && $tokens[$operator]['code'] !== T_IS_NOT_IDENTICAL
            ) {
                continue;
            }

            $nullValue = $phpcsFile->findNext(T_WHITESPACE, ($operator + 1), null, true);
            if ($tokens[$nullValue]['code'] !== T_NULL) {
                continue;
            }

            $error = 'Values submitted via Ajax requests must not be compared directly to NULL; use empty() instead';
            $phpcsFile->addError($error, $nullValue, 'Found');
        }//end for


    }//end process()


}//end class

?>
<?php
/**
 * Warns when function values are returned directly.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Warns when function values are returned directly.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Sniffs_PHP_ReturnFunctionValueSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_RETURN);

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $functionName = $phpcsFile->findNext(T_STRING, ($stackPtr + 1), null, false, null, true);

        while ($functionName !== false) {
            // Check if this is really a function.
            $bracket = $phpcsFile->findNext(T_WHITESPACE, ($functionName + 1), null, true);
            if ($tokens[$bracket]['code'] !== T_OPEN_PARENTHESIS) {
                // Not a function call.
                $functionName = $phpcsFile->findNext(T_STRING, ($functionName + 1), null, false, null, true);
                continue;
            }

            $error = 'The result of a function call should be assigned to a variable before being returned';
            $phpcsFile->addWarning($error, $stackPtr, 'NotAssigned');
            break;
        }

    }//end process()


}//end class

?>
<?php
Debug::bam('test');
Debug::minbam($variable);
?>
<?php
/**
 * Unit test class for the DebugCode sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the DebugCode sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Tests_Debug_DebugCodeUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                2 => 1,
                3 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the FirebugConsole sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the FirebugConsole sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Tests_Debug_FirebugConsoleUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='FirebugConsoleUnitTest.js')
    {
        if ($testFile !== 'FirebugConsoleUnitTest.js') {
            return array();
        }

        return array(
                1 => 1,
                2 => 1,
                3 => 1,
                5 => 1,
                6 => 1,
                8 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
console.info();
console.warn();
console.test();
con.sole();
var console = {
    console: 'string';
};
function console() {}<?php
Channels::includeSystem('MySystem');
Channels::includeAsset('Page');
require_once 'libs/FileSystem2.inc';

function one() {
    Channels::includeSystem('MySystem2');
    $siteid = MySystem2::getCurrentSiteId();
    Page::create();
    PageAssetType::create();
}

function two() {
    $siteid = MySystem2::getCurrentSiteId();
    $parserFiles = FileSystem2::listDirectory();
}

function three() {
    include 'libs/FileSystem.inc';
    $siteid = MySystem::getCurrentSiteId();
    $parserFiles = FileSystem::listDirectory();
}

$siteid = MySystem2::getCurrentSiteId();
$parserFiles = FileSystem2::listDirectory();
$siteid = MySystem::getCurrentSiteId();
$parserFiles = FileSystem::listDirectory();
Page::create();
PageAssetType::create();

class AssetListingAssetType extends AssetAssetType
{
    function one() {
        Channels::includeSystem('MySystem2');
        $siteid = MySystem2::getCurrentSiteId();
        Page::create();
        PageAssetType::create();
    }

    function two() {
        $siteid = MySystem2::getCurrentSiteId();
        $parserFiles = FileSystem2::listDirectory();
        return parent::two();
    }

    function three() {
        include 'libs/FileSystem.inc';
        $siteid = MySystem::getCurrentSiteId();
        $parserFiles = FileSystem::listDirectory();
        echo self::two();
        echo static::two();
    }
}

echo Init::ROOT_DIR;

Channels::includeSystem('AssetType');
AssetType::includeAsset('User');
AssetType::includeAsset('FolderAsset');
UserAssetType::create();
FolderAssetType::create();
$query->fetch(PDO::FETCH_NUM)
BaseSystem::getDataDir();
Util::getArrayIndex(array(), '');


Channels::includeSystem('Widget');
Widget::includeWidget('AbstractContainer');
class MyWidget extends AbstractContainerWidgetType {}
class MyOtherWidget extends BookWidgetType {}

$zip = new ZipArchive();
$res = $zip->open($path, ZipArchive::CREATE);

class AssetListingUnitTest extends AbstractMySourceUnitTest
{
    function setUp() {
        parent::setUp();
        Channels::includeSystem('MySystem2');
        include_once 'Libs/FileSystem.inc';
    }

    function two() {
        $siteid = MySystem2::getCurrentSiteId();
        $parserFiles = FileSystem::listDirectory();
    }

    function three() {
        $siteid = MySystem3::getCurrentSiteId();
        $parserFiles = FileSystem::listDirectory();
    }
}

if (Channels::systemExists('Log') === TRUE) {
   Channels::includeSystem('Log');
} else {
   return;
}

Log::addProjectLog('metadata.field.update', $msg);

function two() {
    Widget::includeWidget('CacheAdminScreen');
    $barChart = CacheAdminScreenWidgetType::constructBarchart($data);
}

$adjustDialog->setOrientation(AbstractWidgetWidgetType::CENTER);

$className = 'SquizPerspective'.ucfirst($property['type']).'PropertyType';
Channels::includeSystem($className);
$className::setValue($assetid, $propertyid, $perspectives, $value, (array) $property['settings']);
?>
<?php
class SomethingActions
{

    private static function _x()
    {
    }


    public static function y()
    {
        self::z();
        static::z();
        SomethingActions::z();
        static::_x();
        self::a();
        static::a();
    }


    public static function z()
    {
    }

    protected static function a()
    {
        self::a(); // recursion, yay!
        self::z();
        static::y();
        self::b();
        echo self::$_myVar;
        echo static::$yourVar;
    }
}

abstract class AbstractEditingScreenModeWidgetActions extends AbstractEditingModeWidgetActions {

    public static function getScreens($systemName)
    {

    }//end getScreens()

    public static function setHelpScreenTitle()
    {
        // This is allowed because we are in an abstract class.
        $screens = self::getScreens('');

    }//end setHelpScreenTitle()

}//end class
?>
<?php
/**
 * Unit test class for the UnusedSystem sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the UnusedSystem sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Tests_Channels_UnusedSystemUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                2  => 1,
                5  => 1,
                8  => 1,
                24 => 1,
                34 => 1,
                54 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the IncludeSystem sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the IncludeSystem sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Tests_Channels_IncludeSystemUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                9  => 1,
                14 => 1,
                24 => 1,
                27 => 1,
                28 => 1,
                31 => 1,
                36 => 1,
                41 => 1,
                61 => 1,
                70 => 1,
                89 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
Channels::includeSystem('OurSystem');
Channels::includeSystem('Page');
Channels::includeAsset('Page2');
Channels::includeAsset('Folder');

function one() {
    Channels::includeSystem('MySystem');
    $siteid = MySystem2::getCurrentSiteId();
    Page::create();
    PageAssetType::create();
}

function two() {
    Page2AssetType::create();
    Folder::getFolder();
}

Channels::includeAsset('Asset');
class AssetListingAssetType extends AssetAssetType
{
    function one() {
        Channels::includeSystem('MySystem2');
        Channels::includeSystem('Page2');
        $siteid = MySystem2::getCurrentSiteId();
    }

    function two() {
        $siteid = Page2::getCurrentSiteId();
    }
}

Channels::includeSystem('Log');
Channels::includeSystem('Log4');
class MyLog implements Dog, Log extends LogMe {}

Channels::includeSystem('Log1');
class MyLog implements Dog, Log1 extends LogMe {}

class MyLog implements Log2 {}

Channels::includeSystem('Log3');
class MyLog implements Log3 {}

if (self::systemExists($systemName) === FALSE) {
    return $actions;
} else {
    // Shouldnt throw an error because we dont know the system name.
    self::includeSystem($systemName);
    self::includeSystem($systemNames['log']);
}

Channels::includeSystem('Widget');
Widget::includeWidget('AbstractContainer');
class MyOtherWidget extends BookWidgetType {}

function myFunction()
{
    if (Channels::systemExists('Log5') === TRUE) {
       Channels::includeSystem('Log5');
    } else {
       return;
    }

    Log5::addProjectLog('metadata.field.update', $msg);
}
?><?php
/**
 * Unit test class for the DisallowSelfActionsUnitTest sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the DisallowSelfActionsUnitTest sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Tests_Channels_DisallowSelfActionsUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                12 => 1,
                13 => 1,
                28 => 1,
                29 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
.SettingsTabPaneWidgetType-tab-mid {
   background: transparent url(tab_inact_mid.png) repeat-x;
   line-height: -25px;
   cursor: pointer;
   -moz-user-select: none;
}

.AssetLineageWidgetType-item {
    float: left;
    list-style: none;
    height: 22px;
    cursor: pointer;
}
<?php
/**
 * Unit test class for the BrowserSpecificStyles sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the BrowserSpecificStyles sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Tests_CSS_BrowserSpecificStylesUnitTest extends AbstractSniffUnitTest
{

    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                5  => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
Channels::includeSystem('Widget');
Widget::includeWidget('PasswordField');
$blah = new PasswordFieldWidgetType();
Widget::getWidget('PasswordField');
?>
var self = this;
buttonWidget.addClickEvent(function() {
    self.addDynamicSouce();
});

var x = self;
var y = this;

var test = '';
if (true) {
    test = this
}

var itemid = this.items[i].getAttribute('itemid');

for (var x = this; y < 10; y++) {
    var x = this + 1;
}

var _self = this;<?php
/**
 * Unit test class for the DisallowNewWidget sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the DisallowNewWidget sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Tests_Objects_DisallowNewWidgetUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                4 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the CreateWidgetTypeCallback sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the CreateWidgetTypeCallback sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Tests_Objects_CreateWidgetTypeCallbackUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='CreateWidgetTypeCallbackUnitTest.js')
    {
        if ($testFile !== 'CreateWidgetTypeCallbackUnitTest.js') {
            return array();
        }

        return array(
                18  => 1,
                23  => 2,
                26  => 1,
                30  => 1,
                34  => 1,
                43  => 2,
                91  => 1,
                123 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
SampleWidgetType.prototype = {

    create: function(callback)
    {
        if (x === 1) {
            return;
        }

        if (y === 1) {
            callback.call(this);
            // A comment here to explain the return is okay.
            return;
        }

        if (a === 1) {
            // Cant return value even after calling callback.
            callback.call(this);
            return something;
        }

        if (a === 1) {
            // Need to pass self or this to callback function.
            callback.call(a);
        }

        callback.call(self);

        var self = this;
        this.createChildren(null, function() {
            callback.call(self, div);
        });

        // Never good to return a vaue.
        return something;

        callback.call(self);
    }

};

AnotherSampleWidgetType.prototype = {

    create: function(input)
    {
        return;
    }

    getSomething: function(input)
    {
        return 1;
    }

};


NoCreateWidgetType.prototype = {

    getSomething: function(input)
    {
        return;
    }

};


SomeRandom.prototype = {

    create: function(input)
    {
        return;
    }

};

SampleWidgetType.prototype = {

    create: function(callback)
    {
        if (a === 1) {
            // This is ok because it is the last statement,
            // even though it is conditional.
            callback.call(self);
        }

    }

};

SampleWidgetType.prototype = {

    create: function(callback)
    {
        var something = callback;

    }

};

SampleWidgetType.prototype = {

    create: function(callback)
    {
        // Also valid because we are passing the callback to
        // someone else to call.
        if (y === 1) {
            this.something(callback);
            return;
        }

        this.init(callback);

    }

};

SampleWidgetType.prototype = {

    create: function(callback)
    {
        // Also valid because we are passing the callback to
        // someone else to call.
        if (y === 1) {
            this.something(callback);
        }

        this.init(callback);

    }

};

SampleWidgetType.prototype = {

    create: function(callback)
    {
        if (a === 1) {
            // This is ok because it is the last statement,
            // even though it is conditional.
            this.something(callback);
        }

    }

};


SampleWidgetType.prototype = {

    create: function(callback)
    {
        if (dfx.isFn(callback) === true) {
            callback.call(this, cont);
            return;
        }
    }

};


SampleWidgetType.prototype = {

    create: function(callback)
    {
        dfx.foreach(items, function(item) {
            return true;
        });

        if (dfx.isFn(callback) === true) {
            callback.call(this);
        }
    }

};

SampleWidgetType.prototype = {

    create: function(callback)
    {
        var self = this;
        this.createChildren(null, function() {
            callback.call(self, div);
            return;
        });
    }

};<?php
/**
 * Unit test class for the AssignThis sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the AssignThis sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Tests_Objects_AssignThisUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='AssignThisUnitTest.js')
    {
        if ($testFile !== 'AssignThisUnitTest.js') {
            return array();
        }

        return array(
                7  => 1,
                11 => 1,
                16 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Short content.
 *
 * @return void
 *
 * @api           read
 * @api-privilege asset.read.content
 * @api-mustlock  false
 */
private function functionCall() {}

/**
 * Short content.
 *
 * @return void
 *
 * @api read
 */
private function functionCall() {}

/**
 * Short content.
 *
 * @api read
 *
 * @return void
 */
private function functionCall() {}

/**
 * Short content.
 *
 * @return void
 *
 * @api-privilege asset.read.content
 * @api           read
 * @api-mustlock  false
 */
private function functionCall() {}

/**
 * Short content.
 *
 * @return void
 *
 * @api           read
 *
 * @api-privilege asset.read.content
 * @api-mustlock  false
 */
private function functionCall() {}

/**
 * Short content.
 *
 * @return void
 * @api read
 */
private function functionCall() {}

/**
 * Test unknown tags.
 *
 * @return  void
 * @since   read
 * @hello   hello
 * @package Test
 */
private function functionCall() {}

/**
 * Short content.
 *
 * @return void
 *
 * @api read
 * @api-privilege asset.read.content
 * @api-mustlock false
 */
private function functionCall() {}

/**
 * Short content.
 *
 * @return void
 *
 * @api          read
 * @api-mustlock false
 */
private function functionCall() {}

/**
 * Short content.
 *
 * @return void
 *
 * @api read
 */
private function functionCall() {}
?>
<?php
/**
 * Unit test class for FunctionCommentSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for FunctionCommentSniff.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Tests_Commenting_FunctionCommentUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                28 => 1,
                36 => 1,
                37 => 2,
                49 => 1,
                58 => 1,
                65 => 1,
                77 => 1,
                79 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the JoinStrings sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the JoinStrings sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Tests_Strings_JoinStringsUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='JoinStringsUnitTest.js')
    {
        if ($testFile !== 'JoinStringsUnitTest.js') {
            return array();
        }

        return array(
                6  => 1,
                7  => 1,
                8  => 2,
                9  => 2,
                10 => 2,
                12 => 2,
                15 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
one = (1 + 2);
two = (one + 2);
two = (one + one);
three = ('1' + 2);

four = ['1', two].join();
four = ['1', two].join('');
four = ['1', [one, two].join(',')].join(' ');
four = ['1', [one, two].join()].join(' ');
four = ['1', [one, two].join()].join();

five = 'string' + ['1', [one, two].join()].join() + 'string';

six = myArray.join(' ');
six = [arrayOne, arrayTwo].join();

// This is fine because the array is not created inline.
var x = 'x' + test[x].join('p') + 't';<?php
/**
 * Adds a new issue.
 *
 * Returns the new issue id.
 *
 * @param string  $title             Title of the new issue.
 * @param string  $description       The description of the issue.
 * @param string  $reporter          Asset id of the reporter.
 * @param integer $projectid         Id of the project that the issue belongs to.
 * @param array   $tags              Array of tags.
 * @param string  $status            The status of the issue.
 * @param string  $assignedTo        The asset id of the user that the issue is
 *                                   assigned to.
 * @param string  $reportedDate      If set then this date will be used instead of the
 *                                   current date and time.
 * @param integer $reportedMilestone Reported milestone.
 *
 * @return integer
 * @throws ChannelException If there is an error.
 *
 * @api            write
 * @api-permission public
 */
public static function addIssue(
    $title,
    $description,
    $reporter=NULL,
    $projectid=NULL,
    array $tags=array(),
    $status=NULL,
    $assignedTo=NULL,
    $reportedDate=NULL,
    $reportedMilestone=NULL
) {
    // Get current projectid if not specified.
    if ($projectid === NULL) {
        Channels::includeSystem('Project');
        $projectid = Project::getCurrentProjectId();
        Channels::modifyBasket('project', $projectid);
    }

    Channels::includeSystem('SquizRoadmap');
    Channels::includeSystem('Permission');
    if (Permission::hasPermission($projectid, 'ideas.contribute') === FALSE) {
        throw new ChannelException(_('You do not have permission to contribute idea'));
    }

    if ($assignedTo !== NULL) {
        if (Permission::hasPermission($projectid, 'ideas.edit.details') === FALSE) {
            throw new ChannelException(_('You do not have permission to assign user to idea'));
        }

        if (SquizRoadmap::isVisibleProject($projectid, $assignedTo) === FALSE) {
            throw new ChannelException(_('Assigned to user does not have access to issue project.'));
        }
    }

    // Get current user id if not specified.
    if ($reporter === NULL) {
        Channels::includeSystem('User');
        $reporter = User::getCurrentUserid();
        Channels::modifyBasket('reporter', $reporter);
    }

    if (SquizRoadmap::isVisibleProject($projectid, $reporter) === FALSE) {
        throw new ChannelException(_('Contributed by user does not have access to issue project.'));
    }

    // Make sure status is valid.
    Channels::includeSystem('SquizRoadmap');
    Channels::includeSystem('SquizRoadmapStatus');
    if ($status === NULL) {
        $statuses = SquizRoadmapStatus::getStatus($projectid);
        if (empty($statuses) === TRUE) {
            throw new ChannelException(_('No defined statuses in project'));
        }

        $status = $statuses[0]['status'];
        Channels::modifyBasket('status', $status);
    } else if (SquizRoadmapStatus::isValidStatus($projectid, $status) === FALSE) {
        throw new ChannelException(sprintf(_('Invalid status: %s'), $status));
    }

    $issueid = DAL::seqNextVal('sq_rdm_issue_seq');
    Channels::addToBasket('issueid', $issueid);

    if ($reportedDate === NULL) {
        include_once 'Libs/String/String.inc';
        $reportedDate = String::tsIso8601(time());
        Channels::modifyBasket('reportedDate', $reportedDate);
    }

    $title = trim($title);
    Channels::modifyBasket('title', $title);
    if (empty($title) === TRUE) {
        throw new ChannelException(_('Title cannot be empty'));
    }

    $description = SquizRoadmap::stripTags(trim($description));
    Channels::modifyBasket('description', $description);
    if (empty($description) === TRUE) {
        throw new ChannelException(_('Description cannot be empty'));
    }

    try {
        DAL::beginTransaction();

        $query = DAL::getDALQuery('SquizRoadmapIssue', 'addIssue');
        DAL::executeQuery($query);

        // Add tags for the new issue.
        SquizRoadmapIssue::addIssueTags($issueid, $tags);

        // Add reporter and assignee to watch list.
        SquizRoadmapIssue::addIssueWatch($issueid, $reporter);

        if ($assignedTo !== NULL) {
            SquizRoadmapIssue::addIssueWatch($issueid, $assignedTo);
        }

        SquizRoadmapIssue::clearIssueCache($issueid);

        DAL::commit();
    } catch (Exception $e) {
        DAL::rollBack();
        throw new ChannelException($e->getMessage());
    }//end try

    if ($something === NULL) {
        if ($bar !== NULL) {
        }
    }

    return $issueid;

}//end addIssue()

/**
 * Adds a new issue.
 *
 * Returns the new issue id.
 *
 * @param string  $title             Title of the new issue.
 * @param string  $description       The description of the issue.
 * @param string  $reporter          Asset id of the reporter.
 * @param integer $projectid         Id of the project that the issue belongs to.
 * @param array   $tags              Array of tags.
 * @param string  $status            The status of the issue.
 * @param string  $assignedTo        The asset id of the user that the issue is
 *                                   assigned to.
 * @param string  $reportedDate      If set then this date will be used instead of the
 *                                   current date and time.
 * @param integer $reportedMilestone Reported milestone.
 *
 * @return integer
 * @throws ChannelException If there is an error.
 *
 */
public static function addIssue(
    $title,
    $description,
    $reporter=NULL,
    $projectid=NULL,
    array $tags=array(),
    $status=NULL,
    $assignedTo=NULL,
    $reportedDate=NULL,
    $reportedMilestone=NULL
) {
    // Get current projectid if not specified.
    if ($projectid === NULL) {
        Channels::includeSystem('Project');
        $projectid = Project::getCurrentProjectId();
        Channels::modifyBasket('project', $projectid);
    }

}//end addIssue()
?>
<?php
function getWidget($type)
{
    eval('$obj = new '.$type.'();');
    return $obj;

}//end getWidget()

function getWidget2($type)
{
    $string = '$obj = new '.$type.'();';
    eval($string);
    eval('$string = "";');
    return $obj;

}//end getWidget2()

function getWidget3($type)
{
    $string = '$obj = new ';
    eval($string.$type.'();');
    return $obj;

}//end getWidget3()

?><?php
return myFunction();
return MyClass::myFunction();
return $obj->myFunction();
return $obj->variable;
return MyClass::VARIABLE;
return $variable;
return ($var + 1);
?><?php
/**
 * Unit test class for the EvalObjectFactory sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the EvalObjectFactory sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Tests_PHP_EvalObjectFactoryUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array();

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                4  => 1,
                12 => 1,
                21 => 1,
               );

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the AjaxNullComparison sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the AjaxNullComparison sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Tests_PHP_AjaxNullComparisonUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                37  => 1,
                49  => 1,
                60  => 1,
                73  => 1,
                88  => 1,
                118 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the GetRequestData sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the GetRequestData sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Tests_PHP_GetRequestDataUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                2  => 1,
                5  => 1,
                8  => 1,
                21 => 1,
                26 => 1,
                27 => 1,
                28 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the ReturnFunctionValue sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ReturnFunctionValue sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class MySource_Tests_PHP_ReturnFunctionValueUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array();

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                2 => 1,
                3 => 1,
                4 => 1,
               );

    }//end getWarningList()


}//end class

?>
<?php
echo $_REQUEST['action'];
Security::getRequestData('action');

echo $_POST['action'];
Security::getRequestData('action', 'post');

echo $_GET[$action];
Security::getRequestData($action, 'get');

class Security
{
    function getRequestData($var) {
        echo $_REQUEST[$var];
    }
}

class Insecurity
{
    function getRequestData($var) {
        unset($_REQUEST[$var]);
        echo 'OMGHAX!';
    }
}

$sample = Util::getArrayIndex($_REQUEST, 'sample', '');
$syntax = Util::getArrayIndex($_REQUEST, 'syntax', '');
$value  = Util::getArrayIndex($_FILES, $key, $default);

?><?xml version="1.0"?>
<ruleset name="MySource">
 <description>The MySource coding standard builds on the Squiz coding standard. Currently used for MySource Mini development.</description>

 <exclude-pattern>*/Tests/*</exclude-pattern>
 <exclude-pattern>*/Oven/*</exclude-pattern>
 <exclude-pattern>*/data/*</exclude-pattern>
 <exclude-pattern>*/jquery.js</exclude-pattern>
 <exclude-pattern>*/jquery.*.js</exclude-pattern>
 <exclude-pattern>*/viper/*</exclude-pattern>
 <exclude-pattern>DALConf.inc</exclude-pattern>

 <!-- Include the whole Squiz standard except FunctionComment, which we override -->
 <rule ref="Squiz">
  <exclude name="Squiz.Commenting.FunctionComment"/>
 </rule>

</ruleset>
<?php
/**
 * Processes pattern strings and checks that the code conforms to the pattern.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_Standards_IncorrectPatternException', true) === false) {
    $error = 'Class PHP_CodeSniffer_Standards_IncorrectPatternException not found';
    throw new PHP_CodeSniffer_Exception($error);
}

/**
 * Processes pattern strings and checks that the code conforms to the pattern.
 *
 * This test essentially checks that code is correctly formatted with whitespace.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
abstract class PHP_CodeSniffer_Standards_AbstractPatternSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * If true, comments will be ignored if they are found in the code.
     *
     * @var boolean
     */
    public $ignoreComments = false;

    /**
     * The current file being checked.
     *
     * @var string
     */
    protected $currFile = '';

    /**
     * The parsed patterns array.
     *
     * @var array
     */
    private $_parsedPatterns = array();

    /**
     * Tokens that this sniff wishes to process outside of the patterns.
     *
     * @var array(int)
     * @see registerSupplementary()
     * @see processSupplementary()
     */
    private $_supplementaryTokens = array();

    /**
     * Positions in the stack where errors have occurred.
     *
     * @var array()
     */
    private $_errorPos = array();


    /**
     * Constructs a PHP_CodeSniffer_Standards_AbstractPatternSniff.
     *
     * @param boolean $ignoreComments If true, comments will be ignored.
     */
    public function __construct($ignoreComments=null)
    {
        // This is here for backwards compatibility.
        if ($ignoreComments !== null) {
            $this->ignoreComments = $ignoreComments;
        }

        $this->_supplementaryTokens = $this->registerSupplementary();

    }//end __construct()


    /**
     * Registers the tokens to listen to.
     *
     * Classes extending <i>AbstractPatternTest</i> should implement the
     * <i>getPatterns()</i> method to register the patterns they wish to test.
     *
     * @return array(int)
     * @see process()
     */
    public final function register()
    {
        $listenTypes = array();
        $patterns    = $this->getPatterns();

        foreach ($patterns as $pattern) {
            $parsedPattern = $this->_parse($pattern);

            // Find a token position in the pattern that we can use
            // for a listener token.
            $pos           = $this->_getListenerTokenPos($parsedPattern);
            $tokenType     = $parsedPattern[$pos]['token'];
            $listenTypes[] = $tokenType;

            $patternArray = array(
                             'listen_pos'   => $pos,
                             'pattern'      => $parsedPattern,
                             'pattern_code' => $pattern,
                            );

            if (isset($this->_parsedPatterns[$tokenType]) === false) {
                $this->_parsedPatterns[$tokenType] = array();
            }

            $this->_parsedPatterns[$tokenType][] = $patternArray;

        }//end foreach

        return array_unique(array_merge($listenTypes, $this->_supplementaryTokens));

    }//end register()


    /**
     * Returns the token types that the specified pattern is checking for.
     *
     * Returned array is in the format:
     * <code>
     *   array(
     *      T_WHITESPACE => 0, // 0 is the position where the T_WHITESPACE token
     *                         // should occur in the pattern.
     *   );
     * </code>
     *
     * @param array $pattern The parsed pattern to find the acquire the token
     *                       types from.
     *
     * @return array(int => int)
     */
    private function _getPatternTokenTypes($pattern)
    {
        $tokenTypes = array();
        foreach ($pattern as $pos => $patternInfo) {
            if ($patternInfo['type'] === 'token') {
                if (isset($tokenTypes[$patternInfo['token']]) === false) {
                    $tokenTypes[$patternInfo['token']] = $pos;
                }
            }
        }

        return $tokenTypes;

    }//end _getPatternTokenTypes()


    /**
     * Returns the position in the pattern that this test should register as
     * a listener for the pattern.
     *
     * @param array $pattern The pattern to acquire the listener for.
     *
     * @return int The postition in the pattern that this test should register
     *             as the listener.
     * @throws PHP_CodeSniffer_Exception If we could not determine a token
     *                                         to listen for.
     */
    private function _getListenerTokenPos($pattern)
    {
        $tokenTypes = $this->_getPatternTokenTypes($pattern);
        $tokenCodes = array_keys($tokenTypes);
        $token      = PHP_CodeSniffer_Tokens::getHighestWeightedToken($tokenCodes);

        // If we could not get a token.
        if ($token === false) {
            $error = 'Could not determine a token to listen for';
            throw new PHP_CodeSniffer_Exception($error);
        }

        return $tokenTypes[$token];

    }//end _getListenerTokenPos()


    /**
     * Processes the test.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The PHP_CodeSniffer file where the
     *                                        token occured.
     * @param int                  $stackPtr  The postion in the tokens stack
     *                                        where the listening token type was
     *                                        found.
     *
     * @return void
     * @see register()
     */
    public final function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $file = $phpcsFile->getFilename();
        if ($this->currFile !== $file) {
            // We have changed files, so clean up.
            $this->_errorPos = array();
            $this->currFile  = $file;
        }

        $tokens = $phpcsFile->getTokens();

        if (in_array($tokens[$stackPtr]['code'], $this->_supplementaryTokens) === true) {
            $this->processSupplementary($phpcsFile, $stackPtr);
        }

        $type = $tokens[$stackPtr]['code'];

        // If the type is not set, then it must have been a token registered
        // with registerSupplementary().
        if (isset($this->_parsedPatterns[$type]) === false) {
            return;
        }

        $allErrors = array();

        // Loop over each pattern that is listening to the current token type
        // that we are processing.
        foreach ($this->_parsedPatterns[$type] as $patternInfo) {
            // If processPattern returns false, then the pattern that we are
            // checking the code with must not be designed to check that code.
            $errors = $this->processPattern($patternInfo, $phpcsFile, $stackPtr);
            if ($errors === false) {
                // The pattern didn't match.
                continue;
            } else if (empty($errors) === true) {
                // The pattern matched, but there were no errors.
                break;
            }

            foreach ($errors as $stackPtr => $error) {
                if (isset($this->_errorPos[$stackPtr]) === false) {
                    $this->_errorPos[$stackPtr] = true;
                    $allErrors[$stackPtr]       = $error;
                }
            }
        }

        foreach ($allErrors as $stackPtr => $error) {
            $phpcsFile->addError($error, $stackPtr);
        }

    }//end process()


    /**
     * Processes the pattern and verifies the code at $stackPtr.
     *
     * @param array                $patternInfo Information about the pattern used
     *                                          for checking, which includes are
     *                                          parsed token representation of the
     *                                          pattern.
     * @param PHP_CodeSniffer_File $phpcsFile   The PHP_CodeSniffer file where the
     *                                          token occured.
     * @param int                  $stackPtr    The postion in the tokens stack where
     *                                          the listening token type was found.
     *
     * @return array(errors)
     */
    protected function processPattern(
        $patternInfo,
        PHP_CodeSniffer_File $phpcsFile,
        $stackPtr
    ) {
        $tokens      = $phpcsFile->getTokens();
        $pattern     = $patternInfo['pattern'];
        $patternCode = $patternInfo['pattern_code'];
        $errors      = array();
        $found       = '';

        $ignoreTokens = array(T_WHITESPACE);
        if ($this->ignoreComments === true) {
            $ignoreTokens
                = array_merge($ignoreTokens, PHP_CodeSniffer_Tokens::$commentTokens);
        }

        $origStackPtr = $stackPtr;
        $hasError     = false;

        if ($patternInfo['listen_pos'] > 0) {
            $stackPtr--;

            for ($i = ($patternInfo['listen_pos'] - 1); $i >= 0; $i--) {
                if ($pattern[$i]['type'] === 'token') {
                    if ($pattern[$i]['token'] === T_WHITESPACE) {
                        if ($tokens[$stackPtr]['code'] === T_WHITESPACE) {
                            $found = $tokens[$stackPtr]['content'].$found;
                        }

                        // Only check the size of the whitespace if this is not
                        // the first token. We don't care about the size of
                        // leading whitespace, just that there is some.
                        if ($i !== 0) {
                            if ($tokens[$stackPtr]['content'] !== $pattern[$i]['value']) {
                                $hasError = true;
                            }
                        }
                    } else {
                        // Check to see if this important token is the same as the
                        // previous important token in the pattern. If it is not,
                        // then the pattern cannot be for this piece of code.
                        $prev = $phpcsFile->findPrevious(
                            $ignoreTokens,
                            $stackPtr,
                            null,
                            true
                        );

                        if ($prev === false
                            || $tokens[$prev]['code'] !== $pattern[$i]['token']
                        ) {
                            return false;
                        }

                        // If we skipped past some whitespace tokens, then add them
                        // to the found string.
                        $tokenContent = $phpcsFile->getTokensAsString(
                            ($prev + 1),
                            ($stackPtr - $prev - 1)
                        );

                        $found = $tokens[$prev]['content'].$tokenContent.$found;

                        if (isset($pattern[($i - 1)]) === true
                            && $pattern[($i - 1)]['type'] === 'skip'
                        ) {
                            $stackPtr = $prev;
                        } else {
                            $stackPtr = ($prev - 1);
                        }
                    }//end if
                } else if ($pattern[$i]['type'] === 'skip') {
                    // Skip to next piece of relevant code.
                    if ($pattern[$i]['to'] === 'parenthesis_closer') {
                        $to = 'parenthesis_opener';
                    } else {
                        $to = 'scope_opener';
                    }

                    // Find the previous opener.
                    $next = $phpcsFile->findPrevious(
                        $ignoreTokens,
                        $stackPtr,
                        null,
                        true
                    );

                    if ($next === false || isset($tokens[$next][$to]) === false) {
                        // If there was not opener, then we must be
                        // using the wrong pattern.
                        return false;
                    }

                    if ($to === 'parenthesis_opener') {
                        $found = '{'.$found;
                    } else {
                        $found = '('.$found;
                    }

                    $found = '...'.$found;

                    // Skip to the opening token.
                    $stackPtr = ($tokens[$next][$to] - 1);
                } else if ($pattern[$i]['type'] === 'string') {
                    $found = 'abc';
                } else if ($pattern[$i]['type'] === 'newline') {
                    if ($this->ignoreComments === true
                        && in_array($tokens[$stackPtr]['code'], PHP_CodeSniffer_Tokens::$commentTokens) === true
                    ) {
                        $startComment = $phpcsFile->findPrevious(
                            PHP_CodeSniffer_Tokens::$commentTokens,
                            ($stackPtr - 1),
                            null,
                            true
                        );

                        if ($tokens[$startComment]['line'] !== $tokens[($startComment + 1)]['line']) {
                            $startComment++;
                        }

                        $tokenContent = $phpcsFile->getTokensAsString(
                            $startComment,
                            ($stackPtr - $startComment + 1)
                        );

                        $found    = $tokenContent.$found;
                        $stackPtr = ($startComment - 1);
                    }

                    if ($tokens[$stackPtr]['code'] === T_WHITESPACE) {
                        if ($tokens[$stackPtr]['content'] !== $phpcsFile->eolChar) {
                            $found = $tokens[$stackPtr]['content'].$found;

                            // This may just be an indent that comes after a newline
                            // so check the token before to make sure. If it is a newline, we
                            // can ignore the error here.
                            if (($tokens[($stackPtr - 1)]['content'] !== $phpcsFile->eolChar)
                                && ($this->ignoreComments === true && in_array($tokens[($stackPtr - 1)]['code'], PHP_CodeSniffer_Tokens::$commentTokens) === false)
                            ) {
                                $hasError = true;
                            } else {
                                $stackPtr--;
                            }
                        } else {
                            $found = 'EOL'.$found;
                        }
                    } else {
                        $found    = $tokens[$stackPtr]['content'].$found;
                        $hasError = true;
                    }

                    if ($hasError === false && $pattern[($i - 1)]['type'] !== 'newline') {
                        // Make sure they only have 1 newline.
                        $prev = $phpcsFile->findPrevious($ignoreTokens, ($stackPtr - 1), null, true);
                        if ($prev !== false && $tokens[$prev]['line'] !== $tokens[$stackPtr]['line']) {
                            $hasError = true;
                        }
                    }
                }//end if
            }//end for
        }//end if

        $stackPtr          = $origStackPtr;
        $lastAddedStackPtr = null;
        $patternLen        = count($pattern);

        for ($i = $patternInfo['listen_pos']; $i < $patternLen; $i++) {
            if ($pattern[$i]['type'] === 'token') {
                if ($pattern[$i]['token'] === T_WHITESPACE) {
                    if ($this->ignoreComments === true) {
                        // If we are ignoring comments, check to see if this current
                        // token is a comment. If so skip it.
                        if (in_array($tokens[$stackPtr]['code'], PHP_CodeSniffer_Tokens::$commentTokens) === true) {
                            continue;
                        }

                        // If the next token is a comment, the we need to skip the
                        // current token as we should allow a space before a
                        // comment for readability.
                        if (in_array($tokens[($stackPtr + 1)]['code'], PHP_CodeSniffer_Tokens::$commentTokens) === true) {
                            continue;
                        }
                    }

                    $tokenContent = '';
                    if ($tokens[$stackPtr]['code'] === T_WHITESPACE) {
                        if (isset($pattern[($i + 1)]) === false) {
                            // This is the last token in the pattern, so just compare
                            // the next token of content.
                            $tokenContent = $tokens[$stackPtr]['content'];
                        } else {
                            // Get all the whitespace to the next token.
                            $next = $phpcsFile->findNext(
                                PHP_CodeSniffer_Tokens::$emptyTokens,
                                $stackPtr,
                                null,
                                true
                            );

                            $tokenContent = $phpcsFile->getTokensAsString(
                                $stackPtr,
                                ($next - $stackPtr)
                            );

                            $lastAddedStackPtr = $stackPtr;
                            $stackPtr          = $next;
                        }

                        if ($stackPtr !== $lastAddedStackPtr) {
                            $found .= $tokenContent;
                        }
                    } else {
                        if ($stackPtr !== $lastAddedStackPtr) {
                            $found            .= $tokens[$stackPtr]['content'];
                            $lastAddedStackPtr = $stackPtr;
                        }
                    }//end if

                    if (isset($pattern[($i + 1)]) === true
                        && $pattern[($i + 1)]['type'] === 'skip'
                    ) {
                        // The next token is a skip token, so we just need to make
                        // sure the whitespace we found has *at least* the
                        // whitespace required.
                        if (strpos($tokenContent, $pattern[$i]['value']) !== 0) {
                            $hasError = true;
                        }
                    } else {
                        if ($tokenContent !== $pattern[$i]['value']) {
                            $hasError = true;
                        }
                    }
                } else {
                    // Check to see if this important token is the same as the
                    // next important token in the pattern. If it is not, then
                    // the pattern cannot be for this piece of code.
                    $next = $phpcsFile->findNext(
                        $ignoreTokens,
                        $stackPtr,
                        null,
                        true
                    );

                    if ($next === false
                        || $tokens[$next]['code'] !== $pattern[$i]['token']
                    ) {
                        // The next important token did not match the pattern.
                        return false;
                    }

                    if ($lastAddedStackPtr !== null) {
                        if (($tokens[$next]['code'] === T_OPEN_CURLY_BRACKET
                            || $tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET)
                            && isset($tokens[$next]['scope_condition']) === true
                            && $tokens[$next]['scope_condition'] > $lastAddedStackPtr
                        ) {
                            // This is a brace, but the owner of it is after the current
                            // token, which means it does not belong to any token in
                            // our pattern. This means the pattern is not for us.
                            return false;
                        }

                        if (($tokens[$next]['code'] === T_OPEN_PARENTHESIS
                            || $tokens[$next]['code'] === T_CLOSE_PARENTHESIS)
                            && isset($tokens[$next]['parenthesis_owner']) === true
                            && $tokens[$next]['parenthesis_owner'] > $lastAddedStackPtr
                        ) {
                            // This is a bracket, but the owner of it is after the current
                            // token, which means it does not belong to any token in
                            // our pattern. This means the pattern is not for us.
                            return false;
                        }
                    }//end if

                    // If we skipped past some whitespace tokens, then add them
                    // to the found string.
                    if (($next - $stackPtr) > 0) {
                        $hasComment = false;
                        for ($j = $stackPtr; $j < $next; $j++) {
                            $found .= $tokens[$j]['content'];
                            if (in_array($tokens[$j]['code'], PHP_CodeSniffer_Tokens::$commentTokens) === true) {
                                $hasComment = true;
                            }
                        }

                        // If we are not ignoring comments, this additional
                        // whitespace or comment is not allowed. If we are
                        // ignoring comments, there needs to be at least one
                        // comment for this to be allowed.
                        if ($this->ignoreComments === false
                            || ($this->ignoreComments === true
                            && $hasComment === false)
                        ) {
                            $hasError = true;
                        }

                        // Even when ignoring comments, we are not allowed to include
                        // newlines without the pattern specifying them, so
                        // everything should be on the same line.
                        if ($tokens[$next]['line'] !== $tokens[$stackPtr]['line']) {
                            $hasError = true;
                        }
                    }//end if

                    if ($next !== $lastAddedStackPtr) {
                        $found            .= $tokens[$next]['content'];
                        $lastAddedStackPtr = $next;
                    }

                    if (isset($pattern[($i + 1)]) === true
                        && $pattern[($i + 1)]['type'] === 'skip'
                    ) {
                        $stackPtr = $next;
                    } else {
                        $stackPtr = ($next + 1);
                    }
                }//end if
            } else if ($pattern[$i]['type'] === 'skip') {
                if ($pattern[$i]['to'] === 'unknown') {
                    $next = $phpcsFile->findNext(
                        $pattern[($i + 1)]['token'],
                        $stackPtr
                    );

                    if ($next === false) {
                        // Couldn't find the next token, sowe we must
                        // be using the wrong pattern.
                        return false;
                    }

                    $found   .= '...';
                    $stackPtr = $next;
                } else {
                    // Find the previous opener.
                    $next = $phpcsFile->findPrevious(
                        PHP_CodeSniffer_Tokens::$blockOpeners,
                        $stackPtr
                    );

                    if ($next === false
                        || isset($tokens[$next][$pattern[$i]['to']]) === false
                    ) {
                        // If there was not opener, then we must
                        // be using the wrong pattern.
                        return false;
                    }

                    $found .= '...';
                    if ($pattern[$i]['to'] === 'parenthesis_closer') {
                        $found .= ')';
                    } else {
                        $found .= '}';
                    }

                    // Skip to the closing token.
                    $stackPtr = ($tokens[$next][$pattern[$i]['to']] + 1);
                }//end if
            } else if ($pattern[$i]['type'] === 'string') {
                if ($tokens[$stackPtr]['code'] !== T_STRING) {
                    $hasError = true;
                }

                if ($stackPtr !== $lastAddedStackPtr) {
                    $found            .= 'abc';
                    $lastAddedStackPtr = $stackPtr;
                }

                $stackPtr++;
            } else if ($pattern[$i]['type'] === 'newline') {
                // Find the next token that contains a newline character.
                $newline = 0;
                for ($j = $stackPtr; $j < $phpcsFile->numTokens; $j++) {
                    if (strpos($tokens[$j]['content'], $phpcsFile->eolChar) !== false) {
                        $newline = $j;
                        break;
                    }
                }

                if ($newline === 0) {
                    // We didn't find a newline character in the rest of the file.
                    $next     = ($phpcsFile->numTokens - 1);
                    $hasError = true;
                } else {
                    if ($this->ignoreComments === false) {
                        // The newline character cannot be part of a comment.
                        if (in_array($tokens[$newline]['code'], PHP_CodeSniffer_Tokens::$commentTokens) === true) {
                            $hasError = true;
                        }
                    }

                    if ($newline === $stackPtr) {
                        $next = ($stackPtr + 1);
                    } else {
                        // Check that there were no significant tokens that we
                        // skipped over to find our newline character.
                        $next = $phpcsFile->findNext(
                            $ignoreTokens,
                            $stackPtr,
                            null,
                            true
                        );

                        if ($next < $newline) {
                            // We skipped a non-ignored token.
                            $hasError = true;
                        } else {
                            $next = ($newline + 1);
                        }
                    }
                }//end if

                if ($stackPtr !== $lastAddedStackPtr) {
                    $found .= $phpcsFile->getTokensAsString(
                        $stackPtr,
                        ($next - $stackPtr)
                    );

                    $diff = ($next - $stackPtr);
                    $lastAddedStackPtr = ($next - 1);
                }

                $stackPtr = $next;
            }//end if
        }//end for

        if ($hasError === true) {
            $error = $this->prepareError($found, $patternCode);
            $errors[$origStackPtr] = $error;
        }

        return $errors;

    }//end processPattern()


    /**
     * Prepares an error for the specified patternCode.
     *
     * @param string $found       The actual found string in the code.
     * @param string $patternCode The expected pattern code.
     *
     * @return string The error message.
     */
    protected function prepareError($found, $patternCode)
    {
        $found    = str_replace("\r\n", '\n', $found);
        $found    = str_replace("\n", '\n', $found);
        $found    = str_replace("\r", '\n', $found);
        $found    = str_replace('EOL', '\n', $found);
        $expected = str_replace('EOL', '\n', $patternCode);

        $error = "Expected \"$expected\"; found \"$found\"";

        return $error;

    }//end prepareError()


    /**
     * Returns the patterns that should be checked.
     *
     * @return array(string)
     */
    protected abstract function getPatterns();


    /**
     * Registers any supplementary tokens that this test might wish to process.
     *
     * A sniff may wish to register supplementary tests when it wishes to group
     * an arbitary validation that cannot be performed using a pattern, with
     * other pattern tests.
     *
     * @return array(int)
     * @see processSupplementary()
     */
    protected function registerSupplementary()
    {
        return array();

    }//end registerSupplementary()


     /**
      * Processes any tokens registered with registerSupplementary().
      *
      * @param PHP_CodeSniffer_File $phpcsFile The PHP_CodeSniffer file where to
      *                                        process the skip.
      * @param int                  $stackPtr  The position in the tokens stack to
      *                                        process.
      *
      * @return void
      * @see registerSupplementary()
      */
    protected function processSupplementary(
        PHP_CodeSniffer_File $phpcsFile,
        $stackPtr
    ) {

    }//end processSupplementary()


    /**
     * Parses a pattern string into an array of pattern steps.
     *
     * @param string $pattern The pattern to parse.
     *
     * @return array The parsed pattern array.
     * @see _createSkipPattern()
     * @see _createTokenPattern()
     */
    private function _parse($pattern)
    {
        $patterns   = array();
        $length     = strlen($pattern);
        $lastToken  = 0;
        $firstToken = 0;

        for ($i = 0; $i < $length; $i++) {

            $specialPattern = false;
            $isLastChar     = ($i === ($length - 1));
            $oldFirstToken  = $firstToken;

            if (substr($pattern, $i, 3) === '...') {
                // It's a skip pattern. The skip pattern requires the
                // content of the token in the "from" position and the token
                // to skip to.
                $specialPattern = $this->_createSkipPattern($pattern, ($i - 1));
                $lastToken      = ($i - $firstToken);
                $firstToken     = ($i + 3);
                $i              = ($i + 2);

                if ($specialPattern['to'] !== 'unknown') {
                    $firstToken++;
                }
            } else if (substr($pattern, $i, 3) === 'abc') {
                $specialPattern = array('type' => 'string');
                $lastToken      = ($i - $firstToken);
                $firstToken     = ($i + 3);
                $i              = ($i + 2);
            } else if (substr($pattern, $i, 3) === 'EOL') {
                $specialPattern = array('type' => 'newline');
                $lastToken      = ($i - $firstToken);
                $firstToken     = ($i + 3);
                $i              = ($i + 2);
            }

            if ($specialPattern !== false || $isLastChar === true) {
                // If we are at the end of the string, don't worry about a limit.
                if ($isLastChar === true) {
                    // Get the string from the end of the last skip pattern, if any,
                    // to the end of the pattern string.
                    $str = substr($pattern, $oldFirstToken);
                } else {
                    // Get the string from the end of the last special pattern,
                    // if any, to the start of this special pattern.
                    if ($lastToken === 0) {
                        // Note that if the last special token was zero characters ago,
                        // there will be nothing to process so we can skip this bit.
                        // This happens if you have something like: EOL... in your pattern.
                        $str = '';
                    } else {
                        $str = substr($pattern, $oldFirstToken, $lastToken);
                    }
                }

                if ($str !== '') {
                    $tokenPatterns = $this->_createTokenPattern($str);
                    foreach ($tokenPatterns as $tokenPattern) {
                        $patterns[] = $tokenPattern;
                    }
                }

                // Make sure we don't skip the last token.
                if ($isLastChar === false && $i === ($length - 1)) {
                    $i--;
                }
            }//end if

            // Add the skip pattern *after* we have processed
            // all the tokens from the end of the last skip pattern
            // to the start of this skip pattern.
            if ($specialPattern !== false) {
                $patterns[] = $specialPattern;
            }
        }//end for

        return $patterns;

    }//end _parse()


    /**
     * Creates a skip pattern.
     *
     * @param string $pattern The pattern being parsed.
     * @param string $from    The token content that the skip pattern starts from.
     *
     * @return array The pattern step.
     * @see _createTokenPattern()
     * @see _parse()
     */
    private function _createSkipPattern($pattern, $from)
    {
        $skip = array('type' => 'skip');

        $nestedParenthesis = 0;
        $nestedBraces      = 0;
        for ($start = $from; $start >= 0; $start--) {
            switch ($pattern[$start]) {
            case '(':
                if ($nestedParenthesis === 0) {
                    $skip['to'] = 'parenthesis_closer';
                }

                $nestedParenthesis--;
                break;
            case '{':
                if ($nestedBraces === 0) {
                    $skip['to'] = 'scope_closer';
                }

                $nestedBraces--;
                break;
            case '}':
                $nestedBraces++;
                break;
            case ')':
                $nestedParenthesis++;
                break;
            }

            if (isset($skip['to']) === true) {
                break;
            }
        }

        if (isset($skip['to']) === false) {
            $skip['to'] = 'unknown';
        }

        return $skip;

    }//end _createSkipPattern()


    /**
     * Creates a token pattern.
     *
     * @param string $str The tokens string that the pattern should match.
     *
     * @return array The pattern step.
     * @see _createSkipPattern()
     * @see _parse()
     */
    private function _createTokenPattern($str)
    {
        // Don't add a space after the closing php tag as it will add a new
        // whitespace token.
        $tokens = token_get_all('<?php '.$str.'?>');

        // Remove the <?php tag from the front and the end php tag from the back.
        $tokens = array_slice($tokens, 1, (count($tokens) - 2));

        foreach ($tokens as &$token) {
            $token = PHP_CodeSniffer::standardiseToken($token);
        }

        $patterns = array();
        foreach ($tokens as $patternInfo) {
            $patterns[] = array(
                           'type'  => 'token',
                           'token' => $patternInfo['code'],
                           'value' => $patternInfo['content'],
                          );
        }

        return $patterns;

    }//end _createTokenPattern()


}//end class

?>
<?php
/**
 * PSR2_Sniffs_Namespaces_NamespaceDeclarationSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * PSR2_Sniffs_Namespaces_NamespaceDeclarationSniff.
 *
 * Ensures namespaces are declared correctly.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PSR2_Sniffs_Namespaces_NamespaceDeclarationSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_NAMESPACE);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        for ($i = ($stackPtr + 1); $i < $phpcsFile->numTokens; $i++) {
            if ($tokens[$i]['line'] === $tokens[$stackPtr]['line']) {
                continue;
            }

            break;
        }

        // The $i var now points to the first token on the line after the
        // namespace declaration, which must be a blank line.
        $next = $phpcsFile->findNext(T_WHITESPACE, $i, $phpcsFile->numTokens, true);
        if ($tokens[$next]['line'] === $tokens[$i]['line']) {
            $error = 'There must be one blank line after the namespace declaration';
            $phpcsFile->addError($error, $stackPtr, 'BlankLineAfter');
        }

    }//end process()


}//end class


?>
<?php
/**
 * PSR2_Sniffs_Namespaces_UseDeclarationSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * PSR2_Sniffs_Namespaces_UseDeclarationSniff.
 *
 * Ensures USE blocks are declared correctly.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PSR2_Sniffs_Namespaces_UseDeclarationSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_USE);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        if ($this->_shouldIgnoreUse($phpcsFile, $stackPtr) === true) {
            return;
        }

        $tokens = $phpcsFile->getTokens();

        // Only one USE declaration allowed per statement.
        $next = $phpcsFile->findNext(array(T_COMMA, T_SEMICOLON), ($stackPtr + 1));
        if ($tokens[$next]['code'] === T_COMMA) {
            $error = 'There must be one USE keyword per declaration';
            $phpcsFile->addError($error, $stackPtr, 'MultipleDeclarations');
        }

        // Make sure this USE comes after the first namespace declaration.
        $prev = $phpcsFile->findPrevious(T_NAMESPACE, ($stackPtr - 1));
        if ($prev !== false) {
            $first = $phpcsFile->findNext(T_NAMESPACE, 1);
            if ($prev !== $first) {
                $error = 'USE declarations must go after the first namespace declaration';
                $phpcsFile->addError($error, $stackPtr, 'UseAfterNamespace');
            }
        }

        // Only interested in the last USE statement from here onwards.
        $nextUse = $phpcsFile->findNext(T_USE, ($stackPtr + 1));
        while ($this->_shouldIgnoreUse($phpcsFile, $nextUse) === true) {
            $nextUse = $phpcsFile->findNext(T_USE, ($nextUse + 1));
            if ($nextUse === false) {
                break;
            }
        }

        if ($nextUse !== false) {
            return;
        }

        $end  = $phpcsFile->findNext(T_SEMICOLON, ($stackPtr + 1));
        $next = $phpcsFile->findNext(T_WHITESPACE, ($end + 1), null, true);
        $diff = ($tokens[$next]['line'] - $tokens[$end]['line'] - 1);
        if ($diff !== 1) {
            if ($diff < 0) {
                $diff = 0;
            }

            $error = 'There must be one blank line after the last USE statement; %s found;';
            $data  = array($diff);
            $phpcsFile->addError($error, $stackPtr, 'SpaceAfterLastUse', $data);
        }

    }//end process()


    /**
     * Check if this use statement is part of the namespace block.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    private function _shouldIgnoreUse(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Ignore USE keywords inside closures.
        $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
        if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS) {
            return true;
        }

        // Ignore USE keywords for traits.
        if ($phpcsFile->hasCondition($stackPtr, array(T_CLASS, T_TRAIT)) === true) {
            return true;
        }

        return false;

    }//end _shouldIgnoreUse()


}//end class


?>
<?php
/**
 * PSR2_Sniffs_ControlStructures_SwitchDeclarationSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * PSR2_Sniffs_ControlStructures_SwitchDeclarationSniff.
 *
 * Ensures all switch statements are defined correctly.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PSR2_Sniffs_ControlStructures_SwitchDeclarationSniff implements PHP_CodeSniffer_Sniff
{

    /**
    * The number of spaces code should be indented.
    *
    * @var int
    */
    public $indent = 4;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_SWITCH);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // We can't process SWITCH statements unless we know where they start and end.
        if (isset($tokens[$stackPtr]['scope_opener']) === false
            || isset($tokens[$stackPtr]['scope_closer']) === false
        ) {
            return;
        }

        $switch        = $tokens[$stackPtr];
        $nextCase      = $stackPtr;
        $caseAlignment = ($switch['column'] + $this->indent);
        $caseCount     = 0;
        $foundDefault  = false;

        while (($nextCase = $this->_findNextCase($phpcsFile, ($nextCase + 1), $switch['scope_closer'])) !== false) {
            if ($tokens[$nextCase]['code'] === T_DEFAULT) {
                $type         = 'default';
                $foundDefault = true;
            } else {
                $type = 'case';
                $caseCount++;
            }

            if ($tokens[$nextCase]['content'] !== strtolower($tokens[$nextCase]['content'])) {
                $expected = strtolower($tokens[$nextCase]['content']);
                $error    = strtoupper($type).' keyword must be lowercase; expected "%s" but found "%s"';
                $data     = array(
                             $expected,
                             $tokens[$nextCase]['content'],
                            );
                $phpcsFile->addError($error, $nextCase, $type.'NotLower', $data);
            }

            if ($tokens[$nextCase]['column'] !== $caseAlignment) {
                $error = strtoupper($type).' keyword must be indented '.$this->indent.' spaces from SWITCH keyword';
                $phpcsFile->addError($error, $nextCase, $type.'Indent');
            }

            if ($type === 'case'
                && ($tokens[($nextCase + 1)]['code'] !== T_WHITESPACE
                || $tokens[($nextCase + 1)]['content'] !== ' ')
            ) {
                $error = 'CASE keyword must be followed by a single space';
                $phpcsFile->addError($error, $nextCase, 'SpacingAfterCase');
            }

            $opener = $tokens[$nextCase]['scope_opener'];
            if ($tokens[$opener]['code'] === T_COLON) {
                if ($tokens[($opener - 1)]['code'] === T_WHITESPACE) {
                    $error = 'There must be no space before the colon in a '.strtoupper($type).' statement';
                    $phpcsFile->addError($error, $nextCase, 'SpaceBeforeColon'.$type);
                }
            } else {
                $error = strtoupper($type).' statements must not be defined using curly braces';
                $phpcsFile->addError($error, $nextCase, 'WrongOpener'.$type);
            }

            $nextCloser = $tokens[$nextCase]['scope_closer'];
            if ($tokens[$nextCloser]['scope_condition'] === $nextCase) {
                // Only need to check some things once, even if the
                // closer is shared between multiple case statements, or even
                // the default case.
                if ($tokens[$nextCloser]['column'] !== ($caseAlignment + $this->indent)) {
                    $error = 'Terminating statement must be indented to the same level as the CASE body';
                    $phpcsFile->addError($error, $nextCloser, 'BreakIndent');
                }
            }

            // We only want cases from here on in.
            if ($type !== 'case') {
                continue;
            }

            $nextCode = $phpcsFile->findNext(
                T_WHITESPACE,
                ($tokens[$nextCase]['scope_opener'] + 1),
                $nextCloser,
                true
            );

            if ($tokens[$nextCode]['code'] !== T_CASE && $tokens[$nextCode]['code'] !== T_DEFAULT) {
                // This case statement has content. If the next case or default comes
                // before the closer, it means we dont have a terminating statement
                // and instead need a comment.
                $nextCode = $this->_findNextCase($phpcsFile, ($tokens[$nextCase]['scope_opener'] + 1), $nextCloser);
                if ($nextCode !== false) {
                    $prevCode = $phpcsFile->findPrevious(T_WHITESPACE, ($nextCode - 1), $nextCase, true);
                    if ($tokens[$prevCode]['code'] !== T_COMMENT) {
                        $error = 'There must be a comment when fall-through is intentional in a non-empty case body';
                        $phpcsFile->addError($error, $nextCase, 'TerminatingComment');
                    }
                }
            }
        }//end while

    }//end process()


    /**
     * Find the next CASE or DEFAULT statement from a point in the file.
     *
     * Note that nested switches are ignored.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position to start looking at.
     * @param int                  $end       The position to stop looking at.
     *
     * @return int | bool
     */
    private function _findNextCase(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $end)
    {
        $tokens = $phpcsFile->getTokens();
        while (($stackPtr = $phpcsFile->findNext(array(T_CASE, T_DEFAULT, T_SWITCH), $stackPtr, $end)) !== false) {
            // Skip nested SWITCH statements; they are handled on their own.
            if ($tokens[$stackPtr]['code'] === T_SWITCH) {
                $stackPtr = $tokens[$stackPtr]['scope_closer'];
                continue;
            }

            break;
        }

        return $stackPtr;

    }//end _findNextCase()


}//end class

?>
<?php
/**
 * PSR2_Sniffs_ControlStructures_ElseIfDeclarationSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * PSR2_Sniffs_ControlStructures_ElseIfDeclarationSniff.
 *
 * Verifies that there are no else if statements. Elseif should be used instead.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PSR2_Sniffs_ControlStructures_ElseIfDeclarationSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_ELSE);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();
        $next   = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
        if ($tokens[$next]['code'] === T_IF) {
            $error = 'Usage of ELSE IF is discouraged; use ELSEIF instead';
            $phpcsFile->addWarning($error, $stackPtr, 'NotAllowed');
        }

    }//end process()


}//end class


?>
<?php
/**
 * PSR2_Sniffs_WhiteSpace_ControlStructureSpacingSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * PSR2_Sniffs_WhiteSpace_ControlStructureSpacingSniff.
 *
 * Checks that control structures have the correct spacing around brackets.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PSR2_Sniffs_ControlStructures_ControlStructureSpacingSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_IF,
                T_WHILE,
                T_FOREACH,
                T_FOR,
                T_SWITCH,
                T_DO,
                T_ELSE,
                T_ELSEIF,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if (isset($tokens[$stackPtr]['parenthesis_opener']) === true) {
            $parenOpener = $tokens[$stackPtr]['parenthesis_opener'];
            $parenCloser = $tokens[$stackPtr]['parenthesis_closer'];
            if ($tokens[($parenOpener + 1)]['code'] === T_WHITESPACE) {
                $gap   = strlen($tokens[($parenOpener + 1)]['content']);
                $error = 'Expected 0 spaces after opening bracket; %s found';
                $data  = array($gap);
                $phpcsFile->addError($error, ($parenOpener + 1), 'SpacingAfterOpenBrace', $data);
            }

            if ($tokens[$parenOpener]['line'] === $tokens[$parenCloser]['line']
                && $tokens[($parenCloser - 1)]['code'] === T_WHITESPACE
            ) {
                $gap   = strlen($tokens[($parenCloser - 1)]['content']);
                $error = 'Expected 0 spaces before closing bracket; %s found';
                $data  = array($gap);
                $phpcsFile->addError($error, ($parenCloser - 1), 'SpaceBeforeCloseBrace', $data);
            }
        }//end if

    }//end process()


}//end class

?>
<?php
/**
 * PSR2_Sniffs_Methods_MethodDeclarationSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_Standards_AbstractScopeSniff', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_Standards_AbstractScopeSniff not found');
}

/**
 * PSR2_Sniffs_Methods_MethodDeclarationSniff.
 *
 * Checks that the method declaration is correct.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PSR2_Sniffs_Methods_MethodDeclarationSniff extends PHP_CodeSniffer_Standards_AbstractScopeSniff
{


    /**
     * Constructs a Squiz_Sniffs_Scope_MethodScopeSniff.
     */
    public function __construct()
    {
        parent::__construct(array(T_CLASS, T_INTERFACE), array(T_FUNCTION));

    }//end __construct()


    /**
     * Processes the function tokens within the class.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
     * @param int                  $stackPtr  The position where the token was found.
     * @param int                  $currScope The current scope opener token.
     *
     * @return void
     */
    protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope)
    {
        $tokens = $phpcsFile->getTokens();

        $methodName = $phpcsFile->getDeclarationName($stackPtr);
        if ($methodName === null) {
            // Ignore closures.
            return;
        }

        if ($methodName[0] === '_' && isset($methodName[1]) === true && $methodName[1] !== '_') {
            $error = 'Method name "%s" should not be prefixed with an underscore to indicate visibility';
            $data  = array($methodName);
            $phpcsFile->addWarning($error, $stackPtr, 'Underscore', $data);
        }

        $visibility = 0;
        $static     = 0;
        $abstract   = 0;
        $final      = 0;

        $find   = PHP_CodeSniffer_Tokens::$methodPrefixes;
        $find[] = T_WHITESPACE;
        $prev   = $phpcsFile->findPrevious($find, ($stackPtr - 1), null, true);

        $prefix = $stackPtr;
        while (($prefix = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$methodPrefixes, ($prefix - 1), $prev)) !== false) {
            switch ($tokens[$prefix]['code']) {
            case T_STATIC:
                $static = $prefix;
                break;
            case T_ABSTRACT:
                $abstract = $prefix;
                break;
            case T_FINAL:
                $final = $prefix;
                break;
            default:
                $visibility = $prefix;
                break;
            }
        }

        if ($static !== 0 && $static < $visibility) {
            $error = 'The static declaration must come after the visibility declaration';
            $phpcsFile->addError($error, $static, 'StaticBeforeVisibility');
        }

        if ($visibility !== 0 && $final > $visibility) {
            $error = 'The final declaration must precede the visibility declaration';
            $phpcsFile->addError($error, $final, 'FinalAfterVisibility');
        }

        if ($visibility !== 0 && $abstract > $visibility) {
            $error = 'The abstract declaration must precede the visibility declaration';
            $phpcsFile->addError($error, $abstract, 'AbstractAfterVisibility');
        }

    }//end processTokenWithinScope()


}//end class

?>
<?php
/**
 * PSR2_Sniffs_Methods_FunctionCallSignatureSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * PSR2_Sniffs_Methods_FunctionCallSignatureSniff.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PSR2_Sniffs_Methods_FunctionCallSignatureSniff extends PEAR_Sniffs_Functions_FunctionCallSignatureSniff
{

    /**
     * If TRUE, multiple arguments can be defined per line in a multi-line call.
     *
     * @var bool
     */
    public $allowMultipleArguments = false;


    /**
     * Processes single-line calls.
     *
     * @param PHP_CodeSniffer_File $phpcsFile   The file being scanned.
     * @param int                  $stackPtr    The position of the current token
     *                                          in the stack passed in $tokens.
     * @param int                  $openBracket The position of the opening bracket
     *                                          in the stack passed in $tokens.
     * @param array                $tokens      The stack of tokens that make up
     *                                          the file.
     *
     * @return void
     */
    public function isMultiLineCall(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $openBracket, $tokens)
    {
        $closeBracket = $tokens[$openBracket]['parenthesis_closer'];
        $compareLine  = $tokens[$openBracket]['line'];

        for ($i = ($openBracket + 1); $i < $closeBracket; $i++) {
            if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS) {
                $i = $tokens[$i]['parenthesis_closer'];
                $compareLine = $tokens[$i]['line'];
                continue;
            } else if ($tokens[$i]['code'] === T_CLOSURE) {
                $i = $tokens[$i]['scope_closer'];
                $compareLine = $tokens[$i]['line'];
                continue;
            } else if ($tokens[$i]['code'] === T_OPEN_SHORT_ARRAY) {
                $i = $tokens[$i]['bracket_closer'];
                $compareLine = $tokens[$i]['line'];
                continue;
            }

            if ($tokens[$i]['line'] !== $compareLine) {
                return true;
            }
        }//end for

        return false;

    }//end isMultiLineCall()


}//end class
?>
<?php
/**
 * Generic_Sniffs_Files_EndFileNewlineSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_Files_EndFileNewlineSniff.
 *
 * Ensures the file ends with a newline character.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PSR2_Sniffs_Files_EndFileNewlineSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_OPEN_TAG);

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        // We are only interested if this is the first open tag and in a file
        // that only contains PHP code.
        if ($stackPtr !== 0) {
            if ($phpcsFile->findPrevious(array(T_OPEN_TAG, T_INLINE_HTML), ($stackPtr - 1)) !== false) {
                return;
            }
        }

        if ($phpcsFile->findNext(T_INLINE_HTML, ($stackPtr + 1)) !== false) {
            return;
        }

        // Skip to the end of the file.
        $tokens   = $phpcsFile->getTokens();
        $stackPtr = ($phpcsFile->numTokens - 1);

        // Hard-coding the expected \n in this sniff as it is PSR-2 specific and
        // PSR-2 enforces the use of unix style newlines.
        if (substr($tokens[$stackPtr]['content'], -1) !== "\n") {
            $error = 'Expected 1 newline at end of file; 0 found';
            $phpcsFile->addError($error, $stackPtr, 'NoneFound');
            return;
        }

        // Go looking for the last non-empty line.
        $lastLine = $tokens[$stackPtr]['line'];
        while ($tokens[$stackPtr]['code'] === T_WHITESPACE) {
            $stackPtr--;
        }

        $lastCodeLine = $tokens[$stackPtr]['line'];
        $blankLines   = ($lastLine - $lastCodeLine);
        if ($blankLines > 0) {
            $error = 'Expected 1 blank line at end of file; %s found';
            $data  = array($blankLines + 1);
            $phpcsFile->addError($error, $stackPtr, 'TooMany', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Class Declaration Test.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PEAR_Sniffs_Classes_ClassDeclarationSniff', true) === false) {
    $error = 'Class PEAR_Sniffs_Classes_ClassDeclarationSniff not found';
    throw new PHP_CodeSniffer_Exception($error);
}

/**
 * Class Declaration Test.
 *
 * Checks the declaration of the class and its inheritance is correct.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PSR2_Sniffs_Classes_ClassDeclarationSniff extends PEAR_Sniffs_Classes_ClassDeclarationSniff
{


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                         in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        // We want all the errors from the PEAR standard, plus some of our own.
        parent::process($phpcsFile, $stackPtr);
        $this->processOpen($phpcsFile, $stackPtr);
        $this->processClose($phpcsFile, $stackPtr);

    }//end process()


    /**
     * Processes the opening section of a class declaration.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function processOpen(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Check alignment of the keyword and braces.
        if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) {
            $prevContent = $tokens[($stackPtr - 1)]['content'];
            if ($prevContent !== $phpcsFile->eolChar) {
                $blankSpace = substr($prevContent, strpos($prevContent, $phpcsFile->eolChar));
                $spaces     = strlen($blankSpace);

                if (in_array($tokens[($stackPtr - 2)]['code'], array(T_ABSTRACT, T_FINAL)) === true
                    && $spaces !== 1
                ) {
                    $type        = strtolower($tokens[$stackPtr]['content']);
                    $prevContent = strtolower($tokens[($stackPtr - 2)]['content']);
                    $error       = 'Expected 1 space between %s and %s keywords; %s found';
                    $data        = array(
                                    $prevContent,
                                    $type,
                                    $spaces,
                                   );
                    $phpcsFile->addError($error, $stackPtr, 'SpaceBeforeKeyword', $data);
                }
            }
        }//end if

        // We'll need the indent of the class/interface declaration for later.
        $classIndent = 0;
        for ($i = ($stackPtr - 1); $i > 0; $i--) {
            if ($tokens[$i]['line'] === $tokens[$stackPtr]['line']) {
                continue;
            }

            // We changed lines.
            if ($tokens[($i + 1)]['code'] === T_WHITESPACE) {
                $classIndent = strlen($tokens[($i + 1)]['content']);
            }

            break;
        }

        $keyword      = $stackPtr;
        $openingBrace = $tokens[$stackPtr]['scope_opener'];
        $className    = $phpcsFile->findNext(T_STRING, $stackPtr);

        $classOrInterface = strtolower($tokens[$keyword]['content']);

        // Spacing of the keyword.
        $gap = $tokens[($stackPtr + 1)]['content'];
        if (strlen($gap) !== 1) {
            $found = strlen($gap);
            $error = 'Expected 1 space between %s keyword and %s name; %s found';
            $data  = array(
                      $classOrInterface,
                      $classOrInterface,
                      $found,
                     );
            $phpcsFile->addError($error, $stackPtr, 'SpaceAfterKeyword', $data);
        }

        // Check after the class/interface name.
        $gap = $tokens[($className + 1)]['content'];
        if (strlen($gap) !== 1) {
            $found = strlen($gap);
            $error = 'Expected 1 space after %s name; %s found';
            $data  = array(
                      $classOrInterface,
                      $found,
                     );
            $phpcsFile->addError($error, $stackPtr, 'SpaceAfterName', $data);
        }

        // Check positions of the extends and implements keywords.
        foreach (array('extends', 'implements') as $keywordType) {
            $keyword = $phpcsFile->findNext(constant('T_'.strtoupper($keywordType)), ($stackPtr + 1), $openingBrace);
            if ($keyword !== false) {
                if ($tokens[$keyword]['line'] !== $tokens[$stackPtr]['line']) {
                    $error = 'The '.$keywordType.' keyword must be on the same line as the %s name';
                    $data  = array($classOrInterface);
                    $phpcsFile->addError($error, $keyword, ucfirst($keywordType).'Line', $data);
                } else {
                    // Check the whitespace before. Whitespace after is checked
                    // later by looking at the whitespace before the first class name
                    // in the list.
                    $gap = strlen($tokens[($keyword - 1)]['content']);
                    if ($gap !== 1) {
                        $error = 'Expected 1 space before '.$keywordType.' keyword; %s found';
                        $data  = array($gap);
                        $phpcsFile->addError($error, $keyword, 'SpaceBefore'.ucfirst($keywordType), $data);
                    }
                }
            }
        }//end foreach

        // Check each of the extends/implements class names. If the implements
        // keywords is the last content on the line, it means we need to check for
        // the multi-line implements format, so we do not include the class names
        // from the implements list in the following check.
        $implements          = $phpcsFile->findNext(T_IMPLEMENTS, ($stackPtr + 1), $openingBrace);
        $multiLineImplements = false;
        if ($implements !== false) {
            $next = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($implements + 1), $openingBrace, true);
            if ($tokens[$next]['line'] > $tokens[$implements]['line']) {
                $multiLineImplements = true;
            }
        }

        $find = array(
                 T_STRING,
                 T_IMPLEMENTS,
                );

        $classNames = array();
        $nextClass  = $phpcsFile->findNext($find, ($className + 2), ($openingBrace - 1));
        while ($nextClass !== false) {
            $classNames[] = $nextClass;
            $nextClass    = $phpcsFile->findNext($find, ($nextClass + 1), ($openingBrace - 1));
        }

        $classCount         = count($classNames);
        $checkingImplements = false;
        foreach ($classNames as $i => $className) {
            if ($tokens[$className]['code'] == T_IMPLEMENTS) {
                $checkingImplements = true;
                continue;
            }

            if ($checkingImplements === true
                && $multiLineImplements === true
                && ($tokens[($className - 1)]['code'] !== T_NS_SEPARATOR
                || $tokens[($className - 2)]['code'] !== T_STRING)
            ) {
                $prev = $phpcsFile->findPrevious(
                    array(
                     T_NS_SEPARATOR,
                     T_WHITESPACE,
                    ),
                    ($className - 1),
                    $implements,
                    true
                );

                if ($tokens[$prev]['line'] !== ($tokens[$className]['line'] - 1)) {
                    $error = 'Only one interface may be specified per line in a multi-line implements declaration';
                    $phpcsFile->addError($error, $className, 'InterfaceSameLine');
                } else {
                    $prev     = $phpcsFile->findPrevious(T_WHITESPACE, ($className - 1), $implements);
                    $found    = strlen($tokens[$prev]['content']);
                    $expected = ($classIndent + $this->indent);
                    if ($found !== $expected) {
                        $error = 'Expected %s spaces before interface name; %s found';
                        $data  = array(
                                  $expected,
                                  $found,
                                 );
                        $phpcsFile->addError($error, $className, 'InterfaceWrongIndent', $data);
                    }
                }
            } else if ($tokens[($className - 1)]['code'] !== T_NS_SEPARATOR
                || $tokens[($className - 2)]['code'] !== T_STRING
            ) {
                if ($tokens[($className - 1)]['code'] === T_COMMA
                    || ($tokens[($className - 1)]['code'] === T_NS_SEPARATOR
                    && $tokens[($className - 2)]['code'] === T_COMMA)
                ) {
                    $error = 'Expected 1 space before "%s"; 0 found';
                    $data  = array($tokens[$className]['content']);
                    $phpcsFile->addError($error, ($nextComma + 1), 'NoSpaceBeforeName', $data);
                } else {
                    if ($tokens[($className - 1)]['code'] === T_NS_SEPARATOR) {
                        $spaceBefore = strlen($tokens[($className - 2)]['content']);
                    } else {
                        $spaceBefore = strlen($tokens[($className - 1)]['content']);
                    }

                    if ($spaceBefore !== 1) {
                        $error = 'Expected 1 space before "%s"; %s found';
                        $data  = array(
                                  $tokens[$className]['content'],
                                  $spaceBefore,
                                 );
                        $phpcsFile->addError($error, $className, 'SpaceBeforeName', $data);
                    }
                }//end if
            }//end if

            if ($tokens[($className + 1)]['code'] !== T_NS_SEPARATOR
                && $tokens[($className + 1)]['code'] !== T_COMMA
            ) {
                if ($i !== ($classCount - 1)) {
                    // This is not the last class name, and the comma
                    // is not where we expect it to be.
                    if ($tokens[($className + 2)]['code'] !== T_IMPLEMENTS) {
                        $error = 'Expected 0 spaces between "%s" and comma; %s found';
                        $data  = array(
                                  $tokens[$className]['content'],
                                  strlen($tokens[($className + 1)]['content']),
                                 );
                        $phpcsFile->addError($error, $className, 'SpaceBeforeComma', $data);
                    }
                }

                $nextComma = $phpcsFile->findNext(T_COMMA, $className);
            } else {
                $nextComma = ($className + 1);
            }
        }//end foreach

    }//end processOpen()


    /**
     * Processes the closing section of a class declaration.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function processClose(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Check that the closing brace comes right after the code body.
        $closeBrace  = $tokens[$stackPtr]['scope_closer'];
        $prevContent = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBrace - 1), null, true);
        if ($prevContent !== $tokens[$stackPtr]['scope_opener']
            && $tokens[$prevContent]['line'] !== ($tokens[$closeBrace]['line'] - 1)
        ) {
            $error = 'The closing brace for the %s must go on the next line after the body';
            $data  = array($tokens[$stackPtr]['content']);
            $phpcsFile->addError($error, $closeBrace, 'CloseBraceAfterBody', $data);
        }

        // Check the closing brace is on it's own line, but allow
        // for comments like "//end class".
        $nextContent = $phpcsFile->findNext(T_COMMENT, ($closeBrace + 1), null, true);
        if ($tokens[$nextContent]['content'] !== $phpcsFile->eolChar
            && $tokens[$nextContent]['line'] === $tokens[$closeBrace]['line']
        ) {
            $type  = strtolower($tokens[$stackPtr]['content']);
            $error = 'Closing %s brace must be on a line by itself';
            $data  = array($tokens[$stackPtr]['content']);
            $phpcsFile->addError($error, $closeBrace, 'CloseBraceSameLine', $data);
        }

    }//end processClose()


}//end class

?>
<?php
/**
 * Verifies that properties are declared correctly.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_Standards_AbstractVariableSniff', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_Standards_AbstractVariableSniff not found');
}

/**
 * Verifies that properties are declared correctly.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PSR2_Sniffs_Classes_PropertyDeclarationSniff extends PHP_CodeSniffer_Standards_AbstractVariableSniff
{


    /**
     * Processes the function tokens within the class.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
     * @param int                  $stackPtr  The position where the token was found.
     *
     * @return void
     */
    protected function processMemberVar(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if ($tokens[$stackPtr]['content'][1] === '_') {
            $error = 'Property name "%s" should not be prefixed with an underscore to indicate visibility';
            $data  = array($tokens[$stackPtr]['content']);
            $phpcsFile->addWarning($error, $stackPtr, 'Underscore', $data);
        }

        // Detect multiple properties defined at the same time. Throw an error
        // for this, but also only process the first property in the list so we don't
        // repeat errors.
        $find = PHP_CodeSniffer_Tokens::$scopeModifiers;
        $find = array_merge($find, array(T_VARIABLE, T_VAR, T_SEMICOLON));
        $prev = $phpcsFile->findPrevious($find, ($stackPtr - 1));
        if ($tokens[$prev]['code'] === T_VARIABLE) {
            return;
        }

        if ($tokens[$prev]['code'] === T_VAR) {
            $error = 'The var keyword must not be used to declare a property';
            $phpcsFile->addError($error, $stackPtr, 'VarUsed');
        }

        $next = $phpcsFile->findNext(array(T_VARIABLE, T_SEMICOLON), ($stackPtr + 1));
        if ($tokens[$next]['code'] === T_VARIABLE) {
            $error = 'There must not be more than one property declared per statement';
            $phpcsFile->addError($error, $stackPtr, 'Multiple');
        }

        $modifier = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$scopeModifiers, $stackPtr);
        if (($modifier === false) || ($tokens[$modifier]['line'] !== $tokens[$stackPtr]['line'])) {
            $error = 'Visibility must be declared on property "%s"';
            $data  = array($tokens[$stackPtr]['content']);
            $phpcsFile->addError($error, $stackPtr, 'ScopeMissing', $data);
        }

    }//end processMemberVar()


    /**
     * Processes normal variables.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
     * @param int                  $stackPtr  The position where the token was found.
     *
     * @return void
     */
    protected function processVariable(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        // We don't care about normal variables.

    }//end processVariable()


    /**
     * Processes variables in double quoted strings.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
     * @param int                  $stackPtr  The position where the token was found.
     *
     * @return void
     */
    protected function processVariableInString(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        // We don't care about normal variables.

    }//end processVariableInString()


}//end class

?>
<documentation title="Namespace Declarations">
    <standard>
    <![CDATA[
    There must be one blank line after the namespace declaration.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: One blank line after the namespace declaration.">
        <![CDATA[
namespace \Foo\Bar;
<em></em>
use \Baz;
        ]]>
        </code>
        <code title="Invalid: No blank line after the namespace declaration.">
        <![CDATA[
namespace \Foo\Bar;
use \Baz;
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Namespace Declarations">
    <standard>
    <![CDATA[
    Each use declaration must contain only one namespace and must come after the first namespace declaration.  There should be one blank line after the final use statement.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: One use declaration per namespace.">
        <![CDATA[
use \Foo;
use \Bar;
        ]]>
        </code>
        <code title="Invalid: Multiple namespaces in a use declaration.">
        <![CDATA[
use <em>\Foo, \Bar</em>;
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Use statements come after first namespace.">
        <![CDATA[
namespace \Foo;

use \Bar;
        ]]>
        </code>
        <code title="Invalid: Namespace declared after use.">
        <![CDATA[
use \Bar;

namespace \Foo;
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: A single blank line after the final use statement.">
        <![CDATA[
use \Foo;
use \Bar;
<em></em>
class Baz
{
}
        ]]>
        </code>
        <code title="Invalid: No blank line after the final use statement.">
        <![CDATA[
use \Foo;
use \Bar;
class Baz
{
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Elseif Declarations">
    <standard>
    <![CDATA[
    PHP's elseif keyword should be used instead of else if.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Single word elseif keyword used.">
        <![CDATA[
if ($foo) {
    $var = 1;
} <em>elseif</em> ($bar) {
    $var = 2;
}
        ]]>
        </code>
        <code title="Invalid: Separate else and if keywords used.">
        <![CDATA[
if ($foo) {
    $var = 1;
} <em>else if</em> ($bar) {
    $var = 2;
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Switch Declarations">
    <standard>
    <![CDATA[
    Case statments should be indented 4 spaces from the switch keyword.  It should also be followed by a space.  Colons in switch declarations should not be preceded by whitespace.  Break statements should be indented 4 more spaces from the case statement.  There must be a comment when falling through from one case into the next.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Case statement indented correctly.">
        <![CDATA[
switch ($foo) {
<em>    </em>case 'bar':
        break;
}
        ]]>
        </code>
        <code title="Invalid: Case statement not indented 4 spaces.">
        <![CDATA[
switch ($foo) {
<em></em>case 'bar':
    break;
}
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Case statement followed by 1 space.">
        <![CDATA[
switch ($foo) {
    case<em> </em>'bar':
        break;
}
        ]]>
        </code>
        <code title="Invalid: Case statement not followed by 1 space.">
        <![CDATA[
switch ($foo) {
    case<em></em>'bar':
        break;
}
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Colons not prefixed by whitespace.">
        <![CDATA[
switch ($foo) {
    case 'bar'<em></em>:
        break;
    default<em></em>:
        break;
}
        ]]>
        </code>
        <code title="Invalid: Colons prefixed by whitespace.">
        <![CDATA[
switch ($foo) {
    case 'bar'<em> </em>:
        break;
    default<em> </em>:
        break;
}
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Break statement indented correctly.">
        <![CDATA[
switch ($foo) {
    case 'bar':
<em>        </em>break;
}
        ]]>
        </code>
        <code title="Invalid: Break statement not indented 4 spaces.">
        <![CDATA[
switch ($foo) {
    case 'bar':
<em>    </em>break;
}
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Comment marking intentional fall-through.">
        <![CDATA[
switch ($foo) {
    case 'bar':
    <em>// no break</em>
    default<em></em>:
        break;
}
        ]]>
        </code>
        <code title="Invalid: No comment marking intentional fall-through.">
        <![CDATA[
switch ($foo) {
    case 'bar':
    default<em></em>:
        break;
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Control Structure Spacing">
    <standard>
    <![CDATA[
    Control Structures should have 0 spaces after opening parentheses and 0 spaces before closing parentheses.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Correct spacing.">
        <![CDATA[
if (<em></em>$foo<em></em>) {
    $var = 1;
}
        ]]>
        </code>
        <code title="Invalid: Whitespace used inside the parentheses.">
        <![CDATA[
if (<em> </em>$foo<em> </em>) {
    $var = 1;
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Method Declarations">
    <standard>
    <![CDATA[
    Method names should not be prefixed with an underscore to indicate visibility.  The static keyword, when present, should come after the visibility declaration, and the final and abstract keywords should come before.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Correct method naming.">
        <![CDATA[
class Foo
{
    private function <em>bar</em>()
    {
    }
}
        ]]>
        </code>
        <code title="Invalid: An underscore prefix used to indicate visibility.">
        <![CDATA[
class Foo
{
    private function <em>_bar</em>()
    {
    }
}
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Correct ordering of method prefixes.">
        <![CDATA[
class Foo
{
    <em>final public static</em> function <em>bar</em>()
    {
    }
}
        ]]>
        </code>
        <code title="Invalid: static keyword used before visibility and final used after.">
        <![CDATA[
class Foo
{
    <em>static public final</em> function <em>bar</em>()
    {
    }
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="End File Newline">
    <standard>
    <![CDATA[
    PHP Files should end with exactly one newline.
    ]]>
    </standard>
</documentation>
<documentation title="Class Declarations">
    <standard>
    <![CDATA[
    There should be exactly 1 space between the abstract or final keyword and the class keyword and between the class keyword and the class name.  The extends and implements keywords, if present, must be on the same line as the class name.  When interfaces implemented are spread over multiple lines, there should be exactly 1 interface metioned per line indented by 1 level.  The closing brace of the class must go on the first line after the body of the class and must be on a line by itself.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Correct spacing around class keyword.">
        <![CDATA[
abstract<em> </em>class<em> </em>Foo
{
}
        ]]>
        </code>
        <code title="Invalid: 2 spaces used around class keyword.">
        <![CDATA[
abstract<em>  </em>class<em>  </em>Foo
{
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Property Declarations">
    <standard>
    <![CDATA[
    Property names should not be prefixed with an underscore to indicate visibility.  Visibility should be used to declare properties rather than the var keyword.  Only one property should be declared within a statement.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Correct property naming.">
        <![CDATA[
class Foo
{
    private $<em>bar</em>;
}
        ]]>
        </code>
        <code title="Invalid: An underscore prefix used to indicate visibility.">
        <![CDATA[
class Foo
{
    private $<em>_bar</em>;
}
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Visibility of property declared.">
        <![CDATA[
class Foo
{
    <em>private</em> $bar;
}
        ]]>
        </code>
        <code title="Invalid: Var keyword used to declare property.">
        <![CDATA[
class Foo
{
    <em>var</em> $bar;
}
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: One property declared per statement.">
        <![CDATA[
class Foo
{
    private $bar;
    private $baz;
}
        ]]>
        </code>
        <code title="Invalid: Multiple properties declared in one statement.">
        <![CDATA[
class Foo
{
    private <em>$bar, $baz</em>;
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<?php
namespace bug;

use someNS\A;
use someNS\B;
class Bug
{
    public function __construct()
    {
        $b = 1;
        $a = function () use ($b) {
            echo $b;
        };
    }
}
<?php
namespace Vendor\Package;

use FooClass;

namespace Vendor\Package;
use BarClass as Bar;

?>
<?php
/**
 * Unit test class for the UseDeclaration sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the UseDeclaration sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PSR2_Tests_Namespaces_UseDeclarationUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='')
    {
        switch ($testFile) {
        case 'UseDeclarationUnitTest.1.inc':
            // The trait test will only work in PHP versions where traits exist
            // and will throw errors in earlier versions.
            if (version_compare(PHP_VERSION, '5.4.0') < 0) {
                return array(
                        30  => 2,
                       );
            }

            return array();
        case 'UseDeclarationUnitTest.2.inc':
            return array(
                    5  => 1,
                    10 => 2,
                   );
        case 'UseDeclarationUnitTest.3.inc':
            return array(
                    5  => 1,
                   );
        default:
            return array();
        }//end switch

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the NamespaceDeclaration sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the NamespaceDeclaration sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PSR2_Tests_Namespaces_NamespaceDeclarationUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                6  => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
namespace MyProject;

use BarClass as Bar;
use My\Full\Classname as Another, My\Full\NSname;


namespace AnotherProject;

use ArrayObject;


$foo = 'bar';

?>
<?php
namespace MyProject;

use BarClass as Bar;
use My\Full\Classname as Another;


use Something;
use SomethingElse;

// Comment here.
use LastThing;

class Foo {
}

$var = new MyClass(
    function () use ($foo, $bar) {
        return true;
    }
);

class Container extends Component implements IContainer
{
    use TContainer;
}

trait HelloWorld
{
    use Hello, World;
}
<?php
if ($something) {
}
foreach ($this as $that ) {
}
while (true) {
    for ($i = 0; $i < 10; $i++) {
    }
    if ($something) {
    }

    foreach ($this as $that) {
        do {
        } while ( true );

    }
}

if ($defaultPageDesign === 0
    && $defaultCascade === TRUE
    && $defaultChildDesign === 0
) {
    $settingsUpdated = FALSE;
}

foreach ( $blah as $var ) {
    if (  $blah    ) {
    }
}

if (
    $defaultPageDesign === 0
    && $defaultCascade === TRUE
    && $defaultChildDesign === 0
) {
    $settingsUpdated = FALSE;
}
?>
<?php
switch ($expr) {
    case 0:
        echo 'First case, with a break';
        break;
    case 1:
        echo 'Second case, which falls through';
        // no break
    case 2:
    case 3:
    case 4:
        echo 'Third case, return instead of break';
        return;
    default:
        echo 'Default case';
        break;
}

switch ($expr) {
    case 0:
        echo 'First case,';

    case 1 :
        echo 'Second case';
        // no break
case 2:
    case 3:
        echo 'Third case';
    return;

    default:
        echo 'Default case';
    break;
}

switch ($foo) {
    case 'Foo': {
        echo 'foo';
        break;
        }
}

while ($i < 10) {
    switch ($foo) {
        case '1':
        case '2':
            ++$i;
            continue 2;
        case '3':
            return $i;
    }
}

switch (true) {
    case is_resource($value):
        throw new Exception('foo');
    case is_object($value):
        return 'object';
}

switch (0) {
    case 0:
        switch (1) {
            case 1:
                echo 'a';
                break;
        }
        break;
}

switch ($foo) {
    case Foo::ONE:
    case Foo::TWO:
        break;
}

switch (true) {
    case $value instanceof StdClass:
        return 1;
    case strpos('_', get_class($value)) !== false:
        break;
}

switch (true) {
    case $value instanceof StdClass:
        if ($value) {
            return null;
        }
}
?>
<?php
/**
 * Unit test class for the FunctionSpacing sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the FunctionSpacing sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PSR2_Tests_ControlStructures_ControlStructureSpacingUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                4  => 1,
                14 => 2,
                26 => 2,
                27 => 2,
                31 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the SwitchDeclaration sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the SwitchDeclaration sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PSR2_Tests_ControlStructures_SwitchDeclarationUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                20 => 1,
                23 => 1,
                26 => 1,
                29 => 1,
                33 => 1,
                37 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php

if ($something) {
} else if ($somethingElse) {
}

if ($something) {
} elseif ($somethingElse) {
}

if ($something) {
} else if ($somethingElse) {
} elseif ($another) {
} else {
}

?><?php
/**
 * Unit test class for the ElseIfDeclaration sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ElseIfDeclaration sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PSR2_Tests_ControlStructures_ElseIfDeclarationUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array();

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                4  => 1,
                12 => 1,
               );

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the MethodDeclaration sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the MethodDeclaration sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PSR2_Tests_Methods_MethodDeclarationUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                9  => 1,
                11 => 1,
                13 => 1,
                15 => 3,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                5 => 1,
               );

    }//end getWarningList()


}//end class

?>
<?php

class MyClass
{
    function _myFunction() {}
    private function myFunction() {}
    function __myFunction() {}
    public static function myFunction() {}
    static public function myFunction() {}
    final public function myFunction() {}
    public final function myFunction() {}
    abstract private function myFunction() {}
    private abstract function myFunction() {}
    final public static function myFunction() {}
    static protected final abstract function myFunction() {}
    public function _() {}
}

?>
<?php
somefunction($foo, $bar, [
    // ...
], $baz);

$app->get('/hello/{name}', function ($name) use ($app) {
    return 'Hello '.$app->escape($name);
}, array(
    '1',
    '2',
    '3',
));

somefunction($foo, $bar, [
    // ...
    ],
$baz);

somefunction(
    $foo,
    $bar,
    [
        // ...
    ],
    $baz
);


?><?php
/**
 * Unit test class for the FunctionCallSignature sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the FunctionCallSignature sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PSR2_Tests_Methods_FunctionCallSignatureUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                14 => 3,
                17 => 2,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
echo 'foo';
?>
</body>
<?php
echo 'foo';
  

     





 
<?php
echo 'foo';
<?php
echo 'foo';  <?php
echo 'foo';<?php
echo 'foo';

<?php
echo 'foo';
?>
</body>
<?php
echo 'bar';
<?php
/**
 * Unit test class for the EndFileNewline sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the EndFileNewline sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PSR2_Tests_Files_EndFileNewlineUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='')
    {
        switch ($testFile) {
        case 'EndFileNewlineUnitTest.1.inc':
        case 'EndFileNewlineUnitTest.3.inc':
        case 'EndFileNewlineUnitTest.6.inc':
        case 'EndFileNewlineUnitTest.7.inc':
            return array(
                    2 => 1,
                   );
            break;
        default:
            return array();
            break;
        }//end switch

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getWarningList($testFile='')
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the ClassDeclaration sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ClassDeclaration sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PSR2_Tests_Classes_ClassDeclarationUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                2  => 1,
                7  => 3,
                12 => 1,
                13 => 1,
                17 => 1,
                19 => 2,
                20 => 1,
                21 => 1,
                22 => 1,
                25 => 1,
                27 => 1,
                28 => 1,
                29 => 1,
                34 => 1,
                35 => 2,
                44 => 1,
                45 => 1,
                63 => 1,
                95 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
class MyClass
{
    public $var = null;
    protected $var = null;
    private $var = null;
    $var = null;

    var $var = null;
    public var $var = null;

    public $_var = null;
    protected $_var = null;
    private $_var = null;

    public $foo, $bar, $var = null;
    public $foo,
           $bar,
           $var = null;
}

class foo
{
    const bar = <<<BAZ
qux
BAZ;
}
?><?php
class ClassName extends ParentClass implements \ArrayAccess,  \Countable
{
    // constants, properties, methods
}

class ClassName extends ParentClass,AnotherParentClass implements \ArrayAccess,\Countable {
    // constants, properties, methods
}

class ClassName
extends ParentClass
implements \ArrayAccess, \Countable
{
    // constants, properties, methods
    
}

class ClassName extends  ParentClass  implements
   \ArrayAccess,
        \Foo\Bar\Countable,
    \Serializable {
    // constants, properties, methods

}

class ClassName extends ParentClass  implements \ArrayAccess,
    \Countable,
    \Serializable
{
    // constants, properties, methods
}

class ClassName extends ParentClass  implements
    \ArrayAccess, \Countable, \Foo\Serializable
{
    // constants, properties, methods
}

// Different indent
if ($foo) {
    class ClassName extends ParentClass implements
        \ArrayAccess,
    \Countable,
            \Serializable
    {
        // constants, properties, methods
    }
}

class Foo extends \Foo\Bar\Object
{
}

class ClassName extends ParentClass implements
    \Foo\Bar\Countable,
    \Serializable
{
    // constants, properties, methods
}

class ClassName extends ParentClass implements
    \Foo\Bar\Countable ,
    \Serializable
{
    // constants, properties, methods
}

class Test
{
    public function test() {
        if (1) 1;
        1 ? (1 ? 1 : 1) : 1;
    }
}

class MyClass
{
}

class MyClass
{

}

class MyClass
{
    // Foo.
}

class MyClass
{
    // Foo.

}

abstract class Test implements
    TestInterface1,
    TestInterface2
{
}

?>
<?php
/**
 * Unit test class for the PropertyDeclaration sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the PropertyDeclaration sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PSR2_Tests_Classes_PropertyDeclarationUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                7  => 1,
                9  => 2,
                10 => 1,
                16 => 1,
                17 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                12 => 1,
                13 => 1,
                14 => 1,
               );

    }//end getWarningList()


}//end class

?>
<?xml version="1.0"?>
<ruleset name="PSR2">
 <description>The PSR-2 coding standard.</description>

 <!-- 2. General -->

 <!-- 2.1 Basic Coding Standard -->

 <!-- Include the whole PSR-1 standard -->
 <rule ref="PSR1"/>

 <!-- 2.2 Files -->

 <!-- All PHP files MUST use the Unix LF (linefeed) line ending. -->
 <rule ref="Generic.Files.LineEndings">
  <properties>
   <property name="eolChar" value="\n"/>
  </properties>
 </rule>

 <!-- All PHP files MUST end with a single blank line. -->
 <!-- checked in Files/EndFileNewlineSniff -->

 <!-- The closing ?> tag MUST be omitted from files containing only PHP. -->
 <rule ref="Zend.Files.ClosingTag"/>

 <!-- 2.3 Lines -->

 <!-- The soft limit on line length MUST be 120 characters; automated style checkers MUST warn but MUST NOT error at the soft limit. -->
 <rule ref="Generic.Files.LineLength">
  <properties>
   <property name="lineLimit" value="120"/>
   <property name="absoluteLineLimit" value="0"/>
  </properties>
 </rule>

 <!-- There MUST NOT be trailing whitespace at the end of non-blank lines. -->
 <rule ref="Squiz.WhiteSpace.SuperfluousWhitespace">
  <properties>
   <property name="ignoreBlankLines" value="true"/>
   </properties>
 </rule>
 <rule ref="Squiz.WhiteSpace.SuperfluousWhitespace.StartFile">
  <severity>0</severity>
 </rule>
 <rule ref="Squiz.WhiteSpace.SuperfluousWhitespace.EndFile">
  <severity>0</severity>
 </rule>
 <rule ref="Squiz.WhiteSpace.SuperfluousWhitespace.EmptyLines">
  <severity>0</severity>
 </rule>

 <!-- There MUST NOT be more than one statement per line. -->
 <rule ref="Generic.Formatting.DisallowMultipleStatements"/>

 <!-- 2.4 Indenting -->

 <!-- Code MUST use an indent of 4 spaces, and MUST NOT use tabs for indenting. -->
 <rule ref="Generic.WhiteSpace.ScopeIndent">
  <properties>
   <property name="ignoreIndentationTokens" type="array" value="T_COMMENT,T_DOC_COMMENT"/>
  </properties>
 </rule>
 <rule ref="Generic.WhiteSpace.DisallowTabIndent"/>

 <!-- 2.5 Keywords and True/False/Null -->

 <!-- PHP keywords MUST be in lower case. -->
 <rule ref="Generic.PHP.LowerCaseKeyword"/>

 <!-- The PHP constants true, false, and null MUST be in lower case. -->
 <rule ref="Generic.PHP.LowerCaseConstant"/>

 <!-- 3. Namespace and Use Declarations -->

 <!-- When present, there MUST be one blank line after the namespace declaration. -->
 <!-- checked in Namespaces/NamespaceDeclarationSniff -->

 <!-- When present, all use declarations MUST go after the namespace declaration.
      There MUST be one use keyword per declaration.
      There MUST be one blank line after the use block. -->
 <!-- checked in Namespaces/UseDeclarationSniff -->

 <!-- 4. Classes, Properties, and Methods -->

 <!-- 4.1. Extends and Implements -->

 <!-- The extends and implements keywords MUST be declared on the same line as the class name.
      The opening brace for the class go MUST go on its own line; the closing brace for the class MUST go on the next line after the body.
      Lists of implements MAY be split across multiple lines, where each subsequent line is indented once. When doing so, the first item in the list MUST be on the next line, and there MUST be only one interface per line. -->
 <!-- checked in Classes/ClassDeclarationSniff -->

 <!-- 4.2. Properties -->

 <!-- Visibility MUST be declared on all properties.
      The var keyword MUST NOT be used to declare a property.
      There MUST NOT be more than one property declared per statement.
      Property names SHOULD NOT be prefixed with a single underscore to indicate protected or private visibility. -->
 <!-- checked in Classes/PropertyDeclarationSniff -->

 <!-- 4.3 Methods -->

 <!-- Visibility MUST be declared on all methods. -->
 <rule ref="Squiz.Scope.MethodScope"/>
 <rule ref="Squiz.WhiteSpace.ScopeKeywordSpacing"/>

 <!-- Method names SHOULD NOT be prefixed with a single underscore to indicate protected or private visibility. -->
 <!-- checked in Methods/MethodDeclarationSniff -->

 <!-- Method names MUST NOT be declared with a space after the method name. The opening brace MUST go on its own line, and the closing brace MUST go on the next line following the body. There MUST NOT be a space after the opening parenthesis, and there MUST NOT be a space before the closing parenthesis. -->
 <rule ref="Squiz.Functions.FunctionDeclaration"/>
 <rule ref="Squiz.Functions.LowercaseFunctionKeywords"/>

 <!-- 4.4 Method Arguments -->

 <!-- In the argument list, there MUST NOT be a space before each comma, and there MUST be one space after each comma. -->
 <rule ref="Squiz.Functions.FunctionDeclarationArgumentSpacing">
  <properties>
   <property name="equalsSpacing" value="1"/>
  </properties>
 </rule>
 <rule ref="Squiz.Functions.FunctionDeclarationArgumentSpacing.SpacingAfterHint">
  <severity>0</severity>
 </rule>

 <!-- Method arguments with default values MUST go at the end of the argument list. -->
 <rule ref="PEAR.Functions.ValidDefaultValue"/>

 <!-- Argument lists MAY be split across multiple lines, where each subsequent line is indented once. When doing so, the first item in the list MUST be on the next line, and there MUST be only one argument per line. When the argument list is split across multiple lines, the closing parenthesis and opening brace MUST be placed together on their own line with one space between them. -->
 <rule ref="Squiz.Functions.MultiLineFunctionDeclaration"/>

 <!-- 4.5 abstract, final, and static -->

 <!-- When present, the abstract and final declarations MUST precede the visibility declaration.
      When present, the static declaration MUST come after the visibility declaration. -->
 <!-- checked in Methods/MethodDeclarationSniff -->

 <!-- 4.6 Method and Function Calls -->

 <!-- When making a method or function call, there MUST NOT be a space between the method or function name and the opening parenthesis, there MUST NOT be a space after the opening parenthesis, and there MUST NOT be a space before the closing parenthesis. In the argument list, there MUST NOT be a space before each comma, and there MUST be one space after each comma.
 Argument lists MAY be split across multiple lines, where each subsequent line is indented once. When doing so, the first item in the list MUST be on the next line, and there MUST be only one argument per line. -->
 <rule ref="Generic.Functions.FunctionCallArgumentSpacing"/>
 <rule ref="PSR2.Methods.FunctionCallSignature.SpaceAfterCloseBracket">
  <severity>0</severity>
 </rule>

 <!-- 5. Control Structures -->

 <!-- The general style rules for control structures are as follows:
 There MUST be one space after the control structure keyword
 There MUST NOT be a space after the opening parenthesis
 There MUST NOT be a space before the closing parenthesis
 There MUST be one space between the closing parenthesis and the opening brace
 The structure body MUST be indented once
 The closing brace MUST be on the next line after the body -->
 <rule ref="Squiz.ControlStructures.ControlSignature">
  <properties>
   <property name="ignoreComments" value="true"/>
  </properties>
 </rule>
 <rule ref="Squiz.WhiteSpace.ScopeClosingBrace"/>
 <rule ref="Squiz.ControlStructures.ForEachLoopDeclaration"/>
 <rule ref="Squiz.ControlStructures.ForLoopDeclaration"/>
 <rule ref="Squiz.ControlStructures.LowercaseDeclaration"/>
 <!-- checked in ControlStructures/ControlStructureSpacingSniff -->

 <!-- The body of each structure MUST be enclosed by braces. This standardizes how the structures look, and reduces the likelihood of introducing errors as new lines get added to the body. -->
 <rule ref="Generic.ControlStructures.InlineControlStructure"/>

 <!-- 5.1. if, elseif, else -->

 <!-- The keyword elseif SHOULD be used instead of else if so that all control keywords look like single words. -->
 <!-- checked in ControlStructures/ElseIfDeclarationSniff -->

 <!-- 5.2. switch, case -->

 <!-- The case statement MUST be indented once from switch, and the break keyword (or other terminating keyword) MUST be indented at the same level as the case body. There MUST be a comment such as // no break when fall-through is intentional in a non-empty case body. -->
 <!-- checked in ControlStructures/SwitchDeclarationSniff -->

 <!-- 6. Closures -->

 <!-- Closures MUST be declared with a space after the function keyword, and a space before and after the use keyword.
 The opening brace MUST go on the same line, and the closing brace MUST go on the next line following the body.
 There MUST NOT be a space after the opening parenthesis of the argument list or variable list, and there MUST NOT be a space before the closing parenthesis of the argument list or variable list.
 In the argument list and variable list, there MUST NOT be a space before each comma, and there MUST be one space after each comma.
 Closure arguments with default values MUST go at the end of the argument list.
 Argument lists and variable lists MAY be split across multiple lines, where each subsequent line is indented once. When doing so, the first item in the list MUST be on the next line, and there MUST be only one argument or variable per line.
 When the ending list (whether or arguments or variables) is split across multiple lines, the closing parenthesis and opening brace MUST be placed together on their own line with one space between them. -->
 <!-- checked in Squiz.Functions.MultiLineFunctionDeclaration -->
</ruleset>
<?php
/**
 * PSR1_Sniffs_Methods_CamelCapsMethodNameSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_Standards_AbstractScopeSniff', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_Standards_AbstractScopeSniff not found');
}

/**
 * PSR1_Sniffs_Methods_CamelCapsMethodNameSniff.
 *
 * Ensures method names are defined using camel case.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PSR1_Sniffs_Methods_CamelCapsMethodNameSniff extends PHP_CodeSniffer_Standards_AbstractScopeSniff
{

    /**
     * Constructs a PSR1_Sniffs_Methods_CamelCapsMethodNameSniff.
     */
    public function __construct()
    {
        parent::__construct(array(T_CLASS, T_INTERFACE, T_TRAIT), array(T_FUNCTION), true);

    }//end __construct()


    /**
     * Processes the tokens within the scope.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being processed.
     * @param int                  $stackPtr  The position where this token was
     *                                        found.
     * @param int                  $currScope The position of the current scope.
     *
     * @return void
     */
    protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope)
    {
        $methodName = $phpcsFile->getDeclarationName($stackPtr);
        if ($methodName === null) {
            // Ignore closures.
            return;
        }

        $testName = ltrim($methodName, '_');
        if (PHP_CodeSniffer::isCamelCaps($testName, false, true, false) === false) {
            $error     = 'Method name "%s" is not in camel caps format';
            $className = $phpcsFile->getDeclarationName($currScope);
            $errorData = array($className.'::'.$methodName);
            $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData);
        }

    }//end processTokenWithinScope()


    /**
     * Processes the tokens outside the scope.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being processed.
     * @param int                  $stackPtr  The position where this token was
     *                                        found.
     *
     * @return void
     */
    protected function processTokenOutsideScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {


    }//end processTokenOutsideScope()


}//end class

?>
<?php
/**
 * PSR1_Sniffs_Files_SideEffectsSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * PSR1_Sniffs_Files_SideEffectsSniff.
 *
 * Ensures a file declare new symbols and causes no other side effects, or executes
 * logic with side effects, but not both.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PSR1_Sniffs_Files_SideEffectsSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_OPEN_TAG);

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the token stack.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        // We are only interested if this is the first open tag.
        if ($stackPtr !== 0) {
            if ($phpcsFile->findPrevious(T_OPEN_TAG, ($stackPtr - 1)) !== false) {
                return;
            }
        }

        $tokens = $phpcsFile->getTokens();
        $result = $this->_searchForConflict($phpcsFile, 0, ($phpcsFile->numTokens - 1), $tokens);

        if ($result['symbol'] !== null && $result['effect'] !== null) {
            $error = 'A file should declare new symbols (classes, functions, constants, etc.) and cause no other side effects, or it should execute logic with side effects, but should not do both. The first symbol is defined on line %s and the first side effect is on line %s.';
            $data  = array(
                      $tokens[$result['symbol']]['line'],
                      $tokens[$result['effect']]['line'],
                     );
            $phpcsFile->addWarning($error, 0, 'FoundWithSymbols', $data);
        }

    }//end process()


    /**
     * Searches for symbol declarations and side effects.
     *
     * Returns the positions of both the first symbol declared and the first
     * side effect in the file. A NULL value for either indicates nothing was
     * found.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $start     The token to start searching from.
     * @param int                  $end       The token to search to.
     * @param array                $tokens    The stack of tokens that make up
     *                                        the file.
     *
     * @return array
     */
    private function _searchForConflict(PHP_CodeSniffer_File $phpcsFile, $start, $end, $tokens)
    {
        $symbols = array(
                    T_CLASS,
                    T_INTERFACE,
                    T_TRAIT,
                    T_FUNCTION,
                   );

        $conditions = array(
                       T_IF,
                       T_ELSE,
                       T_ELSEIF,
                      );

        $firstSymbol = null;
        $firstEffect = null;
        for ($i = $start; $i <= $end; $i++) {
            // Ignore whitespace and comments.
            if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === true) {
                continue;
            }

            // Ignore PHP tags.
            if ($tokens[$i]['code'] === T_OPEN_TAG
                || $tokens[$i]['code'] === T_CLOSE_TAG
            ) {
                continue;
            }

            // Ignore entire namespace, const and use statements.
            if ($tokens[$i]['code'] === T_NAMESPACE) {
                $next = $phpcsFile->findNext(array(T_SEMICOLON, T_OPEN_CURLY_BRACKET), ($i + 1));
                if ($next === false) {
                    $next = $i++;
                } else if ($tokens[$next]['code'] === T_OPEN_CURLY_BRACKET) {
                    $next = $tokens[$next]['bracket_closer'];
                }

                $i = $next;
                continue;
            } else if ($tokens[$i]['code'] === T_USE
                || $tokens[$i]['code'] === T_CONST
            ) {
                $semicolon = $phpcsFile->findNext(T_SEMICOLON, ($i + 1));
                if ($semicolon !== false) {
                    $i = $semicolon;
                }

                continue;
            }

            // Ignore function/class prefixes.
            if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$methodPrefixes) === true) {
                continue;
            }

            // Detect and skip over symbols.
            if (in_array($tokens[$i]['code'], $symbols) === true
                && isset($tokens[$i]['scope_closer']) === true
            ) {
                if ($firstSymbol === null) {
                    $firstSymbol = $i;
                }

                $i = $tokens[$i]['scope_closer'];
                continue;
            } else if ($tokens[$i]['code'] === T_STRING
                && strtolower($tokens[$i]['content']) === 'define'
            ) {
                if ($firstSymbol === null) {
                    $firstSymbol = $i;
                }

                $i = $phpcsFile->findNext(T_SEMICOLON, ($i + 1));
                continue;
            }

            // Conditional statements are allowed in symbol files as long as the
            // contents is only a symbol definition. So don't count these as effects
            // in this case.
            if (in_array($tokens[$i]['code'], $conditions) === true) {
                if (isset($tokens[$i]['scope_opener']) === false) {
                    // Probably an "else if", so just ignore.
                    continue;
                }

                $result = $this->_searchForConflict(
                    $phpcsFile,
                    ($tokens[$i]['scope_opener'] + 1),
                    ($tokens[$i]['scope_closer'] - 1),
                    $tokens
                );

                if ($result['symbol'] !== null) {
                    if ($firstSymbol === null) {
                        $firstSymbol = $result['symbol'];
                    }

                    if ($result['effect'] !== null) {
                        // Found a conflict.
                        $firstEffect = $result['effect'];
                        break;
                    }
                }

                if ($firstEffect === null) {
                    $firstEffect = $result['effect'];
                }

                $i = $tokens[$i]['scope_closer'];
                continue;
            }//end if

            if ($firstEffect === null) {
                $firstEffect = $i;
            }

            if ($firstSymbol !== null) {
                // We have a conflict we have to report, so no point continuing.
                break;
            }
        }//end for

        return array(
                'symbol' => $firstSymbol,
                'effect' => $firstEffect,
               );

    }//end _searchForConflict()


}//end class

?>
<?php
/**
 * Class Declaration Test.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Class Declaration Test.
 *
 * Checks the declaration of the class is correct.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PSR1_Sniffs_Classes_ClassDeclarationSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_CLASS,
                T_INTERFACE,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param integer              $stackPtr  The position of the current token in
     *                                        the token stack.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens    = $phpcsFile->getTokens();
        $nextClass = $phpcsFile->findNext(array(T_CLASS, T_INTERFACE), ($stackPtr + 1));
        if ($nextClass !== false) {
            $error = 'Each class must be in a file by itself';
            $phpcsFile->addError($error, $nextClass, 'MultipleClasses');
        }

        if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
            $namespace = $phpcsFile->findPrevious(T_NAMESPACE, ($stackPtr - 1));
            if ($namespace === false) {
                $error = 'Each class must be in a namespace of at least one level (a top-level vendor name)';
                $phpcsFile->addError($error, $stackPtr, 'MissingNamespace');
            }
        }

    }//end process()


}//end class

?>
<documentation title="Side Effects">
    <standard>
    <![CDATA[
    A php file should either contain declarations with no side effects, or should just have logic (including side effects) with no declarations.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: A class defined in a file by itself.">
        <![CDATA[
<?php
class Foo
{
}
        ]]>
        </code>
        <code title="Invalid: A class defined in a file with other code.">
        <![CDATA[
<?php
class Foo
{
}

<em>echo "Class Foo loaded."</em>
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Class Declaration">
    <standard>
    <![CDATA[
    Each class must be in a file by itself and must be under a namespace (a top-level vendor name).
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: One class in a file.">
        <![CDATA[
<?php
namespace Foo;

<em>class Bar</em> {
}
        ]]>
        </code>
        <code title="Invalid: Multiple classes in a single file.">
        <![CDATA[
<?php
namespace Foo;

<em>class Bar</em> {
}

<em>class Baz</em> {
}
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: A vendor-level namespace is used.">
        <![CDATA[
<?php
<em>namespace Foo;</em>

class Bar {
}
        ]]>
        </code>
        <code title="Invalid: No namespace used in file.">
        <![CDATA[
<?php
class Bar {
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<?php
/**
 * Unit test class for the CamelCapsMethodName sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the CamelCapsMethodName sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PSR1_Tests_Methods_CamelCapsMethodNameUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                6  => 1,
                7  => 1,
                11 => 1,
                12 => 1,
                13 => 1,
                17 => 1,
                21 => 1,
                25 => 1,
                45 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php

abstract class My_Class {

    public function __construct() {}
    public function My_Class() {}
    public function _My_Class() {}

    public function getSomeValue() {}
    public function parseMyDSN() {}
    public function get_some_value() {}
    public function GetSomeValue() {}
    public function getSomeValue_Again() {}

    protected function getSomeValue() {}
    protected function parseMyDSN() {}
    protected function get_some_value() {}

    private function getSomeValue() {}
    private function parseMyDSN() {}
    private function get_some_value() {}

    function getSomeValue() {}
    function parseMyDSN() {}
    function get_some_value() {}

}//end class

function getSomeValue() {}
function parseMyDSN() {}
function get_some_value() {}

class Closure_Test {
    function test() {
        $foo = function() { echo 'foo'; };
    }
}

trait Foo
{
    function __call() {}
}

class Magic_Case_Test {
    function __Construct() {}
    function __isSet() {}
    function __tostring() {}
}
function __autoLoad() {}

class Foo extends \SoapClient
{
    public function __soapCall(
        $functionName,
        $arguments,
        $options = array(),
        $inputHeaders = null,
        &$outputHeaders = array()
    ) {
        // body
    }
}
?>
<?php
define("MAXSIZE", 100);
$defined = true;
if (defined('MINSIZE') === false) {
    $defined = false;
}
<?php
namespace Vendor\Model;

const CONSTANT1 = 1;
const CONSTANT2 = 2;

use Something;
use SomethingElse;

define("MAXSIZE", 100);
if (defined('MINSIZE') === false) {
    define("MINSIZE", 10);
}

// Class comment.
final class Foo
{
    public $myvar = 'foo';

    // Function comment.
    function Bar() {
        echo 'hi';
    }
}

function MyFunction() {
    echo 'hi';
}

if (!function_exists('YourFunction')) {
    // Define a function.
    function YourFunction() {
        echo 'hi';
    }
}

if (!class_exists('MyClass')) {
    // Define a class.
    class MyClass
    {
        function SomeFunction() {}
    }
} else if (!interface_exists('MyInterface')) {
    interface MyInterface {}
} elseif (!interface_exists('MyInterface')) {
    interface MyInterface {}
} else {
    interface MyInterface {}
}

if (!interface_exists('MyInterface')) {
    // Define an interface.
    interface MyInterface {}
}

namespace {
    class A {}
}

?>
<html>
<?php
function printHead() {
    echo '<head></head>';
}

printHead();
?>
<body></body>
</html>
<?php
include 'Somefile';

const CONSTANT1 = 1;
const CONSTANT2 = 2;

if ($something) {
    echo 'hi';
}

$var = myFunction();
print_r($var);
<?php
/**
 * Unit test class for the SideEffects sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the SideEffects sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PSR1_Tests_Files_SideEffectsUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='')
    {
        return array();

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getWarningList($testFile='')
    {
        switch ($testFile) {
        case 'SideEffectsUnitTest.3.inc':
        case 'SideEffectsUnitTest.4.inc':
            return array(
                    1 => 1,
                   );
        default:
            return array();
        }//end switch

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the ClassDeclaration sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ClassDeclaration sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PSR1_Tests_Classes_ClassDeclarationUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
            return array(
                    2 => 1,
                    3 => 2,
                   );
        } else {
            return array(
                    3 => 1,
                   );
        }

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
class Foo {}
class Bar {}
?>
<?xml version="1.0"?>
<ruleset name="PSR1">
 <description>The PSR1 coding standard.</description>

 <!-- 2. Files -->

 <!-- 2.1. PHP Tags -->

 <!-- PHP code MUST use the long <?php ?> tags or the short-echo <?= ?> tags; it MUST NOT use the other tag variations. -->
 <rule ref="Generic.PHP.DisallowShortOpenTag.EchoFound">
  <severity>0</severity>
 </rule>

 <!-- 2.2. Character Encoding -->

 <!-- PHP code MUST use only UTF-8 without BOM. -->
 <rule ref="Generic.Files.ByteOrderMark"/>

 <!-- 2.3. Side Effects -->

 <!-- A file SHOULD declare new symbols (classes, functions, constants, etc.) and cause no other side effects, or it SHOULD execute logic with side effects, but SHOULD NOT do both. -->
 <!-- checked in Files/SideEffectsSniff -->

 <!-- 3. Namespace and Class Names -->

 <!-- Namespaces and classes MUST follow PSR-0.
      This means each class is in a file by itself, and is in a namespace of at least one level: a top-level vendor name. -->
 <!-- checked in Classes/ClassDeclarationSniff -->

 <!-- Class names MUST be declared in StudlyCaps. -->
 <rule ref="Squiz.Classes.ValidClassName"/>

 <!-- 4. Class Constants, Properties, and Methods -->

 <!-- 4.1. Constants -->

 <!-- Class constants MUST be declared in all upper case with underscore separators. -->
 <rule ref="Generic.NamingConventions.UpperCaseConstantName"/>

 <!-- 4.3. Methods -->

 <!-- Method names MUST be declared in camelCase(). -->
 <!-- checked in Methods/CamelCaseMethodNameSniff -->

</ruleset>
<?php
/**
 * Generic_Sniffs_Debug_JSHintSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Alexander Wei§ <aweisswa@gmx.de>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_Debug_JSHintSniff.
 *
 * Runs jshint.js on the file.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Alexander Wei§ <aweisswa@gmx.de>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_Debug_JSHintSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('JS');


    /**
     * Returns the token types that this sniff is interested in.
     *
     * @return array(int)
     */
    public function register()
    {
        return array(T_OPEN_TAG);

    }//end register()


    /**
     * Processes the tokens that this sniff is interested in.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        the token was found.
     *
     * @return void
     * @throws PHP_CodeSniffer_Exception If jshint.js could not be run
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $fileName = $phpcsFile->getFilename();

        $rhinoPath  = PHP_CodeSniffer::getConfigData('rhino_path');
        $jshintPath = PHP_CodeSniffer::getConfigData('jshint_path');
        if ($rhinoPath === null || $jshintPath === null) {
            return;
        }

        $cmd = "$rhinoPath \"$jshintPath\" \"$fileName\"";
        $msg = exec($cmd, $output, $retval);

        if (is_array($output) === true) {
            $tokens = $phpcsFile->getTokens();

            foreach ($output as $finding) {
                $matches    = array();
                $numMatches = preg_match('/^(.+)\(.+:([0-9]+).*:[0-9]+\)$/', $finding, $matches);
                if ($numMatches === 0) {
                    continue;
                }

                $line    = (int) $matches[2];
                $message = 'jshint says: '.trim($matches[1]);

                // Find the token at the start of the line.
                $lineToken = null;
                foreach ($tokens as $ptr => $info) {
                    if ($info['line'] === $line) {
                        $lineToken = $ptr;
                        break;
                    }
                }

                if ($lineToken !== null) {
                    $phpcsFile->addWarning($message, $lineToken, 'ExternalTool');
                }
            }//end foreach
        }//end if

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_Debug_CSSLintSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Roman Levishchenko <index.0h@gmail.com>
 * @copyright 2013 Roman Levishchenko
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_Debug_CSSLintSniff.
 *
 * Runs csslint on the file.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Roman Levishchenko <index.0h@gmail.com>
 * @copyright 2013 Roman Levishchenko
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_Debug_CSSLintSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('CSS');


    /**
     * Returns the token types that this sniff is interested in.
     *
     * @return array(int)
     */
    public function register()
    {
        return array(T_OPEN_TAG);

    }//end register()


    /**
     * Processes the tokens that this sniff is interested in.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        the token was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $fileName = $phpcsFile->getFilename();

        $csslintPath = PHP_CodeSniffer::getConfigData('csslint_path');
        if ($csslintPath === null) {
            return;
        }

        $cmd = $csslintPath.' '.escapeshellarg($fileName);
        exec($cmd, $output, $retval);

        if (is_array($output) === false) {
            return;
        }

        $tokens = $phpcsFile->getTokens();
        $count  = count($output);

        for ($i = 0; $i < $count; $i++) {
            $matches    = array();
            $numMatches = preg_match(
                '/(error|warning) at line (\d+)/',
                $output[$i],
                $matches
            );

            if ($numMatches === 0) {
                continue;
            }

            $line    = (int) $matches[2];
            $message = 'csslint says: '.$output[($i + 1)];
            // 1-st line is message with error line and error code.
            // 2-nd error message.
            // 3-d wrong line in file.
            // 4-th empty line.
            $i += 4;

            $lineToken = null;
            foreach ($tokens as $ptr => $info) {
                if ($info['line'] === $line) {
                    $lineToken = $ptr;
                    break;
                }
            }

            if ($lineToken !== null) {
                $phpcsFile->addWarning($message, $lineToken, 'ExternalTool');
            }
        }//end for

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_Debug_ClosureLinterSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_Debug_ClosureLinterSniff.
 *
 * Runs gjslint on the file.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_Debug_ClosureLinterSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of error codes that should show errors.
     *
     * All other error codes will show warnings.
     *
     * @var int
     */
    public $errorCodes = array();

    /**
     * A list of error codes to ignore.
     *
     * @var int
     */
    public $ignoreCodes = array();

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('JS');


    /**
     * Returns the token types that this sniff is interested in.
     *
     * @return array(int)
     */
    public function register()
    {
        return array(T_OPEN_TAG);

    }//end register()


    /**
     * Processes the tokens that this sniff is interested in.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        the token was found.
     *
     * @return void
     * @throws PHP_CodeSniffer_Exception If jslint.js could not be run
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $fileName = $phpcsFile->getFilename();

        $lintPath = PHP_CodeSniffer::getConfigData('gjslint_path');
        if ($lintPath === null) {
            return;
        }

        $cmd = "$lintPath --nosummary --notime --unix_mode \"$fileName\"";
        $msg = exec($cmd, $output, $retval);

        if (is_array($output) === false) {
            return;
        }

        $tokens = $phpcsFile->getTokens();

        foreach ($output as $finding) {
            $matches    = array();
            $numMatches = preg_match('/^(.*):([0-9]+):\(.*?([0-9]+)\)(.*)$/', $finding, $matches);
            if ($numMatches === 0) {
                continue;
            }

            // Skip error codes we are ignoring.
            $code = $matches[3];
            if (in_array($code, $this->ignoreCodes) === true) {
                continue;
            }

            $line  = (int) $matches[2];
            $error = trim($matches[4]);

            // Find the token at the start of the line.
            $lineToken = null;
            foreach ($tokens as $ptr => $info) {
                if ($info['line'] === $line) {
                    $lineToken = $ptr;
                    break;
                }
            }

            if ($lineToken !== null) {
                $message = 'gjslint says: (%s) %s';
                $data    = array(
                            $code,
                            $error,
                           );
                if (in_array($code, $this->errorCodes) === true) {
                    $phpcsFile->addError($message, $lineToken, 'ExternalToolError', $data);
                } else {
                    $phpcsFile->addWarning($message, $lineToken, 'ExternalTool', $data);
                }
            }
        }//end foreach

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_VersionControl_SubversionPropertiesSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Jack Bates <ms419@freezone.co.uk>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_VersionControl_SubversionPropertiesSniff.
 *
 * Tests that the correct Subversion properties are set.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Jack Bates <ms419@freezone.co.uk>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_VersionControl_SubversionPropertiesSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * The Subversion properties that should be set.
     *
     * Key of array is the SVN property and the value is the
     * exact value the property should have or NULL if the
     * property should just be set but the value is not fixed.
     *
     * @var array
     */
    protected $properties = array(
                             'svn:keywords'  => 'Author Id Revision',
                             'svn:eol-style' => 'native',
                            );


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_OPEN_TAG);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Make sure this is the first PHP open tag so we don't process the
        // same file twice.
        $prevOpenTag = $phpcsFile->findPrevious(T_OPEN_TAG, ($stackPtr - 1));
        if ($prevOpenTag !== false) {
            return;
        }

        $path       = $phpcsFile->getFileName();
        $properties = $this->getProperties($path);
        if ($properties === null) {
            // Not under version control.
            return;
        }

        $allProperties = $properties + $this->properties;
        foreach ($allProperties as $key => $value) {
            if (isset($properties[$key]) === true
                && isset($this->properties[$key]) === false
            ) {
                $error = 'Unexpected Subversion property "%s" = "%s"';
                $data  = array(
                          $key,
                          $properties[$key],
                         );
                $phpcsFile->addError($error, $stackPtr, 'Unexpected', $data);
                continue;
            }

            if (isset($properties[$key]) === false
                && isset($this->properties[$key]) === true
            ) {
                $error = 'Missing Subversion property "%s" = "%s"';
                $data  = array(
                          $key,
                          $this->properties[$key],
                         );
                $phpcsFile->addError($error, $stackPtr, 'Missing', $data);
                continue;
            }

            if ($properties[$key] !== null
                && $properties[$key] !== $this->properties[$key]
            ) {
                $error = 'Subversion property "%s" = "%s" does not match "%s"';
                $data  = array(
                          $key,
                          $properties[$key],
                          $this->properties[$key],
                         );
                $phpcsFile->addError($error, $stackPtr, 'NoMatch', $data);
            }
        }//end foreach

    }//end process()


    /**
     * Returns the Subversion properties which are actually set on a path.
     *
     * Returns NULL if the file is not under version control.
     *
     * @param string $path The path to return Subversion properties on.
     *
     * @return array
     * @throws PHP_CodeSniffer_Exception If Subversion properties file could
     *                                   not be opened.
     */
    protected function getProperties($path)
    {
        $properties = array();

        $paths   = array();
        $paths[] = dirname($path).'/.svn/props/'.basename($path).'.svn-work';
        $paths[] = dirname($path).'/.svn/prop-base/'.basename($path).'.svn-base';

        $foundPath = false;
        foreach ($paths as $path) {
            if (file_exists($path) === true) {
                $foundPath = true;

                $handle = fopen($path, 'r');
                if ($handle === false) {
                    $error = 'Error opening file; could not get Subversion properties';
                    throw new PHP_CodeSniffer_Exception($error);
                }

                while (feof($handle) === false) {
                    // Read a key length line. Might be END, though.
                    $buffer = trim(fgets($handle));

                    // Check for the end of the hash.
                    if ($buffer === 'END') {
                        break;
                    }

                    // Now read that much into a buffer.
                    $key = fread($handle, substr($buffer, 2));

                    // Suck up extra newline after key data.
                    fgetc($handle);

                    // Read a value length line.
                    $buffer = trim(fgets($handle));

                    // Now read that much into a buffer.
                    $length = substr($buffer, 2);
                    if ($length === '0') {
                        // Length of value is ZERO characters, so
                        // value is actually empty.
                        $value = '';
                    } else {
                        $value = fread($handle, $length);
                    }

                    // Suck up extra newline after value data.
                    fgetc($handle);

                    $properties[$key] = $value;
                }//end while

                fclose($handle);
            }//end if
        }//end foreach

        if ($foundPath === false) {
            return null;
        }

        return $properties;

    }//end getProperties()


}//end class

?>
<?php
/**
 * This file is part of the CodeAnalysis addon for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Detects unconditional if- and elseif-statements.
 * 
 * This rule is based on the PMD rule catalog. The Unconditional If Statement
 * sniff detects statement conditions that are only set to one of the constant
 * values <b>true</b> or <b>false</b>
 *
 * <code>
 * class Foo
 * {
 *     public function close()
 *     {
 *         if (true)
 *         {
 *             // ...
 *         }
 *     }
 * }
 * </code>
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_CodeAnalysis_UnconditionalIfStatementSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Registers the tokens that this sniff wants to listen for.
     *
     * @return array(integer)
     */
    public function register()
    {
        return array(
                T_IF,
                T_ELSEIF,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();
        $token  = $tokens[$stackPtr];

        // Skip for-loop without body.
        if (isset($token['parenthesis_opener']) === false) {
            return;
        }

        $next = ++$token['parenthesis_opener'];
        $end  = --$token['parenthesis_closer'];

        $goodCondition = false;
        for (; $next <= $end; ++$next) {
            $code = $tokens[$next]['code'];

            if (in_array($code, PHP_CodeSniffer_Tokens::$emptyTokens) === true) {
                continue;
            } else if ($code !== T_TRUE && $code !== T_FALSE) {
                $goodCondition = true;
            }
        }

        if ($goodCondition === false) {
            $error = 'Avoid IF statements that are always true or false';
            $phpcsFile->addWarning($error, $stackPtr, 'Found');
        }

    }//end process()


}//end class

?><?php
/**
 * This file is part of the CodeAnalysis addon for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Checks the for unused function parameters.
 *
 * This sniff checks that all function parameters are used in the function body.
 * One exception is made for empty function bodies or function bodies that only
 * contain comments. This could be useful for the classes that implement an
 * interface that defines multiple methods but the implementation only needs some
 * of them.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_CodeAnalysis_UnusedFunctionParameterSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_FUNCTION);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();
        $token  = $tokens[$stackPtr];

        // Skip broken function declarations.
        if (isset($token['scope_opener']) === false || isset($token['parenthesis_opener']) === false) {
            return;
        }

        $params = array();
        foreach ($phpcsFile->getMethodParameters($stackPtr) as $param) {
            $params[$param['name']] = $stackPtr;
        }

        $next = ++$token['scope_opener'];
        $end  = --$token['scope_closer'];

        $foundContent = false;

        for (; $next <= $end; ++$next) {
            $token = $tokens[$next];
            $code  = $token['code'];

            // Ignorable tokens.
            if (in_array($code, PHP_CodeSniffer_Tokens::$emptyTokens) === true) {
                continue;
            }

            if ($foundContent === false) {
                // A throw statement as the first content indicates an interface method.
                if ($code === T_THROW) {
                    return;
                }

                // A return statement as the first content indicates an interface method.
                if ($code === T_RETURN) {
                    $tmp = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($next + 1), null, true);
                    if ($tmp === false) {
                        return;
                    }

                    // There is a return.
                    if ($tokens[$tmp]['code'] === T_SEMICOLON) {
                        return;
                    }

                    $tmp = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($tmp + 1), null, true);
                    if ($tmp !== false && $tokens[$tmp]['code'] === T_SEMICOLON) {
                        // There is a return <token>.
                        return;
                    }
                }//end if
            }//end if

            $foundContent = true;

            if ($code === T_VARIABLE && isset($params[$token['content']]) === true) {
                unset($params[$token['content']]);
            } else if ($code === T_DOLLAR) {
                $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($next + 1), null, true);
                if ($tokens[$nextToken]['code'] === T_OPEN_CURLY_BRACKET) {
                    $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($nextToken + 1), null, true);
                    if ($tokens[$nextToken]['code'] === T_STRING) {
                        $varContent = '$'.$tokens[$nextToken]['content'];
                        if (isset($params[$varContent]) === true) {
                            unset($params[$varContent]);
                        }
                    }
                }
            } else if ($code === T_DOUBLE_QUOTED_STRING
                || $code === T_START_HEREDOC
                || $code === T_START_NOWDOC
            ) {
                // Tokenize strings that can contain variables.
                // Make sure the string is re-joined if it occurs over multiple lines.
                $validTokens = array(
                                T_HEREDOC,
                                T_NOWDOC,
                                T_END_HEREDOC,
                                T_END_NOWDOC,
                                T_DOUBLE_QUOTED_STRING,
                               );
                $validTokens = array_merge($validTokens, PHP_CodeSniffer_Tokens::$emptyTokens);

                $content = $token['content'];
                for ($i = ($next + 1); $i <= $end; $i++) {
                    if (in_array($tokens[$i]['code'], $validTokens) === true) {
                        $content .= $tokens[$i]['content'];
                        $next++;
                    } else {
                        break;
                    }
                }

                $stringTokens = token_get_all(sprintf('<?php %s;?>', $content));
                foreach ($stringTokens as $stringPtr => $stringToken) {
                    if (is_array($stringToken) === false) {
                        continue;
                    }

                    $varContent = '';
                    if ($stringToken[0] === T_DOLLAR_OPEN_CURLY_BRACES) {
                        $varContent = '$'.$stringTokens[($stringPtr + 1)][1];
                    } else if ($stringToken[0] === T_VARIABLE) {
                        $varContent = $stringToken[1];
                    }

                    if ($varContent !== '' && isset($params[$varContent]) === true) {
                        unset($params[$varContent]);
                    }
                }
            }//end if
        }//end for

        if ($foundContent === true && count($params) > 0) {
            foreach ($params as $paramName => $position) {
                $error = 'The method parameter %s is never used';
                $data  = array($paramName);
                $phpcsFile->addWarning($error, $position, 'Found', $data);
            }
        }

    }//end process()


}//end class

?>
<?php
/**
 * This file is part of the CodeAnalysis addon for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Detects incrementer jumbling in for loops.
 * 
 * This rule is based on the PMD rule catalog. The jumbling incrementer sniff
 * detects the usage of one and the same incrementer into an outer and an inner
 * loop. Even it is intended this is confusing code.
 *
 * <code>
 * class Foo
 * {
 *     public function bar($x)
 *     {
 *         for ($i = 0; $i < 10; $i++)
 *         {
 *             for ($k = 0; $k < 20; $i++)
 *             {
 *                 echo 'Hello';
 *             }
 *         }
 *     }
 * }
 * </code>
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_CodeAnalysis_JumbledIncrementerSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Registers the tokens that this sniff wants to listen for.
     *
     * @return array(integer)
     */
    public function register()
    {
        return array(T_FOR);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();
        $token  = $tokens[$stackPtr];

        // Skip for-loop without body.
        if (isset($token['scope_opener']) === false) {
            return;
        }

        // Find incrementors for outer loop.
        $outer = $this->findIncrementers($tokens, $token);

        // Skip if empty.
        if (count($outer) === 0) {
            return;
        }

        // Find nested for loops.
        $start = ++$token['scope_opener'];
        $end   = --$token['scope_closer'];

        for (; $start <= $end; ++$start) {
            if ($tokens[$start]['code'] !== T_FOR) {
                continue;
            }

            $inner = $this->findIncrementers($tokens, $tokens[$start]);
            $diff  = array_intersect($outer, $inner);

            if (count($diff) !== 0) {
                $error = 'Loop incrementor (%s) jumbling with inner loop';
                $data  = array(join(', ', $diff));
                $phpcsFile->addWarning($error, $stackPtr, 'Found', $data);
            }
        }

    }//end process()


    /**
     * Get all used variables in the incrementer part of a for statement.
     *
     * @param array(integer=>array) $tokens Array with all code sniffer tokens.
     * @param array(string=>mixed)  $token  Current for loop token
     * 
     * @return array(string) List of all found incrementer variables.
     */
    protected function findIncrementers(array $tokens, array $token)
    {
        // Skip invalid statement.
        if (isset($token['parenthesis_opener']) === false) {
            return array();
        }

        $start = ++$token['parenthesis_opener'];
        $end   = --$token['parenthesis_closer'];

        $incrementers = array();
        $semicolons   = 0;
        for ($next = $start; $next <= $end; ++$next) {
            $code = $tokens[$next]['code'];
            if ($code === T_SEMICOLON) {
                ++$semicolons;
            } else if ($semicolons === 2 && $code === T_VARIABLE) {
                $incrementers[] = $tokens[$next]['content'];
            }
        }

        return $incrementers;

    }//end findIncrementers()


}//end class

?><?php
/**
 * This file is part of the CodeAnalysis addon for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Detects unnecessary overridden methods that simply call their parent.
 *
 * This rule is based on the PMD rule catalog. The Useless Overriding Method
 * sniff detects the use of methods that only call their parent classes's method
 * with the same name and arguments. These methods are not required.
 *
 * <code>
 * class FooBar {
 *   public function __construct($a, $b) {
 *     parent::__construct($a, $b);
 *   }
 * }
 * </code>
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_CodeAnalysis_UselessOverridingMethodSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Registers the tokens that this sniff wants to listen for.
     *
     * @return array(integer)
     */
    public function register()
    {
        return array(T_FUNCTION);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();
        $token  = $tokens[$stackPtr];

        // Skip function without body.
        if (isset($token['scope_opener']) === false) {
            return;
        }

        // Get function name.
        $methodName = $phpcsFile->getDeclarationName($stackPtr);

        // Get all parameters from method signature.
        $signature = array();
        foreach ($phpcsFile->getMethodParameters($stackPtr) as $param) {
            $signature[] = $param['name'];
        }

        $next = ++$token['scope_opener'];
        $end  = --$token['scope_closer'];

        for (; $next <= $end; ++$next) {
            $code = $tokens[$next]['code'];

            if (in_array($code, PHP_CodeSniffer_Tokens::$emptyTokens) === true) {
                continue;
            } else if ($code === T_RETURN) {
                continue;
            }

            break;
        }

        // Any token except 'parent' indicates correct code.
        if ($tokens[$next]['code'] !== T_PARENT) {
            return;
        }

        // Find next non empty token index, should be double colon.
        $next = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($next + 1), null, true);

        // Skip for invalid code.
        if ($next === false || $tokens[$next]['code'] !== T_DOUBLE_COLON) {
            return;
        }

        // Find next non empty token index, should be the function name.
        $next = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($next + 1), null, true);

        // Skip for invalid code or other method.
        if ($next === false || $tokens[$next]['content'] !== $methodName) {
            return;
        }

        // Find next non empty token index, should be the open parenthesis.
        $next = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($next + 1), null, true);

        // Skip for invalid code.
        if ($next === false || $tokens[$next]['code'] !== T_OPEN_PARENTHESIS) {
            return;
        }

        $validParameterTypes = array(
                                T_VARIABLE,
                                T_LNUMBER,
                                T_CONSTANT_ENCAPSED_STRING,
                               );

        $parameters       = array('');
        $parenthesisCount = 1;
        $count            = count($tokens);
        for (++$next; $next < $count; ++$next) {
            $code = $tokens[$next]['code'];

            if ($code === T_OPEN_PARENTHESIS) {
                ++$parenthesisCount;
            } else if ($code === T_CLOSE_PARENTHESIS) {
                --$parenthesisCount;
            } else if ($parenthesisCount === 1 && $code === T_COMMA) {
                $parameters[] = '';
            } else if (in_array($code, PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
                $parameters[(count($parameters) - 1)] .= $tokens[$next]['content'];
            }

            if ($parenthesisCount === 0) {
                break;
            }
        }//end for

        $next = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($next + 1), null, true);
        if ($next === false || $tokens[$next]['code'] !== T_SEMICOLON) {
            return;
        }

        // Check rest of the scope.
        for (++$next; $next <= $end; ++$next) {
            $code = $tokens[$next]['code'];
            // Skip for any other content.
            if (in_array($code, PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
                return;
            }
        }

        $parameters = array_map('trim', $parameters);
        $parameters = array_filter($parameters);

        if (count($parameters) === count($signature) && $parameters === $signature) {
            $phpcsFile->addWarning('Useless method overriding detected', $stackPtr, 'Found');
        }

    }//end process()


}//end class

?><?php
/**
 * This file is part of the CodeAnalysis addon for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Detects unnecessary final modifiers inside of final classes.
 *
 * This rule is based on the PMD rule catalog. The Unnecessary Final Modifier
 * sniff detects the use of the final modifier inside of a final class which
 * is unnecessary.
 *
 * <code>
 * final class Foo
 * {
 *     public final function bar()
 *     {
 *     }
 * }
 * </code>
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_CodeAnalysis_UnnecessaryFinalModifierSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Registers the tokens that this sniff wants to listen for.
     *
     * @return array(integer)
     */
    public function register()
    {
        return array(T_CLASS);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();
        $token  = $tokens[$stackPtr];

        // Skip for-statements without body.
        if (isset($token['scope_opener']) === false) {
            return;
        }

        // Fetch previous token.
        $prev = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr - 1), null, true);

        // Skip for non final class.
        if ($prev === false || $tokens[$prev]['code'] !== T_FINAL) {
            return;
        }

        $next = ++$token['scope_opener'];
        $end  = --$token['scope_closer'];

        for (; $next <= $end; ++$next) {
            if ($tokens[$next]['code'] === T_FINAL) {
                $error = 'Unnecessary FINAL modifier in FINAL class';
                $phpcsFile->addWarning($error, $next, 'Found');
            }
        }

    }//end process()


}//end class

?><?php
/**
 * This file is part of the CodeAnalysis addon for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Detects for-loops that use a function call in the test expression.
 *
 * This rule is based on the PMD rule catalog. Detects for-loops that use a
 * function call in the test expression.
 *
 * <code>
 * class Foo
 * {
 *     public function bar($x)
 *     {
 *         $a = array(1, 2, 3, 4);
 *         for ($i = 0; $i < count($a); $i++) {
 *              $a[$i] *= $i;
 *         }
 *     }
 * }
 * </code>
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_CodeAnalysis_ForLoopWithTestFunctionCallSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Registers the tokens that this sniff wants to listen for.
     *
     * @return array(integer)
     */
    public function register()
    {
        return array(T_FOR);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();
        $token  = $tokens[$stackPtr];

        // Skip invalid statement.
        if (isset($token['parenthesis_opener']) === false) {
            return;
        }

        $next = ++$token['parenthesis_opener'];
        $end  = --$token['parenthesis_closer'];

        $position = 0;

        for (; $next <= $end; ++$next) {
            $code = $tokens[$next]['code'];
            if ($code === T_SEMICOLON) {
                ++$position;
            }

            if ($position < 1) {
                continue;
            } else if ($position > 1) {
                break;
            } else if ($code !== T_VARIABLE && $code !== T_STRING) {
                continue;
            }

            // Find next non empty token, if it is a open curly brace we have a
            // function call.
            $index = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($next + 1), null, true);

            if ($tokens[$index]['code'] === T_OPEN_PARENTHESIS) {
                $error = 'Avoid function calls in a FOR loop test part';
                $phpcsFile->addWarning($error, $stackPtr, 'NotAllowed');
                break;
            }
        }//end for

    }//end process()


}//end class

?>
<?php
/**
 * This file is part of the CodeAnalysis addon for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Detects for-loops that can be simplified to a while-loop.
 *
 * This rule is based on the PMD rule catalog. Detects for-loops that can be
 * simplified as a while-loop.
 *
 * <code>
 * class Foo
 * {
 *     public function bar($x)
 *     {
 *         for (;true;) true; // No Init or Update part, may as well be: while (true)
 *     }
 * }
 * </code>
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_CodeAnalysis_ForLoopShouldBeWhileLoopSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Registers the tokens that this sniff wants to listen for.
     *
     * @return array(integer)
     */
    public function register()
    {
        return array(T_FOR);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();
        $token  = $tokens[$stackPtr];

        // Skip invalid statement.
        if (isset($token['parenthesis_opener']) === false) {
            return;
        }

        $next = ++$token['parenthesis_opener'];
        $end  = --$token['parenthesis_closer'];

        $parts = array(
                  0,
                  0,
                  0,
                 );
        $index = 0;

        for (; $next <= $end; ++$next) {
            $code = $tokens[$next]['code'];
            if ($code === T_SEMICOLON) {
                ++$index;
            } else if (in_array($code, PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
                ++$parts[$index];
            }
        }

        if ($parts[0] === 0 && $parts[2] === 0 && $parts[1] > 0) {
            $error = 'This FOR loop can be simplified to a WHILE loop';
            $phpcsFile->addWarning($error, $stackPtr, 'CanSimplify');
        }

    }//end process()


}//end class

?>
<?php
/**
 * This file is part of the CodeAnalysis addon for PHP_CodeSniffer.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * This sniff class detected empty statement.
 *
 * This sniff implements the common algorithm for empty statement body detection.
 * A body is considered as empty if it is completely empty or it only contains
 * whitespace characters and|or comments.
 *
 * <code>
 * stmt {
 *   // foo
 * }
 * stmt (conditions) {
 *   // foo
 * }
 * </code>
 *
 * Statements covered by this sniff are <b>catch</b>, <b>do</b>, <b>else</b>,
 * <b>elsif</b>, <b>for</b>, <b>foreach<b>, <b>if</b>, <b>switch</b>, <b>try</b>
 * and <b>while</b>.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_CodeAnalysis_EmptyStatementSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * List of block tokens that this sniff covers.
     *
     * The key of this hash identifies the required token while the boolean
     * value says mark an error or mark a warning.
     *
     * @var array
     */
    protected $checkedTokens = array(
                                T_CATCH   => false,
                                T_DO      => true,
                                T_ELSE    => true,
                                T_ELSEIF  => true,
                                T_FOR     => true,
                                T_FOREACH => true,
                                T_IF      => true,
                                T_SWITCH  => true,
                                T_TRY     => true,
                                T_WHILE   => true,
                               );


    /**
     * Registers the tokens that this sniff wants to listen for.
     *
     * @return array(integer)
     */
    public function register()
    {
        return array_keys($this->checkedTokens);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();
        $token  = $tokens[$stackPtr];

        // Skip for-statements without body.
        if (isset($token['scope_opener']) === false) {
            return;
        }

        $next = ++$token['scope_opener'];
        $end  = --$token['scope_closer'];

        $emptyBody = true;
        for (; $next <= $end; ++$next) {
            if (in_array($tokens[$next]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
                $emptyBody = false;
                break;
            }
        }

        if ($emptyBody === true) {
            // Get token identifier.
            $name  = $phpcsFile->getTokensAsString($stackPtr, 1);
            $error = 'Empty %s statement detected';
            $data  = array(strtoupper($name));
            if ($this->checkedTokens[$token['code']] === true) {
                $phpcsFile->addError($error, $stackPtr, 'NotAllowed', $data);
            } else {
                $phpcsFile->addWarning($error, $stackPtr, 'NotAllowedWarning', $data);
            }
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_NamingConventions_CamelCapsFunctionNameSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_Standards_AbstractScopeSniff', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_Standards_AbstractScopeSniff not found');
}

/**
 * Generic_Sniffs_NamingConventions_CamelCapsFunctionNameSniff.
 *
 * Ensures method names are correct depending on whether they are public
 * or private, and that functions are named correctly.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_NamingConventions_CamelCapsFunctionNameSniff extends PHP_CodeSniffer_Standards_AbstractScopeSniff
{

    /**
     * A list of all PHP magic methods.
     *
     * @var array
     */
    protected $magicMethods = array(
                               'construct',
                               'destruct',
                               'call',
                               'callstatic',
                               'get',
                               'set',
                               'isset',
                               'unset',
                               'sleep',
                               'wakeup',
                               'tostring',
                               'set_state',
                               'clone',
                               'invoke',
                               'call',
                              );

    /**
     * A list of all PHP non-magic methods starting with a double underscore.
     *
     * These come from PHP modules such as SOAPClient.
     *
     * @var array
     */
    protected $methodsDoubleUnderscore = array(
                                          'soapcall',
                                          'getlastrequest',
                                          'getlastresponse',
                                          'getlastrequestheaders',
                                          'getlastresponseheaders',
                                          'getfunctions',
                                          'gettypes',
                                          'dorequest',
                                          'setcookie',
                                          'setlocation',
                                          'setsoapheaders',
                                         );

    /**
     * A list of all PHP magic functions.
     *
     * @var array
     */
    protected $magicFunctions = array('autoload');

    /**
     * If TRUE, the string must not have two capital letters next to each other.
     *
     * @var bool
     */
    public $strict = true;


    /**
     * Constructs a Generic_Sniffs_NamingConventions_CamelCapsFunctionNameSniff.
     */
    public function __construct()
    {
        parent::__construct(array(T_CLASS, T_INTERFACE, T_TRAIT), array(T_FUNCTION), true);

    }//end __construct()


    /**
     * Processes the tokens within the scope.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being processed.
     * @param int                  $stackPtr  The position where this token was
     *                                        found.
     * @param int                  $currScope The position of the current scope.
     *
     * @return void
     */
    protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope)
    {
        $methodName = $phpcsFile->getDeclarationName($stackPtr);
        if ($methodName === null) {
            // Ignore closures.
            return;
        }

        $className = $phpcsFile->getDeclarationName($currScope);
        $errorData = array($className.'::'.$methodName);

        // Is this a magic method. i.e., is prefixed with "__" ?
        if (preg_match('|^__|', $methodName) !== 0) {
            $magicPart = strtolower(substr($methodName, 2));
            if (in_array($magicPart, array_merge($this->magicMethods, $this->methodsDoubleUnderscore)) === false) {
                 $error = 'Method name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore';
                 $phpcsFile->addError($error, $stackPtr, 'MethodDoubleUnderscore', $errorData);
            }

            return;
        }

        // PHP4 constructors are allowed to break our rules.
        if ($methodName === $className) {
            return;
        }

        // PHP4 destructors are allowed to break our rules.
        if ($methodName === '_'.$className) {
            return;
        }

        $methodProps = $phpcsFile->getMethodProperties($stackPtr);
        if (PHP_CodeSniffer::isCamelCaps($methodName, false, true, $this->strict) === false) {
            if ($methodProps['scope_specified'] === true) {
                $error = '%s method name "%s" is not in camel caps format';
                $data  = array(
                          ucfirst($methodProps['scope']),
                          $errorData[0],
                         );
                $phpcsFile->addError($error, $stackPtr, 'ScopeNotCamelCaps', $data);
            } else {
                $error = 'Method name "%s" is not in camel caps format';
                $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData);
            }

            return;
        }

    }//end processTokenWithinScope()


    /**
     * Processes the tokens outside the scope.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being processed.
     * @param int                  $stackPtr  The position where this token was
     *                                        found.
     *
     * @return void
     */
    protected function processTokenOutsideScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $functionName = $phpcsFile->getDeclarationName($stackPtr);
        if ($functionName === null) {
            // Ignore closures.
            return;
        }

        $errorData = array($functionName);

        // Is this a magic function. i.e., it is prefixed with "__".
        if (preg_match('|^__|', $functionName) !== 0) {
            $magicPart = strtolower(substr($functionName, 2));
            if (in_array($magicPart, $this->magicFunctions) === false) {
                 $error = 'Function name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore';
                 $phpcsFile->addError($error, $stackPtr, 'FunctionDoubleUnderscore', $errorData);
            }

            return;
        }

        if (PHP_CodeSniffer::isCamelCaps($functionName, false, true, $this->strict) === false) {
            $error = 'Function name "%s" is not in camel caps format';
            $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData);
        }


    }//end processTokenOutsideScope()


}//end class

?>
<?php
/**
 * Generic_Sniffs_NamingConventions_ConstructorNameSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Leif Wickland <lwickland@rightnow.com>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_Standards_AbstractScopeSniff', true) === false) {
    $error = 'Class PHP_CodeSniffer_Standards_AbstractScopeSniff not found';
    throw new PHP_CodeSniffer_Exception($error);
}

/**
 * Generic_Sniffs_NamingConventions_ConstructorNameSniff.
 *
 * Favor PHP 5 constructor syntax, which uses "function __construct()".
 * Avoid PHP 4 constructor syntax, which uses "function ClassName()".
 *
 * @category PHP
 * @package  PHP_CodeSniffer
 * @author   Leif Wickland <lwickland@rightnow.com>
 * @license  https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version  Release: @package_version@
 * @link     http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_NamingConventions_ConstructorNameSniff extends PHP_CodeSniffer_Standards_AbstractScopeSniff
{


    /**
     * Constructs the test with the tokens it wishes to listen for.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct(array(T_CLASS, T_INTERFACE), array(T_FUNCTION), true);

    }//end __construct()


    /**
     * Processes this test when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The current file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     * @param int                  $currScope A pointer to the start of the scope.
     *
     * @return void
     */
    protected function processTokenWithinScope(
        PHP_CodeSniffer_File $phpcsFile,
        $stackPtr,
        $currScope
    ) {
        $className  = $phpcsFile->getDeclarationName($currScope);
        $methodName = $phpcsFile->getDeclarationName($stackPtr);

        if (strcasecmp($methodName, $className) === 0) {
            $error = 'PHP4 style constructors are not allowed; use "__construct()" instead';
            $phpcsFile->addError($error, $stackPtr, 'OldStyle');
        } else if (strcasecmp($methodName, '__construct') !== 0) {
            // Not a constructor.
            return;
        }

        $tokens = $phpcsFile->getTokens();

        $parentClassName = $phpcsFile->findExtendedClassName($currScope);
        if ($parentClassName === false) {
            return;
        }

        // Stop if the constructor doesn't have a body, like when it is abstract.
        if (isset($tokens[$stackPtr]['scope_closer']) === false) {
            return;
        }

        $endFunctionIndex = $tokens[$stackPtr]['scope_closer'];
        $startIndex       = $stackPtr;
        while ($doubleColonIndex = $phpcsFile->findNext(array(T_DOUBLE_COLON), $startIndex, $endFunctionIndex)) {
            if ($tokens[($doubleColonIndex + 1)]['code'] === T_STRING
                && $tokens[($doubleColonIndex + 1)]['content'] === $parentClassName
            ) {
                $error = 'PHP4 style calls to parent constructors are not allowed; use "parent::__construct()" instead';
                $phpcsFile->addError($error, ($doubleColonIndex + 1), 'OldStyleCall');
            }

            $startIndex = ($doubleColonIndex + 1);
        }

    }//end processTokenWithinScope()


}//end class

?>
<?php
/**
 * Generic_Sniffs_NamingConventions_UpperCaseConstantNameSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_NamingConventions_UpperCaseConstantNameSniff.
 *
 * Ensures that constant names are all uppercase.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_NamingConventions_UpperCaseConstantNameSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_STRING);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens    = $phpcsFile->getTokens();
        $constName = $tokens[$stackPtr]['content'];

        // If this token is in a heredoc, ignore it.
        if ($phpcsFile->hasCondition($stackPtr, T_START_HEREDOC) === true) {
            return;
        }

        // Special case for PHP 5.5 class name resolution.
        if (strtolower($constName) === 'class'
            && $tokens[($stackPtr - 1)]['code'] === T_DOUBLE_COLON
        ) {
            return;
        }

        // Special case for PHPUnit.
        if ($constName === 'PHPUnit_MAIN_METHOD') {
            return;
        }

        // If the next non-whitespace token after this token
        // is not an opening parenthesis then it is not a function call.
        $openBracket = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
        if ($tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS) {
            $functionKeyword = $phpcsFile->findPrevious(
                array(
                 T_WHITESPACE,
                 T_COMMA,
                 T_COMMENT,
                 T_STRING,
                 T_NS_SEPARATOR,
                ),
                ($stackPtr - 1),
                null,
                true
            );

            if ($tokens[$functionKeyword]['code'] !== T_CONST) {
                return;
            }

            // This is a class constant.
            if (strtoupper($constName) !== $constName) {
                $error = 'Class constants must be uppercase; expected %s but found %s';
                $data  = array(
                          strtoupper($constName),
                          $constName,
                         );
                $phpcsFile->addError($error, $stackPtr, 'ClassConstantNotUpperCase', $data);
            }

            return;
        }

        if (strtolower($constName) !== 'define') {
            return;
        }

        /*
            This may be a "define" function call.
        */

        // Make sure this is not a method call.
        $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
        if ($tokens[$prev]['code'] === T_OBJECT_OPERATOR
            || $tokens[$prev]['code'] === T_DOUBLE_COLON
        ) {
            return;
        }

        // The next non-whitespace token must be the constant name.
        $constPtr = $phpcsFile->findNext(T_WHITESPACE, ($openBracket + 1), null, true);
        if ($tokens[$constPtr]['code'] !== T_CONSTANT_ENCAPSED_STRING) {
            return;
        }

        $constName = $tokens[$constPtr]['content'];

        // Check for constants like self::CONSTANT.
        $prefix   = '';
        $splitPos = strpos($constName, '::');
        if ($splitPos !== false) {
            $prefix    = substr($constName, 0, ($splitPos + 2));
            $constName = substr($constName, ($splitPos + 2));
        }

        if (strtoupper($constName) !== $constName) {
            $error = 'Constants must be uppercase; expected %s but found %s';
            $data  = array(
                      $prefix.strtoupper($constName),
                      $prefix.$constName,
                     );
            $phpcsFile->addError($error, $stackPtr, 'ConstantNotUpperCase', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_WhiteSpace_DisallowTabIndentSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_WhiteSpace_DisallowTabIndentSniff.
 *
 * Throws errors if tabs are used for indentation.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_WhiteSpace_DisallowTabIndentSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                   'CSS',
                                  );


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_WHITESPACE);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile All the tokens found in the document.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Make sure this is whitespace used for indentation.
        $line = $tokens[$stackPtr]['line'];
        if ($stackPtr > 0 && $tokens[($stackPtr - 1)]['line'] === $line) {
            return;
        }

        if (strpos($tokens[$stackPtr]['content'], "\t") !== false) {
            $error = 'Spaces must be used to indent lines; tabs are not allowed';
            $phpcsFile->addError($error, $stackPtr, 'TabsUsed');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_Whitespace_ScopeIndentSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_Whitespace_ScopeIndentSniff.
 *
 * Checks that control structures are structured correctly, and their content
 * is indented correctly. This sniff will throw errors if tabs are used
 * for indentation rather than spaces.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_WhiteSpace_ScopeIndentSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * The number of spaces code should be indented.
     *
     * @var int
     */
    public $indent = 4;

    /**
     * Does the indent need to be exactly right.
     *
     * If TRUE, indent needs to be exactly $indent spaces. If FALSE,
     * indent needs to be at least $indent spaces (but can be more).
     *
     * @var bool
     */
    public $exact = false;

    /**
     * List of tokens not needing to be checked for indentation.
     *
     * Useful to allow Sniffs based on this to easily ignore/skip some
     * tokens from verification. For example, inline html sections
     * or php open/close tags can escape from here and have their own
     * rules elsewhere.
     *
     * @var array
     */
    public $ignoreIndentationTokens = array();

    /**
     * Any scope openers that should not cause an indent.
     *
     * @var array(int)
     */
    protected $nonIndentingScopes = array();

    /**
     * Stores the indent of the last PHP open tag we found.
     *
     * This value is used to calculate the expected indent of top level structures
     * so we don't assume they are always at column 1. If PHP code is embedded inside
     * HTML (etc.) code, then the starting column for that code may not be column 1.
     *
     * @var int
     */
    private $_openTagIndent = 0;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        $tokens   = PHP_CodeSniffer_Tokens::$scopeOpeners;
        $tokens[] = T_OPEN_TAG;
        return $tokens;

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile All the tokens found in the document.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // We only want to record the indent of open tags, not process them.
        if ($tokens[$stackPtr]['code'] == T_OPEN_TAG) {
            if (empty($tokens[$stackPtr]['conditions']) === true) {
                // Only record top-level PHP tags.
                $this->_openTagIndent = ($tokens[$stackPtr]['column'] - 1);
            }

            return;
        }

        // If this is an inline condition (ie. there is no scope opener), then
        // return, as this is not a new scope.
        if (isset($tokens[$stackPtr]['scope_opener']) === false) {
            return;
        }

        if ($tokens[$stackPtr]['code'] === T_ELSE) {
            $next = $phpcsFile->findNext(
                PHP_CodeSniffer_Tokens::$emptyTokens,
                ($stackPtr + 1),
                null,
                true
            );

            // We will handle the T_IF token in another call to process.
            if ($tokens[$next]['code'] === T_IF) {
                return;
            }
        }

        // Find the first token on this line.
        $firstToken = $stackPtr;
        for ($i = $stackPtr; $i >= 0; $i--) {
            // Record the first code token on the line.
            if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
                $firstToken = $i;
            }

            // It's the start of the line, so we've found our first php token.
            if ($tokens[$i]['column'] === 1) {
                break;
            }
        }

        // Based on the conditions that surround this token, determine the
        // indent that we expect this current content to be.
        $expectedIndent = $this->calculateExpectedIndent($tokens, $firstToken);

        // Don't process the first token if it is a closure because they have
        // different indentation rules as they are often used as function arguments
        // for multi-line function calls. But continue to process the content of the
        // closure because it should be indented as normal.
        if ($tokens[$firstToken]['code'] !== T_CLOSURE
            && $tokens[$firstToken]['column'] !== $expectedIndent
        ) {
            // If the scope opener is a closure but it is not the first token on the
            // line, then the first token may be a variable or array index as so
            // should not require exact indentation unless the exact member var
            // is set to TRUE.
            $exact = true;
            if ($tokens[$stackPtr]['code'] === T_CLOSURE) {
                $exact = $this->exact;
            }

            if ($exact === true || $tokens[$firstToken]['column'] < $expectedIndent) {
                $error = 'Line indented incorrectly; expected %s spaces, found %s';
                $data  = array(
                          ($expectedIndent - 1),
                          ($tokens[$firstToken]['column'] - 1),
                         );
                $phpcsFile->addError($error, $stackPtr, 'Incorrect', $data);
            }
        }//end if

        $scopeOpener = $tokens[$stackPtr]['scope_opener'];
        $scopeCloser = $tokens[$stackPtr]['scope_closer'];

        // Some scopes are expected not to have indents.
        if (in_array($tokens[$firstToken]['code'], $this->nonIndentingScopes) === false) {
            $indent = ($expectedIndent + $this->indent);
        } else {
            $indent = $expectedIndent;
        }

        $newline     = false;
        $commentOpen = false;
        $inHereDoc   = false;

        // Only loop over the content between the opening and closing brace, not
        // the braces themselves.
        for ($i = ($scopeOpener + 1); $i < $scopeCloser; $i++) {

            // If this token is another scope, skip it as it will be handled by
            // another call to this sniff.
            if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$scopeOpeners) === true) {
                if (isset($tokens[$i]['scope_opener']) === true) {
                    $i = $tokens[$i]['scope_closer'];

                    // If the scope closer is followed by a semi-colon, the semi-colon is part
                    // of the closer and should also be ignored. This most commonly happens with
                    // CASE statements that end with "break;", where we don't want to stop
                    // ignoring at the break, but rather at the semi-colon.
                    $nextToken = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($i + 1), null, true);
                    if ($tokens[$nextToken]['code'] === T_SEMICOLON) {
                        $i = $nextToken;
                    }
                } else {
                    // If this token does not have a scope_opener indice, then
                    // it's probably an inline scope, so let's skip to the next
                    // semicolon. Inline scopes include inline if's, abstract
                    // methods etc.
                    $nextToken = $phpcsFile->findNext(T_SEMICOLON, $i, $scopeCloser);
                    if ($nextToken !== false) {
                        $i = $nextToken;
                    }
                }

                continue;
            }//end if

            // If this is a HEREDOC then we need to ignore it as the
            // whitespace before the contents within the HEREDOC are
            // considered part of the content.
            if ($tokens[$i]['code'] === T_START_HEREDOC
                || $tokens[$i]['code'] === T_START_NOWDOC
            ) {
                $inHereDoc = true;
                continue;
            } else if ($inHereDoc === true) {
                if ($tokens[$i]['code'] === T_END_HEREDOC
                    || $tokens[$i]['code'] === T_END_NOWDOC
                ) {
                    $inHereDoc = false;
                }

                continue;
            }

            if ($tokens[$i]['column'] === 1) {
                // We started a newline.
                $newline = true;
            }

            if ($newline === true && $tokens[$i]['code'] !== T_WHITESPACE) {
                // If we started a newline and we find a token that is not
                // whitespace, then this must be the first token on the line that
                // must be indented.
                $newline    = false;
                $firstToken = $i;

                $column = $tokens[$firstToken]['column'];

                // Ignore the token for indentation if it's in the ignore list.
                if (in_array($tokens[$firstToken]['code'], $this->ignoreIndentationTokens)
                    || in_array($tokens[$firstToken]['type'], $this->ignoreIndentationTokens)
                ) {
                    continue;
                }

                // Special case for non-PHP code.
                if ($tokens[$firstToken]['code'] === T_INLINE_HTML) {
                    $trimmedContentLength
                        = strlen(ltrim($tokens[$firstToken]['content']));
                    if ($trimmedContentLength === 0) {
                        continue;
                    }

                    $contentLength = strlen($tokens[$firstToken]['content']);
                    $column        = ($contentLength - $trimmedContentLength + 1);
                }

                // Check to see if this constant string spans multiple lines.
                // If so, then make sure that the strings on lines other than the
                // first line are indented appropriately, based on their whitespace.
                if (in_array($tokens[$firstToken]['code'], PHP_CodeSniffer_Tokens::$stringTokens) === true) {
                    if (in_array($tokens[($firstToken - 1)]['code'], PHP_CodeSniffer_Tokens::$stringTokens) === true) {
                        // If we find a string that directly follows another string
                        // then its just a string that spans multiple lines, so we
                        // don't need to check for indenting.
                        continue;
                    }
                }

                // This is a special condition for T_DOC_COMMENT and C-style
                // comments, which contain whitespace between each line.
                if (in_array($tokens[$firstToken]['code'], PHP_CodeSniffer_Tokens::$commentTokens) === true) {
                    $content = trim($tokens[$firstToken]['content']);
                    if (preg_match('|^/\*|', $content) !== 0) {
                        // Check to see if the end of the comment is on the same line
                        // as the start of the comment. If it is, then we don't
                        // have to worry about opening a comment.
                        if (preg_match('|\*/$|', $content) === 0) {
                            // We don't have to calculate the column for the
                            // start of the comment as there is a whitespace
                            // token before it.
                            $commentOpen = true;
                        }
                    } else if ($commentOpen === true) {
                        if ($content === '') {
                            // We are in a comment, but this line has nothing on it
                            // so let's skip it.
                            continue;
                        }

                        $contentLength = strlen($tokens[$firstToken]['content']);
                        $trimmedContentLength
                            = strlen(ltrim($tokens[$firstToken]['content']));

                        $column = ($contentLength - $trimmedContentLength + 1);
                        if (preg_match('|\*/$|', $content) !== 0) {
                            $commentOpen = false;
                        }

                        // We are in a comment, so the indent does not have to
                        // be exact. The important thing is that the comment opens
                        // at the correct column and nothing sits closer to the left
                        // than that opening column.
                        if ($column > $indent) {
                            continue;
                        }
                    }//end if
                }//end if

                // The token at the start of the line, needs to have its' column
                // greater than the relative indent we set above. If it is less,
                // an error should be shown.
                if ($column !== $indent) {
                    if ($this->exact === true || $column < $indent) {
                        $type  = 'IncorrectExact';
                        $error = 'Line indented incorrectly; expected ';
                        if ($this->exact === false) {
                            $error .= 'at least ';
                            $type   = 'Incorrect';
                        }

                        $error .= '%s spaces, found %s';
                        $data = array(
                                 ($indent - 1),
                                 ($column - 1),
                                );
                        $phpcsFile->addError($error, $firstToken, $type, $data);
                    }
                }//end if
            }//end if
        }//end for

    }//end process()


    /**
     * Calculates the expected indent of a token.
     *
     * Returns the column at which the token should be indented to, so 1 means
     * that the token should not be indented at all.
     *
     * @param array $tokens   The stack of tokens for this file.
     * @param int   $stackPtr The position of the token to get indent for.
     *
     * @return int
     */
    protected function calculateExpectedIndent(array $tokens, $stackPtr)
    {
        $conditionStack = array();

        $inParenthesis = false;
        if (isset($tokens[$stackPtr]['nested_parenthesis']) === true
            && empty($tokens[$stackPtr]['nested_parenthesis']) === false
        ) {
            $inParenthesis = true;
        }

        // Empty conditions array (top level structure).
        if (empty($tokens[$stackPtr]['conditions']) === true) {
            if ($inParenthesis === true) {
                // Wrapped in parenthesis means it is probably in a
                // function call (like a closure) so we have to assume indent
                // is correct here and someone else will check it more
                // carefully in another sniff.
                return $tokens[$stackPtr]['column'];
            } else {
                return ($this->_openTagIndent + 1);
            }
        }

        $indent = 0;

        $tokenConditions = $tokens[$stackPtr]['conditions'];
        foreach ($tokenConditions as $id => $condition) {
            // If it's not an indenting scope i.e., it's in our array of
            // scopes that don't indent, skip it.
            if (in_array($condition, $this->nonIndentingScopes) === true) {
                continue;
            }

            if ($condition === T_CLOSURE && $inParenthesis === true) {
                // Closures cause problems with indents when they are
                // used as function arguments because the code inside them
                // is not technically inside the function yet, so the indent
                // is always off by one. So instead, use the
                // indent of the closure as the base value.
                $lastContent = $id;
                for ($i = ($id - 1); $i > 0; $i--) {
                    if ($tokens[$i]['line'] !== $tokens[$id]['line']) {
                        // Changed lines, so the last content we saw is what
                        // we want.
                        break;
                    }

                    if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
                        $lastContent = $i;
                    }
                }

                $indent = ($tokens[$lastContent]['column'] - 1);
            }

            $indent += $this->indent;
        }//end foreach

        // Increase by 1 to indiciate that the code should start at a specific column.
        // E.g., code indented 4 spaces should start at column 5.
        $indent++;
        return $indent;

    }//end calculateExpectedIndent()


}//end class

?>
<?php
/**
 * Generic_Sniffs_WhiteSpace_DisallowSpaceIndentSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_WhiteSpace_DisallowSpaceIndentSniff.
 *
 * Throws errors if spaces are used for indentation.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_WhiteSpace_DisallowSpaceIndentSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                   'CSS',
                                  );


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_WHITESPACE);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile All the tokens found in the document.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Make sure this is whitespace used for indentation.
        $line = $tokens[$stackPtr]['line'];
        if ($stackPtr > 0 && $tokens[($stackPtr - 1)]['line'] === $line) {
            return;
        }

        if (strpos($tokens[$stackPtr]['content'], ' ') !== false) {
            // Space are considered ok if they are proceeded by tabs and not followed
            // by tabs, as is the case with standard docblock comments.
            $error = 'Tabs must be used to indent lines; spaces are not allowed';
            $phpcsFile->addError($error, $stackPtr, 'TabsUsed');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_Functions_CallTimePassByReferenceSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Florian Grandel <jerico.dev@gmail.com>
 * @copyright 2009 Florian Grandel
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_Functions_CallTimePassByReferenceSniff.
 *
 * Ensures that variables are not passed by reference when calling a function.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Florian Grandel <jerico.dev@gmail.com>
 * @copyright 2009 Florian Grandel
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_Functions_CallTimePassByReferenceSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_STRING,
                T_VARIABLE,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Skip tokens that are the names of functions or classes
        // within their definitions. For example: function myFunction...
        // "myFunction" is T_STRING but we should skip because it is not a
        // function or method *call*.
        $functionName = $stackPtr;
        $findTokens   = array_merge(
            PHP_CodeSniffer_Tokens::$emptyTokens,
            array(T_BITWISE_AND)
        );

        $functionKeyword = $phpcsFile->findPrevious(
            $findTokens,
            ($stackPtr - 1),
            null,
            true
        );

        if ($tokens[$functionKeyword]['code'] === T_FUNCTION
            || $tokens[$functionKeyword]['code'] === T_CLASS
        ) {
            return;
        }

        // If the next non-whitespace token after the function or method call
        // is not an opening parenthesis then it cant really be a *call*.
        $openBracket = $phpcsFile->findNext(
            PHP_CodeSniffer_Tokens::$emptyTokens,
            ($functionName + 1),
            null,
            true
        );

        if ($tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS) {
            return;
        }

        $closeBracket = $tokens[$openBracket]['parenthesis_closer'];

        $nextSeparator = $openBracket;
        while (($nextSeparator = $phpcsFile->findNext(T_VARIABLE, ($nextSeparator + 1), $closeBracket)) !== false) {
            // Make sure the variable belongs directly to this function call
            // and is not inside a nested function call or array.
            $brackets    = $tokens[$nextSeparator]['nested_parenthesis'];
            $lastBracket = array_pop($brackets);
            if ($lastBracket !== $closeBracket) {
                continue;
            }

            // Checking this: $value = my_function(...[*]$arg...).
            $tokenBefore = $phpcsFile->findPrevious(
                PHP_CodeSniffer_Tokens::$emptyTokens,
                ($nextSeparator - 1),
                null,
                true
            );

            if ($tokens[$tokenBefore]['code'] === T_BITWISE_AND) {
                // Checking this: $value = my_function(...[*]&$arg...).
                $tokenBefore = $phpcsFile->findPrevious(
                    PHP_CodeSniffer_Tokens::$emptyTokens,
                    ($tokenBefore - 1),
                    null,
                    true
                );

                // We have to exclude all uses of T_BITWISE_AND that are not
                // references. We use a blacklist approach as we prefer false
                // positives to not identifying a pass-by-reference call at all.
                // The blacklist may not yet be complete.
                switch ($tokens[$tokenBefore]['code']) {
                case T_VARIABLE:
                case T_CLOSE_PARENTHESIS:
                case T_LNUMBER:
                    // In these cases T_BITWISE_AND represents
                    // the bitwise and operator.
                    continue;

                default:
                    // T_BITWISE_AND represents a pass-by-reference.
                    $error = 'Call-time pass-by-reference calls are prohibited';
                    $phpcsFile->addError($error, $tokenBefore, 'NotAllowed');
                    break;
                }
            }//end if
        }//end while

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_Methods_OpeningMethodBraceBsdAllmanSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_Functions_OpeningFunctionBraceBsdAllmanSniff.
 *
 * Checks that the opening brace of a function is on the line after the
 * function declaration.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_Functions_OpeningFunctionBraceBsdAllmanSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Registers the tokens that this sniff wants to listen for.
     *
     * @return void
     */
    public function register()
    {
        return array(T_FUNCTION);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if (isset($tokens[$stackPtr]['scope_opener']) === false) {
            return;
        }

        $openingBrace = $tokens[$stackPtr]['scope_opener'];

        // The end of the function occurs at the end of the argument list. Its
        // like this because some people like to break long function declarations
        // over multiple lines.
        $functionLine = $tokens[$tokens[$stackPtr]['parenthesis_closer']]['line'];
        $braceLine    = $tokens[$openingBrace]['line'];

        $lineDifference = ($braceLine - $functionLine);

        if ($lineDifference === 0) {
            $error = 'Opening brace should be on a new line';
            $phpcsFile->addError($error, $openingBrace, 'BraceOnSameLine');
            return;
        }

        if ($lineDifference > 1) {
            $error = 'Opening brace should be on the line after the declaration; found %s blank line(s)';
            $data  = array(($lineDifference - 1));
            $phpcsFile->addError($error, $openingBrace, 'BraceSpacing', $data);
            return;
        }

        // We need to actually find the first piece of content on this line,
        // as if this is a method with tokens before it (public, static etc)
        // or an if with an else before it, then we need to start the scope
        // checking from there, rather than the current token.
        $lineStart = $stackPtr;
        while (($lineStart = $phpcsFile->findPrevious(array(T_WHITESPACE), ($lineStart - 1), null, false)) !== false) {
            if (strpos($tokens[$lineStart]['content'], $phpcsFile->eolChar) !== false) {
                break;
            }
        }

        // We found a new line, now go forward and find the first non-whitespace
        // token.
        $lineStart = $phpcsFile->findNext(array(T_WHITESPACE), $lineStart, null, true);

        // The opening brace is on the correct line, now it needs to be
        // checked to be correctly indented.
        $startColumn = $tokens[$lineStart]['column'];
        $braceIndent = $tokens[$openingBrace]['column'];

        if ($braceIndent !== $startColumn) {
            $error = 'Opening brace indented incorrectly; expected %s spaces, found %s';
            $data  = array(
                      ($startColumn - 1),
                      ($braceIndent - 1),
                     );
            $phpcsFile->addError($error, $openingBrace, 'BraceIndent', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_Functions_FunctionCallArgumentSpacingSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_Functions_FunctionCallArgumentSpacingSniff.
 *
 * Checks that calls to methods and functions are spaced correctly.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_Functions_FunctionCallArgumentSpacingSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_STRING);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Skip tokens that are the names of functions or classes
        // within their definitions. For example:
        // function myFunction...
        // "myFunction" is T_STRING but we should skip because it is not a
        // function or method *call*.
        $functionName    = $stackPtr;
        $ignoreTokens    = PHP_CodeSniffer_Tokens::$emptyTokens;
        $ignoreTokens[]  = T_BITWISE_AND;
        $functionKeyword = $phpcsFile->findPrevious($ignoreTokens, ($stackPtr - 1), null, true);
        if ($tokens[$functionKeyword]['code'] === T_FUNCTION || $tokens[$functionKeyword]['code'] === T_CLASS) {
            return;
        }

        // If the next non-whitespace token after the function or method call
        // is not an opening parenthesis then it cant really be a *call*.
        $openBracket = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($functionName + 1), null, true);
        if ($tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS) {
            return;
        }

        $closeBracket = $tokens[$openBracket]['parenthesis_closer'];

        $nextSeparator = $openBracket;
        while (($nextSeparator = $phpcsFile->findNext(array(T_COMMA, T_VARIABLE, T_CLOSURE), ($nextSeparator + 1), $closeBracket)) !== false) {
            if ($tokens[$nextSeparator]['code'] === T_CLOSURE) {
                $nextSeparator = $tokens[$nextSeparator]['scope_closer'];
                continue;
            }

            // Make sure the comma or variable belongs directly to this function call,
            // and is not inside a nested function call or array.
            $brackets    = $tokens[$nextSeparator]['nested_parenthesis'];
            $lastBracket = array_pop($brackets);
            if ($lastBracket !== $closeBracket) {
                continue;
            }

            if ($tokens[$nextSeparator]['code'] === T_COMMA) {
                if ($tokens[($nextSeparator - 1)]['code'] === T_WHITESPACE) {
                    $error = 'Space found before comma in function call';
                    $phpcsFile->addError($error, $stackPtr, 'SpaceBeforeComma');
                }

                if ($tokens[($nextSeparator + 1)]['code'] !== T_WHITESPACE) {
                    $error = 'No space found after comma in function call';
                    $phpcsFile->addError($error, $stackPtr, 'NoSpaceAfterComma');
                } else {
                    // If there is a newline in the space, then the must be formatting
                    // each argument on a newline, which is valid, so ignore it.
                    if (strpos($tokens[($nextSeparator + 1)]['content'], $phpcsFile->eolChar) === false) {
                        $space = strlen($tokens[($nextSeparator + 1)]['content']);
                        if ($space > 1) {
                            $error = 'Expected 1 space after comma in function call; %s found';
                            $data  = array($space);
                            $phpcsFile->addError($error, $stackPtr, 'TooMuchSpaceAfterComma', $data);
                        }
                    }
                }
            } else {
                // Token is a variable.
                $nextToken = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($nextSeparator + 1), $closeBracket, true);
                if ($nextToken !== false) {
                    if ($tokens[$nextToken]['code'] === T_EQUAL) {
                        if (($tokens[($nextToken - 1)]['code']) !== T_WHITESPACE) {
                            $error = 'Expected 1 space before = sign of default value';
                            $phpcsFile->addError($error, $stackPtr, 'NoSpaceBeforeEquals');
                        }

                        if ($tokens[($nextToken + 1)]['code'] !== T_WHITESPACE) {
                            $error = 'Expected 1 space after = sign of default value';
                            $phpcsFile->addError($error, $stackPtr, 'NoSpaceAfterEquals');
                        }
                    }
                }
            }//end if
        }//end while

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_Functions_OpeningFunctionBraceKernighanRitchieSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_Functions_OpeningFunctionBraceKernighanRitchieSniff.
 *
 * Checks that the opening brace of a function is on the same line
 * as the function declaration.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_Functions_OpeningFunctionBraceKernighanRitchieSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Registers the tokens that this sniff wants to listen for.
     *
     * @return void
     */
    public function register()
    {
        return array(T_FUNCTION);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if (isset($tokens[$stackPtr]['scope_opener']) === false) {
            return;
        }

        $openingBrace = $tokens[$stackPtr]['scope_opener'];

        // The end of the function occurs at the end of the argument list. Its
        // like this because some people like to break long function declarations
        // over multiple lines.
        $functionLine = $tokens[$tokens[$stackPtr]['parenthesis_closer']]['line'];
        $braceLine    = $tokens[$openingBrace]['line'];

        $lineDifference = ($braceLine - $functionLine);

        if ($lineDifference > 0) {
            $error = 'Opening brace should be on the same line as the declaration';
            $phpcsFile->addError($error, $openingBrace, 'BraceOnNewLine');
            return;
        }

        $closeBracket = $tokens[$stackPtr]['parenthesis_closer'];
        if ($tokens[($closeBracket + 1)]['code'] !== T_WHITESPACE) {
            $length = 0;
        } else if ($tokens[($closeBracket + 1)]['content'] === "\t") {
            $length = '\t';
        } else {
            $length = strlen($tokens[($closeBracket + 1)]['content']);
        }

        if ($length !== 1) {
            $error = 'Expected 1 space after closing parenthesis; found %s';
            $data  = array($length);
            $phpcsFile->addError($error, $closeBracket, 'SpaceAfterBracket', $data);
            return;
        }

        $closeBrace = $tokens[$stackPtr]['scope_opener'];
        if ($tokens[($closeBrace - 1)]['code'] !== T_WHITESPACE) {
            $length = 0;
        } else if ($tokens[($closeBrace - 1)]['content'] === "\t") {
            $length = '\t';
        } else {
            $length = strlen($tokens[($closeBrace - 1)]['content']);
        }

        if ($length !== 1) {
            $error = 'Expected 1 space before opening brace; found %s';
            $data  = array($length);
            $phpcsFile->addError($error, $openingBrace, 'SpaceBeforeBrace', $data);
            return;
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_ControlStructures_InlineControlStructureSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_ControlStructures_InlineControlStructureSniff.
 *
 * Verifies that inline control statements are not present.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_ControlStructures_InlineControlStructureSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                  );

    /**
     * If true, an error will be thrown; otherwise a warning.
     *
     * @var bool
     */
    public $error = true;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_IF,
                T_ELSE,
                T_FOREACH,
                T_WHILE,
                T_DO,
                T_SWITCH,
                T_FOR,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if (isset($tokens[$stackPtr]['scope_opener']) === false) {
            // Ignore the ELSE in ELSE IF. We'll process the IF part later.
            if (($tokens[$stackPtr]['code'] === T_ELSE) && ($tokens[($stackPtr + 2)]['code'] === T_IF)) {
                return;
            }

            if ($tokens[$stackPtr]['code'] === T_WHILE) {
                // This could be from a DO WHILE, which doesn't have an opening brace.
                $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
                if ($tokens[$lastContent]['code'] === T_CLOSE_CURLY_BRACKET) {
                    $brace = $tokens[$lastContent];
                    if (isset($brace['scope_condition']) === true) {
                        $condition = $tokens[$brace['scope_condition']];
                        if ($condition['code'] === T_DO) {
                            return;
                        }
                    }
                }
            }

            // This is a control structure without an opening brace,
            // so it is an inline statement.
            if ($this->error === true) {
                $phpcsFile->addError('Inline control structures are not allowed', $stackPtr, 'NotAllowed');
            } else {
                $phpcsFile->addWarning('Inline control structures are discouraged', $stackPtr, 'Discouraged');
            }

            return;
        }//end if

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_Commenting_FixmeSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Sam Graham <php-codesniffer@illusori.co.uk>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_Commenting_FixmeSniff.
 *
 * Warns about FIXME comments.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Sam Graham <php-codesniffer@illusori.co.uk>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_Commenting_FixmeSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                  );


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return PHP_CodeSniffer_Tokens::$commentTokens;

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $content = $tokens[$stackPtr]['content'];
        $matches = array();
        if (preg_match('|[^a-z]+fixme[^a-z]+(.*)|i', $content, $matches) !== 0) {
            // Clear whitespace and some common characters not required at
            // the end of a fixme message to make the error more informative.
            $type         = 'CommentFound';
            $fixmeMessage = trim($matches[1]);
            $fixmeMessage = trim($fixmeMessage, '[]().');
            $error        = 'Comment refers to a FIXME task';
            $data         = array($fixmeMessage);
            if ($fixmeMessage !== '') {
                $type   = 'TaskFound';
                $error .= ' "%s"';
            }

            $phpcsFile->addError($error, $stackPtr, $type, $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_Commenting_TodoSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_Commenting_TodoSniff.
 *
 * Warns about TODO comments.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_Commenting_TodoSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                  );


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return PHP_CodeSniffer_Tokens::$commentTokens;

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $content = $tokens[$stackPtr]['content'];
        $matches = array();
        if (preg_match('|[^a-z]+todo[^a-z]+(.*)|i', $content, $matches) !== 0) {
            // Clear whitespace and some common characters not required at
            // the end of a to-do message to make the warning more informative.
            $type        = 'CommentFound';
            $todoMessage = trim($matches[1]);
            $todoMessage = trim($todoMessage, '[]().');
            $error       = 'Comment refers to a TODO task';
            $data        = array($todoMessage);
            if ($todoMessage !== '') {
                $type   = 'TaskFound';
                $error .= ' "%s"';
            }

            $phpcsFile->addWarning($error, $stackPtr, $type, $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Checks the cyclomatic complexity (McCabe) for functions.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Checks the cyclomatic complexity (McCabe) for functions.
 *
 * The cyclomatic complexity (also called McCabe code metrics)
 * indicates the complexity within a function by counting
 * the different paths the function includes.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Johann-Peter Hartmann <hartmann@mayflower.de>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2007 Mayflower GmbH
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_Metrics_CyclomaticComplexitySniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A complexity higher than this value will throw a warning.
     *
     * @var int
     */
    public $complexity = 10;

    /**
     * A complexity higer than this value will throw an error.
     *
     * @var int
     */
    public $absoluteComplexity = 20;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_FUNCTION);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $this->currentFile = $phpcsFile;

        $tokens = $phpcsFile->getTokens();

        // Ignore abstract methods.
        if (isset($tokens[$stackPtr]['scope_opener']) === false) {
            return;
        }

        // Detect start and end of this function definition.
        $start = $tokens[$stackPtr]['scope_opener'];
        $end   = $tokens[$stackPtr]['scope_closer'];

        // Predicate nodes for PHP.
        $find = array(
                 'T_CASE',
                 'T_DEFAULT',
                 'T_CATCH',
                 'T_IF',
                 'T_FOR',
                 'T_FOREACH',
                 'T_WHILE',
                 'T_DO',
                 'T_ELSEIF',
                );

        $complexity = 1;

        // Iterate from start to end and count predicate nodes.
        for ($i = ($start + 1); $i < $end; $i++) {
            if (in_array($tokens[$i]['type'], $find) === true) {
                $complexity++;
            }
        }

        if ($complexity > $this->absoluteComplexity) {
            $error = 'Function\'s cyclomatic complexity (%s) exceeds allowed maximum of %s';
            $data  = array(
                      $complexity,
                      $this->absoluteComplexity,
                     );
            $phpcsFile->addError($error, $stackPtr, 'MaxExceeded', $data);
        } else if ($complexity > $this->complexity) {
            $warning = 'Function\'s cyclomatic complexity (%s) exceeds %s; consider refactoring the function';
            $data    = array(
                        $complexity,
                        $this->complexity,
                       );
            $phpcsFile->addWarning($warning, $stackPtr, 'TooHigh', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Checks the nesting level for methods.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Checks the nesting level for methods.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Johann-Peter Hartmann <hartmann@mayflower.de>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2007 Mayflower GmbH
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_Metrics_NestingLevelSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A nesting level than this value will throw a warning.
     *
     * @var int
     */
    public $nestingLevel = 5;

    /**
     * A nesting level than this value will throw an error.
     *
     * @var int
     */
    public $absoluteNestingLevel = 10;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_FUNCTION);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Ignore abstract methods.
        if (isset($tokens[$stackPtr]['scope_opener']) === false) {
            return;
        }

        // Detect start and end of this function definition.
        $start = $tokens[$stackPtr]['scope_opener'];
        $end   = $tokens[$stackPtr]['scope_closer'];

        $nestingLevel = 0;

        // Find the maximum nesting level of any token in the function.
        for ($i = ($start + 1); $i < $end; $i++) {
            $level = $tokens[$i]['level'];
            if ($nestingLevel < $level) {
                $nestingLevel = $level;
            }
        }

        // We subtract the nesting level of the function itself.
        $nestingLevel = ($nestingLevel - $tokens[$stackPtr]['level'] - 1);

        if ($nestingLevel > $this->absoluteNestingLevel) {
            $error = 'Function\'s nesting level (%s) exceeds allowed maximum of %s';
            $data  = array(
                      $nestingLevel,
                      $this->absoluteNestingLevel,
                     );
            $phpcsFile->addError($error, $stackPtr, 'MaxExceeded', $data);
        } else if ($nestingLevel > $this->nestingLevel) {
            $warning = 'Function\'s nesting level (%s) exceeds %s; consider refactoring the function';
            $data    = array(
                        $nestingLevel,
                        $this->nestingLevel,
                       );
            $phpcsFile->addWarning($warning, $stackPtr, 'TooHigh', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_Files_InlineHTMLSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_Files_InlineHTMLSniff.
 *
 * Ensures the whole file is PHP only, with no whitespace or inline HTML anywhere
 * in the file.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_Files_InlineHTMLSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_OPEN_TAG);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        // Make sure this is the first open tag.
        $previousOpenTag = $phpcsFile->findPrevious(T_OPEN_TAG, ($stackPtr - 1));
        if ($previousOpenTag !== false) {
            return;
        }

        $inline = $phpcsFile->findNext(T_INLINE_HTML, 0);
        if ($inline === false) {
            return;
        }

        $error = 'PHP files must only contain PHP code';
        $phpcsFile->addError($error, $inline, 'Found');

    }//end process()


}//end class

<?php
/**
 * Generic_Sniffs_Files_OneClassPerFileSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Andy Grunwald <andygrunwald@gmail.com>
 * @copyright 2010 Andy Grunwald
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Checks that only one class is declared per file.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Andy Grunwald <andygrunwald@gmail.com>
 * @copyright 2010 Andy Grunwald
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_Files_OneClassPerFileSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_CLASS);

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $nextClass = $phpcsFile->findNext($this->register(), ($stackPtr + 1));
        if ($nextClass !== false) {
            $error = 'Only one class is allowed in a file';
            $phpcsFile->addError($error, $nextClass, 'MultipleFound');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_Files_LowercasedFilenameSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Andy Grunwald <andygrunwald@gmail.com>
 * @copyright 2010 Andy Grunwald
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Checks that all file names are lowercased.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Andy Grunwald <andygrunwald@gmail.com>
 * @copyright 2010 Andy Grunwald
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_Files_LowercasedFilenameSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_OPEN_TAG);

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        // We are only interested if this is the first open tag.
        if ($stackPtr !== 0) {
            if ($phpcsFile->findPrevious(T_OPEN_TAG, ($stackPtr - 1)) !== false) {
                return;
            }
        }

        $fileName          = basename($phpcsFile->getFilename());
        $lowercaseFileName = strtolower($fileName);
        if ($fileName !== $lowercaseFileName) {
            $data  = array(
                      $fileName,
                      $lowercaseFileName,
                     );
            $error = 'Filename "%s" doesn\'t match the expected filename "%s"';
            $phpcsFile->addError($error, $stackPtr, 'NotFound', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_Files_LineEndingsSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_Files_LineEndingsSniff.
 *
 * Checks that end of line characters are correct.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_Files_LineEndingsSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                   'CSS',
                                  );

    /**
     * The valid EOL character.
     *
     * @var string
     */
    public $eolChar = '\n';


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_OPEN_TAG);

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        // We are only interested if this is the first open tag.
        if ($stackPtr !== 0) {
            if ($phpcsFile->findPrevious(T_OPEN_TAG, ($stackPtr - 1)) !== false) {
                return;
            }
        }

        $found = $phpcsFile->eolChar;
        $found = str_replace("\n", '\n', $found);
        $found = str_replace("\r", '\r', $found);

        if ($found !== $this->eolChar) {
            // Check for single line files without an EOL. This is a very special
            // case and the EOL char is set to \n when this happens.
            if ($found === '\n') {
                $tokens    = $phpcsFile->getTokens();
                $lastToken = ($phpcsFile->numTokens - 1);
                if ($tokens[$lastToken]['line'] === 1
                    && $tokens[$lastToken]['content'] !== "\n"
                ) {
                    return;
                }
            }

            $error    = 'End of line character is invalid; expected "%s" but found "%s"';
            $expected = $this->eolChar;
            $expected = str_replace("\n", '\n', $expected);
            $expected = str_replace("\r", '\r', $expected);
            $data     = array(
                         $expected,
                         $found,
                        );
            $phpcsFile->addError($error, $stackPtr, 'InvalidEOLChar', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_Files_EndFileNewlineSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_Files_EndFileNewlineSniff.
 *
 * Ensures the file ends with a newline character.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_Files_EndFileNewlineSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                   'CSS',
                                  );


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_OPEN_TAG);

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        // We are only interested if this is the first open tag.
        if ($stackPtr !== 0) {
            if ($phpcsFile->findPrevious(T_OPEN_TAG, ($stackPtr - 1)) !== false) {
                return;
            }
        }

        // Skip to the end of the file.
        $tokens   = $phpcsFile->getTokens();
        $stackPtr = ($phpcsFile->numTokens - 1);

        if ($phpcsFile->tokenizerType === 'JS') {
            $stackPtr--;
        } else if ($phpcsFile->tokenizerType === 'CSS') {
            $stackPtr -= 2;
        }

        $eolCharLen = strlen($phpcsFile->eolChar);
        $lastChars  = substr($tokens[$stackPtr]['content'], ($eolCharLen * -1));
        if ($lastChars !== $phpcsFile->eolChar) {
            $error = 'File must end with a newline character';
            $phpcsFile->addError($error, $stackPtr, 'NotFound');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_Files_ByteOrderMarkSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_Files_ByteOrderMarkSniff.
 *
 * A simple sniff for detecting BOMs that may corrupt application work.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Piotr Karas <office@mediaself.pl>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2010-2011 mediaSELF Sp. z o.o.
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 * @see       http://en.wikipedia.org/wiki/Byte_order_mark
 */
class Generic_Sniffs_Files_ByteOrderMarkSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * List of supported BOM definitions.
     *
     * Use encoding names as keys and hex BOM representations as values.
     *
     * @var array
     */
    public $bomDefinitions = array(
                              'UTF-8'       => 'efbbbf',
                              'UTF-16 (BE)' => 'feff',
                              'UTF-16 (LE)' => 'fffe',
                             );


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_INLINE_HTML);

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process( PHP_CodeSniffer_File $phpcsFile, $stackPtr )
    {
        // The BOM will be the very first token in the file.
        if ($stackPtr !== 0) {
            return;
        }

        $tokens = $phpcsFile->getTokens();

        foreach ($this->bomDefinitions as $bomName => $expectedBomHex) {
            $bomByteLength = (strlen($expectedBomHex) / 2);
            $htmlBomHex    = bin2hex(substr($tokens[$stackPtr]['content'], 0, $bomByteLength));
            if ($htmlBomHex === $expectedBomHex) {
                $errorData = array($bomName);
                $error     = 'File contains %s byte order mark, which may corrupt your application';
                $phpcsFile->addError($error, $stackPtr, 'Found', $errorData);
                break;
            }
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_Files_EndFileNoNewlineSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_Files_EndFileNoNewlineSniff.
 *
 * Ensures the file does not end with a newline character.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_Files_EndFileNoNewlineSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                   'CSS',
                                  );


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_OPEN_TAG);

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        // We are only interested if this is the first open tag.
        if ($stackPtr !== 0) {
            if ($phpcsFile->findPrevious(T_OPEN_TAG, ($stackPtr - 1)) !== false) {
                return;
            }
        }

        // Skip to the end of the file.
        $tokens   = $phpcsFile->getTokens();
        $stackPtr = ($phpcsFile->numTokens - 1);

        if ($phpcsFile->tokenizerType === 'JS') {
            $stackPtr--;
        } else if ($phpcsFile->tokenizerType === 'CSS') {
            $stackPtr -= 2;
        }

        $eolCharLen = strlen($phpcsFile->eolChar);
        $lastChars  = substr($tokens[$stackPtr]['content'], ($eolCharLen * -1));
        if ($lastChars === $phpcsFile->eolChar) {
            $error = 'File must not end with a newline character';
            $phpcsFile->addError($error, $stackPtr, 'Found');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_Files_LineLengthSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_Files_LineLengthSniff.
 *
 * Checks all lines in the file, and throws warnings if they are over 80
 * characters in length and errors if they are over 100. Both these
 * figures can be changed by extending this sniff in your own standard.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_Files_LineLengthSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * The limit that the length of a line should not exceed.
     *
     * @var int
     */
    public $lineLimit = 80;

    /**
     * The limit that the length of a line must not exceed.
     *
     * Set to zero (0) to disable.
     *
     * @var int
     */
    public $absoluteLineLimit = 100;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_OPEN_TAG);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Make sure this is the first open tag.
        $previousOpenTag = $phpcsFile->findPrevious(T_OPEN_TAG, ($stackPtr - 1));
        if ($previousOpenTag !== false) {
            return;
        }

        $tokenCount         = 0;
        $currentLineContent = '';
        $currentLine        = 1;

        $trim = (strlen($phpcsFile->eolChar) * -1);
        for (; $tokenCount < $phpcsFile->numTokens; $tokenCount++) {
            if ($tokens[$tokenCount]['line'] === $currentLine) {
                $currentLineContent .= $tokens[$tokenCount]['content'];
            } else {
                $currentLineContent = substr($currentLineContent, 0, $trim);
                $this->checkLineLength($phpcsFile, ($tokenCount - 1), $currentLineContent);
                $currentLineContent = $tokens[$tokenCount]['content'];
                $currentLine++;
            }
        }

        $currentLineContent = substr($currentLineContent, 0, $trim);
        $this->checkLineLength($phpcsFile, ($tokenCount - 1), $currentLineContent);

    }//end process()


    /**
     * Checks if a line is too long.
     *
     * @param PHP_CodeSniffer_File $phpcsFile   The file being scanned.
     * @param int                  $stackPtr    The token at the end of the line.
     * @param string               $lineContent The content of the line.
     *
     * @return void
     */
    protected function checkLineLength(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $lineContent)
    {
        // If the content is a CVS or SVN id in a version tag, or it is
        // a license tag with a name and URL, or it is an SVN URL, there
        // is nothing the developer can do to shorten the line,
        // so don't throw errors.
        $regex = '~@license|@version[^\$]+\$Id|\$(Head)?URL[:\$]~';
        if (preg_match($regex, $lineContent) !== 0) {
            return;
        }

        if (PHP_CODESNIFFER_ENCODING !== 'iso-8859-1') {
            // Not using the default encoding, so take a bit more care.
            $lineLength = iconv_strlen($lineContent, PHP_CODESNIFFER_ENCODING);
            if ($lineLength === false) {
                // String contained invalid characters, so revert to default.
                $lineLength = strlen($lineContent);
            }
        } else {
            $lineLength = strlen($lineContent);
        }

        if ($this->absoluteLineLimit > 0
            && $lineLength > $this->absoluteLineLimit
        ) {
            $data = array(
                     $this->absoluteLineLimit,
                     $lineLength,
                    );

            $error = 'Line exceeds maximum limit of %s characters; contains %s characters';
            $phpcsFile->addError($error, $stackPtr, 'MaxExceeded', $data);
        } else if ($lineLength > $this->lineLimit) {
            $data = array(
                     $this->lineLimit,
                     $lineLength,
                    );

            $warning = 'Line exceeds %s characters; contains %s characters';
            $phpcsFile->addWarning($warning, $stackPtr, 'TooLong', $data);
        }

    }//end checkLineLength()


}//end class

<?php
/**
 * Generic_Sniffs_Files_OneInterfacePerFileSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Andy Grunwald <andygrunwald@gmail.com>
 * @copyright 2010 Andy Grunwald
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Checks that only one interface is declared per file.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Andy Grunwald <andygrunwald@gmail.com>
 * @copyright 2010 Andy Grunwald
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_Files_OneInterfacePerFileSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_INTERFACE);

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $nextInterface = $phpcsFile->findNext($this->register(), ($stackPtr + 1));
        if ($nextInterface !== false) {
            $error = 'Only one interface is allowed in a file';
            $phpcsFile->addError($error, $nextInterface, 'MultipleFound');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_Strings_UnnecessaryStringConcatSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_Strings_UnnecessaryStringConcatSniff.
 *
 * Checks that two strings are not concatenated together; suggests
 * using one string instead.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_Strings_UnnecessaryStringConcatSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                  );

    /**
     * If true, an error will be thrown; otherwise a warning.
     *
     * @var bool
     */
    public $error = true;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_STRING_CONCAT,
                T_PLUS,
               );

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        // Work out which type of file this is for.
        $tokens = $phpcsFile->getTokens();
        if ($tokens[$stackPtr]['code'] === T_STRING_CONCAT) {
            if ($phpcsFile->tokenizerType === 'JS') {
                return;
            }
        } else {
            if ($phpcsFile->tokenizerType === 'PHP') {
                return;
            }
        }

        $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
        $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
        if ($prev === false || $next === false) {
            return;
        }

        $stringTokens = PHP_CodeSniffer_Tokens::$stringTokens;
        if (in_array($tokens[$prev]['code'], $stringTokens) === true
            && in_array($tokens[$next]['code'], $stringTokens) === true
        ) {
            if ($tokens[$prev]['content'][0] === $tokens[$next]['content'][0]) {
                // Before we throw an error for PHP, allow strings to be
                // combined if they would have < and ? next to each other because
                // this trick is sometimes required in PHP strings.
                if ($phpcsFile->tokenizerType === 'PHP') {
                    $prevChar = substr($tokens[$prev]['content'], -2, 1);
                    $nextChar = $tokens[$next]['content'][1];
                    $combined = $prevChar.$nextChar;
                    if ($combined === '?'.'>' || $combined === '<'.'?') {
                        return;
                    }
                }

                $error = 'String concat is not required here; use a single string instead';
                if ($this->error === true) {
                    $phpcsFile->addError($error, $stackPtr, 'Found');
                } else {
                    $phpcsFile->addWarning($error, $stackPtr, 'Found');
                }
            }
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_PHP_UpperCaseConstantSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_PHP_UpperCaseConstantSniff.
 *
 * Checks that all uses of TRUE, FALSE and NULL are uppercase.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_PHP_UpperCaseConstantSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_TRUE,
                T_FALSE,
                T_NULL,
               );

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Is this a member var name?
        $prevPtr = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
        if ($tokens[$prevPtr]['code'] === T_OBJECT_OPERATOR) {
            return;
        }

        // Is this a class name?
        if ($tokens[$prevPtr]['code'] === T_CLASS
            || $tokens[$prevPtr]['code'] === T_EXTENDS
            || $tokens[$prevPtr]['code'] === T_IMPLEMENTS
            || $tokens[$prevPtr]['code'] === T_NEW
        ) {
            return;
        }

        // Class or namespace?
        if ($tokens[($stackPtr - 1)]['code'] === T_NS_SEPARATOR) {
            return;
        }

        $keyword = $tokens[$stackPtr]['content'];
        if (strtoupper($keyword) !== $keyword) {
            $error = 'TRUE, FALSE and NULL must be uppercase; expected "%s" but found "%s"';
            $data  = array(
                      strtoupper($keyword),
                      $keyword,
                     );
            $phpcsFile->addError($error, $stackPtr, 'Found', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_PHP_DeprecatedFunctionsSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_PHP_DeprecatedFunctionsSniff.
 *
 * Discourages the use of deprecated functions that are kept in PHP for
 * compatibility with older versions.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Sebastian Bergmann <sb@sebastian-bergmann.de>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_PHP_DeprecatedFunctionsSniff extends Generic_Sniffs_PHP_ForbiddenFunctionsSniff
{

    /**
     * A list of forbidden functions with their alternatives.
     *
     * The value is NULL if no alternative exists. IE, the
     * function should just not be used.
     *
     * @var array(string => string|null)
     */
    protected $forbiddenFunctions = array();


    /**
     * Constructor.
     *
     * Uses the Reflection API to get a list of deprecated functions.
     */
    public function __construct()
    {
        $functions = get_defined_functions();

        foreach ($functions['internal'] as $functionName) {
            $function = new ReflectionFunction($functionName);

            if ($function->isDeprecated() === true) {
                $this->forbiddenFunctions[$functionName] = null;
            }
        }

    }//end __construct()


    /**
     * Generates the error or warning for this sniff.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the forbidden function
     *                                        in the token array.
     * @param string               $function  The name of the forbidden function.
     * @param string               $pattern   The pattern used for the match.
     *
     * @return void
     */
    protected function addError($phpcsFile, $stackPtr, $function, $pattern=null)
    {
        $data  = array($function);
        $error = 'Function %s() has been deprecated';
        $type  = 'Deprecated';

        if ($this->error === true) {
            $phpcsFile->addError($error, $stackPtr, $type, $data);
        } else {
            $phpcsFile->addWarning($error, $stackPtr, $type, $data);
        }

    }//end addError()


}//end class

?>
<?php
/**
 * Generic_Sniffs_PHP_LowerCaseConstantSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_PHP_LowerCaseConstantSniff.
 *
 * Checks that all uses of true, false and null are lowercase.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_PHP_LowerCaseConstantSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                  );

    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_TRUE,
                T_FALSE,
                T_NULL,
               );

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Is this a member var name?
        $prevPtr = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
        if ($tokens[$prevPtr]['code'] === T_OBJECT_OPERATOR) {
            return;
        }

        // Is this a class name?
        if ($tokens[$prevPtr]['code'] === T_CLASS
            || $tokens[$prevPtr]['code'] === T_EXTENDS
            || $tokens[$prevPtr]['code'] === T_IMPLEMENTS
            || $tokens[$prevPtr]['code'] === T_NEW
        ) {
            return;
        }

        // Class or namespace?
        if ($tokens[($stackPtr - 1)]['code'] === T_NS_SEPARATOR) {
            return;
        }

        $keyword = $tokens[$stackPtr]['content'];
        if (strtolower($keyword) !== $keyword) {
            $error = 'TRUE, FALSE and NULL must be lowercase; expected "%s" but found "%s"';
            $data  = array(
                      strtolower($keyword),
                      $keyword,
                     );
            $phpcsFile->addError($error, $stackPtr, 'Found', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_PHP_SAPIUsageSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_PHP_SAPIUsageSniff.
 *
 * Ensures the PHP_SAPI constant is used instead of php_sapi_name().
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_PHP_SAPIUsageSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_STRING);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $ignore = array(
                   T_DOUBLE_COLON,
                   T_OBJECT_OPERATOR,
                   T_FUNCTION,
                   T_CONST,
                  );

        $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
        if (in_array($tokens[$prevToken]['code'], $ignore) === true) {
            // Not a call to a PHP function.
            return;
        }

        $function = strtolower($tokens[$stackPtr]['content']);
        if ($function === 'php_sapi_name') {
            $error = 'Use the PHP_SAPI constant instead of calling php_sapi_name()';
            $phpcsFile->addError($error, $stackPtr, 'FunctionFound');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_PHP_ForbiddenFunctionsSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_PHP_ForbiddenFunctionsSniff.
 *
 * Discourages the use of alias functions that are kept in PHP for compatibility
 * with older versions. Can be used to forbid the use of any function.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_PHP_ForbiddenFunctionsSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of forbidden functions with their alternatives.
     *
     * The value is NULL if no alternative exists. IE, the
     * function should just not be used.
     *
     * @var array(string => string|null)
     */
    protected $forbiddenFunctions = array(
                                     'sizeof' => 'count',
                                     'delete' => 'unset',
                                    );

    /**
     * A cache of forbidden function names, for faster lookups.
     *
     * @var array(string)
     */
    protected $forbiddenFunctionNames = array();

    /**
     * If true, forbidden functions will be considered regular expressions.
     *
     * @var bool
     */
    protected $patternMatch = false;

    /**
     * If true, an error will be thrown; otherwise a warning.
     *
     * @var bool
     */
    public $error = true;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        // Everyone has had a chance to figure out what forbidden functions
        // they want to check for, so now we can cache out the list.
        $this->forbiddenFunctionNames = array_keys($this->forbiddenFunctions);

        if ($this->patternMatch === true) {
            foreach ($this->forbiddenFunctionNames as $i => $name) {
                $this->forbiddenFunctionNames[$i] = '/'.$name.'/i';
            }
        }

        return array(T_STRING);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $ignore = array(
                   T_DOUBLE_COLON,
                   T_OBJECT_OPERATOR,
                   T_FUNCTION,
                   T_CONST,
                   T_PUBLIC,
                   T_PRIVATE,
                   T_PROTECTED,
                   T_AS,
                   T_INSTEADOF,
                   T_NS_SEPARATOR,
                  );

        $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
        if (in_array($tokens[$prevToken]['code'], $ignore) === true) {
            // Not a call to a PHP function.
            return;
        }

        $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
        if (in_array($tokens[$nextToken]['code'], $ignore) === true) {
            // Not a call to a PHP function.
            return;
        }

        $function = strtolower($tokens[$stackPtr]['content']);
        $pattern  = null;

        if ($this->patternMatch === true) {
            $count   = 0;
            $pattern = preg_replace(
                $this->forbiddenFunctionNames,
                $this->forbiddenFunctionNames,
                $function,
                1,
                $count
            );

            if ($count === 0) {
                return;
            }

            // Remove the pattern delimiters and modifier.
            $pattern = substr($pattern, 1, -2);
        } else {
            if (in_array($function, $this->forbiddenFunctionNames) === false) {
                return;
            }
        }

        $this->addError($phpcsFile, $stackPtr, $function, $pattern);

    }//end process()


    /**
     * Generates the error or warning for this sniff.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the forbidden function
     *                                        in the token array.
     * @param string               $function  The name of the forbidden function.
     * @param string               $pattern   The pattern used for the match.
     *
     * @return void
     */
    protected function addError($phpcsFile, $stackPtr, $function, $pattern=null)
    {
        $data  = array($function);
        $error = 'The use of function %s() is ';
        if ($this->error === true) {
            $type   = 'Found';
            $error .= 'forbidden';
        } else {
            $type   = 'Discouraged';
            $error .= 'discouraged';
        }

        if ($pattern === null) {
            $pattern = $function;
        }

        if ($this->forbiddenFunctions[$pattern] !== null) {
            $type  .= 'WithAlternative';
            $data[] = $this->forbiddenFunctions[$pattern];
            $error .= '; use %s() instead';
        }

        if ($this->error === true) {
            $phpcsFile->addError($error, $stackPtr, $type, $data);
        } else {
            $phpcsFile->addWarning($error, $stackPtr, $type, $data);
        }

    }//end addError()


}//end class

?>
<?php
/**
 * Generic_Sniffs_PHP_DisallowShortOpenTagSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_PHP_DisallowShortOpenTagSniff.
 *
 * Makes sure that shorthand PHP open tags are not used.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_PHP_DisallowShortOpenTagSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_OPEN_TAG,
                T_OPEN_TAG_WITH_ECHO,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens  = $phpcsFile->getTokens();
        $openTag = $tokens[$stackPtr];

        if ($openTag['content'] === '<?') {
            $error = 'Short PHP opening tag used; expected "<?php" but found "%s"';
            $data  = array($openTag['content']);
            $phpcsFile->addError($error, $stackPtr, 'Found', $data);
        }

        if ($openTag['code'] === T_OPEN_TAG_WITH_ECHO) {
            $nextVar = $tokens[$phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr + 1), null, true)];
            $error   = 'Short PHP opening tag used with echo; expected "<?php echo %s ..." but found "%s %s ..."';
            $data = array(
                     $nextVar['content'],
                     $openTag['content'],
                     $nextVar['content'],
                    );
            $phpcsFile->addError($error, $stackPtr, 'EchoFound', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_PHP_LowerCaseKeywordSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_PHP_LowerCaseKeywordSniff.
 *
 * Checks that all PHP keywords are lowercase.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_PHP_LowerCaseKeywordSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_HALT_COMPILER,
                T_ABSTRACT,
                T_ARRAY,
                T_AS,
                T_BREAK,
                T_CALLABLE,
                T_CASE,
                T_CATCH,
                T_CLASS,
                T_CLONE,
                T_CONST,
                T_CONTINUE,
                T_DECLARE,
                T_DEFAULT,
                T_DO,
                T_ECHO,
                T_ELSE,
                T_ELSEIF,
                T_EMPTY,
                T_ENDDECLARE,
                T_ENDFOR,
                T_ENDFOREACH,
                T_ENDIF,
                T_ENDSWITCH,
                T_ENDWHILE,
                T_EVAL,
                T_EXIT,
                T_EXTENDS,
                T_FINAL,
                T_FINALLY,
                T_FOR,
                T_FOREACH,
                T_FUNCTION,
                T_GLOBAL,
                T_GOTO,
                T_IF,
                T_IMPLEMENTS,
                T_INCLUDE,
                T_INCLUDE_ONCE,
                T_INSTANCEOF,
                T_INSTEADOF,
                T_INTERFACE,
                T_ISSET,
                T_LIST,
                T_LOGICAL_AND,
                T_LOGICAL_OR,
                T_LOGICAL_XOR,
                T_NAMESPACE,
                T_NEW,
                T_PRINT,
                T_PRIVATE,
                T_PROTECTED,
                T_PUBLIC,
                T_REQUIRE,
                T_REQUIRE_ONCE,
                T_RETURN,
                T_STATIC,
                T_SWITCH,
                T_THROW,
                T_TRAIT,
                T_TRY,
                T_UNSET,
                T_USE,
                T_VAR,
                T_WHILE,
               );

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens  = $phpcsFile->getTokens();
        $keyword = $tokens[$stackPtr]['content'];
        if (strtolower($keyword) !== $keyword) {
            $error = 'PHP keywords must be lowercase; expected "%s" but found "%s"';
            $data  = array(
                      strtolower($keyword),
                      $keyword,
                     );
            $phpcsFile->addError($error, $stackPtr, 'Found', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_PHP_ClosingPHPTagSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Stefano Kowalke <blueduck@gmx.net>
 * @copyright 2010 Stefano Kowalke
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Checks that open PHP tags are paired with closing tags.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Stefano Kowalke <blueduck@gmx.net>
 * @copyright 2010 Stefano Kowalke
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_PHP_ClosingPHPTagSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_OPEN_TAG);

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $closeTag = $phpcsFile->findNext(T_CLOSE_TAG, $stackPtr);
        if ($closeTag === false) {
            $error = 'The PHP open tag does not have a corresponding PHP close tag';
            $phpcsFile->addError($error, $stackPtr, 'NotFound');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_PHP_CharacterBeforePHPOpeningTagSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Andy Grunwald <andygrunwald@gmail.com>
 * @copyright 2010 Andy Grunwald
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Checks that the opening PHP tag is the first content in a file.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Andy Grunwald <andygrunwald@gmail.com>
 * @copyright 2010 Andy Grunwald
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_PHP_CharacterBeforePHPOpeningTagSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_OPEN_TAG);

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        if ($stackPtr > 0) {
            $error = 'The opening PHP tag must be the first content in the file';
            $phpcsFile->addError($error, $stackPtr, 'Found');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_PHP_NoSilencedErrorsSniff
 *
 * PHP version 5
 *
 * @category PHP
 * @package  PHP_CodeSniffer
 * @author   Andy Brockhurst <abrock@yahoo-inc.com>
 * @license  https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link     http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_PHP_NoSilencedErrorsSniff.
 *
 * Throws an error or warning when any code prefixed with an asperand is encountered.
 *
 * <code>
 *  if (@in_array($array, $needle))
 *  {
 *      doSomething();
 *  }
 * </code>
 *
 * @category PHP
 * @package  PHP_CodeSniffer
 * @author   Andy Brockhurst <abrock@yahoo-inc.com>
 * @license  https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version  Release: @package_version@
 * @link     http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_PHP_NoSilencedErrorsSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * If true, an error will be thrown; otherwise a warning.
     *
     * @var bool
     */
    public $error = false;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_ASPERAND);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $error = 'Silencing errors is forbidden';
        if ($this->error === true) {
            $error = 'Silencing errors is forbidden';
            $phpcsFile->addError($error, $stackPtr, 'Forbidden');
        } else {
            $error = 'Silencing errors is discouraged';
            $phpcsFile->addWarning($error, $stackPtr, 'Discouraged');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_Formatting_SpaceAfterCastSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_Formatting_SpaceAfterCastSniff.
 *
 * Ensures there is a single space after cast tokens.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_Formatting_SpaceAfterCastSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return PHP_CodeSniffer_Tokens::$castTokens;

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) {
            $error = 'A cast statement must be followed by a single space';
            $phpcsFile->addError($error, $stackPtr, 'NoSpace');
            return;
        }

        if ($tokens[($stackPtr + 1)]['content'] !== ' ') {
            $error = 'A cast statement must be followed by a single space';
            $phpcsFile->addError($error, $stackPtr, 'TooMuchSpace');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_Formatting_DisallowMultipleStatementsSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_Formatting_DisallowMultipleStatementsSniff.
 *
 * Ensures each statement is on a line by itself.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_Formatting_DisallowMultipleStatementsSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_SEMICOLON);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $prev = $phpcsFile->findPrevious(T_SEMICOLON, ($stackPtr - 1));
        if ($prev === false) {
            return;
        }

        // Ignore multiple statements in a FOR condition.
        if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) {
            foreach ($tokens[$stackPtr]['nested_parenthesis'] as $bracket) {
                if (isset($tokens[$bracket]['parenthesis_owner']) === false) {
                    // Probably a closure sitting inside a function call.
                    continue;
                }

                $owner = $tokens[$bracket]['parenthesis_owner'];
                if ($tokens[$owner]['code'] === T_FOR) {
                    return;
                }
            }
        }

        if ($tokens[$prev]['line'] === $tokens[$stackPtr]['line']) {
            $error = 'Each PHP statement must be on a line by itself';
            $phpcsFile->addError($error, $stackPtr, 'SameLine');
            return;
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_Formatting_NoSpaceAfterCastSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_Formatting_NoSpaceAfterCastSniff.
 *
 * Ensures there is no space after cast tokens.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_Formatting_NoSpaceAfterCastSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return PHP_CodeSniffer_Tokens::$castTokens;

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) {
            $error = 'A cast statement must not be followed by a space';
            $phpcsFile->addError($error, $stackPtr, 'SpaceFound');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Generic_Sniffs_Formatting_MultipleStatementAlignmentSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Generic_Sniffs_Formatting_MultipleStatementAlignmentSniff.
 *
 * Checks alignment of assignments. If there are multiple adjacent assignments,
 * it will check that the equals signs of each assignment are aligned. It will
 * display a warning to advise that the signs should be aligned.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_Formatting_MultipleStatementAlignmentSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                  );

    /**
     * If true, an error will be thrown; otherwise a warning.
     *
     * @var bool
     */
    public $error = false;

    /**
     * The maximum amount of padding before the alignment is ignored.
     *
     * If the amount of padding required to align this assignment with the
     * surrounding assignments exceeds this number, the assignment will be
     * ignored and no errors or warnings will be thrown.
     *
     * @var int
     */
    public $maxPadding = 1000;

    /**
     * If true, multi-line assignments are not checked.
     *
     * @var int
     */
    public $ignoreMultiLine = false;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return PHP_CodeSniffer_Tokens::$assignmentTokens;

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Ignore assignments used in a condition, like an IF or FOR.
        if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) {
            foreach ($tokens[$stackPtr]['nested_parenthesis'] as $start => $end) {
                if (isset($tokens[$start]['parenthesis_owner']) === true) {
                    return;
                }
            }
        }

        /*
            By this stage, it is known that there is an assignment on this line.
            We only want to process the block once we reach the last assignment,
            so we need to determine if there are more to follow.
        */

        // The assignment may span over multiple lines, so look for the
        // end of the assignment so we can check assignment blocks correctly.
        $lineEnd = $phpcsFile->findNext(T_SEMICOLON, ($stackPtr + 1));

        $nextAssign = $phpcsFile->findNext(
            PHP_CodeSniffer_Tokens::$assignmentTokens,
            ($lineEnd + 1)
        );

        if ($nextAssign !== false) {
            $isAssign = true;
            if ($tokens[$nextAssign]['line'] === ($tokens[$lineEnd]['line'] + 1)) {
                // Assignment may be in the same block as this one. Just make sure
                // it is not used in a condition, like an IF or FOR.
                if (isset($tokens[$nextAssign]['nested_parenthesis']) === true) {
                    foreach ($tokens[$nextAssign]['nested_parenthesis'] as $start => $end) {
                        if (isset($tokens[$start]['parenthesis_owner']) === true) {
                            // Not an assignment.
                            $isAssign = false;
                            break;
                        }
                    }
                }

                if ($isAssign === true) {
                    return;
                }
            }
        }

        // Getting here means that this is the last in a block of statements.
        $assignments    = array();
        $assignments[]  = $stackPtr;
        $prevAssignment = $stackPtr;
        $lastLine       = $tokens[$stackPtr]['line'];

        while (($prevAssignment = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$assignmentTokens, ($prevAssignment - 1))) !== false) {

            // We are not interested in double arrows as they assign values inside
            // arrays and loops and do not use the same indentation rules.
            if ($tokens[$prevAssignment]['code'] === T_DOUBLE_ARROW) {
                continue;
            }

            // The assignment's end token must be on the line directly
            // above the current one to be in the same assignment block.
            $lineEnd = $phpcsFile->findNext(T_SEMICOLON, ($prevAssignment + 1));

            // And the end token must actually belong to this assignment.
            $nextOpener = $phpcsFile->findNext(
                PHP_CodeSniffer_Tokens::$scopeOpeners,
                ($prevAssignment + 1)
            );

            if ($nextOpener !== false && $nextOpener < $lineEnd) {
                break;
            }

            if ($tokens[$lineEnd]['line'] !== ($lastLine - 1)) {
                break;
            }

            // Make sure it is not assigned inside a condition (eg. IF, FOR).
            if (isset($tokens[$prevAssignment]['nested_parenthesis']) === true) {
                foreach ($tokens[$prevAssignment]['nested_parenthesis'] as $start => $end) {
                    if (isset($tokens[$start]['parenthesis_owner']) === true) {
                        break(2);
                    }
                }
            }

            $assignments[] = $prevAssignment;
            $lastLine      = $tokens[$prevAssignment]['line'];
        }//end while

        $assignmentData      = array();
        $maxAssignmentLength = 0;
        $maxVariableLength   = 0;

        foreach ($assignments as $assignment) {
            $prev = $phpcsFile->findPrevious(
                PHP_CodeSniffer_Tokens::$emptyTokens,
                ($assignment - 1),
                null,
                true
            );

            $endColumn = $tokens[($prev + 1)]['column'];

            if ($maxVariableLength < $endColumn) {
                $maxVariableLength = $endColumn;
            }

            if ($maxAssignmentLength < strlen($tokens[$assignment]['content'])) {
                $maxAssignmentLength = strlen($tokens[$assignment]['content']);
            }

            $assignmentData[$assignment]
                = array(
                   'variable_length'   => $endColumn,
                   'assignment_length' => strlen($tokens[$assignment]['content']),
                  );
        }//end foreach

        foreach ($assignmentData as $assignment => $data) {
            if ($data['assignment_length'] === $maxAssignmentLength) {
                if ($data['variable_length'] === $maxVariableLength) {
                    // The assignment is the longest possible, so the column that
                    // everything has to align to is based on it.
                    $column = ($maxVariableLength + 1);
                    break;
                } else {
                    // The assignment token is the longest out of all of the
                    // assignments, but the variable name is not, so the column
                    // the start at can go back more to cover the space
                    // between the variable name and the assignment operator.
                    $column = ($maxVariableLength - ($maxAssignmentLength - 1) + 1);
                }
            }
        }

        // Determine the actual position that each equals sign should be in.
        foreach ($assignments as $assignment) {
            // Actual column takes into account the length of the assignment operator.
            $actualColumn = ($column + $maxAssignmentLength - strlen($tokens[$assignment]['content']));
            if ($tokens[$assignment]['column'] !== $actualColumn) {
                $prev = $phpcsFile->findPrevious(
                    PHP_CodeSniffer_Tokens::$emptyTokens,
                    ($assignment - 1),
                    null,
                    true
                );

                $expected = ($actualColumn - $tokens[($prev + 1)]['column']);

                if ($tokens[$assignment]['line'] !== $tokens[$prev]['line']) {
                    // Instead of working out how many spaces there are
                    // across new lines, the error message becomes more
                    // generic below.
                    $found = null;
                } else {
                    $found = ($tokens[$assignment]['column'] - $tokens[($prev + 1)]['column']);
                }

                // If the expected number of spaces for alignment exceeds the
                // maxPadding rule, we just check for a single space as no
                // alignment is required.
                if ($expected > $this->maxPadding) {
                    if ($found === 1) {
                        continue;
                    } else {
                        $expected = 1;
                    }
                }

                // Skip multi-line assignments if required.
                if ($found === null && $this->ignoreMultiLine === true) {
                    continue;
                }

                $expected .= ($expected === 1) ? ' space' : ' spaces';
                if ($found === null) {
                    $found = 'a new line';
                } else {
                    $found .= ($found === 1) ? ' space' : ' spaces';
                }

                if (count($assignments) === 1) {
                    $type  = 'Incorrect';
                    $error = 'Equals sign not aligned correctly; expected %s but found %s';
                } else {
                    $type  = 'NotSame';
                    $error = 'Equals sign not aligned with surrounding assignments; expected %s but found %s';
                }

                $errorData = array(
                              $expected,
                              $found,
                             );

                if ($this->error === true) {
                    $phpcsFile->addError($error, $assignment, $type, $errorData);
                } else {
                    $phpcsFile->addWarning($error, $assignment, $type.'Warning', $errorData);
                }
            }//end if
        }//end foreach

    }//end process()


}//end class

?>
<?php
/**
 * Reports errors if the same class or interface name is used in multiple files.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Reports errors if the same class or interface name is used in multiple files.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Sniffs_Classes_DuplicateClassNameSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * List of classes that have been found during checking.
     *
     * @var array
     */
    public $foundClasses = array();


    /**
     * Registers the tokens that this sniff wants to listen for.
     *
     * @return array(integer)
     */
    public function register()
    {
        return array(T_OPEN_TAG);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $namespace  = '';
        $findTokens = array(
                       T_CLASS,
                       T_INTERFACE,
                       T_NAMESPACE,
                       T_CLOSE_TAG,
                      );

        $stackPtr = $phpcsFile->findNext($findTokens, ($stackPtr + 1));
        while ($stackPtr !== false) {
            if ($tokens[$stackPtr]['code'] === T_CLOSE_TAG) {
                // We can stop here. The sniff will continue from the next open
                // tag when PHPCS reaches that token, if there is one.
                return;
            }

            // Keep track of what namespace we are in.
            if ($tokens[$stackPtr]['code'] === T_NAMESPACE) {
                $nsEnd = $phpcsFile->findNext(
                    array(
                     T_NS_SEPARATOR,
                     T_STRING,
                     T_WHITESPACE,
                    ),
                    ($stackPtr + 1),
                    null,
                    true
                );

                $namespace = trim($phpcsFile->getTokensAsString(($stackPtr + 1), ($nsEnd - $stackPtr - 1)));
                $stackPtr  = $nsEnd;
            } else {
                $nameToken = $phpcsFile->findNext(T_STRING, $stackPtr);
                $name      = $tokens[$nameToken]['content'];
                if ($namespace !== '') {
                    $name = $namespace.'\\'.$name;
                }

                $compareName = strtolower($name);
                if (isset($this->foundClasses[$compareName]) === true) {
                    $type  = strtolower($tokens[$stackPtr]['content']);
                    $file  = $this->foundClasses[$compareName]['file'];
                    $line  = $this->foundClasses[$compareName]['line'];
                    $error = 'Duplicate %s name "%s" found; first defined in %s on line %s';
                    $data  = array(
                              $type,
                              $name,
                              $file,
                              $line,
                             );
                    $phpcsFile->addWarning($error, $stackPtr, 'Found', $data);
                } else {
                    $this->foundClasses[$compareName] = array(
                                                         'file' => $phpcsFile->getFilename(),
                                                         'line' => $tokens[$stackPtr]['line'],
                                                        );
                }
            }

            $stackPtr = $phpcsFile->findNext($findTokens, ($stackPtr + 1));
        }//end while

    }//end process()


}//end class

?>
<documentation title="CSSLint">
    <standard>
    <![CDATA[
    All css files should pass the basic csslint tests.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Valid CSS Syntax is used.">
        <![CDATA[
.foo: { width: 100<em></em>%; }
        ]]>
        </code>
        <code title="Invalid: The CSS has a typo in it.">
        <![CDATA[
.foo: { width: 100<em> </em>%; }
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="JSHint">
    <standard>
    <![CDATA[
    All javascript files should pass basic JSHint tests.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Valid JS Syntax is used.">
        <![CDATA[
<em>var</em> foo = 5;
        ]]>
        </code>
        <code title="Invalid: The Javascript is using an undefined variable.">
        <![CDATA[
<em></em>foo = 5;
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Closure Linter">
    <standard>
    <![CDATA[
    All javascript files should pass basic Closure Linter tests.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Valid JS Syntax is used.">
        <![CDATA[
var foo = [1, 2<em></em>];
        ]]>
        </code>
        <code title="Invalid: Trailing comma in a javascript array.">
        <![CDATA[
var foo = [1, 2<em>,</em>];
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Subversion Properties">
    <standard>
    <![CDATA[
    All php files in a subversion repository should have the svn:keywords property set to 'Author Id Revision' and the svn:eol-style property set to 'native'.
    ]]>
    </standard>
</documentation>
<documentation title="Useless Overriding Methods">
    <standard>
    <![CDATA[
    Methods should not be defined that only call the parent method.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: A method that extends functionality on a parent method.">
        <![CDATA[
final class Foo
{
    public function bar()
    {
        parent::bar();
        <em>$this->doSomethingElse();</em>
    }
}
        ]]>
        </code>
        <code title="Invalid: An overriding method that only calls the parent.">
        <![CDATA[
final class Foo
{
    public function bar()
    {
        <em>parent::bar();</em>
    }
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Unnecessary Final Modifiers">
    <standard>
    <![CDATA[
    Methods should not be declared final inside of classes that are declared final.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: A method in a final class is not marked final.">
        <![CDATA[
final class Foo
{
    public function bar()
    {
    }
}
        ]]>
        </code>
        <code title="Invalid: A method in a final class is also marked final.">
        <![CDATA[
final class Foo
{
    public <em>final</em> function bar()
    {
    }
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Empty Statements">
    <standard>
    <![CDATA[
    Control Structures must have at least one statment inside of the body.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: There is a statement inside the control structure.">
        <![CDATA[
if ($test) {
    $var = 1;
}
        ]]>
        </code>
        <code title="Invalid: The control structure has no statements.">
        <![CDATA[
if ($test) {
    <em>// do nothing</em>
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Condition-Only For Loops">
    <standard>
    <![CDATA[
    For loops that have only a second expression (the condition) should be converted to while loops.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: A for loop is used with all three expressions.">
        <![CDATA[
for (<em>$i = 0</em>; $i < 10; <em>$i++</em>) {
    echo "{$i}\n";
}
        ]]>
        </code>
        <code title="Invalid: A for loop is used without a first or third expression.">
        <![CDATA[
for (<em></em>;$test;<em></em>) {
    $test = doSomething();
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Jumbled Incrementers">
    <standard>
    <![CDATA[
    Incrementers in nested loops should use different variable names.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Two different variables being used to increment.">
        <![CDATA[
for ($i = 0; $i < 10; <em>$i++</em>) {
    for ($j = 0; $j < 10; <em>$j++</em>) {
    }
}
        ]]>
        </code>
        <code title="Invalid: Inner incrementer is the same variable name as the outer one.">
        <![CDATA[
for ($i = 0; $i < 10; <em>$i++</em>) {
    for ($j = 0; $j < 10; <em>$i++</em>) {
    }
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="For Loops With Function Calls in the Test">
    <standard>
    <![CDATA[
    For loops should not call functions inside the test for the loop when they can be computed beforehand.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: A for loop that determines its end condition before the loop starts.">
        <![CDATA[
<em>$end = count($foo);</em>
for ($i = 0; $i < $end; $i++) {
    echo $foo[$i]."\n";
}
        ]]>
        </code>
        <code title="Invalid: A for loop that unnecessarily computes the same value on every iteration.">
        <![CDATA[
for ($i = 0; $i < <em>count($foo)</em>; $i++) {
    echo $foo[$i]."\n";
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Unconditional If Statements">
    <standard>
    <![CDATA[
    If statements that are always evaluated should not be used.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: An if statement that only executes conditionally.">
        <![CDATA[
if (<em>$test</em>) {
    $var = 1;
}
        ]]>
        </code>
        <code title="Invalid: An if statement that is always performed.">
        <![CDATA[
if (<em>true</em>) {
    $var = 1;
}
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: An if statement that only executes conditionally.">
        <![CDATA[
if (<em>$test</em>) {
    $var = 1;
}
        ]]>
        </code>
        <code title="Invalid: An if statement that is never performed.">
        <![CDATA[
if (<em>false</em>) {
    $var = 1;
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Unused function parameters">
    <standard>
    <![CDATA[
    All parameters in a functions signature should be used within the function.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: All the parameters are used.">
        <![CDATA[
function addThree($a, $b, $c)
{
    return <em>$a + $b + $c</em>;
}
        ]]>
        </code>
        <code title="Invalid: One of the parameters is not being used.">
        <![CDATA[
function addThree($a, $b, $c)
{
    return <em>$a + $b</em>;
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Constant Names">
    <standard>
    <![CDATA[
     Constants should always be all-uppercase, with underscores to separate words.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: all uppercase">
        <![CDATA[
define('<em>FOO_CONSTANT</em>', 'foo');

class FooClass
{
    const <em>FOO_CONSTANT</em> = 'foo';
}
        ]]>
        </code>
        <code title="Invalid: mixed case">
        <![CDATA[
define('<em>Foo_Constant</em>', 'foo');

class FooClass
{
    const <em>foo_constant</em> = 'foo';
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Constructor name">
    <standard>
    <![CDATA[
    Constructors should be named __construct, not after the class.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: The constructor is named __construct.">
        <![CDATA[
class Foo
{
    function <em>__construct</em>()
    {
    }
}
        ]]>
        </code>
        <code title="Invalid: The old style class name constructor is used.">
        <![CDATA[
class Foo
{
    function <em>Foo</em>()
    {
    }
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="camelCaps Function Names">
    <standard>
    <![CDATA[
    Functions should use camelCaps format for their names. Only PHP's magic methods should use a double underscore prefix.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: A function in camelCaps format.">
        <![CDATA[
function <em>doSomething</em>()
{
}
        ]]>
        </code>
        <code title="Invalid: A function in snake_case format.">
        <![CDATA[
function <em>do_something</em>()
{
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="No Space Indentation">
    <standard>
    <![CDATA[
    Tabs should be used for indentation instead of spaces.
    ]]>
    </standard>
</documentation>
<documentation title="Scope Indentation">
    <standard>
    <![CDATA[
    Indentation for control structures, classes, and functions should be 4 spaces per level.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: 4 spaces are used to indent a control structure.">
        <![CDATA[
if ($test) {
<em>    </em>$var = 1;
}
        ]]>
        </code>
        <code title="Invalid: 8 spaces are used to indent a control structure.">
        <![CDATA[
if ($test) {
<em>        </em>$var = 1;
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="No Tab Indentation">
    <standard>
    <![CDATA[
    Spaces should be used for indentation instead of tabs.
    ]]>
    </standard>
</documentation>
<documentation title="Call-Time Pass-By-Reference">
    <standard>
    <![CDATA[
    Call-time pass-by-reference is not allowed. It should be declared in the function definition.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Pass-by-reference is specified in the function definition.">
        <![CDATA[
function foo(<em>&</em>$bar)
{
    $bar++;
}

$baz = 1;
foo($baz);
        ]]>
        </code>
        <code title="Invalid: Pass-by-reference is done in the call to a function.">
        <![CDATA[
function foo($bar)
{
    $bar++;
}

$baz = 1;
foo(<em>&</em>$baz);
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Opening Brace in Function Declarations">
    <standard>
    <![CDATA[
    Function declarations follow the "Kernighan/Ritchie style". The function brace is on the same line as the function declaration. One space is required between the closing parenthesis and the brace.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: brace on same line">
        <![CDATA[
function fooFunction($arg1, $arg2 = '')<em> {</em>
    ...
}
        ]]>
        </code>
        <code title="Invalid: brace on next line">
        <![CDATA[
function fooFunction($arg1, $arg2 = '')
<em>{</em>
    ...
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Opening Brace in Function Declarations">
    <standard>
    <![CDATA[
    Function declarations follow the "BSD/Allman style". The function brace is on the line following the function declaration and is indented to the same column as the start of the function declaration.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: brace on next line">
        <![CDATA[
function fooFunction($arg1, $arg2 = '')
<em>{</em>
    ...
}
        ]]>
        </code>
        <code title="Invalid: brace on same line">
        <![CDATA[
function fooFunction($arg1, $arg2 = '') <em>{</em>
    ...
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Function Argument Spacing">
    <standard>
    <![CDATA[
    Function arguments should have one space after a comma, and single spaces surrounding the equals sign for default values.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Single spaces after a comma.">
        <![CDATA[
function foo($bar,<em> </em>$baz)
{
}
        ]]>
        </code>
        <code title="Invalid: No spaces after a comma.">
        <![CDATA[
function foo($bar,<em></em>$baz)
{
}
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Single spaces around an equals sign in function declaration.">
        <![CDATA[
function foo($bar, $baz<em> </em>=<em> </em>true)
{
}
        ]]>
        </code>
        <code title="Invalid: No spaces around an equals sign in function declaration.">
        <![CDATA[
function foo($bar, $baz<em></em>=<em></em>true)
{
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Inline Control Structures">
    <standard>
    <![CDATA[
    Control Structures should use braces.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Braces are used around the control structure.">
        <![CDATA[
if ($test) <em>{</em>
    $var = 1;
<em>}</em>
        ]]>
        </code>
        <code title="Invalid: No braces are used for the control structure..">
        <![CDATA[
if ($test)
    $var = 1;
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Todo Comments">
    <standard>
    <![CDATA[
    TODO Statements should be taken care of.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: A comment without a todo.">
        <![CDATA[
// <em>Handle strange case</em>
if ($test) {
    $var = 1;
}
        ]]>
        </code>
        <code title="Invalid: A todo comment.">
        <![CDATA[
// <em>TODO</em>: This needs to be fixed!
if ($test) {
    $var = 1;
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Todo Comments">
    <standard>
    <![CDATA[
    FIXME Statements should be taken care of.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: A comment without a fixme.">
        <![CDATA[
// <em>Handle strange case</em>
if ($test) {
    $var = 1;
}
        ]]>
        </code>
        <code title="Invalid: A fixme comment.">
        <![CDATA[
// <em>FIXME</em>: This needs to be fixed!
if ($test) {
    $var = 1;
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Nesting Level">
    <standard>
    <![CDATA[
    Functions should not have a nesting level greater than 10, and should try to stay below 5.
    ]]>
    </standard>
</documentation>
<documentation title="Cyclomatic Complexity">
    <standard>
    <![CDATA[
    Functions should not have a cyclomatic complexity greater than 20, and should try to stay below a complexity of 10.
    ]]>
    </standard>
</documentation>
<documentation title="One Interface Per File">
    <standard>
    <![CDATA[
    There should only be one interface defined in a file.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Only one interface in the file.">
        <![CDATA[
<?php
<em>interface Foo</em>
{
}
        ]]>
        </code>
        <code title="Invalid: Multiple interfaces defined in one file.">
        <![CDATA[
<?php
<em>interface Foo</em>
{
}

<em>interface Bar</em>
{
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Inline HTML">
    <standard>
    <![CDATA[
    Files that contain php code should only have php code and should not have any "inline html".
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: A php file with only php code in it.">
        <![CDATA[
<?php
$foo = 'bar';
echo $foo . 'baz';
        ]]>
        </code>
        <code title="Invalid: A php file with html in it outside of the php tags.">
        <![CDATA[
<em>some string here</em>
<?php
$foo = 'bar';
echo $foo . 'baz';
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="One Class Per File">
    <standard>
    <![CDATA[
    There should only be one class defined in a file.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Only one class in the file.">
        <![CDATA[
<?php
<em>class Foo</em>
{
}
        ]]>
        </code>
        <code title="Invalid: Multiple classes defined in one file.">
        <![CDATA[
<?php
<em>class Foo</em>
{
}

<em>class Bar</em>
{
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Line Endings">
    <standard>
    <![CDATA[
    Unix-style endlines are preferred ("\n" instead of "\r\n").
    ]]>
    </standard>
</documentation>
<documentation title="No End of File Newline">
    <standard>
    <![CDATA[
    Files should not end with a newline character.
    ]]>
    </standard>
</documentation>
<documentation title="Line Length">
    <standard>
    <![CDATA[
    It is recommended to keep lines at approximately 80 characters long for better code readability.
    ]]>
    </standard>
</documentation>
<documentation title="End of File Newline">
    <standard>
    <![CDATA[
    Files should end with a newline character.
    ]]>
    </standard>
</documentation>
<documentation title="Lowercased Filenames">
    <standard>
    <![CDATA[
    Lowercase filenames are required.
    ]]>
    </standard>
</documentation>
<documentation title="Byte Order Marks">
    <standard>
    <![CDATA[
    Byte Order Marks that may corrupt your application should not be used.  These include 0xefbbbf (UTF-8), 0xfeff (UTF-16 BE) and 0xfffe (UTF-16 LE).
    ]]>
    </standard>
</documentation>
<documentation title="Unnecessary String Concatenation">
    <standard>
    <![CDATA[
    Strings should not be concatenated together.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: A string can be concatenated with an expression.">
        <![CDATA[
echo '5 + 2 = ' . (5 + 2);
        ]]>
        </code>
        <code title="Invalid: Strings should not be concatenated together.">
        <![CDATA[
echo 'Hello' . ' ' . 'World';
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="SAPI Usage">
    <standard>
    <![CDATA[
    The PHP_SAPI constant should be used instead of php_sapi_name().
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: PHP_SAPI is used.">
        <![CDATA[
if (<em>PHP_SAPI</em> === 'cli') {
    echo "Hello, CLI user.";
}
        ]]>
        </code>
        <code title="Invalid: php_sapi_name() is used.">
        <![CDATA[
if (<em>php_sapi_name()</em> === 'cli') {
    echo "Hello, CLI user.";
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Deprecated Functions">
    <standard>
    <![CDATA[
    Deprecated functions should not be used.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: A non-deprecated function is used.">
        <![CDATA[
$foo = <em>explode</em>('a', $bar);
        ]]>
        </code>
        <code title="Invalid: A deprecated function is used.">
        <![CDATA[
$foo = <em>split</em>('a', $bar);
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Opening Tag at Start of File">
    <standard>
    <![CDATA[
    The opening php tag should be the first item in the file.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: A file starting with an opening php tag.">
        <![CDATA[
<em></em><?php
echo 'Foo';
        ]]>
        </code>
        <code title="Invalid: A file with content before the opening php tag.">
        <![CDATA[
<em>Beginning content</em>
<?php
echo 'Foo';
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="PHP Constants">
    <standard>
    <![CDATA[
    The <em>true</em>, <em>false</em> and <em>null</em> constants must always be uppercase.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: uppercase constants">
        <![CDATA[
if ($var === <em>FALSE</em> || $var === <em>NULL</em>) {
    $var = <em>TRUE</em>;
}
        ]]>
        </code>
        <code title="Invalid: lowercase constants">
        <![CDATA[
if ($var === <em>false</em> || $var === <em>null</em>) {
    $var = <em>true</em>;
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Forbidden Functions">
    <standard>
    <![CDATA[
    The forbidden functions sizeof and delete should not be used.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: count is used in place of sizeof.">
        <![CDATA[
$foo = <em>count</em>($bar);
        ]]>
        </code>
        <code title="Invalid: sizeof is used.">
        <![CDATA[
$foo = <em>sizeof</em>($bar);
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Silenced Errors">
    <standard>
    <![CDATA[
    Suppressing Errors is not allowed.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: isset is used to verify that a variable exists before trying to use it.">
        <![CDATA[
if (<em>isset($foo)</em> && $foo) {
    echo "Hello\n";
}
        ]]>
        </code>
        <code title="Invalid: Errors are suppressed.">
        <![CDATA[
if (<em>@</em>$foo) {
    echo "Hello\n";
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="PHP Code Tags">
    <standard>
    <![CDATA[
    Always use <?php ?> to delimit PHP code, not the <? ?> shorthand. This is the most portable way to include PHP code on differing operating systems and setups.
    ]]>
    </standard>
</documentation>
<documentation title="Lowercase Keywords">
    <standard>
    <![CDATA[
    All PHP keywords should be lowercase.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Lowercase array keyword used.">
        <![CDATA[
$foo = <em>array</em>();
        ]]>
        </code>
        <code title="Invalid: Non-lowercase array keyword used.">
        <![CDATA[
$foo = <em>Array</em>();
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Closing PHP Tags">
    <standard>
    <![CDATA[
    All opening php tags should have a corresponding closing tag.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: A closing tag paired with it's opening tag.">
        <![CDATA[
<em><?php</em>
echo 'Foo';
<em>?></em>
        ]]>
        </code>
        <code title="Invalid: No closing tag paired with the opening tag.">
        <![CDATA[
<em><?php</em>
echo 'Foo';
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="PHP Constants">
    <standard>
    <![CDATA[
    The <em>true</em>, <em>false</em> and <em>null</em> constants must always be lowercase.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: lowercase constants">
        <![CDATA[
if ($var === <em>false</em> || $var === <em>null</em>) {
    $var = <em>true</em>;
}
        ]]>
        </code>
        <code title="Invalid: uppercase constants">
        <![CDATA[
if ($var === <em>FALSE</em> || $var === <em>NULL</em>) {
    $var = <em>TRUE</em>;
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Aligning Blocks of Assignments">
    <standard>
    <![CDATA[
      There should be one space on either side of an equals sign used to assign a value to a variable. In the case of a block of related assignments, more space may be inserted to promote readability.
    ]]>
    </standard>
    <code_comparison>
        <code title="Equals signs aligned">
        <![CDATA[
$shortVar        <em>=</em> (1 + 2);
$veryLongVarName <em>=</em> 'string';
$var             <em>=</em> foo($bar, $baz, $quux);
        ]]>
        </code>
        <code title="Not aligned; harder to read">
        <![CDATA[
$shortVar <em>=</em> (1 + 2);
$veryLongVarName <em>=</em> 'string';
$var <em>=</em> foo($bar, $baz, $quux);
        ]]>
        </code>
    </code_comparison>
    <standard>
    <![CDATA[
      When using plus-equals, minus-equals etc. still ensure the equals signs are aligned to one space after the longest variable name.
    ]]>
    </standard>
    <code_comparison>
        <code title="Equals signs aligned; only one space after longest var name">
        <![CDATA[
$shortVar       <em>+= </em>1;
$veryLongVarName<em> = </em>1;
        ]]>
        </code>
        <code title="Two spaces after longest var name">
        <![CDATA[
$shortVar       <em> += </em>1;
$veryLongVarName<em>  = </em>1;
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Equals signs aligned">
        <![CDATA[
$shortVar       <em>  = </em>1;
$veryLongVarName<em> -= </em>1;
        ]]>
        </code>
        <code title="Equals signs not aligned">
        <![CDATA[
$shortVar       <em> = </em>1;
$veryLongVarName<em> -= </em>1;
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Space After Casts">
    <standard>
    <![CDATA[
    Exactly one space is allowed after a cast.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: A cast operator is followed by one space.">
        <![CDATA[
$foo = (string)<em> </em>1;
        ]]>
        </code>
        <code title="Invalid: A cast operator is not followed by whitespace.">
        <![CDATA[
$foo = (string)<em></em>1;
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Multiple Statements On a Single Line">
    <standard>
    <![CDATA[
    Multiple statements are not allowed on a single line.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Two statements are spread out on two separate lines.">
        <![CDATA[
$foo = 1;
$bar = 2;
        ]]>
        </code>
        <code title="Invalid: Two statements are combined onto one line.">
        <![CDATA[
$foo = 1; $bar = 2;
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Space After Casts">
    <standard>
    <![CDATA[
    Spaces are not allowed after casting operators.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: A cast operator is immediately before its value.">
        <![CDATA[
$foo = (string)1;
        ]]>
        </code>
        <code title="Invalid: A cast operator is followed by whitespace.">
        <![CDATA[
$foo = (string)<em> </em>1;
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Duplicate Class Names">
    <standard>
    <![CDATA[
    Class and Interface names should be unique in a project.  They should never be duplicated.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: A unique class name.">
        <![CDATA[
class <em>Foo</em>
{
}
        ]]>
        </code>
        <code title="Invalid: A class duplicated (including across multiple files).">
        <![CDATA[
class <em>Foo</em>
{
}

class <em>Foo</em>
{
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<?php
/**
 * Unit test class for the EmptyStatement sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the EmptyStatement sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_CodeAnalysis_EmptyStatementUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                3  => 1,
                15 => 1,
                17 => 1,
                19 => 1,
                30 => 1,
                35 => 1,
                41 => 1,
                47 => 1,
                52 => 1,
                55 => 1,
                72 => 2,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                64 => 1,
                68 => 1,
               );

    }//end getWarningList()


}//end class

?>
<?php

function foo($a, $b) {
    return $a * 2;
}

function baz($a, $b) {
    echo "baz({$a});";
}

function bar($a, $b) {
    $x = $b;
    for ($i = 0; $i <$a; $i++) {
        $x += $a * $i;
    }
    return $x;
}

function foobar($a, &$b) {
    return (preg_match('/foo/', $a, $b) !== 0);
}

class Foo {
    function barfoo($a, $b) {
        // Empty body means interface method in many cases.
    }

    function fooBar($a, $b) {
        return;
    }
}

function foo($bar)
{
    print <<<BAZ
    $bar
BAZ
}

function foo( $parameter ) {
    $wango = <<<HERE
1 Must be a HEREdoc of at least one line
HERE;
    $x = $parameter; // This line must be immediately after the HERE; with no intervening blank lines.
    $tango = <<<HERE
1 Must be a HEREdoc
2 
3 
4 
5   
6
7
8 
9 at least 9 lines long
HERE;
}

function foo( $parameter ) {
    return <<<HTML
<?xml version="1.0"?>
<value>$parameter</value>
HTML;
}

print foo( 'PARAMETER' );
print "\n";

function foo($bar)
{
    print "${bar} things\n";
}

function bar($x)
{
    return 2 * ${x};
}<?php

if (true) {

} else if (false) {
    
} elseif (true) {
    
}

if (file_exists(__FILE__) === true) {
    
}<?php

switch ($foo) {
    // Empty switch statement body 
}

switch ($foo) {
    case 'bar':
        break;
    default:
        break;
}


if ($foo) {
    // Just a comment
} elseif ($bar) {
    // Yet another comment 
} else {
    
}

if ($foo) {
    $foo = 'bar';
} else if ($bar) {
    $bar = 'foo';
}

for ($i = 0; $i < 10; $i++) {
    for ($j = 0; $j < 10; $j++) {
        // Just a comment
    }
}

foreach ($foo as $bar) {}

foreach ($foo as $bar) {
    $bar *= 2;
}

do {
    // Just a comment
    // Just another comment
} while ($foo);

do {
    while ($bar) {
        
    }
} while (true);

while ($foo) { /* Comment in the same line */ }

while ($foo) {
    try {
        
    } catch (Exception $e) {
        echo $e->getTraceAsString();
    }
}

try {
    throw Exception('Error...');
} catch (Exception $e) {}

try {
    throw Exception('Error...');
} catch (Exception $e) {
    // TODO: Handle this exception later :-)
}

if (true) {} elseif (false) {}<?php
/**
 * Unit test class for the UnnecessaryFinalModifier sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the UnnecessaryFinalModifier sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_CodeAnalysis_UnnecessaryFinalModifierUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array();

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                11 => 1,
                14 => 1,
                17 => 1,
               );

    }//end getWarningList()


}//end class

?><?php
for ($i = 0; $i < 10; $i++) {
    // Everything is fine
}

for (; $it->valid();) {
    $it->next();
}

for (;(($it1->valid() && $foo) || (!$it2->value && ($bar || false)));/*Could be ingored*/) {
    $it1->next();
    $it2->next();
}<?php

class Foo {
    public final $FOOBAR = 23;
    protected final $FOO = 42;
    private final $BAR = 17;    
}

final class Foo_Bar {
    public $foobar;
    public final $FOOBAR = 23;
    
    protected $foo;
    protected final $FOO = 42;
    
    private $bar;
    private final $BAR = 17;
}

final class Bar_Foo {
    public $foobar;
    protected $foo;
    private $bar;    
}<?php
/**
 * Unit test class for the ForLoopWithTestFunctionCall sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ForLoopWithTestFunctionCall sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_CodeAnalysis_ForLoopWithTestFunctionCallUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array();

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                4  => 1,
                13 => 1,
               );

    }//end getWarningList()


}//end class

?><?php
/**
 * Unit test class for the ForLoopShouldBeWhileLoop sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ForLoopShouldBeWhileLoop sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_CodeAnalysis_ForLoopShouldBeWhileLoopUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array();

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                6  => 1,
                10 => 1,
               );

    }//end getWarningList()


}//end class

?><?php
/**
 * Unit test class for the UnusedFunctionParameter sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the UnusedFunctionParameter sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_CodeAnalysis_UnusedFunctionParameterUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array();

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                3 => 1,
                7 => 1,
               );

    }//end getWarningList()


}//end class

?><?php

for ($i = 0; $i < 20; $i++) {
    for ($j = 0; $j < 5; $i += 2) {
        for ($k = 0; $k > 3; $i++) {
            
        }
    }
}

for ($i = 0; $i < 20; $i++) {
    for ($j = 0; $j < 5; $j += 2) {
        for ($k = 0; $k > 3; $k++) {
            
        }
    }
}

for ($i = 0; $i < 20; $i++) {
    for ($j = 0; $j < 5; $j += 2) {
        for ($k = 0; $k > 3; $j++) {
            
        }
    }
}<?php
/**
 * Unit test class for the UselessOverridingMethod sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the UselessOverridingMethod sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_CodeAnalysis_UselessOverridingMethodUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array();

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                4  => 1,
                16 => 1,
               );

    }//end getWarningList()


}//end class

?><?php

class FooBar {
    public function __construct($a, $b) {
        parent::__construct($a, $b);
    }
}

class BarFoo {
    public function __construct($a, $b) {
        parent::__construct($a, 'XML', $b);
    }
}

class Foo {
    public function export($a, $b = null) {
        return parent::export($a, $b);
    }
}

class Bar {
    public function export($a, $b = null) {
        return parent::export($a);
    }
}<?php

$a = array(1, 2, 3, 4);
for ($i = 0; $i < count($a); $i++) {
    $a[$i] *= $i;
}

for ($i = 0, $c = sizeof($a); $i < $c; ++$i) {
    $a[$i] *= $i;
}

$it = new ArrayIterator($a);
for ($it->rewind(); $it->valid(); $it->next()) {
    echo $it->current();
}<?php
/**
 * Unit test class for the UnconditionalIfStatement sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the UnconditionalIfStatement sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_CodeAnalysis_UnconditionalIfStatementUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array();

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                3 => 1,
                5 => 1,
                7 => 1,
               );

    }//end getWarningList()


}//end class

?><?php
/**
 * Unit test class for the JumbledIncrementer sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the JumbledIncrementer sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Manuel Pichler <mapi@manuel-pichler.de>
 * @copyright 2007-2008 Manuel Pichler. All rights reserved.
 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_CodeAnalysis_JumbledIncrementerUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array();

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                3  => 2,
                4  => 1,
                20 => 1,
               );

    }//end getWarningList()


}//end class

?><?php
/**
 * Unit test class for the ValidConstantName sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ValidConstantName sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_NamingConventions_UpperCaseConstantNameUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                8   => 1,
                10  => 1,
                15  => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
use Exception as My_Exception, foo\bar, baz;
namespace foo;
namespace foo\bar;
namespace bar\foo\baz;

define('VALID_NAME', true);
define('invalidName', true);
define("VALID_NAME", true);
define("invalidName", true);

class TestClass extends MyClass, YourClass
{

    const const1 = 'hello';
    const CONST2 = 'hello';

    function test()
    {
        echo constant('VALID_NAME');
        echo VALID_NAME;
        print VALID_NAME;
        echo(VALID_NAME);
        print(VALID_NAME);
        echo constant('invalidName');
        echo invalidName;
        print invalidName;
        echo(invalidName);
        print(invalidName);

        echo constant("VALID_NAME");
        echo constant("invalidName");

        echo 'Hello', VALID_NAME;
        echo 'Hello', invalidName;

        // These might look like constants to
        // poorly written code.
        echo 'Hello there';
        echo "HELLO";
        echo 'HELLO';
        print 'Hello there';
        print "HELLO";
        print 'HELLO';
    }

    function myFunc(PHP_CodeSniffer &$blah) {}
    function myFunc(PHP_CodeSniffer $blah) {}

}

interface MyInterface
{
}

if (($object instanceof Some_Class) === false) {
    $var = <<<EOF
This is some heredoc text.
This is some heredoc text.
This is some heredoc text.

This is some heredoc text.
This is some heredoc text.
This is some heredoc text.
EOF;
}

$var = <<<EOF
This is some heredoc text.
This is some heredoc text.
This is some heredoc text.

This is some heredoc text.
This is some heredoc text.
This is some heredoc text.
EOF;

throw new InvalidSomethingException;

declare(ticks = 1) {
    foreach ($var as $bit) {
        echo $bit;
    }
}

$binary = (binary) $string;

$foo->define('bar');
$foo->getBar()->define('foo');

// This is allowed as it is required for PHPUnit.
if (PHPUnit_MAIN_METHOD == 'PHP_Shell_AllTests::main') {
    PHP_Shell_AllTests::main();
}

class ConstTest {
    const TESTER = '1';
    public function __construct() {
        echo constant('self::TESTER');
        echo constant('self::tester');
    }
}

class A {
    public static function constant($x) {}
}

A::constant('anything-not-in-uppercase');

// goto
goto gotolabel;

gototarget1:

function ConstTest() {
    gototarget2:
}

switch($foo)
{
    case $bar:
    gototarget3:
}

$a = 2 * ${x} - ${minus};

class Object implements IObject
{
    use TProperties;
    use TReflected {
        TReflected::reflect insteadof TProperties;
    }
    use ListenerAggregateTrait, PreLoadUserTrait, PreLoadCompanyTrait {
        PreloadUserTrait::PreLoadUser as loadUser;
        PreloadCompanyTrait::PreLoadCompany as loadCompany;
    }
}

class MyClass {
    use Something {
        delete as protected blah;
    }
}

class Foo
{
    public function bar()
    {
        return Bar::class;
    }
}

?>
<?php

abstract class My_Class {

    public function __construct() {}
    public function My_Class() {}
    public function _My_Class() {}

    public function getSomeValue() {}
    public function parseMyDSN() {}
    public function get_some_value() {}
    public function GetSomeValue() {}
    public function getSomeValue_Again() {}

    protected function getSomeValue() {}
    protected function parseMyDSN() {}
    protected function get_some_value() {}

    private function getSomeValue() {}
    private function parseMyDSN() {}
    private function get_some_value() {}

    function getSomeValue() {}
    function parseMyDSN() {}
    function get_some_value() {}

}//end class

function getSomeValue() {}
function parseMyDSN() {}
function get_some_value() {}


/* Test for magic functions */

class Magic_Test {
    function __construct() {}
    function __destruct() {}
    function __call() {}
    function __callStatic() {}
    function __get() {}
    function __set() {}
    function __isset() {}
    function __unset() {}
    function __sleep() {}
    function __wakeup() {}
    function __toString() {}
    function __set_state() {}
    function __clone() {}
    function __autoload() {}
    function __invoke() {}
    function __myFunction() {}
    function __my_function() {}
    function __call() {}
}

function __construct() {}
function __destruct() {}
function __call() {}
function __callStatic() {}
function __get() {}
function __set() {}
function __isset() {}
function __unset() {}
function __sleep() {}
function __wakeup() {}
function __toString() {}
function __set_state() {}
function __clone() {}
function __autoload() {}
function __invoke() {}
function __myFunction() {}
function __my_function() {}
function __call() {}

class Closure_Test {
    function test() {
        $foo = function() { echo 'foo'; };
    }
}

function test() {
    $foo = function() { echo 'foo'; };
}

/* @codingStandardsIgnoreStart */
class MyClass
{
    /* @codingStandardsIgnoreEnd */
    public function __construct() {}
}

trait Foo
{
    function __call() {}
}

class Magic_Case_Test {
    function __Construct() {}
    function __isSet() {}
    function __tostring() {}
}
function __autoLoad() {}

class Foo extends \SoapClient
{
    public function __soapCall(
        $functionName,
        $arguments,
        $options = array(),
        $inputHeaders = null,
        &$outputHeaders = array()
    ) {
        // body
    }
}
?>
<?php
/**
 * Unit test class for the CamelCapsFunctionName sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the CamelCapsFunctionName sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_NamingConventions_CamelCapsFunctionNameUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        $errors = array(
                   10 => 1,
                   11 => 1,
                   12 => 1,
                   13 => 1,
                   16 => 1,
                   17 => 1,
                   20 => 1,
                   21 => 1,
                   24 => 1,
                   25 => 1,
                   30 => 1,
                   31 => 1,
                   50 => 1,
                   52 => 1,
                   53 => 1,
                   57 => 1,
                   58 => 1,
                   59 => 1,
                   60 => 1,
                   61 => 1,
                   62 => 1,
                   63 => 1,
                   64 => 1,
                   65 => 1,
                   66 => 1,
                   67 => 1,
                   68 => 1,
                   69 => 1,
                   71 => 1,
                   72 => 1,
                   73 => 1,
                   74 => 1,
                  );

        // The trait tests will only work in PHP version where traits exist and
        // will throw errors in earlier versions.
        if (version_compare(PHP_VERSION, '5.4.0') < 0) {
            $errors[95] = 1;
        }

        return $errors;

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
class TestClass extends MyClass
{

    function TestClass() {
        parent::MyClass();
        parent::__construct();
    }

    function __construct() {
        parent::MyClass();
        parent::__construct();
    }

}

class MyClass
{

    function MyClass() {
        parent::YourClass();
        parent::__construct();
    }

    function __construct() {
        parent::YourClass();
        parent::__construct();
    }

}

class MyClass extends \MyNamespace\SomeClass
{
    function __construct() {
        something::MyNamespace();
    }

}

abstract class MyAbstractClass extends \MyNamespace\SomeClass
{
    abstract public function __construct();
}
?>
<?php
/**
 * Unit test class for the ConstructorName sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ConstructorName sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_NamingConventions_ConstructorNameUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                5  => 1,
                6  => 1,
                11 => 1,
                20 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php

class ExampleClass
{
	function exampleFunction() {}

}

	$o = <<<EOF
	this is some text
	this is some text
EOF;

    $correctVar = true;
	$correctVar = false;

?>
<?php
/**
 * Unit test class for the DisallowSpaceIndent sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the DisallowSpaceIndent sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_WhiteSpace_DisallowSpaceIndentUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='DisallowSpaceIndentUnitTest.inc')
    {
        switch ($testFile) {
        case 'DisallowSpaceIndentUnitTest.inc':
            return array(
                    5  => 1,
                    9  => 1,
                    15 => 1,
                    18 => 1,
                    19 => 1,
                    22 => 1,
                    24 => 1,
                   );
            break;
        case 'DisallowSpaceIndentUnitTest.js':
            return array(
                    3 => 1,
                    6 => 1,
                   );
            break;
        case 'DisallowSpaceIndentUnitTest.css':
            return array(
                    2 => 1,
                   );
            break;
        default:
            return array();
            break;
        }//end switch

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
#login-container {
    margin-left: -225px;
	width: 450px;
}
#login-container {
	margin-left: -225px;
    width: 450px;
}

var x = {
	abc: 1,
    zyz: 2,
	abc: 5,
	mno: {
	  abc: 4
	},
	abc: 5
}
<?php

class ExampleClass
{
    function exampleFunction() {}

}

    $o = <<<EOF
    this is some text
    this is some text
EOF;

	$correctVar = false;
    $correctVar = true;

// Indent with spaces is not allowed
 $hello = array();
   $world = '';
// here the indention is mixed with tabs and spaces
// [tab][space][space][space][tab]return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>";
	   	return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>";
// [space][space][space][tab]return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>";
   	return "<$name$xmlns$type_str $atts xsi:nil=\"true\"/>";
// Doc comments are indent with tabs and one space
//[tab]/**
//[tab][space]*
	/**
	 * CVS revision for HTTP headers.
     *
	  * @var string
	 * @access private
	 */
	/**
     *
	*/
<?php
/**
 * Unit test class for the DisallowTabIndent sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the DisallowTabIndent sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_WhiteSpace_DisallowTabIndentUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='DisallowTabIndentUnitTest.inc')
    {
        switch ($testFile) {
        case 'DisallowTabIndentUnitTest.inc':
            return array(
                    5  => 1,
                    9  => 1,
                    15 => 1,
                   );
            break;
        case 'DisallowTabIndentUnitTest.js':
            return array(
                    3 => 1,
                    6 => 1,
                   );
            break;
        case 'DisallowTabIndentUnitTest.css':
            return array(
                    2 => 1,
                   );
            break;
        default:
            return array();
            break;
        }//end switch

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php

class Test
{
    function __construct()
    {
       $this->hello(); // error here
    }

   function hello() // error here
    { // no error here as brackets can be put anywhere in the pear standard
        echo 'hello';
    }

    function hello2()
    {
       if (TRUE) { // error here
            echo 'hello'; // no error here as its more than 4 spaces.
        } else {
        echo 'bye'; // error here
        }

        while (TRUE) {
           echo 'hello'; // error here
         }// no error here as its handled by another test.

       do { // error here
         echo 'hello'; // error here
       } while (TRUE); // no error here as its aligned with the do.
   }// no error here as its handled by another test.

    function hello3()
    {
        switch ($hello) {
            case 'hello':
            break;
        }
    }

}

?>
<pre>
</head>
<body>
<?php
if ($form->validate()) {
    $safe = $form->getSubmitValues();
}
?>
</pre>
<?php

class Test2
{
    function __construct()
    {
    //    $this->open(); // error here
    }

    public function open()
    {
        // Some inline stuff that shouldn't error
        if (TRUE) echo 'hello';
        foreach ($tokens as $token) echo $token;
    }

    /**
     * This is a comment 1.
     * This is a comment 2.
     * This is a comment 3.
     * This is a comment 4.
     */
    public function close()
    {
        // All ok.
        if (TRUE) {
            if (TRUE) {
            } else if (FALSE) {
                foreach ($tokens as $token) {
                    switch ($token) {
                        case '1':
                        case '2':
                            if (true) {
                                if (false) {
                                    if (false) {
                                        if (false) {
                                            echo 'hello';
                                        }
                                    }
                                }
                            }
                        break;
                        case '5':
                        break;
                    }
                    do {
                        while (true) {
                            foreach ($tokens as $token) {
                                for ($i = 0; $i < $token; $i++) {
                                    echo 'hello';
                                }
                            }
                        }
                    } while (true);
                }
            }
        }
    }

    /*
      This is another c style comment 1.
      This is another c style comment 2.
      This is another c style comment 3.
      This is another c style comment 4.
      This is another c style comment 5.
    */

    /*
    *
    *
    *
   */

    /**
   */

    /*
      This comment has a newline in it.

    */

    public function read()
    {
        echo 'hello';

        // no errors below.
        $array = array(
                  'this',
                  'that' => array(
                             'hello',
                             'hello again' => array(
                                               'hello',
                                              ),
                            ),
                 );
    }
}

abstract class Test3
{
    public function parse()
    {

        foreach ($t as $ndx => $token) {
            if (is_array($token)) {
                echo 'here';
            } else {
                $ts[] = array("token" => $token, "value" => '');

                $last = count($ts) - 1;

                switch ($token) {
                    case '(':

                        if ($last >= 3 &&
                            $ts[0]['token'] != T_CLASS &&
                            $ts[$last - 2]['token'] == T_OBJECT_OPERATOR &&
                            $ts[$last - 3]['token'] == T_VARIABLE ) {


                            if (true) {
                                echo 'hello';
                            }
                        }
                        array_push($braces, $token);
                    break;
                }
            }
        }
    }
}

public function test()
{
    $o = <<<EOF
this is some text
this is some text
this is some text
this is some text
this is some text
this is some text
EOF;

    return $o;
}

if ($a === true || $a === true || $a === true || $a === true ||
    $a === true || $a === true || $a === true || $a === true) {

    echo 'hello';
}

if ($true) {
    /* First comment line
    *
    * Comment test here
    * Comment test here
    *
    */

    /* First comment line
    *
    * Comment test here
    * Comment test here
    *
    this si something */
}

function test()
{
    /* taken from http://de3.php.net/manual/en/reserved.php */
    # $m[] = 'declare';
   /* taken from http://de3.php.net/manual/en/reserved.php */
   # $m[] = 'declare';
}

foreach ($elements as $element) {
    if ($something) {
        // Do IF.
    } else if ($somethingElse) {
        // Do ELSE.
    }
}

if ($condition) {
    echo "This is a long
string that spans $numLines lines
without indenting.
";
}

if ($condition) {
    echo 'This is a long
    string that spans nultiple lines
    with indenting.
    ';
}

if ($condition) {
    echo 'This is a long
          string that spans nultiple lines
          with indenting.';
}

switch ($foo) {
    case 1:
        switch ($bar) {
            default:
                echo $string{1};
        }
    break;
}

function temp($foo, $bar) {
    switch ($foo) {
        case 1:
            switch ($bar) {
                default:
                    return $foo;
            }
        break;
    }
}

switch ($foo) {
    case 1:
        switch ($bar) {
        default:
            if ($something) {
                echo $string{1};
            } else if ($else) {
                switch ($else) {
                default:
                }
            }
        }
    break;
}

switch ($name) {
    case "1":
    case "2":
    case "3":
        return true;
}

switch ($name) {
    case "1":
    case "2":
    case "3":
    default :
        return true;
}

function myFunction()
{
    ?>
    <dynamic_content>

   </dynamic_content>
    <?php

}

switch ($name) {
    case "1":
        switch ($name2) {
            case "1":
            break;
            case "2":
            break;
        }
    break;
    case "2":
    break;
}

switch (true) {
    case true: {
    }
    echo 'hi';
    break;
    case false:
    case null:{
    echo 'hi';
    }
    break;
}

switch (true) {
    case true: {
        echo 'hi';
    }
    // No break here.
    case false:
    case true:
    case null:{
    echo 'hi';
        echo 'hi';
    }
    break;
}

switch (true) {
    case true: {
        if (true) {
            echo 'hi';
        }
    }
    break;
}

// Testing anon function.
class a {
    function c()
    {
        $this->doSomething(
            function () {
                echo 123;
            }
        );
    }
}

some_function(
    function() {
        $a = 403;
        if ($a === 404) {
        $a = 403;
        }
    }
);

some_function(
   function() {
      $a = 403;
       if ($a === 404) {
           $a = 403;
       }
    }
);

$myFunction = function() {
    $a = 403;
    if ($a === 404) {
       $a = 403;
    }
}

class Whatever
{
    protected $_protectedArray = array(
        'normalString' => 'That email address is already in use!',
        'offendingString' => <<<'STRING'
Each line of this string is always said to be at column 0, 
    no matter how many spaces are placed
                at the beginning of each line
and the ending STRING on the next line is reported as having to be indented.
STRING
    );
}

$var = call_user_func(
    $new_var = function () use (&$a) {
        if ($a > 0) {
            return $a++;
        } else {
            return $a--;
        }
    }
);

class AnonymousFn
{
    public function getAnonFn()
    {
        return array(
            'functions' => Array(
                'function1' => function ($a, $b, $c) {
                    $a = $b + $c;
                    $b = $c / 2;
                    return Array($a, $b, $c);
                },
            ),
        );
    }
}
?>

<div>
    <?php
    if ($myvar == 'test') {
        echo 'something';
    }
    ?>
<div>
<div>
    <?php
        if ($myvar == 'test') {
            echo 'something';
        }
    ?>
<div>
<div>
    <?php
if ($myvar == 'test') {
    echo 'something';
}
    ?>
<div>
var x = {
  abc: 1,
	zyz: 2,
  abc: 5,
  mno: {
  	abc: 4
  },
  abc: 5
}
<?php
/**
 * Unit test class for the ScopeIndent sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ScopeIndent sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_WhiteSpace_ScopeIndentUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                7   => 1,
                10  => 1,
                17  => 1,
                20  => 1,
                24  => 1,
                27  => 1,
                28  => 1,
                58  => 1,
                123 => 1,
                126 => 1,
                224 => 1,
                225 => 1,
                279 => 1,
                280 => 1,
                281 => 1,
                282 => 1,
                283 => 1,
                284 => 1,
                311 => 1,
                336 => 1,
                349 => 1,
                380 => 1,
                387 => 1,
                397 => 1,
                450 => 1,
                457 => 1,
                458 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
class myclass extends yourclass implements someint {
    function myfunc($var) {
        echo $var;
    }
}

$myvar = true;
myfunc(&$myvar);
myfunc($myvar);

$this->myfunc(&$myvar);
$this->myfunc($myvar);

myclass::myfunc(&$myvar);
myclass::myfunc($myvar);

while(testfunc($var1, &$var2, $var3, &$var4) === false) {
}

sprintf("0%o", 0777 & $p);

$foo(&$myvar);
?>
<?php
/**
 * Unit test class for the CallTimePassByReference sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the CallTimePassByReference sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_Functions_CallTimePassByReferenceUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                9  => 1,
                12 => 1,
                15 => 1,
                18 => 2,
                23 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php

$result = myFunction();
$result = myFunction($arg1, $arg2);
$result = myFunction($arg1,$arg2);
$result = myFunction($arg1 , $arg2);
$result = myFunction($arg1 ,  $arg2);
$result = myFunction($arg1, $arg2, $arg3,$arg4, $arg5);
$result = myFunction($arg1, $arg2, $arg3, $arg4, $arg5);
$result = myFunction($arg1, $arg2 = array());
$result = myFunction($arg1 , $arg2 =array());
$result = myFunction($arg1 , $arg2= array());
$result = myFunction($arg1 , $arg2=array());

$result = myFunction($arg1, 
                     $arg2 = array(), 
                     $arg3, 
                     $arg4, 
                     $arg5);

throw new Exception("This is some massive string for a message", 
                         $cause);

// Function definitions are ignored
function myFunction($arg1,$arg2)
{
}

function myFunction    ($arg1,$arg2)
{
}

function myFunction($arg1=1,$arg2=2)
{
}


function myFunction($arg1 = 1,$arg2 = 2)
{
}

$key = array_search($this->getArray($one,  $two,$three),$this->arrayMap);
$this->error($obj->getCode(),$obj->getMessage(),$obj->getFile(),$obj->getLine());

make_foo($string /*the string*/ , true /*test*/);
make_foo($string/*the string*/ ,   /*test*/ true);
make_foo($string /*the string*/, /*test*/ true);

class MyClass {
    function myFunction() {
        blah($foo, "{{$config['host']}}", "{$config}", "hi there{}{}{{{}{}{}}");
    }
}

// Function definition, not function call, so should be ignored
function &myFunction($arg1=1,$arg2=2)
{
}

return array_udiff(
    $foo,
    $bar,
    function($a, $b) {
        $foo='bar';
        return $foo;
    }
);
?>
<?php
/**
 * Unit test class for the OpeningFunctionBraceKernighanRitchie sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the OpeningFunctionBraceKernighanRitchie sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_Functions_OpeningFunctionBraceKernighanRitchieUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                9   => 1,
                13  => 1,
                17  => 1,
                29  => 1,
                33  => 1,
                37  => 1,
                53  => 1,
                58  => 1,
                63  => 1,
                77  => 1,
                82  => 1,
                87  => 1,
                104 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php

// Good.
function myFunction() {
}

// Brace should be on same line.
function myFunction()
{
}

// Too many spaces.
function myFunction()   {
}

// Uses tab.
function myFunction()	{
}


class myClass()
{
    // Good.
    function myFunction() {
    }
    
    // Brace should be on same line.
    function myFunction()
    {
    }
    
    // Too many spaces.
    function myFunction()   {
    }
    
    // Uses tab.
    function myFunction()	{
    }
}



/* Multi-line declarations */

// Good.
function myFunction($variable1, $variable2,
    $variable3, $variable4) {
}

// Brace should be on same line.
function myFunction($variable1, $variable2,
    $variable3, $variable4)
{
}

// Too many spaces.
function myFunction($variable1, $variable2,
    $variable3, $variable4)   {
}

// Uses tab.
function myFunction($variable1, $variable2,
    $variable3, $variable4)	{
}


class myClass()
{
    // Good.
    function myFunction($variable1, $variable2,
        $variable3, $variable4) {
    }
    
    // Brace should be on same line.
    function myFunction($variable1, $variable2,
        $variable3, $variable4)
    {
    }
    
    // Too many spaces.
    function myFunction($variable1, $variable2,
        $variable3, $variable4)   {
    }
    
    // Uses tab.
    function myFunction($variable1, $variable2,
        $variable3, $variable4)	{
    }
}

interface MyInterface()
{
    function myFunction();
}

function myFunction(
                    $arg1,
                    $arg2,
                    $arg3,
                    $arg4,
                    $arg5,
                    $arg6
                    )
{
}

function myFunction(
                    $arg1,
                    $arg2,
                    $arg3,
                    $arg4,
                    $arg5,
                    $arg6
                    ) {
}

?>
<?php
/**
 * Unit test class for the FunctionCallArgumentSpacing sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the FunctionCallArgumentSpacing sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_Functions_FunctionCallArgumentSpacingUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                5  => 1,
                6  => 1,
                7  => 2,
                8  => 1,
                11 => 2,
                12 => 2,
                13 => 3,
                42 => 3,
                43 => 3,
                45 => 1,
                46 => 2,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the OpeningFunctionBraceBsdAllman sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the OpeningFunctionBraceBsdAllman sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_Functions_OpeningFunctionBraceBsdAllmanUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                4   => 1,
                13  => 1,
                19  => 1,
                24  => 1,
                30  => 1,
                40  => 1,
                44  => 1,
                50  => 1,
                55  => 1,
                67  => 1,
                78  => 1,
                85  => 1,
                91  => 1,
                98  => 1,
                110 => 1,
                115 => 1,
                122 => 1,
                128 => 1,
                155 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php

// Brace should be on new line.
function myFunction() {
}

// Good.
function myFunction()
{
}

// Too many spaces.
function myFunction()   {
}

// Too many newlines.
function myFunction()

{
}

// Space before brace.
function myFunction()
 {
}

class myClass()
{
    // Brace should be on new line.
    function myFunction() {
    }
    
    // Good.
    function myFunction()
    {
    }

    // No aligned correctly.
    function myFunction()
{
}
    
    // Too many spaces.
    function myFunction()   {
    }
    
    // Too many newlines.
    function myFunction()

    {
    }
    
    // Space before brace.
    function myFunction()
     {
    }
}



/* Multi-line declarations */



// Brace should be on new line.
function myFunction($variable1, $variable2,
    $variable3, $variable4) {
}

// Good.
function myFunction($variable1, $variable2,
    $variable3, $variable4)
{
}

// Too many spaces.
function myFunction($variable1, $variable2,
    $variable3, $variable4)   {
}

// Too many newlines.
function myFunction($variable1, $variable2,
    $variable3, $variable4)

{
}

// Space before brace.
function myFunction($variable1, $variable2,
    $variable3, $variable4)
 {
}

class myClass()
{
    // Brace should be on new line.
    function myFunction($variable1, $variable2,
    $variable3, $variable4) {
    }
    
    // Good.
    function myFunction($variable1, $variable2,
    $variable3, $variable4)
    {
    }

    // No aligned correctly.
    function myFunction($variable1, $variable2,
    $variable3, $variable4)
{
}
    
    // Too many spaces.
    function myFunction($variable1, $variable2,
    $variable3, $variable4)   {
    }
    
    // Too many newlines.
    function myFunction($variable1, $variable2,
    $variable3, $variable4)

    {
    }
    
    // Space before brace.
    function myFunction($variable1, $variable2,
    $variable3, $variable4)
     {
    }
}

interface MyInterface()
{
    function myFunction();
}

function myFunction(
                    $arg1,
                    $arg2,
                    $arg3,
                    $arg4,
                    $arg5,
                    $arg6
                    )
{
}

function myFunction(
                    $arg1,
                    $arg2,
                    $arg3,
                    $arg4,
                    $arg5,
                    $arg6
                    ) {
}
?>
<?php
/**
 * Unit test class for the InlineControlStructure sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the InlineControlStructure sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_ControlStructures_InlineControlStructureUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='InlineControlStructureUnitTest.inc')
    {
        switch ($testFile) {
        case 'InlineControlStructureUnitTest.inc':
            return array(
                    3  => 1,
                    7  => 1,
                    11 => 1,
                    13 => 1,
                    15 => 1,
                    17 => 1,
                    23 => 1,
                   );
            break;
        case 'InlineControlStructureUnitTest.js':
            return array(
                    3  => 1,
                    7  => 1,
                    11 => 1,
                    13 => 1,
                    15 => 1,
                   );
            break;
        default:
            return array();
            break;
        }//end switch

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php

if ($something) echo 'hello';

if ($something) {
    echo 'hello';
} else echo 'hi';

if ($something) {
    echo 'hello';
} else if ($else) echo 'hi';

for ($i; $i > 0; $i--) echo 'hello';

while ($something) echo 'hello';

do {
    $i--;
} while ($something);

?><?php

if ($something) echo 'hello';

if ($something) {
    echo 'hello';
} else echo 'hi';

if ($something) {
    echo 'hello';
} else if ($else) echo 'hi';

foreach ($something as $thing) echo 'hello';

for ($i; $i > 0; $i--) echo 'hello';

while ($something) echo 'hello';

do {
    $i--;
} while ($something);

if(true)
  $someObject->{$name};

if (true) :
    $foo = true;
endif;

while (true) :
    $foo = true;
endwhile;

for ($i; $i > 0; $i--) :
    echo 'hello';
endfor;

foreach ($array as $element) :
    echo 'hello';
endforeach;

?>
<?php
/**
 * TODO: Write this comment
 *
 */

// TODO: remove this.
alert('test');

// TODO remove this.
alert('test');

// todo - remove this.

// Extract info from the array.
// TODO: can this be done faster?

// Extract info from the array (todo: make it faster)
// To do this, use a function!
// notodo! NOTODO! NOtodo!
//TODO.
?>
<?php
/**
 * FIXME: Write this comment
 *
 */

// FIXME: remove this.
alert('test');

// FIXME remove this.
alert('test');

// fixme - remove this.

// Extract info from the array.
// FIXME: can this be done faster?

// Extract info from the array (fixme: make it faster)
// To do this, use a function!
// nofixme! NOFIXME! NOfixme!
//FIXME.
?>
<?php
/**
 * Unit test class for the Todo sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the Todo sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_Commenting_TodoUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='TodoUnitTest.inc')
    {
        return array();

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getWarningList($testFile='TodoUnitTest.inc')
    {
        switch ($testFile) {
        case 'TodoUnitTest.inc':
            return array(
                    3  => 1,
                    7  => 1,
                    10 => 1,
                    13 => 1,
                    16 => 1,
                    18 => 1,
                    21 => 1,
                   );
            break;
        case 'TodoUnitTest.js':
            return array(
                    3  => 1,
                    7  => 1,
                    10 => 1,
                    13 => 1,
                    16 => 1,
                    18 => 1,
                    21 => 1,
                   );
            break;
        default:
            return array();
            break;
        }//end switch

    }//end getWarningList()


}//end class

?>
<?php
/**
 * TODO: Write this comment
 *
 */

// TODO: remove this.
error_log('test');

// TODO remove this.
Debug::bam('test');

// todo - remove this.

// Extract info from the array.
// TODO: can this be done faster?

// Extract info from the array (todo: make it faster)
// To do this, use a function!
// notodo! NOTODO! NOtodo!
//TODO.
?>
<?php
/**
 * FIXME: really need to fix this before I commit.
 *
 */

// FIXME: this is broken, don't forget to fix it
error_log('test');

// FIXME remove this.
Debug::bam('test');

// fixme - fix this.

// Extract info from the array.
// FIXME: this is just a stub, fill in later

// Extract info from the array (fixme: finish later)
// To do this, use a function!
// nofixme! NOFIXME! NOfixme!
//FIXME.
?>
<?php
/**
 * Unit test class for the Fixme sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @author    Sam Graham <php-codesniffer BLAHBLAH illusori.co.uk>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the Fixme sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @author    Sam Graham <php-codesniffer BLAHBLAH illusori.co.uk>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_Commenting_FixmeUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='FixmeUnitTest.inc')
    {
        switch ($testFile) {
        case 'FixmeUnitTest.inc':
            return array(
                    3  => 1,
                    7  => 1,
                    10 => 1,
                    13 => 1,
                    16 => 1,
                    18 => 1,
                    21 => 1,
                   );
            break;
        case 'FixmeUnitTest.js':
            return array(
                    3  => 1,
                    7  => 1,
                    10 => 1,
                    13 => 1,
                    16 => 1,
                    18 => 1,
                    21 => 1,
                   );
            break;
        default:
            return array();
            break;
        }//end switch

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getWarningList($testFile='FixmeUnitTest.inc')
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the CyclomaticComplexity sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the CyclomaticComplexity sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_Metrics_CyclomaticComplexityUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                116 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                45 => 1,
                72 => 1,
               );

    }//end getWarningList()


}//end class

?>
<?php

function nestingOne()
{
    if ($condition) {
        echo 'hi';
    }
}

function nestingFive()
{
    if ($condition) {
        echo 'hi';
        switch ($condition)
        {
            case '1':
                if ($condition === '1') {
                    if ($cond) {
                        echo 'hi';
                    }
                }
            break;
        }
    }
}

function nestingSix()
{
    if ($condition) {
        echo 'hi';
        switch ($condition)
        {
            case '1':
                if ($condition === '1') {
                    if ($cond) {
                        foreach ($conds as $cond) {
                            echo 'hi';
                        }
                    }
                }
            break;
        }
    }
}

function nestingTen()
{
    if ($condition) {
        echo 'hi';
        switch ($condition)
        {
            case '1':
                if ($condition === '1') {
                    if ($cond) {
                        switch ($cond) {
                            case '1':
                                if ($cond === '1') {
                                    foreach ($conds as $cond) {
                                        if ($cond === 'hi') {
                                            echo 'hi';
                                        }
                                    }
                                }
                            break;
                        }
                    }
                }
            break;
        }
    }
}

function nestingEleven()
{
    if ($condition) {
        echo 'hi';
        switch ($condition)
        {
            case '1':
                if ($condition === '1') {
                    if ($cond) {
                        switch ($cond) {
                            case '1':
                                if ($cond === '1') {
                                    foreach ($conds as $cond) {
                                        if ($cond === 'hi') {
                                            if ($cond !== 'bye') {
                                                echo 'hi';
                                            }
                                        }
                                    }
                                }
                            break;
                        }
                    }
                }
            break;
        }
    }
}

?>
<?php
/**
 * Unit test class for the NestingLevel sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the NestingLevel sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_Metrics_NestingLevelUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                73 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                27 => 1,
                46 => 1,
               );

    }//end getWarningList()


}//end class

?>
<?php

function complexityOne() { }

function comlexityFive()
{
    if ($condition) {
    }

    switch ($condition) {
        case '1':
        break;
        case '2':
        break;
        case '3':
        break;
    }
}

function comlexityTen()
{
    while ($condition === true) {
        if ($condition) {
        }
    }

    switch ($condition) {
        case '1':
            if ($condition) {
            } else if ($cond) {
            }
        break;
        case '2':
            while ($cond) {
                echo 'hi';
            }
        break;
        case '3':
        break;
        default:
        break;
    }
}

function comlexityEleven()
{
    while ($condition === true) {
        if ($condition) {
        } else if ($cond) {
        }
    }

    switch ($condition) {
        case '1':
            if ($condition) {
            } else if ($cond) {
            }
        break;
        case '2':
            while ($cond) {
                echo 'hi';
            }
        break;
        case '3':
        break;
        default:
        break;
    }
}


function comlexityTwenty()
{
    while ($condition === true) {
        if ($condition) {
        } else if ($cond) {
        }
    }

    switch ($condition) {
        case '1':
            if ($condition) {
            } else if ($cond) {
            }
        break;
        case '2':
            while ($cond) {
                echo 'hi';
            }
        break;
        case '3':
            switch ($cond) {
                case '1':
                break;
                case '2':
                break;
            }
        break;
        case '4':
            do {
                if ($condition) {
                    if ($cond) {
                    } else if ($con) {
                    }
                }
            } while ($cond);
        break;
        default:
            if ($condition) {
            }
        break;
    }
}


function comlexityTwentyOne()
{
    while ($condition === true) {
        if ($condition) {
        } else if ($cond) {
        }
    }

    switch ($condition) {
        case '1':
            if ($condition) {
            } else if ($cond) {
            }
        break;
        case '2':
            while ($cond) {
                echo 'hi';
            }
        break;
        case '3':
            switch ($cond) {
                case '1':
                break;
                case '2':
                break;
            }
        break;
        case '4':
            do {
                if ($condition) {
                    if ($cond) {
                    } else if ($con) {
                    }
                }
            } while ($cond);
        break;
        default:
            if ($condition) {
            } else if ($cond) {
            }
        break;
    }
}

?>
#login-container {
    margin-left: -225px;
}
alert('hi');
alert('hi');

alert('hi);

#login-container {}

<?php
/**
 * Unit test class for the LowercasedFilename sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Andy Grunwald <andygrunwald@gmail.com>
 * @copyright 2010 Andy Grunwald
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the LowercasedFilename sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Andy Grunwald <andygrunwald@gmail.com>
 * @copyright 2010 Andy Grunwald
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_Files_LowercasedFilenameUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(1 => 1);

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>

#login-container {}<?php
class foo {

}

class bar {

}

class baz {

}
?>
alert('hi);

#login-container {}
<?php
/**
 * Unit test class for the LineLength sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the LineLength sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_Files_LineLengthUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                31 => 1,
                34 => 1,
                68 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                9  => 1,
                15 => 1,
                21 => 1,
                24 => 1,
                29 => 1,
                37 => 1,
               );

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the LineEndings sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the LineEndings sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_Files_LineEndingsUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                1 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the OneInterfacePerFile sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Andy Grunwald <andygrunwald@gmail.com>
 * @copyright 2010 Andy Grunwald
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the OneInterfacePerFile sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Andy Grunwald <andygrunwald@gmail.com>
 * @copyright 2010 Andy Grunwald
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_Files_OneInterfacePerFileUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                6  => 1,
                10 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the InlineHTML sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the InlineHTML sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_Files_InlineHTMLUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='')
    {
        switch ($testFile) {
        case 'InlineHTMLUnitTest.3.inc':
            return array(
                    4 => 1,
                   );
            break;
        case 'InlineHTMLUnitTest.4.inc':
            return array(
                    1 => 1,
                   );
            break;
        default:
            return array();
            break;
        }//end switch

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getWarningList($testFile='')
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php

// This line is okay... just!
if (($reallyLongVarName === true) || (is_array($anotherLongVarName) == false)) {
    // Do something.
}

// This line is not okay... just!
if (($reallyLongVarName === true) || (is_array($anotherLongVarName) === false)) {
    // Do something.
}


// This line is is too long.
if (($anotherReallyLongVarName === true) || (is_array($anotherReallyLongVarName) === false)) {
    // Do something.
}

// This is a really really long comment that is going to go to exactly 80 chars.

// This is another really really long comment that is going to go well over 80 characters.

// And here is just a bunch of spaces that exceeds the line length.
                                                                                    

// And here are some spaces exactly 80 chars long.
                                                                                

// This is a really really really really long long comment that is going to go to exactly 100 chars.

// This is another really really really really really long comment that is going to go well over 100 characters.

// And here is just a bunch of spaces that exceeds the max line length.
                                                                                                           

// And here are some spaces exactly 100 chars long.
                                                                                                    
?>
<b>Hello</b>b>
<?php
echo 'hi';
?>

<?php
/**
 * Comments contining CVS IDs can be long, but should be ignored because
 * they cannot be changed by the developer. Same with license URLs. Also
 * and URL/HeadURL in subversion.
 *
 * @license http://www.freebsd.org/copyright/freebsd-license.html BSD License (2 Clause)
 *
 * $URL: file/paths/in/subversion/are/prefixed/by/URL/or/HeadURL/and/can/be/very/long/especially/if/they/are/in/a/branch $
 * $HeadURL: https://svn.example.org/file/paths/in/subversion/are/prefixed/by/URL/or/HeadURL/and/can/be/very/long/especially/if/they/are/in/a/branch $
 */

// $URL: file/paths/in/subversion/are/prefixed/by/URL/or/HeadURL/and/can/be/very/long/especially/if/they/are/in/a/branch $
// $HeadURL: https://svn.example.org/file/paths/in/subversion/are/prefixed/by/URL/or/HeadURL/and/can/be/very/long/especially/if/they/are/in/a/branch $

echo '$URL: file/paths/in/subversion/are/prefixed/by/URL/or/HeadURL/and/can/be/very/long/especially/if/they/are/in/a/branch $';
echo '$HeadURL: https://svn.example.org/file/paths/in/subversion/are/prefixed/by/URL/or/HeadURL/and/can/be/very/long/especially/if/they/are/in/a/branch $'

 ?>

    * $URL: file/paths/in/subversion/are/prefixed/by/URL/or/HeadURL/and/can/be/very/long/especially/if/they/are/in/a/branch $
    * $HeadURL: https://svn.example.org/file/paths/in/subversion/are/prefixed/by/URL/or/HeadURL/and/can/be/very/long/especially/if/they/are/in/a/branch $

<?php
// This is another really long comment that is going to go well over 100 characters, with no closing php tag after it.
<?php
echo 'foo';
<?php
echo 'hi';
?>

<?php
echo 'hi';
?>
<?php

?>

<?php

?>
alert('hi);﻿<?php
echo 'foo';
?>

alert('hi);<?php
echo 'foo';<?php
/**
 * Unit test class for the OneClassPerFile sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Andy Grunwald <andygrunwald@gmail.com>
 * @copyright 2010 Andy Grunwald
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the OneClassPerFile sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Andy Grunwald <andygrunwald@gmail.com>
 * @copyright 2010 Andy Grunwald
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_Files_OneClassPerFileUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                6  => 1,
                10 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>

#login-container {}

#login-container {}

<?php
echo 'foo';
?>

alert('hi);

<html>
<?php echo $allTheThings; ?>
</html>
<?php
echo 'foo';

<?php
echo 'foo';
?>
<?php
interface foo {
	
}

interface bar {
	
}

interface baz {
	
}
?><?php
echo 'foo';
?><?php
/**
 * Unit test class for the ByteOrderMark sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ByteOrderMark sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_Files_ByteOrderMarkUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                1 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
echo 'foo';
?>
<body>
<?php
echo 'bar';
<?php
echo 'foo';

<?php
echo 'foo';


alert('hi);


#login-container {}<?php
echo 'foo';<?php
/**
 * Unit test class for the EndFileNoNewline sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the EndFileNoNewline sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_Files_EndFileNoNewlineUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='')
    {
        switch ($testFile) {
        case 'EndFileNoNewlineUnitTest.1.inc':
        case 'EndFileNoNewlineUnitTest.1.css':
        case 'EndFileNoNewlineUnitTest.1.js':
        case 'EndFileNoNewlineUnitTest.2.inc':
            return array(
                    3 => 1,
                   );
            break;
        case 'EndFileNoNewlineUnitTest.2.css':
        case 'EndFileNoNewlineUnitTest.2.js':
            return array(
                    2 => 1,
                   );
            break;
        default:
            return array();
            break;
        }//end switch

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getWarningList($testFile='')
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the EndFileNewline sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the EndFileNewline sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_Files_EndFileNewlineUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='')
    {
        switch ($testFile) {
        case 'EndFileNewlineUnitTest.3.inc':
        case 'EndFileNewlineUnitTest.3.js':
        case 'EndFileNewlineUnitTest.3.css':
            return array(
                    2 => 1,
                   );
            break;
        default:
            return array();
            break;
        }//end switch

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getWarningList($testFile='')
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the UnnecessaryStringConcat sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the UnnecessaryStringConcat sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_Strings_UnnecessaryStringConcatUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='UnnecessaryStringConcatUnitTest.inc')
    {
        switch ($testFile) {
        case 'UnnecessaryStringConcatUnitTest.inc':
            return array(
                    2  => 1,
                    6  => 1,
                    9  => 1,
                    12 => 1,
                   );
            break;
        case 'UnnecessaryStringConcatUnitTest.js':
            return array(
                    1  => 1,
                    8  => 1,
                    11 => 1,
                   );
            break;
        default:
            return array();
            break;
        }

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
$x = 'My '.'string';
$x = 'My '.1234;
$x = 'My '.$y.' test';

echo $data['my'.'index'];
echo $data['my'.4];
echo $data['my'.$x];
echo $data[$x.$y.'My'.'String'];

$code = '$actions = array();'."\n";
$code = "$actions = array();"."\n";

// No errors for these because they are needed in some cases.
$code = ' ?'.'>';
$code = '<'.'?php ';
?>
var x = 'My ' + 'string';
var x = 'My ' + 1234;
var x = 'My ' + y + ' test';

this.errors['test'] = x;
this.errors['test' + 10] = x;
this.errors['test' + y] = x;
this.errors['test' + 'blah'] = x;
this.errors[y] = x;
this.errors[y + z] = x;
this.errors[y + z + 'My' + 'String'] = x;
<?php
/**
 * Unit test class for the ForbiddenFunctions sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ForbiddenFunctions sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_PHP_ForbiddenFunctionsUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        $errors = array(
                   2 => 1,
                   4 => 1,
                  );

        // The trait insteadof test will only work in PHP versions where traits exist
        // and will throw errors in earlier versions.
        if (version_compare(PHP_VERSION, '5.4.0') < 0) {
            $errors[44] = 2;
        }

        return $errors;

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the LowerCaseConstant sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the LowerCaseConstant sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_PHP_LowerCaseConstantUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='LowerCaseConstantUnitTest.inc')
    {
        switch ($testFile) {
        case 'LowerCaseConstantUnitTest.inc':
            return array(
                    7  => 1,
                    10 => 1,
                    15 => 1,
                    16 => 1,
                    23 => 1,
                    26 => 1,
                    31 => 1,
                    32 => 1,
                    39 => 1,
                    42 => 1,
                    47 => 1,
                    48 => 1,
                    67 => 1,
                    68 => 1,
                   );
        break;
        case 'LowerCaseConstantUnitTest.js':
            return array(
                    2  => 1,
                    3  => 1,
                    4  => 1,
                    7  => 1,
                    8  => 1,
                    12 => 1,
                    13 => 1,
                    14 => 1,
                   );
            break;
        default:
            return array();
            break;
        }

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the ClosingPHPTag sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Andy Grunwald <andygrunwald@gmail.com>
 * @copyright 2010 Andy Grunwald
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ClosingPHPTag sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Andy Grunwald <andygrunwald@gmail.com>
 * @copyright 2010 Andy Grunwald
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_PHP_ClosingPHPTagUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                9 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the CharacterBeforePHPOpeningTag sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Andy Grunwald <andygrunwald@gmail.com>
 * @copyright 2010 Andy Grunwald
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the CharacterBeforePHPOpeningTag sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Andy Grunwald <andygrunwald@gmail.com>
 * @copyright 2010 Andy Grunwald
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_PHP_CharacterBeforePHPOpeningTagUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                2 => 1,
                7 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
if (php_sapi_name() !== 'cli') {}
if (PHP_SAPI !== 'cli') {}
if ($object->php_sapi_name() === true) {}
<?php
$size = sizeof($array);
$size = count($array);
delete($filepath);
unset($filepath);

// No errors thrown for class methods.
$size = MyClass::sizeof($array);
$size = MyClass::count($array);
MyClass::delete($filepath);
MyClass::unset($filepath);

$size = $class->sizeof($array);
$size = $class->count($array);
$class->delete($filepath);
$class->unset($filepath);

function delete() {}
function unset() {}
function sizeof() {}
function count() {}

trait DelProvider {
  public function delete() {
    //irrelevant
  }
}

class LeftSideTest {
    use DelProvider {
        delete as protected unsetter;
    }
}

class RightSideTest {
    use DelProvider {
        delete as delete;
    }
}

class RightSideVisTest {
    use DelProvider {
        delete as protected delete;
        delete insteadof delete;
    }
}

namespace Something\sizeof;

?>
<?php
/**
 * Unit test class for the NoSilencedErrors sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the NoSilencedErrors sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_PHP_NoSilencedErrorsUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array();

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                5 => 1,
               );

    }//end getWarningList()


}//end class

?>
<?php
// A few keywords. Obviously not valid syntax.
class Something extends SomethingElse implements Whatever
abstract public private protected function whatever() {}
const array()
for ($var as $var) { exit; }
if ($a and $b or $c xor $d) { die; } elseif { } else
goto a;

Class Something EXTENDS SomethingElse implementS Whatever
Abstract Public Private Protected function whatever() {}
CONST array()
For ($var As $var) { Exit; }
If ($a AND $b OR $c XOR $d) { Die; } ElseIf { } Else
GOTO a;
?>
<div>
<?php echo $var; ?>
Some content here.
<?= $var; ?>
<? echo $var; ?>
</div>
<?php
/**
 * @see something
 */
if (@in_array($array, $needle))
{
    echo '@';
}
?>
<?php

// True
function myFunction($arg1, $arg2=true)
{
}
function myFunction($arg1, $arg2=TRUE)
{
}
function myFunction($arg1, $arg2=True)
{
}

if ($variable === true) { }
if ($variable === TRUE) { }
if ($variable === True) { }


// False
function myFunction($arg1, $arg2=false)
{
}
function myFunction($arg1, $arg2=FALSE)
{
}
function myFunction($arg1, $arg2=False)
{
}

if ($variable === false) { }
if ($variable === FALSE) { }
if ($variable === False) { }


// Null
function myFunction($arg1, $arg2=null)
{
}
function myFunction($arg1, $arg2=NULL)
{
}
function myFunction($arg1, $arg2=Null)
{
}

if ($variable === null) { }
if ($variable === NULL) { }
if ($variable === Null) { }

$x = new stdClass();
$x->NULL = 7;

use Zend\Log\Writer\NULL as NullWriter;
new \Zend\Log\Writer\NULL()

class True extends Null implements False {}

use Something\True;
class MyClass
{
    public function myFunction()
    {
        $var = array('foo' => new True());
    }
}

$x = $f?FALSE:true;
$x = $f? FALSE:true;
?>
if (variable === true) { }
if (variable === TRUE) { }
if (variable === True) { }
variable = True;

if (variable === false) { }
if (variable === FALSE) { }
if (variable === False) { }
variable = false;

if (variable === null) { }
if (variable === NULL) { }
if (variable === Null) { }
variable = NULL;
<?php
/**
 * Unit test class for the UpperCaseConstant sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the UpperCaseConstant sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_PHP_UpperCaseConstantUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                7  => 1,
                10 => 1,
                15 => 1,
                16 => 1,
                23 => 1,
                26 => 1,
                31 => 1,
                32 => 1,
                39 => 1,
                42 => 1,
                47 => 1,
                48 => 1,
                67 => 1,
                68 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the SAPIUsage sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the SAPIUsage sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_PHP_SAPIUsageUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                2 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php

// True
function myFunction($arg1, $arg2=TRUE)
{
}
function myFunction($arg1, $arg2=true)
{
}
function myFunction($arg1, $arg2=True)
{
}

if ($variable === TRUE) { }
if ($variable === true) { }
if ($variable === True) { }


// False
function myFunction($arg1, $arg2=FALSE)
{
}
function myFunction($arg1, $arg2=false)
{
}
function myFunction($arg1, $arg2=False)
{
}

if ($variable === FALSE) { }
if ($variable === false) { }
if ($variable === False) { }


// Null
function myFunction($arg1, $arg2=NULL)
{
}
function myFunction($arg1, $arg2=null)
{
}
function myFunction($arg1, $arg2=Null)
{
}

if ($variable === NULL) { }
if ($variable === null) { }
if ($variable === Null) { }

$x = new stdClass();
$x->null = 7;

use Zend\Log\Writer\Null as NullWriter;
new \Zend\Log\Writer\Null()

class True extends Null implements False {}

use Something\True;
class MyClass
{
    public function myFunction()
    {
        $var = array('foo' => new True());
    }
}

$x = $f?false:TRUE;
$x = $f? false:TRUE;
?>
<?php
/**
 * Unit test class for the LowerCaseKeyword sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the LowerCaseKeyword sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_PHP_LowerCaseKeywordUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                10 => 3,
                11 => 4,
                12 => 1,
                13 => 3,
                14 => 7,
                15 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
Foo
<?php
// Some code
?>


 <?php
// Some code
?><?php
/**
 * Unit test class for the DisallowShortOpenTag sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the DisallowShortOpenTag sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_PHP_DisallowShortOpenTagUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        $option = (boolean) ini_get('short_open_tag');
        if ($option === true) {
            return array(
                    4 => 1,
                    5 => 1,
                   );
        } else if (version_compare(PHP_VERSION, '5.4.0RC1') >= 0) {
            // Shorthand echo is always available from PHP 5.4.0 but needed the
            // short_open_tag ini var to be set for versions before this.
            return array(
                    4 => 1,
                   );
        }

        return array();

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
echo 'foo';
?>
<b>Bold text</b>
<?php
echo 'bar';
?>
<i>Italic text</i>
<?php
echo 'baz';<?php
/**
 * Unit test class for the MultipleStatementAlignment sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the MultipleStatementAlignment sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_Formatting_MultipleStatementAlignmentUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array();

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getWarningList($testFile='MultipleStatementAlignmentUnitTest.inc')
    {
        switch ($testFile) {
        case 'MultipleStatementAlignmentUnitTest.inc':
            return array(
                    11  => 1,
                    12  => 1,
                    23  => 1,
                    24  => 1,
                    26  => 1,
                    27  => 1,
                    37  => 1,
                    38  => 1,
                    48  => 1,
                    50  => 1,
                    61  => 1,
                    62  => 1,
                    64  => 1,
                    65  => 1,
                    71  => 1,
                    78  => 1,
                    79  => 1,
                    86  => 1,
                    92  => 1,
                    93  => 1,
                    94  => 1,
                    95  => 1,
                    123 => 1,
                    124 => 1,
                    126 => 1,
                    129 => 1,
                    154 => 1,
                    161 => 1,
                    178 => 1,
                    179 => 1,
                    182 => 1,
                   );
        break;
        case 'MultipleStatementAlignmentUnitTest.js':
            return array(
                    11  => 1,
                    12  => 1,
                    23  => 1,
                    24  => 1,
                    26  => 1,
                    27  => 1,
                    37  => 1,
                    38  => 1,
                    48  => 1,
                    50  => 1,
                    61  => 1,
                    62  => 1,
                    64  => 1,
                    65  => 1,
                    71  => 1,
                    78  => 1,
                    79  => 1,
                    81  => 1,
                    82  => 1,
                    83  => 1,
                    85  => 1,
                    86  => 1,
                   );
            break;
        default:
            return array();
            break;
        }

    }//end getWarningList()


}//end class

?>
<?php

$var = (int) $var2;
$var = (int)$var2;
$var = (int)  $var2;

$var = (integer) $var2;
$var = (integer)$var2;
$var = (integer)  $var2;

$var = (string) $var2;
$var = (string)$var2;
$var = (string)  $var2;

$var = (float) $var2;
$var = (float)$var2;
$var = (float)  $var2;

$var = (double) $var2;
$var = (double)$var2;
$var = (double)  $var2;

$var = (real) $var2;
$var = (real)$var2;
$var = (real)  $var2;

$var = (array) $var2;
$var = (array)$var2;
$var = (array)  $var2;

$var = (bool) $var2;
$var = (bool)$var2;
$var = (bool)  $var2;

$var = (boolean) $var2;
$var = (boolean)$var2;
$var = (boolean)  $var2;

$var = (object) $var2;
$var = (object)$var2;
$var = (object)  $var2;

$var = (unset) $var2;
$var = (unset)$var2;
$var = (unset)  $var2;

?>
<?php
/**
 * Unit test class for the DisallowMultipleStatements sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the DisallowMultipleStatements sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_Formatting_DisallowMultipleStatementsUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                2 => 1,
                6 => 1,
                7 => 1,
                8 => 2,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php

$var = (int) $var2;
$var = (int)$var2;
$var = (int)  $var2;

$var = (integer) $var2;
$var = (integer)$var2;
$var = (integer)  $var2;

$var = (string) $var2;
$var = (string)$var2;
$var = (string)  $var2;

$var = (float) $var2;
$var = (float)$var2;
$var = (float)  $var2;

$var = (double) $var2;
$var = (double)$var2;
$var = (double)  $var2;

$var = (real) $var2;
$var = (real)$var2;
$var = (real)  $var2;

$var = (array) $var2;
$var = (array)$var2;
$var = (array)  $var2;

$var = (bool) $var2;
$var = (bool)$var2;
$var = (bool)  $var2;

$var = (boolean) $var2;
$var = (boolean)$var2;
$var = (boolean)  $var2;

$var = (object) $var2;
$var = (object)$var2;
$var = (object)  $var2;

$var = (unset) $var2;
$var = (unset)$var2;
$var = (unset)  $var2;

?>
<?php
$y = 2;;
echo $y;
for ($i = 1; $i < $length; $i++) {}
for (; $i < $length; $i++) {}
echo 'x'; echo $y;
$x = 10; echo $y;
$this->wizardid = 10; $this->paint(); echo 'x';
?>
<?php

// Valid
$var1    = 'var1';
$var10   = 'var1';
$var100  = 'var1';
$var1000 = 'var1';

// Invalid
$var1    = 'var1';
$var10 = 'var1';
$var100 = 'var1';
$var1000 = 'var1';

// Valid
$var1  = 'var1';
$var10 = 'var1';

$var100  = 'var1';
$var1000 = 'var1';

// Invalid
$var1     = 'var1';
$var10    = 'var1';

$var100   = 'var1';
$var1000  = 'var1';

// Valid
$var1    .= 'var1';
$var10   .= 'var1';
$var100  .= 'var1';
$var1000 .= 'var1';

// Invalid
$var1    .= 'var1';
$var10 .= 'var1';
$var100 .= 'var1';
$var1000 .= 'var1';

// Valid
$var1     = 'var1';
$var10   .= 'var1';
$var100   = 'var1';
$var1000 .= 'var1';

// Invalid
$var1    = 'var1';
$var10   .= 'var1';
$var100  = 'var1';
$var1000 .= 'var1';

// Valid
$var1  .= 'var1';
$var10 .= 'var1';

$var100  .= 'var1';
$var1000 .= 'var1';

// Invalid
$var1     .= 'var1';
$var10    .= 'var1';

$var100   .= 'var1';
$var1000  .= 'var1';

// Valid
$var = 100;

// InValid
$var  = 100;

$commentStart = $phpcsFile->findPrevious();
$commentEnd   = $this->_phpcsFile;
$expected    .= '...';

// Invalid
$this->okButton    = new Button();
$content = new MyClass();


$GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] = array();

class MyClass
{
    const MODE_DEBUG = 'debug';
    const MODE_DEBUG2 = 'debug';

    $array[$test] = 'anything';
    $var          = 'anything';

    const MODE_DEBUG2  = 'debug';
    $array[$test]    = 'anything';
    $var             = 'anything';
    $array[($test + 1)] = 'anything';
    $array[($blah + (10 - $test))] = 'anything';
}

function myFunction($var=true)
{
    if ($strict === true) {
        $length          = strlen($string);
        $lastCharWasCaps = ($classFormat === false) ? false : true;

        for ($i = 1; $i < $length; $i++) {
            $isCaps = (strtoupper($string{$i}) === $string{$i}) ? true : false;
            if ($isCaps === true && $lastCharWasCaps === true) {
                return false;
            }

            $lastCharWasCaps = $isCaps;
        }
    }
}

// Valid
for ($i = 0; $i < 10; $i += 2) {
    $i = ($i - 1);
}

// Invalid
foreach ($files as $file) {
    $saves[$file] = array();
    $contents = stripslashes(file_get_contents($file));
    list($assetid, $time, $content) = explode("\n", $contents);
    $saves[$file]['assetid'] = $assetid;
}

$i = ($i - 10);
$ip = ($i - 10);
for ($i = 0; $i < 10; $i += 2) {
    $i = ($i - 10);
}

// Valid
$variable = 12;
$var      = a_very(long_line('that', 'contains'),
                   a_bunch('of long', 'parameters'),
                   'that_need to be aligned with the equal sign');
$var2     = 12;

// Valid
$variable = 12;
$var      = 'a very long line of text that contains '
            .$someVar
            .' and some other stuff that is too long to fit on one line';
$var2     = 12;

// Invalid
$variable = 12;
$var      = a_very(long_line('that', 'contains'),
                   a_bunch('of long', 'parameters'),
                   'that_need to be aligned with the equal sign');
$var2 = 12;

// Invalid
$variable = 12;
$var      = 'a very long line of text that contains '
            .$someVar
            .' and some other stuff that is too long to fit on one line';
$var2 = 12;

// Valid
$variable = 12;
$var     .= 'a very long line of text that contains '
            .$someVar
            .' and some other stuff that is too long to fit on one line';
$var2     = 12;

// Valid
$variable += 12;
$var      .= 'a very long line of text that contains '
            .$someVar
            .' and some other stuff that is too long to fit on one line';
$var2      = 12;

// Invalid
$variable  = 12;
$var      .= 'a very long line of text that contains '
            .$someVar
            .' and some other stuff that is too long to fit on one line';
$var2      = 12;

// Valid
$error = false;
while (list($h, $f) = each($handle)) {
    $error = true;
}

// Valid
$value = false;
function blah ($value = true) {
    $value = false;
    if ($value === true) {
        $value = false;
    }
}

if (TRUE) {
    $args = array('foo' => 'foo');
    $res  = 'bar';
}
?>
<?php
/**
 * Unit test class for the SpaceAfterCast sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the SpaceAfterCast sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_Formatting_SpaceAfterCastUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                4  => 1,
                5  => 1,
                8  => 1,
                9  => 1,
                12 => 1,
                13 => 1,
                16 => 1,
                17 => 1,
                20 => 1,
                21 => 1,
                24 => 1,
                25 => 1,
                28 => 1,
                29 => 1,
                32 => 1,
                33 => 1,
                36 => 1,
                37 => 1,
                40 => 1,
                41 => 1,
                44 => 1,
                45 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the NoSpaceAfterCast sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the NoSpaceAfterCast sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_Formatting_NoSpaceAfterCastUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                3  => 1,
                5  => 1,
                7  => 1,
                9  => 1,
                11 => 1,
                13 => 1,
                15 => 1,
                17 => 1,
                19 => 1,
                21 => 1,
                23 => 1,
                25 => 1,
                27 => 1,
                29 => 1,
                31 => 1,
                33 => 1,
                35 => 1,
                37 => 1,
                39 => 1,
                41 => 1,
                43 => 1,
                45 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>


// Valid
var1    = 'var1';
var10   = 'var1';
var100  = 'var1';
var1000 = 'var1';

// Invalid
var1    = 'var1';
var10 = 'var1';
var100 = 'var1';
var1000 = 'var1';

// Valid
var1  = 'var1';
var10 = 'var1';

var100  = 'var1';
var1000 = 'var1';

// Invalid
var1     = 'var1';
var10    = 'var1';

var100   = 'var1';
var1000  = 'var1';

// Valid
var1    += 'var1';
var10   += 'var1';
var100  += 'var1';
var1000 += 'var1';

// Invalid
var1    += 'var1';
var10 += 'var1';
var100 += 'var1';
var1000 += 'var1';

// Valid
var1     = 'var1';
var10   += 'var1';
var100   = 'var1';
var1000 += 'var1';

// Invalid
var1    = 'var1';
var10   += 'var1';
var100  = 'var1';
var1000 += 'var1';

// Valid
var1  += 'var1';
var10 += 'var1';

var100  += 'var1';
var1000 += 'var1';

// Invalid
var1     += 'var1';
var10    += 'var1';

var100   += 'var1';
var1000  += 'var1';

// Valid
var test = 100;

// InValid
var test  = 100;

commentStart = phpcsFile.findPrevious();
commentEnd   = this._phpcsFile;
expected    += '...';

// Invalid
this.okButton    = {};
content = {};

var buttonid = [this.id, '-positionFormats-add'].join('');
var buttonWidget = WidgetStore.get(buttonid);
var spinButtonid = [this.id, '-positionFormats-spinButton'].join('');
var spinButtonWidget = WidgetStore.get(spinButtonid);
var position = spinButtonWidget.getValue();
var posForamatsList = WidgetStore.get([self.id, '-positionFormats-list'].join(''));

dfx.stripTags = function(content, allowedTags)
{
    var match;
    var re = 'blah';
};

<?php
/**
 * Unit test class for the DuplicateClassName multi-file sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the DuplicateClassName multi-file sniff.
 *
 * A multi-file sniff unit test checks a .1.inc and a .2.inc file for expected violations
 * of a single coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Generic_Tests_Classes_DuplicateClassNameUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array();

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getWarningList($testFile='')
    {
        switch ($testFile) {
        case 'DuplicateClassNameUnitTest.1.inc':
            return array(
                    6 => 1,
                    7 => 1,
                   );
            break;
        case 'DuplicateClassNameUnitTest.2.inc':
            return array(
                    2 => 1,
                    3 => 1,
                   );
            break;
        case 'DuplicateClassNameUnitTest.5.inc':
            return array(
                    3 => 1,
                    7 => 1,
                   );
            break;
        case 'DuplicateClassNameUnitTest.6.inc':
            return array(
                    10 => 1,
                   );
            break;
        default:
            return array();
            break;
        }//end switch

    }//end getWarningList()


}//end class

?>
<?php
class MyClass {}
interface MyInterface {}
?><?php
namespace A\B {
    class MyClass {}
    interface MyInterface {}
}

namespace D {
    class MyClass {}
}
?><?php
class Test{
    public function testOne(){
     ?>
     <p>some html here</p>
    <?php 
   }
}

class Test{

}
<?php
namespace C;
class MyClass {}
interface YourInterface {}

namespace D;
class MyClass {}
?><?php
namespace C;
class MyClass {}
interface MyInterface {}
?><?php
class MyClass {}
class YourClass {}
interface MyInterface {}
interface YourInterface {}
class MyClass {}
interface MyInterface {}
?><?xml version="1.0"?>
<ruleset name="Generic">
 <description>A collection of generic sniffs. This standard is not designed to be used to check code.</description>
</ruleset>
<?php
/**
 * Squiz_Sniffs_Debug_JavaScriptLintSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Debug_JavaScriptLintSniff.
 *
 * Runs JavaScript Lint on the file.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Debug_JavaScriptLintSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('JS');


    /**
     * Returns the token types that this sniff is interested in.
     *
     * @return array(int)
     */
    public function register()
    {
        return array(T_OPEN_TAG);

    }//end register()


    /**
     * Processes the tokens that this sniff is interested in.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        the token was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $fileName = $phpcsFile->getFilename();

        $jslPath = PHP_CodeSniffer::getConfigData('jsl_path');
        if (is_null($jslPath) === true) {
            return;
        }

        $cmd = '"'.$jslPath.'" -nologo -nofilelisting -nocontext -nosummary -output-format __LINE__:__ERROR__ -process "'.$fileName.'"';
        $msg = exec($cmd, $output, $retval);

        // $exitCode is the last line of $output if no error occurs, on error it
        // is numeric. Try to handle various error conditions and provide useful
        // error reporting.
        if ($retval === 2 || $retval === 4) {
            if (is_array($output) === true) {
                $msg = join('\n', $output);
            }

            throw new PHP_CodeSniffer_Exception("Failed invoking JavaScript Lint, retval was [$retval], output was [$msg]");
        }


        if (is_array($output) === true) {
            $tokens = $phpcsFile->getTokens();

            foreach ($output as $finding) {
                $split   = strpos($finding, ':');
                $line    = substr($finding, 0, $split);
                $message = substr($finding, ($split + 1));

                // Find the token at the start of the line.
                $lineToken = null;
                foreach ($tokens as $ptr => $info) {
                    if ($info['line'] == $line) {
                        $lineToken = $ptr;
                        break;
                    }
                }

                if ($lineToken !== null) {
                    $phpcsFile->addWarning(trim($message), $ptr, 'ExternalTool');
                }
            }//end foreach
        }//end if

    }//end process()

}//end class
?>
<?php
/**
 * Squiz_Sniffs_Debug_JSLintSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Debug_JSLintSniff.
 *
 * Runs jslint.js on the file.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Debug_JSLintSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('JS');


    /**
     * Returns the token types that this sniff is interested in.
     *
     * @return array(int)
     */
    public function register()
    {
        return array(T_OPEN_TAG);

    }//end register()


    /**
     * Processes the tokens that this sniff is interested in.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        the token was found.
     *
     * @return void
     * @throws PHP_CodeSniffer_Exception If jslint.js could not be run
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $fileName = $phpcsFile->getFilename();

        $rhinoPath  = PHP_CodeSniffer::getConfigData('rhino_path');
        $jslintPath = PHP_CodeSniffer::getConfigData('jslint_path');
        if ($rhinoPath === null || $jslintPath === null) {
            return;
        }

        $cmd = "$rhinoPath \"$jslintPath\" \"$fileName\"";
        $msg = exec($cmd, $output, $retval);

        if (is_array($output) === true) {
            $tokens = $phpcsFile->getTokens();

            foreach ($output as $finding) {
                $matches    = array();
                $numMatches = preg_match('/Lint at line ([0-9]+).*:(.*)$/', $finding, $matches);
                if ($numMatches === 0) {
                    continue;
                }

                $line    = (int) $matches[1];
                $message = 'jslint says: '.trim($matches[2]);

                // Find the token at the start of the line.
                $lineToken = null;
                foreach ($tokens as $ptr => $info) {
                    if ($info['line'] === $line) {
                        $lineToken = $ptr;
                        break;
                    }
                }

                if ($lineToken !== null) {
                    $phpcsFile->addWarning($message, $lineToken, 'ExternalTool');
                }
            }//end foreach
        }//end if

    }//end process()


}//end class

?>
<?php
/**
 * Verifies that class members have scope modifiers.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_Standards_AbstractScopeSniff', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_Standards_AbstractScopeSniff not found');
}

/**
 * Verifies that class members have scope modifiers.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Scope_MethodScopeSniff extends PHP_CodeSniffer_Standards_AbstractScopeSniff
{


    /**
     * Constructs a Squiz_Sniffs_Scope_MethodScopeSniff.
     */
    public function __construct()
    {
        parent::__construct(array(T_CLASS, T_INTERFACE), array(T_FUNCTION));

    }//end __construct()


    /**
     * Processes the function tokens within the class.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
     * @param int                  $stackPtr  The position where the token was found.
     * @param int                  $currScope The current scope opener token.
     *
     * @return void
     */
    protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope)
    {
        $tokens = $phpcsFile->getTokens();

        $methodName = $phpcsFile->getDeclarationName($stackPtr);
        if ($methodName === null) {
            // Ignore closures.
            return;
        }

        $modifier = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$scopeModifiers, $stackPtr);
        if (($modifier === false) || ($tokens[$modifier]['line'] !== $tokens[$stackPtr]['line'])) {
            $error = 'Visibility must be declared on method "%s"';
            $data  = array($methodName);
            $phpcsFile->addError($error, $stackPtr, 'Missing', $data);
        }

    }//end processTokenWithinScope()


}//end class

?>
<?php
/**
 * Verifies that class members have scope modifiers.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_Standards_AbstractVariableSniff', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_Standards_AbstractVariableSniff not found');
}

/**
 * Verifies that class members have scope modifiers.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Scope_MemberVarScopeSniff extends PHP_CodeSniffer_Standards_AbstractVariableSniff
{


    /**
     * Processes the function tokens within the class.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
     * @param int                  $stackPtr  The position where the token was found.
     *
     * @return void
     */
    protected function processMemberVar(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens   = $phpcsFile->getTokens();
        $modifier = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$scopeModifiers, $stackPtr);

        if (($modifier === false) || ($tokens[$modifier]['line'] !== $tokens[$stackPtr]['line'])) {
            $error = 'Scope modifier not specified for member variable "%s"';
            $data  = array($tokens[$stackPtr]['content']);
            $phpcsFile->addError($error, $stackPtr, 'Missing', $data);
        }

    }//end processMemberVar()


    /**
     * Processes normal variables.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
     * @param int                  $stackPtr  The position where the token was found.
     *
     * @return void
     */
    protected function processVariable(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        // We don't care about normal variables.

    }//end processVariable()


    /**
     * Processes variables in double quoted strings.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
     * @param int                  $stackPtr  The position where the token was found.
     *
     * @return void
     */
    protected function processVariableInString(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        // We don't care about normal variables.

    }//end processVariableInString()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_Scope_StaticThisUsageSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_Standards_AbstractScopeSniff', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_Standards_AbstractScopeSniff not found');
}

/**
 * Squiz_Sniffs_Scope_StaticThisUsageSniff.
 *
 * Checks for usage of "$this" in static methods, which will cause
 * runtime errors.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Scope_StaticThisUsageSniff extends PHP_CodeSniffer_Standards_AbstractScopeSniff
{


    /**
     * Constructs the test with the tokens it wishes to listen for.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct(array(T_CLASS), array(T_FUNCTION));

    }//end __construct()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The current file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     * @param int                  $currScope A pointer to the start of the scope.
     *
     * @return void
     */
    public function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope)
    {
        $tokens   = $phpcsFile->getTokens();
        $function = $tokens[($stackPtr + 2)];

        if ($function['code'] !== T_STRING) {
            return;
        }

        $functionName = $function['content'];
        $classOpener  = $tokens[$currScope]['scope_condition'];
        $className    = $tokens[($classOpener + 2)]['content'];

        $methodProps = $phpcsFile->getMethodProperties($stackPtr);

        if ($methodProps['is_static'] === true) {
            if (isset($tokens[$stackPtr]['scope_closer']) === false) {
                // There is no scope opener or closer, so the function
                // must be abstract.
                return;
            }

            $thisUsage = $stackPtr;
            while (($thisUsage = $phpcsFile->findNext(array(T_VARIABLE), ($thisUsage + 1), $tokens[$stackPtr]['scope_closer'], false, '$this')) !== false) {
                if ($thisUsage === false) {
                    return;
                }

                $error = 'Usage of "$this" in static methods will cause runtime errors';
                $phpcsFile->addError($error, $thisUsage, 'Found');
            }
        }//end if

    }//end processTokenWithinScope()


}//end class

?>
<?php
/**
 * This sniff class detects empty statement.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('Generic_Sniffs_CodeAnalysis_EmptyStatementSniff', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class Generic_Sniffs_CodeAnalysis_EmptyStatementSniff not found');
}

/**
 * This sniff class detects empty statement.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_CodeAnalysis_EmptyStatementSniff extends Generic_Sniffs_CodeAnalysis_EmptyStatementSniff
{

    /**
     * List of block tokens that this sniff covers.
     *
     * The key of this hash identifies the required token while the boolean
     * value says mark an error or mark a warning.
     *
     * @var array
     */
    protected $checkedTokens = array(
                                T_DO      => true,
                                T_ELSE    => true,
                                T_ELSEIF  => true,
                                T_FOR     => true,
                                T_FOREACH => true,
                                T_IF      => true,
                                T_SWITCH  => true,
                                T_WHILE   => true,
                               );

}//end class

?>
<?php
/**
 * Squiz_Sniffs_NamingConventions_ValidFunctionNameSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PEAR_Sniffs_NamingConventions_ValidFunctionNameSniff', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class PEAR_Sniffs_NamingConventions_ValidFunctionNameSniff not found');
}

/**
 * Squiz_Sniffs_NamingConventions_ValidFunctionNameSniff.
 *
 * Ensures method names are correct depending on whether they are public
 * or private, and that functions are named correctly.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_NamingConventions_ValidFunctionNameSniff extends PEAR_Sniffs_NamingConventions_ValidFunctionNameSniff
{


    /**
     * Processes the tokens outside the scope.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being processed.
     * @param int                  $stackPtr  The position where this token was
     *                                        found.
     *
     * @return void
     */
    protected function processTokenOutsideScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $functionName = $phpcsFile->getDeclarationName($stackPtr);
        if ($functionName === null) {
            return;
        }

        $errorData = array($functionName);

        // Does this function claim to be magical?
        if (preg_match('|^__|', $functionName) !== 0) {
            $error = 'Function name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore';
            $phpcsFile->addError($error, $stackPtr, 'DoubleUnderscore', $errorData);
            return;
        }

        if (PHP_CodeSniffer::isCamelCaps($functionName, false, true, false) === false) {
            $error = 'Function name "%s" is not in camel caps format';
            $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData);
        }

    }//end processTokenOutsideScope()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_NamingConventions_ValidFunctionNameSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('Generic_Sniffs_PHP_LowerCaseConstantSniff', true) === false) {
    $error = 'Class Generic_Sniffs_PHP_LowerCaseConstantSniff not found';
    throw new PHP_CodeSniffer_Exception($error);
}

if (class_exists('Generic_Sniffs_PHP_UpperCaseConstantSniff', true) === false) {
    $error = 'Class Generic_Sniffs_PHP_UpperCaseConstantSniff not found';
    throw new PHP_CodeSniffer_Exception($error);
}

/**
 * Squiz_Sniffs_NamingConventions_ConstantCaseSniff.
 *
 * Ensures TRUE, FALSE and NULL are uppercase for PHP and lowercase for JS.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_NamingConventions_ConstantCaseSniff extends Generic_Sniffs_PHP_LowerCaseConstantSniff
{


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        if ($phpcsFile->tokenizerType === 'JS') {
            parent::process($phpcsFile, $stackPtr);
        } else {
            $sniff = new Generic_Sniffs_PHP_UpperCaseConstantSniff;
            $sniff->process($phpcsFile, $stackPtr);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_NamingConventions_ValidVariableNameSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_Standards_AbstractVariableSniff', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_Standards_AbstractVariableSniff not found');
}

/**
 * Squiz_Sniffs_NamingConventions_ValidVariableNameSniff.
 *
 * Checks the naming of variables and member variables.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_NamingConventions_ValidVariableNameSniff extends PHP_CodeSniffer_Standards_AbstractVariableSniff
{

    /**
     * Tokens to ignore so that we can find a DOUBLE_COLON.
     *
     * @var array
     */
    private $_ignore = array(
                        T_WHITESPACE,
                        T_COMMENT,
                       );


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    protected function processVariable(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens  = $phpcsFile->getTokens();
        $varName = ltrim($tokens[$stackPtr]['content'], '$');

        $phpReservedVars = array(
                            '_SERVER',
                            '_GET',
                            '_POST',
                            '_REQUEST',
                            '_SESSION',
                            '_ENV',
                            '_COOKIE',
                            '_FILES',
                            'GLOBALS',
                           );

        // If it's a php reserved var, then its ok.
        if (in_array($varName, $phpReservedVars) === true) {
            return;
        }

        $objOperator = $phpcsFile->findNext(array(T_WHITESPACE), ($stackPtr + 1), null, true);
        if ($tokens[$objOperator]['code'] === T_OBJECT_OPERATOR) {
            // Check to see if we are using a variable from an object.
            $var = $phpcsFile->findNext(array(T_WHITESPACE), ($objOperator + 1), null, true);
            if ($tokens[$var]['code'] === T_STRING) {
                $bracket = $objOperator = $phpcsFile->findNext(array(T_WHITESPACE), ($var + 1), null, true);
                if ($tokens[$bracket]['code'] !== T_OPEN_PARENTHESIS) {
                    $objVarName = $tokens[$var]['content'];

                    // There is no way for us to know if the var is public or
                    // private, so we have to ignore a leading underscore if there is
                    // one and just check the main part of the variable name.
                    $originalVarName = $objVarName;
                    if (substr($objVarName, 0, 1) === '_') {
                        $objVarName = substr($objVarName, 1);
                    }

                    if (PHP_CodeSniffer::isCamelCaps($objVarName, false, true, false) === false) {
                        $error = 'Variable "%s" is not in valid camel caps format';
                        $data  = array($originalVarName);
                        $phpcsFile->addError($error, $var, 'NotCamelCaps', $data);
                    }
                }//end if
            }//end if
        }//end if

        // There is no way for us to know if the var is public or private,
        // so we have to ignore a leading underscore if there is one and just
        // check the main part of the variable name.
        $originalVarName = $varName;
        if (substr($varName, 0, 1) === '_') {
            $objOperator = $phpcsFile->findPrevious(array(T_WHITESPACE), ($stackPtr - 1), null, true);
            if ($tokens[$objOperator]['code'] === T_DOUBLE_COLON) {
                // The variable lives within a class, and is referenced like
                // this: MyClass::$_variable, so we don't know its scope.
                $inClass = true;
            } else {
                $inClass = $phpcsFile->hasCondition($stackPtr, array(T_CLASS, T_INTERFACE));
            }

            if ($inClass === true) {
                $varName = substr($varName, 1);
            }
        }

        if (PHP_CodeSniffer::isCamelCaps($varName, false, true, false) === false) {
            $error = 'Variable "%s" is not in valid camel caps format';
            $data  = array($originalVarName);
            $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $data);
        }

    }//end processVariable()


    /**
     * Processes class member variables.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    protected function processMemberVar(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $varName     = ltrim($tokens[$stackPtr]['content'], '$');
        $memberProps = $phpcsFile->getMemberProperties($stackPtr);
        if (empty($memberProps) === true) {
            // Couldn't get any info about this variable, which
            // generally means it is invalid or possibly has a parse
            // error. Any errors will be reported by the core, so
            // we can ignore it.
            return;
        }

        $public    = ($memberProps['scope'] !== 'private');
        $errorData = array($varName);

        if ($public === true) {
            if (substr($varName, 0, 1) === '_') {
                $error = '%s member variable "%s" must not contain a leading underscore';
                $data  = array(
                          ucfirst($memberProps['scope']),
                          $errorData[0],
                         );
                $phpcsFile->addError($error, $stackPtr, 'PublicHasUnderscore', $data);
                return;
            }
        } else {
            if (substr($varName, 0, 1) !== '_') {
                $error = 'Private member variable "%s" must contain a leading underscore';
                $phpcsFile->addError($error, $stackPtr, 'PrivateNoUnderscore', $errorData);
                return;
            }
        }

        if (PHP_CodeSniffer::isCamelCaps($varName, false, $public, false) === false) {
            $error = 'Variable "%s" is not in valid camel caps format';
            $phpcsFile->addError($error, $stackPtr, 'MemberNotCamelCaps', $errorData);
        }

    }//end processMemberVar()


    /**
     * Processes the variable found within a double quoted string.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the double quoted
     *                                        string.
     *
     * @return void
     */
    protected function processVariableInString(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $phpReservedVars = array(
                            '_SERVER',
                            '_GET',
                            '_POST',
                            '_REQUEST',
                            '_SESSION',
                            '_ENV',
                            '_COOKIE',
                            '_FILES',
                            'GLOBALS',
                           );
        if (preg_match_all('|[^\\\]\${?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)|', $tokens[$stackPtr]['content'], $matches) !== 0) {
            foreach ($matches[1] as $varName) {
                // If it's a php reserved var, then its ok.
                if (in_array($varName, $phpReservedVars) === true) {
                    continue;
                }

                // There is no way for us to know if the var is public or private,
                // so we have to ignore a leading underscore if there is one and just
                // check the main part of the variable name.
                $originalVarName = $varName;
                if (substr($varName, 0, 1) === '_') {
                    if ($phpcsFile->hasCondition($stackPtr, array(T_CLASS, T_INTERFACE)) === true) {
                        $varName = substr($varName, 1);
                    }
                }

                if (PHP_CodeSniffer::isCamelCaps($varName, false, true, false) === false) {
                    $varName = $matches[0];
                    $error = 'Variable "%s" is not in valid camel caps format';
                    $data  = array($originalVarName);
                    $phpcsFile->addError($error, $stackPtr, 'StringNotCamelCaps', $data);
                    
                }
            }
        }//end if

    }//end processVariableInString()


}//end class

?>
<?php
/**
 * A test to ensure that arrays conform to the array coding standard.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * A test to ensure that arrays conform to the array coding standard.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Arrays_ArrayDeclarationSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_ARRAY);

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The current file being checked.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Array keyword should be lower case.
        if (strtolower($tokens[$stackPtr]['content']) !== $tokens[$stackPtr]['content']) {
            $error = 'Array keyword should be lower case; expected "array" but found "%s"';
            $data  = array($tokens[$stackPtr]['content']);
            $phpcsFile->addError($error, $stackPtr, 'NotLowerCase', $data);
        }

        $arrayStart   = $tokens[$stackPtr]['parenthesis_opener'];
        $arrayEnd     = $tokens[$arrayStart]['parenthesis_closer'];
        $keywordStart = $tokens[$stackPtr]['column'];

        if ($arrayStart != ($stackPtr + 1)) {
            $error = 'There must be no space between the Array keyword and the opening parenthesis';
            $phpcsFile->addError($error, $stackPtr, 'SpaceAfterKeyword');
        }

        // Check for empty arrays.
        $content = $phpcsFile->findNext(array(T_WHITESPACE), ($arrayStart + 1), ($arrayEnd + 1), true);
        if ($content === $arrayEnd) {
            // Empty array, but if the brackets aren't together, there's a problem.
            if (($arrayEnd - $arrayStart) !== 1) {
                $error = 'Empty array declaration must have no space between the parentheses';
                $phpcsFile->addError($error, $stackPtr, 'SpaceInEmptyArray');

                // We can return here because there is nothing else to check. All code
                // below can assume that the array is not empty.
                return;
            }
        }

        if ($tokens[$arrayStart]['line'] === $tokens[$arrayEnd]['line']) {
            // Single line array.
            // Check if there are multiple values. If so, then it has to be multiple lines
            // unless it is contained inside a function call or condition.
            $valueCount = 0;
            $commas     = array();
            for ($i = ($arrayStart + 1); $i < $arrayEnd; $i++) {
                // Skip bracketed statements, like function calls.
                if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS) {
                    $i = $tokens[$i]['parenthesis_closer'];
                    continue;
                }

                if ($tokens[$i]['code'] === T_COMMA) {
                    // Before counting this comma, make sure we are not
                    // at the end of the array.
                    $next = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), $arrayEnd, true);
                    if ($next !== false) {
                        $valueCount++;
                        $commas[] = $i;
                    } else {
                        // There is a comma at the end of a single line array.
                        $error = 'Comma not allowed after last value in single-line array declaration';
                        $phpcsFile->addError($error, $i, 'CommaAfterLast');
                    }
                }
            }

            // Now check each of the double arrows (if any).
            $nextArrow = $arrayStart;
            while (($nextArrow = $phpcsFile->findNext(T_DOUBLE_ARROW, ($nextArrow + 1), $arrayEnd)) !== false) {
                if ($tokens[($nextArrow - 1)]['code'] !== T_WHITESPACE) {
                    $content = $tokens[($nextArrow - 1)]['content'];
                    $error   = 'Expected 1 space between "%s" and double arrow; 0 found';
                    $data    = array($content);
                    $phpcsFile->addError($error, $nextArrow, 'NoSpaceBeforeDoubleArrow', $data);
                } else {
                    $spaceLength = strlen($tokens[($nextArrow - 1)]['content']);
                    if ($spaceLength !== 1) {
                        $content = $tokens[($nextArrow - 2)]['content'];
                        $error   = 'Expected 1 space between "%s" and double arrow; %s found';
                        $data    = array(
                                    $content,
                                    $spaceLength,
                                   );
                        $phpcsFile->addError($error, $nextArrow, 'SpaceBeforeDoubleArrow', $data);
                    }
                }

                if ($tokens[($nextArrow + 1)]['code'] !== T_WHITESPACE) {
                    $content = $tokens[($nextArrow + 1)]['content'];
                    $error   = 'Expected 1 space between double arrow and "%s"; 0 found';
                    $data    = array($content);
                    $phpcsFile->addError($error, $nextArrow, 'NoSpaceAfterDoubleArrow', $data);
                } else {
                    $spaceLength = strlen($tokens[($nextArrow + 1)]['content']);
                    if ($spaceLength !== 1) {
                        $content = $tokens[($nextArrow + 2)]['content'];
                        $error   = 'Expected 1 space between double arrow and "%s"; %s found';
                        $data    = array(
                                    $content,
                                    $spaceLength,
                                   );
                        $phpcsFile->addError($error, $nextArrow, 'SpaceAfterDoubleArrow', $data);
                    }
                }
            }//end while

            if ($valueCount > 0) {
                $conditionCheck = $phpcsFile->findPrevious(array(T_OPEN_PARENTHESIS, T_SEMICOLON), ($stackPtr - 1), null, false);

                if (($conditionCheck === false) || ($tokens[$conditionCheck]['line'] !== $tokens[$stackPtr]['line'])) {
                    $error = 'Array with multiple values cannot be declared on a single line';
                    $phpcsFile->addError($error, $stackPtr, 'SingleLineNotAllowed');
                    return;
                }

                // We have a multiple value array that is inside a condition or
                // function. Check its spacing is correct.
                foreach ($commas as $comma) {
                    if ($tokens[($comma + 1)]['code'] !== T_WHITESPACE) {
                        $content = $tokens[($comma + 1)]['content'];
                        $error   = 'Expected 1 space between comma and "%s"; 0 found';
                        $data    = array($content);
                        $phpcsFile->addError($error, $comma, 'NoSpaceAfterComma', $data);
                    } else {
                        $spaceLength = strlen($tokens[($comma + 1)]['content']);
                        if ($spaceLength !== 1) {
                            $content = $tokens[($comma + 2)]['content'];
                            $error   = 'Expected 1 space between comma and "%s"; %s found';
                            $data    = array(
                                        $content,
                                        $spaceLength,
                                       );
                            $phpcsFile->addError($error, $comma, 'SpaceAfterComma', $data);
                        }
                    }

                    if ($tokens[($comma - 1)]['code'] === T_WHITESPACE) {
                        $content     = $tokens[($comma - 2)]['content'];
                        $spaceLength = strlen($tokens[($comma - 1)]['content']);
                        $error       = 'Expected 0 spaces between "%s" and comma; %s found';
                        $data        = array(
                                        $content,
                                        $spaceLength,
                                       );
                        $phpcsFile->addError($error, $comma, 'SpaceBeforeComma', $data);
                    }
                }//end foreach
            }//end if

            return;
        }//end if

        // Check the closing bracket is on a new line.
        $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($arrayEnd - 1), $arrayStart, true);
        if ($tokens[$lastContent]['line'] !== ($tokens[$arrayEnd]['line'] - 1)) {
            $error = 'Closing parenthesis of array declaration must be on a new line';
            $phpcsFile->addError($error, $arrayEnd, 'CloseBraceNewLine');
        } else if ($tokens[$arrayEnd]['column'] !== $keywordStart) {
            // Check the closing bracket is lined up under the a in array.
            $expected = $keywordStart;
            $found    = $tokens[$arrayEnd]['column'];
            $error    = 'Closing parenthesis not aligned correctly; expected %s space(s) but found %s';
            $data     = array(
                         $expected,
                         $found,
                        );
            $phpcsFile->addError($error, $arrayEnd, 'CloseBraceNotAligned', $data);
        }

        $nextToken  = $stackPtr;
        $lastComma  = $stackPtr;
        $keyUsed    = false;
        $singleUsed = false;
        $lastToken  = '';
        $indices    = array();
        $maxLength  = 0;

        // Find all the double arrows that reside in this scope.
        while (($nextToken = $phpcsFile->findNext(array(T_DOUBLE_ARROW, T_COMMA, T_ARRAY), ($nextToken + 1), $arrayEnd)) !== false) {
            $currentEntry = array();

            if ($tokens[$nextToken]['code'] === T_ARRAY) {
                // Let subsequent calls of this test handle nested arrays.
                $indices[] = array('value' => $nextToken);
                $nextToken = $tokens[$tokens[$nextToken]['parenthesis_opener']]['parenthesis_closer'];
                continue;
            }

            if ($tokens[$nextToken]['code'] === T_COMMA) {
                $stackPtrCount = 0;
                if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) {
                    $stackPtrCount = count($tokens[$stackPtr]['nested_parenthesis']);
                }

                if (count($tokens[$nextToken]['nested_parenthesis']) > ($stackPtrCount + 1)) {
                    // This comma is inside more parenthesis than the ARRAY keyword,
                    // then there it is actually a comma used to separate arguments
                    // in a function call.
                    continue;
                }

                if ($keyUsed === true && $lastToken === T_COMMA) {
                    $error = 'No key specified for array entry; first entry specifies key';
                    $phpcsFile->addError($error, $nextToken, 'NoKeySpecified');
                    return;
                }

                if ($keyUsed === false) {
                    if ($tokens[($nextToken - 1)]['code'] === T_WHITESPACE) {
                        $content     = $tokens[($nextToken - 2)]['content'];
                        $spaceLength = strlen($tokens[($nextToken - 1)]['content']);
                        $error       = 'Expected 0 spaces between "%s" and comma; %s found';
                        $data        = array(
                                        $content,
                                        $spaceLength,
                                       );
                        $phpcsFile->addError($error, $nextToken, 'SpaceBeforeComma', $data);
                    }

                    // Find the value, which will be the first token on the line,
                    // excluding the leading whitespace.
                    $valueContent = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($nextToken - 1), null, true);
                    while ($tokens[$valueContent]['line'] === $tokens[$nextToken]['line']) {
                        if ($valueContent === $arrayStart) {
                            // Value must have been on the same line as the array
                            // parenthesis, so we have reached the start of the value.
                            break;
                        }

                        $valueContent--;
                    }

                    $valueContent = $phpcsFile->findNext(T_WHITESPACE, ($valueContent + 1), $nextToken, true);
                    $indices[]    = array('value' => $valueContent);
                    $singleUsed   = true;
                }//end if

                $lastToken = T_COMMA;
                continue;
            }//end if

            if ($tokens[$nextToken]['code'] === T_DOUBLE_ARROW) {
                if ($singleUsed === true) {
                    $error = 'Key specified for array entry; first entry has no key';
                    $phpcsFile->addError($error, $nextToken, 'KeySpecified');
                    return;
                }

                $currentEntry['arrow'] = $nextToken;
                $keyUsed               = true;

                // Find the start of index that uses this double arrow.
                $indexEnd   = $phpcsFile->findPrevious(T_WHITESPACE, ($nextToken - 1), $arrayStart, true);
                $indexStart = $phpcsFile->findPrevious(T_WHITESPACE, $indexEnd, $arrayStart);

                if ($indexStart === false) {
                    $index = $indexEnd;
                } else {
                    $index = ($indexStart + 1);
                }

                $currentEntry['index']         = $index;
                $currentEntry['index_content'] = $phpcsFile->getTokensAsString($index, ($indexEnd - $index + 1));

                $indexLength = strlen($currentEntry['index_content']);
                if ($maxLength < $indexLength) {
                    $maxLength = $indexLength;
                }

                // Find the value of this index.
                $nextContent           = $phpcsFile->findNext(array(T_WHITESPACE), ($nextToken + 1), $arrayEnd, true);
                $currentEntry['value'] = $nextContent;
                $indices[]             = $currentEntry;
                $lastToken             = T_DOUBLE_ARROW;
            }//end if
        }//end while

        // Check for mutli-line arrays that should be single-line.
        $singleValue = false;

        if (empty($indices) === true) {
            $singleValue = true;
        } else if (count($indices) === 1 && $lastToken === T_COMMA) {
            // There may be another array value without a comma.
            $exclude     = PHP_CodeSniffer_Tokens::$emptyTokens;
            $exclude[]   = T_COMMA;
            $nextContent = $phpcsFile->findNext($exclude, ($indices[0]['value'] + 1), $arrayEnd, true);
            if ($nextContent === false) {
                $singleValue = true;
            }
        }

        if ($singleValue === true) {
            // Array cannot be empty, so this is a multi-line array with
            // a single value. It should be defined on single line.
            $error = 'Multi-line array contains a single value; use single-line array instead';
            $phpcsFile->addError($error, $stackPtr, 'MultiLineNotAllowed');
            return;
        }

        /*
            This section checks for arrays that don't specify keys.

            Arrays such as:
               array(
                'aaa',
                'bbb',
                'd',
               );
        */

        if ($keyUsed === false && empty($indices) === false) {
            $count     = count($indices);
            $lastIndex = $indices[($count - 1)]['value'];

            $trailingContent = $phpcsFile->findPrevious(T_WHITESPACE, ($arrayEnd - 1), $lastIndex, true);
            if ($tokens[$trailingContent]['code'] !== T_COMMA) {
                $error = 'Comma required after last value in array declaration';
                $phpcsFile->addError($error, $trailingContent, 'NoCommaAfterLast');
            }

            foreach ($indices as $value) {
                if (empty($value['value']) === true) {
                    // Array was malformed and we couldn't figure out
                    // the array value correctly, so we have to ignore it.
                    // Other parts of this sniff will correct the error.
                    continue;
                }

                if ($tokens[($value['value'] - 1)]['code'] === T_WHITESPACE) {
                    // A whitespace token before this value means that the value
                    // was indented and not flush with the opening parenthesis.
                    if ($tokens[$value['value']]['column'] !== ($keywordStart + 1)) {
                        $error = 'Array value not aligned correctly; expected %s spaces but found %s';
                        $data  = array(
                                  ($keywordStart + 1),
                                  $tokens[$value['value']]['column'],
                                 );
                        $phpcsFile->addError($error, $value['value'], 'ValueNotAligned', $data);
                    }
                }
            }
        }//end if

        /*
            Below the actual indentation of the array is checked.
            Errors will be thrown when a key is not aligned, when
            a double arrow is not aligned, and when a value is not
            aligned correctly.
            If an error is found in one of the above areas, then errors
            are not reported for the rest of the line to avoid reporting
            spaces and columns incorrectly. Often fixing the first
            problem will fix the other 2 anyway.

            For example:

            $a = array(
                  'index'  => '2',
                 );

            In this array, the double arrow is indented too far, but this
            will also cause an error in the value's alignment. If the arrow were
            to be moved back one space however, then both errors would be fixed.
        */

        $numValues = count($indices);

        $indicesStart = ($keywordStart + 1);
        $arrowStart   = ($indicesStart + $maxLength + 1);
        $valueStart   = ($arrowStart + 3);
        foreach ($indices as $index) {
            if (isset($index['index']) === false) {
                // Array value only.
                if (($tokens[$index['value']]['line'] === $tokens[$stackPtr]['line']) && ($numValues > 1)) {
                    $error = 'The first value in a multi-value array must be on a new line';
                    $phpcsFile->addError($error, $stackPtr, 'FirstValueNoNewline');
                }

                continue;
            }

            if (($tokens[$index['index']]['line'] === $tokens[$stackPtr]['line'])) {
                $error = 'The first index in a multi-value array must be on a new line';
                $phpcsFile->addError($error, $stackPtr, 'FirstIndexNoNewline');
                continue;
            }

            if ($tokens[$index['index']]['column'] !== $indicesStart) {
                $error = 'Array key not aligned correctly; expected %s spaces but found %s';
                $data  = array(
                          ($indicesStart - 1),
                          ($tokens[$index['index']]['column'] - 1),
                         );
                $phpcsFile->addError($error, $index['index'], 'KeyNotAligned', $data);
                continue;
            }

            if ($tokens[$index['arrow']]['column'] !== $arrowStart) {
                $expected = ($arrowStart - (strlen($index['index_content']) + $tokens[$index['index']]['column']));
                $found    = ($tokens[$index['arrow']]['column'] - (strlen($index['index_content']) + $tokens[$index['index']]['column']));

                $error = 'Array double arrow not aligned correctly; expected %s space(s) but found %s';
                $data  = array(
                          $expected,
                          $found,
                         );
                $phpcsFile->addError($error, $index['arrow'], 'DoubleArrowNotAligned', $data);
                continue;
            }

            if ($tokens[$index['value']]['column'] !== $valueStart) {
                $expected = ($valueStart - (strlen($tokens[$index['arrow']]['content']) + $tokens[$index['arrow']]['column']));
                $found    = ($tokens[$index['value']]['column'] - (strlen($tokens[$index['arrow']]['content']) + $tokens[$index['arrow']]['column']));

                $error = 'Array value not aligned correctly; expected %s space(s) but found %s';
                $data  = array(
                          $expected,
                          $found,
                         );
                $phpcsFile->addError($error, $index['arrow'], 'ValueNotAligned', $data);
            }

            // Check each line ends in a comma.
            if ($tokens[$index['value']]['code'] !== T_ARRAY) {
                $valueLine = $tokens[$index['value']]['line'];
                $nextComma = false;
                for ($i = ($index['value'] + 1); $i < $arrayEnd; $i++) {
                    // Skip bracketed statements, like function calls.
                    if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS) {
                        $i         = $tokens[$i]['parenthesis_closer'];
                        $valueLine = $tokens[$i]['line'];
                        continue;
                    }

                    if ($tokens[$i]['code'] === T_COMMA) {
                        $nextComma = $i;
                        break;
                    }
                }

                if (($nextComma === false) || ($tokens[$nextComma]['line'] !== $valueLine)) {
                    $error = 'Each line in an array declaration must end in a comma';
                    $phpcsFile->addError($error, $index['value'], 'NoComma');
                }

                // Check that there is no space before the comma.
                if ($nextComma !== false && $tokens[($nextComma - 1)]['code'] === T_WHITESPACE) {
                    $content     = $tokens[($nextComma - 2)]['content'];
                    $spaceLength = strlen($tokens[($nextComma - 1)]['content']);
                    $error       = 'Expected 0 spaces between "%s" and comma; %s found';
                    $data        = array(
                                    $content,
                                    $spaceLength,
                                   );
                    $phpcsFile->addError($error, $nextComma, 'SpaceBeforeComma', $data);
                }
            }
        }//end foreach

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_Arrays_ArrayBracketSpacingSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Arrays_ArrayBracketSpacingSniff.
 *
 * Ensure that there are no spaces around square brackets.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Arrays_ArrayBracketSpacingSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_OPEN_SQUARE_BRACKET,
                T_CLOSE_SQUARE_BRACKET,
               );

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The current file being checked.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // PHP 5.4 introduced a shorthand array declaration syntax, so we need
        // to ignore the these type of array declarations because this sniff is
        // only dealing with array usage.
        if ($tokens[$stackPtr]['code'] === T_OPEN_SQUARE_BRACKET) {
            $openBracket = $stackPtr;
        } else {
            $openBracket = $tokens[$stackPtr]['bracket_opener'];
        }

        $prev = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($openBracket - 1), null, true);
        if ($tokens[$prev]['code'] === T_EQUAL) {
            return;
        }

        // Square brackets can not have a space before them.
        $prevType = $tokens[($stackPtr - 1)]['code'];
        if (in_array($prevType, PHP_CodeSniffer_Tokens::$emptyTokens) === true) {
            $nonSpace = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr - 2), null, true);
            $expected = $tokens[$nonSpace]['content'].$tokens[$stackPtr]['content'];
            $found    = $phpcsFile->getTokensAsString($nonSpace, ($stackPtr - $nonSpace)).$tokens[$stackPtr]['content'];
            $error    = 'Space found before square bracket; expected "%s" but found "%s"';
            $data     = array(
                         $expected,
                         $found,
                        );
            $phpcsFile->addError($error, $stackPtr, 'SpaceBeforeBracket', $data);
        }

        // Open square brackets can't ever have spaces after them.
        if ($tokens[$stackPtr]['code'] === T_OPEN_SQUARE_BRACKET) {
            $nextType = $tokens[($stackPtr + 1)]['code'];
            if (in_array($nextType, PHP_CodeSniffer_Tokens::$emptyTokens) === true) {
                $nonSpace = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr + 2), null, true);
                $expected = $tokens[$stackPtr]['content'].$tokens[$nonSpace]['content'];
                $found    = $phpcsFile->getTokensAsString($stackPtr, ($nonSpace - $stackPtr + 1));
                $error    = 'Space found after square bracket; expected "%s" but found "%s"';
                $data     = array(
                             $expected,
                             $found,
                            );
                $phpcsFile->addError($error, $stackPtr, 'SpaceAfterBracket', $data);
            }
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_WhiteSpace_SemicolonSpacingSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_WhiteSpace_SemicolonSpacingSniff.
 *
 * Ensure there is no whitespace before a semicolon.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_WhiteSpace_SemicolonSpacingSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                  );

    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_SEMICOLON);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $prevType = $tokens[($stackPtr - 1)]['code'];
        if (in_array($prevType, PHP_CodeSniffer_Tokens::$emptyTokens) === true) {
            $nonSpace = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr - 2), null, true);
            $expected = $tokens[$nonSpace]['content'].';';
            $found    = $phpcsFile->getTokensAsString($nonSpace, ($stackPtr - $nonSpace)).';';
            $error    = 'Space found before semicolon; expected "%s" but found "%s"';
            $data     = array(
                         $expected,
                         $found,
                        );
            $phpcsFile->addError($error, $stackPtr, 'Incorrect', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_WhiteSpace_ObjectOperatorSpacingSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_WhiteSpace_ObjectOperatorSpacingSniff.
 *
 * Ensure there is no whitespace before a semicolon.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_WhiteSpace_ObjectOperatorSpacingSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_OBJECT_OPERATOR);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $prevType = $tokens[($stackPtr - 1)]['code'];
        if (in_array($prevType, PHP_CodeSniffer_Tokens::$emptyTokens) === true) {
            $error = 'Space found before object operator';
            $phpcsFile->addError($error, $stackPtr, 'Before');
        }

        $nextType = $tokens[($stackPtr + 1)]['code'];
        if (in_array($nextType, PHP_CodeSniffer_Tokens::$emptyTokens) === true) {
            $error = 'Space found after object operator';
            $phpcsFile->addError($error, $stackPtr, 'After');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_WhiteSpace_CastSpacingSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_WhiteSpace_CastSpacingSniff.
 *
 * Ensure cast statements don't contain whitespace.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_WhiteSpace_CastSpacingSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return PHP_CodeSniffer_Tokens::$castTokens;

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $content  = $tokens[$stackPtr]['content'];
        $expected = str_replace(' ', '', $content);
        $expected = str_replace("\t", '', $expected);

        if ($content !== $expected) {
            $error = 'Cast statements must not contain whitespace; expected "%s" but found "%s"';
            $data  = array(
                      $expected,
                      $content,
                     );
            $phpcsFile->addError($error, $stackPtr, 'ContainsWhiteSpace', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_WhiteSpace_ControlStructureSpacingSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_WhiteSpace_ControlStructureSpacingSniff.
 *
 * Checks that control structures have the correct spacing around brackets.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_WhiteSpace_ControlStructureSpacingSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                  );


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_IF,
                T_WHILE,
                T_FOREACH,
                T_FOR,
                T_SWITCH,
                T_DO,
                T_ELSE,
                T_ELSEIF,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if (isset($tokens[$stackPtr]['scope_closer']) === false) {
            return;
        }

        if (isset($tokens[$stackPtr]['parenthesis_opener']) === true) {
            $parenOpener = $tokens[$stackPtr]['parenthesis_opener'];
            $parenCloser = $tokens[$stackPtr]['parenthesis_closer'];
            if ($tokens[($parenOpener + 1)]['code'] === T_WHITESPACE) {
                $gap   = strlen($tokens[($parenOpener + 1)]['content']);
                $error = 'Expected 0 spaces after opening bracket; %s found';
                $data  = array($gap);
                $phpcsFile->addError($error, ($parenOpener + 1), 'SpacingAfterOpenBrace', $data);
            }

            if ($tokens[$parenOpener]['line'] === $tokens[$parenCloser]['line']
                && $tokens[($parenCloser - 1)]['code'] === T_WHITESPACE
            ) {
                $gap   = strlen($tokens[($parenCloser - 1)]['content']);
                $error = 'Expected 0 spaces before closing bracket; %s found';
                $data  = array($gap);
                $phpcsFile->addError($error, ($parenCloser - 1), 'SpaceBeforeCloseBrace', $data);
            }
        }//end if

        $scopeOpener = $tokens[$stackPtr]['scope_opener'];
        $scopeCloser = $tokens[$stackPtr]['scope_closer'];

        $firstContent = $phpcsFile->findNext(
            T_WHITESPACE,
            ($scopeOpener + 1),
            null,
            true
        );

        if ($tokens[$firstContent]['line'] !== ($tokens[$scopeOpener]['line'] + 1)) {
            $error = 'Blank line found at start of control structure';
            $phpcsFile->addError($error, $scopeOpener, 'SpacingBeforeOpen');
        }

        $lastContent = $phpcsFile->findPrevious(
            T_WHITESPACE,
            ($scopeCloser - 1),
            null,
            true
        );

        if ($tokens[$lastContent]['line'] !== ($tokens[$scopeCloser]['line'] - 1)) {
            $errorToken = $scopeCloser;
            for ($i = ($scopeCloser - 1); $i > $lastContent; $i--) {
                if ($tokens[$i]['line'] < $tokens[$scopeCloser]['line']) {
                    $errorToken = $i;
                    break;
                }
            }

            $error = 'Blank line found at end of control structure';
            $phpcsFile->addError($error, $errorToken, 'SpacingAfterClose');
        }

        $trailingContent = $phpcsFile->findNext(
            T_WHITESPACE,
            ($scopeCloser + 1),
            null,
            true
        );

        if ($tokens[$trailingContent]['code'] === T_ELSE) {
            if ($tokens[$stackPtr]['code'] === T_IF) {
                // IF with ELSE.
                return;
            }
        }

        if ($tokens[$trailingContent]['code'] === T_COMMENT) {
            if ($tokens[$trailingContent]['line'] === $tokens[$scopeCloser]['line']) {
                if (substr($tokens[$trailingContent]['content'], 0, 5) === '//end') {
                    // There is an end comment, so we have to get the next piece
                    // of content.
                    $trailingContent = $phpcsFile->findNext(
                        T_WHITESPACE,
                        ($trailingContent + 1),
                        null,
                        true
                    );
                }
            }
        }

        // If this token is closing a CASE or DEFAULT, we don't need the
        // blank line after this control structure.
        if (isset($tokens[$trailingContent]['scope_condition']) === true) {
            $condition = $tokens[$trailingContent]['scope_condition'];
            if ($tokens[$condition]['code'] === T_CASE
                || $tokens[$condition]['code'] === T_DEFAULT
            ) {
                return;
            }
        }

        if ($tokens[$trailingContent]['code'] === T_CLOSE_TAG) {
            // At the end of the script or embedded code.
            return;
        }

        if ($tokens[$trailingContent]['code'] === T_CLOSE_CURLY_BRACKET) {
            // Another control structure's closing brace.
            if (isset($tokens[$trailingContent]['scope_condition']) === true) {
                $owner = $tokens[$trailingContent]['scope_condition'];
                if ($tokens[$owner]['code'] === T_FUNCTION) {
                    // The next content is the closing brace of a function
                    // so normal function rules apply and we can ignore it.
                    return;
                }
            }

            if ($tokens[$trailingContent]['line'] !== ($tokens[$scopeCloser]['line'] + 1)) {
                $error = 'Blank line found after control structure';
                $phpcsFile->addError($error, $scopeCloser, 'LineAfterClose');
            }
        } else {
            if ($tokens[$trailingContent]['line'] === ($tokens[$scopeCloser]['line'] + 1)) {
                $error = 'No blank line found after control structure';
                $phpcsFile->addError($error, $scopeCloser, 'NoLineAfterClose');
            }
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_WhiteSpace_LanguageConstructSpacingSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_WhiteSpace_LanguageConstructSpacingSniff.
 *
 * Ensures all language constructs (without brackets) contain a
 * single space between themselves and their content.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_WhiteSpace_LanguageConstructSpacingSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_ECHO,
                T_PRINT,
                T_RETURN,
                T_INCLUDE,
                T_INCLUDE_ONCE,
                T_REQUIRE,
                T_REQUIRE_ONCE,
                T_NEW,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if ($tokens[($stackPtr + 1)]['code'] === T_SEMICOLON) {
            // No content for this language construct.
            return;
        }

        if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) {
            $content       = $tokens[($stackPtr + 1)]['content'];
            $contentLength = strlen($content);
            if ($contentLength !== 1) {
                $error = 'Language constructs must be followed by a single space; expected 1 space but found %s';
                $data  = array($contentLength);
                $phpcsFile->addError($error, $stackPtr, 'IncorrectSingle', $data);
            }
        } else {
            $error = 'Language constructs must be followed by a single space; expected "%s" but found "%s"';
            $data  = array(
                      $tokens[$stackPtr]['content'].' '.$tokens[($stackPtr + 1)]['content'],
                      $tokens[$stackPtr]['content'].$tokens[($stackPtr + 1)]['content'],
                     );
            $phpcsFile->addError($error, $stackPtr, 'Incorrect', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Verifies that class members are spaced correctly.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_Standards_AbstractVariableSniff', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_Standards_AbstractVariableSniff not found');
}

/**
 * Verifies that class members are spaced correctly.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_WhiteSpace_MemberVarSpacingSniff extends PHP_CodeSniffer_Standards_AbstractVariableSniff
{


    /**
     * Processes the function tokens within the class.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
     * @param int                  $stackPtr  The position where the token was found.
     *
     * @return void
     */
    protected function processMemberVar(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // There needs to be 1 blank line before the var, not counting comments.
        $prevLineToken = null;
        for ($i = ($stackPtr - 1); $i > 0; $i--) {
            if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$commentTokens) === true) {
                // Skip comments.
                continue;
            } else if (strpos($tokens[$i]['content'], $phpcsFile->eolChar) === false) {
                // Not the end of the line.
                continue;
            } else {
                // If this is a WHITESPACE token, and the token right before
                // it is a DOC_COMMENT, then it is just the newline after the
                // member var's comment, and can be skipped.
                if ($tokens[$i]['code'] === T_WHITESPACE && in_array($tokens[($i - 1)]['code'], PHP_CodeSniffer_Tokens::$commentTokens) === true) {
                    continue;
                }

                $prevLineToken = $i;
                break;
            }
        }

        if (is_null($prevLineToken) === true) {
            // Never found the previous line, which means
            // there are 0 blank lines before the member var.
            $foundLines = 0;
        } else {
            $prevContent = $phpcsFile->findPrevious(array(T_WHITESPACE, T_DOC_COMMENT), $prevLineToken, null, true);
            $foundLines  = ($tokens[$prevLineToken]['line'] - $tokens[$prevContent]['line']);
        }//end if

        if ($foundLines !== 1) {
            $error = 'Expected 1 blank line before member var; %s found';
            $data  = array($foundLines);
            $phpcsFile->addError($error, $stackPtr, 'After', $data);
        }

    }//end processMemberVar()


    /**
     * Processes normal variables.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
     * @param int                  $stackPtr  The position where the token was found.
     *
     * @return void
     */
    protected function processVariable(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        // We don't care about normal variables.

    }//end processVariable()


    /**
     * Processes variables in double quoted strings.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
     * @param int                  $stackPtr  The position where the token was found.
     *
     * @return void
     */
    protected function processVariableInString(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        // We don't care about normal variables.

    }//end processVariableInString()


}//end class

?>
<?php
/**
 * Sniffs_Squiz_WhiteSpace_OperatorSpacingSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Sniffs_Squiz_WhiteSpace_OperatorSpacingSniff.
 *
 * Verifies that operators have valid spacing surrounding them.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_WhiteSpace_LogicalOperatorSpacingSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                  );


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return PHP_CodeSniffer_Tokens::$booleanOperators;

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The current file being checked.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Check there is one space before the operator.
        if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE) {
            $error = 'Expected 1 space before logical operator; 0 found';
            $phpcsFile->addError($error, $stackPtr, 'NoSpaceBefore');
        } else {
            $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
            if ($tokens[$stackPtr]['line'] === $tokens[$prev]['line']
                && strlen($tokens[($stackPtr - 1)]['content']) !== 1
            ) {
                $found = strlen($tokens[($stackPtr - 1)]['content']);
                $error = 'Expected 1 space before logical operator; %s found';
                $data  = array($found);
                $phpcsFile->addError($error, $stackPtr, 'TooMuchSpaceBefore', $data);
            }
        }

        // Check there is one space after the operator.
        if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) {
            $error = 'Expected 1 space after logical operator; 0 found';
            $phpcsFile->addError($error, $stackPtr, 'NoSpaceAfter');
        } else {
            $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
            if ($tokens[$stackPtr]['line'] === $tokens[$next]['line']
                && strlen($tokens[($stackPtr + 1)]['content']) !== 1
            ) {
                $found = strlen($tokens[($stackPtr + 1)]['content']);
                $error = 'Expected 1 space after logical operator; %s found';
                $data  = array($found);
                $phpcsFile->addError($error, $stackPtr, 'TooMuchSpaceAfter', $data);
            }
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_WhiteSpace_ScopeKeywordSpacingSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_WhiteSpace_ScopeKeywordSpacingSniff.
 *
 * Ensure there is a single space after scope keywords.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_WhiteSpace_ScopeKeywordSpacingSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        $register   = PHP_CodeSniffer_Tokens::$scopeModifiers;
        $register[] = T_STATIC;
        return $register;

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
        $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);

        if ($tokens[$stackPtr]['code'] === T_STATIC
            && ($tokens[$nextToken]['code'] === T_DOUBLE_COLON
            || $tokens[$prevToken]['code'] === T_NEW)
        ) {
            // Late static binding, e.g., static:: OR new static() usage.
            return;
        }

        $nextToken = $tokens[($stackPtr + 1)];
        if ($nextToken['code'] !== T_WHITESPACE
            || strlen($nextToken['content']) !== 1
            || $nextToken['content'] === $phpcsFile->eolChar
        ) {
            $error = 'Scope keyword "%s" must be followed by a single space';
            $data  = array($tokens[$stackPtr]['content']);
            $phpcsFile->addError($error, $stackPtr, 'Incorrect', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_Whitespace_ScopeClosingBraceSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Whitespace_ScopeClosingBraceSniff.
 *
 * Checks that the closing braces of scopes are aligned correctly.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_WhiteSpace_ScopeClosingBraceSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return PHP_CodeSniffer_Tokens::$scopeOpeners;

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile All the tokens found in the document.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // If this is an inline condition (ie. there is no scope opener), then
        // return, as this is not a new scope.
        if (isset($tokens[$stackPtr]['scope_closer']) === false) {
            return;
        }

        // We need to actually find the first piece of content on this line,
        // as if this is a method with tokens before it (public, static etc)
        // or an if with an else before it, then we need to start the scope
        // checking from there, rather than the current token.
        $lineStart = ($stackPtr - 1);
        for ($lineStart; $lineStart > 0; $lineStart--) {
            if (strpos($tokens[$lineStart]['content'], $phpcsFile->eolChar) !== false) {
                break;
            }
        }

        // We found a new line, now go forward and find the
        // first non-whitespace token.
        $lineStart = $phpcsFile->findNext(array(T_WHITESPACE), ($lineStart + 1), null, true);

        $startColumn = $tokens[$lineStart]['column'];
        $scopeStart  = $tokens[$stackPtr]['scope_opener'];
        $scopeEnd    = $tokens[$stackPtr]['scope_closer'];

        // Check that the closing brace is on it's own line.
        $lastContent = $phpcsFile->findPrevious(array(T_WHITESPACE), ($scopeEnd - 1), $scopeStart, true);
        if ($tokens[$lastContent]['line'] === $tokens[$scopeEnd]['line']) {
            $error = 'Closing brace must be on a line by itself';
            $phpcsFile->addError($error, $scopeEnd, 'ContentBefore');
            return;
        }

        // Check now that the closing brace is lined up correctly.
        $braceIndent = $tokens[$scopeEnd]['column'];
        if (in_array($tokens[$stackPtr]['code'], array(T_CASE, T_DEFAULT)) === false) {
            if ($braceIndent !== $startColumn) {
                $error = 'Closing brace indented incorrectly; expected %s spaces, found %s';
                $data  = array(
                          ($startColumn - 1),
                          ($braceIndent - 1),
                         );
                $phpcsFile->addError($error, $scopeEnd, 'Indent', $data);
            }
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_WhiteSpace_SuperfluousWhitespaceSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_WhiteSpace_SuperfluousWhitespaceSniff.
 *
 * Checks that no whitespace proceeds the first content of the file, exists
 * after the last content of the file, resides after content on any line, or
 * are two empty lines in functions.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_WhiteSpace_SuperfluousWhitespaceSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                   'CSS',
                                  );

    /**
     * If TRUE, whitespace rules are not checked for blank lines.
     *
     * Blank lines are those that contain only whitespace.
     *
     * @var boolean
     */
    public $ignoreBlankLines = false;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_OPEN_TAG,
                T_CLOSE_TAG,
                T_WHITESPACE,
                T_COMMENT,
               );

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if ($tokens[$stackPtr]['code'] === T_OPEN_TAG) {

            /*
                Check for start of file whitespace.
            */

            if ($phpcsFile->tokenizerType !== 'PHP') {
                // The first token is always the open tag inserted when tokenizsed
                // and the second token is always the first piece of content in
                // the file. If the second token is whitespace, there was
                // whitespace at the start of the file.
                if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) {
                    return;
                }
            } else {
                // If its the first token, then there is no space.
                if ($stackPtr === 0) {
                    return;
                }

                for ($i = ($stackPtr - 1); $i >= 0; $i--) {
                    // If we find something that isn't inline html then there is something previous in the file.
                    if ($tokens[$i]['type'] !== 'T_INLINE_HTML') {
                        return;
                    }

                    // If we have ended up with inline html make sure it isn't just whitespace.
                    $tokenContent = trim($tokens[$i]['content']);
                    if ($tokenContent !== '') {
                        return;
                    }
                }
            }//end if

            $phpcsFile->addError('Additional whitespace found at start of file', $stackPtr, 'StartFile');

        } else if ($tokens[$stackPtr]['code'] === T_CLOSE_TAG) {

            /*
                Check for end of file whitespace.
            */

            if ($phpcsFile->tokenizerType === 'JS') {
                // The last token is always the close tag inserted when tokenized
                // and the second last token is always the last piece of content in
                // the file. If the second last token is whitespace, there was
                // whitespace at the end of the file.
                $stackPtr--;
            } else if ($phpcsFile->tokenizerType === 'CSS') {
                // The last two tokens are always the close tag and whitespace
                // inserted when tokenizsed and the third last token is always the
                // last piece of content in the file. If the third last token is
                // whitespace, there was whitespace at the end of the file.
                $stackPtr -= 2;
            }

            if ($phpcsFile->tokenizerType === 'PHP') {
                if (isset($tokens[($stackPtr + 1)]) === false) {
                    // The close PHP token is the last in the file.
                    return;
                }

                for ($i = ($stackPtr + 1); $i < $phpcsFile->numTokens; $i++) {
                    // If we find something that isn't inline html then there
                    // is more to the file.
                    if ($tokens[$i]['type'] !== 'T_INLINE_HTML') {
                        return;
                    }

                    // If we have ended up with inline html make sure it
                    // isn't just whitespace.
                    $tokenContent = trim($tokens[$i]['content']);
                    if (empty($tokenContent) === false) {
                        return;
                    }
                }
            } else {
                // The pointer is now looking at the last content in the file and
                // not the fake PHP end tag the tokenizer inserted.
                if ($tokens[$stackPtr]['code'] !== T_WHITESPACE) {
                    return;
                }

                // Allow a single newline at the end of the last line in the file.
                if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE
                    && $tokens[$stackPtr]['content'] === $phpcsFile->eolChar
                ) {
                    return;
                }

            }

            $phpcsFile->addError('Additional whitespace found at end of file', $stackPtr, 'EndFile');

        } else {

            /*
                Check for end of line whitespace.
            */

            // Ignore whitespace that is not at the end of a line.
            if (strpos($tokens[$stackPtr]['content'], $phpcsFile->eolChar) === false) {
                return;
            }

            // Ignore blank lines if required.
            if ($this->ignoreBlankLines === true
                && $tokens[($stackPtr - 1)]['line'] !== $tokens[$stackPtr]['line']
            ) {
                return;
            }

            $tokenContent = rtrim($tokens[$stackPtr]['content'], $phpcsFile->eolChar);
            if (empty($tokenContent) === false) {
                if (preg_match('|^.*\s+$|', $tokenContent) !== 0) {
                    $phpcsFile->addError('Whitespace found at end of line', $stackPtr, 'EndLine');
                }
            }

            /*
                Check for multiple blanks lines in a function.
            */

            if ($phpcsFile->hasCondition($stackPtr, T_FUNCTION) === true) {
                if ($tokens[($stackPtr - 1)]['line'] < $tokens[$stackPtr]['line'] && $tokens[($stackPtr - 2)]['line'] === $tokens[($stackPtr - 1)]['line']) {
                    // This is an empty line and the line before this one is not
                    //  empty, so this could be the start of a multiple empty
                    // line block.
                    $next  = $phpcsFile->findNext(T_WHITESPACE, $stackPtr, null, true);
                    $lines = $tokens[$next]['line'] - $tokens[$stackPtr]['line'];
                    if ($lines > 1) {
                        $error = 'Functions must not contain multiple empty lines in a row; found %s empty lines';
                        $data  = array($lines);
                        $phpcsFile->addError($error, $stackPtr, 'EmptyLines', $data);
                    }
                }
            }

        }//end if

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_WhiteSpace_FunctionClosingBraceSpaceSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_WhiteSpace_FunctionClosingBraceSpaceSniff.
 *
 * Checks that there is one empty line before the closing brace of a function.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_WhiteSpace_FunctionClosingBraceSpaceSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                  );


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_FUNCTION);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if (isset($tokens[$stackPtr]['scope_closer']) === false) {
            // Probably an interface method.
            return;
        }

        $closeBrace  = $tokens[$stackPtr]['scope_closer'];
        $prevContent = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBrace - 1), null, true);

        // Special case for empty JS functions
        if ($phpcsFile->tokenizerType === 'JS' && $prevContent === $tokens[$stackPtr]['scope_opener']) {
            // In this case, the opening and closing brace must be
            // right next to each other.
            if ($tokens[$stackPtr]['scope_closer'] !== ($tokens[$stackPtr]['scope_opener'] + 1)) {
                $error = 'The opening and closing braces of empty functions must be directly next to each other; e.g., function () {}';
                $phpcsFile->addError($error, $closeBrace, 'SpacingBetween');
            }

            return;
        }

        $braceLine = $tokens[$closeBrace]['line'];
        $prevLine  = $tokens[$prevContent]['line'];

        $found = ($braceLine - $prevLine - 1);
        if ($phpcsFile->hasCondition($stackPtr, T_FUNCTION) === true || isset($tokens[$stackPtr]['nested_parenthesis']) === true) {
            // Nested function.
            if ($found < 0) {
                $error = 'Closing brace of nested function must be on a new line';
                $phpcsFile->addError($error, $closeBrace, 'ContentBeforeClose');
            } else if ($found > 0) {
                $error = 'Expected 0 blank lines before closing brace of nested function; %s found';
                $data  = array($found);
                $phpcsFile->addError($error, $closeBrace, 'SpacingBeforeNestedClose', $data);
            }
        } else {
            if ($found !== 1) {
                $error = 'Expected 1 blank line before closing function brace; %s found';
                $data  = array($found);
                $phpcsFile->addError($error, $closeBrace, 'SpacingBeforeClose', $data);
            }
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_Formatting_FunctionSpacingSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_WhiteSpace_FunctionSpacingSniff.
 *
 * Checks the separation between methods in a class or interface.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_WhiteSpace_FunctionSpacingSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * The number of blank lines between functions.
     *
     * @var int
     */
    public $spacing = 2;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_FUNCTION);

    }//end register()


    /**
     * Processes this sniff when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens        = $phpcsFile->getTokens();
        $this->spacing = (int) $this->spacing;

        /*
            Check the number of blank lines
            after the function.
        */

        if (isset($tokens[$stackPtr]['scope_closer']) === false) {
            // Must be an interface method, so the closer is the semi-colon.
            $closer = $phpcsFile->findNext(T_SEMICOLON, $stackPtr);
        } else {
            $closer = $tokens[$stackPtr]['scope_closer'];
        }

        $nextLineToken = null;
        for ($i = $closer; $i < $phpcsFile->numTokens; $i++) {
            if (strpos($tokens[$i]['content'], $phpcsFile->eolChar) === false) {
                continue;
            } else {
                $nextLineToken = ($i + 1);
                break;
            }
        }

        if (is_null($nextLineToken) === true) {
            // Never found the next line, which means
            // there are 0 blank lines after the function.
            $foundLines = 0;
        } else {
            $nextContent = $phpcsFile->findNext(array(T_WHITESPACE), ($nextLineToken + 1), null, true);
            if ($nextContent === false) {
                // We are at the end of the file.
                $foundLines = 0;
            } else {
                $foundLines = ($tokens[$nextContent]['line'] - $tokens[$nextLineToken]['line']);
            }
        }

        if ($foundLines !== $this->spacing) {
            $error = 'Expected %s blank line';
            if ($this->spacing !== 1) {
                $error .= 's';
            }

            $error .= ' after function; %s found';
            $data   = array(
                       $this->spacing,
                       $foundLines,
                      );
            $phpcsFile->addError($error, $closer, 'After', $data);
        }

        /*
            Check the number of blank lines
            before the function.
        */

        $prevLineToken = null;
        for ($i = $stackPtr; $i > 0; $i--) {
            if (strpos($tokens[$i]['content'], $phpcsFile->eolChar) === false) {
                continue;
            } else {
                $prevLineToken = $i;
                break;
            }
        }

        if (is_null($prevLineToken) === true) {
            // Never found the previous line, which means
            // there are 0 blank lines before the function.
            $foundLines = 0;
        } else {
            $prevContent = $phpcsFile->findPrevious(array(T_WHITESPACE, T_DOC_COMMENT), $prevLineToken, null, true);

            // Before we throw an error, check that we are not throwing an error
            // for another function. We don't want to error for no blank lines after
            // the previous function and no blank lines before this one as well.
            $currentLine = $tokens[$stackPtr]['line'];
            $prevLine    = ($tokens[$prevContent]['line'] - 1);
            $i           = ($stackPtr - 1);
            $foundLines  = 0;
            while ($currentLine != $prevLine && $currentLine > 1 && $i > 0) {
                if (isset($tokens[$i]['scope_condition']) === true) {
                    $scopeCondition = $tokens[$i]['scope_condition'];
                    if ($tokens[$scopeCondition]['code'] === T_FUNCTION) {
                        // Found a previous function.
                        return;
                    }
                } else if ($tokens[$i]['code'] === T_FUNCTION) {
                    // Found another interface function.
                    return;
                }

                $currentLine = $tokens[$i]['line'];
                if ($currentLine === $prevLine) {
                    break;
                }

                if ($tokens[($i - 1)]['line'] < $currentLine && $tokens[($i + 1)]['line'] > $currentLine) {
                    // This token is on a line by itself. If it is whitespace, the line is empty.
                    if ($tokens[$i]['code'] === T_WHITESPACE) {
                        $foundLines++;
                    }
                }

                $i--;
            }//end while
        }//end if

        if ($foundLines !== $this->spacing) {
            $error = 'Expected %s blank line';
            if ($this->spacing !== 1) {
                $error .= 's';
            }

            $error .= ' before function; %s found';
            $data   = array(
                       $this->spacing,
                       $foundLines,
                      );
            $phpcsFile->addError($error, $stackPtr, 'Before', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Sniffs_Squiz_WhiteSpace_OperatorSpacingSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Sniffs_Squiz_WhiteSpace_OperatorSpacingSniff.
 *
 * Verifies that operators have valid spacing surrounding them.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_WhiteSpace_OperatorSpacingSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                  );


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        $comparison = PHP_CodeSniffer_Tokens::$comparisonTokens;
        $operators  = PHP_CodeSniffer_Tokens::$operators;
        $assignment = PHP_CodeSniffer_Tokens::$assignmentTokens;
        $inlineIf   = array(
                       T_INLINE_THEN,
                       T_INLINE_ELSE,
                      );

        return array_unique(
            array_merge($comparison, $operators, $assignment, $inlineIf)
        );

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The current file being checked.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Skip default values in function declarations.
        if ($tokens[$stackPtr]['code'] === T_EQUAL
            || $tokens[$stackPtr]['code'] === T_MINUS
        ) {
            if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) {
                $parenthesis = array_keys($tokens[$stackPtr]['nested_parenthesis']);
                $bracket     = array_pop($parenthesis);
                if (isset($tokens[$bracket]['parenthesis_owner']) === true) {
                    $function = $tokens[$bracket]['parenthesis_owner'];
                    if ($tokens[$function]['code'] === T_FUNCTION
                        || $tokens[$function]['code'] === T_CLOSURE
                    ) {
                        return;
                    }
                }
            }
        }

        if ($tokens[$stackPtr]['code'] === T_EQUAL) {
            // Skip for '=&' case.
            if (isset($tokens[($stackPtr + 1)]) === true
                && $tokens[($stackPtr + 1)]['code'] === T_BITWISE_AND
            ) {
                return;
            }
        }

        // Skip short ternary such as: $foo = $bar ?: true;
        if (($tokens[$stackPtr]['code'] == T_INLINE_THEN
            && $tokens[$stackPtr + 1]['code'] == T_INLINE_ELSE)
            || ($tokens[$stackPtr - 1]['code'] == T_INLINE_THEN
            && $tokens[$stackPtr]['code'] == T_INLINE_ELSE)
        ) {
                return;
        }

        if ($tokens[$stackPtr]['code'] === T_BITWISE_AND) {
            // If it's not a reference, then we expect one space either side of the
            // bitwise operator.
            if ($phpcsFile->isReference($stackPtr) === true) {
                return;
            }

            // Check there is one space before the & operator.
            if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE) {
                $error = 'Expected 1 space before "&" operator; 0 found';
                $phpcsFile->addError($error, $stackPtr, 'NoSpaceBeforeAmp');
            } else {
                if (strlen($tokens[($stackPtr - 1)]['content']) !== 1) {
                    $found = strlen($tokens[($stackPtr - 1)]['content']);
                    $error = 'Expected 1 space before "&" operator; %s found';
                    $data  = array($found);
                    $phpcsFile->addError($error, $stackPtr, 'SpacingBeforeAmp', $data);
                }
            }

            // Check there is one space after the & operator.
            if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) {
                $error = 'Expected 1 space after "&" operator; 0 found';
                $phpcsFile->addError($error, $stackPtr, 'NoSpaceAfterAmp');
            } else {
                if (strlen($tokens[($stackPtr + 1)]['content']) !== 1) {
                    $found = strlen($tokens[($stackPtr + 1)]['content']);
                    $error = 'Expected 1 space after "&" operator; %s found';
                    $data  = array($found);
                    $phpcsFile->addError($error, $stackPtr, 'SpacingAfterAmp', $data);
                }
            }

            return;
        }//end if

        if ($tokens[$stackPtr]['code'] === T_MINUS) {
            // Check minus spacing, but make sure we aren't just assigning
            // a minus value or returning one.
            $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
            if ($tokens[$prev]['code'] === T_RETURN) {
                // Just returning a negative value; eg. (return -1).
                return;
            }

            if (in_array($tokens[$prev]['code'], PHP_CodeSniffer_Tokens::$operators) === true) {
                // Just trying to operate on a negative value; eg. ($var * -1).
                return;
            }

            if (in_array($tokens[$prev]['code'], PHP_CodeSniffer_Tokens::$comparisonTokens) === true) {
                // Just trying to compare a negative value; eg. ($var === -1).
                return;
            }

            if (in_array($tokens[$prev]['code'], PHP_CodeSniffer_Tokens::$assignmentTokens) === true) {
                // Just trying to assign a negative value; eg. ($var = -1).
                return;
            }

            // A list of tokens that indicate that the token is not
            // part of an arithmetic operation.
            $invalidTokens = array(
                              T_COMMA,
                              T_OPEN_PARENTHESIS,
                              T_OPEN_SQUARE_BRACKET,
                              T_DOUBLE_ARROW,
                              T_COLON,
                              T_INLINE_THEN,
                              T_INLINE_ELSE,
                              T_CASE,
                             );

            if (in_array($tokens[$prev]['code'], $invalidTokens) === true) {
                // Just trying to use a negative value; eg. myFunction($var, -2).
                return;
            }
        }//end if

        $operator = $tokens[$stackPtr]['content'];

        if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE) {
            $error = "Expected 1 space before \"$operator\"; 0 found";
            $phpcsFile->addError($error, $stackPtr, 'NoSpaceBefore');
        } else if (strlen($tokens[($stackPtr - 1)]['content']) !== 1) {
            // Don't throw an error for assignments, because other standards allow
            // multiple spaces there to align multiple assignments.
            if (in_array($tokens[$stackPtr]['code'], PHP_CodeSniffer_Tokens::$assignmentTokens) === false) {
                $found = strlen($tokens[($stackPtr - 1)]['content']);
                $error = 'Expected 1 space before "%s"; %s found';
                $data  = array(
                          $operator,
                          $found,
                         );
                $phpcsFile->addError($error, $stackPtr, 'SpacingBefore', $data);
            }
        }

        if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) {
            $error = "Expected 1 space after \"$operator\"; 0 found";
            $phpcsFile->addError($error, $stackPtr, 'NoSpaceAfter');
        } else if (strlen($tokens[($stackPtr + 1)]['content']) !== 1) {
            $found = strlen($tokens[($stackPtr + 1)]['content']);
            $error = 'Expected 1 space after "%s"; %s found';
            $data  = array(
                      $operator,
                      $found,
                     );
            $phpcsFile->addError($error, $stackPtr, 'SpacingAfter', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_WhiteSpace_PropertyLabelSpacingSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_WhiteSpace_PropertyLabelSpacingSniff.
 *
 * Ensures that the colon in a property or label definition has a single
 * space after it and no space before it.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_WhiteSpace_PropertyLabelSpacingSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('JS');


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_PROPERTY,
                T_LABEL,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $colon = $phpcsFile->findNext(T_COLON, ($stackPtr + 1));

        if ($colon !== ($stackPtr + 1)) {
            $error = 'There must be no space before the colon in a property/label declaration';
            $phpcsFile->addError($error, $stackPtr, 'Before');
        }

        if ($tokens[($colon + 1)]['code'] !== T_WHITESPACE || $tokens[($colon + 1)]['content'] !== ' ') {
            $error = 'There must be a single space after the colon in a property/label declaration';
            $phpcsFile->addError($error, $stackPtr, 'After');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_WhiteSpace_FunctionOpeningBraceSpaceSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_WhiteSpace_FunctionOpeningBraceSpaceSniff.
 *
 * Checks that there is no empty line after the opening brace of a function.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_WhiteSpace_FunctionOpeningBraceSpaceSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                  );


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_FUNCTION);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if (isset($tokens[$stackPtr]['scope_opener']) === false) {
            // Probably an interface method.
            return;
        }

        $openBrace   = $tokens[$stackPtr]['scope_opener'];
        $nextContent = $phpcsFile->findNext(T_WHITESPACE, ($openBrace + 1), null, true);

        if ($nextContent === $tokens[$stackPtr]['scope_closer']) {
             // The next bit of content is the closing brace, so this
             // is an empty function and should have a blank line
             // between the opening and closing braces.
            return;
        }

        $braceLine = $tokens[$openBrace]['line'];
        $nextLine  = $tokens[$nextContent]['line'];

        $found = ($nextLine - $braceLine - 1);
        if ($found > 0) {
            $error = 'Expected 0 blank lines after opening function brace; %s found';
            $data  = array($found);
            $phpcsFile->addError($error, $openBrace, 'SpacingAfter', $data);
        }

        if ($phpcsFile->tokenizerType === 'JS') {
            // Do some additional checking before the function brace.
            $nestedFunction = ($phpcsFile->hasCondition($stackPtr, T_FUNCTION) === true || isset($tokens[$stackPtr]['nested_parenthesis']) === true);

            $functionLine   = $tokens[$tokens[$stackPtr]['parenthesis_closer']]['line'];
            $lineDifference = ($braceLine - $functionLine);

            if ($nestedFunction === true) {
                if ($lineDifference > 0) {
                    $error = 'Opening brace should be on the same line as the function keyword';
                    $phpcsFile->addError($error, $openBrace, 'SpacingAfterNested');
                }
            } else {
                if ($lineDifference === 0) {
                    $error = 'Opening brace should be on a new line';
                    $phpcsFile->addError($error, $openBrace, 'ContentBefore');
                    return;
                }

                if ($lineDifference > 1) {
                    $error = 'Opening brace should be on the line after the declaration; found %s blank line(s)';
                    $data  = array(($lineDifference - 1));
                    $phpcsFile->addError($error, $openBrace, 'SpacingBefore', $data);
                    return;
                }
            }//end if
        }//end if

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_CSS_ColourDefinitionSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_CSS_ColourDefinitionSniff.
 *
 * Ensure colours are defined in upper-case and use shortcuts where possible.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_CSS_ColourDefinitionSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('CSS');


    /**
     * Returns the token types that this sniff is interested in.
     *
     * @return array(int)
     */
    public function register()
    {
        return array(T_COLOUR);

    }//end register()


    /**
     * Processes the tokens that this sniff is interested in.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        the token was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();
        $colour = $tokens[$stackPtr]['content'];

        $expected = strtoupper($colour);
        if ($colour !== $expected) {
            $error = 'CSS colours must be defined in uppercase; expected %s but found %s';
            $data  = array(
                      $expected,
                      $colour,
                     );
            $phpcsFile->addError($error, $stackPtr, 'NotUpper', $data);
        }

        // Now check if shorthand can be used.
        if (strlen($colour) !== 7) {
            return;
        }

        if ($colour{1} === $colour{2} && $colour{3} === $colour{4} && $colour{5} === $colour{6}) {
            $expected = '#'.$colour{1}.$colour{3}.$colour{5};
            $error    = 'CSS colours must use shorthand if available; expected %s but found %s';
            $data     = array(
                         $expected,
                         $colour,
                        );
            $phpcsFile->addError($error, $stackPtr, 'Shorthand', $data);
        }

    }//end process()

}//end class
?>
<?php
/**
 * Squiz_Sniffs_CSS_ClassDefinitionOpeningBraceSpaceSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_CSS_ClassDefinitionOpeningBraceSpaceSniff.
 *
 * Ensure there is a single space before the opening brace in a class definition
 * and the content starts on the next line.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_CSS_ClassDefinitionOpeningBraceSpaceSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('CSS');


    /**
     * Returns the token types that this sniff is interested in.
     *
     * @return array(int)
     */
    public function register()
    {
        return array(T_OPEN_CURLY_BRACKET);

    }//end register()


    /**
     * Processes the tokens that this sniff is interested in.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        the token was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if ($tokens[($stackPtr - 1)]['code'] !== T_WHITESPACE) {
            $error = 'Expected 1 space before opening brace of class definition; 0 found';
            $phpcsFile->addError($error, $stackPtr, 'NoneBefore');
        } else {
            $content = $tokens[($stackPtr - 1)]['content'];
            if ($content !== ' ') {
                $length = strlen($content);
                if ($length === 1) {
                    $length = 'tab';
                }

                $error = 'Expected 1 space before opening brace of class definition; %s found';
                $data  = array($length);
                $phpcsFile->addError($error, $stackPtr, 'Before', $data);
            }
        }//end if

        $next = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr + 1), null, true);
        if ($next === false) {
            return;
        }

        // Check for nested class definitions.
        $nested = false;
        $found  = $phpcsFile->findNext(
            T_OPEN_CURLY_BRACKET,
            ($stackPtr + 1),
            $tokens[$stackPtr]['bracket_closer']
        );
        if ($found !== false) {
            $nested = true;
        }

        $foundLines = ($tokens[$next]['line'] - $tokens[$stackPtr]['line'] - 1);
        if ($nested === true) {
            if ($foundLines !== 1) {
                $error = 'Expected 1 blank line after opening brace of nesting class definition; %s found';
                $data  = array($foundLines);
                $phpcsFile->addError($error, $stackPtr, 'AfterNesting', $data);
            }
        } else {
            if ($foundLines !== 0) {
                $error = 'Expected 0 blank lines after opening brace of class definition; %s found';
                $data  = array($foundLines);
                $phpcsFile->addError($error, $stackPtr, 'After', $data);
            }
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_CSS_LowercaseStyleDefinitionSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_CSS_LowercaseStyleDefinitionSniff.
 *
 * Ensure that all style definitions are in lowercase.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_CSS_LowercaseStyleDefinitionSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('CSS');


    /**
     * Returns the token types that this sniff is interested in.
     *
     * @return array(int)
     */
    public function register()
    {
        return array(T_OPEN_CURLY_BRACKET);

    }//end register()


    /**
     * Processes the tokens that this sniff is interested in.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        the token was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens  = $phpcsFile->getTokens();
        $start   = ($stackPtr + 1);
        $end     = ($tokens[$stackPtr]['bracket_closer'] - 1);
        $inStyle = null;

        for ($i = $start; $i <= $end; $i++) {
            // Skip nested definitions as they are checked individually.
            if ($tokens[$i]['code'] === T_OPEN_CURLY_BRACKET) {
                $i = $tokens[$i]['bracket_closer'];
                continue;
            }

            if ($tokens[$i]['code'] === T_STYLE) {
                $inStyle = $tokens[$i]['content'];
            }

            if ($tokens[$i]['code'] === T_SEMICOLON) {
                $inStyle = null;
            }

            if ($inStyle === 'progid') {
                // Special case for IE filters.
                continue;
            }

            if ($tokens[$i]['code'] === T_STYLE
                || ($inStyle !== null
                && $tokens[$i]['code'] === T_STRING)
            ) {
                $expected = strtolower($tokens[$i]['content']);
                if ($expected !== $tokens[$i]['content']) {
                    $error = 'Style definitions must be lowercase; expected %s but found %s';
                    $data  = array(
                              $expected,
                              $tokens[$i]['content'],
                             );
                    $phpcsFile->addError($error, $i, 'FoundUpper', $data);
                }
            }
        }//end for

    }//end process()

}//end class
?>
<?php
/**
 * Squiz_Sniffs_CSS_IndentationSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_CSS_IndentationSniff.
 *
 * Ensures styles are indented 4 spaces.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_CSS_IndentationSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('CSS');

    /**
    * The number of spaces code should be indented.
    *
    * @var int
    */
    public $indent = 4;


    /**
     * Returns the token types that this sniff is interested in.
     *
     * @return array(int)
     */
    public function register()
    {
        return array(T_OPEN_TAG);

    }//end register()


    /**
     * Processes the tokens that this sniff is interested in.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        the token was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $numTokens    = (count($tokens) - 2);
        $indentLevel  = 0;
        $nestingLevel = 0;
        for ($i = 1; $i < $numTokens; $i++) {
            if ($tokens[$i]['code'] === T_COMMENT) {
                // Don't check the indent of comments.
                continue;
            }

            if ($tokens[$i]['code'] === T_OPEN_CURLY_BRACKET) {
                $indentLevel++;

                // Check for nested class definitions.
                $found  = $phpcsFile->findNext(
                    T_OPEN_CURLY_BRACKET,
                    ($i + 1),
                    $tokens[$i]['bracket_closer']
                );
                if ($found !== false) {
                    $nestingLevel = $indentLevel;
                }
            } else if ($tokens[($i + 1)]['code'] === T_CLOSE_CURLY_BRACKET) {
                $indentLevel--;
            }

            if ($tokens[$i]['column'] !== 1) {
                continue;
            }

            // We started a new line, so check indent.
            if ($tokens[$i]['code'] === T_WHITESPACE) {
                $content     = str_replace($phpcsFile->eolChar, '', $tokens[$i]['content']);
                $foundIndent = strlen($content);
            } else {
                $foundIndent = 0;
            }

            $expectedIndent = ($indentLevel * $this->indent);
            if ($expectedIndent > 0
                && strpos($tokens[$i]['content'], $phpcsFile->eolChar) !== false
            ) {
                if ($nestingLevel !== $indentLevel) {
                    $error = 'Blank lines are not allowed in class definitions';
                    $phpcsFile->addError($error, $i, 'BlankLine');
                }
            } else if ($foundIndent !== $expectedIndent) {
                $error = 'Line indented incorrectly; expected %s spaces, found %s';
                $data  = array(
                          $expectedIndent,
                          $foundIndent,
                         );
                $phpcsFile->addError($error, $i, 'Incorrect', $data);
            }
        }//end foreach
    }//end process()

}//end class
?>
<?php
/**
 * Squiz_Sniffs_CSS_ClassDefinitionNameSpacingSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_CSS_ClassDefinitionNameSpacingSniff.
 *
 * Ensure there are no blank lines between the names of classes/IDs.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_CSS_ClassDefinitionNameSpacingSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('CSS');


    /**
     * Returns the token types that this sniff is interested in.
     *
     * @return array(int)
     */
    public function register()
    {
        return array(T_OPEN_CURLY_BRACKET);

    }//end register()


    /**
     * Processes the tokens that this sniff is interested in.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        the token was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Do not check nested style definitions as, for example, in @media style rules.
        $nested = $phpcsFile->findNext(T_OPEN_CURLY_BRACKET, ($stackPtr + 1), $tokens[$stackPtr]['bracket_closer']);
        if ($nested !== false) {
            return;
        }

        // Find the first blank line before this opening brace, unless we get
        // to another style definition, comment or the start of the file.
        $endTokens = array(
                      T_OPEN_CURLY_BRACKET,
                      T_CLOSE_CURLY_BRACKET,
                      T_COMMENT,
                      T_DOC_COMMENT,
                      T_OPEN_TAG,
                     );

        $foundContent = false;
        $currentLine  = $tokens[$stackPtr]['line'];
        for ($i = ($stackPtr - 1); $i >= 0; $i--) {
            if (in_array($tokens[$i]['code'], $endTokens) === true) {
                break;
            }

            if ($tokens[$i]['line'] === $currentLine) {
                if ($tokens[$i]['code'] !== T_WHITESPACE) {
                    $foundContent = true;
                }

                continue;
            }

            // We changed lines.
            if ($foundContent === false) {
                // Before we throw an error, make sure we are not looking
                // at a gap before the style definition.
                $prev = $phpcsFile->findPrevious(T_WHITESPACE, $i, null, true);
                if ($prev !== false
                    && in_array($tokens[$prev]['code'], $endTokens) === false
                ) {
                    $error = 'Blank lines are not allowed between class names';
                    $phpcsFile->addError($error, ($i + 1), 'BlankLinesFound');
                }
                break;
            }

            $foundContent = false;
            $currentLine  = $tokens[$i]['line'];
        }//end for

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_CSS_SemicolonSpacingSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_CSS_SemicolonSpacingSniff.
 *
 * Ensure each style definition has a semi-colon and it is spaced correctly.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_CSS_SemicolonSpacingSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('CSS');


    /**
     * Returns the token types that this sniff is interested in.
     *
     * @return array(int)
     */
    public function register()
    {
        return array(T_STYLE);

    }//end register()


    /**
     * Processes the tokens that this sniff is interested in.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        the token was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $semicolon = $phpcsFile->findNext(T_SEMICOLON, ($stackPtr + 1));
        if ($semicolon === false || $tokens[$semicolon]['line'] !== $tokens[$stackPtr]['line']) {
            $error = 'Style definitions must end with a semicolon';
            $phpcsFile->addError($error, $stackPtr, 'NotAtEnd');
            return;
        }

        if ($tokens[($semicolon - 1)]['code'] === T_WHITESPACE) {
            $length  = strlen($tokens[($semicolon - 1)]['content']);
            $error = 'Expected 0 spaces before semicolon in style definition; %s found';
            $data  = array($length);
            $phpcsFile->addError($error, $stackPtr, 'SpaceFound', $data);
        }

    }//end process()

}//end class
?>
<?php
/**
 * Squiz_Sniffs_CSS_EmptyClassDefinitionSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_CSS_EmptyClassDefinitionSniff.
 *
 * Ensure that class definitions are not empty.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_CSS_EmptyClassDefinitionSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('CSS');


    /**
     * Returns the token types that this sniff is interested in.
     *
     * @return array(int)
     */
    public function register()
    {
        return array(T_OPEN_CURLY_BRACKET);

    }//end register()


    /**
     * Processes the tokens that this sniff is interested in.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        the token was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();
        $next   = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr + 1), null, true);

        if ($next === false || $tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET) {
            $error = 'Class definition is empty';
            $phpcsFile->addError($error, $stackPtr, 'Found');
        }

    }//end process()

}//end class
?>
<?php
/**
 * Squiz_Sniffs_CSS_ClassDefinitionClosingBraceSpaceSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_CSS_ClassDefinitionClosingBraceSpaceSniff.
 *
 * Ensure there is a single blank line after the closing brace of a class definition.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_CSS_ClassDefinitionClosingBraceSpaceSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('CSS');


    /**
     * Returns the token types that this sniff is interested in.
     *
     * @return array(int)
     */
    public function register()
    {
        return array(T_CLOSE_CURLY_BRACKET);

    }//end register()


    /**
     * Processes the tokens that this sniff is interested in.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        the token was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
        if ($next === false) {
            return;
        }

        if ($tokens[$next]['code'] !== T_CLOSE_TAG) {
            $found = (($tokens[$next]['line'] - $tokens[$stackPtr]['line']) - 1);
            if ($found !== 1) {
                $error = 'Expected one blank line after closing brace of class definition; %s found';
                $data  = array($found);
                $phpcsFile->addError($error, $stackPtr, 'SpacingAfterClose', $data);
            }
        }

        // Ignore nested style definitions from here on. The spacing before the closing brace
        // (a single blank line) will be enforced by the above check, which ensures there is a
        // blank line after the last nested class.
        $found = $phpcsFile->findPrevious(
            T_CLOSE_CURLY_BRACKET,
            ($stackPtr - 1),
            $tokens[$stackPtr]['bracket_opener']
        );
        if ($found !== false) {
            return;
        }

        $prev = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr - 1), null, true);
        if ($prev !== false && $tokens[$prev]['line'] !== ($tokens[$stackPtr]['line'] - 1)) {
            $num   = ($tokens[$stackPtr]['line'] - $tokens[$prev]['line'] - 1);
            $error = 'Expected 0 blank lines before closing brace of class definition; %s found';
            $data  = array($num);
            $phpcsFile->addError($error, $stackPtr, 'SpacingBeforeClose', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_CSS_DuplicateClassDefinitionSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_CSS_DuplicateClassDefinitionSniff.
 *
 * Check for duplicate class definitions that can be merged into one.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_CSS_DuplicateClassDefinitionSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('CSS');


    /**
     * Returns the token types that this sniff is interested in.
     *
     * @return array(int)
     */
    public function register()
    {
        return array(T_OPEN_TAG);

    }//end register()


    /**
     * Processes the tokens that this sniff is interested in.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        the token was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Find the content of each class definition name.
        $classNames = array();
        $next = $phpcsFile->findNext(T_OPEN_CURLY_BRACKET, ($stackPtr + 1));
        if ($next === false) {
            // No class definitions in the file.
            return;
        }

        $find = array(
                 T_CLOSE_CURLY_BRACKET,
                 T_COMMENT,
                 T_OPEN_TAG,
                );

        while ($next !== false) {
            $prev = $phpcsFile->findPrevious($find, ($next - 1));

            // Create a sorted name for the class so we can compare classes
            // even when the individual names are all over the place.
            $name = '';
            for ($i = ($prev + 1); $i < $next; $i++) {
                $name .= $tokens[$i]['content'];
            }

            $name = trim($name);
            $name = str_replace("\n", ' ', $name);
            $name = preg_replace('|[\s]+|', ' ', $name);
            $name = str_replace(', ', ',', $name);

            $names = explode(',', $name);
            sort($names);
            $name = implode(',', $names);

            if (isset($classNames[$name]) === true) {
                $first = $classNames[$name];
                $error = 'Duplicate class definition found; first defined on line %s';
                $data  = array($tokens[$first]['line']);
                $phpcsFile->addError($error, $next, 'Found', $data);
            } else {
                $classNames[$name] = $next;
            }

            $next = $phpcsFile->findNext(T_OPEN_CURLY_BRACKET, ($next + 1));
        }//end while

    }//end process()


}//end class
?>
<?php
/**
 * Squiz_Sniffs_CSS_MissingColonSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_CSS_MissingColonSniff.
 *
 * Ensure that all style definitions have a colon.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_CSS_MissingColonSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('CSS');


    /**
     * Returns the token types that this sniff is interested in.
     *
     * @return array(int)
     */
    public function register()
    {
        return array(T_OPEN_CURLY_BRACKET);

    }//end register()


    /**
     * Processes the tokens that this sniff is interested in.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        the token was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens   = $phpcsFile->getTokens();
        $lastLine = $tokens[$stackPtr]['line'];
        $end      = $tokens[$stackPtr]['bracket_closer'];
        $endLine  = $tokens[$end]['line'];

        // Do not check nested style definitions as, for example, in @media style rules.
        $nested = $phpcsFile->findNext(T_OPEN_CURLY_BRACKET, ($stackPtr + 1), $end);
        if ($nested !== false) {
            return;
        }

        $foundColon  = false;
        $foundString = false;
        for ($i = ($stackPtr + 1); $i <= $end; $i++) {
            if ($tokens[$i]['line'] !== $lastLine) {
                // We changed lines.
                if ($foundColon === false && $foundString !== false) {
                    // We didn't find a colon on the previous line.
                    $error = 'No style definition found on line; check for missing colon';
                    $phpcsFile->addError($error, $foundString, 'Found');
                }

                $foundColon  = false;
                $foundString = false;
                $lastLine    = $tokens[$i]['line'];
            }

            if ($tokens[$i]['code'] === T_STRING) {
                $foundString = $i;
            } else if ($tokens[$i]['code'] === T_COLON) {
                $foundColon = $i;
            }
        }//end for

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_CSS_ColonSpacingSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_CSS_ColonSpacingSniff.
 *
 * Ensure there is no space before a colon and one space after it.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_CSS_ColonSpacingSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('CSS');


    /**
     * Returns the token types that this sniff is interested in.
     *
     * @return array(int)
     */
    public function register()
    {
        return array(T_COLON);

    }//end register()


    /**
     * Processes the tokens that this sniff is interested in.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        the token was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $prev = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr - 1), null, true);
        if ($tokens[$prev]['code'] !== T_STYLE) {
            // The colon is not part of a style definition.
            return;
        }

        if ($tokens[$prev]['content'] === 'progid') {
            // Special case for IE filters.
            return;
        }

        if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) {
            $error = 'There must be no space before a colon in a style definition';
            $phpcsFile->addError($error, $stackPtr, 'Before');
        }

        if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) {
            $error = 'Expected 1 space after colon in style definition; 0 found';
            $phpcsFile->addError($error, $stackPtr, 'NoneAfter');
        } else {
            $content = $tokens[($stackPtr + 1)]['content'];
            if (strpos($content, $phpcsFile->eolChar) === false) {
                $length  = strlen($content);
                if ($length !== 1) {
                    $error = 'Expected 1 space after colon in style definition; %s found';
                    $data  = array($length);
                    $phpcsFile->addError($error, $stackPtr, 'After', $data);
                }
            } else {
                $error = 'Expected 1 space after colon in style definition; newline found';
                $phpcsFile->addError($error, $stackPtr, 'AfterNewline');
            }
        }//end if

    }//end process()

}//end class
?>
<?php
/**
 * Squiz_Sniffs_CSS_NamedColoursSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_CSS_NamedColoursSniff.
 *
 * Ensure colour names are not used.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_CSS_NamedColoursSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('CSS');


    /**
     * A list of named colours.
     *
     * This is the list of standard colours defined in the CSS spec.
     *
     * @var array
     */
    public $colourNames = array(
                           'aqua',
                           'black',
                           'blue',
                           'fuchsia',
                           'gray',
                           'green',
                           'lime',
                           'maroon',
                           'navy',
                           'olive',
                           'orange',
                           'purple',
                           'red',
                           'silver',
                           'teal',
                           'white',
                           'yellow',
                           );


    /**
     * Returns the token types that this sniff is interested in.
     *
     * @return array(int)
     */
    public function register()
    {
        return array(T_STRING);

    }//end register()


    /**
     * Processes the tokens that this sniff is interested in.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        the token was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if ($tokens[($stackPtr - 1)]['code'] === T_HASH
            || $tokens[($stackPtr - 1)]['code'] === T_STRING_CONCAT
        ) {
            // Class name.
            return;
        }

        if (in_array(strtolower($tokens[$stackPtr]['content']), $this->colourNames) === true) {
            $error = 'Named colours are forbidden; use hex, rgb, or rgba values instead';
            $phpcsFile->addError($error, $stackPtr, 'Forbidden');
        }

    }//end process()

}//end class
?>
<?php
/**
 * Squiz_Sniffs_CSS_ShorthandSizeSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_CSS_ShorthandSizeSniff.
 *
 * Ensure sizes are defined using shorthand notation where possible, except in the
 * case where shorthand becomes 3 values.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_CSS_ShorthandSizeSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('CSS');

    /**
     * A list of styles that we shouldn't check.
     *
     * These have values that looks like sizes, but are not.
     *
     * @var array
     */
    public $excludeStyles = array(
                             'background-position',
                             'box-shadow',
                             'transform-origin',
                             '-webkit-transform-origin',
                             '-ms-transform-origin',
                            );


    /**
     * Returns the token types that this sniff is interested in.
     *
     * @return array(int)
     */
    public function register()
    {
        return array(T_STYLE);

    }//end register()


    /**
     * Processes the tokens that this sniff is interested in.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        the token was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Some styles look like shorthand but are not actually a set of 4 sizes.
        $style = strtolower($tokens[$stackPtr]['content']);
        if (in_array($style, $this->excludeStyles) === true) {
            return;
        }

        // Get the whole style content.
        $end     = $phpcsFile->findNext(T_SEMICOLON, ($stackPtr + 1));
        $content = $phpcsFile->getTokensAsString(($stackPtr + 1), ($end - $stackPtr - 1));
        $content = trim($content, ': ');

        // Account for a !important annotation.
        if (substr($content, -10) === '!important') {
            $content = substr($content, 0, -10);
            $content = trim($content);
        }

        // Check if this style value is a set of numbers with optional prefixes.
        $content = preg_replace('/\s+/', ' ', $content);
        $values  = array();
        $num     = preg_match_all(
            '/([0-9]+)([a-zA-Z]{2}\s+|%\s+|\s+)/',
            $content.' ',
            $values,
            PREG_SET_ORDER
        );

        // Only interested in styles that have multiple sizes defined.
        if ($num < 2) {
            return;
        }

        // Rebuild the content we matched to ensure we got everything.
        $matched = '';
        foreach ($values as $value) {
            $matched .= $value[0];
        }

        if ($content !== trim($matched)) {
            return;
        }

        if ($num === 3) {
            $expected = trim($content.' '.$values[1][1].$values[1][2]);
            $error = 'Shorthand syntax not allowed here; use %s instead';
            $data  = array($expected);
            $phpcsFile->addError($error, $stackPtr, 'NotAllowed', $data);
            return;
        }

        if ($num === 2) {
            if ($values[0][0] !== $values[1][0]) {
                // Both values are different, so it is already shorthand.
                return;
            }
        } else if ($values[0][0] !== $values[2][0] || $values[1][0] !== $values[3][0]) {
            // Can't shorthand this.
            return;
        }

        if ($values[0][0] === $values[1][0]) {
            // All values are the same.
            $expected = $values[0][0];
        } else {
            $expected = $values[0][0].' '.$values[1][0];
        }

        $expected = preg_replace('/\s+/', ' ', trim($expected));

        $error = 'Size definitions must use shorthand if available; expected "%s" but found "%s"';
        $data  = array(
                  $expected,
                  $content,
                 );

        $phpcsFile->addError($error, $stackPtr, 'NotUsed', $data);

    }//end process()


}//end class
?>
<?php
/**
 * Squiz_Sniffs_CSS_DisallowMultipleStyleDefinitionsSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_CSS_DisallowMultipleStyleDefinitionsSniff.
 *
 * Ensure that each style definition is on a line by itself.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_CSS_DisallowMultipleStyleDefinitionsSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('CSS');


    /**
     * Returns the token types that this sniff is interested in.
     *
     * @return array(int)
     */
    public function register()
    {
        return array(T_STYLE);

    }//end register()


    /**
     * Processes the tokens that this sniff is interested in.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        the token was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();
        $next   = $phpcsFile->findNext(T_STYLE, ($stackPtr + 1));
        if ($next === false) {
            return;
        }

        if ($tokens[$next]['content'] === 'progid') {
            // Special case for IE filters.
            return;
        }

        if ($tokens[$next]['line'] === $tokens[$stackPtr]['line']) {
            $error = 'Each style definition must be on a line by itself';
            $phpcsFile->addError($error, $next, 'Found');
        }

    }//end process()

}//end class
?>
<?php
/**
 * Squiz_Sniffs_CSS_DuplicateStyleDefinitionSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_CSS_DuplicateStyleDefinitionSniff.
 *
 * Check for duplicate style definitions in the same class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_CSS_DuplicateStyleDefinitionSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('CSS');


    /**
     * Returns the token types that this sniff is interested in.
     *
     * @return array(int)
     */
    public function register()
    {
        return array(T_OPEN_CURLY_BRACKET);

    }//end register()


    /**
     * Processes the tokens that this sniff is interested in.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        the token was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Find the content of each style definition name.
        $end  = $tokens[$stackPtr]['bracket_closer'];
        $next = $phpcsFile->findNext(T_STYLE, ($stackPtr + 1), $end);
        if ($next === false) {
            // Class definition is empty.
            return;
        }

        $styleNames = array();

        while ($next !== false) {
            $name = $tokens[$next]['content'];
            if (isset($styleNames[$name]) === true) {
                $first = $styleNames[$name];
                $error = 'Duplicate style definition found; first defined on line %s';
                $data  = array($tokens[$first]['line']);
                $phpcsFile->addError($error, $next, 'Found', $data);
            } else {
                $styleNames[$name] = $next;
            }

            $next = $phpcsFile->findNext(T_STYLE, ($next + 1), $end);
        }//end while

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_CSS_EmptyStyleDefinitionSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_CSS_EmptyStyleDefinitionSniff.
 *
 * Ensure that style definitions are not empty.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_CSS_EmptyStyleDefinitionSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('CSS');


    /**
     * Returns the token types that this sniff is interested in.
     *
     * @return array(int)
     */
    public function register()
    {
        return array(T_STYLE);

    }//end register()


    /**
     * Processes the tokens that this sniff is interested in.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        the token was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();
        $next   = $phpcsFile->findNext(array(T_WHITESPACE, T_COLON), ($stackPtr + 1), null, true);

        if ($next === false || $tokens[$next]['code'] === T_SEMICOLON || $tokens[$next]['line'] !== $tokens[$stackPtr]['line']) {
            $error = 'Style definition is empty';
            $phpcsFile->addError($error, $stackPtr, 'Found');
        }

    }//end process()

}//end class
?>
<?php
/**
 * Squiz_Sniffs_CSS_ForbiddenStylesSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_CSS_ForbiddenStylesSniff.
 *
 * Bans the use of some styles, such as deprecated or browser-specific styles.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_CSS_ForbiddenStylesSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('CSS');

    /**
     * A list of forbidden styles with their alternatives.
     *
     * The value is NULL if no alternative exists. i.e., the
     * function should just not be used.
     *
     * @var array(string => string|null)
     */
    protected $forbiddenStyles = array(
                                     '-moz-border-radius'             => 'border-radius',
                                     '-webkit-border-radius'          => 'border-radius',
                                     '-moz-border-radius-topleft'     => 'border-top-left-radius',
                                     '-moz-border-radius-topright'    => 'border-top-right-radius',
                                     '-moz-border-radius-bottomright' => 'border-bottom-right-radius',
                                     '-moz-border-radius-bottomleft'  => 'border-bottom-left-radius',
                                     '-moz-box-shadow'                => 'box-shadow',
                                     '-webkit-box-shadow'             => 'box-shadow',
                                    );

    /**
     * A cache of forbidden style names, for faster lookups.
     *
     * @var array(string)
     */
    protected $forbiddenStyleNames = array();

    /**
     * If true, forbidden styles will be considered regular expressions.
     *
     * @var bool
     */
    protected $patternMatch = false;

    /**
     * If true, an error will be thrown; otherwise a warning.
     *
     * @var bool
     */
    public $error = true;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        $this->forbiddenStyleNames = array_keys($this->forbiddenStyles);

        if ($this->patternMatch === true) {
            foreach ($this->forbiddenStyleNames as $i => $name) {
                $this->forbiddenStyleNames[$i] = '/'.$name.'/i';
            }
        }

        return array(T_STYLE);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens  = $phpcsFile->getTokens();
        $style   = strtolower($tokens[$stackPtr]['content']);
        $pattern = null;

        if ($this->patternMatch === true) {
            $count   = 0;
            $pattern = preg_replace(
                $this->forbiddenStyleNames,
                $this->forbiddenStyleNames,
                $style,
                1,
                $count
            );

            if ($count === 0) {
                return;
            }

            // Remove the pattern delimiters and modifier.
            $pattern = substr($pattern, 1, -2);
        } else {
            if (in_array($style, $this->forbiddenStyleNames) === false) {
                return;
            }
        }

        $this->addError($phpcsFile, $stackPtr, $style, $pattern);

    }//end process()


    /**
     * Generates the error or warning for this sniff.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the forbidden style
     *                                        in the token array.
     * @param string               $style     The name of the forbidden style.
     * @param string               $pattern   The pattern used for the match.
     *
     * @return void
     */
    protected function addError($phpcsFile, $stackPtr, $style, $pattern=null)
    {
        $data  = array($style);
        $error = 'The use of style %s is ';
        if ($this->error === true) {
            $type   = 'Found';
            $error .= 'forbidden';
        } else {
            $type   = 'Discouraged';
            $error .= 'discouraged';
        }

        if ($pattern === null) {
            $pattern = $style;
        }

        if ($this->forbiddenStyles[$pattern] !== null) {
            $type  .= 'WithAlternative';
            $data[] = $this->forbiddenStyles[$pattern];
            $error .= '; use %s instead';
        }

        if ($this->error === true) {
            $phpcsFile->addError($error, $stackPtr, $type, $data);
        } else {
            $phpcsFile->addWarning($error, $stackPtr, $type, $data);
        }

    }//end addError()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_CSS_OpacitySniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_CSS_OpacitySniff.
 *
 * Ensure that opacity values start with a 0 if it is not a whole number.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_CSS_OpacitySniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('CSS');


    /**
     * Returns the token types that this sniff is interested in.
     *
     * @return array(int)
     */
    public function register()
    {
        return array(T_STYLE);

    }//end register()


    /**
     * Processes the tokens that this sniff is interested in.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        the token was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if ($tokens[$stackPtr]['content'] !== 'opacity') {
            return;
        }

        $next    = $phpcsFile->findNext(array(T_COLON, T_WHITESPACE), ($stackPtr + 1), null, true);
        $numbers = array(
                    T_DNUMBER,
                    T_LNUMBER,
                   );

        if ($next === false || in_array($tokens[$next]['code'], $numbers) === false) {
            return;
        }

        $value = $tokens[$next]['content'];
        if ($tokens[$next]['code'] === T_LNUMBER) {
            if ($value !== '0' && $value !== '1') {
                $error = 'Opacity values must be between 0 and 1';
                $phpcsFile->addError($error, $next, 'Invalid');
            }
        } else {
            if (strlen($value) > 3) {
                $error = 'Opacity values must have a single value after the decimal point';
                $phpcsFile->addError($error, $next, 'SpacingAfterPoint');
            } else if ($value === '0.0' || $value === '1.0') {
                $error = 'Opacity value does not require decimal point; use %s instead';
                $data  = array($value{0});
                $phpcsFile->addError($error, $next, 'PointNotRequired', $data);
            } else if ($value{0} === '.') {
                $error = 'Opacity values must not start with a decimal point; use 0%s instead';
                $data  = array($value);
                $phpcsFile->addError($error, $next, 'StartWithPoint', $data);
            } else if ($value{0} !== '0') {
                $error = 'Opacity values must be between 0 and 1';
                $phpcsFile->addError($error, $next, 'Invalid');
            }
        }//end if

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_Functions_MultiLineFunctionDeclarationSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PEAR_Sniffs_Functions_FunctionDeclarationSniff', true) === false) {
    $error = 'Class PEAR_Sniffs_Functions_FunctionDeclarationSniff not found';
    throw new PHP_CodeSniffer_Exception($error);
}

/**
 * Squiz_Sniffs_Functions_MultiLineFunctionDeclarationSniff.
 *
 * Ensure single and multi-line function declarations are defined correctly.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Functions_MultiLineFunctionDeclarationSniff extends PEAR_Sniffs_Functions_FunctionDeclarationSniff
{


    /**
     * Processes multi-line declarations.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     * @param array                $tokens    The stack of tokens that make up
     *                                        the file.
     *
     * @return void
     */
    public function processMultiLineDeclaration(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $tokens)
    {
        // We do everything the parent sniff does, and a bit more.
        parent::processMultiLineDeclaration($phpcsFile, $stackPtr, $tokens);

        $openBracket = $tokens[$stackPtr]['parenthesis_opener'];
        $this->processBracket($phpcsFile, $openBracket, $tokens, 'function');

        if ($tokens[$stackPtr]['code'] !== T_CLOSURE) {
            return;
        }

        $use = $phpcsFile->findNext(T_USE, ($tokens[$stackPtr]['parenthesis_closer'] + 1), $tokens[$stackPtr]['scope_opener']);
        if ($use === false) {
            return;
        }

        $openBracket = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1), null);
        $this->processBracket($phpcsFile, $openBracket, $tokens, 'use');

        // Also check spacing.
        if ($tokens[($use - 1)]['code'] === T_WHITESPACE) {
            $gap = strlen($tokens[($use - 1)]['content']);
        } else {
            $gap = 0;
        }

    }//end processMultiLineDeclaration()


    /**
     * Processes the contents of a single set of brackets.
     *
     * @param PHP_CodeSniffer_File $phpcsFile   The file being scanned.
     * @param int                  $openBracket The position of the open bracket
     *                                          in the stack passed in $tokens.
     * @param array                $tokens      The stack of tokens that make up
     *                                          the file.
     * @param string               $type        The type of the token the brackets
     *                                          belong to (function or use).
     *
     * @return void
     */
    public function processBracket(PHP_CodeSniffer_File $phpcsFile, $openBracket, $tokens, $type='function')
    {
        $errorPrefix = '';
        if ($type === 'use') {
            $errorPrefix = 'Use';
        }

        $closeBracket = $tokens[$openBracket]['parenthesis_closer'];

        // The open bracket should be the last thing on the line.
        if ($tokens[$openBracket]['line'] !== $tokens[$closeBracket]['line']) {
            $next = $phpcsFile->findNext(T_WHITESPACE, ($openBracket + 1), null, true);
            if ($tokens[$next]['line'] !== ($tokens[$openBracket]['line'] + 1)) {
                $error = 'The first parameter of a multi-line '.$type.' declaration must be on the line after the opening bracket';
                $phpcsFile->addError($error, $next, $errorPrefix.'FirstParamSpacing');
            }
        }

        // Each line between the brackets should contain a single parameter.
        $lastCommaLine = null;
        for ($i = ($openBracket + 1); $i < $closeBracket; $i++) {
            // Skip brackets, like arrays, as they can contain commas.
            if (isset($tokens[$i]['parenthesis_opener']) === true) {
                $i = $tokens[$i]['parenthesis_closer'];
                continue;
            }

            if ($tokens[$i]['code'] === T_COMMA) {
                if ($lastCommaLine !== null && $lastCommaLine === $tokens[$i]['line']) {
                    $error = 'Multi-line '.$type.' declarations must define one parameter per line';
                    $phpcsFile->addError($error, $i, $errorPrefix.'OneParamPerLine');
                } else {
                    // Comma must be the last thing on the line.
                    $next = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), null, true);
                    if ($tokens[$next]['line'] !== ($tokens[$i]['line'] + 1)) {
                        $error = 'Commas in multi-line '.$type.' declarations must be the last content on a line';
                        $phpcsFile->addError($error, $next, $errorPrefix.'ContentAfterComma');
                    }
                }

                $lastCommaLine = $tokens[$i]['line'];
            }
        }

    }//end processBracket()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_Functions_FunctionDuplicateArgumentSpacingSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Functions_FunctionDuplicateArgumentSpacingSniff.
 *
 * Checks that duplicate arguments are not used in function declarations.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Functions_FunctionDuplicateArgumentSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_FUNCTION);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $openBracket  = $tokens[$stackPtr]['parenthesis_opener'];
        $closeBracket = $tokens[$stackPtr]['parenthesis_closer'];

        $foundVariables = array();
        for ($i = ($openBracket + 1); $i < $closeBracket; $i++) {
            if ($tokens[$i]['code'] === T_VARIABLE) {
                $variable = $tokens[$i]['content'];
                if (in_array($variable, $foundVariables) === true) {
                    $error = 'Variable "%s" appears more than once in function declaration';
                    $data  = array($variable);
                    $phpcsFile->addError($error, $i, 'Found', $data);
                } else {
                    $foundVariables[] = $variable;
                }
            }
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_Functions_FunctionDeclarationSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_Standards_AbstractPatternSniff', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_Standards_AbstractPatternSniff not found');
}

/**
 * Squiz_Sniffs_Functions_FunctionDeclarationSniff.
 *
 * Checks the function declaration is correct.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Functions_FunctionDeclarationSniff extends PHP_CodeSniffer_Standards_AbstractPatternSniff
{


    /**
     * Returns an array of patterns to check are correct.
     *
     * @return array
     */
    protected function getPatterns()
    {
        return array(
                'function abc(...);',
                'abstract function abc(...);',
               );

    }//end getPatterns()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_Functions_FunctionDeclarationArgumentSpacingSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Functions_FunctionDeclarationArgumentSpacingSniff.
 *
 * Checks that arguments in function declarations are spaced correctly.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Functions_FunctionDeclarationArgumentSpacingSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * How many spaces should surround the equals signs.
     *
     * @var int
     */
    public $equalsSpacing = 0;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_FUNCTION,
                T_CLOSURE,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $this->equalsSpacing = (int) $this->equalsSpacing;

        $tokens       = $phpcsFile->getTokens();
        $openBracket  = $tokens[$stackPtr]['parenthesis_opener'];
        $this->processBracket($phpcsFile, $openBracket);

        if ($tokens[$stackPtr]['code'] === T_CLOSURE) {
            $use = $phpcsFile->findNext(T_USE, ($tokens[$openBracket]['parenthesis_closer'] + 1), $tokens[$stackPtr]['scope_opener']);
            if ($use !== false) {
                $openBracket  = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1), null);
                $this->processBracket($phpcsFile, $openBracket);
            }
        }

    }//end process()


    /**
     * Processes the contents of a single set of brackets.
     *
     * @param PHP_CodeSniffer_File $phpcsFile   The file being scanned.
     * @param int                  $openBracket The position of the open bracket
     *                                          in the stack passed in $tokens.
     *
     * @return void
     */
    public function processBracket(PHP_CodeSniffer_File $phpcsFile, $openBracket)
    {
        $tokens       = $phpcsFile->getTokens();
        $closeBracket = $tokens[$openBracket]['parenthesis_closer'];
        $multiLine    = ($tokens[$openBracket]['line'] !== $tokens[$closeBracket]['line']);

        $nextParam = $openBracket;
        $params    = array();
        while (($nextParam = $phpcsFile->findNext(T_VARIABLE, ($nextParam + 1), $closeBracket)) !== false) {

            $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($nextParam + 1), ($closeBracket + 1), true);
            if ($nextToken === false) {
                break;
            }

            $nextCode = $tokens[$nextToken]['code'];

            if ($nextCode === T_EQUAL) {
                // Check parameter default spacing.
                $spacesBefore = 0;
                if (($nextToken - $nextParam) > 1) {
                    $spacesBefore = strlen($tokens[($nextParam + 1)]['content']);
                }

                if ($spacesBefore !== $this->equalsSpacing) {
                    $error = 'Incorrect spacing between argument "%s" and equals sign; expected '.$this->equalsSpacing.' but found %s';
                    $data  = array(
                              $tokens[$nextParam]['content'],
                              $spacesBefore,
                             );
                    $phpcsFile->addError($error, $nextToken, 'SpaceBeforeEquals', $data);
                }

                $spacesAfter = 0;
                if ($tokens[($nextToken + 1)]['code'] === T_WHITESPACE) {
                    $spacesAfter = strlen($tokens[($nextToken + 1)]['content']);
                }

                if ($spacesAfter !== $this->equalsSpacing) {
                    $error = 'Incorrect spacing between default value and equals sign for argument "%s"; expected '.$this->equalsSpacing.' but found %s';
                    $data  = array(
                              $tokens[$nextParam]['content'],
                              $spacesAfter,
                             );
                    $phpcsFile->addError($error, $nextToken, 'SpaceAfterDefault', $data);
                }
            }//end if

            // Find and check the comma (if there is one).
            $nextComma = $phpcsFile->findNext(T_COMMA, ($nextParam + 1), $closeBracket);
            if ($nextComma !== false) {
                // Comma found.
                if ($tokens[($nextComma - 1)]['code'] === T_WHITESPACE) {
                    $error = 'Expected 0 spaces between argument "%s" and comma; %s found';
                    $data  = array(
                              $tokens[$nextParam]['content'],
                              strlen($tokens[($nextComma - 1)]['content']),
                             );
                    $phpcsFile->addError($error, $nextToken, 'SpaceBeforeComma', $data);
                }
            }

            // Take references into account when expecting the
            // location of whitespace.
            if ($phpcsFile->isReference(($nextParam - 1)) === true) {
                $whitespace = ($nextParam - 2);
            } else {
                $whitespace = ($nextParam - 1);
            }

            if (empty($params) === false) {
                // This is not the first argument in the function declaration.
                $arg = $tokens[$nextParam]['content'];

                if ($tokens[$whitespace]['code'] === T_WHITESPACE) {
                    $gap = strlen($tokens[$whitespace]['content']);

                    // Before we throw an error, make sure there is no type hint.
                    $comma     = $phpcsFile->findPrevious(T_COMMA, ($nextParam - 1));
                    $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($comma + 1), null, true);
                    if ($phpcsFile->isReference($nextToken) === true) {
                        $nextToken++;
                    }

                    if ($nextToken !== $nextParam) {
                        // There was a type hint, so check the spacing between
                        // the hint and the variable as well.
                        $hint = $tokens[$nextToken]['content'];

                        if ($gap !== 1) {
                            $error = 'Expected 1 space between type hint and argument "%s"; %s found';
                            $data  = array(
                                      $arg,
                                      $gap,
                                     );
                            $phpcsFile->addError($error, $nextToken, 'SpacingAfterHint', $data);
                        }

                        if ($multiLine === false) {
                            if ($tokens[($comma + 1)]['code'] !== T_WHITESPACE) {
                                $error = 'Expected 1 space between comma and type hint "%s"; 0 found';
                                $data  = array($hint);
                                $phpcsFile->addError($error, $nextToken, 'NoSpaceBeforeHint', $data);
                            } else {
                                $gap = strlen($tokens[($comma + 1)]['content']);
                                if ($gap !== 1) {
                                    $error = 'Expected 1 space between comma and type hint "%s"; %s found';
                                    $data  = array(
                                              $hint,
                                              $gap,
                                             );
                                    $phpcsFile->addError($error, $nextToken, 'SpacingBeforeHint', $data);
                                }
                            }
                        }
                    } else if ($gap !== 1) {
                        // Just make sure this is not actually an indent.
                        if ($tokens[$whitespace]['line'] === $tokens[($whitespace - 1)]['line']) {
                            $error = 'Expected 1 space between comma and argument "%s"; %s found';
                            $data  = array(
                                      $arg,
                                      $gap,
                                     );
                            $phpcsFile->addError($error, $nextToken, 'SpacingBeforeArg', $data);
                        }
                    }//end if
                } else {
                    $error = 'Expected 1 space between comma and argument "%s"; 0 found';
                    $data  = array($arg);
                    $phpcsFile->addError($error, $nextToken, 'NoSpaceBeforeArg', $data);
                }//end if
            } else {
                // First argument in function declaration.
                if ($tokens[$whitespace]['code'] === T_WHITESPACE) {
                    $gap = strlen($tokens[$whitespace]['content']);
                    $arg = $tokens[$nextParam]['content'];

                    // Before we throw an error, make sure there is no type hint.
                    $bracket   = $phpcsFile->findPrevious(T_OPEN_PARENTHESIS, ($nextParam - 1));
                    $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($bracket + 1), null, true);
                    if ($phpcsFile->isReference($nextToken) === true) {
                        $nextToken++;
                    }

                    if ($nextToken !== $nextParam) {
                        // There was a type hint, so check the spacing between
                        // the hint and the variable as well.
                        $hint = $tokens[$nextToken]['content'];

                        if ($gap !== 1) {
                            $error = 'Expected 1 space between type hint and argument "%s"; %s found';
                            $data  = array(
                                      $arg,
                                      $gap,
                                     );
                            $phpcsFile->addError($error, $nextToken, 'SpacingAfterHint', $data);
                        }

                        if ($multiLine === false
                            && $tokens[($bracket + 1)]['code'] === T_WHITESPACE
                        ) {
                            $error = 'Expected 0 spaces between opening bracket and type hint "%s"; %s found';
                            $data  = array(
                                      $hint,
                                      strlen($tokens[($bracket + 1)]['content']),
                                     );
                            $phpcsFile->addError($error, $nextToken, 'SpacingAfterOpenHint', $data);
                        }
                    } else if ($multiLine === false) {
                        $error = 'Expected 0 spaces between opening bracket and argument "%s"; %s found';
                        $data  = array(
                                  $arg,
                                  $gap,
                                 );
                        $phpcsFile->addError($error, $nextToken, 'SpacingAfterOpen', $data);
                    }
                }//end if
            }//end if

            $params[] = $nextParam;

        }//end while

        if (empty($params) === true) {
            // There are no parameters for this function.
            if (($closeBracket - $openBracket) !== 1) {
                $error = 'Expected 0 spaces between brackets of function declaration; %s found';
                $data  = array(strlen($tokens[($closeBracket - 1)]['content']));
                $phpcsFile->addError($error, $openBracket, 'SpacingBetween', $data);
            }
        } else if ($multiLine === false
            && $tokens[($closeBracket - 1)]['code'] === T_WHITESPACE
        ) {
            $lastParam = array_pop($params);
            $error     = 'Expected 0 spaces between argument "%s" and closing bracket; %s found';
            $data      = array(
                          $tokens[$lastParam]['content'],
                          strlen($tokens[($closeBracket - 1)]['content']),
                         );
            $phpcsFile->addError($error, $closeBracket, 'SpacingBeforeClose', $data);
        }

    }//end processBracket()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_Functions_LowercaseFunctionKeywordsSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Functions_LowercaseFunctionKeywordsSniff.
 *
 * Ensures all class keywords are lowercase.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Functions_LowercaseFunctionKeywordsSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_FUNCTION,
                T_PUBLIC,
                T_PRIVATE,
                T_PROTECTED,
                T_STATIC,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $content = $tokens[$stackPtr]['content'];
        if ($content !== strtolower($content)) {
            $error = '%s keyword must be lowercase; expected "%s" but found "%s"';
            $data  = array(
                      strtoupper($content),
                      strtolower($content),
                      $content,
                     );
            $phpcsFile->addError($error, $stackPtr, 'FoundUppercase', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_Functions_GlobalFunctionSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Functions_GlobalFunctionSniff.
 *
 * Tests for functions outside of classes.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Functions_GlobalFunctionSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_FUNCTION);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if (empty($tokens[$stackPtr]['conditions']) === true) {
            $functionName = $phpcsFile->getDeclarationName($stackPtr);
            if ($functionName === null) {
                return;
            }

            // Special exception for __autoload as it needs to be global.
            if ($functionName !== '__autoload') {
                $error = 'Consider putting global function "%s" in a static class';
                $data  = array($functionName);
                $phpcsFile->addWarning($error, $stackPtr, 'Found', $data);
            }
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_ControlStructures_LowercaseDeclarationSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_ControlStructures_LowercaseDeclarationSniff.
 *
 * Ensures all control structure keywords are lowercase.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_ControlStructures_LowercaseDeclarationSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_IF,
                T_ELSE,
                T_ELSEIF,
                T_FOREACH,
                T_FOR,
                T_DO,
                T_SWITCH,
                T_WHILE,
                T_TRY,
                T_CATCH,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $content = $tokens[$stackPtr]['content'];
        if ($content !== strtolower($content)) {
            $error = '%s keyword must be lowercase; expected "%s" but found "%s"';
            $data  = array(
                      strtoupper($content),
                      strtolower($content),
                      $content,
                     );
            $phpcsFile->addError($error, $stackPtr, 'FoundUppercase', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_ControlStructures_SwitchDeclarationSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_ControlStructures_SwitchDeclarationSniff.
 *
 * Ensures all the breaks and cases are aligned correctly according to their
 * parent switch's alignment and enforces other switch formatting.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_ControlStructures_SwitchDeclarationSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                  );

    /**
     * The number of spaces code should be indented.
     *
     * @var int
     */
    public $indent = 4;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_SWITCH);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // We can't process SWITCH statements unless we know where they start and end.
        if (isset($tokens[$stackPtr]['scope_opener']) === false
            || isset($tokens[$stackPtr]['scope_closer']) === false
        ) {
            return;
        }

        $switch        = $tokens[$stackPtr];
        $nextCase      = $stackPtr;
        $caseAlignment = ($switch['column'] + $this->indent);
        $caseCount     = 0;
        $foundDefault  = false;

        while (($nextCase = $phpcsFile->findNext(array(T_CASE, T_DEFAULT, T_SWITCH), ($nextCase + 1), $switch['scope_closer'])) !== false) {
            // Skip nested SWITCH statements; they are handled on their own.
            if ($tokens[$nextCase]['code'] === T_SWITCH) {
                $nextCase = $tokens[$nextCase]['scope_closer'];
                continue;
            }

            if ($tokens[$nextCase]['code'] === T_DEFAULT) {
                $type         = 'Default';
                $foundDefault = true;
            } else {
                $type = 'Case';
                $caseCount++;
            }

            if ($tokens[$nextCase]['content'] !== strtolower($tokens[$nextCase]['content'])) {
                $expected = strtolower($tokens[$nextCase]['content']);
                $error    = strtoupper($type).' keyword must be lowercase; expected "%s" but found "%s"';
                $data     = array(
                             $expected,
                             $tokens[$nextCase]['content'],
                            );
                $phpcsFile->addError($error, $nextCase, $type.'NotLower', $data);
            }

            if ($tokens[$nextCase]['column'] !== $caseAlignment) {
                $error = strtoupper($type).' keyword must be indented '.$this->indent.' spaces from SWITCH keyword';
                $phpcsFile->addError($error, $nextCase, $type.'Indent');
            }

            if ($type === 'Case'
                && ($tokens[($nextCase + 1)]['type'] !== 'T_WHITESPACE'
                || $tokens[($nextCase + 1)]['content'] !== ' ')
            ) {
                $error = 'CASE keyword must be followed by a single space';
                $phpcsFile->addError($error, $nextCase, 'SpacingAfterCase');
            }

            $opener = $tokens[$nextCase]['scope_opener'];
            if ($tokens[($opener - 1)]['type'] === 'T_WHITESPACE') {
                $error = 'There must be no space before the colon in a '.strtoupper($type).' statement';
                $phpcsFile->addError($error, $nextCase, 'SpaceBeforeColon'.$type);
            }

            $nextBreak = $tokens[$nextCase]['scope_closer'];
            if ($tokens[$nextBreak]['code'] === T_BREAK
                || $tokens[$nextBreak]['code'] === T_RETURN
                || $tokens[$nextBreak]['code'] === T_CONTINUE
                || $tokens[$nextBreak]['code'] === T_THROW
            ) {
                if ($tokens[$nextBreak]['scope_condition'] === $nextCase) {
                    // Only need to check a couple of things once, even if the
                    // break is shared between multiple case statements, or even
                    // the default case.
                    if ($tokens[$nextBreak]['column'] !== $caseAlignment) {
                        $error = 'Case breaking statement must be indented '.$this->indent.' spaces from SWITCH keyword';
                        $phpcsFile->addError($error, $nextBreak, 'BreakIndent');
                    }

                    $breakLine = $tokens[$nextBreak]['line'];
                    $prevLine  = 0;
                    for ($i = ($nextBreak - 1); $i > $stackPtr; $i--) {
                        if ($tokens[$i]['type'] !== 'T_WHITESPACE') {
                            $prevLine = $tokens[$i]['line'];
                            break;
                        }
                    }

                    if ($prevLine !== ($breakLine - 1)) {
                        $error = 'Blank lines are not allowed before case breaking statements';
                        $phpcsFile->addError($error, $nextBreak, 'SpacingBeforeBreak');
                    }

                    $breakLine = $tokens[$nextBreak]['line'];
                    $nextLine  = $tokens[$tokens[$stackPtr]['scope_closer']]['line'];
                    $semicolon = $phpcsFile->findNext(T_SEMICOLON, $nextBreak);
                    for ($i = ($semicolon + 1); $i < $tokens[$stackPtr]['scope_closer']; $i++) {
                        if ($tokens[$i]['type'] !== 'T_WHITESPACE') {
                            $nextLine = $tokens[$i]['line'];
                            break;
                        }
                    }

                    if ($type === 'Case') {
                        // Ensure the BREAK statement is followed by
                        // a single blank line, or the end switch brace.
                        if ($nextLine !== ($breakLine + 2) && $i !== $tokens[$stackPtr]['scope_closer']) {
                            $error = 'Case breaking statements must be followed by a single blank line';
                            $phpcsFile->addError($error, $nextBreak, 'SpacingAfterBreak');
                        }
                    } else {
                        // Ensure the BREAK statement is not followed by a blank line.
                        if ($nextLine !== ($breakLine + 1)) {
                            $error = 'Blank lines are not allowed after the DEFAULT case\'s breaking statement';
                            $phpcsFile->addError($error, $nextBreak, 'SpacingAfterDefaultBreak');
                        }
                    }

                    $caseLine = $tokens[$nextCase]['line'];
                    $nextLine = $tokens[$nextBreak]['line'];
                    for ($i = ($opener + 1); $i < $nextBreak; $i++) {
                        if ($tokens[$i]['type'] !== 'T_WHITESPACE') {
                            $nextLine = $tokens[$i]['line'];
                            break;
                        }
                    }

                    if ($nextLine !== ($caseLine + 1)) {
                        $error = 'Blank lines are not allowed after '.strtoupper($type).' statements';
                        $phpcsFile->addError($error, $nextCase, 'SpacingAfter'.$type);
                    }
                }//end if

                if ($tokens[$nextBreak]['code'] === T_BREAK) {
                    if ($type === 'Case') {
                        // Ensure empty CASE statements are not allowed.
                        // They must have some code content in them. A comment is not enough.
                        // But count RETURN statements as valid content if they also
                        // happen to close the CASE statement.
                        $foundContent = false;
                        for ($i = ($tokens[$nextCase]['scope_opener'] + 1); $i < $nextBreak; $i++) {
                            if ($tokens[$i]['code'] === T_CASE) {
                                $i = $tokens[$i]['scope_opener'];
                                continue;
                            }

                            if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
                                $foundContent = true;
                                break;
                            }
                        }

                        if ($foundContent === false) {
                            $error = 'Empty CASE statements are not allowed';
                            $phpcsFile->addError($error, $nextCase, 'EmptyCase');
                        }
                    } else {
                        // Ensure empty DEFAULT statements are not allowed.
                        // They must (at least) have a comment describing why
                        // the default case is being ignored.
                        $foundContent = false;
                        for ($i = ($tokens[$nextCase]['scope_opener'] + 1); $i < $nextBreak; $i++) {
                            if ($tokens[$i]['type'] !== 'T_WHITESPACE') {
                                $foundContent = true;
                                break;
                            }
                        }

                        if ($foundContent === false) {
                            $error = 'Comment required for empty DEFAULT case';
                            $phpcsFile->addError($error, $nextCase, 'EmptyDefault');
                        }
                    }//end if
                }//end if
            } else if ($type === 'Default') {
                $error = 'DEFAULT case must have a breaking statement';
                $phpcsFile->addError($error, $nextCase, 'DefaultNoBreak');
            }//end if
        }//end while

        if ($foundDefault === false) {
            $error = 'All SWITCH statements must contain a DEFAULT case';
            $phpcsFile->addError($error, $stackPtr, 'MissingDefault');
        }

        if ($tokens[$switch['scope_closer']]['column'] !== $switch['column']) {
            $error = 'Closing brace of SWITCH statement must be aligned with SWITCH keyword';
            $phpcsFile->addError($error, $switch['scope_closer'], 'CloseBraceAlign');
        }

        if ($caseCount === 0) {
            $error = 'SWITCH statements must contain at least one CASE statement';
            $phpcsFile->addError($error, $stackPtr, 'MissingCase');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Verifies that control statements conform to their coding standards.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_Standards_AbstractPatternSniff', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_Standards_AbstractPatternSniff not found');
}

/**
 * Verifies that control statements conform to their coding standards.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_ControlStructures_ControlSignatureSniff extends PHP_CodeSniffer_Standards_AbstractPatternSniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                  );


    /**
     * Returns the patterns that this test wishes to verify.
     *
     * @return array(string)
     */
    protected function getPatterns()
    {
        return array(
                'try {EOL...} catch (...) {EOL',
                'do {EOL...} while (...);EOL',
                'while (...) {EOL',
                'for (...) {EOL',
                'if (...) {EOL',
                'foreach (...) {EOL',
                '} else if (...) {EOL',
                '} elseif (...) {EOL',
                '} else {EOL',
               );

    }//end getPatterns()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_ControlStructures_ElseIfDeclarationSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_ControlStructures_ElseIfDeclarationSniff.
 *
 * Verifies that there are not elseif statements. The else and the if should
 * be separated by a space.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_ControlStructures_ElseIfDeclarationSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_ELSEIF);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $error = 'Usage of ELSEIF not allowed; use ELSE IF instead';
        $phpcsFile->addError($error, $stackPtr, 'NotAllowed');

    }//end process()


}//end class


?>
<?php
/**
 * Squiz_Sniffs_ControlStructures_ForLoopDeclarationSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_ControlStructures_ForLoopDeclarationSniff.
 *
 * Verifies that there is a space between each condition of for loops.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_ControlStructures_ForLoopDeclarationSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                  );


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_FOR);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $openingBracket = $phpcsFile->findNext(T_OPEN_PARENTHESIS, $stackPtr);
        if ($openingBracket === false) {
            $error = 'Possible parse error: no opening parenthesis for FOR keyword';
            $phpcsFile->addWarning($error, $stackPtr, 'NoOpenBracket');
            return;
        }

        $closingBracket = $tokens[$openingBracket]['parenthesis_closer'];

        if ($tokens[($openingBracket + 1)]['code'] === T_WHITESPACE) {
            $error = 'Space found after opening bracket of FOR loop';
            $phpcsFile->addError($error, $stackPtr, 'SpacingAfterOpen');
        }

        if ($tokens[($closingBracket - 1)]['code'] === T_WHITESPACE) {
            $error = 'Space found before closing bracket of FOR loop';
            $phpcsFile->addError($error, $stackPtr, 'SpacingBeforeClose');
        }

        $firstSemicolon  = $phpcsFile->findNext(T_SEMICOLON, $openingBracket, $closingBracket);

        // Check whitespace around each of the tokens.
        if ($firstSemicolon !== false) {
            if ($tokens[($firstSemicolon - 1)]['code'] === T_WHITESPACE) {
                $error = 'Space found before first semicolon of FOR loop';
                $phpcsFile->addError($error, $stackPtr, 'SpacingBeforeFirst');
            }

            if ($tokens[($firstSemicolon + 1)]['code'] !== T_WHITESPACE
                && $tokens[($firstSemicolon + 1)]['code'] !== T_SEMICOLON
            ) {
                $error = 'Expected 1 space after first semicolon of FOR loop; 0 found';
                $phpcsFile->addError($error, $stackPtr, 'NoSpaceAfterFirst');
            } else {
                if (strlen($tokens[($firstSemicolon + 1)]['content']) !== 1) {
                    $spaces = strlen($tokens[($firstSemicolon + 1)]['content']);
                    $error  = 'Expected 1 space after first semicolon of FOR loop; %s found';
                    $data   = array($spaces);
                    $phpcsFile->addError($error, $stackPtr, 'SpacingAfterFirst', $data);
                }
            }

            $secondSemicolon = $phpcsFile->findNext(T_SEMICOLON, ($firstSemicolon + 1));

            if ($secondSemicolon !== false) {
                if ($tokens[($secondSemicolon - 1)]['code'] === T_WHITESPACE
                    && $tokens[($firstSemicolon + 1)]['code'] !== T_SEMICOLON
                ) {
                    $error = 'Space found before second semicolon of FOR loop';
                    $phpcsFile->addError($error, $stackPtr, 'SpacingBeforeSecond');
                }

                if (($secondSemicolon + 1) !== $closingBracket
                    && $tokens[($secondSemicolon + 1)]['code'] !== T_WHITESPACE
                ) {
                    $error = 'Expected 1 space after second semicolon of FOR loop; 0 found';
                    $phpcsFile->addError($error, $stackPtr, 'NoSpaceAfterSecond');
                } else {
                    if (strlen($tokens[($secondSemicolon + 1)]['content']) !== 1) {
                        $spaces = strlen($tokens[($secondSemicolon + 1)]['content']);
                        $data   = array($spaces);
                        if (($secondSemicolon + 2) === $closingBracket) {
                            $error = 'Expected no space after second semicolon of FOR loop; %s found';
                            $phpcsFile->addError($error, $stackPtr, 'SpacingAfterSecondNoThird', $data);
                        } else {
                            $error = 'Expected 1 space after second semicolon of FOR loop; %s found';
                            $phpcsFile->addError($error, $stackPtr, 'SpacingAfterSecond', $data);
                        }
                    }
                }
            }//end if
        }//end if

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_ControlStructures_InlineControlStructureSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_ControlStructures_InlineIfDeclarationSniff.
 *
 * Tests the spacing of shorthand IF statements.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_ControlStructures_InlineIfDeclarationSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_INLINE_THEN);

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Find the opening bracket of the inline IF.
        for ($i = ($stackPtr - 1); $i > 0; $i--) {
            if (isset($tokens[$i]['parenthesis_opener']) === true
                && $tokens[$i]['parenthesis_opener'] < $i
            ) {
                $i = $tokens[$i]['parenthesis_opener'];
                continue;
            }

            if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS) {
                break;
            }
        }

        if ($i <= 0) {
            // Could not find the beginning of the statement. Probably not
            // wrapped with brackets, so assume it ends with a semicolon.
            $statementEnd = $phpcsFile->findNext(T_SEMICOLON, ($stackPtr + 1));
        } else {
            $statementEnd = $tokens[$i]['parenthesis_closer'];
        }

        // Make sure it's all on the same line.
        if ($tokens[$statementEnd]['line'] !== $tokens[$stackPtr]['line']) {
            $error = 'Inline shorthand IF statement must be declared on a single line';
            $phpcsFile->addError($error, $stackPtr, 'NotSingleLine');
            return;
        }

        // Make sure there are spaces around the question mark.
        $contentBefore = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
        $contentAfter  = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
        if ($tokens[$contentBefore]['code'] !== T_CLOSE_PARENTHESIS) {
            $error = 'Inline shorthand IF statement requires brackets around comparison';
            $phpcsFile->addError($error, $stackPtr, 'NoBrackets');
            return;
        }

        $spaceBefore = ($tokens[$stackPtr]['column'] - ($tokens[$contentBefore]['column'] + strlen($tokens[$contentBefore]['content'])));
        if ($spaceBefore !== 1) {
            $error = 'Inline shorthand IF statement requires 1 space before THEN; %s found';
            $data  = array($spaceBefore);
            $phpcsFile->addError($error, $stackPtr, 'SpacingBeforeThen', $data);
        }

        $spaceAfter = (($tokens[$contentAfter]['column']) - ($tokens[$stackPtr]['column'] + 1));
        if ($spaceAfter !== 1) {
            $error = 'Inline shorthand IF statement requires 1 space after THEN; %s found';
            $data  = array($spaceAfter);
            $phpcsFile->addError($error, $stackPtr, 'SpacingAfterThen', $data);
        }

        // Make sure the ELSE has the correct spacing.
        $inlineElse    = $phpcsFile->findNext(T_INLINE_ELSE, ($stackPtr + 1), $statementEnd, false);
        $contentBefore = $phpcsFile->findPrevious(T_WHITESPACE, ($inlineElse - 1), null, true);
        $contentAfter  = $phpcsFile->findNext(T_WHITESPACE, ($inlineElse + 1), null, true);

        $spaceBefore = ($tokens[$inlineElse]['column'] - ($tokens[$contentBefore]['column'] + strlen($tokens[$contentBefore]['content'])));
        if ($spaceBefore !== 1) {
            $error = 'Inline shorthand IF statement requires 1 space before ELSE; %s found';
            $data  = array($spaceBefore);
            $phpcsFile->addError($error, $inlineElse, 'SpacingBeforeElse', $data);
        }

        $spaceAfter = (($tokens[$contentAfter]['column']) - ($tokens[$inlineElse]['column'] + 1));
        if ($spaceAfter !== 1) {
            $error = 'Inline shorthand IF statement requires 1 space after ELSE; %s found';
            $data  = array($spaceAfter);
            $phpcsFile->addError($error, $inlineElse, 'SpacingAfterElse', $data);
        }

    }//end process()


}//end class


?>
<?php
/**
 * Squiz_Sniffs_ControlStructures_ForEachLoopDeclarationSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_ControlStructures_ForEachLoopDeclarationSniff.
 *
 * Verifies that there is a space between each condition of foreach loops.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_ControlStructures_ForEachLoopDeclarationSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_FOREACH);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $openingBracket = $phpcsFile->findNext(T_OPEN_PARENTHESIS, $stackPtr);
        $closingBracket = $tokens[$openingBracket]['parenthesis_closer'];

        if ($tokens[($openingBracket + 1)]['code'] === T_WHITESPACE) {
            $error = 'Space found after opening bracket of FOREACH loop';
            $phpcsFile->addError($error, $stackPtr, 'SpaceAfterOpen');
        }

        if ($tokens[($closingBracket - 1)]['code'] === T_WHITESPACE) {
            $error = 'Space found before closing bracket of FOREACH loop';
            $phpcsFile->addError($error, $stackPtr, 'SpaceBeforeClose');
        }

        $asToken = $phpcsFile->findNext(T_AS, $openingBracket);
        $content = $tokens[$asToken]['content'];
        if ($content !== strtolower($content)) {
            $expected = strtolower($content);
            $error    = 'AS keyword must be lowercase; expected "%s" but found "%s"';
            $data     = array(
                         $expected,
                         $content,
                        );
            $phpcsFile->addError($error, $stackPtr, 'AsNotLower', $data);
        }

        $doubleArrow = $phpcsFile->findNext(T_DOUBLE_ARROW, $openingBracket, $closingBracket);

        if ($doubleArrow !== false) {
            if ($tokens[($doubleArrow - 1)]['code'] !== T_WHITESPACE) {
                $error = 'Expected 1 space before "=>"; 0 found';
                $phpcsFile->addError($error, $stackPtr, 'NoSpaceBeforeArrow');
            } else {
                if (strlen($tokens[($doubleArrow - 1)]['content']) !== 1) {
                    $spaces = strlen($tokens[($doubleArrow - 1)]['content']);
                    $error  = 'Expected 1 space before "=>"; %s found';
                    $data   = array($spaces);
                    $phpcsFile->addError($error, $stackPtr, 'SpacingBeforeArrow', $data);
                }

            }

            if ($tokens[($doubleArrow + 1)]['code'] !== T_WHITESPACE) {
                $error = 'Expected 1 space after "=>"; 0 found';
                $phpcsFile->addError($error, $stackPtr, 'NoSpaceAfterArrow');
            } else {
                if (strlen($tokens[($doubleArrow + 1)]['content']) !== 1) {
                    $spaces = strlen($tokens[($doubleArrow + 1)]['content']);
                    $error  = 'Expected 1 space after "=>"; %s found';
                    $data   = array($spaces);
                    $phpcsFile->addError($error, $stackPtr, 'SpacingAfterArrow', $data);
                }

            }

        }//end if

        if ($tokens[($asToken - 1)]['code'] !== T_WHITESPACE) {
            $error = 'Expected 1 space before "as"; 0 found';
            $phpcsFile->addError($error, $stackPtr, 'NoSpaceBeforeAs');
        } else {
            if (strlen($tokens[($asToken - 1)]['content']) !== 1) {
                $spaces = strlen($tokens[($asToken - 1)]['content']);
                $error  = 'Expected 1 space before "as"; %s found';
                $data   = array($spaces);
                $phpcsFile->addError($error, $stackPtr, 'SpacingBeforeAs', $data);
            }
        }

        if ($tokens[($asToken + 1)]['code'] !== T_WHITESPACE) {
            $error = 'Expected 1 space after "as"; 0 found';
            $phpcsFile->addError($error, $stackPtr, 'NoSpaceAfterAs');
        } else {
            if (strlen($tokens[($asToken + 1)]['content']) !== 1) {
                $spaces = strlen($tokens[($asToken + 1)]['content']);
                $error  = 'Expected 1 space after "as"; %s found';
                $data   = array($spaces);
                $phpcsFile->addError($error, $stackPtr, 'SpacingAfterAs', $data);
            }
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_Operators_ValidLogicalOperatorsSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Operators_ValidLogicalOperatorsSniff.
 *
 * Checks to ensure that the logical operators 'and' and 'or' are not used.
 * Use the && and || operators instead.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Operators_ValidLogicalOperatorsSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_LOGICAL_AND,
                T_LOGICAL_OR,
                T_LOGICAL_XOR,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The current file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $replacements = array(
                         'and' => '&&',
                         'or'  => '||',
                         'xor' => '^',
                        );

        $operator = strtolower($tokens[$stackPtr]['content']);
        if (isset($replacements[$operator]) === false) {
            return;
        }

        $error = 'Logical operator "%s" is prohibited; use "%s" instead';
        $data  = array(
                  $operator,
                  $replacements[$operator],
                 );
        $phpcsFile->addError($error, $stackPtr, 'NotAllowed', $data);

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_Operators_IncrementDecrementUsageSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Operators_IncrementDecrementUsageSniff.
 *
 * Tests that the ++ operators are used when possible and not
 * used when it makes the code confusing.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Operators_IncrementDecrementUsageSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_EQUAL,
                T_PLUS_EQUAL,
                T_MINUS_EQUAL,
                T_INC,
                T_DEC,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if ($tokens[$stackPtr]['code'] === T_INC || $tokens[$stackPtr]['code'] === T_DEC) {
            $this->processIncDec($phpcsFile, $stackPtr);
        } else {
            $this->processAssignment($phpcsFile, $stackPtr);
        }

    }//end process()


    /**
     * Checks to ensure increment and decrement operators are not confusing.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    protected function processIncDec(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Work out where the variable is so we know where to
        // start looking for other operators.
        if ($tokens[($stackPtr - 1)]['code'] === T_VARIABLE) {
            $start = ($stackPtr + 1);
        } else {
            $start = ($stackPtr + 2);
        }

        $next = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $start, null, true);
        if ($next === false) {
            return;
        }

        if (in_array($tokens[$next]['code'], PHP_CodeSniffer_Tokens::$arithmeticTokens) === true) {
            $error = 'Increment and decrement operators cannot be used in an arithmetic operation';
            $phpcsFile->addError($error, $stackPtr, 'NotAllowed');
            return;
        }

        $prev = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($start - 3), null, true);
        if ($prev === false) {
            return;
        }

        // Check if this is in a string concat.
        if ($tokens[$next]['code'] === T_STRING_CONCAT || $tokens[$prev]['code'] === T_STRING_CONCAT) {
            $error = 'Increment and decrement operators must be bracketed when used in string concatenation';
            $phpcsFile->addError($error, $stackPtr, 'NoBrackets');
        }

    }//end processIncDec()


    /**
     * Checks to ensure increment and decrement operators are used.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    protected function processAssignment(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $assignedVar = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
        // Not an assignment, return.
        if ($tokens[$assignedVar]['code'] !== T_VARIABLE) {
            return;
        }

        $statementEnd = $phpcsFile->findNext(array(T_SEMICOLON, T_CLOSE_PARENTHESIS, T_CLOSE_SQUARE_BRACKET, T_CLOSE_CURLY_BRACKET), $stackPtr);

        // If there is anything other than variables, numbers, spaces or operators we need to return.
        $noiseTokens = $phpcsFile->findNext(array(T_LNUMBER, T_VARIABLE, T_WHITESPACE, T_PLUS, T_MINUS, T_OPEN_PARENTHESIS), ($stackPtr + 1), $statementEnd, true);

        if ($noiseTokens !== false) {
            return;
        }

        // If we are already using += or -=, we need to ignore
        // the statement if a variable is being used.
        if ($tokens[$stackPtr]['code'] !== T_EQUAL) {
            $nextVar = $phpcsFile->findNext(T_VARIABLE, ($stackPtr + 1), $statementEnd);
            if ($nextVar !== false) {
                return;
            }
        }

        if ($tokens[$stackPtr]['code'] === T_EQUAL) {
            $nextVar          = ($stackPtr + 1);
            $previousVariable = ($stackPtr + 1);
            $variableCount    = 0;
            while (($nextVar = $phpcsFile->findNext(T_VARIABLE, ($nextVar + 1), $statementEnd)) !== false) {
                $previousVariable = $nextVar;
                $variableCount++;
            }

            if ($variableCount !== 1) {
                return;
            }

            $nextVar = $previousVariable;
            if ($tokens[$nextVar]['content'] !== $tokens[$assignedVar]['content']) {
                return;
            }
        }

        // We have only one variable, and it's the same as what is being assigned,
        // so we need to check what is being added or subtracted.
        $nextNumber     = ($stackPtr + 1);
        $previousNumber = ($stackPtr + 1);
        $numberCount    = 0;
        while (($nextNumber = $phpcsFile->findNext(array(T_LNUMBER), ($nextNumber + 1), $statementEnd, false)) !== false) {
            $previousNumber = $nextNumber;
            $numberCount++;
        }

        if ($numberCount !== 1) {
            return;
        }

        $nextNumber = $previousNumber;
        if ($tokens[$nextNumber]['content'] === '1') {
            if ($tokens[$stackPtr]['code'] === T_EQUAL) {
                $opToken = $phpcsFile->findNext(array(T_PLUS, T_MINUS), ($nextVar + 1), $statementEnd);
                if ($opToken === false) {
                    // Operator was before the variable, like:
                    // $var = 1 + $var;
                    // So we ignore it.
                    return;
                }

                $operator = $tokens[$opToken]['content'];
            } else {
                $operator = substr($tokens[$stackPtr]['content'], 0, 1);
            }

            // If we are adding or subtracting negative value, the operator
            // needs to be reversed.
            if ($tokens[$stackPtr]['code'] !== T_EQUAL) {
                $negative = $phpcsFile->findPrevious(T_MINUS, ($nextNumber - 1), $stackPtr);
                if ($negative !== false) {
                    $operator = ($operator === '+') ? '-' : '+';
                }
            }

            $expected = $tokens[$assignedVar]['content'].$operator.$operator;
            $found    = $phpcsFile->getTokensAsString($assignedVar, ($statementEnd - $assignedVar + 1));

            if ($operator === '+') {
                $error = 'Increment';
            } else {
                $error = 'Decrement';
            }

            $error .= " operators should be used where possible; found \"$found\" but expected \"$expected\"";
            $phpcsFile->addError($error, $stackPtr);
        }//end if

    }//end processAssignment()


}//end class

?>
<?php
/**
 * A Sniff to enforce the use of IDENTICAL type operators rather than EQUAL operators.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * A Sniff to enforce the use of IDENTICAL type operators rather than EQUAL operators.
 *
 * The use of === true is enforced over implicit true statements,
 * for example:
 *
 * <code>
 * if ($a)
 * {
 *     ...
 * }
 * </code>
 *
 * should be:
 *
 * <code>
 * if ($a === true)
 * {
 *     ...
 * }
 * </code>
 *
 * It also enforces the use of === false over ! operators.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Operators_ComparisonOperatorUsageSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                  );

    /**
     * A list of valid comparison operators.
     *
     * @var array
     */
    private static $_validOps = array(
                                 T_IS_IDENTICAL,
                                 T_IS_NOT_IDENTICAL,
                                 T_LESS_THAN,
                                 T_GREATER_THAN,
                                 T_IS_GREATER_OR_EQUAL,
                                 T_IS_SMALLER_OR_EQUAL,
                                 T_INSTANCEOF,
                                );

    /**
     * A list of invalid operators with their alternatives.
     *
     * @var array(int => string)
     */
    private static $_invalidOps = array(
                                   'PHP' => array(
                                             T_IS_EQUAL     => '===',
                                             T_IS_NOT_EQUAL => '!==',
                                             T_BOOLEAN_NOT  => '=== FALSE',
                                            ),
                                   'JS'  => array(
                                             T_IS_EQUAL     => '===',
                                             T_IS_NOT_EQUAL => '!==',
                                            ),
                                  );


    /**
     * Registers the token types that this sniff wishes to listen to.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_IF,
                T_ELSEIF,
                T_INLINE_THEN,
               );

    }//end register()


    /**
     * Process the tokens that this sniff is listening for.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where the token
     *                                        was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens    = $phpcsFile->getTokens();
        $tokenizer = $phpcsFile->tokenizerType;

        if ($tokens[$stackPtr]['code'] === T_INLINE_THEN) {
            $end = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr - 1), null, true);
            if ($tokens[$end]['code'] !== T_CLOSE_PARENTHESIS) {
                // This inline IF statement does not have its condition
                // bracketed, so we need to guess where it starts.
                for ($i = ($end - 1); $i >= 0; $i--) {
                    if ($tokens[$i]['code'] === T_SEMICOLON) {
                        // Stop here as we assume it is the end
                        // of the previous statement.
                        break;
                    } else if ($tokens[$i]['code'] === T_OPEN_TAG) {
                        // Stop here as this is the start of the file.
                        break;
                    } else if ($tokens[$i]['code'] === T_CLOSE_CURLY_BRACKET) {
                        // Stop if this is the closing brace of
                        // a code block.
                        if (isset($tokens[$i]['scope_opener']) === true) {
                            break;
                        }
                    } else if ($tokens[$i]['code'] === T_OPEN_CURLY_BRACKET) {
                        // Stop if this is the opening brace of
                        // a code block.
                        if (isset($tokens[$i]['scope_closer']) === true) {
                            break;
                        }
                    }
                }//end for

                $start = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($i + 1), null, true);
            } else {
                $start = $tokens[$end]['parenthesis_opener'];
            }
        } else {
            $start = $tokens[$stackPtr]['parenthesis_opener'];
            $end   = $tokens[$stackPtr]['parenthesis_closer'];
        }

        $requiredOps = 0;
        $foundOps    = 0;

        for ($i = $start; $i <= $end; $i++) {
            $type = $tokens[$i]['code'];
            if (in_array($type, array_keys(self::$_invalidOps[$tokenizer])) === true) {
                $error = 'Operator %s prohibited; use %s instead';
                $data  = array(
                          $tokens[$i]['content'],
                          self::$_invalidOps[$tokenizer][$type],
                         );
                $phpcsFile->addError($error, $i, 'NotAllowed', $data);
                $foundOps++;
            } else if (in_array($type, self::$_validOps) === true) {
                $foundOps++;
            }

            if ($phpcsFile->tokenizerType !== 'JS') {
                if ($tokens[$i]['code'] === T_BOOLEAN_AND || $tokens[$i]['code'] === T_BOOLEAN_OR) {
                    $requiredOps++;

                    // If we get to here and we have not found the right number of
                    // comparison operators, then we must have had an implicit
                    // true operation ie. if ($a) instead of the required
                    // if ($a === true), so let's add an error.
                    if ($requiredOps !== $foundOps) {
                        $error = 'Implicit true comparisons prohibited; use === TRUE instead';
                        $phpcsFile->addError($error, $stackPtr, 'ImplicitTrue');
                        $foundOps++;
                    }
                }
            }//end if
        }//end for

        $requiredOps++;

        if ($phpcsFile->tokenizerType !== 'JS') {
            if ($foundOps < $requiredOps) {
                $error = 'Implicit true comparisons prohibited; use === TRUE instead';
                $phpcsFile->addError($error, $stackPtr, 'ImplicitTrue');
            }
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_Objects_ObjectInstantiationSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Objects_ObjectInstantiationSniff.
 *
 * Ensures objects are assigned to a variable when instantiated.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Objects_ObjectInstantiationSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Registers the token types that this sniff wishes to listen to.
     *
     * @return array
     */
    public function register()
    {
        return array(T_NEW);

    }//end register()


    /**
     * Process the tokens that this sniff is listening for.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        the token was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $allowedTokens   = PHP_CodeSniffer_Tokens::$emptyTokens;
        $allowedTokens[] = T_BITWISE_AND;

        $prev = $phpcsFile->findPrevious($allowedTokens, ($stackPtr - 1), null, true);

        $allowedTokens = array(
                          T_EQUAL,
                          T_DOUBLE_ARROW,
                          T_THROW,
                          T_RETURN,
                          T_INLINE_THEN,
                          T_INLINE_ELSE,
                         );

        if (in_array($tokens[$prev]['code'], $allowedTokens) === false) {
            $error = 'New objects must be assigned to a variable';
            $phpcsFile->addError($error, $stackPtr, 'NotAssigned');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_Objects_ObjectInstantiationSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Objects_ObjectInstantiationSniff.
 *
 * Ensures objects are assigned to a variable when instantiated.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Objects_ObjectMemberCommaSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('JS');


    /**
     * Registers the token types that this sniff wishes to listen to.
     *
     * @return array
     */
    public function register()
    {
        return array(T_CLOSE_CURLY_BRACKET);

    }//end register()


    /**
     * Process the tokens that this sniff is listening for.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        the token was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Only interested in orphaned braces (which are objects)
        // and object definitions.
        if (isset($tokens[$stackPtr]['scope_condition']) === true) {
            $condition = $tokens[$stackPtr]['scope_condition'];
            if ($tokens[$condition]['code'] !== T_OBJECT) {
                return;
            }
        }

        $prev = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr - 1), null, true);
        if ($tokens[$prev]['code'] === T_COMMA) {
            $error = 'Last member of object must not be followed by a comma';
            $phpcsFile->addError($error, $prev, 'Missing');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Ensures that object indexes are written in dot notation.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Sertan Danis <sdanis@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Ensures that object indexes are written in dot notation.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Sertan Danis <sdanis@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Objects_DisallowObjectStringIndexSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('JS');


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_OPEN_SQUARE_BRACKET);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Check if the next non whitespace token is a string.
        $index = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
        if ($tokens[$index]['code'] !== T_CONSTANT_ENCAPSED_STRING) {
            return;
        }

        // Make sure it is the only thing in the square brackets.
        $next = $phpcsFile->findNext(T_WHITESPACE, ($index + 1), null, true);
        if ($tokens[$next]['code'] !== T_CLOSE_SQUARE_BRACKET) {
            return;
        }

        // Allow indexes that have dots in them because we can't write
        // them in dot notation.
        $content = trim($tokens[$index]['content'], '"\' ');
        if (strpos($content, '.') !== false) {
            return;
        }

        // Also ignore reserved words.
        if ($content === 'super') {
            return;
        }

        // Token before the opening square bracket cannot be a var name.
        $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
        if ($tokens[$prev]['code'] === T_STRING) {
            $error = 'Object indexes must be written in dot notation';
            $phpcsFile->addError($error, $prev, 'Found');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_Commenting_InlineCommentSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Commenting_InlineCommentSniff.
 *
 * Checks that there is adequate spacing between comments.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Commenting_InlineCommentSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                  );

    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_COMMENT,
                T_DOC_COMMENT,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // If this is a function/class/interface doc block comment, skip it.
        // We are only interested in inline doc block comments, which are
        // not allowed.
        if ($tokens[$stackPtr]['code'] === T_DOC_COMMENT) {
            $nextToken = $phpcsFile->findNext(
                PHP_CodeSniffer_Tokens::$emptyTokens,
                ($stackPtr + 1),
                null,
                true
            );

            $ignore = array(
                       T_CLASS,
                       T_INTERFACE,
                       T_TRAIT,
                       T_FUNCTION,
                       T_PUBLIC,
                       T_PRIVATE,
                       T_PROTECTED,
                       T_FINAL,
                       T_STATIC,
                       T_ABSTRACT,
                       T_CONST,
                       T_OBJECT,
                       T_PROPERTY,
                      );

            if (in_array($tokens[$nextToken]['code'], $ignore) === true) {
                return;
            } else {
                if ($phpcsFile->tokenizerType === 'JS') {
                    // We allow block comments if a function is being assigned
                    // to a variable.
                    $ignore    = PHP_CodeSniffer_Tokens::$emptyTokens;
                    $ignore[]  = T_EQUAL;
                    $ignore[]  = T_STRING;
                    $ignore[]  = T_OBJECT_OPERATOR;
                    $nextToken = $phpcsFile->findNext($ignore, ($nextToken + 1), null, true);
                    if ($tokens[$nextToken]['code'] === T_FUNCTION) {
                        return;
                    }
                }

                $prevToken = $phpcsFile->findPrevious(
                    PHP_CodeSniffer_Tokens::$emptyTokens,
                    ($stackPtr - 1),
                    null,
                    true
                );

                if ($tokens[$prevToken]['code'] === T_OPEN_TAG) {
                    return;
                }

                // Only error once per comment.
                if (substr($tokens[$stackPtr]['content'], 0, 3) === '/**') {
                    $error  = 'Inline doc block comments are not allowed; use "/* Comment */" or "// Comment" instead';
                    $phpcsFile->addError($error, $stackPtr, 'DocBlock');
                }
            }//end if
        }//end if

        if ($tokens[$stackPtr]['content']{0} === '#') {
            $error  = 'Perl-style comments are not allowed; use "// Comment" instead';
            $phpcsFile->addError($error, $stackPtr, 'WrongStyle');
        }

        // We don't want end of block comments. If the last comment is a closing
        // curly brace.
        $previousContent = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
        if ($tokens[$previousContent]['line'] === $tokens[$stackPtr]['line']) {
            if ($tokens[$previousContent]['code'] === T_CLOSE_CURLY_BRACKET) {
                return;
            }

            // Special case for JS files.
            if ($tokens[$previousContent]['code'] === T_COMMA
                || $tokens[$previousContent]['code'] === T_SEMICOLON
            ) {
                $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($previousContent - 1), null, true);
                if ($tokens[$lastContent]['code'] === T_CLOSE_CURLY_BRACKET) {
                    return;
                }
            }
        }

        $comment = rtrim($tokens[$stackPtr]['content']);

        // Only want inline comments.
        if (substr($comment, 0, 2) !== '//') {
            return;
        }

        $spaceCount = 0;
        for ($i = 2; $i < strlen($comment); $i++) {
            if ($comment[$i] !== ' ') {
                break;
            }

            $spaceCount++;
        }

        if ($spaceCount === 0) {
            $error = 'No space before comment text; expected "// %s" but found "%s"';
            $data  = array(
                      substr($comment, 2),
                      $comment,
                     );
            $phpcsFile->addError($error, $stackPtr, 'NoSpaceBefore', $data);
        }

        if ($spaceCount > 1) {
            $error = '%s spaces found before inline comment line; use block comment if you need indentation';
            $data  = array(
                      $spaceCount,
                      substr($comment, (2 + $spaceCount)),
                      $comment,
                     );
            $phpcsFile->addError($error, $stackPtr, 'SpacingBefore', $data);
        }


        // The below section determines if a comment block is correctly capitalised,
        // and ends in a full-stop. It will find the last comment in a block, and
        // work its way up.
        $nextComment = $phpcsFile->findNext(array(T_COMMENT), ($stackPtr + 1), null, false);

        if (($nextComment !== false) && (($tokens[$nextComment]['line']) === ($tokens[$stackPtr]['line'] + 1))) {
            return;
        }

        $topComment  = $stackPtr;
        $lastComment = $stackPtr;
        while (($topComment = $phpcsFile->findPrevious(array(T_COMMENT), ($lastComment - 1), null, false)) !== false) {
            if ($tokens[$topComment]['line'] !== ($tokens[$lastComment]['line'] - 1)) {
                break;
            }

            $lastComment = $topComment;
        }

        $topComment  = $lastComment;
        $commentText = '';

        for ($i = $topComment; $i <= $stackPtr; $i++) {
            if ($tokens[$i]['code'] === T_COMMENT) {
                $commentText .= trim(substr($tokens[$i]['content'], 2));
            }
        }

        if ($commentText === '') {
            $error = 'Blank comments are not allowed';
            $phpcsFile->addError($error, $stackPtr, 'Empty');
            return;
        }

        if (preg_match('|\p{Lu}|u', $commentText[0]) === 0) {
            $error = 'Inline comments must start with a capital letter';
            $phpcsFile->addError($error, $topComment, 'NotCapital');
        }

        $commentCloser   = $commentText[(strlen($commentText) - 1)];
        $acceptedClosers = array(
                            'full-stops'        => '.',
                            'exclamation marks' => '!',
                            'or question marks' => '?',
                           );

        if (in_array($commentCloser, $acceptedClosers) === false) {
            $error = 'Inline comments must end in %s';
            $ender = '';
            foreach ($acceptedClosers as $closerName => $symbol) {
                $ender .= ' '.$closerName.',';
            }

            $ender = rtrim($ender, ',');
            $data  = array($ender);
            $phpcsFile->addError($error, $stackPtr, 'InvalidEndChar', $data);
        }

        // Finally, the line below the last comment cannot be empty.
        $start = false;
        for ($i = ($stackPtr + 1); $i < $phpcsFile->numTokens; $i++) {
            if ($tokens[$i]['line'] === ($tokens[$stackPtr]['line'] + 1)) {
                if ($tokens[$i]['code'] !== T_WHITESPACE) {
                    return;
                }
            } else if ($tokens[$i]['line'] > ($tokens[$stackPtr]['line'] + 1)) {
                break;
            }
        }

        $error = 'There must be no blank line following an inline comment';
        $phpcsFile->addError($error, $stackPtr, 'SpacingAfter');

    }//end process()


}//end class


?>
<?php
/**
 * Squiz_Sniffs_Commenting_EmptyCatchCommentSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Commenting_EmptyCatchCommentSniff.
 *
 * Checks for empty Catch clause. Catch clause must at least have comment
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Commenting_EmptyCatchCommentSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_CATCH);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile All the tokens found in the document.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $scopeStart   = $tokens[$stackPtr]['scope_opener'];
        $firstContent = $phpcsFile->findNext(T_WHITESPACE, ($scopeStart + 1), $tokens[$stackPtr]['scope_closer'], true);

        if ($firstContent === false) {
            $error = 'Empty CATCH statement must have a comment to explain why the exception is not handled';
            $phpcsFile->addError($error, $scopeStart, 'Missing');
        }

    }//end process()


}//end class


?>
<?php
/**
 * Squiz_Sniffs_Commenting_PostStatementCommentSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Commenting_PostStatementCommentSniff.
 *
 * Checks to ensure that there are no comments after statements.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Commenting_PostStatementCommentSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                  );


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_COMMENT);

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if (substr($tokens[$stackPtr]['content'], 0, 2) !== '//') {
            return;
        }

        $commentLine = $tokens[$stackPtr]['line'];
        $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);

        if ($tokens[$lastContent]['line'] !== $commentLine) {
            return;
        }

        if ($tokens[$lastContent]['code'] === T_CLOSE_CURLY_BRACKET) {
            return;
        }

        // Special case for JS files.
        if ($tokens[$lastContent]['code'] === T_COMMA
            || $tokens[$lastContent]['code'] === T_SEMICOLON
        ) {
            $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($lastContent - 1), null, true);
            if ($tokens[$lastContent]['code'] === T_CLOSE_CURLY_BRACKET) {
                return;
            }
        }

        $error = 'Comments may not appear after statements.';
        $phpcsFile->addError($error, $stackPtr, 'Found');

    }//end process()


}//end class


?>
<?php
/**
 * Verifies that a @throws tag exists for a function that throws exceptions.
 * Verifies the number of @throws tags and the number of throw tokens matches.
 * Verifies the exception type.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_Standards_AbstractScopeSniff', true) === false) {
    $error = 'Class PHP_CodeSniffer_Standards_AbstractScopeSniff not found';
    throw new PHP_CodeSniffer_Exception($error);
}

/**
 * Verifies that a @throws tag exists for a function that throws exceptions.
 * Verifies the number of @throws tags and the number of throw tokens matches.
 * Verifies the exception type.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Commenting_FunctionCommentThrowTagSniff extends PHP_CodeSniffer_Standards_AbstractScopeSniff
{


    /**
     * Constructs a Squiz_Sniffs_Commenting_FunctionCommentThrowTagSniff.
     */
    public function __construct()
    {
        parent::__construct(array(T_FUNCTION), array(T_THROW));

    }//end __construct()


    /**
     * Processes the function tokens within the class.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
     * @param int                  $stackPtr  The position where the token was found.
     * @param int                  $currScope The current scope opener token.
     *
     * @return void
     */
    protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope)
    {
        // Is this the first throw token within the current function scope?
        // If so, we have to validate other throw tokens within the same scope.
        $previousThrow = $phpcsFile->findPrevious(T_THROW, ($stackPtr - 1), $currScope);
        if ($previousThrow !== false) {
            return;
        }

        $tokens = $phpcsFile->getTokens();

        $find = array(
                 T_COMMENT,
                 T_DOC_COMMENT,
                 T_CLASS,
                 T_FUNCTION,
                 T_OPEN_TAG,
                );

        $commentEnd = $phpcsFile->findPrevious($find, ($currScope - 1));

        if ($commentEnd === false) {
            return;
        }

        if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT) {
            // Function doesn't have a comment. Let someone else warn about that.
            return;
        }

        $commentStart = ($phpcsFile->findPrevious(T_DOC_COMMENT, ($commentEnd - 1), null, true) + 1);
        $comment      = $phpcsFile->getTokensAsString($commentStart, ($commentEnd - $commentStart + 1));

        try {
            $this->commentParser = new PHP_CodeSniffer_CommentParser_FunctionCommentParser($comment, $phpcsFile);
            $this->commentParser->parse();
        } catch (PHP_CodeSniffer_CommentParser_ParserException $e) {
            $line = ($e->getLineWithinComment() + $commentStart);
            $phpcsFile->addError($e->getMessage(), $line, 'FailedParse');
            return;
        }

        // Find the position where the current function scope ends.
        $currScopeEnd = 0;
        if (isset($tokens[$currScope]['scope_closer']) === true) {
            $currScopeEnd = $tokens[$currScope]['scope_closer'];
        }

        // Find all the exception type token within the current scope.
        $throwTokens = array();
        $currPos     = $stackPtr;
        if ($currScopeEnd !== 0) {
            while ($currPos < $currScopeEnd && $currPos !== false) {

                /*
                    If we can't find a NEW, we are probably throwing
                    a variable, so we ignore it, but they still need to
                    provide at least one @throws tag, even through we
                    don't know the exception class.
                */

                $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($currPos + 1), null, true);
                if ($tokens[$nextToken]['code'] === T_NEW) {
                    $currException = $phpcsFile->findNext(
                        array(
                         T_NS_SEPARATOR,
                         T_STRING,
                        ),
                        $currPos,
                        $currScopeEnd,
                        false,
                        null,
                        true
                    );

                    if ($currException !== false) {
                        $endException = $phpcsFile->findNext(
                            array(
                             T_NS_SEPARATOR,
                             T_STRING,
                            ),
                            ($currException + 1),
                            $currScopeEnd,
                            true,
                            null,
                            true
                        );

                        if ($endException === false) {
                            $throwTokens[] = $tokens[$currException]['content'];
                        } else {
                            $throwTokens[] = $phpcsFile->getTokensAsString($currException, ($endException - $currException));
                        }
                    }//end if
                }//end if

                $currPos = $phpcsFile->findNext(T_THROW, ($currPos + 1), $currScopeEnd);
            }//end while
        }//end if

        // Only need one @throws tag for each type of exception thrown.
        $throwTokens = array_unique($throwTokens);
        sort($throwTokens);

        $throws = $this->commentParser->getThrows();
        if (empty($throws) === true) {
            $error = 'Missing @throws tag in function comment';
            $phpcsFile->addError($error, $commentEnd, 'Missing');
        } else if (empty($throwTokens) === true) {
            // If token count is zero, it means that only variables are being
            // thrown, so we need at least one @throws tag (checked above).
            // Nothing more to do.
            return;
        } else {
            $throwTags  = array();
            $lineNumber = array();
            foreach ($throws as $throw) {
                $throwTags[]                    = $throw->getValue();
                $lineNumber[$throw->getValue()] = $throw->getLine();
            }

            $throwTags = array_unique($throwTags);
            sort($throwTags);

            // Make sure @throws tag count matches throw token count.
            $tokenCount = count($throwTokens);
            $tagCount   = count($throwTags);
            if ($tokenCount !== $tagCount) {
                $error = 'Expected %s @throws tag(s) in function comment; %s found';
                $data  = array(
                          $tokenCount,
                          $tagCount,
                         );
                $phpcsFile->addError($error, $commentEnd, 'WrongNumber', $data);
                return;
            } else {
                // Exception type in @throws tag must be thrown in the function.
                foreach ($throwTags as $i => $throwTag) {
                    $errorPos = ($commentStart + $lineNumber[$throwTag]);
                    if (empty($throwTag) === false && $throwTag !== $throwTokens[$i]) {
                        $error = 'Expected "%s" but found "%s" for @throws tag exception';
                        $data  = array(
                                  $throwTokens[$i],
                                  $throwTag,
                                 );
                        $phpcsFile->addError($error, $errorPos, 'WrongType', $data);
                    }
                }
            }
        }//end if

    }//end processTokenWithinScope()


}//end class
?>
<?php
/**
 * Squiz_Sniffs_Commenting_ClosingDeclarationCommentSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Commenting_ClosingDeclarationCommentSniff.
 *
 * Checks the //end ... comments on classes, interfaces and functions.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Commenting_ClosingDeclarationCommentSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_FUNCTION,
                T_CLASS,
                T_INTERFACE,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens..
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if ($tokens[$stackPtr]['code'] === T_FUNCTION) {

            $methodProps = $phpcsFile->getMethodProperties($stackPtr);

            // Abstract methods do not require a closing comment.
            if ($methodProps['is_abstract'] === true) {
                return;
            }

            // Closures do not require a closing comment.
            if ($methodProps['is_closure'] === true) {
                return;
            }

            // If this function is in an interface then we don't require
            // a closing comment.
            if ($phpcsFile->hasCondition($stackPtr, T_INTERFACE) === true) {
                return;
            }

            if (isset($tokens[$stackPtr]['scope_closer']) === false) {
                $error = 'Possible parse error: non-abstract method defined as abstract';
                $phpcsFile->addWarning($error, $stackPtr, 'Abstract');
                return;
            }

            $decName = $phpcsFile->getDeclarationName($stackPtr);
            $comment = '//end '.$decName.'()';
        } else if ($tokens[$stackPtr]['code'] === T_CLASS) {
            $comment = '//end class';
        } else {
            $comment = '//end interface';
        }//end if

        if (isset($tokens[$stackPtr]['scope_closer']) === false) {
            $error = 'Possible parse error: %s missing opening or closing brace';
            $data  = array($tokens[$stackPtr]['content']);
            $phpcsFile->addWarning($error, $stackPtr, 'MissingBrace', $data);
            return;
        }

        $closingBracket = $tokens[$stackPtr]['scope_closer'];

        if ($closingBracket === null) {
            // Possible inline structure. Other tests will handle it.
            return;
        }

        $error = 'Expected '.$comment;
        if (isset($tokens[($closingBracket + 1)]) === false || $tokens[($closingBracket + 1)]['code'] !== T_COMMENT) {
            $phpcsFile->addError($error, $closingBracket, 'Missing');
            return;
        }

        if (rtrim($tokens[($closingBracket + 1)]['content']) !== $comment) {
            $phpcsFile->addError($error, $closingBracket, 'Incorrect');
            return;
        }

    }//end process()


}//end class

?>
<?php
/**
 * Parses and verifies the variable doc comment.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_Standards_AbstractVariableSniff', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_Standards_AbstractVariableSniff not found');
}

if (class_exists('PHP_CodeSniffer_CommentParser_MemberCommentParser', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_CommentParser_MemberCommentParser not found');
}

/**
 * Parses and verifies the variable doc comment.
 *
 * Verifies that :
 * <ul>
 *  <li>A variable doc comment exists.</li>
 *  <li>Short description ends with a full stop.</li>
 *  <li>There is a blank line after the short description.</li>
 *  <li>There is a blank line between the description and the tags.</li>
 *  <li>Check the order, indentation and content of each tag.</li>
 * </ul>
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

class Squiz_Sniffs_Commenting_VariableCommentSniff extends PHP_CodeSniffer_Standards_AbstractVariableSniff
{

    /**
     * The header comment parser for the current file.
     *
     * @var PHP_CodeSniffer_Comment_Parser_ClassCommentParser
     */
    protected $commentParser = null;


    /**
     * Called to process class member vars.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function processMemberVar(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $this->currentFile = $phpcsFile;
        $tokens            = $phpcsFile->getTokens();
        $commentToken      = array(
                              T_COMMENT,
                              T_DOC_COMMENT,
                             );

        // Extract the var comment docblock.
        $commentEnd = $phpcsFile->findPrevious($commentToken, ($stackPtr - 3));
        if ($commentEnd !== false && $tokens[$commentEnd]['code'] === T_COMMENT) {
            $phpcsFile->addError('You must use "/**" style comments for a variable comment', $stackPtr, 'WrongStyle');
            return;
        } else if ($commentEnd === false || $tokens[$commentEnd]['code'] !== T_DOC_COMMENT) {
            $phpcsFile->addError('Missing variable doc comment', $stackPtr, 'Missing');
            return;
        } else {
            // Make sure the comment we have found belongs to us.
            $commentFor = $phpcsFile->findNext(array(T_VARIABLE, T_CLASS, T_INTERFACE), ($commentEnd + 1));
            if ($commentFor !== $stackPtr) {
                $phpcsFile->addError('Missing variable doc comment', $stackPtr, 'Missing');
                return;
            }
        }

        $commentStart  = ($phpcsFile->findPrevious(T_DOC_COMMENT, ($commentEnd - 1), null, true) + 1);
        $commentString = $phpcsFile->getTokensAsString($commentStart, ($commentEnd - $commentStart + 1));

        // Parse the header comment docblock.
        try {
            $this->commentParser = new PHP_CodeSniffer_CommentParser_MemberCommentParser($commentString, $phpcsFile);
            $this->commentParser->parse();
        } catch (PHP_CodeSniffer_CommentParser_ParserException $e) {
            $line = ($e->getLineWithinComment() + $commentStart);
            $phpcsFile->addError($e->getMessage(), $line, 'ErrorParsing');
            return;
        }

        $comment = $this->commentParser->getComment();
        if (is_null($comment) === true) {
            $error = 'Variable doc comment is empty';
            $phpcsFile->addError($error, $commentStart, 'Empty');
            return;
        }

        // The first line of the comment should just be the /** code.
        $eolPos    = strpos($commentString, $phpcsFile->eolChar);
        $firstLine = substr($commentString, 0, $eolPos);
        if ($firstLine !== '/**') {
            $error = 'The open comment tag must be the only content on the line';
            $phpcsFile->addError($error, $commentStart, 'ContentAfterOpen');
        }

        // Check for a comment description.
        $short = $comment->getShortComment();
        $long  = '';
        if (trim($short) === '') {
            $error = 'Missing short description in variable doc comment';
            $phpcsFile->addError($error, $commentStart, 'MissingShort');
            $newlineCount = 1;
        } else {
            // No extra newline before short description.
            $newlineCount = 0;
            $newlineSpan  = strspn($short, $phpcsFile->eolChar);
            if ($short !== '' && $newlineSpan > 0) {
                $error = 'Extra newline(s) found before variable comment short description';
                $phpcsFile->addError($error, ($commentStart + 1), 'SpacingBeforeShort');
            }

            $newlineCount = (substr_count($short, $phpcsFile->eolChar) + 1);

            // Exactly one blank line between short and long description.
            $long = $comment->getLongComment();
            if (empty($long) === false) {
                $between        = $comment->getWhiteSpaceBetween();
                $newlineBetween = substr_count($between, $phpcsFile->eolChar);
                if ($newlineBetween !== 2) {
                    $error = 'There must be exactly one blank line between descriptions in variable comment';
                    $phpcsFile->addError($error, ($commentStart + $newlineCount + 1), 'SpacingBetween');
                }

                $newlineCount += $newlineBetween;

                $testLong = trim($long);
                if (preg_match('|\p{Lu}|u', $testLong[0]) === 0) {
                    $error = 'Variable comment long description must start with a capital letter';
                    $phpcsFile->addError($error, ($commentStart + $newlineCount), 'LongNotCapital');
                }
            }//end if

            // Short description must be single line and end with a full stop.
            $testShort = trim($short);
            $lastChar  = $testShort[(strlen($testShort) - 1)];
            if (substr_count($testShort, $phpcsFile->eolChar) !== 0) {
                $error = 'Variable comment short description must be on a single line';
                $phpcsFile->addError($error, ($commentStart + 1), 'ShortSingleLine');
            }

            if (preg_match('|\p{Lu}|u', $testShort[0]) === 0) {
                $error = 'Variable comment short description must start with a capital letter';
                $phpcsFile->addError($error, ($commentStart + 1), 'ShortNotCapital');
            }

            if ($lastChar !== '.') {
                $error = 'Variable comment short description must end with a full stop';
                $phpcsFile->addError($error, ($commentStart + 1), 'ShortFullStop');
            }
        }//end if

        // Exactly one blank line before tags.
        $tags = $this->commentParser->getTagOrders();
        if (count($tags) > 1) {
            $newlineSpan = $comment->getNewlineAfter();
            if ($newlineSpan !== 2) {
                $error = 'There must be exactly one blank line before the tags in variable comment';
                if ($long !== '') {
                    $newlineCount += (substr_count($long, $phpcsFile->eolChar) - $newlineSpan + 1);
                }

                $phpcsFile->addError($error, ($commentStart + $newlineCount), 'SpacingBeforeTags');
                $short = rtrim($short, $phpcsFile->eolChar.' ');
            }
        }

        // Check for unknown/deprecated tags.
        $unknownTags = $this->commentParser->getUnknown();
        foreach ($unknownTags as $errorTag) {
            // Unknown tags are not parsed, do not process further.
            $error = '@%s tag is not allowed in variable comment';
            $data  = array($errorTag['tag']);
            $phpcsFile->addWarning($error, ($commentStart + $errorTag['line']), 'TagNotAllowed', $data);
        }

        // Check each tag.
        $this->processVar($commentStart, $commentEnd);
        $this->processSees($commentStart);

        // The last content should be a newline and the content before
        // that should not be blank. If there is more blank space
        // then they have additional blank lines at the end of the comment.
        $words   = $this->commentParser->getWords();
        $lastPos = (count($words) - 1);
        if (trim($words[($lastPos - 1)]) !== ''
            || strpos($words[($lastPos - 1)], $this->currentFile->eolChar) === false
            || trim($words[($lastPos - 2)]) === ''
        ) {
            $error = 'Additional blank lines found at end of variable comment';
            $this->currentFile->addError($error, $commentEnd, 'SpacingAfter');
        }

    }//end processMemberVar()


    /**
     * Process the var tag.
     *
     * @param int $commentStart The position in the stack where the comment started.
     * @param int $commentEnd   The position in the stack where the comment ended.
     *
     * @return void
     */
    protected function processVar($commentStart, $commentEnd)
    {
        $var = $this->commentParser->getVar();

        if ($var !== null) {
            $errorPos = ($commentStart + $var->getLine());
            $index    = array_keys($this->commentParser->getTagOrders(), 'var');

            if (count($index) > 1) {
                $error = 'Only 1 @var tag is allowed in variable comment';
                $this->currentFile->addError($error, $errorPos, 'DuplicateVar');
                return;
            }

            if ($index[0] !== 1) {
                $error = 'The @var tag must be the first tag in a variable comment';
                $this->currentFile->addError($error, $errorPos, 'VarOrder');
            }

            $content = $var->getContent();
            if (empty($content) === true) {
                $error = 'Var type missing for @var tag in variable comment';
                $this->currentFile->addError($error, $errorPos, 'MissingVarType');
                return;
            } else {
                $suggestedType = PHP_CodeSniffer::suggestType($content);
                if ($content !== $suggestedType) {
                    $error = 'Expected "%s"; found "%s" for @var tag in variable comment';
                    $data  = array(
                              $suggestedType,
                              $content,
                             );
                    $this->currentFile->addError($error, $errorPos, 'IncorrectVarType', $data);
                }
            }

            $spacing = substr_count($var->getWhitespaceBeforeContent(), ' ');
            if ($spacing !== 1) {
                $error = '@var tag indented incorrectly; expected 1 space but found %s';
                $data  = array($spacing);
                $this->currentFile->addError($error, $errorPos, 'VarIndent', $data);
            }
        } else {
            $error = 'Missing @var tag in variable comment';
            $this->currentFile->addError($error, $commentEnd, 'MissingVar');
        }//end if

    }//end processVar()


    /**
     * Process the see tags.
     *
     * @param int $commentStart The position in the stack where the comment started.
     *
     * @return void
     */
    protected function processSees($commentStart)
    {
        $sees = $this->commentParser->getSees();
        if (empty($sees) === false) {
            foreach ($sees as $see) {
                $errorPos = ($commentStart + $see->getLine());
                $content  = $see->getContent();
                if (empty($content) === true) {
                    $error = 'Content missing for @see tag in variable comment';
                    $this->currentFile->addError($error, $errorPos, 'EmptySees');
                    continue;
                }

                $spacing = substr_count($see->getWhitespaceBeforeContent(), ' ');
                if ($spacing !== 1) {
                    $error = '@see tag indented incorrectly; expected 1 spaces but found %s';
                    $data  = array($spacing);
                    $this->currentFile->addError($error, $errorPos, 'SeesIndent', $data);
                }
            }
        }

    }//end processSees()


    /**
     * Called to process a normal variable.
     *
     * Not required for this sniff.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The PHP_CodeSniffer file where this token was found.
     * @param int                  $stackPtr  The position where the double quoted
     *                                        string was found.
     *
     * @return void
     */
    protected function processVariable(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {

    }//end processVariable()


    /**
     * Called to process variables found in double quoted strings.
     *
     * Not required for this sniff.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The PHP_CodeSniffer file where this token was found.
     * @param int                  $stackPtr  The position where the double quoted
     *                                        string was found.
     *
     * @return void
     */
    protected function processVariableInString(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {

    }//end processVariableInString()


}//end class
?>
<?php
/**
 * Squiz_Sniffs_ControlStructures_LongConditionClosingCommentSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_ControlStructures_LongConditionClosingCommentSniff.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Commenting_LongConditionClosingCommentSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                  );

    /**
     * The openers that we are interested in.
     *
     * @var array(int)
     */
    private static $_openers = array(
                                T_SWITCH,
                                T_IF,
                                T_FOR,
                                T_FOREACH,
                                T_WHILE,
                                T_TRY,
                                T_CASE,
                               );

    /**
     * The length that a code block must be before
     * requiring a closing comment.
     *
     * @var int
     */
    protected $lineLimit = 20;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_CLOSE_CURLY_BRACKET);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if (isset($tokens[$stackPtr]['scope_condition']) === false) {
            // No scope condition. It is a function closer.
            return;
        }

        $startCondition = $tokens[$tokens[$stackPtr]['scope_condition']];
        $startBrace     = $tokens[$tokens[$stackPtr]['scope_opener']];
        $endBrace       = $tokens[$stackPtr];

        // We are only interested in some code blocks.
        if (in_array($startCondition['code'], self::$_openers) === false) {
            return;
        }

        if ($startCondition['code'] === T_IF) {
            // If this is actually and ELSE IF, skip it as the brace
            // will be checked by the original IF.
            $else = $phpcsFile->findPrevious(T_WHITESPACE, ($tokens[$stackPtr]['scope_condition'] - 1), null, true);
            if ($tokens[$else]['code'] === T_ELSE) {
                return;
            }

            // IF statements that have an ELSE block need to use
            // "end if" rather than "end else" or "end elseif".
            do {
                $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
                if ($tokens[$nextToken]['code'] === T_ELSE || $tokens[$nextToken]['code'] === T_ELSEIF) {
                    // Check for ELSE IF (2 tokens) as opposed to ELSEIF (1 token).
                    if ($tokens[$nextToken]['code'] === T_ELSE
                        && isset($tokens[$nextToken]['scope_closer']) === false
                    ) {
                        $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($nextToken + 1), null, true);
                        if ($tokens[$nextToken]['code'] !== T_IF
                            || isset($tokens[$nextToken]['scope_closer']) === false
                        ) {
                            // Not an ELSE IF or is an inline ELSE IF.
                            break;
                        }
                    }

                    // The end brace becomes the ELSE's end brace.
                    $stackPtr = $tokens[$nextToken]['scope_closer'];
                    $endBrace = $tokens[$stackPtr];
                } else {
                    break;
                }
            } while (isset($tokens[$nextToken]['scope_closer']) === true);
        }//end if

        if ($startCondition['code'] === T_TRY) {
            // TRY statements need to check until the end of all CATCH statements.
            do {
                $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
                if ($tokens[$nextToken]['code'] === T_CATCH) {
                    // The end brace becomes the CATCH's end brace.
                    $stackPtr = $tokens[$nextToken]['scope_closer'];
                    $endBrace = $tokens[$stackPtr];
                } else {
                    break;
                }
            } while (isset($tokens[$nextToken]['scope_closer']) === true);
        }

        $lineDifference = ($endBrace['line'] - $startBrace['line']);

        $expected = '//end '.$startCondition['content'];
        $comment  = $phpcsFile->findNext(array(T_COMMENT), $stackPtr, null, false);

        if (($comment === false) || ($tokens[$comment]['line'] !== $endBrace['line'])) {
            if ($lineDifference >= $this->lineLimit) {
                $error = 'End comment for long condition not found; expected "%s"';
                $data  = array($expected);
                $phpcsFile->addError($error, $stackPtr, 'Missing', $data);
            }

            return;
        }

        if (($comment - $stackPtr) !== 1) {
            $error = 'Space found before closing comment; expected "%s"';
            $data  = array($expected);
            $phpcsFile->addError($error, $stackPtr, 'SpacingBefore', $data);
        }

        if (trim($tokens[$comment]['content']) !== $expected) {
            $found = trim($tokens[$comment]['content']);
            $error = 'Incorrect closing comment; expected "%s" but found "%s"';
            $data  = array(
                      $expected,
                      $found,
                     );
            $phpcsFile->addError($error, $stackPtr, 'Invalid', $data);
            return;
        }

    }//end process()


}//end class


?>
<?php
/**
 * Parses and verifies the doc comments for functions.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_CommentParser_FunctionCommentParser', true) === false) {
    $error = 'Class PHP_CodeSniffer_CommentParser_FunctionCommentParser not found';
    throw new PHP_CodeSniffer_Exception($error);
}

/**
 * Parses and verifies the doc comments for functions.
 *
 * Verifies that :
 * <ul>
 *  <li>A comment exists</li>
 *  <li>There is a blank newline after the short description</li>
 *  <li>There is a blank newline between the long and short description</li>
 *  <li>There is a blank newline between the long description and tags</li>
 *  <li>Parameter names represent those in the method</li>
 *  <li>Parameter comments are in the correct order</li>
 *  <li>Parameter comments are complete</li>
 *  <li>A type hint is provided for array and custom class</li>
 *  <li>Type hint matches the actual variable/class type</li>
 *  <li>A blank line is present before the first and after the last parameter</li>
 *  <li>A return type exists</li>
 *  <li>Any throw tag must have a comment</li>
 *  <li>The tag order and indentation are correct</li>
 * </ul>
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Commenting_FunctionCommentSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * The name of the method that we are currently processing.
     *
     * @var string
     */
    private $_methodName = '';

    /**
     * The position in the stack where the function token was found.
     *
     * @var int
     */
    private $_functionToken = null;

    /**
     * The position in the stack where the class token was found.
     *
     * @var int
     */
    private $_classToken = null;

    /**
     * The index of the current tag we are processing.
     *
     * @var int
     */
    private $_tagIndex = 0;

    /**
     * The function comment parser for the current method.
     *
     * @var PHP_CodeSniffer_Comment_Parser_FunctionCommentParser
     */
    protected $commentParser = null;

    /**
     * The current PHP_CodeSniffer_File object we are processing.
     *
     * @var PHP_CodeSniffer_File
     */
    protected $currentFile = null;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_FUNCTION);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $this->currentFile = $phpcsFile;

        $tokens = $phpcsFile->getTokens();

        $find = array(
                 T_COMMENT,
                 T_DOC_COMMENT,
                 T_CLASS,
                 T_FUNCTION,
                 T_OPEN_TAG,
                );

        $commentEnd = $phpcsFile->findPrevious($find, ($stackPtr - 1));

        if ($commentEnd === false) {
            return;
        }

        // If the token that we found was a class or a function, then this
        // function has no doc comment.
        $code = $tokens[$commentEnd]['code'];

        if ($code === T_COMMENT) {
            // The function might actually be missing a comment, and this last comment
            // found is just commenting a bit of code on a line. So if it is not the
            // only thing on the line, assume we found nothing.
            $prevContent = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $commentEnd);
            if ($tokens[$commentEnd]['line'] === $tokens[$commentEnd]['line']) {
                $error = 'Missing function doc comment';
                $phpcsFile->addError($error, $stackPtr, 'Missing');
            } else {
                $error = 'You must use "/**" style comments for a function comment';
                $phpcsFile->addError($error, $stackPtr, 'WrongStyle');
            }
            return;
        } else if ($code !== T_DOC_COMMENT) {
            $error = 'Missing function doc comment';
            $phpcsFile->addError($error, $stackPtr, 'Missing');
            return;
        } else if (trim($tokens[$commentEnd]['content']) !== '*/') {
            $error = 'You must use "*/" to end a function comment; found "%s"';
            $phpcsFile->addError($error, $commentEnd, 'WrongEnd', array(trim($tokens[$commentEnd]['content'])));
            return;
        }

        // If there is any code between the function keyword and the doc block
        // then the doc block is not for us.
        $ignore    = PHP_CodeSniffer_Tokens::$scopeModifiers;
        $ignore[]  = T_STATIC;
        $ignore[]  = T_WHITESPACE;
        $ignore[]  = T_ABSTRACT;
        $ignore[]  = T_FINAL;
        $prevToken = $phpcsFile->findPrevious($ignore, ($stackPtr - 1), null, true);
        if ($prevToken !== $commentEnd) {
            $phpcsFile->addError('Missing function doc comment', $stackPtr, 'Missing');
            return;
        }

        $this->_functionToken = $stackPtr;

        $this->_classToken = null;
        foreach ($tokens[$stackPtr]['conditions'] as $condPtr => $condition) {
            if ($condition === T_CLASS || $condition === T_INTERFACE) {
                $this->_classToken = $condPtr;
                break;
            }
        }

        // Find the first doc comment.
        $commentStart      = ($phpcsFile->findPrevious(T_DOC_COMMENT, ($commentEnd - 1), null, true) + 1);
        $commentString     = $phpcsFile->getTokensAsString($commentStart, ($commentEnd - $commentStart + 1));
        $this->_methodName = $phpcsFile->getDeclarationName($stackPtr);

        try {
            $this->commentParser = new PHP_CodeSniffer_CommentParser_FunctionCommentParser($commentString, $phpcsFile);
            $this->commentParser->parse();
        } catch (PHP_CodeSniffer_CommentParser_ParserException $e) {
            $line = ($e->getLineWithinComment() + $commentStart);
            $phpcsFile->addError($e->getMessage(), $line, 'FailedParse');
            return;
        }

        $comment = $this->commentParser->getComment();
        if (is_null($comment) === true) {
            $error = 'Function doc comment is empty';
            $phpcsFile->addError($error, $commentStart, 'Empty');
            return;
        }

        // The first line of the comment should just be the /** code.
        $eolPos    = strpos($commentString, $phpcsFile->eolChar);
        $firstLine = substr($commentString, 0, $eolPos);
        if ($firstLine !== '/**') {
            $error = 'The open comment tag must be the only content on the line';
            $phpcsFile->addError($error, $commentStart, 'ContentAfterOpen');
        }

        $this->processParams($commentStart, $commentEnd);
        $this->processSees($commentStart);
        $this->processReturn($commentStart, $commentEnd);
        $this->processThrows($commentStart);

        // Check for a comment description.
        $short = $comment->getShortComment();
        if (trim($short) === '') {
            $error = 'Missing short description in function doc comment';
            $phpcsFile->addError($error, $commentStart, 'MissingShort');
            return;
        }

        // No extra newline before short description.
        $newlineCount = 0;
        $newlineSpan  = strspn($short, $phpcsFile->eolChar);
        if ($short !== '' && $newlineSpan > 0) {
            $error = 'Extra newline(s) found before function comment short description';
            $phpcsFile->addError($error, ($commentStart + 1), 'SpacingBeforeShort');
        }

        $newlineCount = (substr_count($short, $phpcsFile->eolChar) + 1);

        // Exactly one blank line between short and long description.
        $long = $comment->getLongComment();
        if (empty($long) === false) {
            $between        = $comment->getWhiteSpaceBetween();
            $newlineBetween = substr_count($between, $phpcsFile->eolChar);
            if ($newlineBetween !== 2) {
                $error = 'There must be exactly one blank line between descriptions in function comment';
                $phpcsFile->addError($error, ($commentStart + $newlineCount + 1), 'SpacingBetween');
            }

            $newlineCount += $newlineBetween;

            $testLong = trim($long);
            if (preg_match('|\p{Lu}|u', $testLong[0]) === 0) {
                $error = 'Function comment long description must start with a capital letter';
                $phpcsFile->addError($error, ($commentStart + $newlineCount), 'LongNotCapital');
            }
        }//end if

        // Exactly one blank line before tags.
        $params = $this->commentParser->getTagOrders();
        if (count($params) > 1) {
            $newlineSpan = $comment->getNewlineAfter();
            if ($newlineSpan !== 2) {
                $error = 'There must be exactly one blank line before the tags in function comment';
                if ($long !== '') {
                    $newlineCount += (substr_count($long, $phpcsFile->eolChar) - $newlineSpan + 1);
                }

                $phpcsFile->addError($error, ($commentStart + $newlineCount), 'SpacingBeforeTags');
                $short = rtrim($short, $phpcsFile->eolChar.' ');
            }
        }

        // Short description must be single line and end with a full stop.
        $testShort = trim($short);
        $lastChar  = $testShort[(strlen($testShort) - 1)];
        if (substr_count($testShort, $phpcsFile->eolChar) !== 0) {
            $error = 'Function comment short description must be on a single line';
            $phpcsFile->addError($error, ($commentStart + 1), 'ShortSingleLine');
        }

        if (preg_match('|\p{Lu}|u', $testShort[0]) === 0) {
            $error = 'Function comment short description must start with a capital letter';
            $phpcsFile->addError($error, ($commentStart + 1), 'ShortNotCapital');
        }

        if ($lastChar !== '.') {
            $error = 'Function comment short description must end with a full stop';
            $phpcsFile->addError($error, ($commentStart + 1), 'ShortFullStop');
        }

        // Check for unknown/deprecated tags.
        $this->processUnknownTags($commentStart, $commentEnd);

        // The last content should be a newline and the content before
        // that should not be blank. If there is more blank space
        // then they have additional blank lines at the end of the comment.
        $words   = $this->commentParser->getWords();
        $lastPos = (count($words) - 1);
        if (trim($words[($lastPos - 1)]) !== ''
            || strpos($words[($lastPos - 1)], $this->currentFile->eolChar) === false
            || trim($words[($lastPos - 2)]) === ''
        ) {
            $error = 'Additional blank lines found at end of function comment';
            $this->currentFile->addError($error, $commentEnd, 'SpacingAfter');
        }

    }//end process()


    /**
     * Process the see tags.
     *
     * @param int $commentStart The position in the stack where the comment started.
     *
     * @return void
     */
    protected function processSees($commentStart)
    {
        $sees = $this->commentParser->getSees();
        if (empty($sees) === false) {
            $tagOrder = $this->commentParser->getTagOrders();
            $index    = array_keys($this->commentParser->getTagOrders(), 'see');
            foreach ($sees as $i => $see) {
                $errorPos = ($commentStart + $see->getLine());
                $since    = array_keys($tagOrder, 'since');
                if (count($since) === 1 && $this->_tagIndex !== 0) {
                    $this->_tagIndex++;
                    if ($index[$i] !== $this->_tagIndex) {
                        $error = 'The @see tag is in the wrong order; the tag precedes @return';
                        $this->currentFile->addError($error, $errorPos, 'SeeOrder');
                    }
                }

                $content = $see->getContent();
                if (empty($content) === true) {
                    $error = 'Content missing for @see tag in function comment';
                    $this->currentFile->addError($error, $errorPos, 'EmptySee');
                    continue;
                }

                $spacing = substr_count($see->getWhitespaceBeforeContent(), ' ');
                if ($spacing !== 4) {
                    $error = '@see tag indented incorrectly; expected 4 spaces but found %s';
                    $data  = array($spacing);
                    $this->currentFile->addError($error, $errorPos, 'SeeIndent', $data);
                }
            }//end foreach
        }//end if

    }//end processSees()


    /**
     * Process the return comment of this function comment.
     *
     * @param int $commentStart The position in the stack where the comment started.
     * @param int $commentEnd   The position in the stack where the comment ended.
     *
     * @return void
     */
    protected function processReturn($commentStart, $commentEnd)
    {
        // Skip constructor and destructor.
        $className = '';
        if ($this->_classToken !== null) {
            $className = $this->currentFile->getDeclarationName($this->_classToken);
            $className = strtolower(ltrim($className, '_'));
        }

        $methodName      = strtolower(ltrim($this->_methodName, '_'));
        $isSpecialMethod = ($this->_methodName === '__construct' || $this->_methodName === '__destruct');
        $return          = $this->commentParser->getReturn();

        if ($isSpecialMethod === false && $methodName !== $className) {
            if ($return !== null) {
                $tagOrder = $this->commentParser->getTagOrders();
                $index    = array_keys($tagOrder, 'return');
                $errorPos = ($commentStart + $return->getLine());
                $content  = trim($return->getRawContent());

                if (count($index) > 1) {
                    $error = 'Only 1 @return tag is allowed in function comment';
                    $this->currentFile->addError($error, $errorPos, 'DuplicateReturn');
                    return;
                }

                $since = array_keys($tagOrder, 'since');
                if (count($since) === 1 && $this->_tagIndex !== 0) {
                    $this->_tagIndex++;
                    if ($index[0] !== $this->_tagIndex) {
                        $error = 'The @return tag is in the wrong order; the tag follows @see (if used)';
                        $this->currentFile->addError($error, $errorPos, 'ReturnOrder');
                    }
                }

                if (empty($content) === true) {
                    $error = 'Return type missing for @return tag in function comment';
                    $this->currentFile->addError($error, $errorPos, 'MissingReturnType');
                } else {
                    // Check return type (can be multiple, separated by '|').
                    $typeNames      = explode('|', $content);
                    $suggestedNames = array();
                    foreach ($typeNames as $i => $typeName) {
                        $suggestedName = PHP_CodeSniffer::suggestType($typeName);
                        if (in_array($suggestedName, $suggestedNames) === false) {
                            $suggestedNames[] = $suggestedName;
                        }
                    }

                    $suggestedType = implode('|', $suggestedNames);
                    if ($content !== $suggestedType) {
                        $error = 'Function return type "%s" is invalid';
                        $data  = array($content);
                        $this->currentFile->addError($error, $errorPos, 'InvalidReturn', $data);
                    }

                    $tokens = $this->currentFile->getTokens();

                    // If the return type is void, make sure there is
                    // no return statement in the function.
                    if ($content === 'void') {
                        if (isset($tokens[$this->_functionToken]['scope_closer']) === true) {
                            $endToken = $tokens[$this->_functionToken]['scope_closer'];

                            $tokens = $this->currentFile->getTokens();
                            for ($returnToken = $this->_functionToken; $returnToken < $endToken; $returnToken++) {
                                if ($tokens[$returnToken]['code'] === T_CLOSURE) {
                                    $returnToken = $tokens[$returnToken]['scope_closer'];
                                    continue;
                                }

                                if ($tokens[$returnToken]['code'] === T_RETURN) {
                                    break;
                                }
                            }

                            if ($returnToken !== $endToken) {
                                // If the function is not returning anything, just
                                // exiting, then there is no problem.
                                $semicolon = $this->currentFile->findNext(T_WHITESPACE, ($returnToken + 1), null, true);
                                if ($tokens[$semicolon]['code'] !== T_SEMICOLON) {
                                    $error = 'Function return type is void, but function contains return statement';
                                    $this->currentFile->addError($error, $errorPos, 'InvalidReturnVoid');
                                }
                            }
                        }
                    } else if ($content !== 'mixed') {
                        // If return type is not void, there needs to be a
                        // returns statement somewhere in the function that
                        // returns something.
                        if (isset($tokens[$this->_functionToken]['scope_closer']) === true) {
                            $endToken    = $tokens[$this->_functionToken]['scope_closer'];
                            $returnToken = $this->currentFile->findNext(T_RETURN, $this->_functionToken, $endToken);
                            if ($returnToken === false) {
                                $error = 'Function return type is not void, but function has no return statement';
                                $this->currentFile->addError($error, $errorPos, 'InvalidNoReturn');
                            } else {
                                $semicolon = $this->currentFile->findNext(T_WHITESPACE, ($returnToken + 1), null, true);
                                if ($tokens[$semicolon]['code'] === T_SEMICOLON) {
                                    $error = 'Function return type is not void, but function is returning void here';
                                    $this->currentFile->addError($error, $returnToken, 'InvalidReturnNotVoid');
                                }
                            }
                        }
                    }//end if

                    $spacing = substr_count($return->getWhitespaceBeforeValue(), ' ');
                    if ($spacing !== 1) {
                        $error = '@return tag indented incorrectly; expected 1 space but found %s';
                        $data  = array($spacing);
                        $this->currentFile->addError($error, $errorPos, 'ReturnIndent', $data);
                    }
                }//end if
            } else {
                $error = 'Missing @return tag in function comment';
                $this->currentFile->addError($error, $commentEnd, 'MissingReturn');
            }//end if

        } else {
            // No return tag for constructor and destructor.
            if ($return !== null) {
                $errorPos = ($commentStart + $return->getLine());
                $error    = '@return tag is not required for constructor and destructor';
                $this->currentFile->addError($error, $errorPos, 'ReturnNotRequired');
            }
        }//end if

    }//end processReturn()


    /**
     * Process any throw tags that this function comment has.
     *
     * @param int $commentStart The position in the stack where the comment started.
     *
     * @return void
     */
    protected function processThrows($commentStart)
    {
        if (count($this->commentParser->getThrows()) === 0) {
            return;
        }

        $tagOrder = $this->commentParser->getTagOrders();
        $index    = array_keys($this->commentParser->getTagOrders(), 'throws');

        foreach ($this->commentParser->getThrows() as $i => $throw) {
            $exception = $throw->getValue();
            $content   = trim($throw->getComment());
            $errorPos  = ($commentStart + $throw->getLine());
            if (empty($exception) === true) {
                $error = 'Exception type and comment missing for @throws tag in function comment';
                $this->currentFile->addError($error, $errorPos, 'InvalidThrows');
            } else if (empty($content) === true) {
                $error = 'Comment missing for @throws tag in function comment';
                $this->currentFile->addError($error, $errorPos, 'EmptyThrows');
            } else {
                // Starts with a capital letter and ends with a fullstop.
                $firstChar = $content{0};
                if (strtoupper($firstChar) !== $firstChar) {
                    $error = '@throws tag comment must start with a capital letter';
                    $this->currentFile->addError($error, $errorPos, 'ThrowsNotCapital');
                }

                $lastChar = $content[(strlen($content) - 1)];
                if ($lastChar !== '.') {
                    $error = '@throws tag comment must end with a full stop';
                    $this->currentFile->addError($error, $errorPos, 'ThrowsNoFullStop');
                }
            }

            $since = array_keys($tagOrder, 'since');
            if (count($since) === 1 && $this->_tagIndex !== 0) {
                $this->_tagIndex++;
                if ($index[$i] !== $this->_tagIndex) {
                    $error = 'The @throws tag is in the wrong order; the tag follows @return';
                    $this->currentFile->addError($error, $errorPos, 'ThrowsOrder');
                }
            }
        }//end foreach

    }//end processThrows()


    /**
     * Process the function parameter comments.
     *
     * @param int $commentStart The position in the stack where
     *                          the comment started.
     * @param int $commentEnd   The position in the stack where
     *                          the comment ended.
     *
     * @return void
     */
    protected function processParams($commentStart, $commentEnd)
    {
        $realParams  = $this->currentFile->getMethodParameters($this->_functionToken);
        $params      = $this->commentParser->getParams();
        $foundParams = array();

        if (empty($params) === false) {

            if (substr_count($params[(count($params) - 1)]->getWhitespaceAfter(), $this->currentFile->eolChar) !== 2) {
                $error    = 'Last parameter comment requires a blank newline after it';
                $errorPos = ($params[(count($params) - 1)]->getLine() + $commentStart);
                $this->currentFile->addError($error, $errorPos, 'SpacingAfterParams');
            }

            // Parameters must appear immediately after the comment.
            if ($params[0]->getOrder() !== 2) {
                $error    = 'Parameters must appear immediately after the comment';
                $errorPos = ($params[0]->getLine() + $commentStart);
                $this->currentFile->addError($error, $errorPos, 'SpacingBeforeParams');
            }

            $previousParam      = null;
            $spaceBeforeVar     = 10000;
            $spaceBeforeComment = 10000;
            $longestType        = 0;
            $longestVar         = 0;

            foreach ($params as $param) {

                $paramComment = trim($param->getComment());
                $errorPos     = ($param->getLine() + $commentStart);

                // Make sure that there is only one space before the var type.
                if ($param->getWhitespaceBeforeType() !== ' ') {
                    $error = 'Expected 1 space before variable type';
                    $this->currentFile->addError($error, $errorPos, 'SpacingBeforeParamType');
                }

                $spaceCount = substr_count($param->getWhitespaceBeforeVarName(), ' ');
                if ($spaceCount < $spaceBeforeVar) {
                    $spaceBeforeVar = $spaceCount;
                    $longestType    = $errorPos;
                }

                $spaceCount = substr_count($param->getWhitespaceBeforeComment(), ' ');

                if ($spaceCount < $spaceBeforeComment && $paramComment !== '') {
                    $spaceBeforeComment = $spaceCount;
                    $longestVar         = $errorPos;
                }

                // Make sure they are in the correct order, and have the correct name.
                $pos       = $param->getPosition();
                $paramName = ($param->getVarName() !== '') ? $param->getVarName() : '[ UNKNOWN ]';

                if ($previousParam !== null) {
                    $previousName = ($previousParam->getVarName() !== '') ? $previousParam->getVarName() : 'UNKNOWN';

                    // Check to see if the parameters align properly.
                    if ($param->alignsVariableWith($previousParam) === false) {
                        $error = 'The variable names for parameters %s (%s) and %s (%s) do not align';
                        $data  = array(
                                  $previousName,
                                  ($pos - 1),
                                  $paramName,
                                  $pos,
                                 );
                        $this->currentFile->addError($error, $errorPos, 'ParameterNamesNotAligned', $data);
                    }

                    if ($param->alignsCommentWith($previousParam) === false) {
                        $error = 'The comments for parameters %s (%s) and %s (%s) do not align';
                        $data  = array(
                                  $previousName,
                                  ($pos - 1),
                                  $paramName,
                                  $pos,
                                 );
                        $this->currentFile->addError($error, $errorPos, 'ParameterCommentsNotAligned', $data);
                    }
                }

                // Variable must be one of the supported standard type.
                $typeNames = explode('|', $param->getType());
                foreach ($typeNames as $typeName) {
                    $suggestedName = PHP_CodeSniffer::suggestType($typeName);
                    if ($typeName !== $suggestedName) {
                        $error = 'Expected "%s"; found "%s" for %s at position %s';
                        $data  = array(
                                  $suggestedName,
                                  $typeName,
                                  $paramName,
                                  $pos,
                                 );
                        $this->currentFile->addError($error, $errorPos, 'IncorrectParamVarName', $data);
                    } else if (count($typeNames) === 1) {
                        // Check type hint for array and custom type.
                        $suggestedTypeHint = '';
                        if (strpos($suggestedName, 'array') !== false) {
                            $suggestedTypeHint = 'array';
                        } else if (strpos($suggestedName, 'callable') !== false) {
                            $suggestedTypeHint = 'callable';
                        } else if (in_array($typeName, PHP_CodeSniffer::$allowedTypes) === false) {
                            $suggestedTypeHint = $suggestedName;
                        }

                        if ($suggestedTypeHint !== '' && isset($realParams[($pos - 1)]) === true) {
                            $typeHint = $realParams[($pos - 1)]['type_hint'];
                            if ($typeHint === '') {
                                $error = 'Type hint "%s" missing for %s at position %s';
                                $data  = array(
                                          $suggestedTypeHint,
                                          $paramName,
                                          $pos,
                                         );
                                $this->currentFile->addError($error, ($commentEnd + 2), 'TypeHintMissing', $data);
                            } else if ($typeHint !== $suggestedTypeHint) {
                                $error = 'Expected type hint "%s"; found "%s" for %s at position %s';
                                $data  = array(
                                          $suggestedTypeHint,
                                          $typeHint,
                                          $paramName,
                                          $pos,
                                         );
                                $this->currentFile->addError($error, ($commentEnd + 2), 'IncorrectTypeHint', $data);
                            }
                        } else if ($suggestedTypeHint === '' && isset($realParams[($pos - 1)]) === true) {
                            $typeHint = $realParams[($pos - 1)]['type_hint'];
                            if ($typeHint !== '') {
                                $error = 'Unknown type hint "%s" found for %s at position %s';
                                $data  = array(
                                          $typeHint,
                                          $paramName,
                                          $pos,
                                         );
                                $this->currentFile->addError($error, ($commentEnd + 2), 'InvalidTypeHint', $data);
                            }
                        }
                    }//end if
                }//end foreach

                // Make sure the names of the parameter comment matches the
                // actual parameter.
                if (isset($realParams[($pos - 1)]) === true) {
                    $realName      = $realParams[($pos - 1)]['name'];
                    $foundParams[] = $realName;

                    // Append ampersand to name if passing by reference.
                    if ($realParams[($pos - 1)]['pass_by_reference'] === true) {
                        $realName = '&'.$realName;
                    }

                    if ($realName !== $paramName) {
                        $code = 'ParamNameNoMatch';
                        $data = array(
                                 $paramName,
                                 $realName,
                                 $pos,
                                );

                        $error  = 'Doc comment for var %s does not match ';
                        if (strtolower($paramName) === strtolower($realName)) {
                            $error .= 'case of ';
                            $code   = 'ParamNameNoCaseMatch';
                        }

                        $error .= 'actual variable name %s at position %s';

                        $this->currentFile->addError($error, $errorPos, $code, $data);
                    }
                } else if (substr($paramName, -4) !== ',...') {
                    // We must have an extra parameter comment.
                    $error = 'Superfluous doc comment at position '.$pos;
                    $this->currentFile->addError($error, $errorPos, 'ExtraParamComment');
                }

                if ($param->getVarName() === '') {
                    $error = 'Missing parameter name at position '.$pos;
                     $this->currentFile->addError($error, $errorPos, 'MissingParamName');
                }

                if ($param->getType() === '') {
                    $error = 'Missing type at position '.$pos;
                    $this->currentFile->addError($error, $errorPos, 'MissingParamType');
                }

                if ($paramComment === '') {
                    $error = 'Missing comment for param "%s" at position %s';
                    $data  = array(
                              $paramName,
                              $pos,
                             );
                    $this->currentFile->addError($error, $errorPos, 'MissingParamComment', $data);
                } else {
                    // Param comments must start with a capital letter and
                    // end with the full stop.
                    $firstChar = $paramComment{0};
                    if (preg_match('|\p{Lu}|u', $firstChar) === 0) {
                        $error = 'Param comment must start with a capital letter';
                        $this->currentFile->addError($error, $errorPos, 'ParamCommentNotCapital');
                    }

                    $lastChar = $paramComment[(strlen($paramComment) - 1)];
                    if ($lastChar !== '.') {
                        $error = 'Param comment must end with a full stop';
                        $this->currentFile->addError($error, $errorPos, 'ParamCommentFullStop');
                    }
                }

                $previousParam = $param;

            }//end foreach

            if ($spaceBeforeVar !== 1 && $spaceBeforeVar !== 10000 && $spaceBeforeComment !== 10000) {
                $error = 'Expected 1 space after the longest type';
                $this->currentFile->addError($error, $longestType, 'SpacingAfterLongType');
            }

            if ($spaceBeforeComment !== 1 && $spaceBeforeComment !== 10000) {
                $error = 'Expected 1 space after the longest variable name';
                $this->currentFile->addError($error, $longestVar, 'SpacingAfterLongName');
            }

        }//end if

        $realNames = array();
        foreach ($realParams as $realParam) {
            $realNames[] = $realParam['name'];
        }

        // Report missing comments.
        $diff = array_diff($realNames, $foundParams);
        foreach ($diff as $neededParam) {
            if (count($params) !== 0) {
                $errorPos = ($params[(count($params) - 1)]->getLine() + $commentStart);
            } else {
                $errorPos = $commentStart;
            }

            $error = 'Doc comment for "%s" missing';
            $data  = array($neededParam);
            $this->currentFile->addError($error, $errorPos, 'MissingParamTag', $data);
        }

    }//end processParams()


    /**
     * Process a list of unknown tags.
     *
     * @param int $commentStart The position in the stack where the comment started.
     * @param int $commentEnd   The position in the stack where the comment ended.
     *
     * @return void
     */
    protected function processUnknownTags($commentStart, $commentEnd)
    {

    }//end processUnknownTags


}//end class

?>
<?php
/**
 * Squiz_Sniffs_Commenting_BlockCommentSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Commenting_BlockCommentSniff.
 *
 * Verifies that block comments are used appropriately.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Commenting_BlockCommentSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_COMMENT,
                T_DOC_COMMENT,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The current file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // If its an inline comment return.
        if (substr($tokens[$stackPtr]['content'], 0, 2) !== '/*') {
            return;
        }

        // If this is a function/class/interface doc block comment, skip it.
        // We are only interested in inline doc block comments.
        if ($tokens[$stackPtr]['code'] === T_DOC_COMMENT) {
            $nextToken = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr + 1), null, true);
            $ignore    = array(
                          T_CLASS,
                          T_INTERFACE,
                          T_TRAIT,
                          T_FUNCTION,
                          T_PUBLIC,
                          T_PRIVATE,
                          T_FINAL,
                          T_PROTECTED,
                          T_STATIC,
                          T_ABSTRACT,
                          T_CONST,
                         );
            if (in_array($tokens[$nextToken]['code'], $ignore) === true) {
                return;
            }

            $prevToken = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr - 1), null, true);
            if ($tokens[$prevToken]['code'] === T_OPEN_TAG) {
                return;
            }
        }//end if

        $commentLines = array($stackPtr);
        $nextComment  = $stackPtr;
        $lastLine     = $tokens[$stackPtr]['line'];

        // Construct the comment into an array.
        while (($nextComment = $phpcsFile->findNext($tokens[$stackPtr]['code'], ($nextComment + 1), null, false)) !== false) {
            if (($tokens[$nextComment]['line'] - 1) !== $lastLine) {
                // Not part of the block.
                break;
            }

            $lastLine       = $tokens[$nextComment]['line'];
            $commentLines[] = $nextComment;
        }

        if (count($commentLines) <= 2) {
            // Small comment. Can't be right.
            if (count($commentLines) === 1) {
                $error = 'Single line block comment not allowed; use inline ("// text") comment instead';
                $phpcsFile->addError($error, $stackPtr, 'SingleLine');
                return;
            }

            if (trim($tokens[$commentLines[1]]['content']) === '*/') {
                if (trim($tokens[$stackPtr]['content']) === '/*') {
                    $error = 'Empty block comment not allowed';
                    $phpcsFile->addError($error, $stackPtr, 'Empty');
                    return;
                }
            }
        }

        $content = trim($tokens[$stackPtr]['content']);
        if ($content !== '/*' && $content !== '/**') {
            $error = 'Block comment text must start on a new line';
            $phpcsFile->addError($error, $stackPtr, 'NoNewLine');
            return;
        }

        $starColumn = ($tokens[$stackPtr]['column'] + 3);

        // Make sure first line isn't blank.
        if (trim($tokens[$commentLines[1]]['content']) === '') {
            $error = 'Empty line not allowed at start of comment';
            $phpcsFile->addError($error, $commentLines[1], 'HasEmptyLine');
        } else {
            // Check indentation of first line.
            $content      = $tokens[$commentLines[1]]['content'];
            $commentText  = ltrim($content);
            $leadingSpace = (strlen($content) - strlen($commentText));
            if ($leadingSpace !== $starColumn) {
                $expected  = $starColumn;
                $expected .= ($starColumn === 1) ? ' space' : ' spaces';
                $data      = array(
                              $expected,
                              $leadingSpace,
                             );

                $error = 'First line of comment not aligned correctly; expected %s but found %s';
                $phpcsFile->addError($error, $commentLines[1], 'FirstLineIndent', $data);
            }

            if (preg_match('|\p{Lu}|u', $commentText[0]) === 0) {
                $error = 'Block comments must start with a capital letter';
                $phpcsFile->addError($error, $commentLines[1], 'NoCapital');
            }
        }

        // Check that each line of the comment is indented past the star.
        foreach ($commentLines as $line) {
            $leadingSpace = (strlen($tokens[$line]['content']) - strlen(ltrim($tokens[$line]['content'])));
            // First and last lines (comment opener and closer) are handled separately.
            if ($line === $commentLines[(count($commentLines) - 1)] || $line === $commentLines[0]) {
                continue;
            }

            // First comment line was handled above.
            if ($line === $commentLines[1]) {
                continue;
            }

            // If it's empty, continue.
            if (trim($tokens[$line]['content']) === '') {
                continue;
            }

            if ($leadingSpace < $starColumn) {
                $expected  = $starColumn;
                $expected .= ($starColumn === 1) ? ' space' : ' spaces';
                $data      = array(
                              $expected,
                              $leadingSpace,
                             );

                $error = 'Comment line indented incorrectly; expected at least %s but found %s';
                $phpcsFile->addError($error, $line, 'LineIndent', $data);
            }
        }//end foreach

        // Finally, test the last line is correct.
        $lastIndex = (count($commentLines) - 1);
        $content   = trim($tokens[$commentLines[$lastIndex]]['content']);
        if ($content !== '*/' && $content !== '**/') {
            $error = 'Comment closer must be on a new line';
            $phpcsFile->addError($error, $commentLines[$lastIndex]);
        } else {
            $content      = $tokens[$commentLines[$lastIndex]]['content'];
            $commentText  = ltrim($content);
            $leadingSpace = (strlen($content) - strlen($commentText));
            if ($leadingSpace !== ($tokens[$stackPtr]['column'] - 1)) {
                $expected  = ($tokens[$stackPtr]['column'] - 1);
                $expected .= ($expected === 1) ? ' space' : ' spaces';
                $data      = array(
                              $expected,
                              $leadingSpace,
                             );

                $error = 'Last line of comment aligned incorrectly; expected %s but found %s';
                $phpcsFile->addError($error, $commentLines[$lastIndex], 'LastLineIndent', $data);
            }

        }

        // Check that the lines before and after this comment are blank.
        $contentBefore = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
        if (isset($tokens[$contentBefore]['scope_closer']) === true
            && $tokens[$contentBefore]['scope_opener'] === $contentBefore
        ) {
            if (($tokens[$stackPtr]['line'] - $tokens[$contentBefore]['line']) !== 1) {
                $error = 'Empty line not required before block comment';
                $phpcsFile->addError($error, $stackPtr, 'HasEmptyLineBefore');
            }
        } else {
            if (($tokens[$stackPtr]['line'] - $tokens[$contentBefore]['line']) < 2) {
                $error = 'Empty line required before block comment';
                $phpcsFile->addError($error, $stackPtr, 'NoEmptyLineBefore');
            }
        }

        $commentCloser = $commentLines[$lastIndex];
        $contentAfter  = $phpcsFile->findNext(T_WHITESPACE, ($commentCloser + 1), null, true);
        if (($tokens[$contentAfter]['line'] - $tokens[$commentCloser]['line']) < 2) {
            $error = 'Empty line required after block comment';
            $phpcsFile->addError($error, $commentCloser, 'NoEmptyLineAfter');
        }

    }//end process()


}//end class


?>
<?php
/**
 * Parses and verifies the class doc comment.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_CommentParser_ClassCommentParser', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_CommentParser_ClassCommentParser not found');
}

/**
 * Parses and verifies the class doc comment.
 *
 * Verifies that :
 * <ul>
 *  <li>A class doc comment exists.</li>
 *  <li>There is exactly one blank line before the class comment.</li>
 *  <li>Short description ends with a full stop.</li>
 *  <li>There is a blank line after the short description.</li>
 *  <li>Each paragraph of the long description ends with a full stop.</li>
 *  <li>There is a blank line between the description and the tags.</li>
 *  <li>Check the format of the since tag (x.x.x).</li>
 * </ul>
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Commenting_ClassCommentSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_CLASS);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $this->currentFile = $phpcsFile;

        $tokens = $phpcsFile->getTokens();
        $find   = array(
                   T_ABSTRACT,
                   T_WHITESPACE,
                   T_FINAL,
                  );

        // Extract the class comment docblock.
        $commentEnd = $phpcsFile->findPrevious($find, ($stackPtr - 1), null, true);

        if ($commentEnd !== false && $tokens[$commentEnd]['code'] === T_COMMENT) {
            $phpcsFile->addError('You must use "/**" style comments for a class comment', $stackPtr, 'WrongStyle');
            return;
        } else if ($commentEnd === false || $tokens[$commentEnd]['code'] !== T_DOC_COMMENT) {
            $phpcsFile->addError('Missing class doc comment', $stackPtr, 'Missing');
            return;
        }

        $commentStart = ($phpcsFile->findPrevious(T_DOC_COMMENT, ($commentEnd - 1), null, true) + 1);
        $commentNext  = $phpcsFile->findPrevious(T_WHITESPACE, ($commentEnd + 1), $stackPtr, false, $phpcsFile->eolChar);

        // Distinguish file and class comment.
        $prevClassToken = $phpcsFile->findPrevious(T_CLASS, ($stackPtr - 1));
        if ($prevClassToken === false) {
            // This is the first class token in this file, need extra checks.
            $prevNonComment = $phpcsFile->findPrevious(T_DOC_COMMENT, ($commentStart - 1), null, true);
            if ($prevNonComment !== false) {
                $prevComment = $phpcsFile->findPrevious(T_DOC_COMMENT, ($prevNonComment - 1));
                if ($prevComment === false) {
                    // There is only 1 doc comment between open tag and class token.
                    $newlineToken = $phpcsFile->findNext(T_WHITESPACE, ($commentEnd + 1), $stackPtr, false, $phpcsFile->eolChar);
                    if ($newlineToken !== false) {
                        $newlineToken = $phpcsFile->findNext(T_WHITESPACE, ($newlineToken + 1), $stackPtr, false, $phpcsFile->eolChar);
                        if ($newlineToken !== false) {
                            // Blank line between the class and the doc block.
                            // The doc block is most likely a file comment.
                            $phpcsFile->addError('Missing class doc comment', ($stackPtr + 1), 'Missing');
                            return;
                        }
                    }//end if
                }//end if

                // Exactly one blank line before the class comment.
                $prevTokenEnd = $phpcsFile->findPrevious(T_WHITESPACE, ($commentStart - 1), null, true);
                if ($prevTokenEnd !== false) {
                    $blankLineBefore = 0;
                    for ($i = ($prevTokenEnd + 1); $i < $commentStart; $i++) {
                        if ($tokens[$i]['code'] === T_WHITESPACE && $tokens[$i]['content'] === $phpcsFile->eolChar) {
                            $blankLineBefore++;
                        }
                    }

                    if ($blankLineBefore !== 2) {
                        $error = 'There must be exactly one blank line before the class comment';
                        $phpcsFile->addError($error, ($commentStart - 1), 'SpacingBefore');
                    }
                }

            }//end if
        }//end if

        $commentString = $phpcsFile->getTokensAsString($commentStart, ($commentEnd - $commentStart + 1));

        // Parse the class comment docblock.
        try {
            $this->commentParser = new PHP_CodeSniffer_CommentParser_ClassCommentParser($commentString, $phpcsFile);
            $this->commentParser->parse();
        } catch (PHP_CodeSniffer_CommentParser_ParserException $e) {
            $line = ($e->getLineWithinComment() + $commentStart);
            $phpcsFile->addError($e->getMessage(), $line, 'FailedParse');
            return;
        }

        $comment = $this->commentParser->getComment();
        if (is_null($comment) === true) {
            $error = 'Class doc comment is empty';
            $phpcsFile->addError($error, $commentStart, 'Empty');
            return;
        }

        // The first line of the comment should just be the /** code.
        $eolPos    = strpos($commentString, $phpcsFile->eolChar);
        $firstLine = substr($commentString, 0, $eolPos);
        if ($firstLine !== '/**') {
            $error = 'The open comment tag must be the only content on the line';
            $phpcsFile->addError($error, $commentStart, 'SpacingAfterOpen');
        }

        // Check for a comment description.
        $short = rtrim($comment->getShortComment(), $phpcsFile->eolChar);
        if (trim($short) === '') {
            $error = 'Missing short description in class doc comment';
            $phpcsFile->addError($error, $commentStart, 'MissingShort');
            return;
        }

        // No extra newline before short description.
        $newlineCount = 0;
        $newlineSpan  = strspn($short, $phpcsFile->eolChar);
        if ($short !== '' && $newlineSpan > 0) {
            $error = 'Extra newline(s) found before class comment short description';
            $phpcsFile->addError($error, ($commentStart + 1), 'SpacingBeforeShort');
        }

        $newlineCount = (substr_count($short, $phpcsFile->eolChar) + 1);

        // Exactly one blank line between short and long description.
        $long = $comment->getLongComment();
        if (empty($long) === false) {
            $between        = $comment->getWhiteSpaceBetween();
            $newlineBetween = substr_count($between, $phpcsFile->eolChar);
            if ($newlineBetween !== 2) {
                $error = 'There must be exactly one blank line between descriptions in class comment';
                $phpcsFile->addError($error, ($commentStart + $newlineCount + 1), 'SpacingBetween');
            }

            $newlineCount += $newlineBetween;

            $testLong = trim($long);
            if (preg_match('|\p{Lu}|u', $testLong[0]) === 0) {
                $error = 'Class comment long description must start with a capital letter';
                $phpcsFile->addError($error, ($commentStart + $newlineCount), 'LongNotCapital');
            }
        }

        // Exactly one blank line before tags.
        $tags = $this->commentParser->getTagOrders();
        if (count($tags) > 1) {
            $newlineSpan = $comment->getNewlineAfter();
            if ($newlineSpan !== 2) {
                $error = 'There must be exactly one blank line before the tags in class comment';
                if ($long !== '') {
                    $newlineCount += (substr_count($long, $phpcsFile->eolChar) - $newlineSpan + 1);
                }

                $phpcsFile->addError($error, ($commentStart + $newlineCount), 'SpacingBeforeTags');
                $short = rtrim($short, $phpcsFile->eolChar.' ');
            }
        }

        // Short description must be single line and end with a full stop.
        $testShort = trim($short);
        $lastChar  = $testShort[(strlen($testShort) - 1)];
        if (substr_count($testShort, $phpcsFile->eolChar) !== 0) {
            $error = 'Class comment short description must be on a single line';
            $phpcsFile->addError($error, ($commentStart + 1), 'ShortSingleLine');
        }
        if (preg_match('|\p{Lu}|u', $testShort[0]) === 0) {
            $error = 'Class comment short description must start with a capital letter';
            $phpcsFile->addError($error, ($commentStart + 1), 'ShortNotCapital');
        }

        if ($lastChar !== '.') {
            $error = 'Class comment short description must end with a full stop';
            $phpcsFile->addError($error, ($commentStart + 1), 'ShortFullStop');
        }

        // No tags are allowed in the class comment.
        $tags = $this->commentParser->getTags();
        foreach ($tags as $errorTag) {
            $error = '@%s tag is not allowed in class comment';
            $data  = array($errorTag['tag']);
            $phpcsFile->addWarning($error, ($commentStart + $errorTag['line']), 'TagNotAllowed', $data);
        }

        // The last content should be a newline and the content before
        // that should not be blank. If there is more blank space
        // then they have additional blank lines at the end of the comment.
        $words   = $this->commentParser->getWords();
        $lastPos = (count($words) - 1);
        if (trim($words[($lastPos - 1)]) !== ''
            || strpos($words[($lastPos - 1)], $this->currentFile->eolChar) === false
            || trim($words[($lastPos - 2)]) === ''
        ) {
            $error = 'Additional blank lines found at end of class comment';
            $this->currentFile->addError($error, $commentEnd, 'SpacingAfter');
        }

    }//end process()


}//end class
?>
<?php
/**
 * Squiz_Sniffs_Commenting_EmptyCatchCommentSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Commenting_DocCommentAlignmentSniff.
 *
 * Tests that the stars in a doc comment align correctly.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Commenting_DocCommentAlignmentSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_DOC_COMMENT);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                         in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // We are only interested in function/class/interface doc block comments.
        $nextToken = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr + 1), null, true);
        $ignore    = array(
                      T_CLASS,
                      T_INTERFACE,
                      T_FUNCTION,
                      T_PUBLIC,
                      T_PRIVATE,
                      T_PROTECTED,
                      T_STATIC,
                      T_ABSTRACT,
                     );

        if (in_array($tokens[$nextToken]['code'], $ignore) === false) {
            // Could be a file comment.
            $prevToken = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr - 1), null, true);
            if ($tokens[$prevToken]['code'] !== T_OPEN_TAG) {
                return;
            }
        }

        // We only want to get the first comment in a block. If there is
        // a comment on the line before this one, return.
        $docComment = $phpcsFile->findPrevious(T_DOC_COMMENT, ($stackPtr - 1));
        if ($docComment !== false) {
            if ($tokens[$docComment]['line'] === ($tokens[$stackPtr]['line'] - 1)) {
                return;
            }
        }

        $comments       = array($stackPtr);
        $currentComment = $stackPtr;
        $lastComment    = $stackPtr;
        while (($currentComment = $phpcsFile->findNext(T_DOC_COMMENT, ($currentComment + 1))) !== false) {
            if ($tokens[$lastComment]['line'] === ($tokens[$currentComment]['line'] - 1)) {
                $comments[]  = $currentComment;
                $lastComment = $currentComment;
            } else {
                break;
            }
        }

        // The $comments array now contains pointers to each token in the
        // comment block.
        $requiredColumn  = strpos($tokens[$stackPtr]['content'], '*');
        $requiredColumn += $tokens[$stackPtr]['column'];

        foreach ($comments as $commentPointer) {
            // Check the spacing after each asterisk.
            $content   = $tokens[$commentPointer]['content'];
            $firstChar = substr($content, 0, 1);
            $lastChar  = substr($content, -1);
            if ($firstChar !== '/' &&  $lastChar !== '/') {
                $matches = array();
                preg_match('|^(\s+)?\*(\s+)?@|', $content, $matches);
                if (empty($matches) === false) {
                    if (isset($matches[2]) === false) {
                        $error = 'Expected 1 space between asterisk and tag; 0 found';
                        $phpcsFile->addError($error, $commentPointer, 'NoSpaceBeforeTag');
                    } else {
                        $length = strlen($matches[2]);
                        if ($length !== 1) {
                            $error = 'Expected 1 space between asterisk and tag; %s found';
                            $data  = array($length);
                            $phpcsFile->addError($error, $commentPointer, 'SpaceBeforeTag', $data);
                        }
                    }
                }
            }//end foreach

            // Check the alignment of each asterisk.
            $currentColumn  = strpos($content, '*');
            $currentColumn += $tokens[$commentPointer]['column'];

            if ($currentColumn === $requiredColumn) {
                // Star is aligned correctly.
                continue;
            }

            $error = 'Expected %s space(s) before asterisk; %s found';
            $data  = array(
                      ($requiredColumn - 1),
                      ($currentColumn - 1),
                     );
            $phpcsFile->addError($error, $commentPointer, 'SpaceBeforeAsterisk', $data);
        }//end foreach

    }//end process()


}//end class

?>
<?php
/**
 * Parses and verifies the file doc comment.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_CommentParser_ClassCommentParser', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_CommentParser_ClassCommentParser not found');
}

/**
 * Parses and verifies the file doc comment.
 *
 * Verifies that :
 * <ul>
 *  <li>A file doc comment exists.</li>
 *  <li>There is no blank line between the open tag and the file comment.</li>
 *  <li>Short description ends with a full stop.</li>
 *  <li>There is a blank line after the short description.</li>
 *  <li>Each paragraph of the long description ends with a full stop.</li>
 *  <li>There is a blank line between the description and the tags.</li>
 *  <li>Check the order, indentation and content of each tag.</li>
 *  <li>There is exactly one blank line after the file comment.</li>
 * </ul>
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

class Squiz_Sniffs_Commenting_FileCommentSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                  );

    /**
     * The header comment parser for the current file.
     *
     * @var PHP_CodeSniffer_Comment_Parser_ClassCommentParser
     */
    protected $commentParser = null;

    /**
     * The current PHP_CodeSniffer_File object we are processing.
     *
     * @var PHP_CodeSniffer_File
     */
    protected $currentFile = null;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_OPEN_TAG);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $this->currentFile = $phpcsFile;

        // We are only interested if this is the first open tag.
        if ($stackPtr !== 0) {
            if ($phpcsFile->findPrevious(T_OPEN_TAG, ($stackPtr - 1)) !== false) {
                return;
            }
        }

        $tokens = $phpcsFile->getTokens();

        $errorToken = ($stackPtr + 1);
        if (isset($tokens[$errorToken]) === false) {
            $errorToken--;
        }

        // Find the next non whitespace token.
        $commentStart = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);

        if ($tokens[$commentStart]['code'] === T_CLOSE_TAG) {
            // We are only interested if this is the first open tag.
            return;
        } else if ($tokens[$commentStart]['code'] === T_COMMENT) {
            $phpcsFile->addError('You must use "/**" style comments for a file comment', $errorToken, 'WrongStyle');
            return;
        } else if ($commentStart === false || $tokens[$commentStart]['code'] !== T_DOC_COMMENT) {
            $phpcsFile->addError('Missing file doc comment', $errorToken, 'Missing');
            return;
        }

        // Extract the header comment docblock.
        $commentEnd = ($phpcsFile->findNext(T_DOC_COMMENT, ($commentStart + 1), null, true) - 1);

        // Check if there is only 1 doc comment between the open tag and class token.
        $nextToken   = array(
                        T_ABSTRACT,
                        T_CLASS,
                        T_DOC_COMMENT,
                       );

        $commentNext = $phpcsFile->findNext($nextToken, ($commentEnd + 1));
        if ($commentNext !== false && $tokens[$commentNext]['code'] !== T_DOC_COMMENT) {
            // Found a class token right after comment doc block.
            $newlineToken = $phpcsFile->findNext(T_WHITESPACE, ($commentEnd + 1), $commentNext, false, $phpcsFile->eolChar);
            if ($newlineToken !== false) {
                $newlineToken = $phpcsFile->findNext(T_WHITESPACE, ($newlineToken + 1), $commentNext, false, $phpcsFile->eolChar);
                if ($newlineToken === false) {
                    // No blank line between the class token and the doc block.
                    // The doc block is most likely a class comment.
                    $phpcsFile->addError('Missing file doc comment', $errorToken, 'Missing');
                    return;
                }
            }
        }

        // No blank line between the open tag and the file comment.
        $blankLineBefore = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, false, $phpcsFile->eolChar);
        if ($blankLineBefore !== false && $blankLineBefore < $commentStart) {
            $error = 'Extra newline found after the open tag';
            $phpcsFile->addError($error, $stackPtr, 'SpacingAfterOpen');
        }

        // Exactly one blank line after the file comment.
        $nextTokenStart = $phpcsFile->findNext(T_WHITESPACE, ($commentEnd + 1), null, true);
        if ($nextTokenStart !== false) {
            $blankLineAfter = 0;
            for ($i = ($commentEnd + 1); $i < $nextTokenStart; $i++) {
                if ($tokens[$i]['code'] === T_WHITESPACE && $tokens[$i]['content'] === $phpcsFile->eolChar) {
                    $blankLineAfter++;
                }
            }

            if ($blankLineAfter !== 2) {
                $error = 'There must be exactly one blank line after the file comment';
                $phpcsFile->addError($error, ($commentEnd + 1), 'SpacingAfterComment');
            }
        }

        $commentString = $phpcsFile->getTokensAsString($commentStart, ($commentEnd - $commentStart + 1));

        // Parse the header comment docblock.
        try {
            $this->commentParser = new PHP_CodeSniffer_CommentParser_ClassCommentParser($commentString, $phpcsFile);
            $this->commentParser->parse();
        } catch (PHP_CodeSniffer_CommentParser_ParserException $e) {
            $line = ($e->getLineWithinComment() + $commentStart);
            $phpcsFile->addError($e->getMessage(), $line, 'Exception');
            return;
        }

        $comment = $this->commentParser->getComment();
        if (is_null($comment) === true) {
            $error = 'File doc comment is empty';
            $phpcsFile->addError($error, $commentStart, 'Empty');
            return;
        }

        // The first line of the comment should just be the /** code.
        $eolPos    = strpos($commentString, $phpcsFile->eolChar);
        $firstLine = substr($commentString, 0, $eolPos);
        if ($firstLine !== '/**') {
            $error = 'The open comment tag must be the only content on the line';
            $phpcsFile->addError($error, $commentStart, 'ContentAfterOpen');
        }

        // No extra newline before short description.
        $short        = $comment->getShortComment();
        $newlineCount = 0;
        $newlineSpan  = strspn($short, $phpcsFile->eolChar);
        if ($short !== '' && $newlineSpan > 0) {
            $error = 'Extra newline(s) found before file comment short description';
            $phpcsFile->addError($error, ($commentStart + 1), 'SpacingBeforeShort');
        }

        $newlineCount = (substr_count($short, $phpcsFile->eolChar) + 1);

        // Exactly one blank line between short and long description.
        $long = $comment->getLongComment();
        if (empty($long) === false) {
            $between        = $comment->getWhiteSpaceBetween();
            $newlineBetween = substr_count($between, $phpcsFile->eolChar);
            if ($newlineBetween !== 2) {
                $error = 'There must be exactly one blank line between descriptions in file comment';
                $phpcsFile->addError($error, ($commentStart + $newlineCount + 1), 'SpacingBetween');
            }

            $newlineCount += $newlineBetween;

            $testLong = trim($long);
            if (preg_match('|\p{Lu}|u', $testLong[0]) === 0) {
                $error = 'File comment long description must start with a capital letter';
                $phpcsFile->addError($error, ($commentStart + $newlineCount), 'LongNotCapital');
            }
        }//end if

        // Exactly one blank line before tags.
        $tags = $this->commentParser->getTagOrders();
        if (count($tags) > 1) {
            $newlineSpan = $comment->getNewlineAfter();
            if ($newlineSpan !== 2) {
                $error = 'There must be exactly one blank line before the tags in file comment';
                if ($long !== '') {
                    $newlineCount += (substr_count($long, $phpcsFile->eolChar) - $newlineSpan + 1);
                }

                $phpcsFile->addError($error, ($commentStart + $newlineCount), 'SpacingBeforeTags');
                $short = rtrim($short, $phpcsFile->eolChar.' ');
            }
        }

        // Short description must be single line and end with a full stop.
        $testShort = trim($short);
        if ($testShort === '') {
            $error = 'Missing short description in file comment';
            $phpcsFile->addError($error, ($commentStart + 1), 'MissingShort');
        } else {
            $lastChar  = $testShort[(strlen($testShort) - 1)];
            if (substr_count($testShort, $phpcsFile->eolChar) !== 0) {
                $error = 'File comment short description must be on a single line';
                $phpcsFile->addError($error, ($commentStart + 1), 'ShortSingleLine');
            }

            if (preg_match('|\p{Lu}|u', $testShort[0]) === 0) {
                $error = 'File comment short description must start with a capital letter';
                $phpcsFile->addError($error, ($commentStart + 1), 'ShortNotCapital');
            }

            if ($lastChar !== '.') {
                $error = 'File comment short description must end with a full stop';
                $phpcsFile->addError($error, ($commentStart + 1), 'ShortFullStop');
            }
        }//end if

        // Check each tag.
        $this->processTags($commentStart, $commentEnd);

        // The last content should be a newline and the content before
        // that should not be blank. If there is more blank space
        // then they have additional blank lines at the end of the comment.
        $words   = $this->commentParser->getWords();
        $lastPos = (count($words) - 1);
        if (trim($words[($lastPos - 1)]) !== ''
            || strpos($words[($lastPos - 1)], $this->currentFile->eolChar) === false
            || trim($words[($lastPos - 2)]) === ''
        ) {
            $error = 'Additional blank lines found at end of file comment';
            $this->currentFile->addError($error, $commentEnd, 'SpacingAfter');
        }

    }//end process()


    /**
     * Processes each required or optional tag.
     *
     * @param int $commentStart The position in the stack where the comment started.
     * @param int $commentEnd   The position in the stack where the comment ended.
     *
     * @return void
     */
    protected function processTags($commentStart, $commentEnd)
    {
        // Required tags in correct order.
        $tags = array(
                 'package'    => 'precedes @subpackage',
                 'subpackage' => 'follows @package',
                 'author'     => 'follows @subpackage',
                 'copyright'  => 'follows @author',
                );

        $foundTags   = $this->commentParser->getTagOrders();
        $errorPos    = 0;
        $orderIndex  = 0;
        $longestTag  = 0;
        $indentation = array();
        foreach ($tags as $tag => $orderText) {

            // Required tag missing.
            if (in_array($tag, $foundTags) === false) {
                $error = 'Missing @%s tag in file comment';
                $data  = array($tag);
                $this->currentFile->addError($error, $commentEnd, 'Missing'.ucfirst($tag).'Tag', $data);
                continue;
            }

            // Get the line number for current tag.
            $tagName = ucfirst($tag);
            if ($tagName === 'Author' || $tagName === 'Copyright') {
                // These tags are different because they return an array.
                $tagName .= 's';
            }

            // Work out the line number for this tag.
            $getMethod  = 'get'.$tagName;
            $tagElement = $this->commentParser->$getMethod();
            if (is_null($tagElement) === true || empty($tagElement) === true) {
                continue;
            } else if (is_array($tagElement) === true && empty($tagElement) === false) {
                $tagElement = $tagElement[0];
            }

            $errorPos = ($commentStart + $tagElement->getLine());

            // Make sure there is no duplicate tag.
            $foundIndexes = array_keys($foundTags, $tag);
            if (count($foundIndexes) > 1) {
                $error = 'Only 1 @%s tag is allowed in file comment';
                $data  = array($tag);
                $this->currentFile->addError($error, $errorPos, 'Duplicate'.ucfirst($tag).'Tag', $data);
            }

            // Check tag order.
            if ($foundIndexes[0] > $orderIndex) {
                $orderIndex = $foundIndexes[0];
            } else {
                $error = 'The @%s tag is in the wrong order; the tag %s';
                $data  = array(
                          $tag,
                          $orderText,
                         );
                $this->currentFile->addError($error, $errorPos, ucfirst($tag).'TagOrder', $data);
            }

            // Store the indentation of each tag.
            $len = strlen($tag);
            if ($len > $longestTag) {
                $longestTag = $len;
            }

            $indentation[] = array(
                              'tag'      => $tag,
                              'errorPos' => $errorPos,
                              'space'    => $this->getIndentation($tag, $tagElement),
                             );

            $method = 'process'.$tagName;
            if (method_exists($this, $method) === true) {
                // Process each tag if a method is defined.
                call_user_func(array($this, $method), $errorPos);
            } else {
                $tagElement->process($this->currentFile, $commentStart, 'file');
            }
        }//end foreach

        // Check tag indentation.
        foreach ($indentation as $indentInfo) {
            $tagName = ucfirst($indentInfo['tag']);
            if ($tagName === 'Author') {
                $tagName .= 's';
            }

            if ($indentInfo['space'] !== 0 && $indentInfo['space'] !== ($longestTag + 1)) {
                $expected = ($longestTag - strlen($indentInfo['tag']) + 1);
                $space    = ($indentInfo['space'] - strlen($indentInfo['tag']));
                $error    = '@%s tag comment indented incorrectly; expected %s spaces but found %s';
                $data     = array(
                             $indentInfo['tag'],
                             $expected,
                             $space,
                            );
                $this->currentFile->addError($error, $indentInfo['errorPos'], ucfirst($indentInfo['tag']).'TagIndent', $data);
            }
        }

    }//end processTags()


    /**
     * Get the indentation information of each tag.
     *
     * @param string                                   $tagName    The name of the doc comment element.
     * @param PHP_CodeSniffer_CommentParser_DocElement $tagElement The doc comment element.
     *
     * @return void
     */
    protected function getIndentation($tagName, $tagElement)
    {
        if ($tagElement instanceof PHP_CodeSniffer_CommentParser_SingleElement) {
            if ($tagElement->getContent() !== '') {
                return (strlen($tagName) + substr_count($tagElement->getWhitespaceBeforeContent(), ' '));
            }
        } else if ($tagElement instanceof PHP_CodeSniffer_CommentParser_PairElement) {
            if ($tagElement->getValue() !== '') {
                return (strlen($tagName) + substr_count($tagElement->getWhitespaceBeforeValue(), ' '));
            }
        }

        return 0;

    }//end getIndentation()


    /**
     * The package name must be camel-cased.
     *
     * @param int $errorPos The line number where the error occurs.
     *
     * @return void
     */
    protected function processPackage($errorPos)
    {
        $package = $this->commentParser->getPackage();
        if ($package !== null) {
            $content = $package->getContent();
            if (empty($content) === true) {
                $error = 'Content missing for @package tag in file comment';
                $this->currentFile->addError($error, $errorPos, 'MissingPackage');
            } else if (PHP_CodeSniffer::isUnderscoreName($content) !== true) {
                // Package name must be properly camel-cased.
                $nameBits = explode('_', str_replace(' ', '', $content));
                $firstBit = array_shift($nameBits);
                $newName  = strtoupper($firstBit{0}).substr($firstBit, 1).'_';
                foreach ($nameBits as $bit) {
                    $newName .= strtoupper($bit{0}).substr($bit, 1).'_';
                }

                $error = 'Package name "%s" is not valid; consider "%s" instead';
                $data  = array(
                          $content,
                          trim($newName, '_'),
                         );
                $this->currentFile->addError($error, $errorPos, 'IncorrectPackage', $data);
            } else if (strpos($content, 'Squiz') === 0) {
                // Package name must not start with Squiz.
                $newName = substr($content, 5);
                $error   = 'Package name "%s" is not valid; consider "%s" instead';
                $data    = array(
                            $content,
                            $newName,
                           );
                $this->currentFile->addError($error, $errorPos, 'SquizPackage', $data);
            }
        }

    }//end processPackage()


    /**
     * The subpackage name must be camel-cased.
     *
     * @param int $errorPos The line number where the error occurs.
     *
     * @return void
     */
    protected function processSubpackage($errorPos)
    {
        $subpackage = $this->commentParser->getSubpackage();
        if ($subpackage !== null) {
            $content = $subpackage->getContent();
            if (empty($content) === true) {
                $error = 'Content missing for @subpackage tag in file comment';
                $this->currentFile->addError($error, $errorPos, 'MissingSubpackage');
            } else if (PHP_CodeSniffer::isUnderscoreName($content) !== true) {
                // Subpackage name must be properly camel-cased.
                $nameBits = explode('_', $content);
                $firstBit = array_shift($nameBits);
                $newName  = strtoupper($firstBit{0}).substr($firstBit, 1).'_';
                foreach ($nameBits as $bit) {
                    $newName .= strtoupper($bit{0}).substr($bit, 1).'_';
                }

                $error = 'Subpackage name "%s" is not valid; consider "%s" instead';
                $data  = array(
                          $content,
                          trim($newName, '_'),
                         );
                $this->currentFile->addError($error, $errorPos, 'IncorrectSubpackage', $data);
            }
        }

    }//end processSubpackage()


    /**
     * Author tag must be 'Squiz Pty Ltd <mysource4@squiz.net>'.
     *
     * @param int $errorPos The line number where the error occurs.
     *
     * @return void
     */
    protected function processAuthors($errorPos)
    {
        $authors = $this->commentParser->getAuthors();
        if (empty($authors) === false) {
            $author  = $authors[0];
            $content = $author->getContent();
            if (empty($content) === true) {
                $error = 'Content missing for @author tag in file comment';
                $this->currentFile->addError($error, $errorPos, 'MissingAuthor');
            } else if ($content !== 'Squiz Pty Ltd <products@squiz.net>') {
                $error = 'Expected "Squiz Pty Ltd <products@squiz.net>" for author tag';
                $this->currentFile->addError($error, $errorPos, 'IncorrectAuthor');
            }
        }

    }//end processAuthors()


    /**
     * Copyright tag must be in the form '2006-YYYY Squiz Pty Ltd (ABN 77 084 670 600)'.
     *
     * @param int $errorPos The line number where the error occurs.
     *
     * @return void
     */
    protected function processCopyrights($errorPos)
    {
        $copyrights = $this->commentParser->getCopyrights();
        $copyright  = $copyrights[0];

        if ($copyright !== null) {
            $content = $copyright->getContent();
            if (empty($content) === true) {
                $error = 'Content missing for @copyright tag in file comment';
                $this->currentFile->addError($error, $errorPos, 'MissingCopyright');

            } else if (preg_match('/^([0-9]{4})(-[0-9]{4})? (Squiz Pty Ltd \(ABN 77 084 670 600\))$/', $content) === 0) {
                $error = 'Expected "xxxx-xxxx Squiz Pty Ltd (ABN 77 084 670 600)" for copyright declaration';
                $this->currentFile->addError($error, $errorPos, 'IncorrectCopyright');
            }
        }

    }//end processCopyrights()


}//end class


?>
<?php
/**
 * Squiz_Sniffs_Files_FileExtensionSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Files_FileExtensionSniff.
 *
 * Tests that the stars in a doc comment align correctly.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Files_FileExtensionSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_OPEN_TAG);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Make sure this is the first PHP open tag so we don't process
        // the same file twice.
        $prevOpenTag = $phpcsFile->findPrevious(T_OPEN_TAG, ($stackPtr - 1));
        if ($prevOpenTag !== false) {
            return;
        }

        $fileName  = $phpcsFile->getFileName();
        $extension = substr($fileName, strrpos($fileName, '.'));
        $nextClass = $phpcsFile->findNext(array(T_CLASS, T_INTERFACE, T_TRAIT), $stackPtr);

        if ($extension === '.php') {
            if ($nextClass !== false) {
                $error = '%s found in ".php" file; use ".inc" extension instead';
                $data  = array(ucfirst($tokens[$nextClass]['content']));
                $phpcsFile->addError($error, $stackPtr, 'ClassFound', $data);
            }
        } else if ($extension === '.inc') {
            if ($nextClass === false) {
                $error = 'No interface or class found in ".inc" file; use ".php" extension instead';
                $phpcsFile->addError($error, $stackPtr, 'NoClass');
            }
        }

    }//end process()


}//end class


?>
<?php
/**
 * Squiz_Sniffs_Strings_ConcatenationSpacingSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Strings_ConcatenationSpacingSniff.
 *
 * Makes sure there are no spaces between the concatenation operator (.) and
 * the strings being concatenated.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Strings_ConcatenationSpacingSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_STRING_CONCAT);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();
        if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE
            || $tokens[($stackPtr + 1)]['code'] === T_WHITESPACE
        ) {
            $message = 'Concat operator must not be surrounded by spaces';
            $phpcsFile->addError($message, $stackPtr, 'Missing');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_Strings_EchoedStringsSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Strings_EchoedStringsSniff.
 *
 * Makes sure that any strings that are "echoed" are not enclosed in brackets
 * like a function call.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Strings_EchoedStringsSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_ECHO);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $firstContent = $phpcsFile->findNext(array(T_WHITESPACE), ($stackPtr + 1), null, true);
        // If the first non-whitespace token is not an opening parenthesis, then we are not concerned.
        if ($tokens[$firstContent]['code'] !== T_OPEN_PARENTHESIS) {
            return;
        }

        $endOfStatement = $phpcsFile->findNext(array(T_SEMICOLON), $stackPtr, null, false);

        // If the token before the semi-colon is not a closing parenthesis, then we are not concerned.
        if ($tokens[($endOfStatement - 1)]['code'] !== T_CLOSE_PARENTHESIS) {
            return;
        }

        if (($phpcsFile->findNext(PHP_CodeSniffer_Tokens::$operators, $stackPtr, $endOfStatement, false)) === false) {
            // There are no arithmetic operators in this.
            $error = 'Echoed strings should not be bracketed';
            $phpcsFile->addError($error, $stackPtr, 'HasBracket');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_Strings_DoubleQuoteUsageSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Strings_DoubleQuoteUsageSniff.
 *
 * Makes sure that any use of Double Quotes ("") are warranted.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Strings_DoubleQuoteUsageSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_CONSTANT_ENCAPSED_STRING,
                T_DOUBLE_QUOTED_STRING,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // We are only interested in the first token in a multi-line string.
        if ($tokens[$stackPtr]['code'] === $tokens[($stackPtr - 1)]['code']) {
            return;
        }

        $workingString = $tokens[$stackPtr]['content'];
        $i = ($stackPtr + 1);
        while ($tokens[$i]['code'] === $tokens[$stackPtr]['code']) {
            $workingString .= $tokens[$i]['content'];
            $i++;
        }

        // Check if it's a double quoted string.
        if (strpos($workingString, '"') === false) {
            return;
        }

        // Make sure it's not a part of a string started in a previous line.
        // If it is, then we have already checked it.
        if ($workingString[0] !== '"') {
            return;
        }

        // The use of variables in double quoted strings is not allowed.
        if ($tokens[$stackPtr]['code'] === T_DOUBLE_QUOTED_STRING) {
            $stringTokens = token_get_all('<?php '.$workingString);
            foreach ($stringTokens as $token) {
                if (is_array($token) === true && $token[0] === T_VARIABLE) {
                    $error = 'Variable "%s" not allowed in double quoted string; use concatenation instead';
                    $data  = array($token[1]);
                    $phpcsFile->addError($error, $stackPtr, 'ContainsVar', $data);
                }
            }

            return;
        }//end if

        // Work through the following tokens, in case this string is stretched
        // over multiple Lines.
        for ($i = ($stackPtr + 1); $i < $phpcsFile->numTokens; $i++) {
            if ($tokens[$i]['type'] !== 'T_CONSTANT_ENCAPSED_STRING') {
                break;
            }

            $workingString .= $tokens[$i]['content'];
        }

        $allowedChars = array(
                         '\0',
                         '\n',
                         '\r',
                         '\f',
                         '\t',
                         '\v',
                         '\x',
                         '\'',
                        );

        foreach ($allowedChars as $testChar) {
            if (strpos($workingString, $testChar) !== false) {
                return;
            }
        }

        $error = 'String %s does not require double quotes; use single quotes instead';
        $data  = array($workingString);
        $phpcsFile->addError($error, $stackPtr, 'NotRequired', $data);

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_PHP_DisallowMultipleAssignmentsSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_PHP_DisallowMultipleAssignmentsSniff.
 *
 * Ensures that there is only one value assignment on a line, and that it is
 * the first thing on the line.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_PHP_DisallowMultipleAssignmentsSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_EQUAL);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Ignore default value assignments in function definitions.
        $function = $phpcsFile->findPrevious(array(T_FUNCTION, T_CLOSURE), ($stackPtr - 1));
        if ($function !== false) {
            $opener = $tokens[$function]['parenthesis_opener'];
            $closer = $tokens[$function]['parenthesis_closer'];
            if ($opener < $stackPtr && $closer > $stackPtr) {
                return;
            }
        }

        /*
            The general rule is:
            Find an equal sign and go backwards along the line. If you hit an
            end bracket, skip to the opening bracket. When you find a variable,
            stop. That variable must be the first non-empty token on the line
            or in the statement. If not, throw an error.
        */

        for ($varToken = ($stackPtr - 1); $varToken >= 0; $varToken--) {
            // Skip brackets.
            if (isset($tokens[$varToken]['parenthesis_opener']) === true && $tokens[$varToken]['parenthesis_opener'] < $varToken) {
                $varToken = $tokens[$varToken]['parenthesis_opener'];
                continue;
            }

            if (isset($tokens[$varToken]['bracket_opener']) === true) {
                $varToken = $tokens[$varToken]['bracket_opener'];
                continue;
            }

            if ($tokens[$varToken]['code'] === T_SEMICOLON) {
                // We've reached the next statement, so we
                // didn't find a variable.
                return;
            }

            if ($tokens[$varToken]['code'] === T_VARIABLE) {
                // We found our variable.
                break;
            }
        }

        if ($varToken <= 0) {
            // Didn't find a variable.
            return;
        }

        // Deal with this type of variable: self::$var by setting the var
        // token to be "self" rather than "$var".
        if ($tokens[($varToken - 1)]['code'] === T_DOUBLE_COLON) {
            $varToken = ($varToken - 2);
        }

        // Deal with this type of variable: $obj->$var by setting the var
        // token to be "$obj" rather than "$var".
        if ($tokens[($varToken - 1)]['code'] === T_OBJECT_OPERATOR) {
            $varToken = ($varToken - 2);
        }

        // Deal with this type of variable: $$var by setting the var
        // token to be "$" rather than "$var".
        if ($tokens[($varToken - 1)]['content'] === '$') {
            $varToken--;
        }

        // Ignore member var definitions.
        $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($varToken - 1), null, true);
        if (in_array($tokens[$prev]['code'], PHP_CodeSniffer_Tokens::$scopeModifiers) === true) {
            return;
        }

        if ($tokens[$prev]['code'] === T_STATIC) {
            return;
        }

        // Make sure this variable is the first thing in the statement.
        $varLine  = $tokens[$varToken]['line'];
        $prevLine = 0;
        for ($i = ($varToken - 1); $i >= 0; $i--) {
            if ($tokens[$i]['code'] === T_SEMICOLON) {
                // We reached the end of the statement.
                return;
            }

            if ($tokens[$i]['code'] === T_INLINE_THEN) {
                // We reached the end of the inline THEN statement.
                return;
            }

            if ($tokens[$i]['code'] === T_INLINE_ELSE) {
                // We reached the end of the inline ELSE statement.
                return;
            }

            if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
                $prevLine = $tokens[$i]['line'];
                break;
            }
        }

        // Ignore the first part of FOR loops as we are allowed to
        // assign variables there even though the variable is not the
        // first thing on the line. Also ignore WHILE loops.
        if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS && isset($tokens[$i]['parenthesis_owner']) === true) {
            $owner = $tokens[$i]['parenthesis_owner'];
            if ($tokens[$owner]['code'] === T_FOR || $tokens[$owner]['code'] === T_WHILE) {
                return;
            }
        }

        if ($prevLine === $varLine) {
            $error = 'Assignments must be the first block of code on a line';
            $phpcsFile->addError($error, $stackPtr, 'Found');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_PHP_LowercasePHPFunctionsSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_PHP_LowercasePHPFunctionsSniff.
 *
 * Ensures all calls to inbuilt PHP functions are lowercase.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_PHP_LowercasePHPFunctionsSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_STRING);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Make sure this is a function call.
        $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
        if ($next === false) {
            // Not a function call.
            return;
        }

        if ($tokens[$next]['code'] !== T_OPEN_PARENTHESIS) {
            // Not a function call.
            return;
        }

        $prev = $phpcsFile->findPrevious(array(T_WHITESPACE, T_BITWISE_AND), ($stackPtr - 1), null, true);
        if ($tokens[$prev]['code'] === T_FUNCTION) {
            // Function declaration, not a function call.
            return;
        }

        if ($tokens[$prev]['code'] === T_NEW) {
            // Object creation, not an inbuilt function.
            return;
        }

        if ($tokens[$prev]['code'] === T_OBJECT_OPERATOR) {
            // Not an inbuilt function.
            return;
        }

        if ($tokens[$prev]['code'] === T_DOUBLE_COLON) {
            // Not an inbuilt function.
            return;
        }

        // Make sure it is an inbuilt PHP function.
        // PHP_CodeSniffer doesn't include/require any files, so no
        // user defined global functions can exist, except for
        // PHP_CodeSniffer ones.
        $content = $tokens[$stackPtr]['content'];
        if (function_exists($content) === false) {
            return;
        }

        if ($content !== strtolower($content)) {
            $error = 'Calls to inbuilt PHP functions must be lowercase; expected "%s" but found "%s"';
            $data  = array(
                      strtolower($content),
                      $content,
                     );
            $phpcsFile->addError($error, $stackPtr, 'CallUppercase', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_Formatting_DisallowObEndFlushSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Formatting_DisallowObEndFlushSniff.
 *
 * Checks the indenting used when an ob_start() call occurs.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_PHP_DisallowObEndFlushSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_STRING);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if ($tokens[$stackPtr]['content'] === 'ob_end_flush') {
            $phpcsFile->addError('Use of ob_end_flush() is not allowed; use ob_get_contents() and ob_end_clean() instead', $stackPtr, 'Found');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_Formatting_DisallowObEndFlushSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Formatting_DisallowInlineIfSniff.
 *
 * Stops inline IF statements from being used.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_PHP_DisallowInlineIfSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                  );


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_INLINE_THEN);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $phpcsFile->addError('Inline IF statements are not allowed', $stackPtr, 'Found');

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_PHP_GlobalKeywordSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_PHP_GlobalKeywordSniff.
 *
 * Stops the usage of the "global" keyword.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_PHP_GlobalKeywordSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_GLOBAL);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $nextVar = $tokens[$phpcsFile->findNext(array(T_VARIABLE), $stackPtr)];
        $varName = str_replace('$', '', $nextVar['content']);
        $error   = 'Use of the "global" keyword is forbidden; use "$GLOBALS[\'%s\']" instead';
        $data    = array($varName);
        $phpcsFile->addError($error, $stackPtr, 'NotAllowed', $data);

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_PHP_ForbiddenFunctionsSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('Generic_Sniffs_PHP_ForbiddenFunctionsSniff', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class Generic_Sniffs_PHP_ForbiddenFunctionsSniff not found');
}

/**
 * Squiz_Sniffs_PHP_ForbiddenFunctionsSniff.
 *
 * Discourages the use of alias functions that are kept in PHP for compatibility
 * with older versions. Can be used to forbid the use of any function.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_PHP_ForbiddenFunctionsSniff extends Generic_Sniffs_PHP_ForbiddenFunctionsSniff
{

    /**
     * A list of forbidden functions with their alternatives.
     *
     * The value is NULL if no alternative exists. IE, the
     * function should just not be used.
     *
     * @var array(string => string|null)
     */
    protected $forbiddenFunctions = array(
                                     'sizeof'          => 'count',
                                     'delete'          => 'unset',
                                     'print'           => 'echo',
                                     'is_null'         => null,
                                     'create_function' => null,
                                    );


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        $tokens = parent::register();
        $tokens[] = T_PRINT;
        return $tokens;

    }//end register()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_PHP_DisallowComparisonAssignmentSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_PHP_DisallowComparisonAssignmentSniff.
 *
 * Ensures that the value of a comparison is not assigned to a variable.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_PHP_DisallowComparisonAssignmentSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_EQUAL);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Ignore default value assignments in function definitions.
        $function = $phpcsFile->findPrevious(T_FUNCTION, ($stackPtr - 1));
        if ($function !== false) {
            $opener = $tokens[$function]['parenthesis_opener'];
            $closer = $tokens[$function]['parenthesis_closer'];
            if ($opener < $stackPtr && $closer > $stackPtr) {
                return;
            }
        }

        // Ignore values in array definitions.
        $array = $phpcsFile->findNext(
            T_ARRAY,
            ($stackPtr + 1),
            null,
            false,
            null,
            true
        );

        if ($array !== false) {
            return;
        }

        // Ignore function calls.
        $ignore = array(
                   T_STRING,
                   T_WHITESPACE,
                   T_OBJECT_OPERATOR,
                  );

        $next = $phpcsFile->findNext($ignore, ($stackPtr + 1), null, true);
        if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS
            && $tokens[($next - 1)]['code'] === T_STRING
        ) {
            // Code will look like: $var = myFunction(
            // and will be ignored.
            return;
        }

        $endStatement = $phpcsFile->findNext(T_SEMICOLON, ($stackPtr + 1));
        if ($tokens[$stackPtr]['conditions'] !== $tokens[$endStatement]['conditions']) {
            // This statement doesn't end with a semicolon, which is the case for
            // the last expression in a for loop.
            return;
        }

        for ($i = ($stackPtr + 1); $i < $endStatement; $i++) {
            if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$comparisonTokens) === true) {
                $error = 'The value of a comparison must not be assigned to a variable';
                $phpcsFile->addError($error, $stackPtr, 'AssignedComparison');
                break;
            }

            if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$booleanOperators) === true
                || $tokens[$i]['code'] === T_BOOLEAN_NOT
            ) {
                $error = 'The value of a boolean operation must not be assigned to a variable';
                $phpcsFile->addError($error, $stackPtr, 'AssignedBool');
                break;
            }
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_PHP_EmbeddedPhpSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_PHP_EmbeddedPhpSniff.
 *
 * Checks the indentation of embedded PHP code segments.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_PHP_EmbeddedPhpSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_OPEN_TAG);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // If the close php tag is on the same line as the opening
        // then we have an inline embedded PHP block.
        $closeTag = $phpcsFile->findNext(array(T_CLOSE_TAG), $stackPtr);
        if ($closeTag === false) {
            return;
        }

        if ($tokens[$stackPtr]['line'] !== $tokens[$closeTag]['line']) {
            $this->_validateMultilineEmbeddedPhp($phpcsFile, $stackPtr);
        } else {
            $this->_validateInlineEmbeddedPhp($phpcsFile, $stackPtr);
        }

    }//end process()


    /**
     * Validates embedded PHP that exists on multiple lines.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    private function _validateMultilineEmbeddedPhp(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $prevTag = $phpcsFile->findPrevious(T_OPEN_TAG, ($stackPtr - 1));
        if ($prevTag === false) {
            // This is the first open tag.
            return;
        }

        // This isn't the first opening tag.
        $closingTag = $phpcsFile->findNext(T_CLOSE_TAG, $stackPtr);
        if ($closingTag === false) {
            // No closing tag? Problem.
            return;
        }

        $nextContent = $phpcsFile->findNext(T_WHITESPACE, ($closingTag + 1), $phpcsFile->numTokens, true);
        if ($nextContent === false) {
            // Final closing tag. It will be handled elsewhere.
            return;
        }

        // Make sure the lines are opening and closing on different lines.
        if ($tokens[$stackPtr]['line'] === $tokens[$closingTag]['line']) {
            return;
        }

        // We have an opening and a closing tag, that lie within other content.
        // They are also on different lines.
        $firstContent = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), $closingTag, true);
        if ($firstContent === false) {
            $error = 'Empty embedded PHP tag found';
            $phpcsFile->addError($error, $stackPtr, 'Empty');
            return;
        }

        // Check for a blank line at the top.
        if ($tokens[$firstContent]['line'] > ($tokens[$stackPtr]['line'] + 1)) {
            // Find a token on the blank line to throw the error on.
            $i = $stackPtr;
            do {
                $i++;
            } while ($tokens[$i]['line'] !== ($tokens[$stackPtr]['line'] + 1));

            $error = 'Blank line found at start of embedded PHP content';
            $phpcsFile->addError($error, $i, 'SpacingBefore');
        } else if ($tokens[$firstContent]['line'] === $tokens[$stackPtr]['line']) {
            $error = 'Opening PHP tag must be on a line by itself';
            $phpcsFile->addError($error, $stackPtr, 'ContentAfterOpen');
        }

        // Check the indent of the first line.
        $startColumn   = $tokens[$stackPtr]['column'];
        $contentColumn = $tokens[$firstContent]['column'];
        if ($contentColumn !== $startColumn) {
            $error = 'First line of embedded PHP code must be indented %s spaces; %s found';
            $data  = array(
                      $startColumn,
                      $contentColumn,
                     );
            $phpcsFile->addError($error, $firstContent, 'Indent', $data);
        }

        // Check for a blank line at the bottom.
        $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($closingTag - 1), ($stackPtr + 1), true);
        if ($tokens[$lastContent]['line'] < ($tokens[$closingTag]['line'] - 1)) {
            // Find a token on the blank line to throw the error on.
            $i = $closingTag;
            do {
                $i--;
            } while ($tokens[$i]['line'] !== ($tokens[$closingTag]['line'] - 1));

            $error = 'Blank line found at end of embedded PHP content';
            $phpcsFile->addError($error, $i, 'SpacingAfter');
        } else if ($tokens[$lastContent]['line'] === $tokens[$closingTag]['line']) {
            $error = 'Closing PHP tag must be on a line by itself';
            $phpcsFile->addError($error, $closingTag, 'ContentAfterEnd');
        }

    }//end _validateMultilineEmbeddedPhp()


    /**
     * Validates embedded PHP that exists on one line.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    private function _validateInlineEmbeddedPhp(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // We only want one line PHP sections, so return if the closing tag is
        // on the next line.
        $closeTag = $phpcsFile->findNext(array(T_CLOSE_TAG), $stackPtr, null, false);
        if ($tokens[$stackPtr]['line'] !== $tokens[$closeTag]['line']) {
            return;
        }

        // Check that there is one, and only one space at the start of the statement.
        $firstContent = $phpcsFile->findNext(array(T_WHITESPACE), ($stackPtr + 1), null, true);

        if ($firstContent === false || $tokens[$firstContent]['code'] === T_CLOSE_TAG) {
            $error = 'Empty embedded PHP tag found';
            $phpcsFile->addError($error, $stackPtr, 'Empty');
            return;
        }

        $leadingSpace = '';
        for ($i = ($stackPtr + 1); $i < $firstContent; $i++) {
            $leadingSpace .= $tokens[$i]['content'];
        }

        if (strlen($leadingSpace) >= 1) {
            $error = 'Expected 1 space after opening PHP tag; %s found';
            $data  = array((strlen($leadingSpace) + 1));
            $phpcsFile->addError($error, $stackPtr, 'SpacingAfterOpen', $data);
        }

        $semiColonCount = 0;
        $semiColon      = $stackPtr;
        $lastSemiColon  = $semiColon;

        while (($semiColon = $phpcsFile->findNext(array(T_SEMICOLON), ($semiColon + 1), $closeTag)) !== false) {
            $lastSemiColon = $semiColon;
            $semiColonCount++;
        }

        $semiColon = $lastSemiColon;
        $error     = '';

        // Make sure there is atleast 1 semicolon.
        if ($semiColonCount === 0) {
            $error = 'Inline PHP statement must end with a semicolon';
            $phpcsFile->addError($error, $stackPtr, 'NoSemicolon');
            return;
        }

        // Make sure that there aren't more semicolons than are allowed.
        if ($semiColonCount > 1) {
            $error = 'Inline PHP statement must contain one statement per line; %s found';
            $data  = array($semiColonCount);
            $phpcsFile->addError($error, $stackPtr, 'MultipleStatements', $data);
        }

        // The statement contains only 1 semicolon, now it must be spaced properly.
        $whitespace = '';
        for ($i = ($semiColon + 1); $i < $closeTag; $i++) {
            if ($tokens[$i]['code'] !== T_WHITESPACE) {
                $error = 'Expected 1 space before closing PHP tag; 0 found';
                $phpcsFile->addError($error, $stackPtr, 'NoSpaceBeforeClose');
                return;
            }

            $whitespace .= $tokens[$i]['content'];
        }

        if (strlen($whitespace) === 1) {
            return;
        }

        if (strlen($whitespace) === 0) {
            $error = 'Expected 1 space before closing PHP tag; 0 found';
            $phpcsFile->addError($error, $stackPtr, 'NoSpaceBeforeClose');
        } else {
            $error = 'Expected 1 space before closing PHP tag; %s found';
            $data  = array(strlen($whitespace));
            $phpcsFile->addError($error, $stackPtr, 'SpacingBeforeClose', $data);
        }

    }//end _validateInlineEmbeddedPhp()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_PHP_DiscouragedFunctionsSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('Generic_Sniffs_PHP_ForbiddenFunctionsSniff', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class Generic_Sniffs_PHP_ForbiddenFunctionsSniff not found');
}

/**
 * Squiz_Sniffs_PHP_DiscouragedFunctionsSniff.
 *
 * Discourages the use of debug functions.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_PHP_DiscouragedFunctionsSniff extends Generic_Sniffs_PHP_ForbiddenFunctionsSniff
{

    /**
     * A list of forbidden functions with their alternatives.
     *
     * The value is NULL if no alternative exists. IE, the
     * function should just not be used.
     *
     * @var array(string => string|null)
     */
    protected $forbiddenFunctions = array(
                                     'error_log' => null,
                                     'print_r'   => null,
                                    );

    /**
     * If true, an error will be thrown; otherwise a warning.
     *
     * @var bool
     */
    public $error = false;

}//end class

?>
<?php
/**
 * Squiz_Sniffs_PHP_HeredocSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_PHP_HeredocSniff.
 *
 * Heredocs are prohibited. This test enforces that.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_PHP_HeredocSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_START_HEREDOC,
                T_START_NOWDOC,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $error = 'Use of heredoc and nowdoc syntax ("<<<") is not allowed; use standard strings or inline HTML instead';
        $phpcsFile->addError($error, $stackPtr, 'NotAllowed');

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_PHP_EvalSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_PHP_EvalSniff.
 *
 * The use of eval() is discouraged.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_PHP_EvalSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_EVAL);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $error = 'Use of eval() is discouraged';
        $phpcsFile->addWarning($error, $stackPtr, 'Discouraged');

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_PHP_DisallowSizeFunctionsInLoopsSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_PHP_DisallowSizeFunctionsInLoopsSniff.
 *
 * Bans the use of size-based functions in loop conditions.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_PHP_DisallowSizeFunctionsInLoopsSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                  );

    /**
     * An array of functions we don't want in the condition of loops.
     *
     * @return array
     */
    protected $forbiddenFunctions = array(
                                     'PHP' => array(
                                               'sizeof',
                                               'strlen',
                                               'count',
                                              ),
                                     'JS'  => array('length'),
                                    );


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_WHILE,
                T_FOR,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens       = $phpcsFile->getTokens();
        $tokenizer    = $phpcsFile->tokenizerType;
        $openBracket  = $tokens[$stackPtr]['parenthesis_opener'];
        $closeBracket = $tokens[$stackPtr]['parenthesis_closer'];

        if ($tokens[$stackPtr]['code'] === T_FOR) {
            // We only want to check the condition in FOR loops.
            $start = $phpcsFile->findNext(T_SEMICOLON, ($openBracket + 1));
            $end   = $phpcsFile->findPrevious(T_SEMICOLON, ($closeBracket - 1));
        } else {
            $start = $openBracket;
            $end   = $closeBracket;
        }

        for ($i = ($start + 1); $i < $end; $i++) {
            if ($tokens[$i]['code'] === T_STRING && in_array($tokens[$i]['content'], $this->forbiddenFunctions[$tokenizer])) {
                $functionName = $tokens[$i]['content'];
                if ($tokenizer === 'JS') {
                    // Needs to be in the form object.function to be valid.
                    $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($i - 1), null, true);
                    if ($prev === false || $tokens[$prev]['code'] !== T_OBJECT_OPERATOR) {
                        continue;
                    }

                    $functionName = 'object.'.$functionName;
                } else {
                    // Make sure it isn't a member var.
                    if ($tokens[($i - 1)]['code'] === T_OBJECT_OPERATOR) {
                        continue;
                    }

                    $functionName .= '()';
                }

                $error = 'The use of %s inside a loop condition is not allowed; assign the return value to a variable and use the variable in the loop condition instead';
                $data  = array($functionName);
                $phpcsFile->addError($error, $i, 'Found', $data);
            }//end if
        }//end for

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_PHP_InnerFunctionsSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_PHP_InnerFunctionsSniff.
 *
 * Ensures that functions within functions are never used.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_PHP_InnerFunctionsSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_FUNCTION);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if ($phpcsFile->hasCondition($stackPtr, T_FUNCTION) === true) {
            $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
            if ($tokens[$prev]['code'] === T_EQUAL) {
                // Ignore closures.
                return;
            }

            $error = 'The use of inner functions is forbidden';
            $phpcsFile->addError($error, $stackPtr, 'NotAllowed');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_PHP_DisallowBooleanStatementSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_PHP_DisallowBooleanStatementSniff.
 *
 * Ensures that boolean operators are only used inside control structure conditions.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_PHP_DisallowBooleanStatementSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return PHP_CodeSniffer_Tokens::$booleanOperators;

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();
        if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) {
            $foundOwner = false;
            foreach ($tokens[$stackPtr]['nested_parenthesis'] as $open => $close) {
                if (isset($tokens[$open]['parenthesis_owner']) === true) {
                    // Any owner means we are not just a simple statement.
                    return;
                }
            }
        }

        $error = 'Boolean operators are not allowed outside of control structure conditions';
        $phpcsFile->addError($error, $stackPtr, 'Found');

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_PHP_CommentedOutCodeSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_PHP_CommentedOutCodeSniff.
 *
 * Warn about commented out code.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_PHP_CommentedOutCodeSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'CSS',
                                  );

    /**
     * If a comment is more than $maxPercentage% code, a warning will be shown.
     *
     * @var int
     */
    public $maxPercentage = 35;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return PHP_CodeSniffer_Tokens::$commentTokens;

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Process whole comment blocks at once, so skip all but the first token.
        if ($stackPtr > 0 && $tokens[$stackPtr]['code'] === $tokens[($stackPtr - 1)]['code']) {
            return;
        }

        // Ignore comments at the end of code blocks.
        if (substr($tokens[$stackPtr]['content'], 0, 6) === '//end ') {
            return;
        }

        $content = '';
        if ($phpcsFile->tokenizerType === 'PHP') {
            $content = '<?php ';
        }

        for ($i = $stackPtr; $i < $phpcsFile->numTokens; $i++) {
            if ($tokens[$stackPtr]['code'] !== $tokens[$i]['code']) {
                break;
            }

            /*
                Trim as much off the comment as possible so we don't
                have additional whitespace tokens or comment tokens
            */

            $tokenContent = trim($tokens[$i]['content']);

            if (substr($tokenContent, 0, 2) === '//') {
                $tokenContent = substr($tokenContent, 2);
            }

            if (substr($tokenContent, 0, 1) === '#') {
                $tokenContent = substr($tokenContent, 1);
            }

            if (substr($tokenContent, 0, 3) === '/**') {
                $tokenContent = substr($tokenContent, 3);
            }

            if (substr($tokenContent, 0, 2) === '/*') {
                $tokenContent = substr($tokenContent, 2);
            }

            if (substr($tokenContent, -2) === '*/') {
                $tokenContent = substr($tokenContent, 0, -2);
            }

            if (substr($tokenContent, 0, 1) === '*') {
                $tokenContent = substr($tokenContent, 1);
            }

            $content .= $tokenContent.$phpcsFile->eolChar;
        }//end for

        $content = trim($content);

        if ($phpcsFile->tokenizerType === 'PHP') {
            $content .= ' ?>';
        }

        // Quite a few comments use multiple dashes, equals signs etc
        // to frame comments and licence headers.
        $content = preg_replace('/[-=*]+/', '-', $content);

        // Because we are not really parsing code, the tokenizer can throw all sorts
        // of errors that don't mean anything, so ignore them.
        $oldErrors = ini_get('error_reporting');
        ini_set('error_reporting', 0);
        $stringTokens = PHP_CodeSniffer_File::tokenizeString($content, $phpcsFile->tokenizer, $phpcsFile->eolChar);
        ini_set('error_reporting', $oldErrors);

        $emptyTokens = array(
                        T_WHITESPACE,
                        T_STRING,
                        T_STRING_CONCAT,
                        T_ENCAPSED_AND_WHITESPACE,
                        T_NONE,
                       );

        $numTokens = count($stringTokens);

        /*
            We know what the first two and last two tokens should be
            (because we put them there) so ignore this comment if those
            tokens were not parsed correctly. It obviously means this is not
            valid code.
        */

        // First token is always the opening PHP tag.
        if ($stringTokens[0]['code'] !== T_OPEN_TAG) {
            return;
        }

        // Last token is always the closing PHP tag, unless something went wrong.
        if (isset($stringTokens[($numTokens - 1)]) === false
            || $stringTokens[($numTokens - 1)]['code'] !== T_CLOSE_TAG
        ) {
            return;
        }

        // Second last token is always whitespace or a comment, depending
        // on the code inside the comment.
        if (in_array($stringTokens[($numTokens - 2)]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
            return;
        }

        $numComment  = 0;
        $numPossible = 0;
        $numCode     = 0;

        for ($i = 0; $i < $numTokens; $i++) {
            if (in_array($stringTokens[$i]['code'], $emptyTokens) === true) {
                // Looks like comment.
                $numComment++;
            } else if (in_array($stringTokens[$i]['code'], PHP_CodeSniffer_Tokens::$comparisonTokens)
                || in_array($stringTokens[$i]['code'], PHP_CodeSniffer_Tokens::$arithmeticTokens)
            ) {
                // Commented out HTML/XML and other docs contain a lot of these
                // characters, so it is best to not use them directly.
                $numPossible++;
            } else {
                // Looks like code.
                $numCode++;
            }
        }

        // We subtract 3 from the token number so we ignore the start/end tokens
        // and their surrounding whitespace. We take 2 off the number of code
        // tokens so we ignore the start/end tokens.
        if ($numTokens > 3) {
            $numTokens -= 3;
        }

        if ($numCode >= 2) {
            $numCode -= 2;
        }

        $percentCode = ceil((($numCode / $numTokens) * 100));
        if ($percentCode > $this->maxPercentage) {
            // Just in case.
            $percentCode = min(100, $percentCode);

            $error = 'This comment is %s%% valid code; is this commented out code?';
            $data  = array($percentCode);
            $phpcsFile->addWarning($error, $stackPtr, 'Found', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_PHP_InnerFunctionsSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_PHP_NonExecutableCodeSniff.
 *
 * Warns about code that can never been executed. This happens when a function
 * returns before the code, or a break ends execution of a statement etc.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_PHP_NonExecutableCodeSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_BREAK,
                T_CONTINUE,
                T_RETURN,
                T_THROW,
                T_EXIT,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // If this token is preceded with an "or", it only relates to one line
        // and should be ignored. For example: fopen() or die().
        $prev = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr - 1), null, true);
        if ($tokens[$prev]['code'] === T_LOGICAL_OR) {
            return;
        }

        // Check if this token is actually part of a one-line IF or ELSE statement.
        for ($i = ($stackPtr - 1); $i > 0; $i--) {
            if ($tokens[$i]['code'] === T_CLOSE_PARENTHESIS) {
                $i = $tokens[$i]['parenthesis_opener'];
                continue;
            } else if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === true) {
                continue;
            }

            break;
        }

        if ($tokens[$i]['code'] === T_IF
            || $tokens[$i]['code'] === T_ELSE
            || $tokens[$i]['code'] === T_ELSEIF
        ) {
            return;
        }

        if ($tokens[$stackPtr]['code'] === T_RETURN) {
            $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
            if ($tokens[$next]['code'] === T_SEMICOLON) {
                $next = $phpcsFile->findNext(T_WHITESPACE, ($next + 1), null, true);
                if ($tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET) {
                    // If this is the closing brace of a function
                    // then this return statement doesn't return anything
                    // and is not required anyway.
                    $owner = $tokens[$next]['scope_condition'];
                    if ($tokens[$owner]['code'] === T_FUNCTION) {
                        $warning = 'Empty return statement not required here';
                        $phpcsFile->addWarning($warning, $stackPtr, 'ReturnNotRequired');
                        return;
                    }
                }
            }
        }

        if (isset($tokens[$stackPtr]['scope_opener']) === true) {
            $owner = $tokens[$stackPtr]['scope_condition'];
            if ($tokens[$owner]['code'] === T_CASE || $tokens[$owner]['code'] === T_DEFAULT) {
                // This token closes the scope of a CASE or DEFAULT statement
                // so any code between this token and the next CASE, DEFAULT or
                // end of SWITCH token will not be executable.
                $next = $phpcsFile->findNext(
                    array(
                     T_CASE,
                     T_DEFAULT,
                     T_CLOSE_CURLY_BRACKET,
                    ),
                    ($stackPtr + 1)
                );

                if ($next !== false) {
                    $end      = $phpcsFile->findNext(array(T_SEMICOLON), ($stackPtr + 1));
                    $lastLine = $tokens[$end]['line'];
                    for ($i = ($stackPtr + 1); $i < $next; $i++) {
                        if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === true) {
                            continue;
                        }

                        $line = $tokens[$i]['line'];
                        if ($line > $lastLine) {
                            $type    = substr($tokens[$stackPtr]['type'], 2);
                            $warning = 'Code after %s statement cannot be executed';
                            $data    = array($type);
                            $phpcsFile->addWarning($warning, $i, 'Unreachable', $data);
                            $lastLine = $line;
                        }
                    }
                }//end if

                // That's all we have to check for these types of statements.
                return;
            }
        }//end if

        // This token may be part of an inline condition.
        // If we find a closing parenthesis that belongs to a condition
        // we should ignore this token.
        $prev = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr - 1), null, true);
        if (isset($tokens[$prev]['parenthesis_owner']) === true) {
            $owner  = $tokens[$prev]['parenthesis_owner'];
            $ignore = array(
                       T_IF,
                       T_ELSE,
                       T_ELSEIF,
                      );
            if (in_array($tokens[$owner]['code'], $ignore) === true) {
                return;
            }
        }

        $ourConditions = array_keys($tokens[$stackPtr]['conditions']);

        if (empty($ourConditions) === false) {
            $condition = array_pop($ourConditions);

            if (isset($tokens[$condition]['scope_closer']) === false) {
                return;
            }

            // Special case for BREAK statements sitting directly inside SWITCH
            // statements. If we get to this point, we know the BREAK is not being
            // used to close a CASE statement, so it is most likely non-executable
            // code itself (as is the case when you put return; break; at the end of
            // a case). So we need to ignore this token.
            if ($tokens[$condition]['code'] === T_SWITCH
                && $tokens[$stackPtr]['code'] === T_BREAK
            ) {
                return;
            }

            $closer = $tokens[$condition]['scope_closer'];

            // If the closer for our condition is shared with other openers,
            // we will need to throw errors from this token to the next
            // shared opener (if there is one), not to the scope closer.
            $nextOpener = null;
            for ($i = ($stackPtr + 1); $i < $closer; $i++) {
                if (isset($tokens[$i]['scope_closer']) === true) {
                    if ($tokens[$i]['scope_closer'] === $closer) {
                        // We found an opener that shares the same
                        // closing token as us.
                        $nextOpener = $i;
                        break;
                    }
                }
            }//end for

            if ($nextOpener === null) {
                $end = $closer;
            } else {
                $end = ($nextOpener - 1);
            }
        } else {
            // This token is in the global scope.
            if ($tokens[$stackPtr]['code'] === T_BREAK) {
                return;
            }

            // Throw an error for all lines until the end of the file.
            $end = ($phpcsFile->numTokens - 1);
        }//end if

        // Find the semicolon that ends this statement, skipping
        // nested statements like FOR loops and closures.
        for ($start = ($stackPtr + 1); $start < $phpcsFile->numTokens; $start++) {
            if ($start === $end) {
                break;
            }

            if ($tokens[$start]['code'] === T_OPEN_PARENTHESIS) {
                $start = $tokens[$start]['parenthesis_closer'];
                continue;
            }

            if ($tokens[$start]['code'] === T_OPEN_CURLY_BRACKET) {
                $start = $tokens[$start]['bracket_closer'];
                continue;
            }

            if ($tokens[$start]['code'] === T_SEMICOLON) {
                break;
            }
        }//end for

        $lastLine = $tokens[$start]['line'];
        for ($i = ($start + 1); $i < $end; $i++) {
            if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === true
                || in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$bracketTokens) === true
            ) {
                continue;
            }

            // Skip whole functions and classes/interfaces because they are not
            // technically executed code, but rather declarations that may be used.
            if ($tokens[$i]['code'] === T_FUNCTION
                || $tokens[$i]['code'] === T_CLASS
                || $tokens[$i]['code'] === T_INTERFACE
            ) {
                $i = $tokens[$i]['scope_closer'];
                continue;
            }

            $line = $tokens[$i]['line'];
            if ($line > $lastLine) {
                $type    = substr($tokens[$stackPtr]['type'], 2);
                $warning = 'Code after %s statement cannot be executed';
                $data    = array($type);
                $phpcsFile->addWarning($warning, $i, 'Unreachable', $data);
                $lastLine = $line;
            }
        }//end for

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_Formatting_OperationBracketSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Formatting_OperationBracketSniff.
 *
 * Tests that all arithmetic operations are bracketed.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Formatting_OperatorBracketSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array(
                                   'PHP',
                                   'JS',
                                  );


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return PHP_CodeSniffer_Tokens::$operators;

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if ($phpcsFile->tokenizerType === 'JS' && $tokens[$stackPtr]['code'] === T_PLUS) {
            // JavaScript uses the plus operator for string concatenation as well
            // so we cannot accurately determine if it is a string concat or addition.
            // So just ignore it.
            return;
        }

        // If the & is a reference, then we don't want to check for brackets.
        if ($tokens[$stackPtr]['code'] === T_BITWISE_AND && $phpcsFile->isReference($stackPtr) === true) {
            return;
        }

        // There is one instance where brackets aren't needed, which involves
        // the minus sign being used to assign a negative number to a variable.
        if ($tokens[$stackPtr]['code'] === T_MINUS) {
            // Check to see if we are trying to return -n.
            $prev = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr - 1), null, true);
            if ($tokens[$prev]['code'] === T_RETURN) {
                return;
            }

            $number = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
            if ($tokens[$number]['code'] === T_LNUMBER || $tokens[$number]['code'] === T_DNUMBER) {
                $previous = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
                if ($previous !== false) {
                    $isAssignment = in_array($tokens[$previous]['code'], PHP_CodeSniffer_Tokens::$assignmentTokens);
                    $isEquality   = in_array($tokens[$previous]['code'], PHP_CodeSniffer_Tokens::$equalityTokens);
                    $isComparison = in_array($tokens[$previous]['code'], PHP_CodeSniffer_Tokens::$comparisonTokens);
                    if ($isAssignment === true || $isEquality === true || $isComparison === true) {
                        // This is a negative assignment or comparison.
                        // We need to check that the minus and the number are
                        // adjacent.
                        if (($number - $stackPtr) !== 1) {
                            $error = 'No space allowed between minus sign and number';
                            $phpcsFile->addError($error, $stackPtr, 'SpacingAfterMinus');
                        }

                        return;
                    }
                }
            }
        }//end if

        $lastBracket = false;
        if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) {
            $parenthesis = array_reverse($tokens[$stackPtr]['nested_parenthesis'], true);
            foreach ($parenthesis as $bracket => $endBracket) {
                $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, ($bracket - 1), null, true);
                $prevCode  = $tokens[$prevToken]['code'];

                if ($prevCode === T_ISSET) {
                    // This operation is inside an isset() call, but has
                    // no bracket of it's own.
                    break;
                }

                if ($prevCode === T_STRING || $prevCode === T_SWITCH) {
                    // We allow very simple operations to not be bracketed.
                    // For example, ceil($one / $two).
                    $allowed = array(
                                T_VARIABLE,
                                T_LNUMBER,
                                T_DNUMBER,
                                T_STRING,
                                T_WHITESPACE,
                                T_THIS,
                                T_OBJECT_OPERATOR,
                                T_OPEN_SQUARE_BRACKET,
                                T_CLOSE_SQUARE_BRACKET,
                                T_MODULUS,
                               );

                    for ($prev = ($stackPtr - 1); $prev > $bracket; $prev--) {
                        if (in_array($tokens[$prev]['code'], $allowed) === true) {
                            continue;
                        }

                        if ($tokens[$prev]['code'] === T_CLOSE_PARENTHESIS) {
                            $prev = $tokens[$prev]['parenthesis_opener'];
                        } else {
                            break;
                        }
                    }

                    if ($prev !== $bracket) {
                        break;
                    }

                    for ($next = ($stackPtr + 1); $next < $endBracket; $next++) {
                        if (in_array($tokens[$next]['code'], $allowed) === true) {
                            continue;
                        }

                        if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS) {
                            $next = $tokens[$next]['parenthesis_closer'];
                        } else {
                            break;
                        }
                    }

                    if ($next !== $endBracket) {
                        break;
                    }
                }//end if

                if (in_array($prevCode, PHP_CodeSniffer_Tokens::$scopeOpeners) === true) {
                    // This operation is inside a control structure like FOREACH
                    // or IF, but has no bracket of it's own.
                    // The only control structure allowed to do this is SWITCH.
                    if ($prevCode !== T_SWITCH) {
                        break;
                    }
                }

                if ($prevCode === T_OPEN_PARENTHESIS) {
                    // These are two open parenthesis in a row. If the current
                    // one doesn't enclose the operator, go to the previous one.
                    if ($endBracket < $stackPtr) {
                        continue;
                    }
                }

                $lastBracket = $bracket;
                break;
            }//end foreach
        }//end if

        if ($lastBracket === false) {
            // It is not in a bracketed statement at all.
            $previousToken = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true, null, true);
            if ($previousToken !== false) {
                // A list of tokens that indicate that the token is not
                // part of an arithmetic operation.
                $invalidTokens = array(
                                  T_COMMA,
                                  T_COLON,
                                  T_OPEN_PARENTHESIS,
                                  T_OPEN_SQUARE_BRACKET,
                                  T_CASE,
                                 );

                if (in_array($tokens[$previousToken]['code'], $invalidTokens) === false) {
                    $error = 'Arithmetic operation must be bracketed';
                    $phpcsFile->addError($error, $stackPtr, 'MissingBrackets');
                }

                return;
            }
        } else if ($tokens[$lastBracket]['parenthesis_closer'] < $stackPtr) {
            // There are a set of brackets in front of it that don't include it.
            $error = 'Arithmetic operation must be bracketed';
            $phpcsFile->addError($error, $stackPtr, 'MissingBrackets');
            return;
        } else {
            // We are enclosed in a set of bracket, so the last thing to
            // check is that we are not also enclosed in square brackets
            // like this: ($array[$index + 1]), which is invalid.
            $brackets = array(
                         T_OPEN_SQUARE_BRACKET,
                         T_CLOSE_SQUARE_BRACKET,
                        );

            $squareBracket = $phpcsFile->findPrevious($brackets, ($stackPtr - 1), $lastBracket);
            if ($squareBracket !== false && $tokens[$squareBracket]['code'] === T_OPEN_SQUARE_BRACKET) {
                $closeSquareBracket = $phpcsFile->findNext($brackets, ($stackPtr + 1));
                if ($closeSquareBracket !== false && $tokens[$closeSquareBracket]['code'] === T_CLOSE_SQUARE_BRACKET) {
                    $error = 'Arithmetic operation must be bracketed';
                    $phpcsFile->addError($error, $stackPtr, 'MissingBrackets');
                }
            }

            return;
        }//end if

        $lastAssignment = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$assignmentTokens, $stackPtr, null, false, null, true);
        if ($lastAssignment !== false && $lastAssignment > $lastBracket) {
            $error = 'Arithmetic operation must be bracketed';
            $phpcsFile->addError($error, $stackPtr, 'MissingBrackets');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_Classes_ClassFileNameSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_Standards_AbstractScopeSniff', true) === false) {
    $error = 'Class PHP_CodeSniffer_Standards_AbstractScopeSniff not found';
    throw new PHP_CodeSniffer_Exception($error);
}

/**
 * Tests self member references.
 *
 * Verifies that :
 * <ul>
 *  <li>self:: is used instead of Self::</li>
 *  <li>self:: is used for local static member reference</li>
 *  <li>self:: is used instead of self ::</li>
 * </ul>
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Classes_SelfMemberReferenceSniff extends PHP_CodeSniffer_Standards_AbstractScopeSniff
{


    /**
     * Constructs a Squiz_Sniffs_Classes_SelfMemberReferenceSniff.
     */
    public function __construct()
    {
        parent::__construct(array(T_CLASS), array(T_DOUBLE_COLON));

    }//end __construct()


    /**
     * Processes the function tokens within the class.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
     * @param int                  $stackPtr  The position where the token was found.
     * @param int                  $currScope The current scope opener token.
     *
     * @return void
     */
    protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope)
    {
        $tokens = $phpcsFile->getTokens();

        $className = ($stackPtr - 1);
        if ($tokens[$className]['code'] === T_SELF) {
            if (strtolower($tokens[$className]['content']) !== $tokens[$className]['content']) {
                $error = 'Must use "self::" for local static member reference; found "%s::"';
                $data  = array($tokens[$className]['content']);
                $phpcsFile->addError($error, $className, 'IncorrectCase', $data);
                return;
            }
        } else if ($tokens[$className]['code'] === T_STRING) {
            // Make sure this is another class reference.
            $declarationName        = $phpcsFile->getDeclarationName($currScope);
            $fullQualifiedClassName = $tokens[$className]['content'];

            // If the class is called with a namespace prefix, build fully qualified
            // namespace calls for both current scope class and requested class.
            if ($tokens[($className - 1)]['code'] === T_NS_SEPARATOR) {
                $declarationName         = $this->getDeclarationNameWithNamespace($tokens, $className);
                $declarationName         = substr($declarationName, 1);
                $fullQualifiedClassName  = $this->getNamespaceOfScope($phpcsFile, $currScope);
                $fullQualifiedClassName .= '\\'.$tokens[$className]['content'];
            }

            if ($declarationName === $fullQualifiedClassName) {
                // Class name is the same as the current class, which is not allowed
                // except if being used inside a closure.
                if ($phpcsFile->hasCondition($stackPtr, T_CLOSURE) === false) {
                    $error = 'Must use "self::" for local static member reference';
                    $phpcsFile->addError($error, $className, 'NotUsed');
                    return;
                }
            }
        }//end if

        if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) {
            $found = strlen($tokens[($stackPtr - 1)]['content']);
            $error = 'Expected 0 spaces before double colon; %s found';
            $data  = array($found);
            $phpcsFile->addError($error, $className, 'SpaceBefore', $data);
        }

        if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) {
            $found = strlen($tokens[($stackPtr + 1)]['content']);
            $error = 'Expected 0 spaces after double colon; %s found';
            $data  = array($found);
            $phpcsFile->addError($error, $className, 'SpaceAfter', $data);
        }

    }//end processTokenWithinScope()


    /**
     * Returns the declaration names for classes/interfaces/functions with a namespace.
     *
     * @param array $tokens   Token stack for this file
     * @param int   $stackPtr The position where the namespace building will start.
     *
     * @return string
     */
    protected function getDeclarationNameWithNamespace(array $tokens, $stackPtr)
    {
        $nameParts      = array();
        $currentPointer = $stackPtr;
        while ($tokens[$currentPointer]['code'] === T_NS_SEPARATOR
            || $tokens[$currentPointer]['code'] === T_STRING
        ) {
            $nameParts[] = $tokens[$currentPointer]['content'];
            $currentPointer--;
        }

        $nameParts = array_reverse($nameParts);
        return implode('', $nameParts);

    }//end getDeclarationNameWithNamespace()


    /**
     * Returns the namespace declaration of a file.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
     * @param int                  $stackPtr  The position where the search for the
     *                                        namespace declaration will start.
     *
     * @return string
     */
    protected function getNamespaceOfScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $namespace = '\\';
        $namespaceDeclaration = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr);

        if ($namespaceDeclaration !== false) {
            $endOfNamespaceDeclaration = $phpcsFile->findNext(T_SEMICOLON, $namespaceDeclaration);
            $namespace = $this->getDeclarationNameWithNamespace(
                $phpcsFile->getTokens(),
                ($endOfNamespaceDeclaration - 1)
            );
        }

        return $namespace;

    }//end getNamespaceOfScope


}//end class

?>
<?php
/**
 * Squiz_Sniffs_Classes_ClassFileNameSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Classes_ClassFileNameSniff.
 *
 * Tests that the file name and the name of the class contained within the file
 * match.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Classes_ClassFileNameSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_CLASS,
                T_INTERFACE,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $fullPath = basename($phpcsFile->getFilename());
        $fileName = substr($fullPath, 0, strrpos($fullPath, '.'));
        if ($fileName === '') {
            // No filename probably means STDIN, so we can't do this check.
            return;
        }

        $tokens  = $phpcsFile->getTokens();
        $decName = $phpcsFile->findNext(T_STRING, $stackPtr);

        if ($tokens[$decName]['content'] !== $fileName) {
            $error = '%s name doesn\'t match filename; expected "%s %s"';
            $data  = array(
                      ucfirst($tokens[$stackPtr]['content']),
                      $tokens[$stackPtr]['content'],
                      $fileName,
                     );
            $phpcsFile->addError($error, $stackPtr, 'NoMatch', $data);
        }

    }//end process()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_Classes_ValidClassNameSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Classes_ValidClassNameSniff.
 *
 * Ensures classes are in camel caps, and the first letter is capitalised
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Classes_ValidClassNameSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_CLASS,
                T_INTERFACE,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The current file being processed.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if (isset($tokens[$stackPtr]['scope_opener']) === false) {
            $error = 'Possible parse error: %s missing opening or closing brace';
            $data  = array($tokens[$stackPtr]['content']);
            $phpcsFile->addWarning($error, $stackPtr, 'MissingBrace', $data);
            return;
        }

        // Determine the name of the class or interface. Note that we cannot
        // simply look for the first T_STRING because a class name
        // starting with the number will be multiple tokens.
        $opener    = $tokens[$stackPtr]['scope_opener'];
        $nameStart = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), $opener, true);
        $nameEnd   = $phpcsFile->findNext(T_WHITESPACE, $nameStart, $opener);
        $name      = trim($phpcsFile->getTokensAsString($nameStart, ($nameEnd - $nameStart)));

        // Check for camel caps format.
        $valid = PHP_CodeSniffer::isCamelCaps($name, true, true, false);
        if ($valid === false) {
            $type  = ucfirst($tokens[$stackPtr]['content']);
            $error = '%s name "%s" is not in camel caps format';
            $data  = array(
                      $type,
                      $name,
                     );
            $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $data);
        }

    }//end process()


}//end class


?>
<?php
/**
 * Class Declaration Test.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PSR2_Sniffs_Classes_ClassDeclarationSniff', true) === false) {
    $error = 'Class PSR2_Sniffs_Classes_ClassDeclarationSniff not found';
    throw new PHP_CodeSniffer_Exception($error);
}

/**
 * Class Declaration Test.
 *
 * Checks the declaration of the class and its inheritance is correct.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Classes_ClassDeclarationSniff extends PSR2_Sniffs_Classes_ClassDeclarationSniff
{


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                         in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        // We want all the errors from the PSR2 standard, plus some of our own.
        parent::process($phpcsFile, $stackPtr);

        $tokens = $phpcsFile->getTokens();

        // Check that this is the only class or interface in the file.
        $nextClass = $phpcsFile->findNext(array(T_CLASS, T_INTERFACE), ($stackPtr + 1));
        if ($nextClass !== false) {
            // We have another, so an error is thrown.
            $error = 'Only one interface or class is allowed in a file';
            $phpcsFile->addError($error, $nextClass, 'MultipleClasses');
        }

    }//end process()

    
    /**
     * Processes the opening section of a class declaration.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function processOpen(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        parent::processOpen($phpcsFile, $stackPtr);

        $tokens = $phpcsFile->getTokens();

        if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) {
            $prevContent = $tokens[($stackPtr - 1)]['content'];
            if ($prevContent !== $phpcsFile->eolChar) {
                $blankSpace = substr($prevContent, strpos($prevContent, $phpcsFile->eolChar));
                $spaces     = strlen($blankSpace);

                if (in_array($tokens[($stackPtr - 2)]['code'], array(T_ABSTRACT, T_FINAL)) === false) {
                    if ($spaces !== 0) {
                        $type  = strtolower($tokens[$stackPtr]['content']);
                        $error = 'Expected 0 spaces before %s keyword; %s found';
                        $data  = array(
                                  $type,
                                  $spaces,
                                 );
                        $phpcsFile->addError($error, $stackPtr, 'SpaceBeforeKeyword', $data);
                    }
                }
            }
        }//end if

    }//end processOpen()


    /**
     * Processes the closing section of a class declaration.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function processClose(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $closeBrace = $tokens[$stackPtr]['scope_closer'];
        if ($tokens[($closeBrace - 1)]['code'] === T_WHITESPACE) {
            $prevContent = $tokens[($closeBrace - 1)]['content'];
            if ($prevContent !== $phpcsFile->eolChar) {
                $blankSpace = substr($prevContent, strpos($prevContent, $phpcsFile->eolChar));
                $spaces     = strlen($blankSpace);
                if ($spaces !== 0) {
                    if ($tokens[($closeBrace - 1)]['line'] !== $tokens[$closeBrace]['line']) {
                        $error = 'Expected 0 spaces before closing brace; newline found';
                        $phpcsFile->addError($error, $closeBrace, 'NewLineBeforeCloseBrace');
                    } else {
                        $error = 'Expected 0 spaces before closing brace; %s found';
                        $data  = array($spaces);
                        $phpcsFile->addError($error, $closeBrace, 'SpaceBeforeCloseBrace', $data);
                    }
                }
            }
        }

        // Check that the closing brace has one blank line after it.
        $nextContent = $phpcsFile->findNext(array(T_WHITESPACE, T_COMMENT), ($closeBrace + 1), null, true);
        if ($nextContent === false) {
            // No content found, so we reached the end of the file.
            // That means there was no closing tag either.
            $error = 'Closing brace of a %s must be followed by a blank line and then a closing PHP tag';
            $data  = array($tokens[$stackPtr]['content']);
            $phpcsFile->addError($error, $closeBrace, 'EndFileAfterCloseBrace', $data);
        } else {
            $nextLine  = $tokens[$nextContent]['line'];
            $braceLine = $tokens[$closeBrace]['line'];
            if ($braceLine === $nextLine) {
                $error = 'Closing brace of a %s must be followed by a single blank line';
                $data  = array($tokens[$stackPtr]['content']);
                $phpcsFile->addError($error, $closeBrace, 'NoNewlineAfterCloseBrace', $data);
            } else if ($nextLine !== ($braceLine + 2)) {
                $difference = ($nextLine - $braceLine - 1);
                $error      = 'Closing brace of a %s must be followed by a single blank line; found %s';
                $data       = array(
                               $tokens[$stackPtr]['content'],
                               $difference,
                              );
                $phpcsFile->addError($error, $closeBrace, 'NewlinesAfterCloseBrace', $data);
            }
        }//end if

        // Check the closing brace is on it's own line, but allow
        // for comments like "//end class".
        $nextContent = $phpcsFile->findNext(T_COMMENT, ($closeBrace + 1), null, true);
        if ($tokens[$nextContent]['content'] !== $phpcsFile->eolChar && $tokens[$nextContent]['line'] === $tokens[$closeBrace]['line']) {
            $type  = strtolower($tokens[$stackPtr]['content']);
            $error = 'Closing %s brace must be on a line by itself';
            $data  = array($tokens[$stackPtr]['content']);
            $phpcsFile->addError($error, $closeBrace, 'CloseBraceSameLine', $data);
        }

    }//end processClose()


}//end class

?>
<?php
/**
 * Squiz_Sniffs_Classes_DuplicatePropertySniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Classes_DuplicatePropertySniff.
 *
 * Ensures JS classes don't contain duplicate property names.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Classes_DuplicatePropertySniff implements PHP_CodeSniffer_Sniff
{

    /**
     * A list of tokenizers this sniff supports.
     *
     * @var array
     */
    public $supportedTokenizers = array('JS');


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_OBJECT);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The current file being processed.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();
        $start  = $tokens[$stackPtr]['scope_opener'];
        $end    = $tokens[$stackPtr]['scope_closer'];

        $properties   = array();
        $wantedTokens = array(
                         T_PROPERTY,
                         T_OPEN_CURLY_BRACKET,
                        );

        $next = $phpcsFile->findNext($wantedTokens, ($start + 1), $end);
        while ($next !== false && $next < $end) {
            // Skip nested objects.
            if ($tokens[$next]['code'] === T_OPEN_CURLY_BRACKET) {
                $next = $tokens[$next]['bracket_closer'];
            } else {
                $propName = $tokens[$next]['content'];
                if (isset($properties[$propName]) === true) {
                    $error = 'Duplicate property definition found for "%s"; previously defined on line %s';
                    $data  = array(
                              $propName,
                              $tokens[$properties[$propName]]['line'],
                             );
                    $phpcsFile->addError($error, $next, 'Found', $data);
                }

                $properties[$propName] = $next;
            }//end if

            $next = $phpcsFile->findNext($wantedTokens, ($next + 1), $end);
        }//end while

    }//end process()


}//end class


?>
<?php
/**
 * Squiz_Sniffs_Classes_LowercaseClassKeywordsSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Squiz_Sniffs_Classes_LowercaseClassKeywordsSniff.
 *
 * Ensures all class keywords are lowercase.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Sniffs_Classes_LowercaseClassKeywordsSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_CLASS,
                T_INTERFACE,
                T_TRAIT,
                T_EXTENDS,
                T_IMPLEMENTS,
                T_ABSTRACT,
                T_FINAL,
                T_VAR,
                T_CONST,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $content = $tokens[$stackPtr]['content'];
        if ($content !== strtolower($content)) {
            $error = '%s keyword must be lowercase; expected "%s" but found "%s"';
            $data  = array(
                      strtoupper($content),
                      strtolower($content),
                      $content,
                     );
            $phpcsFile->addError($error, $stackPtr, 'FoundUppercase', $data);
        }

    }//end process()


}//end class

?>
<documentation title="Static This Usage">
    <standard>
    <![CDATA[
    Static methods should not use $this.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Using self:: to access static variables.">
        <![CDATA[
class Foo
{
    <em>static</em> function bar()
    {
        return <em>self</em>::$staticMember;
    }
}
]]>
        </code>
        <code title="Invalid: Using $this-> to access static variables.">
        <![CDATA[
class Foo
{
    <em>static</em> function bar()
    {
    return <em>$this</em>->$staticMember;
    }
}
]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Array Bracket Spacing">
    <standard>
    <![CDATA[
    When referencing arrays you should not put whitespace around the opening bracket or before the closing bracket.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: No spaces around the brackets.">
        <![CDATA[
$foo<em></em>[<em></em>'bar'<em></em>];
]]>
        </code>
        <code title="Invalid: Spaces around the brackets.">
        <![CDATA[
$foo<em> </em>[<em> </em>'bar'<em> </em>];
]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Array Declarations">
    <standard>
    <![CDATA[
    This standard covers all array declarations, regardless of the number and type of values contained within the array.
    ]]>
    </standard>
    <standard>
    <![CDATA[
    The <em>array</em> keyword must be lowercase.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: array keyword lowercase">
        <![CDATA[
$array = <em>a</em>rray('val1', 'val2');
        ]]>
        </code>
        <code title="Invalid: first letter capitalised">
        <![CDATA[
$array = <em>A</em>rray('val1', 'val2');
        ]]>
        </code>
    </code_comparison>
    <standard>
    <![CDATA[
    The first array key must begin on the line after the <em>array</em> keyword.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: first key on second line">
        <![CDATA[
$array = array(
          <em>'key1'</em> => 'value1',
          'key2' => 'value2',
         );
        ]]>
        </code>
        <code title="Invalid: first key on same line">
        <![CDATA[
$array = array(<em>'key1'</em> => 'value1',
          'key2' => 'value2',
         );
        ]]>
        </code>
    </code_comparison>
    <standard>
    <![CDATA[
    All array keys must be indented to one space after the start of the <em>array</em> keyword. The closing parenthesis must be aligned with the start of the <em>array</em> keyword.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: aligned correctly">
        <![CDATA[
$array = array(
         <em> </em>'key1' => 'value1',
         <em> </em>'key2' => 'value2',
         );
        ]]>
        </code>
        <code title="Invalid: keys and parenthesis aligned incorrectly">
        <![CDATA[
$array = array(
         <em>'</em>key1' => 'value1',
         <em>'</em>key2' => 'value2',
);
        ]]>
        </code>
    </code_comparison>
    <standard>
    <![CDATA[
    All double arrow symbols must be aligned to one space after the longest array key. Alignment must be achieved using spaces.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: keys and values aligned">
        <![CDATA[
$array = array(
          'keyTen'<em>    </em>=> 'ValueTen',
          'keyTwenty'<em> </em>=> 'ValueTwenty',
         );
        ]]>
        </code>
        <code title="Invalid: alignment incorrect">
        <![CDATA[
$array = array(
          'keyTen'<em> </em>=> 'ValueTen',
          'keyTwenty'<em> </em>=> 'ValueTwenty',
         );
        ]]>
        </code>
    </code_comparison>
    <standard>
    <![CDATA[
    All array values must be followed by a comma, including the final value.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: comma after each value">
        <![CDATA[
$array = array(
          'key1' => 'value1',
          'key2' => 'value2',
          'key3' => 'value3'<em>,</em>
         );
        ]]>
        </code>
        <code title="Invalid: no comma after last value">
        <![CDATA[
$array = array(
          'key1' => 'value1',
          'key2' => 'value2',
          'key3' => 'value3'<em> </em>
         );
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Semicolon Spacing">
    <standard>
    <![CDATA[
    Semicolons should not have spaces before them.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: No space before the semicolon.">
        <![CDATA[
echo "hi"<em></em>;
]]>
        </code>
        <code title="Invalid: Space before the semicolon.">
        <![CDATA[
echo "hi"<em> </em>;
]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Scope Keyword Spacing">
    <standard>
    <![CDATA[
    The php keywords static, public, private, and protected should have one space after them.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: A single space following the keywords.">
        <![CDATA[
public<em> </em>static<em> </em>function foo()
{
}
]]>
        </code>
        <code title="Invalid: Multiple spaces following the keywords.">
        <![CDATA[
public<em>  </em>static<em>  </em>function foo()
{
}
]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Object Operator Spacing">
    <standard>
    <![CDATA[
    The object operator (->) should not have any space around it.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: No spaces around the object operator.">
        <![CDATA[
$foo<em></em>-><em></em>bar();
]]>
        </code>
        <code title="Invalid: Whitespace surrounding the object operator.">
        <![CDATA[
$foo<em> </em>-><em> </em>bar();
]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Cast Whitespace">
    <standard>
    <![CDATA[
    Casts should not have whitespace inside the parentheses.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: No spaces.">
        <![CDATA[
$foo = (<em></em>int<em></em>)'42';
]]>
        </code>
        <code title="Invalid: Whitespace used inside parentheses.">
        <![CDATA[
$foo = (<em> </em>int<em> </em>)'42';
]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Language Construct Whitespace">
    <standard>
    <![CDATA[
    The php constructs echo, print, return, include, include_once, require, require_once, and new should have one space after them.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: echo statement with a single space after it.">
        <![CDATA[
echo<em> </em>"hi";
]]>
        </code>
        <code title="Invalid: echo statement with no space after it.">
        <![CDATA[
echo<em></em>"hi";
]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Function Opening Brace Whitespace">
    <standard>
    <![CDATA[
    The opening brace for functions should be on a new line with no blank lines surrounding it.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Opening brace is on a new line.">
        <![CDATA[
function foo()
<em>{</em>
}
]]>
        </code>
        <code title="Invalid: Opening brace is on the same line as the function declaration.">
        <![CDATA[
function foo() <em>{</em>
}
]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: No blank lines after the opening brace.">
        <![CDATA[
function foo()
{
<em>    return 42;</em>
}
]]>
        </code>
        <code title="Invalid: A blank line after the opening brace.">
        <![CDATA[
function foo()
{
<em></em>
    return 42;
}
]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Lowercase Function Keywords">
    <standard>
    <![CDATA[
    The php keywords function, public, private, protected, and static should be lowercase.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Lowercase function keyword.">
        <![CDATA[
<em>function</em> foo()
{
    return true;
}
]]>
        </code>
        <code title="Invalid: Uppercase function keyword.">
        <![CDATA[
<em>FUNCTION</em> foo()
{
    return true;
}
]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Lowercase Built-In functions">
    <standard>
    <![CDATA[
    All PHP built-in functions should be lowercased when called.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Lowercase function call.">
        <![CDATA[
if (<em>isset</em>($foo)) {
    echo $foo;
}
]]>
        </code>
        <code title="Invalid: isset not called as lowercase.">
        <![CDATA[
if (<em>isSet</em>($foo)) {
    echo $foo;
}
]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="For Loop Declarations">
    <standard>
    <![CDATA[
    In a for loop declaration, there should be no space inside the brackets and there should be 0 spaces before and 1 space after semicolons.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Correct spacing used.">
        <![CDATA[
for (<em></em>$i = 0; $i < 10; $i++<em></em>) {
    echo $i;
}
]]>
        </code>
        <code title="Invalid: Invalid spacing used inside brackets.">
        <![CDATA[
for (<em> </em>$i = 0; $i < 10; $i++<em> </em>) {
    echo $i;
}
]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Correct spacing used.">
        <![CDATA[
for ($i = 0<em></em>; $i < 10<em></em>; $i++) {
    echo $i;
}
]]>
        </code>
        <code title="Invalid: Invalid spacing used before semicolons.">
        <![CDATA[
for ($i = 0<em> </em>; $i < 10<em> </em>; $i++) {
    echo $i;
}
]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Correct spacing used.">
        <![CDATA[
for ($i = 0;<em> </em>$i < 10;<em> </em>$i++) {
    echo $i;
}
]]>
        </code>
        <code title="Invalid: Invalid spacing used after semicolons.">
        <![CDATA[
for ($i = 0;<em></em>$i < 10;<em></em>$i++) {
    echo $i;
}
]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Lowercase Control Structure Keywords">
    <standard>
    <![CDATA[
    The php keywords if, else, elseif, foreach, for, do, switch, while, try, and catch should be lowercase.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Lowercase if keyword.">
        <![CDATA[
<em>if</em> ($foo) {
    $bar = true;
}
]]>
        </code>
        <code title="Invalid: Uppercase if keyword.">
        <![CDATA[
<em>IF</em> ($foo) {
    $bar = true;
}
]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Foreach Loop Declarations">
    <standard>
    <![CDATA[
    There should be a space between each element of a foreach loop and the as keyword should be lowercase.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Correct spacing used.">
        <![CDATA[
foreach (<em></em>$foo<em> </em>as<em> </em>$bar<em> </em>=><em> </em>$baz<em></em>) {
    echo $baz;
}
]]>
        </code>
        <code title="Invalid: Invalid spacing used.">
        <![CDATA[
foreach (<em> </em>$foo<em>  </em>as<em>  </em>$bar<em></em>=><em></em>$baz<em> </em>) {
    echo $baz;
}
]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Lowercase as keyword.">
        <![CDATA[
foreach ($foo <em>as</em> $bar => $baz) {
    echo $baz;
}
]]>
        </code>
        <code title="Invalid: Uppercase as keyword.">
        <![CDATA[
foreach ($foo <em>AS</em> $bar => $baz) {
    echo $baz;
}
]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Doc Comment Alignment">
    <standard>
    <![CDATA[
    The asterisks in a doc comment should align, and there should be one space between the asterisk and tags.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Asterisks are aligned.">
        <![CDATA[
/**
<em> </em>* @see foo()
<em> </em>*/
]]>
        </code>
        <code title="Invalid: Asterisks are not aligned.">
        <![CDATA[
/**
<em>  </em>* @see foo()
<em></em>*/
]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: One space between asterisk and tag.">
        <![CDATA[
/**
 *<em> </em>@see foo()
 */
]]>
        </code>
        <code title="Invalid: Incorrect spacing used.">
        <![CDATA[
/**
 *<em>  </em>@see foo()
 */
]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Doc Comment Throws Tag">
    <standard>
    <![CDATA[
    If a function throws any exceptions, they should be documented in a @throws tag.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: @throws tag used.">
        <![CDATA[
/**
 * <em>@throws Exception all the time</em>
 * @return void
 */
function foo()
{
    throw new Exception('Danger!');
}
]]>
        </code>
        <code title="Invalid: No @throws tag used for throwing function.">
        <![CDATA[
/**
 * @return void
 */
function foo()
{
    throw new Exception('Danger!');
}
]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Echoed Strings">
    <standard>
    <![CDATA[
    Simple strings should not be enclosed in parentheses when being echoed.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Using echo without parentheses.">
        <![CDATA[
echo<em> </em>"Hello";
]]>
        </code>
        <code title="Invalid: Using echo with parentheses.">
        <![CDATA[
echo<em>(</em>"Hello"<em>)</em>;
]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Self Member Reference">
    <standard>
    <![CDATA[
    The self keyword should be used instead of the current class name, should be lowercase, and should not have spaces before or after it.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Lowercase self used.">
        <![CDATA[
<em>self</em>::foo();
]]>
        </code>
        <code title="Invalid: Uppercase self used.">
        <![CDATA[
<em>SELF</em>::foo();
]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Correct spacing used.">
        <![CDATA[
self<em></em>::<em></em>foo();
]]>
        </code>
        <code title="Invalid: Incorrect spacing used.">
        <![CDATA[
self<em> </em>::<em> </em>foo();
]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Self used as reference.">
        <![CDATA[
class Foo
{
    public static function bar()
    {
    }

    public static function baz()
    {
        <em>self</em>::bar();
    }
}
]]>
        </code>
        <code title="Invalid: Local class name used as reference.">
        <![CDATA[
class <em>Foo</em>
{
    public static function bar()
    {
    }

    public static function baz()
    {
        <em>Foo</em>::bar();
    }
}
]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Lowercase Class Keywords">
    <standard>
    <![CDATA[
    The php keywords class, interface, trait, extends, implements, abstract, final, var, and const should be lowercase.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Lowercase class keywords.">
        <![CDATA[
<em>final</em> <em>class</em> Foo <em>extends</em> Bar
{
}
]]>
        </code>
        <code title="Invalid: Initial capitalization of class keywords.">
        <![CDATA[
<em>Final</em> <em>Class</em> Foo <em>Extends</em> Bar
{
}
]]>
        </code>
    </code_comparison>
</documentation>
<?php
/**
 * Unit test class for the JSLint sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the JSLint sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Debug_JSLintUnitTest extends AbstractSniffUnitTest
{


    /**
     * Should this test be skipped for some reason.
     *
     * @return void
     */
    protected function shouldSkipTest()
    {
        $jslPath = PHP_CodeSniffer::getConfigData('jslint_path');
        return (is_null($jslPath));

    }//end shouldSkipTest()


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array();

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                1 => 2,
                2 => 1,
               );

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the JavaScriptLint sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the JavaScriptLint sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Debug_JavaScriptLintUnitTest extends AbstractSniffUnitTest
{


    /**
     * Should this test be skipped for some reason.
     *
     * @return void
     */
    protected function shouldSkipTest()
    {
        $jslPath = PHP_CodeSniffer::getConfigData('jsl_path');
        return (is_null($jslPath));

    }//end shouldSkipTest()


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array();

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                2 => 1,
               );

    }//end getWarningList()


}//end class

?>
alert('hi')
alert('hi');
alert('hi')
alert('hi');
<?php
/**
 * Unit test class for the MemberVarScope sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the MemberVarScope sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Scope_MemberVarScopeUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                7 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the MethodScope sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the MethodScope sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Scope_MethodScopeUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                6 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
class MyClass
{
    private $var1 = null;
    protected $var2 = null;
    public $var3 = null;
    $var4 = null;
}

class foo
{
    const bar = <<<BAZ
qux
BAZ;
}
?><?php
function func1() {}

class MyClass
{
    function func1() {}
    public function func1() {}
    private function func1() {}
    protected function func1() {}
}

class Closure_Test {
    public function test() {
        $foo = function() { echo 'foo'; };
    }
}

function test() {
    $foo = function() { echo 'foo'; };
}
?><?php
/**
 * Unit test class for the StaticThisUsage sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the StaticThisUsage sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Scope_StaticThisUsageUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                7 => 1,
                8 => 1,
                9 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
class MyClass
{
    public static function func1()
    {
        $value = 'hello';
        $newValue = array($this->func2());
        $result = $this->getValue($value);
        return $this->setValue($result);
    }

    public function func1()
    {
        $value = 'hello';
        $newValue = array($this->func2());
        $result = $this->getValue($value);
        return $this->setValue($result);
    }

    function func1()
    {
        $value = 'hello';
        $newValue = array($this->func2());
        $result = $this->getValue($value);
        return $this->setValue($result);
    }
}
?><?php
/**
 * Unit test class for the EmptyStatement sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the EmptyStatement sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_CodeAnalysis_EmptyStatementUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                3  => 1,
                15 => 1,
                17 => 1,
                19 => 1,
                30 => 1,
                35 => 1,
                41 => 1,
                47 => 1,
                52 => 1,
                55 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php

switch ($foo) {
    // Empty switch statement body 
}

switch ($foo) {
    case 'bar':
        break;
    default:
        break;
}


if ($foo) {
    // Just a comment
} elseif ($bar) {
    // Yet another comment 
} else {
    
}

if ($foo) {
    $foo = 'bar';
} else if ($bar) {
    $bar = 'foo';
}

for ($i = 0; $i < 10; $i++) {
    for ($j = 0; $j < 10; $j++) {
        // Just a comment
    }
}

foreach ($foo as $bar) {}

foreach ($foo as $bar) {
    $bar *= 2;
}

do {
    // Just a comment
    // Just another comment
} while ($foo);

do {
    while ($bar) {
        
    }
} while (true);

while ($foo) { /* Comment in the same line */ }

while ($foo) {
    if ($foo) {
    }
}<?php
/**
 * Unit test class for the ConstantCase sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ConstantCase sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_NamingConventions_ConstantCaseUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='ConstantCaseUnitTest.inc')
    {
        switch ($testFile) {
        case 'ConstantCaseUnitTest.inc':
            return array(
                    7  => 1,
                    10 => 1,
                    15 => 1,
                    16 => 1,
                    23 => 1,
                    26 => 1,
                    31 => 1,
                    32 => 1,
                    39 => 1,
                    42 => 1,
                    47 => 1,
                    48 => 1,
                   );
        break;
        case 'ConstantCaseUnitTest.js':
            return array(
                    2  => 1,
                    3  => 1,
                    4  => 1,
                    7  => 1,
                    8  => 1,
                    12 => 1,
                    13 => 1,
                    14 => 1,
                   );
            break;
        default:
            return array();
            break;
        }//end switch

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the ValidVariableName sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ValidVariableName sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_NamingConventions_ValidVariableNameUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                3   => 1,
                5   => 1,
                10  => 1,
                12  => 1,
                15  => 1,
                17  => 1,
                20  => 1,
                22  => 1,
                25  => 1,
                27  => 1,
                31  => 1,
                33  => 1,
                36  => 1,
                37  => 1,
                39  => 1,
                42  => 1,
                44  => 1,
                53  => 1,
                58  => 1,
                62  => 1,
                63  => 1,
                64  => 1,
                67  => 1,
                81  => 1,
                106 => 1,
                107 => 1,
                108 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
$varName  = 'hello';
$var_name = 'hello';
$varname  = 'hello';
$_varName = 'hello';

class MyClass
{
    $varName  = 'hello';
    $var_name = 'hello';
    $varname  = 'hello';
    $_varName = 'hello';

    public $varName  = 'hello';
    public $var_name = 'hello';
    public $varname  = 'hello';
    public $_varName = 'hello';

    protected $varName  = 'hello';
    protected $var_name = 'hello';
    protected $varname  = 'hello';
    protected $_varName = 'hello';

    private $_varName  = 'hello';
    private $_var_name = 'hello';
    private $_varname  = 'hello';
    private $varName   = 'hello';
}

echo $varName;
echo $var_name;
echo $varname;
echo $_varName;

echo "Hello $varName";
echo "Hello $var_name";
echo "Hello ${var_name}";
echo "Hello $varname";
echo "Hello $_varName";

echo 'Hello '.$varName;
echo 'Hello '.$var_name;
echo 'Hello '.$varname;
echo 'Hello '.$_varName;

echo $_SERVER['var_name'];
echo $_REQUEST['var_name'];
echo $_GET['var_name'];
echo $_POST['var_name'];
echo $GLOBALS['var_name'];

echo MyClass::$varName;
echo MyClass::$var_name;
echo MyClass::$varname;
echo MyClass::$_varName;

echo $this->varName2;
echo $this->var_name2;
echo $this->varname2;
echo $this->_varName2;
echo $object->varName2;
echo $object->var_name2;
echo $object_name->varname2;
echo $object_name->_varName2;

echo $this->myFunction($one, $two);
echo $object->myFunction($one_two);

$error = "format is \$GLOBALS['$varName']";

echo $_SESSION['var_name'];
echo $_FILES['var_name'];
echo $_ENV['var_name'];
echo $_COOKIE['var_name'];

$XML       = 'hello';
$myXML     = 'hello';
$XMLParser = 'hello';
$xmlParser = 'hello';

echo "{$_SERVER['HOSTNAME']} $var_name";

// Need to be the last thing in this test file.
$obj->$classVar = $prefix.'-'.$type;

class foo
{
    const bar = <<<BAZ
qux
BAZ;
}

$foo = <<<'BAR'
$123
"$456"
BAR;

$foo = <<<BAR
$123
"$456"
BAR;

class a
{
    protected
        $_sheet,
        $_FieldParser,
        $_key;
}
?>
if (variable === true) { }
if (variable === TRUE) { }
if (variable === True) { }
variable = True;

if (variable === false) { }
if (variable === FALSE) { }
if (variable === False) { }
variable = false;

if (variable === null) { }
if (variable === NULL) { }
if (variable === Null) { }
variable = NULL;
<?php
function getSomeValue() {}
function parseMyDSN() {}
function get_some_value() {}
function getSomeValue_Again() {}
function _getSomeValue() {}
function _parseMyDSN() {}
function _get_some_value() {}
function _getSomeValue_Again() {}

function __construct() {}
function __destruct() {}
function __myFunction() {}
function __my_function() {}

function XMLParser() {}
function xmlParser() {}

echo preg_replace_callback('~-([a-z])~', function ($match) { return strtoupper($match[1]); }, 'hello-world');

/* @codingStandardsIgnoreStart */
class MyClass
{
    /* @codingStandardsIgnoreEnd */
    public function __construct() {}
}
?>
<?php

// True
function myFunction($arg1, $arg2=TRUE)
{
}
function myFunction($arg1, $arg2=true)
{
}
function myFunction($arg1, $arg2=True)
{
}

if ($variable === TRUE) { }
if ($variable === true) { }
if ($variable === True) { }


// False
function myFunction($arg1, $arg2=FALSE)
{
}
function myFunction($arg1, $arg2=false)
{
}
function myFunction($arg1, $arg2=False)
{
}

if ($variable === FALSE) { }
if ($variable === false) { }
if ($variable === False) { }


// Null
function myFunction($arg1, $arg2=NULL)
{
}
function myFunction($arg1, $arg2=null)
{
}
function myFunction($arg1, $arg2=Null)
{
}

if ($variable === NULL) { }
if ($variable === null) { }
if ($variable === Null) { }

$x = new stdClass();
$x->null = 7;
?>
<?php
/**
 * Unit test class for the ValidFunctionName sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ValidFunctionName sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_NamingConventions_ValidFunctionNameUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                4  => 1,
                5  => 1,
                6  => 1,
                7  => 1,
                8  => 1,
                9  => 1,
                11 => 1,
                12 => 1,
                13 => 1,
                14 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the ArrayDeclaration sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ArrayDeclaration sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Arrays_ArrayDeclarationUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                7   => 2,
                9   => 2,
                22  => 1,
                23  => 1,
                24  => 1,
                25  => 1,
                31  => 1,
                35  => 1,
                36  => 1,
                41  => 1,
                46  => 1,
                47  => 1,
                50 =>  1,
                51  => 1,
                53  => 1,
                56  => 1,
                58  => 1,
                61  => 1,
                62  => 1,
                63  => 1,
                64  => 1,
                65  => 1,
                66  => 3,
                70  => 1,
                76  => 2,
                77  => 1,
                78  => 7,
                79  => 2,
                81  => 2,
                82  => 4,
                87  => 1,
                88  => 1,
                92  => 1,
                97  => 1,
                100 => 1,
                101 => 1,
                102 => 1,
                105 => 1,
                106 => 1,
                107 => 1,
                125 => 1,
                126 => 1,
                141 => 1,
                144 => 1,
                146 => 1,
                148 => 1,
                151 => 1,
                157 => 1,
                174 => 3,
                179 => 1,
                189 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
$myArray['key']                = $value;
$myArray[/* key start */'key'] = $value;
$myArray[/* key start */'key'/* key end */] = $value;
$myArray  [  'key'  ]            = $value;
if ($array[($index + 1)] === true) {
} else if ($array  [ ($index + 1) ] === null) {
}
$array = [
    'foo' => 'bar',
    'bar' => 'foo',
];

$array = [];
?><?php
/**
 * Unit test class for the ArrayBracketSpacing sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ArrayBracketSpacing sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Arrays_ArrayBracketSpacingUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                3 => 1,
                4 => 2,
                5 => 3,
                7 => 3,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php

function test()
{
    $a = array();

    $b = Array ();

    $c = Array(
            'a' => 1,
         );
}


class TestClass
{
    public $good = array(
                    'width'  => '',
                    'height' => '',
                   );

    private $_bad = Array(
                    'width' => '',
                    'height' => ''
                     );


    public function test()
    {
        $truck = array(
                 'width' => '',
                  'height' => '',
                 );

        $plane = Array(
                'width' => '',
                  'height' => '',
                 );

        $car = array(
                'width' => '',
                'height' => '',
               );

        $bus = array(
                'width'  =>   '',
                'height' => ''
               );

        $train = array  (
                   TRUE,
                  FALSE,
                  'aaa'
                 );

        $inline = array('aaa', 'bbb', 'ccc');
        $inline = array('aaa');
        $inline = Array('aaa');

        $bigone = array(
                   'name' => 'bigone',
                   'children'   => Array(
                                    '1a' => 'child',
                                    '11b' => 'child',
                                    '111c'      => 'child',
                                    'children'  => Array(
                                                    'child' => 'aaa',
                                                   ),
                                   ),
                   'short_name' => 'big'
                  );
    }

}//end class

$value = array ( );
$value = array(  );
$value = array('1'=>$one, '2'  =>  $two, '3'=> $three, '4' =>$four);
$value = array('1'=>$one);

if (in_array('1', array('1','2','3')) === TRUE) {
    $value = in_array('1', array('1'  ,   '2',     '3','4'));
}

$value = array(
          '1'=> TRUE,
          FALSE,
          '3' => 'aaa',);

$value = array(
          '1'=> TRUE,
          FALSE,
         );

$value = array(
          TRUE,
          '1' => FALSE,
         );

$value = array(1,
          2 ,
          3 ,
         );

$value = array(1 => $one,
          2 => $two ,
          3 => $three ,
         );

$value = array(
          'tag'   => $tag,
          'space' => $this->_getIndentation($tag, $tagElement),
         );

$expected = array(
             array(
              '1' => 1,
              '1' => 2,
             ),
            );

$expected = array(
             array(
              '1' => 1,
              '1' => 2
             )
            );

// Space in second arg.
$args = array(
         '"'.$this->id.'"',
         (int) $hasSessions,
        );

// No errors.
$paths = array(
          Init::ROOT_DIR.'/Systems'   => 'Systems',
          Init::ROOT_DIR.'/Installer' => 'Systems',
         );

$x = array(
     );

$x = array('test'
     );
$x = array('test',
     );
$x = array('name' => 'test',
     );

$x = array(
      $x,
     );

$func = array(
         $x,
         'get'.$x.'Replacement'
        );

$array = array(
          'input_one' => 'one',
          'inputTwo'  => 'two',
          'input_3'   => 3,
         );

$array = array(
          'input_one',
          'inputTwo',
          'input_3',
         );

// Malformed
$foo = array(1
, 2);

$listItems[$aliasPath] = array('itemContent' => implode('<br/>', $aliases));

$listItems[$aliasPath] = array(
                          'itemContent' => implode('<br/>', $aliases)
                         );

$test = array(
         'test' => TestFunction::blah(
             $value1,
             $value2
         ),
        );

$c = array('a' => 1,);

?>
<?php
$this->testThis();
$this-> testThis();
$this    ->  testThis();
$this->/* comment here */testThis();
$this/* comment here */ -> testThis();
?><?php
$var = (int) $var2;
$var = ( int ) $var2;
$var = (int ) $var2;
$var = ( int) $var2;
$var = (	int	) $var2;
?>.HelpWidgetType-new-bug-title {
    float: left;
}<?php
echo $blah;
echo    $blah;
echo($blah);

print $blah;
print     $blah;
print($blah);

include $blah;
include     $blah;
include($blah);

include_once $blah;
include_once     $blah;
include_once($blah);

require $blah;
require     $blah;
require($blah);

require_once $blah;
require_once     $blah;
require_once($blah);

$obj = new MyClass();
$obj = new    MyClass();

return;
return $blah;
return   $blah;
return($blah);
?>
alert('hi');
alert('hi');<?php
if ($something) {
}
foreach ($this as $that) {
}
while (true) {
    for ($i = 0; $i < 10; $i++) {
    }
    if ($something) {
    }

    foreach ($this as $that) {
        do {
        } while (true);

    }
}

if ($one) {
} else ($two) {
} else if ($three) {
} elseif ($four) {
}
if ($one) {
} else ($two) {
} else if ($three) {
} elseif ($four) {
}
?>
<table>
    <tr>
        <td align="center" valign="center">
        <?php
        foreach ($this->children as $child) {
            // There should be no error after this
            // foreach, because it is followed by a
            // close PHP tag.
        }
        ?>
        </td>
    </tr>
</table>
<?php

switch ($blah) {
    case 'one':
        if ($blah) {
            // There are no spaces before break.
        }
    break;

    default:
        if ($blah) {
            // There are no spaces before break.
        }
    break;
}

switch ($blah) {
    case 'one':
        if ($blah) {
            // There are no spaces before break.
        }
    break;

    default:
        if ($blah) {
            // Code here.
        }
}

foreach ($blah as $var) {
    if ($blah) {
    }
    break;
}

while (true) {
    for ($i = 0; $i < 10; $i++) {

        if ($something) {
        }

    }

    foreach ($this as $that) {
        do {

            echo $i;
        } while (true);
    }
}

function myFunction()
{
    if ($blah) {
    }

}//end myFunction()

foreach ($this->children as $child) {
    echo $child;

}

if ($defaultPageDesign === 0
    && $defaultCascade === TRUE
    && $defaultChildDesign === 0
) {
    $settingsUpdated = FALSE;
}

foreach ( $blah as $var ) {
    if (  $blah    ) {
    }
}

if (
    $defaultPageDesign === 0
    && $defaultCascade === TRUE
    && $defaultChildDesign === 0
) {
    $settingsUpdated = FALSE;
}

$moo = 'blar';
switch ($moo)
{
    case 'blar':
        if ($moo === 'blar2') {
            $moo = 'blar'
        }
    return $moo;

    default:
        $moo = 'moo';
    break;
}
?>
var x = {
    b:  'x',
    xasd: x,
    a: function () {
        alert('thats right');
        x = (x?a:x);
    },
    casdasd :  123123,
    omgwtfbbq:   {
        a: 1,
        b:  2
    }
};

id = id.replace(/row\/:/gi, '');

outer_loop:
for (i=0; i<3; i++) {
   for (j=0; j<5; j++) {
      if (j==x)
         break outer_loop;
   }
}
alert('hi');

even_number: if ((i % 2) == 0) {
    if (i == 12)
        break even_number;
}

switch (blah) {
    case dfx.DOM_VK_LEFT:
        this.caretLeft(shiftKey);
    break;
    default:
        if (blah) {
        }
    break;
}<?php
/**
 * Unit test class for the FunctionOpeningBraceSpace sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the FunctionOpeningBraceSpace sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_WhiteSpace_FunctionOpeningBraceSpaceUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='FunctionOpeningBraceSpaceUnitTest.inc')
    {
        switch ($testFile) {
        case 'FunctionOpeningBraceSpaceUnitTest.inc':
            return array(
                    10 => 1,
                    25 => 1,
                   );
            break;
        case 'FunctionOpeningBraceSpaceUnitTest.js':
            return array(
                    11 => 1,
                    31 => 1,
                    38 => 1,
                    57 => 1,
                    60 => 1,
                    73 => 1,
                    84 => 1,
                   );
            break;
        default:
            return array();
            break;
        }//end switch
        

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>

.HelpWidgetType-new-bug-title {
    float: left;
}
.HelpWidgetType-new-bug-title   {
    float: left;
}
.HelpWidgetType-new-bug-title	{   
    float: left;   
}
    
.HelpWidgetType-new-bug-title{
    float: left;
}

/* @codingStandardsChangeSetting Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines true */
.HelpWidgetType-new-bug-title{
    float: left;
}
    
.HelpWidgetType-new-bug-title{
    float: left;
}
/* @codingStandardsChangeSetting Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines false */

<?php
/**
 * Unit test class for the SuperfluousWhitespace sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the SuperfluousWhitespace sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_WhiteSpace_SuperfluousWhitespaceUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='SuperfluousWhitespaceUnitTest.inc')
    {
        switch ($testFile) {
        case 'SuperfluousWhitespaceUnitTest.inc':
            return array(
                    2  => 1,
                    4  => 1,
                    5  => 1,
                    6  => 1,
                    7  => 1,
                    16 => 1,
                    23 => 1,
                    30 => 1,
                    48 => 1,
                   );
            break;
        case 'SuperfluousWhitespaceUnitTest.1.js':
            return array(
                    1  => 1,
                    3  => 1,
                    4  => 1,
                    5  => 1,
                    6  => 1,
                    15 => 1,
                    22 => 1,
                    29 => 1,
                    47 => 1,
                   );
            break;
        case 'SuperfluousWhitespaceUnitTest.1.css':
            return array(
                    1  => 1,
                    8  => 1,
                    9  => 1,
                    11 => 1,
                    25 => 1,
                   );
            break;
        default:
            return array();
            break;
        }//end switch

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
class MyClass
{
    public static $var = null;
    protected $var = null;

    public   static  $var = null;
    protected  $var = null;

    private function myFunction() {}
    public static function myFunction() {}

    private   function myFunction() {}
    public  static function myFunction() {}
    private static   function myFunction() {}

    private  static
        function myFunction() {}

    public static function output()
    {
        // New in PHP 5.3
        static::bar();
    }
}

abstract class Foo
{
    public static function getInstance()
    {
        return new static();
    }
}

if ($geometry instanceof static) {
    echo 'foo';
}
?>
<?php
/**
 * Unit test class for the ControlStructureSpacing sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ControlStructureSpacing sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_WhiteSpace_ControlStructureSpacingUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='ControlStructureSpacingUnitTest.inc')
    {
        switch ($testFile) {
        case 'ControlStructureSpacingUnitTest.inc':
            return array(
                    3   => 1,
                    5   => 1,
                    8   => 1,
                    15  => 1,
                    23  => 1,
                    74  => 1,
                    79  => 1,
                    82  => 1,
                    83  => 1,
                    87  => 1,
                    103 => 1,
                    113 => 2,
                    114 => 2,
                    118 => 1,
                   );
            break;
        case 'ControlStructureSpacingUnitTest.js':
            return array(
                    3  => 1,
                    9  => 1,
                    15 => 1,
                    21 => 1,
                    56 => 1,
                    61 => 1,
                    64 => 1,
                    65 => 1,
                    68 => 1,
                    74 => 2,
                    75 => 2,
                   );
            break;
        default:
            return array();
            break;
        }//end switch

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
if (something) {
}
for (i = 0; i < 10; i++) {
}

while (true) {
    for (i = 0; i < 10; i++) {
    }
    if (something) {
    }

    do {
    } while (true);

}

if (one) {
} else (two) {
} else if (three) {
}
if (one) {
} else (two) {
} else if (three) {
}

switch (blah) {
    case 'one':
        if (blah) {
            // There are no spaces before break.
        }
    break;

    default:
        if (blah) {
            // There are no spaces before break.
        }
    break;
}

switch (blah) {
    case 'one':
        if (blah) {
            // There are no spaces before break.
        }
    break;

    default:
        if (blah) {
            // Code here.
        }
}

for (i = 0; i < 10; i++) {
    if (blah) {
    }
    break;
}

while (true) {
    for (i = 0; i < 10; i++) {

        if (something) {
        }

    }

    do {

        alert(i);
    } while (true);
}

for (  i = 0; i < 10; i++  ) {
    if ( blah   ) {
    }
}

var x = {
    a: function () {
        if (blah) {
        }

    },
};
?>

result = 1 + 2;
result = 1  + 2;
result = 1  +   2;
result = 1 +2;
result = 1+ 2;
result = 1+2;

result = 1 - 2;
result = 1  - 2;
result = 1  -   2;
result = 1 -2;
result = 1- 2;
result = 1-2;

result = 1 * 2;
result = 1  * 2;
result = 1  *   2;
result = 1 *2;
result = 1* 2;
result = 1*2;

result = 1 / 2;
result = 1  / 2;
result = 1  /   2;
result = 1 /2;
result = 1/ 2;
result = 1/2;

result = 1 % 2;
result = 1  % 2;
result = 1  %   2;
result = 1 %2;
result = 1% 2;
result = 1%2;
result = '100%';

result += 4;
result+=4;
result -= 4;
result-=4;
result /= 4;
result/=4;
result *=4;
result*=4;

$.localScroll({offset: {top: -32}});

switch (result) {
	case -1:
		break;
}

result = x?y:z;
result = x ? y : z;
function FuncOne()
{
    // Code here.

}//end AdjustModalDialogWidgetType


Testing.prototype = {

    doSomething: function()
    {

        // Code here.

    },

    doSomethingElse: function()
    {
        // Code here.

    },

    start: function()
    {
        this.toolbarPlugin.addButton('Image', 'imageEditor', 'Insert/Edit Image', function () { self.editImage() });

    },
};

function FuncFour()
{


    // Code here.
}

AbstractAttributeEditorWidgetType.prototype = {
    isActive: function() {
        return this.active;

    },

    activate: function(data)
    {
        var x = {
            test: function () {
                alert('This is ok');
            }
        };

        this.active = true;

    }

};

function test() {
    var x = 1;
    var y = function()
    {
        alert(1);
    }

    return x;

}

var myFunc = function()
{
    var x = 1;

    blah(x, y, function()
    {
        alert(2);
    }, z);

    blah(function() { alert(2); });

    return x;

}

HelpWidgetType.prototype = {
    init: function() {
    var x = 1;
    var y = {
        test: function() {
            alert(3);
        }
    }
    return x;

    }
}

CustomFormEditWidgetType.prototype = {

    addQuestion: function()
    {
        var settings = {
            default: ''
        };

    },

    addQuestionRulesEvent: function()
    {
        var self = this;

    }

};
<?php
/**
 * Unit test class for the ScopeKeywordSpacing sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ScopeKeywordSpacing sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_WhiteSpace_ScopeKeywordSpacingUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                7  => 2,
                8  => 1,
                13 => 1,
                14 => 1,
                15 => 1,
                17 => 2,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the LanguageConstructSpacing sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the LanguageConstructSpacing sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_WhiteSpace_LanguageConstructSpacingUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                3  => 1,
                4  => 1,
                7  => 1,
                8  => 1,
                11 => 1,
                12 => 1,
                15 => 1,
                16 => 1,
                19 => 1,
                20 => 1,
                23 => 1,
                24 => 1,
                27 => 1,
                31 => 1,
                32 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php

function MyFunction1()
{
    // Some code goes here.
    echo $code;
}

function MyFunction2()
{

    // Some code goes here.
    echo $code;
}

class MyClass
{
    function MyFunction1()
    {
        // Some code goes here.
        echo $code;
    }

    function MyFunction2()
    {

        // Some code goes here.
        echo $code;
    }

    public function register();
}

function emptyFunction()
{

}//end emptyFunction();

public function register();
?>
<?php
$test = $this->testThis();
$test = $this->testThis() ;
$test = $this->testThis()           ;
for ($var = 1   ; $var < 10  ; $var++) {
    echo $var ;
}
$test = $this->testThis()  /* comment here */;
$test = $this->testThis()  /* comment here */  ;
?>
<?php
echo 'hi';
echo 'hello';   
    
if ($something) {  
    
}


function myFunction()
{
    echo 'code here';

    echo 'code here';


    // Hello.

    /*
        HI
    */


}

function myFunction2()
{
    echo 'code here';


    echo 'code here';

}

// @codingStandardsChangeSetting Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines true

function myFunction2()
{
    echo 'code here';
    
    echo 'code here';
    
}

// @codingStandardsChangeSetting Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines false

?>

<?php
class MyClass
{
    public $var1 = 'value';


    public $var2 = 'value';

    public $var3 = 'value';

}//end class


interface MyInterface
{

    public $var1 = 'value';


    public $var2 = 'value';

    protected $var3 = 'value';
}//end interface


class MyClass
{


    public $var1 = 'value';

    private $var2 = 'value';


    protected $var3 = 'value';


}//end class



class MyClass
{
    public $var1 = 'value';
}//end class


interface MyInterface
{
    public $var1 = 'value';
    function myFunction();
}//end interface


class MyClass
{

    /**
     * The actions that this wizard step requires.
     *
     * @var   array
     * @since 4.0.0
     */
    protected $actions = array();


    /**
     * TRUE if this step should be performed after the asset is created.
     *
     * @var   boolean
     * @since 4.0.0
     */
    protected $postStep = FALSE;


}//end class

class MyClass
{
    /**
     * The actions that this wizard step requires.
     *
     * @var   array
     * @since 4.0.0
     */
    protected $actions = array();

}//end class

class MyClass
{

    /**
     * The actions that this wizard step requires.
     *
     * @var   array
     * @since 4.0.0
     */
    protected $actions = array();

    /**
     * The actions that this wizard step requires.
     *
     * @var   array
     * @since 4.0.0
     */
    protected $actions = array();

}//end class
?><?php

if ($foo || $bar) {}
if ($foo||$bar && $baz) {}
if ($foo|| $bar&&$baz) {}
if ($foo  ||   $bar   && $baz) {}

// Spacing after || below is ignored as it is EOL whitespace.
if ($foo ||    
    $bar
    && $baz
) {
}

if ($foo||
    $bar
    &&$baz
) {
}

?>
<?php
/**
 * Unit test class for the FunctionClosingBraceSpace sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the FunctionClosingBraceSpace sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_WhiteSpace_FunctionClosingBraceSpaceUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='FunctionClosingBraceSpaceUnitTest.inc')
    {
        switch ($testFile) {
        case 'FunctionClosingBraceSpaceUnitTest.inc':
            return array(
                    10 => 1,
                    21 => 1,
                   );
            break;
        case 'FunctionClosingBraceSpaceUnitTest.js':
            return array(
                    13 => 1,
                    25 => 1,
                    32 => 1,
                    53 => 1,
                    59 => 1,
                    67 => 1,
                    84 => 1,
                   );
            break;
        default:
            return array();
            break;
        }//end switch

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the CastSpacing sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the CastSpacing sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_WhiteSpace_CastSpacingUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                3 => 1,
                4 => 1,
                5 => 1,
                6 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
function func1() {

}//end func1()


function func2() {

}//end func2()

function func3() {

}//end func3()


class MyClass
{
    function func1() {

    }//end func1()


    function func2() {

    }//end func2()

    function func3() {

    }//end func3()
}//end class


interface MyInterface
{
    function func1();


    function func2();

    function func3();
}//end interface


class MyClass
{


    function func1() {

    }//end func1()


    function func2() {

    }//end func2()



    function func3() {

    }//end func3()


}//end class


interface MyInterface
{


    function func1();


    function func2();



    function func3();


}//end interface

class MyClass
{
    function func1() {

    }//end func1()
}//end class


interface MyInterface
{
    function func1();
}//end interface


class MyClass
{

    /**
     * The tag that this element represents (omiting the @ symbol).
     *
     * @var string
     */
    protected $tag = '';


    /**
     * Function comment.
     *
     * @return boolean
     */
    function func1() {

    }//end func1()

    /**
     * Function comment.
     *
     * @return boolean
     */
    function func2() {

    }//end func2()


    /**
     * Function comment.
     *
     * @return boolean
     */
    function func3() {

    }//end func3()

}//end class


interface MyInterface
{

    /**
     * Function comment.
     *
     * @return boolean
     */
    function func1();



    /**
     * Function comment.
     *
     * @return boolean
     */
    function func2();


    /**
     * Function comment.
     *
     * @return boolean
     */
    function func3();

}//end interface

class MyClass
{

    protected $tag = '';

    protected $tag = '';


    /**
     * Function comment.
     *
     * @return boolean
     */
    function func1() {

    }//end func1()


}//end class

// @codingStandardsChangeSetting Squiz.WhiteSpace.FunctionSpacing spacing 1

interface MyInterface
{

    /**
     * Function comment.
     *
     * @return boolean
     */
    function func1();


    /**
     * Function comment.
     *
     * @return boolean
     */
    function func2();

    /**
     * Function comment.
     *
     * @return boolean
     */
    function func3();


}//end interface

class MyClass
{

    protected $tag = '';

    protected $tag = '';

    /**
     * Function comment.
     *
     * @return boolean
     */
    function func1() {

    }//end func1()


}//end class

// @codingStandardsChangeSetting Squiz.WhiteSpace.FunctionSpacing spacing 2

// Closures should be ignored.
preg_replace_callback(
    '~-([a-z])~',
    function ($match) {
        return strtoupper($match[1]);
    },
    'hello-world'
);

$callback = function ($bar) use ($foo)
            {
                $bar += $foo;
            };
?>
<?php
/**
 * Unit test class for the FunctionSpacing sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the FunctionSpacing sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_WhiteSpace_FunctionSpacingUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                2   => 1,
                9   => 1,
                18  => 1,
                25  => 1,
                29  => 1,
                35  => 1,
                38  => 1,
                40  => 1,
                55  => 1,
                74  => 1,
                85  => 1,
                87  => 1,
                93  => 2,
                115 => 1,
                134 => 1,
                147 => 2,
                164 => 1,
                198 => 1,
                213 => 1,
                232 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the LogicalOperatorSpacing sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the LogicalOperatorSpacing sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_WhiteSpace_LogicalOperatorSpacingUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='LogicalOperatorSpacingUnitTest.inc')
    {
        return array(
                4  => 2,
                5  => 3,
                6  => 3,
                15 => 1,
                17 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the MemberVarSpacing sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the MemberVarSpacing sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_WhiteSpace_MemberVarSpacingUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                4  => 1,
                7  => 1,
                20 => 1,
                30 => 1,
                35 => 1,
                44 => 1,
                50 => 1,
                73 => 1,
                86 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the ScopeClosingBrace sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ScopeClosingBrace sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_WhiteSpace_ScopeClosingBraceUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                11 => 1,
                13 => 1,
                24 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
var x = {
    a: function () {
        alert('thats right')  ;
        x = (x?a:x) ;
    },
} ;

id = id.replace(/row\/:;/gi, '');

for (i=0   ; i<3 ; i++) {
   for (j=0; j<5 ; j++) {
      if (j==x)
         break ;
   }
}
alert('hi');<?php

$result = 1 + 2;
$result = 1  + 2;
$result = 1  +   2;
$result = 1 +2;
$result = 1+ 2;
$result = 1+2;

$result = 1 - 2;
$result = 1  - 2;
$result = 1  -   2;
$result = 1 -2;
$result = 1- 2;
$result = 1-2;

$result = 1 * 2;
$result = 1  * 2;
$result = 1  *   2;
$result = 1 *2;
$result = 1* 2;
$result = 1*2;

$result = 1 / 2;
$result = 1  / 2;
$result = 1  /   2;
$result = 1 /2;
$result = 1/ 2;
$result = 1/2;

$result = 1 % 2;
$result = 1  % 2;
$result = 1  %   2;
$result = 1 %2;
$result = 1% 2;
$result = 1%2;
$result = '100%';

$result += 4;
$result+=4;
$result -= 4;
$result-=4;
$result /= 4;
$result/=4;
$result *=4;
$result*=4;

$result =& $thing;
if ($result & 4) {
    if ($result | 4) {
    }
}
if ($result&4) {
    if ($result |4) {
    }
}

$result = ((1 + 2) - (3 * 4 / 5) % 6);
$result = ((1+  2)  -  (3*4/5)  %  6);
return -1;
$file = '...'.substr($file, (($padding * -1) + 3));

$totalErrors   += $errors['errors'];
$totalWarnings +=  $errors['warnings'];

if (substr($line, 0, 3) === '/**') {
    $line = substr($line, 3);
} else if (substr($line, -2, 2) === '*/') {
    $line = substr(-2, 0, -2);
} else if ($line{0} === '*') {
    $line = substr($line, 1);
}

if ($pos === -1) {
}

for ($i=0; $i<=5; $i++) {
    $j^= $i;
    $k %=$i;
    $l&=$i;
    $m.= 'Hello ';
}

$z = ($a+ $b- $c* $d/ $e% $f^ $g);
$z = ($a +$b -$c *$d /$e %$f ^$g);

$a== $b && $c!= $d && $e=== $f && $g!== $h;
$i> $j && $k< $l && $m>= $n && $o<= $p && $q<> $r;

$a ==$b && $c !=$d && $e ===$f && $g !==$h;
$i >$j && $k <$l && $m >=$n && $o <=$p && $q <>$r;

function myFunction($variable=0, $var2='string') {}

if (index > -1) {
}

array_walk_recursive($array, function(&$item) use (&$something) {
});

$var = saveFile(&$model, &$foo);

// This is all valid.
$boo = -$foo;
function foo($boo = -1) {}
$foo = array('boo' => -1);
$x = $test ? -1 : 1;
$y = $test ? 1 : -1;
$z = $test ?: false;

$closureWithDefaultParamter = function (array $testArray=array()) {};

switch ($foo) {
	case -1:
		break;
}

$y = 1 * -1;
$y = -1 * 1;
$y = -1 * $var;
$y = 10 / -2;
$y = -10 / 2;
$y = (-10 / 2);
$y = (-10 / $var);
$y = 10 + -2;
$y = -10 + 2;

$a = $x?$y:$z;
$a = $x ? $y : $z;
?>
.HelpWidgetType-new-bug-title {
    float: left;
}

alert('hi');
alert('hello');   
    
if (something) {  
    
}


function myFunction()
{
    alert('code here');

    alert('code here');


    // Hello.

    /*
        HI
    */


}

function myFunction2()
{
    alert('code here');


    alert('code here');

}

// @codingStandardsChangeSetting Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines true

function myFunction2()
{
    alert('code here');
    
    alert('code here');
    
}

// @codingStandardsChangeSetting Squiz.WhiteSpace.SuperfluousWhitespace ignoreBlankLines false


function FuncOne()
{
    // Code here.

}//end AdjustModalDialogWidgetType


Testing.prototype = {

    doSomething: function()
    {
        // Code here.
    },

    doSomethingElse: function()
    {
        // Code here.

    },
};

function FuncFour()
{
    // Code here.
}

function FuncFive()
{
    // Code here.


}

function valid()
{
   if (true) {
       test = {
           namespaces: {}
       };
   }

}

dfx.addEvent(this.rightScroll, 'mousedown', function() {
    t = setInterval(function() {
        pos -= 10;
    }, 30);
});

// Valid because function is empty.
if (dfx.isFn(callback) === false) {
    callback = function() {};
    callback = function() { };
}

AbstractAttributeEditorWidgetType.prototype = {
    isActive: function() {
        return this.active;
    },

    activate: function(data)
    {
        var x = {
            test: function () {
                alert('This is ok');

            }
        };

        this.active = true;

    }

};

var myFunc = function()
{
    var x = 1;

    blah(function() {
        alert(2);
    });

    blah(function() { alert(2); });

    return x;

}

CustomFormEditWidgetType.prototype = {

    addQuestion: function()
    {
        var settings = {
            default: ''
        };

    },

    addQuestionRulesEvent: function()
    {
        var self = this;

    }

};


if (foo || bar) {}
if (foo||bar && baz) {}
if (foo|| bar&&baz) {}
if (foo  ||   bar   && baz) {}

// Spacing after || below is ignored as it is EOL whitespace.
if (foo ||    
    bar
    && baz
) {
}

if (foo||
    bar
    &&baz
) {
}
<?php
/**
 * Unit test class for the OperatorSpacing sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the OperatorSpacing sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_WhiteSpace_OperatorSpacingUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='OperatorSpacingUnitTest.inc')
    {
        switch ($testFile) {
        case 'OperatorSpacingUnitTest.inc':
            return array(
                    4  => 1,
                    5  => 2,
                    6  => 1,
                    7  => 1,
                    8  => 2,
                    11 => 1,
                    12 => 2,
                    13 => 1,
                    14 => 1,
                    15 => 2,
                    18 => 1,
                    19 => 2,
                    20 => 1,
                    21 => 1,
                    22 => 2,
                    25 => 1,
                    26 => 2,
                    27 => 1,
                    28 => 1,
                    29 => 2,
                    32 => 1,
                    33 => 2,
                    34 => 1,
                    35 => 1,
                    36 => 2,
                    40 => 2,
                    42 => 2,
                    44 => 2,
                    45 => 1,
                    46 => 2,
                    53 => 2,
                    54 => 1,
                    59 => 10,
                    64 => 1,
                    77 => 4,
                    78 => 1,
                    79 => 1,
                    80 => 2,
                    81 => 1,
                    84 => 6,
                    85 => 6,
                    87 => 4,
                    88 => 5,
                    90 => 4,
                    91 => 5,
                    128 => 4,
                   );
            break;
        case 'OperatorSpacingUnitTest.js':
            return array(
                    4  => 1,
                    5  => 2,
                    6  => 1,
                    7  => 1,
                    8  => 2,
                    11 => 1,
                    12 => 2,
                    13 => 1,
                    14 => 1,
                    15 => 2,
                    18 => 1,
                    19 => 2,
                    20 => 1,
                    21 => 1,
                    22 => 2,
                    25 => 1,
                    26 => 2,
                    27 => 1,
                    28 => 1,
                    29 => 2,
                    32 => 1,
                    33 => 2,
                    34 => 1,
                    35 => 1,
                    36 => 2,
                    40 => 2,
                    42 => 2,
                    44 => 2,
                    45 => 1,
                    46 => 2,
                    55 => 4,
                   );
            break;
        default:
            return array();
            break;
        }//end switch

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the ObjectOperatorSpacing sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ObjectOperatorSpacing sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_WhiteSpace_ObjectOperatorSpacingUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                3 => 1,
                4 => 2,
                5 => 1,
                6 => 2,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the SemicolonSpacing sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the SemicolonSpacing sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_WhiteSpace_SemicolonSpacingUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='SemicolonSpacingUnitTest.inc')
    {
        switch ($testFile) {
        case 'SemicolonSpacingUnitTest.inc':
            return array(
                    3 => 1,
                    4 => 1,
                    5 => 2,
                    6 => 1,
                    8 => 1,
                    9 => 1,
                   );
            break;
        case 'SemicolonSpacingUnitTest.js':
            return array(
                    3  => 1,
                    4  => 1,
                    6  => 1,
                    10 => 2,
                    11 => 1,
                    13 => 1,
                   );
            break;
        default:
            return array();
            break;
        }//end switch

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php

function MyFunction1() {
    // Some code goes here.

}

function MyFunction2() {
    // Some code goes here.
}

class MyClass
{
    function MyFunction3() {
        // Some code goes here.

    }

    function MyFunction4() {
        // Some code goes here.
    }

    public function register();
}

public function register();
?>
<?php
/**
 * Unit test class for the PropertyLabel sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the PropertyLabel sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_WhiteSpace_PropertyLabelSpacingUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                2  => 1,
                8  => 2,
                9  => 1,
                11 => 1,
                17 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php

class Test
{
    public function __construct()
    {
    }

    function test1()
    {
     }

    function test2() {}

    private function _test3()
    {
    }

}


class Test2
{
 }


public function test2()
{
    if ($str{0}) {
        $chr = $str{0};
    }
    
    if (!class_exists($class_name)) {
        echo $error;
    }
    $this->{$property} =& new $class_name($this->db_index);
    $this->modules[$module] =& $this->{$property};
}

foreach ($elements as $element) {
    if ($something) {
        // Do IF.
    } else if ($somethingElse) {
        // Do ELSE.
    }
}

switch ($blah) {
    case 'one':
        echo 'one';
    break;
    default:
        echo 'another';
}

?>
body {
font-family: Arial, Helvetica, sans-serif;
margin     : 40px 0 0 0;
padding :  0;
background:  #8FB7DB url(diag_lines_bg.gif) top left;
margin-top:
10px;
margin-bottom: 
0px;
}

.TableWidgetType .recover:hover {
    background-color: #FFF;
}

#clearCache-settings:rootNodes-list_0 {
    border-top: none;
}

.LookupEditScreenWidgetType-urls a, .LookupEditScreenWidgetType-urls a:visited {
    text-decoration: none;
    color: #444;
}

/* checking embedded PHP */
li {
    background:url(<?php print $staticserver; ?>/images/<?php print $staticdir; ?>/bullet.gif) left <?php print $left; ?>px no-repeat;
    margin:0px;
    padding-left:10px;
    margin-bottom:<?php echo $marginBottom; ?>px;
    line-height:13px;
    filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#2e62a8, endColorstr=#123363);
}
<?php
/**
 * Unit test class for the ClassDefinitionOpeningBraceSpace sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ClassDefinitionOpeningBraceSpace sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_CSS_ClassDefinitionOpeningBraceSpaceUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                4  => 1,
                7  => 1,
                10 => 1,
                13 => 1,
                26 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
.SettingsTabPaneWidgetType-tab-mid {
    font-family: Arial;
    Font-Family: arial;
    background-color: #DA9393;
    BACKGROUND-IMAGE: URL(Warning_Close.png);
}

@media screen and (max-device-width: 769px) {

    .SettingsTabPaneWidgetType-tab-mid {
        Font-Family: arial;
        filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#2e62a8, endColorstr=#123363);
    }
}
<?php
/**
 * Unit test class for the MissingColon sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the MissingColon sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_CSS_MissingColonUnitTest extends AbstractSniffUnitTest
{

    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                2  => 1,
                4  => 1,
                6  => 1,
                12 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
.HelpWidgetType-new-bug-title {}
.HelpWidgetType-new-bug-title {
}
.HelpWidgetType-new-bug-title {
    
}
.HelpWidgetType-new-bug-title {

}
.HelpWidgetType-new-bug-title {
    /* Nothing to see here */
}
.HelpWidgetType-new-bug-title {
    float: left;
}
.HelpWidgetType-new-bug-title {
    float: left;
}
.HelpWidgetType-new-bug-title   {
    float: left;
}
.HelpWidgetType-new-bug-title	{
    float: left;
}
.HelpWidgetType-new-bug-title{
    float: left;
}
.HelpWidgetType-new-bug-title {

    float: left;
}

@media screen and (max-device-width: 769px) {

    header #logo img {
        max-width: 100%;
    }

}

@media screen and (max-device-width: 769px) {
    header #logo img {
        max-width: 100%;
    }

}
<?php
/**
 * Unit test class for the ClassDefinitionClosingBraceSpace sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ClassDefinitionClosingBraceSpace sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_CSS_ClassDefinitionClosingBraceSpaceUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                2  => 1,
                11 => 1,
                19 => 1,
                44 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
#MetadataAdminScreen-addField-fieldType {
    margin-left: 10px;
    margin-right:
    float: ;
}
<?php
/**
 * Unit test class for the DisallowMultipleStyleDefinitions sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the DisallowMultipleStyleDefinitions sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_CSS_DisallowMultipleStyleDefinitionsUnitTest extends AbstractSniffUnitTest
{

    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                3  => 1,
                5  => 2,
                10 => 4,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
.AssetLineageWidgetType-item {
    color: #FFF;
}

.AssetLineageWidgetType-title {
    color: #CCC;
}

.AssetLineageWidgetType-item {
    color: #CCC;
}

.AssetLineageWidgetType-item .selected {
}

.AssetLineageWidgetType-item.selected {
}

#Blah .AssetLineageWidgetType-item {
}

#X.selected,
.AssetLineageWidgetType-item {
}

.MyClass, .YourClass {
}

.YourClass, .MyClass {
}

.YourClass, .MyClass, .OurClass {
}
#red {
    background-color: red;
}

.red {
    border-bottom: 1px dotted black;
    border-top: 1px dotted gray;
}

#red.yellow {
    background: yellow url(diag_lines_bg.gif) top left;
    text-shadow: 0 1px 0 white;
}
<?php
/**
 * Unit test class for the NamedColours sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the NamedColours sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_CSS_NamedColoursUnitTest extends AbstractSniffUnitTest
{

    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                2  => 1,
                6  => 1,
                7  => 1,
                11 => 1,
                12 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the DuplicateStyleDefinition sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the DuplicateStyleDefinition sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_CSS_DuplicateStyleDefinitionUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                7 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
.SettingsTabPaneWidgetType-tab-mid {
   background: transparent url(tab_inact_mid.png) repeat-x;
   height: 100%;float: left;
   line-height: -25px;
   cursor: pointer; margin: 10px; float: right;
}

/* testing embedded PHP */
li {
    background:url(<?php print $staticserver; ?>/images/<?php print $staticdir; ?>/bullet.gif) left <?php print $left; ?>px no-repeat; margin:0px; padding-left:10px; margin-bottom:<?php echo $marginBottom; ?>px; line-height:13px;
    filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#2e62a8, endColorstr=#123363);
}
body {

        font-family: Arial, Helvetica, sans-serif;
    margin: 40px 0 0 0;
padding: 0;
  background: #8FB7DB url(diag_lines_bg.gif) top left;
    
}

td {
    margin: 40px;

    padding: 20px;
}

/*
#AdminScreenModeWidgetType-tab_pane-containers .TabPaneWidgetType-tab-selected-left {
    background: transparent url(images/ScreenImages/tab_on_left.png) no-repeat;
}
#AdminScreenModeWidgetType-tab_pane-containers .TabPaneWidgetType-tab-selected-right {
    background: transparent url(images/ScreenImages/tab_on_right.png) no-repeat;
}
*/

@media screen and (max-device-width: 769px) {

    header #logo img {
    max-width: 100%;
        padding: 20px;
         margin: 40px;
    }
}

@media screen and (max-device-width: 769px) {

    header #logo img {
        max-width: 100%;
    }

    header #logo img {
        min-width: 100%;
    }

}

.GUIFileUpload {
/*     opacity: 0.25; */
}
<?php
/**
 * Unit test class for the DuplicateClassDefinition sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the DuplicateClassDefinition sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_CSS_DuplicateClassDefinitionUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                9  => 1,
                29 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the LowercaseStyleDefinition sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the LowercaseStyleDefinition sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_CSS_LowercaseStyleDefinitionUnitTest extends AbstractSniffUnitTest
{

    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                2  => 1,
                3  => 1,
                5  => 2,
                11 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the Opacity sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the Opacity sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_CSS_OpacityUnitTest extends AbstractSniffUnitTest
{

    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                3  => 1,
                5  => 1,
                6  => 1,
                7  => 1,
                9  => 1,
                10 => 1,
                11 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the ForbiddenStyles sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ForbiddenStyles sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_CSS_ForbiddenStylesUnitTest extends AbstractSniffUnitTest
{

    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                2  => 1,
                3  => 1,
                6  => 1,
                7  => 1,
                8  => 1,
                9  => 1,
                15 => 1,
                16 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
#add-new-comment {
    -moz-border-radius: 1px;
    -webkit-border-radius: 1px;
    border-radius: 1px;

    -moz-border-radius-topleft: 1px;
    -moz-border-radius-topright: 1px;
    -moz-border-radius-bottomright: 1px;
    -moz-border-radius-bottomleft: 1px;
    border-top-left-radius: 1px;
    border-top-right-radius: 1px;
    border-bottom-right-radius: 1px;
    border-bottom-left-radius: 1px;

    -moz-box-shadow: 1px;
    -webkit-box-shadow: 1px;
    box-shadow: 1px;
}
<?php
/**
 * Unit test class for the ShorthandSize sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ShorthandSize sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_CSS_ShorthandSizeUnitTest extends AbstractSniffUnitTest
{

    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                8  => 1,
                9  => 1,
                10 => 1,
                11 => 1,
                12 => 1,
                13 => 1,
                15 => 1,
                16 => 1,
                17 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
.my-style {
    margin-right 15px;
    float: left;
    margin-left 15px;
    margin-top: 15px;
    margin-bottom 15px;
}

@media screen and (max-device-width: 769px) {
    header #logo img {
        max-width: 100%;
        margin-bottom 15px;
    }
}
<?php
/**
 * Unit test class for the ColourDefinition sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ColourDefinition sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_CSS_ColourDefinitionUnitTest extends AbstractSniffUnitTest
{

    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                2 => 1,
                5 => 1,
                6 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
#add-new-comment {
    background-color: #333333;
    padding: 10px;
    border-bottom: 1px dotted #F0F0F0;
    border-top: 1px dotted #FF00FF;
    background: #8fb7db url(diag_lines_bg.gif) top left;
    page-break-inside: 1;
    margin: 8px 8px 8px 8px;
    margin: 8px 8px;
    margin: 0 0 0 0;
    margin: 0 8px 0 8px;
    margin: 8px 4px 8px 4px;
    margin: 8px 4% 8px 4%;
    margin: 6px 2px 9px 2px;
    margin: 6px 2px 9px;
    border-radius: 2px 2px 2px 2px !important;
    border-width: 2px               2px   2px       2px;
    border-width: 1px 2px 2px 4px;
    margin: 97px auto 0 auto;
    text-shadow: 0 1px 0 #fff;

    /* These are black-listed style names. */
    background-position: 0 0;
    box-shadow: 2px 2px 2px 2px;
    transform-origin: 0 110% 0;
}
.AssetListingEditWidgetType-BottomPanel select,
#EditEditingModeWidgetType-assetEditor-filters-assetTypes-addNew {
    float: left;
}

.AssetListingEditWidgetType-BottomPanel select,

#EditEditingModeWidgetType-assetEditor-filters-assetTypes-addNew {
    float: left;
}

.AssetListingEditWidgetType-BottomPanel select,
/*.AssetListingEditWidgetType-BottomPanel ul,*/
#EditEditingModeWidgetType-assetEditor-filters-assetTypes-addNew {
    float: left;
}

.AssetListingEditWidgetType-BottomPanel select,

.AssetListingEditWidgetType-BottomPanel ul,
#EditEditingModeWidgetType-assetEditor-filters-assetTypes-addNew {
    float: left;
}

#SuperUsersSystemConfigScreen-table {
    display: block;
    left: 50%;
    margin-left: -500px;
    margin-top: 180px;
    position: relative;
    width: 1000px;
}

/**
 * More styles below here.
 */

td.TableWidgetType-header.TableWidgetType-header-lastLogin,
td.TableWidgetType-header.TableWidgetType-header-remove,
td.TableWidgetType-header.TableWidgetType-header-email,
td.TableWidgetType-header.TableWidgetType-header-userName {
    background: url(images/ScreenImages/table_header_bg.png) repeat-x;
    border-top: 1px solid #D4D4D4;
    color: #787878;
    height: 33px;
    padding-left: 12px;
    width: 150px;
}

@media screen and (max-device-width: 769px) {

    header #logo img {
    max-width: 100%;
        padding: 20px;
         margin: 40px;
    }
}
<?php
/**
 * Unit test class for the Indentation sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the Indentation sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_CSS_IndentationUnitTest extends AbstractSniffUnitTest
{

    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                2  => 1,
                3  => 1,
                5  => 1,
                6  => 1,
                7  => 1,
                12 => 1,
                28 => 1,
                30 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
.ViperSubToolbar-wrapper {
    height: 34px;
    left: 0;
    position: fixed;
    top: 60px;
    z-index: 997;
    left: 50%;
}

.expandable {
    -moz-transition-property: margin-left, margin-right;
    -moz-transition-duration: 0.2s;
    -moz-transition-timing-function: ease;
    -webkit-transition-property: margin-left, margin-right;
    -webkit-transition-duration: 0.2s;
    -webkit-transition-timing-function: ease;
    z-index: 2;
}
.my-style {
    opacity: 0;
    opacity: 0.0;
    opacity: 1;
    opacity: 1.0;
    opacity: 1.5;
    opacity: .5;
    opacity: 0.5;
    opacity: 2;
    opacity: -1;
    opacity: 0.55;
}
<?php
/**
 * Unit test class for the ClassDefinitionNameSpacing sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ClassDefinitionNameSpacing sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_CSS_ClassDefinitionNameSpacingUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                7  => 1,
                19 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the EmptyStyleDefinition sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the EmptyStyleDefinition sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_CSS_EmptyStyleDefinitionUnitTest extends AbstractSniffUnitTest
{

    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                3 => 1,
                4 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the ColonSpacing sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ColonSpacing sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_CSS_ColonSpacingUnitTest extends AbstractSniffUnitTest
{

    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                3  => 1,
                4  => 2,
                5  => 1,
                6  => 1,
                8  => 1,
                27 => 1,
                28 => 1,
                29 => 1,
                30 => 1,
                31 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the SemicolonSpacing sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the SemicolonSpacing sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_CSS_SemicolonSpacingUnitTest extends AbstractSniffUnitTest
{

    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                2 => 1,
                7 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the EmptyClassDefinition sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the EmptyClassDefinition sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_CSS_EmptyClassDefinitionUnitTest extends AbstractSniffUnitTest
{

    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                1  => 1,
                2  => 1,
                4  => 1,
                7  => 1,
                10 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
#title-bar-bottom-right {
    background-color: #333333;
    padding: 10px;
    border-bottom: 1px dotted #F0F0F0;
    border-top: 1px dotted #FF00FF;
    background: #8fb7db url(diag_lines_bg.gif) top left;
}

#add-new-comment {
}
.my-style {
}


.my-style {
}

/* Comment */

.my-style {
}


/* Comment */

.my-style {
    float: left;

}

.AssetLineageWidgetType-item {
    color: #CCC;
}

/*.AssetLineageWidgetType-item2 .selected,
.AssetLineageWidgetType-item .selected {
}*/

.AssetLineageWidgetType-item.selected {
}

@media screen and (max-device-width: 769px) {

    header #logo img {
        max-width: 100%;
    }

}

@media screen and (max-device-width: 769px) {

    header #logo img {
        max-width: 100%;
    }
}
.HelpWidgetType-new-bug-title {
    width: 308px
    float: left;
}

#MetadataAdminScreen-addField-add {
    float: left ;
}

.TableWidgetType .recover:hover {
    background-color: #FFF;
}

#clearCache-settings:rootNodes-list_0 {
    border-top: none;
}

.HelpWidgetType-list {
    list-style-image: url();
}
<?php
/**
 * Unit test class for the FunctionDeclaration sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the FunctionDeclaration sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Functions_FunctionDeclarationUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                55 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
function func1() {}

class MyClass
{
    function func1() {}
}

interface MyInterface
{
    function func1() {}
}

function __autoload($class) {}

echo preg_replace_callback('~-([a-z])~', function ($match) { return strtoupper($match[1]); }, 'hello-world');
?>
<?php
/**
 * Unit test class for the FunctionDeclarationArgumentSpacing sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the FunctionDeclarationArgumentSpacing sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Functions_FunctionDeclarationArgumentSpacingUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                3  => 1,
                5  => 2,
                7  => 2,
                8  => 2,
                9  => 2,
                11 => 2,
                13 => 7,
                14 => 2,
                15 => 2,
                16 => 4,
                18 => 2,
                35 => 2,
                36 => 3,
                44 => 2,
                45 => 1,
                46 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the FunctionDuplicateArgument sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the FunctionDuplicateArgument sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Functions_FunctionDuplicateArgumentUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                2 => 1,
                4 => 2,
                5 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
function myFunc() {}
function myFunc( ) {}
function myFunc($blah) {}
function myFunc( $blah ) {}
function myFunc($blah, $blah2, $blah3) {}
function myFunc($blah , $blah2, $blah3 ) {}
function myFunc($blah,$blah2,$blah3) {}
function myFunc($blah,   $blah2,  $blah3) {}
function myFunc($blah='hello') {}
function myFunc($blah = 'hello') {}
function myFunc(PHP_CodeSniffer $object, array $array=array(), $blah3='yo') {}
function myFunc(  $blah='hello'   , $blah2=   'hi',  $blah3   = 'yo' ) {}
function myFunc(PHP_CodeSniffer   $object, array  $array=array(), $blah3='yo') {}
function myFunc( PHP_CodeSniffer $object,  array $array=array(), $blah3='yo') {}
function myFunc( array  &$one,  array  &$two) {}
function myFunc(&$blah) {}
function myFunc( &$blah ) {}

function multiLineFunction(
    array $flatList,
    $markup,
    array $otherList,
    $lastOffset=0
) {
}

function multiLineFunction(
    $markup,
    array $otherList,
    $lastOffset=0
) {
}

$noArgs_longVars = function ($longVar1,  $longerVar2= false) use (
    $longVar1 ,  $longerVar2= false,
    $muchLongerVar3
)  {
    // body
};

// @codingStandardsChangeSetting Squiz.Functions.FunctionDeclarationArgumentSpacing equalsSpacing 1
function myFunc($blah = 'hello') {}
function myFunc($blah  =  'hello') {}
function myFunc($blah =  'hello') {}
function myFunc($blah  = 'hello') {}
// @codingStandardsChangeSetting Squiz.Functions.FunctionDeclarationArgumentSpacing equalsSpacing 0
?>
<?php
/**
 * Unit test class for the GlobalFunction sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the GlobalFunction sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Functions_GlobalFunctionUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array();

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                2 => 1,
               );

    }//end getWarningList()


}//end class

?>
<?php
function myFunc($blah, $x, $blah) {}
function myFunc($a, $b, $c) {}
function myFunc($a, $a, $a) {}
function myFunc($a='1', $b='1', $a='2') {}
?>
<?php
Function MyFunction() {}
Public function MyFunction() {}
Private function MyFunction() {}
Protected function MyFunction() {}
Static function MyFunction() {}
?>
<?php
/**
 * Unit test class for the MultiLineFunctionDeclaration sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the MultiLineFunctionDeclaration sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Functions_MultiLineFunctionDeclarationUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                2  => 1,
                3  => 1,
                4  => 3,
                5  => 1,
                7  => 1,
                11 => 1,
                12 => 1,
                13 => 1,
                16 => 1,
                33 => 1,
                36 => 1,
                43 => 2,
                48 => 1,
                81 => 1,
                82 => 2,
                88 => 2,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the LowercaseFunctionKeywords sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the LowercaseFunctionKeywords sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Functions_LowercaseFunctionKeywordsUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                2 => 1,
                3 => 1,
                4 => 1,
                5 => 1,
                6 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
public function someFunctionWithAVeryLongName($firstParameter='something',
   $secondParameter='booooo',
   $third=null, $fourthParameter=false,
     $fifthParameter=123.12,
    $sixthParam=true
){
}

function someFunctionWithAVeryLongName2(
$firstParameter='something',
$secondParameter='booooo',
)  {
}

function blah() {
}

function blah()
{
}

class MyClass
{

    public function someFunctionWithAVeryLongName(
        $firstParameter='something',
        $secondParameter='booooo',
        $third=null,
        $fourthParameter=false,
        $fifthParameter=123.12,
        $sixthParam=true
    ) /** w00t */ {
    }

    public function someFunctionWithAVeryLongName2($firstParameter='something',
        $secondParameter='booooo',
        $third=null
    ) {
    }

     public function someFunctionWithAVeryLongName3(
         $firstParameter, $secondParameter, $third=null
     ) {
     }

     public function someFunctionWithAVeryLongName4(
         $firstParameter, $secondParameter
     ) {
     }

     public function someFunctionWithAVeryLongName5(
         $firstParameter,
         $secondParameter=array(1,2,3),
         $third=null
     ) {
     }

}

$noArgs_longVars = function () use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
    // body
};

$longArgs_longVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
    // body
};

$longArgs_longVars = function ($longArgument,
    $muchLongerArgument) use ($muchLongerVar3
) {
    // body
};

$noArgs_longVars = function () use (
    $longVar1,  $longerVar2,
    $muchLongerVar3
) {
    // body
};

usort(
    $data,
    function ($a, $b) {
        // body
    }
);
?>
<?php


function func1()
{

}//end func1()


function func1() {

}//end func1()


class MyClass
{


    private function func1()
    {

    }//end func1()


    public function func1() {

    }//end func1()


}//end class


abstract class MyClass
{


    abstract function func1();


    public function func1() {

    }//end func1()


}//end class


interface MyInterface
{


    function func1();


    function func2() ;


}//end interface

function recurseCreateTree(
    array $flatList,
    $markup,
    $lastOffset=0
) {
}
?>
<?php
/**
 * Unit test class for the LowercaseDeclaration sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the LowercaseDeclaration sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_ControlStructures_LowercaseDeclarationUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                3  => 1,
                5  => 1,
                7  => 1,
                9  => 1,
                10 => 1,
                12 => 1,
                14 => 1,
                15 => 1,
                16 => 1,
                20 => 1,
                21 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php

// Valid.
for ($i = 0; $i < 10; $i++) {
}

// Invalid.
for ( $i = 0; $i < 10; $i++ ) {
}

for ($i = 0;  $i < 10;  $i++) {
}

for ($i = 0 ; $i < 10 ; $i++) {
}

for ($i = 0;$i < 10;$i++) {
}

// The works.
for ( $i = 0 ;  $i < 10 ;  $i++ ) {
}

for ($i = 0; $i < 10;) {
}

for ($i = 0; $i < 10; ) {
}

for ($i = 0; ; $i++) {
}
for ($i = 0;; $i++) {
}

?>
<?php
/**
 * Unit test class for the ControlSignature sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ControlSignature sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_ControlStructures_ControlSignatureUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='ControlSignatureUnitTest.inc')
    {
        switch ($testFile) {
        case 'ControlSignatureUnitTest.inc':
            return array(
                    9   => 1,
                    14  => 1,
                    20  => 1,
                    22  => 1,
                    32  => 1,
                    36  => 1,
                    44  => 1,
                    48  => 1,
                    56  => 1,
                    60  => 1,
                    68  => 1,
                    72  => 1,
                    84  => 1,
                    88  => 2,
                    100 => 1,
                    104 => 2,
                    116 => 2,
                    120 => 3,
                    122 => 1,
                    126 => 1,
                    130 => 1,
                    134 => 1,
                    139 => 1,
                    148 => 1,
                    152 => 1,
                    158 => 1,
                   );
        break;
        case 'ControlSignatureUnitTest.js':
            return array(
                    7   => 1,
                    12  => 1,
                    18  => 1,
                    20  => 1,
                    29  => 1,
                    33  => 1,
                    40  => 1,
                    44  => 1,
                    51  => 1,
                    55  => 1,
                    66  => 1,
                    70  => 2,
                    88  => 2,
                    92  => 3,
                    94  => 1,
                    98  => 1,
                    102 => 1,
                    106 => 1,
                    111 => 1,
                    120 => 1,
                    124 => 1,
                   );
            break;
        default:
            return array();
            break;
        }//end switch

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
// Valid.
for (var i = 0; i < 10; i++) {
}

// Invalid.
for ( i = 0; i < 10; i++ ) {
}

for (i = 0;  i < 10;  i++) {
}

for (var i = 0 ; i < 10 ; i++) {
}

for (i = 0;i < 10;i++) {
}

// The works.
for ( var i = 0 ;  i < 10 ;  i++ ) {
}

this.formats = {};
dfx.inherits('ContentFormat', 'Widget');

for (var widgetid in this.loadedContents) {
    if (dfx.isset(widget) === true) {
        widget.loadAutoSaveCWidgetStore.setData('activeScreen', null);widget.getContents(this.loadedContents[widgetid], function() {self.widgetLoaded(widget.id);});
    }
}

for (var i = 0; i < 10;) {
}
for (var i = 0; i < 10; ) {
}

for (var i = 0; ; i++) {
}
for (var i = 0;; i++) {
}
// do ... while
i = 0;
do {
    i = 0;
} while (i > 0);

do
{
    i = 0;
} while (i > 0);

do
{
    i = 0;
}
while (i > 0);

do { i = 0; } while (i > 0);

do{
    i = 0;
}while(i > 0);

// while
while (i < 1) {
    i = 0;
}

while(i < 1){
    i = 0;
}

while (i < 1) { i = 0; }

// for
for (i = 1; i < 1; i++) {
    i = 0;
}

for(i = 1; i < 1; i++){
    i = 0;
}

for (i = 1; i < 1; i++) { i = 0; }

// if
if (i == 0) {
    i = 1;
}

if(i == 0){
    i = 1;
}

if (i == 0) { i = 1; }

// else
if (i == 0) {
    i = 1;
} else {
    i = 0;
}

if (i == 0) {
    i = 1;
}else{
    i = 0;
}

if (i == 0) { i = 1; } else { i = 0; }

// else
if (i == 0) {
    i = 1;
} else {
    i = 0;
}

// else if
if (i == 0) {
    i = 1;
} else if (i == 2) {
    i = 0;
}

if (i == 0) {
    i = 1;
}else if(i == 2){
    i = 0;
}

if (i == 0) { i = 1; } else if (i == 2) { i = 0; }

if (i == 0) { // comments are not allowed
    i = 1;
}

if (i == 0) {// comments are not allowed
    i = 1;
}

if (i == 0) { /* comments are not allowed*/
    i = 1;
}

if (i == 0)
{ // this is not ok
    i = 1;
}

if (i == 0) /* this is not ok */ {
}

try {
    code = 'this';
} catch (e) {
    // Caught!
}

try { code = 'this'; } catch (e) {
    // Caught!
}

do { i = 0;
} while (i > 0);<?php

// Valid SWITCH statement.
switch ($something) {
    case '1':
        $case = '1';
    break;

    case '2':
    case '3':
        $case = '5';
    break;

    case '4':
        $case = '4';
    break;

    default:
        $case = null;
    break;
}

// Alignment wrong.
switch ($something) {
    case '1':
        $case = '1';
        return '1';

case '2':
    case '3':
        $case = '5';
    break;

case '4':
    $case = '4';
break;

    default:
        $case = null;
    break;
}

// Closing brace wrong.
switch ($something) {
    case '1':
        $case = '1';
    break;
    }

// PEAR style.
switch ($something) {
case '1':
    $case = '1';
    break;
case '2':
case '3':
    $case = '5';
    break;
case '4':
    $case = '4';
    break;
default:
    $case = null;
    break;
}

// Valid, but missing BREAKS.
switch ($something) {
    case '1':
        $case = '1';

    case '2':
    case '3':
        $case = '5';

    case '4':
        $case = '4';

    default:
        $case = null;
}

// Invalid, and missing BREAKS.
switch ($something) {
    Case '1' :
        $case = '1';

case  '2':
    case  '3' :
        $case = '5';

    case'4':
        $case = '4';

    Default :
        $case = null;
        $something = 'hello';
        $other = 'hi';
    }

// Valid
switch ($condition) {
    case 'string':
        $varStr = 'test';

    default:
        // Ignore the default.
    break;
}

// No default comment
switch ($condition) {
    case 'string':
        $varStr = 'test';

    default:
    break;
}

// Break problems
switch ($condition) {
    case 'string':


        $varStr = 'test';

    break;


    case 'bool':
        $varStr = 'test';


    break;
    default:

        $varStr = 'test';
    break;

}

switch ($var) {
    case 'one':
    case 'two':
    break;

    case 'three':
        // Nothing to do.
    break;

    case 'four':
        echo $hi;
    break;

    default:
        // No default.
    break;
}

switch ($var) {
    case 'one':
        if ($blah) {
        }

    break;

    default:
        // No default.
    break;
}

switch ($name) {
    case "1":
        switch ($name2) {
            case "1":
                return true;
            break;

            case "2":
            return true;
            break;

            default:
                // No default.
            break;
        }
    break;

    case "2":
switch ($name2) {
    case "1":
        return true;
    break;

    case "2":
    return true;
    break;

    default:
        // No default.
    break;
}
    break;
}

switch ($name) {
    case "1":
        switch ($name2) {
            case "1":
            return true;

            default:
                // No default.
            break;
        }
    break;

    default:
        // No default.
    break;
}

switch ($name2) {
    default:
        // No default.
    break;
}

switch ($foo) {
    case "1":
    return true;

    default:
        if ($foo === FALSE) {
            break(2);
        }
    break;
}

// Valid SWITCH statement.
switch ($something) {
    case '1':
        $case = '1';
    return '1';

    case '2':
    case '3':
        $case = '5';
    return '2';

    case '4':
        $case = '4';
    return '3';

    default:
        $case = null;
    return '4';
}

switch ($something) {
    case '1':
        $case = '1';
    break;

    case '2':
        throw new Exception('message');

    default:
    throw new Exception('message');
}
?>
<?php
/**
 * Unit test class for the InlineIfDeclaration sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the InlineIfDeclaration sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_ControlStructures_InlineIfDeclarationUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                4  => 1,
                5  => 1,
                6  => 1,
                7  => 1,
                8  => 1,
                9  => 1,
                10 => 1,
                13 => 1,
                20 => 1,
                24 => 4,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php

echo 'var is '.(($var < 0) ? 'negative' : 'positive');
echo 'var is '.($var < 0 ? 'negative' : 'positive');
echo 'var is '.(($var < 0) ? 'negative' :'positive');
echo 'var is '.(($var < 0) ? 'negative': 'positive');
echo 'var is '.(($var < 0) ? 'negative' :   'positive');
echo 'var is '.(($var < 0) ? 'negative'   : 'positive');
echo 'var is '.(($var < 0) ?   'negative' : 'positive');
echo 'var is '.(($var < 0)  ? 'negative' : 'positive');

echo 'var is '.(($var < 0)
                    ? 'negative'
                    : 'positive');

$args = array(
         '"'.$this->id.'"',
         '"'.$this->stepInfo['title'].'"',
         '"'.((isset($this->stepInfo['description']) === TRUE) ? $this->stepInfo['description'] : '').'"',
         '"'.(isset($this->stepInfo['description']) === TRUE ? $this->stepInfo['description'] : '').'"',
         '"'.$this->stepInfo['title'].'"',
        );

echo (TRUE)?'Hello':'Bye';

?><?php
/**
 * Unit test class for the SwitchDeclaration sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the SwitchDeclaration sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_ControlStructures_SwitchDeclarationUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='SwitchDeclarationUnitTest.inc')
    {
        return array(
                27  => 1,
                29  => 1,
                34  => 1,
                36  => 1,
                44  => 1,
                48  => 1,
                52  => 1,
                54  => 1,
                55  => 1,
                56  => 1,
                58  => 1,
                59  => 1,
                61  => 1,
                62  => 1,
                79  => 1,
                85  => 2,
                88  => 2,
                89  => 2,
                92  => 1,
                95  => 3,
                99  => 1,
                116 => 1,
                122 => 1,
                127 => 2,
                134 => 2,
                135 => 1,
                138 => 1,
                143 => 1,
                144 => 1,
                147 => 1,
                165 => 1,
                172 => 1,
                176 => 2,
                180 => 1,
                192 => 2,
                196 => 1,
                223 => 1,
                266 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the ForLoopDeclaration sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ForEachLoopDeclaration sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_ControlStructures_ForLoopDeclarationUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='ForLoopDeclarationUnitTest.inc')
    {
        switch ($testFile) {
        case 'ForLoopDeclarationUnitTest.inc':
            return array(
                8  => 2,
                11 => 2,
                14 => 2,
                17 => 2,
                21 => 6,
                27 => 1,
                30 => 1,
               );
             break;
        case 'ForLoopDeclarationUnitTest.js':
            return array(
                6  => 2,
                9  => 2,
                12 => 2,
                15 => 2,
                19 => 6,
                33 => 1,
                36 => 1,
               );
             break;
        default:
            return array();
            break;
        }//end switch

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php

// Valid.
foreach ($something as $blah => $that) {
}

// Invalid.
foreach ( $something as $blah => $that ) {
}

foreach ($something   as   $blah => $that) {
}

foreach ($something as $blah   =>  $that) {
}

foreach (${something}AS$blah=>$that) {
}

// The works.
foreach (  $something   aS   $blah    =>   $that   ) {
}

?><?php
/**
 * Unit test class for the ForEachLoopDeclaration sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ForEachLoopDeclaration sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_ControlStructures_ForEachLoopDeclarationUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                8  => 2,
                11 => 2,
                14 => 2,
                17 => 5,
                21 => 7,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>


// Valid SWITCH statement.
switch (something) {
    case '1':
        myvar = '1';
    break;

    case '2':
    case '3':
        myvar = '5';
    break;

    case '4':
        myvar = '4';
    break;

    default:
        myvar = null;
    break;
}

// Alignment wrong.
switch (something) {
    case '1':
        myvar = '1';
        break;

case '2':
    case '3':
        myvar = '5';
    break;

case '4':
    myvar = '4';
break;

    default:
        myvar = null;
    break;
}

// Closing brace wrong.
switch (something) {
    case '1':
        myvar = '1';
    break;
    }

// PEAR style.
switch (something) {
case '1':
    myvar = '1';
    break;
case '2':
case '3':
    myvar = '5';
    break;
case '4':
    myvar = '4';
    break;
default:
    myvar = null;
    break;
}

// Valid, but missing BREAKS.
switch (something) {
    case '1':
        myvar = '1';

    case '2':
    case '3':
        myvar = '5';

    case '4':
        myvar = '4';

    default:
        myvar = null;
}

// Invalid, and missing BREAKS.
switch (something) {
    Case '1' :
        myvar = '1';

case  '2':
    case  '3' :
        myvar = '5';

    case'4':
        myvar = '4';

    Default :
        myvar = null;
        something = 'hello';
        other = 'hi';
    }

// Valid
switch (condition) {
    case 'string':
        varStr = 'test';

    default:
        // Ignore the default.
    break;
}

// No default comment
switch (condition) {
    case 'string':
        varStr = 'test';

    default:
    break;
}

// Break problems
switch (condition) {
    case 'string':


        varStr = 'test';

    break;


    case 'bool':
        varStr = 'test';


    break;
    default:

        varStr = 'test';
    break;

}

switch (var) {
    case 'one':
    case 'two':
    break;

    case 'three':
        // Nothing to do.
    break;

    case 'four':
        echo hi;
    break;

    default:
        // No default.
    break;
}

switch (var) {
    case 'one':
        if (blah) {
        }

    break;

    default:
        // No default.
    break;
}

switch (name) {
    case "1":
        switch (name2) {
            case "1":
                return true;
            break;

            case "2":
            return true;
            break;

            default:
                // No default.
            break;
        }
    break;

    case "2":
switch (name2) {
    case "1":
        return true;
    break;

    case "2":
    return true;
    break;

    default:
        // No default.
    break;
}
    break;
}

switch (name) {
    case "1":
        switch (name2) {
            case "1":
            return true;

            default:
                // No default.
            break;
        }
    break;

    default:
        // No default.
    break;
}

switch (name2) {
    default:
        // No default.
    break;
}

switch (foo) {
    case "1":
    return true;

    default:
        if (foo === false) {
            break;
        }
    break;
}

// Valid SWITCH statement.
switch (something) {
    case '1':
        myvar = '1';
    return '1';

    case '2':
    case '3':
        myvar = '5';
    return '2';

    case '4':
        myvar = '4';
    return '3';

    default:
        myvar = null;
    return '4';
}

switch (something) {
    case '1':
        myvar = '1';
    break;

    case '2':
        throw 'message';

    default:
    throw 'message';
}
<?php

// do ... while
$i = 0;
do {
    echo $i;
} while ($i > 0);

do
{
    echo $i;
} while ($i > 0);

do
{
    echo $i;
}
while ($i > 0);

do { echo $i; } while ($i > 0);

do{
    echo $i;
}while($i > 0);


// while
while ($i < 1) {
    echo $i;
}

while($i < 1){
    echo $i;
}

while ($i < 1) { echo $i; }


// for
for ($i = 1; $i < 1; $i++) {
    echo $i;
}

for($i = 1; $i < 1; $i++){
    echo $i;
}

for ($i = 1; $i < 1; $i++) { echo $i; }


// foreach
foreach ($items as $item) {
    echo $item;
}

foreach($items as $item){
    echo $item;
}

for ($items as $item) { echo $item; }


// if
if ($i == 0) {
    $i = 1;
}

if($i == 0){
    $i = 1;
}

if ($i == 0) { $i = 1; }


// else
if ($i == 0) {
    $i = 1;
} else {
    $i = 0;
}

if ($i == 0) {
    $i = 1;
}else{
    $i = 0;
}

if ($i == 0) { $i = 1; } else { $i = 0; }


// else
if ($i == 0) {
    $i = 1;
} else {
    $i = 0;
}

if ($i == 0) {
    $i = 1;
}else{
    $i = 0;
}

if ($i == 0) { $i = 1; } else { $i = 0; }


// else if
if ($i == 0) {
    $i = 1;
} else if ($i == 2) {
    $i = 0;
}

if ($i == 0) {
    $i = 1;
}else if($i == 2){
    $i = 0;
}

if ($i == 0) { $i = 1; } else if ($i == 2) { $i = 0; }

if ($i == 0) { // comments are not allowed
    $i = 1;
}

if ($i == 0) {// comments are not allowed
    $i = 1;
}

if ($i == 0) { /* comments are not allowed*/
    $i = 1;
}

if ($i == 0)
{ // this is not ok
    $i = 1;
}

if ($i == 0) /* this is not ok */ {
}

try {
    $code = 'this';
} catch (Exception $e) {
    // Caught!
}

try { $code = 'this'; } catch (Exception $e) {
    // Caught!
}

do { echo $i;
} while ($i > 0);

if ($a) {

}
elseif ($b) {

}
?>
<?php

Foreach ($condition as $cond) {}

FOR ($i = 1; $i < 10; $i++) {}

wHile ($i < 10) {}

DO {
} While ($1 < 10)

Switch ($condition) {}

If ($condition) {
} elsE if ($condition) {
} elseIf ($condition) {
} else {
}

TRY {
} Catch (Exception $e) {
}
?><?php

if ($something) {
} else if ($somethingElse) {
}

if ($something) {
} elseif ($somethingElse) {
}

if ($something) {
} else if ($somethingElse) {
} elseif ($another) {
}

?><?php
/**
 * Unit test class for the ElseIfDeclaration sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ElseIfDeclaration sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_ControlStructures_ElseIfDeclarationUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                8  => 1,
                13 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the IncrementDecrementUsage sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the IncrementDecrementUsage sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Operators_IncrementDecrementUsageUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                2  => 1,
                6  => 1,
                12 => 1,
                16 => 1,
                25 => 1,
                26 => 1,
                27 => 1,
                29 => 1,
                31 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
if ($value === TRUE || $other === FALSE) {
}

if ($value === TRUE OR $other === FALSE) {
}

if ($value === TRUE && $other === FALSE) {
}

if ($value === TRUE and $other === FALSE) {
}

if ($one === TRUE && ($two === TRUE || $three === TRUE)) {
}

if ($one === TRUE AND ($two === TRUE or $three === TRUE)) {
}

if ($a ^ $b) {
}

if ($a xor $b) {
}

if ($a XOR $b) {
}
?>
<?php
/**
 * Unit test class for the ComparisonOperatorUsage sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ComparisonOperatorUsage sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Operators_ComparisonOperatorUsageUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='ComparisonOperatorUsageUnitTest.inc')
    {
        switch ($testFile) {
        case 'ComparisonOperatorUsageUnitTest.inc':
            return array(
                    6  => 1,
                    7  => 1,
                    10 => 1,
                    11 => 1,
                    18 => 1,
                    19 => 1,
                    22 => 1,
                    23 => 1,
                    29 => 2,
                    32 => 2,
                    38 => 4,
                    47 => 2,
                    69 => 1,
                    72 => 1,
                    75 => 1,
                    78 => 1,
                    80 => 1,
                    82 => 1,
                    83 => 1,
                   );
            break;
        case 'ComparisonOperatorUsageUnitTest.js':
            return array(
                    5  => 1,
                    6  => 1,
                    17 => 1,
                    18 => 1,
                    28 => 2,
                   );
            break;
        default:
            return array();
            break;
        }//end switch

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the ValidLogicalOperators sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ValidLogicalOperators sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Operators_ValidLogicalOperatorsUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                5  => 1,
                11 => 1,
                17 => 2,
                23 => 1,
                26 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
if (value === TRUE) {
} else if (value === FALSE) {
}

if (value == TRUE) {
} else if (value == FALSE) {
}

if (value) {
} else if (!value) {
}

if (value.isSomething === TRUE) {
} else if (myFunction(value) === FALSE) {
}

if (value.isSomething == TRUE) {
} else if (myFunction(value) == FALSE) {
}

if (value.isSomething) {
} else if (!myFunction(value)) {
}

if (value === TRUE || other === FALSE) {
}

if (value == TRUE || other == FALSE) {
}

if (value || !other) {
}

if (one === TRUE || two === TRUE || three === FALSE || four === TRUE) {
}

if (one || two || !three || four) {
}
<?php
$var  = ($var + 1);
$var  = ($one + 1);
$var  = ($var + 2);
$var  = ($one + $two + 1);
$var += 1;
$var += 2;
$var += $one;
$var += (1 + 2)
$var  = myFunction($var, ($one + 1));

$var  = ($var - 1);
$var  = ($one - 1);
$var  = ($var - 2);
$var  = ($one - $two - 1);
$var -= 1;
$var -= 2;
$var -= $one;
$var -= (1 + 2)
$var  = myFunction($var, ($one - 1));

$var -= $var - 1;
$var += $var - 1;

$id = $id.'_'.($i-- - $x--).'_'.$x;
$id = $id.'_'.(++$i - $x--).'_'.$x;
$id = $id.'_'.(--$i - $x++).'_'.$x;

$id = $id.'_'.$i++;
$id = $id.'_'.($i++);
$id = $id.'_'.$i--.'_';
$id = $id.'_'.($i--).'_';

$var = (1 - $var);
$var = (1 + $var);

$expected[$i]['sort_order'] = ($i + 1);
$expected[($i + 1)]['sort_order'] = ($i + 1);
?>
<?php
if ($value === TRUE) {
} else if ($value === FALSE) {
}

if ($value == TRUE) {
} else if ($value == FALSE) {
}

if ($value) {
} else if (!$value) {
}

if (is_array($array) === TRUE) {
} else if (myFunction($value) === FALSE) {
}

if (is_array($array) == TRUE) {
} else if (myFunction($value) == FALSE) {
}

if (is_array($array)) {
} else if (!myFunction($value)) {
}

if ($value === TRUE || $other === FALSE) {
}

if ($value == TRUE || $other == FALSE) {
}

if ($value || !$other) {
}

if ($one === TRUE || $two === TRUE || $three === FALSE || $four === TRUE) {
}

if ($one || $two || !$three || $four) {
}

if ($var instanceof PHP_CodeSniffer) {
}

if (($var instanceof PHP_CodeSniffer) === false) {
}

if ($good && ($var instanceof PHP_CodeSniffer) === false && $good) {
}

if ($good === true && ($var instanceof PHP_CodeSniffer) === false) {
}

// Without brackets around inline IF condition.
$var1 === TRUE
    ? $var2 = 0
    : $var2 = 1;

$var1 === TRUE ? $var2 = 0 : $var2 = 1;
?>
<?php
$var1 === TRUE ? $var2 = 0 : $var2 = 1;

if ($var2 === TRUE) {
    $var1 === TRUE ? $var2 = 0 : $var2 = 1;
}
$var1 === TRUE ? $var2 = 0 : $var2 = 1;

$var1
    ? $var2 = 0
    : $var2 = 1;

$var1 ? $var2 = 0 : $var2 = 1;


$var1 ? $var2 = 0 : $var2 = 1;

if ($var2 === TRUE) {
    $var1 ? $var2 = 0 : $var2 = 1;
}
$var1 ? $var2 = 0 : $var2 = 1;

if ($value) {
} elseif (!$value) {
}
?>
this.request({ action: 'getTypeFormatContents', });

addTypeFormatButton.addClickEvent(function() {
   self.addNewTypeFormat();
});

var x = {};

var y = {
   VarOne  : 'If you ask me, thats if you ask',
   VarTwo  : ['Alonzo played you', 'for a fool', 'esse'],
   VarThree: function(arg) {
       console.info(1);
   }
};

var z = {
   VarOne  : 'If you ask me, thats if you ask',
   VarTwo  : ['Alonzo played you', 'for a fool', 'esse'],
   VarThree: function(arg) {
       console.info(1);
   },
};

var x = function() {
   console.info(2);
};

AssetListingEditWidgetType.prototype = {
   init: function(data, assetid, editables)
   {
   }
};

AssetListingEditWidgetType.prototype = {
   init: function(data, assetid, editables)
   {
   },
};
<?php
$obj = new MyClass();
$obj =& new MyClass();
$obj = &new MyClass();
new MyClass();

$objects = array('one' => new MyClass());
$object->myFunction(new MyClass());

throw new MyException($msg);

function foo() { return new MyClass(); }

$doodad = $x ? new Foo : new Bar;
?>
<?php
/**
 * Unit test class for the ObjectMemberComma sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ObjectMemberComma sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Objects_ObjectMemberCommaUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='ObjectMemberCommaUnitTest.js')
    {
        if ($testFile !== 'ObjectMemberCommaUnitTest.js') {
            return array();
        }

        return array(
                1  => 1,
                22 => 1,
                38 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the ObjectInstantiation sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ObjectInstantiation sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Objects_ObjectInstantiationUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                5 => 1,
                8 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the DisallowObjectStringIndex sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer_MySource
 * @author    Sertan Danis <sdanis@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the DisallowObjectStringIndex sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Sertan Danis <sdanis@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Objects_DisallowObjectStringIndexUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='DisallowObjectStringIndexUnitTest.js')
    {
        if ($testFile !== 'DisallowObjectStringIndexUnitTest.js') {
            return array();
        }

        return array(
                13 => 1,
                17 => 1,
                25 => 1,
                35 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
function test(id)
{

    this.id = id;

}
/**/
test.prototype = {
    init: function()
    {
        var x      = {};
        x.name     = 'test';
        x['phone'] = 123124324;
        var t      = ['test', 'this'].join('');
        var y      = ['test'].join('');
        var a      = x[0];
        var z      = x[x['name']];
        var p      = x[x.name];
    }

};

function test() {
    this.errors['step_' + step] = errors;
    this.errors['test'] = x;
    this.errors['test' + 10] = x;
    this.errors['test' + y] = x;
    this.errors['test' + 'blah'] = x;
    this.errors[y] = x;
    this.errors[y + z] = x;
    this.permissions['workflow.cancel'] = x;
}

if (child.prototype) {
    above.prototype['constructor'] = parent;
    child.prototype['super']       = new above();
}
<?php
/**
 * Unit test class for the PostStatementComment sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the PostStatementComment sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Commenting_PostStatementCommentUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='PostStatementCommentUnitTest.inc')
    {
        switch ($testFile) {
        case 'PostStatementCommentUnitTest.inc':
            return array(
                    6  => 1,
                    10 => 1,
                    18 => 1,
                   );
            break;
        case 'PostStatementCommentUnitTest.js':
            return array(
                    1 => 1,
                    4 => 1,
                    9 => 1,
                   );
            break;
        default:
            return array();
            break;
        }//end switch

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/** File doc comment */

class No_Comment
{

}//end class


//
// Sample class comment
//
//
//
class Invalid_Comment_Style1
{

}//end class


/**
 *
 *
 * Sample class comment.
 *
 *
 * Long description with extra blank line before and after
 *
 *
 * @version   Release: 1.0
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Extra_Description_Newlines
{

}//end class


/**
 * Sample class comment...
 */
class Missing_Newlines_Before_Tags
{

}//end class


/**
 * Simple class comment
 *
 * @deprecated asd
 */
class Checking_Tags
{
    class Sub_Class {

    }//end class


}//end class


/**
 * Simple class comment
 * that spans multiple line
 * and not end with a full stop
 *
 * @hello      Hello tag
 * @package    phpcs
 */
class Unknown_Hello_Tag
{

}//end class


/**
 *
 *
 *
 */
class Empty_Class_Doc
{

}//end class


/**
 */
class Missing_Short_Desc
{

}//end class


/**
 * sample class comment.
 *
 * - long description with extra blank line before and after
 */
class Incorrect_Case
{

}//end class


/**
 * 0sample class comment.
 *
 * long description with extra blank line before and after
 */
class Incorrect_Case2
{

}//end class


/** Sample class comment.
 */
class Start_Tag_Incorrect
{

}//end class

/**
 * 这是一条测试评论.
 *
 */
class Space_At_end
{

}//end class
?>
<?php
/**
 * Unit test class for ClassCommentSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for ClassCommentSniff.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Commenting_ClassCommentUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                4   => 1,
                15  => 1,
                22  => 1,
                25  => 1,
                28  => 1,
                49  => 1,
                55  => 1,
                64  => 2,
                77  => 1,
                88  => 1,
                97  => 1,
                99  => 1,
                108 => 1,
                110 => 1,
                118 => 1,
                128 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                30 => 1,
                31 => 1,
                51 => 1,
                68 => 1,
                69 => 1,
               );

    }//end getWarningList()


}//end class

?>
<?php

function test()
{
    $string = 'hello';
    $string = 'hello'; // Set string to hello.
    // Valid comment.
}

function test() // This is a function
{

}//end test()


class TestClass
{
    public $good = true; // Indeed.

}//end class

?>function long_function()
{
    if (longFunction) {
        // This is a long
        // IF statement
        // that does
        // not have
        // and ELSE
        // block on it
        variable = 'hello';

        if (variable === 'hello') {
            // This is a short
            // IF statement
        }

        if (variable === 'hello') {
            // This is a short
            // IF statement
        } else {
            // This is a short ELSE
            // statement
        }
    }//end if

    if (longFunction) {
        // This is a long
        // IF statement
        // that does
        // not have
        // and ELSE
        // block on it
        variable = 'hello';

        if (variable === 'hello') {
            // This is a short
            // IF statement
        }

        if (variable === 'hello') {
            // This is a short
            // IF statement
        } else {
            // This is a short ELSE
            // statement
        }
    }

    if (longFunction) {
        // This is a long
        // IF statement
        // that does
        // not have
        // and ELSE
        // block on it
        variable = 'hello';

        if (variable === 'hello') {
            // This is a short
            // IF statement
        }

        if (variable === 'hello') {
            // This is a short
            // IF statement
        } else {
            // This is a short ELSE
            // statement
        }
    } else {
        // Short ELSE
    }//end if

    if (longFunction) {
        // This is a long
        // IF statement
        // that does
        // not have
        // and ELSE
        // block on it
        variable = 'hello';

        if (variable === 'hello') {
            // This is a short
            // IF statement
        }

        if (variable === 'hello') {
            // This is a short
            // IF statement
        } else {
            // This is a short ELSE
            // statement
        }
    } else {
        // Short ELSE
    }
}

for (variable=1; variable < 20; variable++) {
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    // Line 6
    // Line 7
    // Line 8
    // Line 9
    // Line 10
    // Line 11
    // Line 12
    // Line 13
    // Line 14
    // Line 15
    // Line 16
    // Line 17
    // Line 18
    // Line 19
    // Line 20
}//end for

for (variable=1; variable < 20; variable++) {
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    // Line 6
    // Line 7
    // Line 8
    // Line 9
    for (val =1; val < 20; val++) {
        // Short for.
    }
    // Line 13
    // Line 14
    // Line 15
    // Line 16
    // Line 17
    // Line 18
    // Line 19
    // Line 20
}

while (variable < 20) {
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    // Line 6
    // Line 7
    // Line 8
    // Line 9
    // Line 10
    // Line 11
    // Line 12
    // Line 13
    // Line 14
    // Line 15
    // Line 16
    // Line 17
    // Line 18
    // Line 19
    // Line 20
}//end while

while (variable < 20) {
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    // Line 6
    // Line 7
    // Line 8
    // Line 9
    while (something) {
        // Short while.
    }
    // Line 13
    // Line 14
    // Line 15
    // Line 16
    // Line 17
    // Line 18
    // Line 19
    // Line 20
}

if (longFunction) {
    // This is a long
    // IF statement
    // that does
    // not have
    // and ELSE
    // block on it
    variable = 'hello';

    if (variable === 'hello') {
        // This is a short
        // IF statement
    }

    if (variable === 'hello') {
        // This is a short
        // IF statement
    } else {
        // This is a short ELSE
        // statement
    }
} //end if

if (longFunction) {
    // This is a long
    // IF statement
    // that does
    // not have
    // and ELSE
    // block on it
    variable = 'hello';

    if (variable === 'hello') {
        // This is a short
        // IF statement
    }

    if (variable === 'hello') {
        // This is a short
        // IF statement
    } else {
        // This is a short ELSE
        // statement
    }
} else {
    // Short ELSE
} //end if

for (variable=1; variable < 20; variable++) {
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    // Line 6
    // Line 7
    // Line 8
    // Line 9
    // Line 10
    // Line 11
    // Line 12
    // Line 13
    // Line 14
    // Line 15
    // Line 16
    // Line 17
    // Line 18
    // Line 19
    // Line 20
} //end for

while (variable < 20) {
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    // Line 6
    // Line 7
    // Line 8
    // Line 9
    // Line 10
    // Line 11
    // Line 12
    // Line 13
    // Line 14
    // Line 15
    // Line 16
    // Line 17
    // Line 18
    // Line 19
    // Line 20
} //end while

while (variable < 20) {
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    // Line 6
    // Line 7
    // Line 8
    // Line 9
    // Line 10
    // Line 11
    // Line 12
    // Line 13
    // Line 14
    // Line 15
    // Line 16
    // Line 17
    // Line 18
    // Line 19
    // Line 20
}//end for

if (true) {
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    // Line 6
    // Line 7
    // Line 8
    // Line 9
    // Line 10
    // Line 11
    // Line 12
    // Line 13
    // Line 14
    // Line 15
    // Line 16
    // Line 17
    // Line 18
    // Line 19
    // Line 20
} else if (condition) {
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    // Line 6
    // Line 7
    // Line 8
    // Line 9
    // Line 10
    // Line 11
    // Line 12
    // Line 13
    // Line 14
    // Line 15
    // Line 16
    // Line 17
    // Line 18
    // Line 19
    // Line 20
} else {
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    // Line 6
    // Line 7
    // Line 8
    // Line 9
    // Line 10
    // Line 11
    // Line 12
    // Line 13
    // Line 14
    // Line 15
    // Line 16
    // Line 17
    // Line 18
    // Line 19
    // Line 20
}//end if

if (something) {
    // Line 1
    // Line 2
} else if (somethingElse) {
    // Line 1
    // Line 2
} else {
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    // Line 6
    // Line 7
    // Line 8
    // Line 9
    // Line 10
    // Line 11
    // Line 12
    // Line 13
    // Line 14
    // Line 15
    // Line 16
    // Line 17
    // Line 18
    // Line 19
    // Line 20
}

switch (something) {
    case '1':
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    break;
    case '2':
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    break;
    case '3':
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    break;
    case '4':
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    break;
    case '5':
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    break;
}

// Wrong comment
if (condition) {
    condition = true;
}//end foreach<?php
/**
 * Unit test class for VariableCommentSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for VariableCommentSniff.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Commenting_VariableCommentUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                6   => 1,
                8   => 1,
                21  => 1,
                24  => 1,
                28  => 1,
                38  => 1,
                41  => 1,
                53  => 1,
                56  => 1,
                63  => 1,
                64  => 1,
                69  => 2,
                73  => 1,
                81  => 1,
                82  => 1,
                84  => 1,
                90  => 1,
                92  => 1,
                128 => 1,
                137 => 1,
                145 => 1,
                153 => 1,
                158 => 1,
                159 => 1,
                163 => 1,
                178 => 1,
                180 => 1,
                184 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                93 => 1,
               );

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the ClosingDeclarationComment sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ClosingDeclarationComment sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Commenting_ClosingDeclarationCommentUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                13 => 1,
                17 => 1,
                31 => 1,
                41 => 1,
                59 => 1,
                63 => 1,
                67 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                71 => 1,
               );

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the LongConditionClosingComment sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the LongConditionClosingComment sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Commenting_LongConditionClosingCommentUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='LongConditionClosingCommentUnitTest.inc')
    {
        switch ($testFile) {
        case 'LongConditionClosingCommentUnitTest.inc':
            return array(
                    49  => 1,
                    99  => 1,
                    146 => 1,
                    192 => 1,
                    215 => 1,
                    238 => 1,
                    261 => 1,
                    286 => 1,
                    309 => 1,
                    332 => 1,
                    355 => 1,
                    378 => 1,
                    493 => 1,
                    531 => 1,
                    536 => 1,
                    540 => 1,
                    562 => 1,
                    601 => 1,
                    629 => 1,
                    663 => 1,
                   );
            break;
        case 'LongConditionClosingCommentUnitTest.js':
            return array(
                    47  => 1,
                    97  => 1,
                    144 => 1,
                    190 => 1,
                    213 => 1,
                    238 => 1,
                    261 => 1,
                    284 => 1,
                    307 => 1,
                    401 => 1,
                    439 => 1,
                    444 => 1,
                   );
            break;
        default:
            return array();
            break;
        }//end switch

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
class FunctionCommentThrowTagUnitTest
{


    /**
     * Missing throw tag.
     *
     */
    public function missingThrowTag()
    {
        throw new PHP_Exception('Error');

    }//end missingThrowTag()


    /**
     * Tag and token number mismatch.
     *
     * @throws PHP_Exception1
     */
    public function oneMoreThrowsTagNeeded()
    {
        throw new PHP_Exception1('Error');
        throw new PHP_Exception2('Error');

    }//end oneMoreThrowsTagNeeded()


    /**
     * Tag and token number mismatch.
     *
     * @throws PHP_Exception1
     * @throws PHP_Exception2
     */
    public function oneLessThrowsTagNeeded()
    {
        throw new PHP_Exception1('Error');

    }//end oneLessThrowsTagNeeded()


    /**
     * Wrong exception type name.
     *
     * @throws PHP_Wrong_Exception
     */
    public function wrongExceptionName()
    {
        throw new PHP_Correct_Exception('Error');

    }//end wrongExceptionName()


    /**
     * Wrong exception type name.
     *
     * @throws PHP_Correct_Exception1
     * @throws PHP_Wrong_Exception2
     * @throws PHP_Wrong_Exception3
     */
    public function moreWrongExceptionName()
    {
        throw new PHP_Correct_Exception1('Error');
        throw new PHP_Correct_Exception2('Error');
        throw new PHP_Correct_Exception3('Error');

    }//end moreWrongExceptionName()


    /**
     * Wrong exception type name.
     *
     * @throws PHP_Correct_Exception
     */
    public function sameExceptionName()
    {
        throw new PHP_Correct_Exception('Error');
        throw new PHP_Correct_Exception('Error');

    }//end sameExceptionName()


    /**
     * This is a valid chunk.
     *
     * @throws PHP_Exception1
     * @throws PHP_Exception2
     */
    public function thisShouldWorkOK()
    {
        throw new PHP_Exception2('Error');
        throw new PHP_Exception1('Error');
        throw new PHP_Exception2('Error');
        throw new PHP_Exception1('Error');
        throw new PHP_Exception2('Error');

    }//end thisShouldWorkOK()


    /**
     * This is not OK, missing 2 @throws tag.
     *
     * @throws PHP_Exception1
     * @throws PHP_Exception2
     */
    public function notOK()
    {
        throw new PHP_Missing_Exception1('Error');
        throw new PHP_Exception2('Error');
        throw new PHP_Missing_Exception2('Error');
        throw new PHP_Missing_Exception2('Error');
        throw new PHP_Exception1('Error');
        throw new PHP_Exception2('Error');
        throw new PHP_Missing_Exception1('Error');

    }//end notOK()


    /**
     * Needs at least 1 throws tag, even though we
     * don't know what it is.
     */
    public function notOKVariable()
    {
        try {
            // Do something.
        } catch (PHP_Exception2 $e) {
            logError();
            throw $e;
        }

    }//end notOKVariable()


    /**
     * Needs at least 1 throws tag, even though we
     * don't know what it is.
     *
     * @throws PHP_Exception1
     */
    public function okVariable()
    {
        throw new PHP_Exception1('Error');

        try {
            // Do something.
        } catch (PHP_Exception1 $e) {
            logError();
            throw $e;
        }

    }//end okVariable()


    /**
     * Needs 1 @throws tag.
     *
     * @throws Exception Unknown exception type.
     */
    function okVariable()
    {
        throw $e;

    }//end okVariable()


    /**
     * Needs 1 @throws tag.
     *
     * @throws Exception Unknown exception type.
     */
    function okFunction()
    {
        throw $this->callSomeFunction();

    }//end okFunction()


    /**
     * Comment inside function.
     *
     * @throws Exception
     */
    function okFunction()
    {
        /**
         * @var FooClass
         */
        $foo = FooFactory::factory();
        throw new Exception;

    }//end okFunction


}//end class

class NamespacedException {
    /**
     * @throws \Exception
     */
    public function foo() {
        throw new \Exception();
    }

    /**
     * @throws \Foo\Bar\FooBarException
     */
    public function fooBar2() {
        throw new \Foo\Bar\FooBarException();
    }
    
    /**
     * @throws FooBarException
     */
    public function fooBar2() {
        throw new \Foo\Bar\FooBarException();
    }
}

class Foo {
    /**
     * Comment
     */
    public function foo() {
    }//end foo()

    public function bar() {
        throw new Exception();
    }
}
?>
function test(id, buttons) // cool function
{
    alert('hello');
    alert('hello again'); // And again.
    // Valid comment.

}//end test()

var good = true; // Indeed.

mig.Gallery.prototype = {

    init: function(cb)
    {

    },//end init()

    imageClicked: function(id)
    {

    }//end imageClicked()

};

dfx.getIframeDocument = function(iframe)
{

    return doc;

};//end dfx.getIframeDocument()<?php
/**
 * Unit test class for FileCommentSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for FileCommentSniff.
 *
 * Verifies that :
 * <ul>
 *  <li>A doc comment exists.</li>
 *  <li>Short description must start with a capital letter and end with a period.</li>
 *  <li>There must be one blank newline after the short description.</li>
 *  <li>A PHP version is specified.</li>
 *  <li>Check the order of the tags.</li>
 *  <li>Check the indentation of each tag.</li>
 *  <li>Check required and optional tags and the format of their content.</li>
 * </ul>
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Commenting_FileCommentUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                1  => 1,
                6  => 3,
                8  => 1,
                10 => 1,
                21 => 1,
                22 => 2,
                23 => 1,
                24 => 2,
                26 => 1,
                30 => 2,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php



/**
*
* 0Multi-line short description without full stop
*
*
* asdasd
* long description for file (if any)
* asdasdadada
*
* PHP versio
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt.  If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
* @package    SquizCMS
* @package    ADDITIONAL PACKAGE TAG
* @subpackage not_camelcased
* @author     Antônio Carlos Venâncio Júnior <foreign@character.net>
* @author
* @copyright  1997~1994 The PHP Group
* @license    http://www.php.net/license/3_0.txt
* @summary    An unknown summary tag
*
*/
?>
<?php
/**
* This bit here is not qualified as file comment
*
* as it is not after the first open tag
*
*/
?>
<?php

/*
    Comments need to be indented 4 space.
*/

/*
    same with multi-line
    comments.
*/

/*
    But they can:
        - be indented more than 4
        - but not less than 4
*/

/*
    - This is not valid:
   Not indented correctly.
*/

/*
   Comments need to be indented 4 space.
*/

/*
    Comments need to be indented 4 space.
     Comments need to be indented 4 space.
   Comments need to be indented 4 space.
  Comments need to be indented 4 space.

    Comments need to be indented 4 space.
   Comments need to be indented 4 space.
*/

/*
    Block comments require a blank
    line after them.
*/
$code = 'should not be here';

/*
    Closing comment not aligned
    */

/*
    Closing comment not aligned
 */

/* Not allowed */

/*  Not allowed
    either.
*/

/* */

$code = 'should not be here';
/*

    Block comments require a blank
    line before them. */

/*
*/

/** Not allowed */

/**  Not allowed
    either.
**/

/**
    no capital
    letter.
*/

echo 'hi';

function func()
{
    echo 1;
    /**
       test
       here
    **/
    echo 'test';
    /**
        Test
        here
       **/

}//end func()

public static function test()
{
    /*
        Block comments do not require a blank line before them
        if they are after T_OPEN_CURLY_BRACKET.
    */

    $code = '';

}//end test()


public static function test()
{

    /*
        Block comments do not require a blank line before them
        if they are after T_OPEN_CURLY_BRACKET.
    */

    $code = '';

}//end test()

class MyClass
{

    /**
     * Comment should be ignored.
     *
     * @var   integer
     * @since 4.0.0
     */
    const LEFT = 1;

}

/**
 * Comment should be ignored.
 *
 */
final class MyClass
{
    /**
     * Comment should be ignored.
     *
     */
    final public function test() {}
}

switch ($var) {
    case 'foo':
        /*
            Foo comment.
            This is a multiple
            line comment for Foo.
        */

        echo 'Foo';
    break;

    default:

        /*
            Foo comment.
            This is a multiple
            line comment for Foo.
        */

        echo 'Default';
    break;
}//end switch

/**
 * Comment should be ignored in PHP 5.4.
 *
 */
trait MyTrait {

}

/*
    这是一条测试评论.
*/

?>
<?php
class PHP_CodeSniffer_File
{

    /**
     * a simple function comment.
     *
     * long desc here
     *
     * @param bool   $stackPtr   The position in @ @unknown the stack of the token
     *                             that opened the scope
     * @param int    $detph    How many scope levels down we are.
     * @param string    $index    The index
     * @return
     * @throws
     */
    private function _functionCall($stackPtr, $depth=1, $index)
    {
        return $stackPtr;

    }//end _functionCall()

    //
    // Sample function comment
    //
    //
    //
    public function invalidCommentStyle()
    {

    }//end invalidCommentStyle()


    /**
     *
     * A simple function comment
     * Span multiple line
     *
     *
     * 0Long description with extra blank line before and after
     *
     *
     * @return void
     */
    public function extraDescriptionNewlines()
    {
        return true;
    }//end extraDescriptionNewlines()


    /**
     * -A simple function comment.
     * @return void
     */
    public function missingNewlinesBeforeTags()
    {
        return;
    }//end missingNewlinesBeforeTags()


    /**
     * Access tag should not be treated as a long description.
     *
     * @access public
     * @return void
     */
    public function accessTag()
    {

    }//end accessTag()

    /**
     * Constructor.
     *
     * No return tag
     */
    function PHP_CodeSniffer_File()
    {
        return;
    }


    /**
     * Destructor.
     *
     * No return tag too
     */
    function _PHP_CodeSniffer_File()
    {
        return;
    }


    /**
     * Destructor PHP5.
     */
    function __destruct()
    {
        return;
    }


    function missingComment()
    {
        return;
    }


    /**
     * no return tag.
     *
     */
    public function noReturn($one)
    {

    }//end noReturn()


    /**
     * Param not immediate.
     *
     * @return
     * @param   int   $threeSpaces
     * @param integer $superfluous
     * @param miss
     * @param
     */
    public function missingDescription($threeSpaces)
    {

    }//end missingDescroption()


    /**
     * Comments not capitalised.
     *
     * @param integer  $one    comment
     * @param array    $two    -comment
     * @param MyClas   $three  0comment
     *
     * @return void
     */
    public function oneSpaceAfterLongestVar($one, $two, MyClass $three)
    {

    }//end oneSpaceAfterLongestVar()


}//end class


/**
 * A simple function comment.
 *
 * @param string $str The string passed in by reference
 *
 * @return void
 * @return
 */
public function functionOutsideClass(&$str)
{
    return;
}//end functionOutsideClass()


function missingCommentOutsideClass()
{
    return;
}//end missingCommentOutsideClass()


?><?php
function tagBeforeComment()
{
    return;
}//end tagBeforeComment()


/**
 * no return tag.
 *
 * @see    FunctionCommentSniff.php
 */
public function noReturnOutsideClass()
{

}//end noReturnOutsideClass()


/**
 * Missing param comment.
 *
 * @param integer $one comment
 *
 * @see     wrong indent
 * @see
 * @return void
 * @extra  Invalid tag
 * @throws UnknownException unknown
 */
public function missingTwoParamComment($one, $two, $three)
{

}//end missingTwoParamComment()


/**
 * Missing return type.
 *
 * @throws ExceptionWithNoComment
 * @return
 */
public function missingReturnType()
{

}//end missingReturnType()


/**
 * Case-sensitive var type check with multiple return type.
 *
 * @param String  $a1 Comment here.
 * @param BoOL    $a2 Comment here.
 * @param INT     $a3 Comment here.
 * @param aRRay   $a4 Comment here.
 * @param real    $a5 Comment here.
 * @param double  $a6 Comment here.
 * @param Myclass $a7 Comment here.
 *
 * @return int|object|double|float|array(int=>MyClass)
 */
public function caseSensitive($a1, $a2, $a3, arRay $a4, $a5, $a6, myclas $a7)
{

}//end caseSensitive()


/**
 * More type hint check for custom type and array.
 *
 * @param array   $a1 Comment here.
 * @param array   $a2 Comment here.
 * @param MyClass $a3 Comment here.
 * @param MyClass $a4 Comment here.
 *
 * @return array(int => MyClass)
 */
public function typeHint(MyClass $a1, $a2, myclass $a3, $a4)
{
    return (3 => 'myclass obj');

}//end typeHint()


/**
 * Mixed variable type separated by a '|'.
 *
 * @param array|string $a1 Comment here.
 * @param mixed        $a2 Comment here.
 * @param string|array $a3 Comment here.
 * @param MyClass|int  $a4 Comment here.
 *
 * @return bool
 */
public function mixedType($a1, $a2, $a3, $a4)
{
    return true;

}//end mixedType()


/**
 * Array type.
 *
 * @param array(MyClass)         $a1 OK.
 * @param array()                $a2 Invalid type.
 * @param array(                 $a3 Typo.
 * @param array(int)             $a4 Use 'array(integer)' instead.
 * @param array(int => integer)  $a5 Use 'array(integer => integer)' instead.
 * @param array(integer => bool) $a6 Use 'array(integer => boolean)' instead.
 * @param aRRay                  $a7 Use 'array' instead.
 * @param string                 $a8 String with unknown type hint.
 *
 * @return int
 */
public function mixedArrayType($a1, $a2, array $a3, $a4, $a5, $a6, $a7, unknownTypeHint $a8)
{
    return 1;

}//end mixedArrayType()


/**
 */
function empty1()
{
}//end empty1()


/**
 *
 */
function empty2()
{
}//end empty2()


/**
 *
 *
 *
 */
function empty3()
{
}//end empty3


/**
 * @return boolean
 */
public function missingShortDescriptionInFunctionComment()
{
    return true;

}//end missingShortDescriptionInFunctionComment()


class Another_Class
{

    /**
     * Destructor should not include a return tag.
     *
     * @return void
     */
    function __destruct()
    {
        return;
    }

    /**
     * Constructor should not include a return tag.
     *
     * @return void
     */
    function __construct()
    {
        return;
    }

}//end class


/**
 * Comment param alignment test.
 *
 * @param string $varrr1 Comment1..
 * @param string  $vr2    Comment2.
 * @param string  $var3  Comment3..
 *
 * @return void
 */
public static function paramAlign($varrr1, $vr2, $var3)
{

}//end paramAlign()


/**
 * Comment.
 *
 * @param string $id    Comment.
 * @param array $design Comment.
 *
 * @return void
 */
public static function paint($id, array $design)
{

}//end paint()


/**
 * Adds specified class name to class attribute of this widget.
 *
 * @since  4.0.0
 * @return string
 */
public function myFunction()
{
    if ($condition === FALSE) {
        echo 'hi';
    }

}//end myFunction()


/**
 * Adds specified class name to class attribute of this widget.
 *
 * @return string
 */
public function myFunction()
{
    if ($condition === FALSE) {
        echo 'hi';
        return;
    }

    return 'blah';

}//end myFunction()


/**
 * Adds specified class name to class attribute of this widget.
 *
 * @return string
 */
public function myFunction()
{
    if ($condition === FALSE) {
        echo 'hi';
    }

    return 'blah';

}//end myFunction()

/**
 * Test function.
 *
 * @param string $arg1 An argument
 *
 * @access public
 * @return bool
 */

echo $blah;

function myFunction($arg1) {}

class MyClass() {
    /**
     * An abstract function.
     *
     * @return array(string)
     */
    abstract final protected function myFunction();
}

/**
 * Comment.
 *
 * @param mixed $test An argument.
 *
 * @return mixed
 */
function test($test)
{
   if ($test === TRUE) {
       return;
   }

   return $test;

}//end test()


/** Comment.
 *
 * @return mixed
 *
 */
function test()
{

}//end test()

/**
 * Comment.
 *
 * @param \other\ns\item $test An argument.
 *
 * @return mixed
 */
function test(\other\ns\item $test)
{
   return $test;

}//end test()

/**
 * Comment.
 *
 * @param item $test An argument.
 *
 * @return mixed
 */
function test(\other\ns\item $test)
{
   return $test;

}//end test()

/**
 * Comment.
 *
 * @param \first\ns\item $test An argument.
 *
 * @return mixed
 */
function test(\first\ns\item $test = \second\ns::CONSTANT)
{
   return $test;

}//end test()

/**
 * Comment.
 *
 * @param \first\item $test An argument.
 *
 * @return mixed
 */
function test(\first\ns\item $test = \second\ns::CONSTANT)
{
   return $test;

}//end test()

// Closures should be ignored.
preg_replace_callback(
    '~-([a-z])~',
    function ($match) {
        return strtoupper($match[1]);
    },
    'hello-world'
);

$callback = function ($bar) use ($foo)
            {
                $bar += $foo;
            };

/**
 * Comment should end with '*', not '**' before the slash.
 **/
function test123() {

}

/**
 * Cant use resource for type hint.
 *
 * @param resource $test An argument.
 *
 * @return mixed
 */
function test($test)
{
   return $test;

}//end test()

/**
 * Variable number of args.
 *
 * @param string $a1     Comment here.
 * @param string $a2     Comment here.
 * @param string $a2,... Comment here.
 *
 * @return boolean
 */
public function variableArgs($a1, $a2)
{
    return true;

}//end variableArgs()

/**
 * Contains closure.
 *
 * @return void
 */
public function containsClosure()
{
    function ($e) {
        return new Event($e);
    },

}//end containsClosure()

/**
 * 这是一条测试评论.
 *
 * @return void
 */
public function test()
{

}//end variableArgs()

/**
 * Uses callable.
 *
 * @param callable $cb Test parameter.
 *
 * @return void
 */
public function usesCallable(callable $cb) {
    $cb();
}

?>
<?php
/**
 * Unit test class for the DocCommentAlignment sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the DocCommentAlignment sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Commenting_DocCommentAlignmentUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                11 => 1,
                17 => 1,
                18 => 1,
                19 => 1,
                23 => 1,
                24 => 1,
                25 => 2,
                26 => 1,
                32 => 1,
                33 => 1,
                38 => 1,
                39 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the InlineComment sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the InlineComment sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Commenting_InlineCommentUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='InlineCommentUnitTest.inc')
    {
        switch ($testFile) {
        case 'InlineCommentUnitTest.inc':
            $errors = array(
                       17 => 1,
                       27 => 1,
                       28 => 1,
                       32 => 2,
                       36 => 1,
                       44 => 2,
                       54 => 1,
                       58 => 1,
                       61 => 1,
                       64 => 2,
                       67 => 1,
                       95 => 1,
                       96 => 1,
                       97 => 3,
                      );

            // The trait tests will only work in PHP version where traits exist and
            // will throw errors in earlier versions.
            if (version_compare(PHP_VERSION, '5.4.0') < 0) {
                $errors[106] = 1;
            }

            return $errors;
        case 'InlineCommentUnitTest.js':
            return array(
                    31  => 1,
                    36  => 2,
                    44  => 1,
                    48  => 1,
                    51  => 1,
                    54  => 2,
                    57  => 1,
                    102 => 1,
                    103 => 1,
                    104 => 3,
                   );
        default:
            return array();
        }//end switch

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the EmptyCatchComment sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the EmptyCatchComment sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Commenting_EmptyCatchCommentUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                13 => 1,
                33 => 1,
                49 => 1,
                50 => 1,
                51 => 1,
                52 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
// Some content here.
var code = 'hello';

// This comment contains # multiple
// hash signs (#).
code = 'hello';

/**
 * This is the first line of a function comment.
 * This is the second line.
 */
function testFunction()
{
    // Callback methods which are added by external objects.
    this.callbacks = {};

}//end testFunction()

/**
 * This is the first line of a class comment.
 * This is the second line.
 */
myClass.prototype = {

    /**
     * This is the first line of a method comment.
     * This is the second line.
     */
    load: function(url, callback)
    {
        // Some code here.

    }
};

// some code goes here!

/*
    A longer comment goes here.
    It spans multiple lines!!
    Or does it?
*/

// 0This is a simple multi-line
// comment!
code = 'hello';

//This is not valid.
code = 'hello';

//  Neither is this!
code = 'hello';

//
code = 'hello';

/** Neither is this! **/
code = 'hello';

/**
 * This is the first line of a function comment.
 * This is the second line.
 */
var myFunction = function() {
}

/**
 * This is the first line of a function comment.
 * This is the second line.
 */
myFunction = function() {
}

/**
 * This is the first line of a function comment.
 * This is the second line.
 */
myClass.myFunction = function() {
}

dfx.getIframeDocument = function(iframe)
{
    return doc;

};//end dfx.getIframeDocument()

mig.Gallery.prototype = {

    init: function(cb)
    {

    },//end init()

    imageClicked: function(id)
    {

    }//end imageClicked()

};

// Here is some inline example code:
//     -> One
//         -> One.One
//     -> Two

/*
    Here is some inline example code:
        -> One
            -> One.One
        -> Two
*/<?php
class VariableCommentUnitTest
{

    /**
     * short description of the member variable.
     *
     * long description of member variable. Can span over multiple
     * lines and can have multiple paragraphs.
     *
     * @var array
     * @see otherFunctions()
     * @see anotherFunctions()
     */
     public $variableName = array();


     // Not "/**" style comment.
     //
     // @var   string
     private  $_incorrectCommentStyle = '';


     protected $noComment = '';


    /**
     *
     * Extra newline before short comment.
     *
     * @var string
     */
     public $extraNewlineBeforeShort = '';


    /**
     * Extra newline between short description.
     *
     *
     *
     * - Long description,
     *
     * @var string
     */
     private $_extraNewlineBetween = '';


    /**
     * Extra newline before tags.
     *
     * Long description,
     * with two var tags.
     *
     *
     * @var string
     * @var array
     */
     protected $extraNewlineBeforeTags = '';


    /**
     * No newline before tags, var tag missing.
     * @see otherFunctions()
     */
     protected $noNewlineBeforeTags = '';


    /**
     * Short comment that spans multiple
     * lines and does not end with a full stop
     * also var type is missing
     *
     * @var
     */
     public $singleLineFullStopShortComment = '';


    /**
     * Incorrect tag indentation.
     *
     * @var     string
     * @see        otherFunctions()
     * @see anotherFunctions()
     * @see
     */
     public $singleLineFullStopShortComment = '';


    /**
     * Unknown summary tag
     *
     * @var     string
     * @summary unknown tag
     */
     public $missingSinceTag = '';


    /**
     * T_VARIABLE check, without scope.
     *
     * @var string
     */
     $variableCheck = '';


    /**
     * T_VARIABLE check, var in string and in function.
     *
     * @param integer $var1 First variable.
     * @param integer $var2 Second variable.
     *
     * @return integer
     */
    protected function checkVariable($var1, $var2)
    {
        $var4 = 'A normal variable';
        $var5 = PHP_CodeSniffer_Tokens::$operators;
        echo "Printing $var1 $var2 and unknown $var3 in a double quoted  string\n";
        foreach (self::$_array as $index => $content) {
            echo $content;
        }

        return $var1;

    }//end checkVariable()


    /**
     *
     *
     */
     $emptyVarDoc = '';

     /**
     * Var type checking (int v.s. integer).
     *
     * @var int
     */
     private $_varSimpleTypeCheck;


     /**
     * Var type checking (array(int => string) v.s. array(int => string)).
     *
     * @var array(int => string)
     */
     private $_varArrayTypeCheck;


     /**
     * Var type checking (STRING v.s. string).
     *
     * @var STRING
     */
     private $_varCaseTypeCheck;


    /**
     * @var integer
     */
     private $_varWithNoShortComment;

     protected $noComment2 = '';


}//end class


/**
 * VariableCommentUnitTest2.
 *
 * Long description goes here.
 *
 */
class VariableCommentUnitTest2
{

   public $hello;

    /** Comment starts here.
     *
     * @var string
     *
     */
     private $_varCaseTypeCheck;

     /**
      * 这是一条测试评论.
      *
      * @var string
      */
     public $foo;

}//end class

?>
<?php
try {
    // Try something.
    $variable = 'string';
} catch (Exception $e) {
    // Comment.
    echo 'something broke';
}

try {
    // Try something.
    $variable = 'string';
} catch (Exception $e) {
}

try {
    // Try something.
    $variable = 'string';
} catch (Exception $e) {
    // Dont want to do anything.
}

try {
    $variable = 'string';
} catch (MyException $e) {
    echo 'something broke';
} catch (Exception $e) {
    echo 'something broke';
}

try {
    $variable = 'string';
} catch (MyException $e) {

} catch (Exception $e) {
    echo 'something broke';
}

try {
    $variable = 'string';
} catch (MyException $e) {
    // Dont do anything.
} catch (Exception $e) {
    // Do nothing.
}

try {
    $variable = 'string';
} catch (MyException $e) {
} catch (YourException $e) {
} catch (OurException $e) {
} catch (Exception $e) {
}

?><?php
/**
 * Unit test class for FunctionCommentSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for FunctionCommentSniff.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Commenting_FunctionCommentUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                6   => 1,
                8   => 1,
                10  => 4,
                12  => 3,
                13  => 3,
                14  => 1,
                15  => 1,
                28  => 1,
                35  => 3,
                38  => 1,
                40  => 1,
                41  => 1,
                43  => 1,
                52  => 1,
                53  => 1,
                103 => 1,
                109 => 1,
                110 => 1,
                112 => 2,
                122 => 1,
                123 => 4,
                124 => 3,
                125 => 4,
                126 => 6,
                137 => 3,
                138 => 2,
                139 => 3,
                143 => 2,
                155 => 2,
                158 => 1,
                166 => 1,
                173 => 1,
                180 => 1,
                183 => 1,
                193 => 4,
                195 => 1,
                196 => 1,
                199 => 2,
                210 => 1,
                211 => 1,
                222 => 1,
                223 => 1,
                224 => 1,
                225 => 1,
                226 => 1,
                227 => 1,
                230 => 2,
                232 => 1,
                246 => 1,
                248 => 4,
                261 => 1,
                263 => 1,
                276 => 1,
                277 => 1,
                278 => 1,
                279 => 1,
                280 => 1,
                281 => 1,
                284 => 1,
                286 => 2,
                293 => 1,
                300 => 1,
                308 => 1,
                318 => 1,
                334 => 1,
                344 => 1,
                358 => 1,
                359 => 1,
                373 => 2,
                387 => 1,
                407 => 1,
                441 => 1,
                470 => 1,
                474 => 1,
                500 => 1,
                526 => 1,
                548 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Some info about the class here
 *
 */
class MyClass
{
    /**
     * Some info about the function here.
     *
     *@return void
     */
    function myFunction() {}
}

/**
  *  Some info about the class here
  *
  */
class MyClass
{
    /**
      *Some info about the function here.
      *
      *  @return void
      */
    function myFunction() {}
}

/**
 * Some info about the class here
  *
*/
class MyClass
{
    /**
     * Some info about the function here.
      *
    * @return void
     */
    function myFunction() {}
}

function myFunction()
{
    echo 'hi';
    /**
        Comment here.
        */
}

?><?php
/**
 * Unit test class for FunctionCommentThrowTagSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for FunctionCommentThrowTagSniff.
 *
 * Verifies that :
 * <ul>
 *  <li>A @throws tag exists for a function that throws exceptions.</li>
 *  <li>The number of @throws tags and the number of throw tokens matches.</li>
 *  <li>The exception type in comment matches the token.</li>
 * </ul>
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Commenting_FunctionCommentThrowTagUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                9   => 1,
                21  => 1,
                35  => 1,
                46  => 1,
                59  => 1,
                60  => 1,
                106 => 1,
                123 => 1,
                214 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php

function __construct()
{
}//end __construct()

function myFunction()
{
}//end myFunction()

function ourFunction()
{
}//end ourFunction

function yourFunction()
{
}//end myFunction()

class TestClass
{
    function __construct()
    {
    }//end __construct()

    function myFunction()
    {
    }//end myFunction()

    function yourFunction()
    {
    }//end myFunction()

}//end class

abstract class TestClass
{
    abstract function myFunction();

    function ourFunction()
    {
    }//end myFunction()

    function yourFunction()
    {
    }//end yourFunction()

}//end class

interface TestClass
{
    function myFunction();
    function ourFunction();
    function yourFunction();

}//end interface

class TestClass
{
}

abstract class TestClass
{
}

interface TestClass
{
}

class MyClass
{
    public function myFunction();
}//end class

// Closures don't need end comments.
echo preg_replace_callback('~-([a-z])~', function ($match) { return strtoupper($match[1]); }, 'hello-world');

?><?php
// Some code goes here.
$code = 'hello';

// This comment contains # multiple
// hash signs (#).
$code = 'hello';

/*
 * Here is a small function comment.
 */
function test()
{
    // Some code goes here.
    $code = 'hello';

    # This comment is banned.
    $code = 'hello';

}//end test()

/*
    A longer comment goes here.
    It spans multiple lines.
*/

# This is a long comment
# that is banned.



// some code goes here!

// This comment contains # multiple
// hash signs (#) but no
// full stop
$code = 'hello';

/*
 * Here is a small function comment
 */
function test()
{
    // Some code goes here

}//end test()

/*
    A longer comment goes here.
    It spans multiple lines!!
    Or does it?
*/

// 0This is a simple multi-line
// comment!
$code = 'hello';

//This is not valid.
$code = 'hello';

//  Neither is this!
$code = 'hello';

//
$code = 'hello';

/** Neither is this! **/
$code = 'hello';

class MyClass
{
    /**
     * Represents a left orientation for the widget.
     *
     * @var   integer
     * @since 4.0.0
     */
    const LEFT = 1;
}

/**
 * Comment should be ignored.
 *
 */
final class MyClass
{
    /**
     * Comment should be ignored.
     *
     */
    final public function test() {}
}

// 这是一条测试评论
//     -> One
//         -> One.One
//     -> Two

/*
    Here is some inline example code:
        -> One
            -> One.One
        -> Two
*/

/**
 * Comment should be ignored in PHP 5.4.
 *
 */
trait MyTrait {

}
?>




/**
*
* 0Multi-line short description without full stop
*
*
* asdasd
* long description for file (if any)
* asdasdadada
*
* PHP versio
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt.  If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
* @package    SquizCMS
* @package    ADDITIONAL PACKAGE TAG
* @subpackage not_camelcased
* @author     Antônio Carlos Venâncio Júnior <foreign@character.net>
* @author
* @copyright  1997~1994 The PHP Group
* @license    http://www.php.net/license/3_0.txt
* @summary    An unknown summary tag
*
*/


/**
* This bit here is not qualified as file comment
*
* as it is not the first comment in the file
*
*/
<?php

function long_function()
{
    if ($longFunction) {
        // This is a long
        // IF statement
        // that does
        // not have
        // and ELSE
        // block on it
        $variable = 'hello';

        if ($variable === 'hello') {
            // This is a short
            // IF statement
        }

        if ($variable === 'hello') {
            // This is a short
            // IF statement
        } else {
            // This is a short ELSE
            // statement
        }
    }//end if

    if ($longFunction) {
        // This is a long
        // IF statement
        // that does
        // not have
        // and ELSE
        // block on it
        $variable = 'hello';

        if ($variable === 'hello') {
            // This is a short
            // IF statement
        }

        if ($variable === 'hello') {
            // This is a short
            // IF statement
        } else {
            // This is a short ELSE
            // statement
        }
    }

    if ($longFunction) {
        // This is a long
        // IF statement
        // that does
        // not have
        // and ELSE
        // block on it
        $variable = 'hello';

        if ($variable === 'hello') {
            // This is a short
            // IF statement
        }

        if ($variable === 'hello') {
            // This is a short
            // IF statement
        } else {
            // This is a short ELSE
            // statement
        }
    } else {
        // Short ELSE
    }//end if

    if ($longFunction) {
        // This is a long
        // IF statement
        // that does
        // not have
        // and ELSE
        // block on it
        $variable = 'hello';

        if ($variable === 'hello') {
            // This is a short
            // IF statement
        }

        if ($variable === 'hello') {
            // This is a short
            // IF statement
        } else {
            // This is a short ELSE
            // statement
        }
    } else {
        // Short ELSE
    }
}

foreach ($var as $val) {
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    // Line 6
    // Line 7
    // Line 8
    // Line 9
    // Line 10
    // Line 11
    // Line 12
    // Line 13
    // Line 14
    // Line 15
    // Line 16
    // Line 17
    // Line 18
    // Line 19
    // Line 20
}//end foreach

foreach ($var as $val) {
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    // Line 6
    // Line 7
    // Line 8
    // Line 9
    foreach ($blah as $val) {
        // Short foreach.
    }
    // Line 13
    // Line 14
    // Line 15
    // Line 16
    // Line 17
    // Line 18
    // Line 19
    // Line 20
}

for ($var =1; $var < 20; $var++) {
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    // Line 6
    // Line 7
    // Line 8
    // Line 9
    // Line 10
    // Line 11
    // Line 12
    // Line 13
    // Line 14
    // Line 15
    // Line 16
    // Line 17
    // Line 18
    // Line 19
    // Line 20
}//end for

for ($var =1; $var < 20; $var++) {
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    // Line 6
    // Line 7
    // Line 8
    // Line 9
    for ($val =1; $val < 20; $val++) {
        // Short for.
    }
    // Line 13
    // Line 14
    // Line 15
    // Line 16
    // Line 17
    // Line 18
    // Line 19
    // Line 20
}

while ($var < 20) {
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    // Line 6
    // Line 7
    // Line 8
    // Line 9
    // Line 10
    // Line 11
    // Line 12
    // Line 13
    // Line 14
    // Line 15
    // Line 16
    // Line 17
    // Line 18
    // Line 19
    // Line 20
}//end while looping

while ($var < 20) {
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    // Line 6
    // Line 7
    // Line 8
    // Line 9
    while ($something) {
        // Short while.
    }
    // Line 13
    // Line 14
    // Line 15
    // Line 16
    // Line 17
    // Line 18
    // Line 19
    // Line 20
}

if ($longFunction) {
    // This is a long
    // IF statement
    // that does
    // not have
    // and ELSE
    // block on it
    $variable = 'hello';

    if ($variable === 'hello') {
        // This is a short
        // IF statement
    }

    if ($variable === 'hello') {
        // This is a short
        // IF statement
    } else {
        // This is a short ELSE
        // statement
    }
} //end if

if ($longFunction) {
    // This is a long
    // IF statement
    // that does
    // not have
    // and ELSE
    // block on it
    $variable = 'hello';

    if ($variable === 'hello') {
        // This is a short
        // IF statement
    }

    if ($variable === 'hello') {
        // This is a short
        // IF statement
    } else {
        // This is a short ELSE
        // statement
    }
} else {
    // Short ELSE
} //end if

foreach ($var as $val) {
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    // Line 6
    // Line 7
    // Line 8
    // Line 9
    // Line 10
    // Line 11
    // Line 12
    // Line 13
    // Line 14
    // Line 15
    // Line 16
    // Line 17
    // Line 18
    // Line 19
    // Line 20
} //end foreach

for ($var =1; $var < 20; $var++) {
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    // Line 6
    // Line 7
    // Line 8
    // Line 9
    // Line 10
    // Line 11
    // Line 12
    // Line 13
    // Line 14
    // Line 15
    // Line 16
    // Line 17
    // Line 18
    // Line 19
    // Line 20
} //end for

while ($var < 20) {
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    // Line 6
    // Line 7
    // Line 8
    // Line 9
    // Line 10
    // Line 11
    // Line 12
    // Line 13
    // Line 14
    // Line 15
    // Line 16
    // Line 17
    // Line 18
    // Line 19
    // Line 20
} //end while

while ($var < 20) {
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    // Line 6
    // Line 7
    // Line 8
    // Line 9
    // Line 10
    // Line 11
    // Line 12
    // Line 13
    // Line 14
    // Line 15
    // Line 16
    // Line 17
    // Line 18
    // Line 19
    // Line 20
}//end for

if (true) {
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    // Line 6
    // Line 7
    // Line 8
    // Line 9
    // Line 10
    // Line 11
    // Line 12
    // Line 13
    // Line 14
    // Line 15
    // Line 16
    // Line 17
    // Line 18
    // Line 19
    // Line 20
} else if ($condition) {
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    // Line 6
    // Line 7
    // Line 8
    // Line 9
    // Line 10
    // Line 11
    // Line 12
    // Line 13
    // Line 14
    // Line 15
    // Line 16
    // Line 17
    // Line 18
    // Line 19
    // Line 20
} elseif ($cond) {
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    // Line 6
    // Line 7
    // Line 8
    // Line 9
    // Line 10
    // Line 11
    // Line 12
    // Line 13
    // Line 14
    // Line 15
    // Line 16
    // Line 17
    // Line 18
    // Line 19
    // Line 20
} else {
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    // Line 6
    // Line 7
    // Line 8
    // Line 9
    // Line 10
    // Line 11
    // Line 12
    // Line 13
    // Line 14
    // Line 15
    // Line 16
    // Line 17
    // Line 18
    // Line 19
    // Line 20
}//end if

if ($something) {
    // Line 1
    // Line 2
} else if ($somethingElse) {
    // Line 1
    // Line 2
} else {
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    // Line 6
    // Line 7
    // Line 8
    // Line 9
    // Line 10
    // Line 11
    // Line 12
    // Line 13
    // Line 14
    // Line 15
    // Line 16
    // Line 17
    // Line 18
    // Line 19
    // Line 20
}

switch ($something) {
    case '1':
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    break;
    case '2':
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    break;
    case '3':
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    break;
    case '4':
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    break;
    case '5':
    // Line 1
    // Line 2
    // Line 3
    // Line 4
    // Line 5
    break;
}

// Wrong comment
if ($condition) {
    echo "true";
}//end foreach

if ($condition) {
    echo "true";
} //end if

try {
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
} catch (Exception $e) {
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
}

try {
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
} catch (Exception $e) {
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
}

try {
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
} catch (Exception $e) {
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
}//end catch

try {
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
} catch (DALException $e) {
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
    // some code here.
} catch (ChannelException $e) {
    // some code here.
} catch (Exception $e) {
    // some code here.
}

switch ($foo) {
    case 'one' : {
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        break;
    }
    case 'one' :
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
        // some code here.
    break;
}//end switch
?><?php
/**
 * Unit test class for the BlockComment sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the BlockComment sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Commenting_BlockCommentUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        $errors = array(
                   8   => 1,
                   19  => 1,
                   20  => 1,
                   24  => 1,
                   30  => 1,
                   31  => 1,
                   34  => 1,
                   40  => 1,
                   45  => 1,
                   49  => 1,
                   51  => 1,
                   53  => 1,
                   57  => 1,
                   60  => 1,
                   61  => 1,
                   63  => 1,
                   65  => 1,
                   68  => 1,
                   70  => 1,
                   75  => 1,
                   84  => 1,
                   85  => 2,
                   86  => 1,
                   87  => 1,
                   89  => 1,
                   92  => 1,
                   111 => 1,
                   159 => 1,
                  );

        // The trait tests will only work in PHP version where traits exist and
        // will throw errors in earlier versions.
        if (version_compare(PHP_VERSION, '5.4.0') < 0) {
            $errors[170] = 2;
            $errors[171] = 1;
            $errors[172] = 2;
        }

        return $errors;

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
trait MyTrait {}
?>
<?php
function myFunction() {}
?>
<?php
/**
 * Unit test class for the FileExtension sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the FileExtension sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Files_FileExtensionUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='')
    {
        switch ($testFile) {
        case 'FileExtensionUnitTest.1.inc':
            return array(
                    1 => 1,
                   );
        case 'FileExtensionUnitTest.4.inc':
            if (version_compare(PHP_VERSION, '5.4.0', '<') === true) {
                // Traits are available from PHP 5.4.0.
                return array(
                        1 => 1,
                       );
            }
        default:
            return array();
        }

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
interface MyInterface {}
?>
<?php
class MyClass {}
?>
<?php
/**
 * Unit test class for the ConcatenationSpacing sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ConcatenationSpacing sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Strings_ConcatenationSpacingUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                4 => 5,
                6 => 1,
                7 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
$string = 'hello';
echo $string;
echo 'hello';
echo('hello');
echo($hello);
echo ('hello');
echo ($hello);
?><?php
$string = "Hello\tThere";
$string = "Hello There\r\n";
$string = "Hello There";
$string = "Hello $there";
$string = 'Hello'."$there '".'hi';
$string = "My name is 'Greg'";
$string = "Hello"." There"."\n";
$string = "Hello There\f";
$string = "Hello\vThere";
$string = "\x0";
$string = 'Hello '.$there.' Greg';
$string = "<div class='$class'>";
$string = "Value: $var[test]";
$string = "\0";

$x = "bar = '$z',
baz = '" . $a . "'...$x";
?><?php
/**
 * Unit test class for the DoubleQuoteUsage sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the DoubleQuoteUsage sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Strings_DoubleQuoteUsageUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                4  => 1,
                5  => 1,
                6  => 1,
                8  => 2,
                13 => 1,
                14 => 1,
                17 => 1,
                18 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php

$string = 'Hello'.$there.'. How are'.$you.$going."today $okay";
$string = 'Hello' . $there . '. How are' . $you . $going . "today $okay";
$string = 'Hello'.$there;
$string = 'Hello'. $there;
$string = 'Hello' .$there;
?><?php
/**
 * Unit test class for the EchoedStrings sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the EchoedStrings sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Strings_EchoedStringsUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                5 => 1,
                6 => 1,
                7 => 1,
                8 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the ForbiddenFunctions sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ForbiddenFunctions sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_PHP_ForbiddenFunctionsUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                2 => 1,
                3 => 1,
                4 => 1,
                5 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
function outer()
{
    if (!function_exists('inner')) {
        function inner() {
        }
    }
}

// Closures are allowed.
function myFunc($foo)
{
    $callback = function ($bar) use ($foo)
                {
                    $bar += $foo;
                };
}
?>
<?php
eval('$var = 4;');
$string = '$var = 4;';
eval($string);
?>
<?php
ob_start();
    echo 'hello';
    $contents = ob_get_contents();
ob_end_clean();

ob_start();
    echo 'hello';
ob_end_flush();
?>
<?php
/**
 * Unit test class for the DisallowMultipleAssignments sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the DisallowMultipleAssignments sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_PHP_DisallowMultipleAssignmentsUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                4  => 1,
                5  => 2,
                7  => 1,
                9  => 1,
                12 => 1,
                14 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
function getVar($varname='var', $var='var')
{
    $var = $var2 = getVar();
    $var = $var2 = $var3 = '';

    if ($varname === 'var' || $var2 === 'varname' || $var = true) {
        $var[($var + 1)] = $var2;
        $var[($var = 1)] = $var2;
    }

    for ($i = $var; (null !== ($key = key($i))); next($i)) {
        while ($i = true) {
            echo $i = getVar();
        }
    }

    while ($row = $query->fetch(PDO::FETCH_NUM)) {
        $result[$row[0]] = array()
        $result[$row[0]][] = $current;

        self::$_inTransaction = TRUE;
        $$varName = $varValue;
    }

}//end getVar()

class myClass
{
    private static $_dbh = NULL;
    public $dbh = NULL;
    protected $dbh = NULL;
}

$var = $var2;
list ($a, $b) = explode(',', $c);
$var1 ? $var2 = 0 : $var2 = 1;

$obj->$classVar = $prefix.'-'.$type;

$closureWithDefaultParamter = function(array $testArray=array()) {};
?>
<?php
/**
 * Unit test class for the Heredoc sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the Heredoc sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_PHP_HeredocUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                2 => 1,
                8 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the DisallowBooleanStatement sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the DisallowBooleanStatement sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_PHP_DisallowBooleanStatementUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                3  => 1,
                8  => 1,
                13 => 1,
                15 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the NonExecutableCode sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the NonExecutableCode sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_PHP_NonExecutableCodeUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array();

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                5   => 1,
                11  => 1,
                17  => 1,
                18  => 1,
                19  => 2,
                28  => 1,
                32  => 1,
                33  => 2,
                34  => 2,
                42  => 1,
                45  => 1,
                54  => 1,
                58  => 1,
                73  => 1,
                83  => 1,
                95  => 1,
                105 => 1,
                123 => 1,
                146 => 1,
                149 => 1,
                152 => 1,
                165 => 1,
                179 => 1,
                221 => 1,
                222 => 1,
                223 => 1,
                224 => 2,
                228 => 1,
               );

    }//end getWarningList()


}//end class

?>
<?php
$str = <<<EOD
Example of string
spanning multiple lines
using heredoc syntax.
EOD;

echo <<<'EOT'
My name is "$name". I am printing some $foo->foo.
Now, I am printing some {$foo->bar[1]}.
This should not print a capital 'A': \x41
EOT;
?>
<?php
// This is a normal block comment that might
// talk about functions like echo and print and if/else but
// is not commented out code.

// if (empty($this)) {echo 'This is will not work';}

/*
function myFunction()
{

}//end myFunction()
*/

//eval('$var = 4;');
//$string = '$var = 4;';
//eval($string);

#eval('$var = 4;');
#$string = '$var = 4;';
#eval($string);

if ($blah) {
    // This is a multi-line comment that goes over two indented
    // lines.

    // If it's null, then there must be no parameters for this
    // method.
}

// short.

// Continue, as we're done with this token.

/**
 * The listeners array.
 *
 * @var array(PHP_CodeSniffer_Sniff)
 */

//

/*
*/

function myFunction()
{
}//end myFunction()

// ----------------------------
// | A comment block           |
// ----------------------------

// =============================
// | A comment block           |
// =============================

// *****************************
// | A comment block           |
// *****************************

/**
 * List of panels.
 *
 * XML structure:
 * <panels>
 *     <panel_one_id>
 *         <title>Title</title>
 *         <panelContent>Contents</panelContent>
 *         <panels>
 *             <child_panel_id>...</child_panel_id>
 *         </panels>
 *     </panel_one_id>
 * </panels>
 *
 * @return void
 */

/*
    [^\'"]
*/
?>
<?php
/**
 * Unit test class for the Eval sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the Eval sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_PHP_EvalUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array();

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                2 => 1,
                4 => 1,
               );

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the GlobalKeyword sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the GlobalKeyword sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_PHP_GlobalKeywordUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                8 => 1,
                9 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
$newfunc = create_function('$a,$b', 'return "ln($a) + ln($b) = " . log($a * $b);');
print 'hi';
print($var);
if (is_null($blah) === TRUE) {
}

class Test
{
    const DELETE = 'delete';
}
?>
<?php
/**
 * Unit test class for the DisallowObEndFlush sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the DisallowInlineIf sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_PHP_DisallowInlineIfUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='DisallowInlineIfUnitTest.inc')
    {
        switch ($testFile) {
        case 'DisallowInlineIfUnitTest.inc':
            return array(
                    8 => 1,
                   );
            break;
        case 'DisallowInlineIfUnitTest.js':
            return array(
                    1 => 1,
                   );
            break;
        default:
            return array();
            break;
        }//end switch

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the EmbeddedPhp sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the EmbeddedPhp sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_PHP_EmbeddedPhpUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                7  => 1,
                12 => 1,
                18 => 1,
                19 => 2,
                20 => 1,
                21 => 1,
                22 => 3,
                24 => 1,
                26 => 1,
                29 => 1,
                30 => 1,
                31 => 1,
                34 => 1,
                36 => 1,
                40 => 1,
                41 => 2,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the InnerFunctions sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the InnerFunctions sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_PHP_InnerFunctionsUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                5 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
for (var i = 0; i < permissions.length; i++) {
    // Code here.
}

var permLen = permissions.length;
for (var length = 0; i < permLen; i++) {
    // Code here.
}

var myArray = [1, 2, 3, 4];
for (var i = myArray.length; i >= 0; i--) {
    var x = i;
}
<?php
if (Function_Exists('myFunction') === TRUE) {
    $retval = MyFunction(true);
    $keys = Array_Keys($array);
}

function getType() {}

$obj = new Date();

$count = $object->Count();
$count = $object::Count();
$count = $object->count();
$count = $object::count();
class MyClass {
    public function Count() {}
}

function &Sort() {

}
?>
<?php
/**
 * Unit test class for the DisallowObEndFlush sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the DisallowObEndFlush sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_PHP_DisallowObEndFlushUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                9 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
if ($var1) {
    $var2 = 0;
} else {
    $var2 = 1;
}

$var1 ? $var2 = 0 : $var2 = 1;
?>
<?php
/**
 * Unit test class for the LowercasePHPFunctions sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the LowercasePHPFunctions sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_PHP_LowercasePHPFunctionsUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                2 => 1,
                4 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the DisallowSizeFunctionsInLoops sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the DisallowSizeFunctionsInLoops sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_PHP_DisallowSizeFunctionsInLoopsUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='DisallowSizeFunctionsInLoopsUnitTest.inc')
    {
        switch ($testFile) {
        case 'DisallowSizeFunctionsInLoopsUnitTest.inc':
            return array(
                    2  => 1,
                    7  => 1,
                    11 => 1,
                    13 => 1,
                    18 => 1,
                    23 => 1,
                    27 => 1,
                    29 => 1,
                    35 => 1,
                    40 => 1,
                    44 => 1,
                    46 => 1,
                   );
            break;
        case 'DisallowSizeFunctionsInLoopsUnitTest.js':
            return array(
                    1 => 1,
                   );
            break;
        default:
            return array();
            break;
        }//end switch

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
x = (x?a:x);
id = id.replace(/row\/:/gi, '');
<?php
    // Not embedded. Do not check here.
    echo 'hello';
?>
<html>
<head>
<title><?php echo $title ?></title>
<script><?php echo $script; ?></script>
</head>
<body>
    <?php
        echo $body;
    ?>
    hello
    <?php
    echo $moreBody;
    ?>
    <?php  echo 'hi'; ?>
    <?php  echo 'hi';   ?>
    <?php echo 'hi;' ?>
    <?php echo 'hi'; echo 'hi;'; ?>
    <?php  echo 'hi'; echo 'hi;';   ?>

    <?php
    ?>
    <?php ?>

    <?php

        echo $moreBody;

    ?>
    <?php

    echo $moreBody;

    ?>

    <?php
    echo $moreBody; ?>
    <?php echo $moreBody;
    ?>
</body>
</html>
<?php
// Not embedded. Do not check here.
echo 'goodbye';
?>
<?php
for ($i = 0; $i < count($array); $i++) {
}

$num = count($array);

while ($i < count($array)) {
}

do {
} while ($i < count($array));

for ($i = 0; $i < count($this->children); $i++) {
}



for ($i = 0; $i < sizeof($array); $i++) {
}

$num = sizeof($array);

while ($i < sizeof($array)) {
}

do {
} while ($i < sizeof($array));

for ($i = 0; $i < sizeof($this->children); $i++) {
}




for ($i = 0; $i < strlen($string); $i++) {
}

$num = strlen($string);

while ($i < strlen($string)) {
}

do {
} while ($i < strlen($string));

for ($i = 0; $i < strlen($this->string); $i++) {
}

for ($i = sizeof($array); $i > 0; $i--) {
}

do {
    echo $a->count;
    $a->count--;
} while($a->count);

for ($i = 0; $i < $a->count; $i++) {}
?>
/* CSS Document */

body {
font-family: Arial, Helvetica, sans-serif;
margin  :  40px 0 0 0;
padding :  0;
/*background: #8FB7DB url(login_glow_bg.jpg) no-repeat 30% 0;*/
background: #8FB7DB url(diag_lines_bg.gif) top left;
}

#login-container {
    margin-left: -225px;
    margin-top: -161px;
    position:absolute;
    top  :50%;
    /*left :50%;*/
    width:450px;
}

#cacheConfig-dayLabel, #cacheConfig-hourLabel, #cacheConfig-minuteLabel {
    float: left;
    padding-right: 8px;
}
<?php
/**
 * Unit test class for the CommentedOutCode sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the CommentedOutCode sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_PHP_CommentedOutCodeUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array();

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList($testFile='CommentedOutCodeUnitTest.inc')
    {
        switch ($testFile) {
        case 'CommentedOutCodeUnitTest.inc':
            return array(
                    6  => 1,
                    8  => 1,
                    15 => 1,
                    19 => 1,
                   );
            break;
        case 'CommentedOutCodeUnitTest.css':
            return array(
                    7  => 1,
                    16 => 1,
                   );
            break;
        default:
            return array();
            break;
        }//end switch

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the DisallowComparisonAssignment sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the DisallowComparisonAssignment sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_PHP_DisallowComparisonAssignmentUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                3  => 1,
                5  => 1,
                6  => 1,
                7  => 1,
                8  => 1,
                10 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
$var = TRUE;
$var = ($foo === $bar);
$var = ($foo * $bar);
$var = !$foo;
$var = ($foo || $bar);
$var = ($foo === TRUE);
$var = ($foo === TRUE
        || $bar === FALSE);
$var = (!$foo);

$var = is_array($foo);
$var = myFunction($one, $two);
$var = myFunction(
        'one',
        'two'
       );

for ($i = ($stackPtr + 1); $i < $endStatement; $i++) {
}

// These conditions are allowed by this sniff.
$var = myFunction(!$var);

$depthAdv = array(
             $this,
             !$directLinks,
             FALSE,
            );

$var = myFunction(
    $var,
    array(
     $this,
     !$directLinks,
     FALSE,
    );
);

for ($node = $fieldsTag->nextSibling; $node; $node = $node->nextSibling) {
    if ($node->nodeType !== XML_ELEMENT_NODE) {
        continue;
    }

    for ($node = $fields->nextSibling; $node; $node = $node->nextSibling) {
        if ($node->nodeType !== XML_ELEMENT_NODE) {
            continue;
        }
    }
}
?>
<?php
error_log('test');
print_r($array);
?>
<?php
$var = 'hello';
$var2 = 'hello';
$GLOBALS['var'] = 'hello';

function func1()
{
    global $var;
    global $var, $var2;
    echo $var;
    echo $GLOBALS['var'];
}
?>
<?php

trySomething() || trySomethingElse();
if (trySomething() === FALSE) {
    trySomethingElse();
}

$success || fail();
if ($success === FALSE) {
    fail();
}

$foo = ($bar || $foo);

doSomething() || die();

if ($something || somethingElse()) {
    while ($foo && $bar) {
    }

    do {
        // Code here.
    }
    while ($foo && $bar);
}

?><?php
switch ($var) {
    case '1':
        return;
        echo 'hi';

    case '2':
    case '3':
        if ($something === true) {
            break;
            echo 'hi';
        }
    break;
    default:
        return;

        if ($something === true) {
            break;
            echo 'hi';
        }

}

function myFunction($var)
{
    if ($something === TRUE) {
        return;
        echo 'hi';
    }

    return;
    return FALSE;
    if ($something === TRUE) {
        return TRUE;
    }

}//end myFunction()

foreach ($vars as $var) {
    if ($something === TRUE) {
        continue;
        break;
    } else {
        continue;
        echo 'hi';
    }

    echo $var."\n";
}

switch ($lowerVarType) {
    case 'bool':
        return 'boolean';
        echo 'hi';
    case 'double':
    case 'real':
        return 'float';
        echo 'hi';
}

while ($line=fgets($fp,2*1024*1024))
{
    if (!preg_match("/^<([a-z0-9_]+)/",$line,$matches))
    continue;
    print $line;
}

switch ($var) {
    case 1:
        echo '1';
    break;

        echo 'non-executable';
    default:
        echo '2';
    break;
}

switch (0) {
    case 1:
        return '1';

        echo 'non-executable';
    default:
    break;
}

function myFunction()
{
    if ($something === TRUE) {
        return;
    }

    echo 'foo';
    return;

}//end myFunction()

function myFunction()
{
    return uksort(
        $array,
        function() {
            return mt_rand(-1, 1);
            echo 'done';
        }
    );

}//end myFunction()

public static function thisCausesAnError() {
return new foo(function() {return $foo;}
);
}

function myFunction()
{
    if ($something === TRUE) {
        throw new Exception('exception');
    }

    throw new Exception('exception');
    echo 'non-executable';
}//end myFunction()

switch ($var) {
    case 1: {
        return '1';
    }

    case 2: {
        return '2';
    }
}

defined('FOO') or die('error');
interface myInterface {
    function myFunc();
}
echo 'hello';

function foo($color) {
    switch ($color) {
        case 'red':
            return 'yuck';
            break;
        case 'blue':
            return 'yuck';
            break;
        case 'orange':
            return 'yay';
            break;
        default:
            return 'boring';
    }
}

function returnOverMultipleLines($color) {
    switch ($color) {
        case 'red':
            return someFunction(
                'multiple',
                'arguments'
            );
            echo $foo;
        default:
            return array(
                'multiline',
                'array'
            );
    }
}

function test() {
    return array(
                'multiline',
                'array'
            );
    echo $foo;
}

function test(){
    switch($a) {
        case 1:
            if (empty($b))
                return 0;
            break;
        default:
            return 2;
    }

    if (empty($a))
        echo '1';
    elseif ($empty($b))
        return 0;
    else
        return 1;

    echo "oi";
    return 1;
}

switch ($foo) {
    case 'foo':
        if ($foo)
            return $foo;
        return $bar;
    default:
        return $bar;
}

function foo()
{
    return $bar->{$action . 'JsonAction'}();
}

exit();


// Errors are thrown from here down from the exit() above.
foreach ($vars as $var) {
    if ($something === TRUE) {
        break;
        break;
    }
}

exit();

function test() {
    echo 'no error';
}

class myClass {
    function myFunc() {
        echo 'no error';
    }
}

function bar() {
    return function() {
        echo "1";
    };
}

?>
<?php
/**
 * Unit test class for the DiscouragedFunctions sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the DiscouragedFunctions sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_PHP_DiscouragedFunctionsUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array();

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                2 => 1,
                3 => 1,
               );

    }//end getWarningList()


}//end class

?>
value = (one + two);
value = one + two;

value = (one - two);
value = one - two;

value = (one * two);
value = one * two;

value = (one / two);
value = one / two;

value = (one % two);
value = one % two;

value = (one + two + three);
value = one + two + three;
value = (one + (two + three));
value = one + (two + three);

value++;
value--;
value = -1;
value = - 1;

value = (1 + 2);
value = 1 + 2;

value = (1 - 2);
value = 1 - 2;

value = (1 * 2);
value = 1 * 2;

value = (1 / 2);
value = 1 / 2;

value = (1 % 2);
value = 1 % 2;

value = (1 + 2 + 3);
value = 1 + 2 + 3;
value = (1 + (2 + 3));
value = 1 + (2 + 3);

value = one + 2 + 3 - (four * five * (6 + 7)) + nine + 2;
value = myFunction(tokens[stackPtr - 1]);

for (i = 1 + 2; i < 4 + 5; i++) {
}

function myFunction()
{
    value = (one + 1) + (two + 2) + (myFunction() + 2);
    value = myFunction() + 2;
    value = (myFunction(mvar) + myFunction2(mvar));
    return -1;
}

params['mode'] = id.replace(/WidgetType/, '');

if (index < -1) index = 0;
if (index < - 1) index = 0;

var classN = prvId.replace(/\./g, '-');

three = myFunction(one / two);
three = myFunction((one / two) / four);
three = myFunction(one / (two / four));

four = -0.25;

id = id.replace(/row\/:/gi, '');
return /MSIE/.test(navigator.userAgent);

var re = new RegExp(/<\/?(\w+)((\s+\w+(\s*=\s*(?:".*?"|'.*?'|[^'">\s]+))?)+\s*|\s*)\/?>/gim);

var options = {
    minVal: -1,
    maxVal: -1
};

stepWidth = Math.round(this.width / 5);

date.setMonth(d[2] - 1);

switch (number % 10) {
    case -1:
        suffix = 'st';
    break;
}

var pathSplit = ipt.value.split(/\/|\\/);

if (pairs[i].search(/=/) !== -1) {
}

if (urlValue.search(/[a-zA-z]+:\/\//) !== 0) {
}

if (urlValue.search(/[a-zA-z]+:\/\/*/) !== 0) {
}

if (!value || /^\s*$/.test(value)) {
    return true;
}
<?php
/**
 * Unit test class for the OperatorBracket sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the OperatorBracket sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Formatting_OperatorBracketUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @param string $testFile The name of the file being tested.
     *
     * @return array(int => int)
     */
    public function getErrorList($testFile='OperatorBracketUnitTest.inc')
    {
        switch ($testFile) {
        case 'OperatorBracketUnitTest.inc':
            return array(
                    3   => 1,
                    6   => 1,
                    9   => 1,
                    12  => 1,
                    15  => 1,
                    18  => 2,
                    20  => 1,
                    25  => 1,
                    28  => 1,
                    31  => 1,
                    34  => 1,
                    37  => 1,
                    40  => 1,
                    43  => 2,
                    45  => 1,
                    47  => 5,
                    48  => 1,
                    50  => 2,
                    55  => 2,
                    56  => 1,
                    63  => 2,
                    64  => 1,
                    67  => 1,
                    86  => 1,
                    90  => 1,
                    109 => 1,
                    130 => 1,
                   );
            break;
        case 'OperatorBracketUnitTest.js':
            return array(
                    5  => 1,
                    8  => 1,
                    11 => 1,
                    14 => 1,
                    24 => 1,
                    30 => 1,
                    33 => 1,
                    36 => 1,
                    39 => 1,
                    46 => 1,
                    47 => 1,
                    63 => 1,
                   );
             break;
        default:
            return array();
            break;
        }//end switch

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
$value = ($one + $two);
$value = $one + $two;

$value = ($one - $two);
$value = $one - $two;

$value = ($one * $two);
$value = $one * $two;

$value = ($one / $two);
$value = $one / $two;

$value = ($one % $two);
$value = $one % $two;

$value = ($one + $two + $three);
$value = $one + $two + $three;
$value = ($one + ($two + $three));
$value = $one + ($two + $three);

$value++;
$value--;
$value = -1;
$value = - 1;

$value = (1 + 2);
$value = 1 + 2;

$value = (1 - 2);
$value = 1 - 2;

$value = (1 * 2);
$value = 1 * 2;

$value = (1 / 2);
$value = 1 / 2;

$value = (1 % 2);
$value = 1 % 2;

$value = (1 + 2 + 3);
$value = 1 + 2 + 3;
$value = (1 + (2 + 3));
$value = 1 + (2 + 3);

$value = $one + 2 + 3 - ($four * $five * (6 + 7)) + $nine + 2;
$value = myFunction($tokens[$stackPtr - 1]);

for ($i = 1 + 2; $i < 4 + 5; $i++) {
}

function myFunction()
{
    $value = ($one + 1) + ($two + 2) + (myFunction() + 2);
    $value = myFunction() + 2;
    $value = (myFunction($var) + myFunction2($var));
    return -1;
}

$line  = substr($line, 0, -2);
$words = preg_split('|(\s+)|', $line."\n", -1, $flags);
if (!isset($this->words[$wordPos-1]) || $this->words[$wordPos-1] !== ' ') {
} else if ($this->tokens[$pos + 1] === "\n") {
}

if ($pos === count($this->tokens) - 1) {
    $file = '...'.substr($file, (($padding * -1) + 3));
}

if (substr($basename, -5) !== 'Sniff') {
    $i = ($this->_tokens[$i]['parenthesis_closer'] + 1);
}

$pos = $this->_getShortCommentEndPos();
if ($pos === -1) {
    $stackPtr = ($tokens[$next][$to] - 1);
    $stackPtr = ($tokens[$next][$pattern[$i]['to']] + 1);
    $var = (($var1 + $var2) + $var3 + $var4)
}

$commentStart = ($phpcsFile->findPrevious(T_DOC_COMMENT, ($commentEnd - 1), null, true) + 1);
$commentEnd   = ($this->_phpcsFile->findNext(T_DOC_COMMENT, ($commentStart + 1), null, true) - 1);
$expected    .= '...'.substr($tokens[($stackPtr - 2)]['content'], -5).$tokens[$stackPtr]['content'];

if (($tokens[$nextToken - 1]['code']) !== T_WHITESPACE) {
    $errorPos = ($params[(count($params) - 1)]->getLine() + $commentStart);
}

while (($nextSpace = $phpcsFile->findNext(T_WHITESPACE, $nextSpace + 1, $nextBreak)) !== false) {
}

foreach ($attributes as $id => &$attribute) {
}

class MyClass
{


    public function &myFunction(array &$one, array &$two)
    {

    }//end myFunction()


}//end class

if ($index < -1) $index = 0;
if ($index < - 1) $index = 0;

$three = ceil($one / $two);
$three = ceil(($one / $two) / $four);
$three = ceil($one / ($two / $four));

$four = -0.25;

$three = ceil($one[1] / $two);

switch ($number % 10) {
    case -1:
        $suffix = 'st';
    break;
}

$expectedPermission = array(
                       'granted'        => 4,
                       'denied'         => 1,
                       'cascade'        => TRUE,
                       'blockergranted' => 2,
                       'blockerdenied'  => - 3,
                       'effective'      => TRUE,
                      );
?>
<?php
/**
 * Unit test class for the DuplicateProperty sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the DuplicateProperty sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Classes_DuplicatePropertyUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                4  => 1,
                8  => 1,
                28 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the LowercaseClassKeywords sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the LowercaseClassKeywords sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Classes_LowercaseClassKeywordsUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        $errors = array(
                   2  => 3,
                   3  => 3,
                   4  => 1,
                   9  => 1,
                   10 => 1,
                  );

        // The trait test will only work in PHP versions where traits exist.
        if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
            $errors[5] = 1;
        }

        return $errors;

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php


class SelfMemberReferenceUnitTestExample
{


    private $testCount = 0;


    private $testResults = array();


    public function SelfMemberReferenceUnitTestExample()
    {
        $testResults =& $this->testResults;


        // Correct call to self.
        $testResults[] = self::selfMemberReferenceUnitTestFunction();
        $testResults[] = parent::selfMemberReferenceUnitTestFunction();

        // Incorrect case.
        $testResults[] = Self::selfMemberReferenceUnitTestFunction();
        $testResults[] = SELF::selfMemberReferenceUnitTestFunction();
        $testResults[] = SelfMemberReferenceUnitTestExample::selfMemberReferenceUnitTestFunction();


        // Incorrect spacing.
        $testResults[] = self ::selfMemberReferenceUnitTestFunction();
        $testResults[] = self::  selfMemberReferenceUnitTestFunction();
        $testResults[] = self  :: selfMemberReferenceUnitTestFunction();

    }


    function selfMemberReferenceUnitTestFunction()
    {
        $this->testCount = $this->testCount + 1;
        return $this->testCount;

    }


}


class MyClass {

    public static function test($value) {
        echo "$value\n";
    }

    public static function walk() {
        $callback = function($value, $key) {
                        // This is valid because you cant use self:: in a closure
                        MyClass::test($value);
                    };

        $array = array(1,2,3);
        array_walk($array, $callback);
    }
}

MyClass::walk();

class Controller
{
    public function Action()
    {
        Doctrine\Common\Util\Debug::dump();
    }
}

namespace TYPO3\CMS\Reports;

class Status {
    const NOTICE = -2;
    const INFO = -1;
    const OK = 0;
    const WARNING = 1;
    const ERROR = 2;
}

namespace TYPO3\CMS\Reports\Report\Status;

class Status implements \TYPO3\CMS\Reports\ReportInterface {
    public function getHighestSeverity(array $statusCollection) {
        $highestSeverity = \TYPO3\CMS\Reports\Status::NOTICE;
    }
}
?>
<?php
/**
 * Unit test class for the ClassFileName sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ClassFileName sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Classes_ClassFileNameUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                9  => 1,
                10 => 1,
                11 => 1,
                15 => 1,
                16 => 1,
                17 => 1,
                18 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php


// Valid class name.
class ValidCamelCaseClass extends MyClass {}


// Incorrect usage of camel case.
class invalidCamelCaseClass extends MyClass {}
class Invalid_Camel_Case_Class_With_Underscores implements MyClass {}


// All lowercase.
class invalidlowercaseclass extends MyClass {}
class invalid_lowercase_class_with_underscores extends MyClass {}


// All uppercase.
class VALIDUPPERCASECLASS extends MyClass {}
class INVALID_UPPERCASE_CLASS_WITH_UNDERSCORES extends MyClass {}


// Mix camel case with uppercase.
class ValidCamelCaseClassWithUPPERCASE extends MyClass {}


// Usage of numeric characters.
class ValidCamelCaseClassWith1Number extends MyClass {}
class ValidCamelCaseClassWith12345Numbers extends MyClass {}
class 5InvalidCamelCaseClassStartingWithNumber extends MyClass {}
class ValidCamelCaseClassEndingWithNumber5 extends MyClass {}
class 12345 extends MyClass {}


?>var x = {
  abc: 1,
  zyz: 2,
  abc: 5,
  mno: {
      abc: 4
  },
  abc: 5
  
  this.request({
    action: 'getSubmissions'
  });

  this.request({
    action: 'deleteSubmission'
  });
}


LinkingEditScreenWidgetType.prototype = {

    _addDeleteButtonEvent: function(parentid)
    {
        var params = {
            screen: 'LinkingEditScreenWidget',
            assetid: self.assetid,
            parentid: parentid,
            assetid: parentid,
            op: 'deleteLink'
        };

    },

    saveDesignEdit: function()
    {
        var params = {
            screen: [this.id, 'Widget'].join(''),
            assetid: this.assetid,
            changes: dfx.jsonEncode(this.currnetLinksWdgt.getChanges()),
            op: 'saveLinkEdit'
        };

    }

};<?php


// Valid class name (matching filename).
class ClassFileNameUnitTest {}


// Invalid filename matching class name (case sensitive).
class classFileNameUnitTest {}
class classfilenameunittest {}
class CLASSFILENAMEUNITTEST {}


// Invalid non-filename matching class names.
class CompletelyWrongClassName {}
class ClassFileNameUnitTestExtra {}
class ClassFileNameUnitTestInc {}
class ExtraClassFileNameUnitTest {}


?><?php
/**
 * Unit test class for the ClassDeclaration sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ClassDeclaration sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Classes_ClassDeclarationUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                10  => 1,
                15  => 2,
                18  => 1,
                22  => 3,
                23  => 3,
                24  => 3,
                27  => 2,
                28  => 1,
                30  => 2,
                34  => 1,
                35  => 1,
                39  => 1,
                42  => 2,
                45  => 1,
                48  => 1,
                50  => 2,
                55  => 1,
                59  => 4,
                63  => 1,
                65  => 1,
                69  => 3,
                74  => 2,
                77  => 1,
                80  => 1,
                85  => 3,
                89  => 1,
                92  => 1,
                97  => 1,
                100 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the ValidClassName sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ValidClassName sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Classes_ValidClassNameUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                9  => 1,
                10 => 1,
                14 => 1,
                15 => 1,
                20 => 1,
                30 => 1,
                32 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php



class ClassDeclaration
{

}

abstract class CorrectClassDeclarationWithExtends extends correctClassDeclaration
{

}

final  class CorrectClassDeclarationWithImplements implements correctClassDeclaration
{

}


// Incorrect placement of opening/closing braces, including indent.
class IncorrectBracePlacement {}
class IncorrectBracePlacementWithExtends extends correctClassDeclaration {}
class IncorrectBracePlacementWithImplements implements correctClassDeclaration {}


    class IncorrectIndentedClass
    {

    }//end class


// Incorrect code placement for opening/closing brace.
class IncorrectCodeAfterOpeningBrace
{ echo phpinfo();

}//end class

class IncorrectCodeAfterClosingBrace
{

} echo phpinfo();


class IncorrectCodeBeforeClosingBrace
{

echo phpinfo(); }

    class IncorrectIndentedClass
{

}

class ClassOne implements ClassTwo, ClassThree
{
}//end class

class ClassOne implements ClassFour   ,ClassFive,  ClassSix
{
}//end class

class CorrectClassDeclarationWithExtends extends correctClassDeclaration

{

}

class CorrectClassDeclarationWithExtends   extends correctClassDeclaration
{

}//end class

class   CorrectClassDeclaration
{

}//end class


class CorrectClassDeclaration extends CorrectClassDeclaration2 implements ICorrectClassDeclaration
{

}//end class

class File implements \Zend_Auth_Storage_Interface,\Zend_Auth_Storage,  \Zend_Foo
{
}

interface MyInterface
{

}
?>

<?php

class CorrectClassDeclaration
{

}//end class
<?php
Abstract Class MyClass Extends MyClass {}
Final Class MyClass Implements MyInterface {}
Interface MyInterface {}
Trait MyTrait {}

class MyClass
{
    Var $myVar = null;
    Const myConst = true;
}
?>
<?php
/**
 * Unit test class for the SelfMemberReference sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the SelfMemberReference sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Squiz_Tests_Classes_SelfMemberReferenceUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                24 => 1,
                25 => 1,
                26 => 1,
                30 => 1,
                31 => 1,
                32 => 2,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?xml version="1.0"?>
<ruleset name="Squiz">
 <description>The Squiz coding standard.</description>

 <!-- Include some specific sniffs -->
 <rule ref="Generic.CodeAnalysis.UnusedFunctionParameter"/>
 <rule ref="Generic.Commenting.Todo"/>
 <rule ref="Generic.ControlStructures.InlineControlStructure"/>
 <rule ref="Generic.Formatting.DisallowMultipleStatements"/>
 <rule ref="Generic.Formatting.SpaceAfterCast"/>
 <rule ref="Generic.Functions.FunctionCallArgumentSpacing"/>
 <rule ref="Generic.NamingConventions.ConstructorName"/>
 <rule ref="Generic.NamingConventions.UpperCaseConstantName"/>
 <rule ref="Generic.PHP.DeprecatedFunctions"/>
 <rule ref="Generic.PHP.DisallowShortOpenTag"/>
 <rule ref="Generic.PHP.LowerCaseKeyword"/>
 <rule ref="Generic.Strings.UnnecessaryStringConcat"/>
 <rule ref="Generic.WhiteSpace.DisallowTabIndent"/>
 <rule ref="Generic.WhiteSpace.ScopeIndent"/>
 <rule ref="PEAR.ControlStructures.MultiLineCondition"/>
 <rule ref="PEAR.Files.IncludingFile"/>
 <rule ref="PEAR.Formatting.MultiLineAssignment"/>
 <rule ref="Zend.Debug.CodeAnalyzer"/>

 <!-- Lines can be 120 chars long, but never show errors -->
 <rule ref="Generic.Files.LineLength">
  <properties>
   <property name="lineLimit" value="120"/>
   <property name="absoluteLineLimit" value="0"/>
  </properties>
 </rule>

 <!-- Use Unix newlines -->
 <rule ref="Generic.Files.LineEndings">
  <properties>
   <property name="eolChar" value="\n"/>
  </properties>
 </rule>

 <!-- Have 8 chars padding maximum and always show as errors -->
 <rule ref="Generic.Formatting.MultipleStatementAlignment">
  <properties>
   <property name="maxPadding" value="8"/>
   <property name="ignoreMultiLine" value="true"/>
   <property name="error" value="true"/>
  </properties>
 </rule>

 <!-- Tweaks to metrics -->
 <rule ref="Generic.Metrics.CyclomaticComplexity">
  <properties>
   <property name="complexity" value="10"/>
   <property name="absoluteComplexity" value="100"/>
  </properties>
 </rule>
 <rule ref="Generic.Metrics.NestingLevel">
  <properties>
   <property name="nestingLevel" value="5"/>
   <property name="absoluteNestingLevel" value="50"/>
  </properties>
 </rule>

 <!-- We don't want gsjlint throwing errors for things we already check -->
 <rule ref="Generic.Debug.ClosureLinter">
  <properties>
   <property name="errorCodes" type="array" value="0210"/>
   <property name="ignoreCodes" type="array" value="0001,0110,0240"/>
  </properties>
 </rule>
 <rule ref="Generic.Debug.ClosureLinter.ExternalToolError">
  <message>%2$s</message>
 </rule>

 <!-- Only one argument per line in multi-line function calls -->
 <rule ref="PEAR.Functions.FunctionCallSignature">
  <properties>
   <property name="allowMultipleArguments" value="false"/>
  </properties>
 </rule>

</ruleset>
<?php
/**
 * An AbstractScopeTest allows for tests that extend from this class to
 * listen for tokens within a particular scope.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * An AbstractScopeTest allows for tests that extend from this class to
 * listen for tokens within a particular scope.
 *
 * Below is a test that listens to methods that exist only within classes:
 * <code>
 * class ClassScopeTest extends PHP_CodeSniffer_Standards_AbstractScopeSniff
 * {
 *     public function __construct()
 *     {
 *         parent::__construct(array(T_CLASS), array(T_FUNCTION));
 *     }
 *
 *     protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $)
 *     {
 *         $className = $phpcsFile->getDeclarationName($currScope);
 *         echo 'encountered a method within class '.$className;
 *     }
 * }
 * </code>
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
abstract class PHP_CodeSniffer_Standards_AbstractScopeSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * The token types that this test wishes to listen to within the scope.
     *
     * @var array
     */
    private $_tokens = array();

    /**
     * The type of scope opener tokens that this test wishes to listen to.
     *
     * @var string
     */
    private $_scopeTokens = array();

    /**
     * True if this test should fire on tokens outside of the scope.
     *
     * @var boolean
     */
    private $_listenOutside = false;


    /**
     * Constructs a new AbstractScopeTest.
     *
     * @param array   $scopeTokens   The type of scope the test wishes to listen to.
     * @param array   $tokens        The tokens that the test wishes to listen to
     *                               within the scope.
     * @param boolean $listenOutside If true this test will also alert the
     *                               extending class when a token is found outside
     *                               the scope, by calling the
     *                               processTokenOutsideScope method.
     *
     * @see PHP_CodeSniffer.getValidScopeTokeners()
     * @throws PHP_CodeSniffer_Exception If the specified tokens array is empty.
     */
    public function __construct(
        array $scopeTokens,
        array $tokens,
        $listenOutside=false
    ) {
        if (empty($scopeTokens) === true) {
            $error = 'The scope tokens list cannot be empty';
            throw new PHP_CodeSniffer_Exception($error);
        }

        if (empty($tokens) === true) {
            $error = 'The tokens list cannot be empty';
            throw new PHP_CodeSniffer_Exception($error);
        }

        $invalidScopeTokens = array_intersect($scopeTokens, $tokens);
        if (empty($invalidScopeTokens) === false) {
            $invalid = implode(', ', $invalidScopeTokens);
            $error   = "Scope tokens [$invalid] cant be in the tokens array";
            throw new PHP_CodeSniffer_Exception($error);
        }

        $this->_listenOutside = $listenOutside;
        $this->_scopeTokens   = $scopeTokens;
        $this->_tokens        = $tokens;

    }//end __construct()


    /**
     * The method that is called to register the tokens this test wishes to
     * listen to.
     *
     * DO NOT OVERRIDE THIS METHOD. Use the constructor of this class to register
     * for the desired tokens and scope.
     *
     * @return array(int)
     * @see __constructor()
     */
    public final function register()
    {
        return $this->_tokens;

    }//end register()


    /**
     * Processes the tokens that this test is listening for.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
     * @param int                  $stackPtr  The position in the stack where this
     *                                        token was found.
     *
     * @return void
     * @see processTokenWithinScope()
     */
    public final function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $foundScope = false;
        foreach ($tokens[$stackPtr]['conditions'] as $scope => $code) {
            if (in_array($code, $this->_scopeTokens) === true) {
                $this->processTokenWithinScope($phpcsFile, $stackPtr, $scope);
                $foundScope = true;
            }
        }

        if ($this->_listenOutside === true && $foundScope === false) {
            $this->processTokenOutsideScope($phpcsFile, $stackPtr);
        }

    }//end process()


    /**
     * Processes a token that is found within the scope that this test is
     * listening to.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
     * @param int                  $stackPtr  The position in the stack where this
     *                                        token was found.
     * @param int                  $currScope The position in the tokens array that
     *                                        opened the scope that this test is
     *                                        listening for.
     *
     * @return void
     */
    protected abstract function processTokenWithinScope(
        PHP_CodeSniffer_File $phpcsFile,
        $stackPtr,
        $currScope
    );


    /**
     * Processes a token that is found within the scope that this test is
     * listening to.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
     * @param int                  $stackPtr  The position in the stack where this
     *                                        token was found.
     *
     * @return void
     */
    protected function processTokenOutsideScope(
        PHP_CodeSniffer_File $phpcsFile,
        $stackPtr
    ) {

    }//end processTokenOutsideScope()


}//end class

?>
<?php
/**
 * PEAR_Sniffs_NamingConventions_ValidFunctionNameSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_Standards_AbstractScopeSniff', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_Standards_AbstractScopeSniff not found');
}

/**
 * PEAR_Sniffs_NamingConventions_ValidFunctionNameSniff.
 *
 * Ensures method names are correct depending on whether they are public
 * or private, and that functions are named correctly.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Sniffs_NamingConventions_ValidFunctionNameSniff extends PHP_CodeSniffer_Standards_AbstractScopeSniff
{

    /**
     * A list of all PHP magic methods.
     *
     * @var array
     */
    protected $magicMethods = array(
                               'construct',
                               'destruct',
                               'call',
                               'callstatic',
                               'get',
                               'set',
                               'isset',
                               'unset',
                               'sleep',
                               'wakeup',
                               'tostring',
                               'set_state',
                               'clone',
                               'invoke',
                               'call',
                              );

    /**
     * A list of all PHP magic functions.
     *
     * @var array
     */
    protected $magicFunctions = array('autoload');


    /**
     * Constructs a PEAR_Sniffs_NamingConventions_ValidFunctionNameSniff.
     */
    public function __construct()
    {
        parent::__construct(array(T_CLASS, T_INTERFACE, T_TRAIT), array(T_FUNCTION), true);

    }//end __construct()


    /**
     * Processes the tokens within the scope.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being processed.
     * @param int                  $stackPtr  The position where this token was
     *                                        found.
     * @param int                  $currScope The position of the current scope.
     *
     * @return void
     */
    protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope)
    {
        $methodName = $phpcsFile->getDeclarationName($stackPtr);
        if ($methodName === null) {
            // Ignore closures.
            return;
        }

        $className = $phpcsFile->getDeclarationName($currScope);
        $errorData = array($className.'::'.$methodName);

        // Is this a magic method. i.e., is prefixed with "__" ?
        if (preg_match('|^__|', $methodName) !== 0) {
            $magicPart = strtolower(substr($methodName, 2));
            if (in_array($magicPart, $this->magicMethods) === false) {
                 $error = 'Method name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore';
                 $phpcsFile->addError($error, $stackPtr, 'MethodDoubleUnderscore', $errorData);
            }

            return;
        }

        // PHP4 constructors are allowed to break our rules.
        if ($methodName === $className) {
            return;
        }

        // PHP4 destructors are allowed to break our rules.
        if ($methodName === '_'.$className) {
            return;
        }

        $methodProps    = $phpcsFile->getMethodProperties($stackPtr);
        $isPublic       = ($methodProps['scope'] === 'private') ? false : true;
        $scope          = $methodProps['scope'];
        $scopeSpecified = $methodProps['scope_specified'];

        // If it's a private method, it must have an underscore on the front.
        if ($isPublic === false && $methodName{0} !== '_') {
            $error = 'Private method name "%s" must be prefixed with an underscore';
            $phpcsFile->addError($error, $stackPtr, 'PrivateNoUnderscore', $errorData);
            return;
        }

        // If it's not a private method, it must not have an underscore on the front.
        if ($isPublic === true && $scopeSpecified === true && $methodName{0} === '_') {
            $error = '%s method name "%s" must not be prefixed with an underscore';
            $data  = array(
                      ucfirst($scope),
                      $errorData[0],
                     );
            $phpcsFile->addError($error, $stackPtr, 'PublicUnderscore', $data);
            return;
        }

        // If the scope was specified on the method, then the method must be
        // camel caps and an underscore should be checked for. If it wasn't
        // specified, treat it like a public method and remove the underscore
        // prefix if there is one because we cant determine if it is private or
        // public.
        $testMethodName = $methodName;
        if ($scopeSpecified === false && $methodName{0} === '_') {
            $testMethodName = substr($methodName, 1);
        }

        if (PHP_CodeSniffer::isCamelCaps($testMethodName, false, $isPublic, false) === false) {
            if ($scopeSpecified === true) {
                $error = '%s method name "%s" is not in camel caps format';
                $data  = array(
                          ucfirst($scope),
                          $errorData[0],
                         );
                $phpcsFile->addError($error, $stackPtr, 'ScopeNotCamelCaps', $data);
            } else {
                $error = 'Method name "%s" is not in camel caps format';
                $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData);
            }

            return;
        }

    }//end processTokenWithinScope()


    /**
     * Processes the tokens outside the scope.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being processed.
     * @param int                  $stackPtr  The position where this token was
     *                                        found.
     *
     * @return void
     */
    protected function processTokenOutsideScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $functionName = $phpcsFile->getDeclarationName($stackPtr);
        if ($functionName === null) {
            // Ignore closures.
            return;
        }

        $errorData = array($functionName);

        // Is this a magic function. i.e., it is prefixed with "__".
        if (preg_match('|^__|', $functionName) !== 0) {
            $magicPart = strtolower(substr($functionName, 2));
            if (in_array($magicPart, $this->magicFunctions) === false) {
                 $error = 'Function name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore';
                 $phpcsFile->addError($error, $stackPtr, 'FunctionDoubleUnderscore', $errorData);
            }

            return;
        }

        // Function names can be in two parts; the package name and
        // the function name.
        $packagePart   = '';
        $camelCapsPart = '';
        $underscorePos = strrpos($functionName, '_');
        if ($underscorePos === false) {
            $camelCapsPart = $functionName;
        } else {
            $packagePart   = substr($functionName, 0, $underscorePos);
            $camelCapsPart = substr($functionName, ($underscorePos + 1));

            // We don't care about _'s on the front.
            $packagePart = ltrim($packagePart, '_');
        }

        // If it has a package part, make sure the first letter is a capital.
        if ($packagePart !== '') {
            if ($functionName{0} === '_') {
                $error = 'Function name "%s" is invalid; only private methods should be prefixed with an underscore';
                $phpcsFile->addError($error, $stackPtr, 'FunctionUnderscore', $errorData);
                return;
            }

            if ($functionName{0} !== strtoupper($functionName{0})) {
                $error = 'Function name "%s" is prefixed with a package name but does not begin with a capital letter';
                $phpcsFile->addError($error, $stackPtr, 'FunctionNoCapital', $errorData);
                return;
            }
        }

        // If it doesn't have a camel caps part, it's not valid.
        if (trim($camelCapsPart) === '') {
            $error = 'Function name "%s" is not valid; name appears incomplete';
            $phpcsFile->addError($error, $stackPtr, 'FunctionInvalid', $errorData);
            return;
        }

        $validName        = true;
        $newPackagePart   = $packagePart;
        $newCamelCapsPart = $camelCapsPart;

        // Every function must have a camel caps part, so check that first.
        if (PHP_CodeSniffer::isCamelCaps($camelCapsPart, false, true, false) === false) {
            $validName        = false;
            $newCamelCapsPart = strtolower($camelCapsPart{0}).substr($camelCapsPart, 1);
        }

        if ($packagePart !== '') {
            // Check that each new word starts with a capital.
            $nameBits = explode('_', $packagePart);
            foreach ($nameBits as $bit) {
                if ($bit{0} !== strtoupper($bit{0})) {
                    $newPackagePart = '';
                    foreach ($nameBits as $bit) {
                        $newPackagePart .= strtoupper($bit{0}).substr($bit, 1).'_';
                    }

                    $validName = false;
                    break;
                }
            }
        }

        if ($validName === false) {
            $newName = rtrim($newPackagePart, '_').'_'.$newCamelCapsPart;
            if ($newPackagePart === '') {
                $newName = $newCamelCapsPart;
            } else {
                $newName = rtrim($newPackagePart, '_').'_'.$newCamelCapsPart;
            }

            $error  = 'Function name "%s" is invalid; consider "%s" instead';
            $data   = $errorData;
            $data[] = $newName;
            $phpcsFile->addError($error, $stackPtr, 'FunctionNameInvalid', $data);
        }

    }//end processTokenOutsideScope()


}//end class

?>
<?php
/**
 * PEAR_Sniffs_NamingConventions_ValidClassNameSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * PEAR_Sniffs_NamingConventions_ValidClassNameSniff.
 *
 * Ensures class and interface names start with a capital letter
 * and use _ separators.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Sniffs_NamingConventions_ValidClassNameSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_CLASS,
                T_INTERFACE,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The current file being processed.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $className = $phpcsFile->findNext(T_STRING, $stackPtr);
        $name      = trim($tokens[$className]['content']);
        $errorData = array(ucfirst($tokens[$stackPtr]['content']));

        // Make sure the first letter is a capital.
        if (preg_match('|^[A-Z]|', $name) === 0) {
            $error = '%s name must begin with a capital letter';
            $phpcsFile->addError($error, $stackPtr, 'StartWithCapital', $errorData);
        }

        // Check that each new word starts with a capital as well, but don't
        // check the first word, as it is checked above.
        $validName = true;
        $nameBits  = explode('_', $name);
        $firstBit  = array_shift($nameBits);
        foreach ($nameBits as $bit) {
            if ($bit === '' || $bit{0} !== strtoupper($bit{0})) {
                $validName = false;
                break;
            }
        }

        if ($validName === false) {
            // Strip underscores because they cause the suggested name
            // to be incorrect.
            $nameBits = explode('_', trim($name, '_'));
            $firstBit = array_shift($nameBits);
            if ($firstBit === '') {
                $error = '%s name is not valid';
                $phpcsFile->addError($error, $stackPtr, 'Invalid', $errorData);
            } else {
                $newName = strtoupper($firstBit{0}).substr($firstBit, 1).'_';
                foreach ($nameBits as $bit) {
                    if ($bit !== '') {
                        $newName .= strtoupper($bit{0}).substr($bit, 1).'_';
                    }
                }

                $newName = rtrim($newName, '_');
                $error   = '%s name is not valid; consider %s instead';
                $data    = $errorData;
                $data[]  = $newName;
                $phpcsFile->addError($error, $stackPtr, 'Invalid', $data);
            }
        }//end if

    }//end process()


}//end class


?>
<?php
/**
 * PEAR_Sniffs_NamingConventions_ValidVariableNameSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_Standards_AbstractVariableSniff', true) === false) {
    $error = 'Class PHP_CodeSniffer_Standards_AbstractVariableSniff not found';
    throw new PHP_CodeSniffer_Exception($error);
}

/**
 * PEAR_Sniffs_NamingConventions_ValidVariableNameSniff.
 *
 * Checks the naming of member variables.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Sniffs_NamingConventions_ValidVariableNameSniff extends PHP_CodeSniffer_Standards_AbstractVariableSniff
{


    /**
     * Processes class member variables.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    protected function processMemberVar(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $memberProps = $phpcsFile->getMemberProperties($stackPtr);
        if (empty($memberProps) === true) {
            return;
        }

        $memberName     = ltrim($tokens[$stackPtr]['content'], '$');
        $isPublic       = ($memberProps['scope'] === 'private') ? false : true;
        $scope          = $memberProps['scope'];
        $scopeSpecified = $memberProps['scope_specified'];

        // If it's a private member, it must have an underscore on the front.
        if ($isPublic === false && $memberName{0} !== '_') {
            $error = 'Private member variable "%s" must be prefixed with an underscore';
            $data  = array($memberName);
            $phpcsFile->addError($error, $stackPtr, 'PrivateNoUnderscore', $data);
            return;
        }

        // If it's not a private member, it must not have an underscore on the front.
        if ($isPublic === true && $scopeSpecified === true && $memberName{0} === '_') {
            $error = '%s member variable "%s" must not be prefixed with an underscore';
            $data  = array(
                      ucfirst($scope),
                      $memberName,
                     );
            $phpcsFile->addError($error, $stackPtr, 'PublicUnderscore', $data);
            return;
        }

    }//end processMemberVar()


    /**
     * Processes normal variables.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
     * @param int                  $stackPtr  The position where the token was found.
     *
     * @return void
     */
    protected function processVariable(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        // We don't care about normal variables.

    }//end processVariable()


    /**
     * Processes variables in double quoted strings.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
     * @param int                  $stackPtr  The position where the token was found.
     *
     * @return void
     */
    protected function processVariableInString(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        // We don't care about normal variables.

    }//end processVariableInString()


}//end class

?>
<?php
/**
 * PEAR_Sniffs_WhiteSpace_ObjectOperatorIndentSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * PEAR_Sniffs_WhiteSpace_ObjectOperatorIndentSniff.
 *
 * Checks that object operators are indented 4 spaces if they are the first
 * thing on a line.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Sniffs_WhiteSpace_ObjectOperatorIndentSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * The number of spaces code should be indented.
     *
     * @var int
     */
    public $indent = 4;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_OBJECT_OPERATOR);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile All the tokens found in the document.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Make sure this is the first object operator in a chain of them.
        $varToken = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
        if ($varToken === false || $tokens[$varToken]['code'] !== T_VARIABLE) {
            return;
        }

        // Make sure this is a chained call.
        $next = $phpcsFile->findNext(
            T_OBJECT_OPERATOR,
            ($stackPtr + 1),
            null,
            false,
            null,
            true
        );

        if ($next === false) {
            // Not a chained call.
            return;
        }

        // Determine correct indent.
        for ($i = ($varToken - 1); $i >= 0; $i--) {
            if ($tokens[$i]['line'] !== $tokens[$varToken]['line']) {
                $i++;
                break;
            }
        }

        $requiredIndent = 0;
        if ($i >= 0 && $tokens[$i]['code'] === T_WHITESPACE) {
            $requiredIndent = strlen($tokens[$i]['content']);
        }

        $requiredIndent += $this->indent;

        // Determine the scope of the original object operator.
        $origBrackets = null;
        if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) {
            $origBrackets = $tokens[$stackPtr]['nested_parenthesis'];
        }

        $origConditions = null;
        if (isset($tokens[$stackPtr]['conditions']) === true) {
            $origConditions = $tokens[$stackPtr]['conditions'];
        }

        // Check indentation of each object operator in the chain.
        // If the first object operator is on a different line than
        // the variable, make sure we check its indentation too.
        if ($tokens[$stackPtr]['line'] > $tokens[$varToken]['line']) {
            $next = $stackPtr;
        }

        while ($next !== false) {
            // Make sure it is in the same scope, otherwise don't check indent.
            $brackets = null;
            if (isset($tokens[$next]['nested_parenthesis']) === true) {
                $brackets = $tokens[$next]['nested_parenthesis'];
            }

            $conditions = null;
            if (isset($tokens[$next]['conditions']) === true) {
                $conditions = $tokens[$next]['conditions'];
            }

            if ($origBrackets === $brackets && $origConditions === $conditions) {
                // Make sure it starts a line, otherwise dont check indent.
                $indent = $tokens[($next - 1)];
                if ($indent['code'] === T_WHITESPACE) {
                    if ($indent['line'] === $tokens[$next]['line']) {
                        $foundIndent = strlen($indent['content']);
                    } else {
                        $foundIndent = 0;
                    }

                    if ($foundIndent !== $requiredIndent) {
                        $error = 'Object operator not indented correctly; expected %s spaces but found %s';
                        $data  = array(
                                  $requiredIndent,
                                  $foundIndent,
                                 );
                        $phpcsFile->addError($error, $next, 'Incorrect', $data);
                    }
                }

                // It cant be the last thing on the line either.
                $content = $phpcsFile->findNext(T_WHITESPACE, ($next + 1), null, true);
                if ($tokens[$content]['line'] !== $tokens[$next]['line']) {
                    $error = 'Object operator must be at the start of the line, not the end';
                    $phpcsFile->addError($error, $next, 'StartOfLine');
                }
            }//end if

            $next = $phpcsFile->findNext(
                T_OBJECT_OPERATOR,
                ($next + 1),
                null,
                false,
                null,
                true
            );
        }//end while

    }//end process()


}//end class

?>
<?php
/**
 * PEAR_Sniffs_Whitespace_ScopeClosingBraceSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * PEAR_Sniffs_Whitespace_ScopeClosingBraceSniff.
 *
 * Checks that the closing braces of scopes are aligned correctly.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Sniffs_WhiteSpace_ScopeClosingBraceSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * The number of spaces code should be indented.
     *
     * @var int
     */
    public $indent = 4;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return PHP_CodeSniffer_Tokens::$scopeOpeners;

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile All the tokens found in the document.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // If this is an inline condition (ie. there is no scope opener), then
        // return, as this is not a new scope.
        if (isset($tokens[$stackPtr]['scope_closer']) === false) {
            return;
        }

        $scopeStart  = $tokens[$stackPtr]['scope_opener'];
        $scopeEnd    = $tokens[$stackPtr]['scope_closer'];

        // If the scope closer doesn't think it belongs to this scope opener
        // then the opener is sharing its closer ith other tokens. We only
        // want to process the closer once, so skip this one.
        if ($tokens[$scopeEnd]['scope_condition'] !== $stackPtr) {
            return;
        }

        // We need to actually find the first piece of content on this line,
        // because if this is a method with tokens before it (public, static etc)
        // or an if with an else before it, then we need to start the scope
        // checking from there, rather than the current token.
        $lineStart = ($stackPtr - 1);
        for ($lineStart; $lineStart > 0; $lineStart--) {
            if (strpos($tokens[$lineStart]['content'], $phpcsFile->eolChar) !== false) {
                break;
            }
        }

        // We found a new line, now go forward and find the first non-whitespace
        // token.
        $lineStart= $phpcsFile->findNext(
            array(T_WHITESPACE),
            ($lineStart + 1),
            null,
            true
        );

        $startColumn = $tokens[$lineStart]['column'];

        // Check that the closing brace is on it's own line.
        $lastContent = $phpcsFile->findPrevious(
            array(T_WHITESPACE),
            ($scopeEnd - 1),
            $scopeStart,
            true
        );

        if ($tokens[$lastContent]['line'] === $tokens[$scopeEnd]['line']) {
            $error = 'Closing brace must be on a line by itself';
            $phpcsFile->addError($error, $scopeEnd, 'Line');
            return;
        }

        // Check now that the closing brace is lined up correctly.
        $braceIndent   = $tokens[$scopeEnd]['column'];
        if (in_array($tokens[$stackPtr]['code'], array(T_CASE, T_DEFAULT)) === true) {
            // BREAK statements should be indented n spaces from the
            // CASE or DEFAULT statement.
            if ($braceIndent !== ($startColumn + $this->indent)) {
                $error = 'Case breaking statement indented incorrectly; expected %s spaces, found %s';
                $data  = array(
                          ($startColumn + $this->indent - 1),
                          ($braceIndent - 1),
                         );
                $phpcsFile->addError($error, $scopeEnd, 'BreakIdent', $data);
            }
        } else {
            if ($braceIndent !== $startColumn) {
                $error = 'Closing brace indented incorrectly; expected %s spaces, found %s';
                $data  = array(
                          ($startColumn - 1),
                          ($braceIndent - 1),
                         );
                $phpcsFile->addError($error, $scopeEnd, 'Indent', $data);
            }
        }

    }//end process()


}//end class

?>
<?php
/**
 * PEAR_Sniffs_Whitespace_ScopeIndentSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('Generic_Sniffs_WhiteSpace_ScopeIndentSniff', true) === false) {
    $error = 'Class Generic_Sniffs_WhiteSpace_ScopeIndentSniff not found';
    throw new PHP_CodeSniffer_Exception($error);
}

/**
 * PEAR_Sniffs_Whitespace_ScopeIndentSniff.
 *
 * Checks that control structures are structured correctly, and their content
 * is indented correctly.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Sniffs_WhiteSpace_ScopeIndentSniff extends Generic_Sniffs_WhiteSpace_ScopeIndentSniff
{

    /**
     * Any scope openers that should not cause an indent.
     *
     * @var array(int)
     */
    protected $nonIndentingScopes = array(T_SWITCH);

}//end class

?>
<?php
/**
 * PEAR_Sniffs_Functions_ValidDefaultValueSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * PEAR_Sniffs_Functions_ValidDefaultValueSniff.
 *
 * A Sniff to ensure that parameters defined for a function that have a default
 * value come at the end of the function signature.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Sniffs_Functions_ValidDefaultValueSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_FUNCTION);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $argStart = $tokens[$stackPtr]['parenthesis_opener'];
        $argEnd   = $tokens[$stackPtr]['parenthesis_closer'];

        // Flag for when we have found a default in our arg list.
        // If there is a value without a default after this, it is an error.
        $defaultFound = false;

        $nextArg = $argStart;
        while (($nextArg = $phpcsFile->findNext(T_VARIABLE, ($nextArg + 1), $argEnd)) !== false) {
            $argHasDefault = self::_argHasDefault($phpcsFile, $nextArg);
            if (($argHasDefault === false) && ($defaultFound === true)) {
                $error  = 'Arguments with default values must be at the end of the argument list';
                $phpcsFile->addError($error, $nextArg, 'NotAtEnd');
                return;
            }

            if ($argHasDefault === true) {
                $defaultFound = true;
            }
        }

    }//end process()


    /**
     * Returns true if the passed argument has a default value.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $argPtr    The position of the argument
     *                                        in the stack.
     *
     * @return bool
     */
    private static function _argHasDefault(PHP_CodeSniffer_File $phpcsFile, $argPtr)
    {
        $tokens    = $phpcsFile->getTokens();
        $nextToken = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($argPtr + 1), null, true);
        if ($tokens[$nextToken]['code'] !== T_EQUAL) {
            return false;
        }

        return true;

    }//end _argHasDefault()


}//end class

?>
<?php
/**
 * PEAR_Sniffs_Functions_FunctionDeclarationSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * PEAR_Sniffs_Functions_FunctionDeclarationSniff.
 *
 * Ensure single and multi-line function declarations are defined correctly.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Sniffs_Functions_FunctionDeclarationSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * The number of spaces code should be indented.
     *
     * @var int
     */
    public $indent = 4;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_FUNCTION,
                T_CLOSURE,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $spaces = 0;
        if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) {
            $spaces = strlen($tokens[($stackPtr + 1)]['content']);
        }

        if ($spaces !== 1) {
            $error = 'Expected 1 space after FUNCTION keyword; %s found';
            $data  = array($spaces);
            $phpcsFile->addError($error, $stackPtr, 'SpaceAfterFunction', $data);
        }

        // Must be one space before and after USE keyword for closures.
        $openBracket  = $tokens[$stackPtr]['parenthesis_opener'];
        $closeBracket = $tokens[$stackPtr]['parenthesis_closer'];
        if ($tokens[$stackPtr]['code'] === T_CLOSURE) {
            $use = $phpcsFile->findNext(T_USE, ($closeBracket + 1), $tokens[$stackPtr]['scope_opener']);
            if ($use !== false) {
                if ($tokens[($use + 1)]['code'] !== T_WHITESPACE) {
                    $length = 0;
                } else if ($tokens[($use + 1)]['content'] === "\t") {
                    $length = '\t';
                } else {
                    $length = strlen($tokens[($use + 1)]['content']);
                }

                if ($length !== 1) {
                    $error = 'Expected 1 space after USE keyword; found %s';
                    $data  = array($length);
                    $phpcsFile->addError($error, $use, 'SpaceAfterUse', $data);
                }

                if ($tokens[($use - 1)]['code'] !== T_WHITESPACE) {
                    $length = 0;
                } else if ($tokens[($use - 1)]['content'] === "\t") {
                    $length = '\t';
                } else {
                    $length = strlen($tokens[($use - 1)]['content']);
                }

                if ($length !== 1) {
                    $error = 'Expected 1 space before USE keyword; found %s';
                    $data  = array($length);
                    $phpcsFile->addError($error, $use, 'SpaceBeforeUse', $data);
                }
            }//end if
        }//end if

        // Check if this is a single line or multi-line declaration.
        $singleLine = true;
        if ($tokens[$openBracket]['line'] === $tokens[$closeBracket]['line']) {
            // Closures may use the USE keyword and so be multi-line in this way.
            if ($tokens[$stackPtr]['code'] === T_CLOSURE) {
                if ($use !== false) {
                    // If the opening and closing parenthesis of the use statement
                    // are also on the same line, this is a single line declaration.
                    $open  = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1));
                    $close = $tokens[$open]['parenthesis_closer'];
                    if ($tokens[$open]['line'] !== $tokens[$close]['line']) {
                        $singleLine = false;
                    }
                }
            }
        } else {
            $singleLine = false;
        }

        if ($singleLine === true) {
            $this->processSingleLineDeclaration($phpcsFile, $stackPtr, $tokens);
        } else {
            $this->processMultiLineDeclaration($phpcsFile, $stackPtr, $tokens);
        }

    }//end process()


    /**
     * Processes single-line declarations.
     *
     * Just uses the Generic BSD-Allman brace sniff.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     * @param array                $tokens    The stack of tokens that make up
     *                                        the file.
     *
     * @return void
     */
    public function processSingleLineDeclaration(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $tokens)
    {
        if ($tokens[$stackPtr]['code'] === T_CLOSURE) {
            if (class_exists('Generic_Sniffs_Functions_OpeningFunctionBraceKernighanRitchieSniff', true) === false) {
                throw new PHP_CodeSniffer_Exception('Class Generic_Sniffs_Functions_OpeningFunctionBraceKernighanRitchieSniff not found');
            }

            $sniff = new Generic_Sniffs_Functions_OpeningFunctionBraceKernighanRitchieSniff();
        } else {
            if (class_exists('Generic_Sniffs_Functions_OpeningFunctionBraceBsdAllmanSniff', true) === false) {
                throw new PHP_CodeSniffer_Exception('Class Generic_Sniffs_Functions_OpeningFunctionBraceBsdAllmanSniff not found');
            }

            $sniff = new Generic_Sniffs_Functions_OpeningFunctionBraceBsdAllmanSniff();
        }

        $sniff->process($phpcsFile, $stackPtr);

    }//end processSingleLineDeclaration()


    /**
     * Processes mutli-line declarations.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     * @param array                $tokens    The stack of tokens that make up
     *                                        the file.
     *
     * @return void
     */
    public function processMultiLineDeclaration(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $tokens)
    {
        // We need to work out how far indented the function
        // declaration itself is, so we can work out how far to
        // indent parameters.
        $functionIndent = 0;
        for ($i = ($stackPtr - 1); $i >= 0; $i--) {
            if ($tokens[$i]['line'] !== $tokens[$stackPtr]['line']) {
                $i++;
                break;
            }
        }

        if ($tokens[$i]['code'] === T_WHITESPACE) {
            $functionIndent = strlen($tokens[$i]['content']);
        }

        // The closing parenthesis must be on a new line, even
        // when checking abstract function definitions.
        $closeBracket = $tokens[$stackPtr]['parenthesis_closer'];
        $prev = $phpcsFile->findPrevious(
            T_WHITESPACE,
            ($closeBracket - 1),
            null,
            true
        );

        if ($tokens[$closeBracket]['line'] !== $tokens[$tokens[$closeBracket]['parenthesis_opener']]['line']) {
            if ($tokens[$prev]['line'] === $tokens[$closeBracket]['line']) {
                $error = 'The closing parenthesis of a multi-line function declaration must be on a new line';
                $phpcsFile->addError($error, $closeBracket, 'CloseBracketLine');
            }
        }

        // If this is a closure and is using a USE statement, the closing
        // parenthesis we need to look at from now on is the closing parenthesis
        // of the USE statement.
        if ($tokens[$stackPtr]['code'] === T_CLOSURE) {
            $use = $phpcsFile->findNext(T_USE, ($closeBracket + 1), $tokens[$stackPtr]['scope_opener']);
            if ($use !== false) {
                $open         = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1));
                $closeBracket = $tokens[$open]['parenthesis_closer'];

                $prev = $phpcsFile->findPrevious(
                    T_WHITESPACE,
                    ($closeBracket - 1),
                    null,
                    true
                );

                if ($tokens[$closeBracket]['line'] !== $tokens[$tokens[$closeBracket]['parenthesis_opener']]['line']) {
                    if ($tokens[$prev]['line'] === $tokens[$closeBracket]['line']) {
                        $error = 'The closing parenthesis of a multi-line use declaration must be on a new line';
                        $phpcsFile->addError($error, $closeBracket, 'CloseBracketLine');
                    }
                }
            }//end if
        }//end if

        // Each line between the parenthesis should be indented 4 spaces.
        $openBracket  = $tokens[$stackPtr]['parenthesis_opener'];
        $lastLine     = $tokens[$openBracket]['line'];
        for ($i = ($openBracket + 1); $i < $closeBracket; $i++) {
            if ($tokens[$i]['line'] !== $lastLine) {
                if ($i === $tokens[$stackPtr]['parenthesis_closer']
                    || ($tokens[$i]['code'] === T_WHITESPACE
                    && (($i + 1) === $closeBracket
                    || ($i + 1) === $tokens[$stackPtr]['parenthesis_closer']))
                ) {
                    // Closing braces need to be indented to the same level
                    // as the function.
                    $expectedIndent = $functionIndent;
                } else {
                    $expectedIndent = ($functionIndent + $this->indent);
                }

                // We changed lines, so this should be a whitespace indent token.
                if ($tokens[$i]['code'] !== T_WHITESPACE) {
                    $foundIndent = 0;
                } else {
                    $foundIndent = strlen($tokens[$i]['content']);
                }

                if ($expectedIndent !== $foundIndent) {
                    $error = 'Multi-line function declaration not indented correctly; expected %s spaces but found %s';
                    $data  = array(
                              $expectedIndent,
                              $foundIndent,
                             );
                    $phpcsFile->addError($error, $i, 'Indent', $data);
                }

                $lastLine = $tokens[$i]['line'];
            }//end if

            if ($tokens[$i]['code'] === T_ARRAY) {
                // Skip arrays as they have their own indentation rules.
                $i        = $tokens[$i]['parenthesis_closer'];
                $lastLine = $tokens[$i]['line'];
                continue;
            }
        }//end for

        if (isset($tokens[$stackPtr]['scope_opener']) === true) {
            // The openning brace needs to be one space away
            // from the closing parenthesis.
            $next = $tokens[($closeBracket + 1)];
            if ($next['code'] !== T_WHITESPACE) {
                $length = 0;
            } else if ($next['content'] === $phpcsFile->eolChar) {
                $length = -1;
            } else {
                $length = strlen($next['content']);
            }

            if ($length !== 1) {
                $data = array($length);
                $code = 'SpaceBeforeOpenBrace';

                $error = 'There must be a single space between the closing parenthesis and the opening brace of a multi-line function declaration; found ';
                if ($length === -1) {
                    $error .= 'newline';
                    $code   = 'NewlineBeforeOpenBrace';
                } else {
                    $error .= '%s spaces';
                }

                $phpcsFile->addError($error, ($closeBracket + 1), $code, $data);
                return;
            }

            // And just in case they do something funny before the brace...
            $next = $phpcsFile->findNext(
                T_WHITESPACE,
                ($closeBracket + 1),
                null,
                true
            );

            if ($next !== false && $tokens[$next]['code'] !== T_OPEN_CURLY_BRACKET) {
                $error = 'There must be a single space between the closing parenthesis and the opening brace of a multi-line function declaration';
                $phpcsFile->addError($error, $next, 'NoSpaceBeforeOpenBrace');
            }
        }//end if

    }//end processMultiLineDeclaration()


}//end class

?>
<?php
/**
 * PEAR_Sniffs_Functions_FunctionCallSignatureSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * PEAR_Sniffs_Functions_FunctionCallSignatureSniff.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Sniffs_Functions_FunctionCallSignatureSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * The number of spaces code should be indented.
     *
     * @var int
     */
    public $indent = 4;

    /**
     * If TRUE, multiple arguments can be defined per line in a multi-line call.
     *
     * @var bool
     */
    public $allowMultipleArguments = true;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_STRING);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Find the next non-empty token.
        $openBracket = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr + 1), null, true);

        if ($tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS) {
            // Not a function call.
            return;
        }

        if (isset($tokens[$openBracket]['parenthesis_closer']) === false) {
            // Not a function call.
            return;
        }

        // Find the previous non-empty token.
        $search   = PHP_CodeSniffer_Tokens::$emptyTokens;
        $search[] = T_BITWISE_AND;
        $previous = $phpcsFile->findPrevious($search, ($stackPtr - 1), null, true);
        if ($tokens[$previous]['code'] === T_FUNCTION) {
            // It's a function definition, not a function call.
            return;
        }

        $closeBracket = $tokens[$openBracket]['parenthesis_closer'];

        if (($stackPtr + 1) !== $openBracket) {
            // Checking this: $value = my_function[*](...).
            $error = 'Space before opening parenthesis of function call prohibited';
            $phpcsFile->addError($error, $stackPtr, 'SpaceBeforeOpenBracket');
        }

        $next = $phpcsFile->findNext(T_WHITESPACE, ($closeBracket + 1), null, true);
        if ($tokens[$next]['code'] === T_SEMICOLON) {
            if (in_array($tokens[($closeBracket + 1)]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === true) {
                $error = 'Space after closing parenthesis of function call prohibited';
                $phpcsFile->addError($error, $closeBracket, 'SpaceAfterCloseBracket');
            }
        }

        // Check if this is a single line or multi-line function call.
        if ($this->isMultiLineCall($phpcsFile, $stackPtr, $openBracket, $tokens) === true) {
            $this->processMultiLineCall($phpcsFile, $stackPtr, $openBracket, $tokens);
        } else {
            $this->processSingleLineCall($phpcsFile, $stackPtr, $openBracket, $tokens);
        }

    }//end process()


    /**
     * Processes single-line calls.
     *
     * @param PHP_CodeSniffer_File $phpcsFile   The file being scanned.
     * @param int                  $stackPtr    The position of the current token
     *                                          in the stack passed in $tokens.
     * @param int                  $openBracket The position of the opening bracket
     *                                          in the stack passed in $tokens.
     * @param array                $tokens      The stack of tokens that make up
     *                                          the file.
     *
     * @return void
     */
    public function isMultiLineCall(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $openBracket, $tokens)
    {
        $closeBracket = $tokens[$openBracket]['parenthesis_closer'];
        if ($tokens[$openBracket]['line'] !== $tokens[$closeBracket]['line']) {
            return true;
        }

        return false;

    }//end isMultiLineCall()


    /**
     * Processes single-line calls.
     *
     * @param PHP_CodeSniffer_File $phpcsFile   The file being scanned.
     * @param int                  $stackPtr    The position of the current token
     *                                          in the stack passed in $tokens.
     * @param int                  $openBracket The position of the opening bracket
     *                                          in the stack passed in $tokens.
     * @param array                $tokens      The stack of tokens that make up
     *                                          the file.
     *
     * @return void
     */
    public function processSingleLineCall(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $openBracket, $tokens)
    {
        if ($tokens[($openBracket + 1)]['code'] === T_WHITESPACE) {
            // Checking this: $value = my_function([*]...).
            $error = 'Space after opening parenthesis of function call prohibited';
            $phpcsFile->addError($error, $stackPtr, 'SpaceAfterOpenBracket');
        }

        $closer = $tokens[$openBracket]['parenthesis_closer'];

        if ($tokens[($closer - 1)]['code'] === T_WHITESPACE) {
            // Checking this: $value = my_function(...[*]).
            $between = $phpcsFile->findNext(T_WHITESPACE, ($openBracket + 1), null, true);

            // Only throw an error if there is some content between the parenthesis.
            // i.e., Checking for this: $value = my_function().
            // If there is no content, then we would have thrown an error in the
            // previous IF statement because it would look like this:
            // $value = my_function( ).
            if ($between !== $closer) {
                $error = 'Space before closing parenthesis of function call prohibited';
                $phpcsFile->addError($error, $closer, 'SpaceBeforeCloseBracket');
            }
        }

    }//end processSingleLineCall()


    /**
     * Processes multi-line calls.
     *
     * @param PHP_CodeSniffer_File $phpcsFile   The file being scanned.
     * @param int                  $stackPtr    The position of the current token
     *                                          in the stack passed in $tokens.
     * @param int                  $openBracket The position of the openning bracket
     *                                          in the stack passed in $tokens.
     * @param array                $tokens      The stack of tokens that make up
     *                                          the file.
     *
     * @return void
     */
    public function processMultiLineCall(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $openBracket, $tokens)
    {
        // We need to work out how far indented the function
        // call itself is, so we can work out how far to
        // indent the arguments.
        $functionIndent = 0;
        for ($i = ($stackPtr - 1); $i >= 0; $i--) {
            if ($tokens[$i]['line'] !== $tokens[$stackPtr]['line']) {
                $i++;
                break;
            }
        }

        if ($tokens[$i]['code'] === T_WHITESPACE) {
            $functionIndent = strlen($tokens[$i]['content']);
        }

        // Each line between the parenthesis should be indented n spaces.
        $closeBracket = $tokens[$openBracket]['parenthesis_closer'];
        $lastLine     = $tokens[$openBracket]['line'];
        for ($i = ($openBracket + 1); $i < $closeBracket; $i++) {
            // Skip nested function calls.
            if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS) {
                $i        = $tokens[$i]['parenthesis_closer'];
                $lastLine = $tokens[$i]['line'];
                continue;
            }

            if ($tokens[$i]['line'] !== $lastLine) {
                $lastLine = $tokens[$i]['line'];

                // Ignore heredoc indentation.
                if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$heredocTokens) === true) {
                    continue;
                }

                // Ignore multi-line string indentation.
                if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$stringTokens) === true) {
                    if ($tokens[$i]['code'] === $tokens[($i - 1)]['code']) {
                        continue;
                    }
                }

                // We changed lines, so this should be a whitespace indent token, but first make
                // sure it isn't a blank line because we don't need to check indent unless there
                // is actually some code to indent.
                if ($tokens[$i]['code'] === T_WHITESPACE) {
                    $nextCode = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), ($closeBracket + 1), true);
                    if ($tokens[$nextCode]['line'] !== $lastLine) {
                        $error = 'Empty lines are not allowed in multi-line function calls';
                        $phpcsFile->addError($error, $i, 'EmptyLine');
                        continue;
                    }
                } else {
                    $nextCode = $i;
                }

                // Check if the next line contains an object operator, if so rely on
                // the ObjectOperatorIndentSniff to test the indent.
                if ($tokens[$nextCode]['type'] === 'T_OBJECT_OPERATOR') {
                    continue;
                }

                if ($nextCode === $closeBracket) {
                    // Closing brace needs to be indented to the same level
                    // as the function call.
                    $expectedIndent = $functionIndent;
                } else {
                    $expectedIndent = ($functionIndent + $this->indent);
                }

                if ($tokens[$i]['code'] !== T_WHITESPACE) {
                    // Just check if it is a multi-line block comment. If so, we can
                    // calculate the indent from the whitespace before the content.
                    if ($tokens[$i]['code'] === T_COMMENT
                        && $tokens[($i - 1)]['code'] === T_COMMENT
                    ) {
                        $trimmed     = ltrim($tokens[$i]['content']);
                        $foundIndent = (strlen($tokens[$i]['content']) - strlen($trimmed));
                    } else {
                        $foundIndent = 0;
                    }
                } else {
                    $foundIndent = strlen($tokens[$i]['content']);
                }

                if ($expectedIndent !== $foundIndent) {
                    $error = 'Multi-line function call not indented correctly; expected %s spaces but found %s';
                    $data  = array(
                              $expectedIndent,
                              $foundIndent,
                             );
                    $phpcsFile->addError($error, $i, 'Indent', $data);
                }
            }//end if

            // Skip the rest of a closure.
            if ($tokens[$i]['code'] === T_CLOSURE) {
                $i        = $tokens[$i]['scope_closer'];
                $lastLine = $tokens[$i]['line'];
                continue;
            }

            // Skip the rest of a short array.
            if ($tokens[$i]['code'] === T_OPEN_SHORT_ARRAY) {
                $i        = $tokens[$i]['bracket_closer'];
                $lastLine = $tokens[$i]['line'];
                continue;
            }

            if ($this->allowMultipleArguments === false && $tokens[$i]['code'] === T_COMMA) {
                // Comma has to be the last token on the line.
                $next = $phpcsFile->findNext(array(T_WHITESPACE, T_COMMENT), ($i + 1), $closeBracket, true);
                if ($next !== false
                    && $tokens[$i]['line'] === $tokens[$next]['line']
                ) {
                    $error = 'Only one argument is allowed per line in a multi-line function call';
                    $phpcsFile->addError($error, $next, 'MultipleArguments');
                }
            }
        }//end for

        if ($tokens[($openBracket + 1)]['content'] !== $phpcsFile->eolChar) {
            $error = 'Opening parenthesis of a multi-line function call must be the last content on the line';
            $phpcsFile->addError($error, $stackPtr, 'ContentAfterOpenBracket');
        }

        $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBracket - 1), null, true);
        if ($tokens[$prev]['line'] === $tokens[$closeBracket]['line']) {
            $error = 'Closing parenthesis of a multi-line function call must be on a line by itself';
            $phpcsFile->addError($error, $closeBracket, 'CloseBracketLine');
        }

    }//end processMultiLineCall()


}//end class
?>
<?php
/**
 * PEAR_Sniffs_ControlStructures_MultiLineConditionSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * PEAR_Sniffs_ControlStructures_MultiLineConditionSniff.
 *
 * Ensure multi-line IF conditions are defined correctly.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Sniffs_ControlStructures_MultiLineConditionSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * The number of spaces code should be indented.
     *
     * @var int
     */
    public $indent = 4;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_IF,
                T_ELSEIF,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // We need to work out how far indented the if statement
        // itself is, so we can work out how far to indent conditions.
        $statementIndent = 0;
        for ($i = ($stackPtr - 1); $i >= 0; $i--) {
            if ($tokens[$i]['line'] !== $tokens[$stackPtr]['line']) {
                $i++;
                break;
            }
        }

        if ($i >= 0 && $tokens[$i]['code'] === T_WHITESPACE) {
            $statementIndent = strlen($tokens[$i]['content']);
        }

        // Each line between the parenthesis should be indented 4 spaces
        // and start with an operator, unless the line is inside a
        // function call, in which case it is ignored.
        $openBracket  = $tokens[$stackPtr]['parenthesis_opener'];
        $closeBracket = $tokens[$stackPtr]['parenthesis_closer'];
        $lastLine     = $tokens[$openBracket]['line'];
        for ($i = ($openBracket + 1); $i < $closeBracket; $i++) {
            if ($tokens[$i]['line'] !== $lastLine) {
                if ($tokens[$i]['line'] === $tokens[$closeBracket]['line']) {
                    $next = $phpcsFile->findNext(T_WHITESPACE, $i, null, true);
                    if ($next !== $closeBracket) {
                        // Closing bracket is on the same line as a condition.
                        $error = 'Closing parenthesis of a multi-line IF statement must be on a new line';
                        $phpcsFile->addError($error, $i, 'CloseBracketNewLine');
                        $expectedIndent = ($statementIndent + $this->indent);
                    } else {
                        // Closing brace needs to be indented to the same level
                        // as the function.
                        $expectedIndent = $statementIndent;
                    }
                } else {
                    $expectedIndent = ($statementIndent + $this->indent);
                }

                // We changed lines, so this should be a whitespace indent token.
                if ($tokens[$i]['code'] !== T_WHITESPACE) {
                    $foundIndent = 0;
                } else {
                    $foundIndent = strlen($tokens[$i]['content']);
                }

                if ($expectedIndent !== $foundIndent) {
                    $error = 'Multi-line IF statement not indented correctly; expected %s spaces but found %s';
                    $data  = array(
                              $expectedIndent,
                              $foundIndent,
                             );
                    $phpcsFile->addError($error, $i, 'Alignment', $data);
                }

                if ($tokens[$i]['line'] !== $tokens[$closeBracket]['line']) {
                    $next = $phpcsFile->findNext(T_WHITESPACE, $i, null, true);
                    if (in_array($tokens[$next]['code'], PHP_CodeSniffer_Tokens::$booleanOperators) === false) {
                        $error = 'Each line in a multi-line IF statement must begin with a boolean operator';
                        $phpcsFile->addError($error, $i, 'StartWithBoolean');
                    }
                }

                $lastLine = $tokens[$i]['line'];
            }//end if

            if ($tokens[$i]['code'] === T_STRING) {
                $next = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), null, true);
                if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS) {
                    // This is a function call, so skip to the end as they
                    // have their own indentation rules.
                    $i        = $tokens[$next]['parenthesis_closer'];
                    $lastLine = $tokens[$i]['line'];
                    continue;
                }
            }
        }//end for

        // From here on, we are checking the spacing of the opening and closing
        // braces. If this IF statement does not use braces, we end here.
        if (isset($tokens[$stackPtr]['scope_opener']) === false) {
            return;
        }

        // The opening brace needs to be one space away from the closing parenthesis.
        if ($tokens[($closeBracket + 1)]['code'] !== T_WHITESPACE) {
            $length = 0;
        } else if ($tokens[($closeBracket + 1)]['content'] === $phpcsFile->eolChar) {
            $length = -1;
        } else {
            $length = strlen($tokens[($closeBracket + 1)]['content']);
        }

        if ($length !== 1) {
            $data = array($length);
            $code = 'SpaceBeforeOpenBrace';

            $error = 'There must be a single space between the closing parenthesis and the opening brace of a multi-line IF statement; found ';
            if ($length === -1) {
                $error .= 'newline';
                $code   = 'NewlineBeforeOpenBrace';
            } else {
                $error .= '%s spaces';
            }

            $phpcsFile->addError($error, ($closeBracket + 1), $code, $data);
        }

        // And just in case they do something funny before the brace...
        $next = $phpcsFile->findNext(T_WHITESPACE, ($closeBracket + 1), null, true);
        if ($next !== false
            && $tokens[$next]['code'] !== T_OPEN_CURLY_BRACKET
            && $tokens[$next]['code'] !== T_COLON
        ) {
            $error = 'There must be a single space between the closing parenthesis and the opening brace of a multi-line IF statement';
            $phpcsFile->addError($error, $next, 'NoSpaceBeforeOpenBrace');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Verifies that control statements conform to their coding standards.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_Standards_AbstractPatternSniff', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_Standards_AbstractPatternSniff not found');
}

/**
 * Verifies that control statements conform to their coding standards.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Sniffs_ControlStructures_ControlSignatureSniff extends PHP_CodeSniffer_Standards_AbstractPatternSniff
{

    /**
     * If true, comments will be ignored if they are found in the code.
     *
     * @var boolean
     */
    public $ignoreComments = true;


    /**
     * Returns the patterns that this test wishes to verify.
     *
     * @return array(string)
     */
    protected function getPatterns()
    {
        return array(
                'do {EOL...} while (...);EOL',
                'while (...) {EOL',
                'for (...) {EOL',
                'if (...) {EOL',
                'foreach (...) {EOL',
                '} else if (...) {EOL',
                '} elseif (...) {EOL',
                '} else {EOL',
                'do {EOL',
               );

    }//end getPatterns()


}//end class

?>
<?php
/**
 * PHP_CodeSniffer_Sniffs_PEAR_Commenting_InlineCommentSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * PHP_CodeSniffer_Sniffs_PEAR_Commenting_InlineCommentSniff.
 *
 * Checks that no perl-style comments are used.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Sniffs_Commenting_InlineCommentSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_COMMENT);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        if ($tokens[$stackPtr]['content']{0} === '#') {
            $error  = 'Perl-style comments are not allowed. Use "// Comment."';
            $error .= ' or "/* comment */" instead.';
            $phpcsFile->addError($error, $stackPtr, 'WrongStyle');
        }

    }//end process()


}//end class

?>
<?php
/**
 * Parses and verifies the doc comments for functions.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_CommentParser_FunctionCommentParser', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_CommentParser_FunctionCommentParser not found');
}

/**
 * Parses and verifies the doc comments for functions.
 *
 * Verifies that :
 * <ul>
 *  <li>A comment exists</li>
 *  <li>There is a blank newline after the short description.</li>
 *  <li>There is a blank newline between the long and short description.</li>
 *  <li>There is a blank newline between the long description and tags.</li>
 *  <li>Parameter names represent those in the method.</li>
 *  <li>Parameter comments are in the correct order</li>
 *  <li>Parameter comments are complete</li>
 *  <li>A space is present before the first and after the last parameter</li>
 *  <li>A return type exists</li>
 *  <li>There must be one blank line between body and headline comments.</li>
 *  <li>Any throw tag must have an exception class.</li>
 * </ul>
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Sniffs_Commenting_FunctionCommentSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * The name of the method that we are currently processing.
     *
     * @var string
     */
    private $_methodName = '';

    /**
     * The position in the stack where the function token was found.
     *
     * @var int
     */
    private $_functionToken = null;

    /**
     * The position in the stack where the class token was found.
     *
     * @var int
     */
    private $_classToken = null;

    /**
     * The function comment parser for the current method.
     *
     * @var PHP_CodeSniffer_Comment_Parser_FunctionCommentParser
     */
    protected $commentParser = null;

    /**
     * The current PHP_CodeSniffer_File object we are processing.
     *
     * @var PHP_CodeSniffer_File
     */
    protected $currentFile = null;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_FUNCTION);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $find = array(
                 T_COMMENT,
                 T_DOC_COMMENT,
                 T_CLASS,
                 T_FUNCTION,
                 T_OPEN_TAG,
                );

        $commentEnd = $phpcsFile->findPrevious($find, ($stackPtr - 1));

        if ($commentEnd === false) {
            return;
        }

        $this->currentFile = $phpcsFile;
        $tokens            = $phpcsFile->getTokens();

        // If the token that we found was a class or a function, then this
        // function has no doc comment.
        $code = $tokens[$commentEnd]['code'];

        if ($code === T_COMMENT) {
            $error = 'You must use "/**" style comments for a function comment';
            $phpcsFile->addError($error, $stackPtr, 'WrongStyle');
            return;
        } else if ($code !== T_DOC_COMMENT) {
            $phpcsFile->addError('Missing function doc comment', $stackPtr, 'Missing');
            return;
        }

        // If there is any code between the function keyword and the doc block
        // then the doc block is not for us.
        $ignore    = PHP_CodeSniffer_Tokens::$scopeModifiers;
        $ignore[]  = T_STATIC;
        $ignore[]  = T_WHITESPACE;
        $ignore[]  = T_ABSTRACT;
        $ignore[]  = T_FINAL;
        $prevToken = $phpcsFile->findPrevious($ignore, ($stackPtr - 1), null, true);
        if ($prevToken !== $commentEnd) {
            $phpcsFile->addError('Missing function doc comment', $stackPtr, 'Missing');
            return;
        }

        $this->_functionToken = $stackPtr;

        $this->_classToken = null;
        foreach ($tokens[$stackPtr]['conditions'] as $condPtr => $condition) {
            if ($condition === T_CLASS || $condition === T_INTERFACE) {
                $this->_classToken = $condPtr;
                break;
            }
        }

        // If the first T_OPEN_TAG is right before the comment, it is probably
        // a file comment.
        $commentStart = ($phpcsFile->findPrevious(T_DOC_COMMENT, ($commentEnd - 1), null, true) + 1);
        $prevToken    = $phpcsFile->findPrevious(T_WHITESPACE, ($commentStart - 1), null, true);
        if ($tokens[$prevToken]['code'] === T_OPEN_TAG) {
            // Is this the first open tag?
            if ($stackPtr === 0 || $phpcsFile->findPrevious(T_OPEN_TAG, ($prevToken - 1)) === false) {
                $phpcsFile->addError('Missing function doc comment', $stackPtr, 'Missing');
                return;
            }
        }

        $comment           = $phpcsFile->getTokensAsString($commentStart, ($commentEnd - $commentStart + 1));
        $this->_methodName = $phpcsFile->getDeclarationName($stackPtr);

        try {
            $this->commentParser = new PHP_CodeSniffer_CommentParser_FunctionCommentParser($comment, $phpcsFile);
            $this->commentParser->parse();
        } catch (PHP_CodeSniffer_CommentParser_ParserException $e) {
            $line = ($e->getLineWithinComment() + $commentStart);
            $phpcsFile->addError($e->getMessage(), $line, 'FailedParse');
            return;
        }

        $comment = $this->commentParser->getComment();
        if (is_null($comment) === true) {
            $error = 'Function doc comment is empty';
            $phpcsFile->addError($error, $commentStart, 'Empty');
            return;
        }

        $this->processParams($commentStart);
        $this->processReturn($commentStart, $commentEnd);
        $this->processThrows($commentStart);

        // No extra newline before short description.
        $short        = $comment->getShortComment();
        $newlineCount = 0;
        $newlineSpan  = strspn($short, $phpcsFile->eolChar);
        if ($short !== '' && $newlineSpan > 0) {
            $error = 'Extra newline(s) found before function comment short description';
            $phpcsFile->addError($error, ($commentStart + 1), 'SpacingBeforeShort');
        }

        $newlineCount = (substr_count($short, $phpcsFile->eolChar) + 1);

        // Exactly one blank line between short and long description.
        $long = $comment->getLongComment();
        if (empty($long) === false) {
            $between        = $comment->getWhiteSpaceBetween();
            $newlineBetween = substr_count($between, $phpcsFile->eolChar);
            if ($newlineBetween !== 2) {
                $error = 'There must be exactly one blank line between descriptions in function comment';
                $phpcsFile->addError($error, ($commentStart + $newlineCount + 1), 'SpacingAfterShort');
            }

            $newlineCount += $newlineBetween;
        }

        // Exactly one blank line before tags.
        $params = $this->commentParser->getTagOrders();
        if (count($params) > 1) {
            $newlineSpan = $comment->getNewlineAfter();
            if ($newlineSpan !== 2) {
                $error = 'There must be exactly one blank line before the tags in function comment';
                if ($long !== '') {
                    $newlineCount += (substr_count($long, $phpcsFile->eolChar) - $newlineSpan + 1);
                }

                $phpcsFile->addError($error, ($commentStart + $newlineCount), 'SpacingBeforeTags');
                $short = rtrim($short, $phpcsFile->eolChar.' ');
            }
        }

    }//end process()


    /**
     * Process any throw tags that this function comment has.
     *
     * @param int $commentStart The position in the stack where the
     *                          comment started.
     *
     * @return void
     */
    protected function processThrows($commentStart)
    {
        if (count($this->commentParser->getThrows()) === 0) {
            return;
        }

        foreach ($this->commentParser->getThrows() as $throw) {

            $exception = $throw->getValue();
            $errorPos  = ($commentStart + $throw->getLine());

            if ($exception === '') {
                $error = '@throws tag must contain the exception class name';
                $this->currentFile->addError($error, $errorPos, 'EmptyThrows');
            }
        }

    }//end processThrows()


    /**
     * Process the return comment of this function comment.
     *
     * @param int $commentStart The position in the stack where the comment started.
     * @param int $commentEnd   The position in the stack where the comment ended.
     *
     * @return void
     */
    protected function processReturn($commentStart, $commentEnd)
    {
        // Skip constructor and destructor.
        $className = '';
        if ($this->_classToken !== null) {
            $className = $this->currentFile->getDeclarationName($this->_classToken);
            $className = strtolower(ltrim($className, '_'));
        }

        $methodName      = strtolower(ltrim($this->_methodName, '_'));
        $isSpecialMethod = ($this->_methodName === '__construct' || $this->_methodName === '__destruct');

        if ($isSpecialMethod === false && $methodName !== $className) {
            // Report missing return tag.
            if ($this->commentParser->getReturn() === null) {
                $error = 'Missing @return tag in function comment';
                $this->currentFile->addError($error, $commentEnd, 'MissingReturn');
            } else if (trim($this->commentParser->getReturn()->getRawContent()) === '') {
                $error    = '@return tag is empty in function comment';
                $errorPos = ($commentStart + $this->commentParser->getReturn()->getLine());
                $this->currentFile->addError($error, $errorPos, 'EmptyReturn');
            }
        }

    }//end processReturn()


    /**
     * Process the function parameter comments.
     *
     * @param int $commentStart The position in the stack where
     *                          the comment started.
     *
     * @return void
     */
    protected function processParams($commentStart)
    {
        $realParams = $this->currentFile->getMethodParameters($this->_functionToken);

        $params      = $this->commentParser->getParams();
        $foundParams = array();

        if (empty($params) === false) {

            $lastParm = (count($params) - 1);
            if (substr_count($params[$lastParm]->getWhitespaceAfter(), $this->currentFile->eolChar) !== 2) {
                $error    = 'Last parameter comment requires a blank newline after it';
                $errorPos = ($params[$lastParm]->getLine() + $commentStart);
                $this->currentFile->addError($error, $errorPos, 'SpacingAfterParams');
            }

            // Parameters must appear immediately after the comment.
            if ($params[0]->getOrder() !== 2) {
                $error    = 'Parameters must appear immediately after the comment';
                $errorPos = ($params[0]->getLine() + $commentStart);
                $this->currentFile->addError($error, $errorPos, 'SpacingBeforeParams');
            }

            $previousParam      = null;
            $spaceBeforeVar     = 10000;
            $spaceBeforeComment = 10000;
            $longestType        = 0;
            $longestVar         = 0;

            foreach ($params as $param) {

                $paramComment = trim($param->getComment());
                $errorPos     = ($param->getLine() + $commentStart);

                // Make sure that there is only one space before the var type.
                if ($param->getWhitespaceBeforeType() !== ' ') {
                    $error = 'Expected 1 space before variable type';
                    $this->currentFile->addError($error, $errorPos, 'SpacingBeforeParamType');
                }

                $spaceCount = substr_count($param->getWhitespaceBeforeVarName(), ' ');
                if ($spaceCount < $spaceBeforeVar) {
                    $spaceBeforeVar = $spaceCount;
                    $longestType    = $errorPos;
                }

                $spaceCount = substr_count($param->getWhitespaceBeforeComment(), ' ');

                if ($spaceCount < $spaceBeforeComment && $paramComment !== '') {
                    $spaceBeforeComment = $spaceCount;
                    $longestVar         = $errorPos;
                }

                // Make sure they are in the correct order,
                // and have the correct name.
                $pos = $param->getPosition();

                $paramName = ($param->getVarName() !== '') ? $param->getVarName() : '[ UNKNOWN ]';

                if ($previousParam !== null) {
                    $previousName = ($previousParam->getVarName() !== '') ? $previousParam->getVarName() : 'UNKNOWN';

                    // Check to see if the parameters align properly.
                    if ($param->alignsVariableWith($previousParam) === false) {
                        $error = 'The variable names for parameters %s (%s) and %s (%s) do not align';
                        $data  = array(
                                  $previousName,
                                  ($pos - 1),
                                  $paramName,
                                  $pos,
                                 );
                        $this->currentFile->addError($error, $errorPos, 'ParameterNamesNotAligned', $data);
                    }

                    if ($param->alignsCommentWith($previousParam) === false) {
                        $error = 'The comments for parameters %s (%s) and %s (%s) do not align';
                        $data  = array(
                                  $previousName,
                                  ($pos - 1),
                                  $paramName,
                                  $pos,
                                 );
                        $this->currentFile->addError($error, $errorPos, 'ParameterCommentsNotAligned', $data);
                    }
                }//end if

                // Make sure the names of the parameter comment matches the
                // actual parameter.
                if (isset($realParams[($pos - 1)]) === true) {
                    $realName      = $realParams[($pos - 1)]['name'];
                    $foundParams[] = $realName;

                    // Append ampersand to name if passing by reference.
                    if ($realParams[($pos - 1)]['pass_by_reference'] === true) {
                        $realName = '&'.$realName;
                    }

                    if ($realName !== $paramName) {
                        $code = 'ParamNameNoMatch';
                        $data = array(
                                 $paramName,
                                 $realName,
                                 $pos,
                                );

                        $error  = 'Doc comment for var %s does not match ';
                        if (strtolower($paramName) === strtolower($realName)) {
                            $error .= 'case of ';
                            $code   = 'ParamNameNoCaseMatch';
                        }

                        $error .= 'actual variable name %s at position %s';

                        $this->currentFile->addError($error, $errorPos, $code, $data);
                    }
                } else {
                    // We must have an extra parameter comment.
                    $error = 'Superfluous doc comment at position '.$pos;
                    $this->currentFile->addError($error, $errorPos, 'ExtraParamComment');
                }

                if ($param->getVarName() === '') {
                    $error = 'Missing parameter name at position '.$pos;
                     $this->currentFile->addError($error, $errorPos, 'MissingParamName');
                }

                if ($param->getType() === '') {
                    $error = 'Missing type at position '.$pos;
                    $this->currentFile->addError($error, $errorPos, 'MissingParamType');
                }

                if ($paramComment === '') {
                    $error = 'Missing comment for param "%s" at position %s';
                    $data  = array(
                              $paramName,
                              $pos,
                             );
                    $this->currentFile->addError($error, $errorPos, 'MissingParamComment', $data);
                }

                $previousParam = $param;

            }//end foreach

            if ($spaceBeforeVar !== 1 && $spaceBeforeVar !== 10000 && $spaceBeforeComment !== 10000) {
                $error = 'Expected 1 space after the longest type';
                $this->currentFile->addError($error, $longestType, 'SpacingAfterLongType');
            }

            if ($spaceBeforeComment !== 1 && $spaceBeforeComment !== 10000) {
                $error = 'Expected 1 space after the longest variable name';
                $this->currentFile->addError($error, $longestVar, 'SpacingAfterLongName');
            }

        }//end if

        $realNames = array();
        foreach ($realParams as $realParam) {
            $realNames[] = $realParam['name'];
        }

        // Report and missing comments.
        $diff = array_diff($realNames, $foundParams);
        foreach ($diff as $neededParam) {
            if (count($params) !== 0) {
                $errorPos = ($params[(count($params) - 1)]->getLine() + $commentStart);
            } else {
                $errorPos = $commentStart;
            }

            $error = 'Doc comment for "%s" missing';
            $data  = array($neededParam);
            $this->currentFile->addError($error, $errorPos, 'MissingParamTag', $data);
        }

    }//end processParams()


}//end class

?>
<?php
/**
 * Parses and verifies the doc comments for classes.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_CommentParser_ClassCommentParser', true) === false) {
    $error = 'Class PHP_CodeSniffer_CommentParser_ClassCommentParser not found';
    throw new PHP_CodeSniffer_Exception($error);
}

if (class_exists('PEAR_Sniffs_Commenting_FileCommentSniff', true) === false) {
    $error = 'Class PEAR_Sniffs_Commenting_FileCommentSniff not found';
    throw new PHP_CodeSniffer_Exception($error);
}

/**
 * Parses and verifies the doc comments for classes.
 *
 * Verifies that :
 * <ul>
 *  <li>A doc comment exists.</li>
 *  <li>There is a blank newline after the short description.</li>
 *  <li>There is a blank newline between the long and short description.</li>
 *  <li>There is a blank newline between the long description and tags.</li>
 *  <li>Check the order of the tags.</li>
 *  <li>Check the indentation of each tag.</li>
 *  <li>Check required and optional tags and the format of their content.</li>
 * </ul>
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Sniffs_Commenting_ClassCommentSniff extends PEAR_Sniffs_Commenting_FileCommentSniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_CLASS,
                T_INTERFACE,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $this->currentFile = $phpcsFile;

        $tokens    = $phpcsFile->getTokens();
        $type      = strtolower($tokens[$stackPtr]['content']);
        $errorData = array($type);
        $find      = array(
                      T_ABSTRACT,
                      T_WHITESPACE,
                      T_FINAL,
                     );

        // Extract the class comment docblock.
        $commentEnd = $phpcsFile->findPrevious($find, ($stackPtr - 1), null, true);

        if ($commentEnd !== false && $tokens[$commentEnd]['code'] === T_COMMENT) {
            $error = 'You must use "/**" style comments for a %s comment';
            $phpcsFile->addError($error, $stackPtr, 'WrongStyle', $errorData);
            return;
        } else if ($commentEnd === false
            || $tokens[$commentEnd]['code'] !== T_DOC_COMMENT
        ) {
            $phpcsFile->addError('Missing %s doc comment', $stackPtr, 'Missing', $errorData);
            return;
        }

        $commentStart = ($phpcsFile->findPrevious(T_DOC_COMMENT, ($commentEnd - 1), null, true) + 1);
        $commentNext  = $phpcsFile->findPrevious(T_WHITESPACE, ($commentEnd + 1), $stackPtr, false, $phpcsFile->eolChar);

        // Distinguish file and class comment.
        $prevClassToken = $phpcsFile->findPrevious(T_CLASS, ($stackPtr - 1));
        if ($prevClassToken === false) {
            // This is the first class token in this file, need extra checks.
            $prevNonComment = $phpcsFile->findPrevious(T_DOC_COMMENT, ($commentStart - 1), null, true);
            if ($prevNonComment !== false) {
                $prevComment = $phpcsFile->findPrevious(T_DOC_COMMENT, ($prevNonComment - 1));
                if ($prevComment === false) {
                    // There is only 1 doc comment between open tag and class token.
                    $newlineToken = $phpcsFile->findNext(T_WHITESPACE, ($commentEnd + 1), $stackPtr, false, $phpcsFile->eolChar);
                    if ($newlineToken !== false) {
                        $newlineToken = $phpcsFile->findNext(
                            T_WHITESPACE,
                            ($newlineToken + 1),
                            $stackPtr,
                            false,
                            $phpcsFile->eolChar
                        );

                        if ($newlineToken !== false) {
                            // Blank line between the class and the doc block.
                            // The doc block is most likely a file comment.
                            $error = 'Missing %s doc comment';
                            $phpcsFile->addError($error, ($stackPtr + 1), 'Missing', $errorData);
                            return;
                        }
                    }//end if
                }//end if
            }//end if
        }//end if

        $comment = $phpcsFile->getTokensAsString(
            $commentStart,
            ($commentEnd - $commentStart + 1)
        );

        // Parse the class comment.docblock.
        try {
            $this->commentParser = new PHP_CodeSniffer_CommentParser_ClassCommentParser($comment, $phpcsFile);
            $this->commentParser->parse();
        } catch (PHP_CodeSniffer_CommentParser_ParserException $e) {
            $line = ($e->getLineWithinComment() + $commentStart);
            $phpcsFile->addError($e->getMessage(), $line, 'FailedParse');
            return;
        }

        $comment = $this->commentParser->getComment();
        if (is_null($comment) === true) {
            $error = 'Doc comment is empty for %s';
            $phpcsFile->addError($error, $commentStart, 'Empty', $errorData);
            return;
        }

        // No extra newline before short description.
        $short        = $comment->getShortComment();
        $newlineCount = 0;
        $newlineSpan  = strspn($short, $phpcsFile->eolChar);
        if ($short !== '' && $newlineSpan > 0) {
            $error = 'Extra newline(s) found before %s comment short description';
            $phpcsFile->addError($error, ($commentStart + 1), 'SpacingBeforeShort', $errorData);
        }

        $newlineCount = (substr_count($short, $phpcsFile->eolChar) + 1);

        // Exactly one blank line between short and long description.
        $long = $comment->getLongComment();
        if (empty($long) === false) {
            $between        = $comment->getWhiteSpaceBetween();
            $newlineBetween = substr_count($between, $phpcsFile->eolChar);
            if ($newlineBetween !== 2) {
                $error = 'There must be exactly one blank line between descriptions in %s comments';
                $phpcsFile->addError($error, ($commentStart + $newlineCount + 1), 'SpacingAfterShort', $errorData);
            }

            $newlineCount += $newlineBetween;
        }

        // Exactly one blank line before tags.
        $tags = $this->commentParser->getTagOrders();
        if (count($tags) > 1) {
            $newlineSpan = $comment->getNewlineAfter();
            if ($newlineSpan !== 2) {
                $error = 'There must be exactly one blank line before the tags in %s comments';
                if ($long !== '') {
                    $newlineCount += (substr_count($long, $phpcsFile->eolChar) - $newlineSpan + 1);
                }

                $phpcsFile->addError($error, ($commentStart + $newlineCount), 'SpacingBeforeTags', $errorData);
                $short = rtrim($short, $phpcsFile->eolChar.' ');
            }
        }

        // Check each tag.
        $this->processTags($commentStart, $commentEnd);

    }//end process()


    /**
     * Process the version tag.
     *
     * @param int $errorPos The line number where the error occurs.
     *
     * @return void
     */
    protected function processVersion($errorPos)
    {
        $version = $this->commentParser->getVersion();
        if ($version !== null) {
            $content = $version->getContent();
            $matches = array();
            if (empty($content) === true) {
                $error = 'Content missing for @version tag in doc comment';
                $this->currentFile->addError($error, $errorPos, 'EmptyVersion');
            } else if ((strstr($content, 'Release:') === false)) {
                $error = 'Invalid version "%s" in doc comment; consider "Release: <package_version>" instead';
                $data  = array($content);
                $this->currentFile->addWarning($error, $errorPos, 'InvalidVersion', $data);
            }
        }

    }//end processVersion()


}//end class

?>
<?php
/**
 * Parses and verifies the doc comments for files.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_CommentParser_ClassCommentParser', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_CommentParser_ClassCommentParser not found');
}

/**
 * Parses and verifies the doc comments for files.
 *
 * Verifies that :
 * <ul>
 *  <li>A doc comment exists.</li>
 *  <li>There is a blank newline after the short description.</li>
 *  <li>There is a blank newline between the long and short description.</li>
 *  <li>There is a blank newline between the long description and tags.</li>
 *  <li>A PHP version is specified.</li>
 *  <li>Check the order of the tags.</li>
 *  <li>Check the indentation of each tag.</li>
 *  <li>Check required and optional tags and the format of their content.</li>
 * </ul>
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

class PEAR_Sniffs_Commenting_FileCommentSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * The header comment parser for the current file.
     *
     * @var PHP_CodeSniffer_Comment_Parser_ClassCommentParser
     */
    protected $commentParser = null;

    /**
     * The current PHP_CodeSniffer_File object we are processing.
     *
     * @var PHP_CodeSniffer_File
     */
    protected $currentFile = null;

    /**
     * Tags in correct order and related info.
     *
     * @var array
     */
    protected $tags = array(
                       'category'   => array(
                                        'required'       => true,
                                        'allow_multiple' => false,
                                        'order_text'     => 'precedes @package',
                                       ),
                       'package'    => array(
                                        'required'       => true,
                                        'allow_multiple' => false,
                                        'order_text'     => 'follows @category',
                                       ),
                       'subpackage' => array(
                                        'required'       => false,
                                        'allow_multiple' => false,
                                        'order_text'     => 'follows @package',
                                       ),
                       'author'     => array(
                                        'required'       => true,
                                        'allow_multiple' => true,
                                        'order_text'     => 'follows @subpackage (if used) or @package',
                                       ),
                       'copyright'  => array(
                                        'required'       => false,
                                        'allow_multiple' => true,
                                        'order_text'     => 'follows @author',
                                       ),
                       'license'    => array(
                                        'required'       => true,
                                        'allow_multiple' => false,
                                        'order_text'     => 'follows @copyright (if used) or @author',
                                       ),
                       'version'    => array(
                                        'required'       => false,
                                        'allow_multiple' => false,
                                        'order_text'     => 'follows @license',
                                       ),
                       'link'       => array(
                                        'required'       => true,
                                        'allow_multiple' => true,
                                        'order_text'     => 'follows @version',
                                       ),
                       'see'        => array(
                                        'required'       => false,
                                        'allow_multiple' => true,
                                        'order_text'     => 'follows @link',
                                       ),
                       'since'      => array(
                                        'required'       => false,
                                        'allow_multiple' => false,
                                        'order_text'     => 'follows @see (if used) or @link',
                                       ),
                       'deprecated' => array(
                                        'required'       => false,
                                        'allow_multiple' => false,
                                        'order_text'     => 'follows @since (if used) or @see (if used) or @link',
                                       ),
                      );


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_OPEN_TAG);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $this->currentFile = $phpcsFile;

        // We are only interested if this is the first open tag.
        if ($stackPtr !== 0) {
            if ($phpcsFile->findPrevious(T_OPEN_TAG, ($stackPtr - 1)) !== false) {
                return;
            }
        }

        $tokens = $phpcsFile->getTokens();

        // Find the next non whitespace token.
        $commentStart
            = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);

        // Allow declare() statements at the top of the file.
        if ($tokens[$commentStart]['code'] === T_DECLARE) {
            $semicolon = $phpcsFile->findNext(T_SEMICOLON, ($commentStart + 1));
            $commentStart
                = $phpcsFile->findNext(T_WHITESPACE, ($semicolon + 1), null, true);
        }

        // Ignore vim header.
        if ($tokens[$commentStart]['code'] === T_COMMENT) {
            if (strstr($tokens[$commentStart]['content'], 'vim:') !== false) {
                $commentStart = $phpcsFile->findNext(
                    T_WHITESPACE,
                    ($commentStart + 1),
                    null,
                    true
                );
            }
        }

        $errorToken = ($stackPtr + 1);
        if (isset($tokens[$errorToken]) === false) {
            $errorToken--;
        }

        if ($tokens[$commentStart]['code'] === T_CLOSE_TAG) {
            // We are only interested if this is the first open tag.
            return;
        } else if ($tokens[$commentStart]['code'] === T_COMMENT) {
            $error = 'You must use "/**" style comments for a file comment';
            $phpcsFile->addError($error, $errorToken, 'WrongStyle');
            return;
        } else if ($commentStart === false
            || $tokens[$commentStart]['code'] !== T_DOC_COMMENT
        ) {
            $phpcsFile->addError('Missing file doc comment', $errorToken, 'Missing');
            return;
        } else {

            // Extract the header comment docblock.
            $commentEnd = $phpcsFile->findNext(
                T_DOC_COMMENT,
                ($commentStart + 1),
                null,
                true
            );

            $commentEnd--;

            // Check if there is only 1 doc comment between the
            // open tag and class token.
            $nextToken   = array(
                            T_ABSTRACT,
                            T_CLASS,
                            T_FUNCTION,
                            T_DOC_COMMENT,
                           );

            $commentNext = $phpcsFile->findNext($nextToken, ($commentEnd + 1));
            if ($commentNext !== false
                && $tokens[$commentNext]['code'] !== T_DOC_COMMENT
            ) {
                // Found a class token right after comment doc block.
                $newlineToken = $phpcsFile->findNext(
                    T_WHITESPACE,
                    ($commentEnd + 1),
                    $commentNext,
                    false,
                    $phpcsFile->eolChar
                );

                if ($newlineToken !== false) {
                    $newlineToken = $phpcsFile->findNext(
                        T_WHITESPACE,
                        ($newlineToken + 1),
                        $commentNext,
                        false,
                        $phpcsFile->eolChar
                    );

                    if ($newlineToken === false) {
                        // No blank line between the class token and the doc block.
                        // The doc block is most likely a class comment.
                        $error = 'Missing file doc comment';
                        $phpcsFile->addError($error, $errorToken, 'Missing');
                        return;
                    }
                }
            }//end if

            $comment = $phpcsFile->getTokensAsString(
                $commentStart,
                ($commentEnd - $commentStart + 1)
            );

            // Parse the header comment docblock.
            try {
                $this->commentParser = new PHP_CodeSniffer_CommentParser_ClassCommentParser($comment, $phpcsFile);
                $this->commentParser->parse();
            } catch (PHP_CodeSniffer_CommentParser_ParserException $e) {
                $line = ($e->getLineWithinComment() + $commentStart);
                $phpcsFile->addError($e->getMessage(), $line, 'FailedParse');
                return;
            }

            $comment = $this->commentParser->getComment();
            if (is_null($comment) === true) {
                $error = 'File doc comment is empty';
                $phpcsFile->addError($error, $commentStart, 'Empty');
                return;
            }

            // No extra newline before short description.
            $short        = $comment->getShortComment();
            $newlineCount = 0;
            $newlineSpan  = strspn($short, $phpcsFile->eolChar);
            if ($short !== '' && $newlineSpan > 0) {
                $error = 'Extra newline(s) found before file comment short description';
                $phpcsFile->addError($error, ($commentStart + 1), 'SpacingBefore');
            }

            $newlineCount = (substr_count($short, $phpcsFile->eolChar) + 1);

            // Exactly one blank line between short and long description.
            $long = $comment->getLongComment();
            if (empty($long) === false) {
                $between        = $comment->getWhiteSpaceBetween();
                $newlineBetween = substr_count($between, $phpcsFile->eolChar);
                if ($newlineBetween !== 2) {
                    $error = 'There must be exactly one blank line between descriptions in file comment';
                    $phpcsFile->addError($error, ($commentStart + $newlineCount + 1), 'DescriptionSpacing');
                }

                $newlineCount += $newlineBetween;
            }

            // Exactly one blank line before tags.
            $tags = $this->commentParser->getTagOrders();
            if (count($tags) > 1) {
                $newlineSpan = $comment->getNewlineAfter();
                if ($newlineSpan !== 2) {
                    $error = 'There must be exactly one blank line before the tags in file comment';
                    if ($long !== '') {
                        $newlineCount += (substr_count($long, $phpcsFile->eolChar) - $newlineSpan + 1);
                    }

                    $phpcsFile->addError($error, ($commentStart + $newlineCount), 'SpacingBeforeTags');
                    $short = rtrim($short, $phpcsFile->eolChar.' ');
                }
            }

            // Check the PHP Version.
            $this->processPHPVersion($commentStart, $commentEnd, $long);

            // Check each tag.
            $this->processTags($commentStart, $commentEnd);
        }//end if

    }//end process()


    /**
     * Check that the PHP version is specified.
     *
     * @param int    $commentStart Position in the stack where the comment started.
     * @param int    $commentEnd   Position in the stack where the comment ended.
     * @param string $commentText  The text of the function comment.
     *
     * @return void
     */
    protected function processPHPVersion($commentStart, $commentEnd, $commentText)
    {
        if (strstr(strtolower($commentText), 'php version') === false) {
            $error = 'PHP version not specified';
             $this->currentFile->addWarning($error, $commentEnd, 'MissingVersion');
        }

    }//end processPHPVersion()


    /**
     * Processes each required or optional tag.
     *
     * @param int $commentStart Position in the stack where the comment started.
     * @param int $commentEnd   Position in the stack where the comment ended.
     *
     * @return void
     */
    protected function processTags($commentStart, $commentEnd)
    {
        $docBlock    = (get_class($this) === 'PEAR_Sniffs_Commenting_FileCommentSniff') ? 'file' : 'class';
        $foundTags   = $this->commentParser->getTagOrders();
        $orderIndex  = 0;
        $indentation = array();
        $longestTag  = 0;
        $errorPos    = 0;

        foreach ($this->tags as $tag => $info) {

            // Required tag missing.
            if ($info['required'] === true && in_array($tag, $foundTags) === false) {
                $error = 'Missing @%s tag in %s comment';
                $data  = array(
                          $tag,
                          $docBlock,
                         );
                $this->currentFile->addError($error, $commentEnd, 'MissingTag', $data);
                continue;
            }

             // Get the line number for current tag.
            $tagName = ucfirst($tag);
            if ($info['allow_multiple'] === true) {
                $tagName .= 's';
            }

            $getMethod  = 'get'.$tagName;
            $tagElement = $this->commentParser->$getMethod();
            if (is_null($tagElement) === true || empty($tagElement) === true) {
                continue;
            }

            $errorPos = $commentStart;
            if (is_array($tagElement) === false) {
                $errorPos = ($commentStart + $tagElement->getLine());
            }

            // Get the tag order.
            $foundIndexes = array_keys($foundTags, $tag);

            if (count($foundIndexes) > 1) {
                // Multiple occurrence not allowed.
                if ($info['allow_multiple'] === false) {
                    $error = 'Only 1 @%s tag is allowed in a %s comment';
                    $data  = array(
                              $tag,
                              $docBlock,
                             );
                    $this->currentFile->addError($error, $errorPos, 'DuplicateTag', $data);
                } else {
                    // Make sure same tags are grouped together.
                    $i     = 0;
                    $count = $foundIndexes[0];
                    foreach ($foundIndexes as $index) {
                        if ($index !== $count) {
                            $errorPosIndex
                                = ($errorPos + $tagElement[$i]->getLine());
                            $error = '@%s tags must be grouped together';
                            $data  = array($tag);
                            $this->currentFile->addError($error, $errorPosIndex, 'TagsNotGrouped', $data);
                        }

                        $i++;
                        $count++;
                    }
                }
            }//end if

            // Check tag order.
            if ($foundIndexes[0] > $orderIndex) {
                $orderIndex = $foundIndexes[0];
            } else {
                if (is_array($tagElement) === true && empty($tagElement) === false) {
                    $errorPos += $tagElement[0]->getLine();
                }

                $error = 'The @%s tag is in the wrong order; the tag %s';
                $data  = array(
                          $tag,
                          $info['order_text'],
                         );
                $this->currentFile->addError($error, $errorPos, 'WrongTagOrder', $data);
            }

            // Store the indentation for checking.
            $len = strlen($tag);
            if ($len > $longestTag) {
                $longestTag = $len;
            }

            if (is_array($tagElement) === true) {
                foreach ($tagElement as $key => $element) {
                    $indentation[] = array(
                                      'tag'   => $tag,
                                      'space' => $this->getIndentation($tag, $element),
                                      'line'  => $element->getLine(),
                                     );
                }
            } else {
                $indentation[] = array(
                                  'tag'   => $tag,
                                  'space' => $this->getIndentation($tag, $tagElement),
                                 );
            }

            $method = 'process'.$tagName;
            if (method_exists($this, $method) === true) {
                // Process each tag if a method is defined.
                call_user_func(array($this, $method), $errorPos);
            } else {
                if (is_array($tagElement) === true) {
                    foreach ($tagElement as $key => $element) {
                        $element->process(
                            $this->currentFile,
                            $commentStart,
                            $docBlock
                        );
                    }
                } else {
                     $tagElement->process(
                         $this->currentFile,
                         $commentStart,
                         $docBlock
                     );
                }
            }
        }//end foreach

        foreach ($indentation as $indentInfo) {
            if ($indentInfo['space'] !== 0
                && $indentInfo['space'] !== ($longestTag + 1)
            ) {
                $expected = (($longestTag - strlen($indentInfo['tag'])) + 1);
                $space    = ($indentInfo['space'] - strlen($indentInfo['tag']));
                $error    = '@%s tag comment indented incorrectly; expected %s spaces but found %s';
                $data     = array(
                             $indentInfo['tag'],
                             $expected,
                             $space,
                            );

                $getTagMethod = 'get'.ucfirst($indentInfo['tag']);

                if ($this->tags[$indentInfo['tag']]['allow_multiple'] === true) {
                    $line = $indentInfo['line'];
                } else {
                    $tagElem = $this->commentParser->$getTagMethod();
                    $line    = $tagElem->getLine();
                }

                $this->currentFile->addError($error, ($commentStart + $line), 'TagIndent', $data);
            }
        }

    }//end processTags()


    /**
     * Get the indentation information of each tag.
     *
     * @param string                                   $tagName    The name of the
     *                                                             doc comment
     *                                                             element.
     * @param PHP_CodeSniffer_CommentParser_DocElement $tagElement The doc comment
     *                                                             element.
     *
     * @return void
     */
    protected function getIndentation($tagName, $tagElement)
    {
        if ($tagElement instanceof PHP_CodeSniffer_CommentParser_SingleElement) {
            if ($tagElement->getContent() !== '') {
                return (strlen($tagName) + substr_count($tagElement->getWhitespaceBeforeContent(), ' '));
            }
        } else if ($tagElement instanceof PHP_CodeSniffer_CommentParser_PairElement) {
            if ($tagElement->getValue() !== '') {
                return (strlen($tagName) + substr_count($tagElement->getWhitespaceBeforeValue(), ' '));
            }
        }

        return 0;

    }//end getIndentation()


    /**
     * Process the category tag.
     *
     * @param int $errorPos The line number where the error occurs.
     *
     * @return void
     */
    protected function processCategory($errorPos)
    {
        $category = $this->commentParser->getCategory();
        if ($category !== null) {
            $content = $category->getContent();
            if ($content !== '') {
                if (PHP_CodeSniffer::isUnderscoreName($content) !== true) {
                    $newContent = str_replace(' ', '_', $content);
                    $nameBits   = explode('_', $newContent);
                    $firstBit   = array_shift($nameBits);
                    $newName    = ucfirst($firstBit).'_';
                    foreach ($nameBits as $bit) {
                        $newName .= ucfirst($bit).'_';
                    }

                    $error     = 'Category name "%s" is not valid; consider "%s" instead';
                    $validName = trim($newName, '_');
                    $data      = array(
                                  $content,
                                  $validName,
                                 );
                    $this->currentFile->addError($error, $errorPos, 'InvalidCategory', $data);
                }
            } else {
                $error = '@category tag must contain a name';
                $this->currentFile->addError($error, $errorPos, 'EmptyCategory');
            }
        }

    }//end processCategory()


    /**
     * Process the package tag.
     *
     * @param int $errorPos The line number where the error occurs.
     *
     * @return void
     */
    protected function processPackage($errorPos)
    {
        $package = $this->commentParser->getPackage();
        if ($package === null) {
            return;
        }

        $content = $package->getContent();
        if ($content === '') {
            $error = '@package tag must contain a name';
            $this->currentFile->addError($error, $errorPos, 'EmptyPackage');
            return;
        }

        if (PHP_CodeSniffer::isUnderscoreName($content) === true) {
            return;
        }

        $newContent = str_replace(' ', '_', $content);
        $newContent = preg_replace('/[^A-Za-z_]/', '', $newContent);
        $nameBits   = explode('_', $newContent);
        $firstBit   = array_shift($nameBits);
        $newName    = strtoupper($firstBit{0}).substr($firstBit, 1).'_';
        foreach ($nameBits as $bit) {
            $newName .= strtoupper($bit{0}).substr($bit, 1).'_';
        }

        $error     = 'Package name "%s" is not valid; consider "%s" instead';
        $validName = trim($newName, '_');
        $data      = array(
                      $content,
                      $validName,
                     );
        $this->currentFile->addError($error, $errorPos, 'InvalidPackage', $data);

    }//end processPackage()


    /**
     * Process the subpackage tag.
     *
     * @param int $errorPos The line number where the error occurs.
     *
     * @return void
     */
    protected function processSubpackage($errorPos)
    {
        $package = $this->commentParser->getSubpackage();
        if ($package !== null) {
            $content = $package->getContent();
            if ($content !== '') {
                if (PHP_CodeSniffer::isUnderscoreName($content) !== true) {
                    $newContent = str_replace(' ', '_', $content);
                    $nameBits   = explode('_', $newContent);
                    $firstBit   = array_shift($nameBits);
                    $newName    = strtoupper($firstBit{0}).substr($firstBit, 1).'_';
                    foreach ($nameBits as $bit) {
                        $newName .= strtoupper($bit{0}).substr($bit, 1).'_';
                    }

                    $error     = 'Subpackage name "%s" is not valid; consider "%s" instead';
                    $validName = trim($newName, '_');
                    $data      = array(
                                  $content,
                                  $validName,
                                 );
                    $this->currentFile->addError($error, $errorPos, 'InvalidSubpackage', $data);
                }
            } else {
                $error = '@subpackage tag must contain a name';
                $this->currentFile->addError($error, $errorPos, 'EmptySubpackage');
            }
        }

    }//end processSubpackage()


    /**
     * Process the author tag(s) that this header comment has.
     *
     * This function is different from other _process functions
     * as $authors is an array of SingleElements, so we work out
     * the errorPos for each element separately
     *
     * @param int $commentStart The position in the stack where
     *                          the comment started.
     *
     * @return void
     */
    protected function processAuthors($commentStart)
    {
         $authors = $this->commentParser->getAuthors();
        // Report missing return.
        if (empty($authors) === false) {
            foreach ($authors as $author) {
                $errorPos = ($commentStart + $author->getLine());
                $content  = $author->getContent();
                if ($content !== '') {
                    $local = '\da-zA-Z-_+';
                    // Dot character cannot be the first or last character
                    // in the local-part.
                    $localMiddle = $local.'.\w';
                    if (preg_match('/^([^<]*)\s+<(['.$local.'](['.$localMiddle.']*['.$local.'])*@[\da-zA-Z][-.\w]*[\da-zA-Z]\.[a-zA-Z]{2,7})>$/', $content) === 0) {
                        $error = 'Content of the @author tag must be in the form "Display Name <username@example.com>"';
                        $this->currentFile->addError($error, $errorPos, 'InvalidAuthors');
                    }
                } else {
                    $error    = 'Content missing for @author tag in %s comment';
                    $docBlock = (get_class($this) === 'PEAR_Sniffs_Commenting_FileCommentSniff') ? 'file' : 'class';
                    $data     = array($docBlock);
                    $this->currentFile->addError($error, $errorPos, 'EmptyAuthors', $data);
                }
            }
        }

    }//end processAuthors()


    /**
     * Process the copyright tags.
     *
     * @param int $commentStart The position in the stack where
     *                          the comment started.
     *
     * @return void
     */
    protected function processCopyrights($commentStart)
    {
        $copyrights = $this->commentParser->getCopyrights();
        foreach ($copyrights as $copyright) {
            $errorPos = ($commentStart + $copyright->getLine());
            $content  = $copyright->getContent();
            if ($content !== '') {
                $matches = array();
                if (preg_match('/^([0-9]{4})((.{1})([0-9]{4}))? (.+)$/', $content, $matches) !== 0) {
                    // Check earliest-latest year order.
                    if ($matches[3] !== '') {
                        if ($matches[3] !== '-') {
                            $error = 'A hyphen must be used between the earliest and latest year';
                            $this->currentFile->addError($error, $errorPos, 'CopyrightHyphen');
                        }

                        if ($matches[4] !== '' && $matches[4] < $matches[1]) {
                            $error = "Invalid year span \"$matches[1]$matches[3]$matches[4]\" found; consider \"$matches[4]-$matches[1]\" instead";
                            $this->currentFile->addWarning($error, $errorPos, 'InvalidCopyright');
                        }
                    }
                } else {
                    $error = '@copyright tag must contain a year and the name of the copyright holder';
                    $this->currentFile->addError($error, $errorPos, 'EmptyCopyright');
                }
            } else {
                $error = '@copyright tag must contain a year and the name of the copyright holder';
                $this->currentFile->addError($error, $errorPos, 'EmptyCopyright');
            }//end if
        }//end if

    }//end processCopyrights()


    /**
     * Process the license tag.
     *
     * @param int $errorPos The line number where the error occurs.
     *
     * @return void
     */
    protected function processLicense($errorPos)
    {
        $license = $this->commentParser->getLicense();
        if ($license !== null) {
            $value   = $license->getValue();
            $comment = $license->getComment();
            if ($value === '' || $comment === '') {
                $error = '@license tag must contain a URL and a license name';
                $this->currentFile->addError($error, $errorPos, 'EmptyLicense');
            }
        }

    }//end processLicense()


    /**
     * Process the version tag.
     *
     * @param int $errorPos The line number where the error occurs.
     *
     * @return void
     */
    protected function processVersion($errorPos)
    {
        $version = $this->commentParser->getVersion();
        if ($version !== null) {
            $content = $version->getContent();
            $matches = array();
            if (empty($content) === true) {
                $error = 'Content missing for @version tag in file comment';
                $this->currentFile->addError($error, $errorPos, 'EmptyVersion');
            } else if (strstr($content, 'CVS:') === false
                && strstr($content, 'SVN:') === false
                && strstr($content, 'GIT:') === false
                && strstr($content, 'HG:') === false
            ) {
                $error = 'Invalid version "%s" in file comment; consider "CVS: <cvs_id>" or "SVN: <svn_id>" or "GIT: <git_id>" or "HG: <hg_id>" instead';
                $data  = array($content);
                $this->currentFile->addWarning($error, $errorPos, 'InvalidVersion', $data);
            }
        }

    }//end processVersion()


}//end class

?>
<?php
/**
 * PEAR_Sniffs_Files_IncludingFileSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * PEAR_Sniffs_Files_IncludingFileSniff.
 *
 * Checks that the include_once is used in conditional situations, and
 * require_once is used elsewhere. Also checks that brackets do not surround
 * the file being included.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Sniffs_Files_IncludingFileSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * Conditions that should use include_once
     *
     * @var array(int)
     */
    private static $_conditions = array(
                                   T_IF,
                                   T_ELSE,
                                   T_ELSEIF,
                                   T_SWITCH,
                                  );


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_INCLUDE_ONCE,
                T_REQUIRE_ONCE,
                T_REQUIRE,
                T_INCLUDE,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $nextToken = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr + 1), null, true);
        if ($tokens[$nextToken]['code'] === T_OPEN_PARENTHESIS) {
            $error = '"%s" is a statement not a function; no parentheses are required';
            $data  = array($tokens[$stackPtr]['content']);
            $phpcsFile->addError($error, $stackPtr, 'BracketsNotRequired', $data);
        }

        $inCondition = (count($tokens[$stackPtr]['conditions']) !== 0) ? true : false;

        // Check to see if this including statement is within the parenthesis
        // of a condition. If that's the case then we need to process it as being
        // within a condition, as they are checking the return value.
        if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) {
            foreach ($tokens[$stackPtr]['nested_parenthesis'] as $left => $right) {
                if (isset($tokens[$left]['parenthesis_owner']) === true) {
                    $inCondition = true;
                }
            }
        }

        // Check to see if they are assigning the return value of this
        // including call. If they are then they are probably checking it, so
        // it's conditional.
        $previous = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr - 1), null, true);
        if (in_array($tokens[$previous]['code'], PHP_CodeSniffer_Tokens::$assignmentTokens) === true) {
            // The have assigned the return value to it, so its conditional.
            $inCondition = true;
        }

        $tokenCode = $tokens[$stackPtr]['code'];
        if ($inCondition === true) {
            // We are inside a conditional statement. We need an include_once.
            if ($tokenCode === T_REQUIRE_ONCE) {
                $error  = 'File is being conditionally included; ';
                $error .= 'use "include_once" instead';
                $phpcsFile->addError($error, $stackPtr, 'UseIncludeOnce');
            } else if ($tokenCode === T_REQUIRE) {
                $error  = 'File is being conditionally included; ';
                $error .= 'use "include" instead';
                $phpcsFile->addError($error, $stackPtr, 'UseInclude');
            }
        } else {
            // We are unconditionally including, we need a require_once.
            if ($tokenCode === T_INCLUDE_ONCE) {
                $error  = 'File is being unconditionally included; ';
                $error .= 'use "require_once" instead';
                $phpcsFile->addError($error, $stackPtr, 'UseRequireOnce');
            } else if ($tokenCode === T_INCLUDE) {
                $error  = 'File is being unconditionally included; ';
                $error .= 'use "require" instead';
                $phpcsFile->addError($error, $stackPtr, 'UseRequire');
            }
        }//end if

    }//end process()


}//end class

?>
<?php
/**
 * PEAR_Sniffs_Functions_FunctionDeclarationSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * PEAR_Sniffs_Formatting_MultiLineAssignmentSniff.
 *
 * If an assignment goes over two lines, ensure the equal sign is indented.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Sniffs_Formatting_MultiLineAssignmentSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * The number of spaces code should be indented.
     *
     * @var int
     */
    public $indent = 4;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_EQUAL);

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // Equal sign can't be the last thing on the line.
        $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
        if ($next === false) {
            // Bad assignment.
            return;
        }

        if ($tokens[$next]['line'] !== $tokens[$stackPtr]['line']) {
            $error = 'Multi-line assignments must have the equal sign on the second line';
            $phpcsFile->addError($error, $stackPtr, 'EqualSignLine');
            return;
        }

        // Make sure it is the first thing on the line, otherwise we ignore it.
        $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), false, true);
        if ($prev === false) {
            // Bad assignment.
            return;
        }

        if ($tokens[$prev]['line'] === $tokens[$stackPtr]['line']) {
            return;
        }

        // Find the required indent based on the ident of the previous line.
        $assignmentIndent = 0;
        $prevLine         = $tokens[$prev]['line'];
        for ($i = ($prev - 1); $i >= 0; $i--) {
            if ($tokens[$i]['line'] !== $prevLine) {
                $i++;
                break;
            }
        }

        if ($tokens[$i]['code'] === T_WHITESPACE) {
            $assignmentIndent = strlen($tokens[$i]['content']);
        }

        // Find the actual indent.
        $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1));

        $expectedIndent = ($assignmentIndent + $this->indent);
        $foundIndent    = strlen($tokens[$prev]['content']);
        if ($foundIndent !== $expectedIndent) {
            $error = 'Multi-line assignment not indented correctly; expected %s spaces but found %s';
            $data  = array(
                      $expectedIndent,
                      $foundIndent,
                     );
            $phpcsFile->addError($error, $stackPtr, 'Indent', $data);
        }

    }//end process()

}//end class

?>
<?php
/**
 * Class Declaration Test.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Class Declaration Test.
 *
 * Checks the declaration of the class is correct.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Sniffs_Classes_ClassDeclarationSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * The number of spaces code should be indented.
     *
     * @var int
     */
    public $indent = 4;


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
                T_CLASS,
                T_INTERFACE,
               );

    }//end register()


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param integer              $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens    = $phpcsFile->getTokens();
        $errorData = array($tokens[$stackPtr]['content']);

        if (isset($tokens[$stackPtr]['scope_opener']) === false) {
            $error = 'Possible parse error: %s missing opening or closing brace';
            $phpcsFile->addWarning($error, $stackPtr, 'MissingBrace', $errorData);
            return;
        }

        $curlyBrace  = $tokens[$stackPtr]['scope_opener'];
        $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($curlyBrace - 1), $stackPtr, true);
        $classLine   = $tokens[$lastContent]['line'];
        $braceLine   = $tokens[$curlyBrace]['line'];
        if ($braceLine === $classLine) {
            $error = 'Opening brace of a %s must be on the line after the definition';
            $phpcsFile->addError($error, $curlyBrace, 'OpenBraceNewLine', $errorData);
            return;
        } else if ($braceLine > ($classLine + 1)) {
            $error = 'Opening brace of a %s must be on the line following the %s declaration; found %s line(s)';
            $data  = array(
                      $tokens[$stackPtr]['content'],
                      $tokens[$stackPtr]['content'],
                      ($braceLine - $classLine - 1),
                     );
            $phpcsFile->addError($error, $curlyBrace, 'OpenBraceWrongLine', $data);
            return;
        }

        if ($tokens[($curlyBrace + 1)]['content'] !== $phpcsFile->eolChar) {
            $error = 'Opening %s brace must be on a line by itself';
            $phpcsFile->addError($error, $curlyBrace, 'OpenBraceNotAlone', $errorData);
        }

        if ($tokens[($curlyBrace - 1)]['code'] === T_WHITESPACE) {
            $prevContent = $tokens[($curlyBrace - 1)]['content'];
            if ($prevContent === $phpcsFile->eolChar) {
                $spaces = 0;
            } else {
                $blankSpace = substr($prevContent, strpos($prevContent, $phpcsFile->eolChar));
                $spaces     = strlen($blankSpace);
            }

            $expected = ($tokens[$stackPtr]['level'] * $this->indent);
            if ($spaces !== $expected) {
                $error = 'Expected %s spaces before opening brace; %s found';
                $data  = array(
                          $expected,
                          $spaces,
                         );
                $phpcsFile->addError($error, $curlyBrace, 'SpaceBeforeBrace', $data);
            }
        }

    }//end process()


}//end class

?>
<documentation title="Variable Names">
    <standard>
    <![CDATA[
    Private member variable names should be prefixed with an underscore and public/protected variable names should not.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Proper member variable names.">
        <![CDATA[
class Foo
{
    public $<em>publicVar</em>;
    protected $<em>protectedVar</em>;
    private $<em>_privateVar</em>;
}
        ]]>
        </code>
        <code title="Invalid: underscores used on public/protected variables and not used on private variables.">
        <![CDATA[
class Foo
{
    public $<em>_publicVar</em>;
    protected $<em>_protectedVar</em>;
    private $<em>privateVar</em>;
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Function and Method Names">
    <standard>
    <![CDATA[
    Functions and methods should be named using the "studly caps" style (also referred to as "bumpy case" or "camel caps"). Functions should in addition have the package name as a prefix, to avoid name collisions between packages. The initial letter of the name (after the prefix) is lowercase, and each letter that starts a new "word" is capitalized.
    ]]>
    </standard>
    <code_comparison>
        <code title="Examples of valid function names">
        <![CDATA[
connect()
getData()
buildSomeWidget()
XML_RPC_serializeData()
        ]]>
        </code>
        <code title="Examples of invalid function names">
        <![CDATA[
Connect()
get_data()
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Class Names">
    <standard>
    <![CDATA[
    Classes should be given descriptive names. Avoid using abbreviations where possible. Class names should always begin with an uppercase letter. The PEAR class hierarchy is also reflected in the class name, each level of the hierarchy separated with a single underscore.
    ]]>
    </standard>
    <code_comparison>
        <code title="Examples of valid class names">
        <![CDATA[
Log
Net_Finger
HTML_Upload_Error
        ]]>
        </code>
        <code title="Examples of invalid class names">
        <![CDATA[
log
NetFinger
HTML-Upload-Error
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Object Operator Indentation">
    <standard>
    <![CDATA[
    Chained object operators when spread out over multiple lines should be the first thing on the line and be indented by 1 level.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Object operator at the start of a new line.">
        <![CDATA[
$foo
    <em>-></em>bar()
    <em>-></em>baz();
        ]]>
        </code>
        <code title="Invalid: Object operator at the end of the line.">
        <![CDATA[
$foo<em>-></em>
    bar()<em>-></em>
    baz();
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Object operator indented correctly.">
        <![CDATA[
$foo
<em>    </em>->bar()
<em>    </em>->baz();
        ]]>
        </code>
        <code title="Invalid: Object operator not indented correctly.">
        <![CDATA[
$foo
<em></em>->bar()
<em></em>->baz();
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Closing Brace Indentation">
    <standard>
    <![CDATA[
    Closing braces should be indented at the same level as the beginning of the scope.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Consistent indentation level for scope.">
        <![CDATA[
if ($test) {
    $var = 1;
}
        ]]>
        </code>
        <code title="Invalid: The ending brace is indented further than the if statement.">
        <![CDATA[
if ($test) {
    $var = 1;
<em>    </em>}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Scope Indentation">
    <standard>
    <![CDATA[
    Any scope openers except for switch statements should be indented 1 level.  This includes classes, functions, and control structures.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Consistent indentation level for scope.">
        <![CDATA[
function foo()
{
<em>    </em>if ($test) {
<em>        </em>$var = 1;
<em>    </em>}
}
        ]]>
        </code>
        <code title="Invalid: Indentation is not used for scope.">
        <![CDATA[
function foo()
{
<em></em>if ($test) {
<em></em>$var = 1;
<em></em>}
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Default Values in Function Declarations">
    <standard>
    <![CDATA[
    Arguments with default values go at the end of the argument list.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: argument with default value at end of declaration">
        <![CDATA[
function connect($dsn, <em>$persistent = false</em>)
{
    ...
}
        ]]>
        </code>
        <code title="Invalid: argument with default value at start of declaration">
        <![CDATA[
function connect(<em>$persistent = false</em>, $dsn)
{
    ...
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Function Declarations">
    <standard>
    <![CDATA[
    There should be exactly 1 space after the function keyword and 1 space on each side of the use keyword.  Closures should use the Kernighan/Ritchie Brace style and other single-line functions should use the BSD/Allman style.  Multi-line function declarations should have the parameter lists indented one level with the closing parenthesis on a newline followed by a single space and the opening brace of the function.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Correct spacing around function and use keywords.">
        <![CDATA[
$foo = function<em> </em>()<em> </em>use<em> </em>($bar)<em> </em>{
};
        ]]>
        </code>
        <code title="Invalid: No spacing around function and use keywords.">
        <![CDATA[
$foo = function<em></em>()<em></em>use<em></em>($bar)<em></em>{
};
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Multiline function declaration formatted properly.">
        <![CDATA[
function foo(
<em>    </em>$bar,
<em>    </em>$baz
<em>) {</em>
};
        ]]>
        </code>
        <code title="Invalid: Invalid indentation and formatting of closing parenthesis.">
        <![CDATA[
function foo(
<em></em>$bar,
<em></em>$baz<em>)</em>
<em>{</em>
};
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Function Calls">
    <standard>
    <![CDATA[
      Functions should be called with no spaces between the function name, the opening parenthesis, and the first parameter; and no space between the last parameter, the closing parenthesis, and the semicolon.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: spaces between parameters">
        <![CDATA[
$var = foo($bar, $baz, $quux);
        ]]>
        </code>
        <code title="Invalid: additional spaces used">
        <![CDATA[
$var = foo<em> </em>(<em> </em>$bar, $baz, $quux<em> </em>)<em> </em>;
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Control Structure Signatures">
    <standard>
    <![CDATA[
    Control structures should use one space around the parentheses in conditions.  The opening brace should be preceded by one space and should be at the end of the line.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Correct spacing around the condition.">
        <![CDATA[
if<em> </em>($foo)<em> </em>{
}
        ]]>
        </code>
        <code title="Invalid: Incorrect spacing around the condition.">
        <![CDATA[
if<em></em>($foo)<em></em>{
}
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Correct placement of the opening brace.">
        <![CDATA[
if ($foo) <em>{</em>
}
        ]]>
        </code>
        <code title="Invalid: Incorrect placement of the opening brace on a new line.">
        <![CDATA[
if ($foo)
<em>{</em>
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Multi-line If Conditions">
    <standard>
    <![CDATA[
    Multi-line if conditions should be indented one level and each line should begin with a boolean operator.  The end parenthesis should be on a new line.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Correct indentation.">
        <![CDATA[
if ($foo
<em>    </em>&& $bar
) {
}
        ]]>
        </code>
        <code title="Invalid: No indentation used on the condition lines.">
        <![CDATA[
if ($foo
<em></em>&& $bar
) {
}
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Boolean operator at the start of the line.">
        <![CDATA[
if ($foo
    <em>&&</em> $bar
) {
}
        ]]>
        </code>
        <code title="Invalid: Boolean operator at the end of the line.">
        <![CDATA[
if ($foo <em>&&</em>
    $bar
) {
}
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: End parenthesis on a new line.">
        <![CDATA[
if ($foo
    && $bar
<em>)</em> {
}
        ]]>
        </code>
        <code title="Invalid: End parenthesis not moved to a new line.">
        <![CDATA[
if ($foo
    && $bar<em>)</em> {
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Class Comments">
    <standard>
    <![CDATA[
    Files must have a non-empty doc comment.  The short description must be on the second line of the comment.  Each description must have one blank comment line before and after.  There must be one blank line before the tags in the comments.  There must be a category, package, author, license, and link tag.  There may only be one category, package, subpackage, license, version, since and deprecated tag.  The tags must be in the order category, package, subpackage, author, copyright, license, version, link, see, since, and deprecated.  The php version must be specified.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: A file comment is used.">
        <![CDATA[
<?php
<em>/**
 * Short description here.
 *
 * PHP version 5
 *
 * @category Foo
 * @package Foo_Helpers
 * @author Marty McFly <mmcfly@example.com>
 * @copyright 2013 Foo Inc.
 * @license MIT License
 * @link http://example.com
 */</em>
        ]]>
        </code>
        <code title="Invalid: No doc comment for the class.">
        <![CDATA[
<?php
<em></em>
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Short description is the second line of the comment.">
        <![CDATA[
<?php
/**
 * <em>Short description here.</em>
 *
 * PHP version 5
 *
 * @category Foo
 * @package Foo_Helpers
 * @author Marty McFly <mmcfly@example.com>
 * @copyright 2013 Foo Inc.
 * @license MIT License
 * @link http://example.com
 */
        ]]>
        </code>
        <code title="Invalid: An extra blank line before the short description.">
        <![CDATA[
<?php
/**
 * <em></em>
 * <em>Short description here.</em>
 *
 * PHP version 5
 *
 * @category Foo
 * @package Foo_Helpers
 * @author Marty McFly <mmcfly@example.com>
 * @copyright 2013 Foo Inc.
 * @license MIT License
 * @link http://example.com
 */
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Exactly one blank line around descriptions.">
        <![CDATA[
<?php
/**
 * Short description here.
 * <em></em>
 * PHP version 5
 * <em></em>
 * @category Foo
 * @package Foo_Helpers
 * @author Marty McFly <mmcfly@example.com>
 * @copyright 2013 Foo Inc.
 * @license MIT License
 * @link http://example.com
 */
        ]]>
        </code>
        <code title="Invalid: Extra blank lines around the descriptions.">
        <![CDATA[
<?php
/**
 * Short description here.
 * <em></em>
 * <em></em>
 * PHP version 5
 * <em></em>
 * <em></em>
 * @category Foo
 * @package Foo_Helpers
 * @author Marty McFly <mmcfly@example.com>
 * @copyright 2013 Foo Inc.
 * @license MIT License
 * @link http://example.com
 */
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Exactly one blank line before the tags.">
        <![CDATA[
<?php
/**
 * Short description here.
 *
 * PHP version 5
 * <em></em>
 * @category Foo
 * @package Foo_Helpers
 * @author Marty McFly <mmcfly@example.com>
 * @copyright 2013 Foo Inc.
 * @license MIT License
 * @link http://example.com
 */
        ]]>
        </code>
        <code title="Invalid: Extra blank lines before the tags.">
        <![CDATA[
<?php
/**
 * Short description here.
 *
 * PHP version 5
 * <em></em>
 * <em></em>
 * @category Foo
 * @package Foo_Helpers
 * @author Marty McFly <mmcfly@example.com>
 * @copyright 2013 Foo Inc.
 * @license MIT License
 * @link http://example.com
 */
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: All required tags are used.">
        <![CDATA[
<?php
/**
 * Short description here.
 *
 * PHP version 5
 *
 * <em>@category</em> Foo
 * <em>@package</em> Foo_Helpers
 * <em>@author</em> Marty McFly <mmcfly@example.com>
 * <em>@copyright</em> 2013 Foo Inc.
 * <em>@license</em> MIT License
 * <em>@link</em> http://example.com
 */
        ]]>
        </code>
        <code title="Invalid: Missing an author tag.">
        <![CDATA[
<?php
/**
 * Short description here.
 *
 * PHP version 5
 *
 * @category Foo
 * @package Foo_Helpers
 * @copyright 2013 Foo Inc.
 * @license MIT License
 * @link http://example.com
 */
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Tags that should only be used once are only used once.">
        <![CDATA[
<?php
/**
 * Short description here.
 *
 * PHP version 5
 *
 * <em>@category</em> Foo
 * <em>@package</em> Foo_Helpers
 * @author Marty McFly <mmcfly@example.com>
 * @copyright 2013 Foo Inc.
 * <em>@license</em> MIT License
 * @link http://example.com
 */
        ]]>
        </code>
        <code title="Invalid: Multiple category tags.">
        <![CDATA[
<?php
/**
 * Short description here.
 *
 * PHP version 5
 *
 * <em>@category</em> Foo
 * <em>@category</em> Bar
 * @package Foo_Helpers
 * @author Marty McFly <mmcfly@example.com>
 * @copyright 2013 Foo Inc.
 * @license MIT License
 * @link http://example.com
 */
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: PHP version specified.">
        <![CDATA[
<?php
/**
 * Short description here.
 *
 * <em>PHP version 5</em>
 *
 * @category Foo
 * @package Foo_Helpers
 * @author Marty McFly <mmcfly@example.com>
 * @copyright 2013 Foo Inc.
 * @license MIT License
 * @link http://example.com
 */
        ]]>
        </code>
        <code title="Invalid: Category and package tags are swapped in order.">
        <![CDATA[
<?php
/**
 * Short description here.
 *
 * PHP version 5
 *
 * <em>@package</em> Foo_Helpers
 * <em>@category</em> Foo
 * @author Marty McFly <mmcfly@example.com>
 * @copyright 2013 Foo Inc.
 * @license MIT License
 * @link http://example.com
 */
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Tags are in the correct order.">
        <![CDATA[
<?php
/**
 * Short description here.
 *
 * PHP version 5
 *
 * @category Foo
 * @package Foo_Helpers
 * @author Marty McFly <mmcfly@example.com>
 * @copyright 2013 Foo Inc.
 * @license MIT License
 * @link http://example.com
 */
        ]]>
        </code>
        <code title="Invalid: No php version specified.">
        <![CDATA[
<?php
/**
 * Short description here.
 *
 * @category Foo
 * @package Foo_Helpers
 * @author Marty McFly <mmcfly@example.com>
 * @copyright 2013 Foo Inc.
 * @license MIT License
 * @link http://example.com
 */
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Inline Comments">
    <standard>
    <![CDATA[
    Perl-style # comments are not allowed.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: A // style comment.">
        <![CDATA[
<em>//</em> A comment.
        ]]>
        </code>
        <code title="Invalid: A # style comment.">
        <![CDATA[
<em>#</em> A comment.
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Class Comments">
    <standard>
    <![CDATA[
    Functions must have a non-empty doc comment.  The short description must be on the second line of the comment.  Each description must have one blank comment line before and after.  There must be one blank line before the tags in the comments.  There must be a tag for each of the parameters in the right order with the right variable names with a comment.  There must be a return tag.  Any throw tag must have an exception class.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: A function doc comment is used.">
        <![CDATA[
<em>/**
 * Short description here.
 *
 * @return void
 */</em>
 function foo()
 {
 }
        ]]>
        </code>
        <code title="Invalid: No doc comment for the function.">
        <![CDATA[
 function foo()
 {
 }
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Short description is the second line of the comment.">
        <![CDATA[
/**
 * <em>Short description here.</em>
 *
 * @return void
 */
 function foo()
 {
 }
        ]]>
        </code>
        <code title="Invalid: An extra blank line before the short description.">
        <![CDATA[
/**
 * <em></em>
 * <em>Short description here.</em>
 *
 * @return void
 */
 function foo()
 {
 }
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Exactly one blank line around descriptions.">
        <![CDATA[
/**
 * Short description here.
 * <em></em>
 * Long description here.
 * <em></em>
 * @return void
 */
 function foo()
 {
 }
        ]]>
        </code>
        <code title="Invalid: Extra blank lines around the descriptions.">
        <![CDATA[
/**
 * Short description here.
 * <em></em>
 * <em></em>
 * Long description here.
 * <em></em>
 * <em></em>
 * @return void
 */
 function foo()
 {
 }
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Exactly one blank line before the tags.">
        <![CDATA[
/**
 * Short description here.
 *
 * Long description here.
 * <em></em>
 * @return void
 */
 function foo()
 {
 }
        ]]>
        </code>
        <code title="Invalid: Extra blank lines before the tags.">
        <![CDATA[
/**
 * Short description here.
 *
 * Long description here.
 * <em></em>
 * <em></em>
 * @return void
 */
 function foo()
 {
 }
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Throws tag has an exception class.">
        <![CDATA[
/**
 * Short description here.
 *
 * @return void
 * @throws <em>FooException</em>
 */
 function foo()
 {
 }
        ]]>
        </code>
        <code title="Invalid: No exception class given for throws tag.">
        <![CDATA[
/**
 * Short description here.
 *
 * @return void
 * <em>@throws</em>
 */
 function foo()
 {
 }
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Return tag present.">
        <![CDATA[
/**
 * Short description here.
 *
 * <em>@return void</em>
 */
 function foo()
 {
 }
        ]]>
        </code>
        <code title="Invalid: No return tag.">
        <![CDATA[
/**
 * Short description here.
 */
 function foo()
 {
 }
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Param names are correct.">
        <![CDATA[
/**
 * Short description here.
 *
 * @param string <em>$foo</em> Foo parameter
 * @param string <em>$bar</em> Bar parameter
 * @return void
 */
 function foo(<em>$foo</em>, <em>$bar</em>)
 {
 }
        ]]>
        </code>
        <code title="Invalid: Wrong parameter name doesn't match function signature.">
        <![CDATA[
/**
 * Short description here.
 *
 * @param string $foo Foo parameter
 * @param string <em>$qux</em> Bar parameter
 * @return void
 */
 function foo($foo, <em>$bar</em>)
 {
 }
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Param names are ordered correctly.">
        <![CDATA[
/**
 * Short description here.
 *
 * @param string <em>$foo</em> Foo parameter
 * @param string <em>$bar</em> Bar parameter
 * @return void
 */
 function foo(<em>$foo</em>, <em>$bar</em>)
 {
 }
        ]]>
        </code>
        <code title="Invalid: Wrong parameter order.">
        <![CDATA[
/**
 * Short description here.
 *
 * @param string <em>$bar</em> Bar parameter
 * @param string <em>$foo</em> Foo parameter
 * @return void
 */
 function foo(<em>$foo</em>, <em>$bar</em>)
 {
 }
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Class Comments">
    <standard>
    <![CDATA[
    Classes and interfaces must have a non-empty doc comment.  The short description must be on the second line of the comment.  Each description must have one blank comment line before and after.  There must be one blank line before the tags in the comments.  A @version tag must be in Release: package_version format.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: A doc comment for the class.">
        <![CDATA[
<em>/**
 * The Foo class.
 */</em>
class Foo
{
}
        ]]>
        </code>
        <code title="Invalid: No doc comment for the class.">
        <![CDATA[
class Foo
{
}
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: A doc comment for the class.">
        <![CDATA[
<em>/**
 * The Foo class.
 */</em>
class Foo
{
}
        ]]>
        </code>
        <code title="Invalid: Invalid comment type for the class.">
        <![CDATA[
// The Foo class.
class Foo
{
}
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: A doc comment for the class.">
        <![CDATA[
<em>/**
 * The Foo class.
 */</em>
class Foo
{
}
        ]]>
        </code>
        <code title="Invalid: The blank line after the comment makes it appear as a file comment, not a class comment.">
        <![CDATA[
<em>/**
 * The Foo class.
 */</em>

class Foo
{
}
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Short description is the second line of the comment.">
        <![CDATA[
/**
 * <em>The Foo class.</em>
 */
class Foo
{
}
        ]]>
        </code>
        <code title="Invalid: An extra blank line before the short description.">
        <![CDATA[
/**
 *
 * <em>The Foo class.</em>
 */
class Foo
{
}
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Exactly one blank line around descriptions.">
        <![CDATA[
/**
 * The Foo class.
 * <em></em>
 * A helper for the Bar class.
 * <em></em>
 * @see Bar
 */
class Foo
{
}
        ]]>
        </code>
        <code title="Invalid: Extra blank lines around the descriptions.">
        <![CDATA[
/**
 * The Foo class.
 * <em></em>
 * <em></em>
 * A helper for the Bar class.
 * <em></em>
 * <em></em>
 * @see Bar
 */
class Foo
{
}
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Exactly one blank line before the tags.">
        <![CDATA[
/**
 * The Foo class.
 * <em></em>
 * @see Bar
 */
class Foo
{
}
        ]]>
        </code>
        <code title="Invalid: Extra blank lines before the tags.">
        <![CDATA[
/**
 * The Foo class.
 * <em></em>
 * <em></em>
 * @see Bar
 */
class Foo
{
}
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Version tag is in the correct format.">
        <![CDATA[
/**
 * The Foo class.
 *
 * @version <em>Release: 1.0</em>
 */
class Foo
{
}
        ]]>
        </code>
        <code title="Invalid: No Release: text.">
        <![CDATA[
/**
 * The Foo class.
 *
 * @version <em>1.0</em>
 */
class Foo
{
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Including Code">
    <standard>
    <![CDATA[
    Anywhere you are unconditionally including a class file, use <em>require_once</em>. Anywhere you are conditionally including a class file (for example, factory methods), use <em>include_once</em>. Either of these will ensure that class files are included only once. They share the same file list, so you don't need to worry about mixing them - a file included with <em>require_once</em> will not be included again by <em>include_once</em>.
    ]]>
    </standard>
    <standard>
    <![CDATA[
    Note that <em>include_once</em> and <em>require_once</em> are statements, not functions. Parentheses should not surround the subject filename.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: used as statement">
        <![CDATA[
require_once 'PHP/CodeSniffer.php';
        ]]>
        </code>
        <code title="Invalid: used as function">
        <![CDATA[
require_once<em>(</em>'PHP/CodeSniffer.php'<em>)</em>;
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Line Length">
    <standard>
    <![CDATA[
    It is recommended to keep lines at approximately 85 characters long for better code readability.
    ]]>
    </standard>
</documentation>
<documentation title="Multi-Line Assignment">
    <standard>
    <![CDATA[
    Multi-line assignment should have the equals sign be the first item on the second line indented correctly.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Assignment operator at the start of the second line.">
        <![CDATA[
$foo
    <em>=</em> $bar;
        ]]>
        </code>
        <code title="Invalid: Assignment operator at end of first line.">
        <![CDATA[
$foo <em>=</em>
    $bar;
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: Assignment operator indented one level.">
        <![CDATA[
$foo
<em>    </em>= $bar;
        ]]>
        </code>
        <code title="Invalid: Assignment operator not indented.">
        <![CDATA[
$foo
<em></em>= $bar;
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Class Declarations">
    <standard>
    <![CDATA[
    The opening brace of a class must be on the line after the definition by itself.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Opening brace on the correct line.">
        <![CDATA[
class Foo
<em>{</em>
}
        ]]>
        </code>
        <code title="Invalid: Opening brace on same line as declaration.">
        <![CDATA[
class Foo <em>{</em>
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<?php
/**
 * Unit test class for the ValidVariableName sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ValidVariableName sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Tests_NamingConventions_ValidVariableNameUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                12 => 1,
                17 => 1,
                22 => 1,
                92 => 1,
                93 => 1,
                94 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php

class Valid_Name {}

class invalid_Name {}

class invalid_name {}

class Invalid_name {}

class VALID_Name {}

class VALID_NAME {}

class VALID_Name {}

class ValidName {}

class _Invalid_Name {}


interface Valid_Name {}

interface invalid_Name {}

interface invalid_name {}

interface Invalid_name {}

interface VALID_Name {}

interface VALID_NAME {}

interface VALID_Name {}

interface ValidName {}

interface _Invalid_Name {}

class ___ {}

interface ___ {}

class Invalid__Name {}

interface Invalid__Name {}

?>
<?php
/**
 * Unit test class for the ValidClassName sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ValidClassName sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Tests_NamingConventions_ValidClassNameUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                5  => 1,
                7  => 2,
                9  => 1,
                19 => 1,
                24 => 1,
                26 => 2,
                28 => 1,
                38 => 1,
                40 => 2,
                42 => 2,
                44 => 1,
                46 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
class MyClass
{
    $varName  = 'hello';
    $var_name = 'hello';
    $varname  = 'hello';
    $_varName = 'hello';

    public $varName  = 'hello';
    public $var_name = 'hello';
    public $varname  = 'hello';
    public $_varName = 'hello';

    protected $varName  = 'hello';
    protected $var_name = 'hello';
    protected $varname  = 'hello';
    protected $_varName = 'hello';

    private $_varName  = 'hello';
    private $_var_name = 'hello';
    private $_varname  = 'hello';
    private $varName   = 'hello';
}

class MyClass
{
  function func1()
  {
    function func2()
    {
     return $a;
    }
    return $data;
  }
}

class MyClass
{
    public function prepare() {}
    public function paint() {}
}

if (true) {
    class MyClass
    {
        $varName  = 'hello';
        $var_name = 'hello';
    }
}

class MyClass {
    function myFunction($cc, $cv) {
        $req = "delete from blah
                where not (POP_{$cc}_A =
'{$this->def["POP_{$cc}_A"]}'
                         and POP_{$cc}_B =
'{$this->def["POP_{$cc}_B"]}')";
    }
}

class mpgResponse{
   var $term_id;
   var $currentTag;
   function characterHandler($parser,$data){
       switch($this->currentTag)
       {
           case "term_id": {
               $this->term_id=$data;
               break;
           }
       }
   }//end characterHandler
}//end class mpgResponse

class foo
{
    const bar = <<<BAZ
qux
BAZ;
}

class foo
{
    var $c = <<<C
ccc
C;
}

class a
{
    protected
        $_sheet,
        $_FieldParser,
        $_key;
}
?>
<?php

abstract class My_Class {

    public function __construct() {}
    public function My_Class() {}
    public function _My_Class() {}

    public function getSomeValue() {}
    public function parseMyDSN() {}
    public function get_some_value() {}
    public function GetSomeValue() {}
    public function getSomeValue_Again() {}
    public function My_Package_getSomeValue() {}
    public function _getSomeValue() {}
    public function _parseMyDSN() {}
    public function _get_some_value() {}
    public function _GetSomeValue() {}
    public function _getSomeValue_Again() {}
    public function _My_Package_getSomeValue() {}

    protected function getSomeValue() {}
    protected function parseMyDSN() {}
    protected function get_some_value() {}
    protected function GetSomeValue() {}
    protected function getSomeValue_Again() {}
    protected function My_Package_getSomeValue() {}
    protected function _getSomeValue() {}
    protected function _parseMyDSN() {}
    protected function _get_some_value() {}
    protected function _GetSomeValue() {}
    protected function _getSomeValue_Again() {}
    protected function _My_Package_getSomeValue() {}

    private function getSomeValue() {}
    private function parseMyDSN() {}
    private function get_some_value() {}
    private function GetSomeValue() {}
    private function getSomeValue_Again() {}
    private function My_Package_getSomeValue() {}
    private function _getSomeValue() {}
    private function _parseMyDSN() {}
    private function _get_some_value() {}
    private function _GetSomeValue() {}
    private function _getSomeValue_Again() {}
    private function _My_Package_getSomeValue() {}

    function getSomeValue() {}
    function parseMyDSN() {}
    function get_some_value() {}
    function GetSomeValue() {}
    function getSomeValue_Again() {}
    function My_Package_getSomeValue() {}
    function _getSomeValue() {}
    function _parseMyDSN() {}
    function _get_some_value() {}
    function _GetSomeValue() {}
    function _getSomeValue_Again() {}
    function _My_Package_getSomeValue() {}

}//end class

interface My_Interface {

    public function getSomeValue() {}
    public function parseMyDSN() {}
    public function get_some_value() {}
    public function GetSomeValue() {}
    public function getSomeValue_Again() {}
    public function My_Package_getSomeValue() {}
    public function _getSomeValue() {}
    public function _parseMyDSN() {}
    public function _get_some_value() {}
    public function _GetSomeValue() {}
    public function _getSomeValue_Again() {}
    public function _My_Package_getSomeValue() {}

    protected function getSomeValue() {}
    protected function parseMyDSN() {}
    protected function get_some_value() {}
    protected function GetSomeValue() {}
    protected function getSomeValue_Again() {}
    protected function My_Package_getSomeValue() {}
    protected function _getSomeValue() {}
    protected function _parseMyDSN() {}
    protected function _get_some_value() {}
    protected function _GetSomeValue() {}
    protected function _getSomeValue_Again() {}
    protected function _My_Package_getSomeValue() {}

    private function getSomeValue() {}
    private function parseMyDSN() {}
    private function get_some_value() {}
    private function GetSomeValue() {}
    private function getSomeValue_Again() {}
    private function My_Package_getSomeValue() {}
    private function _getSomeValue() {}
    private function _parseMyDSN() {}
    private function _get_some_value() {}
    private function _GetSomeValue() {}
    private function _getSomeValue_Again() {}
    private function _My_Package_getSomeValue() {}

    function getSomeValue() {}
    function parseMyDSN() {}
    function get_some_value() {}
    function GetSomeValue() {}
    function getSomeValue_Again() {}
    function My_Package_getSomeValue() {}
    function _getSomeValue() {}
    function _parseMyDSN() {}
    function _get_some_value() {}
    function _GetSomeValue() {}
    function _getSomeValue_Again() {}
    function _My_Package_getSomeValue() {}

}//end interface

function My_Package_getSomeValue() {}
function My_Package_parseMyDSN() {}
function My_Package_get_some_value() {}
function My_PackagegetSomeValue() {}
function My_Package_getSomeValue_Again() {}
function My_Package() {}
function _My_Package_getSomeValue() {}
function _My_Package_parseMyDSN() {}
function _My_Package_get_some_value() {}
function _My_PackagegetSomeValue() {}
function _My_Package_getSomeValue_Again() {}
function _My_Package() {}


/* Test for magic functions */

class Magic_Test {
    function __construct() {}
    function __destruct() {}
    function __call() {}
    function __callStatic() {}
    function __get() {}
    function __set() {}
    function __isset() {}
    function __unset() {}
    function __sleep() {}
    function __wakeup() {}
    function __toString() {}
    function __set_state() {}
    function __clone() {}
    function __autoload() {}
    function __invoke() {}
    function __myFunction() {}
    function __my_function() {}
}

function __construct() {}
function __destruct() {}
function __call() {}
function __callStatic() {}
function __get() {}
function __set() {}
function __isset() {}
function __unset() {}
function __sleep() {}
function __wakeup() {}
function __toString() {}
function __set_state() {}
function __clone() {}
function __autoload() {}
function __invoke() {}
function __myFunction() {}
function __my_function() {}

function my_package_function() {}
function Package_() {}
function Package() {}

class Closure_Test {
    function test() {
        $foo = function() { echo 'foo'; };
    }
}

function test() {
    $foo = function() { echo 'foo'; };
}

/* @codingStandardsIgnoreStart */
class MyClass
{
    /* @codingStandardsIgnoreEnd */
    public function __construct() {}
}

trait Foo
{
    function __call() {}
}

class Magic_Case_Test {
    function __Construct() {}
    function __isSet() {}
    function __tostring() {}
}
function __autoLoad() {}
?>
<?php
/**
 * Unit test class for the ValidFunctionName sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ValidFunctionName sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Tests_NamingConventions_ValidFunctionNameUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        $errors = array(
                   11  => 1,
                   12  => 1,
                   13  => 1,
                   14  => 1,
                   15  => 1,
                   16  => 1,
                   17  => 1,
                   18  => 1,
                   19  => 1,
                   20  => 1,
                   24  => 1,
                   25  => 1,
                   26  => 1,
                   27  => 1,
                   28  => 1,
                   29  => 1,
                   30  => 1,
                   31  => 1,
                   32  => 1,
                   33  => 1,
                   35  => 1,
                   36  => 1,
                   37  => 1,
                   38  => 1,
                   39  => 1,
                   40  => 1,
                   43  => 1,
                   44  => 1,
                   45  => 1,
                   46  => 1,
                   50  => 1,
                   51  => 1,
                   52  => 1,
                   53  => 1,
                   56  => 1,
                   57  => 1,
                   58  => 1,
                   59  => 1,
                   67  => 1,
                   68  => 1,
                   69  => 1,
                   70  => 1,
                   71  => 1,
                   72  => 1,
                   73  => 1,
                   74  => 1,
                   75  => 1,
                   76  => 1,
                   80  => 1,
                   81  => 1,
                   82  => 1,
                   83  => 1,
                   84  => 1,
                   85  => 1,
                   86  => 1,
                   87  => 1,
                   88  => 1,
                   89  => 1,
                   91  => 1,
                   92  => 1,
                   93  => 1,
                   94  => 1,
                   95  => 1,
                   96  => 1,
                   99  => 1,
                   100 => 1,
                   101 => 1,
                   102 => 1,
                   106 => 1,
                   107 => 1,
                   108 => 1,
                   109 => 1,
                   112 => 1,
                   113 => 1,
                   114 => 1,
                   115 => 1,
                   121 => 1,
                   122 => 1,
                   123 => 1,
                   124 => 1,
                   125 => 1,
                   126 => 1,
                   127 => 1,
                   128 => 1,
                   129 => 1,
                   130 => 1,
                   149 => 1,
                   151 => 1,
                   152 => 1,
                   155 => 1,
                   156 => 1,
                   157 => 1,
                   158 => 1,
                   159 => 1,
                   160 => 1,
                   161 => 1,
                   162 => 1,
                   163 => 1,
                   164 => 1,
                   165 => 1,
                   166 => 1,
                   167 => 1,
                   169 => 1,
                   170 => 1,
                   171 => 1,
                   173 => 1,
                   174 => 1,
                   175 => 1,
               );

        // The trait tests will only work in PHP version where traits exist and
        // will throw errors in earlier versions.
        if (version_compare(PHP_VERSION, '5.4.0') < 0) {
            $errors[196] = 1;
        }

        return $errors;

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the ObjectOperatorIndent sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ObjectOperatorIndent sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Tests_WhiteSpace_ObjectOperatorIndentUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                3  => 2,
                6  => 1,
                15 => 1,
                27 => 1,
                37 => 1,
                38 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
$someObject->someFunction("some", "parameter")
->someOtherFunc(23, 42)->
    someOtherFunc2($one, $two)

 ->someOtherFunc3(23, 42)
    ->andAThirdFunction();

    $someObject->someFunction("some", "parameter")
        ->someOtherFunc(23, 42);

$someObject->someFunction("some", "parameter")->someOtherFunc(23, 42);

$someObject->someFunction("some", "parameter")
        ->someOtherFunc(23, 42);

func(
    $bar->foo()
)
    ->bar();

func(
    $bar->foo()
)
    ->bar(
        $bar->foo()
        ->bar()
            ->func()
    );

$object
    ->setBar($foo)
    ->setFoo($bar);

if ($bar) {
    $object
    ->setBar($foo)
    ->setFoo($bar);
}
?>
<?php
/**
 * Unit test class for the ScopeClosingBrace sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ScopeClosingBrace sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Tests_WhiteSpace_ScopeClosingBraceUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                11 => 1,
                13 => 1,
                24 => 1,
                61 => 1,
                65 => 1,
                85 => 1,
                89 => 1,
                98 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php

class Test
{
    function __construct()
    {
       $this->hello(); // error here
    }

   function hello() // error here
    { // no error here as brackets can be put anywhere in the pear standard
        echo 'hello';
    }

    function hello2()
    {
       if (TRUE) { // error here
            echo 'hello'; // no error here as its more than 4 spaces.
        } else {
        echo 'bye'; // error here
        }

        while (TRUE) {
           echo 'hello'; // error here
         }// no error here as its handled by another test.

       do { // error here
         echo 'hello'; // error here
       } while (TRUE); // no error here as its aligned with the do.
   }// no error here as its handled by another test.

    function hello3()
    {
        switch ($hello) {
        case 'hello': // no error here as switch statements shouldn't be indented ???
            break;
        }
    }

}

?>
<pre>
</head>
<body>
<?php
if ($form->validate()) {
    $safe = $form->getSubmitValues();
}
?>
</pre>
<?php

class Test2
{
    function __construct()
    {
    //    $this->open(); // error here
    }

    public function open()
    {
        // Some inline stuff that shouldn't error
        if (TRUE) echo 'hello';
        foreach ($tokens as $token) echo $token;
    }

    /**
     * This is a comment 1.
     * This is a comment 2.
     * This is a comment 3.
     * This is a comment 4.
     */
    public function close()
    {
        // All ok.
        if (TRUE) {
            if (TRUE) {
            } else if (FALSE) {
                foreach ($tokens as $token) {
                    switch ($token) {
                    case '1':
                    case '2':
                        if (true) {
                            if (false) {
                                if (false) {
                                    if (false) {
                                        echo 'hello';
                                    }
                                }
                            }
                        }
                    break;
                    case '5':
                        break;
                    }
                    do {
                        while (true) {
                            foreach ($tokens as $token) {
                                for ($i = 0; $i < $token; $i++) {
                                    echo 'hello';
                                }
                            }
                        }
                    } while (true);
                }
            }
        }
    }

    /*
      This is another c style comment 1.
      This is another c style comment 2.
      This is another c style comment 3.
      This is another c style comment 4.
      This is another c style comment 5.
    */

    /*
    *
    *
    *
   */

    /**
   */

    /*
      This comment has a newline in it.

    */

    public function read()
    {
        echo 'hello';

        // no errors below.
        $array = array(
                  'this',
                  'that' => array(
                             'hello',
                             'hello again' => array(
                                               'hello',
                                              ),
                            ),
                 );
    }
}

abstract class Test3
{
    public function parse()
    {

        foreach ($t as $ndx => $token) {
            if (is_array($token)) {
                echo 'here';
            } else {
                $ts[] = array("token" => $token, "value" => '');

                $last = count($ts) - 1;

                switch ($token) {
                case '(':

                    if ($last >= 3 &&
                        $ts[0]['token'] != T_CLASS &&
                        $ts[$last - 2]['token'] == T_OBJECT_OPERATOR &&
                        $ts[$last - 3]['token'] == T_VARIABLE ) {


                        if (true) {
                            echo 'hello';
                        }
                    }
                    array_push($braces, $token);
                    break;
                }
            }
        }
    }
}

public function test()
{
    $o = <<<EOF
this is some text
this is some text
this is some text
this is some text
this is some text
this is some text
EOF;

    return $o;
}

if ($a === true || $a === true || $a === true || $a === true ||
    $a === true || $a === true || $a === true || $a === true) {

    echo 'hello';
}

if ($true) {
    /* First comment line
    * 
    * Comment test here
    * Comment test here
    * 
    */
    
    /* First comment line
    * 
    * Comment test here
    * Comment test here
    * 
    this si something */
}

function test()
{
    /* taken from http://de3.php.net/manual/en/reserved.php */
    # $m[] = 'declare';
   /* taken from http://de3.php.net/manual/en/reserved.php */
   # $m[] = 'declare';
}

foreach ($elements as $element) {
    if ($something) {
        // Do IF.
    } else if ($somethingElse) {
        // Do ELSE.
    }
}

if ($condition) {
    echo "This is a long
string that spans $numLines lines
without indenting.
";
}

if ($condition) {
    echo 'This is a long
    string that spans nultiple lines
    with indenting.
    ';
}

if ($condition) {
    echo 'This is a long
          string that spans nultiple lines
          with indenting.';
}

switch ($foo) {
case 1:
    switch ($bar) {
    default:
        echo $string{1};
    }
    break;
}

function temp($foo, $bar) {
    switch ($foo) {
    case 1:
        switch ($bar) {
        default:
            return $foo;
        }
        break;
    }
}

switch ($foo) {
case 1:
    switch ($bar) {
        default:
        if ($something) {
            echo $string{1};
        } else if ($else) {
            switch ($else) {
                default:
            }
        }
    }
    break;
}

switch ($name) {
case "1":
case "2":
case "3":
    return true;
}

switch ($name) {
case "1":
case "2":
case "3":
default :
    return true;
}

// Don't check the first token in the closure.
$array = array();
array_map(
    function($x)
    {
       return trim($x);
    },
    $array
);
?>
<?php

class Test
{
    public function __construct()
    {
    }

    function test1()
    {
     }

    function test2() {}

    private function _test3()
    {
    }

}


class Test2
{
 }


public function test2()
{
    if ($str{0}) {
        $chr = $str{0};
    }
    
    if (!class_exists($class_name)) {
        echo $error;
    }
    $this->{$property} =& new $class_name($this->db_index);
    $this->modules[$module] =& $this->{$property};
}

foreach ($elements as $element) {
    if ($something) {
        // Do IF.
    } else if ($somethingElse) {
        // Do ELSE.
    }
}

switch ($foo) {
case 1:
    switch ($bar) {
    default:
        if ($something) {
            echo $string{1};
        } else if ($else) {
            switch ($else) {
            case 1:
                // Do something.
                break;
            default:
                // Do something.
            break;
            }
        }
    }
break;
case 2:
    // Do something;
    break;
}

switch ($httpResponseCode) {
    case 100:
    case 101:
    case 102:
    default:
        return 'Unknown';
}

switch ($httpResponseCode) {
    case 100:
    case 101:
    case 102:
        return 'Processing.';
    default:
    return 'Unknown';
}

switch($i) {
case 1: {}
}

switch ($httpResponseCode) {
    case 100:
    case 101:
    case 102:
        exit;
    default:
    exit;
}<?php
/**
 * Unit test class for the ScopeIndent sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ScopeIndent sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Tests_WhiteSpace_ScopeIndentUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                7   => 1,
                10  => 1,
                17  => 1,
                20  => 1,
                24  => 1,
                27  => 1,
                28  => 1,
                58  => 1,
                123 => 1,
                126 => 1,
                224 => 1,
                225 => 1,
                279 => 1,
                284 => 1,
                311 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the FunctionDeclaration sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the FunctionDeclaration sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Tests_Functions_FunctionDeclarationUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                3   => 1,
                4   => 1,
                5   => 1,
                9   => 1,
                10  => 1,
                11  => 1,
                14  => 1,
                17  => 1,
                27  => 1,
                44  => 1,
                51  => 1,
                61  => 2,
                86  => 1,
                98  => 2,
                108 => 1,
                109 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the ValidDefaultValue sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ValidDefaultValue sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Tests_Functions_ValidDefaultValueUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                29 => 1,
                34 => 1,
                39 => 1,
                71 => 1,
                76 => 1,
                81 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php

// No args.
function myFunction()
{
}

// No default args.
function myFunction($arg1)
{
}

// Valid
function myFunction($arg1, $arg2='hello')
{
}

// Valid with lots of args
function myFunction($arg1, $arg2, $arg3, $arg4='hello', $arg5=array(), $arg6='hello')
{
}

// Valid type hints
function myFunction(array $arg1, array $arg2=array())
{
}

// Invalid
function myFunction($arg2='hello', $arg1)
{
}

// Invalid with lots of args
function myFunction($arg1, $arg2, $arg3, $arg4='hello', $arg5, $arg6='hello')
{
}

// Invalid type hints
function myFunction(array $arg2=array(), array $arg1)
{
}

class myClass()
{
    // No args.
    function myFunction()
    {
    }

    // No default args.
    function myFunction($arg1)
    {
    }

    // Valid
    function myFunction($arg1, $arg2='hello')
    {
    }

    // Valid with lots of args
    function myFunction($arg1, $arg2, $arg3, $arg4='hello', $arg5=array(), $arg6='hello')
    {
    }

    // Valid type hints
    function myFunction(array $arg1, array $arg2=array())
    {
    }

    // Invalid
    function myFunction($arg2='hello', $arg1)
    {
    }

    // Invalid with lots of args
    function myFunction($arg1, $arg2, $arg3, $arg4='hello', $arg5, $arg6='hello')
    {
    }

    // Invalid type hints
    function myFunction(array $arg2=array(), array $arg1)
    {
    }
}

?>
<?php
public function someFunctionWithAVeryLongName($firstParameter='something',
   $secondParameter='booooo', $third=null, $fourthParameter=false,
     $fifthParameter=123.12, $sixthParam=true
){
}

function someFunctionWithAVeryLongName2($firstParameter='something',
$secondParameter='booooo', $third=null, $fourthParameter=false,
$fifthParameter=123.12, $sixthParam=true
)  {
}

function blah() {
}

function  blah()
{
}

class MyClass
{

    public function someFunctionWithAVeryLongName($firstParameter='something',
        $secondParameter='booooo', $third=null, $fourthParameter=false,
        $fifthParameter=123.12, $sixthParam=true
    ) /** w00t */ {
    }

    public function someFunctionWithAVeryLongName2(
        $firstParameter='something', $secondParameter='booooo', $third=null
    ) {
    }

    protected abstract function processTokenWithinScope(
        PHP_CodeSniffer_File $phpcsFile,
        $stackPtr,
        $currScope
    );

    protected abstract function processToken(
        PHP_CodeSniffer_File $phpcsFile,
        $stackPtr,
        $currScope);

}

function getInstalledStandards(
    $includeGeneric=false,
    $standardsDir=''
)
{
}

function &testFunction($arg1,
    $arg2,
) {
}

function testFunction($arg1,
$arg2) {
}

function validateUrl(
    $url,
    $requireScheme=TRUE,
    array $allowedSchemes=array(
                           'http',
                           'https',
                          )
) {
}

$noArgs_longVars = function () use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
    // body
};

$longArgs_longVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) use  (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
    // body
};

$longArgs_longVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
    )  use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
    // body
};

$longArgs_longVars = function (
    $longArgument,
    $muchLongerArgument) use (
    $muchLongerVar3) {
    // body
};

function test()
{
    $longArgs_longVars = function (
        $longArgument,
        $longerArgument,
        $muchLongerArgument
    ) use (
        $longVar1,
        $longerVar2,
        $muchLongerVar3
    ) {
        // body
    };
}
?>
<?php

test();
test($arg, $arg2);
test ();
test( );
test() ;
test( $arg);
test( $arg );
test ( $arg );

if (is_array($arg) === true) {

}

$something = get($arg1, $arg2);
$something = get($arg1, $arg2) ;
$something = get($arg1, $arg2)   ;

// No errors as this test only checks for function calls.
class TestClass extends MyClass
{

    const const1 = 'hello';
    const CONST2 = 'hello';

    public function test () { }
}

make_foo($string/*the string*/, true/*test*/);
make_foo($string/*the string*/, true/*test*/ );
make_foo($string /*the string*/, true /*test*/);
make_foo(/*the string*/$string, /*test*/true);
make_foo( /*the string*/$string, /*test*/true);

// No errors should be throw here because
// this is multi-line.
throw new Exception(
    'Exception text'
);

// Objects are the same as a normal call.
$obj = new TestClass( );

// Heredocs dont need to be indented.
method_call(
<<<EOH
Anyone want to recomment parse errors?

EOH
);

fputs(
    STDOUT,
    'Examples:
    $ {$app} --all
    $ {$app} --all');

fputs(STDOUT,
    "Examples:
    $ {$app} --all
    $ {$app} --all",
$something
    );

// This is not a function call.
function &testFunction($arg1,
    $arg2,
) {
}

$array = array();
array_map(
    function($x)
    {
        return trim($x);
    },
    $array
);

array_map(
     function($x)
     {
         return trim($x);
     },
    $array
);

$bar = new stdClass(
    4,
    5,
    6
   
);

$bar = new stdClass(
    4,
    5,
    6

);

$foo = new stdClass(
    1,
    2,
    3);

public function doSomething()
{
    return $this->getFoo()
        ->doBar(
            $this->getX() // no comma here
                ->doY()  // this is still the first method argument
                ->doZ()  // this is still the first method argument
        );
}

$var = myFunction(
$foo,
$bar
);

// @codingStandardsChangeSetting PEAR.Functions.FunctionCallSignature allowMultipleArguments false

fputs(
    STDOUT,
    "Examples:
    $ {$app} , --all
    $ {$app} --all", $something
);

$array = array();
array_map(
    function($x)
    {
        return trim($x, $y);
    }, $foo
    $array
);

$bar = new stdClass(
    4, 5, 6
);

public function doSomething()
{
    return $this->getFoo()
        ->doBar(
            $this->getX() // no comma here
                ->doY()  // this is still the first method argument
                ->doZ()  // this is still the first method argument
        );
}

doError(
    404, // status code
    'Not Found', // error name
    'Check your id' // fix
);

// @codingStandardsChangeSetting PEAR.Functions.FunctionCallSignature allowMultipleArguments true

// Don't report errors for closing braces. Leave that to other sniffs.
foo(
    [
        'this',
        'is',
        'an',
        'array'
    ],
[
        'this',
        'is',
        'an',
        'array'
     ],
    array(
        'this',
        'is',
        'an',
        'array'
    ),
    array(
        'this',
        'is',
        'an',
        'array'
     ),
    function($x)
    {
         return trim($x);
   }
);

function foo()
{
    myFunction(
        'string'.
        // comment
        // comment 
        'string'.
        /* comment
         * comment
        */
        'string'.
    );
}
?>
<?php
/**
 * Unit test class for the FunctionCallSignature sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the FunctionCallSignature sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Tests_Functions_FunctionCallSignatureUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                5   => 1,
                6   => 1,
                7   => 1,
                8   => 1,
                9   => 2,
                10  => 3,
                17  => 1,
                18  => 1,
                31  => 1,
                34  => 1,
                43  => 1,
                57  => 1,
                59  => 1,
                63  => 1,
                64  => 1,
                82  => 1,
                93  => 1,
                100 => 1,
                106 => 1,
                119 => 1,
                120 => 1,
                129 => 1,
                137 => 1,
                142 => 2,
                171 => 1,
                203 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the ControlSignature sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ControlSignature sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Tests_ControlStructures_ControlSignatureUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                9   => 1,
                14  => 1,
                20  => 1,
                22  => 1,
                32  => 1,
                36  => 1,
                44  => 1,
                48  => 1,
                56  => 1,
                60  => 1,
                68  => 1,
                72  => 1,
                84  => 1,
                88  => 2,
                100 => 1,
                104 => 2,
                122 => 2,
                128 => 1,
                132 => 3,
                133 => 2,
                147 => 1,
                157 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the MultiLineCondition sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the MultiLineCondition sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Tests_ControlStructures_MultiLineConditionUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                22  => 1,
                35  => 1,
                40  => 1,
                41  => 1,
                42  => 1,
                43  => 1,
                49  => 1,
                54  => 1,
                58  => 1,
                59  => 1,
                61  => 1,
                88  => 1,
                89  => 1,
                90  => 1,
                96  => 2,
                109 => 2,
                125 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php if (isset($param)) { ?>
   <h3>some text</h3>
<?php }

if (($condition1
    || $condition2)
    && $condition3
    && $condition4
    && $condition5
) {
}

if (($condition1 || $condition2) && $condition3 && $condition4 && $condition5) {
}

if (($condition1 || $condition2)
    && $condition3
) {
}

if (
    ($condition1 || $condition2)
    && $condition3
) {
}

if (($condition1
    || $condition2)
) {
}

if (($condition1
    || $condition2)
    && $condition3 &&
    $condition4
) {
}

if (($condition1
   || $condition2)
   && $condition3
   && $condition4
   && $condition5
) {
}

if (($condition1
    || $condition2)
)  {
}

if (($condition1
    || $condition2)
 ) {
}

if (
    (
    $condition1
    || $condition2
    )
    && $condition3
) {
}


if (   $condition1
    || $condition2
    || $condition3
) {
}

if ($condition1
    || $condition2
    || $condition3
) {
} else if ($condition1
    || $condition2
    || $condition3
) {
}

if ($condition1
    || $condition2
    || $condition3
) {
} elseif (
    $condition1
   || $condition2 &&
    $condition3
) {
}

if ($condition1
    || $condition2
|| $condition3) {
}

if ($condition1
    || $condition2 || $condition3
) {
}

if ($condition1)
    echo 'bar';

if ($condition1
    || $condition2
|| $condition3)
    echo 'bar';


if ($condition1
    || $condition2 || $condition3
)
    echo 'bar';

if (!empty($post)
    && (!empty($context['header'])
    xor stripos($context['header'], 'Content-Type'))
) { 
// ...
}

if ($foo)
{
    echo 'bar';
}

// Should be no errors even though lines are
// not exactly aligned together. Multi-line function
// call takes precedence.
if (array_key_exists($key, $value)
    && array_key_exists(
        $key, $value2
    )
) {
}

if (true) :
    $foo = true;
endif;
?>
<?php

// do ... while
$i = 0;
do {
    echo $i;
} while ($i > 0);

do
{
    echo $i;
} while ($i > 0);

do
{
    echo $i;
}
while ($i > 0);

do { echo $i; } while ($i > 0);

do{
    echo $i;
}while($i > 0);


// while
while ($i < 1) {
    echo $i;
}

while($i < 1){
    echo $i;
}

while ($i < 1) { echo $i; }


// for
for ($i = 1; $i < 1; $i++) {
    echo $i;
}

for($i = 1; $i < 1; $i++){
    echo $i;
}

for ($i = 1; $i < 1; $i++) { echo $i; }


// foreach
foreach ($items as $item) {
    echo $item;
}

foreach($items as $item){
    echo $item;
}

for ($items as $item) { echo $item; }


// if
if ($i == 0) {
    $i = 1;
}

if($i == 0){
    $i = 1;
}

if ($i == 0) { $i = 1; }


// else
if ($i == 0) {
    $i = 1;
} else {
    $i = 0;
}

if ($i == 0) {
    $i = 1;
}else{
    $i = 0;
}

if ($i == 0) { $i = 1; } else { $i = 0; }


// else
if ($i == 0) {
    $i = 1;
} else {
    $i = 0;
}

if ($i == 0) {
    $i = 1;
}else{
    $i = 0;
}

if ($i == 0) { $i = 1; } else { $i = 0; }


// else if
if ($i == 0) {
    $i = 1;
} else if ($i == 2) {
    $i = 0;
}

if ($i == 0) {
    $i = 1;
} elseif ($i == 2) {
    $i = 0;
}

if ($i == 0) {
    $i = 1;
}else if($i == 2){
    $i = 0;
}

if ($i == 0) {
    $i = 1;
}elseif($i == 2){
    $i = 0;
}

if ($i == 0) { $i = 1; } else if ($i == 2) { $i = 0; }
if ($i == 0) { $i = 1; } elseif ($1 == 2) { $i = 0; }

if ($i == 0) { // this is ok because comments are allowed
    $i = 1;
}

if ($i == 0) {// this is ok because comments are allowed
    $i = 1;
}

if ($i == 0) { /* this is ok because comments are allowed*/
    $i = 1;
}

if ($i == 0)
{ // this is not ok
    $i = 1;
}

if ($i == 0) /* this is ok */ {
}

if ($i == 0) {
}
else {
}
?><?php
define('OK', 1);

class No_Comment
{

}//end class


//
// Sample class comment
//
//
//
class Invalid_Comment_Style1
{

}//end class


/**
 *
 *
 * Sample class comment
 *
 *
 * Long description with extra blank line before and after
 *
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: 1.0
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Extra_Description_Newlines
{

}//end class


/**
 * Sample class comment
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Missing_Newlines_Before_Tags
{

}//end class


/**
 * Simple class comment
 *
 * @category   _wrong_category
 * @package    PHP_CodeSniffer
 * @package    ADDITIONAL PACKAGE TAG
 * @subpackage SUBPACKAGE TAG
 * @author     Original Author <author@example.com>
 * @author       Greg Sherwood gsherwood@squiz.net
 * @author     Mr T <t@squiz.net>
 * @author
 * @copyright  1997~1994 The PHP Group
 * @license    http://www.php.net/license/3_0.txt
 * @version    INVALID VERSION CONTENT
 * @see
 * @see
 * @link       sdfsdf
 * @see        Net_Sample::Net_Sample()
 * @see        Net_Other
 * @deprecated asd
 * @unknown    Unknown tag
 * @since      Class available since Release 1.2.0
 */
class Checking_Tags
{
    class Sub_Class {

    }//end class


}//end class


/**
 *
 *
 */
class Empty_Class_Doc
{

}//end class


/**
 *
 *
 */
interface Empty_Interface_Doc
{

}//end interface
?>
<?php
/**
 * Unit test class for ClassCommentSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for ClassCommentSniff.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Tests_Commenting_ClassCommentUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                4   => 1,
                15  => 1,
                22  => 1,
                25  => 1,
                28  => 1,
                46  => 1,
                51  => 1,
                63  => 1,
                65  => 2,
                66  => 1,
                68  => 2,
                70  => 1,
                71  => 1,
                72  => 1,
                74  => 2,
                75  => 1,
                77  => 1,
                78  => 1,
                79  => 1,
                85  => 1,
                93  => 1,
                103 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                71 => 1,
                73 => 1,
               );

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for FunctionCommentSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for FunctionCommentSniff.
 *
 * Verifies that :
 * <ul>
 *  <li>A doc comment exists.</li>
 *  <li>Short description must start with a capital letter and end with a period.</li>
 *  <li>There must be one blank newline after the short description.</li>
 *  <li>A PHP version is specified.</li>
 *  <li>Check the order of the tags.</li>
 *  <li>Check the indentation of each tag.</li>
 *  <li>Check required and optional tags and the format of their content.</li>
 * </ul>
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Tests_Commenting_FileCommentUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                6  => 1,
                8  => 1,
                21 => 2,
                23 => 2,
                24 => 1,
                26 => 2,
                28 => 1,
                29 => 1,
                30 => 1,
                31 => 1,
                32 => 2,
                33 => 1,
                35 => 1,
                36 => 1,
                37 => 1,
                40 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                29 => 1,
                30 => 1,
                34 => 1,
                40 => 1,
               );

    }//end getWarningList()


}//end class

?>
<?php
declare(encoding='utf-8');
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

/**
*
* Short description for fileasdasd.
*
*
* asdasd
* long description for file (if any)
* asdasdadada
*
* PHP versio
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt.  If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
* @category   _wrong_category
* @package    PHP_CodeSniffer
* @package    ADDITIONAL PACKAGE TAG
* @subpackage SUBPACKAGE TAG
* @author     Antônio Carlos Venâncio Júnior <foreign@character.net>
* @author       Greg Sherwood gsherwood@squiz.net
* @author     Mr T <t@squiz.net>
* @author
* @copyright  1997~1994 The PHP Group
* @copyright  1997~1994 The PHP Group
* @license    http://www.php.net/license/3_0.txt
* @see
* @see
* @version    INVALID VERSION CONTENT
* @see        Net_Sample::Net_Sample()
* @see        Net_Other
* @deprecated asd
* @since      Class available since Release 1.2.0
* @summary    An unknown summary tag
*/
?>
<?php
/**
* This bit here is not qualified as file comment
*
* as it is not after the first open tag
*
*/
?>
<?php
class PHP_CodeSniffer_File
{

    /**
     * A simple function comment.
     *
     * long desc here
     *
     * @param int $stackPtr   The position in @ @unknown the stack of the token
     *                        that opened the scope
     * @param int $detph    How many scope levels down we are.
     * @param int    $index    The index
     * @return
     * @throws
     */
    private function _functionCall($stackPtr, $depth=1, $index)
    {
        return $stackPtr;

    }//end _functionCall()

    //
    // Sample function comment
    //
    //
    //
    public function invalidCommentStyle()
    {

    }//end invalidCommentStyle()


    /**
     *
     *
     * A simple function comment
     *
     *
     * Long description with extra blank line before and after
     *
     *
     * @return void
     */
    public function extraDescriptionNewlines()
    {

    }//end extraDescriptionNewlines()


    /**
     * A simple function comment
     * @return void
     */
    public function missingNewlinesBeforeTags()
    {

    }//end missingNewlinesBeforeTags()


    /**
     * Access tag should not be treated as a long description
     *
     * @access public
     * @return void
     */
    public function accessTag()
    {

    }//end accessTag()

    /**
     * Constructor
     *
     * No return tag
     */
    function PHP_CodeSniffer_File()
    {
        return;
    }


    /**
     * Destructor
     *
     * No return tag too
     */
    function _PHP_CodeSniffer_File()
    {
        return;
    }


    /**
     * Destructor PHP5
     */
    function __destruct()
    {
        return;
    }


    function missingComment()
    {
        return;
    }


    /**
     * no return tag
     *
     */
    public function noReturn($one)
    {

    }//end noReturn()


    /**
     * Param not immediate
     *
     * @return
     * @param   int   $threeSpaces
     * @param int     $superfluous
     * @param missing
     * @param
     */
    public function missingDescroption($threeSpaces)
    {

    }//end missingDescroption()


    /**
     * Param not immediate
     *
     * @param int      $one   comment
     * @param int      $two   comment
     * @param string   $three comment
     *
     * @return void
     */
    public function oneSpaceAfterLongestVar($one, $two, $three)
    {

    }//end oneSpaceAfterLongestVar()


}//end class


/**
 * A simple function comment
 *
 * @param string $str The string passed in by reference
 *
 * @return void
 */
public function functionOutsideClass(&$str)
{
    return;
}//end functionOutsideClass()


function missingCommentOutsideClass()
{
    return;
}//end missingCommentOutsideClass()


?><?php
function tagBeforeComment()
{
    return;
}//end tagBeforeComment()


/**
 * no return tag
 *
 *
 *
 */
public function noReturnOutsideClass()
{

}//end noReturnOutsideClass()


/**
 * Missing param comment
 *
 * @param int $one comment
 *
 * @return void
 * @fine  Unknown tag
 */
public function missingTwoParamComment($one, $two, $three)
{

}//end missingTwoParamComment()


/**
 *
 */
function emptyFunctionDocComment()
{
}//end emptyFunctionDocComment()


/**
 * Test function.
 *
 * @param string $arg1 An argument
 *
 * @access public
 * @return bool
 */
function myFunction($arg1) {}


/**
 * Test function.
 *
 * @param string $arg1 An argument
 *
 * @access public
 * @return bool
 */

echo $blah;

function myFunction($arg1) {}

/**
 * Test function.
 *
 * @access public
 * @return bool
 * @throws MyException
 * @throws MyException When I feel like it
 */
function myFunction() {}

class MyClass() {
    /**
     * An abstract function.
     *
     * @return array(string)
     */
    abstract final protected function myFunction();
}
?>
<?php
/**
 * Unit test class for the InlineComment sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the InlineComment sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Tests_Commenting_InlineCommentUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                15 => 1,
                24 => 1,
                25 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for FunctionCommentSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for FunctionCommentSniff.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Tests_Commenting_FunctionCommentUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                10  => 1,
                12  => 2,
                13  => 2,
                14  => 1,
                15  => 1,
                28  => 1,
                35  => 1,
                38  => 1,
                41  => 1,
                53  => 1,
                103 => 1,
                109 => 1,
                112 => 1,
                122 => 1,
                123 => 3,
                124 => 3,
                125 => 4,
                126 => 6,
                139 => 1,
                155 => 1,
                165 => 1,
                172 => 1,
                183 => 1,
                193 => 2,
                204 => 1,
                234 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php

// Some code goes here.

// This comment contains # multiple
// hash signs (#).

/*
 * Here is a small function comment.
 */
function test()
{
    // Some code goes here.

    # This comment is banned.

}//end test()

/*
    A longer comment goes here.
    It spans multiple lines.
*/

# This is a long comment
# that is banned.

?><?php

// These are statements and should not have brackets.
require_once('blank.inc');
require('blank.inc');

$test = true;

// Conditionally including a class file: use include_once
if ($test) {
    require_once 'blank.inc';
    require 'blank.inc';
}

// Unconditionally including a class file: use require_once
include_once 'blank.inc';
include 'blank.inc';


// These are ok
if ($test) {
    include_once 'blank.inc';
    include 'blank.inc';
}

require_once 'blank.inc';
require 'blank.inc';

?>
<pre>
Some content goes here.
<?php
include_once 'blank.inc';
include 'blank.inc';
require_once 'blank.inc';
require 'blank.inc';
?>
</pre>
<?php

if (include_once 'blank.inc') {
    $var = include_once 'blank.inc';
    if ($var === true) {
    }
}

if (require_once 'blank.inc') {
    $var = require_once 'blank.inc';
    if ($var === true) {
    }
}

function get_some_value()
{
    include_once 'blank.inc';
    include 'blank.inc';

    // These are ok
    if ($test) {
        include_once 'blank.inc';
        include 'blank.inc';
    }

    require_once 'blank.inc';
    require 'blank.inc';

    ?>
    <pre>
    Some content goes here.
    <?php
    include_once 'blank.inc';
    include 'blank.inc';
    require_once 'blank.inc';
    require 'blank.inc';
    ?>
    </pre>
    <?php

    if (include_once 'blank.inc') {
        $var = include_once 'blank.inc';
        if ($var === true) {
        }
    }
    
    if (require_once 'blank.inc') {
        $var = require_once 'blank.inc';
        if ($var === true) {
        }
    }
}


$var = include_once 'blank.inc';
if ($var == false) {

}

?>
<?php
/**
 * Unit test class for the IncludingFile sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the IncludingFile sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Tests_Files_IncludingFileUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                4  => 1,
                5  => 1,
                11 => 1,
                12 => 1,
                16 => 1,
                17 => 1,
                33 => 1,
                34 => 1,
                47 => 1,
                48 => 1,
                64 => 1,
                65 => 1,
                73 => 1,
                74 => 1,
                85 => 1,
                86 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
/**
 * Unit test class for the MultiLineAssignment sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the MultiLineAssignment sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Tests_Formatting_MultiLineAssignmentUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                3 => 1,
                6 => 1,
                8 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php
$GLOBALS['TSFE']->additionalHeaderData[$this->strApplicationName]
     = $this->xajax->getJavascript(t3lib_extMgm::siteRelPath('nr_xajax'));

$GLOBALS['TSFE']->additionalHeaderData[$this->strApplicationName]
   = $this->xajax->getJavascript(t3lib_extMgm::siteRelPath('nr_xajax'));

$GLOBALS['TSFE']->additionalHeaderData[$this->strApplicationName] = 
    $this->xajax->getJavascript(t3lib_extMgm::siteRelPath('nr_xajax'));

$GLOBALS['TSFE']->additionalHeaderData[$this->strApplicationName]
    = $this->xajax->getJavascript(t3lib_extMgm::siteRelPath('nr_xajax'));
$GLOBALS['TSFE']->additionalHeaderData[$this->strApplicationName] = 'boo'

$var='string';

function getInstalledStandards(
    $includeGeneric=false,
    $standardsDir=''
) {
}
?>
<?php
/**
 * Unit test class for the ClassDeclaration sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ClassDeclaration sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PEAR_Tests_Classes_ClassDeclarationUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                21 => 1,
                22 => 1,
                23 => 1,
                27 => 1,
                33 => 1,
                38 => 1,
                49 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?php

//  Correct declarations.
class CorrectClassDeclaration
{

}

abstract class CorrectClassDeclarationWithExtends extends correctClassDeclaration
{

}

final class CorrectClassDeclarationWithImplements implements correctClassDeclaration
{

}


// Incorrect placement of opening braces
class IncorrectBracePlacement {}
class IncorrectBracePlacementWithExtends extends correctClassDeclaration {}
class IncorrectBracePlacementWithImplements implements correctClassDeclaration {}

// Incorrect code placement for opening brace.
class IncorrectCodeAfterOpeningBrace
{ echo phpinfo();

}//end class

class IncorrectClassDeclarationWithExtends extends correctClassDeclaration

{

}

class IncorrectBracePlacement
 {
 }

abstract class CodeSnifferFail
    extends
        ArrayObject
    implements
        Serializable,
        Iterator,
        Countable,
        OuterIterator,
        RecursiveIterator {
}

abstract class CodeSnifferFail
    extends
        ArrayObject
    implements
        Serializable,
        Iterator,
        Countable,
        OuterIterator,
        RecursiveIterator
{
}

namespace A
{
    class B
    {
    }
}

?><?xml version="1.0"?>
<ruleset name="PEAR">
 <description>The PEAR coding standard.</description>

 <!-- Include some additional sniffs from the Generic standard -->
 <rule ref="Generic.Functions.FunctionCallArgumentSpacing"/>
 <rule ref="Generic.NamingConventions.UpperCaseConstantName"/>
 <rule ref="Generic.PHP.LowerCaseConstant"/>
 <rule ref="Generic.PHP.DisallowShortOpenTag"/>
 <rule ref="Generic.WhiteSpace.DisallowTabIndent"/>

 <!-- Lines can be 85 chars long, but never show errors -->
 <rule ref="Generic.Files.LineLength">
  <properties>
   <property name="lineLimit" value="85"/>
   <property name="absoluteLineLimit" value="0"/>
  </properties>
 </rule>

 <!-- Use Unix newlines -->
 <rule ref="Generic.Files.LineEndings">
  <properties>
   <property name="eolChar" value="\n"/>
  </properties>
 </rule>

 <!-- This message is not required as spaces are allowed for alignment -->
 <rule ref="Generic.Functions.FunctionCallArgumentSpacing.TooMuchSpaceAfterComma">
  <severity>0</severity>
 </rule>

 <!-- Use warnings for inline control structures -->
 <rule ref="Generic.ControlStructures.InlineControlStructure">
  <properties>
   <property name="error" value="false"/>
  </properties>
 </rule>

</ruleset>
<?php
/**
 * Zend_Sniffs_Debug_CodeAnalyzerSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Holger Kral <holger.kral@zend.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Zend_Sniffs_Debug_CodeAnalyzerSniff.
 *
 * Runs the Zend Code Analyzer (from Zend Studio) on the file.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Holger Kral <holger.kral@zend.com>
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Zend_Sniffs_Debug_CodeAnalyzerSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns the token types that this sniff is interested in.
     *
     * @return array(int)
     */
    public function register()
    {
        return array(T_OPEN_TAG);

    }//end register()


    /**
     * Processes the tokens that this sniff is interested in.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
     * @param int                  $stackPtr  The position in the stack where
     *                                        the token was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        // Because we are analyzing the whole file in one step, execute this method
        // only on first occurrence of a T_OPEN_TAG.
        $prevOpenTag = $phpcsFile->findPrevious(T_OPEN_TAG, ($stackPtr - 1));
        if ($prevOpenTag !== false) {
            return;
        }

        $fileName = $phpcsFile->getFilename();

        $analyzerPath = PHP_CodeSniffer::getConfigData('zend_ca_path');
        if (is_null($analyzerPath) === true) {
            return;
        }

        // In the command, 2>&1 is important because the code analyzer sends its
        // findings to stderr. $output normally contains only stdout, so using 2>&1
        // will pipe even stderr to stdout.
        $cmd = $analyzerPath.' '.$fileName.' 2>&1';

        // There is the possibility to pass "--ide" as an option to the analyzer.
        // This would result in an output format which would be easier to parse.
        // The problem here is that no cleartext error messages are returnwd; only
        // error-code-labels. So for a start we go for cleartext output.
        $exitCode = exec($cmd, $output, $retval);

        // $exitCode is the last line of $output if no error occures, on error it
        // is numeric. Try to handle various error conditions and provide useful
        // error reporting.
        if (is_numeric($exitCode) === true && $exitCode > 0) {
            if (is_array($output) === true) {
                $msg = join('\n', $output);
            }

            throw new PHP_CodeSniffer_Exception("Failed invoking ZendCodeAnalyzer, exitcode was [$exitCode], retval was [$retval], output was [$msg]");
        }

        if (is_array($output) === true) {
            $tokens = $phpcsFile->getTokens();

            foreach ($output as $finding) {
                // The first two lines of analyzer output contain
                // something like this:
                // > Zend Code Analyzer 1.2.2
                // > Analyzing <filename>...
                // So skip these...
                $res = preg_match("/^.+\(line ([0-9]+)\):(.+)$/", $finding, $regs);
                if (empty($regs) === true || $res === false) {
                    continue;
                }

                // Find the token at the start of the line.
                $lineToken = null;
                foreach ($tokens as $ptr => $info) {
                    if ($info['line'] == $regs[1]) {
                        $lineToken = $ptr;
                        break;
                    }
                }

                if ($lineToken !== null) {
                    $phpcsFile->addWarning(trim($regs[2]), $ptr, 'ExternalTool');
                }
            }//end foreach
        }//end if

    }//end process()

}//end class
?>
<?php
/**
 * Squiz_Sniffs_NamingConventions_ValidVariableNameSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_Standards_AbstractVariableSniff', true) === false) {
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_Standards_AbstractVariableSniff not found');
}

/**
 * Squiz_Sniffs_NamingConventions_ValidVariableNameSniff.
 *
 * Checks the naming of variables and member variables.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Zend_Sniffs_NamingConventions_ValidVariableNameSniff extends PHP_CodeSniffer_Standards_AbstractVariableSniff
{

    /**
     * Tokens to ignore so that we can find a DOUBLE_COLON.
     *
     * @var array
     */
    private $_ignore = array(
                        T_WHITESPACE,
                        T_COMMENT,
                       );


    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    protected function processVariable(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens  = $phpcsFile->getTokens();
        $varName = ltrim($tokens[$stackPtr]['content'], '$');

        $phpReservedVars = array(
                            '_SERVER',
                            '_GET',
                            '_POST',
                            '_REQUEST',
                            '_SESSION',
                            '_ENV',
                            '_COOKIE',
                            '_FILES',
                            'GLOBALS',
                           );

        // If it's a php reserved var, then its ok.
        if (in_array($varName, $phpReservedVars) === true) {
            return;
        }

        $objOperator = $phpcsFile->findNext(array(T_WHITESPACE), ($stackPtr + 1), null, true);
        if ($tokens[$objOperator]['code'] === T_OBJECT_OPERATOR) {
            // Check to see if we are using a variable from an object.
            $var = $phpcsFile->findNext(array(T_WHITESPACE), ($objOperator + 1), null, true);
            if ($tokens[$var]['code'] === T_STRING) {
                // Either a var name or a function call, so check for bracket.
                $bracket = $phpcsFile->findNext(array(T_WHITESPACE), ($var + 1), null, true);

                if ($tokens[$bracket]['code'] !== T_OPEN_PARENTHESIS) {
                    $objVarName = $tokens[$var]['content'];

                    // There is no way for us to know if the var is public or private,
                    // so we have to ignore a leading underscore if there is one and just
                    // check the main part of the variable name.
                    $originalVarName = $objVarName;
                    if (substr($objVarName, 0, 1) === '_') {
                        $objVarName = substr($objVarName, 1);
                    }

                    if (PHP_CodeSniffer::isCamelCaps($objVarName, false, true, false) === false) {
                        $error = 'Variable "%s" is not in valid camel caps format';
                        $data  = array($originalVarName);
                        $phpcsFile->addError($error, $var, 'NotCamelCaps', $data);
                    } else if (preg_match('|\d|', $objVarName)) {
                        $warning = 'Variable "%s" contains numbers but this is discouraged';
                        $data    = array($originalVarName);
                        $phpcsFile->addWarning($warning, $stackPtr, 'ContainsNumbers', $data);
                    }
                }//end if
            }//end if
        }//end if

        // There is no way for us to know if the var is public or private,
        // so we have to ignore a leading underscore if there is one and just
        // check the main part of the variable name.
        $originalVarName = $varName;
        if (substr($varName, 0, 1) === '_') {
            $objOperator = $phpcsFile->findPrevious(array(T_WHITESPACE), ($stackPtr - 1), null, true);
            if ($tokens[$objOperator]['code'] === T_DOUBLE_COLON) {
                // The variable lives within a class, and is referenced like
                // this: MyClass::$_variable, so we don't know its scope.
                $inClass = true;
            } else {
                $inClass = $phpcsFile->hasCondition($stackPtr, array(T_CLASS, T_INTERFACE));
            }

            if ($inClass === true) {
                $varName = substr($varName, 1);
            }
        }

        if (PHP_CodeSniffer::isCamelCaps($varName, false, true, false) === false) {
            $error = 'Variable "%s" is not in valid camel caps format';
            $data  = array($originalVarName);
            $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $data);
        } else if (preg_match('|\d|', $varName)) {
            $warning = 'Variable "%s" contains numbers but this is discouraged';
            $data    = array($originalVarName);
            $phpcsFile->addWarning($warning, $stackPtr, 'ContainsNumbers', $data);
        }

    }//end processVariable()


    /**
     * Processes class member variables.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    protected function processMemberVar(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens      = $phpcsFile->getTokens();
        $varName     = ltrim($tokens[$stackPtr]['content'], '$');
        $memberProps = $phpcsFile->getMemberProperties($stackPtr);
        $public      = ($memberProps['scope'] === 'public');

        if ($public === true) {
            if (substr($varName, 0, 1) === '_') {
                $error = 'Public member variable "%s" must not contain a leading underscore';
                $data  = array($varName);
                $phpcsFile->addError($error, $stackPtr, 'PublicHasUnderscore', $data);
                return;
            }
        } else {
            if (substr($varName, 0, 1) !== '_') {
                $scope = ucfirst($memberProps['scope']);
                $error = '%s member variable "%s" must contain a leading underscore';
                $data  = array(
                          $scope,
                          $varName,
                         );
                $phpcsFile->addError($error, $stackPtr, 'PrivateNoUnderscore', $data);
                return;
            }
        }

        if (PHP_CodeSniffer::isCamelCaps($varName, false, $public, false) === false) {
            $error = 'Variable "%s" is not in valid camel caps format';
            $data  = array($varName);
            $phpcsFile->addError($error, $stackPtr, 'MemberVarNotCamelCaps', $data);
        } else if (preg_match('|\d|', $varName)) {
            $warning = 'Variable "%s" contains numbers but this is discouraged';
            $data    = array($varName);
            $phpcsFile->addWarning($warning, $stackPtr, 'MemberVarContainsNumbers', $data);
        }

    }//end processMemberVar()


    /**
     * Processes the variable found within a double quoted string.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the double quoted
     *                                        string.
     *
     * @return void
     */
    protected function processVariableInString(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $phpReservedVars = array(
                            '_SERVER',
                            '_GET',
                            '_POST',
                            '_REQUEST',
                            '_SESSION',
                            '_ENV',
                            '_COOKIE',
                            '_FILES',
                            'GLOBALS',
                           );

        if (preg_match_all('|[^\\\]\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)|', $tokens[$stackPtr]['content'], $matches) !== 0) {
            foreach ($matches[1] as $varName) {
                // If it's a php reserved var, then its ok.
                if (in_array($varName, $phpReservedVars) === true) {
                    continue;
                }

                // There is no way for us to know if the var is public or private,
                // so we have to ignore a leading underscore if there is one and just
                // check the main part of the variable name.
                $originalVarName = $varName;
                if (substr($varName, 0, 1) === '_') {
                    if ($phpcsFile->hasCondition($stackPtr, array(T_CLASS, T_INTERFACE)) === true) {
                        $varName = substr($varName, 1);
                    }
                }

                if (PHP_CodeSniffer::isCamelCaps($varName, false, true, false) === false) {
                    $varName = $matches[0];
                    $error   = 'Variable "%s" is not in valid camel caps format';
                    $data    = array($originalVarName);
                    $phpcsFile->addError($error, $stackPtr, 'StringVarNotCamelCaps', $data);
                } else if (preg_match('|\d|', $varName)) {
                    $warning = 'Variable "%s" contains numbers but this is discouraged';
                    $data    = array($originalVarName);
                    $phpcsFile->addWarning($warning, $stackPtr, 'StringVarContainsNumbers', $data);
                }
            }
        }//end if

    }//end processVariableInString()


}//end class

?>
<?php
/**
 * Zend_Sniffs_Files_ClosingTagsSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Zend_Sniffs_Files_LineEndingsSniff.
 *
 * Checks that the file does not end with a closing tag.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Zend_Sniffs_Files_ClosingTagSniff implements PHP_CodeSniffer_Sniff
{


    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_CLOSE_TAG);

    }//end register()


    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in
     *                                        the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $next = $phpcsFile->findNext(T_INLINE_HTML, ($stackPtr + 1), null, true);
        if ($next !== false) {
            return;
        }

        // We've found the last closing tag in the file so the only thing
        // potentially remaining is inline HTML. Now we need to figure out
        // whether or not it's just a bunch of whitespace.
        $content = '';
        for ($i = ($stackPtr + 1); $i < $phpcsFile->numTokens; $i++) {
            $content .= $tokens[$i]['content'];
        }

        // Check if the remaining inline HTML is just whitespace.
        $content = trim($content);
        if (empty($content) === true) {
            $error = 'A closing tag is not permitted at the end of a PHP file';
            $phpcsFile->addError($error, $stackPtr, 'NotAllowed');
        }

    }//end process()


}//end class

?>
<documentation title="Zend Code Analyzer">
    <standard>
    <![CDATA[
    PHP Code should pass the zend code analyzer.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: Valid PHP Code.">
        <![CDATA[
function foo($bar, $baz)
{
    return <em>$bar + $baz</em>;
}
        ]]>
        </code>
        <code title="Invalid: There is an unused function parameter.">
        <![CDATA[
function foo($bar, $baz)
{
    return <em>$bar + 2</em>;
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Variable Names">
    <standard>
    <![CDATA[
    Variable names should be camelCased with the first letter lowercase.  Private and protected member variables should begin with an underscore
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: A multi-word variable uses camel casing.">
        <![CDATA[
<em>$testNumber</em> = 1;
        ]]>
        </code>
        <code title="Invalid: A multi-word variable uses underscores and initial capitalization.">
        <![CDATA[
<em>$Test_Number</em> = 1;
        ]]>
        </code>
    </code_comparison>
    <code_comparison>
        <code title="Valid: A private member variable begins with an underscore.">
        <![CDATA[
class Foo
{
    private $<em>_</em>bar;
}
        ]]>
        </code>
        <code title="Invalid: A private member variable does not begin with an underscore.">
        <![CDATA[
class Foo
{
    private $bar;
}
        ]]>
        </code>
    </code_comparison>
</documentation>
<documentation title="Closing PHP Tags">
    <standard>
    <![CDATA[
    Files should not have closing php tags.
    ]]>
    </standard>
    <code_comparison>
        <code title="Valid: No closing tag at the end of the file.">
        <![CDATA[
<?php
$var = 1;
        ]]>
        </code>
        <code title="Invalid: A closing php tag is included at the end of the file.">
        <![CDATA[
<?php
$var = 1;
<em>?></em>
        ]]>
        </code>
    </code_comparison>
</documentation>
<?php
/**
 * Unit test class for the CodeAnalyzer sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the CodeAnalyzer sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Zend_Tests_Debug_CodeAnalyzerUnitTest extends AbstractSniffUnitTest
{


    /**
     * Should this test be skipped for some reason.
     *
     * @return void
     */
    protected function shouldSkipTest()
    {
        $analyzerPath = PHP_CodeSniffer::getConfigData('zend_ca_path');
        return (is_null($analyzerPath));

    }//end shouldSkipTest()


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array();

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                2 => 1,
               );

    }//end getWarningList()


}//end class

?>
<?php
function myFunction($variable) {
    // $variable is unused.
    echo 'hi';
}
?>
<?php
/**
 * Unit test class for the ValidVariableName sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ValidVariableName sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Zend_Tests_NamingConventions_ValidVariableNameUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                3  => 1,
                5  => 1,
                11 => 1,
                13 => 1,
                17 => 1,
                19 => 1,
                23 => 1,
                25 => 1,
                29 => 1,
                31 => 1,
                36 => 1,
                38 => 1,
                42 => 1,
                44 => 1,
                48 => 1,
                50 => 1,
                61 => 1,
                67 => 1,
                72 => 1,
                74 => 1,
                75 => 1,
                76 => 1,
                79 => 1,
                96 => 1,
                99 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array(
                6  => 1,
                14 => 1,
                20 => 1,
                26 => 1,
                32 => 1,
                39 => 1,
                45 => 1,
                51 => 1,
                64 => 1,
                70 => 1,
                73 => 1,
                76 => 1,
                79 => 1,
                82 => 1,
                94 => 1,
               );

    }//end getWarningList()


}//end class

?>
<?php
$varName  = 'hello';
$var_name = 'hello';
$varname  = 'hello';
$_varName = 'hello';
$varname2 = 'hello';

class MyClass
{
    $varName  = 'hello';
    $var_name = 'hello';
    $varname  = 'hello';
    $_varName = 'hello';
    $varName2 = 'hello';

    public $varName  = 'hello';
    public $var_name = 'hello';
    public $varname  = 'hello';
    public $_varName = 'hello';
    public $varName2 = 'hello';

    protected $_varName  = 'hello';
    protected $_var_name = 'hello';
    protected $_varname  = 'hello';
    protected $varName   = 'hello';
    protected $_varName2 = 'hello';

    private $_varName  = 'hello';
    private $_var_name = 'hello';
    private $_varname  = 'hello';
    private $varName   = 'hello';
    private $_varName2 = 'hello';
}

echo $varName;
echo $var_name;
echo $varname;
echo $_varName;
echo $varName2;

echo "Hello $varName";
echo "Hello $var_name";
echo "Hello $varname";
echo "Hello $_varName";
echo "Hello $varName2";

echo 'Hello '.$varName;
echo 'Hello '.$var_name;
echo 'Hello '.$varname;
echo 'Hello '.$_varName;
echo 'Hello '.$varName2;

echo $_SERVER['var_name'];
echo $_REQUEST['var_name'];
echo $_GET['var_name'];
echo $_POST['var_name'];
echo $GLOBALS['var_name'];
echo $GLOBALS['var_name2'];

echo MyClass::$varName;
echo MyClass::$var_name;
echo MyClass::$varname;
echo MyClass::$_varName;
echo MyClass::$varName2;

echo $this->varName;
echo $this->var_name;
echo $this->varname;
echo $this->_varName;
echo $this->varName2;
echo $object->varName;
echo $object->var_name;
echo $object->varName2;
echo $object_name->varname;
echo $object_name->_varName;
echo $object_name->varName2;

echo $this->myFunction($one, $two);
echo $object->myFunction($one_two, $var2);

$error = "format is \$GLOBALS['$varName']";
$error = "format is \$GLOBALS['$varName2']";

echo $_SESSION['var_name'];
echo $_FILES['var_name'];
echo $_ENV['var_name'];
echo $_COOKIE['var_name'];
echo $_COOKIE['var_name2'];

$XML        = 'hello';
$myXML      = 'hello';
$XMLParser  = 'hello';
$xmlParser  = 'hello';
$xmlParser2 = 'hello';

echo "{$_SERVER['HOSTNAME']} $var_name";

$someObject->{$name};
$someObject->my_function($var_name);
?>
<?php

echo 'hi';

?>

<?php

echo 'bye';

?>

<?php
/**
 * Unit test class for the ClosingTag sniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Unit test class for the ClosingTag sniff.
 *
 * A sniff unit test checks a .inc file for expected violations of a single
 * coding standard. Expected errors and warnings are stored in this class.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Zend_Tests_Files_ClosingTagUnitTest extends AbstractSniffUnitTest
{


    /**
     * Returns the lines where errors should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of errors that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getErrorList()
    {
        return array(
                11 => 1,
               );

    }//end getErrorList()


    /**
     * Returns the lines where warnings should occur.
     *
     * The key of the array should represent the line number and the value
     * should represent the number of warnings that should occur on that line.
     *
     * @return array(int => int)
     */
    public function getWarningList()
    {
        return array();

    }//end getWarningList()


}//end class

?>
<?xml version="1.0"?>
<ruleset name="Zend">
 <description>A coding standard based on an early Zend Framework coding standard. Note that this standard is out of date.</description>

 <!-- Include some sniffs from all around the place -->
 <rule ref="Generic.Functions.FunctionCallArgumentSpacing"/>
 <rule ref="Generic.Functions.OpeningFunctionBraceBsdAllman"/>
 <rule ref="Generic.PHP.DisallowShortOpenTag"/>
 <rule ref="Generic.WhiteSpace.DisallowTabIndent"/>
 <rule ref="PEAR.Classes.ClassDeclaration"/>
 <rule ref="PEAR.ControlStructures.ControlSignature"/>
 <rule ref="PEAR.Functions.FunctionCallSignature"/>
 <rule ref="PEAR.Functions.ValidDefaultValue"/>
 <rule ref="PEAR.WhiteSpace.ScopeClosingBrace"/>
 <rule ref="Squiz.Functions.GlobalFunction"/>

 <!-- Lines can be 80 chars long, show errors at 120 chars -->
 <rule ref="Generic.Files.LineLength">
  <properties>
   <property name="lineLimit" value="80"/>
   <property name="absoluteLineLimit" value="120"/>
  </properties>
 </rule>

 <!-- Use Unix newlines -->
 <rule ref="Generic.Files.LineEndings">
  <properties>
   <property name="eolChar" value="\n"/>
  </properties>
 </rule>

</ruleset>
<?php
/**
 * An exception thrown if the pattern being processed is not supposed to be
 * validating the code in question.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * An exception thrown if the pattern being processed is not supposed to be
 * validating the code in question.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class PHP_CodeSniffer_Standards_IncorrectPatternException extends Exception
{

}//end class

?>
<?php
/**
 * A class to find T_VARIABLE tokens.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

if (class_exists('PHP_CodeSniffer_Standards_AbstractScopeSniff', true) === false) {
    $error = 'Class PHP_CodeSniffer_Standards_AbstractScopeSniff not found';
    throw new PHP_CodeSniffer_Exception($error);
}

/**
 * A class to find T_VARIABLE tokens.
 *
 * This class can distinguish between normal T_VARIABLE tokens, and those tokens
 * that represent class members. If a class member is encountered, then then
 * processMemberVar method is called so the extending class can process it. If
 * the token is found to be a normal T_VARIABLE token, then processVariable is
 * called.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
abstract class PHP_CodeSniffer_Standards_AbstractVariableSniff extends PHP_CodeSniffer_Standards_AbstractScopeSniff
{

    /**
     * The end token of the current function that we are in.
     *
     * @var int
     */
    private $_endFunction = -1;

    /**
     * true if a function is currently open.
     *
     * @var boolean
     */
    private $_functionOpen = false;

    /**
     * The current PHP_CodeSniffer file that we are processing.
     *
     * @var PHP_CodeSniffer_File
     */
    protected $currentFile = null;


    /**
     * Constructs an AbstractVariableTest.
     */
    public function __construct()
    {
        $scopes = array(
                   T_CLASS,
                   T_INTERFACE,
                  );

        $listen = array(
                   T_FUNCTION,
                   T_VARIABLE,
                   T_DOUBLE_QUOTED_STRING,
                   T_HEREDOC,
                  );

        parent::__construct($scopes, $listen, true);

    }//end __construct()


    /**
     * Processes the token in the specified PHP_CodeSniffer_File.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The PHP_CodeSniffer file where this
     *                                        token was found.
     * @param int                  $stackPtr  The position where the token was found.
     * @param array                $currScope The current scope opener token.
     *
     * @return void
     */
    protected final function processTokenWithinScope(
        PHP_CodeSniffer_File $phpcsFile,
        $stackPtr,
        $currScope
    ) {
        if ($this->currentFile !== $phpcsFile) {
            $this->currentFile   = $phpcsFile;
            $this->_functionOpen = false;
            $this->_endFunction  = -1;
        }

        $tokens = $phpcsFile->getTokens();

        if ($stackPtr > $this->_endFunction) {
            $this->_functionOpen = false;
        }

        if ($tokens[$stackPtr]['code'] === T_FUNCTION
            && $this->_functionOpen === false
        ) {
            $this->_functionOpen = true;

            $methodProps = $phpcsFile->getMethodProperties($stackPtr);

            // If the function is abstract, or is in an interface,
            // then set the end of the function to it's closing semicolon.
            if ($methodProps['is_abstract'] === true
                || $tokens[$currScope]['code'] === T_INTERFACE
            ) {
                $this->_endFunction
                    = $phpcsFile->findNext(array(T_SEMICOLON), $stackPtr);
            } else {
                if (isset($tokens[$stackPtr]['scope_closer']) === false) {
                    $error = 'Possible parse error: non-abstract method defined as abstract';
                    $phpcsFile->addWarning($error, $stackPtr);
                    return;
                }

                $this->_endFunction = $tokens[$stackPtr]['scope_closer'];
            }
        }

        if ($tokens[$stackPtr]['code'] === T_DOUBLE_QUOTED_STRING
            || $tokens[$stackPtr]['code'] === T_HEREDOC
        ) {
            // Check to see if this string has a variable in it.
            $pattern = '|(?<!\\\\)(?:\\\\{2})*\${?[a-zA-Z0-9_]+}?|';
            if (preg_match($pattern, $tokens[$stackPtr]['content']) !== 0) {
                $this->processVariableInString($phpcsFile, $stackPtr);
            }

            return;
        }

        if ($this->_functionOpen === true) {
            if ($tokens[$stackPtr]['code'] === T_VARIABLE) {
                $this->processVariable($phpcsFile, $stackPtr);
            }
        } else {
            // What if we assign a member variable to another?
            // ie. private $_count = $this->_otherCount + 1;.
            $this->processMemberVar($phpcsFile, $stackPtr);
        }

    }//end processTokenWithinScope()


    /**
     * Processes the token outside the scope in the file.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The PHP_CodeSniffer file where this
     *                                        token was found.
     * @param int                  $stackPtr  The position where the token was found.
     *
     * @return void
     */
    protected final function processTokenOutsideScope(
        PHP_CodeSniffer_File $phpcsFile,
        $stackPtr
    ) {
        $tokens = $phpcsFile->getTokens();
        // These variables are not member vars.
        if ($tokens[$stackPtr]['code'] === T_VARIABLE) {
            $this->processVariable($phpcsFile, $stackPtr);
        } else if ($tokens[$stackPtr]['code'] === T_DOUBLE_QUOTED_STRING
            || $tokens[$stackPtr]['code'] === T_HEREDOC
        ) {
            // Check to see if this string has a variable in it.
            $pattern = '|(?<!\\\\)(?:\\\\{2})*\${?[a-zA-Z0-9_]+}?|';
            if (preg_match($pattern, $tokens[$stackPtr]['content']) !== 0) {
                $this->processVariableInString($phpcsFile, $stackPtr);
            }
        }

    }//end processTokenOutsideScope()


    /**
     * Called to process class member vars.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The PHP_CodeSniffer file where this
     *                                        token was found.
     * @param int                  $stackPtr  The position where the token was found.
     *
     * @return void
     */
    abstract protected function processMemberVar(
        PHP_CodeSniffer_File $phpcsFile,
        $stackPtr
    );


    /**
     * Called to process normal member vars.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The PHP_CodeSniffer file where this
     *                                        token was found.
     * @param int                  $stackPtr  The position where the token was found.
     *
     * @return void
     */
    abstract protected function processVariable(
        PHP_CodeSniffer_File $phpcsFile,
        $stackPtr
    );


    /**
     * Called to process variables found in double quoted strings or heredocs.
     *
     * Note that there may be more than one variable in the string, which will
     * result only in one call for the string or one call per line for heredocs.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The PHP_CodeSniffer file where this
     *                                        token was found.
     * @param int                  $stackPtr  The position where the double quoted
     *                                        string was found.
     *
     * @return void
     */
    abstract protected function processVariableInString(
        PHP_CodeSniffer_File
        $phpcsFile,
        $stackPtr
    );


}//end class

?>
<?xml version="1.0"?>
<ruleset name="PHP_CodeSniffer">
 <description>The coding standard for PHP_CodeSniffer itself.</description>
 <exclude-pattern>*/Tests/*</exclude-pattern>

 <!-- Include the whole PEAR standard -->
 <rule ref="PEAR"/>

 <!-- Include most of the Squiz standard -->
 <rule ref="Squiz">
  <exclude name="Squiz.Classes.ClassFileName"/>
  <exclude name="Squiz.Classes.ValidClassName"/>
  <exclude name="Squiz.Commenting.ClassComment"/>
  <exclude name="Squiz.Commenting.FileComment"/>
  <exclude name="Squiz.Commenting.FunctionComment"/>
  <exclude name="Squiz.Commenting.VariableComment"/>
  <exclude name="Squiz.ControlStructures.SwitchDeclaration"/>
  <exclude name="Squiz.Files.FileExtension"/>
  <exclude name="Squiz.NamingConventions.ConstantCase"/>
 </rule>

 <!-- We allow variables to be used inside double quoted strings -->
 <rule ref="Squiz.Strings.DoubleQuoteUsage.ContainsVar">
  <severity>0</severity>
 </rule>

</ruleset>
Copyright (c) 2012, Squiz Pty Ltd (ABN 77 084 670 600)
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of Squiz Pty Ltd nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<?php
 $phpCodeSnifferConfig = array (
  'default_standard' => 'PSR2',
  'report_format' => 'summary',
  'show_warnings' => '0',
  'show_progress' => '1',
  'report_width' => '120',
)
?>
{
    "name": "symfony/property-access",
    "type": "library",
    "description": "Symfony PropertyAccess Component",
    "keywords": ["property", "index", "access", "object", "array", "extraction", "injection", "reflection", "property path"],
    "homepage": "http://symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "http://symfony.com/contributors"
        }
    ],
    "require": {
        "php": ">=5.3.3"
    },
    "autoload": {
        "psr-0": { "Symfony\\Component\\PropertyAccess\\": "" }
    },
    "target-dir": "Symfony/Component/PropertyAccess",
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-master": "2.4-dev"
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\PropertyAccess;

use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
use Symfony\Component\PropertyAccess\Exception\NoSuchIndexException;
use Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException;

/**
 * Default implementation of {@link PropertyAccessorInterface}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class PropertyAccessor implements PropertyAccessorInterface
{
    const VALUE = 0;
    const IS_REF = 1;

    /**
     * @var Boolean
     */
    private $magicCall;

    /**
     * @var Boolean
     */
    private $throwExceptionOnInvalidIndex;

    /**
     * Should not be used by application code. Use
     * {@link PropertyAccess::createPropertyAccessor()} instead.
     */
    public function __construct($magicCall = false, $throwExceptionOnInvalidIndex = false)
    {
        $this->magicCall = $magicCall;
        $this->throwExceptionOnInvalidIndex = $throwExceptionOnInvalidIndex;
    }

    /**
     * {@inheritdoc}
     */
    public function getValue($objectOrArray, $propertyPath)
    {
        if (is_string($propertyPath)) {
            $propertyPath = new PropertyPath($propertyPath);
        } elseif (!$propertyPath instanceof PropertyPathInterface) {
            throw new UnexpectedTypeException($propertyPath, 'string or Symfony\Component\PropertyAccess\PropertyPathInterface');
        }

        $propertyValues =& $this->readPropertiesUntil($objectOrArray, $propertyPath, $propertyPath->getLength(), $this->throwExceptionOnInvalidIndex);

        return $propertyValues[count($propertyValues) - 1][self::VALUE];
    }

    /**
     * {@inheritdoc}
     */
    public function setValue(&$objectOrArray, $propertyPath, $value)
    {
        if (is_string($propertyPath)) {
            $propertyPath = new PropertyPath($propertyPath);
        } elseif (!$propertyPath instanceof PropertyPathInterface) {
            throw new UnexpectedTypeException($propertyPath, 'string or Symfony\Component\PropertyAccess\PropertyPathInterface');
        }

        $propertyValues =& $this->readPropertiesUntil($objectOrArray, $propertyPath, $propertyPath->getLength() - 1);
        $overwrite = true;

        // Add the root object to the list
        array_unshift($propertyValues, array(
            self::VALUE => &$objectOrArray,
            self::IS_REF => true,
        ));

        for ($i = count($propertyValues) - 1; $i >= 0; --$i) {
            $objectOrArray =& $propertyValues[$i][self::VALUE];

            if ($overwrite) {
                if (!is_object($objectOrArray) && !is_array($objectOrArray)) {
                    throw new UnexpectedTypeException($objectOrArray, 'object or array');
                }

                $property = $propertyPath->getElement($i);
                //$singular = $propertyPath->singulars[$i];
                $singular = null;

                if ($propertyPath->isIndex($i)) {
                    $this->writeIndex($objectOrArray, $property, $value);
                } else {
                    $this->writeProperty($objectOrArray, $property, $singular, $value);
                }
            }

            $value =& $objectOrArray;
            $overwrite = !$propertyValues[$i][self::IS_REF];
        }
    }

    /**
     * Reads the path from an object up to a given path index.
     *
     * @param object|array          $objectOrArray The object or array to read from
     * @param PropertyPathInterface $propertyPath  The property path to read
     * @param integer               $lastIndex     The index up to which should be read
     *
     * @return array The values read in the path.
     *
     * @throws UnexpectedTypeException If a value within the path is neither object nor array.
     */
    private function &readPropertiesUntil(&$objectOrArray, PropertyPathInterface $propertyPath, $lastIndex, $throwExceptionOnNonexistantIndex = false)
    {
        $propertyValues = array();

        for ($i = 0; $i < $lastIndex; ++$i) {
            if (!is_object($objectOrArray) && !is_array($objectOrArray)) {
                throw new UnexpectedTypeException($objectOrArray, 'object or array');
            }

            $property = $propertyPath->getElement($i);
            $isIndex = $propertyPath->isIndex($i);
            $isArrayAccess = is_array($objectOrArray) || $objectOrArray instanceof \ArrayAccess;

            // Create missing nested arrays on demand
            if ($isIndex && $isArrayAccess && !isset($objectOrArray[$property])) {
                if ($throwExceptionOnNonexistantIndex) {
                    throw new NoSuchIndexException(sprintf('Cannot read property "%s". Available properties are "%s"', $property, print_r(array_keys($objectOrArray), true)));
                }
                $objectOrArray[$property] = $i + 1 < $propertyPath->getLength() ? array() : null;
            }

            if ($isIndex) {
                $propertyValue =& $this->readIndex($objectOrArray, $property);
            } else {
                $propertyValue =& $this->readProperty($objectOrArray, $property);
            }

            $objectOrArray =& $propertyValue[self::VALUE];

            $propertyValues[] =& $propertyValue;
        }

        return $propertyValues;
    }

    /**
     * Reads a key from an array-like structure.
     *
     * @param \ArrayAccess|array $array The array or \ArrayAccess object to read from
     * @param string|integer     $index The key to read
     *
     * @return mixed The value of the key
     *
     * @throws NoSuchPropertyException If the array does not implement \ArrayAccess or it is not an array
     */
    private function &readIndex(&$array, $index)
    {
        if (!$array instanceof \ArrayAccess && !is_array($array)) {
            throw new NoSuchPropertyException(sprintf('Index "%s" cannot be read from object of type "%s" because it doesn\'t implement \ArrayAccess', $index, get_class($array)));
        }

        // Use an array instead of an object since performance is very crucial here
        $result = array(
            self::VALUE => null,
            self::IS_REF => false
        );

        if (isset($array[$index])) {
            if (is_array($array)) {
                $result[self::VALUE] =& $array[$index];
                $result[self::IS_REF] = true;
            } else {
                $result[self::VALUE] = $array[$index];
                // Objects are always passed around by reference
                $result[self::IS_REF] = is_object($array[$index]) ? true : false;
            }
        }

        return $result;
    }

    /**
     * Reads the a property from an object or array.
     *
     * @param object $object   The object to read from.
     * @param string $property The property to read.
     *
     * @return mixed The value of the read property
     *
     * @throws NoSuchPropertyException If the property does not exist or is not
     *                                 public.
     */
    private function &readProperty(&$object, $property)
    {
        // Use an array instead of an object since performance is
        // very crucial here
        $result = array(
            self::VALUE => null,
            self::IS_REF => false
        );

        if (!is_object($object)) {
            throw new NoSuchPropertyException(sprintf('Cannot read property "%s" from an array. Maybe you should write the property path as "[%s]" instead?', $property, $property));
        }

        $camelProp = $this->camelize($property);
        $reflClass = new \ReflectionClass($object);
        $getter = 'get'.$camelProp;
        $isser = 'is'.$camelProp;
        $hasser = 'has'.$camelProp;
        $classHasProperty = $reflClass->hasProperty($property);

        if ($reflClass->hasMethod($getter) && $reflClass->getMethod($getter)->isPublic()) {
            $result[self::VALUE] = $object->$getter();
        } elseif ($reflClass->hasMethod($isser) && $reflClass->getMethod($isser)->isPublic()) {
            $result[self::VALUE] = $object->$isser();
        } elseif ($reflClass->hasMethod($hasser) && $reflClass->getMethod($hasser)->isPublic()) {
            $result[self::VALUE] = $object->$hasser();
        } elseif ($reflClass->hasMethod('__get') && $reflClass->getMethod('__get')->isPublic()) {
            $result[self::VALUE] = $object->$property;
        } elseif ($classHasProperty && $reflClass->getProperty($property)->isPublic()) {
            $result[self::VALUE] =& $object->$property;
            $result[self::IS_REF] = true;
        } elseif (!$classHasProperty && property_exists($object, $property)) {
            // Needed to support \stdClass instances. We need to explicitly
            // exclude $classHasProperty, otherwise if in the previous clause
            // a *protected* property was found on the class, property_exists()
            // returns true, consequently the following line will result in a
            // fatal error.
            $result[self::VALUE] =& $object->$property;
            $result[self::IS_REF] = true;
        } elseif ($this->magicCall && $reflClass->hasMethod('__call') && $reflClass->getMethod('__call')->isPublic()) {
            // we call the getter and hope the __call do the job
            $result[self::VALUE] = $object->$getter();
        } else {
            $methods = array($getter, $isser, $hasser, '__get');
            if ($this->magicCall) {
                $methods[] = '__call';
            }

            throw new NoSuchPropertyException(sprintf(
                'Neither the property "%s" nor one of the methods "%s()" '.
                'exist and have public access in class "%s".',
                $property,
                implode('()", "', $methods),
                $reflClass->name
            ));
        }

        // Objects are always passed around by reference
        if (is_object($result[self::VALUE])) {
            $result[self::IS_REF] = true;
        }

        return $result;
    }

    /**
     * Sets the value of the property at the given index in the path
     *
     * @param \ArrayAccess|array $array An array or \ArrayAccess object to write to
     * @param string|integer     $index The index to write at
     * @param mixed              $value The value to write
     *
     * @throws NoSuchPropertyException If the array does not implement \ArrayAccess or it is not an array
     */
    private function writeIndex(&$array, $index, $value)
    {
        if (!$array instanceof \ArrayAccess && !is_array($array)) {
            throw new NoSuchPropertyException(sprintf('Index "%s" cannot be modified in object of type "%s" because it doesn\'t implement \ArrayAccess', $index, get_class($array)));
        }

        $array[$index] = $value;
    }

    /**
     * Sets the value of the property at the given index in the path
     *
     * @param object|array $object   The object or array to write to
     * @param string       $property The property to write
     * @param string|null  $singular The singular form of the property name or null
     * @param mixed        $value    The value to write
     *
     * @throws NoSuchPropertyException If the property does not exist or is not
     *                                 public.
     */
    private function writeProperty(&$object, $property, $singular, $value)
    {
        $guessedAdders = '';

        if (!is_object($object)) {
            throw new NoSuchPropertyException(sprintf('Cannot write property "%s" to an array. Maybe you should write the property path as "[%s]" instead?', $property, $property));
        }

        $reflClass = new \ReflectionClass($object);
        $plural = $this->camelize($property);

        // Any of the two methods is required, but not yet known
        $singulars = null !== $singular ? array($singular) : (array) StringUtil::singularify($plural);

        if (is_array($value) || $value instanceof \Traversable) {
            $methods = $this->findAdderAndRemover($reflClass, $singulars);

            if (null !== $methods) {
                // At this point the add and remove methods have been found
                // Use iterator_to_array() instead of clone in order to prevent side effects
                // see https://github.com/symfony/symfony/issues/4670
                $itemsToAdd = is_object($value) ? iterator_to_array($value) : $value;
                $itemToRemove = array();
                $propertyValue = $this->readProperty($object, $property);
                $previousValue = $propertyValue[self::VALUE];

                if (is_array($previousValue) || $previousValue instanceof \Traversable) {
                    foreach ($previousValue as $previousItem) {
                        foreach ($value as $key => $item) {
                            if ($item === $previousItem) {
                                // Item found, don't add
                                unset($itemsToAdd[$key]);

                                // Next $previousItem
                                continue 2;
                            }
                        }

                        // Item not found, add to remove list
                        $itemToRemove[] = $previousItem;
                    }
                }

                foreach ($itemToRemove as $item) {
                    call_user_func(array($object, $methods[1]), $item);
                }

                foreach ($itemsToAdd as $item) {
                    call_user_func(array($object, $methods[0]), $item);
                }

                return;
            } else {
                // It is sufficient to include only the adders in the error
                // message. If the user implements the adder but not the remover,
                // an exception will be thrown in findAdderAndRemover() that
                // the remover has to be implemented as well.
                $guessedAdders = '"add'.implode('()", "add', $singulars).'()", ';
            }
        }

        $setter = 'set'.$this->camelize($property);
        $classHasProperty = $reflClass->hasProperty($property);

        if ($reflClass->hasMethod($setter) && $reflClass->getMethod($setter)->isPublic()) {
            $object->$setter($value);
        } elseif ($reflClass->hasMethod('__set') && $reflClass->getMethod('__set')->isPublic()) {
            $object->$property = $value;
        } elseif ($classHasProperty && $reflClass->getProperty($property)->isPublic()) {
            $object->$property = $value;
        } elseif (!$classHasProperty && property_exists($object, $property)) {
            // Needed to support \stdClass instances. We need to explicitly
            // exclude $classHasProperty, otherwise if in the previous clause
            // a *protected* property was found on the class, property_exists()
            // returns true, consequently the following line will result in a
            // fatal error.
            $object->$property = $value;
        } elseif ($this->magicCall && $reflClass->hasMethod('__call') && $reflClass->getMethod('__call')->isPublic()) {
            // we call the getter and hope the __call do the job
            $object->$setter($value);
        } else {
            throw new NoSuchPropertyException(sprintf(
                'Neither the property "%s" nor one of the methods %s"%s()", '.
                '"__set()" or "__call()" exist and have public access in class "%s".',
                $property,
                $guessedAdders,
                $setter,
                $reflClass->name
            ));
        }
    }

    /**
     * Camelizes a given string.
     *
     * @param  string $string Some string
     *
     * @return string The camelized version of the string
     */
    private function camelize($string)
    {
        return preg_replace_callback('/(^|_|\.)+(.)/', function ($match) { return ('.' === $match[1] ? '_' : '').strtoupper($match[2]); }, $string);
    }

    /**
     * Searches for add and remove methods.
     *
     * @param \ReflectionClass $reflClass The reflection class for the given object
     * @param array            $singulars The singular form of the property name or null
     *
     * @return array|null An array containing the adder and remover when found, null otherwise
     *
     * @throws NoSuchPropertyException If the property does not exist
     */
    private function findAdderAndRemover(\ReflectionClass $reflClass, array $singulars)
    {
        foreach ($singulars as $singular) {
            $addMethod = 'add'.$singular;
            $removeMethod = 'remove'.$singular;

            $addMethodFound = $this->isAccessible($reflClass, $addMethod, 1);
            $removeMethodFound = $this->isAccessible($reflClass, $removeMethod, 1);

            if ($addMethodFound && $removeMethodFound) {
                return array($addMethod, $removeMethod);
            }

            if ($addMethodFound xor $removeMethodFound) {
                throw new NoSuchPropertyException(sprintf(
                    'Found the public method "%s()", but did not find a public "%s()" on class %s',
                    $addMethodFound ? $addMethod : $removeMethod,
                    $addMethodFound ? $removeMethod : $addMethod,
                    $reflClass->name
                ));
            }
        }

        return null;
    }

    /**
     * Returns whether a method is public and has a specific number of required parameters.
     *
     * @param  \ReflectionClass $class      The class of the method
     * @param  string           $methodName The method name
     * @param  integer          $parameters The number of parameters
     *
     * @return Boolean Whether the method is public and has $parameters
     *                                      required parameters
     */
    private function isAccessible(\ReflectionClass $class, $methodName, $parameters)
    {
        if ($class->hasMethod($methodName)) {
            $method = $class->getMethod($methodName);

            if ($method->isPublic() && $method->getNumberOfRequiredParameters() === $parameters) {
                return true;
            }
        }

        return false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\PropertyAccess;

use Symfony\Component\PropertyAccess\Exception\InvalidPropertyPathException;
use Symfony\Component\PropertyAccess\Exception\OutOfBoundsException;
use Symfony\Component\PropertyAccess\Exception\UnexpectedTypeException;

/**
 * Default implementation of {@link PropertyPathInterface}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class PropertyPath implements \IteratorAggregate, PropertyPathInterface
{
    /**
     * Character used for separating between plural and singular of an element.
     * @var string
     */
    const SINGULAR_SEPARATOR = '|';

    /**
     * The elements of the property path
     * @var array
     */
    private $elements = array();

    /**
     * The singular forms of the elements in the property path.
     * @var array
     */
    private $singulars = array();

    /**
     * The number of elements in the property path
     * @var integer
     */
    private $length;

    /**
     * Contains a Boolean for each property in $elements denoting whether this
     * element is an index. It is a property otherwise.
     * @var array
     */
    private $isIndex = array();

    /**
     * String representation of the path
     * @var string
     */
    private $pathAsString;

    /**
     * Constructs a property path from a string.
     *
     * @param PropertyPath|string $propertyPath The property path as string or instance
     *
     * @throws UnexpectedTypeException      If the given path is not a string
     * @throws InvalidPropertyPathException If the syntax of the property path is not valid
     */
    public function __construct($propertyPath)
    {
        // Can be used as copy constructor
        if ($propertyPath instanceof PropertyPath) {
            /* @var PropertyPath $propertyPath */
            $this->elements = $propertyPath->elements;
            $this->singulars = $propertyPath->singulars;
            $this->length = $propertyPath->length;
            $this->isIndex = $propertyPath->isIndex;
            $this->pathAsString = $propertyPath->pathAsString;

            return;
        }
        if (!is_string($propertyPath)) {
            throw new UnexpectedTypeException($propertyPath, 'string or Symfony\Component\PropertyAccess\PropertyPath');
        }

        if ('' === $propertyPath) {
            throw new InvalidPropertyPathException('The property path should not be empty.');
        }

        $this->pathAsString = $propertyPath;
        $position = 0;
        $remaining = $propertyPath;

        // first element is evaluated differently - no leading dot for properties
        $pattern = '/^(([^\.\[]+)|\[([^\]]+)\])(.*)/';

        while (preg_match($pattern, $remaining, $matches)) {
            if ('' !== $matches[2]) {
                $element = $matches[2];
                $this->isIndex[] = false;
            } else {
                $element = $matches[3];
                $this->isIndex[] = true;
            }
            // Disabled this behaviour as the syntax is not yet final
            //$pos = strpos($element, self::SINGULAR_SEPARATOR);
            $pos = false;
            $singular = null;

            if (false !== $pos) {
                $singular = substr($element, $pos + 1);
                $element = substr($element, 0, $pos);
            }

            $this->elements[] = $element;
            $this->singulars[] = $singular;

            $position += strlen($matches[1]);
            $remaining = $matches[4];
            $pattern = '/^(\.(\w+)|\[([^\]]+)\])(.*)/';
        }

        if ('' !== $remaining) {
            throw new InvalidPropertyPathException(sprintf(
                'Could not parse property path "%s". Unexpected token "%s" at position %d',
                $propertyPath,
                $remaining{0},
                $position
            ));
        }

        $this->length = count($this->elements);
    }

    /**
     * {@inheritdoc}
     */
    public function __toString()
    {
        return $this->pathAsString;
    }

    /**
     * {@inheritdoc}
     */
    public function getLength()
    {
        return $this->length;
    }

    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        if ($this->length <= 1) {
            return null;
        }

        $parent = clone $this;

        --$parent->length;
        $parent->pathAsString = substr($parent->pathAsString, 0, max(strrpos($parent->pathAsString, '.'), strrpos($parent->pathAsString, '[')));
        array_pop($parent->elements);
        array_pop($parent->singulars);
        array_pop($parent->isIndex);

        return $parent;
    }

    /**
     * Returns a new iterator for this path
     *
     * @return PropertyPathIteratorInterface
     */
    public function getIterator()
    {
        return new PropertyPathIterator($this);
    }

    /**
     * {@inheritdoc}
     */
    public function getElements()
    {
        return $this->elements;
    }

    /**
     * {@inheritdoc}
     */
    public function getElement($index)
    {
        if (!isset($this->elements[$index])) {
            throw new OutOfBoundsException(sprintf('The index %s is not within the property path', $index));
        }

        return $this->elements[$index];
    }

    /**
     * {@inheritdoc}
     */
    public function isProperty($index)
    {
        if (!isset($this->isIndex[$index])) {
            throw new OutOfBoundsException(sprintf('The index %s is not within the property path', $index));
        }

        return !$this->isIndex[$index];
    }

    /**
     * {@inheritdoc}
     */
    public function isIndex($index)
    {
        if (!isset($this->isIndex[$index])) {
            throw new OutOfBoundsException(sprintf('The index %s is not within the property path', $index));
        }

        return $this->isIndex[$index];
    }
}
Copyright (c) 2004-2013 Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\PropertyAccess;

/**
 * Traverses a property path and provides additional methods to find out
 * information about the current element
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class PropertyPathIterator extends \ArrayIterator implements PropertyPathIteratorInterface
{
    /**
     * The traversed property path
     * @var PropertyPathInterface
     */
    protected $path;

    /**
     * Constructor.
     *
     * @param PropertyPathInterface $path The property path to traverse
     */
    public function __construct(PropertyPathInterface $path)
    {
        parent::__construct($path->getElements());

        $this->path = $path;
    }

    /**
     * {@inheritdoc}
     */
    public function isIndex()
    {
        return $this->path->isIndex($this->key());
    }

    /**
     * {@inheritdoc}
     */
    public function isProperty()
    {
        return $this->path->isProperty($this->key());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\PropertyAccess;

/**
 * Creates singulars from plurals.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class StringUtil
{
    /**
     * Map english plural to singular suffixes
     *
     * @var array
     *
     * @see http://english-zone.com/spelling/plurals.html
     * @see http://www.scribd.com/doc/3271143/List-of-100-Irregular-Plural-Nouns-in-English
     */
    private static $pluralMap = array(
        // First entry: plural suffix, reversed
        // Second entry: length of plural suffix
        // Third entry: Whether the suffix may succeed a vocal
        // Fourth entry: Whether the suffix may succeed a consonant
        // Fifth entry: singular suffix, normal

        // bacteria (bacterium), criteria (criterion), phenomena (phenomenon)
        array('a', 1, true, true, array('on', 'um')),

        // nebulae (nebula)
        array('ea', 2, true, true, 'a'),

        // mice (mouse), lice (louse)
        array('eci', 3, false, true, 'ouse'),

        // geese (goose)
        array('esee', 4, false, true, 'oose'),

        // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius)
        array('i', 1, true, true, 'us'),

        // men (man), women (woman)
        array('nem', 3, true, true, 'man'),

        // children (child)
        array('nerdlihc', 8, true, true, 'child'),

        // oxen (ox)
        array('nexo', 4, false, false, 'ox'),

        // indices (index), appendices (appendix), prices (price)
        array('seci', 4, false, true, array('ex', 'ix', 'ice')),

        // babies (baby)
        array('sei', 3, false, true, 'y'),

        // accesses (access), addresses (address), kisses (kiss)
        array('sess', 4, true, false, 'ss'),

        // analyses (analysis), ellipses (ellipsis), funguses (fungus),
        // neuroses (neurosis), theses (thesis), emphases (emphasis),
        // oases (oasis), crises (crisis), houses (house), bases (base),
        // atlases (atlas)
        array('ses', 3, true, true, array('s', 'se', 'sis')),

        // objectives (objective), alternative (alternatives)
        array('sevit', 5, true, true, 'tive'),

        // lives (life), wives (wife)
        array('sevi', 4, false, true, 'ife'),

        // moves (move)
        array('sevom', 5, true, true, 'move'),

        // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf)
        array('sev', 3, true, true, 'f'),

        // axes (axis), axes (ax), axes (axe)
        array('sexa', 4, false, false, array('ax', 'axe', 'axis')),

        // indexes (index), matrixes (matrix)
        array('sex', 3, true, false, 'x'),

        // quizzes (quiz)
        array('sezz', 4, true, false, 'z'),

        // bureaus (bureau)
        array('suae', 4, false, true, 'eau'),

        // roses (rose), garages (garage), cassettes (cassette),
        // waltzes (waltz), heroes (hero), bushes (bush), arches (arch),
        // shoes (shoe)
        array('se', 2, true, true, array('', 'e')),

        // tags (tag)
        array('s', 1, true, true, ''),

        // chateaux (chateau)
        array('xuae', 4, false, true, 'eau'),
    );

    /**
     * This class should not be instantiated
     */
    private function __construct() {}

    /**
     * Returns the singular form of a word
     *
     * If the method can't determine the form with certainty, an array of the
     * possible singulars is returned.
     *
     * @param string $plural A word in plural form
     * @return string|array The singular form or an array of possible singular
     *                      forms
     */
    public static function singularify($plural)
    {
        $pluralRev = strrev($plural);
        $lowerPluralRev = strtolower($pluralRev);
        $pluralLength = strlen($lowerPluralRev);

        // The outer loop iterates over the entries of the plural table
        // The inner loop $j iterates over the characters of the plural suffix
        // in the plural table to compare them with the characters of the actual
        // given plural suffix
        foreach (self::$pluralMap as $map) {
            $suffix = $map[0];
            $suffixLength = $map[1];
            $j = 0;

            // Compare characters in the plural table and of the suffix of the
            // given plural one by one
            while ($suffix[$j] === $lowerPluralRev[$j]) {
                // Let $j point to the next character
                ++$j;

                // Successfully compared the last character
                // Add an entry with the singular suffix to the singular array
                if ($j === $suffixLength) {
                    // Is there any character preceding the suffix in the plural string?
                    if ($j < $pluralLength) {
                        $nextIsVocal = false !== strpos('aeiou', $lowerPluralRev[$j]);

                        if (!$map[2] && $nextIsVocal) {
                            // suffix may not succeed a vocal but next char is one
                            break;
                        }

                        if (!$map[3] && !$nextIsVocal) {
                            // suffix may not succeed a consonant but next char is one
                            break;
                        }
                    }

                    $newBase = substr($plural, 0, $pluralLength - $suffixLength);
                    $newSuffix = $map[4];

                    // Check whether the first character in the plural suffix
                    // is uppercased. If yes, uppercase the first character in
                    // the singular suffix too
                    $firstUpper = ctype_upper($pluralRev[$j - 1]);

                    if (is_array($newSuffix)) {
                        $singulars = array();

                        foreach ($newSuffix as $newSuffixEntry) {
                            $singulars[] = $newBase.($firstUpper ? ucfirst($newSuffixEntry) : $newSuffixEntry);
                        }

                        return $singulars;
                    }

                    return $newBase.($firstUpper ? ucFirst($newSuffix) : $newSuffix);
                }

                // Suffix is longer than word
                if ($j === $pluralLength) {
                    break;
                }
            }
        }

        // Convert teeth to tooth, feet to foot
        if (false !== ($pos = strpos($plural, 'ee')) && strlen($plural) > 3) {
            return substr_replace($plural, 'oo', $pos, 2);
        }

        // Assume that plural and singular is identical
        return $plural;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\PropertyAccess;

/**
 * A configurable builder for PropertyAccessorInterface objects.
 *
 * @author Jérémie Augustin <jeremie.augustin@pixel-cookers.com>
 */
class PropertyAccessorBuilder
{
    /**
     * @var Boolean
     */
    private $magicCall = false;

    /**
     * @var Boolean
     */
    private $throwExceptionOnInvalidIndex = false;

    /**
     * Enables the use of "__call" by the PropertyAccessor.
     *
     * @return PropertyAccessorBuilder The builder object
     */
    public function enableMagicCall()
    {
        $this->magicCall = true;

        return $this;
    }

    /**
     * Disables the use of "__call" by the PropertyAccessor.
     *
     * @return PropertyAccessorBuilder The builder object
     */
    public function disableMagicCall()
    {
        $this->magicCall = false;

        return $this;
    }

    /**
     * @return Boolean true if the use of "__call" by the PropertyAccessor is enabled
     */
    public function isMagicCallEnabled()
    {
        return $this->magicCall;
    }

    /**
     * Enables exceptions in read context for array by PropertyAccessor
     *
     * @return PropertyAccessorBuilder The builder object
     */
    public function enableExceptionOnInvalidIndex()
    {
        $this->throwExceptionOnInvalidIndex = true;

        return $this;
    }

    /**
     * Disables exceptions in read context for array by PropertyAccessor
     *
     * @return PropertyAccessorBuilder The builder object
     */
    public function disableExceptionOnInvalidIndex()
    {
        $this->throwExceptionOnInvalidIndex = false;

        return $this;
    }

    /**
     * @return Boolean true is exceptions in read context for array is enabled
     */
    public function isExceptionOnInvalidIndexEnabled()
    {
        return $this->throwExceptionOnInvalidIndex;
    }

    /**
     * Builds and returns a new propertyAccessor object.
     *
     * @return PropertyAccessorInterface The built propertyAccessor
     */
    public function getPropertyAccessor()
    {
        return new PropertyAccessor($this->magicCall, $this->throwExceptionOnInvalidIndex);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\PropertyAccess;

/**
 * A sequence of property names or array indices.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface PropertyPathInterface extends \Traversable
{
    /**
     * Returns the string representation of the property path
     *
     * @return string The path as string
     */
    public function __toString();

    /**
     * Returns the length of the property path, i.e. the number of elements.
     *
     * @return integer The path length
     */
    public function getLength();

    /**
     * Returns the parent property path.
     *
     * The parent property path is the one that contains the same items as
     * this one except for the last one.
     *
     * If this property path only contains one item, null is returned.
     *
     * @return PropertyPath The parent path or null
     */
    public function getParent();

    /**
     * Returns the elements of the property path as array
     *
     * @return array An array of property/index names
     */
    public function getElements();

    /**
     * Returns the element at the given index in the property path
     *
     * @param  integer $index The index key
     *
     * @return string A property or index name
     *
     * @throws Exception\OutOfBoundsException If the offset is invalid
     */
    public function getElement($index);

    /**
     * Returns whether the element at the given index is a property
     *
     * @param  integer $index The index in the property path
     *
     * @return Boolean Whether the element at this index is a property
     *
     * @throws Exception\OutOfBoundsException If the offset is invalid
     */
    public function isProperty($index);

    /**
     * Returns whether the element at the given index is an array index
     *
     * @param  integer $index The index in the property path
     *
     * @return Boolean Whether the element at this index is an array index
     *
     * @throws Exception\OutOfBoundsException If the offset is invalid
     */
    public function isIndex($index);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\PropertyAccess;

/**
 * Writes and reads values to/from an object/array graph.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface PropertyAccessorInterface
{
    /**
     * Sets the value at the end of the property path of the object
     *
     * Example:
     *
     *     use Symfony\Component\PropertyAccess\PropertyAccess;
     *
     *     $propertyAccessor = PropertyAccess::getPropertyAccessor();
     *
     *     echo $propertyAccessor->setValue($object, 'child.name', 'Fabien');
     *     // equals echo $object->getChild()->setName('Fabien');
     *
     * This method first tries to find a public setter for each property in the
     * path. The name of the setter must be the camel-cased property name
     * prefixed with "set".
     *
     * If the setter does not exist, this method tries to find a public
     * property. The value of the property is then changed.
     *
     * If neither is found, an exception is thrown.
     *
     * @param object|array                 $objectOrArray The object or array to modify
     * @param string|PropertyPathInterface $propertyPath  The property path to modify
     * @param mixed                        $value         The value to set at the end of the property path
     *
     * @throws Exception\NoSuchPropertyException If a property does not exist or is not public.
     * @throws Exception\UnexpectedTypeException If a value within the path is neither object
     *                                           nor array
     */
    public function setValue(&$objectOrArray, $propertyPath, $value);

    /**
     * Returns the value at the end of the property path of the object
     *
     * Example:
     *
     *     use Symfony\Component\PropertyAccess\PropertyAccess;
     *
     *     $propertyAccessor = PropertyAccess::getPropertyAccessor();
     *
     *     echo $propertyAccessor->getValue($object, 'child.name);
     *     // equals echo $object->getChild()->getName();
     *
     * This method first tries to find a public getter for each property in the
     * path. The name of the getter must be the camel-cased property name
     * prefixed with "get", "is", or "has".
     *
     * If the getter does not exist, this method tries to find a public
     * property. The value of the property is then returned.
     *
     * If none of them are found, an exception is thrown.
     *
     * @param object|array                 $objectOrArray The object or array to traverse
     * @param string|PropertyPathInterface $propertyPath  The property path to read
     *
     * @return mixed The value at the end of the property path
     *
     * @throws Exception\NoSuchPropertyException If a property does not exist or is not public.
     */
    public function getValue($objectOrArray, $propertyPath);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\PropertyAccess;

/**
 * Entry point of the PropertyAccess component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
final class PropertyAccess
{
    /**
     * Creates a property accessor with the default configuration.
     *
     * @return PropertyAccessor The new property accessor
     */
    public static function createPropertyAccessor()
    {
        return self::createPropertyAccessorBuilder()->getPropertyAccessor();
    }

    /**
     * Creates a property accessor builder.
     *
     * @return PropertyAccessorBuilder The new property accessor builder
     */
    public static function createPropertyAccessorBuilder()
    {
        return new PropertyAccessorBuilder();
    }

    /**
     * Alias of {@link getPropertyAccessor}.
     *
     * @return PropertyAccessor The new property accessor
     *
     * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
     *             {@link createPropertyAccessor()} instead.
     */
    public static function getPropertyAccessor()
    {
        return self::createPropertyAccessor();
    }

    /**
     * This class cannot be instantiated.
     */
    private function __construct()
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\PropertyAccess;

use Symfony\Component\PropertyAccess\Exception\OutOfBoundsException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class PropertyPathBuilder
{
    /**
     * @var array
     */
    private $elements = array();

    /**
     * @var array
     */
    private $isIndex = array();

    /**
     * Creates a new property path builder.
     *
     * @param null|PropertyPathInterface|string $path The path to initially store
     *                                                in the builder. Optional.
     */
    public function __construct($path = null)
    {
        if (null !== $path) {
            $this->append($path);
        }
    }

    /**
     * Appends a (sub-) path to the current path.
     *
     * @param PropertyPathInterface|string $path   The path to append.
     * @param integer                      $offset The offset where the appended
     *                                             piece starts in $path.
     * @param integer                      $length The length of the appended piece.
     *                                             If 0, the full path is appended.
     */
    public function append($path, $offset = 0, $length = 0)
    {
        if (is_string($path)) {
            $path = new PropertyPath($path);
        }

        if (0 === $length) {
            $end = $path->getLength();
        } else {
            $end = $offset + $length;
        }

        for (; $offset < $end; ++$offset) {
            $this->elements[] = $path->getElement($offset);
            $this->isIndex[] = $path->isIndex($offset);
        }
    }

    /**
     * Appends an index element to the current path.
     *
     * @param string $name The name of the appended index
     */
    public function appendIndex($name)
    {
        $this->elements[] = $name;
        $this->isIndex[] = true;
    }

    /**
     * Appends a property element to the current path.
     *
     * @param string $name The name of the appended property
     */
    public function appendProperty($name)
    {
        $this->elements[] = $name;
        $this->isIndex[] = false;
    }

    /**
     * Removes elements from the current path.
     *
     * @param integer $offset The offset at which to remove
     * @param integer $length The length of the removed piece
     *
     * @throws OutOfBoundsException if offset is invalid
     */
    public function remove($offset, $length = 1)
    {
        if (!isset($this->elements[$offset])) {
            throw new OutOfBoundsException(sprintf('The offset %s is not within the property path', $offset));
        }

        $this->resize($offset, $length, 0);
    }

    /**
     * Replaces a sub-path by a different (sub-) path.
     *
     * @param integer                      $offset     The offset at which to replace.
     * @param integer                      $length     The length of the piece to replace.
     * @param PropertyPathInterface|string $path       The path to insert.
     * @param integer                      $pathOffset The offset where the inserted piece
     *                                                 starts in $path.
     * @param integer                      $pathLength The length of the inserted piece.
     *                                                 If 0, the full path is inserted.
     *
     * @throws OutOfBoundsException If the offset is invalid
     */
    public function replace($offset, $length, $path, $pathOffset = 0, $pathLength = 0)
    {
        if (is_string($path)) {
            $path = new PropertyPath($path);
        }

        if ($offset < 0 && abs($offset) <= $this->getLength()) {
            $offset = $this->getLength() + $offset;
        } elseif (!isset($this->elements[$offset])) {
            throw new OutOfBoundsException('The offset ' . $offset . ' is not within the property path');
        }

        if (0 === $pathLength) {
            $pathLength = $path->getLength() - $pathOffset;
        }

        $this->resize($offset, $length, $pathLength);

        for ($i = 0; $i < $pathLength; ++$i) {
            $this->elements[$offset + $i] = $path->getElement($pathOffset + $i);
            $this->isIndex[$offset + $i] = $path->isIndex($pathOffset + $i);
        }
    }

    /**
     * Replaces a property element by an index element.
     *
     * @param integer $offset The offset at which to replace
     * @param string  $name   The new name of the element. Optional.
     *
     * @throws OutOfBoundsException If the offset is invalid
     */
    public function replaceByIndex($offset, $name = null)
    {
        if (!isset($this->elements[$offset])) {
            throw new OutOfBoundsException(sprintf('The offset %s is not within the property path', $offset));
        }

        if (null !== $name) {
            $this->elements[$offset] = $name;
        }

        $this->isIndex[$offset] = true;
    }

    /**
     * Replaces an index element by a property element.
     *
     * @param integer $offset The offset at which to replace
     * @param string  $name   The new name of the element. Optional.
     *
     * @throws OutOfBoundsException If the offset is invalid
     */
    public function replaceByProperty($offset, $name = null)
    {
        if (!isset($this->elements[$offset])) {
            throw new OutOfBoundsException(sprintf('The offset %s is not within the property path', $offset));
        }

        if (null !== $name) {
            $this->elements[$offset] = $name;
        }

        $this->isIndex[$offset] = false;
    }

    /**
     * Returns the length of the current path.
     *
     * @return integer The path length
     */
    public function getLength()
    {
        return count($this->elements);
    }

    /**
     * Returns the current property path.
     *
     * @return PropertyPathInterface The constructed property path
     */
    public function getPropertyPath()
    {
        $pathAsString = $this->__toString();

        return '' !== $pathAsString ? new PropertyPath($pathAsString) : null;
    }

    /**
     * Returns the current property path as string.
     *
     * @return string The property path as string
     */
    public function __toString()
    {
        $string = '';

        foreach ($this->elements as $offset => $element) {
            if ($this->isIndex[$offset]) {
                $element = '['.$element.']';
            } elseif ('' !== $string) {
                $string .= '.';
            }

            $string .= $element;
        }

        return $string;
    }

    /**
     * Resizes the path so that a chunk of length $cutLength is
     * removed at $offset and another chunk of length $insertionLength
     * can be inserted.
     *
     * @param  integer $offset          The offset where the removed chunk starts
     * @param  integer $cutLength       The length of the removed chunk
     * @param  integer $insertionLength The length of the inserted chunk
     */
    private function resize($offset, $cutLength, $insertionLength)
    {
        // Nothing else to do in this case
        if ($insertionLength === $cutLength) {
            return;
        }

        $length = count($this->elements);

        if ($cutLength > $insertionLength) {
            // More elements should be removed than inserted
            $diff = $cutLength - $insertionLength;
            $newLength = $length - $diff;

            // Shift elements to the left (left-to-right until the new end)
            // Max allowed offset to be shifted is such that
            // $offset + $diff < $length (otherwise invalid index access)
            // i.e. $offset < $length - $diff = $newLength
            for ($i = $offset; $i < $newLength; ++$i) {
                $this->elements[$i] = $this->elements[$i + $diff];
                $this->isIndex[$i] = $this->isIndex[$i + $diff];
            }

            // All remaining elements should be removed
            for (; $i < $length; ++$i) {
                unset($this->elements[$i]);
                unset($this->isIndex[$i]);
            }
        } else {
            $diff = $insertionLength - $cutLength;

            $newLength = $length + $diff;
            $indexAfterInsertion = $offset + $insertionLength;

            // $diff <= $insertionLength
            // $indexAfterInsertion >= $insertionLength
            // => $diff <= $indexAfterInsertion

            // In each of the following loops, $i >= $diff must hold,
            // otherwise ($i - $diff) becomes negative.

            // Shift old elements to the right to make up space for the
            // inserted elements. This needs to be done left-to-right in
            // order to preserve an ascending array index order
            // Since $i = max($length, $indexAfterInsertion) and $indexAfterInsertion >= $diff,
            // $i >= $diff is guaranteed.
            for ($i = max($length, $indexAfterInsertion); $i < $newLength; ++$i) {
                $this->elements[$i] = $this->elements[$i - $diff];
                $this->isIndex[$i] = $this->isIndex[$i - $diff];
            }

            // Shift remaining elements to the right. Do this right-to-left
            // so we don't overwrite elements before copying them
            // The last written index is the immediate index after the inserted
            // string, because the indices before that will be overwritten
            // anyway.
            // Since $i >= $indexAfterInsertion and $indexAfterInsertion >= $diff,
            // $i >= $diff is guaranteed.
            for ($i = $length - 1; $i >= $indexAfterInsertion; --$i) {
                $this->elements[$i] = $this->elements[$i - $diff];
                $this->isIndex[$i] = $this->isIndex[$i - $diff];
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\PropertyAccess\Exception;

/**
 * Base OutOfBoundsException for the PropertyAccess component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\PropertyAccess\Exception;

/**
 * Base RuntimeException for the PropertyAccess component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\PropertyAccess\Exception;

/**
 * Thrown when a property path is not available.
 *
 * @author Stéphane Escandell <stephane.escandell@gmail.com>
 */
class AccessException extends RuntimeException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\PropertyAccess\Exception;

/**
 * Thrown when a property path is malformed.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class InvalidPropertyPathException extends RuntimeException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\PropertyAccess\Exception;

/**
 * Marker interface for the PropertyAccess component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\PropertyAccess\Exception;

/**
 * Thrown when a property cannot be found.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class NoSuchPropertyException extends AccessException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\PropertyAccess\Exception;

/**
 * Thrown when an index cannot be found.
 *
 * @author Stéphane Escandell <stephane.escandell@gmail.com>
 */
class NoSuchIndexException extends AccessException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\PropertyAccess\Exception;

/**
 * Thrown when a value does not match an expected type.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class UnexpectedTypeException extends RuntimeException
{
    public function __construct($value, $expectedType)
    {
        parent::__construct(sprintf('Expected argument of type "%s", "%s" given', $expectedType, is_object($value) ? get_class($value) : gettype($value)));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\PropertyAccess;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface PropertyPathIteratorInterface extends \Iterator, \SeekableIterator
{
    /**
     * Returns whether the current element in the property path is an array
     * index.
     *
     * @return Boolean
     */
    public function isIndex();

    /**
     * Returns whether the current element in the property path is a property
     * name.
     *
     * @return Boolean
     */
    public function isProperty();
}
{
    "name": "symfony/filesystem",
    "type": "library",
    "description": "Symfony Filesystem Component",
    "keywords": [],
    "homepage": "http://symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "http://symfony.com/contributors"
        }
    ],
    "require": {
        "php": ">=5.3.3"
    },
    "autoload": {
        "psr-0": { "Symfony\\Component\\Filesystem\\": "" }
    },
    "target-dir": "Symfony/Component/Filesystem",
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-master": "2.4-dev"
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Filesystem;

use Symfony\Component\Filesystem\Exception\IOException;
use Symfony\Component\Filesystem\Exception\FileNotFoundException;

/**
 * Provides basic utility to manipulate the file system.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Filesystem
{
    /**
     * Copies a file.
     *
     * This method only copies the file if the origin file is newer than the target file.
     *
     * By default, if the target already exists, it is not overridden.
     *
     * @param string  $originFile The original filename
     * @param string  $targetFile The target filename
     * @param boolean $override   Whether to override an existing file or not
     *
     * @throws FileNotFoundException    When originFile doesn't exist
     * @throws IOException              When copy fails
     */
    public function copy($originFile, $targetFile, $override = false)
    {
        if (stream_is_local($originFile) && !is_file($originFile)) {
            throw new FileNotFoundException(sprintf('Failed to copy "%s" because file does not exist.', $originFile), 0, null, $originFile);
        }

        $this->mkdir(dirname($targetFile));

        if (!$override && is_file($targetFile)) {
            $doCopy = filemtime($originFile) > filemtime($targetFile);
        } else {
            $doCopy = true;
        }

        if ($doCopy) {
            // https://bugs.php.net/bug.php?id=64634
            $source = fopen($originFile, 'r');
            $target = fopen($targetFile, 'w+');
            stream_copy_to_stream($source, $target);
            fclose($source);
            fclose($target);
            unset($source, $target);

            if (!is_file($targetFile)) {
                throw new IOException(sprintf('Failed to copy "%s" to "%s".', $originFile, $targetFile), 0, null, $originFile);
            }
        }
    }

    /**
     * Creates a directory recursively.
     *
     * @param string|array|\Traversable $dirs The directory path
     * @param integer                   $mode The directory mode
     *
     * @throws IOException On any directory creation failure
     */
    public function mkdir($dirs, $mode = 0777)
    {
        foreach ($this->toIterator($dirs) as $dir) {
            if (is_dir($dir)) {
                continue;
            }

            if (true !== @mkdir($dir, $mode, true)) {
                throw new IOException(sprintf('Failed to create "%s".', $dir), 0, null, $dir);
            }
        }
    }

    /**
     * Checks the existence of files or directories.
     *
     * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to check
     *
     * @return Boolean true if the file exists, false otherwise
     */
    public function exists($files)
    {
        foreach ($this->toIterator($files) as $file) {
            if (!file_exists($file)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Sets access and modification time of file.
     *
     * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to create
     * @param integer                   $time  The touch time as a unix timestamp
     * @param integer                   $atime The access time as a unix timestamp
     *
     * @throws IOException When touch fails
     */
    public function touch($files, $time = null, $atime = null)
    {
        foreach ($this->toIterator($files) as $file) {
            $touch = $time ? @touch($file, $time, $atime) : @touch($file);
            if (true !== $touch) {
                throw new IOException(sprintf('Failed to touch "%s".', $file), 0, null, $file);
            }
        }
    }

    /**
     * Removes files or directories.
     *
     * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to remove
     *
     * @throws IOException When removal fails
     */
    public function remove($files)
    {
        $files = iterator_to_array($this->toIterator($files));
        $files = array_reverse($files);
        foreach ($files as $file) {
            if (!file_exists($file) && !is_link($file)) {
                continue;
            }

            if (is_dir($file) && !is_link($file)) {
                $this->remove(new \FilesystemIterator($file));

                if (true !== @rmdir($file)) {
                    throw new IOException(sprintf('Failed to remove directory "%s".', $file), 0, null, $file);
                }
            } else {
                // https://bugs.php.net/bug.php?id=52176
                if (defined('PHP_WINDOWS_VERSION_MAJOR') && is_dir($file)) {
                    if (true !== @rmdir($file)) {
                        throw new IOException(sprintf('Failed to remove file "%s".', $file), 0, null, $file);
                    }
                } else {
                    if (true !== @unlink($file)) {
                        throw new IOException(sprintf('Failed to remove file "%s".', $file), 0, null, $file);
                    }
                }
            }
        }
    }

    /**
     * Change mode for an array of files or directories.
     *
     * @param string|array|\Traversable $files     A filename, an array of files, or a \Traversable instance to change mode
     * @param integer                   $mode      The new mode (octal)
     * @param integer                   $umask     The mode mask (octal)
     * @param Boolean                   $recursive Whether change the mod recursively or not
     *
     * @throws IOException When the change fail
     */
    public function chmod($files, $mode, $umask = 0000, $recursive = false)
    {
        foreach ($this->toIterator($files) as $file) {
            if ($recursive && is_dir($file) && !is_link($file)) {
                $this->chmod(new \FilesystemIterator($file), $mode, $umask, true);
            }
            if (true !== @chmod($file, $mode & ~$umask)) {
                throw new IOException(sprintf('Failed to chmod file "%s".', $file), 0, null, $file);
            }
        }
    }

    /**
     * Change the owner of an array of files or directories
     *
     * @param string|array|\Traversable $files     A filename, an array of files, or a \Traversable instance to change owner
     * @param string                    $user      The new owner user name
     * @param Boolean                   $recursive Whether change the owner recursively or not
     *
     * @throws IOException When the change fail
     */
    public function chown($files, $user, $recursive = false)
    {
        foreach ($this->toIterator($files) as $file) {
            if ($recursive && is_dir($file) && !is_link($file)) {
                $this->chown(new \FilesystemIterator($file), $user, true);
            }
            if (is_link($file) && function_exists('lchown')) {
                if (true !== @lchown($file, $user)) {
                    throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
                }
            } else {
                if (true !== @chown($file, $user)) {
                    throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
                }
            }
        }
    }

    /**
     * Change the group of an array of files or directories
     *
     * @param string|array|\Traversable $files     A filename, an array of files, or a \Traversable instance to change group
     * @param string                    $group     The group name
     * @param Boolean                   $recursive Whether change the group recursively or not
     *
     * @throws IOException When the change fail
     */
    public function chgrp($files, $group, $recursive = false)
    {
        foreach ($this->toIterator($files) as $file) {
            if ($recursive && is_dir($file) && !is_link($file)) {
                $this->chgrp(new \FilesystemIterator($file), $group, true);
            }
            if (is_link($file) && function_exists('lchgrp')) {
                if (true !== @lchgrp($file, $group)) {
                    throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
                }
            } else {
                if (true !== @chgrp($file, $group)) {
                    throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
                }
            }
        }
    }

    /**
     * Renames a file or a directory.
     *
     * @param string  $origin    The origin filename or directory
     * @param string  $target    The new filename or directory
     * @param Boolean $overwrite Whether to overwrite the target if it already exists
     *
     * @throws IOException When target file or directory already exists
     * @throws IOException When origin cannot be renamed
     */
    public function rename($origin, $target, $overwrite = false)
    {
        // we check that target does not exist
        if (!$overwrite && is_readable($target)) {
            throw new IOException(sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target);
        }

        if (true !== @rename($origin, $target)) {
            throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target), 0, null, $target);
        }
    }

    /**
     * Creates a symbolic link or copy a directory.
     *
     * @param string  $originDir     The origin directory path
     * @param string  $targetDir     The symbolic link name
     * @param Boolean $copyOnWindows Whether to copy files if on Windows
     *
     * @throws IOException When symlink fails
     */
    public function symlink($originDir, $targetDir, $copyOnWindows = false)
    {
        if (!function_exists('symlink') && $copyOnWindows) {
            $this->mirror($originDir, $targetDir);

            return;
        }

        $this->mkdir(dirname($targetDir));

        $ok = false;
        if (is_link($targetDir)) {
            if (readlink($targetDir) != $originDir) {
                $this->remove($targetDir);
            } else {
                $ok = true;
            }
        }

        if (!$ok) {
            if (true !== @symlink($originDir, $targetDir)) {
                $report = error_get_last();
                if (is_array($report)) {
                    if (defined('PHP_WINDOWS_VERSION_MAJOR') && false !== strpos($report['message'], 'error code(1314)')) {
                        throw new IOException('Unable to create symlink due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?');
                    }
                }

                throw new IOException(sprintf('Failed to create symbolic link from "%s" to "%s".', $originDir, $targetDir), 0, null, $targetDir);
            }
        }
    }

    /**
     * Given an existing path, convert it to a path relative to a given starting path
     *
     * @param string $endPath   Absolute path of target
     * @param string $startPath Absolute path where traversal begins
     *
     * @return string Path of target relative to starting path
     */
    public function makePathRelative($endPath, $startPath)
    {
        // Normalize separators on windows
        if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
            $endPath = strtr($endPath, '\\', '/');
            $startPath = strtr($startPath, '\\', '/');
        }

        // Split the paths into arrays
        $startPathArr = explode('/', trim($startPath, '/'));
        $endPathArr = explode('/', trim($endPath, '/'));

        // Find for which directory the common path stops
        $index = 0;
        while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) {
            $index++;
        }

        // Determine how deep the start path is relative to the common path (ie, "web/bundles" = 2 levels)
        $depth = count($startPathArr) - $index;

        // Repeated "../" for each level need to reach the common path
        $traverser = str_repeat('../', $depth);

        $endPathRemainder = implode('/', array_slice($endPathArr, $index));

        // Construct $endPath from traversing to the common path, then to the remaining $endPath
        $relativePath = $traverser.(strlen($endPathRemainder) > 0 ? $endPathRemainder.'/' : '');

        return (strlen($relativePath) === 0) ? './' : $relativePath;
    }

    /**
     * Mirrors a directory to another.
     *
     * @param string       $originDir The origin directory
     * @param string       $targetDir The target directory
     * @param \Traversable $iterator  A Traversable instance
     * @param array        $options   An array of boolean options
     *                               Valid options are:
     *                                 - $options['override'] Whether to override an existing file on copy or not (see copy())
     *                                 - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink())
     *                                 - $options['delete'] Whether to delete files that are not in the source directory (defaults to false)
     *
     * @throws IOException When file type is unknown
     */
    public function mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array())
    {
        $targetDir = rtrim($targetDir, '/\\');
        $originDir = rtrim($originDir, '/\\');

        // Iterate in destination folder to remove obsolete entries
        if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) {
            $deleteIterator = $iterator;
            if (null === $deleteIterator) {
                $flags = \FilesystemIterator::SKIP_DOTS;
                $deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST);
            }
            foreach ($deleteIterator as $file) {
                $origin = str_replace($targetDir, $originDir, $file->getPathname());
                if (!$this->exists($origin)) {
                    $this->remove($file);
                }
            }
        }

        $copyOnWindows = false;
        if (isset($options['copy_on_windows']) && !function_exists('symlink')) {
            $copyOnWindows = $options['copy_on_windows'];
        }

        if (null === $iterator) {
            $flags = $copyOnWindows ? \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS : \FilesystemIterator::SKIP_DOTS;
            $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, $flags), \RecursiveIteratorIterator::SELF_FIRST);
        }

        foreach ($iterator as $file) {
            $target = str_replace($originDir, $targetDir, $file->getPathname());

            if ($copyOnWindows) {
                if (is_link($file) || is_file($file)) {
                    $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
                } elseif (is_dir($file)) {
                    $this->mkdir($target);
                } else {
                    throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
                }
            } else {
                if (is_link($file)) {
                    $this->symlink($file, $target);
                } elseif (is_dir($file)) {
                    $this->mkdir($target);
                } elseif (is_file($file)) {
                    $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
                } else {
                    throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
                }
            }
        }
    }

    /**
     * Returns whether the file path is an absolute path.
     *
     * @param string $file A file path
     *
     * @return Boolean
     */
    public function isAbsolutePath($file)
    {
        if (strspn($file, '/\\', 0, 1)
            || (strlen($file) > 3 && ctype_alpha($file[0])
                && substr($file, 1, 1) === ':'
                && (strspn($file, '/\\', 2, 1))
            )
            || null !== parse_url($file, PHP_URL_SCHEME)
        ) {
            return true;
        }

        return false;
    }

    /**
     * Atomically dumps content into a file.
     *
     * @param  string  $filename The file to be written to.
     * @param  string  $content  The data to write into the file.
     * @param  integer $mode     The file mode (octal).
     * @throws IOException       If the file cannot be written to.
     */
    public function dumpFile($filename, $content, $mode = 0666)
    {
        $dir = dirname($filename);

        if (!is_dir($dir)) {
            $this->mkdir($dir);
        } elseif (!is_writable($dir)) {
            throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir);
        }

        $tmpFile = tempnam($dir, basename($filename));

        if (false === @file_put_contents($tmpFile, $content)) {
            throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename);
        }

        $this->rename($tmpFile, $filename, true);
        $this->chmod($filename, $mode);
    }

    /**
     * @param mixed $files
     *
     * @return \Traversable
     */
    private function toIterator($files)
    {
        if (!$files instanceof \Traversable) {
            $files = new \ArrayObject(is_array($files) ? $files : array($files));
        }

        return $files;
    }
}
Copyright (c) 2004-2013 Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Filesystem Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Tests</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Filesystem\Exception;

/**
 * Exception class thrown when a filesystem operation failure happens
 *
 * @author Romain Neutron <imprec@gmail.com>
 * @author Christian Gärtner <christiangaertner.film@googlemail.com>
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class IOException extends \RuntimeException implements IOExceptionInterface
{
    private $path;

    public function __construct($message, $code = 0, \Exception $previous = null, $path = null)
    {
        $this->path = $path;

        parent::__construct($message, $code, $previous);
    }

    /**
     * {@inheritdoc}
     */
    public function getPath()
    {
        return $this->path;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Filesystem\Exception;

/**
 * Exception class thrown when a file couldn't be found
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Christian Gärtner <christiangaertner.film@googlemail.com>
 */
class FileNotFoundException extends IOException
{
    public function __construct($message = null, $code = 0, \Exception $previous = null, $path = null)
    {
        if (null === $message) {
            if (null === $path) {
                $message = 'File could not be found.';
            } else {
                $message = sprintf('File "%s" could not be found.', $path);
            }
        }

        parent::__construct($message, $code, $previous, $path);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Filesystem\Exception;

/**
 * IOException interface for file and input/output stream related exceptions thrown by the component.
 *
 * @author Christian Gärtner <christiangaertner.film@googlemail.com>
 */
interface IOExceptionInterface extends ExceptionInterface
{
    /**
     * Returns the associated path for the exception
     *
     * @return string The path.
     */
    public function getPath();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Filesystem\Exception;

/**
 * Exception interface for all exceptions thrown by the component.
 *
 * @author Romain Neutron <imprec@gmail.com>
 *
 * @api
 */
interface ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Filesystem\Tests;

use Symfony\Component\Filesystem\Exception\IOException;
use Symfony\Component\Filesystem\Exception\FileNotFoundException;

/**
 * Test class for Filesystem.
 */
class ExceptionTest extends \PHPUnit_Framework_TestCase
{
    public function testGetPath()
    {
        $e = new IOException('', 0, null, '/foo');
        $this->assertEquals('/foo', $e->getPath(), 'The pass should be returned.');
    }

    public function testGeneratedMessage()
    {
        $e = new FileNotFoundException(null, 0, null, '/foo');
        $this->assertEquals('/foo', $e->getPath());
        $this->assertEquals('File "/foo" could not be found.', $e->getMessage(), 'A message should be generated.');
    }

    public function testGeneratedMessageWithoutPath()
    {
        $e = new FileNotFoundException();
        $this->assertEquals('File could not be found.', $e->getMessage(), 'A message should be generated.');
    }

    public function testCustomMessage()
    {
        $e = new FileNotFoundException('bar', 0, null, '/foo');
        $this->assertEquals('bar', $e->getMessage(), 'A custom message should be possible still.');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Filesystem\Tests;

class FilesystemTestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * @var string $workspace
     */
    protected $workspace = null;

    protected static $symlinkOnWindows = null;

    public static function setUpBeforeClass()
    {
        if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
            static::$symlinkOnWindows = true;
            $originDir = tempnam(sys_get_temp_dir(), 'sl');
            $targetDir = tempnam(sys_get_temp_dir(), 'sl');
            if (true !== @symlink($originDir, $targetDir)) {
                $report = error_get_last();
                if (is_array($report) && false !== strpos($report['message'], 'error code(1314)')) {
                    static::$symlinkOnWindows = false;
                }
            }
        }
    }

    public function setUp()
    {
        $this->workspace = rtrim(sys_get_temp_dir(), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.time().rand(0, 1000);
        mkdir($this->workspace, 0777, true);
        $this->workspace = realpath($this->workspace);
    }

    public function tearDown()
    {
        $this->clean($this->workspace);
    }

    /**
     * @param string $file
     */
    protected function clean($file)
    {
        if (is_dir($file) && !is_link($file)) {
            $dir = new \FilesystemIterator($file);
            foreach ($dir as $childFile) {
                $this->clean($childFile);
            }

            rmdir($file);
        } else {
            unlink($file);
        }
    }

    /**
     * @param int $expectedFilePerms expected file permissions as three digits (i.e. 755)
     * @param string $filePath
     */
    protected function assertFilePermissions($expectedFilePerms, $filePath)
    {
        $actualFilePerms = (int) substr(sprintf('%o', fileperms($filePath)), -3);
        $this->assertEquals(
            $expectedFilePerms,
            $actualFilePerms,
            sprintf('File permissions for %s must be %s. Actual %s', $filePath, $expectedFilePerms, $actualFilePerms)
        );
    }

    protected function getFileOwner($filepath)
    {
        $this->markAsSkippedIfPosixIsMissing();

        $infos = stat($filepath);
        if ($datas = posix_getpwuid($infos['uid'])) {
            return $datas['name'];
        }
    }

    protected function getFileGroup($filepath)
    {
        $this->markAsSkippedIfPosixIsMissing();

        $infos = stat($filepath);
        if ($datas = posix_getgrgid($infos['gid'])) {
            return $datas['name'];
        }
    }

    protected function markAsSkippedIfSymlinkIsMissing()
    {
        if (!function_exists('symlink')) {
            $this->markTestSkipped('symlink is not supported');
        }

        if (defined('PHP_WINDOWS_VERSION_MAJOR') && false === static::$symlinkOnWindows) {
            $this->markTestSkipped('symlink requires "Create symbolic links" privilege on windows');
        }
    }

    protected function markAsSkippedIfChmodIsMissing()
    {
        if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
            $this->markTestSkipped('chmod is not supported on windows');
        }
    }

    protected function markAsSkippedIfPosixIsMissing()
    {
        if (defined('PHP_WINDOWS_VERSION_MAJOR') || !function_exists('posix_isatty')) {
            $this->markTestSkipped('Posix is not supported');
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Filesystem\Tests;

use Symfony\Component\Filesystem\Filesystem;

/**
 * Test class for Filesystem.
 */
class FilesystemTest extends FilesystemTestCase
{
    /**
     * @var \Symfony\Component\Filesystem\Filesystem $filesystem
     */
    private $filesystem = null;

    public function setUp()
    {
        parent::setUp();
        $this->filesystem = new Filesystem();
    }

    public function testCopyCreatesNewFile()
    {
        $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
        $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';

        file_put_contents($sourceFilePath, 'SOURCE FILE');

        $this->filesystem->copy($sourceFilePath, $targetFilePath);

        $this->assertFileExists($targetFilePath);
        $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
    }

    /**
     * @expectedException \Symfony\Component\Filesystem\Exception\IOException
     */
    public function testCopyFails()
    {
        $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
        $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';

        $this->filesystem->copy($sourceFilePath, $targetFilePath);
    }

    public function testCopyOverridesExistingFileIfModified()
    {
        $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
        $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';

        file_put_contents($sourceFilePath, 'SOURCE FILE');
        file_put_contents($targetFilePath, 'TARGET FILE');
        touch($targetFilePath, time() - 1000);

        $this->filesystem->copy($sourceFilePath, $targetFilePath);

        $this->assertFileExists($targetFilePath);
        $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
    }

    public function testCopyDoesNotOverrideExistingFileByDefault()
    {
        $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
        $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';

        file_put_contents($sourceFilePath, 'SOURCE FILE');
        file_put_contents($targetFilePath, 'TARGET FILE');

        // make sure both files have the same modification time
        $modificationTime = time() - 1000;
        touch($sourceFilePath, $modificationTime);
        touch($targetFilePath, $modificationTime);

        $this->filesystem->copy($sourceFilePath, $targetFilePath);

        $this->assertFileExists($targetFilePath);
        $this->assertEquals('TARGET FILE', file_get_contents($targetFilePath));
    }

    public function testCopyOverridesExistingFileIfForced()
    {
        $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
        $targetFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_target_file';

        file_put_contents($sourceFilePath, 'SOURCE FILE');
        file_put_contents($targetFilePath, 'TARGET FILE');

        // make sure both files have the same modification time
        $modificationTime = time() - 1000;
        touch($sourceFilePath, $modificationTime);
        touch($targetFilePath, $modificationTime);

        $this->filesystem->copy($sourceFilePath, $targetFilePath, true);

        $this->assertFileExists($targetFilePath);
        $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
    }

    public function testCopyCreatesTargetDirectoryIfItDoesNotExist()
    {
        $sourceFilePath = $this->workspace.DIRECTORY_SEPARATOR.'copy_source_file';
        $targetFileDirectory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
        $targetFilePath = $targetFileDirectory.DIRECTORY_SEPARATOR.'copy_target_file';

        file_put_contents($sourceFilePath, 'SOURCE FILE');

        $this->filesystem->copy($sourceFilePath, $targetFilePath);

        $this->assertTrue(is_dir($targetFileDirectory));
        $this->assertFileExists($targetFilePath);
        $this->assertEquals('SOURCE FILE', file_get_contents($targetFilePath));
    }

    public function testMkdirCreatesDirectoriesRecursively()
    {
        $directory = $this->workspace
            .DIRECTORY_SEPARATOR.'directory'
            .DIRECTORY_SEPARATOR.'sub_directory';

        $this->filesystem->mkdir($directory);

        $this->assertTrue(is_dir($directory));
    }

    public function testMkdirCreatesDirectoriesFromArray()
    {
        $basePath = $this->workspace.DIRECTORY_SEPARATOR;
        $directories = array(
            $basePath.'1', $basePath.'2', $basePath.'3'
        );

        $this->filesystem->mkdir($directories);

        $this->assertTrue(is_dir($basePath.'1'));
        $this->assertTrue(is_dir($basePath.'2'));
        $this->assertTrue(is_dir($basePath.'3'));
    }

    public function testMkdirCreatesDirectoriesFromTraversableObject()
    {
        $basePath = $this->workspace.DIRECTORY_SEPARATOR;
        $directories = new \ArrayObject(array(
            $basePath.'1', $basePath.'2', $basePath.'3'
        ));

        $this->filesystem->mkdir($directories);

        $this->assertTrue(is_dir($basePath.'1'));
        $this->assertTrue(is_dir($basePath.'2'));
        $this->assertTrue(is_dir($basePath.'3'));
    }

    /**
     * @expectedException \Symfony\Component\Filesystem\Exception\IOException
     */
    public function testMkdirCreatesDirectoriesFails()
    {
        $basePath = $this->workspace.DIRECTORY_SEPARATOR;
        $dir = $basePath.'2';

        file_put_contents($dir, '');

        $this->filesystem->mkdir($dir);
    }

    public function testTouchCreatesEmptyFile()
    {
        $file = $this->workspace.DIRECTORY_SEPARATOR.'1';

        $this->filesystem->touch($file);

        $this->assertFileExists($file);
    }

    /**
     * @expectedException \Symfony\Component\Filesystem\Exception\IOException
     */
    public function testTouchFails()
    {
        $file = $this->workspace.DIRECTORY_SEPARATOR.'1'.DIRECTORY_SEPARATOR.'2';

        $this->filesystem->touch($file);
    }

    public function testTouchCreatesEmptyFilesFromArray()
    {
        $basePath = $this->workspace.DIRECTORY_SEPARATOR;
        $files = array(
            $basePath.'1', $basePath.'2', $basePath.'3'
        );

        $this->filesystem->touch($files);

        $this->assertFileExists($basePath.'1');
        $this->assertFileExists($basePath.'2');
        $this->assertFileExists($basePath.'3');
    }

    public function testTouchCreatesEmptyFilesFromTraversableObject()
    {
        $basePath = $this->workspace.DIRECTORY_SEPARATOR;
        $files = new \ArrayObject(array(
            $basePath.'1', $basePath.'2', $basePath.'3'
        ));

        $this->filesystem->touch($files);

        $this->assertFileExists($basePath.'1');
        $this->assertFileExists($basePath.'2');
        $this->assertFileExists($basePath.'3');
    }

    public function testRemoveCleansFilesAndDirectoriesIteratively()
    {
        $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;

        mkdir($basePath);
        mkdir($basePath.'dir');
        touch($basePath.'file');

        $this->filesystem->remove($basePath);

        $this->assertTrue(!is_dir($basePath));
    }

    public function testRemoveCleansArrayOfFilesAndDirectories()
    {
        $basePath = $this->workspace.DIRECTORY_SEPARATOR;

        mkdir($basePath.'dir');
        touch($basePath.'file');

        $files = array(
            $basePath.'dir', $basePath.'file'
        );

        $this->filesystem->remove($files);

        $this->assertTrue(!is_dir($basePath.'dir'));
        $this->assertTrue(!is_file($basePath.'file'));
    }

    public function testRemoveCleansTraversableObjectOfFilesAndDirectories()
    {
        $basePath = $this->workspace.DIRECTORY_SEPARATOR;

        mkdir($basePath.'dir');
        touch($basePath.'file');

        $files = new \ArrayObject(array(
            $basePath.'dir', $basePath.'file'
        ));

        $this->filesystem->remove($files);

        $this->assertTrue(!is_dir($basePath.'dir'));
        $this->assertTrue(!is_file($basePath.'file'));
    }

    public function testRemoveIgnoresNonExistingFiles()
    {
        $basePath = $this->workspace.DIRECTORY_SEPARATOR;

        mkdir($basePath.'dir');

        $files = array(
            $basePath.'dir', $basePath.'file'
        );

        $this->filesystem->remove($files);

        $this->assertTrue(!is_dir($basePath.'dir'));
    }

    public function testRemoveCleansInvalidLinks()
    {
        $this->markAsSkippedIfSymlinkIsMissing();

        $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;

        mkdir($basePath);
        mkdir($basePath.'dir');
        // create symlink to unexisting file
        @symlink($basePath.'file', $basePath.'link');

        $this->filesystem->remove($basePath);

        $this->assertTrue(!is_dir($basePath));
    }

    public function testFilesExists()
    {
        $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;

        mkdir($basePath);
        touch($basePath.'file1');
        mkdir($basePath.'folder');

        $this->assertTrue($this->filesystem->exists($basePath.'file1'));
        $this->assertTrue($this->filesystem->exists($basePath.'folder'));
    }

    public function testFilesExistsTraversableObjectOfFilesAndDirectories()
    {
        $basePath = $this->workspace.DIRECTORY_SEPARATOR;

        mkdir($basePath.'dir');
        touch($basePath.'file');

        $files = new \ArrayObject(array(
            $basePath.'dir', $basePath.'file'
        ));

        $this->assertTrue($this->filesystem->exists($files));
    }

    public function testFilesNotExistsTraversableObjectOfFilesAndDirectories()
    {
        $basePath = $this->workspace.DIRECTORY_SEPARATOR;

        mkdir($basePath.'dir');
        touch($basePath.'file');
        touch($basePath.'file2');

        $files = new \ArrayObject(array(
            $basePath.'dir', $basePath.'file', $basePath.'file2'
        ));

        unlink($basePath.'file');

        $this->assertFalse($this->filesystem->exists($files));
    }

    public function testInvalidFileNotExists()
    {
        $basePath = $this->workspace.DIRECTORY_SEPARATOR.'directory'.DIRECTORY_SEPARATOR;

        $this->assertFalse($this->filesystem->exists($basePath.time()));
    }

    public function testChmodChangesFileMode()
    {
        $this->markAsSkippedIfChmodIsMissing();

        $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
        mkdir($dir);
        $file = $dir.DIRECTORY_SEPARATOR.'file';
        touch($file);

        $this->filesystem->chmod($file, 0400);
        $this->filesystem->chmod($dir, 0753);

        $this->assertFilePermissions(753, $dir);
        $this->assertFilePermissions(400, $file);
    }

    public function testChmodWrongMod()
    {
        $this->markAsSkippedIfChmodIsMissing();

        $dir = $this->workspace.DIRECTORY_SEPARATOR.'file';
        touch($dir);

        $this->filesystem->chmod($dir, 'Wrongmode');
    }

    public function testChmodRecursive()
    {
        $this->markAsSkippedIfChmodIsMissing();

        $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
        mkdir($dir);
        $file = $dir.DIRECTORY_SEPARATOR.'file';
        touch($file);

        $this->filesystem->chmod($file, 0400, 0000, true);
        $this->filesystem->chmod($dir, 0753, 0000, true);

        $this->assertFilePermissions(753, $dir);
        $this->assertFilePermissions(753, $file);
    }

    public function testChmodAppliesUmask()
    {
        $this->markAsSkippedIfChmodIsMissing();

        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        touch($file);

        $this->filesystem->chmod($file, 0770, 0022);
        $this->assertFilePermissions(750, $file);
    }

    public function testChmodChangesModeOfArrayOfFiles()
    {
        $this->markAsSkippedIfChmodIsMissing();

        $directory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        $files = array($directory, $file);

        mkdir($directory);
        touch($file);

        $this->filesystem->chmod($files, 0753);

        $this->assertFilePermissions(753, $file);
        $this->assertFilePermissions(753, $directory);
    }

    public function testChmodChangesModeOfTraversableFileObject()
    {
        $this->markAsSkippedIfChmodIsMissing();

        $directory = $this->workspace.DIRECTORY_SEPARATOR.'directory';
        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        $files = new \ArrayObject(array($directory, $file));

        mkdir($directory);
        touch($file);

        $this->filesystem->chmod($files, 0753);

        $this->assertFilePermissions(753, $file);
        $this->assertFilePermissions(753, $directory);
    }

    public function testChown()
    {
        $this->markAsSkippedIfPosixIsMissing();

        $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
        mkdir($dir);

        $this->filesystem->chown($dir, $this->getFileOwner($dir));
    }

    public function testChownRecursive()
    {
        $this->markAsSkippedIfPosixIsMissing();

        $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
        mkdir($dir);
        $file = $dir.DIRECTORY_SEPARATOR.'file';
        touch($file);

        $this->filesystem->chown($dir, $this->getFileOwner($dir), true);
    }

    public function testChownSymlink()
    {
        $this->markAsSkippedIfSymlinkIsMissing();

        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        $link = $this->workspace.DIRECTORY_SEPARATOR.'link';

        touch($file);

        $this->filesystem->symlink($file, $link);

        $this->filesystem->chown($link, $this->getFileOwner($link));
    }

    /**
     * @expectedException \Symfony\Component\Filesystem\Exception\IOException
     */
    public function testChownSymlinkFails()
    {
        $this->markAsSkippedIfSymlinkIsMissing();

        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        $link = $this->workspace.DIRECTORY_SEPARATOR.'link';

        touch($file);

        $this->filesystem->symlink($file, $link);

        $this->filesystem->chown($link, 'user'.time().mt_rand(1000, 9999));
    }

    /**
     * @expectedException \Symfony\Component\Filesystem\Exception\IOException
     */
    public function testChownFail()
    {
        $this->markAsSkippedIfPosixIsMissing();

        $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
        mkdir($dir);

        $this->filesystem->chown($dir, 'user'.time().mt_rand(1000, 9999));
    }

    public function testChgrp()
    {
        $this->markAsSkippedIfPosixIsMissing();

        $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
        mkdir($dir);

        $this->filesystem->chgrp($dir, $this->getFileGroup($dir));
    }

    public function testChgrpRecursive()
    {
        $this->markAsSkippedIfPosixIsMissing();

        $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
        mkdir($dir);
        $file = $dir.DIRECTORY_SEPARATOR.'file';
        touch($file);

        $this->filesystem->chgrp($dir, $this->getFileGroup($dir), true);
    }

    public function testChgrpSymlink()
    {
        $this->markAsSkippedIfSymlinkIsMissing();

        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        $link = $this->workspace.DIRECTORY_SEPARATOR.'link';

        touch($file);

        $this->filesystem->symlink($file, $link);

        $this->filesystem->chgrp($link, $this->getFileGroup($link));
    }

    /**
     * @expectedException \Symfony\Component\Filesystem\Exception\IOException
     */
    public function testChgrpSymlinkFails()
    {
        $this->markAsSkippedIfSymlinkIsMissing();

        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        $link = $this->workspace.DIRECTORY_SEPARATOR.'link';

        touch($file);

        $this->filesystem->symlink($file, $link);

        $this->filesystem->chgrp($link, 'user'.time().mt_rand(1000, 9999));
    }

    /**
     * @expectedException \Symfony\Component\Filesystem\Exception\IOException
     */
    public function testChgrpFail()
    {
        $this->markAsSkippedIfPosixIsMissing();

        $dir = $this->workspace.DIRECTORY_SEPARATOR.'dir';
        mkdir($dir);

        $this->filesystem->chgrp($dir, 'user'.time().mt_rand(1000, 9999));
    }

    public function testRename()
    {
        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';
        touch($file);

        $this->filesystem->rename($file, $newPath);

        $this->assertFileNotExists($file);
        $this->assertFileExists($newPath);
    }

    /**
     * @expectedException \Symfony\Component\Filesystem\Exception\IOException
     */
    public function testRenameThrowsExceptionIfTargetAlreadyExists()
    {
        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';

        touch($file);
        touch($newPath);

        $this->filesystem->rename($file, $newPath);
    }

    public function testRenameOverwritesTheTargetIfItAlreadyExists()
    {
        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';

        touch($file);
        touch($newPath);

        $this->filesystem->rename($file, $newPath, true);

        $this->assertFileNotExists($file);
        $this->assertFileExists($newPath);
    }

    /**
     * @expectedException \Symfony\Component\Filesystem\Exception\IOException
     */
    public function testRenameThrowsExceptionOnError()
    {
        $file = $this->workspace.DIRECTORY_SEPARATOR.uniqid();
        $newPath = $this->workspace.DIRECTORY_SEPARATOR.'new_file';

        $this->filesystem->rename($file, $newPath);
    }

    public function testSymlink()
    {
        $this->markAsSkippedIfSymlinkIsMissing();

        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        $link = $this->workspace.DIRECTORY_SEPARATOR.'link';

        touch($file);

        $this->filesystem->symlink($file, $link);

        $this->assertTrue(is_link($link));
        $this->assertEquals($file, readlink($link));
    }

    /**
     * @depends testSymlink
     */
    public function testRemoveSymlink()
    {
        $this->markAsSkippedIfSymlinkIsMissing();

        $link = $this->workspace.DIRECTORY_SEPARATOR.'link';

        $this->filesystem->remove($link);

        $this->assertTrue(!is_link($link));
    }

    public function testSymlinkIsOverwrittenIfPointsToDifferentTarget()
    {
        $this->markAsSkippedIfSymlinkIsMissing();

        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        $link = $this->workspace.DIRECTORY_SEPARATOR.'link';

        touch($file);
        symlink($this->workspace, $link);

        $this->filesystem->symlink($file, $link);

        $this->assertTrue(is_link($link));
        $this->assertEquals($file, readlink($link));
    }

    public function testSymlinkIsNotOverwrittenIfAlreadyCreated()
    {
        $this->markAsSkippedIfSymlinkIsMissing();

        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        $link = $this->workspace.DIRECTORY_SEPARATOR.'link';

        touch($file);
        symlink($file, $link);

        $this->filesystem->symlink($file, $link);

        $this->assertTrue(is_link($link));
        $this->assertEquals($file, readlink($link));
    }

    public function testSymlinkCreatesTargetDirectoryIfItDoesNotExist()
    {
        $this->markAsSkippedIfSymlinkIsMissing();

        $file = $this->workspace.DIRECTORY_SEPARATOR.'file';
        $link1 = $this->workspace.DIRECTORY_SEPARATOR.'dir'.DIRECTORY_SEPARATOR.'link';
        $link2 = $this->workspace.DIRECTORY_SEPARATOR.'dir'.DIRECTORY_SEPARATOR.'subdir'.DIRECTORY_SEPARATOR.'link';

        touch($file);

        $this->filesystem->symlink($file, $link1);
        $this->filesystem->symlink($file, $link2);

        $this->assertTrue(is_link($link1));
        $this->assertEquals($file, readlink($link1));
        $this->assertTrue(is_link($link2));
        $this->assertEquals($file, readlink($link2));
    }

    /**
     * @dataProvider providePathsForMakePathRelative
     */
    public function testMakePathRelative($endPath, $startPath, $expectedPath)
    {
        $path = $this->filesystem->makePathRelative($endPath, $startPath);

        $this->assertEquals($expectedPath, $path);
    }

    /**
     * @return array
     */
    public function providePathsForMakePathRelative()
    {
        $paths = array(
            array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/src/Symfony/Component', '../'),
            array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/src/Symfony/Component/', '../'),
            array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component', '../'),
            array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component/', '../'),
            array('var/lib/symfony/', 'var/lib/symfony/src/Symfony/Component', '../../../'),
            array('/usr/lib/symfony/', '/var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'),
            array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/', 'src/Symfony/'),
            array('/aa/bb', '/aa/bb', './'),
            array('/aa/bb', '/aa/bb/', './'),
            array('/aa/bb/', '/aa/bb', './'),
            array('/aa/bb/', '/aa/bb/', './'),
            array('/aa/bb/cc', '/aa/bb/cc/dd', '../'),
            array('/aa/bb/cc', '/aa/bb/cc/dd/', '../'),
            array('/aa/bb/cc/', '/aa/bb/cc/dd', '../'),
            array('/aa/bb/cc/', '/aa/bb/cc/dd/', '../'),
            array('/aa/bb/cc', '/aa', 'bb/cc/'),
            array('/aa/bb/cc', '/aa/', 'bb/cc/'),
            array('/aa/bb/cc/', '/aa', 'bb/cc/'),
            array('/aa/bb/cc/', '/aa/', 'bb/cc/'),
            array('/a/aab/bb', '/a/aa', '../aab/bb/'),
            array('/a/aab/bb', '/a/aa/', '../aab/bb/'),
            array('/a/aab/bb/', '/a/aa', '../aab/bb/'),
            array('/a/aab/bb/', '/a/aa/', '../aab/bb/'),
        );

        if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
            $paths[] = array('c:\var\lib/symfony/src/Symfony/', 'c:/var/lib/symfony/', 'src/Symfony/');
        }

        return $paths;
    }

    public function testMirrorCopiesFilesAndDirectoriesRecursively()
    {
        $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;
        $directory = $sourcePath.'directory'.DIRECTORY_SEPARATOR;
        $file1 = $directory.'file1';
        $file2 = $sourcePath.'file2';

        mkdir($sourcePath);
        mkdir($directory);
        file_put_contents($file1, 'FILE1');
        file_put_contents($file2, 'FILE2');

        $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;

        $this->filesystem->mirror($sourcePath, $targetPath);

        $this->assertTrue(is_dir($targetPath));
        $this->assertTrue(is_dir($targetPath.'directory'));
        $this->assertFileEquals($file1, $targetPath.'directory'.DIRECTORY_SEPARATOR.'file1');
        $this->assertFileEquals($file2, $targetPath.'file2');

        $this->filesystem->remove($file1);

        $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => false));
        $this->assertTrue($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));

        $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
        $this->assertFalse($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));

        file_put_contents($file1, 'FILE1');

        $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
        $this->assertTrue($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));

        $this->filesystem->remove($directory);
        $this->filesystem->mirror($sourcePath, $targetPath, null, array('delete' => true));
        $this->assertFalse($this->filesystem->exists($targetPath.'directory'));
        $this->assertFalse($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'));
    }

    public function testMirrorCopiesLinks()
    {
        $this->markAsSkippedIfSymlinkIsMissing();

        $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;

        mkdir($sourcePath);
        file_put_contents($sourcePath.'file1', 'FILE1');
        symlink($sourcePath.'file1', $sourcePath.'link1');

        $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;

        $this->filesystem->mirror($sourcePath, $targetPath);

        $this->assertTrue(is_dir($targetPath));
        $this->assertFileEquals($sourcePath.'file1', $targetPath.DIRECTORY_SEPARATOR.'link1');
        $this->assertTrue(is_link($targetPath.DIRECTORY_SEPARATOR.'link1'));
    }

    public function testMirrorCopiesLinkedDirectoryContents()
    {
        $this->markAsSkippedIfSymlinkIsMissing();

        $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR;

        mkdir($sourcePath.'nested/', 0777, true);
        file_put_contents($sourcePath.'/nested/file1.txt', 'FILE1');
        // Note: We symlink directory, not file
        symlink($sourcePath.'nested', $sourcePath.'link1');

        $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR;

        $this->filesystem->mirror($sourcePath, $targetPath);

        $this->assertTrue(is_dir($targetPath));
        $this->assertFileEquals($sourcePath.'/nested/file1.txt', $targetPath.DIRECTORY_SEPARATOR.'link1/file1.txt');
        $this->assertTrue(is_link($targetPath.DIRECTORY_SEPARATOR.'link1'));
    }

    /**
     * @dataProvider providePathsForIsAbsolutePath
     */
    public function testIsAbsolutePath($path, $expectedResult)
    {
        $result = $this->filesystem->isAbsolutePath($path);

        $this->assertEquals($expectedResult, $result);
    }

    /**
     * @return array
     */
    public function providePathsForIsAbsolutePath()
    {
        return array(
            array('/var/lib', true),
            array('c:\\\\var\\lib', true),
            array('\\var\\lib', true),
            array('var/lib', false),
            array('../var/lib', false),
            array('', false),
            array(null, false)
        );
    }

    public function testDumpFile()
    {
        $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt';

        $this->filesystem->dumpFile($filename, 'bar', 0753);

        $this->assertFileExists($filename);
        $this->assertSame('bar', file_get_contents($filename));

        // skip mode check on windows
        if (!defined('PHP_WINDOWS_VERSION_MAJOR')) {
            $this->assertFilePermissions(753, $filename);
        }
    }

    public function testDumpFileOverwritesAnExistingFile()
    {
        $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo.txt';
        file_put_contents($filename, 'FOO BAR');

        $this->filesystem->dumpFile($filename, 'bar');

        $this->assertFileExists($filename);
        $this->assertSame('bar', file_get_contents($filename));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException;

/**
 * Definition represents a service definition.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Definition
{
    private $class;
    private $file;
    private $factoryClass;
    private $factoryMethod;
    private $factoryService;
    private $scope = ContainerInterface::SCOPE_CONTAINER;
    private $properties = array();
    private $calls = array();
    private $configurator;
    private $tags = array();
    private $public = true;
    private $synthetic = false;
    private $abstract = false;
    private $synchronized = false;
    private $lazy = false;

    protected $arguments;

    /**
     * Constructor.
     *
     * @param string|null $class     The service class
     * @param array       $arguments An array of arguments to pass to the service constructor
     *
     * @api
     */
    public function __construct($class = null, array $arguments = array())
    {
        $this->class = $class;
        $this->arguments = $arguments;
    }

    /**
     * Sets the name of the class that acts as a factory using the factory method,
     * which will be invoked statically.
     *
     * @param string $factoryClass The factory class name
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function setFactoryClass($factoryClass)
    {
        $this->factoryClass = $factoryClass;

        return $this;
    }

    /**
     * Gets the factory class.
     *
     * @return string|null The factory class name
     *
     * @api
     */
    public function getFactoryClass()
    {
        return $this->factoryClass;
    }

    /**
     * Sets the factory method able to create an instance of this class.
     *
     * @param string $factoryMethod The factory method name
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function setFactoryMethod($factoryMethod)
    {
        $this->factoryMethod = $factoryMethod;

        return $this;
    }

    /**
     * Gets the factory method.
     *
     * @return string|null The factory method name
     *
     * @api
     */
    public function getFactoryMethod()
    {
        return $this->factoryMethod;
    }

    /**
     * Sets the name of the service that acts as a factory using the factory method.
     *
     * @param string $factoryService The factory service id
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function setFactoryService($factoryService)
    {
        $this->factoryService = $factoryService;

        return $this;
    }

    /**
     * Gets the factory service id.
     *
     * @return string|null The factory service id
     *
     * @api
     */
    public function getFactoryService()
    {
        return $this->factoryService;
    }

    /**
     * Sets the service class.
     *
     * @param string $class The service class
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function setClass($class)
    {
        $this->class = $class;

        return $this;
    }

    /**
     * Gets the service class.
     *
     * @return string|null The service class
     *
     * @api
     */
    public function getClass()
    {
        return $this->class;
    }

    /**
     * Sets the arguments to pass to the service constructor/factory method.
     *
     * @param array $arguments An array of arguments
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function setArguments(array $arguments)
    {
        $this->arguments = $arguments;

        return $this;
    }

    /**
     * @api
     */
    public function setProperties(array $properties)
    {
        $this->properties = $properties;

        return $this;
    }

    /**
     * @api
     */
    public function getProperties()
    {
        return $this->properties;
    }

    /**
     * @api
     */
    public function setProperty($name, $value)
    {
        $this->properties[$name] = $value;

        return $this;
    }

    /**
     * Adds an argument to pass to the service constructor/factory method.
     *
     * @param mixed $argument An argument
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function addArgument($argument)
    {
        $this->arguments[] = $argument;

        return $this;
    }

    /**
     * Sets a specific argument
     *
     * @param integer $index
     * @param mixed   $argument
     *
     * @return Definition The current instance
     *
     * @throws OutOfBoundsException When the replaced argument does not exist
     *
     * @api
     */
    public function replaceArgument($index, $argument)
    {
        if ($index < 0 || $index > count($this->arguments) - 1) {
            throw new OutOfBoundsException(sprintf('The index "%d" is not in the range [0, %d].', $index, count($this->arguments) - 1));
        }

        $this->arguments[$index] = $argument;

        return $this;
    }

    /**
     * Gets the arguments to pass to the service constructor/factory method.
     *
     * @return array The array of arguments
     *
     * @api
     */
    public function getArguments()
    {
        return $this->arguments;
    }

    /**
     * Gets an argument to pass to the service constructor/factory method.
     *
     * @param integer $index
     *
     * @return mixed The argument value
     *
     * @throws OutOfBoundsException When the argument does not exist
     *
     * @api
     */
    public function getArgument($index)
    {
        if ($index < 0 || $index > count($this->arguments) - 1) {
            throw new OutOfBoundsException(sprintf('The index "%d" is not in the range [0, %d].', $index, count($this->arguments) - 1));
        }

        return $this->arguments[$index];
    }

    /**
     * Sets the methods to call after service initialization.
     *
     * @param array $calls An array of method calls
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function setMethodCalls(array $calls = array())
    {
        $this->calls = array();
        foreach ($calls as $call) {
            $this->addMethodCall($call[0], $call[1]);
        }

        return $this;
    }

    /**
     * Adds a method to call after service initialization.
     *
     * @param string $method    The method name to call
     * @param array  $arguments An array of arguments to pass to the method call
     *
     * @return Definition The current instance
     *
     * @throws InvalidArgumentException on empty $method param
     *
     * @api
     */
    public function addMethodCall($method, array $arguments = array())
    {
        if (empty($method)) {
            throw new InvalidArgumentException(sprintf('Method name cannot be empty.'));
        }
        $this->calls[] = array($method, $arguments);

        return $this;
    }

    /**
     * Removes a method to call after service initialization.
     *
     * @param string $method The method name to remove
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function removeMethodCall($method)
    {
        foreach ($this->calls as $i => $call) {
            if ($call[0] === $method) {
                unset($this->calls[$i]);
                break;
            }
        }

        return $this;
    }

    /**
     * Check if the current definition has a given method to call after service initialization.
     *
     * @param string $method The method name to search for
     *
     * @return Boolean
     *
     * @api
     */
    public function hasMethodCall($method)
    {
        foreach ($this->calls as $call) {
            if ($call[0] === $method) {
                return true;
            }
        }

        return false;
    }

    /**
     * Gets the methods to call after service initialization.
     *
     * @return array An array of method calls
     *
     * @api
     */
    public function getMethodCalls()
    {
        return $this->calls;
    }

    /**
     * Sets tags for this definition
     *
     * @param array $tags
     *
     * @return Definition the current instance
     *
     * @api
     */
    public function setTags(array $tags)
    {
        $this->tags = $tags;

        return $this;
    }

    /**
     * Returns all tags.
     *
     * @return array An array of tags
     *
     * @api
     */
    public function getTags()
    {
        return $this->tags;
    }

    /**
     * Gets a tag by name.
     *
     * @param string $name The tag name
     *
     * @return array An array of attributes
     *
     * @api
     */
    public function getTag($name)
    {
        return isset($this->tags[$name]) ? $this->tags[$name] : array();
    }

    /**
     * Adds a tag for this definition.
     *
     * @param string $name       The tag name
     * @param array  $attributes An array of attributes
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function addTag($name, array $attributes = array())
    {
        $this->tags[$name][] = $attributes;

        return $this;
    }

    /**
     * Whether this definition has a tag with the given name
     *
     * @param string $name
     *
     * @return Boolean
     *
     * @api
     */
    public function hasTag($name)
    {
        return isset($this->tags[$name]);
    }

    /**
     * Clears all tags for a given name.
     *
     * @param string $name The tag name
     *
     * @return Definition
     */
    public function clearTag($name)
    {
        if (isset($this->tags[$name])) {
            unset($this->tags[$name]);
        }

        return $this;
    }

    /**
     * Clears the tags for this definition.
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function clearTags()
    {
        $this->tags = array();

        return $this;
    }

    /**
     * Sets a file to require before creating the service.
     *
     * @param string $file A full pathname to include
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function setFile($file)
    {
        $this->file = $file;

        return $this;
    }

    /**
     * Gets the file to require before creating the service.
     *
     * @return string|null The full pathname to include
     *
     * @api
     */
    public function getFile()
    {
        return $this->file;
    }

    /**
     * Sets the scope of the service
     *
     * @param string $scope Whether the service must be shared or not
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function setScope($scope)
    {
        $this->scope = $scope;

        return $this;
    }

    /**
     * Returns the scope of the service
     *
     * @return string
     *
     * @api
     */
    public function getScope()
    {
        return $this->scope;
    }

    /**
     * Sets the visibility of this service.
     *
     * @param Boolean $boolean
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function setPublic($boolean)
    {
        $this->public = (Boolean) $boolean;

        return $this;
    }

    /**
     * Whether this service is public facing
     *
     * @return Boolean
     *
     * @api
     */
    public function isPublic()
    {
        return $this->public;
    }

    /**
     * Sets the synchronized flag of this service.
     *
     * @param Boolean $boolean
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function setSynchronized($boolean)
    {
        $this->synchronized = (Boolean) $boolean;

        return $this;
    }

    /**
     * Whether this service is synchronized.
     *
     * @return Boolean
     *
     * @api
     */
    public function isSynchronized()
    {
        return $this->synchronized;
    }

    /**
     * Sets the lazy flag of this service.
     *
     * @param Boolean $lazy
     *
     * @return Definition The current instance
     */
    public function setLazy($lazy)
    {
        $this->lazy = (Boolean) $lazy;

        return $this;
    }

    /**
     * Whether this service is lazy.
     *
     * @return Boolean
     */
    public function isLazy()
    {
        return $this->lazy;
    }

    /**
     * Sets whether this definition is synthetic, that is not constructed by the
     * container, but dynamically injected.
     *
     * @param Boolean $boolean
     *
     * @return Definition the current instance
     *
     * @api
     */
    public function setSynthetic($boolean)
    {
        $this->synthetic = (Boolean) $boolean;

        return $this;
    }

    /**
     * Whether this definition is synthetic, that is not constructed by the
     * container, but dynamically injected.
     *
     * @return Boolean
     *
     * @api
     */
    public function isSynthetic()
    {
        return $this->synthetic;
    }

    /**
     * Whether this definition is abstract, that means it merely serves as a
     * template for other definitions.
     *
     * @param Boolean $boolean
     *
     * @return Definition the current instance
     *
     * @api
     */
    public function setAbstract($boolean)
    {
        $this->abstract = (Boolean) $boolean;

        return $this;
    }

    /**
     * Whether this definition is abstract, that means it merely serves as a
     * template for other definitions.
     *
     * @return Boolean
     *
     * @api
     */
    public function isAbstract()
    {
        return $this->abstract;
    }

    /**
     * Sets a configurator to call after the service is fully initialized.
     *
     * @param callable $callable A PHP callable
     *
     * @return Definition The current instance
     *
     * @api
     */
    public function setConfigurator($callable)
    {
        $this->configurator = $callable;

        return $this;
    }

    /**
     * Gets the configurator to call after the service is fully initialized.
     *
     * @return callable|null The PHP callable to call
     *
     * @api
     */
    public function getConfigurator()
    {
        return $this->configurator;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

/**
 * Scope Interface.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @api
 */
interface ScopeInterface
{
    /**
     * @api
     */
    public function getName();

    /**
     * @api
     */
    public function getParentName();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Extension;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

/**
 * ConfigurationExtensionInterface is the interface implemented by container extension classes.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
interface ConfigurationExtensionInterface
{
    /**
     * Returns extension configuration
     *
     * @param array            $config    $config    An array of configuration values
     * @param ContainerBuilder $container A ContainerBuilder instance
     *
     * @return ConfigurationInterface|null The configuration or null
     */
    public function getConfiguration(array $config, ContainerBuilder $container);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Extension;

use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * ExtensionInterface is the interface implemented by container extension classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface ExtensionInterface
{
    /**
     * Loads a specific configuration.
     *
     * @param array            $config    An array of configuration values
     * @param ContainerBuilder $container A ContainerBuilder instance
     *
     * @throws \InvalidArgumentException When provided tag is not defined in this extension
     *
     * @api
     */
    public function load(array $config, ContainerBuilder $container);

    /**
     * Returns the namespace to be used for this extension (XML namespace).
     *
     * @return string The XML namespace
     *
     * @api
     */
    public function getNamespace();

    /**
     * Returns the base path for the XSD files.
     *
     * @return string The XSD base path
     *
     * @api
     */
    public function getXsdValidationBasePath();

    /**
     * Returns the recommended alias to use in XML.
     *
     * This alias is also the mandatory prefix to use when using YAML.
     *
     * @return string The alias
     *
     * @api
     */
    public function getAlias();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Extension;

use Symfony\Component\DependencyInjection\ContainerBuilder;

interface PrependExtensionInterface
{
    /**
     * Allow an extension to prepend the extension configurations.
     *
     * @param ContainerBuilder $container
     */
    public function prepend(ContainerBuilder $container);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Extension;

use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\BadMethodCallException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\Definition\Processor;
use Symfony\Component\Config\Definition\ConfigurationInterface;

/**
 * Provides useful features shared by many extensions.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Extension implements ExtensionInterface, ConfigurationExtensionInterface
{
    /**
     * Returns the base path for the XSD files.
     *
     * @return string The XSD base path
     */
    public function getXsdValidationBasePath()
    {
        return false;
    }

    /**
     * Returns the namespace to be used for this extension (XML namespace).
     *
     * @return string The XML namespace
     */
    public function getNamespace()
    {
        return 'http://example.org/schema/dic/'.$this->getAlias();
    }

    /**
     * Returns the recommended alias to use in XML.
     *
     * This alias is also the mandatory prefix to use when using YAML.
     *
     * This convention is to remove the "Extension" postfix from the class
     * name and then lowercase and underscore the result. So:
     *
     *     AcmeHelloExtension
     *
     * becomes
     *
     *     acme_hello
     *
     * This can be overridden in a sub-class to specify the alias manually.
     *
     * @return string The alias
     *
     * @throws BadMethodCallException When the extension name does not follow conventions
     */
    public function getAlias()
    {
        $className = get_class($this);
        if (substr($className, -9) != 'Extension') {
            throw new BadMethodCallException('This extension does not follow the naming convention; you must overwrite the getAlias() method.');
        }
        $classBaseName = substr(strrchr($className, '\\'), 1, -9);

        return Container::underscore($classBaseName);
    }

    /**
     * {@inheritDoc}
     */
    public function getConfiguration(array $config, ContainerBuilder $container)
    {
        $reflected = new \ReflectionClass($this);
        $namespace = $reflected->getNamespaceName();

        $class = $namespace.'\\Configuration';
        if (class_exists($class)) {
            $r = new \ReflectionClass($class);
            $container->addResource(new FileResource($r->getFileName()));

            if (!method_exists($class, '__construct')) {
                $configuration = new $class();

                return $configuration;
            }
        }

        return null;
    }

    final protected function processConfiguration(ConfigurationInterface $configuration, array $configs)
    {
        $processor = new Processor();

        return $processor->processConfiguration($configuration, $configs);
    }

    /**
     * @param ContainerBuilder $container
     * @param array            $config
     *
     * @return Boolean Whether the configuration is enabled
     *
     * @throws InvalidArgumentException When the config is not enableable
     */
    protected function isConfigEnabled(ContainerBuilder $container, array $config)
    {
        if (!array_key_exists('enabled', $config)) {
            throw new InvalidArgumentException("The config array has no 'enabled' key.");
        }

        return (Boolean) $container->getParameterBag()->resolveValue($config['enabled']);
    }
}
{
    "name": "symfony/dependency-injection",
    "type": "library",
    "description": "Symfony DependencyInjection Component",
    "keywords": [],
    "homepage": "http://symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "http://symfony.com/contributors"
        }
    ],
    "require": {
        "php": ">=5.3.3"
    },
    "require-dev": {
        "symfony/yaml": "~2.0",
        "symfony/config": "~2.2",
        "symfony/expression-language": "~2.4"
    },
    "suggest": {
        "symfony/yaml": "",
        "symfony/config": "",
        "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them"
    },
    "autoload": {
        "psr-0": { "Symfony\\Component\\DependencyInjection\\": "" }
    },
    "target-dir": "Symfony/Component/DependencyInjection",
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-master": "2.4-dev"
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

/**
 * TaggedContainerInterface is the interface implemented when a container knows how to deals with tags.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface TaggedContainerInterface extends ContainerInterface
{
    /**
     * Returns service ids for a given tag.
     *
     * @param string $name The tag name
     *
     * @return array An array of tags
     *
     * @api
     */
    public function findTaggedServiceIds($name);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Dumper;

use Symfony\Component\Yaml\Dumper as YmlDumper;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Parameter;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\ExpressionLanguage\Expression;

/**
 * YamlDumper dumps a service container as a YAML string.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class YamlDumper extends Dumper
{
    private $dumper;

    /**
     * Constructor.
     *
     * @param ContainerBuilder $container The service container to dump
     *
     * @api
     */
    public function __construct(ContainerBuilder $container)
    {
        parent::__construct($container);

        $this->dumper = new YmlDumper();
    }

    /**
     * Dumps the service container as an YAML string.
     *
     * @param array $options An array of options
     *
     * @return string A YAML string representing of the service container
     *
     * @api
     */
    public function dump(array $options = array())
    {
        return $this->addParameters()."\n".$this->addServices();
    }

    /**
     * Adds a service
     *
     * @param string     $id
     * @param Definition $definition
     *
     * @return string
     */
    private function addService($id, $definition)
    {
        $code = "    $id:\n";
        if ($definition->getClass()) {
            $code .= sprintf("        class: %s\n", $definition->getClass());
        }

        if (!$definition->isPublic()) {
            $code .= "        public: false\n";
        }

        $tagsCode = '';
        foreach ($definition->getTags() as $name => $tags) {
            foreach ($tags as $attributes) {
                $att = array();
                foreach ($attributes as $key => $value) {
                    $att[] = sprintf('%s: %s', $this->dumper->dump($key), $this->dumper->dump($value));
                }
                $att = $att ? ', '.implode(' ', $att) : '';

                $tagsCode .= sprintf("            - { name: %s%s }\n", $this->dumper->dump($name), $att);
            }
        }
        if ($tagsCode) {
            $code .= "        tags:\n".$tagsCode;
        }

        if ($definition->getFile()) {
            $code .= sprintf("        file: %s\n", $definition->getFile());
        }

        if ($definition->isSynthetic()) {
            $code .= sprintf("        synthetic: true\n");
        }

        if ($definition->isSynchronized()) {
            $code .= sprintf("        synchronized: true\n");
        }

        if ($definition->getFactoryClass()) {
            $code .= sprintf("        factory_class: %s\n", $definition->getFactoryClass());
        }

        if ($definition->isLazy()) {
            $code .= sprintf("        lazy: true\n");
        }

        if ($definition->getFactoryMethod()) {
            $code .= sprintf("        factory_method: %s\n", $definition->getFactoryMethod());
        }

        if ($definition->getFactoryService()) {
            $code .= sprintf("        factory_service: %s\n", $definition->getFactoryService());
        }

        if ($definition->getArguments()) {
            $code .= sprintf("        arguments: %s\n", $this->dumper->dump($this->dumpValue($definition->getArguments()), 0));
        }

        if ($definition->getProperties()) {
            $code .= sprintf("        properties: %s\n", $this->dumper->dump($this->dumpValue($definition->getProperties()), 0));
        }

        if ($definition->getMethodCalls()) {
            $code .= sprintf("        calls:\n%s\n", $this->dumper->dump($this->dumpValue($definition->getMethodCalls()), 1, 12));
        }

        if (ContainerInterface::SCOPE_CONTAINER !== $scope = $definition->getScope()) {
            $code .= sprintf("        scope: %s\n", $scope);
        }

        if ($callable = $definition->getConfigurator()) {
            if (is_array($callable)) {
                if ($callable[0] instanceof Reference) {
                    $callable = array($this->getServiceCall((string) $callable[0], $callable[0]), $callable[1]);
                } else {
                    $callable = array($callable[0], $callable[1]);
                }
            }

            $code .= sprintf("        configurator: %s\n", $this->dumper->dump($callable, 0));
        }

        return $code;
    }

    /**
     * Adds a service alias
     *
     * @param string $alias
     * @param Alias  $id
     *
     * @return string
     */
    private function addServiceAlias($alias, $id)
    {
        if ($id->isPublic()) {
            return sprintf("    %s: @%s\n", $alias, $id);
        } else {
            return sprintf("    %s:\n        alias: %s\n        public: false", $alias, $id);
        }
    }

    /**
     * Adds services
     *
     * @return string
     */
    private function addServices()
    {
        if (!$this->container->getDefinitions()) {
            return '';
        }

        $code = "services:\n";
        foreach ($this->container->getDefinitions() as $id => $definition) {
            $code .= $this->addService($id, $definition);
        }

        $aliases = $this->container->getAliases();
        foreach ($aliases as $alias => $id) {
            while (isset($aliases[(string) $id])) {
                $id = $aliases[(string) $id];
            }
            $code .= $this->addServiceAlias($alias, $id);
        }

        return $code;
    }

    /**
     * Adds parameters
     *
     * @return string
     */
    private function addParameters()
    {
        if (!$this->container->getParameterBag()->all()) {
            return '';
        }

        $parameters = $this->prepareParameters($this->container->getParameterBag()->all(), $this->container->isFrozen());

        return $this->dumper->dump(array('parameters' => $parameters), 2);
    }

    /**
     * Dumps the value to YAML format
     *
     * @param mixed $value
     *
     * @return mixed
     *
     * @throws RuntimeException When trying to dump object or resource
     */
    private function dumpValue($value)
    {
        if (is_array($value)) {
            $code = array();
            foreach ($value as $k => $v) {
                $code[$k] = $this->dumpValue($v);
            }

            return $code;
        } elseif ($value instanceof Reference) {
            return $this->getServiceCall((string) $value, $value);
        } elseif ($value instanceof Parameter) {
            return $this->getParameterCall((string) $value);
        } elseif ($value instanceof Expression) {
            return $this->getExpressionCall((string) $value);
        } elseif (is_object($value) || is_resource($value)) {
            throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.');
        }

        return $value;
    }

    /**
     * Gets the service call.
     *
     * @param string    $id
     * @param Reference $reference
     *
     * @return string
     */
    private function getServiceCall($id, Reference $reference = null)
    {
        if (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) {
            return sprintf('@?%s', $id);
        }

        return sprintf('@%s', $id);
    }

    /**
     * Gets parameter call.
     *
     * @param string $id
     *
     * @return string
     */
    private function getParameterCall($id)
    {
        return sprintf('%%%s%%', $id);
    }

    private function getExpressionCall($expression)
    {
        return sprintf('@=%s', $expression);
    }

    /**
     * Prepares parameters.
     *
     * @param array   $parameters
     * @param Boolean $escape
     *
     * @return array
     */
    private function prepareParameters($parameters, $escape = true)
    {
        $filtered = array();
        foreach ($parameters as $key => $value) {
            if (is_array($value)) {
                $value = $this->prepareParameters($value, $escape);
            } elseif ($value instanceof Reference || is_string($value) && 0 === strpos($value, '@')) {
                $value = '@'.$value;
            }

            $filtered[$key] = $value;
        }

        return $escape ? $this->escape($filtered) : $filtered;
    }

    /**
     * Escapes arguments
     *
     * @param array $arguments
     *
     * @return array
     */
    private function escape($arguments)
    {
        $args = array();
        foreach ($arguments as $k => $v) {
            if (is_array($v)) {
                $args[$k] = $this->escape($v);
            } elseif (is_string($v)) {
                $args[$k] = str_replace('%', '%%', $v);
            } else {
                $args[$k] = $v;
            }
        }

        return $args;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Dumper;

use Symfony\Component\DependencyInjection\Variable;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Parameter;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface as ProxyDumper;
use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper;
use Symfony\Component\DependencyInjection\ExpressionLanguage;
use Symfony\Component\ExpressionLanguage\Expression;

/**
 * PhpDumper dumps a service container as a PHP class.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @api
 */
class PhpDumper extends Dumper
{
    /**
     * Characters that might appear in the generated variable name as first character
     * @var string
     */
    const FIRST_CHARS = 'abcdefghijklmnopqrstuvwxyz';

    /**
     * Characters that might appear in the generated variable name as any but the first character
     * @var string
     */
    const NON_FIRST_CHARS = 'abcdefghijklmnopqrstuvwxyz0123456789_';

    private $inlinedDefinitions;
    private $definitionVariables;
    private $referenceVariables;
    private $variableCount;
    private $reservedVariables = array('instance', 'class');
    private $expressionLanguage;

    /**
     * @var \Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface
     */
    private $proxyDumper;

    /**
     * {@inheritDoc}
     *
     * @api
     */
    public function __construct(ContainerBuilder $container)
    {
        parent::__construct($container);

        $this->inlinedDefinitions = new \SplObjectStorage;
    }

    /**
     * Sets the dumper to be used when dumping proxies in the generated container.
     *
     * @param ProxyDumper $proxyDumper
     */
    public function setProxyDumper(ProxyDumper $proxyDumper)
    {
        $this->proxyDumper = $proxyDumper;
    }

    /**
     * Dumps the service container as a PHP class.
     *
     * Available options:
     *
     *  * class:      The class name
     *  * base_class: The base class name
     *  * namespace:  The class namespace
     *
     * @param array $options An array of options
     *
     * @return string A PHP class representing of the service container
     *
     * @api
     */
    public function dump(array $options = array())
    {
        $options = array_merge(array(
            'class'      => 'ProjectServiceContainer',
            'base_class' => 'Container',
            'namespace' => '',
        ), $options);

        $code = $this->startClass($options['class'], $options['base_class'], $options['namespace']);

        if ($this->container->isFrozen()) {
            $code .= $this->addFrozenConstructor();
        } else {
            $code .= $this->addConstructor();
        }

        $code .=
            $this->addServices().
            $this->addDefaultParametersMethod().
            $this->endClass().
            $this->addProxyClasses()
        ;

        return $code;
    }

    /**
     * Retrieves the currently set proxy dumper or instantiates one.
     *
     * @return ProxyDumper
     */
    private function getProxyDumper()
    {
        if (!$this->proxyDumper) {
            $this->proxyDumper = new NullDumper();
        }

        return $this->proxyDumper;
    }

    /**
     * Generates Service local temp variables.
     *
     * @param string $cId
     * @param string $definition
     *
     * @return string
     */
    private function addServiceLocalTempVariables($cId, $definition)
    {
        static $template = "        \$%s = %s;\n";

        $localDefinitions = array_merge(
            array($definition),
            $this->getInlinedDefinitions($definition)
        );

        $calls = $behavior = array();
        foreach ($localDefinitions as $iDefinition) {
            $this->getServiceCallsFromArguments($iDefinition->getArguments(), $calls, $behavior);
            $this->getServiceCallsFromArguments($iDefinition->getMethodCalls(), $calls, $behavior);
            $this->getServiceCallsFromArguments($iDefinition->getProperties(), $calls, $behavior);
        }

        $code = '';
        foreach ($calls as $id => $callCount) {
            if ('service_container' === $id || $id === $cId) {
                continue;
            }

            if ($callCount > 1) {
                $name = $this->getNextVariableName();
                $this->referenceVariables[$id] = new Variable($name);

                if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $behavior[$id]) {
                    $code .= sprintf($template, $name, $this->getServiceCall($id));
                } else {
                    $code .= sprintf($template, $name, $this->getServiceCall($id, new Reference($id, ContainerInterface::NULL_ON_INVALID_REFERENCE)));
                }
            }
        }

        if ('' !== $code) {
            $code .= "\n";
        }

        return $code;
    }

    /**
     * Generates code for the proxies to be attached after the container class
     *
     * @return string
     */
    private function addProxyClasses()
    {
        /* @var $definitions Definition[] */
        $definitions = array_filter(
            $this->container->getDefinitions(),
            array($this->getProxyDumper(), 'isProxyCandidate')
        );
        $code = '';

        foreach ($definitions as $definition) {
            $code .= "\n" . $this->getProxyDumper()->getProxyCode($definition);
        }

        return $code;
    }

    /**
     * Generates the require_once statement for service includes.
     *
     * @param string     $id         The service id
     * @param Definition $definition
     *
     * @return string
     */
    private function addServiceInclude($id, $definition)
    {
        $template = "        require_once %s;\n";
        $code = '';

        if (null !== $file = $definition->getFile()) {
            $code .= sprintf($template, $this->dumpValue($file));
        }

        foreach ($this->getInlinedDefinitions($definition) as $definition) {
            if (null !== $file = $definition->getFile()) {
                $code .= sprintf($template, $this->dumpValue($file));
            }
        }

        if ('' !== $code) {
            $code .= "\n";
        }

        return $code;
    }

    /**
     * Generates the inline definition of a service.
     *
     * @param string     $id
     * @param Definition $definition
     *
     * @return string
     *
     * @throws RuntimeException When the factory definition is incomplete
     * @throws ServiceCircularReferenceException When a circular reference is detected
     */
    private function addServiceInlinedDefinitions($id, $definition)
    {
        $code = '';
        $variableMap = $this->definitionVariables;
        $nbOccurrences = new \SplObjectStorage();
        $processed = new \SplObjectStorage();
        $inlinedDefinitions = $this->getInlinedDefinitions($definition);

        foreach ($inlinedDefinitions as $definition) {
            if (false === $nbOccurrences->contains($definition)) {
                $nbOccurrences->offsetSet($definition, 1);
            } else {
                $i = $nbOccurrences->offsetGet($definition);
                $nbOccurrences->offsetSet($definition, $i + 1);
            }
        }

        foreach ($inlinedDefinitions as $sDefinition) {
            if ($processed->contains($sDefinition)) {
                continue;
            }
            $processed->offsetSet($sDefinition);

            $class = $this->dumpValue($sDefinition->getClass());
            if ($nbOccurrences->offsetGet($sDefinition) > 1 || $sDefinition->getMethodCalls() || $sDefinition->getProperties() || null !== $sDefinition->getConfigurator() || false !== strpos($class, '$')) {
                $name = $this->getNextVariableName();
                $variableMap->offsetSet($sDefinition, new Variable($name));

                // a construct like:
                // $a = new ServiceA(ServiceB $b); $b = new ServiceB(ServiceA $a);
                // this is an indication for a wrong implementation, you can circumvent this problem
                // by setting up your service structure like this:
                // $b = new ServiceB();
                // $a = new ServiceA(ServiceB $b);
                // $b->setServiceA(ServiceA $a);
                if ($this->hasReference($id, $sDefinition->getArguments())) {
                    throw new ServiceCircularReferenceException($id, array($id));
                }

                $code .= $this->addNewInstance($id, $sDefinition, '$'.$name, ' = ');

                if (!$this->hasReference($id, $sDefinition->getMethodCalls(), true) && !$this->hasReference($id, $sDefinition->getProperties(), true)) {
                    $code .= $this->addServiceMethodCalls(null, $sDefinition, $name);
                    $code .= $this->addServiceProperties(null, $sDefinition, $name);
                    $code .= $this->addServiceConfigurator(null, $sDefinition, $name);
                }

                $code .= "\n";
            }
        }

        return $code;
    }

    /**
     * Adds the service return statement.
     *
     * @param string     $id         Service id
     * @param Definition $definition
     *
     * @return string
     */
    private function addServiceReturn($id, $definition)
    {
        if ($this->isSimpleInstance($id, $definition)) {
            return "    }\n";
        }

        return "\n        return \$instance;\n    }\n";
    }

    /**
     * Generates the service instance.
     *
     * @param string     $id
     * @param Definition $definition
     *
     * @return string
     *
     * @throws InvalidArgumentException
     * @throws RuntimeException
     */
    private function addServiceInstance($id, $definition)
    {
        $class = $this->dumpValue($definition->getClass());

        if (0 === strpos($class, "'") && !preg_match('/^\'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
            throw new InvalidArgumentException(sprintf('"%s" is not a valid class name for the "%s" service.', $class, $id));
        }

        $simple           = $this->isSimpleInstance($id, $definition);
        $isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition);
        $instantiation    = '';

        if (!$isProxyCandidate && ContainerInterface::SCOPE_CONTAINER === $definition->getScope()) {
            $instantiation = "\$this->services['$id'] = ".($simple ? '' : '$instance');
        } elseif (!$isProxyCandidate && ContainerInterface::SCOPE_PROTOTYPE !== $scope = $definition->getScope()) {
            $instantiation = "\$this->services['$id'] = \$this->scopedServices['$scope']['$id'] = ".($simple ? '' : '$instance');
        } elseif (!$simple) {
            $instantiation = '$instance';
        }

        $return = '';
        if ($simple) {
            $return = 'return ';
        } else {
            $instantiation .= ' = ';
        }

        $code = $this->addNewInstance($id, $definition, $return, $instantiation);

        if (!$simple) {
            $code .= "\n";
        }

        return $code;
    }

    /**
     * Checks if the definition is a simple instance.
     *
     * @param string     $id
     * @param Definition $definition
     *
     * @return Boolean
     */
    private function isSimpleInstance($id, $definition)
    {
        foreach (array_merge(array($definition), $this->getInlinedDefinitions($definition)) as $sDefinition) {
            if ($definition !== $sDefinition && !$this->hasReference($id, $sDefinition->getMethodCalls())) {
                continue;
            }

            if ($sDefinition->getMethodCalls() || $sDefinition->getProperties() || $sDefinition->getConfigurator()) {
                return false;
            }
        }

        return true;
    }

    /**
     * Adds method calls to a service definition.
     *
     * @param string     $id
     * @param Definition $definition
     * @param string     $variableName
     *
     * @return string
     */
    private function addServiceMethodCalls($id, $definition, $variableName = 'instance')
    {
        $calls = '';
        foreach ($definition->getMethodCalls() as $call) {
            $arguments = array();
            foreach ($call[1] as $value) {
                $arguments[] = $this->dumpValue($value);
            }

            $calls .= $this->wrapServiceConditionals($call[1], sprintf("        \$%s->%s(%s);\n", $variableName, $call[0], implode(', ', $arguments)));
        }

        return $calls;
    }

    private function addServiceProperties($id, $definition, $variableName = 'instance')
    {
        $code = '';
        foreach ($definition->getProperties() as $name => $value) {
            $code .= sprintf("        \$%s->%s = %s;\n", $variableName, $name, $this->dumpValue($value));
        }

        return $code;
    }

    /**
     * Generates the inline definition setup.
     *
     * @param string     $id
     * @param Definition $definition
     * @return string
     */
    private function addServiceInlinedDefinitionsSetup($id, $definition)
    {
        $this->referenceVariables[$id] = new Variable('instance');

        $code = '';
        $processed = new \SplObjectStorage();
        foreach ($this->getInlinedDefinitions($definition) as $iDefinition) {
            if ($processed->contains($iDefinition)) {
                continue;
            }
            $processed->offsetSet($iDefinition);

            if (!$this->hasReference($id, $iDefinition->getMethodCalls(), true) && !$this->hasReference($id, $iDefinition->getProperties(), true)) {
                continue;
            }

            // if the instance is simple, the return statement has already been generated
            // so, the only possible way to get there is because of a circular reference
            if ($this->isSimpleInstance($id, $definition)) {
                throw new ServiceCircularReferenceException($id, array($id));
            }

            $name = (string) $this->definitionVariables->offsetGet($iDefinition);
            $code .= $this->addServiceMethodCalls(null, $iDefinition, $name);
            $code .= $this->addServiceProperties(null, $iDefinition, $name);
            $code .= $this->addServiceConfigurator(null, $iDefinition, $name);
        }

        if ('' !== $code) {
            $code .= "\n";
        }

        return $code;
    }

    /**
     * Adds configurator definition
     *
     * @param string     $id
     * @param Definition $definition
     * @param string     $variableName
     *
     * @return string
     */
    private function addServiceConfigurator($id, $definition, $variableName = 'instance')
    {
        if (!$callable = $definition->getConfigurator()) {
            return '';
        }

        if (is_array($callable)) {
            if ($callable[0] instanceof Reference) {
                return sprintf("        %s->%s(\$%s);\n", $this->getServiceCall((string) $callable[0]), $callable[1], $variableName);
            }

            return sprintf("        call_user_func(array(%s, '%s'), \$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName);
        }

        return sprintf("        %s(\$%s);\n", $callable, $variableName);
    }

    /**
     * Adds a service
     *
     * @param string     $id
     * @param Definition $definition
     *
     * @return string
     */
    private function addService($id, $definition)
    {
        $this->definitionVariables = new \SplObjectStorage();
        $this->referenceVariables = array();
        $this->variableCount = 0;

        $return = array();

        if ($definition->isSynthetic()) {
            $return[] = '@throws RuntimeException always since this service is expected to be injected dynamically';
        } elseif ($class = $definition->getClass()) {
            $return[] = sprintf("@return %s A %s instance.", 0 === strpos($class, '%') ? 'object' : $class, $class);
        } elseif ($definition->getFactoryClass()) {
            $return[] = sprintf('@return object An instance returned by %s::%s().', $definition->getFactoryClass(), $definition->getFactoryMethod());
        } elseif ($definition->getFactoryService()) {
            $return[] = sprintf('@return object An instance returned by %s::%s().', $definition->getFactoryService(), $definition->getFactoryMethod());
        }

        $scope = $definition->getScope();
        if (!in_array($scope, array(ContainerInterface::SCOPE_CONTAINER, ContainerInterface::SCOPE_PROTOTYPE))) {
            if ($return && 0 === strpos($return[count($return) - 1], '@return')) {
                $return[] = '';
            }
            $return[] = sprintf("@throws InactiveScopeException when the '%s' service is requested while the '%s' scope is not active", $id, $scope);
        }

        $return = implode("\n     * ", $return);

        $doc = '';
        if (ContainerInterface::SCOPE_PROTOTYPE !== $scope) {
            $doc .= <<<EOF

     *
     * This service is shared.
     * This method always returns the same instance of the service.
EOF;
        }

        if (!$definition->isPublic()) {
            $doc .= <<<EOF

     *
     * This service is private.
     * If you want to be able to request this service from the container directly,
     * make it public, otherwise you might end up with broken code.
EOF;
        }

        if ($definition->isLazy()) {
            $lazyInitialization    = '$lazyLoad = true';
            $lazyInitializationDoc = "\n     * @param boolean \$lazyLoad whether to try lazy-loading the service with a proxy\n     *";
        } else {
            $lazyInitialization    = '';
            $lazyInitializationDoc = '';
        }

        // with proxies, for 5.3.3 compatibility, the getter must be public to be accessible to the initializer
        $isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition);
        $visibility       = $isProxyCandidate ? 'public' : 'protected';
        $code             = <<<EOF

    /**
     * Gets the '$id' service.$doc
     *$lazyInitializationDoc
     * $return
     */
    {$visibility} function get{$this->camelize($id)}Service($lazyInitialization)
    {

EOF;

        $code .= $isProxyCandidate ? $this->getProxyDumper()->getProxyFactoryCode($definition, $id) : '';

        if (!in_array($scope, array(ContainerInterface::SCOPE_CONTAINER, ContainerInterface::SCOPE_PROTOTYPE))) {
            $code .= <<<EOF
        if (!isset(\$this->scopedServices['$scope'])) {
            throw new InactiveScopeException('$id', '$scope');
        }


EOF;
        }

        if ($definition->isSynthetic()) {
            $code .= sprintf("        throw new RuntimeException('You have requested a synthetic service (\"%s\"). The DIC does not know how to construct this service.');\n    }\n", $id);
        } else {
            $code .=
                $this->addServiceInclude($id, $definition).
                $this->addServiceLocalTempVariables($id, $definition).
                $this->addServiceInlinedDefinitions($id, $definition).
                $this->addServiceInstance($id, $definition).
                $this->addServiceInlinedDefinitionsSetup($id, $definition).
                $this->addServiceMethodCalls($id, $definition).
                $this->addServiceProperties($id, $definition).
                $this->addServiceConfigurator($id, $definition).
                $this->addServiceReturn($id, $definition)
            ;
        }

        $this->definitionVariables = null;
        $this->referenceVariables = null;

        return $code;
    }

    /**
     * Adds multiple services
     *
     * @return string
     */
    private function addServices()
    {
        $publicServices = $privateServices = $synchronizers = '';
        $definitions = $this->container->getDefinitions();
        ksort($definitions);
        foreach ($definitions as $id => $definition) {
            if ($definition->isPublic()) {
                $publicServices .= $this->addService($id, $definition);
            } else {
                $privateServices .= $this->addService($id, $definition);
            }

            $synchronizers .= $this->addServiceSynchronizer($id, $definition);
        }

        return $publicServices.$synchronizers.$privateServices;
    }

    /**
     * Adds synchronizer methods.
     *
     * @param string     $id         A service identifier
     * @param Definition $definition A Definition instance
     */
    private function addServiceSynchronizer($id, Definition $definition)
    {
        if (!$definition->isSynchronized()) {
            return;
        }

        $code = '';
        foreach ($this->container->getDefinitions() as $definitionId => $definition) {
            foreach ($definition->getMethodCalls() as $call) {
                foreach ($call[1] as $argument) {
                    if ($argument instanceof Reference && $id == (string) $argument) {
                        $arguments = array();
                        foreach ($call[1] as $value) {
                            $arguments[] = $this->dumpValue($value);
                        }

                        $call = $this->wrapServiceConditionals($call[1], sprintf("\$this->get('%s')->%s(%s);", $definitionId, $call[0], implode(', ', $arguments)));

                        $code .= <<<EOF
        if (\$this->initialized('$definitionId')) {
            $call
        }

EOF;
                    }
                }
            }
        }

        if (!$code) {
            return;
        }

        return <<<EOF

    /**
     * Updates the '$id' service.
     */
    protected function synchronize{$this->camelize($id)}Service()
    {
$code    }

EOF;
    }

    private function addNewInstance($id, Definition $definition, $return, $instantiation)
    {
        $class = $this->dumpValue($definition->getClass());

        $arguments = array();
        foreach ($definition->getArguments() as $value) {
            $arguments[] = $this->dumpValue($value);
        }

        if (null !== $definition->getFactoryMethod()) {
            if (null !== $definition->getFactoryClass()) {
                return sprintf("        $return{$instantiation}call_user_func(array(%s, '%s')%s);\n", $this->dumpValue($definition->getFactoryClass()), $definition->getFactoryMethod(), $arguments ? ', '.implode(', ', $arguments) : '');
            }

            if (null !== $definition->getFactoryService()) {
                return sprintf("        $return{$instantiation}%s->%s(%s);\n", $this->getServiceCall($definition->getFactoryService()), $definition->getFactoryMethod(), implode(', ', $arguments));
            }

            throw new RuntimeException(sprintf('Factory method requires a factory service or factory class in service definition for %s', $id));
        }

        if (false !== strpos($class, '$')) {
            return sprintf("        \$class = %s;\n\n        $return{$instantiation}new \$class(%s);\n", $class, implode(', ', $arguments));
        }

        return sprintf("        $return{$instantiation}new \\%s(%s);\n", substr(str_replace('\\\\', '\\', $class), 1, -1), implode(', ', $arguments));
    }

    /**
     * Adds the class headers.
     *
     * @param string $class     Class name
     * @param string $baseClass The name of the base class
     * @param string $namespace The class namespace
     *
     * @return string
     */
    private function startClass($class, $baseClass, $namespace)
    {
        $bagClass = $this->container->isFrozen() ? 'use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;' : 'use Symfony\Component\DependencyInjection\ParameterBag\\ParameterBag;';
        $namespaceLine = $namespace ? "namespace $namespace;\n" : '';

        return <<<EOF
<?php
$namespaceLine
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
$bagClass

/**
 * $class
 *
 * This class has been auto-generated
 * by the Symfony Dependency Injection Component.
 */
class $class extends $baseClass
{
EOF;
    }

    /**
     * Adds the constructor.
     *
     * @return string
     */
    private function addConstructor()
    {
        $arguments = $this->container->getParameterBag()->all() ? 'new ParameterBag($this->getDefaultParameters())' : null;

        $code = <<<EOF

    /**
     * Constructor.
     */
    public function __construct()
    {
        parent::__construct($arguments);

EOF;

        if (count($scopes = $this->container->getScopes()) > 0) {
            $code .= "\n";
            $code .= "        \$this->scopes = ".$this->dumpValue($scopes).";\n";
            $code .= "        \$this->scopeChildren = ".$this->dumpValue($this->container->getScopeChildren()).";\n";
        }

        $code .= $this->addMethodMap();
        $code .= $this->addAliases();

        $code .= <<<EOF
    }

EOF;

        return $code;
    }

    /**
     * Adds the constructor for a frozen container.
     *
     * @return string
     */
    private function addFrozenConstructor()
    {
        $code = <<<EOF

    /**
     * Constructor.
     */
    public function __construct()
    {
EOF;

        if ($this->container->getParameterBag()->all()) {
            $code .= "\n        \$this->parameters = \$this->getDefaultParameters();\n";
        }

        $code .= <<<EOF

        \$this->services =
        \$this->scopedServices =
        \$this->scopeStacks = array();

        \$this->set('service_container', \$this);

EOF;

        $code .= "\n";
        if (count($scopes = $this->container->getScopes()) > 0) {
            $code .= "        \$this->scopes = ".$this->dumpValue($scopes).";\n";
            $code .= "        \$this->scopeChildren = ".$this->dumpValue($this->container->getScopeChildren()).";\n";
        } else {
            $code .= "        \$this->scopes = array();\n";
            $code .= "        \$this->scopeChildren = array();\n";
        }

        $code .= $this->addMethodMap();
        $code .= $this->addAliases();

        $code .= <<<EOF
    }

EOF;

        return $code;
    }

    /**
     * Adds the methodMap property definition
     *
     * @return string
     */
    private function addMethodMap()
    {
        if (!$definitions = $this->container->getDefinitions()) {
            return '';
        }

        $code = "        \$this->methodMap = array(\n";
        ksort($definitions);
        foreach ($definitions as $id => $definition) {
            $code .= '            '.var_export($id, true).' => '.var_export('get'.$this->camelize($id).'Service', true).",\n";
        }

        return $code . "        );\n";
    }

    /**
     * Adds the aliases property definition
     *
     * @return string
     */
    private function addAliases()
    {
        if (!$aliases = $this->container->getAliases()) {
            if ($this->container->isFrozen()) {
                return "\n        \$this->aliases = array();\n";
            } else {
                return '';
            }
        }

        $code = "        \$this->aliases = array(\n";
        ksort($aliases);
        foreach ($aliases as $alias => $id) {
            $id = (string) $id;
            while (isset($aliases[$id])) {
                $id = (string) $aliases[$id];
            }
            $code .= '            '.var_export($alias, true).' => '.var_export($id, true).",\n";
        }

        return $code . "        );\n";
    }

    /**
     * Adds default parameters method.
     *
     * @return string
     */
    private function addDefaultParametersMethod()
    {
        if (!$this->container->getParameterBag()->all()) {
            return '';
        }

        $parameters = $this->exportParameters($this->container->getParameterBag()->all());

        $code = '';
        if ($this->container->isFrozen()) {
            $code .= <<<EOF

    /**
     * {@inheritdoc}
     */
    public function getParameter(\$name)
    {
        \$name = strtolower(\$name);

        if (!(isset(\$this->parameters[\$name]) || array_key_exists(\$name, \$this->parameters))) {
            throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', \$name));
        }

        return \$this->parameters[\$name];
    }

    /**
     * {@inheritdoc}
     */
    public function hasParameter(\$name)
    {
        \$name = strtolower(\$name);

        return isset(\$this->parameters[\$name]) || array_key_exists(\$name, \$this->parameters);
    }

    /**
     * {@inheritdoc}
     */
    public function setParameter(\$name, \$value)
    {
        throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
    }

    /**
     * {@inheritDoc}
     */
    public function getParameterBag()
    {
        if (null === \$this->parameterBag) {
            \$this->parameterBag = new FrozenParameterBag(\$this->parameters);
        }

        return \$this->parameterBag;
    }
EOF;
        }

        $code .= <<<EOF

    /**
     * Gets the default parameters.
     *
     * @return array An array of the default parameters
     */
    protected function getDefaultParameters()
    {
        return $parameters;
    }

EOF;

        return $code;
    }

    /**
     * Exports parameters.
     *
     * @param array   $parameters
     * @param string  $path
     * @param integer $indent
     *
     * @return string
     *
     * @throws InvalidArgumentException
     */
    private function exportParameters($parameters, $path = '', $indent = 12)
    {
        $php = array();
        foreach ($parameters as $key => $value) {
            if (is_array($value)) {
                $value = $this->exportParameters($value, $path.'/'.$key, $indent + 4);
            } elseif ($value instanceof Variable) {
                throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain variable references. Variable "%s" found in "%s".', $value, $path.'/'.$key));
            } elseif ($value instanceof Definition) {
                throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain service definitions. Definition for "%s" found in "%s".', $value->getClass(), $path.'/'.$key));
            } elseif ($value instanceof Reference) {
                throw new InvalidArgumentException(sprintf('You cannot dump a container with parameters that contain references to other services (reference to service "%s" found in "%s").', $value, $path.'/'.$key));
            } else {
                $value = var_export($value, true);
            }

            $php[] = sprintf('%s%s => %s,', str_repeat(' ', $indent), var_export($key, true), $value);
        }

        return sprintf("array(\n%s\n%s)", implode("\n", $php), str_repeat(' ', $indent - 4));
    }

    /**
     * Ends the class definition.
     *
     * @return string
     */
    private function endClass()
    {
        return <<<EOF
}

EOF;
    }

    /**
     * Wraps the service conditionals.
     *
     * @param string $value
     * @param string $code
     *
     * @return string
     */
    private function wrapServiceConditionals($value, $code)
    {
        if (!$services = ContainerBuilder::getServiceConditionals($value)) {
            return $code;
        }

        $conditions = array();
        foreach ($services as $service) {
            $conditions[] = sprintf("\$this->has('%s')", $service);
        }

        // re-indent the wrapped code
        $code = implode("\n", array_map(function ($line) { return $line ? '    '.$line : $line; }, explode("\n", $code)));

        return sprintf("        if (%s) {\n%s        }\n", implode(' && ', $conditions), $code);
    }

    /**
     * Builds service calls from arguments.
     *
     * @param array  $arguments
     * @param array  &$calls    By reference
     * @param array  &$behavior By reference
     */
    private function getServiceCallsFromArguments(array $arguments, array &$calls, array &$behavior)
    {
        foreach ($arguments as $argument) {
            if (is_array($argument)) {
                $this->getServiceCallsFromArguments($argument, $calls, $behavior);
            } elseif ($argument instanceof Reference) {
                $id = (string) $argument;

                if (!isset($calls[$id])) {
                    $calls[$id] = 0;
                }
                if (!isset($behavior[$id])) {
                    $behavior[$id] = $argument->getInvalidBehavior();
                } elseif (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $behavior[$id]) {
                    $behavior[$id] = $argument->getInvalidBehavior();
                }

                $calls[$id] += 1;
            }
        }
    }

    /**
     * Returns the inline definition.
     *
     * @param Definition $definition
     *
     * @return array
     */
    private function getInlinedDefinitions(Definition $definition)
    {
        if (false === $this->inlinedDefinitions->contains($definition)) {
            $definitions = array_merge(
                $this->getDefinitionsFromArguments($definition->getArguments()),
                $this->getDefinitionsFromArguments($definition->getMethodCalls()),
                $this->getDefinitionsFromArguments($definition->getProperties())
            );

            $this->inlinedDefinitions->offsetSet($definition, $definitions);

            return $definitions;
        }

        return $this->inlinedDefinitions->offsetGet($definition);
    }

    /**
     * Gets the definition from arguments.
     *
     * @param array $arguments
     *
     * @return array
     */
    private function getDefinitionsFromArguments(array $arguments)
    {
        $definitions = array();
        foreach ($arguments as $argument) {
            if (is_array($argument)) {
                $definitions = array_merge($definitions, $this->getDefinitionsFromArguments($argument));
            } elseif ($argument instanceof Definition) {
                $definitions = array_merge(
                    $definitions,
                    $this->getInlinedDefinitions($argument),
                    array($argument)
                );
            }
        }

        return $definitions;
    }

    /**
     * Checks if a service id has a reference.
     *
     * @param string  $id
     * @param array   $arguments
     * @param Boolean $deep
     * @param array   $visited
     *
     * @return Boolean
     */
    private function hasReference($id, array $arguments, $deep = false, array $visited = array())
    {
        foreach ($arguments as $argument) {
            if (is_array($argument)) {
                if ($this->hasReference($id, $argument, $deep, $visited)) {
                    return true;
                }
            } elseif ($argument instanceof Reference) {
                $argumentId = (string) $argument;
                if ($id === $argumentId) {
                    return true;
                }

                if ($deep && !isset($visited[$argumentId])) {
                    $visited[$argumentId] = true;

                    $service = $this->container->getDefinition($argumentId);
                    $arguments = array_merge($service->getMethodCalls(), $service->getArguments(), $service->getProperties());

                    if ($this->hasReference($id, $arguments, $deep, $visited)) {
                        return true;
                    }
                }
            }
        }

        return false;
    }

    /**
     * Dumps values.
     *
     * @param array   $value
     * @param Boolean $interpolate
     *
     * @return string
     *
     * @throws RuntimeException
     */
    private function dumpValue($value, $interpolate = true)
    {
        if (is_array($value)) {
            $code = array();
            foreach ($value as $k => $v) {
                $code[] = sprintf('%s => %s', $this->dumpValue($k, $interpolate), $this->dumpValue($v, $interpolate));
            }

            return sprintf('array(%s)', implode(', ', $code));
        } elseif ($value instanceof Definition) {
            if (null !== $this->definitionVariables && $this->definitionVariables->contains($value)) {
                return $this->dumpValue($this->definitionVariables->offsetGet($value), $interpolate);
            }
            if (count($value->getMethodCalls()) > 0) {
                throw new RuntimeException('Cannot dump definitions which have method calls.');
            }
            if (null !== $value->getConfigurator()) {
                throw new RuntimeException('Cannot dump definitions which have a configurator.');
            }

            $arguments = array();
            foreach ($value->getArguments() as $argument) {
                $arguments[] = $this->dumpValue($argument);
            }
            $class = $this->dumpValue($value->getClass());

            if (false !== strpos($class, '$')) {
                throw new RuntimeException('Cannot dump definitions which have a variable class name.');
            }

            if (null !== $value->getFactoryMethod()) {
                if (null !== $value->getFactoryClass()) {
                    return sprintf("call_user_func(array(%s, '%s')%s)", $this->dumpValue($value->getFactoryClass()), $value->getFactoryMethod(), count($arguments) > 0 ? ', '.implode(', ', $arguments) : '');
                } elseif (null !== $value->getFactoryService()) {
                    return sprintf("%s->%s(%s)", $this->getServiceCall($value->getFactoryService()), $value->getFactoryMethod(), implode(', ', $arguments));
                } else {
                    throw new RuntimeException('Cannot dump definitions which have factory method without factory service or factory class.');
                }
            }

            return sprintf("new \\%s(%s)", substr(str_replace('\\\\', '\\', $class), 1, -1), implode(', ', $arguments));
        } elseif ($value instanceof Variable) {
            return '$'.$value;
        } elseif ($value instanceof Reference) {
            if (null !== $this->referenceVariables && isset($this->referenceVariables[$id = (string) $value])) {
                return $this->dumpValue($this->referenceVariables[$id], $interpolate);
            }

            return $this->getServiceCall((string) $value, $value);
        } elseif ($value instanceof Expression) {
            return $this->getExpressionLanguage()->compile((string) $value, array('container'));
        } elseif ($value instanceof Parameter) {
            return $this->dumpParameter($value);
        } elseif (true === $interpolate && is_string($value)) {
            if (preg_match('/^%([^%]+)%$/', $value, $match)) {
                // we do this to deal with non string values (Boolean, integer, ...)
                // the preg_replace_callback converts them to strings
                return $this->dumpParameter(strtolower($match[1]));
            } else {
                $that = $this;
                $replaceParameters = function ($match) use ($that) {
                    return "'.".$that->dumpParameter(strtolower($match[2])).".'";
                };

                $code = str_replace('%%', '%', preg_replace_callback('/(?<!%)(%)([^%]+)\1/', $replaceParameters, var_export($value, true)));

                return $code;
            }
        } elseif (is_object($value) || is_resource($value)) {
            throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.');
        } else {
            return var_export($value, true);
        }
    }

    /**
     * Dumps a parameter
     *
     * @param string $name
     *
     * @return string
     */
    public function dumpParameter($name)
    {
        if ($this->container->isFrozen() && $this->container->hasParameter($name)) {
            return $this->dumpValue($this->container->getParameter($name), false);
        }

        return sprintf("\$this->getParameter('%s')", strtolower($name));
    }

    /**
     * Gets a service call
     *
     * @param string    $id
     * @param Reference $reference
     *
     * @return string
     */
    private function getServiceCall($id, Reference $reference = null)
    {
        if ('service_container' === $id) {
            return '$this';
        }

        if (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) {
            return sprintf('$this->get(\'%s\', ContainerInterface::NULL_ON_INVALID_REFERENCE)', $id);
        } else {
            if ($this->container->hasAlias($id)) {
                $id = (string) $this->container->getAlias($id);
            }

            return sprintf('$this->get(\'%s\')', $id);
        }
    }

    /**
     * Convert a service id to a valid PHP method name.
     *
     * @param string $id
     *
     * @return string
     *
     * @throws InvalidArgumentException
     */
    private function camelize($id)
    {
        $name = Container::camelize($id);

        if (!preg_match('/^[a-zA-Z0-9_\x7f-\xff]+$/', $name)) {
            throw new InvalidArgumentException(sprintf('Service id "%s" cannot be converted to a valid PHP method name.', $id));
        }

        return $name;
    }

    /**
     * Returns the next name to use
     *
     * @return string
     */
    private function getNextVariableName()
    {
        $firstChars = self::FIRST_CHARS;
        $firstCharsLength = strlen($firstChars);
        $nonFirstChars = self::NON_FIRST_CHARS;
        $nonFirstCharsLength = strlen($nonFirstChars);

        while (true) {
            $name = '';
            $i = $this->variableCount;

            if ('' === $name) {
                $name .= $firstChars[$i%$firstCharsLength];
                $i = intval($i/$firstCharsLength);
            }

            while ($i > 0) {
                $i -= 1;
                $name .= $nonFirstChars[$i%$nonFirstCharsLength];
                $i = intval($i/$nonFirstCharsLength);
            }

            $this->variableCount += 1;

            // check that the name is not reserved
            if (in_array($name, $this->reservedVariables, true)) {
                continue;
            }

            return $name;
        }
    }

    private function getExpressionLanguage()
    {
        if (null === $this->expressionLanguage) {
            if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
                throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
            }
            $this->expressionLanguage = new ExpressionLanguage();
        }

        return $this->expressionLanguage;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Dumper;

/**
 * DumperInterface is the interface implemented by service container dumper classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface DumperInterface
{
    /**
     * Dumps the service container.
     *
     * @param array $options An array of options
     *
     * @return string The representation of the service container
     *
     * @api
     */
    public function dump(array $options = array());
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Dumper;

use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * Dumper is the abstract class for all built-in dumpers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
abstract class Dumper implements DumperInterface
{
    protected $container;

    /**
     * Constructor.
     *
     * @param ContainerBuilder $container The service container to dump
     *
     * @api
     */
    public function __construct(ContainerBuilder $container)
    {
        $this->container = $container;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Dumper;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Parameter;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\ExpressionLanguage\Expression;

/**
 * XmlDumper dumps a service container as an XML string.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Martin Hasoň <martin.hason@gmail.com>
 *
 * @api
 */
class XmlDumper extends Dumper
{
    /**
     * @var \DOMDocument
     */
    private $document;

    /**
     * Dumps the service container as an XML string.
     *
     * @param array $options An array of options
     *
     * @return string An xml string representing of the service container
     *
     * @api
     */
    public function dump(array $options = array())
    {
        $this->document = new \DOMDocument('1.0', 'utf-8');
        $this->document->formatOutput = true;

        $container = $this->document->createElementNS('http://symfony.com/schema/dic/services', 'container');
        $container->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
        $container->setAttribute('xsi:schemaLocation', 'http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd');

        $this->addParameters($container);
        $this->addServices($container);

        $this->document->appendChild($container);
        $xml = $this->document->saveXML();
        $this->document = null;

        return $xml;
    }

    /**
     * Adds parameters.
     *
     * @param \DOMElement $parent
     */
    private function addParameters(\DOMElement $parent)
    {
        $data = $this->container->getParameterBag()->all();
        if (!$data) {
            return;
        }

        if ($this->container->isFrozen()) {
            $data = $this->escape($data);
        }

        $parameters = $this->document->createElement('parameters');
        $parent->appendChild($parameters);
        $this->convertParameters($data, 'parameter', $parameters);
    }

    /**
     * Adds method calls.
     *
     * @param array       $methodcalls
     * @param \DOMElement $parent
     */
    private function addMethodCalls(array $methodcalls, \DOMElement $parent)
    {
        foreach ($methodcalls as $methodcall) {
            $call = $this->document->createElement('call');
            $call->setAttribute('method', $methodcall[0]);
            if (count($methodcall[1])) {
                $this->convertParameters($methodcall[1], 'argument', $call);
            }
            $parent->appendChild($call);
        }
    }

    /**
     * Adds a service.
     *
     * @param Definition  $definition
     * @param string      $id
     * @param \DOMElement $parent
     */
    private function addService($definition, $id, \DOMElement $parent)
    {
        $service = $this->document->createElement('service');
        if (null !== $id) {
            $service->setAttribute('id', $id);
        }
        if ($definition->getClass()) {
            $service->setAttribute('class', $definition->getClass());
        }
        if ($definition->getFactoryMethod()) {
            $service->setAttribute('factory-method', $definition->getFactoryMethod());
        }
        if ($definition->getFactoryService()) {
            $service->setAttribute('factory-service', $definition->getFactoryService());
        }
        if (ContainerInterface::SCOPE_CONTAINER !== $scope = $definition->getScope()) {
            $service->setAttribute('scope', $scope);
        }
        if (!$definition->isPublic()) {
            $service->setAttribute('public', 'false');
        }
        if ($definition->isSynthetic()) {
            $service->setAttribute('synthetic', 'true');
        }
        if ($definition->isSynchronized()) {
            $service->setAttribute('synchronized', 'true');
        }
        if ($definition->isLazy()) {
            $service->setAttribute('lazy', 'true');
        }

        foreach ($definition->getTags() as $name => $tags) {
            foreach ($tags as $attributes) {
                $tag = $this->document->createElement('tag');
                $tag->setAttribute('name', $name);
                foreach ($attributes as $key => $value) {
                    $tag->setAttribute($key, $value);
                }
                $service->appendChild($tag);
            }
        }

        if ($definition->getFile()) {
            $file = $this->document->createElement('file');
            $file->appendChild($this->document->createTextNode($definition->getFile()));
            $service->appendChild($file);
        }

        if ($parameters = $definition->getArguments()) {
            $this->convertParameters($parameters, 'argument', $service);
        }

        if ($parameters = $definition->getProperties()) {
            $this->convertParameters($parameters, 'property', $service, 'name');
        }

        $this->addMethodCalls($definition->getMethodCalls(), $service);

        if ($callable = $definition->getConfigurator()) {
            $configurator = $this->document->createElement('configurator');
            if (is_array($callable)) {
                $configurator->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]);
                $configurator->setAttribute('method', $callable[1]);
            } else {
                $configurator->setAttribute('function', $callable);
            }
            $service->appendChild($configurator);
        }

        $parent->appendChild($service);
    }

    /**
     * Adds a service alias.
     *
     * @param string      $alias
     * @param Alias       $id
     * @param \DOMElement $parent
     */
    private function addServiceAlias($alias, Alias $id, \DOMElement $parent)
    {
        $service = $this->document->createElement('service');
        $service->setAttribute('id', $alias);
        $service->setAttribute('alias', $id);
        if (!$id->isPublic()) {
            $service->setAttribute('public', 'false');
        }
        $parent->appendChild($service);
    }

    /**
     * Adds services.
     *
     * @param \DOMElement $parent
     */
    private function addServices(\DOMElement $parent)
    {
        $definitions = $this->container->getDefinitions();
        if (!$definitions) {
            return;
        }

        $services = $this->document->createElement('services');
        foreach ($definitions as $id => $definition) {
            $this->addService($definition, $id, $services);
        }

        $aliases = $this->container->getAliases();
        foreach ($aliases as $alias => $id) {
            while (isset($aliases[(string) $id])) {
                $id = $aliases[(string) $id];
            }
            $this->addServiceAlias($alias, $id, $services);
        }
        $parent->appendChild($services);
    }

    /**
     * Converts parameters.
     *
     * @param array       $parameters
     * @param string      $type
     * @param \DOMElement $parent
     * @param string      $keyAttribute
     */
    private function convertParameters($parameters, $type, \DOMElement $parent, $keyAttribute = 'key')
    {
        $withKeys = array_keys($parameters) !== range(0, count($parameters) - 1);
        foreach ($parameters as $key => $value) {
            $element = $this->document->createElement($type);
            if ($withKeys) {
                $element->setAttribute($keyAttribute, $key);
            }

            if (is_array($value)) {
                $element->setAttribute('type', 'collection');
                $this->convertParameters($value, $type, $element, 'key');
            } elseif ($value instanceof Reference) {
                $element->setAttribute('type', 'service');
                $element->setAttribute('id', (string) $value);
                $behaviour = $value->getInvalidBehavior();
                if ($behaviour == ContainerInterface::NULL_ON_INVALID_REFERENCE) {
                    $element->setAttribute('on-invalid', 'null');
                } elseif ($behaviour == ContainerInterface::IGNORE_ON_INVALID_REFERENCE) {
                    $element->setAttribute('on-invalid', 'ignore');
                }
                if (!$value->isStrict()) {
                    $element->setAttribute('strict', 'false');
                }
            } elseif ($value instanceof Definition) {
                $element->setAttribute('type', 'service');
                $this->addService($value, null, $element);
            } elseif ($value instanceof Expression) {
                $element->setAttribute('type', 'expression');
                $text = $this->document->createTextNode(self::phpToXml((string) $value));
                $element->appendChild($text);
            } else {
                if (in_array($value, array('null', 'true', 'false'), true)) {
                    $element->setAttribute('type', 'string');
                }
                $text = $this->document->createTextNode(self::phpToXml($value));
                $element->appendChild($text);
            }
            $parent->appendChild($element);
        }
    }

    /**
     * Escapes arguments
     *
     * @param array $arguments
     *
     * @return array
     */
    private function escape($arguments)
    {
        $args = array();
        foreach ($arguments as $k => $v) {
            if (is_array($v)) {
                $args[$k] = $this->escape($v);
            } elseif (is_string($v)) {
                $args[$k] = str_replace('%', '%%', $v);
            } else {
                $args[$k] = $v;
            }
        }

        return $args;
    }

    /**
     * Converts php types to xml types.
     *
     * @param mixed $value Value to convert
     *
     * @return string
     *
     * @throws RuntimeException When trying to dump object or resource
     */
    public static function phpToXml($value)
    {
        switch (true) {
            case null === $value:
                return 'null';
            case true === $value:
                return 'true';
            case false === $value:
                return 'false';
            case $value instanceof Parameter:
                return '%'.$value.'%';
            case is_object($value) || is_resource($value):
                throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.');
            default:
                return (string) $value;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Dumper;

use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Parameter;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;

/**
 * GraphvizDumper dumps a service container as a graphviz file.
 *
 * You can convert the generated dot file with the dot utility (http://www.graphviz.org/):
 *
 *   dot -Tpng container.dot > foo.png
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class GraphvizDumper extends Dumper
{
    private $nodes;
    private $edges;
    private $options = array(
            'graph' => array('ratio' => 'compress'),
            'node'  => array('fontsize' => 11, 'fontname' => 'Arial', 'shape' => 'record'),
            'edge'  => array('fontsize' => 9, 'fontname' => 'Arial', 'color' => 'grey', 'arrowhead' => 'open', 'arrowsize' => 0.5),
            'node.instance' => array('fillcolor' => '#9999ff', 'style' => 'filled'),
            'node.definition' => array('fillcolor' => '#eeeeee'),
            'node.missing' => array('fillcolor' => '#ff9999', 'style' => 'filled'),
        );

    /**
     * Dumps the service container as a graphviz graph.
     *
     * Available options:
     *
     *  * graph: The default options for the whole graph
     *  * node: The default options for nodes
     *  * edge: The default options for edges
     *  * node.instance: The default options for services that are defined directly by object instances
     *  * node.definition: The default options for services that are defined via service definition instances
     *  * node.missing: The default options for missing services
     *
     * @param array $options An array of options
     *
     * @return string The dot representation of the service container
     */
    public function dump(array $options = array())
    {
        foreach (array('graph', 'node', 'edge', 'node.instance', 'node.definition', 'node.missing') as $key) {
            if (isset($options[$key])) {
                $this->options[$key] = array_merge($this->options[$key], $options[$key]);
            }
        }

        $this->nodes = $this->findNodes();

        $this->edges = array();
        foreach ($this->container->getDefinitions() as $id => $definition) {
            $this->edges[$id] = array_merge(
                $this->findEdges($id, $definition->getArguments(), true, ''),
                $this->findEdges($id, $definition->getProperties(), false, '')
            );

            foreach ($definition->getMethodCalls() as $call) {
                $this->edges[$id] = array_merge(
                    $this->edges[$id],
                    $this->findEdges($id, $call[1], false, $call[0].'()')
                );
            }
        }

        return $this->startDot().$this->addNodes().$this->addEdges().$this->endDot();
    }

    /**
     * Returns all nodes.
     *
     * @return string A string representation of all nodes
     */
    private function addNodes()
    {
        $code = '';
        foreach ($this->nodes as $id => $node) {
            $aliases = $this->getAliases($id);

            $code .= sprintf("  node_%s [label=\"%s\\n%s\\n\", shape=%s%s];\n", $this->dotize($id), $id.($aliases ? ' ('.implode(', ', $aliases).')' : ''), $node['class'], $this->options['node']['shape'], $this->addAttributes($node['attributes']));
        }

        return $code;
    }

    /**
     * Returns all edges.
     *
     * @return string A string representation of all edges
     */
    private function addEdges()
    {
        $code = '';
        foreach ($this->edges as $id => $edges) {
            foreach ($edges as $edge) {
                $code .= sprintf("  node_%s -> node_%s [label=\"%s\" style=\"%s\"];\n", $this->dotize($id), $this->dotize($edge['to']), $edge['name'], $edge['required'] ? 'filled' : 'dashed');
            }
        }

        return $code;
    }

    /**
     * Finds all edges belonging to a specific service id.
     *
     * @param string  $id        The service id used to find edges
     * @param array   $arguments An array of arguments
     * @param Boolean $required
     * @param string  $name
     *
     * @return array An array of edges
     */
    private function findEdges($id, $arguments, $required, $name)
    {
        $edges = array();
        foreach ($arguments as $argument) {
            if ($argument instanceof Parameter) {
                $argument = $this->container->hasParameter($argument) ? $this->container->getParameter($argument) : null;
            } elseif (is_string($argument) && preg_match('/^%([^%]+)%$/', $argument, $match)) {
                $argument = $this->container->hasParameter($match[1]) ? $this->container->getParameter($match[1]) : null;
            }

            if ($argument instanceof Reference) {
                if (!$this->container->has((string) $argument)) {
                    $this->nodes[(string) $argument] = array('name' => $name, 'required' => $required, 'class' => '', 'attributes' => $this->options['node.missing']);
                }

                $edges[] = array('name' => $name, 'required' => $required, 'to' => $argument);
            } elseif (is_array($argument)) {
                $edges = array_merge($edges, $this->findEdges($id, $argument, $required, $name));
            }
        }

        return $edges;
    }

    /**
     * Finds all nodes.
     *
     * @return array An array of all nodes
     */
    private function findNodes()
    {
        $nodes = array();

        $container = $this->cloneContainer();

        foreach ($container->getDefinitions() as $id => $definition) {
            $nodes[$id] = array('class' => str_replace('\\', '\\\\', $this->container->getParameterBag()->resolveValue($definition->getClass())), 'attributes' => array_merge($this->options['node.definition'], array('style' => ContainerInterface::SCOPE_PROTOTYPE !== $definition->getScope() ? 'filled' : 'dotted')));

            $container->setDefinition($id, new Definition('stdClass'));
        }

        foreach ($container->getServiceIds() as $id) {
            $service = $container->get($id);

            if (in_array($id, array_keys($container->getAliases()))) {
                continue;
            }

            if (!$container->hasDefinition($id)) {
                $class = ('service_container' === $id) ? get_class($this->container) : get_class($service);
                $nodes[$id] = array('class' => str_replace('\\', '\\\\', $class), 'attributes' => $this->options['node.instance']);
            }
        }

        return $nodes;
    }

    private function cloneContainer()
    {
        $parameterBag = new ParameterBag($this->container->getParameterBag()->all());

        $container = new ContainerBuilder($parameterBag);
        $container->setDefinitions($this->container->getDefinitions());
        $container->setAliases($this->container->getAliases());
        $container->setResources($this->container->getResources());
        foreach ($this->container->getScopes() as $scope) {
            $container->addScope($scope);
        }
        foreach ($this->container->getExtensions() as $extension) {
            $container->registerExtension($extension);
        }

        return $container;
    }

    /**
     * Returns the start dot.
     *
     * @return string The string representation of a start dot
     */
    private function startDot()
    {
        return sprintf("digraph sc {\n  %s\n  node [%s];\n  edge [%s];\n\n",
            $this->addOptions($this->options['graph']),
            $this->addOptions($this->options['node']),
            $this->addOptions($this->options['edge'])
        );
    }

    /**
     * Returns the end dot.
     *
     * @return string
     */
    private function endDot()
    {
        return "}\n";
    }

    /**
     * Adds attributes
     *
     * @param array $attributes An array of attributes
     *
     * @return string A comma separated list of attributes
     */
    private function addAttributes($attributes)
    {
        $code = array();
        foreach ($attributes as $k => $v) {
            $code[] = sprintf('%s="%s"', $k, $v);
        }

        return $code ? ', '.implode(', ', $code) : '';
    }

    /**
     * Adds options
     *
     * @param array $options An array of options
     *
     * @return string A space separated list of options
     */
    private function addOptions($options)
    {
        $code = array();
        foreach ($options as $k => $v) {
            $code[] = sprintf('%s="%s"', $k, $v);
        }

        return implode(' ', $code);
    }

    /**
     * Dotizes an identifier.
     *
     * @param string $id The identifier to dotize
     *
     * @return string A dotized string
     */
    private function dotize($id)
    {
        return strtolower(preg_replace('/[^\w]/i', '_', $id));
    }

    /**
     * Compiles an array of aliases for a specified service id.
     *
     * @param string $id A service id
     *
     * @return array An array of aliases
     */
    private function getAliases($id)
    {
        $aliases = array();
        foreach ($this->container->getAliases() as $alias => $origin) {
            if ($id == $origin) {
                $aliases[] = $alias;
            }
        }

        return $aliases;
    }
}
Copyright (c) 2004-2013 Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

/**
 * Represents a variable.
 *
 *     $var = new Variable('a');
 *
 * will be dumped as
 *
 *     $a
 *
 * by the PHP dumper.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class Variable
{
    private $name;

    /**
     * Constructor
     *
     * @param string $name
     */
    public function __construct($name)
    {
        $this->name = $name;
    }

    /**
     * Converts the object to a string
     *
     * @return string
     */
    public function __toString()
    {
        return $this->name;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException;

/**
 * This definition decorates another definition.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @api
 */
class DefinitionDecorator extends Definition
{
    private $parent;
    private $changes = array();

    /**
     * Constructor.
     *
     * @param string $parent The id of Definition instance to decorate.
     *
     * @api
     */
    public function __construct($parent)
    {
        parent::__construct();

        $this->parent = $parent;
    }

    /**
     * Returns the Definition being decorated.
     *
     * @return string
     *
     * @api
     */
    public function getParent()
    {
        return $this->parent;
    }

    /**
     * Returns all changes tracked for the Definition object.
     *
     * @return array An array of changes for this Definition
     *
     * @api
     */
    public function getChanges()
    {
        return $this->changes;
    }

    /**
     * {@inheritDoc}
     *
     * @api
     */
    public function setClass($class)
    {
        $this->changes['class'] = true;

        return parent::setClass($class);
    }

    /**
     * {@inheritDoc}
     *
     * @api
     */
    public function setFactoryClass($class)
    {
        $this->changes['factory_class'] = true;

        return parent::setFactoryClass($class);
    }

    /**
     * {@inheritDoc}
     *
     * @api
     */
    public function setFactoryMethod($method)
    {
        $this->changes['factory_method'] = true;

        return parent::setFactoryMethod($method);
    }

    /**
     * {@inheritDoc}
     *
     * @api
     */
    public function setFactoryService($service)
    {
        $this->changes['factory_service'] = true;

        return parent::setFactoryService($service);
    }

    /**
     * {@inheritDoc}
     *
     * @api
     */
    public function setConfigurator($callable)
    {
        $this->changes['configurator'] = true;

        return parent::setConfigurator($callable);
    }

    /**
     * {@inheritDoc}
     *
     * @api
     */
    public function setFile($file)
    {
        $this->changes['file'] = true;

        return parent::setFile($file);
    }

    /**
     * {@inheritDoc}
     *
     * @api
     */
    public function setPublic($boolean)
    {
        $this->changes['public'] = true;

        return parent::setPublic($boolean);
    }

    /**
     * {@inheritDoc}
     *
     * @api
     */
    public function setLazy($boolean)
    {
        $this->changes['lazy'] = true;

        return parent::setLazy($boolean);
    }

    /**
     * Gets an argument to pass to the service constructor/factory method.
     *
     * If replaceArgument() has been used to replace an argument, this method
     * will return the replacement value.
     *
     * @param integer $index
     *
     * @return mixed The argument value
     *
     * @throws OutOfBoundsException When the argument does not exist
     *
     * @api
     */
    public function getArgument($index)
    {
        if (array_key_exists('index_'.$index, $this->arguments)) {
            return $this->arguments['index_'.$index];
        }

        $lastIndex = count(array_filter(array_keys($this->arguments), 'is_int')) - 1;

        if ($index < 0 || $index > $lastIndex) {
            throw new OutOfBoundsException(sprintf('The index "%d" is not in the range [0, %d].', $index, $lastIndex));
        }

        return $this->arguments[$index];
    }

    /**
     * You should always use this method when overwriting existing arguments
     * of the parent definition.
     *
     * If you directly call setArguments() keep in mind that you must follow
     * certain conventions when you want to overwrite the arguments of the
     * parent definition, otherwise your arguments will only be appended.
     *
     * @param integer $index
     * @param mixed   $value
     *
     * @return DefinitionDecorator the current instance
     * @throws InvalidArgumentException when $index isn't an integer
     *
     * @api
     */
    public function replaceArgument($index, $value)
    {
        if (!is_int($index)) {
            throw new InvalidArgumentException('$index must be an integer.');
        }

        $this->arguments['index_'.$index] = $value;

        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * Checks your services for circular references
 *
 * References from method calls are ignored since we might be able to resolve
 * these references depending on the order in which services are called.
 *
 * Circular reference from method calls will only be detected at run-time.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class CheckCircularReferencesPass implements CompilerPassInterface
{
    private $currentId;
    private $currentPath;
    private $checkedNodes;

    /**
     * Checks the ContainerBuilder object for circular references.
     *
     * @param ContainerBuilder $container The ContainerBuilder instances
     */
    public function process(ContainerBuilder $container)
    {
        $graph = $container->getCompiler()->getServiceReferenceGraph();

        $this->checkedNodes = array();
        foreach ($graph->getNodes() as $id => $node) {
            $this->currentId = $id;
            $this->currentPath = array($id);

            $this->checkOutEdges($node->getOutEdges());
        }
    }

    /**
     * Checks for circular references.
     *
     * @param ServiceReferenceGraphEdge[] $edges An array of Edges
     *
     * @throws ServiceCircularReferenceException When a circular reference is found.
     */
    private function checkOutEdges(array $edges)
    {
        foreach ($edges as $edge) {
            $node      = $edge->getDestNode();
            $id        = $node->getId();

            if (empty($this->checkedNodes[$id])) {
                $searchKey = array_search($id, $this->currentPath);
                $this->currentPath[] = $id;

                if (false !== $searchKey) {
                    throw new ServiceCircularReferenceException($id, array_slice($this->currentPath, $searchKey));
                }

                $this->checkOutEdges($node->getOutEdges());

                $this->checkedNodes[$id] = true;
                array_pop($this->currentPath);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;

/**
 * A pass that might be run repeatedly.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class RepeatedPass implements CompilerPassInterface
{
    /**
     * @var Boolean
     */
    private $repeat = false;

    /**
     * @var RepeatablePassInterface[]
     */
    private $passes;

    /**
     * Constructor.
     *
     * @param RepeatablePassInterface[] $passes An array of RepeatablePassInterface objects
     *
     * @throws InvalidArgumentException when the passes don't implement RepeatablePassInterface
     */
    public function __construct(array $passes)
    {
        foreach ($passes as $pass) {
            if (!$pass instanceof RepeatablePassInterface) {
                throw new InvalidArgumentException('$passes must be an array of RepeatablePassInterface.');
            }

            $pass->setRepeatedPass($this);
        }

        $this->passes = $passes;
    }

    /**
     * Process the repeatable passes that run more than once.
     *
     * @param ContainerBuilder $container
     */
    public function process(ContainerBuilder $container)
    {
        $this->repeat = false;
        foreach ($this->passes as $pass) {
            $pass->process($container);
        }

        if ($this->repeat) {
            $this->process($container);
        }
    }

    /**
     * Sets if the pass should repeat
     */
    public function setRepeat()
    {
        $this->repeat = true;
    }

    /**
     * Returns the passes
     *
     * @return RepeatablePassInterface[] An array of RepeatablePassInterface objects
     */
    public function getPasses()
    {
        return $this->passes;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Reference;

/**
 * Replaces aliases with actual service definitions, effectively removing these
 * aliases.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ReplaceAliasByActualDefinitionPass implements CompilerPassInterface
{
    private $compiler;
    private $formatter;
    private $sourceId;

    /**
     * Process the Container to replace aliases with service definitions.
     *
     * @param ContainerBuilder $container
     *
     * @throws InvalidArgumentException if the service definition does not exist
     */
    public function process(ContainerBuilder $container)
    {
        $this->compiler = $container->getCompiler();
        $this->formatter = $this->compiler->getLoggingFormatter();

        foreach ($container->getAliases() as $id => $alias) {
            $aliasId = (string) $alias;

            try {
                $definition = $container->getDefinition($aliasId);
            } catch (InvalidArgumentException $e) {
                throw new InvalidArgumentException(sprintf('Unable to replace alias "%s" with "%s".', $alias, $id), null, $e);
            }

            if ($definition->isPublic()) {
                continue;
            }

            $definition->setPublic(true);
            $container->setDefinition($id, $definition);
            $container->removeDefinition($aliasId);

            $this->updateReferences($container, $aliasId, $id);

            // we have to restart the process due to concurrent modification of
            // the container
            $this->process($container);

            break;
        }
    }

    /**
     * Updates references to remove aliases.
     *
     * @param ContainerBuilder $container The container
     * @param string           $currentId The alias identifier being replaced
     * @param string           $newId     The id of the service the alias points to
     */
    private function updateReferences($container, $currentId, $newId)
    {
        foreach ($container->getAliases() as $id => $alias) {
            if ($currentId === (string) $alias) {
                $container->setAlias($id, $newId);
            }
        }

        foreach ($container->getDefinitions() as $id => $definition) {
            $this->sourceId = $id;

            $definition->setArguments(
                $this->updateArgumentReferences($definition->getArguments(), $currentId, $newId)
            );

            $definition->setMethodCalls(
                $this->updateArgumentReferences($definition->getMethodCalls(), $currentId, $newId)
            );

            $definition->setProperties(
                $this->updateArgumentReferences($definition->getProperties(), $currentId, $newId)
            );
        }
    }

    /**
     * Updates argument references.
     *
     * @param array  $arguments An array of Arguments
     * @param string $currentId The alias identifier
     * @param string $newId     The identifier the alias points to
     *
     * @return array
     */
    private function updateArgumentReferences(array $arguments, $currentId, $newId)
    {
        foreach ($arguments as $k => $argument) {
            if (is_array($argument)) {
                $arguments[$k] = $this->updateArgumentReferences($argument, $currentId, $newId);
            } elseif ($argument instanceof Reference) {
                if ($currentId === (string) $argument) {
                    $arguments[$k] = new Reference($newId, $argument->getInvalidBehavior());
                    $this->compiler->addLogMessage($this->formatter->formatUpdateReference($this, $this->sourceId, $currentId, $newId));
                }
            }
        }

        return $arguments;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * Removes abstract Definitions
 *
 */
class RemoveAbstractDefinitionsPass implements CompilerPassInterface
{
    /**
     * Removes abstract definitions from the ContainerBuilder
     *
     * @param ContainerBuilder $container
     */
    public function process(ContainerBuilder $container)
    {
        $compiler = $container->getCompiler();
        $formatter = $compiler->getLoggingFormatter();

        foreach ($container->getDefinitions() as $id => $definition) {
            if ($definition->isAbstract()) {
                $container->removeDefinition($id);
                $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'abstract'));
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * Removes unused service definitions from the container.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class RemoveUnusedDefinitionsPass implements RepeatablePassInterface
{
    private $repeatedPass;

    /**
     * {@inheritDoc}
     */
    public function setRepeatedPass(RepeatedPass $repeatedPass)
    {
        $this->repeatedPass = $repeatedPass;
    }

    /**
     * Processes the ContainerBuilder to remove unused definitions.
     *
     * @param ContainerBuilder $container
     */
    public function process(ContainerBuilder $container)
    {
        $compiler = $container->getCompiler();
        $formatter = $compiler->getLoggingFormatter();
        $graph = $compiler->getServiceReferenceGraph();

        $hasChanged = false;
        foreach ($container->getDefinitions() as $id => $definition) {
            if ($definition->isPublic()) {
                continue;
            }

            if ($graph->hasNode($id)) {
                $edges = $graph->getNode($id)->getInEdges();
                $referencingAliases = array();
                $sourceIds = array();
                foreach ($edges as $edge) {
                    $node = $edge->getSourceNode();
                    $sourceIds[] = $node->getId();

                    if ($node->isAlias()) {
                        $referencingAliases[] = $node->getValue();
                    }
                }
                $isReferenced = (count(array_unique($sourceIds)) - count($referencingAliases)) > 0;
            } else {
                $referencingAliases = array();
                $isReferenced = false;
            }

            if (1 === count($referencingAliases) && false === $isReferenced) {
                $container->setDefinition((string) reset($referencingAliases), $definition);
                $definition->setPublic(true);
                $container->removeDefinition($id);
                $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'replaces alias '.reset($referencingAliases)));
            } elseif (0 === count($referencingAliases) && false === $isReferenced) {
                $container->removeDefinition($id);
                $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'unused'));
                $hasChanged = true;
            }
        }

        if ($hasChanged) {
            $this->repeatedPass->setRepeat();
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Definition;

use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * Checks that all references are pointing to a valid service.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class CheckExceptionOnInvalidReferenceBehaviorPass implements CompilerPassInterface
{
    private $container;
    private $sourceId;

    public function process(ContainerBuilder $container)
    {
        $this->container = $container;

        foreach ($container->getDefinitions() as $id => $definition) {
            $this->sourceId = $id;
            $this->processDefinition($definition);
        }
    }

    private function processDefinition(Definition $definition)
    {
        $this->processReferences($definition->getArguments());
        $this->processReferences($definition->getMethodCalls());
        $this->processReferences($definition->getProperties());
    }

    private function processReferences(array $arguments)
    {
        foreach ($arguments as $argument) {
            if (is_array($argument)) {
                $this->processReferences($argument);
            } elseif ($argument instanceof Definition) {
                $this->processDefinition($argument);
            } elseif ($argument instanceof Reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $argument->getInvalidBehavior()) {
                $destId = (string) $argument;

                if (!$this->container->has($destId)) {
                    throw new ServiceNotFoundException($destId, $this->sourceId);
                }
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;

/**
 * Compiler Pass Configuration
 *
 * This class has a default configuration embedded.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @api
 */
class PassConfig
{
    const TYPE_AFTER_REMOVING = 'afterRemoving';
    const TYPE_BEFORE_OPTIMIZATION = 'beforeOptimization';
    const TYPE_BEFORE_REMOVING = 'beforeRemoving';
    const TYPE_OPTIMIZE = 'optimization';
    const TYPE_REMOVE = 'removing';

    private $mergePass;
    private $afterRemovingPasses = array();
    private $beforeOptimizationPasses = array();
    private $beforeRemovingPasses = array();
    private $optimizationPasses;
    private $removingPasses;

    /**
     * Constructor.
     */
    public function __construct()
    {
        $this->mergePass = new MergeExtensionConfigurationPass();

        $this->optimizationPasses = array(
            new ResolveDefinitionTemplatesPass(),
            new ResolveParameterPlaceHoldersPass(),
            new CheckDefinitionValidityPass(),
            new ResolveReferencesToAliasesPass(),
            new ResolveInvalidReferencesPass(),
            new AnalyzeServiceReferencesPass(true),
            new CheckCircularReferencesPass(),
            new CheckReferenceValidityPass(),
        );

        $this->removingPasses = array(
            new RemovePrivateAliasesPass(),
            new RemoveAbstractDefinitionsPass(),
            new ReplaceAliasByActualDefinitionPass(),
            new RepeatedPass(array(
                new AnalyzeServiceReferencesPass(),
                new InlineServiceDefinitionsPass(),
                new AnalyzeServiceReferencesPass(),
                new RemoveUnusedDefinitionsPass(),
            )),
            new CheckExceptionOnInvalidReferenceBehaviorPass(),
        );
    }

    /**
     * Returns all passes in order to be processed.
     *
     * @return array An array of all passes to process
     *
     * @api
     */
    public function getPasses()
    {
        return array_merge(
            array($this->mergePass),
            $this->beforeOptimizationPasses,
            $this->optimizationPasses,
            $this->beforeRemovingPasses,
            $this->removingPasses,
            $this->afterRemovingPasses
        );
    }

    /**
     * Adds a pass.
     *
     * @param CompilerPassInterface $pass A Compiler pass
     * @param string                $type The pass type
     *
     * @throws InvalidArgumentException when a pass type doesn't exist
     *
     * @api
     */
    public function addPass(CompilerPassInterface $pass, $type = self::TYPE_BEFORE_OPTIMIZATION)
    {
        $property = $type.'Passes';
        if (!isset($this->$property)) {
            throw new InvalidArgumentException(sprintf('Invalid type "%s".', $type));
        }

        $passes = &$this->$property;
        $passes[] = $pass;
    }

    /**
     * Gets all passes for the AfterRemoving pass.
     *
     * @return array An array of passes
     *
     * @api
     */
    public function getAfterRemovingPasses()
    {
        return $this->afterRemovingPasses;
    }

    /**
     * Gets all passes for the BeforeOptimization pass.
     *
     * @return array An array of passes
     *
     * @api
     */
    public function getBeforeOptimizationPasses()
    {
        return $this->beforeOptimizationPasses;
    }

    /**
     * Gets all passes for the BeforeRemoving pass.
     *
     * @return array An array of passes
     *
     * @api
     */
    public function getBeforeRemovingPasses()
    {
        return $this->beforeRemovingPasses;
    }

    /**
     * Gets all passes for the Optimization pass.
     *
     * @return array An array of passes
     *
     * @api
     */
    public function getOptimizationPasses()
    {
        return $this->optimizationPasses;
    }

    /**
     * Gets all passes for the Removing pass.
     *
     * @return array An array of passes
     *
     * @api
     */
    public function getRemovingPasses()
    {
        return $this->removingPasses;
    }

    /**
     * Gets all passes for the Merge pass.
     *
     * @return array An array of passes
     *
     * @api
     */
    public function getMergePass()
    {
        return $this->mergePass;
    }

    /**
     * Sets the Merge Pass.
     *
     * @param CompilerPassInterface $pass The merge pass
     *
     * @api
     */
    public function setMergePass(CompilerPassInterface $pass)
    {
        $this->mergePass = $pass;
    }

    /**
     * Sets the AfterRemoving passes.
     *
     * @param array $passes An array of passes
     *
     * @api
     */
    public function setAfterRemovingPasses(array $passes)
    {
        $this->afterRemovingPasses = $passes;
    }

    /**
     * Sets the BeforeOptimization passes.
     *
     * @param array $passes An array of passes
     *
     * @api
     */
    public function setBeforeOptimizationPasses(array $passes)
    {
        $this->beforeOptimizationPasses = $passes;
    }

    /**
     * Sets the BeforeRemoving passes.
     *
     * @param array $passes An array of passes
     *
     * @api
     */
    public function setBeforeRemovingPasses(array $passes)
    {
        $this->beforeRemovingPasses = $passes;
    }

    /**
     * Sets the Optimization passes.
     *
     * @param array $passes An array of passes
     *
     * @api
     */
    public function setOptimizationPasses(array $passes)
    {
        $this->optimizationPasses = $passes;
    }

    /**
     * Sets the Removing passes.
     *
     * @param array $passes An array of passes
     *
     * @api
     */
    public function setRemovingPasses(array $passes)
    {
        $this->removingPasses = $passes;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;

/**
 * This replaces all DefinitionDecorator instances with their equivalent fully
 * merged Definition instance.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ResolveDefinitionTemplatesPass implements CompilerPassInterface
{
    private $container;
    private $compiler;
    private $formatter;

    /**
     * Process the ContainerBuilder to replace DefinitionDecorator instances with their real Definition instances.
     *
     * @param ContainerBuilder $container
     */
    public function process(ContainerBuilder $container)
    {
        $this->container = $container;
        $this->compiler = $container->getCompiler();
        $this->formatter = $this->compiler->getLoggingFormatter();

        foreach (array_keys($container->getDefinitions()) as $id) {
            // yes, we are specifically fetching the definition from the
            // container to ensure we are not operating on stale data
            $definition = $container->getDefinition($id);
            if (!$definition instanceof DefinitionDecorator || $definition->isAbstract()) {
                continue;
            }

            $this->resolveDefinition($id, $definition);
        }
    }

    /**
     * Resolves the definition
     *
     * @param string              $id         The definition identifier
     * @param DefinitionDecorator $definition
     *
     * @return Definition
     *
     * @throws \RuntimeException When the definition is invalid
     */
    private function resolveDefinition($id, DefinitionDecorator $definition)
    {
        if (!$this->container->hasDefinition($parent = $definition->getParent())) {
            throw new RuntimeException(sprintf('The parent definition "%s" defined for definition "%s" does not exist.', $parent, $id));
        }

        $parentDef = $this->container->getDefinition($parent);
        if ($parentDef instanceof DefinitionDecorator) {
            $parentDef = $this->resolveDefinition($parent, $parentDef);
        }

        $this->compiler->addLogMessage($this->formatter->formatResolveInheritance($this, $id, $parent));
        $def = new Definition();

        // merge in parent definition
        // purposely ignored attributes: scope, abstract, tags
        $def->setClass($parentDef->getClass());
        $def->setArguments($parentDef->getArguments());
        $def->setMethodCalls($parentDef->getMethodCalls());
        $def->setProperties($parentDef->getProperties());
        $def->setFactoryClass($parentDef->getFactoryClass());
        $def->setFactoryMethod($parentDef->getFactoryMethod());
        $def->setFactoryService($parentDef->getFactoryService());
        $def->setConfigurator($parentDef->getConfigurator());
        $def->setFile($parentDef->getFile());
        $def->setPublic($parentDef->isPublic());
        $def->setLazy($parentDef->isLazy());

        // overwrite with values specified in the decorator
        $changes = $definition->getChanges();
        if (isset($changes['class'])) {
            $def->setClass($definition->getClass());
        }
        if (isset($changes['factory_class'])) {
            $def->setFactoryClass($definition->getFactoryClass());
        }
        if (isset($changes['factory_method'])) {
            $def->setFactoryMethod($definition->getFactoryMethod());
        }
        if (isset($changes['factory_service'])) {
            $def->setFactoryService($definition->getFactoryService());
        }
        if (isset($changes['configurator'])) {
            $def->setConfigurator($definition->getConfigurator());
        }
        if (isset($changes['file'])) {
            $def->setFile($definition->getFile());
        }
        if (isset($changes['public'])) {
            $def->setPublic($definition->isPublic());
        }
        if (isset($changes['lazy'])) {
            $def->setLazy($definition->isLazy());
        }

        // merge arguments
        foreach ($definition->getArguments() as $k => $v) {
            if (is_numeric($k)) {
                $def->addArgument($v);
                continue;
            }

            if (0 !== strpos($k, 'index_')) {
                throw new RuntimeException(sprintf('Invalid argument key "%s" found.', $k));
            }

            $index = (integer) substr($k, strlen('index_'));
            $def->replaceArgument($index, $v);
        }

        // merge properties
        foreach ($definition->getProperties() as $k => $v) {
            $def->setProperty($k, $v);
        }

        // append method calls
        if (count($calls = $definition->getMethodCalls()) > 0) {
            $def->setMethodCalls(array_merge($def->getMethodCalls(), $calls));
        }

        // these attributes are always taken from the child
        $def->setAbstract($definition->isAbstract());
        $def->setScope($definition->getScope());
        $def->setTags($definition->getTags());

        // set new definition on container
        $this->container->setDefinition($id, $def);

        return $def;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

/**
 * Interface that must be implemented by passes that are run as part of an
 * RepeatedPass.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface RepeatablePassInterface extends CompilerPassInterface
{
    /**
     * Sets the RepeatedPass interface.
     *
     * @param RepeatedPass $repeatedPass
     */
    public function setRepeatedPass(RepeatedPass $repeatedPass);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * Inline service definitions where this is possible.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class InlineServiceDefinitionsPass implements RepeatablePassInterface
{
    private $repeatedPass;
    private $graph;
    private $compiler;
    private $formatter;
    private $currentId;

    /**
     * {@inheritDoc}
     */
    public function setRepeatedPass(RepeatedPass $repeatedPass)
    {
        $this->repeatedPass = $repeatedPass;
    }

    /**
     * Processes the ContainerBuilder for inline service definitions.
     *
     * @param ContainerBuilder $container
     */
    public function process(ContainerBuilder $container)
    {
        $this->compiler = $container->getCompiler();
        $this->formatter = $this->compiler->getLoggingFormatter();
        $this->graph = $this->compiler->getServiceReferenceGraph();

        foreach ($container->getDefinitions() as $id => $definition) {
            $this->currentId = $id;

            $definition->setArguments(
                $this->inlineArguments($container, $definition->getArguments())
            );

            $definition->setMethodCalls(
                $this->inlineArguments($container, $definition->getMethodCalls())
            );

            $definition->setProperties(
                $this->inlineArguments($container, $definition->getProperties())
            );
        }
    }

    /**
     * Processes inline arguments.
     *
     * @param ContainerBuilder $container The ContainerBuilder
     * @param array            $arguments An array of arguments
     *
     * @return array
     */
    private function inlineArguments(ContainerBuilder $container, array $arguments)
    {
        foreach ($arguments as $k => $argument) {
            if (is_array($argument)) {
                $arguments[$k] = $this->inlineArguments($container, $argument);
            } elseif ($argument instanceof Reference) {
                if (!$container->hasDefinition($id = (string) $argument)) {
                    continue;
                }

                if ($this->isInlineableDefinition($container, $id, $definition = $container->getDefinition($id))) {
                    $this->compiler->addLogMessage($this->formatter->formatInlineService($this, $id, $this->currentId));

                    if (ContainerInterface::SCOPE_PROTOTYPE !== $definition->getScope()) {
                        $arguments[$k] = $definition;
                    } else {
                        $arguments[$k] = clone $definition;
                    }
                }
            } elseif ($argument instanceof Definition) {
                $argument->setArguments($this->inlineArguments($container, $argument->getArguments()));
                $argument->setMethodCalls($this->inlineArguments($container, $argument->getMethodCalls()));
                $argument->setProperties($this->inlineArguments($container, $argument->getProperties()));
            }
        }

        return $arguments;
    }

    /**
     * Checks if the definition is inlineable.
     *
     * @param ContainerBuilder $container
     * @param string           $id
     * @param Definition       $definition
     *
     * @return Boolean If the definition is inlineable
     */
    private function isInlineableDefinition(ContainerBuilder $container, $id, Definition $definition)
    {
        if (ContainerInterface::SCOPE_PROTOTYPE === $definition->getScope()) {
            return true;
        }

        if ($definition->isPublic() || $definition->isLazy()) {
            return false;
        }

        if (!$this->graph->hasNode($id)) {
            return true;
        }

        $ids = array();
        foreach ($this->graph->getNode($id)->getInEdges() as $edge) {
            $ids[] = $edge->getSourceNode()->getId();
        }

        if (count(array_unique($ids)) > 1) {
            return false;
        }

        return $container->getDefinition(reset($ids))->getScope() === $definition->getScope();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;

/**
 * This pass validates each definition individually only taking the information
 * into account which is contained in the definition itself.
 *
 * Later passes can rely on the following, and specifically do not need to
 * perform these checks themselves:
 *
 * - non synthetic, non abstract services always have a class set
 * - synthetic services are always public
 * - synthetic services are always of non-prototype scope
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class CheckDefinitionValidityPass implements CompilerPassInterface
{
    /**
     * Processes the ContainerBuilder to validate the Definition.
     *
     * @param ContainerBuilder $container
     *
     * @throws RuntimeException When the Definition is invalid
     */
    public function process(ContainerBuilder $container)
    {
        foreach ($container->getDefinitions() as $id => $definition) {
            // synthetic service is public
            if ($definition->isSynthetic() && !$definition->isPublic()) {
                throw new RuntimeException(sprintf(
                    'A synthetic service ("%s") must be public.',
                    $id
                ));
            }

            // synthetic service has non-prototype scope
            if ($definition->isSynthetic() && ContainerInterface::SCOPE_PROTOTYPE === $definition->getScope()) {
                throw new RuntimeException(sprintf(
                    'A synthetic service ("%s") cannot be of scope "prototype".',
                    $id
                ));
            }

            // non-synthetic, non-abstract service has class
            if (!$definition->isAbstract() && !$definition->isSynthetic() && !$definition->getClass()) {
                if ($definition->getFactoryClass() || $definition->getFactoryService()) {
                    throw new RuntimeException(sprintf(
                        'Please add the class to service "%s" even if it is constructed by a factory '
                       .'since we might need to add method calls based on compile-time checks.',
                       $id
                    ));
                }

                throw new RuntimeException(sprintf(
                    'The definition for "%s" has no class. If you intend to inject '
                   .'this service dynamically at runtime, please mark it as synthetic=true. '
                   .'If this is an abstract definition solely used by child definitions, '
                   .'please add abstract=true, otherwise specify a class to get rid of this error.',
                   $id
                ));
            }

            // tag attribute values must be scalars
            foreach ($definition->getTags() as $name => $tags) {
                foreach ($tags as $attributes) {
                    foreach ($attributes as $attribute => $value) {
                        if (!is_scalar($value) && null !== $value) {
                            throw new RuntimeException(sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s".', $id, $name, $attribute));
                        }
                    }
                }
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

/**
 * Represents an edge in your service graph.
 *
 * Value is typically a reference.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ServiceReferenceGraphEdge
{
    private $sourceNode;
    private $destNode;
    private $value;

    /**
     * Constructor.
     *
     * @param ServiceReferenceGraphNode $sourceNode
     * @param ServiceReferenceGraphNode $destNode
     * @param string                    $value
     */
    public function __construct(ServiceReferenceGraphNode $sourceNode, ServiceReferenceGraphNode $destNode, $value = null)
    {
        $this->sourceNode = $sourceNode;
        $this->destNode = $destNode;
        $this->value = $value;
    }

    /**
     * Returns the value of the edge
     *
     * @return ServiceReferenceGraphNode
     */
    public function getValue()
    {
        return $this->value;
    }

    /**
     * Returns the source node
     *
     * @return ServiceReferenceGraphNode
     */
    public function getSourceNode()
    {
        return $this->sourceNode;
    }

    /**
     * Returns the destination node
     *
     * @return ServiceReferenceGraphNode
     */
    public function getDestNode()
    {
        return $this->destNode;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;

/**
 * Emulates the invalid behavior if the reference is not found within the
 * container.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ResolveInvalidReferencesPass implements CompilerPassInterface
{
    private $container;

    /**
     * Process the ContainerBuilder to resolve invalid references.
     *
     * @param ContainerBuilder $container
     */
    public function process(ContainerBuilder $container)
    {
        $this->container = $container;
        foreach ($container->getDefinitions() as $definition) {
            if ($definition->isSynthetic() || $definition->isAbstract()) {
                continue;
            }

            $definition->setArguments(
                $this->processArguments($definition->getArguments())
            );

            $calls = array();
            foreach ($definition->getMethodCalls() as $call) {
                try {
                    $calls[] = array($call[0], $this->processArguments($call[1], true));
                } catch (RuntimeException $ignore) {
                    // this call is simply removed
                }
            }
            $definition->setMethodCalls($calls);

            $properties = array();
            foreach ($definition->getProperties() as $name => $value) {
                try {
                    $value = $this->processArguments(array($value), true);
                    $properties[$name] = reset($value);
                } catch (RuntimeException $ignore) {
                    // ignore property
                }
            }
            $definition->setProperties($properties);
        }
    }

    /**
     * Processes arguments to determine invalid references.
     *
     * @param array   $arguments    An array of Reference objects
     * @param Boolean $inMethodCall
     *
     * @return array
     *
     * @throws RuntimeException When the config is invalid
     */
    private function processArguments(array $arguments, $inMethodCall = false)
    {
        foreach ($arguments as $k => $argument) {
            if (is_array($argument)) {
                $arguments[$k] = $this->processArguments($argument, $inMethodCall);
            } elseif ($argument instanceof Reference) {
                $id = (string) $argument;

                $invalidBehavior = $argument->getInvalidBehavior();
                $exists = $this->container->has($id);

                // resolve invalid behavior
                if (!$exists && ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) {
                    $arguments[$k] = null;
                } elseif (!$exists && ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $invalidBehavior) {
                    if ($inMethodCall) {
                        throw new RuntimeException('Method shouldn\'t be called.');
                    }

                    $arguments[$k] = null;
                }
            }
        }

        return $arguments;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\Exception\ScopeCrossingInjectionException;
use Symfony\Component\DependencyInjection\Exception\ScopeWideningInjectionException;

/**
 * Checks the validity of references
 *
 * The following checks are performed by this pass:
 * - target definitions are not abstract
 * - target definitions are of equal or wider scope
 * - target definitions are in the same scope hierarchy
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class CheckReferenceValidityPass implements CompilerPassInterface
{
    private $container;
    private $currentId;
    private $currentDefinition;
    private $currentScope;
    private $currentScopeAncestors;
    private $currentScopeChildren;

    /**
     * Processes the ContainerBuilder to validate References.
     *
     * @param ContainerBuilder $container
     */
    public function process(ContainerBuilder $container)
    {
        $this->container = $container;

        $children = $this->container->getScopeChildren();
        $ancestors = array();

        $scopes = $this->container->getScopes();
        foreach ($scopes as $name => $parent) {
            $ancestors[$name] = array($parent);

            while (isset($scopes[$parent])) {
                $ancestors[$name][] = $parent = $scopes[$parent];
            }
        }

        foreach ($container->getDefinitions() as $id => $definition) {
            if ($definition->isSynthetic() || $definition->isAbstract()) {
                continue;
            }

            $this->currentId = $id;
            $this->currentDefinition = $definition;
            $this->currentScope = $scope = $definition->getScope();

            if (ContainerInterface::SCOPE_CONTAINER === $scope) {
                $this->currentScopeChildren = array_keys($scopes);
                $this->currentScopeAncestors = array();
            } elseif (ContainerInterface::SCOPE_PROTOTYPE !== $scope) {
                $this->currentScopeChildren = isset($children[$scope]) ? $children[$scope] : array();
                $this->currentScopeAncestors = isset($ancestors[$scope]) ? $ancestors[$scope] : array();
            }

            $this->validateReferences($definition->getArguments());
            $this->validateReferences($definition->getMethodCalls());
            $this->validateReferences($definition->getProperties());
        }
    }

    /**
     * Validates an array of References.
     *
     * @param array $arguments An array of Reference objects
     *
     * @throws RuntimeException when there is a reference to an abstract definition.
     */
    private function validateReferences(array $arguments)
    {
        foreach ($arguments as $argument) {
            if (is_array($argument)) {
                $this->validateReferences($argument);
            } elseif ($argument instanceof Reference) {
                $targetDefinition = $this->getDefinition((string) $argument);

                if (null !== $targetDefinition && $targetDefinition->isAbstract()) {
                    throw new RuntimeException(sprintf(
                        'The definition "%s" has a reference to an abstract definition "%s". '
                       .'Abstract definitions cannot be the target of references.',
                       $this->currentId,
                       $argument
                    ));
                }

                $this->validateScope($argument, $targetDefinition);
            }
        }
    }

    /**
     * Validates the scope of a single Reference.
     *
     * @param Reference  $reference
     * @param Definition $definition
     *
     * @throws ScopeWideningInjectionException when the definition references a service of a narrower scope
     * @throws ScopeCrossingInjectionException when the definition references a service of another scope hierarchy
     */
    private function validateScope(Reference $reference, Definition $definition = null)
    {
        if (ContainerInterface::SCOPE_PROTOTYPE === $this->currentScope) {
            return;
        }

        if (!$reference->isStrict()) {
            return;
        }

        if (null === $definition) {
            return;
        }

        if ($this->currentScope === $scope = $definition->getScope()) {
            return;
        }

        $id = (string) $reference;

        if (in_array($scope, $this->currentScopeChildren, true)) {
            throw new ScopeWideningInjectionException($this->currentId, $this->currentScope, $id, $scope);
        }

        if (!in_array($scope, $this->currentScopeAncestors, true)) {
            throw new ScopeCrossingInjectionException($this->currentId, $this->currentScope, $id, $scope);
        }
    }

    /**
     * Returns the Definition given an id.
     *
     * @param string $id Definition identifier
     *
     * @return Definition
     */
    private function getDefinition($id)
    {
        if (!$this->container->hasDefinition($id)) {
            return null;
        }

        return $this->container->getDefinition($id);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;

/**
 * Merges extension configs into the container builder
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class MergeExtensionConfigurationPass implements CompilerPassInterface
{
    /**
     * {@inheritDoc}
     */
    public function process(ContainerBuilder $container)
    {
        $parameters = $container->getParameterBag()->all();
        $definitions = $container->getDefinitions();
        $aliases = $container->getAliases();

        foreach ($container->getExtensions() as $extension) {
            if ($extension instanceof PrependExtensionInterface) {
                $extension->prepend($container);
            }
        }

        foreach ($container->getExtensions() as $name => $extension) {
            if (!$config = $container->getExtensionConfig($name)) {
                // this extension was not called
                continue;
            }
            $config = $container->getParameterBag()->resolveValue($config);

            $tmpContainer = new ContainerBuilder($container->getParameterBag());
            $tmpContainer->setResourceTracking($container->isTrackingResources());
            $tmpContainer->addObjectResource($extension);

            $extension->load($config, $tmpContainer);

            $container->merge($tmpContainer);
        }

        $container->addDefinitions($definitions);
        $container->addAliases($aliases);
        $container->getParameterBag()->add($parameters);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * Interface that must be implemented by compilation passes
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @api
 */
interface CompilerPassInterface
{
    /**
     * You can modify the container here before it is dumped to PHP code.
     *
     * @param ContainerBuilder $container
     *
     * @api
     */
    public function process(ContainerBuilder $container);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;

/**
 * Resolves all parameter placeholders "%somevalue%" to their real values.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ResolveParameterPlaceHoldersPass implements CompilerPassInterface
{
    /**
     * Processes the ContainerBuilder to resolve parameter placeholders.
     *
     * @param ContainerBuilder $container
     *
     * @throws ParameterNotFoundException
     */
    public function process(ContainerBuilder $container)
    {
        $parameterBag = $container->getParameterBag();

        foreach ($container->getDefinitions() as $id => $definition) {
            try {
                $definition->setClass($parameterBag->resolveValue($definition->getClass()));
                $definition->setFile($parameterBag->resolveValue($definition->getFile()));
                $definition->setArguments($parameterBag->resolveValue($definition->getArguments()));

                $calls = array();
                foreach ($definition->getMethodCalls() as $name => $arguments) {
                    $calls[$parameterBag->resolveValue($name)] = $parameterBag->resolveValue($arguments);
                }
                $definition->setMethodCalls($calls);

                $definition->setProperties($parameterBag->resolveValue($definition->getProperties()));
            } catch (ParameterNotFoundException $e) {
                $e->setSourceId($id);

                throw $e;
            }
        }

        $aliases = array();
        foreach ($container->getAliases() as $name => $target) {
            $aliases[$parameterBag->resolveValue($name)] = $parameterBag->resolveValue($target);
        }
        $container->setAliases($aliases);

        $parameterBag->resolve();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * Run this pass before passes that need to know more about the relation of
 * your services.
 *
 * This class will populate the ServiceReferenceGraph with information. You can
 * retrieve the graph in other passes from the compiler.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class AnalyzeServiceReferencesPass implements RepeatablePassInterface
{
    private $graph;
    private $container;
    private $currentId;
    private $currentDefinition;
    private $repeatedPass;
    private $onlyConstructorArguments;

    /**
     * Constructor.
     *
     * @param Boolean $onlyConstructorArguments Sets this Service Reference pass to ignore method calls
     */
    public function __construct($onlyConstructorArguments = false)
    {
        $this->onlyConstructorArguments = (Boolean) $onlyConstructorArguments;
    }

    /**
     * {@inheritDoc}
     */
    public function setRepeatedPass(RepeatedPass $repeatedPass)
    {
        $this->repeatedPass = $repeatedPass;
    }

    /**
     * Processes a ContainerBuilder object to populate the service reference graph.
     *
     * @param ContainerBuilder $container
     */
    public function process(ContainerBuilder $container)
    {
        $this->container = $container;
        $this->graph     = $container->getCompiler()->getServiceReferenceGraph();
        $this->graph->clear();

        foreach ($container->getDefinitions() as $id => $definition) {
            if ($definition->isSynthetic() || $definition->isAbstract()) {
                continue;
            }

            $this->currentId = $id;
            $this->currentDefinition = $definition;
            $this->processArguments($definition->getArguments());

            if (!$this->onlyConstructorArguments) {
                $this->processArguments($definition->getMethodCalls());
                $this->processArguments($definition->getProperties());
                if ($definition->getConfigurator()) {
                    $this->processArguments(array($definition->getConfigurator()));
                }
            }
        }

        foreach ($container->getAliases() as $id => $alias) {
            $this->graph->connect($id, $alias, (string) $alias, $this->getDefinition((string) $alias), null);
        }
    }

    /**
     * Processes service definitions for arguments to find relationships for the service graph.
     *
     * @param array $arguments An array of Reference or Definition objects relating to service definitions
     */
    private function processArguments(array $arguments)
    {
        foreach ($arguments as $argument) {
            if (is_array($argument)) {
                $this->processArguments($argument);
            } elseif ($argument instanceof Reference) {
                $this->graph->connect(
                    $this->currentId,
                    $this->currentDefinition,
                    $this->getDefinitionId((string) $argument),
                    $this->getDefinition((string) $argument),
                    $argument
                );
            } elseif ($argument instanceof Definition) {
                $this->processArguments($argument->getArguments());
                $this->processArguments($argument->getMethodCalls());
                $this->processArguments($argument->getProperties());
            }
        }
    }

    /**
     * Returns a service definition given the full name or an alias.
     *
     * @param string $id A full id or alias for a service definition.
     *
     * @return Definition|null The definition related to the supplied id
     */
    private function getDefinition($id)
    {
        $id = $this->getDefinitionId($id);

        return null === $id ? null : $this->container->getDefinition($id);
    }

    private function getDefinitionId($id)
    {
        while ($this->container->hasAlias($id)) {
            $id = (string) $this->container->getAlias($id);
        }

        if (!$this->container->hasDefinition($id)) {
            return null;
        }

        return $id;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Alias;

/**
 * Represents a node in your service graph.
 *
 * Value is typically a definition, or an alias.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ServiceReferenceGraphNode
{
    private $id;
    private $inEdges = array();
    private $outEdges = array();
    private $value;

    /**
     * Constructor.
     *
     * @param string $id    The node identifier
     * @param mixed  $value The node value
     */
    public function __construct($id, $value)
    {
        $this->id = $id;
        $this->value = $value;
    }

    /**
     * Adds an in edge to this node.
     *
     * @param ServiceReferenceGraphEdge $edge
     */
    public function addInEdge(ServiceReferenceGraphEdge $edge)
    {
        $this->inEdges[] = $edge;
    }

    /**
     * Adds an out edge to this node.
     *
     * @param ServiceReferenceGraphEdge $edge
     */
    public function addOutEdge(ServiceReferenceGraphEdge $edge)
    {
        $this->outEdges[] = $edge;
    }

    /**
     * Checks if the value of this node is an Alias.
     *
     * @return Boolean True if the value is an Alias instance
     */
    public function isAlias()
    {
        return $this->value instanceof Alias;
    }

    /**
     * Checks if the value of this node is a Definition.
     *
     * @return Boolean True if the value is a Definition instance
     */
    public function isDefinition()
    {
        return $this->value instanceof Definition;
    }

    /**
     * Returns the identifier.
     *
     * @return string
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Returns the in edges.
     *
     * @return array The in ServiceReferenceGraphEdge array
     */
    public function getInEdges()
    {
        return $this->inEdges;
    }

    /**
     * Returns the out edges.
     *
     * @return array The out ServiceReferenceGraphEdge array
     */
    public function getOutEdges()
    {
        return $this->outEdges;
    }

    /**
     * Returns the value of this Node
     *
     * @return mixed The value
     */
    public function getValue()
    {
        return $this->value;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

/**
 * Used to format logging messages during the compilation.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class LoggingFormatter
{
    public function formatRemoveService(CompilerPassInterface $pass, $id, $reason)
    {
        return $this->format($pass, sprintf('Removed service "%s"; reason: %s', $id, $reason));
    }

    public function formatInlineService(CompilerPassInterface $pass, $id, $target)
    {
        return $this->format($pass, sprintf('Inlined service "%s" to "%s".', $id, $target));
    }

    public function formatUpdateReference(CompilerPassInterface $pass, $serviceId, $oldDestId, $newDestId)
    {
        return $this->format($pass, sprintf('Changed reference of service "%s" previously pointing to "%s" to "%s".', $serviceId, $oldDestId, $newDestId));
    }

    public function formatResolveInheritance(CompilerPassInterface $pass, $childId, $parentId)
    {
        return $this->format($pass, sprintf('Resolving inheritance for "%s" (parent: %s).', $childId, $parentId));
    }

    public function format(CompilerPassInterface $pass, $message)
    {
        return sprintf('%s: %s', get_class($pass), $message);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;

/**
 * This is a directed graph of your services.
 *
 * This information can be used by your compiler passes instead of collecting
 * it themselves which improves performance quite a lot.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ServiceReferenceGraph
{
    /**
     * @var ServiceReferenceGraphNode[]
     */
    private $nodes = array();

    /**
     * Checks if the graph has a specific node.
     *
     * @param string $id Id to check
     *
     * @return Boolean
     */
    public function hasNode($id)
    {
        return isset($this->nodes[$id]);
    }

    /**
     * Gets a node by identifier.
     *
     * @param string $id The id to retrieve
     *
     * @return ServiceReferenceGraphNode The node matching the supplied identifier
     *
     * @throws InvalidArgumentException if no node matches the supplied identifier
     */
    public function getNode($id)
    {
        if (!isset($this->nodes[$id])) {
            throw new InvalidArgumentException(sprintf('There is no node with id "%s".', $id));
        }

        return $this->nodes[$id];
    }

    /**
     * Returns all nodes.
     *
     * @return ServiceReferenceGraphNode[] An array of all ServiceReferenceGraphNode objects
     */
    public function getNodes()
    {
        return $this->nodes;
    }

    /**
     * Clears all nodes.
     */
    public function clear()
    {
        $this->nodes = array();
    }

    /**
     * Connects 2 nodes together in the Graph.
     *
     * @param string $sourceId
     * @param string $sourceValue
     * @param string $destId
     * @param string $destValue
     * @param string $reference
     */
    public function connect($sourceId, $sourceValue, $destId, $destValue = null, $reference = null)
    {
        $sourceNode = $this->createNode($sourceId, $sourceValue);
        $destNode = $this->createNode($destId, $destValue);
        $edge = new ServiceReferenceGraphEdge($sourceNode, $destNode, $reference);

        $sourceNode->addOutEdge($edge);
        $destNode->addInEdge($edge);
    }

    /**
     * Creates a graph node.
     *
     * @param string $id
     * @param string $value
     *
     * @return ServiceReferenceGraphNode
     */
    private function createNode($id, $value)
    {
        if (isset($this->nodes[$id]) && $this->nodes[$id]->getValue() === $value) {
            return $this->nodes[$id];
        }

        return $this->nodes[$id] = new ServiceReferenceGraphNode($id, $value);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * Remove private aliases from the container. They were only used to establish
 * dependencies between services, and these dependencies have been resolved in
 * one of the previous passes.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class RemovePrivateAliasesPass implements CompilerPassInterface
{
    /**
     * Removes private aliases from the ContainerBuilder
     *
     * @param ContainerBuilder $container
     */
    public function process(ContainerBuilder $container)
    {
        $compiler = $container->getCompiler();
        $formatter = $compiler->getLoggingFormatter();

        foreach ($container->getAliases() as $id => $alias) {
            if ($alias->isPublic()) {
                continue;
            }

            $container->removeAlias($id);
            $compiler->addLogMessage($formatter->formatRemoveService($this, $id, 'private alias'));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * Replaces all references to aliases with references to the actual service.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ResolveReferencesToAliasesPass implements CompilerPassInterface
{
    private $container;

    /**
     * Processes the ContainerBuilder to replace references to aliases with actual service references.
     *
     * @param ContainerBuilder $container
     */
    public function process(ContainerBuilder $container)
    {
        $this->container = $container;

        foreach ($container->getDefinitions() as $definition) {
            if ($definition->isSynthetic() || $definition->isAbstract()) {
                continue;
            }

            $definition->setArguments($this->processArguments($definition->getArguments()));
            $definition->setMethodCalls($this->processArguments($definition->getMethodCalls()));
            $definition->setProperties($this->processArguments($definition->getProperties()));
        }

        foreach ($container->getAliases() as $id => $alias) {
            $aliasId = (string) $alias;
            if ($aliasId !== $defId = $this->getDefinitionId($aliasId)) {
                $container->setAlias($id, new Alias($defId, $alias->isPublic()));
            }
        }
    }

    /**
     * Processes the arguments to replace aliases.
     *
     * @param array $arguments An array of References
     *
     * @return array An array of References
     */
    private function processArguments(array $arguments)
    {
        foreach ($arguments as $k => $argument) {
            if (is_array($argument)) {
                $arguments[$k] = $this->processArguments($argument);
            } elseif ($argument instanceof Reference) {
                $defId = $this->getDefinitionId($id = (string) $argument);

                if ($defId !== $id) {
                    $arguments[$k] = new Reference($defId, $argument->getInvalidBehavior(), $argument->isStrict());
                }
            }
        }

        return $arguments;
    }

    /**
     * Resolves an alias into a definition id.
     *
     * @param string $id The definition or alias id to resolve
     *
     * @return string The definition id with aliases resolved
     */
    private function getDefinitionId($id)
    {
        while ($this->container->hasAlias($id)) {
            $id = (string) $this->container->getAlias($id);
        }

        return $id;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;

/**
 * This class is used to remove circular dependencies between individual passes.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @api
 */
class Compiler
{
    private $passConfig;
    private $log = array();
    private $loggingFormatter;
    private $serviceReferenceGraph;

    /**
     * Constructor.
     */
    public function __construct()
    {
        $this->passConfig = new PassConfig();
        $this->serviceReferenceGraph = new ServiceReferenceGraph();
        $this->loggingFormatter = new LoggingFormatter();
    }

    /**
     * Returns the PassConfig.
     *
     * @return PassConfig The PassConfig instance
     *
     * @api
     */
    public function getPassConfig()
    {
        return $this->passConfig;
    }

    /**
     * Returns the ServiceReferenceGraph.
     *
     * @return ServiceReferenceGraph The ServiceReferenceGraph instance
     *
     * @api
     */
    public function getServiceReferenceGraph()
    {
        return $this->serviceReferenceGraph;
    }

    /**
     * Returns the logging formatter which can be used by compilation passes.
     *
     * @return LoggingFormatter
     */
    public function getLoggingFormatter()
    {
        return $this->loggingFormatter;
    }

    /**
     * Adds a pass to the PassConfig.
     *
     * @param CompilerPassInterface $pass A compiler pass
     * @param string                $type The type of the pass
     *
     * @api
     */
    public function addPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION)
    {
        $this->passConfig->addPass($pass, $type);
    }

    /**
     * Adds a log message.
     *
     * @param string $string The log message
     */
    public function addLogMessage($string)
    {
        $this->log[] = $string;
    }

    /**
     * Returns the log.
     *
     * @return array Log array
     */
    public function getLog()
    {
        return $this->log;
    }

    /**
     * Run the Compiler and process all Passes.
     *
     * @param ContainerBuilder $container
     *
     * @api
     */
    public function compile(ContainerBuilder $container)
    {
        foreach ($this->passConfig->getPasses() as $pass) {
            $pass->process($container);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

/**
 * ContainerAware trait.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
trait ContainerAwareTrait
{
    /**
     * @var ContainerInterface
     */
    protected $container;

    /**
     * Sets the Container associated with this Controller.
     *
     * @param ContainerInterface $container A ContainerInterface instance
     */
    public function setContainer(ContainerInterface $container = null)
    {
        $this->container = $container;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;

/**
 * Container is a dependency injection container.
 *
 * It gives access to object instances (services).
 *
 * Services and parameters are simple key/pair stores.
 *
 * Parameter and service keys are case insensitive.
 *
 * A service id can contain lowercased letters, digits, underscores, and dots.
 * Underscores are used to separate words, and dots to group services
 * under namespaces:
 *
 * <ul>
 *   <li>request</li>
 *   <li>mysql_session_storage</li>
 *   <li>symfony.mysql_session_storage</li>
 * </ul>
 *
 * A service can also be defined by creating a method named
 * getXXXService(), where XXX is the camelized version of the id:
 *
 * <ul>
 *   <li>request -> getRequestService()</li>
 *   <li>mysql_session_storage -> getMysqlSessionStorageService()</li>
 *   <li>symfony.mysql_session_storage -> getSymfony_MysqlSessionStorageService()</li>
 * </ul>
 *
 * The container can have three possible behaviors when a service does not exist:
 *
 *  * EXCEPTION_ON_INVALID_REFERENCE: Throws an exception (the default)
 *  * NULL_ON_INVALID_REFERENCE:      Returns null
 *  * IGNORE_ON_INVALID_REFERENCE:    Ignores the wrapping command asking for the reference
 *                                    (for instance, ignore a setter if the service does not exist)
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @api
 */
class Container implements IntrospectableContainerInterface
{
    /**
     * @var ParameterBagInterface
     */
    protected $parameterBag;

    protected $services = array();
    protected $methodMap = array();
    protected $aliases = array();
    protected $scopes = array();
    protected $scopeChildren = array();
    protected $scopedServices = array();
    protected $scopeStacks = array();
    protected $loading = array();

    /**
     * Constructor.
     *
     * @param ParameterBagInterface $parameterBag A ParameterBagInterface instance
     *
     * @api
     */
    public function __construct(ParameterBagInterface $parameterBag = null)
    {
        $this->parameterBag = $parameterBag ?: new ParameterBag();

        $this->set('service_container', $this);
    }

    /**
     * Compiles the container.
     *
     * This method does two things:
     *
     *  * Parameter values are resolved;
     *  * The parameter bag is frozen.
     *
     * @api
     */
    public function compile()
    {
        $this->parameterBag->resolve();

        $this->parameterBag = new FrozenParameterBag($this->parameterBag->all());
    }

    /**
     * Returns true if the container parameter bag are frozen.
     *
     * @return Boolean true if the container parameter bag are frozen, false otherwise
     *
     * @api
     */
    public function isFrozen()
    {
        return $this->parameterBag instanceof FrozenParameterBag;
    }

    /**
     * Gets the service container parameter bag.
     *
     * @return ParameterBagInterface A ParameterBagInterface instance
     *
     * @api
     */
    public function getParameterBag()
    {
        return $this->parameterBag;
    }

    /**
     * Gets a parameter.
     *
     * @param string $name The parameter name
     *
     * @return mixed  The parameter value
     *
     * @throws InvalidArgumentException if the parameter is not defined
     *
     * @api
     */
    public function getParameter($name)
    {
        return $this->parameterBag->get($name);
    }

    /**
     * Checks if a parameter exists.
     *
     * @param string $name The parameter name
     *
     * @return Boolean The presence of parameter in container
     *
     * @api
     */
    public function hasParameter($name)
    {
        return $this->parameterBag->has($name);
    }

    /**
     * Sets a parameter.
     *
     * @param string $name  The parameter name
     * @param mixed  $value The parameter value
     *
     * @api
     */
    public function setParameter($name, $value)
    {
        $this->parameterBag->set($name, $value);
    }

    /**
     * Sets a service.
     *
     * Setting a service to null resets the service: has() returns false and get()
     * behaves in the same way as if the service was never created.
     *
     * @param string $id      The service identifier
     * @param object $service The service instance
     * @param string $scope   The scope of the service
     *
     * @throws RuntimeException When trying to set a service in an inactive scope
     * @throws InvalidArgumentException When trying to set a service in the prototype scope
     *
     * @api
     */
    public function set($id, $service, $scope = self::SCOPE_CONTAINER)
    {
        if (self::SCOPE_PROTOTYPE === $scope) {
            throw new InvalidArgumentException(sprintf('You cannot set service "%s" of scope "prototype".', $id));
        }

        $id = strtolower($id);

        if (self::SCOPE_CONTAINER !== $scope) {
            if (!isset($this->scopedServices[$scope])) {
                throw new RuntimeException(sprintf('You cannot set service "%s" of inactive scope.', $id));
            }

            $this->scopedServices[$scope][$id] = $service;
        }

        $this->services[$id] = $service;

        if (method_exists($this, $method = 'synchronize'.strtr($id, array('_' => '', '.' => '_')).'Service')) {
            $this->$method();
        }

        if (self::SCOPE_CONTAINER !== $scope && null === $service) {
            unset($this->scopedServices[$scope][$id]);
        }

        if (null === $service) {
            unset($this->services[$id]);
        }
    }

    /**
     * Returns true if the given service is defined.
     *
     * @param string $id The service identifier
     *
     * @return Boolean true if the service is defined, false otherwise
     *
     * @api
     */
    public function has($id)
    {
        $id = strtolower($id);

        return isset($this->services[$id])
            || array_key_exists($id, $this->services)
            || isset($this->aliases[$id])
            || method_exists($this, 'get'.strtr($id, array('_' => '', '.' => '_')).'Service')
        ;
    }

    /**
     * Gets a service.
     *
     * If a service is defined both through a set() method and
     * with a get{$id}Service() method, the former has always precedence.
     *
     * @param string  $id              The service identifier
     * @param integer $invalidBehavior The behavior when the service does not exist
     *
     * @return object The associated service
     *
     * @throws InvalidArgumentException if the service is not defined
     * @throws ServiceCircularReferenceException When a circular reference is detected
     * @throws ServiceNotFoundException When the service is not defined
     *
     * @see Reference
     *
     * @api
     */
    public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE)
    {
        // Attempt to retrieve the service by checking first aliases then
        // available services. Service IDs are case insensitive, however since
        // this method can be called thousands of times during a request, avoid
        // calling strotolower() unless necessary.
        foreach (array(false, true) as $strtolower) {
            if ($strtolower) {
                $id = strtolower($id);
            }
            if (isset($this->aliases[$id])) {
                $id = $this->aliases[$id];
            }
            // Re-use shared service instance if it exists.
            if (isset($this->services[$id]) || array_key_exists($id, $this->services)) {
                return $this->services[$id];
            }
        }

        if (isset($this->loading[$id])) {
            throw new ServiceCircularReferenceException($id, array_keys($this->loading));
        }

        if (isset($this->methodMap[$id])) {
            $method = $this->methodMap[$id];
        } elseif (method_exists($this, $method = 'get'.strtr($id, array('_' => '', '.' => '_')).'Service')) {
            // $method is set to the right value, proceed
        } else {
            if (self::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) {
                if (!$id) {
                    throw new ServiceNotFoundException($id);
                }

                $alternatives = array();
                foreach (array_keys($this->services) as $key) {
                    $lev = levenshtein($id, $key);
                    if ($lev <= strlen($id) / 3 || false !== strpos($key, $id)) {
                        $alternatives[] = $key;
                    }
                }

                throw new ServiceNotFoundException($id, null, null, $alternatives);
            }

            return null;
        }

        $this->loading[$id] = true;

        try {
            $service = $this->$method();
        } catch (\Exception $e) {
            unset($this->loading[$id]);

            if (array_key_exists($id, $this->services)) {
                unset($this->services[$id]);
            }

            if ($e instanceof InactiveScopeException && self::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
                return null;
            }

            throw $e;
        }

        unset($this->loading[$id]);

        return $service;
    }

    /**
     * Returns true if the given service has actually been initialized
     *
     * @param string $id The service identifier
     *
     * @return Boolean true if service has already been initialized, false otherwise
     */
    public function initialized($id)
    {
        $id = strtolower($id);

        return isset($this->services[$id]) || array_key_exists($id, $this->services);
    }

    /**
     * Gets all service ids.
     *
     * @return array An array of all defined service ids
     */
    public function getServiceIds()
    {
        $ids = array();
        $r = new \ReflectionClass($this);
        foreach ($r->getMethods() as $method) {
            if (preg_match('/^get(.+)Service$/', $method->name, $match)) {
                $ids[] = self::underscore($match[1]);
            }
        }

        return array_unique(array_merge($ids, array_keys($this->services)));
    }

    /**
     * This is called when you enter a scope
     *
     * @param string $name
     *
     * @throws RuntimeException         When the parent scope is inactive
     * @throws InvalidArgumentException When the scope does not exist
     *
     * @api
     */
    public function enterScope($name)
    {
        if (!isset($this->scopes[$name])) {
            throw new InvalidArgumentException(sprintf('The scope "%s" does not exist.', $name));
        }

        if (self::SCOPE_CONTAINER !== $this->scopes[$name] && !isset($this->scopedServices[$this->scopes[$name]])) {
            throw new RuntimeException(sprintf('The parent scope "%s" must be active when entering this scope.', $this->scopes[$name]));
        }

        // check if a scope of this name is already active, if so we need to
        // remove all services of this scope, and those of any of its child
        // scopes from the global services map
        if (isset($this->scopedServices[$name])) {
            $services = array($this->services, $name => $this->scopedServices[$name]);
            unset($this->scopedServices[$name]);

            foreach ($this->scopeChildren[$name] as $child) {
                if (isset($this->scopedServices[$child])) {
                    $services[$child] = $this->scopedServices[$child];
                    unset($this->scopedServices[$child]);
                }
            }

            // update global map
            $this->services = call_user_func_array('array_diff_key', $services);
            array_shift($services);

            // add stack entry for this scope so we can restore the removed services later
            if (!isset($this->scopeStacks[$name])) {
                $this->scopeStacks[$name] = new \SplStack();
            }
            $this->scopeStacks[$name]->push($services);
        }

        $this->scopedServices[$name] = array();
    }

    /**
     * This is called to leave the current scope, and move back to the parent
     * scope.
     *
     * @param string $name The name of the scope to leave
     *
     * @throws InvalidArgumentException if the scope is not active
     *
     * @api
     */
    public function leaveScope($name)
    {
        if (!isset($this->scopedServices[$name])) {
            throw new InvalidArgumentException(sprintf('The scope "%s" is not active.', $name));
        }

        // remove all services of this scope, or any of its child scopes from
        // the global service map
        $services = array($this->services, $this->scopedServices[$name]);
        unset($this->scopedServices[$name]);
        foreach ($this->scopeChildren[$name] as $child) {
            if (!isset($this->scopedServices[$child])) {
                continue;
            }

            $services[] = $this->scopedServices[$child];
            unset($this->scopedServices[$child]);
        }
        $this->services = call_user_func_array('array_diff_key', $services);

        // check if we need to restore services of a previous scope of this type
        if (isset($this->scopeStacks[$name]) && count($this->scopeStacks[$name]) > 0) {
            $services = $this->scopeStacks[$name]->pop();
            $this->scopedServices += $services;

            foreach ($services as $array) {
                foreach ($array as $id => $service) {
                    $this->set($id, $service, $name);
                }
            }
        }
    }

    /**
     * Adds a scope to the container.
     *
     * @param ScopeInterface $scope
     *
     * @throws InvalidArgumentException
     *
     * @api
     */
    public function addScope(ScopeInterface $scope)
    {
        $name = $scope->getName();
        $parentScope = $scope->getParentName();

        if (self::SCOPE_CONTAINER === $name || self::SCOPE_PROTOTYPE === $name) {
            throw new InvalidArgumentException(sprintf('The scope "%s" is reserved.', $name));
        }
        if (isset($this->scopes[$name])) {
            throw new InvalidArgumentException(sprintf('A scope with name "%s" already exists.', $name));
        }
        if (self::SCOPE_CONTAINER !== $parentScope && !isset($this->scopes[$parentScope])) {
            throw new InvalidArgumentException(sprintf('The parent scope "%s" does not exist, or is invalid.', $parentScope));
        }

        $this->scopes[$name] = $parentScope;
        $this->scopeChildren[$name] = array();

        // normalize the child relations
        while ($parentScope !== self::SCOPE_CONTAINER) {
            $this->scopeChildren[$parentScope][] = $name;
            $parentScope = $this->scopes[$parentScope];
        }
    }

    /**
     * Returns whether this container has a certain scope
     *
     * @param string $name The name of the scope
     *
     * @return Boolean
     *
     * @api
     */
    public function hasScope($name)
    {
        return isset($this->scopes[$name]);
    }

    /**
     * Returns whether this scope is currently active
     *
     * This does not actually check if the passed scope actually exists.
     *
     * @param string $name
     *
     * @return Boolean
     *
     * @api
     */
    public function isScopeActive($name)
    {
        return isset($this->scopedServices[$name]);
    }

    /**
     * Camelizes a string.
     *
     * @param string $id A string to camelize
     *
     * @return string The camelized string
     */
    public static function camelize($id)
    {
        return strtr(ucwords(strtr($id, array('_' => ' ', '.' => '_ ', '\\' => '_ '))), array(' ' => ''));
    }

    /**
     * A string to underscore.
     *
     * @param string $id The string to underscore
     *
     * @return string The underscored string
     */
    public static function underscore($id)
    {
        return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), strtr($id, '_', '.')));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage;

/**
 * Adds some function to the default ExpressionLanguage.
 *
 * To get a service, use service('request').
 * To get a parameter, use parameter('kernel.debug').
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ExpressionLanguage extends BaseExpressionLanguage
{
    protected function registerFunctions()
    {
        parent::registerFunctions();

        $this->register('service', function ($arg) {
            return sprintf('$this->get(%s)', $arg);
        }, function (array $variables, $value) {
            return $variables['container']->get($value);
        });

        $this->register('parameter', function ($arg) {
            return sprintf('$this->getParameter(%s)', $arg);
        }, function (array $variables, $value) {
            return $variables['container']->getParameter($value);
        });
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

use Symfony\Component\DependencyInjection\Compiler\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use Symfony\Component\DependencyInjection\Exception\BadMethodCallException;
use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Config\Resource\ResourceInterface;
use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface;
use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator;
use Symfony\Component\DependencyInjection\ExpressionLanguage;
use Symfony\Component\ExpressionLanguage\Expression;

/**
 * ContainerBuilder is a DI container that provides an API to easily describe services.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class ContainerBuilder extends Container implements TaggedContainerInterface
{
    /**
     * @var ExtensionInterface[]
     */
    private $extensions = array();

    /**
     * @var ExtensionInterface[]
     */
    private $extensionsByNs = array();

    /**
     * @var Definition[]
     */
    private $definitions = array();

    /**
     * @var Definition[]
     */
    private $obsoleteDefinitions = array();

    /**
     * @var Alias[]
     */
    private $aliasDefinitions = array();

    /**
     * @var ResourceInterface[]
     */
    private $resources = array();

    private $extensionConfigs = array();

    /**
     * @var Compiler
     */
    private $compiler;

    private $trackResources = true;

    /**
     * @var InstantiatorInterface|null
     */
    private $proxyInstantiator;

    /**
     * @var ExpressionLanguage|null
     */
    private $expressionLanguage;

    /**
     * Sets the track resources flag.
     *
     * If you are not using the loaders and therefore don't want
     * to depend on the Config component, set this flag to false.
     *
     * @param Boolean $track true if you want to track resources, false otherwise
     */
    public function setResourceTracking($track)
    {
        $this->trackResources = (Boolean) $track;
    }

    /**
     * Checks if resources are tracked.
     *
     * @return Boolean true if resources are tracked, false otherwise
     */
    public function isTrackingResources()
    {
        return $this->trackResources;
    }

    /**
     * Sets the instantiator to be used when fetching proxies.
     *
     * @param InstantiatorInterface $proxyInstantiator
     */
    public function setProxyInstantiator(InstantiatorInterface $proxyInstantiator)
    {
        $this->proxyInstantiator = $proxyInstantiator;
    }

    /**
     * Registers an extension.
     *
     * @param ExtensionInterface $extension An extension instance
     *
     * @api
     */
    public function registerExtension(ExtensionInterface $extension)
    {
        $this->extensions[$extension->getAlias()] = $extension;

        if (false !== $extension->getNamespace()) {
            $this->extensionsByNs[$extension->getNamespace()] = $extension;
        }
    }

    /**
     * Returns an extension by alias or namespace.
     *
     * @param string $name An alias or a namespace
     *
     * @return ExtensionInterface An extension instance
     *
     * @throws LogicException if the extension is not registered
     *
     * @api
     */
    public function getExtension($name)
    {
        if (isset($this->extensions[$name])) {
            return $this->extensions[$name];
        }

        if (isset($this->extensionsByNs[$name])) {
            return $this->extensionsByNs[$name];
        }

        throw new LogicException(sprintf('Container extension "%s" is not registered', $name));
    }

    /**
     * Returns all registered extensions.
     *
     * @return ExtensionInterface[] An array of ExtensionInterface
     *
     * @api
     */
    public function getExtensions()
    {
        return $this->extensions;
    }

    /**
     * Checks if we have an extension.
     *
     * @param string $name The name of the extension
     *
     * @return Boolean If the extension exists
     *
     * @api
     */
    public function hasExtension($name)
    {
        return isset($this->extensions[$name]) || isset($this->extensionsByNs[$name]);
    }

    /**
     * Returns an array of resources loaded to build this configuration.
     *
     * @return ResourceInterface[] An array of resources
     *
     * @api
     */
    public function getResources()
    {
        return array_unique($this->resources);
    }

    /**
     * Adds a resource for this configuration.
     *
     * @param ResourceInterface $resource A resource instance
     *
     * @return ContainerBuilder The current instance
     *
     * @api
     */
    public function addResource(ResourceInterface $resource)
    {
        if (!$this->trackResources) {
            return $this;
        }

        $this->resources[] = $resource;

        return $this;
    }

    /**
     * Sets the resources for this configuration.
     *
     * @param ResourceInterface[] $resources An array of resources
     *
     * @return ContainerBuilder The current instance
     *
     * @api
     */
    public function setResources(array $resources)
    {
        if (!$this->trackResources) {
            return $this;
        }

        $this->resources = $resources;

        return $this;
    }

    /**
     * Adds the object class hierarchy as resources.
     *
     * @param object $object An object instance
     *
     * @return ContainerBuilder The current instance
     *
     * @api
     */
    public function addObjectResource($object)
    {
        if ($this->trackResources) {
            $this->addClassResource(new \ReflectionClass($object));
        }

        return $this;
    }

    /**
     * Adds the given class hierarchy as resources.
     *
     * @param \ReflectionClass $class
     *
     * @return ContainerBuilder The current instance
     */
    public function addClassResource(\ReflectionClass $class)
    {
        if (!$this->trackResources) {
            return $this;
        }

        do {
            $this->addResource(new FileResource($class->getFileName()));
        } while ($class = $class->getParentClass());

        return $this;
    }

    /**
     * Loads the configuration for an extension.
     *
     * @param string $extension The extension alias or namespace
     * @param array  $values    An array of values that customizes the extension
     *
     * @return ContainerBuilder The current instance
     * @throws BadMethodCallException When this ContainerBuilder is frozen
     *
     * @throws \LogicException if the container is frozen
     *
     * @api
     */
    public function loadFromExtension($extension, array $values = array())
    {
        if ($this->isFrozen()) {
            throw new BadMethodCallException('Cannot load from an extension on a frozen container.');
        }

        $namespace = $this->getExtension($extension)->getAlias();

        $this->extensionConfigs[$namespace][] = $values;

        return $this;
    }

    /**
     * Adds a compiler pass.
     *
     * @param CompilerPassInterface $pass A compiler pass
     * @param string                $type The type of compiler pass
     *
     * @return ContainerBuilder The current instance
     *
     * @api
     */
    public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION)
    {
        $this->getCompiler()->addPass($pass, $type);

        $this->addObjectResource($pass);

        return $this;
    }

    /**
     * Returns the compiler pass config which can then be modified.
     *
     * @return PassConfig The compiler pass config
     *
     * @api
     */
    public function getCompilerPassConfig()
    {
        return $this->getCompiler()->getPassConfig();
    }

    /**
     * Returns the compiler.
     *
     * @return Compiler The compiler
     *
     * @api
     */
    public function getCompiler()
    {
        if (null === $this->compiler) {
            $this->compiler = new Compiler();
        }

        return $this->compiler;
    }

    /**
     * Returns all Scopes.
     *
     * @return array An array of scopes
     *
     * @api
     */
    public function getScopes()
    {
        return $this->scopes;
    }

    /**
     * Returns all Scope children.
     *
     * @return array An array of scope children.
     *
     * @api
     */
    public function getScopeChildren()
    {
        return $this->scopeChildren;
    }

    /**
     * Sets a service.
     *
     * @param string $id      The service identifier
     * @param object $service The service instance
     * @param string $scope   The scope
     *
     * @throws BadMethodCallException When this ContainerBuilder is frozen
     *
     * @api
     */
    public function set($id, $service, $scope = self::SCOPE_CONTAINER)
    {
        $id = strtolower($id);

        if ($this->isFrozen()) {
            // setting a synthetic service on a frozen container is alright
            if (
                (!isset($this->definitions[$id]) && !isset($this->obsoleteDefinitions[$id]))
                    ||
                (isset($this->definitions[$id]) && !$this->definitions[$id]->isSynthetic())
                    ||
                (isset($this->obsoleteDefinitions[$id]) && !$this->obsoleteDefinitions[$id]->isSynthetic())
            ) {
                throw new BadMethodCallException(sprintf('Setting service "%s" on a frozen container is not allowed.', $id));
            }
        }

        if (isset($this->definitions[$id])) {
            $this->obsoleteDefinitions[$id] = $this->definitions[$id];
        }

        unset($this->definitions[$id], $this->aliasDefinitions[$id]);

        parent::set($id, $service, $scope);

        if (isset($this->obsoleteDefinitions[$id]) && $this->obsoleteDefinitions[$id]->isSynchronized()) {
            $this->synchronize($id);
        }
    }

    /**
     * Removes a service definition.
     *
     * @param string $id The service identifier
     *
     * @api
     */
    public function removeDefinition($id)
    {
        unset($this->definitions[strtolower($id)]);
    }

    /**
     * Returns true if the given service is defined.
     *
     * @param string $id The service identifier
     *
     * @return Boolean true if the service is defined, false otherwise
     *
     * @api
     */
    public function has($id)
    {
        $id = strtolower($id);

        return isset($this->definitions[$id]) || isset($this->aliasDefinitions[$id]) || parent::has($id);
    }

    /**
     * Gets a service.
     *
     * @param string  $id              The service identifier
     * @param integer $invalidBehavior The behavior when the service does not exist
     *
     * @return object The associated service
     *
     * @throws InvalidArgumentException when no definitions are available
     * @throws InactiveScopeException   when the current scope is not active
     * @throws LogicException           when a circular dependency is detected
     * @throws \Exception
     *
     * @see Reference
     *
     * @api
     */
    public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE)
    {
        $id = strtolower($id);

        try {
            return parent::get($id, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE);
        } catch (InactiveScopeException $e) {
            if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
                return null;
            }

            throw $e;
        } catch (InvalidArgumentException $e) {
            if (isset($this->loading[$id])) {
                throw new LogicException(sprintf('The service "%s" has a circular reference to itself.', $id), 0, $e);
            }

            if (!$this->hasDefinition($id) && isset($this->aliasDefinitions[$id])) {
                return $this->get($this->aliasDefinitions[$id]);
            }

            try {
                $definition = $this->getDefinition($id);
            } catch (InvalidArgumentException $e) {
                if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
                    return null;
                }

                throw $e;
            }

            $this->loading[$id] = true;

            try {
                $service = $this->createService($definition, $id);
            } catch (\Exception $e) {
                unset($this->loading[$id]);

                if ($e instanceof InactiveScopeException && self::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
                    return null;
                }

                throw $e;
            }

            unset($this->loading[$id]);

            return $service;
        }
    }

    /**
     * Merges a ContainerBuilder with the current ContainerBuilder configuration.
     *
     * Service definitions overrides the current defined ones.
     *
     * But for parameters, they are overridden by the current ones. It allows
     * the parameters passed to the container constructor to have precedence
     * over the loaded ones.
     *
     * $container = new ContainerBuilder(array('foo' => 'bar'));
     * $loader = new LoaderXXX($container);
     * $loader->load('resource_name');
     * $container->register('foo', new stdClass());
     *
     * In the above example, even if the loaded resource defines a foo
     * parameter, the value will still be 'bar' as defined in the ContainerBuilder
     * constructor.
     *
     * @param ContainerBuilder $container The ContainerBuilder instance to merge.
     *
     *
     * @throws BadMethodCallException When this ContainerBuilder is frozen
     *
     * @api
     */
    public function merge(ContainerBuilder $container)
    {
        if ($this->isFrozen()) {
            throw new BadMethodCallException('Cannot merge on a frozen container.');
        }

        $this->addDefinitions($container->getDefinitions());
        $this->addAliases($container->getAliases());
        $this->getParameterBag()->add($container->getParameterBag()->all());

        if ($this->trackResources) {
            foreach ($container->getResources() as $resource) {
                $this->addResource($resource);
            }
        }

        foreach ($this->extensions as $name => $extension) {
            if (!isset($this->extensionConfigs[$name])) {
                $this->extensionConfigs[$name] = array();
            }

            $this->extensionConfigs[$name] = array_merge($this->extensionConfigs[$name], $container->getExtensionConfig($name));
        }
    }

    /**
     * Returns the configuration array for the given extension.
     *
     * @param string $name The name of the extension
     *
     * @return array An array of configuration
     *
     * @api
     */
    public function getExtensionConfig($name)
    {
        if (!isset($this->extensionConfigs[$name])) {
            $this->extensionConfigs[$name] = array();
        }

        return $this->extensionConfigs[$name];
    }

    /**
     * Prepends a config array to the configs of the given extension.
     *
     * @param string $name    The name of the extension
     * @param array  $config  The config to set
     */
    public function prependExtensionConfig($name, array $config)
    {
        if (!isset($this->extensionConfigs[$name])) {
            $this->extensionConfigs[$name] = array();
        }

        array_unshift($this->extensionConfigs[$name], $config);
    }

    /**
     * Compiles the container.
     *
     * This method passes the container to compiler
     * passes whose job is to manipulate and optimize
     * the container.
     *
     * The main compiler passes roughly do four things:
     *
     *  * The extension configurations are merged;
     *  * Parameter values are resolved;
     *  * The parameter bag is frozen;
     *  * Extension loading is disabled.
     *
     * @api
     */
    public function compile()
    {
        $compiler = $this->getCompiler();

        if ($this->trackResources) {
            foreach ($compiler->getPassConfig()->getPasses() as $pass) {
                $this->addObjectResource($pass);
            }
        }

        $compiler->compile($this);

        if ($this->trackResources) {
            foreach ($this->definitions as $definition) {
                if ($definition->isLazy() && ($class = $definition->getClass()) && class_exists($class)) {
                    $this->addClassResource(new \ReflectionClass($class));
                }
            }
        }

        $this->extensionConfigs = array();

        parent::compile();
    }

    /**
     * Gets all service ids.
     *
     * @return array An array of all defined service ids
     */
    public function getServiceIds()
    {
        return array_unique(array_merge(array_keys($this->getDefinitions()), array_keys($this->aliasDefinitions), parent::getServiceIds()));
    }

    /**
     * Adds the service aliases.
     *
     * @param array $aliases An array of aliases
     *
     * @api
     */
    public function addAliases(array $aliases)
    {
        foreach ($aliases as $alias => $id) {
            $this->setAlias($alias, $id);
        }
    }

    /**
     * Sets the service aliases.
     *
     * @param array $aliases An array of aliases
     *
     * @api
     */
    public function setAliases(array $aliases)
    {
        $this->aliasDefinitions = array();
        $this->addAliases($aliases);
    }

    /**
     * Sets an alias for an existing service.
     *
     * @param string        $alias The alias to create
     * @param string|Alias  $id    The service to alias
     *
     * @throws InvalidArgumentException if the id is not a string or an Alias
     * @throws InvalidArgumentException if the alias is for itself
     *
     * @api
     */
    public function setAlias($alias, $id)
    {
        $alias = strtolower($alias);

        if (is_string($id)) {
            $id = new Alias($id);
        } elseif (!$id instanceof Alias) {
            throw new InvalidArgumentException('$id must be a string, or an Alias object.');
        }

        if ($alias === strtolower($id)) {
            throw new InvalidArgumentException(sprintf('An alias can not reference itself, got a circular reference on "%s".', $alias));
        }

        unset($this->definitions[$alias]);

        $this->aliasDefinitions[$alias] = $id;
    }

    /**
     * Removes an alias.
     *
     * @param string $alias The alias to remove
     *
     * @api
     */
    public function removeAlias($alias)
    {
        unset($this->aliasDefinitions[strtolower($alias)]);
    }

    /**
     * Returns true if an alias exists under the given identifier.
     *
     * @param string $id The service identifier
     *
     * @return Boolean true if the alias exists, false otherwise
     *
     * @api
     */
    public function hasAlias($id)
    {
        return isset($this->aliasDefinitions[strtolower($id)]);
    }

    /**
     * Gets all defined aliases.
     *
     * @return Alias[] An array of aliases
     *
     * @api
     */
    public function getAliases()
    {
        return $this->aliasDefinitions;
    }

    /**
     * Gets an alias.
     *
     * @param string $id The service identifier
     *
     * @return Alias An Alias instance
     *
     * @throws InvalidArgumentException if the alias does not exist
     *
     * @api
     */
    public function getAlias($id)
    {
        $id = strtolower($id);

        if (!$this->hasAlias($id)) {
            throw new InvalidArgumentException(sprintf('The service alias "%s" does not exist.', $id));
        }

        return $this->aliasDefinitions[$id];
    }

    /**
     * Registers a service definition.
     *
     * This methods allows for simple registration of service definition
     * with a fluid interface.
     *
     * @param string $id    The service identifier
     * @param string $class The service class
     *
     * @return Definition A Definition instance
     *
     * @api
     */
    public function register($id, $class = null)
    {
        return $this->setDefinition(strtolower($id), new Definition($class));
    }

    /**
     * Adds the service definitions.
     *
     * @param Definition[] $definitions An array of service definitions
     *
     * @api
     */
    public function addDefinitions(array $definitions)
    {
        foreach ($definitions as $id => $definition) {
            $this->setDefinition($id, $definition);
        }
    }

    /**
     * Sets the service definitions.
     *
     * @param Definition[] $definitions An array of service definitions
     *
     * @api
     */
    public function setDefinitions(array $definitions)
    {
        $this->definitions = array();
        $this->addDefinitions($definitions);
    }

    /**
     * Gets all service definitions.
     *
     * @return Definition[] An array of Definition instances
     *
     * @api
     */
    public function getDefinitions()
    {
        return $this->definitions;
    }

    /**
     * Sets a service definition.
     *
     * @param string     $id         The service identifier
     * @param Definition $definition A Definition instance
     *
     * @return Definition the service definition
     *
     * @throws BadMethodCallException When this ContainerBuilder is frozen
     *
     * @api
     */
    public function setDefinition($id, Definition $definition)
    {
        if ($this->isFrozen()) {
            throw new BadMethodCallException('Adding definition to a frozen container is not allowed');
        }

        $id = strtolower($id);

        unset($this->aliasDefinitions[$id]);

        return $this->definitions[$id] = $definition;
    }

    /**
     * Returns true if a service definition exists under the given identifier.
     *
     * @param string $id The service identifier
     *
     * @return Boolean true if the service definition exists, false otherwise
     *
     * @api
     */
    public function hasDefinition($id)
    {
        return array_key_exists(strtolower($id), $this->definitions);
    }

    /**
     * Gets a service definition.
     *
     * @param string $id The service identifier
     *
     * @return Definition A Definition instance
     *
     * @throws InvalidArgumentException if the service definition does not exist
     *
     * @api
     */
    public function getDefinition($id)
    {
        $id = strtolower($id);

        if (!$this->hasDefinition($id)) {
            throw new InvalidArgumentException(sprintf('The service definition "%s" does not exist.', $id));
        }

        return $this->definitions[$id];
    }

    /**
     * Gets a service definition by id or alias.
     *
     * The method "unaliases" recursively to return a Definition instance.
     *
     * @param string $id The service identifier or alias
     *
     * @return Definition A Definition instance
     *
     * @throws InvalidArgumentException if the service definition does not exist
     *
     * @api
     */
    public function findDefinition($id)
    {
        while ($this->hasAlias($id)) {
            $id = (string) $this->getAlias($id);
        }

        return $this->getDefinition($id);
    }

    /**
     * Creates a service for a service definition.
     *
     * @param Definition $definition A service definition instance
     * @param string     $id         The service identifier
     * @param Boolean    $tryProxy   Whether to try proxying the service with a lazy proxy
     *
     * @return object The service described by the service definition
     *
     * @throws RuntimeException When the scope is inactive
     * @throws RuntimeException When the factory definition is incomplete
     * @throws RuntimeException When the service is a synthetic service
     * @throws InvalidArgumentException When configure callable is not callable
     *
     * @internal this method is public because of PHP 5.3 limitations, do not use it explicitly in your code
     */
    public function createService(Definition $definition, $id, $tryProxy = true)
    {
        if ($definition->isSynthetic()) {
            throw new RuntimeException(sprintf('You have requested a synthetic service ("%s"). The DIC does not know how to construct this service.', $id));
        }

        if ($tryProxy && $definition->isLazy()) {
            $container = $this;

            $proxy = $this
                ->getProxyInstantiator()
                ->instantiateProxy(
                    $container,
                    $definition,
                    $id, function () use ($definition, $id, $container) {
                        return $container->createService($definition, $id, false);
                    }
                );
            $this->shareService($definition, $proxy, $id);

            return $proxy;
        }

        $parameterBag = $this->getParameterBag();

        if (null !== $definition->getFile()) {
            require_once $parameterBag->resolveValue($definition->getFile());
        }

        $arguments = $this->resolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments())));

        if (null !== $definition->getFactoryMethod()) {
            if (null !== $definition->getFactoryClass()) {
                $factory = $parameterBag->resolveValue($definition->getFactoryClass());
            } elseif (null !== $definition->getFactoryService()) {
                $factory = $this->get($parameterBag->resolveValue($definition->getFactoryService()));
            } else {
                throw new RuntimeException(sprintf('Cannot create service "%s" from factory method without a factory service or factory class.', $id));
            }

            $service = call_user_func_array(array($factory, $definition->getFactoryMethod()), $arguments);
        } else {
            $r = new \ReflectionClass($parameterBag->resolveValue($definition->getClass()));

            $service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs($arguments);
        }

        if ($tryProxy || !$definition->isLazy()) {
            // share only if proxying failed, or if not a proxy
            $this->shareService($definition, $service, $id);
        }

        foreach ($definition->getMethodCalls() as $call) {
            $this->callMethod($service, $call);
        }

        $properties = $this->resolveServices($parameterBag->resolveValue($definition->getProperties()));
        foreach ($properties as $name => $value) {
            $service->$name = $value;
        }

        if ($callable = $definition->getConfigurator()) {
            if (is_array($callable)) {
                $callable[0] = $callable[0] instanceof Reference ? $this->get((string) $callable[0]) : $parameterBag->resolveValue($callable[0]);
            }

            if (!is_callable($callable)) {
                throw new InvalidArgumentException(sprintf('The configure callable for class "%s" is not a callable.', get_class($service)));
            }

            call_user_func($callable, $service);
        }

        return $service;
    }

    /**
     * Replaces service references by the real service instance and evaluates expressions.
     *
     * @param mixed $value A value
     *
     * @return mixed The same value with all service references replaced by
     *               the real service instances and all expressions evaluated
     */
    public function resolveServices($value)
    {
        if (is_array($value)) {
            foreach ($value as &$v) {
                $v = $this->resolveServices($v);
            }
        } elseif ($value instanceof Reference) {
            $value = $this->get((string) $value, $value->getInvalidBehavior());
        } elseif ($value instanceof Definition) {
            $value = $this->createService($value, null);
        } elseif ($value instanceof Expression) {
            $value = $this->getExpressionLanguage()->evaluate($value, array('container' => $this));
        }

        return $value;
    }

    /**
     * Returns service ids for a given tag.
     *
     * Example:
     *
     * $container->register('foo')->addTag('my.tag', array('hello' => 'world'));
     *
     * $serviceIds = $container->findTaggedServiceIds('my.tag');
     * foreach ($serviceIds as $serviceId => $tags) {
     *     foreach ($tags as $tag) {
     *         echo $tag['hello'];
     *     }
     * }
     *
     * @param string $name The tag name
     *
     * @return array An array of tags with the tagged service as key, holding a list of attribute arrays.
     *
     * @api
     */
    public function findTaggedServiceIds($name)
    {
        $tags = array();
        foreach ($this->getDefinitions() as $id => $definition) {
            if ($definition->hasTag($name)) {
                $tags[$id] = $definition->getTag($name);
            }
        }

        return $tags;
    }

    /**
     * Returns all tags the defined services use.
     *
     * @return array An array of tags
     */
    public function findTags()
    {
        $tags = array();
        foreach ($this->getDefinitions() as $id => $definition) {
            $tags = array_merge(array_keys($definition->getTags()), $tags);
        }

        return array_unique($tags);
    }

    /**
     * Returns the Service Conditionals.
     *
     * @param mixed $value An array of conditionals to return.
     *
     * @return array An array of Service conditionals
     */
    public static function getServiceConditionals($value)
    {
        $services = array();

        if (is_array($value)) {
            foreach ($value as $v) {
                $services = array_unique(array_merge($services, self::getServiceConditionals($v)));
            }
        } elseif ($value instanceof Reference && $value->getInvalidBehavior() === ContainerInterface::IGNORE_ON_INVALID_REFERENCE) {
            $services[] = (string) $value;
        }

        return $services;
    }

    /**
     * Retrieves the currently set proxy instantiator or instantiates one.
     *
     * @return InstantiatorInterface
     */
    private function getProxyInstantiator()
    {
        if (!$this->proxyInstantiator) {
            $this->proxyInstantiator = new RealServiceInstantiator();
        }

        return $this->proxyInstantiator;
    }

    /**
     * Synchronizes a service change.
     *
     * This method updates all services that depend on the given
     * service by calling all methods referencing it.
     *
     * @param string $id A service id
     */
    private function synchronize($id)
    {
        foreach ($this->definitions as $definitionId => $definition) {
            // only check initialized services
            if (!$this->initialized($definitionId)) {
                continue;
            }

            foreach ($definition->getMethodCalls() as $call) {
                foreach ($call[1] as $argument) {
                    if ($argument instanceof Reference && $id == (string) $argument) {
                        $this->callMethod($this->get($definitionId), $call);
                    }
                }
            }
        }
    }

    private function callMethod($service, $call)
    {
        $services = self::getServiceConditionals($call[1]);

        foreach ($services as $s) {
            if (!$this->has($s)) {
                return;
            }
        }

        call_user_func_array(array($service, $call[0]), $this->resolveServices($this->getParameterBag()->resolveValue($call[1])));
    }

    /**
     * Shares a given service in the container
     *
     * @param Definition $definition
     * @param mixed      $service
     * @param string     $id
     *
     * @throws InactiveScopeException
     */
    private function shareService(Definition $definition, $service, $id)
    {
        if (self::SCOPE_PROTOTYPE !== $scope = $definition->getScope()) {
            if (self::SCOPE_CONTAINER !== $scope && !isset($this->scopedServices[$scope])) {
                throw new InactiveScopeException($id, $scope);
            }

            $this->services[$lowerId = strtolower($id)] = $service;

            if (self::SCOPE_CONTAINER !== $scope) {
                $this->scopedServices[$scope][$lowerId] = $service;
            }
        }
    }

    private function getExpressionLanguage()
    {
        if (null === $this->expressionLanguage) {
            if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
                throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
            }
            $this->expressionLanguage = new ExpressionLanguage();
        }

        return $this->expressionLanguage;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;

/**
 * ContainerInterface is the interface implemented by service container classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @api
 */
interface ContainerInterface
{
    const EXCEPTION_ON_INVALID_REFERENCE = 1;
    const NULL_ON_INVALID_REFERENCE      = 2;
    const IGNORE_ON_INVALID_REFERENCE    = 3;
    const SCOPE_CONTAINER                = 'container';
    const SCOPE_PROTOTYPE                = 'prototype';

    /**
     * Sets a service.
     *
     * @param string $id      The service identifier
     * @param object $service The service instance
     * @param string $scope   The scope of the service
     *
     * @api
     */
    public function set($id, $service, $scope = self::SCOPE_CONTAINER);

    /**
     * Gets a service.
     *
     * @param string $id              The service identifier
     * @param int    $invalidBehavior The behavior when the service does not exist
     *
     * @return object The associated service
     *
     * @throws InvalidArgumentException if the service is not defined
     * @throws ServiceCircularReferenceException When a circular reference is detected
     * @throws ServiceNotFoundException When the service is not defined
     *
     * @see Reference
     *
     * @api
     */
    public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE);

    /**
     * Returns true if the given service is defined.
     *
     * @param string $id The service identifier
     *
     * @return Boolean true if the service is defined, false otherwise
     *
     * @api
     */
    public function has($id);

    /**
     * Gets a parameter.
     *
     * @param string $name The parameter name
     *
     * @return mixed  The parameter value
     *
     * @throws InvalidArgumentException if the parameter is not defined
     *
     * @api
     */
    public function getParameter($name);

    /**
     * Checks if a parameter exists.
     *
     * @param string $name The parameter name
     *
     * @return Boolean The presence of parameter in container
     *
     * @api
     */
    public function hasParameter($name);

    /**
     * Sets a parameter.
     *
     * @param string $name  The parameter name
     * @param mixed  $value The parameter value
     *
     * @api
     */
    public function setParameter($name, $value);

    /**
     * Enters the given scope
     *
     * @param string $name
     *
     * @api
     */
    public function enterScope($name);

    /**
     * Leaves the current scope, and re-enters the parent scope
     *
     * @param string $name
     *
     * @api
     */
    public function leaveScope($name);

    /**
     * Adds a scope to the container
     *
     * @param ScopeInterface $scope
     *
     * @api
     */
    public function addScope(ScopeInterface $scope);

    /**
     * Whether this container has the given scope
     *
     * @param string $name
     *
     * @return Boolean
     *
     * @api
     */
    public function hasScope($name);

    /**
     * Determines whether the given scope is currently active.
     *
     * It does however not check if the scope actually exists.
     *
     * @param string $name
     *
     * @return Boolean
     *
     * @api
     */
    public function isScopeActive($name);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

/**
 * A simple implementation of ContainerAwareInterface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
abstract class ContainerAware implements ContainerAwareInterface
{
    /**
     * @var ContainerInterface
     *
     * @api
     */
    protected $container;

    /**
     * Sets the Container associated with this Controller.
     *
     * @param ContainerInterface $container A ContainerInterface instance
     *
     * @api
     */
    public function setContainer(ContainerInterface $container = null)
    {
        $this->container = $container;
    }
}
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony DependencyInjection Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Resources</directory>
                <directory>./Tests</directory>
                <directory>./vendor</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Loader;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\Loader\FileLoader as BaseFileLoader;
use Symfony\Component\Config\FileLocatorInterface;

/**
 * FileLoader is the abstract class used by all built-in loaders that are file based.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class FileLoader extends BaseFileLoader
{
    protected $container;

    /**
     * Constructor.
     *
     * @param ContainerBuilder $container A ContainerBuilder instance
     * @param FileLocatorInterface      $locator   A FileLocator instance
     */
    public function __construct(ContainerBuilder $container, FileLocatorInterface $locator)
    {
        $this->container = $container;

        parent::__construct($locator);
    }
}
<?xml version="1.0" encoding="UTF-8" ?>

<xsd:schema xmlns="http://symfony.com/schema/dic/services"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema"
     targetNamespace="http://symfony.com/schema/dic/services"
     elementFormDefault="qualified">

  <xsd:annotation>
    <xsd:documentation><![CDATA[
      Symfony XML Services Schema, version 1.0
      Authors: Fabien Potencier

      This defines a way to describe PHP objects (services) and their
      dependencies.
    ]]></xsd:documentation>
  </xsd:annotation>

  <xsd:element name="container" type="container" />

  <xsd:complexType name="container">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        The root element of a service file.
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:sequence>
      <xsd:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="imports" type="imports" minOccurs="0" maxOccurs="1" />
      <xsd:element name="parameters" type="parameters" minOccurs="0" maxOccurs="1" />
      <xsd:element name="services" type="services" minOccurs="0" maxOccurs="1" />
      <xsd:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded" />
    </xsd:sequence>
  </xsd:complexType>

  <xsd:complexType name="services">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        Enclosing element for the definition of all services
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:choice minOccurs="1" maxOccurs="unbounded">
      <xsd:element name="service" type="service" />
    </xsd:choice>
  </xsd:complexType>

  <xsd:complexType name="imports">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        Enclosing element for the import elements
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:choice minOccurs="1" maxOccurs="unbounded">
      <xsd:element name="import" type="import" />
    </xsd:choice>
  </xsd:complexType>

  <xsd:complexType name="import">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        Import an external resource defining other services or parameters
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:attribute name="resource" type="xsd:string" use="required" />
    <xsd:attribute name="ignore-errors" type="boolean" />
  </xsd:complexType>

  <xsd:complexType name="configurator">
    <xsd:attribute name="id" type="xsd:string" />
    <xsd:attribute name="service" type="xsd:string" />
    <xsd:attribute name="class" type="xsd:string" />
    <xsd:attribute name="method" type="xsd:string" />
    <xsd:attribute name="function" type="xsd:string" />
  </xsd:complexType>

  <xsd:complexType name="service">
    <xsd:choice maxOccurs="unbounded">
      <xsd:element name="file" type="xsd:string" minOccurs="0" maxOccurs="1" />
      <xsd:element name="argument" type="argument" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="configurator" type="configurator" minOccurs="0" maxOccurs="1" />
      <xsd:element name="call" type="call" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
    </xsd:choice>
    <xsd:attribute name="id" type="xsd:string" />
    <xsd:attribute name="class" type="xsd:string" />
    <xsd:attribute name="scope" type="xsd:string" />
    <xsd:attribute name="public" type="boolean" />
    <xsd:attribute name="synthetic" type="boolean" />
    <xsd:attribute name="synchronized" type="boolean" />
    <xsd:attribute name="lazy" type="boolean" />
    <xsd:attribute name="abstract" type="boolean" />
    <xsd:attribute name="factory-class" type="xsd:string" />
    <xsd:attribute name="factory-method" type="xsd:string" />
    <xsd:attribute name="factory-service" type="xsd:string" />
    <xsd:attribute name="alias" type="xsd:string" />
    <xsd:attribute name="parent" type="xsd:string" />
  </xsd:complexType>

  <xsd:complexType name="tag">
    <xsd:attribute name="name" type="xsd:string" />
    <xsd:anyAttribute namespace="##any" processContents="lax" />
  </xsd:complexType>

  <xsd:complexType name="parameters">
    <xsd:choice minOccurs="1" maxOccurs="unbounded">
      <xsd:element name="parameter" type="parameter" />
    </xsd:choice>
    <xsd:attribute name="type" type="parameter_type" />
    <xsd:attribute name="key" type="xsd:string" />
  </xsd:complexType>

  <xsd:complexType name="parameter" mixed="true">
    <xsd:choice minOccurs="0" maxOccurs="unbounded">
      <xsd:element name="parameter" type="parameter" />
    </xsd:choice>
    <xsd:attribute name="type" type="parameter_type" />
    <xsd:attribute name="id" type="xsd:string" />
    <xsd:attribute name="key" type="xsd:string" />
    <xsd:attribute name="on-invalid" type="invalid_sequence" />
  </xsd:complexType>

  <xsd:complexType name="property" mixed="true">
    <xsd:choice minOccurs="0" maxOccurs="1">
      <xsd:element name="service" type="service" />
    </xsd:choice>
    <xsd:attribute name="type" type="argument_type" />
    <xsd:attribute name="id" type="xsd:string" />
    <xsd:attribute name="name" type="xsd:string" />
    <xsd:attribute name="on-invalid" type="xsd:string" />
    <xsd:attribute name="strict" type="boolean" />
  </xsd:complexType>

  <xsd:complexType name="argument" mixed="true">
    <xsd:choice maxOccurs="unbounded">
      <xsd:element name="argument" type="argument" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="service" type="service" />
    </xsd:choice>
    <xsd:attribute name="type" type="argument_type" />
    <xsd:attribute name="id" type="xsd:string" />
    <xsd:attribute name="key" type="xsd:string" />
    <xsd:attribute name="index" type="xsd:integer" />
    <xsd:attribute name="on-invalid" type="xsd:string" />
    <xsd:attribute name="strict" type="boolean" />
  </xsd:complexType>

  <xsd:complexType name="call" mixed="true">
    <xsd:choice maxOccurs="unbounded">
      <xsd:element name="argument" type="argument" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="service" type="service" />
    </xsd:choice>
    <xsd:attribute name="method" type="xsd:string" />
  </xsd:complexType>

  <xsd:simpleType name="parameter_type">
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="collection" />
      <xsd:enumeration value="service" />
      <xsd:enumeration value="string" />
      <xsd:enumeration value="constant" />
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:simpleType name="argument_type">
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="collection" />
      <xsd:enumeration value="service" />
      <xsd:enumeration value="expression" />
      <xsd:enumeration value="string" />
      <xsd:enumeration value="constant" />
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:simpleType name="invalid_sequence">
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="null" />
      <xsd:enumeration value="ignore" />
      <xsd:enumeration value="exception" />
    </xsd:restriction>
  </xsd:simpleType>

  <xsd:simpleType name="boolean">
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="(%.+%|true|false)" />
    </xsd:restriction>
  </xsd:simpleType>
</xsd:schema>
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Loader;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\Loader\Loader;

/**
 * ClosureLoader loads service definitions from a PHP closure.
 *
 * The Closure has access to the container as its first argument.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ClosureLoader extends Loader
{
    private $container;

    /**
     * Constructor.
     *
     * @param ContainerBuilder $container A ContainerBuilder instance
     */
    public function __construct(ContainerBuilder $container)
    {
        $this->container = $container;
    }

    /**
     * Loads a Closure.
     *
     * @param \Closure $closure The resource
     * @param string   $type    The resource type
     */
    public function load($closure, $type = null)
    {
        call_user_func($closure, $this->container);
    }

    /**
     * Returns true if this class supports the given resource.
     *
     * @param mixed  $resource A resource
     * @param string $type     The resource type
     *
     * @return Boolean true if this class supports the given resource, false otherwise
     */
    public function supports($resource, $type = null)
    {
        return $resource instanceof \Closure;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Loader;

use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;

/**
 * IniFileLoader loads parameters from INI files.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class IniFileLoader extends FileLoader
{
    /**
     * Loads a resource.
     *
     * @param mixed  $file The resource
     * @param string $type The resource type
     *
     * @throws InvalidArgumentException When ini file is not valid
     */
    public function load($file, $type = null)
    {
        $path = $this->locator->locate($file);

        $this->container->addResource(new FileResource($path));

        $result = parse_ini_file($path, true);
        if (false === $result || array() === $result) {
            throw new InvalidArgumentException(sprintf('The "%s" file is not valid.', $file));
        }

        if (isset($result['parameters']) && is_array($result['parameters'])) {
            foreach ($result['parameters'] as $key => $value) {
                $this->container->setParameter($key, $value);
            }
        }
    }

    /**
     * Returns true if this class supports the given resource.
     *
     * @param mixed  $resource A resource
     * @param string $type     The resource type
     *
     * @return Boolean true if this class supports the given resource, false otherwise
     */
    public function supports($resource, $type = null)
    {
        return is_string($resource) && 'ini' === pathinfo($resource, PATHINFO_EXTENSION);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Loader;

use Symfony\Component\Config\Resource\FileResource;

/**
 * PhpFileLoader loads service definitions from a PHP file.
 *
 * The PHP file is required and the $container variable can be
 * used within the file to change the container.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class PhpFileLoader extends FileLoader
{
    /**
     * Loads a PHP file.
     *
     * @param mixed  $file The resource
     * @param string $type The resource type
     */
    public function load($file, $type = null)
    {
        // the container and loader variables are exposed to the included file below
        $container = $this->container;
        $loader = $this;

        $path = $this->locator->locate($file);
        $this->setCurrentDir(dirname($path));
        $this->container->addResource(new FileResource($path));

        include $path;
    }

    /**
     * Returns true if this class supports the given resource.
     *
     * @param mixed  $resource A resource
     * @param string $type     The resource type
     *
     * @return Boolean true if this class supports the given resource, false otherwise
     */
    public function supports($resource, $type = null)
    {
        return is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Loader;

use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Config\Util\XmlUtils;
use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\SimpleXMLElement;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;

/**
 * XmlFileLoader loads XML files service definitions.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class XmlFileLoader extends FileLoader
{
    /**
     * Loads an XML file.
     *
     * @param mixed  $file The resource
     * @param string $type The resource type
     */
    public function load($file, $type = null)
    {
        $path = $this->locator->locate($file);

        $xml = $this->parseFile($path);
        $xml->registerXPathNamespace('container', 'http://symfony.com/schema/dic/services');

        $this->container->addResource(new FileResource($path));

        // anonymous services
        $this->processAnonymousServices($xml, $path);

        // imports
        $this->parseImports($xml, $path);

        // parameters
        $this->parseParameters($xml, $path);

        // extensions
        $this->loadFromExtensions($xml);

        // services
        $this->parseDefinitions($xml, $path);
    }

    /**
     * Returns true if this class supports the given resource.
     *
     * @param mixed  $resource A resource
     * @param string $type     The resource type
     *
     * @return Boolean true if this class supports the given resource, false otherwise
     */
    public function supports($resource, $type = null)
    {
        return is_string($resource) && 'xml' === pathinfo($resource, PATHINFO_EXTENSION);
    }

    /**
     * Parses parameters
     *
     * @param SimpleXMLElement $xml
     * @param string           $file
     */
    private function parseParameters(SimpleXMLElement $xml, $file)
    {
        if (!$xml->parameters) {
            return;
        }

        $this->container->getParameterBag()->add($xml->parameters->getArgumentsAsPhp('parameter'));
    }

    /**
     * Parses imports
     *
     * @param SimpleXMLElement $xml
     * @param string           $file
     */
    private function parseImports(SimpleXMLElement $xml, $file)
    {
        if (false === $imports = $xml->xpath('//container:imports/container:import')) {
            return;
        }

        foreach ($imports as $import) {
            $this->setCurrentDir(dirname($file));
            $this->import((string) $import['resource'], null, (Boolean) $import->getAttributeAsPhp('ignore-errors'), $file);
        }
    }

    /**
     * Parses multiple definitions
     *
     * @param SimpleXMLElement $xml
     * @param string           $file
     */
    private function parseDefinitions(SimpleXMLElement $xml, $file)
    {
        if (false === $services = $xml->xpath('//container:services/container:service')) {
            return;
        }

        foreach ($services as $service) {
            $this->parseDefinition((string) $service['id'], $service, $file);
        }
    }

    /**
     * Parses an individual Definition
     *
     * @param string           $id
     * @param SimpleXMLElement $service
     * @param string           $file
     */
    private function parseDefinition($id, $service, $file)
    {
        if ((string) $service['alias']) {
            $public = true;
            if (isset($service['public'])) {
                $public = $service->getAttributeAsPhp('public');
            }
            $this->container->setAlias($id, new Alias((string) $service['alias'], $public));

            return;
        }

        if (isset($service['parent'])) {
            $definition = new DefinitionDecorator((string) $service['parent']);
        } else {
            $definition = new Definition();
        }

        foreach (array('class', 'scope', 'public', 'factory-class', 'factory-method', 'factory-service', 'synthetic', 'synchronized', 'lazy', 'abstract') as $key) {
            if (isset($service[$key])) {
                $method = 'set'.str_replace('-', '', $key);
                $definition->$method((string) $service->getAttributeAsPhp($key));
            }
        }

        if ($service->file) {
            $definition->setFile((string) $service->file);
        }

        $definition->setArguments($service->getArgumentsAsPhp('argument'));
        $definition->setProperties($service->getArgumentsAsPhp('property'));

        if (isset($service->configurator)) {
            if (isset($service->configurator['function'])) {
                $definition->setConfigurator((string) $service->configurator['function']);
            } else {
                if (isset($service->configurator['service'])) {
                    $class = new Reference((string) $service->configurator['service'], ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false);
                } else {
                    $class = (string) $service->configurator['class'];
                }

                $definition->setConfigurator(array($class, (string) $service->configurator['method']));
            }
        }

        foreach ($service->call as $call) {
            $definition->addMethodCall((string) $call['method'], $call->getArgumentsAsPhp('argument'));
        }

        foreach ($service->tag as $tag) {
            $parameters = array();
            foreach ($tag->attributes() as $name => $value) {
                if ('name' === $name) {
                    continue;
                }

                $parameters[$name] = SimpleXMLElement::phpize($value);
            }

            $definition->addTag((string) $tag['name'], $parameters);
        }

        $this->container->setDefinition($id, $definition);
    }

    /**
     * Parses a XML file.
     *
     * @param string $file Path to a file
     *
     * @return SimpleXMLElement
     *
     * @throws InvalidArgumentException When loading of XML file returns error
     */
    protected function parseFile($file)
    {
        try {
            $dom = XmlUtils::loadFile($file, array($this, 'validateSchema'));
        } catch (\InvalidArgumentException $e) {
            throw new InvalidArgumentException(sprintf('Unable to parse file "%s".', $file), $e->getCode(), $e);
        }

        $this->validateExtensions($dom, $file);

        return simplexml_import_dom($dom, 'Symfony\\Component\\DependencyInjection\\SimpleXMLElement');
    }

    /**
     * Processes anonymous services
     *
     * @param SimpleXMLElement $xml
     * @param string           $file
     */
    private function processAnonymousServices(SimpleXMLElement $xml, $file)
    {
        $definitions = array();
        $count = 0;

        // anonymous services as arguments/properties
        if (false !== $nodes = $xml->xpath('//container:argument[@type="service"][not(@id)]|//container:property[@type="service"][not(@id)]')) {
            foreach ($nodes as $node) {
                // give it a unique name
                $id = sprintf('%s_%d', hash('sha256', $file), ++$count);
                $node['id'] = $id;

                $definitions[$id] = array($node->service, $file, false);
                $node->service['id'] = $id;
            }
        }

        // anonymous services "in the wild"
        if (false !== $nodes = $xml->xpath('//container:services/container:service[not(@id)]')) {
            foreach ($nodes as $node) {
                // give it a unique name
                $id = sprintf('%s_%d', hash('sha256', $file), ++$count);
                $node['id'] = $id;

                $definitions[$id] = array($node, $file, true);
                $node->service['id'] = $id;
            }
        }

        // resolve definitions
        krsort($definitions);
        foreach ($definitions as $id => $def) {
            // anonymous services are always private
            $def[0]['public'] = false;

            $this->parseDefinition($id, $def[0], $def[1]);

            $oNode = dom_import_simplexml($def[0]);
            if (true === $def[2]) {
                $nNode = new \DOMElement('_services');
                $oNode->parentNode->replaceChild($nNode, $oNode);
                $nNode->setAttribute('id', $id);
            } else {
                $oNode->parentNode->removeChild($oNode);
            }
        }
    }

    /**
     * Validates a documents XML schema.
     *
     * @param \DOMDocument $dom
     *
     * @return Boolean
     *
     * @throws RuntimeException When extension references a non-existent XSD file
     */
    public function validateSchema(\DOMDocument $dom)
    {
        $schemaLocations = array('http://symfony.com/schema/dic/services' => str_replace('\\', '/', __DIR__.'/schema/dic/services/services-1.0.xsd'));

        if ($element = $dom->documentElement->getAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'schemaLocation')) {
            $items = preg_split('/\s+/', $element);
            for ($i = 0, $nb = count($items); $i < $nb; $i += 2) {
                if (!$this->container->hasExtension($items[$i])) {
                    continue;
                }

                if (($extension = $this->container->getExtension($items[$i])) && false !== $extension->getXsdValidationBasePath()) {
                    $path = str_replace($extension->getNamespace(), str_replace('\\', '/', $extension->getXsdValidationBasePath()).'/', $items[$i + 1]);

                    if (!is_file($path)) {
                        throw new RuntimeException(sprintf('Extension "%s" references a non-existent XSD file "%s"', get_class($extension), $path));
                    }

                    $schemaLocations[$items[$i]] = $path;
                }
            }
        }

        $tmpfiles = array();
        $imports = '';
        foreach ($schemaLocations as $namespace => $location) {
            $parts = explode('/', $location);
            if (0 === stripos($location, 'phar://')) {
                $tmpfile = tempnam(sys_get_temp_dir(), 'sf2');
                if ($tmpfile) {
                    copy($location, $tmpfile);
                    $tmpfiles[] = $tmpfile;
                    $parts = explode('/', str_replace('\\', '/', $tmpfile));
                }
            }
            $drive = '\\' === DIRECTORY_SEPARATOR ? array_shift($parts).'/' : '';
            $location = 'file:///'.$drive.implode('/', array_map('rawurlencode', $parts));

            $imports .= sprintf('  <xsd:import namespace="%s" schemaLocation="%s" />'."\n", $namespace, $location);
        }

        $source = <<<EOF
<?xml version="1.0" encoding="utf-8" ?>
<xsd:schema xmlns="http://symfony.com/schema"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://symfony.com/schema"
    elementFormDefault="qualified">

    <xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
$imports
</xsd:schema>
EOF
        ;

        $valid = @$dom->schemaValidateSource($source);

        foreach ($tmpfiles as $tmpfile) {
            @unlink($tmpfile);
        }

        return $valid;
    }

    /**
     * Validates an extension.
     *
     * @param \DOMDocument $dom
     * @param string       $file
     *
     * @throws InvalidArgumentException When no extension is found corresponding to a tag
     */
    private function validateExtensions(\DOMDocument $dom, $file)
    {
        foreach ($dom->documentElement->childNodes as $node) {
            if (!$node instanceof \DOMElement || 'http://symfony.com/schema/dic/services' === $node->namespaceURI) {
                continue;
            }

            // can it be handled by an extension?
            if (!$this->container->hasExtension($node->namespaceURI)) {
                $extensionNamespaces = array_filter(array_map(function ($ext) { return $ext->getNamespace(); }, $this->container->getExtensions()));
                throw new InvalidArgumentException(sprintf(
                    'There is no extension able to load the configuration for "%s" (in %s). Looked for namespace "%s", found %s',
                    $node->tagName,
                    $file,
                    $node->namespaceURI,
                    $extensionNamespaces ? sprintf('"%s"', implode('", "', $extensionNamespaces)) : 'none'
                ));
            }
        }
    }

    /**
     * Loads from an extension.
     *
     * @param SimpleXMLElement $xml
     */
    private function loadFromExtensions(SimpleXMLElement $xml)
    {
        foreach (dom_import_simplexml($xml)->childNodes as $node) {
            if (!$node instanceof \DOMElement || $node->namespaceURI === 'http://symfony.com/schema/dic/services') {
                continue;
            }

            $values = static::convertDomElementToArray($node);
            if (!is_array($values)) {
                $values = array();
            }

            $this->container->loadFromExtension($node->namespaceURI, $values);
        }
    }

    /**
     * Converts a \DomElement object to a PHP array.
     *
     * The following rules applies during the conversion:
     *
     *  * Each tag is converted to a key value or an array
     *    if there is more than one "value"
     *
     *  * The content of a tag is set under a "value" key (<foo>bar</foo>)
     *    if the tag also has some nested tags
     *
     *  * The attributes are converted to keys (<foo foo="bar"/>)
     *
     *  * The nested-tags are converted to keys (<foo><foo>bar</foo></foo>)
     *
     * @param \DomElement $element A \DomElement instance
     *
     * @return array A PHP array
     */
    public static function convertDomElementToArray(\DomElement $element)
    {
        return XmlUtils::convertDomElementToArray($element);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Loader;

use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Yaml\Parser as YamlParser;
use Symfony\Component\ExpressionLanguage\Expression;

/**
 * YamlFileLoader loads YAML files service definitions.
 *
 * The YAML format does not support anonymous services (cf. the XML loader).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class YamlFileLoader extends FileLoader
{
    private $yamlParser;

    /**
     * Loads a Yaml file.
     *
     * @param mixed  $file The resource
     * @param string $type The resource type
     */
    public function load($file, $type = null)
    {
        $path = $this->locator->locate($file);

        $content = $this->loadFile($path);

        $this->container->addResource(new FileResource($path));

        // empty file
        if (null === $content) {
            return;
        }

        // imports
        $this->parseImports($content, $file);

        // parameters
        if (isset($content['parameters'])) {
            foreach ($content['parameters'] as $key => $value) {
                $this->container->setParameter($key, $this->resolveServices($value));
            }
        }

        // extensions
        $this->loadFromExtensions($content);

        // services
        $this->parseDefinitions($content, $file);
    }

    /**
     * Returns true if this class supports the given resource.
     *
     * @param mixed  $resource A resource
     * @param string $type     The resource type
     *
     * @return Boolean true if this class supports the given resource, false otherwise
     */
    public function supports($resource, $type = null)
    {
        return is_string($resource) && 'yml' === pathinfo($resource, PATHINFO_EXTENSION);
    }

    /**
     * Parses all imports
     *
     * @param array  $content
     * @param string $file
     */
    private function parseImports($content, $file)
    {
        if (!isset($content['imports'])) {
            return;
        }

        foreach ($content['imports'] as $import) {
            $this->setCurrentDir(dirname($file));
            $this->import($import['resource'], null, isset($import['ignore_errors']) ? (Boolean) $import['ignore_errors'] : false, $file);
        }
    }

    /**
     * Parses definitions
     *
     * @param array  $content
     * @param string $file
     */
    private function parseDefinitions($content, $file)
    {
        if (!isset($content['services'])) {
            return;
        }

        foreach ($content['services'] as $id => $service) {
            $this->parseDefinition($id, $service, $file);
        }
    }

    /**
     * Parses a definition.
     *
     * @param string $id
     * @param array  $service
     * @param string $file
     *
     * @throws InvalidArgumentException When tags are invalid
     */
    private function parseDefinition($id, $service, $file)
    {
        if (is_string($service) && 0 === strpos($service, '@')) {
            $this->container->setAlias($id, substr($service, 1));

            return;
        } elseif (isset($service['alias'])) {
            $public = !array_key_exists('public', $service) || (Boolean) $service['public'];
            $this->container->setAlias($id, new Alias($service['alias'], $public));

            return;
        }

        if (isset($service['parent'])) {
            $definition = new DefinitionDecorator($service['parent']);
        } else {
            $definition = new Definition();
        }

        if (isset($service['class'])) {
            $definition->setClass($service['class']);
        }

        if (isset($service['scope'])) {
            $definition->setScope($service['scope']);
        }

        if (isset($service['synthetic'])) {
            $definition->setSynthetic($service['synthetic']);
        }

        if (isset($service['synchronized'])) {
            $definition->setSynchronized($service['synchronized']);
        }

        if (isset($service['lazy'])) {
            $definition->setLazy($service['lazy']);
        }

        if (isset($service['public'])) {
            $definition->setPublic($service['public']);
        }

        if (isset($service['abstract'])) {
            $definition->setAbstract($service['abstract']);
        }

        if (isset($service['factory_class'])) {
            $definition->setFactoryClass($service['factory_class']);
        }

        if (isset($service['factory_method'])) {
            $definition->setFactoryMethod($service['factory_method']);
        }

        if (isset($service['factory_service'])) {
            $definition->setFactoryService($service['factory_service']);
        }

        if (isset($service['file'])) {
            $definition->setFile($service['file']);
        }

        if (isset($service['arguments'])) {
            $definition->setArguments($this->resolveServices($service['arguments']));
        }

        if (isset($service['properties'])) {
            $definition->setProperties($this->resolveServices($service['properties']));
        }

        if (isset($service['configurator'])) {
            if (is_string($service['configurator'])) {
                $definition->setConfigurator($service['configurator']);
            } else {
                $definition->setConfigurator(array($this->resolveServices($service['configurator'][0]), $service['configurator'][1]));
            }
        }

        if (isset($service['calls'])) {
            foreach ($service['calls'] as $call) {
                $args = isset($call[1]) ? $this->resolveServices($call[1]) : array();
                $definition->addMethodCall($call[0], $args);
            }
        }

        if (isset($service['tags'])) {
            if (!is_array($service['tags'])) {
                throw new InvalidArgumentException(sprintf('Parameter "tags" must be an array for service "%s" in %s.', $id, $file));
            }

            foreach ($service['tags'] as $tag) {
                if (!isset($tag['name'])) {
                    throw new InvalidArgumentException(sprintf('A "tags" entry is missing a "name" key for service "%s" in %s.', $id, $file));
                }

                $name = $tag['name'];
                unset($tag['name']);

                foreach ($tag as $attribute => $value) {
                    if (!is_scalar($value) && null !== $value) {
                        throw new InvalidArgumentException(sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s" in %s.', $id, $name, $attribute, $file));
                    }
                }

                $definition->addTag($name, $tag);
            }
        }

        $this->container->setDefinition($id, $definition);
    }

    /**
     * Loads a YAML file.
     *
     * @param string $file
     *
     * @return array The file content
     */
    protected function loadFile($file)
    {
        if (!stream_is_local($file)) {
            throw new InvalidArgumentException(sprintf('This is not a local file "%s".', $file));
        }

        if (!file_exists($file)) {
            throw new InvalidArgumentException(sprintf('The service file "%s" is not valid.', $file));
        }

        if (null === $this->yamlParser) {
            $this->yamlParser = new YamlParser();
        }

        return $this->validate($this->yamlParser->parse(file_get_contents($file)), $file);
    }

    /**
     * Validates a YAML file.
     *
     * @param mixed  $content
     * @param string $file
     *
     * @return array
     *
     * @throws InvalidArgumentException When service file is not valid
     */
    private function validate($content, $file)
    {
        if (null === $content) {
            return $content;
        }

        if (!is_array($content)) {
            throw new InvalidArgumentException(sprintf('The service file "%s" is not valid.', $file));
        }

        foreach (array_keys($content) as $namespace) {
            if (in_array($namespace, array('imports', 'parameters', 'services'))) {
                continue;
            }

            if (!$this->container->hasExtension($namespace)) {
                $extensionNamespaces = array_filter(array_map(function ($ext) { return $ext->getAlias(); }, $this->container->getExtensions()));
                throw new InvalidArgumentException(sprintf(
                    'There is no extension able to load the configuration for "%s" (in %s). Looked for namespace "%s", found %s',
                    $namespace,
                    $file,
                    $namespace,
                    $extensionNamespaces ? sprintf('"%s"', implode('", "', $extensionNamespaces)) : 'none'
                ));
            }
        }

        return $content;
    }

    /**
     * Resolves services.
     *
     * @param string $value
     *
     * @return Reference
     */
    private function resolveServices($value)
    {
        if (is_array($value)) {
            $value = array_map(array($this, 'resolveServices'), $value);
        } elseif (is_string($value) &&  0 === strpos($value, '@=')) {
            return new Expression(substr($value, 2));
        } elseif (is_string($value) &&  0 === strpos($value, '@')) {
            if (0 === strpos($value, '@@')) {
                $value = substr($value, 1);
                $invalidBehavior = null;
            } elseif (0 === strpos($value, '@?')) {
                $value = substr($value, 2);
                $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
            } else {
                $value = substr($value, 1);
                $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
            }

            if ('=' === substr($value, -1)) {
                $value = substr($value, 0, -1);
                $strict = false;
            } else {
                $strict = true;
            }

            if (null !== $invalidBehavior) {
                $value = new Reference($value, $invalidBehavior, $strict);
            }
        }

        return $value;
    }

    /**
     * Loads from Extensions
     *
     * @param array $content
     */
    private function loadFromExtensions($content)
    {
        foreach ($content as $namespace => $values) {
            if (in_array($namespace, array('imports', 'parameters', 'services'))) {
                continue;
            }

            if (!is_array($values)) {
                $values = array();
            }

            $this->container->loadFromExtension($namespace, $values);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

/**
 * @api
 */
class Alias
{
    private $id;
    private $public;

    /**
     * Constructor.
     *
     * @param string  $id     Alias identifier
     * @param Boolean $public If this alias is public
     *
     * @api
     */
    public function __construct($id, $public = true)
    {
        $this->id = strtolower($id);
        $this->public = $public;
    }

    /**
     * Checks if this DI Alias should be public or not.
     *
     * @return Boolean
     *
     * @api
     */
    public function isPublic()
    {
        return $this->public;
    }

    /**
     * Sets if this Alias is public.
     *
     * @param Boolean $boolean If this Alias should be public
     *
     * @api
     */
    public function setPublic($boolean)
    {
        $this->public = (Boolean) $boolean;
    }

    /**
     * Returns the Id of this alias.
     *
     * @return string The alias id
     *
     * @api
     */
    public function __toString()
    {
        return $this->id;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\LazyProxy\Instantiator;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;

/**
 * Lazy proxy instantiator, capable of instantiating a proxy given a container, the
 * service definitions and a callback that produces the real service instance.
 *
 * @author Marco Pivetta <ocramius@gmail.com>
 */
interface InstantiatorInterface
{
    /**
     * Instantiates a proxy object.
     *
     * @param ContainerInterface $container        the container from which the service is being requested
     * @param Definition         $definition       the definition of the requested service
     * @param string             $id               identifier of the requested service
     * @param callable           $realInstantiator zero-argument callback that is capable of producing the real
     *                                             service instance
     *
     * @return object
     */
    public function instantiateProxy(ContainerInterface $container, Definition $definition, $id, $realInstantiator);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\LazyProxy\Instantiator;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;

/**
 * {@inheritDoc}
 *
 * Noop proxy instantiator - simply produces the real service instead of a proxy instance.
 *
 * @author Marco Pivetta <ocramius@gmail.com>
 */
class RealServiceInstantiator implements InstantiatorInterface
{
    /**
     * {@inheritDoc}
     */
    public function instantiateProxy(ContainerInterface $container, Definition $definition, $id, $realInstantiator)
    {
        return call_user_func($realInstantiator);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\LazyProxy\PhpDumper;

use Symfony\Component\DependencyInjection\Definition;

/**
 * Null dumper, negates any proxy code generation for any given service definition.
 *
 * @author Marco Pivetta <ocramius@gmail.com>
 */
class NullDumper implements DumperInterface
{
    /**
     * {@inheritDoc}
     */
    public function isProxyCandidate(Definition $definition)
    {
        return false;
    }

    /**
     * {@inheritDoc}
     */
    public function getProxyFactoryCode(Definition $definition, $id)
    {
        return '';
    }

    /**
     * {@inheritDoc}
     */
    public function getProxyCode(Definition $definition)
    {
        return '';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\LazyProxy\PhpDumper;

use Symfony\Component\DependencyInjection\Definition;

/**
 * Lazy proxy dumper capable of generating the instantiation logic php code for proxied services.
 *
 * @author Marco Pivetta <ocramius@gmail.com>
 */
interface DumperInterface
{
    /**
     * Inspects whether the given definitions should produce proxy instantiation logic in the dumped container.
     *
     * @param Definition $definition
     *
     * @return bool
     */
    public function isProxyCandidate(Definition $definition);

    /**
     * Generates the code to be used to instantiate a proxy in the dumped factory code.
     *
     * @param Definition $definition
     * @param string     $id         service identifier
     *
     * @return string
     */
    public function getProxyFactoryCode(Definition $definition, $id);

    /**
     * Generates the code for the lazy proxy.
     *
     * @param Definition $definition
     *
     * @return string
     */
    public function getProxyCode(Definition $definition);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

use Symfony\Component\Config\Util\XmlUtils;
use Symfony\Component\ExpressionLanguage\Expression;

/**
 * SimpleXMLElement class.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class SimpleXMLElement extends \SimpleXMLElement
{
    /**
     * Converts an attribute as a php type.
     *
     * @param string $name
     *
     * @return mixed
     */
    public function getAttributeAsPhp($name)
    {
        return self::phpize($this[$name]);
    }

    /**
     * Returns arguments as valid php types.
     *
     * @param string  $name
     * @param Boolean $lowercase
     *
     * @return mixed
     */
    public function getArgumentsAsPhp($name, $lowercase = true)
    {
        $arguments = array();
        foreach ($this->$name as $arg) {
            if (isset($arg['name'])) {
                $arg['key'] = (string) $arg['name'];
            }
            $key = isset($arg['key']) ? (string) $arg['key'] : (!$arguments ? 0 : max(array_keys($arguments)) + 1);

            // parameter keys are case insensitive
            if ('parameter' == $name && $lowercase) {
                $key = strtolower($key);
            }

            // this is used by DefinitionDecorator to overwrite a specific
            // argument of the parent definition
            if (isset($arg['index'])) {
                $key = 'index_'.$arg['index'];
            }

            switch ($arg['type']) {
                case 'service':
                    $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
                    if (isset($arg['on-invalid']) && 'ignore' == $arg['on-invalid']) {
                        $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
                    } elseif (isset($arg['on-invalid']) && 'null' == $arg['on-invalid']) {
                        $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE;
                    }

                    if (isset($arg['strict'])) {
                        $strict = self::phpize($arg['strict']);
                    } else {
                        $strict = true;
                    }

                    $arguments[$key] = new Reference((string) $arg['id'], $invalidBehavior, $strict);
                    break;
                case 'expression':
                    $arguments[$key] = new Expression((string) $arg);
                    break;
                case 'collection':
                    $arguments[$key] = $arg->getArgumentsAsPhp($name, false);
                    break;
                case 'string':
                    $arguments[$key] = (string) $arg;
                    break;
                case 'constant':
                    $arguments[$key] = constant((string) $arg);
                    break;
                default:
                    $arguments[$key] = self::phpize($arg);
            }
        }

        return $arguments;
    }

    /**
     * Converts an xml value to a php type.
     *
     * @param mixed $value
     *
     * @return mixed
     */
    public static function phpize($value)
    {
        return XmlUtils::phpize($value);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

/**
 * Reference represents a service reference.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Reference
{
    private $id;
    private $invalidBehavior;
    private $strict;

    /**
     * Constructor.
     *
     * @param string  $id              The service identifier
     * @param int     $invalidBehavior The behavior when the service does not exist
     * @param Boolean $strict          Sets how this reference is validated
     *
     * @see Container
     */
    public function __construct($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $strict = true)
    {
        $this->id = strtolower($id);
        $this->invalidBehavior = $invalidBehavior;
        $this->strict = $strict;
    }

    /**
     * __toString.
     *
     * @return string The service identifier
     */
    public function __toString()
    {
        return $this->id;
    }

    /**
     * Returns the behavior to be used when the service does not exist.
     *
     * @return int
     */
    public function getInvalidBehavior()
    {
        return $this->invalidBehavior;
    }

    /**
     * Returns true when this Reference is strict
     *
     * @return Boolean
     */
    public function isStrict()
    {
        return $this->strict;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

/**
 * Parameter represents a parameter reference.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Parameter
{
    private $id;

    /**
     * Constructor.
     *
     * @param string $id The parameter key
     */
    public function __construct($id)
    {
        $this->id = $id;
    }

    /**
     * __toString.
     *
     * @return string The parameter key
     */
    public function __toString()
    {
        return (string) $this->id;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\ParameterBag;

use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;

/**
 * ParameterBagInterface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface ParameterBagInterface
{
    /**
     * Clears all parameters.
     *
     * @api
     */
    public function clear();

    /**
     * Adds parameters to the service container parameters.
     *
     * @param array $parameters An array of parameters
     *
     * @api
     */
    public function add(array $parameters);

    /**
     * Gets the service container parameters.
     *
     * @return array An array of parameters
     *
     * @api
     */
    public function all();

    /**
     * Gets a service container parameter.
     *
     * @param string $name The parameter name
     *
     * @return mixed  The parameter value
     *
     * @throws ParameterNotFoundException if the parameter is not defined
     *
     * @api
     */
    public function get($name);

    /**
     * Sets a service container parameter.
     *
     * @param string $name  The parameter name
     * @param mixed  $value The parameter value
     *
     * @api
     */
    public function set($name, $value);

    /**
     * Returns true if a parameter name is defined.
     *
     * @param string $name The parameter name
     *
     * @return Boolean true if the parameter name is defined, false otherwise
     *
     * @api
     */
    public function has($name);

    /**
     * Replaces parameter placeholders (%name%) by their values for all parameters.
     */
    public function resolve();

    /**
     * Replaces parameter placeholders (%name%) by their values.
     *
     * @param mixed $value A value
     *
     * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist
     */
    public function resolveValue($value);

    /**
     * Escape parameter placeholders %
     *
     * @param mixed $value
     *
     * @return mixed
     */
    public function escapeValue($value);

    /**
     * Unescape parameter placeholders %
     *
     * @param mixed $value
     *
     * @return mixed
     */
    public function unescapeValue($value);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\ParameterBag;

use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;

/**
 * Holds parameters.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class ParameterBag implements ParameterBagInterface
{
    protected $parameters = array();
    protected $resolved = false;

    /**
     * Constructor.
     *
     * @param array $parameters An array of parameters
     *
     * @api
     */
    public function __construct(array $parameters = array())
    {
        $this->add($parameters);
    }

    /**
     * Clears all parameters.
     *
     * @api
     */
    public function clear()
    {
        $this->parameters = array();
    }

    /**
     * Adds parameters to the service container parameters.
     *
     * @param array $parameters An array of parameters
     *
     * @api
     */
    public function add(array $parameters)
    {
        foreach ($parameters as $key => $value) {
            $this->parameters[strtolower($key)] = $value;
        }
    }

    /**
     * Gets the service container parameters.
     *
     * @return array An array of parameters
     *
     * @api
     */
    public function all()
    {
        return $this->parameters;
    }

    /**
     * Gets a service container parameter.
     *
     * @param string $name The parameter name
     *
     * @return mixed  The parameter value
     *
     * @throws ParameterNotFoundException if the parameter is not defined
     *
     * @api
     */
    public function get($name)
    {
        $name = strtolower($name);

        if (!array_key_exists($name, $this->parameters)) {
            if (!$name) {
                throw new ParameterNotFoundException($name);
            }

            $alternatives = array();
            foreach (array_keys($this->parameters) as $key) {
                $lev = levenshtein($name, $key);
                if ($lev <= strlen($name) / 3 || false !== strpos($key, $name)) {
                    $alternatives[] = $key;
                }
            }

            throw new ParameterNotFoundException($name, null, null, null, $alternatives);
        }

        return $this->parameters[$name];
    }

    /**
     * Sets a service container parameter.
     *
     * @param string $name  The parameter name
     * @param mixed  $value The parameter value
     *
     * @api
     */
    public function set($name, $value)
    {
        $this->parameters[strtolower($name)] = $value;
    }

    /**
     * Returns true if a parameter name is defined.
     *
     * @param string $name The parameter name
     *
     * @return Boolean true if the parameter name is defined, false otherwise
     *
     * @api
     */
    public function has($name)
    {
        return array_key_exists(strtolower($name), $this->parameters);
    }

    /**
     * Removes a parameter.
     *
     * @param string $name The parameter name
     *
     * @api
     */
    public function remove($name)
    {
        unset($this->parameters[strtolower($name)]);
    }

    /**
     * Replaces parameter placeholders (%name%) by their values for all parameters.
     */
    public function resolve()
    {
        if ($this->resolved) {
            return;
        }

        $parameters = array();
        foreach ($this->parameters as $key => $value) {
            try {
                $value = $this->resolveValue($value);
                $parameters[$key] = $this->unescapeValue($value);
            } catch (ParameterNotFoundException $e) {
                $e->setSourceKey($key);

                throw $e;
            }
        }

        $this->parameters = $parameters;
        $this->resolved = true;
    }

    /**
     * Replaces parameter placeholders (%name%) by their values.
     *
     * @param mixed $value     A value
     * @param array $resolving An array of keys that are being resolved (used internally to detect circular references)
     *
     * @return mixed The resolved value
     *
     * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist
     * @throws ParameterCircularReferenceException if a circular reference if detected
     * @throws RuntimeException when a given parameter has a type problem.
     */
    public function resolveValue($value, array $resolving = array())
    {
        if (is_array($value)) {
            $args = array();
            foreach ($value as $k => $v) {
                $args[$this->resolveValue($k, $resolving)] = $this->resolveValue($v, $resolving);
            }

            return $args;
        }

        if (!is_string($value)) {
            return $value;
        }

        return $this->resolveString($value, $resolving);
    }

    /**
     * Resolves parameters inside a string
     *
     * @param string $value     The string to resolve
     * @param array  $resolving An array of keys that are being resolved (used internally to detect circular references)
     *
     * @return string The resolved string
     *
     * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist
     * @throws ParameterCircularReferenceException if a circular reference if detected
     * @throws RuntimeException when a given parameter has a type problem.
     */
    public function resolveString($value, array $resolving = array())
    {
        // we do this to deal with non string values (Boolean, integer, ...)
        // as the preg_replace_callback throw an exception when trying
        // a non-string in a parameter value
        if (preg_match('/^%([^%\s]+)%$/', $value, $match)) {
            $key = strtolower($match[1]);

            if (isset($resolving[$key])) {
                throw new ParameterCircularReferenceException(array_keys($resolving));
            }

            $resolving[$key] = true;

            return $this->resolved ? $this->get($key) : $this->resolveValue($this->get($key), $resolving);
        }

        $self = $this;

        return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($self, $resolving, $value) {
            // skip %%
            if (!isset($match[1])) {
                return '%%';
            }

            $key = strtolower($match[1]);
            if (isset($resolving[$key])) {
                throw new ParameterCircularReferenceException(array_keys($resolving));
            }

            $resolved = $self->get($key);

            if (!is_string($resolved) && !is_numeric($resolved)) {
                throw new RuntimeException(sprintf('A string value must be composed of strings and/or numbers, but found parameter "%s" of type %s inside string value "%s".', $key, gettype($resolved), $value));
            }

            $resolved = (string) $resolved;
            $resolving[$key] = true;

            return $self->isResolved() ? $resolved : $self->resolveString($resolved, $resolving);
        }, $value);
    }

    public function isResolved()
    {
        return $this->resolved;
    }

    /**
     * {@inheritDoc}
     */
    public function escapeValue($value)
    {
        if (is_string($value)) {
            return str_replace('%', '%%', $value);
        }

        if (is_array($value)) {
            $result = array();
            foreach ($value as $k => $v) {
                $result[$k] = $this->escapeValue($v);
            }

            return $result;
        }

        return $value;
    }

    public function unescapeValue($value)
    {
        if (is_string($value)) {
            return str_replace('%%', '%', $value);
        }

        if (is_array($value)) {
            $result = array();
            foreach ($value as $k => $v) {
                $result[$k] = $this->unescapeValue($v);
            }

            return $result;
        }

        return $value;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\ParameterBag;

use Symfony\Component\DependencyInjection\Exception\LogicException;

/**
 * Holds read-only parameters.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class FrozenParameterBag extends ParameterBag
{
    /**
     * Constructor.
     *
     * For performance reasons, the constructor assumes that
     * all keys are already lowercased.
     *
     * This is always the case when used internally.
     *
     * @param array $parameters An array of parameters
     *
     * @api
     */
    public function __construct(array $parameters = array())
    {
        $this->parameters = $parameters;
        $this->resolved = true;
    }

    /**
     * {@inheritDoc}
     *
     * @api
     */
    public function clear()
    {
        throw new LogicException('Impossible to call clear() on a frozen ParameterBag.');
    }

    /**
     * {@inheritDoc}
     *
     * @api
     */
    public function add(array $parameters)
    {
        throw new LogicException('Impossible to call add() on a frozen ParameterBag.');
    }

    /**
     * {@inheritDoc}
     *
     * @api
     */
    public function set($name, $value)
    {
        throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Exception;

/**
 * Base OutOfBoundsException for Dependency Injection component.
 */
class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Exception;

/**
 * Base InvalidArgumentException for Dependency Injection component.
 *
 * @author Bulat Shakirzyanov <bulat@theopenskyproject.com>
 */
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Exception;

/**
 * Base RuntimeException for Dependency Injection component.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Exception;

/**
 * This exception is thrown when a non-existent service is requested.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ServiceNotFoundException extends InvalidArgumentException
{
    private $id;
    private $sourceId;

    public function __construct($id, $sourceId = null, \Exception $previous = null, array $alternatives = array())
    {
        if (null === $sourceId) {
            $msg = sprintf('You have requested a non-existent service "%s".', $id);
        } else {
            $msg = sprintf('The service "%s" has a dependency on a non-existent service "%s".', $sourceId, $id);
        }

        if ($alternatives) {
            if (1 == count($alternatives)) {
                $msg .= ' Did you mean this: "';
            } else {
                $msg .= ' Did you mean one of these: "';
            }
            $msg .= implode('", "', $alternatives).'"?';
        }

        parent::__construct($msg, 0, $previous);

        $this->id = $id;
        $this->sourceId = $sourceId;
    }

    public function getId()
    {
        return $this->id;
    }

    public function getSourceId()
    {
        return $this->sourceId;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Exception;

/**
 * Base LogicException for Dependency Injection component.
 */
class LogicException extends \LogicException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Exception;

/**
 * Base ExceptionInterface for Dependency Injection component.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bulat Shakirzyanov <bulat@theopenskyproject.com>
 */
interface ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Exception;

/**
 * This exception is thrown when you try to create a service of an inactive scope.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class InactiveScopeException extends RuntimeException
{
    private $serviceId;
    private $scope;

    public function __construct($serviceId, $scope, \Exception $previous = null)
    {
        parent::__construct(sprintf('You cannot create a service ("%s") of an inactive scope ("%s").', $serviceId, $scope), 0, $previous);

        $this->serviceId = $serviceId;
        $this->scope = $scope;
    }

    public function getServiceId()
    {
        return $this->serviceId;
    }

    public function getScope()
    {
        return $this->scope;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Exception;

/**
 * This exception is thrown when a circular reference in a parameter is detected.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ParameterCircularReferenceException extends RuntimeException
{
    private $parameters;

    public function __construct($parameters, \Exception $previous = null)
    {
        parent::__construct(sprintf('Circular reference detected for parameter "%s" ("%s" > "%s").', $parameters[0], implode('" > "', $parameters), $parameters[0]), 0, $previous);

        $this->parameters = $parameters;
    }

    public function getParameters()
    {
        return $this->parameters;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Exception;

/**
 * Base BadMethodCallException for Dependency Injection component.
 */
class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Exception;

/**
 * This exception is thrown when the a scope crossing injection is detected.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ScopeCrossingInjectionException extends RuntimeException
{
    private $sourceServiceId;
    private $sourceScope;
    private $destServiceId;
    private $destScope;

    public function __construct($sourceServiceId, $sourceScope, $destServiceId, $destScope, \Exception $previous = null)
    {
        parent::__construct(sprintf(
            'Scope Crossing Injection detected: The definition "%s" references the service "%s" which belongs to another scope hierarchy. '
           .'This service might not be available consistently. Generally, it is safer to either move the definition "%s" to scope "%s", or '
           .'declare "%s" as a child scope of "%s". If you can be sure that the other scope is always active, you can set the reference to strict=false to get rid of this error.',
           $sourceServiceId,
           $destServiceId,
           $sourceServiceId,
           $destScope,
           $sourceScope,
           $destScope
        ), 0, $previous);

        $this->sourceServiceId = $sourceServiceId;
        $this->sourceScope = $sourceScope;
        $this->destServiceId = $destServiceId;
        $this->destScope = $destScope;
    }

    public function getSourceServiceId()
    {
        return $this->sourceServiceId;
    }

    public function getSourceScope()
    {
        return $this->sourceScope;
    }

    public function getDestServiceId()
    {
        return $this->destServiceId;
    }

    public function getDestScope()
    {
        return $this->destScope;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Exception;

/**
 * This exception is thrown when a circular reference is detected.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ServiceCircularReferenceException extends RuntimeException
{
    private $serviceId;
    private $path;

    public function __construct($serviceId, array $path, \Exception $previous = null)
    {
        parent::__construct(sprintf('Circular reference detected for service "%s", path: "%s".', $serviceId, implode(' -> ', $path)), 0, $previous);

        $this->serviceId = $serviceId;
        $this->path = $path;
    }

    public function getServiceId()
    {
        return $this->serviceId;
    }

    public function getPath()
    {
        return $this->path;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Exception;

/**
 * Thrown when a scope widening injection is detected.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ScopeWideningInjectionException extends RuntimeException
{
    private $sourceServiceId;
    private $sourceScope;
    private $destServiceId;
    private $destScope;

    public function __construct($sourceServiceId, $sourceScope, $destServiceId, $destScope, \Exception $previous = null)
    {
        parent::__construct(sprintf(
            'Scope Widening Injection detected: The definition "%s" references the service "%s" which belongs to a narrower scope. '
           .'Generally, it is safer to either move "%s" to scope "%s" or alternatively rely on the provider pattern by injecting the container itself, and requesting the service "%s" each time it is needed. '
           .'In rare, special cases however that might not be necessary, then you can set the reference to strict=false to get rid of this error.',
           $sourceServiceId,
           $destServiceId,
           $sourceServiceId,
           $destScope,
           $destServiceId
        ), 0, $previous);

        $this->sourceServiceId = $sourceServiceId;
        $this->sourceScope = $sourceScope;
        $this->destServiceId = $destServiceId;
        $this->destScope = $destScope;
    }

    public function getSourceServiceId()
    {
        return $this->sourceServiceId;
    }

    public function getSourceScope()
    {
        return $this->sourceScope;
    }

    public function getDestServiceId()
    {
        return $this->destServiceId;
    }

    public function getDestScope()
    {
        return $this->destScope;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Exception;

/**
 * This exception is thrown when a non-existent parameter is used.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ParameterNotFoundException extends InvalidArgumentException
{
    private $key;
    private $sourceId;
    private $sourceKey;
    private $alternatives;

    /**
     * Constructor.
     *
     * @param string     $key          The requested parameter key
     * @param string     $sourceId     The service id that references the non-existent parameter
     * @param string     $sourceKey    The parameter key that references the non-existent parameter
     * @param \Exception $previous     The previous exception
     * @param string[]   $alternatives Some parameter name alternatives
     */
    public function __construct($key, $sourceId = null, $sourceKey = null, \Exception $previous = null, array $alternatives = array())
    {
        $this->key = $key;
        $this->sourceId = $sourceId;
        $this->sourceKey = $sourceKey;
        $this->alternatives = $alternatives;

        parent::__construct('', 0, $previous);

        $this->updateRepr();
    }

    public function updateRepr()
    {
        if (null !== $this->sourceId) {
            $this->message = sprintf('The service "%s" has a dependency on a non-existent parameter "%s".', $this->sourceId, $this->key);
        } elseif (null !== $this->sourceKey) {
            $this->message = sprintf('The parameter "%s" has a dependency on a non-existent parameter "%s".', $this->sourceKey, $this->key);
        } else {
            $this->message = sprintf('You have requested a non-existent parameter "%s".', $this->key);
        }

        if ($this->alternatives) {
            if (1 == count($this->alternatives)) {
                $this->message .= ' Did you mean this: "';
            } else {
                $this->message .= ' Did you mean one of these: "';
            }
            $this->message .= implode('", "', $this->alternatives).'"?';
        }
    }

    public function getKey()
    {
        return $this->key;
    }

    public function getSourceId()
    {
        return $this->sourceId;
    }

    public function getSourceKey()
    {
        return $this->sourceKey;
    }

    public function setSourceId($sourceId)
    {
        $this->sourceId = $sourceId;

        $this->updateRepr();
    }

    public function setSourceKey($sourceKey)
    {
        $this->sourceKey = $sourceKey;

        $this->updateRepr();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

/**
 * IntrospectableContainerInterface defines additional introspection functionality
 * for containers, allowing logic to be implemented based on a Container's state.
 *
 * @author Evan Villemez <evillemez@gmail.com>
 *
 */
interface IntrospectableContainerInterface extends ContainerInterface
{
    /**
     * Check for whether or not a service has been initialized.
     *
     * @param string $id
     *
     * @return Boolean true if the service has been initialized, false otherwise
     *
     */
    public function initialized($id);

}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

/**
 * ContainerAwareInterface should be implemented by classes that depends on a Container.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface ContainerAwareInterface
{
    /**
     * Sets the Container.
     *
     * @param ContainerInterface|null $container A ContainerInterface instance or null
     *
     * @api
     */
    public function setContainer(ContainerInterface $container = null);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Extension;

class ExtensionTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getResolvedEnabledFixtures
     */
    public function testIsConfigEnabledReturnsTheResolvedValue($enabled)
    {
        $pb = $this->getMockBuilder('Symfony\Component\DependencyInjection\ParameterBag\ParameterBag')
            ->setMethods(array('resolveValue'))
            ->getMock()
        ;

        $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')
            ->setMethods(array('getParameterBag'))
            ->getMock()
        ;

        $pb->expects($this->once())
            ->method('resolveValue')
            ->with($this->equalTo($enabled))
            ->will($this->returnValue($enabled))
        ;

        $container->expects($this->once())
            ->method('getParameterBag')
            ->will($this->returnValue($pb))
        ;

        $extension = $this->getMockBuilder('Symfony\Component\DependencyInjection\Extension\Extension')
            ->setMethods(array())
            ->getMockForAbstractClass()
        ;

        $r = new \ReflectionMethod('Symfony\Component\DependencyInjection\Extension\Extension', 'isConfigEnabled');
        $r->setAccessible(true);

        $r->invoke($extension, $container, array('enabled' => $enabled));
    }

    public function getResolvedEnabledFixtures()
    {
        return array(
            array(true),
            array(false)
        );
    }

    /**
     * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
     * @expectedExceptionMessage The config array has no 'enabled' key.
     */
    public function testIsConfigEnabledOnNonEnableableConfig()
    {
        $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')
            ->getMock()
        ;

        $extension = $this->getMockBuilder('Symfony\Component\DependencyInjection\Extension\Extension')
            ->setMethods(array())
            ->getMockForAbstractClass()
        ;

        $r = new \ReflectionMethod('Symfony\Component\DependencyInjection\Extension\Extension', 'isConfigEnabled');
        $r->setAccessible(true);

        $r->invoke($extension, $container, array());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;

class CrossCheckTest extends \PHPUnit_Framework_TestCase
{
    protected static $fixturesPath;

    public static function setUpBeforeClass()
    {
        self::$fixturesPath = __DIR__.'/Fixtures/';

        require_once self::$fixturesPath.'/includes/classes.php';
        require_once self::$fixturesPath.'/includes/foo.php';
    }

    /**
     * @dataProvider crossCheckLoadersDumpers
     */
    public function testCrossCheck($fixture, $type)
    {
        $loaderClass = 'Symfony\\Component\\DependencyInjection\\Loader\\'.ucfirst($type).'FileLoader';
        $dumperClass = 'Symfony\\Component\\DependencyInjection\\Dumper\\'.ucfirst($type).'Dumper';

        $tmp = tempnam('sf_service_container', 'sf');

        file_put_contents($tmp, file_get_contents(self::$fixturesPath.'/'.$type.'/'.$fixture));

        $container1 = new ContainerBuilder();
        $loader1 = new $loaderClass($container1, new FileLocator());
        $loader1->load($tmp);

        $dumper = new $dumperClass($container1);
        file_put_contents($tmp, $dumper->dump());

        $container2 = new ContainerBuilder();
        $loader2 = new $loaderClass($container2, new FileLocator());
        $loader2->load($tmp);

        unlink($tmp);

        $this->assertEquals($container2->getAliases(), $container1->getAliases(), 'loading a dump from a previously loaded container returns the same container');
        $this->assertEquals($container2->getDefinitions(), $container1->getDefinitions(), 'loading a dump from a previously loaded container returns the same container');
        $this->assertEquals($container2->getParameterBag()->all(), $container1->getParameterBag()->all(), '->getParameterBag() returns the same value for both containers');

        $this->assertEquals(serialize($container2), serialize($container1), 'loading a dump from a previously loaded container returns the same container');

        $services1 = array();
        foreach ($container1 as $id => $service) {
            $services1[$id] = serialize($service);
        }
        $services2 = array();
        foreach ($container2 as $id => $service) {
            $services2[$id] = serialize($service);
        }

        unset($services1['service_container'], $services2['service_container']);

        $this->assertEquals($services2, $services1, 'Iterator on the containers returns the same services');
    }

    public function crossCheckLoadersDumpers()
    {
        $tests = array(
            array('services1.xml', 'xml'),
            array('services2.xml', 'xml'),
            array('services6.xml', 'xml'),
            array('services8.xml', 'xml'),
            array('services9.xml', 'xml'),
        );

        if (class_exists('Symfony\Component\Yaml\Yaml')) {
            $tests = array_merge($tests, array(
                array('services1.yml', 'yaml'),
                array('services2.yml', 'yaml'),
                array('services6.yml', 'yaml'),
                array('services8.yml', 'yaml'),
                array('services9.yml', 'yaml'),
            ));
        }

        return $tests;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Dumper;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Definition;

class PhpDumperTest extends \PHPUnit_Framework_TestCase
{
    protected static $fixturesPath;

    public static function setUpBeforeClass()
    {
        self::$fixturesPath = realpath(__DIR__.'/../Fixtures/');
    }

    public function testDump()
    {
        $dumper = new PhpDumper($container = new ContainerBuilder());

        $this->assertStringEqualsFile(self::$fixturesPath.'/php/services1.php', $dumper->dump(), '->dump() dumps an empty container as an empty PHP class');
        $this->assertStringEqualsFile(self::$fixturesPath.'/php/services1-1.php', $dumper->dump(array('class' => 'Container', 'base_class' => 'AbstractContainer', 'namespace' => 'Symfony\Component\DependencyInjection\Dump')), '->dump() takes a class and a base_class options');

        $container = new ContainerBuilder();
        new PhpDumper($container);
    }

    public function testDumpFrozenContainerWithNoParameter()
    {
        $container = new ContainerBuilder();
        $container->setResourceTracking(false);
        $container->register('foo', 'stdClass');

        $container->compile();

        $dumper = new PhpDumper($container);

        $dumpedString = $dumper->dump();
        $this->assertStringEqualsFile(self::$fixturesPath.'/php/services11.php', $dumpedString, '->dump() does not add getDefaultParameters() method call if container have no parameters.');
        $this->assertNotRegexp("/function getDefaultParameters\(/", $dumpedString, '->dump() does not add getDefaultParameters() method definition.');
    }

    public function testDumpOptimizationString()
    {
        $definition = new Definition();
        $definition->setClass('stdClass');
        $definition->addArgument(array(
            'only dot' => '.',
            'concatenation as value' => '.\'\'.',
            'concatenation from the start value' => '\'\'.',
            '.' => 'dot as a key',
            '.\'\'.' => 'concatenation as a key',
            '\'\'.' =>'concatenation from the start key',
            'optimize concatenation' => "string1%some_string%string2",
            'optimize concatenation with empty string' => "string1%empty_value%string2",
            'optimize concatenation from the start' => '%empty_value%start',
            'optimize concatenation at the end' => 'end%empty_value%',
        ));

        $container = new ContainerBuilder();
        $container->setResourceTracking(false);
        $container->setDefinition('test', $definition);
        $container->setParameter('empty_value', '');
        $container->setParameter('some_string', '-');
        $container->compile();

        $dumper = new PhpDumper($container);
        $this->assertStringEqualsFile(self::$fixturesPath.'/php/services10.php', $dumper->dump(), '->dump() dumps an empty container as an empty PHP class');
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testExportParameters()
    {
        $dumper = new PhpDumper(new ContainerBuilder(new ParameterBag(array('foo' => new Reference('foo')))));
        $dumper->dump();
    }

    public function testAddParameters()
    {
        $container = include self::$fixturesPath.'/containers/container8.php';
        $dumper = new PhpDumper($container);
        $this->assertStringEqualsFile(self::$fixturesPath.'/php/services8.php', $dumper->dump(), '->dump() dumps parameters');
    }

    public function testAddService()
    {
        // without compilation
        $container = include self::$fixturesPath.'/containers/container9.php';
        $dumper = new PhpDumper($container);
        $this->assertEquals(str_replace('%path%', str_replace('\\','\\\\',self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR), file_get_contents(self::$fixturesPath.'/php/services9.php')), $dumper->dump(), '->dump() dumps services');

        // with compilation
        $container = include self::$fixturesPath.'/containers/container9.php';
        $container->compile();
        $dumper = new PhpDumper($container);
        $this->assertEquals(str_replace('%path%', str_replace('\\','\\\\',self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR), file_get_contents(self::$fixturesPath.'/php/services9_compiled.php')), $dumper->dump(), '->dump() dumps services');

        $dumper = new PhpDumper($container = new ContainerBuilder());
        $container->register('foo', 'FooClass')->addArgument(new \stdClass());
        try {
            $dumper->dump();
            $this->fail('->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\Symfony\Component\DependencyInjection\Exception\RuntimeException', $e, '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources');
            $this->assertEquals('Unable to dump a service container if a parameter is an object or a resource.', $e->getMessage(), '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources');
        }
    }

    /**
     * @expectedException \InvalidArgumentException
     * @expectedExceptionMessage Service id "bar$" cannot be converted to a valid PHP method name.
     */
    public function testAddServiceInvalidServiceId()
    {
        $container = new ContainerBuilder();
        $container->register('bar$', 'FooClass');
        $dumper = new PhpDumper($container);
        $dumper->dump();
    }

    public function testAliases()
    {
        $container = include self::$fixturesPath.'/containers/container9.php';
        $container->compile();
        $dumper = new PhpDumper($container);
        eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Aliases')));

        $container = new \Symfony_DI_PhpDumper_Test_Aliases();
        $container->set('foo', $foo = new \stdClass);
        $this->assertSame($foo, $container->get('foo'));
        $this->assertSame($foo, $container->get('alias_for_foo'));
        $this->assertSame($foo, $container->get('alias_for_alias'));
    }

    public function testFrozenContainerWithoutAliases()
    {
        $container = new ContainerBuilder();
        $container->compile();

        $dumper = new PhpDumper($container);
        eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Frozen_No_Aliases')));

        $container = new \Symfony_DI_PhpDumper_Test_Frozen_No_Aliases();
        $this->assertFalse($container->has('foo'));
    }

    public function testOverrideServiceWhenUsingADumpedContainer()
    {
        require_once self::$fixturesPath.'/php/services9.php';
        require_once self::$fixturesPath.'/includes/foo.php';

        $container = new \ProjectServiceContainer();
        $container->set('bar', $bar = new \stdClass());
        $container->setParameter('foo_bar', 'foo_bar');

        $this->assertEquals($bar, $container->get('bar'), '->set() overrides an already defined service');
    }

    public function testOverrideServiceWhenUsingADumpedContainerAndServiceIsUsedFromAnotherOne()
    {
        require_once self::$fixturesPath.'/php/services9.php';
        require_once self::$fixturesPath.'/includes/foo.php';
        require_once self::$fixturesPath.'/includes/classes.php';

        $container = new \ProjectServiceContainer();
        $container->set('bar', $bar = new \stdClass());

        $this->assertSame($bar, $container->get('foo')->bar, '->set() overrides an already defined service');
    }

    /**
     * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException
     */
    public function testCircularReference()
    {
        $container = new ContainerBuilder();
        $container->register('foo', 'stdClass')->addArgument(new Reference('bar'));
        $container->register('bar', 'stdClass')->setPublic(false)->addMethodCall('setA', array(new Reference('baz')));
        $container->register('baz', 'stdClass')->addMethodCall('setA', array(new Reference('foo')));
        $container->compile();

        $dumper = new PhpDumper($container);
        $dumper->dump();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Dumper;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Dumper\YamlDumper;

class YamlDumperTest extends \PHPUnit_Framework_TestCase
{
    protected static $fixturesPath;

    public static function setUpBeforeClass()
    {
        self::$fixturesPath = realpath(__DIR__.'/../Fixtures/');
    }

    public function testDump()
    {
        $dumper = new YamlDumper($container = new ContainerBuilder());

        $this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services1.yml', $dumper->dump(), '->dump() dumps an empty container as an empty YAML file');

        $container = new ContainerBuilder();
        $dumper = new YamlDumper($container);
    }

    public function testAddParameters()
    {
        $container = include self::$fixturesPath.'/containers/container8.php';
        $dumper = new YamlDumper($container);
        $this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services8.yml', $dumper->dump(), '->dump() dumps parameters');
    }

    public function testAddService()
    {
        $container = include self::$fixturesPath.'/containers/container9.php';
        $dumper = new YamlDumper($container);
        $this->assertEquals(str_replace('%path%', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR, file_get_contents(self::$fixturesPath.'/yaml/services9.yml')), $dumper->dump(), '->dump() dumps services');

        $dumper = new YamlDumper($container = new ContainerBuilder());
        $container->register('foo', 'FooClass')->addArgument(new \stdClass());
        try {
            $dumper->dump();
            $this->fail('->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\RuntimeException', $e, '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources');
            $this->assertEquals('Unable to dump a service container if a parameter is an object or a resource.', $e->getMessage(), '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources');
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Dumper;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Dumper\GraphvizDumper;

class GraphvizDumperTest extends \PHPUnit_Framework_TestCase
{
    protected static $fixturesPath;

    public static function setUpBeforeClass()
    {
        self::$fixturesPath = __DIR__.'/../Fixtures/';
    }

    public function testDump()
    {
        $dumper = new GraphvizDumper($container = new ContainerBuilder());

        $this->assertStringEqualsFile(self::$fixturesPath.'/graphviz/services1.dot', $dumper->dump(), '->dump() dumps an empty container as an empty dot file');

        $container = include self::$fixturesPath.'/containers/container9.php';
        $dumper = new GraphvizDumper($container);
        $this->assertEquals(str_replace('%path%', __DIR__, file_get_contents(self::$fixturesPath.'/graphviz/services9.dot')), $dumper->dump(), '->dump() dumps services');

        $container = include self::$fixturesPath.'/containers/container10.php';
        $dumper = new GraphvizDumper($container);
        $this->assertEquals(str_replace('%path%', __DIR__, file_get_contents(self::$fixturesPath.'/graphviz/services10.dot')), $dumper->dump(), '->dump() dumps services');

        $container = include self::$fixturesPath.'/containers/container10.php';
        $dumper = new GraphvizDumper($container);
        $this->assertEquals($dumper->dump(array(
            'graph' => array('ratio' => 'normal'),
            'node'  => array('fontsize' => 13, 'fontname' => 'Verdana', 'shape' => 'square'),
            'edge'  => array('fontsize' => 12, 'fontname' => 'Verdana', 'color' => 'white', 'arrowhead' => 'closed', 'arrowsize' => 1),
            'node.instance' => array('fillcolor' => 'green', 'style' => 'empty'),
            'node.definition' => array('fillcolor' => 'grey'),
            'node.missing' => array('fillcolor' => 'red', 'style' => 'empty'),
        )), str_replace('%path%', __DIR__, file_get_contents(self::$fixturesPath.'/graphviz/services10-1.dot')), '->dump() dumps services');
    }

    public function testDumpWithFrozenContainer()
    {
        $container = include self::$fixturesPath.'/containers/container13.php';
        $dumper = new GraphvizDumper($container);
        $this->assertEquals(str_replace('%path%', __DIR__, file_get_contents(self::$fixturesPath.'/graphviz/services13.dot')), $dumper->dump(), '->dump() dumps services');
    }

    public function testDumpWithFrozenCustomClassContainer()
    {
        $container = include self::$fixturesPath.'/containers/container14.php';
        $dumper = new GraphvizDumper($container);
        $this->assertEquals(str_replace('%path%', __DIR__, file_get_contents(self::$fixturesPath.'/graphviz/services14.dot')), $dumper->dump(), '->dump() dumps services');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Dumper;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Dumper\XmlDumper;

class XmlDumperTest extends \PHPUnit_Framework_TestCase
{
    protected static $fixturesPath;

    public static function setUpBeforeClass()
    {
        self::$fixturesPath = realpath(__DIR__.'/../Fixtures/');
    }

    public function testDump()
    {
        $dumper = new XmlDumper($container = new ContainerBuilder());

        $this->assertXmlStringEqualsXmlFile(self::$fixturesPath.'/xml/services1.xml', $dumper->dump(), '->dump() dumps an empty container as an empty XML file');

        $container = new ContainerBuilder();
        $dumper = new XmlDumper($container);
    }

    public function testExportParameters()
    {
        $container = include self::$fixturesPath.'//containers/container8.php';
        $dumper = new XmlDumper($container);
        $this->assertXmlStringEqualsXmlFile(self::$fixturesPath.'/xml/services8.xml', $dumper->dump(), '->dump() dumps parameters');
    }

    public function testAddParameters()
    {
        $container = include self::$fixturesPath.'//containers/container8.php';
        $dumper = new XmlDumper($container);
        $this->assertXmlStringEqualsXmlFile(self::$fixturesPath.'/xml/services8.xml', $dumper->dump(), '->dump() dumps parameters');
    }

    public function testAddService()
    {
        $container = include self::$fixturesPath.'/containers/container9.php';
        $dumper = new XmlDumper($container);
        $this->assertEquals(str_replace('%path%', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR, file_get_contents(self::$fixturesPath.'/xml/services9.xml')), $dumper->dump(), '->dump() dumps services');

        $dumper = new XmlDumper($container = new ContainerBuilder());
        $container->register('foo', 'FooClass')->addArgument(new \stdClass());
        try {
            $dumper->dump();
            $this->fail('->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\RuntimeException', $e, '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources');
            $this->assertEquals('Unable to dump a service container if a parameter is an object or a resource.', $e->getMessage(), '->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources');
        }
    }

    public function testDumpAnonymousServices()
    {
        include self::$fixturesPath.'/containers/container11.php';
        $dumper = new XmlDumper($container);
        $this->assertEquals("<?xml version=\"1.0\" encoding=\"utf-8\"?>
<container xmlns=\"http://symfony.com/schema/dic/services\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd\">
  <services>
    <service id=\"foo\" class=\"FooClass\">
      <argument type=\"service\">
        <service class=\"BarClass\">
          <argument type=\"service\">
            <service class=\"BazClass\"/>
          </argument>
        </service>
      </argument>
    </service>
  </services>
</container>
", $dumper->dump());
    }

    public function testDumpEntities()
    {
        include self::$fixturesPath.'/containers/container12.php';
        $dumper = new XmlDumper($container);
        $this->assertEquals("<?xml version=\"1.0\" encoding=\"utf-8\"?>
<container xmlns=\"http://symfony.com/schema/dic/services\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd\">
  <services>
    <service id=\"foo\" class=\"FooClass\Foo\">
      <tag name=\"foo&quot;bar\bar\" foo=\"foo&quot;barřž€\"/>
      <argument>foo&lt;&gt;&amp;bar</argument>
    </service>
  </services>
</container>
", $dumper->dump());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests;

require_once __DIR__.'/Fixtures/includes/classes.php';
require_once __DIR__.'/Fixtures/includes/ProjectExtension.php';

use Symfony\Component\Config\Resource\ResourceInterface;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\Scope;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\ExpressionLanguage\Expression;

class ContainerBuilderTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::setDefinitions
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getDefinitions
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::setDefinition
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getDefinition
     */
    public function testDefinitions()
    {
        $builder = new ContainerBuilder();
        $definitions = array(
            'foo' => new Definition('FooClass'),
            'bar' => new Definition('BarClass'),
        );
        $builder->setDefinitions($definitions);
        $this->assertEquals($definitions, $builder->getDefinitions(), '->setDefinitions() sets the service definitions');
        $this->assertTrue($builder->hasDefinition('foo'), '->hasDefinition() returns true if a service definition exists');
        $this->assertFalse($builder->hasDefinition('foobar'), '->hasDefinition() returns false if a service definition does not exist');

        $builder->setDefinition('foobar', $foo = new Definition('FooBarClass'));
        $this->assertEquals($foo, $builder->getDefinition('foobar'), '->getDefinition() returns a service definition if defined');
        $this->assertTrue($builder->setDefinition('foobar', $foo = new Definition('FooBarClass')) === $foo, '->setDefinition() implements a fluid interface by returning the service reference');

        $builder->addDefinitions($defs = array('foobar' => new Definition('FooBarClass')));
        $this->assertEquals(array_merge($definitions, $defs), $builder->getDefinitions(), '->addDefinitions() adds the service definitions');

        try {
            $builder->getDefinition('baz');
            $this->fail('->getDefinition() throws an InvalidArgumentException if the service definition does not exist');
        } catch (\InvalidArgumentException $e) {
            $this->assertEquals('The service definition "baz" does not exist.', $e->getMessage(), '->getDefinition() throws an InvalidArgumentException if the service definition does not exist');
        }
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::register
     */
    public function testRegister()
    {
        $builder = new ContainerBuilder();
        $builder->register('foo', 'FooClass');
        $this->assertTrue($builder->hasDefinition('foo'), '->register() registers a new service definition');
        $this->assertInstanceOf('Symfony\Component\DependencyInjection\Definition', $builder->getDefinition('foo'), '->register() returns the newly created Definition instance');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::has
     */
    public function testHas()
    {
        $builder = new ContainerBuilder();
        $this->assertFalse($builder->has('foo'), '->has() returns false if the service does not exist');
        $builder->register('foo', 'FooClass');
        $this->assertTrue($builder->has('foo'), '->has() returns true if a service definition exists');
        $builder->set('bar', new \stdClass());
        $this->assertTrue($builder->has('bar'), '->has() returns true if a service exists');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::get
     */
    public function testGet()
    {
        $builder = new ContainerBuilder();
        try {
            $builder->get('foo');
            $this->fail('->get() throws an InvalidArgumentException if the service does not exist');
        } catch (\InvalidArgumentException $e) {
            $this->assertEquals('The service definition "foo" does not exist.', $e->getMessage(), '->get() throws an InvalidArgumentException if the service does not exist');
        }

        $this->assertNull($builder->get('foo', ContainerInterface::NULL_ON_INVALID_REFERENCE), '->get() returns null if the service does not exist and NULL_ON_INVALID_REFERENCE is passed as a second argument');

        $builder->register('foo', 'stdClass');
        $this->assertInternalType('object', $builder->get('foo'), '->get() returns the service definition associated with the id');
        $builder->set('bar', $bar = new \stdClass());
        $this->assertEquals($bar, $builder->get('bar'), '->get() returns the service associated with the id');
        $builder->register('bar', 'stdClass');
        $this->assertEquals($bar, $builder->get('bar'), '->get() returns the service associated with the id even if a definition has been defined');

        $builder->register('baz', 'stdClass')->setArguments(array(new Reference('baz')));
        try {
            @$builder->get('baz');
            $this->fail('->get() throws a ServiceCircularReferenceException if the service has a circular reference to itself');
        } catch (\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException $e) {
            $this->assertEquals('Circular reference detected for service "baz", path: "baz".', $e->getMessage(), '->get() throws a LogicException if the service has a circular reference to itself');
        }

        $builder->register('foobar', 'stdClass')->setScope('container');
        $this->assertTrue($builder->get('bar') === $builder->get('bar'), '->get() always returns the same instance if the service is shared');
    }

    /**
     * @covers                   \Symfony\Component\DependencyInjection\ContainerBuilder::get
     * @expectedException        \Symfony\Component\DependencyInjection\Exception\RuntimeException
     * @expectedExceptionMessage You have requested a synthetic service ("foo"). The DIC does not know how to construct this service.
     */
    public function testGetUnsetLoadingServiceWhenCreateServiceThrowsAnException()
    {
        $builder = new ContainerBuilder();
        $builder->register('foo', 'stdClass')->setSynthetic(true);

        // we expect a RuntimeException here as foo is synthetic
        try {
            $builder->get('foo');
        } catch (RuntimeException $e) {
        }

        // we must also have the same RuntimeException here
        $builder->get('foo');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::get
     */
    public function testGetReturnsNullOnInactiveScope()
    {
        $builder = new ContainerBuilder();
        $builder->register('foo', 'stdClass')->setScope('request');

        $this->assertNull($builder->get('foo', ContainerInterface::NULL_ON_INVALID_REFERENCE));
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getServiceIds
     */
    public function testGetServiceIds()
    {
        $builder = new ContainerBuilder();
        $builder->register('foo', 'stdClass');
        $builder->bar = $bar = new \stdClass();
        $builder->register('bar', 'stdClass');
        $this->assertEquals(array('foo', 'bar', 'service_container'), $builder->getServiceIds(), '->getServiceIds() returns all defined service ids');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::setAlias
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::hasAlias
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getAlias
     */
    public function testAliases()
    {
        $builder = new ContainerBuilder();
        $builder->register('foo', 'stdClass');
        $builder->setAlias('bar', 'foo');
        $this->assertTrue($builder->hasAlias('bar'), '->hasAlias() returns true if the alias exists');
        $this->assertFalse($builder->hasAlias('foobar'), '->hasAlias() returns false if the alias does not exist');
        $this->assertEquals('foo', (string) $builder->getAlias('bar'), '->getAlias() returns the aliased service');
        $this->assertTrue($builder->has('bar'), '->setAlias() defines a new service');
        $this->assertTrue($builder->get('bar') === $builder->get('foo'), '->setAlias() creates a service that is an alias to another one');

        try {
            $builder->getAlias('foobar');
            $this->fail('->getAlias() throws an InvalidArgumentException if the alias does not exist');
        } catch (\InvalidArgumentException $e) {
            $this->assertEquals('The service alias "foobar" does not exist.', $e->getMessage(), '->getAlias() throws an InvalidArgumentException if the alias does not exist');
        }
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getAliases
     */
    public function testGetAliases()
    {
        $builder = new ContainerBuilder();
        $builder->setAlias('bar', 'foo');
        $builder->setAlias('foobar', 'foo');
        $builder->setAlias('moo', new Alias('foo', false));

        $aliases = $builder->getAliases();
        $this->assertEquals('foo', (string) $aliases['bar']);
        $this->assertTrue($aliases['bar']->isPublic());
        $this->assertEquals('foo', (string) $aliases['foobar']);
        $this->assertEquals('foo', (string) $aliases['moo']);
        $this->assertFalse($aliases['moo']->isPublic());

        $builder->register('bar', 'stdClass');
        $this->assertFalse($builder->hasAlias('bar'));

        $builder->set('foobar', 'stdClass');
        $builder->set('moo', 'stdClass');
        $this->assertCount(0, $builder->getAliases(), '->getAliases() does not return aliased services that have been overridden');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::setAliases
     */
    public function testSetAliases()
    {
        $builder = new ContainerBuilder();
        $builder->setAliases(array('bar' => 'foo', 'foobar' => 'foo'));

        $aliases = $builder->getAliases();
        $this->assertTrue(isset($aliases['bar']));
        $this->assertTrue(isset($aliases['foobar']));
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addAliases
     */
    public function testAddAliases()
    {
        $builder = new ContainerBuilder();
        $builder->setAliases(array('bar' => 'foo'));
        $builder->addAliases(array('foobar' => 'foo'));

        $aliases = $builder->getAliases();
        $this->assertTrue(isset($aliases['bar']));
        $this->assertTrue(isset($aliases['foobar']));
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addCompilerPass
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getCompilerPassConfig
     */
    public function testAddGetCompilerPass()
    {
        $builder = new ContainerBuilder();
        $builder->setResourceTracking(false);
        $builderCompilerPasses = $builder->getCompiler()->getPassConfig()->getPasses();
        $builder->addCompilerPass($this->getMock('Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface'));
        $this->assertEquals(sizeof($builderCompilerPasses) + 1, sizeof($builder->getCompiler()->getPassConfig()->getPasses()));
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
     */
    public function testCreateService()
    {
        $builder = new ContainerBuilder();
        $builder->register('foo1', 'FooClass')->setFile(__DIR__.'/Fixtures/includes/foo.php');
        $this->assertInstanceOf('\FooClass', $builder->get('foo1'), '->createService() requires the file defined by the service definition');
        $builder->register('foo2', 'FooClass')->setFile(__DIR__.'/Fixtures/includes/%file%.php');
        $builder->setParameter('file', 'foo');
        $this->assertInstanceOf('\FooClass', $builder->get('foo2'), '->createService() replaces parameters in the file provided by the service definition');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
     */
    public function testCreateProxyWithRealServiceInstantiator()
    {
        $builder = new ContainerBuilder();

        $builder->register('foo1', 'FooClass')->setFile(__DIR__.'/Fixtures/includes/foo.php');
        $builder->getDefinition('foo1')->setLazy(true);

        $foo1 = $builder->get('foo1');

        $this->assertSame($foo1, $builder->get('foo1'), 'The same proxy is retrieved on multiple subsequent calls');
        $this->assertSame('FooClass', get_class($foo1));
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
     */
    public function testCreateServiceClass()
    {
        $builder = new ContainerBuilder();
        $builder->register('foo1', '%class%');
        $builder->setParameter('class', 'stdClass');
        $this->assertInstanceOf('\stdClass', $builder->get('foo1'), '->createService() replaces parameters in the class provided by the service definition');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
     */
    public function testCreateServiceArguments()
    {
        $builder = new ContainerBuilder();
        $builder->register('bar', 'stdClass');
        $builder->register('foo1', 'FooClass')->addArgument(array('foo' => '%value%', '%value%' => 'foo', new Reference('bar'), '%%unescape_it%%'));
        $builder->setParameter('value', 'bar');
        $this->assertEquals(array('foo' => 'bar', 'bar' => 'foo', $builder->get('bar'), '%unescape_it%'), $builder->get('foo1')->arguments, '->createService() replaces parameters and service references in the arguments provided by the service definition');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
     */
    public function testCreateServiceFactoryMethod()
    {
        $builder = new ContainerBuilder();
        $builder->register('bar', 'stdClass');
        $builder->register('foo1', 'FooClass')->setFactoryClass('FooClass')->setFactoryMethod('getInstance')->addArgument(array('foo' => '%value%', '%value%' => 'foo', new Reference('bar')));
        $builder->setParameter('value', 'bar');
        $this->assertTrue($builder->get('foo1')->called, '->createService() calls the factory method to create the service instance');
        $this->assertEquals(array('foo' => 'bar', 'bar' => 'foo', $builder->get('bar')), $builder->get('foo1')->arguments, '->createService() passes the arguments to the factory method');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
     */
    public function testCreateServiceFactoryService()
    {
        $builder = new ContainerBuilder();
        $builder->register('baz_service')->setFactoryService('baz_factory')->setFactoryMethod('getInstance');
        $builder->register('baz_factory', 'BazClass');

        $this->assertInstanceOf('BazClass', $builder->get('baz_service'));
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
     */
    public function testCreateServiceMethodCalls()
    {
        $builder = new ContainerBuilder();
        $builder->register('bar', 'stdClass');
        $builder->register('foo1', 'FooClass')->addMethodCall('setBar', array(array('%value%', new Reference('bar'))));
        $builder->setParameter('value', 'bar');
        $this->assertEquals(array('bar', $builder->get('bar')), $builder->get('foo1')->bar, '->createService() replaces the values in the method calls arguments');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
     */
    public function testCreateServiceConfigurator()
    {
        $builder = new ContainerBuilder();
        $builder->register('foo1', 'FooClass')->setConfigurator('sc_configure');
        $this->assertTrue($builder->get('foo1')->configured, '->createService() calls the configurator');

        $builder->register('foo2', 'FooClass')->setConfigurator(array('%class%', 'configureStatic'));
        $builder->setParameter('class', 'BazClass');
        $this->assertTrue($builder->get('foo2')->configured, '->createService() calls the configurator');

        $builder->register('baz', 'BazClass');
        $builder->register('foo3', 'FooClass')->setConfigurator(array(new Reference('baz'), 'configure'));
        $this->assertTrue($builder->get('foo3')->configured, '->createService() calls the configurator');

        $builder->register('foo4', 'FooClass')->setConfigurator('foo');
        try {
            $builder->get('foo4');
            $this->fail('->createService() throws an InvalidArgumentException if the configure callable is not a valid callable');
        } catch (\InvalidArgumentException $e) {
            $this->assertEquals('The configure callable for class "FooClass" is not a callable.', $e->getMessage(), '->createService() throws an InvalidArgumentException if the configure callable is not a valid callable');
        }
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::createService
     * @expectedException \RuntimeException
     */
    public function testCreateSyntheticService()
    {
        $builder = new ContainerBuilder();
        $builder->register('foo', 'FooClass')->setSynthetic(true);
        $builder->get('foo');
    }

    public function testCreateServiceWithExpression()
    {
        $builder = new ContainerBuilder();
        $builder->setParameter('bar', 'bar');
        $builder->register('bar', 'BarClass');
        $builder->register('foo', 'FooClass')->addArgument(array('foo' => new Expression('service("bar").foo ~ parameter("bar")')));
        $this->assertEquals('foobar', $builder->get('foo')->arguments['foo']);
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::resolveServices
     */
    public function testResolveServices()
    {
        $builder = new ContainerBuilder();
        $builder->register('foo', 'FooClass');
        $this->assertEquals($builder->get('foo'), $builder->resolveServices(new Reference('foo')), '->resolveServices() resolves service references to service instances');
        $this->assertEquals(array('foo' => array('foo', $builder->get('foo'))), $builder->resolveServices(array('foo' => array('foo', new Reference('foo')))), '->resolveServices() resolves service references to service instances in nested arrays');
        $this->assertEquals($builder->get('foo'), $builder->resolveServices(new Expression('service("foo")')), '->resolveServices() resolves expressions');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::merge
     */
    public function testMerge()
    {
        $container = new ContainerBuilder(new ParameterBag(array('bar' => 'foo')));
        $container->setResourceTracking(false);
        $config = new ContainerBuilder(new ParameterBag(array('foo' => 'bar')));
        $container->merge($config);
        $this->assertEquals(array('bar' => 'foo', 'foo' => 'bar'), $container->getParameterBag()->all(), '->merge() merges current parameters with the loaded ones');

        $container = new ContainerBuilder(new ParameterBag(array('bar' => 'foo')));
        $container->setResourceTracking(false);
        $config = new ContainerBuilder(new ParameterBag(array('foo' => '%bar%')));
        $container->merge($config);
        $container->compile();
        $this->assertEquals(array('bar' => 'foo', 'foo' => 'foo'), $container->getParameterBag()->all(), '->merge() evaluates the values of the parameters towards already defined ones');

        $container = new ContainerBuilder(new ParameterBag(array('bar' => 'foo')));
        $container->setResourceTracking(false);
        $config = new ContainerBuilder(new ParameterBag(array('foo' => '%bar%', 'baz' => '%foo%')));
        $container->merge($config);
        $container->compile();
        $this->assertEquals(array('bar' => 'foo', 'foo' => 'foo', 'baz' => 'foo'), $container->getParameterBag()->all(), '->merge() evaluates the values of the parameters towards already defined ones');

        $container = new ContainerBuilder();
        $container->setResourceTracking(false);
        $container->register('foo', 'FooClass');
        $container->register('bar', 'BarClass');
        $config = new ContainerBuilder();
        $config->setDefinition('baz', new Definition('BazClass'));
        $config->setAlias('alias_for_foo', 'foo');
        $container->merge($config);
        $this->assertEquals(array('foo', 'bar', 'baz'), array_keys($container->getDefinitions()), '->merge() merges definitions already defined ones');

        $aliases = $container->getAliases();
        $this->assertTrue(isset($aliases['alias_for_foo']));
        $this->assertEquals('foo', (string) $aliases['alias_for_foo']);

        $container = new ContainerBuilder();
        $container->setResourceTracking(false);
        $container->register('foo', 'FooClass');
        $config->setDefinition('foo', new Definition('BazClass'));
        $container->merge($config);
        $this->assertEquals('BazClass', $container->getDefinition('foo')->getClass(), '->merge() overrides already defined services');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::merge
     * @expectedException \LogicException
     */
    public function testMergeLogicException()
    {
        $container = new ContainerBuilder();
        $container->setResourceTracking(false);
        $container->compile();
        $container->merge(new ContainerBuilder());
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::findTaggedServiceIds
     */
    public function testfindTaggedServiceIds()
    {
        $builder = new ContainerBuilder();
        $builder
            ->register('foo', 'FooClass')
            ->addTag('foo', array('foo' => 'foo'))
            ->addTag('bar', array('bar' => 'bar'))
            ->addTag('foo', array('foofoo' => 'foofoo'))
        ;
        $this->assertEquals($builder->findTaggedServiceIds('foo'), array(
            'foo' => array(
                array('foo' => 'foo'),
                array('foofoo' => 'foofoo'),
            )
        ), '->findTaggedServiceIds() returns an array of service ids and its tag attributes');
        $this->assertEquals(array(), $builder->findTaggedServiceIds('foobar'), '->findTaggedServiceIds() returns an empty array if there is annotated services');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::findDefinition
     */
    public function testFindDefinition()
    {
        $container = new ContainerBuilder();
        $container->setDefinition('foo', $definition = new Definition('FooClass'));
        $container->setAlias('bar', 'foo');
        $container->setAlias('foobar', 'bar');
        $this->assertEquals($definition, $container->findDefinition('foobar'), '->findDefinition() returns a Definition');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addObjectResource
     */
    public function testAddObjectResource()
    {
        $container = new ContainerBuilder();

        $container->setResourceTracking(false);
        $container->addObjectResource(new \BarClass());

        $this->assertEmpty($container->getResources(), 'No resources get registered without resource tracking');

        $container->setResourceTracking(true);
        $container->addObjectResource(new \BarClass());

        $resources = $container->getResources();

        $this->assertCount(1, $resources, '1 resource was registered');

        /* @var $resource \Symfony\Component\Config\Resource\FileResource */
        $resource = end($resources);

        $this->assertInstanceOf('Symfony\Component\Config\Resource\FileResource', $resource);
        $this->assertSame(realpath(__DIR__.'/Fixtures/includes/classes.php'), realpath($resource->getResource()));
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addClassResource
     */
    public function testAddClassResource()
    {
        $container = new ContainerBuilder();

        $container->setResourceTracking(false);
        $container->addClassResource(new \ReflectionClass('BarClass'));

        $this->assertEmpty($container->getResources(), 'No resources get registered without resource tracking');

        $container->setResourceTracking(true);
        $container->addClassResource(new \ReflectionClass('BarClass'));

        $resources = $container->getResources();

        $this->assertCount(1, $resources, '1 resource was registered');

        /* @var $resource \Symfony\Component\Config\Resource\FileResource */
        $resource = end($resources);

        $this->assertInstanceOf('Symfony\Component\Config\Resource\FileResource', $resource);
        $this->assertSame(realpath(__DIR__.'/Fixtures/includes/classes.php'), realpath($resource->getResource()));
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::compile
     */
    public function testCompilesClassDefinitionsOfLazyServices()
    {
        $container = new ContainerBuilder();

        $this->assertEmpty($container->getResources(), 'No resources get registered without resource tracking');

        $container->register('foo', 'BarClass');
        $container->getDefinition('foo')->setLazy(true);

        $container->compile();

        $classesPath       = realpath(__DIR__.'/Fixtures/includes/classes.php');
        $matchingResources = array_filter(
            $container->getResources(),
            function (ResourceInterface $resource) use ($classesPath) {
                return $resource instanceof FileResource && $classesPath === realpath($resource->getResource());
            }
        );

        $this->assertNotEmpty($matchingResources);
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getResources
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::addResource
     */
    public function testResources()
    {
        $container = new ContainerBuilder();
        $container->addResource($a = new FileResource(__DIR__.'/Fixtures/xml/services1.xml'));
        $container->addResource($b = new FileResource(__DIR__.'/Fixtures/xml/services2.xml'));
        $resources = array();
        foreach ($container->getResources() as $resource) {
            if (false === strpos($resource, '.php')) {
                $resources[] = $resource;
            }
        }
        $this->assertEquals(array($a, $b), $resources, '->getResources() returns an array of resources read for the current configuration');
        $this->assertSame($container, $container->setResources(array()));
        $this->assertEquals(array(), $container->getResources());
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::registerExtension
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getExtension
     */
    public function testExtension()
    {
        $container = new ContainerBuilder();
        $container->setResourceTracking(false);

        $container->registerExtension($extension = new \ProjectExtension());
        $this->assertTrue($container->getExtension('project') === $extension, '->registerExtension() registers an extension');

        $this->setExpectedException('LogicException');
        $container->getExtension('no_registered');
    }

    public function testRegisteredButNotLoadedExtension()
    {
        $extension = $this->getMock('Symfony\\Component\\DependencyInjection\\Extension\\ExtensionInterface');
        $extension->expects($this->once())->method('getAlias')->will($this->returnValue('project'));
        $extension->expects($this->never())->method('load');

        $container = new ContainerBuilder();
        $container->setResourceTracking(false);
        $container->registerExtension($extension);
        $container->compile();
    }

    public function testRegisteredAndLoadedExtension()
    {
        $extension = $this->getMock('Symfony\\Component\\DependencyInjection\\Extension\\ExtensionInterface');
        $extension->expects($this->exactly(2))->method('getAlias')->will($this->returnValue('project'));
        $extension->expects($this->once())->method('load')->with(array(array('foo' => 'bar')));

        $container = new ContainerBuilder();
        $container->setResourceTracking(false);
        $container->registerExtension($extension);
        $container->loadFromExtension('project', array('foo' => 'bar'));
        $container->compile();
    }

    public function testPrivateServiceUser()
    {
        $fooDefinition     = new Definition('BarClass');
        $fooUserDefinition = new Definition('BarUserClass', array(new Reference('bar')));
        $container         = new ContainerBuilder();
        $container->setResourceTracking(false);

        $fooDefinition->setPublic(false);

        $container->addDefinitions(array(
            'bar'       => $fooDefinition,
            'bar_user'  => $fooUserDefinition
        ));

        $container->compile();
        $this->assertInstanceOf('BarClass', $container->get('bar_user')->bar);
    }

    /**
     * @expectedException \BadMethodCallException
     */
    public function testThrowsExceptionWhenSetServiceOnAFrozenContainer()
    {
        $container = new ContainerBuilder();
        $container->setResourceTracking(false);
        $container->setDefinition('a', new Definition('stdClass'));
        $container->compile();
        $container->set('a', new \stdClass());
    }

    /**
     * @expectedException \BadMethodCallException
     */
    public function testThrowsExceptionWhenAddServiceOnAFrozenContainer()
    {
        $container = new ContainerBuilder();
        $container->compile();
        $container->set('a', new \stdClass());
    }

    public function testNoExceptionWhenSetSyntheticServiceOnAFrozenContainer()
    {
        $container = new ContainerBuilder();
        $def = new Definition('stdClass');
        $def->setSynthetic(true);
        $container->setDefinition('a', $def);
        $container->compile();
        $container->set('a', $a = new \stdClass());
        $this->assertEquals($a, $container->get('a'));
    }

    public function testSetOnSynchronizedService()
    {
        $container = new ContainerBuilder();
        $container->register('baz', 'BazClass')
            ->setSynchronized(true)
        ;
        $container->register('bar', 'BarClass')
            ->addMethodCall('setBaz', array(new Reference('baz')))
        ;

        $container->set('baz', $baz = new \BazClass());
        $this->assertSame($baz, $container->get('bar')->getBaz());

        $container->set('baz', $baz = new \BazClass());
        $this->assertSame($baz, $container->get('bar')->getBaz());
    }

    public function testSynchronizedServiceWithScopes()
    {
        $container = new ContainerBuilder();
        $container->addScope(new Scope('foo'));
        $container->register('baz', 'BazClass')
            ->setSynthetic(true)
            ->setSynchronized(true)
            ->setScope('foo')
        ;
        $container->register('bar', 'BarClass')
            ->addMethodCall('setBaz', array(new Reference('baz', ContainerInterface::NULL_ON_INVALID_REFERENCE, false)))
        ;
        $container->compile();

        $container->enterScope('foo');
        $container->set('baz', $outerBaz = new \BazClass(), 'foo');
        $this->assertSame($outerBaz, $container->get('bar')->getBaz());

        $container->enterScope('foo');
        $container->set('baz', $innerBaz = new \BazClass(), 'foo');
        $this->assertSame($innerBaz, $container->get('bar')->getBaz());
        $container->leaveScope('foo');

        $this->assertNotSame($innerBaz, $container->get('bar')->getBaz());
        $this->assertSame($outerBaz, $container->get('bar')->getBaz());

        $container->leaveScope('foo');
    }

    /**
     * @expectedException \BadMethodCallException
     */
    public function testThrowsExceptionWhenSetDefinitionOnAFrozenContainer()
    {
        $container = new ContainerBuilder();
        $container->setResourceTracking(false);
        $container->compile();
        $container->setDefinition('a', new Definition());
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::getExtensionConfig
     * @covers Symfony\Component\DependencyInjection\ContainerBuilder::prependExtensionConfig
     */
    public function testExtensionConfig()
    {
        $container = new ContainerBuilder();

        $configs = $container->getExtensionConfig('foo');
        $this->assertEmpty($configs);

        $first = array('foo' => 'bar');
        $container->prependExtensionConfig('foo', $first);
        $configs = $container->getExtensionConfig('foo');
        $this->assertEquals(array($first), $configs);

        $second = array('ding' => 'dong');
        $container->prependExtensionConfig('foo', $second);
        $configs = $container->getExtensionConfig('foo');
        $this->assertEquals(array($second, $first), $configs);
    }

    public function testLazyLoadedService()
    {
        $loader = new ClosureLoader($container = new ContainerBuilder());
        $loader->load(function (ContainerBuilder $container) {
                $container->set('a', new \BazClass());
                $definition = new Definition('BazClass');
                $definition->setLazy(true);
                $container->setDefinition('a', $definition);
            }
        );

        $container->setResourceTracking(true);

        $container->compile();

        $class = new \BazClass();
        $reflectionClass = new \ReflectionClass($class);

        $r = new \ReflectionProperty($container, 'resources');
        $r->setAccessible(true);
        $resources = $r->getValue($container);

        $classInList = false;
        foreach ($resources as $resource) {
            if ($resource->getResource() === $reflectionClass->getFileName()) {
                $classInList = true;
                break;
            }
        }

        $this->assertEquals(true, $classInList);
    }
}

class FooClass {}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests;

use Symfony\Component\DependencyInjection\Reference;

class ReferenceTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\DependencyInjection\Reference::__construct
     */
    public function testConstructor()
    {
        $ref = new Reference('foo');
        $this->assertEquals('foo', (string) $ref, '__construct() sets the id of the reference, which is used for the __toString() method');
    }

    public function testCaseInsensitive()
    {
        $ref = new Reference('FooBar');
        $this->assertEquals('foobar', (string) $ref, 'the id is lowercased as the container is case insensitive');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Compiler;

use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass;
use Symfony\Component\DependencyInjection\Compiler\Compiler;
use Symfony\Component\DependencyInjection\Compiler\RepeatedPass;
use Symfony\Component\DependencyInjection\Compiler\RemoveUnusedDefinitionsPass;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class RemoveUnusedDefinitionsPassTest extends \PHPUnit_Framework_TestCase
{
    public function testProcess()
    {
        $container = new ContainerBuilder();
        $container
            ->register('foo')
            ->setPublic(false)
        ;
        $container
            ->register('bar')
            ->setPublic(false)
        ;
        $container
            ->register('moo')
            ->setArguments(array(new Reference('bar')))
        ;

        $this->process($container);

        $this->assertFalse($container->hasDefinition('foo'));
        $this->assertTrue($container->hasDefinition('bar'));
        $this->assertTrue($container->hasDefinition('moo'));
    }

    public function testProcessRemovesUnusedDefinitionsRecursively()
    {
        $container = new ContainerBuilder();
        $container
            ->register('foo')
            ->setPublic(false)
        ;
        $container
            ->register('bar')
            ->setArguments(array(new Reference('foo')))
            ->setPublic(false)
        ;

        $this->process($container);

        $this->assertFalse($container->hasDefinition('foo'));
        $this->assertFalse($container->hasDefinition('bar'));
    }

    public function testProcessWorksWithInlinedDefinitions()
    {
        $container = new ContainerBuilder();
        $container
            ->register('foo')
            ->setPublic(false)
        ;
        $container
            ->register('bar')
            ->setArguments(array(new Definition(null, array(new Reference('foo')))))
        ;

        $this->process($container);

        $this->assertTrue($container->hasDefinition('foo'));
        $this->assertTrue($container->hasDefinition('bar'));
    }

    protected function process(ContainerBuilder $container)
    {
        $repeatedPass = new RepeatedPass(array(new AnalyzeServiceReferencesPass(), new RemoveUnusedDefinitionsPass()));
        $repeatedPass->process($container);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Compiler;

use Symfony\Component\DependencyInjection\Compiler\ReplaceAliasByActualDefinitionPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;

class ReplaceAliasByActualDefinitionPassTest extends \PHPUnit_Framework_TestCase
{
    public function testProcess()
    {
        $container = new ContainerBuilder();

        $container->register('a', '\stdClass');

        $bDefinition = new Definition('\stdClass');
        $bDefinition->setPublic(false);
        $container->setDefinition('b', $bDefinition);

        $container->setAlias('a_alias', 'a');
        $container->setAlias('b_alias', 'b');

        $this->process($container);

        $this->assertTrue($container->has('a'), '->process() does nothing to public definitions.');
        $this->assertTrue($container->hasAlias('a_alias'));
        $this->assertFalse($container->has('b'), '->process() removes non-public definitions.');
        $this->assertTrue(
            $container->has('b_alias') && !$container->hasAlias('b_alias'),
            '->process() replaces alias to actual.'
        );
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testProcessWithInvalidAlias()
    {
        $container = new ContainerBuilder();
        $container->setAlias('a_alias', 'a');
        $this->process($container);
    }

    protected function process(ContainerBuilder $container)
    {
        $pass = new ReplaceAliasByActualDefinitionPass();
        $pass->process($container);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Compiler;

use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Compiler\Compiler;
use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass;
use Symfony\Component\DependencyInjection\Compiler\RepeatedPass;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class AnalyzeServiceReferencesPassTest extends \PHPUnit_Framework_TestCase
{
    public function testProcess()
    {
        $container = new ContainerBuilder();

        $a = $container
            ->register('a')
            ->addArgument($ref1 = new Reference('b'))
        ;

        $b = $container
            ->register('b')
            ->addMethodCall('setA', array($ref2 = new Reference('a')))
        ;

        $c = $container
            ->register('c')
            ->addArgument($ref3 = new Reference('a'))
            ->addArgument($ref4 = new Reference('b'))
        ;

        $d = $container
            ->register('d')
            ->setProperty('foo', $ref5 = new Reference('b'))
        ;

        $e = $container
            ->register('e')
            ->setConfigurator(array($ref6 = new Reference('b'), 'methodName'))
        ;

        $graph = $this->process($container);

        $this->assertCount(4, $edges = $graph->getNode('b')->getInEdges());

        $this->assertSame($ref1, $edges[0]->getValue());
        $this->assertSame($ref4, $edges[1]->getValue());
        $this->assertSame($ref5, $edges[2]->getValue());
        $this->assertSame($ref6, $edges[3]->getValue());
    }

    public function testProcessDetectsReferencesFromInlinedDefinitions()
    {
        $container = new ContainerBuilder();

        $container
            ->register('a')
        ;

        $container
            ->register('b')
            ->addArgument(new Definition(null, array($ref = new Reference('a'))))
        ;

        $graph = $this->process($container);

        $this->assertCount(1, $refs = $graph->getNode('a')->getInEdges());
        $this->assertSame($ref, $refs[0]->getValue());
    }

    public function testProcessDoesNotSaveDuplicateReferences()
    {
        $container = new ContainerBuilder();

        $container
            ->register('a')
        ;
        $container
            ->register('b')
            ->addArgument(new Definition(null, array($ref1 = new Reference('a'))))
            ->addArgument(new Definition(null, array($ref2 = new Reference('a'))))
        ;

        $graph = $this->process($container);

        $this->assertCount(2, $graph->getNode('a')->getInEdges());
    }

    protected function process(ContainerBuilder $container)
    {
        $pass = new RepeatedPass(array(new AnalyzeServiceReferencesPass()));
        $pass->process($container);

        return $container->getCompiler()->getServiceReferenceGraph();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Compiler;

use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Compiler\ResolveReferencesToAliasesPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class ResolveReferencesToAliasesPassTest extends \PHPUnit_Framework_TestCase
{
    public function testProcess()
    {
        $container = new ContainerBuilder();
        $container->setAlias('bar', 'foo');
        $def = $container
            ->register('moo')
            ->setArguments(array(new Reference('bar')))
        ;

        $this->process($container);

        $arguments = $def->getArguments();
        $this->assertEquals('foo', (string) $arguments[0]);
    }

    public function testProcessRecursively()
    {
        $container = new ContainerBuilder();
        $container->setAlias('bar', 'foo');
        $container->setAlias('moo', 'bar');
        $def = $container
            ->register('foobar')
            ->setArguments(array(new Reference('moo')))
        ;

        $this->process($container);

        $arguments = $def->getArguments();
        $this->assertEquals('foo', (string) $arguments[0]);
    }

    protected function process(ContainerBuilder $container)
    {
        $pass = new ResolveReferencesToAliasesPass();
        $pass->process($container);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Compiler;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Symfony\Component\DependencyInjection\Compiler\ResolveDefinitionTemplatesPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class ResolveDefinitionTemplatesPassTest extends \PHPUnit_Framework_TestCase
{
    public function testProcess()
    {
        $container = new ContainerBuilder();
        $container->register('parent', 'foo')->setArguments(array('moo', 'b'))->setProperty('foo', 'moo');
        $container->setDefinition('child', new DefinitionDecorator('parent'))
            ->replaceArgument(0, 'a')
            ->setProperty('foo', 'bar')
            ->setClass('bar')
        ;

        $this->process($container);

        $def = $container->getDefinition('child');
        $this->assertNotInstanceOf('Symfony\Component\DependencyInjection\DefinitionDecorator', $def);
        $this->assertEquals('bar', $def->getClass());
        $this->assertEquals(array('a', 'b'), $def->getArguments());
        $this->assertEquals(array('foo' => 'bar'), $def->getProperties());
    }

    public function testProcessAppendsMethodCallsAlways()
    {
        $container = new ContainerBuilder();

        $container
            ->register('parent')
            ->addMethodCall('foo', array('bar'))
        ;

        $container
            ->setDefinition('child', new DefinitionDecorator('parent'))
            ->addMethodCall('bar', array('foo'))
        ;

        $this->process($container);

        $def = $container->getDefinition('child');
        $this->assertEquals(array(
            array('foo', array('bar')),
            array('bar', array('foo')),
        ), $def->getMethodCalls());
    }

    public function testProcessDoesNotCopyAbstract()
    {
        $container = new ContainerBuilder();

        $container
            ->register('parent')
            ->setAbstract(true)
        ;

        $container
            ->setDefinition('child', new DefinitionDecorator('parent'))
        ;

        $this->process($container);

        $def = $container->getDefinition('child');
        $this->assertFalse($def->isAbstract());
    }

    public function testProcessDoesNotCopyScope()
    {
        $container = new ContainerBuilder();

        $container
            ->register('parent')
            ->setScope('foo')
        ;

        $container
            ->setDefinition('child', new DefinitionDecorator('parent'))
        ;

        $this->process($container);

        $def = $container->getDefinition('child');
        $this->assertEquals(ContainerInterface::SCOPE_CONTAINER, $def->getScope());
    }

    public function testProcessDoesNotCopyTags()
    {
        $container = new ContainerBuilder();

        $container
            ->register('parent')
            ->addTag('foo')
        ;

        $container
            ->setDefinition('child', new DefinitionDecorator('parent'))
        ;

        $this->process($container);

        $def = $container->getDefinition('child');
        $this->assertEquals(array(), $def->getTags());
    }

    public function testProcessHandlesMultipleInheritance()
    {
        $container = new ContainerBuilder();

        $container
            ->register('parent', 'foo')
            ->setArguments(array('foo', 'bar', 'c'))
        ;

        $container
            ->setDefinition('child2', new DefinitionDecorator('child1'))
            ->replaceArgument(1, 'b')
        ;

        $container
            ->setDefinition('child1', new DefinitionDecorator('parent'))
            ->replaceArgument(0, 'a')
        ;

        $this->process($container);

        $def = $container->getDefinition('child2');
        $this->assertEquals(array('a', 'b', 'c'), $def->getArguments());
        $this->assertEquals('foo', $def->getClass());
    }

    public function testSetLazyOnServiceHasParent()
    {
        $container = new ContainerBuilder();

        $container->register('parent','stdClass');

        $container->setDefinition('child1',new DefinitionDecorator('parent'))
            ->setLazy(true)
        ;

        $this->process($container);

        $this->assertTrue($container->getDefinition('child1')->isLazy());
    }

    public function testSetLazyOnServiceIsParent()
    {
        $container = new ContainerBuilder();

        $container->register('parent','stdClass')
            ->setLazy(true)
        ;

        $container->setDefinition('child1',new DefinitionDecorator('parent'));

        $this->process($container);

        $this->assertTrue($container->getDefinition('child1')->isLazy());
    }

    protected function process(ContainerBuilder $container)
    {
        $pass = new ResolveDefinitionTemplatesPass();
        $pass->process($container);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Compiler;

use Symfony\Component\DependencyInjection\Reference;

use Symfony\Component\DependencyInjection\Compiler\CheckCircularReferencesPass;

use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass;

use Symfony\Component\DependencyInjection\Compiler\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;

class CheckCircularReferencesPassTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException
     */
    public function testProcess()
    {
        $container = new ContainerBuilder();
        $container->register('a')->addArgument(new Reference('b'));
        $container->register('b')->addArgument(new Reference('a'));

        $this->process($container);
    }

    /**
     * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException
     */
    public function testProcessWithAliases()
    {
        $container = new ContainerBuilder();
        $container->register('a')->addArgument(new Reference('b'));
        $container->setAlias('b', 'c');
        $container->setAlias('c', 'a');

        $this->process($container);
    }

    /**
     * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException
     */
    public function testProcessDetectsIndirectCircularReference()
    {
        $container = new ContainerBuilder();
        $container->register('a')->addArgument(new Reference('b'));
        $container->register('b')->addArgument(new Reference('c'));
        $container->register('c')->addArgument(new Reference('a'));

        $this->process($container);
    }

    /**
     * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException
     */
    public function testDeepCircularReference()
    {
        $container = new ContainerBuilder();
        $container->register('a')->addArgument(new Reference('b'));
        $container->register('b')->addArgument(new Reference('c'));
        $container->register('c')->addArgument(new Reference('b'));

        $this->process($container);
    }

    public function testProcessIgnoresMethodCalls()
    {
        $container = new ContainerBuilder();
        $container->register('a')->addArgument(new Reference('b'));
        $container->register('b')->addMethodCall('setA', array(new Reference('a')));

        $this->process($container);
    }

    protected function process(ContainerBuilder $container)
    {
        $compiler = new Compiler();
        $passConfig = $compiler->getPassConfig();
        $passConfig->setOptimizationPasses(array(
            new AnalyzeServiceReferencesPass(true),
            new CheckCircularReferencesPass(),
        ));
        $passConfig->setRemovingPasses(array());

        $compiler->compile($container);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Compiler;

use Symfony\Component\DependencyInjection\Compiler\CheckDefinitionValidityPass;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class CheckDefinitionValidityPassTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
     */
    public function testProcessDetectsSyntheticNonPublicDefinitions()
    {
        $container = new ContainerBuilder();
        $container->register('a')->setSynthetic(true)->setPublic(false);

        $this->process($container);
    }

    /**
     * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
     */
    public function testProcessDetectsSyntheticPrototypeDefinitions()
    {
        $container = new ContainerBuilder();
        $container->register('a')->setSynthetic(true)->setScope(ContainerInterface::SCOPE_PROTOTYPE);

        $this->process($container);
    }

    /**
     * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
     */
    public function testProcessDetectsNonSyntheticNonAbstractDefinitionWithoutClass()
    {
        $container = new ContainerBuilder();
        $container->register('a')->setSynthetic(false)->setAbstract(false);

        $this->process($container);
    }

    public function testProcess()
    {
        $container = new ContainerBuilder();
        $container->register('a', 'class');
        $container->register('b', 'class')->setSynthetic(true)->setPublic(true);
        $container->register('c', 'class')->setAbstract(true);
        $container->register('d', 'class')->setSynthetic(true);

        $this->process($container);
    }

    public function testValidTags()
    {
        $container = new ContainerBuilder();
        $container->register('a', 'class')->addTag('foo', array('bar' => 'baz'));
        $container->register('b', 'class')->addTag('foo', array('bar' => null));
        $container->register('c', 'class')->addTag('foo', array('bar' => 1));
        $container->register('d', 'class')->addTag('foo', array('bar' => 1.1));

        $this->process($container);
    }

    /**
     * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
     */
    public function testInvalidTags()
    {
        $container = new ContainerBuilder();
        $container->register('a', 'class')->addTag('foo', array('bar' => array('baz' => 'baz')));

        $this->process($container);
    }

    protected function process(ContainerBuilder $container)
    {
        $pass = new CheckDefinitionValidityPass();
        $pass->process($container);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Compiler;

use Symfony\Component\DependencyInjection\Definition;

use Symfony\Component\DependencyInjection\Compiler\CheckExceptionOnInvalidReferenceBehaviorPass;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class CheckExceptionOnInvalidReferenceBehaviorPassTest extends \PHPUnit_Framework_TestCase
{
    public function testProcess()
    {
        $container = new ContainerBuilder();

        $container
            ->register('a', '\stdClass')
            ->addArgument(new Reference('b'))
        ;
        $container->register('b', '\stdClass');
    }

    /**
     * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException
     */
    public function testProcessThrowsExceptionOnInvalidReference()
    {
        $container = new ContainerBuilder();

        $container
            ->register('a', '\stdClass')
            ->addArgument(new Reference('b'))
        ;

        $this->process($container);
    }

    /**
     * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException
     */
    public function testProcessThrowsExceptionOnInvalidReferenceFromInlinedDefinition()
    {
        $container = new ContainerBuilder();

        $def = new Definition();
        $def->addArgument(new Reference('b'));

        $container
            ->register('a', '\stdClass')
            ->addArgument($def)
        ;

        $this->process($container);
    }

    private function process(ContainerBuilder $container)
    {
        $pass = new CheckExceptionOnInvalidReferenceBehaviorPass();
        $pass->process($container);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Compiler;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Compiler\ResolveInvalidReferencesPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class ResolveInvalidReferencesPassTest extends \PHPUnit_Framework_TestCase
{
    public function testProcess()
    {
        $container = new ContainerBuilder();
        $def = $container
            ->register('foo')
            ->setArguments(array(new Reference('bar', ContainerInterface::NULL_ON_INVALID_REFERENCE)))
            ->addMethodCall('foo', array(new Reference('moo', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)))
        ;

        $this->process($container);

        $arguments = $def->getArguments();
        $this->assertNull($arguments[0]);
        $this->assertCount(0, $def->getMethodCalls());
    }

    public function testProcessIgnoreNonExistentServices()
    {
        $container = new ContainerBuilder();
        $def = $container
            ->register('foo')
            ->setArguments(array(new Reference('bar')))
        ;

        $this->process($container);

        $arguments = $def->getArguments();
        $this->assertEquals('bar', (string) $arguments[0]);
    }

    public function testProcessRemovesPropertiesOnInvalid()
    {
        $container = new ContainerBuilder();
        $def = $container
            ->register('foo')
            ->setProperty('foo', new Reference('bar', ContainerInterface::IGNORE_ON_INVALID_REFERENCE))
        ;

        $this->process($container);

        $this->assertEquals(array(), $def->getProperties());
    }

    public function testStrictFlagIsPreserved()
    {
        $container = new ContainerBuilder();
        $container->register('bar');
        $def = $container
            ->register('foo')
            ->addArgument(new Reference('bar', ContainerInterface::NULL_ON_INVALID_REFERENCE, false))
        ;

        $this->process($container);

        $this->assertFalse($def->getArgument(0)->isStrict());
    }

    protected function process(ContainerBuilder $container)
    {
        $pass = new ResolveInvalidReferencesPass();
        $pass->process($container);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Compiler;

use Symfony\Component\DependencyInjection\Scope;

use Symfony\Component\DependencyInjection\Compiler\CheckReferenceValidityPass;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class CheckReferenceValidityPassTest extends \PHPUnit_Framework_TestCase
{
    public function testProcessIgnoresScopeWideningIfNonStrictReference()
    {
        $container = new ContainerBuilder();
        $container->register('a')->addArgument(new Reference('b', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false));
        $container->register('b')->setScope('prototype');

        $this->process($container);
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testProcessDetectsScopeWidening()
    {
        $container = new ContainerBuilder();
        $container->register('a')->addArgument(new Reference('b'));
        $container->register('b')->setScope('prototype');

        $this->process($container);
    }

    public function testProcessIgnoresCrossScopeHierarchyReferenceIfNotStrict()
    {
        $container = new ContainerBuilder();
        $container->addScope(new Scope('a'));
        $container->addScope(new Scope('b'));

        $container->register('a')->setScope('a')->addArgument(new Reference('b', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false));
        $container->register('b')->setScope('b');

        $this->process($container);
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testProcessDetectsCrossScopeHierarchyReference()
    {
        $container = new ContainerBuilder();
        $container->addScope(new Scope('a'));
        $container->addScope(new Scope('b'));

        $container->register('a')->setScope('a')->addArgument(new Reference('b'));
        $container->register('b')->setScope('b');

        $this->process($container);
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testProcessDetectsReferenceToAbstractDefinition()
    {
        $container = new ContainerBuilder();

        $container->register('a')->setAbstract(true);
        $container->register('b')->addArgument(new Reference('a'));

        $this->process($container);
    }

    public function testProcess()
    {
        $container = new ContainerBuilder();
        $container->register('a')->addArgument(new Reference('b'));
        $container->register('b');

        $this->process($container);
    }

    protected function process(ContainerBuilder $container)
    {
        $pass = new CheckReferenceValidityPass();
        $pass->process($container);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Compiler;

use Symfony\Component\DependencyInjection\Scope;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass;
use Symfony\Component\DependencyInjection\Compiler\RepeatedPass;
use Symfony\Component\DependencyInjection\Compiler\InlineServiceDefinitionsPass;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class InlineServiceDefinitionsPassTest extends \PHPUnit_Framework_TestCase
{
    public function testProcess()
    {
        $container = new ContainerBuilder();
        $container
            ->register('inlinable.service')
            ->setPublic(false)
        ;

        $container
            ->register('service')
            ->setArguments(array(new Reference('inlinable.service')))
        ;

        $this->process($container);

        $arguments = $container->getDefinition('service')->getArguments();
        $this->assertInstanceOf('Symfony\Component\DependencyInjection\Definition', $arguments[0]);
        $this->assertSame($container->getDefinition('inlinable.service'), $arguments[0]);
    }

    public function testProcessDoesNotInlineWhenAliasedServiceIsNotOfPrototypeScope()
    {
        $container = new ContainerBuilder();
        $container
            ->register('foo')
            ->setPublic(false)
        ;
        $container->setAlias('moo', 'foo');

        $container
            ->register('service')
            ->setArguments(array($ref = new Reference('foo')))
        ;

        $this->process($container);

        $arguments = $container->getDefinition('service')->getArguments();
        $this->assertSame($ref, $arguments[0]);
    }

    public function testProcessDoesInlineServiceOfPrototypeScope()
    {
        $container = new ContainerBuilder();
        $container
            ->register('foo')
            ->setScope('prototype')
        ;
        $container
            ->register('bar')
            ->setPublic(false)
            ->setScope('prototype')
        ;
        $container->setAlias('moo', 'bar');

        $container
            ->register('service')
            ->setArguments(array(new Reference('foo'), $ref = new Reference('moo'), new Reference('bar')))
        ;

        $this->process($container);

        $arguments = $container->getDefinition('service')->getArguments();
        $this->assertEquals($container->getDefinition('foo'), $arguments[0]);
        $this->assertNotSame($container->getDefinition('foo'), $arguments[0]);
        $this->assertSame($ref, $arguments[1]);
        $this->assertEquals($container->getDefinition('bar'), $arguments[2]);
        $this->assertNotSame($container->getDefinition('bar'), $arguments[2]);
    }

    public function testProcessInlinesIfMultipleReferencesButAllFromTheSameDefinition()
    {
        $container = new ContainerBuilder();

        $a = $container->register('a')->setPublic(false);
        $b = $container
            ->register('b')
            ->addArgument(new Reference('a'))
            ->addArgument(new Definition(null, array(new Reference('a'))))
        ;

        $this->process($container);

        $arguments = $b->getArguments();
        $this->assertSame($a, $arguments[0]);

        $inlinedArguments = $arguments[1]->getArguments();
        $this->assertSame($a, $inlinedArguments[0]);
    }

    public function testProcessInlinesOnlyIfSameScope()
    {
        $container = new ContainerBuilder();

        $container->addScope(new Scope('foo'));
        $a = $container->register('a')->setPublic(false)->setScope('foo');
        $b = $container->register('b')->addArgument(new Reference('a'));

        $this->process($container);
        $arguments = $b->getArguments();
        $this->assertEquals(new Reference('a'), $arguments[0]);
        $this->assertTrue($container->hasDefinition('a'));
    }

    public function testProcessDoesNotInlineWhenServiceIsPrivateButLazy()
    {
        $container = new ContainerBuilder();
        $container
            ->register('foo')
            ->setPublic(false)
            ->setLazy(true)
        ;

        $container
            ->register('service')
            ->setArguments(array($ref = new Reference('foo')))
        ;

        $this->process($container);

        $arguments = $container->getDefinition('service')->getArguments();
        $this->assertSame($ref, $arguments[0]);
    }

    protected function process(ContainerBuilder $container)
    {
        $repeatedPass = new RepeatedPass(array(new AnalyzeServiceReferencesPass(), new InlineServiceDefinitionsPass()));
        $repeatedPass->process($container);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Compiler;

use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;

/**
 * This class tests the integration of the different compiler passes
 */
class IntegrationTest extends \PHPUnit_Framework_TestCase
{
    /**
     * This tests that the following dependencies are correctly processed:
     *
     * A is public, B/C are private
     * A -> C
     * B -> C
     */
    public function testProcessRemovesAndInlinesRecursively()
    {
        $container = new ContainerBuilder();
        $container->setResourceTracking(false);

        $a = $container
            ->register('a', '\stdClass')
            ->addArgument(new Reference('c'))
        ;

        $b = $container
            ->register('b', '\stdClass')
            ->addArgument(new Reference('c'))
            ->setPublic(false)
        ;

        $c = $container
            ->register('c', '\stdClass')
            ->setPublic(false)
        ;

        $container->compile();

        $this->assertTrue($container->hasDefinition('a'));
        $arguments = $a->getArguments();
        $this->assertSame($c, $arguments[0]);
        $this->assertFalse($container->hasDefinition('b'));
        $this->assertFalse($container->hasDefinition('c'));
    }

    public function testProcessInlinesReferencesToAliases()
    {
        $container = new ContainerBuilder();
        $container->setResourceTracking(false);

        $a = $container
            ->register('a', '\stdClass')
            ->addArgument(new Reference('b'))
        ;

        $container->setAlias('b', new Alias('c', false));

        $c = $container
            ->register('c', '\stdClass')
            ->setPublic(false)
        ;

        $container->compile();

        $this->assertTrue($container->hasDefinition('a'));
        $arguments = $a->getArguments();
        $this->assertSame($c, $arguments[0]);
        $this->assertFalse($container->hasAlias('b'));
        $this->assertFalse($container->hasDefinition('c'));
    }

    public function testProcessInlinesWhenThereAreMultipleReferencesButFromTheSameDefinition()
    {
        $container = new ContainerBuilder();
        $container->setResourceTracking(false);

        $container
            ->register('a', '\stdClass')
            ->addArgument(new Reference('b'))
            ->addMethodCall('setC', array(new Reference('c')))
        ;

        $container
            ->register('b', '\stdClass')
            ->addArgument(new Reference('c'))
            ->setPublic(false)
        ;

        $container
            ->register('c', '\stdClass')
            ->setPublic(false)
        ;

        $container->compile();

        $this->assertTrue($container->hasDefinition('a'));
        $this->assertFalse($container->hasDefinition('b'));
        $this->assertFalse($container->hasDefinition('c'), 'Service C was not inlined.');
    }
}
<?php

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;

$container = new ContainerBuilder();
$container->
    register('foo', 'FooClass')->
    addArgument(new Definition('BarClass', array(new Definition('BazClass'))))
;

return $container;
<?php

namespace Container14;

use Symfony\Component\DependencyInjection\ContainerBuilder;

class ProjectServiceContainer extends ContainerBuilder
{
}

return new ProjectServiceContainer();
<?php

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;

$container = new ContainerBuilder();

$factoryDefinition = new Definition('BarClassFactory');
$container->setDefinition('barFactory', $factoryDefinition);

$definition = new Definition();
$definition->setFactoryService('barFactory');
$definition->setFactoryMethod('createBarClass');
$container->setDefinition('bar', $definition);

return $container;

class BarClass
{
    public $foo;

    public function setBar($foo)
    {
        $this->foo = $foo;
    }
}

class BarClassFactory
{
    public function createBarClass()
    {
        return new BarClass();
    }
}
<?php

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;

$container = new ContainerBuilder();
$container->
    register('foo', 'FooClass\\Foo')->
    addArgument('foo<>&bar')->
    addTag('foo"bar\\bar', array('foo' => 'foo"barřž€'))
;

return $container;
<?php

require_once __DIR__.'/../includes/classes.php';

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

$container = new ContainerBuilder();
$container->
    register('foo', 'FooClass')->
    addArgument(new Reference('bar'))
;

return $container;
<?php

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

$container = new ContainerBuilder();
$container->
    register('foo', 'FooClass')->
    addArgument(new Reference('bar'))
;
$container->
    register('bar', 'BarClass')
;
$container->compile();

return $container;
<?php

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;

$container = new ContainerBuilder();
$container->setParameter('cla', 'Fo');
$container->setParameter('ss', 'Class');

$definition = new Definition('%cla%o%ss%');
$container->setDefinition('foo', $definition);

return $container;

if (!class_exists('FooClass')) {
    class FooClass
    {
        public $bar;

        public function setBar($bar)
        {
            $this->bar = $bar;
        }
    }
}
<?php

require_once __DIR__.'/../includes/classes.php';

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Parameter;
use Symfony\Component\ExpressionLanguage\Expression;

$container = new ContainerBuilder();
$container->
    register('foo', 'FooClass')->
    addTag('foo', array('foo' => 'foo'))->
    addTag('foo', array('bar' => 'bar'))->
    setFactoryClass('FooClass')->
    setFactoryMethod('getInstance')->
    setArguments(array('foo', new Reference('foo.baz'), array('%foo%' => 'foo is %foo%', 'foobar' => '%foo%'), true, new Reference('service_container')))->
    setProperties(array('foo' => 'bar', 'moo' => new Reference('foo.baz')))->
    addMethodCall('setBar', array(new Reference('bar')))->
    addMethodCall('initialize')->
    setConfigurator('sc_configure')
;
$container->
    register('bar', 'FooClass')->
    setArguments(array('foo', new Reference('foo.baz'), new Parameter('foo_bar')))->
    setScope('container')->
    setConfigurator(array(new Reference('foo.baz'), 'configure'))
;
$container->
    register('foo.baz', '%baz_class%')->
    setFactoryClass('%baz_class%')->
    setFactoryMethod('getInstance')->
    setConfigurator(array('%baz_class%', 'configureStatic1'))
;
$container->
    register('foo_bar', '%foo_class%')->
    setScope('prototype')
;
$container->getParameterBag()->clear();
$container->getParameterBag()->add(array(
    'baz_class' => 'BazClass',
    'foo_class' => 'FooClass',
    'foo' => 'bar',
));
$container->setAlias('alias_for_foo', 'foo');
$container->setAlias('alias_for_alias', 'alias_for_foo');
$container->
    register('method_call1', 'FooClass')->
    setFile(realpath(__DIR__.'/../includes/foo.php'))->
    addMethodCall('setBar', array(new Reference('foo')))->
    addMethodCall('setBar', array(new Reference('foo2', ContainerInterface::NULL_ON_INVALID_REFERENCE)))->
    addMethodCall('setBar', array(new Reference('foo3', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)))->
    addMethodCall('setBar', array(new Reference('foobaz', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)))->
    addMethodCall('setBar', array(new Expression('service("foo").foo() ~ parameter("foo")')))
;
$container->
    register('factory_service', 'Bar')->
    setFactoryService('foo.baz')->
    setFactoryMethod('getInstance')
;

$container
    ->register('foo_with_inline', 'Foo')
    ->addMethodCall('setBar', array(new Reference('inlined')))
;
$container
    ->register('inlined', 'Bar')
    ->setProperty('pub', 'pub')
    ->addMethodCall('setBaz', array(new Reference('baz')))
    ->setPublic(false)
;
$container
    ->register('baz', 'Baz')
    ->addMethodCall('setFoo', array(new Reference('foo_with_inline')))
;
$container
    ->register('request', 'Request')
    ->setSynthetic(true)
    ->setSynchronized(true)
;
$container
    ->register('depends_on_request', 'stdClass')
    ->addMethodCall('setRequest', array(new Reference('request', ContainerInterface::NULL_ON_INVALID_REFERENCE, false)))
;

return $container;
<?php

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;

$container = new ContainerBuilder(new ParameterBag(array(
    'FOO'    => '%baz%',
    'baz'    => 'bar',
    'bar'    => 'foo is %%foo bar',
    'escape' => '@escapeme',
    'values' => array(true, false, null, 0, 1000.3, 'true', 'false', 'null'),
)));

return $container;
<?php

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;

/**
 * ProjectServiceContainer
 *
 * This class has been auto-generated
 * by the Symfony Dependency Injection Component.
 */
class ProjectServiceContainer extends Container
{
    /**
     * Constructor.
     */
    public function __construct()
    {
        $this->parameters = $this->getDefaultParameters();

        $this->services =
        $this->scopedServices =
        $this->scopeStacks = array();

        $this->set('service_container', $this);

        $this->scopes = array();
        $this->scopeChildren = array();
        $this->methodMap = array(
            'bar' => 'getBarService',
            'baz' => 'getBazService',
            'depends_on_request' => 'getDependsOnRequestService',
            'factory_service' => 'getFactoryServiceService',
            'foo' => 'getFooService',
            'foo.baz' => 'getFoo_BazService',
            'foo_bar' => 'getFooBarService',
            'foo_with_inline' => 'getFooWithInlineService',
            'method_call1' => 'getMethodCall1Service',
            'request' => 'getRequestService',
        );
        $this->aliases = array(
            'alias_for_alias' => 'foo',
            'alias_for_foo' => 'foo',
        );
    }

    /**
     * Gets the 'bar' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return FooClass A FooClass instance.
     */
    protected function getBarService()
    {
        $this->services['bar'] = $instance = new \FooClass('foo', $this->get('foo.baz'), $this->getParameter('foo_bar'));

        $this->get('foo.baz')->configure($instance);

        return $instance;
    }

    /**
     * Gets the 'baz' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return Baz A Baz instance.
     */
    protected function getBazService()
    {
        $this->services['baz'] = $instance = new \Baz();

        $instance->setFoo($this->get('foo_with_inline'));

        return $instance;
    }

    /**
     * Gets the 'depends_on_request' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return stdClass A stdClass instance.
     */
    protected function getDependsOnRequestService()
    {
        $this->services['depends_on_request'] = $instance = new \stdClass();

        $instance->setRequest($this->get('request', ContainerInterface::NULL_ON_INVALID_REFERENCE));

        return $instance;
    }

    /**
     * Gets the 'factory_service' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return Bar A Bar instance.
     */
    protected function getFactoryServiceService()
    {
        return $this->services['factory_service'] = $this->get('foo.baz')->getInstance();
    }

    /**
     * Gets the 'foo' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return FooClass A FooClass instance.
     */
    protected function getFooService()
    {
        $a = $this->get('foo.baz');

        $this->services['foo'] = $instance = call_user_func(array('FooClass', 'getInstance'), 'foo', $a, array('bar' => 'foo is bar', 'foobar' => 'bar'), true, $this);

        $instance->setBar($this->get('bar'));
        $instance->initialize();
        $instance->foo = 'bar';
        $instance->moo = $a;
        sc_configure($instance);

        return $instance;
    }

    /**
     * Gets the 'foo.baz' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return BazClass A BazClass instance.
     */
    protected function getFoo_BazService()
    {
        $this->services['foo.baz'] = $instance = call_user_func(array('BazClass', 'getInstance'));

        call_user_func(array('BazClass', 'configureStatic1'), $instance);

        return $instance;
    }

    /**
     * Gets the 'foo_bar' service.
     *
     * @return FooClass A FooClass instance.
     */
    protected function getFooBarService()
    {
        return new \FooClass();
    }

    /**
     * Gets the 'foo_with_inline' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return Foo A Foo instance.
     */
    protected function getFooWithInlineService()
    {
        $a = new \Bar();

        $this->services['foo_with_inline'] = $instance = new \Foo();

        $a->setBaz($this->get('baz'));
        $a->pub = 'pub';

        $instance->setBar($a);

        return $instance;
    }

    /**
     * Gets the 'method_call1' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return FooClass A FooClass instance.
     */
    protected function getMethodCall1Service()
    {
        require_once '%path%foo.php';

        $this->services['method_call1'] = $instance = new \FooClass();

        $instance->setBar($this->get('foo'));
        $instance->setBar(NULL);
        $instance->setBar(($this->get("foo")->foo() . $this->getParameter("foo")));

        return $instance;
    }

    /**
     * Gets the 'request' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @throws RuntimeException always since this service is expected to be injected dynamically
     */
    protected function getRequestService()
    {
        throw new RuntimeException('You have requested a synthetic service ("request"). The DIC does not know how to construct this service.');
    }

    /**
     * Updates the 'request' service.
     */
    protected function synchronizeRequestService()
    {
        if ($this->initialized('depends_on_request')) {
            $this->get('depends_on_request')->setRequest($this->get('request', ContainerInterface::NULL_ON_INVALID_REFERENCE));
        }
    }

    /**
     * {@inheritdoc}
     */
    public function getParameter($name)
    {
        $name = strtolower($name);

        if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters))) {
            throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name));
        }

        return $this->parameters[$name];
    }

    /**
     * {@inheritdoc}
     */
    public function hasParameter($name)
    {
        $name = strtolower($name);

        return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters);
    }

    /**
     * {@inheritdoc}
     */
    public function setParameter($name, $value)
    {
        throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
    }

    /**
     * {@inheritDoc}
     */
    public function getParameterBag()
    {
        if (null === $this->parameterBag) {
            $this->parameterBag = new FrozenParameterBag($this->parameters);
        }

        return $this->parameterBag;
    }
    /**
     * Gets the default parameters.
     *
     * @return array An array of the default parameters
     */
    protected function getDefaultParameters()
    {
        return array(
            'baz_class' => 'BazClass',
            'foo_class' => 'FooClass',
            'foo' => 'bar',
        );
    }
}
<?php

$container->setParameter('foo', 'foo');
<?php

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;

/**
 * ProjectServiceContainer
 *
 * This class has been auto-generated
 * by the Symfony Dependency Injection Component.
 */
class ProjectServiceContainer extends Container
{
    /**
     * Constructor.
     */
    public function __construct()
    {
        parent::__construct();
    }
}
<?php
namespace Symfony\Component\DependencyInjection\Dump;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;

/**
 * Container
 *
 * This class has been auto-generated
 * by the Symfony Dependency Injection Component.
 */
class Container extends AbstractContainer
{
    /**
     * Constructor.
     */
    public function __construct()
    {
        parent::__construct();
    }
}
<?php

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;

/**
 * ProjectServiceContainer
 *
 * This class has been auto-generated
 * by the Symfony Dependency Injection Component.
 */
class ProjectServiceContainer extends Container
{
    /**
     * Constructor.
     */
    public function __construct()
    {
        parent::__construct(new ParameterBag($this->getDefaultParameters()));
    }

    /**
     * Gets the default parameters.
     *
     * @return array An array of the default parameters
     */
    protected function getDefaultParameters()
    {
        return array(
            'foo' => '%baz%',
            'baz' => 'bar',
            'bar' => 'foo is %%foo bar',
            'escape' => '@escapeme',
            'values' => array(
                0 => true,
                1 => false,
                2 => NULL,
                3 => 0,
                4 => 1000.3,
                5 => 'true',
                6 => 'false',
                7 => 'null',
            ),
        );
    }
}
<?php

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;

/**
 * ProjectServiceContainer
 *
 * This class has been auto-generated
 * by the Symfony Dependency Injection Component.
 */
class ProjectServiceContainer extends Container
{
    /**
     * Constructor.
     */
    public function __construct()
    {
        $this->parameters = $this->getDefaultParameters();

        $this->services =
        $this->scopedServices =
        $this->scopeStacks = array();

        $this->set('service_container', $this);

        $this->scopes = array();
        $this->scopeChildren = array();
        $this->methodMap = array(
            'test' => 'getTestService',
        );

        $this->aliases = array();
    }

    /**
     * Gets the 'test' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return stdClass A stdClass instance.
     */
    protected function getTestService()
    {
        return $this->services['test'] = new \stdClass(array('only dot' => '.', 'concatenation as value' => '.\'\'.', 'concatenation from the start value' => '\'\'.', '.' => 'dot as a key', '.\'\'.' => 'concatenation as a key', '\'\'.' => 'concatenation from the start key', 'optimize concatenation' => 'string1-string2', 'optimize concatenation with empty string' => 'string1string2', 'optimize concatenation from the start' => 'start', 'optimize concatenation at the end' => 'end'));
    }

    /**
     * {@inheritdoc}
     */
    public function getParameter($name)
    {
        $name = strtolower($name);

        if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters))) {
            throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name));
        }

        return $this->parameters[$name];
    }

    /**
     * {@inheritdoc}
     */
    public function hasParameter($name)
    {
        $name = strtolower($name);

        return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters);
    }

    /**
     * {@inheritdoc}
     */
    public function setParameter($name, $value)
    {
        throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
    }

    /**
     * {@inheritDoc}
     */
    public function getParameterBag()
    {
        if (null === $this->parameterBag) {
            $this->parameterBag = new FrozenParameterBag($this->parameters);
        }

        return $this->parameterBag;
    }
    /**
     * Gets the default parameters.
     *
     * @return array An array of the default parameters
     */
    protected function getDefaultParameters()
    {
        return array(
            'empty_value' => '',
            'some_string' => '-',
        );
    }
}
<?php

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;

/**
 * ProjectServiceContainer
 *
 * This class has been auto-generated
 * by the Symfony Dependency Injection Component.
 */
class ProjectServiceContainer extends Container
{
    /**
     * Constructor.
     */
    public function __construct()
    {
        $this->services =
        $this->scopedServices =
        $this->scopeStacks = array();

        $this->set('service_container', $this);

        $this->scopes = array();
        $this->scopeChildren = array();
        $this->methodMap = array(
            'foo' => 'getFooService',
        );

        $this->aliases = array();
    }

    /**
     * Gets the 'foo' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return stdClass A stdClass instance.
     */
    protected function getFooService()
    {
        return $this->services['foo'] = new \stdClass();
    }
}
<?php

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;

/**
 * ProjectServiceContainer
 *
 * This class has been auto-generated
 * by the Symfony Dependency Injection Component.
 */
class ProjectServiceContainer extends Container
{
    /**
     * Constructor.
     */
    public function __construct()
    {
        parent::__construct(new ParameterBag($this->getDefaultParameters()));
        $this->methodMap = array(
            'bar' => 'getBarService',
            'baz' => 'getBazService',
            'depends_on_request' => 'getDependsOnRequestService',
            'factory_service' => 'getFactoryServiceService',
            'foo' => 'getFooService',
            'foo.baz' => 'getFoo_BazService',
            'foo_bar' => 'getFooBarService',
            'foo_with_inline' => 'getFooWithInlineService',
            'inlined' => 'getInlinedService',
            'method_call1' => 'getMethodCall1Service',
            'request' => 'getRequestService',
        );
        $this->aliases = array(
            'alias_for_alias' => 'foo',
            'alias_for_foo' => 'foo',
        );
    }

    /**
     * Gets the 'bar' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return FooClass A FooClass instance.
     */
    protected function getBarService()
    {
        $this->services['bar'] = $instance = new \FooClass('foo', $this->get('foo.baz'), $this->getParameter('foo_bar'));

        $this->get('foo.baz')->configure($instance);

        return $instance;
    }

    /**
     * Gets the 'baz' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return Baz A Baz instance.
     */
    protected function getBazService()
    {
        $this->services['baz'] = $instance = new \Baz();

        $instance->setFoo($this->get('foo_with_inline'));

        return $instance;
    }

    /**
     * Gets the 'depends_on_request' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return stdClass A stdClass instance.
     */
    protected function getDependsOnRequestService()
    {
        $this->services['depends_on_request'] = $instance = new \stdClass();

        $instance->setRequest($this->get('request', ContainerInterface::NULL_ON_INVALID_REFERENCE));

        return $instance;
    }

    /**
     * Gets the 'factory_service' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return Bar A Bar instance.
     */
    protected function getFactoryServiceService()
    {
        return $this->services['factory_service'] = $this->get('foo.baz')->getInstance();
    }

    /**
     * Gets the 'foo' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return FooClass A FooClass instance.
     */
    protected function getFooService()
    {
        $a = $this->get('foo.baz');

        $this->services['foo'] = $instance = call_user_func(array('FooClass', 'getInstance'), 'foo', $a, array($this->getParameter('foo') => 'foo is '.$this->getParameter('foo').'', 'foobar' => $this->getParameter('foo')), true, $this);

        $instance->setBar($this->get('bar'));
        $instance->initialize();
        $instance->foo = 'bar';
        $instance->moo = $a;
        sc_configure($instance);

        return $instance;
    }

    /**
     * Gets the 'foo.baz' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return object A %baz_class% instance.
     */
    protected function getFoo_BazService()
    {
        $this->services['foo.baz'] = $instance = call_user_func(array($this->getParameter('baz_class'), 'getInstance'));

        call_user_func(array($this->getParameter('baz_class'), 'configureStatic1'), $instance);

        return $instance;
    }

    /**
     * Gets the 'foo_bar' service.
     *
     * @return object A %foo_class% instance.
     */
    protected function getFooBarService()
    {
        $class = $this->getParameter('foo_class');

        return new $class();
    }

    /**
     * Gets the 'foo_with_inline' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return Foo A Foo instance.
     */
    protected function getFooWithInlineService()
    {
        $this->services['foo_with_inline'] = $instance = new \Foo();

        $instance->setBar($this->get('inlined'));

        return $instance;
    }

    /**
     * Gets the 'method_call1' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @return FooClass A FooClass instance.
     */
    protected function getMethodCall1Service()
    {
        require_once '%path%foo.php';

        $this->services['method_call1'] = $instance = new \FooClass();

        $instance->setBar($this->get('foo'));
        $instance->setBar($this->get('foo2', ContainerInterface::NULL_ON_INVALID_REFERENCE));
        if ($this->has('foo3')) {
            $instance->setBar($this->get('foo3', ContainerInterface::NULL_ON_INVALID_REFERENCE));
        }
        if ($this->has('foobaz')) {
            $instance->setBar($this->get('foobaz', ContainerInterface::NULL_ON_INVALID_REFERENCE));
        }
        $instance->setBar(($this->get("foo")->foo() . $this->getParameter("foo")));

        return $instance;
    }

    /**
     * Gets the 'request' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * @throws RuntimeException always since this service is expected to be injected dynamically
     */
    protected function getRequestService()
    {
        throw new RuntimeException('You have requested a synthetic service ("request"). The DIC does not know how to construct this service.');
    }

    /**
     * Updates the 'request' service.
     */
    protected function synchronizeRequestService()
    {
        if ($this->initialized('depends_on_request')) {
            $this->get('depends_on_request')->setRequest($this->get('request', ContainerInterface::NULL_ON_INVALID_REFERENCE));
        }
    }

    /**
     * Gets the 'inlined' service.
     *
     * This service is shared.
     * This method always returns the same instance of the service.
     *
     * This service is private.
     * If you want to be able to request this service from the container directly,
     * make it public, otherwise you might end up with broken code.
     *
     * @return Bar A Bar instance.
     */
    protected function getInlinedService()
    {
        $this->services['inlined'] = $instance = new \Bar();

        $instance->setBaz($this->get('baz'));
        $instance->pub = 'pub';

        return $instance;
    }

    /**
     * Gets the default parameters.
     *
     * @return array An array of the default parameters
     */
    protected function getDefaultParameters()
    {
        return array(
            'baz_class' => 'BazClass',
            'foo_class' => 'FooClass',
            'foo' => 'bar',
        );
    }
}
[parameters]
  FOO = foo
  baz = baz
[parameters]
  imported_from_ini = true
{NOT AN INI FILE}
{JUST A PLAIN TEXT FILE}
[parameters]
  foo = bar
  bar = %foo%
parameters:
    foo: foo
    values:
        - true
        - false
foobarfoobar: {}

services:
    foo: { class: FooClass }
    baz: { class: BazClass }
    scope.container: { class: FooClass, scope: container }
    scope.custom: { class: FooClass, scope: custom }
    scope.prototype: { class: FooClass, scope: prototype }
    constructor: { class: FooClass, factory_method: getInstance }
    file: { class: FooClass, file: %path%/foo.php }
    arguments: { class: FooClass, arguments: [foo, @foo, [true, false]] }
    configurator1: { class: FooClass, configurator: sc_configure }
    configurator2: { class: FooClass, configurator: [@baz, configure] }
    configurator3: { class: FooClass, configurator: [BazClass, configureStatic] }
    method_call1:
        class: FooClass
        calls:
            - [ setBar, [] ]
            - [ setBar ]
            - [ setBar, ['@=service("foo").foo() ~ parameter("foo")'] ]
    method_call2:
        class: FooClass
        calls:
            - [ setBar, [ foo, @foo, [true, false] ] ]
    alias_for_foo: @foo
    another_alias_for_foo:
        alias: foo
        public: false
    factory_service: { class: BazClass, factory_method: getInstance, factory_service: baz_factory }
    request:
        class: Request
        synthetic: true
        synchronized: true
        lazy: true
services:
    foo_service:
        class:    FooClass
        tags:
          # tag is missing the name key
          foo_tag:   { foo: bar }
imports:
    - { resource: services2.yml }
    - { resource: services3.yml }
    - { resource: "../ini/parameters.ini", class: Symfony\Component\DependencyInjection\Loader\IniFileLoader }
    - { resource: "../ini/parameters2.ini" }
    - { resource: "../xml/services13.xml" }
parameters:
    baz_class: BazClass
    foo_class: FooClass
    foo: bar

services:
    foo:
        class: FooClass
        tags:
            - { name: foo, foo: foo }
            - { name: foo, bar: bar }
        factory_class: FooClass
        factory_method: getInstance
        arguments: [foo, '@foo.baz', { '%foo%': 'foo is %foo%', foobar: '%foo%' }, true, '@service_container']
        properties: { foo: bar, moo: '@foo.baz' }
        calls:
            - [setBar, ['@bar']]
            - [initialize, {  }]

        configurator: sc_configure
    bar:
        class: FooClass
        arguments: [foo, '@foo.baz', '%foo_bar%']
        configurator: ['@foo.baz', configure]
    foo.baz:
        class: %baz_class%
        factory_class: %baz_class%
        factory_method: getInstance
        configurator: ['%baz_class%', configureStatic1]
    foo_bar:
        class: %foo_class%
        scope: prototype
    method_call1:
        class: FooClass
        file: %path%foo.php
        calls:
            - [setBar, ['@foo']]
            - [setBar, ['@?foo2']]
            - [setBar, ['@?foo3']]
            - [setBar, ['@?foobaz']]
            - [setBar, ['@=service("foo").foo() ~ parameter("foo")']]

    factory_service:
        class: Bar
        factory_method: getInstance
        factory_service: foo.baz
    foo_with_inline:
        class: Foo
        calls:
            - [setBar, ['@inlined']]

    inlined:
        class: Bar
        public: false
        properties: { pub: pub }
        calls:
            - [setBaz, ['@baz']]

    baz:
        class: Baz
        calls:
            - [setFoo, ['@foo_with_inline']]

    request:
        class: Request
        synthetic: true
        synchronized: true
    depends_on_request:
        class: stdClass
        calls:
            - [setRequest, ['@?request']]

    alias_for_foo: @foo
    alias_for_alias: @foo
services:
    foo: { class: BarClass }
foo:
  bar
parameters:
    FOO: bar
    values:
        - true
        - false
        - 0
        - 1000.3
    bar: foo
    escape: @@escapeme
    foo_bar: @foo_bar
    MixedCase:
        MixedCaseKey: value
services:
    foo_service:
        class:    FooClass
        # tags is not an array
        tags:     string
false
parameters:
    project.parameter.foo: BAR

services:
    project.service.foo:
        class: BAR

project:
    test: %project.parameter.foo%
parameters:
    foo: '%baz%'
    baz: bar
    bar: 'foo is %%foo bar'
    escape: '@@escapeme'
    values: [true, false, null, 0, 1000.3, 'true', 'false', 'null']

# used to test imports in XML
parameters:
    imported_from_yaml: true
services:
    foo_service:
        class:    FooClass
        tags:
          # tag-attribute is not a scalar
          - { name: foo, bar: { foo: foo, bar: bar } }
imports:
    - { resource: foo_fake.yml, ignore_errors: true }
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  <services>
    <service id="extension2.foo" class="FooClass2">
      <argument type="service">
        <service class="BarClass2">
        </service>
      </argument>
    </service>
  </services>
</container>
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  <parameters>
    <parameter key="foo">foo</parameter>
    <parameter key="values" type="collection">
      <parameter>true</parameter>
      <parameter>false</parameter>
    </parameter>
  </parameters>
</container>
<?xml version="1.0" ?>

<nonvalid />
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:project="http://www.example.com/schema/projectwithxsd"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
                        http://www.example.com/schema/projectwithxsd http://www.example.com/schema/projectwithxsd/project-1.0.xsd">

    <parameters>
        <parameter key="project.parameter.foo">BAR</parameter>
    </parameters>

    <services>
        <service id="project.service.foo" class="BAR" />
    </services>

    <project:bar bar="bar" />

</container>
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:project="http://www.example.com/schema/not_registered_extension">
  <project:bar />
</container>
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:project="http://www.example.com/schema/projectwithxsd"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
                        http://www.example.com/schema/projectwithxsd http://www.example.com/schema/projectwithxsd/project-1.0.xsd">

    <parameters>
        <parameter key="project.parameter.foo">BAR</parameter>
    </parameters>

    <services>
        <service id="project.service.foo" class="BAR" />
    </services>

    <project:bar />

</container>
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:project="http://www.example.com/schema/projectwithxsd"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
                        http://www.example.com/schema/projectwithxsd http://www.example.com/schema/projectwithxsd/project-1.0.xsd">

    <project:foobar />

</container>
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:project="http://www.example.com/schema/projectwithxsdinphar"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
                        http://www.example.com/schema/projectwithxsdinphar http://www.example.com/schema/projectwithxsdinphar/project-1.0.xsd">

    <project:bar bar="foo" />

</container>
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:project="http://www.example.com/schema/projectwithxsdinphar"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
                        http://www.example.com/schema/projectwithxsdinphar http://www.example.com/schema/projectwithxsdinphar/project-1.0.xsd">

    <project:bar />

</container>
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:project="http://www.example.com/schema/project">

    <parameters>
        <parameter key="project.parameter.foo">BAR</parameter>
    </parameters>

    <services>
        <service id="project.service.foo" class="BAR" />
    </services>

    <project:bar babar="babar">
        <another />
        <another2>%project.parameter.foo%</another2>
    </project:bar>

</container>
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  <imports>
    <import resource="services2.xml" />
    <import resource="services3.xml" />
    <import resource="../ini/parameters.ini" />
    <import resource="../ini/parameters2.ini" />
    <import resource="../yaml/services13.yml" />
  </imports>
</container>
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  <parameters>
    <parameter>a string</parameter>
    <parameter key="FOO">bar</parameter>
    <parameter key="values" type="collection">
      <parameter>0</parameter>
      <parameter key="integer">4</parameter>
      <parameter key="100">null</parameter>
      <parameter type="string">true</parameter>
      <parameter>true</parameter>
      <parameter>false</parameter>
      <parameter>on</parameter>
      <parameter>off</parameter>
      <parameter key="float">1.3</parameter>
      <parameter>1000.3</parameter>
      <parameter>a string</parameter>
      <parameter type="collection">
        <parameter>foo</parameter>
        <parameter>bar</parameter>
      </parameter>
    </parameter>
    <parameter key="foo_bar" type="service" id="foo_bar" />
    <parameter key="MixedCase" type="collection"> <!-- Should be lower cased -->
      <parameter key="MixedCaseKey">value</parameter> <!-- Should stay mixed case -->
    </parameter>
    <parameter key="constant" type="constant">PHP_EOL</parameter>
  </parameters>
</container>
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  <imports>
    <import resource="foo_fake.xml" ignore-errors="true" />
  </imports>
</container>
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  <services>
    <service id="foo" class="FooClass">
      <argument type="service">
        <service class="BarClass">
          <argument type="service">
            <service class="BazClass">
            </service>
          </argument>
        </service>
      </argument>
      <property name="p" type="service">
        <service class="BazClass" />
      </property>
    </service>
  </services>
</container>
<?xml version="1.0"?>
<!DOCTYPE foo>
<foo></foo>
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  <services>
    <service id="foo" class="BarClass" />
  </services>
</container>
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  <parameters>
    <parameter key="imported_from_xml">true</parameter>
  </parameters>
</container>
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  <services>
    <service id="foo" class="FooClass" />
    <service id="baz" class="BazClass" />
    <service id="scope.container" class="FooClass" scope="container" />
    <service id="scope.custom" class="FooClass" scope="custom" />
    <service id="scope.prototype" class="FooClass" scope="prototype" />
    <service id="constructor" class="FooClass" factory-method="getInstance" />
    <service id="file" class="FooClass">
      <file>%path%/foo.php</file>
    </service>
    <service id="arguments" class="FooClass">
      <argument>foo</argument>
      <argument type="service" id="foo" />
      <argument type="collection">
        <argument>true</argument>
        <argument>false</argument>
      </argument>
    </service>
    <service id="configurator1" class="FooClass">
      <configurator function="sc_configure" />
    </service>
    <service id="configurator2" class="FooClass">
      <configurator service="baz" method="configure" />
    </service>
    <service id="configurator3" class="FooClass">
      <configurator class="BazClass" method="configureStatic" />
    </service>
    <service id="method_call1" class="FooClass">
      <call method="setBar" />
      <call method="setBar">
        <argument type="expression">service("foo").foo() ~ parameter("foo")</argument>
      </call>
    </service>
    <service id="method_call2" class="FooClass">
      <call method="setBar">
        <argument>foo</argument>
        <argument type="service" id="foo" />
        <argument type="collection">
          <argument>true</argument>
          <argument>false</argument>
        </argument>
      </call>
    </service>
    <service id="alias_for_foo" alias="foo" />
    <service id="another_alias_for_foo" alias="foo" public="false" />
    <service id="factory_service" factory-method="getInstance" factory-service="baz_factory" />
    <service id="request" class="Request" synthetic="true" synchronized="true" lazy="true"/>
  </services>
</container>
<?xml version="1.0" encoding="utf-8"?>
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"/>
<?xml version="1.0" encoding="utf-8"?>
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  <parameters>
    <parameter key="baz_class">BazClass</parameter>
    <parameter key="foo_class">FooClass</parameter>
    <parameter key="foo">bar</parameter>
  </parameters>
  <services>
    <service id="foo" class="FooClass" factory-method="getInstance">
      <tag name="foo" foo="foo"/>
      <tag name="foo" bar="bar"/>
      <argument>foo</argument>
      <argument type="service" id="foo.baz"/>
      <argument type="collection">
        <argument key="%foo%">foo is %foo%</argument>
        <argument key="foobar">%foo%</argument>
      </argument>
      <argument>true</argument>
      <argument type="service" id="service_container"/>
      <property name="foo">bar</property>
      <property name="moo" type="service" id="foo.baz"/>
      <call method="setBar">
        <argument type="service" id="bar"/>
      </call>
      <call method="initialize"/>
      <configurator function="sc_configure"/>
    </service>
    <service id="bar" class="FooClass">
      <argument>foo</argument>
      <argument type="service" id="foo.baz"/>
      <argument>%foo_bar%</argument>
      <configurator service="foo.baz" method="configure"/>
    </service>
    <service id="foo.baz" class="%baz_class%" factory-method="getInstance">
      <configurator class="%baz_class%" method="configureStatic1"/>
    </service>
    <service id="foo_bar" class="%foo_class%" scope="prototype"/>
    <service id="method_call1" class="FooClass">
      <file>%path%foo.php</file>
      <call method="setBar">
        <argument type="service" id="foo"/>
      </call>
      <call method="setBar">
        <argument type="service" id="foo2" on-invalid="null"/>
      </call>
      <call method="setBar">
        <argument type="service" id="foo3" on-invalid="ignore"/>
      </call>
      <call method="setBar">
        <argument type="service" id="foobaz" on-invalid="ignore"/>
      </call>
      <call method="setBar">
        <argument type="expression">service("foo").foo() ~ parameter("foo")</argument>
      </call>
    </service>
    <service id="factory_service" class="Bar" factory-method="getInstance" factory-service="foo.baz"/>
    <service id="foo_with_inline" class="Foo">
      <call method="setBar">
        <argument type="service" id="inlined"/>
      </call>
    </service>
    <service id="inlined" class="Bar" public="false">
      <property name="pub">pub</property>
      <call method="setBaz">
        <argument type="service" id="baz"/>
      </call>
    </service>
    <service id="baz" class="Baz">
      <call method="setFoo">
        <argument type="service" id="foo_with_inline"/>
      </call>
    </service>
    <service id="request" class="Request" synthetic="true" synchronized="true"/>
    <service id="depends_on_request" class="stdClass">
      <call method="setRequest">
        <argument type="service" id="request" on-invalid="null" strict="false"/>
      </call>
    </service>
    <service id="alias_for_foo" alias="foo"/>
    <service id="alias_for_alias" alias="foo"/>
  </services>
</container>
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  <services>
    <service id="extension1.foo" class="FooClass1">
      <argument type="service">
        <service class="BarClass1">
        </service>
      </argument>
    </service>
  </services>
</container>
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
  <parameters>
    <parameter key="foo">%baz%</parameter>
    <parameter key="baz">bar</parameter>
    <parameter key="bar">foo is %%foo bar</parameter>
    <parameter key="escape">@escapeme</parameter>
    <parameter key="values" type="collection">
      <parameter>true</parameter>
      <parameter>false</parameter>
      <parameter>null</parameter>
      <parameter>0</parameter>
      <parameter>1000.3</parameter>
      <parameter type="string">true</parameter>
      <parameter type="string">false</parameter>
      <parameter type="string">null</parameter>
    </parameter>
  </parameters>
</container>
digraph sc {
  ratio="normal"
  node [fontsize="13" fontname="Verdana" shape="square"];
  edge [fontsize="12" fontname="Verdana" color="white" arrowhead="closed" arrowsize="1"];

  node_foo [label="foo\nFooClass\n", shape=square, fillcolor="grey", style="filled"];
  node_service_container [label="service_container\nSymfony\\Component\\DependencyInjection\\ContainerBuilder\n", shape=square, fillcolor="green", style="empty"];
  node_bar [label="bar\n\n", shape=square, fillcolor="red", style="empty"];
  node_foo -> node_bar [label="" style="filled"];
}
digraph sc {
  ratio="compress"
  node [fontsize="11" fontname="Arial" shape="record"];
  edge [fontsize="9" fontname="Arial" color="grey" arrowhead="open" arrowsize="0.5"];

  node_foo [label="foo (alias_for_foo)\nFooClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
  node_bar [label="bar\nFooClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
  node_foo_baz [label="foo.baz\nBazClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
  node_foo_bar [label="foo_bar\nFooClass\n", shape=record, fillcolor="#eeeeee", style="dotted"];
  node_method_call1 [label="method_call1\nFooClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
  node_factory_service [label="factory_service\nBar\n", shape=record, fillcolor="#eeeeee", style="filled"];
  node_foo_with_inline [label="foo_with_inline\nFoo\n", shape=record, fillcolor="#eeeeee", style="filled"];
  node_inlined [label="inlined\nBar\n", shape=record, fillcolor="#eeeeee", style="filled"];
  node_baz [label="baz\nBaz\n", shape=record, fillcolor="#eeeeee", style="filled"];
  node_request [label="request\nRequest\n", shape=record, fillcolor="#eeeeee", style="filled"];
  node_depends_on_request [label="depends_on_request\nstdClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
  node_service_container [label="service_container\nSymfony\\Component\\DependencyInjection\\ContainerBuilder\n", shape=record, fillcolor="#9999ff", style="filled"];
  node_foo2 [label="foo2\n\n", shape=record, fillcolor="#ff9999", style="filled"];
  node_foo3 [label="foo3\n\n", shape=record, fillcolor="#ff9999", style="filled"];
  node_foobaz [label="foobaz\n\n", shape=record, fillcolor="#ff9999", style="filled"];
  node_foo -> node_foo_baz [label="" style="filled"];
  node_foo -> node_service_container [label="" style="filled"];
  node_foo -> node_foo_baz [label="" style="dashed"];
  node_foo -> node_bar [label="setBar()" style="dashed"];
  node_bar -> node_foo_baz [label="" style="filled"];
  node_method_call1 -> node_foo [label="setBar()" style="dashed"];
  node_method_call1 -> node_foo2 [label="setBar()" style="dashed"];
  node_method_call1 -> node_foo3 [label="setBar()" style="dashed"];
  node_method_call1 -> node_foobaz [label="setBar()" style="dashed"];
  node_foo_with_inline -> node_inlined [label="setBar()" style="dashed"];
  node_inlined -> node_baz [label="setBaz()" style="dashed"];
  node_baz -> node_foo_with_inline [label="setFoo()" style="dashed"];
  node_depends_on_request -> node_request [label="setRequest()" style="dashed"];
}
digraph sc {
  ratio="compress"
  node [fontsize="11" fontname="Arial" shape="record"];
  edge [fontsize="9" fontname="Arial" color="grey" arrowhead="open" arrowsize="0.5"];

  node_foo [label="foo\nFooClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
  node_service_container [label="service_container\nSymfony\\Component\\DependencyInjection\\ContainerBuilder\n", shape=record, fillcolor="#9999ff", style="filled"];
  node_bar [label="bar\n\n", shape=record, fillcolor="#ff9999", style="filled"];
  node_foo -> node_bar [label="" style="filled"];
}
digraph sc {
  ratio="compress"
  node [fontsize="11" fontname="Arial" shape="record"];
  edge [fontsize="9" fontname="Arial" color="grey" arrowhead="open" arrowsize="0.5"];

  node_service_container [label="service_container\nContainer14\\ProjectServiceContainer\n", shape=record, fillcolor="#9999ff", style="filled"];
}
digraph sc {
  ratio="compress"
  node [fontsize="11" fontname="Arial" shape="record"];
  edge [fontsize="9" fontname="Arial" color="grey" arrowhead="open" arrowsize="0.5"];

  node_service_container [label="service_container\nSymfony\\Component\\DependencyInjection\\ContainerBuilder\n", shape=record, fillcolor="#9999ff", style="filled"];
}
digraph sc {
  ratio="compress"
  node [fontsize="11" fontname="Arial" shape="record"];
  edge [fontsize="9" fontname="Arial" color="grey" arrowhead="open" arrowsize="0.5"];

  node_foo [label="foo\nFooClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
  node_bar [label="bar\nBarClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
  node_service_container [label="service_container\nSymfony\\Component\\DependencyInjection\\ContainerBuilder\n", shape=record, fillcolor="#9999ff", style="filled"];
  node_foo -> node_bar [label="" style="filled"];
}
<?php

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;

class ProjectExtension implements ExtensionInterface
{
    public function load(array $configs, ContainerBuilder $configuration)
    {
        $config = call_user_func_array('array_merge', $configs);

        $configuration->setDefinition('project.service.bar', new Definition('FooClass'));
        $configuration->setParameter('project.parameter.bar', isset($config['foo']) ? $config['foo'] : 'foobar');

        $configuration->setDefinition('project.service.foo', new Definition('FooClass'));
        $configuration->setParameter('project.parameter.foo', isset($config['foo']) ? $config['foo'] : 'foobar');

        return $configuration;
    }

    public function getXsdValidationBasePath()
    {
        return false;
    }

    public function getNamespace()
    {
        return 'http://www.example.com/schema/project';
    }

    public function getAlias()
    {
        return 'project';
    }

    public function getConfiguration(array $config, ContainerBuilder $container)
    {
        return null;
    }
}
<?php

$file = __DIR__.'/ProjectWithXsdExtensionInPhar.phar';
if (is_file($file)) {
    @unlink($file);
}

$phar = new Phar($file, 0, 'ProjectWithXsdExtensionInPhar.phar');
$phar->addFromString('ProjectWithXsdExtensionInPhar.php',<<<EOT
<?php

class ProjectWithXsdExtensionInPhar extends ProjectExtension
{
    public function getXsdValidationBasePath()
    {
        return __DIR__.'/schema';
    }

    public function getNamespace()
    {
        return 'http://www.example.com/schema/projectwithxsdinphar';
    }

    public function getAlias()
    {
        return 'projectwithxsdinphar';
    }
}
EOT
);
$phar->addFromString('schema/project-1.0.xsd', <<<EOT
<?xml version="1.0" encoding="UTF-8" ?>

<xsd:schema xmlns="http://www.example.com/schema/projectwithxsdinphar"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.example.com/schema/projectwithxsdinphar"
    elementFormDefault="qualified">

  <xsd:element name="bar" type="bar" />

  <xsd:complexType name="bar">
    <xsd:attribute name="foo" type="xsd:string" />
  </xsd:complexType>
</xsd:schema>
EOT
);
$phar->setStub('<?php require_once "phar://ProjectWithXsdExtensionInPhar.phar/ProjectWithXsdExtensionInPhar.php"; __HALT_COMPILER(); ?>');
<?xml version="1.0" encoding="UTF-8" ?>

<xsd:schema xmlns="http://www.example.com/schema/projectwithxsd"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.example.com/schema/projectwithxsd"
    elementFormDefault="qualified">

  <xsd:element name="bar" type="bar" />

  <xsd:complexType name="bar">
    <xsd:attribute name="foo" type="xsd:string" />
  </xsd:complexType>
</xsd:schema>
<?php

function sc_configure($instance)
{
    $instance->configure();
}

class BarClass
{
    protected $baz;
    public $foo = 'foo';

    public function setBaz(BazClass $baz)
    {
        $this->baz = $baz;
    }

    public function getBaz()
    {
        return $this->baz;
    }
}

class BazClass
{
    protected $foo;

    public function setFoo(Foo $foo)
    {
        $this->foo = $foo;
    }

    public function configure($instance)
    {
        $instance->configure();
    }

    public static function getInstance()
    {
        return new self();
    }

    public static function configureStatic($instance)
    {
        $instance->configure();
    }

    public static function configureStatic1()
    {
    }
}

class BarUserClass
{
    public $bar;

    public function __construct(BarClass $bar)
    {
        $this->bar = $bar;
    }
}
<?php require_once "phar://ProjectWithXsdExtensionInPhar.phar/ProjectWithXsdExtensionInPhar.php"; __HALT_COMPILER(); ?>
          "   ProjectWithXsdExtensionInPhar.phar    !   ProjectWithXsdExtensionInPhar.php~  akM~            schema/project-1.0.xsd  akM  Qp      <?php

class ProjectWithXsdExtensionInPhar extends ProjectExtension
{
    public function getXsdValidationBasePath()
    {
        return __DIR__.'/schema';
    }

    public function getNamespace()
    {
        return 'http://www.example.com/schema/projectwithxsdinphar';
    }

    public function getAlias()
    {
        return 'projectwithxsdinphar';
    }
}<?xml version="1.0" encoding="UTF-8" ?>

<xsd:schema xmlns="http://www.example.com/schema/projectwithxsdinphar"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.example.com/schema/projectwithxsdinphar"
    elementFormDefault="qualified">

  <xsd:element name="bar" type="bar" />

  <xsd:complexType name="bar">
    <xsd:attribute name="foo" type="xsd:string" />
  </xsd:complexType>
</xsd:schema>W]ʯ`5,,)EY   GBMB<?php

class FooClass
{
    public $foo, $moo;

    public $bar = null, $initialized = false, $configured = false, $called = false, $arguments = array();

    public function __construct($arguments = array())
    {
        $this->arguments = $arguments;
    }

    public static function getInstance($arguments = array())
    {
        $obj = new self($arguments);
        $obj->called = true;

        return $obj;
    }

    public function initialize()
    {
        $this->initialized = true;
    }

    public function configure()
    {
        $this->configured = true;
    }

    public function setBar($value = null)
    {
        $this->bar = $value;
    }
}
<?php

class ProjectWithXsdExtension extends ProjectExtension
{
    public function getXsdValidationBasePath()
    {
        return __DIR__.'/schema';
    }

    public function getNamespace()
    {
        return 'http://www.example.com/schema/projectwithxsd';
    }

    public function getAlias()
    {
        return 'projectwithxsd';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Loader;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\Config\Loader\Loader;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\ExpressionLanguage\Expression;

class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    protected static $fixturesPath;

    public static function setUpBeforeClass()
    {
        self::$fixturesPath = realpath(__DIR__.'/../Fixtures/');
        require_once self::$fixturesPath.'/includes/foo.php';
        require_once self::$fixturesPath.'/includes/ProjectExtension.php';
    }

    public function testLoadFile()
    {
        $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/ini'));
        $r = new \ReflectionObject($loader);
        $m = $r->getMethod('loadFile');
        $m->setAccessible(true);

        try {
            $m->invoke($loader, 'foo.yml');
            $this->fail('->load() throws an InvalidArgumentException if the loaded file does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the loaded file does not exist');
            $this->assertEquals('The service file "foo.yml" is not valid.', $e->getMessage(), '->load() throws an InvalidArgumentException if the loaded file does not exist');
        }

        try {
            $m->invoke($loader, 'parameters.ini');
            $this->fail('->load() throws an InvalidArgumentException if the loaded file is not a valid YAML file');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the loaded file is not a valid YAML file');
            $this->assertEquals('The service file "parameters.ini" is not valid.', $e->getMessage(), '->load() throws an InvalidArgumentException if the loaded file is not a valid YAML file');
        }

        $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));

        foreach (array('nonvalid1', 'nonvalid2') as $fixture) {
            try {
                $m->invoke($loader, $fixture.'.yml');
                $this->fail('->load() throws an InvalidArgumentException if the loaded file does not validate');
            } catch (\Exception $e) {
                $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the loaded file does not validate');
                $this->assertStringMatchesFormat('The service file "nonvalid%d.yml" is not valid.', $e->getMessage(), '->load() throws an InvalidArgumentException if the loaded file does not validate');
            }
        }
    }

    public function testLoadParameters()
    {
        $container = new ContainerBuilder();
        $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
        $loader->load('services2.yml');
        $this->assertEquals(array('foo' => 'bar', 'mixedcase' => array('MixedCaseKey' => 'value'), 'values' => array(true, false, 0, 1000.3), 'bar' => 'foo', 'escape' => '@escapeme', 'foo_bar' => new Reference('foo_bar')), $container->getParameterBag()->all(), '->load() converts YAML keys to lowercase');
    }

    public function testLoadImports()
    {
        $container = new ContainerBuilder();
        $resolver = new LoaderResolver(array(
            new IniFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')),
            new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')),
            $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')),
        ));
        $loader->setResolver($resolver);
        $loader->load('services4.yml');

        $actual = $container->getParameterBag()->all();
        $expected = array('foo' => 'bar', 'values' => array(true, false), 'bar' => '%foo%', 'escape' => '@escapeme', 'foo_bar' => new Reference('foo_bar'), 'mixedcase' => array('MixedCaseKey' => 'value'), 'imported_from_ini' => true, 'imported_from_xml' => true);
        $this->assertEquals(array_keys($expected), array_keys($actual), '->load() imports and merges imported files');

        // Bad import throws no exception due to ignore_errors value.
        $loader->load('services4_bad_import.yml');
    }

    public function testLoadServices()
    {
        $container = new ContainerBuilder();
        $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
        $loader->load('services6.yml');
        $services = $container->getDefinitions();
        $this->assertTrue(isset($services['foo']), '->load() parses service elements');
        $this->assertEquals('Symfony\\Component\\DependencyInjection\\Definition', get_class($services['foo']), '->load() converts service element to Definition instances');
        $this->assertEquals('FooClass', $services['foo']->getClass(), '->load() parses the class attribute');
        $this->assertEquals('container', $services['scope.container']->getScope());
        $this->assertEquals('custom', $services['scope.custom']->getScope());
        $this->assertEquals('prototype', $services['scope.prototype']->getScope());
        $this->assertEquals('getInstance', $services['constructor']->getFactoryMethod(), '->load() parses the factory_method attribute');
        $this->assertEquals('%path%/foo.php', $services['file']->getFile(), '->load() parses the file tag');
        $this->assertEquals(array('foo', new Reference('foo'), array(true, false)), $services['arguments']->getArguments(), '->load() parses the argument tags');
        $this->assertEquals('sc_configure', $services['configurator1']->getConfigurator(), '->load() parses the configurator tag');
        $this->assertEquals(array(new Reference('baz'), 'configure'), $services['configurator2']->getConfigurator(), '->load() parses the configurator tag');
        $this->assertEquals(array('BazClass', 'configureStatic'), $services['configurator3']->getConfigurator(), '->load() parses the configurator tag');
        $this->assertEquals(array(array('setBar', array()), array('setBar', array()), array('setBar', array(new Expression('service("foo").foo() ~ parameter("foo")')))), $services['method_call1']->getMethodCalls(), '->load() parses the method_call tag');
        $this->assertEquals(array(array('setBar', array('foo', new Reference('foo'), array(true, false)))), $services['method_call2']->getMethodCalls(), '->load() parses the method_call tag');
        $this->assertEquals('baz_factory', $services['factory_service']->getFactoryService());

        $this->assertTrue($services['request']->isSynthetic(), '->load() parses the synthetic flag');
        $this->assertTrue($services['request']->isSynchronized(), '->load() parses the synchronized flag');
        $this->assertTrue($services['request']->isLazy(), '->load() parses the lazy flag');

        $aliases = $container->getAliases();
        $this->assertTrue(isset($aliases['alias_for_foo']), '->load() parses aliases');
        $this->assertEquals('foo', (string) $aliases['alias_for_foo'], '->load() parses aliases');
        $this->assertTrue($aliases['alias_for_foo']->isPublic());
        $this->assertTrue(isset($aliases['another_alias_for_foo']));
        $this->assertEquals('foo', (string) $aliases['another_alias_for_foo']);
        $this->assertFalse($aliases['another_alias_for_foo']->isPublic());
    }

    public function testExtensions()
    {
        $container = new ContainerBuilder();
        $container->registerExtension(new \ProjectExtension());
        $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
        $loader->load('services10.yml');
        $container->compile();
        $services = $container->getDefinitions();
        $parameters = $container->getParameterBag()->all();

        $this->assertTrue(isset($services['project.service.bar']), '->load() parses extension elements');
        $this->assertTrue(isset($parameters['project.parameter.bar']), '->load() parses extension elements');

        $this->assertEquals('BAR', $services['project.service.foo']->getClass(), '->load() parses extension elements');
        $this->assertEquals('BAR', $parameters['project.parameter.foo'], '->load() parses extension elements');

        try {
            $loader->load('services11.yml');
            $this->fail('->load() throws an InvalidArgumentException if the tag is not valid');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the tag is not valid');
            $this->assertStringStartsWith('There is no extension able to load the configuration for "foobarfoobar" (in', $e->getMessage(), '->load() throws an InvalidArgumentException if the tag is not valid');
        }
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Loader\YamlFileLoader::supports
     */
    public function testSupports()
    {
        $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator());

        $this->assertTrue($loader->supports('foo.yml'), '->supports() returns true if the resource is loadable');
        $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable');
    }

    public function testNonArrayTagThrowsException()
    {
        $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
        try {
            $loader->load('badtag1.yml');
            $this->fail('->load() should throw an exception when the tags key of a service is not an array');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the tags key is not an array');
            $this->assertStringStartsWith('Parameter "tags" must be an array for service', $e->getMessage(), '->load() throws an InvalidArgumentException if the tags key is not an array');
        }
    }

    public function testTagWithoutNameThrowsException()
    {
        $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
        try {
            $loader->load('badtag2.yml');
            $this->fail('->load() should throw an exception when a tag is missing the name key');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if a tag is missing the name key');
            $this->assertStringStartsWith('A "tags" entry is missing a "name" key for service ', $e->getMessage(), '->load() throws an InvalidArgumentException if a tag is missing the name key');
        }
    }

    public function testTagWithAttributeArrayThrowsException()
    {
        $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml'));
        try {
            $loader->load('badtag3.yml');
            $this->fail('->load() should throw an exception when a tag-attribute is not a scalar');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if a tag-attribute is not a scalar');
            $this->assertStringStartsWith('A "tags" attribute must be of a scalar-type for service "foo_service", tag "foo", attribute "bar"', $e->getMessage(), '->load() throws an InvalidArgumentException if a tag-attribute is not a scalar');
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Loader;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\Loader\Loader;
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
use Symfony\Component\Config\FileLocator;

class PhpFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\DependencyInjection\Loader\PhpFileLoader::supports
     */
    public function testSupports()
    {
        $loader = new PhpFileLoader(new ContainerBuilder(), new FileLocator());

        $this->assertTrue($loader->supports('foo.php'), '->supports() returns true if the resource is loadable');
        $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Loader\PhpFileLoader::load
     */
    public function testLoad()
    {
        $loader = new PhpFileLoader($container = new ContainerBuilder(), new FileLocator());

        $loader->load(__DIR__.'/../Fixtures/php/simple.php');

        $this->assertEquals('foo', $container->getParameter('foo'), '->load() loads a PHP file resource');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Loader;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\ClosureLoader;

class ClosureLoaderTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\DependencyInjection\Loader\ClosureLoader::supports
     */
    public function testSupports()
    {
        $loader = new ClosureLoader(new ContainerBuilder());

        $this->assertTrue($loader->supports(function ($container) {}), '->supports() returns true if the resource is loadable');
        $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Loader\ClosureLoader::load
     */
    public function testLoad()
    {
        $loader = new ClosureLoader($container = new ContainerBuilder());

        $loader->load(function ($container) {
            $container->setParameter('foo', 'foo');
        });

        $this->assertEquals('foo', $container->getParameter('foo'), '->load() loads a \Closure resource');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Loader;

use Symfony\Component\DependencyInjection\ContainerInterface;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\Config\Loader\Loader;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\ExpressionLanguage\Expression;

class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    protected static $fixturesPath;

    public static function setUpBeforeClass()
    {
        self::$fixturesPath = realpath(__DIR__.'/../Fixtures/');
        require_once self::$fixturesPath.'/includes/foo.php';
        require_once self::$fixturesPath.'/includes/ProjectExtension.php';
        require_once self::$fixturesPath.'/includes/ProjectWithXsdExtension.php';
    }

    public function testLoad()
    {
        $loader = new XmlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/ini'));

        try {
            $loader->load('foo.xml');
            $this->fail('->load() throws an InvalidArgumentException if the loaded file does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the loaded file does not exist');
            $this->assertStringStartsWith('The file "foo.xml" does not exist (in:', $e->getMessage(), '->load() throws an InvalidArgumentException if the loaded file does not exist');
        }
    }

    public function testParseFile()
    {
        $loader = new XmlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/ini'));
        $r = new \ReflectionObject($loader);
        $m = $r->getMethod('parseFile');
        $m->setAccessible(true);

        try {
            $m->invoke($loader, self::$fixturesPath.'/ini/parameters.ini');
            $this->fail('->parseFile() throws an InvalidArgumentException if the loaded file is not a valid XML file');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->parseFile() throws an InvalidArgumentException if the loaded file is not a valid XML file');
            $this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'parameters.ini'), $e->getMessage(), '->parseFile() throws an InvalidArgumentException if the loaded file is not a valid XML file');

            $e = $e->getPrevious();
            $this->assertInstanceOf('InvalidArgumentException', $e, '->parseFile() throws an InvalidArgumentException if the loaded file is not a valid XML file');
            $this->assertStringStartsWith('[ERROR 4] Start tag expected, \'<\' not found (in', $e->getMessage(), '->parseFile() throws an InvalidArgumentException if the loaded file is not a valid XML file');
        }

        $loader = new XmlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/xml'));

        try {
            $m->invoke($loader, self::$fixturesPath.'/xml/nonvalid.xml');
            $this->fail('->parseFile() throws an InvalidArgumentException if the loaded file does not validate the XSD');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->parseFile() throws an InvalidArgumentException if the loaded file does not validate the XSD');
            $this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'nonvalid.xml'), $e->getMessage(), '->parseFile() throws an InvalidArgumentException if the loaded file is not a valid XML file');

            $e = $e->getPrevious();
            $this->assertInstanceOf('InvalidArgumentException', $e, '->parseFile() throws an InvalidArgumentException if the loaded file does not validate the XSD');
            $this->assertStringStartsWith('[ERROR 1845] Element \'nonvalid\': No matching global declaration available for the validation root. (in', $e->getMessage(), '->parseFile() throws an InvalidArgumentException if the loaded file does not validate the XSD');
        }

        $xml = $m->invoke($loader, self::$fixturesPath.'/xml/services1.xml');
        $this->assertEquals('Symfony\\Component\\DependencyInjection\\SimpleXMLElement', get_class($xml), '->parseFile() returns an SimpleXMLElement object');
    }

    public function testLoadParameters()
    {
        $container = new ContainerBuilder();
        $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
        $loader->load('services2.xml');

        $actual = $container->getParameterBag()->all();
        $expected = array(
            'a string',
            'foo' => 'bar',
            'values' => array(
                0,
                'integer' => 4,
                100 => null,
                'true',
                true,
                false,
                'on',
                'off',
                'float' => 1.3,
                1000.3,
                'a string',
                array('foo', 'bar'),
            ),
            'foo_bar' => new Reference('foo_bar'),
            'mixedcase' => array('MixedCaseKey' => 'value'),
            'constant' => PHP_EOL,
        );

        $this->assertEquals($expected, $actual, '->load() converts XML values to PHP ones');
    }

    public function testLoadImports()
    {
        $container = new ContainerBuilder();
        $resolver = new LoaderResolver(array(
            new IniFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')),
            new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')),
            $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')),
        ));
        $loader->setResolver($resolver);
        $loader->load('services4.xml');

        $actual = $container->getParameterBag()->all();
        $expected = array(
            'a string',
            'foo' => 'bar',
            'values' => array(
                0,
                'integer' => 4,
                100 => null,
                'true',
                true,
                false,
                'on',
                'off',
                'float' => 1.3,
                1000.3,
                'a string',
                array('foo', 'bar'),
            ),
            'foo_bar' => new Reference('foo_bar'),
            'mixedcase' => array('MixedCaseKey' => 'value'),
            'constant' => PHP_EOL,
            'bar' => '%foo%',
            'imported_from_ini' => true,
            'imported_from_yaml' => true
        );

        $this->assertEquals(array_keys($expected), array_keys($actual), '->load() imports and merges imported files');

        // Bad import throws no exception due to ignore_errors value.
        $loader->load('services4_bad_import.xml');
    }

    public function testLoadAnonymousServices()
    {
        $container = new ContainerBuilder();
        $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
        $loader->load('services5.xml');
        $services = $container->getDefinitions();
        $this->assertEquals(4, count($services), '->load() attributes unique ids to anonymous services');

        // anonymous service as an argument
        $args = $services['foo']->getArguments();
        $this->assertEquals(1, count($args), '->load() references anonymous services as "normal" ones');
        $this->assertEquals('Symfony\\Component\\DependencyInjection\\Reference', get_class($args[0]), '->load() converts anonymous services to references to "normal" services');
        $this->assertTrue(isset($services[(string) $args[0]]), '->load() makes a reference to the created ones');
        $inner = $services[(string) $args[0]];
        $this->assertEquals('BarClass', $inner->getClass(), '->load() uses the same configuration as for the anonymous ones');

        // inner anonymous services
        $args = $inner->getArguments();
        $this->assertEquals(1, count($args), '->load() references anonymous services as "normal" ones');
        $this->assertEquals('Symfony\\Component\\DependencyInjection\\Reference', get_class($args[0]), '->load() converts anonymous services to references to "normal" services');
        $this->assertTrue(isset($services[(string) $args[0]]), '->load() makes a reference to the created ones');
        $inner = $services[(string) $args[0]];
        $this->assertEquals('BazClass', $inner->getClass(), '->load() uses the same configuration as for the anonymous ones');

        // anonymous service as a property
        $properties = $services['foo']->getProperties();
        $property = $properties['p'];
        $this->assertEquals('Symfony\\Component\\DependencyInjection\\Reference', get_class($property), '->load() converts anonymous services to references to "normal" services');
        $this->assertTrue(isset($services[(string) $property]), '->load() makes a reference to the created ones');
        $inner = $services[(string) $property];
        $this->assertEquals('BazClass', $inner->getClass(), '->load() uses the same configuration as for the anonymous ones');
    }

    public function testLoadServices()
    {
        $container = new ContainerBuilder();
        $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
        $loader->load('services6.xml');
        $services = $container->getDefinitions();
        $this->assertTrue(isset($services['foo']), '->load() parses <service> elements');
        $this->assertEquals('Symfony\\Component\\DependencyInjection\\Definition', get_class($services['foo']), '->load() converts <service> element to Definition instances');
        $this->assertEquals('FooClass', $services['foo']->getClass(), '->load() parses the class attribute');
        $this->assertEquals('container', $services['scope.container']->getScope());
        $this->assertEquals('custom', $services['scope.custom']->getScope());
        $this->assertEquals('prototype', $services['scope.prototype']->getScope());
        $this->assertEquals('getInstance', $services['constructor']->getFactoryMethod(), '->load() parses the factory-method attribute');
        $this->assertEquals('%path%/foo.php', $services['file']->getFile(), '->load() parses the file tag');
        $this->assertEquals(array('foo', new Reference('foo'), array(true, false)), $services['arguments']->getArguments(), '->load() parses the argument tags');
        $this->assertEquals('sc_configure', $services['configurator1']->getConfigurator(), '->load() parses the configurator tag');
        $this->assertEquals(array(new Reference('baz', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false), 'configure'), $services['configurator2']->getConfigurator(), '->load() parses the configurator tag');
        $this->assertEquals(array('BazClass', 'configureStatic'), $services['configurator3']->getConfigurator(), '->load() parses the configurator tag');
        $this->assertEquals(array(array('setBar', array()), array('setBar', array(new Expression('service("foo").foo() ~ parameter("foo")')))), $services['method_call1']->getMethodCalls(), '->load() parses the method_call tag');
        $this->assertEquals(array(array('setBar', array('foo', new Reference('foo'), array(true, false)))), $services['method_call2']->getMethodCalls(), '->load() parses the method_call tag');
        $this->assertNull($services['factory_service']->getClass());
        $this->assertEquals('getInstance', $services['factory_service']->getFactoryMethod());
        $this->assertEquals('baz_factory', $services['factory_service']->getFactoryService());

        $this->assertTrue($services['request']->isSynthetic(), '->load() parses the synthetic flag');
        $this->assertTrue($services['request']->isSynchronized(), '->load() parses the synchronized flag');
        $this->assertTrue($services['request']->isLazy(), '->load() parses the lazy flag');

        $aliases = $container->getAliases();
        $this->assertTrue(isset($aliases['alias_for_foo']), '->load() parses <service> elements');
        $this->assertEquals('foo', (string) $aliases['alias_for_foo'], '->load() parses aliases');
        $this->assertTrue($aliases['alias_for_foo']->isPublic());
        $this->assertTrue(isset($aliases['another_alias_for_foo']));
        $this->assertEquals('foo', (string) $aliases['another_alias_for_foo']);
        $this->assertFalse($aliases['another_alias_for_foo']->isPublic());
    }

    public function testConvertDomElementToArray()
    {
        $doc = new \DOMDocument("1.0");
        $doc->loadXML('<foo>bar</foo>');
        $this->assertEquals('bar', XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');

        $doc = new \DOMDocument("1.0");
        $doc->loadXML('<foo foo="bar" />');
        $this->assertEquals(array('foo' => 'bar'), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');

        $doc = new \DOMDocument("1.0");
        $doc->loadXML('<foo><foo>bar</foo></foo>');
        $this->assertEquals(array('foo' => 'bar'), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');

        $doc = new \DOMDocument("1.0");
        $doc->loadXML('<foo><foo>bar<foo>bar</foo></foo></foo>');
        $this->assertEquals(array('foo' => array('value' => 'bar', 'foo' => 'bar')), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');

        $doc = new \DOMDocument("1.0");
        $doc->loadXML('<foo><foo></foo></foo>');
        $this->assertEquals(array('foo' => null), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');

        $doc = new \DOMDocument("1.0");
        $doc->loadXML('<foo><foo><!-- foo --></foo></foo>');
        $this->assertEquals(array('foo' => null), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');

        $doc = new \DOMDocument("1.0");
        $doc->loadXML('<foo><foo foo="bar"/><foo foo="bar"/></foo>');
        $this->assertEquals(array('foo' => array(array('foo' => 'bar'), array('foo' => 'bar'))), XmlFileLoader::convertDomElementToArray($doc->documentElement), '::convertDomElementToArray() converts a \DomElement to an array');
    }

    public function testExtensions()
    {
        $container = new ContainerBuilder();
        $container->registerExtension(new \ProjectExtension());
        $container->registerExtension(new \ProjectWithXsdExtension());
        $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));

        // extension without an XSD
        $loader->load('extensions/services1.xml');
        $container->compile();
        $services = $container->getDefinitions();
        $parameters = $container->getParameterBag()->all();

        $this->assertTrue(isset($services['project.service.bar']), '->load() parses extension elements');
        $this->assertTrue(isset($parameters['project.parameter.bar']), '->load() parses extension elements');

        $this->assertEquals('BAR', $services['project.service.foo']->getClass(), '->load() parses extension elements');
        $this->assertEquals('BAR', $parameters['project.parameter.foo'], '->load() parses extension elements');

        // extension with an XSD
        $container = new ContainerBuilder();
        $container->registerExtension(new \ProjectExtension());
        $container->registerExtension(new \ProjectWithXsdExtension());
        $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
        $loader->load('extensions/services2.xml');
        $container->compile();
        $services = $container->getDefinitions();
        $parameters = $container->getParameterBag()->all();

        $this->assertTrue(isset($services['project.service.bar']), '->load() parses extension elements');
        $this->assertTrue(isset($parameters['project.parameter.bar']), '->load() parses extension elements');

        $this->assertEquals('BAR', $services['project.service.foo']->getClass(), '->load() parses extension elements');
        $this->assertEquals('BAR', $parameters['project.parameter.foo'], '->load() parses extension elements');

        $container = new ContainerBuilder();
        $container->registerExtension(new \ProjectExtension());
        $container->registerExtension(new \ProjectWithXsdExtension());
        $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));

        // extension with an XSD (does not validate)
        try {
            $loader->load('extensions/services3.xml');
            $this->fail('->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
            $this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'services3.xml'), $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');

            $e = $e->getPrevious();
            $this->assertInstanceOf('InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
            $this->assertContains('The attribute \'bar\' is not allowed', $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
        }

        // non-registered extension
        try {
            $loader->load('extensions/services4.xml');
            $this->fail('->load() throws an InvalidArgumentException if the tag is not valid');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the tag is not valid');
            $this->assertStringStartsWith('There is no extension able to load the configuration for "project:bar" (in', $e->getMessage(), '->load() throws an InvalidArgumentException if the tag is not valid');
        }
    }

    public function testExtensionInPhar()
    {
        if (extension_loaded('suhosin') && false === strpos(ini_get('suhosin.executor.include.whitelist'), 'phar')) {
            $this->markTestSkipped('To run this test, add "phar" to the "suhosin.executor.include.whitelist" settings in your php.ini file.');
        }

        require_once self::$fixturesPath.'/includes/ProjectWithXsdExtensionInPhar.phar';

        // extension with an XSD in PHAR archive
        $container = new ContainerBuilder();
        $container->registerExtension(new \ProjectWithXsdExtensionInPhar());
        $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
        $loader->load('extensions/services6.xml');

        // extension with an XSD in PHAR archive (does not validate)
        try {
            $loader->load('extensions/services7.xml');
            $this->fail('->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
            $this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'services7.xml'), $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');

            $e = $e->getPrevious();
            $this->assertInstanceOf('InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
            $this->assertContains('The attribute \'bar\' is not allowed', $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration does not validate the XSD');
        }
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Loader\XmlFileLoader::supports
     */
    public function testSupports()
    {
        $loader = new XmlFileLoader(new ContainerBuilder(), new FileLocator());

        $this->assertTrue($loader->supports('foo.xml'), '->supports() returns true if the resource is loadable');
        $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable');
    }

    public function testNoNamingConflictsForAnonymousServices()
    {
        $container = new ContainerBuilder();

        $loader1 = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml/extension1'));
        $loader1->load('services.xml');
        $services = $container->getDefinitions();
        $this->assertEquals(2, count($services), '->load() attributes unique ids to anonymous services');
        $loader2 = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml/extension2'));
        $loader2->load('services.xml');
        $services = $container->getDefinitions();
        $this->assertEquals(4, count($services), '->load() attributes unique ids to anonymous services');

        $services = $container->getDefinitions();
        $args1 = $services['extension1.foo']->getArguments();
        $inner1 = $services[(string) $args1[0]];
        $this->assertEquals('BarClass1', $inner1->getClass(), '->load() uses the same configuration as for the anonymous ones');
        $args2 = $services['extension2.foo']->getArguments();
        $inner2 = $services[(string) $args2[0]];
        $this->assertEquals('BarClass2', $inner2->getClass(), '->load() uses the same configuration as for the anonymous ones');
    }

    public function testDocTypeIsNotAllowed()
    {
        $container = new ContainerBuilder();

        $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));

        // document types are not allowed.
        try {
            $loader->load('withdoctype.xml');
            $this->fail('->load() throws an InvalidArgumentException if the configuration contains a document type');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration contains a document type');
            $this->assertRegExp(sprintf('#^Unable to parse file ".+%s".$#', 'withdoctype.xml'), $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration contains a document type');

            $e = $e->getPrevious();
            $this->assertInstanceOf('InvalidArgumentException', $e, '->load() throws an InvalidArgumentException if the configuration contains a document type');
            $this->assertSame('Document types are not allowed.', $e->getMessage(), '->load() throws an InvalidArgumentException if the configuration contains a document type');
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\Loader;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
use Symfony\Component\Config\FileLocator;

class IniFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    protected static $fixturesPath;

    protected $container;
    protected $loader;

    public static function setUpBeforeClass()
    {
        self::$fixturesPath = realpath(__DIR__.'/../Fixtures/');
    }

    protected function setUp()
    {
        $this->container = new ContainerBuilder();
        $this->loader    = new IniFileLoader($this->container, new FileLocator(self::$fixturesPath.'/ini'));
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::__construct
     * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::load
     */
    public function testIniFileCanBeLoaded()
    {
        $this->loader->load('parameters.ini');
        $this->assertEquals(array('foo' => 'bar', 'bar' => '%foo%'), $this->container->getParameterBag()->all(), '->load() takes a single file name as its first argument');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::__construct
     * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::load
     *
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The file "foo.ini" does not exist (in:
     */
    public function testExceptionIsRaisedWhenIniFileDoesNotExist()
    {
        $this->loader->load('foo.ini');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::__construct
     * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::load
     *
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The "nonvalid.ini" file is not valid.
     */
    public function testExceptionIsRaisedWhenIniFileCannotBeParsed()
    {
        @$this->loader->load('nonvalid.ini');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Loader\IniFileLoader::supports
     */
    public function testSupports()
    {
        $loader = new IniFileLoader(new ContainerBuilder(), new FileLocator());

        $this->assertTrue($loader->supports('foo.ini'), '->supports() returns true if the resource is loadable');
        $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests;

use Symfony\Component\DependencyInjection\DefinitionDecorator;

class DefinitionDecoratorTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $def = new DefinitionDecorator('foo');

        $this->assertEquals('foo', $def->getParent());
        $this->assertEquals(array(), $def->getChanges());
    }

    /**
     * @dataProvider getPropertyTests
     */
    public function testSetProperty($property, $changeKey)
    {
        $def = new DefinitionDecorator('foo');

        $getter = 'get'.ucfirst($property);
        $setter = 'set'.ucfirst($property);

        $this->assertNull($def->$getter());
        $this->assertSame($def, $def->$setter('foo'));
        $this->assertEquals('foo', $def->$getter());
        $this->assertEquals(array($changeKey => true), $def->getChanges());
    }

    public function getPropertyTests()
    {
        return array(
            array('class', 'class'),
            array('factoryClass', 'factory_class'),
            array('factoryMethod', 'factory_method'),
            array('factoryService', 'factory_service'),
            array('configurator', 'configurator'),
            array('file', 'file'),
        );
    }

    public function testSetPublic()
    {
        $def = new DefinitionDecorator('foo');

        $this->assertTrue($def->isPublic());
        $this->assertSame($def, $def->setPublic(false));
        $this->assertFalse($def->isPublic());
        $this->assertEquals(array('public' => true), $def->getChanges());
    }

    public function testSetLazy()
    {
        $def = new DefinitionDecorator('foo');

        $this->assertFalse($def->isLazy());
        $this->assertSame($def, $def->setLazy(false));
        $this->assertFalse($def->isLazy());
        $this->assertEquals(array('lazy' => true), $def->getChanges());
    }

    public function testSetArgument()
    {
        $def = new DefinitionDecorator('foo');

        $this->assertEquals(array(), $def->getArguments());
        $this->assertSame($def, $def->replaceArgument(0, 'foo'));
        $this->assertEquals(array('index_0' => 'foo'), $def->getArguments());
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testReplaceArgumentShouldRequireIntegerIndex()
    {
        $def = new DefinitionDecorator('foo');

        $def->replaceArgument('0', 'foo');
    }

    public function testReplaceArgument()
    {
        $def = new DefinitionDecorator('foo');

        $def->setArguments(array(0 => 'foo', 1 => 'bar'));
        $this->assertEquals('foo', $def->getArgument(0));
        $this->assertEquals('bar', $def->getArgument(1));

        $this->assertSame($def, $def->replaceArgument(1, 'baz'));
        $this->assertEquals('foo', $def->getArgument(0));
        $this->assertEquals('baz', $def->getArgument(1));

        $this->assertEquals(array(0 => 'foo', 1 => 'bar', 'index_1' => 'baz'), $def->getArguments());
    }

    /**
     * @expectedException \OutOfBoundsException
     */
    public function testGetArgumentShouldCheckBounds()
    {
        $def = new DefinitionDecorator('foo');

        $def->setArguments(array(0 => 'foo'));
        $def->replaceArgument(0, 'foo');

        $def->getArgument(1);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\LazyProxy\Instantiator;

use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator;

/**
 * Tests for {@see \Symfony\Component\DependencyInjection\Instantiator\RealServiceInstantiator}
 *
 * @author Marco Pivetta <ocramius@gmail.com>
 *
 * @covers \Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator
 */
class RealServiceInstantiatorTest extends \PHPUnit_Framework_TestCase
{
    public function testInstantiateProxy()
    {
        $instantiator = new RealServiceInstantiator();
        $instance     = new \stdClass();
        $container    = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
        $callback     = function () use ($instance) {
            return $instance;
        };

        $this->assertSame($instance, $instantiator->instantiateProxy($container, new Definition(), 'foo', $callback));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\LazyProxy\PhpDumper;

use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper;

/**
 * Tests for {@see \Symfony\Component\DependencyInjection\PhpDumper\NullDumper}
 *
 * @author Marco Pivetta <ocramius@gmail.com>
 *
 * @covers \Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper
 */
class NullDumperTest extends \PHPUnit_Framework_TestCase
{
    public function testNullDumper()
    {
        $dumper     = new NullDumper();
        $definition = new Definition('stdClass');

        $this->assertFalse($dumper->isProxyCandidate($definition));
        $this->assertSame('', $dumper->getProxyFactoryCode($definition, 'foo'));
        $this->assertSame('', $dumper->getProxyCode($definition));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests;

use Symfony\Component\DependencyInjection\Definition;

class DefinitionTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\DependencyInjection\Definition::__construct
     */
    public function testConstructor()
    {
        $def = new Definition('stdClass');
        $this->assertEquals('stdClass', $def->getClass(), '__construct() takes the class name as its first argument');

        $def = new Definition('stdClass', array('foo'));
        $this->assertEquals(array('foo'), $def->getArguments(), '__construct() takes an optional array of arguments as its second argument');
    }

    public function testSetGetFactoryClass()
    {
        $def = new Definition('stdClass');
        $this->assertNull($def->getFactoryClass());
        $this->assertSame($def, $def->setFactoryClass('stdClass2'), "->setFactoryClass() implements a fluent interface.");
        $this->assertEquals('stdClass2', $def->getFactoryClass(), "->getFactoryClass() returns current class to construct this service.");
    }

    public function testSetGetFactoryMethod()
    {
        $def = new Definition('stdClass');
        $this->assertNull($def->getFactoryMethod());
        $this->assertSame($def, $def->setFactoryMethod('foo'), '->setFactoryMethod() implements a fluent interface');
        $this->assertEquals('foo', $def->getFactoryMethod(), '->getFactoryMethod() returns the factory method name');
    }

    public function testSetGetFactoryService()
    {
        $def = new Definition('stdClass');
        $this->assertNull($def->getFactoryService());
        $this->assertSame($def, $def->setFactoryService('foo.bar'), "->setFactoryService() implements a fluent interface.");
        $this->assertEquals('foo.bar', $def->getFactoryService(), "->getFactoryService() returns current service to construct this service.");
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::setClass
     * @covers Symfony\Component\DependencyInjection\Definition::getClass
     */
    public function testSetGetClass()
    {
        $def = new Definition('stdClass');
        $this->assertSame($def, $def->setClass('foo'), '->setClass() implements a fluent interface');
        $this->assertEquals('foo', $def->getClass(), '->getClass() returns the class name');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::setArguments
     * @covers Symfony\Component\DependencyInjection\Definition::getArguments
     * @covers Symfony\Component\DependencyInjection\Definition::addArgument
     */
    public function testArguments()
    {
        $def = new Definition('stdClass');
        $this->assertSame($def, $def->setArguments(array('foo')), '->setArguments() implements a fluent interface');
        $this->assertEquals(array('foo'), $def->getArguments(), '->getArguments() returns the arguments');
        $this->assertSame($def, $def->addArgument('bar'), '->addArgument() implements a fluent interface');
        $this->assertEquals(array('foo', 'bar'), $def->getArguments(), '->addArgument() adds an argument');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::setMethodCalls
     * @covers Symfony\Component\DependencyInjection\Definition::addMethodCall
     * @covers Symfony\Component\DependencyInjection\Definition::hasMethodCall
     * @covers Symfony\Component\DependencyInjection\Definition::removeMethodCall
     */
    public function testMethodCalls()
    {
        $def = new Definition('stdClass');
        $this->assertSame($def, $def->setMethodCalls(array(array('foo', array('foo')))), '->setMethodCalls() implements a fluent interface');
        $this->assertEquals(array(array('foo', array('foo'))), $def->getMethodCalls(), '->getMethodCalls() returns the methods to call');
        $this->assertSame($def, $def->addMethodCall('bar', array('bar')), '->addMethodCall() implements a fluent interface');
        $this->assertEquals(array(array('foo', array('foo')), array('bar', array('bar'))), $def->getMethodCalls(), '->addMethodCall() adds a method to call');
        $this->assertTrue($def->hasMethodCall('bar'), '->hasMethodCall() returns true if first argument is a method to call registered');
        $this->assertFalse($def->hasMethodCall('no_registered'), '->hasMethodCall() returns false if first argument is not a method to call registered');
        $this->assertSame($def, $def->removeMethodCall('bar'), '->removeMethodCall() implements a fluent interface');
        $this->assertEquals(array(array('foo', array('foo'))), $def->getMethodCalls(), '->removeMethodCall() removes a method to call');
    }

    /**
     * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
     * @expectedExceptionMessage Method name cannot be empty.
     */
    public function testExceptionOnEmptyMethodCall()
    {
        $def = new Definition('stdClass');
        $def->addMethodCall('');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::setFile
     * @covers Symfony\Component\DependencyInjection\Definition::getFile
     */
    public function testSetGetFile()
    {
        $def = new Definition('stdClass');
        $this->assertSame($def, $def->setFile('foo'), '->setFile() implements a fluent interface');
        $this->assertEquals('foo', $def->getFile(), '->getFile() returns the file to include');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::setScope
     * @covers Symfony\Component\DependencyInjection\Definition::getScope
     */
    public function testSetGetScope()
    {
        $def = new Definition('stdClass');
        $this->assertEquals('container', $def->getScope());
        $this->assertSame($def, $def->setScope('foo'));
        $this->assertEquals('foo', $def->getScope());
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::setPublic
     * @covers Symfony\Component\DependencyInjection\Definition::isPublic
     */
    public function testSetIsPublic()
    {
        $def = new Definition('stdClass');
        $this->assertTrue($def->isPublic(), '->isPublic() returns true by default');
        $this->assertSame($def, $def->setPublic(false), '->setPublic() implements a fluent interface');
        $this->assertFalse($def->isPublic(), '->isPublic() returns false if the instance must not be public.');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::setSynthetic
     * @covers Symfony\Component\DependencyInjection\Definition::isSynthetic
     */
    public function testSetIsSynthetic()
    {
        $def = new Definition('stdClass');
        $this->assertFalse($def->isSynthetic(), '->isSynthetic() returns false by default');
        $this->assertSame($def, $def->setSynthetic(true), '->setSynthetic() implements a fluent interface');
        $this->assertTrue($def->isSynthetic(), '->isSynthetic() returns true if the service is synthetic.');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::setSynchronized
     * @covers Symfony\Component\DependencyInjection\Definition::isSynchronized
     */
    public function testSetIsSynchronized()
    {
        $def = new Definition('stdClass');
        $this->assertFalse($def->isSynchronized(), '->isSynchronized() returns false by default');
        $this->assertSame($def, $def->setSynchronized(true), '->setSynchronized() implements a fluent interface');
        $this->assertTrue($def->isSynchronized(), '->isSynchronized() returns true if the service is synchronized.');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::setLazy
     * @covers Symfony\Component\DependencyInjection\Definition::isLazy
     */
    public function testSetIsLazy()
    {
        $def = new Definition('stdClass');
        $this->assertFalse($def->isLazy(), '->isLazy() returns false by default');
        $this->assertSame($def, $def->setLazy(true), '->setLazy() implements a fluent interface');
        $this->assertTrue($def->isLazy(), '->isLazy() returns true if the service is lazy.');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::setAbstract
     * @covers Symfony\Component\DependencyInjection\Definition::isAbstract
     */
    public function testSetIsAbstract()
    {
        $def = new Definition('stdClass');
        $this->assertFalse($def->isAbstract(), '->isAbstract() returns false by default');
        $this->assertSame($def, $def->setAbstract(true), '->setAbstract() implements a fluent interface');
        $this->assertTrue($def->isAbstract(), '->isAbstract() returns true if the instance must not be public.');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::setConfigurator
     * @covers Symfony\Component\DependencyInjection\Definition::getConfigurator
     */
    public function testSetGetConfigurator()
    {
        $def = new Definition('stdClass');
        $this->assertSame($def, $def->setConfigurator('foo'), '->setConfigurator() implements a fluent interface');
        $this->assertEquals('foo', $def->getConfigurator(), '->getConfigurator() returns the configurator');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::clearTags
     */
    public function testClearTags()
    {
        $def = new Definition('stdClass');
        $this->assertSame($def, $def->clearTags(), '->clearTags() implements a fluent interface');
        $def->addTag('foo', array('foo' => 'bar'));
        $def->clearTags();
        $this->assertEquals(array(), $def->getTags(), '->clearTags() removes all current tags');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::clearTags
     */
    public function testClearTag()
    {
        $def = new Definition('stdClass');
        $this->assertSame($def, $def->clearTags(), '->clearTags() implements a fluent interface');
        $def->addTag('1foo1', array('foo1' => 'bar1'));
        $def->addTag('2foo2', array('foo2' => 'bar2'));
        $def->addTag('3foo3', array('foo3' => 'bar3'));
        $def->clearTag('2foo2');
        $this->assertTrue($def->hasTag('1foo1'));
        $this->assertFalse($def->hasTag('2foo2'));
        $this->assertTrue($def->hasTag('3foo3'));
        $def->clearTag('1foo1');
        $this->assertFalse($def->hasTag('1foo1'));
        $this->assertTrue($def->hasTag('3foo3'));
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::addTag
     * @covers Symfony\Component\DependencyInjection\Definition::getTag
     * @covers Symfony\Component\DependencyInjection\Definition::getTags
     * @covers Symfony\Component\DependencyInjection\Definition::hasTag
     */
    public function testTags()
    {
        $def = new Definition('stdClass');
        $this->assertEquals(array(), $def->getTag('foo'), '->getTag() returns an empty array if the tag is not defined');
        $this->assertFalse($def->hasTag('foo'));
        $this->assertSame($def, $def->addTag('foo'), '->addTag() implements a fluent interface');
        $this->assertTrue($def->hasTag('foo'));
        $this->assertEquals(array(array()), $def->getTag('foo'), '->getTag() returns attributes for a tag name');
        $def->addTag('foo', array('foo' => 'bar'));
        $this->assertEquals(array(array(), array('foo' => 'bar')), $def->getTag('foo'), '->addTag() can adds the same tag several times');
        $def->addTag('bar', array('bar' => 'bar'));
        $this->assertEquals($def->getTags(), array(
            'foo' => array(array(), array('foo' => 'bar')),
            'bar' => array(array('bar' => 'bar')),
        ), '->getTags() returns all tags');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Definition::replaceArgument
     */
    public function testSetArgument()
    {
        $def = new Definition('stdClass');

        $def->addArgument('foo');
        $this->assertSame(array('foo'), $def->getArguments());

        $this->assertSame($def, $def->replaceArgument(0, 'moo'));
        $this->assertSame(array('moo'), $def->getArguments());

        $def->addArgument('moo');
        $def
            ->replaceArgument(0, 'foo')
            ->replaceArgument(1, 'bar')
        ;
        $this->assertSame(array('foo', 'bar'), $def->getArguments());
    }

    /**
     * @expectedException \OutOfBoundsException
     */
    public function testGetArgumentShouldCheckBounds()
    {
        $def = new Definition('stdClass');

        $def->addArgument('foo');
        $def->getArgument(1);
    }

    /**
     * @expectedException \OutOfBoundsException
     */
    public function testReplaceArgumentShouldCheckBounds()
    {
        $def = new Definition('stdClass');

        $def->addArgument('foo');
        $def->replaceArgument(1, 'bar');
    }

    public function testSetGetProperties()
    {
        $def = new Definition('stdClass');

        $this->assertEquals(array(), $def->getProperties());
        $this->assertSame($def, $def->setProperties(array('foo' => 'bar')));
        $this->assertEquals(array('foo' => 'bar'), $def->getProperties());
    }

    public function testSetProperty()
    {
        $def = new Definition('stdClass');

        $this->assertEquals(array(), $def->getProperties());
        $this->assertSame($def, $def->setProperty('foo', 'bar'));
        $this->assertEquals(array('foo' => 'bar'), $def->getProperties());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\ParameterBag;

use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;

class ParameterBagTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::__construct
     */
    public function testConstructor()
    {
        $bag = new ParameterBag($parameters = array(
            'foo' => 'foo',
            'bar' => 'bar',
        ));
        $this->assertEquals($parameters, $bag->all(), '__construct() takes an array of parameters as its first argument');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::clear
     */
    public function testClear()
    {
        $bag = new ParameterBag($parameters = array(
            'foo' => 'foo',
            'bar' => 'bar',
        ));
        $bag->clear();
        $this->assertEquals(array(), $bag->all(), '->clear() removes all parameters');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::remove
     */
    public function testRemove()
    {
        $bag = new ParameterBag(array(
            'foo' => 'foo',
            'bar' => 'bar',
        ));
        $bag->remove('foo');
        $this->assertEquals(array('bar' => 'bar'), $bag->all(), '->remove() removes a parameter');
        $bag->remove('BAR');
        $this->assertEquals(array(), $bag->all(), '->remove() converts key to lowercase before removing');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::get
     * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::set
     */
    public function testGetSet()
    {
        $bag = new ParameterBag(array('foo' => 'bar'));
        $bag->set('bar', 'foo');
        $this->assertEquals('foo', $bag->get('bar'), '->set() sets the value of a new parameter');

        $bag->set('foo', 'baz');
        $this->assertEquals('baz', $bag->get('foo'), '->set() overrides previously set parameter');

        $bag->set('Foo', 'baz1');
        $this->assertEquals('baz1', $bag->get('foo'), '->set() converts the key to lowercase');
        $this->assertEquals('baz1', $bag->get('FOO'), '->get() converts the key to lowercase');

        try {
            $bag->get('baba');
            $this->fail('->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException', $e, '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist');
            $this->assertEquals('You have requested a non-existent parameter "baba".', $e->getMessage(), '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist');
        }
    }

    public function testGetThrowParameterNotFoundException()
    {
        $bag = new ParameterBag(array(
            'foo' => 'foo',
            'bar' => 'bar',
            'baz' => 'baz',
        ));

        try {
            $bag->get('foo1');
            $this->fail('->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException', $e, '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist');
            $this->assertEquals('You have requested a non-existent parameter "foo1". Did you mean this: "foo"?', $e->getMessage(), '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException with some advices');
        }

        try {
            $bag->get('bag');
            $this->fail('->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException', $e, '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist');
            $this->assertEquals('You have requested a non-existent parameter "bag". Did you mean one of these: "bar", "baz"?', $e->getMessage(), '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException with some advices');
        }

        try {
            $bag->get('');
            $this->fail('->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException', $e, '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist');
            $this->assertEquals('You have requested a non-existent parameter "".', $e->getMessage(), '->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException with some advices');
        }
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::has
     */
    public function testHas()
    {
        $bag = new ParameterBag(array('foo' => 'bar'));
        $this->assertTrue($bag->has('foo'), '->has() returns true if a parameter is defined');
        $this->assertTrue($bag->has('Foo'), '->has() converts the key to lowercase');
        $this->assertFalse($bag->has('bar'), '->has() returns false if a parameter is not defined');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::resolveValue
     */
    public function testResolveValue()
    {
        $bag = new ParameterBag(array());
        $this->assertEquals('foo', $bag->resolveValue('foo'), '->resolveValue() returns its argument unmodified if no placeholders are found');

        $bag = new ParameterBag(array('foo' => 'bar'));
        $this->assertEquals('I\'m a bar', $bag->resolveValue('I\'m a %foo%'), '->resolveValue() replaces placeholders by their values');
        $this->assertEquals(array('bar' => 'bar'), $bag->resolveValue(array('%foo%' => '%foo%')), '->resolveValue() replaces placeholders in keys and values of arrays');
        $this->assertEquals(array('bar' => array('bar' => array('bar' => 'bar'))), $bag->resolveValue(array('%foo%' => array('%foo%' => array('%foo%' => '%foo%')))), '->resolveValue() replaces placeholders in nested arrays');
        $this->assertEquals('I\'m a %%foo%%', $bag->resolveValue('I\'m a %%foo%%'), '->resolveValue() supports % escaping by doubling it');
        $this->assertEquals('I\'m a bar %%foo bar', $bag->resolveValue('I\'m a %foo% %%foo %foo%'), '->resolveValue() supports % escaping by doubling it');
        $this->assertEquals(array('foo' => array('bar' => array('ding' => 'I\'m a bar %%foo %%bar'))), $bag->resolveValue(array('foo' => array('bar' => array('ding' => 'I\'m a bar %%foo %%bar')))), '->resolveValue() supports % escaping by doubling it');

        $bag = new ParameterBag(array('foo' => true));
        $this->assertTrue($bag->resolveValue('%foo%'), '->resolveValue() replaces arguments that are just a placeholder by their value without casting them to strings');
        $bag = new ParameterBag(array('foo' => null));
        $this->assertNull($bag->resolveValue('%foo%'), '->resolveValue() replaces arguments that are just a placeholder by their value without casting them to strings');

        $bag = new ParameterBag(array('foo' => 'bar', 'baz' => '%%%foo% %foo%%% %%foo%% %%%foo%%%'));
        $this->assertEquals('%%bar bar%% %%foo%% %%bar%%', $bag->resolveValue('%baz%'), '->resolveValue() replaces params placed besides escaped %');

        $bag = new ParameterBag(array('baz' => '%%s?%%s'));
        $this->assertEquals('%%s?%%s', $bag->resolveValue('%baz%'), '->resolveValue() is not replacing greedily');

        $bag = new ParameterBag(array());
        try {
            $bag->resolveValue('%foobar%');
            $this->fail('->resolveValue() throws an InvalidArgumentException if a placeholder references a non-existent parameter');
        } catch (ParameterNotFoundException $e) {
            $this->assertEquals('You have requested a non-existent parameter "foobar".', $e->getMessage(), '->resolveValue() throws a ParameterNotFoundException if a placeholder references a non-existent parameter');
        }

        try {
            $bag->resolveValue('foo %foobar% bar');
            $this->fail('->resolveValue() throws a ParameterNotFoundException if a placeholder references a non-existent parameter');
        } catch (ParameterNotFoundException $e) {
            $this->assertEquals('You have requested a non-existent parameter "foobar".', $e->getMessage(), '->resolveValue() throws a ParameterNotFoundException if a placeholder references a non-existent parameter');
        }

        $bag = new ParameterBag(array('foo' => 'a %bar%', 'bar' => array()));
        try {
            $bag->resolveValue('%foo%');
            $this->fail('->resolveValue() throws a RuntimeException when a parameter embeds another non-string parameter');
        } catch (RuntimeException $e) {
            $this->assertEquals('A string value must be composed of strings and/or numbers, but found parameter "bar" of type array inside string value "a %bar%".', $e->getMessage(), '->resolveValue() throws a RuntimeException when a parameter embeds another non-string parameter');
        }

        $bag = new ParameterBag(array('foo' => '%bar%', 'bar' => '%foobar%', 'foobar' => '%foo%'));
        try {
            $bag->resolveValue('%foo%');
            $this->fail('->resolveValue() throws a ParameterCircularReferenceException when a parameter has a circular reference');
        } catch (ParameterCircularReferenceException $e) {
            $this->assertEquals('Circular reference detected for parameter "foo" ("foo" > "bar" > "foobar" > "foo").', $e->getMessage(), '->resolveValue() throws a ParameterCircularReferenceException when a parameter has a circular reference');
        }

        $bag = new ParameterBag(array('foo' => 'a %bar%', 'bar' => 'a %foobar%', 'foobar' => 'a %foo%'));
        try {
            $bag->resolveValue('%foo%');
            $this->fail('->resolveValue() throws a ParameterCircularReferenceException when a parameter has a circular reference');
        } catch (ParameterCircularReferenceException $e) {
            $this->assertEquals('Circular reference detected for parameter "foo" ("foo" > "bar" > "foobar" > "foo").', $e->getMessage(), '->resolveValue() throws a ParameterCircularReferenceException when a parameter has a circular reference');
        }

        $bag = new ParameterBag(array('host' => 'foo.bar', 'port' => 1337));
        $this->assertEquals('foo.bar:1337', $bag->resolveValue('%host%:%port%'));
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::resolve
     */
    public function testResolveIndicatesWhyAParameterIsNeeded()
    {
        $bag = new ParameterBag(array('foo' => '%bar%'));

        try {
            $bag->resolve();
        } catch (ParameterNotFoundException $e) {
            $this->assertEquals('The parameter "foo" has a dependency on a non-existent parameter "bar".', $e->getMessage());
        }

        $bag = new ParameterBag(array('foo' => '%bar%'));

        try {
            $bag->resolve();
        } catch (ParameterNotFoundException $e) {
            $this->assertEquals('The parameter "foo" has a dependency on a non-existent parameter "bar".', $e->getMessage());
        }
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::resolve
     */
    public function testResolveUnescapesValue()
    {
        $bag = new ParameterBag(array(
            'foo' => array('bar' => array('ding' => 'I\'m a bar %%foo %%bar')),
            'bar' => 'I\'m a %%foo%%',
        ));

        $bag->resolve();

        $this->assertEquals('I\'m a %foo%', $bag->get('bar'), '->resolveValue() supports % escaping by doubling it');
        $this->assertEquals(array('bar' => array('ding' => 'I\'m a bar %foo %bar')), $bag->get('foo'), '->resolveValue() supports % escaping by doubling it');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::escapeValue
     */
    public function testEscapeValue()
    {
        $bag = new ParameterBag();

        $bag->add(array(
            'foo' => $bag->escapeValue(array('bar' => array('ding' => 'I\'m a bar %foo %bar', 'zero' => null))),
            'bar' => $bag->escapeValue('I\'m a %foo%'),
        ));

        $this->assertEquals('I\'m a %%foo%%', $bag->get('bar'), '->escapeValue() escapes % by doubling it');
        $this->assertEquals(array('bar' => array('ding' => 'I\'m a bar %%foo %%bar', 'zero' => null)), $bag->get('foo'), '->escapeValue() escapes % by doubling it');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\ParameterBag::resolve
     * @dataProvider stringsWithSpacesProvider
     */
    public function testResolveStringWithSpacesReturnsString($expected, $test, $description)
    {
        $bag = new ParameterBag(array('foo' => 'bar'));

        try {
            $this->assertEquals($expected, $bag->resolveString($test), $description);
        } catch (ParameterNotFoundException $e) {
            $this->fail(sprintf('%s - "%s"', $description, $expected));
        }
    }

    public function stringsWithSpacesProvider()
    {
        return array(
            array('bar', '%foo%', 'Parameters must be wrapped by %.'),
            array('% foo %', '% foo %', 'Parameters should not have spaces.'),
            array('{% set my_template = "foo" %}', '{% set my_template = "foo" %}', 'Twig-like strings are not parameters.'),
            array('50% is less than 100%', '50% is less than 100%', 'Text between % signs is allowed, if there are spaces.'),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests\ParameterBag;

use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;

class FrozenParameterBagTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag::__construct
     */
    public function testConstructor()
    {
        $parameters = array(
            'foo' => 'foo',
            'bar' => 'bar',
        );
        $bag = new FrozenParameterBag($parameters);
        $this->assertEquals($parameters, $bag->all(), '__construct() takes an array of parameters as its first argument');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag::clear
     * @expectedException \LogicException
     */
    public function testClear()
    {
        $bag = new FrozenParameterBag(array());
        $bag->clear();
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag::set
     * @expectedException \LogicException
     */
    public function testSet()
    {
        $bag = new FrozenParameterBag(array());
        $bag->set('foo', 'bar');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag::add
     * @expectedException \LogicException
     */
    public function testAdd()
    {
        $bag = new FrozenParameterBag(array());
        $bag->add(array());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests;

use Symfony\Component\DependencyInjection\Scope;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;

class ContainerTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\DependencyInjection\Container::__construct
     */
    public function testConstructor()
    {
        $sc = new Container();
        $this->assertSame($sc, $sc->get('service_container'), '__construct() automatically registers itself as a service');

        $sc = new Container(new ParameterBag(array('foo' => 'bar')));
        $this->assertEquals(array('foo' => 'bar'), $sc->getParameterBag()->all(), '__construct() takes an array of parameters as its first argument');
    }

    /**
     * @dataProvider dataForTestCamelize
     */
    public function testCamelize($id, $expected)
    {
        $this->assertEquals($expected, Container::camelize($id), sprintf('Container::camelize("%s")', $id));
    }

    public function dataForTestCamelize()
    {
        return array(
            array('foo_bar', 'FooBar'),
            array('foo.bar', 'Foo_Bar'),
            array('foo.bar_baz', 'Foo_BarBaz'),
            array('foo._bar', 'Foo_Bar'),
            array('foo_.bar', 'Foo_Bar'),
            array('_foo', 'Foo'),
            array('.foo', '_Foo'),
            array('foo_', 'Foo'),
            array('foo.', 'Foo_'),
            array('foo\bar', 'Foo_Bar'),
        );
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Container::compile
     */
    public function testCompile()
    {
        $sc = new Container(new ParameterBag(array('foo' => 'bar')));
        $sc->compile();
        $this->assertInstanceOf('Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag', $sc->getParameterBag(), '->compile() changes the parameter bag to a FrozenParameterBag instance');
        $this->assertEquals(array('foo' => 'bar'), $sc->getParameterBag()->all(), '->compile() copies the current parameters to the new parameter bag');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Container::isFrozen
     */
    public function testIsFrozen()
    {
        $sc = new Container(new ParameterBag(array('foo' => 'bar')));
        $this->assertFalse($sc->isFrozen(), '->isFrozen() returns false if the parameters are not frozen');
        $sc->compile();
        $this->assertTrue($sc->isFrozen(), '->isFrozen() returns true if the parameters are frozen');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Container::getParameterBag
     */
    public function testGetParameterBag()
    {
        $sc = new Container();
        $this->assertEquals(array(), $sc->getParameterBag()->all(), '->getParameterBag() returns an empty array if no parameter has been defined');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Container::setParameter
     * @covers Symfony\Component\DependencyInjection\Container::getParameter
     */
    public function testGetSetParameter()
    {
        $sc = new Container(new ParameterBag(array('foo' => 'bar')));
        $sc->setParameter('bar', 'foo');
        $this->assertEquals('foo', $sc->getParameter('bar'), '->setParameter() sets the value of a new parameter');

        $sc->setParameter('foo', 'baz');
        $this->assertEquals('baz', $sc->getParameter('foo'), '->setParameter() overrides previously set parameter');

        $sc->setParameter('Foo', 'baz1');
        $this->assertEquals('baz1', $sc->getParameter('foo'), '->setParameter() converts the key to lowercase');
        $this->assertEquals('baz1', $sc->getParameter('FOO'), '->getParameter() converts the key to lowercase');

        try {
            $sc->getParameter('baba');
            $this->fail('->getParameter() thrown an \InvalidArgumentException if the key does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->getParameter() thrown an \InvalidArgumentException if the key does not exist');
            $this->assertEquals('You have requested a non-existent parameter "baba".', $e->getMessage(), '->getParameter() thrown an \InvalidArgumentException if the key does not exist');
        }
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Container::getServiceIds
     */
    public function testGetServiceIds()
    {
        $sc = new Container();
        $sc->set('foo', $obj = new \stdClass());
        $sc->set('bar', $obj = new \stdClass());
        $this->assertEquals(array('service_container', 'foo', 'bar'), $sc->getServiceIds(), '->getServiceIds() returns all defined service ids');

        $sc = new ProjectServiceContainer();
        $this->assertEquals(array('scoped', 'scoped_foo', 'inactive', 'bar', 'foo_bar', 'foo.baz', 'circular', 'throw_exception', 'throws_exception_on_service_configuration', 'service_container'), $sc->getServiceIds(), '->getServiceIds() returns defined service ids by getXXXService() methods');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Container::set
     */
    public function testSet()
    {
        $sc = new Container();
        $sc->set('foo', $foo = new \stdClass());
        $this->assertEquals($foo, $sc->get('foo'), '->set() sets a service');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Container::set
     */
    public function testSetWithNullResetTheService()
    {
        $sc = new Container();
        $sc->set('foo', null);
        $this->assertFalse($sc->has('foo'));
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testSetDoesNotAllowPrototypeScope()
    {
        $c = new Container();
        $c->set('foo', new \stdClass(), 'prototype');
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testSetDoesNotAllowInactiveScope()
    {
        $c = new Container();
        $c->addScope(new Scope('foo'));
        $c->set('foo', new \stdClass(), 'foo');
    }

    public function testSetAlsoSetsScopedService()
    {
        $c = new Container();
        $c->addScope(new Scope('foo'));
        $c->enterScope('foo');
        $c->set('foo', $foo = new \stdClass(), 'foo');

        $services = $this->getField($c, 'scopedServices');
        $this->assertTrue(isset($services['foo']['foo']));
        $this->assertSame($foo, $services['foo']['foo']);
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Container::get
     */
    public function testGet()
    {
        $sc = new ProjectServiceContainer();
        $sc->set('foo', $foo = new \stdClass());
        $this->assertEquals($foo, $sc->get('foo'), '->get() returns the service for the given id');
        $this->assertEquals($sc->__bar, $sc->get('bar'), '->get() returns the service for the given id');
        $this->assertEquals($sc->__foo_bar, $sc->get('foo_bar'), '->get() returns the service if a get*Method() is defined');
        $this->assertEquals($sc->__foo_baz, $sc->get('foo.baz'), '->get() returns the service if a get*Method() is defined');

        $sc->set('bar', $bar = new \stdClass());
        $this->assertEquals($bar, $sc->get('bar'), '->get() prefers to return a service defined with set() than one defined with a getXXXMethod()');

        try {
            $sc->get('');
            $this->fail('->get() throws a \InvalidArgumentException exception if the service is empty');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException', $e, '->get() throws a ServiceNotFoundException exception if the service is empty');
        }
        $this->assertNull($sc->get('', ContainerInterface::NULL_ON_INVALID_REFERENCE));
    }

    public function testGetThrowServiceNotFoundException()
    {
        $sc = new ProjectServiceContainer();
        $sc->set('foo', $foo = new \stdClass());
        $sc->set('bar', $foo = new \stdClass());
        $sc->set('baz', $foo = new \stdClass());

        try {
            $sc->get('foo1');
            $this->fail('->get() throws an Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException if the key does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException', $e, '->get() throws an Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException if the key does not exist');
            $this->assertEquals('You have requested a non-existent service "foo1". Did you mean this: "foo"?', $e->getMessage(), '->get() throws an Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException with some advices');
        }

        try {
            $sc->get('bag');
            $this->fail('->get() throws an Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException if the key does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException', $e, '->get() throws an Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException if the key does not exist');
            $this->assertEquals('You have requested a non-existent service "bag". Did you mean one of these: "bar", "baz"?', $e->getMessage(), '->get() throws an Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException with some advices');
        }
    }

    public function testGetCircularReference()
    {

        $sc = new ProjectServiceContainer();
        try {
            $sc->get('circular');
            $this->fail('->get() throws a ServiceCircularReferenceException if it contains circular reference');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException', $e, '->get() throws a ServiceCircularReferenceException if it contains circular reference');
            $this->assertStringStartsWith('Circular reference detected for service "circular"', $e->getMessage(), '->get() throws a \LogicException if it contains circular reference');
        }
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Container::get
     */
    public function testGetReturnsNullOnInactiveScope()
    {
        $sc = new ProjectServiceContainer();
        $this->assertNull($sc->get('inactive', ContainerInterface::NULL_ON_INVALID_REFERENCE));
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Container::has
     */
    public function testHas()
    {
        $sc = new ProjectServiceContainer();
        $sc->set('foo', new \stdClass());
        $this->assertFalse($sc->has('foo1'), '->has() returns false if the service does not exist');
        $this->assertTrue($sc->has('foo'), '->has() returns true if the service exists');
        $this->assertTrue($sc->has('bar'), '->has() returns true if a get*Method() is defined');
        $this->assertTrue($sc->has('foo_bar'), '->has() returns true if a get*Method() is defined');
        $this->assertTrue($sc->has('foo.baz'), '->has() returns true if a get*Method() is defined');
    }

    /**
     * @covers Symfony\Component\DependencyInjection\Container::initialized
     */
    public function testInitialized()
    {
        $sc = new ProjectServiceContainer();
        $sc->set('foo', new \stdClass());
        $this->assertTrue($sc->initialized('foo'), '->initialized() returns true if service is loaded');
        $this->assertFalse($sc->initialized('foo1'), '->initialized() returns false if service is not loaded');
        $this->assertFalse($sc->initialized('bar'), '->initialized() returns false if a service is defined, but not currently loaded');
    }

    public function testEnterLeaveCurrentScope()
    {
        $container = new ProjectServiceContainer();
        $container->addScope(new Scope('foo'));

        $container->enterScope('foo');
        $scoped1 = $container->get('scoped');
        $scopedFoo1 = $container->get('scoped_foo');

        $container->enterScope('foo');
        $scoped2 = $container->get('scoped');
        $scoped3 = $container->get('scoped');
        $scopedFoo2 = $container->get('scoped_foo');

        $container->leaveScope('foo');
        $scoped4 = $container->get('scoped');
        $scopedFoo3 = $container->get('scoped_foo');

        $this->assertNotSame($scoped1, $scoped2);
        $this->assertSame($scoped2, $scoped3);
        $this->assertSame($scoped1, $scoped4);
        $this->assertNotSame($scopedFoo1, $scopedFoo2);
        $this->assertSame($scopedFoo1, $scopedFoo3);
    }

    public function testEnterLeaveScopeWithChildScopes()
    {
        $container = new Container();
        $container->addScope(new Scope('foo'));
        $container->addScope(new Scope('bar', 'foo'));

        $this->assertFalse($container->isScopeActive('foo'));

        $container->enterScope('foo');
        $container->enterScope('bar');

        $this->assertTrue($container->isScopeActive('foo'));
        $this->assertFalse($container->has('a'));

        $a = new \stdClass();
        $container->set('a', $a, 'bar');

        $services = $this->getField($container, 'scopedServices');
        $this->assertTrue(isset($services['bar']['a']));
        $this->assertSame($a, $services['bar']['a']);

        $this->assertTrue($container->has('a'));
        $container->leaveScope('foo');

        $services = $this->getField($container, 'scopedServices');
        $this->assertFalse(isset($services['bar']));

        $this->assertFalse($container->isScopeActive('foo'));
        $this->assertFalse($container->has('a'));
    }

    public function testEnterScopeRecursivelyWithInactiveChildScopes()
    {
        $container = new Container();
        $container->addScope(new Scope('foo'));
        $container->addScope(new Scope('bar', 'foo'));

        $this->assertFalse($container->isScopeActive('foo'));

        $container->enterScope('foo');

        $this->assertTrue($container->isScopeActive('foo'));
        $this->assertFalse($container->isScopeActive('bar'));
        $this->assertFalse($container->has('a'));

        $a = new \stdClass();
        $container->set('a', $a, 'foo');

        $services = $this->getField($container, 'scopedServices');
        $this->assertTrue(isset($services['foo']['a']));
        $this->assertSame($a, $services['foo']['a']);

        $this->assertTrue($container->has('a'));
        $container->enterScope('foo');

        $services = $this->getField($container, 'scopedServices');
        $this->assertFalse(isset($services['a']));

        $this->assertTrue($container->isScopeActive('foo'));
        $this->assertFalse($container->isScopeActive('bar'));
        $this->assertFalse($container->has('a'));
    }

    public function testLeaveScopeNotActive()
    {
        $container = new Container();
        $container->addScope(new Scope('foo'));

        try {
            $container->leaveScope('foo');
            $this->fail('->leaveScope() throws a \LogicException if the scope is not active yet');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\LogicException', $e, '->leaveScope() throws a \LogicException if the scope is not active yet');
            $this->assertEquals('The scope "foo" is not active.', $e->getMessage(), '->leaveScope() throws a \LogicException if the scope is not active yet');
        }

        try {
            $container->leaveScope('bar');
            $this->fail('->leaveScope() throws a \LogicException if the scope does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\LogicException', $e, '->leaveScope() throws a \LogicException if the scope does not exist');
            $this->assertEquals('The scope "bar" is not active.', $e->getMessage(), '->leaveScope() throws a \LogicException if the scope does not exist');
        }
    }

    /**
     * @expectedException \InvalidArgumentException
     * @dataProvider getBuiltInScopes
     */
    public function testAddScopeDoesNotAllowBuiltInScopes($scope)
    {
        $container = new Container();
        $container->addScope(new Scope($scope));
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testAddScopeDoesNotAllowExistingScope()
    {
        $container = new Container();
        $container->addScope(new Scope('foo'));
        $container->addScope(new Scope('foo'));
    }

    /**
     * @expectedException \InvalidArgumentException
     * @dataProvider getInvalidParentScopes
     */
    public function testAddScopeDoesNotAllowInvalidParentScope($scope)
    {
        $c = new Container();
        $c->addScope(new Scope('foo', $scope));
    }

    public function testAddScope()
    {
        $c = new Container();
        $c->addScope(new Scope('foo'));
        $c->addScope(new Scope('bar', 'foo'));

        $this->assertSame(array('foo' => 'container', 'bar' => 'foo'), $this->getField($c, 'scopes'));
        $this->assertSame(array('foo' => array('bar'), 'bar' => array()), $this->getField($c, 'scopeChildren'));
    }

    public function testHasScope()
    {
        $c = new Container();

        $this->assertFalse($c->hasScope('foo'));
        $c->addScope(new Scope('foo'));
        $this->assertTrue($c->hasScope('foo'));
    }

    public function testIsScopeActive()
    {
        $c = new Container();

        $this->assertFalse($c->isScopeActive('foo'));
        $c->addScope(new Scope('foo'));

        $this->assertFalse($c->isScopeActive('foo'));
        $c->enterScope('foo');

        $this->assertTrue($c->isScopeActive('foo'));
        $c->leaveScope('foo');

        $this->assertFalse($c->isScopeActive('foo'));
    }

    public function testGetThrowsException()
    {
        $c = new ProjectServiceContainer();

        try {
            $c->get('throw_exception');
            $this->fail();
        } catch (\Exception $e) {
            $this->assertEquals('Something went terribly wrong!', $e->getMessage());
        }

        try {
            $c->get('throw_exception');
            $this->fail();
        } catch (\Exception $e) {
            $this->assertEquals('Something went terribly wrong!', $e->getMessage());
        }
    }

    public function testGetThrowsExceptionOnServiceConfiguration()
    {
        $c = new ProjectServiceContainer();

        try {
            $c->get('throws_exception_on_service_configuration');
            $this->fail('The container can not contain invalid service!');
        } catch (\Exception $e) {
            $this->assertEquals('Something was terribly wrong while trying to configure the service!', $e->getMessage());
        }
        $this->assertFalse($c->initialized('throws_exception_on_service_configuration'));

        try {
            $c->get('throws_exception_on_service_configuration');
            $this->fail('The container can not contain invalid service!');
        } catch (\Exception $e) {
            $this->assertEquals('Something was terribly wrong while trying to configure the service!', $e->getMessage());
        }
        $this->assertFalse($c->initialized('throws_exception_on_service_configuration'));
    }

    public function getInvalidParentScopes()
    {
        return array(
            array(ContainerInterface::SCOPE_PROTOTYPE),
            array('bar'),
        );
    }

    public function getBuiltInScopes()
    {
        return array(
            array(ContainerInterface::SCOPE_CONTAINER),
            array(ContainerInterface::SCOPE_PROTOTYPE),
        );
    }

    protected function getField($obj, $field)
    {
        $reflection = new \ReflectionProperty($obj, $field);
        $reflection->setAccessible(true);

        return $reflection->getValue($obj);
    }

    public function testAlias()
    {
        $c = new ProjectServiceContainer();

        $this->assertTrue($c->has('alias'));
        $this->assertSame($c->get('alias'), $c->get('bar'));
    }
}

class ProjectServiceContainer extends Container
{
    public $__bar, $__foo_bar, $__foo_baz;

    public function __construct()
    {
        parent::__construct();

        $this->__bar = new \stdClass();
        $this->__foo_bar = new \stdClass();
        $this->__foo_baz = new \stdClass();
        $this->aliases = array('alias' => 'bar');
    }

    protected function getScopedService()
    {
        if (!isset($this->scopedServices['foo'])) {
            throw new \RuntimeException('Invalid call');
        }

        return $this->services['scoped'] = $this->scopedServices['foo']['scoped'] = new \stdClass();
    }

    protected function getScopedFooService()
    {
        if (!isset($this->scopedServices['foo'])) {
            throw new \RuntimeException('invalid call');
        }

        return $this->services['scoped_foo'] = $this->scopedServices['foo']['scoped_foo'] = new \stdClass();
    }

    protected function getInactiveService()
    {
        throw new InactiveScopeException('request', 'request');
    }

    protected function getBarService()
    {
        return $this->__bar;
    }

    protected function getFooBarService()
    {
        return $this->__foo_bar;
    }

    protected function getFoo_BazService()
    {
        return $this->__foo_baz;
    }

    protected function getCircularService()
    {
        return $this->get('circular');
    }

    protected function getThrowExceptionService()
    {
        throw new \Exception('Something went terribly wrong!');
    }

    protected function getThrowsExceptionOnServiceConfigurationService()
    {
        $this->services['throws_exception_on_service_configuration'] = $instance = new \stdClass();

        throw new \Exception('Something was terribly wrong while trying to configure the service!');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection\Tests;

use Symfony\Component\DependencyInjection\Parameter;

class ParameterTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\DependencyInjection\Parameter::__construct
     */
    public function testConstructor()
    {
        $ref = new Parameter('foo');
        $this->assertEquals('foo', (string) $ref, '__construct() sets the id of the parameter, which is used for the __toString() method');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\DependencyInjection;

/**
 * Scope class.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @api
 */
class Scope implements ScopeInterface
{
    private $name;
    private $parentName;

    /**
     * @api
     */
    public function __construct($name, $parentName = ContainerInterface::SCOPE_CONTAINER)
    {
        $this->name = $name;
        $this->parentName = $parentName;
    }

    /**
     * @api
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @api
     */
    public function getParentName()
    {
        return $this->parentName;
    }
}
{
    "name": "symfony/yaml",
    "type": "library",
    "description": "Symfony Yaml Component",
    "keywords": [],
    "homepage": "http://symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "http://symfony.com/contributors"
        }
    ],
    "require": {
        "php": ">=5.3.3"
    },
    "autoload": {
        "psr-0": { "Symfony\\Component\\Yaml\\": "" }
    },
    "target-dir": "Symfony/Component/Yaml",
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-master": "2.4-dev"
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml;

/**
 * Unescaper encapsulates unescaping rules for single and double-quoted
 * YAML strings.
 *
 * @author Matthew Lewinski <matthew@lewinski.org>
 */
class Unescaper
{
    // Parser and Inline assume UTF-8 encoding, so escaped Unicode characters
    // must be converted to that encoding.
    const ENCODING = 'UTF-8';

    // Regex fragment that matches an escaped character in a double quoted
    // string.
    const REGEX_ESCAPED_CHARACTER = "\\\\([0abt\tnvfre \\\"\\/\\\\N_LP]|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})";

    /**
     * Unescapes a single quoted string.
     *
     * @param string $value A single quoted string.
     *
     * @return string The unescaped string.
     */
    public function unescapeSingleQuotedString($value)
    {
        return str_replace('\'\'', '\'', $value);
    }

    /**
     * Unescapes a double quoted string.
     *
     * @param string $value A double quoted string.
     *
     * @return string The unescaped string.
     */
    public function unescapeDoubleQuotedString($value)
    {
        $self = $this;
        $callback = function($match) use ($self) {
            return $self->unescapeCharacter($match[0]);
        };

        // evaluate the string
        return preg_replace_callback('/'.self::REGEX_ESCAPED_CHARACTER.'/u', $callback, $value);
    }

    /**
     * Unescapes a character that was found in a double-quoted string
     *
     * @param string $value An escaped character
     *
     * @return string The unescaped character
     */
    public function unescapeCharacter($value)
    {
        switch ($value{1}) {
            case '0':
                return "\x0";
            case 'a':
                return "\x7";
            case 'b':
                return "\x8";
            case 't':
                return "\t";
            case "\t":
                return "\t";
            case 'n':
                return "\n";
            case 'v':
                return "\xb";
            case 'f':
                return "\xc";
            case 'r':
                return "\xd";
            case 'e':
                return "\x1b";
            case ' ':
                return ' ';
            case '"':
                return '"';
            case '/':
                return '/';
            case '\\':
                return '\\';
            case 'N':
                // U+0085 NEXT LINE
                return $this->convertEncoding("\x00\x85", self::ENCODING, 'UCS-2BE');
            case '_':
                // U+00A0 NO-BREAK SPACE
                return $this->convertEncoding("\x00\xA0", self::ENCODING, 'UCS-2BE');
            case 'L':
                // U+2028 LINE SEPARATOR
                return $this->convertEncoding("\x20\x28", self::ENCODING, 'UCS-2BE');
            case 'P':
                // U+2029 PARAGRAPH SEPARATOR
                return $this->convertEncoding("\x20\x29", self::ENCODING, 'UCS-2BE');
            case 'x':
                $char = pack('n', hexdec(substr($value, 2, 2)));

                return $this->convertEncoding($char, self::ENCODING, 'UCS-2BE');
            case 'u':
                $char = pack('n', hexdec(substr($value, 2, 4)));

                return $this->convertEncoding($char, self::ENCODING, 'UCS-2BE');
            case 'U':
                $char = pack('N', hexdec(substr($value, 2, 8)));

                return $this->convertEncoding($char, self::ENCODING, 'UCS-4BE');
        }
    }

    /**
     * Convert a string from one encoding to another.
     *
     * @param string $value The string to convert
     * @param string $to    The input encoding
     * @param string $from  The output encoding
     *
     * @return string The string with the new encoding
     *
     * @throws \RuntimeException if no suitable encoding function is found (iconv or mbstring)
     */
    private function convertEncoding($value, $to, $from)
    {
        if (function_exists('mb_convert_encoding')) {
            return mb_convert_encoding($value, $to, $from);
        } elseif (function_exists('iconv')) {
            return iconv($from, $to, $value);
        }

        throw new \RuntimeException('No suitable convert encoding function (install the iconv or mbstring extension).');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml;

use Symfony\Component\Yaml\Exception\ParseException;

/**
 * Parser parses YAML strings to convert them to PHP arrays.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Parser
{
    const FOLDED_SCALAR_PATTERN = '(?P<separator>\||>)(?P<modifiers>\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P<comments> +#.*)?';

    private $offset         = 0;
    private $lines          = array();
    private $currentLineNb  = -1;
    private $currentLine    = '';
    private $refs           = array();

    /**
     * Constructor
     *
     * @param integer $offset The offset of YAML document (used for line numbers in error messages)
     */
    public function __construct($offset = 0)
    {
        $this->offset = $offset;
    }

    /**
     * Parses a YAML string to a PHP value.
     *
     * @param string  $value                  A YAML string
     * @param Boolean $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise
     * @param Boolean $objectSupport          true if object support is enabled, false otherwise
     *
     * @return mixed  A PHP value
     *
     * @throws ParseException If the YAML is not valid
     */
    public function parse($value, $exceptionOnInvalidType = false, $objectSupport = false)
    {
        $this->currentLineNb = -1;
        $this->currentLine = '';
        $this->lines = explode("\n", $this->cleanup($value));

        if (function_exists('mb_detect_encoding') && false === mb_detect_encoding($value, 'UTF-8', true)) {
            throw new ParseException('The YAML value does not appear to be valid UTF-8.');
        }

        if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) {
            $mbEncoding = mb_internal_encoding();
            mb_internal_encoding('UTF-8');
        }

        $data = array();
        $context = null;
        while ($this->moveToNextLine()) {
            if ($this->isCurrentLineEmpty()) {
                continue;
            }

            // tab?
            if ("\t" === $this->currentLine[0]) {
                throw new ParseException('A YAML file cannot contain tabs as indentation.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
            }

            $isRef = $isInPlace = $isProcessed = false;
            if (preg_match('#^\-((?P<leadspaces>\s+)(?P<value>.+?))?\s*$#u', $this->currentLine, $values)) {
                if ($context && 'mapping' == $context) {
                    throw new ParseException('You cannot define a sequence item when in a mapping');
                }
                $context = 'sequence';

                if (isset($values['value']) && preg_match('#^&(?P<ref>[^ ]+) *(?P<value>.*)#u', $values['value'], $matches)) {
                    $isRef = $matches['ref'];
                    $values['value'] = $matches['value'];
                }

                // array
                if (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) {
                    $c = $this->getRealCurrentLineNb() + 1;
                    $parser = new Parser($c);
                    $parser->refs =& $this->refs;
                    $data[] = $parser->parse($this->getNextEmbedBlock(), $exceptionOnInvalidType, $objectSupport);
                } else {
                    if (isset($values['leadspaces'])
                        && ' ' == $values['leadspaces']
                        && preg_match('#^(?P<key>'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\{\[].*?) *\:(\s+(?P<value>.+?))?\s*$#u', $values['value'], $matches)
                    ) {
                        // this is a compact notation element, add to next block and parse
                        $c = $this->getRealCurrentLineNb();
                        $parser = new Parser($c);
                        $parser->refs =& $this->refs;

                        $block = $values['value'];
                        if ($this->isNextLineIndented()) {
                            $block .= "\n".$this->getNextEmbedBlock($this->getCurrentLineIndentation() + 2);
                        }

                        $data[] = $parser->parse($block, $exceptionOnInvalidType, $objectSupport);
                    } else {
                        $data[] = $this->parseValue($values['value'], $exceptionOnInvalidType, $objectSupport);
                    }
                }
            } elseif (preg_match('#^(?P<key>'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\[\{].*?) *\:(\s+(?P<value>.+?))?\s*$#u', $this->currentLine, $values) && false === strpos($values['key'],' #')) {
                if ($context && 'sequence' == $context) {
                    throw new ParseException('You cannot define a mapping item when in a sequence');
                }
                $context = 'mapping';

                // force correct settings
                Inline::parse(null, $exceptionOnInvalidType, $objectSupport);
                try {
                    $key = Inline::parseScalar($values['key']);
                } catch (ParseException $e) {
                    $e->setParsedLine($this->getRealCurrentLineNb() + 1);
                    $e->setSnippet($this->currentLine);

                    throw $e;
                }

                if ('<<' === $key) {
                    if (isset($values['value']) && 0 === strpos($values['value'], '*')) {
                        $isInPlace = substr($values['value'], 1);
                        if (!array_key_exists($isInPlace, $this->refs)) {
                            throw new ParseException(sprintf('Reference "%s" does not exist.', $isInPlace), $this->getRealCurrentLineNb() + 1, $this->currentLine);
                        }
                    } else {
                        if (isset($values['value']) && $values['value'] !== '') {
                            $value = $values['value'];
                        } else {
                            $value = $this->getNextEmbedBlock();
                        }
                        $c = $this->getRealCurrentLineNb() + 1;
                        $parser = new Parser($c);
                        $parser->refs =& $this->refs;
                        $parsed = $parser->parse($value, $exceptionOnInvalidType, $objectSupport);

                        $merged = array();
                        if (!is_array($parsed)) {
                            throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
                        } elseif (isset($parsed[0])) {
                            // Numeric array, merge individual elements
                            foreach (array_reverse($parsed) as $parsedItem) {
                                if (!is_array($parsedItem)) {
                                    throw new ParseException('Merge items must be arrays.', $this->getRealCurrentLineNb() + 1, $parsedItem);
                                }
                                $merged = array_merge($parsedItem, $merged);
                            }
                        } else {
                            // Associative array, merge
                            $merged = array_merge($merged, $parsed);
                        }

                        $isProcessed = $merged;
                    }
                } elseif (isset($values['value']) && preg_match('#^&(?P<ref>[^ ]+) *(?P<value>.*)#u', $values['value'], $matches)) {
                    $isRef = $matches['ref'];
                    $values['value'] = $matches['value'];
                }

                if ($isProcessed) {
                    // Merge keys
                    $data = $isProcessed;
                // hash
                } elseif (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) {
                    // if next line is less indented or equal, then it means that the current value is null
                    if (!$this->isNextLineIndented() && !$this->isNextLineUnIndentedCollection()) {
                        $data[$key] = null;
                    } else {
                        $c = $this->getRealCurrentLineNb() + 1;
                        $parser = new Parser($c);
                        $parser->refs =& $this->refs;
                        $data[$key] = $parser->parse($this->getNextEmbedBlock(), $exceptionOnInvalidType, $objectSupport);
                    }
                } else {
                    if ($isInPlace) {
                        $data = $this->refs[$isInPlace];
                    } else {
                        $data[$key] = $this->parseValue($values['value'], $exceptionOnInvalidType, $objectSupport);
                    }
                }
            } else {
                // 1-liner optionally followed by newline
                $lineCount = count($this->lines);
                if (1 === $lineCount || (2 === $lineCount && empty($this->lines[1]))) {
                    try {
                        $value = Inline::parse($this->lines[0], $exceptionOnInvalidType, $objectSupport);
                    } catch (ParseException $e) {
                        $e->setParsedLine($this->getRealCurrentLineNb() + 1);
                        $e->setSnippet($this->currentLine);

                        throw $e;
                    }

                    if (is_array($value)) {
                        $first = reset($value);
                        if (is_string($first) && 0 === strpos($first, '*')) {
                            $data = array();
                            foreach ($value as $alias) {
                                $data[] = $this->refs[substr($alias, 1)];
                            }
                            $value = $data;
                        }
                    }

                    if (isset($mbEncoding)) {
                        mb_internal_encoding($mbEncoding);
                    }

                    return $value;
                }

                switch (preg_last_error()) {
                    case PREG_INTERNAL_ERROR:
                        $error = 'Internal PCRE error.';
                        break;
                    case PREG_BACKTRACK_LIMIT_ERROR:
                        $error = 'pcre.backtrack_limit reached.';
                        break;
                    case PREG_RECURSION_LIMIT_ERROR:
                        $error = 'pcre.recursion_limit reached.';
                        break;
                    case PREG_BAD_UTF8_ERROR:
                        $error = 'Malformed UTF-8 data.';
                        break;
                    case PREG_BAD_UTF8_OFFSET_ERROR:
                        $error = 'Offset doesn\'t correspond to the begin of a valid UTF-8 code point.';
                        break;
                    default:
                        $error = 'Unable to parse.';
                }

                throw new ParseException($error, $this->getRealCurrentLineNb() + 1, $this->currentLine);
            }

            if ($isRef) {
                $this->refs[$isRef] = end($data);
            }
        }

        if (isset($mbEncoding)) {
            mb_internal_encoding($mbEncoding);
        }

        return empty($data) ? null : $data;
    }

    /**
     * Returns the current line number (takes the offset into account).
     *
     * @return integer The current line number
     */
    private function getRealCurrentLineNb()
    {
        return $this->currentLineNb + $this->offset;
    }

    /**
     * Returns the current line indentation.
     *
     * @return integer The current line indentation
     */
    private function getCurrentLineIndentation()
    {
        return strlen($this->currentLine) - strlen(ltrim($this->currentLine, ' '));
    }

    /**
     * Returns the next embed block of YAML.
     *
     * @param integer $indentation The indent level at which the block is to be read, or null for default
     *
     * @return string A YAML string
     *
     * @throws ParseException When indentation problem are detected
     */
    private function getNextEmbedBlock($indentation = null)
    {
        $this->moveToNextLine();

        if (null === $indentation) {
            $newIndent = $this->getCurrentLineIndentation();

            $unindentedEmbedBlock = $this->isStringUnIndentedCollectionItem($this->currentLine);

            if (!$this->isCurrentLineEmpty() && 0 === $newIndent && !$unindentedEmbedBlock) {
                throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
            }
        } else {
            $newIndent = $indentation;
        }

        $data = array(substr($this->currentLine, $newIndent));

        $isItUnindentedCollection = $this->isStringUnIndentedCollectionItem($this->currentLine);

        // Comments must not be removed inside a string block (ie. after a line ending with "|")
        $removeCommentsPattern = '~'.self::FOLDED_SCALAR_PATTERN.'$~';
        $removeComments = !preg_match($removeCommentsPattern, $this->currentLine);

        while ($this->moveToNextLine()) {
            if ($this->getCurrentLineIndentation() === $newIndent) {
                $removeComments = !preg_match($removeCommentsPattern, $this->currentLine);
            }

            if ($isItUnindentedCollection && !$this->isStringUnIndentedCollectionItem($this->currentLine)) {
                $this->moveToPreviousLine();
                break;
            }

            if ($removeComments && $this->isCurrentLineEmpty() || $this->isCurrentLineBlank()) {
                if ($this->isCurrentLineBlank()) {
                    $data[] = substr($this->currentLine, $newIndent);
                }

                continue;
            }

            $indent = $this->getCurrentLineIndentation();

            if (preg_match('#^(?P<text> *)$#', $this->currentLine, $match)) {
                // empty line
                $data[] = $match['text'];
            } elseif ($indent >= $newIndent) {
                $data[] = substr($this->currentLine, $newIndent);
            } elseif (0 == $indent) {
                $this->moveToPreviousLine();

                break;
            } else {
                throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine);
            }
        }

        return implode("\n", $data);
    }

    /**
     * Moves the parser to the next line.
     *
     * @return Boolean
     */
    private function moveToNextLine()
    {
        if ($this->currentLineNb >= count($this->lines) - 1) {
            return false;
        }

        $this->currentLine = $this->lines[++$this->currentLineNb];

        return true;
    }

    /**
     * Moves the parser to the previous line.
     */
    private function moveToPreviousLine()
    {
        $this->currentLine = $this->lines[--$this->currentLineNb];
    }

    /**
     * Parses a YAML value.
     *
     * @param string  $value                  A YAML value
     * @param Boolean $exceptionOnInvalidType True if an exception must be thrown on invalid types false otherwise
     * @param Boolean $objectSupport          True if object support is enabled, false otherwise
     *
     * @return mixed  A PHP value
     *
     * @throws ParseException When reference does not exist
     */
    private function parseValue($value, $exceptionOnInvalidType, $objectSupport)
    {
        if (0 === strpos($value, '*')) {
            if (false !== $pos = strpos($value, '#')) {
                $value = substr($value, 1, $pos - 2);
            } else {
                $value = substr($value, 1);
            }

            if (!array_key_exists($value, $this->refs)) {
                throw new ParseException(sprintf('Reference "%s" does not exist.', $value), $this->currentLine);
            }

            return $this->refs[$value];
        }

        if (preg_match('/^'.self::FOLDED_SCALAR_PATTERN.'$/', $value, $matches)) {
            $modifiers = isset($matches['modifiers']) ? $matches['modifiers'] : '';

            return $this->parseFoldedScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), intval(abs($modifiers)));
        }

        try {
            return Inline::parse($value, $exceptionOnInvalidType, $objectSupport);
        } catch (ParseException $e) {
            $e->setParsedLine($this->getRealCurrentLineNb() + 1);
            $e->setSnippet($this->currentLine);

            throw $e;
        }
    }

    /**
     * Parses a folded scalar.
     *
     * @param string  $separator   The separator that was used to begin this folded scalar (| or >)
     * @param string  $indicator   The indicator that was used to begin this folded scalar (+ or -)
     * @param integer $indentation The indentation that was used to begin this folded scalar
     *
     * @return string  The text value
     */
    private function parseFoldedScalar($separator, $indicator = '', $indentation = 0)
    {
        $notEOF = $this->moveToNextLine();
        if (!$notEOF) {
            return '';
        }

        $isCurrentLineBlank = $this->isCurrentLineBlank();
        $text = '';

        // leading blank lines are consumed before determining indentation
        while ($notEOF && $isCurrentLineBlank) {
            // newline only if not EOF
            if ($notEOF = $this->moveToNextLine()) {
                $text .= "\n";
                $isCurrentLineBlank = $this->isCurrentLineBlank();
            }
        }

        // determine indentation if not specified
        if (0 === $indentation) {
            if (preg_match('/^ +/', $this->currentLine, $matches)) {
                $indentation = strlen($matches[0]);
            }
        }

        if ($indentation > 0) {
            $pattern = sprintf('/^ {%d}(.*)$/', $indentation);

            while (
                $notEOF && (
                    $isCurrentLineBlank ||
                    preg_match($pattern, $this->currentLine, $matches)
                )
            ) {
                if ($isCurrentLineBlank) {
                    $text .= substr($this->currentLine, $indentation);
                } else {
                    $text .= $matches[1];
                }

                // newline only if not EOF
                if ($notEOF = $this->moveToNextLine()) {
                    $text .= "\n";
                    $isCurrentLineBlank = $this->isCurrentLineBlank();
                }
            }
        } elseif ($notEOF) {
            $text .= "\n";
        }

        if ($notEOF) {
            $this->moveToPreviousLine();
        }

        // replace all non-trailing single newlines with spaces in folded blocks
        if ('>' === $separator) {
            preg_match('/(\n*)$/', $text, $matches);
            $text = preg_replace('/(?<!\n)\n(?!\n)/', ' ', rtrim($text, "\n"));
            $text .= $matches[1];
        }

        // deal with trailing newlines as indicated
        if ('' === $indicator) {
            $text = preg_replace('/\n+$/s', "\n", $text);
        } elseif ('-' === $indicator) {
            $text = preg_replace('/\n+$/s', '', $text);
        }

        return $text;
    }

    /**
     * Returns true if the next line is indented.
     *
     * @return Boolean Returns true if the next line is indented, false otherwise
     */
    private function isNextLineIndented()
    {
        $currentIndentation = $this->getCurrentLineIndentation();
        $EOF = !$this->moveToNextLine();

        while (!$EOF && $this->isCurrentLineEmpty()) {
            $EOF = !$this->moveToNextLine();
        }

        if ($EOF) {
            return false;
        }

        $ret = false;
        if ($this->getCurrentLineIndentation() > $currentIndentation) {
            $ret = true;
        }

        $this->moveToPreviousLine();

        return $ret;
    }

    /**
     * Returns true if the current line is blank or if it is a comment line.
     *
     * @return Boolean Returns true if the current line is empty or if it is a comment line, false otherwise
     */
    private function isCurrentLineEmpty()
    {
        return $this->isCurrentLineBlank() || $this->isCurrentLineComment();
    }

    /**
     * Returns true if the current line is blank.
     *
     * @return Boolean Returns true if the current line is blank, false otherwise
     */
    private function isCurrentLineBlank()
    {
        return '' == trim($this->currentLine, ' ');
    }

    /**
     * Returns true if the current line is a comment line.
     *
     * @return Boolean Returns true if the current line is a comment line, false otherwise
     */
    private function isCurrentLineComment()
    {
        //checking explicitly the first char of the trim is faster than loops or strpos
        $ltrimmedLine = ltrim($this->currentLine, ' ');

        return $ltrimmedLine[0] === '#';
    }

    /**
     * Cleanups a YAML string to be parsed.
     *
     * @param string $value The input YAML string
     *
     * @return string A cleaned up YAML string
     */
    private function cleanup($value)
    {
        $value = str_replace(array("\r\n", "\r"), "\n", $value);

        // strip YAML header
        $count = 0;
        $value = preg_replace('#^\%YAML[: ][\d\.]+.*\n#su', '', $value, -1, $count);
        $this->offset += $count;

        // remove leading comments
        $trimmedValue = preg_replace('#^(\#.*?\n)+#s', '', $value, -1, $count);
        if ($count == 1) {
            // items have been removed, update the offset
            $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n");
            $value = $trimmedValue;
        }

        // remove start of the document marker (---)
        $trimmedValue = preg_replace('#^\-\-\-.*?\n#s', '', $value, -1, $count);
        if ($count == 1) {
            // items have been removed, update the offset
            $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n");
            $value = $trimmedValue;

            // remove end of the document marker (...)
            $value = preg_replace('#\.\.\.\s*$#s', '', $value);
        }

        return $value;
    }

    /**
     * Returns true if the next line starts unindented collection
     *
     * @return Boolean Returns true if the next line starts unindented collection, false otherwise
     */
    private function isNextLineUnIndentedCollection()
    {
        $currentIndentation = $this->getCurrentLineIndentation();
        $notEOF = $this->moveToNextLine();

        while ($notEOF && $this->isCurrentLineEmpty()) {
            $notEOF = $this->moveToNextLine();
        }

        if (false === $notEOF) {
            return false;
        }

        $ret = false;
        if (
            $this->getCurrentLineIndentation() == $currentIndentation
            &&
            $this->isStringUnIndentedCollectionItem($this->currentLine)
        ) {
            $ret = true;
        }

        $this->moveToPreviousLine();

        return $ret;
    }

    /**
     * Returns true if the string is un-indented collection item
     *
     * @return Boolean Returns true if the string is un-indented collection item, false otherwise
     */
    private function isStringUnIndentedCollectionItem()
    {
        return (0 === strpos($this->currentLine, '- '));
    }

}
Copyright (c) 2004-2013 Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml;

use Symfony\Component\Yaml\Exception\ParseException;

/**
 * Yaml offers convenience methods to load and dump YAML.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Yaml
{
    /**
     * Parses YAML into a PHP array.
     *
     * The parse method, when supplied with a YAML stream (string or file),
     * will do its best to convert YAML in a file into a PHP array.
     *
     *  Usage:
     *  <code>
     *   $array = Yaml::parse('config.yml');
     *   print_r($array);
     *  </code>
     *
     * As this method accepts both plain strings and file names as an input,
     * you must validate the input before calling this method. Passing a file
     * as an input is a deprecated feature and will be removed in 3.0.
     *
     * @param string  $input                  Path to a YAML file or a string containing YAML
     * @param Boolean $exceptionOnInvalidType True if an exception must be thrown on invalid types false otherwise
     * @param Boolean $objectSupport          True if object support is enabled, false otherwise
     *
     * @return array The YAML converted to a PHP array
     *
     * @throws ParseException If the YAML is not valid
     *
     * @api
     */
    public static function parse($input, $exceptionOnInvalidType = false, $objectSupport = false)
    {
        // if input is a file, process it
        $file = '';
        if (strpos($input, "\n") === false && is_file($input)) {
            if (false === is_readable($input)) {
                throw new ParseException(sprintf('Unable to parse "%s" as the file is not readable.', $input));
            }

            $file = $input;
            $input = file_get_contents($file);
        }

        $yaml = new Parser();

        try {
            return $yaml->parse($input, $exceptionOnInvalidType, $objectSupport);
        } catch (ParseException $e) {
            if ($file) {
                $e->setParsedFile($file);
            }

            throw $e;
        }
    }

    /**
     * Dumps a PHP array to a YAML string.
     *
     * The dump method, when supplied with an array, will do its best
     * to convert the array into friendly YAML.
     *
     * @param array   $array                  PHP array
     * @param integer $inline                 The level where you switch to inline YAML
     * @param integer $indent                 The amount of spaces to use for indentation of nested nodes.
     * @param Boolean $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise
     * @param Boolean $objectSupport          true if object support is enabled, false otherwise
     *
     * @return string A YAML string representing the original PHP array
     *
     * @api
     */
    public static function dump($array, $inline = 2, $indent = 4, $exceptionOnInvalidType = false, $objectSupport = false)
    {
        $yaml = new Dumper();
        $yaml->setIndentation($indent);

        return $yaml->dump($array, $inline, 0, $exceptionOnInvalidType, $objectSupport);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml;

/**
 * Escaper encapsulates escaping rules for single and double-quoted
 * YAML strings.
 *
 * @author Matthew Lewinski <matthew@lewinski.org>
 */
class Escaper
{
    // Characters that would cause a dumped string to require double quoting.
    const REGEX_CHARACTER_TO_ESCAPE = "[\\x00-\\x1f]|\xc2\x85|\xc2\xa0|\xe2\x80\xa8|\xe2\x80\xa9";

    // Mapping arrays for escaping a double quoted string. The backslash is
    // first to ensure proper escaping because str_replace operates iteratively
    // on the input arrays. This ordering of the characters avoids the use of strtr,
    // which performs more slowly.
    private static $escapees = array('\\\\', '\\"', '"',
                                     "\x00",  "\x01",  "\x02",  "\x03",  "\x04",  "\x05",  "\x06",  "\x07",
                                     "\x08",  "\x09",  "\x0a",  "\x0b",  "\x0c",  "\x0d",  "\x0e",  "\x0f",
                                     "\x10",  "\x11",  "\x12",  "\x13",  "\x14",  "\x15",  "\x16",  "\x17",
                                     "\x18",  "\x19",  "\x1a",  "\x1b",  "\x1c",  "\x1d",  "\x1e",  "\x1f",
                                     "\xc2\x85", "\xc2\xa0", "\xe2\x80\xa8", "\xe2\x80\xa9");
    private static $escaped  = array('\\"', '\\\\', '\\"',
                                     "\\0",   "\\x01", "\\x02", "\\x03", "\\x04", "\\x05", "\\x06", "\\a",
                                     "\\b",   "\\t",   "\\n",   "\\v",   "\\f",   "\\r",   "\\x0e", "\\x0f",
                                     "\\x10", "\\x11", "\\x12", "\\x13", "\\x14", "\\x15", "\\x16", "\\x17",
                                     "\\x18", "\\x19", "\\x1a", "\\e",   "\\x1c", "\\x1d", "\\x1e", "\\x1f",
                                     "\\N", "\\_", "\\L", "\\P");

    /**
     * Determines if a PHP value would require double quoting in YAML.
     *
     * @param string $value A PHP value
     *
     * @return Boolean True if the value would require double quotes.
     */
    public static function requiresDoubleQuoting($value)
    {
        return preg_match('/'.self::REGEX_CHARACTER_TO_ESCAPE.'/u', $value);
    }

    /**
     * Escapes and surrounds a PHP value with double quotes.
     *
     * @param string $value A PHP value
     *
     * @return string The quoted, escaped string
     */
    public static function escapeWithDoubleQuotes($value)
    {
        return sprintf('"%s"', str_replace(self::$escapees, self::$escaped, $value));
    }

    /**
     * Determines if a PHP value would require single quoting in YAML.
     *
     * @param string $value A PHP value
     *
     * @return Boolean True if the value would require single quotes.
     */
    public static function requiresSingleQuoting($value)
    {
        return preg_match('/[ \s \' " \: \{ \} \[ \] , & \* \# \?] | \A[ \- ? | < > = ! % @ ` ]/x', $value);
    }

    /**
     * Escapes and surrounds a PHP value with single quotes.
     *
     * @param string $value A PHP value
     *
     * @return string The quoted, escaped string
     */
    public static function escapeWithSingleQuotes($value)
    {
        return sprintf("'%s'", str_replace('\'', '\'\'', $value));
    }
}
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Yaml Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./vendor</directory>
                <directory>./Tests</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
<?php

/*
 * This file is part of the Symfony package.
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml;

use Symfony\Component\Yaml\Exception\ParseException;
use Symfony\Component\Yaml\Exception\DumpException;

/**
 * Inline implements a YAML parser/dumper for the YAML inline syntax.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Inline
{
    const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\']*(?:\'\'[^\']*)*)\')';

    private static $exceptionOnInvalidType = false;
    private static $objectSupport = false;

    /**
     * Converts a YAML string to a PHP array.
     *
     * @param string  $value                  A YAML string
     * @param Boolean $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise
     * @param Boolean $objectSupport          true if object support is enabled, false otherwise
     *
     * @return array A PHP array representing the YAML string
     *
     * @throws ParseException
     */
    public static function parse($value, $exceptionOnInvalidType = false, $objectSupport = false)
    {
        self::$exceptionOnInvalidType = $exceptionOnInvalidType;
        self::$objectSupport = $objectSupport;

        $value = trim($value);

        if (0 == strlen($value)) {
            return '';
        }

        if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) {
            $mbEncoding = mb_internal_encoding();
            mb_internal_encoding('ASCII');
        }

        $i = 0;
        switch ($value[0]) {
            case '[':
                $result = self::parseSequence($value, $i);
                ++$i;
                break;
            case '{':
                $result = self::parseMapping($value, $i);
                ++$i;
                break;
            default:
                $result = self::parseScalar($value, null, array('"', "'"), $i);
        }

        // some comments are allowed at the end
        if (preg_replace('/\s+#.*$/A', '', substr($value, $i))) {
            throw new ParseException(sprintf('Unexpected characters near "%s".', substr($value, $i)));
        }

        if (isset($mbEncoding)) {
            mb_internal_encoding($mbEncoding);
        }

        return $result;
    }

    /**
     * Dumps a given PHP variable to a YAML string.
     *
     * @param mixed   $value                  The PHP variable to convert
     * @param Boolean $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise
     * @param Boolean $objectSupport          true if object support is enabled, false otherwise
     *
     * @return string The YAML string representing the PHP array
     *
     * @throws DumpException When trying to dump PHP resource
     */
    public static function dump($value, $exceptionOnInvalidType = false, $objectSupport = false)
    {
        switch (true) {
            case is_resource($value):
                if ($exceptionOnInvalidType) {
                    throw new DumpException(sprintf('Unable to dump PHP resources in a YAML file ("%s").', get_resource_type($value)));
                }

                return 'null';
            case is_object($value):
                if ($objectSupport) {
                    return '!!php/object:'.serialize($value);
                }

                if ($exceptionOnInvalidType) {
                    throw new DumpException('Object support when dumping a YAML file has been disabled.');
                }

                return 'null';
            case is_array($value):
                return self::dumpArray($value, $exceptionOnInvalidType, $objectSupport);
            case null === $value:
                return 'null';
            case true === $value:
                return 'true';
            case false === $value:
                return 'false';
            case ctype_digit($value):
                return is_string($value) ? "'$value'" : (int) $value;
            case is_numeric($value):
                $locale = setlocale(LC_NUMERIC, 0);
                if (false !== $locale) {
                    setlocale(LC_NUMERIC, 'C');
                }
                $repr = is_string($value) ? "'$value'" : (is_infinite($value) ? str_ireplace('INF', '.Inf', strval($value)) : strval($value));

                if (false !== $locale) {
                    setlocale(LC_NUMERIC, $locale);
                }

                return $repr;
            case Escaper::requiresDoubleQuoting($value):
                return Escaper::escapeWithDoubleQuotes($value);
            case Escaper::requiresSingleQuoting($value):
                return Escaper::escapeWithSingleQuotes($value);
            case '' == $value:
                return "''";
            case preg_match(self::getTimestampRegex(), $value):
            case in_array(strtolower($value), array('null', '~', 'true', 'false')):
                return "'$value'";
            default:
                return $value;
        }
    }

    /**
     * Dumps a PHP array to a YAML string.
     *
     * @param array   $value                  The PHP array to dump
     * @param Boolean $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise
     * @param Boolean $objectSupport          true if object support is enabled, false otherwise
     *
     * @return string The YAML string representing the PHP array
     */
    private static function dumpArray($value, $exceptionOnInvalidType, $objectSupport)
    {
        // array
        $keys = array_keys($value);
        if ((1 == count($keys) && '0' == $keys[0])
            || (count($keys) > 1 && array_reduce($keys, function ($v, $w) { return (integer) $v + $w; }, 0) == count($keys) * (count($keys) - 1) / 2)
        ) {
            $output = array();
            foreach ($value as $val) {
                $output[] = self::dump($val, $exceptionOnInvalidType, $objectSupport);
            }

            return sprintf('[%s]', implode(', ', $output));
        }

        // mapping
        $output = array();
        foreach ($value as $key => $val) {
            $output[] = sprintf('%s: %s', self::dump($key, $exceptionOnInvalidType, $objectSupport), self::dump($val, $exceptionOnInvalidType, $objectSupport));
        }

        return sprintf('{ %s }', implode(', ', $output));
    }

    /**
     * Parses a scalar to a YAML string.
     *
     * @param scalar $scalar
     * @param string $delimiters
     * @param array  $stringDelimiters
     * @param integer &$i
     * @param Boolean $evaluate
     *
     * @return string A YAML string
     *
     * @throws ParseException When malformed inline YAML string is parsed
     */
    public static function parseScalar($scalar, $delimiters = null, $stringDelimiters = array('"', "'"), &$i = 0, $evaluate = true)
    {
        if (in_array($scalar[$i], $stringDelimiters)) {
            // quoted scalar
            $output = self::parseQuotedScalar($scalar, $i);

            if (null !== $delimiters) {
                $tmp = ltrim(substr($scalar, $i), ' ');
                if (!in_array($tmp[0], $delimiters)) {
                    throw new ParseException(sprintf('Unexpected characters (%s).', substr($scalar, $i)));
                }
            }
        } else {
            // "normal" string
            if (!$delimiters) {
                $output = substr($scalar, $i);
                $i += strlen($output);

                // remove comments
                if (false !== $strpos = strpos($output, ' #')) {
                    $output = rtrim(substr($output, 0, $strpos));
                }
            } elseif (preg_match('/^(.+?)('.implode('|', $delimiters).')/', substr($scalar, $i), $match)) {
                $output = $match[1];
                $i += strlen($output);
            } else {
                throw new ParseException(sprintf('Malformed inline YAML string (%s).', $scalar));
            }

            $output = $evaluate ? self::evaluateScalar($output) : $output;
        }

        return $output;
    }

    /**
     * Parses a quoted scalar to YAML.
     *
     * @param string $scalar
     * @param integer &$i
     *
     * @return string A YAML string
     *
     * @throws ParseException When malformed inline YAML string is parsed
     */
    private static function parseQuotedScalar($scalar, &$i)
    {
        if (!preg_match('/'.self::REGEX_QUOTED_STRING.'/Au', substr($scalar, $i), $match)) {
            throw new ParseException(sprintf('Malformed inline YAML string (%s).', substr($scalar, $i)));
        }

        $output = substr($match[0], 1, strlen($match[0]) - 2);

        $unescaper = new Unescaper();
        if ('"' == $scalar[$i]) {
            $output = $unescaper->unescapeDoubleQuotedString($output);
        } else {
            $output = $unescaper->unescapeSingleQuotedString($output);
        }

        $i += strlen($match[0]);

        return $output;
    }

    /**
     * Parses a sequence to a YAML string.
     *
     * @param string $sequence
     * @param integer &$i
     *
     * @return string A YAML string
     *
     * @throws ParseException When malformed inline YAML string is parsed
     */
    private static function parseSequence($sequence, &$i = 0)
    {
        $output = array();
        $len = strlen($sequence);
        $i += 1;

        // [foo, bar, ...]
        while ($i < $len) {
            switch ($sequence[$i]) {
                case '[':
                    // nested sequence
                    $output[] = self::parseSequence($sequence, $i);
                    break;
                case '{':
                    // nested mapping
                    $output[] = self::parseMapping($sequence, $i);
                    break;
                case ']':
                    return $output;
                case ',':
                case ' ':
                    break;
                default:
                    $isQuoted = in_array($sequence[$i], array('"', "'"));
                    $value = self::parseScalar($sequence, array(',', ']'), array('"', "'"), $i);

                    if (!$isQuoted && false !== strpos($value, ': ')) {
                        // embedded mapping?
                        try {
                            $value = self::parseMapping('{'.$value.'}');
                        } catch (\InvalidArgumentException $e) {
                            // no, it's not
                        }
                    }

                    $output[] = $value;

                    --$i;
            }

            ++$i;
        }

        throw new ParseException(sprintf('Malformed inline YAML string %s', $sequence));
    }

    /**
     * Parses a mapping to a YAML string.
     *
     * @param string $mapping
     * @param integer &$i
     *
     * @return string A YAML string
     *
     * @throws ParseException When malformed inline YAML string is parsed
     */
    private static function parseMapping($mapping, &$i = 0)
    {
        $output = array();
        $len = strlen($mapping);
        $i += 1;

        // {foo: bar, bar:foo, ...}
        while ($i < $len) {
            switch ($mapping[$i]) {
                case ' ':
                case ',':
                    ++$i;
                    continue 2;
                case '}':
                    return $output;
            }

            // key
            $key = self::parseScalar($mapping, array(':', ' '), array('"', "'"), $i, false);

            // value
            $done = false;
            while ($i < $len) {
                switch ($mapping[$i]) {
                    case '[':
                        // nested sequence
                        $output[$key] = self::parseSequence($mapping, $i);
                        $done = true;
                        break;
                    case '{':
                        // nested mapping
                        $output[$key] = self::parseMapping($mapping, $i);
                        $done = true;
                        break;
                    case ':':
                    case ' ':
                        break;
                    default:
                        $output[$key] = self::parseScalar($mapping, array(',', '}'), array('"', "'"), $i);
                        $done = true;
                        --$i;
                }

                ++$i;

                if ($done) {
                    continue 2;
                }
            }
        }

        throw new ParseException(sprintf('Malformed inline YAML string %s', $mapping));
    }

    /**
     * Evaluates scalars and replaces magic values.
     *
     * @param string $scalar
     *
     * @return string A YAML string
     */
    private static function evaluateScalar($scalar)
    {
        $scalar = trim($scalar);

        switch (true) {
            case 'null' == strtolower($scalar):
            case '' == $scalar:
            case '~' == $scalar:
                return null;
            case 0 === strpos($scalar, '!str'):
                return (string) substr($scalar, 5);
            case 0 === strpos($scalar, '! '):
                return intval(self::parseScalar(substr($scalar, 2)));
            case 0 === strpos($scalar, '!!php/object:'):
                if (self::$objectSupport) {
                    return unserialize(substr($scalar, 13));
                }

                if (self::$exceptionOnInvalidType) {
                    throw new ParseException('Object support when parsing a YAML file has been disabled.');
                }

                return null;
            case ctype_digit($scalar):
                $raw = $scalar;
                $cast = intval($scalar);

                return '0' == $scalar[0] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw);
            case '-' === $scalar[0] && ctype_digit(substr($scalar, 1)):
                $raw = $scalar;
                $cast = intval($scalar);

                return '0' == $scalar[1] ? octdec($scalar) : (((string) $raw == (string) $cast) ? $cast : $raw);
            case 'true' === strtolower($scalar):
                return true;
            case 'false' === strtolower($scalar):
                return false;
            case is_numeric($scalar):
                return '0x' == $scalar[0].$scalar[1] ? hexdec($scalar) : floatval($scalar);
            case 0 == strcasecmp($scalar, '.inf'):
            case 0 == strcasecmp($scalar, '.NaN'):
                return -log(0);
            case 0 == strcasecmp($scalar, '-.inf'):
                return log(0);
            case preg_match('/^(-|\+)?[0-9,]+(\.[0-9]+)?$/', $scalar):
                return floatval(str_replace(',', '', $scalar));
            case preg_match(self::getTimestampRegex(), $scalar):
                return strtotime($scalar);
            default:
                return (string) $scalar;
        }
    }

    /**
     * Gets a regex that matches a YAML date.
     *
     * @return string The regular expression
     *
     * @see http://www.yaml.org/spec/1.2/spec.html#id2761573
     */
    private static function getTimestampRegex()
    {
        return <<<EOF
        ~^
        (?P<year>[0-9][0-9][0-9][0-9])
        -(?P<month>[0-9][0-9]?)
        -(?P<day>[0-9][0-9]?)
        (?:(?:[Tt]|[ \t]+)
        (?P<hour>[0-9][0-9]?)
        :(?P<minute>[0-9][0-9])
        :(?P<second>[0-9][0-9])
        (?:\.(?P<fraction>[0-9]*))?
        (?:[ \t]*(?P<tz>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9][0-9]?)
        (?::(?P<tz_minute>[0-9][0-9]))?))?)?
        $~x
EOF;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml\Exception;

/**
 * Exception class thrown when an error occurs during parsing.
 *
 * @author Romain Neutron <imprec@gmail.com>
 *
 * @api
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml\Exception;

/**
 * Exception interface for all exceptions thrown by the component.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml\Exception;

if (!defined('JSON_UNESCAPED_UNICODE')) {
    define('JSON_UNESCAPED_SLASHES', 64);
    define('JSON_UNESCAPED_UNICODE', 256);
}

/**
 * Exception class thrown when an error occurs during parsing.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class ParseException extends RuntimeException
{
    private $parsedFile;
    private $parsedLine;
    private $snippet;
    private $rawMessage;

    /**
     * Constructor.
     *
     * @param string    $message    The error message
     * @param integer   $parsedLine The line where the error occurred
     * @param integer   $snippet    The snippet of code near the problem
     * @param string    $parsedFile The file name where the error occurred
     * @param \Exception $previous   The previous exception
     */
    public function __construct($message, $parsedLine = -1, $snippet = null, $parsedFile = null, \Exception $previous = null)
    {
        $this->parsedFile = $parsedFile;
        $this->parsedLine = $parsedLine;
        $this->snippet = $snippet;
        $this->rawMessage = $message;

        $this->updateRepr();

        parent::__construct($this->message, 0, $previous);
    }

    /**
     * Gets the snippet of code near the error.
     *
     * @return string The snippet of code
     */
    public function getSnippet()
    {
        return $this->snippet;
    }

    /**
     * Sets the snippet of code near the error.
     *
     * @param string $snippet The code snippet
     */
    public function setSnippet($snippet)
    {
        $this->snippet = $snippet;

        $this->updateRepr();
    }

    /**
     * Gets the filename where the error occurred.
     *
     * This method returns null if a string is parsed.
     *
     * @return string The filename
     */
    public function getParsedFile()
    {
        return $this->parsedFile;
    }

    /**
     * Sets the filename where the error occurred.
     *
     * @param string $parsedFile The filename
     */
    public function setParsedFile($parsedFile)
    {
        $this->parsedFile = $parsedFile;

        $this->updateRepr();
    }

    /**
     * Gets the line where the error occurred.
     *
     * @return integer The file line
     */
    public function getParsedLine()
    {
        return $this->parsedLine;
    }

    /**
     * Sets the line where the error occurred.
     *
     * @param integer $parsedLine The file line
     */
    public function setParsedLine($parsedLine)
    {
        $this->parsedLine = $parsedLine;

        $this->updateRepr();
    }

    private function updateRepr()
    {
        $this->message = $this->rawMessage;

        $dot = false;
        if ('.' === substr($this->message, -1)) {
            $this->message = substr($this->message, 0, -1);
            $dot = true;
        }

        if (null !== $this->parsedFile) {
            $this->message .= sprintf(' in %s', json_encode($this->parsedFile, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
        }

        if ($this->parsedLine >= 0) {
            $this->message .= sprintf(' at line %d', $this->parsedLine);
        }

        if ($this->snippet) {
            $this->message .= sprintf(' (near "%s")', $this->snippet);
        }

        if ($dot) {
            $this->message .= '.';
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml\Exception;

/**
 * Exception class thrown when an error occurs during dumping.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class DumpException extends RuntimeException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml;

/**
 * Dumper dumps PHP variables to YAML strings.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Dumper
{
    /**
     * The amount of spaces to use for indentation of nested nodes.
     *
     * @var integer
     */
    protected $indentation = 4;

    /**
     * Sets the indentation.
     *
     * @param integer $num The amount of spaces to use for indentation of nested nodes.
     */
    public function setIndentation($num)
    {
        $this->indentation = (int) $num;
    }

    /**
     * Dumps a PHP value to YAML.
     *
     * @param mixed   $input                  The PHP value
     * @param integer $inline                 The level where you switch to inline YAML
     * @param integer $indent                 The level of indentation (used internally)
     * @param Boolean $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise
     * @param Boolean $objectSupport          true if object support is enabled, false otherwise
     *
     * @return string  The YAML representation of the PHP value
     */
    public function dump($input, $inline = 0, $indent = 0, $exceptionOnInvalidType = false, $objectSupport = false)
    {
        $output = '';
        $prefix = $indent ? str_repeat(' ', $indent) : '';

        if ($inline <= 0 || !is_array($input) || empty($input)) {
            $output .= $prefix.Inline::dump($input, $exceptionOnInvalidType, $objectSupport);
        } else {
            $isAHash = array_keys($input) !== range(0, count($input) - 1);

            foreach ($input as $key => $value) {
                $willBeInlined = $inline - 1 <= 0 || !is_array($value) || empty($value);

                $output .= sprintf('%s%s%s%s',
                    $prefix,
                    $isAHash ? Inline::dump($key, $exceptionOnInvalidType, $objectSupport).':' : '-',
                    $willBeInlined ? ' ' : "\n",
                    $this->dump($value, $inline - 1, $willBeInlined ? 0 : $indent + $this->indentation, $exceptionOnInvalidType, $objectSupport)
                ).($willBeInlined ? "\n" : '');
            }
        }

        return $output;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml\Tests;

use Symfony\Component\Yaml\Yaml;
use Symfony\Component\Yaml\Parser;

class ParserTest extends \PHPUnit_Framework_TestCase
{
    protected $parser;

    protected function setUp()
    {
        $this->parser = new Parser();
    }

    protected function tearDown()
    {
        $this->parser = null;
    }

    /**
     * @dataProvider getDataFormSpecifications
     */
    public function testSpecifications($file, $expected, $yaml, $comment)
    {
        if ('escapedCharacters' == $file) {
            if (!function_exists('iconv') && !function_exists('mb_convert_encoding')) {
                $this->markTestSkipped('The iconv and mbstring extensions are not available.');
            }
        }

        $this->assertEquals($expected, var_export($this->parser->parse($yaml), true), $comment);
    }

    public function getDataFormSpecifications()
    {
        $parser = new Parser();
        $path = __DIR__.'/Fixtures';

        $tests = array();
        $files = $parser->parse(file_get_contents($path.'/index.yml'));
        foreach ($files as $file) {
            $yamls = file_get_contents($path.'/'.$file.'.yml');

            // split YAMLs documents
            foreach (preg_split('/^---( %YAML\:1\.0)?/m', $yamls) as $yaml) {
                if (!$yaml) {
                    continue;
                }

                $test = $parser->parse($yaml);
                if (isset($test['todo']) && $test['todo']) {
                    // TODO
                } else {
                    $expected = var_export(eval('return '.trim($test['php']).';'), true);

                    $tests[] = array($file, $expected, $test['yaml'], $test['test']);
                }
            }
        }

        return $tests;
    }

    public function testTabsInYaml()
    {
        // test tabs in YAML
        $yamls = array(
            "foo:\n	bar",
            "foo:\n 	bar",
            "foo:\n	 bar",
            "foo:\n 	 bar",
        );

        foreach ($yamls as $yaml) {
            try {
                $content = $this->parser->parse($yaml);

                $this->fail('YAML files must not contain tabs');
            } catch (\Exception $e) {
                $this->assertInstanceOf('\Exception', $e, 'YAML files must not contain tabs');
                $this->assertEquals('A YAML file cannot contain tabs as indentation at line 2 (near "'.strpbrk($yaml, "\t").'").', $e->getMessage(), 'YAML files must not contain tabs');
            }
        }
    }

    public function testEndOfTheDocumentMarker()
    {
        $yaml = <<<EOF
--- %YAML:1.0
foo
...
EOF;

        $this->assertEquals('foo', $this->parser->parse($yaml));
    }

    public function getBlockChompingTests()
    {
        $tests = array();

        $yaml = <<<'EOF'
foo: |-
    one
    two
bar: |-
    one
    two

EOF;
        $expected = array(
            'foo' => "one\ntwo",
            'bar' => "one\ntwo",
        );
        $tests['Literal block chomping strip with single trailing newline'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: |-
    one
    two

bar: |-
    one
    two


EOF;
        $expected = array(
            'foo' => "one\ntwo",
            'bar' => "one\ntwo",
        );
        $tests['Literal block chomping strip with multiple trailing newlines'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: |-
    one
    two
bar: |-
    one
    two
EOF;
        $expected = array(
            'foo' => "one\ntwo",
            'bar' => "one\ntwo",
        );
        $tests['Literal block chomping strip without trailing newline'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: |
    one
    two
bar: |
    one
    two

EOF;
        $expected = array(
            'foo' => "one\ntwo\n",
            'bar' => "one\ntwo\n",
        );
        $tests['Literal block chomping clip with single trailing newline'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: |
    one
    two

bar: |
    one
    two


EOF;
        $expected = array(
            'foo' => "one\ntwo\n",
            'bar' => "one\ntwo\n",
        );
        $tests['Literal block chomping clip with multiple trailing newlines'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: |
    one
    two
bar: |
    one
    two
EOF;
        $expected = array(
            'foo' => "one\ntwo\n",
            'bar' => "one\ntwo",
        );
        $tests['Literal block chomping clip without trailing newline'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: |+
    one
    two
bar: |+
    one
    two

EOF;
        $expected = array(
            'foo' => "one\ntwo\n",
            'bar' => "one\ntwo\n",
        );
        $tests['Literal block chomping keep with single trailing newline'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: |+
    one
    two

bar: |+
    one
    two


EOF;
        $expected = array(
            'foo' => "one\ntwo\n\n",
            'bar' => "one\ntwo\n\n",
        );
        $tests['Literal block chomping keep with multiple trailing newlines'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: |+
    one
    two
bar: |+
    one
    two
EOF;
        $expected = array(
            'foo' => "one\ntwo\n",
            'bar' => "one\ntwo",
        );
        $tests['Literal block chomping keep without trailing newline'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: >-
    one
    two
bar: >-
    one
    two

EOF;
        $expected = array(
            'foo' => "one two",
            'bar' => "one two",
        );
        $tests['Folded block chomping strip with single trailing newline'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: >-
    one
    two

bar: >-
    one
    two


EOF;
        $expected = array(
            'foo' => "one two",
            'bar' => "one two",
        );
        $tests['Folded block chomping strip with multiple trailing newlines'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: >-
    one
    two
bar: >-
    one
    two
EOF;
        $expected = array(
            'foo' => "one two",
            'bar' => "one two",
        );
        $tests['Folded block chomping strip without trailing newline'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: >
    one
    two
bar: >
    one
    two

EOF;
        $expected = array(
            'foo' => "one two\n",
            'bar' => "one two\n",
        );
        $tests['Folded block chomping clip with single trailing newline'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: >
    one
    two

bar: >
    one
    two


EOF;
        $expected = array(
            'foo' => "one two\n",
            'bar' => "one two\n",
        );
        $tests['Folded block chomping clip with multiple trailing newlines'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: >
    one
    two
bar: >
    one
    two
EOF;
        $expected = array(
            'foo' => "one two\n",
            'bar' => "one two",
        );
        $tests['Folded block chomping clip without trailing newline'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: >+
    one
    two
bar: >+
    one
    two

EOF;
        $expected = array(
            'foo' => "one two\n",
            'bar' => "one two\n",
        );
        $tests['Folded block chomping keep with single trailing newline'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: >+
    one
    two

bar: >+
    one
    two


EOF;
        $expected = array(
            'foo' => "one two\n\n",
            'bar' => "one two\n\n",
        );
        $tests['Folded block chomping keep with multiple trailing newlines'] = array($expected, $yaml);

        $yaml = <<<'EOF'
foo: >+
    one
    two
bar: >+
    one
    two
EOF;
        $expected = array(
            'foo' => "one two\n",
            'bar' => "one two",
        );
        $tests['Folded block chomping keep without trailing newline'] = array($expected, $yaml);

        return $tests;
    }

    /**
     * @dataProvider getBlockChompingTests
     */
    public function testBlockChomping($expected, $yaml)
    {
        $this->assertSame($expected, $this->parser->parse($yaml));
    }

    /**
     * Regression test for issue #7989.
     *
     * @see https://github.com/symfony/symfony/issues/7989
     */
    public function testBlockLiteralWithLeadingNewlines()
    {
        $yaml = <<<'EOF'
foo: |-


    bar

EOF;
        $expected = array(
            'foo' => "\n\nbar"
        );

        $this->assertSame($expected, $this->parser->parse($yaml));
    }

    public function testObjectSupportEnabled()
    {
        $input = <<<EOF
foo: !!php/object:O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";}
bar: 1
EOF;
        $this->assertEquals(array('foo' => new B(), 'bar' => 1), $this->parser->parse($input, false, true), '->parse() is able to parse objects');
    }

    public function testObjectSupportDisabledButNoExceptions()
    {
        $input = <<<EOF
foo: !!php/object:O:30:"Symfony\Tests\Component\Yaml\B":1:{s:1:"b";s:3:"foo";}
bar: 1
EOF;

        $this->assertEquals(array('foo' => null, 'bar' => 1), $this->parser->parse($input), '->parse() does not parse objects');
    }

    /**
     * @expectedException \Symfony\Component\Yaml\Exception\ParseException
     */
    public function testObjectsSupportDisabledWithExceptions()
    {
        $this->parser->parse('foo: !!php/object:O:30:"Symfony\Tests\Component\Yaml\B":1:{s:1:"b";s:3:"foo";}', true, false);
    }

    public function testNonUtf8Exception()
    {
        if (!function_exists('mb_detect_encoding') || !function_exists('iconv')) {
            $this->markTestSkipped('Exceptions for non-utf8 charsets require the mb_detect_encoding() and iconv() functions.');

            return;
        }

        $yamls = array(
            iconv("UTF-8", "ISO-8859-1", "foo: 'äöüß'"),
            iconv("UTF-8", "ISO-8859-15", "euro: '€'"),
            iconv("UTF-8", "CP1252", "cp1252: '©ÉÇáñ'")
        );

        foreach ($yamls as $yaml) {
            try {
                $this->parser->parse($yaml);

                $this->fail('charsets other than UTF-8 are rejected.');
            } catch (\Exception $e) {
                 $this->assertInstanceOf('Symfony\Component\Yaml\Exception\ParseException', $e, 'charsets other than UTF-8 are rejected.');
            }
        }
    }

    /**
     *
     * @expectedException \Symfony\Component\Yaml\Exception\ParseException
     *
     */
    public function testUnindentedCollectionException()
    {
        $yaml = <<<EOF

collection:
-item1
-item2
-item3

EOF;

        $this->parser->parse($yaml);
    }

    /**
     * @expectedException \Symfony\Component\Yaml\Exception\ParseException
     */
    public function testSequenceInAMapping()
    {
        Yaml::parse(<<<EOF
yaml:
  hash: me
  - array stuff
EOF
        );
    }

    /**
     * @expectedException \Symfony\Component\Yaml\Exception\ParseException
     */
    public function testMappingInASequence()
    {
        Yaml::parse(<<<EOF
yaml:
  - array stuff
  hash: me
EOF
        );
    }

    public function testEmptyValue()
    {
        $input = <<<EOF
hash:
EOF;

        $this->assertEquals(array('hash' => null), Yaml::parse($input));
    }

    public function testStringBlockWithComments()
    {
        $this->assertEquals(array('content' => <<<EOT
# comment 1
header

    # comment 2
    <body>
        <h1>title</h1>
    </body>

footer # comment3
EOT
        ), Yaml::parse(<<<EOF
content: |
    # comment 1
    header

        # comment 2
        <body>
            <h1>title</h1>
        </body>

    footer # comment3
EOF
        ));
    }

    public function testFoldedStringBlockWithComments()
    {
        $this->assertEquals(array(array('content' => <<<EOT
# comment 1
header

    # comment 2
    <body>
        <h1>title</h1>
    </body>

footer # comment3
EOT
        )), Yaml::parse(<<<EOF
-
    content: |
        # comment 1
        header

            # comment 2
            <body>
                <h1>title</h1>
            </body>

        footer # comment3
EOF
        ));
    }

    public function testNestedFoldedStringBlockWithComments()
    {
        $this->assertEquals(array(array(
            'title'   => 'some title',
            'content' => <<<EOT
# comment 1
header

    # comment 2
    <body>
        <h1>title</h1>
    </body>

footer # comment3
EOT
        )), Yaml::parse(<<<EOF
-
    title: some title
    content: |
        # comment 1
        header

            # comment 2
            <body>
                <h1>title</h1>
            </body>

        footer # comment3
EOF
        ));
    }
}

class B
{
    public $b = 'foo';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml\Tests;

use Symfony\Component\Yaml\Yaml;

class YamlTest extends \PHPUnit_Framework_TestCase
{
    public function testParseAndDump()
    {
        $data = array('lorem' => 'ipsum', 'dolor' => 'sit');
        $yml = Yaml::dump($data);
        $parsed = Yaml::parse($yml);
        $this->assertEquals($data, $parsed);

        $filename = __DIR__.'/Fixtures/index.yml';
        $contents = file_get_contents($filename);
        $parsedByFilename = Yaml::parse($filename);
        $parsedByContents = Yaml::parse($contents);
        $this->assertEquals($parsedByFilename, $parsedByContents);
    }
}
test: outside double quotes
yaml: |
    \0 \ \a \b \n
php: |
    "\\0 \\ \\a \\b \\n"
---
test: null
yaml: |
    "\0"
php: |
    "\x00"
---
test: bell
yaml: |
    "\a"
php: |
    "\x07"
---
test: backspace
yaml: |
    "\b"
php: |
    "\x08"
---
test: horizontal tab (1)
yaml: |
    "\t"
php: |
    "\x09"
---
test: horizontal tab (2)
yaml: |
    "\	"
php: |
    "\x09"
---
test: line feed
yaml: |
    "\n"
php: |
    "\x0a"
---
test: vertical tab
yaml: |
    "\v"
php: |
    "\x0b"
---
test: form feed
yaml: |
    "\f"
php: |
    "\x0c"
---
test: carriage return
yaml: |
    "\r"
php: |
    "\x0d"
---
test: escape
yaml: |
    "\e"
php: |
   "\x1b"
---
test: space
yaml: |
    "\ "
php: |
    "\x20"
---
test: slash
yaml: |
    "\/"
php: |
    "\x2f"
---
test: backslash
yaml: |
    "\\"
php: |
    "\\"
---
test: Unicode next line
yaml: |
    "\N"
php: |
    "\xc2\x85"
---
test: Unicode non-breaking space
yaml: |
    "\_"
php: |
    "\xc2\xa0"
---
test: Unicode line separator
yaml: |
    "\L"
php: |
    "\xe2\x80\xa8"
---
test: Unicode paragraph separator
yaml: |
    "\P"
php: |
    "\xe2\x80\xa9"
---
test: Escaped 8-bit Unicode
yaml: |
    "\x42"
php: |
    "B"
---
test: Escaped 16-bit Unicode
yaml: |
    "\u20ac"
php: |
    "\xe2\x82\xac"
---
test: Escaped 32-bit Unicode
yaml: |
    "\U00000043"
php: |
    "C"
---
test: Example 5.13 Escaped Characters
note: |
    Currently throws an error parsing first line. Maybe Symfony Yaml doesn't support
    continuation of string across multiple lines? Keeping test here but disabled.
todo: true
yaml: |
    "Fun with \\
    \" \a \b \e \f \
    \n \r \t \v \0 \
    \  \_ \N \L \P \
    \x41 \u0041 \U00000041"
php: |
    "Fun with \x5C\n\x22 \x07 \x08 \x1B \x0C\n\x0A \x0D \x09 \x0B \x00\n\x20 \xA0 \x85 \xe2\x80\xa8 \xe2\x80\xa9\nA A A"
---
test: Double quotes with a line feed
yaml: |
   { double: "some value\n \"some quoted string\" and 'some single quotes one'" }
php: |
    array(
        'double' => "some value\n \"some quoted string\" and 'some single quotes one'"
    )
--- %YAML:1.0
test: Compact notation
brief: |
    Compact notation for sets of mappings with single element
yaml: |
  ---
  # products purchased
  - item    : Super Hoop
  - item    : Basketball
    quantity: 1
  - item:
      name: Big Shoes
      nick: Biggies
    quantity: 1
php: |
  array (
    array (
      'item' => 'Super Hoop',
    ),
    array (
      'item' => 'Basketball',
      'quantity' => 1,
    ),
    array (
      'item' => array(
        'name' => 'Big Shoes',
        'nick' => 'Biggies'
      ),
      'quantity' => 1
    )
  )
---
test: Compact notation combined with inline notation
brief: |
    Combinations of compact and inline notation are allowed
yaml: |
  ---
  items:
    - { item: Super Hoop, quantity: 1 }
    - [ Basketball, Big Shoes ]
php: |
  array (
    'items' => array (
      array (
        'item' => 'Super Hoop',
        'quantity' => 1,
      ),
      array (
        'Basketball',
        'Big Shoes'
      )
    )
  )
--- %YAML:1.0
test: Compact notation
brief: |
    Compact notation for sets of mappings with single element
yaml: |
  ---
  # products purchased
  - item    : Super Hoop
  - item    : Basketball
    quantity: 1
  - item:
      name: Big Shoes
      nick: Biggies
    quantity: 1
php: |
  array (
    array (
      'item' => 'Super Hoop',
    ),
    array (
      'item' => 'Basketball',
      'quantity' => 1,
    ),
    array (
      'item' => array(
        'name' => 'Big Shoes',
        'nick' => 'Biggies'
      ),
      'quantity' => 1
    )
  )
---
test: Compact notation combined with inline notation
brief: |
    Combinations of compact and inline notation are allowed
yaml: |
  ---
  items:
    - { item: Super Hoop, quantity: 1 }
    - [ Basketball, Big Shoes ]
php: |
  array (
    'items' => array (
      array (
        'item' => 'Super Hoop',
        'quantity' => 1,
      ),
      array (
        'Basketball',
        'Big Shoes'
      )
    )
  )
--- %YAML:1.0
test: Compact notation
brief: |
    Compact notation for sets of mappings with single element
yaml: |
  ---
  # products purchased
  - item    : Super Hoop
  - item    : Basketball
    quantity: 1
  - item:
      name: Big Shoes
      nick: Biggies
    quantity: 1
php: |
  array (
    array (
      'item' => 'Super Hoop',
    ),
    array (
      'item' => 'Basketball',
      'quantity' => 1,
    ),
    array (
      'item' => array(
        'name' => 'Big Shoes',
        'nick' => 'Biggies'
      ),
      'quantity' => 1
    )
  )
---
test: Compact notation combined with inline notation
brief: |
    Combinations of compact and inline notation are allowed
yaml: |
  ---
  items:
    - { item: Super Hoop, quantity: 1 }
    - [ Basketball, Big Shoes ]
php: |
  array (
    'items' => array (
      array (
        'item' => 'Super Hoop',
        'quantity' => 1,
      ),
      array (
        'Basketball',
        'Big Shoes'
      )
    )
  )
--- %YAML:1.0
test: Strings
brief: >
    Any group of characters beginning with an
    alphabetic or numeric character is a string,
    unless it belongs to one of the groups below
    (such as an Integer or Time).
yaml: |
    String
php: |
    'String'
---
test: String characters
brief: >
    A string can contain any alphabetic or
    numeric character, along with many
    punctuation characters, including the
    period, dash, space, quotes, exclamation, and
    question mark.
yaml: |
    - What's Yaml?
    - It's for writing data structures in plain text.
    - And?
    - And what? That's not good enough for you?
    - No, I mean, "And what about Yaml?"
    - Oh, oh yeah. Uh.. Yaml for Ruby.
php: |
    array(
      "What's Yaml?",
      "It's for writing data structures in plain text.",
      "And?",
      "And what? That's not good enough for you?",
      "No, I mean, \"And what about Yaml?\"",
      "Oh, oh yeah. Uh.. Yaml for Ruby."
    )
---
test: Indicators in Strings
brief: >
    Be careful using indicators in strings.  In particular,
    the comma, colon, and pound sign must be used carefully.
yaml: |
    the colon followed by space is an indicator: but is a string:right here
    same for the pound sign: here we have it#in a string
    the comma can, honestly, be used in most cases: [ but not in, inline collections ]
php: |
    array(
      'the colon followed by space is an indicator' => 'but is a string:right here',
      'same for the pound sign' => 'here we have it#in a string',
      'the comma can, honestly, be used in most cases' => array('but not in', 'inline collections')
    )
---
test: Forcing Strings
brief: >
    Any YAML type can be forced into a string using the
    explicit !str method.
yaml: |
    date string: !str 2001-08-01
    number string: !str 192
php: |
    array(
      'date string' => '2001-08-01',
      'number string' => '192'
    )
---
test: Single-quoted Strings
brief: >
    You can also enclose your strings within single quotes,
    which allows use of slashes, colons, and other indicators
    freely.  Inside single quotes, you can represent a single
    quote in your string by using two single quotes next to
    each other.
yaml: |
    all my favorite symbols: '#:!/%.)'
    a few i hate: '&(*'
    why do i hate them?: 'it''s very hard to explain'
    entities: '&pound; me'
php: |
    array(
      'all my favorite symbols' => '#:!/%.)',
      'a few i hate' => '&(*',
      'why do i hate them?' => 'it\'s very hard to explain',
      'entities' => '&pound; me'
    )
---
test: Double-quoted Strings
brief: >
    Enclosing strings in double quotes allows you
    to use escapings to represent ASCII and
    Unicode characters.
yaml: |
    i know where i want my line breaks: "one here\nand another here\n"
php: |
    array(
      'i know where i want my line breaks' => "one here\nand another here\n"
    )
---
test: Multi-line Quoted Strings
todo: true
brief: >
    Both single- and double-quoted strings may be
    carried on to new lines in your YAML document.
    They must be indented a step and indentation
    is interpreted as a single space.
yaml: |
    i want a long string: "so i'm going to
      let it go on and on to other lines
      until i end it with a quote."
php: |
    array('i want a long string' => "so i'm going to ".
         "let it go on and on to other lines ".
         "until i end it with a quote."
    )

---
test: Plain scalars
todo: true
brief: >
    Unquoted strings may also span multiple lines, if they
    are free of YAML space indicators and indented.
yaml: |
    - My little toe is broken in two places;
    - I'm crazy to have skied this way;
    - I'm not the craziest he's seen, since there was always the German guy
      who skied for 3 hours on a broken shin bone (just below the kneecap);
    - Nevertheless, second place is respectable, and he doesn't
      recommend going for the record;
    - He's going to put my foot in plaster for a month;
    - This would impair my skiing ability somewhat for the
      duration, as can be imagined.
php: |
    array(
      "My little toe is broken in two places;",
      "I'm crazy to have skied this way;",
      "I'm not the craziest he's seen, since there was always ".
         "the German guy who skied for 3 hours on a broken shin ".
         "bone (just below the kneecap);",
      "Nevertheless, second place is respectable, and he doesn't ".
         "recommend going for the record;",
      "He's going to put my foot in plaster for a month;",
      "This would impair my skiing ability somewhat for the duration, ".
         "as can be imagined."
    )
---
test: 'Null'
brief: >
    You can use the tilde '~' character for a null value.
yaml: |
    name: Mr. Show
    hosted by: Bob and David
    date of next season: ~
php: |
    array(
      'name' => 'Mr. Show',
      'hosted by' => 'Bob and David',
      'date of next season' => null
    )
---
test: Boolean
brief: >
    You can use 'true' and 'false' for Boolean values.
yaml: |
    Is Gus a Liar?: true
    Do I rely on Gus for Sustenance?: false
php: |
    array(
      'Is Gus a Liar?' => true,
      'Do I rely on Gus for Sustenance?' => false
    )
---
test: Integers
dump_skip: true
brief: >
    An integer is a series of numbers, optionally
    starting with a positive or negative sign.  Integers
    may also contain commas for readability.
yaml: |
    zero: 0
    simple: 12
    one-thousand: 1,000
    negative one-thousand: -1,000
php: |
    array(
      'zero' => 0,
      'simple' => 12,
      'one-thousand' => 1000,
      'negative one-thousand' => -1000
    )
---
test: Integers as Map Keys
brief: >
    An integer can be used a dictionary key.
yaml: |
    1: one
    2: two
    3: three
php: |
    array(
        1 => 'one',
        2 => 'two',
        3 => 'three'
    )
---
test: Floats
dump_skip: true
brief: >
     Floats are represented by numbers with decimals,
     allowing for scientific notation, as well as
     positive and negative infinity and "not a number."
yaml: |
     a simple float: 2.00
     larger float: 1,000.09
     scientific notation: 1.00009e+3
php: |
     array(
       'a simple float' => 2.0,
       'larger float' => 1000.09,
       'scientific notation' => 1000.09
     )
---
test: Time
todo: true
brief: >
    You can represent timestamps by using
    ISO8601 format, or a variation which
    allows spaces between the date, time and
    time zone.
yaml: |
    iso8601: 2001-12-14t21:59:43.10-05:00
    space separated: 2001-12-14 21:59:43.10 -05:00
php: |
    array(
      'iso8601' => mktime( 2001, 12, 14, 21, 59, 43, 0.10, "-05:00" ),
      'space separated' => mktime( 2001, 12, 14, 21, 59, 43, 0.10, "-05:00" )
    )
---
test: Date
todo: true
brief: >
    A date can be represented by its year,
    month and day in ISO8601 order.
yaml: |
    1976-07-31
php: |
    date( 1976, 7, 31 )
--- %YAML:1.0
test: Simple Sequence
brief: |
    You can specify a list in YAML by placing each
    member of the list on a new line with an opening
    dash. These lists are called sequences.
yaml: |
    - apple
    - banana
    - carrot
php: |
    array('apple', 'banana', 'carrot')
---
test: Nested Sequences
brief: |
    You can include a sequence within another
    sequence by giving the sequence an empty
    dash, followed by an indented list.
yaml: |
    -
     - foo
     - bar
     - baz
php: |
    array(array('foo', 'bar', 'baz'))
---
test: Mixed Sequences
brief: |
    Sequences can contain any YAML data,
    including strings and other sequences.
yaml: |
    - apple
    -
     - foo
     - bar
     - x123
    - banana
    - carrot
php: |
    array('apple', array('foo', 'bar', 'x123'), 'banana', 'carrot')
---
test: Deeply Nested Sequences
brief: |
    Sequences can be nested even deeper, with each
    level of indentation representing a level of
    depth.
yaml: |
    -
     -
      - uno
      - dos
php: |
    array(array(array('uno', 'dos')))
---
test: Simple Mapping
brief: |
    You can add a keyed list (also known as a dictionary or
    hash) to your document by placing each member of the
    list on a new line, with a colon separating the key
    from its value.  In YAML, this type of list is called
    a mapping.
yaml: |
    foo: whatever
    bar: stuff
php: |
    array('foo' => 'whatever', 'bar' => 'stuff')
---
test: Sequence in a Mapping
brief: |
    A value in a mapping can be a sequence.
yaml: |
    foo: whatever
    bar:
     - uno
     - dos
php: |
    array('foo' => 'whatever', 'bar' => array('uno', 'dos'))
---
test: Nested Mappings
brief: |
    A value in a mapping can be another mapping.
yaml: |
    foo: whatever
    bar:
     fruit: apple
     name: steve
     sport: baseball
php: |
    array(
      'foo' => 'whatever',
      'bar' => array(
         'fruit' => 'apple',
         'name' => 'steve',
         'sport' => 'baseball'
       )
    )
---
test: Mixed Mapping
brief: |
    A mapping can contain any assortment
    of mappings and sequences as values.
yaml: |
    foo: whatever
    bar:
     -
       fruit: apple
       name: steve
       sport: baseball
     - more
     -
       python: rocks
       perl: papers
       ruby: scissorses
php: |
    array(
      'foo' => 'whatever',
      'bar' => array(
        array(
            'fruit' => 'apple',
            'name' => 'steve',
            'sport' => 'baseball'
        ),
        'more',
        array(
            'python' => 'rocks',
            'perl' => 'papers',
            'ruby' => 'scissorses'
        )
      )
    )
---
test: Mapping-in-Sequence Shortcut
todo: true
brief: |
     If you are adding a mapping to a sequence, you
     can place the mapping on the same line as the
     dash as a shortcut.
yaml: |
     - work on YAML.py:
        - work on Store
php: |
    array(array('work on YAML.py' => array('work on Store')))
---
test: Sequence-in-Mapping Shortcut
todo: true
brief: |
     The dash in a sequence counts as indentation, so
     you can add a sequence inside of a mapping without
     needing spaces as indentation.
yaml: |
     allow:
     - 'localhost'
     - '%.sourceforge.net'
     - '%.freepan.org'
php: |
     array('allow' => array('localhost', '%.sourceforge.net', '%.freepan.org'))
---
todo: true
test: Merge key
brief: |
     A merge key ('<<') can be used in a mapping to insert other mappings.  If
     the value associated with the merge key is a mapping, each of its key/value
     pairs is inserted into the current mapping.
yaml: |
     mapping:
       name: Joe
       job: Accountant
       <<:
         age: 38
php: |
     array(
       'mapping' =>
       array(
         'name' => 'Joe',
         'job' => 'Accountant',
         'age' => 38
       )
     )
value: <?php echo 1 + 2 + 3 ?>
--- %YAML:1.0
test: Simple In Place Substitution
brief: >
    If you want to reuse an entire alias, only overwriting what is different
    you can use a << in place substitution. This is not part of the official
    YAML spec, but a widely implemented extension. See the following URL for
    details: http://yaml.org/type/merge.html
yaml: |
    foo: &foo
        a: Steve
        b: Clark
        c: Brian
    bar: &bar
        <<: *foo
        x: Oren
    foo2: &foo2
        a: Ballmer
    ding: &dong [ fi, fei, fo, fam]
    check:
        <<:
            - *foo
            - *dong
        isit: tested
    head:
        <<: [ *foo , *dong , *foo2 ]
php: |
    array('foo' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian'), 'bar' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'x' => 'Oren'), 'foo2' => array('a' => 'Ballmer'), 'ding' => array('fi', 'fei', 'fo', 'fam'), 'check' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'fi', 'fei', 'fo', 'fam', 'isit' => 'tested'), 'head' => array('a' => 'Ballmer', 'b' => 'Clark', 'c' => 'Brian', 'fi', 'fei', 'fo', 'fam'))
---
test: Simple Inline Array
brief: >
    Sequences can be contained on a
    single line, using the inline syntax.
    Separate each entry with commas and
    enclose in square brackets.
yaml: |
    seq: [ a, b, c ]
php: |
    array('seq' => array('a', 'b', 'c'))
---
test: Simple Inline Hash
brief: >
    Mapping can also be contained on
    a single line, using the inline
    syntax.  Each key-value pair is
    separated by a colon, with a comma
    between each entry in the mapping.
    Enclose with curly braces.
yaml: |
    hash: { name: Steve, foo: bar }
php: |
    array('hash' => array('name' => 'Steve', 'foo' => 'bar'))
---
test: Multi-line Inline Collections
todo: true
brief: >
    Both inline sequences and inline mappings
    can span multiple lines, provided that you
    indent the additional lines.
yaml: |
    languages: [ Ruby,
                 Perl,
                 Python ]
    websites: { YAML: yaml.org,
                Ruby: ruby-lang.org,
                Python: python.org,
                Perl: use.perl.org }
php: |
    array(
      'languages' => array('Ruby', 'Perl', 'Python'),
      'websites' => array(
        'YAML' => 'yaml.org',
        'Ruby' => 'ruby-lang.org',
        'Python' => 'python.org',
        'Perl' => 'use.perl.org'
      )
    )
---
test: Commas in Values (not in the spec!)
todo: true
brief: >
    List items in collections are delimited by commas, but
    there must be a space after each comma.  This allows you
    to add numbers without quoting.
yaml: |
    attendances: [ 45,123, 70,000, 17,222 ]
php: |
    array('attendances' => array(45123, 70000, 17222))
--- %YAML:1.0
test: Single ending newline
brief: >
    A pipe character, followed by an indented
    block of text is treated as a literal
    block, in which newlines are preserved
    throughout the block, including the final
    newline.
yaml: |
    ---
    this: |
        Foo
        Bar
php: |
    array('this' => "Foo\nBar\n")
---
test: The '+' indicator
brief: >
    The '+' indicator says to keep newlines at the end of text
    blocks.
yaml: |
    normal: |
      extra new lines not kept

    preserving: |+
      extra new lines are kept


    dummy: value
php: |
    array(
        'normal' => "extra new lines not kept\n",
        'preserving' => "extra new lines are kept\n\n\n",
        'dummy' => 'value'
    )
---
test: Three trailing newlines in literals
brief: >
    To give you more control over how space
    is preserved in text blocks, YAML has
    the keep '+' and chomp '-' indicators.
    The keep indicator will preserve all
    ending newlines, while the chomp indicator
    will strip all ending newlines.
yaml: |
    clipped: |
        This has one newline.



    same as "clipped" above: "This has one newline.\n"

    stripped: |-
        This has no newline.



    same as "stripped" above: "This has no newline."

    kept: |+
        This has four newlines.



    same as "kept" above: "This has four newlines.\n\n\n\n"
php: |
    array(
      'clipped' => "This has one newline.\n",
      'same as "clipped" above' => "This has one newline.\n",
      'stripped' => 'This has no newline.',
      'same as "stripped" above' => 'This has no newline.',
      'kept' => "This has four newlines.\n\n\n\n",
      'same as "kept" above' => "This has four newlines.\n\n\n\n"
    )
---
test: Extra trailing newlines with spaces
todo: true
brief: >
    Normally, only a single newline is kept
    from the end of a literal block, unless the
    keep '+' character is used in combination
    with the pipe.  The following example
    will preserve all ending whitespace
    since the last line of both literal blocks
    contains spaces which extend past the indentation
    level.
yaml: |
    ---
    this: |
        Foo


    kept: |+
        Foo


php: |
    array('this' => "Foo\n\n  \n",
      'kept' => "Foo\n\n  \n" )

---
test: Folded Block in a Sequence
brief: >
    A greater-then character, followed by an indented
    block of text is treated as a folded block, in
    which lines of text separated by a single newline
    are concatenated as a single line.
yaml: |
    ---
    - apple
    - banana
    - >
        can't you see
        the beauty of yaml?
        hmm
    - dog
php: |
    array(
        'apple',
        'banana',
        "can't you see the beauty of yaml? hmm\n",
        'dog'
    )
---
test: Folded Block as a Mapping Value
brief: >
    Both literal and folded blocks can be
    used in collections, as values in a
    sequence or a mapping.
yaml: |
    ---
    quote: >
        Mark McGwire's
        year was crippled
        by a knee injury.
    source: espn
php: |
    array(
        'quote' => "Mark McGwire's year was crippled by a knee injury.\n",
        'source' => 'espn'
    )
---
test: Three trailing newlines in folded blocks
brief: >
    The keep and chomp indicators can also
    be applied to folded blocks.
yaml: |
    clipped: >
        This has one newline.



    same as "clipped" above: "This has one newline.\n"

    stripped: >-
        This has no newline.



    same as "stripped" above: "This has no newline."

    kept: >+
        This has four newlines.



    same as "kept" above: "This has four newlines.\n\n\n\n"
php: |
    array(
      'clipped' => "This has one newline.\n",
      'same as "clipped" above' => "This has one newline.\n",
      'stripped' => 'This has no newline.',
      'same as "stripped" above' => 'This has no newline.',
      'kept' => "This has four newlines.\n\n\n\n",
      'same as "kept" above' => "This has four newlines.\n\n\n\n"
    )
--- %YAML:1.0
test: Sequence of scalars
spec: 2.1
yaml: |
  - Mark McGwire
  - Sammy Sosa
  - Ken Griffey
php: |
  array('Mark McGwire', 'Sammy Sosa', 'Ken Griffey')
---
test: Mapping of scalars to scalars
spec: 2.2
yaml: |
  hr:  65
  avg: 0.278
  rbi: 147
php: |
  array('hr' => 65, 'avg' => 0.278, 'rbi' => 147)
---
test: Mapping of scalars to sequences
spec: 2.3
yaml: |
    american:
       - Boston Red Sox
       - Detroit Tigers
       - New York Yankees
    national:
       - New York Mets
       - Chicago Cubs
       - Atlanta Braves
php: |
    array('american' =>
        array( 'Boston Red Sox', 'Detroit Tigers',
          'New York Yankees' ),
      'national' =>
        array( 'New York Mets', 'Chicago Cubs',
          'Atlanta Braves' )
    )
---
test: Sequence of mappings
spec: 2.4
yaml: |
    -
      name: Mark McGwire
      hr:   65
      avg:  0.278
    -
      name: Sammy Sosa
      hr:   63
      avg:  0.288
php: |
    array(
      array('name' => 'Mark McGwire', 'hr' => 65, 'avg' => 0.278),
      array('name' => 'Sammy Sosa', 'hr' => 63, 'avg' => 0.288)
    )
---
test: Legacy A5
todo: true
spec: legacy_A5
yaml: |
    ?
        - New York Yankees
        - Atlanta Braves
    :
      - 2001-07-02
      - 2001-08-12
      - 2001-08-14
    ?
        - Detroit Tigers
        - Chicago Cubs
    :
      - 2001-07-23
perl-busted: >
    YAML.pm will be able to emulate this behavior soon. In this regard
    it may be somewhat more correct than Python's native behaviour which
    can only use tuples as mapping keys. PyYAML will also need to figure
    out some clever way to roundtrip structured keys.
python: |
    [
    {
        ('New York Yankees', 'Atlanta Braves'):
            [yaml.timestamp('2001-07-02'),
             yaml.timestamp('2001-08-12'),
             yaml.timestamp('2001-08-14')],
        ('Detroit Tigers', 'Chicago Cubs'):
        [yaml.timestamp('2001-07-23')]
    }
    ]
ruby: |
    {
      [ 'New York Yankees', 'Atlanta Braves' ] =>
        [ Date.new( 2001, 7, 2 ), Date.new( 2001, 8, 12 ), Date.new( 2001, 8, 14 ) ],
      [ 'Detroit Tigers', 'Chicago Cubs' ] =>
        [ Date.new( 2001, 7, 23 ) ]
    }
syck: |
  struct test_node seq1[] = {
      { T_STR, 0, "New York Yankees" },
      { T_STR, 0, "Atlanta Braves" },
      end_node
  };
  struct test_node seq2[] = {
      { T_STR, 0, "2001-07-02" },
      { T_STR, 0, "2001-08-12" },
      { T_STR, 0, "2001-08-14" },
      end_node
  };
  struct test_node seq3[] = {
      { T_STR, 0, "Detroit Tigers" },
      { T_STR, 0, "Chicago Cubs" },
      end_node
  };
  struct test_node seq4[] = {
      { T_STR, 0, "2001-07-23" },
      end_node
  };
  struct test_node map[] = {
      { T_SEQ, 0, 0, seq1 },
      { T_SEQ, 0, 0, seq2 },
      { T_SEQ, 0, 0, seq3 },
      { T_SEQ, 0, 0, seq4 },
      end_node
  };
  struct test_node stream[] = {
      { T_MAP, 0, 0, map },
      end_node
  };

---
test: Sequence of sequences
spec: 2.5
yaml: |
  - [ name         , hr , avg   ]
  - [ Mark McGwire , 65 , 0.278 ]
  - [ Sammy Sosa   , 63 , 0.288 ]
php: |
  array(
    array( 'name', 'hr', 'avg' ),
    array( 'Mark McGwire', 65, 0.278 ),
    array( 'Sammy Sosa', 63, 0.288 )
  )
---
test: Mapping of mappings
todo: true
spec: 2.6
yaml: |
  Mark McGwire: {hr: 65, avg: 0.278}
  Sammy Sosa: {
      hr: 63,
      avg: 0.288
    }
php: |
  array(
    'Mark McGwire' =>
      array( 'hr' => 65, 'avg' => 0.278 ),
    'Sammy Sosa' =>
      array( 'hr' => 63, 'avg' => 0.288 )
  )
---
test: Two documents in a stream each with a leading comment
todo: true
spec: 2.7
yaml: |
  # Ranking of 1998 home runs
  ---
  - Mark McGwire
  - Sammy Sosa
  - Ken Griffey

  # Team ranking
  ---
  - Chicago Cubs
  - St Louis Cardinals
ruby: |
  y = YAML::Stream.new
  y.add( [ 'Mark McGwire', 'Sammy Sosa', 'Ken Griffey' ] )
  y.add( [ 'Chicago Cubs', 'St Louis Cardinals' ] )
documents: 2

---
test: Play by play feed from a game
todo: true
spec: 2.8
yaml: |
  ---
  time: 20:03:20
  player: Sammy Sosa
  action: strike (miss)
  ...
  ---
  time: 20:03:47
  player: Sammy Sosa
  action: grand slam
  ...
perl: |
  [ 'Mark McGwire', 'Sammy Sosa', 'Ken Griffey' ]
documents: 2

---
test: Single document with two comments
spec: 2.9
yaml: |
  hr: # 1998 hr ranking
    - Mark McGwire
    - Sammy Sosa
  rbi:
    # 1998 rbi ranking
    - Sammy Sosa
    - Ken Griffey
php: |
  array(
    'hr' => array( 'Mark McGwire', 'Sammy Sosa' ),
    'rbi' => array( 'Sammy Sosa', 'Ken Griffey' )
  )
---
test: Node for Sammy Sosa appears twice in this document
spec: 2.10
yaml: |
   ---
   hr:
      - Mark McGwire
      # Following node labeled SS
      - &SS Sammy Sosa
   rbi:
      - *SS # Subsequent occurrence
      - Ken Griffey
php: |
   array(
      'hr' =>
         array('Mark McGwire', 'Sammy Sosa'),
      'rbi' =>
         array('Sammy Sosa', 'Ken Griffey')
   )
---
test: Mapping between sequences
todo: true
spec: 2.11
yaml: |
   ? # PLAY SCHEDULE
     - Detroit Tigers
     - Chicago Cubs
   :
     - 2001-07-23

   ? [ New York Yankees,
       Atlanta Braves ]
   : [ 2001-07-02, 2001-08-12,
       2001-08-14 ]
ruby: |
   {
      [ 'Detroit Tigers', 'Chicago Cubs' ] => [ Date.new( 2001, 7, 23 ) ],
      [ 'New York Yankees', 'Atlanta Braves' ] => [ Date.new( 2001, 7, 2 ), Date.new( 2001, 8, 12 ), Date.new( 2001, 8, 14 ) ]
   }
syck: |
  struct test_node seq1[] = {
      { T_STR, 0, "New York Yankees" },
      { T_STR, 0, "Atlanta Braves" },
      end_node
  };
  struct test_node seq2[] = {
      { T_STR, 0, "2001-07-02" },
      { T_STR, 0, "2001-08-12" },
      { T_STR, 0, "2001-08-14" },
      end_node
  };
  struct test_node seq3[] = {
      { T_STR, 0, "Detroit Tigers" },
      { T_STR, 0, "Chicago Cubs" },
      end_node
  };
  struct test_node seq4[] = {
      { T_STR, 0, "2001-07-23" },
      end_node
  };
  struct test_node map[] = {
      { T_SEQ, 0, 0, seq3 },
      { T_SEQ, 0, 0, seq4 },
      { T_SEQ, 0, 0, seq1 },
      { T_SEQ, 0, 0, seq2 },
      end_node
  };
  struct test_node stream[] = {
      { T_MAP, 0, 0, map },
      end_node
  };

---
test: Sequence key shortcut
spec: 2.12
yaml: |
  ---
  # products purchased
  - item    : Super Hoop
    quantity: 1
  - item    : Basketball
    quantity: 4
  - item    : Big Shoes
    quantity: 1
php: |
  array (
    array (
      'item' => 'Super Hoop',
      'quantity' => 1,
    ),
    array (
      'item' => 'Basketball',
      'quantity' => 4,
    ),
    array (
      'item' => 'Big Shoes',
      'quantity' => 1,
    )
  )
perl: |
  [
     { item => 'Super Hoop', quantity => 1 },
     { item => 'Basketball', quantity => 4 },
     { item => 'Big Shoes',  quantity => 1 }
  ]

ruby: |
  [
     { 'item' => 'Super Hoop', 'quantity' => 1 },
     { 'item' => 'Basketball', 'quantity' => 4 },
     { 'item' => 'Big Shoes', 'quantity' => 1 }
  ]
python: |
  [
       { 'item': 'Super Hoop', 'quantity': 1 },
       { 'item': 'Basketball', 'quantity': 4 },
       { 'item': 'Big Shoes',  'quantity': 1 }
  ]
syck: |
  struct test_node map1[] = {
      { T_STR, 0, "item" },
          { T_STR, 0, "Super Hoop" },
      { T_STR, 0, "quantity" },
          { T_STR, 0, "1" },
      end_node
  };
  struct test_node map2[] = {
      { T_STR, 0, "item" },
          { T_STR, 0, "Basketball" },
      { T_STR, 0, "quantity" },
          { T_STR, 0, "4" },
      end_node
  };
  struct test_node map3[] = {
      { T_STR, 0, "item" },
          { T_STR, 0, "Big Shoes" },
      { T_STR, 0, "quantity" },
          { T_STR, 0, "1" },
      end_node
  };
  struct test_node seq[] = {
      { T_MAP, 0, 0, map1 },
      { T_MAP, 0, 0, map2 },
      { T_MAP, 0, 0, map3 },
      end_node
  };
  struct test_node stream[] = {
      { T_SEQ, 0, 0, seq },
      end_node
  };


---
test: Literal perserves newlines
todo: true
spec: 2.13
yaml: |
  # ASCII Art
  --- |
    \//||\/||
    // ||  ||_
perl: |
  "\\//||\\/||\n// ||  ||_\n"
ruby: |
  "\\//||\\/||\n// ||  ||_\n"
python: |
    [
        flushLeft(
        """
        \//||\/||
        // ||  ||_
        """
        )
    ]
syck: |
  struct test_node stream[] = {
      { T_STR, 0, "\\//||\\/||\n// ||  ||_\n" },
      end_node
  };

---
test: Folded treats newlines as a space
todo: true
spec: 2.14
yaml: |
  ---
    Mark McGwire's
    year was crippled
    by a knee injury.
perl: |
  "Mark McGwire's year was crippled by a knee injury."
ruby: |
  "Mark McGwire's year was crippled by a knee injury."
python: |
    [ "Mark McGwire's year was crippled by a knee injury." ]
syck: |
  struct test_node stream[] = {
      { T_STR, 0, "Mark McGwire's year was crippled by a knee injury." },
      end_node
  };

---
test: Newlines preserved for indented and blank lines
todo: true
spec: 2.15
yaml: |
  --- >
   Sammy Sosa completed another
   fine season with great stats.

     63 Home Runs
     0.288 Batting Average

   What a year!
perl: |
  "Sammy Sosa completed another fine season with great stats.\n\n  63 Home Runs\n  0.288 Batting Average\n\nWhat a year!\n"
ruby: |
  "Sammy Sosa completed another fine season with great stats.\n\n  63 Home Runs\n  0.288 Batting Average\n\nWhat a year!\n"
python: |
    [
        flushLeft(
        """
        Sammy Sosa completed another fine season with great stats.

          63 Home Runs
          0.288 Batting Average

        What a year!
        """
        )
    ]
syck: |
  struct test_node stream[] = {
      { T_STR, 0, "Sammy Sosa completed another fine season with great stats.\n\n  63 Home Runs\n  0.288 Batting Average\n\nWhat a year!\n" },
      end_node
  };


---
test: Indentation determines scope
spec: 2.16
yaml: |
  name: Mark McGwire
  accomplishment: >
     Mark set a major league
     home run record in 1998.
  stats: |
     65 Home Runs
     0.278 Batting Average
php: |
  array(
    'name'           => 'Mark McGwire',
    'accomplishment' => "Mark set a major league home run record in 1998.\n",
    'stats'          => "65 Home Runs\n0.278 Batting Average\n"
  )
---
test: Quoted scalars
todo: true
spec: 2.17
yaml: |
  unicode: "Sosa did fine.\u263A"
  control: "\b1998\t1999\t2000\n"
  hexesc:  "\x0D\x0A is \r\n"

  single: '"Howdy!" he cried.'
  quoted: ' # not a ''comment''.'
  tie-fighter: '|\-*-/|'
ruby: |
  {
    "tie-fighter" => "|\\-*-/|",
    "control"=>"\0101998\t1999\t2000\n",
    "unicode"=>"Sosa did fine." + ["263A".hex ].pack('U*'),
    "quoted"=>" # not a 'comment'.",
    "single"=>"\"Howdy!\" he cried.",
    "hexesc"=>"\r\n is \r\n"
  }
---
test: Multiline flow scalars
todo: true
spec: 2.18
yaml: |
  plain:
    This unquoted scalar
    spans many lines.

  quoted: "So does this
    quoted scalar.\n"
ruby: |
  {
    'plain' => 'This unquoted scalar spans many lines.',
    'quoted' => "So does this quoted scalar.\n"
  }
---
test: Integers
spec: 2.19
yaml: |
  canonical: 12345
  decimal: +12,345
  octal: 014
  hexadecimal: 0xC
php: |
  array(
    'canonical' => 12345,
    'decimal' => 12345,
    'octal' => 014,
    'hexadecimal' => 0xC
  )
---
# FIX: spec shows parens around -inf and NaN
test: Floating point
spec: 2.20
yaml: |
  canonical: 1.23015e+3
  exponential: 12.3015e+02
  fixed: 1,230.15
  negative infinity: -.inf
  not a number: .NaN
php: |
  array(
    'canonical' => 1230.15,
    'exponential' => 1230.15,
    'fixed' => 1230.15,
    'negative infinity' => log(0),
    'not a number' => -log(0),
  )
---
test: Miscellaneous
spec: 2.21
yaml: |
  null: ~
  true: true
  false: false
  string: '12345'
php: |
  array(
    '' => null,
    1 => true,
    0 => false,
    'string' => '12345'
  )
---
test: Timestamps
todo: true
spec: 2.22
yaml: |
  canonical: 2001-12-15T02:59:43.1Z
  iso8601:  2001-12-14t21:59:43.10-05:00
  spaced:  2001-12-14 21:59:43.10 -05:00
  date:   2002-12-14 # Time is noon UTC
php: |
  array(
    'canonical' => YAML::mktime( 2001, 12, 15, 2, 59, 43, 0.10 ),
    'iso8601' => YAML::mktime( 2001, 12, 14, 21, 59, 43, 0.10, "-05:00" ),
    'spaced' => YAML::mktime( 2001, 12, 14, 21, 59, 43, 0.10, "-05:00" ),
    'date' => Date.new( 2002, 12, 14 )
  )
---
test: legacy Timestamps test
todo: true
spec: legacy D4
yaml: |
    canonical: 2001-12-15T02:59:43.00Z
    iso8601:  2001-02-28t21:59:43.00-05:00
    spaced:  2001-12-14 21:59:43.00 -05:00
    date:   2002-12-14
php: |
   array(
     'canonical' => Time::utc( 2001, 12, 15, 2, 59, 43, 0 ),
     'iso8601' => YAML::mktime( 2001, 2, 28, 21, 59, 43, 0, "-05:00" ),
     'spaced' => YAML::mktime( 2001, 12, 14, 21, 59, 43, 0, "-05:00" ),
     'date' => Date.new( 2002, 12, 14 )
   )
---
test: Various explicit families
todo: true
spec: 2.23
yaml: |
  not-date: !str 2002-04-28
  picture: !binary |
   R0lGODlhDAAMAIQAAP//9/X
   17unp5WZmZgAAAOfn515eXv
   Pz7Y6OjuDg4J+fn5OTk6enp
   56enmleECcgggoBADs=

  application specific tag: !!something |
   The semantics of the tag
   above may be different for
   different documents.

ruby-setup: |
  YAML.add_private_type( "something" ) do |type, val|
    "SOMETHING: #{val}"
  end
ruby: |
  {
    'not-date' => '2002-04-28',
    'picture' => "GIF89a\f\000\f\000\204\000\000\377\377\367\365\365\356\351\351\345fff\000\000\000\347\347\347^^^\363\363\355\216\216\216\340\340\340\237\237\237\223\223\223\247\247\247\236\236\236i^\020' \202\n\001\000;",
    'application specific tag' => "SOMETHING: The semantics of the tag\nabove may be different for\ndifferent documents.\n"
  }
---
test: Application specific family
todo: true
spec: 2.24
yaml: |
  # Establish a tag prefix
  --- !clarkevans.com,2002/graph/^shape
    # Use the prefix: shorthand for
    # !clarkevans.com,2002/graph/circle
  - !^circle
    center: &ORIGIN {x: 73, 'y': 129}
    radius: 7
  - !^line # !clarkevans.com,2002/graph/line
    start: *ORIGIN
    finish: { x: 89, 'y': 102 }
  - !^label
    start: *ORIGIN
    color: 0xFFEEBB
    value: Pretty vector drawing.
ruby-setup: |
  YAML.add_domain_type( "clarkevans.com,2002", 'graph/shape' ) { |type, val|
    if Array === val
      val << "Shape Container"
      val
    else
      raise YAML::Error, "Invalid graph of class #{ val.class }: " + val.inspect
    end
  }
  one_shape_proc = Proc.new { |type, val|
    scheme, domain, type = type.split( /:/, 3 )
    if val.is_a? ::Hash
      val['TYPE'] = "Shape: #{type}"
      val
    else
      raise YAML::Error, "Invalid graph of class #{ val.class }: " + val.inspect
    end
  }
  YAML.add_domain_type( "clarkevans.com,2002", 'graph/circle', &one_shape_proc )
  YAML.add_domain_type( "clarkevans.com,2002", 'graph/line', &one_shape_proc )
  YAML.add_domain_type( "clarkevans.com,2002", 'graph/label', &one_shape_proc )
ruby: |
  [
    {
      "radius" => 7,
      "center"=>
      {
        "x" => 73,
        "y" => 129
      },
      "TYPE" => "Shape: graph/circle"
    }, {
      "finish" =>
      {
        "x" => 89,
        "y" => 102
      },
      "TYPE" => "Shape: graph/line",
      "start" =>
      {
        "x" => 73,
        "y" => 129
      }
    }, {
      "TYPE" => "Shape: graph/label",
      "value" => "Pretty vector drawing.",
      "start" =>
      {
        "x" => 73,
        "y" => 129
      },
      "color" => 16772795
    },
    "Shape Container"
  ]
# ---
# test: Unordered set
# spec: 2.25
# yaml: |
#   # sets are represented as a
#   # mapping where each key is
#   # associated with the empty string
#   --- !set
#   ? Mark McGwire
#   ? Sammy Sosa
#   ? Ken Griff
---
test: Ordered mappings
todo: true
spec: 2.26
yaml: |
  # ordered maps are represented as
  # a sequence of mappings, with
  # each mapping having one key
  --- !omap
  - Mark McGwire: 65
  - Sammy Sosa: 63
  - Ken Griffy: 58
ruby: |
  YAML::Omap[
    'Mark McGwire', 65,
    'Sammy Sosa', 63,
    'Ken Griffy', 58
  ]
---
test: Invoice
dump_skip: true
spec: 2.27
yaml: |
  --- !clarkevans.com,2002/^invoice
  invoice: 34843
  date   : 2001-01-23
  bill-to: &id001
      given  : Chris
      family : Dumars
      address:
          lines: |
              458 Walkman Dr.
              Suite #292
          city    : Royal Oak
          state   : MI
          postal  : 48046
  ship-to: *id001
  product:
      -
        sku         : BL394D
        quantity    : 4
        description : Basketball
        price       : 450.00
      -
        sku         : BL4438H
        quantity    : 1
        description : Super Hoop
        price       : 2392.00
  tax  : 251.42
  total: 4443.52
  comments: >
    Late afternoon is best.
    Backup contact is Nancy
    Billsmer @ 338-4338.
php: |
  array(
     'invoice' => 34843, 'date' => mktime(0, 0, 0, 1, 23, 2001),
     'bill-to' =>
      array( 'given' => 'Chris', 'family' => 'Dumars', 'address' => array( 'lines' => "458 Walkman Dr.\nSuite #292\n", 'city' => 'Royal Oak', 'state' => 'MI', 'postal' => 48046 ) )
     , 'ship-to' =>
      array( 'given' => 'Chris', 'family' => 'Dumars', 'address' => array( 'lines' => "458 Walkman Dr.\nSuite #292\n", 'city' => 'Royal Oak', 'state' => 'MI', 'postal' => 48046 ) )
     , 'product' =>
       array(
        array( 'sku' => 'BL394D', 'quantity' => 4, 'description' => 'Basketball', 'price' => 450.00 ),
        array( 'sku' => 'BL4438H', 'quantity' => 1, 'description' => 'Super Hoop', 'price' => 2392.00 )
      ),
     'tax' => 251.42, 'total' => 4443.52,
     'comments' => "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338.\n"
  )
---
test: Log file
todo: true
spec: 2.28
yaml: |
  ---
  Time: 2001-11-23 15:01:42 -05:00
  User: ed
  Warning: >
    This is an error message
    for the log file
  ---
  Time: 2001-11-23 15:02:31 -05:00
  User: ed
  Warning: >
    A slightly different error
    message.
  ---
  Date: 2001-11-23 15:03:17 -05:00
  User: ed
  Fatal: >
    Unknown variable "bar"
  Stack:
    - file: TopClass.py
      line: 23
      code: |
        x = MoreObject("345\n")
    - file: MoreClass.py
      line: 58
      code: |-
        foo = bar
ruby: |
  y = YAML::Stream.new
  y.add( { 'Time' => YAML::mktime( 2001, 11, 23, 15, 01, 42, 00, "-05:00" ),
           'User' => 'ed', 'Warning' => "This is an error message for the log file\n" } )
  y.add( { 'Time' => YAML::mktime( 2001, 11, 23, 15, 02, 31, 00, "-05:00" ),
           'User' => 'ed', 'Warning' => "A slightly different error message.\n" } )
  y.add( { 'Date' => YAML::mktime( 2001, 11, 23, 15, 03, 17, 00, "-05:00" ),
           'User' => 'ed', 'Fatal' => "Unknown variable \"bar\"\n",
           'Stack' => [
           { 'file' => 'TopClass.py', 'line' => 23, 'code' => "x = MoreObject(\"345\\n\")\n" },
           { 'file' => 'MoreClass.py', 'line' => 58, 'code' => "foo = bar" } ] } )
documents: 3

---
test: Throwaway comments
yaml: |
   ### These are four throwaway comment  ###

   ### lines (the second line is empty). ###
   this: |   # Comments may trail lines.
      contains three lines of text.
      The third one starts with a
      # character. This isn't a comment.

   # These are three throwaway comment
   # lines (the first line is empty).
php: |
   array(
     'this' => "contains three lines of text.\nThe third one starts with a\n# character. This isn't a comment.\n"
   )
---
test: Document with a single value
todo: true
yaml: |
   --- >
   This YAML stream contains a single text value.
   The next stream is a log file - a sequence of
   log entries. Adding an entry to the log is a
   simple matter of appending it at the end.
ruby: |
   "This YAML stream contains a single text value. The next stream is a log file - a sequence of log entries. Adding an entry to the log is a simple matter of appending it at the end.\n"
---
test: Document stream
todo: true
yaml: |
   ---
   at: 2001-08-12 09:25:00.00 Z
   type: GET
   HTTP: '1.0'
   url: '/index.html'
   ---
   at: 2001-08-12 09:25:10.00 Z
   type: GET
   HTTP: '1.0'
   url: '/toc.html'
ruby: |
   y = YAML::Stream.new
   y.add( {
      'at' => Time::utc( 2001, 8, 12, 9, 25, 00 ),
      'type' => 'GET',
      'HTTP' => '1.0',
      'url' => '/index.html'
   } )
   y.add( {
      'at' => Time::utc( 2001, 8, 12, 9, 25, 10 ),
      'type' => 'GET',
      'HTTP' => '1.0',
      'url' => '/toc.html'
   } )
documents: 2

---
test: Top level mapping
yaml: |
   # This stream is an example of a top-level mapping.
   invoice : 34843
   date    : 2001-01-23
   total   : 4443.52
php: |
   array(
      'invoice' => 34843,
      'date' => mktime(0, 0, 0, 1, 23, 2001),
      'total' => 4443.52
   )
---
test: Single-line documents
todo: true
yaml: |
  # The following is a sequence of three documents.
  # The first contains an empty mapping, the second
  # an empty sequence, and the last an empty string.
  --- {}
  --- [ ]
  --- ''
ruby: |
  y = YAML::Stream.new
  y.add( {} )
  y.add( [] )
  y.add( '' )
documents: 3

---
test: Document with pause
todo: true
yaml: |
  # A communication channel based on a YAML stream.
  ---
  sent at: 2002-06-06 11:46:25.10 Z
  payload: Whatever
  # Receiver can process this as soon as the following is sent:
  ...
  # Even if the next message is sent long after:
  ---
  sent at: 2002-06-06 12:05:53.47 Z
  payload: Whatever
  ...
ruby: |
  y = YAML::Stream.new
  y.add(
    { 'sent at' => YAML::mktime( 2002, 6, 6, 11, 46, 25, 0.10 ),
      'payload' => 'Whatever' }
  )
  y.add(
    { "payload" => "Whatever", "sent at" => YAML::mktime( 2002, 6, 6, 12, 5, 53, 0.47 ) }
  )
documents: 2

---
test: Explicit typing
yaml: |
   integer: 12
   also int: ! "12"
   string: !str 12
php: |
   array( 'integer' => 12, 'also int' => 12, 'string' => '12' )
---
test: Private types
todo: true
yaml: |
  # Both examples below make use of the 'x-private:ball'
  # type family URI, but with different semantics.
  ---
  pool: !!ball
    number: 8
    color: black
  ---
  bearing: !!ball
    material: steel
ruby: |
  y = YAML::Stream.new
  y.add( { 'pool' =>
    YAML::PrivateType.new( 'ball',
      { 'number' => 8, 'color' => 'black' } ) }
  )
  y.add( { 'bearing' =>
    YAML::PrivateType.new( 'ball',
      { 'material' => 'steel' } ) }
  )
documents: 2

---
test: Type family under yaml.org
yaml: |
  # The URI is 'tag:yaml.org,2002:str'
  - !str a Unicode string
php: |
  array( 'a Unicode string' )
---
test: Type family under perl.yaml.org
todo: true
yaml: |
  # The URI is 'tag:perl.yaml.org,2002:Text::Tabs'
  - !perl/Text::Tabs {}
ruby: |
  [ YAML::DomainType.new( 'perl.yaml.org,2002', 'Text::Tabs', {} ) ]
---
test: Type family under clarkevans.com
todo: true
yaml: |
  # The URI is 'tag:clarkevans.com,2003-02:timesheet'
  - !clarkevans.com,2003-02/timesheet {}
ruby: |
  [ YAML::DomainType.new( 'clarkevans.com,2003-02', 'timesheet', {} ) ]
---
test: URI Escaping
todo: true
yaml: |
  same:
    - !domain.tld,2002/type\x30 value
    - !domain.tld,2002/type0 value
  different: # As far as the YAML parser is concerned
    - !domain.tld,2002/type%30 value
    - !domain.tld,2002/type0 value
ruby-setup: |
  YAML.add_domain_type( "domain.tld,2002", "type0" ) { |type, val|
    "ONE: #{val}"
  }
  YAML.add_domain_type( "domain.tld,2002", "type%30" ) { |type, val|
    "TWO: #{val}"
  }
ruby: |
  { 'same' => [ 'ONE: value', 'ONE: value' ], 'different' => [ 'TWO: value', 'ONE: value' ] }
---
test: URI Prefixing
todo: true
yaml: |
  # 'tag:domain.tld,2002:invoice' is some type family.
  invoice: !domain.tld,2002/^invoice
    # 'seq' is shorthand for 'tag:yaml.org,2002:seq'.
    # This does not effect '^customer' below
    # because it is does not specify a prefix.
    customers: !seq
      # '^customer' is shorthand for the full
      # notation 'tag:domain.tld,2002:customer'.
      - !^customer
        given : Chris
        family : Dumars
ruby-setup: |
  YAML.add_domain_type( "domain.tld,2002", /(invoice|customer)/ ) { |type, val|
    if val.is_a? ::Hash
      scheme, domain, type = type.split( /:/, 3 )
      val['type'] = "domain #{type}"
      val
    else
      raise YAML::Error, "Not a Hash in domain.tld/invoice: " + val.inspect
    end
  }
ruby: |
  { "invoice"=> { "customers"=> [ { "given"=>"Chris", "type"=>"domain customer", "family"=>"Dumars" } ], "type"=>"domain invoice" } }

---
test: Overriding anchors
yaml: |
  anchor : &A001 This scalar has an anchor.
  override : &A001 >
   The alias node below is a
   repeated use of this value.
  alias : *A001
php: |
  array( 'anchor' => 'This scalar has an anchor.',
    'override' => "The alias node below is a repeated use of this value.\n",
    'alias' => "The alias node below is a repeated use of this value.\n" )
---
test: Flow and block formatting
todo: true
yaml: |
  empty: []
  flow: [ one, two, three # May span lines,
           , four,           # indentation is
             five ]          # mostly ignored.
  block:
   - First item in top sequence
   -
    - Subordinate sequence entry
   - >
     A folded sequence entry
   - Sixth item in top sequence
ruby: |
  { 'empty' => [], 'flow' => [ 'one', 'two', 'three', 'four', 'five' ],
    'block' => [ 'First item in top sequence', [ 'Subordinate sequence entry' ],
    "A folded sequence entry\n", 'Sixth item in top sequence' ] }
---
test: Complete mapping test
todo: true
yaml: |
 empty: {}
 flow: { one: 1, two: 2 }
 spanning: { one: 1,
    two: 2 }
 block:
  first : First entry
  second:
   key: Subordinate mapping
  third:
   - Subordinate sequence
   - { }
   - Previous mapping is empty.
   - A key: value pair in a sequence.
     A second: key:value pair.
   - The previous entry is equal to the following one.
   -
     A key: value pair in a sequence.
     A second: key:value pair.
  !float 12 : This key is a float.
  ? >
   ?
  : This key had to be protected.
  "\a" : This key had to be escaped.
  ? >
   This is a
   multi-line
   folded key
  : Whose value is
    also multi-line.
  ? this also works as a key
  : with a value at the next line.
  ?
   - This key
   - is a sequence
  :
   - With a sequence value.
  ?
   This: key
   is a: mapping
  :
   with a: mapping value.
ruby: |
  { 'empty' => {}, 'flow' => { 'one' => 1, 'two' => 2 },
    'spanning' => { 'one' => 1, 'two' => 2 },
    'block' => { 'first' => 'First entry', 'second' =>
    { 'key' => 'Subordinate mapping' }, 'third' =>
      [ 'Subordinate sequence', {}, 'Previous mapping is empty.',
        { 'A key' => 'value pair in a sequence.', 'A second' => 'key:value pair.' },
        'The previous entry is equal to the following one.',
        { 'A key' => 'value pair in a sequence.', 'A second' => 'key:value pair.' } ],
    12.0 => 'This key is a float.', "?\n" => 'This key had to be protected.',
    "\a" => 'This key had to be escaped.',
    "This is a multi-line folded key\n" => "Whose value is also multi-line.",
    'this also works as a key' => 'with a value at the next line.',
    [ 'This key', 'is a sequence' ] => [ 'With a sequence value.' ] } }
  # Couldn't recreate map exactly, so we'll do a detailed check to be sure it's entact
  obj_y['block'].keys.each { |k|
    if Hash === k
      v = obj_y['block'][k]
      if k['This'] == 'key' and k['is a'] == 'mapping' and v['with a'] == 'mapping value.'
         obj_r['block'][k] = v
      end
    end
  }
---
test: Literal explicit indentation
yaml: |
   # Explicit indentation must
   # be given in all the three
   # following cases.
   leading spaces: |2
         This value starts with four spaces.

   leading line break: |2

     This value starts with a line break.

   leading comment indicator: |2
     # first line starts with a
     # character.

   # Explicit indentation may
   # also be given when it is
   # not required.
   redundant: |2
     This value is indented 2 spaces.
php: |
   array(
      'leading spaces' => "    This value starts with four spaces.\n",
      'leading line break' => "\nThis value starts with a line break.\n",
      'leading comment indicator' => "# first line starts with a\n# character.\n",
      'redundant' => "This value is indented 2 spaces.\n"
   )
---
test: Chomping and keep modifiers
yaml: |
    clipped: |
        This has one newline.

    same as "clipped" above: "This has one newline.\n"

    stripped: |-
        This has no newline.

    same as "stripped" above: "This has no newline."

    kept: |+
        This has two newlines.

    same as "kept" above: "This has two newlines.\n\n"
php: |
    array(
      'clipped' => "This has one newline.\n",
      'same as "clipped" above' => "This has one newline.\n",
      'stripped' => 'This has no newline.',
      'same as "stripped" above' => 'This has no newline.',
      'kept' => "This has two newlines.\n\n",
      'same as "kept" above' => "This has two newlines.\n\n"
    )
---
test: Literal combinations
todo: true
yaml: |
   empty: |

   literal: |
    The \ ' " characters may be
    freely used. Leading white
       space is significant.

    Line breaks are significant.
    Thus this value contains one
    empty line and ends with a
    single line break, but does
    not start with one.

   is equal to: "The \\ ' \" characters may \
    be\nfreely used. Leading white\n   space \
    is significant.\n\nLine breaks are \
    significant.\nThus this value contains \
    one\nempty line and ends with a\nsingle \
    line break, but does\nnot start with one.\n"

   # Comments may follow a block
   # scalar value. They must be
   # less indented.

   # Modifiers may be combined in any order.
   indented and chomped: |2-
       This has no newline.

   also written as: |-2
       This has no newline.

   both are equal to: "  This has no newline."
php: |
   array(
     'empty' => '',
     'literal' => "The \\ ' \" characters may be\nfreely used. Leading white\n   space " +
       "is significant.\n\nLine breaks are significant.\nThus this value contains one\n" +
       "empty line and ends with a\nsingle line break, but does\nnot start with one.\n",
     'is equal to' => "The \\ ' \" characters may be\nfreely used. Leading white\n   space " +
       "is significant.\n\nLine breaks are significant.\nThus this value contains one\n" +
       "empty line and ends with a\nsingle line break, but does\nnot start with one.\n",
     'indented and chomped' => '  This has no newline.',
     'also written as' => '  This has no newline.',
     'both are equal to' => '  This has no newline.'
   )
---
test: Folded combinations
todo: true
yaml: |
   empty: >

   one paragraph: >
    Line feeds are converted
    to spaces, so this value
    contains no line breaks
    except for the final one.

   multiple paragraphs: >2

     An empty line, either
     at the start or in
     the value:

     Is interpreted as a
     line break. Thus this
     value contains three
     line breaks.

   indented text: >
       This is a folded
       paragraph followed
       by a list:
        * first entry
        * second entry
       Followed by another
       folded paragraph,
       another list:

        * first entry

        * second entry

       And a final folded
       paragraph.

   above is equal to: |
       This is a folded paragraph followed by a list:
        * first entry
        * second entry
       Followed by another folded paragraph, another list:

        * first entry

        * second entry

       And a final folded paragraph.

   # Explicit comments may follow
   # but must be less indented.
php: |
   array(
     'empty' => '',
     'one paragraph' => 'Line feeds are converted to spaces, so this value'.
       " contains no line breaks except for the final one.\n",
     'multiple paragraphs' => "\nAn empty line, either at the start or in the value:\n".
       "Is interpreted as a line break. Thus this value contains three line breaks.\n",
     'indented text' => "This is a folded paragraph followed by a list:\n".
       " * first entry\n * second entry\nFollowed by another folded paragraph, ".
       "another list:\n\n * first entry\n\n * second entry\n\nAnd a final folded paragraph.\n",
     'above is equal to' => "This is a folded paragraph followed by a list:\n".
       " * first entry\n * second entry\nFollowed by another folded paragraph, ".
       "another list:\n\n * first entry\n\n * second entry\n\nAnd a final folded paragraph.\n"
   )
---
test: Single quotes
todo: true
yaml: |
   empty: ''
   second: '! : \ etc. can be used freely.'
   third: 'a single quote '' must be escaped.'
   span: 'this contains
         six spaces

         and one
         line break'
   is same as: "this contains six spaces\nand one line break"
php: |
   array(
     'empty' => '',
     'second' => '! : \\ etc. can be used freely.',
     'third' => "a single quote ' must be escaped.",
     'span' => "this contains six spaces\nand one line break",
     'is same as' => "this contains six spaces\nand one line break"
   )
---
test: Double quotes
todo: true
yaml: |
   empty: ""
   second: "! : etc. can be used freely."
   third: "a \" or a \\ must be escaped."
   fourth: "this value ends with an LF.\n"
   span: "this contains
     four  \
         spaces"
   is equal to: "this contains four  spaces"
php: |
   array(
     'empty' => '',
     'second' => '! : etc. can be used freely.',
     'third' => 'a " or a \\ must be escaped.',
     'fourth' => "this value ends with an LF.\n",
     'span' => "this contains four  spaces",
     'is equal to' => "this contains four  spaces"
   )
---
test: Unquoted strings
todo: true
yaml: |
   first: There is no unquoted empty string.

   second: 12          ## This is an integer.

   third: !str 12      ## This is a string.

   span: this contains
         six spaces

         and one
         line break

   indicators: this has no comments.
               #:foo and bar# are
               both text.

   flow: [ can span
              lines, # comment
              like
              this ]

   note: { one-line keys: but multi-line values }

php: |
   array(
     'first' => 'There is no unquoted empty string.',
     'second' => 12,
     'third' => '12',
     'span' => "this contains six spaces\nand one line break",
     'indicators' => "this has no comments. #:foo and bar# are both text.",
     'flow' => [ 'can span lines', 'like this' ],
     'note' => { 'one-line keys' => 'but multi-line values' }
   )
---
test: Spanning sequences
todo: true
yaml: |
   # The following are equal seqs
   # with different identities.
   flow: [ one, two ]
   spanning: [ one,
        two ]
   block:
     - one
     - two
php: |
   array(
     'flow' => [ 'one', 'two' ],
     'spanning' => [ 'one', 'two' ],
     'block' => [ 'one', 'two' ]
   )
---
test: Flow mappings
yaml: |
   # The following are equal maps
   # with different identities.
   flow: { one: 1, two: 2 }
   block:
       one: 1
       two: 2
php: |
   array(
     'flow' => array( 'one' => 1, 'two' => 2 ),
     'block' => array( 'one' => 1, 'two' => 2 )
   )
---
test: Representations of 12
todo: true
yaml: |
   - 12 # An integer
   # The following scalars
   # are loaded to the
   # string value '1' '2'.
   - !str 12
   - '12'
   - "12"
   - "\
     1\
     2\
     "
   # Strings containing paths and regexps can be unquoted:
   - /foo/bar
   - d:/foo/bar
   - foo/bar
   - /a.*b/
php: |
   array( 12, '12', '12', '12', '12', '/foo/bar', 'd:/foo/bar', 'foo/bar', '/a.*b/' )
---
test: "Null"
todo: true
yaml: |
   canonical: ~

   english: null

   # This sequence has five
   # entries, two with values.
   sparse:
     - ~
     - 2nd entry
     - Null
     - 4th entry
     -

   four: This mapping has five keys,
         only two with values.

php: |
   array (
     'canonical' => null,
     'english' => null,
     'sparse' => array( null, '2nd entry', null, '4th entry', null ]),
     'four' => 'This mapping has five keys, only two with values.'
   )
---
test: Omap
todo: true
yaml: |
   # Explicitly typed dictionary.
   Bestiary: !omap
     - aardvark: African pig-like ant eater. Ugly.
     - anteater: South-American ant eater. Two species.
     - anaconda: South-American constrictor snake. Scary.
     # Etc.
ruby: |
   {
     'Bestiary' => YAML::Omap[
       'aardvark', 'African pig-like ant eater. Ugly.',
       'anteater', 'South-American ant eater. Two species.',
       'anaconda', 'South-American constrictor snake. Scary.'
     ]
   }

---
test: Pairs
todo: true
yaml: |
  # Explicitly typed pairs.
  tasks: !pairs
    - meeting: with team.
    - meeting: with boss.
    - break: lunch.
    - meeting: with client.
ruby: |
  {
    'tasks' => YAML::Pairs[
      'meeting', 'with team.',
      'meeting', 'with boss.',
      'break', 'lunch.',
      'meeting', 'with client.'
    ]
  }

---
test: Set
todo: true
yaml: |
  # Explicitly typed set.
  baseball players: !set
    Mark McGwire:
    Sammy Sosa:
    Ken Griffey:
ruby: |
  {
    'baseball players' => YAML::Set[
      'Mark McGwire', nil,
      'Sammy Sosa', nil,
      'Ken Griffey', nil
    ]
  }

---
test: Boolean
yaml: |
   false: used as key
   logical:  true
   answer: false
php: |
   array(
     false => 'used as key',
     'logical' => true,
     'answer' => false
   )
---
test: Integer
yaml: |
   canonical: 12345
   decimal: +12,345
   octal: 014
   hexadecimal: 0xC
php: |
   array(
     'canonical' => 12345,
     'decimal' => 12345,
     'octal' => 12,
     'hexadecimal' => 12
   )
---
test: Float
yaml: |
   canonical: 1.23015e+3
   exponential: 12.3015e+02
   fixed: 1,230.15
   negative infinity: -.inf
   not a number: .NaN
php: |
  array(
    'canonical' => 1230.15,
    'exponential' => 1230.15,
    'fixed' => 1230.15,
    'negative infinity' => log(0),
    'not a number' => -log(0)
  )
---
test: Timestamp
todo: true
yaml: |
   canonical:       2001-12-15T02:59:43.1Z
   valid iso8601:   2001-12-14t21:59:43.10-05:00
   space separated: 2001-12-14 21:59:43.10 -05:00
   date (noon UTC): 2002-12-14
ruby: |
   array(
     'canonical' => YAML::mktime( 2001, 12, 15, 2, 59, 43, 0.10 ),
     'valid iso8601' => YAML::mktime( 2001, 12, 14, 21, 59, 43, 0.10, "-05:00" ),
     'space separated' => YAML::mktime( 2001, 12, 14, 21, 59, 43, 0.10, "-05:00" ),
     'date (noon UTC)' => Date.new( 2002, 12, 14 )
   )
---
test: Binary
todo: true
yaml: |
   canonical: !binary "\
    R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5\
    OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+\
    +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC\
    AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs="
   base64: !binary |
    R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5
    OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+
    +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC
    AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs=
   description: >
    The binary value above is a tiny arrow
    encoded as a gif image.
ruby-setup: |
   arrow_gif = "GIF89a\f\000\f\000\204\000\000\377\377\367\365\365\356\351\351\345fff\000\000\000\347\347\347^^^\363\363\355\216\216\216\340\340\340\237\237\237\223\223\223\247\247\247\236\236\236iiiccc\243\243\243\204\204\204\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371\377\376\371!\376\016Made with GIMP\000,\000\000\000\000\f\000\f\000\000\005,  \216\2010\236\343@\024\350i\020\304\321\212\010\034\317\200M$z\357\3770\205p\270\2601f\r\e\316\001\303\001\036\020' \202\n\001\000;"
ruby: |
   {
     'canonical' => arrow_gif,
     'base64' => arrow_gif,
     'description' => "The binary value above is a tiny arrow encoded as a gif image.\n"
   }

---
test: Merge key
todo: true
yaml: |
  ---
  - &CENTER { x: 1, y: 2 }
  - &LEFT { x: 0, y: 2 }
  - &BIG { r: 10 }
  - &SMALL { r: 1 }

  # All the following maps are equal:

  - # Explicit keys
    x: 1
    y: 2
    r: 10
    label: center/big

  - # Merge one map
    << : *CENTER
    r: 10
    label: center/big

  - # Merge multiple maps
    << : [ *CENTER, *BIG ]
    label: center/big

  - # Override
    << : [ *BIG, *LEFT, *SMALL ]
    x: 1
    label: center/big

ruby-setup: |
  center = { 'x' => 1, 'y' => 2 }
  left = { 'x' => 0, 'y' => 2 }
  big = { 'r' => 10 }
  small = { 'r' => 1 }
  node1 = { 'x' => 1, 'y' => 2, 'r' => 10, 'label' => 'center/big' }
  node2 = center.dup
  node2.update( { 'r' => 10, 'label' => 'center/big' } )
  node3 = big.dup
  node3.update( center )
  node3.update( { 'label' => 'center/big' } )
  node4 = small.dup
  node4.update( left )
  node4.update( big )
  node4.update( { 'x' => 1, 'label' => 'center/big' } )

ruby: |
  [
    center, left, big, small, node1, node2, node3, node4
  ]

---
test: Default key
todo: true
yaml: |
   ---     # Old schema
   link with:
     - library1.dll
     - library2.dll
   ---     # New schema
   link with:
     - = : library1.dll
       version: 1.2
     - = : library2.dll
       version: 2.3
ruby: |
   y = YAML::Stream.new
   y.add( { 'link with' => [ 'library1.dll', 'library2.dll' ] } )
   obj_h = Hash[ 'version' => 1.2 ]
   obj_h.default = 'library1.dll'
   obj_h2 = Hash[ 'version' => 2.3 ]
   obj_h2.default = 'library2.dll'
   y.add( { 'link with' => [ obj_h, obj_h2 ] } )
documents: 2

---
test: Special keys
todo: true
yaml: |
   "!": These three keys
   "&": had to be quoted
   "=": and are normal strings.
   # NOTE: the following node should NOT be serialized this way.
   encoded node :
    !special '!' : '!type'
    !special|canonical '&' : 12
    = : value
   # The proper way to serialize the above node is as follows:
   node : !!type &12 value
ruby: |
   { '!' => 'These three keys', '&' => 'had to be quoted',
     '=' => 'and are normal strings.',
     'encoded node' => YAML::PrivateType.new( 'type', 'value' ),
     'node' => YAML::PrivateType.new( 'type', 'value' ) }
--- %YAML:1.0
test: Trailing Document Separator
todo: true
brief: >
    You can separate YAML documents
    with a string of three dashes.
yaml: |
    - foo: 1
      bar: 2
    ---
    more: stuff
python: |
    [
        [ { 'foo': 1, 'bar': 2 } ],
        { 'more': 'stuff' }
    ]
ruby: |
    [ { 'foo' => 1, 'bar' => 2 } ]

---
test: Leading Document Separator
todo: true
brief: >
    You can explicity give an opening
    document separator to your YAML stream.
yaml: |
    ---
    - foo: 1
      bar: 2
    ---
    more: stuff
python: |
    [
        [ {'foo': 1, 'bar': 2}],
        {'more': 'stuff'}
    ]
ruby: |
    [ { 'foo' => 1, 'bar' => 2 } ]

---
test: YAML Header
todo: true
brief: >
    The opening separator can contain directives
    to the YAML parser, such as the version
    number.
yaml: |
    --- %YAML:1.0
    foo: 1
    bar: 2
php: |
    array('foo' => 1, 'bar' => 2)
documents: 1

---
test: Red Herring Document Separator
brief: >
    Separators included in blocks or strings
    are treated as blocks or strings, as the
    document separator should have no indentation
    preceding it.
yaml: |
    foo: |
        ---
php: |
    array('foo' => "---\n")

---
test: Multiple Document Separators in Block
brief: >
    This technique allows you to embed other YAML
    documents within literal blocks.
yaml: |
    foo: |
        ---
        foo: bar
        ---
        yo: baz
    bar: |
        fooness
php: |
    array(
       'foo' => "---\nfoo: bar\n---\nyo: baz\n",
       'bar' => "fooness\n"
    )
--- %YAML:1.0
test: Objects
brief: >
    Comments at the end of a line
yaml: |
    ex1: "foo # bar"
    ex2: "foo # bar" # comment
    ex3: 'foo # bar' # comment
    ex4: foo # comment
php: |
    array('ex1' => 'foo # bar', 'ex2' => 'foo # bar', 'ex3' => 'foo # bar', 'ex4' => 'foo')
--- %YAML:1.0
test: Multiple quoted string on one line
brief: >
    Multiple quoted string on one line
yaml: |
    stripped_title: { name: "foo bar", help: "bar foo" }
php: |
    array('stripped_title' => array('name' => 'foo bar', 'help' => 'bar foo'))
---
test: Empty sequence
yaml: |
    foo: [ ]
php: |
    array('foo' => array())
---
test: Empty value
yaml: |
    foo:
php: |
    array('foo' => null)
---
test: Inline string parsing
brief: >
    Inline string parsing
yaml: |
    test: ['complex: string', 'another [string]']
php: |
    array('test' => array('complex: string', 'another [string]'))
---
test: Boolean
brief: >
    Boolean
yaml: |
    - false
    - true
    - null
    - ~
    - 'false'
    - 'true'
    - 'null'
    - '~'
php: |
    array(
      false,
      true,
      null,
      null,
      'false',
      'true',
      'null',
      '~',
    )
---
test: Empty lines in folded blocks
brief: >
  Empty lines in folded blocks
yaml: |
  foo:
    bar: |
      foo


        
      bar
php: |
  array('foo' => array('bar' => "foo\n\n\n  \nbar\n"))
---
test: IP addresses
brief: >
  IP addresses
yaml: |
  foo: 10.0.0.2
php: |
  array('foo' => '10.0.0.2')
---
test: A sequence with an embedded mapping
brief: >
  A sequence with an embedded mapping
yaml: |
  - foo
  - bar: { bar: foo }
php: |
  array('foo', array('bar' => array('bar' => 'foo')))
---
test: A sequence with an unordered array
brief: >
  A sequence with an unordered array
yaml: |
  1: foo
  0: bar
php: |
  array(1 => 'foo', 0 => 'bar')
---
test: Octal
brief: as in spec example 2.19, octal value is converted
yaml: |
  foo: 0123
php: |
  array('foo' => 83)
---
test: Octal strings
brief: Octal notation in a string must remain a string
yaml: |
  foo: "0123"
php: |
  array('foo' => '0123')
---
test: Octal strings
brief: Octal notation in a string must remain a string
yaml: |
  foo: '0123'
php: |
  array('foo' => '0123')
---
test: Octal strings
brief: Octal notation in a string must remain a string
yaml: |
  foo: |
    0123
php: |
  array('foo' => "0123\n")
---
test: Document as a simple hash
brief: Document as a simple hash
yaml: |
  { foo: bar }
php: |
  array('foo' => 'bar')
---
test: Document as a simple array
brief: Document as a simple array
yaml: |
  [ foo, bar ]
php: |
  array('foo', 'bar')
--- %YAML:1.0
test: Comments at the end of a line
brief: >
    Comments at the end of a line
yaml: |
    ex1: "foo # bar"
    ex2: "foo # bar" # comment
    ex3: 'foo # bar' # comment
    ex4: foo # comment
php: |
    array('ex1' => 'foo # bar', 'ex2' => 'foo # bar', 'ex3' => 'foo # bar', 'ex4' => 'foo')
---
test: Comments in the middle
brief: >
  Comments in the middle
yaml: |
    foo:
    # some comment
    # some comment
      bar: foo
    # some comment
    # some comment
php: |
    array('foo' => array('bar' => 'foo'))
---
test: Comments on a hash line
brief: >
  Comments on a hash line
yaml: |
    foo:   # a comment
      foo: bar # a comment
php: |
    array('foo' => array('foo' => 'bar'))
---
test: 'Value starting with a #'
brief: >
  'Value starting with a #'
yaml: |
    foo:   '#bar'
php: |
    array('foo' => '#bar')
---
test: Document starting with a comment and a separator
brief: >
  Commenting before document start is allowed
yaml: |
    # document comment
    ---
    foo: bar # a comment
php: |
    array('foo' => 'bar')
---
test: Comment containing a colon on a hash line
brief: >
    Comment containing a colon on a scalar line
yaml: 'foo # comment: this is also part of the comment'
php: |
    'foo'
---
test: 'Hash key containing a #'
brief: >
    'Hash key containing a #'
yaml: 'foo#bar: baz'
php: |
    array('foo#bar' => 'baz')
--- %YAML:1.0
test: Unindented collection
brief: >
    Unindented collection
yaml: |
    collection:
    - item1
    - item2
    - item3
php: |
    array('collection' => array('item1', 'item2', 'item3'))
---
test: Nested unindented collection (two levels)
brief: >
    Nested unindented collection
yaml: |
    collection:
        key:
        - a
        - b
        - c
php: |
    array('collection' => array('key' => array('a', 'b', 'c')))
---
test: Nested unindented collection (three levels)
brief: >
    Nested unindented collection
yaml: |
    collection:
        key:
            subkey:
            - one
            - two
            - three
php: |
    array('collection' => array('key' => array('subkey' => array('one', 'two', 'three'))))
---
test: Key/value after unindented collection (1)
brief: >
    Key/value after unindented collection (1)
yaml: |
    collection:
        key:
        - a
        - b
        - c
    foo: bar
php: |
    array('collection' => array('key' => array('a', 'b', 'c')), 'foo' => 'bar')
---
test: Key/value after unindented collection (at the same level)
brief: >
    Key/value after unindented collection
yaml: |
    collection:
        key:
        - a
        - b
        - c
        foo: bar
php: |
    array('collection' => array('key' => array('a', 'b', 'c'), 'foo' => 'bar'))
- escapedCharacters
- sfComments
- sfCompact
- sfTests
- sfObjects
- sfMergeKey
- sfQuotes
- YtsAnchorAlias
- YtsBasicTests
- YtsBlockMapping
- YtsDocumentSeparator
- YtsErrorTests
- YtsFlowCollections
- YtsFoldedScalars
- YtsNullsAndEmpties
- YtsSpecificationExamples
- YtsTypeTransfers
- unindentedCollections
--- %YAML:1.0
test: Simple Alias Example
brief: >
    If you need to refer to the same item of data twice,
    you can give that item an alias.  The alias is a plain
    string, starting with an ampersand.  The item may then
    be referred to by the alias throughout your document
    by using an asterisk before the name of the alias.
    This is called an anchor.
yaml: |
    - &showell Steve
    - Clark
    - Brian
    - Oren
    - *showell
php: |
    array('Steve', 'Clark', 'Brian', 'Oren', 'Steve')

---
test: Alias of a Mapping
brief: >
    An alias can be used on any item of data, including
    sequences, mappings, and other complex data types.
yaml: |
    - &hello
        Meat: pork
        Starch: potato
    - banana
    - *hello
php: |
    array(array('Meat'=>'pork', 'Starch'=>'potato'), 'banana', array('Meat'=>'pork', 'Starch'=>'potato'))
--- %YAML:1.0
test: Some characters at the beginning of a string must be escaped
brief: >
    Some characters at the beginning of a string must be escaped
yaml: |
    foo: | bar
php: |
    array('foo' => '| bar')
---
test: A key can be a quoted string
brief: >
  A key can be a quoted string
yaml: |
    "foo1": bar
    'foo2': bar
    "foo \" bar": bar
    'foo '' bar': bar
    'foo3: ': bar
    "foo4: ": bar
    foo5: { "foo \" bar: ": bar, 'foo '' bar: ': bar }
php: |
    array(
      'foo1' => 'bar',
      'foo2' => 'bar',
      'foo " bar' => 'bar',
      'foo \' bar' => 'bar',
      'foo3: ' => 'bar',
      'foo4: ' => 'bar',
      'foo5' => array(
        'foo " bar: ' => 'bar',
        'foo \' bar: ' => 'bar',
      ),
    )
--- %YAML:1.0
test: Empty Sequence
brief: >
    You can represent the empty sequence
    with an empty inline sequence.
yaml: |
    empty: []
php: |
    array('empty' => array())
---
test: Empty Mapping
brief: >
    You can represent the empty mapping
    with an empty inline mapping.
yaml: |
    empty: {}
php: |
    array('empty' => array())
---
test: Empty Sequence as Entire Document
yaml: |
    []
php: |
    array()
---
test: Empty Mapping as Entire Document
yaml: |
    {}
php: |
    array()
---
test: Null as Document
yaml: |
    ~
php: |
    null
---
test: Empty String
brief: >
    You can represent an empty string
    with a pair of quotes.
yaml: |
    ''
php: |
    ''
---
test: One Element Mapping
brief: |
    A mapping with one key/value pair
yaml: |
    foo: bar
php: |
    array('foo' => 'bar')
---
test: Multi Element Mapping
brief: |
    More than one key/value pair
yaml: |
    red: baron
    white: walls
    blue: berries
php: |
    array(
     'red' => 'baron',
     'white' => 'walls',
     'blue' => 'berries',
    )
---
test: Values aligned
brief: |
    Often times human editors of documents will align the values even
    though YAML emitters generally don't.
yaml: |
    red:   baron
    white: walls
    blue:  berries
php: |
    array(
     'red' => 'baron',
     'white' => 'walls',
     'blue' => 'berries',
    )
---
test: Colons aligned
brief: |
    Spaces can come before the ': ' key/value separator.
yaml: |
    red   : baron
    white : walls
    blue  : berries
php: |
    array(
     'red' => 'baron',
     'white' => 'walls',
     'blue' => 'berries',
    )
---
test: Missing value for hash item
todo: true
brief: |
    Third item in this hash doesn't have a value
yaml: |
    okay: value
    also okay: ~
    causes error because no value specified
    last key: value okay here too
python-error: causes error because no value specified

---
test: Not indenting enough
brief: |
    There was a bug in PyYaml where it was off by one
    in the indentation check.  It was allowing the YAML
    below.
# This is actually valid YAML now. Someone should tell showell.
yaml: |
    foo:
    firstline: 1
    secondline: 2
php: |
  array('foo' => null, 'firstline' => 1, 'secondline' => 2)
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml\Tests;

use Symfony\Component\Yaml\Exception\ParseException;
use Symfony\Component\Yaml\Yaml;

class ParseExceptionTest extends \PHPUnit_Framework_TestCase
{
    public function testGetMessage()
    {
        $exception = new ParseException('Error message', 42, 'foo: bar', '/var/www/app/config.yml');
        if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
            $message = 'Error message in "/var/www/app/config.yml" at line 42 (near "foo: bar")';
        } else {
            $message = 'Error message in "\\/var\\/www\\/app\\/config.yml" at line 42 (near "foo: bar")';
        }

        $this->assertEquals($message, $exception->getMessage());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml\Tests;

use Symfony\Component\Yaml\Inline;

class InlineTest extends \PHPUnit_Framework_TestCase
{
    public function testParse()
    {
        foreach ($this->getTestsForParse() as $yaml => $value) {
            $this->assertSame($value, Inline::parse($yaml), sprintf('::parse() converts an inline YAML to a PHP structure (%s)', $yaml));
        }
    }

    public function testDump()
    {
        $testsForDump = $this->getTestsForDump();

        foreach ($testsForDump as $yaml => $value) {
            $this->assertEquals($yaml, Inline::dump($value), sprintf('::dump() converts a PHP structure to an inline YAML (%s)', $yaml));
        }

        foreach ($this->getTestsForParse() as $value) {
            $this->assertEquals($value, Inline::parse(Inline::dump($value)), 'check consistency');
        }

        foreach ($testsForDump as $value) {
            $this->assertEquals($value, Inline::parse(Inline::dump($value)), 'check consistency');
        }
    }

    public function testDumpNumericValueWithLocale()
    {
        $locale = setlocale(LC_NUMERIC, 0);
        if (false === $locale) {
            $this->markTestSkipped('Your platform does not support locales.');
        }

        $required_locales = array('fr_FR.UTF-8', 'fr_FR.UTF8', 'fr_FR.utf-8', 'fr_FR.utf8', 'French_France.1252');
        if (false === setlocale(LC_ALL, $required_locales)) {
            $this->markTestSkipped('Could not set any of required locales: '.implode(", ", $required_locales));
        }

        $this->assertEquals('1.2', Inline::dump(1.2));
        $this->assertContains('fr', strtolower(setlocale(LC_NUMERIC, 0)));

        setlocale(LC_ALL, $locale);
    }

    public function testHashStringsResemblingExponentialNumericsShouldNotBeChangedToINF()
    {
        $value = '686e444';

        $this->assertSame($value, Inline::parse(Inline::dump($value)));
    }

    /**
     * @expectedException \Symfony\Component\Yaml\Exception\ParseException
     */
    public function testParseScalarWithIncorrectlyQuotedStringShouldThrowException()
    {
        $value = "'don't do somthin' like that'";
        Inline::parse($value);
    }

    /**
     * @expectedException \Symfony\Component\Yaml\Exception\ParseException
     */
    public function testParseScalarWithIncorrectlyDoubleQuotedStringShouldThrowException()
    {
        $value = '"don"t do somthin" like that"';
        Inline::parse($value);
    }

    /**
     * @expectedException \Symfony\Component\Yaml\Exception\ParseException
     */
    public function testParseInvalidMappingKeyShouldThrowException()
    {
        $value = '{ "foo " bar": "bar" }';
        Inline::parse($value);
    }

    /**
     * @expectedException \Symfony\Component\Yaml\Exception\ParseException
     */
    public function testParseInvalidMappingShouldThrowException()
    {
        Inline::parse('[foo] bar');
    }

    /**
     * @expectedException \Symfony\Component\Yaml\Exception\ParseException
     */
    public function testParseInvalidSequenceShouldThrowException()
    {
        Inline::parse('{ foo: bar } bar');
    }

    public function testParseScalarWithCorrectlyQuotedStringShouldReturnString()
    {
        $value = "'don''t do somthin'' like that'";
        $expect = "don't do somthin' like that";

        $this->assertSame($expect, Inline::parseScalar($value));
    }

    protected function getTestsForParse()
    {
        return array(
            '' => '',
            'null' => null,
            'false' => false,
            'true' => true,
            '12' => 12,
            '-12' => -12,
            '"quoted string"' => 'quoted string',
            "'quoted string'" => 'quoted string',
            '12.30e+02' => 12.30e+02,
            '0x4D2' => 0x4D2,
            '02333' => 02333,
            '.Inf' => -log(0),
            '-.Inf' => log(0),
            "'686e444'" => '686e444',
            '686e444' => 646e444,
            '123456789123456789123456789123456789' => '123456789123456789123456789123456789',
            '"foo\r\nbar"' => "foo\r\nbar",
            "'foo#bar'" => 'foo#bar',
            "'foo # bar'" => 'foo # bar',
            "'#cfcfcf'" => '#cfcfcf',
            '::form_base.html.twig' => '::form_base.html.twig',

            '2007-10-30' => mktime(0, 0, 0, 10, 30, 2007),
            '2007-10-30T02:59:43Z' => gmmktime(2, 59, 43, 10, 30, 2007),
            '2007-10-30 02:59:43 Z' => gmmktime(2, 59, 43, 10, 30, 2007),
            '1960-10-30 02:59:43 Z' => gmmktime(2, 59, 43, 10, 30, 1960),
            '1730-10-30T02:59:43Z' => gmmktime(2, 59, 43, 10, 30, 1730),

            '"a \\"string\\" with \'quoted strings inside\'"' => 'a "string" with \'quoted strings inside\'',
            "'a \"string\" with ''quoted strings inside'''" => 'a "string" with \'quoted strings inside\'',

            // sequences
            // urls are no key value mapping. see #3609. Valid yaml "key: value" mappings require a space after the colon
            '[foo, http://urls.are/no/mappings, false, null, 12]' => array('foo', 'http://urls.are/no/mappings', false, null, 12),
            '[  foo  ,   bar , false  ,  null     ,  12  ]' => array('foo', 'bar', false, null, 12),
            '[\'foo,bar\', \'foo bar\']' => array('foo,bar', 'foo bar'),

            // mappings
            '{foo:bar,bar:foo,false:false,null:null,integer:12}' => array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12),
            '{ foo  : bar, bar : foo,  false  :   false,  null  :   null,  integer :  12  }' => array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12),
            '{foo: \'bar\', bar: \'foo: bar\'}' => array('foo' => 'bar', 'bar' => 'foo: bar'),
            '{\'foo\': \'bar\', "bar": \'foo: bar\'}' => array('foo' => 'bar', 'bar' => 'foo: bar'),
            '{\'foo\'\'\': \'bar\', "bar\"": \'foo: bar\'}' => array('foo\'' => 'bar', "bar\"" => 'foo: bar'),
            '{\'foo: \': \'bar\', "bar: ": \'foo: bar\'}' => array('foo: ' => 'bar', "bar: " => 'foo: bar'),

            // nested sequences and mappings
            '[foo, [bar, foo]]' => array('foo', array('bar', 'foo')),
            '[foo, {bar: foo}]' => array('foo', array('bar' => 'foo')),
            '{ foo: {bar: foo} }' => array('foo' => array('bar' => 'foo')),
            '{ foo: [bar, foo] }' => array('foo' => array('bar', 'foo')),

            '[  foo, [  bar, foo  ]  ]' => array('foo', array('bar', 'foo')),

            '[{ foo: {bar: foo} }]' => array(array('foo' => array('bar' => 'foo'))),

            '[foo, [bar, [foo, [bar, foo]], foo]]' => array('foo', array('bar', array('foo', array('bar', 'foo')), 'foo')),

            '[foo, {bar: foo, foo: [foo, {bar: foo}]}, [foo, {bar: foo}]]' => array('foo', array('bar' => 'foo', 'foo' => array('foo', array('bar' => 'foo'))), array('foo', array('bar' => 'foo'))),

            '[foo, bar: { foo: bar }]' => array('foo', '1' => array('bar' => array('foo' => 'bar'))),
            '[foo, \'@foo.baz\', { \'%foo%\': \'foo is %foo%\', bar: \'%foo%\' }, true, \'@service_container\']' => array('foo', '@foo.baz', array('%foo%' => 'foo is %foo%', 'bar' => '%foo%',), true, '@service_container',),
        );
    }

    protected function getTestsForDump()
    {
        return array(
            'null' => null,
            'false' => false,
            'true' => true,
            '12' => 12,
            "'quoted string'" => 'quoted string',
            '12.30e+02' => 12.30e+02,
            '1234' => 0x4D2,
            '1243' => 02333,
            '.Inf' => -log(0),
            '-.Inf' => log(0),
            "'686e444'" => '686e444',
            '"foo\r\nbar"' => "foo\r\nbar",
            "'foo#bar'" => 'foo#bar',
            "'foo # bar'" => 'foo # bar',
            "'#cfcfcf'" => '#cfcfcf',

            "'a \"string\" with ''quoted strings inside'''" => 'a "string" with \'quoted strings inside\'',

            "'-dash'" => '-dash',
            "'-'" => '-',

            // sequences
            '[foo, bar, false, null, 12]' => array('foo', 'bar', false, null, 12),
            '[\'foo,bar\', \'foo bar\']' => array('foo,bar', 'foo bar'),

            // mappings
            '{ foo: bar, bar: foo, \'false\': false, \'null\': null, integer: 12 }' => array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12),
            '{ foo: bar, bar: \'foo: bar\' }' => array('foo' => 'bar', 'bar' => 'foo: bar'),

            // nested sequences and mappings
            '[foo, [bar, foo]]' => array('foo', array('bar', 'foo')),

            '[foo, [bar, [foo, [bar, foo]], foo]]' => array('foo', array('bar', array('foo', array('bar', 'foo')), 'foo')),

            '{ foo: { bar: foo } }' => array('foo' => array('bar' => 'foo')),

            '[foo, { bar: foo }]' => array('foo', array('bar' => 'foo')),

            '[foo, { bar: foo, foo: [foo, { bar: foo }] }, [foo, { bar: foo }]]' => array('foo', array('bar' => 'foo', 'foo' => array('foo', array('bar' => 'foo'))), array('foo', array('bar' => 'foo'))),

            '[foo, \'@foo.baz\', { \'%foo%\': \'foo is %foo%\', bar: \'%foo%\' }, true, \'@service_container\']' => array('foo', '@foo.baz', array('%foo%' => 'foo is %foo%', 'bar' => '%foo%',), true, '@service_container',),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Yaml\Tests;

use Symfony\Component\Yaml\Yaml;
use Symfony\Component\Yaml\Parser;
use Symfony\Component\Yaml\Dumper;

class DumperTest extends \PHPUnit_Framework_TestCase
{
    protected $parser;
    protected $dumper;
    protected $path;

    protected $array = array(
        '' => 'bar',
        'foo' => '#bar',
        'foo\'bar' => array(),
        'bar' => array(1, 'foo'),
        'foobar' => array(
            'foo' => 'bar',
            'bar' => array(1, 'foo'),
            'foobar' => array(
                'foo' => 'bar',
                'bar' => array(1, 'foo'),
            ),
        ),
    );

    protected function setUp()
    {
        $this->parser = new Parser();
        $this->dumper = new Dumper();
        $this->path = __DIR__.'/Fixtures';
    }

    protected function tearDown()
    {
        $this->parser = null;
        $this->dumper = null;
        $this->path = null;
        $this->array = null;
    }

    public function testSetIndentation()
    {
        $this->dumper->setIndentation(7);

$expected = <<<EOF
'': bar
foo: '#bar'
'foo''bar': {  }
bar:
       - 1
       - foo
foobar:
       foo: bar
       bar:
              - 1
              - foo
       foobar:
              foo: bar
              bar:
                     - 1
                     - foo

EOF;
        $this->assertEquals($expected, $this->dumper->dump($this->array, 4, 0));
    }

    public function testSpecifications()
    {
        $files = $this->parser->parse(file_get_contents($this->path.'/index.yml'));
        foreach ($files as $file) {
            $yamls = file_get_contents($this->path.'/'.$file.'.yml');

            // split YAMLs documents
            foreach (preg_split('/^---( %YAML\:1\.0)?/m', $yamls) as $yaml) {
                if (!$yaml) {
                    continue;
                }

                $test = $this->parser->parse($yaml);
                if (isset($test['dump_skip']) && $test['dump_skip']) {
                    continue;
                } elseif (isset($test['todo']) && $test['todo']) {
                    // TODO
                } else {
                    $expected = eval('return '.trim($test['php']).';');

                    $this->assertEquals($expected, $this->parser->parse($this->dumper->dump($expected, 10)), $test['test']);
                }
            }
        }
    }

    public function testInlineLevel()
    {
        $expected = <<<EOF
{ '': bar, foo: '#bar', 'foo''bar': {  }, bar: [1, foo], foobar: { foo: bar, bar: [1, foo], foobar: { foo: bar, bar: [1, foo] } } }
EOF;
$this->assertEquals($expected, $this->dumper->dump($this->array, -10), '->dump() takes an inline level argument');
$this->assertEquals($expected, $this->dumper->dump($this->array, 0), '->dump() takes an inline level argument');

$expected = <<<EOF
'': bar
foo: '#bar'
'foo''bar': {  }
bar: [1, foo]
foobar: { foo: bar, bar: [1, foo], foobar: { foo: bar, bar: [1, foo] } }

EOF;
        $this->assertEquals($expected, $this->dumper->dump($this->array, 1), '->dump() takes an inline level argument');

        $expected = <<<EOF
'': bar
foo: '#bar'
'foo''bar': {  }
bar:
    - 1
    - foo
foobar:
    foo: bar
    bar: [1, foo]
    foobar: { foo: bar, bar: [1, foo] }

EOF;
        $this->assertEquals($expected, $this->dumper->dump($this->array, 2), '->dump() takes an inline level argument');

        $expected = <<<EOF
'': bar
foo: '#bar'
'foo''bar': {  }
bar:
    - 1
    - foo
foobar:
    foo: bar
    bar:
        - 1
        - foo
    foobar:
        foo: bar
        bar: [1, foo]

EOF;
        $this->assertEquals($expected, $this->dumper->dump($this->array, 3), '->dump() takes an inline level argument');

        $expected = <<<EOF
'': bar
foo: '#bar'
'foo''bar': {  }
bar:
    - 1
    - foo
foobar:
    foo: bar
    bar:
        - 1
        - foo
    foobar:
        foo: bar
        bar:
            - 1
            - foo

EOF;
        $this->assertEquals($expected, $this->dumper->dump($this->array, 4), '->dump() takes an inline level argument');
        $this->assertEquals($expected, $this->dumper->dump($this->array, 10), '->dump() takes an inline level argument');
    }

    public function testObjectSupportEnabled()
    {
        $dump = $this->dumper->dump(array('foo' => new A(), 'bar' => 1), 0, 0, false, true);

        $this->assertEquals('{ foo: !!php/object:O:30:"Symfony\Component\Yaml\Tests\A":1:{s:1:"a";s:3:"foo";}, bar: 1 }', $dump, '->dump() is able to dump objects');
    }

    public function testObjectSupportDisabledButNoExceptions()
    {
        $dump = $this->dumper->dump(array('foo' => new A(), 'bar' => 1));

        $this->assertEquals('{ foo: null, bar: 1 }', $dump, '->dump() does not dump objects when disabled');
    }

    /**
     * @expectedException \Symfony\Component\Yaml\Exception\DumpException
     */
    public function testObjectSupportDisabledWithExceptions()
    {
        $this->dumper->dump(array('foo' => new A(), 'bar' => 1), 0, 0, true, false);
    }
}

class A
{
    public $a = 'foo';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\EventDispatcher;

/**
 * An EventSubscriber knows himself what events he is interested in.
 * If an EventSubscriber is added to an EventDispatcherInterface, the manager invokes
 * {@link getSubscribedEvents} and registers the subscriber as a listener for all
 * returned events.
 *
 * @author  Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author  Jonathan Wage <jonwage@gmail.com>
 * @author  Roman Borschel <roman@code-factory.org>
 * @author  Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
interface EventSubscriberInterface
{
    /**
     * Returns an array of event names this subscriber wants to listen to.
     *
     * The array keys are event names and the value can be:
     *
     *  * The method name to call (priority defaults to 0)
     *  * An array composed of the method name to call and the priority
     *  * An array of arrays composed of the method names to call and respective
     *    priorities, or 0 if unset
     *
     * For instance:
     *
     *  * array('eventName' => 'methodName')
     *  * array('eventName' => array('methodName', $priority))
     *  * array('eventName' => array(array('methodName1', $priority), array('methodName2'))
     *
     * @return array The event names to listen to
     *
     * @api
     */
    public static function getSubscribedEvents();
}
{
    "name": "symfony/event-dispatcher",
    "type": "library",
    "description": "Symfony EventDispatcher Component",
    "keywords": [],
    "homepage": "http://symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "http://symfony.com/contributors"
        }
    ],
    "require": {
        "php": ">=5.3.3"
    },
    "require-dev": {
        "symfony/dependency-injection": "~2.0"
    },
    "suggest": {
        "symfony/dependency-injection": "",
        "symfony/http-kernel": ""
    },
    "autoload": {
        "psr-0": { "Symfony\\Component\\EventDispatcher\\": "" }
    },
    "target-dir": "Symfony/Component/EventDispatcher",
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-master": "2.4-dev"
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\EventDispatcher\Debug;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface TraceableEventDispatcherInterface
{
    /**
     * Gets the called listeners.
     *
     * @return array An array of called listeners
     */
    public function getCalledListeners();

    /**
     * Gets the not called listeners.
     *
     * @return array An array of not called listeners
     */
    public function getNotCalledListeners();
}
Copyright (c) 2004-2013 Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\EventDispatcher;

/**
 * The EventDispatcherInterface is the central point of Symfony's event listener system.
 * Listeners are registered on the manager and events are dispatched through the
 * manager.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
interface EventDispatcherInterface
{
    /**
     * Dispatches an event to all registered listeners.
     *
     * @param string $eventName The name of the event to dispatch. The name of
     *                          the event is the name of the method that is
     *                          invoked on listeners.
     * @param Event $event The event to pass to the event handlers/listeners.
     *                          If not supplied, an empty Event instance is created.
     *
     * @return Event
     *
     * @api
     */
    public function dispatch($eventName, Event $event = null);

    /**
     * Adds an event listener that listens on the specified events.
     *
     * @param string   $eventName The event to listen on
     * @param callable $listener  The listener
     * @param integer  $priority  The higher this value, the earlier an event
     *                            listener will be triggered in the chain (defaults to 0)
     *
     * @api
     */
    public function addListener($eventName, $listener, $priority = 0);

    /**
     * Adds an event subscriber.
     *
     * The subscriber is asked for all the events he is
     * interested in and added as a listener for these events.
     *
     * @param EventSubscriberInterface $subscriber The subscriber.
     *
     * @api
     */
    public function addSubscriber(EventSubscriberInterface $subscriber);

    /**
     * Removes an event listener from the specified events.
     *
     * @param string|array $eventName The event(s) to remove a listener from
     * @param callable     $listener  The listener to remove
     */
    public function removeListener($eventName, $listener);

    /**
     * Removes an event subscriber.
     *
     * @param EventSubscriberInterface $subscriber The subscriber
     */
    public function removeSubscriber(EventSubscriberInterface $subscriber);

    /**
     * Gets the listeners of a specific event or all listeners.
     *
     * @param string $eventName The name of the event
     *
     * @return array The event listeners for the specified event, or all event listeners by event name
     */
    public function getListeners($eventName = null);

    /**
     * Checks whether an event has any registered listeners.
     *
     * @param string $eventName The name of the event
     *
     * @return Boolean true if the specified event has any listeners, false otherwise
     */
    public function hasListeners($eventName = null);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\EventDispatcher;

/**
 * A read-only proxy for an event dispatcher.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ImmutableEventDispatcher implements EventDispatcherInterface
{
    /**
     * The proxied dispatcher.
     * @var EventDispatcherInterface
     */
    private $dispatcher;

    /**
     * Creates an unmodifiable proxy for an event dispatcher.
     *
     * @param EventDispatcherInterface $dispatcher The proxied event dispatcher.
     */
    public function __construct(EventDispatcherInterface $dispatcher)
    {
        $this->dispatcher = $dispatcher;
    }

    /**
     * {@inheritdoc}
     */
    public function dispatch($eventName, Event $event = null)
    {
        return $this->dispatcher->dispatch($eventName, $event);
    }

    /**
     * {@inheritdoc}
     */
    public function addListener($eventName, $listener, $priority = 0)
    {
        throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.');
    }

    /**
     * {@inheritdoc}
     */
    public function addSubscriber(EventSubscriberInterface $subscriber)
    {
        throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.');
    }

    /**
     * {@inheritdoc}
     */
    public function removeListener($eventName, $listener)
    {
        throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.');
    }

    /**
     * {@inheritdoc}
     */
    public function removeSubscriber(EventSubscriberInterface $subscriber)
    {
        throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.');
    }

    /**
     * {@inheritdoc}
     */
    public function getListeners($eventName = null)
    {
        return $this->dispatcher->getListeners($eventName);
    }

    /**
     * {@inheritdoc}
     */
    public function hasListeners($eventName = null)
    {
        return $this->dispatcher->hasListeners($eventName);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\EventDispatcher;

/**
 * The EventDispatcherInterface is the central point of Symfony's event listener system.
 *
 * Listeners are registered on the manager and events are dispatched through the
 * manager.
 *
 * @author  Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author  Jonathan Wage <jonwage@gmail.com>
 * @author  Roman Borschel <roman@code-factory.org>
 * @author  Bernhard Schussek <bschussek@gmail.com>
 * @author  Fabien Potencier <fabien@symfony.com>
 * @author  Jordi Boggiano <j.boggiano@seld.be>
 * @author  Jordan Alliot <jordan.alliot@gmail.com>
 *
 * @api
 */
class EventDispatcher implements EventDispatcherInterface
{
    private $listeners = array();
    private $sorted = array();

    /**
     * @see EventDispatcherInterface::dispatch
     *
     * @api
     */
    public function dispatch($eventName, Event $event = null)
    {
        if (null === $event) {
            $event = new Event();
        }

        $event->setDispatcher($this);
        $event->setName($eventName);

        if (!isset($this->listeners[$eventName])) {
            return $event;
        }

        $this->doDispatch($this->getListeners($eventName), $eventName, $event);

        return $event;
    }

    /**
     * @see EventDispatcherInterface::getListeners
     */
    public function getListeners($eventName = null)
    {
        if (null !== $eventName) {
            if (!isset($this->sorted[$eventName])) {
                $this->sortListeners($eventName);
            }

            return $this->sorted[$eventName];
        }

        foreach (array_keys($this->listeners) as $eventName) {
            if (!isset($this->sorted[$eventName])) {
                $this->sortListeners($eventName);
            }
        }

        return $this->sorted;
    }

    /**
     * @see EventDispatcherInterface::hasListeners
     */
    public function hasListeners($eventName = null)
    {
        return (Boolean) count($this->getListeners($eventName));
    }

    /**
     * @see EventDispatcherInterface::addListener
     *
     * @api
     */
    public function addListener($eventName, $listener, $priority = 0)
    {
        $this->listeners[$eventName][$priority][] = $listener;
        unset($this->sorted[$eventName]);
    }

    /**
     * @see EventDispatcherInterface::removeListener
     */
    public function removeListener($eventName, $listener)
    {
        if (!isset($this->listeners[$eventName])) {
            return;
        }

        foreach ($this->listeners[$eventName] as $priority => $listeners) {
            if (false !== ($key = array_search($listener, $listeners, true))) {
                unset($this->listeners[$eventName][$priority][$key], $this->sorted[$eventName]);
            }
        }
    }

    /**
     * @see EventDispatcherInterface::addSubscriber
     *
     * @api
     */
    public function addSubscriber(EventSubscriberInterface $subscriber)
    {
        foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
            if (is_string($params)) {
                $this->addListener($eventName, array($subscriber, $params));
            } elseif (is_string($params[0])) {
                $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0);
            } else {
                foreach ($params as $listener) {
                    $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0);
                }
            }
        }
    }

    /**
     * @see EventDispatcherInterface::removeSubscriber
     */
    public function removeSubscriber(EventSubscriberInterface $subscriber)
    {
        foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
            if (is_array($params) && is_array($params[0])) {
                foreach ($params as $listener) {
                    $this->removeListener($eventName, array($subscriber, $listener[0]));
                }
            } else {
                $this->removeListener($eventName, array($subscriber, is_string($params) ? $params : $params[0]));
            }
        }
    }

    /**
     * Triggers the listeners of an event.
     *
     * This method can be overridden to add functionality that is executed
     * for each listener.
     *
     * @param callable[] $listeners The event listeners.
     * @param string     $eventName The name of the event to dispatch.
     * @param Event      $event     The event object to pass to the event handlers/listeners.
     */
    protected function doDispatch($listeners, $eventName, Event $event)
    {
        foreach ($listeners as $listener) {
            call_user_func($listener, $event, $eventName, $this);
            if ($event->isPropagationStopped()) {
                break;
            }
        }
    }

    /**
     * Sorts the internal list of listeners for the given event by priority.
     *
     * @param string $eventName The name of the event.
     */
    private function sortListeners($eventName)
    {
        $this->sorted[$eventName] = array();

        if (isset($this->listeners[$eventName])) {
            krsort($this->listeners[$eventName]);
            $this->sorted[$eventName] = call_user_func_array('array_merge', $this->listeners[$eventName]);
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony EventDispatcher Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Resources</directory>
                <directory>./Tests</directory>
                <directory>./vendor</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\EventDispatcher;

/**
 * Event is the base class for classes containing event data.
 *
 * This class contains no event data. It is used by events that do not pass
 * state information to an event handler when an event is raised.
 *
 * You can call the method stopPropagation() to abort the execution of
 * further listeners in your event listener.
 *
 * @author  Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author  Jonathan Wage <jonwage@gmail.com>
 * @author  Roman Borschel <roman@code-factory.org>
 * @author  Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Event
{
    /**
     * @var Boolean Whether no further event listeners should be triggered
     */
    private $propagationStopped = false;

    /**
     * @var EventDispatcher Dispatcher that dispatched this event
     */
    private $dispatcher;

    /**
     * @var string This event's name
     */
    private $name;

    /**
     * Returns whether further event listeners should be triggered.
     *
     * @see Event::stopPropagation
     * @return Boolean Whether propagation was already stopped for this event.
     *
     * @api
     */
    public function isPropagationStopped()
    {
        return $this->propagationStopped;
    }

    /**
     * Stops the propagation of the event to further event listeners.
     *
     * If multiple event listeners are connected to the same event, no
     * further event listener will be triggered once any trigger calls
     * stopPropagation().
     *
     * @api
     */
    public function stopPropagation()
    {
        $this->propagationStopped = true;
    }

    /**
     * Stores the EventDispatcher that dispatches this Event
     *
     * @param EventDispatcherInterface $dispatcher
     *
     * @deprecated Deprecated in 2.4, to be removed in 3.0. The event dispatcher is passed to the listener call.
     *
     * @api
     */
    public function setDispatcher(EventDispatcherInterface $dispatcher)
    {
        $this->dispatcher = $dispatcher;
    }

    /**
     * Returns the EventDispatcher that dispatches this Event
     *
     * @return EventDispatcherInterface
     *
     * @deprecated Deprecated in 2.4, to be removed in 3.0. The event dispatcher is passed to the listener call.
     *
     * @api
     */
    public function getDispatcher()
    {
        return $this->dispatcher;
    }

    /**
     * Gets the event's name.
     *
     * @return string
     *
     * @deprecated Deprecated in 2.4, to be removed in 3.0. The event name is passed to the listener call.
     *
     * @api
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Sets the event's name property.
     *
     * @param string $name The event name.
     *
     * @deprecated Deprecated in 2.4, to be removed in 3.0. The event name is passed to the listener call.
     *
     * @api
     */
    public function setName($name)
    {
        $this->name = $name;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\EventDispatcher;

use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Lazily loads listeners and subscribers from the dependency injection
 * container
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Jordan Alliot <jordan.alliot@gmail.com>
 */
class ContainerAwareEventDispatcher extends EventDispatcher
{
    /**
     * The container from where services are loaded
     * @var ContainerInterface
     */
    private $container;

    /**
     * The service IDs of the event listeners and subscribers
     * @var array
     */
    private $listenerIds = array();

    /**
     * The services registered as listeners
     * @var array
     */
    private $listeners = array();

    /**
     * Constructor.
     *
     * @param ContainerInterface $container A ContainerInterface instance
     */
    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    /**
     * Adds a service as event listener
     *
     * @param string $eventName Event for which the listener is added
     * @param array  $callback  The service ID of the listener service & the method
     *                            name that has to be called
     * @param integer $priority The higher this value, the earlier an event listener
     *                            will be triggered in the chain.
     *                            Defaults to 0.
     *
     * @throws \InvalidArgumentException
     */
    public function addListenerService($eventName, $callback, $priority = 0)
    {
        if (!is_array($callback) || 2 !== count($callback)) {
            throw new \InvalidArgumentException('Expected an array("service", "method") argument');
        }

        $this->listenerIds[$eventName][] = array($callback[0], $callback[1], $priority);
    }

    public function removeListener($eventName, $listener)
    {
        $this->lazyLoad($eventName);

        if (isset($this->listeners[$eventName])) {
            foreach ($this->listeners[$eventName] as $key => $l) {
                foreach ($this->listenerIds[$eventName] as $i => $args) {
                    list($serviceId, $method, $priority) = $args;
                    if ($key === $serviceId.'.'.$method) {
                        if ($listener === array($l, $method)) {
                            unset($this->listeners[$eventName][$key]);
                            if (empty($this->listeners[$eventName])) {
                                unset($this->listeners[$eventName]);
                            }
                            unset($this->listenerIds[$eventName][$i]);
                            if (empty($this->listenerIds[$eventName])) {
                                unset($this->listenerIds[$eventName]);
                            }
                        }
                    }
                }
            }
        }

        parent::removeListener($eventName, $listener);
    }

    /**
     * @see EventDispatcherInterface::hasListeners
     */
    public function hasListeners($eventName = null)
    {
        if (null === $eventName) {
            return (Boolean) count($this->listenerIds) || (Boolean) count($this->listeners);
        }

        if (isset($this->listenerIds[$eventName])) {
            return true;
        }

        return parent::hasListeners($eventName);
    }

    /**
     * @see EventDispatcherInterface::getListeners
     */
    public function getListeners($eventName = null)
    {
        if (null === $eventName) {
            foreach (array_keys($this->listenerIds) as $serviceEventName) {
                $this->lazyLoad($serviceEventName);
            }
        } else {
            $this->lazyLoad($eventName);
        }

        return parent::getListeners($eventName);
    }

    /**
     * Adds a service as event subscriber
     *
     * @param string $serviceId The service ID of the subscriber service
     * @param string $class     The service's class name (which must implement EventSubscriberInterface)
     */
    public function addSubscriberService($serviceId, $class)
    {
        foreach ($class::getSubscribedEvents() as $eventName => $params) {
            if (is_string($params)) {
                $this->listenerIds[$eventName][] = array($serviceId, $params, 0);
            } elseif (is_string($params[0])) {
                $this->listenerIds[$eventName][] = array($serviceId, $params[0], isset($params[1]) ? $params[1] : 0);
            } else {
                foreach ($params as $listener) {
                    $this->listenerIds[$eventName][] = array($serviceId, $listener[0], isset($listener[1]) ? $listener[1] : 0);
                }
            }
        }
    }

    /**
     * {@inheritDoc}
     *
     * Lazily loads listeners for this event from the dependency injection
     * container.
     *
     * @throws \InvalidArgumentException if the service is not defined
     */
    public function dispatch($eventName, Event $event = null)
    {
        $this->lazyLoad($eventName);

        return parent::dispatch($eventName, $event);
    }

    public function getContainer()
    {
        return $this->container;
    }

    /**
     * Lazily loads listeners for this event from the dependency injection
     * container.
     *
     * @param string $eventName The name of the event to dispatch. The name of
     *                          the event is the name of the method that is
     *                          invoked on listeners.
     */
    protected function lazyLoad($eventName)
    {
        if (isset($this->listenerIds[$eventName])) {
            foreach ($this->listenerIds[$eventName] as $args) {
                list($serviceId, $method, $priority) = $args;
                $listener = $this->container->get($serviceId);

                $key = $serviceId.'.'.$method;
                if (!isset($this->listeners[$eventName][$key])) {
                    $this->addListener($eventName, array($listener, $method), $priority);
                } elseif ($listener !== $this->listeners[$eventName][$key]) {
                    parent::removeListener($eventName, array($this->listeners[$eventName][$key], $method));
                    $this->addListener($eventName, array($listener, $method), $priority);
                }

                $this->listeners[$eventName][$key] = $listener;
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\EventDispatcher;

/**
 * Event encapsulation class.
 *
 * Encapsulates events thus decoupling the observer from the subject they encapsulate.
 *
 * @author Drak <drak@zikula.org>
 */
class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate
{
    /**
     * Event subject.
     *
     * @var mixed usually object or callable
     */
    protected $subject;

    /**
     * Array of arguments.
     *
     * @var array
     */
    protected $arguments;

    /**
     * Encapsulate an event with $subject and $args.
     *
     * @param mixed $subject   The subject of the event, usually an object.
     * @param array $arguments Arguments to store in the event.
     */
    public function __construct($subject = null, array $arguments = array())
    {
        $this->subject = $subject;
        $this->arguments = $arguments;
    }

    /**
     * Getter for subject property.
     *
     * @return mixed $subject The observer subject.
     */
    public function getSubject()
    {
        return $this->subject;
    }

    /**
     * Get argument by key.
     *
     * @param string $key Key.
     *
     * @throws \InvalidArgumentException If key is not found.
     *
     * @return mixed Contents of array key.
     */
    public function getArgument($key)
    {
        if ($this->hasArgument($key)) {
            return $this->arguments[$key];
        }

        throw new \InvalidArgumentException(sprintf('%s not found in %s', $key, $this->getName()));
    }

    /**
     * Add argument to event.
     *
     * @param string $key   Argument name.
     * @param mixed  $value Value.
     *
     * @return GenericEvent
     */
    public function setArgument($key, $value)
    {
        $this->arguments[$key] = $value;

        return $this;
    }

    /**
     * Getter for all arguments.
     *
     * @return array
     */
    public function getArguments()
    {
        return $this->arguments;
    }

    /**
     * Set args property.
     *
     * @param array $args Arguments.
     *
     * @return GenericEvent
     */
    public function setArguments(array $args = array())
    {
        $this->arguments = $args;

        return $this;
    }

    /**
     * Has argument.
     *
     * @param string $key Key of arguments array.
     *
     * @return boolean
     */
    public function hasArgument($key)
    {
        return array_key_exists($key, $this->arguments);
    }

    /**
     * ArrayAccess for argument getter.
     *
     * @param string $key Array key.
     *
     * @throws \InvalidArgumentException If key does not exist in $this->args.
     *
     * @return mixed
     */
    public function offsetGet($key)
    {
        return $this->getArgument($key);
    }

    /**
     * ArrayAccess for argument setter.
     *
     * @param string $key   Array key to set.
     * @param mixed  $value Value.
     */
    public function offsetSet($key, $value)
    {
        $this->setArgument($key, $value);
    }

    /**
     * ArrayAccess for unset argument.
     *
     * @param string $key Array key.
     */
    public function offsetUnset($key)
    {
        if ($this->hasArgument($key)) {
            unset($this->arguments[$key]);
        }
    }

    /**
     * ArrayAccess has argument.
     *
     * @param string $key Array key.
     *
     * @return boolean
     */
    public function offsetExists($key)
    {
        return $this->hasArgument($key);
    }

    /**
     * IteratorAggregate for iterating over the object like an array
     *
     * @return \ArrayIterator
     */
    public function getIterator()
    {
        return new \ArrayIterator($this->arguments);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\EventDispatcher\Tests;

use Symfony\Component\EventDispatcher\GenericEvent;

/**
 * Test class for Event.
 */
class GenericEventTest extends \PHPUnit_Framework_TestCase
{

    /**
     * @var GenericEvent
     */
    private $event;

    private $subject;

    /**
     * Prepares the environment before running a test.
     */
    protected function setUp()
    {
        parent::setUp();

        $this->subject = new \stdClass();
        $this->event = new GenericEvent($this->subject, array('name' => 'Event'), 'foo');
    }

    /**
     * Cleans up the environment after running a test.
     */
    protected function tearDown()
    {
        $this->subject = null;
        $this->event = null;

        parent::tearDown();
    }

    public function testConstruct()
    {
        $this->assertEquals($this->event, new GenericEvent($this->subject, array('name' => 'Event')));
    }

    /**
     * Tests Event->getArgs()
     */
    public function testGetArguments()
    {
        // test getting all
        $this->assertSame(array('name' => 'Event'), $this->event->getArguments());
    }

    public function testSetArguments()
    {
        $result = $this->event->setArguments(array('foo' => 'bar'));
        $this->assertAttributeSame(array('foo' => 'bar'), 'arguments', $this->event);
        $this->assertSame($this->event, $result);
    }

    public function testSetArgument()
    {
        $result = $this->event->setArgument('foo2', 'bar2');
        $this->assertAttributeSame(array('name' => 'Event', 'foo2' => 'bar2'), 'arguments', $this->event);
        $this->assertEquals($this->event, $result);
    }

    public function testGetArgument()
    {
        // test getting key
        $this->assertEquals('Event', $this->event->getArgument('name'));
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testGetArgException()
    {
        $this->event->getArgument('nameNotExist');
    }

    public function testOffsetGet()
    {
        // test getting key
        $this->assertEquals('Event', $this->event['name']);

        // test getting invalid arg
        $this->setExpectedException('InvalidArgumentException');
        $this->assertFalse($this->event['nameNotExist']);
    }

    public function testOffsetSet()
    {
        $this->event['foo2'] = 'bar2';
        $this->assertAttributeSame(array('name' => 'Event', 'foo2' => 'bar2'), 'arguments', $this->event);
    }

    public function testOffsetUnset()
    {
        unset($this->event['name']);
        $this->assertAttributeSame(array(), 'arguments', $this->event);
    }

    public function testOffsetIsset()
    {
        $this->assertTrue(isset($this->event['name']));
        $this->assertFalse(isset($this->event['nameNotExist']));
    }

    public function testHasArgument()
    {
        $this->assertTrue($this->event->hasArgument('name'));
        $this->assertFalse($this->event->hasArgument('nameNotExist'));
    }

    public function testGetSubject()
    {
        $this->assertSame($this->subject, $this->event->getSubject());
    }

    public function testHasIterator()
    {
        $data = array();
        foreach ($this->event as $key => $value) {
            $data[$key] = $value;
        }
        $this->assertEquals(array('name' => 'Event'), $data);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\EventDispatcher\Tests;

use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcher;

/**
 * Test class for Event.
 */
class EventTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var \Symfony\Component\EventDispatcher\Event
     */
    protected $event;

    /**
     * @var \Symfony\Component\EventDispatcher\EventDispatcher
     */
    protected $dispatcher;

    /**
     * Sets up the fixture, for example, opens a network connection.
     * This method is called before a test is executed.
     */
    protected function setUp()
    {
        $this->event = new Event();
        $this->dispatcher = new EventDispatcher();
    }

    /**
     * Tears down the fixture, for example, closes a network connection.
     * This method is called after a test is executed.
     */
    protected function tearDown()
    {
        $this->event = null;
        $this->dispatcher = null;
    }

    public function testIsPropagationStopped()
    {
        $this->assertFalse($this->event->isPropagationStopped());
    }

    public function testStopPropagationAndIsPropagationStopped()
    {
        $this->event->stopPropagation();
        $this->assertTrue($this->event->isPropagationStopped());
    }

    public function testSetDispatcher()
    {
        $this->event->setDispatcher($this->dispatcher);
        $this->assertSame($this->dispatcher, $this->event->getDispatcher());
    }

    public function testGetDispatcher()
    {
        $this->assertNull($this->event->getDispatcher());
    }

    public function testGetName()
    {
        $this->assertNull($this->event->getName());
    }

    public function testSetName()
    {
        $this->event->setName('foo');
        $this->assertEquals('foo', $this->event->getName());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\EventDispatcher\Tests;

use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\ImmutableEventDispatcher;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ImmutableEventDispatcherTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $innerDispatcher;

    /**
     * @var ImmutableEventDispatcher
     */
    private $dispatcher;

    protected function setUp()
    {
        $this->innerDispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
        $this->dispatcher = new ImmutableEventDispatcher($this->innerDispatcher);
    }

    public function testDispatchDelegates()
    {
        $event = new Event();

        $this->innerDispatcher->expects($this->once())
            ->method('dispatch')
            ->with('event', $event)
            ->will($this->returnValue('result'));

        $this->assertSame('result', $this->dispatcher->dispatch('event', $event));
    }

    public function testGetListenersDelegates()
    {
        $this->innerDispatcher->expects($this->once())
            ->method('getListeners')
            ->with('event')
            ->will($this->returnValue('result'));

        $this->assertSame('result', $this->dispatcher->getListeners('event'));
    }

    public function testHasListenersDelegates()
    {
        $this->innerDispatcher->expects($this->once())
            ->method('hasListeners')
            ->with('event')
            ->will($this->returnValue('result'));

        $this->assertSame('result', $this->dispatcher->hasListeners('event'));
    }

    /**
     * @expectedException \BadMethodCallException
     */
    public function testAddListenerDisallowed()
    {
        $this->dispatcher->addListener('event', function () { return 'foo'; });
    }

    /**
     * @expectedException \BadMethodCallException
     */
    public function testAddSubscriberDisallowed()
    {
        $subscriber = $this->getMock('Symfony\Component\EventDispatcher\EventSubscriberInterface');

        $this->dispatcher->addSubscriber($subscriber);
    }

    /**
     * @expectedException \BadMethodCallException
     */
    public function testRemoveListenerDisallowed()
    {
        $this->dispatcher->removeListener('event', function () { return 'foo'; });
    }

    /**
     * @expectedException \BadMethodCallException
     */
    public function testRemoveSubscriberDisallowed()
    {
        $subscriber = $this->getMock('Symfony\Component\EventDispatcher\EventSubscriberInterface');

        $this->dispatcher->removeSubscriber($subscriber);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\EventDispatcher\Tests;

use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Scope;
use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class ContainerAwareEventDispatcherTest extends \PHPUnit_Framework_TestCase
{
    public function testAddAListenerService()
    {
        $event = new Event();

        $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service');

        $service
            ->expects($this->once())
            ->method('onEvent')
            ->with($event)
        ;

        $container = new Container();
        $container->set('service.listener', $service);

        $dispatcher = new ContainerAwareEventDispatcher($container);
        $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'));

        $dispatcher->dispatch('onEvent', $event);
    }

    public function testAddASubscriberService()
    {
        $event = new Event();

        $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\SubscriberService');

        $service
            ->expects($this->once())
            ->method('onEvent')
            ->with($event)
        ;

        $container = new Container();
        $container->set('service.subscriber', $service);

        $dispatcher = new ContainerAwareEventDispatcher($container);
        $dispatcher->addSubscriberService('service.subscriber', 'Symfony\Component\EventDispatcher\Tests\SubscriberService');

        $dispatcher->dispatch('onEvent', $event);
    }

    public function testPreventDuplicateListenerService()
    {
        $event = new Event();

        $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service');

        $service
            ->expects($this->once())
            ->method('onEvent')
            ->with($event)
        ;

        $container = new Container();
        $container->set('service.listener', $service);

        $dispatcher = new ContainerAwareEventDispatcher($container);
        $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'), 5);
        $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'), 10);

        $dispatcher->dispatch('onEvent', $event);
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testTriggerAListenerServiceOutOfScope()
    {
        $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service');

        $scope = new Scope('scope');
        $container = new Container();
        $container->addScope($scope);
        $container->enterScope('scope');

        $container->set('service.listener', $service, 'scope');

        $dispatcher = new ContainerAwareEventDispatcher($container);
        $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'));

        $container->leaveScope('scope');
        $dispatcher->dispatch('onEvent');
    }

    public function testReEnteringAScope()
    {
        $event = new Event();

        $service1 = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service');

        $service1
            ->expects($this->exactly(2))
            ->method('onEvent')
            ->with($event)
        ;

        $scope = new Scope('scope');
        $container = new Container();
        $container->addScope($scope);
        $container->enterScope('scope');

        $container->set('service.listener', $service1, 'scope');

        $dispatcher = new ContainerAwareEventDispatcher($container);
        $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'));
        $dispatcher->dispatch('onEvent', $event);

        $service2 = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service');

        $service2
            ->expects($this->once())
            ->method('onEvent')
            ->with($event)
        ;

        $container->enterScope('scope');
        $container->set('service.listener', $service2, 'scope');

        $dispatcher->dispatch('onEvent', $event);

        $container->leaveScope('scope');

        $dispatcher->dispatch('onEvent');
    }

    public function testHasListenersOnLazyLoad()
    {
        $event = new Event();

        $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service');

        $container = new Container();
        $container->set('service.listener', $service);

        $dispatcher = new ContainerAwareEventDispatcher($container);
        $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'));

        $event->setDispatcher($dispatcher);
        $event->setName('onEvent');

        $service
            ->expects($this->once())
            ->method('onEvent')
            ->with($event)
        ;

        $this->assertTrue($dispatcher->hasListeners());

        if ($dispatcher->hasListeners('onEvent')) {
            $dispatcher->dispatch('onEvent');
        }
    }

    public function testGetListenersOnLazyLoad()
    {
        $event = new Event();

        $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service');

        $container = new Container();
        $container->set('service.listener', $service);

        $dispatcher = new ContainerAwareEventDispatcher($container);
        $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'));

        $listeners = $dispatcher->getListeners();

        $this->assertTrue(isset($listeners['onEvent']));

        $this->assertCount(1, $dispatcher->getListeners('onEvent'));
    }

    public function testRemoveAfterDispatch()
    {
        $event = new Event();

        $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service');

        $container = new Container();
        $container->set('service.listener', $service);

        $dispatcher = new ContainerAwareEventDispatcher($container);
        $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'));

        $dispatcher->dispatch('onEvent', new Event());
        $dispatcher->removeListener('onEvent', array($container->get('service.listener'), 'onEvent'));
        $this->assertFalse($dispatcher->hasListeners('onEvent'));
    }

    public function testRemoveBeforeDispatch()
    {
        $event = new Event();

        $service = $this->getMock('Symfony\Component\EventDispatcher\Tests\Service');

        $container = new Container();
        $container->set('service.listener', $service);

        $dispatcher = new ContainerAwareEventDispatcher($container);
        $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'));

        $dispatcher->removeListener('onEvent', array($container->get('service.listener'), 'onEvent'));
        $this->assertFalse($dispatcher->hasListeners('onEvent'));
    }
}

class Service
{
    public function onEvent(Event $e)
    {
    }
}

class SubscriberService implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return array(
            'onEvent' => 'onEvent',
            'onEvent' => array('onEvent', 10),
            'onEvent' => array('onEvent'),
        );
    }

    public function onEvent(Event $e)
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\EventDispatcher\Tests;

use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class EventDispatcherTest extends \PHPUnit_Framework_TestCase
{
    /* Some pseudo events */
    const preFoo = 'pre.foo';
    const postFoo = 'post.foo';
    const preBar = 'pre.bar';
    const postBar = 'post.bar';

    /**
     * @var EventDispatcher
     */
    private $dispatcher;

    private $listener;

    protected function setUp()
    {
        $this->dispatcher = new EventDispatcher();
        $this->listener = new TestEventListener();
    }

    protected function tearDown()
    {
        $this->dispatcher = null;
        $this->listener = null;
    }

    public function testInitialState()
    {
        $this->assertEquals(array(), $this->dispatcher->getListeners());
        $this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
        $this->assertFalse($this->dispatcher->hasListeners(self::postFoo));
    }

    public function testAddListener()
    {
        $this->dispatcher->addListener('pre.foo', array($this->listener, 'preFoo'));
        $this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo'));
        $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
        $this->assertTrue($this->dispatcher->hasListeners(self::postFoo));
        $this->assertCount(1, $this->dispatcher->getListeners(self::preFoo));
        $this->assertCount(1, $this->dispatcher->getListeners(self::postFoo));
        $this->assertCount(2, $this->dispatcher->getListeners());
    }

    public function testGetListenersSortsByPriority()
    {
        $listener1 = new TestEventListener();
        $listener2 = new TestEventListener();
        $listener3 = new TestEventListener();
        $listener1->name = '1';
        $listener2->name = '2';
        $listener3->name = '3';

        $this->dispatcher->addListener('pre.foo', array($listener1, 'preFoo'), -10);
        $this->dispatcher->addListener('pre.foo', array($listener2, 'preFoo'), 10);
        $this->dispatcher->addListener('pre.foo', array($listener3, 'preFoo'));

        $expected = array(
            array($listener2, 'preFoo'),
            array($listener3, 'preFoo'),
            array($listener1, 'preFoo'),
        );

        $this->assertSame($expected, $this->dispatcher->getListeners('pre.foo'));
    }

    public function testGetAllListenersSortsByPriority()
    {
        $listener1 = new TestEventListener();
        $listener2 = new TestEventListener();
        $listener3 = new TestEventListener();
        $listener4 = new TestEventListener();
        $listener5 = new TestEventListener();
        $listener6 = new TestEventListener();

        $this->dispatcher->addListener('pre.foo', $listener1, -10);
        $this->dispatcher->addListener('pre.foo', $listener2);
        $this->dispatcher->addListener('pre.foo', $listener3, 10);
        $this->dispatcher->addListener('post.foo', $listener4, -10);
        $this->dispatcher->addListener('post.foo', $listener5);
        $this->dispatcher->addListener('post.foo', $listener6, 10);

        $expected = array(
            'pre.foo'  => array($listener3, $listener2, $listener1),
            'post.foo' => array($listener6, $listener5, $listener4),
        );

        $this->assertSame($expected, $this->dispatcher->getListeners());
    }

    public function testDispatch()
    {
        $this->dispatcher->addListener('pre.foo', array($this->listener, 'preFoo'));
        $this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo'));
        $this->dispatcher->dispatch(self::preFoo);
        $this->assertTrue($this->listener->preFooInvoked);
        $this->assertFalse($this->listener->postFooInvoked);
        $this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch('noevent'));
        $this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch(self::preFoo));
        $event = new Event();
        $return = $this->dispatcher->dispatch(self::preFoo, $event);
        $this->assertEquals('pre.foo', $event->getName());
        $this->assertSame($event, $return);
    }

    public function testDispatchForClosure()
    {
        $invoked = 0;
        $listener = function () use (&$invoked) {
            $invoked++;
        };
        $this->dispatcher->addListener('pre.foo', $listener);
        $this->dispatcher->addListener('post.foo', $listener);
        $this->dispatcher->dispatch(self::preFoo);
        $this->assertEquals(1, $invoked);
    }

    public function testStopEventPropagation()
    {
        $otherListener = new TestEventListener();

        // postFoo() stops the propagation, so only one listener should
        // be executed
        // Manually set priority to enforce $this->listener to be called first
        $this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo'), 10);
        $this->dispatcher->addListener('post.foo', array($otherListener, 'preFoo'));
        $this->dispatcher->dispatch(self::postFoo);
        $this->assertTrue($this->listener->postFooInvoked);
        $this->assertFalse($otherListener->postFooInvoked);
    }

    public function testDispatchByPriority()
    {
        $invoked = array();
        $listener1 = function () use (&$invoked) {
            $invoked[] = '1';
        };
        $listener2 = function () use (&$invoked) {
            $invoked[] = '2';
        };
        $listener3 = function () use (&$invoked) {
            $invoked[] = '3';
        };
        $this->dispatcher->addListener('pre.foo', $listener1, -10);
        $this->dispatcher->addListener('pre.foo', $listener2);
        $this->dispatcher->addListener('pre.foo', $listener3, 10);
        $this->dispatcher->dispatch(self::preFoo);
        $this->assertEquals(array('3', '2', '1'), $invoked);
    }

    public function testRemoveListener()
    {
        $this->dispatcher->addListener('pre.bar', $this->listener);
        $this->assertTrue($this->dispatcher->hasListeners(self::preBar));
        $this->dispatcher->removeListener('pre.bar', $this->listener);
        $this->assertFalse($this->dispatcher->hasListeners(self::preBar));
        $this->dispatcher->removeListener('notExists', $this->listener);
    }

    public function testAddSubscriber()
    {
        $eventSubscriber = new TestEventSubscriber();
        $this->dispatcher->addSubscriber($eventSubscriber);
        $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
        $this->assertTrue($this->dispatcher->hasListeners(self::postFoo));
    }

    public function testAddSubscriberWithPriorities()
    {
        $eventSubscriber = new TestEventSubscriber();
        $this->dispatcher->addSubscriber($eventSubscriber);

        $eventSubscriber = new TestEventSubscriberWithPriorities();
        $this->dispatcher->addSubscriber($eventSubscriber);

        $listeners = $this->dispatcher->getListeners('pre.foo');
        $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
        $this->assertCount(2, $listeners);
        $this->assertInstanceOf('Symfony\Component\EventDispatcher\Tests\TestEventSubscriberWithPriorities', $listeners[0][0]);
    }

    public function testAddSubscriberWithMultipleListeners()
    {
        $eventSubscriber = new TestEventSubscriberWithMultipleListeners();
        $this->dispatcher->addSubscriber($eventSubscriber);

        $listeners = $this->dispatcher->getListeners('pre.foo');
        $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
        $this->assertCount(2, $listeners);
        $this->assertEquals('preFoo2', $listeners[0][1]);
    }

    public function testRemoveSubscriber()
    {
        $eventSubscriber = new TestEventSubscriber();
        $this->dispatcher->addSubscriber($eventSubscriber);
        $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
        $this->assertTrue($this->dispatcher->hasListeners(self::postFoo));
        $this->dispatcher->removeSubscriber($eventSubscriber);
        $this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
        $this->assertFalse($this->dispatcher->hasListeners(self::postFoo));
    }

    public function testRemoveSubscriberWithPriorities()
    {
        $eventSubscriber = new TestEventSubscriberWithPriorities();
        $this->dispatcher->addSubscriber($eventSubscriber);
        $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
        $this->dispatcher->removeSubscriber($eventSubscriber);
        $this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
    }

    public function testRemoveSubscriberWithMultipleListeners()
    {
        $eventSubscriber = new TestEventSubscriberWithMultipleListeners();
        $this->dispatcher->addSubscriber($eventSubscriber);
        $this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
        $this->assertCount(2, $this->dispatcher->getListeners(self::preFoo));
        $this->dispatcher->removeSubscriber($eventSubscriber);
        $this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
    }

    public function testEventReceivesTheDispatcherInstance()
    {
        $this->dispatcher->addListener('test', function ($event) use (&$dispatcher) {
            $dispatcher = $event->getDispatcher();
        });
        $this->dispatcher->dispatch('test');
        $this->assertSame($this->dispatcher, $dispatcher);
    }

    public function testEventReceivesTheDispatcherInstanceAsArgument()
    {
        $listener = new TestWithDispatcher();
        $this->dispatcher->addListener('test', array($listener, 'foo'));
        $this->assertNull($listener->name);
        $this->assertNull($listener->dispatcher);
        $this->dispatcher->dispatch('test');
        $this->assertEquals('test', $listener->name);
        $this->assertSame($this->dispatcher, $listener->dispatcher);
    }

    /**
     * @see https://bugs.php.net/bug.php?id=62976
     *
     * This bug affects:
     *  - The PHP 5.3 branch for versions < 5.3.18
     *  - The PHP 5.4 branch for versions < 5.4.8
     *  - The PHP 5.5 branch is not affected
     */
    public function testWorkaroundForPhpBug62976()
    {
        $dispatcher = new EventDispatcher();
        $dispatcher->addListener('bug.62976', new CallableClass());
        $dispatcher->removeListener('bug.62976', function() {});
        $this->assertTrue($dispatcher->hasListeners('bug.62976'));
    }
}

class CallableClass
{
    public function __invoke()
    {
    }
}

class TestEventListener
{
    public $preFooInvoked = false;
    public $postFooInvoked = false;

    /* Listener methods */

    public function preFoo(Event $e)
    {
        $this->preFooInvoked = true;
    }

    public function postFoo(Event $e)
    {
        $this->postFooInvoked = true;

        $e->stopPropagation();
    }
}

class TestWithDispatcher
{
    public $name;
    public $dispatcher;

    public function foo(Event $e, $name, $dispatcher)
    {
        $this->name = $name;
        $this->dispatcher = $dispatcher;
    }
}

class TestEventSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return array('pre.foo' => 'preFoo', 'post.foo' => 'postFoo');
    }
}

class TestEventSubscriberWithPriorities implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return array(
            'pre.foo' => array('preFoo', 10),
            'post.foo' => array('postFoo'),
            );
    }
}

class TestEventSubscriberWithMultipleListeners implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return array('pre.foo' => array(
            array('preFoo1'),
            array('preFoo2', 10)
        ));
    }
}
{
    "name": "symfony/config",
    "type": "library",
    "description": "Symfony Config Component",
    "keywords": [],
    "homepage": "http://symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "http://symfony.com/contributors"
        }
    ],
    "require": {
        "php": ">=5.3.3",
        "symfony/filesystem": "~2.3"
    },
    "autoload": {
        "psr-0": { "Symfony\\Component\\Config\\": "" }
    },
    "target-dir": "Symfony/Component/Config",
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-master": "2.4-dev"
        }
    }
}
Copyright (c) 2004-2013 Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Util;

/**
 * XMLUtils is a bunch of utility methods to XML operations.
 *
 * This class contains static methods only and is not meant to be instantiated.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Martin Hasoň <martin.hason@gmail.com>
 */
class XmlUtils
{
    /**
     * This class should not be instantiated
     */
    private function __construct()
    {
    }

    /**
     * Loads an XML file.
     *
     * @param string               $file             An XML file path
     * @param string|callable|null $schemaOrCallable An XSD schema file path, a callable, or null to disable validation
     *
     * @return \DOMDocument
     *
     * @throws \InvalidArgumentException When loading of XML file returns error
     */
    public static function loadFile($file, $schemaOrCallable = null)
    {
        $internalErrors = libxml_use_internal_errors(true);
        $disableEntities = libxml_disable_entity_loader(true);
        libxml_clear_errors();

        $dom = new \DOMDocument();
        $dom->validateOnParse = true;
        if (!$dom->loadXML(file_get_contents($file), LIBXML_NONET | (defined('LIBXML_COMPACT') ? LIBXML_COMPACT : 0))) {
            libxml_disable_entity_loader($disableEntities);

            throw new \InvalidArgumentException(implode("\n", static::getXmlErrors($internalErrors)));
        }

        $dom->normalizeDocument();

        libxml_use_internal_errors($internalErrors);
        libxml_disable_entity_loader($disableEntities);

        foreach ($dom->childNodes as $child) {
            if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) {
                throw new \InvalidArgumentException('Document types are not allowed.');
            }
        }

        if (null !== $schemaOrCallable) {
            $internalErrors = libxml_use_internal_errors(true);
            libxml_clear_errors();

            $e = null;
            if (is_callable($schemaOrCallable)) {
                try {
                    $valid = call_user_func($schemaOrCallable, $dom, $internalErrors);
                } catch (\Exception $e) {
                    $valid = false;
                }
            } elseif (!is_array($schemaOrCallable) && is_file((string) $schemaOrCallable)) {
                $valid = @$dom->schemaValidate($schemaOrCallable);
            } else {
                libxml_use_internal_errors($internalErrors);

                throw new \InvalidArgumentException('The schemaOrCallable argument has to be a valid path to XSD file or callable.');
            }

            if (!$valid) {
                $messages = static::getXmlErrors($internalErrors);
                if (empty($messages)) {
                    $messages = array(sprintf('The XML file "%s" is not valid.', $file));
                }
                throw new \InvalidArgumentException(implode("\n", $messages), 0, $e);
            }

            libxml_use_internal_errors($internalErrors);
        }

        return $dom;
    }

    /**
     * Converts a \DomElement object to a PHP array.
     *
     * The following rules applies during the conversion:
     *
     *  * Each tag is converted to a key value or an array
     *    if there is more than one "value"
     *
     *  * The content of a tag is set under a "value" key (<foo>bar</foo>)
     *    if the tag also has some nested tags
     *
     *  * The attributes are converted to keys (<foo foo="bar"/>)
     *
     *  * The nested-tags are converted to keys (<foo><foo>bar</foo></foo>)
     *
     * @param \DomElement $element     A \DomElement instance
     * @param Boolean     $checkPrefix Check prefix in an element or an attribute name
     *
     * @return array A PHP array
     */
    public static function convertDomElementToArray(\DomElement $element, $checkPrefix = true)
    {
        $prefix = (string) $element->prefix;
        $empty = true;
        $config = array();
        foreach ($element->attributes as $name => $node) {
            if ($checkPrefix && !in_array((string) $node->prefix, array('', $prefix), true)) {
                continue;
            }
            $config[$name] = static::phpize($node->value);
            $empty = false;
        }

        $nodeValue = false;
        foreach ($element->childNodes as $node) {
            if ($node instanceof \DOMText) {
                if (trim($node->nodeValue)) {
                    $nodeValue = trim($node->nodeValue);
                    $empty = false;
                }
            } elseif ($checkPrefix && $prefix != (string) $node->prefix) {
                continue;
            } elseif (!$node instanceof \DOMComment) {
                $value = static::convertDomElementToArray($node, $checkPrefix);

                $key = $node->localName;
                if (isset($config[$key])) {
                    if (!is_array($config[$key]) || !is_int(key($config[$key]))) {
                        $config[$key] = array($config[$key]);
                    }
                    $config[$key][] = $value;
                } else {
                    $config[$key] = $value;
                }

                $empty = false;
            }
        }

        if (false !== $nodeValue) {
            $value = static::phpize($nodeValue);
            if (count($config)) {
                $config['value'] = $value;
            } else {
                $config = $value;
            }
        }

        return !$empty ? $config : null;
    }

    /**
     * Converts an xml value to a php type.
     *
     * @param mixed $value
     *
     * @return mixed
     */
    public static function phpize($value)
    {
        $value = (string) $value;
        $lowercaseValue = strtolower($value);

        switch (true) {
            case 'null' === $lowercaseValue:
                return null;
            case ctype_digit($value):
                $raw = $value;
                $cast = intval($value);

                return '0' == $value[0] ? octdec($value) : (((string) $raw == (string) $cast) ? $cast : $raw);
            case isset($value[1]) && '-' === $value[0] && ctype_digit(substr($value, 1)):
                $raw = $value;
                $cast = intval($value);

                return '0' == $value[1] ? octdec($value) : (((string) $raw == (string) $cast) ? $cast : $raw);
            case 'true' === $lowercaseValue:
                return true;
            case 'false' === $lowercaseValue:
                return false;
            case isset($value[1]) && '0b' == $value[0].$value[1]:
                return bindec($value);
            case is_numeric($value):
                return '0x' == $value[0].$value[1] ? hexdec($value) : floatval($value);
            case preg_match('/^(-|\+)?[0-9]+(\.[0-9]+)?$/', $value):
                return floatval($value);
            default:
                return $value;
        }
    }

    protected static function getXmlErrors($internalErrors)
    {
        $errors = array();
        foreach (libxml_get_errors() as $error) {
            $errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)',
                LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR',
                $error->code,
                trim($error->message),
                $error->file ? $error->file : 'n/a',
                $error->line,
                $error->column
            );
        }

        libxml_clear_errors();
        libxml_use_internal_errors($internalErrors);

        return $errors;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Resource;

/**
 * FileResource represents a resource stored on the filesystem.
 *
 * The resource can be a file or a directory.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FileResource implements ResourceInterface, \Serializable
{
    private $resource;

    /**
     * Constructor.
     *
     * @param string $resource The file path to the resource
     */
    public function __construct($resource)
    {
        $this->resource = realpath($resource);
    }

    /**
     * Returns a string representation of the Resource.
     *
     * @return string A string representation of the Resource
     */
    public function __toString()
    {
        return (string) $this->resource;
    }

    /**
     * Returns the resource tied to this Resource.
     *
     * @return mixed The resource
     */
    public function getResource()
    {
        return $this->resource;
    }

    /**
     * Returns true if the resource has not been updated since the given timestamp.
     *
     * @param integer $timestamp The last time the resource was loaded
     *
     * @return Boolean true if the resource has not been updated, false otherwise
     */
    public function isFresh($timestamp)
    {
        if (!file_exists($this->resource)) {
            return false;
        }

        return filemtime($this->resource) < $timestamp;
    }

    public function serialize()
    {
        return serialize($this->resource);
    }

    public function unserialize($serialized)
    {
        $this->resource = unserialize($serialized);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Resource;

/**
 * DirectoryResource represents a resources stored in a subdirectory tree.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DirectoryResource implements ResourceInterface, \Serializable
{
    private $resource;
    private $pattern;

    /**
     * Constructor.
     *
     * @param string $resource The file path to the resource
     * @param string $pattern  A pattern to restrict monitored files
     */
    public function __construct($resource, $pattern = null)
    {
        $this->resource = $resource;
        $this->pattern = $pattern;
    }

    /**
     * Returns a string representation of the Resource.
     *
     * @return string A string representation of the Resource
     */
    public function __toString()
    {
        return (string) $this->resource;
    }

    /**
     * Returns the resource tied to this Resource.
     *
     * @return mixed The resource
     */
    public function getResource()
    {
        return $this->resource;
    }

    public function getPattern()
    {
        return $this->pattern;
    }

    /**
     * Returns true if the resource has not been updated since the given timestamp.
     *
     * @param integer $timestamp The last time the resource was loaded
     *
     * @return Boolean true if the resource has not been updated, false otherwise
     */
    public function isFresh($timestamp)
    {
        if (!is_dir($this->resource)) {
            return false;
        }

        $newestMTime = filemtime($this->resource);
        foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->resource), \RecursiveIteratorIterator::SELF_FIRST) as $file) {
            // if regex filtering is enabled only check matching files
            if ($this->pattern && $file->isFile() && !preg_match($this->pattern, $file->getBasename())) {
                continue;
            }

            // always monitor directories for changes, except the .. entries
            // (otherwise deleted files wouldn't get detected)
            if ($file->isDir() && '/..' === substr($file, -3)) {
                continue;
            }

            $newestMTime = max($file->getMTime(), $newestMTime);
        }

        return $newestMTime < $timestamp;
    }

    public function serialize()
    {
        return serialize(array($this->resource, $this->pattern));
    }

    public function unserialize($serialized)
    {
        list($this->resource, $this->pattern) = unserialize($serialized);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Resource;

/**
 * ResourceInterface is the interface that must be implemented by all Resource classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface ResourceInterface
{
    /**
     * Returns a string representation of the Resource.
     *
     * @return string A string representation of the Resource
     */
    public function __toString();

    /**
     * Returns true if the resource has not been updated since the given timestamp.
     *
     * @param integer $timestamp The last time the resource was loaded
     *
     * @return Boolean true if the resource has not been updated, false otherwise
     */
    public function isFresh($timestamp);

    /**
     * Returns the resource tied to this Resource.
     *
     * @return mixed The resource
     */
    public function getResource();
}
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Config Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Resources</directory>
                <directory>./Tests</directory>
                <directory>./vendor</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config;

use Symfony\Component\Config\Resource\ResourceInterface;
use Symfony\Component\Filesystem\Filesystem;

/**
 * ConfigCache manages PHP cache files.
 *
 * When debug is enabled, it knows when to flush the cache
 * thanks to an array of ResourceInterface instances.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ConfigCache
{
    private $debug;
    private $file;

    /**
     * Constructor.
     *
     * @param string  $file  The absolute cache path
     * @param Boolean $debug Whether debugging is enabled or not
     */
    public function __construct($file, $debug)
    {
        $this->file = $file;
        $this->debug = (Boolean) $debug;
    }

    /**
     * Gets the cache file path.
     *
     * @return string The cache file path
     */
    public function __toString()
    {
        return $this->file;
    }

    /**
     * Checks if the cache is still fresh.
     *
     * This method always returns true when debug is off and the
     * cache file exists.
     *
     * @return Boolean true if the cache is fresh, false otherwise
     */
    public function isFresh()
    {
        if (!is_file($this->file)) {
            return false;
        }

        if (!$this->debug) {
            return true;
        }

        $metadata = $this->getMetaFile();
        if (!is_file($metadata)) {
            return false;
        }

        $time = filemtime($this->file);
        $meta = unserialize(file_get_contents($metadata));
        foreach ($meta as $resource) {
            if (!$resource->isFresh($time)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Writes cache.
     *
     * @param string              $content  The content to write in the cache
     * @param ResourceInterface[] $metadata An array of ResourceInterface instances
     *
     * @throws \RuntimeException When cache file can't be wrote
     */
    public function write($content, array $metadata = null)
    {
        $mode = 0666 & ~umask();
        $filesystem = new Filesystem();
        $filesystem->dumpFile($this->file, $content, $mode);

        if (null !== $metadata && true === $this->debug) {
            $filesystem->dumpFile($this->getMetaFile(), serialize($metadata), $mode);
        }
    }

    /**
     * Gets the meta file path.
     *
     * @return string The meta file path
     */
    private function getMetaFile()
    {
        return $this->file.'.meta';
    }

}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Loader;

/**
 * LoaderInterface is the interface implemented by all loader classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface LoaderInterface
{
    /**
     * Loads a resource.
     *
     * @param mixed  $resource The resource
     * @param string $type     The resource type
     */
    public function load($resource, $type = null);

    /**
     * Returns true if this class supports the given resource.
     *
     * @param mixed  $resource A resource
     * @param string $type     The resource type
     *
     * @return Boolean true if this class supports the given resource, false otherwise
     */
    public function supports($resource, $type = null);

    /**
     * Gets the loader resolver.
     *
     * @return LoaderResolverInterface A LoaderResolverInterface instance
     */
    public function getResolver();

    /**
     * Sets the loader resolver.
     *
     * @param LoaderResolverInterface $resolver A LoaderResolverInterface instance
     */
    public function setResolver(LoaderResolverInterface $resolver);

}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Loader;

/**
 * LoaderResolverInterface selects a loader for a given resource.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface LoaderResolverInterface
{
    /**
     * Returns a loader able to load the resource.
     *
     * @param mixed  $resource A resource
     * @param string $type     The resource type
     *
     * @return LoaderInterface A LoaderInterface instance
     */
    public function resolve($resource, $type = null);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Loader;

use Symfony\Component\Config\FileLocatorInterface;
use Symfony\Component\Config\Exception\FileLoaderLoadException;
use Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException;

/**
 * FileLoader is the abstract class used by all built-in loaders that are file based.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class FileLoader extends Loader
{
    protected static $loading = array();

    protected $locator;

    private $currentDir;

    /**
     * Constructor.
     *
     * @param FileLocatorInterface $locator A FileLocatorInterface instance
     */
    public function __construct(FileLocatorInterface $locator)
    {
        $this->locator = $locator;
    }

    public function setCurrentDir($dir)
    {
        $this->currentDir = $dir;
    }

    public function getLocator()
    {
        return $this->locator;
    }

    /**
     * Imports a resource.
     *
     * @param mixed   $resource       A Resource
     * @param string  $type           The resource type
     * @param Boolean $ignoreErrors   Whether to ignore import errors or not
     * @param string  $sourceResource The original resource importing the new resource
     *
     * @return mixed
     *
     * @throws FileLoaderLoadException
     * @throws FileLoaderImportCircularReferenceException
     */
    public function import($resource, $type = null, $ignoreErrors = false, $sourceResource = null)
    {
        try {
            $loader = $this->resolve($resource, $type);

            if ($loader instanceof FileLoader && null !== $this->currentDir) {
                $resource = $this->locator->locate($resource, $this->currentDir, false);
            }

            $resources = is_array($resource) ? $resource : array($resource);
            for ($i = 0; $i < $resourcesCount = count($resources); $i++ ) {
                if (isset(self::$loading[$resources[$i]])) {
                    if ($i == $resourcesCount-1) {
                        throw new FileLoaderImportCircularReferenceException(array_keys(self::$loading));
                    }
                } else {
                    $resource = $resources[$i];
                    break;
                }
            }
            self::$loading[$resource] = true;

            $ret = $loader->load($resource, $type);

            unset(self::$loading[$resource]);

            return $ret;
        } catch (FileLoaderImportCircularReferenceException $e) {
            throw $e;
        } catch (\Exception $e) {
            if (!$ignoreErrors) {
                // prevent embedded imports from nesting multiple exceptions
                if ($e instanceof FileLoaderLoadException) {
                    throw $e;
                }

                throw new FileLoaderLoadException($resource, $sourceResource, null, $e);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Loader;

use Symfony\Component\Config\Exception\FileLoaderLoadException;

/**
 * Loader is the abstract class used by all built-in loaders.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Loader implements LoaderInterface
{
    protected $resolver;

    /**
     * Gets the loader resolver.
     *
     * @return LoaderResolverInterface A LoaderResolverInterface instance
     */
    public function getResolver()
    {
        return $this->resolver;
    }

    /**
     * Sets the loader resolver.
     *
     * @param LoaderResolverInterface $resolver A LoaderResolverInterface instance
     */
    public function setResolver(LoaderResolverInterface $resolver)
    {
        $this->resolver = $resolver;
    }

    /**
     * Imports a resource.
     *
     * @param mixed  $resource A Resource
     * @param string $type     The resource type
     *
     * @return mixed
     */
    public function import($resource, $type = null)
    {
        return $this->resolve($resource, $type)->load($resource, $type);
    }

    /**
     * Finds a loader able to load an imported resource.
     *
     * @param mixed  $resource A Resource
     * @param string $type     The resource type
     *
     * @return LoaderInterface A LoaderInterface instance
     *
     * @throws FileLoaderLoadException if no loader is found
     */
    public function resolve($resource, $type = null)
    {
        if ($this->supports($resource, $type)) {
            return $this;
        }

        $loader = null === $this->resolver ? false : $this->resolver->resolve($resource, $type);

        if (false === $loader) {
            throw new FileLoaderLoadException($resource);
        }

        return $loader;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Loader;

use Symfony\Component\Config\Exception\FileLoaderLoadException;

/**
 * DelegatingLoader delegates loading to other loaders using a loader resolver.
 *
 * This loader acts as an array of LoaderInterface objects - each having
 * a chance to load a given resource (handled by the resolver)
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DelegatingLoader extends Loader
{
    /**
     * Constructor.
     *
     * @param LoaderResolverInterface $resolver A LoaderResolverInterface instance
     */
    public function __construct(LoaderResolverInterface $resolver)
    {
        $this->resolver = $resolver;
    }

    /**
     * Loads a resource.
     *
     * @param mixed  $resource A resource
     * @param string $type     The resource type
     *
     * @return mixed
     *
     * @throws FileLoaderLoadException if no loader is found.
     */
    public function load($resource, $type = null)
    {
        if (false === $loader = $this->resolver->resolve($resource, $type)) {
            throw new FileLoaderLoadException($resource);
        }

        return $loader->load($resource, $type);
    }

    /**
     * {@inheritdoc}
     */
    public function supports($resource, $type = null)
    {
        return false === $this->resolver->resolve($resource, $type) ? false : true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Loader;

/**
 * LoaderResolver selects a loader for a given resource.
 *
 * A resource can be anything (e.g. a full path to a config file or a Closure).
 * Each loader determines whether it can load a resource and how.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class LoaderResolver implements LoaderResolverInterface
{
    /**
     * @var LoaderInterface[] An array of LoaderInterface objects
     */
    private $loaders = array();

    /**
     * Constructor.
     *
     * @param LoaderInterface[] $loaders An array of loaders
     */
    public function __construct(array $loaders = array())
    {
        foreach ($loaders as $loader) {
            $this->addLoader($loader);
        }
    }

    /**
     * Returns a loader able to load the resource.
     *
     * @param mixed  $resource A resource
     * @param string $type     The resource type
     *
     * @return LoaderInterface|false A LoaderInterface instance
     */
    public function resolve($resource, $type = null)
    {
        foreach ($this->loaders as $loader) {
            if ($loader->supports($resource, $type)) {
                return $loader;
            }
        }

        return false;
    }

    /**
     * Adds a loader.
     *
     * @param LoaderInterface $loader A LoaderInterface instance
     */
    public function addLoader(LoaderInterface $loader)
    {
        $this->loaders[] = $loader;
        $loader->setResolver($this);
    }

    /**
     * Returns the registered loaders.
     *
     * @return LoaderInterface[] An array of LoaderInterface instances
     */
    public function getLoaders()
    {
        return $this->loaders;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface FileLocatorInterface
{
    /**
     * Returns a full path for a given file name.
     *
     * @param mixed   $name        The file name to locate
     * @param string  $currentPath The current path
     * @param Boolean $first       Whether to return the first occurrence or an array of filenames
     *
     * @return string|array The full path to the file|An array of file paths
     *
     * @throws \InvalidArgumentException When file is not found
     */
    public function locate($name, $currentPath = null, $first = true);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Exception;

/**
 * Exception class for when a resource cannot be loaded or imported.
 *
 * @author Ryan Weaver <ryan@thatsquality.com>
 */
class FileLoaderLoadException extends \Exception
{
    /**
     * @param string     $resource       The resource that could not be imported
     * @param string     $sourceResource The original resource importing the new resource
     * @param integer    $code           The error code
     * @param \Exception $previous       A previous exception
     */
    public function __construct($resource, $sourceResource = null, $code = null, $previous = null)
    {
        if (null === $sourceResource) {
            $message = sprintf('Cannot load resource "%s".', $this->varToString($resource));
        } else {
            $message = sprintf('Cannot import resource "%s" from "%s".', $this->varToString($resource), $this->varToString($sourceResource));
        }

        // Is the resource located inside a bundle?
        if ('@' === $resource[0]) {
            $parts = explode(DIRECTORY_SEPARATOR, $resource);
            $bundle = substr($parts[0], 1);
            $message .= ' '.sprintf('Make sure the "%s" bundle is correctly registered and loaded in the application kernel class.', $bundle);
        } elseif ($previous) {
            // include the previous exception, to help the user see what might be the underlying cause
            $message .= ' '.sprintf('(%s)', $previous->getMessage());
        }

        parent::__construct($message, $code, $previous);
    }

    protected function varToString($var)
    {
        if (is_object($var)) {
            return sprintf('Object(%s)', get_class($var));
        }

        if (is_array($var)) {
            $a = array();
            foreach ($var as $k => $v) {
                $a[] = sprintf('%s => %s', $k, $this->varToString($v));
            }

            return sprintf("Array(%s)", implode(', ', $a));
        }

        if (is_resource($var)) {
            return sprintf('Resource(%s)', get_resource_type($var));
        }

        if (null === $var) {
            return 'null';
        }

        if (false === $var) {
            return 'false';
        }

        if (true === $var) {
            return 'true';
        }

        return (string) $var;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Exception;

/**
 * Exception class for when a circular reference is detected when importing resources.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FileLoaderImportCircularReferenceException extends FileLoaderLoadException
{
    public function __construct(array $resources, $code = null, $previous = null)
    {
        $message = sprintf('Circular reference detected in "%s" ("%s" > "%s").', $this->varToString($resources[0]), implode('" > "', $resources), $resources[0]);

        call_user_func('Exception::__construct', $message, $code, $previous);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config;

/**
 * FileLocator uses an array of pre-defined paths to find files.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FileLocator implements FileLocatorInterface
{
    protected $paths;

    /**
     * Constructor.
     *
     * @param string|array $paths A path or an array of paths where to look for resources
     */
    public function __construct($paths = array())
    {
        $this->paths = (array) $paths;
    }

    /**
     * Returns a full path for a given file name.
     *
     * @param mixed   $name        The file name to locate
     * @param string  $currentPath The current path
     * @param Boolean $first       Whether to return the first occurrence or an array of filenames
     *
     * @return string|array The full path to the file|An array of file paths
     *
     * @throws \InvalidArgumentException When file is not found
     */
    public function locate($name, $currentPath = null, $first = true)
    {
        if ($this->isAbsolutePath($name)) {
            if (!file_exists($name)) {
                throw new \InvalidArgumentException(sprintf('The file "%s" does not exist.', $name));
            }

            return $name;
        }

        $filepaths = array();
        if (null !== $currentPath && file_exists($file = $currentPath.DIRECTORY_SEPARATOR.$name)) {
            if (true === $first) {
                return $file;
            }
            $filepaths[] = $file;
        }

        foreach ($this->paths as $path) {
            if (file_exists($file = $path.DIRECTORY_SEPARATOR.$name)) {
                if (true === $first) {
                    return $file;
                }
                $filepaths[] = $file;
            }
        }

        if (!$filepaths) {
            throw new \InvalidArgumentException(sprintf('The file "%s" does not exist (in: %s%s).', $name, null !== $currentPath ? $currentPath.', ' : '', implode(', ', $this->paths)));
        }

        return array_values(array_unique($filepaths));
    }

    /**
     * Returns whether the file path is an absolute path.
     *
     * @param string $file A file path
     *
     * @return Boolean
     */
    private function isAbsolutePath($file)
    {
        if ($file[0] == '/' || $file[0] == '\\'
            || (strlen($file) > 3 && ctype_alpha($file[0])
                && $file[1] == ':'
                && ($file[2] == '\\' || $file[2] == '/')
            )
            || null !== parse_url($file, PHP_URL_SCHEME)
        ) {
            return true;
        }

        return false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

/**
 * This class is the entry point for config normalization/merging/finalization.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class Processor
{
    /**
     * Processes an array of configurations.
     *
     * @param NodeInterface $configTree The node tree describing the configuration
     * @param array         $configs    An array of configuration items to process
     *
     * @return array The processed configuration
     */
    public function process(NodeInterface $configTree, array $configs)
    {
        $currentConfig = array();
        foreach ($configs as $config) {
            $config = $configTree->normalize($config);
            $currentConfig = $configTree->merge($currentConfig, $config);
        }

        return $configTree->finalize($currentConfig);
    }

    /**
     * Processes an array of configurations.
     *
     * @param ConfigurationInterface $configuration The configuration class
     * @param array                  $configs       An array of configuration items to process
     *
     * @return array The processed configuration
     */
    public function processConfiguration(ConfigurationInterface $configuration, array $configs)
    {
        return $this->process($configuration->getConfigTreeBuilder()->buildTree(), $configs);
    }

    /**
     * Normalizes a configuration entry.
     *
     * This method returns a normalize configuration array for a given key
     * to remove the differences due to the original format (YAML and XML mainly).
     *
     * Here is an example.
     *
     * The configuration in XML:
     *
     * <twig:extension>twig.extension.foo</twig:extension>
     * <twig:extension>twig.extension.bar</twig:extension>
     *
     * And the same configuration in YAML:
     *
     * extensions: ['twig.extension.foo', 'twig.extension.bar']
     *
     * @param array  $config A config array
     * @param string $key    The key to normalize
     * @param string $plural The plural form of the key if it is irregular
     *
     * @return array
     */
    public static function normalizeConfig($config, $key, $plural = null)
    {
        if (null === $plural) {
            $plural = $key.'s';
        }

        if (isset($config[$plural])) {
            return $config[$plural];
        }

        if (isset($config[$key])) {
            if (is_string($config[$key]) || !is_int(key($config[$key]))) {
                // only one
                return  array($config[$key]);
            }

            return  $config[$key];
        }

        return array();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

/**
 * This interface must be implemented by nodes which can be used as prototypes.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface PrototypeNodeInterface extends NodeInterface
{
    /**
     * Sets the name of the node.
     *
     * @param string $name The name of the node
     */
    public function setName($name);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

use Symfony\Component\Config\Definition\Exception\InvalidTypeException;

/**
 * This node represents an integer value in the config tree.
 *
 * @author Jeanmonod David <david.jeanmonod@gmail.com>
 */
class IntegerNode extends NumericNode
{
    /**
     * {@inheritDoc}
     */
    protected function validateType($value)
    {
        if (!is_int($value)) {
            $ex = new InvalidTypeException(sprintf('Invalid type for path "%s". Expected int, but got %s.', $this->getPath(), gettype($value)));
            $ex->setPath($this->getPath());

            throw $ex;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

use Symfony\Component\Config\Definition\Exception\InvalidTypeException;

/**
 * This node represents a Boolean value in the config tree.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class BooleanNode extends ScalarNode
{
    /**
     * {@inheritDoc}
     */
    protected function validateType($value)
    {
        if (!is_bool($value)) {
            $ex = new InvalidTypeException(sprintf(
                'Invalid type for path "%s". Expected boolean, but got %s.',
                $this->getPath(),
                gettype($value)
            ));
            $ex->setPath($this->getPath());

            throw $ex;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Dumper;

use Symfony\Component\Config\Definition\ConfigurationInterface;
use Symfony\Component\Config\Definition\NodeInterface;
use Symfony\Component\Config\Definition\ArrayNode;
use Symfony\Component\Config\Definition\ScalarNode;
use Symfony\Component\Config\Definition\EnumNode;
use Symfony\Component\Config\Definition\PrototypedArrayNode;
use Symfony\Component\Yaml\Inline;

/**
 * Dumps a Yaml reference configuration for the given configuration/node instance.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
class YamlReferenceDumper
{
    private $reference;

    public function dump(ConfigurationInterface $configuration)
    {
        return $this->dumpNode($configuration->getConfigTreeBuilder()->buildTree());
    }

    public function dumpNode(NodeInterface $node)
    {
        $this->reference = '';
        $this->writeNode($node);
        $ref = $this->reference;
        $this->reference = null;

        return $ref;
    }

    /**
     * @param NodeInterface $node
     * @param integer       $depth
     */
    private function writeNode(NodeInterface $node, $depth = 0)
    {
        $comments = array();
        $default = '';
        $defaultArray = null;
        $children = null;
        $example = $node->getExample();

        // defaults
        if ($node instanceof ArrayNode) {
            $children = $node->getChildren();

            if ($node instanceof PrototypedArrayNode) {
                $prototype = $node->getPrototype();

                if ($prototype instanceof ArrayNode) {
                    $children = $prototype->getChildren();
                }

                // check for attribute as key
                if ($key = $node->getKeyAttribute()) {
                    $keyNodeClass = 'Symfony\Component\Config\Definition\\'.($prototype instanceof ArrayNode ? 'ArrayNode' : 'ScalarNode');
                    $keyNode = new $keyNodeClass($key, $node);
                    $keyNode->setInfo('Prototype');

                    // add children
                    foreach ($children as $childNode) {
                        $keyNode->addChild($childNode);
                    }
                    $children = array($key => $keyNode);
                }
            }

            if (!$children) {
                if ($node->hasDefaultValue() && count($defaultArray = $node->getDefaultValue())) {
                    $default = '';
                } elseif (!is_array($example)) {
                    $default = '[]';
                }
            }
        } elseif ($node instanceof EnumNode) {
            $comments[] = 'One of '.implode('; ', array_map('json_encode', $node->getValues()));
            $default = '~';
        } else {
            $default = '~';

            if ($node->hasDefaultValue()) {
                $default = $node->getDefaultValue();

                if (is_array($default)) {
                    if ($node->hasDefaultValue() && count($defaultArray = $node->getDefaultValue())) {
                        $default = '';
                    } elseif (!is_array($example)) {
                        $default = '[]';
                    }
                } else {
                    $default = Inline::dump($default);
                }
            }
        }

        // required?
        if ($node->isRequired()) {
            $comments[] = 'Required';
        }

        // example
        if ($example && !is_array($example)) {
            $comments[] = 'Example: '.$example;
        }

        $default = (string) $default != '' ? ' '.$default : '';
        $comments = count($comments) ? '# '.implode(', ', $comments) : '';

        $text = rtrim(sprintf('%-20s %s %s', $node->getName().':', $default, $comments), ' ');

        if ($info = $node->getInfo()) {
            $this->writeLine('');
            // indenting multi-line info
            $info = str_replace("\n", sprintf("\n%".$depth * 4 . "s# ", ' '), $info);
            $this->writeLine('# '.$info, $depth * 4);
        }

        $this->writeLine($text, $depth * 4);

        // output defaults
        if ($defaultArray) {
            $this->writeLine('');

            $message = count($defaultArray) > 1 ? 'Defaults' : 'Default';

            $this->writeLine('# '.$message.':', $depth * 4 + 4);

            $this->writeArray($defaultArray, $depth + 1);
        }

        if (is_array($example)) {
            $this->writeLine('');

            $message = count($example) > 1 ? 'Examples' : 'Example';

            $this->writeLine('# '.$message.':', $depth * 4 + 4);

            $this->writeArray($example, $depth + 1);
        }

        if ($children) {
            foreach ($children as $childNode) {
                $this->writeNode($childNode, $depth + 1);
            }
        }
    }

    /**
     * Outputs a single config reference line
     *
     * @param string $text
     * @param int    $indent
     */
    private function writeLine($text, $indent = 0)
    {
        $indent = strlen($text) + $indent;
        $format = '%'.$indent.'s';

        $this->reference .= sprintf($format, $text)."\n";
    }

    private function writeArray(array $array, $depth)
    {
        $isIndexed = array_values($array) === $array;

        foreach ($array as $key => $value) {
            if (is_array($value)) {
                $val = '';
            } else {
                $val = $value;
            }

            if ($isIndexed) {
                $this->writeLine('- '.$val, $depth * 4);
            } else {
                $this->writeLine(sprintf('%-20s %s', $key.':', $val), $depth * 4);
            }

            if (is_array($value)) {
                $this->writeArray($value, $depth + 1);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Dumper;

use Symfony\Component\Config\Definition\ConfigurationInterface;
use Symfony\Component\Config\Definition\NodeInterface;
use Symfony\Component\Config\Definition\ArrayNode;
use Symfony\Component\Config\Definition\EnumNode;
use Symfony\Component\Config\Definition\PrototypedArrayNode;

/**
 * Dumps a XML reference configuration for the given configuration/node instance.
 *
 * @author Wouter J <waldio.webdesign@gmail.com>
 */
class XmlReferenceDumper
{
    private $reference;

    public function dump(ConfigurationInterface $configuration, $namespace = null)
    {
        return $this->dumpNode($configuration->getConfigTreeBuilder()->buildTree(), $namespace);
    }

    public function dumpNode(NodeInterface $node, $namespace = null)
    {
        $this->reference = '';
        $this->writeNode($node, 0, true, $namespace);
        $ref = $this->reference;
        $this->reference = null;

        return $ref;
    }

    /**
     * @param NodeInterface $node
     * @param integer       $depth
     * @param Boolean       $root      If the node is the root node
     * @param string        $namespace The namespace of the node
     */
    private function writeNode(NodeInterface $node, $depth = 0, $root = false, $namespace = null)
    {
        $rootName = ($root ? 'config' : $node->getName());
        $rootNamespace = ($namespace ?: ($root ? 'http://example.org/schema/dic/'.$node->getName() : null));

        // xml remapping
        if ($node->getParent()) {
            $remapping = array_filter($node->getParent()->getXmlRemappings(), function ($mapping) use ($rootName) {
                return $rootName === $mapping[1];
            });

            if (count($remapping)) {
                list($singular, $plural) = current($remapping);
                $rootName = $singular;
            }
        }
        $rootName = str_replace('_', '-', $rootName);

        $rootAttributes = array();
        $rootAttributeComments = array();
        $rootChildren = array();
        $rootComments = array();

        if ($node instanceof ArrayNode) {
            $children = $node->getChildren();

            // comments about the root node
            if ($rootInfo = $node->getInfo()) {
                $rootComments[] = $rootInfo;
            }

            if ($rootNamespace) {
                $rootComments[] = 'Namespace: '.$rootNamespace;
            }

            // render prototyped nodes
            if ($node instanceof PrototypedArrayNode) {
                array_unshift($rootComments, 'prototype');

                if ($key = $node->getKeyAttribute()) {
                    $rootAttributes[$key] = str_replace('-', ' ', $rootName).' '.$key;
                }

                $prototype = $node->getPrototype();

                if ($prototype instanceof ArrayNode) {
                    $children = $prototype->getChildren();
                } else {
                    if ($prototype->hasDefaultValue()) {
                        $prototypeValue = $prototype->getDefaultValue();
                    } else {
                        switch (get_class($prototype)) {
                            case 'Symfony\Component\Config\Definition\ScalarNode':
                                $prototypeValue = 'scalar value';
                                break;

                            case 'Symfony\Component\Config\Definition\FloatNode':
                            case 'Symfony\Component\Config\Definition\IntegerNode':
                                $prototypeValue = 'numeric value';
                                break;

                            case 'Symfony\Component\Config\Definition\BooleanNode':
                                $prototypeValue = 'true|false';
                                break;

                            case 'Symfony\Component\Config\Definition\EnumNode':
                                $prototypeValue = implode('|', array_map('json_encode', $prototype->getValues()));
                                break;

                            default:
                                $prototypeValue = 'value';
                        }
                    }
                }
            }

            // get attributes and elements
            foreach ($children as $child) {
                if (!$child instanceof ArrayNode) {
                    // get attributes

                    // metadata
                    $name  = str_replace('_', '-', $child->getName());
                    $value = '%%%%not_defined%%%%'; // use a string which isn't used in the normal world

                    // comments
                    $comments = array();
                    if ($info = $child->getInfo()) {
                        $comments[] = $info;
                    }

                    if ($example = $child->getExample()) {
                        $comments[] = 'Example: '.$example;
                    }

                    if ($child->isRequired()) {
                        $comments[] = 'Required';
                    }

                    if ($child instanceof EnumNode) {
                        $comments[] = 'One of '.implode('; ', array_map('json_encode', $child->getValues()));
                    }

                    if (count($comments)) {
                        $rootAttributeComments[$name] = implode(";\n", $comments);
                    }

                    // default values
                    if ($child->hasDefaultValue()) {
                        $value = $child->getDefaultValue();
                    }

                    // append attribute
                    $rootAttributes[$name] = $value;
                } else {
                    // get elements
                    $rootChildren[] = $child;
                }
            }
        }

        // render comments

        // root node comment
        if (count($rootComments)) {
            foreach ($rootComments as $comment) {
                $this->writeLine('<!-- '.$comment.' -->', $depth);
            }
        }

        // attribute comments
        if (count($rootAttributeComments)) {
            foreach ($rootAttributeComments as $attrName => $comment) {
                $commentDepth = $depth + 4 + strlen($attrName) + 2;
                $commentLines = explode("\n", $comment);
                $multiline = (count($commentLines) > 1);
                $comment = implode(PHP_EOL.str_repeat(' ', $commentDepth), $commentLines);

                if ($multiline) {
                    $this->writeLine('<!--', $depth);
                    $this->writeLine($attrName.': '.$comment, $depth + 4);
                    $this->writeLine('-->', $depth);
                } else {
                    $this->writeLine('<!-- '.$attrName.': '.$comment.' -->', $depth);
                }
            }
        }

        // render start tag + attributes
        $rootIsVariablePrototype = isset($prototypeValue);
        $rootIsEmptyTag = (0 === count($rootChildren) && !$rootIsVariablePrototype);
        $rootOpenTag = '<'.$rootName;
        if (1 >= ($attributesCount = count($rootAttributes))) {
            if (1 === $attributesCount) {
                $rootOpenTag .= sprintf(' %s="%s"', current(array_keys($rootAttributes)), $this->writeValue(current($rootAttributes)));
            }

            $rootOpenTag .= $rootIsEmptyTag ? ' />' : '>';

            if ($rootIsVariablePrototype) {
                $rootOpenTag .= $prototypeValue.'</'.$rootName.'>';
            }

            $this->writeLine($rootOpenTag, $depth);
        } else {
            $this->writeLine($rootOpenTag, $depth);

            $i = 1;

            foreach ($rootAttributes as $attrName => $attrValue) {
                $attr = sprintf('%s="%s"', $attrName, $this->writeValue($attrValue));

                $this->writeLine($attr, $depth + 4);

                if ($attributesCount === $i++) {
                    $this->writeLine($rootIsEmptyTag ? '/>' : '>', $depth);

                    if ($rootIsVariablePrototype) {
                        $rootOpenTag .= $prototypeValue.'</'.$rootName.'>';
                    }
                }
            }
        }

        // render children tags
        foreach ($rootChildren as $child) {
            $this->writeLine('');
            $this->writeNode($child, $depth + 4);
        }

        // render end tag
        if (!$rootIsEmptyTag && !$rootIsVariablePrototype) {
            $this->writeLine('');

            $rootEndTag = '</'.$rootName.'>';
            $this->writeLine($rootEndTag, $depth);
        }
    }

    /**
     * Outputs a single config reference line
     *
     * @param string $text
     * @param int    $indent
     */
    private function writeLine($text, $indent = 0)
    {
        $indent = strlen($text) + $indent;
        $format = '%'.$indent.'s';

        $this->reference .= sprintf($format, $text)."\n";
    }

    /**
     * Renders the string conversion of the value.
     *
     * @param mixed $value
     *
     * @return string
     */
    private function writeValue($value)
    {
        if ('%%%%not_defined%%%%' === $value) {
            return '';
        }

        if (is_string($value) || is_numeric($value)) {
            return $value;
        }

        if (false === $value) {
            return 'false';
        }

        if (true === $value) {
            return 'true';
        }

        if (null === $value) {
            return 'null';
        }

        if (empty($value)) {
            return '';
        }

        if (is_array($value)) {
            return implode(',', $value);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

use Symfony\Component\Config\Definition\EnumNode;
use Symfony\Component\Config\Definition\Builder\ScalarNodeDefinition;

/**
 * Enum Node Definition.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class EnumNodeDefinition extends ScalarNodeDefinition
{
    private $values;

    public function values(array $values)
    {
        $values = array_unique($values);

        if (count($values) <= 1) {
            throw new \InvalidArgumentException('->values() must be called with at least two distinct values.');
        }

        $this->values = $values;

        return $this;
    }

    /**
     * Instantiate a Node
     *
     * @return EnumNode The node
     *
     * @throws \RuntimeException
     */
    protected function instantiateNode()
    {
        if (null === $this->values) {
            throw new \RuntimeException('You must call ->values() on enum nodes.');
        }

        return new EnumNode($this->name, $this->parent, $this->values);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

use Symfony\Component\Config\Definition\BooleanNode;

/**
 * This class provides a fluent interface for defining a node.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class BooleanNodeDefinition extends ScalarNodeDefinition
{
    /**
     * {@inheritDoc}
     */
    public function __construct($name, NodeParentInterface $parent = null)
    {
        parent::__construct($name, $parent);

        $this->nullEquivalent = true;
    }

    /**
     * Instantiate a Node
     *
     * @return BooleanNode The node
     */
    protected function instantiateNode()
    {
        return new BooleanNode($this->name, $this->parent);
    }

}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

use Symfony\Component\Config\Definition\NodeInterface;
use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;

/**
 * This class provides a fluent interface for defining a node.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
abstract class NodeDefinition implements NodeParentInterface
{
    protected $name;
    protected $normalization;
    protected $validation;
    protected $defaultValue;
    protected $default = false;
    protected $required = false;
    protected $merge;
    protected $allowEmptyValue = true;
    protected $nullEquivalent;
    protected $trueEquivalent = true;
    protected $falseEquivalent = false;

    /**
     * @var NodeParentInterface|null
     */
    protected $parent;
    protected $attributes = array();

    /**
     * Constructor
     *
     * @param string                   $name   The name of the node
     * @param NodeParentInterface|null $parent The parent
     */
    public function __construct($name, NodeParentInterface $parent = null)
    {
        $this->parent = $parent;
        $this->name = $name;
    }

    /**
     * Sets the parent node.
     *
     * @param NodeParentInterface $parent The parent
     *
     * @return NodeDefinition
     */
    public function setParent(NodeParentInterface $parent)
    {
        $this->parent = $parent;

        return $this;
    }

    /**
     * Sets info message.
     *
     * @param string $info The info text
     *
     * @return NodeDefinition
     */
    public function info($info)
    {
        return $this->attribute('info', $info);
    }

    /**
     * Sets example configuration.
     *
     * @param string|array $example
     *
     * @return NodeDefinition
     */
    public function example($example)
    {
        return $this->attribute('example', $example);
    }

    /**
     * Sets an attribute on the node.
     *
     * @param string $key
     * @param mixed $value
     *
     * @return NodeDefinition
     */
    public function attribute($key, $value)
    {
        $this->attributes[$key] = $value;

        return $this;
    }

    /**
     * Returns the parent node.
     *
     * @return NodeParentInterface|null The builder of the parent node
     */
    public function end()
    {
        return $this->parent;
    }

    /**
     * Creates the node.
     *
     * @param Boolean $forceRootNode Whether to force this node as the root node
     *
     * @return NodeInterface
     */
    public function getNode($forceRootNode = false)
    {
        if ($forceRootNode) {
            $this->parent = null;
        }

        if (null !== $this->normalization) {
            $this->normalization->before = ExprBuilder::buildExpressions($this->normalization->before);
        }

        if (null !== $this->validation) {
            $this->validation->rules = ExprBuilder::buildExpressions($this->validation->rules);
        }

        $node = $this->createNode();
        $node->setAttributes($this->attributes);

        return $node;
    }

    /**
     * Sets the default value.
     *
     * @param mixed $value The default value
     *
     * @return NodeDefinition
     */
    public function defaultValue($value)
    {
        $this->default = true;
        $this->defaultValue = $value;

        return $this;
    }

    /**
     * Sets the node as required.
     *
     * @return NodeDefinition
     */
    public function isRequired()
    {
        $this->required = true;

        return $this;
    }

    /**
     * Sets the equivalent value used when the node contains null.
     *
     * @param mixed $value
     *
     * @return NodeDefinition
     */
    public function treatNullLike($value)
    {
        $this->nullEquivalent = $value;

        return $this;
    }

    /**
     * Sets the equivalent value used when the node contains true.
     *
     * @param mixed $value
     *
     * @return NodeDefinition
     */
    public function treatTrueLike($value)
    {
        $this->trueEquivalent = $value;

        return $this;
    }

    /**
     * Sets the equivalent value used when the node contains false.
     *
     * @param mixed $value
     *
     * @return NodeDefinition
     */
    public function treatFalseLike($value)
    {
        $this->falseEquivalent = $value;

        return $this;
    }

    /**
     * Sets null as the default value.
     *
     * @return NodeDefinition
     */
    public function defaultNull()
    {
        return $this->defaultValue(null);
    }

    /**
     * Sets true as the default value.
     *
     * @return NodeDefinition
     */
    public function defaultTrue()
    {
        return $this->defaultValue(true);
    }

    /**
     * Sets false as the default value.
     *
     * @return NodeDefinition
     */
    public function defaultFalse()
    {
        return $this->defaultValue(false);
    }

    /**
     * Sets an expression to run before the normalization.
     *
     * @return ExprBuilder
     */
    public function beforeNormalization()
    {
        return $this->normalization()->before();
    }

    /**
     * Denies the node value being empty.
     *
     * @return NodeDefinition
     */
    public function cannotBeEmpty()
    {
        $this->allowEmptyValue = false;

        return $this;
    }

    /**
     * Sets an expression to run for the validation.
     *
     * The expression receives the value of the node and must return it. It can
     * modify it.
     * An exception should be thrown when the node is not valid.
     *
     * @return ExprBuilder
     */
    public function validate()
    {
        return $this->validation()->rule();
    }

    /**
     * Sets whether the node can be overwritten.
     *
     * @param Boolean $deny Whether the overwriting is forbidden or not
     *
     * @return NodeDefinition
     */
    public function cannotBeOverwritten($deny = true)
    {
        $this->merge()->denyOverwrite($deny);

        return $this;
    }

    /**
     * Gets the builder for validation rules.
     *
     * @return ValidationBuilder
     */
    protected function validation()
    {
        if (null === $this->validation) {
            $this->validation = new ValidationBuilder($this);
        }

        return $this->validation;
    }

    /**
     * Gets the builder for merging rules.
     *
     * @return MergeBuilder
     */
    protected function merge()
    {
        if (null === $this->merge) {
            $this->merge = new MergeBuilder($this);
        }

        return $this->merge;
    }

    /**
     * Gets the builder for normalization rules.
     *
     * @return NormalizationBuilder
     */
    protected function normalization()
    {
        if (null === $this->normalization) {
            $this->normalization = new NormalizationBuilder($this);
        }

        return $this->normalization;
    }

    /**
     * Instantiate and configure the node according to this definition
     *
     * @return NodeInterface $node The node instance
     *
     * @throws InvalidDefinitionException When the definition is invalid
     */
    abstract protected function createNode();

}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

/**
 * This class provides a fluent interface for building a node.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class NodeBuilder implements NodeParentInterface
{
    protected $parent;
    protected $nodeMapping;

    /**
     * Constructor
     *
     */
    public function __construct()
    {
        $this->nodeMapping = array(
            'variable'    => __NAMESPACE__.'\\VariableNodeDefinition',
            'scalar'      => __NAMESPACE__.'\\ScalarNodeDefinition',
            'boolean'     => __NAMESPACE__.'\\BooleanNodeDefinition',
            'integer'     => __NAMESPACE__.'\\IntegerNodeDefinition',
            'float'       => __NAMESPACE__.'\\FloatNodeDefinition',
            'array'       => __NAMESPACE__.'\\ArrayNodeDefinition',
            'enum'        => __NAMESPACE__.'\\EnumNodeDefinition',
        );
    }

    /**
     * Set the parent node.
     *
     * @param ParentNodeDefinitionInterface $parent The parent node
     *
     * @return NodeBuilder This node builder
     */
    public function setParent(ParentNodeDefinitionInterface $parent = null)
    {
        $this->parent = $parent;

        return $this;
    }

    /**
     * Creates a child array node.
     *
     * @param string $name The name of the node
     *
     * @return ArrayNodeDefinition The child node
     */
    public function arrayNode($name)
    {
        return $this->node($name, 'array');
    }

    /**
     * Creates a child scalar node.
     *
     * @param string $name the name of the node
     *
     * @return ScalarNodeDefinition The child node
     */
    public function scalarNode($name)
    {
        return $this->node($name, 'scalar');
    }

    /**
     * Creates a child Boolean node.
     *
     * @param string $name The name of the node
     *
     * @return BooleanNodeDefinition The child node
     */
    public function booleanNode($name)
    {
        return $this->node($name, 'boolean');
    }

    /**
     * Creates a child integer node.
     *
     * @param string $name the name of the node
     *
     * @return IntegerNodeDefinition The child node
     */
    public function integerNode($name)
    {
        return $this->node($name, 'integer');
    }

    /**
     * Creates a child float node.
     *
     * @param string $name the name of the node
     *
     * @return FloatNodeDefinition The child node
     */
    public function floatNode($name)
    {
        return $this->node($name, 'float');
    }

    /**
     * Creates a child EnumNode.
     *
     * @param string $name
     *
     * @return EnumNodeDefinition
     */
    public function enumNode($name)
    {
        return $this->node($name, 'enum');
    }

    /**
     * Creates a child variable node.
     *
     * @param string $name The name of the node
     *
     * @return VariableNodeDefinition The builder of the child node
     */
    public function variableNode($name)
    {
        return $this->node($name, 'variable');
    }

    /**
     * Returns the parent node.
     *
     * @return ParentNodeDefinitionInterface The parent node
     */
    public function end()
    {
        return $this->parent;
    }

    /**
     * Creates a child node.
     *
     * @param string $name The name of the node
     * @param string $type The type of the node
     *
     * @return NodeDefinition The child node
     *
     * @throws \RuntimeException When the node type is not registered
     * @throws \RuntimeException When the node class is not found
     */
    public function node($name, $type)
    {
        $class = $this->getNodeClass($type);

        $node = new $class($name);

        $this->append($node);

        return $node;
    }

    /**
     * Appends a node definition.
     *
     * Usage:
     *
     *     $node = new ArrayNodeDefinition('name')
     *         ->children()
     *             ->scalarNode('foo')->end()
     *             ->scalarNode('baz')->end()
     *             ->append($this->getBarNodeDefinition())
     *         ->end()
     *     ;
     *
     * @param NodeDefinition $node
     *
     * @return NodeBuilder This node builder
     */
    public function append(NodeDefinition $node)
    {
        if ($node instanceof ParentNodeDefinitionInterface) {
            $builder = clone $this;
            $builder->setParent(null);
            $node->setBuilder($builder);
        }

        if (null !== $this->parent) {
            $this->parent->append($node);
            // Make this builder the node parent to allow for a fluid interface
            $node->setParent($this);
        }

        return $this;
    }

    /**
     * Adds or overrides a node Type.
     *
     * @param string $type  The name of the type
     * @param string $class The fully qualified name the node definition class
     *
     * @return NodeBuilder This node builder
     */
    public function setNodeClass($type, $class)
    {
        $this->nodeMapping[strtolower($type)] = $class;

        return $this;
    }

    /**
     * Returns the class name of the node definition.
     *
     * @param string $type The node type
     *
     * @return string The node definition class name
     *
     * @throws \RuntimeException When the node type is not registered
     * @throws \RuntimeException When the node class is not found
     */
    protected function getNodeClass($type)
    {
        $type = strtolower($type);

        if (!isset($this->nodeMapping[$type])) {
            throw new \RuntimeException(sprintf('The node type "%s" is not registered.', $type));
        }

        $class = $this->nodeMapping[$type];

        if (!class_exists($class)) {
            throw new \RuntimeException(sprintf('The node class "%s" does not exist.', $class));
        }

        return $class;
    }

}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

use Symfony\Component\Config\Definition\FloatNode;

/**
 * This class provides a fluent interface for defining a float node.
 *
 * @author Jeanmonod David <david.jeanmonod@gmail.com>
 */
class FloatNodeDefinition extends NumericNodeDefinition
{
    /**
     * Instantiates a Node.
     *
     * @return FloatNode The node
     */
    protected function instantiateNode()
    {
        return new FloatNode($this->name, $this->parent, $this->min, $this->max);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

use Symfony\Component\Config\Definition\ArrayNode;
use Symfony\Component\Config\Definition\PrototypedArrayNode;
use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;

/**
 * This class provides a fluent interface for defining an array node.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinitionInterface
{
    protected $performDeepMerging = true;
    protected $ignoreExtraKeys = false;
    protected $children = array();
    protected $prototype;
    protected $atLeastOne = false;
    protected $allowNewKeys = true;
    protected $key;
    protected $removeKeyItem;
    protected $addDefaults = false;
    protected $addDefaultChildren = false;
    protected $nodeBuilder;
    protected $normalizeKeys = true;

    /**
     * {@inheritDoc}
     */
    public function __construct($name, NodeParentInterface $parent = null)
    {
        parent::__construct($name, $parent);

        $this->nullEquivalent = array();
        $this->trueEquivalent = array();
    }

    /**
     * Sets a custom children builder.
     *
     * @param NodeBuilder $builder A custom NodeBuilder
     */
    public function setBuilder(NodeBuilder $builder)
    {
        $this->nodeBuilder = $builder;
    }

    /**
     * Returns a builder to add children nodes.
     *
     * @return NodeBuilder
     */
    public function children()
    {
        return $this->getNodeBuilder();
    }

    /**
     * Sets a prototype for child nodes.
     *
     * @param string $type the type of node
     *
     * @return NodeDefinition
     */
    public function prototype($type)
    {
        return $this->prototype = $this->getNodeBuilder()->node(null, $type)->setParent($this);
    }

    /**
     * Adds the default value if the node is not set in the configuration.
     *
     * This method is applicable to concrete nodes only (not to prototype nodes).
     * If this function has been called and the node is not set during the finalization
     * phase, it's default value will be derived from its children default values.
     *
     * @return ArrayNodeDefinition
     */
    public function addDefaultsIfNotSet()
    {
        $this->addDefaults = true;

        return $this;
    }

    /**
     * Adds children with a default value when none are defined.
     *
     * @param integer|string|array|null $children The number of children|The child name|The children names to be added
     *
     * This method is applicable to prototype nodes only.
     *
     * @return ArrayNodeDefinition
     */
    public function addDefaultChildrenIfNoneSet($children = null)
    {
        $this->addDefaultChildren = $children;

        return $this;
    }

    /**
     * Requires the node to have at least one element.
     *
     * This method is applicable to prototype nodes only.
     *
     * @return ArrayNodeDefinition
     */
    public function requiresAtLeastOneElement()
    {
        $this->atLeastOne = true;

        return $this;
    }

    /**
     * Disallows adding news keys in a subsequent configuration.
     *
     * If used all keys have to be defined in the same configuration file.
     *
     * @return ArrayNodeDefinition
     */
    public function disallowNewKeysInSubsequentConfigs()
    {
        $this->allowNewKeys = false;

        return $this;
    }

    /**
     * Sets a normalization rule for XML configurations.
     *
     * @param string $singular The key to remap
     * @param string $plural   The plural of the key for irregular plurals
     *
     * @return ArrayNodeDefinition
     */
    public function fixXmlConfig($singular, $plural = null)
    {
        $this->normalization()->remap($singular, $plural);

        return $this;
    }

    /**
     * Sets the attribute which value is to be used as key.
     *
     * This is useful when you have an indexed array that should be an
     * associative array. You can select an item from within the array
     * to be the key of the particular item. For example, if "id" is the
     * "key", then:
     *
     *     array(
     *         array('id' => 'my_name', 'foo' => 'bar'),
     *     );
     *
     *   becomes
     *
     *     array(
     *         'my_name' => array('foo' => 'bar'),
     *     );
     *
     * If you'd like "'id' => 'my_name'" to still be present in the resulting
     * array, then you can set the second argument of this method to false.
     *
     * This method is applicable to prototype nodes only.
     *
     * @param string  $name          The name of the key
     * @param Boolean $removeKeyItem Whether or not the key item should be removed.
     *
     * @return ArrayNodeDefinition
     */
    public function useAttributeAsKey($name, $removeKeyItem = true)
    {
        $this->key = $name;
        $this->removeKeyItem = $removeKeyItem;

        return $this;
    }

    /**
     * Sets whether the node can be unset.
     *
     * @param Boolean $allow
     *
     * @return ArrayNodeDefinition
     */
    public function canBeUnset($allow = true)
    {
        $this->merge()->allowUnset($allow);

        return $this;
    }

    /**
     * Adds an "enabled" boolean to enable the current section.
     *
     * By default, the section is disabled. If any configuration is specified then
     * the node will be automatically enabled:
     *
     * enableableArrayNode: {enabled: true, ...}   # The config is enabled & default values get overridden
     * enableableArrayNode: ~                      # The config is enabled & use the default values
     * enableableArrayNode: true                   # The config is enabled & use the default values
     * enableableArrayNode: {other: value, ...}    # The config is enabled & default values get overridden
     * enableableArrayNode: {enabled: false, ...}  # The config is disabled
     * enableableArrayNode: false                  # The config is disabled
     *
     * @return ArrayNodeDefinition
     */
    public function canBeEnabled()
    {
        $this
            ->addDefaultsIfNotSet()
            ->treatFalseLike(array('enabled' => false))
            ->treatTrueLike(array('enabled' => true))
            ->treatNullLike(array('enabled' => true))
            ->beforeNormalization()
                ->ifArray()
                ->then(function($v) {
                    $v['enabled'] = isset($v['enabled']) ? $v['enabled'] : true;

                    return $v;
                })
            ->end()
            ->children()
                ->booleanNode('enabled')
                    ->defaultFalse()
        ;

        return $this;
    }

    /**
     * Adds an "enabled" boolean to enable the current section.
     *
     * By default, the section is enabled.
     *
     * @return ArrayNodeDefinition
     */
    public function canBeDisabled()
    {
        $this
            ->addDefaultsIfNotSet()
            ->treatFalseLike(array('enabled' => false))
            ->treatTrueLike(array('enabled' => true))
            ->treatNullLike(array('enabled' => true))
            ->children()
                ->booleanNode('enabled')
                    ->defaultTrue()
        ;

        return $this;
    }

    /**
     * Disables the deep merging of the node.
     *
     * @return ArrayNodeDefinition
     */
    public function performNoDeepMerging()
    {
        $this->performDeepMerging = false;

        return $this;
    }

    /**
     * Allows extra config keys to be specified under an array without
     * throwing an exception.
     *
     * Those config values are simply ignored. This should be used only
     * in special cases where you want to send an entire configuration
     * array through a special tree that processes only part of the array.
     *
     * @return ArrayNodeDefinition
     */
    public function ignoreExtraKeys()
    {
        $this->ignoreExtraKeys = true;

        return $this;
    }

    /**
     * Sets key normalization.
     *
     * @param Boolean $bool Whether to enable key normalization
     *
     * @return ArrayNodeDefinition
     */
    public function normalizeKeys($bool)
    {
        $this->normalizeKeys = (Boolean) $bool;

        return $this;
    }

    /**
     * Appends a node definition.
     *
     *     $node = new ArrayNodeDefinition()
     *         ->children()
     *             ->scalarNode('foo')->end()
     *             ->scalarNode('baz')->end()
     *         ->end()
     *         ->append($this->getBarNodeDefinition())
     *     ;
     *
     * @param NodeDefinition $node A NodeDefinition instance
     *
     * @return ArrayNodeDefinition This node
     */
    public function append(NodeDefinition $node)
    {
        $this->children[$node->name] = $node->setParent($this);

        return $this;
    }

    /**
     * Returns a node builder to be used to add children and prototype
     *
     * @return NodeBuilder The node builder
     */
    protected function getNodeBuilder()
    {
        if (null === $this->nodeBuilder) {
            $this->nodeBuilder = new NodeBuilder();
        }

        return $this->nodeBuilder->setParent($this);
    }

    /**
     * {@inheritDoc}
     */
    protected function createNode()
    {
        if (null === $this->prototype) {
            $node = new ArrayNode($this->name, $this->parent);

            $this->validateConcreteNode($node);

            $node->setAddIfNotSet($this->addDefaults);

            foreach ($this->children as $child) {
                $child->parent = $node;
                $node->addChild($child->getNode());
            }
        } else {
            $node = new PrototypedArrayNode($this->name, $this->parent);

            $this->validatePrototypeNode($node);

            if (null !== $this->key) {
                $node->setKeyAttribute($this->key, $this->removeKeyItem);
            }

            if (true === $this->atLeastOne) {
                $node->setMinNumberOfElements(1);
            }

            if ($this->default) {
                $node->setDefaultValue($this->defaultValue);
            }

            if (false !== $this->addDefaultChildren) {
                $node->setAddChildrenIfNoneSet($this->addDefaultChildren);
                if ($this->prototype instanceof static && null === $this->prototype->prototype) {
                    $this->prototype->addDefaultsIfNotSet();
                }
            }

            $this->prototype->parent = $node;
            $node->setPrototype($this->prototype->getNode());
        }

        $node->setAllowNewKeys($this->allowNewKeys);
        $node->addEquivalentValue(null, $this->nullEquivalent);
        $node->addEquivalentValue(true, $this->trueEquivalent);
        $node->addEquivalentValue(false, $this->falseEquivalent);
        $node->setPerformDeepMerging($this->performDeepMerging);
        $node->setRequired($this->required);
        $node->setIgnoreExtraKeys($this->ignoreExtraKeys);
        $node->setNormalizeKeys($this->normalizeKeys);

        if (null !== $this->normalization) {
            $node->setNormalizationClosures($this->normalization->before);
            $node->setXmlRemappings($this->normalization->remappings);
        }

        if (null !== $this->merge) {
            $node->setAllowOverwrite($this->merge->allowOverwrite);
            $node->setAllowFalse($this->merge->allowFalse);
        }

        if (null !== $this->validation) {
            $node->setFinalValidationClosures($this->validation->rules);
        }

        return $node;
    }

    /**
     * Validate the configuration of a concrete node.
     *
     * @param ArrayNode $node The related node
     *
     * @throws InvalidDefinitionException
     */
    protected function validateConcreteNode(ArrayNode $node)
    {
        $path = $node->getPath();

        if (null !== $this->key) {
            throw new InvalidDefinitionException(
                sprintf('->useAttributeAsKey() is not applicable to concrete nodes at path "%s"', $path)
            );
        }

        if (true === $this->atLeastOne) {
            throw new InvalidDefinitionException(
                sprintf('->requiresAtLeastOneElement() is not applicable to concrete nodes at path "%s"', $path)
            );
        }

        if ($this->default) {
            throw new InvalidDefinitionException(
                sprintf('->defaultValue() is not applicable to concrete nodes at path "%s"', $path)
            );
        }

        if (false !== $this->addDefaultChildren) {
            throw new InvalidDefinitionException(
                sprintf('->addDefaultChildrenIfNoneSet() is not applicable to concrete nodes at path "%s"', $path)
            );
        }
    }

    /**
     * Validate the configuration of a prototype node.
     *
     * @param PrototypedArrayNode $node The related node
     *
     * @throws InvalidDefinitionException
     */
    protected function validatePrototypeNode(PrototypedArrayNode $node)
    {
        $path = $node->getPath();

        if ($this->addDefaults) {
            throw new InvalidDefinitionException(
                sprintf('->addDefaultsIfNotSet() is not applicable to prototype nodes at path "%s"', $path)
            );
        }

        if (false !== $this->addDefaultChildren) {
            if ($this->default) {
                throw new InvalidDefinitionException(
                    sprintf('A default value and default children might not be used together at path "%s"', $path)
                );
            }

            if (null !== $this->key && (null === $this->addDefaultChildren || is_integer($this->addDefaultChildren) && $this->addDefaultChildren > 0)) {
                throw new InvalidDefinitionException(
                    sprintf('->addDefaultChildrenIfNoneSet() should set default children names as ->useAttributeAsKey() is used at path "%s"', $path)
                );
            }

            if (null === $this->key && (is_string($this->addDefaultChildren) || is_array($this->addDefaultChildren))) {
                throw new InvalidDefinitionException(
                    sprintf('->addDefaultChildrenIfNoneSet() might not set default children names as ->useAttributeAsKey() is not used at path "%s"', $path)
                );
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

use Symfony\Component\Config\Definition\IntegerNode;

/**
 * This class provides a fluent interface for defining an integer node.
 *
 * @author Jeanmonod David <david.jeanmonod@gmail.com>
 */
class IntegerNodeDefinition extends NumericNodeDefinition
{
    /**
     * Instantiates a Node.
     *
     * @return IntegerNode The node
     */
    protected function instantiateNode()
    {
        return new IntegerNode($this->name, $this->parent, $this->min, $this->max);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

/**
 * This class builds normalization conditions.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class NormalizationBuilder
{
    protected $node;
    public $before = array();
    public $remappings = array();

    /**
     * Constructor
     *
     * @param NodeDefinition $node The related node
     */
    public function __construct(NodeDefinition $node)
    {
        $this->node = $node;
    }

    /**
     * Registers a key to remap to its plural form.
     *
     * @param string $key    The key to remap
     * @param string $plural The plural of the key in case of irregular plural
     *
     * @return NormalizationBuilder
     */
    public function remap($key, $plural = null)
    {
        $this->remappings[] = array($key, null === $plural ? $key.'s' : $plural);

        return $this;
    }

    /**
     * Registers a closure to run before the normalization or an expression builder to build it if null is provided.
     *
     * @param \Closure $closure
     *
     * @return ExprBuilder|NormalizationBuilder
     */
    public function before(\Closure $closure = null)
    {
        if (null !== $closure) {
            $this->before[] = $closure;

            return $this;
        }

        return $this->before[] = new ExprBuilder($this->node);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

/**
 * This class builds merge conditions.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class MergeBuilder
{
    protected $node;
    public $allowFalse = false;
    public $allowOverwrite = true;

    /**
     * Constructor
     *
     * @param NodeDefinition $node The related node
     */
    public function __construct(NodeDefinition $node)
    {
        $this->node = $node;
    }

    /**
     * Sets whether the node can be unset.
     *
     * @param Boolean $allow
     *
     * @return MergeBuilder
     */
    public function allowUnset($allow = true)
    {
        $this->allowFalse = $allow;

        return $this;
    }

    /**
     * Sets whether the node can be overwritten.
     *
     * @param Boolean $deny Whether the overwriting is forbidden or not
     *
     * @return MergeBuilder
     */
    public function denyOverwrite($deny = true)
    {
        $this->allowOverwrite = !$deny;

        return $this;
    }

    /**
     * Returns the related node.
     *
     * @return NodeDefinition
     */
    public function end()
    {
        return $this->node;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

use Symfony\Component\Config\Definition\Exception\UnsetKeyException;

/**
 * This class builds an if expression.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Christophe Coevoet <stof@notk.org>
 */
class ExprBuilder
{
    protected $node;
    public $ifPart;
    public $thenPart;

    /**
     * Constructor
     *
     * @param NodeDefinition $node The related node
     */
    public function __construct(NodeDefinition $node)
    {
        $this->node = $node;
    }

    /**
     * Marks the expression as being always used.
     *
     * @param \Closure $then
     *
     * @return ExprBuilder
     */
    public function always(\Closure $then = null)
    {
        $this->ifPart = function($v) { return true; };

        if (null !== $then) {
            $this->thenPart = $then;
        }

        return $this;
    }

    /**
     * Sets a closure to use as tests.
     *
     * The default one tests if the value is true.
     *
     * @param \Closure $closure
     *
     * @return ExprBuilder
     */
    public function ifTrue(\Closure $closure = null)
    {
        if (null === $closure) {
            $closure = function($v) { return true === $v; };
        }

        $this->ifPart = $closure;

        return $this;
    }

    /**
     * Tests if the value is a string.
     *
     * @return ExprBuilder
     */
    public function ifString()
    {
        $this->ifPart = function($v) { return is_string($v); };

        return $this;
    }

    /**
     * Tests if the value is null.
     *
     * @return ExprBuilder
     */
    public function ifNull()
    {
        $this->ifPart = function($v) { return null === $v; };

        return $this;
    }

    /**
     * Tests if the value is an array.
     *
     * @return ExprBuilder
     */
    public function ifArray()
    {
        $this->ifPart = function($v) { return is_array($v); };

        return $this;
    }

    /**
     * Tests if the value is in an array.
     *
     * @param array $array
     *
     * @return ExprBuilder
     */
    public function ifInArray(array $array)
    {
        $this->ifPart = function($v) use ($array) { return in_array($v, $array, true); };

        return $this;
    }

    /**
     * Tests if the value is not in an array.
     *
     * @param array $array
     *
     * @return ExprBuilder
     */
    public function ifNotInArray(array $array)
    {
        $this->ifPart = function($v) use ($array) { return !in_array($v, $array, true); };

        return $this;
    }

    /**
     * Sets the closure to run if the test pass.
     *
     * @param \Closure $closure
     *
     * @return ExprBuilder
     */
    public function then(\Closure $closure)
    {
        $this->thenPart = $closure;

        return $this;
    }

    /**
     * Sets a closure returning an empty array.
     *
     * @return ExprBuilder
     */
    public function thenEmptyArray()
    {
        $this->thenPart = function($v) { return array(); };

        return $this;
    }

    /**
     * Sets a closure marking the value as invalid at validation time.
     *
     * if you want to add the value of the node in your message just use a %s placeholder.
     *
     * @param string $message
     *
     * @return ExprBuilder
     *
     * @throws \InvalidArgumentException
     */
    public function thenInvalid($message)
    {
        $this->thenPart = function ($v) use ($message) {throw new \InvalidArgumentException(sprintf($message, json_encode($v))); };

        return $this;
    }

    /**
     * Sets a closure unsetting this key of the array at validation time.
     *
     * @return ExprBuilder
     *
     * @throws UnsetKeyException
     */
    public function thenUnset()
    {
        $this->thenPart = function ($v) { throw new UnsetKeyException('Unsetting key'); };

        return $this;
    }

    /**
     * Returns the related node
     *
     * @return NodeDefinition
     *
     * @throws \RuntimeException
     */
    public function end()
    {
        if (null === $this->ifPart) {
            throw new \RuntimeException('You must specify an if part.');
        }
        if (null === $this->thenPart) {
            throw new \RuntimeException('You must specify a then part.');
        }

        return $this->node;
    }

    /**
     * Builds the expressions.
     *
     * @param ExprBuilder[] $expressions An array of ExprBuilder instances to build
     *
     * @return array
     */
    public static function buildExpressions(array $expressions)
    {
        foreach ($expressions as $k => $expr) {
            if ($expr instanceof ExprBuilder) {
                $expressions[$k] = function($v) use ($expr) {
                    return call_user_func($expr->ifPart, $v) ? call_user_func($expr->thenPart, $v) : $v;
                };
            }
        }

        return $expressions;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

/**
 * An interface that must be implemented by all node parents
 *
 * @author Victor Berchet <victor@suumit.com>
 */
interface NodeParentInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

use Symfony\Component\Config\Definition\VariableNode;

/**
 * This class provides a fluent interface for defining a node.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class VariableNodeDefinition extends NodeDefinition
{
    /**
     * Instantiate a Node
     *
     * @return VariableNode The node
     */
    protected function instantiateNode()
    {
        return new VariableNode($this->name, $this->parent);
    }

    /**
     * {@inheritDoc}
     */
    protected function createNode()
    {
        $node = $this->instantiateNode();

        if (null !== $this->normalization) {
            $node->setNormalizationClosures($this->normalization->before);
        }

        if (null !== $this->merge) {
            $node->setAllowOverwrite($this->merge->allowOverwrite);
        }

        if (true === $this->default) {
            $node->setDefaultValue($this->defaultValue);
        }

        $node->setAllowEmptyValue($this->allowEmptyValue);
        $node->addEquivalentValue(null, $this->nullEquivalent);
        $node->addEquivalentValue(true, $this->trueEquivalent);
        $node->addEquivalentValue(false, $this->falseEquivalent);
        $node->setRequired($this->required);

        if (null !== $this->validation) {
            $node->setFinalValidationClosures($this->validation->rules);
        }

        return $node;
    }

}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

use Symfony\Component\Config\Definition\ScalarNode;

/**
 * This class provides a fluent interface for defining a node.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ScalarNodeDefinition extends VariableNodeDefinition
{
    /**
     * Instantiate a Node
     *
     * @return ScalarNode The node
     */
    protected function instantiateNode()
    {
        return new ScalarNode($this->name, $this->parent);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

/**
 * Abstract class that contain common code of integer and float node definition.
 *
 * @author David Jeanmonod <david.jeanmonod@gmail.com>
 */
abstract class NumericNodeDefinition extends ScalarNodeDefinition
{
    protected $min;
    protected $max;

    /**
     * Ensures that the value is smaller than the given reference.
     *
     * @param mixed $max
     *
     * @return NumericNodeDefinition
     *
     * @throws \InvalidArgumentException when the constraint is inconsistent
     */
    public function max($max)
    {
        if (isset($this->min) && $this->min > $max) {
            throw new \InvalidArgumentException(sprintf('You cannot define a max(%s) as you already have a min(%s)', $max, $this->min));
        }
        $this->max = $max;

        return $this;
    }

    /**
     * Ensures that the value is bigger than the given reference.
     *
     * @param mixed $min
     *
     * @return NumericNodeDefinition
     *
     * @throws \InvalidArgumentException when the constraint is inconsistent
     */
    public function min($min)
    {
        if (isset($this->max) && $this->max < $min) {
            throw new \InvalidArgumentException(sprintf('You cannot define a min(%s) as you already have a max(%s)', $min, $this->max));
        }
        $this->min = $min;

        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

/**
 * An interface that must be implemented by nodes which can have children
 *
 * @author Victor Berchet <victor@suumit.com>
 */
interface ParentNodeDefinitionInterface
{
    public function children();

    public function append(NodeDefinition $node);

    public function setBuilder(NodeBuilder $builder);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

/**
 * This class builds validation conditions.
 *
 * @author Christophe Coevoet <stof@notk.org>
 */
class ValidationBuilder
{
    protected $node;
    public $rules = array();

    /**
     * Constructor
     *
     * @param NodeDefinition $node The related node
     */
    public function __construct(NodeDefinition $node)
    {
        $this->node = $node;
    }

    /**
     * Registers a closure to run as normalization or an expression builder to build it if null is provided.
     *
     * @param \Closure $closure
     *
     * @return ExprBuilder|ValidationBuilder
     */
    public function rule(\Closure $closure = null)
    {
        if (null !== $closure) {
            $this->rules[] = $closure;

            return $this;
        }

        return $this->rules[] = new ExprBuilder($this->node);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Builder;

use Symfony\Component\Config\Definition\NodeInterface;

/**
 * This is the entry class for building a config tree.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class TreeBuilder implements NodeParentInterface
{
    protected $tree;
    protected $root;
    protected $builder;

    /**
     * Creates the root node.
     *
     * @param string      $name    The name of the root node
     * @param string      $type    The type of the root node
     * @param NodeBuilder $builder A custom node builder instance
     *
     * @return ArrayNodeDefinition|NodeDefinition The root node (as an ArrayNodeDefinition when the type is 'array')
     *
     * @throws \RuntimeException When the node type is not supported
     */
    public function root($name, $type = 'array', NodeBuilder $builder = null)
    {
        $builder = $builder ?: new NodeBuilder();

        return $this->root = $builder->node($name, $type)->setParent($this);
    }

    /**
     * Builds the tree.
     *
     * @return NodeInterface
     *
     * @throws \RuntimeException
     */
    public function buildTree()
    {
        if (null === $this->root) {
            throw new \RuntimeException('The configuration tree has no root node.');
        }
        if (null !== $this->tree) {
            return $this->tree;
        }

        return $this->tree = $this->root->getNode(true);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

use Symfony\Component\Config\Definition\Exception\Exception;
use Symfony\Component\Config\Definition\Exception\ForbiddenOverwriteException;
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;

/**
 * The base node class
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
abstract class BaseNode implements NodeInterface
{
    protected $name;
    protected $parent;
    protected $normalizationClosures = array();
    protected $finalValidationClosures = array();
    protected $allowOverwrite = true;
    protected $required = false;
    protected $equivalentValues = array();
    protected $attributes = array();

    /**
     * Constructor.
     *
     * @param string        $name   The name of the node
     * @param NodeInterface $parent The parent of this node
     *
     * @throws \InvalidArgumentException if the name contains a period.
     */
    public function __construct($name, NodeInterface $parent = null)
    {
        if (false !== strpos($name, '.')) {
            throw new \InvalidArgumentException('The name must not contain ".".');
        }

        $this->name = $name;
        $this->parent = $parent;
    }

    public function setAttribute($key, $value)
    {
        $this->attributes[$key] = $value;
    }

    public function getAttribute($key, $default = null)
    {
        return isset($this->attributes[$key]) ? $this->attributes[$key] : $default;
    }

    public function hasAttribute($key)
    {
        return isset($this->attributes[$key]);
    }

    public function getAttributes()
    {
        return $this->attributes;
    }

    public function setAttributes(array $attributes)
    {
        $this->attributes = $attributes;
    }

    public function removeAttribute($key)
    {
        unset($this->attributes[$key]);
    }

    /**
     * Sets an info message.
     *
     * @param string $info
     */
    public function setInfo($info)
    {
        $this->setAttribute('info', $info);
    }

    /**
     * Returns info message.
     *
     * @return string The info text
     */
    public function getInfo()
    {
        return $this->getAttribute('info');
    }

    /**
     * Sets the example configuration for this node.
     *
     * @param string|array $example
     */
    public function setExample($example)
    {
        $this->setAttribute('example', $example);
    }

    /**
     * Retrieves the example configuration for this node.
     *
     * @return string|array The example
     */
    public function getExample()
    {
        return $this->getAttribute('example');
    }

    /**
     * Adds an equivalent value.
     *
     * @param mixed $originalValue
     * @param mixed $equivalentValue
     */
    public function addEquivalentValue($originalValue, $equivalentValue)
    {
        $this->equivalentValues[] = array($originalValue, $equivalentValue);
    }

    /**
     * Set this node as required.
     *
     * @param Boolean $boolean Required node
     */
    public function setRequired($boolean)
    {
        $this->required = (Boolean) $boolean;
    }

    /**
     * Sets if this node can be overridden.
     *
     * @param Boolean $allow
     */
    public function setAllowOverwrite($allow)
    {
        $this->allowOverwrite = (Boolean) $allow;
    }

    /**
     * Sets the closures used for normalization.
     *
     * @param \Closure[] $closures An array of Closures used for normalization
     */
    public function setNormalizationClosures(array $closures)
    {
        $this->normalizationClosures = $closures;
    }

    /**
     * Sets the closures used for final validation.
     *
     * @param \Closure[] $closures An array of Closures used for final validation
     */
    public function setFinalValidationClosures(array $closures)
    {
        $this->finalValidationClosures = $closures;
    }

    /**
     * Checks if this node is required.
     *
     * @return Boolean
     */
    public function isRequired()
    {
        return $this->required;
    }

    /**
     * Returns the name of this node
     *
     * @return string The Node's name.
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Retrieves the path of this node.
     *
     * @return string The Node's path
     */
    public function getPath()
    {
        $path = $this->name;

        if (null !== $this->parent) {
            $path = $this->parent->getPath().'.'.$path;
        }

        return $path;
    }

    /**
     * Merges two values together.
     *
     * @param mixed $leftSide
     * @param mixed $rightSide
     *
     * @return mixed The merged value
     *
     * @throws ForbiddenOverwriteException
     */
    final public function merge($leftSide, $rightSide)
    {
        if (!$this->allowOverwrite) {
            throw new ForbiddenOverwriteException(sprintf(
                'Configuration path "%s" cannot be overwritten. You have to '
               .'define all options for this path, and any of its sub-paths in '
               .'one configuration section.',
                $this->getPath()
            ));
        }

        $this->validateType($leftSide);
        $this->validateType($rightSide);

        return $this->mergeValues($leftSide, $rightSide);
    }

    /**
     * Normalizes a value, applying all normalization closures.
     *
     * @param mixed $value Value to normalize.
     *
     * @return mixed The normalized value.
     */
    final public function normalize($value)
    {
        $value = $this->preNormalize($value);

        // run custom normalization closures
        foreach ($this->normalizationClosures as $closure) {
            $value = $closure($value);
        }

        // replace value with their equivalent
        foreach ($this->equivalentValues as $data) {
            if ($data[0] === $value) {
                $value = $data[1];
            }
        }

        // validate type
        $this->validateType($value);

        // normalize value
        return $this->normalizeValue($value);
    }

    /**
     * Normalizes the value before any other normalization is applied.
     *
     * @param $value
     *
     * @return $value The normalized array value
     */
    protected function preNormalize($value)
    {
        return $value;
    }

    /**
     * Returns parent node for this node.
     *
     * @return NodeInterface|null
     */
    public function getParent()
    {
        return $this->parent;
    }

    /**
     * Finalizes a value, applying all finalization closures.
     *
     * @param mixed $value The value to finalize
     *
     * @return mixed The finalized value
     *
     * @throws InvalidConfigurationException
     */
    final public function finalize($value)
    {
        $this->validateType($value);

        $value = $this->finalizeValue($value);

        // Perform validation on the final value if a closure has been set.
        // The closure is also allowed to return another value.
        foreach ($this->finalValidationClosures as $closure) {
            try {
                $value = $closure($value);
            } catch (Exception $correctEx) {
                throw $correctEx;
            } catch (\Exception $invalid) {
                throw new InvalidConfigurationException(sprintf(
                    'Invalid configuration for path "%s": %s',
                    $this->getPath(),
                    $invalid->getMessage()
                ), $invalid->getCode(), $invalid);
            }
        }

        return $value;
    }

    /**
     * Validates the type of a Node.
     *
     * @param mixed $value The value to validate
     *
     * @throws InvalidTypeException when the value is invalid
     */
    abstract protected function validateType($value);

    /**
     * Normalizes the value.
     *
     * @param mixed $value The value to normalize.
     *
     * @return mixed The normalized value
     */
    abstract protected function normalizeValue($value);

    /**
     * Merges two values together.
     *
     * @param mixed $leftSide
     * @param mixed $rightSide
     *
     * @return mixed The merged value
     */
    abstract protected function mergeValues($leftSide, $rightSide);

    /**
     * Finalizes a value.
     *
     * @param mixed $value The value to finalize
     *
     * @return mixed The finalized value
     */
    abstract protected function finalizeValue($value);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

use Symfony\Component\Config\Definition\Exception\InvalidTypeException;

/**
 * This node represents a float value in the config tree.
 *
 * @author Jeanmonod David <david.jeanmonod@gmail.com>
 */
class FloatNode extends NumericNode
{
    /**
     * {@inheritDoc}
     */
    protected function validateType($value)
    {
        // Integers are also accepted, we just cast them
        if (is_int($value)) {
            $value = (float) $value;
        }

        if (!is_float($value)) {
            $ex = new InvalidTypeException(sprintf('Invalid type for path "%s". Expected float, but got %s.', $this->getPath(), gettype($value)));
            $ex->setPath($this->getPath());

            throw $ex;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

use Symfony\Component\Config\Definition\VariableNode;
use Symfony\Component\Config\Definition\Exception\InvalidTypeException;

/**
 * This node represents a scalar value in the config tree.
 *
 * The following values are considered scalars:
 *   * booleans
 *   * strings
 *   * null
 *   * integers
 *   * floats
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ScalarNode extends VariableNode
{
    /**
     * {@inheritDoc}
     */
    protected function validateType($value)
    {
        if (!is_scalar($value) && null !== $value) {
            $ex = new InvalidTypeException(sprintf(
                'Invalid type for path "%s". Expected scalar, but got %s.',
                $this->getPath(),
                gettype($value)
            ));
            $ex->setPath($this->getPath());

            throw $ex;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use Symfony\Component\Config\Definition\Exception\DuplicateKeyException;
use Symfony\Component\Config\Definition\Exception\UnsetKeyException;
use Symfony\Component\Config\Definition\Exception\Exception;

/**
 * Represents a prototyped Array node in the config tree.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class PrototypedArrayNode extends ArrayNode
{
    protected $prototype;
    protected $keyAttribute;
    protected $removeKeyAttribute = false;
    protected $minNumberOfElements = 0;
    protected $defaultValue = array();
    protected $defaultChildren;

    /**
     * Sets the minimum number of elements that a prototype based node must
     * contain. By default this is zero, meaning no elements.
     *
     * @param integer $number
     */
    public function setMinNumberOfElements($number)
    {
        $this->minNumberOfElements = $number;
    }

    /**
     * Sets the attribute which value is to be used as key.
     *
     * This is useful when you have an indexed array that should be an
     * associative array. You can select an item from within the array
     * to be the key of the particular item. For example, if "id" is the
     * "key", then:
     *
     *     array(
     *         array('id' => 'my_name', 'foo' => 'bar'),
     *     );
     *
     *  becomes
     *
     *      array(
     *          'my_name' => array('foo' => 'bar'),
     *      );
     *
     * If you'd like "'id' => 'my_name'" to still be present in the resulting
     * array, then you can set the second argument of this method to false.
     *
     * @param string  $attribute The name of the attribute which value is to be used as a key
     * @param Boolean $remove    Whether or not to remove the key
     */
    public function setKeyAttribute($attribute, $remove = true)
    {
        $this->keyAttribute = $attribute;
        $this->removeKeyAttribute = $remove;
    }

    /**
     * Retrieves the name of the attribute which value should be used as key.
     *
     * @return string The name of the attribute
     */
    public function getKeyAttribute()
    {
        return $this->keyAttribute;
    }

    /**
     * Sets the default value of this node.
     *
     * @param string $value
     *
     * @throws \InvalidArgumentException if the default value is not an array
     */
    public function setDefaultValue($value)
    {
        if (!is_array($value)) {
            throw new \InvalidArgumentException($this->getPath().': the default value of an array node has to be an array.');
        }

        $this->defaultValue = $value;
    }

    /**
     * Checks if the node has a default value.
     *
     * @return Boolean
     */
    public function hasDefaultValue()
    {
        return true;
    }

    /**
     * Adds default children when none are set.
     *
     * @param integer|string|array|null $children The number of children|The child name|The children names to be added
     */
    public function setAddChildrenIfNoneSet($children = array('defaults'))
    {
        if (null === $children) {
            $this->defaultChildren = array('defaults');
        } else {
            $this->defaultChildren = is_integer($children) && $children > 0 ? range(1, $children) : (array) $children;
        }
    }

    /**
     * Retrieves the default value.
     *
     * The default value could be either explicited or derived from the prototype
     * default value.
     *
     * @return array The default value
     */
    public function getDefaultValue()
    {
        if (null !== $this->defaultChildren) {
            $default = $this->prototype->hasDefaultValue() ? $this->prototype->getDefaultValue() : array();
            $defaults = array();
            foreach (array_values($this->defaultChildren) as $i => $name) {
                $defaults[null === $this->keyAttribute ? $i : $name] = $default;
            }

            return $defaults;
        }

        return $this->defaultValue;
    }

    /**
     * Sets the node prototype.
     *
     * @param PrototypeNodeInterface $node
     */
    public function setPrototype(PrototypeNodeInterface $node)
    {
        $this->prototype = $node;
    }

    /**
     * Retrieves the prototype
     *
     * @return PrototypeNodeInterface The prototype
     */
    public function getPrototype()
    {
        return $this->prototype;
    }

    /**
     * Disable adding concrete children for prototyped nodes.
     *
     * @param NodeInterface $node The child node to add
     *
     * @throws Exception
     */
    public function addChild(NodeInterface $node)
    {
        throw new Exception('A prototyped array node can not have concrete children.');
    }

    /**
     * Finalizes the value of this node.
     *
     * @param mixed $value
     *
     * @return mixed The finalized value
     *
     * @throws UnsetKeyException
     * @throws InvalidConfigurationException if the node doesn't have enough children
     */
    protected function finalizeValue($value)
    {
        if (false === $value) {
            $msg = sprintf('Unsetting key for path "%s", value: %s', $this->getPath(), json_encode($value));
            throw new UnsetKeyException($msg);
        }

        foreach ($value as $k => $v) {
            $this->prototype->setName($k);
            try {
                $value[$k] = $this->prototype->finalize($v);
            } catch (UnsetKeyException $unset) {
                unset($value[$k]);
            }
        }

        if (count($value) < $this->minNumberOfElements) {
            $msg = sprintf('The path "%s" should have at least %d element(s) defined.', $this->getPath(), $this->minNumberOfElements);
            $ex = new InvalidConfigurationException($msg);
            $ex->setPath($this->getPath());

            throw $ex;
        }

        return $value;
    }

    /**
     * Normalizes the value.
     *
     * @param mixed $value The value to normalize
     *
     * @return mixed The normalized value
     *
     * @throws InvalidConfigurationException
     * @throws DuplicateKeyException
     */
    protected function normalizeValue($value)
    {
        if (false === $value) {
            return $value;
        }

        $value = $this->remapXml($value);

        $isAssoc = array_keys($value) !== range(0, count($value) -1);
        $normalized = array();
        foreach ($value as $k => $v) {
            if (null !== $this->keyAttribute && is_array($v)) {
                if (!isset($v[$this->keyAttribute]) && is_int($k) && !$isAssoc) {
                    $msg = sprintf('The attribute "%s" must be set for path "%s".', $this->keyAttribute, $this->getPath());
                    $ex = new InvalidConfigurationException($msg);
                    $ex->setPath($this->getPath());

                    throw $ex;
                } elseif (isset($v[$this->keyAttribute])) {
                    $k = $v[$this->keyAttribute];

                    // remove the key attribute when required
                    if ($this->removeKeyAttribute) {
                        unset($v[$this->keyAttribute]);
                    }

                    // if only "value" is left
                    if (1 == count($v) && isset($v['value'])) {
                        $v = $v['value'];
                    }
                }

                if (array_key_exists($k, $normalized)) {
                    $msg = sprintf('Duplicate key "%s" for path "%s".', $k, $this->getPath());
                    $ex = new DuplicateKeyException($msg);
                    $ex->setPath($this->getPath());

                    throw $ex;
                }
            }

            $this->prototype->setName($k);
            if (null !== $this->keyAttribute || $isAssoc) {
                $normalized[$k] = $this->prototype->normalize($v);
            } else {
                $normalized[] = $this->prototype->normalize($v);
            }
        }

        return $normalized;
    }

    /**
     * Merges values together.
     *
     * @param mixed $leftSide  The left side to merge.
     * @param mixed $rightSide The right side to merge.
     *
     * @return mixed The merged values
     *
     * @throws InvalidConfigurationException
     * @throws \RuntimeException
     */
    protected function mergeValues($leftSide, $rightSide)
    {
        if (false === $rightSide) {
            // if this is still false after the last config has been merged the
            // finalization pass will take care of removing this key entirely
            return false;
        }

        if (false === $leftSide || !$this->performDeepMerging) {
            return $rightSide;
        }

        foreach ($rightSide as $k => $v) {
            // prototype, and key is irrelevant, so simply append the element
            if (null === $this->keyAttribute) {
                $leftSide[] = $v;
                continue;
            }

            // no conflict
            if (!array_key_exists($k, $leftSide)) {
                if (!$this->allowNewKeys) {
                    $ex = new InvalidConfigurationException(sprintf(
                        'You are not allowed to define new elements for path "%s". ' .
                        'Please define all elements for this path in one config file.',
                        $this->getPath()
                    ));
                    $ex->setPath($this->getPath());

                    throw $ex;
                }

                $leftSide[$k] = $v;
                continue;
            }

            $this->prototype->setName($k);
            $leftSide[$k] = $this->prototype->merge($leftSide[$k], $v);
        }

        return $leftSide;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;

/**
 * This node represents a value of variable type in the config tree.
 *
 * This node is intended for values of arbitrary type.
 * Any PHP type is accepted as a value.
 *
 * @author Jeremy Mikola <jmikola@gmail.com>
 */
class VariableNode extends BaseNode implements PrototypeNodeInterface
{
    protected $defaultValueSet = false;
    protected $defaultValue;
    protected $allowEmptyValue = true;

    /**
     * {@inheritDoc}
     */
    public function setDefaultValue($value)
    {
        $this->defaultValueSet = true;
        $this->defaultValue = $value;
    }

    /**
     * {@inheritDoc}
     */
    public function hasDefaultValue()
    {
        return $this->defaultValueSet;
    }

    /**
     * {@inheritDoc}
     */
    public function getDefaultValue()
    {
        return $this->defaultValue instanceof \Closure ? call_user_func($this->defaultValue) : $this->defaultValue;
    }

    /**
     * Sets if this node is allowed to have an empty value.
     *
     * @param Boolean $boolean True if this entity will accept empty values.
     */
    public function setAllowEmptyValue($boolean)
    {
        $this->allowEmptyValue = (Boolean) $boolean;
    }

    /**
     * {@inheritDoc}
     */
    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * {@inheritDoc}
     */
    protected function validateType($value)
    {
    }

    /**
     * {@inheritDoc}
     */
    protected function finalizeValue($value)
    {
        if (!$this->allowEmptyValue && empty($value)) {
            $ex = new InvalidConfigurationException(sprintf(
                'The path "%s" cannot contain an empty value, but got %s.',
                $this->getPath(),
                json_encode($value)
            ));
            $ex->setPath($this->getPath());

            throw $ex;
        }

        return $value;
    }

    /**
     * {@inheritDoc}
     */
    protected function normalizeValue($value)
    {
        return $value;
    }

    /**
     * {@inheritDoc}
     */
    protected function mergeValues($leftSide, $rightSide)
    {
        return $rightSide;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

/**
 * Configuration interface
 *
 * @author Victor Berchet <victor@suumit.com>
 */
interface ConfigurationInterface
{
    /**
     * Generates the configuration tree builder.
     *
     * @return \Symfony\Component\Config\Definition\Builder\TreeBuilder The tree builder
     */
    public function getConfigTreeBuilder();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

/**
 * Common Interface among all nodes.
 *
 * In most cases, it is better to inherit from BaseNode instead of implementing
 * this interface yourself.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface NodeInterface
{
    /**
     * Returns the name of the node.
     *
     * @return string The name of the node
     */
    public function getName();

    /**
     * Returns the path of the node.
     *
     * @return string The node path
     */
    public function getPath();

    /**
     * Returns true when the node is required.
     *
     * @return Boolean If the node is required
     */
    public function isRequired();

    /**
     * Returns true when the node has a default value.
     *
     * @return Boolean If the node has a default value
     */
    public function hasDefaultValue();

    /**
     * Returns the default value of the node.
     *
     * @return mixed The default value
     * @throws \RuntimeException if the node has no default value
     */
    public function getDefaultValue();

    /**
     * Normalizes the supplied value.
     *
     * @param mixed $value The value to normalize
     *
     * @return mixed The normalized value
     */
    public function normalize($value);

    /**
     * Merges two values together.
     *
     * @param mixed $leftSide
     * @param mixed $rightSide
     *
     * @return mixed The merged values
     */
    public function merge($leftSide, $rightSide);

    /**
     * Finalizes a value.
     *
     * @param mixed $value The value to finalize
     *
     * @return mixed The finalized value
     */
    public function finalize($value);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use Symfony\Component\Config\Definition\ScalarNode;

/**
 * Node which only allows a finite set of values.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class EnumNode extends ScalarNode
{
    private $values;

    public function __construct($name, NodeInterface $parent = null, array $values = array())
    {
        $values = array_unique($values);
        if (count($values) <= 1) {
            throw new \InvalidArgumentException('$values must contain at least two distinct elements.');
        }

        parent::__construct($name, $parent);
        $this->values = $values;
    }

    public function getValues()
    {
        return $this->values;
    }

    protected function finalizeValue($value)
    {
        $value = parent::finalizeValue($value);

        if (!in_array($value, $this->values, true)) {
            $ex = new InvalidConfigurationException(sprintf(
                'The value %s is not allowed for path "%s". Permissible values: %s',
                json_encode($value),
                $this->getPath(),
                implode(', ', array_map('json_encode', $this->values))));
            $ex->setPath($this->getPath());

            throw $ex;
        }

        return $value;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

use Symfony\Component\Config\Definition\Dumper\YamlReferenceDumper;

/**
 * @deprecated Deprecated since version 2.4, to be removed in 3.0. Use Symfony\Component\Config\Definition\Dumper\YamlReferenceDumper instead.
 */
class ReferenceDumper extends YamlReferenceDumper
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;

/**
 * This node represents a numeric value in the config tree
 *
 * @author David Jeanmonod <david.jeanmonod@gmail.com>
 */
class NumericNode extends ScalarNode
{
    protected $min;
    protected $max;

    public function __construct($name, NodeInterface $parent = null, $min = null, $max = null)
    {
        parent::__construct($name, $parent);
        $this->min = $min;
        $this->max = $max;
    }

    /**
     * {@inheritDoc}
     */
    protected function finalizeValue($value)
    {
        $value = parent::finalizeValue($value);

        $errorMsg = null;
        if (isset($this->min) && $value < $this->min) {
            $errorMsg = sprintf('The value %s is too small for path "%s". Should be greater than or equal to %s', $value, $this->getPath(), $this->min);
        }
        if (isset($this->max) && $value > $this->max) {
            $errorMsg = sprintf('The value %s is too big for path "%s". Should be less than or equal to %s', $value, $this->getPath(), $this->max);
        }
        if (isset($errorMsg)) {
            $ex = new InvalidConfigurationException($errorMsg);
            $ex->setPath($this->getPath());
            throw $ex;
        }

        return $value;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Exception;

/**
 * Base exception for all configuration exceptions
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class Exception extends \RuntimeException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Exception;

/**
 * This exception is thrown whenever the key of an array is not unique. This can
 * only be the case if the configuration is coming from an XML file.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class DuplicateKeyException extends InvalidConfigurationException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Exception;

/**
 * This exception is thrown if an invalid type is encountered.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class InvalidTypeException extends InvalidConfigurationException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Exception;

/**
 * Thrown when an error is detected in a node Definition.
 *
 * @author Victor Berchet <victor.berchet@suumit.com>
 */
class InvalidDefinitionException extends Exception
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Exception;

/**
 * This exception is usually not encountered by the end-user, but only used
 * internally to signal the parent scope to unset a key.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class UnsetKeyException extends Exception
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Exception;

/**
 * This exception is thrown when a configuration path is overwritten from a
 * subsequent configuration file, but the entry node specifically forbids this.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ForbiddenOverwriteException extends InvalidConfigurationException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition\Exception;

/**
 * A very general exception which can be thrown whenever non of the more specific
 * exceptions is suitable.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class InvalidConfigurationException extends Exception
{
    private $path;

    public function setPath($path)
    {
        $this->path = $path;
    }

    public function getPath()
    {
        return $this->path;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Definition;

use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use Symfony\Component\Config\Definition\Exception\InvalidTypeException;
use Symfony\Component\Config\Definition\Exception\UnsetKeyException;

/**
 * Represents an Array node in the config tree.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ArrayNode extends BaseNode implements PrototypeNodeInterface
{
    protected $xmlRemappings = array();
    protected $children = array();
    protected $allowFalse = false;
    protected $allowNewKeys = true;
    protected $addIfNotSet = false;
    protected $performDeepMerging = true;
    protected $ignoreExtraKeys = false;
    protected $normalizeKeys = true;

    public function setNormalizeKeys($normalizeKeys)
    {
        $this->normalizeKeys = (Boolean) $normalizeKeys;
    }

    /**
     * Normalizes keys between the different configuration formats.
     *
     * Namely, you mostly have foo_bar in YAML while you have foo-bar in XML.
     * After running this method, all keys are normalized to foo_bar.
     *
     * If you have a mixed key like foo-bar_moo, it will not be altered.
     * The key will also not be altered if the target key already exists.
     *
     * @param mixed $value
     *
     * @return array The value with normalized keys
     */
    protected function preNormalize($value)
    {
        if (!$this->normalizeKeys || !is_array($value)) {
            return $value;
        }

        foreach ($value as $k => $v) {
            if (false !== strpos($k, '-') && false === strpos($k, '_') && !array_key_exists($normalizedKey = str_replace('-', '_', $k), $value)) {
                $value[$normalizedKey] = $v;
                unset($value[$k]);
            }
        }

        return $value;
    }

    /**
     * Retrieves the children of this node.
     *
     * @return array The children
     */
    public function getChildren()
    {
        return $this->children;
    }

    /**
     * Sets the xml remappings that should be performed.
     *
     * @param array $remappings an array of the form array(array(string, string))
     */
    public function setXmlRemappings(array $remappings)
    {
        $this->xmlRemappings = $remappings;
    }

    /**
     * Gets the xml remappings that should be performed.
     *
     * @return array $remappings an array of the form array(array(string, string))
     */
    public function getXmlRemappings()
    {
        return $this->xmlRemappings;
    }

    /**
     * Sets whether to add default values for this array if it has not been
     * defined in any of the configuration files.
     *
     * @param Boolean $boolean
     */
    public function setAddIfNotSet($boolean)
    {
        $this->addIfNotSet = (Boolean) $boolean;
    }

    /**
     * Sets whether false is allowed as value indicating that the array should be unset.
     *
     * @param Boolean $allow
     */
    public function setAllowFalse($allow)
    {
        $this->allowFalse = (Boolean) $allow;
    }

    /**
     * Sets whether new keys can be defined in subsequent configurations.
     *
     * @param Boolean $allow
     */
    public function setAllowNewKeys($allow)
    {
        $this->allowNewKeys = (Boolean) $allow;
    }

    /**
     * Sets if deep merging should occur.
     *
     * @param Boolean $boolean
     */
    public function setPerformDeepMerging($boolean)
    {
        $this->performDeepMerging = (Boolean) $boolean;
    }

    /**
     * Whether extra keys should just be ignore without an exception.
     *
     * @param Boolean $boolean To allow extra keys
     */
    public function setIgnoreExtraKeys($boolean)
    {
        $this->ignoreExtraKeys = (Boolean) $boolean;
    }

    /**
     * Sets the node Name.
     *
     * @param string $name The node's name
     */
    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * Checks if the node has a default value.
     *
     * @return Boolean
     */
    public function hasDefaultValue()
    {
        return $this->addIfNotSet;
    }

    /**
     * Retrieves the default value.
     *
     * @return array The default value
     *
     * @throws \RuntimeException if the node has no default value
     */
    public function getDefaultValue()
    {
        if (!$this->hasDefaultValue()) {
            throw new \RuntimeException(sprintf('The node at path "%s" has no default value.', $this->getPath()));
        }

        $defaults = array();
        foreach ($this->children as $name => $child) {
            if ($child->hasDefaultValue()) {
                $defaults[$name] = $child->getDefaultValue();
            }
        }

        return $defaults;
    }

    /**
     * Adds a child node.
     *
     * @param NodeInterface $node The child node to add
     *
     * @throws \InvalidArgumentException when the child node has no name
     * @throws \InvalidArgumentException when the child node's name is not unique
     */
    public function addChild(NodeInterface $node)
    {
        $name = $node->getName();
        if (empty($name)) {
            throw new \InvalidArgumentException('Child nodes must be named.');
        }
        if (isset($this->children[$name])) {
            throw new \InvalidArgumentException(sprintf('A child node named "%s" already exists.', $name));
        }

        $this->children[$name] = $node;
    }

    /**
     * Finalizes the value of this node.
     *
     * @param mixed $value
     *
     * @return mixed The finalised value
     *
     * @throws UnsetKeyException
     * @throws InvalidConfigurationException if the node doesn't have enough children
     */
    protected function finalizeValue($value)
    {
        if (false === $value) {
            $msg = sprintf('Unsetting key for path "%s", value: %s', $this->getPath(), json_encode($value));
            throw new UnsetKeyException($msg);
        }

        foreach ($this->children as $name => $child) {
            if (!array_key_exists($name, $value)) {
                if ($child->isRequired()) {
                    $msg = sprintf('The child node "%s" at path "%s" must be configured.', $name, $this->getPath());
                    $ex = new InvalidConfigurationException($msg);
                    $ex->setPath($this->getPath());

                    throw $ex;
                }

                if ($child->hasDefaultValue()) {
                    $value[$name] = $child->getDefaultValue();
                }

                continue;
            }

            try {
                $value[$name] = $child->finalize($value[$name]);
            } catch (UnsetKeyException $unset) {
                unset($value[$name]);
            }
        }

        return $value;
    }

    /**
     * Validates the type of the value.
     *
     * @param mixed $value
     *
     * @throws InvalidTypeException
     */
    protected function validateType($value)
    {
        if (!is_array($value) && (!$this->allowFalse || false !== $value)) {
            $ex = new InvalidTypeException(sprintf(
                'Invalid type for path "%s". Expected array, but got %s',
                $this->getPath(),
                gettype($value)
            ));
            $ex->setPath($this->getPath());

            throw $ex;
        }
    }

    /**
     * Normalizes the value.
     *
     * @param mixed $value The value to normalize
     *
     * @return mixed The normalized value
     *
     * @throws InvalidConfigurationException
     */
    protected function normalizeValue($value)
    {
        if (false === $value) {
            return $value;
        }

        $value = $this->remapXml($value);

        $normalized = array();
        foreach ($this->children as $name => $child) {
            if (array_key_exists($name, $value)) {
                $normalized[$name] = $child->normalize($value[$name]);
                unset($value[$name]);
            }
        }

        // if extra fields are present, throw exception
        if (count($value) && !$this->ignoreExtraKeys) {
            $msg = sprintf('Unrecognized options "%s" under "%s"', implode(', ', array_keys($value)), $this->getPath());
            $ex = new InvalidConfigurationException($msg);
            $ex->setPath($this->getPath());

            throw $ex;
        }

        return $normalized;
    }

    /**
     * Remaps multiple singular values to a single plural value.
     *
     * @param array $value The source values
     *
     * @return array The remapped values
     */
    protected function remapXml($value)
    {
        foreach ($this->xmlRemappings as $transformation) {
            list($singular, $plural) = $transformation;

            if (!isset($value[$singular])) {
                continue;
            }

            $value[$plural] = Processor::normalizeConfig($value, $singular, $plural);
            unset($value[$singular]);
        }

        return $value;
    }

    /**
     * Merges values together.
     *
     * @param mixed $leftSide  The left side to merge.
     * @param mixed $rightSide The right side to merge.
     *
     * @return mixed The merged values
     *
     * @throws InvalidConfigurationException
     * @throws \RuntimeException
     */
    protected function mergeValues($leftSide, $rightSide)
    {
        if (false === $rightSide) {
            // if this is still false after the last config has been merged the
            // finalization pass will take care of removing this key entirely
            return false;
        }

        if (false === $leftSide || !$this->performDeepMerging) {
            return $rightSide;
        }

        foreach ($rightSide as $k => $v) {
            // no conflict
            if (!array_key_exists($k, $leftSide)) {
                if (!$this->allowNewKeys) {
                    $ex = new InvalidConfigurationException(sprintf(
                        'You are not allowed to define new elements for path "%s". '
                       .'Please define all elements for this path in one config file. '
                       .'If you are trying to overwrite an element, make sure you redefine it '
                       .'with the same name.',
                        $this->getPath()
                    ));
                    $ex->setPath($this->getPath());

                    throw $ex;
                }

                $leftSide[$k] = $v;
                continue;
            }

            if (!isset($this->children[$k])) {
                throw new \RuntimeException('merge() expects a normalized config array.');
            }

            $leftSide[$k] = $this->children[$k]->merge($leftSide[$k], $v);
        }

        return $leftSide;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests;

use Symfony\Component\Config\ConfigCache;
use Symfony\Component\Config\Resource\FileResource;

class ConfigTest extends \PHPUnit_Framework_TestCase
{
    private $resourceFile = null;

    private $cacheFile = null;

    private $metaFile = null;

    public function setUp()
    {
        $this->resourceFile = tempnam(sys_get_temp_dir(), '_resource');
        $this->cacheFile = tempnam(sys_get_temp_dir(), 'config_');
        $this->metaFile = $this->cacheFile.'.meta';

        $this->makeCacheFresh();
        $this->generateMetaFile();
    }

    public function tearDown()
    {
        $files = array($this->cacheFile, $this->metaFile, $this->resourceFile);

        foreach ($files as $file) {
            if (file_exists($file)) {
                unlink($file);
            }
        }
    }

    public function testToString()
    {
        $cache = new ConfigCache($this->cacheFile, true);

        $this->assertSame($this->cacheFile, (string) $cache);
    }

    public function testCacheIsNotFreshIfFileDoesNotExist()
    {
        unlink($this->cacheFile);

        $cache = new ConfigCache($this->cacheFile, false);

        $this->assertFalse($cache->isFresh());
    }

    public function testCacheIsAlwaysFreshIfFileExistsWithDebugDisabled()
    {
        $this->makeCacheStale();

        $cache = new ConfigCache($this->cacheFile, false);

        $this->assertTrue($cache->isFresh());
    }

    public function testCacheIsNotFreshWithoutMetaFile()
    {
        unlink($this->metaFile);

        $cache = new ConfigCache($this->cacheFile, true);

        $this->assertFalse($cache->isFresh());
    }

    public function testCacheIsFreshIfResourceIsFresh()
    {
        $cache = new ConfigCache($this->cacheFile, true);

        $this->assertTrue($cache->isFresh());
    }

    public function testCacheIsNotFreshIfOneOfTheResourcesIsNotFresh()
    {
        $this->makeCacheStale();

        $cache = new ConfigCache($this->cacheFile, true);

        $this->assertFalse($cache->isFresh());
    }

    public function testWriteDumpsFile()
    {
        unlink($this->cacheFile);
        unlink($this->metaFile);

        $cache = new ConfigCache($this->cacheFile, false);
        $cache->write('FOOBAR');

        $this->assertFileExists($this->cacheFile, 'Cache file is created');
        $this->assertSame('FOOBAR', file_get_contents($this->cacheFile));
        $this->assertFileNotExists($this->metaFile, 'Meta file is not created');
    }

    public function testWriteDumpsMetaFileWithDebugEnabled()
    {
        unlink($this->cacheFile);
        unlink($this->metaFile);

        $metadata = array(new FileResource($this->resourceFile));

        $cache = new ConfigCache($this->cacheFile, true);
        $cache->write('FOOBAR', $metadata);

        $this->assertFileExists($this->cacheFile, 'Cache file is created');
        $this->assertFileExists($this->metaFile, 'Meta file is created');
        $this->assertSame(serialize($metadata), file_get_contents($this->metaFile));
    }

    private function makeCacheFresh()
    {
        touch($this->resourceFile, filemtime($this->cacheFile) - 3600);
    }

    private function makeCacheStale()
    {
        touch($this->cacheFile, time() - 3600);
    }

    private function generateMetaFile()
    {
        file_put_contents($this->metaFile, serialize(array(new FileResource($this->resourceFile))));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition\Builder;

use Symfony\Component\Config\Definition\Builder\NodeDefinition;

class BarNodeDefinition extends NodeDefinition
{
    protected function createNode()
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition\Builder;

use Symfony\Component\Config\Definition\Builder\NodeBuilder as BaseNodeBuilder;

class NodeBuilder extends BaseNodeBuilder
{
    public function barNode($name)
    {
        return $this->node($name, 'bar');
    }

    protected function getNodeClass($type)
    {
        switch ($type) {
            case 'variable':
                return __NAMESPACE__.'\\'.ucfirst($type).'NodeDefinition';
            case 'bar':
                return __NAMESPACE__.'\\'.ucfirst($type).'NodeDefinition';
            default:
                return parent::getNodeClass($type);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition\Builder;

use Symfony\Component\Config\Definition\Builder\VariableNodeDefinition as BaseVariableNodeDefinition;

class VariableNodeDefinition extends BaseVariableNodeDefinition
{
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE scan [<!ENTITY test SYSTEM "php://filter/read=convert.base64-encode/resource={{ resource }}">]>
<scan></scan>
<?xml version="1.0" encoding="UTF-8"?>
<root>
<?xml version="1.0" encoding="UTF-8"?>

<xsd:schema xmlns="http://example.com/schema"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://example.com/schema"
    elementFormDefault="qualified">

  <xsd:element name="root" />
</xsd:schema>
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="http://example.com/schema">
</root>
<?xml version="1.0" encoding="UTF-8"?>
<root2 xmlns="http://example.com/schema" />
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Fixtures\Configuration;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

class ExampleConfiguration implements ConfigurationInterface
{
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();
        $rootNode = $treeBuilder->root('acme_root');

        $rootNode
            ->fixXmlConfig('parameter')
            ->fixXmlConfig('connection')
            ->children()
                ->booleanNode('boolean')->defaultTrue()->end()
                ->scalarNode('scalar_empty')->end()
                ->scalarNode('scalar_null')->defaultNull()->end()
                ->scalarNode('scalar_true')->defaultTrue()->end()
                ->scalarNode('scalar_false')->defaultFalse()->end()
                ->scalarNode('scalar_default')->defaultValue('default')->end()
                ->scalarNode('scalar_array_empty')->defaultValue(array())->end()
                ->scalarNode('scalar_array_defaults')->defaultValue(array('elem1', 'elem2'))->end()
                ->scalarNode('scalar_required')->isRequired()->end()
                ->enumNode('enum')->values(array('this', 'that'))->end()
                ->arrayNode('array')
                    ->info('some info')
                    ->canBeUnset()
                    ->children()
                        ->scalarNode('child1')->end()
                        ->scalarNode('child2')->end()
                        ->scalarNode('child3')
                            ->info(
                                "this is a long\n".
                                "multi-line info text\n".
                                "which should be indented"
                            )
                            ->example('example setting')
                        ->end()
                    ->end()
                ->end()
                ->arrayNode('parameters')
                    ->useAttributeAsKey('name')
                    ->prototype('scalar')->end()
                ->end()
                ->arrayNode('connections')
                    ->prototype('array')
                        ->children()
                            ->scalarNode('user')->end()
                            ->scalarNode('pass')->end()
                        ->end()
                    ->end()
                ->end()
            ->end()
        ;

        return $treeBuilder;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Loader;

use Symfony\Component\Config\Util\XmlUtils;

class XmlUtilsTest extends \PHPUnit_Framework_TestCase
{
    public function testLoadFile()
    {
        $fixtures = __DIR__.'/../Fixtures/Util/';

        try {
            XmlUtils::loadFile($fixtures.'invalid.xml');
            $this->fail();
        } catch (\InvalidArgumentException $e) {
            $this->assertContains('ERROR 77', $e->getMessage());
        }

        try {
            XmlUtils::loadFile($fixtures.'document_type.xml');
            $this->fail();
        } catch (\InvalidArgumentException $e) {
            $this->assertContains('Document types are not allowed', $e->getMessage());
        }

        try {
            XmlUtils::loadFile($fixtures.'invalid_schema.xml', $fixtures.'schema.xsd');
            $this->fail();
        } catch (\InvalidArgumentException $e) {
            $this->assertContains('ERROR 1845', $e->getMessage());
        }

        try {
            XmlUtils::loadFile($fixtures.'invalid_schema.xml', 'invalid_callback_or_file');
            $this->fail();
        } catch (\InvalidArgumentException $e) {
            $this->assertContains('XSD file or callable', $e->getMessage());
        }

        $mock = $this->getMock(__NAMESPACE__.'\Validator');
        $mock->expects($this->exactly(2))->method('validate')->will($this->onConsecutiveCalls(false, true));

        try {
            XmlUtils::loadFile($fixtures.'valid.xml', array($mock, 'validate'));
            $this->fail();
        } catch (\InvalidArgumentException $e) {
            $this->assertContains('is not valid', $e->getMessage());
        }

        $this->assertInstanceOf('DOMDocument', XmlUtils::loadFile($fixtures.'valid.xml', array($mock, 'validate')));
    }

    /**
     * @dataProvider getDataForConvertDomToArray
     */
    public function testConvertDomToArray($expected, $xml, $root = false, $checkPrefix = true)
    {
        $dom = new \DOMDocument();
        $dom->loadXML($root ? $xml : '<root>'.$xml.'</root>');

        $this->assertSame($expected, XmlUtils::convertDomElementToArray($dom->documentElement, $checkPrefix));
    }

    public function getDataForConvertDomToArray()
    {
        return array(
            array(null, ''),
            array('bar', 'bar'),
            array(array('bar' => 'foobar'), '<foo bar="foobar" />', true),
            array(array('foo' => null), '<foo />'),
            array(array('foo' => 'bar'), '<foo>bar</foo>'),
            array(array('foo' => array('foo' => 'bar')), '<foo foo="bar"/>'),
            array(array('foo' => array('foo' => 'bar')), '<foo><foo>bar</foo></foo>'),
            array(array('foo' => array('foo' => 'bar', 'value' => 'text')), '<foo foo="bar">text</foo>'),
            array(array('foo' => array('attr' => 'bar', 'foo' => 'text')), '<foo attr="bar"><foo>text</foo></foo>'),
            array(array('foo' => array('bar', 'text')), '<foo>bar</foo><foo>text</foo>'),
            array(array('foo' => array(array('foo' => 'bar'), array('foo' => 'text'))), '<foo foo="bar"/><foo foo="text" />'),
            array(array('foo' => array('foo' => array('bar', 'text'))), '<foo foo="bar"><foo>text</foo></foo>'),
            array(array('foo' => 'bar'), '<foo><!-- Comment -->bar</foo>'),
            array(array('foo' => 'text'), '<foo xmlns:h="http://www.example.org/bar" h:bar="bar">text</foo>'),
            array(array('foo' => array('bar' => 'bar', 'value' => 'text')), '<foo xmlns:h="http://www.example.org/bar" h:bar="bar">text</foo>', false, false),
            array(array('attr' => 1, 'b' => 'hello'), '<foo:a xmlns:foo="http://www.example.org/foo" xmlns:h="http://www.example.org/bar" attr="1" h:bar="bar"><foo:b>hello</foo:b><h:c>2</h:c></foo:a>', true),
        );
    }

    /**
     * @dataProvider getDataForPhpize
     */
    public function testPhpize($expected, $value)
    {
        $this->assertSame($expected, XmlUtils::phpize($value));
    }

    public function getDataForPhpize()
    {
        return array(
            array('', ''),
            array(null, 'null'),
            array(true, 'true'),
            array(false, 'false'),
            array(null, 'Null'),
            array(true, 'True'),
            array(false, 'False'),
            array(0, '0'),
            array(1, '1'),
            array(-1, '-1'),
            array(0777, '0777'),
            array(255, '0xFF'),
            array(100.0, '1e2'),
            array(-120.0, '-1.2E2'),
            array(-10100.1, '-10100.1'),
            array('-10,100.1', '-10,100.1'),
            array('1234 5678 9101 1121 3141', '1234 5678 9101 1121 3141'),
            array('1,2,3,4', '1,2,3,4'),
            array('11,22,33,44', '11,22,33,44'),
            array('11,222,333,4', '11,222,333,4'),
            array('1,222,333,444', '1,222,333,444'),
            array('11,222,333,444', '11,222,333,444'),
            array('111,222,333,444', '111,222,333,444'),
            array('1111,2222,3333,4444,5555', '1111,2222,3333,4444,5555'),
            array('foo', 'foo'),
            array(6, '0b0110'),
        );
    }
}

interface Validator
{
    public function validate();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Resource;

use Symfony\Component\Config\Resource\DirectoryResource;

class DirectoryResourceTest extends \PHPUnit_Framework_TestCase
{
    protected $directory;

    protected function setUp()
    {
        $this->directory = sys_get_temp_dir().'/symfonyDirectoryIterator';
        if (!file_exists($this->directory)) {
            mkdir($this->directory);
        }
        touch($this->directory.'/tmp.xml');
    }

    protected function tearDown()
    {
        if (!is_dir($this->directory)) {
            return;
        }
        $this->removeDirectory($this->directory);
    }

    protected function removeDirectory($directory)
    {
        $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($directory), \RecursiveIteratorIterator::CHILD_FIRST);
        foreach ($iterator as $path) {
            if (preg_match('#[/\\\\]\.\.?$#', $path->__toString())) {
                continue;
            }
            if ($path->isDir()) {
               rmdir($path->__toString());
            } else {
               unlink($path->__toString());
            }
        }
        rmdir($directory);
    }

    public function testGetResource()
    {
        $resource = new DirectoryResource($this->directory);
        $this->assertSame($this->directory, $resource->getResource(), '->getResource() returns the path to the resource');
        $this->assertSame($this->directory, (string) $resource, '->__toString() returns the path to the resource');
    }

    public function testGetPattern()
    {
        $resource = new DirectoryResource('foo', 'bar');
        $this->assertEquals('bar', $resource->getPattern());
    }

    public function testIsFresh()
    {
        $resource = new DirectoryResource($this->directory);
        $this->assertTrue($resource->isFresh(time() + 10), '->isFresh() returns true if the resource has not changed');
        $this->assertFalse($resource->isFresh(time() - 86400), '->isFresh() returns false if the resource has been updated');

        $resource = new DirectoryResource('/____foo/foobar'.rand(1, 999999));
        $this->assertFalse($resource->isFresh(time()), '->isFresh() returns false if the resource does not exist');
    }

    public function testIsFreshUpdateFile()
    {
        $resource = new DirectoryResource($this->directory);
        touch($this->directory.'/tmp.xml', time() + 20);
        $this->assertFalse($resource->isFresh(time() + 10), '->isFresh() returns false if an existing file is modified');
    }

    public function testIsFreshNewFile()
    {
        $resource = new DirectoryResource($this->directory);
        touch($this->directory.'/new.xml', time() + 20);
        $this->assertFalse($resource->isFresh(time() + 10), '->isFresh() returns false if a new file is added');
    }

    public function testIsFreshDeleteFile()
    {
        $resource = new DirectoryResource($this->directory);
        unlink($this->directory.'/tmp.xml');
        $this->assertFalse($resource->isFresh(time()), '->isFresh() returns false if an existing file is removed');
    }

    public function testIsFreshDeleteDirectory()
    {
        $resource = new DirectoryResource($this->directory);
        $this->removeDirectory($this->directory);
        $this->assertFalse($resource->isFresh(time()), '->isFresh() returns false if the whole resource is removed');
    }

    public function testIsFreshCreateFileInSubdirectory()
    {
        $subdirectory = $this->directory.'/subdirectory';
        mkdir($subdirectory);

        $resource = new DirectoryResource($this->directory);
        $this->assertTrue($resource->isFresh(time() + 10), '->isFresh() returns true if an unmodified subdirectory exists');

        touch($subdirectory.'/newfile.xml', time() + 20);
        $this->assertFalse($resource->isFresh(time() + 10), '->isFresh() returns false if a new file in a subdirectory is added');
    }

    public function testIsFreshModifySubdirectory()
    {
        $resource = new DirectoryResource($this->directory);

        $subdirectory = $this->directory.'/subdirectory';
        mkdir($subdirectory);
        touch($subdirectory, time() + 20);

        $this->assertFalse($resource->isFresh(time() + 10), '->isFresh() returns false if a subdirectory is modified (e.g. a file gets deleted)');
    }

    public function testFilterRegexListNoMatch()
    {
        $resource = new DirectoryResource($this->directory, '/\.(foo|xml)$/');

        touch($this->directory.'/new.bar', time() + 20);
        $this->assertTrue($resource->isFresh(time() + 10), '->isFresh() returns true if a new file not matching the filter regex is created');
    }

    public function testFilterRegexListMatch()
    {
        $resource = new DirectoryResource($this->directory, '/\.(foo|xml)$/');

        touch($this->directory.'/new.xml', time() + 20);
        $this->assertFalse($resource->isFresh(time() + 10), '->isFresh() returns false if an new file matching the filter regex is created ');
    }

    public function testSerializeUnserialize()
    {
        $resource = new DirectoryResource($this->directory, '/\.(foo|xml)$/');

        $unserialized = unserialize(serialize($resource));

        $this->assertSame($this->directory, $resource->getResource());
        $this->assertSame('/\.(foo|xml)$/', $resource->getPattern());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Resource;

use Symfony\Component\Config\Resource\FileResource;

class FileResourceTest extends \PHPUnit_Framework_TestCase
{
    protected $resource;
    protected $file;

    protected function setUp()
    {
        $this->file = realpath(sys_get_temp_dir()).'/tmp.xml';
        touch($this->file);
        $this->resource = new FileResource($this->file);
    }

    protected function tearDown()
    {
        unlink($this->file);
    }

    public function testGetResource()
    {
        $this->assertSame(realpath($this->file), $this->resource->getResource(), '->getResource() returns the path to the resource');
    }

    public function testToString()
    {
        $this->assertSame(realpath($this->file), (string) $this->resource);
    }

    public function testIsFresh()
    {
        $this->assertTrue($this->resource->isFresh(time() + 10), '->isFresh() returns true if the resource has not changed');
        $this->assertFalse($this->resource->isFresh(time() - 86400), '->isFresh() returns false if the resource has been updated');

        $resource = new FileResource('/____foo/foobar'.rand(1, 999999));
        $this->assertFalse($resource->isFresh(time()), '->isFresh() returns false if the resource does not exist');
    }

    public function testSerializeUnserialize()
    {
        $unserialized = unserialize(serialize($this->resource));

        $this->assertSame(realpath($this->file), $this->resource->getResource());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Loader;

use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\Config\Loader\DelegatingLoader;

class DelegatingLoaderTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\Config\Loader\DelegatingLoader::__construct
     */
    public function testConstructor()
    {
        $loader = new DelegatingLoader($resolver = new LoaderResolver());
        $this->assertTrue(true, '__construct() takes a loader resolver as its first argument');
    }

    /**
     * @covers Symfony\Component\Config\Loader\DelegatingLoader::getResolver
     * @covers Symfony\Component\Config\Loader\DelegatingLoader::setResolver
     */
    public function testGetSetResolver()
    {
        $resolver = new LoaderResolver();
        $loader = new DelegatingLoader($resolver);
        $this->assertSame($resolver, $loader->getResolver(), '->getResolver() gets the resolver loader');
        $loader->setResolver($resolver = new LoaderResolver());
        $this->assertSame($resolver, $loader->getResolver(), '->setResolver() sets the resolver loader');
    }

    /**
     * @covers Symfony\Component\Config\Loader\DelegatingLoader::supports
     */
    public function testSupports()
    {
        $loader1 = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface');
        $loader1->expects($this->once())->method('supports')->will($this->returnValue(true));
        $loader = new DelegatingLoader(new LoaderResolver(array($loader1)));
        $this->assertTrue($loader->supports('foo.xml'), '->supports() returns true if the resource is loadable');

        $loader1 = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface');
        $loader1->expects($this->once())->method('supports')->will($this->returnValue(false));
        $loader = new DelegatingLoader(new LoaderResolver(array($loader1)));
        $this->assertFalse($loader->supports('foo.foo'), '->supports() returns false if the resource is not loadable');
    }

    /**
     * @covers Symfony\Component\Config\Loader\DelegatingLoader::load
     */
    public function testLoad()
    {
        $loader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface');
        $loader->expects($this->once())->method('supports')->will($this->returnValue(true));
        $loader->expects($this->once())->method('load');
        $resolver = new LoaderResolver(array($loader));
        $loader = new DelegatingLoader($resolver);

        $loader->load('foo');
    }

    /**
     * @expectedException \Symfony\Component\Config\Exception\FileLoaderLoadException
     */
    public function testLoadThrowsAnExceptionIfTheResourceCannotBeLoaded()
    {
        $loader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface');
        $loader->expects($this->once())->method('supports')->will($this->returnValue(false));
        $resolver = new LoaderResolver(array($loader));
        $loader = new DelegatingLoader($resolver);

        $loader->load('foo');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Loader;

use Symfony\Component\Config\Loader\LoaderResolver;

class LoaderResolverTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\Config\Loader\LoaderResolver::__construct
     */
    public function testConstructor()
    {
        $resolver = new LoaderResolver(array(
            $loader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface'),
        ));

        $this->assertEquals(array($loader), $resolver->getLoaders(), '__construct() takes an array of loaders as its first argument');
    }

    /**
     * @covers Symfony\Component\Config\Loader\LoaderResolver::resolve
     */
    public function testResolve()
    {
        $loader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface');
        $resolver = new LoaderResolver(array($loader));
        $this->assertFalse($resolver->resolve('foo.foo'), '->resolve() returns false if no loader is able to load the resource');

        $loader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface');
        $loader->expects($this->once())->method('supports')->will($this->returnValue(true));
        $resolver = new LoaderResolver(array($loader));
        $this->assertEquals($loader, $resolver->resolve(function () {}), '->resolve() returns the loader for the given resource');
    }

    /**
     * @covers Symfony\Component\Config\Loader\LoaderResolver::getLoaders
     * @covers Symfony\Component\Config\Loader\LoaderResolver::addLoader
     */
    public function testLoaders()
    {
        $resolver = new LoaderResolver();
        $resolver->addLoader($loader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface'));

        $this->assertEquals(array($loader), $resolver->getLoaders(), 'addLoader() adds a loader');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Loader;

use Symfony\Component\Config\Loader\Loader;

class LoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testGetSetResolver()
    {
        $resolver = $this->getMock('Symfony\Component\Config\Loader\LoaderResolverInterface');

        $loader = new ProjectLoader1();
        $loader->setResolver($resolver);

        $this->assertSame($resolver, $loader->getResolver(), '->setResolver() sets the resolver loader');
    }

    public function testResolve()
    {
        $resolvedLoader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface');

        $resolver = $this->getMock('Symfony\Component\Config\Loader\LoaderResolverInterface');
        $resolver->expects($this->once())
            ->method('resolve')
            ->with('foo.xml')
            ->will($this->returnValue($resolvedLoader));

        $loader = new ProjectLoader1();
        $loader->setResolver($resolver);

        $this->assertSame($loader, $loader->resolve('foo.foo'), '->resolve() finds a loader');
        $this->assertSame($resolvedLoader, $loader->resolve('foo.xml'), '->resolve() finds a loader');
    }

    /**
     * @expectedException \Symfony\Component\Config\Exception\FileLoaderLoadException
     */
    public function testResolveWhenResolverCannotFindLoader()
    {
        $resolver = $this->getMock('Symfony\Component\Config\Loader\LoaderResolverInterface');
        $resolver->expects($this->once())
            ->method('resolve')
            ->with('FOOBAR')
            ->will($this->returnValue(false));

        $loader = new ProjectLoader1();
        $loader->setResolver($resolver);

        $loader->resolve('FOOBAR');
    }

    public function testImport()
    {
        $resolvedLoader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface');
        $resolvedLoader->expects($this->once())
            ->method('load')
            ->with('foo')
            ->will($this->returnValue('yes'));

        $resolver = $this->getMock('Symfony\Component\Config\Loader\LoaderResolverInterface');
        $resolver->expects($this->once())
            ->method('resolve')
            ->with('foo')
            ->will($this->returnValue($resolvedLoader));

        $loader = new ProjectLoader1();
        $loader->setResolver($resolver);

        $this->assertEquals('yes', $loader->import('foo'));
    }

    public function testImportWithType()
    {
        $resolvedLoader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface');
        $resolvedLoader->expects($this->once())
            ->method('load')
            ->with('foo', 'bar')
            ->will($this->returnValue('yes'));

        $resolver = $this->getMock('Symfony\Component\Config\Loader\LoaderResolverInterface');
        $resolver->expects($this->once())
            ->method('resolve')
            ->with('foo', 'bar')
            ->will($this->returnValue($resolvedLoader));

        $loader = new ProjectLoader1();
        $loader->setResolver($resolver);

        $this->assertEquals('yes', $loader->import('foo', 'bar'));
    }
}

class ProjectLoader1 extends Loader
{
    public function load($resource, $type = null)
    {
    }

    public function supports($resource, $type = null)
    {
        return is_string($resource) && 'foo' === pathinfo($resource, PATHINFO_EXTENSION);
    }

    public function getType()
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Loader;

use Symfony\Component\Config\Loader\FileLoader;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException;

class FileLoaderTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Symfony\Component\Config\Loader\FileLoader
     */
    public function testImport()
    {
        $locatorMock = $this->getMock('Symfony\Component\Config\FileLocatorInterface');
        $locatorMock->expects($this->any())->method('locate')->will($this->onConsecutiveCalls(
                array('path/to/file1'),                    // Default
                array('path/to/file1', 'path/to/file2'),   // First is imported
                array('path/to/file1', 'path/to/file2'),   // Second is imported
                array('path/to/file1'),                    // Exception
                array('path/to/file1', 'path/to/file2')    // Exception
                ));

        $fileLoader = new TestFileLoader($locatorMock);
        $fileLoader->setCurrentDir('.');
        $fileLoader->setResolver($loaderResolver = new LoaderResolver(array($fileLoader)));

        // Default case
        $this->assertSame('path/to/file1', $fileLoader->import('my_resource'));

        // Check first file is imported if not already loading
        $this->assertSame('path/to/file1', $fileLoader->import('my_resource'));

        // Check second file is imported if first is already loading
        $fileLoader->addLoading('path/to/file1');
        $this->assertSame('path/to/file2', $fileLoader->import('my_resource'));

        // Check exception throws if first (and only available) file is already loading
        try {
            $fileLoader->import('my_resource');
            $this->fail('->import() throws a FileLoaderImportCircularReferenceException if the resource is already loading');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException', $e, '->import() throws a FileLoaderImportCircularReferenceException if the resource is already loading');
        }

        // Check exception throws if all files are already loading
        try {
            $fileLoader->addLoading('path/to/file2');
            $fileLoader->import('my_resource');
            $this->fail('->import() throws a FileLoaderImportCircularReferenceException if the resource is already loading');
        } catch (\Exception $e) {
            $this->assertInstanceOf('Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException', $e, '->import() throws a FileLoaderImportCircularReferenceException if the resource is already loading');
        }
    }
}

class TestFileLoader extends FileLoader
{
    public function load($resource, $type = null)
    {
        return $resource;
    }

    public function supports($resource, $type = null)
    {
        return true;
    }

    public function addLoading($resource)
    {
        self::$loading[$resource] = true;
    }

    public function removeLoading($resource)
    {
        unset(self::$loading[$resource]);
    }

    public function clearLoading()
    {
        self::$loading = array();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests;

use Symfony\Component\Config\FileLocator;

class FileLocatorTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getIsAbsolutePathTests
     */
    public function testIsAbsolutePath($path)
    {
        $loader = new FileLocator(array());
        $r = new \ReflectionObject($loader);
        $m = $r->getMethod('isAbsolutePath');
        $m->setAccessible(true);

        $this->assertTrue($m->invoke($loader, $path), '->isAbsolutePath() returns true for an absolute path');
    }

    public function getIsAbsolutePathTests()
    {
        return array(
            array('/foo.xml'),
            array('c:\\\\foo.xml'),
            array('c:/foo.xml'),
            array('\\server\\foo.xml'),
            array('https://server/foo.xml'),
            array('phar://server/foo.xml'),
        );
    }

    public function testLocate()
    {
        $loader = new FileLocator(__DIR__.'/Fixtures');

        $this->assertEquals(
            __DIR__.DIRECTORY_SEPARATOR.'FileLocatorTest.php',
            $loader->locate('FileLocatorTest.php', __DIR__),
            '->locate() returns the absolute filename if the file exists in the given path'
        );

        $this->assertEquals(
            __DIR__.'/Fixtures'.DIRECTORY_SEPARATOR.'foo.xml',
            $loader->locate('foo.xml', __DIR__),
            '->locate() returns the absolute filename if the file exists in one of the paths given in the constructor'
        );

        $this->assertEquals(
            __DIR__.'/Fixtures'.DIRECTORY_SEPARATOR.'foo.xml',
            $loader->locate(__DIR__.'/Fixtures'.DIRECTORY_SEPARATOR.'foo.xml', __DIR__),
            '->locate() returns the absolute filename if the file exists in one of the paths given in the constructor'
        );

        $loader = new FileLocator(array(__DIR__.'/Fixtures', __DIR__.'/Fixtures/Again'));

        $this->assertEquals(
            array(__DIR__.'/Fixtures'.DIRECTORY_SEPARATOR.'foo.xml', __DIR__.'/Fixtures/Again'.DIRECTORY_SEPARATOR.'foo.xml'),
            $loader->locate('foo.xml', __DIR__, false),
            '->locate() returns an array of absolute filenames'
        );

        $this->assertEquals(
            array(__DIR__.'/Fixtures'.DIRECTORY_SEPARATOR.'foo.xml', __DIR__.'/Fixtures/Again'.DIRECTORY_SEPARATOR.'foo.xml'),
            $loader->locate('foo.xml', __DIR__.'/Fixtures', false),
            '->locate() returns an array of absolute filenames'
        );

        $loader = new FileLocator(__DIR__.'/Fixtures/Again');

        $this->assertEquals(
            array(__DIR__.'/Fixtures'.DIRECTORY_SEPARATOR.'foo.xml', __DIR__.'/Fixtures/Again'.DIRECTORY_SEPARATOR.'foo.xml'),
            $loader->locate('foo.xml', __DIR__.'/Fixtures', false),
            '->locate() returns an array of absolute filenames'
        );
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testLocateThrowsAnExceptionIfTheFileDoesNotExists()
    {
        $loader = new FileLocator(array(__DIR__.'/Fixtures'));

        $loader->locate('foobar.xml', __DIR__);
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testLocateThrowsAnExceptionIfTheFileDoesNotExistsInAbsolutePath()
    {
        $loader = new FileLocator(array(__DIR__.'/Fixtures'));

        $loader->locate(__DIR__.'/Fixtures/foobar.xml', __DIR__);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition;

use Symfony\Component\Config\Definition\FloatNode;

class FloatNodeTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getValidValues
     */
    public function testNormalize($value)
    {
        $node = new FloatNode('test');
        $this->assertSame($value, $node->normalize($value));
    }

    public function getValidValues()
    {
        return array(
            array(1798.0),
            array(-678.987),
            array(12.56E45),
            array(0.0),
            // Integer are accepted too, they will be cast
            array(17),
            array(-10),
            array(0)
        );
    }

    /**
     * @dataProvider getInvalidValues
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidTypeException
     */
    public function testNormalizeThrowsExceptionOnInvalidValues($value)
    {
        $node = new FloatNode('test');
        $node->normalize($value);
    }

    public function getInvalidValues()
    {
        return array(
            array(null),
            array(''),
            array('foo'),
            array(true),
            array(false),
            array(array()),
            array(array('foo' => 'bar')),
            array(new \stdClass()),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition\Dumper;

use Symfony\Component\Config\Definition\Dumper\XmlReferenceDumper;
use Symfony\Component\Config\Tests\Fixtures\Configuration\ExampleConfiguration;

class XmlReferenceDumperTest extends \PHPUnit_Framework_TestCase
{
    public function testDumper()
    {
        $configuration = new ExampleConfiguration();

        $dumper = new XmlReferenceDumper();
        $this->assertEquals($this->getConfigurationAsString(), $dumper->dump($configuration));
    }

    public function testNamespaceDumper()
    {
        $configuration = new ExampleConfiguration();

        $dumper = new XmlReferenceDumper();
        $this->assertEquals(str_replace('http://example.org/schema/dic/acme_root', 'http://symfony.com/schema/dic/symfony', $this->getConfigurationAsString()), $dumper->dump($configuration, 'http://symfony.com/schema/dic/symfony'));
    }

    private function getConfigurationAsString()
    {
      return <<<EOL
<!-- Namespace: http://example.org/schema/dic/acme_root -->
<!-- scalar-required: Required -->
<!-- enum: One of "this"; "that" -->
<config
    boolean="true"
    scalar-empty=""
    scalar-null="null"
    scalar-true="true"
    scalar-false="false"
    scalar-default="default"
    scalar-array-empty=""
    scalar-array-defaults="elem1,elem2"
    scalar-required=""
    enum=""
>

    <!-- some info -->
    <!--
        child3: this is a long
                multi-line info text
                which should be indented;
                Example: example setting
    -->
    <array
        child1=""
        child2=""
        child3=""
    />

    <!-- prototype -->
    <parameter name="parameter name">scalar value</parameter>

    <!-- prototype -->
    <connection
        user=""
        pass=""
    />

</config>

EOL;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition\Dumper;

use Symfony\Component\Config\Definition\Dumper\YamlReferenceDumper;
use Symfony\Component\Config\Tests\Fixtures\Configuration\ExampleConfiguration;

class YamlReferenceDumperTest extends \PHPUnit_Framework_TestCase
{
    public function testDumper()
    {
        $configuration = new ExampleConfiguration();

        $dumper = new YamlReferenceDumper();

        $this->markTestIncomplete('The Yaml Dumper currently does not support prototyped arrays');
        $this->assertEquals($this->getConfigurationAsString(), $dumper->dump($configuration));
    }

    private function getConfigurationAsString()
    {
      return <<<EOL
acme_root:
    boolean:              true
    scalar_empty:         ~
    scalar_null:          ~
    scalar_true:          true
    scalar_false:         false
    scalar_default:       default
    scalar_array_empty:   []
    scalar_array_defaults:

        # Defaults:
        - elem1
        - elem2
    scalar_required:      ~ # Required
    enum:                 ~ # One of "this"; "that"

    # some info
    array:
        child1:               ~
        child2:               ~

        # this is a long
        # multi-line info text
        # which should be indented
        child3:               ~ # Example: example setting
    parameters:

        # Prototype
        name:                 ~
    connections:
        # Prototype
        - { user: ~, pass: ~ }

EOL;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition\Builder;

use Symfony\Component\Config\Definition\Builder\NodeBuilder as BaseNodeBuilder;
use Symfony\Component\Config\Definition\Builder\VariableNodeDefinition as BaseVariableNodeDefinition;

class NodeBuilderTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \RuntimeException
     */
    public function testThrowsAnExceptionWhenTryingToCreateANonRegisteredNodeType()
    {
        $builder = new BaseNodeBuilder();
        $builder->node('', 'foobar');
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testThrowsAnExceptionWhenTheNodeClassIsNotFound()
    {
        $builder = new BaseNodeBuilder();
        $builder
            ->setNodeClass('noclasstype', '\\foo\\bar\\noclass')
            ->node('', 'noclasstype');
    }

    public function testAddingANewNodeType()
    {
        $class = __NAMESPACE__.'\\SomeNodeDefinition';

        $builder = new BaseNodeBuilder();
        $node = $builder
            ->setNodeClass('newtype', $class)
            ->node('', 'newtype');

        $this->assertEquals(get_class($node), $class);
    }

    public function testOverridingAnExistingNodeType()
    {
        $class = __NAMESPACE__.'\\SomeNodeDefinition';

        $builder = new BaseNodeBuilder();
        $node = $builder
            ->setNodeClass('variable', $class)
            ->node('', 'variable');

        $this->assertEquals(get_class($node), $class);
    }

    public function testNodeTypesAreNotCaseSensitive()
    {
        $builder = new BaseNodeBuilder();

        $node1 = $builder->node('', 'VaRiAbLe');
        $node2 = $builder->node('', 'variable');

        $this->assertEquals(get_class($node1), get_class($node2));

        $builder->setNodeClass('CuStOm', __NAMESPACE__.'\\SomeNodeDefinition');

        $node1 = $builder->node('', 'CUSTOM');
        $node2 = $builder->node('', 'custom');

        $this->assertEquals(get_class($node1), get_class($node2));
    }

    public function testNumericNodeCreation()
    {
        $builder = new NodeBuilder();

        $node = $builder->integerNode('foo')->min(3)->max(5);
        $this->assertEquals('Symfony\Component\Config\Definition\Builder\IntegerNodeDefinition', get_class($node));

        $node = $builder->floatNode('bar')->min(3.0)->max(5.0);
        $this->assertEquals('Symfony\Component\Config\Definition\Builder\FloatNodeDefinition', get_class($node));
    }
}

class SomeNodeDefinition extends BaseVariableNodeDefinition
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition\Builder;

use Symfony\Component\Config\Definition\Builder\IntegerNodeDefinition as NumericNodeDefinition;
use Symfony\Component\Config\Definition\Builder\IntegerNodeDefinition;
use Symfony\Component\Config\Definition\Builder\FloatNodeDefinition;

class NumericNodeDefinitionTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \InvalidArgumentException
     * @expectedExceptionMessage You cannot define a min(4) as you already have a max(3)
     */
    public function testIncoherentMinAssertion()
    {
        $def = new NumericNodeDefinition('foo');
        $def->max(3)->min(4);
    }

    /**
     * @expectedException \InvalidArgumentException
     * @expectedExceptionMessage You cannot define a max(2) as you already have a min(3)
     */
    public function testIncoherentMaxAssertion()
    {
        $node = new NumericNodeDefinition('foo');
        $node->min(3)->max(2);
    }

    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
     * @expectedExceptionMessage The value 4 is too small for path "foo". Should be greater than or equal to 5
     */
    public function testIntegerMinAssertion()
    {
        $def = new IntegerNodeDefinition('foo');
        $def->min(5)->getNode()->finalize(4);
    }

    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
     * @expectedExceptionMessage The value 4 is too big for path "foo". Should be less than or equal to 3
     */
    public function testIntegerMaxAssertion()
    {
        $def = new IntegerNodeDefinition('foo');
        $def->max(3)->getNode()->finalize(4);
    }

    public function testIntegerValidMinMaxAssertion()
    {
        $def = new IntegerNodeDefinition('foo');
        $node = $def->min(3)->max(7)->getNode();
        $this->assertEquals(4, $node->finalize(4));
    }

    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
     * @expectedExceptionMessage The value 400 is too small for path "foo". Should be greater than or equal to 500
     */
    public function testFloatMinAssertion()
    {
        $def = new FloatNodeDefinition('foo');
        $def->min(5E2)->getNode()->finalize(4e2);
    }

    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
     * @expectedExceptionMessage The value 4.3 is too big for path "foo". Should be less than or equal to 0.3
     */
    public function testFloatMaxAssertion()
    {
        $def = new FloatNodeDefinition('foo');
        $def->max(0.3)->getNode()->finalize(4.3);
    }

    public function testFloatValidMinMaxAssertion()
    {
        $def = new FloatNodeDefinition('foo');
        $node = $def->min(3.0)->max(7e2)->getNode();
        $this->assertEquals(4.5, $node->finalize(4.5));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition\Builder;

use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\Config\Definition\Processor;
use Symfony\Component\Config\Definition\Builder\ScalarNodeDefinition;
use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;

class ArrayNodeDefinitionTest extends \PHPUnit_Framework_TestCase
{
    public function testAppendingSomeNode()
    {
        $parent = new ArrayNodeDefinition('root');
        $child = new ScalarNodeDefinition('child');

        $parent
            ->children()
                ->scalarNode('foo')->end()
                ->scalarNode('bar')->end()
            ->end()
            ->append($child);

        $this->assertCount(3, $this->getField($parent, 'children'));
        $this->assertTrue(in_array($child, $this->getField($parent, 'children')));
    }

    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidDefinitionException
     * @dataProvider providePrototypeNodeSpecificCalls
     */
    public function testPrototypeNodeSpecificOption($method, $args)
    {
        $node = new ArrayNodeDefinition('root');

        call_user_func_array(array($node, $method), $args);

        $node->getNode();
    }

    public function providePrototypeNodeSpecificCalls()
    {
        return array(
            array('defaultValue', array(array())),
            array('addDefaultChildrenIfNoneSet', array()),
            array('requiresAtLeastOneElement', array()),
            array('useAttributeAsKey', array('foo'))
        );
    }

    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidDefinitionException
     */
    public function testConcreteNodeSpecificOption()
    {
        $node = new ArrayNodeDefinition('root');
        $node
            ->addDefaultsIfNotSet()
            ->prototype('array')
        ;
        $node->getNode();
    }

    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidDefinitionException
     */
    public function testPrototypeNodesCantHaveADefaultValueWhenUsingDefaultChildren()
    {
        $node = new ArrayNodeDefinition('root');
        $node
            ->defaultValue(array())
            ->addDefaultChildrenIfNoneSet('foo')
            ->prototype('array')
        ;
        $node->getNode();
    }

    public function testPrototypedArrayNodeDefaultWhenUsingDefaultChildren()
    {
        $node = new ArrayNodeDefinition('root');
        $node
            ->addDefaultChildrenIfNoneSet()
            ->prototype('array')
        ;
        $tree = $node->getNode();
        $this->assertEquals(array(array()), $tree->getDefaultValue());
    }

    /**
     * @dataProvider providePrototypedArrayNodeDefaults
     */
    public function testPrototypedArrayNodeDefault($args, $shouldThrowWhenUsingAttrAsKey, $shouldThrowWhenNotUsingAttrAsKey, $defaults)
    {
        $node = new ArrayNodeDefinition('root');
        $node
            ->addDefaultChildrenIfNoneSet($args)
            ->prototype('array')
        ;

        try {
            $tree = $node->getNode();
            $this->assertFalse($shouldThrowWhenNotUsingAttrAsKey);
            $this->assertEquals($defaults, $tree->getDefaultValue());
        } catch (InvalidDefinitionException $e) {
            $this->assertTrue($shouldThrowWhenNotUsingAttrAsKey);
        }

        $node = new ArrayNodeDefinition('root');
        $node
            ->useAttributeAsKey('attr')
            ->addDefaultChildrenIfNoneSet($args)
            ->prototype('array')
        ;

        try {
            $tree = $node->getNode();
            $this->assertFalse($shouldThrowWhenUsingAttrAsKey);
            $this->assertEquals($defaults, $tree->getDefaultValue());
        } catch (InvalidDefinitionException $e) {
            $this->assertTrue($shouldThrowWhenUsingAttrAsKey);
        }
    }

    public function providePrototypedArrayNodeDefaults()
    {
        return array(
            array(null, true, false, array(array())),
            array(2, true, false, array(array(), array())),
            array('2', false, true, array('2' => array())),
            array('foo', false, true, array('foo' => array())),
            array(array('foo'), false, true, array('foo' => array())),
            array(array('foo', 'bar'), false, true, array('foo' => array(), 'bar' => array())),
        );
    }

    public function testNestedPrototypedArrayNodes()
    {
        $node = new ArrayNodeDefinition('root');
        $node
            ->addDefaultChildrenIfNoneSet()
            ->prototype('array')
                  ->prototype('array')
        ;
        $node->getNode();
    }

    public function testEnabledNodeDefaults()
    {
        $node = new ArrayNodeDefinition('root');
        $node
            ->canBeEnabled()
            ->children()
                ->scalarNode('foo')->defaultValue('bar')->end()
        ;

        $this->assertEquals(array('enabled' => false, 'foo' => 'bar'), $node->getNode()->getDefaultValue());
    }

    /**
     * @dataProvider getEnableableNodeFixtures
     */
    public function testTrueEnableEnabledNode($expected, $config, $message)
    {
        $processor = new Processor();
        $node = new ArrayNodeDefinition('root');
        $node
            ->canBeEnabled()
            ->children()
                ->scalarNode('foo')->defaultValue('bar')->end()
        ;

        $this->assertEquals(
            $expected,
            $processor->process($node->getNode(), $config),
            $message
        );
    }

    public function getEnableableNodeFixtures()
    {
        return array(
            array(array('enabled' => true, 'foo' => 'bar'), array(true), 'true enables an enableable node'),
            array(array('enabled' => true, 'foo' => 'bar'), array(null), 'null enables an enableable node'),
            array(array('enabled' => true, 'foo' => 'bar'), array(array('enabled' => true)), 'An enableable node can be enabled'),
            array(array('enabled' => true, 'foo' => 'baz'), array(array('foo' => 'baz')), 'any configuration enables an enableable node'),
            array(array('enabled' => false, 'foo' => 'baz'), array(array('foo' => 'baz', 'enabled' => false)), 'An enableable node can be disabled'),
            array(array('enabled' => false, 'foo' => 'bar'), array(false), 'false disables an enableable node'),
        );
    }

    protected function getField($object, $field)
    {
        $reflection = new \ReflectionProperty($object, $field);
        $reflection->setAccessible(true);

        return $reflection->getValue($object);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition\Builder;

use Symfony\Component\Config\Definition\Builder\EnumNodeDefinition;

class EnumNodeDefinitionTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \InvalidArgumentException
     * @expectedExceptionMessage ->values() must be called with at least two distinct values.
     */
    public function testNoDistinctValues()
    {
        $def = new EnumNodeDefinition('foo');
        $def->values(array('foo', 'foo'));
    }

    /**
     * @expectedException \RuntimeException
     * @expectedExceptionMessage You must call ->values() on enum nodes.
     */
    public function testNoValuesPassed()
    {
        $def = new EnumNodeDefinition('foo');
        $def->getNode();
    }

    public function testGetNode()
    {
        $def = new EnumNodeDefinition('foo');
        $def->values(array('foo', 'bar'));

        $node = $def->getNode();
        $this->assertEquals(array('foo', 'bar'), $node->getValues());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition\Builder;

use Symfony\Component\Config\Tests\Definition\Builder\NodeBuilder as CustomNodeBuilder;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\Builder\NodeBuilder;

require __DIR__.'/../../Fixtures/Builder/NodeBuilder.php';
require __DIR__.'/../../Fixtures/Builder/BarNodeDefinition.php';
require __DIR__.'/../../Fixtures/Builder/VariableNodeDefinition.php';

class TreeBuilderTest extends \PHPUnit_Framework_TestCase
{
    public function testUsingACustomNodeBuilder()
    {
        $builder = new TreeBuilder();
        $root = $builder->root('custom', 'array', new CustomNodeBuilder());

        $nodeBuilder = $root->children();

        $this->assertEquals(get_class($nodeBuilder), 'Symfony\Component\Config\Tests\Definition\Builder\NodeBuilder');

        $nodeBuilder = $nodeBuilder->arrayNode('deeper')->children();

        $this->assertEquals(get_class($nodeBuilder), 'Symfony\Component\Config\Tests\Definition\Builder\NodeBuilder');
    }

    public function testOverrideABuiltInNodeType()
    {
        $builder = new TreeBuilder();
        $root = $builder->root('override', 'array', new CustomNodeBuilder());

        $definition = $root->children()->variableNode('variable');

        $this->assertEquals(get_class($definition), 'Symfony\Component\Config\Tests\Definition\Builder\VariableNodeDefinition');
    }

    public function testAddANodeType()
    {
        $builder = new TreeBuilder();
        $root = $builder->root('override', 'array', new CustomNodeBuilder());

        $definition = $root->children()->barNode('variable');

        $this->assertEquals(get_class($definition), 'Symfony\Component\Config\Tests\Definition\Builder\BarNodeDefinition');
    }

    public function testCreateABuiltInNodeTypeWithACustomNodeBuilder()
    {
        $builder = new TreeBuilder();
        $root = $builder->root('builtin', 'array', new CustomNodeBuilder());

        $definition = $root->children()->booleanNode('boolean');

        $this->assertEquals(get_class($definition), 'Symfony\Component\Config\Definition\Builder\BooleanNodeDefinition');
    }

    public function testPrototypedArrayNodeUseTheCustomNodeBuilder()
    {
        $builder = new TreeBuilder();
        $root = $builder->root('override', 'array', new CustomNodeBuilder());

        $root->prototype('bar')->end();
    }

    public function testAnExtendedNodeBuilderGetsPropagatedToTheChildren()
    {
        $builder = new TreeBuilder();

        $builder->root('propagation')
            ->children()
                ->setNodeClass('extended', 'Symfony\Component\Config\Tests\Definition\Builder\VariableNodeDefinition')
                ->node('foo', 'extended')->end()
                ->arrayNode('child')
                    ->children()
                        ->node('foo', 'extended')
                    ->end()
                ->end()
            ->end()
        ->end();
    }

    public function testDefinitionInfoGetsTransferredToNode()
    {
        $builder = new TreeBuilder();

        $builder->root('test')->info('root info')
            ->children()
                ->node('child', 'variable')->info('child info')->defaultValue('default')
            ->end()
        ->end();

        $tree = $builder->buildTree();
        $children = $tree->getChildren();

        $this->assertEquals('root info', $tree->getInfo());
        $this->assertEquals('child info', $children['child']->getInfo());
    }

    public function testDefinitionExampleGetsTransferredToNode()
    {
        $builder = new TreeBuilder();

        $builder->root('test')
            ->example(array('key' => 'value'))
            ->children()
                ->node('child', 'variable')->info('child info')->defaultValue('default')->example('example')
            ->end()
        ->end();

        $tree = $builder->buildTree();
        $children = $tree->getChildren();

        $this->assertTrue(is_array($tree->getExample()));
        $this->assertEquals('example', $children['child']->getExample());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition\Builder;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;

class ExprBuilderTest extends \PHPUnit_Framework_TestCase
{

    public function testAlwaysExpression()
    {
        $test = $this->getTestBuilder()
            ->always($this->returnClosure('new_value'))
        ->end();

        $this->assertFinalizedValueIs('new_value', $test);
    }

    public function testIfTrueExpression()
    {
        $test = $this->getTestBuilder()
            ->ifTrue()
            ->then($this->returnClosure('new_value'))
        ->end();
        $this->assertFinalizedValueIs('new_value', $test, array('key'=>true));

        $test = $this->getTestBuilder()
            ->ifTrue( function($v){ return true; })
            ->then($this->returnClosure('new_value'))
        ->end();
        $this->assertFinalizedValueIs('new_value', $test);

        $test = $this->getTestBuilder()
            ->ifTrue( function($v){ return false; })
            ->then($this->returnClosure('new_value'))
        ->end();
        $this->assertFinalizedValueIs('value',$test);
    }

    public function testIfStringExpression()
    {
        $test = $this->getTestBuilder()
            ->ifString()
            ->then($this->returnClosure('new_value'))
        ->end();
        $this->assertFinalizedValueIs('new_value', $test);

        $test = $this->getTestBuilder()
            ->ifString()
            ->then($this->returnClosure('new_value'))
        ->end();
        $this->assertFinalizedValueIs(45, $test, array('key'=>45));

    }

    public function testIfNullExpression()
    {
        $test = $this->getTestBuilder()
            ->ifNull()
            ->then($this->returnClosure('new_value'))
        ->end();
        $this->assertFinalizedValueIs('new_value', $test, array('key'=>null));

        $test = $this->getTestBuilder()
            ->ifNull()
            ->then($this->returnClosure('new_value'))
        ->end();
        $this->assertFinalizedValueIs('value', $test);
    }

    public function testIfArrayExpression()
    {
        $test = $this->getTestBuilder()
            ->ifArray()
            ->then($this->returnClosure('new_value'))
        ->end();
        $this->assertFinalizedValueIs('new_value', $test, array('key'=>array()));

        $test = $this->getTestBuilder()
            ->ifArray()
            ->then($this->returnClosure('new_value'))
        ->end();
        $this->assertFinalizedValueIs('value', $test);
    }

    public function testIfInArrayExpression()
    {
        $test = $this->getTestBuilder()
            ->ifInArray(array('foo', 'bar', 'value'))
            ->then($this->returnClosure('new_value'))
        ->end();
        $this->assertFinalizedValueIs('new_value', $test);

        $test = $this->getTestBuilder()
            ->ifInArray(array('foo', 'bar'))
            ->then($this->returnClosure('new_value'))
        ->end();
        $this->assertFinalizedValueIs('value', $test);
    }

    public function testIfNotInArrayExpression()
    {
        $test = $this->getTestBuilder()
            ->ifNotInArray(array('foo', 'bar'))
            ->then($this->returnClosure('new_value'))
        ->end();
        $this->assertFinalizedValueIs('new_value', $test);

        $test = $this->getTestBuilder()
            ->ifNotInArray(array('foo', 'bar', 'value_from_config' ))
            ->then($this->returnClosure('new_value'))
        ->end();
        $this->assertFinalizedValueIs('new_value', $test);
    }

    public function testThenEmptyArrayExpression()
    {
        $test = $this->getTestBuilder()
            ->ifString()
            ->thenEmptyArray()
        ->end();
        $this->assertFinalizedValueIs(array(), $test);
    }

    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
     */
    public function testThenInvalid()
    {
        $test = $this->getTestBuilder()
            ->ifString()
            ->thenInvalid('Invalid value')
        ->end();
        $this->finalizeTestBuilder($test);
    }

    public function testThenUnsetExpression()
    {
        $test = $this->getTestBuilder()
            ->ifString()
            ->thenUnset()
        ->end();
        $this->assertEquals(array(), $this->finalizeTestBuilder($test));
    }

    /**
     * Create a test treebuilder with a variable node, and init the validation
     * @return TreeBuilder
     */
    protected function getTestBuilder()
    {
        $builder = new TreeBuilder();

        return $builder
            ->root('test')
            ->children()
            ->variableNode('key')
            ->validate()
       ;
    }

    /**
     * Close the validation process and finalize with the given config
     * @param TreeBuilder $testBuilder The tree builder to finalize
     * @param array       $config      The config you want to use for the finalization, if nothing provided
     *                       a simple array('key'=>'value') will be used
     * @return array The finalized config values
     */
    protected function finalizeTestBuilder($testBuilder, $config = null)
    {
        return $testBuilder
            ->end()
            ->end()
            ->end()
            ->buildTree()
            ->finalize($config === null ? array('key'=>'value') : $config)
        ;
    }

    /**
     * Return a closure that will return the given value
     * @param $val The value that the closure must return
     * @return Closure
     */
    protected function returnClosure($val)
    {
        return function($v) use ($val) {
            return $val;
        };
    }

    /**
     * Assert that the given test builder, will return the given value
     *
     * @param mixed       $value       The value to test
     * @param TreeBuilder $treeBuilder The tree builder to finalize
     * @param mixed       $config      The config values that new to be finalized
     */
    protected function assertFinalizedValueIs($value, $treeBuilder, $config = null)
    {
        $this->assertEquals(array('key'=>$value), $this->finalizeTestBuilder($treeBuilder, $config));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition;

use Symfony\Component\Config\Definition\EnumNode;

class EnumNodeTest extends \PHPUnit_Framework_TestCase
{
    public function testFinalizeValue()
    {
        $node = new EnumNode('foo', null, array('foo', 'bar'));
        $this->assertSame('foo', $node->finalize('foo'));
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testConstructionWithOneValue()
    {
        new EnumNode('foo', null, array('foo', 'foo'));
    }

    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
     * @expectedExceptionMessage The value "foobar" is not allowed for path "foo". Permissible values: "foo", "bar"
     */
    public function testFinalizeWithInvalidValue()
    {
        $node = new EnumNode('foo', null, array('foo', 'bar'));
        $node->finalize('foobar');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition;

use Symfony\Component\Config\Definition\NodeInterface;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;

class NormalizerTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getEncoderTests
     */
    public function testNormalizeEncoders($denormalized)
    {
        $tb = new TreeBuilder();
        $tree = $tb
            ->root('root_name', 'array')
                ->fixXmlConfig('encoder')
                ->children()
                    ->node('encoders', 'array')
                        ->useAttributeAsKey('class')
                        ->prototype('array')
                            ->beforeNormalization()->ifString()->then(function($v) { return array('algorithm' => $v); })->end()
                            ->children()
                                ->node('algorithm', 'scalar')->end()
                            ->end()
                        ->end()
                    ->end()
                ->end()
            ->end()
            ->buildTree()
        ;

        $normalized = array(
            'encoders' => array(
                'foo' => array('algorithm' => 'plaintext'),
            ),
        );

        $this->assertNormalized($tree, $denormalized, $normalized);
    }

    public function getEncoderTests()
    {
        $configs = array();

        // XML
        $configs[] = array(
            'encoder' => array(
                array('class' => 'foo', 'algorithm' => 'plaintext'),
            ),
        );

        // XML when only one element of this type
        $configs[] = array(
            'encoder' => array('class' => 'foo', 'algorithm' => 'plaintext'),
        );

        // YAML/PHP
        $configs[] = array(
            'encoders' => array(
                array('class' => 'foo', 'algorithm' => 'plaintext'),
            ),
        );

        // YAML/PHP
        $configs[] = array(
            'encoders' => array(
                'foo' => 'plaintext',
            ),
        );

        // YAML/PHP
        $configs[] = array(
            'encoders' => array(
                'foo' => array('algorithm' => 'plaintext'),
            ),
        );

        return array_map(function($v) {
            return array($v);
        }, $configs);
    }

    /**
     * @dataProvider getAnonymousKeysTests
     */
    public function testAnonymousKeysArray($denormalized)
    {
        $tb = new TreeBuilder();
        $tree = $tb
            ->root('root', 'array')
                ->children()
                    ->node('logout', 'array')
                        ->fixXmlConfig('handler')
                        ->children()
                            ->node('handlers', 'array')
                                ->prototype('scalar')->end()
                            ->end()
                        ->end()
                    ->end()
                ->end()
            ->end()
            ->buildTree()
        ;

        $normalized = array('logout' => array('handlers' => array('a', 'b', 'c')));

        $this->assertNormalized($tree, $denormalized, $normalized);
    }

    public function getAnonymousKeysTests()
    {
        $configs = array();

        $configs[] = array(
            'logout' => array(
                'handlers' => array('a', 'b', 'c'),
            ),
        );

        $configs[] = array(
            'logout' => array(
                'handler' => array('a', 'b', 'c'),
            ),
        );

        return array_map(function($v) { return array($v); }, $configs);
    }

    /**
     * @dataProvider getNumericKeysTests
     */
    public function testNumericKeysAsAttributes($denormalized)
    {
        $normalized = array(
            'thing' => array(42 => array('foo', 'bar'), 1337 => array('baz', 'qux')),
        );

        $this->assertNormalized($this->getNumericKeysTestTree(), $denormalized, $normalized);
    }

    public function getNumericKeysTests()
    {
        $configs = array();

        $configs[] = array(
            'thing' => array(
                42 => array('foo', 'bar'), 1337 => array('baz', 'qux'),
            ),
        );

        $configs[] = array(
            'thing' => array(
                array('foo', 'bar', 'id' => 42), array('baz', 'qux', 'id' => 1337),
            ),
        );

        return array_map(function($v) { return array($v); }, $configs);
    }

    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
     * @expectedExceptionMessage The attribute "id" must be set for path "root.thing".
     */
    public function testNonAssociativeArrayThrowsExceptionIfAttributeNotSet()
    {
        $denormalized = array(
            'thing' => array(
                array('foo', 'bar'), array('baz', 'qux')
            )
        );

        $this->assertNormalized($this->getNumericKeysTestTree(), $denormalized, array());
    }

    public function testAssociativeArrayPreserveKeys()
    {
        $tb = new TreeBuilder();
        $tree = $tb
            ->root('root', 'array')
                ->prototype('array')
                    ->children()
                        ->node('foo', 'scalar')->end()
                    ->end()
                ->end()
            ->end()
            ->buildTree()
        ;

        $data = array('first' => array('foo' => 'bar'));

        $this->assertNormalized($tree, $data, $data);
    }

    public static function assertNormalized(NodeInterface $tree, $denormalized, $normalized)
    {
        self::assertSame($normalized, $tree->normalize($denormalized));
    }

    private function getNumericKeysTestTree()
    {
        $tb = new TreeBuilder();
        $tree = $tb
            ->root('root', 'array')
                ->children()
                    ->node('thing', 'array')
                        ->useAttributeAsKey('id')
                        ->prototype('array')
                            ->prototype('scalar')->end()
                        ->end()
                    ->end()
                ->end()
            ->end()
            ->buildTree()
        ;

        return $tree;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;

class MergeTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\ForbiddenOverwriteException
     */
    public function testForbiddenOverwrite()
    {
        $tb = new TreeBuilder();
        $tree = $tb
            ->root('root', 'array')
                ->children()
                    ->node('foo', 'scalar')
                        ->cannotBeOverwritten()
                    ->end()
                ->end()
            ->end()
            ->buildTree()
        ;

        $a = array(
            'foo' => 'bar',
        );

        $b = array(
            'foo' => 'moo',
        );

        $tree->merge($a, $b);
    }

    public function testUnsetKey()
    {
        $tb = new TreeBuilder();
        $tree = $tb
            ->root('root', 'array')
                ->children()
                    ->node('foo', 'scalar')->end()
                    ->node('bar', 'scalar')->end()
                    ->node('unsettable', 'array')
                        ->canBeUnset()
                        ->children()
                            ->node('foo', 'scalar')->end()
                            ->node('bar', 'scalar')->end()
                        ->end()
                    ->end()
                    ->node('unsetted', 'array')
                        ->canBeUnset()
                        ->prototype('scalar')->end()
                    ->end()
                ->end()
            ->end()
            ->buildTree()
        ;

        $a = array(
            'foo' => 'bar',
            'unsettable' => array(
                'foo' => 'a',
                'bar' => 'b',
            ),
            'unsetted' => false,
        );

        $b = array(
            'foo' => 'moo',
            'bar' => 'b',
            'unsettable' => false,
            'unsetted' => array('a', 'b'),
        );

        $this->assertEquals(array(
            'foo' => 'moo',
            'bar' => 'b',
            'unsettable' => false,
            'unsetted' => array('a', 'b'),
        ), $tree->merge($a, $b));
    }

    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
     */
    public function testDoesNotAllowNewKeysInSubsequentConfigs()
    {
        $tb = new TreeBuilder();
        $tree = $tb
            ->root('config', 'array')
                ->children()
                    ->node('test', 'array')
                        ->disallowNewKeysInSubsequentConfigs()
                        ->useAttributeAsKey('key')
                        ->prototype('array')
                            ->children()
                                ->node('value', 'scalar')->end()
                            ->end()
                        ->end()
                    ->end()
                ->end()
            ->end()
            ->buildTree();

        $a = array(
            'test' => array(
                'a' => array('value' => 'foo')
            )
        );

        $b = array(
            'test' => array(
                'b' => array('value' => 'foo')
            )
        );

        $tree->merge($a, $b);
    }

    public function testPerformsNoDeepMerging()
    {
        $tb = new TreeBuilder();

        $tree = $tb
            ->root('config', 'array')
                ->children()
                    ->node('no_deep_merging', 'array')
                        ->performNoDeepMerging()
                        ->children()
                            ->node('foo', 'scalar')->end()
                            ->node('bar', 'scalar')->end()
                        ->end()
                    ->end()
                ->end()
            ->end()
            ->buildTree()
        ;

        $a = array(
            'no_deep_merging' => array(
                'foo' => 'a',
                'bar' => 'b',
            ),
        );

        $b = array(
            'no_deep_merging' => array(
                'c' => 'd',
            )
        );

        $this->assertEquals(array(
            'no_deep_merging' => array(
                'c' => 'd',
            )
        ), $tree->merge($a, $b));
    }

    public function testPrototypeWithoutAKeyAttribute()
    {
        $tb = new TreeBuilder();

        $tree = $tb
            ->root('config', 'array')
                ->children()
                    ->arrayNode('append_elements')
                        ->prototype('scalar')->end()
                    ->end()
                ->end()
            ->end()
            ->buildTree()
        ;

        $a = array(
            'append_elements' => array('a', 'b'),
        );

        $b = array(
            'append_elements' => array('c', 'd'),
        );

        $this->assertEquals(array('append_elements' => array('a', 'b', 'c', 'd')), $tree->merge($a, $b));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition;

use Symfony\Component\Config\Definition\IntegerNode;

class IntegerNodeTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getValidValues
     */
    public function testNormalize($value)
    {
        $node = new IntegerNode('test');
        $this->assertSame($value, $node->normalize($value));
    }

    public function getValidValues()
    {
        return array(
            array(1798),
            array(-678),
            array(0),
        );
    }

    /**
     * @dataProvider getInvalidValues
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidTypeException
     */
    public function testNormalizeThrowsExceptionOnInvalidValues($value)
    {
        $node = new IntegerNode('test');
        $node->normalize($value);
    }

    public function getInvalidValues()
    {
        return array(
            array(null),
            array(''),
            array('foo'),
            array(true),
            array(false),
            array(0.0),
            array(0.1),
            array(array()),
            array(array('foo' => 'bar')),
            array(new \stdClass()),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\Processor;
use Symfony\Component\Config\Definition\NodeInterface;

class FinalizationTest extends \PHPUnit_Framework_TestCase
{
    public function testUnsetKeyWithDeepHierarchy()
    {
        $tb = new TreeBuilder();
        $tree = $tb
            ->root('config', 'array')
                ->children()
                    ->node('level1', 'array')
                        ->canBeUnset()
                        ->children()
                            ->node('level2', 'array')
                                ->canBeUnset()
                                ->children()
                                    ->node('somevalue', 'scalar')->end()
                                    ->node('anothervalue', 'scalar')->end()
                                ->end()
                            ->end()
                            ->node('level1_scalar', 'scalar')->end()
                        ->end()
                    ->end()
                ->end()
            ->end()
            ->buildTree()
        ;

        $a = array(
            'level1' => array(
                'level2' => array(
                    'somevalue' => 'foo',
                    'anothervalue' => 'bar',
                ),
                'level1_scalar' => 'foo',
            ),
        );

        $b = array(
            'level1' => array(
                'level2' => false,
            ),
        );

        $this->assertEquals(array(
            'level1' => array(
                'level1_scalar' => 'foo',
            ),
        ), $this->process($tree, array($a, $b)));
    }

    protected function process(NodeInterface $tree, array $configs)
    {
        $processor = new Processor();

        return $processor->process($tree, $configs);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition;

use Symfony\Component\Config\Definition\PrototypedArrayNode;
use Symfony\Component\Config\Definition\ArrayNode;
use Symfony\Component\Config\Definition\ScalarNode;

class PrototypedArrayNodeTest extends \PHPUnit_Framework_TestCase
{
    public function testGetDefaultValueReturnsAnEmptyArrayForPrototypes()
    {
        $node = new PrototypedArrayNode('root');
        $prototype = new ArrayNode(null, $node);
        $node->setPrototype($prototype);
        $this->assertEmpty($node->getDefaultValue());
    }

    public function testGetDefaultValueReturnsDefaultValueForPrototypes()
    {
        $node = new PrototypedArrayNode('root');
        $prototype = new ArrayNode(null, $node);
        $node->setPrototype($prototype);
        $node->setDefaultValue(array('test'));
        $this->assertEquals(array('test'), $node->getDefaultValue());
    }

    // a remapped key (e.g. "mapping" -> "mappings") should be unset after being used
    public function testRemappedKeysAreUnset()
    {
        $node = new ArrayNode('root');
        $mappingsNode = new PrototypedArrayNode('mappings');
        $node->addChild($mappingsNode);

        // each item under mappings is just a scalar
        $prototype = new ScalarNode(null, $mappingsNode);
        $mappingsNode->setPrototype($prototype);

        $remappings = array();
        $remappings[] = array('mapping', 'mappings');
        $node->setXmlRemappings($remappings);

        $normalized = $node->normalize(array('mapping' => array('foo', 'bar')));
        $this->assertEquals(array('mappings' => array('foo', 'bar')), $normalized);
    }

    /**
     * Tests that when a key attribute is mapped, that key is removed from the array:
     *
     *     <things>
     *         <option id="option1" value="foo">
     *         <option id="option2" value="bar">
     *     </things>
     *
     * The above should finally be mapped to an array that looks like this
     * (because "id" is the key attribute).
     *
     *     array(
     *         'things' => array(
     *             'option1' => 'foo',
     *             'option2' => 'bar',
     *         )
     *     )
     */
    public function testMappedAttributeKeyIsRemoved()
    {
        $node = new PrototypedArrayNode('root');
        $node->setKeyAttribute('id', true);

        // each item under the root is an array, with one scalar item
        $prototype = new ArrayNode(null, $node);
        $prototype->addChild(new ScalarNode('foo'));
        $node->setPrototype($prototype);

        $children = array();
        $children[] = array('id' => 'item_name', 'foo' => 'bar');
        $normalized = $node->normalize($children);

        $expected = array();
        $expected['item_name'] = array('foo' => 'bar');
        $this->assertEquals($expected, $normalized);
    }

    /**
     * Tests the opposite of the testMappedAttributeKeyIsRemoved because
     * the removal can be toggled with an option.
     */
    public function testMappedAttributeKeyNotRemoved()
    {
        $node = new PrototypedArrayNode('root');
        $node->setKeyAttribute('id', false);

        // each item under the root is an array, with two scalar items
        $prototype = new ArrayNode(null, $node);
        $prototype->addChild(new ScalarNode('foo'));
        $prototype->addChild(new ScalarNode('id')); // the key attribute will remain
        $node->setPrototype($prototype);

        $children = array();
        $children[] = array('id' => 'item_name', 'foo' => 'bar');
        $normalized = $node->normalize($children);

        $expected = array();
        $expected['item_name'] = array('id' => 'item_name', 'foo' => 'bar');
        $this->assertEquals($expected, $normalized);
    }

    public function testAddDefaultChildren()
    {
        $node = $this->getPrototypeNodeWithDefaultChildren();
        $node->setAddChildrenIfNoneSet();
        $this->assertTrue($node->hasDefaultValue());
        $this->assertEquals(array(array('foo' => 'bar')), $node->getDefaultValue());

        $node = $this->getPrototypeNodeWithDefaultChildren();
        $node->setKeyAttribute('foobar');
        $node->setAddChildrenIfNoneSet();
        $this->assertTrue($node->hasDefaultValue());
        $this->assertEquals(array('defaults' => array('foo' => 'bar')), $node->getDefaultValue());

        $node = $this->getPrototypeNodeWithDefaultChildren();
        $node->setKeyAttribute('foobar');
        $node->setAddChildrenIfNoneSet('defaultkey');
        $this->assertTrue($node->hasDefaultValue());
        $this->assertEquals(array('defaultkey' => array('foo' => 'bar')), $node->getDefaultValue());

        $node = $this->getPrototypeNodeWithDefaultChildren();
        $node->setKeyAttribute('foobar');
        $node->setAddChildrenIfNoneSet(array('defaultkey'));
        $this->assertTrue($node->hasDefaultValue());
        $this->assertEquals(array('defaultkey' => array('foo' => 'bar')), $node->getDefaultValue());

        $node = $this->getPrototypeNodeWithDefaultChildren();
        $node->setKeyAttribute('foobar');
        $node->setAddChildrenIfNoneSet(array('dk1', 'dk2'));
        $this->assertTrue($node->hasDefaultValue());
        $this->assertEquals(array('dk1' => array('foo' => 'bar'), 'dk2' => array('foo' => 'bar')), $node->getDefaultValue());

        $node = $this->getPrototypeNodeWithDefaultChildren();
        $node->setAddChildrenIfNoneSet(array(5, 6));
        $this->assertTrue($node->hasDefaultValue());
        $this->assertEquals(array(0 => array('foo' => 'bar'), 1 => array('foo' => 'bar')), $node->getDefaultValue());

        $node = $this->getPrototypeNodeWithDefaultChildren();
        $node->setAddChildrenIfNoneSet(2);
        $this->assertTrue($node->hasDefaultValue());
        $this->assertEquals(array(array('foo' => 'bar'), array('foo' => 'bar')), $node->getDefaultValue());
    }

    public function testDefaultChildrenWinsOverDefaultValue()
    {
        $node = $this->getPrototypeNodeWithDefaultChildren();
        $node->setAddChildrenIfNoneSet();
        $node->setDefaultValue(array('bar' => 'foo'));
        $this->assertTrue($node->hasDefaultValue());
        $this->assertEquals(array(array('foo' => 'bar')), $node->getDefaultValue());
    }

    protected function getPrototypeNodeWithDefaultChildren()
    {
        $node = new PrototypedArrayNode('root');
        $prototype = new ArrayNode(null, $node);
        $child = new ScalarNode('foo');
        $child->setDefaultValue('bar');
        $prototype->addChild($child);
        $prototype->setAddIfNotSet(true);
        $node->setPrototype($prototype);

        return $node;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition;

use Symfony\Component\Config\Definition\BooleanNode;

class BooleanNodeTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getValidValues
     */
    public function testNormalize($value)
    {
        $node = new BooleanNode('test');
        $this->assertSame($value, $node->normalize($value));
    }

    public function getValidValues()
    {
        return array(
            array(false),
            array(true),
        );
    }

    /**
     * @dataProvider getInvalidValues
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidTypeException
     */
    public function testNormalizeThrowsExceptionOnInvalidValues($value)
    {
        $node = new BooleanNode('test');
        $node->normalize($value);
    }

    public function getInvalidValues()
    {
        return array(
            array(null),
            array(''),
            array('foo'),
            array(0),
            array(1),
            array(0.0),
            array(0.1),
            array(array()),
            array(array('foo' => 'bar')),
            array(new \stdClass()),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition;

use Symfony\Component\Config\Definition\ScalarNode;

class ScalarNodeTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getValidValues
     */
    public function testNormalize($value)
    {
        $node = new ScalarNode('test');
        $this->assertSame($value, $node->normalize($value));
    }

    public function getValidValues()
    {
        return array(
            array(false),
            array(true),
            array(null),
            array(''),
            array('foo'),
            array(0),
            array(1),
            array(0.0),
            array(0.1),
        );
    }

    /**
     * @dataProvider getInvalidValues
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidTypeException
     */
    public function testNormalizeThrowsExceptionOnInvalidValues($value)
    {
        $node = new ScalarNode('test');
        $node->normalize($value);
    }

    public function getInvalidValues()
    {
        return array(
            array(array()),
            array(array('foo' => 'bar')),
            array(new \stdClass()),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Config\Tests\Definition;

use Symfony\Component\Config\Definition\ArrayNode;

class ArrayNodeTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidTypeException
     */
    public function testNormalizeThrowsExceptionWhenFalseIsNotAllowed()
    {
        $node = new ArrayNode('root');
        $node->normalize(false);
    }

    /**
     * @expectedException        \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
     * @expectedExceptionMessage Unrecognized options "foo" under "root"
     */
    public function testExceptionThrownOnUnrecognizedChild()
    {
        $node = new ArrayNode('root');
        $node->normalize(array('foo' => 'bar'));
    }

    /**
     * Tests that no exception is thrown for an unrecognized child if the
     * ignoreExtraKeys option is set to true.
     *
     * Related to testExceptionThrownOnUnrecognizedChild
     */
    public function testIgnoreExtraKeysNoException()
    {
        $node = new ArrayNode('roo');
        $node->setIgnoreExtraKeys(true);

        $node->normalize(array('foo' => 'bar'));
        $this->assertTrue(true, 'No exception was thrown when setIgnoreExtraKeys is true');
    }

    /**
     * @dataProvider getPreNormalizationTests
     */
    public function testPreNormalize($denormalized, $normalized)
    {
        $node = new ArrayNode('foo');

        $r = new \ReflectionMethod($node, 'preNormalize');
        $r->setAccessible(true);

        $this->assertSame($normalized, $r->invoke($node, $denormalized));
    }

    public function getPreNormalizationTests()
    {
        return array(
            array(
                array('foo-bar' => 'foo'),
                array('foo_bar' => 'foo'),
            ),
            array(
                array('foo-bar_moo' => 'foo'),
                array('foo-bar_moo' => 'foo'),
            ),
            array(
                array('foo-bar' => null, 'foo_bar' => 'foo'),
                array('foo-bar' => null, 'foo_bar' => 'foo'),
            )
        );
    }
}
{
    "name": "symfony/translation",
    "type": "library",
    "description": "Symfony Translation Component",
    "keywords": [],
    "homepage": "http://symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "http://symfony.com/contributors"
        }
    ],
    "require": {
        "php": ">=5.3.3"
    },
    "require-dev": {
        "symfony/config": "~2.0",
        "symfony/yaml": "~2.2"
    },
    "suggest": {
        "symfony/config": "",
        "symfony/yaml": ""
    },
    "autoload": {
        "psr-0": { "Symfony\\Component\\Translation\\": "" }
    },
    "target-dir": "Symfony/Component/Translation",
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-master": "2.4-dev"
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

/**
 * MessageSelector.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class MessageSelector
{
    /**
     * Given a message with different plural translations separated by a
     * pipe (|), this method returns the correct portion of the message based
     * on the given number, locale and the pluralization rules in the message
     * itself.
     *
     * The message supports two different types of pluralization rules:
     *
     * interval: {0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples
     * indexed:  There is one apple|There are %count% apples
     *
     * The indexed solution can also contain labels (e.g. one: There is one apple).
     * This is purely for making the translations more clear - it does not
     * affect the functionality.
     *
     * The two methods can also be mixed:
     *     {0} There are no apples|one: There is one apple|more: There are %count% apples
     *
     * @param string  $message The message being translated
     * @param integer $number  The number of items represented for the message
     * @param string  $locale  The locale to use for choosing
     *
     * @return string
     *
     * @throws \InvalidArgumentException
     *
     * @api
     */
    public function choose($message, $number, $locale)
    {
        $parts = explode('|', $message);
        $explicitRules = array();
        $standardRules = array();
        foreach ($parts as $part) {
            $part = trim($part);

            if (preg_match('/^(?P<interval>'.Interval::getIntervalRegexp().')\s*(?P<message>.*?)$/x', $part, $matches)) {
                $explicitRules[$matches['interval']] = $matches['message'];
            } elseif (preg_match('/^\w+\:\s*(.*?)$/', $part, $matches)) {
                $standardRules[] = $matches[1];
            } else {
                $standardRules[] = $part;
            }
        }

        // try to match an explicit rule, then fallback to the standard ones
        foreach ($explicitRules as $interval => $m) {
            if (Interval::test($number, $interval)) {
                return $m;
            }
        }

        $position = PluralizationRules::get($number, $locale);

        if (!isset($standardRules[$position])) {
            // when there's exactly one rule given, and that rule is a standard
            // rule, use this rule
            if (1 === count($parts) && isset($standardRules[0])) {
                return $standardRules[0];
            }

            throw new \InvalidArgumentException(sprintf('Unable to choose a translation for "%s" with locale "%s". Double check that this translation has the correct plural options (e.g. "There is one apple|There are %%count%% apples").', $message, $locale));
        }

        return $standardRules[$position];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

/**
 * IdentityTranslator does not translate anything.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class IdentityTranslator implements TranslatorInterface
{
    private $selector;
    private $locale;

    /**
     * Constructor.
     *
     * @param MessageSelector|null $selector The message selector for pluralization
     *
     * @api
     */
    public function __construct(MessageSelector $selector = null)
    {
        $this->selector = $selector ?: new MessageSelector();
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function setLocale($locale)
    {
        $this->locale = $locale;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function getLocale()
    {
        return $this->locale ?: \Locale::getDefault();
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function trans($id, array $parameters = array(), $domain = null, $locale = null)
    {
        return strtr((string) $id, $parameters);
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
    {
        return strtr($this->selector->choose((string) $id, (int) $number, $locale ?: $this->getLocale()), $parameters);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * IniFileDumper generates an ini formatted string representation of a message catalogue.
 *
 * @author Stealth35
 */
class IniFileDumper extends FileDumper
{
    /**
     * {@inheritDoc}
     */
    public function format(MessageCatalogue $messages, $domain = 'messages')
    {
        $output = '';

        foreach ($messages->all($domain) as $source => $target) {
            $escapeTarget = str_replace('"', '\"', $target);
            $output .= $source.'="'.$escapeTarget."\"\n";
        }

        return $output;
    }

    /**
     * {@inheritDoc}
     */
    protected function getExtension()
    {
        return 'ini';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * FileDumper is an implementation of DumperInterface that dump a message catalogue to file(s).
 * Performs backup of already existing files.
 *
 * Options:
 * - path (mandatory): the directory where the files should be saved
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 */
abstract class FileDumper implements DumperInterface
{
    /**
     * {@inheritDoc}
     */
    public function dump(MessageCatalogue $messages, $options = array())
    {
        if (!array_key_exists('path', $options)) {
            throw new \InvalidArgumentException('The file dumper needs a path option.');
        }

        // save a file for each domain
        foreach ($messages->getDomains() as $domain) {
            $file = $domain.'.'.$messages->getLocale().'.'.$this->getExtension();
            // backup
            $fullpath = $options['path'].'/'.$file;
            if (file_exists($fullpath)) {
                copy($fullpath, $fullpath.'~');
            }
            // save file
            file_put_contents($fullpath, $this->format($messages, $domain));
        }
    }

    /**
     * Transforms a domain of a message catalogue to its string representation.
     *
     * @param MessageCatalogue $messages
     * @param string           $domain
     *
     * @return string representation
     */
    abstract protected function format(MessageCatalogue $messages, $domain);

    /**
     * Gets the file extension of the dumper.
     *
     * @return string file extension
     */
    abstract protected function getExtension();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * QtFileDumper generates ts files from a message catalogue.
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 */
class QtFileDumper extends FileDumper
{
    /**
     * {@inheritDoc}
     */
    public function format(MessageCatalogue $messages, $domain)
    {
        $dom = new \DOMDocument('1.0', 'utf-8');
        $dom->formatOutput = true;
        $ts = $dom->appendChild($dom->createElement('TS'));
        $context = $ts->appendChild($dom->createElement('context'));
        $context->appendChild($dom->createElement('name', $domain));

        foreach ($messages->all($domain) as $source => $target) {
            $message = $context->appendChild($dom->createElement('message'));
            $message->appendChild($dom->createElement('source', $source));
            $message->appendChild($dom->createElement('translation', $target));
        }

        return $dom->saveXML();
    }

    /**
     * {@inheritDoc}
     */
    protected function getExtension()
    {
        return 'ts';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * IcuResDumper generates an ICU ResourceBundle formatted string representation of a message catalogue.
 *
 * @author Stealth35
 */
class IcuResFileDumper implements DumperInterface
{
    /**
     * {@inheritDoc}
     */
    public function dump(MessageCatalogue $messages, $options = array())
    {
        if (!array_key_exists('path', $options)) {
            throw new \InvalidArgumentException('The file dumper need a path options.');
        }

        // save a file for each domain
        foreach ($messages->getDomains() as $domain) {
            $file = $messages->getLocale().'.'.$this->getExtension();
            $path = $options['path'].'/'.$domain.'/';

            if (!file_exists($path)) {
                mkdir($path);
            }

            // backup
            if (file_exists($path.$file)) {
                copy($path.$file, $path.$file.'~');
            }

            // save file
            file_put_contents($path.$file, $this->format($messages, $domain));
        }
    }

    /**
     * {@inheritDoc}
     */
    public function format(MessageCatalogue $messages, $domain = 'messages')
    {
        $data = $indexes = $resources = '';

        foreach ($messages->all($domain) as $source => $target) {
            $indexes .= pack('v', strlen($data) + 28);
            $data    .= $source."\0";
        }

        $data .= $this->writePadding($data);

        $keyTop = $this->getPosition($data);

        foreach ($messages->all($domain) as $source => $target) {
            $resources .= pack('V', $this->getPosition($data));

            $data .= pack('V', strlen($target))
                .mb_convert_encoding($target."\0", 'UTF-16LE', 'UTF-8')
                .$this->writePadding($data)
                  ;
        }

        $resOffset = $this->getPosition($data);

        $data .= pack('v', count($messages))
            .$indexes
            .$this->writePadding($data)
            .$resources
              ;

        $bundleTop = $this->getPosition($data);

        $root = pack('V7',
            $resOffset + (2 << 28), // Resource Offset + Resource Type
            6,                      // Index length
            $keyTop,                // Index keys top
            $bundleTop,             // Index resources top
            $bundleTop,             // Index bundle top
            count($messages),       // Index max table length
            0                       // Index attributes
        );

        $header = pack('vC2v4C12@32',
            32,                     // Header size
            0xDA, 0x27,             // Magic number 1 and 2
            20, 0, 0, 2,            // Rest of the header, ..., Size of a char
            0x52, 0x65, 0x73, 0x42, // Data format identifier
            1, 2, 0, 0,             // Data version
            1, 4, 0, 0              // Unicode version
        );

        $output = $header
               .$root
               .$data;

        return $output;
    }

    private function writePadding($data)
    {
        $padding = strlen($data) % 4;

        if ($padding) {
            return str_repeat("\xAA", 4 - $padding);
        }
    }

    private function getPosition($data)
    {
        $position = (strlen($data) + 28) / 4;

        return $position;
    }

    /**
     * {@inheritDoc}
     */
    protected function getExtension()
    {
        return 'res';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * XliffFileDumper generates xliff files from a message catalogue.
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 */
class XliffFileDumper extends FileDumper
{
    /**
     * {@inheritDoc}
     */
    protected function format(MessageCatalogue $messages, $domain)
    {
        $dom = new \DOMDocument('1.0', 'utf-8');
        $dom->formatOutput = true;

        $xliff = $dom->appendChild($dom->createElement('xliff'));
        $xliff->setAttribute('version', '1.2');
        $xliff->setAttribute('xmlns', 'urn:oasis:names:tc:xliff:document:1.2');

        $xliffFile = $xliff->appendChild($dom->createElement('file'));
        $xliffFile->setAttribute('source-language', $messages->getLocale());
        $xliffFile->setAttribute('datatype', 'plaintext');
        $xliffFile->setAttribute('original', 'file.ext');

        $xliffBody = $xliffFile->appendChild($dom->createElement('body'));
        foreach ($messages->all($domain) as $source => $target) {
            $translation = $dom->createElement('trans-unit');

            $translation->setAttribute('id', md5($source));
            $translation->setAttribute('resname', $source);

            $s = $translation->appendChild($dom->createElement('source'));
            $s->appendChild($dom->createTextNode($source));

            $t = $translation->appendChild($dom->createElement('target'));
            $t->appendChild($dom->createTextNode($target));

            $xliffBody->appendChild($translation);
        }

        return $dom->saveXML();
    }

    /**
     * {@inheritDoc}
     */
    protected function getExtension()
    {
        return 'xlf';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * CsvFileDumper generates a csv formatted string representation of a message catalogue.
 *
 * @author Stealth35
 */
class CsvFileDumper extends FileDumper
{
    private $delimiter = ';';
    private $enclosure = '"';

    /**
     * {@inheritDoc}
     */
    public function format(MessageCatalogue $messages, $domain = 'messages')
    {
        $handle = fopen('php://memory', 'rb+');

        foreach ($messages->all($domain) as $source => $target) {
            fputcsv($handle, array($source, $target), $this->delimiter, $this->enclosure);
        }

        rewind($handle);
        $output = stream_get_contents($handle);
        fclose($handle);

        return $output;
    }

    /**
     * Sets the delimiter and escape character for CSV.
     *
     * @param string $delimiter delimiter character
     * @param string $enclosure enclosure character
     */
    public function setCsvControl($delimiter = ';', $enclosure = '"')
    {
        $this->delimiter = $delimiter;
        $this->enclosure = $enclosure;
    }

    /**
     * {@inheritDoc}
     */
    protected function getExtension()
    {
        return 'csv';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * PoFileDumper generates a gettext formatted string representation of a message catalogue.
 *
 * @author Stealth35
 */
class PoFileDumper extends FileDumper
{
    /**
     * {@inheritDoc}
     */
    public function format(MessageCatalogue $messages, $domain = 'messages')
    {
        $output = 'msgid ""'."\n";
        $output .= 'msgstr ""'."\n";
        $output .= '"Content-Type: text/plain; charset=UTF-8\n"'."\n";
        $output .= '"Content-Transfer-Encoding: 8bit\n"'."\n";
        $output .= '"Language: '.$messages->getLocale().'\n"'."\n";
        $output .= "\n";

        $newLine = false;
        foreach ($messages->all($domain) as $source => $target) {
            if ($newLine) {
              $output .= "\n";
            } else {
              $newLine = true;
            }
            $output .= sprintf('msgid "%s"'."\n", $this->escape($source));
            $output .= sprintf('msgstr "%s"', $this->escape($target));
        }

        return $output;
    }

    /**
     * {@inheritDoc}
     */
    protected function getExtension()
    {
        return 'po';
    }

    private function escape($str)
    {
        return addcslashes($str, "\0..\37\42\134");
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * PhpFileDumper generates php files from a message catalogue.
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 */
class PhpFileDumper extends FileDumper
{
    /**
     * {@inheritDoc}
     */
    protected function format(MessageCatalogue $messages, $domain)
    {
        $output = "<?php\n\nreturn ".var_export($messages->all($domain), true).";\n";

        return $output;
    }

    /**
     * {@inheritDoc}
     */
    protected function getExtension()
    {
        return 'php';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

if (!defined('JSON_PRETTY_PRINT')) {
    define('JSON_PRETTY_PRINT', 128);
}

/**
 * JsonFileDumper generates an json formatted string representation of a message catalogue.
 *
 * @author singles
 */
class JsonFileDumper extends FileDumper
{
    /**
     * {@inheritDoc}
     */
    public function format(MessageCatalogue $messages, $domain = 'messages')
    {
        return json_encode($messages->all($domain), JSON_PRETTY_PRINT);
    }

    /**
     * {@inheritDoc}
     */
    protected function getExtension()
    {
        return 'json';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * DumperInterface is the interface implemented by all translation dumpers.
 * There is no common option.
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 */
interface DumperInterface
{
    /**
     * Dumps the message catalogue.
     *
     * @param MessageCatalogue $messages The message catalogue
     * @param array            $options  Options that are used by the dumper
     */
    public function dump(MessageCatalogue $messages, $options = array());
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Loader\MoFileLoader;

/**
 * MoFileDumper generates a gettext formatted string representation of a message catalogue.
 *
 * @author Stealth35
 */
class MoFileDumper extends FileDumper
{
    /**
     * {@inheritDoc}
     */
    public function format(MessageCatalogue $messages, $domain = 'messages')
    {
        $output = $sources = $targets = $sourceOffsets = $targetOffsets = '';
        $offsets = array();
        $size = 0;

        foreach ($messages->all($domain) as $source => $target) {
            $offsets[] = array_map('strlen', array($sources, $source, $targets, $target));
            $sources .= "\0".$source;
            $targets .= "\0".$target;
            ++$size;
        }

        $header = array(
            'magicNumber'      => MoFileLoader::MO_LITTLE_ENDIAN_MAGIC,
            'formatRevision'   => 0,
            'count'            => $size,
            'offsetId'         => MoFileLoader::MO_HEADER_SIZE,
            'offsetTranslated' => MoFileLoader::MO_HEADER_SIZE + (8 * $size),
            'sizeHashes'       => 0,
            'offsetHashes'     => MoFileLoader::MO_HEADER_SIZE + (16 * $size),
        );

        $sourcesSize  = strlen($sources);
        $sourcesStart = $header['offsetHashes'] + 1;

        foreach ($offsets as $offset) {
            $sourceOffsets .= $this->writeLong($offset[1])
                          .$this->writeLong($offset[0] + $sourcesStart);
            $targetOffsets .= $this->writeLong($offset[3])
                          .$this->writeLong($offset[2] + $sourcesStart + $sourcesSize);
        }

        $output = implode(array_map(array($this, 'writeLong'), $header))
               .$sourceOffsets
               .$targetOffsets
               .$sources
               .$targets
                ;

        return $output;
    }

    /**
     * {@inheritDoc}
     */
    protected function getExtension()
    {
        return 'mo';
    }

    private function writeLong($str)
    {
        return pack('V*', $str);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Dumper;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Yaml\Yaml;

/**
 * YamlFileDumper generates yaml files from a message catalogue.
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 */
class YamlFileDumper extends FileDumper
{
    /**
     * {@inheritDoc}
     */
    protected function format(MessageCatalogue $messages, $domain)
    {
         return Yaml::dump($messages->all($domain));
    }

    /**
     * {@inheritDoc}
     */
    protected function getExtension()
    {
        return 'yml';
    }
}
Copyright (c) 2004-2013 Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Catalogue;

/**
 * Diff operation between two catalogues.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class DiffOperation extends AbstractOperation
{
    /**
     * {@inheritdoc}
     */
    protected function processDomain($domain)
    {
        $this->messages[$domain] = array(
            'all'      => array(),
            'new'      => array(),
            'obsolete' => array(),
        );

        foreach ($this->source->all($domain) as $id => $message) {
            if ($this->target->has($id, $domain)) {
                $this->messages[$domain]['all'][$id] = $message;
                $this->result->add(array($id => $message), $domain);
            } else {
                $this->messages[$domain]['obsolete'][$id] = $message;
            }
        }

        foreach ($this->target->all($domain) as $id => $message) {
            if (!$this->source->has($id, $domain)) {
                $this->messages[$domain]['all'][$id] = $message;
                $this->messages[$domain]['new'][$id] = $message;
                $this->result->add(array($id => $message), $domain);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Catalogue;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\MessageCatalogueInterface;

/**
 * Base catalogues binary operation class.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
abstract class AbstractOperation implements OperationInterface
{
    /**
     * @var MessageCatalogueInterface
     */
    protected $source;

    /**
     * @var MessageCatalogueInterface
     */
    protected $target;

    /**
     * @var MessageCatalogue
     */
    protected $result;

    /**
     * @var null|array
     */
    private $domains;

    /**
     * @var array
     */
    protected $messages;

    /**
     * @param MessageCatalogueInterface $source
     * @param MessageCatalogueInterface $target
     *
     * @throws \LogicException
     */
    public function __construct(MessageCatalogueInterface $source, MessageCatalogueInterface $target)
    {
        if ($source->getLocale() !== $target->getLocale()) {
            throw new \LogicException('Operated catalogues must belong to the same locale.');
        }

        $this->source = $source;
        $this->target = $target;
        $this->result = new MessageCatalogue($source->getLocale());
        $this->domains = null;
        $this->messages = array();
    }

    /**
     * {@inheritdoc}
     */
    public function getDomains()
    {
        if (null === $this->domains) {
            $this->domains = array_values(array_unique(array_merge($this->source->getDomains(), $this->target->getDomains())));
        }

        return $this->domains;
    }

    /**
     * {@inheritdoc}
     */
    public function getMessages($domain)
    {
        if (!in_array($domain, $this->getDomains())) {
            throw new \InvalidArgumentException(sprintf('Invalid domain: %s.', $domain));
        }

        if (!isset($this->messages[$domain]['all'])) {
            $this->processDomain($domain);
        }

        return $this->messages[$domain]['all'];
    }

    /**
     * {@inheritdoc}
     */
    public function getNewMessages($domain)
    {
        if (!in_array($domain, $this->getDomains())) {
            throw new \InvalidArgumentException(sprintf('Invalid domain: %s.', $domain));
        }

        if (!isset($this->messages[$domain]['new'])) {
            $this->processDomain($domain);
        }

        return $this->messages[$domain]['new'];
    }

    /**
     * {@inheritdoc}
     */
    public function getObsoleteMessages($domain)
    {
        if (!in_array($domain, $this->getDomains())) {
            throw new \InvalidArgumentException(sprintf('Invalid domain: %s.', $domain));
        }

        if (!isset($this->messages[$domain]['obsolete'])) {
            $this->processDomain($domain);
        }

        return $this->messages[$domain]['obsolete'];
    }

    /**
     * {@inheritdoc}
     */
    public function getResult()
    {
        foreach ($this->getDomains() as $domain) {
            if (!isset($this->messages[$domain])) {
                $this->processDomain($domain);
            }
        }

        return $this->result;
    }

    /**
     * @param string $domain
     */
    abstract protected function processDomain($domain);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Catalogue;

use Symfony\Component\Translation\MessageCatalogueInterface;

/**
 * Represents an operation on catalogue(s).
 *
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
interface OperationInterface
{
    /**
     * Returns domains affected by operation.
     *
     * @return array
     */
    public function getDomains();

    /**
     * Returns all valid messages after operation.
     *
     * @param string $domain
     *
     * @return array
     */
    public function getMessages($domain);

    /**
     * Returns new messages after operation.
     *
     * @param string $domain
     *
     * @return array
     */
    public function getNewMessages($domain);

    /**
     * Returns obsolete messages after operation.
     *
     * @param string $domain
     *
     * @return array
     */
    public function getObsoleteMessages($domain);

    /**
     * Returns resulting catalogue.
     *
     * @return MessageCatalogueInterface
     */
    public function getResult();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Catalogue;

/**
 * Merge operation between two catalogues.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class MergeOperation extends AbstractOperation
{
    /**
     * {@inheritdoc}
     */
    protected function processDomain($domain)
    {
        $this->messages[$domain] = array(
            'all'      => array(),
            'new'      => array(),
            'obsolete' => array(),
        );

        foreach ($this->source->all($domain) as $id => $message) {
            $this->messages[$domain]['all'][$id] = $message;
            $this->result->add(array($id => $message), $domain);
        }

        foreach ($this->target->all($domain) as $id => $message) {
            if (!$this->source->has($id, $domain)) {
                $this->messages[$domain]['all'][$id] = $message;
                $this->messages[$domain]['new'][$id] = $message;
                $this->result->add(array($id => $message), $domain);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

/**
 * MetadataAwareInterface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface MetadataAwareInterface
{
    /**
     * Gets metadata for the given domain and key.
     *
     * Passing an empty domain will return an array with all metadata indexed by
     * domain and then by key. Passing an empty key will return an array with all
     * metadata for the given domain.
     *
     * @param string $domain The domain name
     * @param string $key    The key
     *
     * @return mixed The value that was set or an array with the domains/keys or null
     */
    public function getMetadata($key = '', $domain = 'messages');

    /**
     * Adds metadata to a message domain.
     *
     * @param string $key    The key
     * @param mixed  $value  The value
     * @param string $domain The domain name
     */
    public function setMetadata($key, $value, $domain = 'messages');

    /**
     * Deletes metadata for the given key and domain.
     *
     * Passing an empty domain will delete all metadata. Passing an empty key will
     * delete all metadata for the given domain.
     *
     * @param string $domain The domain name
     * @param string $key    The key
     */
    public function deleteMetadata($key = '', $domain = 'messages');
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

use Symfony\Component\Translation\Loader\LoaderInterface;
use Symfony\Component\Translation\Exception\NotFoundResourceException;

/**
 * Translator.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Translator implements TranslatorInterface
{
    /**
     * @var MessageCatalogueInterface[]
     */
    protected $catalogues = array();

    /**
     * @var string
     */
    protected $locale;

    /**
     * @var array
     */
    private $fallbackLocales = array();

    /**
     * @var LoaderInterface[]
     */
    private $loaders = array();

    /**
     * @var array
     */
    private $resources = array();

    /**
     * @var MessageSelector
     */
    private $selector;

    /**
     * Constructor.
     *
     * @param string               $locale   The locale
     * @param MessageSelector|null $selector The message selector for pluralization
     *
     * @api
     */
    public function __construct($locale, MessageSelector $selector = null)
    {
        $this->locale = $locale;
        $this->selector = $selector ?: new MessageSelector();
    }

    /**
     * Adds a Loader.
     *
     * @param string          $format The name of the loader (@see addResource())
     * @param LoaderInterface $loader A LoaderInterface instance
     *
     * @api
     */
    public function addLoader($format, LoaderInterface $loader)
    {
        $this->loaders[$format] = $loader;
    }

    /**
     * Adds a Resource.
     *
     * @param string $format   The name of the loader (@see addLoader())
     * @param mixed  $resource The resource name
     * @param string $locale   The locale
     * @param string $domain   The domain
     *
     * @api
     */
    public function addResource($format, $resource, $locale, $domain = null)
    {
        if (null === $domain) {
            $domain = 'messages';
        }

        $this->resources[$locale][] = array($format, $resource, $domain);

        if (in_array($locale, $this->fallbackLocales)) {
            $this->catalogues = array();
        } else {
            unset($this->catalogues[$locale]);
        }
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function setLocale($locale)
    {
        $this->locale = $locale;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function getLocale()
    {
        return $this->locale;
    }

    /**
     * Sets the fallback locale(s).
     *
     * @param string|array $locales The fallback locale(s)
     *
     * @deprecated since 2.3, to be removed in 3.0. Use setFallbackLocales() instead.
     *
     * @api
     */
    public function setFallbackLocale($locales)
    {
        $this->setFallbackLocales(is_array($locales) ? $locales : array($locales));
    }

    /**
     * Sets the fallback locales.
     *
     * @param array $locales The fallback locales
     *
     * @api
     */
    public function setFallbackLocales(array $locales)
    {
        // needed as the fallback locales are linked to the already loaded catalogues
        $this->catalogues = array();

        $this->fallbackLocales = $locales;
    }

    /**
     * Gets the fallback locales.
     *
     * @return array $locales The fallback locales
     *
     * @api
     */
    public function getFallbackLocales()
    {
        return $this->fallbackLocales;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function trans($id, array $parameters = array(), $domain = null, $locale = null)
    {
        if (null === $locale) {
            $locale = $this->getLocale();
        }

        if (null === $domain) {
            $domain = 'messages';
        }

        if (!isset($this->catalogues[$locale])) {
            $this->loadCatalogue($locale);
        }

        return strtr($this->catalogues[$locale]->get((string) $id, $domain), $parameters);
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
    {
        if (null === $locale) {
            $locale = $this->getLocale();
        }

        if (null === $domain) {
            $domain = 'messages';
        }

        if (!isset($this->catalogues[$locale])) {
            $this->loadCatalogue($locale);
        }

        $id = (string) $id;

        $catalogue = $this->catalogues[$locale];
        while (!$catalogue->defines($id, $domain)) {
            if ($cat = $catalogue->getFallbackCatalogue()) {
                $catalogue = $cat;
                $locale = $catalogue->getLocale();
            } else {
                break;
            }
        }

        return strtr($this->selector->choose($catalogue->get($id, $domain), (int) $number, $locale), $parameters);
    }

    /**
     * Gets the loaders.
     *
     * @return array LoaderInterface[]
     */
    protected function getLoaders()
    {
        return $this->loaders;
    }

    protected function loadCatalogue($locale)
    {
        try {
            $this->doLoadCatalogue($locale);
        } catch (NotFoundResourceException $e) {
            if (!$this->computeFallbackLocales($locale)) {
                throw $e;
            }
        }
        $this->loadFallbackCatalogues($locale);
    }

    private function doLoadCatalogue($locale)
    {
        $this->catalogues[$locale] = new MessageCatalogue($locale);

        if (isset($this->resources[$locale])) {
            foreach ($this->resources[$locale] as $resource) {
                if (!isset($this->loaders[$resource[0]])) {
                    throw new \RuntimeException(sprintf('The "%s" translation loader is not registered.', $resource[0]));
                }
                $this->catalogues[$locale]->addCatalogue($this->loaders[$resource[0]]->load($resource[1], $locale, $resource[2]));
            }
        }
    }

    private function loadFallbackCatalogues($locale)
    {
        $current = $this->catalogues[$locale];

        foreach ($this->computeFallbackLocales($locale) as $fallback) {
            if (!isset($this->catalogues[$fallback])) {
                $this->doLoadCatalogue($fallback);
            }

            $current->addFallbackCatalogue($this->catalogues[$fallback]);
            $current = $this->catalogues[$fallback];
        }
    }

    protected function computeFallbackLocales($locale)
    {
        $locales = array();
        foreach ($this->fallbackLocales as $fallback) {
            if ($fallback === $locale) {
                continue;
            }

            $locales[] = $fallback;
        }

        if (strrchr($locale, '_') !== false) {
            array_unshift($locales, substr($locale, 0, -strlen(strrchr($locale, '_'))));
        }

        return array_unique($locales);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

/**
 * Tests if a given number belongs to a given math interval.
 *
 * An interval can represent a finite set of numbers:
 *
 *  {1,2,3,4}
 *
 * An interval can represent numbers between two numbers:
 *
 *  [1, +Inf]
 *  ]-1,2[
 *
 * The left delimiter can be [ (inclusive) or ] (exclusive).
 * The right delimiter can be [ (exclusive) or ] (inclusive).
 * Beside numbers, you can use -Inf and +Inf for the infinite.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @see    http://en.wikipedia.org/wiki/Interval_%28mathematics%29#The_ISO_notation
 */
class Interval
{
    /**
     * Tests if the given number is in the math interval.
     *
     * @param integer $number   A number
     * @param string  $interval An interval
     *
     * @return Boolean
     *
     * @throws \InvalidArgumentException
     */
    public static function test($number, $interval)
    {
        $interval = trim($interval);

        if (!preg_match('/^'.self::getIntervalRegexp().'$/x', $interval, $matches)) {
            throw new \InvalidArgumentException(sprintf('"%s" is not a valid interval.', $interval));
        }

        if ($matches[1]) {
            foreach (explode(',', $matches[2]) as $n) {
                if ($number == $n) {
                    return true;
                }
            }
        } else {
            $leftNumber = self::convertNumber($matches['left']);
            $rightNumber = self::convertNumber($matches['right']);

            return
                ('[' === $matches['left_delimiter'] ? $number >= $leftNumber : $number > $leftNumber)
                && (']' === $matches['right_delimiter'] ? $number <= $rightNumber : $number < $rightNumber)
            ;
        }

        return false;
    }

    /**
     * Returns a Regexp that matches valid intervals.
     *
     * @return string A Regexp (without the delimiters)
     */
    public static function getIntervalRegexp()
    {
        return <<<EOF
        ({\s*
            (\-?\d+(\.\d+)?[\s*,\s*\-?\d+(\.\d+)?]*)
        \s*})

            |

        (?P<left_delimiter>[\[\]])
            \s*
            (?P<left>-Inf|\-?\d+(\.\d+)?)
            \s*,\s*
            (?P<right>\+?Inf|\-?\d+(\.\d+)?)
            \s*
        (?P<right_delimiter>[\[\]])
EOF;
    }

    private static function convertNumber($number)
    {
        if ('-Inf' === $number) {
            return log(0);
        } elseif ('+Inf' === $number || 'Inf' === $number) {
            return -log(0);
        }

        return (float) $number;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

/**
 * Returns the plural rules for a given locale.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class PluralizationRules
{
    // @codeCoverageIgnoreStart
    private static $rules = array();

    /**
     * Returns the plural position to use for the given locale and number.
     *
     * @param integer $number The number
     * @param string  $locale The locale
     *
     * @return integer The plural position
     */
    public static function get($number, $locale)
    {
        if ('pt_BR' === $locale) {
            // temporary set a locale for brazilian
            $locale = 'xbr';
        }

        if (strlen($locale) > 3) {
            $locale = substr($locale, 0, -strlen(strrchr($locale, '_')));
        }

        if (isset(self::$rules[$locale])) {
            $return = call_user_func(self::$rules[$locale], $number);

            if (!is_int($return) || $return < 0) {
                return 0;
            }

            return $return;
        }

        /*
         * The plural rules are derived from code of the Zend Framework (2010-09-25),
         * which is subject to the new BSD license (http://framework.zend.com/license/new-bsd).
         * Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
         */
        switch ($locale) {
            case 'bo':
            case 'dz':
            case 'id':
            case 'ja':
            case 'jv':
            case 'ka':
            case 'km':
            case 'kn':
            case 'ko':
            case 'ms':
            case 'th':
            case 'tr':
            case 'vi':
            case 'zh':
                return 0;
                break;

            case 'af':
            case 'az':
            case 'bn':
            case 'bg':
            case 'ca':
            case 'da':
            case 'de':
            case 'el':
            case 'en':
            case 'eo':
            case 'es':
            case 'et':
            case 'eu':
            case 'fa':
            case 'fi':
            case 'fo':
            case 'fur':
            case 'fy':
            case 'gl':
            case 'gu':
            case 'ha':
            case 'he':
            case 'hu':
            case 'is':
            case 'it':
            case 'ku':
            case 'lb':
            case 'ml':
            case 'mn':
            case 'mr':
            case 'nah':
            case 'nb':
            case 'ne':
            case 'nl':
            case 'nn':
            case 'no':
            case 'om':
            case 'or':
            case 'pa':
            case 'pap':
            case 'ps':
            case 'pt':
            case 'so':
            case 'sq':
            case 'sv':
            case 'sw':
            case 'ta':
            case 'te':
            case 'tk':
            case 'ur':
            case 'zu':
                return ($number == 1) ? 0 : 1;

            case 'am':
            case 'bh':
            case 'fil':
            case 'fr':
            case 'gun':
            case 'hi':
            case 'ln':
            case 'mg':
            case 'nso':
            case 'xbr':
            case 'ti':
            case 'wa':
                return (($number == 0) || ($number == 1)) ? 0 : 1;

            case 'be':
            case 'bs':
            case 'hr':
            case 'ru':
            case 'sr':
            case 'uk':
                return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);

            case 'cs':
            case 'sk':
                return ($number == 1) ? 0 : ((($number >= 2) && ($number <= 4)) ? 1 : 2);

            case 'ga':
                return ($number == 1) ? 0 : (($number == 2) ? 1 : 2);

            case 'lt':
                return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);

            case 'sl':
                return ($number % 100 == 1) ? 0 : (($number % 100 == 2) ? 1 : ((($number % 100 == 3) || ($number % 100 == 4)) ? 2 : 3));

            case 'mk':
                return ($number % 10 == 1) ? 0 : 1;

            case 'mt':
                return ($number == 1) ? 0 : ((($number == 0) || (($number % 100 > 1) && ($number % 100 < 11))) ? 1 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 2 : 3));

            case 'lv':
                return ($number == 0) ? 0 : ((($number % 10 == 1) && ($number % 100 != 11)) ? 1 : 2);

            case 'pl':
                return ($number == 1) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 1 : 2);

            case 'cy':
                return ($number == 1) ? 0 : (($number == 2) ? 1 : ((($number == 8) || ($number == 11)) ? 2 : 3));

            case 'ro':
                return ($number == 1) ? 0 : ((($number == 0) || (($number % 100 > 0) && ($number % 100 < 20))) ? 1 : 2);

            case 'ar':
                return ($number == 0) ? 0 : (($number == 1) ? 1 : (($number == 2) ? 2 : ((($number >= 3) && ($number <= 10)) ? 3 : ((($number >= 11) && ($number <= 99)) ? 4 : 5))));

            default:
                return 0;
        }
    }

    /**
     * Overrides the default plural rule for a given locale.
     *
     * @param string $rule   A PHP callable
     * @param string $locale The locale
     *
     * @throws \LogicException
     */
    public static function set($rule, $locale)
    {
        if ('pt_BR' === $locale) {
            // temporary set a locale for brazilian
            $locale = 'xbr';
        }

        if (strlen($locale) > 3) {
            $locale = substr($locale, 0, -strlen(strrchr($locale, '_')));
        }

        if (!is_callable($rule)) {
            throw new \LogicException('The given rule can not be called');
        }

        self::$rules[$locale] = $rule;
    }

    // @codeCoverageIgnoreEnd
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

/**
 * TranslatorInterface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface TranslatorInterface
{
    /**
     * Translates the given message.
     *
     * @param string      $id         The message id (may also be an object that can be cast to string)
     * @param array       $parameters An array of parameters for the message
     * @param string|null $domain     The domain for the message or null to use the default
     * @param string|null $locale     The locale or null to use the default
     *
     * @return string The translated string
     *
     * @api
     */
    public function trans($id, array $parameters = array(), $domain = null, $locale = null);

    /**
     * Translates the given choice message by choosing a translation according to a number.
     *
     * @param string      $id         The message id (may also be an object that can be cast to string)
     * @param integer     $number     The number to use to find the indice of the message
     * @param array       $parameters An array of parameters for the message
     * @param string|null $domain     The domain for the message or null to use the default
     * @param string|null $locale     The locale or null to use the default
     *
     * @return string The translated string
     *
     * @api
     */
    public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null);

    /**
     * Sets the current locale.
     *
     * @param string $locale The locale
     *
     * @api
     */
    public function setLocale($locale);

    /**
     * Returns the current locale.
     *
     * @return string The locale
     *
     * @api
     */
    public function getLocale();
}
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Translation Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./vendor</directory>
                <directory>./Tests</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Extractor;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * ChainExtractor extracts translation messages from template files.
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 */
class ChainExtractor implements ExtractorInterface
{
    /**
     * The extractors.
     *
     * @var ExtractorInterface[]
     */
    private $extractors = array();

    /**
     * Adds a loader to the translation extractor.
     *
     * @param string             $format    The format of the loader
     * @param ExtractorInterface $extractor The loader
     */
    public function addExtractor($format, ExtractorInterface $extractor)
    {
        $this->extractors[$format] = $extractor;
    }

    /**
     * {@inheritDoc}
     */
    public function setPrefix($prefix)
    {
        foreach ($this->extractors as $extractor) {
            $extractor->setPrefix($prefix);
        }
    }

    /**
     * {@inheritDoc}
     */
    public function extract($directory, MessageCatalogue $catalogue)
    {
        foreach ($this->extractors as $extractor) {
            $extractor->extract($directory, $catalogue);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Extractor;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * Extracts translation messages from a template directory to the catalogue.
 * New found messages are injected to the catalogue using the prefix.
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 */
interface ExtractorInterface
{
    /**
     * Extracts translation messages from a template directory to the catalogue.
     *
     * @param string           $directory The path to look into
     * @param MessageCatalogue $catalogue The catalogue
     */
    public function extract($directory, MessageCatalogue $catalogue);

    /**
     * Sets the prefix that should be used for new found messages.
     *
     * @param string $prefix The prefix
     */
    public function setPrefix($prefix);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Config\Resource\FileResource;

/**
 * XliffFileLoader loads translations from XLIFF files.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class XliffFileLoader implements LoaderInterface
{
    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function load($resource, $locale, $domain = 'messages')
    {
        if (!stream_is_local($resource)) {
            throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
        }

        if (!file_exists($resource)) {
            throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
        }

        list($xml, $encoding) = $this->parseFile($resource);
        $xml->registerXPathNamespace('xliff', 'urn:oasis:names:tc:xliff:document:1.2');

        $catalogue = new MessageCatalogue($locale);
        foreach ($xml->xpath('//xliff:trans-unit') as $translation) {
            $attributes = $translation->attributes();

            if (!(isset($attributes['resname']) || isset($translation->source)) || !isset($translation->target)) {
                continue;
            }

            $source = isset($attributes['resname']) && $attributes['resname'] ? $attributes['resname'] : $translation->source;
            $target = (string) $translation->target;

            // If the xlf file has another encoding specified, try to convert it because
            // simple_xml will always return utf-8 encoded values
            if ('UTF-8' !== $encoding && !empty($encoding)) {
                if (function_exists('mb_convert_encoding')) {
                    $target = mb_convert_encoding($target, $encoding, 'UTF-8');
                } elseif (function_exists('iconv')) {
                    $target = iconv('UTF-8', $encoding, $target);
                } else {
                    throw new \RuntimeException('No suitable convert encoding function (use UTF-8 as your encoding or install the iconv or mbstring extension).');
                }
            }

            $catalogue->set((string) $source, $target, $domain);
        }
        $catalogue->addResource(new FileResource($resource));

        return $catalogue;
    }

    /**
     * Validates and parses the given file into a SimpleXMLElement
     *
     * @param string $file
     *
     * @throws \RuntimeException
     *
     * @return \SimpleXMLElement
     *
     * @throws InvalidResourceException
     */
    private function parseFile($file)
    {
        $internalErrors = libxml_use_internal_errors(true);
        $disableEntities = libxml_disable_entity_loader(true);
        libxml_clear_errors();

        $dom = new \DOMDocument();
        $dom->validateOnParse = true;
        if (!@$dom->loadXML(file_get_contents($file), LIBXML_NONET | (defined('LIBXML_COMPACT') ? LIBXML_COMPACT : 0))) {
            libxml_disable_entity_loader($disableEntities);

            throw new InvalidResourceException(implode("\n", $this->getXmlErrors($internalErrors)));
        }

        libxml_disable_entity_loader($disableEntities);

        foreach ($dom->childNodes as $child) {
            if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) {
                libxml_use_internal_errors($internalErrors);

                throw new InvalidResourceException('Document types are not allowed.');
            }
        }

        $location = str_replace('\\', '/', __DIR__).'/schema/dic/xliff-core/xml.xsd';
        $parts = explode('/', $location);
        if (0 === stripos($location, 'phar://')) {
            $tmpfile = tempnam(sys_get_temp_dir(), 'sf2');
            if ($tmpfile) {
                copy($location, $tmpfile);
                $parts = explode('/', str_replace('\\', '/', $tmpfile));
            }
        }
        $drive = '\\' === DIRECTORY_SEPARATOR ? array_shift($parts).'/' : '';
        $location = 'file:///'.$drive.implode('/', array_map('rawurlencode', $parts));

        $source = file_get_contents(__DIR__.'/schema/dic/xliff-core/xliff-core-1.2-strict.xsd');
        $source = str_replace('http://www.w3.org/2001/xml.xsd', $location, $source);

        if (!@$dom->schemaValidateSource($source)) {
            throw new InvalidResourceException(implode("\n", $this->getXmlErrors($internalErrors)));
        }

        $dom->normalizeDocument();

        libxml_use_internal_errors($internalErrors);

        return array(simplexml_import_dom($dom), strtoupper($dom->encoding));
    }

    /**
     * Returns the XML errors of the internal XML parser
     *
     * @param Boolean $internalErrors
     *
     * @return array An array of errors
     */
    private function getXmlErrors($internalErrors)
    {
        $errors = array();
        foreach (libxml_get_errors() as $error) {
            $errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)',
                LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR',
                $error->code,
                trim($error->message),
                $error->file ? $error->file : 'n/a',
                $error->line,
                $error->column
            );
        }

        libxml_clear_errors();
        libxml_use_internal_errors($internalErrors);

        return $errors;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;

/**
 * LoaderInterface is the interface implemented by all translation loaders.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface LoaderInterface
{
    /**
     * Loads a locale.
     *
     * @param mixed  $resource A resource
     * @param string $locale   A locale
     * @param string $domain   The domain
     *
     * @return MessageCatalogue A MessageCatalogue instance
     *
     * @api
     *
     * @throws NotFoundResourceException when the resource cannot be found
     * @throws InvalidResourceException  when the resource cannot be loaded
     */
    public function load($resource, $locale, $domain = 'messages');
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Config\Resource\FileResource;

/**
 * IcuResFileLoader loads translations from a resource bundle.
 *
 * @author stealth35
 */
class IcuDatFileLoader extends IcuResFileLoader
{
    /**
     * {@inheritdoc}
     */
    public function load($resource, $locale, $domain = 'messages')
    {
        if (!stream_is_local($resource.'.dat')) {
            throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
        }

        if (!file_exists($resource.'.dat')) {
            throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
        }

        $rb = new \ResourceBundle($locale, $resource);

        if (!$rb) {
            throw new InvalidResourceException(sprintf('Cannot load resource "%s"', $resource));
        } elseif (intl_is_failure($rb->getErrorCode())) {
            throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode());
        }

        $messages = $this->flatten($rb);
        $catalogue = new MessageCatalogue($locale);
        $catalogue->add($messages, $domain);
        $catalogue->addResource(new FileResource($resource.'.dat'));

        return $catalogue;
    }
}
<?xml version='1.0'?>
<?xml-stylesheet href="../2008/09/xsd.xsl" type="text/xsl"?>
<xs:schema targetNamespace="http://www.w3.org/XML/1998/namespace" 
  xmlns:xs="http://www.w3.org/2001/XMLSchema" 
  xmlns   ="http://www.w3.org/1999/xhtml"
  xml:lang="en">

 <xs:annotation>
  <xs:documentation>
   <div>
    <h1>About the XML namespace</h1>

    <div class="bodytext">
     <p>

      This schema document describes the XML namespace, in a form
      suitable for import by other schema documents.
     </p>
     <p>
      See <a href="http://www.w3.org/XML/1998/namespace.html">
      http://www.w3.org/XML/1998/namespace.html</a> and
      <a href="http://www.w3.org/TR/REC-xml">
      http://www.w3.org/TR/REC-xml</a> for information 
      about this namespace.
     </p>

     <p>
      Note that local names in this namespace are intended to be
      defined only by the World Wide Web Consortium or its subgroups.
      The names currently defined in this namespace are listed below.
      They should not be used with conflicting semantics by any Working
      Group, specification, or document instance.
     </p>
     <p>   
      See further below in this document for more information about <a
      href="#usage">how to refer to this schema document from your own
      XSD schema documents</a> and about <a href="#nsversioning">the
      namespace-versioning policy governing this schema document</a>.
     </p>
    </div>
   </div>

  </xs:documentation>
 </xs:annotation>

 <xs:attribute name="lang">
  <xs:annotation>
   <xs:documentation>
    <div>
     
      <h3>lang (as an attribute name)</h3>
      <p>

       denotes an attribute whose value
       is a language code for the natural language of the content of
       any element; its value is inherited.  This name is reserved
       by virtue of its definition in the XML specification.</p>
     
    </div>
    <div>
     <h4>Notes</h4>
     <p>
      Attempting to install the relevant ISO 2- and 3-letter
      codes as the enumerated possible values is probably never
      going to be a realistic possibility.  
     </p>
     <p>

      See BCP 47 at <a href="http://www.rfc-editor.org/rfc/bcp/bcp47.txt">
       http://www.rfc-editor.org/rfc/bcp/bcp47.txt</a>
      and the IANA language subtag registry at
      <a href="http://www.iana.org/assignments/language-subtag-registry">
       http://www.iana.org/assignments/language-subtag-registry</a>
      for further information.
     </p>
     <p>

      The union allows for the 'un-declaration' of xml:lang with
      the empty string.
     </p>
    </div>
   </xs:documentation>
  </xs:annotation>
  <xs:simpleType>
   <xs:union memberTypes="xs:language">
    <xs:simpleType>    
     <xs:restriction base="xs:string">
      <xs:enumeration value=""/>

     </xs:restriction>
    </xs:simpleType>
   </xs:union>
  </xs:simpleType>
 </xs:attribute>

 <xs:attribute name="space">
  <xs:annotation>
   <xs:documentation>

    <div>
     
      <h3>space (as an attribute name)</h3>
      <p>
       denotes an attribute whose
       value is a keyword indicating what whitespace processing
       discipline is intended for the content of the element; its
       value is inherited.  This name is reserved by virtue of its
       definition in the XML specification.</p>
     
    </div>
   </xs:documentation>
  </xs:annotation>
  <xs:simpleType>

   <xs:restriction base="xs:NCName">
    <xs:enumeration value="default"/>
    <xs:enumeration value="preserve"/>
   </xs:restriction>
  </xs:simpleType>
 </xs:attribute>
 
 <xs:attribute name="base" type="xs:anyURI"> <xs:annotation>
   <xs:documentation>

    <div>
     
      <h3>base (as an attribute name)</h3>
      <p>
       denotes an attribute whose value
       provides a URI to be used as the base for interpreting any
       relative URIs in the scope of the element on which it
       appears; its value is inherited.  This name is reserved
       by virtue of its definition in the XML Base specification.</p>
     
     <p>
      See <a
      href="http://www.w3.org/TR/xmlbase/">http://www.w3.org/TR/xmlbase/</a>
      for information about this attribute.
     </p>

    </div>
   </xs:documentation>
  </xs:annotation>
 </xs:attribute>
 
 <xs:attribute name="id" type="xs:ID">
  <xs:annotation>
   <xs:documentation>
    <div>
     
      <h3>id (as an attribute name)</h3> 
      <p>

       denotes an attribute whose value
       should be interpreted as if declared to be of type ID.
       This name is reserved by virtue of its definition in the
       xml:id specification.</p>
     
     <p>
      See <a
      href="http://www.w3.org/TR/xml-id/">http://www.w3.org/TR/xml-id/</a>
      for information about this attribute.
     </p>
    </div>
   </xs:documentation>
  </xs:annotation>

 </xs:attribute>

 <xs:attributeGroup name="specialAttrs">
  <xs:attribute ref="xml:base"/>
  <xs:attribute ref="xml:lang"/>
  <xs:attribute ref="xml:space"/>
  <xs:attribute ref="xml:id"/>
 </xs:attributeGroup>

 <xs:annotation>

  <xs:documentation>
   <div>
   
    <h3>Father (in any context at all)</h3> 

    <div class="bodytext">
     <p>
      denotes Jon Bosak, the chair of 
      the original XML Working Group.  This name is reserved by 
      the following decision of the W3C XML Plenary and 
      XML Coordination groups:
     </p>
     <blockquote>
       <p>

	In appreciation for his vision, leadership and
	dedication the W3C XML Plenary on this 10th day of
	February, 2000, reserves for Jon Bosak in perpetuity
	the XML name "xml:Father".
       </p>
     </blockquote>
    </div>
   </div>
  </xs:documentation>
 </xs:annotation>

 <xs:annotation>
  <xs:documentation>

   <div xml:id="usage" id="usage">
    <h2><a name="usage">About this schema document</a></h2>

    <div class="bodytext">
     <p>
      This schema defines attributes and an attribute group suitable
      for use by schemas wishing to allow <code>xml:base</code>,
      <code>xml:lang</code>, <code>xml:space</code> or
      <code>xml:id</code> attributes on elements they define.
     </p>

     <p>
      To enable this, such a schema must import this schema for
      the XML namespace, e.g. as follows:
     </p>
     <pre>
          &lt;schema.. .>
          .. .
           &lt;import namespace="http://www.w3.org/XML/1998/namespace"
                      schemaLocation="http://www.w3.org/2001/xml.xsd"/>
     </pre>
     <p>
      or
     </p>
     <pre>

           &lt;import namespace="http://www.w3.org/XML/1998/namespace"
                      schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
     </pre>
     <p>
      Subsequently, qualified reference to any of the attributes or the
      group defined below will have the desired effect, e.g.
     </p>
     <pre>
          &lt;type.. .>
          .. .
           &lt;attributeGroup ref="xml:specialAttrs"/>
     </pre>
     <p>
      will define a type which will schema-validate an instance element
      with any of those attributes.
     </p>

    </div>
   </div>
  </xs:documentation>
 </xs:annotation>

 <xs:annotation>
  <xs:documentation>
   <div id="nsversioning" xml:id="nsversioning">
    <h2><a name="nsversioning">Versioning policy for this schema document</a></h2>

    <div class="bodytext">
     <p>
      In keeping with the XML Schema WG's standard versioning
      policy, this schema document will persist at
      <a href="http://www.w3.org/2009/01/xml.xsd">
       http://www.w3.org/2009/01/xml.xsd</a>.
     </p>
     <p>
      At the date of issue it can also be found at
      <a href="http://www.w3.org/2001/xml.xsd">
       http://www.w3.org/2001/xml.xsd</a>.
     </p>

     <p>
      The schema document at that URI may however change in the future,
      in order to remain compatible with the latest version of XML
      Schema itself, or with the XML namespace itself.  In other words,
      if the XML Schema or XML namespaces change, the version of this
      document at <a href="http://www.w3.org/2001/xml.xsd">
       http://www.w3.org/2001/xml.xsd 
      </a> 
      will change accordingly; the version at 
      <a href="http://www.w3.org/2009/01/xml.xsd">
       http://www.w3.org/2009/01/xml.xsd 
      </a> 
      will not change.
     </p>
     <p>

      Previous dated (and unchanging) versions of this schema 
      document are at:
     </p>
     <ul>
      <li><a href="http://www.w3.org/2009/01/xml.xsd">
	http://www.w3.org/2009/01/xml.xsd</a></li>
      <li><a href="http://www.w3.org/2007/08/xml.xsd">
	http://www.w3.org/2007/08/xml.xsd</a></li>
      <li><a href="http://www.w3.org/2004/10/xml.xsd">

	http://www.w3.org/2004/10/xml.xsd</a></li>
      <li><a href="http://www.w3.org/2001/03/xml.xsd">
	http://www.w3.org/2001/03/xml.xsd</a></li>
     </ul>
    </div>
   </div>
  </xs:documentation>
 </xs:annotation>

</xs:schema>
<?xml version="1.0" encoding="UTF-8"?>

<!--

May-19-2004:
- Changed the <choice> for ElemType_header, moving minOccurs="0" maxOccurs="unbounded" from its elements 
to <choice> itself.
- Added <choice> for ElemType_trans-unit to allow "any order" for <context-group>, <count-group>, <prop-group>, <note>, and
<alt-trans>.

Oct-2005
- updated version info to 1.2
- equiv-trans attribute to <trans-unit> element 
- merged-trans attribute for <group> element
- Add the <seg-source> element as optional in the <trans-unit> and <alt-trans> content models, at the same level as <source> 
- Create a new value "seg" for the mtype attribute of the <mrk> element
- Add mid as an optional attribute for the <alt-trans> element

Nov-14-2005
- Changed name attribute for <context-group> from required to optional
- Added extension point at <xliff>

Jan-9-2006
- Added alttranstype type attribute to <alt-trans>, and values

Jan-10-2006
- Corrected error with overwritten purposeValueList
- Corrected name="AttrType_Version",  attribute should have been "name"

-->
<xsd:schema xmlns:xlf="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="urn:oasis:names:tc:xliff:document:1.2" xml:lang="en">
  <!-- Import for xml:lang and xml:space -->
  <xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd"/>
  <!-- Attributes Lists -->
  <xsd:simpleType name="XTend">
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="x-[^\s]+"/>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="context-typeValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'context-type'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="database">
        <xsd:annotation>
          <xsd:documentation>Indicates a database content.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="element">
        <xsd:annotation>
          <xsd:documentation>Indicates the content of an element within an XML document.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="elementtitle">
        <xsd:annotation>
          <xsd:documentation>Indicates the name of an element within an XML document.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="linenumber">
        <xsd:annotation>
          <xsd:documentation>Indicates the line number from the sourcefile (see context-type="sourcefile") where the &lt;source&gt; is found.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="numparams">
        <xsd:annotation>
          <xsd:documentation>Indicates a the number of parameters contained within the &lt;source&gt;.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="paramnotes">
        <xsd:annotation>
          <xsd:documentation>Indicates notes pertaining to the parameters in the &lt;source&gt;.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="record">
        <xsd:annotation>
          <xsd:documentation>Indicates the content of a record within a database.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="recordtitle">
        <xsd:annotation>
          <xsd:documentation>Indicates the name of a record within a database.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="sourcefile">
        <xsd:annotation>
          <xsd:documentation>Indicates the original source file in the case that multiple files are merged to form the original file from which the XLIFF file is created. This differs from the original &lt;file&gt; attribute in that this sourcefile is one of many that make up that file.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="count-typeValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'count-type'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="num-usages">
        <xsd:annotation>
          <xsd:documentation>Indicates the count units are items that are used X times in a certain context; example: this is a reusable text unit which is used 42 times in other texts.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="repetition">
        <xsd:annotation>
          <xsd:documentation>Indicates the count units are translation units existing already in the same document.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="total">
        <xsd:annotation>
          <xsd:documentation>Indicates a total count.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="InlineDelimitersValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'ctype' when used other elements than &lt;ph&gt; or &lt;x&gt;.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="bold">
        <xsd:annotation>
          <xsd:documentation>Indicates a run of bolded text.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="italic">
        <xsd:annotation>
          <xsd:documentation>Indicates a run of text in italics.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="underlined">
        <xsd:annotation>
          <xsd:documentation>Indicates a run of underlined text.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="link">
        <xsd:annotation>
          <xsd:documentation>Indicates a run of hyper-text.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="InlinePlaceholdersValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'ctype' when used with &lt;ph&gt; or &lt;x&gt;.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="image">
        <xsd:annotation>
          <xsd:documentation>Indicates a inline image.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="pb">
        <xsd:annotation>
          <xsd:documentation>Indicates a page break.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="lb">
        <xsd:annotation>
          <xsd:documentation>Indicates a line break.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="mime-typeValueList">
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="(text|multipart|message|application|image|audio|video|model)(/.+)*"/>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="datatypeValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'datatype'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="asp">
        <xsd:annotation>
          <xsd:documentation>Indicates Active Server Page data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="c">
        <xsd:annotation>
          <xsd:documentation>Indicates C source file data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="cdf">
        <xsd:annotation>
          <xsd:documentation>Indicates Channel Definition Format (CDF) data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="cfm">
        <xsd:annotation>
          <xsd:documentation>Indicates ColdFusion data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="cpp">
        <xsd:annotation>
          <xsd:documentation>Indicates C++ source file data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="csharp">
        <xsd:annotation>
          <xsd:documentation>Indicates C-Sharp data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="cstring">
        <xsd:annotation>
          <xsd:documentation>Indicates strings from C, ASM, and driver files data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="csv">
        <xsd:annotation>
          <xsd:documentation>Indicates comma-separated values data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="database">
        <xsd:annotation>
          <xsd:documentation>Indicates database data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="documentfooter">
        <xsd:annotation>
          <xsd:documentation>Indicates portions of document that follows data and contains metadata.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="documentheader">
        <xsd:annotation>
          <xsd:documentation>Indicates portions of document that precedes data and contains metadata.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="filedialog">
        <xsd:annotation>
          <xsd:documentation>Indicates data from standard UI file operations dialogs (e.g., Open, Save, Save As, Export, Import).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="form">
        <xsd:annotation>
          <xsd:documentation>Indicates standard user input screen data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="html">
        <xsd:annotation>
          <xsd:documentation>Indicates HyperText Markup Language (HTML) data - document instance.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="htmlbody">
        <xsd:annotation>
          <xsd:documentation>Indicates content within an HTML document’s &lt;body&gt; element.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="ini">
        <xsd:annotation>
          <xsd:documentation>Indicates Windows INI file data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="interleaf">
        <xsd:annotation>
          <xsd:documentation>Indicates Interleaf data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="javaclass">
        <xsd:annotation>
          <xsd:documentation>Indicates Java source file data (extension '.java').</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="javapropertyresourcebundle">
        <xsd:annotation>
          <xsd:documentation>Indicates Java property resource bundle data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="javalistresourcebundle">
        <xsd:annotation>
          <xsd:documentation>Indicates Java list resource bundle data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="javascript">
        <xsd:annotation>
          <xsd:documentation>Indicates JavaScript source file data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="jscript">
        <xsd:annotation>
          <xsd:documentation>Indicates JScript source file data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="layout">
        <xsd:annotation>
          <xsd:documentation>Indicates information relating to formatting.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="lisp">
        <xsd:annotation>
          <xsd:documentation>Indicates LISP source file data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="margin">
        <xsd:annotation>
          <xsd:documentation>Indicates information relating to margin formats.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="menufile">
        <xsd:annotation>
          <xsd:documentation>Indicates a file containing menu.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="messagefile">
        <xsd:annotation>
          <xsd:documentation>Indicates numerically identified string table.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="mif">
        <xsd:annotation>
          <xsd:documentation>Indicates Maker Interchange Format (MIF) data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="mimetype">
        <xsd:annotation>
          <xsd:documentation>Indicates that the datatype attribute value is a MIME Type value and is defined in the mime-type attribute.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="mo">
        <xsd:annotation>
          <xsd:documentation>Indicates GNU Machine Object data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="msglib">
        <xsd:annotation>
          <xsd:documentation>Indicates Message Librarian strings created by Novell's Message Librarian Tool.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="pagefooter">
        <xsd:annotation>
          <xsd:documentation>Indicates information to be displayed at the bottom of each page of a document.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="pageheader">
        <xsd:annotation>
          <xsd:documentation>Indicates information to be displayed at the top of each page of a document.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="parameters">
        <xsd:annotation>
          <xsd:documentation>Indicates a list of property values (e.g., settings within INI files or preferences dialog).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="pascal">
        <xsd:annotation>
          <xsd:documentation>Indicates Pascal source file data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="php">
        <xsd:annotation>
          <xsd:documentation>Indicates Hypertext Preprocessor data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="plaintext">
        <xsd:annotation>
          <xsd:documentation>Indicates plain text file (no formatting other than, possibly, wrapping).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="po">
        <xsd:annotation>
          <xsd:documentation>Indicates GNU Portable Object file.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="report">
        <xsd:annotation>
          <xsd:documentation>Indicates dynamically generated user defined document. e.g. Oracle Report, Crystal Report, etc.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="resources">
        <xsd:annotation>
          <xsd:documentation>Indicates Windows .NET binary resources.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="resx">
        <xsd:annotation>
          <xsd:documentation>Indicates Windows .NET Resources.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="rtf">
        <xsd:annotation>
          <xsd:documentation>Indicates Rich Text Format (RTF) data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="sgml">
        <xsd:annotation>
          <xsd:documentation>Indicates Standard Generalized Markup Language (SGML) data - document instance.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="sgmldtd">
        <xsd:annotation>
          <xsd:documentation>Indicates Standard Generalized Markup Language (SGML) data - Document Type Definition (DTD).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="svg">
        <xsd:annotation>
          <xsd:documentation>Indicates Scalable Vector Graphic (SVG) data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="vbscript">
        <xsd:annotation>
          <xsd:documentation>Indicates VisualBasic Script source file.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="warning">
        <xsd:annotation>
          <xsd:documentation>Indicates warning message.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="winres">
        <xsd:annotation>
          <xsd:documentation>Indicates Windows (Win32) resources (i.e. resources extracted from an RC script, a message file, or a compiled file).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="xhtml">
        <xsd:annotation>
          <xsd:documentation>Indicates Extensible HyperText Markup Language (XHTML) data - document instance.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="xml">
        <xsd:annotation>
          <xsd:documentation>Indicates Extensible Markup Language (XML) data - document instance.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="xmldtd">
        <xsd:annotation>
          <xsd:documentation>Indicates Extensible Markup Language (XML) data - Document Type Definition (DTD).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="xsl">
        <xsd:annotation>
          <xsd:documentation>Indicates Extensible Stylesheet Language (XSL) data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="xul">
        <xsd:annotation>
          <xsd:documentation>Indicates XUL elements.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="mtypeValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'mtype'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="abbrev">
        <xsd:annotation>
          <xsd:documentation>Indicates the marked text is an abbreviation.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="abbreviated-form">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.8: A term resulting from the omission of any part of the full term while designating the same concept.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="abbreviation">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.8.1: An abbreviated form of a simple term resulting from the omission of some of its letters (e.g. 'adj.' for 'adjective').</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="acronym">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.8.4: An abbreviated form of a term made up of letters from the full form of a multiword term strung together into a sequence pronounced only syllabically (e.g. 'radar' for 'radio detecting and ranging').</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="appellation">
        <xsd:annotation>
          <xsd:documentation>ISO-12620: A proper-name term, such as the name of an agency or other proper entity.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="collocation">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.18.1: A recurrent word combination characterized by cohesion in that the components of the collocation must co-occur within an utterance or series of utterances, even though they do not necessarily have to maintain immediate proximity to one another.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="common-name">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.5: A synonym for an international scientific term that is used in general discourse in a given language.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="datetime">
        <xsd:annotation>
          <xsd:documentation>Indicates the marked text is a date and/or time.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="equation">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.15: An expression used to represent a concept based on a statement that two mathematical expressions are, for instance, equal as identified by the equal sign (=), or assigned to one another by a similar sign.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="expanded-form">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.7: The complete representation of a term for which there is an abbreviated form.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="formula">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.14: Figures, symbols or the like used to express a concept briefly, such as a mathematical or chemical formula.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="head-term">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.1: The concept designation that has been chosen to head a terminological record.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="initialism">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.8.3: An abbreviated form of a term consisting of some of the initial letters of the words making up a multiword term or the term elements making up a compound term when these letters are pronounced individually (e.g. 'BSE' for 'bovine spongiform encephalopathy').</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="international-scientific-term">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.4: A term that is part of an international scientific nomenclature as adopted by an appropriate scientific body.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="internationalism">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.6: A term that has the same or nearly identical orthographic or phonemic form in many languages.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="logical-expression">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.16: An expression used to represent a concept based on mathematical or logical relations, such as statements of inequality, set relationships, Boolean operations, and the like.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="materials-management-unit">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.17: A unit to track object.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="name">
        <xsd:annotation>
          <xsd:documentation>Indicates the marked text is a name.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="near-synonym">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.3: A term that represents the same or a very similar concept as another term in the same language, but for which interchangeability is limited to some contexts and inapplicable in others.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="part-number">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.17.2: A unique alphanumeric designation assigned to an object in a manufacturing system.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="phrase">
        <xsd:annotation>
          <xsd:documentation>Indicates the marked text is a phrase.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="phraseological-unit">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.18: Any group of two or more words that form a unit, the meaning of which frequently cannot be deduced based on the combined sense of the words making up the phrase.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="protected">
        <xsd:annotation>
          <xsd:documentation>Indicates the marked text should not be translated.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="romanized-form">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.12: A form of a term resulting from an operation whereby non-Latin writing systems are converted to the Latin alphabet.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="seg">
        <xsd:annotation>
          <xsd:documentation>Indicates that the marked text represents a segment.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="set-phrase">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.18.2: A fixed, lexicalized phrase.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="short-form">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.8.2: A variant of a multiword term that includes fewer words than the full form of the term (e.g. 'Group of Twenty-four' for 'Intergovernmental Group of Twenty-four on International Monetary Affairs').</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="sku">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.17.1: Stock keeping unit, an inventory item identified by a unique alphanumeric designation assigned to an object in an inventory control system.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="standard-text">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.19: A fixed chunk of recurring text.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="symbol">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.13: A designation of a concept by letters, numerals, pictograms or any combination thereof.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="synonym">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.2: Any term that represents the same or a very similar concept as the main entry term in a term entry.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="synonymous-phrase">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.18.3: Phraseological unit in a language that expresses the same semantic content as another phrase in that same language.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="term">
        <xsd:annotation>
          <xsd:documentation>Indicates the marked text is a term.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="transcribed-form">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.11: A form of a term resulting from an operation whereby the characters of one writing system are represented by characters from another writing system, taking into account the pronunciation of the characters converted.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="transliterated-form">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.10: A form of a term resulting from an operation whereby the characters of an alphabetic writing system are represented by characters from another alphabetic writing system.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="truncated-term">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.8.5: An abbreviated form of a term resulting from the omission of one or more term elements or syllables (e.g. 'flu' for 'influenza').</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="variant">
        <xsd:annotation>
          <xsd:documentation>ISO-12620 2.1.9: One of the alternate forms of a term.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="restypeValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'restype'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="auto3state">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC AUTO3STATE control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="autocheckbox">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC AUTOCHECKBOX control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="autoradiobutton">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC AUTORADIOBUTTON control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="bedit">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC BEDIT control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="bitmap">
        <xsd:annotation>
          <xsd:documentation>Indicates a bitmap, for example a BITMAP resource in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="button">
        <xsd:annotation>
          <xsd:documentation>Indicates a button object, for example a BUTTON control Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="caption">
        <xsd:annotation>
          <xsd:documentation>Indicates a caption, such as the caption of a dialog box.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="cell">
        <xsd:annotation>
          <xsd:documentation>Indicates the cell in a table, for example the content of the &lt;td&gt; element in HTML.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="checkbox">
        <xsd:annotation>
          <xsd:documentation>Indicates check box object, for example a CHECKBOX control in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="checkboxmenuitem">
        <xsd:annotation>
          <xsd:documentation>Indicates a menu item with an associated checkbox.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="checkedlistbox">
        <xsd:annotation>
          <xsd:documentation>Indicates a list box, but with a check-box for each item.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="colorchooser">
        <xsd:annotation>
          <xsd:documentation>Indicates a color selection dialog.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="combobox">
        <xsd:annotation>
          <xsd:documentation>Indicates a combination of edit box and listbox object, for example a COMBOBOX control in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="comboboxexitem">
        <xsd:annotation>
          <xsd:documentation>Indicates an initialization entry of an extended combobox DLGINIT resource block. (code 0x1234).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="comboboxitem">
        <xsd:annotation>
          <xsd:documentation>Indicates an initialization entry of a combobox DLGINIT resource block (code 0x0403).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="component">
        <xsd:annotation>
          <xsd:documentation>Indicates a UI base class element that cannot be represented by any other element.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="contextmenu">
        <xsd:annotation>
          <xsd:documentation>Indicates a context menu.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="ctext">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC CTEXT control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="cursor">
        <xsd:annotation>
          <xsd:documentation>Indicates a cursor, for example a CURSOR resource in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="datetimepicker">
        <xsd:annotation>
          <xsd:documentation>Indicates a date/time picker.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="defpushbutton">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC DEFPUSHBUTTON control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="dialog">
        <xsd:annotation>
          <xsd:documentation>Indicates a dialog box.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="dlginit">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC DLGINIT resource block.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="edit">
        <xsd:annotation>
          <xsd:documentation>Indicates an edit box object, for example an EDIT control in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="file">
        <xsd:annotation>
          <xsd:documentation>Indicates a filename.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="filechooser">
        <xsd:annotation>
          <xsd:documentation>Indicates a file dialog.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="fn">
        <xsd:annotation>
          <xsd:documentation>Indicates a footnote.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="font">
        <xsd:annotation>
          <xsd:documentation>Indicates a font name.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="footer">
        <xsd:annotation>
          <xsd:documentation>Indicates a footer.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="frame">
        <xsd:annotation>
          <xsd:documentation>Indicates a frame object.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="grid">
        <xsd:annotation>
          <xsd:documentation>Indicates a XUL grid element.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="groupbox">
        <xsd:annotation>
          <xsd:documentation>Indicates a groupbox object, for example a GROUPBOX control in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="header">
        <xsd:annotation>
          <xsd:documentation>Indicates a header item.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="heading">
        <xsd:annotation>
          <xsd:documentation>Indicates a heading, such has the content of &lt;h1&gt;, &lt;h2&gt;, etc. in HTML.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="hedit">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC HEDIT control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="hscrollbar">
        <xsd:annotation>
          <xsd:documentation>Indicates a horizontal scrollbar.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="icon">
        <xsd:annotation>
          <xsd:documentation>Indicates an icon, for example an ICON resource in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="iedit">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC IEDIT control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="keywords">
        <xsd:annotation>
          <xsd:documentation>Indicates keyword list, such as the content of the Keywords meta-data in HTML, or a K footnote in WinHelp RTF.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="label">
        <xsd:annotation>
          <xsd:documentation>Indicates a label object.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="linklabel">
        <xsd:annotation>
          <xsd:documentation>Indicates a label that is also a HTML link (not necessarily a URL).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="list">
        <xsd:annotation>
          <xsd:documentation>Indicates a list (a group of list-items, for example an &lt;ol&gt; or &lt;ul&gt; element in HTML).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="listbox">
        <xsd:annotation>
          <xsd:documentation>Indicates a listbox object, for example an LISTBOX control in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="listitem">
        <xsd:annotation>
          <xsd:documentation>Indicates an list item (an entry in a list).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="ltext">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC LTEXT control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="menu">
        <xsd:annotation>
          <xsd:documentation>Indicates a menu (a group of menu-items).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="menubar">
        <xsd:annotation>
          <xsd:documentation>Indicates a toolbar containing one or more tope level menus.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="menuitem">
        <xsd:annotation>
          <xsd:documentation>Indicates a menu item (an entry in a menu).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="menuseparator">
        <xsd:annotation>
          <xsd:documentation>Indicates a XUL menuseparator element.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="message">
        <xsd:annotation>
          <xsd:documentation>Indicates a message, for example an entry in a MESSAGETABLE resource in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="monthcalendar">
        <xsd:annotation>
          <xsd:documentation>Indicates a calendar control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="numericupdown">
        <xsd:annotation>
          <xsd:documentation>Indicates an edit box beside a spin control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="panel">
        <xsd:annotation>
          <xsd:documentation>Indicates a catch all for rectangular areas.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="popupmenu">
        <xsd:annotation>
          <xsd:documentation>Indicates a standalone menu not necessarily associated with a menubar.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="pushbox">
        <xsd:annotation>
          <xsd:documentation>Indicates a pushbox object, for example a PUSHBOX control in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="pushbutton">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC PUSHBUTTON control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="radio">
        <xsd:annotation>
          <xsd:documentation>Indicates a radio button object.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="radiobuttonmenuitem">
        <xsd:annotation>
          <xsd:documentation>Indicates a menuitem with associated radio button.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="rcdata">
        <xsd:annotation>
          <xsd:documentation>Indicates raw data resources for an application.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="row">
        <xsd:annotation>
          <xsd:documentation>Indicates a row in a table.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="rtext">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC RTEXT control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="scrollpane">
        <xsd:annotation>
          <xsd:documentation>Indicates a user navigable container used to show a portion of a document.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="separator">
        <xsd:annotation>
          <xsd:documentation>Indicates a generic divider object (e.g. menu group separator).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="shortcut">
        <xsd:annotation>
          <xsd:documentation>Windows accelerators, shortcuts in resource or property files.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="spinner">
        <xsd:annotation>
          <xsd:documentation>Indicates a UI control to indicate process activity but not progress.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="splitter">
        <xsd:annotation>
          <xsd:documentation>Indicates a splitter bar.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="state3">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC STATE3 control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="statusbar">
        <xsd:annotation>
          <xsd:documentation>Indicates a window for providing feedback to the users, like 'read-only', etc.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="string">
        <xsd:annotation>
          <xsd:documentation>Indicates a string, for example an entry in a STRINGTABLE resource in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="tabcontrol">
        <xsd:annotation>
          <xsd:documentation>Indicates a layers of controls with a tab to select layers.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="table">
        <xsd:annotation>
          <xsd:documentation>Indicates a display and edits regular two-dimensional tables of cells.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="textbox">
        <xsd:annotation>
          <xsd:documentation>Indicates a XUL textbox element.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="togglebutton">
        <xsd:annotation>
          <xsd:documentation>Indicates a UI button that can be toggled to on or off state.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="toolbar">
        <xsd:annotation>
          <xsd:documentation>Indicates an array of controls, usually buttons.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="tooltip">
        <xsd:annotation>
          <xsd:documentation>Indicates a pop up tool tip text.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="trackbar">
        <xsd:annotation>
          <xsd:documentation>Indicates a bar with a pointer indicating a position within a certain range.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="tree">
        <xsd:annotation>
          <xsd:documentation>Indicates a control that displays a set of hierarchical data.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="uri">
        <xsd:annotation>
          <xsd:documentation>Indicates a URI (URN or URL).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="userbutton">
        <xsd:annotation>
          <xsd:documentation>Indicates a Windows RC USERBUTTON control.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="usercontrol">
        <xsd:annotation>
          <xsd:documentation>Indicates a user-defined control like CONTROL control in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="var">
        <xsd:annotation>
          <xsd:documentation>Indicates the text of a variable.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="versioninfo">
        <xsd:annotation>
          <xsd:documentation>Indicates version information about a resource like VERSIONINFO in Windows.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="vscrollbar">
        <xsd:annotation>
          <xsd:documentation>Indicates a vertical scrollbar.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="window">
        <xsd:annotation>
          <xsd:documentation>Indicates a graphical window.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="size-unitValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'size-unit'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="byte">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in 8-bit bytes.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="char">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in Unicode characters.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="col">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in columns. Used for HTML text area.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="cm">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in centimeters.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="dlgunit">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in dialog units, as defined in Windows resources.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="em">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in 'font-size' units (as defined in CSS).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="ex">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in 'x-height' units (as defined in CSS).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="glyph">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in glyphs. A glyph is considered to be one or more combined Unicode characters that represent a single displayable text character. Sometimes referred to as a 'grapheme cluster'</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="in">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in inches.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="mm">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in millimeters.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="percent">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in percentage.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="pixel">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in pixels.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="point">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in point.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="row">
        <xsd:annotation>
          <xsd:documentation>Indicates a size in rows. Used for HTML text area.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="stateValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'state'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="final">
        <xsd:annotation>
          <xsd:documentation>Indicates the terminating state.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="needs-adaptation">
        <xsd:annotation>
          <xsd:documentation>Indicates only non-textual information needs adaptation.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="needs-l10n">
        <xsd:annotation>
          <xsd:documentation>Indicates both text and non-textual information needs adaptation.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="needs-review-adaptation">
        <xsd:annotation>
          <xsd:documentation>Indicates only non-textual information needs review.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="needs-review-l10n">
        <xsd:annotation>
          <xsd:documentation>Indicates both text and non-textual information needs review.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="needs-review-translation">
        <xsd:annotation>
          <xsd:documentation>Indicates that only the text of the item needs to be reviewed.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="needs-translation">
        <xsd:annotation>
          <xsd:documentation>Indicates that the item needs to be translated.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="new">
        <xsd:annotation>
          <xsd:documentation>Indicates that the item is new. For example, translation units that were not in a previous version of the document.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="signed-off">
        <xsd:annotation>
          <xsd:documentation>Indicates that changes are reviewed and approved.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="translated">
        <xsd:annotation>
          <xsd:documentation>Indicates that the item has been translated.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="state-qualifierValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'state-qualifier'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="exact-match">
        <xsd:annotation>
          <xsd:documentation>Indicates an exact match. An exact match occurs when a source text of a segment is exactly the same as the source text of a segment that was translated previously.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="fuzzy-match">
        <xsd:annotation>
          <xsd:documentation>Indicates a fuzzy match. A fuzzy match occurs when a source text of a segment is very similar to the source text of a segment that was translated previously (e.g. when the difference is casing, a few changed words, white-space discripancy, etc.).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="id-match">
        <xsd:annotation>
          <xsd:documentation>Indicates a match based on matching IDs (in addition to matching text).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="leveraged-glossary">
        <xsd:annotation>
          <xsd:documentation>Indicates a translation derived from a glossary.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="leveraged-inherited">
        <xsd:annotation>
          <xsd:documentation>Indicates a translation derived from existing translation.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="leveraged-mt">
        <xsd:annotation>
          <xsd:documentation>Indicates a translation derived from machine translation.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="leveraged-repository">
        <xsd:annotation>
          <xsd:documentation>Indicates a translation derived from a translation repository.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="leveraged-tm">
        <xsd:annotation>
          <xsd:documentation>Indicates a translation derived from a translation memory.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="mt-suggestion">
        <xsd:annotation>
          <xsd:documentation>Indicates the translation is suggested by machine translation.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="rejected-grammar">
        <xsd:annotation>
          <xsd:documentation>Indicates that the item has been rejected because of incorrect grammar.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="rejected-inaccurate">
        <xsd:annotation>
          <xsd:documentation>Indicates that the item has been rejected because it is incorrect.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="rejected-length">
        <xsd:annotation>
          <xsd:documentation>Indicates that the item has been rejected because it is too long or too short.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="rejected-spelling">
        <xsd:annotation>
          <xsd:documentation>Indicates that the item has been rejected because of incorrect spelling.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="tm-suggestion">
        <xsd:annotation>
          <xsd:documentation>Indicates the translation is suggested by translation memory.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="unitValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'unit'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="word">
        <xsd:annotation>
          <xsd:documentation>Refers to words.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="page">
        <xsd:annotation>
          <xsd:documentation>Refers to pages.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="trans-unit">
        <xsd:annotation>
          <xsd:documentation>Refers to &lt;trans-unit&gt; elements.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="bin-unit">
        <xsd:annotation>
          <xsd:documentation>Refers to &lt;bin-unit&gt; elements.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="glyph">
        <xsd:annotation>
          <xsd:documentation>Refers to glyphs.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="item">
        <xsd:annotation>
          <xsd:documentation>Refers to &lt;trans-unit&gt; and/or &lt;bin-unit&gt; elements.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="instance">
        <xsd:annotation>
          <xsd:documentation>Refers to the occurrences of instances defined by the count-type value.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="character">
        <xsd:annotation>
          <xsd:documentation>Refers to characters.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="line">
        <xsd:annotation>
          <xsd:documentation>Refers to lines.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="sentence">
        <xsd:annotation>
          <xsd:documentation>Refers to sentences.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="paragraph">
        <xsd:annotation>
          <xsd:documentation>Refers to paragraphs.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="segment">
        <xsd:annotation>
          <xsd:documentation>Refers to segments.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="placeable">
        <xsd:annotation>
          <xsd:documentation>Refers to placeables (inline elements).</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="priorityValueList">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'priority'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:positiveInteger">
      <xsd:enumeration value="1">
        <xsd:annotation>
          <xsd:documentation>Highest priority.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="2">
        <xsd:annotation>
          <xsd:documentation>High priority.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="3">
        <xsd:annotation>
          <xsd:documentation>High priority, but not as important as 2.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="4">
        <xsd:annotation>
          <xsd:documentation>High priority, but not as important as 3.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="5">
        <xsd:annotation>
          <xsd:documentation>Medium priority, but more important than 6.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="6">
        <xsd:annotation>
          <xsd:documentation>Medium priority, but less important than 5.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="7">
        <xsd:annotation>
          <xsd:documentation>Low priority, but more important than 8.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="8">
        <xsd:annotation>
          <xsd:documentation>Low priority, but more important than 9.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="9">
        <xsd:annotation>
          <xsd:documentation>Low priority.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="10">
        <xsd:annotation>
          <xsd:documentation>Lowest priority.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="reformatValueYesNo">
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="yes">
        <xsd:annotation>
          <xsd:documentation>This value indicates that all properties can be reformatted. This value must be used alone.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="no">
        <xsd:annotation>
          <xsd:documentation>This value indicates that no properties should be reformatted. This value must be used alone.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="reformatValueList">
    <xsd:list>
      <xsd:simpleType>
        <xsd:union memberTypes="xlf:XTend">
          <xsd:simpleType>
            <xsd:restriction base="xsd:string">
              <xsd:enumeration value="coord">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that all information in the coord attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="coord-x">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the x information in the coord attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="coord-y">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the y information in the coord attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="coord-cx">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the cx information in the coord attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="coord-cy">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the cy information in the coord attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="font">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that all the information in the font attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="font-name">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the name information in the font attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="font-size">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the size information in the font attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="font-weight">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the weight information in the font attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="css-style">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the information in the css-style attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="style">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the information in the style attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
              <xsd:enumeration value="ex-style">
                <xsd:annotation>
                  <xsd:documentation>This value indicates that the information in the exstyle attribute can be modified.</xsd:documentation>
                </xsd:annotation>
              </xsd:enumeration>
            </xsd:restriction>
          </xsd:simpleType>
        </xsd:union>
      </xsd:simpleType>
    </xsd:list>
  </xsd:simpleType>
  <xsd:simpleType name="purposeValueList">
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="information">
        <xsd:annotation>
          <xsd:documentation>Indicates that the context is informational in nature, specifying for example, how a term should be translated. Thus, should be displayed to anyone editing the XLIFF document.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="location">
        <xsd:annotation>
          <xsd:documentation>Indicates that the context-group is used to specify where the term was found in the translatable source. Thus, it is not displayed.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="match">
        <xsd:annotation>
          <xsd:documentation>Indicates that the context information should be used during translation memory lookups. Thus, it is not displayed.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="alttranstypeValueList">
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="proposal">
        <xsd:annotation>
          <xsd:documentation>Represents a translation proposal from a translation memory or other resource.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="previous-version">
        <xsd:annotation>
          <xsd:documentation>Represents a previous version of the target element.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="rejected">
        <xsd:annotation>
          <xsd:documentation>Represents a rejected version of the target element.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="reference">
        <xsd:annotation>
          <xsd:documentation>Represents a translation to be used for reference purposes only, for example from a related product or a different language.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
      <xsd:enumeration value="accepted">
        <xsd:annotation>
          <xsd:documentation>Represents a proposed translation that was used for the translation of the trans-unit, possibly modified.</xsd:documentation>
        </xsd:annotation>
      </xsd:enumeration>
    </xsd:restriction>
  </xsd:simpleType>
  <!-- Other Types -->
  <xsd:complexType name="ElemType_ExternalReference">
    <xsd:choice>
      <xsd:element ref="xlf:internal-file"/>
      <xsd:element ref="xlf:external-file"/>
    </xsd:choice>
  </xsd:complexType>
  <xsd:simpleType name="AttrType_purpose">
    <xsd:list>
      <xsd:simpleType>
        <xsd:union memberTypes="xlf:purposeValueList xlf:XTend"/>
      </xsd:simpleType>
    </xsd:list>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_datatype">
    <xsd:union memberTypes="xlf:datatypeValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_restype">
    <xsd:union memberTypes="xlf:restypeValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_alttranstype">
    <xsd:union memberTypes="xlf:alttranstypeValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_context-type">
    <xsd:union memberTypes="xlf:context-typeValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_state">
    <xsd:union memberTypes="xlf:stateValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_state-qualifier">
    <xsd:union memberTypes="xlf:state-qualifierValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_count-type">
    <xsd:union memberTypes="xlf:restypeValueList xlf:count-typeValueList xlf:datatypeValueList xlf:stateValueList xlf:state-qualifierValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_InlineDelimiters">
    <xsd:union memberTypes="xlf:InlineDelimitersValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_InlinePlaceholders">
    <xsd:union memberTypes="xlf:InlinePlaceholdersValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_size-unit">
    <xsd:union memberTypes="xlf:size-unitValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_mtype">
    <xsd:union memberTypes="xlf:mtypeValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_unit">
    <xsd:union memberTypes="xlf:unitValueList xlf:XTend"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_priority">
    <xsd:union memberTypes="xlf:priorityValueList"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_reformat">
    <xsd:union memberTypes="xlf:reformatValueYesNo xlf:reformatValueList"/>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_YesNo">
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="yes"/>
      <xsd:enumeration value="no"/>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_Position">
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="open"/>
      <xsd:enumeration value="close"/>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_assoc">
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="preceding"/>
      <xsd:enumeration value="following"/>
      <xsd:enumeration value="both"/>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_annotates">
    <xsd:restriction base="xsd:NMTOKEN">
      <xsd:enumeration value="source"/>
      <xsd:enumeration value="target"/>
      <xsd:enumeration value="general"/>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_Coordinates">
    <xsd:annotation>
      <xsd:documentation>Values for the attribute 'coord'.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
      <xsd:pattern value="(-?\d+|#);(-?\d+|#);(-?\d+|#);(-?\d+|#)"/>
    </xsd:restriction>
  </xsd:simpleType>
  <xsd:simpleType name="AttrType_Version">
    <xsd:annotation>
      <xsd:documentation>Version values: 1.0 and 1.1 are allowed for backward compatibility.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="1.2"/>
      <xsd:enumeration value="1.1"/>
      <xsd:enumeration value="1.0"/>
    </xsd:restriction>
  </xsd:simpleType>
  <!-- Groups -->
  <xsd:group name="ElemGroup_TextContent">
    <xsd:choice>
      <xsd:element ref="xlf:g"/>
      <xsd:element ref="xlf:bpt"/>
      <xsd:element ref="xlf:ept"/>
      <xsd:element ref="xlf:ph"/>
      <xsd:element ref="xlf:it"/>
      <xsd:element ref="xlf:mrk"/>
      <xsd:element ref="xlf:x"/>
      <xsd:element ref="xlf:bx"/>
      <xsd:element ref="xlf:ex"/>
    </xsd:choice>
  </xsd:group>
  <xsd:attributeGroup name="AttrGroup_TextContent">
    <xsd:attribute name="id" type="xsd:string" use="required"/>
    <xsd:attribute name="xid" type="xsd:string" use="optional"/>
    <xsd:attribute name="equiv-text" type="xsd:string" use="optional"/>
    <xsd:anyAttribute namespace="##other" processContents="strict"/>
  </xsd:attributeGroup>
  <!-- XLIFF Structure -->
  <xsd:element name="xliff">
    <xsd:complexType>
      <xsd:sequence maxOccurs="unbounded">
        <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
        <xsd:element ref="xlf:file"/>
      </xsd:sequence>
      <xsd:attribute name="version" type="xlf:AttrType_Version" use="required"/>
      <xsd:attribute ref="xml:lang" use="optional"/>
      <xsd:anyAttribute namespace="##other" processContents="strict"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="file">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element minOccurs="0" ref="xlf:header"/>
        <xsd:element ref="xlf:body"/>
      </xsd:sequence>
      <xsd:attribute name="original" type="xsd:string" use="required"/>
      <xsd:attribute name="source-language" type="xsd:language" use="required"/>
      <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="required"/>
      <xsd:attribute name="tool-id" type="xsd:string" use="optional"/>
      <xsd:attribute name="date" type="xsd:dateTime" use="optional"/>
      <xsd:attribute ref="xml:space" use="optional"/>
      <xsd:attribute name="category" type="xsd:string" use="optional"/>
      <xsd:attribute name="target-language" type="xsd:language" use="optional"/>
      <xsd:attribute name="product-name" type="xsd:string" use="optional"/>
      <xsd:attribute name="product-version" type="xsd:string" use="optional"/>
      <xsd:attribute name="build-num" type="xsd:string" use="optional"/>
      <xsd:anyAttribute namespace="##other" processContents="strict"/>
    </xsd:complexType>
    <xsd:unique name="U_group_id">
      <xsd:selector xpath=".//xlf:group"/>
      <xsd:field xpath="@id"/>
    </xsd:unique>
    <xsd:key name="K_unit_id">
      <xsd:selector xpath=".//xlf:trans-unit|.//xlf:bin-unit"/>
      <xsd:field xpath="@id"/>
    </xsd:key>
    <xsd:keyref name="KR_unit_id" refer="xlf:K_unit_id">
      <xsd:selector xpath=".//bpt|.//ept|.//it|.//ph|.//g|.//x|.//bx|.//ex|.//sub"/>
      <xsd:field xpath="@xid"/>
    </xsd:keyref>
    <xsd:key name="K_tool-id">
      <xsd:selector xpath="xlf:header/xlf:tool"/>
      <xsd:field xpath="@tool-id"/>
    </xsd:key>
    <xsd:keyref name="KR_file_tool-id" refer="xlf:K_tool-id">
      <xsd:selector xpath="."/>
      <xsd:field xpath="@tool-id"/>
    </xsd:keyref>
    <xsd:keyref name="KR_phase_tool-id" refer="xlf:K_tool-id">
      <xsd:selector xpath="xlf:header/xlf:phase-group/xlf:phase"/>
      <xsd:field xpath="@tool-id"/>
    </xsd:keyref>
    <xsd:keyref name="KR_alt-trans_tool-id" refer="xlf:K_tool-id">
      <xsd:selector xpath=".//xlf:trans-unit/xlf:alt-trans"/>
      <xsd:field xpath="@tool-id"/>
    </xsd:keyref>
    <xsd:key name="K_count-group_name">
      <xsd:selector xpath=".//xlf:count-group"/>
      <xsd:field xpath="@name"/>
    </xsd:key>
    <xsd:unique name="U_context-group_name">
      <xsd:selector xpath=".//xlf:context-group"/>
      <xsd:field xpath="@name"/>
    </xsd:unique>
    <xsd:key name="K_phase-name">
      <xsd:selector xpath="xlf:header/xlf:phase-group/xlf:phase"/>
      <xsd:field xpath="@phase-name"/>
    </xsd:key>
    <xsd:keyref name="KR_phase-name" refer="xlf:K_phase-name">
      <xsd:selector xpath=".//xlf:count|.//xlf:trans-unit|.//xlf:target|.//bin-unit|.//bin-target"/>
      <xsd:field xpath="@phase-name"/>
    </xsd:keyref>
    <xsd:unique name="U_uid">
      <xsd:selector xpath=".//xlf:external-file"/>
      <xsd:field xpath="@uid"/>
    </xsd:unique>
  </xsd:element>
  <xsd:element name="header">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element minOccurs="0" name="skl" type="xlf:ElemType_ExternalReference"/>
        <xsd:element minOccurs="0" ref="xlf:phase-group"/>
        <xsd:choice maxOccurs="unbounded" minOccurs="0">
          <xsd:element name="glossary" type="xlf:ElemType_ExternalReference"/>
          <xsd:element name="reference" type="xlf:ElemType_ExternalReference"/>
          <xsd:element ref="xlf:count-group"/>
          <xsd:element ref="xlf:note"/>
          <xsd:element ref="xlf:tool"/>
        </xsd:choice>
        <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="internal-file">
    <xsd:complexType>
      <xsd:simpleContent>
        <xsd:extension base="xsd:string">
          <xsd:attribute name="form" type="xsd:string"/>
          <xsd:attribute name="crc" type="xsd:NMTOKEN"/>
        </xsd:extension>
      </xsd:simpleContent>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="external-file">
    <xsd:complexType>
      <xsd:attribute name="href" type="xsd:string" use="required"/>
      <xsd:attribute name="crc" type="xsd:NMTOKEN"/>
      <xsd:attribute name="uid" type="xsd:NMTOKEN"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="note">
    <xsd:complexType>
      <xsd:simpleContent>
        <xsd:extension base="xsd:string">
          <xsd:attribute ref="xml:lang" use="optional"/>
          <xsd:attribute default="1" name="priority" type="xlf:AttrType_priority" use="optional"/>
          <xsd:attribute name="from" type="xsd:string" use="optional"/>
          <xsd:attribute default="general" name="annotates" type="xlf:AttrType_annotates" use="optional"/>
        </xsd:extension>
      </xsd:simpleContent>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="phase-group">
    <xsd:complexType>
      <xsd:sequence maxOccurs="unbounded">
        <xsd:element ref="xlf:phase"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="phase">
    <xsd:complexType>
      <xsd:sequence maxOccurs="unbounded" minOccurs="0">
        <xsd:element ref="xlf:note"/>
      </xsd:sequence>
      <xsd:attribute name="phase-name" type="xsd:string" use="required"/>
      <xsd:attribute name="process-name" type="xsd:string" use="required"/>
      <xsd:attribute name="company-name" type="xsd:string" use="optional"/>
      <xsd:attribute name="tool-id" type="xsd:string" use="optional"/>
      <xsd:attribute name="date" type="xsd:dateTime" use="optional"/>
      <xsd:attribute name="job-id" type="xsd:string" use="optional"/>
      <xsd:attribute name="contact-name" type="xsd:string" use="optional"/>
      <xsd:attribute name="contact-email" type="xsd:string" use="optional"/>
      <xsd:attribute name="contact-phone" type="xsd:string" use="optional"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="count-group">
    <xsd:complexType>
      <xsd:sequence maxOccurs="unbounded" minOccurs="0">
        <xsd:element ref="xlf:count"/>
      </xsd:sequence>
      <xsd:attribute name="name" type="xsd:string" use="required"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="count">
    <xsd:complexType>
      <xsd:simpleContent>
        <xsd:extension base="xsd:string">
          <xsd:attribute name="count-type" type="xlf:AttrType_count-type" use="optional"/>
          <xsd:attribute name="phase-name" type="xsd:string" use="optional"/>
          <xsd:attribute default="word" name="unit" type="xlf:AttrType_unit" use="optional"/>
        </xsd:extension>
      </xsd:simpleContent>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="context-group">
    <xsd:complexType>
      <xsd:sequence maxOccurs="unbounded">
        <xsd:element ref="xlf:context"/>
      </xsd:sequence>
      <xsd:attribute name="name" type="xsd:string" use="optional"/>
      <xsd:attribute name="crc" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="purpose" type="xlf:AttrType_purpose" use="optional"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="context">
    <xsd:complexType>
      <xsd:simpleContent>
        <xsd:extension base="xsd:string">
          <xsd:attribute name="context-type" type="xlf:AttrType_context-type" use="required"/>
          <xsd:attribute default="no" name="match-mandatory" type="xlf:AttrType_YesNo" use="optional"/>
          <xsd:attribute name="crc" type="xsd:NMTOKEN" use="optional"/>
        </xsd:extension>
      </xsd:simpleContent>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="tool">
    <xsd:complexType mixed="true">
      <xsd:sequence>
        <xsd:any namespace="##any" processContents="strict" minOccurs="0" maxOccurs="unbounded"/>
      </xsd:sequence>
      <xsd:attribute name="tool-id" type="xsd:string" use="required"/>
      <xsd:attribute name="tool-name" type="xsd:string" use="required"/>
      <xsd:attribute name="tool-version" type="xsd:string" use="optional"/>
      <xsd:attribute name="tool-company" type="xsd:string" use="optional"/>
      <xsd:anyAttribute namespace="##other" processContents="strict"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="body">
    <xsd:complexType>
      <xsd:choice maxOccurs="unbounded" minOccurs="0">
        <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:group"/>
        <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:trans-unit"/>
        <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:bin-unit"/>
      </xsd:choice>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="group">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:sequence>
          <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:context-group"/>
          <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:count-group"/>
          <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:note"/>
          <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
        </xsd:sequence>
        <xsd:choice maxOccurs="unbounded">
          <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:group"/>
          <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:trans-unit"/>
          <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:bin-unit"/>
        </xsd:choice>
      </xsd:sequence>
      <xsd:attribute name="id" type="xsd:string" use="optional"/>
      <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
      <xsd:attribute default="default" ref="xml:space" use="optional"/>
      <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
      <xsd:attribute name="resname" type="xsd:string" use="optional"/>
      <xsd:attribute name="extradata" type="xsd:string" use="optional"/>
      <xsd:attribute name="extype" type="xsd:string" use="optional"/>
      <xsd:attribute name="help-id" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="menu" type="xsd:string" use="optional"/>
      <xsd:attribute name="menu-option" type="xsd:string" use="optional"/>
      <xsd:attribute name="menu-name" type="xsd:string" use="optional"/>
      <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
      <xsd:attribute name="font" type="xsd:string" use="optional"/>
      <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
      <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute default="yes" name="translate" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:attribute default="yes" name="reformat" type="xlf:AttrType_reformat" use="optional"/>
      <xsd:attribute default="pixel" name="size-unit" type="xlf:AttrType_size-unit" use="optional"/>
      <xsd:attribute name="maxwidth" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="minwidth" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="maxheight" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="minheight" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="maxbytes" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="minbytes" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="charclass" type="xsd:string" use="optional"/>
      <xsd:attribute default="no" name="merged-trans" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:anyAttribute namespace="##other" processContents="strict"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="trans-unit">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element ref="xlf:source"/>
        <xsd:element minOccurs="0" ref="xlf:seg-source"/>
        <xsd:element minOccurs="0" ref="xlf:target"/>
        <xsd:choice maxOccurs="unbounded" minOccurs="0">
          <xsd:element ref="xlf:context-group"/>
          <xsd:element ref="xlf:count-group"/>
          <xsd:element ref="xlf:note"/>
          <xsd:element ref="xlf:alt-trans"/>
        </xsd:choice>
        <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
      </xsd:sequence>
      <xsd:attribute name="id" type="xsd:string" use="required"/>
      <xsd:attribute name="approved" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:attribute default="yes" name="translate" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:attribute default="yes" name="reformat" type="xlf:AttrType_reformat" use="optional"/>
      <xsd:attribute default="default" ref="xml:space" use="optional"/>
      <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
      <xsd:attribute name="phase-name" type="xsd:string" use="optional"/>
      <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
      <xsd:attribute name="resname" type="xsd:string" use="optional"/>
      <xsd:attribute name="extradata" type="xsd:string" use="optional"/>
      <xsd:attribute name="extype" type="xsd:string" use="optional"/>
      <xsd:attribute name="help-id" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="menu" type="xsd:string" use="optional"/>
      <xsd:attribute name="menu-option" type="xsd:string" use="optional"/>
      <xsd:attribute name="menu-name" type="xsd:string" use="optional"/>
      <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
      <xsd:attribute name="font" type="xsd:string" use="optional"/>
      <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
      <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute default="pixel" name="size-unit" type="xlf:AttrType_size-unit" use="optional"/>
      <xsd:attribute name="maxwidth" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="minwidth" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="maxheight" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="minheight" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="maxbytes" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="minbytes" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="charclass" type="xsd:string" use="optional"/>
      <xsd:attribute default="yes" name="merged-trans" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:anyAttribute namespace="##other" processContents="strict"/>
    </xsd:complexType>
    <xsd:unique name="U_tu_segsrc_mid">
      <xsd:selector xpath="./xlf:seg-source/xlf:mrk"/>
      <xsd:field xpath="@mid"/>
    </xsd:unique>
    <xsd:keyref name="KR_tu_segsrc_mid" refer="xlf:U_tu_segsrc_mid">
      <xsd:selector xpath="./xlf:target/xlf:mrk|./xlf:alt-trans"/>
      <xsd:field xpath="@mid"/>
    </xsd:keyref>
  </xsd:element>
  <xsd:element name="source">
    <xsd:complexType mixed="true">
      <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
      <xsd:attribute ref="xml:lang" use="optional"/>
      <xsd:anyAttribute namespace="##other" processContents="strict"/>
    </xsd:complexType>
    <xsd:unique name="U_source_bpt_rid">
      <xsd:selector xpath=".//xlf:bpt"/>
      <xsd:field xpath="@rid"/>
    </xsd:unique>
    <xsd:keyref name="KR_source_ept_rid" refer="xlf:U_source_bpt_rid">
      <xsd:selector xpath=".//xlf:ept"/>
      <xsd:field xpath="@rid"/>
    </xsd:keyref>
    <xsd:unique name="U_source_bx_rid">
      <xsd:selector xpath=".//xlf:bx"/>
      <xsd:field xpath="@rid"/>
    </xsd:unique>
    <xsd:keyref name="KR_source_ex_rid" refer="xlf:U_source_bx_rid">
      <xsd:selector xpath=".//xlf:ex"/>
      <xsd:field xpath="@rid"/>
    </xsd:keyref>
  </xsd:element>
  <xsd:element name="seg-source">
    <xsd:complexType mixed="true">
      <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
      <xsd:attribute ref="xml:lang" use="optional"/>
      <xsd:anyAttribute namespace="##other" processContents="strict"/>
    </xsd:complexType>
    <xsd:unique name="U_segsrc_bpt_rid">
      <xsd:selector xpath=".//xlf:bpt"/>
      <xsd:field xpath="@rid"/>
    </xsd:unique>
    <xsd:keyref name="KR_segsrc_ept_rid" refer="xlf:U_segsrc_bpt_rid">
      <xsd:selector xpath=".//xlf:ept"/>
      <xsd:field xpath="@rid"/>
    </xsd:keyref>
    <xsd:unique name="U_segsrc_bx_rid">
      <xsd:selector xpath=".//xlf:bx"/>
      <xsd:field xpath="@rid"/>
    </xsd:unique>
    <xsd:keyref name="KR_segsrc_ex_rid" refer="xlf:U_segsrc_bx_rid">
      <xsd:selector xpath=".//xlf:ex"/>
      <xsd:field xpath="@rid"/>
    </xsd:keyref>
  </xsd:element>
  <xsd:element name="target">
    <xsd:complexType mixed="true">
      <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
      <xsd:attribute name="state" type="xlf:AttrType_state" use="optional"/>
      <xsd:attribute name="state-qualifier" type="xlf:AttrType_state-qualifier" use="optional"/>
      <xsd:attribute name="phase-name" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute ref="xml:lang" use="optional"/>
      <xsd:attribute name="resname" type="xsd:string" use="optional"/>
      <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
      <xsd:attribute name="font" type="xsd:string" use="optional"/>
      <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
      <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute default="yes" name="equiv-trans" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:anyAttribute namespace="##other" processContents="strict"/>
    </xsd:complexType>
    <xsd:unique name="U_target_bpt_rid">
      <xsd:selector xpath=".//xlf:bpt"/>
      <xsd:field xpath="@rid"/>
    </xsd:unique>
    <xsd:keyref name="KR_target_ept_rid" refer="xlf:U_target_bpt_rid">
      <xsd:selector xpath=".//xlf:ept"/>
      <xsd:field xpath="@rid"/>
    </xsd:keyref>
    <xsd:unique name="U_target_bx_rid">
      <xsd:selector xpath=".//xlf:bx"/>
      <xsd:field xpath="@rid"/>
    </xsd:unique>
    <xsd:keyref name="KR_target_ex_rid" refer="xlf:U_target_bx_rid">
      <xsd:selector xpath=".//xlf:ex"/>
      <xsd:field xpath="@rid"/>
    </xsd:keyref>
  </xsd:element>
  <xsd:element name="alt-trans">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element minOccurs="0" ref="xlf:source"/>
        <xsd:element minOccurs="0" ref="xlf:seg-source"/>
        <xsd:element maxOccurs="1" ref="xlf:target"/>
        <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:context-group"/>
        <xsd:element maxOccurs="unbounded" minOccurs="0" ref="xlf:note"/>
        <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
      </xsd:sequence>
      <xsd:attribute name="match-quality" type="xsd:string" use="optional"/>
      <xsd:attribute name="tool-id" type="xsd:string" use="optional"/>
      <xsd:attribute name="crc" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute ref="xml:lang" use="optional"/>
      <xsd:attribute name="origin" type="xsd:string" use="optional"/>
      <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
      <xsd:attribute default="default" ref="xml:space" use="optional"/>
      <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
      <xsd:attribute name="resname" type="xsd:string" use="optional"/>
      <xsd:attribute name="extradata" type="xsd:string" use="optional"/>
      <xsd:attribute name="extype" type="xsd:string" use="optional"/>
      <xsd:attribute name="help-id" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="menu" type="xsd:string" use="optional"/>
      <xsd:attribute name="menu-option" type="xsd:string" use="optional"/>
      <xsd:attribute name="menu-name" type="xsd:string" use="optional"/>
      <xsd:attribute name="mid" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="coord" type="xlf:AttrType_Coordinates" use="optional"/>
      <xsd:attribute name="font" type="xsd:string" use="optional"/>
      <xsd:attribute name="css-style" type="xsd:string" use="optional"/>
      <xsd:attribute name="style" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="exstyle" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="phase-name" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute default="proposal" name="alttranstype" type="xlf:AttrType_alttranstype" use="optional"/>
      <xsd:anyAttribute namespace="##other" processContents="strict"/>
    </xsd:complexType>
    <xsd:unique name="U_at_segsrc_mid">
      <xsd:selector xpath="./xlf:seg-source/xlf:mrk"/>
      <xsd:field xpath="@mid"/>
    </xsd:unique>
    <xsd:keyref name="KR_at_segsrc_mid" refer="xlf:U_at_segsrc_mid">
      <xsd:selector xpath="./xlf:target/xlf:mrk"/>
      <xsd:field xpath="@mid"/>
    </xsd:keyref>
  </xsd:element>
  <xsd:element name="bin-unit">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element ref="xlf:bin-source"/>
        <xsd:element minOccurs="0" ref="xlf:bin-target"/>
        <xsd:choice maxOccurs="unbounded" minOccurs="0">
          <xsd:element ref="xlf:context-group"/>
          <xsd:element ref="xlf:count-group"/>
          <xsd:element ref="xlf:note"/>
          <xsd:element ref="xlf:trans-unit"/>
        </xsd:choice>
        <xsd:any maxOccurs="unbounded" minOccurs="0" namespace="##other" processContents="strict"/>
      </xsd:sequence>
      <xsd:attribute name="id" type="xsd:string" use="required"/>
      <xsd:attribute name="mime-type" type="xlf:mime-typeValueList" use="required"/>
      <xsd:attribute name="approved" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:attribute default="yes" name="translate" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:attribute default="yes" name="reformat" type="xlf:AttrType_reformat" use="optional"/>
      <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
      <xsd:attribute name="resname" type="xsd:string" use="optional"/>
      <xsd:attribute name="phase-name" type="xsd:string" use="optional"/>
      <xsd:anyAttribute namespace="##other" processContents="strict"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="bin-source">
    <xsd:complexType>
      <xsd:choice>
        <xsd:element ref="xlf:internal-file"/>
        <xsd:element ref="xlf:external-file"/>
      </xsd:choice>
      <xsd:anyAttribute namespace="##other" processContents="strict"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="bin-target">
    <xsd:complexType>
      <xsd:choice>
        <xsd:element ref="xlf:internal-file"/>
        <xsd:element ref="xlf:external-file"/>
      </xsd:choice>
      <xsd:attribute name="mime-type" type="xlf:mime-typeValueList" use="optional"/>
      <xsd:attribute name="state" type="xlf:AttrType_state" use="optional"/>
      <xsd:attribute name="state-qualifier" type="xlf:AttrType_state-qualifier" use="optional"/>
      <xsd:attribute name="phase-name" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="restype" type="xlf:AttrType_restype" use="optional"/>
      <xsd:attribute name="resname" type="xsd:string" use="optional"/>
      <xsd:anyAttribute namespace="##other" processContents="strict"/>
    </xsd:complexType>
  </xsd:element>
  <!-- Element for inline codes -->
  <xsd:element name="g">
    <xsd:complexType mixed="true">
      <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
      <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
      <xsd:attribute default="yes" name="clone" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="x">
    <xsd:complexType>
      <xsd:attribute name="ctype" type="xlf:AttrType_InlinePlaceholders" use="optional"/>
      <xsd:attribute default="yes" name="clone" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="bx">
    <xsd:complexType>
      <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
      <xsd:attribute default="yes" name="clone" type="xlf:AttrType_YesNo" use="optional"/>
      <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="ex">
    <xsd:complexType>
      <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="ph">
    <xsd:complexType mixed="true">
      <xsd:sequence maxOccurs="unbounded" minOccurs="0">
        <xsd:element ref="xlf:sub"/>
      </xsd:sequence>
      <xsd:attribute name="ctype" type="xlf:AttrType_InlinePlaceholders" use="optional"/>
      <xsd:attribute name="crc" type="xsd:string" use="optional"/>
      <xsd:attribute name="assoc" type="xlf:AttrType_assoc" use="optional"/>
      <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="bpt">
    <xsd:complexType mixed="true">
      <xsd:sequence maxOccurs="unbounded" minOccurs="0">
        <xsd:element ref="xlf:sub"/>
      </xsd:sequence>
      <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
      <xsd:attribute name="crc" type="xsd:string" use="optional"/>
      <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="ept">
    <xsd:complexType mixed="true">
      <xsd:sequence maxOccurs="unbounded" minOccurs="0">
        <xsd:element ref="xlf:sub"/>
      </xsd:sequence>
      <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="crc" type="xsd:string" use="optional"/>
      <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="it">
    <xsd:complexType mixed="true">
      <xsd:sequence maxOccurs="unbounded" minOccurs="0">
        <xsd:element ref="xlf:sub"/>
      </xsd:sequence>
      <xsd:attribute name="pos" type="xlf:AttrType_Position" use="required"/>
      <xsd:attribute name="rid" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
      <xsd:attribute name="crc" type="xsd:string" use="optional"/>
      <xsd:attributeGroup ref="xlf:AttrGroup_TextContent"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="sub">
    <xsd:complexType mixed="true">
      <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
      <xsd:attribute name="datatype" type="xlf:AttrType_datatype" use="optional"/>
      <xsd:attribute name="ctype" type="xlf:AttrType_InlineDelimiters" use="optional"/>
      <xsd:attribute name="xid" type="xsd:string" use="optional"/>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="mrk">
    <xsd:complexType mixed="true">
      <xsd:group maxOccurs="unbounded" minOccurs="0" ref="xlf:ElemGroup_TextContent"/>
      <xsd:attribute name="mtype" type="xlf:AttrType_mtype" use="required"/>
      <xsd:attribute name="mid" type="xsd:NMTOKEN" use="optional"/>
      <xsd:attribute name="comment" type="xsd:string" use="optional"/>
      <xsd:anyAttribute namespace="##other" processContents="strict"/>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Config\Resource\DirectoryResource;

/**
 * IcuResFileLoader loads translations from a resource bundle.
 *
 * @author stealth35
 */
class IcuResFileLoader implements LoaderInterface
{
    /**
     * {@inheritdoc}
     */
    public function load($resource, $locale, $domain = 'messages')
    {
        if (!stream_is_local($resource)) {
            throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
        }

        if (!is_dir($resource)) {
            throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
        }

        $rb = new \ResourceBundle($locale, $resource);

        if (!$rb) {
            throw new InvalidResourceException(sprintf('Cannot load resource "%s"', $resource));
        } elseif (intl_is_failure($rb->getErrorCode())) {
            throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode());
        }

        $messages = $this->flatten($rb);
        $catalogue = new MessageCatalogue($locale);
        $catalogue->add($messages, $domain);
        $catalogue->addResource(new DirectoryResource($resource));

        return $catalogue;
    }

    /**
     * Flattens an ResourceBundle
     *
     * The scheme used is:
     *   key { key2 { key3 { "value" } } }
     * Becomes:
     *   'key.key2.key3' => 'value'
     *
     * This function takes an array by reference and will modify it
     *
     * @param \ResourceBundle $rb       the ResourceBundle that will be flattened
     * @param array           $messages used internally for recursive calls
     * @param string          $path     current path being parsed, used internally for recursive calls
     *
     * @return array the flattened ResourceBundle
     */
    protected function flatten(\ResourceBundle $rb, array &$messages = array(), $path = null)
    {
        foreach ($rb as $key => $value) {
            $nodePath = $path ? $path.'.'.$key : $key;
            if ($value instanceof \ResourceBundle) {
                $this->flatten($value, $messages, $nodePath);
            } else {
                $messages[$nodePath] = $value;
            }
        }

        return $messages;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Config\Resource\FileResource;

/**
 * IniFileLoader loads translations from an ini file.
 *
 * @author stealth35
 */
class IniFileLoader extends ArrayLoader implements LoaderInterface
{
    /**
     * {@inheritdoc}
     */
    public function load($resource, $locale, $domain = 'messages')
    {
        if (!stream_is_local($resource)) {
            throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
        }

        if (!file_exists($resource)) {
            throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
        }

        $messages = parse_ini_file($resource, true);

        $catalogue = parent::load($messages, $locale, $domain);
        $catalogue->addResource(new FileResource($resource));

        return $catalogue;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Config\Resource\FileResource;

/**
 * PhpFileLoader loads translations from PHP files returning an array of translations.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class PhpFileLoader extends ArrayLoader implements LoaderInterface
{
    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function load($resource, $locale, $domain = 'messages')
    {
        if (!stream_is_local($resource)) {
            throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
        }

        if (!file_exists($resource)) {
            throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
        }

        $messages = require($resource);

        $catalogue = parent::load($messages, $locale, $domain);
        $catalogue->addResource(new FileResource($resource));

        return $catalogue;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Config\Resource\FileResource;

/**
 * JsonFileLoader loads translations from an json file.
 *
 * @author singles
 */
class JsonFileLoader extends ArrayLoader implements LoaderInterface
{
    /**
     * {@inheritdoc}
     */
    public function load($resource, $locale, $domain = 'messages')
    {
        if (!stream_is_local($resource)) {
            throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
        }

        if (!file_exists($resource)) {
            throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
        }

        $messages = json_decode(file_get_contents($resource), true);

        if (0 < $errorCode = json_last_error()) {
            throw new InvalidResourceException(sprintf('Error parsing JSON - %s', $this->getJSONErrorMessage($errorCode)));
        }

        if (null === $messages) {
            $messages = array();
        }

        $catalogue = parent::load($messages, $locale, $domain);
        $catalogue->addResource(new FileResource($resource));

        return $catalogue;
    }

    /**
     * Translates JSON_ERROR_* constant into meaningful message.
     *
     * @param  integer $errorCode Error code returned by json_last_error() call
     *
     * @return string  Message string
     */
    private function getJSONErrorMessage($errorCode)
    {
        switch ($errorCode) {
            case JSON_ERROR_DEPTH:
                return 'Maximum stack depth exceeded';
            case JSON_ERROR_STATE_MISMATCH:
                return 'Underflow or the modes mismatch';
            case JSON_ERROR_CTRL_CHAR:
                return 'Unexpected control character found';
            case JSON_ERROR_SYNTAX:
                return 'Syntax error, malformed JSON';
            case JSON_ERROR_UTF8:
                return 'Malformed UTF-8 characters, possibly incorrectly encoded';
            default:
                return 'Unknown error';
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Config\Resource\FileResource;

/**
 * @copyright Copyright (c) 2010, Union of RAD http://union-of-rad.org (http://lithify.me/)
 */
class MoFileLoader extends ArrayLoader implements LoaderInterface
{
    /**
     * Magic used for validating the format of a MO file as well as
     * detecting if the machine used to create that file was little endian.
     *
     * @var float
     */
    const MO_LITTLE_ENDIAN_MAGIC = 0x950412de;

    /**
     * Magic used for validating the format of a MO file as well as
     * detecting if the machine used to create that file was big endian.
     *
     * @var float
     */
    const MO_BIG_ENDIAN_MAGIC = 0xde120495;

    /**
     * The size of the header of a MO file in bytes.
     *
     * @var integer Number of bytes.
     */
    const MO_HEADER_SIZE = 28;

    public function load($resource, $locale, $domain = 'messages')
    {
        if (!stream_is_local($resource)) {
            throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
        }

        if (!file_exists($resource)) {
            throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
        }

        $messages = $this->parse($resource);

        // empty file
        if (null === $messages) {
            $messages = array();
        }

        // not an array
        if (!is_array($messages)) {
            throw new InvalidResourceException(sprintf('The file "%s" must contain a valid mo file.', $resource));
        }

        $catalogue = parent::load($messages, $locale, $domain);
        $catalogue->addResource(new FileResource($resource));

        return $catalogue;
    }

    /**
     * Parses machine object (MO) format, independent of the machine's endian it
     * was created on. Both 32bit and 64bit systems are supported.
     *
     * @param resource $resource
     *
     * @return array
     * @throws InvalidResourceException If stream content has an invalid format.
     */
    private function parse($resource)
    {
        $stream = fopen($resource, 'r');

        $stat = fstat($stream);

        if ($stat['size'] < self::MO_HEADER_SIZE) {
            throw new InvalidResourceException("MO stream content has an invalid format.");
        }
        $magic = unpack('V1', fread($stream, 4));
        $magic = hexdec(substr(dechex(current($magic)), -8));

        if ($magic == self::MO_LITTLE_ENDIAN_MAGIC) {
            $isBigEndian = false;
        } elseif ($magic == self::MO_BIG_ENDIAN_MAGIC) {
            $isBigEndian = true;
        } else {
            throw new InvalidResourceException("MO stream content has an invalid format.");
        }

        // formatRevision
        $this->readLong($stream, $isBigEndian);
        $count = $this->readLong($stream, $isBigEndian);
        $offsetId = $this->readLong($stream, $isBigEndian);
        $offsetTranslated = $this->readLong($stream, $isBigEndian);
        // sizeHashes
        $this->readLong($stream, $isBigEndian);
        // offsetHashes
        $this->readLong($stream, $isBigEndian);

        $messages = array();

        for ($i = 0; $i < $count; $i++) {
            $singularId = $pluralId = null;
            $translated = null;

            fseek($stream, $offsetId + $i * 8);

            $length = $this->readLong($stream, $isBigEndian);
            $offset = $this->readLong($stream, $isBigEndian);

            if ($length < 1) {
                continue;
            }

            fseek($stream, $offset);
            $singularId = fread($stream, $length);

            if (strpos($singularId, "\000") !== false) {
                list($singularId, $pluralId) = explode("\000", $singularId);
            }

            fseek($stream, $offsetTranslated + $i * 8);
            $length = $this->readLong($stream, $isBigEndian);
            $offset = $this->readLong($stream, $isBigEndian);

            fseek($stream, $offset);
            $translated = fread($stream, $length);

            if (strpos($translated, "\000") !== false) {
                $translated = explode("\000", $translated);
            }

            $ids = array('singular' => $singularId, 'plural' => $pluralId);
            $item = compact('ids', 'translated');

            if (is_array($item['translated'])) {
                $messages[$item['ids']['singular']] = stripcslashes($item['translated'][0]);
                if (isset($item['ids']['plural'])) {
                    $plurals = array();
                    foreach ($item['translated'] as $plural => $translated) {
                        $plurals[] = sprintf('{%d} %s', $plural, $translated);
                    }
                    $messages[$item['ids']['plural']] = stripcslashes(implode('|', $plurals));
                }
            } elseif (!empty($item['ids']['singular'])) {
                $messages[$item['ids']['singular']] = stripcslashes($item['translated']);
            }
        }

        fclose($stream);

        return array_filter($messages);
    }

    /**
     * Reads an unsigned long from stream respecting endianess.
     *
     * @param  resource $stream
     * @param  boolean  $isBigEndian
     * @return integer
     */
    private function readLong($stream, $isBigEndian)
    {
        $result = unpack($isBigEndian ? 'N1' : 'V1', fread($stream, 4));
        $result = current($result);

        return (integer) substr($result, -8);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Config\Resource\FileResource;

/**
 * CsvFileLoader loads translations from CSV files.
 *
 * @author Saša Stamenković <umpirsky@gmail.com>
 *
 * @api
 */
class CsvFileLoader extends ArrayLoader implements LoaderInterface
{
    private $delimiter = ';';
    private $enclosure = '"';
    private $escape    = '\\';

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function load($resource, $locale, $domain = 'messages')
    {
        if (!stream_is_local($resource)) {
            throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
        }

        if (!file_exists($resource)) {
            throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
        }

        $messages = array();

        try {
            $file = new \SplFileObject($resource, 'rb');
        } catch (\RuntimeException $e) {
            throw new NotFoundResourceException(sprintf('Error opening file "%s".', $resource), 0, $e);
        }

        $file->setFlags(\SplFileObject::READ_CSV | \SplFileObject::SKIP_EMPTY);
        $file->setCsvControl($this->delimiter, $this->enclosure, $this->escape);

        foreach ($file as $data) {
            if (substr($data[0], 0, 1) === '#') {
                continue;
            }

            if (!isset($data[1])) {
                continue;
            }

            if (count($data) == 2) {
                $messages[$data[0]] = $data[1];
            } else {
                 continue;
            }
        }

        $catalogue = parent::load($messages, $locale, $domain);
        $catalogue->addResource(new FileResource($resource));

        return $catalogue;
    }

    /**
     * Sets the delimiter, enclosure, and escape character for CSV.
     *
     * @param string $delimiter delimiter character
     * @param string $enclosure enclosure character
     * @param string $escape    escape character
     */
    public function setCsvControl($delimiter = ';', $enclosure = '"', $escape = '\\')
    {
        $this->delimiter = $delimiter;
        $this->enclosure = $enclosure;
        $this->escape    = $escape;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\MessageCatalogue;

/**
 * ArrayLoader loads translations from a PHP array.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class ArrayLoader implements LoaderInterface
{
    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function load($resource, $locale, $domain = 'messages')
    {
        $this->flatten($resource);
        $catalogue = new MessageCatalogue($locale);
        $catalogue->add($resource, $domain);

        return $catalogue;
    }

    /**
     * Flattens an nested array of translations
     *
     * The scheme used is:
     *   'key' => array('key2' => array('key3' => 'value'))
     * Becomes:
     *   'key.key2.key3' => 'value'
     *
     * This function takes an array by reference and will modify it
     *
     * @param array  &$messages The array that will be flattened
     * @param array  $subnode Current subnode being parsed, used internally for recursive calls
     * @param string $path    Current path being parsed, used internally for recursive calls
     */
    private function flatten(array &$messages, array $subnode = null, $path = null)
    {
        if (null === $subnode) {
            $subnode =& $messages;
        }
        foreach ($subnode as $key => $value) {
            if (is_array($value)) {
                $nodePath = $path ? $path.'.'.$key : $key;
                $this->flatten($messages, $value, $nodePath);
                if (null === $path) {
                    unset($messages[$key]);
                }
            } elseif (null !== $path) {
                $messages[$path.'.'.$key] = $value;
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Config\Resource\FileResource;

/**
 * QtFileLoader loads translations from QT Translations XML files.
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 *
 * @api
 */
class QtFileLoader implements LoaderInterface
{
    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function load($resource, $locale, $domain = 'messages')
    {
        if (!stream_is_local($resource)) {
            throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
        }

        if (!file_exists($resource)) {
            throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
        }

        $dom = new \DOMDocument();
        $current = libxml_use_internal_errors(true);
        if (!@$dom->load($resource, defined('LIBXML_COMPACT') ? LIBXML_COMPACT : 0)) {
            throw new InvalidResourceException(implode("\n", $this->getXmlErrors()));
        }

        $xpath = new \DOMXPath($dom);
        $nodes = $xpath->evaluate('//TS/context/name[text()="'.$domain.'"]');

        $catalogue = new MessageCatalogue($locale);
        if ($nodes->length == 1) {
            $translations = $nodes->item(0)->nextSibling->parentNode->parentNode->getElementsByTagName('message');
            foreach ($translations as $translation) {
                $catalogue->set(
                    (string) $translation->getElementsByTagName('source')->item(0)->nodeValue,
                    (string) $translation->getElementsByTagName('translation')->item(0)->nodeValue,
                    $domain
                );
                $translation = $translation->nextSibling;
            }
            $catalogue->addResource(new FileResource($resource));
        }

        libxml_use_internal_errors($current);

        return $catalogue;
    }

    /**
     * Returns the XML errors of the internal XML parser
     *
     * @return array An array of errors
     */
    private function getXmlErrors()
    {
        $errors = array();
        foreach (libxml_get_errors() as $error) {
            $errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)',
                LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR',
                $error->code,
                trim($error->message),
                $error->file ? $error->file : 'n/a',
                $error->line,
                $error->column
            );
        }

        libxml_clear_errors();
        libxml_use_internal_errors(false);

        return $errors;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Yaml\Parser as YamlParser;
use Symfony\Component\Yaml\Exception\ParseException;

/**
 * YamlFileLoader loads translations from Yaml files.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class YamlFileLoader extends ArrayLoader implements LoaderInterface
{
    private $yamlParser;

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function load($resource, $locale, $domain = 'messages')
    {
        if (!stream_is_local($resource)) {
            throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
        }

        if (!file_exists($resource)) {
            throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
        }

        if (null === $this->yamlParser) {
            $this->yamlParser = new YamlParser();
        }

        try {
            $messages = $this->yamlParser->parse(file_get_contents($resource));
        } catch (ParseException $e) {
            throw new InvalidResourceException('Error parsing YAML.', 0, $e);
        }

        // empty file
        if (null === $messages) {
            $messages = array();
        }

        // not an array
        if (!is_array($messages)) {
            throw new InvalidResourceException(sprintf('The file "%s" must contain a YAML array.', $resource));
        }

        $catalogue = parent::load($messages, $locale, $domain);
        $catalogue->addResource(new FileResource($resource));

        return $catalogue;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Loader;

use Symfony\Component\Translation\Exception\InvalidResourceException;
use Symfony\Component\Translation\Exception\NotFoundResourceException;
use Symfony\Component\Config\Resource\FileResource;

/**
 * @copyright Copyright (c) 2010, Union of RAD http://union-of-rad.org (http://lithify.me/)
 * @copyright Copyright (c) 2012, Clemens Tolboom
 */
class PoFileLoader extends ArrayLoader implements LoaderInterface
{
    public function load($resource, $locale, $domain = 'messages')
    {
        if (!stream_is_local($resource)) {
            throw new InvalidResourceException(sprintf('This is not a local file "%s".', $resource));
        }

        if (!file_exists($resource)) {
            throw new NotFoundResourceException(sprintf('File "%s" not found.', $resource));
        }

        $messages = $this->parse($resource);

        // empty file
        if (null === $messages) {
            $messages = array();
        }

        // not an array
        if (!is_array($messages)) {
            throw new InvalidResourceException(sprintf('The file "%s" must contain a valid po file.', $resource));
        }

        $catalogue = parent::load($messages, $locale, $domain);
        $catalogue->addResource(new FileResource($resource));

        return $catalogue;
    }

    /**
     * Parses portable object (PO) format.
     *
     * From http://www.gnu.org/software/gettext/manual/gettext.html#PO-Files
     * we should be able to parse files having:
     *
     * white-space
     * #  translator-comments
     * #. extracted-comments
     * #: reference...
     * #, flag...
     * #| msgid previous-untranslated-string
     * msgid untranslated-string
     * msgstr translated-string
     *
     * extra or different lines are:
     *
     * #| msgctxt previous-context
     * #| msgid previous-untranslated-string
     * msgctxt context
     *
     * #| msgid previous-untranslated-string-singular
     * #| msgid_plural previous-untranslated-string-plural
     * msgid untranslated-string-singular
     * msgid_plural untranslated-string-plural
     * msgstr[0] translated-string-case-0
     * ...
     * msgstr[N] translated-string-case-n
     *
     * The definition states:
     * - white-space and comments are optional.
     * - msgid "" that an empty singleline defines a header.
     *
     * This parser sacrifices some features of the reference implementation the
     * differences to that implementation are as follows.
     * - No support for comments spanning multiple lines.
     * - Translator and extracted comments are treated as being the same type.
     * - Message IDs are allowed to have other encodings as just US-ASCII.
     *
     * Items with an empty id are ignored.
     *
     * @param resource $resource
     *
     * @return array
     */
    private function parse($resource)
    {
        $stream = fopen($resource, 'r');

        $defaults = array(
            'ids' => array(),
            'translated' => null,
        );

        $messages = array();
        $item = $defaults;

        while ($line = fgets($stream)) {
            $line = trim($line);

            if ($line === '') {
                // Whitespace indicated current item is done
                $this->addMessage($messages, $item);
                $item = $defaults;
            } elseif (substr($line, 0, 7) === 'msgid "') {
                // We start a new msg so save previous
                // TODO: this fails when comments or contexts are added
                $this->addMessage($messages, $item);
                $item = $defaults;
                $item['ids']['singular'] = substr($line, 7, -1);
            } elseif (substr($line, 0, 8) === 'msgstr "') {
                $item['translated'] = substr($line, 8, -1);
            } elseif ($line[0] === '"') {
                $continues = isset($item['translated']) ? 'translated' : 'ids';

                if (is_array($item[$continues])) {
                    end($item[$continues]);
                    $item[$continues][key($item[$continues])] .= substr($line, 1, -1);
                } else {
                    $item[$continues] .= substr($line, 1, -1);
                }
            } elseif (substr($line, 0, 14) === 'msgid_plural "') {
                $item['ids']['plural'] = substr($line, 14, -1);
            } elseif (substr($line, 0, 7) === 'msgstr[') {
                $size = strpos($line, ']');
                $item['translated'][(integer) substr($line, 7, 1)] = substr($line, $size + 3, -1);
            }

        }
        // save last item
        $this->addMessage($messages, $item);
        fclose($stream);

        return $messages;
    }

    /**
     * Save a translation item to the messeages.
     *
     * A .po file could contain by error missing plural indexes. We need to
     * fix these before saving them.
     *
     * @param array $messages
     * @param array $item
     */
    private function addMessage(array &$messages, array $item)
    {
        if (is_array($item['translated'])) {
            $messages[$item['ids']['singular']] = stripslashes($item['translated'][0]);
            if (isset($item['ids']['plural'])) {
                $plurals = $item['translated'];
                // PO are by definition indexed so sort by index.
                ksort($plurals);
                // Make sure every index is filled.
                end($plurals);
                $count = key($plurals);
                // Fill missing spots with '-'.
                $empties = array_fill(0, $count+1, '-');
                $plurals += $empties;
                ksort($plurals);
                $messages[$item['ids']['plural']] = stripcslashes(implode('|', $plurals));
            }
        } elseif (!empty($item['ids']['singular'])) {
              $messages[$item['ids']['singular']] = stripslashes($item['translated']);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Exception;

/**
 * Thrown when a resource does not exist.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class NotFoundResourceException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Exception;

/**
 * Exception interface for all exceptions thrown by the component.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Exception;

/**
 * Thrown when a resource cannot be loaded.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class InvalidResourceException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

use Symfony\Component\Config\Resource\ResourceInterface;

/**
 * MessageCatalogue.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterface
{
    private $messages = array();
    private $metadata = array();
    private $resources = array();
    private $locale;
    private $fallbackCatalogue;
    private $parent;

    /**
     * Constructor.
     *
     * @param string $locale   The locale
     * @param array  $messages An array of messages classified by domain
     *
     * @api
     */
    public function __construct($locale, array $messages = array())
    {
        $this->locale = $locale;
        $this->messages = $messages;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function getLocale()
    {
        return $this->locale;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function getDomains()
    {
        return array_keys($this->messages);
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function all($domain = null)
    {
        if (null === $domain) {
            return $this->messages;
        }

        return isset($this->messages[$domain]) ? $this->messages[$domain] : array();
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function set($id, $translation, $domain = 'messages')
    {
        $this->add(array($id => $translation), $domain);
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function has($id, $domain = 'messages')
    {
        if (isset($this->messages[$domain][$id])) {
            return true;
        }

        if (null !== $this->fallbackCatalogue) {
            return $this->fallbackCatalogue->has($id, $domain);
        }

        return false;
    }

    /**
     * {@inheritdoc}
     */
    public function defines($id, $domain = 'messages')
    {
        return isset($this->messages[$domain][$id]);
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function get($id, $domain = 'messages')
    {
        if (isset($this->messages[$domain][$id])) {
            return $this->messages[$domain][$id];
        }

        if (null !== $this->fallbackCatalogue) {
            return $this->fallbackCatalogue->get($id, $domain);
        }

        return $id;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function replace($messages, $domain = 'messages')
    {
        $this->messages[$domain] = array();

        $this->add($messages, $domain);
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function add($messages, $domain = 'messages')
    {
        if (!isset($this->messages[$domain])) {
            $this->messages[$domain] = $messages;
        } else {
            $this->messages[$domain] = array_replace($this->messages[$domain], $messages);
        }
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function addCatalogue(MessageCatalogueInterface $catalogue)
    {
        if ($catalogue->getLocale() !== $this->locale) {
            throw new \LogicException(sprintf('Cannot add a catalogue for locale "%s" as the current locale for this catalogue is "%s"', $catalogue->getLocale(), $this->locale));
        }

        foreach ($catalogue->all() as $domain => $messages) {
            $this->add($messages, $domain);
        }

        foreach ($catalogue->getResources() as $resource) {
            $this->addResource($resource);
        }

        if ($catalogue instanceof MetadataAwareInterface) {
            $metadata = $catalogue->getMetadata('', '');
            $this->addMetadata($metadata);
        }
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function addFallbackCatalogue(MessageCatalogueInterface $catalogue)
    {
        // detect circular references
        $c = $this;
        do {
            if ($c->getLocale() === $catalogue->getLocale()) {
                throw new \LogicException(sprintf('Circular reference detected when adding a fallback catalogue for locale "%s".', $catalogue->getLocale()));
            }
        } while ($c = $c->parent);

        $catalogue->parent = $this;
        $this->fallbackCatalogue = $catalogue;

        foreach ($catalogue->getResources() as $resource) {
            $this->addResource($resource);
        }
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function getFallbackCatalogue()
    {
        return $this->fallbackCatalogue;
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function getResources()
    {
        return array_values($this->resources);
    }

    /**
     * {@inheritdoc}
     *
     * @api
     */
    public function addResource(ResourceInterface $resource)
    {
        $this->resources[$resource->__toString()] = $resource;
    }

    /**
     * {@inheritdoc}
     */
    public function getMetadata($key = '', $domain = 'messages')
    {
        if ('' == $domain) {
            return $this->metadata;
        }

        if (isset($this->metadata[$domain])) {
            if ('' == $key) {
                return $this->metadata[$domain];
            }

            if (isset($this->metadata[$domain][$key])) {
                return $this->metadata[$domain][$key];
            }
        }

        return null;
    }

    /**
     * {@inheritdoc}
     */
    public function setMetadata($key, $value, $domain = 'messages')
    {
        $this->metadata[$domain][$key] = $value;
    }

    /**
     * {@inheritdoc}
     */
    public function deleteMetadata($key = '', $domain = 'messages')
    {
        if ('' == $domain) {
            $this->metadata = array();
        } elseif ('' == $key) {
            unset($this->metadata[$domain]);
        } else {
            unset($this->metadata[$domain][$key]);
        }
    }

    /**
     * Adds current values with the new values.
     *
     * @param array $values Values to add
     */
    private function addMetadata(array $values)
    {
        foreach ($values as $domain => $keys) {
            foreach ($keys as $key => $value) {
                $this->setMetadata($key, $value, $domain);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Writer;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Dumper\DumperInterface;

/**
 * TranslationWriter writes translation messages.
 *
 * @author Michel Salib <michelsalib@hotmail.com>
 */
class TranslationWriter
{
    /**
     * Dumpers used for export.
     *
     * @var array
     */
    private $dumpers = array();

    /**
     * Adds a dumper to the writer.
     *
     * @param string          $format The format of the dumper
     * @param DumperInterface $dumper The dumper
     */
    public function addDumper($format, DumperInterface $dumper)
    {
        $this->dumpers[$format] = $dumper;
    }

    /**
     * Obtains the list of supported formats.
     *
     * @return array
     */
    public function getFormats()
    {
        return array_keys($this->dumpers);
    }

    /**
     * Writes translation from the catalogue according to the selected format.
     *
     * @param MessageCatalogue $catalogue The message catalogue to dump
     * @param string           $format    The format to use to dump the messages
     * @param array            $options   Options that are passed to the dumper
     *
     * @throws \InvalidArgumentException
     */
    public function writeTranslations(MessageCatalogue $catalogue, $format, $options = array())
    {
        if (!isset($this->dumpers[$format])) {
            throw new \InvalidArgumentException(sprintf('There is no dumper associated with format "%s".', $format));
        }

        // get the right dumper
        $dumper = $this->dumpers[$format];

        // save
        $dumper->dump($catalogue, $options);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests;

use Symfony\Component\Translation\Interval;

class IntervalTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getTests
     */
    public function testTest($expected, $number, $interval)
    {
        $this->assertEquals($expected, Interval::test($number, $interval));
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testTestException()
    {
        Interval::test(1, 'foobar');
    }

    public function getTests()
    {
        return array(
            array(true, 3, '{1,2, 3 ,4}'),
            array(false, 10, '{1,2, 3 ,4}'),
            array(false, 3, '[1,2]'),
            array(true, 1, '[1,2]'),
            array(true, 2, '[1,2]'),
            array(false, 1, ']1,2['),
            array(false, 2, ']1,2['),
            array(true, log(0), '[-Inf,2['),
            array(true, -log(0), '[-2,+Inf]'),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Dumper;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Dumper\IniFileDumper;

class IniFileDumperTest extends \PHPUnit_Framework_TestCase
{
    public function testDump()
    {
        $catalogue = new MessageCatalogue('en');
        $catalogue->add(array('foo' => 'bar'));

        $tempDir = sys_get_temp_dir();
        $dumper = new IniFileDumper();
        $dumper->dump($catalogue, array('path' => $tempDir));

        $this->assertEquals(file_get_contents(__DIR__.'/../fixtures/resources.ini'), file_get_contents($tempDir.'/messages.en.ini'));

        unlink($tempDir.'/messages.en.ini');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Dumper;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Dumper\XliffFileDumper;

class XliffFileDumperTest extends \PHPUnit_Framework_TestCase
{
    public function testDump()
    {
        $catalogue = new MessageCatalogue('en');
        $catalogue->add(array('foo' => 'bar', 'key' => ''));

        $tempDir = sys_get_temp_dir();
        $dumper = new XliffFileDumper();
        $dumper->dump($catalogue, array('path' => $tempDir));

        $this->assertEquals(file_get_contents(__DIR__.'/../fixtures/resources-clean.xlf'), file_get_contents($tempDir.'/messages.en.xlf'));

        unlink($tempDir.'/messages.en.xlf');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Dumper;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Dumper\YamlFileDumper;

class YamlFileDumperTest extends \PHPUnit_Framework_TestCase
{
    public function testDump()
    {
        $catalogue = new MessageCatalogue('en');
        $catalogue->add(array('foo' => 'bar'));

        $tempDir = sys_get_temp_dir();
        $dumper = new YamlFileDumper();
        $dumper->dump($catalogue, array('path' => $tempDir));

        $this->assertEquals(file_get_contents(__DIR__.'/../fixtures/resources.yml'), file_get_contents($tempDir.'/messages.en.yml'));

        unlink($tempDir.'/messages.en.yml');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Dumper;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Dumper\PoFileDumper;

class PoFileDumperTest extends \PHPUnit_Framework_TestCase
{
    public function testDump()
    {
        $catalogue = new MessageCatalogue('en');
        $catalogue->add(array('foo' => 'bar'));

        $tempDir = sys_get_temp_dir();
        $dumper = new PoFileDumper();
        $dumper->dump($catalogue, array('path' => $tempDir));
        $this->assertEquals(file_get_contents(__DIR__.'/../fixtures/resources.po'), file_get_contents($tempDir.'/messages.en.po'));

        unlink($tempDir.'/messages.en.po');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Dumper;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Dumper\QtFileDumper;

class QtFileDumperTest extends \PHPUnit_Framework_TestCase
{
    public function testDump()
    {
        $catalogue = new MessageCatalogue('en');
        $catalogue->add(array('foo' => 'bar'), 'resources');

        $tempDir = sys_get_temp_dir();
        $dumper = new QtFileDumper();
        $dumper->dump($catalogue, array('path' => $tempDir));

        $this->assertEquals(file_get_contents(__DIR__.'/../fixtures/resources.ts'), file_get_contents($tempDir.'/resources.en.ts'));

        unlink($tempDir.'/resources.en.ts');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Dumper;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Dumper\MoFileDumper;

class MoFileDumperTest extends \PHPUnit_Framework_TestCase
{
    public function testDump()
    {
        $catalogue = new MessageCatalogue('en');
        $catalogue->add(array('foo' => 'bar'));

        $tempDir = sys_get_temp_dir();
        $dumper = new MoFileDumper();
        $dumper->dump($catalogue, array('path' => $tempDir));
        $this->assertEquals(file_get_contents(__DIR__.'/../fixtures/resources.mo'), file_get_contents($tempDir.'/messages.en.mo'));

        unlink($tempDir.'/messages.en.mo');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Dumper;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Dumper\IcuResFileDumper;

class IcuResFileDumperTest extends \PHPUnit_Framework_TestCase
{
    public function testDump()
    {
        if (!extension_loaded('mbstring')) {
            $this->markTestSkipped('This test requires mbstring to work.');
        }

        $catalogue = new MessageCatalogue('en');
        $catalogue->add(array('foo' => 'bar'));

        $tempDir = sys_get_temp_dir() . '/IcuResFileDumperTest';
        mkdir($tempDir);
        $dumper = new IcuResFileDumper();
        $dumper->dump($catalogue, array('path' => $tempDir));

        $this->assertEquals(file_get_contents(__DIR__.'/../fixtures/resourcebundle/res/en.res'), file_get_contents($tempDir.'/messages/en.res'));

        unlink($tempDir.'/messages/en.res');
        rmdir($tempDir.'/messages');
        rmdir($tempDir);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Dumper;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Dumper\CsvFileDumper;

class CsvFileDumperTest extends \PHPUnit_Framework_TestCase
{
    public function testDump()
    {
        $catalogue = new MessageCatalogue('en');
        $catalogue->add(array('foo' => 'bar', 'bar' => 'foo
foo', 'foo;foo' => 'bar'));

        $tempDir = sys_get_temp_dir();
        $dumper = new CsvFileDumper();
        $dumper->dump($catalogue, array('path' => $tempDir));

        $this->assertEquals(file_get_contents(__DIR__.'/../fixtures/valid.csv'), file_get_contents($tempDir.'/messages.en.csv'));

        unlink($tempDir.'/messages.en.csv');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Dumper;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Dumper\JsonFileDumper;

class JsonFileDumperTest extends \PHPUnit_Framework_TestCase
{
    public function testDump()
    {
        if (version_compare(PHP_VERSION, '5.4.0', '<')) {
            $this->markTestIncomplete('PHP below 5.4 doesn\'t support JSON pretty printing');
        }

        $catalogue = new MessageCatalogue('en');
        $catalogue->add(array('foo' => 'bar'));

        $tempDir = sys_get_temp_dir();
        $dumper = new JsonFileDumper();
        $dumper->dump($catalogue, array('path' => $tempDir));

        $this->assertEquals(file_get_contents(__DIR__.'/../fixtures/resources.json'), file_get_contents($tempDir.'/messages.en.json'));

        unlink($tempDir.'/messages.en.json');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Dumper;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Dumper\PhpFileDumper;

class PhpFileDumperTest extends \PHPUnit_Framework_TestCase
{
    public function testDump()
    {
        $catalogue = new MessageCatalogue('en');
        $catalogue->add(array('foo' => 'bar'));

        $tempDir = sys_get_temp_dir();
        $dumper = new PhpFileDumper();
        $dumper->dump($catalogue, array('path' => $tempDir));

        $this->assertEquals(file_get_contents(__DIR__.'/../fixtures/resources.php'), file_get_contents($tempDir.'/messages.en.php'));

        unlink($tempDir.'/messages.en.php');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Test\Catalogue;

use Symfony\Component\Translation\Catalogue\DiffOperation;
use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\MessageCatalogueInterface;

class DiffOperationTest extends AbstractOperationTest
{
    public function testGetMessagesFromSingleDomain()
    {
        $operation = $this->createOperation(
            new MessageCatalogue('en', array('messages' => array('a' => 'old_a', 'b' => 'old_b'))),
            new MessageCatalogue('en', array('messages' => array('a' => 'new_a', 'c' => 'new_c')))
        );

        $this->assertEquals(
            array('a' => 'old_a', 'c' => 'new_c'),
            $operation->getMessages('messages')
        );

        $this->assertEquals(
            array('c' => 'new_c'),
            $operation->getNewMessages('messages')
        );

        $this->assertEquals(
            array('b' => 'old_b'),
            $operation->getObsoleteMessages('messages')
        );
    }

    public function testGetResultFromSingleDomain()
    {
        $this->assertEquals(
            new MessageCatalogue('en', array(
                'messages' => array('a' => 'old_a', 'c' => 'new_c')
            )),
            $this->createOperation(
                new MessageCatalogue('en', array('messages' => array('a' => 'old_a', 'b' => 'old_b'))),
                new MessageCatalogue('en', array('messages' => array('a' => 'new_a', 'c' => 'new_c')))
            )->getResult()
        );
    }

    protected function createOperation(MessageCatalogueInterface $source, MessageCatalogueInterface $target)
    {
        return new DiffOperation($source, $target);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Test\Catalogue;

use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\MessageCatalogueInterface;

abstract class AbstractOperationTest extends \PHPUnit_Framework_TestCase
{
    public function testGetEmptyDomains()
    {
        $this->assertEquals(
            array(),
            $this->createOperation(
                new MessageCatalogue('en'),
                new MessageCatalogue('en')
            )->getDomains()
        );
    }

    public function testGetMergedDomains()
    {
        $this->assertEquals(
            array('a', 'b', 'c'),
            $this->createOperation(
                new MessageCatalogue('en', array('a' => array(), 'b' => array())),
                new MessageCatalogue('en', array('b' => array(), 'c' => array()))
            )->getDomains()
        );
    }

    public function testGetMessagesFromUnknownDomain()
    {
        $this->setExpectedException('InvalidArgumentException');
        $this->createOperation(
            new MessageCatalogue('en'),
            new MessageCatalogue('en')
        )->getMessages('domain');
    }

    public function testGetEmptyMessages()
    {
        $this->assertEquals(
            array(),
            $this->createOperation(
                new MessageCatalogue('en', array('a' => array())),
                new MessageCatalogue('en')
            )->getMessages('a')
        );
    }

    public function testGetEmptyResult()
    {
        $this->assertEquals(
            new MessageCatalogue('en'),
            $this->createOperation(
                new MessageCatalogue('en'),
                new MessageCatalogue('en')
            )->getResult()
        );
    }

    abstract protected function createOperation(MessageCatalogueInterface $source, MessageCatalogueInterface $target);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Test\Catalogue;

use Symfony\Component\Translation\Catalogue\MergeOperation;
use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\MessageCatalogueInterface;

class MergeOperationTest extends AbstractOperationTest
{
    public function testGetMessagesFromSingleDomain()
    {
        $operation = $this->createOperation(
            new MessageCatalogue('en', array('messages' => array('a' => 'old_a', 'b' => 'old_b'))),
            new MessageCatalogue('en', array('messages' => array('a' => 'new_a', 'c' => 'new_c')))
        );

        $this->assertEquals(
            array('a' => 'old_a', 'b' => 'old_b', 'c' => 'new_c'),
            $operation->getMessages('messages')
        );

        $this->assertEquals(
            array('c' => 'new_c'),
            $operation->getNewMessages('messages')
        );

        $this->assertEquals(
            array(),
            $operation->getObsoleteMessages('messages')
        );
    }

    public function testGetResultFromSingleDomain()
    {
        $this->assertEquals(
            new MessageCatalogue('en', array(
                'messages' => array('a' => 'old_a', 'b' => 'old_b', 'c' => 'new_c')
            )),
            $this->createOperation(
                new MessageCatalogue('en', array('messages' => array('a' => 'old_a', 'b' => 'old_b'))),
                new MessageCatalogue('en', array('messages' => array('a' => 'new_a', 'c' => 'new_c')))
            )->getResult()
        );
    }

    protected function createOperation(MessageCatalogueInterface $source, MessageCatalogueInterface $target)
    {
        return new MergeOperation($source, $target);
    }
}
          $       ,      -      1    foo bar{
    "foo": "bar" "
}foo
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
  <file source-language="en" datatype="plaintext" original="file.ext">
    <body>
      <trans-unit id="1">
        <source>foo</source>
        <target>bar</target>
      </trans-unit>
      <trans-unit id="2">
        <source>extra</source>
      </trans-unit>
      <trans-unit id="3">
        <source>key</source>
        <target></target>
      </trans-unit>
      <trans-unit id="4">
        <source>test</source>
        <target>with</target>
        <note>note</note>
      </trans-unit>
    </body>
  </file>
</xliff>
msgid "foo"
msgstr ""

<?xml version="1.0"?>
<!DOCTYPE foo>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>foo</source>
                <target>bar</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0" encoding="utf-8"?>
<TS>
  <context>
    <name>resources</name>
    <message>
      <source>foo</source>
      <translation>bar</translation>
    </message>
  </context>
</TS>
{
    "foo": "bar"
}<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
  <file source-language="en" datatype="plaintext" original="file.ext">
    <body>
      <trans-unit id="1" resname="foo">
        <source></source>
        <target>bar</target>
      </trans-unit>
      <trans-unit id="2" resname="bar">
        <source>bar source</source>
        <target>baz</target>
      </trans-unit>
      <trans-unit id="3">
        <source>baz</source>
        <target>foo</target>
      </trans-unit>
    </body>
  </file>
</xliff>
XXXen{
    symfony{"Symfony 2 is great"}
}  '      ResB                  	                symfony    S y m f o n y   2   e s t   g  n i a l     	   fr{
    symfony{"Symfony 2 est génial"}
}  '      ResB                  	                symfony    S y m f o n y   2   i s   g r e a t     	   en.res
fr.res
  '      CmnD                    @   %      resources/en.res resources/fr.res   '      ResB                  	                symfony    S y m f o n y   2   i s   g r e a t     	     '      ResB                  	                symfony    S y m f o n y   2   e s t   g  n i a l     	     '      ResB                                  foo    b a r        <?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>foo</source>
                <target>bar
            </trans-unit>
            <trans-unit id="2">
                <source>extra</source>
            </trans-unit>
            <trans-unit id="3">
                <source>key</source>
                <target></target>
            </trans-unit>
            <trans-unit id="4">
                <source>test</source>
                <target>with</target>
                <note>note</note>
            </trans-unit>
        </body>
    </file>
</xliff>
<?php

return array (
  'foo' => 'bar',
);
<?xml version="1.0" encoding="ISO-8859-1"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
  <file source-language="en" datatype="plaintext" original="file.ext">
    <body>
      <trans-unit id="1" resname="foo">
        <source>foo</source>
        <target>br</target>
      </trans-unit>
      <trans-unit id="2" resname="bar">
        <source>bar</source>
        <target>f</target>
      </trans-unit>
    </body>
  </file>
</xliff>
          $      ,      8      A              foo foos bar bars msgid "foo"
msgid_plural "foos"
msgstr[0] "bar"
msgstr[1] "bars"

msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: en\n"

msgid "foo"
msgstr "bar"<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
  <file source-language="en" datatype="plaintext" original="file.ext">
    <body>
      <trans-unit id="acbd18db4cc2f85cedef654fccc4a4d8" resname="foo">
        <source>foo</source>
        <target>bar</target>
      </trans-unit>
      <trans-unit id="3c6e0b8a9c15224a8228b9a98ca1531d" resname="key">
        <source>key</source>
        <target></target>
      </trans-unit>
    </body>
  </file>
</xliff>
"foo"; "bar"
#"bar"; "foo"
"incorrect"; "number"; "columns"; "will"; "be"; "ignored"
"incorrect"foo;bar
bar;"foo
foo"
"foo;foo";bar
foo="bar"
foo: bar
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit>
                <source>foo</source>
                <target>bar</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Loader;

use Symfony\Component\Translation\Loader\YamlFileLoader;
use Symfony\Component\Config\Resource\FileResource;

class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testLoad()
    {
        $loader = new YamlFileLoader();
        $resource = __DIR__.'/../fixtures/resources.yml';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array('foo' => 'bar'), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    public function testLoadDoesNothingIfEmpty()
    {
        $loader = new YamlFileLoader();
        $resource = __DIR__.'/../fixtures/empty.yml';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array(), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
     */
    public function testLoadNonExistingResource()
    {
        $loader = new YamlFileLoader();
        $resource = __DIR__.'/../fixtures/non-existing.yml';
        $loader->load($resource, 'en', 'domain1');
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
     */
    public function testLoadThrowsAnExceptionIfFileNotLocal()
    {
        $loader = new YamlFileLoader();
        $resource = 'http://example.com/resources.yml';
        $loader->load($resource, 'en', 'domain1');
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
     */
    public function testLoadThrowsAnExceptionIfNotAnArray()
    {
        $loader = new YamlFileLoader();
        $resource = __DIR__.'/../fixtures/non-valid.yml';
        $loader->load($resource, 'en', 'domain1');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Loader;

abstract class LocalizedTestCase extends \PHPUnit_Framework_TestCase
{
    protected function setUp()
    {
        if (!extension_loaded('intl')) {
            $this->markTestSkipped('The "intl" extension is not available');
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Loader;

use Symfony\Component\Translation\Loader\IcuResFileLoader;
use Symfony\Component\Config\Resource\DirectoryResource;

class IcuResFileLoaderTest extends LocalizedTestCase
{
    protected function setUp()
    {
        if (!extension_loaded('intl')) {
            $this->markTestSkipped('This test requires intl extension to work.');
        }
    }

    public function testLoad()
    {
        // resource is build using genrb command
        $loader = new IcuResFileLoader();
        $resource = __DIR__.'/../fixtures/resourcebundle/res';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array('foo' => 'bar'), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new DirectoryResource($resource)), $catalogue->getResources());
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
     */
    public function testLoadNonExistingResource()
    {
        $loader = new IcuResFileLoader();
        $loader->load(__DIR__.'/../fixtures/non-existing.txt', 'en', 'domain1');
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
     */
    public function testLoadInvalidResource()
    {
        $loader = new IcuResFileLoader();
        $loader->load(__DIR__.'/../fixtures/resourcebundle/corrupted', 'en', 'domain1');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Loader;

use Symfony\Component\Translation\Loader\CsvFileLoader;
use Symfony\Component\Config\Resource\FileResource;

class CsvFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testLoad()
    {
        $loader = new CsvFileLoader();
        $resource = __DIR__.'/../fixtures/resources.csv';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array('foo' => 'bar'), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    public function testLoadDoesNothingIfEmpty()
    {
        $loader = new CsvFileLoader();
        $resource = __DIR__.'/../fixtures/empty.csv';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array(), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
     */
    public function testLoadNonExistingResource()
    {
        $loader = new CsvFileLoader();
        $resource = __DIR__.'/../fixtures/not-exists.csv';
        $loader->load($resource, 'en', 'domain1');
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
     */
    public function testLoadNonLocalResource()
    {
        $loader = new CsvFileLoader();
        $resource = 'http://example.com/resources.csv';
        $loader->load($resource, 'en', 'domain1');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Loader;

use Symfony\Component\Translation\Loader\MoFileLoader;
use Symfony\Component\Config\Resource\FileResource;

class MoFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testLoad()
    {
        $loader = new MoFileLoader();
        $resource = __DIR__.'/../fixtures/resources.mo';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array('foo' => 'bar'), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    public function testLoadPlurals()
    {
        $loader = new MoFileLoader();
        $resource = __DIR__.'/../fixtures/plurals.mo';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array('foo' => 'bar', 'foos' => '{0} bar|{1} bars'), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
     */
    public function testLoadNonExistingResource()
    {
        $loader = new MoFileLoader();
        $resource = __DIR__.'/../fixtures/non-existing.mo';
        $loader->load($resource, 'en', 'domain1');
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
     */
    public function testLoadInvalidResource()
    {
        $loader = new MoFileLoader();
        $resource = __DIR__.'/../fixtures/empty.mo';
        $loader->load($resource, 'en', 'domain1');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Loader;

use Symfony\Component\Translation\Loader\PhpFileLoader;
use Symfony\Component\Config\Resource\FileResource;

class PhpFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testLoad()
    {
        $loader = new PhpFileLoader();
        $resource = __DIR__.'/../fixtures/resources.php';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array('foo' => 'bar'), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
     */
    public function testLoadNonExistingResource()
    {
        $loader = new PhpFileLoader();
        $resource = __DIR__.'/../fixtures/non-existing.php';
        $loader->load($resource, 'en', 'domain1');
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
     */
    public function testLoadThrowsAnExceptionIfFileNotLocal()
    {
        $loader = new PhpFileLoader();
        $resource = 'http://example.com/resources.php';
        $loader->load($resource, 'en', 'domain1');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Loader;

use Symfony\Component\Translation\Loader\QtFileLoader;
use Symfony\Component\Config\Resource\FileResource;

class QtFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testLoad()
    {
        $loader = new QtFileLoader();
        $resource = __DIR__.'/../fixtures/resources.ts';
        $catalogue = $loader->load($resource, 'en', 'resources');

        $this->assertEquals(array('foo' => 'bar'), $catalogue->all('resources'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
     */
    public function testLoadNonExistingResource()
    {
        $loader = new QtFileLoader();
        $resource = __DIR__.'/../fixtures/non-existing.ts';
        $loader->load($resource, 'en', 'domain1');
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
     */
    public function testLoadNonLocalResource()
    {
        $loader = new QtFileLoader();
        $resource = 'http://domain1.com/resources.ts';
        $loader->load($resource, 'en', 'domain1');
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
     */
    public function testLoadInvalidResource()
    {
        $loader = new QtFileLoader();
        $resource = __DIR__.'/../fixtures/invalid-xml-resources.xlf';
        $loader->load($resource, 'en', 'domain1');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Loader;

use Symfony\Component\Translation\Loader\XliffFileLoader;
use Symfony\Component\Config\Resource\FileResource;

class XliffFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testLoad()
    {
        $loader = new XliffFileLoader();
        $resource = __DIR__.'/../fixtures/resources.xlf';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    public function testLoadWithResname()
    {
        $loader = new XliffFileLoader();
        $catalogue = $loader->load(__DIR__.'/../fixtures/resname.xlf', 'en', 'domain1');

        $this->assertEquals(array('foo' => 'bar', 'bar' => 'baz', 'baz' => 'foo'), $catalogue->all('domain1'));
    }

    public function testIncompleteResource()
    {
        $loader = new XliffFileLoader();
        $catalogue = $loader->load(__DIR__.'/../fixtures/resources.xlf', 'en', 'domain1');

        $this->assertEquals(array('foo' => 'bar', 'key' => '', 'test' => 'with'), $catalogue->all('domain1'));
        $this->assertFalse($catalogue->has('extra', 'domain1'));
    }

    public function testEncoding()
    {
        if (!function_exists('iconv') && !function_exists('mb_convert_encoding')) {
            $this->markTestSkipped('The iconv and mbstring extensions are not available.');
        }

        $loader = new XliffFileLoader();
        $catalogue = $loader->load(__DIR__.'/../fixtures/encoding.xlf', 'en', 'domain1');

        $this->assertEquals(utf8_decode('föö'), $catalogue->get('bar', 'domain1'));
        $this->assertEquals(utf8_decode('bär'), $catalogue->get('foo', 'domain1'));
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
     */
    public function testLoadInvalidResource()
    {
        $loader = new XliffFileLoader();
        $loader->load(__DIR__.'/../fixtures/resources.php', 'en', 'domain1');
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
     */
    public function testLoadResourceDoesNotValidate()
    {
        $loader = new XliffFileLoader();
        $loader->load(__DIR__.'/../fixtures/non-valid.xlf', 'en', 'domain1');
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
     */
    public function testLoadNonExistingResource()
    {
        $loader = new XliffFileLoader();
        $resource = __DIR__.'/../fixtures/non-existing.xlf';
        $loader->load($resource, 'en', 'domain1');
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
     */
    public function testLoadThrowsAnExceptionIfFileNotLocal()
    {
        $loader = new XliffFileLoader();
        $resource = 'http://example.com/resources.xlf';
        $loader->load($resource, 'en', 'domain1');
    }

    /**
     * @expectedException        \Symfony\Component\Translation\Exception\InvalidResourceException
     * @expectedExceptionMessage Document types are not allowed.
     */
    public function testDocTypeIsNotAllowed()
    {
        $loader = new XliffFileLoader();
        $loader->load(__DIR__.'/../fixtures/withdoctype.xlf', 'en', 'domain1');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Loader;

use Symfony\Component\Translation\Loader\IcuDatFileLoader;
use Symfony\Component\Config\Resource\FileResource;

class IcuDatFileLoaderTest extends LocalizedTestCase
{
    protected function setUp()
    {
        if (!extension_loaded('intl')) {
            $this->markTestSkipped('This test requires intl extension to work.');
        }
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\InvalidResourceException
     */
    public function testLoadInvalidResource()
    {
        $loader = new IcuDatFileLoader();
        $loader->load(__DIR__.'/../fixtures/resourcebundle/corrupted/resources', 'es', 'domain2');
    }

    public function testDatEnglishLoad()
    {
        // bundled resource is build using pkgdata command which at least in ICU 4.2 comes in extremely! buggy form
        // you must specify an temporary build directory which is not the same as current directory and
        // MUST reside on the same partition. pkgdata -p resources -T /srv -d.packagelist.txt
        $loader = new IcuDatFileLoader();
        $resource = __DIR__.'/../fixtures/resourcebundle/dat/resources';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array('symfony' => 'Symfony 2 is great'), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource.'.dat')), $catalogue->getResources());
    }

    public function testDatFrenchLoad()
    {
        $loader = new IcuDatFileLoader();
        $resource = __DIR__.'/../fixtures/resourcebundle/dat/resources';
        $catalogue = $loader->load($resource, 'fr', 'domain1');

        $this->assertEquals(array('symfony' => 'Symfony 2 est génial'), $catalogue->all('domain1'));
        $this->assertEquals('fr', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource.'.dat')), $catalogue->getResources());
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
     */
    public function testLoadNonExistingResource()
    {
        $loader = new IcuDatFileLoader();
        $loader->load(__DIR__.'/../fixtures/non-existing.txt', 'en', 'domain1');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Loader;

use Symfony\Component\Translation\Loader\PoFileLoader;
use Symfony\Component\Config\Resource\FileResource;

class PoFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testLoad()
    {
        $loader = new PoFileLoader();
        $resource = __DIR__.'/../fixtures/resources.po';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array('foo' => 'bar'), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    public function testLoadPlurals()
    {
        $loader = new PoFileLoader();
        $resource = __DIR__.'/../fixtures/plurals.po';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array('foo' => 'bar', 'foos' => 'bar|bars'), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    public function testLoadDoesNothingIfEmpty()
    {
        $loader = new PoFileLoader();
        $resource = __DIR__.'/../fixtures/empty.po';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array(), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
     */
    public function testLoadNonExistingResource()
    {
        $loader = new PoFileLoader();
        $resource = __DIR__.'/../fixtures/non-existing.po';
        $loader->load($resource, 'en', 'domain1');
    }

    public function testLoadEmptyTranslation()
    {
        $loader = new PoFileLoader();
        $resource = __DIR__.'/../fixtures/empty-translation.po';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array('foo' => ''), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Loader;

use Symfony\Component\Translation\Loader\JsonFileLoader;
use Symfony\Component\Config\Resource\FileResource;

class JsonFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    protected function setUp()
    {
        if (!class_exists('Symfony\Component\Config\Loader\Loader')) {
            $this->markTestSkipped('The "Config" component is not available');
        }
    }

    public function testLoad()
    {
        $loader = new JsonFileLoader();
        $resource = __DIR__.'/../fixtures/resources.json';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array('foo' => 'bar'), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    public function testLoadDoesNothingIfEmpty()
    {
        $loader = new JsonFileLoader();
        $resource = __DIR__.'/../fixtures/empty.json';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array(), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
     */
    public function testLoadNonExistingResource()
    {
        $loader = new JsonFileLoader();
        $resource = __DIR__.'/../fixtures/non-existing.json';
        $loader->load($resource, 'en', 'domain1');
    }

    /**
     * @expectedException           \Symfony\Component\Translation\Exception\InvalidResourceException
     * @expectedExceptionMessage    Error parsing JSON - Syntax error, malformed JSON
     */
    public function testParseException()
    {
        $loader = new JsonFileLoader();
        $resource = __DIR__.'/../fixtures/malformed.json';
        $loader->load($resource, 'en', 'domain1');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests\Loader;

use Symfony\Component\Translation\Loader\IniFileLoader;
use Symfony\Component\Config\Resource\FileResource;

class IniFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testLoad()
    {
        $loader = new IniFileLoader();
        $resource = __DIR__.'/../fixtures/resources.ini';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array('foo' => 'bar'), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    public function testLoadDoesNothingIfEmpty()
    {
        $loader = new IniFileLoader();
        $resource = __DIR__.'/../fixtures/empty.ini';
        $catalogue = $loader->load($resource, 'en', 'domain1');

        $this->assertEquals(array(), $catalogue->all('domain1'));
        $this->assertEquals('en', $catalogue->getLocale());
        $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources());
    }

    /**
     * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
     */
    public function testLoadNonExistingResource()
    {
        $loader = new IniFileLoader();
        $resource = __DIR__.'/../fixtures/non-existing.ini';
        $loader->load($resource, 'en', 'domain1');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests;

use Symfony\Component\Translation\IdentityTranslator;

class IdentityTranslatorTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getTransTests
     */
    public function testTrans($expected, $id, $parameters)
    {
        $translator = new IdentityTranslator();

        $this->assertEquals($expected, $translator->trans($id, $parameters));
    }

    /**
     * @dataProvider getTransChoiceTests
     */
    public function testTransChoiceWithExplicitLocale($expected, $id, $number, $parameters)
    {
        $translator = new IdentityTranslator();
        $translator->setLocale('en');

        $this->assertEquals($expected, $translator->transChoice($id, $number, $parameters));
    }

    /**
     * @dataProvider getTransChoiceTests
     */
    public function testTransChoiceWithDefaultLocale($expected, $id, $number, $parameters)
    {
        \Locale::setDefault('en');

        $translator = new IdentityTranslator();

        $this->assertEquals($expected, $translator->transChoice($id, $number, $parameters));
    }

    public function testGetSetLocale()
    {
        $translator = new IdentityTranslator();
        $translator->setLocale('en');

        $this->assertEquals('en', $translator->getLocale());
    }

    public function testGetLocaleReturnsDefaultLocaleIfNotSet()
    {
        $translator = new IdentityTranslator();

        \Locale::setDefault('en');
        $this->assertEquals('en', $translator->getLocale());

        \Locale::setDefault('pt_BR');
        $this->assertEquals('pt_BR', $translator->getLocale());
    }

    public function getTransTests()
    {
        return array(
            array('Symfony2 is great!', 'Symfony2 is great!', array()),
            array('Symfony2 is awesome!', 'Symfony2 is %what%!', array('%what%' => 'awesome')),
        );
    }

    public function getTransChoiceTests()
    {
        return array(
            array('There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0, array('%count%' => 0)),
            array('There is one apple', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 1, array('%count%' => 1)),
            array('There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10, array('%count%' => 10)),
            array('There are 0 apples', 'There is 1 apple|There are %count% apples', 0, array('%count%' => 0)),
            array('There is 1 apple', 'There is 1 apple|There are %count% apples', 1, array('%count%' => 1)),
            array('There are 10 apples', 'There is 1 apple|There are %count% apples', 10, array('%count%' => 10)),
            // custom validation messages may be coded with a fixed value
            array('There are 2 apples', 'There are 2 apples', 2, array('%count%' => 2)),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests;

use Symfony\Component\Translation\PluralizationRules;

/**
 * Test should cover all languages mentioned on http://translate.sourceforge.net/wiki/l10n/pluralforms
 * and Plural forms mentioned on http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms
 *
 * See also https://developer.mozilla.org/en/Localization_and_Plurals which mentions 15 rules having a maximum of 6 forms.
 * The mozilla code is also interesting to check for.
 *
 * As mentioned by chx http://drupal.org/node/1273968 we can cover all by testing number from 0 to 199
 *
 * The goal to cover all languages is to far fetched so this test case is smaller.
 *
 * @author Clemens Tolboom clemens@build2be.nl
 */
class PluralizationRulesTest  extends \PHPUnit_Framework_TestCase
{

    /**
     * We test failed langcode here.
     *
     * TODO: The languages mentioned in the data provide need to get fixed somehow within PluralizationRules.
     *
     * @dataProvider failingLangcodes
     */
    public function testFailedLangcodes($nplural, $langCodes)
    {
        $matrix = $this->generateTestData($nplural, $langCodes);
        $this->validateMatrix($nplural, $matrix, false);
    }

    /**
     * @dataProvider successLangcodes
     */
    public function testLangcodes($nplural, $langCodes)
    {
        $matrix = $this->generateTestData($nplural, $langCodes);
        $this->validateMatrix($nplural, $matrix);
    }

    /**
     * This array should contain all currently known langcodes.
     *
     * As it is impossible to have this ever complete we should try as hard as possible to have it almost complete.
     *
     * @return type
     */
    public function successLangcodes()
    {
      return array(
        array('1' , array('ay','bo', 'cgg','dz','id', 'ja', 'jbo', 'ka','kk','km','ko','ky')),
        array('2' , array('nl', 'fr', 'en', 'de', 'de_GE')),
        array('3' , array('be','bs','cs','hr')),
        array('4' , array('cy','mt', 'sl')),
        array('5' , array()),
        array('6' , array('ar')),
      );
    }

    /**
     * This array should be at least empty within the near future.
     *
     * This both depends on a complete list trying to add above as understanding
     * the plural rules of the current failing languages.
     *
     * @return array with nplural together with langcodes
     */
    public function failingLangcodes()
    {
      return array(
        array('1' , array('fa')),
        array('2' , array('jbo')),
        array('3' , array('cbs')),
        array('4' , array('gd','kw')),
        array('5' , array('ga')),
        array('6' , array()),
      );
    }

    /**
     * We validate only on the plural coverage. Thus the real rules is not tested.
     *
     * @param string  $nplural       plural expected
     * @param array   $matrix        containing langcodes and their plural index values.
     * @param boolean $expectSuccess
     */
    protected function validateMatrix($nplural, $matrix, $expectSuccess = true)
    {
        foreach ($matrix as $langCode => $data) {
            $indexes = array_flip($data);
            if ($expectSuccess) {
                $this->assertEquals($nplural, count($indexes), "Langcode '$langCode' has '$nplural' plural forms.");
            } else {
                $this->assertNotEquals((int) $nplural, count($indexes), "Langcode '$langCode' has '$nplural' plural forms.");
            }
        }
    }

    protected function generateTestData($plural, $langCodes)
    {
        $matrix = array();
        foreach ($langCodes as $langCode) {
            for ($count=0; $count<200; $count++) {
                $plural = PluralizationRules::get($count, $langCode);
                $matrix[$langCode][$count] = $plural;
            }
        }

        return $matrix;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests;

use Symfony\Component\Translation\Translator;
use Symfony\Component\Translation\Loader\ArrayLoader;

class TranslatorTest extends \PHPUnit_Framework_TestCase
{
    public function testSetGetLocale()
    {
        $translator = new Translator('en');

        $this->assertEquals('en', $translator->getLocale());

        $translator->setLocale('fr');
        $this->assertEquals('fr', $translator->getLocale());
    }

    public function testSetFallbackLocales()
    {
        $translator = new Translator('en');
        $translator->addLoader('array', new ArrayLoader());
        $translator->addResource('array', array('foo' => 'foofoo'), 'en');
        $translator->addResource('array', array('bar' => 'foobar'), 'fr');

        // force catalogue loading
        $translator->trans('bar');

        $translator->setFallbackLocales(array('fr'));
        $this->assertEquals('foobar', $translator->trans('bar'));
    }

    public function testSetFallbackLocalesMultiple()
    {
        $translator = new Translator('en');
        $translator->addLoader('array', new ArrayLoader());
        $translator->addResource('array', array('foo' => 'foo (en)'), 'en');
        $translator->addResource('array', array('bar' => 'bar (fr)'), 'fr');

        // force catalogue loading
        $translator->trans('bar');

        $translator->setFallbackLocales(array('fr_FR', 'fr'));
        $this->assertEquals('bar (fr)', $translator->trans('bar'));
    }

    public function testTransWithFallbackLocale()
    {
        $translator = new Translator('fr_FR');
        $translator->addLoader('array', new ArrayLoader());
        $translator->addResource('array', array('foo' => 'foofoo'), 'en_US');
        $translator->addResource('array', array('bar' => 'foobar'), 'en');

        $translator->setFallbackLocales(array('en'));

        $this->assertEquals('foobar', $translator->trans('bar'));
    }

    public function testAddResourceAfterTrans()
    {
        $translator = new Translator('fr');
        $translator->addLoader('array', new ArrayLoader());

        $translator->setFallbackLocale(array('en'));

        $translator->addResource('array', array('foo' => 'foofoo'), 'en');
        $this->assertEquals('foofoo', $translator->trans('foo'));

        $translator->addResource('array', array('bar' => 'foobar'), 'en');
        $this->assertEquals('foobar', $translator->trans('bar'));
    }

    /**
     * @dataProvider      getTransFileTests
     * @expectedException \Symfony\Component\Translation\Exception\NotFoundResourceException
     */
    public function testTransWithoutFallbackLocaleFile($format, $loader)
    {
        $loaderClass = 'Symfony\\Component\\Translation\\Loader\\'.$loader;
        $translator = new Translator('en');
        $translator->addLoader($format, new $loaderClass());
        $translator->addResource($format, __DIR__.'/fixtures/non-existing', 'en');
        $translator->addResource($format, __DIR__.'/fixtures/resources.'.$format, 'en');

        // force catalogue loading
        $translator->trans('foo');
    }

    /**
     * @dataProvider getTransFileTests
     */
    public function testTransWithFallbackLocaleFile($format, $loader)
    {
        $loaderClass = 'Symfony\\Component\\Translation\\Loader\\'.$loader;
        $translator = new Translator('en_GB');
        $translator->addLoader($format, new $loaderClass());
        $translator->addResource($format, __DIR__.'/fixtures/non-existing', 'en_GB');
        $translator->addResource($format, __DIR__.'/fixtures/resources.'.$format, 'en', 'resources');

        $this->assertEquals('bar', $translator->trans('foo', array(), 'resources'));
    }

    public function testTransWithFallbackLocaleBis()
    {
        $translator = new Translator('en_US');
        $translator->addLoader('array', new ArrayLoader());
        $translator->addResource('array', array('foo' => 'foofoo'), 'en_US');
        $translator->addResource('array', array('bar' => 'foobar'), 'en');
        $this->assertEquals('foobar', $translator->trans('bar'));
    }

    public function testTransWithFallbackLocaleTer()
    {
        $translator = new Translator('fr_FR');
        $translator->addLoader('array', new ArrayLoader());
        $translator->addResource('array', array('foo' => 'foo (en_US)'), 'en_US');
        $translator->addResource('array', array('bar' => 'bar (en)'), 'en');

        $translator->setFallbackLocales(array('en_US', 'en'));

        $this->assertEquals('foo (en_US)', $translator->trans('foo'));
        $this->assertEquals('bar (en)', $translator->trans('bar'));
    }

    public function testTransNonExistentWithFallback()
    {
        $translator = new Translator('fr');
        $translator->setFallbackLocales(array('en'));
        $translator->addLoader('array', new ArrayLoader());
        $this->assertEquals('non-existent', $translator->trans('non-existent'));
    }

    /**
     * @expectedException \RuntimeException
     */
    public function testWhenAResourceHasNoRegisteredLoader()
    {
        $translator = new Translator('en');
        $translator->addResource('array', array('foo' => 'foofoo'), 'en');

        $translator->trans('foo');
    }

    /**
     * @dataProvider getTransTests
     */
    public function testTrans($expected, $id, $translation, $parameters, $locale, $domain)
    {
        $translator = new Translator('en');
        $translator->addLoader('array', new ArrayLoader());
        $translator->addResource('array', array((string) $id => $translation), $locale, $domain);

        $this->assertEquals($expected, $translator->trans($id, $parameters, $domain, $locale));
    }

    /**
     * @dataProvider getFlattenedTransTests
     */
    public function testFlattenedTrans($expected, $messages, $id)
    {
        $translator = new Translator('en');
        $translator->addLoader('array', new ArrayLoader());
        $translator->addResource('array', $messages, 'fr', '');

        $this->assertEquals($expected, $translator->trans($id, array(), '', 'fr'));
    }

    /**
     * @dataProvider getTransChoiceTests
     */
    public function testTransChoice($expected, $id, $translation, $number, $parameters, $locale, $domain)
    {
        $translator = new Translator('en');
        $translator->addLoader('array', new ArrayLoader());
        $translator->addResource('array', array((string) $id => $translation), $locale, $domain);

        $this->assertEquals($expected, $translator->transChoice($id, $number, $parameters, $domain, $locale));
    }

    public function getTransFileTests()
    {
        return array(
            array('csv', 'CsvFileLoader'),
            array('ini', 'IniFileLoader'),
            array('mo', 'MoFileLoader'),
            array('po', 'PoFileLoader'),
            array('php', 'PhpFileLoader'),
            array('ts', 'QtFileLoader'),
            array('xlf', 'XliffFileLoader'),
            array('yml', 'YamlFileLoader'),
            array('json', 'JsonFileLoader'),
        );
    }

    public function getTransTests()
    {
        return array(
            array('Symfony2 est super !', 'Symfony2 is great!', 'Symfony2 est super !', array(), 'fr', ''),
            array('Symfony2 est awesome !', 'Symfony2 is %what%!', 'Symfony2 est %what% !', array('%what%' => 'awesome'), 'fr', ''),
            array('Symfony2 est super !', new String('Symfony2 is great!'), 'Symfony2 est super !', array(), 'fr', ''),
        );
    }

    public function getFlattenedTransTests()
    {
        $messages = array(
            'symfony2' => array(
                'is' => array(
                    'great' => 'Symfony2 est super!'
                )
            ),
            'foo' => array(
                'bar' => array(
                    'baz' => 'Foo Bar Baz'
                ),
                'baz' => 'Foo Baz',
            ),
        );

        return array(
            array('Symfony2 est super!', $messages, 'symfony2.is.great'),
            array('Foo Bar Baz', $messages, 'foo.bar.baz'),
            array('Foo Baz', $messages, 'foo.baz'),
        );
    }

    public function getTransChoiceTests()
    {
        return array(
            array('Il y a 0 pomme', '{0} There are no appless|{1} There is one apple|]1,Inf] There is %count% apples', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 0, array('%count%' => 0), 'fr', ''),
            array('Il y a 1 pomme', '{0} There are no appless|{1} There is one apple|]1,Inf] There is %count% apples', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 1, array('%count%' => 1), 'fr', ''),
            array('Il y a 10 pommes', '{0} There are no appless|{1} There is one apple|]1,Inf] There is %count% apples', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 10, array('%count%' => 10), 'fr', ''),

            array('Il y a 0 pomme', 'There is one apple|There is %count% apples', 'Il y a %count% pomme|Il y a %count% pommes', 0, array('%count%' => 0), 'fr', ''),
            array('Il y a 1 pomme', 'There is one apple|There is %count% apples', 'Il y a %count% pomme|Il y a %count% pommes', 1, array('%count%' => 1), 'fr', ''),
            array('Il y a 10 pommes', 'There is one apple|There is %count% apples', 'Il y a %count% pomme|Il y a %count% pommes', 10, array('%count%' => 10), 'fr', ''),

            array('Il y a 0 pomme', 'one: There is one apple|more: There is %count% apples', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 0, array('%count%' => 0), 'fr', ''),
            array('Il y a 1 pomme', 'one: There is one apple|more: There is %count% apples', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 1, array('%count%' => 1), 'fr', ''),
            array('Il y a 10 pommes', 'one: There is one apple|more: There is %count% apples', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 10, array('%count%' => 10), 'fr', ''),

            array('Il n\'y a aucune pomme', '{0} There are no apples|one: There is one apple|more: There is %count% apples', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 0, array('%count%' => 0), 'fr', ''),
            array('Il y a 1 pomme', '{0} There are no apples|one: There is one apple|more: There is %count% apples', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 1, array('%count%' => 1), 'fr', ''),
            array('Il y a 10 pommes', '{0} There are no apples|one: There is one apple|more: There is %count% apples', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 10, array('%count%' => 10), 'fr', ''),

            array('Il y a 0 pomme', new String('{0} There are no appless|{1} There is one apple|]1,Inf] There is %count% apples'), '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 0, array('%count%' => 0), 'fr', ''),
        );
    }

    public function testTransChoiceFallback()
    {
        $translator = new Translator('ru');
        $translator->setFallbackLocales(array('en'));
        $translator->addLoader('array', new ArrayLoader());
        $translator->addResource('array', array('some_message2' => 'one thing|%count% things'), 'en');

        $this->assertEquals('10 things', $translator->transChoice('some_message2', 10, array('%count%' => 10)));
    }

    public function testTransChoiceFallbackBis()
    {
        $translator = new Translator('ru');
        $translator->setFallbackLocales(array('en_US', 'en'));
        $translator->addLoader('array', new ArrayLoader());
        $translator->addResource('array', array('some_message2' => 'one thing|%count% things'), 'en_US');

        $this->assertEquals('10 things', $translator->transChoice('some_message2', 10, array('%count%' => 10)));
    }

    public function testTransChoiceFallbackWithNoTranslation()
    {
        $translator = new Translator('ru');
        $translator->setFallbackLocales(array('en'));
        $translator->addLoader('array', new ArrayLoader());

        // consistent behavior with Translator::trans(), which returns the string
        // unchanged if it can't be found
        $this->assertEquals('some_message2', $translator->transChoice('some_message2', 10, array('%count%' => 10)));
    }
}

class String
{
    protected $str;

    public function __construct($str)
    {
        $this->str = $str;
    }

    public function __toString()
    {
        return $this->str;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests;

use Symfony\Component\Translation\MessageCatalogue;

class MessageCatalogueTest extends \PHPUnit_Framework_TestCase
{
    public function testGetLocale()
    {
        $catalogue = new MessageCatalogue('en');

        $this->assertEquals('en', $catalogue->getLocale());
    }

    public function testGetDomains()
    {
        $catalogue = new MessageCatalogue('en', array('domain1' => array(), 'domain2' => array()));

        $this->assertEquals(array('domain1', 'domain2'), $catalogue->getDomains());
    }

    public function testAll()
    {
        $catalogue = new MessageCatalogue('en', $messages = array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));

        $this->assertEquals(array('foo' => 'foo'), $catalogue->all('domain1'));
        $this->assertEquals(array(), $catalogue->all('domain88'));
        $this->assertEquals($messages, $catalogue->all());
    }

    public function testHas()
    {
        $catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));

        $this->assertTrue($catalogue->has('foo', 'domain1'));
        $this->assertFalse($catalogue->has('bar', 'domain1'));
        $this->assertFalse($catalogue->has('foo', 'domain88'));
    }

    public function testGetSet()
    {
        $catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
        $catalogue->set('foo1', 'foo1', 'domain1');

        $this->assertEquals('foo', $catalogue->get('foo', 'domain1'));
        $this->assertEquals('foo1', $catalogue->get('foo1', 'domain1'));
    }

    public function testAdd()
    {
        $catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
        $catalogue->add(array('foo1' => 'foo1'), 'domain1');

        $this->assertEquals('foo', $catalogue->get('foo', 'domain1'));
        $this->assertEquals('foo1', $catalogue->get('foo1', 'domain1'));

        $catalogue->add(array('foo' => 'bar'), 'domain1');
        $this->assertEquals('bar', $catalogue->get('foo', 'domain1'));
        $this->assertEquals('foo1', $catalogue->get('foo1', 'domain1'));

        $catalogue->add(array('foo' => 'bar'), 'domain88');
        $this->assertEquals('bar', $catalogue->get('foo', 'domain88'));
    }

    public function testReplace()
    {
        $catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
        $catalogue->replace($messages = array('foo1' => 'foo1'), 'domain1');

        $this->assertEquals($messages, $catalogue->all('domain1'));
    }

    public function testAddCatalogue()
    {
        $r = $this->getMock('Symfony\Component\Config\Resource\ResourceInterface');
        $r->expects($this->any())->method('__toString')->will($this->returnValue('r'));

        $r1 = $this->getMock('Symfony\Component\Config\Resource\ResourceInterface');
        $r1->expects($this->any())->method('__toString')->will($this->returnValue('r1'));

        $catalogue = new MessageCatalogue('en', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
        $catalogue->addResource($r);

        $catalogue1 = new MessageCatalogue('en', array('domain1' => array('foo1' => 'foo1')));
        $catalogue1->addResource($r1);

        $catalogue->addCatalogue($catalogue1);

        $this->assertEquals('foo', $catalogue->get('foo', 'domain1'));
        $this->assertEquals('foo1', $catalogue->get('foo1', 'domain1'));

        $this->assertEquals(array($r, $r1), $catalogue->getResources());
    }

    public function testAddFallbackCatalogue()
    {
        $r = $this->getMock('Symfony\Component\Config\Resource\ResourceInterface');
        $r->expects($this->any())->method('__toString')->will($this->returnValue('r'));

        $r1 = $this->getMock('Symfony\Component\Config\Resource\ResourceInterface');
        $r1->expects($this->any())->method('__toString')->will($this->returnValue('r1'));

        $catalogue = new MessageCatalogue('en_US', array('domain1' => array('foo' => 'foo'), 'domain2' => array('bar' => 'bar')));
        $catalogue->addResource($r);

        $catalogue1 = new MessageCatalogue('en', array('domain1' => array('foo' => 'bar', 'foo1' => 'foo1')));
        $catalogue1->addResource($r1);

        $catalogue->addFallbackCatalogue($catalogue1);

        $this->assertEquals('foo', $catalogue->get('foo', 'domain1'));
        $this->assertEquals('foo1', $catalogue->get('foo1', 'domain1'));

        $this->assertEquals(array($r, $r1), $catalogue->getResources());
    }

    /**
     * @expectedException \LogicException
     */
    public function testAddFallbackCatalogueWithCircularReference()
    {
        $main = new MessageCatalogue('en_US');
        $fallback = new MessageCatalogue('fr_FR');

        $fallback->addFallbackCatalogue($main);
        $main->addFallbackCatalogue($fallback);
    }

    /**
     * @expectedException \LogicException
     */
    public function testAddCatalogueWhenLocaleIsNotTheSameAsTheCurrentOne()
    {
        $catalogue = new MessageCatalogue('en');
        $catalogue->addCatalogue(new MessageCatalogue('fr', array()));
    }

    public function testGetAddResource()
    {
        $catalogue = new MessageCatalogue('en');
        $r = $this->getMock('Symfony\Component\Config\Resource\ResourceInterface');
        $r->expects($this->any())->method('__toString')->will($this->returnValue('r'));
        $catalogue->addResource($r);
        $catalogue->addResource($r);
        $r1 = $this->getMock('Symfony\Component\Config\Resource\ResourceInterface');
        $r1->expects($this->any())->method('__toString')->will($this->returnValue('r1'));
        $catalogue->addResource($r1);

        $this->assertEquals(array($r, $r1), $catalogue->getResources());
    }

    public function testMetadataDelete()
    {
        $catalogue = new MessageCatalogue('en');
        $this->assertEquals(array(), $catalogue->getMetadata('', ''), 'Metadata is empty');
        $catalogue->deleteMetadata('key', 'messages');
        $catalogue->deleteMetadata('', 'messages');
        $catalogue->deleteMetadata();
    }

    public function testMetadataSetGetDelete()
    {
        $catalogue = new MessageCatalogue('en');
        $catalogue->setMetadata('key', 'value');
        $this->assertEquals('value', $catalogue->getMetadata('key', 'messages'), "Metadata 'key' = 'value'");

        $catalogue->setMetadata('key2', array());
        $this->assertEquals(array(), $catalogue->getMetadata('key2', 'messages'), 'Metadata key2 is array');

        $catalogue->deleteMetadata('key2', 'messages');
        $this->assertEquals(null, $catalogue->getMetadata('key2', 'messages'), 'Metadata key2 should is deleted.');

        $catalogue->deleteMetadata('key2', 'domain');
        $this->assertEquals(null, $catalogue->getMetadata('key2', 'domain'), 'Metadata key2 should is deleted.');
    }

    public function testMetadataMerge()
    {
        $cat1 = new MessageCatalogue('en');
        $cat1->setMetadata('a', 'b');
        $this->assertEquals(array('messages' => array('a' => 'b')), $cat1->getMetadata('', ''), 'Cat1 contains messages metadata.');

        $cat2 = new MessageCatalogue('en');
        $cat2->setMetadata('b', 'c', 'domain');
        $this->assertEquals(array('domain' => array('b' => 'c')), $cat2->getMetadata('', ''), 'Cat2 contains domain metadata.');

        $cat1->addCatalogue($cat2);
        $this->assertEquals(array('messages' => array('a' => 'b'), 'domain' => array('b' => 'c')), $cat1->getMetadata('', ''), 'Cat1 contains merged metadata.');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation\Tests;

use Symfony\Component\Translation\MessageSelector;

class MessageSelectorTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getChooseTests
     */
    public function testChoose($expected, $id, $number)
    {
        $selector = new MessageSelector();

        $this->assertEquals($expected, $selector->choose($id, $number, 'en'));
    }

    public function testReturnMessageIfExactlyOneStandardRuleIsGiven()
    {
        $selector = new MessageSelector();

        $this->assertEquals('There are two apples', $selector->choose('There are two apples', 2, 'en'));
    }

    /**
     * @dataProvider getNonMatchingMessages
     * @expectedException \InvalidArgumentException
     */
    public function testThrowExceptionIfMatchingMessageCannotBeFound($id, $number)
    {
        $selector = new MessageSelector();

        $selector->choose($id, $number, 'en');
    }

    public function getNonMatchingMessages()
    {
        return array(
            array('{0} There are no apples|{1} There is one apple', 2),
            array('{1} There is one apple|]1,Inf] There are %count% apples', 0),
            array('{1} There is one apple|]2,Inf] There are %count% apples', 2),
            array('{0} There are no apples|There is one apple', 2),
        );
    }

    public function getChooseTests()
    {
        return array(
            array('There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0),
            array('There are no apples', '{0}     There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0),
            array('There are no apples', '{0}There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0),

            array('There is one apple', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 1),

            array('There are %count% apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10),
            array('There are %count% apples', '{0} There are no apples|{1} There is one apple|]1,Inf]There are %count% apples', 10),
            array('There are %count% apples', '{0} There are no apples|{1} There is one apple|]1,Inf]     There are %count% apples', 10),

            array('There are %count% apples', 'There is one apple|There are %count% apples', 0),
            array('There is one apple', 'There is one apple|There are %count% apples', 1),
            array('There are %count% apples', 'There is one apple|There are %count% apples', 10),

            array('There are %count% apples', 'one: There is one apple|more: There are %count% apples', 0),
            array('There is one apple', 'one: There is one apple|more: There are %count% apples', 1),
            array('There are %count% apples', 'one: There is one apple|more: There are %count% apples', 10),

            array('There are no apples', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 0),
            array('There is one apple', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 1),
            array('There are %count% apples', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 10),

            array('', '{0}|{1} There is one apple|]1,Inf] There are %count% apples', 0),
            array('', '{0} There are no apples|{1}|]1,Inf] There are %count% apples', 1),

            // Indexed only tests which are Gettext PoFile* compatible strings.
            array('There are %count% apples', 'There is one apple|There are %count% apples', 0),
            array('There is one apple', 'There is one apple|There are %count% apples', 1),
            array('There are %count% apples', 'There is one apple|There are %count% apples', 2),

            // Tests for float numbers
            array('There is almost one apple', '{0} There are no apples|]0,1[ There is almost one apple|{1} There is one apple|[1,Inf] There is more than one apple', 0.7),
            array('There is one apple', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 1),
            array('There is more than one apple', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 1.7),
            array('There are no apples', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0),
            array('There are no apples', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0.0),
            array('There are no apples', '{0.0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Translation;

use Symfony\Component\Config\Resource\ResourceInterface;

/**
 * MessageCatalogueInterface.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface MessageCatalogueInterface
{
    /**
     * Gets the catalogue locale.
     *
     * @return string The locale
     *
     * @api
     */
    public function getLocale();

    /**
     * Gets the domains.
     *
     * @return array An array of domains
     *
     * @api
     */
    public function getDomains();

    /**
     * Gets the messages within a given domain.
     *
     * If $domain is null, it returns all messages.
     *
     * @param string $domain The domain name
     *
     * @return array An array of messages
     *
     * @api
     */
    public function all($domain = null);

    /**
     * Sets a message translation.
     *
     * @param string $id          The message id
     * @param string $translation The messages translation
     * @param string $domain      The domain name
     *
     * @api
     */
    public function set($id, $translation, $domain = 'messages');

    /**
     * Checks if a message has a translation.
     *
     * @param string $id     The message id
     * @param string $domain The domain name
     *
     * @return Boolean true if the message has a translation, false otherwise
     *
     * @api
     */
    public function has($id, $domain = 'messages');

    /**
     * Checks if a message has a translation (it does not take into account the fallback mechanism).
     *
     * @param string $id     The message id
     * @param string $domain The domain name
     *
     * @return Boolean true if the message has a translation, false otherwise
     *
     * @api
     */
    public function defines($id, $domain = 'messages');

    /**
     * Gets a message translation.
     *
     * @param string $id     The message id
     * @param string $domain The domain name
     *
     * @return string The message translation
     *
     * @api
     */
    public function get($id, $domain = 'messages');

    /**
     * Sets translations for a given domain.
     *
     * @param array  $messages An array of translations
     * @param string $domain   The domain name
     *
     * @api
     */
    public function replace($messages, $domain = 'messages');

    /**
     * Adds translations for a given domain.
     *
     * @param array  $messages An array of translations
     * @param string $domain   The domain name
     *
     * @api
     */
    public function add($messages, $domain = 'messages');

    /**
     * Merges translations from the given Catalogue into the current one.
     *
     * The two catalogues must have the same locale.
     *
     * @param MessageCatalogueInterface $catalogue A MessageCatalogueInterface instance
     *
     * @api
     */
    public function addCatalogue(MessageCatalogueInterface $catalogue);

    /**
     * Merges translations from the given Catalogue into the current one
     * only when the translation does not exist.
     *
     * This is used to provide default translations when they do not exist for the current locale.
     *
     * @param MessageCatalogueInterface $catalogue A MessageCatalogueInterface instance
     *
     * @api
     */
    public function addFallbackCatalogue(MessageCatalogueInterface $catalogue);

    /**
     * Gets the fallback catalogue.
     *
     * @return MessageCatalogueInterface|null A MessageCatalogueInterface instance or null when no fallback has been set
     *
     * @api
     */
    public function getFallbackCatalogue();

    /**
     * Returns an array of resources loaded to build this collection.
     *
     * @return ResourceInterface[] An array of resources
     *
     * @api
     */
    public function getResources();

    /**
     * Adds a resource for this collection.
     *
     * @param ResourceInterface $resource A resource instance
     *
     * @api
     */
    public function addResource(ResourceInterface $resource);
}
{
    "name": "symfony/finder",
    "type": "library",
    "description": "Symfony Finder Component",
    "keywords": [],
    "homepage": "http://symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "http://symfony.com/contributors"
        }
    ],
    "require": {
        "php": ">=5.3.3"
    },
    "autoload": {
        "psr-0": { "Symfony\\Component\\Finder\\": "" }
    },
    "target-dir": "Symfony/Component/Finder",
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-master": "2.4-dev"
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Comparator;

/**
 * Comparator.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Comparator
{
    private $target;
    private $operator = '==';

    /**
     * Gets the target value.
     *
     * @return string The target value
     */
    public function getTarget()
    {
        return $this->target;
    }

    /**
     * Sets the target value.
     *
     * @param string $target The target value
     */
    public function setTarget($target)
    {
        $this->target = $target;
    }

    /**
     * Gets the comparison operator.
     *
     * @return string The operator
     */
    public function getOperator()
    {
        return $this->operator;
    }

    /**
     * Sets the comparison operator.
     *
     * @param string $operator A valid operator
     *
     * @throws \InvalidArgumentException
     */
    public function setOperator($operator)
    {
        if (!$operator) {
            $operator = '==';
        }

        if (!in_array($operator, array('>', '<', '>=', '<=', '==', '!='))) {
            throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator));
        }

        $this->operator = $operator;
    }

    /**
     * Tests against the target.
     *
     * @param mixed $test A test value
     *
     * @return Boolean
     */
    public function test($test)
    {
        switch ($this->operator) {
            case '>':
                return $test > $this->target;
            case '>=':
                return $test >= $this->target;
            case '<':
                return $test < $this->target;
            case '<=':
                return $test <= $this->target;
            case '!=':
                return $test != $this->target;
        }

        return $test == $this->target;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Comparator;

/**
 * NumberComparator compiles a simple comparison to an anonymous
 * subroutine, which you can call with a value to be tested again.
 *
 * Now this would be very pointless, if NumberCompare didn't understand
 * magnitudes.
 *
 * The target value may use magnitudes of kilobytes (k, ki),
 * megabytes (m, mi), or gigabytes (g, gi).  Those suffixed
 * with an i use the appropriate 2**n version in accordance with the
 * IEC standard: http://physics.nist.gov/cuu/Units/binary.html
 *
 * Based on the Perl Number::Compare module.
 *
 * @author    Fabien Potencier <fabien@symfony.com> PHP port
 * @author    Richard Clamp <richardc@unixbeard.net> Perl version
 *
 * @copyright 2004-2005 Fabien Potencier <fabien@symfony.com>
 * @copyright 2002 Richard Clamp <richardc@unixbeard.net>
 *
 * @see       http://physics.nist.gov/cuu/Units/binary.html
 */
class NumberComparator extends Comparator
{
    /**
     * Constructor.
     *
     * @param string $test A comparison string
     *
     * @throws \InvalidArgumentException If the test is not understood
     */
    public function __construct($test)
    {
        if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) {
            throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test));
        }

        $target = $matches[2];
        if (!is_numeric($target)) {
            throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target));
        }
        if (isset($matches[3])) {
            // magnitude
            switch (strtolower($matches[3])) {
                case 'k':
                    $target *= 1000;
                    break;
                case 'ki':
                    $target *= 1024;
                    break;
                case 'm':
                    $target *= 1000000;
                    break;
                case 'mi':
                    $target *= 1024*1024;
                    break;
                case 'g':
                    $target *= 1000000000;
                    break;
                case 'gi':
                    $target *= 1024*1024*1024;
                    break;
            }
        }

        $this->setTarget($target);
        $this->setOperator(isset($matches[1]) ? $matches[1] : '==');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Comparator;

/**
 * DateCompare compiles date comparisons.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DateComparator extends Comparator
{

    /**
     * Constructor.
     *
     * @param string $test A comparison string
     *
     * @throws \InvalidArgumentException If the test is not understood
     */
    public function __construct($test)
    {
        if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) {
            throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test));
        }

        try {
            $date = new \DateTime($matches[2]);
            $target = $date->format('U');
        } catch (\Exception $e) {
            throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2]));
        }

        $operator = isset($matches[1]) ? $matches[1] : '==';
        if ('since' === $operator || 'after' === $operator) {
            $operator = '>';
        }

        if ('until' === $operator || 'before' === $operator) {
            $operator = '<';
        }

        $this->setOperator($operator);
        $this->setTarget($target);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder;

use Symfony\Component\Finder\Adapter\AdapterInterface;
use Symfony\Component\Finder\Adapter\GnuFindAdapter;
use Symfony\Component\Finder\Adapter\BsdFindAdapter;
use Symfony\Component\Finder\Adapter\PhpAdapter;
use Symfony\Component\Finder\Exception\ExceptionInterface;

/**
 * Finder allows to build rules to find files and directories.
 *
 * It is a thin wrapper around several specialized iterator classes.
 *
 * All rules may be invoked several times.
 *
 * All methods return the current Finder object to allow easy chaining:
 *
 * $finder = Finder::create()->files()->name('*.php')->in(__DIR__);
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Finder implements \IteratorAggregate, \Countable
{
    const IGNORE_VCS_FILES = 1;
    const IGNORE_DOT_FILES = 2;

    private $mode        = 0;
    private $names       = array();
    private $notNames    = array();
    private $exclude     = array();
    private $filters     = array();
    private $depths      = array();
    private $sizes       = array();
    private $followLinks = false;
    private $sort        = false;
    private $ignore      = 0;
    private $dirs        = array();
    private $dates       = array();
    private $iterators   = array();
    private $contains    = array();
    private $notContains = array();
    private $adapters    = array();
    private $paths       = array();
    private $notPaths    = array();
    private $ignoreUnreadableDirs = false;

    private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg');

    /**
     * Constructor.
     */
    public function __construct()
    {
        $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES;

        $this
            ->addAdapter(new GnuFindAdapter())
            ->addAdapter(new BsdFindAdapter())
            ->addAdapter(new PhpAdapter(), -50)
            ->setAdapter('php')
        ;
    }

    /**
     * Creates a new Finder.
     *
     * @return Finder A new Finder instance
     *
     * @api
     */
    public static function create()
    {
        return new static();
    }

    /**
     * Registers a finder engine implementation.
     *
     * @param AdapterInterface $adapter  An adapter instance
     * @param integer          $priority Highest is selected first
     *
     * @return Finder The current Finder instance
     */
    public function addAdapter(Adapter\AdapterInterface $adapter, $priority = 0)
    {
        $this->adapters[$adapter->getName()] = array(
            'adapter'  => $adapter,
            'priority' => $priority,
            'selected' => false,
        );

        return $this->sortAdapters();
    }

    /**
     * Sets the selected adapter to the best one according to the current platform the code is run on.
     *
     * @return Finder The current Finder instance
     */
    public function useBestAdapter()
    {
        $this->resetAdapterSelection();

        return $this->sortAdapters();
    }

    /**
     * Selects the adapter to use.
     *
     * @param string $name
     *
     * @throws \InvalidArgumentException
     *
     * @return Finder The current Finder instance
     */
    public function setAdapter($name)
    {
        if (!isset($this->adapters[$name])) {
            throw new \InvalidArgumentException(sprintf('Adapter "%s" does not exist.', $name));
        }

        $this->resetAdapterSelection();
        $this->adapters[$name]['selected'] = true;

        return $this->sortAdapters();
    }

    /**
     * Removes all adapters registered in the finder.
     *
     * @return Finder The current Finder instance
     */
    public function removeAdapters()
    {
        $this->adapters = array();

        return $this;
    }

    /**
     * Returns registered adapters ordered by priority without extra information.
     *
     * @return AdapterInterface[]
     */
    public function getAdapters()
    {
        return array_values(array_map(function(array $adapter) {
            return $adapter['adapter'];
        }, $this->adapters));
    }

    /**
     * Restricts the matching to directories only.
     *
     * @return Finder The current Finder instance
     *
     * @api
     */
    public function directories()
    {
        $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES;

        return $this;
    }

    /**
     * Restricts the matching to files only.
     *
     * @return Finder The current Finder instance
     *
     * @api
     */
    public function files()
    {
        $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES;

        return $this;
    }

    /**
     * Adds tests for the directory depth.
     *
     * Usage:
     *
     *   $finder->depth('> 1') // the Finder will start matching at level 1.
     *   $finder->depth('< 3') // the Finder will descend at most 3 levels of directories below the starting point.
     *
     * @param int $level The depth level expression
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\DepthRangeFilterIterator
     * @see Symfony\Component\Finder\Comparator\NumberComparator
     *
     * @api
     */
    public function depth($level)
    {
        $this->depths[] = new Comparator\NumberComparator($level);

        return $this;
    }

    /**
     * Adds tests for file dates (last modified).
     *
     * The date must be something that strtotime() is able to parse:
     *
     *   $finder->date('since yesterday');
     *   $finder->date('until 2 days ago');
     *   $finder->date('> now - 2 hours');
     *   $finder->date('>= 2005-10-15');
     *
     * @param string $date A date rage string
     *
     * @return Finder The current Finder instance
     *
     * @see strtotime
     * @see Symfony\Component\Finder\Iterator\DateRangeFilterIterator
     * @see Symfony\Component\Finder\Comparator\DateComparator
     *
     * @api
     */
    public function date($date)
    {
        $this->dates[] = new Comparator\DateComparator($date);

        return $this;
    }

    /**
     * Adds rules that files must match.
     *
     * You can use patterns (delimited with / sign), globs or simple strings.
     *
     * $finder->name('*.php')
     * $finder->name('/\.php$/') // same as above
     * $finder->name('test.php')
     *
     * @param string $pattern A pattern (a regexp, a glob, or a string)
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\FilenameFilterIterator
     *
     * @api
     */
    public function name($pattern)
    {
        $this->names[] = $pattern;

        return $this;
    }

    /**
     * Adds rules that files must not match.
     *
     * @param string $pattern A pattern (a regexp, a glob, or a string)
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\FilenameFilterIterator
     *
     * @api
     */
    public function notName($pattern)
    {
        $this->notNames[] = $pattern;

        return $this;
    }

    /**
     * Adds tests that file contents must match.
     *
     * Strings or PCRE patterns can be used:
     *
     * $finder->contains('Lorem ipsum')
     * $finder->contains('/Lorem ipsum/i')
     *
     * @param string $pattern A pattern (string or regexp)
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\FilecontentFilterIterator
     */
    public function contains($pattern)
    {
        $this->contains[] = $pattern;

        return $this;
    }

    /**
     * Adds tests that file contents must not match.
     *
     * Strings or PCRE patterns can be used:
     *
     * $finder->notContains('Lorem ipsum')
     * $finder->notContains('/Lorem ipsum/i')
     *
     * @param string $pattern A pattern (string or regexp)
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\FilecontentFilterIterator
     */
    public function notContains($pattern)
    {
        $this->notContains[] = $pattern;

        return $this;
    }

    /**
     * Adds rules that filenames must match.
     *
     * You can use patterns (delimited with / sign) or simple strings.
     *
     * $finder->path('some/special/dir')
     * $finder->path('/some\/special\/dir/') // same as above
     *
     * Use only / as dirname separator.
     *
     * @param string $pattern A pattern (a regexp or a string)
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\FilenameFilterIterator
     */
    public function path($pattern)
    {
        $this->paths[] = $pattern;

        return $this;
    }

    /**
     * Adds rules that filenames must not match.
     *
     * You can use patterns (delimited with / sign) or simple strings.
     *
     * $finder->notPath('some/special/dir')
     * $finder->notPath('/some\/special\/dir/') // same as above
     *
     * Use only / as dirname separator.
     *
     * @param string $pattern A pattern (a regexp or a string)
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\FilenameFilterIterator
     */
    public function notPath($pattern)
    {
        $this->notPaths[] = $pattern;

        return $this;
    }

    /**
     * Adds tests for file sizes.
     *
     * $finder->size('> 10K');
     * $finder->size('<= 1Ki');
     * $finder->size(4);
     *
     * @param string $size A size range string
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\SizeRangeFilterIterator
     * @see Symfony\Component\Finder\Comparator\NumberComparator
     *
     * @api
     */
    public function size($size)
    {
        $this->sizes[] = new Comparator\NumberComparator($size);

        return $this;
    }

    /**
     * Excludes directories.
     *
     * @param string|array $dirs A directory path or an array of directories
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator
     *
     * @api
     */
    public function exclude($dirs)
    {
        $this->exclude = array_merge($this->exclude, (array) $dirs);

        return $this;
    }

    /**
     * Excludes "hidden" directories and files (starting with a dot).
     *
     * @param Boolean $ignoreDotFiles Whether to exclude "hidden" files or not
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator
     *
     * @api
     */
    public function ignoreDotFiles($ignoreDotFiles)
    {
        if ($ignoreDotFiles) {
            $this->ignore = $this->ignore | static::IGNORE_DOT_FILES;
        } else {
            $this->ignore = $this->ignore & ~static::IGNORE_DOT_FILES;
        }

        return $this;
    }

    /**
     * Forces the finder to ignore version control directories.
     *
     * @param Boolean $ignoreVCS Whether to exclude VCS files or not
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator
     *
     * @api
     */
    public function ignoreVCS($ignoreVCS)
    {
        if ($ignoreVCS) {
            $this->ignore = $this->ignore | static::IGNORE_VCS_FILES;
        } else {
            $this->ignore = $this->ignore & ~static::IGNORE_VCS_FILES;
        }

        return $this;
    }

    /**
     * Adds VCS patterns.
     *
     * @see ignoreVCS
     *
     * @param string|string[] $pattern VCS patterns to ignore
     */
    public static function addVCSPattern($pattern)
    {
        foreach ((array) $pattern as $p) {
            self::$vcsPatterns[] = $p;
        }

        self::$vcsPatterns = array_unique(self::$vcsPatterns);
    }

    /**
     * Sorts files and directories by an anonymous function.
     *
     * The anonymous function receives two \SplFileInfo instances to compare.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @param \Closure $closure An anonymous function
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\SortableIterator
     *
     * @api
     */
    public function sort(\Closure $closure)
    {
        $this->sort = $closure;

        return $this;
    }

    /**
     * Sorts files and directories by name.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\SortableIterator
     *
     * @api
     */
    public function sortByName()
    {
        $this->sort = Iterator\SortableIterator::SORT_BY_NAME;

        return $this;
    }

    /**
     * Sorts files and directories by type (directories before files), then by name.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\SortableIterator
     *
     * @api
     */
    public function sortByType()
    {
        $this->sort = Iterator\SortableIterator::SORT_BY_TYPE;

        return $this;
    }

    /**
     * Sorts files and directories by the last accessed time.
     *
     * This is the time that the file was last accessed, read or written to.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\SortableIterator
     *
     * @api
     */
    public function sortByAccessedTime()
    {
        $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME;

        return $this;
    }

    /**
     * Sorts files and directories by the last inode changed time.
     *
     * This is the time that the inode information was last modified (permissions, owner, group or other metadata).
     *
     * On Windows, since inode is not available, changed time is actually the file creation time.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\SortableIterator
     *
     * @api
     */
    public function sortByChangedTime()
    {
        $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME;

        return $this;
    }

    /**
     * Sorts files and directories by the last modified time.
     *
     * This is the last time the actual contents of the file were last modified.
     *
     * This can be slow as all the matching files and directories must be retrieved for comparison.
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\SortableIterator
     *
     * @api
     */
    public function sortByModifiedTime()
    {
        $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME;

        return $this;
    }

    /**
     * Filters the iterator with an anonymous function.
     *
     * The anonymous function receives a \SplFileInfo and must return false
     * to remove files.
     *
     * @param \Closure $closure An anonymous function
     *
     * @return Finder The current Finder instance
     *
     * @see Symfony\Component\Finder\Iterator\CustomFilterIterator
     *
     * @api
     */
    public function filter(\Closure $closure)
    {
        $this->filters[] = $closure;

        return $this;
    }

    /**
     * Forces the following of symlinks.
     *
     * @return Finder The current Finder instance
     *
     * @api
     */
    public function followLinks()
    {
        $this->followLinks = true;

        return $this;
    }

    /**
     * Tells finder to ignore unreadable directories.
     *
     * By default, scanning unreadable directories content throws an AccessDeniedException.
     *
     * @param boolean $ignore
     *
     * @return Finder The current Finder instance
     */
    public function ignoreUnreadableDirs($ignore = true)
    {
        $this->ignoreUnreadableDirs = (Boolean) $ignore;

        return $this;
    }

    /**
     * Searches files and directories which match defined rules.
     *
     * @param string|array $dirs A directory path or an array of directories
     *
     * @return Finder The current Finder instance
     *
     * @throws \InvalidArgumentException if one of the directories does not exist
     *
     * @api
     */
    public function in($dirs)
    {
        $resolvedDirs = array();

        foreach ((array) $dirs as $dir) {
            if (is_dir($dir)) {
                $resolvedDirs[] = $dir;
            } elseif ($glob = glob($dir, GLOB_ONLYDIR)) {
                $resolvedDirs = array_merge($resolvedDirs, $glob);
            } else {
                throw new \InvalidArgumentException(sprintf('The "%s" directory does not exist.', $dir));
            }
        }

        $this->dirs = array_merge($this->dirs, $resolvedDirs);

        return $this;
    }

    /**
     * Returns an Iterator for the current Finder configuration.
     *
     * This method implements the IteratorAggregate interface.
     *
     * @return \Iterator An iterator
     *
     * @throws \LogicException if the in() method has not been called
     */
    public function getIterator()
    {
        if (0 === count($this->dirs) && 0 === count($this->iterators)) {
            throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.');
        }

        if (1 === count($this->dirs) && 0 === count($this->iterators)) {
            return $this->searchInDirectory($this->dirs[0]);
        }

        $iterator = new \AppendIterator();
        foreach ($this->dirs as $dir) {
            $iterator->append($this->searchInDirectory($dir));
        }

        foreach ($this->iterators as $it) {
            $iterator->append($it);
        }

        return $iterator;
    }

    /**
     * Appends an existing set of files/directories to the finder.
     *
     * The set can be another Finder, an Iterator, an IteratorAggregate, or even a plain array.
     *
     * @param mixed $iterator
     *
     * @return Finder The finder
     *
     * @throws \InvalidArgumentException When the given argument is not iterable.
     */
    public function append($iterator)
    {
        if ($iterator instanceof \IteratorAggregate) {
            $this->iterators[] = $iterator->getIterator();
        } elseif ($iterator instanceof \Iterator) {
            $this->iterators[] = $iterator;
        } elseif ($iterator instanceof \Traversable || is_array($iterator)) {
            $it = new \ArrayIterator();
            foreach ($iterator as $file) {
                $it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file));
            }
            $this->iterators[] = $it;
        } else {
            throw new \InvalidArgumentException('Finder::append() method wrong argument type.');
        }

        return $this;
    }

    /**
     * Counts all the results collected by the iterators.
     *
     * @return int
     */
    public function count()
    {
        return iterator_count($this->getIterator());
    }

    /**
     * @return Finder The current Finder instance
     */
    private function sortAdapters()
    {
        uasort($this->adapters, function (array $a, array $b) {
            if ($a['selected'] || $b['selected']) {
                return $a['selected'] ? -1 : 1;
            }

            return $a['priority'] > $b['priority'] ? -1 : 1;
        });

        return $this;
    }

    /**
     * @param $dir
     *
     * @return \Iterator
     *
     * @throws \RuntimeException When none of the adapters are supported
     */
    private function searchInDirectory($dir)
    {
        if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) {
            $this->exclude = array_merge($this->exclude, self::$vcsPatterns);
        }

        if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) {
            $this->notPaths[] = '#(^|/)\..+(/|$)#';
        }

        foreach ($this->adapters as $adapter) {
            if ($adapter['adapter']->isSupported()) {
                try {
                    return $this
                        ->buildAdapter($adapter['adapter'])
                        ->searchInDirectory($dir);
                } catch (ExceptionInterface $e) {}
            }
        }

        throw new \RuntimeException('No supported adapter found.');
    }

    /**
     * @param AdapterInterface $adapter
     *
     * @return AdapterInterface
     */
    private function buildAdapter(AdapterInterface $adapter)
    {
        return $adapter
            ->setFollowLinks($this->followLinks)
            ->setDepths($this->depths)
            ->setMode($this->mode)
            ->setExclude($this->exclude)
            ->setNames($this->names)
            ->setNotNames($this->notNames)
            ->setContains($this->contains)
            ->setNotContains($this->notContains)
            ->setSizes($this->sizes)
            ->setDates($this->dates)
            ->setFilters($this->filters)
            ->setSort($this->sort)
            ->setPath($this->paths)
            ->setNotPath($this->notPaths)
            ->ignoreUnreadableDirs($this->ignoreUnreadableDirs);
    }

    /**
     * Unselects all adapters.
     */
    private function resetAdapterSelection()
    {
        $this->adapters = array_map(function (array $properties) {
            $properties['selected'] = false;

            return $properties;
        }, $this->adapters);
    }
}
Copyright (c) 2004-2013 Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder;

/**
 * Extends \SplFileInfo to support relative paths
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class SplFileInfo extends \SplFileInfo
{
    private $relativePath;
    private $relativePathname;

    /**
     * Constructor
     *
     * @param string $file             The file name
     * @param string $relativePath     The relative path
     * @param string $relativePathname The relative path name
     */
    public function __construct($file, $relativePath, $relativePathname)
    {
        parent::__construct($file);
        $this->relativePath = $relativePath;
        $this->relativePathname = $relativePathname;
    }

    /**
     * Returns the relative path
     *
     * @return string the relative path
     */
    public function getRelativePath()
    {
        return $this->relativePath;
    }

    /**
     * Returns the relative path name
     *
     * @return string the relative path name
     */
    public function getRelativePathname()
    {
        return $this->relativePathname;
    }

    /**
     * Returns the contents of the file
     *
     * @return string the contents of the file
     *
     * @throws \RuntimeException
     */
    public function getContents()
    {
        $level = error_reporting(0);
        $content = file_get_contents($this->getPathname());
        error_reporting($level);
        if (false === $content) {
            $error = error_get_last();
            throw new \RuntimeException($error['message']);
        }

        return $content;
    }
}
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Finder Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Tests</directory>
                <directory>./vendor</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder;

/**
 * Glob matches globbing patterns against text.
 *
 *   if match_glob("foo.*", "foo.bar") echo "matched\n";
 *
 * // prints foo.bar and foo.baz
 * $regex = glob_to_regex("foo.*");
 * for (array('foo.bar', 'foo.baz', 'foo', 'bar') as $t)
 * {
 *   if (/$regex/) echo "matched: $car\n";
 * }
 *
 * Glob implements glob(3) style matching that can be used to match
 * against text, rather than fetching names from a filesystem.
 *
 * Based on the Perl Text::Glob module.
 *
 * @author Fabien Potencier <fabien@symfony.com> PHP port
 * @author     Richard Clamp <richardc@unixbeard.net> Perl version
 * @copyright  2004-2005 Fabien Potencier <fabien@symfony.com>
 * @copyright  2002 Richard Clamp <richardc@unixbeard.net>
 */
class Glob
{
    /**
     * Returns a regexp which is the equivalent of the glob pattern.
     *
     * @param string  $glob                The glob pattern
     * @param Boolean $strictLeadingDot
     * @param Boolean $strictWildcardSlash
     *
     * @return string regex The regexp
     */
    public static function toRegex($glob, $strictLeadingDot = true, $strictWildcardSlash = true)
    {
        $firstByte = true;
        $escaping = false;
        $inCurlies = 0;
        $regex = '';
        $sizeGlob = strlen($glob);
        for ($i = 0; $i < $sizeGlob; $i++) {
            $car = $glob[$i];
            if ($firstByte) {
                if ($strictLeadingDot && '.' !== $car) {
                    $regex .= '(?=[^\.])';
                }

                $firstByte = false;
            }

            if ('/' === $car) {
                $firstByte = true;
            }

            if ('.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) {
                $regex .= "\\$car";
            } elseif ('*' === $car) {
                $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*');
            } elseif ('?' === $car) {
                $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.');
            } elseif ('{' === $car) {
                $regex .= $escaping ? '\\{' : '(';
                if (!$escaping) {
                    ++$inCurlies;
                }
            } elseif ('}' === $car && $inCurlies) {
                $regex .= $escaping ? '}' : ')';
                if (!$escaping) {
                    --$inCurlies;
                }
            } elseif (',' === $car && $inCurlies) {
                $regex .= $escaping ? ',' : '|';
            } elseif ('\\' === $car) {
                if ($escaping) {
                    $regex .= '\\\\';
                    $escaping = false;
                } else {
                    $escaping = true;
                }

                continue;
            } else {
                $regex .= $car;
            }
            $escaping = false;
        }

        return '#^'.$regex.'$#';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Shell;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class Shell
{
    const TYPE_UNIX    = 1;
    const TYPE_DARWIN  = 2;
    const TYPE_CYGWIN  = 3;
    const TYPE_WINDOWS = 4;
    const TYPE_BSD     = 5;

    /**
     * @var string|null
     */
    private $type;

    /**
     * Returns guessed OS type.
     *
     * @return int
     */
    public function getType()
    {
        if (null === $this->type) {
            $this->type = $this->guessType();
        }

        return $this->type;
    }

    /**
     * Tests if a command is available.
     *
     * @param string $command
     *
     * @return bool
     */
    public function testCommand($command)
    {
        if (self::TYPE_WINDOWS === $this->type) {
            // todo: find a way to test if windows command exists
            return false;
        }

        if (!function_exists('exec')) {
            return false;
        }

        // todo: find a better way (command could not be available)
        exec('command -v '.$command, $output, $code);

        return 0 === $code && count($output) > 0;
    }

    /**
     * Guesses OS type.
     *
     * @return int
     */
    private function guessType()
    {
        $os = strtolower(PHP_OS);

        if (false !== strpos($os, 'cygwin')) {
            return self::TYPE_CYGWIN;
        }

        if (false !== strpos($os, 'darwin')) {
            return self::TYPE_DARWIN;
        }

        if (false !== strpos($os, 'bsd')) {
            return self::TYPE_BSD;
        }

        if (0 === strpos($os, 'win')) {
            return self::TYPE_WINDOWS;
        }

        return self::TYPE_UNIX;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Shell;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class Command
{
    /**
     * @var Command|null
     */
    private $parent;

    /**
     * @var array
     */
    private $bits = array();

    /**
     * @var array
     */
    private $labels = array();

    /**
     * @var \Closure|null
     */
    private $errorHandler;

    /**
     * Constructor.
     *
     * @param Command|null $parent Parent command
     */
    public function __construct(Command $parent = null)
    {
        $this->parent = $parent;
    }

    /**
     * Returns command as string.
     *
     * @return string
     */
    public function __toString()
    {
        return $this->join();
    }

    /**
     * Creates a new Command instance.
     *
     * @param Command|null $parent Parent command
     *
     * @return Command New Command instance
     */
    public static function create(Command $parent = null)
    {
        return new self($parent);
    }

    /**
     * Escapes special chars from input.
     *
     * @param string $input A string to escape
     *
     * @return string The escaped string
     */
    public static function escape($input)
    {
        return escapeshellcmd($input);
    }

    /**
     * Quotes input.
     *
     * @param string $input An argument string
     *
     * @return string The quoted string
     */
    public static function quote($input)
    {
        return escapeshellarg($input);
    }

    /**
     * Appends a string or a Command instance.
     *
     * @param string|Command $bit
     *
     * @return Command The current Command instance
     */
    public function add($bit)
    {
        $this->bits[] = $bit;

        return $this;
    }

    /**
     * Prepends a string or a command instance.
     *
     * @param string|Command $bit
     *
     * @return Command The current Command instance
     */
    public function top($bit)
    {
        array_unshift($this->bits, $bit);

        foreach ($this->labels as $label => $index) {
            $this->labels[$label] += 1;
        }

        return $this;
    }

    /**
     * Appends an argument, will be quoted.
     *
     * @param string $arg
     *
     * @return Command The current Command instance
     */
    public function arg($arg)
    {
        $this->bits[] = self::quote($arg);

        return $this;
    }

    /**
     * Appends escaped special command chars.
     *
     * @param string $esc
     *
     * @return Command The current Command instance
     */
    public function cmd($esc)
    {
        $this->bits[] = self::escape($esc);

        return $this;
    }

    /**
     * Inserts a labeled command to feed later.
     *
     * @param string $label The unique label
     *
     * @return Command The current Command instance
     *
     * @throws \RuntimeException If label already exists
     */
    public function ins($label)
    {
        if (isset($this->labels[$label])) {
            throw new \RuntimeException(sprintf('Label "%s" already exists.', $label));
        }

        $this->bits[] = self::create($this);
        $this->labels[$label] = count($this->bits)-1;

        return $this->bits[$this->labels[$label]];
    }

    /**
     * Retrieves a previously labeled command.
     *
     * @param string $label
     *
     * @return Command The labeled command
     *
     * @throws \RuntimeException
     */
    public function get($label)
    {
        if (!isset($this->labels[$label])) {
            throw new \RuntimeException(sprintf('Label "%s" does not exist.', $label));
        }

        return $this->bits[$this->labels[$label]];
    }

    /**
     * Returns parent command (if any).
     *
     * @return Command Parent command
     *
     * @throws \RuntimeException If command has no parent
     */
    public function end()
    {
        if (null === $this->parent) {
            throw new \RuntimeException('Calling end on root command doesn\'t make sense.');
        }

        return $this->parent;
    }

    /**
     * Counts bits stored in command.
     *
     * @return int The bits count
     */
    public function length()
    {
        return count($this->bits);
    }

    /**
     * @param \Closure $errorHandler
     *
     * @return Command
     */
    public function setErrorHandler(\Closure $errorHandler)
    {
        $this->errorHandler = $errorHandler;

        return $this;
    }

    /**
     * @return \Closure|null
     */
    public function getErrorHandler()
    {
        return $this->errorHandler;
    }

    /**
     * Executes current command.
     *
     * @return array The command result
     *
     * @throws \RuntimeException
     */
    public function execute()
    {
        if (null === $this->errorHandler) {
            exec($this->join(), $output);
        } else {
            $process = proc_open($this->join(), array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes);
            $output = preg_split('~(\r\n|\r|\n)~', stream_get_contents($pipes[1]), -1, PREG_SPLIT_NO_EMPTY);

            if ($error = stream_get_contents($pipes[2])) {
                call_user_func($this->errorHandler, $error);
            }

            proc_close($process);
        }

        return $output ?: array();
    }

    /**
     * Joins bits.
     *
     * @return string
     */
    public function join()
    {
        return implode(' ', array_filter(
            array_map(function($bit) {
                return $bit instanceof Command ? $bit->join() : ($bit ?: null);
            }, $this->bits),
            function($bit) { return null !== $bit; }
        ));
    }

    /**
     * Insert a string or a Command instance before the bit at given position $index (index starts from 0).
     *
     * @param string|Command $bit
     * @param integer        $index
     *
     * @return Command The current Command instance
     */
    public function addAtIndex($bit, $index)
    {
        array_splice($this->bits, $index, 0, $bit);

        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Exception;

use Symfony\Component\Finder\Adapter\AdapterInterface;
use Symfony\Component\Finder\Shell\Command;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class ShellCommandFailureException extends AdapterFailureException
{
    /**
     * @var Command
     */
    private $command;

    /**
     * @param AdapterInterface $adapter
     * @param Command          $command
     * @param \Exception|null  $previous
     */
    public function __construct(AdapterInterface $adapter, Command $command, \Exception $previous = null)
    {
        $this->command = $command;
        parent::__construct($adapter, 'Shell command failed: "'.$command->join().'".', $previous);
    }

    /**
     * @return Command
     */
    public function getCommand()
    {
        return $this->command;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Exception;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class OperationNotPermitedException extends AdapterFailureException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Exception;

/**
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class AccessDeniedException extends \UnexpectedValueException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Exception;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
interface ExceptionInterface
{
    /**
     * @return \Symfony\Component\Finder\Adapter\AdapterInterface
     */
    public function getAdapter();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Exception;

use Symfony\Component\Finder\Adapter\AdapterInterface;

/**
 * Base exception for all adapter failures.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class AdapterFailureException extends \RuntimeException implements ExceptionInterface
{
    /**
     * @var \Symfony\Component\Finder\Adapter\AdapterInterface
     */
    private $adapter;

    /**
     * @param AdapterInterface $adapter
     * @param string|null      $message
     * @param \Exception|null  $previous
     */
    public function __construct(AdapterInterface $adapter, $message = null, \Exception $previous = null)
    {
        $this->adapter = $adapter;
        parent::__construct($message ?: 'Search failed with "'.$adapter->getName().'" adapter.', $previous);
    }

    /**
     * {@inheritdoc}
     */
    public function getAdapter()
    {
        return $this->adapter;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Expression;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class Regex implements ValueInterface
{
    const START_FLAG = '^';
    const END_FLAG   = '$';
    const BOUNDARY   = '~';
    const JOKER      = '.*';
    const ESCAPING   = '\\';

    /**
     * @var string
     */
    private $pattern;

    /**
     * @var array
     */
    private $options;

    /**
     * @var bool
     */
    private $startFlag;

    /**
     * @var bool
     */
    private $endFlag;

    /**
     * @var bool
     */
    private $startJoker;

    /**
     * @var bool
     */
    private $endJoker;

    /**
     * @param string $expr
     *
     * @return Regex
     *
     * @throws \InvalidArgumentException
     */
    public static function create($expr)
    {
        if (preg_match('/^(.{3,}?)([imsxuADU]*)$/', $expr, $m)) {
            $start = substr($m[1], 0, 1);
            $end   = substr($m[1], -1);

            if (($start === $end && !preg_match('/[*?[:alnum:] \\\\]/', $start)) || ($start === '{' && $end === '}')) {
                return new self(substr($m[1], 1, -1), $m[2], $end);
            }
        }

        throw new \InvalidArgumentException('Given expression is not a regex.');
    }

    /**
     * @param string $pattern
     * @param string $options
     * @param string $delimiter
     */
    public function __construct($pattern, $options = '', $delimiter = null)
    {
        if (null !== $delimiter) {
            // removes delimiter escaping
            $pattern = str_replace('\\'.$delimiter, $delimiter, $pattern);
        }

        $this->parsePattern($pattern);
        $this->options = $options;
    }

    /**
     * @return string
     */
    public function __toString()
    {
        return $this->render();
    }

    /**
     * {@inheritdoc}
     */
    public function render()
    {
        return self::BOUNDARY
            .$this->renderPattern()
            .self::BOUNDARY
            .$this->options;
    }

    /**
     * {@inheritdoc}
     */
    public function renderPattern()
    {
        return ($this->startFlag ? self::START_FLAG : '')
            .($this->startJoker ? self::JOKER : '')
            .str_replace(self::BOUNDARY, '\\'.self::BOUNDARY, $this->pattern)
            .($this->endJoker ? self::JOKER : '')
            .($this->endFlag ? self::END_FLAG : '');
    }

    /**
     * {@inheritdoc}
     */
    public function isCaseSensitive()
    {
        return !$this->hasOption('i');
    }

    /**
     * {@inheritdoc}
     */
    public function getType()
    {
        return Expression::TYPE_REGEX;
    }

    /**
     * {@inheritdoc}
     */
    public function prepend($expr)
    {
        $this->pattern = $expr.$this->pattern;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function append($expr)
    {
        $this->pattern .= $expr;

        return $this;
    }

    /**
     * @param string $option
     *
     * @return bool
     */
    public function hasOption($option)
    {
        return false !== strpos($this->options, $option);
    }

    /**
     * @param string $option
     *
     * @return Regex
     */
    public function addOption($option)
    {
        if (!$this->hasOption($option)) {
            $this->options.= $option;
        }

        return $this;
    }

    /**
     * @param string $option
     *
     * @return Regex
     */
    public function removeOption($option)
    {
        $this->options = str_replace($option, '', $this->options);

        return $this;
    }

    /**
     * @param bool $startFlag
     *
     * @return Regex
     */
    public function setStartFlag($startFlag)
    {
        $this->startFlag = $startFlag;

        return $this;
    }

    /**
     * @return bool
     */
    public function hasStartFlag()
    {
        return $this->startFlag;
    }

    /**
     * @param bool $endFlag
     *
     * @return Regex
     */
    public function setEndFlag($endFlag)
    {
        $this->endFlag = (bool) $endFlag;

        return $this;
    }

    /**
     * @return bool
     */
    public function hasEndFlag()
    {
        return $this->endFlag;
    }

    /**
     * @param bool $startJoker
     *
     * @return Regex
     */
    public function setStartJoker($startJoker)
    {
        $this->startJoker = $startJoker;

        return $this;
    }

    /**
     * @return bool
     */
    public function hasStartJoker()
    {
        return $this->startJoker;
    }

    /**
     * @param bool $endJoker
     *
     * @return Regex
     */
    public function setEndJoker($endJoker)
    {
        $this->endJoker = (bool) $endJoker;

        return $this;
    }

    /**
     * @return bool
     */
    public function hasEndJoker()
    {
        return $this->endJoker;
    }

    /**
     * @param array $replacement
     *
     * @return Regex
     */
    public function replaceJokers($replacement)
    {
        $replace = function ($subject) use ($replacement) {
            $subject = $subject[0];
            $replace = 0 === substr_count($subject, '\\') % 2;

            return $replace ? str_replace('.', $replacement, $subject) : $subject;
        };

        $this->pattern = preg_replace_callback('~[\\\\]*\\.~', $replace, $this->pattern);

        return $this;
    }

    /**
     * @param string $pattern
     */
    private function parsePattern($pattern)
    {
        if ($this->startFlag = self::START_FLAG === substr($pattern, 0, 1)) {
            $pattern = substr($pattern, 1);
        }

        if ($this->startJoker = self::JOKER === substr($pattern, 0, 2)) {
            $pattern = substr($pattern, 2);
        }

        if ($this->endFlag = (self::END_FLAG === substr($pattern, -1) && self::ESCAPING !== substr($pattern, -2, -1))) {
            $pattern = substr($pattern, 0, -1);
        }

        if ($this->endJoker = (self::JOKER === substr($pattern, -2) && self::ESCAPING !== substr($pattern, -3, -2))) {
            $pattern = substr($pattern, 0, -2);
        }

        $this->pattern = $pattern;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Expression;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class Glob implements ValueInterface
{
    /**
     * @var string
     */
    private $pattern;

    /**
     * @param string $pattern
     */
    public function __construct($pattern)
    {
        $this->pattern = $pattern;
    }

    /**
     * {@inheritdoc}
     */
    public function render()
    {
        return $this->pattern;
    }

    /**
     * {@inheritdoc}
     */
    public function renderPattern()
    {
        return $this->pattern;
    }

    /**
     * {@inheritdoc}
     */
    public function getType()
    {
        return Expression::TYPE_GLOB;
    }

    /**
     * {@inheritdoc}
     */
    public function isCaseSensitive()
    {
        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function prepend($expr)
    {
        $this->pattern = $expr.$this->pattern;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function append($expr)
    {
        $this->pattern .= $expr;

        return $this;
    }

    /**
     * Tests if glob is expandable ("*.{a,b}" syntax).
     *
     * @return bool
     */
    public function isExpandable()
    {
        return false !== strpos($this->pattern, '{')
            && false !== strpos($this->pattern, '}');
    }

    /**
     * @param bool $strictLeadingDot
     * @param bool $strictWildcardSlash
     *
     * @return Regex
     */
    public function toRegex($strictLeadingDot = true, $strictWildcardSlash = true)
    {
        $firstByte = true;
        $escaping = false;
        $inCurlies = 0;
        $regex = '';
        $sizeGlob = strlen($this->pattern);
        for ($i = 0; $i < $sizeGlob; $i++) {
            $car = $this->pattern[$i];
            if ($firstByte) {
                if ($strictLeadingDot && '.' !== $car) {
                    $regex .= '(?=[^\.])';
                }

                $firstByte = false;
            }

            if ('/' === $car) {
                $firstByte = true;
            }

            if ('.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) {
                $regex .= "\\$car";
            } elseif ('*' === $car) {
                $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*');
            } elseif ('?' === $car) {
                $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.');
            } elseif ('{' === $car) {
                $regex .= $escaping ? '\\{' : '(';
                if (!$escaping) {
                    ++$inCurlies;
                }
            } elseif ('}' === $car && $inCurlies) {
                $regex .= $escaping ? '}' : ')';
                if (!$escaping) {
                    --$inCurlies;
                }
            } elseif (',' === $car && $inCurlies) {
                $regex .= $escaping ? ',' : '|';
            } elseif ('\\' === $car) {
                if ($escaping) {
                    $regex .= '\\\\';
                    $escaping = false;
                } else {
                    $escaping = true;
                }

                continue;
            } else {
                $regex .= $car;
            }
            $escaping = false;
        }

        return new Regex('^'.$regex.'$');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Expression;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
interface ValueInterface
{
    /**
     * Renders string representation of expression.
     *
     * @return string
     */
    public function render();

    /**
     * Renders string representation of pattern.
     *
     * @return string
     */
    public function renderPattern();

    /**
     * Returns value case sensitivity.
     *
     * @return bool
     */
    public function isCaseSensitive();

    /**
     * Returns expression type.
     *
     * @return int
     */
    public function getType();

    /**
     * @param string $expr
     *
     * @return ValueInterface
     */
    public function prepend($expr);

    /**
     * @param string $expr
     *
     * @return ValueInterface
     */
    public function append($expr);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Expression;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class Expression implements ValueInterface
{
    const TYPE_REGEX = 1;
    const TYPE_GLOB  = 2;

    /**
     * @var ValueInterface
     */
    private $value;

    /**
     * @param string $expr
     *
     * @return Expression
     */
    public static function create($expr)
    {
        return new self($expr);
    }

    /**
     * @param string $expr
     */
    public function __construct($expr)
    {
        try {
            $this->value = Regex::create($expr);
        } catch (\InvalidArgumentException $e) {
            $this->value = new Glob($expr);
        }
    }

    /**
     * @return string
     */
    public function __toString()
    {
        return $this->render();
    }

    /**
     * {@inheritdoc}
     */
    public function render()
    {
        return $this->value->render();
    }

    /**
     * {@inheritdoc}
     */
    public function renderPattern()
    {
        return $this->value->renderPattern();
    }

    /**
     * @return bool
     */
    public function isCaseSensitive()
    {
        return $this->value->isCaseSensitive();
    }

    /**
     * @return int
     */
    public function getType()
    {
        return $this->value->getType();
    }

    /**
     * {@inheritdoc}
     */
    public function prepend($expr)
    {
        $this->value->prepend($expr);

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function append($expr)
    {
        $this->value->append($expr);

        return $this;
    }

    /**
     * @return bool
     */
    public function isRegex()
    {
        return self::TYPE_REGEX === $this->value->getType();
    }

    /**
     * @return bool
     */
    public function isGlob()
    {
        return self::TYPE_GLOB === $this->value->getType();
    }

    /**
     * @throws \LogicException
     *
     * @return Glob
     */
    public function getGlob()
    {
        if (self::TYPE_GLOB !== $this->value->getType()) {
            throw new \LogicException('Regex can\'t be transformed to glob.');
        }

        return $this->value;
    }

    /**
     * @return Regex
     */
    public function getRegex()
    {
        return self::TYPE_REGEX === $this->value->getType() ? $this->value : $this->value->toRegex();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

/**
 * CustomFilterIterator filters files by applying anonymous functions.
 *
 * The anonymous function receives a \SplFileInfo and must return false
 * to remove files.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class CustomFilterIterator extends FilterIterator
{
    private $filters = array();

    /**
     * Constructor.
     *
     * @param \Iterator $iterator The Iterator to filter
     * @param array     $filters  An array of PHP callbacks
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(\Iterator $iterator, array $filters)
    {
        foreach ($filters as $filter) {
            if (!is_callable($filter)) {
                throw new \InvalidArgumentException('Invalid PHP callback.');
            }
        }
        $this->filters = $filters;

        parent::__construct($iterator);
    }

    /**
     * Filters the iterator values.
     *
     * @return Boolean true if the value should be kept, false otherwise
     */
    public function accept()
    {
        $fileinfo = $this->current();

        foreach ($this->filters as $filter) {
            if (false === call_user_func($filter, $fileinfo)) {
                return false;
            }
        }

        return true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

/**
 * PathFilterIterator filters files by path patterns (e.g. some/special/dir).
 *
 * @author Fabien Potencier  <fabien@symfony.com>
 * @author Włodzimierz Gajda <gajdaw@gajdaw.pl>
 */
class PathFilterIterator extends MultiplePcreFilterIterator
{

    /**
     * Filters the iterator values.
     *
     * @return Boolean true if the value should be kept, false otherwise
     */
    public function accept()
    {
        $filename = $this->current()->getRelativePathname();

        if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
            $filename = strtr($filename, '\\', '/');
        }

        // should at least not match one rule to exclude
        foreach ($this->noMatchRegexps as $regex) {
            if (preg_match($regex, $filename)) {
                return false;
            }
        }

        // should at least match one rule
        $match = true;
        if ($this->matchRegexps) {
            $match = false;
            foreach ($this->matchRegexps as $regex) {
                if (preg_match($regex, $filename)) {
                    return true;
                }
            }
        }

        return $match;
    }

    /**
     * Converts strings to regexp.
     *
     * PCRE patterns are left unchanged.
     *
     * Default conversion:
     *     'lorem/ipsum/dolor'  ==>  'lorem\/ipsum\/dolor/'
     *
     * Use only / as directory separator (on Windows also).
     *
     * @param string $str Pattern: regexp or dirname.
     *
     * @return string regexp corresponding to a given string or regexp
     */
    protected function toRegex($str)
    {
        return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

/**
 * FilecontentFilterIterator filters files by their contents using patterns (regexps or strings).
 *
 * @author Fabien Potencier  <fabien@symfony.com>
 * @author Włodzimierz Gajda <gajdaw@gajdaw.pl>
 */
class FilecontentFilterIterator extends MultiplePcreFilterIterator
{
    /**
     * Filters the iterator values.
     *
     * @return Boolean true if the value should be kept, false otherwise
     */
    public function accept()
    {
        if (!$this->matchRegexps && !$this->noMatchRegexps) {
            return true;
        }

        $fileinfo = $this->current();

        if ($fileinfo->isDir() || !$fileinfo->isReadable()) {
            return false;
        }

        $content = $fileinfo->getContents();
        if (!$content) {
            return false;
        }

        // should at least not match one rule to exclude
        foreach ($this->noMatchRegexps as $regex) {
            if (preg_match($regex, $content)) {
                return false;
            }
        }

        // should at least match one rule
        $match = true;
        if ($this->matchRegexps) {
            $match = false;
            foreach ($this->matchRegexps as $regex) {
                if (preg_match($regex, $content)) {
                    return true;
                }
            }
        }

        return $match;
    }

    /**
     * Converts string to regexp if necessary.
     *
     * @param string $str Pattern: string or regexp
     *
     * @return string regexp corresponding to a given string or regexp
     */
    protected function toRegex($str)
    {
        return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

/**
 * This iterator just overrides the rewind method in order to correct a PHP bug.
 *
 * @see https://bugs.php.net/bug.php?id=49104
 *
 * @author Alex Bogomazov
 */
abstract class FilterIterator extends \FilterIterator
{
    /**
     * This is a workaround for the problem with \FilterIterator leaving inner \FilesystemIterator in wrong state after
     * rewind in some cases.
     *
     * @see FilterIterator::rewind()
     */
    public function rewind()
    {
        $iterator = $this;
        while ($iterator instanceof \OuterIterator) {
            $innerIterator = $iterator->getInnerIterator();

            if ($innerIterator instanceof RecursiveDirectoryIterator) {
                if ($innerIterator->isRewindable()) {
                    $innerIterator->next();
                    $innerIterator->rewind();
                }
            } elseif ($iterator->getInnerIterator() instanceof \FilesystemIterator) {
                $iterator->getInnerIterator()->next();
                $iterator->getInnerIterator()->rewind();
            }
            $iterator = $iterator->getInnerIterator();
        }

        parent::rewind();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

use Symfony\Component\Finder\Expression\Expression;

/**
 * FilenameFilterIterator filters files by patterns (a regexp, a glob, or a string).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FilenameFilterIterator extends MultiplePcreFilterIterator
{

    /**
     * Filters the iterator values.
     *
     * @return Boolean true if the value should be kept, false otherwise
     */
    public function accept()
    {
        $filename = $this->current()->getFilename();

        // should at least not match one rule to exclude
        foreach ($this->noMatchRegexps as $regex) {
            if (preg_match($regex, $filename)) {
                return false;
            }
        }

        // should at least match one rule
        $match = true;
        if ($this->matchRegexps) {
            $match = false;
            foreach ($this->matchRegexps as $regex) {
                if (preg_match($regex, $filename)) {
                    return true;
                }
            }
        }

        return $match;
    }

    /**
     * Converts glob to regexp.
     *
     * PCRE patterns are left unchanged.
     * Glob strings are transformed with Glob::toRegex().
     *
     * @param string $str Pattern: glob or regexp
     *
     * @return string regexp corresponding to a given glob or regexp
     */
    protected function toRegex($str)
    {
        return Expression::create($str)->getRegex()->render();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

use Symfony\Component\Finder\Comparator\DateComparator;

/**
 * DateRangeFilterIterator filters out files that are not in the given date range (last modified dates).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DateRangeFilterIterator extends FilterIterator
{
    private $comparators = array();

    /**
     * Constructor.
     *
     * @param \Iterator        $iterator    The Iterator to filter
     * @param DateComparator[] $comparators An array of DateComparator instances
     */
    public function __construct(\Iterator $iterator, array $comparators)
    {
        $this->comparators = $comparators;

        parent::__construct($iterator);
    }

    /**
     * Filters the iterator values.
     *
     * @return Boolean true if the value should be kept, false otherwise
     */
    public function accept()
    {
        $fileinfo = $this->current();

        if (!$fileinfo->isFile()) {
            return true;
        }

        $filedate = $fileinfo->getMTime();
        foreach ($this->comparators as $compare) {
            if (!$compare->test($filedate)) {
                return false;
            }
        }

        return true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

use Symfony\Component\Finder\Exception\AccessDeniedException;
use Symfony\Component\Finder\SplFileInfo;

/**
 * Extends the \RecursiveDirectoryIterator to support relative paths
 *
 * @author Victor Berchet <victor@suumit.com>
 */
class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
{
    /**
     * @var boolean
     */
    private $ignoreUnreadableDirs;

    /**
     * @var Boolean
     */
    private $rewindable;

    /**
     * Constructor.
     *
     * @param string  $path
     * @param int     $flags
     * @param boolean $ignoreUnreadableDirs
     *
     * @throws \RuntimeException
     */
    public function __construct($path, $flags, $ignoreUnreadableDirs = false)
    {
        if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) {
            throw new \RuntimeException('This iterator only support returning current as fileinfo.');
        }

        parent::__construct($path, $flags);
        $this->ignoreUnreadableDirs = $ignoreUnreadableDirs;
    }

    /**
     * Return an instance of SplFileInfo with support for relative paths
     *
     * @return SplFileInfo File information
     */
    public function current()
    {
        return new SplFileInfo(parent::current()->getPathname(), $this->getSubPath(), $this->getSubPathname());
    }

    /**
     * @return \RecursiveIterator
     *
     * @throws AccessDeniedException
     */
    public function getChildren()
    {
        try {
            return parent::getChildren();
        } catch (\UnexpectedValueException $e) {
            if ($this->ignoreUnreadableDirs) {
                // If directory is unreadable and finder is set to ignore it, a fake empty content is returned.
                return new \RecursiveArrayIterator(array());
            } else {
                throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e);
            }
        }
    }

    /**
     * Do nothing for non rewindable stream
     */
    public function rewind()
    {
        if (false === $this->isRewindable()) {
            return;
        }

        // @see https://bugs.php.net/bug.php?id=49104
        parent::next();

        parent::rewind();
    }

    /**
     * Checks if the stream is rewindable.
     *
     * @return Boolean true when the stream is rewindable, false otherwise
     */
    public function isRewindable()
    {
        if (null !== $this->rewindable) {
            return $this->rewindable;
        }

        if (false !== $stream = @opendir($this->getPath())) {
            $infos = stream_get_meta_data($stream);
            closedir($stream);

            if ($infos['seekable']) {
                return $this->rewindable = true;
            }
        }

        return $this->rewindable = false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

use Symfony\Component\Finder\SplFileInfo;

/**
 * Iterate over shell command result.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class FilePathsIterator extends \ArrayIterator
{
    /**
     * @var string
     */
    private $baseDir;

    /**
     * @var int
     */
    private $baseDirLength;

    /**
     * @var string
     */
    private $subPath;

    /**
     * @var string
     */
    private $subPathname;

    /**
     * @var SplFileInfo
     */
    private $current;

    /**
     * @param array  $paths   List of paths returned by shell command
     * @param string $baseDir Base dir for relative path building
     */
    public function __construct(array $paths, $baseDir)
    {
        $this->baseDir       = $baseDir;
        $this->baseDirLength = strlen($baseDir);

        parent::__construct($paths);
    }

    /**
     * @param string $name
     * @param array  $arguments
     *
     * @return mixed
     */
    public function __call($name, array $arguments)
    {
        return call_user_func_array(array($this->current(), $name), $arguments);
    }

    /**
     * Return an instance of SplFileInfo with support for relative paths.
     *
     * @return SplFileInfo File information
     */
    public function current()
    {
        return $this->current;
    }

    /**
     * @return string
     */
    public function key()
    {
        return $this->current->getPathname();
    }

    public function next()
    {
        parent::next();
        $this->buildProperties();
    }

    public function rewind()
    {
        parent::rewind();
        $this->buildProperties();
    }

    /**
     * @return string
     */
    public function getSubPath()
    {
        return $this->subPath;
    }

    /**
     * @return string
     */
    public function getSubPathname()
    {
        return $this->subPathname;
    }

    private function buildProperties()
    {
        $absolutePath = parent::current();

        if ($this->baseDir === substr($absolutePath, 0, $this->baseDirLength)) {
            $this->subPathname = ltrim(substr($absolutePath, $this->baseDirLength), '/\\');
            $dir = dirname($this->subPathname);
            $this->subPath = '.' === $dir ? '' : $dir;
        } else {
            $this->subPath = $this->subPathname = '';
        }

        $this->current = new SplFileInfo(parent::current(), $this->subPath, $this->subPathname);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

/**
 * ExcludeDirectoryFilterIterator filters out directories.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ExcludeDirectoryFilterIterator extends FilterIterator
{
    private $patterns = array();

    /**
     * Constructor.
     *
     * @param \Iterator $iterator    The Iterator to filter
     * @param array     $directories An array of directories to exclude
     */
    public function __construct(\Iterator $iterator, array $directories)
    {
        foreach ($directories as $directory) {
            $this->patterns[] = '#(^|/)'.preg_quote($directory, '#').'(/|$)#';
        }

        parent::__construct($iterator);
    }

    /**
     * Filters the iterator values.
     *
     * @return Boolean true if the value should be kept, false otherwise
     */
    public function accept()
    {
        $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath();
        $path = strtr($path, '\\', '/');
        foreach ($this->patterns as $pattern) {
            if (preg_match($pattern, $path)) {
                return false;
            }
        }

        return true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

use Symfony\Component\Finder\Expression\Expression;

/**
 * MultiplePcreFilterIterator filters files using patterns (regexps, globs or strings).
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class MultiplePcreFilterIterator extends FilterIterator
{
    protected $matchRegexps = array();
    protected $noMatchRegexps = array();

    /**
     * Constructor.
     *
     * @param \Iterator $iterator        The Iterator to filter
     * @param array     $matchPatterns   An array of patterns that need to match
     * @param array     $noMatchPatterns An array of patterns that need to not match
     */
    public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns)
    {
        foreach ($matchPatterns as $pattern) {
            $this->matchRegexps[] = $this->toRegex($pattern);
        }

        foreach ($noMatchPatterns as $pattern) {
            $this->noMatchRegexps[] = $this->toRegex($pattern);
        }

        parent::__construct($iterator);
    }

    /**
     * Checks whether the string is a regex.
     *
     * @param string $str
     *
     * @return Boolean Whether the given string is a regex
     */
    protected function isRegex($str)
    {
        return Expression::create($str)->isRegex();
    }

    /**
     * Converts string into regexp.
     *
     * @param string $str Pattern
     *
     * @return string regexp corresponding to a given string
     */
    abstract protected function toRegex($str);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

/**
 * SortableIterator applies a sort on a given Iterator.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class SortableIterator implements \IteratorAggregate
{
    const SORT_BY_NAME = 1;
    const SORT_BY_TYPE = 2;
    const SORT_BY_ACCESSED_TIME = 3;
    const SORT_BY_CHANGED_TIME = 4;
    const SORT_BY_MODIFIED_TIME = 5;

    private $iterator;
    private $sort;

    /**
     * Constructor.
     *
     * @param \Traversable     $iterator The Iterator to filter
     * @param integer|callback $sort     The sort type (SORT_BY_NAME, SORT_BY_TYPE, or a PHP callback)
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(\Traversable $iterator, $sort)
    {
        $this->iterator = $iterator;

        if (self::SORT_BY_NAME === $sort) {
            $this->sort = function ($a, $b) {
                return strcmp($a->getRealpath(), $b->getRealpath());
            };
        } elseif (self::SORT_BY_TYPE === $sort) {
            $this->sort = function ($a, $b) {
                if ($a->isDir() && $b->isFile()) {
                    return -1;
                } elseif ($a->isFile() && $b->isDir()) {
                    return 1;
                }

                return strcmp($a->getRealpath(), $b->getRealpath());
            };
        } elseif (self::SORT_BY_ACCESSED_TIME === $sort) {
            $this->sort = function ($a, $b) {
                return ($a->getATime() > $b->getATime());
            };
        } elseif (self::SORT_BY_CHANGED_TIME === $sort) {
            $this->sort = function ($a, $b) {
                return ($a->getCTime() > $b->getCTime());
            };
        } elseif (self::SORT_BY_MODIFIED_TIME === $sort) {
            $this->sort = function ($a, $b) {
                return ($a->getMTime() > $b->getMTime());
            };
        } elseif (is_callable($sort)) {
            $this->sort = $sort;
        } else {
            throw new \InvalidArgumentException('The SortableIterator takes a PHP callback or a valid built-in sort algorithm as an argument.');
        }
    }

    public function getIterator()
    {
        $array = iterator_to_array($this->iterator, true);
        uasort($array, $this->sort);

        return new \ArrayIterator($array);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

/**
 * DepthRangeFilterIterator limits the directory depth.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DepthRangeFilterIterator extends FilterIterator
{
    private $minDepth = 0;

    /**
     * Constructor.
     *
     * @param \RecursiveIteratorIterator $iterator    The Iterator to filter
     * @param int                        $minDepth    The min depth
     * @param int                        $maxDepth    The max depth
     */
    public function __construct(\RecursiveIteratorIterator $iterator, $minDepth = 0, $maxDepth = PHP_INT_MAX)
    {
        $this->minDepth = $minDepth;
        $iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth);

        parent::__construct($iterator);
    }

    /**
     * Filters the iterator values.
     *
     * @return Boolean true if the value should be kept, false otherwise
     */
    public function accept()
    {
        return $this->getInnerIterator()->getDepth() >= $this->minDepth;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

/**
 * FileTypeFilterIterator only keeps files, directories, or both.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FileTypeFilterIterator extends FilterIterator
{
    const ONLY_FILES       = 1;
    const ONLY_DIRECTORIES = 2;

    private $mode;

    /**
     * Constructor.
     *
     * @param \Iterator $iterator The Iterator to filter
     * @param integer   $mode     The mode (self::ONLY_FILES or self::ONLY_DIRECTORIES)
     */
    public function __construct(\Iterator $iterator, $mode)
    {
        $this->mode = $mode;

        parent::__construct($iterator);
    }

    /**
     * Filters the iterator values.
     *
     * @return Boolean true if the value should be kept, false otherwise
     */
    public function accept()
    {
        $fileinfo = $this->current();
        if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) {
            return false;
        } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) {
            return false;
        }

        return true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Iterator;

use Symfony\Component\Finder\Comparator\NumberComparator;

/**
 * SizeRangeFilterIterator filters out files that are not in the given size range.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class SizeRangeFilterIterator extends FilterIterator
{
    private $comparators = array();

    /**
     * Constructor.
     *
     * @param \Iterator          $iterator    The Iterator to filter
     * @param NumberComparator[] $comparators An array of NumberComparator instances
     */
    public function __construct(\Iterator $iterator, array $comparators)
    {
        $this->comparators = $comparators;

        parent::__construct($iterator);
    }

    /**
     * Filters the iterator values.
     *
     * @return Boolean true if the value should be kept, false otherwise
     */
    public function accept()
    {
        $fileinfo = $this->current();
        if (!$fileinfo->isFile()) {
            return true;
        }

        $filesize = $fileinfo->getSize();
        foreach ($this->comparators as $compare) {
            if (!$compare->test($filesize)) {
                return false;
            }
        }

        return true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Comparator;

use Symfony\Component\Finder\Comparator\Comparator;

class ComparatorTest extends \PHPUnit_Framework_TestCase
{
    public function testGetSetOperator()
    {
        $comparator = new Comparator();
        try {
            $comparator->setOperator('foo');
            $this->fail('->setOperator() throws an \InvalidArgumentException if the operator is not valid.');
        } catch (\Exception $e) {
            $this->assertInstanceOf('InvalidArgumentException', $e, '->setOperator() throws an \InvalidArgumentException if the operator is not valid.');
        }

        $comparator = new Comparator();
        $comparator->setOperator('>');
        $this->assertEquals('>', $comparator->getOperator(), '->getOperator() returns the current operator');
    }

    public function testGetSetTarget()
    {
        $comparator = new Comparator();
        $comparator->setTarget(8);
        $this->assertEquals(8, $comparator->getTarget(), '->getTarget() returns the target');
    }

    /**
     * @dataProvider getTestData
     */
    public function testTest($operator, $target, $match, $noMatch)
    {
        $c = new Comparator();
        $c->setOperator($operator);
        $c->setTarget($target);

        foreach ($match as $m) {
            $this->assertTrue($c->test($m), '->test() tests a string against the expression');
        }

        foreach ($noMatch as $m) {
            $this->assertFalse($c->test($m), '->test() tests a string against the expression');
        }
    }

    public function getTestData()
    {
        return array(
            array('<', '1000', array('500', '999'), array('1000', '1500')),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Comparator;

use Symfony\Component\Finder\Comparator\DateComparator;

class DateComparatorTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        try {
            new DateComparator('foobar');
            $this->fail('__construct() throws an \InvalidArgumentException if the test expression is not valid.');
        } catch (\Exception $e) {
            $this->assertInstanceOf('InvalidArgumentException', $e, '__construct() throws an \InvalidArgumentException if the test expression is not valid.');
        }

        try {
            new DateComparator('');
            $this->fail('__construct() throws an \InvalidArgumentException if the test expression is not valid.');
        } catch (\Exception $e) {
            $this->assertInstanceOf('InvalidArgumentException', $e, '__construct() throws an \InvalidArgumentException if the test expression is not valid.');
        }
    }

    /**
     * @dataProvider getTestData
     */
    public function testTest($test, $match, $noMatch)
    {
        $c = new DateComparator($test);

        foreach ($match as $m) {
            $this->assertTrue($c->test($m), '->test() tests a string against the expression');
        }

        foreach ($noMatch as $m) {
            $this->assertFalse($c->test($m), '->test() tests a string against the expression');
        }
    }

    public function getTestData()
    {
        return array(
            array('< 2005-10-10', array(strtotime('2005-10-09')), array(strtotime('2005-10-15'))),
            array('until 2005-10-10', array(strtotime('2005-10-09')), array(strtotime('2005-10-15'))),
            array('before 2005-10-10', array(strtotime('2005-10-09')), array(strtotime('2005-10-15'))),
            array('> 2005-10-10', array(strtotime('2005-10-15')), array(strtotime('2005-10-09'))),
            array('after 2005-10-10', array(strtotime('2005-10-15')), array(strtotime('2005-10-09'))),
            array('since 2005-10-10', array(strtotime('2005-10-15')), array(strtotime('2005-10-09'))),
            array('!= 2005-10-10', array(strtotime('2005-10-11')), array(strtotime('2005-10-10'))),
        );

    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Comparator;

use Symfony\Component\Finder\Comparator\NumberComparator;

class NumberComparatorTest extends \PHPUnit_Framework_TestCase
{

    /**
     * @dataProvider getConstructorTestData
     */
    public function testConstructor($successes, $failures)
    {
        foreach ($successes as $s) {
            new NumberComparator($s);
        }

        foreach ($failures as $f) {
            try {
                new NumberComparator($f);
                $this->fail('__construct() throws an \InvalidArgumentException if the test expression is not valid.');
            } catch (\Exception $e) {
                $this->assertInstanceOf('InvalidArgumentException', $e, '__construct() throws an \InvalidArgumentException if the test expression is not valid.');
            }
        }
    }

    /**
     * @dataProvider getTestData
     */
    public function testTest($test, $match, $noMatch)
    {
        $c = new NumberComparator($test);

        foreach ($match as $m) {
            $this->assertTrue($c->test($m), '->test() tests a string against the expression');
        }

        foreach ($noMatch as $m) {
            $this->assertFalse($c->test($m), '->test() tests a string against the expression');
        }
    }

    public function getTestData()
    {
        return array(
            array('< 1000', array('500', '999'), array('1000', '1500')),

            array('< 1K', array('500', '999'), array('1000', '1500')),
            array('<1k', array('500', '999'), array('1000', '1500')),
            array('  < 1 K ', array('500', '999'), array('1000', '1500')),
            array('<= 1K', array('1000'), array('1001')),
            array('> 1K', array('1001'), array('1000')),
            array('>= 1K', array('1000'), array('999')),

            array('< 1KI', array('500', '1023'), array('1024', '1500')),
            array('<= 1KI', array('1024'), array('1025')),
            array('> 1KI', array('1025'), array('1024')),
            array('>= 1KI', array('1024'), array('1023')),

            array('1KI', array('1024'), array('1023', '1025')),
            array('==1KI', array('1024'), array('1023', '1025')),

            array('==1m', array('1000000'), array('999999', '1000001')),
            array('==1mi', array(1024*1024), array(1024*1024-1, 1024*1024+1)),

            array('==1g', array('1000000000'), array('999999999', '1000000001')),
            array('==1gi', array(1024*1024*1024), array(1024*1024*1024-1, 1024*1024*1024+1)),

            array('!= 1000', array('500', '999'), array('1000')),
        );
    }

    public function getConstructorTestData()
    {
        return array(
            array(
                array(
                    '1', '0',
                    '3.5', '33.55', '123.456', '123456.78',
                    '.1', '.123',
                    '.0', '0.0',
                    '1.', '0.', '123.',
                    '==1', '!=1', '<1', '>1', '<=1', '>=1',
                    '==1k', '==1ki', '==1m', '==1mi', '==1g', '==1gi',
                    '1k', '1ki', '1m', '1mi', '1g', '1gi',
                ),
                array(
                    false, null, '',
                    ' ', 'foobar',
                    '=1', '===1',
                    '0 . 1', '123 .45', '234. 567',
                    '..', '.0.', '0.1.2',
                )
            ),
        );
    }

}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\FakeAdapter;

use Symfony\Component\Finder\Adapter\AbstractAdapter;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class NamedAdapter extends AbstractAdapter
{
    /**
     * @var string
     */
    private $name;

    /**
     * @param string $name
     */
    public function __construct($name)
    {
        $this->name = $name;
    }

    /**
     * {@inheritdoc}
     */
    public function searchInDirectory($dir)
    {
        return new \ArrayIterator(array());
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * {@inheritdoc}
     */
    protected function canBeUsed()
    {
        return true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\FakeAdapter;

use Symfony\Component\Finder\Adapter\AbstractAdapter;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class UnsupportedAdapter extends AbstractAdapter
{
    /**
     * {@inheritdoc}
     */
    public function searchInDirectory($dir)
    {
        return new \ArrayIterator(array());
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'unsupported';
    }

    /**
     * {@inheritdoc}
     */
    protected function canBeUsed()
    {
        return false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\FakeAdapter;

use Symfony\Component\Finder\Adapter\AbstractAdapter;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class DummyAdapter extends AbstractAdapter
{
    /**
     * @var \Iterator
     */
    private $iterator;

    /**
     * @param \Iterator $iterator
     */
    public function __construct(\Iterator $iterator)
    {
        $this->iterator = $iterator;
    }

    /**
     * {@inheritdoc}
     */
    public function searchInDirectory($dir)
    {
        return $this->iterator;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'yes';
    }

    /**
     * {@inheritdoc}
     */
    protected function canBeUsed()
    {
        return true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\FakeAdapter;

use Symfony\Component\Finder\Adapter\AbstractAdapter;
use Symfony\Component\Finder\Exception\AdapterFailureException;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class FailingAdapter extends AbstractAdapter
{
    /**
     * {@inheritdoc}
     */
    public function searchInDirectory($dir)
    {
        throw new AdapterFailureException($this);
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'failing';
    }

    /**
     * {@inheritdoc}
     */
    protected function canBeUsed()
    {
        return true;
    }
}
lorem ipsum dolor sit amet
LOREM IPSUM DOLOR SIT AMETdolor sit amet
DOLOR SIT AMETipsum dolor sit amet
IPSUM DOLOR SIT AMET<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests;

use Symfony\Component\Finder\Finder;
use Symfony\Component\Finder\Adapter;
use Symfony\Component\Finder\Tests\FakeAdapter;

class FinderTest extends Iterator\RealIteratorTestCase
{

    public function testCreate()
    {
        $this->assertInstanceOf('Symfony\Component\Finder\Finder', Finder::create());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testDirectories($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->directories());
        $this->assertIterator($this->toAbsolute(array('foo', 'toto')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $finder->directories();
        $finder->files();
        $finder->directories();
        $this->assertIterator($this->toAbsolute(array('foo', 'toto')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testFiles($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->files());
        $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'test.py', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $finder->files();
        $finder->directories();
        $finder->files();
        $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'test.py', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testDepth($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->depth('< 1'));
        $this->assertIterator($this->toAbsolute(array('foo', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->depth('<= 0'));
        $this->assertIterator($this->toAbsolute(array('foo', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->depth('>= 1'));
        $this->assertIterator($this->toAbsolute(array('foo/bar.tmp')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $finder->depth('< 1')->depth('>= 1');
        $this->assertIterator(array(), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testName($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->name('*.php'));
        $this->assertIterator($this->toAbsolute(array('test.php')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $finder->name('test.ph*');
        $finder->name('test.py');
        $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $finder->name('~^test~i');
        $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $finder->name('~\\.php$~i');
        $this->assertIterator($this->toAbsolute(array('test.php')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $finder->name('test.p{hp,y}');
        $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testNotName($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->notName('*.php'));
        $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $finder->notName('*.php');
        $finder->notName('*.py');
        $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $finder->name('test.ph*');
        $finder->name('test.py');
        $finder->notName('*.php');
        $finder->notName('*.py');
        $this->assertIterator(array(), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $finder->name('test.ph*');
        $finder->name('test.py');
        $finder->notName('*.p{hp,y}');
        $this->assertIterator(array(), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getRegexNameTestData
     *
     * @group regexName
     */
    public function testRegexName($adapter, $regex)
    {
        $finder = $this->buildFinder($adapter);
        $finder->name($regex);
        $this->assertIterator($this->toAbsolute(array('test.py', 'test.php')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testSize($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->files()->size('< 1K')->size('> 500'));
        $this->assertIterator($this->toAbsolute(array('test.php')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testDate($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->files()->date('until last month'));
        $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testExclude($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->exclude('foo'));
        $this->assertIterator($this->toAbsolute(array('test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testIgnoreVCS($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->ignoreVCS(false)->ignoreDotFiles(false));
        $this->assertIterator($this->toAbsolute(array('.git', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $finder->ignoreVCS(false)->ignoreVCS(false)->ignoreDotFiles(false);
        $this->assertIterator($this->toAbsolute(array('.git', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->ignoreVCS(true)->ignoreDotFiles(false));
        $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testIgnoreDotFiles($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->ignoreDotFiles(false)->ignoreVCS(false));
        $this->assertIterator($this->toAbsolute(array('.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $finder->ignoreDotFiles(false)->ignoreDotFiles(false)->ignoreVCS(false);
        $this->assertIterator($this->toAbsolute(array('.git', '.bar', '.foo', '.foo/.bar', '.foo/bar', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());

        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->ignoreDotFiles(true)->ignoreVCS(false));
        $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testSortByName($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->sortByName());
        $this->assertIterator($this->toAbsolute(array('foo', 'foo bar', 'foo/bar.tmp', 'test.php', 'test.py', 'toto')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testSortByType($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->sortByType());
        $this->assertIterator($this->toAbsolute(array('foo', 'foo bar', 'toto', 'foo/bar.tmp', 'test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testSortByAccessedTime($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->sortByAccessedTime());
        $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'toto', 'test.py', 'foo', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testSortByChangedTime($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->sortByChangedTime());
        $this->assertIterator($this->toAbsolute(array('toto', 'test.py', 'test.php', 'foo/bar.tmp', 'foo', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testSortByModifiedTime($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->sortByModifiedTime());
        $this->assertIterator($this->toAbsolute(array('foo/bar.tmp', 'test.php', 'toto', 'test.py', 'foo', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testSort($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->sort(function (\SplFileInfo $a, \SplFileInfo $b) { return strcmp($a->getRealpath(), $b->getRealpath()); }));
        $this->assertIterator($this->toAbsolute(array('foo', 'foo bar', 'foo/bar.tmp', 'test.php', 'test.py', 'toto')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testFilter($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->filter(function (\SplFileInfo $f) { return preg_match('/test/', $f) > 0; }));
        $this->assertIterator($this->toAbsolute(array('test.php', 'test.py')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testFollowLinks($adapter)
    {
        if ('\\' == DIRECTORY_SEPARATOR) {
            return;
        }

        $finder = $this->buildFinder($adapter);
        $this->assertSame($finder, $finder->followLinks());
        $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testIn($adapter)
    {
        $finder = $this->buildFinder($adapter);
        try {
            $finder->in('foobar');
            $this->fail('->in() throws a \InvalidArgumentException if the directory does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('InvalidArgumentException', $e, '->in() throws a \InvalidArgumentException if the directory does not exist');
        }

        $finder = $this->buildFinder($adapter);
        $iterator = $finder->files()->name('*.php')->depth('< 1')->in(array(self::$tmpDir, __DIR__))->getIterator();

        $this->assertIterator(array(self::$tmpDir.DIRECTORY_SEPARATOR.'test.php', __DIR__.DIRECTORY_SEPARATOR.'FinderTest.php'), $iterator);
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testInWithGlob($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $finder->in(array(__DIR__.'/Fixtures/*/B/C', __DIR__.'/Fixtures/*/*/B/C'))->getIterator();

        $this->assertIterator($this->toAbsoluteFixtures(array('A/B/C/abc.dat', 'copy/A/B/C/abc.dat.copy')), $finder);
    }

    /**
     * @dataProvider getAdaptersTestData
     * @expectedException \InvalidArgumentException
     */
    public function testInWithNonDirectoryGlob($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $finder->in(__DIR__.'/Fixtures/A/a*');
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testGetIterator($adapter)
    {
        $finder = $this->buildFinder($adapter);
        try {
            $finder->getIterator();
            $this->fail('->getIterator() throws a \LogicException if the in() method has not been called');
        } catch (\Exception $e) {
            $this->assertInstanceOf('LogicException', $e, '->getIterator() throws a \LogicException if the in() method has not been called');
        }

        $finder = $this->buildFinder($adapter);
        $dirs = array();
        foreach ($finder->directories()->in(self::$tmpDir) as $dir) {
            $dirs[] = (string) $dir;
        }

        $expected = $this->toAbsolute(array('foo', 'toto'));

        sort($dirs);
        sort($expected);

        $this->assertEquals($expected, $dirs, 'implements the \IteratorAggregate interface');

        $finder = $this->buildFinder($adapter);
        $this->assertEquals(2, iterator_count($finder->directories()->in(self::$tmpDir)), 'implements the \IteratorAggregate interface');

        $finder = $this->buildFinder($adapter);
        $a = iterator_to_array($finder->directories()->in(self::$tmpDir));
        $a = array_values(array_map(function ($a) { return (string) $a; }, $a));
        sort($a);
        $this->assertEquals($expected, $a, 'implements the \IteratorAggregate interface');
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testRelativePath($adapter)
    {
        $finder = $this->buildFinder($adapter)->in(self::$tmpDir);

        $paths = array();

        foreach ($finder as $file) {
            $paths[] = $file->getRelativePath();
        }

        $ref = array("", "", "", "", "foo", "");

        sort($ref);
        sort($paths);

        $this->assertEquals($ref, $paths);
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testRelativePathname($adapter)
    {
        $finder = $this->buildFinder($adapter)->in(self::$tmpDir)->sortByName();

        $paths = array();

        foreach ($finder as $file) {
            $paths[] = $file->getRelativePathname();
        }

        $ref = array("test.php", "toto", "test.py", "foo", "foo".DIRECTORY_SEPARATOR."bar.tmp", "foo bar");

        sort($paths);
        sort($ref);

        $this->assertEquals($ref, $paths);
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testAppendWithAFinder($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $finder->files()->in(self::$tmpDir.DIRECTORY_SEPARATOR.'foo');

        $finder1 = $this->buildFinder($adapter);
        $finder1->directories()->in(self::$tmpDir);

        $finder = $finder->append($finder1);

        $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'toto')), $finder->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testAppendWithAnArray($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $finder->files()->in(self::$tmpDir.DIRECTORY_SEPARATOR.'foo');

        $finder->append($this->toAbsolute(array('foo', 'toto')));

        $this->assertIterator($this->toAbsolute(array('foo', 'foo/bar.tmp', 'toto')), $finder->getIterator());
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testAppendReturnsAFinder($adapter)
    {
        $this->assertInstanceOf('Symfony\\Component\\Finder\\Finder', $this->buildFinder($adapter)->append(array()));
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testAppendDoesNotRequireIn($adapter)
    {
        $finder = $this->buildFinder($adapter);
        $finder->in(self::$tmpDir.DIRECTORY_SEPARATOR.'foo');

        $finder1 = Finder::create()->append($finder);

        $this->assertIterator(iterator_to_array($finder->getIterator()), $finder1->getIterator());
    }

    public function testCountDirectories()
    {
        $directory = Finder::create()->directories()->in(self::$tmpDir);
        $i = 0;

        foreach ($directory as $dir) {
            $i++;
        }

        $this->assertCount($i, $directory);
    }

    public function testCountFiles()
    {
        $files = Finder::create()->files()->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures');
        $i = 0;

        foreach ($files as $file) {
            $i++;
        }

        $this->assertCount($i, $files);
    }

    /**
     * @expectedException \LogicException
     */
    public function testCountWithoutIn()
    {
        $finder = Finder::create()->files();
        count($finder);
    }

    /**
     * @dataProvider getContainsTestData
     * @group grep
     */
    public function testContains($adapter, $matchPatterns, $noMatchPatterns, $expected)
    {
        $finder = $this->buildFinder($adapter);
        $finder->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures')
            ->name('*.txt')->sortByName()
            ->contains($matchPatterns)
            ->notContains($noMatchPatterns);

        $this->assertIterator($this->toAbsoluteFixtures($expected), $finder);
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testContainsOnDirectory(Adapter\AdapterInterface $adapter)
    {
        $finder = $this->buildFinder($adapter);
        $finder->in(__DIR__)
            ->directories()
            ->name('Fixtures')
            ->contains('abc');
        $this->assertIterator(array(), $finder);
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testNotContainsOnDirectory(Adapter\AdapterInterface $adapter)
    {
        $finder = $this->buildFinder($adapter);
        $finder->in(__DIR__)
            ->directories()
            ->name('Fixtures')
            ->notContains('abc');
        $this->assertIterator(array(), $finder);
    }

    /**
     * Searching in multiple locations involves AppendIterator which does an unnecessary rewind which leaves FilterIterator
     * with inner FilesystemIterator in an invalid state.
     *
     * @see https://bugs.php.net/bug.php?id=49104
     *
     * @dataProvider getAdaptersTestData
     */
    public function testMultipleLocations(Adapter\AdapterInterface $adapter)
    {
        $locations = array(
            self::$tmpDir.'/',
            self::$tmpDir.'/toto/',
        );

        // it is expected that there are test.py test.php in the tmpDir
        $finder = $this->buildFinder($adapter);
        $finder->in($locations)->depth('< 1')->name('test.php');

        $this->assertEquals(1, count($finder));
    }

    /**
     * Iterator keys must be the file pathname.
     *
     * @dataProvider getAdaptersTestData
     */
    public function testIteratorKeys(Adapter\AdapterInterface $adapter)
    {
        $finder = $this->buildFinder($adapter)->in(self::$tmpDir);
        foreach ($finder as $key => $file) {
            $this->assertEquals($file->getPathname(), $key);
        }
    }

    public function testAdaptersOrdering()
    {
        $finder = Finder::create()
            ->removeAdapters()
            ->addAdapter(new FakeAdapter\NamedAdapter('a'), 0)
            ->addAdapter(new FakeAdapter\NamedAdapter('b'), -50)
            ->addAdapter(new FakeAdapter\NamedAdapter('c'), 50)
            ->addAdapter(new FakeAdapter\NamedAdapter('d'), -25)
            ->addAdapter(new FakeAdapter\NamedAdapter('e'), 25);

        $this->assertEquals(
            array('c', 'e', 'a', 'd', 'b'),
            array_map(function(Adapter\AdapterInterface $adapter) {
                return $adapter->getName();
            }, $finder->getAdapters())
        );
    }

    public function testAdaptersChaining()
    {
        $iterator  = new \ArrayIterator(array());
        $filenames = $this->toAbsolute(array('foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto'));
        foreach ($filenames as $file) {
            $iterator->append(new \Symfony\Component\Finder\SplFileInfo($file, null, null));
        }

        $finder = Finder::create()
            ->removeAdapters()
            ->addAdapter(new FakeAdapter\UnsupportedAdapter(), 3)
            ->addAdapter(new FakeAdapter\FailingAdapter(), 2)
            ->addAdapter(new FakeAdapter\DummyAdapter($iterator), 1);

        $this->assertIterator($filenames, $finder->in(sys_get_temp_dir())->getIterator());
    }

    public function getAdaptersTestData()
    {
        return array_map(
            function ($adapter)  { return array($adapter); },
            $this->getValidAdapters()
        );
    }

    public function getContainsTestData()
    {
        $tests = array(
            array('', '', array()),
            array('foo', 'bar', array()),
            array('', 'foobar', array('dolor.txt', 'ipsum.txt', 'lorem.txt')),
            array('lorem ipsum dolor sit amet', 'foobar', array('lorem.txt')),
            array('sit', 'bar', array('dolor.txt', 'ipsum.txt', 'lorem.txt')),
            array('dolor sit amet', '@^L@m', array('dolor.txt', 'ipsum.txt')),
            array('/^lorem ipsum dolor sit amet$/m', 'foobar', array('lorem.txt')),
            array('lorem', 'foobar', array('lorem.txt')),
            array('', 'lorem', array('dolor.txt', 'ipsum.txt')),
            array('ipsum dolor sit amet', '/^IPSUM/m', array('lorem.txt')),
        );

        return $this->buildTestData($tests);
    }

    public function getRegexNameTestData()
    {
        $tests = array(
            array('~.+\\.p.+~i'),
            array('~t.*s~i'),
        );

        return $this->buildTestData($tests);
    }

    /**
     * @dataProvider getTestPathData
     */
    public function testPath(Adapter\AdapterInterface $adapter, $matchPatterns, $noMatchPatterns, array $expected)
    {
        $finder = $this->buildFinder($adapter);
        $finder->in(__DIR__.DIRECTORY_SEPARATOR.'Fixtures')
            ->path($matchPatterns)
            ->notPath($noMatchPatterns);

        $this->assertIterator($this->toAbsoluteFixtures($expected), $finder);
    }

    public function testAdapterSelection()
    {
        // test that by default, PhpAdapter is selected
        $adapters = Finder::create()->getAdapters();
        $this->assertTrue($adapters[0] instanceof Adapter\PhpAdapter);

        // test another adapter selection
        $adapters = Finder::create()->setAdapter('gnu_find')->getAdapters();
        $this->assertTrue($adapters[0] instanceof Adapter\GnuFindAdapter);

        // test that useBestAdapter method removes selection
        $adapters = Finder::create()->useBestAdapter()->getAdapters();
        $this->assertFalse($adapters[0] instanceof Adapter\PhpAdapter);
    }

    public function getTestPathData()
    {
        $tests = array(
            array('', '', array()),
            array('/^A\/B\/C/', '/C$/',
                array('A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat')
            ),
            array('/^A\/B/', 'foobar',
                array(
                    'A'.DIRECTORY_SEPARATOR.'B',
                    'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C',
                    'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'ab.dat',
                    'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat',
                )
            ),
            array('A/B/C', 'foobar',
                array(
                    'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C',
                    'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat',
                    'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C',
                    'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat.copy',
                )
            ),
            array('A/B', 'foobar',
                array(
                    //dirs
                    'A'.DIRECTORY_SEPARATOR.'B',
                    'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C',
                    'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B',
                    'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C',
                    //files
                    'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'ab.dat',
                    'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat',
                    'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'ab.dat.copy',
                    'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat.copy',
                )
            ),
            array('/^with space\//', 'foobar',
                array(
                    'with space'.DIRECTORY_SEPARATOR.'foo.txt',
                )
            ),
        );

        return $this->buildTestData($tests);
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testAccessDeniedException(Adapter\AdapterInterface $adapter)
    {
        if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
            $this->markTestSkipped('chmod is not supported on windows');
        }

        $finder = $this->buildFinder($adapter);
        $finder->files()->in(self::$tmpDir);

        // make 'foo' directory non-readable
        chmod(self::$tmpDir.DIRECTORY_SEPARATOR.'foo', 0333);

        try {
            $this->assertIterator($this->toAbsolute(array('foo bar', 'test.php', 'test.py')), $finder->getIterator());
            $this->fail('Finder should throw an exception when opening a non-readable directory.');
        } catch (\Exception $e) {
            $this->assertEquals('Symfony\\Component\\Finder\\Exception\\AccessDeniedException', get_class($e));
        }

        // restore original permissions
        chmod(self::$tmpDir.DIRECTORY_SEPARATOR.'foo', 0777);
    }

    /**
     * @dataProvider getAdaptersTestData
     */
    public function testIgnoredAccessDeniedException(Adapter\AdapterInterface $adapter)
    {
        if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
            $this->markTestSkipped('chmod is not supported on windows');
        }

        $finder = $this->buildFinder($adapter);
        $finder->files()->ignoreUnreadableDirs()->in(self::$tmpDir);

        // make 'foo' directory non-readable
        chmod(self::$tmpDir.DIRECTORY_SEPARATOR.'foo', 0333);

        $this->assertIterator($this->toAbsolute(array('foo bar', 'test.php', 'test.py')), $finder->getIterator());

        // restore original permissions
        chmod(self::$tmpDir.DIRECTORY_SEPARATOR.'foo', 0777);
    }

    private function buildTestData(array $tests)
    {
        $data = array();
        foreach ($this->getValidAdapters() as $adapter) {
            foreach ($tests as $test) {
                $data[] = array_merge(array($adapter), $test);
            }
        }

        return $data;
    }

    private function buildFinder(Adapter\AdapterInterface $adapter)
    {
        return Finder::create()
            ->removeAdapters()
            ->addAdapter($adapter);
    }

    private function getValidAdapters()
    {
        return array_filter(
            array(
                new Adapter\BsdFindAdapter(),
                new Adapter\GnuFindAdapter(),
                new Adapter\PhpAdapter()
            ),
            function (Adapter\AdapterInterface $adapter)  {
                return $adapter->isSupported();
            }
        );
    }

   /**
     * Searching in multiple locations with sub directories involves
     * AppendIterator which does an unnecessary rewind which leaves
     * FilterIterator with inner FilesystemIterator in an invalid state.
     *
     * @see https://bugs.php.net/bug.php?id=49104
     */
    public function testMultipleLocationsWithSubDirectories()
    {
        $locations = array(
            __DIR__.'/Fixtures/one',
            self::$tmpDir.DIRECTORY_SEPARATOR.'toto',
        );

        $finder = new Finder();
        $finder->in($locations)->depth('< 10')->name('*.neon');

        $expected = array(
            __DIR__.'/Fixtures/one'.DIRECTORY_SEPARATOR.'b'.DIRECTORY_SEPARATOR.'c.neon',
            __DIR__.'/Fixtures/one'.DIRECTORY_SEPARATOR.'b'.DIRECTORY_SEPARATOR.'d.neon',
        );

        $this->assertIterator($expected, $finder);
        $this->assertIteratorInForeach($expected, $finder);
    }

    public function testNonSeekableStream()
    {
        try {
            $i = Finder::create()->in('ftp://ftp.mozilla.org/')->depth(0)->getIterator();
        } catch (\UnexpectedValueException $e) {
            $this->markTestSkipped(sprintf('Unsupported stream "%s".', 'ftp'));
        }

        $contains = array(
            'ftp://ftp.mozilla.org'.DIRECTORY_SEPARATOR.'README',
            'ftp://ftp.mozilla.org'.DIRECTORY_SEPARATOR.'index.html',
            'ftp://ftp.mozilla.org'.DIRECTORY_SEPARATOR.'pub',
        );

        $this->assertIteratorInForeach($contains, $i);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests;

use Symfony\Component\Finder\Expression\Expression;

class ExpressionTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getTypeGuesserData
     */
    public function testTypeGuesser($expr, $type)
    {
        $this->assertEquals($type, Expression::create($expr)->getType());
    }

    /**
     * @dataProvider getCaseSensitiveData
     */
    public function testCaseSensitive($expr, $isCaseSensitive)
    {
        $this->assertEquals($isCaseSensitive, Expression::create($expr)->isCaseSensitive());
    }

    /**
     * @dataProvider getRegexRenderingData
     */
    public function testRegexRendering($expr, $body)
    {
        $this->assertEquals($body, Expression::create($expr)->renderPattern());
    }

    public function getTypeGuesserData()
    {
        return array(
            array('{foo}', Expression::TYPE_REGEX),
            array('/foo/', Expression::TYPE_REGEX),
            array('foo',   Expression::TYPE_GLOB),
            array('foo*',  Expression::TYPE_GLOB),
        );
    }

    public function getCaseSensitiveData()
    {
        return array(
            array('{foo}m', true),
            array('/foo/i', false),
            array('foo*',   true),
        );
    }

    public function getRegexRenderingData()
    {
        return array(
            array('{foo}m', 'foo'),
            array('/foo/i', 'foo'),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests;

use Symfony\Component\Finder\Expression\Expression;

class RegexTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getHasFlagsData
     */
    public function testHasFlags($regex, $start, $end)
    {
        $expr = new Expression($regex);

        $this->assertEquals($start, $expr->getRegex()->hasStartFlag());
        $this->assertEquals($end,   $expr->getRegex()->hasEndFlag());
    }

    /**
     * @dataProvider getHasJokersData
     */
    public function testHasJokers($regex, $start, $end)
    {
        $expr = new Expression($regex);

        $this->assertEquals($start, $expr->getRegex()->hasStartJoker());
        $this->assertEquals($end,   $expr->getRegex()->hasEndJoker());
    }

    /**
     * @dataProvider getSetFlagsData
     */
    public function testSetFlags($regex, $start, $end, $expected)
    {
        $expr = new Expression($regex);
        $expr->getRegex()->setStartFlag($start)->setEndFlag($end);

        $this->assertEquals($expected, $expr->render());
    }

    /**
     * @dataProvider getSetJokersData
     */
    public function testSetJokers($regex, $start, $end, $expected)
    {
        $expr = new Expression($regex);
        $expr->getRegex()->setStartJoker($start)->setEndJoker($end);

        $this->assertEquals($expected, $expr->render());
    }

    public function testOptions()
    {
        $expr = new Expression('~abc~is');
        $expr->getRegex()->removeOption('i')->addOption('m');

        $this->assertEquals('~abc~sm', $expr->render());
    }

    public function testMixFlagsAndJokers()
    {
        $expr = new Expression('~^.*abc.*$~is');

        $expr->getRegex()->setStartFlag(false)->setEndFlag(false)->setStartJoker(false)->setEndJoker(false);
        $this->assertEquals('~abc~is', $expr->render());

        $expr->getRegex()->setStartFlag(true)->setEndFlag(true)->setStartJoker(true)->setEndJoker(true);
        $this->assertEquals('~^.*abc.*$~is', $expr->render());
    }

    /**
     * @dataProvider getReplaceJokersTestData
     */
    public function testReplaceJokers($regex, $expected)
    {
        $expr = new Expression($regex);
        $expr = $expr->getRegex()->replaceJokers('@');

        $this->assertEquals($expected, $expr->renderPattern());
    }

    public function getHasFlagsData()
    {
        return array(
            array('~^abc~', true, false),
            array('~abc$~', false, true),
            array('~abc~', false, false),
            array('~^abc$~', true, true),
            array('~^abc\\$~', true, false),
        );
    }

    public function getHasJokersData()
    {
        return array(
            array('~.*abc~', true, false),
            array('~abc.*~', false, true),
            array('~abc~', false, false),
            array('~.*abc.*~', true, true),
            array('~.*abc\\.*~', true, false),
        );
    }

    public function getSetFlagsData()
    {
        return array(
            array('~abc~', true, false, '~^abc~'),
            array('~abc~', false, true, '~abc$~'),
            array('~abc~', false, false, '~abc~'),
            array('~abc~', true, true, '~^abc$~'),
        );
    }

    public function getSetJokersData()
    {
        return array(
            array('~abc~', true, false, '~.*abc~'),
            array('~abc~', false, true, '~abc.*~'),
            array('~abc~', false, false, '~abc~'),
            array('~abc~', true, true, '~.*abc.*~'),
        );
    }

    public function getReplaceJokersTestData()
    {
        return array(
            array('~.abc~', '@abc'),
            array('~\\.abc~', '\\.abc'),
            array('~\\\\.abc~', '\\\\@abc'),
            array('~\\\\\\.abc~', '\\\\\\.abc'),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests;

use Symfony\Component\Finder\Expression\Expression;

class GlobTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getToRegexData
     */
    public function testGlobToRegex($glob, $match, $noMatch)
    {
        foreach ($match as $m) {
            $this->assertRegExp(Expression::create($glob)->getRegex()->render(), $m, '::toRegex() converts a glob to a regexp');
        }

        foreach ($noMatch as $m) {
            $this->assertNotRegExp(Expression::create($glob)->getRegex()->render(), $m, '::toRegex() converts a glob to a regexp');
        }
    }

    public function getToRegexData()
    {
        return array(
            array('', array(''), array('f', '/')),
            array('*', array('foo'), array('foo/', '/foo')),
            array('foo.*', array('foo.php', 'foo.a', 'foo.'), array('fooo.php', 'foo.php/foo')),
            array('fo?', array('foo', 'fot'), array('fooo', 'ffoo', 'fo/')),
            array('fo{o,t}', array('foo', 'fot'), array('fob', 'fo/')),
            array('foo(bar|foo)', array('foo(bar|foo)'), array('foobar', 'foofoo')),
            array('foo,bar', array('foo,bar'), array('foo', 'bar')),
            array('fo{o,\\,}', array('foo', 'fo,'), array()),
            array('fo{o,\\\\}', array('foo', 'fo\\'), array()),
            array('/foo', array('/foo'), array('foo')),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

use Symfony\Component\Finder\Iterator\FileTypeFilterIterator;

class FileTypeFilterIteratorTest extends RealIteratorTestCase
{
    /**
     * @dataProvider getAcceptData
     */
    public function testAccept($mode, $expected)
    {
        $inner = new InnerTypeIterator(self::$files);

        $iterator = new FileTypeFilterIterator($inner, $mode);

        $this->assertIterator($expected, $iterator);
    }

    public function getAcceptData()
    {
        $onlyFiles = array(
            'test.py',
            'foo/bar.tmp',
            'test.php',
            '.bar',
            '.foo/.bar',
            '.foo/bar',
            'foo bar',
        );

        $onlyDirectories = array(
            '.git',
            'foo',
            'toto',
            '.foo',
        );

        return array(
            array(FileTypeFilterIterator::ONLY_FILES, $this->toAbsolute($onlyFiles)),
            array(FileTypeFilterIterator::ONLY_DIRECTORIES, $this->toAbsolute($onlyDirectories)),
        );
    }
}

class InnerTypeIterator extends \ArrayIterator
{
   public function current()
    {
        return new \SplFileInfo(parent::current());
    }

    public function isFile()
    {
        return $this->current()->isFile();
    }

    public function isDir()
    {
        return $this->current()->isDir();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

use Symfony\Component\Finder\Iterator\FilenameFilterIterator;

class FilenameFilterIteratorTest extends IteratorTestCase
{
    /**
     * @dataProvider getAcceptData
     */
    public function testAccept($matchPatterns, $noMatchPatterns, $expected)
    {
        $inner = new InnerNameIterator(array('test.php', 'test.py', 'foo.php'));

        $iterator = new FilenameFilterIterator($inner, $matchPatterns, $noMatchPatterns);

        $this->assertIterator($expected, $iterator);
    }

    public function getAcceptData()
    {
        return array(
            array(array('test.*'), array(), array('test.php', 'test.py')),
            array(array(), array('test.*'), array('foo.php')),
            array(array('*.php'), array('test.*'), array('foo.php')),
            array(array('*.php', '*.py'), array('foo.*'), array('test.php', 'test.py')),
            array(array('/\.php$/'), array(), array('test.php', 'foo.php')),
            array(array(), array('/\.php$/'), array('test.py')),
        );
    }
}

class InnerNameIterator extends \ArrayIterator
{
    public function current()
    {
        return new \SplFileInfo(parent::current());
    }

    public function getFilename()
    {
        return parent::current();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator;

class DepthRangeFilterIteratorTest extends RealIteratorTestCase
{
    /**
     * @dataProvider getAcceptData
     */
    public function testAccept($minDepth, $maxDepth, $expected)
    {
        $inner = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->toAbsolute(), \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST);

        $iterator = new DepthRangeFilterIterator($inner, $minDepth, $maxDepth);

        $actual = array_keys(iterator_to_array($iterator));
        sort($expected);
        sort($actual);
        $this->assertEquals($expected, $actual);
    }

    public function getAcceptData()
    {
        $lessThan1 = array(
            '.git',
            'test.py',
            'foo',
            'test.php',
            'toto',
            '.foo',
            '.bar',
            'foo bar',
        );

        $lessThanOrEqualTo1 = array(
            '.git',
            'test.py',
            'foo',
            'foo/bar.tmp',
            'test.php',
            'toto',
            '.foo',
            '.foo/.bar',
            '.bar',
            'foo bar',
            '.foo/bar',
        );

        $graterThanOrEqualTo1 = array(
            'foo/bar.tmp',
            '.foo/.bar',
            '.foo/bar',
        );

        $equalTo1 = array(
            'foo/bar.tmp',
            '.foo/.bar',
            '.foo/bar',
        );

        return array(
            array(0, 0, $this->toAbsolute($lessThan1)),
            array(0, 1, $this->toAbsolute($lessThanOrEqualTo1)),
            array(2, PHP_INT_MAX, array()),
            array(1, PHP_INT_MAX, $this->toAbsolute($graterThanOrEqualTo1)),
            array(1, 1, $this->toAbsolute($equalTo1)),
        );
    }

}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

use Symfony\Component\Finder\Iterator\DateRangeFilterIterator;
use Symfony\Component\Finder\Comparator\DateComparator;

class DateRangeFilterIteratorTest extends RealIteratorTestCase
{
    /**
     * @dataProvider getAcceptData
     */
    public function testAccept($size, $expected)
    {
        $inner = new Iterator(self::$files);

        $iterator = new DateRangeFilterIterator($inner, $size);

        $this->assertIterator($expected, $iterator);
    }

    public function getAcceptData()
    {
        $since20YearsAgo = array(
            '.git',
            'test.py',
            'foo',
            'foo/bar.tmp',
            'test.php',
            'toto',
            '.bar',
            '.foo',
            '.foo/.bar',
            'foo bar',
            '.foo/bar',
        );

        $since2MonthsAgo = array(
            '.git',
            'test.py',
            'foo',
            'toto',
            '.bar',
            '.foo',
            '.foo/.bar',
            'foo bar',
            '.foo/bar',
        );

        $untilLastMonth = array(
            '.git',
            'foo',
            'foo/bar.tmp',
            'test.php',
            'toto',
            '.foo',
        );

        return array(
            array(array(new DateComparator('since 20 years ago')), $this->toAbsolute($since20YearsAgo)),
            array(array(new DateComparator('since 2 months ago')), $this->toAbsolute($since2MonthsAgo)),
            array(array(new DateComparator('until last month')), $this->toAbsolute($untilLastMonth)),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

use Symfony\Component\Finder\Iterator\FilePathsIterator;

class FilePathsIteratorTest extends RealIteratorTestCase
{
    /**
     * @dataProvider getSubPathData
     */
    public function testSubPath($baseDir, array $paths, array $subPaths, array $subPathnames)
    {
        $iterator = new FilePathsIterator($paths, $baseDir);

        foreach ($iterator as $index => $file) {
            $this->assertEquals($paths[$index], $file->getPathname());
            $this->assertEquals($subPaths[$index], $iterator->getSubPath());
            $this->assertEquals($subPathnames[$index], $iterator->getSubPathname());
        }
    }

    public function getSubPathData()
    {
        $tmpDir = sys_get_temp_dir().'/symfony2_finder';

        return array(
            array(
                $tmpDir,
                array( // paths
                    $tmpDir.DIRECTORY_SEPARATOR.'.git' => $tmpDir.DIRECTORY_SEPARATOR.'.git',
                    $tmpDir.DIRECTORY_SEPARATOR.'test.py' => $tmpDir.DIRECTORY_SEPARATOR.'test.py',
                    $tmpDir.DIRECTORY_SEPARATOR.'foo' => $tmpDir.DIRECTORY_SEPARATOR.'foo',
                    $tmpDir.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'bar.tmp' => $tmpDir.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'bar.tmp',
                    $tmpDir.DIRECTORY_SEPARATOR.'test.php' => $tmpDir.DIRECTORY_SEPARATOR.'test.php',
                    $tmpDir.DIRECTORY_SEPARATOR.'toto' => $tmpDir.DIRECTORY_SEPARATOR.'toto'
                ),
                array( // subPaths
                    $tmpDir.DIRECTORY_SEPARATOR.'.git' => '',
                    $tmpDir.DIRECTORY_SEPARATOR.'test.py' => '',
                    $tmpDir.DIRECTORY_SEPARATOR.'foo' => '',
                    $tmpDir.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'bar.tmp' => 'foo',
                    $tmpDir.DIRECTORY_SEPARATOR.'test.php' => '',
                    $tmpDir.DIRECTORY_SEPARATOR.'toto' => ''
                ),
                array( // subPathnames
                    $tmpDir.DIRECTORY_SEPARATOR.'.git' => '.git',
                    $tmpDir.DIRECTORY_SEPARATOR.'test.py' => 'test.py',
                    $tmpDir.DIRECTORY_SEPARATOR.'foo' => 'foo',
                    $tmpDir.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'bar.tmp' => 'foo'.DIRECTORY_SEPARATOR.'bar.tmp',
                    $tmpDir.DIRECTORY_SEPARATOR.'test.php' => 'test.php',
                    $tmpDir.DIRECTORY_SEPARATOR.'toto' => 'toto'
                ),
            ),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

use Symfony\Component\Finder\Iterator\PathFilterIterator;

class PathFilterIteratorTest extends IteratorTestCase
{

    /**
     * @dataProvider getTestFilterData
     */
    public function testFilter(\Iterator $inner, array $matchPatterns, array $noMatchPatterns, array $resultArray)
    {
        $iterator = new PathFilterIterator($inner, $matchPatterns, $noMatchPatterns);
        $this->assertIterator($resultArray, $iterator);
    }

    public function getTestFilterData()
    {
        $inner = new MockFileListIterator();

        //PATH:   A/B/C/abc.dat
        $inner[] = new MockSplFileInfo(array(
            'name'              => 'abc.dat',
            'relativePathname'  => 'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat',
        ));

        //PATH:   A/B/ab.dat
        $inner[] = new MockSplFileInfo(array(
            'name'              => 'ab.dat',
            'relativePathname'  => 'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'ab.dat',
        ));

        //PATH:   A/a.dat
        $inner[] = new MockSplFileInfo(array(
            'name'              => 'a.dat',
            'relativePathname'  => 'A'.DIRECTORY_SEPARATOR.'a.dat',
        ));

        //PATH:   copy/A/B/C/abc.dat.copy
        $inner[] = new MockSplFileInfo(array(
            'name'              => 'abc.dat.copy',
            'relativePathname'  => 'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'C'.DIRECTORY_SEPARATOR.'abc.dat',
        ));

        //PATH:   copy/A/B/ab.dat.copy
        $inner[] = new MockSplFileInfo(array(
            'name'              => 'ab.dat.copy',
            'relativePathname'  => 'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'B'.DIRECTORY_SEPARATOR.'ab.dat',
        ));

        //PATH:   copy/A/a.dat.copy
        $inner[] = new MockSplFileInfo(array(
            'name'              => 'a.dat.copy',
            'relativePathname'  => 'copy'.DIRECTORY_SEPARATOR.'A'.DIRECTORY_SEPARATOR.'a.dat',
        ));

        return array(
            array($inner, array('/^A/'),       array(), array('abc.dat', 'ab.dat', 'a.dat')),
            array($inner, array('/^A\/B/'),    array(), array('abc.dat', 'ab.dat')),
            array($inner, array('/^A\/B\/C/'), array(), array('abc.dat')),
            array($inner, array('/A\/B\/C/'),  array(), array('abc.dat', 'abc.dat.copy')),

            array($inner, array('A'),      array(), array('abc.dat', 'ab.dat', 'a.dat', 'abc.dat.copy', 'ab.dat.copy', 'a.dat.copy')),
            array($inner, array('A/B'),    array(), array('abc.dat', 'ab.dat', 'abc.dat.copy', 'ab.dat.copy')),
            array($inner, array('A/B/C'),  array(), array('abc.dat', 'abc.dat.copy')),

            array($inner, array('copy/A'),      array(), array('abc.dat.copy', 'ab.dat.copy', 'a.dat.copy')),
            array($inner, array('copy/A/B'),    array(), array('abc.dat.copy', 'ab.dat.copy')),
            array($inner, array('copy/A/B/C'),  array(), array('abc.dat.copy')),

        );
    }

}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

use Symfony\Component\Finder\Iterator\MultiplePcreFilterIterator;

class MultiplePcreFilterIteratorTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getIsRegexFixtures
     */
    public function testIsRegex($string, $isRegex, $message)
    {
        $testIterator = new TestMultiplePcreFilterIterator();
        $this->assertEquals($isRegex, $testIterator->isRegex($string), $message);
    }

    public function getIsRegexFixtures()
    {
        return array(
            array('foo', false, 'string'),
            array(' foo ', false, '" " is not a valid delimiter'),
            array('\\foo\\', false, '"\\" is not a valid delimiter'),
            array('afooa', false, '"a" is not a valid delimiter'),
            array('//', false, 'the pattern should contain at least 1 character'),
            array('/a/', true, 'valid regex'),
            array('/foo/', true, 'valid regex'),
            array('/foo/i', true, 'valid regex with a single modifier'),
            array('/foo/imsxu', true, 'valid regex with multiple modifiers'),
            array('#foo#', true, '"#" is a valid delimiter'),
            array('{foo}', true, '"{,}" is a valid delimiter pair'),
            array('*foo.*', false, '"*" is not considered as a valid delimiter'),
            array('?foo.?', false, '"?" is not considered as a valid delimiter'),
        );
    }
}

class TestMultiplePcreFilterIterator extends MultiplePcreFilterIterator
{
    public function __construct()
    {
    }

    public function accept()
    {
        throw new \BadFunctionCallException('Not implemented');
    }

    public function isRegex($str)
    {
        return parent::isRegex($str);
    }

    public function toRegex($str)
    {
        throw new \BadFunctionCallException('Not implemented');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

abstract class RealIteratorTestCase extends IteratorTestCase
{

    protected static $tmpDir;
    protected static $files;

    public static function setUpBeforeClass()
    {
        self::$tmpDir = realpath(sys_get_temp_dir()).DIRECTORY_SEPARATOR.'symfony2_finder';

        self::$files = array(
            '.git/',
            '.foo/',
            '.foo/.bar',
            '.foo/bar',
            '.bar',
            'test.py',
            'foo/',
            'foo/bar.tmp',
            'test.php',
            'toto/',
            'foo bar'
        );

        self::$files = self::toAbsolute(self::$files);

        if (is_dir(self::$tmpDir)) {
            self::tearDownAfterClass();
        } else {
            mkdir(self::$tmpDir);
        }

        foreach (self::$files as $file) {
            if (DIRECTORY_SEPARATOR === $file[strlen($file) - 1]) {
                mkdir($file);
            } else {
                touch($file);
            }
        }

        file_put_contents(self::toAbsolute('test.php'), str_repeat(' ', 800));
        file_put_contents(self::toAbsolute('test.py'), str_repeat(' ', 2000));

        touch(self::toAbsolute('foo/bar.tmp'), strtotime('2005-10-15'));
        touch(self::toAbsolute('test.php'), strtotime('2005-10-15'));
    }

    public static function tearDownAfterClass()
    {
        foreach (array_reverse(self::$files) as $file) {
            if (DIRECTORY_SEPARATOR === $file[strlen($file) - 1]) {
                @rmdir($file);
            } else {
                @unlink($file);
            }
        }
    }

    protected static function toAbsolute($files = null)
    {
        /*
         * Without the call to setUpBeforeClass() property can be null.
         */
        if (!self::$tmpDir) {
            self::$tmpDir = realpath(sys_get_temp_dir()).DIRECTORY_SEPARATOR.'symfony2_finder';
        }

        if (is_array($files)) {
            $f = array();
            foreach ($files as $file) {
                $f[] = self::$tmpDir.DIRECTORY_SEPARATOR.str_replace('/', DIRECTORY_SEPARATOR, $file);
            }

            return $f;
        }

        if (is_string($files)) {
            return self::$tmpDir.DIRECTORY_SEPARATOR.str_replace('/', DIRECTORY_SEPARATOR, $files);
        }

        return self::$tmpDir;
    }

    protected static function toAbsoluteFixtures($files)
    {
        $f = array();
        foreach ($files as $file) {
            $f[] = realpath(__DIR__.DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.$file);
        }

        return $f;
    }

}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator;
use Symfony\Component\Finder\Comparator\NumberComparator;

class SizeRangeFilterIteratorTest extends RealIteratorTestCase
{
    /**
     * @dataProvider getAcceptData
     */
    public function testAccept($size, $expected)
    {
        $inner = new InnerSizeIterator(self::$files);

        $iterator = new SizeRangeFilterIterator($inner, $size);

        $this->assertIterator($expected, $iterator);
    }

    public function getAcceptData()
    {
        $lessThan1KGreaterThan05K = array(
            '.foo',
            '.git',
            'foo',
            'test.php',
            'toto',
        );

        return array(
            array(array(new NumberComparator('< 1K'), new NumberComparator('> 0.5K')), $this->toAbsolute($lessThan1KGreaterThan05K)),
        );
    }
}

class InnerSizeIterator extends \ArrayIterator
{
   public function current()
    {
        return new \SplFileInfo(parent::current());
    }

    public function getFilename()
    {
        return parent::current();
    }

    public function isFile()
    {
        return $this->current()->isFile();
    }

    public function getSize()
    {
        return $this->current()->getSize();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

class MockFileListIterator extends \ArrayIterator
{
    public function __construct(array $filesArray = array())
    {
        $files = array_map(function($file){ return new MockSplFileInfo($file); }, $filesArray);
        parent::__construct($files);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

use Symfony\Component\Finder\Iterator\CustomFilterIterator;

class CustomFilterIteratorTest extends IteratorTestCase
{
    /**
     * @expectedException \InvalidArgumentException
     */
    public function testWithInvalidFilter()
    {
        new CustomFilterIterator(new Iterator(), array('foo'));
    }

    /**
     * @dataProvider getAcceptData
     */
    public function testAccept($filters, $expected)
    {
        $inner = new Iterator(array('test.php', 'test.py', 'foo.php'));

        $iterator = new CustomFilterIterator($inner, $filters);

        $this->assertIterator($expected, $iterator);
    }

    public function getAcceptData()
    {
        return array(
            array(array(function (\SplFileInfo $fileinfo) { return false; }), array()),
            array(array(function (\SplFileInfo $fileinfo) { return preg_match('/^test/', $fileinfo) > 0; }), array('test.php', 'test.py')),
            array(array('is_dir'), array()),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator;
use Symfony\Component\Finder\Iterator\RecursiveDirectoryIterator;

class ExcludeDirectoryFilterIteratorTest extends RealIteratorTestCase
{
    /**
     * @dataProvider getAcceptData
     */
    public function testAccept($directories, $expected)
    {
        $inner = new \RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->toAbsolute(), \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST);

        $iterator = new ExcludeDirectoryFilterIterator($inner, $directories);

        $this->assertIterator($expected, $iterator);
    }

    public function getAcceptData()
    {
        $foo = array(
            '.bar',
            '.foo',
            '.foo/.bar',
            '.foo/bar',
            '.git',
            'test.py',
            'test.php',
            'toto',
            'foo bar'
        );

        $fo = array(
            '.bar',
            '.foo',
            '.foo/.bar',
            '.foo/bar',
            '.git',
            'test.py',
            'foo',
            'foo/bar.tmp',
            'test.php',
            'toto',
            'foo bar'
        );

        return array(
            array(array('foo'), $this->toAbsolute($foo)),
            array(array('fo'), $this->toAbsolute($fo)),
        );
    }

}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

use Symfony\Component\Finder\Iterator\SortableIterator;

class SortableIteratorTest extends RealIteratorTestCase
{
    public function testConstructor()
    {
        try {
            new SortableIterator(new Iterator(array()), 'foobar');
            $this->fail('__construct() throws an \InvalidArgumentException exception if the mode is not valid');
        } catch (\Exception $e) {
            $this->assertInstanceOf('InvalidArgumentException', $e, '__construct() throws an \InvalidArgumentException exception if the mode is not valid');
        }
    }

    /**
     * @dataProvider getAcceptData
     */
    public function testAccept($mode, $expected)
    {
        $inner = new Iterator(self::$files);

        $iterator = new SortableIterator($inner, $mode);

        $this->assertOrderedIterator($expected, $iterator);
    }

    public function getAcceptData()
    {

        $sortByName = array(
            '.bar',
            '.foo',
            '.foo/.bar',
            '.foo/bar',
            '.git',
            'foo',
            'foo bar',
            'foo/bar.tmp',
            'test.php',
            'test.py',
            'toto',
        );

        $sortByType = array(
            '.foo',
            '.git',
            'foo',
            'toto',
            '.bar',
            '.foo/.bar',
            '.foo/bar',
            'foo bar',
            'foo/bar.tmp',
            'test.php',
            'test.py',
        );

        $customComparison = array(
            '.bar',
            '.foo',
            '.foo/.bar',
            '.foo/bar',
            '.git',
            'foo',
            'foo bar',
            'foo/bar.tmp',
            'test.php',
            'test.py',
            'toto',
        );

        return array(
            array(SortableIterator::SORT_BY_NAME, $this->toAbsolute($sortByName)),
            array(SortableIterator::SORT_BY_TYPE, $this->toAbsolute($sortByType)),
            array(function (\SplFileInfo $a, \SplFileInfo $b) { return strcmp($a->getRealpath(), $b->getRealpath()); }, $this->toAbsolute($customComparison)),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

class Iterator implements \Iterator
{
    protected $values = array();

    public function __construct(array $values = array())
    {
        foreach ($values as $value) {
            $this->attach(new \SplFileInfo($value));
        }
        $this->rewind();
    }

    public function attach(\SplFileInfo $fileinfo)
    {
        $this->values[] = $fileinfo;
    }

    public function rewind()
    {
        reset($this->values);
    }

    public function valid()
    {
        return false !== $this->current();
    }

    public function next()
    {
        next($this->values);
    }

    public function current()
    {
        return current($this->values);
    }

    public function key()
    {
        return key($this->values);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

class MockSplFileInfo extends \SplFileInfo
{
    const   TYPE_DIRECTORY = 1;
    const   TYPE_FILE      = 2;
    const   TYPE_UNKNOWN   = 3;

    private $contents         = null;
    private $mode             = null;
    private $type             = null;
    private $relativePath     = null;
    private $relativePathname = null;

    public function __construct($param)
    {
        if (is_string($param)) {
            parent::__construct($param);
        } elseif (is_array($param)) {
            $defaults = array(
              'name'             => 'file.txt',
              'contents'         => null,
              'mode'             => null,
              'type'             => null,
              'relativePath'     => null,
              'relativePathname' => null,
            );
            $defaults = array_merge($defaults, $param);
            parent::__construct($defaults['name']);
            $this->setContents($defaults['contents']);
            $this->setMode($defaults['mode']);
            $this->setType($defaults['type']);
            $this->setRelativePath($defaults['relativePath']);
            $this->setRelativePathname($defaults['relativePathname']);
        } else {
            throw new \RuntimeException(sprintf('Incorrect parameter "%s"', $param));
        }
    }

    public function isFile()
    {
        if ($this->type === null) {
            return preg_match('/file/', $this->getFilename());
        };

        return self::TYPE_FILE === $this->type;
    }

    public function isDir()
    {
        if ($this->type === null) {
            return preg_match('/directory/', $this->getFilename());
        }

        return self::TYPE_DIRECTORY === $this->type;
    }

    public function isReadable()
    {
        if ($this->mode === null) {
            return preg_match('/r\+/', $this->getFilename());
        }

        return preg_match('/r\+/', $this->mode);
    }

    public function getContents()
    {
        return $this->contents;
    }

    public function setContents($contents)
    {
        $this->contents = $contents;
    }

    public function setMode($mode)
    {
        $this->mode = $mode;
    }

    public function setType($type)
    {
        if (is_string($type)) {
            switch ($type) {
                case 'directory':
                    $this->type = self::TYPE_DIRECTORY;
                case 'd':
                    $this->type = self::TYPE_DIRECTORY;
                    break;
                case 'file':
                    $this->type = self::TYPE_FILE;
                case 'f':
                    $this->type = self::TYPE_FILE;
                    break;
                default:
                    $this->type = self::TYPE_UNKNOWN;
            }
        } else {
            $this->type = $type;
        }
    }

    public function setRelativePath($relativePath)
    {
        $this->relativePath = $relativePath;
    }

    public function setRelativePathname($relativePathname)
    {
        $this->relativePathname = $relativePathname;
    }

    public function getRelativePath()
    {
        return $this->relativePath;
    }

    public function getRelativePathname()
    {
        return $this->relativePathname;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

use Symfony\Component\Finder\Iterator\FilecontentFilterIterator;
use Symfony\Component\Finder\Tests\Iterator\MockSplFileInfo;
use Symfony\Component\Finder\Tests\Iterator\MockFileListIterator;

class FilecontentFilterIteratorTest extends IteratorTestCase
{

    public function testAccept()
    {
        $inner = new MockFileListIterator(array('test.txt'));
        $iterator = new FilecontentFilterIterator($inner, array(), array());
        $this->assertIterator(array('test.txt'), $iterator);
    }

    public function testDirectory()
    {
        $inner = new MockFileListIterator(array('directory'));
        $iterator = new FilecontentFilterIterator($inner, array('directory'), array());
        $this->assertIterator(array(), $iterator);
    }

    public function testUnreadableFile()
    {
        $inner = new MockFileListIterator(array('file r-'));
        $iterator = new FilecontentFilterIterator($inner, array('file r-'), array());
        $this->assertIterator(array(), $iterator);
    }

    /**
     * @dataProvider getTestFilterData
     */
    public function testFilter(\Iterator $inner, array $matchPatterns, array $noMatchPatterns, array $resultArray)
    {
        $iterator = new FilecontentFilterIterator($inner, $matchPatterns, $noMatchPatterns);
        $this->assertIterator($resultArray, $iterator);
    }

    public function getTestFilterData()
    {
        $inner = new MockFileListIterator();

        $inner[] = new MockSplFileInfo(array(
            'name'     => 'a.txt',
            'contents' => 'Lorem ipsum...',
            'type'     => 'file',
            'mode'     => 'r+')
        );

        $inner[] = new MockSplFileInfo(array(
            'name'     => 'b.yml',
            'contents' => 'dolor sit...',
            'type'     => 'file',
            'mode'     => 'r+')
        );

        $inner[] = new MockSplFileInfo(array(
            'name'     => 'some/other/dir/third.php',
            'contents' => 'amet...',
            'type'     => 'file',
            'mode'     => 'r+')
        );

        $inner[] = new MockSplFileInfo(array(
            'name'     => 'unreadable-file.txt',
            'contents' => false,
            'type'     => 'file',
            'mode'     => 'r+')
        );

        return array(
            array($inner, array('.'), array(), array('a.txt', 'b.yml', 'some/other/dir/third.php')),
            array($inner, array('ipsum'), array(), array('a.txt')),
            array($inner, array('i', 'amet'), array('Lorem', 'amet'), array('b.yml')),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Finder\Tests\Iterator;

use Symfony\Component\Finder\Iterator\RecursiveDirectoryIterator;

class RecursiveDirectoryIteratorTest extends IteratorTestCase
{
    /**
     * @dataProvider getPaths
     *
     * @param string  $path
     * @param Boolean $seekable
     * @param array   $contains
     * @param string  $message
     */
    public function testRewind($path, $seekable, $contains, $message = null)
    {
        try {
            $i = new RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS);
        } catch (\UnexpectedValueException $e) {
            $this->markTestSkipped(sprintf('Unsupported stream "%s".', $path));
        }

        $i->rewind();

        $this->assertTrue(true, $message);
    }

    /**
     * @dataProvider getPaths
     *
     * @param string  $path
     * @param Boolean $seekable
     * @param array   $contains
     * @param string  $message
     */
    public function testSeek($path, $seekable, $contains, $message = null)
    {
        try {
            $i = new RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS);
        } catch (\UnexpectedValueException $e) {
            $this->markTestSkipped(sprintf('Unsupported stream "%s".', $path));
        }

        $actual = array();

        $i->seek(0);
        $actual[] = $i->getPathname();

        $i->seek(1);
        $actual[] = $i->getPathname();

        $i->seek(2);
        $actual[] = $i->getPathname();

        $this->assertEquals($contains, $actual);
    }

    public function getPaths()
    {
        $data = array();

        // ftp
        $contains = array(
            'ftp://ftp.mozilla.org'.DIRECTORY_SEPARATOR.'README',
            'ftp://ftp.mozilla.org'.DIRECTORY_SEPARATOR.'index.html',
            'ftp://ftp.mozilla.org'.DIRECTORY_SEPARATOR.'pub',
        );
        $data[] = array('ftp://ftp.mozilla.org/', false, $contains);

        return $data;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

abstract class IteratorTestCase extends \PHPUnit_Framework_TestCase
{
    protected function assertIterator($expected, \Traversable $iterator)
    {
        // set iterator_to_array $use_key to false to avoid values merge
        // this made FinderTest::testAppendWithAnArray() failed with GnuFinderAdapter
        $values = array_map(function (\SplFileInfo $fileinfo) { return str_replace('/', DIRECTORY_SEPARATOR, $fileinfo->getPathname()); }, iterator_to_array($iterator, false));

        $expected = array_map(function ($path) { return str_replace('/', DIRECTORY_SEPARATOR, $path); }, $expected);

        sort($values);
        sort($expected);

        $this->assertEquals($expected, array_values($values));
    }

    protected function assertOrderedIterator($expected, \Traversable $iterator)
    {
        $values = array_map(function (\SplFileInfo $fileinfo) { return $fileinfo->getPathname(); }, iterator_to_array($iterator));

        $this->assertEquals($expected, array_values($values));
    }

    /**
     * Same as IteratorTestCase::assertIterator with foreach usage
     *
     * @param array $expected
     * @param \Traversable $iterator
     */
    protected function assertIteratorInForeach($expected, \Traversable $iterator)
    {
        $values = array();
        foreach ($iterator as $file) {
            $this->assertInstanceOf('Symfony\\Component\\Finder\\SplFileInfo', $file);
            $values[] = $file->getPathname();
        }

        sort($values);
        sort($expected);

        $this->assertEquals($expected, array_values($values));
    }

    /**
     * Same as IteratorTestCase::assertOrderedIterator with foreach usage
     *
     * @param array $expected
     * @param \Traversable $iterator
     */
    protected function assertOrderedIteratorInForeach($expected, \Traversable $iterator)
    {
        $values = array();
        foreach ($iterator as $file) {
            $this->assertInstanceOf('Symfony\\Component\\Finder\\SplFileInfo', $file);
            $values[] = $file->getPathname();
        }

        $this->assertEquals($expected, array_values($values));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Tests\Iterator;

/**
 * @author Alex Bogomazov
 */
class FilterIteratorTest extends RealIteratorTestCase
{
    public function testFilterFilesystemIterators()
    {
        $i = new \FilesystemIterator($this->toAbsolute());

        // it is expected that there are test.py test.php in the tmpDir
        $i = $this->getMockForAbstractClass('Symfony\Component\Finder\Iterator\FilterIterator', array($i));
        $i->expects($this->any())
            ->method('accept')
            ->will($this->returnCallback(function () use ($i) {
                return (bool) preg_match('/\.php/', (string) $i->current());
            })
        );

        $c = 0;
        foreach ($i as $item) {
            $c++;
        }

        $this->assertEquals(1, $c);

        $i->rewind();

        $c = 0;
        foreach ($i as $item) {
            $c++;
        }

        // This would fail with \FilterIterator but works with Symfony\Component\Finder\Iterator\FilterIterator
        // see https://bugs.php.net/bug.php?id=49104
        $this->assertEquals(1, $c);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Adapter;

use Symfony\Component\Finder\Iterator;

/**
 * PHP finder engine implementation.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class PhpAdapter extends AbstractAdapter
{
    /**
     * {@inheritdoc}
     */
    public function searchInDirectory($dir)
    {
        $flags = \RecursiveDirectoryIterator::SKIP_DOTS;

        if ($this->followLinks) {
            $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
        }

        $iterator = new \RecursiveIteratorIterator(
            new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs),
            \RecursiveIteratorIterator::SELF_FIRST
        );

        if ($this->minDepth > 0 || $this->maxDepth < PHP_INT_MAX) {
            $iterator = new Iterator\DepthRangeFilterIterator($iterator, $this->minDepth, $this->maxDepth);
        }

        if ($this->mode) {
            $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
        }

        if ($this->exclude) {
            $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
        }

        if ($this->names || $this->notNames) {
            $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
        }

        if ($this->contains || $this->notContains) {
            $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
        }

        if ($this->sizes) {
            $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
        }

        if ($this->dates) {
            $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
        }

        if ($this->filters) {
            $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
        }

        if ($this->sort) {
            $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
            $iterator = $iteratorAggregate->getIterator();
        }

        if ($this->paths || $this->notPaths) {
            $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
        }

        return $iterator;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'php';
    }

    /**
     * {@inheritdoc}
     */
    protected function canBeUsed()
    {
        return true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Adapter;

use Symfony\Component\Finder\Shell\Shell;
use Symfony\Component\Finder\Shell\Command;
use Symfony\Component\Finder\Iterator\SortableIterator;
use Symfony\Component\Finder\Expression\Expression;

/**
 * Shell engine implementation using GNU find command.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class GnuFindAdapter extends AbstractFindAdapter
{
    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'gnu_find';
    }

    /**
     * {@inheritdoc}
     */
    protected function buildFormatSorting(Command $command, $sort)
    {
        switch ($sort) {
            case SortableIterator::SORT_BY_NAME:
                $command->ins('sort')->add('| sort');

                return;
            case SortableIterator::SORT_BY_TYPE:
                $format = '%y';
                break;
            case SortableIterator::SORT_BY_ACCESSED_TIME:
                $format = '%A@';
                break;
            case SortableIterator::SORT_BY_CHANGED_TIME:
                $format = '%C@';
                break;
            case SortableIterator::SORT_BY_MODIFIED_TIME:
                $format = '%T@';
                break;
            default:
                throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
        }

        $command
            ->get('find')
            ->add('-printf')
            ->arg($format.' %h/%f\\n')
            ->add('| sort | cut')
            ->arg('-d ')
            ->arg('-f2-')
        ;
    }

    /**
     * {@inheritdoc}
     */
    protected function canBeUsed()
    {
        return $this->shell->getType() === Shell::TYPE_UNIX && parent::canBeUsed();
    }

    /**
     * {@inheritdoc}
     */
    protected function buildFindCommand(Command $command, $dir)
    {
      return parent::buildFindCommand($command, $dir)->add('-regextype posix-extended');
    }

    /**
     * {@inheritdoc}
     */
    protected function buildContentFiltering(Command $command, array $contains, $not = false)
    {
        foreach ($contains as $contain) {
            $expr = Expression::create($contain);

            // todo: avoid forking process for each $pattern by using multiple -e options
            $command
                ->add('| xargs -I{} -r grep -I')
                ->add($expr->isCaseSensitive() ? null : '-i')
                ->add($not ? '-L' : '-l')
                ->add('-Ee')->arg($expr->renderPattern())
                ->add('{}')
            ;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Adapter;

use Symfony\Component\Finder\Shell\Shell;
use Symfony\Component\Finder\Shell\Command;
use Symfony\Component\Finder\Iterator\SortableIterator;
use Symfony\Component\Finder\Expression\Expression;

/**
 * Shell engine implementation using BSD find command.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class BsdFindAdapter extends AbstractFindAdapter
{
    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'bsd_find';
    }

    /**
     * {@inheritdoc}
     */
    protected function canBeUsed()
    {
        return in_array($this->shell->getType(), array(Shell::TYPE_BSD, Shell::TYPE_DARWIN)) && parent::canBeUsed();
    }

    /**
     * {@inheritdoc}
     */
    protected function buildFormatSorting(Command $command, $sort)
    {
        switch ($sort) {
            case SortableIterator::SORT_BY_NAME:
                $command->ins('sort')->add('| sort');

                return;
            case SortableIterator::SORT_BY_TYPE:
                $format = '%HT';
                break;
            case SortableIterator::SORT_BY_ACCESSED_TIME:
                $format = '%a';
                break;
            case SortableIterator::SORT_BY_CHANGED_TIME:
                $format = '%c';
                break;
            case SortableIterator::SORT_BY_MODIFIED_TIME:
                $format = '%m';
                break;
            default:
                throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
        }

        $command
            ->add('-print0 | xargs -0 stat -f')
            ->arg($format.'%t%N')
            ->add('| sort | cut -f 2');
    }

    /**
     * {@inheritdoc}
     */
    protected function buildFindCommand(Command $command, $dir)
    {
        parent::buildFindCommand($command, $dir)->addAtIndex('-E', 1);

        return $command;
    }

    /**
     * {@inheritdoc}
     */
    protected function buildContentFiltering(Command $command, array $contains, $not = false)
    {
        foreach ($contains as $contain) {
            $expr = Expression::create($contain);

            // todo: avoid forking process for each $pattern by using multiple -e options
            $command
                ->add('| grep -v \'^$\'')
                ->add('| xargs -I{} grep -I')
                ->add($expr->isCaseSensitive() ? null : '-i')
                ->add($not ? '-L' : '-l')
                ->add('-Ee')->arg($expr->renderPattern())
                ->add('{}')
            ;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Adapter;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
interface AdapterInterface
{
    /**
     * @param Boolean $followLinks
     *
     * @return AdapterInterface Current instance
     */
    public function setFollowLinks($followLinks);

    /**
     * @param integer $mode
     *
     * @return AdapterInterface Current instance
     */
    public function setMode($mode);

    /**
     * @param array $exclude
     *
     * @return AdapterInterface Current instance
     */
    public function setExclude(array $exclude);

    /**
     * @param array $depths
     *
     * @return AdapterInterface Current instance
     */
    public function setDepths(array $depths);

    /**
     * @param array $names
     *
     * @return AdapterInterface Current instance
     */
    public function setNames(array $names);

    /**
     * @param array $notNames
     *
     * @return AdapterInterface Current instance
     */
    public function setNotNames(array $notNames);

    /**
     * @param array $contains
     *
     * @return AdapterInterface Current instance
     */
    public function setContains(array $contains);

    /**
     * @param array $notContains
     *
     * @return AdapterInterface Current instance
     */
    public function setNotContains(array $notContains);

    /**
     * @param array $sizes
     *
     * @return AdapterInterface Current instance
     */
    public function setSizes(array $sizes);

    /**
     * @param array $dates
     *
     * @return AdapterInterface Current instance
     */
    public function setDates(array $dates);

    /**
     * @param array $filters
     *
     * @return AdapterInterface Current instance
     */
    public function setFilters(array $filters);

    /**
     * @param \Closure|integer $sort
     *
     * @return AdapterInterface Current instance
     */
    public function setSort($sort);

    /**
     * @param array $paths
     *
     * @return AdapterInterface Current instance
     */
    public function setPath(array $paths);

    /**
     * @param array $notPaths
     *
     * @return AdapterInterface Current instance
     */
    public function setNotPath(array $notPaths);

    /**
     * @param boolean $ignore
     *
     * @return AdapterInterface Current instance
     */
    public function ignoreUnreadableDirs($ignore = true);

    /**
     * @param string $dir
     *
     * @return \Iterator Result iterator
     */
    public function searchInDirectory($dir);

    /**
     * Tests adapter support for current platform.
     *
     * @return Boolean
     */
    public function isSupported();

    /**
     * Returns adapter name.
     *
     * @return string
     */
    public function getName();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Adapter;

/**
 * Interface for finder engine implementations.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
abstract class AbstractAdapter implements AdapterInterface
{
    protected $followLinks = false;
    protected $mode        = 0;
    protected $minDepth    = 0;
    protected $maxDepth    = PHP_INT_MAX;
    protected $exclude     = array();
    protected $names       = array();
    protected $notNames    = array();
    protected $contains    = array();
    protected $notContains = array();
    protected $sizes       = array();
    protected $dates       = array();
    protected $filters     = array();
    protected $sort        = false;
    protected $paths       = array();
    protected $notPaths    = array();
    protected $ignoreUnreadableDirs = false;

    private static $areSupported = array();

    /**
     * {@inheritDoc}
     */
    public function isSupported()
    {
        $name = $this->getName();

        if (!array_key_exists($name, self::$areSupported)) {
            self::$areSupported[$name] = $this->canBeUsed();
        }

        return self::$areSupported[$name];
    }

    /**
     * {@inheritdoc}
     */
    public function setFollowLinks($followLinks)
    {
        $this->followLinks = $followLinks;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setMode($mode)
    {
        $this->mode = $mode;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setDepths(array $depths)
    {
        $this->minDepth = 0;
        $this->maxDepth = PHP_INT_MAX;

        foreach ($depths as $comparator) {
            switch ($comparator->getOperator()) {
                case '>':
                    $this->minDepth = $comparator->getTarget() + 1;
                    break;
                case '>=':
                    $this->minDepth = $comparator->getTarget();
                    break;
                case '<':
                    $this->maxDepth = $comparator->getTarget() - 1;
                    break;
                case '<=':
                    $this->maxDepth = $comparator->getTarget();
                    break;
                default:
                    $this->minDepth = $this->maxDepth = $comparator->getTarget();
            }
        }

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setExclude(array $exclude)
    {
        $this->exclude = $exclude;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setNames(array $names)
    {
        $this->names = $names;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setNotNames(array $notNames)
    {
        $this->notNames = $notNames;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setContains(array $contains)
    {
        $this->contains = $contains;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setNotContains(array $notContains)
    {
        $this->notContains = $notContains;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setSizes(array $sizes)
    {
        $this->sizes = $sizes;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setDates(array $dates)
    {
        $this->dates = $dates;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setFilters(array $filters)
    {
        $this->filters = $filters;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setSort($sort)
    {
        $this->sort = $sort;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setPath(array $paths)
    {
        $this->paths = $paths;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setNotPath(array $notPaths)
    {
        $this->notPaths = $notPaths;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function ignoreUnreadableDirs($ignore = true)
    {
        $this->ignoreUnreadableDirs = (Boolean) $ignore;

        return $this;
    }

    /**
     * Returns whether the adapter is supported in the current environment.
     *
     * This method should be implemented in all adapters. Do not implement
     * isSupported in the adapters as the generic implementation provides a cache
     * layer.
     *
     * @see isSupported
     *
     * @return Boolean Whether the adapter is supported
     */
    abstract protected function canBeUsed();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Finder\Adapter;

use Symfony\Component\Finder\Exception\AccessDeniedException;
use Symfony\Component\Finder\Iterator;
use Symfony\Component\Finder\Shell\Shell;
use Symfony\Component\Finder\Expression\Expression;
use Symfony\Component\Finder\Shell\Command;
use Symfony\Component\Finder\Iterator\SortableIterator;
use Symfony\Component\Finder\Comparator\NumberComparator;
use Symfony\Component\Finder\Comparator\DateComparator;

/**
 * Shell engine implementation using GNU find command.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
abstract class AbstractFindAdapter extends AbstractAdapter
{
    /**
     * @var Shell
     */
    protected $shell;

    /**
     * Constructor.
     */
    public function __construct()
    {
        $this->shell = new Shell();
    }

    /**
     * {@inheritdoc}
     */
    public function searchInDirectory($dir)
    {
        // having "/../" in path make find fail
        $dir = realpath($dir);

        // searching directories containing or not containing strings leads to no result
        if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode && ($this->contains || $this->notContains)) {
            return new Iterator\FilePathsIterator(array(), $dir);
        }

        $command = Command::create();
        $find = $this->buildFindCommand($command, $dir);

        if ($this->followLinks) {
            $find->add('-follow');
        }

        $find->add('-mindepth')->add($this->minDepth + 1);

        if (PHP_INT_MAX !== $this->maxDepth) {
            $find->add('-maxdepth')->add($this->maxDepth + 1);
        }

        if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode) {
            $find->add('-type d');
        } elseif (Iterator\FileTypeFilterIterator::ONLY_FILES === $this->mode) {
            $find->add('-type f');
        }

        $this->buildNamesFiltering($find, $this->names);
        $this->buildNamesFiltering($find, $this->notNames, true);
        $this->buildPathsFiltering($find, $dir, $this->paths);
        $this->buildPathsFiltering($find, $dir, $this->notPaths, true);
        $this->buildSizesFiltering($find, $this->sizes);
        $this->buildDatesFiltering($find, $this->dates);

        $useGrep = $this->shell->testCommand('grep') && $this->shell->testCommand('xargs');
        $useSort = is_int($this->sort) && $this->shell->testCommand('sort') && $this->shell->testCommand('cut');

        if ($useGrep && ($this->contains || $this->notContains)) {
            $grep = $command->ins('grep');
            $this->buildContentFiltering($grep, $this->contains);
            $this->buildContentFiltering($grep, $this->notContains, true);
        }

        if ($useSort) {
            $this->buildSorting($command, $this->sort);
        }

        $command->setErrorHandler(
            $this->ignoreUnreadableDirs
                // If directory is unreadable and finder is set to ignore it, `stderr` is ignored.
                ? function ($stderr) { return; }
                : function ($stderr) { throw new AccessDeniedException($stderr); }
        );

        $paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute());
        $iterator = new Iterator\FilePathsIterator($paths, $dir);

        if ($this->exclude) {
            $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
        }

        if (!$useGrep && ($this->contains || $this->notContains)) {
            $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
        }

        if ($this->filters) {
            $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
        }

        if (!$useSort && $this->sort) {
            $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
            $iterator = $iteratorAggregate->getIterator();
        }

        return $iterator;
    }

    /**
     * {@inheritdoc}
     */
    protected function canBeUsed()
    {
        return $this->shell->testCommand('find');
    }

    /**
     * @param Command $command
     * @param string  $dir
     *
     * @return Command
     */
    protected function buildFindCommand(Command $command, $dir)
    {
        return $command
            ->ins('find')
            ->add('find ')
            ->arg($dir)
            ->add('-noleaf'); // the -noleaf option is required for filesystems that don't follow the '.' and '..' conventions
    }

    /**
     * @param Command  $command
     * @param string[] $names
     * @param Boolean  $not
     */
    private function buildNamesFiltering(Command $command, array $names, $not = false)
    {
        if (0 === count($names)) {
            return;
        }

        $command->add($not ? '-not' : null)->cmd('(');

        foreach ($names as $i => $name) {
            $expr = Expression::create($name);

            // Find does not support expandable globs ("*.{a,b}" syntax).
            if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
                $expr = Expression::create($expr->getGlob()->toRegex(false));
            }

            // Fixes 'not search' and 'full path matching' regex problems.
            // - Jokers '.' are replaced by [^/].
            // - We add '[^/]*' before and after regex (if no ^|$ flags are present).
            if ($expr->isRegex()) {
                $regex = $expr->getRegex();
                $regex->prepend($regex->hasStartFlag() ? '/' : '/[^/]*')
                    ->setStartFlag(false)
                    ->setStartJoker(true)
                    ->replaceJokers('[^/]');
                if (!$regex->hasEndFlag() || $regex->hasEndJoker()) {
                    $regex->setEndJoker(false)->append('[^/]*');
                }
            }

            $command
                ->add($i > 0 ? '-or' : null)
                ->add($expr->isRegex()
                    ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
                    : ($expr->isCaseSensitive() ? '-name' : '-iname')
                )
                ->arg($expr->renderPattern());
        }

        $command->cmd(')');
    }

    /**
     * @param Command  $command
     * @param string   $dir
     * @param string[] $paths
     * @param Boolean  $not
     */
    private function buildPathsFiltering(Command $command, $dir, array $paths, $not = false)
    {
        if (0 === count($paths)) {
            return;
        }

        $command->add($not ? '-not' : null)->cmd('(');

        foreach ($paths as $i => $path) {
            $expr = Expression::create($path);

            // Find does not support expandable globs ("*.{a,b}" syntax).
            if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
                $expr = Expression::create($expr->getGlob()->toRegex(false));
            }

            // Fixes 'not search' regex problems.
            if ($expr->isRegex()) {
                $regex = $expr->getRegex();
                $regex->prepend($regex->hasStartFlag() ? $dir.DIRECTORY_SEPARATOR : '.*')->setEndJoker(!$regex->hasEndFlag());
            } else {
                $expr->prepend('*')->append('*');
            }

            $command
                ->add($i > 0 ? '-or' : null)
                ->add($expr->isRegex()
                    ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
                    : ($expr->isCaseSensitive() ? '-path' : '-ipath')
                )
                ->arg($expr->renderPattern());
        }

        $command->cmd(')');
    }

    /**
     * @param Command            $command
     * @param NumberComparator[] $sizes
     */
    private function buildSizesFiltering(Command $command, array $sizes)
    {
        foreach ($sizes as $i => $size) {
            $command->add($i > 0 ? '-and' : null);

            switch ($size->getOperator()) {
                case '<=':
                    $command->add('-size -'.($size->getTarget() + 1).'c');
                    break;
                case '>=':
                    $command->add('-size +'. ($size->getTarget() - 1).'c');
                    break;
                case '>':
                    $command->add('-size +'.$size->getTarget().'c');
                    break;
                case '!=':
                    $command->add('-size -'.$size->getTarget().'c');
                    $command->add('-size +'.$size->getTarget().'c');
                case '<':
                default:
                    $command->add('-size -'.$size->getTarget().'c');
            }
        }
    }

    /**
     * @param Command          $command
     * @param DateComparator[] $dates
     */
    private function buildDatesFiltering(Command $command, array $dates)
    {
        foreach ($dates as $i => $date) {
            $command->add($i > 0 ? '-and' : null);

            $mins = (int) round((time()-$date->getTarget()) / 60);

            if (0 > $mins) {
                // mtime is in the future
                $command->add(' -mmin -0');
                // we will have no result so we don't need to continue
                return;
            }

            switch ($date->getOperator()) {
                case '<=':
                    $command->add('-mmin +'.($mins - 1));
                    break;
                case '>=':
                    $command->add('-mmin -'.($mins + 1));
                    break;
                case '>':
                    $command->add('-mmin -'.$mins);
                    break;
                case '!=':
                    $command->add('-mmin +'.$mins.' -or -mmin -'.$mins);
                    break;
                case '<':
                default:
                    $command->add('-mmin +'.$mins);
            }
        }
    }

    /**
     * @param Command $command
     * @param string  $sort
     *
     * @throws \InvalidArgumentException
     */
    private function buildSorting(Command $command, $sort)
    {
        $this->buildFormatSorting($command, $sort);
    }

    /**
     * @param Command $command
     * @param string  $sort
     */
    abstract protected function buildFormatSorting(Command $command, $sort);

    /**
     * @param Command $command
     * @param array   $contains
     * @param Boolean $not
     */
    abstract protected function buildContentFiltering(Command $command, array $contains, $not = false);
}
{
    "name": "symfony/stopwatch",
    "type": "library",
    "description": "Symfony Stopwatch Component",
    "keywords": [],
    "homepage": "http://symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "http://symfony.com/contributors"
        }
    ],
    "require": {
        "php": ">=5.3.3"
    },
    "autoload": {
        "psr-0": { "Symfony\\Component\\Stopwatch\\": "" }
    },
    "target-dir": "Symfony/Component/Stopwatch",
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-master": "2.4-dev"
        }
    }
}
Copyright (c) 2004-2013 Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Stopwatch;

/**
 * Stopwatch provides a way to profile code.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Stopwatch
{
    /**
     * @var Section[]
     */
    private $sections;

    /**
     * @var array
     */
    private $activeSections;

    public function __construct()
    {
        $this->sections = $this->activeSections = array('__root__' => new Section('__root__'));
    }

    /**
     * Creates a new section or re-opens an existing section.
     *
     * @param string|null $id The id of the session to re-open, null to create a new one
     *
     * @throws \LogicException When the section to re-open is not reachable
     */
    public function openSection($id = null)
    {
        $current = end($this->activeSections);

        if (null !== $id && null === $current->get($id)) {
            throw new \LogicException(sprintf('The section "%s" has been started at an other level and can not be opened.', $id));
        }

        $this->start('__section__.child', 'section');
        $this->activeSections[] = $current->open($id);
        $this->start('__section__');
    }

    /**
     * Stops the last started section.
     *
     * The id parameter is used to retrieve the events from this section.
     *
     * @see getSectionEvents
     *
     * @param string $id The identifier of the section
     *
     * @throws \LogicException When there's no started section to be stopped
     */
    public function stopSection($id)
    {
        $this->stop('__section__');

        if (1 == count($this->activeSections)) {
            throw new \LogicException('There is no started section to stop.');
        }

        $this->sections[$id] = array_pop($this->activeSections)->setId($id);
        $this->stop('__section__.child');
    }

    /**
     * Starts an event.
     *
     * @param string $name     The event name
     * @param string $category The event category
     *
     * @return StopwatchEvent A StopwatchEvent instance
     */
    public function start($name, $category = null)
    {
        return end($this->activeSections)->startEvent($name, $category);
    }

    /**
     * Checks if the event was started
     *
     * @param string $name The event name
     *
     * @return bool
     */
    public function isStarted($name)
    {
        return end($this->activeSections)->isEventStarted($name);
    }

    /**
     * Stops an event.
     *
     * @param string $name The event name
     *
     * @return StopwatchEvent A StopwatchEvent instance
     */
    public function stop($name)
    {
        return end($this->activeSections)->stopEvent($name);
    }

    /**
     * Stops then restarts an event.
     *
     * @param string $name The event name
     *
     * @return StopwatchEvent A StopwatchEvent instance
     */
    public function lap($name)
    {
        return end($this->activeSections)->stopEvent($name)->start();
    }

    /**
     * Gets all events for a given section.
     *
     * @param string $id A section identifier
     *
     * @return StopwatchEvent[] An array of StopwatchEvent instances
     */
    public function getSectionEvents($id)
    {
        return isset($this->sections[$id]) ? $this->sections[$id]->getEvents() : array();
    }
}


/**
 * @internal This class is for internal usage only
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Section
{
    /**
     * @var StopwatchEvent[]
     */
    private $events = array();

    /**
     * @var null|float
     */
    private $origin;

    /**
     * @var string
     */
    private $id;

    /**
     * @var Section[]
     */
    private $children = array();

    /**
     * Constructor.
     *
     * @param float|null $origin Set the origin of the events in this section, use null to set their origin to their start time
     */
    public function __construct($origin = null)
    {
        $this->origin = is_numeric($origin) ? $origin : null;
    }

    /**
     * Returns the child section.
     *
     * @param string $id The child section identifier
     *
     * @return Section|null The child section or null when none found
     */
    public function get($id)
    {
        foreach ($this->children as $child) {
            if ($id === $child->getId()) {
                return $child;
            }
        }

        return null;
    }

    /**
     * Creates or re-opens a child section.
     *
     * @param string|null $id null to create a new section, the identifier to re-open an existing one.
     *
     * @return Section A child section
     */
    public function open($id)
    {
        if (null === $session = $this->get($id)) {
            $session = $this->children[] = new self(microtime(true) * 1000);
        }

        return $session;
    }

    /**
     * @return string The identifier of the section
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Sets the session identifier.
     *
     * @param string $id The session identifier
     *
     * @return Section The current section
     */
    public function setId($id)
    {
        $this->id = $id;

        return $this;
    }

    /**
     * Starts an event.
     *
     * @param string $name     The event name
     * @param string $category The event category
     *
     * @return StopwatchEvent The event
     */
    public function startEvent($name, $category)
    {
        if (!isset($this->events[$name])) {
            $this->events[$name] = new StopwatchEvent($this->origin ?: microtime(true) * 1000, $category);
        }

        return $this->events[$name]->start();
    }

    /**
     * Checks if the event was started
     *
     * @param string $name The event name
     *
     * @return bool
     */
    public function isEventStarted($name)
    {
        return isset($this->events[$name]) && $this->events[$name]->isStarted();
    }

    /**
     * Stops an event.
     *
     * @param string $name The event name
     *
     * @return StopwatchEvent The event
     *
     * @throws \LogicException When the event has not been started
     */
    public function stopEvent($name)
    {
        if (!isset($this->events[$name])) {
            throw new \LogicException(sprintf('Event "%s" is not started.', $name));
        }

        return $this->events[$name]->stop();
    }

    /**
     * Stops then restarts an event.
     *
     * @param string $name The event name
     *
     * @return StopwatchEvent The event
     *
     * @throws \LogicException When the event has not been started
     */
    public function lap($name)
    {
        return $this->stopEvent($name)->start();
    }

    /**
     * Returns the events from this section.
     *
     * @return StopwatchEvent[] An array of StopwatchEvent instances
     */
    public function getEvents()
    {
        return $this->events;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Stopwatch;

/**
 * Represents an Event managed by Stopwatch.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class StopwatchEvent
{
    /**
     * @var StopwatchPeriod[]
     */
    private $periods = array();

    /**
     * @var float
     */
    private $origin;

    /**
     * @var string
     */
    private $category;

    /**
     * @var float[]
     */
    private $started = array();

    /**
     * Constructor.
     *
     * @param float       $origin   The origin time in milliseconds
     * @param string|null $category The event category or null to use the default
     *
     * @throws \InvalidArgumentException When the raw time is not valid
     */
    public function __construct($origin, $category = null)
    {
        $this->origin = $this->formatTime($origin);
        $this->category = is_string($category) ? $category : 'default';
    }

    /**
     * Gets the category.
     *
     * @return string The category
     */
    public function getCategory()
    {
        return $this->category;
    }

    /**
     * Gets the origin.
     *
     * @return float The origin in milliseconds
     */
    public function getOrigin()
    {
        return $this->origin;
    }

    /**
     * Starts a new event period.
     *
     * @return StopwatchEvent The event
     */
    public function start()
    {
        $this->started[] = $this->getNow();

        return $this;
    }

    /**
     * Stops the last started event period.
     *
     * @throws \LogicException When start wasn't called before stopping
     *
     * @return StopwatchEvent The event
     *
     * @throws \LogicException When stop() is called without a matching call to start()
     */
    public function stop()
    {
        if (!count($this->started)) {
            throw new \LogicException('stop() called but start() has not been called before.');
        }

        $this->periods[] = new StopwatchPeriod(array_pop($this->started), $this->getNow());

        return $this;
    }

    /**
     * Checks if the event was started
     *
     * @return bool
     */
    public function isStarted()
    {
        return !empty($this->started);
    }

    /**
     * Stops the current period and then starts a new one.
     *
     * @return StopwatchEvent The event
     */
    public function lap()
    {
        return $this->stop()->start();
    }

    /**
     * Stops all non already stopped periods.
     */
    public function ensureStopped()
    {
        while (count($this->started)) {
            $this->stop();
        }
    }

    /**
     * Gets all event periods.
     *
     * @return StopwatchPeriod[] An array of StopwatchPeriod instances
     */
    public function getPeriods()
    {
        return $this->periods;
    }

    /**
     * Gets the relative time of the start of the first period.
     *
     * @return integer The time (in milliseconds)
     */
    public function getStartTime()
    {
        return isset($this->periods[0]) ? $this->periods[0]->getStartTime() : 0;
    }

    /**
     * Gets the relative time of the end of the last period.
     *
     * @return integer The time (in milliseconds)
     */
    public function getEndTime()
    {
        return ($count = count($this->periods)) ? $this->periods[$count - 1]->getEndTime() : 0;
    }

    /**
     * Gets the duration of the events (including all periods).
     *
     * @return integer The duration (in milliseconds)
     */
    public function getDuration()
    {
        $total = 0;
        foreach ($this->periods as $period) {
            $total += $period->getDuration();
        }

        return $total;
    }

    /**
     * Gets the max memory usage of all periods.
     *
     * @return integer The memory usage (in bytes)
     */
    public function getMemory()
    {
        $memory = 0;
        foreach ($this->periods as $period) {
            if ($period->getMemory() > $memory) {
                $memory = $period->getMemory();
            }
        }

        return $memory;
    }

    /**
     * Return the current time relative to origin.
     *
     * @return float Time in ms
     */
    protected function getNow()
    {
        return $this->formatTime(microtime(true) * 1000 - $this->origin);
    }

    /**
     * Formats a time.
     *
     * @param integer|float $time A raw time
     *
     * @return float The formatted time
     *
     * @throws \InvalidArgumentException When the raw time is not valid
     */
    private function formatTime($time)
    {
        if (!is_numeric($time)) {
            throw new \InvalidArgumentException('The time must be a numerical value');
        }

        return round($time, 1);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Stopwatch;

/**
 * Represents an Period for an Event.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class StopwatchPeriod
{
    private $start;
    private $end;
    private $memory;

    /**
     * Constructor.
     *
     * @param integer $start The relative time of the start of the period (in milliseconds)
     * @param integer $end   The relative time of the end of the period (in milliseconds)
     */
    public function __construct($start, $end)
    {
        $this->start = (integer) $start;
        $this->end = (integer) $end;
        $this->memory = memory_get_usage(true);
    }

    /**
     * Gets the relative time of the start of the period.
     *
     * @return integer The time (in milliseconds)
     */
    public function getStartTime()
    {
        return $this->start;
    }

    /**
     * Gets the relative time of the end of the period.
     *
     * @return integer The time (in milliseconds)
     */
    public function getEndTime()
    {
        return $this->end;
    }

    /**
     * Gets the time spent in this period.
     *
     * @return integer The period duration (in milliseconds)
     */
    public function getDuration()
    {
        return $this->end - $this->start;
    }

    /**
     * Gets the memory usage.
     *
     * @return integer The memory usage (in bytes)
     */
    public function getMemory()
    {
        return $this->memory;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * Defines the interface for a group sequence provider.
 */
interface GroupSequenceProviderInterface
{
    /**
     * Returns which validation groups should be used for a certain state
     * of the object.
     *
     * @return array An array of validation groups
     */
    public function getGroupSequence();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

use Symfony\Component\Validator\Constraint;

/**
 * Specifies an object able to return the correct ConstraintValidatorInterface
 * instance given a Constraint object.
 */
interface ConstraintValidatorFactoryInterface
{
    /**
     * Given a Constraint, this returns the ConstraintValidatorInterface
     * object that should be used to verify its validity.
     *
     * @param Constraint $constraint The source constraint
     *
     * @return ConstraintValidatorInterface
     */
    public function getInstance(Constraint $constraint);
}
{
    "name": "symfony/validator",
    "type": "library",
    "description": "Symfony Validator Component",
    "keywords": [],
    "homepage": "http://symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "http://symfony.com/contributors"
        }
    ],
    "require": {
        "php": ">=5.3.3",
        "symfony/translation": "~2.0",
        "symfony/property-access": "~2.2"
    },
    "require-dev": {
        "symfony/http-foundation": "~2.1",
        "symfony/intl": "~2.3",
        "symfony/yaml": "~2.0",
        "symfony/config": "~2.2",
        "doctrine/annotations": "~1.0",
        "doctrine/cache": "~1.0"
    },
    "suggest": {
        "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.",
        "doctrine/cache": "For using the default cached annotation reader",
        "symfony/http-foundation": "",
        "symfony/intl": "",
        "symfony/yaml": "",
        "symfony/config": ""
    },
    "autoload": {
        "psr-0": { "Symfony\\Component\\Validator\\": "" }
    },
    "target-dir": "Symfony/Component/Validator",
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-master": "2.4-dev"
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * Stores the validator's state during validation.
 *
 * For example, let's validate the following object graph:
 *
 * <pre>
 * (Person)---($firstName: string)
 *      \
 *   ($address: Address)---($street: string)
 * </pre>
 *
 * We validate the <tt>Person</tt> instance, which becomes the "root" of the
 * validation run (see {@link getRoot}). The state of the context after the
 * first step will be like this:
 *
 * <pre>
 * (Person)---($firstName: string)
 *    ^ \
 *   ($address: Address)---($street: string)
 * </pre>
 *
 * The validator is stopped at the <tt>Person</tt> node, both the root and the
 * value (see {@link getValue}) of the context point to the <tt>Person</tt>
 * instance. The property path is empty at this point (see {@link getPropertyPath}).
 * The metadata of the context is the metadata of the <tt>Person</tt> node
 * (see {@link getMetadata}).
 *
 * After advancing to the property <tt>$firstName</tt> of the <tt>Person</tt>
 * instance, the state of the context looks like this:
 *
 * <pre>
 * (Person)---($firstName: string)
 *      \              ^
 *   ($address: Address)---($street: string)
 * </pre>
 *
 * The validator is stopped at the property <tt>$firstName</tt>. The root still
 * points to the <tt>Person</tt> instance, because this is where the validation
 * started. The property path is now "firstName" and the current value is the
 * value of that property.
 *
 * After advancing to the <tt>$address</tt> property and then to the
 * <tt>$street</tt> property of the <tt>Address</tt> instance, the context state
 * looks like this:
 *
 * <pre>
 * (Person)---($firstName: string)
 *      \
 *   ($address: Address)---($street: string)
 *                               ^
 * </pre>
 *
 * The validator is stopped at the property <tt>$street</tt>. The root still
 * points to the <tt>Person</tt> instance, but the property path is now
 * "address.street" and the validated value is the value of that property.
 *
 * Apart from the root, the property path and the currently validated value,
 * the execution context also knows the metadata of the current node (see
 * {@link getMetadata}) which for example returns a {@link Mapping\PropertyMetadata}
 * or a {@link Mapping\ClassMetadata} object. he context also contains the
 * validation group that is currently being validated (see {@link getGroup}) and
 * the violations that happened up until now (see {@link getViolations}).
 *
 * Apart from reading the execution context, you can also use
 * {@link addViolation} or {@link addViolationAt} to add new violations and
 * {@link validate} or {@link validateValue} to validate values that the
 * validator otherwise would not reach.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
interface ExecutionContextInterface
{
    /**
     * Adds a violation at the current node of the validation graph.
     *
     * @param string       $message       The error message.
     * @param array        $params        The parameters substituted in the error message.
     * @param mixed        $invalidValue  The invalid, validated value.
     * @param integer|null $pluralization The number to use to pluralize of the message.
     * @param integer|null $code          The violation code.
     *
     * @api
     */
    public function addViolation($message, array $params = array(), $invalidValue = null, $pluralization = null, $code = null);

    /**
     * Adds a violation at the validation graph node with the given property
     * path relative to the current property path.
     *
     * @param string       $subPath       The relative property path for the violation.
     * @param string       $message       The error message.
     * @param array        $params        The parameters substituted in the error message.
     * @param mixed        $invalidValue  The invalid, validated value.
     * @param integer|null $pluralization The number to use to pluralize of the message.
     * @param integer|null $code          The violation code.
     *
     * @api
     */
    public function addViolationAt($subPath, $message, array $params = array(), $invalidValue = null, $pluralization = null, $code = null);

    /**
     * Validates the given value within the scope of the current validation.
     *
     * The value may be any value recognized by the used metadata factory
     * (see {@link MetadataFactoryInterface::getMetadata}), or an array or a
     * traversable object of such values.
     *
     * Usually you validate a value that is not the current node of the
     * execution context. For this case, you can pass the {@link $subPath}
     * argument which is appended to the current property path when a violation
     * is created. For example, take the following object graph:
     *
     * <pre>
     * (Person)---($address: Address)---($phoneNumber: PhoneNumber)
     *                     ^
     * </pre>
     *
     * When the execution context stops at the <tt>Person</tt> instance, the
     * property path is "address". When you validate the <tt>PhoneNumber</tt>
     * instance now, pass "phoneNumber" as sub path to correct the property path
     * to "address.phoneNumber":
     *
     * <pre>
     * $context->validate($address->phoneNumber, 'phoneNumber');
     * </pre>
     *
     * Any violations generated during the validation will be added to the
     * violation list that you can access with {@link getViolations}.
     *
     * @param mixed                $value    The value to validate.
     * @param string               $subPath  The path to append to the context's property path.
     * @param null|string|string[] $groups   The groups to validate in. If you don't pass any
     *                                       groups here, the current group of the context
     *                                       will be used.
     * @param Boolean              $traverse Whether to traverse the value if it is an array
     *                                       or an instance of <tt>\Traversable</tt>.
     * @param Boolean              $deep     Whether to traverse the value recursively if
     *                                       it is a collection of collections.
     */
    public function validate($value, $subPath = '', $groups = null, $traverse = false, $deep = false);

    /**
     * Validates a value against a constraint.
     *
     * Use the parameter <tt>$subPath</tt> to adapt the property path for the
     * validated value. For example, take the following object graph:
     *
     * <pre>
     * (Person)---($address: Address)---($street: string)
     *                     ^
     * </pre>
     *
     * When the validator validates the <tt>Address</tt> instance, the
     * property path stored in the execution context is "address". When you
     * manually validate the property <tt>$street</tt> now, pass the sub path
     * "street" to adapt the full property path to "address.street":
     *
     * <pre>
     * $context->validate($address->street, new NotNull(), 'street');
     * </pre>
     *
     * @param mixed                   $value       The value to validate.
     * @param Constraint|Constraint[] $constraints The constraint(s) to validate against.
     * @param string                  $subPath     The path to append to the context's property path.
     * @param null|string|string[]    $groups      The groups to validate in. If you don't pass any
     *                                             groups here, the current group of the context
     *                                             will be used.
     */
    public function validateValue($value, $constraints, $subPath = '', $groups = null);

    /**
     * Returns the violations generated by the validator so far.
     *
     * @return ConstraintViolationListInterface The constraint violation list.
     *
     * @api
     */
    public function getViolations();

    /**
     * Returns the value at which validation was started in the object graph.
     *
     * The validator, when given an object, traverses the properties and
     * related objects and their properties. The root of the validation is the
     * object from which the traversal started.
     *
     * The current value is returned by {@link getValue}.
     *
     * @return mixed The root value of the validation.
     */
    public function getRoot();

    /**
     * Returns the value that the validator is currently validating.
     *
     * If you want to retrieve the object that was originally passed to the
     * validator, use {@link getRoot}.
     *
     * @return mixed The currently validated value.
     */
    public function getValue();

    /**
     * Returns the metadata for the currently validated value.
     *
     * With the core implementation, this method returns a
     * {@link Mapping\ClassMetadata} instance if the current value is an object,
     * a {@link Mapping\PropertyMetadata} instance if the current value is
     * the value of a property and a {@link Mapping\GetterMetadata} instance if
     * the validated value is the result of a getter method.
     *
     * If the validated value is neither of these, for example if the validator
     * has been called with a plain value and constraint, this method returns
     * null.
     *
     * @return MetadataInterface|null The metadata of the currently validated
     *                                value.
     */
    public function getMetadata();

    /**
     * Returns the used metadata factory.
     *
     * @return MetadataFactoryInterface The metadata factory.
     */
    public function getMetadataFactory();

    /**
     * Returns the validation group that is currently being validated.
     *
     * @return string The current validation group.
     */
    public function getGroup();

    /**
     * Returns the class name of the current node.
     *
     * If the metadata of the current node does not implement
     * {@link ClassBasedInterface} or if no metadata is available for the
     * current node, this method returns null.
     *
     * @return string|null The class name or null, if no class name could be found.
     */
    public function getClassName();

    /**
     * Returns the property name of the current node.
     *
     * If the metadata of the current node does not implement
     * {@link PropertyMetadataInterface} or if no metadata is available for the
     * current node, this method returns null.
     *
     * @return string|null The property name or null, if no property name could be found.
     */
    public function getPropertyName();

    /**
     * Returns the property path to the value that the validator is currently
     * validating.
     *
     * For example, take the following object graph:
     *
     * <pre>
     * (Person)---($address: Address)---($street: string)
     * </pre>
     *
     * When the <tt>Person</tt> instance is passed to the validator, the
     * property path is initially empty. When the <tt>$address</tt> property
     * of that person is validated, the property path is "address". When
     * the <tt>$street</tt> property of the related <tt>Address</tt> instance
     * is validated, the property path is "address.street".
     *
     * Properties of objects are prefixed with a dot in the property path.
     * Indices of arrays or objects implementing the {@link \ArrayAccess}
     * interface are enclosed in brackets. For example, if the property in
     * the previous example is <tt>$addresses</tt> and contains an array
     * of <tt>Address</tt> instance, the property path generated for the
     * <tt>$street</tt> property of one of these addresses is for example
     * "addresses[0].street".
     *
     * @param string $subPath Optional. The suffix appended to the current
     *                        property path.
     *
     * @return string The current property path. The result may be an empty
     *                string if the validator is currently validating the
     *                root value of the validation graph.
     */
    public function getPropertyPath($subPath = '');
}
﻿<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Reikšmė turi būti neigiama.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Reikšmė turi būti teigiama.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Šios reikšmės tipas turi būti {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Ši reikšmė turi būti tuščia.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Neteisingas pasirinkimas.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Turite pasirinkti bent {{ limit }} variantą.|Turite pasirinkti bent {{ limit }} variantus.|Turite pasirinkti bent {{ limit }} variantų.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Turite pasirinkti ne daugiau kaip {{ limit }} variantą.|Turite pasirinkti ne daugiau kaip {{ limit }} variantus.|Turite pasirinkti ne daugiau kaip {{ limit }} variantų.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Viena ar daugiau įvestų reikšmių yra netinkamos.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Laukai {{ fields }} yra nenumatyti.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Trūkstami laukai {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Ši reikšmė nėra data.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Ši reikšmė nera data ir laikas.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Ši reikšmė nėra tinkamas el. pašto adresas.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Byla nerasta.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Negalima nuskaityti bylos.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Byla yra per didelė ({{ size }} {{ suffix }}). Maksimalus dydis {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Netinkamas bylos tipas (mime type) ({{ type }}). Galimi bylų tipai {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Reikšmė turi būti {{ limit }} arba mažiau.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Per didelis simbolių skaičius. Turi susidaryti iš {{ limit }} arba mažiau simbolių.|Per didelis simbolių skaičius. Turi susidaryti iš {{ limit }} arba mažiau simbolių.|Per didelis simbolių skaičius. Turi susidaryti iš {{ limit }} arba mažiau simbolių.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Reikšmė turi būti {{ limit }} arba daugiau.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Per mažas simbolių skaičius. Turi susidaryti iš {{ limit }} arba daugiau simbolių.|Per mažas simbolių skaičius. Turi susidaryti iš {{ limit }} arba daugiau simbolių.|Per mažas simbolių skaičius. Turi susidaryti iš {{ limit }} arba daugiau simbolių.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Ši reikšmė negali būti tuščia.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Ši reikšmė negali būti null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Ši reikšmė turi būti null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Netinkama reikšmė.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Ši reikšmė nėra laikas.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Ši reikšmė nėra tinkamas interneto adresas.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Abi reikšmės turi būti identiškos.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Byla yra per didelė. Maksimalus dydis yra {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Byla per didelė.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Byla negali būti įkelta.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Ši reikšmė turi būti skaičius.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This value is not a valid country.</source>
                <target>Ši reikšmė nėra tinkama šalis.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This file is not a valid image.</source>
                <target>Byla nėra paveikslėlis.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This is not a valid IP address.</source>
                <target>Ši reikšmė nėra tinkamas IP adresas.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid language.</source>
                <target>Ši reikšmė nėra tinkama kalba.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid locale.</source>
                <target>Ši reikšmė nėra tinkama lokalė.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Ši reikšmė jau yra naudojama.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Nepavyko nustatyti nuotraukos dydžio.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Nuotraukos plotis per didelis ({{ width }}px). Maksimalus leidžiamas plotis yra {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Nuotraukos plotis per mažas ({{ width }}px). Minimalus leidžiamas plotis yra {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Nuotraukos aukštis per didelis ({{ height }}px). Maksimalus leidžiamas aukštis yra {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Nuotraukos aukštis per mažas ({{ height }}px). Minimalus leidžiamas aukštis yra {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Ši reikšmė turi sutapti su dabartiniu vartotojo slaptažodžiu.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Ši reikšmė turi turėti lygiai {{ limit }} simbolį.|Ši reikšmė turi turėti lygiai {{ limit }} simbolius.|Ši reikšmė turi turėti lygiai {{ limit }} simbolių.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Failas buvo tik dalinai įkeltas.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Nebuvo įkelta jokių failų.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Nėra sukonfiguruoto jokio laikino katalogo php.ini faile.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Nepavyko išsaugoti laikino failo.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>PHP plėtinys sutrukdė failo įkėlimą ir jis nepavyko.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Sąraše turi būti {{ limit }} arba daugiau įrašų.|Sąraše turi būti {{ limit }} arba daugiau įrašų.|Sąraše turi būti {{ limit }} arba daugiau įrašų.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Sąraše turi būti {{ limit }} arba mažiau įrašų.|Sąraše turi būti {{ limit }} arba mažiau įrašų.|Sąraše turi būti {{ limit }} arba mažiau įrašų.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Sąraše turi būti lygiai {{ limit }} įrašas.|Sąraše turi būti lygiai {{ limit }} įrašai.|Sąraše turi būti lygiai {{ limit }} įrašų.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
﻿<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Энэ утга буруу байх ёстой.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Энэ утга үнэн байх ёстой.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Энэ утга  {{ type }} -н төрөл байх ёстой.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Энэ утга хоосон байх ёстой.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Сонгосон утга буруу байна.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Хамгийн багадаа {{ limit }} утга сонгогдсон байх ёстой.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Хамгийн ихдээ {{ limit }} утга сонгогдох боломжтой.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Өгөгдсөн нэг эсвэл нэгээс олон утга буруу байна.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>Талбарууд {{ fields }} зөвшөөрөгдөөгүй байна.</source>
                <target>{{ fields }}.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>{{ fields }} талбарууд дутуу байна.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Энэ утга буруу date төрөл байна .</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Энэ утга буруу цаг төрөл байна.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>И-майл хаяг буруу байна.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Файл олдсонгүй.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Файл уншигдахуйц биш байна.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Файл хэтэрхий том байна ({{ size }} {{ suffix }}). Зөвшөөрөгдөх дээд хэмжээ  {{ limit }} {{ suffix }} байна.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Файлын MIME-төрөл нь буруу байна ({{ type }}). Зөвшөөрөгдөх MIME-төрлүүд {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Энэ утга  {{ limit }} юмуу эсвэл бага байна.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Энэ утга хэтэрхий урт байна. {{ limit }} тэмдэгтийн урттай юмуу эсвэл бага байна.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Энэ утга {{ limit }} юмуу эсвэл их байна.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Энэ утга хэтэрхий богино байна. {{ limit }} тэмдэгт эсвэл их байна.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Энэ утга хоосон байж болохгүй.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Энэ утга null байж болохгүй.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Энэ утга null байна.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Энэ утга буруу байна.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Энэ утга буруу цаг төрөл байна.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Энэ утга буруу URL байна .</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Хоёр утгууд ижил байх ёстой.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Файл хэтэрхий том байна. Зөвшөөрөгдөх дээд хэмжээ нь {{ limit }} {{ suffix }} байна.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Файл хэтэрхий том байна.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Файл upload хийгдсэнгүй.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Энэ утга зөвхөн тоо байна.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This value is not a valid country.</source>
                <target>Энэ утга үнэн бодит улс биш байна.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This file is not a valid image.</source>
                <target>Файл зураг биш байна.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This is not a valid IP address.</source>
                <target>IP хаяг зөв биш байна.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid language.</source>
                <target>Энэ утга үнэн зөв хэл биш байна .</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Verdien skulle ha vore tom/nei</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Verdien skulla ha vore satt/ja.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Verdien må vere av typen {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Verdien skal vere blank.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Verdien du valgte er ikkje gyldig.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Du må velge minst {{ limit }} valg.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Du kan maksimalt gjere {{ limit }} valg.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Ein eller fleire av dei opplyste verdiane er ugyldige.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Felta {{ fields }} var ikkje forventa.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Felta {{ fields }} manglar.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Verdien er ikkje ein gyldig dato.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Verdien er ikkje ein gyldig dato og tid.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Verdien er ikkje ei gyldig e-postadresse.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Fila kunne ikkje finnes.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Fila kan ikkje lesast.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Fila er for stor ({{ size }} {{ suffix }}). Tillatt maksimal størrelse er {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Mime-typen av fila er ugyldig ({{ type }}). Tillatte mime-typar er {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Verdien må vere {{ limit }} eller mindre.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Verdien er for lang. Den må vere {{ limit }} bokstavar eller mindre.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Verdien må vere {{ limit }} eller meir.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Verdien er for kort. Den må ha {{ limit }} teikn eller fleire.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Verdien må ikkje vere blank.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Verdien må ikkje vere tom (null).</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Verdien må vere tom (null).</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Verdien er ikkje gyldig.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Verdien er ikkje gyldig tidseining.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Verdien er ikkje ein gyldig URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Dei to verdiane må vere like.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Fila er for stor. Den maksimale storleik er {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Fila er for stor.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Fila kunne ikkje bli lasta opp.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Verdien må vere eit gyldig tal.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Fila er ikkje eit gyldig bilete.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Dette er ikkje ei gyldig IP-adresse.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Verdien er ikkje eit gyldig språk.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Verdien er ikkje ein gyldig lokalitet (språk/region).</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Verdien er ikkje eit gyldig land.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Verdien er allereie i bruk.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Storleiken på biletet kunne ikkje oppdagast.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Biletbreidda er for stor, ({{ width }} pikslar). Tillatt maksimumsbreidde er {{ max_width }} pikslar.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Biletbreidda er for liten, ({{ width }} pikslar). Forventa minimumsbreidde er {{ min_width }} pikslar.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Bilethøgda er for stor, ({{ height }} pikslar). Tillatt maksimumshøgde er {{ max_height }} pikslar.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Billethøgda er for låg, ({{ height }} pikslar). Forventa minimumshøgde er {{ min_height }} pikslar.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Verdien må vere brukaren sitt noverande passord.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Verdien må vere nøyaktig {{ limit }} teikn.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Fila vart kun delvis opplasta.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Inga fil vart lasta opp.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Førebels mappe (tmp) er ikkje konfigurert i php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Kan ikkje skrive førebels fil til disk.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Ei PHP-udviding forårsaka feil under opplasting.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Denne samlinga må innehalde {{ limit }} element eller meir.|Denne samlinga må innehalde {{ limit }} element eller meir.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Denne samlinga må innehalde {{ limit }} element eller færre.|Denne samlinga må innehalde {{ limit }} element eller færre.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Denne samlinga må innehalde nøyaktig {{ limit }} element.|Denne samlinga må innehalde nøyaktig {{ limit }} element.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Ugyldig kortnummer.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Korttypen er ikkje støtta eller ugyldig kortnummer.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Aquest valor hauria de ser fals.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Aquest valor hauria de ser cert.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Aquest valor hauria de ser del tipus {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Aquest valor hauria d'estar buit.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>El valor seleccionat no és una opció vàlida.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Ha de seleccionar almenys {{ limit }} opció.|Ha de seleccionar almenys {{ limit }} opcions.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Ha de seleccionar com a màxim {{ limit }} opció.|Ha de seleccionar com a màxim {{ limit }} opcions.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Un o més dels valors facilitats són incorrectes.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>No s'esperaven els camps {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Falten els camps {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Aquest valor no és una data vàlida.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Aquest valor no és una data i hora vàlida.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Aquest valor no és una adreça d'email vàlida.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>No s'ha pogut trobar l'arxiu.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>No es pot llegir l'arxiu.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>L'arxiu és massa gran ({{ size }} {{ suffix }}). La grandària màxima permesa és {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>El tipus mime de l'arxiu no és vàlid ({{ type }}). Els tipus mime vàlids són {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Aquest valor hauria de ser {{ limit }} o menys.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Aquest valor és massa llarg. Hauria de tenir {{ limit }} caràcter o menys.|Aquest valor és massa llarg. Hauria de tenir {{ limit }} caràcters o menys.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Aquest valor hauria de ser {{ limit }} o més.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Aquest valor és massa curt. Hauria de tenir {{ limit }} caràcters o més.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Aquest valor no hauria d'estar buit.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Aquest valor no hauria de ser null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Aquest valor hauria de ser null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Aquest valor no és vàlid.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Aquest valor no és una hora vàlida.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Aquest valor no és una URL vàlida.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Els dos valors haurien de ser iguals.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>L'arxiu és massa gran. El tamany màxim permés és {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>L'arxiu és massa gran.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>No es pot pujar l'arxiu.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Aquest valor hauria de ser un nombre vàlid.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>L'arxiu no és una imatge vàlida.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Això no és una adreça IP vàlida.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Aquest valor no és un idioma vàlid.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Aquest valor no és una localització vàlida.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Aquest valor no és un país vàlid.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Aquest valor ja s'ha utilitzat.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>No s'ha pogut determinar la grandària de la imatge.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>L'amplària de la imatge és massa gran ({{ width }}px). L'amplària màxima permesa són {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>L'amplària de la imatge és massa petita ({{ width }}px). L'amplària mínima requerida són {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>L'altura de la imatge és massa gran ({{ height }}px). L'altura màxima permesa són {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>L'altura de la imatge és massa petita ({{ height }}px). L'altura mínima requerida són {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Aquest valor hauria de ser la contrasenya actual de l'usuari.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Aquest valor hauria de tenir exactament {{ limit }} caràcter.|Aquest valor hauria de tenir exactament {{ limit }} caràcters.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>L'arxiu va ser només pujat parcialment.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Cap arxiu va ser pujat.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Cap carpeta temporal va ser configurada en php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>No es va poder escriure l'arxiu temporal en el disc.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Una extensió de PHP va fer que la pujada fallara.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Aquesta col·lecció ha de contenir {{ limit }} element o més.|Aquesta col·lecció ha de contenir {{ limit }} elements o més.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Aquesta col·lecció ha de contenir {{ limit }} element o menys.|Aquesta col·lecció ha de contenir {{ limit }} elements o menys.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Aquesta col·lecció ha de contenir exactament {{ limit }} element.|Aquesta col·lecció ha de contenir exactament {{ limit }} elements.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Número de targeta invàlid.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Tipus de targeta no suportada o número de targeta invàlid.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Això no és un nombre de compte bancari internacional (IBAN) vàlid.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Aquest valor no és un ISBN-10 vàlid.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Aquest valor no és un ISBN-13 vàlid.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Aquest valor no és ni un ISBN-10 vàlid ni un ISBN-13 vàlid.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Aquest valor no és un ISSN vàlid.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Este valor debería ser falso.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Este valor debería ser verdadero.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Este valor debería ser de tipo {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Este valor debería estar vacío.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>El valor seleccionado no es una opción válida.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Debe seleccionar al menos {{ limit }} opción.|Debe seleccionar al menos {{ limit }} opciones.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Debe seleccionar como máximo {{ limit }} opción.|Debe seleccionar como máximo {{ limit }} opciones.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Uno o más de los valores indicados no son válidos.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>No se esperaban los campos {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Faltan los campos {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Este valor no es una fecha válida.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Este valor no es una fecha y hora válidas.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Este valor no es una dirección de email válida.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>No se pudo encontrar el archivo.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>No se puede leer el archivo.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>El archivo es demasiado grande ({{ size }} {{ suffix }}). El tamaño máximo permitido es {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>El tipo mime del archivo no es válido ({{ type }}). Los tipos mime válidos son {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Este valor debería ser {{ limit }} o menos.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Este valor es demasiado largo. Debería tener {{ limit }} carácter o menos.|Este valor es demasiado largo. Debería tener {{ limit }} caracteres o menos.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Este valor debería ser {{ limit }} o más.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Este valor es demasiado corto. Debería tener {{ limit }} carácter o más.|Este valor es demasiado corto. Debería tener {{ limit }} caracteres o más.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Este valor no debería estar vacío.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Este valor no debería ser null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Este valor debería ser null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Este valor no es válido.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Este valor no es una hora válida.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Este valor no es una URL válida.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Los dos valores deberían ser iguales.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>El archivo es demasiado grande. El tamaño máximo permitido es {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>El archivo es demasiado grande.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>No se pudo subir el archivo.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Este valor debería ser un número válido.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>El archivo no es una imagen válida.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Esto no es una dirección IP válida.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Este valor no es un idioma válido.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Este valor no es una localización válida.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Este valor no es un país válido.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Este valor ya se ha utilizado.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>No se pudo determinar el tamaño de la imagen.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>La anchura de la imagen es demasiado grande ({{ width }}px). La anchura máxima permitida son {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>La anchura de la imagen es demasiado pequeña ({{ width }}px). La anchura mínima requerida son {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>La altura de la imagen es demasiado grande ({{ height }}px). La altura máxima permitida son {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>La altura de la imagen es demasiado pequeña ({{ height }}px). La altura mínima requerida son {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Este valor debería ser la contraseña actual del usuario.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Este valor debería tener exactamente {{ limit }} carácter.|Este valor debería tener exactamente {{ limit }} caracteres.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>El archivo fue sólo subido parcialmente.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Ningún archivo fue subido.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Ninguna carpeta temporal fue configurada en php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>No se pudo escribir el archivo temporal en el disco.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Una extensión de PHP hizo que la subida fallara.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Esta colección debe contener {{ limit }} elemento o más.|Esta colección debe contener {{ limit }} elementos o más.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Esta colección debe contener {{ limit }} elemento o menos.|Esta colección debe contener {{ limit }} elementos o menos.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Esta colección debe contener exactamente {{ limit }} elemento.|Esta colección debe contener exactamente {{ limit }} elementos.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Número de tarjeta inválido.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Tipo de tarjeta no soportado o número de tarjeta inválido.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Esto no es un International Bank Account Number (IBAN) válido.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Este valor no es un ISBN-10 válido.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Este valor no es un ISBN-13 válido.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Este valor no es ni un ISBN-10 válido ni un ISBN-13 válido.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Este valor no es un ISSN válido.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
﻿<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Значение должно быть ложным.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Значение должно быть истинным.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Тип значения должен быть {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Значение должно быть пустым.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Выбранное Вами значение недопустимо.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Вы должны выбрать хотя бы {{ limit }} вариант.|Вы должны выбрать хотя бы {{ limit }} варианта.|Вы должны выбрать хотя бы {{ limit }} вариантов.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Вы должны выбрать не более чем {{ limit }} вариант.|Вы должны выбрать не более чем {{ limit }} варианта.|Вы должны выбрать не более чем {{ limit }} вариантов.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Одно или несколько заданных значений недопустимо.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Поля {{ fields }} не ожидались.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Поля {{ fields }} отсутствуют.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Значение не является правильной датой.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Значение даты и времени недопустимо.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Значение адреса электронной почты недопустимо.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Файл не может быть найден.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Файл не может быть прочитан.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Файл слишком большой ({{ size }} {{ suffix }}). Максимально допустимый размер {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>MIME-тип файла недопустим ({{ type }}). Допустимы MIME-типы файлов {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Значение должно быть {{ limit }} или меньше.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Значение слишком длинное. Должно быть равно {{ limit }} символу или меньше.|Значение слишком длинное. Должно быть равно {{ limit }} символам или меньше.|Значение слишком длинное. Должно быть равно {{ limit }} символам или меньше.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Значение должно быть {{ limit }} или больше.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Значение слишком короткое. Должно быть равно {{ limit }} символу или больше.|Значение слишком короткое. Должно быть равно {{ limit }} символам или больше.|Значение слишком короткое. Должно быть равно {{ limit }} символам или больше.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Значение не должно быть пустым.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Значение не должно быть null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Значение должно быть null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Значение недопустимо.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Значение времени недопустимо.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Значение не является допустимым URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Оба значения должны быть одинаковыми.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Файл слишком большой. Максимально допустимый размер {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Файл слишком большой.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Файл не может быть загружен.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Значение должно быть числом.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This value is not a valid country.</source>
                <target>Значение не является допустимой страной.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This file is not a valid image.</source>
                <target>Файл не является допустимым форматом изображения.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This is not a valid IP address.</source>
                <target>Значение не является допустимым IP адресом.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid language.</source>
                <target>Значение не является допустимым языком.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid locale.</source>
                <target>Значение не является допустимой локалью.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Это значение уже используется.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Не удалось определить размер изображения.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Ширина изображения слишком велика ({{ width }}px). Максимально допустимая ширина {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Ширина изображения слишком мала ({{ width }}px). Минимально допустимая ширина {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Высота изображения слишком велика ({{ height }}px). Максимально допустимая высота {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Высота изображения слишком мала ({{ height }}px). Минимально допустимая высота {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Значение должно быть текущим паролем пользователя.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Значение должно быть равно {{ limit }} символу.|Значение должно быть равно {{ limit }} символам.|Значение должно быть равно {{ limit }} символам.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Файл был загружен только частично.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Файл не был загружен.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Не настроена временная директория в php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Невозможно записать временный файл на диск.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Расширение PHP вызвало ошибку при загрузке.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Эта коллекция должна содержать {{ limit }} элемент или больше.|Эта коллекция должна содержать {{ limit }} элемента или больше.|Эта коллекция должна содержать {{ limit }} элементов или больше.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Эта коллекция должна содержать {{ limit }} элемент или меньше.|Эта коллекция должна содержать {{ limit }} элемента или меньше.|Эта коллекция должна содержать {{ limit }} элементов или меньше.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Эта коллекция должна содержать ровно {{ limit }} элемент.|Эта коллекция должна содержать ровно {{ limit }} элемента.|Эта коллекция должна содержать ровно {{ limit }} элементов.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Неверный номер карты.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Неподдерживаемый тип или неверный номер карты.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Значение не является допустимым международным номером банковского счета (IBAN).</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Значение имеет неверный формат ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Значение имеет неверный формат ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Значение не соответствует форматам ISBN-10 и ISBN-13</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Значение не соответствует формату ISSN.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Некорректный формат валюты.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Значение должно быть равно {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Значение должно быть больше чем {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Значение должно быть больше или равно {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Значение должно быть идентичным {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Значение должно быть меньше чем {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Значение должно быть меньше или равно {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Значение не должно быть равно {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Значение не должно быть идентичным {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Dëse Wäert sollt falsch sinn.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Dëse Wäert sollt wouer sinn.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Dëse Wäert sollt vum Typ {{ type }} sinn.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Dëse Wäert sollt eidel sinn.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Dëse Wäert sollt enger vun de Wielméiglechkeeten entspriechen.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Dir sollt mindestens {{ limit }} Méiglechkeete wielen.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Dir sollt héchstens {{ limit }} Méiglechkeete wielen.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Een oder méi vun de Wäerter ass ongëlteg.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>D'Felder {{ fields }} goufen net erwaart.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>D'Felder {{ fields }} feelen.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Dëse Wäert entsprécht kenger gëlteger Datumsangab.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Dëse Wäert entsprécht kenger gëlteger Datums- an Zäitangab.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Dëse Wäert ass keng gëlteg Email-Adress.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>De Fichier gouf net fonnt.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>De Fichier ass net liesbar.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>De Fichier ass ze grouss ({{ size }} {{ suffix }}). Déi zougeloosse Maximalgréisst bedréit {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Den Typ vum Fichier ass ongëlteg ({{ type }}). Erlaabten Type sinn {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Dëse Wäert soll méi kleng oder gläich {{ limit }} sinn.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Dës Zeecheketten ass ze laang. Se sollt héchstens {{ limit }} Zeechen hunn.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Dëse Wäert sollt méi grouss oder gläich {{ limit }} sinn.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Dës Zeecheketten ass ze kuerz. Se sollt mindestens {{ limit }} Zeechen hunn.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Dëse Wäert sollt net eidel sinn.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Dëst sollt keen Null-Wäert sinn.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Dëst sollt keen Null-Wäert sinn.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Dëse Wäert ass net gëlteg.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Dëse Wäert entsprécht kenger gëlteger Zäitangab.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Dëse Wäert ass keng gëlteg URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Béid Wäerter sollten identesch sinn.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>De fichier ass ze grouss. Déi maximal Gréisst dierf {{ limit }} {{ suffix }} net depasséieren.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>De Fichier ass ze grouss.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>De Fichier konnt net eropgeluede ginn.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Dëse Wäert sollt eng gëlteg Zuel sinn.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Dëse Fichier ass kee gëltegt Bild.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Dëst ass keng gëlteg IP-Adress.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Dëse Wäert aentsprécht kenger gëlteger Sprooch.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Dëse Wäert entsprécht kengem gëltege Gebittsschema.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Dëse Wäert entsprécht kengem gëltege Land.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Dëse Wäert gëtt scho benotzt.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>D'Gréisst vum Bild konnt net detektéiert ginn.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>D'Breet vum Bild ass ze grouss ({{ width }}px). Déi erlaabte maximal Breet ass {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>D'Breet vum Bild ass ze kleng ({{ width }}px). Déi minimal Breet ass {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>D'Héicht vum Bild ass ze grouss ({{ height }}px). Déi erlaabte maximal Héicht ass {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>D'Héicht vum Bild ass ze kleng ({{ height }}px). Déi minimal Héicht ass {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Dëse Wäert sollt dem aktuelle Benotzerpasswuert entspriechen.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Dëse Wäert sollt exactly {{ limit }} Buschtaf hunn.|Dëse Wäert sollt exakt {{ limit }} Buschtawen hunn.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>De Fichier gouf just deelweis eropgelueden.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Et gouf kee Fichier eropgelueden.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Et gouf keen temporären Dossier an der php.ini konfiguréiert.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Den temporäre Fichier kann net gespäichert ginn.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Eng PHP-Erweiderung huet den Upload verhënnert.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Dës Sammlung sollt {{ limit }} oder méi Elementer hunn.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Dës Sammlung sollt {{ limit }} oder manner Elementer hunn.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Dës Sammlung sollt exakt {{ limit }} Element hunn.|Dës Sammlung sollt exakt {{ limit }} Elementer hunn.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Ongëlteg Kaartennummer.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Net ënnerstëtzte Kaartentyp oder ongëlteg Kaartennummer.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Dëst ass keng gëlteg IBAN-Kontonummer.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Dëse Wäert ass keng gëlteg ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Dëse Wäert ass keng gëlteg ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Dëse Wäert ass weder eng gëlteg ISBN-10 nach eng gëlteg ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Dëse Wäert ass keng gëlteg ISSN.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Värdet ska vara falskt.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Värdet ska vara sant.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Värdet ska vara av typen {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Värdet ska vara tomt.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Värdet ska vara ett av de givna valen.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Du måste välja minst {{ limit }} val.|Du måste välja minst {{ limit }} val.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Du kan som mest välja {{ limit }} val.|Du kan som mest välja {{ limit }} val.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Ett eller fler av de angivna värdena är ogiltigt.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Fälten {{ fields }} var oväntade.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Fälten {{ fields }} saknas.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Värdet är inte ett giltigt datum.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Värdet är inte ett giltigt datum med tid.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Värdet är inte en giltig epost-adress.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Filen kunde inte hittas.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Filen är inte läsbar.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Filen är för stor ({{ size }} {{ suffix }}). Största tillåtna storlek är {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Filens MIME-typ ({{ type }}) är ogiltig. De tillåtna typerna är {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Värdet ska vara {{ limit }} eller mindre.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Värdet är för långt. Det ska ha {{ limit }} tecken eller färre.|Värdet är för långt. Det ska ha {{ limit }} tecken eller färre.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Värdet ska vara {{ limit }} eller mer.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Värdet är för kort. Det ska ha {{ limit }} tecken eller mer.|Värdet är för kort. Det ska ha {{ limit }} tecken eller mer.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Värdet kan inte vara tomt.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Värdet kan inte vara null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Värdet ska vara null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Värdet är inte giltigt.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Värdet är inte en giltig tid.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Värdet är inte en giltig URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>De två värdena måste vara lika.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Filen är för stor. Tillåten maximal storlek är {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Filen är för stor.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Filen kunde inte laddas upp.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Värdet ska vara ett giltigt nummer.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Den är filen är ingen giltig bild.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Det här är inte en giltig IP-adress.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Värdet är inte ett giltigt språk.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Värdet är inte en giltig plats.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Värdet är inte ett giltigt land.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Värdet används redan.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Det gick inte att fastställa storleken på bilden.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Bildens bredd är för stor ({{ width }}px). Tillåten maximal bredd är {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Bildens bredd är för liten ({{ width }}px). Minsta förväntade bredd är {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Bildens höjd är för stor ({{ height }}px). Tillåten maximal bredd är {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Bildens höjd är för liten ({{ height }}px). Minsta förväntade höjd är {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Värdet ska vara användarens nuvarande lösenord.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Värdet ska ha exakt {{ limit }} tecken.|Värdet ska ha exakt {{ limit }} tecken.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Filen laddades bara upp delvis.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Ingen fil laddades upp.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Det finns ingen temporär mapp konfigurerad i php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Kan inte skriva temporär fil till disken.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>En PHP extension gjorde att uppladdningen misslyckades.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Den här samlingen ska innehålla {{ limit }} element eller mer.|Den här samlingen ska innehålla {{ limit }} element eller mer.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Den här samlingen ska innehålla {{ limit }} element eller mindre.|Den här samlingen ska innehålla {{ limit }} element eller mindre.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Den här samlingen ska innehålla exakt {{ limit }} element.|Den här samlingen ska innehålla exakt {{ limit }} element.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Ta wartość powinna być fałszem.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Ta wartość powinna być prawdą.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Ta wartość powinna być typu {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Ta wartość powinna być pusta.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Ta wartość powinna być jedną z podanych opcji.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Powinieneś wybrać co najmniej {{ limit }} opcję.|Powinieneś wybrać co najmniej {{ limit }} opcje.|Powinieneś wybrać co najmniej {{ limit }} opcji.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Powinieneś wybrać maksymalnie {{ limit }} opcję.|Powinieneś wybrać maksymalnie {{ limit }} opcje.|Powinieneś wybrać maksymalnie {{ limit }} opcji.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Jedna lub więcej z podanych wartości jest nieprawidłowa.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Pola {{ fields }} nie były oczekiwane.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Brakuje pól {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Ta wartość nie jest prawidłową datą.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Ta wartość nie jest prawidłową datą i czasem.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Ta wartość nie jest prawidłowym adresem email.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Plik nie mógł zostać odnaleziony.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Nie można odczytać pliku.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Plik jest za duży ({{ size }} {{ suffix }}). Maksymalny dozwolony rozmiar to {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Nieprawidłowy typ mime pliku ({{ type }}). Dozwolone typy mime to {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Ta wartość powinna wynosić {{ limit }} lub mniej.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Ta wartość jest zbyt długa. Powinna mieć {{ limit }} lub mniej znaków.|Ta wartość jest zbyt długa. Powinna mieć {{ limit }} lub mniej znaków.|Ta wartość jest zbyt długa. Powinna mieć {{ limit }} lub mniej znaków.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Ta wartość powinna wynosić {{ limit }} lub więcej.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Ta wartość jest zbyt krótka. Powinna mieć {{ limit }} lub więcej znaków.|Ta wartość jest zbyt krótka. Powinna mieć {{ limit }} lub więcej znaków.|Ta wartość jest zbyt krótka. Powinna mieć {{ limit }} lub więcej znaków.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Ta wartość nie powinna być pusta.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Ta wartość nie powinna być nullem.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Ta wartość powinna być nullem.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Ta wartość jest nieprawidłowa.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Ta wartość nie jest prawidłowym czasem.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Ta wartość nie jest prawidłowym adresem URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Obie wartości powinny być równe.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Plik jest za duży. Maksymalny dozwolony rozmiar to {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Plik jest za duży.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Plik nie mógł być wgrany.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Ta wartość powinna być prawidłową liczbą.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Ten plik nie jest obrazem.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>To nie jest prawidłowy adres IP.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Ta wartość nie jest prawidłowym językiem.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Ta wartość nie jest prawidłową lokalizacją.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Ta wartość nie jest prawidłową nazwą kraju.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Ta wartość jest już wykorzystywana.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Nie można wykryć rozmiaru obrazka.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Szerokość obrazka jest zbyt duża ({{ width }}px). Maksymalna dopuszczalna szerokość to {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Szerokość obrazka jest zbyt mała ({{ width }}px). Oczekiwana minimalna szerokość to {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Wysokość obrazka jest zbyt duża ({{ height }}px). Maksymalna dopuszczalna wysokość to {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Wysokość obrazka jest zbyt mała ({{ height }}px). Oczekiwana minimalna wysokość to {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Ta wartość powinna być aktualnym hasłem użytkownika.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Ta wartość powinna mieć dokładnie {{ limit }} znak.|Ta wartość powinna mieć dokładnie {{ limit }} znaki.|Ta wartość powinna mieć dokładnie {{ limit }} znaków.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Plik został wgrany tylko częściowo.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Żaden plik nie został wgrany.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Nie skonfigurowano folderu tymczasowego w php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Nie można zapisać pliku tymczasowego na dysku.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Rozszerzenie PHP spowodowało błąd podczas wgrywania.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Ten zbiór powinien zawierać {{ limit }} lub więcej elementów.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Ten zbiór powinien zawierać {{ limit }} lub mniej elementów.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Ten zbiór powinien zawierać dokładnie {{ limit }} element.|Ten zbiór powinien zawierać dokładnie {{ limit }} elementy.|Ten zbiór powinien zawierać dokładnie {{ limit }} elementów.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Nieprawidłowy numer karty.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Nieobsługiwany rodzaj karty lub nieprawidłowy numer karty.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Nieprawidłowy międzynarodowy numer rachunku bankowego (IBAN).</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Ta wartość nie jest prawidłowym numerem ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Ta wartość nie jest prawidłowym numerem ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Ta wartość nie jest prawidłowym numerem ISBN-10 ani ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Ta wartość nie jest prawidłowym numerem ISSN.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Ta wartość nie jest prawidłową walutą.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Ta wartość powinna być równa {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Ta wartość powinna być większa niż {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Ta wartość powinna być większa bądź równa {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Ta wartość powinna być identycznego typu {{ compared_value_type }} oraz wartości {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Ta wartość powinna być mniejsza niż {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Ta wartość powinna być mniejsza bądź równa {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Ta wartość nie powinna być równa {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Ta wartość nie powinna być identycznego typu {{ compared_value_type }} oraz wartości {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Vrednost treba da bude netačna.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Vrednost treba da bude tačna.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Vrednost treba da bude tipa {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Vrednost treba da bude prazna.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Vrednost treba da bude jedna od ponuđenih.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Izaberite bar {{ limit }} mogućnost.|Izaberite bar {{ limit }} mogućnosti.|Izaberite bar {{ limit }} mogućnosti.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Izaberite najviše {{ limit }} mogućnost.|Izaberite najviše {{ limit }} mogućnosti.|Izaberite najviše {{ limit }} mogućnosti.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Jedna ili više vrednosti je nevalidna.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Polja {{ fields }} nisu bila očekivana.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Polja {{ fields }} nedostaju.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Vrednost nije validan datum.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Vrednost nije validan datum-vreme.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Vrednost nije validna adresa elektronske pošte.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Datoteka ne može biti pronađena.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Datoteka nije čitljiva.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Datoteka je prevelika ({{ size }} {{ suffix }}). Najveća dozvoljena veličina je {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Mime tip datoteke nije validan ({{ type }}). Dozvoljeni mime tipovi su {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Vrednost treba da bude {{ limit }} ili manje.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Vrednost je predugačka. Treba da ima {{ limit }} karakter ili manje.|Vrednost je predugačka. Treba da ima {{ limit }} karaktera ili manje.|Vrednost je predugačka. Treba da ima {{ limit }} karaktera ili manje.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Vrednost treba da bude {{ limit }} ili više.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Vrednost je prekratka. Treba da ima {{ limit }} karakter ili više.|Vrednost je prekratka. Treba da ima {{ limit }} karaktera ili više.|Vrednost je prekratka. Treba da ima {{ limit }} karaktera ili više.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Vrednost ne treba da bude prazna.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Vrednost ne treba da bude null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Vrednost treba da bude null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Vrednost je nevalidna.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Vrednost nije validno vreme.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Vrednost nije validan URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Obe vrednosti treba da budu jednake.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Datoteka je prevelika. Najveća dozvoljena veličina je {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Datoteka je prevelika.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Datoteka ne može biti otpremljena.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Vrednost treba da bude validan broj.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Ova datoteka nije validna slika.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Ovo nije validna IP adresa.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Vrednost nije validan jezik.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Vrednost nije validan lokal.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Vrednost nije validna zemlja.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Vrednost je već iskorišćena.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Veličina slike ne može biti određena.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Širina slike je prevelika ({{ width }}px). Najeća dozvoljena širina je {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Širina slike je premala ({{ width }}px). Najmanja dozvoljena širina je {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Visina slike je prevelika ({{ height }}px). Najeća dozvoljena visina je {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Visina slike je premala ({{ height }}px). Najmanja dozvoljena visina je {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Vrednost treba da bude trenutna korisnička lozinka.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Vrednost treba da ima tačno {{ limit }} karakter.|Vrednost treba da ima tačno {{ limit }} karaktera.|Vrednost treba da ima tačno {{ limit }} karaktera.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Datoteka je samo parcijalno otpremljena.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Datoteka nije otpremljena.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Privremeni direktorijum nije konfigurisan u php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Nemoguće pisanje privremene datoteke na disk.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>PHP ekstenzija je prouzrokovala neuspeh otpremanja datoteke.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Ova kolekcija treba da sadrži {{ limit }} ili više elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili više elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili više elemenata.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Ova kolekcija treba da sadrži {{ limit }} ili manje elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili manje elemenata.|Ova kolekcija treba da sadrži {{ limit }} ili manje elemenata.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Ova kolekcija treba da sadrži tačno {{ limit }} element.|Ova kolekcija treba da sadrži tačno {{ limit }} elementa.|Ova kolekcija treba da sadrži tačno {{ limit }} elemenata.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Nevalidan broj kartice.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Nevalidan broj kartice ili tip kartice nije podržan.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target state="needs-review-translation">این مقدار باید نادرست(False) باشد.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>این مقدار باید درست(True) باشد.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>این مقدار باید از نوع {{ type }} باشد.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>این فیلد باید خالی باشد.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>گزینه انتخابی معتبر نیست.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>باید حداقل {{ limit }} گزینه انتخاب کنید.|باید حداقل {{ limit }} گزینه انتخاب کنید.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>حداکثر {{ limit }} گزینه می توانید انتخاب کنید.|حداکثر {{ limit }} گزینه می توانید انتخاب کنید.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>یک یا چند مقدار نامعتبر وجود دارد.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>فیلدهای {{ fields }} اضافی هستند.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>فیلدهای {{ fields }} کم هستند.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>این مقدار یک تاریخ معتبر نیست.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>این مقدار یک تاریخ و زمان معتبر نیست.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>این یک رایانامه معتبر نیست.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>فایل پیدا نشد.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>فایل قابلیت خواندن ندارد.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>فایل بیش از اندازه بزرگ است({{ size }} {{ suffix }}). حداکثر اندازه مجاز برابر {{ limit }} {{ suffix }} است.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>این نوع فایل مجاز نیست({{ type }}). نوع های مجاز {{ types }} هستند.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>این مقدار باید کوچکتر یا مساوی {{ limit }} باشد.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>بسیار طولانی است.حداکثر تعداد حروف مجاز برابر {{ limit }} است.|بسیار طولانی است.حداکثر تعداد حروف مجاز برابر {{ limit }} است.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>این مقدار باید برابر و یا بیشتر از {{ limit }} باشد.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>بسیار کوتاه است.تعداد حروف باید حداقل {{ limit }} باشد.|بسیار کوتاه است.تعداد حروف باید حداقل {{ limit }} باشد.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>این مقدار نباید تهی باشد.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>باید مقداری داشته باشد..</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>نباید مقداری داشته باشد.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>این مقدار معتبر نیست.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>این مقدار یک زمان صحیح نیست.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>این یک URL معتبر نیست.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>دو مقدار باید برابر باشند.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>فایل بیش از اندازه بزرگ است. حداکثر اندازه مجاز برابر {{ limit }} {{ suffix }} است.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>فایل بیش از اندازه بزرگ است.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>بارگذاری فایل با شکست مواجه شد.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>این مقدار باید یک عدد معتبر باشد.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>این فایل یک تصویر نیست.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>این مقدار یک IP معتبر نیست.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>این مقدار یک زبان صحیح نیست.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>این مقدار یک محل صحیح نیست.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>این مقدار یک کشور صحیح نیست.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>این مقدار قبلا مورد استفاده قرار گرفته است.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>اندازه تصویر قابل شناسایی نیست.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>طول تصویر بسیار بزرگ است ({{ width }}px). بشینه طول مجاز {{ max_width }}px است.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>طول تصویر بسیار کوچک است ({{ width }}px). کمینه طول موردنظر {{ min_width }}px است.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>ارتفاع تصویر بسیار بزرگ است ({{ height }}px). بشینه ارتفاع مجاز {{ max_height }}px است.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>ارتفاع تصویر بسیار کوچک است ({{ height }}px). کمینه ارتفاع موردنظر {{ min_height }}px است.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>این مقدار می بایست کلمه عبور کنونی کاربر باشد.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>این مقدار می بایست دقیفا {{ limit }} کاراکتر داشته باشد.|این مقدرا می بایشت دقیقا {{ limit }} کاراکتر داشته باشد.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>فایل به صورت جزیی بارگذاری شده است.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>هیچ فایلی بارگذاری نشد.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>فولدر موقت در php.ini پیکربندی نشده است.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>فایل موقت را نمی توان در دیسک نوشت.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>اکستنشن PHP موجب شد که بارگذاری فایل با شکست مواجه شود.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>این مجموعه می بایست دارای {{ limit }} عنصر یا بیشتر باشد.|این مجموعه می بایست دارای {{ limit }} عنصر یا بیشتر باشد.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>این مجموعه می بایست دارای حداقل {{ limit }} عنصر یا کمتر باشد.|این مجموعه می بایست دارای {{ limit }} عنصر یا کمتر باشد.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>این مجموعه می بایست به طور دقیق دارا {{ limit }} عنصر باشد.|این مجموعه می بایست به طور دقیق دارای {{ limit }} قلم باشد.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>شماره کارت نامعتبر است.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>نوع کارت پشتیبانی نمی شود یا شماره کارت نامعتبر است.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>این یک شماره حساب بین المللی بانک (IBAN) درست نیست.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>این مقدار یک ISBN-10 درست نیست.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>این مقدار یک ISBN-13 درست نیست.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>این مقدار یک ISBN-10 درست یا ISBN-13 درست نیست.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>این مقدار یک ISSN درست نیست.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>این مقدار یک یکای پول درست نیست.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>این مقدار باید برابر با {{ compared_value }} باشد.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>این مقدار باید از {{ compared_value }} بیشتر باشد.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>این مقدار باید بزرگتر یا مساوی با {{ compared_value }} باشد.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>این مقدار باید با {{ compared_value_type }} {{ compared_value }} یکی باشد.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>این مقدار باید کمتر از {{ compared_value }} باشد.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>این مقدار باید کمتر یا مساوی با {{ compared_value }} باشد.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>این مقدار نباید با {{ compared_value }} برابر باشد.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>این مقدار نباید {{ compared_value_type }} {{ compared_value }} یکی باشد.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>הערך צריך להיות שקר.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>הערך צריך להיות אמת.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>הערך צריך להיות מסוג {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>הערך צריך להיות ריק.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>הערך שבחרת אינו חוקי.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>אתה צריך לבחור לפחות {{ limit }} אפשרויות.|אתה צריך לבחור לפחות {{ limit }} אפשרויות.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>אתה צריך לבחור לכל היותר {{ limit }} אפשרויות.|אתה צריך לבחור לכל היותר {{ limit }} אפשרויות.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>אחד או יותר מהערכים אינו חוקי.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>השדות {{ fields }} לא היו צפויים.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>השדות {{ fields }} חסרים.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>הערך אינו תאריך חוקי.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>הערך אינו תאריך ושעה חוקיים.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>כתובת המייל אינה תקינה.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>הקובץ לא נמצא.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>לא ניתן לקרוא את הקובץ.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>הקובץ גדול מדי ({{ size }} {{ suffix }}). הגודל המרבי המותר הוא {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>סוג MIME של הקובץ אינו חוקי ({{ type }}). מותרים סוגי MIME {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>הערך צריל להכיל {{ limit }} תווים לכל היותר.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>הערך ארוך מידי. הוא צריך להכיל {{ limit }} תווים לכל היותר.|הערך ארוך מידי. הוא צריך להכיל {{ limit }} תווים לכל היותר.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>הערך צריך להכיל {{ limit }} תווים לפחות.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>הערך קצר מידיץ הוא צריך להכיל {{ limit }} תווים לפחות.|הערך קצר מידיץ הוא צריך להכיל {{ limit }} תווים לפחות.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>הערך לא אמור להיות ריק.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>הערך לא אמור להיות ריק.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>הערך צריך להיות ריק.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>הערך אינו חוקי.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>הערך אינו זמן תקין.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>זאת אינה כתובת אתר תקינה.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>שני הערכים צריכים להיות שווים.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>הקובץ גדול מדי. הגודל המרבי המותר הוא {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>הקובץ גדול מדי.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>לא ניתן לעלות את הקובץ.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>הערך צריך להיות מספר חוקי.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>הקובץ הזה אינו תמונה תקינה.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>זו אינה כתובת IP חוקית.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>הערך אינו שפה חוקית.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>הערך אינו אזור תקף.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>הערך אינו ארץ חוקית.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>הערך כבר בשימוש.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>לא ניתן לקבוע את גודל התמונה.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>רוחב התמונה גדול מדי ({{ width }}px). הרוחב המקסימלי הוא {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>רוחב התמונה קטן מדי ({{ width }}px). הרוחב המינימלי הוא {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>גובה התמונה גדול מדי ({{ height }}px). הגובה המקסימלי הוא {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>גובה התמונה קטן מדי ({{ height }}px). הגובה המינימלי הוא {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>הערך צריך להיות סיסמת המשתמש הנוכחי.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>הערך צריך להיות בדיוק {{ limit }} תווים.|הערך צריך להיות בדיוק {{ limit }} תווים.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>הקובץ הועלה באופן חלקי.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>הקובץ לא הועלה.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>לא הוגדרה תיקייה זמנית ב php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>לא ניתן לכתוב קובץ זמני לדיסק.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>סיומת PHP גרם להעלאה להיכשל.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>האוסף אמור להכיל {{ limit }} אלמנטים או יותר.|האוסף אמור להכיל {{ limit }} אלמנטים או יותר.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>האוסף אמור להכיל {{ limit }} אלמנטים או פחות.|האוסף אמור להכיל {{ limit }} אלמנטים או פחות.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>האוסף צריך להכיל בדיוק {{ limit }} אלמנטים.|האוסף צריך להכיל בדיוק {{ limit }} אלמנטים.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>מספר הכרטיס אינו חוקי.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>סוג הכרטיס אינו נתמך או לא חוקי.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Balio honek faltsua izan beharko luke (false).</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Balio honek egiazkoa izan beharko luke (true).</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Balio honek {{ type }} motakoa izan beharko luke.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Balio honek hutsik egon beharko luke.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Hautatu duzun balioa ez da aukera egoki bat.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Gutxienez {{ limit }} aukera hautatu behar dituzu.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Gehienez {{ limit }} aukera hautatu behar dituzu.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Emandako balio bat edo gehiago ez dira egokiak.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>{{ fields }} eremuak ez ziren espero.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>{{ fields }} eremuak falta dira.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Balio hau ez da data egoki bat.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Balio hau ez da data eta ordu egoki bat.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Balio hau ez da helbide elektroniko egoki bat.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Ezin izan da fitxategia aurkitu.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Fitxategia ez dago irakurgai.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Fitxategia handiegia da ({{ size }} {{ suffix }}). Baimendutako tamainu handiena {{ limit }} {{ suffix }} da.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Fitxategiaren mime mota ez da egokia ({{ type }}). Hauek dira baimendutako mime motak: {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Balio honek {{ limit }} edo gutxiago izan beharko luke.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Balio hau luzeegia da. {{ limit }} karaktere edo gutxiago eduki beharko lituzke.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Balio honek {{ limit }} edo handiago izan beharko luke.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Balio hau motzegia da. {{ limit }} karaktere edo gehiago eduki beharko lituzke.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Balio honek ez luke hutsik egon behar.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Balio honek ez luke nulua izan behar.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Balio honek nulua izan beharko luke.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Balio hau ez da egokia.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Balio hau ez da ordu egoki bat.</target>
           </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Balio hau ez da URL egoki bat.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Bi balioak berdinak izan beharko lirateke.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Fitxategia handiegia da. Baimendutako tamainu handiena {{ limit }} {{ suffix }} da.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Fitxategia handiegia da.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Ezin izan da fitxategia igo.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Balio honek zenbaki egoki bat izan beharko luke.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Fitxategi hau ez da irudi egoki bat.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Honako hau ez da IP helbide egoki bat.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Balio hau ez da hizkuntza egoki bat.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Balio hau ez da lokalizazio egoki bat.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Balio hau ez da herrialde egoki bat.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Balio hau jadanik erabilia izan da.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Ezin izan da irudiaren tamaina detektatu.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Irudiaren zabalera haundiegia da ({{ width }}px). Onartutako gehienezko zabalera {{ max_width }}px dira.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Irudiaren zabalera txikiegia da ({{ width }}px). Onartutako gutxieneko zabalera {{ min_width }}px dira.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Irudiaren altuera haundiegia da ({{ height }}px). Onartutako gehienezko altuera {{ max_height }}px dira.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Irudiaren altuera txikiegia da ({{ height }}px). Onartutako gutxieneko altuera {{ min_height }}px dira.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Balio honek uneko erabiltzailearen pasahitza izan beharko luke.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Balio honek zehazki {{ limit }} karaktere izan beharko lituzke.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Fitxategia partzialki bakarrik igo da.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Ez da fitxategirik igo.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Ez da aldi baterako karpetarik konfiguratu php.ini fitxategian.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Ezin izan da aldi baterako fitxategia diskoan idatzi.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>PHP luzapen batek igoeraren hutsa eragin du.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Bilduma honek {{ limit }} elementu edo gehiago eduki beharko lituzke.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Bilduma honek {{ limit }} elementu edo gutxiago eduki beharko lituzke.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Bilduma honek zehazki {{ limit }} elementu eduki beharko lituzke.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Txartelaren zenbaki baliogabea.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Onartzen ez den txartel mota edo txartelaren zenbaki baliogabea.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Hau ez da onartutako International Bank Account Number (IBAN) bat.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Balio hau ez da onartutako ISBN-10 bat.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Balio hau ez da onartutako ISBN-13 bat.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Balio hau ez da onartutako ISBN-10 edo ISBN-13 bat.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Balio hau ez da onartutako ISSN bat.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Balio hau ez da baliozko moneta.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Balio honek {{ compared_value }}-(r)en berdina izan behar du.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Balio honek {{ compared_value }} baino handiagoa izan behar du.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Balio honek {{ compared_value }}-(r)en berdina edo handiagoa izan beharko luke.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Balio honek berbera izan behar du {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Balio honek {{ compared_value }} baino txikiago izan behar du.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Balio honek {{ compared_value }}-(r)en berdina edo txikiago izan behar du.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Balio honek {{ compared_value }}-(r)en berdina izan behar du.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Balio honek ez du berbera izan behar {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Această valoare ar trebui să fie falsă (false).</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Această valoare ar trebui să fie adevarătă (true).</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Această valoare ar trebui să fie de tipul {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Această valoare ar trebui sa fie goală.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Valoarea selectată nu este o opțiune validă.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Trebuie să selectați cel puțin {{ limit }} opțiuni.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Trebuie să selectați cel mult {{ limit }} opțiuni.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Una sau mai multe dintre valorile furnizate sunt invalide.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Câmpurile {{ fields }} nu erau așteptate.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Câmpurile {{ fields }} lipsesc.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Această valoare nu reprezintă o dată validă.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Această valoare nu reprezintă o dată și oră o valide.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Această valoare nu reprezintă o adresă de e-mail validă.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Fișierul nu a putut fi găsit.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Fișierul nu poate fi citit.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Fișierul este prea mare ({{ size }} {{ suffix }}). Dimensiunea maximă permisă este {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Tipul fișierului este invalid ({{ type }}). Tipurile permise de fișiere sunt ({{ types }}).</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Această valoare ar trebui să fie cel mult {{ limit }}.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Această valoare este prea lungă. Ar trebui să aibă maxim {{ limit }} caracter.|Această valoare este prea lungă. Ar trebui să aibă maxim {{ limit }} caractere.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Această valoare ar trebui să fie cel puțin {{ limit }}.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Această valoare este prea scurtă. Ar trebui să aibă minim {{ limit }} caracter.|Această valoare este prea scurtă. Ar trebui să aibă minim {{ limit }} caractere.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Această valoare nu ar trebui să fie goală.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Această valoare nu ar trebui să fie nulă (null).</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Această valoare ar trebui să fie nulă (null).</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Această valoare nu este validă.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Această valoare nu reprezintă o oră validă.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Această valoare nu reprezintă un URL (link) valid.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Cele două valori ar trebui să fie egale.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Fișierul este prea mare. Mărimea maximă permisă este {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Fișierul este prea mare.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Fișierul nu a putut fi încărcat.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Această valoare nu reprezintă un număr valid.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Acest fișier nu este o imagine validă.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Această valoare nu este o adresă IP validă.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Această valoare nu reprezintă o limbă corectă.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Această valoare nu reprezintă un dialect (o limbă) corect.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Această valoare nu este o țară validă.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Această valoare este folosită deja.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Mărimea imaginii nu a putut fi detectată.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Lățimea imaginii este prea mare ({{ width }}px). Lățimea maximă permisă este de {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Lățimea imaginii este prea mică ({{ width }}px). Lățimea minimă permisă este de {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Înlățimea imaginii este prea mare ({{ height }}px). Înălțimea maximă permisă este de {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Înlățimea imaginii este prea mică ({{ height }}px). Înălțimea minimă permisă este de {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Această valoare trebuie să fie parola curentă a utilizatorului.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Această valoare trebuie să conțină exact {{ limit }} caracter.|Această valoare trebuie să conțină exact {{ limit }} caractere.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Fișierul a fost încărcat parțial.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Nu a fost încărcat nici un fișier.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Nu este configurat nici un director temporar in php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Nu a fost posibilă scrierea fișierului temporar pe disk.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>O extensie PHP a prevenit încărcarea cu succes a fișierului.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Această colecție trebuie să conțină cel puțin {{ limit }} elemente.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Această colecție trebuie să conțină cel mult {{ limit }} elemente.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Această colecție trebuie să conțină {{ limit }} elemente.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Numărul card invalid.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Tipul sau numărul cardului nu sunt valide.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Acesta nu este un cod IBAN (International Bank Account Number) valid.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Această valoare nu este un cod ISBN-10 valid.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Această valoare nu este un cod ISBN-13 valid.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Această valoare nu este un cod ISBN-10 sau ISBN-13 valid.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Această valoare nu este un cod ISSN valid.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Această valoare nu este o monedă validă.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Această valoare trebuie să fie egală cu {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Această valoare trebuie să fie mai mare de {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Această valoare trebuie să fie mai mare sau egală cu {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Această valoare trebuie identică cu {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Această valoare trebuie să fie mai mică de {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Această valoare trebuie să fie mai mică sau egală cu {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Această valoare nu trebuie să fie egală cu {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Această valoare nu trebuie identică cu {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Vrednost bi morala biti nepravilna (false).</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Vrednost bi morala biti pravilna (true).</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Vrednost mora biti naslednjega tipa {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Vrednost mora biti prazna.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Vrednost, ki ste jo izbrali, ni veljavna možnost.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Izbrati morate vsaj {{ limit }} možnost.|Izbrati morate vsaj {{ limit }} možnosti.|Izbrati morate vsaj {{ limit }} možnosti.|Izbrati morate vsaj {{ limit }} možnosti.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Izberete lahko največ {{ limit }} možnost.|Izberete lahko največ {{ limit }} možnosti.|Izberete lahko največ {{ limit }} možnosti.|Izberete lahko največ {{ limit }} možnosti.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Ena ali več podanih vrednosti ni veljavnih.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Polja {{ fields }} niso bila pričakovana.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Polja {{ fields }} manjkajo.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Ta vrednost ni veljaven datum.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Ta vrednost ni veljaven datum in čas.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Ta vrednost ni veljaven e-poštni naslov.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Datoteke ni mogoče najti.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Datoteke ni mogoče prebrati.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Datoteka je prevelika ({{ size }} {{ suffix }}). Največja dovoljena velikost je {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Mime tip datoteke je neveljaven ({{ type }}). Dovoljeni mime tipi so {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Ta vrednost bi morala biti {{ limit }} ali manj.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Ta vrednost je predolga. Morala bi imeti {{ limit }} znak ali manj.|Ta vrednost je predolga. Morala bi imeti {{ limit }} znaka ali manj.|Ta vrednost je predolga. Morala bi imeti {{ limit }} znake ali manj.|Ta vrednost je predolga. Morala bi imeti {{ limit }} znakov ali manj.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Ta vrednost bi morala biti {{ limit }} ali več.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Ta vrednost je prekratka. Morala bi imeti {{ limit }} znak ali več.|Ta vrednost je prekratka. Morala bi imeti {{ limit }} znaka ali več.|Ta vrednost je prekratka. Morala bi imeti {{ limit }} znake ali več.|Ta vrednost je prekratka. Morala bi imeti {{ limit }} znakov ali več.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Ta vrednost ne bi smela biti prazna.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Ta vrednost ne bi smela biti nedefinirana (null).</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Ta vrednost bi morala biti nedefinirana (null).</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Ta vrednost ni veljavna.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Ta vrednost ni veljaven čas.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Ta vrednost ni veljaven URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Ti dve vrednosti bi morali biti enaki.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Datoteka je prevelika. Največja dovoljena velikost je {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Datoteka je prevelika.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Datoteke ni bilo mogoče naložiti.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Ta vrednost bi morala biti veljavna številka.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Ta datoteka ni veljavna slika.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>To ni veljaven IP naslov.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Ta vrednost ni veljaven jezik.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Ta vrednost ni veljavna lokalnost.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Ta vrednost ni veljavna država.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Ta vrednost je že uporabljena.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Velikosti slike ni bilo mogoče zaznati.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Širina slike je preširoka ({{ width }}px). Največja dovoljena širina je {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Širina slike je premajhna ({{ width }}px). Najmanjša predvidena širina je {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Višina slike je prevelika ({{ height }}px). Največja dovoljena višina je {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Višina slike je premajhna ({{ height }}px). Najmanjša predvidena višina je {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Ta vrednost bi morala biti trenutno uporabnikovo geslo.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Ta vrednost bi morala imeti točno {{ limit }} znak.|Ta vrednost bi morala imeti točno {{ limit }} znaka.|Ta vrednost bi morala imeti točno {{ limit }} znake.|Ta vrednost bi morala imeti točno {{ limit }} znakov.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Datoteka je bila le delno naložena.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Nobena datoteka ni bila naložena.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Začasna mapa ni nastavljena v php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Začasne datoteke ni bilo mogoče zapisati na disk.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>PHP razširitev je vzrok, da nalaganje ni uspelo.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Ta zbirka bi morala vsebovati {{ limit }} element ali več.|Ta zbirka bi morala vsebovati {{ limit }} elementa ali več.|Ta zbirka bi morala vsebovati {{ limit }} elemente ali več.|Ta zbirka bi morala vsebovati {{ limit }} elementov ali več.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Ta zbirka bi morala vsebovati {{ limit }} element ali manj.|Ta zbirka bi morala vsebovati {{ limit }} elementa ali manj.|Ta zbirka bi morala vsebovati {{ limit }} elemente ali manj.|Ta zbirka bi morala vsebovati {{ limit }} elementov ali manj.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Ta zbirka bi morala vsebovati točno {{ limit }} element.|Ta zbirka bi morala vsebovati točno {{ limit }} elementa.|Ta zbirka bi morala vsebovati točno {{ limit }} elemente.|Ta zbirka bi morala vsebovati točno {{ limit }} elementov.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Neveljavna številka kartice.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Nepodprti tip kartice ali neveljavna številka kartice.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>To ni veljavna mednarodna številka bančnega računa (IBAN).</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Neveljavna vrednost po ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Neveljavna vrednost po ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Neveljavna vrednost po ISBN-10 ali po ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Neveljavna vrednost ISSN.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Ta vrednost ni veljavna valuta.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Ta vrednost bi morala biti enaka {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Ta vrednost bi morala biti večja od {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Ta vrednost bi morala biti večja ali enaka {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Ta vrednost bi morala biti identična {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Ta vrednost bi morala biti manjša od {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Ta vrednost bi morala biti manjša ali enaka {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Ta vrednost ne bi smela biti enaka {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Ta vrednost ne bi smela biti identična {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Questo valore dovrebbe essere falso.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Questo valore dovrebbe essere vero.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Questo valore dovrebbe essere di tipo {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Questo valore dovrebbe essere vuoto.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Questo valore dovrebbe essere una delle opzioni disponibili.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Si dovrebbe selezionare almeno {{ limit }} opzione.|Si dovrebbero selezionare almeno {{ limit }} opzioni.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Si dovrebbe selezionare al massimo {{ limit }} opzione.|Si dovrebbero selezionare al massimo {{ limit }} opzioni.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Uno o più valori inseriti non sono validi.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>I campi {{ fields }} non sono validi.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>I campi {{ fields }} sono mancanti.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Questo valore non è una data valida.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Questo valore non è una data e ora valida.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Questo valore non è un indirizzo email valido.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Non è stato possibile trovare il file.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Il file non è leggibile.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Il file è troppo grande ({{ size }} {{ suffix }}). La dimensione massima consentita è {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Il mime type del file non è valido ({{ type }}). I tipi permessi sono {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Questo valore dovrebbe essere {{ limit }} o inferiore.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Questo valore è troppo lungo. Dovrebbe essere al massimo di {{ limit }} carattere.|Questo valore è troppo lungo. Dovrebbe essere al massimo di {{ limit }} caratteri.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Questo valore dovrebbe essere {{ limit }} o superiore.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Questo valore è troppo corto. Dovrebbe essere almeno di {{ limit }} carattere.|Questo valore è troppo corto. Dovrebbe essere almeno di {{ limit }} caratteri.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Questo valore non dovrebbe essere vuoto.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Questo valore non dovrebbe essere nullo.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Questo valore dovrebbe essere nullo.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Questo valore non è valido.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Questo valore non è un'ora valida.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Questo valore non è un URL valido.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>I due valori dovrebbero essere uguali.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Il file è troppo grande. La dimensione massima è {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Il file è troppo grande.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Il file non può essere caricato.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Questo valore dovrebbe essere un numero.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Questo file non è una immagine valida.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Questo valore non è un indirizzo IP valido.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Questo valore non è una lingua valida.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Questo valore non è una impostazione regionale valida.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Questo valore non è una nazione valida.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Questo valore è già stato utilizzato.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>La dimensione dell'immagine non può essere determinata.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>La larghezza dell'immagine è troppo grande ({{ width }}px). La larghezza massima è di {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>La larghezza dell'immagine è troppo piccola ({{ width }}px). La larghezza minima è di {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>L'altezza dell'immagine è troppo grande ({{ height }}px). L'altezza massima è di {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>L'altezza dell'immagine è troppo piccola ({{ height }}px). L'altezza minima è di {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Questo valore dovrebbe essere la password attuale dell'utente.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Questo valore dovrebbe contenere esattamente {{ limit }} carattere.|Questo valore dovrebbe contenere esattamente {{ limit }} caratteri.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Il file è stato caricato solo parzialmente.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Nessun file è stato caricato.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Nessuna cartella temporanea è stata configurata nel php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Impossibile scrivere il file temporaneo sul disco.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Un'estensione PHP ha causato il fallimento del caricamento.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Questa collezione dovrebbe contenere almeno {{ limit }} elemento.|Questa collezione dovrebbe contenere almeno {{ limit }} elementi.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Questa collezione dovrebbe contenere massimo {{ limit }} elemento.|Questa collezione dovrebbe contenere massimo {{ limit }} elementi.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Questa collezione dovrebbe contenere esattamente {{ limit }} elemento.|Questa collezione dovrebbe contenere esattamente {{ limit }} elementi.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Numero di carta non valido.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Tipo di carta non supportato o numero non valido.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Questo valore non è un IBAN (International Bank Account Number) valido.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Questo valore non è un codice ISBN-10 valido.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Questo valore non è un codice ISBN-13 valido.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Questo valore non è un codice ISBN-10 o ISBN-13 valido.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Questo valore non è un codice ISSN valido.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Questo valore non è una valuta valida.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
﻿<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Значення повинно бути Ні.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Значення повинно бути Так.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Тип значення повинен бути {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Значення повинно бути пустим.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Обране вами значення недопустиме.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Ви повинні обрати хоча б {{ limit }} варіант.|Ви повинні обрати хоча б {{ limit }} варіанти.|Ви повинні обрати хоча б {{ limit }} варіантів.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Ви повинні обрати не більше ніж {{ limit }} варіантів</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Одне або кілька заданих значень є недопустимі.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Поля {{ fields }} не очікувалися.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Поля {{ fields }} відсутні.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Дане значення не є вірною датою.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Дане значення дати та часу недопустиме.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Значення адреси электронної пошти недопустиме.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Файл не знайдено.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Файл не читається.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Файл занадто великий ({{ size }} {{ suffix }}). Дозволений максимальний розмір {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>MIME-тип файлу недопустимий ({{ type }}). Допустимі MIME-типи файлів {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Значення повинно бути {{ limit }} або менше.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Значення занадто довге. Повинно бути рівне {{ limit }} символу або менше.|Значення занадто довге. Повинно бути рівне {{ limit }} символам або менше.|Значення занадто довге. Повинно бути рівне {{ limit }} символам або менше.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Значення повинно бути {{ limit }} або більше.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Значення занадто коротке. Повинно бути рівне {{ limit }} символу або більше.|Значення занадто коротке. Повинно бути рівне {{ limit }} символам або більше.|Значення занадто коротке. Повинно бути рівне {{ limit }} символам або більше.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Значення не повинно бути пустим.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Значення не повинно бути null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Значення повинно бути null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Значення недопустиме.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Значення часу недопустиме.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Значення URL недопустиме.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Обидва занчення повинні бути одинаковими.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Файл занадто великий. Максимальний допустимий розмір {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Файл занадто великий.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Файл не можливо завантажити.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Значення має бути допустимим числом.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Цей файл не є допустимим форматом зображення.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Це некоректна IP адреса.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Це некоректна мова.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Це некоректна локалізація.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Це некоректна країна.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Це значення вже використовується.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Не вдалося визначити розмір зображення.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Ширина зображення занадто велика ({{ width }}px). Максимально допустима ширина {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Ширина зображення занадто мала ({{ width }}px). Мінімально допустима ширина {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Висота зображення занадто велика ({{ height }}px). Максимально допустима висота {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Висота зображення занадто мала ({{ height }}px). Мінімально допустима висота {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Значення має бути поточним паролем користувача.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Значення повиино бути рівним {{ limit }} символу.|Значення повиино бути рівним {{ limit }} символам.|Значення повиино бути рівним {{ limit }} символам.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Файл був завантажений лише частково.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Файл не був завантажений.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Не налаштована тимчасова директорія в php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Неможливо записати тимчасовий файл на диск.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Розширення PHP викликало помилку при завантаженні.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Ця колекція повинна містити {{ limit }} елемент чи більше.|Ця колекція повинна містити {{ limit }} елемента чи більше.|Ця колекція повинна містити {{ limit }} елементів чи більше.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Ця колекція повинна містити {{ limit }} елемент чи менше.|Ця колекція повинна містити {{ limit }} елемента чи менше.|Ця колекція повинна містити {{ limit }} елементов чи менше.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Ця колекція повинна містити рівно {{ limit }} елемент.|Ця колекція повинна містити рівно {{ limit }} елемента.|Ця колекція повинна містити рівно {{ limit }} елементів.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Невірний номер карти.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Непідтримуваний тип карти або невірний номер карти.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Це не дійсний міжнародний номер банківського рахунку (IBAN).</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Значення не у форматі ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Значення не у форматі ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Значення не відповідає форматам ISBN-10 та ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Значення має невірний формат ISSN.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Значення має невірний формат валюти.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Значення повинно дорівнювати {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Значення має бути більше ніж {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Значення має бути більше або дорівнювати {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Значення має бути ідентичним {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Значення повинно бути менше ніж {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Значення повинно бути менше або дорівнювати {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Значення не повинно дорівнювати  {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Значення не повинно бути ідентичним {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Cette valeur doit être fausse.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Cette valeur doit être vraie.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Cette valeur doit être de type {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Cette valeur doit être vide.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Cette valeur doit être l'un des choix proposés.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Vous devez sélectionner au moins {{ limit }} choix.|Vous devez sélectionner au moins {{ limit }} choix.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Vous devez sélectionner au maximum {{ limit }} choix.|Vous devez sélectionner au maximum {{ limit }} choix.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Une ou plusieurs des valeurs soumises sont invalides.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Les champs {{ fields }} n'ont pas été prévus.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Les champs {{ fields }} sont manquants.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Cette valeur n'est pas une date valide.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Cette valeur n'est pas une date valide.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Cette valeur n'est pas une adresse email valide.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Le fichier n'a pas été trouvé.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Le fichier n'est pas lisible.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Le fichier est trop volumineux ({{ size }} {{ suffix }}). Sa taille ne doit pas dépasser {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Le type du fichier est invalide ({{ type }}). Les types autorisés sont {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Cette valeur doit être inférieure ou égale à {{ limit }}.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Cette chaine est trop longue. Elle doit avoir au maximum {{ limit }} caractère.|Cette chaine est trop longue. Elle doit avoir au maximum {{ limit }} caractères.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Cette valeur doit être supérieure ou égale à {{ limit }}.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Cette chaine est trop courte. Elle doit avoir au minimum {{ limit }} caractère.|Cette chaine est trop courte. Elle doit avoir au minimum {{ limit }} caractères.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Cette valeur ne doit pas être vide.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Cette valeur ne doit pas être nulle.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Cette valeur doit être nulle.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Cette valeur n'est pas valide.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Cette valeur n'est pas une heure valide.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Cette valeur n'est pas une URL valide.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Les deux valeurs doivent être identiques.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Le fichier est trop volumineux. Sa taille ne doit pas dépasser {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Le fichier est trop volumineux.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Le téléchargement de ce fichier est impossible.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Cette valeur doit être un nombre.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Ce fichier n'est pas une image valide.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Cette adresse IP n'est pas valide.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Cette langue n'est pas valide.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Ce paramètre régional n'est pas valide.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Ce pays n'est pas valide.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Cette valeur est déjà utilisée.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>La taille de l'image n'a pas pu être détectée.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>La largeur de l'image est trop grande ({{ width }}px). La largeur maximale autorisée est de {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>La largeur de l'image est trop petite ({{ width }}px). La largeur minimale attendue est de {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>La hauteur de l'image est trop grande ({{ height }}px). La hauteur maximale autorisée est de {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>La hauteur de l'image est trop petite ({{ height }}px). La hauteur minimale attendue est de {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Cette valeur doit être le mot de passe actuel de l'utilisateur.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Cette chaine doit avoir exactement {{ limit }} caractère.|Cette chaine doit avoir exactement {{ limit }} caractères.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Le fichier a été partiellement transféré.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Aucun fichier n'a été transféré.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Aucun répertoire temporaire n'a été configuré dans le php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Impossible d'écrire le fichier temporaire sur le disque.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Une extension PHP a empêché le transfert du fichier.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Cette collection doit contenir {{ limit }} élément ou plus.|Cette collection doit contenir {{ limit }} éléments ou plus.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Cette collection doit contenir {{ limit }} élément ou moins.|Cette collection doit contenir {{ limit }} éléments ou moins.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Cette collection doit contenir exactement {{ limit }} élément.|Cette collection doit contenir exactement {{ limit }} éléments.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Numéro de carte invalide.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Type de carte non supporté ou numéro invalide.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Le numéro IBAN (International Bank Account Number) saisi n'est pas valide.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Cette valeur n'est pas un code ISBN-10 valide.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Cette valeur n'est pas un code ISBN-13 valide.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Cette valeur n'est ni un code ISBN-10, ni un code ISBN-13 valide.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Cette valeur n'est pas un code ISSN valide.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Cette valeur n'est pas une devise valide.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Cette valeur doit être égale à {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Cette valeur doit être supérieure à {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Cette valeur doit être supérieure ou égale à {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Cette valeur doit être identique à {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Cette valeur doit être inférieure à {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Cette valeur doit être inférieure ou égale à {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Cette valeur ne doit pas être égale à {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Cette valeur ne doit pas être identique à {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Este valor deveria ser falso.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Este valor deveria ser verdadeiro.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Este valor deveria ser do tipo {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Este valor deveria ser vazio.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>O valor selecionado não é uma opção válida.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Você deveria selecionar {{ limit }} opção no mínimo.|Você deveria selecionar {{ limit }} opções no mínimo.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Você deve selecionar, no máximo {{ limit }} opção.|Você deve selecionar, no máximo {{ limit }} opções.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Um ou mais dos valores introduzidos não são válidos.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Os campos {{ fields }} não eram esperados.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Os campos {{ fields }} estão ausentes.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Este valor não é uma data válida.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Este valor não é uma data-hora válida.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Este valor não é um endereço de e-mail válido.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>O arquivo não pôde ser encontrado.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>O arquivo não pôde ser lido.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>O arquivo é muito grande ({{ size }} {{ suffix }}). O tamanho máximo permitido é de {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>O tipo mime do arquivo é inválido ({{ type }}). Os tipos mime permitidos são {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Este valor deveria ser {{ limit }} ou menor.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>O valor é muito longo. Deveria ter {{ limit }} caracteres ou menos.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Este valor deveria ser {{ limit }} ou mais.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>O valor é muito curto. Deveria de ter {{ limit }} caractere ou mais.|O valor é muito curto. Deveria de ter {{ limit }} caracteres ou mais.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Este valor não deveria ser branco/vazio.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Este valor não deveria ser nulo.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Este valor deveria ser nulo.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Este valor não é válido.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Este valor não é uma hora válida.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Este valor não é um URL válido.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Os dois valores deveriam ser iguais.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>O arquivo é muito grande. O tamanho máximo permitido é de {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>O ficheiro é muito grande.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Não foi possível carregar o ficheiro.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Este valor deveria de ser um número válido.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Este ficheito não é uma imagem.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Este endereço de IP não é válido.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Este valor não é uma linguagem válida.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Este valor não é um 'locale' válido.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Este valor não é um País válido.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Este valor já está a ser usado.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>O tamanho da imagem não foi detetado.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>A largura da imagem ({{ width }}px) é muito grande. A largura máxima da imagem é: {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>A largura da imagem ({{ width }}px) é muito pequena. A largura miníma da imagem é de: {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>A altura da imagem ({{ height }}px) é muito grande. A altura máxima da imagem é de: {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>A altura da imagem ({{ height }}px) é muito pequena. A altura miníma da imagem é de: {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Este valor deveria de ser a password atual do utilizador.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Este valor tem de ter exatamente {{ limit }} carateres.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Só foi enviado parte do ficheiro.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Nenhum ficheiro foi enviado.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Não existe nenhum directório temporária configurado no ficheiro php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Não foi possível escrever ficheiros temporários no disco.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Uma extensão PHP causou a falha no envio.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Esta coleção deve conter {{ limit }} elemento ou mais.|Esta coleção deve conter {{ limit }} elementos ou mais.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Esta coleção deve conter {{ limit }} elemento ou menos.|Esta coleção deve conter {{ limit }} elementos ou menos.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Esta coleção deve conter exatamente {{ limit }} elemento.|Esta coleção deve conter exatamente {{ limit }} elementos.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Número de cartão inválido.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Tipo de cartão não suportado ou número de cartão inválido.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Este não é um Número Internacional de Conta Bancária (IBAN) válido.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Este valor não é um ISBN-10 válido.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Este valor não é um ISBN-13 válido.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Este valor não é um ISBN-10 ou ISBN-13 válido.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Este valor não é um ISSN válido.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Este não é um valor monetário válido.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Este valor deve ser igual a {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Este valor deve ser superior a {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Este valor deve ser igual ou superior a {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Este valor deve ser idêntico a {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Este valor deve ser inferior a {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Este valor deve ser igual ou inferior a {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Este valor não deve ser igual a {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Este valor não deve ser idêntico a {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Ova vrijednost treba biti netočna (false).</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Ova vrijednost treba biti točna (true).</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Ova vrijednost treba biti tipa {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Ova vrijednost treba biti prazna.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Ova vrijednost treba biti jedna od ponuđenih.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Izaberite barem {{ limit }} mogućnosti.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Izaberite najviše {{ limit }} mogućnosti.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Jedna ili više danih vrijednosti nije ispravna.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Polja {{ fields }} nisu bila očekivana.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Polja {{ fields }} nedostaju.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Ova vrijednost nije ispravan datum.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Ova vrijednost nije ispravan datum-vrijeme.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Ova vrijednost nije ispravna e-mail adresa.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Datoteka ne može biti pronađena.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Datoteka nije čitljiva.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Datoteka je prevelika ({{ size }} {{ suffix }}). Najveća dozvoljena veličina je {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Mime tip datoteke nije ispravan ({{ type }}). Dozvoljeni mime tipovi su {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Ova vrijednost treba biti {{ limit }} ili manje.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Ova vrijednost je predugačka. Treba imati {{ limit }} znakova ili manje.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Ova vrijednost treba biti {{ limit }} ili više.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Ova vrijednost je prekratka. Treba imati {{ limit }} znakova ili više.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Ova vrijednost ne smije biti prazna.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Ova vrijednost ne smije biti null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Ova vrijednost treba biti null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Ova vrijednost nije ispravna.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Ova vrijednost nije ispravno vrijeme.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Ova vrijednost nije ispravan URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Obje vrijednosti trebaju biti jednake.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Ova datoteka je prevelika. Najveća dozvoljena veličina je {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Ova datoteka je prevelika.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Ova datoteka ne može biti prenesena.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Ova vrijednost treba biti ispravan broj.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Ova datoteka nije ispravna slika.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Ovo nije ispravna IP adresa.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Ova vrijednost nije ispravan jezik.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Ova vrijednost nije ispravana regionalna oznaka.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Ova vrijednost nije ispravna zemlja.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Ova vrijednost je već iskorištena.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Veličina slike se ne može odrediti.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Širina slike je prevelika ({{ width }}px). Najveća dozvoljena širina je {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Širina slike je premala ({{ width }}px). Najmanja dozvoljena širina je {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Visina slike je prevelika ({{ height }}px). Najveća dozvoljena visina je {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Visina slike je premala ({{ height }}px). Najmanja dozvoljena visina je {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Ova vrijednost treba biti trenutna korisnička lozinka.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Ova vrijednost treba imati točno {{ limit }} znakova.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Datoteka je samo djelomično prenesena.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Niti jedna datoteka nije prenesena.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>U php.ini datoteci nije konfiguriran privremeni folder.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Ne mogu zapisati privremenu datoteku na disk.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Prijenos datoteke nije uspio zbog PHP ekstenzije.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Ova kolekcija treba sadržavati {{ limit }} ili više elemenata.|Ova kolekcija treba sadržavati {{ limit }} ili više elemenata.|Ova kolekcija treba sadržavati {{ limit }} ili više elemenata.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Ova kolekcija treba sadržavati {{ limit }} ili manje elemenata.|Ova kolekcija treba sadržavati {{ limit }} ili manje elemenata.|Ova kolekcija treba sadržavati {{ limit }} ili manje elemenata.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Ova kolekcija treba sadržavati točno {{ limit }} element.|Ova kolekcija treba sadržavati točno {{ limit }} elementa.|Ova kolekcija treba sadržavati točno {{ limit }} elemenata.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Neispravan broj kartice.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Neispravan broj kartice ili tip kartice nije podržan.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Ova vrijednost nije ispravan međunarodni broj bankovnog računa (IBAN).</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Ova vrijednost nije ispravan ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Ova vrijednost nije ispravan ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Ova vrijednost nije ispravan ISBN-10 niti ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Ova vrijednost nije ispravan ISSN.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>This value should be false.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>This value should be true.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>This value should be of type {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>This value should be blank.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>The value you selected is not a valid choice.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>One or more of the given values is invalid.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>The fields {{ fields }} were not expected.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>The fields {{ fields }} are missing.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>This value is not a valid date.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>This value is not a valid datetime.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>This value is not a valid email address.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>The file could not be found.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>The file is not readable.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>This value should be {{ limit }} or less.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>This value should be {{ limit }} or more.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>This value should not be blank.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>This value should not be null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>This value should be null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>This value is not valid.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>This value is not a valid time.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>This value is not a valid URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>The two values should be equal.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>The file is too large.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>The file could not be uploaded.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>This value should be a valid number.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>This file is not a valid image.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>This is not a valid IP address.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>This value is not a valid language.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>This value is not a valid locale.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>This value is not a valid country.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>This value is already used.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>The size of the image could not be detected.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>This value should be the user current password.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>The file was only partially uploaded.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>No file was uploaded.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>No temporary folder was configured in php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Cannot write temporary file to disk.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>A PHP extension caused the upload to fail.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Invalid card number.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Unsupported card type or invalid card number.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>This is not a valid International Bank Account Number (IBAN).</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>This value is not a valid ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>This value is not a valid ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>This value is neither a valid ISBN-10 nor a valid ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>This value is not a valid ISSN.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>This value is not a valid currency.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>This value should be equal to {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>This value should be greater than {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>This value should be greater than or equal to {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>This value should be less than {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>This value should be less than or equal to {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>This value should not be equal to {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Este valor debería ser falso.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Este valor debería ser verdadeiro.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Este valor debería ser de tipo {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Este valor debería estar baleiro.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>O valor seleccionado non é unha opción válida.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Debe seleccionar polo menos {{ limit }} opción.|Debe seleccionar polo menos {{ limit }} opcions.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Debe seleccionar como máximo {{ limit }} opción.|Debe seleccionar como máximo {{ limit }} opcions.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Un ou máis dos valores indicados non son válidos.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Non se esperaban os campos {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Faltan os campos {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Este valor non é unha data válida.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Este valor non é unha data e hora válidas.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Este valor non é unha dirección de correo electrónico válida.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Non se puido atopar o arquivo.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>O arquivo non se pode ler.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>O arquivo é demasiado grande ({{ size }} {{ suffix }}). O tamaño máximo permitido é {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>O tipo mime do arquivo non é válido ({{ type }}). Os tipos mime válidos son {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Este valor debería ser {{ limit }} ou menos.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Este valor é demasiado longo. Debería ter {{ limit }} carácter ou menos.|Este valor é demasiado longo. Debería ter {{ limit }} caracteres ou menos.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Este valor debería ser {{ limit }} ou máis.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Este valor é demasiado curto. Debería ter {{ limit }} carácter ou máis.|Este valor é demasiado corto. Debería ter {{ limit }} caracteres ou máis.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Este valor non debería estar baleiro.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Este valor non debería ser null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Este valor debería ser null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Este valor non é válido.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Este valor non é unha hora válida.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Este valor non é unha URL válida.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Os dous valores deberían ser iguais.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>O arquivo é demasiado grande. O tamaño máximo permitido é {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>O arquivo é demasiado grande.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>No se puido cargar o arquivo.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Este valor debería ser un número válido.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>O arquivo non é unha imaxe válida.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Isto non é unha dirección IP válida.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Este valor non é un idioma válido.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Este valor non é unha localización válida.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Este valor non é un país válido.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Este valor xa está a ser empregado.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Non se puido determinar o tamaño da imaxe.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>A largura da imaxe é demasiado grande ({{ width }}px). A largura máxima permitida son {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>A largura da imaxe é demasiado pequena ({{ width }}px). A largura mínima requerida son {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>A altura da imaxe é demasiado grande ({{ height }}px). A altura máxima permitida son {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>A altura da imaxe é demasiado pequena ({{ height }}px). A altura mínima requerida son {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Este valor debería ser a contrasinal actual do usuario.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Este valor debería ter exactamente {{ limit }} carácter.|Este valor debería ter exactamente {{ limit }} caracteres.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>O arquivo foi só subido parcialmente.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Non se subiu ningún arquivo.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Ningunha carpeta temporal foi configurada en php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Non se puido escribir o arquivo temporal no disco.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Unha extensión de PHP provocou que a subida fallara.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Esta colección debe conter {{ limit }} elemento ou máis.|Esta colección debe conter {{ limit }} elementos ou máis.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Esta colección debe conter {{ limit }} elemento ou menos.|Esta colección debe conter {{ limit }} elementos ou menos.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Esta colección debe conter exactamente {{ limit }} elemento.|Esta colección debe conter exactamente {{ limit }} elementos.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Número de tarxeta non válido.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Tipo de tarxeta non soportado ou número de tarxeta non válido.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Este valor non é un International Bank Account Number (IBAN) válido.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Este valor non é un ISBN-10 válido.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Este valor non é un ISBN-13 válido.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Este valor non é nin un ISBN-10 válido nin un ISBN-13 válido.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Este valor non é un ISSN válido.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Este valor non é unha moeda válida.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Este valor debería ser igual a {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Este valor debería ser maior que {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Este valor debería ser maior ou igual que {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Este valor debería ser identico a {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Este valor debería ser menor que {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Este valor debería ser menor ou igual que {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Este valor non debería ser igual a {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Este valor non debería ser identico a {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Nilai ini harus bernilai salah.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Nilai ini harus bernilai benar.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Nilai ini harus bertipe {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Nilai ini harus kosong.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Nilai yang dipilih tidak tepat.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Anda harus memilih paling tidak {{ limit }} pilihan.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Anda harus memilih paling banyak {{ limit }} pilihan.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Satu atau lebih nilai yang diberikan tidak sah.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Kolom {{ fields }} tidak seperti yang diharapkan.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Kolom {{ fields }} hilang.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Nilai ini bukan merupakan tanggal yang sah.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Nilai ini bukan merupakan tanggal dan waktu yang sah.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Nilai ini bukan alamat email yang sah.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Berkas tidak ditemukan.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Berkas tidak bisa dibaca.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Ukuran berkas terlalu besar ({{ size }} {{ suffix }}). Ukuran maksimum yang diizinkan adalah {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Jenis berkas ({{ type }}) tidak sah. Jenis berkas yang diijinkan adalah {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Nilai ini harus {{ limit }} atau kurang.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Nilai ini terlalu panjang. Seharusnya {{ limit }} karakter atau kurang.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Nilai ini harus {{ limit }} atau lebih.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Nilai ini terlalu pendek. Seharusnya {{ limit }} karakter atau lebih.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Nilai ini tidak boleh kosong.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Nilai ini tidak boleh 'null'.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Nilai ini harus 'null'.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Nilai ini tidak sah.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Nilai ini bukan merupakan waktu yang sah.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Nilai ini bukan URL yang sah.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Isi keduanya harus sama.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Ukuran berkas terlalu besar. Ukuran maksimum yang diijinkan adalah {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Ukuran berkas terlalu besar.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Berkas tidak dapat diunggah.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Nilai ini harus angka yang sah.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Berkas ini tidak termasuk gambar.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Ini bukan alamat IP yang sah.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Nilai ini bukan bahasa yang sah.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Nilai ini bukan lokal yang sah.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Nilai ini bukan negara yang sah.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Nilai ini sudah digunakan.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Ukuran dari gambar tidak bisa dideteksi.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Lebar gambar terlalu besar ({{ width }}px). Ukuran lebar maksimum adalah {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Lebar gambar terlalu kecil ({{ width}}px). Ukuran lebar minimum yang diharapkan adalah {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Tinggi gambar terlalu besar ({{ height }}px). Ukuran tinggi maksimum adalah {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Tinggi gambar terlalu kecil ({{ height }}px). Ukuran tinggi minimum yang diharapkan adalah {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Nilai ini harus kata sandi pengguna saat ini.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Nilai ini harus memiliki tepat {{ limit }} karakter.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Berkas hanya terunggah sebagian.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Tidak ada berkas terunggah.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Direktori sementara tidak dikonfiguasi pada php.ini</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Tidak dapat menuliskan berkas sementara ke dalam media penyimpanan.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Sebuah ekstensi PHP menyebabkan kegagalan unggah.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Kumpulan ini harus memiliki {{ limit }} elemen atau lebih.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Kumpulan ini harus memiliki kurang dari {{ limit }} elemen.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Kumpulan ini harus memiliki tepat {{ limit }} elemen.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Nomor kartu tidak sah.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Jenis kartu tidak didukung atau nomor kartu tidak sah.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Værdien skal være falsk.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Værdien skal være sand.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Værdien skal være af typen {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Værdien skal være blank.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Værdien skal være en af de givne muligheder.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Du skal vælge mindst {{ limit }} muligheder.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Du kan højest vælge {{ limit }} muligheder.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>En eller flere af de oplyste værdier er ugyldige.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Felterne {{ fields }} var ikke forventet.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Felterne {{ fields }} mangler.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Værdien er ikke en gyldig dato.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Værdien er ikke en gyldig dato og tid.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Værdien er ikke en gyldig e-mail adresse.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Filen kunne ikke findes.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Filen kan ikke læses.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Filen er for stor ({{ size }} {{ suffix }}). Tilladte maksimale størrelse {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Mimetypen af filen er ugyldig ({{ type }}). Tilladte mimetyper er {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Værdien skal være {{ limit }} eller mindre.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Værdien er for lang. Den skal have {{ limit }} bogstaver eller mindre.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Værdien skal være {{ limit }} eller mere.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Værdien er for kort. Den skal have {{ limit }} tegn eller flere.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Værdien må ikke være blank.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Værdien må ikke være tom (null).</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Værdien skal være tom (null).</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Værdien er ikke gyldig.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Værdien er ikke en gyldig tid.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Værdien er ikke en gyldig URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>De to værdier skal være ens.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Filen er for stor. Den maksimale størrelse er {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Filen er for stor.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Filen kunne ikke blive uploadet.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Værdien skal være et gyldigt tal.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Filen er ikke gyldigt billede.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Dette er ikke en gyldig IP adresse.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Værdien er ikke et gyldigt sprog.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Værdien er ikke en gyldig lokalitet.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Værdien er ikke et gyldigt land.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Værdien er allerede i brug.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Størrelsen på billedet kunne ikke detekteres.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Billedbredden er for stor ({{ width }}px). Tilladt maksimumsbredde er {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Billedebredden er for lille ({{ width }}px). Forventet minimumshøjde er {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Billedhøjden er for stor ({{ height }}px). Tilladt maksimumshøjde er {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Billedhøjden er for lille ({{ height }}px). Forventet minimumshøjde er {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Værdien skal være brugerens nuværende password.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Værdien skal have præcis {{ limit }} tegn.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Filen var kun delvis uploadet.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Ingen fil blev uploadet.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Ingen midlertidig mappe er konfigureret i php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Kan ikke skrive midlertidig fil til disk.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>En PHP udvidelse forårsagede fejl i upload.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Denne samling skal indeholde {{ limit }} element eller flere.|Denne samling skal indeholde {{ limit }} elementer eller flere.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Denne samling skal indeholde {{ limit }} element eller mindre.|Denne samling skal indeholde {{ limit }} elementer eller mindre.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Denne samling skal indeholde præcis {{ limit }} element.|Denne samling skal indeholde præcis {{ limit }} elementer.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Ugyldigt kortnummer.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Ikke-understøttet korttype eller ugyldigt kortnummer.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Det er ikke en gyldig International Bank Account Number (IBAN).</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Værdien er ikke en gyldig ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Værdien er ikke en gyldig ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Værdien er hverken en gyldig ISBN-10 eller en gyldig ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Værdien er ikke en gyldig ISSN.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
﻿<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Արժեքը պետք է լինի կեղծ.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Արժեքը պետք է լինի ճշմարիտ.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Արժեքը պետք է լինի {{ type }} տեսակի.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Արժեքը պետք է լինի դատարկ.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Ձեր ընտրած արժեքը անթույլատրելի է.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Դուք պետք է ընտրեք ամենաքիչը {{ limit }} տարբերակներ.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Դուք պետք է ընտրեք ոչ ավելի քան {{ limit }} տարբերակներ.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Մեկ կամ ավելի տրված արժեքները անթույլատրելի են.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>{{ fields }} տողերը չէին սպասվում.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>{{ fields }} տողերը բացակայում են.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Արժեքը սխալ ամսաթիվ է.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Ամսաթվի և ժամանակի արժեքը անթույլատրելի է.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Էլ-փոստի արժեքը անթույլատրելի է.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Ֆայլը չի գտնվել.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Ֆայլը անընթեռնելի է.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Ֆայլը չափազանց մեծ է ({{ size }} {{ suffix }}): Մաքսիմալ թույլատրելի չափսը՝ {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>MIME-տեսակը անթույլատրելի է({{ type }}): Ֆայլերի թույլատրելի MIME-տեսակներն են: {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Արժեքը պետք է լինի {{ limit }} կամ փոքր.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Արժեքը չափազանց երկար է: Պետք է լինի {{ limit }} կամ ավել սիմվոլներ.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Արժեքը պետ է լինի {{ limit }} կամ շատ.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Արժեքը չափազանց կարճ է: Պետք է լինի {{ limit }} կամ ավելի սիմվոլներ.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Արժեքը չպետք է դատարկ լինի.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Արժեքը չպետք է լինի null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Արժեքը պետք է լինի null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Անթույլատրելի արժեք.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Ժամանակի արժեքը անթույլատրելի է.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Արժեքը  URL  չէ.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Երկու արժեքները պետք է նույնը լինեն.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Ֆայլը չափազանց մեծ է: Մաքսիմալ թույլատրելի չափսը {{ limit }} {{ suffix }} է.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Ֆայլը չափազանց մեծ է.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Ֆայլը չի կարող բեռնվել.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Արժեքը պետք է լինի թիվ.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This value is not a valid country.</source>
                <target>Արժեքը պետք է լինի երկիր.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This file is not a valid image.</source>
                <target>Ֆայլը նկարի թույլատրելի ֆորմատ չէ.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This is not a valid IP address.</source>
                <target>Արժեքը թույլատրելի IP հասցե չէ.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid language.</source>
                <target>Արժեքը թույլատրելի լեզու չէ.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid locale.</source>
                <target>Արժեքը չի հանդիսանում թույլատրելի տեղայնացում.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Այդ արժեքը արդեն օգտագործվում է.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Նկարի չափսերը չստացվեց որոշել.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Նկարի լայնությունը չափազանց մեծ է({{ width }}px). Մաքսիմալ չափն է {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Նկարի լայնությունը չափազանց փոքր է ({{ width }}px). Մինիմալ չափն է {{ min_ width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Նկարի բարձրությունը չափազանց մեծ է ({{ height }}px). Մաքսիմալ չափն է {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Նկարի բարձրությունը չափազանց փոքր է ({{ height }}px). Մինիմալ չափն է {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Այս արժեքը պետք է լինի օգտագործողի ներկա ծածկագիրը.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Այս արժեքը պետք է ունենա ճիշտ {{ limit }} սիմվոլներ.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Arvon tulee olla epätosi.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Arvon tulee olla tosi.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Arvon tulee olla tyyppiä {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Arvon tulee olla tyhjä.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Arvon tulee olla yksi annetuista vaihtoehdoista.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Sinun tulee valita vähintään {{ limit }} vaihtoehtoa.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Sinun tulee valitan enintään {{ limit }} vaihtoehtoa.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Yksi tai useampi annetuista arvoista on virheellinen.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Odottamattomia kenttiä {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Kentät {{ fields }} puuttuvat.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Annettu arvo ei ole kelvollinen päivämäärä.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Annettu arvo ei ole kelvollinen päivämäärä ja kellonaika.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Annettu arvo ei ole kelvollinen sähköpostiosoite.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Tiedostoa ei löydy.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Tiedostoa ei voida lukea.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Tiedostonkoko ({{ size }} {{ suffix }}) on liian iso. Suurin sallittu tiedostonkoko on {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Tiedostotyyppi ({{ type }}) on virheellinen. Sallittuja tiedostotyyppejä ovat {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Arvon tulee olla {{ limit }} tai vähemmän.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Liian pitkä syöte. Syöte saa olla enintään {{ limit }} merkkiä.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Arvon tulee olla {{ limit }} tai enemmän.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Liian lyhyt syöte. Syötteen tulee olla vähintään {{ limit }} merkkiä.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Kenttä ei voi olla tyhjä.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Syöte ei voi olla null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Syötteen tulee olla null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Virheellinen arvo.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Annettu arvo ei ole kelvollinen kellonaika.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Annettu arvo ei ole kelvollinen URL-osoite.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Kahden annetun arvon tulee olla samat.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Annettu tiedosto on liian iso. Suurin sallittu tiedostokoko on {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Tiedosto on liian iso.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Tiedoston siirto epäonnistui.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Tämän arvon tulee olla numero.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Tämä tiedosto ei ole kelvollinen kuva.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Tämä ei ole kelvollinen IP-osoite.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Tämä arvo ei ole kelvollinen kieli.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Tämä arvo ei ole kelvollinen kieli- ja alueasetus (locale).</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Tämä arvo ei ole kelvollinen maa.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Tämä arvo on jo käytetty.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Kuvan kokoa ei voitu tunnistaa.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Kuva on liian leveä ({{ width }}px). Sallittu maksimileveys on {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Kuva on liian kapea ({{ width }}px). Leveyden tulisi olla vähintään {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Kuva on liian korkea ({{ width }}px). Sallittu maksimikorkeus on {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Kuva on liian matala ({{ height }}px). Korkeuden tulisi olla vähintään {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Tämän arvon tulisi olla käyttäjän tämänhetkinen salasana.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Tämän arvon tulisi olla tasan yhden merkin pituinen.|Tämän arvon tulisi olla tasan {{ limit }} merkkiä pitkä.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Tiedosto ladattiin vain osittain.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Tiedostoa ei ladattu.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Väliaikaishakemistoa ei ole asetettu php.ini -tiedostoon.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Väliaikaistiedostoa ei voitu kirjoittaa levylle.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>PHP-laajennoksen vuoksi tiedoston lataus epäonnistui.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Tässä ryhmässä tulisi olla yksi tai useampi elementti.|Tässä ryhmässä tulisi olla vähintään {{ limit }} elementtiä.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Tässä ryhmässä tulisi olla enintään yksi elementti.|Tässä ryhmässä tulisi olla enintään {{ limit }} elementtiä.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Tässä ryhmässä tulisi olla tasan yksi elementti.|Tässä ryhmässä tulisi olla enintään {{ limit }} elementtiä.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Virheellinen korttinumero.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Tätä korttityyppiä ei tueta tai korttinumero on virheellinen.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Hierdie waarde moet vals wees.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Hierdie waarde moet waar wees.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Hierdie waarde moet van die soort {{type}} wees.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Hierdie waarde moet leeg wees.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Die waarde wat jy gekies het is nie 'n geldige keuse nie.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Jy moet ten minste {{ limit }} kies.|Jy moet ten minste {{ limit }} keuses kies.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Jy moet by die meeste {{ limit }} keuse kies.|Jy moet by die meeste {{ limit }} keuses kies.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Een of meer van die gegewe waardes is ongeldig.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Die velde {{ fields }} is nie verwag nie.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Die velde {{ fields }} ontbreek.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Hierdie waarde is nie 'n geldige datum nie.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Hierdie waarde is nie 'n geldige datum en tyd nie.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Hierdie waarde is nie 'n geldige e-pos adres nie.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Die lêer kon nie gevind word nie.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Die lêer kan nie gelees word nie.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Die lêer is te groot ({{ size }} {{ suffix }}). Toegelaat maksimum grootte is {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Die MIME-tipe van die lêer is ongeldig ({{ type }}). Toegelaat MIME-tipes is {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Hierdie waarde moet {{ limit }} of minder wees.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Hierdie waarde is te lank. Dit moet {{ limit }} karakter of minder wees.|Hierdie waarde is te lank. Dit moet {{ limit }} karakters of minder wees.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Hierdie waarde moet {{ limit }} of meer wees.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Hierdie waarde is te kort. Dit moet {{ limit }} karakter of meer wees.|Hierdie waarde is te kort. Dit moet {{ limit }} karakters of meer wees.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Hierdie waarde moet nie leeg wees nie.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Hierdie waarde moet nie nul wees nie.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Hierdie waarde moet nul wees.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Hierdie waarde is nie geldig nie.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Hierdie waarde is nie 'n geldige tyd nie.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Hierdie waarde is nie 'n geldige URL nie.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Die twee waardes moet gelyk wees.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Die lêer is te groot. Toegelaat maksimum grootte is {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Die lêer is te groot.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Die lêer kan nie opgelaai word nie.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Hierdie waarde moet 'n geldige nommer wees.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Hierdie lêer is nie 'n geldige beeld nie.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Hierdie is nie 'n geldige IP-adres nie.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Hierdie waarde is nie 'n geldige taal nie.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Hierdie waarde is nie 'n geldige land instelling nie.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Hierdie waarde is nie 'n geldige land nie.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Hierdie waarde word reeds gebruik.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Die grootte van die beeld kon nie opgespoor word nie.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Die beeld breedte is te groot ({{ width }}px). Toegelaat maksimum breedte is {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Die beeld breedte is te klein ({{ width }}px). Minimum breedte verwag is {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Die beeld hoogte is te groot ({{ height }}px). Toegelaat maksimum hoogte is {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Die beeld hoogte is te klein ({{ height }}px). Minimum hoogte verwag is {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Hierdie waarde moet die huidige wagwoord van die gebruiker wees.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Hierdie waarde moet presies {{ limit }} karakter wees.|Hierdie waarde moet presies {{ limit }} karakters wees.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Die lêer is slegs gedeeltelik opgelaai.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Geen lêer is opgelaai nie.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Geen tydelike lêer is ingestel in php.ini nie.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Kan nie tydelike lêer skryf op skyf nie.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>'n PHP-uitbreiding veroorsaak die oplaai van die lêer om te misluk.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Hierdie versameling moet {{ limit }} element of meer bevat.|Hierdie versameling moet {{ limit }} elemente of meer bevat.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Hierdie versameling moet {{ limit }} element of minder bevat.|Hierdie versameling moet {{ limit }} elemente of meer bevat.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Hierdie versameling moet presies {{ limit }} element bevat.|Hierdie versameling moet presies {{ limit }} elemente bevat.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Ongeldige kredietkaart nommer.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Nie-ondersteunde tipe kaart of ongeldige kredietkaart nommer.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Dylid bod y gwerth hwn yn ffug.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Dylid bod y gwerth hwn yn wir.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Dylid bod y gwerth hwn bod o fath {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Dylid bod y gwerth hwn yn wag.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Nid yw'r gwerth � ddewiswyd yn ddilys.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Rhaid dewis o leiaf {{ limit }} opsiwn.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Rhaid dewis dim mwy na {{ limit }} opsiwn.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Mae un neu fwy o'r gwerthoedd a roddwyd yn annilys.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Roedd y maesydd {{ fields }} yn anisgwyl.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Roedd y maesydd {{ fields }} ar goll.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Nid yw'r gwerth yn ddyddiad dilys.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Nid yw'r gwerth yn datetime dilys.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Nid yw'r gwerth yn gyfeiriad ebost dilys.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Ni ddarganfyddwyd y ffeil.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Ni ellir darllen y ffeil.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Mae'r ffeil yn rhy fawr ({{ size }} {{ suffix }}). Yr uchafswm � ganiateir yw {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Nid yw math mime y ffeil yn ddilys ({{ type }}). Dyma'r mathau � ganiateir {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Dylai'r gwerth hwn fod yn {{ limit }} neu lai.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Mae'r gwerth hwn rhy hir. Dylai gynnwys {{ limit }} nodyn cyfrifiadurol neu lai.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Dylai'r gwerth hwn fod yn {{ limit }} neu fwy.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Mae'r gwerth hwn yn rhy fyr. Dylai gynnwys {{ limit }} nodyn cyfrifiadurol neu fwy.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Ni ddylai'r gwerth hwn fod yn wag.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Ni ddylai'r gwerth hwn fod yn null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Dylai'r gwerth fod yn null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Nid yw'r gwerth hwn yn ddilys.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Nid yw'r gwerth hwn yn amser dilys.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Nid yw'r gwerth hwn yn URL dilys.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Rhaid i'r ddau werth fod yn gyfystyr a'u gilydd.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Mae'r ffeil yn rhy fawr. Yr uchafswm � ganiateir yw {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Mae'r ffeil yn rhy fawr.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Methwyd � uwchlwytho'r ffeil. </target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Dylai'r gwerth hwn fod yn rif dilys.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Nid yw'r ffeil hon yn ddelwedd dilys.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Nid yw hwn yn gyfeiriad IP dilys.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Nid yw'r gwerth hwn yn iaith ddilys.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Nid yw'r gwerth hwn yn locale dilys.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Nid yw'r gwerth hwn yn wlad dilys.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Mae'r gwerth hwn eisoes yn cael ei ddefnyddio.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Methwyd � darganfod maint y ddelwedd.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Mae lled y ddelwedd yn rhy fawr ({{ width }}px). Y lled mwyaf � ganiateir yw {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Mae lled y ddelwedd yn rhy fach ({{ width }}px). Y lled lleiaf � ganiateir yw {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Mae uchder y ddelwedd yn rhy fawr ({{ width }}px). Yr uchder mwyaf � ganiateir yw {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Mae uchder y ddelwedd yn rhy fach ({{ width }}px). Yr uchder lleiaf � ganiateir yw {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Dylaid bod y gwerth hwn yn gyfrinair presenol y defnyddiwr.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Dylai'r gwerth hwn fod yn union {{ limit }} nodyn cyfrifiadurol o hyd.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Dim ond rhan o'r ffeil � uwchlwythwyd.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Ni uwchlwythwyd unrhyw ffeil.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Nid oes ffolder dros-dro wedi'i gosod yn php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Methwyd � ysgrifennu'r ffeil dros-dro ar ddisg.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Methwyd � uwchlwytho oherwydd ategyn PHP.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Dylai'r casgliad hwn gynnwys {{ limit }} elfen neu fwy.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Dylai'r casgliad hwn gynnwys {{ limit }} elfen neu lai.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Dylai'r casgliad hwn gynnwys union {{ limit }} elfen.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Nid oedd rhif y cerdyn yn ddilys.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Unai ni dderbynir y math yna o gerdyn, neu nid yw rhif y cerdyn yn ddilys.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Стойността трябва да бъде лъжа (false).</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Стойността трябва да бъде истина (true).</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Стойността трябва да бъде от тип {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Стойността трябва да бъде празна.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Избраната стойност е невалидна.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Трябва да изберете поне {{ limit }} опция.|Трябва да изберете поне {{ limit }} опции.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Трябва да изберете най-много {{ limit }} опция.|Трябва да изберете най-много {{ limit }} опции.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Една или повече от зададените стойности е невалидна.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Полетата {{ fields }} не бяха очаквани.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Полетата {{ fields }} липсват.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Стойността не е валидна дата (date).</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Стойността не е валидна дата (datetime).</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Стойността не е валиден email адрес.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Файлът не беше открит.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Файлът не може да бъде прочетен.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Файлът е твърде голям ({{ size }} {{ suffix }}). Максималният размер е {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Майм типа на файла е невалиден ({{ type }}). Разрешени майм типове са {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Стойността трябва да бъде {{ limit }} или по-малко.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Стойността е твърде дълга. Трябва да съдържа най-много {{ limit }} символ.|Стойността е твърде дълга. Трябва да съдържа най-много {{ limit }} символа.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Стойността трябва да бъде {{ limit }} или повече.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Стойността е твърде кратка. Трябва да съдържа поне {{ limit }} символ.|Стойността е твърде кратка. Трябва да съдържа поне {{ limit }} символа.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Стойността не трябва да бъде празна.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Стойността не трябва да бъде null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Стойността трябва да бъде null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Стойността не е валидна.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Стойността не е валидно време (time).</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Стойността не е валиден URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Двете стойности трябва да бъдат равни.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Файлът е твърде голям. Разрешеният максимален размер е {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Файлът е твърде голям.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Файлът не може да бъде качен.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Стойността трябва да бъде валиден номер.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Файлът не е валидно изображение.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Това не е валиден IP адрес.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Стойността не е валиден език.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Стойността не е валидна локализация.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Стойността не е валидна държава.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Стойността вече е в употреба.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Размера на изображението не може да бъде определен.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Изображението е твърде широко ({{ width }}px). Широчината трябва да бъде максимум {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Изображението е с твърде малка широчина ({{ width }}px). Широчината трябва да бъде минимум {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Изображението е с твърде голяма височина ({{ height }}px). Височината трябва да бъде максимум {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Изображението е с твърде малка височина ({{ height }}px). Височина трябва да бъде минимум {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Стойността трябва да бъде текущата потребителска парола.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Стойността трябва да бъде точно {{ limit }} символ.|Стойността трябва да бъде точно {{ limit }} символа.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Файлът е качен частично.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Файлът не беше качен.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Не е посочена директория за временни файлове в php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Не може да запише временен файл на диска.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>PHP разширение предизвика прекъсване на качването.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Колекцията трябва да съдържа поне {{ limit }} елемент.|Колекцията трябва да съдържа поне {{ limit }} елемента.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Колекцията трябва да съдържа най-много {{ limit }} елемент.|Колекцията трябва да съдържа най-много {{ limit }} елемента.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Колекцията трябва да съдържа точно {{ limit }} елемент.|Колекцията трябва да съдържа точно {{ limit }} елемента.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>هذه القيمة يجب أن تكون خاطئة.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>هذه القيمة يجب أن تكون حقيقية.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>هذه القيمة يجب ان تكون من نوع {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>هذه القيمة يجب ان تكون فارغة.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>القيمة المختارة ليست خيارا صحيحا.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>يجب ان تختار {{ limit }} اختيار على الاقل.|يجب ان تختار {{ limit }} اختيار على الاقل.|يجب ان تختار {{ limit }} اختيارات على الاقل.|يجب ان تختار {{ limit }} اختيار على الاقل.|يجب ان تختار {{ limit }} اختيار على الاقل.|يجب ان تختار {{ limit }} اختيار على الاقل.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>يجب ان تختار {{ limit }} اختيار على الاكثر.|يجب ان تختار {{ limit }} اختيار على الاكثر.|يجب ان تختار {{ limit }} اختيارات على الاكثر.|يجب ان تختار {{ limit }} اختيار على الاكثر.|يجب ان تختار {{ limit }} اختيار على الاكثر.|يجب ان تختار {{ limit }} اختيار على الاكثر.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>واحد أو أكثر من القيم المعطاه خاطئ.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>القيم {{ fields }} لم تكن متوقعة.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>القيم {{ fields }} مفقودة.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>هذه القيمة ليست تاريخا صالحا.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>هذه القيمة ليست تاريخا و وقتا صالحا.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>هذه القيمة ليست عنوان بريد إلكتروني صحيح.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>لا يمكن العثور على الملف.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>الملف غير قابل للقراءة.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>الملف كبير جدا ({{ size }} {{ suffix }}).اقصى مساحه مسموح بها ({{ limit }} {{ suffix }}).</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>نوع الملف غير صحيح ({{ type }}). الانواع المسموح بها هى {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>هذه القيمة يجب ان تكون {{ limit }} او اقل.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حروف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.|هذه القيمة طويلة جدا. يجب ان تكون {{ limit }} حرف او اقل.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>هذه القيمة يجب ان تكون {{ limit }} او اكثر</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حروف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.|هذه القيمة قصيرة جدا. يجب ان تكون {{ limit }} حرف او اكثر.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>هذه القيمة يجب الا تكون فارغة.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>هذه القيمة يجب الا تكون فارغة.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>هذه القيمة يجب ان تكون فارغة.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>هذه القيمة غير صحيحة.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>هذه القيمة ليست وقت صحيح</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>هذه القيمة ليست رابط الكترونى صحيح.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>القيمتان يجب ان تكونا متساويتان.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>الملف كبير جدا. اقصى مساحه مسموح بها {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>الملف كبير جدا.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>لم استطع استقبال الملف.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>هذه القيمة يجب ان تكون رقم.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>هذا الملف ليس صورة صحيحة.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>هذه القيمة ليست عنوان رقمى صحيح.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>هذه القيمة ليست لغة صحيحة.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>هذه القيمة ليست موقع صحيح.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>هذه القيمة ليست بلدا صالحا.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>هذه القيمة مستخدمة بالفعل.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>لم استطع معرفة حجم الصورة.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>عرض الصورة كبير جدا ({{ width }}px). اقصى عرض مسموح به هو{{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>عرض الصورة صغير جدا ({{ width }}px). اقل عرض مسموح به هو{{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>طول الصورة كبير جدا ({{ height }}px). اقصى طول مسموح به هو{{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>طول الصورة صغير جدا ({{ height }}px). اقل طول مسموح به هو{{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>هذه القيمة يجب ان تكون كلمة سر المستخدم الحالية.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حروف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.|هذه القيمة يجب ان تحتوى على {{ limit }} حرف فقط.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>تم استقبال جزء من الملف فقط.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>لم يتم ارسال اى ملف.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>لم يتم تهيئة حافظة مؤقتة فى ملف php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>لم استطع كتابة الملف المؤقت.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>احد اضافات PHP تسببت فى فشل استقبال الملف.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عناصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اكثر.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عناصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر او اقل.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عناصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.|هذه المجموعة يجب ان تحتوى على {{ limit }} عنصر فقط.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>رقم البطاقه غير صحيح.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>نوع البطاقه غير مدعوم او الرقم غير صحيح.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>الرقم IBAN (رقم الحساب المصرفي الدولي) الذي تم إدخاله غير صالح.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>هذه القيمة ليست ISBN-10 صالحة.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>هذه القيمة ليست ISBN-13 صالحة.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>هذه القيمة ليست ISBN-10 صالحة ولا ISBN-13 صالحة.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>هذه القيمة ليست ISSN صالحة.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Вредност треба да буде нетачна.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Вредност треба да буде тачна.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Вредност треба да буде типа {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Вредност треба да буде празна.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Вредност треба да буде једна од понуђених.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Изаберите бар {{ limit }} могућност.|Изаберите бар {{ limit }} могућности.|Изаберите бар {{ limit }} могућности.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Изаберите највише {{ limit }} могућност.|Изаберите највише {{ limit }} могућности.|Изаберите највише {{ limit }} могућности.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Једна или више вредности је невалидна.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Поља {{ fields }} нису била очекивана.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Поља {{ fields }} недостају.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Вредност није валидан датум.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Вредност није валидан датум-време.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Вредност није валидна адреса електронске поште.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Датотека не може бити пронађена.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Датотека није читљива.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Датотека је превелика ({{ size }} {{ suffix }}). Највећа дозвољена величина је {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Миме тип датотеке није валидан ({{ type }}). Дозвољени миме типови су {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Вредност треба да буде {{ limit }} или мање.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Вредност је предугачка. Треба да има {{ limit }} карактер или мање.|Вредност је предугачка. Треба да има {{ limit }} карактера или мање.|Вредност је предугачка. Треба да има {{ limit }} карактера или мање.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Вредност треба да буде {{ limit }} или више.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Вредност је прекратка. Треба да има {{ limit }} карактер или више.|Вредност је прекратка. Треба да има {{ limit }} карактера или више.|Вредност је прекратка. Треба да има {{ limit }} карактера или више.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Вредност не треба да буде празна.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Вредност не треба да буде null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Вредност треба да буде null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Вредност је невалидна.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Вредност није валидно време.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Вредност није валидан URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Обе вредности треба да буду једнаке.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Датотека је превелика. Највећа дозвољена величина је {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Датотека је превелика.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Датотека не може бити отпремљена.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Вредност треба да буде валидан број.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Ова датотека није валидна слика.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Ово није валидна ИП адреса.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Вредност није валидан језик.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Вредност није валидан локал.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Вредност није валидна земља.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Вредност је већ искоришћена.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Величина слике не може бити одређена.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Ширина слике је превелика ({{ width }}px). Најећа дозвољена ширина је {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Ширина слике је премала ({{ width }}px). Најмања дозвољена ширина је {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Висина слике је превелика ({{ height }}px). Најећа дозвољена висина је {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Висина слике је премала ({{ height }}px). Најмања дозвољена висина је {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Вредност треба да буде тренутна корисничка лозинка.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Вредност треба да има тачно {{ limit }} карактер.|Вредност треба да има тачно {{ limit }} карактера.|Вредност треба да има тачно {{ limit }} карактера.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Датотека је само парцијално отпремљена.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Датотека није отпремљена.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Привремени директоријум није конфигурисан у php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Немогуће писање привремене датотеке на диск.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>PHP екстензија је проузроковала неуспех отпремања датотеке.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Ова колекција треба да садржи {{ limit }} или више елемената.|Ова колекција треба да садржи {{ limit }} или више елемената.|Ова колекција треба да садржи {{ limit }} или више елемената.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Ова колекција треба да садржи {{ limit }} или мање елемената.|Ова колекција треба да садржи {{ limit }} или мање елемената.|Ова колекција треба да садржи {{ limit }} или мање елемената.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Ова колекција треба да садржи тачно {{ limit }} елемент.|Ова колекција треба да садржи тачно {{ limit }} елемента.|Ова колекција треба да садржи тачно {{ limit }} елемената.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Невалидан број картице.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Невалидан број картице или тип картице није подржан.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Ово није валидан међународни број банковног рачуна (IBAN).</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Ово није валидан ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Ово није валидан ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Ово није валидан ISBN-10 или ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Ово није валидан ISSN.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Verdien skal være falsk.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Verdien skal være sann.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Verdien skal være av typen {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Verdien skal være blank.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Verdien skal være en av de gitte valg.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Du skal velge minst {{ limit }} valg.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Du kan maks velge {{ limit }} valg.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>En eller flere av de oppgitte verdier er ugyldige.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Feltene {{ fields }} var ikke forventet.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Feltene {{ fields }} mangler.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Verdien er ikke en gyldig dato.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Verdien er ikke en gyldig dato og tid.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Verdien er ikke en gyldig e-mail adresse.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Filen kunne ikke finnes.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Filen kan ikke leses.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Filen er for stor ({{ size }} {{ suffix }}). Tilatte maksimale størrelse {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Mimetypen av filen er ugyldig ({{ type }}). Tilatte mimetyper er {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Verdien skal være {{ limit }} eller mindre.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Verdien er for lang. Den skal ha {{ limit }} bokstaver eller mindre.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Verdien skal være {{ limit }} eller mer.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Verdien er for kort. Den skal ha {{ limit }} tegn eller flere.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Verdien må ikke være blank.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Verdien må ikke være tom (null).</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Verdien skal være tom (null).</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Verdien er ikke gyldig.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Verdien er ikke en gyldig tid.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Verdien er ikke en gyldig URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>De to verdier skal være ens.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Filen er for stor. Den maksimale størrelse er {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Filen er for stor.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Filen kunne ikke lastes opp.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Denne verdi skal være et gyldig tall.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Denne filen er ikke et gyldig bilde.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Dette er ikke en gyldig IP adresse.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Denne verdi er ikke et gyldig språk.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Denne verdi er ikke en gyldig lokalitet.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Denne verdi er ikke et gyldig land.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Αυτή η τιμή πρέπει να είναι ψευδής.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Αυτή η τιμή πρέπει να είναι αληθής.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Αυτή η τιμή πρέπει να είναι τύπου {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Αυτή η τιμή πρέπει να είναι κενή.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Η τιμή που επιλέχθηκε δεν αντιστοιχεί σε έγκυρη επιλογή.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Πρέπει να επιλέξετε τουλάχιστον {{ limit }} επιλογή.|Πρέπει να επιλέξετε τουλάχιστον {{ limit }} επιλογές.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Πρέπει να επιλέξετε το πολύ {{ limit }} επιλογή.|Πρέπει να επιλέξετε το πολύ {{ limit }} επιλογές.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Μια ή περισσότερες τιμές δεν είναι έγκυρες.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Τα πεδία {{ fields }} δεν ήταν αναμενόμενα.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Τα πεδία {{ fields }} απουσιάζουν.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Η τιμή δεν αντιστοιχεί σε έγκυρη ημερομηνία.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Η τιμή δεν αντιστοιχεί σε έγκυρη ημερομηνία και ώρα.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Η τιμή δεν αντιστοιχεί σε έγκυρο email.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Το αρχείο δε μπορεί να βρεθεί.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Το αρχείο δεν είναι αναγνώσιμο.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Το αρχείο είναι πολύ μεγάλο ({{ size }} {{ suffix }}). Το μέγιστο επιτρεπτό μέγεθος είναι {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Ο τύπος mime του αρχείου δεν είναι έγκυρος ({{ type }}). Οι έγκρυοι τύποι mime είναι {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Αυτή η τιμή θα έπρεπε να είναι {{ limit }} ή λιγότερο.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Αυτή η τιμή είναι πολύ μεγάλη. Θα έπρεπε να έχει {{ limit }} χαρακτήρα ή λιγότερο.|Αυτή η τιμή είναι πολύ μεγάλη. Θα έπρεπε να έχει {{ limit }} χαρακτήρες ή λιγότερο.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Αυτή η τιμή θα έπρεπε να είναι {{ limit }} ή περισσότερο.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Αυτή η τιμή είναι πολύ μικρή. Θα έπρεπε να έχει {{ limit }} χαρακτήρα ή περισσότερο.|Αυτή η τιμή είναι πολύ μικρή. Θα έπρεπε να έχει {{ limit }} χαρακτήρες ή περισσότερο.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Αυτή η τιμή δεν πρέπει να είναι κενή.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Αυτή η τιμή δεν πρέπει να είναι μηδενική.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Αυτή η τιμή πρέπει να είναι μηδενική.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Αυτή η τιμή δεν είναι έκγυρη.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Αυτή η τιμή δεν αντιστοιχεί σε έγκυρη ώρα.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Αυτή η τιμή δεν αντιστοιχεί σε έγκυρο URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Οι δύο τιμές θα πρέπει να είναι ίδιες.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Το αρχείο είναι πολύ μεγάλο. Το μέγιστο επιτρεπτό μέγεθος είναι {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Το αρχείο είναι πολύ μεγάλο.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Το αρχείο δε μπορεί να ανέβει.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Αυτή η τιμή θα πρέπει να είναι ένας έγκυρος αριθμός.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Το αρχείο δεν αποτελεί έγκυρη εικόνα.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Αυτό δεν είναι μια έκγυρη διεύθυνση IP.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Αυτή η τιμή δεν αντιστοιχεί σε μια έκγυρη γλώσσα.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Αυτή η τιμή δεν αντιστοιχεί σε έκγυρο κωδικό τοποθεσίας.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Αυτή η τιμή δεν αντιστοιχεί σε μια έκγυρη χώρα.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Αυτή η τιμή χρησιμοποιείται ήδη.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Το μέγεθος της εικόνας δεν ήταν δυνατό να ανιχνευθεί.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Το πλάτος της εικόνας είναι πολύ μεγάλο ({{ width }}px). Το μέγιστο επιτρεπτό πλάτος είναι {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Το πλάτος της εικόνας είναι πολύ μικρό ({{ width }}px). Το ελάχιστο επιτρεπτό πλάτος είναι {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Το ύψος της εικόνας είναι πολύ μεγάλο ({{ height }}px). Το μέγιστο επιτρεπτό ύψος είναι {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Το ύψος της εικόνας είναι πολύ μικρό ({{ height }}px). Το ελάχιστο επιτρεπτό ύψος είναι {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Αυτή η τιμή θα έπρεπε να είναι ο τρέχων κωδικός.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Αυτή η τιμή θα έπρεπε να έχει ακριβώς {{ limit }} χαρακτήρα.|Αυτή η τιμή θα έπρεπε να έχει ακριβώς {{ limit }} χαρακτήρες.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Το αρχείο δεν ανέβηκε ολόκληρο.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Δεν ανέβηκε κανένα αρχείο.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Κανένας προσωρινός φάκελος δεν έχει ρυθμιστεί στο php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Αδυναμία εγγραφής προσωρινού αρχείου στο δίσκο.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Μια επέκταση PHP προκάλεσε αδυναμία ανεβάσματος.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Αυτή η συλλογή θα πρέπει να περιέχει {{ limit }} στοιχείο ή περισσότερα.|Αυτή η συλλογή θα πρέπει να περιέχει {{ limit }} στοιχεία ή περισσότερα.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Αυτή η συλλογή θα πρέπει να περιέχει {{ limit }} στοιχείo ή λιγότερα.|Αυτή η συλλογή θα πρέπει να περιέχει {{ limit }} στοιχεία ή λιγότερα.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Αυτή η συλλογή θα πρέπει να περιέχει ακριβώς {{ limit }} στοιχείo.|Αυτή η συλλογή θα πρέπει να περιέχει ακριβώς {{ limit }} στοιχεία.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Μη έγκυρος αριθμός κάρτας.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Μη υποστηριζόμενος τύπος κάρτας ή μη έγκυρος αριθμός κάρτας.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Αυτό δεν αντιστοιχεί σε έκγυρο διεθνή αριθμό τραπεζικού λογαριασμού (IBAN).</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Αυτό δεν είναι έγκυρος κωδικός ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Αυτό δεν είναι έγκυρος κωδικός ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Αυτό δεν είναι ούτε έγκυρος κωδικός ISBN-10 ούτε έγκυρος κωδικός ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Αυτό δεν είναι έγκυρος κωδικός ISSN.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Αυτό δεν αντιστοιχεί σε έγκυρο νόμισμα.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Αυτή η τιμή θα πρέπει να είναι ίση με {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Αυτή η τιμή θα πρέπει να είναι μεγαλύτερη από {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Αυτή η τιμή θα πρέπει να είναι μεγαλύτερη ή ίση με {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Αυτή η τιμή θα πρέπει να είναι πανομοιότυπη με {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Αυτή η τιμή θα πρέπει να είναι μικρότερη από {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Αυτή η τιμή θα πρέπει να είναι μικρότερη ή ίση με {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Αυτή η τιμή δεν θα πρέπει να είναι ίση με {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Αυτή η τιμή δεν πρέπει να είναι πανομοιότυπη με {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Deze waarde mag niet waar zijn.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Deze waarde moet waar zijn.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Deze waarde moet van het type {{ type }} zijn.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Deze waarde moet leeg zijn.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>De geselecteerde waarde is geen geldige optie.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Selecteer ten minste {{ limit }} optie.|Selecteer ten minste {{ limit }} opties.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Selecteer maximaal {{ limit }} optie.|Selecteer maximaal {{ limit }} opties.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Eén of meer van de ingegeven waarden zijn ongeldig.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>De velden {{ fields }} werden niet verwacht.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>De velden {{ fields }} ontbreken.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Deze waarde is geen geldige datum.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Deze waarde is geen geldige datum en tijd.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Deze waarde is geen geldig e-mailadres.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Het bestand is niet gevonden.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Het bestand is niet leesbaar.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Het bestand is te groot ({{ size }} {{ suffix }}). Toegestane maximum grootte is {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Het mime type van het bestand is ongeldig ({{ type }}). Toegestane mime types zijn {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Deze waarde moet {{ limit }} of minder zijn.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Deze waarde is te lang. Hij mag maximaal {{ limit }} teken bevatten.|Deze waarde is te lang. Hij mag maximaal {{ limit }} tekens bevatten.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Deze waarde moet {{ limit }} of meer zijn.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Deze waarde is te kort. Hij moet tenminste {{ limit }} teken bevatten.|Deze waarde is te kort. Hij moet tenminste {{ limit }} tekens bevatten.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Deze waarde mag niet leeg zijn.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Deze waarde mag niet null zijn.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Deze waarde moet null zijn.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Deze waarde is ongeldig.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Deze waarde is geen geldige tijd.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Deze waarde is geen geldige URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>De twee waarden moeten gelijk zijn.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Het bestand is te groot. Toegestane maximum grootte is {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Het bestand is te groot.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Het bestand kon niet geüpload worden.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Deze waarde moet een geldig getal zijn.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Dit bestand is geen geldige afbeelding.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Dit is geen geldig IP-adres.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Deze waarde representeert geen geldige taal.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Deze waarde representeert geen geldige lokalisering.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Deze waarde representeert geen geldig land.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Deze waarde wordt al gebruikt.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>De grootte van de afbeelding kon niet bepaald worden.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>De afbeelding is te breed ({{ width }}px). De maximaal toegestane breedte is {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>De afbeelding is niet breed genoeg ({{ width }}px). De minimaal verwachte breedte is {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>De afbeelding is te hoog ({{ height }}px). De maximaal toegestane hoogte is {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>De afbeelding is niet hoog genoeg ({{ height }}px). De minimaal verwachte hoogte is {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Deze waarde moet het huidige wachtwoord van de gebruiker zijn.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Deze waarde moet exact {{ limit }} tekens lang zijn.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Het bestand is niet geheel geüpload.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Er is geen bestand geüpload.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Er is geen tijdelijke map geconfigureerd in php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Kan het tijdelijke bestand niet wegschrijven op disk.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>De upload is mislukt vanwege een PHP-extensie.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Deze collectie moet {{ limit }} element of meer bevatten.|Deze collectie moet {{ limit }} elementen of meer bevatten.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Deze collectie moet {{ limit }} element of minder bevatten.|Deze collectie moet {{ limit }} elementen of minder bevatten.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Deze collectie moet exact {{ limit }} element bevatten.|Deze collectie moet exact {{ limit }} elementen bevatten.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Ongeldig creditcardnummer.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Niet-ondersteund type creditcard of ongeldig nummer.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Dit is geen geldig internationaal bankrekeningnummer (IBAN).</target>
            </trans-unit>
             <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Deze waarde is geen geldige ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Deze waarde is geen geldige ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Deze waarde is geen geldige ISBN-10 of ISBN-13 waarde.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Deze waarde is geen geldige ISSN waarde.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Deze waarde is geen geldige valuta.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Deze waarde moet gelijk zijn aan {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Deze waarde moet groter zijn dan {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Deze waarde moet groter dan of gelijk aan {{ compared_value }} zijn.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical  to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Deze waarde moet identiek zijn aan {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Deze waarde moet minder zijn dan {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Deze waarde moet minder dan of gelijk aan {{ compared_value }} zijn.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Deze waarde moet niet gelijk zijn aan {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This valuemahould not be identical to {{ compared_value }}.</source>
                <target>Deze waarde moet niet identiek zijn aan {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Este valor deve ser falso.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Este valor deve ser verdadeiro.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Este valor deve ser do tipo {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Este valor deve ser vazio.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>O valor selecionado não é uma opção válida.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Você deve selecionar, no mínimo, {{ limit }} opção.|Você deve selecionar, no mínimo, {{ limit }} opções</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Você deve selecionar, no máximo, {{ limit }} opção.|Você deve selecionar, no máximo, {{ limit }} opções.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Um ou mais valores informados são inválidos.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Os campos {{ fields }} não são esperados.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Os campos {{ fields }} estão ausentes.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Este valor não é uma data válida.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Este valor não é uma data e hora válida.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Este valor não é um endereço de e-mail válido.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>O arquivo não foi encontrado.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>O arquivo não pode ser lido.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>O arquivo é muito grande ({{ size }} {{ suffix }}). O tamanho máximo permitido é {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>O tipo mime do arquivo é inválido ({{ type }}). Os tipos mime permitidos são {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Este valor deve ser {{ limit }} ou menos.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Este valor é muito longo. Deve ter {{ limit }} caractere ou menos.|Este valor é muito longo. Deve ter {{ limit }} caracteres ou menos.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Este valor deve ser {{ limit }} ou mais.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Este valor é muito curto. Deve ter {{ limit }} caractere ou mais.|Este valor é muito curto. Deve ter {{ limit }} caracteres ou mais.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Este valor não deve ser vazio.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Este valor não deve ser nulo.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Este valor deve ser nulo.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Este valor não é válido.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Este valor não é uma hora válida.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Este valor não é uma URL válida.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Os dois valores devem ser iguais.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>O arquivo é muito grande. O tamanho máximo permitido é de {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>O arquivo é muito grande.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>O arquivo não pode ser enviado.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Este valor deve ser um número válido.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Este arquivo não é uma imagem válida.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Este não é um endereço de IP válido.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Este valor não é um idioma válido.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Este valor não é uma localidade válida.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Este valor não é um país válido.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Este valor já está sendo usado.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>O tamanho da imagem não pode ser detectado.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>A largura da imagem é muito grande ({{ width }}px). A largura máxima permitida é de {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>A largura da imagem é muito pequena ({{ width }}px). A largura mínima esperada é de {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>A altura da imagem é muito grande ({{ height }}px). A altura máxima permitida é de {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>A altura da imagem é muito pequena ({{ height }}px). A altura mínima esperada é de {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Este valor deve ser a senha atual do usuário.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Este valor deve ter exatamente {{ limit }} caractere.|Este valor deve ter exatamente {{ limit }} caracteres.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>O arquivo foi enviado apenas parcialmente.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Nenhum arquivo foi enviado.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Nenhum diretório temporário foi configurado no php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Não foi possível escrever o arquivo temporário no disco.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Uma extensão PHP fez com que o envio falhasse.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Esta coleção deve conter {{ limit }} elemento ou mais.|Esta coleção deve conter {{ limit }} elementos ou mais.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Esta coleção deve conter {{ limit }} elemento ou menos.|Esta coleção deve conter {{ limit }} elementos ou menos.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Esta coleção deve conter exatamente {{ limit }} elemento.|Esta coleção deve conter exatamente {{ limit }} elementos.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Número de cartão inválido.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Tipo de cartão não suportado ou número de cartão inválido.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Este não é um Número Internacional de Conta Bancária (IBAN) válido.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Este valor não é um ISBN-10 válido.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Este valor não é um ISBN-13 válido.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Este valor não é um ISBN-10 e nem um ISBN-13 válido.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Este valor não é um ISSN válido.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>falseでなければなりません。</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>trueでなければなりません。</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>型は{{ type }}でなければなりません。</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>空でなければなりません。</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>有効な選択肢ではありません。</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>{{ limit }}個以上選択してください。</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>{{ limit }}個以内で選択してください。</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>無効な選択肢が含まれています。</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>フィールド{{ fields }}は無効です。</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>フィールド{{ fields }}は必須です。</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>有効な日付ではありません。</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>有効な日時ではありません。</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>有効なメールアドレスではありません。</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>ファイルが見つかりません。</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>ファイルを読み込めません。</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>ファイルのサイズが大きすぎます({{ size }} {{ suffix }})。有効な最大サイズは{{ limit }} {{ suffix }}です。</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>ファイルのMIMEタイプが無効です({{ type }})。有効なMIMEタイプは{{ types }}です。</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>{{ limit }}以下でなければなりません。</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>値が長すぎます。{{ limit }}文字以内でなければなりません。</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>{{ limit }}以上でなければなりません。</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>値が短すぎます。{{ limit }}文字以上でなければなりません。</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>空であってはなりません。</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>nullであってはなりません。</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>nullでなければなりません。</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>有効な値ではありません。</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>有効な時刻ではありません。</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>有効なURLではありません。</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>2つの値が同じでなければなりません。</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>ファイルのサイズが大きすぎます。有効な最大サイズは{{ limit }} {{ suffix }}です。</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>ファイルのサイズが大きすぎます。</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>ファイルをアップロードできませんでした。</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>有効な数字ではありません。</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>ファイルが画像ではありません。</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>有効なIPアドレスではありません。</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>有効な言語名ではありません。</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>有効なロケールではありません。</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>有効な国名ではありません。</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>既に使用されています。</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>画像のサイズが検出できません。</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>画像の幅が大きすぎます({{ width }}ピクセル)。{{ max_width }}ピクセルまでにしてください。</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>画像の幅が小さすぎます({{ width }}ピクセル)。{{ min_width }}ピクセル以上にしてください。</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>画像の高さが大きすぎます({{ height }}ピクセル)。{{ max_height }}ピクセルまでにしてください。</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>画像の高さが小さすぎます({{ height }}ピクセル)。{{ min_height }}ピクセル以上にしてください。</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>ユーザーの現在のパスワードでなければなりません。</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>ちょうど{{ limit }}文字でなければなりません。</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>ファイルのアップロードは完全ではありません。</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>ファイルがアップロードされていません。</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>php.iniで一時フォルダが設定されていません。</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>一時ファイルをディスクに書き込むことができません。</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>PHP拡張によってアップロードに失敗しました。</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>{{ limit }}個以上の要素を含んでなければいけません。</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>要素は{{ limit }}個までです。</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>要素はちょうど{{ limit }}個でなければなりません。</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>無効なカード番号です。</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>未対応のカード種類又は無効なカード番号です。</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>有効なIBANコードではありません。</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>有効なISBN-10コードではありません。</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>有効なISBN-13コードではありません。</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>有効なISBN-10コード又はISBN-13コードではありません。</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>有効なISSNコードではありません。</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>有効な貨幣ではありません。</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>{{ compared_value }}と等しくなければなりません。</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>{{ compared_value }}より大きくなければなりません。</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>{{ compared_value }}以上でなければなりません。</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>{{ compared_value_type }}としての{{ compared_value }}と等しくなければなりません。</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>{{ compared_value }}未満でなければなりません。</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>{{ compared_value }}以下でなければなりません。</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>{{ compared_value }}と等しくてはいけません。</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>{{ compared_value_type }}としての{{ compared_value }}と等しくてはいけません。</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Dieser Wert sollte false sein.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Dieser Wert sollte true sein.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Dieser Wert sollte vom Typ {{ type }} sein.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Dieser Wert sollte leer sein.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Sie haben einen ungültigen Wert ausgewählt.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Sie müssen mindestens {{ limit }} Möglichkeit wählen.|Sie müssen mindestens {{ limit }} Möglichkeiten wählen.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Sie dürfen höchstens {{ limit }} Möglichkeit wählen.|Sie dürfen höchstens {{ limit }} Möglichkeiten wählen.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Einer oder mehrere der angegebenen Werte sind ungültig.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Die Felder {{ fields }} wurden nicht erwartet.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Die erwarteten Felder {{ fields }} fehlen.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Dieser Wert entspricht keiner gültigen Datumsangabe.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Dieser Wert entspricht keiner gültigen Datums- und Zeitangabe.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Dieser Wert ist keine gültige E-Mail-Adresse.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Die Datei wurde nicht gefunden.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Die Datei ist nicht lesbar.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Die Datei ist zu groß ({{ size }} {{ suffix }}). Die maximal zulässige Größe beträgt {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Der Dateityp ist ungültig ({{ type }}). Erlaubte Dateitypen sind {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Dieser Wert sollte kleiner oder gleich {{ limit }} sein.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Diese Zeichenkette ist zu lang. Sie sollte höchstens {{ limit }} Zeichen haben.|Diese Zeichenkette ist zu lang. Sie sollte höchstens {{ limit }} Zeichen haben.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Dieser Wert sollte größer oder gleich {{ limit }} sein.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Diese Zeichenkette ist zu kurz. Sie sollte mindestens {{ limit }} Zeichen haben.|Diese Zeichenkette ist zu kurz. Sie sollte mindestens {{ limit }} Zeichen haben.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Dieser Wert sollte nicht leer sein.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Dieser Wert sollte nicht null sein.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Dieser Wert sollte null sein.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Dieser Wert ist nicht gültig.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Dieser Wert entspricht keiner gültigen Zeitangabe.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Dieser Wert ist keine gültige URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Die beiden Werte sollten identisch sein.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Die Datei ist zu groß. Die maximal zulässige Größe beträgt {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Die Datei ist zu groß.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Die Datei konnte nicht hochgeladen werden.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Dieser Wert sollte eine gültige Zahl sein.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Diese Datei ist kein gültiges Bild.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Dies ist keine gültige IP-Adresse.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Dieser Wert entspricht keiner gültigen Sprache.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Dieser Wert entspricht keinem gültigen Gebietsschema.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Dieser Wert entspricht keinem gültigen Land.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Dieser Wert wird bereits verwendet.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Die Größe des Bildes konnte nicht ermittelt werden.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Die Bildbreite ist zu groß ({{ width }}px). Die maximal zulässige Breite beträgt {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Die Bildbreite ist zu gering ({{ width }}px). Die erwartete Mindestbreite beträgt {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Die Bildhöhe ist zu groß ({{ height }}px). Die maximal zulässige Höhe beträgt {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Die Bildhöhe ist zu gering ({{ height }}px). Die erwartete Mindesthöhe beträgt {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Dieser Wert sollte dem aktuellen Benutzerpasswort entsprechen.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Dieser Wert sollte genau {{ limit }} Zeichen lang sein.|Dieser Wert sollte genau {{ limit }} Zeichen lang sein.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Die Datei wurde nur teilweise hochgeladen.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Es wurde keine Datei hochgeladen.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Es wurde kein temporärer Ordner in der php.ini konfiguriert.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Kann die temporäre Datei nicht speichern.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Eine PHP-Erweiterung verhinderte den Upload.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Diese Sammlung sollte {{ limit }} oder mehr Elemente beinhalten.|Diese Sammlung sollte {{ limit }} oder mehr Elemente beinhalten.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Diese Sammlung sollte {{ limit }} oder weniger Elemente beinhalten.|Diese Sammlung sollte {{ limit }} oder weniger Elemente beinhalten.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Diese Sammlung sollte genau {{ limit }} Element beinhalten.|Diese Sammlung sollte genau {{ limit }} Elemente beinhalten.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Ungültige Kartennummer.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Nicht unterstützer Kartentyp oder ungültige Kartennummer.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Dieser Wert ist keine gültige IBAN-Kontonummer.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Dieser Wert entspricht keiner gültigen ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Dieser Wert entspricht keiner gültigen ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Dieser Wert ist weder eine gültige ISBN-10 noch eine gültige ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Dieser Wert ist keine gültige ISSN.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Dieser Wert ist keine gültige Währung.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Dieser Wert sollte gleich {{ compared_value }} sein.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Dieser Wert sollte größer als {{ compared_value }} sein.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Dieser Wert sollte größer oder gleich {{ compared_value }} sein.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Dieser Wert sollte identisch sein mit {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Dieser Wert sollte kleiner als {{ compared_value }} sein.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Dieser Wert sollte kleiner oder gleich {{ compared_value }} sein.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Dieser Wert sollte nicht {{ compared_value }} sein.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Dieser Wert sollte nicht identisch sein mit {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Kjo vlerë duhet të jetë e pavërtetë (false).</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Kjo vlerë duhet të jetë e vërtetë (true).</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Kjo vlerë duhet të jetë e llojit {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Kjo vlerë duhet të jetë e zbrazët.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Vlera që keni zgjedhur nuk është alternativë e vlefshme.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Duhet të zgjedhni së paku {{ limit }} alternativa.|Duhet të zgjedhni së paku {{ limit }} alternativa.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Duhet të zgjedhni më së shumti {{ limit }} alternativa.|Duhet të zgjedhni më së shumti {{ limit }} alternativa.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Një apo më shumë nga vlerat e dhëna nuk janë të sakta.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Fushat {{ fields }} nuk ishin të pritura.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Fushat {{ fields }} mungojnë.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Kjo vlerë nuk është datë e vlefshme.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Kjo vlerë nuk është datë-kohë e vlefshme.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Kjo vlerë nuk është e-mail adresë e vlefshme.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>File nuk mund të gjindej.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>File nuk është i lexueshëm.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>File është shumë i madh ({{ size }} {{ suffix }}). Madhësia më e madhe e lejuar është {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Lloji mime i files nuk është i vlefshëm ({{ type }}). Llojet mime të lejuara janë {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Kjo vlerë duhet të jetë {{ limit }} ose më pak.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Kjo vlerë është shumë e gjatë. Duhet t'i ketë {{ limit }} ose më pak karaktere.|Kjo vlerë është shumë e gjatë. Duhet t'i ketë {{ limit }} ose më pak karaktere.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Kjo vlerë duhet të jetë {{ limit }} ose më shumë.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Kjo vlerë është shumë e shkurtër. Duhet t'i ketë {{ limit }} ose më shumë karaktere.|Kjo vlerë është shumë e shkurtër. Duhet t'i ketë {{ limit }} ose më shumë karaktere.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Kjo vlerë nuk duhet të jetë e zbrazët.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Kjo vlerë nuk duhet të jetë null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Kjo vlerë duhet të jetë null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Kjo vlerë nuk është e vlefshme.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Kjo vlerë nuk është kohë e vlefshme.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Kjo vlerë nuk është URL e vlefshme.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Këto dy vlera duhet të jenë të barabarta.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Ky file është shumë i madh. Madhësia maksimale e lejuar është {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Ky file është shumë i madh.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Ky file nuk mund të ngarkohet.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Kjo vlerë duhet të jetë numër i vlefshëm.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Ky file nuk është imazh i vlefshëm.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Kjo vlerë nuk është IP adresë e vlefshme.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Kjo vlerë nuk është gjuhë e vlefshme.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Kjo vlerë nuk është përcaktim rajonal i vlefshëm.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Kjo vlerë nuk është shtet i vlefshëm.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Kjo vlerë është tashmë në përdorim.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Madhësia e këtij imazhi nuk mund të zbulohet.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Gjerësia e imazhit është shumë e madhe ({{ width }}px). Gjerësia maksimale e lejuar është {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Gjerësia e imazhit është shumë e vogël ({{ width }}px). Gjerësia minimale e pritur është {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Gjatësia e imazhit është shumë e madhe ({{ height }}px). Gjatësia maksimale e lejuar është {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Gjatësia e imazhit është shumë e vogël ({{ height }}px). Gjatësia minimale e pritur është {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Kjo vlerë duhet të jetë fjalëkalimi aktual i përdoruesit.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Kjo vlerë duhet të ketë saktësisht {{ limit }} karaktere.|Kjo vlerë duhet të ketë saktësisht {{ limit }} karaktere.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Ky file është ngarkuar pjesërisht.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Nuk është ngarkuar ndonjë file.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Asnjë folder i përkohshëm nuk është konfiguruar në php.ini.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Nuk mund të shkruhet file i përkohshëm në disk.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Një ekstenzion i PHP-së bëri të dështojë ngarkimi i files.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente.|Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente.|Ky kolekcion duhet të përmbajë {{ limit }} ose më shumë elemente.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Ky kolekcion duhet të përmbajë saktësisht {{ limit }} elemente.|Ky kolekcion duhet të përmbajë saktësisht {{ limit }} elemente.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Numër kartele i pavlefshëm.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Lloj kartele i pambështetur ose numër kartele i pavlefshëm.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Tato hodnota musí být nepravdivá (false).</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Tato hodnota musí být pravdivá (true).</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Tato hodnota musí být typu {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Tato hodnota musí být prázdná.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Vybraná hodnota není platnou možností.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Musí být vybrána nejméně {{ limit }} možnost.|Musí být vybrány nejméně {{ limit }} možnosti.|Musí být vybráno nejméně {{ limit }} možností.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Musí být vybrána maximálně {{ limit }} možnost.|Musí být vybrány maximálně {{ limit }} možnosti.|Musí být vybráno maximálně {{ limit }} možností.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Některé z uvedených hodnot jsou neplatné.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Neočekávaná pole {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Chybí následující pole {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Tato hodnota není platné datum.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Tato hodnota není platné datum s časovým údajem.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Tato hodnota není platná e-mailová adresa.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Soubor nebyl nalezen.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Soubor je nečitelný.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Soubor je příliš velký ({{ size }} {{ suffix }}). Maximální povolená velikost souboru je {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Neplatný mime typ souboru ({{ type }}). Povolené mime typy souborů jsou {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Tato hodnota musí být {{ limit }} nebo méně.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Tato hodnota je příliš dlouhá. Musí obsahovat maximálně {{ limit }} znak.|Tato hodnota je příliš dlouhá. Musí obsahovat maximálně {{ limit }} znaky.|Tato hodnota je příliš dlouhá. Musí obsahovat maximálně {{ limit }} znaků.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Tato hodnota musí být {{ limit }} nebo více.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Tato hodnota je příliš krátká. Musí obsahovat minimálně {{ limit }} znak.|Tato hodnota je příliš krátká. Musí obsahovat minimálně {{ limit }} znaky.|Tato hodnota je příliš krátká. Musí obsahovat minimálně {{ limit }} znaků.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Tato hodnota nesmí být prázdná.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Tato hodnota nesmí být null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Tato hodnota musí být null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Tato hodnota není platná.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Tato hodnota není platný časový údaj.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Tato hodnota není platná URL adresa.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Tyto dvě hodnoty musí být stejné.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Soubor je příliš velký. Maximální povolená velikost souboru je {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Soubor je příliš velký.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Soubor se nepodařilo nahrát.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Tato hodnota musí být číslo.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Tento soubor není obrázek.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Toto není platná IP adresa.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Tento jazyk neexistuje.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Tato lokalizace neexistuje.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Tato země neexistuje.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Tato hodnota je již používána.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Nepodařily se zjistit rozměry obrázku.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Obrázek je příliš široký ({{ width }}px). Maximální povolená šířka obrázku je {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Obrázek je příliš úzký ({{ width }}px). Minimální šířka musí být {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Obrázek je příliš vysoký ({{ height }}px). Maximální povolená výška obrázku je {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Obrázek je příliš nízký ({{ height }}px). Minimální výška obrázku musí být {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Tato hodnota musí být aktuální heslo uživatele.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Tato hodnota musí mít přesně {{ limit }} znak.|Tato hodnota musí mít přesně {{ limit }} znaky.|Tato hodnota musí mít přesně {{ limit }} znaků.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Byla nahrána jen část souboru.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Žádný soubor nebyl nahrán.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>V php.ini není nastavena cesta k adresáři pro dočasné soubory.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Dočasný soubor se nepodařilo zapsat na disk.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Rozšíření PHP zabránilo nahrání souboru.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Tato kolekce musí obsahovat minimálně {{ limit }} prvek.|Tato kolekce musí obsahovat minimálně {{ limit }} prvky.|Tato kolekce musí obsahovat minimálně {{ limit }} prvků.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Tato kolekce musí obsahovat maximálně {{ limit }} prvek.|Tato kolekce musí obsahovat maximálně {{ limit }} prvky.|Tato kolekce musí obsahovat maximálně {{ limit }} prvků.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Tato kolekce musí obsahovat přesně {{ limit }} prvek.|Tato kolekce musí obsahovat přesně {{ limit }} prvky.|Tato kolekce musí obsahovat přesně {{ limit }} prvků.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Neplatné číslo karty.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Nepodporovaný typ karty nebo neplatné číslo karty.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Toto je neplatný IBAN.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Tato hodnota není platné ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Tato hodnota není platné ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Tato hodnota není platné ISBN-10 ani ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Tato hodnota není platné ISSN.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Tato měna neexistuje.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Tato hodnota musí být rovna {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Tato hodnota musí být větší než {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Tato hodnota musí být větší nebo rovna {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Tato hodnota musí být typu {{ compared_value_type }} a zároveň musí být rovna {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Tato hodnota musí být menší než {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Tato hodnota musí být menší nebo rovna {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Tato hodnota nesmí být rovna {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Tato hodnota nesmí být typu {{ compared_value_type }} a zároveň nesmí být rovna {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Ennek az értéknek hamisnak kell lennie.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Ennek az értéknek igaznak kell lennie.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Ennek az értéknek {{ type }} típusúnak kell lennie.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Ennek az értéknek üresnek kell lennie.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>A választott érték érvénytelen.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Legalább {{ limit }} értéket kell kiválasztani.|Legalább {{ limit }} értéket kell kiválasztani.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Legfeljebb {{ limit }} értéket lehet kiválasztani.|Legfeljebb {{ limit }} értéket lehet kiválasztani.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>A megadott értékek közül legalább egy érvénytelen.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Váratlan mezők: {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>A következő mezők hiányoznak: {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Ez az érték nem egy érvényes dátum.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Ez az érték nem egy érvényes időpont.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Ez az érték nem egy érvényes e-mail cím.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>A fájl nem található.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>A fájl nem olvasható.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>A fájl túl nagy ({{ size }} {{ suffix }}). A legnagyobb megengedett méret {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>A fájl mime típusa érvénytelen ({{ type }}). Az engedélyezett mime típusok: {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Ez az érték legfeljebb {{ limit }} lehet.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Ez az érték túl hosszú. Legfeljebb {{ limit }} karaktert tartalmazhat.|Ez az érték túl hosszú. Legfeljebb {{ limit }} karaktert tartalmazhat.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Ez az érték legalább {{ limit }} kell legyen.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Ez az érték túl rövid. Legalább {{ limit }} karaktert kell tartalmaznia.|Ez az érték túl rövid. Legalább {{ limit }} karaktert kell tartalmaznia.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Ez az érték nem lehet üres.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Ez az érték nem lehet null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Ennek az értéknek nullnak kell lennie.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Ez az érték nem érvényes.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Ez az érték nem egy érvényes időpont.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Ez az érték nem egy érvényes URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>A két értéknek azonosnak kell lennie.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>A fájl túl nagy. A megengedett maximális méret: {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>A fájl túl nagy.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>A fájl nem tölthető fel.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Ennek az értéknek érvényes számnak kell lennie.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Ez a fájl nem egy érvényes kép.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Ez az érték nem egy érvényes IP cím.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Ez az érték nem egy érvényes nyelv.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Ez az érték nem egy érvényes területi beállítás.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Ez az érték nem egy érvényes ország.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Ez az érték már használatban van.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>A kép méretét nem lehet megállapítani.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>A kép szélessége túl nagy ({{ width }}px). A megengedett legnagyobb szélesség {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>A kép szélessége túl kicsi ({{ width }}px). Az elvárt legkisebb szélesség {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>A kép magassága túl nagy ({{ height }}px). A megengedett legnagyobb magasság {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>A kép magassága túl kicsi ({{ height }}px). Az elvárt legkisebb magasság {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Ez az érték a felhasználó jelenlegi jelszavával kell megegyezzen.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Ennek az értéknek pontosan {{ limit }} karaktert kell tartalmaznia.|Ennek az értéknek pontosan {{ limit }} karaktert kell tartalmaznia.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>A fájl csak részben lett feltöltve.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Nem lett fájl feltöltve.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Nincs ideiglenes könyvtár beállítva a php.ini-ben.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Az ideiglenes fájl nem írható a lemezre.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Egy PHP bővítmény miatt a feltöltés nem sikerült.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Ennek a gyűjteménynek legalább {{ limit }} elemet kell tartalmaznia.|Ennek a gyűjteménynek legalább {{ limit }} elemet kell tartalmaznia.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Ez a gyűjtemény legfeljebb {{ limit }} elemet tartalmazhat.|Ez a gyűjtemény legfeljebb {{ limit }} elemet tartalmazhat.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Ennek a gyűjteménynek pontosan {{ limit }} elemet kell tartalmaznia.|Ennek a gyűjteménynek pontosan {{ limit }} elemet kell tartalmaznia.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Érvénytelen kártyaszám.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Nem támogatott kártyatípus vagy érvénytelen kártyaszám.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Érvénytelen nemzetközi bankszámlaszám (IBAN).</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Ez az érték nem egy érvényes ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Ez az érték nem egy érvényes ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Ez az érték nem egy érvényes ISBN-10 vagy ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Ez az érték nem egy érvényes ISSN.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Ez az érték nem egy érvényes pénznem.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Ez az érték legyen {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Ez az érték nagyobb legyen mint {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Ez az érték nagyobb vagy egyenlő legyen mint {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Ez az érték ugyanolyan legyen mint {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Ez az érték kisebb legyen mint {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Ez az érték kisebb vagy egyenlő legyen mint {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Ez az érték ne legyen {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Ez az érték ne legyen ugyanolyan mint {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>该变量的值应为 false.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>该变量的值应为 true.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>该变量的类型应为 {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>该变量值应为空.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>选定变量的值不是有效的选项.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>您至少要选择 {{ limit }} 个选项.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>您最多能选择 {{ limit }} 个选项.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>一个或者多个给定的值无效.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>非预期字段 {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>遗漏字段 {{ fields }}.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>该值不是一个有效日期（date）.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>该值不是一个有效日期时间（datetime）.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>该值不是一个有效邮件地址.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>文件未找到.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>文件不可读.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>文件太大 ({{ size }} {{ suffix }}). 文件大小不可以超过 {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>文件类型不合法 ({{ type }}). 合法的文件类型有 {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>这个变量的值应该小于或等于 {{ limit }}.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>字符串太长， 长度不可超过 {{ limit }} 个字符.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>该变量的值应该大于或等于 {{ limit }}.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>字符串太短， 长度不可少于 {{ limit }} 个字符.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>该变量不应为空.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>该变量不应为 null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>该变量应为空 null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>该变量值无效.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>该值不是一个有效时间.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>该值不是一个有效的 URL 地址.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>该两个变量的值应该相同.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>文件太大， 文件大小不可以超过 {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>文件太大.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>文件不可被上传.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>该值应该为有效的数字.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This value is not a valid country.</source>
                <target>该值不是有效的国家名.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This file is not a valid image.</source>
                <target>该文件不是有效的图片.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This is not a valid IP address.</source>
                <target>该值不是有效的IP地址.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid language.</source>
                <target>该值不是有效的语言名.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid locale.</source>
                <target>该值不是有效的区域值.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>该值已经被使用了.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>不能解析图片大小.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>图片太宽 ({{ width }}px)，最大宽度为 {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>图片宽度不够 ({{ width }}px)，最小宽度为 {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>图片太高 ({{ height }}px)，最大高度为 {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>图片高度不够 ({{ height }}px)，最小高度为 {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>该变量应为用户当前的密码.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>该变量应为 {{ limit }} 个字符.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>该文件的上传不完整.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>没有上传任何文件.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>php.ini里没有配置临时文件目录.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>临时文件写入磁盘失败.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>某个PHP扩展造成上传失败.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>该集合最少应包含 {{ limit }} 个元素.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>该集合最多包含 {{ limit }} 个元素.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>该集合应包含正好 {{ limit }} 个元素element.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>无效的信用卡号.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>不支持的信用卡类型或无效的信用卡号.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Bu değer olumsuz olmalıdır.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Bu değer olumlu olmalıdır.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Bu değerin tipi {{ type }} olmalıdır.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Bu değer boş olmalıdır.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Seçtiğiniz değer geçerli bir seçenek değil.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>En az {{ limit }} seçenek belirtmelisiniz.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>En çok {{ limit }} seçenek belirtmelisiniz.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Verilen değerlerden bir veya daha fazlası geçersiz.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>{{ fields }} alanları kabul edilmedi.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>{{ fields }} alanları eksik.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Bu değer doğru bir tarih biçimi değildir.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Bu değer doğru bir tarihsaat biçimi değildir.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Bu değer doğru bir e-mail adresi değildir.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Dosya bulunamadı.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Dosya okunabilir değil.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Dosya çok büyük ({{ size }} {{ suffix }}). İzin verilen en büyük dosya boyutu {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Dosyanın mime tipi geçersiz ({{ type }}). İzin verilen mime tipleri {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Bu değer {{ limit }} ve altında olmalıdır.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Bu değer çok uzun. {{ limit }} karakter veya daha az olmalıdır.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Bu değer {{ limit }} veya daha fazla olmalıdır.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Bu değer çok kısa. {{ limit }} karakter veya daha fazla olmaldır.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Bu değer boşluk olamaz.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Bu değer boş bırakılmamalıdır.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Bu değer boş bırakılmalıdır.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Bu değer geçerli değil.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Bu değer doğru bir saat değil.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Bu değer doğru bir URL değil.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>İki değer eşit olmalıdır.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Dosya çok büyük. İzin verilen en büyük dosya boyutu {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Dosya çok büyük.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Dosya yüklenemiyor.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Bu değer geçerli bir rakam olmalıdır.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Bu dosya geçerli bir resim değildir.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Bu geçerli bir IP adresi değildir.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Bu değer geçerli bir lisan değil.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Bu değer geçerli bir yer değildir.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Bu değer geçerli bir ülke değildir.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Bu değer şu anda kullanımda.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Resmin boyutu saptanamıyor.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Resmin genişliği çok büyük ({{ width }}px). İzin verilen en büyük genişlik {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Resmin genişliği çok küçük ({{ width }}px). En az {{ min_width }}px olmalıdır.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Resmin yüksekliği çok büyük ({{ height }}px). İzin verilen en büyük yükseklik {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Resmin yüksekliği çok küçük ({{ height }}px). En az {{ min_height }}px olmalıdır.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Bu değer kullanıcının şu anki şifresi olmalıdır.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Bu değer tam olarak {{ limit }} karakter olmaldır.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Dosya sadece kısmen yüklendi.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Hiçbir dosya yüklenmedi.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>php.ini içerisinde geçici dizin tanımlanmadı.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Geçici dosya diske yazılamıyor.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Bir PHP eklentisi dosyanın yüklemesini başarısız kıldı.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Bu derlem {{ limit }} veya daha çok eleman içermelidir</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Bu derlem {{ limit }} veya daha az eleman içermelidir</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Bu derlem {{ limit }} eleman içermelidir</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Geçersiz kart numarası.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Desteklenmeyen kart tipi veya geçersiz kart numarası.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Táto hodnota by mala byť nastavená na false.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Táto hodnota by mala byť nastavená na true.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Táto hodnota by mala byť typu {{ type }}.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Táto hodnota by mala byť prázdna.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Táto hodnota by mala byť jednou z poskytnutých možností.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Mali by ste vybrať minimálne {{ limit }} možnosť.|Mali by ste vybrať minimálne {{ limit }} možnosti.|Mali by ste vybrať minimálne {{ limit }} možností.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Mali by ste vybrať najviac {{ limit }} možnosť.|Mali by ste vybrať najviac {{ limit }} možnosti.|Mali by ste vybrať najviac {{ limit }} možností.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>Niektoré z uvedených hodnôt sú neplatné.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Polia {{ fields }} neboli očakávané.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Chýbajú polia {{ fields }} .</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Tato hodnota nemá platný formát dátumu.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Táto hodnota nemá platný formát dátumu a času.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Táto hodnota nie je platná emailová adresa.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Súbor sa nenašiel.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Súbor nie je čitateľný.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Súbor je príliš veľký ({{ size }} {{ suffix }}). Maximálna povolená veľkosť je {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Súbor typu ({{ type }}) nie je podporovaný. Podporované typy sú {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Táto hodnota by mala byť {{ limit }} alebo menej.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Táto hodnota obsahuje viac znakov ako je povolené. Mala by obsahovať najviac {{ limit }} znak.|Táto hodnota obsahuje viac znakov ako je povolené. Mala by obsahovať najviac {{ limit }} znaky.|Táto hodnota obsahuje viac znakov ako je povolené. Mala by obsahovať najviac {{ limit }} znakov.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Táto hodnota by mala byť viac ako {{ limit }}.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Táto hodnota je príliš krátka. Musí obsahovať minimálne {{ limit }} znak.|Táto hodnota je príliš krátka. Musí obsahovať minimálne {{ limit }} znaky.|Táto hodnota je príliš krátka. Minimálny počet znakov je {{ limit }}.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Táto hodnota by mala byť vyplnená.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Táto hodnota by nemala byť null.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Táto hodnota by mala byť null.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Táto hodnota nie je platná.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Tato hodnota nemá správny formát času.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Táto hodnota nie je platnou URL adresou.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Tieto dve hodnoty by mali byť rovnaké.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Súbor je príliš veľký. Maximálna povolená veľkosť je {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Súbor je príliš veľký.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Súbor sa nepodarilo nahrať.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Táto hodnota by mala byť číslo.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Tento súbor nie je obrázok.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>Toto nie je platná IP adresa.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Tento jazyk neexistuje.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Táto lokalizácia neexistuje.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Táto krajina neexistuje.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Táto hodnota sa už používa.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Nepodarilo sa zistiť rozmery obrázku.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Obrázok je príliš široký ({{ width }}px). Maximálna povolená šírka obrázku je {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Obrázok je príliš úzky ({{ width }}px). Minimálna šírka obrázku by mala byť {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>>Obrázok je príliš vysoký ({{ height }}px). Maximálna povolená výška obrázku je {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Obrázok je príliš nízky ({{ height }}px). Minimálna výška obrázku by mala byť {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Táto hodnota by mala byť aktuálne heslo používateľa.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source>
                <target>Táto hodnota by mala mať presne {{ limit }} znak.|Táto hodnota by mala mať presne {{ limit }} znaky.|Táto hodnota by mala mať presne {{ limit }} znakov.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Bola nahraná len časť súboru.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Žiadny súbor nebol nahraný.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>V php.ini nie je nastavená cesta k adresáru pre dočasné súbory.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Dočasný súbor sa nepodarilo zapísať na disk.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>Rozšírenie PHP zabránilo nahraniu súboru.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source>
                <target>Táto kolekcia by mala obsahovať aspoň {{ limit }} prvok alebo viac.|Táto kolekcia by mala obsahovať aspoň {{ limit }} prvky alebo viac.|Táto kolekcia by mala obsahovať aspoň {{ limit }} prvkov alebo viac.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source>
                <target>Táto kolekcia by mala maximálne {{ limit }} prvok.|Táto kolekcia by mala obsahovať maximálne {{ limit }} prvky.|Táto kolekcia by mala obsahovať maximálne {{ limit }} prvkov.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source>
                <target>Táto kolekcia by mala obsahovať presne {{ limit }} prvok.|Táto kolekcia by mala obsahovať presne {{ limit }} prvky.|Táto kolekcia by mala obsahovať presne {{ limit }} prvkov.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Neplatné číslo karty.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Nepodporovaný typ karty alebo neplatné číslo karty.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Toto je neplatný IBAN.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Táto hodnota je neplatné ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Táto hodnota je neplatné ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Táto hodnota nie je platné ISBN-10 ani ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Táto hodnota nie je platné ISSN.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Táto hodnota nie je platná mena.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Táto hodnota by mala byť rovná {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Táto hodnota by mala byť väčšia ako {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Táto hodnota by mala byť väčšia alebo rovná {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Táto hodnota by mala byť typu {{ compared_value_type }} a zároveň by mala byť rovná {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Táto hodnota by mala byť menšia ako {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Táto hodnota by mala byť menšia alebo rovná {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Táto hodnota by nemala byť rovná {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Táto hodnota by nemala byť typu {{ compared_value_type }} a zároveň by nemala byť rovná {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
<?xml version='1.0'?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>This value should be false.</source>
                <target>Väärtus peaks olema väär.</target>
            </trans-unit>
            <trans-unit id="2">
                <source>This value should be true.</source>
                <target>Väärtus peaks oleme tõene.</target>
            </trans-unit>
            <trans-unit id="3">
                <source>This value should be of type {{ type }}.</source>
                <target>Väärtus peaks olema {{ type }}-tüüpi.</target>
            </trans-unit>
            <trans-unit id="4">
                <source>This value should be blank.</source>
                <target>Väärtus peaks olema tühi.</target>
            </trans-unit>
            <trans-unit id="5">
                <source>The value you selected is not a valid choice.</source>
                <target>Väärtus peaks olema üks etteantud valikutest.</target>
            </trans-unit>
            <trans-unit id="6">
                <source>You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.</source>
                <target>Valima peaks vähemalt {{ limit }} valikut.</target>
            </trans-unit>
            <trans-unit id="7">
                <source>You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.</source>
                <target>Valima peaks mitte rohkem kui  {{ limit }} valikut.</target>
            </trans-unit>
            <trans-unit id="8">
                <source>One or more of the given values is invalid.</source>
                <target>One or more of the given values is invalid.</target>
            </trans-unit>
            <trans-unit id="9">
                <source>The fields {{ fields }} were not expected.</source>
                <target>Väljad {{ fields }} olid ootamatud.</target>
            </trans-unit>
            <trans-unit id="10">
                <source>The fields {{ fields }} are missing.</source>
                <target>Väljad {{ fields }} on puudu.</target>
            </trans-unit>
            <trans-unit id="11">
                <source>This value is not a valid date.</source>
                <target>Väärtus pole korrektne kuupäev.</target>
            </trans-unit>
            <trans-unit id="12">
                <source>This value is not a valid datetime.</source>
                <target>Väärtus pole korrektne kuupäev ja kellaeg.</target>
            </trans-unit>
            <trans-unit id="13">
                <source>This value is not a valid email address.</source>
                <target>Väärtus pole korrektne e-maili aadress.</target>
            </trans-unit>
            <trans-unit id="14">
                <source>The file could not be found.</source>
                <target>Faili ei leita.</target>
            </trans-unit>
            <trans-unit id="15">
                <source>The file is not readable.</source>
                <target>Fail ei ole loetav.</target>
            </trans-unit>
            <trans-unit id="16">
                <source>The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Fail on liiga suur ({{ size }} {{ suffix }}). Suurim lubatud suurus on {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="17">
                <source>The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.</source>
                <target>Faili sisutüüp on vigane ({{ type }}). Lubatud sisutüübid on {{ types }}.</target>
            </trans-unit>
            <trans-unit id="18">
                <source>This value should be {{ limit }} or less.</source>
                <target>Väärtus peaks olema {{ limit }} või vähem.</target>
            </trans-unit>
            <trans-unit id="19">
                <source>This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.</source>
                <target>Väärtus on liiga pikk. Pikkus peaks olema {{ limit }} tähemärki või vähem.</target>
            </trans-unit>
            <trans-unit id="20">
                <source>This value should be {{ limit }} or more.</source>
                <target>Väärtus peaks olema {{ limit }} või rohkem.</target>
            </trans-unit>
            <trans-unit id="21">
                <source>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</source>
                <target>Väärtus on liiga lühike. Pikkus peaks  olema {{ limit }} tähemärki või rohkem.</target>
            </trans-unit>
            <trans-unit id="22">
                <source>This value should not be blank.</source>
                <target>Väärtus ei tohiks olla tühi.</target>
            </trans-unit>
            <trans-unit id="23">
                <source>This value should not be null.</source>
                <target>Väärtus ei tohiks olla 'null'.</target>
            </trans-unit>
            <trans-unit id="24">
                <source>This value should be null.</source>
                <target>Väärtus peaks olema 'null'.</target>
            </trans-unit>
            <trans-unit id="25">
                <source>This value is not valid.</source>
                <target>Väärtus on vigane.</target>
            </trans-unit>
            <trans-unit id="26">
                <source>This value is not a valid time.</source>
                <target>Väärtus pole korrektne aeg.</target>
            </trans-unit>
            <trans-unit id="27">
                <source>This value is not a valid URL.</source>
                <target>Väärtus pole korrektne URL.</target>
            </trans-unit>
            <trans-unit id="31">
                <source>The two values should be equal.</source>
                <target>Väärtused peaksid olema võrdsed.</target>
            </trans-unit>
            <trans-unit id="32">
                <source>The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.</source>
                <target>Fail on liiga suur. Maksimaalne lubatud suurus on {{ limit }} {{ suffix }}.</target>
            </trans-unit>
            <trans-unit id="33">
                <source>The file is too large.</source>
                <target>Fail on liiga suur.</target>
            </trans-unit>
            <trans-unit id="34">
                <source>The file could not be uploaded.</source>
                <target>Faili ei saa üles laadida.</target>
            </trans-unit>
            <trans-unit id="35">
                <source>This value should be a valid number.</source>
                <target>Väärtus peaks olema korrektne number.</target>
            </trans-unit>
            <trans-unit id="36">
                <source>This file is not a valid image.</source>
                <target>Fail ei ole korrektne pilt.</target>
            </trans-unit>
            <trans-unit id="37">
                <source>This is not a valid IP address.</source>
                <target>IP aadress pole korrektne.</target>
            </trans-unit>
            <trans-unit id="38">
                <source>This value is not a valid language.</source>
                <target>Väärtus pole korrektne keel.</target>
            </trans-unit>
            <trans-unit id="39">
                <source>This value is not a valid locale.</source>
                <target>Väärtus pole korrektne asukohakeel.</target>
            </trans-unit>
            <trans-unit id="40">
                <source>This value is not a valid country.</source>
                <target>Väärtus pole olemasolev riik.</target>
            </trans-unit>
            <trans-unit id="41">
                <source>This value is already used.</source>
                <target>Väärtust on juba kasutatud.</target>
            </trans-unit>
            <trans-unit id="42">
                <source>The size of the image could not be detected.</source>
                <target>Pildi suurust polnud võimalik tuvastada.</target>
            </trans-unit>
            <trans-unit id="43">
                <source>The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.</source>
                <target>Pilt on liiga lai ({{ width }}px). Suurim lubatud laius on {{ max_width }}px.</target>
            </trans-unit>
            <trans-unit id="44">
                <source>The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.</source>
                <target>Pilt on liiga kitsas ({{ width }}px). Vähim lubatud laius on {{ min_width }}px.</target>
            </trans-unit>
            <trans-unit id="45">
                <source>The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.</source>
                <target>Pilt on liiga pikk ({{ height }}px). Lubatud suurim pikkus on {{ max_height }}px.</target>
            </trans-unit>
            <trans-unit id="46">
                <source>The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.</source>
                <target>Pilt pole piisavalt pikk ({{ height }}px). Lubatud vähim pikkus on {{ min_height }}px.</target>
            </trans-unit>
            <trans-unit id="47">
                <source>This value should be the user current password.</source>
                <target>Väärtus peaks olema kasutaja kehtiv salasõna.</target>
            </trans-unit>
            <trans-unit id="48">
                <source>This value should have exactly {{ limit }} characters.</source>
                <target>Väärtus peaks olema täpselt {{ limit }} tähemärk pikk.|Väärtus peaks olema täpselt {{ limit }} tähemärki pikk.</target>
            </trans-unit>
            <trans-unit id="49">
                <source>The file was only partially uploaded.</source>
                <target>Fail ei laetud täielikult üles.</target>
            </trans-unit>
            <trans-unit id="50">
                <source>No file was uploaded.</source>
                <target>Ühtegi faili ei laetud üles.</target>
            </trans-unit>
            <trans-unit id="51">
                <source>No temporary folder was configured in php.ini.</source>
                <target>Ühtegi ajutist kausta polnud php.ini-s seadistatud.</target>
            </trans-unit>
            <trans-unit id="52">
                <source>Cannot write temporary file to disk.</source>
                <target>Ajutist faili ei saa kettale kirjutada.</target>
            </trans-unit>
            <trans-unit id="53">
                <source>A PHP extension caused the upload to fail.</source>
                <target>PHP laiendi tõttu ebaõnnestus faili üleslaadimine.</target>
            </trans-unit>
            <trans-unit id="54">
                <source>This collection should contain {{ limit }} elements or more.</source>
                <target>Kogumikus peaks olema vähemalt {{ limit }} element.|Kogumikus peaks olema vähemalt {{ limit }} elementi.</target>
            </trans-unit>
            <trans-unit id="55">
                <source>This collection should contain {{ limit }} elements or less.</source>
                <target>Kogumikus peaks olema ülimalt {{ limit }} element.|Kogumikus peaks olema ülimalt {{ limit }} elementi.</target>
            </trans-unit>
            <trans-unit id="56">
                <source>This collection should contain exactly {{ limit }} elements.</source>
                <target>Kogumikus peaks olema täpselt {{ limit }} element.|Kogumikus peaks olema täpselt {{ limit }}|elementi.</target>
            </trans-unit>
            <trans-unit id="57">
                <source>Invalid card number.</source>
                <target>Vigane kaardi number.</target>
            </trans-unit>
            <trans-unit id="58">
                <source>Unsupported card type or invalid card number.</source>
                <target>Kaardi tüüpi ei toetata või kaardi number on vigane.</target>
            </trans-unit>
            <trans-unit id="59">
                <source>This is not a valid International Bank Account Number (IBAN).</source>
                <target>Väärtus pole korrektne IBAN-number.</target>
            </trans-unit>
            <trans-unit id="60">
                <source>This value is not a valid ISBN-10.</source>
                <target>Väärtus pole korrektne ISBN-10.</target>
            </trans-unit>
            <trans-unit id="61">
                <source>This value is not a valid ISBN-13.</source>
                <target>Väärtus pole korrektne ISBN-13.</target>
            </trans-unit>
            <trans-unit id="62">
                <source>This value is neither a valid ISBN-10 nor a valid ISBN-13.</source>
                <target>Väärtus pole korrektne ISBN-10 ega ISBN-13.</target>
            </trans-unit>
            <trans-unit id="63">
                <source>This value is not a valid ISSN.</source>
                <target>Väärtus pole korrektne ISSN.</target>
            </trans-unit>
            <trans-unit id="64">
                <source>This value is not a valid currency.</source>
                <target>Väärtus pole korrektne valuuta.</target>
            </trans-unit>
            <trans-unit id="65">
                <source>This value should be equal to {{ compared_value }}.</source>
                <target>Väärtus peaks olema võrdne {{ compared_value }}-ga.</target>
            </trans-unit>
            <trans-unit id="66">
                <source>This value should be greater than {{ compared_value }}.</source>
                <target>Väärtus peaks olema suurem kui {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="67">
                <source>This value should be greater than or equal to {{ compared_value }}.</source>
                <target>Väärtus peaks olema suurem kui või võrduma {{ compared_value }}-ga.</target>
            </trans-unit>
            <trans-unit id="68">
                <source>This value should be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Väärtus peaks olema identne väärtusega {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="69">
                <source>This value should be less than {{ compared_value }}.</source>
                <target>Väärtus peaks olema väiksem kui {{ compared_value }}.</target>
            </trans-unit>
            <trans-unit id="70">
                <source>This value should be less than or equal to {{ compared_value }}.</source>
                <target>Väärtus peaks olema väiksem kui või võrduma {{ compared_value }}-ga.</target>
            </trans-unit>
            <trans-unit id="71">
                <source>This value should not be equal to {{ compared_value }}.</source>
                <target>Väärtus ei tohiks võrduda {{ compared_value }}-ga.</target>
            </trans-unit>
            <trans-unit id="72">
                <source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
                <target>Väärtus ei tohiks olla identne väärtusega {{ compared_value_type }} {{ compared_value }}.</target>
            </trans-unit>
        </body>
    </file>
</xliff>
Copyright (c) 2004-2013 Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

use Symfony\Component\Validator\Constraint;

/**
 * Validates values and graphs of objects and arrays.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
interface ValidatorInterface
{
    /**
     * Validates a value.
     *
     * The accepted values depend on the {@link MetadataFactoryInterface}
     * implementation.
     *
     * @param mixed      $value    The value to validate
     * @param array|null $groups   The validation groups to validate.
     * @param Boolean    $traverse Whether to traverse the value if it is traversable.
     * @param Boolean    $deep     Whether to traverse nested traversable values recursively.
     *
     * @return ConstraintViolationListInterface A list of constraint violations. If the
     *                                          list is empty, validation succeeded.
     *
     * @api
     */
    public function validate($value, $groups = null, $traverse = false, $deep = false);

    /**
     * Validates a property of a value against its current value.
     *
     * The accepted values depend on the {@link MetadataFactoryInterface}
     * implementation.
     *
     * @param mixed      $containingValue The value containing the property.
     * @param string     $property        The name of the property to validate.
     * @param array|null $groups          The validation groups to validate.
     *
     * @return ConstraintViolationListInterface A list of constraint violations. If the
     *                                          list is empty, validation succeeded.
     *
     * @api
     */
    public function validateProperty($containingValue, $property, $groups = null);

    /**
     * Validate a property of a value against a potential value.
     *
     * The accepted values depend on the {@link MetadataFactoryInterface}
     * implementation.
     *
     * @param string     $containingValue The value containing the property.
     * @param string     $property        The name of the property to validate
     * @param string     $value           The value to validate against the
     *                                    constraints of the property.
     * @param array|null $groups          The validation groups to validate.
     *
     * @return ConstraintViolationListInterface A list of constraint violations. If the
     *                                          list is empty, validation succeeded.
     *
     * @api
     */
    public function validatePropertyValue($containingValue, $property, $value, $groups = null);

    /**
     * Validates a value against a constraint or a list of constraints.
     *
     * @param mixed                   $value       The value to validate.
     * @param Constraint|Constraint[] $constraints The constraint(s) to validate against.
     * @param array|null              $groups      The validation groups to validate.
     *
     * @return ConstraintViolationListInterface A list of constraint violations. If the
     *                                          list is empty, validation succeeded.
     *
     * @api
     */
    public function validateValue($value, $constraints, $groups = null);

    /**
     * Returns the factory for metadata instances.
     *
     * @return MetadataFactoryInterface The metadata factory.
     *
     * @api
     */
    public function getMetadataFactory();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * A violation of a constraint that happened during validation.
 *
 * For each constraint that fails during validation one or more violations are
 * created. The violations store the violation message, the path to the failing
 * element in the validation graph and the root element that was originally
 * passed to the validator. For example, take the following graph:
 *
 * <pre>
 * (Person)---(firstName: string)
 *      \
 *   (address: Address)---(street: string)
 * </pre>
 *
 * If the <tt>Person</tt> object is validated and validation fails for the
 * "firstName" property, the generated violation has the <tt>Person</tt>
 * instance as root and the property path "firstName". If validation fails
 * for the "street" property of the related <tt>Address</tt> instance, the root
 * element is still the person, but the property path is "address.street".
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
interface ConstraintViolationInterface
{
    /**
     * Returns the violation message.
     *
     * @return string The violation message.
     *
     * @api
     */
    public function getMessage();

    /**
     * Returns the raw violation message.
     *
     * The raw violation message contains placeholders for the parameters
     * returned by {@link getMessageParameters}. Typically you'll pass the
     * message template and parameters to a translation engine.
     *
     * @return string The raw violation message.
     *
     * @api
     */
    public function getMessageTemplate();

    /**
     * Returns the parameters to be inserted into the raw violation message.
     *
     * @return array A possibly empty list of parameters indexed by the names
     *               that appear in the message template.
     *
     * @see getMessageTemplate
     *
     * @api
     */
    public function getMessageParameters();

    /**
     * Returns a number for pluralizing the violation message.
     *
     * For example, the message template could have different translation based
     * on a parameter "choices":
     *
     * <ul>
     * <li>Please select exactly one entry. (choices=1)</li>
     * <li>Please select two entries. (choices=2)</li>
     * </ul>
     *
     * This method returns the value of the parameter for choosing the right
     * pluralization form (in this case "choices").
     *
     * @return integer|null The number to use to pluralize of the message.
     */
    public function getMessagePluralization();

    /**
     * Returns the root element of the validation.
     *
     * @return mixed The value that was passed originally to the validator when
     *               the validation was started. Because the validator traverses
     *               the object graph, the value at which the violation occurs
     *               is not necessarily the value that was originally validated.
     *
     * @api
     */
    public function getRoot();

    /**
     * Returns the property path from the root element to the violation.
     *
     * @return string The property path indicates how the validator reached
     *                the invalid value from the root element. If the root
     *                element is a <tt>Person</tt> instance with a property
     *                "address" that contains an <tt>Address</tt> instance
     *                with an invalid property "street", the generated property
     *                path is "address.street". Property access is denoted by
     *                dots, while array access is denoted by square brackets,
     *                for example "addresses[1].street".
     *
     * @api
     */
    public function getPropertyPath();

    /**
     * Returns the value that caused the violation.
     *
     * @return mixed The invalid value that caused the validated constraint to
     *               fail.
     *
     * @api
     */
    public function getInvalidValue();

    /**
     * Returns a machine-digestible error code for the violation.
     *
     * @return mixed The error code.
     */
    public function getCode();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * Validates values are all unequal (!=).
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class NotEqualToValidator extends AbstractComparisonValidator
{
    /**
     * @inheritDoc
     */
    protected function compareValues($value1, $value2)
    {
        return $value1 != $value2;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
use Symfony\Component\PropertyAccess\PropertyPath;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use Symfony\Component\Validator\Exception\RuntimeException;

/**
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bernhard Schussek <bschussek@symfony.com>
 */
class ExpressionValidator extends ConstraintValidator
{
    /**
     * @var PropertyAccessorInterface
     */
    private $propertyAccessor;

    /**
     * @var ExpressionLanguage
     */
    private $expressionLanguage;

    public function __construct(PropertyAccessorInterface $propertyAccessor)
    {
        $this->propertyAccessor = $propertyAccessor;
    }

    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        $variables = array();

        if (null === $this->context->getPropertyName()) {
            $variables['this'] = $value;
        } else {
            // Extract the object that the property belongs to from the object
            // graph
            $path = new PropertyPath($this->context->getPropertyPath());
            $parentPath = $path->getParent();
            $root = $this->context->getRoot();

            $variables['value'] = $value;
            $variables['this'] = $parentPath ? $this->propertyAccessor->getValue($root, $parentPath) : $root;
        }

        if (!$this->getExpressionLanguage()->evaluate($constraint->expression, $variables)) {
            $this->context->addViolation($constraint->message);
        }
    }

    private function getExpressionLanguage()
    {
        if (null === $this->expressionLanguage) {
            if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
                throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
            }
            $this->expressionLanguage = new ExpressionLanguage();
        }

        return $this->expressionLanguage;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class UrlValidator extends ConstraintValidator
{
    const PATTERN = '~^
            (%s)://                                 # protocol
            (
                ([\pL\pN\pS-]+\.)+[\pL]+                   # a domain name
                    |                                     #  or
                \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}      # a IP address
                    |                                     #  or
                \[
                    (?:(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){6})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:::(?:(?:(?:[0-9a-f]{1,4})):){5})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){4})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,1}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){3})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,2}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){2})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,3}(?:(?:[0-9a-f]{1,4})))?::(?:(?:[0-9a-f]{1,4})):)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,4}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,5}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,6}(?:(?:[0-9a-f]{1,4})))?::))))
                \]  # a IPv6 address
            )
            (:[0-9]+)?                              # a port (optional)
            (/?|/\S+)                               # a /, nothing or a / with something
        $~ixu';

    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        $value = (string) $value;

        $pattern = sprintf(static::PATTERN, implode('|', $constraint->protocols));

        if (!preg_match($pattern, $value)) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * @Annotation
 *
 * @api
 */
class Image extends File
{
    public $mimeTypes = 'image/*';
    public $minWidth = null;
    public $maxWidth = null;
    public $maxHeight = null;
    public $minHeight = null;
    public $maxRatio = null;
    public $minRatio = null;
    public $allowSquare = true;
    public $allowLandscape = true;
    public $allowPortrait = true;

    public $mimeTypesMessage = 'This file is not a valid image.';
    public $sizeNotDetectedMessage = 'The size of the image could not be detected.';
    public $maxWidthMessage = 'The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px.';
    public $minWidthMessage = 'The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.';
    public $maxHeightMessage = 'The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.';
    public $minHeightMessage = 'The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.';
    public $maxRatioMessage = 'The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.';
    public $minRatioMessage = 'The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.';
    public $allowSquareMessage = 'The image is square ({{ width }}x{{ height }}px). Square images are not allowed.';
    public $allowLandscapeMessage = 'The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.';
    public $allowPortraitMessage = 'The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class FalseValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || false === $value || 0 === $value || '0' === $value) {
            return;
        }

        $this->context->addViolation($constraint->message);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class Optional extends Existence
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Antonio J. García Lagar <aj@garcialagar.es>
 */
class Issn extends Constraint
{
    public $message = 'This value is not a valid ISSN.';
    public $caseSensitive = false;
    public $requireHyphen = false;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * Annotation for group sequences
 *
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class GroupSequence
{
    /**
     * The members of the sequence
     * @var array
     */
    public $groups;

    public function __construct(array $groups)
    {
        $this->groups = $groups['value'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * Validates whether a value match or not given regexp pattern
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Joseph Bielawski <stloyd@gmail.com>
 *
 * @api
 */
class RegexValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        $value = (string) $value;

        if ($constraint->match xor preg_match($constraint->pattern, $value)) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;

/**
 * Validator for Callback constraint
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class CallbackValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($object, Constraint $constraint)
    {
        if (null === $object) {
            return;
        }

        if (null !== $constraint->callback && null !== $constraint->methods) {
            throw new ConstraintDefinitionException(
                'The Callback constraint supports either the option "callback" ' .
                'or "methods", but not both at the same time.'
            );
        }

        // has to be an array so that we can differentiate between callables
        // and method names
        if (null !== $constraint->methods && !is_array($constraint->methods)) {
            throw new UnexpectedTypeException($constraint->methods, 'array');
        }

        $methods = $constraint->methods ?: array($constraint->callback);

        foreach ($methods as $method) {
            if (is_array($method) || $method instanceof \Closure) {
                if (!is_callable($method)) {
                    throw new ConstraintDefinitionException(sprintf('"%s::%s" targeted by Callback constraint is not a valid callable', $method[0], $method[1]));
                }

                call_user_func($method, $object, $this->context);
            } else {
                if (!method_exists($object, $method)) {
                    throw new ConstraintDefinitionException(sprintf('Method "%s" targeted by Callback constraint does not exist', $method));
                }

                $reflMethod = new \ReflectionMethod($object, $method);

                if ($reflMethod->isStatic()) {
                    $reflMethod->invoke(null, $object, $this->context);
                } else {
                    $reflMethod->invoke($object, $this->context);
                }
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class NullValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null !== $value) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class TypeValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value) {
            return;
        }

        $type = strtolower($constraint->type);
        $type = $type == 'boolean' ? 'bool' : $constraint->type;
        $isFunction = 'is_'.$type;
        $ctypeFunction = 'ctype_'.$type;

        if (function_exists($isFunction) && call_user_func($isFunction, $value)) {
            return;
        } elseif (function_exists($ctypeFunction) && call_user_func($ctypeFunction, $value)) {
            return;
        } elseif ($value instanceof $constraint->type) {
            return;
        }

        $this->context->addViolation($constraint->message, array(
            '{{ value }}' => is_object($value) ? get_class($value) : (is_array($value) ? 'Array' : (string) $value),
            '{{ type }}'  => $constraint->type,
        ));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class Required extends Existence
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * Validates values are greater than or equal to the previous (>=).
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class GreaterThanOrEqualValidator extends AbstractComparisonValidator
{
    /**
     * @inheritDoc
     */
    protected function compareValues($value1, $value2)
    {
        return $value1 >= $value2;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class NotBlank extends Constraint
{
    public $message = 'This value should not be blank.';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\MissingOptionsException;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Length extends Constraint
{
    public $maxMessage = 'This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.';
    public $minMessage = 'This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.';
    public $exactMessage = 'This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.';
    public $max;
    public $min;
    public $charset = 'UTF-8';

    public function __construct($options = null)
    {
        if (null !== $options && !is_array($options)) {
            $options = array(
                'min' => $options,
                'max' => $options,
            );
        }

        parent::__construct($options);

        if (null === $this->min && null === $this->max) {
            throw new MissingOptionsException(sprintf('Either option "min" or "max" must be given for constraint %s', __CLASS__), array('min', 'max'));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * Annotation to define a group sequence provider
 *
 * @Annotation
 */
class GroupSequenceProvider
{

}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * @Annotation
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class NotIdenticalTo extends AbstractComparison
{
    public $message = 'This value should not be identical to {{ compared_value_type }} {{ compared_value }}.';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Date extends Constraint
{
    public $message = 'This value is not a valid date.';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Constraints\Required;
use Symfony\Component\Validator\Constraints\Optional;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Collection extends Constraint
{
    public $fields = array();
    public $allowExtraFields = false;
    public $allowMissingFields = false;
    public $extraFieldsMessage = 'This field was not expected.';
    public $missingFieldsMessage = 'This field is missing.';

    /**
     * {@inheritDoc}
     */
    public function __construct($options = null)
    {
        // no known options set? $options is the fields array
        if (is_array($options)
            && !array_intersect(array_keys($options), array('groups', 'fields', 'allowExtraFields', 'allowMissingFields', 'extraFieldsMessage', 'missingFieldsMessage'))) {
            $options = array('fields' => $options);
        }

        parent::__construct($options);

        if (!is_array($this->fields)) {
            throw new ConstraintDefinitionException(sprintf('The option "fields" is expected to be an array in constraint %s', __CLASS__));
        }

        foreach ($this->fields as $fieldName => $field) {
            // the XmlFileLoader and YamlFileLoader pass the field Optional
            // and Required constraint as an array with exactly one element
            if (is_array($field) && count($field) == 1) {
                $this->fields[$fieldName] = $field = $field[0];
            }

            if (!$field instanceof Optional && !$field instanceof Required) {
                $this->fields[$fieldName] = $field = new Required($field);
            }

            if (!is_array($field->constraints)) {
                $field->constraints = array($field->constraints);
            }

            foreach ($field->constraints as $constraint) {
                if (!$constraint instanceof Constraint) {
                    throw new ConstraintDefinitionException(sprintf('The value %s of the field %s is not an instance of Constraint in constraint %s', $constraint, $fieldName, __CLASS__));
                }

                if ($constraint instanceof Valid) {
                    throw new ConstraintDefinitionException(sprintf('The constraint Valid cannot be nested inside constraint %s. You can only declare the Valid constraint directly on a field or method.', __CLASS__));
                }
            }
        }
    }

    public function getRequiredOptions()
    {
        return array('fields');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * Validates a PAN using the LUHN Algorithm
 *
 * For a list of example card numbers that are used to test this
 * class, please see the LuhnValidatorTest class.
 *
 * @see    http://en.wikipedia.org/wiki/Luhn_algorithm
 * @author Tim Nagel <t.nagel@infinite.net.au>
 * @author Greg Knapp http://gregk.me/2011/php-implementation-of-bank-card-luhn-algorithm/
 */
class LuhnValidator extends ConstraintValidator
{
    /**
     * Validates a creditcard number with the Luhn algorithm.
     *
     * @param mixed      $value
     * @param Constraint $constraint
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        /**
         * need to work with strings only because long numbers are treated as floats and don't work with strlen
         */
        if (!is_string($value)) {
            throw new UnexpectedTypeException($value, 'string');
        }

        if (!is_numeric($value)) {
            $this->context->addViolation($constraint->message);

            return;
        }

        $length = strlen($value);
        $oddLength = $length % 2;
        for ($sum = 0, $i = $length - 1; $i >= 0; $i--) {
            $digit = (int) $value[$i];
            $sum += (($i % 2) === $oddLength) ? array_sum(str_split($digit * 2)) : $digit;
        }

        if ($sum === 0 || ($sum % 10) !== 0) {
            $this->context->addViolation($constraint->message);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class False extends Constraint
{
    public $message = 'This value should be false.';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * @Annotation
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class LessThan extends AbstractComparison
{
    public $message = 'This value should be less than {{ compared_value }}.';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Callback extends Constraint
{
    /**
     * @var string|callable
     *
     * @since 2.4
     */
    public $callback;

    /**
     * @var array
     *
     * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0.
     */
    public $methods;

    /**
     * {@inheritdoc}
     */
    public function __construct($options = null)
    {
        // Invocation through annotations with an array parameter only
        if (is_array($options) && 1 === count($options) && isset($options['value'])) {
            $options = $options['value'];
        }

        if (is_array($options) && !isset($options['callback']) && !isset($options['methods']) && !isset($options['groups'])) {
            if (is_callable($options)) {
                $options = array('callback' => $options);
            } else {
                // BC with Symfony < 2.4
                $options = array('methods' => $options);
            }
        }

        parent::__construct($options);
    }

    /**
     * {@inheritdoc}
     */
    public function getDefaultOption()
    {
        return 'callback';
    }

    /**
     * {@inheritdoc}
     */
    public function getTargets()
    {
        return self::CLASS_CONSTRAINT;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Locale extends Constraint
{
    public $message = 'This value is not a valid locale.';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class CountValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value) {
            return;
        }

        if (!is_array($value) && !$value instanceof \Countable) {
            throw new UnexpectedTypeException($value, 'array or \Countable');
        }

        $count = count($value);

        if ($constraint->min == $constraint->max && $count != $constraint->min) {
            $this->context->addViolation($constraint->exactMessage, array(
                '{{ count }}' => $count,
                '{{ limit }}' => $constraint->min,
            ), $value, (int) $constraint->min);

            return;
        }

        if (null !== $constraint->max && $count > $constraint->max) {
            $this->context->addViolation($constraint->maxMessage, array(
                '{{ count }}' => $count,
                '{{ limit }}' => $constraint->max,
            ), $value, (int) $constraint->max);

            return;
        }

        if (null !== $constraint->min && $count < $constraint->min) {
            $this->context->addViolation($constraint->minMessage, array(
                '{{ count }}' => $count,
                '{{ limit }}' => $constraint->min,
            ), $value, (int) $constraint->min);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class NotNull extends Constraint
{
    public $message = 'This value should not be null.';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;

/**
 * Validates whether a value is a valid image file and is valid
 * against minWidth, maxWidth, minHeight and maxHeight constraints
 *
 * @author Benjamin Dulau <benjamin.dulau@gmail.com>
 */
class ImageValidator extends FileValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        $violations = count($this->context->getViolations());

        parent::validate($value, $constraint);

        $failed = count($this->context->getViolations()) !== $violations;

        if ($failed || null === $value || '' === $value) {
            return;
        }

        if (null === $constraint->minWidth && null === $constraint->maxWidth
            && null === $constraint->minHeight && null === $constraint->maxHeight
            && null === $constraint->minRatio && null === $constraint->maxRatio
            && $constraint->allowSquare && $constraint->allowLandscape && $constraint->allowPortrait) {
            return;
        }

        $size = @getimagesize($value);
        if (empty($size) || ($size[0] === 0) || ($size[1] === 0)) {
            $this->context->addViolation($constraint->sizeNotDetectedMessage);

            return;
        }

        $width  = $size[0];
        $height = $size[1];

        if ($constraint->minWidth) {
            if (!ctype_digit((string) $constraint->minWidth)) {
                throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum width', $constraint->minWidth));
            }

            if ($width < $constraint->minWidth) {
                $this->context->addViolation($constraint->minWidthMessage, array(
                    '{{ width }}'    => $width,
                    '{{ min_width }}' => $constraint->minWidth
                ));

                return;
            }
        }

        if ($constraint->maxWidth) {
            if (!ctype_digit((string) $constraint->maxWidth)) {
                throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum width', $constraint->maxWidth));
            }

            if ($width > $constraint->maxWidth) {
                $this->context->addViolation($constraint->maxWidthMessage, array(
                    '{{ width }}'    => $width,
                    '{{ max_width }}' => $constraint->maxWidth
                ));

                return;
            }
        }

        if ($constraint->minHeight) {
            if (!ctype_digit((string) $constraint->minHeight)) {
                throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum height', $constraint->minHeight));
            }

            if ($height < $constraint->minHeight) {
                $this->context->addViolation($constraint->minHeightMessage, array(
                    '{{ height }}'    => $height,
                    '{{ min_height }}' => $constraint->minHeight
                ));

                return;
            }
        }

        if ($constraint->maxHeight) {
            if (!ctype_digit((string) $constraint->maxHeight)) {
                throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum height', $constraint->maxHeight));
            }

            if ($height > $constraint->maxHeight) {
                $this->context->addViolation($constraint->maxHeightMessage, array(
                    '{{ height }}'    => $height,
                    '{{ max_height }}' => $constraint->maxHeight
                ));
            }
        }

        $ratio = $width / $height;

        if (null !== $constraint->minRatio) {
            if (!is_numeric((string) $constraint->minRatio)) {
                throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum ratio', $constraint->minRatio));
            }

            if ($ratio < $constraint->minRatio) {
                $this->context->addViolation($constraint->minRatioMessage, array(
                    '{{ ratio }}' => $ratio,
                    '{{ min_ratio }}' => $constraint->minRatio
                ));
            }
        }

        if (null !== $constraint->maxRatio) {
            if (!is_numeric((string) $constraint->maxRatio)) {
                throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum ratio', $constraint->maxRatio));
            }

            if ($ratio > $constraint->maxRatio) {
                $this->context->addViolation($constraint->maxRatioMessage, array(
                    '{{ ratio }}' => $ratio,
                    '{{ max_ratio }}' => $constraint->maxRatio
                ));
            }
        }

        if (!$constraint->allowSquare && $width == $height) {
            $this->context->addViolation($constraint->allowSquareMessage, array(
                '{{ width }}' => $width,
                '{{ height }}' => $height
            ));
        }

        if (!$constraint->allowLandscape && $width > $height) {
            $this->context->addViolation($constraint->allowLandscapeMessage, array(
                '{{ width }}' => $width,
                '{{ height }}' => $height
            ));
        }

        if (!$constraint->allowPortrait && $width < $height) {
            $this->context->addViolation($constraint->allowPortraitMessage, array(
                '{{ width }}' => $width,
                '{{ height }}' => $height
            ));
        }

    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * Validates values are greater than the previous (>).
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class GreaterThanValidator extends AbstractComparisonValidator
{
    /**
     * @inheritDoc
     */
    protected function compareValues($value1, $value2)
    {
        return $value1 > $value2;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * Validates whether the value is a valid ISSN.
 *
 * @author Antonio J. García Lagar <aj@garcialagar.es>
 *
 * @see https://en.wikipedia.org/wiki/Issn
 */
class IssnValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        // Compose regex pattern
        $digitsPattern = $constraint->requireHyphen ? '\d{4}-\d{3}' : '\d{4}-?\d{3}';
        $checksumPattern = $constraint->caseSensitive ? '[\d|X]' : '[\d|X|x]';
        $pattern = "/^".$digitsPattern.$checksumPattern."$/";

        if (!preg_match($pattern, $value)) {
            $this->context->addViolation($constraint->message);
        } else {
            $digits = str_split(strtoupper(str_replace('-', '', $value)));

            $sum = 0;
            for ($i = 8; $i > 1; $i--) {
                $sum += $i * (int) array_shift($digits);
            }

            $checksum = 'X' == reset($digits) ? 10 : (int) reset($digits);

            if (0 != ($sum + $checksum) % 11) {
                $this->context->addViolation($constraint->message);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Constraints\Optional;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class CollectionValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value) {
            return;
        }

        if (!is_array($value) && !($value instanceof \Traversable && $value instanceof \ArrayAccess)) {
            throw new UnexpectedTypeException($value, 'array or Traversable and ArrayAccess');
        }

        $group = $this->context->getGroup();

        foreach ($constraint->fields as $field => $fieldConstraint) {
            if (
                // bug fix issue #2779
                (is_array($value) && array_key_exists($field, $value)) ||
                ($value instanceof \ArrayAccess && $value->offsetExists($field))
            ) {
                foreach ($fieldConstraint->constraints as $constr) {
                    $this->context->validateValue($value[$field], $constr, '['.$field.']', $group);
                }
            } elseif (!$fieldConstraint instanceof Optional && !$constraint->allowMissingFields) {
                $this->context->addViolationAt('['.$field.']', $constraint->missingFieldsMessage, array(
                    '{{ field }}' => $field
                ), null);
            }
        }

        if (!$constraint->allowExtraFields) {
            foreach ($value as $field => $fieldValue) {
                if (!isset($constraint->fields[$field])) {
                    $this->context->addViolationAt('['.$field.']', $constraint->extraFieldsMessage, array(
                        '{{ field }}' => $field
                    ), $fieldValue);
                }
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\MissingOptionsException;

/**
 * @Annotation
 *
 * @author The Whole Life To Learn <thewholelifetolearn@gmail.com>
 */
class Isbn extends Constraint
{
    public $isbn10Message = 'This value is not a valid ISBN-10.';
    public $isbn13Message = 'This value is not a valid ISBN-13.';
    public $bothIsbnMessage = 'This value is neither a valid ISBN-10 nor a valid ISBN-13.';
    public $isbn10;
    public $isbn13;

    public function __construct($options = null)
    {
        if (null !== $options && !is_array($options)) {
            $options = array(
                'isbn10' => $options,
                'isbn13' => $options,
            );
        }

        parent::__construct($options);

        if (null === $this->isbn10 && null === $this->isbn13) {
            throw new MissingOptionsException(sprintf('Either option "isbn10" or "isbn13" must be given for constraint "%s".', __CLASS__), array('isbn10', 'isbn13'));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Intl\Intl;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * Validates whether a value is a valid locale code
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class LocaleValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        $value = (string) $value;
        $locales = Intl::getLocaleBundle()->getLocaleNames();

        if (!isset($locales[$value])) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * Metadata for the LuhnValidator.
 *
 * @Annotation
 */
class Luhn extends Constraint
{
    public $message = 'Invalid card number.';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Intl\Intl;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * Validates whether a value is a valid language code
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class LanguageValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        $value = (string) $value;
        $languages = Intl::getLanguageBundle()->getLanguageNames();

        if (!isset($languages[$value])) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * @author Manuel Reinhard <manu@sprain.ch>
 * @author Michael Schummel
 * @link http://www.michael-schummel.de/2007/10/05/iban-prufung-mit-php/
 */
class IbanValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        $teststring = preg_replace('/\s+/', '', $value);

        if (strlen($teststring) < 4) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));

            return;
        }

        $teststring = substr($teststring, 4)
            .strval(ord($teststring{0}) - 55)
            .strval(ord($teststring{1}) - 55)
            .substr($teststring, 2, 2);

        $teststring = preg_replace_callback('/[A-Za-z]/', function ($letter) {
            return intval(ord(strtolower($letter[0])) - 87);
        }, $teststring);

        $rest = 0;
        $strlen = strlen($teststring);
        for ($pos = 0; $pos < $strlen; $pos += 7) {
            $part = strval($rest).substr($teststring, $pos, 7);
            $rest = intval($part) % 97;
        }

        if ($rest != 1) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));

            return;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * ChoiceValidator validates that the value is one of the expected values.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Florian Eckerstorfer <florian@eckerstorfer.org>
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class ChoiceValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (!$constraint->choices && !$constraint->callback) {
            throw new ConstraintDefinitionException('Either "choices" or "callback" must be specified on constraint Choice');
        }

        if (null === $value) {
            return;
        }

        if ($constraint->multiple && !is_array($value)) {
            throw new UnexpectedTypeException($value, 'array');
        }

        if ($constraint->callback) {
            if (is_callable(array($this->context->getClassName(), $constraint->callback))) {
                $choices = call_user_func(array($this->context->getClassName(), $constraint->callback));
            } elseif (is_callable($constraint->callback)) {
                $choices = call_user_func($constraint->callback);
            } else {
                throw new ConstraintDefinitionException('The Choice constraint expects a valid callback');
            }
        } else {
            $choices = $constraint->choices;
        }

        if ($constraint->multiple) {
            foreach ($value as $_value) {
                if (!in_array($_value, $choices, $constraint->strict)) {
                    $this->context->addViolation($constraint->multipleMessage, array('{{ value }}' => $_value));
                }
            }

            $count = count($value);

            if ($constraint->min !== null && $count < $constraint->min) {
                $this->context->addViolation($constraint->minMessage, array('{{ limit }}' => $constraint->min), null, (int) $constraint->min);

                return;
            }

            if ($constraint->max !== null && $count > $constraint->max) {
                $this->context->addViolation($constraint->maxMessage, array('{{ limit }}' => $constraint->max), null, (int) $constraint->max);

                return;
            }
        } elseif (!in_array($value, $choices, $constraint->strict)) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class All extends Constraint
{
    public $constraints = array();

    /**
     * {@inheritDoc}
     */
    public function __construct($options = null)
    {
        parent::__construct($options);

        if (!is_array($this->constraints)) {
            $this->constraints = array($this->constraints);
        }

        foreach ($this->constraints as $constraint) {
            if (!$constraint instanceof Constraint) {
                throw new ConstraintDefinitionException(sprintf('The value %s is not an instance of Constraint in constraint %s', $constraint, __CLASS__));
            }

            if ($constraint instanceof Valid) {
                throw new ConstraintDefinitionException(sprintf('The constraint Valid cannot be nested inside constraint %s. You can only declare the Valid constraint directly on a field or method.', __CLASS__));
            }
        }
    }

    public function getDefaultOption()
    {
        return 'constraints';
    }

    public function getRequiredOptions()
    {
        return array('constraints');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * @Annotation
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class GreaterThan extends AbstractComparison
{
    public $message = 'This value should be greater than {{ compared_value }}.';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\MissingOptionsException;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Count extends Constraint
{
    public $minMessage = 'This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.';
    public $maxMessage = 'This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.';
    public $exactMessage = 'This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.';
    public $min;
    public $max;

    public function __construct($options = null)
    {
        if (null !== $options && !is_array($options)) {
            $options = array(
                'min' => $options,
                'max' => $options,
            );
        }

        parent::__construct($options);

        if (null === $this->min && null === $this->max) {
            throw new MissingOptionsException(sprintf('Either option "min" or "max" must be given for constraint %s', __CLASS__), array('min', 'max'));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Blank extends Constraint
{
    public $message = 'This value should be blank.';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class File extends Constraint
{
    public $maxSize = null;
    public $mimeTypes = array();
    public $notFoundMessage = 'The file could not be found.';
    public $notReadableMessage = 'The file is not readable.';
    public $maxSizeMessage = 'The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}.';
    public $mimeTypesMessage = 'The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.';

    public $uploadIniSizeErrorMessage   = 'The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}.';
    public $uploadFormSizeErrorMessage  = 'The file is too large.';
    public $uploadPartialErrorMessage   = 'The file was only partially uploaded.';
    public $uploadNoFileErrorMessage    = 'No file was uploaded.';
    public $uploadNoTmpDirErrorMessage  = 'No temporary folder was configured in php.ini.';
    public $uploadCantWriteErrorMessage = 'Cannot write temporary file to disk.';
    public $uploadExtensionErrorMessage = 'A PHP extension caused the upload to fail.';
    public $uploadErrorMessage          = 'The file could not be uploaded.';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Email extends Constraint
{
    public $message = 'This value is not a valid email address.';
    public $checkMX = false;
    public $checkHost = false;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\HttpFoundation\File\File as FileObject;
use Symfony\Component\HttpFoundation\File\UploadedFile;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class FileValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        if ($value instanceof UploadedFile && !$value->isValid()) {
            switch ($value->getError()) {
                case UPLOAD_ERR_INI_SIZE:
                    if ($constraint->maxSize) {
                        if (ctype_digit((string) $constraint->maxSize)) {
                            $maxSize = (int) $constraint->maxSize;
                        } elseif (preg_match('/^\d++k$/', $constraint->maxSize)) {
                            $maxSize = $constraint->maxSize * 1024;
                        } elseif (preg_match('/^\d++M$/', $constraint->maxSize)) {
                            $maxSize = $constraint->maxSize * 1048576;
                        } else {
                            throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum size', $constraint->maxSize));
                        }
                        $maxSize = min(UploadedFile::getMaxFilesize(), $maxSize);
                    } else {
                        $maxSize = UploadedFile::getMaxFilesize();
                    }

                    $this->context->addViolation($constraint->uploadIniSizeErrorMessage, array(
                        '{{ limit }}' => $maxSize,
                        '{{ suffix }}' => 'bytes',
                    ));

                    return;
                case UPLOAD_ERR_FORM_SIZE:
                    $this->context->addViolation($constraint->uploadFormSizeErrorMessage);

                    return;
                case UPLOAD_ERR_PARTIAL:
                    $this->context->addViolation($constraint->uploadPartialErrorMessage);

                    return;
                case UPLOAD_ERR_NO_FILE:
                    $this->context->addViolation($constraint->uploadNoFileErrorMessage);

                    return;
                case UPLOAD_ERR_NO_TMP_DIR:
                    $this->context->addViolation($constraint->uploadNoTmpDirErrorMessage);

                    return;
                case UPLOAD_ERR_CANT_WRITE:
                    $this->context->addViolation($constraint->uploadCantWriteErrorMessage);

                    return;
                case UPLOAD_ERR_EXTENSION:
                    $this->context->addViolation($constraint->uploadExtensionErrorMessage);

                    return;
                default:
                    $this->context->addViolation($constraint->uploadErrorMessage);

                    return;
            }
        }

        if (!is_scalar($value) && !$value instanceof FileObject && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        $path = $value instanceof FileObject ? $value->getPathname() : (string) $value;

        if (!is_file($path)) {
            $this->context->addViolation($constraint->notFoundMessage, array('{{ file }}' => $path));

            return;
        }

        if (!is_readable($path)) {
            $this->context->addViolation($constraint->notReadableMessage, array('{{ file }}' => $path));

            return;
        }

        if ($constraint->maxSize) {
            if (ctype_digit((string) $constraint->maxSize)) {
                $size = filesize($path);
                $limit = (int) $constraint->maxSize;
                $suffix = 'bytes';
            } elseif (preg_match('/^\d++k$/', $constraint->maxSize)) {
                $size = round(filesize($path) / 1000, 2);
                $limit = (int) $constraint->maxSize;
                $suffix = 'kB';
            } elseif (preg_match('/^\d++M$/', $constraint->maxSize)) {
                $size = round(filesize($path) / 1000000, 2);
                $limit = (int) $constraint->maxSize;
                $suffix = 'MB';
            } else {
                throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum size', $constraint->maxSize));
            }

            if ($size > $limit) {
                $this->context->addViolation($constraint->maxSizeMessage, array(
                    '{{ size }}'    => $size,
                    '{{ limit }}'   => $limit,
                    '{{ suffix }}'  => $suffix,
                    '{{ file }}'    => $path,
                ));

                return;
            }
        }

        if ($constraint->mimeTypes) {
            if (!$value instanceof FileObject) {
                $value = new FileObject($value);
            }

            $mimeTypes = (array) $constraint->mimeTypes;
            $mime = $value->getMimeType();
            $valid = false;

            foreach ($mimeTypes as $mimeType) {
                if ($mimeType === $mime) {
                    $valid = true;
                    break;
                }

                if ($discrete = strstr($mimeType, '/*', true)) {
                    if (strstr($mime, '/', true) === $discrete) {
                        $valid = true;
                        break;
                    }
                }
            }

            if (false === $valid) {
                $this->context->addViolation($constraint->mimeTypesMessage, array(
                    '{{ type }}'    => '"'.$mime.'"',
                    '{{ types }}'   => '"'.implode('", "', $mimeTypes) .'"',
                    '{{ file }}'    => $path,
                ));
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * Validates that a card number belongs to a specified scheme.
 *
 * @see http://en.wikipedia.org/wiki/Bank_card_number
 * @see http://www.regular-expressions.info/creditcard.html
 * @author Tim Nagel <t.nagel@infinite.net.au>
 */
class CardSchemeValidator extends ConstraintValidator
{
    protected $schemes = array(
        /**
         * American Express card numbers start with 34 or 37 and have 15 digits.
         */
        'AMEX' => array(
            '/^3[47][0-9]{13}$/'
        ),
        /**
         * China UnionPay cards start with 62 and have between 16 and 19 digits.
         * Please note that these cards do not follow Luhn Algorithm as a checksum.
         */
        'CHINA_UNIONPAY' => array(
            '/^62[0-9]{14,17}$/'
        ),
        /**
         * Diners Club card numbers begin with 300 through 305, 36 or 38. All have 14 digits.
         * There are Diners Club cards that begin with 5 and have 16 digits.
         * These are a joint venture between Diners Club and MasterCard, and should be processed like a MasterCard.
         */
        'DINERS' => array(
            '/^3(?:0[0-5]|[68][0-9])[0-9]{11}$/',
        ),
        /**
         * Discover card numbers begin with 6011, 622126 through 622925, 644 through 649 or 65.
         * All have 16 digits
         */
        'DISCOVER' => array(
            '/^6011[0-9]{12}$/',
            '/^64[4-9][0-9]{13}$/',
            '/^65[0-9]{14}$/',
            '/^622(12[6-9]|1[3-9][0-9]|[2-8][0-9][0-9]|91[0-9]|92[0-5])[0-9]{10}$/'
        ),
        /**
         * InstaPayment cards begin with 637 through 639 and have 16 digits
         */
        'INSTAPAYMENT' => array(
            '/^63[7-9][0-9]{13}$/'
        ),
        /**
         * JCB cards beginning with 2131 or 1800 have 15 digits.
         * JCB cards beginning with 35 have 16 digits.
         */
        'JCB' => array(
            '/^(?:2131|1800|35[0-9]{3})[0-9]{11}$/'
        ),
        /**
         * Laser cards begin with either 6304, 6706, 6709 or 6771 and have between 16 and 19 digits
         */
        'LASER' => array(
            '/^(6304|670[69]|6771)[0-9]{12,15}$/'
        ),
        /**
         * Maestro cards begin with either 5018, 5020, 5038, 5893, 6304, 6759, 6761, 6762, 6763 or 0604
         * They have between 12 and 19 digits
         */
        'MAESTRO' => array(
            '/^(5018|5020|5038|6304|6759|6761|676[23]|0604)[0-9]{8,15}$/'
        ),
        /**
         * All MasterCard numbers start with the numbers 51 through 55. All have 16 digits.
         */
        'MASTERCARD' => array(
            '/^5[1-5][0-9]{14}$/'
        ),
        /**
         * All Visa card numbers start with a 4. New cards have 16 digits. Old cards have 13.
         */
        'VISA' => array(
            '/^4([0-9]{12}|[0-9]{15})$/'
        ),
    );

    /**
     * Validates a creditcard belongs to a specified scheme.
     *
     * @param mixed $value
     * @param Constraint $constraint
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        if (!is_numeric($value)) {
            $this->context->addViolation($constraint->message);

            return;
        }

        $schemes = array_flip((array) $constraint->schemes);
        $schemeRegexes = array_intersect_key($this->schemes, $schemes);

        foreach ($schemeRegexes as $regexes) {
            foreach ($regexes as $regex) {
                if (preg_match($regex, $value)) {
                    return;
                }
            }
        }

        $this->context->addViolation($constraint->message);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Choice extends Constraint
{
    public $choices;
    public $callback;
    public $multiple = false;
    public $strict = false;
    public $min = null;
    public $max = null;
    public $message = 'The value you selected is not a valid choice.';
    public $multipleMessage = 'One or more of the given values is invalid.';
    public $minMessage = 'You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices.';
    public $maxMessage = 'You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices.';

    /**
     * {@inheritDoc}
     */
    public function getDefaultOption()
    {
        return 'choices';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class BlankValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if ('' !== $value && null !== $value) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * Validates whether a value is a valid IP address
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Joseph Bielawski <stloyd@gmail.com>
 *
 * @api
 */
class IpValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        $value = (string) $value;

        switch ($constraint->version) {
            case Ip::V4:
               $flag = FILTER_FLAG_IPV4;
               break;

            case Ip::V6:
               $flag = FILTER_FLAG_IPV6;
               break;

            case Ip::V4_NO_PRIV:
               $flag = FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE;
               break;

            case Ip::V6_NO_PRIV:
               $flag = FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE;
               break;

            case Ip::ALL_NO_PRIV:
               $flag = FILTER_FLAG_NO_PRIV_RANGE;
               break;

            case Ip::V4_NO_RES:
               $flag = FILTER_FLAG_IPV4 | FILTER_FLAG_NO_RES_RANGE;
               break;

            case Ip::V6_NO_RES:
               $flag = FILTER_FLAG_IPV6 | FILTER_FLAG_NO_RES_RANGE;
               break;

            case Ip::ALL_NO_RES:
               $flag = FILTER_FLAG_NO_RES_RANGE;
               break;

            case Ip::V4_ONLY_PUBLIC:
               $flag = FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE;
               break;

            case Ip::V6_ONLY_PUBLIC:
               $flag = FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE;
               break;

            case Ip::ALL_ONLY_PUBLIC:
               $flag = FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE;
               break;

            default:
                $flag = null;
                break;
        }

        if (!filter_var($value, FILTER_VALIDATE_IP, $flag)) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * @Annotation
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class IdenticalTo extends AbstractComparison
{
    public $message = 'This value should be identical to {{ compared_value_type }} {{ compared_value }}.';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * Validates values are less than or equal to the previous (<=).
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class LessThanOrEqualValidator extends AbstractComparisonValidator
{
    /**
     * @inheritDoc
     */
    protected function compareValues($value1, $value2)
    {
        return $value1 <= $value2;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Intl\Intl;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * Validates whether a value is a valid currency
 *
 * @author Miha Vrhovnik <miha.vrhovnik@pagein.si>
 *
 * @api
 */
class CurrencyValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        $value = (string) $value;
        $currencies = Intl::getCurrencyBundle()->getCurrencyNames();

        if (!isset($currencies[$value])) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Regex extends Constraint
{
    public $message = 'This value is not valid.';
    public $pattern;
    public $htmlPattern = null;
    public $match = true;

    /**
     * {@inheritDoc}
     */
    public function getDefaultOption()
    {
        return 'pattern';
    }

    /**
     * {@inheritDoc}
     */
    public function getRequiredOptions()
    {
        return array('pattern');
    }

    /**
     * Returns htmlPattern if exists or pattern is convertible.
     *
     * @return string|null
     */
    public function getHtmlPattern()
    {
        // If htmlPattern is specified, use it
        if (null !== $this->htmlPattern) {
            return empty($this->htmlPattern)
                ? null
                : $this->htmlPattern;
        }

        return $this->getNonDelimitedPattern();
    }

    /**
     * Convert the htmlPattern to a suitable format for HTML5 pattern.
     * Example: /^[a-z]+$/ would be converted to [a-z]+
     * However, if options are specified, it cannot be converted
     *
     * Pattern is also ignored if match=false since the pattern should
     * then be reversed before application.
     *
     * @todo reverse pattern in case match=false as per issue #5307
     *
     * @link http://dev.w3.org/html5/spec/single-page.html#the-pattern-attribute
     *
     * @return string|null
     */
    private function getNonDelimitedPattern()
    {
        // If match = false, pattern should not be added to HTML5 validation
        if (!$this->match) {
            return null;
        }

        if (preg_match('/^(.)(\^?)(.*?)(\$?)\1$/', $this->pattern, $matches)) {
            $delimiter = $matches[1];
            $start     = empty($matches[2]) ? '.*' : '';
            $pattern   = $matches[3];
            $end       = empty($matches[4]) ? '.*' : '';

            // Unescape the delimiter in pattern
            $pattern = str_replace('\\'.$delimiter, $delimiter, $pattern);

            return $start.$pattern.$end;
        }

        return null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;

/**
 * Used for the comparison of values.
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
abstract class AbstractComparison extends Constraint
{
    public $message;
    public $value;

    /**
     * {@inheritDoc}
     */
    public function __construct($options = null)
    {
        if (!isset($options['value'])) {
            throw new ConstraintDefinitionException(sprintf(
                'The %s constraint requires the "value" option to be set.',
                get_class($this)
            ));
        }

        parent::__construct($options);
    }

    /**
     * {@inheritDoc}
     */
    public function getDefaultOption()
    {
        return 'value';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Url extends Constraint
{
    public $message = 'This value is not a valid URL.';
    public $protocols = array('http', 'https');
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * Validates values are equal (==).
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class EqualToValidator extends AbstractComparisonValidator
{
    /**
     * @inheritDoc
     */
    protected function compareValues($value1, $value2)
    {
        return $value1 == $value2;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Type extends Constraint
{
    public $message = 'This value should be of type {{ type }}.';
    public $type;

    /**
     * {@inheritDoc}
     */
    public function getDefaultOption()
    {
        return 'type';
    }

    /**
     * {@inheritDoc}
     */
    public function getRequiredOptions()
    {
        return array('type');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class NotNullValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value) {
            $this->context->addViolation($constraint->message);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Null extends Constraint
{
    public $message = 'This value should be null.';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * Provides a base class for the validation of property comparisons.
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
abstract class AbstractComparisonValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value) {
            return;
        }

        if (!$this->compareValues($value, $constraint->value, $constraint)) {
            $this->context->addViolation($constraint->message, array(
                '{{ value }}' => $this->valueToString($constraint->value),
                '{{ compared_value }}' => $this->valueToString($constraint->value),
                '{{ compared_value_type }}' => $this->valueToType($constraint->value)
            ));
        }
    }

    /**
     * Returns a string representation of the type of the value.
     *
     * @param  mixed $value
     *
     * @return string
     */
    private function valueToType($value)
    {
        return is_object($value) ? get_class($value) : gettype($value);
    }

    /**
     * Returns a string representation of the value.
     *
     * @param  mixed  $value
     *
     * @return string
     */
    private function valueToString($value)
    {
        if (is_object($value) && method_exists($value, '__toString')) {
            return (string) $value;
        }

        if ($value instanceof \DateTime) {
            return $value->format('Y-m-d H:i:s');
        }

        return var_export($value, true);
    }

    /**
     * Compares the two given values to find if their relationship is valid
     *
     * @param mixed      $value1     The first value to compare
     * @param mixed      $value2     The second value to compare
     *
     * @return Boolean true if the relationship is valid, false otherwise
     */
    abstract protected function compareValues($value1, $value2);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class RangeValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value) {
            return;
        }

        if (!is_numeric($value)) {
            $this->context->addViolation($constraint->invalidMessage, array(
                '{{ value }}' => $value,
            ));

            return;
        }

        if (null !== $constraint->max && $value > $constraint->max) {
            $this->context->addViolation($constraint->maxMessage, array(
                '{{ value }}' => $value,
                '{{ limit }}' => $constraint->max,
            ));

            return;
        }

        if (null !== $constraint->min && $value < $constraint->min) {
            $this->context->addViolation($constraint->minMessage, array(
                '{{ value }}' => $value,
                '{{ limit }}' => $constraint->min,
            ));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Intl\Intl;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * Validates whether a value is a valid country code
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class CountryValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        $value = (string) $value;
        $countries = Intl::getRegionBundle()->getCountryNames();

        if (!isset($countries[$value])) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class True extends Constraint
{
    public $message = 'This value should be true.';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class TimeValidator extends ConstraintValidator
{
    const PATTERN = '/^(0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/';

    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value || $value instanceof \DateTime) {
            return;
        }

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        $value = (string) $value;

        if (!preg_match(static::PATTERN, $value)) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Time extends Constraint
{
    public $message = 'This value is not a valid time.';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * @Annotation
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class LessThanOrEqual extends AbstractComparison
{
    public $message = 'This value should be less than or equal to {{ compared_value }}.';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * @Annotation
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class EqualTo extends AbstractComparison
{
    public $message = 'This value should be equal to {{ compared_value }}.';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * @Annotation
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class NotEqualTo extends AbstractComparison
{
    public $message = 'This value should not be equal to {{ compared_value }}.';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class NotBlankValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (false === $value || (empty($value) && '0' != $value)) {
            $this->context->addViolation($constraint->message);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Miha Vrhovnik <miha.vrhovnik@pagein.si>
 *
 * @api
 */
class Currency extends Constraint
{
    public $message = 'This value is not a valid currency.';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * Validates values aren't identical (!==).
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class NotIdenticalToValidator extends AbstractComparisonValidator
{
    /**
     * @inheritDoc
     */
    protected function compareValues($value1, $value2)
    {
        return $value1 !== $value2;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class DateValidator extends ConstraintValidator
{
    const PATTERN = '/^(\d{4})-(\d{2})-(\d{2})$/';

    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value || $value instanceof \DateTime) {
            return;
        }

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        $value = (string) $value;

        if (!preg_match(static::PATTERN, $value, $matches) || !checkdate($matches[2], $matches[3], $matches[1])) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * @Annotation
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class GreaterThanOrEqual extends AbstractComparison
{
    public $message = 'This value should be greater than or equal to {{ compared_value }}.';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Country extends Constraint
{
    public $message = 'This value is not a valid country.';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
abstract class Existence extends Constraint
{
    public $constraints = array();

    public function getDefaultOption()
    {
        return 'constraints';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
use Symfony\Component\Validator\Constraint;

/**
 * Validates that a value is a valid IP address
 *
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Joseph Bielawski <stloyd@gmail.com>
 *
 * @api
 */
class Ip extends Constraint
{
    const V4 = '4';
    const V6 = '6';
    const ALL = 'all';

    // adds FILTER_FLAG_NO_PRIV_RANGE flag (skip private ranges)
    const V4_NO_PRIV = '4_no_priv';
    const V6_NO_PRIV = '6_no_priv';
    const ALL_NO_PRIV = 'all_no_priv';

    // adds FILTER_FLAG_NO_RES_RANGE flag (skip reserved ranges)
    const V4_NO_RES = '4_no_res';
    const V6_NO_RES = '6_no_res';
    const ALL_NO_RES = 'all_no_res';

    // adds FILTER_FLAG_NO_PRIV_RANGE and FILTER_FLAG_NO_RES_RANGE flags (skip both)
    const V4_ONLY_PUBLIC = '4_public';
    const V6_ONLY_PUBLIC = '6_public';
    const ALL_ONLY_PUBLIC = 'all_public';

    protected static $versions = array(
        self::V4,
        self::V6,
        self::ALL,

        self::V4_NO_PRIV,
        self::V6_NO_PRIV,
        self::ALL_NO_PRIV,

        self::V4_NO_RES,
        self::V6_NO_RES,
        self::ALL_NO_RES,

        self::V4_ONLY_PUBLIC,
        self::V6_ONLY_PUBLIC,
        self::ALL_ONLY_PUBLIC,
    );

    public $version = self::V4;

    public $message = 'This is not a valid IP address.';

    /**
     * {@inheritDoc}
     */
    public function __construct($options = null)
    {
        parent::__construct($options);

        if (!in_array($this->version, self::$versions)) {
            throw new ConstraintDefinitionException(sprintf('The option "version" must be one of "%s"', implode('", "', self::$versions)));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 */
class Iban extends Constraint
{
    public $message = 'This is not a valid International Bank Account Number (IBAN).';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class EmailValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        $value = (string) $value;
        $valid = filter_var($value, FILTER_VALIDATE_EMAIL);

        if ($valid) {
            $host = substr($value, strpos($value, '@') + 1);

            // Check for host DNS resource records
            if ($valid && $constraint->checkMX) {
                $valid = $this->checkMX($host);
            } elseif ($valid && $constraint->checkHost) {
                $valid = $this->checkHost($host);
            }
        }

        if (!$valid) {
            $this->context->addViolation($constraint->message, array('{{ value }}' => $value));
        }
    }

    /**
     * Check DNS Records for MX type.
     *
     * @param string $host Host
     *
     * @return Boolean
     */
    private function checkMX($host)
    {
        return checkdnsrr($host, 'MX');
    }

    /**
     * Check if one of MX, A or AAAA DNS RR exists.
     *
     * @param string $host Host
     *
     * @return Boolean
     */
    private function checkHost($host)
    {
        return $this->checkMX($host) || (checkdnsrr($host, "A") || checkdnsrr($host, "AAAA"));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class Expression extends Constraint
{
    public $message = 'This value is not valid.';
    public $expression;

    /**
     * {@inheritDoc}
     */
    public function getDefaultOption()
    {
        return 'expression';
    }

    /**
     * {@inheritDoc}
     */
    public function getRequiredOptions()
    {
        return array('expression');
    }

    /**
     * {@inheritDoc}
     */
    public function getTargets()
    {
        return array(self::CLASS_CONSTRAINT, self::PROPERTY_CONSTRAINT);
    }

    /**
     * {@inheritDoc}
     */
    public function validatedBy()
    {
        return 'validator.expression';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * Validates values are identical (===).
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class IdenticalToValidator extends AbstractComparisonValidator
{
    /**
     * @inheritDoc
     */
    protected function compareValues($value1, $value2)
    {
        return $value1 === $value2;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * Metadata for the CardSchemeValidator.
 *
 * @Annotation
 */
class CardScheme extends Constraint
{
    public $message = 'Unsupported card type or invalid card number.';
    public $schemes;

    public function getDefaultOption()
    {
        return 'schemes';
    }

    public function getRequiredOptions()
    {
        return array('schemes');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * Validates whether the value is a valid ISBN-10 or ISBN-13.
 *
 * @author The Whole Life To Learn <thewholelifetolearn@gmail.com>
 *
 * @see https://en.wikipedia.org/wiki/Isbn
 */
class IsbnValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        if (!is_numeric($value)) {
            $value = str_replace('-', '', $value);
        }

        $validation = 0;
        $value = strtoupper($value);
        $valueLength = strlen($value);

        if (10 === $valueLength && null !== $constraint->isbn10) {
            for ($i = 0; $i < 10; $i++) {
                if ($value[$i] == 'X') {
                    $validation += 10 * intval(10 - $i);
                } else {
                    $validation += intval($value[$i]) * intval(10 - $i);
                }
            }

            if ($validation % 11 != 0) {
                if (null !== $constraint->isbn13) {
                    $this->context->addViolation($constraint->bothIsbnMessage);
                } else {
                    $this->context->addViolation($constraint->isbn10Message);
                }
            }
        } elseif (13 === $valueLength && null !== $constraint->isbn13) {
            for ($i = 0; $i < 13; $i += 2) {
                $validation += intval($value[$i]);
            }
            for ($i = 1; $i < 12; $i += 2) {
                $validation += intval($value[$i]) * 3;
            }

            if ($validation % 10 != 0) {
                if (null !== $constraint->isbn10) {
                    $this->context->addViolation($constraint->bothIsbnMessage);
                } else {
                    $this->context->addViolation($constraint->isbn13Message);
                }
            }
        } else {
            if (null !== $constraint->isbn10 && null !== $constraint->isbn13) {
                $this->context->addViolation($constraint->bothIsbnMessage);
            } elseif (null !== $constraint->isbn10) {
                $this->context->addViolation($constraint->isbn10Message);
            } else {
                $this->context->addViolation($constraint->isbn13Message);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\MissingOptionsException;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Range extends Constraint
{
    public $minMessage = 'This value should be {{ limit }} or more.';
    public $maxMessage = 'This value should be {{ limit }} or less.';
    public $invalidMessage = 'This value should be a valid number.';
    public $min;
    public $max;

    public function __construct($options = null)
    {
        parent::__construct($options);

        if (null === $this->min && null === $this->max) {
            throw new MissingOptionsException(sprintf('Either option "min" or "max" must be given for constraint %s', __CLASS__), array('min', 'max'));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class TrueValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value) {
            return;
        }

        if (true !== $value && 1 !== $value && '1' !== $value) {
            $this->context->addViolation($constraint->message);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class DateTime extends Constraint
{
    public $message = 'This value is not a valid datetime.';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints\Collection;

use Symfony\Component\Validator\Constraints\Optional as BaseOptional;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated in 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Validator\Constraints\Optional} instead.
 */
class Optional extends BaseOptional
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints\Collection;

use Symfony\Component\Validator\Constraints\Required as BaseRequired;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @deprecated Deprecated in 2.3, to be removed in 3.0. Use
 *             {@link \Symfony\Component\Validator\Constraints\Required} instead.
 */
class Required extends BaseRequired
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class AllValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value) {
            return;
        }

        if (!is_array($value) && !$value instanceof \Traversable) {
            throw new UnexpectedTypeException($value, 'array or Traversable');
        }

        $group = $this->context->getGroup();

        foreach ($value as $key => $element) {
            foreach ($constraint->constraints as $constr) {
                $this->context->validateValue($element, $constr, '['.$key.']', $group);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class DateTimeValidator extends DateValidator
{
    const PATTERN = '/^(\d{4})-(\d{2})-(\d{2}) (0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

/**
 * Validates values are less than the previous (<).
 *
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class LessThanValidator extends AbstractComparisonValidator
{
    /**
     * @inheritDoc
     */
    protected function compareValues($value1, $value2)
    {
        return $value1 < $value2;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class LengthValidator extends ConstraintValidator
{
    /**
     * {@inheritDoc}
     */
    public function validate($value, Constraint $constraint)
    {
        if (null === $value || '' === $value) {
            return;
        }

        if (!is_scalar($value) && !(is_object($value) && method_exists($value, '__toString'))) {
            throw new UnexpectedTypeException($value, 'string');
        }

        $stringValue = (string) $value;

        if (function_exists('grapheme_strlen') && 'UTF-8' === $constraint->charset) {
            $length = grapheme_strlen($stringValue);
        } elseif (function_exists('mb_strlen')) {
            $length = mb_strlen($stringValue, $constraint->charset);
        } else {
            $length = strlen($stringValue);
        }

        if ($constraint->min == $constraint->max && $length != $constraint->min) {
            $this->context->addViolation($constraint->exactMessage, array(
                '{{ value }}' => $stringValue,
                '{{ limit }}' => $constraint->min,
            ), $value, (int) $constraint->min);

            return;
        }

        if (null !== $constraint->max && $length > $constraint->max) {
            $this->context->addViolation($constraint->maxMessage, array(
                '{{ value }}' => $stringValue,
                '{{ limit }}' => $constraint->max,
            ), $value, (int) $constraint->max);

            return;
        }

        if (null !== $constraint->min && $length < $constraint->min) {
            $this->context->addViolation($constraint->minMessage, array(
                '{{ value }}' => $stringValue,
                '{{ limit }}' => $constraint->min,
            ), $value, (int) $constraint->min);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Valid extends Constraint
{
    public $traverse = true;

    public $deep = false;

    public function __construct($options = null)
    {
        if (is_array($options) && array_key_exists('groups', $options)) {
            throw new ConstraintDefinitionException(sprintf('The option "groups" is not supported by the constraint %s', __CLASS__));
        }

        parent::__construct($options);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
class Language extends Constraint
{
    public $message = 'This value is not a valid language.';
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * A container for validation metadata of a property.
 *
 * What exactly you define as "property" is up to you. The validator expects
 * implementations of {@link MetadataInterface} that contain constraints and
 * optionally a list of named properties that also have constraints (and may
 * have further sub properties). Such properties are mapped by implementations
 * of this interface.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @see MetadataInterface
 */
interface PropertyMetadataInterface extends MetadataInterface
{
    /**
     * Returns the name of the property.
     *
     * @return string The property name.
     */
    public function getPropertyName();

    /**
     * Extracts the value of the property from the given container.
     *
     * @param mixed $containingValue The container to extract the property value from.
     *
     * @return mixed The value of the property.
     */
    public function getPropertyValue($containingValue);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * A list of constraint violations.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
interface ConstraintViolationListInterface extends \Traversable, \Countable, \ArrayAccess
{
    /**
     * Adds a constraint violation to this list.
     *
     * @param ConstraintViolationInterface $violation The violation to add.
     *
     * @api
     */
    public function add(ConstraintViolationInterface $violation);

    /**
     * Merges an existing violation list into this list.
     *
     * @param ConstraintViolationListInterface $otherList The list to merge.
     *
     * @api
     */
    public function addAll(ConstraintViolationListInterface $otherList);

    /**
     * Returns the violation at a given offset.
     *
     * @param  integer $offset The offset of the violation.
     *
     * @return ConstraintViolationInterface The violation.
     *
     * @throws \OutOfBoundsException If the offset does not exist.
     *
     * @api
     */
    public function get($offset);

    /**
     * Returns whether the given offset exists.
     *
     * @param  integer $offset The violation offset.
     *
     * @return Boolean Whether the offset exists.
     *
     * @api
     */
    public function has($offset);

    /**
     * Sets a violation at a given offset.
     *
     * @param integer                      $offset    The violation offset.
     * @param ConstraintViolationInterface $violation The violation.
     *
     * @api
     */
    public function set($offset, ConstraintViolationInterface $violation);

    /**
     * Removes a violation at a given offset.
     *
     * @param integer $offset The offset to remove.
     *
     * @api
     */
    public function remove($offset);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping;

use Symfony\Component\Validator\Exception\ValidatorException;

class PropertyMetadata extends MemberMetadata
{
    /**
     * Constructor.
     *
     * @param string $class The class this property is defined on
     * @param string $name  The name of this property
     *
     * @throws ValidatorException
     */
    public function __construct($class, $name)
    {
        if (!property_exists($class, $name)) {
            throw new ValidatorException(sprintf('Property %s does not exist in class %s', $name, $class));
        }

        parent::__construct($class, $name, $name);
    }

    /**
     * {@inheritDoc}
     */
    public function getPropertyValue($object)
    {
        return $this->getReflectionMember($object)->getValue($object);
    }

    /**
     * {@inheritDoc}
     */
    protected function newReflectionMember($objectOrClassName)
    {
        $class = new \ReflectionClass($objectOrClassName);
        while (!$class->hasProperty($this->getName())) {
            $class = $class->getParentClass();
        }

        $member = new \ReflectionProperty($class->getName(), $this->getName());
        $member->setAccessible(true);

        return $member;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping\Cache;

use Symfony\Component\Validator\Mapping\ClassMetadata;

class ApcCache implements CacheInterface
{
    private $prefix;

    public function __construct($prefix)
    {
        if (!extension_loaded('apc')) {
            throw new \RuntimeException('Unable to use ApcCache to cache validator mappings as APC is not enabled.');
        }

        $this->prefix = $prefix;
    }

    public function has($class)
    {
        if (!function_exists('apc_exists')) {
            $exists = false;

            apc_fetch($this->prefix.$class, $exists);

            return $exists;
        }

        return apc_exists($this->prefix.$class);
    }

    public function read($class)
    {
        return apc_fetch($this->prefix.$class);
    }

    public function write(ClassMetadata $metadata)
    {
        apc_store($this->prefix.$metadata->getClassName(), $metadata);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping\Cache;

use Symfony\Component\Validator\Mapping\ClassMetadata;

/**
 * Persists ClassMetadata instances in a cache
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface CacheInterface
{
    /**
     * Returns whether metadata for the given class exists in the cache
     *
     * @param string $class
     */
    public function has($class);

    /**
     * Returns the metadata for the given class from the cache
     *
     * @param string $class Class Name
     *
     * @return ClassMetadata|false A ClassMetadata instance or false on miss
     */
    public function read($class);

    /**
     * Stores a class metadata in the cache
     *
     * @param ClassMetadata $metadata A Class Metadata
     */
    public function write(ClassMetadata $metadata);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping;

use Symfony\Component\Validator\ValidationVisitorInterface;
use Symfony\Component\Validator\ClassBasedInterface;
use Symfony\Component\Validator\PropertyMetadataInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Constraints\Valid;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;

abstract class MemberMetadata extends ElementMetadata implements PropertyMetadataInterface, ClassBasedInterface
{
    public $class;
    public $name;
    public $property;
    public $cascaded = false;
    public $collectionCascaded = false;
    public $collectionCascadedDeeply = false;
    private $reflMember = array();

    /**
     * Constructor.
     *
     * @param string $class    The name of the class this member is defined on
     * @param string $name     The name of the member
     * @param string $property The property the member belongs to
     */
    public function __construct($class, $name, $property)
    {
        $this->class = $class;
        $this->name = $name;
        $this->property = $property;
    }

    public function accept(ValidationVisitorInterface $visitor, $value, $group, $propertyPath, $propagatedGroup = null)
    {
        $visitor->visit($this, $value, $group, $propertyPath);

        if ($this->isCascaded()) {
            $visitor->validate($value, $propagatedGroup ?: $group, $propertyPath, $this->isCollectionCascaded(), $this->isCollectionCascadedDeeply());
        }
    }

    /**
     * {@inheritDoc}
     */
    public function addConstraint(Constraint $constraint)
    {
        if (!in_array(Constraint::PROPERTY_CONSTRAINT, (array) $constraint->getTargets())) {
            throw new ConstraintDefinitionException(sprintf(
                'The constraint %s cannot be put on properties or getters',
                get_class($constraint)
            ));
        }

        if ($constraint instanceof Valid) {
            $this->cascaded = true;
            /* @var Valid $constraint */
            $this->collectionCascaded = $constraint->traverse;
            $this->collectionCascadedDeeply = $constraint->deep;
        } else {
            parent::addConstraint($constraint);
        }

        return $this;
    }

    /**
     * Returns the names of the properties that should be serialized
     *
     * @return array
     */
    public function __sleep()
    {
        return array_merge(parent::__sleep(), array(
            'class',
            'name',
            'property',
            'cascaded',
            'collectionCascaded',
            'collectionCascadedDeeply',
        ));
    }

    /**
     * Returns the name of the member
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Returns the class this member is defined on
     *
     * @return string
     */
    public function getClassName()
    {
        return $this->class;
    }

    /**
     * Returns the name of the property this member belongs to
     *
     * @return string The property name
     */
    public function getPropertyName()
    {
        return $this->property;
    }

    /**
     * Returns whether this member is public
     *
     * @param object|string $objectOrClassName The object or the class name
     *
     * @return Boolean
     */
    public function isPublic($objectOrClassName)
    {
        return $this->getReflectionMember($objectOrClassName)->isPublic();
    }

    /**
     * Returns whether this member is protected
     *
     * @param object|string $objectOrClassName The object or the class name
     *
     * @return Boolean
     */
    public function isProtected($objectOrClassName)
    {
        return $this->getReflectionMember($objectOrClassName)->isProtected();
    }

    /**
     * Returns whether this member is private
     *
     * @param object|string $objectOrClassName The object or the class name
     *
     * @return Boolean
     */
    public function isPrivate($objectOrClassName)
    {
        return $this->getReflectionMember($objectOrClassName)->isPrivate();
    }

    /**
     * Returns whether objects stored in this member should be validated
     *
     * @return Boolean
     */
    public function isCascaded()
    {
        return $this->cascaded;
    }

    /**
     * Returns whether arrays or traversable objects stored in this member
     * should be traversed and validated in each entry
     *
     * @return Boolean
     */
    public function isCollectionCascaded()
    {
        return $this->collectionCascaded;
    }

    /**
     * Returns whether arrays or traversable objects stored in this member
     * should be traversed recursively for inner arrays/traversable objects
     *
     * @return Boolean
     */
    public function isCollectionCascadedDeeply()
    {
        return $this->collectionCascadedDeeply;
    }

    /**
     * Returns the Reflection instance of the member
     *
     * @param object|string $objectOrClassName The object or the class name
     *
     * @return object
     */
    public function getReflectionMember($objectOrClassName)
    {
        $className = is_string($objectOrClassName) ? $objectOrClassName : get_class($objectOrClassName);
        if (!isset($this->reflMember[$className])) {
            $this->reflMember[$className] = $this->newReflectionMember($objectOrClassName);
        }

        return $this->reflMember[$className];
    }

    /**
     * Creates a new Reflection instance for the member
     *
     * @param object|string $objectOrClassName The object or the class name
     *
     * @return mixed Reflection class
     */
    abstract protected function newReflectionMember($objectOrClassName);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping;

use Symfony\Component\Validator\MetadataFactoryInterface;

/**
 * Simple implementation of MetadataFactoryInterface that can be used when using ValidatorInterface::validateValue().
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class BlackholeMetadataFactory implements MetadataFactoryInterface
{
    /**
     * @inheritdoc
     */
    public function getMetadataFor($value)
    {
        throw new \LogicException('BlackholeClassMetadataFactory only works with ValidatorInterface::validateValue().');
    }

    /**
     * @inheritdoc
     */
    public function hasMetadataFor($value)
    {
        return false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping;

use Symfony\Component\Validator\Constraint;

abstract class ElementMetadata
{
    /**
     * @var Constraint[]
     */
    public $constraints = array();

    /**
     * @var array
     */
    public $constraintsByGroup = array();

    /**
     * Returns the names of the properties that should be serialized.
     *
     * @return array
     */
    public function __sleep()
    {
        return array(
            'constraints',
            'constraintsByGroup',
        );
    }

    /**
     * Clones this object.
     */
    public function __clone()
    {
        $constraints = $this->constraints;

        $this->constraints = array();
        $this->constraintsByGroup = array();

        foreach ($constraints as $constraint) {
            $this->addConstraint(clone $constraint);
        }
    }

    /**
     * Adds a constraint to this element.
     *
     * @param Constraint $constraint
     *
     * @return ElementMetadata
     */
    public function addConstraint(Constraint $constraint)
    {
        $this->constraints[] = $constraint;

        foreach ($constraint->groups as $group) {
            $this->constraintsByGroup[$group][] = $constraint;
        }

        return $this;
    }

    /**
     * Returns all constraints of this element.
     *
     * @return Constraint[] An array of Constraint instances
     */
    public function getConstraints()
    {
        return $this->constraints;
    }

    /**
     * Returns whether this element has any constraints.
     *
     * @return Boolean
     */
    public function hasConstraints()
    {
        return count($this->constraints) > 0;
    }

    /**
     * Returns the constraints of the given group and global ones (* group).
     *
     * @param string $group The group name
     *
     * @return array An array with all Constraint instances belonging to the group
     */
    public function findConstraints($group)
    {
        return isset($this->constraintsByGroup[$group])
                ? $this->constraintsByGroup[$group]
                : array();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping;

use Symfony\Component\Validator\ValidationVisitorInterface;
use Symfony\Component\Validator\PropertyMetadataContainerInterface;
use Symfony\Component\Validator\ClassBasedInterface;
use Symfony\Component\Validator\MetadataInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
use Symfony\Component\Validator\Exception\GroupDefinitionException;

/**
 * Represents all the configured constraints on a given class.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ClassMetadata extends ElementMetadata implements MetadataInterface, ClassBasedInterface, PropertyMetadataContainerInterface
{
    /**
     * @var string
     */
    public $name;

    /**
     * @var string
     */
    public $defaultGroup;

    /**
     * @var MemberMetadata[]
     */
    public $members = array();

    /**
     * @var PropertyMetadata[]
     */
    public $properties = array();

    /**
     * @var GetterMetadata[]
     */
    public $getters = array();

    /**
     * @var array
     */
    public $groupSequence = array();

    /**
     * @var Boolean
     */
    public $groupSequenceProvider = false;

    /**
     * @var \ReflectionClass
     */
    private $reflClass;

    /**
     * Constructs a metadata for the given class
     *
     * @param string $class
     */
    public function __construct($class)
    {
        $this->name = $class;
        // class name without namespace
        if (false !== $nsSep = strrpos($class, '\\')) {
            $this->defaultGroup = substr($class, $nsSep + 1);
        } else {
            $this->defaultGroup = $class;
        }
    }

    public function accept(ValidationVisitorInterface $visitor, $value, $group, $propertyPath, $propagatedGroup = null)
    {
        if (null === $propagatedGroup && Constraint::DEFAULT_GROUP === $group
                && ($this->hasGroupSequence() || $this->isGroupSequenceProvider())) {
            if ($this->hasGroupSequence()) {
                $groups = $this->getGroupSequence();
            } else {
                $groups = $value->getGroupSequence();
            }

            foreach ($groups as $group) {
                $this->accept($visitor, $value, $group, $propertyPath, Constraint::DEFAULT_GROUP);

                if (count($visitor->getViolations()) > 0) {
                    break;
                }
            }

            return;
        }

        $visitor->visit($this, $value, $group, $propertyPath);

        if (null !== $value) {
            $pathPrefix = empty($propertyPath) ? '' : $propertyPath.'.';

            foreach ($this->getConstrainedProperties() as $property) {
                foreach ($this->getMemberMetadatas($property) as $member) {
                    $member->accept($visitor, $member->getPropertyValue($value), $group, $pathPrefix.$property, $propagatedGroup);
                }
            }
        }
    }

    /**
     * Returns the properties to be serialized
     *
     * @return array
     */
    public function __sleep()
    {
        return array_merge(parent::__sleep(), array(
            'getters',
            'groupSequence',
            'groupSequenceProvider',
            'members',
            'name',
            'properties',
            'defaultGroup'
        ));
    }

    /**
     * Returns the fully qualified name of the class
     *
     * @return string  The fully qualified class name
     */
    public function getClassName()
    {
        return $this->name;
    }

    /**
     * Returns the name of the default group for this class
     *
     * For each class, the group "Default" is an alias for the group
     * "<ClassName>", where <ClassName> is the non-namespaced name of the
     * class. All constraints implicitly or explicitly assigned to group
     * "Default" belong to both of these groups, unless the class defines
     * a group sequence.
     *
     * If a class defines a group sequence, validating the class in "Default"
     * will validate the group sequence. The constraints assigned to "Default"
     * can still be validated by validating the class in "<ClassName>".
     *
     * @return string  The name of the default group
     */
    public function getDefaultGroup()
    {
        return $this->defaultGroup;
    }

    /**
     * {@inheritDoc}
     */
    public function addConstraint(Constraint $constraint)
    {
        if (!in_array(Constraint::CLASS_CONSTRAINT, (array) $constraint->getTargets())) {
            throw new ConstraintDefinitionException(sprintf(
                'The constraint %s cannot be put on classes',
                get_class($constraint)
            ));
        }

        $constraint->addImplicitGroupName($this->getDefaultGroup());

        parent::addConstraint($constraint);
    }

    /**
     * Adds a constraint to the given property.
     *
     * @param string     $property   The name of the property
     * @param Constraint $constraint The constraint
     *
     * @return ClassMetadata This object
     */
    public function addPropertyConstraint($property, Constraint $constraint)
    {
        if (!isset($this->properties[$property])) {
            $this->properties[$property] = new PropertyMetadata($this->getClassName(), $property);

            $this->addMemberMetadata($this->properties[$property]);
        }

        $constraint->addImplicitGroupName($this->getDefaultGroup());

        $this->properties[$property]->addConstraint($constraint);

        return $this;
    }

    /**
     * Adds a constraint to the getter of the given property.
     *
     * The name of the getter is assumed to be the name of the property with an
     * uppercased first letter and either the prefix "get" or "is".
     *
     * @param string     $property   The name of the property
     * @param Constraint $constraint The constraint
     *
     * @return ClassMetadata This object
     */
    public function addGetterConstraint($property, Constraint $constraint)
    {
        if (!isset($this->getters[$property])) {
            $this->getters[$property] = new GetterMetadata($this->getClassName(), $property);

            $this->addMemberMetadata($this->getters[$property]);
        }

        $constraint->addImplicitGroupName($this->getDefaultGroup());

        $this->getters[$property]->addConstraint($constraint);

        return $this;
    }

    /**
     * Merges the constraints of the given metadata into this object.
     *
     * @param ClassMetadata $source The source metadata
     */
    public function mergeConstraints(ClassMetadata $source)
    {
        foreach ($source->getConstraints() as $constraint) {
            $this->addConstraint(clone $constraint);
        }

        foreach ($source->getConstrainedProperties() as $property) {
            foreach ($source->getMemberMetadatas($property) as $member) {
                $member = clone $member;

                foreach ($member->getConstraints() as $constraint) {
                    $constraint->addImplicitGroupName($this->getDefaultGroup());
                }

                $this->addMemberMetadata($member);

                if (!$member->isPrivate($this->name)) {
                    $property = $member->getPropertyName();

                    if ($member instanceof PropertyMetadata && !isset($this->properties[$property])) {
                        $this->properties[$property] = $member;
                    } elseif ($member instanceof GetterMetadata && !isset($this->getters[$property])) {
                        $this->getters[$property] = $member;
                    }
                }
            }
        }
    }

    /**
     * Adds a member metadata.
     *
     * @param MemberMetadata $metadata
     */
    protected function addMemberMetadata(MemberMetadata $metadata)
    {
        $property = $metadata->getPropertyName();

        $this->members[$property][] = $metadata;
    }

    /**
     * Returns true if metadatas of members is present for the given property.
     *
     * @param string $property The name of the property
     *
     * @return Boolean
     */
    public function hasMemberMetadatas($property)
    {
        return array_key_exists($property, $this->members);
    }

    /**
     * Returns all metadatas of members describing the given property.
     *
     * @param string $property The name of the property
     *
     * @return MemberMetadata[] An array of MemberMetadata
     */
    public function getMemberMetadatas($property)
    {
        return $this->members[$property];
    }

    /**
     * {@inheritdoc}
     */
    public function hasPropertyMetadata($property)
    {
        return array_key_exists($property, $this->members);
    }

    /**
     * {@inheritdoc}
     */
    public function getPropertyMetadata($property)
    {
        return $this->members[$property];
    }

    /**
     * Returns all properties for which constraints are defined.
     *
     * @return array An array of property names
     */
    public function getConstrainedProperties()
    {
        return array_keys($this->members);
    }

    /**
     * Sets the default group sequence for this class.
     *
     * @param array $groups An array of group names
     *
     * @return ClassMetadata
     *
     * @throws GroupDefinitionException
     */
    public function setGroupSequence(array $groups)
    {
        if ($this->isGroupSequenceProvider()) {
            throw new GroupDefinitionException('Defining a static group sequence is not allowed with a group sequence provider');
        }

        if (in_array(Constraint::DEFAULT_GROUP, $groups, true)) {
            throw new GroupDefinitionException(sprintf('The group "%s" is not allowed in group sequences', Constraint::DEFAULT_GROUP));
        }

        if (!in_array($this->getDefaultGroup(), $groups, true)) {
            throw new GroupDefinitionException(sprintf('The group "%s" is missing in the group sequence', $this->getDefaultGroup()));
        }

        $this->groupSequence = $groups;

        return $this;
    }

    /**
     * Returns whether this class has an overridden default group sequence.
     *
     * @return Boolean
     */
    public function hasGroupSequence()
    {
        return count($this->groupSequence) > 0;
    }

    /**
     * Returns the default group sequence for this class.
     *
     * @return array An array of group names
     */
    public function getGroupSequence()
    {
        return $this->groupSequence;
    }

    /**
     * Returns a ReflectionClass instance for this class.
     *
     * @return \ReflectionClass
     */
    public function getReflectionClass()
    {
        if (!$this->reflClass) {
            $this->reflClass = new \ReflectionClass($this->getClassName());
        }

        return $this->reflClass;
    }

    /**
     * Sets whether a group sequence provider should be used.
     *
     * @param Boolean $active
     *
     * @throws GroupDefinitionException
     */
    public function setGroupSequenceProvider($active)
    {
        if ($this->hasGroupSequence()) {
            throw new GroupDefinitionException('Defining a group sequence provider is not allowed with a static group sequence');
        }

        if (!$this->getReflectionClass()->implementsInterface('Symfony\Component\Validator\GroupSequenceProviderInterface')) {
            throw new GroupDefinitionException(sprintf('Class "%s" must implement GroupSequenceProviderInterface', $this->name));
        }

        $this->groupSequenceProvider = $active;
    }

    /**
     * Returns whether the class is a group sequence provider.
     *
     * @return Boolean
     */
    public function isGroupSequenceProvider()
    {
        return $this->groupSequenceProvider;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping\Loader;

use Symfony\Component\Validator\Mapping\ClassMetadata;

interface LoaderInterface
{
    /**
     * Load a Class Metadata.
     *
     * @param ClassMetadata $metadata A metadata
     *
     * @return Boolean
     */
    public function loadClassMetadata(ClassMetadata $metadata);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping\Loader;

/**
 * Creates mapping loaders for array of files.
 *
 * Abstract class, used by
 *
 * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
 *
 * @see    Symfony\Component\Validator\Mapping\Loader\YamlFileLoader
 * @see    Symfony\Component\Validator\Mapping\Loader\XmlFileLoader
 */
abstract class FilesLoader extends LoaderChain
{
    /**
     * Array of mapping files.
     *
     * @param array $paths Array of file paths
     */
    public function __construct(array $paths)
    {
        parent::__construct($this->getFileLoaders($paths));
    }

    /**
     * Array of mapping files.
     *
     * @param array $paths Array of file paths
     *
     * @return LoaderInterface[] Array of metadata loaders
     */
    protected function getFileLoaders($paths)
    {
        $loaders = array();
        foreach ($paths as $path) {
            $loaders[] = $this->getFileLoaderInstance($path);
        }

        return $loaders;
    }

    /**
     * Takes mapping file path.
     *
     * @param string $file
     *
     * @return LoaderInterface
     */
    abstract protected function getFileLoaderInstance($file);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping\Loader;

use Symfony\Component\Validator\Exception\MappingException;

abstract class FileLoader extends AbstractLoader
{
    protected $file;

    /**
     * Constructor.
     *
     * @param string $file The mapping file to load
     *
     * @throws MappingException if the mapping file does not exist
     * @throws MappingException if the mapping file is not readable
     */
    public function __construct($file)
    {
        if (!is_file($file)) {
            throw new MappingException(sprintf('The mapping file %s does not exist', $file));
        }

        if (!is_readable($file)) {
            throw new MappingException(sprintf('The mapping file %s is not readable', $file));
        }

        $this->file = $file;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping\Loader;

use Symfony\Component\Validator\Exception\MappingException;
use Symfony\Component\Validator\Mapping\ClassMetadata;

/**
 * Calls multiple LoaderInterface instances in a chain
 *
 * This class accepts multiple instances of LoaderInterface to be passed to the
 * constructor. When loadClassMetadata() is called, the same method is called
 * in <em>all</em> of these loaders, regardless of whether any of them was
 * successful or not.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class LoaderChain implements LoaderInterface
{
    protected $loaders;

    /**
     * Accepts a list of LoaderInterface instances
     *
     * @param LoaderInterface[] $loaders An array of LoaderInterface instances
     *
     * @throws MappingException If any of the loaders does not implement LoaderInterface
     */
    public function __construct(array $loaders)
    {
        foreach ($loaders as $loader) {
            if (!$loader instanceof LoaderInterface) {
                throw new MappingException(sprintf('Class %s is expected to implement LoaderInterface', get_class($loader)));
            }
        }

        $this->loaders = $loaders;
    }

    /**
     * {@inheritDoc}
     */
    public function loadClassMetadata(ClassMetadata $metadata)
    {
        $success = false;

        foreach ($this->loaders as $loader) {
            $success = $loader->loadClassMetadata($metadata) || $success;
        }

        return $success;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping\Loader;

/**
 * Loads multiple xml mapping files
 *
 * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
 *
 * @see    Symfony\Component\Validator\Mapping\Loader\FilesLoader
 */
class XmlFilesLoader extends FilesLoader
{
    /**
     * {@inheritDoc}
     */
    public function getFileLoaderInstance($file)
    {
        return new XmlFileLoader($file);
    }
}
<?xml version="1.0" ?>

<xsd:schema xmlns="http://symfony.com/schema/dic/constraint-mapping"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://symfony.com/schema/dic/constraint-mapping"
    elementFormDefault="qualified">

  <xsd:annotation>
    <xsd:documentation><![CDATA[
      Symfony Validator Constraint Mapping Schema, version 1.0
      Authors: Bernhard Schussek

      A constraint mapping connects classes, properties and getters with
      validation constraints.
    ]]></xsd:documentation>
  </xsd:annotation>
  
  <xsd:element name="constraint-mapping" type="constraint-mapping" />
  
  <xsd:complexType name="constraint-mapping">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        The root element of the constraint mapping definition.
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:sequence>
      <xsd:element name="namespace" type="namespace" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="class" type="class" maxOccurs="unbounded" />
    </xsd:sequence>
  </xsd:complexType>
  
  <xsd:complexType name="namespace">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        Contains the abbreviation for a namespace.
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:simpleContent>
      <xsd:extension base="xsd:string">
        <xsd:attribute name="prefix" type="xsd:string" use="required" />
      </xsd:extension>
    </xsd:simpleContent>
  </xsd:complexType>
  
  <xsd:complexType name="class">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        Contains constraints for a single class.
        
        Nested elements may be class constraints, property and/or getter 
        definitions.
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:choice minOccurs="0" maxOccurs="unbounded">
      <xsd:element name="group-sequence-provider" type="group-sequence-provider" minOccurs="0" maxOccurs="1" />
      <xsd:element name="group-sequence" type="group-sequence" minOccurs="0" maxOccurs="1" />
      <xsd:element name="constraint" type="constraint" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
      <xsd:element name="getter" type="getter" minOccurs="0" maxOccurs="unbounded" />
    </xsd:choice>
    <xsd:attribute name="name" type="xsd:string" use="required" />
  </xsd:complexType>

  <xsd:complexType name="group-sequence">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        Contains the group sequence of a class. Each group should be written
        into a "value" tag.
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:sequence>
      <xsd:element name="value" type="value" minOccurs="1" maxOccurs="unbounded" />
    </xsd:sequence>
  </xsd:complexType>
  
  <xsd:complexType name="group-sequence-provider">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        Defines the name of the group sequence provider for a class.
      ]]></xsd:documentation>
    </xsd:annotation>
  </xsd:complexType>
  
  <xsd:complexType name="property">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        Contains constraints for a single property. The name of the property
        should be given in the "name" option.
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:sequence>
      <xsd:element name="constraint" type="constraint" maxOccurs="unbounded" />
    </xsd:sequence>
    <xsd:attribute name="name" type="xsd:string" use="required" />
  </xsd:complexType>
  
  <xsd:complexType name="getter">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        Contains constraints for a getter method. The name of the corresponding
        property should be given in the "property" option.
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:sequence>
      <xsd:element name="constraint" type="constraint" maxOccurs="unbounded" />
    </xsd:sequence>
    <xsd:attribute name="property" type="xsd:string" use="required" />
  </xsd:complexType>
  
  <xsd:complexType name="constraint" mixed="true">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        Contains a constraint definition. The name of the constraint should be
        given in the "name" option.
        
        May contain a single value, multiple "constraint" elements, 
        multiple "value" elements or multiple "option" elements.
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:choice minOccurs="0">
      <xsd:element name="constraint" type="constraint" minOccurs="1" maxOccurs="unbounded" />
      <xsd:element name="option" type="option" minOccurs="1" maxOccurs="unbounded" />
      <xsd:element name="value" type="value" minOccurs="1" maxOccurs="unbounded" />
    </xsd:choice>
    <xsd:attribute name="name" type="xsd:string" use="required" />    
  </xsd:complexType>
  
  <xsd:complexType name="option" mixed="true">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        Contains a constraint option definition. The name of the option
        should be given in the "name" option.
        
        May contain a single value, multiple "value" elements or multiple
        "constraint" elements.
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:choice minOccurs="0">
      <xsd:element name="constraint" type="constraint" minOccurs="1" maxOccurs="unbounded" />
      <xsd:element name="value" type="value" minOccurs="1" maxOccurs="unbounded" />
    </xsd:choice>
    <xsd:attribute name="name" type="xsd:string" use="required" />  
  </xsd:complexType>
  
  <xsd:complexType name="value" mixed="true">
    <xsd:annotation>
      <xsd:documentation><![CDATA[
        A value of an element.
        
        May contain a single value, multiple "value" elements or multiple
        "constraint" elements.
      ]]></xsd:documentation>
    </xsd:annotation>
    <xsd:choice minOccurs="0">
      <xsd:element name="constraint" type="constraint" minOccurs="1" maxOccurs="unbounded" />
      <xsd:element name="value" type="value" minOccurs="1" maxOccurs="unbounded" />
    </xsd:choice>
    <xsd:attribute name="key" type="xsd:string" use="optional" /> 
  </xsd:complexType>
</xsd:schema>
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping\Loader;

use Symfony\Component\Validator\Exception\MappingException;
use Symfony\Component\Validator\Mapping\ClassMetadata;

class StaticMethodLoader implements LoaderInterface
{
    protected $methodName;

    public function __construct($methodName = 'loadValidatorMetadata')
    {
        $this->methodName = $methodName;
    }

    /**
     * {@inheritDoc}
     */
    public function loadClassMetadata(ClassMetadata $metadata)
    {
        /** @var \ReflectionClass $reflClass */
        $reflClass = $metadata->getReflectionClass();

        if (!$reflClass->isInterface() && $reflClass->hasMethod($this->methodName)) {
            $reflMethod = $reflClass->getMethod($this->methodName);

            if ($reflMethod->isAbstract()) {
                return false;
            }

            if (!$reflMethod->isStatic()) {
                throw new MappingException(sprintf('The method %s::%s should be static', $reflClass->name, $this->methodName));
            }

            if ($reflMethod->getDeclaringClass()->name != $reflClass->name) {
                return false;
            }

            $reflMethod->invoke(null, $metadata);

            return true;
        }

        return false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping\Loader;

use Symfony\Component\Validator\Exception\MappingException;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Config\Util\XmlUtils;

class XmlFileLoader extends FileLoader
{
    /**
     * An array of SimpleXMLElement instances.
     *
     * @var \SimpleXMLElement[]
     */
    protected $classes = null;

    /**
     * {@inheritDoc}
     */
    public function loadClassMetadata(ClassMetadata $metadata)
    {
        if (null === $this->classes) {
            $this->classes = array();
            $xml = $this->parseFile($this->file);

            foreach ($xml->namespace as $namespace) {
                $this->addNamespaceAlias((string) $namespace['prefix'], trim((string) $namespace));
            }

            foreach ($xml->class as $class) {
                $this->classes[(string) $class['name']] = $class;
            }
        }

        if (isset($this->classes[$metadata->getClassName()])) {
            $xml = $this->classes[$metadata->getClassName()];

            foreach ($xml->{'group-sequence-provider'} as $provider) {
                $metadata->setGroupSequenceProvider(true);
            }

            foreach ($xml->{'group-sequence'} as $groupSequence) {
                if (count($groupSequence->value) > 0) {
                    $metadata->setGroupSequence($this->parseValues($groupSequence[0]->value));
                }
            }

            foreach ($this->parseConstraints($xml->constraint) as $constraint) {
                $metadata->addConstraint($constraint);
            }

            foreach ($xml->property as $property) {
                foreach ($this->parseConstraints($property->constraint) as $constraint) {
                    $metadata->addPropertyConstraint((string) $property['name'], $constraint);
                }
            }

            foreach ($xml->getter as $getter) {
                foreach ($this->parseConstraints($getter->constraint) as $constraint) {
                    $metadata->addGetterConstraint((string) $getter['property'], $constraint);
                }
            }

            return true;
        }

        return false;
    }

    /**
     * Parses a collection of "constraint" XML nodes.
     *
     * @param \SimpleXMLElement $nodes The XML nodes
     *
     * @return array The Constraint instances
     */
    protected function parseConstraints(\SimpleXMLElement $nodes)
    {
        $constraints = array();

        foreach ($nodes as $node) {
            if (count($node) > 0) {
                if (count($node->value) > 0) {
                    $options = $this->parseValues($node->value);
                } elseif (count($node->constraint) > 0) {
                    $options = $this->parseConstraints($node->constraint);
                } elseif (count($node->option) > 0) {
                    $options = $this->parseOptions($node->option);
                } else {
                    $options = array();
                }
            } elseif (strlen((string) $node) > 0) {
                $options = trim($node);
            } else {
                $options = null;
            }

            $constraints[] = $this->newConstraint($node['name'], $options);
        }

        return $constraints;
    }

    /**
     * Parses a collection of "value" XML nodes.
     *
     * @param \SimpleXMLElement $nodes The XML nodes
     *
     * @return array The values
     */
    protected function parseValues(\SimpleXMLElement $nodes)
    {
        $values = array();

        foreach ($nodes as $node) {
            if (count($node) > 0) {
                if (count($node->value) > 0) {
                    $value = $this->parseValues($node->value);
                } elseif (count($node->constraint) > 0) {
                    $value = $this->parseConstraints($node->constraint);
                } else {
                    $value = array();
                }
            } else {
                $value = trim($node);
            }

            if (isset($node['key'])) {
                $values[(string) $node['key']] = $value;
            } else {
                $values[] = $value;
            }
        }

        return $values;
    }

    /**
     * Parses a collection of "option" XML nodes.
     *
     * @param \SimpleXMLElement $nodes The XML nodes
     *
     * @return array The options
     */
    protected function parseOptions(\SimpleXMLElement $nodes)
    {
        $options = array();

        foreach ($nodes as $node) {
            if (count($node) > 0) {
                if (count($node->value) > 0) {
                    $value = $this->parseValues($node->value);
                } elseif (count($node->constraint) > 0) {
                    $value = $this->parseConstraints($node->constraint);
                } else {
                    $value = array();
                }
            } else {
                $value = XmlUtils::phpize($node);
                if (is_string($value)) {
                    $value = trim($value);
                }
            }

            $options[(string) $node['name']] = $value;
        }

        return $options;
    }

    /**
     * Parse a XML File.
     *
     * @param string $file Path of file
     *
     * @return \SimpleXMLElement
     *
     * @throws MappingException
     */
    protected function parseFile($file)
    {
        try {
            $dom = XmlUtils::loadFile($file, __DIR__.'/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd');
        } catch (\Exception $e) {
            throw new MappingException($e->getMessage(), $e->getCode(), $e);
        }

        return simplexml_import_dom($dom);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping\Loader;

use Symfony\Component\Validator\Exception\MappingException;
use Symfony\Component\Validator\Constraint;

abstract class AbstractLoader implements LoaderInterface
{
    /**
     * Contains all known namespaces indexed by their prefix
     * @var array
     */
    protected $namespaces = array();

    /**
     * Adds a namespace alias.
     *
     * @param string $alias     The alias
     * @param string $namespace The PHP namespace
     */
    protected function addNamespaceAlias($alias, $namespace)
    {
        $this->namespaces[$alias] = $namespace;
    }

    /**
     * Creates a new constraint instance for the given constraint name.
     *
     * @param string $name The constraint name. Either a constraint relative
     *                        to the default constraint namespace, or a fully
     *                        qualified class name
     * @param array $options The constraint options
     *
     * @return Constraint
     *
     * @throws MappingException If the namespace prefix is undefined
     */
    protected function newConstraint($name, $options)
    {
        if (strpos($name, '\\') !== false && class_exists($name)) {
            $className = (string) $name;
        } elseif (strpos($name, ':') !== false) {
            list($prefix, $className) = explode(':', $name, 2);

            if (!isset($this->namespaces[$prefix])) {
                throw new MappingException(sprintf('Undefined namespace prefix "%s"', $prefix));
            }

            $className = $this->namespaces[$prefix].$className;
        } else {
            $className = 'Symfony\\Component\\Validator\\Constraints\\'.$name;
        }

        return new $className($options);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping\Loader;

use Doctrine\Common\Annotations\Reader;
use Symfony\Component\Validator\Constraints\Callback;
use Symfony\Component\Validator\Exception\MappingException;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints\GroupSequence;
use Symfony\Component\Validator\Constraints\GroupSequenceProvider;
use Symfony\Component\Validator\Constraint;

class AnnotationLoader implements LoaderInterface
{
    protected $reader;

    public function __construct(Reader $reader)
    {
        $this->reader = $reader;
    }

    /**
     * {@inheritDoc}
     */
    public function loadClassMetadata(ClassMetadata $metadata)
    {
        $reflClass = $metadata->getReflectionClass();
        $className = $reflClass->name;
        $loaded = false;

        foreach ($this->reader->getClassAnnotations($reflClass) as $constraint) {
            if ($constraint instanceof GroupSequence) {
                $metadata->setGroupSequence($constraint->groups);
            } elseif ($constraint instanceof GroupSequenceProvider) {
                $metadata->setGroupSequenceProvider(true);
            } elseif ($constraint instanceof Constraint) {
                $metadata->addConstraint($constraint);
            }

            $loaded = true;
        }

        foreach ($reflClass->getProperties() as $property) {
            if ($property->getDeclaringClass()->name == $className) {
                foreach ($this->reader->getPropertyAnnotations($property) as $constraint) {
                    if ($constraint instanceof Constraint) {
                        $metadata->addPropertyConstraint($property->name, $constraint);
                    }

                    $loaded = true;
                }
            }
        }

        foreach ($reflClass->getMethods() as $method) {
            if ($method->getDeclaringClass()->name ==  $className) {
                foreach ($this->reader->getMethodAnnotations($method) as $constraint) {
                    if ($constraint instanceof Callback) {
                        $constraint->callback = $method->getName();
                        $constraint->methods = null;

                        $metadata->addConstraint($constraint);
                    } elseif ($constraint instanceof Constraint) {
                        if (preg_match('/^(get|is)(.+)$/i', $method->name, $matches)) {
                            $metadata->addGetterConstraint(lcfirst($matches[2]), $constraint);
                        } else {
                            throw new MappingException(sprintf('The constraint on "%s::%s" cannot be added. Constraints can only be added on methods beginning with "get" or "is".', $className, $method->name));
                        }
                    }

                    $loaded = true;
                }
            }
        }

        return $loaded;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping\Loader;

use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Yaml\Parser as YamlParser;

class YamlFileLoader extends FileLoader
{
    private $yamlParser;

    /**
     * An array of YAML class descriptions
     *
     * @var array
     */
    protected $classes = null;

    /**
     * {@inheritDoc}
     */
    public function loadClassMetadata(ClassMetadata $metadata)
    {
        if (null === $this->classes) {
            if (!stream_is_local($this->file)) {
                throw new \InvalidArgumentException(sprintf('This is not a local file "%s".', $this->file));
            }

            if (!file_exists($this->file)) {
                throw new \InvalidArgumentException(sprintf('File "%s" not found.', $this->file));
            }

            if (null === $this->yamlParser) {
                $this->yamlParser = new YamlParser();
            }

            $this->classes = $this->yamlParser->parse(file_get_contents($this->file));

            // empty file
            if (null === $this->classes) {
                return false;
            }

            // not an array
            if (!is_array($this->classes)) {
                throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $this->file));
            }

            if (isset($this->classes['namespaces'])) {
                foreach ($this->classes['namespaces'] as $alias => $namespace) {
                    $this->addNamespaceAlias($alias, $namespace);
                }

                unset($this->classes['namespaces']);
            }
        }

        // TODO validation

        if (isset($this->classes[$metadata->getClassName()])) {
            $yaml = $this->classes[$metadata->getClassName()];

            if (isset($yaml['group_sequence_provider'])) {
                $metadata->setGroupSequenceProvider((bool) $yaml['group_sequence_provider']);
            }

            if (isset($yaml['group_sequence'])) {
                $metadata->setGroupSequence($yaml['group_sequence']);
            }

            if (isset($yaml['constraints']) && is_array($yaml['constraints'])) {
                foreach ($this->parseNodes($yaml['constraints']) as $constraint) {
                    $metadata->addConstraint($constraint);
                }
            }

            if (isset($yaml['properties']) && is_array($yaml['properties'])) {
                foreach ($yaml['properties'] as $property => $constraints) {
                    if (null !== $constraints) {
                        foreach ($this->parseNodes($constraints) as $constraint) {
                            $metadata->addPropertyConstraint($property, $constraint);
                        }
                    }
                }
            }

            if (isset($yaml['getters']) && is_array($yaml['getters'])) {
                foreach ($yaml['getters'] as $getter => $constraints) {
                    if (null !== $constraints) {
                        foreach ($this->parseNodes($constraints) as $constraint) {
                            $metadata->addGetterConstraint($getter, $constraint);
                        }
                    }
                }
            }

            return true;
        }

        return false;
    }

    /**
     * Parses a collection of YAML nodes
     *
     * @param array $nodes The YAML nodes
     *
     * @return array An array of values or Constraint instances
     */
    protected function parseNodes(array $nodes)
    {
        $values = array();

        foreach ($nodes as $name => $childNodes) {
            if (is_numeric($name) && is_array($childNodes) && count($childNodes) == 1) {
                $options = current($childNodes);

                if (is_array($options)) {
                    $options = $this->parseNodes($options);
                }

                $values[] = $this->newConstraint(key($childNodes), $options);
            } else {
                if (is_array($childNodes)) {
                    $childNodes = $this->parseNodes($childNodes);
                }

                $values[$name] = $childNodes;
            }
        }

        return $values;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping\Loader;

/**
 * Loads multiple yaml mapping files
 *
 * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
 *
 * @see    Symfony\Component\Validator\Mapping\Loader\FilesLoader
 */
class YamlFilesLoader extends FilesLoader
{
    /**
     * {@inheritDoc}
     */
    public function getFileLoaderInstance($file)
    {
        return new YamlFileLoader($file);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping;

use Symfony\Component\Validator\MetadataFactoryInterface;
use Symfony\Component\Validator\Exception\NoSuchMetadataException;
use Symfony\Component\Validator\Mapping\Loader\LoaderInterface;
use Symfony\Component\Validator\Mapping\Cache\CacheInterface;

/**
 * A factory for creating metadata for PHP classes.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ClassMetadataFactory implements MetadataFactoryInterface
{
    /**
     * The loader for loading the class metadata
     * @var LoaderInterface
     */
    protected $loader;

    /**
     * The cache for caching class metadata
     * @var CacheInterface
     */
    protected $cache;

    protected $loadedClasses = array();

    public function __construct(LoaderInterface $loader = null, CacheInterface $cache = null)
    {
        $this->loader = $loader;
        $this->cache = $cache;
    }

    /**
     * {@inheritdoc}
     */
    public function getMetadataFor($value)
    {
        if (!is_object($value) && !is_string($value)) {
            throw new NoSuchMetadataException(sprintf('Cannot create metadata for non-objects. Got: %s', gettype($value)));
        }

        $class = ltrim(is_object($value) ? get_class($value) : $value, '\\');

        if (isset($this->loadedClasses[$class])) {
            return $this->loadedClasses[$class];
        }

        if (null !== $this->cache && false !== ($this->loadedClasses[$class] = $this->cache->read($class))) {
            return $this->loadedClasses[$class];
        }

        if (!class_exists($class) && !interface_exists($class)) {
            throw new NoSuchMetadataException(sprintf('The class or interface "%s" does not exist.', $class));
        }

        $metadata = new ClassMetadata($class);

        // Include constraints from the parent class
        if ($parent = $metadata->getReflectionClass()->getParentClass()) {
            $metadata->mergeConstraints($this->getMetadataFor($parent->name));
        }

        // Include constraints from all implemented interfaces
        foreach ($metadata->getReflectionClass()->getInterfaces() as $interface) {
            if ('Symfony\Component\Validator\GroupSequenceProviderInterface' === $interface->name) {
                continue;
            }
            $metadata->mergeConstraints($this->getMetadataFor($interface->name));
        }

        if (null !== $this->loader) {
            $this->loader->loadClassMetadata($metadata);
        }

        if (null !== $this->cache) {
            $this->cache->write($metadata);
        }

        return $this->loadedClasses[$class] = $metadata;
    }

    /**
     * {@inheritdoc}
     */
    public function hasMetadataFor($value)
    {
        if (!is_object($value) && !is_string($value)) {
            return false;
        }

        $class = ltrim(is_object($value) ? get_class($value) : $value, '\\');

        if (class_exists($class) || interface_exists($class)) {
            return true;
        }

        return false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Mapping;

use Symfony\Component\Validator\Exception\ValidatorException;

class GetterMetadata extends MemberMetadata
{
    /**
     * Constructor.
     *
     * @param string $class    The class the getter is defined on
     * @param string $property The property which the getter returns
     *
     * @throws ValidatorException
     */
    public function __construct($class, $property)
    {
        $getMethod = 'get'.ucfirst($property);
        $isMethod = 'is'.ucfirst($property);

        if (method_exists($class, $getMethod)) {
            $method = $getMethod;
        } elseif (method_exists($class, $isMethod)) {
            $method = $isMethod;
        } else {
            throw new ValidatorException(sprintf('Neither method %s nor %s exists in class %s', $getMethod, $isMethod, $class));
        }

        parent::__construct($class, $method, $property);
    }

    /**
     * {@inheritDoc}
     */
    public function getPropertyValue($object)
    {
        return $this->newReflectionMember($object)->invoke($object);
    }

    /**
     * {@inheritDoc}
     */
    protected function newReflectionMember($objectOrClassName)
    {
        return new \ReflectionMethod($objectOrClassName, $this->getName());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

use Symfony\Component\Validator\Exception\InvalidOptionsException;
use Symfony\Component\Validator\Exception\MissingOptionsException;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;

/**
 * Contains the properties of a constraint definition.
 *
 * A constraint can be defined on a class, an option or a getter method.
 * The Constraint class encapsulates all the configuration required for
 * validating this class, option or getter result successfully.
 *
 * Constraint instances are immutable and serializable.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
abstract class Constraint
{
    /**
     * The name of the group given to all constraints with no explicit group
     * @var string
     */
    const DEFAULT_GROUP = 'Default';

    /**
     * Marks a constraint that can be put onto classes
     * @var string
     */
    const CLASS_CONSTRAINT = 'class';

    /**
     * Marks a constraint that can be put onto properties
     * @var string
     */
    const PROPERTY_CONSTRAINT = 'property';

    /**
     * @var array
     */
    public $groups = array(self::DEFAULT_GROUP);

    /**
     * Initializes the constraint with options.
     *
     * You should pass an associative array. The keys should be the names of
     * existing properties in this class. The values should be the value for these
     * properties.
     *
     * Alternatively you can override the method getDefaultOption() to return the
     * name of an existing property. If no associative array is passed, this
     * property is set instead.
     *
     * You can force that certain options are set by overriding
     * getRequiredOptions() to return the names of these options. If any
     * option is not set here, an exception is thrown.
     *
     * @param mixed $options The options (as associative array)
     *                       or the value for the default
     *                       option (any other type)
     *
     * @throws InvalidOptionsException       When you pass the names of non-existing
     *                                       options
     * @throws MissingOptionsException       When you don't pass any of the options
     *                                       returned by getRequiredOptions()
     * @throws ConstraintDefinitionException When you don't pass an associative
     *                                       array, but getDefaultOption() returns
     *                                       NULL
     *
     * @api
     */
    public function __construct($options = null)
    {
        $invalidOptions = array();
        $missingOptions = array_flip((array) $this->getRequiredOptions());

        if (is_array($options) && count($options) >= 1 && isset($options['value']) && !property_exists($this, 'value')) {
            $options[$this->getDefaultOption()] = $options['value'];
            unset($options['value']);
        }

        if (is_array($options) && count($options) > 0 && is_string(key($options))) {
            foreach ($options as $option => $value) {
                if (property_exists($this, $option)) {
                    $this->$option = $value;
                    unset($missingOptions[$option]);
                } else {
                    $invalidOptions[] = $option;
                }
            }
        } elseif (null !== $options && ! (is_array($options) && count($options) === 0)) {
            $option = $this->getDefaultOption();

            if (null === $option) {
                throw new ConstraintDefinitionException(
                    sprintf('No default option is configured for constraint %s', get_class($this))
                );
            }

            if (property_exists($this, $option)) {
                $this->$option = $options;
                unset($missingOptions[$option]);
            } else {
                $invalidOptions[] = $option;
            }
        }

        if (count($invalidOptions) > 0) {
            throw new InvalidOptionsException(
                sprintf('The options "%s" do not exist in constraint %s', implode('", "', $invalidOptions), get_class($this)),
                $invalidOptions
            );
        }

        if (count($missingOptions) > 0) {
            throw new MissingOptionsException(
                sprintf('The options "%s" must be set for constraint %s', implode('", "', array_keys($missingOptions)), get_class($this)),
                array_keys($missingOptions)
            );
        }

        $this->groups = (array) $this->groups;
    }

    /**
     * Unsupported operation.
     */
    public function __set($option, $value)
    {
        throw new InvalidOptionsException(sprintf('The option "%s" does not exist in constraint %s', $option, get_class($this)), array($option));
    }

    /**
     * Adds the given group if this constraint is in the Default group
     *
     * @param string $group
     *
     * @api
     */
    public function addImplicitGroupName($group)
    {
        if (in_array(Constraint::DEFAULT_GROUP, $this->groups) && !in_array($group, $this->groups)) {
            $this->groups[] = $group;
        }
    }

    /**
     * Returns the name of the default option
     *
     * Override this method to define a default option.
     *
     * @return string
     * @see __construct()
     *
     * @api
     */
    public function getDefaultOption()
    {
        return null;
    }

    /**
     * Returns the name of the required options
     *
     * Override this method if you want to define required options.
     *
     * @return array
     * @see __construct()
     *
     * @api
     */
    public function getRequiredOptions()
    {
        return array();
    }

    /**
     * Returns the name of the class that validates this constraint
     *
     * By default, this is the fully qualified name of the constraint class
     * suffixed with "Validator". You can override this method to change that
     * behaviour.
     *
     * @return string
     *
     * @api
     */
    public function validatedBy()
    {
        return get_class($this).'Validator';
    }

    /**
     * Returns whether the constraint can be put onto classes, properties or
     * both
     *
     * This method should return one or more of the constants
     * Constraint::CLASS_CONSTRAINT and Constraint::PROPERTY_CONSTRAINT.
     *
     * @return string|array  One or more constant values
     *
     * @api
     */
    public function getTargets()
    {
        return self::PROPERTY_CONSTRAINT;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * Base class for constraint validators
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
abstract class ConstraintValidator implements ConstraintValidatorInterface
{
    /**
     * @var ExecutionContextInterface
     */
    protected $context;

    /**
     * {@inheritDoc}
     */
    public function initialize(ExecutionContextInterface $context)
    {
        $this->context = $context;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * A container for validation metadata.
 *
 * The container contains constraints that may belong to different validation
 * groups. Constraints for a specific group can be fetched by calling
 * {@link findConstraints}.
 *
 * Implement this interface to add validation metadata to your own metadata
 * layer. Each metadata may have named properties. Each property can be
 * represented by one or more {@link PropertyMetadataInterface} instances that
 * are returned by {@link getPropertyMetadata}. Since
 * <tt>PropertyMetadataInterface</tt> inherits from <tt>MetadataInterface</tt>,
 * each property may be divided into further properties.
 *
 * The {@link accept} method of each metadata implements the Visitor pattern.
 * The method should forward the call to the visitor's
 * {@link ValidationVisitorInterface::visit} method and additionally call
 * <tt>accept()</tt> on all structurally related metadata instances.
 *
 * For example, to store constraints for PHP classes and their properties,
 * create a class <tt>ClassMetadata</tt> (implementing <tt>MetadataInterface</tt>)
 * and a class <tt>PropertyMetadata</tt> (implementing <tt>PropertyMetadataInterface</tt>).
 * <tt>ClassMetadata::getPropertyMetadata($property)</tt> returns all
 * <tt>PropertyMetadata</tt> instances for a property of that class. Its
 * <tt>accept()</tt>-method simply forwards to <tt>ValidationVisitorInterface::visit()</tt>
 * and calls <tt>accept()</tt> on all contained <tt>PropertyMetadata</tt>
 * instances, which themselves call <tt>ValidationVisitorInterface::visit()</tt>
 * again.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface MetadataInterface
{
    /**
     * Implementation of the Visitor design pattern.
     *
     * Calls {@link ValidationVisitorInterface::visit} and then forwards the
     * <tt>accept()</tt>-call to all property metadata instances.
     *
     * @param ValidationVisitorInterface $visitor      The visitor implementing the validation logic.
     * @param mixed                      $value        The value to validate.
     * @param string|string[]            $group        The validation group to validate in.
     * @param string                     $propertyPath The current property path in the validation graph.
     */
    public function accept(ValidationVisitorInterface $visitor, $value, $group, $propertyPath);

    /**
     * Returns all constraints for a given validation group.
     *
     * @param string $group The validation group.
     *
     * @return Constraint[] A list of constraint instances.
     */
    public function findConstraints($group);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
use Symfony\Component\Validator\Mapping\Cache\CacheInterface;
use Symfony\Component\Translation\TranslatorInterface;
use Doctrine\Common\Annotations\Reader;

/**
 * A configurable builder for ValidatorInterface objects.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface ValidatorBuilderInterface
{
    /**
     * Adds an object initializer to the validator.
     *
     * @param ObjectInitializerInterface $initializer The initializer.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function addObjectInitializer(ObjectInitializerInterface $initializer);

    /**
     * Adds a list of object initializers to the validator.
     *
     * @param array $initializers The initializer.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function addObjectInitializers(array $initializers);

    /**
     * Adds an XML constraint mapping file to the validator.
     *
     * @param string $path The path to the mapping file.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function addXmlMapping($path);

    /**
     * Adds a list of XML constraint mapping files to the validator.
     *
     * @param array $paths The paths to the mapping files.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function addXmlMappings(array $paths);

    /**
     * Adds a YAML constraint mapping file to the validator.
     *
     * @param string $path The path to the mapping file.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function addYamlMapping($path);

    /**
     * Adds a list of YAML constraint mappings file to the validator.
     *
     * @param array $paths The paths to the mapping files.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function addYamlMappings(array $paths);

    /**
     * Enables constraint mapping using the given static method.
     *
     * @param string $methodName The name of the method.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function addMethodMapping($methodName);

    /**
     * Enables constraint mapping using the given static methods.
     *
     * @param array $methodNames The names of the methods.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function addMethodMappings(array $methodNames);

    /**
     * Enables annotation based constraint mapping.
     *
     * @param Reader $annotationReader The annotation reader to be used.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function enableAnnotationMapping(Reader $annotationReader = null);

    /**
     * Disables annotation based constraint mapping.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function disableAnnotationMapping();

    /**
     * Sets the class metadata factory used by the validator.
     *
     * @param MetadataFactoryInterface $metadataFactory The metadata factory.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function setMetadataFactory(MetadataFactoryInterface $metadataFactory);

    /**
     * Sets the cache for caching class metadata.
     *
     * @param CacheInterface $cache The cache instance.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function setMetadataCache(CacheInterface $cache);

    /**
     * Sets the constraint validator factory used by the validator.
     *
     * @param ConstraintValidatorFactoryInterface $validatorFactory The validator factory.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function setConstraintValidatorFactory(ConstraintValidatorFactoryInterface $validatorFactory);

    /**
     * Sets the translator used for translating violation messages.
     *
     * @param TranslatorInterface $translator The translator instance.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function setTranslator(TranslatorInterface $translator);

    /**
     * Sets the default translation domain of violation messages.
     *
     * The same message can have different translations in different domains.
     * Pass the domain that is used for violation messages by default to this
     * method.
     *
     * @param string $translationDomain The translation domain of the violation messages.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function setTranslationDomain($translationDomain);

    /**
     * Sets the property accessor for resolving property paths.
     *
     * @param PropertyAccessorInterface $propertyAccessor The property accessor.
     *
     * @return ValidatorBuilderInterface The builder object.
     */
    public function setPropertyAccessor(PropertyAccessorInterface $propertyAccessor);

    /**
     * Builds and returns a new validator object.
     *
     * @return ValidatorInterface The built validator.
     */
    public function getValidator();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * Default implementation of {@ConstraintViolationInterface}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ConstraintViolation implements ConstraintViolationInterface
{
    /**
     * @var string
     */
    private $message;

    /**
     * @var string
     */
    private $messageTemplate;

    /**
     * @var array
     */
    private $messageParameters;

    /**
     * @var integer|null
     */
    private $messagePluralization;

    /**
     * @var mixed
     */
    private $root;

    /**
     * @var string
     */
    private $propertyPath;

    /**
     * @var mixed
     */
    private $invalidValue;

    /**
     * @var mixed
     */
    private $code;

    /**
     * Creates a new constraint violation.
     *
     * @param string       $message               The violation message.
     * @param string       $messageTemplate       The raw violation message.
     * @param array        $messageParameters     The parameters to substitute
     *                                            in the raw message.
     * @param mixed        $root                  The value originally passed
     *                                            to the validator.
     * @param string       $propertyPath          The property path from the
     *                                            root value to the invalid
     *                                            value.
     * @param mixed        $invalidValue          The invalid value causing the
     *                                            violation.
     * @param integer|null $messagePluralization  The pluralization parameter.
     * @param mixed        $code                  The error code of the
     *                                            violation, if any.
     */
    public function __construct($message, $messageTemplate, array $messageParameters, $root, $propertyPath, $invalidValue, $messagePluralization = null, $code = null)
    {
        $this->message = $message;
        $this->messageTemplate = $messageTemplate;
        $this->messageParameters = $messageParameters;
        $this->messagePluralization = $messagePluralization;
        $this->root = $root;
        $this->propertyPath = $propertyPath;
        $this->invalidValue = $invalidValue;
        $this->code = $code;
    }

    /**
     * Converts the violation into a string for debugging purposes.
     *
     * @return string The violation as string.
     */
    public function __toString()
    {
        $class = (string) (is_object($this->root) ? get_class($this->root) : $this->root);
        $propertyPath = (string) $this->propertyPath;
        $code = $this->code;

        if ('' !== $propertyPath && '[' !== $propertyPath[0] && '' !== $class) {
            $class .= '.';
        }

        if (!empty($code)) {
            $code = ' (code '.$code.')';
        }

        return $class.$propertyPath.":\n    ".$this->getMessage().$code;
    }

    /**
     * {@inheritDoc}
     */
    public function getMessageTemplate()
    {
        return $this->messageTemplate;
    }

    /**
     * {@inheritDoc}
     */
    public function getMessageParameters()
    {
        return $this->messageParameters;
    }

    /**
     * {@inheritDoc}
     */
    public function getMessagePluralization()
    {
        return $this->messagePluralization;
    }

    /**
     * {@inheritDoc}
     */
    public function getMessage()
    {
        return $this->message;
    }

    /**
     * {@inheritDoc}
     */
    public function getRoot()
    {
        return $this->root;
    }

    /**
     * {@inheritDoc}
     */
    public function getPropertyPath()
    {
        return $this->propertyPath;
    }

    /**
     * {@inheritDoc}
     */
    public function getInvalidValue()
    {
        return $this->invalidValue;
    }

    /**
     * {@inheritDoc}
     */
    public function getCode()
    {
        return $this->code;
    }
}
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Validator Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./vendor</directory>
                <directory>./Tests</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * Default implementation of {@ConstraintViolationListInterface}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ConstraintViolationList implements \IteratorAggregate, ConstraintViolationListInterface
{
    /**
     * @var ConstraintViolationInterface[]
     */
    private $violations = array();

    /**
     * Creates a new constraint violation list.
     *
     * @param ConstraintViolationInterface[] $violations The constraint violations to add to the list
     */
    public function __construct(array $violations = array())
    {
        foreach ($violations as $violation) {
            $this->add($violation);
        }
    }

    /**
     * Converts the violation into a string for debugging purposes.
     *
     * @return string The violation as string.
     */
    public function __toString()
    {
        $string = '';

        foreach ($this->violations as $violation) {
            $string .= $violation."\n";
        }

        return $string;
    }

    /**
     * {@inheritDoc}
     */
    public function add(ConstraintViolationInterface $violation)
    {
        $this->violations[] = $violation;
    }

    /**
     * {@inheritDoc}
     */
    public function addAll(ConstraintViolationListInterface $otherList)
    {
        foreach ($otherList as $violation) {
            $this->violations[] = $violation;
        }
    }

    /**
     * {@inheritDoc}
     */
    public function get($offset)
    {
        if (!isset($this->violations[$offset])) {
            throw new \OutOfBoundsException(sprintf('The offset "%s" does not exist.', $offset));
        }

        return $this->violations[$offset];
    }

    /**
     * {@inheritDoc}
     */
    public function has($offset)
    {
        return isset($this->violations[$offset]);
    }

    /**
     * {@inheritDoc}
     */
    public function set($offset, ConstraintViolationInterface $violation)
    {
        $this->violations[$offset] = $violation;
    }

    /**
     * {@inheritDoc}
     */
    public function remove($offset)
    {
        unset($this->violations[$offset]);
    }

    /**
     * {@inheritDoc}
     */
    public function getIterator()
    {
        return new \ArrayIterator($this->violations);
    }

    /**
     * {@inheritDoc}
     */
    public function count()
    {
        return count($this->violations);
    }

    /**
     * {@inheritDoc}
     */
    public function offsetExists($offset)
    {
        return $this->has($offset);
    }

    /**
     * {@inheritDoc}
     */
    public function offsetGet($offset)
    {
        return $this->get($offset);
    }

    /**
     * {@inheritDoc}
     */
    public function offsetSet($offset, $violation)
    {
        if (null === $offset) {
            $this->add($violation);
        } else {
            $this->set($offset, $violation);
        }
    }

    /**
     * {@inheritDoc}
     */
    public function offsetUnset($offset)
    {
        $this->remove($offset);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * A container for {@link PropertyMetadataInterface} instances.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface PropertyMetadataContainerInterface
{
    /**
     * Check if there's any metadata attached to the given named property.
     *
     * @param string $property The property name.
     *
     * @return Boolean
     */
    public function hasPropertyMetadata($property);

    /**
     * Returns all metadata instances for the given named property.
     *
     * If your implementation does not support properties, simply throw an
     * exception in this method (for example a <tt>BadMethodCallException</tt>).
     *
     * @param string $property The property name.
     *
     * @return PropertyMetadataInterface[] A list of metadata instances. Empty if
     *                                     no metadata exists for the property.
     */
    public function getPropertyMetadata($property);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
interface ConstraintValidatorInterface
{
    /**
     * Initializes the constraint validator.
     *
     * @param ExecutionContextInterface $context The current validation context
     */
    public function initialize(ExecutionContextInterface $context);

    /**
     * Checks if the passed value is valid.
     *
     * @param mixed      $value      The value that should be validated
     * @param Constraint $constraint The constraint for the validation
     *
     * @api
     */
    public function validate($value, Constraint $constraint);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

use Symfony\Component\Translation\TranslatorInterface;

/**
 * Default implementation of {@link ExecutionContextInterface}.
 *
 * This class is immutable by design.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ExecutionContext implements ExecutionContextInterface
{
    /**
     * @var GlobalExecutionContextInterface
     */
    private $globalContext;

    /**
     * @var TranslatorInterface
     */
    private $translator;

    /**
     * @var null|string
     */
    private $translationDomain;

    /**
     * @var MetadataInterface
     */
    private $metadata;

    /**
     * @var mixed
     */
    private $value;

    /**
     * @var string
     */
    private $group;

    /**
     * @var string
     */
    private $propertyPath;

    /**
     * Creates a new execution context.
     *
     * @param GlobalExecutionContextInterface $globalContext     The global context storing node-independent state.
     * @param TranslatorInterface             $translator        The translator for translating violation messages.
     * @param null|string                     $translationDomain The domain of the validation messages.
     * @param MetadataInterface               $metadata          The metadata of the validated node.
     * @param mixed                           $value             The value of the validated node.
     * @param string                          $group             The current validation group.
     * @param string                          $propertyPath      The property path to the current node.
     */
    public function __construct(GlobalExecutionContextInterface $globalContext, TranslatorInterface $translator, $translationDomain = null, MetadataInterface $metadata = null, $value = null, $group = null, $propertyPath = '')
    {
        if (null === $group) {
            $group = Constraint::DEFAULT_GROUP;
        }

        $this->globalContext = $globalContext;
        $this->translator = $translator;
        $this->translationDomain = $translationDomain;
        $this->metadata = $metadata;
        $this->value = $value;
        $this->propertyPath = $propertyPath;
        $this->group = $group;
    }

    /**
     * {@inheritdoc}
     */
    public function addViolation($message, array $params = array(), $invalidValue = null, $pluralization = null, $code = null)
    {
        if (null === $pluralization) {
            $translatedMessage = $this->translator->trans($message, $params, $this->translationDomain);
        } else {
            try {
                $translatedMessage = $this->translator->transChoice($message, $pluralization, $params, $this->translationDomain);
            } catch (\InvalidArgumentException $e) {
                $translatedMessage = $this->translator->trans($message, $params, $this->translationDomain);
            }
        }

        $this->globalContext->getViolations()->add(new ConstraintViolation(
            $translatedMessage,
            $message,
            $params,
            $this->globalContext->getRoot(),
            $this->propertyPath,
            // check using func_num_args() to allow passing null values
            func_num_args() >= 3 ? $invalidValue : $this->value,
            $pluralization,
            $code
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function addViolationAt($subPath, $message, array $params = array(), $invalidValue = null, $pluralization = null, $code = null)
    {
        $this->globalContext->getViolations()->add(new ConstraintViolation(
            null === $pluralization
                ? $this->translator->trans($message, $params, $this->translationDomain)
                : $this->translator->transChoice($message, $pluralization, $params, $this->translationDomain),
            $message,
            $params,
            $this->globalContext->getRoot(),
            $this->getPropertyPath($subPath),
            // check using func_num_args() to allow passing null values
            func_num_args() >= 4 ? $invalidValue : $this->value,
            $pluralization,
            $code
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getViolations()
    {
        return $this->globalContext->getViolations();
    }

    /**
     * {@inheritdoc}
     */
    public function getRoot()
    {
        return $this->globalContext->getRoot();
    }

    /**
     * {@inheritdoc}
     */
    public function getPropertyPath($subPath = '')
    {
        if ('' != $subPath && '' !== $this->propertyPath && '[' !== $subPath[0]) {
            return $this->propertyPath.'.'.$subPath;
        }

        return $this->propertyPath.$subPath;
    }

    /**
     * {@inheritdoc}
     */
    public function getClassName()
    {
        if ($this->metadata instanceof ClassBasedInterface) {
            return $this->metadata->getClassName();
        }

        return null;
    }

    /**
     * {@inheritdoc}
     */
    public function getPropertyName()
    {
        if ($this->metadata instanceof PropertyMetadataInterface) {
            return $this->metadata->getPropertyName();
        }

        return null;
    }

    /**
     * {@inheritdoc}
     */
    public function getValue()
    {
        return $this->value;
    }

    /**
     * {@inheritdoc}
     */
    public function getGroup()
    {
        return $this->group;
    }

    /**
     * {@inheritdoc}
     */
    public function getMetadata()
    {
        return $this->metadata;
    }

    /**
     * {@inheritdoc}
     */
    public function getMetadataFor($value)
    {
        return $this->globalContext->getMetadataFactory()->getMetadataFor($value);
    }

    /**
     * {@inheritdoc}
     */
    public function validate($value, $subPath = '', $groups = null, $traverse = false, $deep = false)
    {
        $propertyPath = $this->getPropertyPath($subPath);

        foreach ($this->resolveGroups($groups) as $group) {
            $this->globalContext->getVisitor()->validate($value, $group, $propertyPath, $traverse, $deep);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function validateValue($value, $constraints, $subPath = '', $groups = null)
    {
        $constraints = is_array($constraints) ? $constraints : array($constraints);

        if (null === $groups && '' === $subPath) {
            $context = clone $this;
            $context->value = $value;
            $context->executeConstraintValidators($value, $constraints);

            return;
        }

        $propertyPath = $this->getPropertyPath($subPath);

        foreach ($this->resolveGroups($groups) as $group) {
            $context = clone $this;
            $context->value = $value;
            $context->group = $group;
            $context->propertyPath = $propertyPath;
            $context->executeConstraintValidators($value, $constraints);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function getMetadataFactory()
    {
        return $this->globalContext->getMetadataFactory();
    }

    /**
     * Executes the validators of the given constraints for the given value.
     *
     * @param mixed        $value       The value to validate.
     * @param Constraint[] $constraints The constraints to match against.
     */
    private function executeConstraintValidators($value, array $constraints)
    {
        foreach ($constraints as $constraint) {
            $validator = $this->globalContext->getValidatorFactory()->getInstance($constraint);
            $validator->initialize($this);
            $validator->validate($value, $constraint);
        }
    }

    /**
     * Returns an array of group names.
     *
     * @param null|string|string[] $groups The groups to resolve. If a single string is
     *                                     passed, it is converted to an array. If null
     *                                     is passed, an array containing the current
     *                                     group of the context is returned.
     *
     * @return array An array of validation groups.
     */
    private function resolveGroups($groups)
    {
        return $groups ? (array) $groups : (array) $this->group;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * Prepares an object for validation.
 *
 * Concrete implementations of this interface are used by {@link ValidationVisitorInterface}
 * to initialize objects just before validating them.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bernhard Schussek <bschussek@gmail.com>
 *
 * @api
 */
interface ObjectInitializerInterface
{
    /**
     * Initializes an object just before validation.
     *
     * @param object $object The object to validate
     *
     * @api
     */
    public function initialize($object);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * Validates values against constraints defined in {@link MetadataInterface}
 * instances.
 *
 * This interface is an implementation of the Visitor design pattern. A value
 * is validated by first passing it to the {@link validate} method. That method
 * will determine the matching {@link MetadataInterface} for validating the
 * value. It then calls the {@link MetadataInterface::accept} method of that
 * metadata. <tt>accept()</tt> does two things:
 *
 * <ol>
 * <li>It calls {@link visit} to validate the value against the constraints of
 * the metadata.</li>
 * <li>It calls <tt>accept()</tt> on all nested metadata instances with the
 * corresponding values extracted from the current value. For example, if the
 * current metadata represents a class and the current value is an object of
 * that class, the metadata contains nested instances for each property of that
 * class. It forwards the call to these nested metadata with the values of the
 * corresponding properties in the original object.</li>
 * </ol>
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface ValidationVisitorInterface
{
    /**
     * Validates a value.
     *
     * If the value is an array or a traversable object, you can set the
     * parameter <tt>$traverse</tt> to <tt>true</tt> in order to run through
     * the collection and validate each element. If these elements can be
     * collections again and you want to traverse them recursively, set the
     * parameter <tt>$deep</tt> to <tt>true</tt> as well.
     *
     * If you set <tt>$traversable</tt> to <tt>true</tt>, the visitor will
     * nevertheless try to find metadata for the collection and validate its
     * constraints. If no such metadata is found, the visitor ignores that and
     * only iterates the collection.
     *
     * If you don't set <tt>$traversable</tt> to <tt>true</tt> and the visitor
     * does not find metadata for the given value, it will fail with an
     * exception.
     *
     * @param mixed   $value        The value to validate.
     * @param string  $group        The validation group to validate.
     * @param string  $propertyPath The current property path in the validation graph.
     * @param Boolean $traverse     Whether to traverse the value if it is traversable.
     * @param Boolean $deep         Whether to traverse nested traversable values recursively.
     *
     * @throws Exception\NoSuchMetadataException If no metadata can be found for
     *                                           the given value.
     */
    public function validate($value, $group, $propertyPath, $traverse = false, $deep = false);

    /**
     * Validates a value against the constraints defined in some metadata.
     *
     * This method implements the Visitor design pattern. See also
     * {@link ValidationVisitorInterface}.
     *
     * @param MetadataInterface $metadata     The metadata holding the constraints.
     * @param mixed             $value        The value to validate.
     * @param string            $group        The validation group to validate.
     * @param string            $propertyPath The current property path in the validation graph.
     */
    public function visit(MetadataInterface $metadata, $value, $group, $propertyPath);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

use Symfony\Component\Validator\Exception\NoSuchMetadataException;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Translation\TranslatorInterface;

/**
 * Default implementation of {@link ValidationVisitorInterface} and
 * {@link GlobalExecutionContextInterface}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ValidationVisitor implements ValidationVisitorInterface, GlobalExecutionContextInterface
{
    /**
     * @var mixed
     */
    private $root;

    /**
     * @var MetadataFactoryInterface
     */
    private $metadataFactory;

    /**
     * @var ConstraintValidatorFactoryInterface
     */
    private $validatorFactory;

    /**
     * @var TranslatorInterface
     */
    private $translator;

    /**
     * @var null|string
     */
    private $translationDomain;

    /**
     * @var array
     */
    private $objectInitializers;

    /**
     * @var ConstraintViolationList
     */
    private $violations;

    /**
     * @var array
     */
    private $validatedObjects = array();

    /**
     * Creates a new validation visitor.
     *
     * @param mixed                               $root               The value passed to the validator.
     * @param MetadataFactoryInterface            $metadataFactory    The factory for obtaining metadata instances.
     * @param ConstraintValidatorFactoryInterface $validatorFactory   The factory for creating constraint validators.
     * @param TranslatorInterface                 $translator         The translator for translating violation messages.
     * @param string|null                         $translationDomain  The domain of the translation messages.
     * @param ObjectInitializerInterface[]        $objectInitializers The initializers for preparing objects before validation.
     *
     * @throws UnexpectedTypeException If any of the object initializers is not an instance of ObjectInitializerInterface
     */
    public function __construct($root, MetadataFactoryInterface $metadataFactory, ConstraintValidatorFactoryInterface $validatorFactory, TranslatorInterface $translator, $translationDomain = null, array $objectInitializers = array())
    {
        foreach ($objectInitializers as $initializer) {
            if (!$initializer instanceof ObjectInitializerInterface) {
                throw new UnexpectedTypeException($initializer, 'Symfony\Component\Validator\ObjectInitializerInterface');
            }
        }

        $this->root = $root;
        $this->metadataFactory = $metadataFactory;
        $this->validatorFactory = $validatorFactory;
        $this->translator = $translator;
        $this->translationDomain = $translationDomain;
        $this->objectInitializers = $objectInitializers;
        $this->violations = new ConstraintViolationList();
    }

    /**
     * {@inheritdoc}
     */
    public function visit(MetadataInterface $metadata, $value, $group, $propertyPath)
    {
        $context = new ExecutionContext(
            $this,
            $this->translator,
            $this->translationDomain,
            $metadata,
            $value,
            $group,
            $propertyPath
        );

        $context->validateValue($value, $metadata->findConstraints($group));
    }

    /**
     * {@inheritdoc}
     */
    public function validate($value, $group, $propertyPath, $traverse = false, $deep = false)
    {
        if (null === $value) {
            return;
        }

        if (is_object($value)) {
            $hash = spl_object_hash($value);

            // Exit, if the object is already validated for the current group
            if (isset($this->validatedObjects[$hash][$group])) {
                return;
            }

            // Remember validating this object before starting and possibly
            // traversing the object graph
            $this->validatedObjects[$hash][$group] = true;

            foreach ($this->objectInitializers as $initializer) {
                if (!$initializer instanceof ObjectInitializerInterface) {
                    throw new \LogicException('Validator initializers must implement ObjectInitializerInterface.');
                }
                $initializer->initialize($value);
            }
        }

        // Validate arrays recursively by default, otherwise every driver needs
        // to implement special handling for arrays.
        // https://github.com/symfony/symfony/issues/6246
        if (is_array($value) || ($traverse && $value instanceof \Traversable)) {
            foreach ($value as $key => $element) {
                // Ignore any scalar values in the collection
                if (is_object($element) || is_array($element)) {
                    // Only repeat the traversal if $deep is set
                    $this->validate($element, $group, $propertyPath.'['.$key.']', $deep, $deep);
                }
            }

            try {
                $this->metadataFactory->getMetadataFor($value)->accept($this, $value, $group, $propertyPath);
            } catch (NoSuchMetadataException $e) {
                // Metadata doesn't necessarily have to exist for
                // traversable objects, because we know how to validate
                // them anyway. Optionally, additional metadata is supported.
            }
        } else {
            $this->metadataFactory->getMetadataFor($value)->accept($this, $value, $group, $propertyPath);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function getViolations()
    {
        return $this->violations;
    }

    /**
     * {@inheritdoc}
     */
    public function getRoot()
    {
        return $this->root;
    }

    /**
     * {@inheritdoc}
     */
    public function getVisitor()
    {
        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function getValidatorFactory()
    {
        return $this->validatorFactory;
    }

    /**
     * {@inheritdoc}
     */
    public function getMetadataFactory()
    {
        return $this->metadataFactory;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

use Symfony\Component\Validator\Constraints\Valid;
use Symfony\Component\Validator\Exception\ValidatorException;
use Symfony\Component\Translation\TranslatorInterface;

/**
 * Default implementation of {@link ValidatorInterface}.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class Validator implements ValidatorInterface
{
    /**
     * @var MetadataFactoryInterface
     */
    private $metadataFactory;

    /**
     * @var ConstraintValidatorFactoryInterface
     */
    private $validatorFactory;

    /**
     * @var TranslatorInterface
     */
    private $translator;

    /**
     * @var null|string
     */
    private $translationDomain;

    /**
     * @var array
     */
    private $objectInitializers;

    public function __construct(
        MetadataFactoryInterface $metadataFactory,
        ConstraintValidatorFactoryInterface $validatorFactory,
        TranslatorInterface $translator,
        $translationDomain = 'validators',
        array $objectInitializers = array()
    )
    {
        $this->metadataFactory = $metadataFactory;
        $this->validatorFactory = $validatorFactory;
        $this->translator = $translator;
        $this->translationDomain = $translationDomain;
        $this->objectInitializers = $objectInitializers;
    }

    /**
     * {@inheritdoc}
     */
    public function getMetadataFactory()
    {
        return $this->metadataFactory;
    }

    /**
     * {@inheritDoc}
     */
    public function getMetadataFor($value)
    {
        return $this->metadataFactory->getMetadataFor($value);
    }

    /**
     * {@inheritDoc}
     */
    public function validate($value, $groups = null, $traverse = false, $deep = false)
    {
        $visitor = $this->createVisitor($value);

        foreach ($this->resolveGroups($groups) as $group) {
            $visitor->validate($value, $group, '', $traverse, $deep);
        }

        return $visitor->getViolations();
    }

    /**
     * {@inheritDoc}
     *
     * @throws ValidatorException If the metadata for the value does not support properties.
     */
    public function validateProperty($containingValue, $property, $groups = null)
    {
        $visitor = $this->createVisitor($containingValue);
        $metadata = $this->metadataFactory->getMetadataFor($containingValue);

        if (!$metadata instanceof PropertyMetadataContainerInterface) {
            $valueAsString = is_scalar($containingValue)
                ? '"'.$containingValue.'"'
                : 'the value of type '.gettype($containingValue);

            throw new ValidatorException(sprintf('The metadata for '.$valueAsString.' does not support properties.'));
        }

        foreach ($this->resolveGroups($groups) as $group) {
            if (!$metadata->hasPropertyMetadata($property)) {
                continue;
            }

            foreach ($metadata->getPropertyMetadata($property) as $propMeta) {
                $propMeta->accept($visitor, $propMeta->getPropertyValue($containingValue), $group, $property);
            }
        }

        return $visitor->getViolations();
    }

    /**
     * {@inheritDoc}
     *
     * @throws ValidatorException If the metadata for the value does not support properties.
     */
    public function validatePropertyValue($containingValue, $property, $value, $groups = null)
    {
        $visitor = $this->createVisitor($containingValue);
        $metadata = $this->metadataFactory->getMetadataFor($containingValue);

        if (!$metadata instanceof PropertyMetadataContainerInterface) {
            $valueAsString = is_scalar($containingValue)
                ? '"'.$containingValue.'"'
                : 'the value of type '.gettype($containingValue);

            throw new ValidatorException(sprintf('The metadata for '.$valueAsString.' does not support properties.'));
        }

        foreach ($this->resolveGroups($groups) as $group) {
            if (!$metadata->hasPropertyMetadata($property)) {
                continue;
            }

            foreach ($metadata->getPropertyMetadata($property) as $propMeta) {
                $propMeta->accept($visitor, $value, $group, $property);
            }
        }

        return $visitor->getViolations();
    }

    /**
     * {@inheritDoc}
     */
    public function validateValue($value, $constraints, $groups = null)
    {
        $context = new ExecutionContext($this->createVisitor($value), $this->translator, $this->translationDomain);

        $constraints = is_array($constraints) ? $constraints : array($constraints);

        foreach ($constraints as $constraint) {
            if ($constraint instanceof Valid) {
                // Why can't the Valid constraint be executed directly?
                //
                // It cannot be executed like regular other constraints, because regular
                // constraints are only executed *if they belong to the validated group*.
                // The Valid constraint, on the other hand, is always executed and propagates
                // the group to the cascaded object. The propagated group depends on
                //
                //  * Whether a group sequence is currently being executed. Then the default
                //    group is propagated.
                //
                //  * Otherwise the validated group is propagated.

                throw new ValidatorException(
                    sprintf(
                        'The constraint %s cannot be validated. Use the method validate() instead.',
                        get_class($constraint)
                    )
                );
            }

            $context->validateValue($value, $constraint, '', $groups);
        }

        return $context->getViolations();
    }

    /**
     * @param mixed $root
     *
     * @return ValidationVisitor
     */
    private function createVisitor($root)
    {
        return new ValidationVisitor(
            $root,
            $this->metadataFactory,
            $this->validatorFactory,
            $this->translator,
            $this->translationDomain,
            $this->objectInitializers
        );
    }

    /**
     * @param null|string|string[] $groups
     *
     * @return string[]
     */
    private function resolveGroups($groups)
    {
        return $groups ? (array) $groups : array(Constraint::DEFAULT_GROUP);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

use Symfony\Component\Validator\Exception\BadMethodCallException;
use Symfony\Component\Validator\Exception\InvalidArgumentException;
use Symfony\Component\Translation\TranslatorInterface;

/**
 * Simple translator implementation that simply replaces the parameters in
 * the message IDs.
 *
 * Example usage:
 *
 *     $translator = new DefaultTranslator();
 *
 *     echo $translator->trans(
 *         'This is a {{ var }}.',
 *         array('{{ var }}' => 'donkey')
 *     );
 *
 *     // -> This is a donkey.
 *
 *     echo $translator->transChoice(
 *         'This is {{ count }} donkey.|These are {{ count }} donkeys.',
 *         3,
 *         array('{{ count }}' => 'three')
 *     );
 *
 *     // -> These are three donkeys.
 *
 * This translator does not support message catalogs, translation domains or
 * locales. Instead, it implements a subset of the capabilities of
 * {@link \Symfony\Component\Translation\Translator} and can be used in places
 * where translation is not required by default but should be optional.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class DefaultTranslator implements TranslatorInterface
{
    /**
     * Interpolates the given message.
     *
     * Parameters are replaced in the message in the same manner that
     * {@link strtr()} uses.
     *
     * Example usage:
     *
     *     $translator = new DefaultTranslator();
     *
     *     echo $translator->trans(
     *         'This is a {{ var }}.',
     *         array('{{ var }}' => 'donkey')
     *     );
     *
     *     // -> This is a donkey.
     *
     * @param string $id         The message id
     * @param array  $parameters An array of parameters for the message
     * @param string $domain     Ignored
     * @param string $locale     Ignored
     *
     * @return string The interpolated string
     */
    public function trans($id, array $parameters = array(), $domain = null, $locale = null)
    {
        return strtr($id, $parameters);
    }

    /**
     * Interpolates the given choice message by choosing a variant according to a number.
     *
     * The variants are passed in the message ID using the format
     * "<singular>|<plural>". "<singular>" is chosen if the passed $number is
     * exactly 1. "<plural>" is chosen otherwise.
     *
     * This format is consistent with the format supported by
     * {@link \Symfony\Component\Translation\Translator}, but it does not
     * have the same expressiveness. While Translator supports intervals in
     * message translations, which are needed for languages other than English,
     * this translator does not. You should use Translator or a custom
     * implementation of {@link TranslatorInterface} if you need this or similar
     * functionality.
     *
     * Example usage:
     *
     *     echo $translator->transChoice(
     *         'This is {{ count }} donkey.|These are {{ count }} donkeys.',
     *         0,
     *         array('{{ count }}' => 0)
     *     );
     *
     *     // -> These are 0 donkeys.
     *
     *     echo $translator->transChoice(
     *         'This is {{ count }} donkey.|These are {{ count }} donkeys.',
     *         1,
     *         array('{{ count }}' => 1)
     *     );
     *
     *     // -> This is 1 donkey.
     *
     *     echo $translator->transChoice(
     *         'This is {{ count }} donkey.|These are {{ count }} donkeys.',
     *         3,
     *         array('{{ count }}' => 3)
     *     );
     *
     *     // -> These are 3 donkeys.
     *
     * @param string  $id         The message id
     * @param integer $number     The number to use to find the index of the message
     * @param array   $parameters An array of parameters for the message
     * @param string  $domain     Ignored
     * @param string  $locale     Ignored
     *
     * @return string The translated string
     *
     * @throws InvalidArgumentException If the message id does not have the format
     *                                  "singular|plural".
     */
    public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null)
    {
        $ids = explode('|', $id);

        if (1 == $number) {
            return strtr($ids[0], $parameters);
        }

        if (!isset($ids[1])) {
            throw new InvalidArgumentException(sprintf('The message "%s" cannot be pluralized, because it is missing a plural (e.g. "There is one apple|There are %%count%% apples").', $id));
        }

        return strtr($ids[1], $parameters);
    }

    /**
     * Not supported.
     *
     * @param string $locale The locale
     *
     * @throws BadMethodCallException
     */
    public function setLocale($locale)
    {
        throw new BadMethodCallException('Unsupported method.');
    }

    /**
     * Returns the locale of the translator.
     *
     * @return string Always returns 'en'
     */
    public function getLocale()
    {
        return 'en';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Exception;

class MappingException extends ValidatorException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Exception;

/**
 * Base InvalidArgumentException for the Validator component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Exception;

/**
 * Base RuntimeException for the Validator component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Exception;

class ValidatorException extends \RuntimeException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Exception;

class InvalidOptionsException extends ValidatorException
{
    private $options;

    public function __construct($message, array $options)
    {
        parent::__construct($message);

        $this->options = $options;
    }

    public function getOptions()
    {
        return $this->options;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Exception;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class NoSuchMetadataException extends ValidatorException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Exception;

class MissingOptionsException extends ValidatorException
{
    private $options;

    public function __construct($message, array $options)
    {
        parent::__construct($message);

        $this->options = $options;
    }

    public function getOptions()
    {
        return $this->options;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Exception;

class GroupDefinitionException extends ValidatorException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Exception;

/**
 * Base ExceptionInterface for the Validator component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Exception;

/**
 * Base BadMethodCallException for the Validator component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Exception;

class UnexpectedTypeException extends ValidatorException
{
    public function __construct($value, $expectedType)
    {
        parent::__construct(sprintf('Expected argument of type %s, %s given', $expectedType, gettype($value)));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Exception;

class ConstraintDefinitionException extends ValidatorException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * Entry point for the Validator component.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
final class Validation
{
    /**
     * Creates a new validator.
     *
     * If you want to configure the validator, use
     * {@link createValidatorBuilder()} instead.
     *
     * @return ValidatorInterface The new validator.
     */
    public static function createValidator()
    {
        return self::createValidatorBuilder()->getValidator();
    }

    /**
     * Creates a configurable builder for validator objects.
     *
     * @return ValidatorBuilderInterface The new builder.
     */
    public static function createValidatorBuilder()
    {
        return new ValidatorBuilder();
    }

    /**
     * This class cannot be instantiated.
     */
    private function __construct()
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * Stores the node-independent state of a validation run.
 *
 * When the validator validates a graph of objects, it uses two classes to
 * store the state during the validation:
 *
 * <ul>
 * <li>For each node in the validation graph (objects, properties, getters) the
 * validator creates an instance of {@link ExecutionContextInterface} that
 * stores the information about that node.</li>
 * <li>One single <tt>GlobalExecutionContextInterface</tt> stores the state
 * that is independent of the current node.</li>
 * </ul>
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface GlobalExecutionContextInterface
{
    /**
     * Returns the violations generated by the validator so far.
     *
     * @return ConstraintViolationListInterface A list of constraint violations.
     */
    public function getViolations();

    /**
     * Returns the value at which validation was started in the object graph.
     *
     * @return mixed The root value.
     *
     * @see ExecutionContextInterface::getRoot
     */
    public function getRoot();

    /**
     * Returns the visitor instance used to validate the object graph nodes.
     *
     * @return ValidationVisitorInterface The validation visitor.
     */
    public function getVisitor();

    /**
     * Returns the factory for constraint validators.
     *
     * @return ConstraintValidatorFactoryInterface The constraint validator factory.
     */
    public function getValidatorFactory();

    /**
     * Returns the factory for validation metadata objects.
     *
     * @return MetadataFactoryInterface The metadata factory.
     */
    public function getMetadataFactory();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Range;
use Symfony\Component\Validator\Constraints\NotNull;
use Symfony\Component\Validator\Constraints\Required;
use Symfony\Component\Validator\Constraints\Optional;
use Symfony\Component\Validator\Constraints\Collection;
use Symfony\Component\Validator\Constraints\CollectionValidator;

abstract class CollectionValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new CollectionValidator();
        $this->validator->initialize($this->context);

        $this->context->expects($this->any())
            ->method('getGroup')
            ->will($this->returnValue('MyGroup'));
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    abstract protected function prepareTestData(array $contents);

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolationAt');

        $this->validator->validate(null, new Collection(array('fields' => array(
            'foo' => new Range(array('min' => 4)),
        ))));
    }

    public function testFieldsAsDefaultOption()
    {
        $data = $this->prepareTestData(array('foo' => 'foobar'));

        $this->context->expects($this->never())
            ->method('addViolationAt');

        $this->validator->validate($data, new Collection(array(
            'foo' => new Range(array('min' => 4)),
        )));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testThrowsExceptionIfNotTraversable()
    {
        $this->validator->validate('foobar', new Collection(array('fields' => array(
            'foo' => new Range(array('min' => 4)),
        ))));
    }

    public function testWalkSingleConstraint()
    {
        $constraint = new Range(array('min' => 4));

        $array = array(
            'foo' => 3,
            'bar' => 5,
        );
        $i = 1;

        foreach ($array as $key => $value) {
            $this->context->expects($this->at($i++))
                ->method('validateValue')
                ->with($value, $constraint, '['.$key.']', 'MyGroup');
        }

        $data = $this->prepareTestData($array);

        $this->context->expects($this->never())
            ->method('addViolationAt');

        $this->validator->validate($data, new Collection(array(
            'fields' => array(
                'foo' => $constraint,
                'bar' => $constraint,
            ),
        )));
    }

    public function testWalkMultipleConstraints()
    {
        $constraints = array(
            new Range(array('min' => 4)),
            new NotNull(),
        );

        $array = array(
            'foo' => 3,
            'bar' => 5,
        );
        $i = 1;

        foreach ($array as $key => $value) {
            foreach ($constraints as $constraint) {
                $this->context->expects($this->at($i++))
                    ->method('validateValue')
                    ->with($value, $constraint, '['.$key.']', 'MyGroup');
            }
        }

        $data = $this->prepareTestData($array);

        $this->context->expects($this->never())
            ->method('addViolationAt');

        $this->validator->validate($data, new Collection(array(
            'fields' => array(
                'foo' => $constraints,
                'bar' => $constraints,
            )
        )));
    }

    public function testExtraFieldsDisallowed()
    {
        $data = $this->prepareTestData(array(
            'foo' => 5,
            'baz' => 6,
        ));

        $this->context->expects($this->once())
            ->method('addViolationAt')
            ->with('[baz]', 'myMessage', array(
                '{{ field }}' => 'baz'
            ));

        $this->validator->validate($data, new Collection(array(
            'fields' => array(
                'foo' => new Range(array('min' => 4)),
            ),
            'extraFieldsMessage' => 'myMessage',
        )));
    }

    // bug fix
    public function testNullNotConsideredExtraField()
    {
        $data = $this->prepareTestData(array(
            'foo' => null,
        ));

        $constraint = new Collection(array(
            'fields' => array(
                'foo' => new Range(array('min' => 4)),
            ),
        ));

        $this->context->expects($this->never())
            ->method('addViolationAt');

        $this->validator->validate($data, $constraint);
    }

    public function testExtraFieldsAllowed()
    {
        $data = $this->prepareTestData(array(
            'foo' => 5,
            'bar' => 6,
        ));

        $constraint = new Collection(array(
            'fields' => array(
                'foo' => new Range(array('min' => 4)),
            ),
            'allowExtraFields' => true,
        ));

        $this->context->expects($this->never())
            ->method('addViolationAt');

        $this->validator->validate($data, $constraint);
    }

    public function testMissingFieldsDisallowed()
    {
        $data = $this->prepareTestData(array());

        $constraint = new Collection(array(
            'fields' => array(
                'foo' => new Range(array('min' => 4)),
            ),
            'missingFieldsMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolationAt')
            ->with('[foo]', 'myMessage', array(
                '{{ field }}' => 'foo',
            ));

        $this->validator->validate($data, $constraint);
    }

    public function testMissingFieldsAllowed()
    {
        $data = $this->prepareTestData(array());

        $constraint = new Collection(array(
            'fields' => array(
                'foo' => new Range(array('min' => 4)),
            ),
            'allowMissingFields' => true,
        ));

        $this->context->expects($this->never())
            ->method('addViolationAt');

        $this->validator->validate($data, $constraint);
    }

    public function testOptionalFieldPresent()
    {
        $data = $this->prepareTestData(array(
            'foo' => null,
        ));

        $this->context->expects($this->never())
            ->method('addViolationAt');

        $this->validator->validate($data, new Collection(array(
            'foo' => new Optional(),
        )));
    }

    public function testOptionalFieldNotPresent()
    {
        $data = $this->prepareTestData(array());

        $this->context->expects($this->never())
            ->method('addViolationAt');

        $this->validator->validate($data, new Collection(array(
            'foo' => new Optional(),
        )));
    }

    public function testOptionalFieldSingleConstraint()
    {
        $array = array(
            'foo' => 5,
        );

        $constraint = new Range(array('min' => 4));

        $this->context->expects($this->once())
            ->method('validateValue')
            ->with($array['foo'], $constraint, '[foo]', 'MyGroup');

        $this->context->expects($this->never())
            ->method('addViolationAt');

        $data = $this->prepareTestData($array);

        $this->validator->validate($data, new Collection(array(
            'foo' => new Optional($constraint),
        )));
    }

    public function testOptionalFieldMultipleConstraints()
    {
        $array = array(
            'foo' => 5,
        );

        $constraints = array(
            new NotNull(),
            new Range(array('min' => 4)),
        );
        $i = 1;

        foreach ($constraints as $constraint) {
            $this->context->expects($this->at($i++))
                ->method('validateValue')
                ->with($array['foo'], $constraint, '[foo]', 'MyGroup');
        }

        $this->context->expects($this->never())
            ->method('addViolationAt');

        $data = $this->prepareTestData($array);

        $this->validator->validate($data, new Collection(array(
            'foo' => new Optional($constraints),
        )));
    }

    public function testRequiredFieldPresent()
    {
        $data = $this->prepareTestData(array(
            'foo' => null,
        ));

        $this->context->expects($this->never())
            ->method('addViolationAt');

        $this->validator->validate($data, new Collection(array(
            'foo' => new Required(),
        )));
    }

    public function testRequiredFieldNotPresent()
    {
        $data = $this->prepareTestData(array());

        $this->context->expects($this->once())
            ->method('addViolationAt')
            ->with('[foo]', 'myMessage', array(
                '{{ field }}' => 'foo',
            ));

        $this->validator->validate($data, new Collection(array(
            'fields' => array(
                'foo' => new Required(),
            ),
            'missingFieldsMessage' => 'myMessage',
        )));
    }

    public function testRequiredFieldSingleConstraint()
    {
        $array = array(
            'foo' => 5,
        );

        $constraint = new Range(array('min' => 4));

        $this->context->expects($this->once())
            ->method('validateValue')
            ->with($array['foo'], $constraint, '[foo]', 'MyGroup');

        $this->context->expects($this->never())
            ->method('addViolationAt');

        $data = $this->prepareTestData($array);

        $this->validator->validate($data, new Collection(array(
            'foo' => new Required($constraint),
        )));
    }

    public function testRequiredFieldMultipleConstraints()
    {
        $array = array(
            'foo' => 5,
        );

        $constraints = array(
            new NotNull(),
            new Range(array('min' => 4)),
        );
        $i = 1;

        foreach ($constraints as $constraint) {
            $this->context->expects($this->at($i++))
                ->method('validateValue')
                ->with($array['foo'], $constraint, '[foo]', 'MyGroup');
        }

        $this->context->expects($this->never())
            ->method('addViolationAt');

        $data = $this->prepareTestData($array);

        $this->validator->validate($array, new Collection(array(
            'foo' => new Required($constraints),
        )));
    }

    public function testObjectShouldBeLeftUnchanged()
    {
        $value = new \ArrayObject(array(
            'foo' => 3
        ));

        $this->validator->validate($value, new Collection(array(
            'fields' => array(
                'foo' => new Range(array('min' => 2)),
            )
        )));

        $this->assertEquals(array(
            'foo' => 3
        ), (array) $value);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\EmailValidator;

class EmailValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new EmailValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Email());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Email());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $this->validator->validate(new \stdClass(), new Email());
    }

    /**
     * @dataProvider getValidEmails
     */
    public function testValidEmails($email)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($email, new Email());
    }

    public function getValidEmails()
    {
        return array(
            array('fabien@symfony.com'),
            array('example@example.co.uk'),
            array('fabien_potencier@example.fr'),
        );
    }

    /**
     * @dataProvider getInvalidEmails
     */
    public function testInvalidEmails($email)
    {
        $constraint = new Email(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $email,
            ));

        $this->validator->validate($email, $constraint);
    }

    public function getInvalidEmails()
    {
        return array(
            array('example'),
            array('example@'),
            array('example@localhost'),
            array('example@example.com@example.com'),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Image;
use Symfony\Component\Validator\Constraints\ImageValidator;

class ImageValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;
    protected $path;
    protected $image;
    protected $imageLandscape;
    protected $imagePortrait;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new ImageValidator();
        $this->validator->initialize($this->context);
        $this->image = __DIR__.'/Fixtures/test.gif';
        $this->imageLandscape = __DIR__.'/Fixtures/test_landscape.gif';
        $this->imagePortrait = __DIR__.'/Fixtures/test_portrait.gif';
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Image());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Image());
    }

    public function testValidImage()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($this->image, new Image());
    }

    public function testValidSize()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new Image(array(
            'minWidth' => 1,
            'maxWidth' => 2,
            'minHeight' => 1,
            'maxHeight' => 2,
        ));

        $this->validator->validate($this->image, $constraint);
    }

    public function testWidthTooSmall()
    {
        $constraint = new Image(array(
            'minWidth' => 3,
            'minWidthMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ width }}' => '2',
                '{{ min_width }}' => '3',
            ));

        $this->validator->validate($this->image, $constraint);
    }

    public function testWidthTooBig()
    {
        $constraint = new Image(array(
            'maxWidth' => 1,
            'maxWidthMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ width }}' => '2',
                '{{ max_width }}' => '1',
            ));

        $this->validator->validate($this->image, $constraint);
    }

    public function testHeightTooSmall()
    {
        $constraint = new Image(array(
            'minHeight' => 3,
            'minHeightMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ height }}' => '2',
                '{{ min_height }}' => '3',
            ));

        $this->validator->validate($this->image, $constraint);
    }

    public function testHeightTooBig()
    {
        $constraint = new Image(array(
            'maxHeight' => 1,
            'maxHeightMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ height }}' => '2',
                '{{ max_height }}' => '1',
            ));

        $this->validator->validate($this->image, $constraint);
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testInvalidMinWidth()
    {
        $constraint = new Image(array(
            'minWidth' => '1abc',
        ));

        $this->validator->validate($this->image, $constraint);
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testInvalidMaxWidth()
    {
        $constraint = new Image(array(
            'maxWidth' => '1abc',
        ));

        $this->validator->validate($this->image, $constraint);
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testInvalidMinHeight()
    {
        $constraint = new Image(array(
            'minHeight' => '1abc',
        ));

        $this->validator->validate($this->image, $constraint);
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testInvalidMaxHeight()
    {
        $constraint = new Image(array(
            'maxHeight' => '1abc',
        ));

        $this->validator->validate($this->image, $constraint);
    }

    public function testRatioTooSmall()
    {
        $constraint = new Image(array(
            'minRatio' => 2,
            'minRatioMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ ratio }}' => 1,
                '{{ min_ratio }}' => 2,
            ));

        $this->validator->validate($this->image, $constraint);
    }

    public function testRatioTooBig()
    {
        $constraint = new Image(array(
            'maxRatio' => 0.5,
            'maxRatioMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ ratio }}' => 1,
                '{{ max_ratio }}' => 0.5,
            ));

        $this->validator->validate($this->image, $constraint);
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testInvalidMinRatio()
    {
        $constraint = new Image(array(
            'minRatio' => '1abc',
        ));

        $this->validator->validate($this->image, $constraint);
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testInvalidMaxRatio()
    {
        $constraint = new Image(array(
            'maxRatio' => '1abc',
        ));

        $this->validator->validate($this->image, $constraint);
    }

    public function testSquareNotAllowed()
    {
        $constraint = new Image(array(
            'allowSquare' => false,
            'allowSquareMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ width }}' => 2,
                '{{ height }}' => 2,
            ));

        $this->validator->validate($this->image, $constraint);
    }

    public function testLandscapeNotAllowed()
    {
        $constraint = new Image(array(
            'allowLandscape' => false,
            'allowLandscapeMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ width }}' => 2,
                '{{ height }}' => 1,
            ));

        $this->validator->validate($this->imageLandscape, $constraint);
    }

    public function testPortraitNotAllowed()
    {
        $constraint = new Image(array(
            'allowPortrait' => false,
            'allowPortraitMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ width }}' => 1,
                '{{ height }}' => 2,
            ));

        $this->validator->validate($this->imagePortrait, $constraint);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\NotNull;
use Symfony\Component\Validator\Constraints\NotNullValidator;

class NotNullValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new NotNullValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    /**
     * @dataProvider getValidValues
     */
    public function testValidValues($value)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($value, new NotNull());
    }

    public function getValidValues()
    {
        return array(
            array(0),
            array(false),
            array(true),
            array(''),
        );
    }

    public function testNullIsInvalid()
    {
        $constraint = new NotNull(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
            ));

        $this->validator->validate(null, $constraint);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Blank;
use Symfony\Component\Validator\Constraints\BlankValidator;

class BlankValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new BlankValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Blank());
    }

    public function testBlankIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Blank());
    }

    /**
     * @dataProvider getInvalidValues
     */
    public function testInvalidValues($value)
    {
        $constraint = new Blank(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $value,
            ));

        $this->validator->validate($value, $constraint);
    }

    public function getInvalidValues()
    {
        return array(
            array('foobar'),
            array(0),
            array(false),
            array(1234),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Count;
use Symfony\Component\Validator\Constraints\CountValidator;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
abstract class CountValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new CountValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    abstract protected function createCollection(array $content);

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Count(6));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsCountableType()
    {
        $this->validator->validate(new \stdClass(), new Count(5));
    }

    public function getThreeOrLessElements()
    {
        return array(
            array($this->createCollection(array(1))),
            array($this->createCollection(array(1, 2))),
            array($this->createCollection(array(1, 2, 3))),
            array($this->createCollection(array('a' => 1, 'b' => 2, 'c' => 3))),
        );
    }

    public function getFourElements()
    {
        return array(
            array($this->createCollection(array(1, 2, 3, 4))),
            array($this->createCollection(array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4))),
        );
    }

    public function getNotFourElements()
    {
        return array_merge(
            $this->getThreeOrLessElements(),
            $this->getFiveOrMoreElements()
        );
    }

    public function getFiveOrMoreElements()
    {
        return array(
            array($this->createCollection(array(1, 2, 3, 4, 5))),
            array($this->createCollection(array(1, 2, 3, 4, 5, 6))),
            array($this->createCollection(array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5))),
        );
    }

    /**
     * @dataProvider getThreeOrLessElements
     */
    public function testValidValuesMax($value)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new Count(array('max' => 3));
        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getFiveOrMoreElements
     */
    public function testValidValuesMin($value)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new Count(array('min' => 5));
        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getFourElements
     */
    public function testValidValuesExact($value)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new Count(4);
        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getFiveOrMoreElements
     */
    public function testInvalidValuesMax($value)
    {
        $constraint = new Count(array(
            'max' => 4,
            'maxMessage' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', $this->identicalTo(array(
                '{{ count }}' => count($value),
                '{{ limit }}' => 4,
            )), $value, 4);

        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getThreeOrLessElements
     */
    public function testInvalidValuesMin($value)
    {
        $constraint = new Count(array(
            'min' => 4,
            'minMessage' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', $this->identicalTo(array(
                '{{ count }}' => count($value),
                '{{ limit }}' => 4,
            )), $value, 4);

        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getNotFourElements
     */
    public function testInvalidValuesExact($value)
    {
        $constraint = new Count(array(
            'min' => 4,
            'max' => 4,
            'exactMessage' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', $this->identicalTo(array(
            '{{ count }}' => count($value),
            '{{ limit }}' => 4,
        )), $value, 4);

        $this->validator->validate($value, $constraint);
    }

    public function testDefaultOption()
    {
        $constraint = new Count(5);

        $this->assertEquals(5, $constraint->min);
        $this->assertEquals(5, $constraint->max);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Choice;
use Symfony\Component\Validator\Constraints\ChoiceValidator;

function choice_callback()
{
    return array('foo', 'bar');
}

class ChoiceValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    public static function staticCallback()
    {
        return array('foo', 'bar');
    }

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new ChoiceValidator();
        $this->validator->initialize($this->context);

        $this->context->expects($this->any())
            ->method('getClassName')
            ->will($this->returnValue(__CLASS__));
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectArrayIfMultipleIsTrue()
    {
        $constraint = new Choice(array(
            'choices' => array('foo', 'bar'),
            'multiple' => true,
        ));

        $this->validator->validate('asdf', $constraint);
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Choice(array('choices' => array('foo', 'bar'))));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testChoicesOrCallbackExpected()
    {
        $this->validator->validate('foobar', new Choice());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testValidCallbackExpected()
    {
        $this->validator->validate('foobar', new Choice(array('callback' => 'abcd')));
    }

    public function testValidChoiceArray()
    {
        $constraint = new Choice(array('choices' => array('foo', 'bar')));

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('bar', $constraint);
    }

    public function testValidChoiceCallbackFunction()
    {
        $constraint = new Choice(array('callback' => __NAMESPACE__.'\choice_callback'));

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('bar', $constraint);
    }

    public function testValidChoiceCallbackClosure()
    {
        $constraint = new Choice(array('callback' => function() {
            return array('foo', 'bar');
        }));

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('bar', $constraint);
    }

    public function testValidChoiceCallbackStaticMethod()
    {
        $constraint = new Choice(array('callback' => array(__CLASS__, 'staticCallback')));

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('bar', $constraint);
    }

    public function testValidChoiceCallbackContextMethod()
    {
        $constraint = new Choice(array('callback' => 'staticCallback'));

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('bar', $constraint);
    }

    public function testMultipleChoices()
    {
        $constraint = new Choice(array(
            'choices' => array('foo', 'bar', 'baz'),
            'multiple' => true,
        ));

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(array('baz', 'bar'), $constraint);
    }

    public function testInvalidChoice()
    {
        $constraint = new Choice(array(
            'choices' => array('foo', 'bar'),
            'message' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => 'baz',
            ), null, null);

        $this->validator->validate('baz', $constraint);
    }

    public function testInvalidChoiceMultiple()
    {
        $constraint = new Choice(array(
            'choices' => array('foo', 'bar'),
            'multipleMessage' => 'myMessage',
            'multiple' => true,
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => 'baz',
            ));

        $this->validator->validate(array('foo', 'baz'), $constraint);
    }

    public function testTooFewChoices()
    {
        $constraint = new Choice(array(
            'choices' => array('foo', 'bar', 'moo', 'maa'),
            'multiple' => true,
            'min' => 2,
            'minMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ limit }}' => 2,
            ), null, 2);

        $this->validator->validate(array('foo'), $constraint);
    }

    public function testTooManyChoices()
    {
        $constraint = new Choice(array(
            'choices' => array('foo', 'bar', 'moo', 'maa'),
            'multiple' => true,
            'max' => 2,
            'maxMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ limit }}' => 2,
            ), null, 2);

        $this->validator->validate(array('foo', 'bar', 'moo'), $constraint);
    }

    public function testNonStrict()
    {
        $constraint = new Choice(array(
            'choices' => array(1, 2),
            'strict' => false,
        ));

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('2', $constraint);
        $this->validator->validate(2, $constraint);
    }

    public function testStrictAllowsExactValue()
    {
        $constraint = new Choice(array(
            'choices' => array(1, 2),
            'strict' => true,
        ));

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(2, $constraint);
    }

    public function testStrictDisallowsDifferentType()
    {
        $constraint = new Choice(array(
            'choices' => array(1, 2),
            'strict' => true,
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => '2',
            ));

        $this->validator->validate('2', $constraint);
    }

    public function testNonStrictWithMultipleChoices()
    {
        $constraint = new Choice(array(
            'choices' => array(1, 2, 3),
            'multiple' => true,
            'strict' => false
        ));

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(array('2', 3), $constraint);
    }

    public function testStrictWithMultipleChoices()
    {
        $constraint = new Choice(array(
            'choices' => array(1, 2, 3),
            'multiple' => true,
            'strict' => true,
            'multipleMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => '3',
            ));

        $this->validator->validate(array(2, '3'), $constraint);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Issn;
use Symfony\Component\Validator\Constraints\IssnValidator;

/**
 * @see https://en.wikipedia.org/wiki/Issn
 */
class IssnValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    public function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new IssnValidator();
        $this->validator->initialize($this->context);
    }

    public function getValidLowerCasedIssn()
    {
        return array(
            array('2162-321x'),
            array('2160-200x'),
            array('1537-453x'),
            array('1937-710x'),
            array('0002-922x'),
            array('1553-345x'),
            array('1553-619x'),
        );
    }

    public function getValidNonHyphenatedIssn()
    {
        return array(
            array('2162321X'),
            array('01896016'),
            array('15744647'),
            array('14350645'),
            array('07174055'),
            array('20905076'),
            array('14401592'),
        );
    }

    public function getFullValidIssn()
    {
        return array(
            array('1550-7416'),
            array('1539-8560'),
            array('2156-5376'),
            array('1119-023X'),
            array('1684-5315'),
            array('1996-0786'),
            array('1684-5374'),
            array('1996-0794')
        );
    }

    public function getValidIssn()
    {
        return array_merge(
            $this->getValidLowerCasedIssn(),
            $this->getValidNonHyphenatedIssn(),
            $this->getFullValidIssn()
        );
    }

    public function getInvalidFormatedIssn()
    {
        return array(
            array(0),
            array('1539'),
            array('2156-537A')
        );
    }

    public function getInvalidValueIssn()
    {
        return array(
            array('1119-0231'),
            array('1684-5312'),
            array('1996-0783'),
            array('1684-537X'),
            array('1996-0795')
        );

    }

    public function getInvalidIssn()
    {
        return array_merge(
            $this->getInvalidFormatedIssn(),
            $this->getInvalidValueIssn()
        );
    }

    public function testNullIsValid()
    {
        $constraint = new Issn();
        $this->context
            ->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, $constraint);
    }

    public function testEmptyStringIsValid()
    {
        $constraint = new Issn();
        $this->context
            ->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', $constraint);
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $constraint = new Issn();
        $this->validator->validate(new \stdClass(), $constraint);
    }

    /**
     * @dataProvider getValidLowerCasedIssn
     */
    public function testCaseSensitiveIssns($issn)
    {
        $constraint = new Issn(array('caseSensitive' => true));
        $this->context
            ->expects($this->once())
            ->method('addViolation')
            ->with($constraint->message);

        $this->validator->validate($issn, $constraint);
    }

    /**
     * @dataProvider getValidNonHyphenatedIssn
     */
    public function testRequireHyphenIssns($issn)
    {
        $constraint = new Issn(array('requireHyphen' => true));
        $this->context
            ->expects($this->once())
            ->method('addViolation')
            ->with($constraint->message);

        $this->validator->validate($issn, $constraint);
    }

    /**
     * @dataProvider getValidIssn
     */
    public function testValidIssn($issn)
    {
        $constraint = new Issn();
        $this->context
            ->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($issn, $constraint);
    }

    /**
     * @dataProvider getInvalidFormatedIssn
     */
    public function testInvalidFormatIssn($issn)
    {
        $constraint = new Issn();
        $this->context
            ->expects($this->once())
            ->method('addViolation')
            ->with($constraint->message);

        $this->validator->validate($issn, $constraint);
    }

    /**
     * @dataProvider getInvalidValueIssn
     */
    public function testInvalidValueIssn($issn)
    {
        $constraint = new Issn();
        $this->context
            ->expects($this->once())
            ->method('addViolation')
            ->with($constraint->message);

        $this->validator->validate($issn, $constraint);
    }

    /**
     * @dataProvider getInvalidIssn
     */
    public function testInvalidIssn($issn)
    {
        $constraint = new Issn();
        $this->context
            ->expects($this->once())
            ->method('addViolation');

        $this->validator->validate($issn, $constraint);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\IdenticalTo;
use Symfony\Component\Validator\Constraints\IdenticalToValidator;
use Symfony\Component\Validator\Tests\Constraints\AbstractComparisonValidatorTestCase;

/**
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class IdenticalToValidatorTest extends AbstractComparisonValidatorTestCase
{
    protected function createValidator()
    {
        return new IdenticalToValidator();
    }

    protected function createConstraint(array $options)
    {
        return new IdenticalTo($options);
    }

    /**
     * {@inheritDoc}
     */
    public function provideValidComparisons()
    {
        $date = new \DateTime('2000-01-01');
        $object = new ComparisonTest_Class(2);

        return array(
            array(3, 3),
            array('a', 'a'),
            array($date, $date),
            array($object, $object),
            array(null, 1),
        );
    }

    /**
     * {@inheritDoc}
     */
    public function provideInvalidComparisons()
    {
        return array(
            array(1, 2, '2', 'integer'),
            array(2, '2', "'2'", 'string'),
            array('22', '333', "'333'", 'string'),
            array(new \DateTime('2001-01-01'), new \DateTime('2001-01-01'), '2001-01-01 00:00:00', 'DateTime'),
            array(new \DateTime('2001-01-01'), new \DateTime('1999-01-01'), '1999-01-01 00:00:00', 'DateTime'),
            array(new ComparisonTest_Class(4), new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Time;
use Symfony\Component\Validator\Constraints\TimeValidator;

class TimeValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new TimeValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Time());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Time());
    }

    public function testDateTimeClassIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(new \DateTime(), new Time());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $this->validator->validate(new \stdClass(), new Time());
    }

    /**
     * @dataProvider getValidTimes
     */
    public function testValidTimes($time)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($time, new Time());
    }

    public function getValidTimes()
    {
        return array(
            array('01:02:03'),
            array('00:00:00'),
            array('23:59:59'),
        );
    }

    /**
     * @dataProvider getInvalidTimes
     */
    public function testInvalidTimes($time)
    {
        $constraint = new Time(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $time,
            ));

        $this->validator->validate($time, $constraint);
    }

    public function getInvalidTimes()
    {
        return array(
            array('foobar'),
            array('foobar 12:34:56'),
            array('12:34:56 foobar'),
            array('00:00'),
            array('24:00:00'),
            array('00:60:00'),
            array('00:00:60'),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Luhn;
use Symfony\Component\Validator\Constraints\LuhnValidator;

class LuhnValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new LuhnValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Luhn());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Luhn());
    }

    /**
     * @dataProvider getValidNumbers
     */
    public function testValidNumbers($number)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($number, new Luhn());
    }

    public function getValidNumbers()
    {
        return array(
            array('42424242424242424242'),
            array('378282246310005'),
            array('371449635398431'),
            array('378734493671000'),
            array('5610591081018250'),
            array('30569309025904'),
            array('38520000023237'),
            array('6011111111111117'),
            array('6011000990139424'),
            array('3530111333300000'),
            array('3566002020360505'),
            array('5555555555554444'),
            array('5105105105105100'),
            array('4111111111111111'),
            array('4012888888881881'),
            array('4222222222222'),
            array('5019717010103742'),
            array('6331101999990016'),
        );
    }

    /**
     * @dataProvider getInvalidNumbers
     */
    public function testInvalidNumbers($number)
    {
        $constraint = new Luhn();

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with($constraint->message);

        $this->validator->validate($number, $constraint);
    }

    public function getInvalidNumbers()
    {
        return array(
            array('1234567812345678'),
            array('4222222222222222'),
            array('0000000000000000'),
        );
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     * @dataProvider getInvalidTypes
     */
    public function testInvalidTypes($number)
    {
        $constraint = new Luhn();

        $this->validator->validate($number, $constraint);
    }

    public function getInvalidTypes()
    {
        return array(
            array(0),
            array(123),
            array(42424242424242424242),
            array(378282246310005),
            array(371449635398431),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\HttpFoundation\File\File;

class FileValidatorObjectTest extends FileValidatorTest
{
    protected function getFile($filename)
    {
        return new File($filename);
    }
}
GIF89a    !
  ,       L
 ;GIF89a                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 ,         ;GIF89a    !
  ,       L
 ;<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Intl\Util\IntlTestHelper;
use Symfony\Component\Validator\Constraints\Currency;
use Symfony\Component\Validator\Constraints\CurrencyValidator;

class CurrencyValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        IntlTestHelper::requireIntl($this);

        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new CurrencyValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Currency());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Currency());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $this->validator->validate(new \stdClass(), new Currency());
    }

    /**
     * @dataProvider getValidCurrencies
     */
    public function testValidCurrencies($currency)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($currency, new Currency());
    }

    /**
     * @dataProvider getValidCurrencies
     **/
    public function testValidCurrenciesWithCountrySpecificLocale($currency)
    {
        \Locale::setDefault('en_GB');
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($currency, new Currency());
    }

    public function getValidCurrencies()
    {
        return array(
            array('EUR'),
            array('USD'),
            array('SIT'),
            array('AUD'),
            array('CAD'),
        );
    }

    /**
     * @dataProvider getInvalidCurrencies
     */
    public function testInvalidCurrencies($currency)
    {
        $constraint = new Currency(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $currency,
            ));

        $this->validator->validate($currency, $constraint);
    }

    public function getInvalidCurrencies()
    {
        return array(
            array('EN'),
            array('foobar'),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Type;
use Symfony\Component\Validator\Constraints\TypeValidator;

class TypeValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected static $file;

    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new TypeValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Type(array('type' => 'integer')));
    }

    public function testEmptyIsValidIfString()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Type(array('type' => 'string')));
    }

    public function testEmptyIsInvalidIfNoString()
    {
        $this->context->expects($this->once())
            ->method('addViolation');

        $this->validator->validate('', new Type(array('type' => 'integer')));
    }

    /**
     * @dataProvider getValidValues
     */
    public function testValidValues($value, $type)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new Type(array('type' => $type));

        $this->validator->validate($value, $constraint);
    }

    public function getValidValues()
    {
        $object = new \stdClass();
        $file = $this->createFile();

        return array(
            array(true, 'Boolean'),
            array(false, 'Boolean'),
            array(true, 'boolean'),
            array(false, 'boolean'),
            array(true, 'bool'),
            array(false, 'bool'),
            array(0, 'numeric'),
            array('0', 'numeric'),
            array(1.5, 'numeric'),
            array('1.5', 'numeric'),
            array(0, 'integer'),
            array(1.5, 'float'),
            array('12345', 'string'),
            array(array(), 'array'),
            array($object, 'object'),
            array($object, 'stdClass'),
            array($file, 'resource'),
            array('12345', 'digit'),
            array('12a34', 'alnum'),
            array('abcde', 'alpha'),
            array("\n\r\t", 'cntrl'),
            array('arf12', 'graph'),
            array('abcde', 'lower'),
            array('ABCDE', 'upper'),
            array('arf12', 'print'),
            array('*&$()', 'punct'),
            array("\n\r\t", 'space'),
            array('AB10BC99', 'xdigit'),
        );
    }

    /**
     * @dataProvider getInvalidValues
     */
    public function testInvalidValues($value, $type, $valueAsString)
    {
        $constraint = new Type(array(
            'type' => $type,
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $valueAsString,
                '{{ type }}' => $type,
            ));

        $this->validator->validate($value, $constraint);
    }

    public function getInvalidValues()
    {
        $object = new \stdClass();
        $file = $this->createFile();

        return array(
            array('foobar', 'numeric', 'foobar'),
            array('foobar', 'boolean', 'foobar'),
            array('0', 'integer', '0'),
            array('1.5', 'float', '1.5'),
            array(12345, 'string', '12345'),
            array($object, 'boolean', 'stdClass'),
            array($object, 'numeric', 'stdClass'),
            array($object, 'integer', 'stdClass'),
            array($object, 'float', 'stdClass'),
            array($object, 'string', 'stdClass'),
            array($object, 'resource', 'stdClass'),
            array($file, 'boolean', (string) $file),
            array($file, 'numeric', (string) $file),
            array($file, 'integer', (string) $file),
            array($file, 'float', (string) $file),
            array($file, 'string', (string) $file),
            array($file, 'object', (string) $file),
            array('12a34', 'digit', '12a34'),
            array('1a#23', 'alnum', '1a#23'),
            array('abcd1', 'alpha', 'abcd1'),
            array("\nabc", 'cntrl', "\nabc"),
            array("abc\n", 'graph', "abc\n"),
            array('abCDE', 'lower', 'abCDE'),
            array('ABcde', 'upper', 'ABcde'),
            array("\nabc", 'print', "\nabc"),
            array('abc&$!', 'punct', 'abc&$!'),
            array("\nabc", 'space', "\nabc"),
            array('AR1012', 'xdigit', 'AR1012'),
        );
    }

    protected function createFile()
    {
        if (!self::$file) {
            self::$file = fopen(__FILE__, 'r');
        }

        return self::$file;
    }

    public static function tearDownAfterClass()
    {
        if (self::$file) {
            fclose(self::$file);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

/**
 * This class is a hand written simplified version of PHP native `ArrayObject`
 * class, to show that it behaves differently than the PHP native implementation.
 */
class CustomArrayObject implements \ArrayAccess, \IteratorAggregate, \Countable, \Serializable
{
    private $array;

    public function __construct(array $array = null)
    {
        $this->array = $array ?: array();
    }

    public function offsetExists($offset)
    {
        return array_key_exists($offset, $this->array);
    }

    public function offsetGet($offset)
    {
        return $this->array[$offset];
    }

    public function offsetSet($offset, $value)
    {
        if (null === $offset) {
            $this->array[] = $value;
        } else {
            $this->array[$offset] = $value;
        }
    }

    public function offsetUnset($offset)
    {
        unset($this->array[$offset]);
    }

    public function getIterator()
    {
        return new \ArrayIterator($this->array);
    }

    public function count()
    {
        return count($this->array);
    }

    public function serialize()
    {
        return serialize($this->array);
    }

    public function unserialize($serialized)
    {
        $this->array = (array) unserialize((string) $serialized);
    }
}

class CollectionValidatorCustomArrayObjectTest extends CollectionValidatorTest
{
    public function prepareTestData(array $contents)
    {
        return new CustomArrayObject($contents);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Date;
use Symfony\Component\Validator\Constraints\DateValidator;

class DateValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new DateValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Date());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Date());
    }

    public function testDateTimeClassIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(new \DateTime(), new Date());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $this->validator->validate(new \stdClass(), new Date());
    }

    /**
     * @dataProvider getValidDates
     */
    public function testValidDates($date)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($date, new Date());
    }

    public function getValidDates()
    {
        return array(
            array('2010-01-01'),
            array('1955-12-12'),
            array('2030-05-31'),
        );
    }

    /**
     * @dataProvider getInvalidDates
     */
    public function testInvalidDates($date)
    {
        $constraint = new Date(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $date,
            ));

        $this->validator->validate($date, $constraint);
    }

    public function getInvalidDates()
    {
        return array(
            array('foobar'),
            array('foobar 2010-13-01'),
            array('2010-13-01 foobar'),
            array('2010-13-01'),
            array('2010-04-32'),
            array('2010-02-29'),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\LengthValidator;

class LengthValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new LengthValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Length(6));
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Length(6));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $this->validator->validate(new \stdClass(), new Length(5));
    }

    public function getThreeOrLessCharacters()
    {
        return array(
            array(12),
            array('12'),
            array('üü', true),
            array('éé', true),
            array(123),
            array('123'),
            array('üüü', true),
            array('ééé', true),
        );
    }

    public function getFourCharacters()
    {
        return array(
            array(1234),
            array('1234'),
            array('üüüü', true),
            array('éééé', true),
        );
    }

    public function getNotFourCharacters()
    {
        return array_merge(
            $this->getThreeOrLessCharacters(),
            $this->getFiveOrMoreCharacters()
        );
    }

    public function getFiveOrMoreCharacters()
    {
        return array(
            array(12345),
            array('12345'),
            array('üüüüü', true),
            array('ééééé', true),
            array(123456),
            array('123456'),
            array('üüüüüü', true),
            array('éééééé', true),
        );
    }

    /**
     * @dataProvider getFiveOrMoreCharacters
     */
    public function testValidValuesMin($value, $mbOnly = false)
    {
        if ($mbOnly && !function_exists('mb_strlen')) {
            $this->markTestSkipped('mb_strlen does not exist');
        }

        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new Length(array('min' => 5));
        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getThreeOrLessCharacters
     */
    public function testValidValuesMax($value, $mbOnly = false)
    {
        if ($mbOnly && !function_exists('mb_strlen')) {
            $this->markTestSkipped('mb_strlen does not exist');
        }

        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new Length(array('max' => 3));
        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getFourCharacters
     */
    public function testValidValuesExact($value, $mbOnly = false)
    {
        if ($mbOnly && !function_exists('mb_strlen')) {
            $this->markTestSkipped('mb_strlen does not exist');
        }

        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new Length(4);
        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getThreeOrLessCharacters
     */
    public function testInvalidValuesMin($value, $mbOnly = false)
    {
        if ($mbOnly && !function_exists('mb_strlen')) {
            $this->markTestSkipped('mb_strlen does not exist');
        }

        $constraint = new Length(array(
            'min' => 4,
            'minMessage' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', $this->identicalTo(array(
                '{{ value }}' => (string) $value,
                '{{ limit }}' => 4,
            )), $this->identicalTo($value), 4);

        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getFiveOrMoreCharacters
     */
    public function testInvalidValuesMax($value, $mbOnly = false)
    {
        if ($mbOnly && !function_exists('mb_strlen')) {
            $this->markTestSkipped('mb_strlen does not exist');
        }

        $constraint = new Length(array(
            'max' => 4,
            'maxMessage' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', $this->identicalTo(array(
                '{{ value }}' => (string) $value,
                '{{ limit }}' => 4,
            )), $this->identicalTo($value), 4);

        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getNotFourCharacters
     */
    public function testInvalidValuesExact($value, $mbOnly = false)
    {
        if ($mbOnly && !function_exists('mb_strlen')) {
            $this->markTestSkipped('mb_strlen does not exist');
        }

        $constraint = new Length(array(
            'min' => 4,
            'max' => 4,
            'exactMessage' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', $this->identicalTo(array(
                '{{ value }}' => (string) $value,
                '{{ limit }}' => 4,
            )), $this->identicalTo($value), 4);

        $this->validator->validate($value, $constraint);
    }

    public function testConstraintGetDefaultOption()
    {
        $constraint = new Length(5);

        $this->assertEquals(5, $constraint->min);
        $this->assertEquals(5, $constraint->max);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\False;
use Symfony\Component\Validator\Constraints\FalseValidator;

class FalseValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new FalseValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new False());
    }

    public function testFalseIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(false, new False());
    }

    public function testTrueIsInvalid()
    {
        $constraint = new False(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array());

        $this->validator->validate(true, $constraint);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\ExecutionContext;
use Symfony\Component\Validator\Constraints\Callback;
use Symfony\Component\Validator\Constraints\CallbackValidator;

class CallbackValidatorTest_Class
{
    public static function validateCallback($object, ExecutionContext $context)
    {
        $context->addViolation('Callback message', array('{{ value }}' => 'foobar'), 'invalidValue');

        return false;
    }
}

class CallbackValidatorTest_Object
{
    public function validate(ExecutionContext $context)
    {
        $context->addViolation('My message', array('{{ value }}' => 'foobar'), 'invalidValue');

        return false;
    }

    public static function validateStatic($object, ExecutionContext $context)
    {
        $context->addViolation('Static message', array('{{ value }}' => 'baz'), 'otherInvalidValue');

        return false;
    }
}

class CallbackValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new CallbackValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Callback(array('foo')));
    }

    public function testSingleMethod()
    {
        $object = new CallbackValidatorTest_Object();
        $constraint = new Callback('validate');

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('My message', array(
                '{{ value }}' => 'foobar',
            ));

        $this->validator->validate($object, $constraint);
    }

    public function testSingleMethodExplicitName()
    {
        $object = new CallbackValidatorTest_Object();
        $constraint = new Callback(array('callback' => 'validate'));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('My message', array(
                '{{ value }}' => 'foobar',
            ));

        $this->validator->validate($object, $constraint);
    }

    public function testSingleStaticMethod()
    {
        $object = new CallbackValidatorTest_Object();
        $constraint = new Callback('validateStatic');

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('Static message', array(
                '{{ value }}' => 'baz',
            ));

        $this->validator->validate($object, $constraint);
    }

    public function testClosure()
    {
        $object = new CallbackValidatorTest_Object();
        $constraint = new Callback(function ($object, ExecutionContext $context) {
            $context->addViolation('My message', array('{{ value }}' => 'foobar'), 'invalidValue');

            return false;
        });

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('My message', array(
                '{{ value }}' => 'foobar',
            ));

        $this->validator->validate($object, $constraint);
    }

    public function testClosureExplicitName()
    {
        $object = new CallbackValidatorTest_Object();
        $constraint = new Callback(array(
            'callback' => function ($object, ExecutionContext $context) {
                $context->addViolation('My message', array('{{ value }}' => 'foobar'), 'invalidValue');

                return false;
            },
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('My message', array(
                '{{ value }}' => 'foobar',
            ));

        $this->validator->validate($object, $constraint);
    }

    public function testArrayCallable()
    {
        $object = new CallbackValidatorTest_Object();
        $constraint = new Callback(array(__CLASS__.'_Class', 'validateCallback'));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('Callback message', array(
                '{{ value }}' => 'foobar',
            ));

        $this->validator->validate($object, $constraint);
    }

    public function testArrayCallableExplicitName()
    {
        $object = new CallbackValidatorTest_Object();
        $constraint = new Callback(array(
            'callback' => array(__CLASS__.'_Class', 'validateCallback'),
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('Callback message', array(
                '{{ value }}' => 'foobar',
            ));

        $this->validator->validate($object, $constraint);
    }

    // BC with Symfony < 2.4
    public function testSingleMethodBc()
    {
        $object = new CallbackValidatorTest_Object();
        $constraint = new Callback(array('validate'));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('My message', array(
                '{{ value }}' => 'foobar',
            ));

        $this->validator->validate($object, $constraint);
    }

    // BC with Symfony < 2.4
    public function testSingleMethodBcExplicitName()
    {
        $object = new CallbackValidatorTest_Object();
        $constraint = new Callback(array('methods' => array('validate')));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('My message', array(
                '{{ value }}' => 'foobar',
            ));

        $this->validator->validate($object, $constraint);
    }

    // BC with Symfony < 2.4
    public function testMultipleMethodsBc()
    {
        $object = new CallbackValidatorTest_Object();
        $constraint = new Callback(array('validate', 'validateStatic'));

        $this->context->expects($this->at(0))
            ->method('addViolation')
            ->with('My message', array(
                '{{ value }}' => 'foobar',
            ));
        $this->context->expects($this->at(1))
            ->method('addViolation')
            ->with('Static message', array(
                '{{ value }}' => 'baz',
            ));

        $this->validator->validate($object, $constraint);
    }

    // BC with Symfony < 2.4
    public function testMultipleMethodsBcExplicitName()
    {
        $object = new CallbackValidatorTest_Object();
        $constraint = new Callback(array(
            'methods' => array('validate', 'validateStatic'),
        ));

        $this->context->expects($this->at(0))
            ->method('addViolation')
            ->with('My message', array(
                '{{ value }}' => 'foobar',
            ));
        $this->context->expects($this->at(1))
            ->method('addViolation')
            ->with('Static message', array(
                '{{ value }}' => 'baz',
            ));

        $this->validator->validate($object, $constraint);
    }

    // BC with Symfony < 2.4
    public function testSingleStaticMethodBc()
    {
        $object = new CallbackValidatorTest_Object();
        $constraint = new Callback(array(
            array(__CLASS__.'_Class', 'validateCallback')
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('Callback message', array(
                '{{ value }}' => 'foobar',
            ));

        $this->validator->validate($object, $constraint);
    }

    // BC with Symfony < 2.4
    public function testSingleStaticMethodBcExplicitName()
    {
        $object = new CallbackValidatorTest_Object();
        $constraint = new Callback(array(
            'methods' => array(array(__CLASS__.'_Class', 'validateCallback')),
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('Callback message', array(
                '{{ value }}' => 'foobar',
            ));

        $this->validator->validate($object, $constraint);
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testExpectValidMethods()
    {
        $object = new CallbackValidatorTest_Object();

        $this->validator->validate($object, new Callback(array('foobar')));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testExpectValidCallbacks()
    {
        $object = new CallbackValidatorTest_Object();

        $this->validator->validate($object, new Callback(array(array('foo', 'bar'))));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testExpectEitherCallbackOrMethods()
    {
        $object = new CallbackValidatorTest_Object();

        $this->validator->validate($object, new Callback(array(
            'callback' => 'validate',
            'methods' => array('validateStatic'),
        )));
    }

    public function testConstraintGetTargets()
    {
        $constraint = new Callback(array('foo'));

        $this->assertEquals('class', $constraint->getTargets());
    }

    // Should succeed. Needed when defining constraints as annotations.
    public function testNoConstructorArguments()
    {
        new Callback();
    }

    public function testAnnotationInvocationSingleValued()
    {
        $constraint = new Callback(array('value' => 'validateStatic'));

        $this->assertEquals(new Callback('validateStatic'), $constraint);
    }

    public function testAnnotationInvocationMultiValued()
    {
        $constraint = new Callback(array('value' => array(__CLASS__.'_Class', 'validateCallback')));

        $this->assertEquals(new Callback(array(__CLASS__.'_Class', 'validateCallback')), $constraint);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Intl\Util\IntlTestHelper;
use Symfony\Component\Validator\Constraints\Locale;
use Symfony\Component\Validator\Constraints\LocaleValidator;

class LocaleValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        IntlTestHelper::requireIntl($this);

        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new LocaleValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Locale());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Locale());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $this->validator->validate(new \stdClass(), new Locale());
    }

    /**
     * @dataProvider getValidLocales
     */
    public function testValidLocales($locale)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($locale, new Locale());
    }

    public function getValidLocales()
    {
        return array(
            array('en'),
            array('en_US'),
            array('pt'),
            array('pt_PT'),
            array('zh_Hans'),
        );
    }

    /**
     * @dataProvider getInvalidLocales
     */
    public function testInvalidLocales($locale)
    {
        $constraint = new Locale(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $locale,
            ));

        $this->validator->validate($locale, $constraint);
    }

    public function getInvalidLocales()
    {
        return array(
            array('EN'),
            array('foobar'),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Null;
use Symfony\Component\Validator\Constraints\NullValidator;

class NullValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new NullValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Null());
    }

    /**
     * @dataProvider getInvalidValues
     */
    public function testInvalidValues($value)
    {
        $constraint = new Null(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $value,
            ));

        $this->validator->validate($value, $constraint);
    }

    public function getInvalidValues()
    {
        return array(
            array(0),
            array(false),
            array(true),
            array(''),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

class CountValidatorCountableTest_Countable implements \Countable
{
    private $content;

    public function __construct(array $content)
    {
        $this->content = $content;
    }

    public function count()
    {
        return count($this->content);
    }
}

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class CountValidatorCountableTest extends CountValidatorTest
{
    protected function createCollection(array $content)
    {
        return new CountValidatorCountableTest_Countable($content);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Url;
use Symfony\Component\Validator\Constraints\UrlValidator;

class UrlValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new UrlValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Url());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Url());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $this->validator->validate(new \stdClass(), new Url());
    }

    /**
     * @dataProvider getValidUrls
     */
    public function testValidUrls($url)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($url, new Url());
    }

    public function getValidUrls()
    {
        return array(
            array('http://a.pl'),
            array('http://www.google.com'),
            array('http://www.google.museum'),
            array('https://google.com/'),
            array('https://google.com:80/'),
            array('http://www.example.coop/'),
            array('http://www.test-example.com/'),
            array('http://www.symfony.com/'),
            array('http://symfony.fake/blog/'),
            array('http://symfony.com/?'),
            array('http://symfony.com/search?type=&q=url+validator'),
            array('http://symfony.com/#'),
            array('http://symfony.com/#?'),
            array('http://www.symfony.com/doc/current/book/validation.html#supported-constraints'),
            array('http://very.long.domain.name.com/'),
            array('http://127.0.0.1/'),
            array('http://127.0.0.1:80/'),
            array('http://[::1]/'),
            array('http://[::1]:80/'),
            array('http://[1:2:3::4:5:6:7]/'),
            array('http://sãopaulo.com/'),
            array('http://sãopaulo.com.br/'),
            array('http://пример.испытание/'),
            array('http://مثال.إختبار/'),
            array('http://例子.测试/'),
            array('http://例子.測試/'),
            array('http://例え.テスト/'),
            array('http://مثال.آزمایشی/'),
            array('http://실례.테스트/'),
            array('http://العربية.idn.icann.org/'),
            array('http://☎.com/'),
        );
    }

    /**
     * @dataProvider getInvalidUrls
     */
    public function testInvalidUrls($url)
    {
        $constraint = new Url(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $url,
            ));

        $this->validator->validate($url, $constraint);
    }

    public function getInvalidUrls()
    {
        return array(
            array('google.com'),
            array('://google.com'),
            array('http ://google.com'),
            array('http:/google.com'),
            array('http://goog_le.com'),
            array('http://google.com::aa'),
            array('http://google.com:aa'),
            array('http://symfony.com?'),
            array('http://symfony.com#'),
            array('ftp://google.fr'),
            array('faked://google.fr'),
            array('http://127.0.0.1:aa/'),
            array('ftp://[::1]/'),
            array('http://[::1'),
        );
    }

    /**
     * @dataProvider getValidCustomUrls
     */
    public function testCustomProtocolIsValid($url)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new Url(array(
            'protocols' => array('ftp', 'file', 'git')
        ));

        $this->validator->validate($url, $constraint);
    }

    public function getValidCustomUrls()
    {
        return array(
            array('ftp://google.com'),
            array('file://127.0.0.1'),
            array('git://[::1]/'),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\File;

class FileValidatorPathTest extends FileValidatorTest
{
    protected function getFile($filename)
    {
        return $filename;
    }

    public function testFileNotFound()
    {
        $constraint = new File(array(
            'notFoundMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ file }}' => 'foobar',
            ));

        $this->validator->validate('foobar', $constraint);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

class CollectionValidatorArrayObjectTest extends CollectionValidatorTest
{
    public function prepareTestData(array $contents)
    {
        return new \ArrayObject($contents);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\GreaterThan;
use Symfony\Component\Validator\Constraints\GreaterThanValidator;

/**
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class GreaterThanValidatorTest extends AbstractComparisonValidatorTestCase
{
    protected function createValidator()
    {
        return new GreaterThanValidator();
    }

    protected function createConstraint(array $options)
    {
        return new GreaterThan($options);
    }

    /**
     * {@inheritDoc}
     */
    public function provideValidComparisons()
    {
        return array(
            array(2, 1),
            array(new \DateTime('2005/01/01'), new \DateTime('2001/01/01')),
            array(new ComparisonTest_Class(5), new ComparisonTest_Class(4)),
            array('333', '22'),
            array(null, 1),
        );
    }

    /**
     * {@inheritDoc}
     */
    public function provideInvalidComparisons()
    {
        return array(
            array(1, 2, '2', 'integer'),
            array(2, 2, '2', 'integer'),
            array(new \DateTime('2000/01/01'), new \DateTime('2005/01/01'), '2005-01-01 00:00:00', 'DateTime'),
            array(new \DateTime('2000/01/01'), new \DateTime('2000/01/01'), '2000-01-01 00:00:00', 'DateTime'),
            array(new ComparisonTest_Class(4), new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'),
            array(new ComparisonTest_Class(5), new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'),
            array('22', '333', "'333'", 'string'),
            array('22', '22', "'22'", 'string')
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\True;
use Symfony\Component\Validator\Constraints\TrueValidator;

class TrueValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new TrueValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new True());
    }

    public function testTrueIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(true, new True());
    }

    public function testFalseIsInvalid()
    {
        $constraint = new True(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
            ));

        $this->validator->validate(false, $constraint);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Iban;
use Symfony\Component\Validator\Constraints\IbanValidator;

class IbanValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new IbanValidator();
        $this->validator->initialize($this->context);
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())->method('addViolation');

        $this->validator->validate(null, new Iban());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())->method('addViolation');

        $this->validator->validate('', new Iban());
    }

    /**
     * @dataProvider getValidIbans
     */
    public function testValidIbans($iban)
    {
        $this->context->expects($this->never())->method('addViolation');

        $this->validator->validate($iban, new Iban());
    }

    public function getValidIbans()
    {
        return array(
            array('CH93 0076 2011 6238 5295 7'), //Switzerland
            array('CH9300762011623852957'), // Switzerland without spaces

            //Country list
            //http://www.rbs.co.uk/corporate/international/g0/guide-to-international-business/regulatory-information/iban/iban-example.ashx

            array('AL47 2121 1009 0000 0002 3569 8741'), //Albania
            array('AD12 0001 2030 2003 5910 0100'), //Andorra
            array('AT61 1904 3002 3457 3201'), //Austria
            array('AZ21 NABZ 0000 0000 1370 1000 1944'), //Azerbaijan
            array('BH67 BMAG 0000 1299 1234 56'), //Bahrain
            array('BE62 5100 0754 7061'), //Belgium
            array('BA39 1290 0794 0102 8494'), //Bosnia and Herzegovina
            array('BG80 BNBG 9661 1020 3456 78'), //Bulgaria
            array('HR12 1001 0051 8630 0016 0'), //Croatia
            array('CY17 0020 0128 0000 0012 0052 7600'), //Cyprus
            array('CZ65 0800 0000 1920 0014 5399'), //Czech Republic
            array('DK50 0040 0440 1162 43'), //Denmark
            array('EE38 2200 2210 2014 5685'), //Estonia
            array('FO97 5432 0388 8999 44'), //Faroe Islands
            array('FI21 1234 5600 0007 85'), //Finland
            array('FR14 2004 1010 0505 0001 3M02 606'), //France
            array('GE29 NB00 0000 0101 9049 17'), //Georgia
            array('DE89 3704 0044 0532 0130 00'), //Germany
            array('GI75 NWBK 0000 0000 7099 453'), //Gibraltar
            array('GR16 0110 1250 0000 0001 2300 695'), //Greece
            array('GL56 0444 9876 5432 10'), //Greenland
            array('HU42 1177 3016 1111 1018 0000 0000'), //Hungary
            array('IS14 0159 2600 7654 5510 7303 39'), //Iceland
            array('IE29 AIBK 9311 5212 3456 78'), //Ireland
            array('IL62 0108 0000 0009 9999 999'), //Israel
            array('IT40 S054 2811 1010 0000 0123 456'), //Italy
            array('LV80 BANK 0000 4351 9500 1'), //Latvia
            array('LB62 0999 0000 0001 0019 0122 9114'), //Lebanon
            array('LI21 0881 0000 2324 013A A'), //Liechtenstein
            array('LT12 1000 0111 0100 1000'), //Lithuania
            array('LU28 0019 4006 4475 0000'), //Luxembourg
            array('MK072 5012 0000 0589 84'), //Macedonia
            array('MT84 MALT 0110 0001 2345 MTLC AST0 01S'), //Malta
            array('MU17 BOMM 0101 1010 3030 0200 000M UR'), //Mauritius
            array('MD24 AG00 0225 1000 1310 4168'), //Moldova
            array('MC93 2005 2222 1001 1223 3M44 555'), //Monaco
            array('ME25 5050 0001 2345 6789 51'), //Montenegro
            array('NL39 RABO 0300 0652 64'), //Netherlands
            array('NO93 8601 1117 947'), //Norway
            array('PK36 SCBL 0000 0011 2345 6702'), //Pakistan
            array('PL60 1020 1026 0000 0422 7020 1111'), //Poland
            array('PT50 0002 0123 1234 5678 9015 4'), //Portugal
            array('RO49 AAAA 1B31 0075 9384 0000'), //Romania
            array('SM86 U032 2509 8000 0000 0270 100'), //San Marino
            array('SA03 8000 0000 6080 1016 7519'), //Saudi Arabia
            array('RS35 2600 0560 1001 6113 79'), //Serbia
            array('SK31 1200 0000 1987 4263 7541'), //Slovak Republic
            array('SI56 1910 0000 0123 438'), //Slovenia
            array('ES80 2310 0001 1800 0001 2345'), //Spain
            array('SE35 5000 0000 0549 1000 0003'), //Sweden
            array('CH93 0076 2011 6238 5295 7'), //Switzerland
            array('TN59 1000 6035 1835 9847 8831'), //Tunisia
            array('TR33 0006 1005 1978 6457 8413 26'), //Turkey
            array('AE07 0331 2345 6789 0123 456'), //UAE
            array('GB 12 CPBK 0892 9965 0449 91'), //United Kingdom

            //Extended country list
            //http://www.nordea.com/Our+services/International+products+and+services/Cash+Management/IBAN+countries/908462.html
            array('AO06000600000100037131174'), //Angola
            array('AZ21NABZ00000000137010001944'), //Azerbaijan
            array('BH29BMAG1299123456BH00'), //Bahrain
            array('BJ11B00610100400271101192591'), //Benin
            array('VG96VPVG0000012345678901'), //British Virgin Islands
            array('BF1030134020015400945000643'), //Burkina Faso
            array('BI43201011067444'), //Burundi
            array('CM2110003001000500000605306'), //Cameroon
            array('CV64000300004547069110176'), //Cape Verde
            array('FR7630007000110009970004942'), //Central African Republic
            array('CG5230011000202151234567890'), //Congo
            array('CR0515202001026284066'), //Costa Rica
            array('DO28BAGR00000001212453611324'), //Dominican Republic
            array('GT82TRAJ01020000001210029690'), //Guatemala
            array('IR580540105180021273113007'), //Iran
            array('IL620108000000099999999'), //Israel
            array('CI05A00060174100178530011852'), //Ivory Coast
            array('KZ176010251000042993'), //Kazakhstan
            array('KW74NBOK0000000000001000372151'), //Kuwait
            array('LB30099900000001001925579115'), //Lebanon
            array('MG4600005030010101914016056'), //Madagascar
            array('ML03D00890170001002120000447'), //Mali
            array('MR1300012000010000002037372'), //Mauritania
            array('MU17BOMM0101101030300200000MUR'), //Mauritius
            array('MZ59000100000011834194157'), //Mozambique
            array('PS92PALS000000000400123456702'), //Palestinian Territory
            array('PT50000200000163099310355'), //Sao Tome and Principe
            array('SA0380000000608010167519'), //Saudi Arabia
            array('SN12K00100152000025690007542'), //Senegal
            array('TN5914207207100707129648'), //Tunisia
            array('TR330006100519786457841326'), //Turkey
            array('AE260211000000230064016'), //United Arab Emirates
        );
    }

    /**
     * @dataProvider getInvalidIbans
     */
    public function testInvalidIbans($iban)
    {
        $constraint = new Iban(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $iban,
            ));

        $this->validator->validate($iban, $constraint);
    }

    public function getInvalidIbans()
    {
        return array(
            array('CH93 0076 2011 6238 5295'),
            array('CH930076201162385295'),
            array('GB29 RBOS 6016 1331 9268 19'),
            array('CH930072011623852957'),
            array('NL39 RASO 0300 0652 64'),
            array('NO93 8601117 947'),
            array('CY170020 128 0000 0012 0052 7600'),
            array('foo'),
            array('123'),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\LessThanOrEqual;
use Symfony\Component\Validator\Constraints\LessThanOrEqualValidator;

/**
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class LessThanOrEqualValidatorTest extends AbstractComparisonValidatorTestCase
{
    protected function createValidator()
    {
        return new LessThanOrEqualValidator();
    }

    protected function createConstraint(array $options)
    {
        return new LessThanOrEqual($options);
    }

    /**
     * {@inheritDoc}
     */
    public function provideValidComparisons()
    {
        return array(
            array(1, 2),
            array(1, 1),
            array(new \DateTime('2000-01-01'), new \DateTime('2000-01-01')),
            array(new \DateTime('2000-01-01'), new \DateTime('2020-01-01')),
            array(new ComparisonTest_Class(4), new ComparisonTest_Class(5)),
            array(new ComparisonTest_Class(5), new ComparisonTest_Class(5)),
            array('a', 'a'),
            array('a', 'z'),
            array(null, 1),
        );
    }

    /**
     * {@inheritDoc}
     */
    public function provideInvalidComparisons()
    {
        return array(
            array(2, 1, '1', 'integer'),
            array(new \DateTime('2010-01-01'), new \DateTime('2000-01-01'), '2000-01-01 00:00:00', 'DateTime'),
            array(new ComparisonTest_Class(5), new ComparisonTest_Class(4), '4', __NAMESPACE__.'\ComparisonTest_Class'),
            array('c', 'b', "'b'", 'string')
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\Validator\Constraints\Expression;
use Symfony\Component\Validator\Constraints\ExpressionValidator;

class ExpressionValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new ExpressionValidator(PropertyAccess::createPropertyAccessor());
        $this->validator->initialize($this->context);

        $this->context->expects($this->any())
            ->method('getClassName')
            ->will($this->returnValue(__CLASS__));
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Expression('value == 1'));
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Expression('value == 1'));
    }

    public function testSucceedingExpressionAtObjectLevel()
    {
        $constraint = new Expression('this.property == 1');

        $object = (object) array('property' => '1');

        $this->context->expects($this->any())
            ->method('getPropertyName')
            ->will($this->returnValue(null));

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($object, $constraint);
    }

    public function testFailingExpressionAtObjectLevel()
    {
        $constraint = new Expression(array(
            'expression' => 'this.property == 1',
            'message' => 'myMessage',
        ));

        $object = (object) array('property' => '2');

        $this->context->expects($this->any())
            ->method('getPropertyName')
            ->will($this->returnValue(null));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage');

        $this->validator->validate($object, $constraint);
    }

    public function testSucceedingExpressionAtPropertyLevel()
    {
        $constraint = new Expression('value == this.expected');

        $object = (object) array('expected' => '1');

        $this->context->expects($this->any())
            ->method('getPropertyName')
            ->will($this->returnValue('property'));

        $this->context->expects($this->any())
            ->method('getPropertyPath')
            ->will($this->returnValue('property'));

        $this->context->expects($this->any())
            ->method('getRoot')
            ->will($this->returnValue($object));

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('1', $constraint);
    }

    public function testFailingExpressionAtPropertyLevel()
    {
        $constraint = new Expression(array(
            'expression' => 'value == this.expected',
            'message' => 'myMessage',
        ));

        $object = (object) array('expected' => '1');

        $this->context->expects($this->any())
            ->method('getPropertyName')
            ->will($this->returnValue('property'));

        $this->context->expects($this->any())
            ->method('getPropertyPath')
            ->will($this->returnValue('property'));

        $this->context->expects($this->any())
            ->method('getRoot')
            ->will($this->returnValue($object));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage');

        $this->validator->validate('2', $constraint);
    }

    public function testSucceedingExpressionAtNestedPropertyLevel()
    {
        $constraint = new Expression('value == this.expected');

        $object = (object) array('expected' => '1');
        $root = (object) array('nested' => $object);

        $this->context->expects($this->any())
            ->method('getPropertyName')
            ->will($this->returnValue('property'));

        $this->context->expects($this->any())
            ->method('getPropertyPath')
            ->will($this->returnValue('nested.property'));

        $this->context->expects($this->any())
            ->method('getRoot')
            ->will($this->returnValue($root));

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('1', $constraint);
    }

    public function testFailingExpressionAtNestedPropertyLevel()
    {
        $constraint = new Expression(array(
            'expression' => 'value == this.expected',
            'message' => 'myMessage',
        ));

        $object = (object) array('expected' => '1');
        $root = (object) array('nested' => $object);

        $this->context->expects($this->any())
            ->method('getPropertyName')
            ->will($this->returnValue('property'));

        $this->context->expects($this->any())
            ->method('getPropertyPath')
            ->will($this->returnValue('nested.property'));

        $this->context->expects($this->any())
            ->method('getRoot')
            ->will($this->returnValue($root));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage');

        $this->validator->validate('2', $constraint);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\CardScheme;
use Symfony\Component\Validator\Constraints\CardSchemeValidator;

class CardSchemeValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new CardSchemeValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new CardScheme(array('schemes' => array())));
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new CardScheme(array('schemes' => array())));
    }

    /**
     * @dataProvider getValidNumbers
     */
    public function testValidNumbers($scheme, $number)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($number, new CardScheme(array('schemes' => $scheme)));
    }

    /**
     * @dataProvider getInvalidNumbers
     */
    public function testInvalidNumbers($scheme, $number)
    {
        $this->context->expects($this->once())
            ->method('addViolation');

        $this->validator->validate($number, new CardScheme(array('schemes' => $scheme)));
    }

    public function getValidNumbers()
    {
        return array(
            array('AMEX', '378282246310005'),
            array('AMEX', '371449635398431'),
            array('AMEX', '378734493671000'),
            array('AMEX', '347298508610146'),
            array('CHINA_UNIONPAY', '6228888888888888'),
            array('CHINA_UNIONPAY', '62288888888888888'),
            array('CHINA_UNIONPAY', '622888888888888888'),
            array('CHINA_UNIONPAY', '6228888888888888888'),
            array('DINERS', '30569309025904'),
            array('DINERS', '36088894118515'),
            array('DINERS', '38520000023237'),
            array('DISCOVER', '6011111111111117'),
            array('DISCOVER', '6011000990139424'),
            array('INSTAPAYMENT', '6372476031350068'),
            array('INSTAPAYMENT', '6385537775789749'),
            array('INSTAPAYMENT', '6393440808445746'),
            array('JCB', '3530111333300000'),
            array('JCB', '3566002020360505'),
            array('JCB', '213112345678901'),
            array('JCB', '180012345678901'),
            array('LASER', '6304678107004080'),
            array('LASER', '6706440607428128629'),
            array('LASER', '6771656738314582216'),
            array('MAESTRO', '6759744069209'),
            array('MAESTRO', '5020507657408074712'),
            array('MAESTRO', '6759744069209'),
            array('MAESTRO', '6759744069209'),
            array('MASTERCARD', '5555555555554444'),
            array('MASTERCARD', '5105105105105100'),
            array('VISA', '4111111111111111'),
            array('VISA', '4012888888881881'),
            array('VISA', '4222222222222'),
            array(array('AMEX', 'VISA'), '4111111111111111'),
            array(array('AMEX', 'VISA'), '378282246310005'),
            array(array('JCB', 'MASTERCARD'), '5105105105105100'),
            array(array('VISA', 'MASTERCARD'), '5105105105105100'),
        );
    }

    public function getInvalidNumbers()
    {
        return array(
            array('VISA', '42424242424242424242'),
            array('AMEX', '357298508610146'),
            array('DINERS', '31569309025904'),
            array('DINERS', '37088894118515'),
            array('INSTAPAYMENT', '6313440808445746'),
            array('CHINA_UNIONPAY', '622888888888888'),
            array('CHINA_UNIONPAY', '62288888888888888888'),
            array('AMEX', '30569309025904'), // DINERS number
            array('AMEX', 'invalid'), // A string
            array('AMEX', 0), // a lone number
            array('AMEX', '0'), // a lone number
            array('AMEX', '000000000000'), // a lone number
            array('DINERS', '3056930'), // only first part of the number
            array('DISCOVER', '1117'), // only last 4 digits
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\File;
use Symfony\Component\Validator\Constraints\FileValidator;
use Symfony\Component\HttpFoundation\File\UploadedFile;

abstract class FileValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;
    protected $path;
    protected $file;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new FileValidator();
        $this->validator->initialize($this->context);
        $this->path = sys_get_temp_dir().DIRECTORY_SEPARATOR.'FileValidatorTest';
        $this->file = fopen($this->path, 'w');
    }

    protected function tearDown()
    {
        fclose($this->file);

        $this->context = null;
        $this->validator = null;
        $this->path = null;
        $this->file = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new File());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new File());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleTypeOrFile()
    {
        $this->validator->validate(new \stdClass(), new File());
    }

    public function testValidFile()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($this->path, new File());
    }

    public function testValidUploadedfile()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $file = new UploadedFile($this->path, 'originalName', null, null, null, true);
        $this->validator->validate($file, new File());
    }

    public function testTooLargeBytes()
    {
        fwrite($this->file, str_repeat('0', 11));

        $constraint = new File(array(
            'maxSize'           => 10,
            'maxSizeMessage'    => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ limit }}'   => '10',
                '{{ size }}'    => '11',
                '{{ suffix }}'  => 'bytes',
                '{{ file }}'    => $this->path,
            ));

        $this->validator->validate($this->getFile($this->path), $constraint);
    }

    public function testTooLargeKiloBytes()
    {
        fwrite($this->file, str_repeat('0', 1400));

        $constraint = new File(array(
            'maxSize'           => '1k',
            'maxSizeMessage'    => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ limit }}'   => '1',
                '{{ size }}'    => '1.4',
                '{{ suffix }}'  => 'kB',
                '{{ file }}'    => $this->path,
            ));

        $this->validator->validate($this->getFile($this->path), $constraint);
    }

    public function testTooLargeMegaBytes()
    {
        fwrite($this->file, str_repeat('0', 1400000));

        $constraint = new File(array(
            'maxSize'           => '1M',
            'maxSizeMessage'    => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ limit }}'   => '1',
                '{{ size }}'    => '1.4',
                '{{ suffix }}'  => 'MB',
                '{{ file }}'    => $this->path,
            ));

        $this->validator->validate($this->getFile($this->path), $constraint);
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testInvalidMaxSize()
    {
        $constraint = new File(array(
            'maxSize' => '1abc',
        ));

        $this->validator->validate($this->path, $constraint);
    }

    public function testValidMimeType()
    {
        $file = $this
            ->getMockBuilder('Symfony\Component\HttpFoundation\File\File')
            ->disableOriginalConstructor()
            ->getMock()
        ;
        $file
            ->expects($this->once())
            ->method('getPathname')
            ->will($this->returnValue($this->path))
        ;
        $file
            ->expects($this->once())
            ->method('getMimeType')
            ->will($this->returnValue('image/jpg'))
        ;

        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new File(array(
            'mimeTypes' => array('image/png', 'image/jpg'),
        ));

        $this->validator->validate($file, $constraint);
    }

    public function testValidWildcardMimeType()
    {
        $file = $this
            ->getMockBuilder('Symfony\Component\HttpFoundation\File\File')
            ->disableOriginalConstructor()
            ->getMock()
        ;
        $file
            ->expects($this->once())
            ->method('getPathname')
            ->will($this->returnValue($this->path))
        ;
        $file
            ->expects($this->once())
            ->method('getMimeType')
            ->will($this->returnValue('image/jpg'))
        ;

        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new File(array(
            'mimeTypes' => array('image/*'),
        ));

        $this->validator->validate($file, $constraint);
    }

    public function testInvalidMimeType()
    {
        $file = $this
            ->getMockBuilder('Symfony\Component\HttpFoundation\File\File')
            ->disableOriginalConstructor()
            ->getMock()
        ;
        $file
            ->expects($this->once())
            ->method('getPathname')
            ->will($this->returnValue($this->path))
        ;
        $file
            ->expects($this->once())
            ->method('getMimeType')
            ->will($this->returnValue('application/pdf'))
        ;

        $constraint = new File(array(
            'mimeTypes' => array('image/png', 'image/jpg'),
            'mimeTypesMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ type }}'    => '"application/pdf"',
                '{{ types }}'   => '"image/png", "image/jpg"',
                '{{ file }}'    => $this->path,
            ));

        $this->validator->validate($file, $constraint);
    }

    public function testInvalidWildcardMimeType()
    {
        $file = $this
            ->getMockBuilder('Symfony\Component\HttpFoundation\File\File')
            ->disableOriginalConstructor()
            ->getMock()
        ;
        $file
            ->expects($this->once())
            ->method('getPathname')
            ->will($this->returnValue($this->path))
        ;
        $file
            ->expects($this->once())
            ->method('getMimeType')
            ->will($this->returnValue('application/pdf'))
        ;

        $constraint = new File(array(
            'mimeTypes' => array('image/*', 'image/jpg'),
            'mimeTypesMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ type }}'    => '"application/pdf"',
                '{{ types }}'   => '"image/*", "image/jpg"',
                '{{ file }}'    => $this->path,
            ));

        $this->validator->validate($file, $constraint);
    }

    /**
     * @dataProvider uploadedFileErrorProvider
     */
    public function testUploadedFileError($error, $message, array $params = array(), $maxSize = null)
    {
        $file = new UploadedFile('/path/to/file', 'originalName', 'mime', 0, $error);

        $constraint = new File(array(
            $message => 'myMessage',
            'maxSize' => $maxSize
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', $params);

        $this->validator->validate($file, $constraint);

    }

    public function uploadedFileErrorProvider()
    {
        $tests = array(
            array(UPLOAD_ERR_FORM_SIZE, 'uploadFormSizeErrorMessage'),
            array(UPLOAD_ERR_PARTIAL, 'uploadPartialErrorMessage'),
            array(UPLOAD_ERR_NO_FILE, 'uploadNoFileErrorMessage'),
            array(UPLOAD_ERR_NO_TMP_DIR, 'uploadNoTmpDirErrorMessage'),
            array(UPLOAD_ERR_CANT_WRITE, 'uploadCantWriteErrorMessage'),
            array(UPLOAD_ERR_EXTENSION, 'uploadExtensionErrorMessage'),
        );

        if (class_exists('Symfony\Component\HttpFoundation\File\UploadedFile')) {
            // when no maxSize is specified on constraint, it should use the ini value
            $tests[] = array(UPLOAD_ERR_INI_SIZE, 'uploadIniSizeErrorMessage', array(
                '{{ limit }}' => UploadedFile::getMaxFilesize(),
                '{{ suffix }}' => 'bytes',
            ));

            // it should use the smaller limitation (maxSize option in this case)
            $tests[] = array(UPLOAD_ERR_INI_SIZE, 'uploadIniSizeErrorMessage', array(
                '{{ limit }}' => 1,
                '{{ suffix }}' => 'bytes',
            ), '1');

            // it correctly parses the maxSize option and not only uses simple string comparison
            // 1000M should be bigger than the ini value
            $tests[] = array(UPLOAD_ERR_INI_SIZE, 'uploadIniSizeErrorMessage', array(
                '{{ limit }}' => UploadedFile::getMaxFilesize(),
                '{{ suffix }}' => 'bytes',
            ), '1000M');
        }

        return $tests;
    }

    abstract protected function getFile($filename);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\All;
use Symfony\Component\Validator\Constraints\Valid;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class AllTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testRejectNonConstraints()
    {
        new All(array(
            'foo',
        ));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testRejectValidConstraint()
    {
        new All(array(
            new Valid(),
        ));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\DateTime;
use Symfony\Component\Validator\Constraints\DateTimeValidator;

class DateTimeValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new DateTimeValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new DateTime());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new DateTime());
    }

    public function testDateTimeClassIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(new \DateTime(), new DateTime());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $this->validator->validate(new \stdClass(), new DateTime());
    }

    /**
     * @dataProvider getValidDateTimes
     */
    public function testValidDateTimes($dateTime)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($dateTime, new DateTime());
    }

    public function getValidDateTimes()
    {
        return array(
            array('2010-01-01 01:02:03'),
            array('1955-12-12 00:00:00'),
            array('2030-05-31 23:59:59'),
        );
    }

    /**
     * @dataProvider getInvalidDateTimes
     */
    public function testInvalidDateTimes($dateTime)
    {
        $constraint = new DateTime(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $dateTime,
            ));

        $this->validator->validate($dateTime, $constraint);
    }

    public function getInvalidDateTimes()
    {
        return array(
            array('foobar'),
            array('2010-01-01'),
            array('00:00:00'),
            array('2010-01-01 00:00'),
            array('2010-13-01 00:00:00'),
            array('2010-04-32 00:00:00'),
            array('2010-02-29 00:00:00'),
            array('2010-01-01 24:00:00'),
            array('2010-01-01 00:60:00'),
            array('2010-01-01 00:00:60'),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\NotIdenticalTo;
use Symfony\Component\Validator\Constraints\NotIdenticalToValidator;
use Symfony\Component\Validator\Tests\Constraints\AbstractComparisonValidatorTestCase;

/**
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class NotIdenticalToValidatorTest extends AbstractComparisonValidatorTestCase
{
    protected function createValidator()
    {
        return new NotIdenticalToValidator();
    }

    protected function createConstraint(array $options)
    {
        return new NotIdenticalTo($options);
    }

    /**
     * {@inheritDoc}
     */
    public function provideValidComparisons()
    {
        return array(
            array(1, 2),
            array('2', 2),
            array('22', '333'),
            array(new \DateTime('2001-01-01'), new \DateTime('2000-01-01')),
            array(new \DateTime('2000-01-01'), new \DateTime('2000-01-01')),
            array(null, 1),
        );
    }

    /**
     * {@inheritDoc}
     */
    public function provideInvalidComparisons()
    {
        $date = new \DateTime('2000-01-01');
        $object = new ComparisonTest_Class(2);

        return array(
            array(3, 3, '3', 'integer'),
            array('a', 'a', "'a'", 'string'),
            array($date, $date, '2000-01-01 00:00:00', 'DateTime'),
            array($object, $object, '2', __NAMESPACE__.'\ComparisonTest_Class'),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Intl\Util\IntlTestHelper;
use Symfony\Component\Validator\Constraints\Country;
use Symfony\Component\Validator\Constraints\CountryValidator;

class CountryValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        IntlTestHelper::requireIntl($this);

        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new CountryValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Country());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Country());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $this->validator->validate(new \stdClass(), new Country());
    }

    /**
     * @dataProvider getValidCountries
     */
    public function testValidCountries($country)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($country, new Country());
    }

    public function getValidCountries()
    {
        return array(
            array('GB'),
            array('AT'),
            array('MY'),
        );
    }

    /**
     * @dataProvider getInvalidCountries
     */
    public function testInvalidCountries($country)
    {
        $constraint = new Country(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $country,
            ));

        $this->validator->validate($country, $constraint);
    }

    public function getInvalidCountries()
    {
        return array(
            array('foobar'),
            array('EN'),
        );
    }

    public function testValidateUsingCountrySpecificLocale()
    {
        \Locale::setDefault('en_GB');
        $existingCountry = 'GB';
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($existingCountry, new Country());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Intl\Util\IntlTestHelper;
use Symfony\Component\Validator\Constraints\Language;
use Symfony\Component\Validator\Constraints\LanguageValidator;

class LanguageValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        IntlTestHelper::requireIntl($this);

        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new LanguageValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Language());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Language());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $this->validator->validate(new \stdClass(), new Language());
    }

    /**
     * @dataProvider getValidLanguages
     */
    public function testValidLanguages($language)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($language, new Language());
    }

    public function getValidLanguages()
    {
        return array(
            array('en'),
            array('en_US'),
            array('my'),
        );
    }

    /**
     * @dataProvider getInvalidLanguages
     */
    public function testInvalidLanguages($language)
    {
        $constraint = new Language(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $language,
            ));

        $this->validator->validate($language, $constraint);
    }

    public function getInvalidLanguages()
    {
        return array(
            array('EN'),
            array('foobar'),
        );
    }

    public function testValidateUsingCountrySpecificLocale()
    {
        \Locale::setDefault('fr_FR');
        $existingLanguage = 'en';
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($existingLanguage, new Language(array(
            'message' => 'aMessage'
        )));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\GreaterThanOrEqual;
use Symfony\Component\Validator\Constraints\GreaterThanOrEqualValidator;

/**
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class GreaterThanOrEqualValidatorTest extends AbstractComparisonValidatorTestCase
{
    protected function createValidator()
    {
        return new GreaterThanOrEqualValidator();
    }

    protected function createConstraint(array $options)
    {
        return new GreaterThanOrEqual($options);
    }

    /**
     * {@inheritDoc}
     */
    public function provideValidComparisons()
    {
        return array(
            array(3, 2),
            array(1, 1),
            array(new \DateTime('2010/01/01'), new \DateTime('2000/01/01')),
            array(new \DateTime('2000/01/01'), new \DateTime('2000/01/01')),
            array('a', 'a'),
            array('z', 'a'),
            array(null, 1),
        );
    }

    /**
     * {@inheritDoc}
     */
    public function provideInvalidComparisons()
    {
        return array(
            array(1, 2, '2', 'integer'),
            array(new \DateTime('2000/01/01'), new \DateTime('2005/01/01'), '2005-01-01 00:00:00', 'DateTime'),
            array('b', 'c', "'c'", 'string')
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\LessThan;
use Symfony\Component\Validator\Constraints\LessThanValidator;

/**
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class LessThanValidatorTest extends AbstractComparisonValidatorTestCase
{
    protected function createValidator()
    {
        return new LessThanValidator();
    }

    protected function createConstraint(array $options)
    {
        return new LessThan($options);
    }

    /**
     * {@inheritDoc}
     */
    public function provideValidComparisons()
    {
        return array(
            array(1, 2),
            array(new \DateTime('2000-01-01'), new \DateTime('2010-01-01')),
            array(new ComparisonTest_Class(4), new ComparisonTest_Class(5)),
            array('22', '333'),
            array(null, 1),
        );
    }

    /**
     * {@inheritDoc}
     */
    public function provideInvalidComparisons()
    {
        return array(
            array(3, 2, '2', 'integer'),
            array(2, 2, '2', 'integer'),
            array(new \DateTime('2010-01-01'), new \DateTime('2000-01-01'), '2000-01-01 00:00:00', 'DateTime'),
            array(new \DateTime('2000-01-01'), new \DateTime('2000-01-01'), '2000-01-01 00:00:00', 'DateTime'),
            array(new ComparisonTest_Class(5), new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'),
            array(new ComparisonTest_Class(6), new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'),
            array('333', '22', "'22'", 'string')
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Range;
use Symfony\Component\Validator\Constraints\RangeValidator;

class RangeValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new RangeValidator();
        $this->validator->initialize($this->context);
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Range(array('min' => 10, 'max' => 20)));
    }

    public function getTenToTwenty()
    {
        return array(
            array(10.00001),
            array(19.99999),
            array('10.00001'),
            array('19.99999'),
            array(10),
            array(20),
            array(10.0),
            array(20.0),
        );
    }

    public function getLessThanTen()
    {
        return array(
            array(9.99999),
            array('9.99999'),
            array(5),
            array(1.0),
        );
    }

    public function getMoreThanTwenty()
    {
        return array(
            array(20.000001),
            array('20.000001'),
            array(21),
            array(30.0),
        );
    }

    /**
     * @dataProvider getTenToTwenty
     */
    public function testValidValuesMin($value)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new Range(array('min' => 10));
        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getTenToTwenty
     */
    public function testValidValuesMax($value)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new Range(array('max' => 20));
        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getTenToTwenty
     */
    public function testValidValuesMinMax($value)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new Range(array('min' => 10, 'max' => 20));
        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getLessThanTen
     */
    public function testInvalidValuesMin($value)
    {
        $constraint = new Range(array(
            'min' => 10,
            'minMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', $this->identicalTo(array(
                '{{ value }}' => $value,
                '{{ limit }}' => 10,
        )));

        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getMoreThanTwenty
     */
    public function testInvalidValuesMax($value)
    {
        $constraint = new Range(array(
            'max' => 20,
            'maxMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', $this->identicalTo(array(
                '{{ value }}' => $value,
                '{{ limit }}' => 20,
            )));

        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getMoreThanTwenty
     */
    public function testInvalidValuesCombinedMax($value)
    {
        $constraint = new Range(array(
            'min' => 10,
            'max' => 20,
            'minMessage' => 'myMinMessage',
            'maxMessage' => 'myMaxMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMaxMessage', $this->identicalTo(array(
                '{{ value }}' => $value,
                '{{ limit }}' => 20,
            )));

        $this->validator->validate($value, $constraint);
    }

    /**
     * @dataProvider getLessThanTen
     */
    public function testInvalidValuesCombinedMin($value)
    {
        $constraint = new Range(array(
            'min' => 10,
            'max' => 20,
            'minMessage' => 'myMinMessage',
            'maxMessage' => 'myMaxMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMinMessage', $this->identicalTo(array(
            '{{ value }}' => $value,
            '{{ limit }}' => 10,
        )));

        $this->validator->validate($value, $constraint);
    }

    public function getInvalidValues()
    {
        return array(
            array(9.999999),
            array(20.000001),
            array('9.999999'),
            array('20.000001'),
            array(new \stdClass()),
        );
    }

    public function testMinMessageIsSet()
    {
        $constraint = new Range(array(
            'min' => 10,
            'max' => 20,
            'minMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => 9,
                '{{ limit }}' => 10,
            ));

        $this->validator->validate(9, $constraint);
    }

    public function testMaxMessageIsSet()
    {
        $constraint = new Range(array(
            'min' => 10,
            'max' => 20,
            'maxMessage' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => 21,
                '{{ limit }}' => 20,
            ));

        $this->validator->validate(21, $constraint);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Isbn;
use Symfony\Component\Validator\Constraints\IsbnValidator;

/**
 * @see https://en.wikipedia.org/wiki/Isbn
 */
class IsbnValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    public function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new IsbnValidator();
        $this->validator->initialize($this->context);
    }

    public function getValidIsbn10()
    {
        return array(
            array('2723442284'),
            array('2723442276'),
            array('2723455041'),
            array('2070546810'),
            array('2711858839'),
            array('2756406767'),
            array('2870971648'),
            array('226623854X'),
            array('2851806424'),
            array('0321812700'),
            array('0-45122-5244'),
            array('0-4712-92311'),
        );
    }

    public function getInvalidIsbn10()
    {
        return array(
            array('1234567890'),
            array('987'),
            array('0987656789'),
            array(0),
            array('7-35622-5444'),
            array('0-4X19-92611'),
            array('0_45122_5244'),
            array('2870#971#648'),
        );
    }

    public function getValidIsbn13()
    {
        return array(
            array('978-2723442282'),
            array('978-2723442275'),
            array('978-2723455046'),
            array('978-2070546817'),
            array('978-2711858835'),
            array('978-2756406763'),
            array('978-2870971642'),
            array('978-2266238540'),
            array('978-2851806420'),
            array('978-0321812704'),
            array('978-0451225245'),
            array('978-0471292319'),
        );
    }

    public function getInvalidIsbn13()
    {
        return array(
            array('1234567890'),
            array('987'),
            array('0987656789'),
            array(0),
            array('0-4X19-9261981'),
            array('978-0321513774'),
            array('979-0431225385'),
            array('980-0474292319'),
            array('978_0451225245'),
            array('978#0471292319'),
        );
    }

    public function getValidIsbn()
    {
        return array_merge(
            $this->getValidIsbn10(),
            $this->getValidIsbn13()
        );
    }

    public function getInvalidIsbn()
    {
        return array_merge(
            $this->getInvalidIsbn10(),
            $this->getInvalidIsbn13()
        );
    }

    public function testNullIsValid()
    {
        $constraint = new Isbn(true);
        $this->context
            ->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, $constraint);
    }

    public function testEmptyStringIsValid()
    {
        $constraint = new Isbn(true);
        $this->context
            ->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', $constraint);
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $constraint = new Isbn(true);
        $this->validator->validate(new \stdClass(), $constraint);
    }

    /**
     * @dataProvider getValidIsbn10
     */
    public function testValidIsbn10($isbn)
    {
        $constraint = new Isbn(array('isbn10' => true));
        $this->context
            ->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($isbn, $constraint);
    }

    /**
     * @dataProvider getInvalidIsbn10
     */
    public function testInvalidIsbn10($isbn)
    {
        $constraint = new Isbn(array('isbn10' => true));
        $this->context
            ->expects($this->once())
            ->method('addViolation')
            ->with($constraint->isbn10Message);

        $this->validator->validate($isbn, $constraint);
    }

    /**
     * @dataProvider getValidIsbn13
     */
    public function testValidIsbn13($isbn)
    {
        $constraint = new Isbn(array('isbn13' => true));
        $this->context
            ->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($isbn, $constraint);
    }

    /**
     * @dataProvider getInvalidIsbn13
     */
    public function testInvalidIsbn13($isbn)
    {
        $constraint = new Isbn(array('isbn13' => true));
        $this->context
            ->expects($this->once())
            ->method('addViolation')
            ->with($constraint->isbn13Message);

        $this->validator->validate($isbn, $constraint);
    }

    /**
     * @dataProvider getValidIsbn
     */
    public function testValidIsbn($isbn)
    {
        $constraint = new Isbn(array('isbn10' => true, 'isbn13' => true));
        $this->context
            ->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($isbn, $constraint);
    }

    /**
     * @dataProvider getInvalidIsbn
     */
    public function testInvalidIsbn($isbn)
    {
        $constraint = new Isbn(array('isbn10' => true, 'isbn13' => true));
        $this->context
            ->expects($this->once())
            ->method('addViolation')
            ->with($constraint->bothIsbnMessage);

        $this->validator->validate($isbn, $constraint);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\NotEqualTo;
use Symfony\Component\Validator\Constraints\NotEqualToValidator;
use Symfony\Component\Validator\Tests\Constraints\AbstractComparisonValidatorTestCase;

/**
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class NotEqualToValidatorTest extends AbstractComparisonValidatorTestCase
{
    protected function createValidator()
    {
        return new NotEqualToValidator();
    }

    protected function createConstraint(array $options)
    {
        return new NotEqualTo($options);
    }

    /**
     * {@inheritDoc}
     */
    public function provideValidComparisons()
    {
        return array(
            array(1, 2),
            array('22', '333'),
            array(new \DateTime('2001-01-01'), new \DateTime('2000-01-01')),
            array(new ComparisonTest_Class(6), new ComparisonTest_Class(5)),
            array(null, 1),
        );
    }

    /**
     * {@inheritDoc}
     */
    public function provideInvalidComparisons()
    {
        return array(
            array(3, 3, '3', 'integer'),
            array('2', 2, '2', 'integer'),
            array('a', 'a', "'a'", 'string'),
            array(new \DateTime('2000-01-01'), new \DateTime('2000-01-01'), '2000-01-01 00:00:00', 'DateTime'),
            array(new ComparisonTest_Class(5), new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\EqualTo;
use Symfony\Component\Validator\Constraints\EqualToValidator;
use Symfony\Component\Validator\Tests\Constraints\AbstractComparisonValidatorTestCase;

/**
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
class EqualToValidatorTest extends AbstractComparisonValidatorTestCase
{
    protected function createValidator()
    {
        return new EqualToValidator();
    }

    protected function createConstraint(array $options)
    {
        return new EqualTo($options);
    }

    /**
     * {@inheritDoc}
     */
    public function provideValidComparisons()
    {
        return array(
            array(3, 3),
            array(3, '3'),
            array('a', 'a'),
            array(new \DateTime('2000-01-01'), new \DateTime('2000-01-01')),
            array(new ComparisonTest_Class(5), new ComparisonTest_Class(5)),
            array(null, 1),
        );
    }

    /**
     * {@inheritDoc}
     */
    public function provideInvalidComparisons()
    {
        return array(
            array(1, 2, '2', 'integer'),
            array('22', '333', "'333'", 'string'),
            array(new \DateTime('2001-01-01'), new \DateTime('2000-01-01'), '2000-01-01 00:00:00', 'DateTime'),
            array(new ComparisonTest_Class(4), new ComparisonTest_Class(5), '5', __NAMESPACE__.'\ComparisonTest_Class'),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

class CollectionValidatorArrayTest extends CollectionValidatorTest
{
    public function prepareTestData(array $contents)
    {
        return $contents;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Ip;
use Symfony\Component\Validator\Constraints\IpValidator;

class IpValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new IpValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Ip());
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Ip());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $this->validator->validate(new \stdClass(), new Ip());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testInvalidValidatorVersion()
    {
        $ip = new Ip(array(
            'version' => 666,
        ));
    }

    /**
     * @dataProvider getValidIpsV4
     */
    public function testValidIpsV4($ip)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($ip, new Ip(array(
            'version' => Ip::V4,
        )));
    }

    public function getValidIpsV4()
    {
        return array(
            array('0.0.0.0'),
            array('10.0.0.0'),
            array('123.45.67.178'),
            array('172.16.0.0'),
            array('192.168.1.0'),
            array('224.0.0.1'),
            array('255.255.255.255'),
            array('127.0.0.0'),
        );
    }

    /**
     * @dataProvider getValidIpsV6
     */
    public function testValidIpsV6($ip)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($ip, new Ip(array(
            'version' => Ip::V6,
        )));
    }

    public function getValidIpsV6()
    {
        return array(
            array('2001:0db8:85a3:0000:0000:8a2e:0370:7334'),
            array('2001:0DB8:85A3:0000:0000:8A2E:0370:7334'),
            array('2001:0Db8:85a3:0000:0000:8A2e:0370:7334'),
            array('fdfe:dcba:9876:ffff:fdc6:c46b:bb8f:7d4c'),
            array('fdc6:c46b:bb8f:7d4c:fdc6:c46b:bb8f:7d4c'),
            array('fdc6:c46b:bb8f:7d4c:0000:8a2e:0370:7334'),
            array('fe80:0000:0000:0000:0202:b3ff:fe1e:8329'),
            array('fe80:0:0:0:202:b3ff:fe1e:8329'),
            array('fe80::202:b3ff:fe1e:8329'),
            array('0:0:0:0:0:0:0:0'),
            array('::'),
            array('0::'),
            array('::0'),
            array('0::0'),
            // IPv4 mapped to IPv6
            array('2001:0db8:85a3:0000:0000:8a2e:0.0.0.0'),
            array('::0.0.0.0'),
            array('::255.255.255.255'),
            array('::123.45.67.178'),
        );
    }

    /**
     * @dataProvider getValidIpsAll
     */
    public function testValidIpsAll($ip)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($ip, new Ip(array(
            'version' => Ip::ALL,
        )));
    }

    public function getValidIpsAll()
    {
        return array_merge($this->getValidIpsV4(), $this->getValidIpsV6());
    }

    /**
     * @dataProvider getInvalidIpsV4
     */
    public function testInvalidIpsV4($ip)
    {
        $constraint = new Ip(array(
            'version' => Ip::V4,
            'message' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $ip,
            ));

        $this->validator->validate($ip, $constraint);
    }

    public function getInvalidIpsV4()
    {
        return array(
            array('0'),
            array('0.0'),
            array('0.0.0'),
            array('256.0.0.0'),
            array('0.256.0.0'),
            array('0.0.256.0'),
            array('0.0.0.256'),
            array('-1.0.0.0'),
            array('foobar'),
        );
    }

    /**
     * @dataProvider getInvalidPrivateIpsV4
     */
    public function testInvalidPrivateIpsV4($ip)
    {
        $constraint = new Ip(array(
            'version' => Ip::V4_NO_PRIV,
            'message' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $ip,
            ));

        $this->validator->validate($ip, $constraint);
    }

    public function getInvalidPrivateIpsV4()
    {
        return array(
            array('10.0.0.0'),
            array('172.16.0.0'),
            array('192.168.1.0'),
        );
    }

    /**
     * @dataProvider getInvalidReservedIpsV4
     */
    public function testInvalidReservedIpsV4($ip)
    {
        $constraint = new Ip(array(
            'version' => Ip::V4_NO_RES,
            'message' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $ip,
            ));

        $this->validator->validate($ip, $constraint);
    }

    public function getInvalidReservedIpsV4()
    {
        return array(
            array('0.0.0.0'),
            array('224.0.0.1'),
            array('255.255.255.255'),
        );
    }

    /**
     * @dataProvider getInvalidPublicIpsV4
     */
    public function testInvalidPublicIpsV4($ip)
    {
        $constraint = new Ip(array(
            'version' => Ip::V4_ONLY_PUBLIC,
            'message' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $ip,
            ));

        $this->validator->validate($ip, $constraint);
    }

    public function getInvalidPublicIpsV4()
    {
        return array_merge($this->getInvalidPrivateIpsV4(), $this->getInvalidReservedIpsV4());
    }

    /**
     * @dataProvider getInvalidIpsV6
     */
    public function testInvalidIpsV6($ip)
    {
        $constraint = new Ip(array(
            'version' => Ip::V6,
            'message' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $ip,
            ));

        $this->validator->validate($ip, $constraint);
    }

    public function getInvalidIpsV6()
    {
        return array(
            array('z001:0db8:85a3:0000:0000:8a2e:0370:7334'),
            array('fe80'),
            array('fe80:8329'),
            array('fe80:::202:b3ff:fe1e:8329'),
            array('fe80::202:b3ff::fe1e:8329'),
            // IPv4 mapped to IPv6
            array('2001:0db8:85a3:0000:0000:8a2e:0370:0.0.0.0'),
            array('::0.0'),
            array('::0.0.0'),
            array('::256.0.0.0'),
            array('::0.256.0.0'),
            array('::0.0.256.0'),
            array('::0.0.0.256'),
        );
    }

    /**
     * @dataProvider getInvalidPrivateIpsV6
     */
    public function testInvalidPrivateIpsV6($ip)
    {
        $constraint = new Ip(array(
            'version' => Ip::V6_NO_PRIV,
            'message' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $ip,
            ));

        $this->validator->validate($ip, $constraint);
    }

    public function getInvalidPrivateIpsV6()
    {
        return array(
            array('fdfe:dcba:9876:ffff:fdc6:c46b:bb8f:7d4c'),
            array('fdc6:c46b:bb8f:7d4c:fdc6:c46b:bb8f:7d4c'),
            array('fdc6:c46b:bb8f:7d4c:0000:8a2e:0370:7334'),
        );
    }

    /**
     * @dataProvider getInvalidReservedIpsV6
     */
    public function testInvalidReservedIpsV6($ip)
    {
        $constraint = new Ip(array(
            'version' => Ip::V6_NO_RES,
            'message' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $ip,
            ));

        $this->validator->validate($ip, $constraint);
    }

    public function getInvalidReservedIpsV6()
    {
        // Quoting after official filter documentation:
        // "FILTER_FLAG_NO_RES_RANGE = This flag does not apply to IPv6 addresses."
        // Full description: http://php.net/manual/en/filter.filters.flags.php
        return $this->getInvalidIpsV6();
    }

    /**
     * @dataProvider getInvalidPublicIpsV6
     */
    public function testInvalidPublicIpsV6($ip)
    {
        $constraint = new Ip(array(
            'version' => Ip::V6_ONLY_PUBLIC,
            'message' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $ip,
            ));

        $this->validator->validate($ip, $constraint);
    }

    public function getInvalidPublicIpsV6()
    {
        return array_merge($this->getInvalidPrivateIpsV6(), $this->getInvalidReservedIpsV6());
    }

    /**
     * @dataProvider getInvalidIpsAll
     */
    public function testInvalidIpsAll($ip)
    {
        $constraint = new Ip(array(
            'version' => Ip::ALL,
            'message' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $ip,
            ));

        $this->validator->validate($ip, $constraint);
    }

    public function getInvalidIpsAll()
    {
        return array_merge($this->getInvalidIpsV4(), $this->getInvalidIpsV6());
    }

    /**
     * @dataProvider getInvalidPrivateIpsAll
     */
    public function testInvalidPrivateIpsAll($ip)
    {
        $constraint = new Ip(array(
            'version' => Ip::ALL_NO_PRIV,
            'message' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $ip,
            ));

        $this->validator->validate($ip, $constraint);
    }

    public function getInvalidPrivateIpsAll()
    {
        return array_merge($this->getInvalidPrivateIpsV4(), $this->getInvalidPrivateIpsV6());
    }

    /**
     * @dataProvider getInvalidReservedIpsAll
     */
    public function testInvalidReservedIpsAll($ip)
    {
        $constraint = new Ip(array(
            'version' => Ip::ALL_NO_RES,
            'message' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $ip,
            ));

        $this->validator->validate($ip, $constraint);
    }

    public function getInvalidReservedIpsAll()
    {
        return array_merge($this->getInvalidReservedIpsV4(), $this->getInvalidReservedIpsV6());
    }

    /**
     * @dataProvider getInvalidPublicIpsAll
     */
    public function testInvalidPublicIpsAll($ip)
    {
        $constraint = new Ip(array(
            'version' => Ip::ALL_ONLY_PUBLIC,
            'message' => 'myMessage',
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $ip,
            ));

        $this->validator->validate($ip, $constraint);
    }

    public function getInvalidPublicIpsAll()
    {
        return array_merge($this->getInvalidPublicIpsV4(), $this->getInvalidPublicIpsV6());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class CountValidatorArrayTest extends CountValidatorTest
{
    protected function createCollection(array $content)
    {
        return $content;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Collection;
use Symfony\Component\Validator\Constraints\Required;
use Symfony\Component\Validator\Constraints\Optional;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\Valid;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class CollectionTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testRejectInvalidFieldsOption()
    {
        new Collection(array(
            'fields' => 'foo',
        ));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testRejectNonConstraints()
    {
        new Collection(array(
            'foo' => 'bar',
        ));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testRejectValidConstraint()
    {
        new Collection(array(
            'foo' => new Valid(),
        ));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testRejectValidConstraintWithinOptional()
    {
        new Collection(array(
            'foo' => new Optional(new Valid()),
        ));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testRejectValidConstraintWithinRequired()
    {
        new Collection(array(
            'foo' => new Required(new Valid()),
        ));
    }

    public function testAcceptOptionalConstraintAsOneElementArray()
    {
        $collection1 = new Collection(array(
            "fields" => array(
                "alternate_email" => array(
                    new Optional(new Email()),
                ),
            ),
        ));

        $collection2 = new Collection(array(
            "fields" => array(
                "alternate_email" => new Optional(new Email()),
            ),
        ));

        $this->assertEquals($collection1, $collection2);
    }

    public function testAcceptRequiredConstraintAsOneElementArray()
    {
        $collection1 = new Collection(array(
            "fields" => array(
                "alternate_email" => array(
                    new Required(new Email()),
                ),
            ),
        ));

        $collection2 = new Collection(array(
            "fields" => array(
                "alternate_email" => new Required(new Email()),
            ),
        ));

        $this->assertEquals($collection1, $collection2);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Regex;
use Symfony\Component\Validator\Constraints\RegexValidator;

class RegexValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new RegexValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new Regex(array('pattern' => '/^[0-9]+$/')));
    }

    public function testEmptyStringIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate('', new Regex(array('pattern' => '/^[0-9]+$/')));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testExpectsStringCompatibleType()
    {
        $this->validator->validate(new \stdClass(), new Regex(array('pattern' => '/^[0-9]+$/')));
    }

    /**
     * @dataProvider getValidValues
     */
    public function testValidValues($value)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = new Regex(array('pattern' => '/^[0-9]+$/'));
        $this->validator->validate($value, $constraint);
    }

    public function getValidValues()
    {
        return array(
            array(0),
            array('0'),
            array('090909'),
            array(90909),
        );
    }

    /**
     * @dataProvider getInvalidValues
     */
    public function testInvalidValues($value)
    {
        $constraint = new Regex(array(
            'pattern' => '/^[0-9]+$/',
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage', array(
                '{{ value }}' => $value,
            ));

        $this->validator->validate($value, $constraint);
    }

    public function getInvalidValues()
    {
        return array(
            array('abcd'),
            array('090foo'),
        );
    }

    public function testConstraintGetDefaultOption()
    {
        $constraint = new Regex(array(
            'pattern' => '/^[0-9]+$/',
        ));

        $this->assertEquals('pattern', $constraint->getDefaultOption());
    }

    public function testHtmlPatternEscaping()
    {
        $constraint = new Regex(array(
            'pattern' => '/^[0-9]+\/$/',
        ));

        $this->assertEquals('[0-9]+/', $constraint->getHtmlPattern());

        $constraint = new Regex(array(
            'pattern' => '#^[0-9]+\#$#',
        ));

        $this->assertEquals('[0-9]+#', $constraint->getHtmlPattern());
    }

    public function testHtmlPattern()
    {
        // Specified htmlPattern
        $constraint = new Regex(array(
            'pattern' => '/^[a-z]+$/i',
            'htmlPattern' => '[a-zA-Z]+',
        ));
        $this->assertEquals('[a-zA-Z]+', $constraint->getHtmlPattern());

        // Disabled htmlPattern
        $constraint = new Regex(array(
            'pattern' => '/^[a-z]+$/i',
            'htmlPattern' => false,
        ));
        $this->assertNull($constraint->getHtmlPattern());

        // Cannot be converted
        $constraint = new Regex(array(
            'pattern' => '/^[a-z]+$/i',
        ));
        $this->assertNull($constraint->getHtmlPattern());

        // Automatically converted
        $constraint = new Regex(array(
            'pattern' => '/^[a-z]+$/',
        ));
        $this->assertEquals('[a-z]+', $constraint->getHtmlPattern());

        // Automatically converted, adds .*
        $constraint = new Regex(array(
            'pattern' => '/[a-z]+/',
        ));
        $this->assertEquals('.*[a-z]+.*', $constraint->getHtmlPattern());

        // Dropped because of match=false
        $constraint = new Regex(array(
            'pattern' => '/[a-z]+/',
            'match' => false
        ));
        $this->assertNull($constraint->getHtmlPattern());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\NotBlankValidator;

class NotBlankValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new NotBlankValidator();
        $this->validator->initialize($this->context);
    }

    protected function tearDown()
    {
        $this->context = null;
        $this->validator = null;
    }

    /**
     * @dataProvider getValidValues
     */
    public function testValidValues($date)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($date, new NotBlank());
    }

    public function getValidValues()
    {
        return array(
            array('foobar'),
            array(0),
            array(0.0),
            array('0'),
            array(1234),
        );
    }

    public function testNullIsInvalid()
    {
        $constraint = new NotBlank(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage');

        $this->validator->validate(null, $constraint);
    }

    public function testBlankIsInvalid()
    {
        $constraint = new NotBlank(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage');

        $this->validator->validate('', $constraint);
    }

    public function testFalseIsInvalid()
    {
        $constraint = new NotBlank(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage');

        $this->validator->validate(false, $constraint);
    }

    public function testEmptyArrayIsInvalid()
    {
        $constraint = new NotBlank(array(
            'message' => 'myMessage'
        ));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('myMessage');

        $this->validator->validate(array(), $constraint);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\ExecutionContext;
use Symfony\Component\Validator\Constraints\Range;
use Symfony\Component\Validator\Constraints\NotNull;
use Symfony\Component\Validator\Constraints\All;
use Symfony\Component\Validator\Constraints\AllValidator;

class AllValidatorTest extends \PHPUnit_Framework_TestCase
{
    protected $context;
    protected $validator;

    protected function setUp()
    {
        $this->context = $this->getMock('Symfony\Component\Validator\ExecutionContext', array(), array(), '', false);
        $this->validator = new AllValidator();
        $this->validator->initialize($this->context);

        $this->context->expects($this->any())
            ->method('getGroup')
            ->will($this->returnValue('MyGroup'));
    }

    protected function tearDown()
    {
        $this->validator = null;
        $this->context = null;
    }

    public function testNullIsValid()
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate(null, new All(new Range(array('min' => 4))));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
     */
    public function testThrowsExceptionIfNotTraversable()
    {
        $this->validator->validate('foo.barbar', new All(new Range(array('min' => 4))));
    }

    /**
     * @dataProvider getValidArguments
     */
    public function testWalkSingleConstraint($array)
    {
        $constraint = new Range(array('min' => 4));

        $i = 1;

        foreach ($array as $key => $value) {
            $this->context->expects($this->at($i++))
                ->method('validateValue')
                ->with($value, $constraint, '['.$key.']', 'MyGroup');
        }

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($array, new All($constraint));
    }

    /**
     * @dataProvider getValidArguments
     */
    public function testWalkMultipleConstraints($array)
    {
        $constraint1 = new Range(array('min' => 4));
        $constraint2 = new NotNull();

        $constraints = array($constraint1, $constraint2);
        $i = 1;

        foreach ($array as $key => $value) {
            $this->context->expects($this->at($i++))
                ->method('validateValue')
                ->with($value, $constraint1, '['.$key.']', 'MyGroup');
            $this->context->expects($this->at($i++))
                ->method('validateValue')
                ->with($value, $constraint2, '['.$key.']', 'MyGroup');
        }

        $this->context->expects($this->never())
            ->method('addViolation');

        $this->validator->validate($array, new All($constraints));
    }

    public function getValidArguments()
    {
        return array(
            array(array(5, 6, 7)),
            array(new \ArrayObject(array(5, 6, 7))),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraints\Valid;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ValidTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
     */
    public function testRejectGroupsOption()
    {
        new Valid(array('groups' => 'foo'));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Constraints\AbstractComparisonValidator;

class ComparisonTest_Class
{
    protected $value;

    public function __construct($value)
    {
        $this->value = $value;
    }

    public function __toString()
    {
        return (string) $this->value;
    }
}

/**
 * @author Daniel Holmes <daniel@danielholmes.org>
 */
abstract class AbstractComparisonValidatorTestCase extends \PHPUnit_Framework_TestCase
{
    private $validator;
    private $context;

    protected function setUp()
    {
        $this->validator = $this->createValidator();
        $this->context = $this->getMockBuilder('Symfony\Component\Validator\ExecutionContext')
            ->disableOriginalConstructor()
            ->getMock();
        $this->validator->initialize($this->context);
    }

    /**
     * @return AbstractComparisonValidator
     */
    abstract protected function createValidator();

    public function testThrowsConstraintExceptionIfNoValueOrProperty()
    {
        $this->setExpectedException('Symfony\Component\Validator\Exception\ConstraintDefinitionException');

        $comparison = $this->createConstraint(array());
        $this->validator->validate('some value', $comparison);
    }

    /**
     * @dataProvider provideValidComparisons
     * @param mixed $dirtyValue
     * @param mixed $comparisonValue
     */
    public function testValidComparisonToValue($dirtyValue, $comparisonValue)
    {
        $this->context->expects($this->never())
            ->method('addViolation');

        $constraint = $this->createConstraint(array('value' => $comparisonValue));

        $this->context->expects($this->any())
            ->method('getPropertyPath')
            ->will($this->returnValue('property1'));

        $this->validator->validate($dirtyValue, $constraint);
    }

    /**
     * @return array
     */
    abstract public function provideValidComparisons();

    /**
     * @dataProvider provideInvalidComparisons
     * @param mixed  $dirtyValue
     * @param mixed  $comparedValue
     * @param mixed  $comparedValueString
     * @param string $comparedValueType
     */
    public function testInvalidComparisonToValue($dirtyValue, $comparedValue, $comparedValueString, $comparedValueType)
    {
        $constraint = $this->createConstraint(array('value' => $comparedValue));
        $constraint->message = 'Constraint Message';

        $this->context->expects($this->any())
            ->method('getPropertyPath')
            ->will($this->returnValue('property1'));

        $this->context->expects($this->once())
            ->method('addViolation')
            ->with('Constraint Message', array(
                '{{ value }}' => $comparedValueString,
                '{{ compared_value }}' => $comparedValueString,
                '{{ compared_value_type }}' => $comparedValueType
            ));

        $this->validator->validate($dirtyValue, $constraint);
    }

    /**
     * @return array
     */
    abstract public function provideInvalidComparisons();

    /**
     * @param  array      $options Options for the constraint
     * @return Constraint
     */
    abstract protected function createConstraint(array $options);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\ExecutionContextInterface;

class ConstraintAValidator extends ConstraintValidator
{
    public static $passedContext;

    public function initialize(ExecutionContextInterface $context)
    {
        parent::initialize($context);

        self::$passedContext = $context;
    }

    public function validate($value, Constraint $constraint)
    {
        if ('VALID' != $value) {
            $this->context->addViolation('message', array('param' => 'value'));

            return;
        }

        return;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\ExecutionContextInterface;

/**
 * @Symfony\Component\Validator\Tests\Fixtures\ConstraintA
 * @Assert\GroupSequence({"Foo", "Entity"})
 * @Assert\Callback({"Symfony\Component\Validator\Tests\Fixtures\CallbackClass", "callback"})
 */
class Entity extends EntityParent implements EntityInterface
{
    /**
     * @Assert\NotNull
     * @Assert\Range(min=3)
     * @Assert\All({@Assert\NotNull, @Assert\Range(min=3)}),
     * @Assert\All(constraints={@Assert\NotNull, @Assert\Range(min=3)})
     * @Assert\Collection(fields={
     *   "foo" = {@Assert\NotNull, @Assert\Range(min=3)},
     *   "bar" = @Assert\Range(min=5)
     * })
     * @Assert\Choice(choices={"A", "B"}, message="Must be one of %choices%")
     */
    protected $firstName;
    protected $lastName;
    public $reference;
    private $internal;
    public $data = 'Overridden data';

    public function __construct($internal = null)
    {
        $this->internal = $internal;
    }

    public function getInternal()
    {
        return $this->internal.' from getter';
    }

    /**
     * @Assert\NotNull
     */
    public function getLastName()
    {
        return $this->lastName;
    }

    public function getData()
    {
        return 'Overridden data';
    }

    /**
     * @Assert\Callback
     */
    public function validateMe(ExecutionContextInterface $context)
    {
    }

    /**
     * @Assert\Callback
     */
    public static function validateMeStatic($object, ExecutionContextInterface $context)
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Mapping\Loader\FilesLoader as BaseFilesLoader;
use Symfony\Component\Validator\Mapping\Loader\LoaderInterface;

abstract class FilesLoader extends BaseFilesLoader
{
    protected $timesCalled = 0;
    protected $loader;

    public function __construct(array $paths, LoaderInterface $loader)
    {
        $this->loader = $loader;
        parent::__construct($paths);
    }

    protected function getFileLoaderInstance($file)
    {
        $this->timesCalled++;

        return $this->loader;
    }

    public function getTimesCalled()
    {
        return $this->timesCalled;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraint;

class FailingConstraint extends Constraint
{
    public $message = 'Failed';

    public function getTargets()
    {
        return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\ExecutionContextInterface;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class CallbackClass
{
    public static function callback($object, ExecutionContextInterface $context)
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\GroupSequenceProviderInterface;

/**
 * @Assert\GroupSequenceProvider
 */
class GroupSequenceProviderEntity implements GroupSequenceProviderInterface
{
    public $firstName;
    public $lastName;

    protected $groups = array();

    public function setGroups($groups)
    {
        $this->groups = $groups;
    }

    public function getGroupSequence()
    {
        return $this->groups;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraint;

/** @Annotation */
class ConstraintWithValueAsDefault extends Constraint
{
    public $property;
    public $value;

    public function getDefaultOption()
    {
        return 'value';
    }

    public function getTargets()
    {
        return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\MetadataFactoryInterface;
use Symfony\Component\Validator\Exception\NoSuchMetadataException;
use Symfony\Component\Validator\Mapping\ClassMetadata;

class FakeMetadataFactory implements MetadataFactoryInterface
{
    protected $metadatas = array();

    public function getMetadataFor($class)
    {
        if (is_object($class)) {
            $class = get_class($class);
        }

        if (!is_string($class)) {
            throw new NoSuchMetadataException(sprintf('No metadata for type %s', gettype($class)));
        }

        if (!isset($this->metadatas[$class])) {
            throw new NoSuchMetadataException(sprintf('No metadata for "%s"', $class));
        }

        return $this->metadatas[$class];
    }

    public function hasMetadataFor($class)
    {
        if (is_object($class)) {
            $class = get_class($class);
        }

        if (!is_string($class)) {
            return false;
        }

        return isset($this->metadatas[$class]);
    }

    public function addMetadata(ClassMetadata $metadata)
    {
        $this->metadatas[$metadata->getClassName()] = $metadata;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

class InvalidConstraintValidator {}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraint;

/** @Annotation */
class ConstraintWithValue extends Constraint
{
    public $property;
    public $value;

    public function getDefaultOption()
    {
        return 'property';
    }

    public function getTargets()
    {
        return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraint;

class PropertyConstraint extends Constraint
{
    public function getTargets()
    {
        return self::PROPERTY_CONSTRAINT;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraint;

class InvalidConstraint extends Constraint {}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraint;

/** @Annotation */
class ConstraintB extends Constraint
{
    public function getTargets()
    {
        return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

class Reference
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraint;

class ClassConstraint extends Constraint
{
    public function getTargets()
    {
        return self::CLASS_CONSTRAINT;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraint;

/** @Annotation */
class ConstraintA extends Constraint
{
    public $property1;
    public $property2;

    public function getDefaultOption()
    {
        return 'property2';
    }

    public function getTargets()
    {
        return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class FailingConstraintValidator extends ConstraintValidator
{
    public function validate($value, Constraint $constraint)
    {
        $this->context->addViolation($constraint->message, array());

        return;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

interface EntityInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraint;

/** @Annotation */
class ConstraintC extends Constraint
{
    public $option1;

    public function getRequiredOptions()
    {
        return array('option1');
    }

    public function getTargets()
    {
        return array(self::PROPERTY_CONSTRAINT, self::CLASS_CONSTRAINT);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Fixtures;

use Symfony\Component\Validator\Constraints\NotNull;

class EntityParent
{
    protected $firstName;
    private $internal;
    private $data = 'Data';

    /**
     * @NotNull
     */
    protected $other;

    public function getData()
    {
        return 'Data';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping;

use Symfony\Component\Validator\Mapping\BlackholeMetadataFactory;

class BlackholeMetadataFactoryTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException \LogicException
     */
    public function testGetMetadataForThrowsALogicException()
    {
        $metadataFactory = new BlackholeMetadataFactory();
        $metadataFactory->getMetadataFor('foo');
    }

    public function testHasMetadataForReturnsFalse()
    {
        $metadataFactory = new BlackholeMetadataFactory();

        $this->assertFalse($metadataFactory->hasMetadataFor('foo'));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping\Cache;

use Symfony\Component\Validator\Mapping\Cache\ApcCache;

class ApcCacheTest extends \PHPUnit_Framework_TestCase
{
    protected function setUp()
    {
        if (!extension_loaded('apc') || !ini_get('apc.enable_cli')) {
            $this->markTestSkipped('APC is not loaded.');
        }
    }

    public function testWrite()
    {
        $meta = $this->getMockBuilder('Symfony\\Component\\Validator\\Mapping\\ClassMetadata')
            ->disableOriginalConstructor()
            ->setMethods(array('getClassName'))
            ->getMock();

        $meta->expects($this->once())
            ->method('getClassName')
            ->will($this->returnValue('bar'));

        $cache = new ApcCache('foo');
        $cache->write($meta);

        $this->assertInstanceOf('Symfony\\Component\\Validator\\Mapping\\ClassMetadata', apc_fetch('foobar'), '->write() stores metadata in APC');
    }

    public function testHas()
    {
        $meta = $this->getMockBuilder('Symfony\\Component\\Validator\\Mapping\\ClassMetadata')
            ->disableOriginalConstructor()
            ->setMethods(array('getClassName'))
            ->getMock();

        $meta->expects($this->once())
            ->method('getClassName')
            ->will($this->returnValue('bar'));

        apc_delete('foobar');

        $cache = new ApcCache('foo');
        $this->assertFalse($cache->has('bar'), '->has() returns false when there is no entry');

        $cache->write($meta);
        $this->assertTrue($cache->has('bar'), '->has() returns true when the is an entry');
    }

    public function testRead()
    {
        $meta = $this->getMockBuilder('Symfony\\Component\\Validator\\Mapping\\ClassMetadata')
            ->disableOriginalConstructor()
            ->setMethods(array('getClassName'))
            ->getMock();

        $meta->expects($this->once())
            ->method('getClassName')
            ->will($this->returnValue('bar'));

        $cache = new ApcCache('foo');
        $cache->write($meta);

        $this->assertInstanceOf('Symfony\\Component\\Validator\\Mapping\\ClassMetadata', $cache->read('bar'), '->read() returns metadata');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Constraints\Valid;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Exception\GroupDefinitionException;
use Symfony\Component\Validator\Tests\Fixtures\Entity;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintB;
use Symfony\Component\Validator\Tests\Fixtures\PropertyConstraint;

class ClassMetadataTest extends \PHPUnit_Framework_TestCase
{
    const CLASSNAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity';
    const PARENTCLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParent';
    const PROVIDERCLASS = 'Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity';

    protected $metadata;

    protected function setUp()
    {
        $this->metadata = new ClassMetadata(self::CLASSNAME);
    }

    protected function tearDown()
    {
        $this->metadata = null;
    }

    public function testAddConstraintDoesNotAcceptValid()
    {
        $this->setExpectedException('Symfony\Component\Validator\Exception\ConstraintDefinitionException');

        $this->metadata->addConstraint(new Valid());
    }

    public function testAddConstraintRequiresClassConstraints()
    {
        $this->setExpectedException('Symfony\Component\Validator\Exception\ConstraintDefinitionException');

        $this->metadata->addConstraint(new PropertyConstraint());
    }

    public function testAddPropertyConstraints()
    {
        $this->metadata->addPropertyConstraint('firstName', new ConstraintA());
        $this->metadata->addPropertyConstraint('lastName', new ConstraintB());

        $this->assertEquals(array('firstName', 'lastName'), $this->metadata->getConstrainedProperties());
    }

    public function testMergeConstraintsMergesClassConstraints()
    {
        $parent = new ClassMetadata(self::PARENTCLASS);
        $parent->addConstraint(new ConstraintA());

        $this->metadata->mergeConstraints($parent);
        $this->metadata->addConstraint(new ConstraintA());

        $constraints = array(
            new ConstraintA(array('groups' => array(
                'Default',
                'EntityParent',
                'Entity',
            ))),
            new ConstraintA(array('groups' => array(
                'Default',
                'Entity',
            ))),
        );

        $this->assertEquals($constraints, $this->metadata->getConstraints());
    }

    public function testMergeConstraintsMergesMemberConstraints()
    {
        $parent = new ClassMetadata(self::PARENTCLASS);
        $parent->addPropertyConstraint('firstName', new ConstraintA());

        $this->metadata->mergeConstraints($parent);
        $this->metadata->addPropertyConstraint('firstName', new ConstraintA());

        $constraints = array(
            new ConstraintA(array('groups' => array(
                'Default',
                'EntityParent',
                'Entity',
            ))),
            new ConstraintA(array('groups' => array(
                'Default',
                'Entity',
            ))),
        );

        $members = $this->metadata->getMemberMetadatas('firstName');

        $this->assertCount(1, $members);
        $this->assertEquals(self::PARENTCLASS, $members[0]->getClassName());
        $this->assertEquals($constraints, $members[0]->getConstraints());
    }

    public function testMemberMetadatas()
    {
        $this->metadata->addPropertyConstraint('firstName', new ConstraintA());

        $this->assertTrue($this->metadata->hasMemberMetadatas('firstName'));
        $this->assertFalse($this->metadata->hasMemberMetadatas('non_existant_field'));
    }

    public function testMergeConstraintsKeepsPrivateMembersSeparate()
    {
        $parent = new ClassMetadata(self::PARENTCLASS);
        $parent->addPropertyConstraint('internal', new ConstraintA());

        $this->metadata->mergeConstraints($parent);
        $this->metadata->addPropertyConstraint('internal', new ConstraintA());

        $parentConstraints = array(
            new ConstraintA(array('groups' => array(
                'Default',
                'EntityParent',
                'Entity',
            ))),
        );
        $constraints = array(
            new ConstraintA(array('groups' => array(
                'Default',
                'Entity',
            ))),
        );

        $members = $this->metadata->getMemberMetadatas('internal');

        $this->assertCount(2, $members);
        $this->assertEquals(self::PARENTCLASS, $members[0]->getClassName());
        $this->assertEquals($parentConstraints, $members[0]->getConstraints());
        $this->assertEquals(self::CLASSNAME, $members[1]->getClassName());
        $this->assertEquals($constraints, $members[1]->getConstraints());
    }

    public function testGetReflectionClass()
    {
        $reflClass = new \ReflectionClass(self::CLASSNAME);

        $this->assertEquals($reflClass, $this->metadata->getReflectionClass());
    }

    public function testSerialize()
    {
        $this->metadata->addConstraint(new ConstraintA(array('property1' => 'A')));
        $this->metadata->addConstraint(new ConstraintB(array('groups' => 'TestGroup')));
        $this->metadata->addPropertyConstraint('firstName', new ConstraintA());
        $this->metadata->addGetterConstraint('lastName', new ConstraintB());

        $metadata = unserialize(serialize($this->metadata));

        $this->assertEquals($this->metadata, $metadata);
    }

    public function testGroupSequencesWorkIfContainingDefaultGroup()
    {
        $this->metadata->setGroupSequence(array('Foo', $this->metadata->getDefaultGroup()));
    }

    public function testGroupSequencesFailIfNotContainingDefaultGroup()
    {
        $this->setExpectedException('Symfony\Component\Validator\Exception\GroupDefinitionException');

        $this->metadata->setGroupSequence(array('Foo', 'Bar'));
    }

    public function testGroupSequencesFailIfContainingDefault()
    {
        $this->setExpectedException('Symfony\Component\Validator\Exception\GroupDefinitionException');

        $this->metadata->setGroupSequence(array('Foo', $this->metadata->getDefaultGroup(), Constraint::DEFAULT_GROUP));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\GroupDefinitionException
     */
    public function testGroupSequenceFailsIfGroupSequenceProviderIsSet()
    {
        $metadata = new ClassMetadata(self::PROVIDERCLASS);
        $metadata->setGroupSequenceProvider(true);
        $metadata->setGroupSequence(array('GroupSequenceProviderEntity', 'Foo'));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\GroupDefinitionException
     */
    public function testGroupSequenceProviderFailsIfGroupSequenceIsSet()
    {
        $metadata = new ClassMetadata(self::PROVIDERCLASS);
        $metadata->setGroupSequence(array('GroupSequenceProviderEntity', 'Foo'));
        $metadata->setGroupSequenceProvider(true);
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\GroupDefinitionException
     */
    public function testGroupSequenceProviderFailsIfDomainClassIsInvalid()
    {
        $metadata = new ClassMetadata('stdClass');
        $metadata->setGroupSequenceProvider(true);
    }

    public function testGroupSequenceProvider()
    {
        $metadata = new ClassMetadata(self::PROVIDERCLASS);
        $metadata->setGroupSequenceProvider(true);
        $this->assertTrue($metadata->isGroupSequenceProvider());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping;

use Symfony\Component\Validator\Mapping\PropertyMetadata;
use Symfony\Component\Validator\Tests\Fixtures\Entity;

class PropertyMetadataTest extends \PHPUnit_Framework_TestCase
{
    const CLASSNAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity';
    const PARENTCLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParent';

    public function testInvalidPropertyName()
    {
        $this->setExpectedException('Symfony\Component\Validator\Exception\ValidatorException');

        new PropertyMetadata(self::CLASSNAME, 'foobar');
    }

    public function testGetPropertyValueFromPrivateProperty()
    {
        $entity = new Entity('foobar');
        $metadata = new PropertyMetadata(self::CLASSNAME, 'internal');

        $this->assertEquals('foobar', $metadata->getPropertyValue($entity));
    }

    public function testGetPropertyValueFromOverriddenPrivateProperty()
    {
        $entity = new Entity('foobar');
        $metadata = new PropertyMetadata(self::PARENTCLASS, 'data');

        $this->assertTrue($metadata->isPublic($entity));
        $this->assertEquals('Overridden data', $metadata->getPropertyValue($entity));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping\Loader;

use Symfony\Component\Validator\Constraints\All;
use Symfony\Component\Validator\Constraints\Callback;
use Symfony\Component\Validator\Constraints\Collection;
use Symfony\Component\Validator\Constraints\NotNull;
use Symfony\Component\Validator\Constraints\Range;
use Symfony\Component\Validator\Constraints\Choice;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Mapping\Loader\YamlFileLoader;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintB;

class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testLoadClassMetadataReturnsFalseIfEmpty()
    {
        $loader = new YamlFileLoader(__DIR__.'/empty-mapping.yml');
        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');

        $this->assertFalse($loader->loadClassMetadata($metadata));
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testLoadClassMetadataThrowsExceptionIfNotAnArray()
    {
        $loader = new YamlFileLoader(__DIR__.'/nonvalid-mapping.yml');
        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
        $loader->loadClassMetadata($metadata);
    }

    public function testLoadClassMetadataReturnsTrueIfSuccessful()
    {
        $loader = new YamlFileLoader(__DIR__.'/constraint-mapping.yml');
        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');

        $this->assertTrue($loader->loadClassMetadata($metadata));
    }

    public function testLoadClassMetadataReturnsFalseIfNotSuccessful()
    {
        $loader = new YamlFileLoader(__DIR__.'/constraint-mapping.yml');
        $metadata = new ClassMetadata('\stdClass');

        $this->assertFalse($loader->loadClassMetadata($metadata));
    }

    public function testLoadClassMetadata()
    {
        $loader = new YamlFileLoader(__DIR__.'/constraint-mapping.yml');
        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');

        $loader->loadClassMetadata($metadata);

        $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
        $expected->setGroupSequence(array('Foo', 'Entity'));
        $expected->addConstraint(new ConstraintA());
        $expected->addConstraint(new ConstraintB());
        $expected->addConstraint(new Callback('validateMe'));
        $expected->addConstraint(new Callback('validateMeStatic'));
        $expected->addConstraint(new Callback(array('Symfony\Component\Validator\Tests\Fixtures\CallbackClass', 'callback')));
        $expected->addPropertyConstraint('firstName', new NotNull());
        $expected->addPropertyConstraint('firstName', new Range(array('min' => 3)));
        $expected->addPropertyConstraint('firstName', new Choice(array('A', 'B')));
        $expected->addPropertyConstraint('firstName', new All(array(new NotNull(), new Range(array('min' => 3)))));
        $expected->addPropertyConstraint('firstName', new All(array('constraints' => array(new NotNull(), new Range(array('min' => 3))))));
        $expected->addPropertyConstraint('firstName', new Collection(array('fields' => array(
            'foo' => array(new NotNull(), new Range(array('min' => 3))),
            'bar' => array(new Range(array('min' => 5))),
        ))));
        $expected->addPropertyConstraint('firstName', new Choice(array(
            'message' => 'Must be one of %choices%',
            'choices' => array('A', 'B'),
        )));
        $expected->addGetterConstraint('lastName', new NotNull());

        $this->assertEquals($expected, $metadata);
    }

    public function testLoadGroupSequenceProvider()
    {
        $loader = new YamlFileLoader(__DIR__.'/constraint-mapping.yml');
        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity');

        $loader->loadClassMetadata($metadata);

        $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity');
        $expected->setGroupSequenceProvider(true);

        $this->assertEquals($expected, $metadata);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping\Loader;

use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;

class StaticMethodLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testLoadClassMetadataReturnsTrueIfSuccessful()
    {
        $loader = new StaticMethodLoader('loadMetadata');
        $metadata = new ClassMetadata(__NAMESPACE__.'\StaticLoaderEntity');

        $this->assertTrue($loader->loadClassMetadata($metadata));
    }

    public function testLoadClassMetadataReturnsFalseIfNotSuccessful()
    {
        $loader = new StaticMethodLoader('loadMetadata');
        $metadata = new ClassMetadata('\stdClass');

        $this->assertFalse($loader->loadClassMetadata($metadata));
    }

    public function testLoadClassMetadata()
    {
        $loader = new StaticMethodLoader('loadMetadata');
        $metadata = new ClassMetadata(__NAMESPACE__.'\StaticLoaderEntity');

        $loader->loadClassMetadata($metadata);

        $this->assertEquals(StaticLoaderEntity::$invokedWith, $metadata);
    }

    public function testLoadClassMetadataDoesNotRepeatLoadWithParentClasses()
    {
        $loader = new StaticMethodLoader('loadMetadata');
        $metadata = new ClassMetadata(__NAMESPACE__.'\StaticLoaderDocument');
        $loader->loadClassMetadata($metadata);
        $this->assertCount(0, $metadata->getConstraints());

        $loader = new StaticMethodLoader('loadMetadata');
        $metadata = new ClassMetadata(__NAMESPACE__.'\BaseStaticLoaderDocument');
        $loader->loadClassMetadata($metadata);
        $this->assertCount(1, $metadata->getConstraints());
    }

    public function testLoadClassMetadataIgnoresInterfaces()
    {
        $loader = new StaticMethodLoader('loadMetadata');
        $metadata = new ClassMetadata(__NAMESPACE__.'\StaticLoaderInterface');

        $loader->loadClassMetadata($metadata);

        $this->assertCount(0, $metadata->getConstraints());
    }

    public function testLoadClassMetadataInAbstractClasses()
    {
        $loader = new StaticMethodLoader('loadMetadata');
        $metadata = new ClassMetadata(__NAMESPACE__.'\AbstractStaticLoader');

        $loader->loadClassMetadata($metadata);

        $this->assertCount(1, $metadata->getConstraints());
    }

    public function testLoadClassMetadataIgnoresAbstractMethods()
    {
        $loader = new StaticMethodLoader('loadMetadata');
        try {
            include __DIR__ . '/AbstractMethodStaticLoader.php';
            $this->fail('AbstractMethodStaticLoader should produce a strict standard error.');
        } catch (\Exception $e) {
        }

        $metadata = new ClassMetadata(__NAMESPACE__.'\AbstractMethodStaticLoader');
        $loader->loadClassMetadata($metadata);

        $this->assertCount(0, $metadata->getConstraints());
    }
}

interface StaticLoaderInterface
{
    public static function loadMetadata(ClassMetadata $metadata);
}

abstract class AbstractStaticLoader
{
    public static function loadMetadata(ClassMetadata $metadata)
    {
        $metadata->addConstraint(new ConstraintA());
    }
}

class StaticLoaderEntity
{
    public static $invokedWith = null;

    public static function loadMetadata(ClassMetadata $metadata)
    {
        self::$invokedWith = $metadata;
    }
}

class StaticLoaderDocument extends BaseStaticLoaderDocument
{
}

class BaseStaticLoaderDocument
{
    public static function loadMetadata(ClassMetadata $metadata)
    {
        $metadata->addConstraint(new ConstraintA());
    }
}
<?xml version="1.0" ?>

<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">

  <namespace prefix="custom">Symfony\Component\Validator\Tests\Fixtures\</namespace>

  <class name="Symfony\Component\Validator\Tests\Fixtures\Entity">
    <property name="firstName">
      <!-- Constraint with a Boolean -->
      <constraint name="Regex">
          <option name="pattern">/^1/</option>
          <option name="match">false</option>
      </constraint>
    </property>
  </class>

</constraint-mapping>
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping\Loader;

use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Mapping\Loader\LoaderChain;

class LoaderChainTest extends \PHPUnit_Framework_TestCase
{
    public function testAllLoadersAreCalled()
    {
        $metadata = new ClassMetadata('\stdClass');

        $loader1 = $this->getMock('Symfony\Component\Validator\Mapping\Loader\LoaderInterface');
        $loader1->expects($this->once())
                        ->method('loadClassMetadata')
                        ->with($this->equalTo($metadata));

        $loader2 = $this->getMock('Symfony\Component\Validator\Mapping\Loader\LoaderInterface');
        $loader2->expects($this->once())
                        ->method('loadClassMetadata')
                        ->with($this->equalTo($metadata));

        $chain = new LoaderChain(array(
            $loader1,
            $loader2,
        ));

        $chain->loadClassMetadata($metadata);
    }

    public function testReturnsTrueIfAnyLoaderReturnedTrue()
    {
        $metadata = new ClassMetadata('\stdClass');

        $loader1 = $this->getMock('Symfony\Component\Validator\Mapping\Loader\LoaderInterface');
        $loader1->expects($this->any())
                        ->method('loadClassMetadata')
                        ->will($this->returnValue(true));

        $loader2 = $this->getMock('Symfony\Component\Validator\Mapping\Loader\LoaderInterface');
        $loader2->expects($this->any())
                        ->method('loadClassMetadata')
                        ->will($this->returnValue(false));

        $chain = new LoaderChain(array(
            $loader1,
            $loader2,
        ));

        $this->assertTrue($chain->loadClassMetadata($metadata));
    }

    public function testReturnsFalseIfNoLoaderReturnedTrue()
    {
        $metadata = new ClassMetadata('\stdClass');

        $loader1 = $this->getMock('Symfony\Component\Validator\Mapping\Loader\LoaderInterface');
        $loader1->expects($this->any())
                        ->method('loadClassMetadata')
                        ->will($this->returnValue(false));

        $loader2 = $this->getMock('Symfony\Component\Validator\Mapping\Loader\LoaderInterface');
        $loader2->expects($this->any())
                        ->method('loadClassMetadata')
                        ->will($this->returnValue(false));

        $chain = new LoaderChain(array(
            $loader1,
            $loader2,
        ));

        $this->assertFalse($chain->loadClassMetadata($metadata));
    }
}
namespaces:
  custom: Symfony\Component\Validator\Tests\Fixtures\

Symfony\Component\Validator\Tests\Fixtures\Entity:
  group_sequence:
    - Foo
    - Entity

  constraints:
    # Custom constraint
    - Symfony\Component\Validator\Tests\Fixtures\ConstraintA: ~
    # Custom constraint with namespaces prefix
    - "custom:ConstraintB": ~
    # Callbacks
    - Callback: validateMe
    - Callback: validateMeStatic
    - Callback: [Symfony\Component\Validator\Tests\Fixtures\CallbackClass, callback]

  properties:
    firstName:
      # Constraint without value
      - NotNull: ~
      # Constraint with single value
      - Range:
          min: 3
      # Constraint with multiple values
      - Choice: [A, B]
      # Constraint with child constraints
      - All:
          - NotNull: ~
          - Range:
              min: 3
      # Option with child constraints
      - All:
          constraints:
            - NotNull: ~
            - Range:
                min: 3
      # Value with child constraints
      - Collection:
          fields:
            foo:
              - NotNull: ~
              - Range:
                  min: 3
            bar:
              - Range:
                  min: 5
      # Constraint with options
      - Choice: { choices: [A, B], message: Must be one of %choices% }
    dummy:

  getters:
    lastName:
      - NotNull: ~

Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity:
  group_sequence_provider: true
<?php

namespace Symfony\Component\Validator\Tests\Mapping\Loader;

use Symfony\Component\Validator\Mapping\ClassMetadata;

abstract class AbstractMethodStaticLoader
{
    abstract public static function loadMetadata(ClassMetadata $metadata);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping\Loader;

use Symfony\Component\Validator\Constraints\All;
use Symfony\Component\Validator\Constraints\Callback;
use Symfony\Component\Validator\Constraints\Collection;
use Symfony\Component\Validator\Constraints\NotNull;
use Symfony\Component\Validator\Constraints\Range;
use Symfony\Component\Validator\Constraints\Choice;
use Symfony\Component\Validator\Constraints\Regex;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Mapping\Loader\XmlFileLoader;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintB;

class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testLoadClassMetadataReturnsTrueIfSuccessful()
    {
        $loader = new XmlFileLoader(__DIR__.'/constraint-mapping.xml');
        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');

        $this->assertTrue($loader->loadClassMetadata($metadata));
    }

    public function testLoadClassMetadataReturnsFalseIfNotSuccessful()
    {
        $loader = new XmlFileLoader(__DIR__.'/constraint-mapping.xml');
        $metadata = new ClassMetadata('\stdClass');

        $this->assertFalse($loader->loadClassMetadata($metadata));
    }

    public function testLoadClassMetadata()
    {
        $loader = new XmlFileLoader(__DIR__.'/constraint-mapping.xml');
        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');

        $loader->loadClassMetadata($metadata);

        $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
        $expected->setGroupSequence(array('Foo', 'Entity'));
        $expected->addConstraint(new ConstraintA());
        $expected->addConstraint(new ConstraintB());
        $expected->addConstraint(new Callback('validateMe'));
        $expected->addConstraint(new Callback('validateMeStatic'));
        $expected->addConstraint(new Callback(array('Symfony\Component\Validator\Tests\Fixtures\CallbackClass', 'callback')));
        $expected->addPropertyConstraint('firstName', new NotNull());
        $expected->addPropertyConstraint('firstName', new Range(array('min' => 3)));
        $expected->addPropertyConstraint('firstName', new Choice(array('A', 'B')));
        $expected->addPropertyConstraint('firstName', new All(array(new NotNull(), new Range(array('min' => 3)))));
        $expected->addPropertyConstraint('firstName', new All(array('constraints' => array(new NotNull(), new Range(array('min' => 3))))));
        $expected->addPropertyConstraint('firstName', new Collection(array('fields' => array(
            'foo' => array(new NotNull(), new Range(array('min' => 3))),
            'bar' => array(new Range(array('min' => 5))),
        ))));
        $expected->addPropertyConstraint('firstName', new Choice(array(
            'message' => 'Must be one of %choices%',
            'choices' => array('A', 'B'),
        )));
        $expected->addGetterConstraint('lastName', new NotNull());

        $this->assertEquals($expected, $metadata);
    }

    public function testLoadClassMetadataWithNonStrings()
    {
        $loader = new XmlFileLoader(__DIR__.'/constraint-mapping-non-strings.xml');
        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');

        $loader->loadClassMetadata($metadata);

        $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
        $expected->addPropertyConstraint('firstName', new Regex(array('pattern' => '/^1/', 'match' => false)));

        $properties = $metadata->getPropertyMetadata('firstName');
        $constraints = $properties[0]->getConstraints();

        $this->assertFalse($constraints[0]->match);
    }

    public function testLoadGroupSequenceProvider()
    {
        $loader = new XmlFileLoader(__DIR__.'/constraint-mapping.xml');
        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity');

        $loader->loadClassMetadata($metadata);

        $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity');
        $expected->setGroupSequenceProvider(true);

        $this->assertEquals($expected, $metadata);
    }

    /**
     * @expectedException        \Symfony\Component\Validator\Exception\MappingException
     * @expectedExceptionMessage Document types are not allowed.
     */
    public function testDocTypeIsNotAllowed()
    {
        $loader = new XmlFileLoader(__DIR__.'/withdoctype.xml');
        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');

        $loader->loadClassMetadata($metadata);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping\Loader;

use Doctrine\Common\Annotations\AnnotationReader;
use Symfony\Component\Validator\Constraints\All;
use Symfony\Component\Validator\Constraints\Callback;
use Symfony\Component\Validator\Constraints\Collection;
use Symfony\Component\Validator\Constraints\NotNull;
use Symfony\Component\Validator\Constraints\Range;
use Symfony\Component\Validator\Constraints\Choice;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;

class AnnotationLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testLoadClassMetadataReturnsTrueIfSuccessful()
    {
        $reader = new AnnotationReader();
        $loader = new AnnotationLoader($reader);
        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');

        $this->assertTrue($loader->loadClassMetadata($metadata));
    }

    public function testLoadClassMetadataReturnsFalseIfNotSuccessful()
    {
        $loader = new AnnotationLoader(new AnnotationReader());
        $metadata = new ClassMetadata('\stdClass');

        $this->assertFalse($loader->loadClassMetadata($metadata));
    }

    public function testLoadClassMetadata()
    {
        $loader = new AnnotationLoader(new AnnotationReader());
        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');

        $loader->loadClassMetadata($metadata);

        $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
        $expected->setGroupSequence(array('Foo', 'Entity'));
        $expected->addConstraint(new ConstraintA());
        $expected->addConstraint(new Callback(array('Symfony\Component\Validator\Tests\Fixtures\CallbackClass', 'callback')));
        $expected->addConstraint(new Callback('validateMe'));
        $expected->addConstraint(new Callback('validateMeStatic'));
        $expected->addPropertyConstraint('firstName', new NotNull());
        $expected->addPropertyConstraint('firstName', new Range(array('min' => 3)));
        $expected->addPropertyConstraint('firstName', new All(array(new NotNull(), new Range(array('min' => 3)))));
        $expected->addPropertyConstraint('firstName', new All(array('constraints' => array(new NotNull(), new Range(array('min' => 3))))));
        $expected->addPropertyConstraint('firstName', new Collection(array('fields' => array(
            'foo' => array(new NotNull(), new Range(array('min' => 3))),
            'bar' => new Range(array('min' => 5)),
        ))));
        $expected->addPropertyConstraint('firstName', new Choice(array(
            'message' => 'Must be one of %choices%',
            'choices' => array('A', 'B'),
        )));
        $expected->addGetterConstraint('lastName', new NotNull());

        // load reflection class so that the comparison passes
        $expected->getReflectionClass();

        $this->assertEquals($expected, $metadata);
    }

    /**
     * Test MetaData merge with parent annotation.
     */
    public function testLoadParentClassMetadata()
    {
        $loader = new AnnotationLoader(new AnnotationReader());

        // Load Parent MetaData
        $parent_metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\EntityParent');
        $loader->loadClassMetadata($parent_metadata);

        $expected_parent = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\EntityParent');
        $expected_parent->addPropertyConstraint('other', new NotNull());
        $expected_parent->getReflectionClass();

        $this->assertEquals($expected_parent, $parent_metadata);
    }
    /**
     * Test MetaData merge with parent annotation.
     */
    public function testLoadClassMetadataAndMerge()
    {
        $loader = new AnnotationLoader(new AnnotationReader());

        // Load Parent MetaData
        $parent_metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\EntityParent');
        $loader->loadClassMetadata($parent_metadata);

        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');

        // Merge parent metaData.
        $metadata->mergeConstraints($parent_metadata);

        $loader->loadClassMetadata($metadata);

        $expected_parent = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\EntityParent');
        $expected_parent->addPropertyConstraint('other', new NotNull());
        $expected_parent->getReflectionClass();

        $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
        $expected->mergeConstraints($expected_parent);

        $expected->setGroupSequence(array('Foo', 'Entity'));
        $expected->addConstraint(new ConstraintA());
        $expected->addConstraint(new Callback(array('Symfony\Component\Validator\Tests\Fixtures\CallbackClass', 'callback')));
        $expected->addConstraint(new Callback('validateMe'));
        $expected->addConstraint(new Callback('validateMeStatic'));
        $expected->addPropertyConstraint('firstName', new NotNull());
        $expected->addPropertyConstraint('firstName', new Range(array('min' => 3)));
        $expected->addPropertyConstraint('firstName', new All(array(new NotNull(), new Range(array('min' => 3)))));
        $expected->addPropertyConstraint('firstName', new All(array('constraints' => array(new NotNull(), new Range(array('min' => 3))))));
        $expected->addPropertyConstraint('firstName', new Collection(array('fields' => array(
            'foo' => array(new NotNull(), new Range(array('min' => 3))),
            'bar' => new Range(array('min' => 5)),
        ))));
        $expected->addPropertyConstraint('firstName', new Choice(array(
            'message' => 'Must be one of %choices%',
            'choices' => array('A', 'B'),
        )));
        $expected->addGetterConstraint('lastName', new NotNull());

        // load reflection class so that the comparison passes
        $expected->getReflectionClass();

        $this->assertEquals($expected, $metadata);
    }

    public function testLoadGroupSequenceProviderAnnotation()
    {
        $loader = new AnnotationLoader(new AnnotationReader());

        $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity');
        $loader->loadClassMetadata($metadata);

        $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity');
        $expected->setGroupSequenceProvider(true);
        $expected->getReflectionClass();

        $this->assertEquals($expected, $metadata);
    }
}
foo
<?xml version="1.0" ?>

<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">

  <namespace prefix="custom">Symfony\Component\Validator\Tests\Fixtures\</namespace>

  <class name="Symfony\Component\Validator\Tests\Fixtures\Entity">

    <group-sequence>
       <value>Foo</value>
       <value>Entity</value>
    </group-sequence>

    <!-- CLASS CONSTRAINTS -->

    <!-- Custom constraint -->
    <constraint name="Symfony\Component\Validator\Tests\Fixtures\ConstraintA" />

    <!-- Custom constraint with namespace abbreviation-->
    <constraint name="custom:ConstraintB" />

    <!-- Callbacks -->
    <constraint name="Callback">validateMe</constraint>

    <constraint name="Callback">validateMeStatic</constraint>

    <constraint name="Callback">
        <value>Symfony\Component\Validator\Tests\Fixtures\CallbackClass</value>
        <value>callback</value>
    </constraint>

    <!-- PROPERTY CONSTRAINTS -->

    <property name="firstName">

      <!-- Constraint without value -->
      <constraint name="NotNull" />

      <!-- Constraint with single value -->
      <constraint name="Range">
         <option name="min">3</option>
      </constraint>

      <!-- Constraint with multiple values -->
      <constraint name="Choice">
        <value>A</value>
        <value>B</value>
      </constraint>

      <!-- Constraint with child constraints -->
      <constraint name="All">
        <constraint name="NotNull" />
        <constraint name="Range">
           <option name="min">3</option>
        </constraint>

      </constraint>

      <!-- Option with child constraints -->
      <constraint name="All">
        <option name="constraints">
          <constraint name="NotNull" />
          <constraint name="Range">
             <option name="min">3</option>
          </constraint>
        </option>
      </constraint>

      <!-- Value with child constraints -->
      <constraint name="Collection">
        <option name="fields">
          <value key="foo">
            <constraint name="NotNull" />
            <constraint name="Range">
               <option name="min">3</option>
            </constraint>
          </value>
          <value key="bar">
            <constraint name="Range">
               <option name="min">5</option>
            </constraint>
          </value>
        </option>
      </constraint>

      <!-- Constraint with options -->
      <constraint name="Choice">
        <!-- Option with single value -->
        <option name="message"> Must be one of %choices% </option>
        <!-- Option with multiple values -->
        <option name="choices">
          <value>A</value>
          <value>B</value>
        </option>
      </constraint>
    </property>

    <!-- GETTER CONSTRAINTS -->

    <getter property="lastName">
      <constraint name="NotNull" />
    </getter>
  </class>

  <class name="Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity">

    <!-- GROUP SEQUENCE PROVIDER -->
    <group-sequence-provider />

  </class>
</constraint-mapping>
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping\Loader;

use Symfony\Component\Validator\Mapping\Loader\LoaderInterface;
use Symfony\Component\Validator\Mapping\ClassMetadata;

class FilesLoaderTest extends \PHPUnit_Framework_TestCase
{
    public function testCallsGetFileLoaderInstanceForeachPath()
    {
        $loader = $this->getFilesLoader($this->getFileLoader());
        $this->assertEquals(4, $loader->getTimesCalled());
    }

    public function testCallsActualFileLoaderForMetadata()
    {
        $fileLoader = $this->getFileLoader();
        $fileLoader->expects($this->exactly(4))
            ->method('loadClassMetadata');
        $loader = $this->getFilesLoader($fileLoader);
        $loader->loadClassMetadata(new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'));
    }

    public function getFilesLoader(LoaderInterface $loader)
    {
        return $this->getMockForAbstractClass('Symfony\Component\Validator\Tests\Fixtures\FilesLoader', array(array(
            __DIR__.'/constraint-mapping.xml',
            __DIR__.'/constraint-mapping.yaml',
            __DIR__.'/constraint-mapping.test',
            __DIR__.'/constraint-mapping.txt',
        ), $loader));
    }

    public function getFileLoader()
    {
        return $this->getMock('Symfony\Component\Validator\Mapping\Loader\LoaderInterface');
    }
}
<?xml version="1.0"?>
<!DOCTYPE foo>
<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">
  <class name="Symfony\Component\Validator\Tests\Fixtures\Entity" />
</constraint-mapping>
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping;

use Symfony\Component\Validator\Mapping\GetterMetadata;
use Symfony\Component\Validator\Tests\Fixtures\Entity;

class GetterMetadataTest extends \PHPUnit_Framework_TestCase
{
    const CLASSNAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity';

    public function testInvalidPropertyName()
    {
        $this->setExpectedException('Symfony\Component\Validator\Exception\ValidatorException');

        new GetterMetadata(self::CLASSNAME, 'foobar');
    }

    public function testGetPropertyValueFromPublicGetter()
    {
        // private getters don't work yet because ReflectionMethod::setAccessible()
        // does not exist yet in a stable PHP release

        $entity = new Entity('foobar');
        $metadata = new GetterMetadata(self::CLASSNAME, 'internal');

        $this->assertEquals('foobar from getter', $metadata->getPropertyValue($entity));
    }

    public function testGetPropertyValueFromOverriddenPublicGetter()
    {
        $entity = new Entity();
        $metadata = new GetterMetadata(self::CLASSNAME, 'data');

        $this->assertEquals('Overridden data', $metadata->getPropertyValue($entity));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping;

use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintB;
use Symfony\Component\Validator\Tests\Fixtures\ClassConstraint;
use Symfony\Component\Validator\Constraints\Valid;
use Symfony\Component\Validator\Mapping\MemberMetadata;

class MemberMetadataTest extends \PHPUnit_Framework_TestCase
{
    protected $metadata;

    protected function setUp()
    {
        $this->metadata = new TestMemberMetadata(
            'Symfony\Component\Validator\Tests\Fixtures\Entity',
            'getLastName',
            'lastName'
        );
    }

    protected function tearDown()
    {
        $this->metadata = null;
    }

    public function testAddValidSetsMemberToCascaded()
    {
        $result = $this->metadata->addConstraint(new Valid());

        $this->assertEquals(array(), $this->metadata->getConstraints());
        $this->assertEquals($result, $this->metadata);
        $this->assertTrue($this->metadata->isCascaded());
    }

    public function testAddOtherConstraintDoesNotSetMemberToCascaded()
    {
        $result = $this->metadata->addConstraint($constraint = new ConstraintA());

        $this->assertEquals(array($constraint), $this->metadata->getConstraints());
        $this->assertEquals($result, $this->metadata);
        $this->assertFalse($this->metadata->isCascaded());
    }

    public function testAddConstraintRequiresClassConstraints()
    {
        $this->setExpectedException('Symfony\Component\Validator\Exception\ConstraintDefinitionException');

        $this->metadata->addConstraint(new ClassConstraint());
    }

    public function testSerialize()
    {
        $this->metadata->addConstraint(new ConstraintA(array('property1' => 'A')));
        $this->metadata->addConstraint(new ConstraintB(array('groups' => 'TestGroup')));

        $metadata = unserialize(serialize($this->metadata));

        $this->assertEquals($this->metadata, $metadata);
    }

    public function testSerializeCollectionCascaded()
    {
        $this->metadata->addConstraint(new Valid(array('traverse' => true, 'deep' => false)));

        $metadata = unserialize(serialize($this->metadata));

        $this->assertEquals($this->metadata, $metadata);
    }

    public function testSerializeCollectionCascadedDeeply()
    {
        $this->metadata->addConstraint(new Valid(array('traverse' => true, 'deep' => true)));

        $metadata = unserialize(serialize($this->metadata));

        $this->assertEquals($this->metadata, $metadata);
    }

    public function testSerializeCollectionNotCascaded()
    {
        $this->metadata->addConstraint(new Valid(array('traverse' => false)));

        $metadata = unserialize(serialize($this->metadata));

        $this->assertEquals($this->metadata, $metadata);
    }
}

class TestMemberMetadata extends MemberMetadata
{
    public function getPropertyValue($object)
    {
    }

    protected function newReflectionMember($object)
    {
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping;

use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintB;
use Symfony\Component\Validator\Mapping\ElementMetadata;

class ElementMetadataTest extends \PHPUnit_Framework_TestCase
{
    protected $metadata;

    protected function setUp()
    {
        $this->metadata = new TestElementMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity');
    }

    protected function tearDown()
    {
        $this->metadata = null;
    }

    public function testAddConstraints()
    {
        $this->metadata->addConstraint($constraint1 = new ConstraintA());
        $this->metadata->addConstraint($constraint2 = new ConstraintA());

        $this->assertEquals(array($constraint1, $constraint2), $this->metadata->getConstraints());
    }

    public function testMultipleConstraintsOfTheSameType()
    {
        $constraint1 = new ConstraintA(array('property1' => 'A'));
        $constraint2 = new ConstraintA(array('property1' => 'B'));

        $this->metadata->addConstraint($constraint1);
        $this->metadata->addConstraint($constraint2);

        $this->assertEquals(array($constraint1, $constraint2), $this->metadata->getConstraints());
    }

    public function testFindConstraintsByGroup()
    {
        $constraint1 = new ConstraintA(array('groups' => 'TestGroup'));
        $constraint2 = new ConstraintB();

        $this->metadata->addConstraint($constraint1);
        $this->metadata->addConstraint($constraint2);

        $this->assertEquals(array($constraint1), $this->metadata->findConstraints('TestGroup'));
    }

    public function testSerialize()
    {
        $this->metadata->addConstraint(new ConstraintA(array('property1' => 'A')));
        $this->metadata->addConstraint(new ConstraintB(array('groups' => 'TestGroup')));

        $metadata = unserialize(serialize($this->metadata));

        $this->assertEquals($this->metadata, $metadata);
    }
}

class TestElementMetadata extends ElementMetadata {}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests\Mapping;

use Symfony\Component\Validator\Tests\Fixtures\Entity;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
use Symfony\Component\Validator\Mapping\ClassMetadataFactory;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Mapping\Loader\LoaderInterface;

class ClassMetadataFactoryTest extends \PHPUnit_Framework_TestCase
{
    const CLASSNAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity';
    const PARENTCLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParent';

    public function testLoadClassMetadata()
    {
        $factory = new ClassMetadataFactory(new TestLoader());
        $metadata = $factory->getMetadataFor(self::PARENTCLASS);

        $constraints = array(
            new ConstraintA(array('groups' => array('Default', 'EntityParent'))),
        );

        $this->assertEquals($constraints, $metadata->getConstraints());
    }

    public function testMergeParentConstraints()
    {
        $factory = new ClassMetadataFactory(new TestLoader());
        $metadata = $factory->getMetadataFor(self::CLASSNAME);

        $constraints = array(
            new ConstraintA(array('groups' => array(
                'Default',
                'EntityParent',
                'Entity',
            ))),
            new ConstraintA(array('groups' => array(
                'Default',
                'EntityInterface',
                'Entity',
            ))),
            new ConstraintA(array('groups' => array(
                'Default',
                'Entity',
            ))),
        );

        $this->assertEquals($constraints, $metadata->getConstraints());
    }

    public function testWriteMetadataToCache()
    {
        $cache = $this->getMock('Symfony\Component\Validator\Mapping\Cache\CacheInterface');
        $factory = new ClassMetadataFactory(new TestLoader(), $cache);

        $tester = $this;
        $constraints = array(
            new ConstraintA(array('groups' => array('Default', 'EntityParent'))),
        );

        $cache->expects($this->never())
              ->method('has');
        $cache->expects($this->once())
              ->method('read')
              ->with($this->equalTo(self::PARENTCLASS))
              ->will($this->returnValue(false));
        $cache->expects($this->once())
              ->method('write')
              ->will($this->returnCallback(function($metadata) use ($tester, $constraints) {
                  $tester->assertEquals($constraints, $metadata->getConstraints());
              }));

        $metadata = $factory->getMetadataFor(self::PARENTCLASS);

        $this->assertEquals(self::PARENTCLASS, $metadata->getClassName());
        $this->assertEquals($constraints, $metadata->getConstraints());
    }

    public function testReadMetadataFromCache()
    {
        $loader = $this->getMock('Symfony\Component\Validator\Mapping\Loader\LoaderInterface');
        $cache = $this->getMock('Symfony\Component\Validator\Mapping\Cache\CacheInterface');
        $factory = new ClassMetadataFactory($loader, $cache);

        $tester = $this;
        $metadata = new ClassMetadata(self::PARENTCLASS);
        $metadata->addConstraint(new ConstraintA());

        $loader->expects($this->never())
               ->method('loadClassMetadata');

        $cache->expects($this->never())
              ->method('has');
        $cache->expects($this->once())
              ->method('read')
              ->will($this->returnValue($metadata));

        $this->assertEquals($metadata,$factory->getMetadataFor(self::PARENTCLASS));
    }
}

class TestLoader implements LoaderInterface
{
    public function loadClassMetadata(ClassMetadata $metadata)
    {
        $metadata->addConstraint(new ConstraintA());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests;

use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;

class ConstraintViolationListTest extends \PHPUnit_Framework_TestCase
{
    protected $list;

    protected function setUp()
    {
        $this->list = new ConstraintViolationList();
    }

    protected function tearDown()
    {
        $this->list = null;
    }

    public function testInit()
    {
        $this->assertCount(0, $this->list);
    }

    public function testInitWithViolations()
    {
        $violation = $this->getViolation('Error');
        $this->list = new ConstraintViolationList(array($violation));

        $this->assertCount(1, $this->list);
        $this->assertSame($violation, $this->list[0]);
    }

    public function testAdd()
    {
        $violation = $this->getViolation('Error');
        $this->list->add($violation);

        $this->assertCount(1, $this->list);
        $this->assertSame($violation, $this->list[0]);
    }

    public function testAddAll()
    {
        $violations = array(
            10 => $this->getViolation('Error 1'),
            20 => $this->getViolation('Error 2'),
            30 => $this->getViolation('Error 3'),
        );
        $otherList = new ConstraintViolationList($violations);
        $this->list->addAll($otherList);

        $this->assertCount(3, $this->list);

        $this->assertSame($violations[10], $this->list[0]);
        $this->assertSame($violations[20], $this->list[1]);
        $this->assertSame($violations[30], $this->list[2]);
    }

    public function testIterator()
    {
        $violations = array(
            10 => $this->getViolation('Error 1'),
            20 => $this->getViolation('Error 2'),
            30 => $this->getViolation('Error 3'),
        );

        $this->list = new ConstraintViolationList($violations);

        // indices are reset upon adding -> array_values()
        $this->assertSame(array_values($violations), iterator_to_array($this->list));
    }

    public function testArrayAccess()
    {
        $violation = $this->getViolation('Error');
        $this->list[] = $violation;

        $this->assertSame($violation, $this->list[0]);
        $this->assertTrue(isset($this->list[0]));

        unset($this->list[0]);

        $this->assertFalse(isset($this->list[0]));

        $this->list[10] = $violation;

        $this->assertSame($violation, $this->list[10]);
        $this->assertTrue(isset($this->list[10]));
    }

    public function testToString()
    {
        $this->list = new ConstraintViolationList(array(
            $this->getViolation('Error 1', 'Root'),
            $this->getViolation('Error 2', 'Root', 'foo.bar'),
            $this->getViolation('Error 3', 'Root', '[baz]'),
            $this->getViolation('Error 4', '', 'foo.bar'),
            $this->getViolation('Error 5', '', '[baz]'),
        ));

        $expected = <<<EOF
Root:
    Error 1
Root.foo.bar:
    Error 2
Root[baz]:
    Error 3
foo.bar:
    Error 4
[baz]:
    Error 5

EOF;

        $this->assertEquals($expected, (string) $this->list);
    }

    protected function getViolation($message, $root = null, $propertyPath = null)
    {
        return new ConstraintViolation($message, $message, array(), $root, $propertyPath, null);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests;

use Symfony\Component\Validator\Tests\Fixtures\ClassConstraint;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintB;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintC;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintWithValue;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintWithValueAsDefault;

class ConstraintTest extends \PHPUnit_Framework_TestCase
{
    public function testSetProperties()
    {
        $constraint = new ConstraintA(array(
            'property1' => 'foo',
            'property2' => 'bar',
        ));

        $this->assertEquals('foo', $constraint->property1);
        $this->assertEquals('bar', $constraint->property2);
    }

    public function testSetNotExistingPropertyThrowsException()
    {
        $this->setExpectedException('Symfony\Component\Validator\Exception\InvalidOptionsException');

        new ConstraintA(array(
            'foo' => 'bar',
        ));
    }

    public function testMagicPropertiesAreNotAllowed()
    {
        $constraint = new ConstraintA();

        $this->setExpectedException('Symfony\Component\Validator\Exception\InvalidOptionsException');

        $constraint->foo = 'bar';
    }

    public function testInvalidAndRequiredOptionsPassed()
    {
        $this->setExpectedException('Symfony\Component\Validator\Exception\InvalidOptionsException');

        new ConstraintC(array(
            'option1' => 'default',
            'foo' => 'bar'
        ));
    }

    public function testSetDefaultProperty()
    {
        $constraint = new ConstraintA('foo');

        $this->assertEquals('foo', $constraint->property2);
    }

    public function testSetDefaultPropertyDoctrineStyle()
    {
        $constraint = new ConstraintA(array('value' => 'foo'));

        $this->assertEquals('foo', $constraint->property2);
    }

    public function testSetDefaultPropertyDoctrineStylePlusOtherProperty()
    {
        $constraint = new ConstraintA(array('value' => 'foo', 'property1' => 'bar'));

        $this->assertEquals('foo', $constraint->property2);
        $this->assertEquals('bar', $constraint->property1);
    }

    public function testSetDefaultPropertyDoctrineStyleWhenDefaultPropertyIsNamedValue()
    {
        $constraint = new ConstraintWithValueAsDefault(array('value' => 'foo'));

        $this->assertEquals('foo', $constraint->value);
        $this->assertNull($constraint->property);
    }

    public function testDontSetDefaultPropertyIfValuePropertyExists()
    {
        $constraint = new ConstraintWithValue(array('value' => 'foo'));

        $this->assertEquals('foo', $constraint->value);
        $this->assertNull($constraint->property);
    }

    public function testSetUndefinedDefaultProperty()
    {
        $this->setExpectedException('Symfony\Component\Validator\Exception\ConstraintDefinitionException');

        new ConstraintB('foo');
    }

    public function testRequiredOptionsMustBeDefined()
    {
        $this->setExpectedException('Symfony\Component\Validator\Exception\MissingOptionsException');

        new ConstraintC();
    }

    public function testRequiredOptionsPassed()
    {
        new ConstraintC(array('option1' => 'default'));
    }

    public function testGroupsAreConvertedToArray()
    {
        $constraint = new ConstraintA(array('groups' => 'Foo'));

        $this->assertEquals(array('Foo'), $constraint->groups);
    }

    public function testAddDefaultGroupAddsGroup()
    {
        $constraint = new ConstraintA(array('groups' => 'Default'));
        $constraint->addImplicitGroupName('Foo');
        $this->assertEquals(array('Default', 'Foo'), $constraint->groups);
    }

    public function testAllowsSettingZeroRequiredPropertyValue()
    {
        $constraint = new ConstraintA(0);
        $this->assertEquals(0, $constraint->property2);
    }

    public function testCanCreateConstraintWithNoDefaultOptionAndEmptyArray()
    {
        new ConstraintB(array());
    }

    public function testGetTargetsCanBeString()
    {
        $constraint = new ClassConstraint();

        $this->assertEquals('class', $constraint->getTargets());
    }

    public function testGetTargetsCanBeArray()
    {
        $constraint = new ConstraintA();

        $this->assertEquals(array('property', 'class'), $constraint->getTargets());
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests;

use Symfony\Component\Validator\Tests\Fixtures\Entity;
use Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity;
use Symfony\Component\Validator\Tests\Fixtures\FakeMetadataFactory;
use Symfony\Component\Validator\Tests\Fixtures\FailingConstraint;
use Symfony\Component\Validator\Validator;
use Symfony\Component\Validator\DefaultTranslator;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\ConstraintValidatorFactory;
use Symfony\Component\Validator\Constraints\Valid;
use Symfony\Component\Validator\Mapping\ClassMetadata;

class ValidatorTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var FakeMetadataFactory
     */
    private $metadataFactory;

    /**
     * @var Validator
     */
    private $validator;

    protected function setUp()
    {
        $this->metadataFactory = new FakeMetadataFactory();
        $this->validator = new Validator($this->metadataFactory, new ConstraintValidatorFactory(), new DefaultTranslator());
    }

    protected function tearDown()
    {
        $this->metadataFactory = null;
        $this->validator = null;
    }

    public function testValidateDefaultGroup()
    {
        $entity = new Entity();
        $metadata = new ClassMetadata(get_class($entity));
        $metadata->addPropertyConstraint('firstName', new FailingConstraint());
        $metadata->addPropertyConstraint('lastName', new FailingConstraint(array(
            'groups' => 'Custom',
        )));
        $this->metadataFactory->addMetadata($metadata);

        // Only the constraint of group "Default" failed
        $violations = new ConstraintViolationList();
        $violations->add(new ConstraintViolation(
            'Failed',
            'Failed',
            array(),
            $entity,
            'firstName',
            ''
        ));

        $this->assertEquals($violations, $this->validator->validate($entity));
    }

    public function testValidateOneGroup()
    {
        $entity = new Entity();
        $metadata = new ClassMetadata(get_class($entity));
        $metadata->addPropertyConstraint('firstName', new FailingConstraint());
        $metadata->addPropertyConstraint('lastName', new FailingConstraint(array(
            'groups' => 'Custom',
        )));
        $this->metadataFactory->addMetadata($metadata);

        // Only the constraint of group "Custom" failed
        $violations = new ConstraintViolationList();
        $violations->add(new ConstraintViolation(
            'Failed',
            'Failed',
            array(),
            $entity,
            'lastName',
            ''
        ));

        $this->assertEquals($violations, $this->validator->validate($entity, 'Custom'));
    }

    public function testValidateMultipleGroups()
    {
        $entity = new Entity();
        $metadata = new ClassMetadata(get_class($entity));
        $metadata->addPropertyConstraint('firstName', new FailingConstraint(array(
            'groups' => 'First',
        )));
        $metadata->addPropertyConstraint('lastName', new FailingConstraint(array(
            'groups' => 'Second',
        )));
        $this->metadataFactory->addMetadata($metadata);

        // The constraints of both groups failed
        $violations = new ConstraintViolationList();
        $violations->add(new ConstraintViolation(
            'Failed',
            'Failed',
            array(),
            $entity,
            'firstName',
            ''
        ));
        $violations->add(new ConstraintViolation(
            'Failed',
            'Failed',
            array(),
            $entity,
            'lastName',
            ''
        ));

        $result = $this->validator->validate($entity, array('First', 'Second'));

        $this->assertEquals($violations, $result);
    }

    public function testValidateGroupSequenceProvider()
    {
        $entity = new GroupSequenceProviderEntity();
        $metadata = new ClassMetadata(get_class($entity));
        $metadata->addPropertyConstraint('firstName', new FailingConstraint(array(
            'groups' => 'First',
        )));
        $metadata->addPropertyConstraint('lastName', new FailingConstraint(array(
            'groups' => 'Second',
        )));
        $metadata->setGroupSequenceProvider(true);
        $this->metadataFactory->addMetadata($metadata);

        $violations = new ConstraintViolationList();
        $violations->add(new ConstraintViolation(
            'Failed',
            'Failed',
            array(),
            $entity,
            'firstName',
            ''
        ));

        $entity->setGroups(array('First'));
        $result = $this->validator->validate($entity);
        $this->assertEquals($violations, $result);

        $violations = new ConstraintViolationList();
        $violations->add(new ConstraintViolation(
            'Failed',
            'Failed',
            array(),
            $entity,
            'lastName',
            ''
        ));

        $entity->setGroups(array('Second'));
        $result = $this->validator->validate($entity);
        $this->assertEquals($violations, $result);

        $entity->setGroups(array());
        $result = $this->validator->validate($entity);
        $this->assertEquals(new ConstraintViolationList(), $result);
    }

    public function testValidateProperty()
    {
        $entity = new Entity();
        $metadata = new ClassMetadata(get_class($entity));
        $metadata->addPropertyConstraint('firstName', new FailingConstraint());
        $this->metadataFactory->addMetadata($metadata);

        $result = $this->validator->validateProperty($entity, 'firstName');

        $this->assertCount(1, $result);

        $result = $this->validator->validateProperty($entity, 'lastName');

        $this->assertCount(0, $result);
    }

    public function testValidatePropertyValue()
    {
        $entity = new Entity();
        $metadata = new ClassMetadata(get_class($entity));
        $metadata->addPropertyConstraint('firstName', new FailingConstraint());
        $this->metadataFactory->addMetadata($metadata);

        $result = $this->validator->validatePropertyValue(get_class($entity), 'firstName', 'Bernhard');

        $this->assertCount(1, $result);
    }

    public function testValidateValue()
    {
        $violations = new ConstraintViolationList();
        $violations->add(new ConstraintViolation(
            'Failed',
            'Failed',
            array(),
            'Bernhard',
            '',
            'Bernhard'
        ));

        $this->assertEquals($violations, $this->validator->validateValue('Bernhard', new FailingConstraint()));
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ValidatorException
     */
    public function testValidateValueRejectsValid()
    {
        $entity = new Entity();
        $metadata = new ClassMetadata(get_class($entity));
        $this->metadataFactory->addMetadata($metadata);

        $this->validator->validateValue($entity, new Valid());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ValidatorException
     */
    public function testValidatePropertyFailsIfPropertiesNotSupported()
    {
        // $metadata does not implement PropertyMetadataContainerInterface
        $metadata = $this->getMock('Symfony\Component\Validator\MetadataInterface');
        $this->metadataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface');
        $this->metadataFactory->expects($this->any())
            ->method('getMetadataFor')
            ->with('VALUE')
            ->will($this->returnValue($metadata));
        $this->validator = new Validator($this->metadataFactory, new ConstraintValidatorFactory(), new DefaultTranslator());

        $this->validator->validateProperty('VALUE', 'someProperty');
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\ValidatorException
     */
    public function testValidatePropertyValueFailsIfPropertiesNotSupported()
    {
        // $metadata does not implement PropertyMetadataContainerInterface
        $metadata = $this->getMock('Symfony\Component\Validator\MetadataInterface');
        $this->metadataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface');
        $this->metadataFactory->expects($this->any())
            ->method('getMetadataFor')
            ->with('VALUE')
            ->will($this->returnValue($metadata));
        $this->validator = new Validator($this->metadataFactory, new ConstraintValidatorFactory(), new DefaultTranslator());

        $this->validator->validatePropertyValue('VALUE', 'someProperty', 'propertyValue');
    }

    public function testGetMetadataFactory()
    {
        $this->assertInstanceOf(
            'Symfony\Component\Validator\MetadataFactoryInterface',
            $this->validator->getMetadataFactory()
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests;

use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\ExecutionContext;
use Symfony\Component\Validator\Constraints\Collection;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
use Symfony\Component\Validator\ValidationVisitor;
use Symfony\Component\Validator\ConstraintValidatorFactory;

class ExecutionContextTest extends \PHPUnit_Framework_TestCase
{
    const TRANS_DOMAIN = 'trans_domain';

    private $visitor;
    private $violations;
    private $metadata;
    private $metadataFactory;
    private $globalContext;
    private $translator;

    /**
     * @var ExecutionContext
     */
    private $context;

    protected function setUp()
    {
        $this->visitor = $this->getMockBuilder('Symfony\Component\Validator\ValidationVisitor')
            ->disableOriginalConstructor()
            ->getMock();
        $this->violations = new ConstraintViolationList();
        $this->metadata = $this->getMock('Symfony\Component\Validator\MetadataInterface');
        $this->metadataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface');
        $this->globalContext = $this->getMock('Symfony\Component\Validator\GlobalExecutionContextInterface');
        $this->globalContext->expects($this->any())
            ->method('getRoot')
            ->will($this->returnValue('Root'));
        $this->globalContext->expects($this->any())
            ->method('getViolations')
            ->will($this->returnValue($this->violations));
        $this->globalContext->expects($this->any())
            ->method('getVisitor')
            ->will($this->returnValue($this->visitor));
        $this->globalContext->expects($this->any())
            ->method('getMetadataFactory')
            ->will($this->returnValue($this->metadataFactory));
        $this->translator = $this->getMock('Symfony\Component\Translation\TranslatorInterface');
        $this->context = new ExecutionContext($this->globalContext, $this->translator, self::TRANS_DOMAIN, $this->metadata, 'currentValue', 'Group', 'foo.bar');
    }

    protected function tearDown()
    {
        $this->globalContext = null;
        $this->context = null;
    }

    public function testInit()
    {
        $this->assertCount(0, $this->context->getViolations());
        $this->assertSame('Root', $this->context->getRoot());
        $this->assertSame('foo.bar', $this->context->getPropertyPath());
        $this->assertSame('Group', $this->context->getGroup());
    }

    public function testClone()
    {
        $clone = clone $this->context;

        // Cloning the context keeps the reference to the original violation
        // list. This way we can efficiently duplicate context instances during
        // the validation run and only modify the properties that need to be
        // changed.
        $this->assertSame($this->context->getViolations(), $clone->getViolations());
    }

    public function testAddViolation()
    {
        $this->translator->expects($this->once())
            ->method('trans')
            ->with('Error', array('foo' => 'bar'))
            ->will($this->returnValue('Translated error'));

        $this->context->addViolation('Error', array('foo' => 'bar'), 'invalid');

        $this->assertEquals(new ConstraintViolationList(array(
            new ConstraintViolation(
                'Translated error',
                'Error',
                array('foo' => 'bar'),
                'Root',
                'foo.bar',
                'invalid'
            ),
        )), $this->context->getViolations());
    }

    public function testAddViolationUsesPreconfiguredValueIfNotPassed()
    {
        $this->translator->expects($this->once())
            ->method('trans')
            ->with('Error', array())
            ->will($this->returnValue('Translated error'));

        $this->context->addViolation('Error');

        $this->assertEquals(new ConstraintViolationList(array(
            new ConstraintViolation(
                'Translated error',
                'Error',
                array(),
                'Root',
                'foo.bar',
                'currentValue'
            ),
        )), $this->context->getViolations());
    }

    public function testAddViolationUsesPassedNullValue()
    {
        $this->translator->expects($this->once())
            ->method('trans')
            ->with('Error', array('foo1' => 'bar1'))
            ->will($this->returnValue('Translated error'));
        $this->translator->expects($this->once())
            ->method('transChoice')
            ->with('Choice error', 1, array('foo2' => 'bar2'))
            ->will($this->returnValue('Translated choice error'));

        // passed null value should override preconfigured value "invalid"
        $this->context->addViolation('Error', array('foo1' => 'bar1'), null);
        $this->context->addViolation('Choice error', array('foo2' => 'bar2'), null, 1);

        $this->assertEquals(new ConstraintViolationList(array(
            new ConstraintViolation(
                'Translated error',
                'Error',
                array('foo1' => 'bar1'),
                'Root',
                'foo.bar',
                null
            ),
            new ConstraintViolation(
                'Translated choice error',
                'Choice error',
                array('foo2' => 'bar2'),
                'Root',
                'foo.bar',
                null,
                1
            ),
        )), $this->context->getViolations());
    }

    public function testAddViolationAt()
    {
        $this->translator->expects($this->once())
            ->method('trans')
            ->with('Error', array('foo' => 'bar'))
            ->will($this->returnValue('Translated error'));

        // override preconfigured property path
        $this->context->addViolationAt('bam.baz', 'Error', array('foo' => 'bar'), 'invalid');

        $this->assertEquals(new ConstraintViolationList(array(
            new ConstraintViolation(
                'Translated error',
                'Error',
                array('foo' => 'bar'),
                'Root',
                'foo.bar.bam.baz',
                'invalid'
            ),
        )), $this->context->getViolations());
    }

    public function testAddViolationAtUsesPreconfiguredValueIfNotPassed()
    {
        $this->translator->expects($this->once())
            ->method('trans')
            ->with('Error', array())
            ->will($this->returnValue('Translated error'));

        $this->context->addViolationAt('bam.baz', 'Error');

        $this->assertEquals(new ConstraintViolationList(array(
            new ConstraintViolation(
                'Translated error',
                'Error',
                array(),
                'Root',
                'foo.bar.bam.baz',
                'currentValue'
            ),
        )), $this->context->getViolations());
    }

    public function testAddViolationAtUsesPassedNullValue()
    {
        $this->translator->expects($this->once())
            ->method('trans')
            ->with('Error', array('foo' => 'bar'))
            ->will($this->returnValue('Translated error'));
        $this->translator->expects($this->once())
            ->method('transChoice')
            ->with('Choice error', 2, array('foo' => 'bar'))
            ->will($this->returnValue('Translated choice error'));

        // passed null value should override preconfigured value "invalid"
        $this->context->addViolationAt('bam.baz', 'Error', array('foo' => 'bar'), null);
        $this->context->addViolationAt('bam.baz', 'Choice error', array('foo' => 'bar'), null, 2);

        $this->assertEquals(new ConstraintViolationList(array(
            new ConstraintViolation(
                'Translated error',
                'Error',
                array('foo' => 'bar'),
                'Root',
                'foo.bar.bam.baz',
                null
            ),
            new ConstraintViolation(
                'Translated choice error',
                'Choice error',
                array('foo' => 'bar'),
                'Root',
                'foo.bar.bam.baz',
                null,
                2
            ),
        )), $this->context->getViolations());
    }

    public function testAddViolationPluralTranslationError()
    {
        $this->translator->expects($this->once())
            ->method('transChoice')
            ->with('foo')
            ->will($this->throwException(new \InvalidArgumentException()));
        $this->translator->expects($this->once())
            ->method('trans')
            ->with('foo');

        $this->context->addViolation('foo', array(), null, 2);
    }

    public function testGetPropertyPath()
    {
        $this->assertEquals('foo.bar', $this->context->getPropertyPath());
    }

    public function testGetPropertyPathWithIndexPath()
    {
        $this->assertEquals('foo.bar[bam]', $this->context->getPropertyPath('[bam]'));
    }

    public function testGetPropertyPathWithEmptyPath()
    {
        $this->assertEquals('foo.bar', $this->context->getPropertyPath(''));
    }

    public function testGetPropertyPathWithEmptyCurrentPropertyPath()
    {
        $this->context = new ExecutionContext($this->globalContext, $this->translator, self::TRANS_DOMAIN, $this->metadata, 'currentValue', 'Group', '');

        $this->assertEquals('bam.baz', $this->context->getPropertyPath('bam.baz'));
    }

    public function testGetPropertyPathWithNestedCollectionsMixed()
    {
        $constraints = new Collection(array(
            'foo' => new Collection(array(
                'foo' => new ConstraintA(),
                'bar' => new ConstraintA(),
             )),
            'name' => new ConstraintA()
        ));

        $visitor = new ValidationVisitor('Root', $this->metadataFactory, new ConstraintValidatorFactory(), $this->translator);
        $context = new ExecutionContext($visitor, $this->translator, self::TRANS_DOMAIN);
        $context->validateValue(array('foo' => array('foo' => 'VALID')), $constraints);
        $violations = $context->getViolations();

        $this->assertEquals('[name]', $violations[1]->getPropertyPath());
    }
}

class ExecutionContextTest_TestClass
{
    public $myProperty;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests;

use Symfony\Component\Validator\ValidatorBuilder;
use Symfony\Component\Validator\ValidatorBuilderInterface;

class ValidatorBuilderTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var ValidatorBuilderInterface
     */
    protected $builder;

    protected function setUp()
    {
        $this->builder = new ValidatorBuilder();
    }

    protected function tearDown()
    {
        $this->builder = null;
    }

    public function testAddObjectInitializer()
    {
        $this->assertSame($this->builder, $this->builder->addObjectInitializer(
            $this->getMock('Symfony\Component\Validator\ObjectInitializerInterface')
        ));
    }

    public function testAddObjectInitializers()
    {
        $this->assertSame($this->builder, $this->builder->addObjectInitializers(array()));
    }

    public function testAddXmlMapping()
    {
        $this->assertSame($this->builder, $this->builder->addXmlMapping('mapping'));
    }

    public function testAddXmlMappings()
    {
        $this->assertSame($this->builder, $this->builder->addXmlMappings(array()));
    }

    public function testAddYamlMapping()
    {
        $this->assertSame($this->builder, $this->builder->addYamlMapping('mapping'));
    }

    public function testAddYamlMappings()
    {
        $this->assertSame($this->builder, $this->builder->addYamlMappings(array()));
    }

    public function testAddMethodMapping()
    {
        $this->assertSame($this->builder, $this->builder->addMethodMapping('mapping'));
    }

    public function testAddMethodMappings()
    {
        $this->assertSame($this->builder, $this->builder->addMethodMappings(array()));
    }

    public function testEnableAnnotationMapping()
    {
        $this->assertSame($this->builder, $this->builder->enableAnnotationMapping());
    }

    public function testDisableAnnotationMapping()
    {
        $this->assertSame($this->builder, $this->builder->disableAnnotationMapping());
    }

    public function testSetMetadataCache()
    {
        $this->assertSame($this->builder, $this->builder->setMetadataCache(
            $this->getMock('Symfony\Component\Validator\Mapping\Cache\CacheInterface'))
        );
    }

    public function testSetConstraintValidatorFactory()
    {
        $this->assertSame($this->builder, $this->builder->setConstraintValidatorFactory(
            $this->getMock('Symfony\Component\Validator\ConstraintValidatorFactoryInterface'))
        );
    }

    public function testSetTranslator()
    {
        $this->assertSame($this->builder, $this->builder->setTranslator(
            $this->getMock('Symfony\Component\Translation\TranslatorInterface'))
        );
    }

    public function testSetTranslationDomain()
    {
        $this->assertSame($this->builder, $this->builder->setTranslationDomain('TRANS_DOMAIN'));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests;

use Symfony\Component\Validator\ConstraintViolation;

class ConstraintViolationTest extends \PHPUnit_Framework_TestCase
{
    public function testToStringHandlesArrays()
    {
        $violation = new ConstraintViolation(
            'Array',
            '{{ value }}',
            array('{{ value }}' => array(1, 2, 3)),
            'Root',
            'property.path',
            null
        );

        $expected = <<<EOF
Root.property.path:
    Array
EOF;

        $this->assertSame($expected, (string) $violation);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator\Tests;

use Symfony\Component\Validator\Tests\Fixtures\FakeMetadataFactory;
use Symfony\Component\Validator\Constraints\Valid;
use Symfony\Component\Validator\Tests\Fixtures\Reference;
use Symfony\Component\Validator\DefaultTranslator;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\Tests\Fixtures\FailingConstraint;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintAValidator;
use Symfony\Component\Validator\Tests\Fixtures\Entity;
use Symfony\Component\Validator\Tests\Fixtures\ConstraintA;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\ConstraintValidatorFactory;
use Symfony\Component\Validator\ValidationVisitor;

/**
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ValidationVisitorTest extends \PHPUnit_Framework_TestCase
{
    const CLASS_NAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity';

    /**
     * @var ValidationVisitor
     */
    private $visitor;

    /**
     * @var FakeMetadataFactory
     */
    private $metadataFactory;

    /**
     * @var ClassMetadata
     */
    private $metadata;

    protected function setUp()
    {
        $this->metadataFactory = new FakeMetadataFactory();
        $this->visitor = new ValidationVisitor('Root', $this->metadataFactory, new ConstraintValidatorFactory(), new DefaultTranslator());
        $this->metadata = new ClassMetadata(self::CLASS_NAME);
        $this->metadataFactory->addMetadata($this->metadata);
    }

    protected function tearDown()
    {
        $this->metadataFactory = null;
        $this->visitor = null;
        $this->metadata = null;
    }

    public function testValidatePassesCorrectClassAndProperty()
    {
        $this->metadata->addConstraint(new ConstraintA());

        $entity = new Entity();
        $this->visitor->validate($entity, 'Default', '');

        $context = ConstraintAValidator::$passedContext;

        $this->assertEquals('Symfony\Component\Validator\Tests\Fixtures\Entity', $context->getClassName());
        $this->assertNull($context->getPropertyName());
    }

    public function testValidateConstraints()
    {
        $this->metadata->addConstraint(new ConstraintA());

        $this->visitor->validate(new Entity(), 'Default', '');

        $this->assertCount(1, $this->visitor->getViolations());
    }

    public function testValidateTwiceValidatesConstraintsOnce()
    {
        $this->metadata->addConstraint(new ConstraintA());

        $entity = new Entity();

        $this->visitor->validate($entity, 'Default', '');
        $this->visitor->validate($entity, 'Default', '');

        $this->assertCount(1, $this->visitor->getViolations());
    }

    public function testValidateDifferentObjectsValidatesTwice()
    {
        $this->metadata->addConstraint(new ConstraintA());

        $this->visitor->validate(new Entity(), 'Default', '');
        $this->visitor->validate(new Entity(), 'Default', '');

        $this->assertCount(2, $this->visitor->getViolations());
    }

    public function testValidateTwiceInDifferentGroupsValidatesTwice()
    {
        $this->metadata->addConstraint(new ConstraintA());
        $this->metadata->addConstraint(new ConstraintA(array('groups' => 'Custom')));

        $entity = new Entity();

        $this->visitor->validate($entity, 'Default', '');
        $this->visitor->validate($entity, 'Custom', '');

        $this->assertCount(2, $this->visitor->getViolations());
    }

    public function testValidatePropertyConstraints()
    {
        $this->metadata->addPropertyConstraint('firstName', new ConstraintA());

        $this->visitor->validate(new Entity(), 'Default', '');

        $this->assertCount(1, $this->visitor->getViolations());
    }

    public function testValidateGetterConstraints()
    {
        $this->metadata->addGetterConstraint('lastName', new ConstraintA());

        $this->visitor->validate(new Entity(), 'Default', '');

        $this->assertCount(1, $this->visitor->getViolations());
    }

    public function testValidateInDefaultGroupTraversesGroupSequence()
    {
        $entity = new Entity();

        $this->metadata->addPropertyConstraint('firstName', new FailingConstraint(array(
            'groups' => 'First',
        )));
        $this->metadata->addGetterConstraint('lastName', new FailingConstraint(array(
            'groups' => 'Default',
        )));
        $this->metadata->setGroupSequence(array('First', $this->metadata->getDefaultGroup()));

        $this->visitor->validate($entity, 'Default', '');

        // After validation of group "First" failed, no more group was
        // validated
        $violations = new ConstraintViolationList(array(
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                'firstName',
                ''
            ),
        ));

        $this->assertEquals($violations, $this->visitor->getViolations());
    }

    public function testValidateInGroupSequencePropagatesDefaultGroup()
    {
        $entity = new Entity();
        $entity->reference = new Reference();

        $this->metadata->addPropertyConstraint('reference', new Valid());
        $this->metadata->setGroupSequence(array($this->metadata->getDefaultGroup()));

        $referenceMetadata = new ClassMetadata(get_class($entity->reference));
        $referenceMetadata->addConstraint(new FailingConstraint(array(
                // this constraint is only evaluated if group "Default" is
                // propagated to the reference
                'groups' => 'Default',
            )));
        $this->metadataFactory->addMetadata($referenceMetadata);

        $this->visitor->validate($entity, 'Default', '');

        // The validation of the reference's FailingConstraint in group
        // "Default" was launched
        $violations = new ConstraintViolationList(array(
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                'reference',
                $entity->reference
            ),
        ));

        $this->assertEquals($violations, $this->visitor->getViolations());
    }

    public function testValidateInOtherGroupTraversesNoGroupSequence()
    {
        $entity = new Entity();

        $this->metadata->addPropertyConstraint('firstName', new FailingConstraint(array(
            'groups' => 'First',
        )));
        $this->metadata->addGetterConstraint('lastName', new FailingConstraint(array(
            'groups' => $this->metadata->getDefaultGroup(),
        )));
        $this->metadata->setGroupSequence(array('First', $this->metadata->getDefaultGroup()));

        $this->visitor->validate($entity, $this->metadata->getDefaultGroup(), '');

        // Only group "Second" was validated
        $violations = new ConstraintViolationList(array(
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                'lastName',
                ''
            ),
        ));

        $this->assertEquals($violations, $this->visitor->getViolations());
    }

    public function testValidateCascadedPropertyValidatesReferences()
    {
        $entity = new Entity();
        $entity->reference = new Entity();

        // add a constraint for the entity that always fails
        $this->metadata->addConstraint(new FailingConstraint());

        // validate entity when validating the property "reference"
        $this->metadata->addPropertyConstraint('reference', new Valid());

        // invoke validation on an object
        $this->visitor->validate($entity, 'Default', '');

        $violations = new ConstraintViolationList(array(
            // generated by the root object
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                '',
                $entity
            ),
            // generated by the reference
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                'reference',
                $entity->reference
            ),
        ));

        $this->assertEquals($violations, $this->visitor->getViolations());
    }

    public function testValidateCascadedPropertyValidatesArraysByDefault()
    {
        $entity = new Entity();
        $entity->reference = array('key' => new Entity());

        // add a constraint for the entity that always fails
        $this->metadata->addConstraint(new FailingConstraint());

        // validate array when validating the property "reference"
        $this->metadata->addPropertyConstraint('reference', new Valid());

        $this->visitor->validate($entity, 'Default', '');

        $violations = new ConstraintViolationList(array(
            // generated by the root object
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                '',
                $entity
            ),
            // generated by the reference
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                'reference[key]',
                $entity->reference['key']
            ),
        ));

        $this->assertEquals($violations, $this->visitor->getViolations());
    }

    public function testValidateCascadedPropertyValidatesTraversableByDefault()
    {
        $entity = new Entity();
        $entity->reference = new \ArrayIterator(array('key' => new Entity()));

        // add a constraint for the entity that always fails
        $this->metadata->addConstraint(new FailingConstraint());

        // validate array when validating the property "reference"
        $this->metadata->addPropertyConstraint('reference', new Valid());

        $this->visitor->validate($entity, 'Default', '');

        $violations = new ConstraintViolationList(array(
            // generated by the root object
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                '',
                $entity
            ),
            // generated by the reference
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                'reference[key]',
                $entity->reference['key']
            ),
        ));

        $this->assertEquals($violations, $this->visitor->getViolations());
    }

    public function testValidateCascadedPropertyDoesNotValidateTraversableIfDisabled()
    {
        $entity = new Entity();
        $entity->reference = new \ArrayIterator(array('key' => new Entity()));

        $this->metadataFactory->addMetadata(new ClassMetadata('ArrayIterator'));

        // add a constraint for the entity that always fails
        $this->metadata->addConstraint(new FailingConstraint());

        // validate array when validating the property "reference"
        $this->metadata->addPropertyConstraint('reference', new Valid(array(
            'traverse' => false,
        )));

        $this->visitor->validate($entity, 'Default', '');

        $violations = new ConstraintViolationList(array(
            // generated by the root object
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                '',
                $entity
            ),
            // nothing generated by the reference!
        ));

        $this->assertEquals($violations, $this->visitor->getViolations());
    }

    public function testMetadataMayNotExistIfTraversalIsEnabled()
    {
        $entity = new Entity();
        $entity->reference = new \ArrayIterator();

        $this->metadata->addPropertyConstraint('reference', new Valid(array(
            'traverse' => true,
        )));

        $this->visitor->validate($entity, 'Default', '');
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\NoSuchMetadataException
     */
    public function testMetadataMustExistIfTraversalIsDisabled()
    {
        $entity = new Entity();
        $entity->reference = new \ArrayIterator();

        $this->metadata->addPropertyConstraint('reference', new Valid(array(
            'traverse' => false,
        )));

        $this->visitor->validate($entity, 'Default', '');
    }

    public function testValidateCascadedPropertyDoesNotRecurseByDefault()
    {
        $entity = new Entity();
        $entity->reference = new \ArrayIterator(array(
            // The inner iterator should not be traversed by default
            'key' => new \ArrayIterator(array(
                'nested' => new Entity(),
            )),
        ));

        $this->metadataFactory->addMetadata(new ClassMetadata('ArrayIterator'));

        // add a constraint for the entity that always fails
        $this->metadata->addConstraint(new FailingConstraint());

        // validate iterator when validating the property "reference"
        $this->metadata->addPropertyConstraint('reference', new Valid());

        $this->visitor->validate($entity, 'Default', '');

        $violations = new ConstraintViolationList(array(
            // generated by the root object
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                '',
                $entity
            ),
            // nothing generated by the reference!
        ));

        $this->assertEquals($violations, $this->visitor->getViolations());
    }

    // https://github.com/symfony/symfony/issues/6246
    public function testValidateCascadedPropertyRecursesArraysByDefault()
    {
        $entity = new Entity();
        $entity->reference = array(
            'key' => array(
                'nested' => new Entity(),
            ),
        );

        // add a constraint for the entity that always fails
        $this->metadata->addConstraint(new FailingConstraint());

        // validate iterator when validating the property "reference"
        $this->metadata->addPropertyConstraint('reference', new Valid());

        $this->visitor->validate($entity, 'Default', '');

        $violations = new ConstraintViolationList(array(
            // generated by the root object
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                '',
                $entity
            ),
            // nothing generated by the reference!
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                'reference[key][nested]',
                $entity->reference['key']['nested']
            ),
        ));

        $this->assertEquals($violations, $this->visitor->getViolations());
    }

    public function testValidateCascadedPropertyRecursesIfDeepIsSet()
    {
        $entity = new Entity();
        $entity->reference = new \ArrayIterator(array(
            // The inner iterator should now be traversed
            'key' => new \ArrayIterator(array(
                'nested' => new Entity(),
            )),
        ));

        // add a constraint for the entity that always fails
        $this->metadata->addConstraint(new FailingConstraint());

        // validate iterator when validating the property "reference"
        $this->metadata->addPropertyConstraint('reference', new Valid(array(
            'deep' => true,
        )));

        $this->visitor->validate($entity, 'Default', '');

        $violations = new ConstraintViolationList(array(
            // generated by the root object
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                '',
                $entity
            ),
            // nothing generated by the reference!
            new ConstraintViolation(
                'Failed',
                'Failed',
                array(),
                'Root',
                'reference[key][nested]',
                $entity->reference['key']['nested']
            ),
        ));

        $this->assertEquals($violations, $this->visitor->getViolations());
    }

    public function testValidateCascadedPropertyDoesNotValidateNestedScalarValues()
    {
        $entity = new Entity();
        $entity->reference = array('scalar', 'values');

        // validate array when validating the property "reference"
        $this->metadata->addPropertyConstraint('reference', new Valid());

        $this->visitor->validate($entity, 'Default', '');

        $this->assertCount(0, $this->visitor->getViolations());
    }

    public function testValidateCascadedPropertyDoesNotValidateNullValues()
    {
        $entity = new Entity();
        $entity->reference = null;

        $this->metadata->addPropertyConstraint('reference', new Valid());

        $this->visitor->validate($entity, 'Default', '');

        $this->assertCount(0, $this->visitor->getViolations());
    }

    /**
     * @expectedException \Symfony\Component\Validator\Exception\NoSuchMetadataException
     */
    public function testValidateCascadedPropertyRequiresObjectOrArray()
    {
        $entity = new Entity();
        $entity->reference = 'no object';

        $this->metadata->addPropertyConstraint('reference', new Valid());

        $this->visitor->validate($entity, 'Default', '');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
use Symfony\Component\Validator\Constraints\ExpressionValidator;

/**
 * Default implementation of the ConstraintValidatorFactoryInterface.
 *
 * This enforces the convention that the validatedBy() method on any
 * Constraint will return the class name of the ConstraintValidator that
 * should validate the Constraint.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ConstraintValidatorFactory implements ConstraintValidatorFactoryInterface
{
    protected $validators = array();

    /**
     * @var PropertyAccessorInterface
     */
    private $propertyAccessor;

    public function __construct(PropertyAccessorInterface $propertyAccessor = null)
    {
        $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
    }

    /**
     * {@inheritDoc}
     */
    public function getInstance(Constraint $constraint)
    {
        $className = $constraint->validatedBy();

        // The second condition is a hack that is needed when CollectionValidator
        // calls itself recursively (Collection constraints can be nested).
        // Since the context of the validator is overwritten when initialize()
        // is called for the nested constraint, the outer validator is
        // acting on the wrong context when the nested validation terminates.
        //
        // A better solution - which should be approached in Symfony 3.0 - is to
        // remove the initialize() method and pass the context as last argument
        // to validate() instead.
        if (!isset($this->validators[$className]) || 'Symfony\Component\Validator\Constraints\CollectionValidator' === $className) {
            $this->validators[$className] = 'validator.expression' === $className
                ? new ExpressionValidator($this->propertyAccessor)
                : new $className();
        }

        return $this->validators[$className];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * An object backed by a PHP class.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface ClassBasedInterface
{
    /**
     * Returns the name of the backing PHP class.
     *
     * @return string The name of the backing class.
     */
    public function getClassName();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
use Symfony\Component\Validator\Mapping\ClassMetadataFactory;
use Symfony\Component\Validator\Exception\ValidatorException;
use Symfony\Component\Validator\Mapping\Loader\LoaderChain;
use Symfony\Component\Validator\Mapping\Cache\CacheInterface;
use Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader;
use Symfony\Component\Validator\Mapping\Loader\YamlFileLoader;
use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Validator\Mapping\Loader\YamlFilesLoader;
use Symfony\Component\Validator\Mapping\Loader\XmlFileLoader;
use Symfony\Component\Validator\Mapping\Loader\XmlFilesLoader;
use Symfony\Component\Translation\TranslatorInterface;
use Doctrine\Common\Annotations\Reader;
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\CachedReader;
use Doctrine\Common\Cache\ArrayCache;

/**
 * The default implementation of {@link ValidatorBuilderInterface}.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
class ValidatorBuilder implements ValidatorBuilderInterface
{
    /**
     * @var array
     */
    private $initializers = array();

    /**
     * @var array
     */
    private $xmlMappings = array();

    /**
     * @var array
     */
    private $yamlMappings = array();

    /**
     * @var array
     */
    private $methodMappings = array();

    /**
     * @var Reader
     */
    private $annotationReader = null;

    /**
     * @var MetadataFactoryInterface
     */
    private $metadataFactory;

    /**
     * @var ConstraintValidatorFactoryInterface
     */
    private $validatorFactory;

    /**
     * @var CacheInterface
     */
    private $metadataCache;

    /**
     * @var TranslatorInterface
     */
    private $translator;

    /**
     * @var null|string
     */
    private $translationDomain;

    /**
     * @var PropertyAccessorInterface
     */
    private $propertyAccessor;

    /**
     * {@inheritdoc}
     */
    public function addObjectInitializer(ObjectInitializerInterface $initializer)
    {
        $this->initializers[] = $initializer;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addObjectInitializers(array $initializers)
    {
        $this->initializers = array_merge($this->initializers, $initializers);

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addXmlMapping($path)
    {
        if (null !== $this->metadataFactory) {
            throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.');
        }

        $this->xmlMappings[] = $path;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addXmlMappings(array $paths)
    {
        if (null !== $this->metadataFactory) {
            throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.');
        }

        $this->xmlMappings = array_merge($this->xmlMappings, $paths);

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addYamlMapping($path)
    {
        if (null !== $this->metadataFactory) {
            throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.');
        }

        $this->yamlMappings[] = $path;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addYamlMappings(array $paths)
    {
        if (null !== $this->metadataFactory) {
            throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.');
        }

        $this->yamlMappings = array_merge($this->yamlMappings, $paths);

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addMethodMapping($methodName)
    {
        if (null !== $this->metadataFactory) {
            throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.');
        }

        $this->methodMappings[] = $methodName;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function addMethodMappings(array $methodNames)
    {
        if (null !== $this->metadataFactory) {
            throw new ValidatorException('You cannot add custom mappings after setting a custom metadata factory. Configure your metadata factory instead.');
        }

        $this->methodMappings = array_merge($this->methodMappings, $methodNames);

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function enableAnnotationMapping(Reader $annotationReader = null)
    {
        if (null !== $this->metadataFactory) {
            throw new ValidatorException('You cannot enable annotation mapping after setting a custom metadata factory. Configure your metadata factory instead.');
        }

        if (null === $annotationReader) {
            if (!class_exists('Doctrine\Common\Annotations\AnnotationReader') || !class_exists('Doctrine\Common\Cache\ArrayCache')) {
                throw new \RuntimeException('Enabling annotation based constraint mapping requires the packages doctrine/annotations and doctrine/cache to be installed.');
            }

            $annotationReader = new CachedReader(new AnnotationReader(), new ArrayCache());
        }

        $this->annotationReader = $annotationReader;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function disableAnnotationMapping()
    {
        $this->annotationReader = null;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setMetadataFactory(MetadataFactoryInterface $metadataFactory)
    {
        if (count($this->xmlMappings) > 0 || count($this->yamlMappings) > 0 || count($this->methodMappings) > 0 || null !== $this->annotationReader) {
            throw new ValidatorException('You cannot set a custom metadata factory after adding custom mappings. You should do either of both.');
        }

        $this->metadataFactory = $metadataFactory;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setMetadataCache(CacheInterface $cache)
    {
        if (null !== $this->metadataFactory) {
            throw new ValidatorException('You cannot set a custom metadata cache after setting a custom metadata factory. Configure your metadata factory instead.');
        }

        $this->metadataCache = $cache;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setConstraintValidatorFactory(ConstraintValidatorFactoryInterface $validatorFactory)
    {
        if (null !== $this->propertyAccessor) {
            throw new ValidatorException('You cannot set a validator factory after setting a custom property accessor. Remove the call to setPropertyAccessor() if you want to call setConstraintValidatorFactory().');
        }

        $this->validatorFactory = $validatorFactory;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setTranslator(TranslatorInterface $translator)
    {
        $this->translator = $translator;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setTranslationDomain($translationDomain)
    {
        $this->translationDomain = $translationDomain;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function setPropertyAccessor(PropertyAccessorInterface $propertyAccessor)
    {
        if (null !== $this->validatorFactory) {
            throw new ValidatorException('You cannot set a property accessor after setting a custom validator factory. Configure your validator factory instead.');
        }

        $this->propertyAccessor = $propertyAccessor;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function getValidator()
    {
        $metadataFactory = $this->metadataFactory;

        if (!$metadataFactory) {
            $loaders = array();

            if (count($this->xmlMappings) > 1) {
                $loaders[] = new XmlFilesLoader($this->xmlMappings);
            } elseif (1 === count($this->xmlMappings)) {
                $loaders[] = new XmlFileLoader($this->xmlMappings[0]);
            }

            if (count($this->yamlMappings) > 1) {
                $loaders[] = new YamlFilesLoader($this->yamlMappings);
            } elseif (1 === count($this->yamlMappings)) {
                $loaders[] = new YamlFileLoader($this->yamlMappings[0]);
            }

            foreach ($this->methodMappings as $methodName) {
                $loaders[] = new StaticMethodLoader($methodName);
            }

            if ($this->annotationReader) {
                $loaders[] = new AnnotationLoader($this->annotationReader);
            }

            $loader = null;

            if (count($loaders) > 1) {
                $loader = new LoaderChain($loaders);
            } elseif (1 === count($loaders)) {
                $loader = $loaders[0];
            }

            $metadataFactory = new ClassMetadataFactory($loader, $this->metadataCache);
        }

        $propertyAccessor = $this->propertyAccessor ?: PropertyAccess::createPropertyAccessor();
        $validatorFactory = $this->validatorFactory ?: new ConstraintValidatorFactory($propertyAccessor);
        $translator = $this->translator ?: new DefaultTranslator();

        return new Validator($metadataFactory, $validatorFactory, $translator, $this->translationDomain, $this->initializers);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Validator;

/**
 * Returns {@link MetadataInterface} instances for values.
 *
 * @author Bernhard Schussek <bschussek@gmail.com>
 */
interface MetadataFactoryInterface
{
    /**
     * Returns the metadata for the given value.
     *
     * @param mixed $value Some value.
     *
     * @return MetadataInterface The metadata for the value.
     *
     * @throws Exception\NoSuchMetadataException If no metadata exists for the value.
     */
    public function getMetadataFor($value);

    /**
     * Returns whether metadata exists for the given value.
     *
     * @param mixed $value Some value.
     *
     * @return Boolean Whether metadata exists for the value.
     */
    public function hasMetadataFor($value);
}
{
    "name": "symfony/process",
    "type": "library",
    "description": "Symfony Process Component",
    "keywords": [],
    "homepage": "http://symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "http://symfony.com/contributors"
        }
    ],
    "require": {
        "php": ">=5.3.3"
    },
    "autoload": {
        "psr-0": { "Symfony\\Component\\Process\\": "" }
    },
    "target-dir": "Symfony/Component/Process",
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-master": "2.4-dev"
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process;

/**
 * An executable finder specifically designed for the PHP executable.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class PhpExecutableFinder
{
    private $executableFinder;

    public function __construct()
    {
        $this->executableFinder = new ExecutableFinder();
    }

    /**
     * Finds The PHP executable.
     *
     * @return string|false The PHP executable path or false if it cannot be found
     */
    public function find()
    {
        // PHP_BINARY return the current sapi executable
        if (defined('PHP_BINARY') && PHP_BINARY && ('cli' === PHP_SAPI) && is_file(PHP_BINARY)) {
            return PHP_BINARY;
        }

        if ($php = getenv('PHP_PATH')) {
            if (!is_executable($php)) {
                return false;
            }

            return $php;
        }

        if ($php = getenv('PHP_PEAR_PHP_BIN')) {
            if (is_executable($php)) {
                return $php;
            }
        }

        $dirs = array(PHP_BINDIR);
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $dirs[] = 'C:\xampp\php\\';
        }

        return $this->executableFinder->find('php', false, $dirs);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process;

use Symfony\Component\Process\Exception\InvalidArgumentException;
use Symfony\Component\Process\Exception\LogicException;

/**
 * Process builder.
 *
 * @author Kris Wallsmith <kris@symfony.com>
 */
class ProcessBuilder
{
    private $arguments;
    private $cwd;
    private $env = array();
    private $stdin;
    private $timeout = 60;
    private $options = array();
    private $inheritEnv = true;
    private $prefix = array();

    public function __construct(array $arguments = array())
    {
        $this->arguments = $arguments;
    }

    public static function create(array $arguments = array())
    {
        return new static($arguments);
    }

    /**
     * Adds an unescaped argument to the command string.
     *
     * @param string $argument A command argument
     *
     * @return ProcessBuilder
     */
    public function add($argument)
    {
        $this->arguments[] = $argument;

        return $this;
    }

    /**
     * Adds an unescaped prefix to the command string.
     *
     * The prefix is preserved when resetting arguments.
     *
     * @param string|array $prefix A command prefix or an array of command prefixes
     *
     * @return ProcessBuilder
     */
    public function setPrefix($prefix)
    {
        $this->prefix = is_array($prefix) ? $prefix : array($prefix);

        return $this;
    }

    /**
     * @param array $arguments
     *
     * @return ProcessBuilder
     */
    public function setArguments(array $arguments)
    {
        $this->arguments = $arguments;

        return $this;
    }

    public function setWorkingDirectory($cwd)
    {
        $this->cwd = $cwd;

        return $this;
    }

    public function inheritEnvironmentVariables($inheritEnv = true)
    {
        $this->inheritEnv = $inheritEnv;

        return $this;
    }

    public function setEnv($name, $value)
    {
        $this->env[$name] = $value;

        return $this;
    }

    public function addEnvironmentVariables(array $variables)
    {
        $this->env = array_replace($this->env, $variables);

        return $this;
    }

    public function setInput($stdin)
    {
        $this->stdin = $stdin;

        return $this;
    }

    /**
     * Sets the process timeout.
     *
     * To disable the timeout, set this value to null.
     *
     * @param float|null
     *
     * @return ProcessBuilder
     *
     * @throws InvalidArgumentException
     */
    public function setTimeout($timeout)
    {
        if (null === $timeout) {
            $this->timeout = null;

            return $this;
        }

        $timeout = (float) $timeout;

        if ($timeout < 0) {
            throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
        }

        $this->timeout = $timeout;

        return $this;
    }

    public function setOption($name, $value)
    {
        $this->options[$name] = $value;

        return $this;
    }

    public function getProcess()
    {
        if (0 === count($this->prefix) && 0 === count($this->arguments)) {
            throw new LogicException('You must add() command arguments before calling getProcess().');
        }

        $options = $this->options;

        $arguments = array_merge($this->prefix, $this->arguments);
        $script = implode(' ', array_map(array(__NAMESPACE__.'\\ProcessUtils', 'escapeArgument'), $arguments));

        if ($this->inheritEnv) {
            // include $_ENV for BC purposes
            $env = array_replace($_ENV, $_SERVER, $this->env);
        } else {
            $env = $this->env;
        }

        return new Process($script, $this->cwd, $env, $this->stdin, $this->timeout, $options);
    }
}
Copyright (c) 2004-2013 Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process;

use Symfony\Component\Process\Exception\RuntimeException;

/**
 * ProcessPipes manages descriptors and pipes for the use of proc_open.
 */
class ProcessPipes
{
    /** @var array */
    public $pipes = array();
    /** @var array */
    private $fileHandles = array();
    /** @var array */
    private $readBytes = array();
    /** @var Boolean */
    private $useFiles;

    public function __construct($useFiles = false)
    {
        $this->useFiles = (Boolean) $useFiles;

        // Fix for PHP bug #51800: reading from STDOUT pipe hangs forever on Windows if the output is too big.
        // Workaround for this problem is to use temporary files instead of pipes on Windows platform.
        //
        // Please note that this work around prevents hanging but
        // another issue occurs : In some race conditions, some data may be
        // lost or corrupted.
        //
        // @see https://bugs.php.net/bug.php?id=51800
        if ($this->useFiles) {
            $this->fileHandles = array(
                Process::STDOUT => tmpfile(),
            );
            if (false === $this->fileHandles[Process::STDOUT]) {
                throw new RuntimeException('A temporary file could not be opened to write the process output to, verify that your TEMP environment variable is writable');
            }
            $this->readBytes = array(
                Process::STDOUT => 0,
            );
        }
    }

    public function __destruct()
    {
        $this->close();
    }

    /**
     * Sets non-blocking mode on pipes.
     */
    public function unblock()
    {
        foreach ($this->pipes as $pipe) {
            stream_set_blocking($pipe, 0);
        }
    }

    /**
     * Closes file handles and pipes.
     */
    public function close()
    {
        $this->closeUnixPipes();
        foreach ($this->fileHandles as $offset => $handle) {
            fclose($handle);
        }
        $this->fileHandles = array();
    }

    /**
     * Closes unix pipes.
     *
     * Nothing happens in case file handles are used.
     */
    public function closeUnixPipes()
    {
        foreach ($this->pipes as $pipe) {
            fclose($pipe);
        }
        $this->pipes = array();
    }

    /**
     * Returns an array of descriptors for the use of proc_open.
     *
     * @return array
     */
    public function getDescriptors()
    {
        if ($this->useFiles) {
            return array(
                array('pipe', 'r'),
                $this->fileHandles[Process::STDOUT],
                // Use a file handle only for STDOUT. Using for both STDOUT and STDERR would trigger https://bugs.php.net/bug.php?id=65650
                array('pipe', 'w'),
            );
        }

        return array(
            array('pipe', 'r'), // stdin
            array('pipe', 'w'), // stdout
            array('pipe', 'w'), // stderr
        );
    }

    /**
     * Reads data in file handles and pipes.
     *
     * @param Boolean $blocking Whether to use blocking calls or not.
     *
     * @return array An array of read data indexed by their fd.
     */
    public function read($blocking)
    {
        return array_replace($this->readStreams($blocking), $this->readFileHandles());
    }

    /**
     * Reads data in file handles and pipes, closes them if EOF is reached.
     *
     * @param Boolean $blocking Whether to use blocking calls or not.
     *
     * @return array An array of read data indexed by their fd.
     */
    public function readAndCloseHandles($blocking)
    {
        return array_replace($this->readStreams($blocking, true), $this->readFileHandles(true));
    }

    /**
     * Returns if the current state has open file handles or pipes.
     *
     * @return Boolean
     */
    public function hasOpenHandles()
    {
        if (!$this->useFiles) {
            return (Boolean) $this->pipes;
        }

        return (Boolean) $this->pipes && (Boolean) $this->fileHandles;
    }

    /**
     * Writes stdin data.
     *
     * @param Boolean     $blocking Whether to use blocking calls or not.
     * @param string|null $stdin    The data to write.
     */
    public function write($blocking, $stdin)
    {
        if (null === $stdin) {
            fclose($this->pipes[0]);
            unset($this->pipes[0]);

            return;
        }

        $writePipes = array($this->pipes[0]);
        unset($this->pipes[0]);
        $stdinLen = strlen($stdin);
        $stdinOffset = 0;

        while ($writePipes) {
            $r = null;
            $w = $writePipes;
            $e = null;

            if (false === $n = @stream_select($r, $w, $e, 0, $blocking ? ceil(Process::TIMEOUT_PRECISION * 1E6) : 0)) {
                // if a system call has been interrupted, forget about it, let's try again
                if ($this->hasSystemCallBeenInterrupted()) {
                    continue;
                }
                break;
            }

            // nothing has changed, let's wait until the process is ready
            if (0 === $n) {
                continue;
            }

            if ($w) {
                $written = fwrite($writePipes[0], (binary) substr($stdin, $stdinOffset), 8192);
                if (false !== $written) {
                    $stdinOffset += $written;
                }
                if ($stdinOffset >= $stdinLen) {
                    fclose($writePipes[0]);
                    $writePipes = null;
                }
            }
        }
    }

    /**
     * Reads data in file handles.
     *
     * @return array An array of read data indexed by their fd.
     */
    private function readFileHandles($close = false)
    {
        $read = array();
        $fh = $this->fileHandles;
        foreach ($fh as $type => $fileHandle) {
            if (0 !== fseek($fileHandle, $this->readBytes[$type])) {
                continue;
            }
            $data = '';
            $dataread = null;
            while (!feof($fileHandle)) {
                if (false !== $dataread = fread($fileHandle, 16392)) {
                    $data .= $dataread;
                }
            }
            if (0 < $length = strlen($data)) {
                $this->readBytes[$type] += $length;
                $read[$type] = $data;
            }

            if (false === $dataread || (true === $close && feof($fileHandle) && '' === $data)) {
                fclose($this->fileHandles[$type]);
                unset($this->fileHandles[$type]);
            }
        }

        return $read;
    }

    /**
     * Reads data in file pipes streams.
     *
     * @param Boolean $blocking Whether to use blocking calls or not.
     *
     * @return array An array of read data indexed by their fd.
     */
    private function readStreams($blocking, $close = false)
    {
        if (empty($this->pipes)) {
            return array();
        }

        $read = array();

        $r = $this->pipes;
        $w = null;
        $e = null;

        // let's have a look if something changed in streams
        if (false === $n = @stream_select($r, $w, $e, 0, $blocking ? ceil(Process::TIMEOUT_PRECISION * 1E6) : 0)) {
            // if a system call has been interrupted, forget about it, let's try again
            // otherwise, an error occurred, let's reset pipes
            if (!$this->hasSystemCallBeenInterrupted()) {
                $this->pipes = array();
            }

            return $read;
        }

        // nothing has changed
        if (0 === $n) {
            return $read;
        }

        foreach ($r as $pipe) {
            $type = array_search($pipe, $this->pipes);
            $data = fread($pipe, 8192);

            if (strlen($data) > 0) {
                $read[$type] = $data;
            }

            if (false === $data || (true === $close && feof($pipe) && '' === $data)) {
                fclose($this->pipes[$type]);
                unset($this->pipes[$type]);
            }
        }

        return $read;
    }

    /**
     * Returns true if a system call has been interrupted.
     *
     * @return Boolean
     */
    private function hasSystemCallBeenInterrupted()
    {
        $lastError = error_get_last();

        // stream_select returns false when the `select` system call is interrupted by an incoming signal
        return isset($lastError['message']) && false !== stripos($lastError['message'], 'interrupted system call');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process;

use Symfony\Component\Process\Exception\RuntimeException;

/**
 * PhpProcess runs a PHP script in an independent process.
 *
 * $p = new PhpProcess('<?php echo "foo"; ?>');
 * $p->run();
 * print $p->getOutput()."\n";
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class PhpProcess extends Process
{
    private $executableFinder;

    /**
     * Constructor.
     *
     * @param string  $script  The PHP script to run (as a string)
     * @param string  $cwd     The working directory
     * @param array   $env     The environment variables
     * @param integer $timeout The timeout in seconds
     * @param array   $options An array of options for proc_open
     *
     * @api
     */
    public function __construct($script, $cwd = null, array $env = array(), $timeout = 60, array $options = array())
    {
        parent::__construct(null, $cwd, $env, $script, $timeout, $options);

        $this->executableFinder = new PhpExecutableFinder();
    }

    /**
     * Sets the path to the PHP binary to use.
     *
     * @api
     */
    public function setPhpBinary($php)
    {
        $this->setCommandLine($php);
    }

    /**
     * {@inheritdoc}
     */
    public function start($callback = null)
    {
        if (null === $this->getCommandLine()) {
            if (false === $php = $this->executableFinder->find()) {
                throw new RuntimeException('Unable to find the PHP executable.');
            }
            $this->setCommandLine($php);
        }

        parent::start($callback);
    }
}
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Process Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Tests</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process;

use Symfony\Component\Process\Exception\InvalidArgumentException;
use Symfony\Component\Process\Exception\LogicException;
use Symfony\Component\Process\Exception\ProcessTimedOutException;
use Symfony\Component\Process\Exception\RuntimeException;

/**
 * Process is a thin wrapper around proc_* functions to ease
 * start independent PHP processes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Process
{
    const ERR = 'err';
    const OUT = 'out';

    const STATUS_READY = 'ready';
    const STATUS_STARTED = 'started';
    const STATUS_TERMINATED = 'terminated';

    const STDIN = 0;
    const STDOUT = 1;
    const STDERR = 2;

    // Timeout Precision in seconds.
    const TIMEOUT_PRECISION = 0.2;

    private $callback;
    private $commandline;
    private $cwd;
    private $env;
    private $stdin;
    private $starttime;
    private $lastOutputTime;
    private $timeout;
    private $idleTimeout;
    private $options;
    private $exitcode;
    private $fallbackExitcode;
    private $processInformation;
    private $stdout;
    private $stderr;
    private $enhanceWindowsCompatibility;
    private $enhanceSigchildCompatibility;
    private $process;
    private $status = self::STATUS_READY;
    private $incrementalOutputOffset;
    private $incrementalErrorOutputOffset;
    private $tty;

    private $useFileHandles = false;
    /** @var ProcessPipes */
    private $processPipes;

    private static $sigchild;

    /**
     * Exit codes translation table.
     *
     * User-defined errors must use exit codes in the 64-113 range.
     *
     * @var array
     */
    public static $exitCodes = array(
        0 => 'OK',
        1 => 'General error',
        2 => 'Misuse of shell builtins',

        126 => 'Invoked command cannot execute',
        127 => 'Command not found',
        128 => 'Invalid exit argument',

        // signals
        129 => 'Hangup',
        130 => 'Interrupt',
        131 => 'Quit and dump core',
        132 => 'Illegal instruction',
        133 => 'Trace/breakpoint trap',
        134 => 'Process aborted',
        135 => 'Bus error: "access to undefined portion of memory object"',
        136 => 'Floating point exception: "erroneous arithmetic operation"',
        137 => 'Kill (terminate immediately)',
        138 => 'User-defined 1',
        139 => 'Segmentation violation',
        140 => 'User-defined 2',
        141 => 'Write to pipe with no one reading',
        142 => 'Signal raised by alarm',
        143 => 'Termination (request to terminate)',
        // 144 - not defined
        145 => 'Child process terminated, stopped (or continued*)',
        146 => 'Continue if stopped',
        147 => 'Stop executing temporarily',
        148 => 'Terminal stop signal',
        149 => 'Background process attempting to read from tty ("in")',
        150 => 'Background process attempting to write to tty ("out")',
        151 => 'Urgent data available on socket',
        152 => 'CPU time limit exceeded',
        153 => 'File size limit exceeded',
        154 => 'Signal raised by timer counting virtual time: "virtual timer expired"',
        155 => 'Profiling timer expired',
        // 156 - not defined
        157 => 'Pollable event',
        // 158 - not defined
        159 => 'Bad syscall',
    );

    /**
     * Constructor.
     *
     * @param string             $commandline The command line to run
     * @param string|null        $cwd         The working directory or null to use the working dir of the current PHP process
     * @param array|null         $env         The environment variables or null to inherit
     * @param string|null        $stdin       The STDIN content
     * @param integer|float|null $timeout     The timeout in seconds or null to disable
     * @param array              $options     An array of options for proc_open
     *
     * @throws RuntimeException When proc_open is not installed
     *
     * @api
     */
    public function __construct($commandline, $cwd = null, array $env = null, $stdin = null, $timeout = 60, array $options = array())
    {
        if (!function_exists('proc_open')) {
            throw new RuntimeException('The Process class relies on proc_open, which is not available on your PHP installation.');
        }

        $this->commandline = $commandline;
        $this->cwd = $cwd;

        // on windows, if the cwd changed via chdir(), proc_open defaults to the dir where php was started
        // on gnu/linux, PHP builds with --enable-maintainer-zts are also affected
        // @see : https://bugs.php.net/bug.php?id=51800
        // @see : https://bugs.php.net/bug.php?id=50524

        if (null === $this->cwd && (defined('ZEND_THREAD_SAFE') || defined('PHP_WINDOWS_VERSION_BUILD'))) {
            $this->cwd = getcwd();
        }
        if (null !== $env) {
            $this->setEnv($env);
        } else {
            $this->env = null;
        }
        $this->stdin = $stdin;
        $this->setTimeout($timeout);
        $this->useFileHandles = defined('PHP_WINDOWS_VERSION_BUILD');
        $this->enhanceWindowsCompatibility = true;
        $this->enhanceSigchildCompatibility = !defined('PHP_WINDOWS_VERSION_BUILD') && $this->isSigchildEnabled();
        $this->options = array_replace(array('suppress_errors' => true, 'binary_pipes' => true), $options);
    }

    public function __destruct()
    {
        // stop() will check if we have a process running.
        $this->stop();
    }

    public function __clone()
    {
        $this->resetProcessData();
    }

    /**
     * Runs the process.
     *
     * The callback receives the type of output (out or err) and
     * some bytes from the output in real-time. It allows to have feedback
     * from the independent process during execution.
     *
     * The STDOUT and STDERR are also available after the process is finished
     * via the getOutput() and getErrorOutput() methods.
     *
     * @param callable|null $callback A PHP callback to run whenever there is some
     *                                output available on STDOUT or STDERR
     *
     * @return integer The exit status code
     *
     * @throws RuntimeException When process can't be launch or is stopped
     *
     * @api
     */
    public function run($callback = null)
    {
        $this->start($callback);

        return $this->wait();
    }

    /**
     * Starts the process and returns after sending the STDIN.
     *
     * This method blocks until all STDIN data is sent to the process then it
     * returns while the process runs in the background.
     *
     * The termination of the process can be awaited with wait().
     *
     * The callback receives the type of output (out or err) and some bytes from
     * the output in real-time while writing the standard input to the process.
     * It allows to have feedback from the independent process during execution.
     * If there is no callback passed, the wait() method can be called
     * with true as a second parameter then the callback will get all data occurred
     * in (and since) the start call.
     *
     * @param callable|null $callback A PHP callback to run whenever there is some
     *                                output available on STDOUT or STDERR
     *
     * @return Process The process itself
     *
     * @throws RuntimeException When process can't be launch or is stopped
     * @throws RuntimeException When process is already running
     */
    public function start($callback = null)
    {
        if ($this->isRunning()) {
            throw new RuntimeException('Process is already running');
        }

        $this->resetProcessData();
        $this->starttime = $this->lastOutputTime = microtime(true);
        $this->callback = $this->buildCallback($callback);
        $descriptors = $this->getDescriptors();

        $commandline = $this->commandline;

        if (defined('PHP_WINDOWS_VERSION_BUILD') && $this->enhanceWindowsCompatibility) {
            $commandline = 'cmd /V:ON /E:ON /C "'.$commandline.'"';
            if (!isset($this->options['bypass_shell'])) {
                $this->options['bypass_shell'] = true;
            }
        }

        $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $this->env, $this->options);

        if (!is_resource($this->process)) {
            throw new RuntimeException('Unable to launch a new process.');
        }
        $this->status = self::STATUS_STARTED;

        $this->processPipes->unblock();
        $this->processPipes->write(false, $this->stdin);
        $this->updateStatus(false);
        $this->checkTimeout();
    }

    /**
     * Restarts the process.
     *
     * Be warned that the process is cloned before being started.
     *
     * @param callable|null $callback A PHP callback to run whenever there is some
     *                                output available on STDOUT or STDERR
     *
     * @return Process The new process
     *
     * @throws RuntimeException When process can't be launch or is stopped
     * @throws RuntimeException When process is already running
     *
     * @see start()
     */
    public function restart($callback = null)
    {
        if ($this->isRunning()) {
            throw new RuntimeException('Process is already running');
        }

        $process = clone $this;
        $process->start($callback);

        return $process;
    }

    /**
     * Waits for the process to terminate.
     *
     * The callback receives the type of output (out or err) and some bytes
     * from the output in real-time while writing the standard input to the process.
     * It allows to have feedback from the independent process during execution.
     *
     * @param callable|null $callback A valid PHP callback
     *
     * @return integer The exitcode of the process
     *
     * @throws RuntimeException When process timed out
     * @throws RuntimeException When process stopped after receiving signal
     */
    public function wait($callback = null)
    {
        $this->updateStatus(false);
        if (null !== $callback) {
            $this->callback = $this->buildCallback($callback);
        }

        do {
            $this->checkTimeout();
            $running = defined('PHP_WINDOWS_VERSION_BUILD') ? $this->isRunning() : $this->processPipes->hasOpenHandles();
            $close = !defined('PHP_WINDOWS_VERSION_BUILD') || !$running;;
            $this->readPipes(true, $close);
        } while ($running);

        while ($this->isRunning()) {
            usleep(1000);
        }

        if ($this->processInformation['signaled']) {
            if ($this->isSigchildEnabled()) {
                throw new RuntimeException('The process has been signaled.');
            }

            throw new RuntimeException(sprintf('The process has been signaled with signal "%s".', $this->processInformation['termsig']));
        }

        return $this->exitcode;
    }

    /**
     * Returns the Pid (process identifier), if applicable.
     *
     * @return integer|null The process id if running, null otherwise
     *
     * @throws RuntimeException In case --enable-sigchild is activated
     */
    public function getPid()
    {
        if ($this->isSigchildEnabled()) {
            throw new RuntimeException('This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved.');
        }

        $this->updateStatus(false);

        return $this->isRunning() ? $this->processInformation['pid'] : null;
    }

    /**
     * Sends a posix signal to the process.
     *
     * @param  integer $signal A valid posix signal (see http://www.php.net/manual/en/pcntl.constants.php)
     * @return Process
     *
     * @throws LogicException   In case the process is not running
     * @throws RuntimeException In case --enable-sigchild is activated
     * @throws RuntimeException In case of failure
     */
    public function signal($signal)
    {
        if (!$this->isRunning()) {
            throw new LogicException('Can not send signal on a non running process.');
        }

        if ($this->isSigchildEnabled()) {
            throw new RuntimeException('This PHP has been compiled with --enable-sigchild. The process can not be signaled.');
        }

        if (true !== @proc_terminate($this->process, $signal)) {
            throw new RuntimeException(sprintf('Error while sending signal `%d`.', $signal));
        }

        return $this;
    }

    /**
     * Returns the current output of the process (STDOUT).
     *
     * @return string The process output
     *
     * @api
     */
    public function getOutput()
    {
        $this->readPipes(false, defined('PHP_WINDOWS_VERSION_BUILD') ? !$this->processInformation['running'] : true);

        return $this->stdout;
    }

    /**
     * Returns the output incrementally.
     *
     * In comparison with the getOutput method which always return the whole
     * output, this one returns the new output since the last call.
     *
     * @return string The process output since the last call
     */
    public function getIncrementalOutput()
    {
        $data = $this->getOutput();

        $latest = substr($data, $this->incrementalOutputOffset);
        $this->incrementalOutputOffset = strlen($data);

        return $latest;
    }

    /**
     * Clears the process output.
     *
     * @return Process
     */
    public function clearOutput()
    {
        $this->stdout = '';
        $this->incrementalOutputOffset = 0;

        return $this;
    }

    /**
     * Returns the current error output of the process (STDERR).
     *
     * @return string The process error output
     *
     * @api
     */
    public function getErrorOutput()
    {
        $this->readPipes(false, defined('PHP_WINDOWS_VERSION_BUILD') ? !$this->processInformation['running'] : true);

        return $this->stderr;
    }

    /**
     * Returns the errorOutput incrementally.
     *
     * In comparison with the getErrorOutput method which always return the
     * whole error output, this one returns the new error output since the last
     * call.
     *
     * @return string The process error output since the last call
     */
    public function getIncrementalErrorOutput()
    {
        $data = $this->getErrorOutput();

        $latest = substr($data, $this->incrementalErrorOutputOffset);
        $this->incrementalErrorOutputOffset = strlen($data);

        return $latest;
    }

    /**
     * Clears the process output.
     *
     * @return Process
     */
    public function clearErrorOutput()
    {
        $this->stderr = '';
        $this->incrementalErrorOutputOffset = 0;

        return $this;
    }

    /**
     * Returns the exit code returned by the process.
     *
     * @return integer The exit status code
     *
     * @throws RuntimeException In case --enable-sigchild is activated and the sigchild compatibility mode is disabled
     *
     * @api
     */
    public function getExitCode()
    {
        if ($this->isSigchildEnabled() && !$this->enhanceSigchildCompatibility) {
            throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method');
        }

        $this->updateStatus(false);

        return $this->exitcode;
    }

    /**
     * Returns a string representation for the exit code returned by the process.
     *
     * This method relies on the Unix exit code status standardization
     * and might not be relevant for other operating systems.
     *
     * @return string A string representation for the exit status code
     *
     * @see http://tldp.org/LDP/abs/html/exitcodes.html
     * @see http://en.wikipedia.org/wiki/Unix_signal
     */
    public function getExitCodeText()
    {
        $exitcode = $this->getExitCode();

        return isset(self::$exitCodes[$exitcode]) ? self::$exitCodes[$exitcode] : 'Unknown error';
    }

    /**
     * Checks if the process ended successfully.
     *
     * @return Boolean true if the process ended successfully, false otherwise
     *
     * @api
     */
    public function isSuccessful()
    {
        return 0 === $this->getExitCode();
    }

    /**
     * Returns true if the child process has been terminated by an uncaught signal.
     *
     * It always returns false on Windows.
     *
     * @return Boolean
     *
     * @throws RuntimeException In case --enable-sigchild is activated
     *
     * @api
     */
    public function hasBeenSignaled()
    {
        if ($this->isSigchildEnabled()) {
            throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved');
        }

        $this->updateStatus(false);

        return $this->processInformation['signaled'];
    }

    /**
     * Returns the number of the signal that caused the child process to terminate its execution.
     *
     * It is only meaningful if hasBeenSignaled() returns true.
     *
     * @return integer
     *
     * @throws RuntimeException In case --enable-sigchild is activated
     *
     * @api
     */
    public function getTermSignal()
    {
        if ($this->isSigchildEnabled()) {
            throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved');
        }

        $this->updateStatus(false);

        return $this->processInformation['termsig'];
    }

    /**
     * Returns true if the child process has been stopped by a signal.
     *
     * It always returns false on Windows.
     *
     * @return Boolean
     *
     * @api
     */
    public function hasBeenStopped()
    {
        $this->updateStatus(false);

        return $this->processInformation['stopped'];
    }

    /**
     * Returns the number of the signal that caused the child process to stop its execution.
     *
     * It is only meaningful if hasBeenStopped() returns true.
     *
     * @return integer
     *
     * @api
     */
    public function getStopSignal()
    {
        $this->updateStatus(false);

        return $this->processInformation['stopsig'];
    }

    /**
     * Checks if the process is currently running.
     *
     * @return Boolean true if the process is currently running, false otherwise
     */
    public function isRunning()
    {
        if (self::STATUS_STARTED !== $this->status) {
            return false;
        }

        $this->updateStatus(false);

        return $this->processInformation['running'];
    }

    /**
     * Checks if the process has been started with no regard to the current state.
     *
     * @return Boolean true if status is ready, false otherwise
     */
    public function isStarted()
    {
        return $this->status != self::STATUS_READY;
    }

    /**
     * Checks if the process is terminated.
     *
     * @return Boolean true if process is terminated, false otherwise
     */
    public function isTerminated()
    {
        $this->updateStatus(false);

        return $this->status == self::STATUS_TERMINATED;
    }

    /**
     * Gets the process status.
     *
     * The status is one of: ready, started, terminated.
     *
     * @return string The current process status
     */
    public function getStatus()
    {
        $this->updateStatus(false);

        return $this->status;
    }

    /**
     * Stops the process.
     *
     * @param integer|float $timeout The timeout in seconds
     * @param integer       $signal  A posix signal to send in case the process has not stop at timeout, default is SIGKILL
     *
     * @return integer The exit-code of the process
     *
     * @throws RuntimeException if the process got signaled
     */
    public function stop($timeout = 10, $signal = null)
    {
        $timeoutMicro = microtime(true) + $timeout;
        if ($this->isRunning()) {
            proc_terminate($this->process);
            do {
                usleep(1000);
            } while ($this->isRunning() && microtime(true) < $timeoutMicro);

            if ($this->isRunning() && !$this->isSigchildEnabled()) {
                if (null !== $signal || defined('SIGKILL')) {
                    $this->signal($signal ?: SIGKILL);
                }
            }
        }

        $this->updateStatus(false);
        if ($this->processInformation['running']) {
            $this->close();
        }

        $this->status = self::STATUS_TERMINATED;

        return $this->exitcode;
    }

    /**
     * Adds a line to the STDOUT stream.
     *
     * @param string $line The line to append
     */
    public function addOutput($line)
    {
        $this->lastOutputTime = microtime(true);
        $this->stdout .= $line;
    }

    /**
     * Adds a line to the STDERR stream.
     *
     * @param string $line The line to append
     */
    public function addErrorOutput($line)
    {
        $this->lastOutputTime = microtime(true);
        $this->stderr .= $line;
    }

    /**
     * Gets the command line to be executed.
     *
     * @return string The command to execute
     */
    public function getCommandLine()
    {
        return $this->commandline;
    }

    /**
     * Sets the command line to be executed.
     *
     * @param string $commandline The command to execute
     *
     * @return self The current Process instance
     */
    public function setCommandLine($commandline)
    {
        $this->commandline = $commandline;

        return $this;
    }

    /**
     * Gets the process timeout.
     *
     * @return float|null The timeout in seconds or null if it's disabled
     */
    public function getTimeout()
    {
        return $this->timeout;
    }

    /**
     * Gets the process idle timeout.
     *
     * @return float|null
     */
    public function getIdleTimeout()
    {
        return $this->idleTimeout;
    }

    /**
     * Sets the process timeout.
     *
     * To disable the timeout, set this value to null.
     *
     * @param integer|float|null $timeout The timeout in seconds
     *
     * @return self The current Process instance
     *
     * @throws InvalidArgumentException if the timeout is negative
     */
    public function setTimeout($timeout)
    {
        $this->timeout = $this->validateTimeout($timeout);

        return $this;
    }

    /**
     * Sets the process idle timeout.
     *
     * @param integer|float|null $timeout
     *
     * @return self The current Process instance.
     *
     * @throws InvalidArgumentException if the timeout is negative
     */
    public function setIdleTimeout($timeout)
    {
        $this->idleTimeout = $this->validateTimeout($timeout);

        return $this;
    }

    /**
     * Enables or disables the TTY mode.
     *
     * @param boolean $tty True to enabled and false to disable
     *
     * @return self The current Process instance
     */
    public function setTty($tty)
    {
        $this->tty = (Boolean) $tty;

        return $this;
    }

    /**
     * Checks if  the TTY mode is enabled.
     *
     * @return Boolean true if the TTY mode is enabled, false otherwise
     */
    public function isTty()
    {
        return $this->tty;
    }

    /**
     * Gets the working directory.
     *
     * @return string|null The current working directory or null on failure
     */
    public function getWorkingDirectory()
    {
        if (null === $this->cwd) {
            // getcwd() will return false if any one of the parent directories does not have
            // the readable or search mode set, even if the current directory does
            return getcwd() ?: null;
        }

        return $this->cwd;
    }

    /**
     * Sets the current working directory.
     *
     * @param string $cwd The new working directory
     *
     * @return self The current Process instance
     */
    public function setWorkingDirectory($cwd)
    {
        $this->cwd = $cwd;

        return $this;
    }

    /**
     * Gets the environment variables.
     *
     * @return array The current environment variables
     */
    public function getEnv()
    {
        return $this->env;
    }

    /**
     * Sets the environment variables.
     *
     * An environment variable value should be a string.
     * If it is an array, the variable is ignored.
     *
     * That happens in PHP when 'argv' is registered into
     * the $_ENV array for instance.
     *
     * @param array $env The new environment variables
     *
     * @return self The current Process instance
     */
    public function setEnv(array $env)
    {
        // Process can not handle env values that are arrays
        $env = array_filter($env, function ($value) { if (!is_array($value)) { return true; } });

        $this->env = array();
        foreach ($env as $key => $value) {
            $this->env[(binary) $key] = (binary) $value;
        }

        return $this;
    }

    /**
     * Gets the contents of STDIN.
     *
     * @return string|null The current contents
     */
    public function getStdin()
    {
        return $this->stdin;
    }

    /**
     * Sets the contents of STDIN.
     *
     * @param string|null $stdin The new contents
     *
     * @return self The current Process instance
     */
    public function setStdin($stdin)
    {
        $this->stdin = $stdin;

        return $this;
    }

    /**
     * Gets the options for proc_open.
     *
     * @return array The current options
     */
    public function getOptions()
    {
        return $this->options;
    }

    /**
     * Sets the options for proc_open.
     *
     * @param array $options The new options
     *
     * @return self The current Process instance
     */
    public function setOptions(array $options)
    {
        $this->options = $options;

        return $this;
    }

    /**
     * Gets whether or not Windows compatibility is enabled.
     *
     * This is true by default.
     *
     * @return Boolean
     */
    public function getEnhanceWindowsCompatibility()
    {
        return $this->enhanceWindowsCompatibility;
    }

    /**
     * Sets whether or not Windows compatibility is enabled.
     *
     * @param Boolean $enhance
     *
     * @return self The current Process instance
     */
    public function setEnhanceWindowsCompatibility($enhance)
    {
        $this->enhanceWindowsCompatibility = (Boolean) $enhance;

        return $this;
    }

    /**
     * Returns whether sigchild compatibility mode is activated or not.
     *
     * @return Boolean
     */
    public function getEnhanceSigchildCompatibility()
    {
        return $this->enhanceSigchildCompatibility;
    }

    /**
     * Activates sigchild compatibility mode.
     *
     * Sigchild compatibility mode is required to get the exit code and
     * determine the success of a process when PHP has been compiled with
     * the --enable-sigchild option
     *
     * @param Boolean $enhance
     *
     * @return self The current Process instance
     */
    public function setEnhanceSigchildCompatibility($enhance)
    {
        $this->enhanceSigchildCompatibility = (Boolean) $enhance;

        return $this;
    }

    /**
     * Performs a check between the timeout definition and the time the process started.
     *
     * In case you run a background process (with the start method), you should
     * trigger this method regularly to ensure the process timeout
     *
     * @throws ProcessTimedOutException In case the timeout was reached
     */
    public function checkTimeout()
    {
        if (null !== $this->timeout && $this->timeout < microtime(true) - $this->starttime) {
            $this->stop(0);

            throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL);
        }

        if (0 < $this->idleTimeout && $this->idleTimeout < microtime(true) - $this->lastOutputTime) {
            $this->stop(0);

            throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE);
        }
    }

    /**
     * Creates the descriptors needed by the proc_open.
     *
     * @return array
     */
    private function getDescriptors()
    {
        $this->processPipes = new ProcessPipes($this->useFileHandles);
        $descriptors = $this->processPipes->getDescriptors();

        if (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
            // last exit code is output on the fourth pipe and caught to work around --enable-sigchild
            $descriptors = array_merge($descriptors, array(array('pipe', 'w')));

            $this->commandline = '('.$this->commandline.') 3>/dev/null; code=$?; echo $code >&3; exit $code';
        }

        return $descriptors;
    }

    /**
     * Builds up the callback used by wait().
     *
     * The callbacks adds all occurred output to the specific buffer and calls
     * the user callback (if present) with the received output.
     *
     * @param callable|null $callback The user defined PHP callback
     *
     * @return callable A PHP callable
     */
    protected function buildCallback($callback)
    {
        $that = $this;
        $out = self::OUT;
        $err = self::ERR;
        $callback = function ($type, $data) use ($that, $callback, $out, $err) {
            if ($out == $type) {
                $that->addOutput($data);
            } else {
                $that->addErrorOutput($data);
            }

            if (null !== $callback) {
                call_user_func($callback, $type, $data);
            }
        };

        return $callback;
    }

    /**
     * Updates the status of the process, reads pipes.
     *
     * @param Boolean $blocking Whether to use a clocking read call.
     */
    protected function updateStatus($blocking)
    {
        if (self::STATUS_STARTED !== $this->status) {
            return;
        }

        $this->processInformation = proc_get_status($this->process);
        $this->captureExitCode();

        $this->readPipes($blocking, defined('PHP_WINDOWS_VERSION_BUILD') ? !$this->processInformation['running'] : true);

        if (!$this->processInformation['running']) {
            $this->close();
            $this->status = self::STATUS_TERMINATED;
        }
    }

    /**
     * Returns whether PHP has been compiled with the '--enable-sigchild' option or not.
     *
     * @return Boolean
     */
    protected function isSigchildEnabled()
    {
        if (null !== self::$sigchild) {
            return self::$sigchild;
        }

        ob_start();
        phpinfo(INFO_GENERAL);

        return self::$sigchild = false !== strpos(ob_get_clean(), '--enable-sigchild');
    }

    /**
     * Validates and returns the filtered timeout.
     *
     * @param integer|float|null $timeout
     *
     * @return float|null
     */
    private function validateTimeout($timeout)
    {
        $timeout = (float) $timeout;

        if (0.0 === $timeout) {
            $timeout = null;
        } elseif ($timeout < 0) {
            throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
        }

        return $timeout;
    }

    /**
     * Reads pipes, executes callback.
     *
     * @param Boolean $blocking Whether to use blocking calls or not.
     */
    private function readPipes($blocking, $close)
    {
        if ($close) {
            $result = $this->processPipes->readAndCloseHandles($blocking);
        } else {
            $result = $this->processPipes->read($blocking);
        }

        foreach ($result as $type => $data) {
            if (3 == $type) {
                $this->fallbackExitcode = (int) $data;
            } else {
                call_user_func($this->callback, $type === self::STDOUT ? self::OUT : self::ERR, $data);
            }
        }
    }

    /**
     * Captures the exitcode if mentioned in the process informations.
     */
    private function captureExitCode()
    {
        if (isset($this->processInformation['exitcode']) && -1 != $this->processInformation['exitcode']) {
            $this->exitcode = $this->processInformation['exitcode'];
        }
    }

    /**
     * Closes process resource, closes file handles, sets the exitcode.
     *
     * @return Integer The exitcode
     */
    private function close()
    {
        $exitcode = -1;

        $this->processPipes->close();
        if (is_resource($this->process)) {
            $exitcode = proc_close($this->process);
        }

        $this->exitcode = $this->exitcode !== null ? $this->exitcode : -1;
        $this->exitcode = -1 != $exitcode ? $exitcode : $this->exitcode;

        if (-1 == $this->exitcode && null !== $this->fallbackExitcode) {
            $this->exitcode = $this->fallbackExitcode;
        } elseif (-1 === $this->exitcode && $this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) {
            // if process has been signaled, no exitcode but a valid termsig, apply unix convention
            $this->exitcode = 128 + $this->processInformation['termsig'];
        }

        return $this->exitcode;
    }

    /**
     * Resets data related to the latest run of the process.
     */
    private function resetProcessData()
    {
        $this->starttime = null;
        $this->callback = null;
        $this->exitcode = null;
        $this->fallbackExitcode = null;
        $this->processInformation = null;
        $this->stdout = null;
        $this->stderr = null;
        $this->process = null;
        $this->status = self::STATUS_READY;
        $this->incrementalOutputOffset = 0;
        $this->incrementalErrorOutputOffset = 0;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Exception;

/**
 * InvalidArgumentException for the Process Component.
 *
 * @author Romain Neutron <imprec@gmail.com>
 */
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Exception;

/**
 * RuntimeException for the Process Component.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Exception;

/**
 * LogicException for the Process Component.
 *
 * @author Romain Neutron <imprec@gmail.com>
 */
class LogicException extends \LogicException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Exception;

/**
 * Marker Interface for the Process Component.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Exception;

use Symfony\Component\Process\Process;

/**
 * Exception that is thrown when a process times out.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ProcessTimedOutException extends RuntimeException
{
    const TYPE_GENERAL = 1;
    const TYPE_IDLE = 2;

    private $process;
    private $timeoutType;

    public function __construct(Process $process, $timeoutType)
    {
        $this->process = $process;
        $this->timeoutType = $timeoutType;

        parent::__construct(sprintf(
            'The process "%s" exceeded the timeout of %s seconds.',
            $process->getCommandLine(),
            $this->getExceededTimeout()
        ));
    }

    public function getProcess()
    {
        return $this->process;
    }

    public function isGeneralTimeout()
    {
        return $this->timeoutType === self::TYPE_GENERAL;
    }

    public function isIdleTimeout()
    {
        return $this->timeoutType === self::TYPE_IDLE;
    }

    public function getExceededTimeout()
    {
        switch ($this->timeoutType) {
            case self::TYPE_GENERAL:
                return $this->process->getTimeout();

            case self::TYPE_IDLE:
                return $this->process->getIdleTimeout();

            default:
                throw new \LogicException(sprintf('Unknown timeout type "%d".', $this->timeoutType));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Exception;

use Symfony\Component\Process\Process;

/**
 * Exception for failed processes.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ProcessFailedException extends RuntimeException
{
    private $process;

    public function __construct(Process $process)
    {
        if ($process->isSuccessful()) {
            throw new InvalidArgumentException('Expected a failed process, but the given process was successful.');
        }

        parent::__construct(
            sprintf(
                'The command "%s" failed.'."\nExit Code: %s(%s)\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s",
                $process->getCommandLine(),
                $process->getExitCode(),
                $process->getExitCodeText(),
                $process->getOutput(),
                $process->getErrorOutput()
            )
        );

        $this->process = $process;
    }

    public function getProcess()
    {
        return $this->process;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process;

/**
 * ProcessUtils is a bunch of utility methods.
 *
 * This class contains static methods only and is not meant to be instantiated.
 *
 * @author Martin Hasoň <martin.hason@gmail.com>
 */
class ProcessUtils
{
    /**
     * This class should not be instantiated
     */
    private function __construct()
    {
    }

    /**
     * Escapes a string to be used as a shell argument.
     *
     * @param string $argument The argument that will be escaped
     *
     * @return string The escaped argument
     */
    public static function escapeArgument($argument)
    {
        //Fix for PHP bug #43784 escapeshellarg removes % from given string
        //Fix for PHP bug #49446 escapeshellarg dosn`t work on windows
        //@see https://bugs.php.net/bug.php?id=43784
        //@see https://bugs.php.net/bug.php?id=49446
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            if ('' === $argument) {
                return escapeshellarg($argument);
            }

            $escapedArgument = '';
            foreach (preg_split('/([%"])/i', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
                if ('"' === $part) {
                    $escapedArgument .= '\\"';
                } elseif ('%' === $part) {
                    $escapedArgument .= '^%';
                } else {
                    $escapedArgument .= escapeshellarg($part);
                }
            }

            return $escapedArgument;
        }

        return escapeshellarg($argument);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process;

/**
 * Generic executable finder.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ExecutableFinder
{
    private $suffixes = array('.exe', '.bat', '.cmd', '.com');

    /**
     * Replaces default suffixes of executable.
     *
     * @param array $suffixes
     */
    public function setSuffixes(array $suffixes)
    {
        $this->suffixes = $suffixes;
    }

    /**
     * Adds new possible suffix to check for executable.
     *
     * @param string $suffix
     */
    public function addSuffix($suffix)
    {
        $this->suffixes[] = $suffix;
    }

    /**
     * Finds an executable by name.
     *
     * @param string $name      The executable name (without the extension)
     * @param string $default   The default to return if no executable is found
     * @param array  $extraDirs Additional dirs to check into
     *
     * @return string The executable path or default value
     */
    public function find($name, $default = null, array $extraDirs = array())
    {
        if (ini_get('open_basedir')) {
            $searchPath = explode(PATH_SEPARATOR, getenv('open_basedir'));
            $dirs = array();
            foreach ($searchPath as $path) {
                if (is_dir($path)) {
                    $dirs[] = $path;
                } else {
                    $file = str_replace(dirname($path), '', $path);
                    if ($file == $name && is_executable($path)) {
                        return $path;
                    }
                }
            }
        } else {
            $dirs = array_merge(
                explode(PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')),
                $extraDirs
            );
        }

        $suffixes = array('');
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $pathExt = getenv('PATHEXT');
            $suffixes = $pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes;
        }
        foreach ($suffixes as $suffix) {
            foreach ($dirs as $dir) {
                if (is_file($file = $dir.DIRECTORY_SEPARATOR.$name.$suffix) && (defined('PHP_WINDOWS_VERSION_BUILD') || is_executable($file))) {
                    return $file;
                }
            }
        }

        return $default;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Tests;

use Symfony\Component\Process\Exception\ProcessTimedOutException;
use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\RuntimeException;

/**
 * @author Robert Schönthal <seroscho@googlemail.com>
 */
abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
{
    public function testThatProcessDoesNotThrowWarningDuringRun()
    {
        @trigger_error('Test Error', E_USER_NOTICE);
        $process = $this->getProcess("php -r 'sleep(3)'");
        $process->run();
        $actualError = error_get_last();
        $this->assertEquals('Test Error', $actualError['message']);
        $this->assertEquals(E_USER_NOTICE, $actualError['type']);
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\InvalidArgumentException
     */
    public function testNegativeTimeoutFromConstructor()
    {
        $this->getProcess('', null, null, null, -1);
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\InvalidArgumentException
     */
    public function testNegativeTimeoutFromSetter()
    {
        $p = $this->getProcess('');
        $p->setTimeout(-1);
    }

    public function testFloatAndNullTimeout()
    {
        $p = $this->getProcess('');

        $p->setTimeout(10);
        $this->assertSame(10.0, $p->getTimeout());

        $p->setTimeout(null);
        $this->assertNull($p->getTimeout());

        $p->setTimeout(0.0);
        $this->assertNull($p->getTimeout());
    }

    public function testStopWithTimeoutIsActuallyWorking()
    {
        $this->verifyPosixIsEnabled();

        // exec is mandatory here since we send a signal to the process
        // see https://github.com/symfony/symfony/issues/5030 about prepending
        // command with exec
        $p = $this->getProcess('exec php '.__DIR__.'/NonStopableProcess.php 3');
        $p->start();
        usleep(100000);
        $start = microtime(true);
        $p->stop(1.1, SIGKILL);
        while ($p->isRunning()) {
            usleep(1000);
        }
        $duration = microtime(true) - $start;

        $this->assertLessThan(1.8, $duration);
    }

    public function testCallbacksAreExecutedWithStart()
    {
        $data = '';

        $process = $this->getProcess('echo foo && php -r "sleep(1);" && echo foo');
        $process->start(function ($type, $buffer) use (&$data) {
            $data .= $buffer;
        });

        while ($process->isRunning()) {
            usleep(10000);
        }

        $this->assertEquals(2, preg_match_all('/foo/', $data, $matches));
    }

    /**
     * tests results from sub processes
     *
     * @dataProvider responsesCodeProvider
     */
    public function testProcessResponses($expected, $getter, $code)
    {
        $p = $this->getProcess(sprintf('php -r %s', escapeshellarg($code)));
        $p->run();

        $this->assertSame($expected, $p->$getter());
    }

    /**
     * tests results from sub processes
     *
     * @dataProvider pipesCodeProvider
     */
    public function testProcessPipes($code, $size)
    {
        $expected = str_repeat(str_repeat('*', 1024), $size) . '!';
        $expectedLength = (1024 * $size) + 1;

        $p = $this->getProcess(sprintf('php -r %s', escapeshellarg($code)));
        $p->setStdin($expected);
        $p->run();

        $this->assertEquals($expectedLength, strlen($p->getOutput()));
        $this->assertEquals($expectedLength, strlen($p->getErrorOutput()));
    }

    public function chainedCommandsOutputProvider()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            return array(
                array("2 \r\n2\r\n", '&&', '2')
            );
        }

        return array(
            array("1\n1\n", ';', '1'),
            array("2\n2\n", '&&', '2'),
        );
    }

    /**
     *
     * @dataProvider chainedCommandsOutputProvider
     */
    public function testChainedCommandsOutput($expected, $operator, $input)
    {
        $process = $this->getProcess(sprintf('echo %s %s echo %s', $input, $operator, $input));
        $process->run();
        $this->assertEquals($expected, $process->getOutput());
    }

    public function testCallbackIsExecutedForOutput()
    {
        $p = $this->getProcess(sprintf('php -r %s', escapeshellarg('echo \'foo\';')));

        $called = false;
        $p->run(function ($type, $buffer) use (&$called) {
            $called = $buffer === 'foo';
        });

        $this->assertTrue($called, 'The callback should be executed with the output');
    }

    public function testGetErrorOutput()
    {
        $p = new Process(sprintf('php -r %s', escapeshellarg('$n = 0; while ($n < 3) { file_put_contents(\'php://stderr\', \'ERROR\'); $n++; }')));

        $p->run();
        $this->assertEquals(3, preg_match_all('/ERROR/', $p->getErrorOutput(), $matches));
    }

    public function testGetIncrementalErrorOutput()
    {
        $p = new Process(sprintf('php -r %s', escapeshellarg('$n = 0; while ($n < 3) { usleep(50000); file_put_contents(\'php://stderr\', \'ERROR\'); $n++; }')));

        $p->start();
        while ($p->isRunning()) {
            $this->assertLessThanOrEqual(1, preg_match_all('/ERROR/', $p->getIncrementalErrorOutput(), $matches));
            usleep(20000);
        }
    }

    public function testFlushErrorOutput()
    {
        $p = new Process(sprintf('php -r %s', escapeshellarg('$n = 0; while ($n < 3) { file_put_contents(\'php://stderr\', \'ERROR\'); $n++; }')));

        $p->run();
        $p->clearErrorOutput();
        $this->assertEmpty($p->getErrorOutput());
    }

    public function testGetOutput()
    {
        $p = new Process(sprintf('php -r %s', escapeshellarg('$n=0;while ($n<3) {echo \' foo \';$n++; usleep(500); }')));

        $p->run();
        $this->assertEquals(3, preg_match_all('/foo/', $p->getOutput(), $matches));
    }

    public function testGetIncrementalOutput()
    {
        $p = new Process(sprintf('php -r %s', escapeshellarg('$n=0;while ($n<3) { echo \' foo \'; usleep(50000); $n++; }')));

        $p->start();
        while ($p->isRunning()) {
            $this->assertLessThanOrEqual(1, preg_match_all('/foo/', $p->getIncrementalOutput(), $matches));
            usleep(20000);
        }
    }

    public function testFlushOutput()
    {
        $p = new Process(sprintf('php -r %s', escapeshellarg('$n=0;while ($n<3) {echo \' foo \';$n++;}')));

        $p->run();
        $p->clearOutput();
        $this->assertEmpty($p->getOutput());
    }

    public function testExitCodeCommandFailed()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('Windows does not support POSIX exit code');
        }

        // such command run in bash return an exitcode 127
        $process = $this->getProcess('nonexistingcommandIhopeneversomeonewouldnameacommandlikethis');
        $process->run();

        $this->assertGreaterThan(0, $process->getExitCode());
    }

    public function testTTYCommand()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('Windows does have /dev/tty support');
        }

        $process = $this->getProcess('echo "foo" >> /dev/null');
        $process->setTTY(true);
        $process->run();

        $this->assertSame(Process::STATUS_TERMINATED, $process->getStatus());
    }

    public function testExitCodeText()
    {
        $process = $this->getProcess('');
        $r = new \ReflectionObject($process);
        $p = $r->getProperty('exitcode');
        $p->setAccessible(true);

        $p->setValue($process, 2);
        $this->assertEquals('Misuse of shell builtins', $process->getExitCodeText());
    }

    public function testStartIsNonBlocking()
    {
        $process = $this->getProcess('php -r "sleep(4);"');
        $start = microtime(true);
        $process->start();
        $end = microtime(true);
        $this->assertLessThan(1 , $end-$start);
    }

    public function testUpdateStatus()
    {
        $process = $this->getProcess('php -h');
        $process->run();
        $this->assertTrue(strlen($process->getOutput()) > 0);
    }

    public function testGetExitCodeIsNullOnStart()
    {
        $process = $this->getProcess('php -r "usleep(200000);"');
        $this->assertNull($process->getExitCode());
        $process->start();
        $this->assertNull($process->getExitCode());
        $process->wait();
        $this->assertEquals(0, $process->getExitCode());
    }

    public function testGetExitCodeIsNullOnWhenStartingAgain()
    {
        $process = $this->getProcess('php -r "usleep(200000);"');
        $process->run();
        $this->assertEquals(0, $process->getExitCode());
        $process->start();
        $this->assertNull($process->getExitCode());
        $process->wait();
        $this->assertEquals(0, $process->getExitCode());
    }

    public function testGetExitCode()
    {
        $process = $this->getProcess('php -m');
        $process->run();
        $this->assertEquals(0, $process->getExitCode());
    }

    public function testStatus()
    {
        $process = $this->getProcess('php -r "usleep(500000);"');
        $this->assertFalse($process->isRunning());
        $this->assertFalse($process->isStarted());
        $this->assertFalse($process->isTerminated());
        $this->assertSame(Process::STATUS_READY, $process->getStatus());
        $process->start();
        $this->assertTrue($process->isRunning());
        $this->assertTrue($process->isStarted());
        $this->assertFalse($process->isTerminated());
        $this->assertSame(Process::STATUS_STARTED, $process->getStatus());
        $process->wait();
        $this->assertFalse($process->isRunning());
        $this->assertTrue($process->isStarted());
        $this->assertTrue($process->isTerminated());
        $this->assertSame(Process::STATUS_TERMINATED, $process->getStatus());
    }

    public function testStop()
    {
        $process = $this->getProcess('php -r "sleep(4);"');
        $process->start();
        $this->assertTrue($process->isRunning());
        $process->stop();
        $this->assertFalse($process->isRunning());
    }

    public function testIsSuccessful()
    {
        $process = $this->getProcess('php -m');
        $process->run();
        $this->assertTrue($process->isSuccessful());
    }

    public function testIsSuccessfulOnlyAfterTerminated()
    {
        $process = $this->getProcess('php -r "sleep(1);"');
        $process->start();
        while ($process->isRunning()) {
            $this->assertFalse($process->isSuccessful());
            usleep(300000);
        }

        $this->assertTrue($process->isSuccessful());
    }

    public function testIsNotSuccessful()
    {
        $process = $this->getProcess('php -r "sleep(4);"');
        $process->start();
        $this->assertTrue($process->isRunning());
        $process->stop();
        $this->assertFalse($process->isSuccessful());
    }

    public function testProcessIsNotSignaled()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('Windows does not support POSIX signals');
        }

        $process = $this->getProcess('php -m');
        $process->run();
        $this->assertFalse($process->hasBeenSignaled());
    }

    public function testProcessWithoutTermSignalIsNotSignaled()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('Windows does not support POSIX signals');
        }

        $process = $this->getProcess('php -m');
        $process->run();
        $this->assertFalse($process->hasBeenSignaled());
    }

    public function testProcessWithoutTermSignal()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('Windows does not support POSIX signals');
        }

        $process = $this->getProcess('php -m');
        $process->run();
        $this->assertEquals(0, $process->getTermSignal());
    }

    public function testProcessIsSignaledIfStopped()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('Windows does not support POSIX signals');
        }

        $process = $this->getProcess('php -r "sleep(4);"');
        $process->start();
        $process->stop();
        $this->assertTrue($process->hasBeenSignaled());
    }

    public function testProcessWithTermSignal()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('Windows does not support POSIX signals');
        }

        // SIGTERM is only defined if pcntl extension is present
        $termSignal = defined('SIGTERM') ? SIGTERM : 15;

        $process = $this->getProcess('php -r "sleep(4);"');
        $process->start();
        $process->stop();

        $this->assertEquals($termSignal, $process->getTermSignal());
    }

    public function testProcessThrowsExceptionWhenExternallySignaled()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('Windows does not support POSIX signals');
        }

        if (!function_exists('posix_kill')) {
            $this->markTestSkipped('posix_kill is required for this test');
        }

        $termSignal = defined('SIGKILL') ? SIGKILL : 9;

        $process = $this->getProcess('exec php -r "while (true) {}"');
        $process->start();
        posix_kill($process->getPid(), $termSignal);

        $this->setExpectedException('Symfony\Component\Process\Exception\RuntimeException', 'The process has been signaled with signal "9".');
        $process->wait();
    }

    public function testRestart()
    {
        $process1 = $this->getProcess('php -r "echo getmypid();"');
        $process1->run();
        $process2 = $process1->restart();

        usleep(300000); // wait for output

        // Ensure that both processed finished and the output is numeric
        $this->assertFalse($process1->isRunning());
        $this->assertFalse($process2->isRunning());
        $this->assertTrue(is_numeric($process1->getOutput()));
        $this->assertTrue(is_numeric($process2->getOutput()));

        // Ensure that restart returned a new process by check that the output is different
        $this->assertNotEquals($process1->getOutput(), $process2->getOutput());
    }

    public function testPhpDeadlock()
    {
        $this->markTestSkipped('Can course php to hang');

        // Sleep doesn't work as it will allow the process to handle signals and close
        // file handles from the other end.
        $process = $this->getProcess('php -r "while (true) {}"');
        $process->start();

        // PHP will deadlock when it tries to cleanup $process
    }

    public function testRunProcessWithTimeout()
    {
        $timeout = 0.5;
        $process = $this->getProcess('php -r "sleep(3);"');
        $process->setTimeout($timeout);
        $start = microtime(true);
        try {
            $process->run();
            $this->fail('A RuntimeException should have been raised');
        } catch (RuntimeException $e) {

        }
        $duration = microtime(true) - $start;

        $this->assertLessThan($timeout + Process::TIMEOUT_PRECISION, $duration);
    }

    public function testCheckTimeoutOnStartedProcess()
    {
        $timeout = 0.5;
        $precision = 100000;
        $process = $this->getProcess('php -r "sleep(3);"');
        $process->setTimeout($timeout);
        $start = microtime(true);

        $process->start();

        try {
            while ($process->isRunning()) {
                $process->checkTimeout();
                usleep($precision);
            }
            $this->fail('A RuntimeException should have been raised');
        } catch (RuntimeException $e) {

        }
        $duration = microtime(true) - $start;

        $this->assertLessThan($timeout + $precision, $duration);
        $this->assertFalse($process->isSuccessful());
    }

    /**
     * @group idle-timeout
     */
    public function testIdleTimeout()
    {
        $process = $this->getProcess('sleep 3');
        $process->setTimeout(10);
        $process->setIdleTimeout(1);

        try {
            $process->run();

            $this->fail('A timeout exception was expected.');
        } catch (ProcessTimedOutException $ex) {
            $this->assertTrue($ex->isIdleTimeout());
            $this->assertFalse($ex->isGeneralTimeout());
            $this->assertEquals(1.0, $ex->getExceededTimeout());
        }
    }

    /**
     * @group idle-timeout
     */
    public function testIdleTimeoutNotExceededWhenOutputIsSent()
    {
        $process = $this->getProcess('echo "foo" && sleep 1 && echo "foo" && sleep 1 && echo "foo" && sleep 1 && echo "foo" && sleep 5');
        $process->setTimeout(5);
        $process->setIdleTimeout(3);

        try {
            $process->run();
            $this->fail('A timeout exception was expected.');
        } catch (ProcessTimedOutException $ex) {
            $this->assertTrue($ex->isGeneralTimeout());
            $this->assertFalse($ex->isIdleTimeout());
            $this->assertEquals(5.0, $ex->getExceededTimeout());
        }
    }

    public function testStartAfterATimeout()
    {
        $process = $this->getProcess('php -r "while (true) {echo \'\'; usleep(1000); }"');
        $process->setTimeout(0.1);
        try {
            $process->run();
            $this->fail('An exception should have been raised.');
        } catch (\Exception $e) {

        }
        $process->start();
        usleep(10000);
        $process->stop();
    }

    public function testGetPid()
    {
        $process = $this->getProcess('php -r "sleep(1);"');
        $process->start();
        $this->assertGreaterThan(0, $process->getPid());
        $process->stop();
    }

    public function testGetPidIsNullBeforeStart()
    {
        $process = $this->getProcess('php -r "sleep(1);"');
        $this->assertNull($process->getPid());
    }

    public function testGetPidIsNullAfterRun()
    {
        $process = $this->getProcess('php -m');
        $process->run();
        $this->assertNull($process->getPid());
    }

    public function testSignal()
    {
        $this->verifyPosixIsEnabled();

        $process = $this->getProcess('exec php -f ' . __DIR__ . '/SignalListener.php');
        $process->start();
        usleep(500000);
        $process->signal(SIGUSR1);

        while ($process->isRunning() && false === strpos($process->getoutput(), 'Caught SIGUSR1')) {
            usleep(10000);
        }

        $this->assertEquals('Caught SIGUSR1', $process->getOutput());
    }

    public function testExitCodeIsAvailableAfterSignal()
    {
        $this->verifyPosixIsEnabled();

        $process = $this->getProcess('sleep 4');
        $process->start();
        $process->signal(SIGKILL);

        while ($process->isRunning()) {
            usleep(10000);
        }

        $this->assertFalse($process->isRunning());
        $this->assertTrue($process->hasBeenSignaled());
        $this->assertFalse($process->isSuccessful());
        $this->assertEquals(137, $process->getExitCode());
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\LogicException
     */
    public function testSignalProcessNotRunning()
    {
        $this->verifyPosixIsEnabled();
        $process = $this->getProcess('php -m');
        $process->signal(SIGHUP);
    }

    private function verifyPosixIsEnabled()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('POSIX signals do not work on windows');
        }
        if (!defined('SIGUSR1')) {
            $this->markTestSkipped('The pcntl extension is not enabled');
        }
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testSignalWithWrongIntSignal()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('POSIX signals do not work on windows');
        }

        $process = $this->getProcess('php -r "sleep(3);"');
        $process->start();
        $process->signal(-4);
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testSignalWithWrongNonIntSignal()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('POSIX signals do not work on windows');
        }

        $process = $this->getProcess('php -r "sleep(3);"');
        $process->start();
        $process->signal('Céphalopodes');
    }

    public function responsesCodeProvider()
    {
        return array(
            //expected output / getter / code to execute
            //array(1,'getExitCode','exit(1);'),
            //array(true,'isSuccessful','exit();'),
            array('output', 'getOutput', 'echo \'output\';'),
        );
    }

    public function pipesCodeProvider()
    {
        $variations = array(
            'fwrite(STDOUT, $in = file_get_contents(\'php://stdin\')); fwrite(STDERR, $in);',
            'include \''.__DIR__.'/PipeStdinInStdoutStdErrStreamSelect.php\';',
        );

        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            // Avoid XL buffers on Windows because of https://bugs.php.net/bug.php?id=65650
            $sizes = array(1, 2, 4, 8);
        } else {
            $sizes = array(1, 16, 64, 1024, 4096);
        }

        $codes = array();
        foreach ($sizes as $size) {
            foreach ($variations as $code) {
                $codes[] = array($code, $size);
            }
        }

        return $codes;
    }

    /**
     * provides default method names for simple getter/setter
     */
    public function methodProvider()
    {
        $defaults = array(
            array('CommandLine'),
            array('Timeout'),
            array('WorkingDirectory'),
            array('Env'),
            array('Stdin'),
            array('Options')
        );

        return $defaults;
    }

    /**
     * @param string  $commandline
     * @param null    $cwd
     * @param array   $env
     * @param null    $stdin
     * @param integer $timeout
     * @param array   $options
     *
     * @return Process
     */
    abstract protected function getProcess($commandline, $cwd = null, array $env = null, $stdin = null, $timeout = 60, array $options = array());
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Tests;

use Symfony\Component\Process\ProcessBuilder;

class ProcessBuilderTest extends \PHPUnit_Framework_TestCase
{
    public function testInheritEnvironmentVars()
    {
        $_ENV['MY_VAR_1'] = 'foo';

        $proc = ProcessBuilder::create()
            ->add('foo')
            ->getProcess();

        unset($_ENV['MY_VAR_1']);

        $env = $proc->getEnv();
        $this->assertArrayHasKey('MY_VAR_1', $env);
        $this->assertEquals('foo', $env['MY_VAR_1']);
    }

    public function testAddEnvironmentVariables()
    {
        $pb = new ProcessBuilder();
        $env = array(
            'foo' => 'bar',
            'foo2' => 'bar2',
        );
        $proc = $pb
            ->add('command')
            ->setEnv('foo', 'bar2')
            ->addEnvironmentVariables($env)
            ->inheritEnvironmentVariables(false)
            ->getProcess()
        ;

        $this->assertSame($env, $proc->getEnv());
    }

    public function testProcessShouldInheritAndOverrideEnvironmentVars()
    {
        $_ENV['MY_VAR_1'] = 'foo';

        $proc = ProcessBuilder::create()
            ->setEnv('MY_VAR_1', 'bar')
            ->add('foo')
            ->getProcess();

        unset($_ENV['MY_VAR_1']);

        $env = $proc->getEnv();
        $this->assertArrayHasKey('MY_VAR_1', $env);
        $this->assertEquals('bar', $env['MY_VAR_1']);
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\InvalidArgumentException
     */
    public function testNegativeTimeoutFromSetter()
    {
        $pb = new ProcessBuilder();
        $pb->setTimeout(-1);
    }

    public function testNullTimeout()
    {
        $pb = new ProcessBuilder();
        $pb->setTimeout(10);
        $pb->setTimeout(null);

        $r = new \ReflectionObject($pb);
        $p = $r->getProperty('timeout');
        $p->setAccessible(true);

        $this->assertNull($p->getValue($pb));
    }

    public function testShouldSetArguments()
    {
        $pb = new ProcessBuilder(array('initial'));
        $pb->setArguments(array('second'));

        $proc = $pb->getProcess();

        $this->assertContains("second", $proc->getCommandLine());
    }

    public function testPrefixIsPrependedToAllGeneratedProcess()
    {
        $pb = new ProcessBuilder();
        $pb->setPrefix('/usr/bin/php');

        $proc = $pb->setArguments(array('-v'))->getProcess();
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->assertEquals('"/usr/bin/php" "-v"', $proc->getCommandLine());
        } else {
            $this->assertEquals("'/usr/bin/php' '-v'", $proc->getCommandLine());
        }

        $proc = $pb->setArguments(array('-i'))->getProcess();
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->assertEquals('"/usr/bin/php" "-i"', $proc->getCommandLine());
        } else {
            $this->assertEquals("'/usr/bin/php' '-i'", $proc->getCommandLine());
        }
    }

    public function testArrayPrefixesArePrependedToAllGeneratedProcess()
    {
        $pb = new ProcessBuilder();
        $pb->setPrefix(array('/usr/bin/php', 'composer.phar'));

        $proc = $pb->setArguments(array('-v'))->getProcess();
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->assertEquals('"/usr/bin/php" "composer.phar" "-v"', $proc->getCommandLine());
        } else {
            $this->assertEquals("'/usr/bin/php' 'composer.phar' '-v'", $proc->getCommandLine());
        }

        $proc = $pb->setArguments(array('-i'))->getProcess();
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->assertEquals('"/usr/bin/php" "composer.phar" "-i"', $proc->getCommandLine());
        } else {
            $this->assertEquals("'/usr/bin/php' 'composer.phar' '-i'", $proc->getCommandLine());
        }
    }

    public function testShouldEscapeArguments()
    {
        $pb = new ProcessBuilder(array('%path%', 'foo " bar'));
        $proc = $pb->getProcess();

        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->assertSame('^%"path"^% "foo "\\"" bar"', $proc->getCommandLine());
        } else {
            $this->assertSame("'%path%' 'foo \" bar'", $proc->getCommandLine());
        }
    }

    public function testShouldEscapeArgumentsAndPrefix()
    {
        $pb = new ProcessBuilder(array('arg'));
        $pb->setPrefix('%prefix%');
        $proc = $pb->getProcess();

        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->assertSame('^%"prefix"^% "arg"', $proc->getCommandLine());
        } else {
            $this->assertSame("'%prefix%' 'arg'", $proc->getCommandLine());
        }
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\LogicException
     */
    public function testShouldThrowALogicExceptionIfNoPrefixAndNoArgument()
    {
        ProcessBuilder::create()->getProcess();
    }

    public function testShouldNotThrowALogicExceptionIfNoArgument()
    {
        $process = ProcessBuilder::create()
            ->setPrefix('/usr/bin/php')
            ->getProcess();

        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->assertEquals('"/usr/bin/php"', $process->getCommandLine());
        } else {
            $this->assertEquals("'/usr/bin/php'", $process->getCommandLine());
        }
    }

    public function testShouldNotThrowALogicExceptionIfNoPrefix()
    {
        $process = ProcessBuilder::create(array('/usr/bin/php'))
            ->getProcess();

        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->assertEquals('"/usr/bin/php"', $process->getCommandLine());
        } else {
            $this->assertEquals("'/usr/bin/php'", $process->getCommandLine());
        }
    }
}
<?php

/**
 * Runs a PHP script that can be stopped only with a SIGKILL (9) signal for 3 seconds
 *
 * @args duration Run this script with a custom duration
 *
 * @example `php NonStopableProcess.php 42` will run the script for 42 seconds
 */

function handleSignal($signal)
{
    switch ($signal) {
        case SIGTERM:
            $name = 'SIGTERM';
            break;
        case SIGINT:
            $name = 'SIGINT';
            break;
        default:
            $name = $signal . ' (unknown)';
            break;
    }

    echo "received signal $name\n";
}

declare(ticks=1);
pcntl_signal(SIGTERM, 'handleSignal');
pcntl_signal(SIGINT, 'handleSignal');

$duration = isset($argv[1]) ? (int) $argv[1] : 3;
$start = microtime(true);

while ($duration > (microtime(true) - $start)) {
    usleep(1000);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Tests;

class SigchildDisabledProcessTest extends AbstractProcessTest
{
    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testGetExitCode()
    {
        parent::testGetExitCode();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testGetExitCodeIsNullOnStart()
    {
        parent::testGetExitCodeIsNullOnStart();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testGetExitCodeIsNullOnWhenStartingAgain()
    {
        parent::testGetExitCodeIsNullOnWhenStartingAgain();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testExitCodeCommandFailed()
    {
        parent::testExitCodeCommandFailed();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testProcessIsSignaledIfStopped()
    {
        parent::testProcessIsSignaledIfStopped();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testProcessWithTermSignal()
    {
        parent::testProcessWithTermSignal();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testProcessIsNotSignaled()
    {
        parent::testProcessIsNotSignaled();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testProcessWithoutTermSignal()
    {
        parent::testProcessWithoutTermSignal();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testCheckTimeoutOnStartedProcess()
    {
        parent::testCheckTimeoutOnStartedProcess();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testGetPid()
    {
        parent::testGetPid();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testGetPidIsNullBeforeStart()
    {
        parent::testGetPidIsNullBeforeStart();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testGetPidIsNullAfterRun()
    {
        parent::testGetPidIsNullAfterRun();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testExitCodeText()
    {
        $process = $this->getProcess('qdfsmfkqsdfmqmsd');
        $process->run();

        $process->getExitCodeText();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testIsSuccessful()
    {
        parent::testIsSuccessful();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testIsSuccessfulOnlyAfterTerminated()
    {
        parent::testIsSuccessfulOnlyAfterTerminated();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testIsNotSuccessful()
    {
        parent::testIsNotSuccessful();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testSignal()
    {
        parent::testSignal();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testProcessWithoutTermSignalIsNotSignaled()
    {
        parent::testProcessWithoutTermSignalIsNotSignaled();
    }

    public function testStopWithTimeoutIsActuallyWorking()
    {
        $this->markTestSkipped('Stopping with signal is not supported in sigchild environment');
    }

    public function testProcessThrowsExceptionWhenExternallySignaled()
    {
        $this->markTestSkipped('Retrieving Pid is not supported in sigchild environment');
    }

    public function testExitCodeIsAvailableAfterSignal()
    {
        $this->markTestSkipped('Signal is not supported in sigchild environment');
    }

    /**
     * {@inheritdoc}
     */
    protected function getProcess($commandline, $cwd = null, array $env = null, $stdin = null, $timeout = 60, array $options = array())
    {
        $process = new ProcessInSigchildEnvironment($commandline, $cwd, $env, $stdin, $timeout, $options);
        $process->setEnhanceSigchildCompatibility(false);

        return $process;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Tests;

use Symfony\Component\Process\PhpExecutableFinder;

/**
 * @author Robert Schönthal <seroscho@googlemail.com>
 */
class PhpExecutableFinderTest extends \PHPUnit_Framework_TestCase
{
    /**
     * tests find() with the env var PHP_PATH
     */
    public function testFindWithPhpPath()
    {
        if (defined('PHP_BINARY')) {
            $this->markTestSkipped('The PHP binary is easily available as of PHP 5.4');
        }

        $f = new PhpExecutableFinder();

        $current = $f->find();

        //not executable PHP_PATH
        putenv('PHP_PATH=/not/executable/php');
        $this->assertFalse($f->find(), '::find() returns false for not executable php');

        //executable PHP_PATH
        putenv('PHP_PATH='.$current);
        $this->assertEquals($f->find(), $current, '::find() returns the executable php');
    }

    /**
     * tests find() with default executable
     */
    public function testFindWithSuffix()
    {
        if (defined('PHP_BINARY')) {
            $this->markTestSkipped('The PHP binary is easily available as of PHP 5.4');
        }

        putenv('PHP_PATH=');
        putenv('PHP_PEAR_PHP_BIN=');
        $f = new PhpExecutableFinder();

        $current = $f->find();

        //TODO maybe php executable is custom or even windows
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->assertTrue(is_executable($current));
            $this->assertTrue((bool) preg_match('/'.addSlashes(DIRECTORY_SEPARATOR).'php\.(exe|bat|cmd|com)$/i', $current), '::find() returns the executable php with suffixes');
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Tests;

use Symfony\Component\Process\PhpProcess;

class PhpProcessTest extends \PHPUnit_Framework_TestCase
{
    public function testNonBlockingWorks()
    {
        $expected = 'hello world!';
        $process = new PhpProcess(<<<PHP
<?php echo '$expected';
PHP
        );
        $process->start();
        $process->wait();
        $this->assertEquals($expected, $process->getOutput());
    }
}
<?php

// required for signal handling
declare(ticks = 1);

pcntl_signal(SIGUSR1, function(){echo "Caught SIGUSR1"; exit;});

$n=0;

// ticks require activity to work - sleep(4); does not work
while ($n < 400) {
    usleep(10000);
    $n++;
}

return;
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Tests;

use Symfony\Component\Process\ProcessUtils;

class ProcessUtilsTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider dataArguments
     */
    public function testEscapeArgument($result, $argument)
    {
        $this->assertSame($result, ProcessUtils::escapeArgument($argument));
    }

    public function dataArguments()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            return array(
                array('"foo bar"', 'foo bar'),
                array('^%"path"^%', '%path%'),
                array('"<|>"\\"" "\\""\'f"', '<|>" "\'f'),
                array('""', ''),
            );
        }

        return array(
            array("'foo bar'", 'foo bar'),
            array("'%path%'", '%path%'),
            array("'<|>\" \"'\\''f'", '<|>" "\'f'),
            array("''", ''),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Tests;

use Symfony\Component\Process\Exception\ProcessFailedException;

/**
 * @author Sebastian Marek <proofek@gmail.com>
 */
class ProcessFailedExceptionTest extends \PHPUnit_Framework_TestCase
{
    /**
     * tests ProcessFailedException throws exception if the process was successful
     */
    public function testProcessFailedExceptionThrowsException()
    {
        $process = $this->getMock(
            'Symfony\Component\Process\Process',
            array('isSuccessful'),
            array('php')
        );
        $process->expects($this->once())
            ->method('isSuccessful')
            ->will($this->returnValue(true));

        $this->setExpectedException(
            '\InvalidArgumentException',
            'Expected a failed process, but the given process was successful.'
        );

        new ProcessFailedException($process);
    }

    /**
     * tests ProcessFailedException uses information from process output
     * to generate exception message
     */
    public function testProcessFailedExceptionPopulatesInformationFromProcessOutput()
    {
        $cmd = 'php';
        $exitCode = 1;
        $exitText = 'General error';
        $output = "Command output";
        $errorOutput = "FATAL: Unexpected error";

        $process = $this->getMock(
            'Symfony\Component\Process\Process',
            array('isSuccessful', 'getOutput', 'getErrorOutput', 'getExitCode', 'getExitCodeText'),
            array($cmd)
        );
        $process->expects($this->once())
            ->method('isSuccessful')
            ->will($this->returnValue(false));
        $process->expects($this->once())
            ->method('getOutput')
            ->will($this->returnValue($output));
        $process->expects($this->once())
            ->method('getErrorOutput')
            ->will($this->returnValue($errorOutput));
        $process->expects($this->once())
            ->method('getExitCode')
            ->will($this->returnValue($exitCode));
        $process->expects($this->once())
            ->method('getExitCodeText')
            ->will($this->returnValue($exitText));

        $exception = new ProcessFailedException($process);

        $this->assertEquals(
            "The command \"$cmd\" failed.\nExit Code: $exitCode($exitText)\n\nOutput:\n================\n{$output}\n\nError Output:\n================\n{$errorOutput}",
            $exception->getMessage()
        );
    }
}
<?php

define('ERR_SELECT_FAILED', 1);
define('ERR_TIMEOUT', 2);
define('ERR_READ_FAILED', 3);
define('ERR_WRITE_FAILED', 4);

$read = array(STDIN);
$write = array(STDOUT, STDERR);

stream_set_blocking(STDIN, 0);
stream_set_blocking(STDOUT, 0);
stream_set_blocking(STDERR, 0);

$out = $err = '';
while ($read || $write) {
    $r = $read;
    $w = $write;
    $e = null;
    $n = stream_select($r, $w, $e, 5);

    if (false === $n) {
        die(ERR_SELECT_FAILED);
    } elseif ($n < 1) {
        die(ERR_TIMEOUT);
    }

    if (in_array(STDOUT, $w) && strlen($out) > 0) {
         $written = fwrite(STDOUT, (binary) $out, 32768);
         if (false === $written) {
             die(ERR_WRITE_FAILED);
         }
         $out = (binary) substr($out, $written);
    }
    if (null === $read && strlen($out) < 1) {
        $write = array_diff($write, array(STDOUT));
    }

    if (in_array(STDERR, $w) && strlen($err) > 0) {
         $written = fwrite(STDERR, (binary) $err, 32768);
         if (false === $written) {
             die(ERR_WRITE_FAILED);
         }
         $err = (binary) substr($err, $written);
    }
    if (null === $read && strlen($err) < 1) {
        $write = array_diff($write, array(STDERR));
    }

    if ($r) {
        $str = fread(STDIN, 32768);
        if (false !== $str) {
            $out .= $str;
            $err .= $str;
        }
        if (false === $str || feof(STDIN)) {
            $read = null;
            if (!feof(STDIN)) {
                die(ERR_READ_FAILED);
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Tests;

use Symfony\Component\Process\Process;

class ProcessInSigchildEnvironment extends Process
{
    protected function isSigchildEnabled()
    {
        return true;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Tests;

use Symfony\Component\Process\Process;

class SimpleProcessTest extends AbstractProcessTest
{
    private $enabledSigchild = false;

    public function setUp()
    {
        ob_start();
        phpinfo(INFO_GENERAL);

        $this->enabledSigchild = false !== strpos(ob_get_clean(), '--enable-sigchild');
    }

    public function testGetExitCode()
    {
        $this->skipIfPHPSigchild();
        parent::testGetExitCode();
    }

    public function testExitCodeCommandFailed()
    {
        $this->skipIfPHPSigchild();
        parent::testExitCodeCommandFailed();
    }

    public function testProcessIsSignaledIfStopped()
    {
        $this->skipIfPHPSigchild();
        parent::testProcessIsSignaledIfStopped();
    }

    public function testProcessWithTermSignal()
    {
        $this->skipIfPHPSigchild();
        parent::testProcessWithTermSignal();
    }

    public function testProcessIsNotSignaled()
    {
        $this->skipIfPHPSigchild();
        parent::testProcessIsNotSignaled();
    }

    public function testProcessWithoutTermSignal()
    {
        $this->skipIfPHPSigchild();
        parent::testProcessWithoutTermSignal();
    }

    public function testExitCodeText()
    {
        $this->skipIfPHPSigchild();
        parent::testExitCodeText();
    }

    public function testIsSuccessful()
    {
        $this->skipIfPHPSigchild();
        parent::testIsSuccessful();
    }

    public function testIsNotSuccessful()
    {
        $this->skipIfPHPSigchild();
        parent::testIsNotSuccessful();
    }

    public function testGetPid()
    {
        $this->skipIfPHPSigchild();
        parent::testGetPid();
    }

    public function testGetPidIsNullBeforeStart()
    {
        $this->skipIfPHPSigchild();
        parent::testGetPidIsNullBeforeStart();
    }

    public function testGetPidIsNullAfterRun()
    {
        $this->skipIfPHPSigchild();
        parent::testGetPidIsNullAfterRun();
    }

    public function testSignal()
    {
        $this->skipIfPHPSigchild();
        parent::testSignal();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\LogicException
     */
    public function testSignalProcessNotRunning()
    {
        $this->skipIfPHPSigchild();
        parent::testSignalProcessNotRunning();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testSignalWithWrongIntSignal()
    {
        $this->skipIfPHPSigchild();
        parent::testSignalWithWrongIntSignal();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testSignalWithWrongNonIntSignal()
    {
        $this->skipIfPHPSigchild();
        parent::testSignalWithWrongNonIntSignal();
    }

    /**
     * {@inheritdoc}
     */
    protected function getProcess($commandline, $cwd = null, array $env = null, $stdin = null, $timeout = 60, array $options = array())
    {
        return new Process($commandline, $cwd, $env, $stdin, $timeout, $options);
    }

    private function skipIfPHPSigchild()
    {
        if ($this->enabledSigchild) {
            $this->markTestSkipped('Your PHP has been compiled with --enable-sigchild, this test can not be executed');
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Process\Tests;

class SigchildEnabledProcessTest extends AbstractProcessTest
{
    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testProcessIsSignaledIfStopped()
    {
        parent::testProcessIsSignaledIfStopped();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testProcessWithTermSignal()
    {
        parent::testProcessWithTermSignal();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testProcessIsNotSignaled()
    {
        parent::testProcessIsNotSignaled();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testProcessWithoutTermSignal()
    {
        parent::testProcessWithoutTermSignal();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testGetPid()
    {
        parent::testGetPid();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testGetPidIsNullBeforeStart()
    {
        parent::testGetPidIsNullBeforeStart();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testGetPidIsNullAfterRun()
    {
        parent::testGetPidIsNullAfterRun();
    }

    public function testExitCodeText()
    {
        $process = $this->getProcess('qdfsmfkqsdfmqmsd');
        $process->run();

        $this->assertInternalType('string', $process->getExitCodeText());
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testSignal()
    {
        parent::testSignal();
    }

    /**
     * @expectedException \Symfony\Component\Process\Exception\RuntimeException
     */
    public function testProcessWithoutTermSignalIsNotSignaled()
    {
        parent::testProcessWithoutTermSignalIsNotSignaled();
    }

    public function testProcessThrowsExceptionWhenExternallySignaled()
    {
        $this->markTestSkipped('Retrieving Pid is not supported in sigchild environment');
    }

    public function testExitCodeIsAvailableAfterSignal()
    {
        $this->markTestSkipped('Signal is not supported in sigchild environment');
    }

    /**
     * {@inheritdoc}
     */
    protected function getProcess($commandline, $cwd = null, array $env = null, $stdin = null, $timeout = 60, array $options = array())
    {
        $process = new ProcessInSigchildEnvironment($commandline, $cwd, $env, $stdin, $timeout, $options);
        $process->setEnhanceSigchildCompatibility(true);

        return $process;
    }
}
{
    "name": "symfony/console",
    "type": "library",
    "description": "Symfony Console Component",
    "keywords": [],
    "homepage": "http://symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "http://symfony.com/contributors"
        }
    ],
    "require": {
        "php": ">=5.3.3"
    },
    "require-dev": {
        "symfony/event-dispatcher": "~2.1"
    },
    "suggest": {
        "symfony/event-dispatcher": ""
    },
    "autoload": {
        "psr-0": { "Symfony\\Component\\Console\\": "" }
    },
    "target-dir": "Symfony/Component/Console",
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-master": "2.4-dev"
        }
    }
}
MZ                @                                       	!L!This program cannot be run in DOS mode.
$       ,;B;B;B2מ:B2-B2ƞ9B2ў?Ba98B;CB2Ȟ:B2֞:B2Ӟ:BRich;B        PE  L MoO         	  
         8           @                      `     ?   @                           "  P    @                      P  p   !                             8!  @                                          .text   	      
                    `.rdata  	       
                 @  @.data      0                    @  .rsrc       @                    @  @.reloc     P      "              @  B                                                                                                                                                                                                                                                                                                                                                        j$@ x  j @ e EPV  @ EЃPV @ MX @ e EP5H @ L @ YY5\ @ EP5` @ D @ YYP @ MMT @ 3H  ; 0@ u  h@   l3@ $40@ 5h3@ 40@ h$0@ h(0@ h 0@  @ 00@ }j  Yjh"@   3ۉ]d   p]俀3@ SVW0 @ ;t;u3Fuh  4 @ 3F|3@ ;u
j\  Y;|3@ u,5|3@ h @ h @   YYtE      5<0@ |3@ ;uh @ h @ l  YY|3@    9]uSW8 @ 93@ th3@   Yt
SjS3@ $0@  @ 5$0@ 5(0@ 5 0@ 80@ 9,0@ u7P @ E	MPQ  YYËeE80@ 39,0@ uPh @ 9<0@ u @ E80@   øMZ  f9  @ t3M< @   @ 8PE  uH  t  uՃ   v39   xtv39   j,0@ p @ jl @ YY3@ 3@  @ t3@  @ p3@  @  x3@ V    =0@  uh@  @ Yg  =0@ u	j @ Y3{  U(  H1@ D1@ @1@ <1@ 581@ =41@ f`1@ fT1@ f01@ f,1@ f%(1@ f-$1@ X1@ E L1@ EP1@ E\1@ 0@   P1@ L0@ @0@ 	 D0@     0@ 0@  @ 0@ j?  Yj   @ h!@ $ @ =0@  uj  Yh	 ( @ P, @ ËUE 8csmu*xu$@= t=!t="t= @u  3] hH@   @ 3% @ jh("@ b  53@ 5 @ YEuu @ Ygj  Ye 53@ ։E53@ YYEEPEPu5l @ YPU  Eu֣3@ uփ3@ E	   E  j  YËUuNYH]ËV!@ !@ W;stЃ;r_^ËV"@ "@ W;stЃ;r_^% @ ̋UMMZ  f9t3]ËA<8PE  u3ҹ  f9H]̋UEH<ASVq3WDv}H;r	X;r
B(;r3_^[]̋UjhH"@ he@ d    PSVW 0@ 1E3PEd    eE    h  @ *tUE-  @ Ph  @ Pt;@$ЃEMd    Y_^[]ËE3=  ËeE3Md    Y_^[]% @ % @ he@ d5    D$l$l$+SVW 0@ 1E3PeuEEEEd    ËMd    Y__^[]QËUuuuuh@ h 0@    ]ËVh   h   3V   tVVVVV   ^3ËU 0@ e e SWN@  ;tt	У0@ `VEP< @ u3u @ 3 @ 3 @ 3EP @ E3E3;uO@u5 0@ ։50@ ^_[%t @ %x @ %| @ % @ % @ % @ % @ % @ % @ Pd5    D$+d$SVW( 0@ 3PEuEEd    ËMd    Y__^[]QËM3M%T @ T$BJ3J3l"@ s                                                                                                                                                                                                                                                     #  #  #  )  r)  b)  H)  4)  )  (  (  (  (  (  (  )      #  $  %  %  &  d&  &  $      ('  '  '  '  '  (  ((  6(  '  H(  Z(  t(  (  '  '   '  '  '  l'  ^'  R'  F'  >'  >(  0'  '  )          @         W@ @                     MoO       l   !    @0@ 0@ bad allocation      H                                                            0@ !@    RSDSьJ!LZ    c:\users\seld\documents\visual studio 2010\Projects\hiddeninp\Release\hiddeninp.pdb     e                            @ @                 :@             @ @ @ "   d"@                        "          #      $#          &  D   H#          (  h                       #  #  #  )  r)  b)  H)  4)  )  (  (  (  (  (  (  )      #  $  %  %  &  d&  &  $      ('  '  '  '  '  (  ((  6(  '  H(  Z(  t(  (  '  '   '  '  '  l'  ^'  R'  F'  >'  >(  0'  '  )      GetConsoleMode  SetConsoleMode  ;GetStdHandle  KERNEL32.dll   ??$?6DU?$char_traits@D@std@@V?$allocator@D@1@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@@Z ?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A  J?cin@std@@3V?$basic_istream@DU?$char_traits@D@std@@@1@A  ??$getline@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@YAAAV?$basic_istream@DU?$char_traits@D@std@@@0@AAV10@AAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@@Z ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z  _??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ  {??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ  ?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@Z  MSVCP90.dll _amsg_exit   __getmainargs ,_cexit  |_exit f _XcptFilter exit   __initenv _initterm _initterm_e <_configthreadlocale  __setusermatherr  _adjust_fdiv   __p__commode   __p__fmode  j_encode_pointer  __set_app_type  K_crt_debugger_hook  C ?terminate@@YAXXZ MSVCR90.dll _unlock  __dllonexit v_lock _onexit `_decode_pointer s_except_handler4_common _invoke_watson  ?_controlfp_s  InterlockedExchange !Sleep InterlockedCompareExchange  -TerminateProcess  GetCurrentProcess >UnhandledExceptionFilter  SetUnhandledExceptionFilter IsDebuggerPresent TQueryPerformanceCounter fGetTickCount  GetCurrentThreadId  GetCurrentProcessId OGetSystemTimeAsFileTime s __CxxFrameHandler3                                                    N@D   $!@                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            8                   P                   h                	                   	     @  (        C  V        (4   V S _ V E R S I O N _ I N F O                                                  S t r i n g F i l e I n f o   b   0 4 0 9 0 4 b 0    Q  F i l e D e s c r i p t i o n     R e a d s   f r o m   s t d i n   w i t h o u t   l e a k i n g   i n f o   t o   t h e   t e r m i n a l   a n d   o u t p u t s   b a c k   t o   s t d o u t     6   F i l e V e r s i o n     1 ,   0 ,   0 ,   0     8   I n t e r n a l N a m e   h i d d e n i n p u t   P   L e g a l C o p y r i g h t   J o r d i   B o g g i a n o   -   2 0 1 2   H   O r i g i n a l F i l e n a m e   h i d d e n i n p u t . e x e   :   P r o d u c t N a m e     H i d d e n   I n p u t     :   P r o d u c t V e r s i o n   1 ,   0 ,   0 ,   0     D    V a r F i l e I n f o     $    T r a n s l a t i o n     	<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
      </requestedPrivileges>
    </security>
  </trustInfo>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
</assembly>PAPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDING   @  00!0/080F0L0T0^0d0n0{000000000000001#1-1@1J1O1T1v1{1111111111111112"2*23292A2M2_2j2p222222222222333%303N3T3Z3`3f3l3s3z333333333333333334444%4;4B444444444445!5^5c5555H6M6_6}666 777*7w7|77777888=8E8P8V8\8b8h8n8t8z88889      $   0001 1t1x12 2@2\2`2h2t2 0     0                                                                                                                                                  <?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Event;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * Allows to handle exception thrown in a command.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ConsoleExceptionEvent extends ConsoleEvent
{
    private $exception;
    private $exitCode;

    public function __construct(Command $command, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode)
    {
        parent::__construct($command, $input, $output);

        $this->setException($exception);
        $this->exitCode = (int) $exitCode;
    }

    /**
     * Returns the thrown exception.
     *
     * @return \Exception The thrown exception
     */
    public function getException()
    {
        return $this->exception;
    }

    /**
     * Replaces the thrown exception.
     *
     * This exception will be thrown if no response is set in the event.
     *
     * @param \Exception $exception The thrown exception
     */
    public function setException(\Exception $exception)
    {
        $this->exception = $exception;
    }

    /**
     * Gets the exit code.
     *
     * @return integer The command exit code
     */
    public function getExitCode()
    {
        return $this->exitCode;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Event;

/**
 * Allows to do things before the command is executed.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ConsoleCommandEvent extends ConsoleEvent
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Event;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * Allows to manipulate the exit code of a command after its execution.
 *
 * @author Francesco Levorato <git@flevour.net>
 */
class ConsoleTerminateEvent extends ConsoleEvent
{
    /**
     * The exit code of the command.
     *
     * @var integer
     */
    private $exitCode;

    public function __construct(Command $command, InputInterface $input, OutputInterface $output, $exitCode)
    {
        parent::__construct($command, $input, $output);

        $this->setExitCode($exitCode);
    }

    /**
     * Sets the exit code.
     *
     * @param integer $exitCode The command exit code
     */
    public function setExitCode($exitCode)
    {
        $this->exitCode = (int) $exitCode;
    }

    /**
     * Gets the exit code.
     *
     * @return integer The command exit code
     */
    public function getExitCode()
    {
        return $this->exitCode;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Event;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\EventDispatcher\Event;

/**
 * Allows to inspect input and output of a command.
 *
 * @author Francesco Levorato <git@flevour.net>
 */
class ConsoleEvent extends Event
{
    protected $command;

    private $input;
    private $output;

    public function __construct(Command $command, InputInterface $input, OutputInterface $output)
    {
        $this->command = $command;
        $this->input = $input;
        $this->output = $output;
    }

    /**
     * Gets the command that is executed.
     *
     * @return Command A Command instance
     */
    public function getCommand()
    {
        return $this->command;
    }

    /**
     * Gets the input instance.
     *
     * @return InputInterface An InputInterface instance
     */
    public function getInput()
    {
        return $this->input;
    }

    /**
     * Gets the output instance.
     *
     * @return OutputInterface An OutputInterface instance
     */
    public function getOutput()
    {
        return $this->output;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Command;

use Symfony\Component\Console\Helper\DescriptorHelper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputDefinition;

/**
 * ListCommand displays the list of all available commands for the application.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ListCommand extends Command
{
    /**
     * {@inheritdoc}
     */
    protected function configure()
    {
        $this
            ->setName('list')
            ->setDefinition($this->createDefinition())
            ->setDescription('Lists commands')
            ->setHelp(<<<EOF
The <info>%command.name%</info> command lists all commands:

  <info>php %command.full_name%</info>

You can also display the commands for a specific namespace:

  <info>php %command.full_name% test</info>

You can also output the information in other formats by using the <comment>--format</comment> option:

  <info>php %command.full_name% --format=xml</info>

It's also possible to get raw list of commands (useful for embedding command runner):

  <info>php %command.full_name% --raw</info>
EOF
            )
        ;
    }

    /**
     * {@inheritdoc}
     */
    public function getNativeDefinition()
    {
        return $this->createDefinition();
    }

    /**
     * {@inheritdoc}
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        if ($input->getOption('xml')) {
            $input->setOption('format', 'xml');
        }

        $helper = new DescriptorHelper();
        $helper->describe($output, $this->getApplication(), array(
            'format'    => $input->getOption('format'),
            'raw_text'  => $input->getOption('raw'),
            'namespace' => $input->getArgument('namespace'),
        ));
    }

    /**
     * {@inheritdoc}
     */
    private function createDefinition()
    {
        return new InputDefinition(array(
            new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
            new InputOption('xml', null, InputOption::VALUE_NONE, 'To output list as XML'),
            new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'),
            new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output list in other formats', 'txt'),
        ));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Command;

use Symfony\Component\Console\Descriptor\TextDescriptor;
use Symfony\Component\Console\Descriptor\XmlDescriptor;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Helper\HelperSet;

/**
 * Base class for all commands.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Command
{
    private $application;
    private $name;
    private $aliases = array();
    private $definition;
    private $help;
    private $description;
    private $ignoreValidationErrors = false;
    private $applicationDefinitionMerged = false;
    private $applicationDefinitionMergedWithArgs = false;
    private $code;
    private $synopsis;
    private $helperSet;

    /**
     * Constructor.
     *
     * @param string|null $name The name of the command; passing null means it must be set in configure()
     *
     * @throws \LogicException When the command name is empty
     *
     * @api
     */
    public function __construct($name = null)
    {
        $this->definition = new InputDefinition();

        if (null !== $name) {
            $this->setName($name);
        }

        $this->configure();

        if (!$this->name) {
            throw new \LogicException('The command name cannot be empty.');
        }
    }

    /**
     * Ignores validation errors.
     *
     * This is mainly useful for the help command.
     */
    public function ignoreValidationErrors()
    {
        $this->ignoreValidationErrors = true;
    }

    /**
     * Sets the application instance for this command.
     *
     * @param Application $application An Application instance
     *
     * @api
     */
    public function setApplication(Application $application = null)
    {
        $this->application = $application;
        if ($application) {
            $this->setHelperSet($application->getHelperSet());
        } else {
            $this->helperSet = null;
        }
    }

    /**
     * Sets the helper set.
     *
     * @param HelperSet $helperSet A HelperSet instance
     */
    public function setHelperSet(HelperSet $helperSet)
    {
        $this->helperSet = $helperSet;
    }

    /**
     * Gets the helper set.
     *
     * @return HelperSet A HelperSet instance
     */
    public function getHelperSet()
    {
        return $this->helperSet;
    }

    /**
     * Gets the application instance for this command.
     *
     * @return Application An Application instance
     *
     * @api
     */
    public function getApplication()
    {
        return $this->application;
    }

    /**
     * Checks whether the command is enabled or not in the current environment
     *
     * Override this to check for x or y and return false if the command can not
     * run properly under the current conditions.
     *
     * @return Boolean
     */
    public function isEnabled()
    {
        return true;
    }

    /**
     * Configures the current command.
     */
    protected function configure()
    {
    }

    /**
     * Executes the current command.
     *
     * This method is not abstract because you can use this class
     * as a concrete class. In this case, instead of defining the
     * execute() method, you set the code to execute by passing
     * a Closure to the setCode() method.
     *
     * @param InputInterface  $input  An InputInterface instance
     * @param OutputInterface $output An OutputInterface instance
     *
     * @return null|integer null or 0 if everything went fine, or an error code
     *
     * @throws \LogicException When this abstract method is not implemented
     * @see    setCode()
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        throw new \LogicException('You must override the execute() method in the concrete command class.');
    }

    /**
     * Interacts with the user.
     *
     * @param InputInterface  $input  An InputInterface instance
     * @param OutputInterface $output An OutputInterface instance
     */
    protected function interact(InputInterface $input, OutputInterface $output)
    {
    }

    /**
     * Initializes the command just after the input has been validated.
     *
     * This is mainly useful when a lot of commands extends one main command
     * where some things need to be initialized based on the input arguments and options.
     *
     * @param InputInterface  $input  An InputInterface instance
     * @param OutputInterface $output An OutputInterface instance
     */
    protected function initialize(InputInterface $input, OutputInterface $output)
    {
    }

    /**
     * Runs the command.
     *
     * The code to execute is either defined directly with the
     * setCode() method or by overriding the execute() method
     * in a sub-class.
     *
     * @param InputInterface  $input  An InputInterface instance
     * @param OutputInterface $output An OutputInterface instance
     *
     * @return integer The command exit code
     *
     * @throws \Exception
     *
     * @see setCode()
     * @see execute()
     *
     * @api
     */
    public function run(InputInterface $input, OutputInterface $output)
    {
        // force the creation of the synopsis before the merge with the app definition
        $this->getSynopsis();

        // add the application arguments and options
        $this->mergeApplicationDefinition();

        // bind the input against the command specific arguments/options
        try {
            $input->bind($this->definition);
        } catch (\Exception $e) {
            if (!$this->ignoreValidationErrors) {
                throw $e;
            }
        }

        $this->initialize($input, $output);

        if ($input->isInteractive()) {
            $this->interact($input, $output);
        }

        $input->validate();

        if ($this->code) {
            $statusCode = call_user_func($this->code, $input, $output);
        } else {
            $statusCode = $this->execute($input, $output);
        }

        return is_numeric($statusCode) ? (int) $statusCode : 0;
    }

    /**
     * Sets the code to execute when running this command.
     *
     * If this method is used, it overrides the code defined
     * in the execute() method.
     *
     * @param callable $code A callable(InputInterface $input, OutputInterface $output)
     *
     * @return Command The current instance
     *
     * @throws \InvalidArgumentException
     *
     * @see execute()
     *
     * @api
     */
    public function setCode($code)
    {
        if (!is_callable($code)) {
            throw new \InvalidArgumentException('Invalid callable provided to Command::setCode.');
        }

        $this->code = $code;

        return $this;
    }

    /**
     * Merges the application definition with the command definition.
     *
     * This method is not part of public API and should not be used directly.
     *
     * @param Boolean $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments
     */
    public function mergeApplicationDefinition($mergeArgs = true)
    {
        if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) {
            return;
        }

        if ($mergeArgs) {
            $currentArguments = $this->definition->getArguments();
            $this->definition->setArguments($this->application->getDefinition()->getArguments());
            $this->definition->addArguments($currentArguments);
        }

        $this->definition->addOptions($this->application->getDefinition()->getOptions());

        $this->applicationDefinitionMerged = true;
        if ($mergeArgs) {
            $this->applicationDefinitionMergedWithArgs = true;
        }
    }

    /**
     * Sets an array of argument and option instances.
     *
     * @param array|InputDefinition $definition An array of argument and option instances or a definition instance
     *
     * @return Command The current instance
     *
     * @api
     */
    public function setDefinition($definition)
    {
        if ($definition instanceof InputDefinition) {
            $this->definition = $definition;
        } else {
            $this->definition->setDefinition($definition);
        }

        $this->applicationDefinitionMerged = false;

        return $this;
    }

    /**
     * Gets the InputDefinition attached to this Command.
     *
     * @return InputDefinition An InputDefinition instance
     *
     * @api
     */
    public function getDefinition()
    {
        return $this->definition;
    }

    /**
     * Gets the InputDefinition to be used to create XML and Text representations of this Command.
     *
     * Can be overridden to provide the original command representation when it would otherwise
     * be changed by merging with the application InputDefinition.
     *
     * This method is not part of public API and should not be used directly.
     *
     * @return InputDefinition An InputDefinition instance
     */
    public function getNativeDefinition()
    {
        return $this->getDefinition();
    }

    /**
     * Adds an argument.
     *
     * @param string  $name        The argument name
     * @param integer $mode        The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL
     * @param string  $description A description text
     * @param mixed   $default     The default value (for InputArgument::OPTIONAL mode only)
     *
     * @return Command The current instance
     *
     * @api
     */
    public function addArgument($name, $mode = null, $description = '', $default = null)
    {
        $this->definition->addArgument(new InputArgument($name, $mode, $description, $default));

        return $this;
    }

    /**
     * Adds an option.
     *
     * @param string  $name        The option name
     * @param string  $shortcut    The shortcut (can be null)
     * @param integer $mode        The option mode: One of the InputOption::VALUE_* constants
     * @param string  $description A description text
     * @param mixed   $default     The default value (must be null for InputOption::VALUE_REQUIRED or InputOption::VALUE_NONE)
     *
     * @return Command The current instance
     *
     * @api
     */
    public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
    {
        $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));

        return $this;
    }

    /**
     * Sets the name of the command.
     *
     * This method can set both the namespace and the name if
     * you separate them by a colon (:)
     *
     *     $command->setName('foo:bar');
     *
     * @param string $name The command name
     *
     * @return Command The current instance
     *
     * @throws \InvalidArgumentException When the name is invalid
     *
     * @api
     */
    public function setName($name)
    {
        $this->validateName($name);

        $this->name = $name;

        return $this;
    }

    /**
     * Returns the command name.
     *
     * @return string The command name
     *
     * @api
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Sets the description for the command.
     *
     * @param string $description The description for the command
     *
     * @return Command The current instance
     *
     * @api
     */
    public function setDescription($description)
    {
        $this->description = $description;

        return $this;
    }

    /**
     * Returns the description for the command.
     *
     * @return string The description for the command
     *
     * @api
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     * Sets the help for the command.
     *
     * @param string $help The help for the command
     *
     * @return Command The current instance
     *
     * @api
     */
    public function setHelp($help)
    {
        $this->help = $help;

        return $this;
    }

    /**
     * Returns the help for the command.
     *
     * @return string The help for the command
     *
     * @api
     */
    public function getHelp()
    {
        return $this->help;
    }

    /**
     * Returns the processed help for the command replacing the %command.name% and
     * %command.full_name% patterns with the real values dynamically.
     *
     * @return string  The processed help for the command
     */
    public function getProcessedHelp()
    {
        $name = $this->name;

        $placeholders = array(
            '%command.name%',
            '%command.full_name%'
        );
        $replacements = array(
            $name,
            $_SERVER['PHP_SELF'].' '.$name
        );

        return str_replace($placeholders, $replacements, $this->getHelp());
    }

    /**
     * Sets the aliases for the command.
     *
     * @param array $aliases An array of aliases for the command
     *
     * @return Command The current instance
     *
     * @throws \InvalidArgumentException When an alias is invalid
     *
     * @api
     */
    public function setAliases($aliases)
    {
        foreach ($aliases as $alias) {
            $this->validateName($alias);
        }

        $this->aliases = $aliases;

        return $this;
    }

    /**
     * Returns the aliases for the command.
     *
     * @return array An array of aliases for the command
     *
     * @api
     */
    public function getAliases()
    {
        return $this->aliases;
    }

    /**
     * Returns the synopsis for the command.
     *
     * @return string The synopsis
     */
    public function getSynopsis()
    {
        if (null === $this->synopsis) {
            $this->synopsis = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis()));
        }

        return $this->synopsis;
    }

    /**
     * Gets a helper instance by name.
     *
     * @param string $name The helper name
     *
     * @return mixed The helper value
     *
     * @throws \InvalidArgumentException if the helper is not defined
     *
     * @api
     */
    public function getHelper($name)
    {
        return $this->helperSet->get($name);
    }

    /**
     * Returns a text representation of the command.
     *
     * @return string A string representing the command
     *
     * @deprecated Deprecated since version 2.3, to be removed in 3.0.
     */
    public function asText()
    {
        $descriptor = new TextDescriptor();
        $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
        $descriptor->describe($output, $this, array('raw_output' => true));

        return $output->fetch();
    }

    /**
     * Returns an XML representation of the command.
     *
     * @param Boolean $asDom Whether to return a DOM or an XML string
     *
     * @return string|\DOMDocument An XML string representing the command
     *
     * @deprecated Deprecated since version 2.3, to be removed in 3.0.
     */
    public function asXml($asDom = false)
    {
        $descriptor = new XmlDescriptor();

        if ($asDom) {
            return $descriptor->getCommandDocument($this);
        }

        $output = new BufferedOutput();
        $descriptor->describe($output, $this);

        return $output->fetch();
    }

    /**
     * Validates a command name.
     *
     * It must be non-empty and parts can optionally be separated by ":".
     *
     * @param string $name
     *
     * @throws \InvalidArgumentException When the name is invalid
     */
    private function validateName($name)
    {
        if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
            throw new \InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Command;

use Symfony\Component\Console\Helper\DescriptorHelper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * HelpCommand displays the help for a given command.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class HelpCommand extends Command
{
    private $command;

    /**
     * {@inheritdoc}
     */
    protected function configure()
    {
        $this->ignoreValidationErrors();

        $this
            ->setName('help')
            ->setDefinition(array(
                new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'),
                new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'),
                new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output help in other formats', 'txt'),
                new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'),
            ))
            ->setDescription('Displays help for a command')
            ->setHelp(<<<EOF
The <info>%command.name%</info> command displays help for a given command:

  <info>php %command.full_name% list</info>

You can also output the help in other formats by using the <comment>--format</comment> option:

  <info>php %command.full_name% --format=xml list</info>

To display the list of available commands, please use the <info>list</info> command.
EOF
            )
        ;
    }

    /**
     * Sets the command
     *
     * @param Command $command The command to set
     */
    public function setCommand(Command $command)
    {
        $this->command = $command;
    }

    /**
     * {@inheritdoc}
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        if (null === $this->command) {
            $this->command = $this->getApplication()->find($input->getArgument('command_name'));
        }

        if ($input->getOption('xml')) {
            $input->setOption('format', 'xml');
        }

        $helper = new DescriptorHelper();
        $helper->describe($output, $this->command, array(
            'format' => $input->getOption('format'),
            'raw'    => $input->getOption('raw'),
        ));

        $this->command = null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Input\StringInput;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Process\ProcessBuilder;
use Symfony\Component\Process\PhpExecutableFinder;

/**
 * A Shell wraps an Application to add shell capabilities to it.
 *
 * Support for history and completion only works with a PHP compiled
 * with readline support (either --with-readline or --with-libedit)
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Martin Hasoň <martin.hason@gmail.com>
 */
class Shell
{
    private $application;
    private $history;
    private $output;
    private $hasReadline;
    private $processIsolation = false;

    /**
     * Constructor.
     *
     * If there is no readline support for the current PHP executable
     * a \RuntimeException exception is thrown.
     *
     * @param Application $application An application instance
     */
    public function __construct(Application $application)
    {
        $this->hasReadline = function_exists('readline');
        $this->application = $application;
        $this->history = getenv('HOME').'/.history_'.$application->getName();
        $this->output = new ConsoleOutput();
    }

    /**
     * Runs the shell.
     */
    public function run()
    {
        $this->application->setAutoExit(false);
        $this->application->setCatchExceptions(true);

        if ($this->hasReadline) {
            readline_read_history($this->history);
            readline_completion_function(array($this, 'autocompleter'));
        }

        $this->output->writeln($this->getHeader());
        $php = null;
        if ($this->processIsolation) {
            $finder = new PhpExecutableFinder();
            $php = $finder->find();
            $this->output->writeln(<<<EOF
<info>Running with process isolation, you should consider this:</info>
  * each command is executed as separate process,
  * commands don't support interactivity, all params must be passed explicitly,
  * commands output is not colorized.

EOF
            );
        }

        while (true) {
            $command = $this->readline();

            if (false === $command) {
                $this->output->writeln("\n");

                break;
            }

            if ($this->hasReadline) {
                readline_add_history($command);
                readline_write_history($this->history);
            }

            if ($this->processIsolation) {
                $pb = new ProcessBuilder();

                $process = $pb
                    ->add($php)
                    ->add($_SERVER['argv'][0])
                    ->add($command)
                    ->inheritEnvironmentVariables(true)
                    ->getProcess()
                ;

                $output = $this->output;
                $process->run(function($type, $data) use ($output) {
                    $output->writeln($data);
                });

                $ret = $process->getExitCode();
            } else {
                $ret = $this->application->run(new StringInput($command), $this->output);
            }

            if (0 !== $ret) {
                $this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>', $ret));
            }
        }
    }

    /**
     * Returns the shell header.
     *
     * @return string The header string
     */
    protected function getHeader()
    {
        return <<<EOF

Welcome to the <info>{$this->application->getName()}</info> shell (<comment>{$this->application->getVersion()}</comment>).

At the prompt, type <comment>help</comment> for some help,
or <comment>list</comment> to get a list of available commands.

To exit the shell, type <comment>^D</comment>.

EOF;
    }

    /**
     * Renders a prompt.
     *
     * @return string The prompt
     */
    protected function getPrompt()
    {
        // using the formatter here is required when using readline
        return $this->output->getFormatter()->format($this->application->getName().' > ');
    }

    protected function getOutput()
    {
        return $this->output;
    }

    protected function getApplication()
    {
        return $this->application;
    }

    /**
     * Tries to return autocompletion for the current entered text.
     *
     * @param string $text The last segment of the entered text
     *
     * @return Boolean|array A list of guessed strings or true
     */
    private function autocompleter($text)
    {
        $info = readline_info();
        $text = substr($info['line_buffer'], 0, $info['end']);

        if ($info['point'] !== $info['end']) {
            return true;
        }

        // task name?
        if (false === strpos($text, ' ') || !$text) {
            return array_keys($this->application->all());
        }

        // options and arguments?
        try {
            $command = $this->application->find(substr($text, 0, strpos($text, ' ')));
        } catch (\Exception $e) {
            return true;
        }

        $list = array('--help');
        foreach ($command->getDefinition()->getOptions() as $option) {
            $list[] = '--'.$option->getName();
        }

        return $list;
    }

    /**
     * Reads a single line from standard input.
     *
     * @return string The single line from standard input
     */
    private function readline()
    {
        if ($this->hasReadline) {
            $line = readline($this->getPrompt());
        } else {
            $this->output->write($this->getPrompt());
            $line = fgets(STDIN, 1024);
            $line = (!$line && strlen($line) == 0) ? false : rtrim($line);
        }

        return $line;
    }

    public function getProcessIsolation()
    {
        return $this->processIsolation;
    }

    public function setProcessIsolation($processIsolation)
    {
        $this->processIsolation = (Boolean) $processIsolation;

        if ($this->processIsolation && !class_exists('Symfony\\Component\\Process\\Process')) {
            throw new \RuntimeException('Unable to isolate processes as the Symfony Process Component is not installed.');
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console;

use Symfony\Component\Console\Descriptor\TextDescriptor;
use Symfony\Component\Console\Descriptor\XmlDescriptor;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputAwareInterface;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Console\Output\ConsoleOutputInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Command\HelpCommand;
use Symfony\Component\Console\Command\ListCommand;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Helper\FormatterHelper;
use Symfony\Component\Console\Helper\DialogHelper;
use Symfony\Component\Console\Helper\ProgressHelper;
use Symfony\Component\Console\Helper\TableHelper;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\Event\ConsoleExceptionEvent;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

/**
 * An Application is the container for a collection of commands.
 *
 * It is the main entry point of a Console application.
 *
 * This class is optimized for a standard CLI environment.
 *
 * Usage:
 *
 *     $app = new Application('myapp', '1.0 (stable)');
 *     $app->add(new SimpleCommand());
 *     $app->run();
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class Application
{
    private $commands = array();
    private $wantHelps = false;
    private $runningCommand;
    private $name;
    private $version;
    private $catchExceptions = true;
    private $autoExit = true;
    private $definition;
    private $helperSet;
    private $dispatcher;
    private $terminalDimensions;

    /**
     * Constructor.
     *
     * @param string $name    The name of the application
     * @param string $version The version of the application
     *
     * @api
     */
    public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
    {
        $this->name = $name;
        $this->version = $version;
        $this->helperSet = $this->getDefaultHelperSet();
        $this->definition = $this->getDefaultInputDefinition();

        foreach ($this->getDefaultCommands() as $command) {
            $this->add($command);
        }
    }

    public function setDispatcher(EventDispatcherInterface $dispatcher)
    {
        $this->dispatcher = $dispatcher;
    }

    /**
     * Runs the current application.
     *
     * @param InputInterface  $input  An Input instance
     * @param OutputInterface $output An Output instance
     *
     * @return integer 0 if everything went fine, or an error code
     *
     * @throws \Exception When doRun returns Exception
     *
     * @api
     */
    public function run(InputInterface $input = null, OutputInterface $output = null)
    {
        if (null === $input) {
            $input = new ArgvInput();
        }

        if (null === $output) {
            $output = new ConsoleOutput();
        }

        $this->configureIO($input, $output);

        try {
            $exitCode = $this->doRun($input, $output);
        } catch (\Exception $e) {
            if (!$this->catchExceptions) {
                throw $e;
            }

            if ($output instanceof ConsoleOutputInterface) {
                $this->renderException($e, $output->getErrorOutput());
            } else {
                $this->renderException($e, $output);
            }

            $exitCode = $e->getCode();
            if (is_numeric($exitCode)) {
                $exitCode = (int) $exitCode;
                if (0 === $exitCode) {
                    $exitCode = 1;
                }
            } else {
                $exitCode = 1;
            }
        }

        if ($this->autoExit) {
            if ($exitCode > 255) {
                $exitCode = 255;
            }
            // @codeCoverageIgnoreStart
            exit($exitCode);
            // @codeCoverageIgnoreEnd
        }

        return $exitCode;
    }

    /**
     * Runs the current application.
     *
     * @param InputInterface  $input  An Input instance
     * @param OutputInterface $output An Output instance
     *
     * @return integer 0 if everything went fine, or an error code
     */
    public function doRun(InputInterface $input, OutputInterface $output)
    {
        if (true === $input->hasParameterOption(array('--version', '-V'))) {
            $output->writeln($this->getLongVersion());

            return 0;
        }

        $name = $this->getCommandName($input);
        if (true === $input->hasParameterOption(array('--help', '-h'))) {
            if (!$name) {
                $name = 'help';
                $input = new ArrayInput(array('command' => 'help'));
            } else {
                $this->wantHelps = true;
            }
        }

        if (!$name) {
            $name = 'list';
            $input = new ArrayInput(array('command' => 'list'));
        }

        // the command name MUST be the first element of the input
        $command = $this->find($name);

        $this->runningCommand = $command;
        $exitCode = $this->doRunCommand($command, $input, $output);
        $this->runningCommand = null;

        return $exitCode;
    }

    /**
     * Set a helper set to be used with the command.
     *
     * @param HelperSet $helperSet The helper set
     *
     * @api
     */
    public function setHelperSet(HelperSet $helperSet)
    {
        $this->helperSet = $helperSet;
    }

    /**
     * Get the helper set associated with the command.
     *
     * @return HelperSet The HelperSet instance associated with this command
     *
     * @api
     */
    public function getHelperSet()
    {
        return $this->helperSet;
    }

    /**
     * Set an input definition set to be used with this application
     *
     * @param InputDefinition $definition The input definition
     *
     * @api
     */
    public function setDefinition(InputDefinition $definition)
    {
        $this->definition = $definition;
    }

    /**
     * Gets the InputDefinition related to this Application.
     *
     * @return InputDefinition The InputDefinition instance
     */
    public function getDefinition()
    {
        return $this->definition;
    }

    /**
     * Gets the help message.
     *
     * @return string A help message.
     */
    public function getHelp()
    {
        $messages = array(
            $this->getLongVersion(),
            '',
            '<comment>Usage:</comment>',
            '  [options] command [arguments]',
            '',
            '<comment>Options:</comment>',
        );

        foreach ($this->getDefinition()->getOptions() as $option) {
            $messages[] = sprintf('  %-29s %s %s',
                '<info>--'.$option->getName().'</info>',
                $option->getShortcut() ? '<info>-'.$option->getShortcut().'</info>' : '  ',
                $option->getDescription()
            );
        }

        return implode(PHP_EOL, $messages);
    }

    /**
     * Sets whether to catch exceptions or not during commands execution.
     *
     * @param Boolean $boolean Whether to catch exceptions or not during commands execution
     *
     * @api
     */
    public function setCatchExceptions($boolean)
    {
        $this->catchExceptions = (Boolean) $boolean;
    }

    /**
     * Sets whether to automatically exit after a command execution or not.
     *
     * @param Boolean $boolean Whether to automatically exit after a command execution or not
     *
     * @api
     */
    public function setAutoExit($boolean)
    {
        $this->autoExit = (Boolean) $boolean;
    }

    /**
     * Gets the name of the application.
     *
     * @return string The application name
     *
     * @api
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Sets the application name.
     *
     * @param string $name The application name
     *
     * @api
     */
    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * Gets the application version.
     *
     * @return string The application version
     *
     * @api
     */
    public function getVersion()
    {
        return $this->version;
    }

    /**
     * Sets the application version.
     *
     * @param string $version The application version
     *
     * @api
     */
    public function setVersion($version)
    {
        $this->version = $version;
    }

    /**
     * Returns the long version of the application.
     *
     * @return string The long application version
     *
     * @api
     */
    public function getLongVersion()
    {
        if ('UNKNOWN' !== $this->getName() && 'UNKNOWN' !== $this->getVersion()) {
            return sprintf('<info>%s</info> version <comment>%s</comment>', $this->getName(), $this->getVersion());
        }

        return '<info>Console Tool</info>';
    }

    /**
     * Registers a new command.
     *
     * @param string $name The command name
     *
     * @return Command The newly created command
     *
     * @api
     */
    public function register($name)
    {
        return $this->add(new Command($name));
    }

    /**
     * Adds an array of command objects.
     *
     * @param Command[] $commands An array of commands
     *
     * @api
     */
    public function addCommands(array $commands)
    {
        foreach ($commands as $command) {
            $this->add($command);
        }
    }

    /**
     * Adds a command object.
     *
     * If a command with the same name already exists, it will be overridden.
     *
     * @param Command $command A Command object
     *
     * @return Command The registered command
     *
     * @api
     */
    public function add(Command $command)
    {
        $command->setApplication($this);

        if (!$command->isEnabled()) {
            $command->setApplication(null);

            return;
        }

        if (null === $command->getDefinition()) {
            throw new \LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command)));
        }

        $this->commands[$command->getName()] = $command;

        foreach ($command->getAliases() as $alias) {
            $this->commands[$alias] = $command;
        }

        return $command;
    }

    /**
     * Returns a registered command by name or alias.
     *
     * @param string $name The command name or alias
     *
     * @return Command A Command object
     *
     * @throws \InvalidArgumentException When command name given does not exist
     *
     * @api
     */
    public function get($name)
    {
        if (!isset($this->commands[$name])) {
            throw new \InvalidArgumentException(sprintf('The command "%s" does not exist.', $name));
        }

        $command = $this->commands[$name];

        if ($this->wantHelps) {
            $this->wantHelps = false;

            $helpCommand = $this->get('help');
            $helpCommand->setCommand($command);

            return $helpCommand;
        }

        return $command;
    }

    /**
     * Returns true if the command exists, false otherwise.
     *
     * @param string $name The command name or alias
     *
     * @return Boolean true if the command exists, false otherwise
     *
     * @api
     */
    public function has($name)
    {
        return isset($this->commands[$name]);
    }

    /**
     * Returns an array of all unique namespaces used by currently registered commands.
     *
     * It does not returns the global namespace which always exists.
     *
     * @return array An array of namespaces
     */
    public function getNamespaces()
    {
        $namespaces = array();
        foreach ($this->commands as $command) {
            $namespaces[] = $this->extractNamespace($command->getName());

            foreach ($command->getAliases() as $alias) {
                $namespaces[] = $this->extractNamespace($alias);
            }
        }

        return array_values(array_unique(array_filter($namespaces)));
    }

    /**
     * Finds a registered namespace by a name or an abbreviation.
     *
     * @param string $namespace A namespace or abbreviation to search for
     *
     * @return string A registered namespace
     *
     * @throws \InvalidArgumentException When namespace is incorrect or ambiguous
     */
    public function findNamespace($namespace)
    {
        $allNamespaces = $this->getNamespaces();
        $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $namespace);
        $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces);

        if (empty($namespaces)) {
            $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);

            if ($alternatives = $this->findAlternatives($namespace, $allNamespaces, array())) {
                if (1 == count($alternatives)) {
                    $message .= "\n\nDid you mean this?\n    ";
                } else {
                    $message .= "\n\nDid you mean one of these?\n    ";
                }

                $message .= implode("\n    ", $alternatives);
            }

            throw new \InvalidArgumentException($message);
        }

        $exact = in_array($namespace, $namespaces, true);
        if (count($namespaces) > 1 && !$exact) {
            throw new \InvalidArgumentException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))));
        }

        return $exact ? $namespace : reset($namespaces);
    }

    /**
     * Finds a command by name or alias.
     *
     * Contrary to get, this command tries to find the best
     * match if you give it an abbreviation of a name or alias.
     *
     * @param string $name A command name or a command alias
     *
     * @return Command A Command instance
     *
     * @throws \InvalidArgumentException When command name is incorrect or ambiguous
     *
     * @api
     */
    public function find($name)
    {
        $allCommands = array_keys($this->commands);
        $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name);
        $commands = preg_grep('{^'.$expr.'}', $allCommands);

        if (empty($commands) || count(preg_grep('{^'.$expr.'$}', $commands)) < 1) {
            if (false !== $pos = strrpos($name, ':')) {
                // check if a namespace exists and contains commands
                $this->findNamespace(substr($name, 0, $pos));
            }

            $message = sprintf('Command "%s" is not defined.', $name);

            if ($alternatives = $this->findAlternatives($name, $allCommands, array())) {
                if (1 == count($alternatives)) {
                    $message .= "\n\nDid you mean this?\n    ";
                } else {
                    $message .= "\n\nDid you mean one of these?\n    ";
                }
                $message .= implode("\n    ", $alternatives);
            }

            throw new \InvalidArgumentException($message);
        }

        $exact = in_array($name, $commands, true);
        if (count($commands) > 1 && !$exact) {
            $suggestions = $this->getAbbreviationSuggestions(array_values($commands));

            throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions));
        }

        return $this->get($exact ? $name : reset($commands));
    }

    /**
     * Gets the commands (registered in the given namespace if provided).
     *
     * The array keys are the full names and the values the command instances.
     *
     * @param string $namespace A namespace name
     *
     * @return Command[] An array of Command instances
     *
     * @api
     */
    public function all($namespace = null)
    {
        if (null === $namespace) {
            return $this->commands;
        }

        $commands = array();
        foreach ($this->commands as $name => $command) {
            if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) {
                $commands[$name] = $command;
            }
        }

        return $commands;
    }

    /**
     * Returns an array of possible abbreviations given a set of names.
     *
     * @param array $names An array of names
     *
     * @return array An array of abbreviations
     */
    public static function getAbbreviations($names)
    {
        $abbrevs = array();
        foreach ($names as $name) {
            for ($len = strlen($name); $len > 0; --$len) {
                $abbrev = substr($name, 0, $len);
                $abbrevs[$abbrev][] = $name;
            }
        }

        return $abbrevs;
    }

    /**
     * Returns a text representation of the Application.
     *
     * @param string  $namespace An optional namespace name
     * @param boolean $raw       Whether to return raw command list
     *
     * @return string A string representing the Application
     *
     * @deprecated Deprecated since version 2.3, to be removed in 3.0.
     */
    public function asText($namespace = null, $raw = false)
    {
        $descriptor = new TextDescriptor();
        $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, !$raw);
        $descriptor->describe($output, $this, array('namespace' => $namespace, 'raw_output' => true));

        return $output->fetch();
    }

    /**
     * Returns an XML representation of the Application.
     *
     * @param string  $namespace An optional namespace name
     * @param Boolean $asDom     Whether to return a DOM or an XML string
     *
     * @return string|\DOMDocument An XML string representing the Application
     *
     * @deprecated Deprecated since version 2.3, to be removed in 3.0.
     */
    public function asXml($namespace = null, $asDom = false)
    {
        $descriptor = new XmlDescriptor();

        if ($asDom) {
            return $descriptor->getApplicationDocument($this, $namespace);
        }

        $output = new BufferedOutput();
        $descriptor->describe($output, $this, array('namespace' => $namespace));

        return $output->fetch();
    }

    /**
     * Renders a caught exception.
     *
     * @param \Exception       $e      An exception instance
     * @param OutputInterface $output An OutputInterface instance
     */
    public function renderException($e, $output)
    {
        $strlen = function ($string) {
            if (!function_exists('mb_strlen')) {
                return strlen($string);
            }

            if (false === $encoding = mb_detect_encoding($string)) {
                return strlen($string);
            }

            return mb_strlen($string, $encoding);
        };

        do {
            $title = sprintf('  [%s]  ', get_class($e));
            $len = $strlen($title);
            $width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : PHP_INT_MAX;
            $formatter = $output->getFormatter();
            $lines = array();
            foreach (preg_split('/\r?\n/', $e->getMessage()) as $line) {
                foreach (str_split($line, $width - 4) as $line) {
                    // pre-format lines to get the right string length
                    $lineLength = $strlen(preg_replace('/\[[^m]*m/', '', $formatter->format($line))) + 4;
                    $lines[] = array($line, $lineLength);

                    $len = max($lineLength, $len);
                }
            }

            $messages = array('', '');
            $messages[] = $emptyLine = $formatter->format(sprintf('<error>%s</error>', str_repeat(' ', $len)));
            $messages[] = $formatter->format(sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - $strlen($title)))));
            foreach ($lines as $line) {
                $messages[] = $formatter->format(sprintf('<error>  %s  %s</error>', $line[0], str_repeat(' ', $len - $line[1])));
            }
            $messages[] = $emptyLine;
            $messages[] = '';
            $messages[] = '';

            $output->writeln($messages, OutputInterface::OUTPUT_RAW);

            if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
                $output->writeln('<comment>Exception trace:</comment>');

                // exception related properties
                $trace = $e->getTrace();
                array_unshift($trace, array(
                    'function' => '',
                    'file'     => $e->getFile() != null ? $e->getFile() : 'n/a',
                    'line'     => $e->getLine() != null ? $e->getLine() : 'n/a',
                    'args'     => array(),
                ));

                for ($i = 0, $count = count($trace); $i < $count; $i++) {
                    $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
                    $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
                    $function = $trace[$i]['function'];
                    $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a';
                    $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a';

                    $output->writeln(sprintf(' %s%s%s() at <info>%s:%s</info>', $class, $type, $function, $file, $line));
                }

                $output->writeln("");
                $output->writeln("");
            }
        } while ($e = $e->getPrevious());

        if (null !== $this->runningCommand) {
            $output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())));
            $output->writeln("");
            $output->writeln("");
        }
    }

    /**
     * Tries to figure out the terminal width in which this application runs
     *
     * @return int|null
     */
    protected function getTerminalWidth()
    {
        $dimensions = $this->getTerminalDimensions();

        return $dimensions[0];
    }

    /**
     * Tries to figure out the terminal height in which this application runs
     *
     * @return int|null
     */
    protected function getTerminalHeight()
    {
        $dimensions = $this->getTerminalDimensions();

        return $dimensions[1];
    }

    /**
     * Tries to figure out the terminal dimensions based on the current environment
     *
     * @return array Array containing width and height
     */
    public function getTerminalDimensions()
    {
        if ($this->terminalDimensions) {
            return $this->terminalDimensions;
        }

        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            // extract [w, H] from "wxh (WxH)"
            if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) {
                return array((int) $matches[1], (int) $matches[2]);
            }
            // extract [w, h] from "wxh"
            if (preg_match('/^(\d+)x(\d+)$/', $this->getConsoleMode(), $matches)) {
                return array((int) $matches[1], (int) $matches[2]);
            }
        }

        if ($sttyString = $this->getSttyColumns()) {
            // extract [w, h] from "rows h; columns w;"
            if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) {
                return array((int) $matches[2], (int) $matches[1]);
            }
            // extract [w, h] from "; h rows; w columns"
            if (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) {
                return array((int) $matches[2], (int) $matches[1]);
            }
        }

        return array(null, null);
    }

    /**
     * Sets terminal dimensions.
     *
     * Can be useful to force terminal dimensions for functional tests.
     *
     * @param integer $width  The width
     * @param integer $height The height
     *
     * @return Application The current application
     */
    public function setTerminalDimensions($width, $height)
    {
        $this->terminalDimensions = array($width, $height);

        return $this;
    }

    /**
     * Configures the input and output instances based on the user arguments and options.
     *
     * @param InputInterface  $input  An InputInterface instance
     * @param OutputInterface $output An OutputInterface instance
     */
    protected function configureIO(InputInterface $input, OutputInterface $output)
    {
        if (true === $input->hasParameterOption(array('--ansi'))) {
            $output->setDecorated(true);
        } elseif (true === $input->hasParameterOption(array('--no-ansi'))) {
            $output->setDecorated(false);
        }

        if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) {
            $input->setInteractive(false);
        } elseif (function_exists('posix_isatty') && $this->getHelperSet()->has('dialog')) {
            $inputStream = $this->getHelperSet()->get('dialog')->getInputStream();
            if (!@posix_isatty($inputStream)) {
                $input->setInteractive(false);
            }
        }

        if (true === $input->hasParameterOption(array('--quiet', '-q'))) {
            $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
        } else {
            if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || $input->getParameterOption('--verbose') === 3) {
                $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
            } elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || $input->getParameterOption('--verbose') === 2) {
                $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
            } elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) {
                $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
            }
        }
    }

    /**
     * Runs the current command.
     *
     * If an event dispatcher has been attached to the application,
     * events are also dispatched during the life-cycle of the command.
     *
     * @param Command         $command A Command instance
     * @param InputInterface  $input   An Input instance
     * @param OutputInterface $output  An Output instance
     *
     * @return integer 0 if everything went fine, or an error code
     */
    protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
    {
        foreach ($command->getHelperSet() as $helper) {
            if ($helper instanceof InputAwareInterface) {
                $helper->setInput($input);
            }
        }

        if (null === $this->dispatcher) {
            return $command->run($input, $output);
        }

        $event = new ConsoleCommandEvent($command, $input, $output);
        $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);

        try {
            $exitCode = $command->run($input, $output);
        } catch (\Exception $e) {
            $event = new ConsoleTerminateEvent($command, $input, $output, $e->getCode());
            $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);

            $event = new ConsoleExceptionEvent($command, $input, $output, $e, $event->getExitCode());
            $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);

            throw $event->getException();
        }

        $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
        $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);

        return $event->getExitCode();
    }

    /**
     * Gets the name of the command based on input.
     *
     * @param InputInterface $input The input interface
     *
     * @return string The command name
     */
    protected function getCommandName(InputInterface $input)
    {
        return $input->getFirstArgument();
    }

    /**
     * Gets the default input definition.
     *
     * @return InputDefinition An InputDefinition instance
     */
    protected function getDefaultInputDefinition()
    {
        return new InputDefinition(array(
            new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),

            new InputOption('--help',           '-h', InputOption::VALUE_NONE, 'Display this help message.'),
            new InputOption('--quiet',          '-q', InputOption::VALUE_NONE, 'Do not output any message.'),
            new InputOption('--verbose',        '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'),
            new InputOption('--version',        '-V', InputOption::VALUE_NONE, 'Display this application version.'),
            new InputOption('--ansi',           '',   InputOption::VALUE_NONE, 'Force ANSI output.'),
            new InputOption('--no-ansi',        '',   InputOption::VALUE_NONE, 'Disable ANSI output.'),
            new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question.'),
        ));
    }

    /**
     * Gets the default commands that should always be available.
     *
     * @return Command[] An array of default Command instances
     */
    protected function getDefaultCommands()
    {
        return array(new HelpCommand(), new ListCommand());
    }

    /**
     * Gets the default helper set with the helpers that should always be available.
     *
     * @return HelperSet A HelperSet instance
     */
    protected function getDefaultHelperSet()
    {
        return new HelperSet(array(
            new FormatterHelper(),
            new DialogHelper(),
            new ProgressHelper(),
            new TableHelper(),
        ));
    }

    /**
     * Runs and parses stty -a if it's available, suppressing any error output
     *
     * @return string
     */
    private function getSttyColumns()
    {
        if (!function_exists('proc_open')) {
            return;
        }

        $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
        $process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
        if (is_resource($process)) {
            $info = stream_get_contents($pipes[1]);
            fclose($pipes[1]);
            fclose($pipes[2]);
            proc_close($process);

            return $info;
        }
    }

    /**
     * Runs and parses mode CON if it's available, suppressing any error output
     *
     * @return string <width>x<height> or null if it could not be parsed
     */
    private function getConsoleMode()
    {
        if (!function_exists('proc_open')) {
            return;
        }

        $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
        $process = proc_open('mode CON', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
        if (is_resource($process)) {
            $info = stream_get_contents($pipes[1]);
            fclose($pipes[1]);
            fclose($pipes[2]);
            proc_close($process);

            if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) {
                return $matches[2].'x'.$matches[1];
            }
        }
    }

    /**
     * Returns abbreviated suggestions in string format.
     *
     * @param array $abbrevs Abbreviated suggestions to convert
     *
     * @return string A formatted string of abbreviated suggestions
     */
    private function getAbbreviationSuggestions($abbrevs)
    {
        return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : '');
    }

    /**
     * Returns the namespace part of the command name.
     *
     * This method is not part of public API and should not be used directly.
     *
     * @param string $name  The full name of the command
     * @param string $limit The maximum number of parts of the namespace
     *
     * @return string The namespace of the command
     */
    public function extractNamespace($name, $limit = null)
    {
        $parts = explode(':', $name);
        array_pop($parts);

        return implode(':', null === $limit ? $parts : array_slice($parts, 0, $limit));
    }

    /**
     * Finds alternative of $name among $collection
     *
     * @param string               $name       The string
     * @param array|Traversable    $collection The collection
     *
     * @return array A sorted array of similar string
     */
    private function findAlternatives($name, $collection)
    {
        $threshold = 1e3;
        $alternatives = array();

        $collectionParts = array();
        foreach ($collection as $item) {
            $collectionParts[$item] = explode(':', $item);
        }

        foreach (explode(':', $name) as $i => $subname) {
            foreach ($collectionParts as $collectionName => $parts) {
                $exists = isset($alternatives[$collectionName]);
                if (!isset($parts[$i]) && $exists) {
                    $alternatives[$collectionName] += $threshold;
                    continue;
                } elseif (!isset($parts[$i])) {
                    continue;
                }

                $lev = levenshtein($subname, $parts[$i]);
                if ($lev <= strlen($subname) / 3 || false !== strpos($parts[$i], $subname)) {
                    $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev;
                } elseif ($exists) {
                    $alternatives[$collectionName] += $threshold;
                }
            }
        }

        foreach ($collection as $item) {
            $lev = levenshtein($name, $item);
            if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) {
                $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
            }
        }

        $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2*$threshold; });
        asort($alternatives);

        return array_keys($alternatives);
    }
}
Copyright (c) 2004-2013 Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Descriptor;

use Symfony\Component\Console\Output\OutputInterface;

/**
 * Descriptor interface.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
interface DescriptorInterface
{
    /**
     * Describes an InputArgument instance.
     *
     * @param OutputInterface $output
     * @param object          $object
     * @param array           $options
     */
    public function describe(OutputInterface $output, $object, array $options = array());
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Descriptor;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;

/**
 * Text descriptor.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class TextDescriptor extends Descriptor
{
    /**
     * {@inheritdoc}
     */
    protected function describeInputArgument(InputArgument $argument, array $options = array())
    {
        if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) {
            $default = sprintf('<comment> (default: %s)</comment>', $this->formatDefaultValue($argument->getDefault()));
        } else {
            $default = '';
        }

        $nameWidth = isset($options['name_width']) ? $options['name_width'] : strlen($argument->getName());

        $this->writeText(sprintf(" <info>%-${nameWidth}s</info> %s%s",
            $argument->getName(),
            str_replace("\n", "\n".str_repeat(' ', $nameWidth + 2), $argument->getDescription()),
            $default
        ), $options);
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputOption(InputOption $option, array $options = array())
    {
        if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) {
            $default = sprintf('<comment> (default: %s)</comment>', $this->formatDefaultValue($option->getDefault()));
        } else {
            $default = '';
        }

        $nameWidth = isset($options['name_width']) ? $options['name_width'] : strlen($option->getName());
        $nameWithShortcutWidth = $nameWidth - strlen($option->getName()) - 2;

        $this->writeText(sprintf(" <info>%s</info> %-${nameWithShortcutWidth}s%s%s%s",
            '--'.$option->getName(),
            $option->getShortcut() ? sprintf('(-%s) ', $option->getShortcut()) : '',
            str_replace("\n", "\n".str_repeat(' ', $nameWidth + 2), $option->getDescription()),
            $default,
            $option->isArray() ? '<comment> (multiple values allowed)</comment>' : ''
        ), $options);
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputDefinition(InputDefinition $definition, array $options = array())
    {
        $nameWidth = 0;
        foreach ($definition->getOptions() as $option) {
            $nameLength = strlen($option->getName()) + 2;
            if ($option->getShortcut()) {
                $nameLength += strlen($option->getShortcut()) + 3;
            }
            $nameWidth = max($nameWidth, $nameLength);
        }
        foreach ($definition->getArguments() as $argument) {
            $nameWidth = max($nameWidth, strlen($argument->getName()));
        }
        ++$nameWidth;

        if ($definition->getArguments()) {
            $this->writeText('<comment>Arguments:</comment>', $options);
            $this->writeText("\n");
            foreach ($definition->getArguments() as $argument) {
                $this->describeInputArgument($argument, array_merge($options, array('name_width' => $nameWidth)));
                $this->writeText("\n");
            }
        }

        if ($definition->getArguments() && $definition->getOptions()) {
            $this->writeText("\n");
        }

        if ($definition->getOptions()) {
            $this->writeText('<comment>Options:</comment>', $options);
            $this->writeText("\n");
            foreach ($definition->getOptions() as $option) {
                $this->describeInputOption($option, array_merge($options, array('name_width' => $nameWidth)));
                $this->writeText("\n");
            }
        }
    }

    /**
     * {@inheritdoc}
     */
    protected function describeCommand(Command $command, array $options = array())
    {
        $command->getSynopsis();
        $command->mergeApplicationDefinition(false);

        $this->writeText('<comment>Usage:</comment>', $options);
        $this->writeText("\n");
        $this->writeText(' '.$command->getSynopsis(), $options);
        $this->writeText("\n");

        if (count($command->getAliases()) > 0) {
            $this->writeText("\n");
            $this->writeText('<comment>Aliases:</comment> <info>'.implode(', ', $command->getAliases()).'</info>', $options);
        }

        if ($definition = $command->getNativeDefinition()) {
            $this->writeText("\n");
            $this->describeInputDefinition($definition, $options);
        }

        $this->writeText("\n");

        if ($help = $command->getProcessedHelp()) {
            $this->writeText('<comment>Help:</comment>', $options);
            $this->writeText("\n");
            $this->writeText(' '.str_replace("\n", "\n ", $help), $options);
            $this->writeText("\n");
        }
    }

    /**
     * {@inheritdoc}
     */
    protected function describeApplication(Application $application, array $options = array())
    {
        $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
        $description = new ApplicationDescription($application, $describedNamespace);

        if (isset($options['raw_text']) && $options['raw_text']) {
            $width = $this->getColumnWidth($description->getCommands());

            foreach ($description->getCommands() as $command) {
                $this->writeText(sprintf("%-${width}s %s", $command->getName(), $command->getDescription()), $options);
                $this->writeText("\n");
            }
        } else {
            $width = $this->getColumnWidth($description->getCommands());

            $this->writeText($application->getHelp(), $options);
            $this->writeText("\n\n");

            if ($describedNamespace) {
                $this->writeText(sprintf("<comment>Available commands for the \"%s\" namespace:</comment>", $describedNamespace), $options);
            } else {
                $this->writeText('<comment>Available commands:</comment>', $options);
            }

            // add commands by namespace
            foreach ($description->getNamespaces() as $namespace) {
                if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
                    $this->writeText("\n");
                    $this->writeText('<comment>'.$namespace['id'].'</comment>', $options);
                }

                foreach ($namespace['commands'] as $name) {
                    $this->writeText("\n");
                    $this->writeText(sprintf("  <info>%-${width}s</info> %s", $name, $description->getCommand($name)->getDescription()), $options);
                }
            }

            $this->writeText("\n");
        }
    }

    /**
     * {@inheritdoc}
     */
    private function writeText($content, array $options = array())
    {
        $this->write(
            isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content,
            isset($options['raw_output']) ? !$options['raw_output'] : true
        );
    }

    /**
     * Formats input option/argument default value.
     *
     * @param mixed $default
     *
     * @return string
     */
    private function formatDefaultValue($default)
    {
        if (version_compare(PHP_VERSION, '5.4', '<')) {
            return str_replace('\/', '/', json_encode($default));
        }

        return json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
    }

    /**
     * @param Command[] $commands
     *
     * @return int
     */
    private function getColumnWidth(array $commands)
    {
        $width = 0;
        foreach ($commands as $command) {
            $width = strlen($command->getName()) > $width ? strlen($command->getName()) : $width;
        }

        return $width + 2;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Descriptor;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
abstract class Descriptor implements DescriptorInterface
{
    /**
     * @var OutputInterface
     */
    private $output;

    /**
     * {@inheritdoc}
     */
    public function describe(OutputInterface $output, $object, array $options = array())
    {
        $this->output = $output;

        switch (true) {
            case $object instanceof InputArgument:
                $this->describeInputArgument($object, $options);
                break;
            case $object instanceof InputOption:
                $this->describeInputOption($object, $options);
                break;
            case $object instanceof InputDefinition:
                $this->describeInputDefinition($object, $options);
                break;
            case $object instanceof Command:
                $this->describeCommand($object, $options);
                break;
            case $object instanceof Application:
                $this->describeApplication($object, $options);
                break;
            default:
                throw new \InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_class($object)));
        }
    }

    /**
     * Writes content to output.
     *
     * @param string  $content
     * @param boolean $decorated
     */
    protected function write($content, $decorated = false)
    {
        $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW);
    }

    /**
     * Describes an InputArgument instance.
     *
     * @param InputArgument $argument
     * @param array         $options
     *
     * @return string|mixed
     */
    abstract protected function describeInputArgument(InputArgument $argument, array $options = array());

    /**
     * Describes an InputOption instance.
     *
     * @param InputOption $option
     * @param array       $options
     *
     * @return string|mixed
     */
    abstract protected function describeInputOption(InputOption $option, array $options = array());

    /**
     * Describes an InputDefinition instance.
     *
     * @param InputDefinition $definition
     * @param array           $options
     *
     * @return string|mixed
     */
    abstract protected function describeInputDefinition(InputDefinition $definition, array $options = array());

    /**
     * Describes a Command instance.
     *
     * @param Command $command
     * @param array   $options
     *
     * @return string|mixed
     */
    abstract protected function describeCommand(Command $command, array $options = array());

    /**
     * Describes an Application instance.
     *
     * @param Application $application
     * @param array       $options
     *
     * @return string|mixed
     */
    abstract protected function describeApplication(Application $application, array $options = array());
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Descriptor;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;

/**
 * Markdown descriptor.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class MarkdownDescriptor extends Descriptor
{
    /**
     * {@inheritdoc}
     */
    protected function describeInputArgument(InputArgument $argument, array $options = array())
    {
        $this->write(
            '**'.$argument->getName().':**'."\n\n"
            .'* Name: '.($argument->getName() ?: '<none>')."\n"
            .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n"
            .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n"
            .'* Description: '.($argument->getDescription() ?: '<none>')."\n"
            .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`'
        );
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputOption(InputOption $option, array $options = array())
    {
        $this->write(
            '**'.$option->getName().':**'."\n\n"
            .'* Name: `--'.$option->getName().'`'."\n"
            .'* Shortcut: '.($option->getShortcut() ? '`-'.implode('|-', explode('|', $option->getShortcut())).'`' : '<none>')."\n"
            .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n"
            .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n"
            .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n"
            .'* Description: '.($option->getDescription() ?: '<none>')."\n"
            .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`'
        );
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputDefinition(InputDefinition $definition, array $options = array())
    {
        if ($showArguments = count($definition->getArguments()) > 0) {
            $this->write('### Arguments:');
            foreach ($definition->getArguments() as $argument) {
                $this->write("\n\n");
                $this->write($this->describeInputArgument($argument));
            }
        }

        if (count($definition->getOptions()) > 0) {
            if ($showArguments) {
                $this->write("\n\n");
            }

            $this->write('### Options:');
            foreach ($definition->getOptions() as $option) {
                $this->write("\n\n");
                $this->write($this->describeInputOption($option));
            }
        }
    }

    /**
     * {@inheritdoc}
     */
    protected function describeCommand(Command $command, array $options = array())
    {
        $command->getSynopsis();
        $command->mergeApplicationDefinition(false);

        $this->write(
            $command->getName()."\n"
            .str_repeat('-', strlen($command->getName()))."\n\n"
            .'* Description: '.($command->getDescription() ?: '<none>')."\n"
            .'* Usage: `'.$command->getSynopsis().'`'."\n"
            .'* Aliases: '.(count($command->getAliases()) ? '`'.implode('`, `', $command->getAliases()).'`' : '<none>')
        );

        if ($help = $command->getProcessedHelp()) {
            $this->write("\n\n");
            $this->write($help);
        }

        if ($definition = $command->getNativeDefinition()) {
            $this->write("\n\n");
            $this->describeInputDefinition($command->getNativeDefinition());
        }
    }

    /**
     * {@inheritdoc}
     */
    protected function describeApplication(Application $application, array $options = array())
    {
        $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
        $description = new ApplicationDescription($application, $describedNamespace);

        $this->write($application->getName()."\n".str_repeat('=', strlen($application->getName())));

        foreach ($description->getNamespaces() as $namespace) {
            if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
                $this->write("\n\n");
                $this->write('**'.$namespace['id'].':**');
            }

            $this->write("\n\n");
            $this->write(implode("\n", array_map(function ($commandName) {
                return '* '.$commandName;
            } , $namespace['commands'])));
        }

        foreach ($description->getCommands() as $command) {
            $this->write("\n\n");
            $this->write($this->describeCommand($command));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Descriptor;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;

/**
 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
 */
class ApplicationDescription
{
    const GLOBAL_NAMESPACE = '_global';

    /**
     * @var Application
     */
    private $application;

    /**
     * @var null|string
     */
    private $namespace;

    /**
     * @var array
     */
    private $namespaces;

    /**
     * @var Command[]
     */
    private $commands;

    /**
     * @var Command[]
     */
    private $aliases;

    /**
     * Constructor.
     *
     * @param Application $application
     * @param string|null $namespace
     */
    public function __construct(Application $application, $namespace = null)
    {
        $this->application = $application;
        $this->namespace = $namespace;
    }

    /**
     * @return array
     */
    public function getNamespaces()
    {
        if (null === $this->namespaces) {
            $this->inspectApplication();
        }

        return $this->namespaces;
    }

    /**
     * @return Command[]
     */
    public function getCommands()
    {
        if (null === $this->commands) {
            $this->inspectApplication();
        }

        return $this->commands;
    }

    /**
     * @param string $name
     *
     * @return Command
     *
     * @throws \InvalidArgumentException
     */
    public function getCommand($name)
    {
        if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) {
            throw new \InvalidArgumentException(sprintf('Command %s does not exist.', $name));
        }

        return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name];
    }

    private function inspectApplication()
    {
        $this->commands = array();
        $this->namespaces = array();

        $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null);
        foreach ($this->sortCommands($all) as $namespace => $commands) {
            $names = array();

            /** @var Command $command */
            foreach ($commands as $name => $command) {
                if (!$command->getName()) {
                    continue;
                }

                if ($command->getName() === $name) {
                    $this->commands[$name] = $command;
                } else {
                    $this->aliases[$name] = $command;
                }

                $names[] = $name;
            }

            $this->namespaces[$namespace] = array('id' => $namespace, 'commands' => $names);
        }
    }

    /**
     * @param array $commands
     *
     * @return array
     */
    private function sortCommands(array $commands)
    {
        $namespacedCommands = array();
        foreach ($commands as $name => $command) {
            $key = $this->application->extractNamespace($name, 1);
            if (!$key) {
                $key = '_global';
            }

            $namespacedCommands[$key][$name] = $command;
        }
        ksort($namespacedCommands);

        foreach ($namespacedCommands as &$commands) {
            ksort($commands);
        }

        return $namespacedCommands;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Descriptor;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;

/**
 * XML descriptor.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class XmlDescriptor extends Descriptor
{
    /**
     * @param InputDefinition $definition
     *
     * @return \DOMDocument
     */
    public function getInputDefinitionDocument(InputDefinition $definition)
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($definitionXML = $dom->createElement('definition'));

        $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
        foreach ($definition->getArguments() as $argument) {
            $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument));
        }

        $definitionXML->appendChild($optionsXML = $dom->createElement('options'));
        foreach ($definition->getOptions() as $option) {
            $this->appendDocument($optionsXML, $this->getInputOptionDocument($option));
        }

        return $dom;
    }

    /**
     * @param Command $command
     *
     * @return \DOMDocument
     */
    public function getCommandDocument(Command $command)
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($commandXML = $dom->createElement('command'));

        $command->getSynopsis();
        $command->mergeApplicationDefinition(false);

        $commandXML->setAttribute('id', $command->getName());
        $commandXML->setAttribute('name', $command->getName());

        $commandXML->appendChild($usageXML = $dom->createElement('usage'));
        $usageXML->appendChild($dom->createTextNode(sprintf($command->getSynopsis(), '')));

        $commandXML->appendChild($descriptionXML = $dom->createElement('description'));
        $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription())));

        $commandXML->appendChild($helpXML = $dom->createElement('help'));
        $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp())));

        $commandXML->appendChild($aliasesXML = $dom->createElement('aliases'));
        foreach ($command->getAliases() as $alias) {
            $aliasesXML->appendChild($aliasXML = $dom->createElement('alias'));
            $aliasXML->appendChild($dom->createTextNode($alias));
        }

        $definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition());
        $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0));

        return $dom;
    }

    /**
     * @param Application $application
     * @param string|null $namespace
     *
     * @return \DOMDocument
     */
    public function getApplicationDocument(Application $application, $namespace = null)
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($rootXml = $dom->createElement('symfony'));

        if ($application->getName() !== 'UNKNOWN') {
            $rootXml->setAttribute('name', $application->getName());
            if ($application->getVersion() !== 'UNKNOWN') {
                $rootXml->setAttribute('version', $application->getVersion());
            }
        }

        $rootXml->appendChild($commandsXML = $dom->createElement('commands'));

        $description = new ApplicationDescription($application, $namespace);

        if ($namespace) {
            $commandsXML->setAttribute('namespace', $namespace);
        }

        foreach ($description->getCommands() as $command) {
            $this->appendDocument($commandsXML, $this->getCommandDocument($command));
        }

        if (!$namespace) {
            $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces'));

            foreach ($description->getNamespaces() as $namespaceDescription) {
                $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace'));
                $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']);

                foreach ($namespaceDescription['commands'] as $name) {
                    $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command'));
                    $commandXML->appendChild($dom->createTextNode($name));
                }
            }
        }

        return $dom;
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputArgument(InputArgument $argument, array $options = array())
    {
        $this->writeDocument($this->getInputArgumentDocument($argument));
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputOption(InputOption $option, array $options = array())
    {
        $this->writeDocument($this->getInputOptionDocument($option));
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputDefinition(InputDefinition $definition, array $options = array())
    {
        $this->writeDocument($this->getInputDefinitionDocument($definition));
    }

    /**
     * {@inheritdoc}
     */
    protected function describeCommand(Command $command, array $options = array())
    {
        $this->writeDocument($this->getCommandDocument($command));
    }

    /**
     * {@inheritdoc}
     */
    protected function describeApplication(Application $application, array $options = array())
    {
        $this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null));
    }

    /**
     * Appends document children to parent node.
     *
     * @param \DOMNode $parentNode
     * @param \DOMNode $importedParent
     */
    private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent)
    {
        foreach ($importedParent->childNodes as $childNode) {
            $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true));
        }
    }

    /**
     * Writes DOM document.
     *
     * @param \DOMDocument $dom
     *
     * @return \DOMDocument|string
     */
    private function writeDocument(\DOMDocument $dom)
    {
        $dom->formatOutput = true;
        $this->write($dom->saveXML());
    }

    /**
     * @param InputArgument $argument
     *
     * @return \DOMDocument
     */
    private function getInputArgumentDocument(InputArgument $argument)
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');

        $dom->appendChild($objectXML = $dom->createElement('argument'));
        $objectXML->setAttribute('name', $argument->getName());
        $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
        $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
        $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
        $descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));

        $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
        $defaults = is_array($argument->getDefault()) ? $argument->getDefault() : (is_bool($argument->getDefault()) ? array(var_export($argument->getDefault(), true)) : ($argument->getDefault() ? array($argument->getDefault()) : array()));
        foreach ($defaults as $default) {
            $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
            $defaultXML->appendChild($dom->createTextNode($default));
        }

        return $dom;
    }

    /**
     * @param InputOption $option
     *
     * @return \DOMDocument
     */
    private function getInputOptionDocument(InputOption $option)
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');

        $dom->appendChild($objectXML = $dom->createElement('option'));
        $objectXML->setAttribute('name', '--'.$option->getName());
        $pos = strpos($option->getShortcut(), '|');
        if (false !== $pos) {
            $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos));
            $objectXML->setAttribute('shortcuts', '-'.implode('|-', explode('|', $option->getShortcut())));
        } else {
            $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
        }
        $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0);
        $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0);
        $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
        $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
        $descriptionXML->appendChild($dom->createTextNode($option->getDescription()));

        if ($option->acceptValue()) {
            $defaults = is_array($option->getDefault()) ? $option->getDefault() : (is_bool($option->getDefault()) ? array(var_export($option->getDefault(), true)) : ($option->getDefault() ? array($option->getDefault()) : array()));
            $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));

            if (!empty($defaults)) {
                foreach ($defaults as $default) {
                    $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
                    $defaultXML->appendChild($dom->createTextNode($default));
                }
            }
        }

        return $dom;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Descriptor;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;

/**
 * JSON descriptor.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class JsonDescriptor extends Descriptor
{
    /**
     * {@inheritdoc}
     */
    protected function describeInputArgument(InputArgument $argument, array $options = array())
    {
        $this->writeData($this->getInputArgumentData($argument), $options);
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputOption(InputOption $option, array $options = array())
    {
        $this->writeData($this->getInputOptionData($option), $options);
    }

    /**
     * {@inheritdoc}
     */
    protected function describeInputDefinition(InputDefinition $definition, array $options = array())
    {
        $this->writeData($this->getInputDefinitionData($definition), $options);
    }

    /**
     * {@inheritdoc}
     */
    protected function describeCommand(Command $command, array $options = array())
    {
        $this->writeData($this->getCommandData($command), $options);
    }

    /**
     * {@inheritdoc}
     */
    protected function describeApplication(Application $application, array $options = array())
    {
        $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
        $description = new ApplicationDescription($application, $describedNamespace);
        $commands = array();

        foreach ($description->getCommands() as $command) {
            $commands[] = $this->getCommandData($command);
        }

        $data = $describedNamespace
            ? array('commands' => $commands, 'namespace' => $describedNamespace)
            : array('commands' => $commands, 'namespaces' => array_values($description->getNamespaces()));

        $this->writeData($data, $options);
    }

    /**
     * Writes data as json.
     *
     * @param array $data
     * @param array $options
     *
     * @return array|string
     */
    private function writeData(array $data, array $options)
    {
        $this->write(json_encode($data, isset($options['json_encoding']) ? $options['json_encoding'] : 0));
    }

    /**
     * @param InputArgument $argument
     *
     * @return array
     */
    private function getInputArgumentData(InputArgument $argument)
    {
        return array(
            'name'        => $argument->getName(),
            'is_required' => $argument->isRequired(),
            'is_array'    => $argument->isArray(),
            'description' => $argument->getDescription(),
            'default'     => $argument->getDefault(),
        );
    }

    /**
     * @param InputOption $option
     *
     * @return array
     */
    private function getInputOptionData(InputOption $option)
    {
        return array(
            'name'              => '--'.$option->getName(),
            'shortcut'          => $option->getShortcut() ? '-'.implode('|-', explode('|', $option->getShortcut())) : '',
            'accept_value'      => $option->acceptValue(),
            'is_value_required' => $option->isValueRequired(),
            'is_multiple'       => $option->isArray(),
            'description'       => $option->getDescription(),
            'default'           => $option->getDefault(),
        );
    }

    /**
     * @param InputDefinition $definition
     *
     * @return array
     */
    private function getInputDefinitionData(InputDefinition $definition)
    {
        $inputArguments = array();
        foreach ($definition->getArguments() as $name => $argument) {
            $inputArguments[$name] = $this->getInputArgumentData($argument);
        }

        $inputOptions = array();
        foreach ($definition->getOptions() as $name => $option) {
            $inputOptions[$name] = $this->getInputOptionData($option);
        }

        return array('arguments' => $inputArguments, 'options' => $inputOptions);
    }

    /**
     * @param Command $command
     *
     * @return array
     */
    private function getCommandData(Command $command)
    {
        $command->getSynopsis();
        $command->mergeApplicationDefinition(false);

        return array(
            'name'        => $command->getName(),
            'usage'       => $command->getSynopsis(),
            'description' => $command->getDescription(),
            'help'        => $command->getProcessedHelp(),
            'aliases'     => $command->getAliases(),
            'definition'  => $this->getInputDefinitionData($command->getNativeDefinition()),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Output;

use Symfony\Component\Console\Formatter\OutputFormatter;
use Symfony\Component\Console\Formatter\OutputFormatterInterface;

/**
 * NullOutput suppresses all output.
 *
 *     $output = new NullOutput();
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 *
 * @api
 */
class NullOutput implements OutputInterface
{
    /**
     * {@inheritdoc}
     */
    public function setFormatter(OutputFormatterInterface $formatter)
    {
        // do nothing
    }

    /**
     * {@inheritdoc}
     */
    public function getFormatter()
    {
        // to comply with the interface we must return a OutputFormatterInterface
        return new OutputFormatter();
    }

    /**
     * {@inheritdoc}
     */
    public function setDecorated($decorated)
    {
        // do nothing
    }

    /**
     * {@inheritdoc}
     */
    public function isDecorated()
    {
        return false;
    }

    /**
     * {@inheritdoc}
     */
    public function setVerbosity($level)
    {
        // do nothing
    }

    /**
     * {@inheritdoc}
     */
    public function getVerbosity()
    {
        return self::VERBOSITY_QUIET;
    }

    /**
     * {@inheritdoc}
     */
    public function writeln($messages, $type = self::OUTPUT_NORMAL)
    {
        // do nothing
    }

    /**
     * {@inheritdoc}
     */
    public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
    {
        // do nothing
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Output;

use Symfony\Component\Console\Formatter\OutputFormatterInterface;

/**
 * OutputInterface is the interface implemented by all Output classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface OutputInterface
{
    const VERBOSITY_QUIET        = 0;
    const VERBOSITY_NORMAL       = 1;
    const VERBOSITY_VERBOSE      = 2;
    const VERBOSITY_VERY_VERBOSE = 3;
    const VERBOSITY_DEBUG        = 4;

    const OUTPUT_NORMAL = 0;
    const OUTPUT_RAW    = 1;
    const OUTPUT_PLAIN  = 2;

    /**
     * Writes a message to the output.
     *
     * @param string|array $messages The message as an array of lines or a single string
     * @param Boolean      $newline  Whether to add a newline
     * @param integer      $type     The type of output (one of the OUTPUT constants)
     *
     * @throws \InvalidArgumentException When unknown output type is given
     *
     * @api
     */
    public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL);

    /**
     * Writes a message to the output and adds a newline at the end.
     *
     * @param string|array $messages The message as an array of lines of a single string
     * @param integer      $type     The type of output (one of the OUTPUT constants)
     *
     * @throws \InvalidArgumentException When unknown output type is given
     *
     * @api
     */
    public function writeln($messages, $type = self::OUTPUT_NORMAL);

    /**
     * Sets the verbosity of the output.
     *
     * @param integer $level The level of verbosity (one of the VERBOSITY constants)
     *
     * @api
     */
    public function setVerbosity($level);

    /**
     * Gets the current verbosity of the output.
     *
     * @return integer The current level of verbosity (one of the VERBOSITY constants)
     *
     * @api
     */
    public function getVerbosity();

    /**
     * Sets the decorated flag.
     *
     * @param Boolean $decorated Whether to decorate the messages
     *
     * @api
     */
    public function setDecorated($decorated);

    /**
     * Gets the decorated flag.
     *
     * @return Boolean true if the output will decorate messages, false otherwise
     *
     * @api
     */
    public function isDecorated();

    /**
     * Sets output formatter.
     *
     * @param OutputFormatterInterface $formatter
     *
     * @api
     */
    public function setFormatter(OutputFormatterInterface $formatter);

    /**
     * Returns current output formatter instance.
     *
     * @return  OutputFormatterInterface
     *
     * @api
     */
    public function getFormatter();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Output;

use Symfony\Component\Console\Formatter\OutputFormatterInterface;

/**
 * StreamOutput writes the output to a given stream.
 *
 * Usage:
 *
 * $output = new StreamOutput(fopen('php://stdout', 'w'));
 *
 * As `StreamOutput` can use any stream, you can also use a file:
 *
 * $output = new StreamOutput(fopen('/path/to/output.log', 'a', false));
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class StreamOutput extends Output
{
    private $stream;

    /**
     * Constructor.
     *
     * @param mixed                         $stream    A stream resource
     * @param integer                       $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
     * @param Boolean|null                  $decorated Whether to decorate messages (null for auto-guessing)
     * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter)
     *
     * @throws \InvalidArgumentException When first argument is not a real stream
     *
     * @api
     */
    public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
    {
        if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) {
            throw new \InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
        }

        $this->stream = $stream;

        if (null === $decorated) {
            $decorated = $this->hasColorSupport();
        }

        parent::__construct($verbosity, $decorated, $formatter);
    }

    /**
     * Gets the stream attached to this StreamOutput instance.
     *
     * @return resource A stream resource
     */
    public function getStream()
    {
        return $this->stream;
    }

    /**
     * {@inheritdoc}
     */
    protected function doWrite($message, $newline)
    {
        if (false === @fwrite($this->stream, $message.($newline ? PHP_EOL : ''))) {
            // @codeCoverageIgnoreStart
            // should never happen
            throw new \RuntimeException('Unable to write output.');
            // @codeCoverageIgnoreEnd
        }

        fflush($this->stream);
    }

    /**
     * Returns true if the stream supports colorization.
     *
     * Colorization is disabled if not supported by the stream:
     *
     *  -  windows without ansicon and ConEmu
     *  -  non tty consoles
     *
     * @return Boolean true if the stream supports colorization, false otherwise
     */
    protected function hasColorSupport()
    {
        // @codeCoverageIgnoreStart
        if (DIRECTORY_SEPARATOR == '\\') {
            return false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI');
        }

        return function_exists('posix_isatty') && @posix_isatty($this->stream);
        // @codeCoverageIgnoreEnd
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Output;

use Symfony\Component\Console\Formatter\OutputFormatterInterface;
use Symfony\Component\Console\Formatter\OutputFormatter;

/**
 * Base class for output classes.
 *
 * There are five levels of verbosity:
 *
 *  * normal: no option passed (normal output)
 *  * verbose: -v (more output)
 *  * very verbose: -vv (highly extended output)
 *  * debug: -vvv (all debug output)
 *  * quiet: -q (no output)
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
abstract class Output implements OutputInterface
{
    private $verbosity;
    private $formatter;

    /**
     * Constructor.
     *
     * @param integer                       $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
     * @param Boolean                       $decorated Whether to decorate messages
     * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter)
     *
     * @api
     */
    public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = false, OutputFormatterInterface $formatter = null)
    {
        $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity;
        $this->formatter = $formatter ?: new OutputFormatter();
        $this->formatter->setDecorated($decorated);
    }

    /**
     * {@inheritdoc}
     */
    public function setFormatter(OutputFormatterInterface $formatter)
    {
        $this->formatter = $formatter;
    }

    /**
     * {@inheritdoc}
     */
    public function getFormatter()
    {
        return $this->formatter;
    }

    /**
     * {@inheritdoc}
     */
    public function setDecorated($decorated)
    {
        $this->formatter->setDecorated($decorated);
    }

    /**
     * {@inheritdoc}
     */
    public function isDecorated()
    {
        return $this->formatter->isDecorated();
    }

    /**
     * {@inheritdoc}
     */
    public function setVerbosity($level)
    {
        $this->verbosity = (int) $level;
    }

    /**
     * {@inheritdoc}
     */
    public function getVerbosity()
    {
        return $this->verbosity;
    }

    public function isQuiet()
    {
        return self::VERBOSITY_QUIET === $this->verbosity;
    }

    public function isVerbose()
    {
        return self::VERBOSITY_VERBOSE <= $this->verbosity;
    }

    public function isVeryVerbose()
    {
        return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity;
    }

    public function isDebug()
    {
        return self::VERBOSITY_DEBUG <= $this->verbosity;
    }

    /**
     * {@inheritdoc}
     */
    public function writeln($messages, $type = self::OUTPUT_NORMAL)
    {
        $this->write($messages, true, $type);
    }

    /**
     * {@inheritdoc}
     */
    public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
    {
        if (self::VERBOSITY_QUIET === $this->verbosity) {
            return;
        }

        $messages = (array) $messages;

        foreach ($messages as $message) {
            switch ($type) {
                case OutputInterface::OUTPUT_NORMAL:
                    $message = $this->formatter->format($message);
                    break;
                case OutputInterface::OUTPUT_RAW:
                    break;
                case OutputInterface::OUTPUT_PLAIN:
                    $message = strip_tags($this->formatter->format($message));
                    break;
                default:
                    throw new \InvalidArgumentException(sprintf('Unknown output type given (%s)', $type));
            }

            $this->doWrite($message, $newline);
        }
    }

    /**
     * Writes a message to the output.
     *
     * @param string  $message A message to write to the output
     * @param Boolean $newline Whether to add a newline or not
     */
    abstract protected function doWrite($message, $newline);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Output;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class BufferedOutput extends Output
{
    /**
     * @var string
     */
    private $buffer = '';

    /**
     * Empties buffer and returns its content.
     *
     * @return string
     */
    public function fetch()
    {
        $content = $this->buffer;
        $this->buffer = '';

        return $content;
    }

    /**
     * {@inheritdoc}
     */
    protected function doWrite($message, $newline)
    {
        $this->buffer .= $message;

        if ($newline) {
            $this->buffer .= "\n";
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Output;

use Symfony\Component\Console\Output\OutputInterface;

/**
 * ConsoleOutputInterface is the interface implemented by ConsoleOutput class.
 * This adds information about stderr output stream.
 *
 * @author Dariusz Górecki <darek.krk@gmail.com>
 */
interface ConsoleOutputInterface extends OutputInterface
{
    /**
     * Gets the OutputInterface for errors.
     *
     * @return OutputInterface
     */
    public function getErrorOutput();

    /**
     * Sets the OutputInterface used for errors.
     *
     * @param OutputInterface $error
     */
    public function setErrorOutput(OutputInterface $error);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Output;

use Symfony\Component\Console\Formatter\OutputFormatterInterface;
use Symfony\Component\Console\Output\ConsoleOutputInterface;

/**
 * ConsoleOutput is the default class for all CLI output. It uses STDOUT.
 *
 * This class is a convenient wrapper around `StreamOutput`.
 *
 *     $output = new ConsoleOutput();
 *
 * This is equivalent to:
 *
 *     $output = new StreamOutput(fopen('php://stdout', 'w'));
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
{
    private $stderr;

    /**
     * Constructor.
     *
     * @param integer                       $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
     * @param Boolean|null                  $decorated Whether to decorate messages (null for auto-guessing)
     * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter)
     *
     * @api
     */
    public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
    {
        $outputStream = 'php://stdout';
        if (!$this->hasStdoutSupport()) {
            $outputStream = 'php://output';
        }

        parent::__construct(fopen($outputStream, 'w'), $verbosity, $decorated, $formatter);

        $this->stderr = new StreamOutput(fopen('php://stderr', 'w'), $verbosity, $decorated, $formatter);
    }

    /**
     * {@inheritdoc}
     */
    public function setDecorated($decorated)
    {
        parent::setDecorated($decorated);
        $this->stderr->setDecorated($decorated);
    }

    /**
     * {@inheritdoc}
     */
    public function setFormatter(OutputFormatterInterface $formatter)
    {
        parent::setFormatter($formatter);
        $this->stderr->setFormatter($formatter);
    }

    /**
     * {@inheritdoc}
     */
    public function setVerbosity($level)
    {
        parent::setVerbosity($level);
        $this->stderr->setVerbosity($level);
    }

    /**
     * {@inheritdoc}
     */
    public function getErrorOutput()
    {
        return $this->stderr;
    }

    /**
     * {@inheritdoc}
     */
    public function setErrorOutput(OutputInterface $error)
    {
        $this->stderr = $error;
    }

    /**
     * Returns true if current environment supports writing console output to
     * STDOUT.
     *
     * IBM iSeries (OS400) exhibits character-encoding issues when writing to
     * STDOUT and doesn't properly convert ASCII to EBCDIC, resulting in garbage
     * output.
     *
     * @return boolean
     */
    protected function hasStdoutSupport()
    {
        return ('OS400' != php_uname('s'));
    }
}
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="vendor/autoload.php"
>
    <testsuites>
        <testsuite name="Symfony Console Component Test Suite">
            <directory>./Tests/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>./</directory>
            <exclude>
                <directory>./Resources</directory>
                <directory>./Tests</directory>
                <directory>./vendor</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

/**
 * Represents a command line option.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class InputOption
{
    const VALUE_NONE     = 1;
    const VALUE_REQUIRED = 2;
    const VALUE_OPTIONAL = 4;
    const VALUE_IS_ARRAY = 8;

    private $name;
    private $shortcut;
    private $mode;
    private $default;
    private $description;

    /**
     * Constructor.
     *
     * @param string       $name        The option name
     * @param string|array $shortcut    The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts
     * @param integer      $mode        The option mode: One of the VALUE_* constants
     * @param string       $description A description text
     * @param mixed        $default     The default value (must be null for self::VALUE_REQUIRED or self::VALUE_NONE)
     *
     * @throws \InvalidArgumentException If option mode is invalid or incompatible
     *
     * @api
     */
    public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null)
    {
        if (0 === strpos($name, '--')) {
            $name = substr($name, 2);
        }

        if (empty($name)) {
            throw new \InvalidArgumentException('An option name cannot be empty.');
        }

        if (empty($shortcut)) {
            $shortcut = null;
        }

        if (null !== $shortcut) {
            if (is_array($shortcut)) {
                $shortcut = implode('|', $shortcut);
            }
            $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-'));
            $shortcuts = array_filter($shortcuts);
            $shortcut = implode('|', $shortcuts);

            if (empty($shortcut)) {
                throw new \InvalidArgumentException('An option shortcut cannot be empty.');
            }
        }

        if (null === $mode) {
            $mode = self::VALUE_NONE;
        } elseif (!is_int($mode) || $mode > 15 || $mode < 1) {
            throw new \InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode));
        }

        $this->name        = $name;
        $this->shortcut    = $shortcut;
        $this->mode        = $mode;
        $this->description = $description;

        if ($this->isArray() && !$this->acceptValue()) {
            throw new \InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.');
        }

        $this->setDefault($default);
    }

    /**
     * Returns the option shortcut.
     *
     * @return string The shortcut
     */
    public function getShortcut()
    {
        return $this->shortcut;
    }

    /**
     * Returns the option name.
     *
     * @return string The name
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Returns true if the option accepts a value.
     *
     * @return Boolean true if value mode is not self::VALUE_NONE, false otherwise
     */
    public function acceptValue()
    {
        return $this->isValueRequired() || $this->isValueOptional();
    }

    /**
     * Returns true if the option requires a value.
     *
     * @return Boolean true if value mode is self::VALUE_REQUIRED, false otherwise
     */
    public function isValueRequired()
    {
        return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode);
    }

    /**
     * Returns true if the option takes an optional value.
     *
     * @return Boolean true if value mode is self::VALUE_OPTIONAL, false otherwise
     */
    public function isValueOptional()
    {
        return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode);
    }

    /**
     * Returns true if the option can take multiple values.
     *
     * @return Boolean true if mode is self::VALUE_IS_ARRAY, false otherwise
     */
    public function isArray()
    {
        return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode);
    }

    /**
     * Sets the default value.
     *
     * @param mixed $default The default value
     *
     * @throws \LogicException When incorrect default value is given
     */
    public function setDefault($default = null)
    {
        if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) {
            throw new \LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.');
        }

        if ($this->isArray()) {
            if (null === $default) {
                $default = array();
            } elseif (!is_array($default)) {
                throw new \LogicException('A default value for an array option must be an array.');
            }
        }

        $this->default = $this->acceptValue() ? $default : false;
    }

    /**
     * Returns the default value.
     *
     * @return mixed The default value
     */
    public function getDefault()
    {
        return $this->default;
    }

    /**
     * Returns the description text.
     *
     * @return string The description text
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     * Checks whether the given option equals this one
     *
     * @param InputOption $option option to compare
     * @return Boolean
     */
    public function equals(InputOption $option)
    {
        return $option->getName() === $this->getName()
            && $option->getShortcut() === $this->getShortcut()
            && $option->getDefault() === $this->getDefault()
            && $option->isArray() === $this->isArray()
            && $option->isValueRequired() === $this->isValueRequired()
            && $option->isValueOptional() === $this->isValueOptional()
        ;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

/**
 * InputInterface is the interface implemented by all input classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface InputInterface
{
    /**
     * Returns the first argument from the raw parameters (not parsed).
     *
     * @return string The value of the first argument or null otherwise
     */
    public function getFirstArgument();

    /**
     * Returns true if the raw parameters (not parsed) contain a value.
     *
     * This method is to be used to introspect the input parameters
     * before they have been validated. It must be used carefully.
     *
     * @param string|array $values The values to look for in the raw parameters (can be an array)
     *
     * @return Boolean true if the value is contained in the raw parameters
     */
    public function hasParameterOption($values);

    /**
     * Returns the value of a raw option (not parsed).
     *
     * This method is to be used to introspect the input parameters
     * before they have been validated. It must be used carefully.
     *
     * @param string|array $values  The value(s) to look for in the raw parameters (can be an array)
     * @param mixed        $default The default value to return if no result is found
     *
     * @return mixed The option value
     */
    public function getParameterOption($values, $default = false);

    /**
     * Binds the current Input instance with the given arguments and options.
     *
     * @param InputDefinition $definition A InputDefinition instance
     */
    public function bind(InputDefinition $definition);

    /**
     * Validates if arguments given are correct.
     *
     * Throws an exception when not enough arguments are given.
     *
     * @throws \RuntimeException
     */
    public function validate();

    /**
     * Returns all the given arguments merged with the default values.
     *
     * @return array
     */
    public function getArguments();

    /**
     * Gets argument by name.
     *
     * @param string $name The name of the argument
     *
     * @return mixed
     */
    public function getArgument($name);

    /**
     * Sets an argument value by name.
     *
     * @param string $name  The argument name
     * @param string $value The argument value
     *
     * @throws \InvalidArgumentException When argument given doesn't exist
     */
    public function setArgument($name, $value);

    /**
     * Returns true if an InputArgument object exists by name or position.
     *
     * @param string|integer $name The InputArgument name or position
     *
     * @return Boolean true if the InputArgument object exists, false otherwise
     */
    public function hasArgument($name);

    /**
     * Returns all the given options merged with the default values.
     *
     * @return array
     */
    public function getOptions();

    /**
     * Gets an option by name.
     *
     * @param string $name The name of the option
     *
     * @return mixed
     */
    public function getOption($name);

    /**
     * Sets an option value by name.
     *
     * @param string $name  The option name
     * @param string $value The option value
     *
     * @throws \InvalidArgumentException When option given doesn't exist
     */
    public function setOption($name, $value);

    /**
     * Returns true if an InputOption object exists by name.
     *
     * @param string $name The InputOption name
     *
     * @return Boolean true if the InputOption object exists, false otherwise
     */
    public function hasOption($name);

    /**
     * Is this input means interactive?
     *
     * @return Boolean
     */
    public function isInteractive();

    /**
     * Sets the input interactivity.
     *
     * @param Boolean $interactive If the input should be interactive
     */
    public function setInteractive($interactive);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

if (!defined('JSON_UNESCAPED_UNICODE')) {
    define('JSON_UNESCAPED_SLASHES', 64);
    define('JSON_UNESCAPED_UNICODE', 256);
}

use Symfony\Component\Console\Descriptor\TextDescriptor;
use Symfony\Component\Console\Descriptor\XmlDescriptor;
use Symfony\Component\Console\Output\BufferedOutput;

/**
 * A InputDefinition represents a set of valid command line arguments and options.
 *
 * Usage:
 *
 *     $definition = new InputDefinition(array(
 *       new InputArgument('name', InputArgument::REQUIRED),
 *       new InputOption('foo', 'f', InputOption::VALUE_REQUIRED),
 *     ));
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class InputDefinition
{
    private $arguments;
    private $requiredCount;
    private $hasAnArrayArgument = false;
    private $hasOptional;
    private $options;
    private $shortcuts;

    /**
     * Constructor.
     *
     * @param array $definition An array of InputArgument and InputOption instance
     *
     * @api
     */
    public function __construct(array $definition = array())
    {
        $this->setDefinition($definition);
    }

    /**
     * Sets the definition of the input.
     *
     * @param array $definition The definition array
     *
     * @api
     */
    public function setDefinition(array $definition)
    {
        $arguments = array();
        $options = array();
        foreach ($definition as $item) {
            if ($item instanceof InputOption) {
                $options[] = $item;
            } else {
                $arguments[] = $item;
            }
        }

        $this->setArguments($arguments);
        $this->setOptions($options);
    }

    /**
     * Sets the InputArgument objects.
     *
     * @param InputArgument[] $arguments An array of InputArgument objects
     *
     * @api
     */
    public function setArguments($arguments = array())
    {
        $this->arguments          = array();
        $this->requiredCount      = 0;
        $this->hasOptional        = false;
        $this->hasAnArrayArgument = false;
        $this->addArguments($arguments);
    }

    /**
     * Adds an array of InputArgument objects.
     *
     * @param InputArgument[] $arguments An array of InputArgument objects
     *
     * @api
     */
    public function addArguments($arguments = array())
    {
        if (null !== $arguments) {
            foreach ($arguments as $argument) {
                $this->addArgument($argument);
            }
        }
    }

    /**
     * Adds an InputArgument object.
     *
     * @param InputArgument $argument An InputArgument object
     *
     * @throws \LogicException When incorrect argument is given
     *
     * @api
     */
    public function addArgument(InputArgument $argument)
    {
        if (isset($this->arguments[$argument->getName()])) {
            throw new \LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName()));
        }

        if ($this->hasAnArrayArgument) {
            throw new \LogicException('Cannot add an argument after an array argument.');
        }

        if ($argument->isRequired() && $this->hasOptional) {
            throw new \LogicException('Cannot add a required argument after an optional one.');
        }

        if ($argument->isArray()) {
            $this->hasAnArrayArgument = true;
        }

        if ($argument->isRequired()) {
            ++$this->requiredCount;
        } else {
            $this->hasOptional = true;
        }

        $this->arguments[$argument->getName()] = $argument;
    }

    /**
     * Returns an InputArgument by name or by position.
     *
     * @param string|integer $name The InputArgument name or position
     *
     * @return InputArgument An InputArgument object
     *
     * @throws \InvalidArgumentException When argument given doesn't exist
     *
     * @api
     */
    public function getArgument($name)
    {
        if (!$this->hasArgument($name)) {
            throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
        }

        $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;

        return $arguments[$name];
    }

    /**
     * Returns true if an InputArgument object exists by name or position.
     *
     * @param string|integer $name The InputArgument name or position
     *
     * @return Boolean true if the InputArgument object exists, false otherwise
     *
     * @api
     */
    public function hasArgument($name)
    {
        $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;

        return isset($arguments[$name]);
    }

    /**
     * Gets the array of InputArgument objects.
     *
     * @return InputArgument[] An array of InputArgument objects
     *
     * @api
     */
    public function getArguments()
    {
        return $this->arguments;
    }

    /**
     * Returns the number of InputArguments.
     *
     * @return integer The number of InputArguments
     */
    public function getArgumentCount()
    {
        return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments);
    }

    /**
     * Returns the number of required InputArguments.
     *
     * @return integer The number of required InputArguments
     */
    public function getArgumentRequiredCount()
    {
        return $this->requiredCount;
    }

    /**
     * Gets the default values.
     *
     * @return array An array of default values
     */
    public function getArgumentDefaults()
    {
        $values = array();
        foreach ($this->arguments as $argument) {
            $values[$argument->getName()] = $argument->getDefault();
        }

        return $values;
    }

    /**
     * Sets the InputOption objects.
     *
     * @param InputOption[] $options An array of InputOption objects
     *
     * @api
     */
    public function setOptions($options = array())
    {
        $this->options = array();
        $this->shortcuts = array();
        $this->addOptions($options);
    }

    /**
     * Adds an array of InputOption objects.
     *
     * @param InputOption[] $options An array of InputOption objects
     *
     * @api
     */
    public function addOptions($options = array())
    {
        foreach ($options as $option) {
            $this->addOption($option);
        }
    }

    /**
     * Adds an InputOption object.
     *
     * @param InputOption $option An InputOption object
     *
     * @throws \LogicException When option given already exist
     *
     * @api
     */
    public function addOption(InputOption $option)
    {
        if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) {
            throw new \LogicException(sprintf('An option named "%s" already exists.', $option->getName()));
        }

        if ($option->getShortcut()) {
            foreach (explode('|', $option->getShortcut()) as $shortcut) {
                if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) {
                    throw new \LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut));
                }
            }
        }

        $this->options[$option->getName()] = $option;
        if ($option->getShortcut()) {
            foreach (explode('|', $option->getShortcut()) as $shortcut) {
                $this->shortcuts[$shortcut] = $option->getName();
            }
        }
    }

    /**
     * Returns an InputOption by name.
     *
     * @param string $name The InputOption name
     *
     * @return InputOption A InputOption object
     *
     * @throws \InvalidArgumentException When option given doesn't exist
     *
     * @api
     */
    public function getOption($name)
    {
        if (!$this->hasOption($name)) {
            throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
        }

        return $this->options[$name];
    }

    /**
     * Returns true if an InputOption object exists by name.
     *
     * @param string $name The InputOption name
     *
     * @return Boolean true if the InputOption object exists, false otherwise
     *
     * @api
     */
    public function hasOption($name)
    {
        return isset($this->options[$name]);
    }

    /**
     * Gets the array of InputOption objects.
     *
     * @return InputOption[] An array of InputOption objects
     *
     * @api
     */
    public function getOptions()
    {
        return $this->options;
    }

    /**
     * Returns true if an InputOption object exists by shortcut.
     *
     * @param string $name The InputOption shortcut
     *
     * @return Boolean true if the InputOption object exists, false otherwise
     */
    public function hasShortcut($name)
    {
        return isset($this->shortcuts[$name]);
    }

    /**
     * Gets an InputOption by shortcut.
     *
     * @param string $shortcut the Shortcut name
     *
     * @return InputOption An InputOption object
     */
    public function getOptionForShortcut($shortcut)
    {
        return $this->getOption($this->shortcutToName($shortcut));
    }

    /**
     * Gets an array of default values.
     *
     * @return array An array of all default values
     */
    public function getOptionDefaults()
    {
        $values = array();
        foreach ($this->options as $option) {
            $values[$option->getName()] = $option->getDefault();
        }

        return $values;
    }

    /**
     * Returns the InputOption name given a shortcut.
     *
     * @param string $shortcut The shortcut
     *
     * @return string The InputOption name
     *
     * @throws \InvalidArgumentException When option given does not exist
     */
    private function shortcutToName($shortcut)
    {
        if (!isset($this->shortcuts[$shortcut])) {
            throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
        }

        return $this->shortcuts[$shortcut];
    }

    /**
     * Gets the synopsis.
     *
     * @return string The synopsis
     */
    public function getSynopsis()
    {
        $elements = array();
        foreach ($this->getOptions() as $option) {
            $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : '';
            $elements[] = sprintf('['.($option->isValueRequired() ? '%s--%s="..."' : ($option->isValueOptional() ? '%s--%s[="..."]' : '%s--%s')).']', $shortcut, $option->getName());
        }

        foreach ($this->getArguments() as $argument) {
            $elements[] = sprintf($argument->isRequired() ? '%s' : '[%s]', $argument->getName().($argument->isArray() ? '1' : ''));

            if ($argument->isArray()) {
                $elements[] = sprintf('... [%sN]', $argument->getName());
            }
        }

        return implode(' ', $elements);
    }

    /**
     * Returns a textual representation of the InputDefinition.
     *
     * @return string A string representing the InputDefinition
     *
     * @deprecated Deprecated since version 2.3, to be removed in 3.0.
     */
    public function asText()
    {
        $descriptor = new TextDescriptor();
        $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
        $descriptor->describe($output, $this, array('raw_output' => true));

        return $output->fetch();
    }

    /**
     * Returns an XML representation of the InputDefinition.
     *
     * @param Boolean $asDom Whether to return a DOM or an XML string
     *
     * @return string|\DOMDocument An XML string representing the InputDefinition
     *
     * @deprecated Deprecated since version 2.3, to be removed in 3.0.
     */
    public function asXml($asDom = false)
    {
        $descriptor = new XmlDescriptor();

        if ($asDom) {
            return $descriptor->getInputDefinitionDocument($this);
        }

        $output = new BufferedOutput();
        $descriptor->describe($output, $this);

        return $output->fetch();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

/**
 * StringInput represents an input provided as a string.
 *
 * Usage:
 *
 *     $input = new StringInput('foo --bar="foobar"');
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class StringInput extends ArgvInput
{
    const REGEX_STRING = '([^\s]+?)(?:\s|(?<!\\\\)"|(?<!\\\\)\'|$)';
    const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';

    /**
     * Constructor.
     *
     * @param string          $input      An array of parameters from the CLI (in the argv format)
     * @param InputDefinition $definition A InputDefinition instance
     *
     * @deprecated The second argument is deprecated as it does not work (will be removed in 3.0), use 'bind' method instead
     *
     * @api
     */
    public function __construct($input, InputDefinition $definition = null)
    {
        parent::__construct(array(), null);

        $this->setTokens($this->tokenize($input));

        if (null !== $definition) {
            $this->bind($definition);
        }
    }

    /**
     * Tokenizes a string.
     *
     * @param string $input The input to tokenize
     *
     * @return array An array of tokens
     *
     * @throws \InvalidArgumentException When unable to parse input (should never happen)
     */
    private function tokenize($input)
    {
        $tokens = array();
        $length = strlen($input);
        $cursor = 0;
        while ($cursor < $length) {
            if (preg_match('/\s+/A', $input, $match, null, $cursor)) {
            } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) {
                $tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, strlen($match[3]) - 2)));
            } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) {
                $tokens[] = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2));
            } elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) {
                $tokens[] = stripcslashes($match[1]);
            } else {
                // should never happen
                // @codeCoverageIgnoreStart
                throw new \InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10)));
                // @codeCoverageIgnoreEnd
            }

            $cursor += strlen($match[0]);
        }

        return $tokens;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

/**
 * ArgvInput represents an input coming from the CLI arguments.
 *
 * Usage:
 *
 *     $input = new ArgvInput();
 *
 * By default, the `$_SERVER['argv']` array is used for the input values.
 *
 * This can be overridden by explicitly passing the input values in the constructor:
 *
 *     $input = new ArgvInput($_SERVER['argv']);
 *
 * If you pass it yourself, don't forget that the first element of the array
 * is the name of the running application.
 *
 * When passing an argument to the constructor, be sure that it respects
 * the same rules as the argv one. It's almost always better to use the
 * `StringInput` when you want to provide your own input.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @see    http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html
 * @see    http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02
 *
 * @api
 */
class ArgvInput extends Input
{
    private $tokens;
    private $parsed;

    /**
     * Constructor.
     *
     * @param array           $argv       An array of parameters from the CLI (in the argv format)
     * @param InputDefinition $definition A InputDefinition instance
     *
     * @api
     */
    public function __construct(array $argv = null, InputDefinition $definition = null)
    {
        if (null === $argv) {
            $argv = $_SERVER['argv'];
        }

        // strip the application name
        array_shift($argv);

        $this->tokens = $argv;

        parent::__construct($definition);
    }

    protected function setTokens(array $tokens)
    {
        $this->tokens = $tokens;
    }

    /**
     * Processes command line arguments.
     */
    protected function parse()
    {
        $parseOptions = true;
        $this->parsed = $this->tokens;
        while (null !== $token = array_shift($this->parsed)) {
            if ($parseOptions && '' == $token) {
                $this->parseArgument($token);
            } elseif ($parseOptions && '--' == $token) {
                $parseOptions = false;
            } elseif ($parseOptions && 0 === strpos($token, '--')) {
                $this->parseLongOption($token);
            } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) {
                $this->parseShortOption($token);
            } else {
                $this->parseArgument($token);
            }
        }
    }

    /**
     * Parses a short option.
     *
     * @param string $token The current token.
     */
    private function parseShortOption($token)
    {
        $name = substr($token, 1);

        if (strlen($name) > 1) {
            if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) {
                // an option with a value (with no space)
                $this->addShortOption($name[0], substr($name, 1));
            } else {
                $this->parseShortOptionSet($name);
            }
        } else {
            $this->addShortOption($name, null);
        }
    }

    /**
     * Parses a short option set.
     *
     * @param string $name The current token
     *
     * @throws \RuntimeException When option given doesn't exist
     */
    private function parseShortOptionSet($name)
    {
        $len = strlen($name);
        for ($i = 0; $i < $len; $i++) {
            if (!$this->definition->hasShortcut($name[$i])) {
                throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i]));
            }

            $option = $this->definition->getOptionForShortcut($name[$i]);
            if ($option->acceptValue()) {
                $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1));

                break;
            } else {
                $this->addLongOption($option->getName(), null);
            }
        }
    }

    /**
     * Parses a long option.
     *
     * @param string $token The current token
     */
    private function parseLongOption($token)
    {
        $name = substr($token, 2);

        if (false !== $pos = strpos($name, '=')) {
            $this->addLongOption(substr($name, 0, $pos), substr($name, $pos + 1));
        } else {
            $this->addLongOption($name, null);
        }
    }

    /**
     * Parses an argument.
     *
     * @param string $token The current token
     *
     * @throws \RuntimeException When too many arguments are given
     */
    private function parseArgument($token)
    {
        $c = count($this->arguments);

        // if input is expecting another argument, add it
        if ($this->definition->hasArgument($c)) {
            $arg = $this->definition->getArgument($c);
            $this->arguments[$arg->getName()] = $arg->isArray()? array($token) : $token;

        // if last argument isArray(), append token to last argument
        } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) {
            $arg = $this->definition->getArgument($c - 1);
            $this->arguments[$arg->getName()][] = $token;

        // unexpected argument
        } else {
            throw new \RuntimeException('Too many arguments.');
        }
    }

    /**
     * Adds a short option value.
     *
     * @param string $shortcut The short option key
     * @param mixed  $value    The value for the option
     *
     * @throws \RuntimeException When option given doesn't exist
     */
    private function addShortOption($shortcut, $value)
    {
        if (!$this->definition->hasShortcut($shortcut)) {
            throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut));
        }

        $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
    }

    /**
     * Adds a long option value.
     *
     * @param string $name  The long option key
     * @param mixed  $value The value for the option
     *
     * @throws \RuntimeException When option given doesn't exist
     */
    private function addLongOption($name, $value)
    {
        if (!$this->definition->hasOption($name)) {
            throw new \RuntimeException(sprintf('The "--%s" option does not exist.', $name));
        }

        $option = $this->definition->getOption($name);

        // Convert false values (from a previous call to substr()) to null
        if (false === $value) {
            $value = null;
        }

        if (null !== $value && !$option->acceptValue()) {
            throw new \RuntimeException(sprintf('The "--%s" option does not accept a value.', $name, $value));
        }

        if (null === $value && $option->acceptValue() && count($this->parsed)) {
            // if option accepts an optional or mandatory argument
            // let's see if there is one provided
            $next = array_shift($this->parsed);
            if (isset($next[0]) && '-' !== $next[0]) {
                $value = $next;
            } elseif (empty($next)) {
                $value = '';
            } else {
                array_unshift($this->parsed, $next);
            }
        }

        if (null === $value) {
            if ($option->isValueRequired()) {
                throw new \RuntimeException(sprintf('The "--%s" option requires a value.', $name));
            }

            if (!$option->isArray()) {
                $value = $option->isValueOptional() ? $option->getDefault() : true;
            }
        }

        if ($option->isArray()) {
            $this->options[$name][] = $value;
        } else {
            $this->options[$name] = $value;
        }
    }

    /**
     * Returns the first argument from the raw parameters (not parsed).
     *
     * @return string The value of the first argument or null otherwise
     */
    public function getFirstArgument()
    {
        foreach ($this->tokens as $token) {
            if ($token && '-' === $token[0]) {
                continue;
            }

            return $token;
        }
    }

    /**
     * Returns true if the raw parameters (not parsed) contain a value.
     *
     * This method is to be used to introspect the input parameters
     * before they have been validated. It must be used carefully.
     *
     * @param string|array $values The value(s) to look for in the raw parameters (can be an array)
     *
     * @return Boolean true if the value is contained in the raw parameters
     */
    public function hasParameterOption($values)
    {
        $values = (array) $values;

        foreach ($this->tokens as $token) {
            foreach ($values as $value) {
                if ($token === $value || 0 === strpos($token, $value.'=')) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Returns the value of a raw option (not parsed).
     *
     * This method is to be used to introspect the input parameters
     * before they have been validated. It must be used carefully.
     *
     * @param string|array $values  The value(s) to look for in the raw parameters (can be an array)
     * @param mixed        $default The default value to return if no result is found
     *
     * @return mixed The option value
     */
    public function getParameterOption($values, $default = false)
    {
        $values = (array) $values;

        $tokens = $this->tokens;
        while ($token = array_shift($tokens)) {
            foreach ($values as $value) {
                if ($token === $value || 0 === strpos($token, $value.'=')) {
                    if (false !== $pos = strpos($token, '=')) {
                        return substr($token, $pos + 1);
                    }

                    return array_shift($tokens);
                }
            }
        }

        return $default;
    }

    /**
     * Returns a stringified representation of the args passed to the command
     *
     * @return string
     */
    public function __toString()
    {
        $self = $this;
        $tokens = array_map(function ($token) use ($self) {
            if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) {
                return $match[1] . $self->escapeToken($match[2]);
            }

            if ($token && $token[0] !== '-') {
                return $self->escapeToken($token);
            }

            return $token;
        }, $this->tokens);

        return implode(' ', $tokens);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

/**
 * Input is the base class for all concrete Input classes.
 *
 * Three concrete classes are provided by default:
 *
 *  * `ArgvInput`: The input comes from the CLI arguments (argv)
 *  * `StringInput`: The input is provided as a string
 *  * `ArrayInput`: The input is provided as an array
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Input implements InputInterface
{
    /**
     * @var InputDefinition
     */
    protected $definition;
    protected $options = array();
    protected $arguments = array();
    protected $interactive = true;

    /**
     * Constructor.
     *
     * @param InputDefinition $definition A InputDefinition instance
     */
    public function __construct(InputDefinition $definition = null)
    {
        if (null === $definition) {
            $this->definition = new InputDefinition();
        } else {
            $this->bind($definition);
            $this->validate();
        }
    }

    /**
     * Binds the current Input instance with the given arguments and options.
     *
     * @param InputDefinition $definition A InputDefinition instance
     */
    public function bind(InputDefinition $definition)
    {
        $this->arguments = array();
        $this->options = array();
        $this->definition = $definition;

        $this->parse();
    }

    /**
     * Processes command line arguments.
     */
    abstract protected function parse();

    /**
     * Validates the input.
     *
     * @throws \RuntimeException When not enough arguments are given
     */
    public function validate()
    {
        if (count($this->arguments) < $this->definition->getArgumentRequiredCount()) {
            throw new \RuntimeException('Not enough arguments.');
        }
    }

    /**
     * Checks if the input is interactive.
     *
     * @return Boolean Returns true if the input is interactive
     */
    public function isInteractive()
    {
        return $this->interactive;
    }

    /**
     * Sets the input interactivity.
     *
     * @param Boolean $interactive If the input should be interactive
     */
    public function setInteractive($interactive)
    {
        $this->interactive = (Boolean) $interactive;
    }

    /**
     * Returns the argument values.
     *
     * @return array An array of argument values
     */
    public function getArguments()
    {
        return array_merge($this->definition->getArgumentDefaults(), $this->arguments);
    }

    /**
     * Returns the argument value for a given argument name.
     *
     * @param string $name The argument name
     *
     * @return mixed The argument value
     *
     * @throws \InvalidArgumentException When argument given doesn't exist
     */
    public function getArgument($name)
    {
        if (!$this->definition->hasArgument($name)) {
            throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
        }

        return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault();
    }

    /**
     * Sets an argument value by name.
     *
     * @param string $name  The argument name
     * @param string $value The argument value
     *
     * @throws \InvalidArgumentException When argument given doesn't exist
     */
    public function setArgument($name, $value)
    {
        if (!$this->definition->hasArgument($name)) {
            throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
        }

        $this->arguments[$name] = $value;
    }

    /**
     * Returns true if an InputArgument object exists by name or position.
     *
     * @param string|integer $name The InputArgument name or position
     *
     * @return Boolean true if the InputArgument object exists, false otherwise
     */
    public function hasArgument($name)
    {
        return $this->definition->hasArgument($name);
    }

    /**
     * Returns the options values.
     *
     * @return array An array of option values
     */
    public function getOptions()
    {
        return array_merge($this->definition->getOptionDefaults(), $this->options);
    }

    /**
     * Returns the option value for a given option name.
     *
     * @param string $name The option name
     *
     * @return mixed The option value
     *
     * @throws \InvalidArgumentException When option given doesn't exist
     */
    public function getOption($name)
    {
        if (!$this->definition->hasOption($name)) {
            throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
        }

        return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
    }

    /**
     * Sets an option value by name.
     *
     * @param string $name  The option name
     * @param string $value The option value
     *
     * @throws \InvalidArgumentException When option given doesn't exist
     */
    public function setOption($name, $value)
    {
        if (!$this->definition->hasOption($name)) {
            throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
        }

        $this->options[$name] = $value;
    }

    /**
     * Returns true if an InputOption object exists by name.
     *
     * @param string $name The InputOption name
     *
     * @return Boolean true if the InputOption object exists, false otherwise
     */
    public function hasOption($name)
    {
        return $this->definition->hasOption($name);
    }

    /**
     * Escapes a token through escapeshellarg if it contains unsafe chars
     *
     * @param string $token
     *
     * @return string
     */
    public function escapeToken($token)
    {
        return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

/**
 * ArrayInput represents an input provided as an array.
 *
 * Usage:
 *
 *     $input = new ArrayInput(array('name' => 'foo', '--bar' => 'foobar'));
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class ArrayInput extends Input
{
    private $parameters;

    /**
     * Constructor.
     *
     * @param array           $parameters An array of parameters
     * @param InputDefinition $definition A InputDefinition instance
     *
     * @api
     */
    public function __construct(array $parameters, InputDefinition $definition = null)
    {
        $this->parameters = $parameters;

        parent::__construct($definition);
    }

    /**
     * Returns the first argument from the raw parameters (not parsed).
     *
     * @return string The value of the first argument or null otherwise
     */
    public function getFirstArgument()
    {
        foreach ($this->parameters as $key => $value) {
            if ($key && '-' === $key[0]) {
                continue;
            }

            return $value;
        }
    }

    /**
     * Returns true if the raw parameters (not parsed) contain a value.
     *
     * This method is to be used to introspect the input parameters
     * before they have been validated. It must be used carefully.
     *
     * @param string|array $values The values to look for in the raw parameters (can be an array)
     *
     * @return Boolean true if the value is contained in the raw parameters
     */
    public function hasParameterOption($values)
    {
        $values = (array) $values;

        foreach ($this->parameters as $k => $v) {
            if (!is_int($k)) {
                $v = $k;
            }

            if (in_array($v, $values)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Returns the value of a raw option (not parsed).
     *
     * This method is to be used to introspect the input parameters
     * before they have been validated. It must be used carefully.
     *
     * @param string|array $values  The value(s) to look for in the raw parameters (can be an array)
     * @param mixed        $default The default value to return if no result is found
     *
     * @return mixed The option value
     */
    public function getParameterOption($values, $default = false)
    {
        $values = (array) $values;

        foreach ($this->parameters as $k => $v) {
            if (is_int($k) && in_array($v, $values)) {
                return true;
            } elseif (in_array($k, $values)) {
                return $v;
            }
        }

        return $default;
    }

    /**
     * Returns a stringified representation of the args passed to the command
     *
     * @return string
     */
    public function __toString()
    {
        $params = array();
        foreach ($this->parameters as $param => $val) {
            if ($param && '-' === $param[0]) {
                $params[] = $param . ('' != $val ? '='.$this->escapeToken($val) : '');
            } else {
                $params[] = $this->escapeToken($val);
            }
        }

        return implode(' ', $params);
    }

    /**
     * Processes command line arguments.
     */
    protected function parse()
    {
        foreach ($this->parameters as $key => $value) {
            if (0 === strpos($key, '--')) {
                $this->addLongOption(substr($key, 2), $value);
            } elseif ('-' === $key[0]) {
                $this->addShortOption(substr($key, 1), $value);
            } else {
                $this->addArgument($key, $value);
            }
        }
    }

    /**
     * Adds a short option value.
     *
     * @param string $shortcut The short option key
     * @param mixed  $value    The value for the option
     *
     * @throws \InvalidArgumentException When option given doesn't exist
     */
    private function addShortOption($shortcut, $value)
    {
        if (!$this->definition->hasShortcut($shortcut)) {
            throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
        }

        $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
    }

    /**
     * Adds a long option value.
     *
     * @param string $name  The long option key
     * @param mixed  $value The value for the option
     *
     * @throws \InvalidArgumentException When option given doesn't exist
     * @throws \InvalidArgumentException When a required value is missing
     */
    private function addLongOption($name, $value)
    {
        if (!$this->definition->hasOption($name)) {
            throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
        }

        $option = $this->definition->getOption($name);

        if (null === $value) {
            if ($option->isValueRequired()) {
                throw new \InvalidArgumentException(sprintf('The "--%s" option requires a value.', $name));
            }

            $value = $option->isValueOptional() ? $option->getDefault() : true;
        }

        $this->options[$name] = $value;
    }

    /**
     * Adds an argument value.
     *
     * @param string $name  The argument name
     * @param mixed  $value The value for the argument
     *
     * @throws \InvalidArgumentException When argument given doesn't exist
     */
    private function addArgument($name, $value)
    {
        if (!$this->definition->hasArgument($name)) {
            throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
        }

        $this->arguments[$name] = $value;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

/**
 * Represents a command line argument.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
class InputArgument
{
    const REQUIRED = 1;
    const OPTIONAL = 2;
    const IS_ARRAY = 4;

    private $name;
    private $mode;
    private $default;
    private $description;

    /**
     * Constructor.
     *
     * @param string  $name        The argument name
     * @param integer $mode        The argument mode: self::REQUIRED or self::OPTIONAL
     * @param string  $description A description text
     * @param mixed   $default     The default value (for self::OPTIONAL mode only)
     *
     * @throws \InvalidArgumentException When argument mode is not valid
     *
     * @api
     */
    public function __construct($name, $mode = null, $description = '', $default = null)
    {
        if (null === $mode) {
            $mode = self::OPTIONAL;
        } elseif (!is_int($mode) || $mode > 7 || $mode < 1) {
            throw new \InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode));
        }

        $this->name        = $name;
        $this->mode        = $mode;
        $this->description = $description;

        $this->setDefault($default);
    }

    /**
     * Returns the argument name.
     *
     * @return string The argument name
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Returns true if the argument is required.
     *
     * @return Boolean true if parameter mode is self::REQUIRED, false otherwise
     */
    public function isRequired()
    {
        return self::REQUIRED === (self::REQUIRED & $this->mode);
    }

    /**
     * Returns true if the argument can take multiple values.
     *
     * @return Boolean true if mode is self::IS_ARRAY, false otherwise
     */
    public function isArray()
    {
        return self::IS_ARRAY === (self::IS_ARRAY & $this->mode);
    }

    /**
     * Sets the default value.
     *
     * @param mixed $default The default value
     *
     * @throws \LogicException When incorrect default value is given
     */
    public function setDefault($default = null)
    {
        if (self::REQUIRED === $this->mode && null !== $default) {
            throw new \LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.');
        }

        if ($this->isArray()) {
            if (null === $default) {
                $default = array();
            } elseif (!is_array($default)) {
                throw new \LogicException('A default value for an array argument must be an array.');
            }
        }

        $this->default = $default;
    }

    /**
     * Returns the default value.
     *
     * @return mixed The default value
     */
    public function getDefault()
    {
        return $this->default;
    }

    /**
     * Returns the description text.
     *
     * @return string The description text
     */
    public function getDescription()
    {
        return $this->description;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Input;

/**
 * InputAwareInterface should be implemented by classes that depends on the
 * Console Input.
 *
 * @author Wouter J <waldio.webdesign@gmail.com>
 */
interface InputAwareInterface
{
    /**
     * Sets the Console Input.
     *
     * @param InputInterface
     */
    public function setInput(InputInterface $input);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tester;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\StreamOutput;

/**
 * Eases the testing of console applications.
 *
 * When testing an application, don't forget to disable the auto exit flag:
 *
 *     $application = new Application();
 *     $application->setAutoExit(false);
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ApplicationTester
{
    private $application;
    private $input;
    private $output;
    private $statusCode;

    /**
     * Constructor.
     *
     * @param Application $application An Application instance to test.
     */
    public function __construct(Application $application)
    {
        $this->application = $application;
    }

    /**
     * Executes the application.
     *
     * Available options:
     *
     *  * interactive: Sets the input interactive flag
     *  * decorated:   Sets the output decorated flag
     *  * verbosity:   Sets the output verbosity flag
     *
     * @param array $input   An array of arguments and options
     * @param array $options An array of options
     *
     * @return integer The command exit code
     */
    public function run(array $input, $options = array())
    {
        $this->input = new ArrayInput($input);
        if (isset($options['interactive'])) {
            $this->input->setInteractive($options['interactive']);
        }

        $this->output = new StreamOutput(fopen('php://memory', 'w', false));
        if (isset($options['decorated'])) {
            $this->output->setDecorated($options['decorated']);
        }
        if (isset($options['verbosity'])) {
            $this->output->setVerbosity($options['verbosity']);
        }

        return $this->statusCode = $this->application->run($this->input, $this->output);
    }

    /**
     * Gets the display returned by the last execution of the application.
     *
     * @param Boolean $normalize Whether to normalize end of lines to \n or not
     *
     * @return string The display
     */
    public function getDisplay($normalize = false)
    {
        rewind($this->output->getStream());

        $display = stream_get_contents($this->output->getStream());

        if ($normalize) {
            $display = str_replace(PHP_EOL, "\n", $display);
        }

        return $display;
    }

    /**
     * Gets the input instance used by the last execution of the application.
     *
     * @return InputInterface The current input instance
     */
    public function getInput()
    {
        return $this->input;
    }

    /**
     * Gets the output instance used by the last execution of the application.
     *
     * @return OutputInterface The current output instance
     */
    public function getOutput()
    {
        return $this->output;
    }

    /**
     * Gets the status code returned by the last execution of the application.
     *
     * @return integer The status code
     */
    public function getStatusCode()
    {
        return $this->statusCode;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tester;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\StreamOutput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * Eases the testing of console commands.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class CommandTester
{
    private $command;
    private $input;
    private $output;
    private $statusCode;

    /**
     * Constructor.
     *
     * @param Command $command A Command instance to test.
     */
    public function __construct(Command $command)
    {
        $this->command = $command;
    }

    /**
     * Executes the command.
     *
     * Available options:
     *
     *  * interactive: Sets the input interactive flag
     *  * decorated:   Sets the output decorated flag
     *  * verbosity:   Sets the output verbosity flag
     *
     * @param array $input   An array of arguments and options
     * @param array $options An array of options
     *
     * @return integer The command exit code
     */
    public function execute(array $input, array $options = array())
    {
        // set the command name automatically if the application requires
        // this argument and no command name was passed
        if (!isset($input['command'])
            && (null !== $application = $this->command->getApplication())
            && $application->getDefinition()->hasArgument('command')
        ) {
            $input['command'] = $this->command->getName();
        }

        $this->input = new ArrayInput($input);
        if (isset($options['interactive'])) {
            $this->input->setInteractive($options['interactive']);
        }

        $this->output = new StreamOutput(fopen('php://memory', 'w', false));
        if (isset($options['decorated'])) {
            $this->output->setDecorated($options['decorated']);
        }
        if (isset($options['verbosity'])) {
            $this->output->setVerbosity($options['verbosity']);
        }

        return $this->statusCode = $this->command->run($this->input, $this->output);
    }

    /**
     * Gets the display returned by the last execution of the command.
     *
     * @param Boolean $normalize Whether to normalize end of lines to \n or not
     *
     * @return string The display
     */
    public function getDisplay($normalize = false)
    {
        rewind($this->output->getStream());

        $display = stream_get_contents($this->output->getStream());

        if ($normalize) {
            $display = str_replace(PHP_EOL, "\n", $display);
        }

        return $display;
    }

    /**
     * Gets the input instance used by the last execution of the command.
     *
     * @return InputInterface The current input instance
     */
    public function getInput()
    {
        return $this->input;
    }

    /**
     * Gets the output instance used by the last execution of the command.
     *
     * @return OutputInterface The current output instance
     */
    public function getOutput()
    {
        return $this->output;
    }

    /**
     * Gets the status code returned by the last execution of the application.
     *
     * @return integer The status code
     */
    public function getStatusCode()
    {
        return $this->statusCode;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

/**
 * HelperInterface is the interface all helpers must implement.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
interface HelperInterface
{
    /**
     * Sets the helper set associated with this helper.
     *
     * @param HelperSet $helperSet A HelperSet instance
     *
     * @api
     */
    public function setHelperSet(HelperSet $helperSet = null);

    /**
     * Gets the helper set associated with this helper.
     *
     * @return HelperSet A HelperSet instance
     *
     * @api
     */
    public function getHelperSet();

    /**
     * Returns the canonical name of this helper.
     *
     * @return string The canonical name
     *
     * @api
     */
    public function getName();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Formatter\OutputFormatter;

/**
 * The Formatter class provides helpers to format messages.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FormatterHelper extends Helper
{
    /**
     * Formats a message within a section.
     *
     * @param string $section The section name
     * @param string $message The message
     * @param string $style   The style to apply to the section
     *
     * @return string The format section
     */
    public function formatSection($section, $message, $style = 'info')
    {
        return sprintf('<%s>[%s]</%s> %s', $style, $section, $style, $message);
    }

    /**
     * Formats a message as a block of text.
     *
     * @param string|array $messages The message to write in the block
     * @param string       $style    The style to apply to the whole block
     * @param Boolean      $large    Whether to return a large block
     *
     * @return string The formatter message
     */
    public function formatBlock($messages, $style, $large = false)
    {
        $messages = (array) $messages;

        $len = 0;
        $lines = array();
        foreach ($messages as $message) {
            $message = OutputFormatter::escape($message);
            $lines[] = sprintf($large ? '  %s  ' : ' %s ', $message);
            $len = max($this->strlen($message) + ($large ? 4 : 2), $len);
        }

        $messages = $large ? array(str_repeat(' ', $len)) : array();
        foreach ($lines as $line) {
            $messages[] = $line.str_repeat(' ', $len - $this->strlen($line));
        }
        if ($large) {
            $messages[] = str_repeat(' ', $len);
        }

        foreach ($messages as &$message) {
            $message = sprintf('<%s>%s</%s>', $style, $message, $style);
        }

        return implode("\n", $messages);
    }

    /**
     * {@inheritDoc}
     */
    public function getName()
    {
        return 'formatter';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Output\OutputInterface;

/**
 * The Progress class provides helpers to display progress output.
 *
 * @author Chris Jones <leeked@gmail.com>
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ProgressHelper extends Helper
{
    const FORMAT_QUIET         = ' %percent%%';
    const FORMAT_NORMAL        = ' %current%/%max% [%bar%] %percent%%';
    const FORMAT_VERBOSE       = ' %current%/%max% [%bar%] %percent%% Elapsed: %elapsed%';
    const FORMAT_QUIET_NOMAX   = ' %current%';
    const FORMAT_NORMAL_NOMAX  = ' %current% [%bar%]';
    const FORMAT_VERBOSE_NOMAX = ' %current% [%bar%] Elapsed: %elapsed%';

    // options
    private $barWidth     = 28;
    private $barChar      = '=';
    private $emptyBarChar = '-';
    private $progressChar = '>';
    private $format       = null;
    private $redrawFreq   = 1;

    private $lastMessagesLength;
    private $barCharOriginal;

    /**
     * @var OutputInterface
     */
    private $output;

    /**
     * Current step
     *
     * @var integer
     */
    private $current;

    /**
     * Maximum number of steps
     *
     * @var integer
     */
    private $max;

    /**
     * Start time of the progress bar
     *
     * @var integer
     */
    private $startTime;

    /**
     * List of formatting variables
     *
     * @var array
     */
    private $defaultFormatVars = array(
        'current',
        'max',
        'bar',
        'percent',
        'elapsed',
    );

    /**
     * Available formatting variables
     *
     * @var array
     */
    private $formatVars;

    /**
     * Stored format part widths (used for padding)
     *
     * @var array
     */
    private $widths = array(
        'current' => 4,
        'max'     => 4,
        'percent' => 3,
        'elapsed' => 6,
    );

    /**
     * Various time formats
     *
     * @var array
     */
    private $timeFormats = array(
        array(0, '???'),
        array(2, '1 sec'),
        array(59, 'secs', 1),
        array(60, '1 min'),
        array(3600, 'mins', 60),
        array(5400, '1 hr'),
        array(86400, 'hrs', 3600),
        array(129600, '1 day'),
        array(604800, 'days', 86400),
    );

    /**
     * Sets the progress bar width.
     *
     * @param int $size The progress bar size
     */
    public function setBarWidth($size)
    {
        $this->barWidth = (int) $size;
    }

    /**
     * Sets the bar character.
     *
     * @param string $char A character
     */
    public function setBarCharacter($char)
    {
        $this->barChar = $char;
    }

    /**
     * Sets the empty bar character.
     *
     * @param string $char A character
     */
    public function setEmptyBarCharacter($char)
    {
        $this->emptyBarChar = $char;
    }

    /**
     * Sets the progress bar character.
     *
     * @param string $char A character
     */
    public function setProgressCharacter($char)
    {
        $this->progressChar = $char;
    }

    /**
     * Sets the progress bar format.
     *
     * @param string $format The format
     */
    public function setFormat($format)
    {
        $this->format = $format;
    }

    /**
     * Sets the redraw frequency.
     *
     * @param int $freq The frequency in steps
     */
    public function setRedrawFrequency($freq)
    {
        $this->redrawFreq = (int) $freq;
    }

    /**
     * Starts the progress output.
     *
     * @param OutputInterface $output An Output instance
     * @param integer|null    $max    Maximum steps
     */
    public function start(OutputInterface $output, $max = null)
    {
        $this->startTime = time();
        $this->current   = 0;
        $this->max       = (int) $max;
        $this->output    = $output;
        $this->lastMessagesLength = 0;
        $this->barCharOriginal = '';

        if (null === $this->format) {
            switch ($output->getVerbosity()) {
                case OutputInterface::VERBOSITY_QUIET:
                    $this->format = self::FORMAT_QUIET_NOMAX;
                    if ($this->max > 0) {
                        $this->format = self::FORMAT_QUIET;
                    }
                    break;
                case OutputInterface::VERBOSITY_VERBOSE:
                case OutputInterface::VERBOSITY_VERY_VERBOSE:
                case OutputInterface::VERBOSITY_DEBUG:
                    $this->format = self::FORMAT_VERBOSE_NOMAX;
                    if ($this->max > 0) {
                        $this->format = self::FORMAT_VERBOSE;
                    }
                    break;
                default:
                    $this->format = self::FORMAT_NORMAL_NOMAX;
                    if ($this->max > 0) {
                        $this->format = self::FORMAT_NORMAL;
                    }
                    break;
            }
        }

        $this->initialize();
    }

    /**
     * Advances the progress output X steps.
     *
     * @param integer $step   Number of steps to advance
     * @param Boolean $redraw Whether to redraw or not
     *
     * @throws \LogicException
     */
    public function advance($step = 1, $redraw = false)
    {
        $this->setCurrent($this->current + $step, $redraw);
    }

    /**
     * Sets the current progress.
     *
     * @param integer $current The current progress
     * @param Boolean $redraw  Whether to redraw or not
     *
     * @throws \LogicException
     */
    public function setCurrent($current, $redraw = false)
    {
        if (null === $this->startTime) {
            throw new \LogicException('You must start the progress bar before calling setCurrent().');
        }

        $current = (int) $current;

        if ($current < $this->current) {
            throw new \LogicException('You can\'t regress the progress bar');
        }

        if (0 === $this->current) {
            $redraw = true;
        }

        $prevPeriod = intval($this->current / $this->redrawFreq);

        $this->current = $current;

        $currPeriod = intval($this->current / $this->redrawFreq);
        if ($redraw || $prevPeriod !== $currPeriod || $this->max === $this->current) {
            $this->display();
        }
    }

    /**
     * Outputs the current progress string.
     *
     * @param Boolean $finish Forces the end result
     *
     * @throws \LogicException
     */
    public function display($finish = false)
    {
        if (null === $this->startTime) {
            throw new \LogicException('You must start the progress bar before calling display().');
        }

        $message = $this->format;
        foreach ($this->generate($finish) as $name => $value) {
            $message = str_replace("%{$name}%", $value, $message);
        }
        $this->overwrite($this->output, $message);
    }

    /**
     * Removes the progress bar from the current line.
     *
     * This is useful if you wish to write some output
     * while a progress bar is running.
     * Call display() to show the progress bar again.
     */
    public function clear()
    {
        $this->overwrite($this->output, '');
    }

    /**
     * Finishes the progress output.
     */
    public function finish()
    {
        if (null === $this->startTime) {
            throw new \LogicException('You must start the progress bar before calling finish().');
        }

        if (null !== $this->startTime) {
            if (!$this->max) {
                $this->barChar = $this->barCharOriginal;
                $this->display(true);
            }
            $this->startTime = null;
            $this->output->writeln('');
            $this->output = null;
        }
    }

    /**
     * Initializes the progress helper.
     */
    private function initialize()
    {
        $this->formatVars = array();
        foreach ($this->defaultFormatVars as $var) {
            if (false !== strpos($this->format, "%{$var}%")) {
                $this->formatVars[$var] = true;
            }
        }

        if ($this->max > 0) {
            $this->widths['max']     = $this->strlen($this->max);
            $this->widths['current'] = $this->widths['max'];
        } else {
            $this->barCharOriginal = $this->barChar;
            $this->barChar         = $this->emptyBarChar;
        }
    }

    /**
     * Generates the array map of format variables to values.
     *
     * @param Boolean $finish Forces the end result
     *
     * @return array Array of format vars and values
     */
    private function generate($finish = false)
    {
        $vars    = array();
        $percent = 0;
        if ($this->max > 0) {
            $percent = (double) $this->current / $this->max;
        }

        if (isset($this->formatVars['bar'])) {
            $completeBars = 0;

            if ($this->max > 0) {
                $completeBars = floor($percent * $this->barWidth);
            } else {
                if (!$finish) {
                    $completeBars = floor($this->current % $this->barWidth);
                } else {
                    $completeBars = $this->barWidth;
                }
            }

            $emptyBars = $this->barWidth - $completeBars - $this->strlen($this->progressChar);
            $bar = str_repeat($this->barChar, $completeBars);
            if ($completeBars < $this->barWidth) {
                $bar .= $this->progressChar;
                $bar .= str_repeat($this->emptyBarChar, $emptyBars);
            }

            $vars['bar'] = $bar;
        }

        if (isset($this->formatVars['elapsed'])) {
            $elapsed = time() - $this->startTime;
            $vars['elapsed'] = str_pad($this->humaneTime($elapsed), $this->widths['elapsed'], ' ', STR_PAD_LEFT);
        }

        if (isset($this->formatVars['current'])) {
            $vars['current'] = str_pad($this->current, $this->widths['current'], ' ', STR_PAD_LEFT);
        }

        if (isset($this->formatVars['max'])) {
            $vars['max'] = $this->max;
        }

        if (isset($this->formatVars['percent'])) {
            $vars['percent'] = str_pad(floor($percent * 100), $this->widths['percent'], ' ', STR_PAD_LEFT);
        }

        return $vars;
    }

    /**
     * Converts seconds into human-readable format.
     *
     * @param integer $secs Number of seconds
     *
     * @return string Time in readable format
     */
    private function humaneTime($secs)
    {
        $text = '';
        foreach ($this->timeFormats as $format) {
            if ($secs < $format[0]) {
                if (count($format) == 2) {
                    $text = $format[1];
                    break;
                } else {
                    $text = ceil($secs / $format[2]).' '.$format[1];
                    break;
                }
            }
        }

        return $text;
    }

    /**
     * Overwrites a previous message to the output.
     *
     * @param OutputInterface $output   An Output instance
     * @param string          $message  The message
     */
    private function overwrite(OutputInterface $output, $message)
    {
        $length = $this->strlen($message);

        // append whitespace to match the last line's length
        if (null !== $this->lastMessagesLength && $this->lastMessagesLength > $length) {
            $message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
        }

        // carriage return
        $output->write("\x0D");
        $output->write($message);

        $this->lastMessagesLength = $this->strlen($message);
    }

    /**
     * {@inheritDoc}
     */
    public function getName()
    {
        return 'progress';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputAwareInterface;

/**
 * An implementation of InputAwareInterface for Helpers.
 *
 * @author Wouter J <waldio.webdesign@gmail.com>
 */
abstract class InputAwareHelper extends Helper implements InputAwareInterface
{
    protected $input;

    /**
     * {@inheritDoc}
     */
    public function setInput(InputInterface $input)
    {
        $this->input = $input;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;

/**
 * The Dialog class provides helpers to interact with the user.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DialogHelper extends InputAwareHelper
{
    private $inputStream;
    private static $shell;
    private static $stty;

    /**
     * Asks the user to select a value.
     *
     * @param OutputInterface $output       An Output instance
     * @param string|array    $question     The question to ask
     * @param array           $choices      List of choices to pick from
     * @param Boolean         $default      The default answer if the user enters nothing
     * @param Boolean|integer $attempts Max number of times to ask before giving up (false by default, which means infinite)
     * @param string          $errorMessage Message which will be shown if invalid value from choice list would be picked
     * @param Boolean         $multiselect  Select more than one value separated by comma
     *
     * @return integer|string|array The selected value or values (the key of the choices array)
     *
     * @throws \InvalidArgumentException
     */
    public function select(OutputInterface $output, $question, $choices, $default = null, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
    {
        $width = max(array_map('strlen', array_keys($choices)));

        $messages = (array) $question;
        foreach ($choices as $key => $value) {
            $messages[] = sprintf("  [<info>%-${width}s</info>] %s", $key, $value);
        }

        $output->writeln($messages);

        $result = $this->askAndValidate($output, '> ', function ($picked) use ($choices, $errorMessage, $multiselect) {
            // Collapse all spaces.
            $selectedChoices = str_replace(" ", "", $picked);

            if ($multiselect) {
                // Check for a separated comma values
                if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) {
                    throw new \InvalidArgumentException(sprintf($errorMessage, $picked));
                }
                $selectedChoices = explode(",", $selectedChoices);
            } else {
                $selectedChoices = array($picked);
            }

            $multiselectChoices = array();

            foreach ($selectedChoices as $value) {
                if (empty($choices[$value])) {
                    throw new \InvalidArgumentException(sprintf($errorMessage, $value));
                }
                array_push($multiselectChoices, $value);
            }

            if ($multiselect) {
                return $multiselectChoices;
            }

            return $picked;
        }, $attempts, $default);

        return $result;
    }

    /**
     * Asks a question to the user.
     *
     * @param OutputInterface $output       An Output instance
     * @param string|array    $question     The question to ask
     * @param string          $default      The default answer if none is given by the user
     * @param array           $autocomplete List of values to autocomplete
     *
     * @return string The user answer
     *
     * @throws \RuntimeException If there is no data to read in the input stream
     */
    public function ask(OutputInterface $output, $question, $default = null, array $autocomplete = null)
    {
        if ($this->input && !$this->input->isInteractive()) {
            return $default;
        }

        $output->write($question);

        $inputStream = $this->inputStream ?: STDIN;

        if (null === $autocomplete || !$this->hasSttyAvailable()) {
            $ret = fgets($inputStream, 4096);
            if (false === $ret) {
                throw new \RuntimeException('Aborted');
            }
            $ret = trim($ret);
        } else {
            $ret = '';

            $i = 0;
            $ofs = -1;
            $matches = $autocomplete;
            $numMatches = count($matches);

            $sttyMode = shell_exec('stty -g');

            // Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead)
            shell_exec('stty -icanon -echo');

            // Add highlighted text style
            $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));

            // Read a keypress
            while (!feof($inputStream)) {
                $c = fread($inputStream, 1);

                // Backspace Character
                if ("\177" === $c) {
                    if (0 === $numMatches && 0 !== $i) {
                        $i--;
                        // Move cursor backwards
                        $output->write("\033[1D");
                    }

                    if ($i === 0) {
                        $ofs = -1;
                        $matches = $autocomplete;
                        $numMatches = count($matches);
                    } else {
                        $numMatches = 0;
                    }

                    // Pop the last character off the end of our string
                    $ret = substr($ret, 0, $i);
                } elseif ("\033" === $c) { // Did we read an escape sequence?
                    $c .= fread($inputStream, 2);

                    // A = Up Arrow. B = Down Arrow
                    if ('A' === $c[2] || 'B' === $c[2]) {
                        if ('A' === $c[2] && -1 === $ofs) {
                            $ofs = 0;
                        }

                        if (0 === $numMatches) {
                            continue;
                        }

                        $ofs += ('A' === $c[2]) ? -1 : 1;
                        $ofs = ($numMatches + $ofs) % $numMatches;
                    }
                } elseif (ord($c) < 32) {
                    if ("\t" === $c || "\n" === $c) {
                        if ($numMatches > 0 && -1 !== $ofs) {
                            $ret = $matches[$ofs];
                            // Echo out remaining chars for current match
                            $output->write(substr($ret, $i));
                            $i = strlen($ret);
                        }

                        if ("\n" === $c) {
                            $output->write($c);
                            break;
                        }

                        $numMatches = 0;
                    }

                    continue;
                } else {
                    $output->write($c);
                    $ret .= $c;
                    $i++;

                    $numMatches = 0;
                    $ofs = 0;

                    foreach ($autocomplete as $value) {
                        // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle)
                        if (0 === strpos($value, $ret) && $i !== strlen($value)) {
                            $matches[$numMatches++] = $value;
                        }
                    }
                }

                // Erase characters from cursor to end of line
                $output->write("\033[K");

                if ($numMatches > 0 && -1 !== $ofs) {
                    // Save cursor position
                    $output->write("\0337");
                    // Write highlighted text
                    $output->write('<hl>'.substr($matches[$ofs], $i).'</hl>');
                    // Restore cursor position
                    $output->write("\0338");
                }
            }

            // Reset stty so it behaves normally again
            shell_exec(sprintf('stty %s', $sttyMode));
        }

        return strlen($ret) > 0 ? $ret : $default;
    }

    /**
     * Asks a confirmation to the user.
     *
     * The question will be asked until the user answers by nothing, yes, or no.
     *
     * @param OutputInterface $output   An Output instance
     * @param string|array    $question The question to ask
     * @param Boolean         $default  The default answer if the user enters nothing
     *
     * @return Boolean true if the user has confirmed, false otherwise
     */
    public function askConfirmation(OutputInterface $output, $question, $default = true)
    {
        $answer = 'z';
        while ($answer && !in_array(strtolower($answer[0]), array('y', 'n'))) {
            $answer = $this->ask($output, $question);
        }

        if (false === $default) {
            return $answer && 'y' == strtolower($answer[0]);
        }

        return !$answer || 'y' == strtolower($answer[0]);
    }

    /**
     * Asks a question to the user, the response is hidden
     *
     * @param OutputInterface $output   An Output instance
     * @param string|array    $question The question
     * @param Boolean         $fallback In case the response can not be hidden, whether to fallback on non-hidden question or not
     *
     * @return string         The answer
     *
     * @throws \RuntimeException In case the fallback is deactivated and the response can not be hidden
     */
    public function askHiddenResponse(OutputInterface $output, $question, $fallback = true)
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';

            // handle code running from a phar
            if ('phar:' === substr(__FILE__, 0, 5)) {
                $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
                copy($exe, $tmpExe);
                $exe = $tmpExe;
            }

            $output->write($question);
            $value = rtrim(shell_exec($exe));
            $output->writeln('');

            if (isset($tmpExe)) {
                unlink($tmpExe);
            }

            return $value;
        }

        if ($this->hasSttyAvailable()) {
            $output->write($question);

            $sttyMode = shell_exec('stty -g');

            shell_exec('stty -echo');
            $value = fgets($this->inputStream ?: STDIN, 4096);
            shell_exec(sprintf('stty %s', $sttyMode));

            if (false === $value) {
                throw new \RuntimeException('Aborted');
            }

            $value = trim($value);
            $output->writeln('');

            return $value;
        }

        if (false !== $shell = $this->getShell()) {
            $output->write($question);
            $readCmd = $shell === 'csh' ? 'set mypassword = $<' : 'read -r mypassword';
            $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
            $value = rtrim(shell_exec($command));
            $output->writeln('');

            return $value;
        }

        if ($fallback) {
            return $this->ask($output, $question);
        }

        throw new \RuntimeException('Unable to hide the response');
    }

    /**
     * Asks for a value and validates the response.
     *
     * The validator receives the data to validate. It must return the
     * validated data when the data is valid and throw an exception
     * otherwise.
     *
     * @param OutputInterface $output       An Output instance
     * @param string|array    $question     The question to ask
     * @param callable        $validator    A PHP callback
     * @param integer         $attempts     Max number of times to ask before giving up (false by default, which means infinite)
     * @param string          $default      The default answer if none is given by the user
     * @param array           $autocomplete List of values to autocomplete
     *
     * @return mixed
     *
     * @throws \Exception When any of the validators return an error
     */
    public function askAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $default = null, array $autocomplete = null)
    {
        $that = $this;

        $interviewer = function() use ($output, $question, $default, $autocomplete, $that) {
            return $that->ask($output, $question, $default, $autocomplete);
        };

        return $this->validateAttempts($interviewer, $output, $validator, $attempts);
    }

    /**
     * Asks for a value, hide and validates the response.
     *
     * The validator receives the data to validate. It must return the
     * validated data when the data is valid and throw an exception
     * otherwise.
     *
     * @param OutputInterface $output    An Output instance
     * @param string|array    $question  The question to ask
     * @param callable        $validator A PHP callback
     * @param integer         $attempts  Max number of times to ask before giving up (false by default, which means infinite)
     * @param Boolean         $fallback  In case the response can not be hidden, whether to fallback on non-hidden question or not
     *
     * @return string         The response
     *
     * @throws \Exception        When any of the validators return an error
     * @throws \RuntimeException In case the fallback is deactivated and the response can not be hidden
     *
     */
    public function askHiddenResponseAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $fallback = true)
    {
        $that = $this;

        $interviewer = function() use ($output, $question, $fallback, $that) {
            return $that->askHiddenResponse($output, $question, $fallback);
        };

        return $this->validateAttempts($interviewer, $output, $validator, $attempts);
    }

    /**
     * Sets the input stream to read from when interacting with the user.
     *
     * This is mainly useful for testing purpose.
     *
     * @param resource $stream The input stream
     */
    public function setInputStream($stream)
    {
        $this->inputStream = $stream;
    }

    /**
     * Returns the helper's input stream
     *
     * @return string
     */
    public function getInputStream()
    {
        return $this->inputStream;
    }

    /**
     * {@inheritDoc}
     */
    public function getName()
    {
        return 'dialog';
    }

    /**
     * Return a valid unix shell
     *
     * @return string|Boolean  The valid shell name, false in case no valid shell is found
     */
    private function getShell()
    {
        if (null !== self::$shell) {
            return self::$shell;
        }

        self::$shell = false;

        if (file_exists('/usr/bin/env')) {
            // handle other OSs with bash/zsh/ksh/csh if available to hide the answer
            $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
            foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
                if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
                    self::$shell = $sh;
                    break;
                }
            }
        }

        return self::$shell;
    }

    private function hasSttyAvailable()
    {
        if (null !== self::$stty) {
            return self::$stty;
        }

        exec('stty 2>&1', $output, $exitcode);

        return self::$stty = $exitcode === 0;
    }

    /**
     * Validate an attempt
     *
     * @param callable         $interviewer  A callable that will ask for a question and return the result
     * @param OutputInterface  $output       An Output instance
     * @param callable         $validator    A PHP callback
     * @param integer          $attempts     Max number of times to ask before giving up ; false will ask infinitely
     *
     * @return string   The validated response
     *
     * @throws \Exception In case the max number of attempts has been reached and no valid response has been given
     */
    private function validateAttempts($interviewer, OutputInterface $output, $validator, $attempts)
    {
        $error = null;
        while (false === $attempts || $attempts--) {
            if (null !== $error) {
                $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error'));
            }

            try {
                return call_user_func($validator, $interviewer());
            } catch (\Exception $error) {
            }
        }

        throw $error;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Descriptor\DescriptorInterface;
use Symfony\Component\Console\Descriptor\JsonDescriptor;
use Symfony\Component\Console\Descriptor\MarkdownDescriptor;
use Symfony\Component\Console\Descriptor\TextDescriptor;
use Symfony\Component\Console\Descriptor\XmlDescriptor;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * This class adds helper method to describe objects in various formats.
 *
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class DescriptorHelper extends Helper
{
    /**
     * @var DescriptorInterface[]
     */
    private $descriptors = array();

    /**
     * Constructor.
     */
    public function __construct()
    {
        $this
            ->register('txt',  new TextDescriptor())
            ->register('xml',  new XmlDescriptor())
            ->register('json', new JsonDescriptor())
            ->register('md',   new MarkdownDescriptor())
        ;
    }

    /**
     * Describes an object if supported.
     *
     * Available options are:
     * * format: string, the output format name
     * * raw_text: boolean, sets output type as raw
     *
     * @param OutputInterface $output
     * @param object          $object
     * @param array           $options
     *
     * @throws \InvalidArgumentException
     */
    public function describe(OutputInterface $output, $object, array $options = array())
    {
        $options = array_merge(array(
            'raw_text'  => false,
            'format'    => 'txt',
        ), $options);

        if (!isset($this->descriptors[$options['format']])) {
            throw new \InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format']));
        }

        $descriptor = $this->descriptors[$options['format']];
        $descriptor->describe($output, $object, $options);
    }

    /**
     * Registers a descriptor.
     *
     * @param string              $format
     * @param DescriptorInterface $descriptor
     *
     * @return DescriptorHelper
     */
    public function register($format, DescriptorInterface $descriptor)
    {
        $this->descriptors[$format] = $descriptor;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'descriptor';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Output\OutputInterface;
use InvalidArgumentException;

/**
 * Provides helpers to display table output.
 *
 * @author Саша Стаменковић <umpirsky@gmail.com>
 */
class TableHelper extends Helper
{
    const LAYOUT_DEFAULT = 0;
    const LAYOUT_BORDERLESS = 1;
    const LAYOUT_COMPACT = 2;

    /**
     * Table headers.
     *
     * @var array
     */
    private $headers = array();

    /**
     * Table rows.
     *
     * @var array
     */
    private $rows = array();

    // Rendering options
    private $paddingChar;
    private $horizontalBorderChar;
    private $verticalBorderChar;
    private $crossingChar;
    private $cellHeaderFormat;
    private $cellRowFormat;
    private $cellRowContentFormat;
    private $borderFormat;
    private $padType;

    /**
     * Column widths cache.
     *
     * @var array
     */
    private $columnWidths = array();

    /**
     * Number of columns cache.
     *
     * @var array
     */
    private $numberOfColumns;

    /**
     * @var OutputInterface
     */
    private $output;

    public function __construct()
    {
        $this->setLayout(self::LAYOUT_DEFAULT);
    }

    /**
     * Sets table layout type.
     *
     * @param int $layout self::LAYOUT_*
     *
     * @return TableHelper
     */
    public function setLayout($layout)
    {
        switch ($layout) {
            case self::LAYOUT_BORDERLESS:
                $this
                    ->setPaddingChar(' ')
                    ->setHorizontalBorderChar('=')
                    ->setVerticalBorderChar(' ')
                    ->setCrossingChar(' ')
                    ->setCellHeaderFormat('<info>%s</info>')
                    ->setCellRowFormat('%s')
                    ->setCellRowContentFormat(' %s ')
                    ->setBorderFormat('%s')
                    ->setPadType(STR_PAD_RIGHT)
                ;
                break;

            case self::LAYOUT_COMPACT:
                $this
                    ->setPaddingChar(' ')
                    ->setHorizontalBorderChar('')
                    ->setVerticalBorderChar(' ')
                    ->setCrossingChar('')
                    ->setCellHeaderFormat('<info>%s</info>')
                    ->setCellRowFormat('%s')
                    ->setCellRowContentFormat('%s')
                    ->setBorderFormat('%s')
                    ->setPadType(STR_PAD_RIGHT)
                ;
                break;

            case self::LAYOUT_DEFAULT:
                $this
                    ->setPaddingChar(' ')
                    ->setHorizontalBorderChar('-')
                    ->setVerticalBorderChar('|')
                    ->setCrossingChar('+')
                    ->setCellHeaderFormat('<info>%s</info>')
                    ->setCellRowFormat('%s')
                    ->setCellRowContentFormat(' %s ')
                    ->setBorderFormat('%s')
                    ->setPadType(STR_PAD_RIGHT)
                ;
                break;

            default:
                throw new InvalidArgumentException(sprintf('Invalid table layout "%s".', $layout));
                break;
        };

        return $this;
    }

    public function setHeaders(array $headers)
    {
        $this->headers = array_values($headers);

        return $this;
    }

    public function setRows(array $rows)
    {
        $this->rows = array();

        return $this->addRows($rows);
    }

    public function addRows(array $rows)
    {
        foreach ($rows as $row) {
            $this->addRow($row);
        }

        return $this;
    }

    public function addRow(array $row)
    {
        $this->rows[] = array_values($row);

        return $this;
    }

    public function setRow($column, array $row)
    {
        $this->rows[$column] = $row;

        return $this;
    }

    /**
     * Sets padding character, used for cell padding.
     *
     * @param string $paddingChar
     *
     * @return TableHelper
     */
    public function setPaddingChar($paddingChar)
    {
        if (!$paddingChar) {
            throw new \LogicException('The padding char must not be empty');
        }

        $this->paddingChar = $paddingChar;

        return $this;
    }

    /**
     * Sets horizontal border character.
     *
     * @param string $horizontalBorderChar
     *
     * @return TableHelper
     */
    public function setHorizontalBorderChar($horizontalBorderChar)
    {
        $this->horizontalBorderChar = $horizontalBorderChar;

        return $this;
    }

    /**
     * Sets vertical border character.
     *
     * @param string $verticalBorderChar
     *
     * @return TableHelper
     */
    public function setVerticalBorderChar($verticalBorderChar)
    {
        $this->verticalBorderChar = $verticalBorderChar;

        return $this;
    }

    /**
     * Sets crossing character.
     *
     * @param string $crossingChar
     *
     * @return TableHelper
     */
    public function setCrossingChar($crossingChar)
    {
        $this->crossingChar = $crossingChar;

        return $this;
    }

    /**
     * Sets header cell format.
     *
     * @param string $cellHeaderFormat
     *
     * @return TableHelper
     */
    public function setCellHeaderFormat($cellHeaderFormat)
    {
        $this->cellHeaderFormat = $cellHeaderFormat;

        return $this;
    }

    /**
     * Sets row cell format.
     *
     * @param string $cellRowFormat
     *
     * @return TableHelper
     */
    public function setCellRowFormat($cellRowFormat)
    {
        $this->cellRowFormat = $cellRowFormat;

        return $this;
    }

    /**
     * Sets row cell content format.
     *
     * @param string $cellRowContentFormat
     *
     * @return TableHelper
     */
    public function setCellRowContentFormat($cellRowContentFormat)
    {
        $this->cellRowContentFormat = $cellRowContentFormat;

        return $this;
    }

    /**
     * Sets table border format.
     *
     * @param string $borderFormat
     *
     * @return TableHelper
     */
    public function setBorderFormat($borderFormat)
    {
        $this->borderFormat = $borderFormat;

        return $this;
    }

    /**
     * Sets cell padding type.
     *
     * @param integer $padType STR_PAD_*
     *
     * @return TableHelper
     */
    public function setPadType($padType)
    {
        $this->padType = $padType;

        return $this;
    }

    /**
     * Renders table to output.
     *
     * Example:
     * +---------------+-----------------------+------------------+
     * | ISBN          | Title                 | Author           |
     * +---------------+-----------------------+------------------+
     * | 99921-58-10-7 | Divine Comedy         | Dante Alighieri  |
     * | 9971-5-0210-0 | A Tale of Two Cities  | Charles Dickens  |
     * | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
     * +---------------+-----------------------+------------------+
     *
     * @param OutputInterface $output
     */
    public function render(OutputInterface $output)
    {
        $this->output = $output;

        $this->renderRowSeparator();
        $this->renderRow($this->headers, $this->cellHeaderFormat);
        if (!empty($this->headers)) {
            $this->renderRowSeparator();
        }
        foreach ($this->rows as $row) {
            $this->renderRow($row, $this->cellRowFormat);
        }
        if (!empty($this->rows)) {
            $this->renderRowSeparator();
        }

        $this->cleanup();
    }

    /**
     * Renders horizontal header separator.
     *
     * Example: +-----+-----------+-------+
     */
    private function renderRowSeparator()
    {
        if (0 === $count = $this->getNumberOfColumns()) {
            return;
        }

        if (!$this->horizontalBorderChar && !$this->crossingChar) {
            return;
        }

        $markup = $this->crossingChar;
        for ($column = 0; $column < $count; $column++) {
            $markup .= str_repeat($this->horizontalBorderChar, $this->getColumnWidth($column)).$this->crossingChar;
        }

        $this->output->writeln(sprintf($this->borderFormat, $markup));
    }

    /**
     * Renders vertical column separator.
     */
    private function renderColumnSeparator()
    {
        $this->output->write(sprintf($this->borderFormat, $this->verticalBorderChar));
    }

    /**
     * Renders table row.
     *
     * Example: | 9971-5-0210-0 | A Tale of Two Cities  | Charles Dickens  |
     *
     * @param array  $row
     * @param string $cellFormat
     */
    private function renderRow(array $row, $cellFormat)
    {
        if (empty($row)) {
            return;
        }

        $this->renderColumnSeparator();
        for ($column = 0, $count = $this->getNumberOfColumns(); $column < $count; $column++) {
            $this->renderCell($row, $column, $cellFormat);
            $this->renderColumnSeparator();
        }
        $this->output->writeln('');
    }

    /**
     * Renders table cell with padding.
     *
     * @param array   $row
     * @param integer $column
     * @param string  $cellFormat
     */
    private function renderCell(array $row, $column, $cellFormat)
    {
        $cell = isset($row[$column]) ? $row[$column] : '';
        $width = $this->getColumnWidth($column);

        // str_pad won't work properly with multi-byte strings, we need to fix the padding
        if (function_exists('mb_strlen') && false !== $encoding = mb_detect_encoding($cell)) {
            $width += strlen($cell) - mb_strlen($cell, $encoding);
        }

        $content = sprintf($this->cellRowContentFormat, $cell);

        $this->output->write(sprintf($cellFormat, str_pad($content, $width, $this->paddingChar, $this->padType)));
    }

    /**
     * Gets number of columns for this table.
     *
     * @return int
     */
    private function getNumberOfColumns()
    {
        if (null !== $this->numberOfColumns) {
            return $this->numberOfColumns;
        }

        $columns = array(0);
        $columns[] = count($this->headers);
        foreach ($this->rows as $row) {
            $columns[] = count($row);
        }

        return $this->numberOfColumns = max($columns);
    }

    /**
     * Gets column width.
     *
     * @param integer $column
     *
     * @return int
     */
    private function getColumnWidth($column)
    {
        if (isset($this->columnWidths[$column])) {
            return $this->columnWidths[$column];
        }

        $lengths = array(0);
        $lengths[] = $this->getCellWidth($this->headers, $column);
        foreach ($this->rows as $row) {
            $lengths[] = $this->getCellWidth($row, $column);
        }

        return $this->columnWidths[$column] = max($lengths) + strlen($this->cellRowContentFormat) - 2;
    }

    /**
     * Gets cell width.
     *
     * @param array   $row
     * @param integer $column
     *
     * @return int
     */
    private function getCellWidth(array $row, $column)
    {
        if ($column < 0) {
            return 0;
        }

        if (isset($row[$column])) {
            return $this->strlen($row[$column]);
        }

        return $this->getCellWidth($row, $column - 1);
    }

    /**
     * Called after rendering to cleanup cache data.
     */
    private function cleanup()
    {
        $this->columnWidths = array();
        $this->numberOfColumns = null;
    }

    /**
     * {@inheritDoc}
     */
    public function getName()
    {
        return 'table';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

/**
 * Helper is the base class for all helper classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Helper implements HelperInterface
{
    protected $helperSet = null;

    /**
     * Sets the helper set associated with this helper.
     *
     * @param HelperSet $helperSet A HelperSet instance
     */
    public function setHelperSet(HelperSet $helperSet = null)
    {
        $this->helperSet = $helperSet;
    }

    /**
     * Gets the helper set associated with this helper.
     *
     * @return HelperSet A HelperSet instance
     */
    public function getHelperSet()
    {
        return $this->helperSet;
    }

    /**
     * Returns the length of a string, using mb_strlen if it is available.
     *
     * @param string $string The string to check its length
     *
     * @return integer The length of the string
     */
    protected function strlen($string)
    {
        if (!function_exists('mb_strlen')) {
            return strlen($string);
        }

        if (false === $encoding = mb_detect_encoding($string)) {
            return strlen($string);
        }

        return mb_strlen($string, $encoding);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Command\Command;

/**
 * HelperSet represents a set of helpers to be used with a command.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class HelperSet implements \IteratorAggregate
{
    private $helpers = array();
    private $command;

    /**
     * Constructor.
     *
     * @param Helper[] $helpers An array of helper.
     */
    public function __construct(array $helpers = array())
    {
        foreach ($helpers as $alias => $helper) {
            $this->set($helper, is_int($alias) ? null : $alias);
        }
    }

    /**
     * Sets a helper.
     *
     * @param HelperInterface $helper The helper instance
     * @param string          $alias  An alias
     */
    public function set(HelperInterface $helper, $alias = null)
    {
        $this->helpers[$helper->getName()] = $helper;
        if (null !== $alias) {
            $this->helpers[$alias] = $helper;
        }

        $helper->setHelperSet($this);
    }

    /**
     * Returns true if the helper if defined.
     *
     * @param string $name The helper name
     *
     * @return Boolean true if the helper is defined, false otherwise
     */
    public function has($name)
    {
        return isset($this->helpers[$name]);
    }

    /**
     * Gets a helper value.
     *
     * @param string $name The helper name
     *
     * @return HelperInterface The helper instance
     *
     * @throws \InvalidArgumentException if the helper is not defined
     */
    public function get($name)
    {
        if (!$this->has($name)) {
            throw new \InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name));
        }

        return $this->helpers[$name];
    }

    /**
     * Sets the command associated with this helper set.
     *
     * @param Command $command A Command instance
     */
    public function setCommand(Command $command = null)
    {
        $this->command = $command;
    }

    /**
     * Gets the command associated with this helper set.
     *
     * @return Command A Command instance
     */
    public function getCommand()
    {
        return $this->command;
    }

    public function getIterator()
    {
        return new \ArrayIterator($this->helpers);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Formatter;

/**
 * Formatter interface for console output.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 *
 * @api
 */
interface OutputFormatterInterface
{
    /**
     * Sets the decorated flag.
     *
     * @param Boolean $decorated Whether to decorate the messages or not
     *
     * @api
     */
    public function setDecorated($decorated);

    /**
     * Gets the decorated flag.
     *
     * @return Boolean true if the output will decorate messages, false otherwise
     *
     * @api
     */
    public function isDecorated();

    /**
     * Sets a new style.
     *
     * @param string                        $name  The style name
     * @param OutputFormatterStyleInterface $style The style instance
     *
     * @api
     */
    public function setStyle($name, OutputFormatterStyleInterface $style);

    /**
     * Checks if output formatter has style with specified name.
     *
     * @param string $name
     *
     * @return Boolean
     *
     * @api
     */
    public function hasStyle($name);

    /**
     * Gets style options from style with specified name.
     *
     * @param string $name
     *
     * @return OutputFormatterStyleInterface
     *
     * @api
     */
    public function getStyle($name);

    /**
     * Formats a message according to the given styles.
     *
     * @param string $message The message to style
     *
     * @return string The styled message
     *
     * @api
     */
    public function format($message);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Formatter;

/**
 * Formatter style interface for defining styles.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 *
 * @api
 */
interface OutputFormatterStyleInterface
{
    /**
     * Sets style foreground color.
     *
     * @param string $color The color name
     *
     * @api
     */
    public function setForeground($color = null);

    /**
     * Sets style background color.
     *
     * @param string $color The color name
     *
     * @api
     */
    public function setBackground($color = null);

    /**
     * Sets some specific style option.
     *
     * @param string $option The option name
     *
     * @api
     */
    public function setOption($option);

    /**
     * Unsets some specific style option.
     *
     * @param string $option The option name
     */
    public function unsetOption($option);

    /**
     * Sets multiple style options at once.
     *
     * @param array $options
     */
    public function setOptions(array $options);

    /**
     * Applies the style to a given text.
     *
     * @param string $text The text to style
     *
     * @return string
     */
    public function apply($text);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Formatter;

/**
 * Formatter style class for defining styles.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 *
 * @api
 */
class OutputFormatterStyle implements OutputFormatterStyleInterface
{
    private static $availableForegroundColors = array(
        'black'     => 30,
        'red'       => 31,
        'green'     => 32,
        'yellow'    => 33,
        'blue'      => 34,
        'magenta'   => 35,
        'cyan'      => 36,
        'white'     => 37
    );
    private static $availableBackgroundColors = array(
        'black'     => 40,
        'red'       => 41,
        'green'     => 42,
        'yellow'    => 43,
        'blue'      => 44,
        'magenta'   => 45,
        'cyan'      => 46,
        'white'     => 47
    );
    private static $availableOptions = array(
        'bold'          => 1,
        'underscore'    => 4,
        'blink'         => 5,
        'reverse'       => 7,
        'conceal'       => 8
    );

    private $foreground;
    private $background;
    private $options = array();

    /**
     * Initializes output formatter style.
     *
     * @param string|null $foreground The style foreground color name
     * @param string|null $background The style background color name
     * @param array       $options    The style options
     *
     * @api
     */
    public function __construct($foreground = null, $background = null, array $options = array())
    {
        if (null !== $foreground) {
            $this->setForeground($foreground);
        }
        if (null !== $background) {
            $this->setBackground($background);
        }
        if (count($options)) {
            $this->setOptions($options);
        }
    }

    /**
     * Sets style foreground color.
     *
     * @param string|null $color The color name
     *
     * @throws \InvalidArgumentException When the color name isn't defined
     *
     * @api
     */
    public function setForeground($color = null)
    {
        if (null === $color) {
            $this->foreground = null;

            return;
        }

        if (!isset(static::$availableForegroundColors[$color])) {
            throw new \InvalidArgumentException(sprintf(
                'Invalid foreground color specified: "%s". Expected one of (%s)',
                $color,
                implode(', ', array_keys(static::$availableForegroundColors))
            ));
        }

        $this->foreground = static::$availableForegroundColors[$color];
    }

    /**
     * Sets style background color.
     *
     * @param string|null $color The color name
     *
     * @throws \InvalidArgumentException When the color name isn't defined
     *
     * @api
     */
    public function setBackground($color = null)
    {
        if (null === $color) {
            $this->background = null;

            return;
        }

        if (!isset(static::$availableBackgroundColors[$color])) {
            throw new \InvalidArgumentException(sprintf(
                'Invalid background color specified: "%s". Expected one of (%s)',
                $color,
                implode(', ', array_keys(static::$availableBackgroundColors))
            ));
        }

        $this->background = static::$availableBackgroundColors[$color];
    }

    /**
     * Sets some specific style option.
     *
     * @param string $option The option name
     *
     * @throws \InvalidArgumentException When the option name isn't defined
     *
     * @api
     */
    public function setOption($option)
    {
        if (!isset(static::$availableOptions[$option])) {
            throw new \InvalidArgumentException(sprintf(
                'Invalid option specified: "%s". Expected one of (%s)',
                $option,
                implode(', ', array_keys(static::$availableOptions))
            ));
        }

        if (false === array_search(static::$availableOptions[$option], $this->options)) {
            $this->options[] = static::$availableOptions[$option];
        }
    }

    /**
     * Unsets some specific style option.
     *
     * @param string $option The option name
     *
     * @throws \InvalidArgumentException When the option name isn't defined
     *
     */
    public function unsetOption($option)
    {
        if (!isset(static::$availableOptions[$option])) {
            throw new \InvalidArgumentException(sprintf(
                'Invalid option specified: "%s". Expected one of (%s)',
                $option,
                implode(', ', array_keys(static::$availableOptions))
            ));
        }

        $pos = array_search(static::$availableOptions[$option], $this->options);
        if (false !== $pos) {
            unset($this->options[$pos]);
        }
    }

    /**
     * Sets multiple style options at once.
     *
     * @param array $options
     */
    public function setOptions(array $options)
    {
        $this->options = array();

        foreach ($options as $option) {
            $this->setOption($option);
        }
    }

    /**
     * Applies the style to a given text.
     *
     * @param string $text The text to style
     *
     * @return string
     */
    public function apply($text)
    {
        $codes = array();

        if (null !== $this->foreground) {
            $codes[] = $this->foreground;
        }
        if (null !== $this->background) {
            $codes[] = $this->background;
        }
        if (count($this->options)) {
            $codes = array_merge($codes, $this->options);
        }

        if (0 === count($codes)) {
            return $text;
        }

        return sprintf("\033[%sm%s\033[0m", implode(';', $codes), $text);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Formatter;

/**
 * Formatter class for console output.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 *
 * @api
 */
class OutputFormatter implements OutputFormatterInterface
{
    /**
     * The pattern to phrase the format.
     */
    const FORMAT_PATTERN = '#(\\\\?)<(/?)([a-z][a-z0-9_=;-]*)?>((?: [^<\\\\]+ | (?!<(?:/?[a-z]|/>)). | .(?<=\\\\<) )*)#isx';

    private $decorated;
    private $styles = array();
    private $styleStack;

    /**
     * Escapes "<" special char in given text.
     *
     * @param string $text Text to escape
     *
     * @return string Escaped text
     */
    public static function escape($text)
    {
        return preg_replace('/([^\\\\]?)</is', '$1\\<', $text);
    }

    /**
     * Initializes console output formatter.
     *
     * @param Boolean          $decorated Whether this formatter should actually decorate strings
     * @param OutputFormatterStyleInterface[] $styles    Array of "name => FormatterStyle" instances
     *
     * @api
     */
    public function __construct($decorated = false, array $styles = array())
    {
        $this->decorated = (Boolean) $decorated;

        $this->setStyle('error', new OutputFormatterStyle('white', 'red'));
        $this->setStyle('info', new OutputFormatterStyle('green'));
        $this->setStyle('comment', new OutputFormatterStyle('yellow'));
        $this->setStyle('question', new OutputFormatterStyle('black', 'cyan'));

        foreach ($styles as $name => $style) {
            $this->setStyle($name, $style);
        }

        $this->styleStack = new OutputFormatterStyleStack();
    }

    /**
     * Sets the decorated flag.
     *
     * @param Boolean $decorated Whether to decorate the messages or not
     *
     * @api
     */
    public function setDecorated($decorated)
    {
        $this->decorated = (Boolean) $decorated;
    }

    /**
     * Gets the decorated flag.
     *
     * @return Boolean true if the output will decorate messages, false otherwise
     *
     * @api
     */
    public function isDecorated()
    {
        return $this->decorated;
    }

    /**
     * Sets a new style.
     *
     * @param string                        $name  The style name
     * @param OutputFormatterStyleInterface $style The style instance
     *
     * @api
     */
    public function setStyle($name, OutputFormatterStyleInterface $style)
    {
        $this->styles[strtolower($name)] = $style;
    }

    /**
     * Checks if output formatter has style with specified name.
     *
     * @param string $name
     *
     * @return Boolean
     *
     * @api
     */
    public function hasStyle($name)
    {
        return isset($this->styles[strtolower($name)]);
    }

    /**
     * Gets style options from style with specified name.
     *
     * @param string $name
     *
     * @return OutputFormatterStyleInterface
     *
     * @throws \InvalidArgumentException When style isn't defined
     *
     * @api
     */
    public function getStyle($name)
    {
        if (!$this->hasStyle($name)) {
            throw new \InvalidArgumentException(sprintf('Undefined style: %s', $name));
        }

        return $this->styles[strtolower($name)];
    }

    /**
     * Formats a message according to the given styles.
     *
     * @param string $message The message to style
     *
     * @return string The styled message
     *
     * @api
     */
    public function format($message)
    {
        $message = preg_replace_callback(self::FORMAT_PATTERN, array($this, 'replaceStyle'), $message);

        return str_replace('\\<', '<', $message);
    }

    /**
     * @return OutputFormatterStyleStack
     */
    public function getStyleStack()
    {
        return $this->styleStack;
    }

    /**
     * Replaces style of the output.
     *
     * All escaped tags and tags that reference unknown styles are kept as is.
     *
     * @param array $match
     *
     * @return string The replaced style
     */
    private function replaceStyle($match)
    {
        // we got "\<" escaped char
        if ('\\' === $match[1]) {
            return $this->applyCurrentStyle($match[0]);
        }

        if ('' === $match[3]) {
            if ('/' === $match[2]) {
                // we got "</>" tag
                $this->styleStack->pop();

                return $this->applyCurrentStyle($match[4]);
            }

            // we got "<>" tag
            return '<>'.$this->applyCurrentStyle($match[4]);
        }

        if (isset($this->styles[strtolower($match[3])])) {
            $style = $this->styles[strtolower($match[3])];
        } else {
            $style = $this->createStyleFromString($match[3]);

            if (false === $style) {
                return $this->applyCurrentStyle($match[0]);
            }
        }

        if ('/' === $match[2]) {
            $this->styleStack->pop($style);
        } else {
            $this->styleStack->push($style);
        }

        return $this->applyCurrentStyle($match[4]);
    }

    /**
     * Tries to create new style instance from string.
     *
     * @param string $string
     *
     * @return OutputFormatterStyle|Boolean false if string is not format string
     */
    private function createStyleFromString($string)
    {
        if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($string), $matches, PREG_SET_ORDER)) {
            return false;
        }

        $style = new OutputFormatterStyle();
        foreach ($matches as $match) {
            array_shift($match);

            if ('fg' == $match[0]) {
                $style->setForeground($match[1]);
            } elseif ('bg' == $match[0]) {
                $style->setBackground($match[1]);
            } else {
                $style->setOption($match[1]);
            }
        }

        return $style;
    }

    /**
     * Applies current style from stack to text, if must be applied.
     *
     * @param string $text Input text
     *
     * @return string Styled text
     */
    private function applyCurrentStyle($text)
    {
        return $this->isDecorated() && strlen($text) > 0 ? $this->styleStack->getCurrent()->apply($text) : $text;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Formatter;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class OutputFormatterStyleStack
{
    /**
     * @var OutputFormatterStyleInterface[]
     */
    private $styles;

    /**
     * @var OutputFormatterStyleInterface
     */
    private $emptyStyle;

    /**
     * Constructor.
     *
     * @param OutputFormatterStyleInterface|null $emptyStyle
     */
    public function __construct(OutputFormatterStyleInterface $emptyStyle = null)
    {
        $this->emptyStyle = $emptyStyle ?: new OutputFormatterStyle();
        $this->reset();
    }

    /**
     * Resets stack (ie. empty internal arrays).
     */
    public function reset()
    {
        $this->styles = array();
    }

    /**
     * Pushes a style in the stack.
     *
     * @param OutputFormatterStyleInterface $style
     */
    public function push(OutputFormatterStyleInterface $style)
    {
        $this->styles[] = $style;
    }

    /**
     * Pops a style from the stack.
     *
     * @param OutputFormatterStyleInterface|null $style
     *
     * @return OutputFormatterStyleInterface
     *
     * @throws \InvalidArgumentException  When style tags incorrectly nested
     */
    public function pop(OutputFormatterStyleInterface $style = null)
    {
        if (empty($this->styles)) {
            return $this->emptyStyle;
        }

        if (null === $style) {
            return array_pop($this->styles);
        }

        foreach (array_reverse($this->styles, true) as $index => $stackedStyle) {
            if ($style->apply('') === $stackedStyle->apply('')) {
                $this->styles = array_slice($this->styles, 0, $index);

                return $stackedStyle;
            }
        }

        throw new \InvalidArgumentException('Incorrectly nested style tag found.');
    }

    /**
     * Computes current style with stacks top codes.
     *
     * @return OutputFormatterStyle
     */
    public function getCurrent()
    {
        if (empty($this->styles)) {
            return $this->emptyStyle;
        }

        return $this->styles[count($this->styles)-1];
    }

    /**
     * @param OutputFormatterStyleInterface $emptyStyle
     *
     * @return OutputFormatterStyleStack
     */
    public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle)
    {
        $this->emptyStyle = $emptyStyle;

        return $this;
    }

    /**
     * @return OutputFormatterStyleInterface
     */
    public function getEmptyStyle()
    {
        return $this->emptyStyle;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\FormatterHelper;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\StringInput;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Tester\CommandTester;

class CommandTest extends \PHPUnit_Framework_TestCase
{
    protected static $fixturesPath;

    public static function setUpBeforeClass()
    {
        self::$fixturesPath = __DIR__.'/../Fixtures/';
        require_once self::$fixturesPath.'/TestCommand.php';
    }

    public function testConstructor()
    {
        $command = new Command('foo:bar');
        $this->assertEquals('foo:bar', $command->getName(), '__construct() takes the command name as its first argument');
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage The command name cannot be empty.
     */
    public function testCommandNameCannotBeEmpty()
    {
        new Command();
    }

    public function testSetApplication()
    {
        $application = new Application();
        $command = new \TestCommand();
        $command->setApplication($application);
        $this->assertEquals($application, $command->getApplication(), '->setApplication() sets the current application');
    }

    public function testSetGetDefinition()
    {
        $command = new \TestCommand();
        $ret = $command->setDefinition($definition = new InputDefinition());
        $this->assertEquals($command, $ret, '->setDefinition() implements a fluent interface');
        $this->assertEquals($definition, $command->getDefinition(), '->setDefinition() sets the current InputDefinition instance');
        $command->setDefinition(array(new InputArgument('foo'), new InputOption('bar')));
        $this->assertTrue($command->getDefinition()->hasArgument('foo'), '->setDefinition() also takes an array of InputArguments and InputOptions as an argument');
        $this->assertTrue($command->getDefinition()->hasOption('bar'), '->setDefinition() also takes an array of InputArguments and InputOptions as an argument');
        $command->setDefinition(new InputDefinition());
    }

    public function testAddArgument()
    {
        $command = new \TestCommand();
        $ret = $command->addArgument('foo');
        $this->assertEquals($command, $ret, '->addArgument() implements a fluent interface');
        $this->assertTrue($command->getDefinition()->hasArgument('foo'), '->addArgument() adds an argument to the command');
    }

    public function testAddOption()
    {
        $command = new \TestCommand();
        $ret = $command->addOption('foo');
        $this->assertEquals($command, $ret, '->addOption() implements a fluent interface');
        $this->assertTrue($command->getDefinition()->hasOption('foo'), '->addOption() adds an option to the command');
    }

    public function testGetNamespaceGetNameSetName()
    {
        $command = new \TestCommand();
        $this->assertEquals('namespace:name', $command->getName(), '->getName() returns the command name');
        $command->setName('foo');
        $this->assertEquals('foo', $command->getName(), '->setName() sets the command name');

        $ret = $command->setName('foobar:bar');
        $this->assertEquals($command, $ret, '->setName() implements a fluent interface');
        $this->assertEquals('foobar:bar', $command->getName(), '->setName() sets the command name');
    }

    /**
     * @dataProvider provideInvalidCommandNames
     */
    public function testInvalidCommandNames($name)
    {
        $this->setExpectedException('InvalidArgumentException', sprintf('Command name "%s" is invalid.', $name));

        $command = new \TestCommand();
        $command->setName($name);
    }

    public function provideInvalidCommandNames()
    {
        return array(
            array(''),
            array('foo:')
        );
    }

    public function testGetSetDescription()
    {
        $command = new \TestCommand();
        $this->assertEquals('description', $command->getDescription(), '->getDescription() returns the description');
        $ret = $command->setDescription('description1');
        $this->assertEquals($command, $ret, '->setDescription() implements a fluent interface');
        $this->assertEquals('description1', $command->getDescription(), '->setDescription() sets the description');
    }

    public function testGetSetHelp()
    {
        $command = new \TestCommand();
        $this->assertEquals('help', $command->getHelp(), '->getHelp() returns the help');
        $ret = $command->setHelp('help1');
        $this->assertEquals($command, $ret, '->setHelp() implements a fluent interface');
        $this->assertEquals('help1', $command->getHelp(), '->setHelp() sets the help');
    }

    public function testGetProcessedHelp()
    {
        $command = new \TestCommand();
        $command->setHelp('The %command.name% command does... Example: php %command.full_name%.');
        $this->assertContains('The namespace:name command does...', $command->getProcessedHelp(), '->getProcessedHelp() replaces %command.name% correctly');
        $this->assertNotContains('%command.full_name%', $command->getProcessedHelp(), '->getProcessedHelp() replaces %command.full_name%');
    }

    public function testGetSetAliases()
    {
        $command = new \TestCommand();
        $this->assertEquals(array('name'), $command->getAliases(), '->getAliases() returns the aliases');
        $ret = $command->setAliases(array('name1'));
        $this->assertEquals($command, $ret, '->setAliases() implements a fluent interface');
        $this->assertEquals(array('name1'), $command->getAliases(), '->setAliases() sets the aliases');
    }

    public function testGetSynopsis()
    {
        $command = new \TestCommand();
        $command->addOption('foo');
        $command->addArgument('foo');
        $this->assertEquals('namespace:name [--foo] [foo]', $command->getSynopsis(), '->getSynopsis() returns the synopsis');
    }

    public function testGetHelper()
    {
        $application = new Application();
        $command = new \TestCommand();
        $command->setApplication($application);
        $formatterHelper = new FormatterHelper();
        $this->assertEquals($formatterHelper->getName(), $command->getHelper('formatter')->getName(), '->getHelper() returns the correct helper');
    }

    public function testGet()
    {
        $application = new Application();
        $command = new \TestCommand();
        $command->setApplication($application);
        $formatterHelper = new FormatterHelper();
        $this->assertEquals($formatterHelper->getName(), $command->getHelper('formatter')->getName(), '->__get() returns the correct helper');
    }

    public function testMergeApplicationDefinition()
    {
        $application1 = new Application();
        $application1->getDefinition()->addArguments(array(new InputArgument('foo')));
        $application1->getDefinition()->addOptions(array(new InputOption('bar')));
        $command = new \TestCommand();
        $command->setApplication($application1);
        $command->setDefinition($definition = new InputDefinition(array(new InputArgument('bar'), new InputOption('foo'))));

        $r = new \ReflectionObject($command);
        $m = $r->getMethod('mergeApplicationDefinition');
        $m->setAccessible(true);
        $m->invoke($command);
        $this->assertTrue($command->getDefinition()->hasArgument('foo'), '->mergeApplicationDefinition() merges the application arguments and the command arguments');
        $this->assertTrue($command->getDefinition()->hasArgument('bar'), '->mergeApplicationDefinition() merges the application arguments and the command arguments');
        $this->assertTrue($command->getDefinition()->hasOption('foo'), '->mergeApplicationDefinition() merges the application options and the command options');
        $this->assertTrue($command->getDefinition()->hasOption('bar'), '->mergeApplicationDefinition() merges the application options and the command options');

        $m->invoke($command);
        $this->assertEquals(3, $command->getDefinition()->getArgumentCount(), '->mergeApplicationDefinition() does not try to merge twice the application arguments and options');
    }

    public function testMergeApplicationDefinitionWithoutArgsThenWithArgsAddsArgs()
    {
        $application1 = new Application();
        $application1->getDefinition()->addArguments(array(new InputArgument('foo')));
        $application1->getDefinition()->addOptions(array(new InputOption('bar')));
        $command = new \TestCommand();
        $command->setApplication($application1);
        $command->setDefinition($definition = new InputDefinition(array()));

        $r = new \ReflectionObject($command);
        $m = $r->getMethod('mergeApplicationDefinition');
        $m->setAccessible(true);
        $m->invoke($command, false);
        $this->assertTrue($command->getDefinition()->hasOption('bar'), '->mergeApplicationDefinition(false) merges the application and the commmand options');
        $this->assertFalse($command->getDefinition()->hasArgument('foo'), '->mergeApplicationDefinition(false) does not merge the application arguments');

        $m->invoke($command, true);
        $this->assertTrue($command->getDefinition()->hasArgument('foo'), '->mergeApplicationDefinition(true) merges the application arguments and the command arguments');

        $m->invoke($command);
        $this->assertEquals(2, $command->getDefinition()->getArgumentCount(), '->mergeApplicationDefinition() does not try to merge twice the application arguments');
    }

    public function testRunInteractive()
    {
        $tester = new CommandTester(new \TestCommand());

        $tester->execute(array(), array('interactive' => true));

        $this->assertEquals('interact called'.PHP_EOL.'execute called'.PHP_EOL, $tester->getDisplay(), '->run() calls the interact() method if the input is interactive');
    }

    public function testRunNonInteractive()
    {
        $tester = new CommandTester(new \TestCommand());

        $tester->execute(array(), array('interactive' => false));

        $this->assertEquals('execute called'.PHP_EOL, $tester->getDisplay(), '->run() does not call the interact() method if the input is not interactive');
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage You must override the execute() method in the concrete command class.
     */
    public function testExecuteMethodNeedsToBeOverriden()
    {
        $command = new Command('foo');
        $command->run(new StringInput(''), new NullOutput());
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The "--bar" option does not exist.
     */
    public function testRunWithInvalidOption()
    {
        $command = new \TestCommand();
        $tester = new CommandTester($command);
        $tester->execute(array('--bar' => true));
    }

    public function testRunReturnsIntegerExitCode()
    {
        $command = new \TestCommand();
        $exitCode = $command->run(new StringInput(''), new NullOutput());
        $this->assertSame(0, $exitCode, '->run() returns integer exit code (treats null as 0)');

        $command = $this->getMock('TestCommand', array('execute'));
        $command->expects($this->once())
             ->method('execute')
             ->will($this->returnValue('2.3'));
        $exitCode = $command->run(new StringInput(''), new NullOutput());
        $this->assertSame(2, $exitCode, '->run() returns integer exit code (casts numeric to int)');
    }

    public function testRunReturnsAlwaysInteger()
    {
        $command = new \TestCommand();

        $this->assertSame(0, $command->run(new StringInput(''), new NullOutput()));
    }

    public function testSetCode()
    {
        $command = new \TestCommand();
        $ret = $command->setCode(function (InputInterface $input, OutputInterface $output) {
            $output->writeln('from the code...');
        });
        $this->assertEquals($command, $ret, '->setCode() implements a fluent interface');
        $tester = new CommandTester($command);
        $tester->execute(array());
        $this->assertEquals('interact called'.PHP_EOL.'from the code...'.PHP_EOL, $tester->getDisplay());
    }

    public function testSetCodeWithNonClosureCallable()
    {
        $command = new \TestCommand();
        $ret = $command->setCode(array($this, 'callableMethodCommand'));
        $this->assertEquals($command, $ret, '->setCode() implements a fluent interface');
        $tester = new CommandTester($command);
        $tester->execute(array());
        $this->assertEquals('interact called'.PHP_EOL.'from the code...'.PHP_EOL, $tester->getDisplay());
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage Invalid callable provided to Command::setCode.
     */
    public function testSetCodeWithNonCallable()
    {
        $command = new \TestCommand();
        $command->setCode(array($this, 'nonExistentMethod'));
    }

    public function callableMethodCommand(InputInterface $input, OutputInterface $output)
    {
        $output->writeln('from the code...');
    }

    public function testAsText()
    {
        $command = new \TestCommand();
        $command->setApplication(new Application());
        $tester = new CommandTester($command);
        $tester->execute(array('command' => $command->getName()));
        $this->assertStringEqualsFile(self::$fixturesPath.'/command_astext.txt', $command->asText(), '->asText() returns a text representation of the command');
    }

    public function testAsXml()
    {
        $command = new \TestCommand();
        $command->setApplication(new Application());
        $tester = new CommandTester($command);
        $tester->execute(array('command' => $command->getName()));
        $this->assertXmlStringEqualsXmlFile(self::$fixturesPath.'/command_asxml.txt', $command->asXml(), '->asXml() returns an XML representation of the command');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Command;

use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Component\Console\Command\HelpCommand;
use Symfony\Component\Console\Command\ListCommand;
use Symfony\Component\Console\Application;

class HelpCommandTest extends \PHPUnit_Framework_TestCase
{
    public function testExecuteForCommandAlias()
    {
        $command = new HelpCommand();
        $command->setApplication(new Application());
        $commandTester = new CommandTester($command);
        $commandTester->execute(array('command_name' => 'li'));
        $this->assertRegExp('/list \[--xml\] \[--raw\] \[--format="\.\.\."\] \[namespace\]/', $commandTester->getDisplay(), '->execute() returns a text help for the given command alias');
    }

    public function testExecuteForCommand()
    {
        $command = new HelpCommand();
        $commandTester = new CommandTester($command);
        $command->setCommand(new ListCommand());
        $commandTester->execute(array());
        $this->assertRegExp('/list \[--xml\] \[--raw\] \[--format="\.\.\."\] \[namespace\]/', $commandTester->getDisplay(), '->execute() returns a text help for the given command');
    }

    public function testExecuteForCommandWithXmlOption()
    {
        $command = new HelpCommand();
        $commandTester = new CommandTester($command);
        $command->setCommand(new ListCommand());
        $commandTester->execute(array('--format' => 'xml'));
        $this->assertRegExp('/<command/', $commandTester->getDisplay(), '->execute() returns an XML help text if --xml is passed');
    }

    public function testExecuteForApplicationCommand()
    {
        $application = new Application();
        $commandTester = new CommandTester($application->get('help'));
        $commandTester->execute(array('command_name' => 'list'));
        $this->assertRegExp('/list \[--xml\] \[--raw\] \[--format="\.\.\."\] \[namespace\]/', $commandTester->getDisplay(), '->execute() returns a text help for the given command');
    }

    public function testExecuteForApplicationCommandWithXmlOption()
    {
        $application = new Application();
        $commandTester = new CommandTester($application->get('help'));
        $commandTester->execute(array('command_name' => 'list', '--format' => 'xml'));
        $this->assertRegExp('/list \[--xml\] \[--raw\] \[--format="\.\.\."\] \[namespace\]/', $commandTester->getDisplay(), '->execute() returns a text help for the given command');
        $this->assertRegExp('/<command/', $commandTester->getDisplay(), '->execute() returns an XML help text if --format=xml is passed');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Command;

use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Component\Console\Application;

class ListCommandTest extends \PHPUnit_Framework_TestCase
{
    public function testExecuteListsCommands()
    {
        $application = new Application();
        $commandTester = new CommandTester($command = $application->get('list'));
        $commandTester->execute(array('command' => $command->getName()), array('decorated' => false));

        $this->assertRegExp('/help   Displays help for a command/', $commandTester->getDisplay(), '->execute() returns a list of available commands');
    }

    public function testExecuteListsCommandsWithXmlOption()
    {
        $application = new Application();
        $commandTester = new CommandTester($command = $application->get('list'));
        $commandTester->execute(array('command' => $command->getName(), '--format' => 'xml'));
        $this->assertRegExp('/<command id="list" name="list">/', $commandTester->getDisplay(), '->execute() returns a list of available commands in XML if --xml is passed');
    }

    public function testExecuteListsCommandsWithRawOption()
    {
        $application = new Application();
        $commandTester = new CommandTester($command = $application->get('list'));
        $commandTester->execute(array('command' => $command->getName(), '--raw' => true));
        $output = <<<EOF
help   Displays help for a command
list   Lists commands

EOF;

        $this->assertEquals($output, $commandTester->getDisplay(true));
    }

    public function testExecuteListsCommandsWithNamespaceArgument()
    {

        require_once(realpath(__DIR__.'/../Fixtures/FooCommand.php'));
        $application = new Application();
        $application->add(new \FooCommand());
        $commandTester = new CommandTester($command = $application->get('list'));
        $commandTester->execute(array('command' => $command->getName(), 'namespace' => 'foo', '--raw' => true));
        $output = <<<EOF
foo:bar   The foo:bar command

EOF;

        $this->assertEquals($output, $commandTester->getDisplay(true));
    }
}
Console Tool
{"name":"--option_name","shortcut":"-o","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"option description","default":null}
<?xml version="1.0" encoding="UTF-8"?>
<argument name="argument_name" is_required="0" is_array="0">
  <description>argument description</description>
  <defaults>
    <default>default_value</default>
  </defaults>
</argument>
Usage:
 help [--xml] [--format="..."] [--raw] [command_name]

Arguments:
 command               The command to execute
 command_name          The command name (default: "help")

Options:
 --xml                 To output help as XML
 --format              To output help in other formats (default: "txt")
 --raw                 To output raw command help
 --help (-h)           Display this help message.
 --quiet (-q)          Do not output any message.
 --verbose (-v|vv|vvv) Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
 --version (-V)        Display this application version.
 --ansi                Force ANSI output.
 --no-ansi             Disable ANSI output.
 --no-interaction (-n) Do not ask any interactive question.

Help:
 The help command displays help for a given command:
 
   php app/console help list
 
 You can also output the help in other formats by using the --format option:
 
   php app/console help --format=xml list
 
 To display the list of available commands, please use the list command.
<?php

use Symfony\Component\Console\Command\Command;

class Foo5Command extends Command
{
    public function __construct()
    {
    }
}
<?php

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class FooCommand extends Command
{
    public $input;
    public $output;

    protected function configure()
    {
        $this
            ->setName('foo:bar')
            ->setDescription('The foo:bar command')
            ->setAliases(array('afoobar'))
        ;
    }

    protected function interact(InputInterface $input, OutputInterface $output)
    {
        $output->writeln('interact called');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $this->input = $input;
        $this->output = $output;

        $output->writeln('called');
    }
}
<comment>Arguments:</comment>
 <info>argument_name     </info> 

<comment>Options:</comment>
 <info>--option_name</info> (-o)
{"commands":[{"name":"help","usage":"help [--xml] [--format=\"...\"] [--raw] [command_name]","description":"Displays help for a command","help":"The <info>help<\/info> command displays help for a given command:\n\n  <info>php app\/console help list<\/info>\n\nYou can also output the help in other formats by using the <comment>--format<\/comment> option:\n\n  <info>php app\/console help --format=xml list<\/info>\n\nTo display the list of available commands, please use the <info>list<\/info> command.","aliases":[],"definition":{"arguments":{"command_name":{"name":"command_name","is_required":false,"is_array":false,"description":"The command name","default":"help"}},"options":{"xml":{"name":"--xml","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output help as XML","default":false},"format":{"name":"--format","shortcut":"","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"To output help in other formats","default":"txt"},"raw":{"name":"--raw","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output raw command help","default":false},"help":{"name":"--help","shortcut":"-h","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this help message.","default":false},"quiet":{"name":"--quiet","shortcut":"-q","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not output any message.","default":false},"verbose":{"name":"--verbose","shortcut":"-v|-vv|-vvv","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug","default":false},"version":{"name":"--version","shortcut":"-V","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this application version.","default":false},"ansi":{"name":"--ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Force ANSI output.","default":false},"no-ansi":{"name":"--no-ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Disable ANSI output.","default":false},"no-interaction":{"name":"--no-interaction","shortcut":"-n","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not ask any interactive question.","default":false}}}},{"name":"list","usage":"list [--xml] [--raw] [--format=\"...\"] [namespace]","description":"Lists commands","help":"The <info>list<\/info> command lists all commands:\n\n  <info>php app\/console list<\/info>\n\nYou can also display the commands for a specific namespace:\n\n  <info>php app\/console list test<\/info>\n\nYou can also output the information in other formats by using the <comment>--format<\/comment> option:\n\n  <info>php app\/console list --format=xml<\/info>\n\nIt's also possible to get raw list of commands (useful for embedding command runner):\n\n  <info>php app\/console list --raw<\/info>","aliases":[],"definition":{"arguments":{"namespace":{"name":"namespace","is_required":false,"is_array":false,"description":"The namespace name","default":null}},"options":{"xml":{"name":"--xml","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output list as XML","default":false},"raw":{"name":"--raw","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output raw command list","default":false},"format":{"name":"--format","shortcut":"","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"To output list in other formats","default":"txt"}}}}],"namespaces":[{"id":"_global","commands":["help","list"]}]}
<info>Console Tool</info>

<comment>Usage:</comment>
  [options] command [arguments]

<comment>Options:</comment>
  <info>--help</info>           <info>-h</info> Display this help message.
  <info>--quiet</info>          <info>-q</info> Do not output any message.
  <info>--verbose</info>        <info>-v|vv|vvv</info> Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
  <info>--version</info>        <info>-V</info> Display this application version.
  <info>--ansi</info>              Force ANSI output.
  <info>--no-ansi</info>           Disable ANSI output.
  <info>--no-interaction</info> <info>-n</info> Do not ask any interactive question.

<comment>Available commands:</comment>
  <info>afoobar  </info> The foo:bar command
  <info>help     </info> Displays help for a command
  <info>list     </info> Lists commands
<comment>foo</comment>
  <info>foo:bar  </info> The foo:bar command
<?php

use Symfony\Component\Console\Command\Command;

class BarBucCommand extends Command
{
    protected function configure()
    {
        $this->setName('bar:buc');
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<definition>
  <arguments>
    <argument name="argument_name" is_required="1" is_array="0">
      <description></description>
      <defaults/>
    </argument>
  </arguments>
  <options/>
</definition>
{"name":"argument_name","is_required":false,"is_array":false,"description":"argument description","default":"default_value"}
<?xml version="1.0" encoding="UTF-8"?>
<definition>
  <arguments/>
  <options>
    <option name="--option_name" shortcut="-o" accept_value="0" is_value_required="0" is_multiple="0">
      <description></description>
    </option>
  </options>
</definition>
 <info>--option_name</info> (-o)
<comment>Usage:</comment>
 namespace:name

<comment>Aliases:</comment> <info>name</info>
<comment>Arguments:</comment>
 <info>command              </info> The command to execute

<comment>Options:</comment>
 <info>--help</info> (-h)           Display this help message.
 <info>--quiet</info> (-q)          Do not output any message.
 <info>--verbose</info> (-v|vv|vvv) Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
 <info>--version</info> (-V)        Display this application version.
 <info>--ansi</info>                Force ANSI output.
 <info>--no-ansi</info>             Disable ANSI output.
 <info>--no-interaction</info> (-n) Do not ask any interactive question.

<comment>Help:</comment>
 help
<?xml version="1.0" encoding="UTF-8"?>
<option name="--option_name" shortcut="-o" accept_value="0" is_value_required="0" is_multiple="0">
  <description></description>
</option>
<?xml version="1.0" encoding="UTF-8"?>
<argument name="argument_name" is_required="0" is_array="1">
  <description>argument description</description>
  <defaults/>
</argument>


[37;41m                           [0m
[37;41m  [Exception]              [0m
[37;41m  Third exception [0m[34;41mcomment[0m[37;41m  [0m
[37;41m                           [0m




[37;41m                            [0m
[37;41m  [Exception]               [0m
[37;41m  Second exception [0m[33mcomment[0m[37;41m  [0m
[37;41m                            [0m




[37;41m                                       [0m
[37;41m  [Exception]                          [0m
[37;41m  First exception [0m[37;41m<p>this is html[0m[37;41m</p>  [0m
[37;41m                                       [0m


[32mfoo3:bar[0m


<comment>Options:</comment>
 <info>--option_name</info> (-o)
Console Tool

Usage:
  [options] command [arguments]

Options:
  --help           -h Display this help message.
  --quiet          -q Do not output any message.
  --verbose        -v|vv|vvv Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
  --version        -V Display this application version.
  --ansi              Force ANSI output.
  --no-ansi           Disable ANSI output.
  --no-interaction -n Do not ask any interactive question.

Available commands:
  help   Displays help for a command
  list   Lists commands
<?xml version="1.0" encoding="UTF-8"?>
<definition>
  <arguments>
    <argument name="foo" is_required="0" is_array="0">
      <description>The foo argument</description>
      <defaults/>
    </argument>
    <argument name="baz" is_required="0" is_array="0">
      <description>The baz argument</description>
      <defaults>
        <default>true</default>
      </defaults>
    </argument>
    <argument name="bar" is_required="0" is_array="1">
      <description>The bar argument</description>
      <defaults>
        <default>bar</default>
      </defaults>
    </argument>
  </arguments>
  <options>
    <option name="--foo" shortcut="-f" accept_value="1" is_value_required="1" is_multiple="0">
      <description>The foo option</description>
      <defaults/>
    </option>
    <option name="--baz" shortcut="" accept_value="1" is_value_required="0" is_multiple="0">
      <description>The baz option</description>
      <defaults>
        <default>false</default>
      </defaults>
    </option>
    <option name="--bar" shortcut="-b" accept_value="1" is_value_required="0" is_multiple="0">
      <description>The bar option</description>
      <defaults>
        <default>bar</default>
      </defaults>
    </option>
  </options>
</definition>
<?xml version="1.0" encoding="UTF-8"?>
<option name="--option_name" shortcut="-o" accept_value="1" is_value_required="0" is_multiple="0">
  <description>option description</description>
  <defaults>
    <default>default_value</default>
  </defaults>
</option>
<comment>Arguments:</comment>
 <info>argument_name </info>
{"arguments":{"argument_name":{"name":"argument_name","is_required":true,"is_array":false,"description":"","default":null}},"options":{"option_name":{"name":"--option_name","shortcut":"-o","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"","default":false}}}
<?php

use Symfony\Component\Console\Command\Command;

class Foo4Command extends Command
{
    protected function configure()
    {
        $this->setName('foo3:bar:toh');
    }
}
{"name":"argument_name","is_required":true,"is_array":false,"description":"","default":null}
<?xml version="1.0" encoding="UTF-8"?>
<option name="--option_name" shortcut="-o" accept_value="1" is_value_required="0" is_multiple="1">
  <description>option description</description>
  <defaults/>
</option>
<?php

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class FoobarCommand extends Command
{
    public $input;
    public $output;

    protected function configure()
    {
        $this
            ->setName('foobar:foo')
            ->setDescription('The foobar:foo command')
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $this->input = $input;
        $this->output = $output;
    }
}
<?php

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class Foo3Command extends Command
{
    protected function configure()
    {
        $this
            ->setName('foo3:bar')
            ->setDescription('The foo3:bar command')
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        try {
            try {
                throw new \Exception("First exception <p>this is html</p>");
            } catch (\Exception $e) {
                throw new \Exception("Second exception <comment>comment</comment>", 0, $e);
            }
        } catch (\Exception $e) {
            throw new \Exception("Third exception <fg=blue;bg=red>comment</>", 0, $e);
        }
    }
}
<?php

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class Foo2Command extends Command
{
    protected function configure()
    {
        $this
            ->setName('foo1:bar')
            ->setDescription('The foo1:bar command')
            ->setAliases(array('afoobar2'))
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
    }
}
 <info>argument_name</info>
<?xml version="1.0" encoding="UTF-8"?>
<argument name="argument_name" is_required="1" is_array="0">
  <description></description>
  <defaults/>
</argument>
<?xml version="1.0" encoding="UTF-8"?>
<symfony>
  <commands>
    <command id="help" name="help">
  <usage>help [--xml] [--format="..."] [--raw] [command_name]</usage>
  <description>Displays help for a command</description>
  <help>The &lt;info&gt;help&lt;/info&gt; command displays help for a given command:
 
   &lt;info&gt;php app/console help list&lt;/info&gt;
 
 You can also output the help in other formats by using the &lt;comment&gt;--format&lt;/comment&gt; option:
 
   &lt;info&gt;php app/console help --format=xml list&lt;/info&gt;
 
 To display the list of available commands, please use the &lt;info&gt;list&lt;/info&gt; command.</help>
  <aliases />
  <arguments>
    <argument name="command_name" is_required="0" is_array="0">
      <description>The command name</description>
      <defaults>
        <default>help</default>
      </defaults>
    </argument>
  </arguments>
  <options>
    <option name="--xml" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
      <description>To output help as XML</description>
    </option>
    <option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0">
      <description>To output help in other formats</description>
      <defaults>
        <default>txt</default>
      </defaults>
    </option>
    <option name="--raw" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
      <description>To output raw command help</description>
    </option>
    <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Display this help message.</description>
    </option>
    <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Do not output any message.</description>
    </option>
    <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description>
    </option>
    <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Display this application version.</description>
    </option>
    <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Force ANSI output.</description>
    </option>
    <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Disable ANSI output.</description>
    </option>
    <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Do not ask any interactive question.</description>
    </option>
  </options>
</command>
    <command id="list" name="list">
  <usage>list [--xml] [--raw] [--format="..."] [namespace]</usage>
  <description>Lists commands</description>
  <help>The &lt;info&gt;list&lt;/info&gt; command lists all commands:
 
   &lt;info&gt;php app/console list&lt;/info&gt;
 
 You can also display the commands for a specific namespace:
 
   &lt;info&gt;php app/console list test&lt;/info&gt;
 
 You can also output the information in other formats by using the &lt;comment&gt;--format&lt;/comment&gt; option:
 
   &lt;info&gt;php app/console list --format=xml&lt;/info&gt;
 
 It's also possible to get raw list of commands (useful for embedding command runner):
 
   &lt;info&gt;php app/console list --raw&lt;/info&gt;</help>
  <aliases/>
  <arguments>
    <argument name="namespace" is_required="0" is_array="0">
      <description>The namespace name</description>
      <defaults/>
    </argument>
  </arguments>
  <options>
    <option name="--xml" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
      <description>To output list as XML</description>
    </option>
    <option name="--raw" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
      <description>To output raw command list</description>
    </option>
    <option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0">
      <description>To output list in other formats</description>
      <defaults>
        <default>txt</default>
      </defaults>
    </option>
  </options>
</command>
    <command id="foo:bar" name="foo:bar">
  <usage>foo:bar</usage>
  <description>The foo:bar command</description>
  <help/>
  <aliases>
    <alias>afoobar</alias>
  </aliases>
  <arguments/>
    <options>
      <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Display this help message.</description>
      </option>
      <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Do not output any message.</description>
      </option>
      <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description>
      </option>
      <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Display this application version.</description>
      </option>
      <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Force ANSI output.</description>
      </option>
      <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Disable ANSI output.</description>
      </option>
      <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Do not ask any interactive question.</description>
      </option>
    </options>
</command>
  </commands>
  <namespaces>
    <namespace id="_global">
      <command>afoobar</command>
      <command>help</command>
      <command>list</command>
    </namespace>
    <namespace id="foo">
      <command>foo:bar</command>
    </namespace>
  </namespaces>
</symfony>
{"name":"--option_name","shortcut":"-o","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"","default":false}
<info>Console Tool</info>

<comment>Usage:</comment>
  [options] command [arguments]

<comment>Options:</comment>
  <info>--help</info>           <info>-h</info> Display this help message.
  <info>--quiet</info>          <info>-q</info> Do not output any message.
  <info>--verbose</info>        <info>-v|vv|vvv</info> Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
  <info>--version</info>        <info>-V</info> Display this application version.
  <info>--ansi</info>              Force ANSI output.
  <info>--no-ansi</info>           Disable ANSI output.
  <info>--no-interaction</info> <info>-n</info> Do not ask any interactive question.

<comment>Available commands:</comment>
  <info>help  </info> Displays help for a command
  <info>list  </info> Lists commands
<?xml version="1.0" encoding="UTF-8"?>
<option name="--option_name" shortcut="-o" accept_value="1" is_value_required="1" is_multiple="0">
  <description>option description</description>
  <defaults/>
</option>
<?xml version="1.0" encoding="UTF-8"?>
<command id="namespace:name" name="namespace:name">
  <usage>namespace:name</usage>
  <description>description</description>
  <help>help</help>
  <aliases>
    <alias>name</alias>
  </aliases>
  <arguments>
    <argument name="command" is_required="1" is_array="0">
      <description>The command to execute</description>
      <defaults/>
    </argument>
  </arguments>
  <options>
    <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Display this help message.</description>
    </option>
    <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Do not output any message.</description>
    </option>
    <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description>
    </option>
    <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Display this application version.</description>
    </option>
    <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Force ANSI output.</description>
    </option>
    <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Disable ANSI output.</description>
    </option>
    <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0">
      <description>Do not ask any interactive question.</description>
    </option>
  </options>
</command>
<info>Console Tool</info>

<comment>Usage:</comment>
  [options] command [arguments]

<comment>Options:</comment>
  <info>--help</info>           <info>-h</info> Display this help message.
  <info>--quiet</info>          <info>-q</info> Do not output any message.
  <info>--verbose</info>        <info>-v|vv|vvv</info> Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
  <info>--version</info>        <info>-V</info> Display this application version.
  <info>--ansi</info>              Force ANSI output.
  <info>--no-ansi</info>           Disable ANSI output.
  <info>--no-interaction</info> <info>-n</info> Do not ask any interactive question.

<comment>Available commands for the "foo" namespace:</comment>
  <info>foo:bar  </info> The foo:bar command
<?xml version="1.0" encoding="UTF-8"?>
<symfony>
  <commands namespace="foo">
    <command id="foo:bar" name="foo:bar">
  <usage>foo:bar</usage>
  <description>The foo:bar command</description>
  <help/>
  <aliases>
    <alias>afoobar</alias>
  </aliases>
  <arguments/>
    <options>
      <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Display this help message.</description>
      </option>
      <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Do not output any message.</description>
      </option>
      <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description>
      </option>
      <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Display this application version.</description>
      </option>
      <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Force ANSI output.</description>
      </option>
      <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Disable ANSI output.</description>
      </option>
      <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0">
        <description>Do not ask any interactive question.</description>
      </option>
    </options>
</command>
  </commands>
</symfony>
{"name":"--option_name","shortcut":"-o","accept_value":true,"is_value_required":false,"is_multiple":false,"description":"option description","default":"default_value"}
{"name":"descriptor:command1","usage":"descriptor:command1","description":"command 1 description","help":"command 1 help","aliases":["alias1","alias2"],"definition":{"arguments":[],"options":[]}}
{"arguments":{"argument_name":{"name":"argument_name","is_required":true,"is_array":false,"description":"","default":null}},"options":[]}


                                 
  [InvalidArgumentException]     
  Command "foo" is not defined.  
                                 


{"name":"--option_name","shortcut":"-o","accept_value":true,"is_value_required":false,"is_multiple":true,"description":"option description","default":[]}
 <info>--option_name</info> (-o) option description<comment> (multiple values allowed)</comment>


                           
  [Exception]              
  Third exception comment  
                           




                            
  [Exception]               
  Second exception comment  
                            




                                       
  [Exception]                          
  First exception <p>this is html</p>  
                                       


foo3:bar


Usage:
 list [--xml] [--raw] [--format="..."] [namespace]

Arguments:
 namespace  The namespace name

Options:
 --xml      To output list as XML
 --raw      To output raw command list
 --format   To output list in other formats (default: "txt")

Help:
 The list command lists all commands:
 
   php app/console list
 
 You can also display the commands for a specific namespace:
 
   php app/console list test
 
 You can also output the information in other formats by using the --format option:
 
   php app/console list --format=xml
 
 It's also possible to get raw list of commands (useful for embedding command runner):
 
   php app/console list --raw
{"name":"descriptor:command2","usage":"descriptor:command2 [-o|--option_name] argument_name","description":"command 2 description","help":"command 2 help","aliases":[],"definition":{"arguments":{"argument_name":{"name":"argument_name","is_required":true,"is_array":false,"description":"","default":null}},"options":{"option_name":{"name":"--option_name","shortcut":"-o","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"","default":false}}}}
<comment>Usage:</comment>
 descriptor:command1

<comment>Aliases:</comment> <info>alias1, alias2</info>

<comment>Help:</comment>
 command 1 help
{"arguments":[],"options":{"option_name":{"name":"--option_name","shortcut":"-o","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"","default":false}}}
<?php

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class TestCommand extends Command
{
    protected function configure()
    {
        $this
            ->setName('namespace:name')
            ->setAliases(array('name'))
            ->setDescription('description')
            ->setHelp('help')
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $output->writeln('execute called');
    }

    protected function interact(InputInterface $input, OutputInterface $output)
    {
        $output->writeln('interact called');
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<symfony name="My Symfony application" version="v1.0">
  <commands>
    <command id="help" name="help">
      <usage>help [--xml] [--format="..."] [--raw] [command_name]</usage>
      <description>Displays help for a command</description>
      <help>The &lt;info&gt;help&lt;/info&gt; command displays help for a given command:
 
   &lt;info&gt;php app/console help list&lt;/info&gt;
 
 You can also output the help in other formats by using the &lt;comment&gt;--format&lt;/comment&gt; option:
 
   &lt;info&gt;php app/console help --format=xml list&lt;/info&gt;
 
 To display the list of available commands, please use the &lt;info&gt;list&lt;/info&gt; command.</help>
      <aliases/>
      <arguments>
        <argument name="command_name" is_required="0" is_array="0">
          <description>The command name</description>
          <defaults>
            <default>help</default>
          </defaults>
        </argument>
      </arguments>
      <options>
        <option name="--xml" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>To output help as XML</description>
        </option>
        <option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0">
          <description>To output help in other formats</description>
          <defaults>
            <default>txt</default>
          </defaults>
        </option>
        <option name="--raw" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>To output raw command help</description>
        </option>
        <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Display this help message.</description>
        </option>
        <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Do not output any message.</description>
        </option>
        <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description>
        </option>
        <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Display this application version.</description>
        </option>
        <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Force ANSI output.</description>
        </option>
        <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Disable ANSI output.</description>
        </option>
        <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Do not ask any interactive question.</description>
        </option>
      </options>
    </command>
    <command id="list" name="list">
      <usage>list [--xml] [--raw] [--format="..."] [namespace]</usage>
      <description>Lists commands</description>
      <help>The &lt;info&gt;list&lt;/info&gt; command lists all commands:
 
   &lt;info&gt;php app/console list&lt;/info&gt;
 
 You can also display the commands for a specific namespace:
 
   &lt;info&gt;php app/console list test&lt;/info&gt;
 
 You can also output the information in other formats by using the &lt;comment&gt;--format&lt;/comment&gt; option:
 
   &lt;info&gt;php app/console list --format=xml&lt;/info&gt;
 
 It's also possible to get raw list of commands (useful for embedding command runner):
 
   &lt;info&gt;php app/console list --raw&lt;/info&gt;</help>
      <aliases/>
      <arguments>
        <argument name="namespace" is_required="0" is_array="0">
          <description>The namespace name</description>
          <defaults/>
        </argument>
      </arguments>
      <options>
        <option name="--xml" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>To output list as XML</description>
        </option>
        <option name="--raw" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>To output raw command list</description>
        </option>
        <option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0">
          <description>To output list in other formats</description>
          <defaults>
            <default>txt</default>
          </defaults>
        </option>
      </options>
    </command>
    <command id="descriptor:command1" name="descriptor:command1">
      <usage>descriptor:command1</usage>
      <description>command 1 description</description>
      <help>command 1 help</help>
      <aliases>
        <alias>alias1</alias>
        <alias>alias2</alias>
      </aliases>
      <arguments/>
      <options>
        <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Display this help message.</description>
        </option>
        <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Do not output any message.</description>
        </option>
        <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description>
        </option>
        <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Display this application version.</description>
        </option>
        <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Force ANSI output.</description>
        </option>
        <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Disable ANSI output.</description>
        </option>
        <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Do not ask any interactive question.</description>
        </option>
      </options>
    </command>
    <command id="descriptor:command2" name="descriptor:command2">
      <usage>descriptor:command2 [-o|--option_name] argument_name</usage>
      <description>command 2 description</description>
      <help>command 2 help</help>
      <aliases/>
      <arguments>
        <argument name="argument_name" is_required="1" is_array="0">
          <description></description>
          <defaults/>
        </argument>
      </arguments>
      <options>
        <option name="--option_name" shortcut="-o" accept_value="0" is_value_required="0" is_multiple="0">
          <description></description>
        </option>
        <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Display this help message.</description>
        </option>
        <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Do not output any message.</description>
        </option>
        <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description>
        </option>
        <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Display this application version.</description>
        </option>
        <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Force ANSI output.</description>
        </option>
        <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Disable ANSI output.</description>
        </option>
        <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Do not ask any interactive question.</description>
        </option>
      </options>
    </command>
  </commands>
  <namespaces>
    <namespace id="_global">
      <command>alias1</command>
      <command>alias2</command>
      <command>help</command>
      <command>list</command>
    </namespace>
    <namespace id="descriptor">
      <command>descriptor:command1</command>
      <command>descriptor:command2</command>
    </namespace>
  </namespaces>
</symfony>
<?xml version="1.0" encoding="UTF-8"?>
<definition>
  <arguments/>
  <options/>
</definition>
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Fixtures;

use Symfony\Component\Console\Command\Command;

class DescriptorCommand1 extends Command
{
    protected function configure()
    {
        $this
            ->setName('descriptor:command1')
            ->setAliases(array('alias1', 'alias2'))
            ->setDescription('command 1 description')
            ->setHelp('command 1 help')
        ;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Fixtures;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;

class DescriptorCommand2 extends Command
{
    protected function configure()
    {
        $this
            ->setName('descriptor:command2')
            ->setDescription('command 2 description')
            ->setHelp('command 2 help')
            ->addArgument('argument_name', InputArgument::REQUIRED)
            ->addOption('option_name', 'o', InputOption::VALUE_NONE)
        ;
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<command id="descriptor:command2" name="descriptor:command2">
  <usage>descriptor:command2 [-o|--option_name] argument_name</usage>
  <description>command 2 description</description>
  <help>command 2 help</help>
  <aliases/>
  <arguments>
    <argument name="argument_name" is_required="1" is_array="0">
      <description></description>
      <defaults/>
    </argument>
  </arguments>
  <options>
    <option name="--option_name" shortcut="-o" accept_value="0" is_value_required="0" is_multiple="0">
      <description></description>
    </option>
  </options>
</command>
<comment>Usage:</comment>
 descriptor:command2 [-o|--option_name] argument_name

<comment>Arguments:</comment>
 <info>argument_name     </info> 

<comment>Options:</comment>
 <info>--option_name</info> (-o) 

<comment>Help:</comment>
 command 2 help
<?php

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class Foo1Command extends Command
{
    public $input;
    public $output;

    protected function configure()
    {
        $this
            ->setName('foo:bar1')
            ->setDescription('The foo:bar1 command')
            ->setAliases(array('afoobar1'))
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $this->input = $input;
        $this->output = $output;
    }
}


                                      
  [InvalidArgumentException]          
  The "--foo" option does not exist.  
                                      


list [--xml] [--raw] [--format="..."] [namespace]


<info>My Symfony application</info> version <comment>v1.0</comment>

<comment>Usage:</comment>
  [options] command [arguments]

<comment>Options:</comment>
  <info>--help</info>           <info>-h</info> Display this help message.
  <info>--quiet</info>          <info>-q</info> Do not output any message.
  <info>--verbose</info>        <info>-v|vv|vvv</info> Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
  <info>--version</info>        <info>-V</info> Display this application version.
  <info>--ansi</info>              Force ANSI output.
  <info>--no-ansi</info>           Disable ANSI output.
  <info>--no-interaction</info> <info>-n</info> Do not ask any interactive question.

<comment>Available commands:</comment>
  <info>alias1               </info> command 1 description
  <info>alias2               </info> command 1 description
  <info>help                 </info> Displays help for a command
  <info>list                 </info> Lists commands
<comment>descriptor</comment>
  <info>descriptor:command1  </info> command 1 description
  <info>descriptor:command2  </info> command 2 description
 <info>argument_name</info> argument description
<?xml version="1.0" encoding="UTF-8"?>
<definition>
  <arguments>
    <argument name="argument_name" is_required="1" is_array="0">
      <description></description>
      <defaults/>
    </argument>
  </arguments>
  <options>
    <option name="--option_name" shortcut="-o" accept_value="0" is_value_required="0" is_multiple="0">
      <description></description>
    </option>
  </options>
</definition>


                               
  [InvalidArgumentException]   
  Command "foo" is not define  
  d.                           
                               


{"commands":[{"name":"help","usage":"help [--xml] [--format=\"...\"] [--raw] [command_name]","description":"Displays help for a command","help":"The <info>help<\/info> command displays help for a given command:\n\n  <info>php app\/console help list<\/info>\n\nYou can also output the help in other formats by using the <comment>--format<\/comment> option:\n\n  <info>php app\/console help --format=xml list<\/info>\n\nTo display the list of available commands, please use the <info>list<\/info> command.","aliases":[],"definition":{"arguments":{"command_name":{"name":"command_name","is_required":false,"is_array":false,"description":"The command name","default":"help"}},"options":{"xml":{"name":"--xml","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output help as XML","default":false},"format":{"name":"--format","shortcut":"","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"To output help in other formats","default":"txt"},"raw":{"name":"--raw","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output raw command help","default":false},"help":{"name":"--help","shortcut":"-h","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this help message.","default":false},"quiet":{"name":"--quiet","shortcut":"-q","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not output any message.","default":false},"verbose":{"name":"--verbose","shortcut":"-v|-vv|-vvv","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug","default":false},"version":{"name":"--version","shortcut":"-V","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this application version.","default":false},"ansi":{"name":"--ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Force ANSI output.","default":false},"no-ansi":{"name":"--no-ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Disable ANSI output.","default":false},"no-interaction":{"name":"--no-interaction","shortcut":"-n","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not ask any interactive question.","default":false}}}},{"name":"list","usage":"list [--xml] [--raw] [--format=\"...\"] [namespace]","description":"Lists commands","help":"The <info>list<\/info> command lists all commands:\n\n  <info>php app\/console list<\/info>\n\nYou can also display the commands for a specific namespace:\n\n  <info>php app\/console list test<\/info>\n\nYou can also output the information in other formats by using the <comment>--format<\/comment> option:\n\n  <info>php app\/console list --format=xml<\/info>\n\nIt's also possible to get raw list of commands (useful for embedding command runner):\n\n  <info>php app\/console list --raw<\/info>","aliases":[],"definition":{"arguments":{"namespace":{"name":"namespace","is_required":false,"is_array":false,"description":"The namespace name","default":null}},"options":{"xml":{"name":"--xml","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output list as XML","default":false},"raw":{"name":"--raw","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"To output raw command list","default":false},"format":{"name":"--format","shortcut":"","accept_value":true,"is_value_required":true,"is_multiple":false,"description":"To output list in other formats","default":"txt"}}}},{"name":"descriptor:command1","usage":"descriptor:command1","description":"command 1 description","help":"command 1 help","aliases":["alias1","alias2"],"definition":{"arguments":[],"options":{"help":{"name":"--help","shortcut":"-h","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this help message.","default":false},"quiet":{"name":"--quiet","shortcut":"-q","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not output any message.","default":false},"verbose":{"name":"--verbose","shortcut":"-v|-vv|-vvv","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug","default":false},"version":{"name":"--version","shortcut":"-V","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this application version.","default":false},"ansi":{"name":"--ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Force ANSI output.","default":false},"no-ansi":{"name":"--no-ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Disable ANSI output.","default":false},"no-interaction":{"name":"--no-interaction","shortcut":"-n","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not ask any interactive question.","default":false}}}},{"name":"descriptor:command2","usage":"descriptor:command2 [-o|--option_name] argument_name","description":"command 2 description","help":"command 2 help","aliases":[],"definition":{"arguments":{"argument_name":{"name":"argument_name","is_required":true,"is_array":false,"description":"","default":null}},"options":{"option_name":{"name":"--option_name","shortcut":"-o","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"","default":false},"help":{"name":"--help","shortcut":"-h","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this help message.","default":false},"quiet":{"name":"--quiet","shortcut":"-q","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not output any message.","default":false},"verbose":{"name":"--verbose","shortcut":"-v|-vv|-vvv","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug","default":false},"version":{"name":"--version","shortcut":"-V","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Display this application version.","default":false},"ansi":{"name":"--ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Force ANSI output.","default":false},"no-ansi":{"name":"--no-ansi","shortcut":"","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Disable ANSI output.","default":false},"no-interaction":{"name":"--no-interaction","shortcut":"-n","accept_value":false,"is_value_required":false,"is_multiple":false,"description":"Do not ask any interactive question.","default":false}}}}],"namespaces":[{"id":"_global","commands":["alias1","alias2","help","list"]},{"id":"descriptor","commands":["descriptor:command1","descriptor:command2"]}]}
<?xml version="1.0" encoding="UTF-8"?>
<command id="descriptor:command1" name="descriptor:command1">
  <usage>descriptor:command1</usage>
  <description>command 1 description</description>
  <help>command 1 help</help>
  <aliases>
    <alias>alias1</alias>
    <alias>alias2</alias>
  </aliases>
  <arguments/>
  <options/>
</command>
<comment>Arguments:</comment>
 <info>foo       </info> The foo argument
 <info>baz       </info> The baz argument<comment> (default: true)</comment>
 <info>bar       </info> The bar argument<comment> (default: ["http://foo.com/"])</comment>

<comment>Options:</comment>
 <info>--foo</info> (-f) The foo option
 <info>--baz</info>      The baz option<comment> (default: false)</comment>
 <info>--bar</info> (-b) The bar option<comment> (default: "bar")</comment>
 <info>--qux</info>      The qux option<comment> (default: ["http://foo.com/","bar"])</comment><comment> (multiple values allowed)</comment>
 <info>--qux2</info>     The qux2 option<comment> (default: {"foo":"bar"})</comment><comment> (multiple values allowed)</comment>
<info>Console Tool</info>

<comment>Usage:</comment>
  [options] command [arguments]

<comment>Options:</comment>
  <info>--help</info>           <info>-h</info> Display this help message.
  <info>--quiet</info>          <info>-q</info> Do not output any message.
  <info>--verbose</info>        <info>-v|vv|vvv</info> Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
  <info>--version</info>        <info>-V</info> Display this application version.
  <info>--ansi</info>              Force ANSI output.
  <info>--no-ansi</info>           Disable ANSI output.
  <info>--no-interaction</info> <info>-n</info> Do not ask any interactive question.<?xml version="1.0" encoding="UTF-8"?>
<symfony>
  <commands>
    <command id="help" name="help">
      <usage>help [--xml] [--format="..."] [--raw] [command_name]</usage>
      <description>Displays help for a command</description>
      <help>The &lt;info&gt;help&lt;/info&gt; command displays help for a given command:
 
   &lt;info&gt;php app/console help list&lt;/info&gt;
 
 You can also output the help in other formats by using the &lt;comment&gt;--format&lt;/comment&gt; option:
 
   &lt;info&gt;php app/console help --format=xml list&lt;/info&gt;
 
 To display the list of available commands, please use the &lt;info&gt;list&lt;/info&gt; command.</help>
      <aliases/>
      <arguments>
        <argument name="command_name" is_required="0" is_array="0">
          <description>The command name</description>
          <defaults>
            <default>help</default>
          </defaults>
        </argument>
      </arguments>
      <options>
        <option name="--xml" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>To output help as XML</description>
        </option>
        <option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0">
          <description>To output help in other formats</description>
          <defaults>
            <default>txt</default>
          </defaults>
        </option>
        <option name="--raw" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>To output raw command help</description>
        </option>
        <option name="--help" shortcut="-h" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Display this help message.</description>
        </option>
        <option name="--quiet" shortcut="-q" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Do not output any message.</description>
        </option>
        <option name="--verbose" shortcut="-v" shortcuts="-v|-vv|-vvv" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug</description>
        </option>
        <option name="--version" shortcut="-V" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Display this application version.</description>
        </option>
        <option name="--ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Force ANSI output.</description>
        </option>
        <option name="--no-ansi" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Disable ANSI output.</description>
        </option>
        <option name="--no-interaction" shortcut="-n" accept_value="0" is_value_required="0" is_multiple="0">
          <description>Do not ask any interactive question.</description>
        </option>
      </options>
    </command>
    <command id="list" name="list">
      <usage>list [--xml] [--raw] [--format="..."] [namespace]</usage>
      <description>Lists commands</description>
      <help>The &lt;info&gt;list&lt;/info&gt; command lists all commands:
 
   &lt;info&gt;php app/console list&lt;/info&gt;
 
 You can also display the commands for a specific namespace:
 
   &lt;info&gt;php app/console list test&lt;/info&gt;
 
 You can also output the information in other formats by using the &lt;comment&gt;--format&lt;/comment&gt; option:
 
   &lt;info&gt;php app/console list --format=xml&lt;/info&gt;
 
 It's also possible to get raw list of commands (useful for embedding command runner):
 
   &lt;info&gt;php app/console list --raw&lt;/info&gt;</help>
      <aliases/>
      <arguments>
        <argument name="namespace" is_required="0" is_array="0">
          <description>The namespace name</description>
          <defaults/>
        </argument>
      </arguments>
      <options>
        <option name="--xml" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>To output list as XML</description>
        </option>
        <option name="--raw" shortcut="" accept_value="0" is_value_required="0" is_multiple="0">
          <description>To output raw command list</description>
        </option>
        <option name="--format" shortcut="" accept_value="1" is_value_required="1" is_multiple="0">
          <description>To output list in other formats</description>
          <defaults>
            <default>txt</default>
          </defaults>
        </option>
      </options>
    </command>
  </commands>
  <namespaces>
    <namespace id="_global">
      <command>help</command>
      <command>list</command>
    </namespace>
  </namespaces>
</symfony>
 <info>--option_name</info> (-o) option description
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Fixtures;

use Symfony\Component\Console\Application;

class DescriptorApplication2 extends Application
{
    public function __construct()
    {
        parent::__construct('My Symfony application', 'v1.0');
        $this->add(new DescriptorCommand1());
        $this->add(new DescriptorCommand2());
    }
}
{"name":"argument_name","is_required":false,"is_array":true,"description":"argument description","default":[]}
 <info>argument_name</info> argument description<comment> (default: "default_value")</comment>
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Fixtures;

use Symfony\Component\Console\Application;

class DescriptorApplication1 extends Application
{
}
 <info>--option_name</info> (-o) option description<comment> (default: "default_value")</comment>
{"arguments":[],"options":[]}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Descriptor;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\BufferedOutput;

abstract class AbstractDescriptorTest extends \PHPUnit_Framework_TestCase
{
    /** @dataProvider getDescribeInputArgumentTestData */
    public function testDescribeInputArgument(InputArgument $argument, $expectedDescription)
    {
        $this->assertDescription($expectedDescription, $argument);
    }

    /** @dataProvider getDescribeInputOptionTestData */
    public function testDescribeInputOption(InputOption $option, $expectedDescription)
    {
        $this->assertDescription($expectedDescription, $option);
    }

    /** @dataProvider getDescribeInputDefinitionTestData */
    public function testDescribeInputDefinition(InputDefinition $definition, $expectedDescription)
    {
        $this->assertDescription($expectedDescription, $definition);
    }

    /** @dataProvider getDescribeCommandTestData */
    public function testDescribeCommand(Command $command, $expectedDescription)
    {
        $this->assertDescription($expectedDescription, $command);
    }

    /** @dataProvider getDescribeApplicationTestData */
    public function testDescribeApplication(Application $application, $expectedDescription)
    {
        // Replaces the dynamic placeholders of the command help text with a static version.
        // The placeholder %command.full_name% includes the script path that is not predictable
        // and can not be tested against.
        foreach ($application->all() as $command) {
            $command->setHelp(str_replace('%command.full_name%', 'app/console %command.name%', $command->getHelp()));
        }

        $this->assertDescription($expectedDescription, $application);
    }

    public function getDescribeInputArgumentTestData()
    {
        return $this->getDescriptionTestData(ObjectsProvider::getInputArguments());
    }

    public function getDescribeInputOptionTestData()
    {
        return $this->getDescriptionTestData(ObjectsProvider::getInputOptions());
    }

    public function getDescribeInputDefinitionTestData()
    {
        return $this->getDescriptionTestData(ObjectsProvider::getInputDefinitions());
    }

    public function getDescribeCommandTestData()
    {
        return $this->getDescriptionTestData(ObjectsProvider::getCommands());
    }

    public function getDescribeApplicationTestData()
    {
        return $this->getDescriptionTestData(ObjectsProvider::getApplications());
    }

    abstract protected function getDescriptor();
    abstract protected function getFormat();

    private function getDescriptionTestData(array $objects)
    {
        $data = array();
        foreach ($objects as $name => $object) {
            $description = file_get_contents(sprintf('%s/../Fixtures/%s.%s', __DIR__, $name, $this->getFormat()));
            $data[] = array($object, $description);
        }

        return $data;
    }

    private function assertDescription($expectedDescription, $describedObject)
    {
        $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
        $this->getDescriptor()->describe($output, $describedObject, array('raw_output' => true));
        $this->assertEquals(trim($expectedDescription), trim(str_replace(PHP_EOL, "\n", $output->fetch())));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Descriptor;

use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Tests\Fixtures\DescriptorApplication1;
use Symfony\Component\Console\Tests\Fixtures\DescriptorApplication2;
use Symfony\Component\Console\Tests\Fixtures\DescriptorCommand1;
use Symfony\Component\Console\Tests\Fixtures\DescriptorCommand2;

/**
 * @author Jean-François Simon <contact@jfsimon.fr>
 */
class ObjectsProvider
{
    public static function getInputArguments()
    {
        return array(
            'input_argument_1' => new InputArgument('argument_name', InputArgument::REQUIRED),
            'input_argument_2' => new InputArgument('argument_name', InputArgument::IS_ARRAY, 'argument description'),
            'input_argument_3' => new InputArgument('argument_name', InputArgument::OPTIONAL, 'argument description', 'default_value'),
        );
    }

    public static function getInputOptions()
    {
        return array(
            'input_option_1' => new InputOption('option_name', 'o', InputOption::VALUE_NONE),
            'input_option_2' => new InputOption('option_name', 'o', InputOption::VALUE_OPTIONAL, 'option description', 'default_value'),
            'input_option_3' => new InputOption('option_name', 'o', InputOption::VALUE_REQUIRED, 'option description'),
            'input_option_4' => new InputOption('option_name', 'o', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL, 'option description', array()),
        );
    }

    public static function getInputDefinitions()
    {
        return array(
            'input_definition_1' => new InputDefinition(),
            'input_definition_2' => new InputDefinition(array(new InputArgument('argument_name', InputArgument::REQUIRED))),
            'input_definition_3' => new InputDefinition(array(new InputOption('option_name', 'o', InputOption::VALUE_NONE))),
            'input_definition_4' => new InputDefinition(array(
                new InputArgument('argument_name', InputArgument::REQUIRED),
                new InputOption('option_name', 'o', InputOption::VALUE_NONE),
            )),
        );
    }

    public static function getCommands()
    {
        return array(
            'command_1' => new DescriptorCommand1(),
            'command_2' => new DescriptorCommand2(),
        );
    }

    public static function getApplications()
    {
        return array(
            'application_1' => new DescriptorApplication1(),
            'application_2' => new DescriptorApplication2(),
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Descriptor;

use Symfony\Component\Console\Descriptor\JsonDescriptor;

class JsonDescriptorTest extends AbstractDescriptorTest
{
    protected function getDescriptor()
    {
        return new JsonDescriptor();
    }

    protected function getFormat()
    {
        return 'json';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Descriptor;

use Symfony\Component\Console\Descriptor\TextDescriptor;

class TextDescriptorTest extends AbstractDescriptorTest
{
    protected function getDescriptor()
    {
        return new TextDescriptor();
    }

    protected function getFormat()
    {
        return 'txt';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Descriptor;

use Symfony\Component\Console\Descriptor\XmlDescriptor;

class XmlDescriptorTest extends AbstractDescriptorTest
{
    protected function getDescriptor()
    {
        return new XmlDescriptor();
    }

    protected function getFormat()
    {
        return 'xml';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Descriptor;

use Symfony\Component\Console\Descriptor\MarkdownDescriptor;

class MarkdownDescriptorTest extends AbstractDescriptorTest
{
    protected function getDescriptor()
    {
        return new MarkdownDescriptor();
    }

    protected function getFormat()
    {
        return 'md';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Output;

use Symfony\Component\Console\Output\Output;
use Symfony\Component\Console\Output\StreamOutput;

class StreamOutputTest extends \PHPUnit_Framework_TestCase
{
    protected $stream;

    protected function setUp()
    {
        $this->stream = fopen('php://memory', 'a', false);
    }

    protected function tearDown()
    {
        $this->stream = null;
    }

    public function testConstructor()
    {
        $output = new StreamOutput($this->stream, Output::VERBOSITY_QUIET, true);
        $this->assertEquals(Output::VERBOSITY_QUIET, $output->getVerbosity(), '__construct() takes the verbosity as its first argument');
        $this->assertTrue($output->isDecorated(), '__construct() takes the decorated flag as its second argument');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The StreamOutput class needs a stream as its first argument.
     */
    public function testStreamIsRequired()
    {
        new StreamOutput('foo');
    }

    public function testGetStream()
    {
        $output = new StreamOutput($this->stream);
        $this->assertEquals($this->stream, $output->getStream(), '->getStream() returns the current stream');
    }

    public function testDoWrite()
    {
        $output = new StreamOutput($this->stream);
        $output->writeln('foo');
        rewind($output->getStream());
        $this->assertEquals('foo'.PHP_EOL, stream_get_contents($output->getStream()), '->doWrite() writes to the stream');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Output;

use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Console\Output\Output;

class ConsoleOutputTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $output = new ConsoleOutput(Output::VERBOSITY_QUIET, true);
        $this->assertEquals(Output::VERBOSITY_QUIET, $output->getVerbosity(), '__construct() takes the verbosity as its first argument');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Output;

use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Output\OutputInterface;

class NullOutputTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $output = new NullOutput();

        ob_start();
        $output->write('foo');
        $buffer = ob_get_clean();

        $this->assertSame('', $buffer, '->write() does nothing (at least nothing is printed)');
        $this->assertFalse($output->isDecorated(), '->isDecorated() returns false');
    }

    public function testVerbosity()
    {
        $output = new NullOutput();
        $this->assertSame(OutputInterface::VERBOSITY_QUIET, $output->getVerbosity(), '->getVerbosity() returns VERBOSITY_QUIET for NullOutput by default');

        $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
        $this->assertSame(OutputInterface::VERBOSITY_QUIET, $output->getVerbosity(), '->getVerbosity() always returns VERBOSITY_QUIET for NullOutput');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Output;

use Symfony\Component\Console\Output\Output;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;

class OutputTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $output = new TestOutput(Output::VERBOSITY_QUIET, true);
        $this->assertEquals(Output::VERBOSITY_QUIET, $output->getVerbosity(), '__construct() takes the verbosity as its first argument');
        $this->assertTrue($output->isDecorated(), '__construct() takes the decorated flag as its second argument');
    }

    public function testSetIsDecorated()
    {
        $output = new TestOutput();
        $output->setDecorated(true);
        $this->assertTrue($output->isDecorated(), 'setDecorated() sets the decorated flag');
    }

    public function testSetGetVerbosity()
    {
        $output = new TestOutput();
        $output->setVerbosity(Output::VERBOSITY_QUIET);
        $this->assertEquals(Output::VERBOSITY_QUIET, $output->getVerbosity(), '->setVerbosity() sets the verbosity');

        $this->assertTrue($output->isQuiet());
        $this->assertFalse($output->isVerbose());
        $this->assertFalse($output->isVeryVerbose());
        $this->assertFalse($output->isDebug());

        $output->setVerbosity(Output::VERBOSITY_NORMAL);
        $this->assertFalse($output->isQuiet());
        $this->assertFalse($output->isVerbose());
        $this->assertFalse($output->isVeryVerbose());
        $this->assertFalse($output->isDebug());

        $output->setVerbosity(Output::VERBOSITY_VERBOSE);
        $this->assertFalse($output->isQuiet());
        $this->assertTrue($output->isVerbose());
        $this->assertFalse($output->isVeryVerbose());
        $this->assertFalse($output->isDebug());

        $output->setVerbosity(Output::VERBOSITY_VERY_VERBOSE);
        $this->assertFalse($output->isQuiet());
        $this->assertTrue($output->isVerbose());
        $this->assertTrue($output->isVeryVerbose());
        $this->assertFalse($output->isDebug());

        $output->setVerbosity(Output::VERBOSITY_DEBUG);
        $this->assertFalse($output->isQuiet());
        $this->assertTrue($output->isVerbose());
        $this->assertTrue($output->isVeryVerbose());
        $this->assertTrue($output->isDebug());
    }

    public function testWriteWithVerbosityQuiet()
    {
        $output = new TestOutput(Output::VERBOSITY_QUIET);
        $output->writeln('foo');
        $this->assertEquals('', $output->output, '->writeln() outputs nothing if verbosity is set to VERBOSITY_QUIET');
    }

    public function testWriteAnArrayOfMessages()
    {
        $output = new TestOutput();
        $output->writeln(array('foo', 'bar'));
        $this->assertEquals("foo\nbar\n", $output->output, '->writeln() can take an array of messages to output');
    }

    /**
     * @dataProvider provideWriteArguments
     */
    public function testWriteRawMessage($message, $type, $expectedOutput)
    {
        $output = new TestOutput();
        $output->writeln($message, $type);
        $this->assertEquals($expectedOutput, $output->output);
    }

    public function provideWriteArguments()
    {
        return array(
            array('<info>foo</info>', Output::OUTPUT_RAW, "<info>foo</info>\n"),
            array('<info>foo</info>', Output::OUTPUT_PLAIN, "foo\n"),
        );
    }

    public function testWriteWithDecorationTurnedOff()
    {
        $output = new TestOutput();
        $output->setDecorated(false);
        $output->writeln('<info>foo</info>');
        $this->assertEquals("foo\n", $output->output, '->writeln() strips decoration tags if decoration is set to false');
    }

    public function testWriteDecoratedMessage()
    {
        $fooStyle = new OutputFormatterStyle('yellow', 'red', array('blink'));
        $output = new TestOutput();
        $output->getFormatter()->setStyle('FOO', $fooStyle);
        $output->setDecorated(true);
        $output->writeln('<foo>foo</foo>');
        $this->assertEquals("\033[33;41;5mfoo\033[0m\n", $output->output, '->writeln() decorates the output');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage Unknown output type given (24)
     */
    public function testWriteWithInvalidOutputType()
    {
        $output = new TestOutput();
        $output->writeln('<foo>foo</foo>', 24);
    }

    public function testWriteWithInvalidStyle()
    {
        $output = new TestOutput();

        $output->clear();
        $output->write('<bar>foo</bar>');
        $this->assertEquals('<bar>foo</bar>', $output->output, '->write() do nothing when a style does not exist');

        $output->clear();
        $output->writeln('<bar>foo</bar>');
        $this->assertEquals("<bar>foo</bar>\n", $output->output, '->writeln() do nothing when a style does not exist');
    }
}

class TestOutput extends Output
{
    public $output = '';

    public function clear()
    {
        $this->output = '';
    }

    protected function doWrite($message, $newline)
    {
        $this->output .= $message.($newline ? "\n" : '');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Input;

use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;

class ArgvInputTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $_SERVER['argv'] = array('cli.php', 'foo');
        $input = new ArgvInput();
        $r = new \ReflectionObject($input);
        $p = $r->getProperty('tokens');
        $p->setAccessible(true);

        $this->assertEquals(array('foo'), $p->getValue($input), '__construct() automatically get its input from the argv server variable');
    }

    public function testParseArguments()
    {
        $input = new ArgvInput(array('cli.php', 'foo'));
        $input->bind(new InputDefinition(array(new InputArgument('name'))));
        $this->assertEquals(array('name' => 'foo'), $input->getArguments(), '->parse() parses required arguments');

        $input->bind(new InputDefinition(array(new InputArgument('name'))));
        $this->assertEquals(array('name' => 'foo'), $input->getArguments(), '->parse() is stateless');
    }

    /**
     * @dataProvider provideOptions
     */
    public function testParseOptions($input, $options, $expectedOptions, $message)
    {
        $input = new ArgvInput($input);
        $input->bind(new InputDefinition($options));

        $this->assertEquals($expectedOptions, $input->getOptions(), $message);
    }

    public function provideOptions()
    {
        return array(
            array(
                array('cli.php', '--foo'),
                array(new InputOption('foo')),
                array('foo' => true),
                '->parse() parses long options without a value'
            ),
            array(
                array('cli.php', '--foo=bar'),
                array(new InputOption('foo', 'f', InputOption::VALUE_REQUIRED)),
                array('foo' => 'bar'),
                '->parse() parses long options with a required value (with a = separator)'
            ),
            array(
                array('cli.php', '--foo', 'bar'),
                array(new InputOption('foo', 'f', InputOption::VALUE_REQUIRED)),
                array('foo' => 'bar'),
                '->parse() parses long options with a required value (with a space separator)'
            ),
            array(
                array('cli.php', '-f'),
                array(new InputOption('foo', 'f')),
                array('foo' => true),
                '->parse() parses short options without a value'
            ),
            array(
                array('cli.php', '-fbar'),
                array(new InputOption('foo', 'f', InputOption::VALUE_REQUIRED)),
                array('foo' => 'bar'),
                '->parse() parses short options with a required value (with no separator)'
            ),
            array(
                array('cli.php', '-f', 'bar'),
                array(new InputOption('foo', 'f', InputOption::VALUE_REQUIRED)),
                array('foo' => 'bar'),
                '->parse() parses short options with a required value (with a space separator)'
            ),
            array(
                array('cli.php', '-f', ''),
                array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL)),
                array('foo' => ''),
                '->parse() parses short options with an optional empty value'
            ),
            array(
                array('cli.php', '-f', '', 'foo'),
                array(new InputArgument('name'), new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL)),
                array('foo' => ''),
                '->parse() parses short options with an optional empty value followed by an argument'
            ),
            array(
                array('cli.php', '-f', '', '-b'),
                array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputOption('bar', 'b')),
                array('foo' => '', 'bar' => true),
                '->parse() parses short options with an optional empty value followed by an option'
            ),
            array(
                array('cli.php', '-f', '-b', 'foo'),
                array(new InputArgument('name'), new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputOption('bar', 'b')),
                array('foo' => null, 'bar' => true),
                '->parse() parses short options with an optional value which is not present'
            ),
            array(
                array('cli.php', '-fb'),
                array(new InputOption('foo', 'f'), new InputOption('bar', 'b')),
                array('foo' => true, 'bar' => true),
                '->parse() parses short options when they are aggregated as a single one'
            ),
            array(
                array('cli.php', '-fb', 'bar'),
                array(new InputOption('foo', 'f'), new InputOption('bar', 'b', InputOption::VALUE_REQUIRED)),
                array('foo' => true, 'bar' => 'bar'),
                '->parse() parses short options when they are aggregated as a single one and the last one has a required value'
            ),
            array(
                array('cli.php', '-fb', 'bar'),
                array(new InputOption('foo', 'f'), new InputOption('bar', 'b', InputOption::VALUE_OPTIONAL)),
                array('foo' => true, 'bar' => 'bar'),
                '->parse() parses short options when they are aggregated as a single one and the last one has an optional value'
            ),
            array(
                array('cli.php', '-fbbar'),
                array(new InputOption('foo', 'f'), new InputOption('bar', 'b', InputOption::VALUE_OPTIONAL)),
                array('foo' => true, 'bar' => 'bar'),
                '->parse() parses short options when they are aggregated as a single one and the last one has an optional value with no separator'
            ),
            array(
                array('cli.php', '-fbbar'),
                array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL), new InputOption('bar', 'b', InputOption::VALUE_OPTIONAL)),
                array('foo' => 'bbar', 'bar' => null),
                '->parse() parses short options when they are aggregated as a single one and one of them takes a value'
            )
        );
    }

    /**
     * @dataProvider provideInvalidInput
     */
    public function testInvalidInput($argv, $definition, $expectedExceptionMessage)
    {
        $this->setExpectedException('RuntimeException', $expectedExceptionMessage);

        $input = new ArgvInput($argv);
        $input->bind($definition);
    }

    public function provideInvalidInput()
    {
        return array(
            array(
                array('cli.php', '--foo'),
                new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_REQUIRED))),
                'The "--foo" option requires a value.'
            ),
            array(
                array('cli.php', '-f'),
                new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_REQUIRED))),
                'The "--foo" option requires a value.'
            ),
            array(
                array('cli.php', '-ffoo'),
                new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_NONE))),
                'The "-o" option does not exist.'
            ),
            array(
                array('cli.php', '--foo=bar'),
                new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_NONE))),
                'The "--foo" option does not accept a value.'
            ),
            array(
                array('cli.php', 'foo', 'bar'),
                new InputDefinition(),
                'Too many arguments.'
            ),
            array(
                array('cli.php', '--foo'),
                new InputDefinition(),
                'The "--foo" option does not exist.'
            ),
            array(
                array('cli.php', '-f'),
                new InputDefinition(),
                'The "-f" option does not exist.'
            ),
            array(
                array('cli.php', '-1'),
                new InputDefinition(array(new InputArgument('number'))),
                'The "-1" option does not exist.'
            )
        );
    }

    public function testParseArrayArgument()
    {
        $input = new ArgvInput(array('cli.php', 'foo', 'bar', 'baz', 'bat'));
        $input->bind(new InputDefinition(array(new InputArgument('name', InputArgument::IS_ARRAY))));

        $this->assertEquals(array('name' => array('foo', 'bar', 'baz', 'bat')), $input->getArguments(), '->parse() parses array arguments');
    }

    public function testParseArrayOption()
    {
        $input = new ArgvInput(array('cli.php', '--name=foo', '--name=bar', '--name=baz'));
        $input->bind(new InputDefinition(array(new InputOption('name', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY))));

        $this->assertEquals(array('name' => array('foo', 'bar', 'baz')), $input->getOptions(), '->parse() parses array options ("--option=value" syntax)');

        $input = new ArgvInput(array('cli.php', '--name', 'foo', '--name', 'bar', '--name', 'baz'));
        $input->bind(new InputDefinition(array(new InputOption('name', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY))));
        $this->assertEquals(array('name' => array('foo', 'bar', 'baz')), $input->getOptions(), '->parse() parses array options ("--option value" syntax)');

        $input = new ArgvInput(array('cli.php', '--name=foo', '--name=bar', '--name='));
        $input->bind(new InputDefinition(array(new InputOption('name', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY))));
        $this->assertSame(array('name' => array('foo', 'bar', null)), $input->getOptions(), '->parse() parses empty array options as null ("--option=value" syntax)');

        $input = new ArgvInput(array('cli.php', '--name', 'foo', '--name', 'bar', '--name', '--anotherOption'));
        $input->bind(new InputDefinition(array(
            new InputOption('name', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY),
            new InputOption('anotherOption', null, InputOption::VALUE_NONE),
        )));
        $this->assertSame(array('name' => array('foo', 'bar', null), 'anotherOption' => true), $input->getOptions(), '->parse() parses empty array options as null ("--option value" syntax)');
    }

    public function testParseNegativeNumberAfterDoubleDash()
    {
        $input = new ArgvInput(array('cli.php', '--', '-1'));
        $input->bind(new InputDefinition(array(new InputArgument('number'))));
        $this->assertEquals(array('number' => '-1'), $input->getArguments(), '->parse() parses arguments with leading dashes as arguments after having encountered a double-dash sequence');

        $input = new ArgvInput(array('cli.php', '-f', 'bar', '--', '-1'));
        $input->bind(new InputDefinition(array(new InputArgument('number'), new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL))));
        $this->assertEquals(array('foo' => 'bar'), $input->getOptions(), '->parse() parses arguments with leading dashes as options before having encountered a double-dash sequence');
        $this->assertEquals(array('number' => '-1'), $input->getArguments(), '->parse() parses arguments with leading dashes as arguments after having encountered a double-dash sequence');
    }

    public function testParseEmptyStringArgument()
    {
        $input = new ArgvInput(array('cli.php', '-f', 'bar', ''));
        $input->bind(new InputDefinition(array(new InputArgument('empty'), new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL))));

        $this->assertEquals(array('empty' => ''), $input->getArguments(), '->parse() parses empty string arguments');
    }

    public function testGetFirstArgument()
    {
        $input = new ArgvInput(array('cli.php', '-fbbar'));
        $this->assertEquals('', $input->getFirstArgument(), '->getFirstArgument() returns the first argument from the raw input');

        $input = new ArgvInput(array('cli.php', '-fbbar', 'foo'));
        $this->assertEquals('foo', $input->getFirstArgument(), '->getFirstArgument() returns the first argument from the raw input');
    }

    public function testHasParameterOption()
    {
        $input = new ArgvInput(array('cli.php', '-f', 'foo'));
        $this->assertTrue($input->hasParameterOption('-f'), '->hasParameterOption() returns true if the given short option is in the raw input');

        $input = new ArgvInput(array('cli.php', '--foo', 'foo'));
        $this->assertTrue($input->hasParameterOption('--foo'), '->hasParameterOption() returns true if the given short option is in the raw input');

        $input = new ArgvInput(array('cli.php', 'foo'));
        $this->assertFalse($input->hasParameterOption('--foo'), '->hasParameterOption() returns false if the given short option is not in the raw input');

        $input = new ArgvInput(array('cli.php', '--foo=bar'));
        $this->assertTrue($input->hasParameterOption('--foo'), '->hasParameterOption() returns true if the given option with provided value is in the raw input');
    }

    public function testToString()
    {
        $input = new ArgvInput(array('cli.php', '-f', 'foo'));
        $this->assertEquals('-f foo', (string) $input);

        $input = new ArgvInput(array('cli.php', '-f', '--bar=foo', 'a b c d', "A\nB'C"));
        $this->assertEquals('-f --bar=foo '.escapeshellarg('a b c d').' '.escapeshellarg("A\nB'C"), (string) $input);
    }

    /**
     * @dataProvider provideGetParameterOptionValues
     */
    public function testGetParameterOptionEqualSign($argv, $key, $expected)
    {
        $input = new ArgvInput($argv);
        $this->assertEquals($expected, $input->getParameterOption($key), '->getParameterOption() returns the expected value');
    }

    public function provideGetParameterOptionValues()
    {
        return array(
            array(array('app/console', 'foo:bar', '-e', 'dev'), '-e', 'dev'),
            array(array('app/console', 'foo:bar', '--env=dev'), '--env', 'dev'),
            array(array('app/console', 'foo:bar', '-e', 'dev'), array('-e', '--env'), 'dev'),
            array(array('app/console', 'foo:bar', '--env=dev'), array('-e', '--env'), 'dev'),
            array(array('app/console', 'foo:bar', '--env=dev', '--en=1'), array('--en'), '1'),
        );
    }

    public function testParseSingleDashAsArgument()
    {
        $input = new ArgvInput(array('cli.php', '-'));
        $input->bind(new InputDefinition(array(new InputArgument('file'))));
        $this->assertEquals(array('file' => '-'), $input->getArguments(), '->parse() parses single dash as an argument');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Input;

use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\StringInput;

class StringInputTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider getTokenizeData
     */
    public function testTokenize($input, $tokens, $message)
    {
        $input = new StringInput($input);
        $r = new \ReflectionClass('Symfony\Component\Console\Input\ArgvInput');
        $p = $r->getProperty('tokens');
        $p->setAccessible(true);
        $this->assertEquals($tokens, $p->getValue($input), $message);
    }

    public function testInputOptionWithGivenString()
    {
        $definition = new InputDefinition(
            array(new InputOption('foo', null, InputOption::VALUE_REQUIRED))
        );

        // call to bind
        $input = new StringInput('--foo=bar');
        $input->bind($definition);
        $this->assertEquals('bar', $input->getOption('foo'));

        // definition in constructor
        $input = new StringInput('--foo=bar', $definition);
        $this->assertEquals('bar', $input->getOption('foo'));
    }

    public function getTokenizeData()
    {
        return array(
            array('', array(), '->tokenize() parses an empty string'),
            array('foo', array('foo'), '->tokenize() parses arguments'),
            array('  foo  bar  ', array('foo', 'bar'), '->tokenize() ignores whitespaces between arguments'),
            array('"quoted"', array('quoted'), '->tokenize() parses quoted arguments'),
            array("'quoted'", array('quoted'), '->tokenize() parses quoted arguments'),
            array("'a\rb\nc\td'", array("a\rb\nc\td"), '->tokenize() parses whitespace chars in strings'),
            array("'a'\r'b'\n'c'\t'd'", array('a','b','c','d'), '->tokenize() parses whitespace chars between args as spaces'),
            array('\"quoted\"', array('"quoted"'), '->tokenize() parses escaped-quoted arguments'),
            array("\'quoted\'", array('\'quoted\''), '->tokenize() parses escaped-quoted arguments'),
            array('-a', array('-a'), '->tokenize() parses short options'),
            array('-azc', array('-azc'), '->tokenize() parses aggregated short options'),
            array('-awithavalue', array('-awithavalue'), '->tokenize() parses short options with a value'),
            array('-a"foo bar"', array('-afoo bar'), '->tokenize() parses short options with a value'),
            array('-a"foo bar""foo bar"', array('-afoo barfoo bar'), '->tokenize() parses short options with a value'),
            array('-a\'foo bar\'', array('-afoo bar'), '->tokenize() parses short options with a value'),
            array('-a\'foo bar\'\'foo bar\'', array('-afoo barfoo bar'), '->tokenize() parses short options with a value'),
            array('-a\'foo bar\'"foo bar"', array('-afoo barfoo bar'), '->tokenize() parses short options with a value'),
            array('--long-option', array('--long-option'), '->tokenize() parses long options'),
            array('--long-option=foo', array('--long-option=foo'), '->tokenize() parses long options with a value'),
            array('--long-option="foo bar"', array('--long-option=foo bar'), '->tokenize() parses long options with a value'),
            array('--long-option="foo bar""another"', array('--long-option=foo baranother'), '->tokenize() parses long options with a value'),
            array('--long-option=\'foo bar\'', array('--long-option=foo bar'), '->tokenize() parses long options with a value'),
            array("--long-option='foo bar''another'", array("--long-option=foo baranother"), '->tokenize() parses long options with a value'),
            array("--long-option='foo bar'\"another\"", array("--long-option=foo baranother"), '->tokenize() parses long options with a value'),
            array('foo -a -ffoo --long bar', array('foo', '-a', '-ffoo', '--long', 'bar'), '->tokenize() parses when several arguments and options'),
        );
    }

    public function testToString()
    {
        $input = new StringInput('-f foo');
        $this->assertEquals('-f foo', (string) $input);

        $input = new StringInput('-f --bar=foo "a b c d"');
        $this->assertEquals('-f --bar=foo '.escapeshellarg('a b c d'), (string) $input);

        $input = new StringInput('-f --bar=foo \'a b c d\' '."'A\nB\\'C'");
        $this->assertEquals('-f --bar=foo '.escapeshellarg('a b c d').' '.escapeshellarg("A\nB'C"), (string) $input);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Input;

use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;

class InputDefinitionTest extends \PHPUnit_Framework_TestCase
{
    protected static $fixtures;

    protected $foo, $bar, $foo1, $foo2;

    public static function setUpBeforeClass()
    {
        self::$fixtures = __DIR__.'/../Fixtures/';
    }

    public function testConstructorArguments()
    {
        $this->initializeArguments();

        $definition = new InputDefinition();
        $this->assertEquals(array(), $definition->getArguments(), '__construct() creates a new InputDefinition object');

        $definition = new InputDefinition(array($this->foo, $this->bar));
        $this->assertEquals(array('foo' => $this->foo, 'bar' => $this->bar), $definition->getArguments(), '__construct() takes an array of InputArgument objects as its first argument');
    }

    public function testConstructorOptions()
    {
        $this->initializeOptions();

        $definition = new InputDefinition();
        $this->assertEquals(array(), $definition->getOptions(), '__construct() creates a new InputDefinition object');

        $definition = new InputDefinition(array($this->foo, $this->bar));
        $this->assertEquals(array('foo' => $this->foo, 'bar' => $this->bar), $definition->getOptions(), '__construct() takes an array of InputOption objects as its first argument');
    }

    public function testSetArguments()
    {
        $this->initializeArguments();

        $definition = new InputDefinition();
        $definition->setArguments(array($this->foo));
        $this->assertEquals(array('foo' => $this->foo), $definition->getArguments(), '->setArguments() sets the array of InputArgument objects');
        $definition->setArguments(array($this->bar));

        $this->assertEquals(array('bar' => $this->bar), $definition->getArguments(), '->setArguments() clears all InputArgument objects');
    }

    public function testAddArguments()
    {
        $this->initializeArguments();

        $definition = new InputDefinition();
        $definition->addArguments(array($this->foo));
        $this->assertEquals(array('foo' => $this->foo), $definition->getArguments(), '->addArguments() adds an array of InputArgument objects');
        $definition->addArguments(array($this->bar));
        $this->assertEquals(array('foo' => $this->foo, 'bar' => $this->bar), $definition->getArguments(), '->addArguments() does not clear existing InputArgument objects');
    }

    public function testAddArgument()
    {
        $this->initializeArguments();

        $definition = new InputDefinition();
        $definition->addArgument($this->foo);
        $this->assertEquals(array('foo' => $this->foo), $definition->getArguments(), '->addArgument() adds a InputArgument object');
        $definition->addArgument($this->bar);
        $this->assertEquals(array('foo' => $this->foo, 'bar' => $this->bar), $definition->getArguments(), '->addArgument() adds a InputArgument object');
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage An argument with name "foo" already exists.
     */
    public function testArgumentsMustHaveDifferentNames()
    {
        $this->initializeArguments();

        $definition = new InputDefinition();
        $definition->addArgument($this->foo);
        $definition->addArgument($this->foo1);
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage Cannot add an argument after an array argument.
     */
    public function testArrayArgumentHasToBeLast()
    {
        $this->initializeArguments();

        $definition = new InputDefinition();
        $definition->addArgument(new InputArgument('fooarray', InputArgument::IS_ARRAY));
        $definition->addArgument(new InputArgument('anotherbar'));
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage Cannot add a required argument after an optional one.
     */
    public function testRequiredArgumentCannotFollowAnOptionalOne()
    {
        $this->initializeArguments();

        $definition = new InputDefinition();
        $definition->addArgument($this->foo);
        $definition->addArgument($this->foo2);
    }

    public function testGetArgument()
    {
        $this->initializeArguments();

        $definition = new InputDefinition();
        $definition->addArguments(array($this->foo));
        $this->assertEquals($this->foo, $definition->getArgument('foo'), '->getArgument() returns a InputArgument by its name');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The "bar" argument does not exist.
     */
    public function testGetInvalidArgument()
    {
        $this->initializeArguments();

        $definition = new InputDefinition();
        $definition->addArguments(array($this->foo));
        $definition->getArgument('bar');
    }

    public function testHasArgument()
    {
        $this->initializeArguments();

        $definition = new InputDefinition();
        $definition->addArguments(array($this->foo));

        $this->assertTrue($definition->hasArgument('foo'), '->hasArgument() returns true if a InputArgument exists for the given name');
        $this->assertFalse($definition->hasArgument('bar'), '->hasArgument() returns false if a InputArgument exists for the given name');
    }

    public function testGetArgumentRequiredCount()
    {
        $this->initializeArguments();

        $definition = new InputDefinition();
        $definition->addArgument($this->foo2);
        $this->assertEquals(1, $definition->getArgumentRequiredCount(), '->getArgumentRequiredCount() returns the number of required arguments');
        $definition->addArgument($this->foo);
        $this->assertEquals(1, $definition->getArgumentRequiredCount(), '->getArgumentRequiredCount() returns the number of required arguments');
    }

    public function testGetArgumentCount()
    {
        $this->initializeArguments();

        $definition = new InputDefinition();
        $definition->addArgument($this->foo2);
        $this->assertEquals(1, $definition->getArgumentCount(), '->getArgumentCount() returns the number of arguments');
        $definition->addArgument($this->foo);
        $this->assertEquals(2, $definition->getArgumentCount(), '->getArgumentCount() returns the number of arguments');
    }

    public function testGetArgumentDefaults()
    {
        $definition = new InputDefinition(array(
            new InputArgument('foo1', InputArgument::OPTIONAL),
            new InputArgument('foo2', InputArgument::OPTIONAL, '', 'default'),
            new InputArgument('foo3', InputArgument::OPTIONAL | InputArgument::IS_ARRAY),
        //  new InputArgument('foo4', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, '', array(1, 2)),
        ));
        $this->assertEquals(array('foo1' => null, 'foo2' => 'default', 'foo3' => array()), $definition->getArgumentDefaults(), '->getArgumentDefaults() return the default values for each argument');

        $definition = new InputDefinition(array(
            new InputArgument('foo4', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, '', array(1, 2)),
        ));
        $this->assertEquals(array('foo4' => array(1, 2)), $definition->getArgumentDefaults(), '->getArgumentDefaults() return the default values for each argument');
    }

    public function testSetOptions()
    {
        $this->initializeOptions();

        $definition = new InputDefinition(array($this->foo));
        $this->assertEquals(array('foo' => $this->foo), $definition->getOptions(), '->setOptions() sets the array of InputOption objects');
        $definition->setOptions(array($this->bar));
        $this->assertEquals(array('bar' => $this->bar), $definition->getOptions(), '->setOptions() clears all InputOption objects');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The "-f" option does not exist.
     */
    public function testSetOptionsClearsOptions()
    {
        $this->initializeOptions();

        $definition = new InputDefinition(array($this->foo));
        $definition->setOptions(array($this->bar));
        $definition->getOptionForShortcut('f');
    }

    public function testAddOptions()
    {
        $this->initializeOptions();

        $definition = new InputDefinition(array($this->foo));
        $this->assertEquals(array('foo' => $this->foo), $definition->getOptions(), '->addOptions() adds an array of InputOption objects');
        $definition->addOptions(array($this->bar));
        $this->assertEquals(array('foo' => $this->foo, 'bar' => $this->bar), $definition->getOptions(), '->addOptions() does not clear existing InputOption objects');
    }

    public function testAddOption()
    {
        $this->initializeOptions();

        $definition = new InputDefinition();
        $definition->addOption($this->foo);
        $this->assertEquals(array('foo' => $this->foo), $definition->getOptions(), '->addOption() adds a InputOption object');
        $definition->addOption($this->bar);
        $this->assertEquals(array('foo' => $this->foo, 'bar' => $this->bar), $definition->getOptions(), '->addOption() adds a InputOption object');
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage An option named "foo" already exists.
     */
    public function testAddDuplicateOption()
    {
        $this->initializeOptions();

        $definition = new InputDefinition();
        $definition->addOption($this->foo);
        $definition->addOption($this->foo2);
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage An option with shortcut "f" already exists.
     */
    public function testAddDuplicateShortcutOption()
    {
        $this->initializeOptions();

        $definition = new InputDefinition();
        $definition->addOption($this->foo);
        $definition->addOption($this->foo1);
    }

    public function testGetOption()
    {
        $this->initializeOptions();

        $definition = new InputDefinition(array($this->foo));
        $this->assertEquals($this->foo, $definition->getOption('foo'), '->getOption() returns a InputOption by its name');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The "--bar" option does not exist.
     */
    public function testGetInvalidOption()
    {
        $this->initializeOptions();

        $definition = new InputDefinition(array($this->foo));
        $definition->getOption('bar');
    }

    public function testHasOption()
    {
        $this->initializeOptions();

        $definition = new InputDefinition(array($this->foo));
        $this->assertTrue($definition->hasOption('foo'), '->hasOption() returns true if a InputOption exists for the given name');
        $this->assertFalse($definition->hasOption('bar'), '->hasOption() returns false if a InputOption exists for the given name');
    }

    public function testHasShortcut()
    {
        $this->initializeOptions();

        $definition = new InputDefinition(array($this->foo));
        $this->assertTrue($definition->hasShortcut('f'), '->hasShortcut() returns true if a InputOption exists for the given shortcut');
        $this->assertFalse($definition->hasShortcut('b'), '->hasShortcut() returns false if a InputOption exists for the given shortcut');
    }

    public function testGetOptionForShortcut()
    {
        $this->initializeOptions();

        $definition = new InputDefinition(array($this->foo));
        $this->assertEquals($this->foo, $definition->getOptionForShortcut('f'), '->getOptionForShortcut() returns a InputOption by its shortcut');
    }

    public function testGetOptionForMultiShortcut()
    {
        $this->initializeOptions();

        $definition = new InputDefinition(array($this->multi));
        $this->assertEquals($this->multi, $definition->getOptionForShortcut('m'), '->getOptionForShortcut() returns a InputOption by its shortcut');
        $this->assertEquals($this->multi, $definition->getOptionForShortcut('mmm'), '->getOptionForShortcut() returns a InputOption by its shortcut');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The "-l" option does not exist.
     */
    public function testGetOptionForInvalidShortcut()
    {
        $this->initializeOptions();

        $definition = new InputDefinition(array($this->foo));
        $definition->getOptionForShortcut('l');
    }

    public function testGetOptionDefaults()
    {
        $definition = new InputDefinition(array(
            new InputOption('foo1', null, InputOption::VALUE_NONE),
            new InputOption('foo2', null, InputOption::VALUE_REQUIRED),
            new InputOption('foo3', null, InputOption::VALUE_REQUIRED, '', 'default'),
            new InputOption('foo4', null, InputOption::VALUE_OPTIONAL),
            new InputOption('foo5', null, InputOption::VALUE_OPTIONAL, '', 'default'),
            new InputOption('foo6', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY),
            new InputOption('foo7', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, '', array(1, 2)),
        ));
        $defaults = array(
            'foo1' => null,
            'foo2' => null,
            'foo3' => 'default',
            'foo4' => null,
            'foo5' => 'default',
            'foo6' => array(),
            'foo7' => array(1, 2),
        );
        $this->assertEquals($defaults, $definition->getOptionDefaults(), '->getOptionDefaults() returns the default values for all options');
    }

    public function testGetSynopsis()
    {
        $definition = new InputDefinition(array(new InputOption('foo')));
        $this->assertEquals('[--foo]', $definition->getSynopsis(), '->getSynopsis() returns a synopsis of arguments and options');
        $definition = new InputDefinition(array(new InputOption('foo', 'f')));
        $this->assertEquals('[-f|--foo]', $definition->getSynopsis(), '->getSynopsis() returns a synopsis of arguments and options');
        $definition = new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_REQUIRED)));
        $this->assertEquals('[-f|--foo="..."]', $definition->getSynopsis(), '->getSynopsis() returns a synopsis of arguments and options');
        $definition = new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL)));
        $this->assertEquals('[-f|--foo[="..."]]', $definition->getSynopsis(), '->getSynopsis() returns a synopsis of arguments and options');

        $definition = new InputDefinition(array(new InputArgument('foo')));
        $this->assertEquals('[foo]', $definition->getSynopsis(), '->getSynopsis() returns a synopsis of arguments and options');
        $definition = new InputDefinition(array(new InputArgument('foo', InputArgument::REQUIRED)));
        $this->assertEquals('foo', $definition->getSynopsis(), '->getSynopsis() returns a synopsis of arguments and options');
        $definition = new InputDefinition(array(new InputArgument('foo', InputArgument::IS_ARRAY)));
        $this->assertEquals('[foo1] ... [fooN]', $definition->getSynopsis(), '->getSynopsis() returns a synopsis of arguments and options');
        $definition = new InputDefinition(array(new InputArgument('foo', InputArgument::REQUIRED | InputArgument::IS_ARRAY)));
        $this->assertEquals('foo1 ... [fooN]', $definition->getSynopsis(), '->getSynopsis() returns a synopsis of arguments and options');
    }

    public function testAsText()
    {
        $definition = new InputDefinition(array(
            new InputArgument('foo', InputArgument::OPTIONAL, 'The foo argument'),
            new InputArgument('baz', InputArgument::OPTIONAL, 'The baz argument', true),
            new InputArgument('bar', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, 'The bar argument', array('http://foo.com/')),
            new InputOption('foo', 'f', InputOption::VALUE_REQUIRED, 'The foo option'),
            new InputOption('baz', null, InputOption::VALUE_OPTIONAL, 'The baz option', false),
            new InputOption('bar', 'b', InputOption::VALUE_OPTIONAL, 'The bar option', 'bar'),
            new InputOption('qux', '', InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'The qux option', array('http://foo.com/', 'bar')),
            new InputOption('qux2', '', InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'The qux2 option', array('foo' => 'bar')),
        ));
        $this->assertStringEqualsFile(self::$fixtures.'/definition_astext.txt', $definition->asText(), '->asText() returns a textual representation of the InputDefinition');
    }

    public function testAsXml()
    {
        $definition = new InputDefinition(array(
            new InputArgument('foo', InputArgument::OPTIONAL, 'The foo argument'),
            new InputArgument('baz', InputArgument::OPTIONAL, 'The baz argument', true),
            new InputArgument('bar', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, 'The bar argument', array('bar')),
            new InputOption('foo', 'f', InputOption::VALUE_REQUIRED, 'The foo option'),
            new InputOption('baz', null, InputOption::VALUE_OPTIONAL, 'The baz option', false),
            new InputOption('bar', 'b', InputOption::VALUE_OPTIONAL, 'The bar option', 'bar'),
        ));
        $this->assertXmlStringEqualsXmlFile(self::$fixtures.'/definition_asxml.txt', $definition->asXml(), '->asText() returns a textual representation of the InputDefinition');
    }

    protected function initializeArguments()
    {
        $this->foo = new InputArgument('foo');
        $this->bar = new InputArgument('bar');
        $this->foo1 = new InputArgument('foo');
        $this->foo2 = new InputArgument('foo2', InputArgument::REQUIRED);
    }

    protected function initializeOptions()
    {
        $this->foo = new InputOption('foo', 'f');
        $this->bar = new InputOption('bar', 'b');
        $this->foo1 = new InputOption('fooBis', 'f');
        $this->foo2 = new InputOption('foo', 'p');
        $this->multi = new InputOption('multi', 'm|mm|mmm');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Input;

use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;

class ArrayInputTest extends \PHPUnit_Framework_TestCase
{
    public function testGetFirstArgument()
    {
        $input = new ArrayInput(array());
        $this->assertNull($input->getFirstArgument(), '->getFirstArgument() returns null if no argument were passed');
        $input = new ArrayInput(array('name' => 'Fabien'));
        $this->assertEquals('Fabien', $input->getFirstArgument(), '->getFirstArgument() returns the first passed argument');
        $input = new ArrayInput(array('--foo' => 'bar', 'name' => 'Fabien'));
        $this->assertEquals('Fabien', $input->getFirstArgument(), '->getFirstArgument() returns the first passed argument');
    }

    public function testHasParameterOption()
    {
        $input = new ArrayInput(array('name' => 'Fabien', '--foo' => 'bar'));
        $this->assertTrue($input->hasParameterOption('--foo'), '->hasParameterOption() returns true if an option is present in the passed parameters');
        $this->assertFalse($input->hasParameterOption('--bar'), '->hasParameterOption() returns false if an option is not present in the passed parameters');

        $input = new ArrayInput(array('--foo'));
        $this->assertTrue($input->hasParameterOption('--foo'), '->hasParameterOption() returns true if an option is present in the passed parameters');
    }

    public function testParseArguments()
    {
        $input = new ArrayInput(array('name' => 'foo'), new InputDefinition(array(new InputArgument('name'))));

        $this->assertEquals(array('name' => 'foo'), $input->getArguments(), '->parse() parses required arguments');
    }

    /**
     * @dataProvider provideOptions
     */
    public function testParseOptions($input, $options, $expectedOptions, $message)
    {
        $input = new ArrayInput($input, new InputDefinition($options));

        $this->assertEquals($expectedOptions, $input->getOptions(), $message);
    }

    public function provideOptions()
    {
        return array(
            array(
                array('--foo' => 'bar'),
                array(new InputOption('foo')),
                array('foo' => 'bar'),
                '->parse() parses long options'
            ),
            array(
                array('--foo' => 'bar'),
                array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL, '', 'default')),
                array('foo' => 'bar'),
                '->parse() parses long options with a default value'
            ),
            array(
                array('--foo' => null),
                array(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL, '', 'default')),
                array('foo' => 'default'),
                '->parse() parses long options with a default value'
            ),
            array(
                array('-f' => 'bar'),
                array(new InputOption('foo', 'f')),
                array('foo' => 'bar'),
                '->parse() parses short options'
            )
        );
    }

    /**
     * @dataProvider provideInvalidInput
     */
    public function testParseInvalidInput($parameters, $definition, $expectedExceptionMessage)
    {
        $this->setExpectedException('InvalidArgumentException', $expectedExceptionMessage);

        new ArrayInput($parameters, $definition);
    }

    public function provideInvalidInput()
    {
        return array(
            array(
                array('foo' => 'foo'),
                new InputDefinition(array(new InputArgument('name'))),
                'The "foo" argument does not exist.'
            ),
            array(
                array('--foo' => null),
                new InputDefinition(array(new InputOption('foo', 'f', InputOption::VALUE_REQUIRED))),
                'The "--foo" option requires a value.'
            ),
            array(
                array('--foo' => 'foo'),
                new InputDefinition(),
                'The "--foo" option does not exist.'
            ),
            array(
                array('-o' => 'foo'),
                new InputDefinition(),
                'The "-o" option does not exist.'
            )
        );
    }

    public function testToString()
    {
        $input = new ArrayInput(array('-f' => null, '-b' => 'bar', '--foo' => 'b a z', '--lala' => null, 'test' => 'Foo', 'test2' => "A\nB'C"));
        $this->assertEquals('-f -b=bar --foo='.escapeshellarg('b a z').' --lala Foo '.escapeshellarg("A\nB'C"), (string) $input);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Input;

use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;

class InputTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $input = new ArrayInput(array('name' => 'foo'), new InputDefinition(array(new InputArgument('name'))));
        $this->assertEquals('foo', $input->getArgument('name'), '->__construct() takes a InputDefinition as an argument');
    }

    public function testOptions()
    {
        $input = new ArrayInput(array('--name' => 'foo'), new InputDefinition(array(new InputOption('name'))));
        $this->assertEquals('foo', $input->getOption('name'), '->getOption() returns the value for the given option');

        $input->setOption('name', 'bar');
        $this->assertEquals('bar', $input->getOption('name'), '->setOption() sets the value for a given option');
        $this->assertEquals(array('name' => 'bar'), $input->getOptions(), '->getOptions() returns all option values');

        $input = new ArrayInput(array('--name' => 'foo'), new InputDefinition(array(new InputOption('name'), new InputOption('bar', '', InputOption::VALUE_OPTIONAL, '', 'default'))));
        $this->assertEquals('default', $input->getOption('bar'), '->getOption() returns the default value for optional options');
        $this->assertEquals(array('name' => 'foo', 'bar' => 'default'), $input->getOptions(), '->getOptions() returns all option values, even optional ones');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The "foo" option does not exist.
     */
    public function testSetInvalidOption()
    {
        $input = new ArrayInput(array('--name' => 'foo'), new InputDefinition(array(new InputOption('name'), new InputOption('bar', '', InputOption::VALUE_OPTIONAL, '', 'default'))));
        $input->setOption('foo', 'bar');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The "foo" option does not exist.
     */
    public function testGetInvalidOption()
    {
        $input = new ArrayInput(array('--name' => 'foo'), new InputDefinition(array(new InputOption('name'), new InputOption('bar', '', InputOption::VALUE_OPTIONAL, '', 'default'))));
        $input->getOption('foo');
    }

    public function testArguments()
    {
        $input = new ArrayInput(array('name' => 'foo'), new InputDefinition(array(new InputArgument('name'))));
        $this->assertEquals('foo', $input->getArgument('name'), '->getArgument() returns the value for the given argument');

        $input->setArgument('name', 'bar');
        $this->assertEquals('bar', $input->getArgument('name'), '->setArgument() sets the value for a given argument');
        $this->assertEquals(array('name' => 'bar'), $input->getArguments(), '->getArguments() returns all argument values');

        $input = new ArrayInput(array('name' => 'foo'), new InputDefinition(array(new InputArgument('name'), new InputArgument('bar', InputArgument::OPTIONAL, '', 'default'))));
        $this->assertEquals('default', $input->getArgument('bar'), '->getArgument() returns the default value for optional arguments');
        $this->assertEquals(array('name' => 'foo', 'bar' => 'default'), $input->getArguments(), '->getArguments() returns all argument values, even optional ones');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The "foo" argument does not exist.
     */
    public function testSetInvalidArgument()
    {
        $input = new ArrayInput(array('name' => 'foo'), new InputDefinition(array(new InputArgument('name'), new InputArgument('bar', InputArgument::OPTIONAL, '', 'default'))));
        $input->setArgument('foo', 'bar');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The "foo" argument does not exist.
     */
    public function testGetInvalidArgument()
    {
        $input = new ArrayInput(array('name' => 'foo'), new InputDefinition(array(new InputArgument('name'), new InputArgument('bar', InputArgument::OPTIONAL, '', 'default'))));
        $input->getArgument('foo');
    }

    /**
     * @expectedException        \RuntimeException
     * @expectedExceptionMessage Not enough arguments.
     */
    public function testValidateWithMissingArguments()
    {
        $input = new ArrayInput(array());
        $input->bind(new InputDefinition(array(new InputArgument('name', InputArgument::REQUIRED))));
        $input->validate();
    }

    public function testValidate()
    {
        $input = new ArrayInput(array('name' => 'foo'));
        $input->bind(new InputDefinition(array(new InputArgument('name', InputArgument::REQUIRED))));

        $this->assertNull($input->validate());
    }

    public function testSetGetInteractive()
    {
        $input = new ArrayInput(array());
        $this->assertTrue($input->isInteractive(), '->isInteractive() returns whether the input should be interactive or not');
        $input->setInteractive(false);
        $this->assertFalse($input->isInteractive(), '->setInteractive() changes the interactive flag');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Input;

use Symfony\Component\Console\Input\InputOption;

class InputOptionTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $option = new InputOption('foo');
        $this->assertEquals('foo', $option->getName(), '__construct() takes a name as its first argument');
        $option = new InputOption('--foo');
        $this->assertEquals('foo', $option->getName(), '__construct() removes the leading -- of the option name');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.
     */
    public function testArrayModeWithoutValue()
    {
        new InputOption('foo', 'f', InputOption::VALUE_IS_ARRAY);
    }

    public function testShortcut()
    {
        $option = new InputOption('foo', 'f');
        $this->assertEquals('f', $option->getShortcut(), '__construct() can take a shortcut as its second argument');
        $option = new InputOption('foo', '-f|-ff|fff');
        $this->assertEquals('f|ff|fff', $option->getShortcut(), '__construct() removes the leading - of the shortcuts');
        $option = new InputOption('foo', array('f', 'ff', '-fff'));
        $this->assertEquals('f|ff|fff', $option->getShortcut(), '__construct() removes the leading - of the shortcuts');
        $option = new InputOption('foo');
        $this->assertNull($option->getShortcut(), '__construct() makes the shortcut null by default');
    }

    public function testModes()
    {
        $option = new InputOption('foo', 'f');
        $this->assertFalse($option->acceptValue(), '__construct() gives a "InputOption::VALUE_NONE" mode by default');
        $this->assertFalse($option->isValueRequired(), '__construct() gives a "InputOption::VALUE_NONE" mode by default');
        $this->assertFalse($option->isValueOptional(), '__construct() gives a "InputOption::VALUE_NONE" mode by default');

        $option = new InputOption('foo', 'f', null);
        $this->assertFalse($option->acceptValue(), '__construct() can take "InputOption::VALUE_NONE" as its mode');
        $this->assertFalse($option->isValueRequired(), '__construct() can take "InputOption::VALUE_NONE" as its mode');
        $this->assertFalse($option->isValueOptional(), '__construct() can take "InputOption::VALUE_NONE" as its mode');

        $option = new InputOption('foo', 'f', InputOption::VALUE_NONE);
        $this->assertFalse($option->acceptValue(), '__construct() can take "InputOption::VALUE_NONE" as its mode');
        $this->assertFalse($option->isValueRequired(), '__construct() can take "InputOption::VALUE_NONE" as its mode');
        $this->assertFalse($option->isValueOptional(), '__construct() can take "InputOption::VALUE_NONE" as its mode');

        $option = new InputOption('foo', 'f', InputOption::VALUE_REQUIRED);
        $this->assertTrue($option->acceptValue(), '__construct() can take "InputOption::VALUE_REQUIRED" as its mode');
        $this->assertTrue($option->isValueRequired(), '__construct() can take "InputOption::VALUE_REQUIRED" as its mode');
        $this->assertFalse($option->isValueOptional(), '__construct() can take "InputOption::VALUE_REQUIRED" as its mode');

        $option = new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL);
        $this->assertTrue($option->acceptValue(), '__construct() can take "InputOption::VALUE_OPTIONAL" as its mode');
        $this->assertFalse($option->isValueRequired(), '__construct() can take "InputOption::VALUE_OPTIONAL" as its mode');
        $this->assertTrue($option->isValueOptional(), '__construct() can take "InputOption::VALUE_OPTIONAL" as its mode');
    }

    /**
     * @dataProvider provideInvalidModes
     */
    public function testInvalidModes($mode)
    {
        $this->setExpectedException('InvalidArgumentException', sprintf('Option mode "%s" is not valid.', $mode));

        new InputOption('foo', 'f', $mode);
    }

    public function provideInvalidModes()
    {
        return array(
            array('ANOTHER_ONE'),
            array(-1)
        );
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testEmptyNameIsInvalid()
    {
        new InputOption('');
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testDoubleDashNameIsInvalid()
    {
        new InputOption('--');
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testSingleDashOptionIsInvalid()
    {
        new InputOption('foo', '-');
    }

    public function testIsArray()
    {
        $option = new InputOption('foo', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY);
        $this->assertTrue($option->isArray(), '->isArray() returns true if the option can be an array');
        $option = new InputOption('foo', null, InputOption::VALUE_NONE);
        $this->assertFalse($option->isArray(), '->isArray() returns false if the option can not be an array');
    }

    public function testGetDescription()
    {
        $option = new InputOption('foo', 'f', null, 'Some description');
        $this->assertEquals('Some description', $option->getDescription(), '->getDescription() returns the description message');
    }

    public function testGetDefault()
    {
        $option = new InputOption('foo', null, InputOption::VALUE_OPTIONAL, '', 'default');
        $this->assertEquals('default', $option->getDefault(), '->getDefault() returns the default value');

        $option = new InputOption('foo', null, InputOption::VALUE_REQUIRED, '', 'default');
        $this->assertEquals('default', $option->getDefault(), '->getDefault() returns the default value');

        $option = new InputOption('foo', null, InputOption::VALUE_REQUIRED);
        $this->assertNull($option->getDefault(), '->getDefault() returns null if no default value is configured');

        $option = new InputOption('foo', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY);
        $this->assertEquals(array(), $option->getDefault(), '->getDefault() returns an empty array if option is an array');

        $option = new InputOption('foo', null, InputOption::VALUE_NONE);
        $this->assertFalse($option->getDefault(), '->getDefault() returns false if the option does not take a value');
    }

    public function testSetDefault()
    {
        $option = new InputOption('foo', null, InputOption::VALUE_REQUIRED, '', 'default');
        $option->setDefault(null);
        $this->assertNull($option->getDefault(), '->setDefault() can reset the default value by passing null');
        $option->setDefault('another');
        $this->assertEquals('another', $option->getDefault(), '->setDefault() changes the default value');

        $option = new InputOption('foo', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY);
        $option->setDefault(array(1, 2));
        $this->assertEquals(array(1, 2), $option->getDefault(), '->setDefault() changes the default value');
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage Cannot set a default value when using InputOption::VALUE_NONE mode.
     */
    public function testDefaultValueWithValueNoneMode()
    {
        $option = new InputOption('foo', 'f', InputOption::VALUE_NONE);
        $option->setDefault('default');
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage A default value for an array option must be an array.
     */
    public function testDefaultValueWithIsArrayMode()
    {
        $option = new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY);
        $option->setDefault('default');
    }

    public function testEquals()
    {
        $option = new InputOption('foo', 'f', null, 'Some description');
        $option2 = new InputOption('foo', 'f', null, 'Alternative description');
        $this->assertTrue($option->equals($option2));

        $option = new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL, 'Some description');
        $option2 = new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL, 'Some description', true);
        $this->assertFalse($option->equals($option2));

        $option = new InputOption('foo', 'f', null, 'Some description');
        $option2 = new InputOption('bar', 'f', null, 'Some description');
        $this->assertFalse($option->equals($option2));

        $option = new InputOption('foo', 'f', null, 'Some description');
        $option2 = new InputOption('foo', '', null, 'Some description');
        $this->assertFalse($option->equals($option2));

        $option = new InputOption('foo', 'f', null, 'Some description');
        $option2 = new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL, 'Some description');
        $this->assertFalse($option->equals($option2));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Input;

use Symfony\Component\Console\Input\InputArgument;

class InputArgumentTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $argument = new InputArgument('foo');
        $this->assertEquals('foo', $argument->getName(), '__construct() takes a name as its first argument');
    }

    public function testModes()
    {
        $argument = new InputArgument('foo');
        $this->assertFalse($argument->isRequired(), '__construct() gives a "InputArgument::OPTIONAL" mode by default');

        $argument = new InputArgument('foo', null);
        $this->assertFalse($argument->isRequired(), '__construct() can take "InputArgument::OPTIONAL" as its mode');

        $argument = new InputArgument('foo', InputArgument::OPTIONAL);
        $this->assertFalse($argument->isRequired(), '__construct() can take "InputArgument::OPTIONAL" as its mode');

        $argument = new InputArgument('foo', InputArgument::REQUIRED);
        $this->assertTrue($argument->isRequired(), '__construct() can take "InputArgument::REQUIRED" as its mode');
    }

    /**
     * @dataProvider provideInvalidModes
     */
    public function testInvalidModes($mode)
    {
        $this->setExpectedException('InvalidArgumentException', sprintf('Argument mode "%s" is not valid.', $mode));

        new InputArgument('foo', $mode);
    }

    public function provideInvalidModes()
    {
        return array(
            array('ANOTHER_ONE'),
            array(-1)
        );
    }

    public function testIsArray()
    {
        $argument = new InputArgument('foo', InputArgument::IS_ARRAY);
        $this->assertTrue($argument->isArray(), '->isArray() returns true if the argument can be an array');
        $argument = new InputArgument('foo', InputArgument::OPTIONAL | InputArgument::IS_ARRAY);
        $this->assertTrue($argument->isArray(), '->isArray() returns true if the argument can be an array');
        $argument = new InputArgument('foo', InputArgument::OPTIONAL);
        $this->assertFalse($argument->isArray(), '->isArray() returns false if the argument can not be an array');
    }

    public function testGetDescription()
    {
        $argument = new InputArgument('foo', null, 'Some description');
        $this->assertEquals('Some description', $argument->getDescription(), '->getDescription() return the message description');
    }

    public function testGetDefault()
    {
        $argument = new InputArgument('foo', InputArgument::OPTIONAL, '', 'default');
        $this->assertEquals('default', $argument->getDefault(), '->getDefault() return the default value');
    }

    public function testSetDefault()
    {
        $argument = new InputArgument('foo', InputArgument::OPTIONAL, '', 'default');
        $argument->setDefault(null);
        $this->assertNull($argument->getDefault(), '->setDefault() can reset the default value by passing null');
        $argument->setDefault('another');
        $this->assertEquals('another', $argument->getDefault(), '->setDefault() changes the default value');

        $argument = new InputArgument('foo', InputArgument::OPTIONAL | InputArgument::IS_ARRAY);
        $argument->setDefault(array(1, 2));
        $this->assertEquals(array(1, 2), $argument->getDefault(), '->setDefault() changes the default value');
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage Cannot set a default value except for InputArgument::OPTIONAL mode.
     */
    public function testSetDefaultWithRequiredArgument()
    {
        $argument = new InputArgument('foo', InputArgument::REQUIRED);
        $argument->setDefault('default');
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage A default value for an array argument must be an array.
     */
    public function testSetDefaultWithArrayArgument()
    {
        $argument = new InputArgument('foo', InputArgument::IS_ARRAY);
        $argument->setDefault('default');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Tester;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Output\Output;
use Symfony\Component\Console\Tester\CommandTester;

class CommandTesterTest extends \PHPUnit_Framework_TestCase
{
    protected $command;
    protected $tester;

    protected function setUp()
    {
        $this->command = new Command('foo');
        $this->command->addArgument('command');
        $this->command->addArgument('foo');
        $this->command->setCode(function ($input, $output) { $output->writeln('foo'); });

        $this->tester = new CommandTester($this->command);
        $this->tester->execute(array('foo' => 'bar'), array('interactive' => false, 'decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE));
    }

    protected function tearDown()
    {
        $this->command = null;
        $this->tester = null;
    }

    public function testExecute()
    {
        $this->assertFalse($this->tester->getInput()->isInteractive(), '->execute() takes an interactive option');
        $this->assertFalse($this->tester->getOutput()->isDecorated(), '->execute() takes a decorated option');
        $this->assertEquals(Output::VERBOSITY_VERBOSE, $this->tester->getOutput()->getVerbosity(), '->execute() takes a verbosity option');
    }

    public function testGetInput()
    {
        $this->assertEquals('bar', $this->tester->getInput()->getArgument('foo'), '->getInput() returns the current input instance');
    }

    public function testGetOutput()
    {
        rewind($this->tester->getOutput()->getStream());
        $this->assertEquals('foo'.PHP_EOL, stream_get_contents($this->tester->getOutput()->getStream()), '->getOutput() returns the current output instance');
    }

    public function testGetDisplay()
    {
        $this->assertEquals('foo'.PHP_EOL, $this->tester->getDisplay(), '->getDisplay() returns the display of the last execution');
    }

    public function testGetStatusCode()
    {
        $this->assertSame(0, $this->tester->getStatusCode(), '->getStatusCode() returns the status code');
    }

    public function testCommandFromApplication()
    {
        $application = new Application();
        $application->setAutoExit(false);

        $command = new Command('foo');
        $command->setCode(function ($input, $output) { $output->writeln('foo'); });

        $application->add($command);

        $tester = new CommandTester($application->find('foo'));

        // check that there is no need to pass the command name here
        $this->assertEquals(0, $tester->execute(array()));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Tester;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Output\Output;
use Symfony\Component\Console\Tester\ApplicationTester;

class ApplicationTesterTest extends \PHPUnit_Framework_TestCase
{
    protected $application;
    protected $tester;

    protected function setUp()
    {
        $this->application = new Application();
        $this->application->setAutoExit(false);
        $this->application->register('foo')
            ->addArgument('foo')
            ->setCode(function ($input, $output) { $output->writeln('foo'); })
        ;

        $this->tester = new ApplicationTester($this->application);
        $this->tester->run(array('command' => 'foo', 'foo' => 'bar'), array('interactive' => false, 'decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE));
    }

    protected function tearDown()
    {
        $this->application = null;
        $this->tester = null;
    }

    public function testRun()
    {
        $this->assertFalse($this->tester->getInput()->isInteractive(), '->execute() takes an interactive option');
        $this->assertFalse($this->tester->getOutput()->isDecorated(), '->execute() takes a decorated option');
        $this->assertEquals(Output::VERBOSITY_VERBOSE, $this->tester->getOutput()->getVerbosity(), '->execute() takes a verbosity option');
    }

    public function testGetInput()
    {
        $this->assertEquals('bar', $this->tester->getInput()->getArgument('foo'), '->getInput() returns the current input instance');
    }

    public function testGetOutput()
    {
        rewind($this->tester->getOutput()->getStream());
        $this->assertEquals('foo'.PHP_EOL, stream_get_contents($this->tester->getOutput()->getStream()), '->getOutput() returns the current output instance');
    }

    public function testGetDisplay()
    {
        $this->assertEquals('foo'.PHP_EOL, $this->tester->getDisplay(), '->getDisplay() returns the display of the last execution');
    }

    public function testGetStatusCode()
    {
        $this->assertSame(0, $this->tester->getStatusCode(), '->getStatusCode() returns the status code');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Helper;

use Symfony\Component\Console\Helper\FormatterHelper;

class FormatterHelperTest extends \PHPUnit_Framework_TestCase
{
    public function testFormatSection()
    {
        $formatter = new FormatterHelper();

        $this->assertEquals(
            '<info>[cli]</info> Some text to display',
            $formatter->formatSection('cli', 'Some text to display'),
            '::formatSection() formats a message in a section'
        );
    }

    public function testFormatBlock()
    {
        $formatter = new FormatterHelper();

        $this->assertEquals(
            '<error> Some text to display </error>',
            $formatter->formatBlock('Some text to display', 'error'),
            '::formatBlock() formats a message in a block'
        );

        $this->assertEquals(
            '<error> Some text to display </error>'."\n" .
            '<error> foo bar              </error>',
            $formatter->formatBlock(array('Some text to display', 'foo bar'), 'error'),
            '::formatBlock() formats a message in a block'
        );

        $this->assertEquals(
            '<error>                        </error>'."\n" .
            '<error>  Some text to display  </error>'."\n" .
            '<error>                        </error>',
            $formatter->formatBlock('Some text to display', 'error', true),
            '::formatBlock() formats a message in a block'
        );
    }

    public function testFormatBlockWithDiacriticLetters()
    {
        if (!extension_loaded('mbstring')) {
            $this->markTestSkipped('This test requires mbstring to work.');
        }

        $formatter = new FormatterHelper();

        $this->assertEquals(
            '<error>                       </error>'."\n" .
            '<error>  Du texte à afficher  </error>'."\n" .
            '<error>                       </error>',
            $formatter->formatBlock('Du texte à afficher', 'error', true),
            '::formatBlock() formats a message in a block'
        );
    }

    public function testFormatBlockLGEscaping()
    {
        $formatter = new FormatterHelper();

        $this->assertEquals(
            '<error>                            </error>'."\n" .
            '<error>  \<info>some info\</info>  </error>'."\n" .
            '<error>                            </error>',
            $formatter->formatBlock('<info>some info</info>', 'error', true),
            '::formatBlock() escapes \'<\' chars'
        );
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Helper;

use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Command\Command;

class HelperSetTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers \Symfony\Component\Console\Helper\HelperSet::__construct
     */
    public function testConstructor()
    {
        $mock_helper = $this->getGenericMockHelper('fake_helper');
        $helperset = new HelperSet(array('fake_helper_alias' => $mock_helper));

        $this->assertEquals($mock_helper, $helperset->get('fake_helper_alias'), '__construct sets given helper to helpers');
        $this->assertTrue($helperset->has('fake_helper_alias'), '__construct sets helper alias for given helper');
    }

    /**
     * @covers \Symfony\Component\Console\Helper\HelperSet::set
     */
    public function testSet()
    {
        $helperset = new HelperSet();
        $helperset->set($this->getGenericMockHelper('fake_helper', $helperset));
        $this->assertTrue($helperset->has('fake_helper'), '->set() adds helper to helpers');

        $helperset = new HelperSet();
        $helperset->set($this->getGenericMockHelper('fake_helper_01', $helperset));
        $helperset->set($this->getGenericMockHelper('fake_helper_02', $helperset));
        $this->assertTrue($helperset->has('fake_helper_01'), '->set() will set multiple helpers on consecutive calls');
        $this->assertTrue($helperset->has('fake_helper_02'), '->set() will set multiple helpers on consecutive calls');

        $helperset = new HelperSet();
        $helperset->set($this->getGenericMockHelper('fake_helper', $helperset), 'fake_helper_alias');
        $this->assertTrue($helperset->has('fake_helper'), '->set() adds helper alias when set');
        $this->assertTrue($helperset->has('fake_helper_alias'), '->set() adds helper alias when set');
    }

    /**
     * @covers \Symfony\Component\Console\Helper\HelperSet::has
     */
    public function testHas()
    {
        $helperset = new HelperSet(array('fake_helper_alias' => $this->getGenericMockHelper('fake_helper')));
        $this->assertTrue($helperset->has('fake_helper'), '->has() finds set helper');
        $this->assertTrue($helperset->has('fake_helper_alias'), '->has() finds set helper by alias');
    }

    /**
     * @covers \Symfony\Component\Console\Helper\HelperSet::get
     */
    public function testGet()
    {
        $helper_01 = $this->getGenericMockHelper('fake_helper_01');
        $helper_02 = $this->getGenericMockHelper('fake_helper_02');
        $helperset = new HelperSet(array('fake_helper_01_alias' => $helper_01, 'fake_helper_02_alias' => $helper_02));
        $this->assertEquals($helper_01, $helperset->get('fake_helper_01'), '->get() returns correct helper by name');
        $this->assertEquals($helper_01, $helperset->get('fake_helper_01_alias'), '->get() returns correct helper by alias');
        $this->assertEquals($helper_02, $helperset->get('fake_helper_02'), '->get() returns correct helper by name');
        $this->assertEquals($helper_02, $helperset->get('fake_helper_02_alias'), '->get() returns correct helper by alias');

        $helperset = new HelperSet();
        try {
            $helperset->get('foo');
            $this->fail('->get() throws \InvalidArgumentException when helper not found');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->get() throws \InvalidArgumentException when helper not found');
            $this->assertContains('The helper "foo" is not defined.', $e->getMessage(), '->get() throws \InvalidArgumentException when helper not found');
        }
    }

    /**
     * @covers \Symfony\Component\Console\Helper\HelperSet::setCommand
     */
    public function testSetCommand()
    {
        $cmd_01 = new Command('foo');
        $cmd_02 = new Command('bar');

        $helperset = new HelperSet();
        $helperset->setCommand($cmd_01);
        $this->assertEquals($cmd_01, $helperset->getCommand(), '->setCommand() stores given command');

        $helperset = new HelperSet();
        $helperset->setCommand($cmd_01);
        $helperset->setCommand($cmd_02);
        $this->assertEquals($cmd_02, $helperset->getCommand(), '->setCommand() overwrites stored command with consecutive calls');
    }

    /**
     * @covers \Symfony\Component\Console\Helper\HelperSet::getCommand
     */
    public function testGetCommand()
    {
        $cmd = new Command('foo');
        $helperset = new HelperSet();
        $helperset->setCommand($cmd);
        $this->assertEquals($cmd, $helperset->getCommand(), '->getCommand() retrieves stored command');
    }

    /**
     * @covers \Symfony\Component\Console\Helper\HelperSet::getIterator
     */
    public function testIteration()
    {
        $helperset = new HelperSet();
        $helperset->set($this->getGenericMockHelper('fake_helper_01', $helperset));
        $helperset->set($this->getGenericMockHelper('fake_helper_02', $helperset));

        $helpers = array('fake_helper_01', 'fake_helper_02');
        $i = 0;

        foreach ($helperset as $helper) {
            $this->assertEquals($helpers[$i++], $helper->getName());
        }
    }

   /**
     * Create a generic mock for the helper interface. Optionally check for a call to setHelperSet with a specific
     * helperset instance.
     *
     * @param string    $name
     * @param HelperSet $helperset allows a mock to verify a particular helperset set is being added to the Helper
     */
    private function getGenericMockHelper($name, HelperSet $helperset = null)
    {
        $mock_helper = $this->getMock('\Symfony\Component\Console\Helper\HelperInterface');
        $mock_helper->expects($this->any())
            ->method('getName')
            ->will($this->returnValue($name));

        if ($helperset) {
            $mock_helper->expects($this->any())
                ->method('setHelperSet')
                ->with($this->equalTo($helperset));
        }

        return $mock_helper;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Helper;

use Symfony\Component\Console\Helper\ProgressHelper;
use Symfony\Component\Console\Output\StreamOutput;

class ProgressHelperTest extends \PHPUnit_Framework_TestCase
{
    public function testAdvance()
    {
        $progress = new ProgressHelper();
        $progress->start($output = $this->getOutputStream());
        $progress->advance();

        rewind($output->getStream());
        $this->assertEquals($this->generateOutput('    1 [->--------------------------]'), stream_get_contents($output->getStream()));
    }

    public function testAdvanceWithStep()
    {
        $progress = new ProgressHelper();
        $progress->start($output = $this->getOutputStream());
        $progress->advance(5);

        rewind($output->getStream());
        $this->assertEquals($this->generateOutput('    5 [----->----------------------]'), stream_get_contents($output->getStream()));
    }

    public function testAdvanceMultipleTimes()
    {
        $progress = new ProgressHelper();
        $progress->start($output = $this->getOutputStream());
        $progress->advance(3);
        $progress->advance(2);

        rewind($output->getStream());
        $this->assertEquals($this->generateOutput('    3 [--->------------------------]').$this->generateOutput('    5 [----->----------------------]'), stream_get_contents($output->getStream()));
    }

    public function testCustomizations()
    {
        $progress = new ProgressHelper();
        $progress->setBarWidth(10);
        $progress->setBarCharacter('_');
        $progress->setEmptyBarCharacter(' ');
        $progress->setProgressCharacter('/');
        $progress->setFormat(' %current%/%max% [%bar%] %percent%%');
        $progress->start($output = $this->getOutputStream(), 10);
        $progress->advance();

        rewind($output->getStream());
        $this->assertEquals($this->generateOutput('  1/10 [_/        ]  10%'), stream_get_contents($output->getStream()));
    }

    public function testPercent()
    {
        $progress = new ProgressHelper();
        $progress->start($output = $this->getOutputStream(), 50);
        $progress->display();
        $progress->advance();
        $progress->advance();

        rewind($output->getStream());
        $this->assertEquals($this->generateOutput('  0/50 [>---------------------------]   0%').$this->generateOutput('  1/50 [>---------------------------]   2%').$this->generateOutput('  2/50 [=>--------------------------]   4%'), stream_get_contents($output->getStream()));
    }

    public function testOverwriteWithShorterLine()
    {
        $progress = new ProgressHelper();
        $progress->setFormat(' %current%/%max% [%bar%] %percent%%');
        $progress->start($output = $this->getOutputStream(), 50);
        $progress->display();
        $progress->advance();

        // set shorter format
        $progress->setFormat(' %current%/%max% [%bar%]');
        $progress->advance();

        rewind($output->getStream());
        $this->assertEquals(
            $this->generateOutput('  0/50 [>---------------------------]   0%') .
            $this->generateOutput('  1/50 [>---------------------------]   2%') .
            $this->generateOutput('  2/50 [=>--------------------------]     '),
            stream_get_contents($output->getStream())
        );
    }

    public function testSetCurrentProgress()
    {
        $progress = new ProgressHelper();
        $progress->start($output = $this->getOutputStream(), 50);
        $progress->display();
        $progress->advance();
        $progress->setCurrent(15);
        $progress->setCurrent(25);

        rewind($output->getStream());
        $this->assertEquals(
            $this->generateOutput('  0/50 [>---------------------------]   0%') .
            $this->generateOutput('  1/50 [>---------------------------]   2%') .
            $this->generateOutput(' 15/50 [========>-------------------]  30%') .
            $this->generateOutput(' 25/50 [==============>-------------]  50%'),
            stream_get_contents($output->getStream())
        );
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage You must start the progress bar
     */
    public function testSetCurrentBeforeStarting()
    {
        $progress = new ProgressHelper();
        $progress->setCurrent(15);
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage You can't regress the progress bar
     */
    public function testRegressProgress()
    {
        $progress = new ProgressHelper();
        $progress->start($output = $this->getOutputStream(), 50);
        $progress->setCurrent(15);
        $progress->setCurrent(10);
    }

    public function testRedrawFrequency()
    {
        $progress = $this->getMock('Symfony\Component\Console\Helper\ProgressHelper', array('display'));
        $progress->expects($this->exactly(4))
                 ->method('display');

        $progress->setRedrawFrequency(2);

        $progress->start($output = $this->getOutputStream(), 6);
        $progress->setCurrent(1);
        $progress->advance(2);
        $progress->advance(2);
        $progress->advance(1);
    }

    public function testMultiByteSupport()
    {
        if (!function_exists('mb_strlen') || (false === $encoding = mb_detect_encoding('■'))) {
            $this->markTestSkipped('The mbstring extension is needed for multi-byte support');
        }

        $progress = new ProgressHelper();
        $progress->start($output = $this->getOutputStream());
        $progress->setBarCharacter('■');
        $progress->advance(3);

        rewind($output->getStream());
        $this->assertEquals($this->generateOutput('    3 [■■■>------------------------]'), stream_get_contents($output->getStream()));
    }

    public function testClear()
    {
        $progress = new ProgressHelper();
        $progress->start($output = $this->getOutputStream(), 50);
        $progress->setCurrent(25);
        $progress->clear();

        rewind($output->getStream());
        $this->assertEquals(
            $this->generateOutput(' 25/50 [==============>-------------]  50%') . $this->generateOutput(''),
            stream_get_contents($output->getStream())
        );
    }

    public function testPercentNotHundredBeforeComplete()
    {
        $progress = new ProgressHelper();
        $progress->start($output = $this->getOutputStream(), 200);
        $progress->display();
        $progress->advance(199);
        $progress->advance();

        rewind($output->getStream());
        $this->assertEquals($this->generateOutput('   0/200 [>---------------------------]   0%').$this->generateOutput(' 199/200 [===========================>]  99%').$this->generateOutput(' 200/200 [============================] 100%'), stream_get_contents($output->getStream()));
    }

    protected function getOutputStream()
    {
        return new StreamOutput(fopen('php://memory', 'r+', false));
    }

    protected $lastMessagesLength;

    protected function generateOutput($expected)
    {
        $expectedout = $expected;

        if ($this->lastMessagesLength !== null) {
            $expectedout = str_pad($expected, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
        }

        $this->lastMessagesLength = strlen($expectedout);

        return "\x0D".$expectedout;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Helper;

use Symfony\Component\Console\Helper\TableHelper;
use Symfony\Component\Console\Output\StreamOutput;

class TableHelperTest extends \PHPUnit_Framework_TestCase
{
    protected $stream;

    protected function setUp()
    {
        $this->stream = fopen('php://memory', 'r+');
    }

    protected function tearDown()
    {
        fclose($this->stream);
        $this->stream = null;
    }

    /**
     * @dataProvider testRenderProvider
     */
    public function testRender($headers, $rows, $layout, $expected)
    {
        $table = new TableHelper();
        $table
            ->setHeaders($headers)
            ->setRows($rows)
            ->setLayout($layout)
        ;
        $table->render($output = $this->getOutputStream());

        $this->assertEquals($expected, $this->getOutputContent($output));
    }

    /**
     * @dataProvider testRenderProvider
     */
    public function testRenderAddRows($headers, $rows, $layout, $expected)
    {
        $table = new TableHelper();
        $table
            ->setHeaders($headers)
            ->addRows($rows)
            ->setLayout($layout)
        ;
        $table->render($output = $this->getOutputStream());

        $this->assertEquals($expected, $this->getOutputContent($output));
    }

    /**
     * @dataProvider testRenderProvider
     */
    public function testRenderAddRowsOneByOne($headers, $rows, $layout, $expected)
    {
        $table = new TableHelper();
        $table
            ->setHeaders($headers)
            ->setLayout($layout)
        ;
        foreach ($rows as $row) {
            $table->addRow($row);
        }
        $table->render($output = $this->getOutputStream());

        $this->assertEquals($expected, $this->getOutputContent($output));
    }

    public function testRenderProvider()
    {
        $books = array(
            array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'),
            array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'),
            array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'),
            array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'),
        );

        return array(
            array(
                array('ISBN', 'Title', 'Author'),
                $books,
                TableHelper::LAYOUT_DEFAULT,
<<<TABLE
+---------------+--------------------------+------------------+
| ISBN          | Title                    | Author           |
+---------------+--------------------------+------------------+
| 99921-58-10-7 | Divine Comedy            | Dante Alighieri  |
| 9971-5-0210-0 | A Tale of Two Cities     | Charles Dickens  |
| 960-425-059-0 | The Lord of the Rings    | J. R. R. Tolkien |
| 80-902734-1-6 | And Then There Were None | Agatha Christie  |
+---------------+--------------------------+------------------+

TABLE
            ),
            array(
                array('ISBN', 'Title', 'Author'),
                $books,
                TableHelper::LAYOUT_COMPACT,
<<<TABLE
 ISBN          Title                    Author           
 99921-58-10-7 Divine Comedy            Dante Alighieri  
 9971-5-0210-0 A Tale of Two Cities     Charles Dickens  
 960-425-059-0 The Lord of the Rings    J. R. R. Tolkien 
 80-902734-1-6 And Then There Were None Agatha Christie  

TABLE
            ),
            array(
                array('ISBN', 'Title', 'Author'),
                $books,
                TableHelper::LAYOUT_BORDERLESS,
<<<TABLE
 =============== ========================== ================== 
  ISBN            Title                      Author            
 =============== ========================== ================== 
  99921-58-10-7   Divine Comedy              Dante Alighieri   
  9971-5-0210-0   A Tale of Two Cities       Charles Dickens   
  960-425-059-0   The Lord of the Rings      J. R. R. Tolkien  
  80-902734-1-6   And Then There Were None   Agatha Christie   
 =============== ========================== ================== 

TABLE
            ),
            array(
                array('ISBN', 'Title'),
                array(
                    array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'),
                    array('9971-5-0210-0'),
                    array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'),
                    array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'),
                ),
                TableHelper::LAYOUT_DEFAULT,
<<<TABLE
+---------------+--------------------------+------------------+
| ISBN          | Title                    |                  |
+---------------+--------------------------+------------------+
| 99921-58-10-7 | Divine Comedy            | Dante Alighieri  |
| 9971-5-0210-0 |                          |                  |
| 960-425-059-0 | The Lord of the Rings    | J. R. R. Tolkien |
| 80-902734-1-6 | And Then There Were None | Agatha Christie  |
+---------------+--------------------------+------------------+

TABLE
            ),
            array(
                array(),
                array(
                    array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'),
                    array('9971-5-0210-0'),
                    array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'),
                    array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'),
                ),
                TableHelper::LAYOUT_DEFAULT,
<<<TABLE
+---------------+--------------------------+------------------+
| 99921-58-10-7 | Divine Comedy            | Dante Alighieri  |
| 9971-5-0210-0 |                          |                  |
| 960-425-059-0 | The Lord of the Rings    | J. R. R. Tolkien |
| 80-902734-1-6 | And Then There Were None | Agatha Christie  |
+---------------+--------------------------+------------------+

TABLE
            ),
            array(
                array('ISBN', 'Title'),
                array(),
                TableHelper::LAYOUT_DEFAULT,
<<<TABLE
+------+-------+
| ISBN | Title |
+------+-------+

TABLE
            ),
            array(
                array(),
                array(),
                TableHelper::LAYOUT_DEFAULT,
                '',
            ),
        );
    }

    public function testRenderMultiByte()
    {
        if (!function_exists('mb_strlen')) {
            $this->markTestSkipped('The "mbstring" extension is not available');
        }

        $table = new TableHelper();
        $table
            ->setHeaders(array('■■'))
            ->setRows(array(array(1234)))
            ->setLayout(TableHelper::LAYOUT_DEFAULT)
        ;
        $table->render($output = $this->getOutputStream());

        $expected =
<<<TABLE
+------+
| ■■   |
+------+
| 1234 |
+------+

TABLE;

        $this->assertEquals($expected, $this->getOutputContent($output));
    }

    protected function getOutputStream()
    {
        return new StreamOutput($this->stream, StreamOutput::VERBOSITY_NORMAL, false);
    }

    protected function getOutputContent(StreamOutput $output)
    {
        rewind($output->getStream());

        return str_replace(PHP_EOL, "\n", stream_get_contents($output->getStream()));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Helper;

use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Helper\DialogHelper;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Helper\FormatterHelper;
use Symfony\Component\Console\Output\StreamOutput;

class DialogHelperTest extends \PHPUnit_Framework_TestCase
{
    public function testSelect()
    {
        $dialog = new DialogHelper();

        $helperSet = new HelperSet(array(new FormatterHelper()));
        $dialog->setHelperSet($helperSet);

        $heroes = array('Superman', 'Batman', 'Spiderman');

        $dialog->setInputStream($this->getInputStream("\n1\n  1  \nFabien\n1\nFabien\n1\n0,2\n 0 , 2  \n\n\n"));
        $this->assertEquals('2', $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes, '2'));
        $this->assertEquals('1', $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes));
        $this->assertEquals('1', $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes));
        $this->assertEquals('1', $dialog->select($output = $this->getOutputStream(), 'What is your favorite superhero?', $heroes, null, false, 'Input "%s" is not a superhero!', false));

        rewind($output->getStream());
        $this->assertContains('Input "Fabien" is not a superhero!', stream_get_contents($output->getStream()));

        try {
            $this->assertEquals('1', $dialog->select($output = $this->getOutputStream(), 'What is your favorite superhero?', $heroes, null, 1));
            $this->fail();
        } catch (\InvalidArgumentException $e) {
            $this->assertEquals('Value "Fabien" is invalid', $e->getMessage());
        }

        $this->assertEquals(array('1'), $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes, null, false, 'Input "%s" is not a superhero!', true));
        $this->assertEquals(array('0', '2'), $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes, null, false, 'Input "%s" is not a superhero!', true));
        $this->assertEquals(array('0', '2'), $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes, null, false, 'Input "%s" is not a superhero!', true));
        $this->assertEquals(array('0', '1'), $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes, '0,1', false, 'Input "%s" is not a superhero!', true));
        $this->assertEquals(array('0', '1'), $dialog->select($this->getOutputStream(), 'What is your favorite superhero?', $heroes, ' 0 , 1 ', false, 'Input "%s" is not a superhero!', true));
    }

    public function testAsk()
    {
        $dialog = new DialogHelper();

        $dialog->setInputStream($this->getInputStream("\n8AM\n"));

        $this->assertEquals('2PM', $dialog->ask($this->getOutputStream(), 'What time is it?', '2PM'));
        $this->assertEquals('8AM', $dialog->ask($output = $this->getOutputStream(), 'What time is it?', '2PM'));

        rewind($output->getStream());
        $this->assertEquals('What time is it?', stream_get_contents($output->getStream()));
    }

    public function testAskWithAutocomplete()
    {
        if (!$this->hasSttyAvailable()) {
            $this->markTestSkipped('`stty` is required to test autocomplete functionality');
        }

        // Acm<NEWLINE>
        // Ac<BACKSPACE><BACKSPACE>s<TAB>Test<NEWLINE>
        // <NEWLINE>
        // <UP ARROW><UP ARROW><NEWLINE>
        // <UP ARROW><UP ARROW><UP ARROW><UP ARROW><UP ARROW><TAB>Test<NEWLINE>
        // <DOWN ARROW><NEWLINE>
        // S<BACKSPACE><BACKSPACE><DOWN ARROW><DOWN ARROW><NEWLINE>
        // F00<BACKSPACE><BACKSPACE>oo<TAB><NEWLINE>
        $inputStream = $this->getInputStream("Acm\nAc\177\177s\tTest\n\n\033[A\033[A\n\033[A\033[A\033[A\033[A\033[A\tTest\n\033[B\nS\177\177\033[B\033[B\nF00\177\177oo\t\n");

        $dialog = new DialogHelper();
        $dialog->setInputStream($inputStream);

        $bundles = array('AcmeDemoBundle', 'AsseticBundle', 'SecurityBundle', 'FooBundle');

        $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles));
        $this->assertEquals('AsseticBundleTest', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles));
        $this->assertEquals('FrameworkBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles));
        $this->assertEquals('SecurityBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles));
        $this->assertEquals('FooBundleTest', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles));
        $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles));
        $this->assertEquals('AsseticBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles));
        $this->assertEquals('FooBundle', $dialog->ask($this->getOutputStream(), 'Please select a bundle', 'FrameworkBundle', $bundles));
    }

    /**
     * @group tty
     */
    public function testAskHiddenResponse()
    {
        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->markTestSkipped('This test is not supported on Windows');
        }

        $dialog = new DialogHelper();

        $dialog->setInputStream($this->getInputStream("8AM\n"));

        $this->assertEquals('8AM', $dialog->askHiddenResponse($this->getOutputStream(), 'What time is it?'));
    }

    public function testAskConfirmation()
    {
        $dialog = new DialogHelper();

        $dialog->setInputStream($this->getInputStream("\n\n"));
        $this->assertTrue($dialog->askConfirmation($this->getOutputStream(), 'Do you like French fries?'));
        $this->assertFalse($dialog->askConfirmation($this->getOutputStream(), 'Do you like French fries?', false));

        $dialog->setInputStream($this->getInputStream("y\nyes\n"));
        $this->assertTrue($dialog->askConfirmation($this->getOutputStream(), 'Do you like French fries?', false));
        $this->assertTrue($dialog->askConfirmation($this->getOutputStream(), 'Do you like French fries?', false));

        $dialog->setInputStream($this->getInputStream("n\nno\n"));
        $this->assertFalse($dialog->askConfirmation($this->getOutputStream(), 'Do you like French fries?', true));
        $this->assertFalse($dialog->askConfirmation($this->getOutputStream(), 'Do you like French fries?', true));
    }

    public function testAskAndValidate()
    {
        $dialog = new DialogHelper();
        $helperSet = new HelperSet(array(new FormatterHelper()));
        $dialog->setHelperSet($helperSet);

        $question ='What color was the white horse of Henry IV?';
        $error = 'This is not a color!';
        $validator = function ($color) use ($error) {
            if (!in_array($color, array('white', 'black'))) {
                throw new \InvalidArgumentException($error);
            }

            return $color;
        };

        $dialog->setInputStream($this->getInputStream("\nblack\n"));
        $this->assertEquals('white', $dialog->askAndValidate($this->getOutputStream(), $question, $validator, 2, 'white'));
        $this->assertEquals('black', $dialog->askAndValidate($this->getOutputStream(), $question, $validator, 2, 'white'));

        $dialog->setInputStream($this->getInputStream("green\nyellow\norange\n"));
        try {
            $this->assertEquals('white', $dialog->askAndValidate($this->getOutputStream(), $question, $validator, 2, 'white'));
            $this->fail();
        } catch (\InvalidArgumentException $e) {
            $this->assertEquals($error, $e->getMessage());
        }
    }

    public function testNoInteration()
    {
        $dialog = new DialogHelper();

        $input = new ArrayInput(array());
        $input->setInteractive(false);

        $dialog->setInput($input);

        $this->assertEquals('not yet', $dialog->ask($this->getOutputStream(), 'Do you have a job?', 'not yet'));
    }

    protected function getInputStream($input)
    {
        $stream = fopen('php://memory', 'r+', false);
        fputs($stream, $input);
        rewind($stream);

        return $stream;
    }

    protected function getOutputStream()
    {
        return new StreamOutput(fopen('php://memory', 'r+', false));
    }

    private function hasSttyAvailable()
    {
        exec('stty 2>&1', $output, $exitcode);

        return $exitcode === 0;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Formatter;

use Symfony\Component\Console\Formatter\OutputFormatterStyle;

class OutputFormatterStyleTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructor()
    {
        $style = new OutputFormatterStyle('green', 'black', array('bold', 'underscore'));
        $this->assertEquals("\033[32;40;1;4mfoo\033[0m", $style->apply('foo'));

        $style = new OutputFormatterStyle('red', null, array('blink'));
        $this->assertEquals("\033[31;5mfoo\033[0m", $style->apply('foo'));

        $style = new OutputFormatterStyle(null, 'white');
        $this->assertEquals("\033[47mfoo\033[0m", $style->apply('foo'));
    }

    public function testForeground()
    {
        $style = new OutputFormatterStyle();

        $style->setForeground('black');
        $this->assertEquals("\033[30mfoo\033[0m", $style->apply('foo'));

        $style->setForeground('blue');
        $this->assertEquals("\033[34mfoo\033[0m", $style->apply('foo'));

        $this->setExpectedException('InvalidArgumentException');
        $style->setForeground('undefined-color');
    }

    public function testBackground()
    {
        $style = new OutputFormatterStyle();

        $style->setBackground('black');
        $this->assertEquals("\033[40mfoo\033[0m", $style->apply('foo'));

        $style->setBackground('yellow');
        $this->assertEquals("\033[43mfoo\033[0m", $style->apply('foo'));

        $this->setExpectedException('InvalidArgumentException');
        $style->setBackground('undefined-color');
    }

    public function testOptions()
    {
        $style = new OutputFormatterStyle();

        $style->setOptions(array('reverse', 'conceal'));
        $this->assertEquals("\033[7;8mfoo\033[0m", $style->apply('foo'));

        $style->setOption('bold');
        $this->assertEquals("\033[7;8;1mfoo\033[0m", $style->apply('foo'));

        $style->unsetOption('reverse');
        $this->assertEquals("\033[8;1mfoo\033[0m", $style->apply('foo'));

        $style->setOption('bold');
        $this->assertEquals("\033[8;1mfoo\033[0m", $style->apply('foo'));

        $style->setOptions(array('bold'));
        $this->assertEquals("\033[1mfoo\033[0m", $style->apply('foo'));

        try {
            $style->setOption('foo');
            $this->fail('->setOption() throws an \InvalidArgumentException when the option does not exist in the available options');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->setOption() throws an \InvalidArgumentException when the option does not exist in the available options');
            $this->assertContains('Invalid option specified: "foo"', $e->getMessage(), '->setOption() throws an \InvalidArgumentException when the option does not exist in the available options');
        }

        try {
            $style->unsetOption('foo');
            $this->fail('->unsetOption() throws an \InvalidArgumentException when the option does not exist in the available options');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->unsetOption() throws an \InvalidArgumentException when the option does not exist in the available options');
            $this->assertContains('Invalid option specified: "foo"', $e->getMessage(), '->unsetOption() throws an \InvalidArgumentException when the option does not exist in the available options');
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Formatter;

use Symfony\Component\Console\Formatter\OutputFormatterStyleStack;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;

class OutputFormatterStyleStackTest extends \PHPUnit_Framework_TestCase
{
    public function testPush()
    {
        $stack = new OutputFormatterStyleStack();
        $stack->push($s1 = new OutputFormatterStyle('white', 'black'));
        $stack->push($s2 = new OutputFormatterStyle('yellow', 'blue'));

        $this->assertEquals($s2, $stack->getCurrent());

        $stack->push($s3 = new OutputFormatterStyle('green', 'red'));

        $this->assertEquals($s3, $stack->getCurrent());
    }

    public function testPop()
    {
        $stack = new OutputFormatterStyleStack();
        $stack->push($s1 = new OutputFormatterStyle('white', 'black'));
        $stack->push($s2 = new OutputFormatterStyle('yellow', 'blue'));

        $this->assertEquals($s2, $stack->pop());
        $this->assertEquals($s1, $stack->pop());
    }

    public function testPopEmpty()
    {
        $stack = new OutputFormatterStyleStack();
        $style = new OutputFormatterStyle();

        $this->assertEquals($style, $stack->pop());
    }

    public function testPopNotLast()
    {
        $stack = new OutputFormatterStyleStack();
        $stack->push($s1 = new OutputFormatterStyle('white', 'black'));
        $stack->push($s2 = new OutputFormatterStyle('yellow', 'blue'));
        $stack->push($s3 = new OutputFormatterStyle('green', 'red'));

        $this->assertEquals($s2, $stack->pop($s2));
        $this->assertEquals($s1, $stack->pop());
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testInvalidPop()
    {
        $stack = new OutputFormatterStyleStack();
        $stack->push(new OutputFormatterStyle('white', 'black'));
        $stack->pop(new OutputFormatterStyle('yellow', 'blue'));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests\Formatter;

use Symfony\Component\Console\Formatter\OutputFormatter;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;

class FormatterStyleTest extends \PHPUnit_Framework_TestCase
{
    public function testEmptyTag()
    {
        $formatter = new OutputFormatter(true);
        $this->assertEquals("foo<>bar", $formatter->format('foo<>bar'));
    }

    public function testLGCharEscaping()
    {
        $formatter = new OutputFormatter(true);

        $this->assertEquals("foo<bar", $formatter->format('foo\\<bar'));
        $this->assertEquals("<info>some info</info>", $formatter->format('\\<info>some info\\</info>'));
        $this->assertEquals("\\<info>some info\\</info>", OutputFormatter::escape('<info>some info</info>'));

        $this->assertEquals(
            "\033[33mSymfony\\Component\\Console does work very well!\033[0m",
            $formatter->format('<comment>Symfony\Component\Console does work very well!</comment>')
        );
    }

    public function testBundledStyles()
    {
        $formatter = new OutputFormatter(true);

        $this->assertTrue($formatter->hasStyle('error'));
        $this->assertTrue($formatter->hasStyle('info'));
        $this->assertTrue($formatter->hasStyle('comment'));
        $this->assertTrue($formatter->hasStyle('question'));

        $this->assertEquals(
            "\033[37;41msome error\033[0m",
            $formatter->format('<error>some error</error>')
        );
        $this->assertEquals(
            "\033[32msome info\033[0m",
            $formatter->format('<info>some info</info>')
        );
        $this->assertEquals(
            "\033[33msome comment\033[0m",
            $formatter->format('<comment>some comment</comment>')
        );
        $this->assertEquals(
            "\033[30;46msome question\033[0m",
            $formatter->format('<question>some question</question>')
        );
    }

    public function testNestedStyles()
    {
        $formatter = new OutputFormatter(true);

        $this->assertEquals(
            "\033[37;41msome \033[0m\033[32msome info\033[0m\033[37;41m error\033[0m",
            $formatter->format('<error>some <info>some info</info> error</error>')
        );
    }

    public function testStyleMatchingNotGreedy()
    {
        $formatter = new OutputFormatter(true);

        $this->assertEquals(
            "(\033[32m>=2.0,<2.3\033[0m)",
            $formatter->format('(<info>>=2.0,<2.3</info>)')
        );
    }

    public function testStyleEscaping()
    {
        $formatter = new OutputFormatter(true);

        $this->assertEquals(
            "(\033[32mz>=2.0,<a2.3\033[0m)",
            $formatter->format('(<info>'.$formatter->escape('z>=2.0,<a2.3').'</info>)')
        );
    }

    public function testDeepNestedStyles()
    {
        $formatter = new OutputFormatter(true);

        $this->assertEquals(
            "\033[37;41merror\033[0m\033[32minfo\033[0m\033[33mcomment\033[0m\033[37;41merror\033[0m",
            $formatter->format('<error>error<info>info<comment>comment</info>error</error>')
        );
    }

    public function testNewStyle()
    {
        $formatter = new OutputFormatter(true);

        $style = new OutputFormatterStyle('blue', 'white');
        $formatter->setStyle('test', $style);

        $this->assertEquals($style, $formatter->getStyle('test'));
        $this->assertNotEquals($style, $formatter->getStyle('info'));

        $style = new OutputFormatterStyle('blue', 'white');
        $formatter->setStyle('b', $style);

        $this->assertEquals("\033[34;47msome \033[0m\033[34;47mcustom\033[0m\033[34;47m msg\033[0m", $formatter->format('<test>some <b>custom</b> msg</test>'));
    }

    public function testRedefineStyle()
    {
        $formatter = new OutputFormatter(true);

        $style = new OutputFormatterStyle('blue', 'white');
        $formatter->setStyle('info', $style);

        $this->assertEquals("\033[34;47msome custom msg\033[0m", $formatter->format('<info>some custom msg</info>'));
    }

    public function testInlineStyle()
    {
        $formatter = new OutputFormatter(true);

        $this->assertEquals("\033[34;41msome text\033[0m", $formatter->format('<fg=blue;bg=red>some text</>'));
        $this->assertEquals("\033[34;41msome text\033[0m", $formatter->format('<fg=blue;bg=red>some text</fg=blue;bg=red>'));
    }

    public function testNonStyleTag()
    {
        $formatter = new OutputFormatter(true);
        $this->assertEquals("\033[32msome \033[0m\033[32m<tag> styled \033[0m\033[32m<p>single-char tag\033[0m\033[32m</p>\033[0m", $formatter->format('<info>some <tag> styled <p>single-char tag</p></info>'));
    }

    public function testNotDecoratedFormatter()
    {
        $formatter = new OutputFormatter(false);

        $this->assertTrue($formatter->hasStyle('error'));
        $this->assertTrue($formatter->hasStyle('info'));
        $this->assertTrue($formatter->hasStyle('comment'));
        $this->assertTrue($formatter->hasStyle('question'));

        $this->assertEquals(
            "some error", $formatter->format('<error>some error</error>')
        );
        $this->assertEquals(
            "some info", $formatter->format('<info>some info</info>')
        );
        $this->assertEquals(
            "some comment", $formatter->format('<comment>some comment</comment>')
        );
        $this->assertEquals(
            "some question", $formatter->format('<question>some question</question>')
        );

        $formatter->setDecorated(true);

        $this->assertEquals(
            "\033[37;41msome error\033[0m", $formatter->format('<error>some error</error>')
        );
        $this->assertEquals(
            "\033[32msome info\033[0m", $formatter->format('<info>some info</info>')
        );
        $this->assertEquals(
            "\033[33msome comment\033[0m", $formatter->format('<comment>some comment</comment>')
        );
        $this->assertEquals(
            "\033[30;46msome question\033[0m", $formatter->format('<question>some question</question>')
        );
    }

    public function testContentWithLineBreaks()
    {
        $formatter = new OutputFormatter(true);

        $this->assertEquals(<<<EOF
\033[32m
some text\033[0m
EOF
            , $formatter->format(<<<EOF
<info>
some text</info>
EOF
        ));

        $this->assertEquals(<<<EOF
\033[32msome text
\033[0m
EOF
            , $formatter->format(<<<EOF
<info>some text
</info>
EOF
        ));

        $this->assertEquals(<<<EOF
\033[32m
some text
\033[0m
EOF
            , $formatter->format(<<<EOF
<info>
some text
</info>
EOF
        ));

        $this->assertEquals(<<<EOF
\033[32m
some text
more text
\033[0m
EOF
            , $formatter->format(<<<EOF
<info>
some text
more text
</info>
EOF
        ));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console\Tests;

use Symfony\Component\Console\Application;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Helper\FormatterHelper;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Output\Output;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\StreamOutput;
use Symfony\Component\Console\Tester\ApplicationTester;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\Event\ConsoleExceptionEvent;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\EventDispatcher\EventDispatcher;

class ApplicationTest extends \PHPUnit_Framework_TestCase
{
    protected static $fixturesPath;

    public static function setUpBeforeClass()
    {
        self::$fixturesPath = realpath(__DIR__.'/Fixtures/');
        require_once self::$fixturesPath.'/FooCommand.php';
        require_once self::$fixturesPath.'/Foo1Command.php';
        require_once self::$fixturesPath.'/Foo2Command.php';
        require_once self::$fixturesPath.'/Foo3Command.php';
        require_once self::$fixturesPath.'/Foo4Command.php';
        require_once self::$fixturesPath.'/Foo5Command.php';
        require_once self::$fixturesPath.'/FoobarCommand.php';
        require_once self::$fixturesPath.'/BarBucCommand.php';
    }

    protected function normalizeLineBreaks($text)
    {
        return str_replace(PHP_EOL, "\n", $text);
    }

    /**
     * Replaces the dynamic placeholders of the command help text with a static version.
     * The placeholder %command.full_name% includes the script path that is not predictable
     * and can not be tested against.
     */
    protected function ensureStaticCommandHelp(Application $application)
    {
        foreach ($application->all() as $command) {
            $command->setHelp(str_replace('%command.full_name%', 'app/console %command.name%', $command->getHelp()));
        }
    }

    public function testConstructor()
    {
        $application = new Application('foo', 'bar');
        $this->assertEquals('foo', $application->getName(), '__construct() takes the application name as its first argument');
        $this->assertEquals('bar', $application->getVersion(), '__construct() takes the application version as its second argument');
        $this->assertEquals(array('help', 'list'), array_keys($application->all()), '__construct() registered the help and list commands by default');
    }

    public function testSetGetName()
    {
        $application = new Application();
        $application->setName('foo');
        $this->assertEquals('foo', $application->getName(), '->setName() sets the name of the application');
    }

    public function testSetGetVersion()
    {
        $application = new Application();
        $application->setVersion('bar');
        $this->assertEquals('bar', $application->getVersion(), '->setVersion() sets the version of the application');
    }

    public function testGetLongVersion()
    {
        $application = new Application('foo', 'bar');
        $this->assertEquals('<info>foo</info> version <comment>bar</comment>', $application->getLongVersion(), '->getLongVersion() returns the long version of the application');
    }

    public function testHelp()
    {
        $application = new Application();
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_gethelp.txt', $this->normalizeLineBreaks($application->getHelp()), '->setHelp() returns a help message');
    }

    public function testAll()
    {
        $application = new Application();
        $commands = $application->all();
        $this->assertEquals('Symfony\\Component\\Console\\Command\\HelpCommand', get_class($commands['help']), '->all() returns the registered commands');

        $application->add(new \FooCommand());
        $commands = $application->all('foo');
        $this->assertEquals(1, count($commands), '->all() takes a namespace as its first argument');
    }

    public function testRegister()
    {
        $application = new Application();
        $command = $application->register('foo');
        $this->assertEquals('foo', $command->getName(), '->register() registers a new command');
    }

    public function testAdd()
    {
        $application = new Application();
        $application->add($foo = new \FooCommand());
        $commands = $application->all();
        $this->assertEquals($foo, $commands['foo:bar'], '->add() registers a command');

        $application = new Application();
        $application->addCommands(array($foo = new \FooCommand(), $foo1 = new \Foo1Command()));
        $commands = $application->all();
        $this->assertEquals(array($foo, $foo1), array($commands['foo:bar'], $commands['foo:bar1']), '->addCommands() registers an array of commands');
    }

    /**
     * @expectedException \LogicException
     * @expectedExceptionMessage Command class "Foo5Command" is not correctly initialized. You probably forgot to call the parent constructor.
     */
    public function testAddCommandWithEmptyConstructor()
    {
        $application = new Application();
        $application->add(new \Foo5Command());
    }

    public function testHasGet()
    {
        $application = new Application();
        $this->assertTrue($application->has('list'), '->has() returns true if a named command is registered');
        $this->assertFalse($application->has('afoobar'), '->has() returns false if a named command is not registered');

        $application->add($foo = new \FooCommand());
        $this->assertTrue($application->has('afoobar'), '->has() returns true if an alias is registered');
        $this->assertEquals($foo, $application->get('foo:bar'), '->get() returns a command by name');
        $this->assertEquals($foo, $application->get('afoobar'), '->get() returns a command by alias');

        $application = new Application();
        $application->add($foo = new \FooCommand());
        // simulate --help
        $r = new \ReflectionObject($application);
        $p = $r->getProperty('wantHelps');
        $p->setAccessible(true);
        $p->setValue($application, true);
        $command = $application->get('foo:bar');
        $this->assertInstanceOf('Symfony\Component\Console\Command\HelpCommand', $command, '->get() returns the help command if --help is provided as the input');
    }

    public function testSilentHelp()
    {
        $application = new Application();
        $application->setAutoExit(false);
        $application->setCatchExceptions(false);

        $tester = new ApplicationTester($application);
        $tester->run(array('-h' => true, '-q' => true), array('decorated' => false));

        $this->assertEmpty($tester->getDisplay(true));
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The command "foofoo" does not exist.
     */
    public function testGetInvalidCommand()
    {
        $application = new Application();
        $application->get('foofoo');
    }

    public function testGetNamespaces()
    {
        $application = new Application();
        $application->add(new \FooCommand());
        $application->add(new \Foo1Command());
        $this->assertEquals(array('foo'), $application->getNamespaces(), '->getNamespaces() returns an array of unique used namespaces');
    }

    public function testFindNamespace()
    {
        $application = new Application();
        $application->add(new \FooCommand());
        $this->assertEquals('foo', $application->findNamespace('foo'), '->findNamespace() returns the given namespace if it exists');
        $this->assertEquals('foo', $application->findNamespace('f'), '->findNamespace() finds a namespace given an abbreviation');
        $application->add(new \Foo2Command());
        $this->assertEquals('foo', $application->findNamespace('foo'), '->findNamespace() returns the given namespace if it exists');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage The namespace "f" is ambiguous (foo, foo1).
     */
    public function testFindAmbiguousNamespace()
    {
        $application = new Application();
        $application->add(new \BarBucCommand());
        $application->add(new \FooCommand());
        $application->add(new \Foo2Command());
        $application->findNamespace('f');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage There are no commands defined in the "bar" namespace.
     */
    public function testFindInvalidNamespace()
    {
        $application = new Application();
        $application->findNamespace('bar');
    }

    /**
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage Command "foo1" is not defined
     */
    public function testFindUniqueNameButNamespaceName()
    {
        $application = new Application();
        $application->add(new \FooCommand());
        $application->add(new \Foo1Command());
        $application->add(new \Foo2Command());

        $application->find($commandName = 'foo1');
    }

    public function testFind()
    {
        $application = new Application();
        $application->add(new \FooCommand());

        $this->assertInstanceOf('FooCommand', $application->find('foo:bar'), '->find() returns a command if its name exists');
        $this->assertInstanceOf('Symfony\Component\Console\Command\HelpCommand', $application->find('h'), '->find() returns a command if its name exists');
        $this->assertInstanceOf('FooCommand', $application->find('f:bar'), '->find() returns a command if the abbreviation for the namespace exists');
        $this->assertInstanceOf('FooCommand', $application->find('f:b'), '->find() returns a command if the abbreviation for the namespace and the command name exist');
        $this->assertInstanceOf('FooCommand', $application->find('a'), '->find() returns a command if the abbreviation exists for an alias');
    }

    /**
     * @dataProvider provideAmbiguousAbbreviations
     */
    public function testFindWithAmbiguousAbbreviations($abbreviation, $expectedExceptionMessage)
    {
        $this->setExpectedException('InvalidArgumentException', $expectedExceptionMessage);

        $application = new Application();
        $application->add(new \FooCommand());
        $application->add(new \Foo1Command());
        $application->add(new \Foo2Command());

        $application->find($abbreviation);
    }

    public function provideAmbiguousAbbreviations()
    {
        return array(
            array('f', 'Command "f" is not defined.'),
            array('a', 'Command "a" is ambiguous (afoobar, afoobar1 and 1 more).'),
            array('foo:b', 'Command "foo:b" is ambiguous (foo:bar, foo:bar1 and 1 more).')
        );
    }

    public function testFindCommandEqualNamespace()
    {
        $application = new Application();
        $application->add(new \Foo3Command());
        $application->add(new \Foo4Command());

        $this->assertInstanceOf('Foo3Command', $application->find('foo3:bar'), '->find() returns the good command even if a namespace has same name');
        $this->assertInstanceOf('Foo4Command', $application->find('foo3:bar:toh'), '->find() returns a command even if its namespace equals another command name');
    }

    public function testFindCommandWithAmbiguousNamespacesButUniqueName()
    {
        $application = new Application();
        $application->add(new \FooCommand());
        $application->add(new \FoobarCommand());

        $this->assertInstanceOf('FoobarCommand', $application->find('f:f'));
    }

    public function testFindCommandWithMissingNamespace()
    {
        $application = new Application();
        $application->add(new \Foo4Command());

        $this->assertInstanceOf('Foo4Command', $application->find('f::t'));
    }

    /**
     * @dataProvider             provideInvalidCommandNamesSingle
     * @expectedException        \InvalidArgumentException
     * @expectedExceptionMessage Did you mean this
     */
    public function testFindAlternativeExceptionMessageSingle($name)
    {
        $application = new Application();
        $application->add(new \Foo3Command());
        $application->find($name);
    }

    public function provideInvalidCommandNamesSingle()
    {
        return array(
            array('foo3:baR'),
            array('foO3:bar')
        );
    }

    public function testFindAlternativeExceptionMessageMultiple()
    {
        $application = new Application();
        $application->add(new \FooCommand());
        $application->add(new \Foo1Command());
        $application->add(new \Foo2Command());

        // Command + plural
        try {
            $application->find('foo:baR');
            $this->fail('->find() throws an \InvalidArgumentException if command does not exist, with alternatives');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->find() throws an \InvalidArgumentException if command does not exist, with alternatives');
            $this->assertRegExp('/Did you mean one of these/', $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, with alternatives');
            $this->assertRegExp('/foo1:bar/', $e->getMessage());
            $this->assertRegExp('/foo:bar/', $e->getMessage());
        }

        // Namespace + plural
        try {
            $application->find('foo2:bar');
            $this->fail('->find() throws an \InvalidArgumentException if command does not exist, with alternatives');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->find() throws an \InvalidArgumentException if command does not exist, with alternatives');
            $this->assertRegExp('/Did you mean one of these/', $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, with alternatives');
            $this->assertRegExp('/foo1/', $e->getMessage());
        }

        $application->add(new \Foo3Command());
        $application->add(new \Foo4Command());

        // Subnamespace + plural
        try {
            $a = $application->find('foo3:');
            $this->fail('->find() should throw an \InvalidArgumentException if a command is ambiguous because of a subnamespace, with alternatives');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e);
            $this->assertRegExp('/foo3:bar/', $e->getMessage());
            $this->assertRegExp('/foo3:bar:toh/', $e->getMessage());
        }
    }

    public function testFindAlternativeCommands()
    {
        $application = new Application();

        $application->add(new \FooCommand());
        $application->add(new \Foo1Command());
        $application->add(new \Foo2Command());

        try {
            $application->find($commandName = 'Unknown command');
            $this->fail('->find() throws an \InvalidArgumentException if command does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->find() throws an \InvalidArgumentException if command does not exist');
            $this->assertEquals(sprintf('Command "%s" is not defined.', $commandName), $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, without alternatives');
        }

        // Test if "bar1" command throw an "\InvalidArgumentException" and does not contain
        // "foo:bar" as alternative because "bar1" is too far from "foo:bar"
        try {
            $application->find($commandName = 'bar1');
            $this->fail('->find() throws an \InvalidArgumentException if command does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->find() throws an \InvalidArgumentException if command does not exist');
            $this->assertRegExp(sprintf('/Command "%s" is not defined./', $commandName), $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, with alternatives');
            $this->assertRegExp('/afoobar1/', $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, with alternative : "afoobar1"');
            $this->assertRegExp('/foo:bar1/', $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, with alternative : "foo:bar1"');
            $this->assertNotRegExp('/foo:bar(?>!1)/', $e->getMessage(), '->find() throws an \InvalidArgumentException if command does not exist, without "foo:bar" alternative');
        }
    }

    public function testFindAlternativeNamespace()
    {
        $application = new Application();

        $application->add(new \FooCommand());
        $application->add(new \Foo1Command());
        $application->add(new \Foo2Command());
        $application->add(new \foo3Command());

        try {
            $application->find('Unknown-namespace:Unknown-command');
            $this->fail('->find() throws an \InvalidArgumentException if namespace does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->find() throws an \InvalidArgumentException if namespace does not exist');
            $this->assertEquals('There are no commands defined in the "Unknown-namespace" namespace.', $e->getMessage(), '->find() throws an \InvalidArgumentException if namespace does not exist, without alternatives');
        }

        try {
            $application->find('foo2:command');
            $this->fail('->find() throws an \InvalidArgumentException if namespace does not exist');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\InvalidArgumentException', $e, '->find() throws an \InvalidArgumentException if namespace does not exist');
            $this->assertRegExp('/There are no commands defined in the "foo2" namespace./', $e->getMessage(), '->find() throws an \InvalidArgumentException if namespace does not exist, with alternative');
            $this->assertRegExp('/foo/', $e->getMessage(), '->find() throws an \InvalidArgumentException if namespace does not exist, with alternative : "foo"');
            $this->assertRegExp('/foo1/', $e->getMessage(), '->find() throws an \InvalidArgumentException if namespace does not exist, with alternative : "foo1"');
            $this->assertRegExp('/foo3/', $e->getMessage(), '->find() throws an \InvalidArgumentException if namespace does not exist, with alternative : "foo3"');
        }
    }

    public function testFindNamespaceDoesNotFailOnDeepSimilarNamespaces()
    {
        $application = $this->getMock('Symfony\Component\Console\Application', array('getNamespaces'));
        $application->expects($this->once())
            ->method('getNamespaces')
            ->will($this->returnValue(array('foo:sublong', 'bar:sub')));

        $this->assertEquals('foo:sublong', $application->findNamespace('f:sub'));
    }

    public function testSetCatchExceptions()
    {
        $application = $this->getMock('Symfony\Component\Console\Application', array('getTerminalWidth'));
        $application->setAutoExit(false);
        $application->expects($this->any())
            ->method('getTerminalWidth')
            ->will($this->returnValue(120));
        $tester = new ApplicationTester($application);

        $application->setCatchExceptions(true);
        $tester->run(array('command' => 'foo'), array('decorated' => false));
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception1.txt', $tester->getDisplay(true), '->setCatchExceptions() sets the catch exception flag');

        $application->setCatchExceptions(false);
        try {
            $tester->run(array('command' => 'foo'), array('decorated' => false));
            $this->fail('->setCatchExceptions() sets the catch exception flag');
        } catch (\Exception $e) {
            $this->assertInstanceOf('\Exception', $e, '->setCatchExceptions() sets the catch exception flag');
            $this->assertEquals('Command "foo" is not defined.', $e->getMessage(), '->setCatchExceptions() sets the catch exception flag');
        }
    }

    public function testAsText()
    {
        $application = new Application();
        $application->add(new \FooCommand);
        $this->ensureStaticCommandHelp($application);
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_astext1.txt', $this->normalizeLineBreaks($application->asText()), '->asText() returns a text representation of the application');
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_astext2.txt', $this->normalizeLineBreaks($application->asText('foo')), '->asText() returns a text representation of the application');
    }

    public function testAsXml()
    {
        $application = new Application();
        $application->add(new \FooCommand);
        $this->ensureStaticCommandHelp($application);
        $this->assertXmlStringEqualsXmlFile(self::$fixturesPath.'/application_asxml1.txt', $application->asXml(), '->asXml() returns an XML representation of the application');
        $this->assertXmlStringEqualsXmlFile(self::$fixturesPath.'/application_asxml2.txt', $application->asXml('foo'), '->asXml() returns an XML representation of the application');
    }

    public function testRenderException()
    {
        $application = $this->getMock('Symfony\Component\Console\Application', array('getTerminalWidth'));
        $application->setAutoExit(false);
        $application->expects($this->any())
            ->method('getTerminalWidth')
            ->will($this->returnValue(120));
        $tester = new ApplicationTester($application);

        $tester->run(array('command' => 'foo'), array('decorated' => false));
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception1.txt', $tester->getDisplay(true), '->renderException() renders a pretty exception');

        $tester->run(array('command' => 'foo'), array('decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE));
        $this->assertContains('Exception trace', $tester->getDisplay(), '->renderException() renders a pretty exception with a stack trace when verbosity is verbose');

        $tester->run(array('command' => 'list', '--foo' => true), array('decorated' => false));
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception2.txt', $tester->getDisplay(true), '->renderException() renders the command synopsis when an exception occurs in the context of a command');

        $application->add(new \Foo3Command);
        $tester = new ApplicationTester($application);
        $tester->run(array('command' => 'foo3:bar'), array('decorated' => false));
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception3.txt', $tester->getDisplay(true), '->renderException() renders a pretty exceptions with previous exceptions');

        $tester->run(array('command' => 'foo3:bar'), array('decorated' => true));
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception3decorated.txt', $tester->getDisplay(true), '->renderException() renders a pretty exceptions with previous exceptions');

        $application = $this->getMock('Symfony\Component\Console\Application', array('getTerminalWidth'));
        $application->setAutoExit(false);
        $application->expects($this->any())
            ->method('getTerminalWidth')
            ->will($this->returnValue(32));
        $tester = new ApplicationTester($application);

        $tester->run(array('command' => 'foo'), array('decorated' => false));
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception4.txt', $tester->getDisplay(true), '->renderException() wraps messages when they are bigger than the terminal');
    }

    public function testRun()
    {
        $application = new Application();
        $application->setAutoExit(false);
        $application->setCatchExceptions(false);
        $application->add($command = new \Foo1Command());
        $_SERVER['argv'] = array('cli.php', 'foo:bar1');

        ob_start();
        $application->run();
        ob_end_clean();

        $this->assertSame('Symfony\Component\Console\Input\ArgvInput', get_class($command->input), '->run() creates an ArgvInput by default if none is given');
        $this->assertSame('Symfony\Component\Console\Output\ConsoleOutput', get_class($command->output), '->run() creates a ConsoleOutput by default if none is given');

        $application = new Application();
        $application->setAutoExit(false);
        $application->setCatchExceptions(false);

        $this->ensureStaticCommandHelp($application);
        $tester = new ApplicationTester($application);

        $tester->run(array(), array('decorated' => false));
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_run1.txt', $tester->getDisplay(true), '->run() runs the list command if no argument is passed');

        $tester->run(array('--help' => true), array('decorated' => false));
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_run2.txt', $tester->getDisplay(true), '->run() runs the help command if --help is passed');

        $tester->run(array('-h' => true), array('decorated' => false));
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_run2.txt', $tester->getDisplay(true), '->run() runs the help command if -h is passed');

        $tester->run(array('command' => 'list', '--help' => true), array('decorated' => false));
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_run3.txt', $tester->getDisplay(true), '->run() displays the help if --help is passed');

        $tester->run(array('command' => 'list', '-h' => true), array('decorated' => false));
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_run3.txt', $tester->getDisplay(true), '->run() displays the help if -h is passed');

        $tester->run(array('--ansi' => true));
        $this->assertTrue($tester->getOutput()->isDecorated(), '->run() forces color output if --ansi is passed');

        $tester->run(array('--no-ansi' => true));
        $this->assertFalse($tester->getOutput()->isDecorated(), '->run() forces color output to be disabled if --no-ansi is passed');

        $tester->run(array('--version' => true), array('decorated' => false));
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_run4.txt', $tester->getDisplay(true), '->run() displays the program version if --version is passed');

        $tester->run(array('-V' => true), array('decorated' => false));
        $this->assertStringEqualsFile(self::$fixturesPath.'/application_run4.txt', $tester->getDisplay(true), '->run() displays the program version if -v is passed');

        $tester->run(array('command' => 'list', '--quiet' => true));
        $this->assertSame('', $tester->getDisplay(), '->run() removes all output if --quiet is passed');

        $tester->run(array('command' => 'list', '-q' => true));
        $this->assertSame('', $tester->getDisplay(), '->run() removes all output if -q is passed');

        $tester->run(array('command' => 'list', '--verbose' => true));
        $this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if --verbose is passed');

        $tester->run(array('command' => 'list', '--verbose' => 1));
        $this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if --verbose=1 is passed');

        $tester->run(array('command' => 'list', '--verbose' => 2));
        $this->assertSame(Output::VERBOSITY_VERY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to very verbose if --verbose=2 is passed');

        $tester->run(array('command' => 'list', '--verbose' => 3));
        $this->assertSame(Output::VERBOSITY_DEBUG, $tester->getOutput()->getVerbosity(), '->run() sets the output to debug if --verbose=3 is passed');

        $tester->run(array('command' => 'list', '--verbose' => 4));
        $this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if unknown --verbose level is passed');

        $tester->run(array('command' => 'list', '-v' => true));
        $this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if -v is passed');

        $tester->run(array('command' => 'list', '-vv' => true));
        $this->assertSame(Output::VERBOSITY_VERY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if -v is passed');

        $tester->run(array('command' => 'list', '-vvv' => true));
        $this->assertSame(Output::VERBOSITY_DEBUG, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if -v is passed');

        $application = new Application();
        $application->setAutoExit(false);
        $application->setCatchExceptions(false);
        $application->add(new \FooCommand());
        $tester = new ApplicationTester($application);

        $tester->run(array('command' => 'foo:bar', '--no-interaction' => true), array('decorated' => false));
        $this->assertSame('called'.PHP_EOL, $tester->getDisplay(), '->run() does not call interact() if --no-interaction is passed');

        $tester->run(array('command' => 'foo:bar', '-n' => true), array('decorated' => false));
        $this->assertSame('called'.PHP_EOL, $tester->getDisplay(), '->run() does not call interact() if -n is passed');
    }

    /**
     * Issue #9285
     *
     * If the "verbose" option is just before an argument in ArgvInput,
     * an argument value should not be treated as verbosity value.
     * This test will fail with "Not enough arguments." if broken
     */
    public function testVerboseValueNotBreakArguments()
    {
        $application = new Application();
        $application->setAutoExit(false);
        $application->setCatchExceptions(false);
        $application->add(new \FooCommand());

        $output = new StreamOutput(fopen('php://memory', 'w', false));

        $input = new ArgvInput(array('cli.php', '-v', 'foo:bar'));
        $application->run($input, $output);

        $input = new ArgvInput(array('cli.php', '--verbose', 'foo:bar'));
        $application->run($input, $output);
    }

    public function testRunReturnsIntegerExitCode()
    {
        $exception = new \Exception('', 4);

        $application = $this->getMock('Symfony\Component\Console\Application', array('doRun'));
        $application->setAutoExit(false);
        $application->expects($this->once())
             ->method('doRun')
             ->will($this->throwException($exception));

        $exitCode = $application->run(new ArrayInput(array()), new NullOutput());

        $this->assertSame(4, $exitCode, '->run() returns integer exit code extracted from raised exception');
    }

    public function testRunReturnsExitCodeOneForExceptionCodeZero()
    {
        $exception = new \Exception('', 0);

        $application = $this->getMock('Symfony\Component\Console\Application', array('doRun'));
        $application->setAutoExit(false);
        $application->expects($this->once())
             ->method('doRun')
             ->will($this->throwException($exception));

        $exitCode = $application->run(new ArrayInput(array()), new NullOutput());

        $this->assertSame(1, $exitCode, '->run() returns exit code 1 when exception code is 0');
    }

    /**
     * @expectedException \LogicException
     * @dataProvider getAddingAlreadySetDefinitionElementData
     */
    public function testAddingAlreadySetDefinitionElementData($def)
    {
        $application = new Application();
        $application->setAutoExit(false);
        $application->setCatchExceptions(false);
        $application
            ->register('foo')
            ->setDefinition(array($def))
            ->setCode(function (InputInterface $input, OutputInterface $output) {})
        ;

        $input = new ArrayInput(array('command' => 'foo'));
        $output = new NullOutput();
        $application->run($input, $output);
    }

    public function getAddingAlreadySetDefinitionElementData()
    {
        return array(
            array(new InputArgument('command', InputArgument::REQUIRED)),
            array(new InputOption('quiet', '', InputOption::VALUE_NONE)),
            array(new InputOption('query', 'q', InputOption::VALUE_NONE)),
        );
    }

    public function testGetDefaultHelperSetReturnsDefaultValues()
    {
        $application = new Application();
        $application->setAutoExit(false);
        $application->setCatchExceptions(false);

        $helperSet = $application->getHelperSet();

        $this->assertTrue($helperSet->has('formatter'));
        $this->assertTrue($helperSet->has('dialog'));
        $this->assertTrue($helperSet->has('progress'));
    }

    public function testAddingSingleHelperSetOverwritesDefaultValues()
    {
        $application = new Application();
        $application->setAutoExit(false);
        $application->setCatchExceptions(false);

        $application->setHelperSet(new HelperSet(array(new FormatterHelper())));

        $helperSet = $application->getHelperSet();

        $this->assertTrue($helperSet->has('formatter'));

        // no other default helper set should be returned
        $this->assertFalse($helperSet->has('dialog'));
        $this->assertFalse($helperSet->has('progress'));
    }

    public function testOverwritingDefaultHelperSetOverwritesDefaultValues()
    {
        $application = new CustomApplication();
        $application->setAutoExit(false);
        $application->setCatchExceptions(false);

        $application->setHelperSet(new HelperSet(array(new FormatterHelper())));

        $helperSet = $application->getHelperSet();

        $this->assertTrue($helperSet->has('formatter'));

        // no other default helper set should be returned
        $this->assertFalse($helperSet->has('dialog'));
        $this->assertFalse($helperSet->has('progress'));
    }

    public function testGetDefaultInputDefinitionReturnsDefaultValues()
    {
        $application = new Application();
        $application->setAutoExit(false);
        $application->setCatchExceptions(false);

        $inputDefinition = $application->getDefinition();

        $this->assertTrue($inputDefinition->hasArgument('command'));

        $this->assertTrue($inputDefinition->hasOption('help'));
        $this->assertTrue($inputDefinition->hasOption('quiet'));
        $this->assertTrue($inputDefinition->hasOption('verbose'));
        $this->assertTrue($inputDefinition->hasOption('version'));
        $this->assertTrue($inputDefinition->hasOption('ansi'));
        $this->assertTrue($inputDefinition->hasOption('no-ansi'));
        $this->assertTrue($inputDefinition->hasOption('no-interaction'));
    }

    public function testOverwritingDefaultInputDefinitionOverwritesDefaultValues()
    {
        $application = new CustomApplication();
        $application->setAutoExit(false);
        $application->setCatchExceptions(false);

        $inputDefinition = $application->getDefinition();

        // check whether the default arguments and options are not returned any more
        $this->assertFalse($inputDefinition->hasArgument('command'));

        $this->assertFalse($inputDefinition->hasOption('help'));
        $this->assertFalse($inputDefinition->hasOption('quiet'));
        $this->assertFalse($inputDefinition->hasOption('verbose'));
        $this->assertFalse($inputDefinition->hasOption('version'));
        $this->assertFalse($inputDefinition->hasOption('ansi'));
        $this->assertFalse($inputDefinition->hasOption('no-ansi'));
        $this->assertFalse($inputDefinition->hasOption('no-interaction'));

        $this->assertTrue($inputDefinition->hasOption('custom'));
    }

    public function testSettingCustomInputDefinitionOverwritesDefaultValues()
    {
        $application = new Application();
        $application->setAutoExit(false);
        $application->setCatchExceptions(false);

        $application->setDefinition(new InputDefinition(array(new InputOption('--custom', '-c', InputOption::VALUE_NONE, 'Set the custom input definition.'))));

        $inputDefinition = $application->getDefinition();

        // check whether the default arguments and options are not returned any more
        $this->assertFalse($inputDefinition->hasArgument('command'));

        $this->assertFalse($inputDefinition->hasOption('help'));
        $this->assertFalse($inputDefinition->hasOption('quiet'));
        $this->assertFalse($inputDefinition->hasOption('verbose'));
        $this->assertFalse($inputDefinition->hasOption('version'));
        $this->assertFalse($inputDefinition->hasOption('ansi'));
        $this->assertFalse($inputDefinition->hasOption('no-ansi'));
        $this->assertFalse($inputDefinition->hasOption('no-interaction'));

        $this->assertTrue($inputDefinition->hasOption('custom'));
    }

    public function testRunWithDispatcher()
    {
        $application = new Application();
        $application->setAutoExit(false);
        $application->setDispatcher($this->getDispatcher());

        $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) {
            $output->write('foo.');
        });

        $tester = new ApplicationTester($application);
        $tester->run(array('command' => 'foo'));
        $this->assertEquals('before.foo.after.', $tester->getDisplay());
    }

    /**
     * @expectedException        \LogicException
     * @expectedExceptionMessage caught
     */
    public function testRunWithExceptionAndDispatcher()
    {
        $application = new Application();
        $application->setDispatcher($this->getDispatcher());
        $application->setAutoExit(false);
        $application->setCatchExceptions(false);

        $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) {
            throw new \RuntimeException('foo');
        });

        $tester = new ApplicationTester($application);
        $tester->run(array('command' => 'foo'));
    }

    public function testRunDispatchesAllEventsWithException()
    {
        $application = new Application();
        $application->setDispatcher($this->getDispatcher());
        $application->setAutoExit(false);

        $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) {
            $output->write('foo.');

            throw new \RuntimeException('foo');
        });

        $tester = new ApplicationTester($application);
        $tester->run(array('command' => 'foo'));
        $this->assertContains('before.foo.after.caught.', $tester->getDisplay());
    }

    public function testTerminalDimensions()
    {
        $application = new Application();
        $originalDimensions = $application->getTerminalDimensions();
        $this->assertCount(2, $originalDimensions);

        $width = 80;
        if ($originalDimensions[0] == $width) {
            $width = 100;
        }

        $application->setTerminalDimensions($width, 80);
        $this->assertSame(array($width, 80), $application->getTerminalDimensions());
    }

    protected function getDispatcher()
    {
        $dispatcher = new EventDispatcher();
        $dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) {
            $event->getOutput()->write('before.');
        });
        $dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) {
            $event->getOutput()->write('after.');

            $event->setExitCode(128);
        });
        $dispatcher->addListener('console.exception', function (ConsoleExceptionEvent $event) {
            $event->getOutput()->writeln('caught.');

            $event->setException(new \LogicException('caught.', $event->getExitCode(), $event->getException()));
        });

        return $dispatcher;
    }
}

class CustomApplication extends Application
{
    /**
     * Overwrites the default input definition.
     *
     * @return InputDefinition An InputDefinition instance
     */
    protected function getDefaultInputDefinition()
    {
        return new InputDefinition(array(new InputOption('--custom', '-c', InputOption::VALUE_NONE, 'Set the custom input definition.')));
    }

    /**
     * Gets the default helper set with the helpers that should always be available.
     *
     * @return HelperSet A HelperSet instance
     */
    protected function getDefaultHelperSet()
    {
        return new HelperSet(array(new FormatterHelper()));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Symfony\Component\Console;

/**
 * Contains all events dispatched by an Application.
 *
 * @author Francesco Levorato <git@flevour.net>
 */
final class ConsoleEvents
{
    /**
     * The COMMAND event allows you to attach listeners before any command is
     * executed by the console. It also allows you to modify the command, input and output
     * before they are handled to the command.
     *
     * The event listener method receives a Symfony\Component\Console\Event\ConsoleCommandEvent
     * instance.
     *
     * @var string
     */
    const COMMAND = 'console.command';

    /**
     * The TERMINATE event allows you to attach listeners after a command is
     * executed by the console.
     *
     * The event listener method receives a Symfony\Component\Console\Event\ConsoleTerminateEvent
     * instance.
     *
     * @var string
     */
    const TERMINATE = 'console.terminate';

    /**
     * The EXCEPTION event occurs when an uncaught exception appears.
     *
     * This event allows you to deal with the exception or
     * to modify the thrown exception. The event listener method receives
     * a Symfony\Component\Console\Event\ConsoleExceptionEvent
     * instance.
     *
     * @var string
     */
    const EXCEPTION = 'console.exception';
}
{
    "name": "psr/log",
    "description": "Common interface for logging libraries",
    "keywords": ["psr", "psr-3", "log"],
    "license": "MIT",
    "authors": [
        {
            "name": "PHP-FIG",
            "homepage": "http://www.php-fig.org/"
        }
    ],
    "autoload": {
        "psr-0": {
            "Psr\\Log\\": ""
        }
    }
}
Copyright (c) 2012 PHP Framework Interoperability Group

Permission is hereby granted, free of charge, to any person obtaining a copy 
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights 
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
copies of the Software, and to permit persons to whom the Software is 
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in 
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

namespace Psr\Log;

/**
 * This is a simple Logger implementation that other Loggers can inherit from.
 *
 * It simply delegates all log-level-specific methods to the `log` method to
 * reduce boilerplate code that a simple Logger that does the same thing with
 * messages regardless of the error level has to implement.
 */
abstract class AbstractLogger implements LoggerInterface
{
    /**
     * System is unusable.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function emergency($message, array $context = array())
    {
        $this->log(LogLevel::EMERGENCY, $message, $context);
    }

    /**
     * Action must be taken immediately.
     *
     * Example: Entire website down, database unavailable, etc. This should
     * trigger the SMS alerts and wake you up.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function alert($message, array $context = array())
    {
        $this->log(LogLevel::ALERT, $message, $context);
    }

    /**
     * Critical conditions.
     *
     * Example: Application component unavailable, unexpected exception.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function critical($message, array $context = array())
    {
        $this->log(LogLevel::CRITICAL, $message, $context);
    }

    /**
     * Runtime errors that do not require immediate action but should typically
     * be logged and monitored.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function error($message, array $context = array())
    {
        $this->log(LogLevel::ERROR, $message, $context);
    }

    /**
     * Exceptional occurrences that are not errors.
     *
     * Example: Use of deprecated APIs, poor use of an API, undesirable things
     * that are not necessarily wrong.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function warning($message, array $context = array())
    {
        $this->log(LogLevel::WARNING, $message, $context);
    }

    /**
     * Normal but significant events.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function notice($message, array $context = array())
    {
        $this->log(LogLevel::NOTICE, $message, $context);
    }

    /**
     * Interesting events.
     *
     * Example: User logs in, SQL logs.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function info($message, array $context = array())
    {
        $this->log(LogLevel::INFO, $message, $context);
    }

    /**
     * Detailed debug information.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function debug($message, array $context = array())
    {
        $this->log(LogLevel::DEBUG, $message, $context);
    }
}
<?php

namespace Psr\Log;

class InvalidArgumentException extends \InvalidArgumentException
{
}
<?php

namespace Psr\Log;

/**
 * This is a simple Logger trait that classes unable to extend AbstractLogger
 * (because they extend another class, etc) can include.
 *
 * It simply delegates all log-level-specific methods to the `log` method to 
 * reduce boilerplate code that a simple Logger that does the same thing with 
 * messages regardless of the error level has to implement.
 */
trait LoggerTrait
{
    /**
     * System is unusable.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function emergency($message, array $context = array())
    {
        $this->log(LogLevel::EMERGENCY, $message, $context);
    }

    /**
     * Action must be taken immediately.
     *
     * Example: Entire website down, database unavailable, etc. This should
     * trigger the SMS alerts and wake you up.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function alert($message, array $context = array())
    {
        $this->log(LogLevel::ALERT, $message, $context);
    }

    /**
     * Critical conditions.
     *
     * Example: Application component unavailable, unexpected exception.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function critical($message, array $context = array())
    {
        $this->log(LogLevel::CRITICAL, $message, $context);
    }

    /**
     * Runtime errors that do not require immediate action but should typically
     * be logged and monitored.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function error($message, array $context = array())
    {
        $this->log(LogLevel::ERROR, $message, $context);
    }

    /**
     * Exceptional occurrences that are not errors.
     *
     * Example: Use of deprecated APIs, poor use of an API, undesirable things
     * that are not necessarily wrong.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function warning($message, array $context = array())
    {
        $this->log(LogLevel::WARNING, $message, $context);
    }

    /**
     * Normal but significant events.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function notice($message, array $context = array())
    {
        $this->log(LogLevel::NOTICE, $message, $context);
    }

    /**
     * Interesting events.
     *
     * Example: User logs in, SQL logs.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function info($message, array $context = array())
    {
        $this->log(LogLevel::INFO, $message, $context);
    }

    /**
     * Detailed debug information.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function debug($message, array $context = array())
    {
        $this->log(LogLevel::DEBUG, $message, $context);
    }

    /**
     * Logs with an arbitrary level.
     *
     * @param mixed $level
     * @param string $message
     * @param array $context
     * @return null
     */
    abstract public function log($level, $message, array $context = array());
}
<?php

namespace Psr\Log;

/**
 * Describes log levels
 */
class LogLevel
{
    const EMERGENCY = 'emergency';
    const ALERT = 'alert';
    const CRITICAL = 'critical';
    const ERROR = 'error';
    const WARNING = 'warning';
    const NOTICE = 'notice';
    const INFO = 'info';
    const DEBUG = 'debug';
}
<?php

namespace Psr\Log;

/**
 * Describes a logger instance
 *
 * The message MUST be a string or object implementing __toString().
 *
 * The message MAY contain placeholders in the form: {foo} where foo
 * will be replaced by the context data in key "foo".
 *
 * The context array can contain arbitrary data, the only assumption that
 * can be made by implementors is that if an Exception instance is given
 * to produce a stack trace, it MUST be in a key named "exception".
 *
 * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
 * for the full interface specification.
 */
interface LoggerInterface
{
    /**
     * System is unusable.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function emergency($message, array $context = array());

    /**
     * Action must be taken immediately.
     *
     * Example: Entire website down, database unavailable, etc. This should
     * trigger the SMS alerts and wake you up.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function alert($message, array $context = array());

    /**
     * Critical conditions.
     *
     * Example: Application component unavailable, unexpected exception.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function critical($message, array $context = array());

    /**
     * Runtime errors that do not require immediate action but should typically
     * be logged and monitored.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function error($message, array $context = array());

    /**
     * Exceptional occurrences that are not errors.
     *
     * Example: Use of deprecated APIs, poor use of an API, undesirable things
     * that are not necessarily wrong.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function warning($message, array $context = array());

    /**
     * Normal but significant events.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function notice($message, array $context = array());

    /**
     * Interesting events.
     *
     * Example: User logs in, SQL logs.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function info($message, array $context = array());

    /**
     * Detailed debug information.
     *
     * @param string $message
     * @param array $context
     * @return null
     */
    public function debug($message, array $context = array());

    /**
     * Logs with an arbitrary level.
     *
     * @param mixed $level
     * @param string $message
     * @param array $context
     * @return null
     */
    public function log($level, $message, array $context = array());
}
<?php

namespace Psr\Log;

/**
 * Basic Implementation of LoggerAwareInterface.
 */
trait LoggerAwareTrait
{
    /** @var LoggerInterface */
    protected $logger;

    /**
     * Sets a logger.
     * 
     * @param LoggerInterface $logger
     */
    public function setLogger(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }
}
<?php

namespace Psr\Log;

/**
 * This Logger can be used to avoid conditional log calls
 *
 * Logging should always be optional, and if no logger is provided to your
 * library creating a NullLogger instance to have something to throw logs at
 * is a good way to avoid littering your code with `if ($this->logger) { }`
 * blocks.
 */
class NullLogger extends AbstractLogger
{
    /**
     * Logs with an arbitrary level.
     *
     * @param mixed $level
     * @param string $message
     * @param array $context
     * @return null
     */
    public function log($level, $message, array $context = array())
    {
        // noop
    }
}
<?php

namespace Psr\Log\Test;

use Psr\Log\LogLevel;

/**
 * Provides a base test class for ensuring compliance with the LoggerInterface
 *
 * Implementors can extend the class and implement abstract methods to run this as part of their test suite
 */
abstract class LoggerInterfaceTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @return LoggerInterface
     */
    abstract function getLogger();

    /**
     * This must return the log messages in order with a simple formatting: "<LOG LEVEL> <MESSAGE>"
     *
     * Example ->error('Foo') would yield "error Foo"
     *
     * @return string[]
     */
    abstract function getLogs();

    public function testImplements()
    {
        $this->assertInstanceOf('Psr\Log\LoggerInterface', $this->getLogger());
    }

    /**
     * @dataProvider provideLevelsAndMessages
     */
    public function testLogsAtAllLevels($level, $message)
    {
        $logger = $this->getLogger();
        $logger->{$level}($message, array('user' => 'Bob'));
        $logger->log($level, $message, array('user' => 'Bob'));

        $expected = array(
            $level.' message of level '.$level.' with context: Bob',
            $level.' message of level '.$level.' with context: Bob',
        );
        $this->assertEquals($expected, $this->getLogs());
    }

    public function provideLevelsAndMessages()
    {
        return array(
            LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'),
            LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'),
            LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'),
            LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'),
            LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'),
            LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'),
            LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'),
            LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'),
        );
    }

    /**
     * @expectedException Psr\Log\InvalidArgumentException
     */
    public function testThrowsOnInvalidLevel()
    {
        $logger = $this->getLogger();
        $logger->log('invalid level', 'Foo');
    }

    public function testContextReplacement()
    {
        $logger = $this->getLogger();
        $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar'));

        $expected = array('info {Message {nothing} Bob Bar a}');
        $this->assertEquals($expected, $this->getLogs());
    }

    public function testObjectCastToString()
    {
        $dummy = $this->getMock('Psr\Log\Test\DummyTest', array('__toString'));
        $dummy->expects($this->once())
            ->method('__toString')
            ->will($this->returnValue('DUMMY'));

        $this->getLogger()->warning($dummy);
    }

    public function testContextCanContainAnything()
    {
        $context = array(
            'bool' => true,
            'null' => null,
            'string' => 'Foo',
            'int' => 0,
            'float' => 0.5,
            'nested' => array('with object' => new DummyTest),
            'object' => new \DateTime,
            'resource' => fopen('php://memory', 'r'),
        );

        $this->getLogger()->warning('Crazy context data', $context);
    }

    public function testContextExceptionKeyCanBeExceptionOrOtherValues()
    {
        $this->getLogger()->warning('Random message', array('exception' => 'oops'));
        $this->getLogger()->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail')));
    }
}

class DummyTest
{
}<?php

namespace Psr\Log;

/**
 * Describes a logger-aware instance
 */
interface LoggerAwareInterface
{
    /**
     * Sets a logger instance on the object
     *
     * @param LoggerInterface $logger
     * @return null
     */
    public function setLogger(LoggerInterface $logger);
}
<?php

#
#
# Parsedown
# http://parsedown.org
#
# (c) Emanuil Rusev
# http://erusev.com
#
# For the full license information, please view the LICENSE file that was
# distributed with this source code.
#
#

class Parsedown
{
	#
	# Multiton (http://en.wikipedia.org/wiki/Multiton_pattern)
	#

	static function instance($name = 'default')
	{
		if (isset(self::$instances[$name]))
			return self::$instances[$name];

		$instance = new Parsedown();

		self::$instances[$name] = $instance;

		return $instance;
	}

	private static $instances = array();

	#
	# Fields
	#

	private $reference_map = array();
	private $escape_sequence_map = array();

	#
	# Public Methods
	#

	function parse($text)
	{
		# removes UTF-8 BOM and marker characters
		$text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text);

		# removes \r characters
		$text = str_replace("\r\n", "\n", $text);
		$text = str_replace("\r", "\n", $text);

		# replaces tabs with spaces
		$text = str_replace("\t", '    ', $text);

		# encodes escape sequences

		if (strpos($text, '\\') !== FALSE)
		{
			$escape_sequences = array('\\\\', '\`', '\*', '\_', '\{', '\}', '\[', '\]', '\(', '\)', '\>', '\#', '\+', '\-', '\.', '\!');

			foreach ($escape_sequences as $index => $escape_sequence)
			{
				if (strpos($text, $escape_sequence) !== FALSE)
				{
					$code = "\x1A".'\\'.$index.';';

					$text = str_replace($escape_sequence, $code, $text);

					$this->escape_sequence_map[$code] = $escape_sequence;
				}
			}
		}

		# ~

		$text = preg_replace('/\n\s*\n/', "\n\n", $text);
		$text = trim($text, "\n");

		$lines = explode("\n", $text);

		$text = $this->parse_block_elements($lines);

		# decodes escape sequences

		foreach ($this->escape_sequence_map as $code => $escape_sequence)
		{
			$text = str_replace($code, $escape_sequence[1], $text);
		}

		$text = rtrim($text, "\n");

		return $text;
	}

	#
	# Private Methods
	#

	private function parse_block_elements(array $lines, $context = '')
	{
		$elements = array();

		$element = array(
			'type' => '',
		);

		foreach ($lines as $line)
		{
			# fenced elements

			switch ($element['type'])
			{
				case 'fenced_code_block':

					if ( ! isset($element['closed']))
					{
						if (preg_match('/^[ ]*'.$element['fence'][0].'{3,}[ ]*$/', $line))
						{
							$element['closed'] = true;
						}
						else
						{
							$element['text'] !== '' and $element['text'] .= "\n";

							$element['text'] .= $line;
						}

						continue 2;
					}

					break;

				case 'markup':

					if ( ! isset($element['closed']))
					{
						if (preg_match('{<'.$element['subtype'].'>$}', $line)) # opening tag
						{
							$element['depth']++;
						}

						if (preg_match('{</'.$element['subtype'].'>$}', $line)) # closing tag
						{
							$element['depth'] > 0
								? $element['depth']--
								: $element['closed'] = true;
						}

						$element['text'] .= "\n".$line;

						continue 2;
					}

					break;
			}

			# *

			if ($line === '')
			{
				$element['interrupted'] = true;

				continue;
			}

			# composite elements

			switch ($element['type'])
			{
				case 'blockquote':

					if ( ! isset($element['interrupted']))
					{
						$line = preg_replace('/^[ ]*>[ ]?/', '', $line);

						$element['lines'] []= $line;

						continue 2;
					}

					break;

				case 'li':

					if (preg_match('/^([ ]{0,3})(\d+[.]|[*+-])[ ](.*)/', $line, $matches))
					{
						if ($element['indentation'] !== $matches[1])
						{
							$element['lines'] []= $line;
						}
						else
						{
							unset($element['last']);

							$elements []= $element;

							$element = array(
								'type' => 'li',
								'indentation' => $matches[1],
								'last' => true,
								'lines' => array(
									preg_replace('/^[ ]{0,4}/', '', $matches[3]),
								),
							);
						}

						continue 2;
					}

					if (isset($element['interrupted']))
					{
						if ($line[0] === ' ')
						{
							$element['lines'] []= '';

							$line = preg_replace('/^[ ]{0,4}/', '', $line);

							$element['lines'] []= $line;

							continue 2;
						}
					}
					else
					{
						$line = preg_replace('/^[ ]{0,4}/', '', $line);

						$element['lines'] []= $line;

						continue 2;
					}

					break;
			}

			# indentation sensitive types

			$deindented_line = $line;

			switch ($line[0])
			{
				case ' ':

					# ~

					$deindented_line = ltrim($line);

					if ($deindented_line === '')
					{
						continue 2;
					}

					# code block

					if (preg_match('/^[ ]{4}(.*)/', $line, $matches))
					{
						if ($element['type'] === 'code_block')
						{
							if (isset($element['interrupted']))
							{
								$element['text'] .= "\n";

								unset ($element['interrupted']);
							}

							$element['text'] .= "\n".$matches[1];
						}
						else
						{
							$elements []= $element;

							$element = array(
								'type' => 'code_block',
								'text' => $matches[1],
							);
						}

						continue 2;
					}

					break;

				case '#':

					# atx heading (#)

					if (preg_match('/^(#{1,6})[ ]*(.+?)[ ]*#*$/', $line, $matches))
					{
						$elements []= $element;

						$level = strlen($matches[1]);

						$element = array(
							'type' => 'h.',
							'text' => $matches[2],
							'level' => $level,
						);

						continue 2;
					}

					break;

				case '-':

					# setext heading (---)

					if ($line[0] === '-' and $element['type'] === 'p' and ! isset($element['interrupted']) and preg_match('/^[-]+[ ]*$/', $line))
					{
						$element['type'] = 'h.';
						$element['level'] = 2;

						continue 2;
					}

					break;

				case '=':

					# setext heading (===)

					if ($line[0] === '=' and $element['type'] === 'p' and ! isset($element['interrupted']) and preg_match('/^[=]+[ ]*$/', $line))
					{
						$element['type'] = 'h.';
						$element['level'] = 1;

						continue 2;
					}

					break;
			}

			# indentation insensitive types

			switch ($deindented_line[0])
			{
				case '<':

					# self-closing tag

					if (preg_match('{^<.+?/>$}', $deindented_line))
					{
						$elements []= $element;

						$element = array(
							'type' => '',
							'text' => $deindented_line,
						);

						continue 2;
					}

					# opening tag

					if (preg_match('{^<(\w+)(?:[ ].*?)?>}', $deindented_line, $matches))
					{
						$elements []= $element;

						$element = array(
							'type' => 'markup',
							'subtype' => strtolower($matches[1]),
							'text' => $deindented_line,
							'depth' => 0,
						);

						preg_match('{</'.$matches[1].'>\s*$}', $deindented_line) and $element['closed'] = true;

						continue 2;
					}

					break;

				case '>':

					# quote

					if (preg_match('/^>[ ]?(.*)/', $deindented_line, $matches))
					{
						$elements []= $element;

						$element = array(
							'type' => 'blockquote',
							'lines' => array(
								$matches[1],
							),
						);

						continue 2;
					}

					break;

				case '[':

					# reference

					if (preg_match('/^\[(.+?)\]:[ ]*([^ ]+)/', $deindented_line, $matches))
					{
						$label = strtolower($matches[1]);

						$this->reference_map[$label] = trim($matches[2], '<>');;

						continue 2;
					}

					break;

				case '`':
				case '~':

					# fenced code block

					if (preg_match('/^([`]{3,}|[~]{3,})[ ]*(\S+)?[ ]*$/', $deindented_line, $matches))
					{
						$elements []= $element;

						$element = array(
							'type' => 'fenced_code_block',
							'text' => '',
							'fence' => $matches[1],
						);

						isset($matches[2]) and $element['language'] = $matches[2];

						continue 2;
					}

					break;

				case '*':
				case '+':
				case '-':
				case '_':

					# hr

					if (preg_match('/^([-*_])([ ]{0,2}\1){2,}[ ]*$/', $deindented_line))
					{
						$elements []= $element;

						$element = array(
							'type' => 'hr',
						);

						continue 2;
					}

					# li

					if (preg_match('/^([ ]*)[*+-][ ](.*)/', $line, $matches))
					{
						$elements []= $element;

						$element = array(
							'type' => 'li',
							'ordered' => false,
							'indentation' => $matches[1],
							'last' => true,
							'lines' => array(
								preg_replace('/^[ ]{0,4}/', '', $matches[2]),
							),
						);

						continue 2;
					}
			}

			# li

			if ($deindented_line[0] <= '9' and $deindented_line >= '0' and preg_match('/^([ ]*)\d+[.][ ](.*)/', $line, $matches))
			{
				$elements []= $element;

				$element = array(
					'type' => 'li',
					'ordered' => true,
					'indentation' => $matches[1],
					'last' => true,
					'lines' => array(
						preg_replace('/^[ ]{0,4}/', '', $matches[2]),
					),
				);

				continue;
			}

			# paragraph

			if ($element['type'] === 'p')
			{
				if (isset($element['interrupted']))
				{
					$elements []= $element;

					$element['text'] = $line;

					unset($element['interrupted']);
				}
				else
				{
					$element['text'] .= "\n".$line;
				}
			}
			else
			{
				$elements []= $element;

				$element = array(
					'type' => 'p',
					'text' => $line,
				);
			}
		}

		$elements []= $element;

		unset($elements[0]);

		#
		# ~
		#

		$markup = '';

		foreach ($elements as $element)
		{
			switch ($element['type'])
			{
				case 'p':

					$text = $this->parse_span_elements($element['text']);

					$text = preg_replace('/[ ]{2}\n/', '<br />'."\n", $text);

					if ($context === 'li' and $markup === '')
					{
						if (isset($element['interrupted']))
						{
							$markup .= "\n".'<p>'.$text.'</p>'."\n";
						}
						else
						{
							$markup .= $text;
						}
					}
					else
					{
						$markup .= '<p>'.$text.'</p>'."\n";
					}

					break;

				case 'blockquote':

					$text = $this->parse_block_elements($element['lines']);

					$markup .= '<blockquote>'."\n".$text.'</blockquote>'."\n";

					break;

				case 'code_block':
				case 'fenced_code_block':

					$text = htmlspecialchars($element['text'], ENT_NOQUOTES, 'UTF-8');

					strpos($text, "\x1A\\") !== FALSE and $text = strtr($text, $this->escape_sequence_map);

					$markup .= isset($element['language'])
						? '<pre><code class="language-'.$element['language'].'">'.$text.'</code></pre>'
						: '<pre><code>'.$text.'</code></pre>';

					$markup .= "\n";

					break;

				case 'h.':

					$text = $this->parse_span_elements($element['text']);

					$markup .= '<h'.$element['level'].'>'.$text.'</h'.$element['level'].'>'."\n";

					break;

				case 'hr':

					$markup .= '<hr />'."\n";

					break;

				case 'li':

					if (isset($element['ordered'])) # first
					{
						$list_type = $element['ordered'] ? 'ol' : 'ul';

						$markup .= '<'.$list_type.'>'."\n";
					}

					if (isset($element['interrupted']) and ! isset($element['last']))
					{
						$element['lines'] []= '';
					}

					$text = $this->parse_block_elements($element['lines'], 'li');

					$markup .= '<li>'.$text.'</li>'."\n";

					isset($element['last']) and $markup .= '</'.$list_type.'>'."\n";

					break;

				default:

					$markup .= $element['text']."\n";
			}
		}

		return $markup;
	}

	private function parse_span_elements($text)
	{
		$map = array();

		$index = 0;

		# code span

		if (strpos($text, '`') !== FALSE and preg_match_all('/`(.+?)`/', $text, $matches, PREG_SET_ORDER))
		{
			foreach ($matches as $matches)
			{
				$element_text = $matches[1];
				$element_text = htmlspecialchars($element_text, ENT_NOQUOTES, 'UTF-8');

				# decodes escape sequences

				$this->escape_sequence_map
					and strpos($element_text, "\x1A") !== FALSE
					and $element_text = strtr($element_text, $this->escape_sequence_map);

				# composes element

				$element = '<code>'.$element_text.'</code>';

				# encodes element

				$code = "\x1A".'$'.$index;

				$text = str_replace($matches[0], $code, $text);

				$map[$code] = $element;

				$index ++;
			}
		}

		# inline link or image

		if (strpos($text, '](') !== FALSE and preg_match_all('/(!?)(\[((?:[^\[\]]|(?2))*)\])\((.*?)\)/', $text, $matches, PREG_SET_ORDER)) # inline
		{
			foreach ($matches as $matches)
			{
				$url = $matches[4];

				strpos($url, '&') !== FALSE and $url = preg_replace('/&(?!#?\w+;)/', '&amp;', $url);

				if ($matches[1]) # image
				{
					$element = '<img alt="'.$matches[3].'" src="'.$url.'">';
				}
				else
				{
					$element_text = $this->parse_span_elements($matches[3]);

					$element = '<a href="'.$url.'">'.$element_text.'</a>';
				}

				# ~

				$code = "\x1A".'$'.$index;

				$text = str_replace($matches[0], $code, $text);

				$map[$code] = $element;

				$index ++;
			}
		}

		# reference link or image

		if ($this->reference_map and strpos($text, '[') !== FALSE and preg_match_all('/(!?)\[(.+?)\](?:\n?[ ]?\[(.*?)\])?/ms', $text, $matches, PREG_SET_ORDER))
		{
			foreach ($matches as $matches)
			{
				$link_definition = isset($matches[3]) && $matches[3]
					? $matches[3]
					: $matches[2]; # implicit

				$link_definition = strtolower($link_definition);

				if (isset($this->reference_map[$link_definition]))
				{
					$url = $this->reference_map[$link_definition];

					strpos($url, '&') !== FALSE and $url = preg_replace('/&(?!#?\w+;)/', '&amp;', $url);

					if ($matches[1]) # image
					{
						$element = '<img alt="'.$matches[2].'" src="'.$url.'">';
					}
					else # anchor
					{
						$element_text = $this->parse_span_elements($matches[2]);

						$element = '<a href="'.$url.'">'.$element_text.'</a>';
					}

					# ~

					$code = "\x1A".'$'.$index;

					$text = str_replace($matches[0], $code, $text);

					$map[$code] = $element;

					$index ++;
				}
			}
		}

		if (strpos($text, '://') !== FALSE)
		{
			switch (TRUE)
			{
				case preg_match_all('{<(https?:[/]{2}[^\s]+)>}i', $text, $matches, PREG_SET_ORDER):
				case preg_match_all('{\b(https?:[/]{2}[^\s]+)\b}i', $text, $matches, PREG_SET_ORDER):

					foreach ($matches as $matches)
					{
						$url = $matches[1];

						strpos($url, '&') !== FALSE and $url = preg_replace('/&(?!#?\w+;)/', '&amp;', $url);

						$element = '<a href=":href">:text</a>';
						$element = str_replace(':text', $url, $element);
						$element = str_replace(':href', $url, $element);

						# ~

						$code = "\x1A".'$'.$index;

						$text = str_replace($matches[0], $code, $text);

						$map[$code] = $element;

						$index ++;
					}

					break;
			}
		}

		# ~

		strpos($text, '&') !== FALSE and $text = preg_replace('/&(?!#?\w+;)/', '&amp;', $text);
		strpos($text, '<') !== FALSE and $text = preg_replace('/<(?!\/?\w.*?>)/', '&lt;', $text);

		# ~

		if (strpos($text, '~~') !== FALSE)
		{
			$text = preg_replace('/~~(?=\S)(.+?)(?<=\S)~~/s', '<del>$1</del>', $text);
		}

		if (strpos($text, '_') !== FALSE)
		{
			$text = preg_replace('/__(?=\S)([^_]+?)(?<=\S)__/s', '<strong>$1</strong>', $text, -1, $count);
			$count or $text = preg_replace('/__(?=\S)(.+?)(?<=\S)__(?!_)/s', '<strong>$1</strong>', $text);

			$text = preg_replace('/\b_(?=\S)(.+?)(?<=\S)_\b/s', '<em>$1</em>', $text);
		}

		if (strpos($text, '*') !== FALSE)
		{
			$text = preg_replace('/\*\*(?=\S)([^*]+?)(?<=\S)\*\*/s', '<strong>$1</strong>', $text, -1, $count);
			$count or $text = preg_replace('/\*\*(?=\S)(.+?)(?<=\S)\*\*(?!\*)/s', '<strong>$1</strong>', $text);

			$text = preg_replace('/\*(?=\S)([^*]+?)(?<=\S)\*/s', '<em>$1</em>', $text, -1, $count);
			$count or $text = preg_replace('/\*(?=\S)(.+?)(?<=\S)\*(?!\*)/s', '<em>$1</em>', $text);
		}

		$text = strtr($text, $map);

		return $text;
	}
}
{
    "name": "erusev/parsedown",
    "description": "Parser for Markdown.",
    "keywords": ["markdown", "parser"],
    "homepage": "http://parsedown.org",
    "type": "library",
    "license": "MIT",
    "authors": [
        {
            "name": "Emanuil Rusev",
            "email": "hello@erusev.com",
            "homepage": "http://erusev.com"
        }
    ],
    "autoload": {
        "psr-0": {"Parsedown": ""}
    }
}<?php

include 'Parsedown.php';

class Test extends PHPUnit_Framework_TestCase
{
	const provider_dir = 'data/';

	/**
	 * @dataProvider provider
	 */
	function test_($markdown, $expected_markup)
	{
		$actual_markup = Parsedown::instance()->parse($markdown);

		$this->assertEquals($expected_markup, $actual_markup);
	}

	function provider()
	{
		$provider = array();

		$path = dirname(__FILE__).'/';

		$DirectoryIterator = new DirectoryIterator($path . '/' . self::provider_dir);

		foreach ($DirectoryIterator as $Item)
		{
			if ($Item->isFile())
			{
				$filename = $Item->getFilename();

				$extension = pathinfo($filename, PATHINFO_EXTENSION);

				if ($extension !== 'md')
					continue;

				$basename = $Item->getBasename('.md');

				$markdown = file_get_contents($path . '/' . self::provider_dir . $basename . '.md');

				if (!$markdown)
					continue;

				$expected_markup = file_get_contents($path . '/' . self::provider_dir . $basename . '.html');
				$expected_markup = str_replace("\r\n", "\n", $expected_markup);
				$expected_markup = str_replace("\r", "\n", $expected_markup);

				$provider [] = array($markdown, $expected_markup);
			}
		}

		return $provider;
	}
}<p><em>underscore</em>, <em>asterisk</em>, <em>one two</em>, <em>three four</em>, <em>a</em>, <em>b</em></p>
<p><em>multiline
emphasis</em></p>
<p>_ this _ is not an emphasis, neither is _ this_, _this _, or _this*</p>
<p>this_is_not_an_emphasis</p>
<p>an empty emphasis __ ** is not an emphasis</p><pre><code>&lt;?php

$message = 'fenced code block';
echo $message;</code></pre>
<pre><code>tilde</code></pre><pre><code>&lt;?php

$message = 'Hello World!'; 
echo $message;</code></pre>
<hr />
<pre><code>&gt; not a quote 
- not a list item
[not a reference]: http://foo.com</code></pre><blockquote>
<p>quote</p>
</blockquote>
<p>indented:</p>
<blockquote>
<p>quote</p>
</blockquote>
<p>no space after <code>&gt;</code>:</p>
<blockquote>
<p>quote</p>
</blockquote><p>line<br />
line</p><p>escaped *emphasis*.</p>
<p><code>escaped \*emphasis\* in a code span</code></p>
<pre><code>escaped \*emphasis\* in a code block</code></pre>
<p>\ ` * _ { } [ ] ( ) > # + - . !</p><p>an <b>important</b> <a href=''>link</a></p>
<p>broken<br/>
line</p><p><em><strong>strong em</strong></em> </p>
<p><em>em <strong>strong em</strong></em></p>
<p><em><strong>strong em</strong> em</em></p>
<p><em><strong>strong em</strong></em></p>
<p><em>em <strong>strong em</strong></em></p>
<p><em><strong>strong em</strong> em</em></p><ul>
<li>
<p>paragraph</p>
<p>paragraph</p>
</li>
<li>
<p>paragraph</p>
<blockquote>
<p>quote</p>
</blockquote>
</li>
</ul><hr />
<hr />
<hr />
<hr />
<hr /><h1>h1</h1>
<h2>h2</h2>
<h3>h3</h3>
<h4>h4</h4>
<h5>h5</h5>
<h6>h6</h6>
<h1>closed h1</h1><p>an <a href="http://example.com">implicit</a> reference link</p>
<p>an <a href="http://example.com">implicit</a> reference link with an empty link definition</p><pre><code>code</code></pre><blockquote>
<p>quote
the rest of it</p>
</blockquote><p><strong><em>em strong</em> strong</strong></p>
<p><strong>strong <em>em strong</em></strong></p>
<p><strong>strong <em>em strong</em> strong</strong></p>
<p><strong>strong <em>em strong</em></strong></p><ul>
<li>li
the rest of it</li>
</ul><p><a href="http://example.com">reference link</a></p>
<p><a href="http://example.com">one</a> with a semantic name</p>
<p>[one][404] with no definition</p>
<p><a href="http://example.com">multiline
one</a> defined on 2 lines</p>
<p><a href="http://example.com">one</a> with an upper case label</p><div>content</div>
<hr style="background: #eaa;" />
<p>nested elements:</p>
<div>
parent
<div>
child
</div>
</div><blockquote>
<h2>header</h2>
<p>paragraph</p>
<ul>
<li>li</li>
</ul>
<hr />
<p>paragraph</p>
</blockquote><p>a <code>code span</code></p><p>AT&amp;T has an ampersand in their name</p>
<pre><code>Let's play some cards ♠ ♣ ♥ ♦</code></pre>
<p>AT&amp;T is another way to write it</p>
<p>this &amp; that</p>
<p>4 &lt; 5 and 6 > 5</p>
<p><a href="http://example.com/autolink?a=1&amp;b=2">http://example.com/autolink?a=1&amp;b=2</a> </p>
<p><a href="/script?a=1&amp;b=2">inline link</a></p>
<p><a href="http://example.com/?a=1&amp;b=2">reference link</a></p><p><del>strikethrough</del></p>
<p>in the <del>middle</del> of a sentence</p>
<p>in the middle of a w<del>or</del>d</p><p><a href="http://example.com">http://example.com</a></p><ol>
<li>one</li>
<li>two</li>
</ol>
<p>repeating numbers:</p>
<ol>
<li>one</li>
<li>two</li>
</ol>
<p>large numbers:</p>
<ol>
<li>one</li>
</ol><p><a href="http://example.com">link</a></p>
<p><a href="http://example.com"><img alt="MD Logo" src="http://parsedown.org/md.png"></a></p><ul>
<li>li</li>
<li>li</li>
</ul>
<p>mixed markers:</p>
<ul>
<li>li</li>
<li>li</li>
<li>li</li>
</ul><p><img alt="Markdown Logo" src="/md.png"></p><ul>
<li>
<p>li</p>
</li>
<li>li</li>
</ul>
<hr />
<ul>
<li>
<p>li</p>
<ul>
<li>indented li</li>
</ul>
</li>
</ul><h1>h1</h1>
<h2>h2</h2>
<h2>single character</h2>
<p>not a header</p>
<hr /><p>Here's an autolink <a href="http://example.com">http://example.com</a>.</p><?xml version="1.0" encoding="UTF-8"?>
<phpunit colors="true">
	<testsuites>
		<testsuite>
			<file>tests/Test.php</file>
		</testsuite>
	</testsuites>
</phpunit>The MIT License (MIT)

Copyright (c) 2013 Emanuil Rusev, erusev.com

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.{
    "name": "nikic/php-parser",
    "description": "A PHP parser written in PHP",
    "keywords": ["php", "parser"],
    "type": "library",
    "license": "BSD-3-Clause",
    "authors": [
        {
            "name": "Nikita Popov"
        }
    ],
    "require": {
        "php": ">=5.2"
    },
    "autoload": {
        "psr-0": { "PHPParser": "lib/" }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "0.9-dev"
        }
    }
}
Copyright (c) 2011 by Nikita Popov.

Some rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above
      copyright notice, this list of conditions and the following
      disclaimer in the documentation and/or other materials provided
      with the distribution.

    * The names of the contributors may not be used to endorse or
      promote products derived from this software without specific
      prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.<?php

const GRAMMAR_FILE = './zend_language_parser.phpy';

const LIB = '(?(DEFINE)
    (?<singleQuotedString>\'[^\\\\\']*+(?:\\\\.[^\\\\\']*+)*+\')
    (?<doubleQuotedString>"[^\\\\"]*+(?:\\\\.[^\\\\"]*+)*+")
    (?<string>(?&singleQuotedString)|(?&doubleQuotedString))
    (?<comment>/\*[^*]*+(?:\*(?!/)[^*]*+)*+\*/)
    (?<code>\{[^\'"/{}]*+(?:(?:(?&string)|(?&comment)|(?&code)|/)[^\'"/{}]*+)*+})
)';

const RULE_BLOCK = '(?<name>[a-z_]++):(?<rules>[^\'"/{};]*+(?:(?:(?&string)|(?&comment)|(?&code)|/|})[^\'"/{};]*+)*+);';

$usedTerminals = array_flip(array(
    'T_VARIABLE', 'T_STRING', 'T_INLINE_HTML', 'T_ENCAPSED_AND_WHITESPACE',
    'T_LNUMBER', 'T_DNUMBER', 'T_CONSTANT_ENCAPSED_STRING', 'T_STRING_VARNAME', 'T_NUM_STRING'
));
$unusedNonterminals = array_flip(array(
    'case_separator', 'optional_comma'
));

function regex($regex) {
    return '~' . LIB . '(?:' . str_replace('~', '\~', $regex) . ')~';
}

function magicSplit($regex, $string) {
    $pieces = preg_split(regex('(?:(?&string)|(?&comment)|(?&code))(*SKIP)(*FAIL)|' . $regex), $string);

    foreach ($pieces as &$piece) {
        $piece = trim($piece);
    }

    return array_filter($pieces);
}

echo '<pre>';

////////////////////
////////////////////
////////////////////

list($defs, $ruleBlocks) = magicSplit('%%', file_get_contents(GRAMMAR_FILE));

if ('' !== trim(preg_replace(regex(RULE_BLOCK), '', $ruleBlocks))) {
    die('Not all rule blocks were properly recognized!');
}

preg_match_all(regex(RULE_BLOCK), $ruleBlocks, $ruleBlocksMatches, PREG_SET_ORDER);
foreach ($ruleBlocksMatches as $match) {
    $ruleBlockName = $match['name'];
    $rules = magicSplit('\|', $match['rules']);

    foreach ($rules as &$rule) {
        $parts = magicSplit('\s+', $rule);
        $usedParts = array();

        foreach ($parts as $part) {
            if ('{' === $part[0]) {
                preg_match_all('~\$([0-9]+)~', $part, $backReferencesMatches, PREG_SET_ORDER);
                foreach ($backReferencesMatches as $match) {
                    $usedParts[$match[1]] = true;
                }
            }
        }

        $i = 1;
        foreach ($parts as &$part) {
            if ('/' === $part[0]) {
                continue;
            }

            if (isset($usedParts[$i])) {
                if ('\'' === $part[0] || '{' === $part[0]
                    || (ctype_upper($part[0]) && !isset($usedTerminals[$part]))
                    || (ctype_lower($part[0]) && isset($unusedNonterminals[$part]))
                ) {
                    $part = '<span style="background-color: red; color: white;">' . $part . '</span>';
                } else {
                    $part = '<strong><em>' . $part . '</em></strong>';
                }
            } elseif ((ctype_upper($part[0]) && isset($usedTerminals[$part]))
                      || (ctype_lower($part[0]) && !isset($unusedNonterminals[$part]))

            ) {
                $part = '<span style="background-color: blue; color: white;">' . $part . '</span>';
            }

            ++$i;
        }

        $rule = implode(' ', $parts);
    }

    echo $ruleBlockName, ':', "\n", '      ', implode("\n" . '    | ', $rules), "\n", ';', "\n\n";
}<?php
$meta #
#semval($) $this->yyval
#semval($,%t) $this->yyval
#semval(%n) $this->yyastk[$this->stackPos-(%l-%n)]
#semval(%n,%t) $this->yyastk[$this->stackPos-(%l-%n)]
#include;

/* This is an automatically GENERATED file, which should not be manually edited.
 * Instead edit one of the following:
 *  * the grammar file grammar/zend_language_parser.phpy
 *  * the parser skeleton grammar/kymacc.php.parser
 *  * the preprocessing script grammar/rebuildParser.php
 *
 * The skeleton for this parser was written by Moriyoshi Koizumi and is based on
 * the work by Masato Bito and is in the PUBLIC DOMAIN.
 */
#if -t
class #(-p)_Debug extends #(-p)
#endif
#ifnot -t
class #(-p)
#endif
{
#ifnot -t
    const TOKEN_NONE    = -1;
    const TOKEN_INVALID = #(YYBADCH);

    const TOKEN_MAP_SIZE = #(YYMAXLEX);

    const YYLAST       = #(YYLAST);
    const YY2TBLSTATE  = #(YY2TBLSTATE);
    const YYGLAST      = #(YYGLAST);
    const YYNLSTATES   = #(YYNLSTATES);
    const YYUNEXPECTED = #(YYUNEXPECTED);
    const YYDEFAULT    = #(YYDEFAULT);

    // {{{ Tokens
#tokenval
    const %s = %n;
#endtokenval
    // }}}

    /* @var array Map of token ids to their respective names */
    protected static $terminals = array(
        #listvar terminals
        , "???"
    );

    /* @var array Map which translates lexer tokens to internal tokens */
    protected static $translate = array(
        #listvar yytranslate
    );

    protected static $yyaction = array(
        #listvar yyaction
    );

    protected static $yycheck = array(
        #listvar yycheck
    );

    protected static $yybase = array(
        #listvar yybase
    );

    protected static $yydefault = array(
        #listvar yydefault
    );

    protected static $yygoto = array(
        #listvar yygoto
    );

    protected static $yygcheck = array(
        #listvar yygcheck
    );

    protected static $yygbase = array(
        #listvar yygbase
    );

    protected static $yygdefault = array(
        #listvar yygdefault
    );

    protected static $yylhs = array(
        #listvar yylhs
    );

    protected static $yylen = array(
        #listvar yylen
    );

    protected $yyval;
    protected $yyastk;
    protected $stackPos;
    protected $lexer;

    /**
     * Creates a parser instance.
     *
     * @param PHPParser_Lexer $lexer A lexer
     */
    public function __construct(PHPParser_Lexer $lexer) {
        $this->lexer = $lexer;
    }
#endif
#if -t
    protected static $yyproduction = array(
        #production-strings;
    );

    protected function yyprintln($msg) {
        echo $msg, "\n";
    }

    protected function YYTRACE_NEWSTATE($state, $tokenId) {
        $this->yyprintln(
            '% State ' . $state
          . ', Lookahead ' . ($tokenId == self::TOKEN_NONE ? '--none--' : self::$terminals[$tokenId])
        );
    }

    protected function YYTRACE_READ($tokenId) {
        $this->yyprintln('% Reading ' . self::$terminals[$tokenId]);
    }

    protected function YYTRACE_SHIFT($tokenId) {
        $this->yyprintln('% Shift ' . self::$terminals[$tokenId]);
    }

    protected function YYTRACE_ACCEPT() {
        $this->yyprintln('% Accepted.');
    }

    protected function YYTRACE_REDUCE($n) {
        $this->yyprintln('% Reduce by (' . $n . ') ' . self::$yyproduction[$n]);
    }

    protected function YYTRACE_POP($state) {
        $this->yyprintln('% Recovering, uncovers state ' . $state);
    }

    protected function YYTRACE_DISCARD($tokenId) {
        $this->yyprintln('% Discard ' . self::$terminals[$tokenId]);
    }
#endif

    /**
#ifnot -t
     * Parses PHP code into a node tree.
#endif
#if -t
     * Parses PHP code into a node tree and prints out debugging information.
#endif
     *
     * @param string $code The source code to parse
     *
     * @return PHPParser_Node[] Array of statements
     */
    public function parse($code) {
        $this->lexer->startLexing($code);

        // We start off with no lookahead-token
        $tokenId = self::TOKEN_NONE;

        // The attributes for a node are taken from the first and last token of the node.
        // From the first token only the startAttributes are taken and from the last only
        // the endAttributes. Both are merged using the array union operator (+).
        $startAttributes = array('startLine' => 1);
        $endAttributes   = array();

        // In order to figure out the attributes for the starting token, we have to keep
        // them in a stack
        $attributeStack = array($startAttributes);

        // Start off in the initial state and keep a stack of previous states
        $state = 0;
        $stateStack = array($state);

        // AST stack (?)
        $this->yyastk = array();

        // Current position in the stack(s)
        $this->stackPos = 0;

        for (;;) {
#if -t
            $this->YYTRACE_NEWSTATE($state, $tokenId);

#endif
            if (self::$yybase[$state] == 0) {
                $yyn = self::$yydefault[$state];
            } else {
                if ($tokenId === self::TOKEN_NONE) {
                    // Fetch the next token id from the lexer and fetch additional info by-ref.
                    // The end attributes are fetched into a temporary variable and only set once the token is really
                    // shifted (not during read). Otherwise you would sometimes get off-by-one errors, when a rule is
                    // reduced after a token was read but not yet shifted.
                    $origTokenId = $this->lexer->getNextToken($tokenValue, $startAttributes, $nextEndAttributes);

                    // map the lexer token id to the internally used token id's
                    $tokenId = $origTokenId >= 0 && $origTokenId < self::TOKEN_MAP_SIZE
                        ? self::$translate[$origTokenId]
                        : self::TOKEN_INVALID;

                    if ($tokenId === self::TOKEN_INVALID) {
                        throw new RangeException(sprintf(
                            'The lexer returned an invalid token (id=%d, value=%s)',
                            $origTokenId, $tokenValue
                        ));
                    }

                    $attributeStack[$this->stackPos] = $startAttributes;
#if -t

                    $this->YYTRACE_READ($tokenId);
#endif
                }

                if ((($yyn = self::$yybase[$state] + $tokenId) >= 0
                     && $yyn < self::YYLAST && self::$yycheck[$yyn] == $tokenId
                     || ($state < self::YY2TBLSTATE
                        && ($yyn = self::$yybase[$state + self::YYNLSTATES] + $tokenId) >= 0
                        && $yyn < self::YYLAST
                        && self::$yycheck[$yyn] == $tokenId))
                    && ($yyn = self::$yyaction[$yyn]) != self::YYDEFAULT) {
                    /*
                     * >= YYNLSTATE: shift and reduce
                     * > 0: shift
                     * = 0: accept
                     * < 0: reduce
                     * = -YYUNEXPECTED: error
                     */
                    if ($yyn > 0) {
                        /* shift */
#if -t
                        $this->YYTRACE_SHIFT($tokenId);

#endif
                        ++$this->stackPos;

                        $stateStack[$this->stackPos]     = $state = $yyn;
                        $this->yyastk[$this->stackPos]   = $tokenValue;
                        $attributeStack[$this->stackPos] = $startAttributes;
                        $endAttributes = $nextEndAttributes;
                        $tokenId = self::TOKEN_NONE;

                        if ($yyn < self::YYNLSTATES)
                            continue;

                        /* $yyn >= YYNLSTATES means shift-and-reduce */
                        $yyn -= self::YYNLSTATES;
                    } else {
                        $yyn = -$yyn;
                    }
                } else {
                    $yyn = self::$yydefault[$state];
                }
            }

            for (;;) {
                /* reduce/error */
                if ($yyn == 0) {
                    /* accept */
#if -t
                    $this->YYTRACE_ACCEPT();
#endif
                    return $this->yyval;
                } elseif ($yyn != self::YYUNEXPECTED) {
                    /* reduce */
#if -t
                    $this->YYTRACE_REDUCE($yyn);
#endif
                    try {
                        $this->{'yyn' . $yyn}(
                            $attributeStack[$this->stackPos - self::$yylen[$yyn]]
                            + $endAttributes
                        );
                    } catch (PHPParser_Error $e) {
                        if (-1 === $e->getRawLine()) {
                            $e->setRawLine($startAttributes['startLine']);
                        }

                        throw $e;
                    }

                    /* Goto - shift nonterminal */
                    $this->stackPos -= self::$yylen[$yyn];
                    $yyn = self::$yylhs[$yyn];
                    if (($yyp = self::$yygbase[$yyn] + $stateStack[$this->stackPos]) >= 0
                         && $yyp < self::YYGLAST
                         && self::$yygcheck[$yyp] == $yyn) {
                        $state = self::$yygoto[$yyp];
                    } else {
                        $state = self::$yygdefault[$yyn];
                    }

                    ++$this->stackPos;

                    $stateStack[$this->stackPos]     = $state;
                    $this->yyastk[$this->stackPos]   = $this->yyval;
                    $attributeStack[$this->stackPos] = $startAttributes;
                } else {
                    /* error */
                    $expected = array();

                    $base = self::$yybase[$state];
                    for ($i = 0; $i < self::TOKEN_MAP_SIZE; ++$i) {
                        $n = $base + $i;
                        if ($n >= 0 && $n < self::YYLAST && self::$yycheck[$n] == $i
                         || $state < self::YY2TBLSTATE
                            && ($n = self::$yybase[$state + self::YYNLSTATES] + $i) >= 0
                            && $n < self::YYLAST && self::$yycheck[$n] == $i
                        ) {
                            if (self::$yyaction[$n] != self::YYUNEXPECTED) {
                                if (count($expected) == 4) {
                                    /* Too many expected tokens */
                                    $expected = array();
                                    break;
                                }

                                $expected[] = self::$terminals[$i];
                            }
                        }
                    }

                    $expectedString = '';
                    if ($expected) {
                        $expectedString = ', expecting ' . implode(' or ', $expected);
                    }

                    throw new PHPParser_Error(
                        'Syntax error, unexpected ' . self::$terminals[$tokenId] . $expectedString,
                        $startAttributes['startLine']
                    );
                }

                if ($state < self::YYNLSTATES)
                    break;
                /* >= YYNLSTATES means shift-and-reduce */
                $yyn = $state - self::YYNLSTATES;
            }
        }
    }
#ifnot -t
#reduce

    protected function yyn%n($attributes) {
        %b
    }
#noact

    protected function yyn%n() {
        $this->yyval = $this->yyastk[$this->stackPos];
    }
#endreduce
#endif
}
#tailcode;
%pure_parser
%expect 2

%left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE
%left ','
%left T_LOGICAL_OR
%left T_LOGICAL_XOR
%left T_LOGICAL_AND
%right T_PRINT
%right T_YIELD
%left '=' T_PLUS_EQUAL T_MINUS_EQUAL T_MUL_EQUAL T_DIV_EQUAL T_CONCAT_EQUAL T_MOD_EQUAL T_AND_EQUAL T_OR_EQUAL T_XOR_EQUAL T_SL_EQUAL T_SR_EQUAL
%left '?' ':'
%left T_BOOLEAN_OR
%left T_BOOLEAN_AND
%left '|'
%left '^'
%left '&'
%nonassoc T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL
%nonassoc '<' T_IS_SMALLER_OR_EQUAL '>' T_IS_GREATER_OR_EQUAL
%left T_SL T_SR
%left '+' '-' '.'
%left '*' '/' '%'
%right '!'
%nonassoc T_INSTANCEOF
%right '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@'
%right '['
%nonassoc T_NEW T_CLONE
%token T_EXIT
%token T_IF
%left T_ELSEIF
%left T_ELSE
%left T_ENDIF
%token T_LNUMBER
%token T_DNUMBER
%token T_STRING
%token T_STRING_VARNAME
%token T_VARIABLE
%token T_NUM_STRING
%token T_INLINE_HTML
%token T_CHARACTER
%token T_BAD_CHARACTER
%token T_ENCAPSED_AND_WHITESPACE
%token T_CONSTANT_ENCAPSED_STRING
%token T_ECHO
%token T_DO
%token T_WHILE
%token T_ENDWHILE
%token T_FOR
%token T_ENDFOR
%token T_FOREACH
%token T_ENDFOREACH
%token T_DECLARE
%token T_ENDDECLARE
%token T_AS
%token T_SWITCH
%token T_ENDSWITCH
%token T_CASE
%token T_DEFAULT
%token T_BREAK
%token T_CONTINUE
%token T_GOTO
%token T_FUNCTION
%token T_CONST
%token T_RETURN
%token T_TRY
%token T_CATCH
%token T_FINALLY
%token T_THROW
%token T_USE
%token T_INSTEADOF
%token T_GLOBAL
%right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC
%token T_VAR
%token T_UNSET
%token T_ISSET
%token T_EMPTY
%token T_HALT_COMPILER
%token T_CLASS
%token T_TRAIT
%token T_INTERFACE
%token T_EXTENDS
%token T_IMPLEMENTS
%token T_OBJECT_OPERATOR
%token T_DOUBLE_ARROW
%token T_LIST
%token T_ARRAY
%token T_CALLABLE
%token T_CLASS_C
%token T_TRAIT_C
%token T_METHOD_C
%token T_FUNC_C
%token T_LINE
%token T_FILE
%token T_COMMENT
%token T_DOC_COMMENT
%token T_OPEN_TAG
%token T_OPEN_TAG_WITH_ECHO
%token T_CLOSE_TAG
%token T_WHITESPACE
%token T_START_HEREDOC
%token T_END_HEREDOC
%token T_DOLLAR_OPEN_CURLY_BRACES
%token T_CURLY_OPEN
%token T_PAAMAYIM_NEKUDOTAYIM
%token T_NAMESPACE
%token T_NS_C
%token T_DIR
%token T_NS_SEPARATOR

%%

start:
    top_statement_list                                      { $$ = Stmt_Namespace::postprocess($1); }
;

top_statement_list:
      top_statement_list top_statement                      { pushNormalizing($1, $2); }
    | /* empty */                                           { init(); }
;

namespace_name:
      T_STRING                                              { init($1); }
    | namespace_name T_NS_SEPARATOR T_STRING                { push($1, $3); }
;

top_statement:
      statement                                             { $$ = $1; }
    | function_declaration_statement                        { $$ = $1; }
    | class_declaration_statement                           { $$ = $1; }
    | T_HALT_COMPILER
          { $$ = Stmt_HaltCompiler[$this->lexer->handleHaltCompiler()]; }
    | T_NAMESPACE namespace_name ';'                        { $$ = Stmt_Namespace[Name[$2], null]; }
    | T_NAMESPACE namespace_name '{' top_statement_list '}' { $$ = Stmt_Namespace[Name[$2], $4]; }
    | T_NAMESPACE '{' top_statement_list '}'                { $$ = Stmt_Namespace[null,     $3]; }
    | T_USE use_declarations ';'                            { $$ = Stmt_Use[$2]; }
    | T_CONST constant_declaration_list ';'                 { $$ = Stmt_Const[$2]; }
;

use_declarations:
      use_declarations ',' use_declaration                  { push($1, $3); }
    | use_declaration                                       { init($1); }
;

use_declaration:
      namespace_name                                        { $$ = Stmt_UseUse[Name[$1], null]; }
    | namespace_name T_AS T_STRING                          { $$ = Stmt_UseUse[Name[$1], $3]; }
    | T_NS_SEPARATOR namespace_name                         { $$ = Stmt_UseUse[Name[$2], null]; }
    | T_NS_SEPARATOR namespace_name T_AS T_STRING           { $$ = Stmt_UseUse[Name[$2], $4]; }
;

constant_declaration_list:
      constant_declaration_list ',' constant_declaration    { push($1, $3); }
    | constant_declaration                                  { init($1); }
;

constant_declaration:
    T_STRING '=' static_scalar                              { $$ = Const[$1, $3]; }
;

inner_statement_list:
      inner_statement_list inner_statement                  { pushNormalizing($1, $2); }
    | /* empty */                                           { init(); }
;

inner_statement:
      statement                                             { $$ = $1; }
    | function_declaration_statement                        { $$ = $1; }
    | class_declaration_statement                           { $$ = $1; }
    | T_HALT_COMPILER                                       { error('__halt_compiler() can only be used from the outermost scope'); }
;

statement:
      '{' inner_statement_list '}'                          { $$ = $2; }
    | T_IF parentheses_expr statement elseif_list else_single
          { $$ = Stmt_If[$2, [stmts: toArray($3), elseifs: $4, else: $5]]; }
    | T_IF parentheses_expr ':' inner_statement_list new_elseif_list new_else_single T_ENDIF ';'
          { $$ = Stmt_If[$2, [stmts: $4, elseifs: $5, else: $6]]; }
    | T_WHILE parentheses_expr while_statement              { $$ = Stmt_While[$2, $3]; }
    | T_DO statement T_WHILE parentheses_expr ';'           { $$ = Stmt_Do   [$4, toArray($2)]; }
    | T_FOR '(' for_expr ';'  for_expr ';' for_expr ')' for_statement
          { $$ = Stmt_For[[init: $3, cond: $5, loop: $7, stmts: $9]]; }
    | T_SWITCH parentheses_expr switch_case_list            { $$ = Stmt_Switch[$2, $3]; }
    | T_BREAK ';'                                           { $$ = Stmt_Break[null]; }
    | T_BREAK expr ';'                                      { $$ = Stmt_Break[$2]; }
    | T_CONTINUE ';'                                        { $$ = Stmt_Continue[null]; }
    | T_CONTINUE expr ';'                                   { $$ = Stmt_Continue[$2]; }
    | T_RETURN ';'                                          { $$ = Stmt_Return[null]; }
    | T_RETURN expr ';'                                     { $$ = Stmt_Return[$2]; }
    | yield_expr ';'                                        { $$ = $1; }
    | T_GLOBAL global_var_list ';'                          { $$ = Stmt_Global[$2]; }
    | T_STATIC static_var_list ';'                          { $$ = Stmt_Static[$2]; }
    | T_ECHO expr_list ';'                                  { $$ = Stmt_Echo[$2]; }
    | T_INLINE_HTML                                         { $$ = Stmt_InlineHTML[$1]; }
    | expr ';'                                              { $$ = $1; }
    | T_UNSET '(' variables_list ')' ';'                    { $$ = Stmt_Unset[$3]; }
    | T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement
          { $$ = Stmt_Foreach[$3, $5[0], [keyVar: null, byRef: $5[1], stmts: $7]]; }
    | T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW foreach_variable ')' foreach_statement
          { $$ = Stmt_Foreach[$3, $7[0], [keyVar: $5, byRef: $7[1], stmts: $9]]; }
    | T_DECLARE '(' declare_list ')' declare_statement      { $$ = Stmt_Declare[$3, $5]; }
    | ';'                                                   { $$ = array(); /* means: no statement */ }
    | T_TRY '{' inner_statement_list '}' catches optional_finally
          { $$ = Stmt_TryCatch[$3, $5, $6]; }
    | T_THROW expr ';'                                      { $$ = Stmt_Throw[$2]; }
    | T_GOTO T_STRING ';'                                   { $$ = Stmt_Goto[$2]; }
    | T_STRING ':'                                          { $$ = Stmt_Label[$1]; }
;

catches:
      /* empty */                                           { init(); }
    | catches catch                                         { push($1, $2); }
;

catch:
    T_CATCH '(' name T_VARIABLE ')' '{' inner_statement_list '}'
        { $$ = Stmt_Catch[$3, parseVar($4), $7]; }
;

optional_finally:
      /* empty */                                           { $$ = null; }
    | T_FINALLY '{' inner_statement_list '}'                { $$ = $3; }
;

variables_list:
      variable                                              { init($1); }
    | variables_list ',' variable                           { push($1, $3); }
;

optional_ref:
      /* empty */                                           { $$ = false; }
    | '&'                                                   { $$ = true; }
;

function_declaration_statement:
    T_FUNCTION optional_ref T_STRING '(' parameter_list ')' '{' inner_statement_list '}'
        { $$ = Stmt_Function[$3, [byRef: $2, params: $5, stmts: $8]]; }
;

class_declaration_statement:
      class_entry_type T_STRING extends_from implements_list '{' class_statement_list '}'
          { $$ = Stmt_Class[$2, [type: $1, extends: $3, implements: $4, stmts: $6]]; }
    | T_INTERFACE T_STRING interface_extends_list '{' class_statement_list '}'
          { $$ = Stmt_Interface[$2, [extends: $3, stmts: $5]]; }
    | T_TRAIT T_STRING '{' class_statement_list '}'
          { $$ = Stmt_Trait[$2, $4]; }
;

class_entry_type:
      T_CLASS                                               { $$ = 0; }
    | T_ABSTRACT T_CLASS                                    { $$ = Stmt_Class::MODIFIER_ABSTRACT; }
    | T_FINAL T_CLASS                                       { $$ = Stmt_Class::MODIFIER_FINAL; }
;

extends_from:
      /* empty */                                           { $$ = null; }
    | T_EXTENDS name                                        { $$ = $2; }
;

interface_extends_list:
      /* empty */                                           { $$ = array(); }
    | T_EXTENDS name_list                                   { $$ = $2; }
;

implements_list:
      /* empty */                                           { $$ = array(); }
    | T_IMPLEMENTS name_list                                { $$ = $2; }
;

name_list:
      name                                                  { init($1); }
    | name_list ',' name                                    { push($1, $3); }
;

for_statement:
      statement                                             { $$ = toArray($1); }
    | ':' inner_statement_list T_ENDFOR ';'                 { $$ = $2; }
;

foreach_statement:
      statement                                             { $$ = toArray($1); }
    | ':' inner_statement_list T_ENDFOREACH ';'             { $$ = $2; }
;

declare_statement:
      statement                                             { $$ = toArray($1); }
    | ':' inner_statement_list T_ENDDECLARE ';'             { $$ = $2; }
;

declare_list:
      declare_list_element                                  { init($1); }
    | declare_list ',' declare_list_element                 { push($1, $3); }
;

declare_list_element:
      T_STRING '=' static_scalar                            { $$ = Stmt_DeclareDeclare[$1, $3]; }
;

switch_case_list:
      '{' case_list '}'                                     { $$ = $2; }
    | '{' ';' case_list '}'                                 { $$ = $3; }
    | ':' case_list T_ENDSWITCH ';'                         { $$ = $2; }
    | ':' ';' case_list T_ENDSWITCH ';'                     { $$ = $3; }
;

case_list:
      /* empty */                                           { init(); }
    | case_list case                                        { push($1, $2); }
;

case:
      T_CASE expr case_separator inner_statement_list       { $$ = Stmt_Case[$2, $4]; }
    | T_DEFAULT case_separator inner_statement_list         { $$ = Stmt_Case[null, $3]; }
;

case_separator:
      ':'
    | ';'
;

while_statement:
      statement                                             { $$ = toArray($1); }
    | ':' inner_statement_list T_ENDWHILE ';'               { $$ = $2; }
;

elseif_list:
      /* empty */                                           { init(); }
    | elseif_list elseif                                    { push($1, $2); }
;

elseif:
      T_ELSEIF parentheses_expr statement                   { $$ = Stmt_ElseIf[$2, toArray($3)]; }
;

new_elseif_list:
      /* empty */                                           { init(); }
    | new_elseif_list new_elseif                            { push($1, $2); }
;

new_elseif:
     T_ELSEIF parentheses_expr ':' inner_statement_list     { $$ = Stmt_ElseIf[$2, $4]; }
;

else_single:
      /* empty */                                           { $$ = null; }
    | T_ELSE statement                                      { $$ = Stmt_Else[toArray($2)]; }
;

new_else_single:
      /* empty */                                           { $$ = null; }
    | T_ELSE ':' inner_statement_list                       { $$ = Stmt_Else[$3]; }
;

foreach_variable:
      variable                                              { $$ = array($1, false); }
    | '&' variable                                          { $$ = array($2, true); }
    | list_expr                                             { $$ = array($1, false); }
;

parameter_list:
      non_empty_parameter_list                              { $$ = $1; }
    | /* empty */                                           { $$ = array(); }
;

non_empty_parameter_list:
      parameter                                             { init($1); }
    | non_empty_parameter_list ',' parameter                { push($1, $3); }
;

parameter:
      optional_class_type optional_ref T_VARIABLE
          { $$ = Param[parseVar($3), null, $1, $2]; }
    | optional_class_type optional_ref T_VARIABLE '=' static_scalar
          { $$ = Param[parseVar($3), $5, $1, $2]; }
;

optional_class_type:
      /* empty */                                           { $$ = null; }
    | name                                                  { $$ = $1; }
    | T_ARRAY                                               { $$ = 'array'; }
    | T_CALLABLE                                            { $$ = 'callable'; }
;

argument_list:
      '(' ')'                                               { $$ = array(); }
    | '(' non_empty_argument_list ')'                       { $$ = $2; }
    | '(' yield_expr ')'                                    { $$ = array(Arg[$2, false]); }
;

non_empty_argument_list:
      argument                                              { init($1); }
    | non_empty_argument_list ',' argument                  { push($1, $3); }
;

argument:
      expr                                                  { $$ = Arg[$1, false]; }
    | '&' variable                                          { $$ = Arg[$2, true]; }
;

global_var_list:
      global_var_list ',' global_var                        { push($1, $3); }
    | global_var                                            { init($1); }
;

global_var:
      T_VARIABLE                                            { $$ = Expr_Variable[parseVar($1)]; }
    | '$' variable                                          { $$ = Expr_Variable[$2]; }
    | '$' '{' expr '}'                                      { $$ = Expr_Variable[$3]; }
;

static_var_list:
      static_var_list ',' static_var                        { push($1, $3); }
    | static_var                                            { init($1); }
;

static_var:
      T_VARIABLE                                            { $$ = Stmt_StaticVar[parseVar($1), null]; }
    | T_VARIABLE '=' static_scalar                          { $$ = Stmt_StaticVar[parseVar($1), $3]; }
;

class_statement_list:
      class_statement_list class_statement                  { push($1, $2); }
    | /* empty */                                           { init(); }
;

class_statement:
      variable_modifiers property_declaration_list ';'      { $$ = Stmt_Property[$1, $2]; }
    | T_CONST constant_declaration_list ';'                 { $$ = Stmt_ClassConst[$2]; }
    | method_modifiers T_FUNCTION optional_ref T_STRING '(' parameter_list ')' method_body
          { $$ = Stmt_ClassMethod[$4, [type: $1, byRef: $3, params: $6, stmts: $8]]; }
    | T_USE name_list trait_adaptations                     { $$ = Stmt_TraitUse[$2, $3]; }
;

trait_adaptations:
      ';'                                                   { $$ = array(); }
    | '{' trait_adaptation_list '}'                         { $$ = $2; }
;

trait_adaptation_list:
      /* empty */                                           { init(); }
    | trait_adaptation_list trait_adaptation                { push($1, $2); }
;

trait_adaptation:
      trait_method_reference_fully_qualified T_INSTEADOF name_list ';'
          { $$ = Stmt_TraitUseAdaptation_Precedence[$1[0], $1[1], $3]; }
    | trait_method_reference T_AS member_modifier T_STRING ';'
          { $$ = Stmt_TraitUseAdaptation_Alias[$1[0], $1[1], $3, $4]; }
    | trait_method_reference T_AS member_modifier ';'
          { $$ = Stmt_TraitUseAdaptation_Alias[$1[0], $1[1], $3, null]; }
    | trait_method_reference T_AS T_STRING ';'
          { $$ = Stmt_TraitUseAdaptation_Alias[$1[0], $1[1], null, $3]; }
;

trait_method_reference_fully_qualified:
      name T_PAAMAYIM_NEKUDOTAYIM T_STRING                  { $$ = array($1, $3); }
;
trait_method_reference:
      trait_method_reference_fully_qualified                { $$ = $1; }
    | T_STRING                                              { $$ = array(null, $1); }
;

method_body:
      ';' /* abstract method */                             { $$ = null; }
    | '{' inner_statement_list '}'                          { $$ = $2; }
;

variable_modifiers:
      non_empty_member_modifiers                            { $$ = $1; }
    | T_VAR                                                 { $$ = Stmt_Class::MODIFIER_PUBLIC; }
;

method_modifiers:
      /* empty */                                           { $$ = Stmt_Class::MODIFIER_PUBLIC; }
    | non_empty_member_modifiers                            { $$ = $1; }
;

non_empty_member_modifiers:
      member_modifier                                       { $$ = $1; }
    | non_empty_member_modifiers member_modifier            { Stmt_Class::verifyModifier($1, $2); $$ = $1 | $2; }
;

member_modifier:
      T_PUBLIC                                              { $$ = Stmt_Class::MODIFIER_PUBLIC; }
    | T_PROTECTED                                           { $$ = Stmt_Class::MODIFIER_PROTECTED; }
    | T_PRIVATE                                             { $$ = Stmt_Class::MODIFIER_PRIVATE; }
    | T_STATIC                                              { $$ = Stmt_Class::MODIFIER_STATIC; }
    | T_ABSTRACT                                            { $$ = Stmt_Class::MODIFIER_ABSTRACT; }
    | T_FINAL                                               { $$ = Stmt_Class::MODIFIER_FINAL; }
;

property_declaration_list:
      property_declaration                                  { init($1); }
    | property_declaration_list ',' property_declaration    { push($1, $3); }
;

property_declaration:
      T_VARIABLE                                            { $$ = Stmt_PropertyProperty[parseVar($1), null]; }
    | T_VARIABLE '=' static_scalar                          { $$ = Stmt_PropertyProperty[parseVar($1), $3]; }
;

expr_list:
      expr_list ',' expr                                    { push($1, $3); }
    | expr                                                  { init($1); }
;

for_expr:
      /* empty */                                           { $$ = array(); }
    | expr_list                                             { $$ = $1; }
;

expr:
      variable                                              { $$ = $1; }
    | list_expr '=' expr                                    { $$ = Expr_Assign[$1, $3]; }
    | variable '=' expr                                     { $$ = Expr_Assign[$1, $3]; }
    | variable '=' '&' variable                             { $$ = Expr_AssignRef[$1, $4]; }
    | variable '=' '&' new_expr                             { $$ = Expr_AssignRef[$1, $4]; }
    | new_expr                                              { $$ = $1; }
    | T_CLONE expr                                          { $$ = Expr_Clone[$2]; }
    | variable T_PLUS_EQUAL expr                            { $$ = Expr_AssignPlus      [$1, $3]; }
    | variable T_MINUS_EQUAL expr                           { $$ = Expr_AssignMinus     [$1, $3]; }
    | variable T_MUL_EQUAL expr                             { $$ = Expr_AssignMul       [$1, $3]; }
    | variable T_DIV_EQUAL expr                             { $$ = Expr_AssignDiv       [$1, $3]; }
    | variable T_CONCAT_EQUAL expr                          { $$ = Expr_AssignConcat    [$1, $3]; }
    | variable T_MOD_EQUAL expr                             { $$ = Expr_AssignMod       [$1, $3]; }
    | variable T_AND_EQUAL expr                             { $$ = Expr_AssignBitwiseAnd[$1, $3]; }
    | variable T_OR_EQUAL expr                              { $$ = Expr_AssignBitwiseOr [$1, $3]; }
    | variable T_XOR_EQUAL expr                             { $$ = Expr_AssignBitwiseXor[$1, $3]; }
    | variable T_SL_EQUAL expr                              { $$ = Expr_AssignShiftLeft [$1, $3]; }
    | variable T_SR_EQUAL expr                              { $$ = Expr_AssignShiftRight[$1, $3]; }
    | variable T_INC                                        { $$ = Expr_PostInc[$1]; }
    | T_INC variable                                        { $$ = Expr_PreInc [$2]; }
    | variable T_DEC                                        { $$ = Expr_PostDec[$1]; }
    | T_DEC variable                                        { $$ = Expr_PreDec [$2]; }
    | expr T_BOOLEAN_OR expr                                { $$ = Expr_BooleanOr [$1, $3]; }
    | expr T_BOOLEAN_AND expr                               { $$ = Expr_BooleanAnd[$1, $3]; }
    | expr T_LOGICAL_OR expr                                { $$ = Expr_LogicalOr [$1, $3]; }
    | expr T_LOGICAL_AND expr                               { $$ = Expr_LogicalAnd[$1, $3]; }
    | expr T_LOGICAL_XOR expr                               { $$ = Expr_LogicalXor[$1, $3]; }
    | expr '|' expr                                         { $$ = Expr_BitwiseOr [$1, $3]; }
    | expr '&' expr                                         { $$ = Expr_BitwiseAnd[$1, $3]; }
    | expr '^' expr                                         { $$ = Expr_BitwiseXor[$1, $3]; }
    | expr '.' expr                                         { $$ = Expr_Concat    [$1, $3]; }
    | expr '+' expr                                         { $$ = Expr_Plus      [$1, $3]; }
    | expr '-' expr                                         { $$ = Expr_Minus     [$1, $3]; }
    | expr '*' expr                                         { $$ = Expr_Mul       [$1, $3]; }
    | expr '/' expr                                         { $$ = Expr_Div       [$1, $3]; }
    | expr '%' expr                                         { $$ = Expr_Mod       [$1, $3]; }
    | expr T_SL expr                                        { $$ = Expr_ShiftLeft [$1, $3]; }
    | expr T_SR expr                                        { $$ = Expr_ShiftRight[$1, $3]; }
    | '+' expr %prec T_INC                                  { $$ = Expr_UnaryPlus [$2]; }
    | '-' expr %prec T_INC                                  { $$ = Expr_UnaryMinus[$2]; }
    | '!' expr                                              { $$ = Expr_BooleanNot[$2]; }
    | '~' expr                                              { $$ = Expr_BitwiseNot[$2]; }
    | expr T_IS_IDENTICAL expr                              { $$ = Expr_Identical     [$1, $3]; }
    | expr T_IS_NOT_IDENTICAL expr                          { $$ = Expr_NotIdentical  [$1, $3]; }
    | expr T_IS_EQUAL expr                                  { $$ = Expr_Equal         [$1, $3]; }
    | expr T_IS_NOT_EQUAL expr                              { $$ = Expr_NotEqual      [$1, $3]; }
    | expr '<' expr                                         { $$ = Expr_Smaller       [$1, $3]; }
    | expr T_IS_SMALLER_OR_EQUAL expr                       { $$ = Expr_SmallerOrEqual[$1, $3]; }
    | expr '>' expr                                         { $$ = Expr_Greater       [$1, $3]; }
    | expr T_IS_GREATER_OR_EQUAL expr                       { $$ = Expr_GreaterOrEqual[$1, $3]; }
    | expr T_INSTANCEOF class_name_reference                { $$ = Expr_Instanceof    [$1, $3]; }
    | parentheses_expr                                      { $$ = $1; }
    /* we need a separate '(' new_expr ')' rule to avoid problems caused by a s/r conflict */
    | '(' new_expr ')'                                      { $$ = $2; }
    | expr '?' expr ':' expr                                { $$ = Expr_Ternary[$1, $3,   $5]; }
    | expr '?' ':' expr                                     { $$ = Expr_Ternary[$1, null, $4]; }
    | T_ISSET '(' variables_list ')'                        { $$ = Expr_Isset[$3]; }
    | T_EMPTY '(' expr ')'                                  { $$ = Expr_Empty[$3]; }
    | T_INCLUDE expr                                        { $$ = Expr_Include[$2, Expr_Include::TYPE_INCLUDE]; }
    | T_INCLUDE_ONCE expr                                   { $$ = Expr_Include[$2, Expr_Include::TYPE_INCLUDE_ONCE]; }
    | T_EVAL parentheses_expr                               { $$ = Expr_Eval[$2]; }
    | T_REQUIRE expr                                        { $$ = Expr_Include[$2, Expr_Include::TYPE_REQUIRE]; }
    | T_REQUIRE_ONCE expr                                   { $$ = Expr_Include[$2, Expr_Include::TYPE_REQUIRE_ONCE]; }
    | T_INT_CAST expr                                       { $$ = Expr_Cast_Int     [$2]; }
    | T_DOUBLE_CAST expr                                    { $$ = Expr_Cast_Double  [$2]; }
    | T_STRING_CAST expr                                    { $$ = Expr_Cast_String  [$2]; }
    | T_ARRAY_CAST expr                                     { $$ = Expr_Cast_Array   [$2]; }
    | T_OBJECT_CAST expr                                    { $$ = Expr_Cast_Object  [$2]; }
    | T_BOOL_CAST expr                                      { $$ = Expr_Cast_Bool    [$2]; }
    | T_UNSET_CAST expr                                     { $$ = Expr_Cast_Unset   [$2]; }
    | T_EXIT exit_expr                                      { $$ = Expr_Exit         [$2]; }
    | '@' expr                                              { $$ = Expr_ErrorSuppress[$2]; }
    | scalar                                                { $$ = $1; }
    | array_expr                                            { $$ = $1; }
    | scalar_dereference                                    { $$ = $1; }
    | '`' backticks_expr '`'                                { $$ = Expr_ShellExec[$2]; }
    | T_PRINT expr                                          { $$ = Expr_Print[$2]; }
    | T_YIELD                                               { $$ = Expr_Yield[null, null]; }
    | T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars '{' inner_statement_list '}'
          { $$ = Expr_Closure[[static: false, byRef: $2, params: $4, uses: $6, stmts: $8]]; }
    | T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars '{' inner_statement_list '}'
          { $$ = Expr_Closure[[static: true, byRef: $3, params: $5, uses: $7, stmts: $9]]; }
;

parentheses_expr:
      '(' expr ')'                                          { $$ = $2; }
    | '(' yield_expr ')'                                    { $$ = $2; }
;

yield_expr:
      T_YIELD expr                                          { $$ = Expr_Yield[$2, null]; }
    | T_YIELD expr T_DOUBLE_ARROW expr                      { $$ = Expr_Yield[$4, $2]; }
;

array_expr:
      T_ARRAY '(' array_pair_list ')'                       { $$ = Expr_Array[$3]; }
    | '[' array_pair_list ']'                               { $$ = Expr_Array[$2]; }
;

scalar_dereference:
      array_expr '[' dim_offset ']'                         { $$ = Expr_ArrayDimFetch[$1, $3]; }
    | T_CONSTANT_ENCAPSED_STRING '[' dim_offset ']'
          { $$ = Expr_ArrayDimFetch[Scalar_String[Scalar_String::parse($1)], $3]; }
    | scalar_dereference '[' dim_offset ']'                 { $$ = Expr_ArrayDimFetch[$1, $3]; }
    /* alternative array syntax missing intentionally */
;

new_expr:
      T_NEW class_name_reference ctor_arguments             { $$ = Expr_New[$2, $3]; }
;

lexical_vars:
      /* empty */                                           { $$ = array(); }
    | T_USE '(' lexical_var_list ')'                        { $$ = $3; }
;

lexical_var_list:
      lexical_var                                           { init($1); }
    | lexical_var_list ',' lexical_var                      { push($1, $3); }
;

lexical_var:
      optional_ref T_VARIABLE                               { $$ = Expr_ClosureUse[parseVar($2), $1]; }
;

function_call:
      name argument_list                                    { $$ = Expr_FuncCall[$1, $2]; }
    | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM T_STRING argument_list
          { $$ = Expr_StaticCall[$1, $3, $4]; }
    | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '{' expr '}' argument_list
          { $$ = Expr_StaticCall[$1, $4, $6]; }
    | static_property argument_list {
            if ($1 instanceof PHPParser_Node_Expr_StaticPropertyFetch) {
                $$ = Expr_StaticCall[$1->class, Expr_Variable[$1->name], $2];
            } elseif ($1 instanceof PHPParser_Node_Expr_ArrayDimFetch) {
                $tmp = $1;
                while ($tmp->var instanceof PHPParser_Node_Expr_ArrayDimFetch) {
                    $tmp = $tmp->var;
                }

                $$ = Expr_StaticCall[$tmp->var->class, $1, $2];
                $tmp->var = Expr_Variable[$tmp->var->name];
            } else {
                throw new Exception;
            }
          }
    | variable_without_objects argument_list
          { $$ = Expr_FuncCall[$1, $2]; }
    | function_call '[' dim_offset ']'                      { $$ = Expr_ArrayDimFetch[$1, $3]; }
      /* alternative array syntax missing intentionally */
;

class_name:
      T_STATIC                                              { $$ = Name['static']; }
    | name                                                  { $$ = $1; }
;

name:
      namespace_name                                        { $$ = Name[$1]; }
    | T_NS_SEPARATOR namespace_name                         { $$ = Name_FullyQualified[$2]; }
    | T_NAMESPACE T_NS_SEPARATOR namespace_name             { $$ = Name_Relative[$3]; }
;

class_name_reference:
      class_name                                            { $$ = $1; }
    | dynamic_class_name_reference                          { $$ = $1; }
;

dynamic_class_name_reference:
      object_access_for_dcnr                                { $$ = $1; }
    | base_variable                                         { $$ = $1; }
;

class_name_or_var:
      class_name                                            { $$ = $1; }
    | reference_variable                                    { $$ = $1; }
;

object_access_for_dcnr:
    | base_variable T_OBJECT_OPERATOR object_property
          { $$ = Expr_PropertyFetch[$1, $3]; }
    | object_access_for_dcnr T_OBJECT_OPERATOR object_property
          { $$ = Expr_PropertyFetch[$1, $3]; }
    | object_access_for_dcnr '[' dim_offset ']'             { $$ = Expr_ArrayDimFetch[$1, $3]; }
    | object_access_for_dcnr '{' expr '}'                   { $$ = Expr_ArrayDimFetch[$1, $3]; }
;

exit_expr:
      /* empty */                                           { $$ = null; }
    | '(' ')'                                               { $$ = null; }
    | parentheses_expr                                      { $$ = $1; }
;

backticks_expr:
      /* empty */                                           { $$ = array(); }
    | T_ENCAPSED_AND_WHITESPACE                             { $$ = array(Scalar_String::parseEscapeSequences($1, '`')); }
    | encaps_list                                           { parseEncapsed($1, '`'); $$ = $1; }
;

ctor_arguments:
      /* empty */                                           { $$ = array(); }
    | argument_list                                         { $$ = $1; }
;

common_scalar:
      T_LNUMBER                                             { $$ = Scalar_LNumber[Scalar_LNumber::parse($1)]; }
    | T_DNUMBER                                             { $$ = Scalar_DNumber[Scalar_DNumber::parse($1)]; }
    | T_CONSTANT_ENCAPSED_STRING                            { $$ = Scalar_String[Scalar_String::parse($1)]; }
    | T_LINE                                                { $$ = Scalar_LineConst[]; }
    | T_FILE                                                { $$ = Scalar_FileConst[]; }
    | T_DIR                                                 { $$ = Scalar_DirConst[]; }
    | T_CLASS_C                                             { $$ = Scalar_ClassConst[]; }
    | T_TRAIT_C                                             { $$ = Scalar_TraitConst[]; }
    | T_METHOD_C                                            { $$ = Scalar_MethodConst[]; }
    | T_FUNC_C                                              { $$ = Scalar_FuncConst[]; }
    | T_NS_C                                                { $$ = Scalar_NSConst[]; }
    | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC
          { $$ = Scalar_String[Scalar_String::parseDocString($1, $2)]; }
    | T_START_HEREDOC T_END_HEREDOC
          { $$ = Scalar_String['']; }
    | name                                                  { $$ = Expr_ConstFetch[$1]; }
;

static_scalar: /* compile-time evaluated scalars */
      common_scalar                                         { $$ = $1; }
    | class_name T_PAAMAYIM_NEKUDOTAYIM class_const_name    { $$ = Expr_ClassConstFetch[$1, $3]; }
    | '+' static_scalar                                     { $$ = Expr_UnaryPlus[$2]; }
    | '-' static_scalar                                     { $$ = Expr_UnaryMinus[$2]; }
    | T_ARRAY '(' static_array_pair_list ')'                { $$ = Expr_Array[$3]; }
    | '[' static_array_pair_list ']'                        { $$ = Expr_Array[$2]; }
;

scalar:
      common_scalar                                         { $$ = $1; }
    | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM class_const_name
          { $$ = Expr_ClassConstFetch[$1, $3]; }
    | '"' encaps_list '"'
          { parseEncapsed($2, '"'); $$ = Scalar_Encapsed[$2]; }
    | T_START_HEREDOC encaps_list T_END_HEREDOC
          { parseEncapsedDoc($2); $$ = Scalar_Encapsed[$2]; }
;

class_const_name:
      T_STRING                                              { $$ = $1; }
    | T_CLASS                                               { $$ = 'class'; }
;

static_array_pair_list:
      /* empty */                                           { $$ = array(); }
    | non_empty_static_array_pair_list optional_comma       { $$ = $1; }
;

optional_comma:
      /* empty */
    | ','
;

non_empty_static_array_pair_list:
      non_empty_static_array_pair_list ',' static_array_pair { push($1, $3); }
    | static_array_pair                                      { init($1); }
;

static_array_pair:
      static_scalar T_DOUBLE_ARROW static_scalar            { $$ = Expr_ArrayItem[$3, $1,   false]; }
    | static_scalar                                         { $$ = Expr_ArrayItem[$1, null, false]; }
;

variable:
      object_access                                         { $$ = $1; }
    | base_variable                                         { $$ = $1; }
    | function_call                                         { $$ = $1; }
    | new_expr_array_deref                                  { $$ = $1; }
;

new_expr_array_deref:
      '(' new_expr ')' '[' dim_offset ']'                   { $$ = Expr_ArrayDimFetch[$2, $5]; }
    | new_expr_array_deref '[' dim_offset ']'               { $$ = Expr_ArrayDimFetch[$1, $3]; }
      /* alternative array syntax missing intentionally */
;

object_access:
      variable_or_new_expr T_OBJECT_OPERATOR object_property
          { $$ = Expr_PropertyFetch[$1, $3]; }
    | variable_or_new_expr T_OBJECT_OPERATOR object_property argument_list
          { $$ = Expr_MethodCall[$1, $3, $4]; }
    | object_access argument_list                           { $$ = Expr_FuncCall[$1, $2]; }
    | object_access '[' dim_offset ']'                      { $$ = Expr_ArrayDimFetch[$1, $3]; }
    | object_access '{' expr '}'                            { $$ = Expr_ArrayDimFetch[$1, $3]; }
;

variable_or_new_expr:
      variable                                              { $$ = $1; }
    | '(' new_expr ')'                                      { $$ = $2; }
;

variable_without_objects:
      reference_variable                                    { $$ = $1; }
    | '$' variable_without_objects                          { $$ = Expr_Variable[$2]; }
;

base_variable:
      variable_without_objects                              { $$ = $1; }
    | static_property                                       { $$ = $1; }
;

static_property:
      class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '$' reference_variable
          { $$ = Expr_StaticPropertyFetch[$1, $4]; }
    | static_property_with_arrays                           { $$ = $1; }
;

static_property_with_arrays:
      class_name_or_var T_PAAMAYIM_NEKUDOTAYIM T_VARIABLE
          { $$ = Expr_StaticPropertyFetch[$1, parseVar($3)]; }
    | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '$' '{' expr '}'
          { $$ = Expr_StaticPropertyFetch[$1, $5]; }
    | static_property_with_arrays '[' dim_offset ']'        { $$ = Expr_ArrayDimFetch[$1, $3]; }
    | static_property_with_arrays '{' expr '}'              { $$ = Expr_ArrayDimFetch[$1, $3]; }
;

reference_variable:
      reference_variable '[' dim_offset ']'                 { $$ = Expr_ArrayDimFetch[$1, $3]; }
    | reference_variable '{' expr '}'                       { $$ = Expr_ArrayDimFetch[$1, $3]; }
    | T_VARIABLE                                            { $$ = Expr_Variable[parseVar($1)]; }
    | '$' '{' expr '}'                                      { $$ = Expr_Variable[$3]; }
;

dim_offset:
      /* empty */                                           { $$ = null; }
    | expr                                                  { $$ = $1; }
;

object_property:
      T_STRING                                              { $$ = $1; }
    | '{' expr '}'                                          { $$ = $2; }
    | variable_without_objects                              { $$ = $1; }
;

list_expr:
      T_LIST '(' list_expr_elements ')'                     { $$ = Expr_List[$3]; }
;

list_expr_elements:
      list_expr_elements ',' list_expr_element              { push($1, $3); }
    | list_expr_element                                     { init($1); }
;

list_expr_element:
      variable                                              { $$ = $1; }
    | list_expr                                             { $$ = $1; }
    | /* empty */                                           { $$ = null; }
;

array_pair_list:
      /* empty */                                           { $$ = array(); }
    | non_empty_array_pair_list optional_comma              { $$ = $1; }
;

non_empty_array_pair_list:
      non_empty_array_pair_list ',' array_pair              { push($1, $3); }
    | array_pair                                            { init($1); }
;

array_pair:
      expr T_DOUBLE_ARROW expr                              { $$ = Expr_ArrayItem[$3, $1,   false]; }
    | expr                                                  { $$ = Expr_ArrayItem[$1, null, false]; }
    | expr T_DOUBLE_ARROW '&' variable                      { $$ = Expr_ArrayItem[$4, $1,   true]; }
    | '&' variable                                          { $$ = Expr_ArrayItem[$2, null, true]; }
;

encaps_list:
      encaps_list encaps_var                                { push($1, $2); }
    | encaps_list T_ENCAPSED_AND_WHITESPACE                 { push($1, $2); }
    | encaps_var                                            { init($1); }
    | T_ENCAPSED_AND_WHITESPACE encaps_var                  { init($1, $2); }
;

encaps_var:
      T_VARIABLE                                            { $$ = Expr_Variable[parseVar($1)]; }
    | T_VARIABLE '[' encaps_var_offset ']'                  { $$ = Expr_ArrayDimFetch[Expr_Variable[parseVar($1)], $3]; }
    | T_VARIABLE T_OBJECT_OPERATOR T_STRING                 { $$ = Expr_PropertyFetch[Expr_Variable[parseVar($1)], $3]; }
    | T_DOLLAR_OPEN_CURLY_BRACES expr '}'                   { $$ = Expr_Variable[$2]; }
    | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}'       { $$ = Expr_Variable[$2]; }
    | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}'
          { $$ = Expr_ArrayDimFetch[Expr_Variable[$2], $4]; }
    | T_CURLY_OPEN variable '}'                             { $$ = $2; }
;

encaps_var_offset:
      T_STRING                                              { $$ = Scalar_String[$1]; }
    | T_NUM_STRING                                          { $$ = Scalar_String[$1]; }
    | T_VARIABLE                                            { $$ = Expr_Variable[parseVar($1)]; }
;

%%
<?php

$grammarFile           = __DIR__ . '/zend_language_parser.phpy';
$skeletonFile          = __DIR__ . '/kmyacc.php.parser';
$tmpGrammarFile        = __DIR__ . '/tmp_parser.phpy';
$tmpResultFile         = __DIR__ . '/tmp_parser.php';
$parserResultFile      = __DIR__ . '/../lib/PHPParser/Parser.php';
$debugParserResultFile = __DIR__ . '/../lib/PHPParser/Parser/Debug.php';

// check for kmyacc.exe binary in this directory, otherwise fall back to global name
$kmyacc = __DIR__ . '/kmyacc.exe';
if (!file_exists($kmyacc)) {
    $kmyacc = 'kmyacc';
}

$options = array_flip($argv);
$optionDebug = isset($options['--debug']);
$optionKeepTmpGrammar = isset($options['--keep-tmp-grammar']);

///////////////////////////////
/// Utility regex constants ///
///////////////////////////////

const LIB = '(?(DEFINE)
    (?<singleQuotedString>\'[^\\\\\']*+(?:\\\\.[^\\\\\']*+)*+\')
    (?<doubleQuotedString>"[^\\\\"]*+(?:\\\\.[^\\\\"]*+)*+")
    (?<string>(?&singleQuotedString)|(?&doubleQuotedString))
    (?<comment>/\*[^*]*+(?:\*(?!/)[^*]*+)*+\*/)
    (?<code>\{[^\'"/{}]*+(?:(?:(?&string)|(?&comment)|(?&code)|/)[^\'"/{}]*+)*+})
)';

const PARAMS = '\[(?<params>[^[\]]*+(?:\[(?&params)\][^[\]]*+)*+)\]';
const ARGS   = '\((?<args>[^()]*+(?:\((?&args)\)[^()]*+)*+)\)';

///////////////////
/// Main script ///
///////////////////

echo 'Building temporary preproprocessed grammar file.', "\n";

$grammarCode = file_get_contents($grammarFile);

$grammarCode = resolveConstants($grammarCode);
$grammarCode = resolveNodes($grammarCode);
$grammarCode = resolveMacros($grammarCode);
$grammarCode = resolveArrays($grammarCode);

file_put_contents($tmpGrammarFile, $grammarCode);

echo "Building parser.\n";
$output = trim(shell_exec("$kmyacc -l -m $skeletonFile -p PHPParser_Parser $tmpGrammarFile 2>&1"));
echo "Output: \"$output\"\n";

moveFileWithDirCheck($tmpResultFile, $parserResultFile);

if ($optionDebug) {
    echo "Building debug parser.\n";
    $output = trim(shell_exec("$kmyacc -t -v -l -m $skeletonFile -p PHPParser_Parser $tmpGrammarFile 2>&1"));
    echo "Output: \"$output\"\n";

    moveFileWithDirCheck($tmpResultFile, $debugParserResultFile);
}

if (!$optionKeepTmpGrammar) {
    unlink($tmpGrammarFile);
}

///////////////////////////////
/// Preprocessing functions ///
///////////////////////////////

function resolveConstants($code) {
    return preg_replace('~[A-Z][a-zA-Z_]++::~', 'PHPParser_Node_$0', $code);
}

function resolveNodes($code) {
    return preg_replace_callback(
        '~(?<name>[A-Z][a-zA-Z_]++)\s*' . PARAMS . '~',
        function($matches) {
            // recurse
            $matches['params'] = resolveNodes($matches['params']);

            $params = magicSplit(
                '(?:' . PARAMS . '|' . ARGS . ')(*SKIP)(*FAIL)|,',
                $matches['params']
            );

            $paramCode = '';
            foreach ($params as $param) {
                $paramCode .= $param . ', ';
            }

            return 'new PHPParser_Node_' . $matches['name'] . '(' . $paramCode . '$attributes)';
        },
        $code
    );
}

function resolveMacros($code) {
    return preg_replace_callback(
        '~\b(?<!::|->)(?!array\()(?<name>[a-z][A-Za-z]++)' . ARGS . '~',
        function($matches) {
            // recurse
            $matches['args'] = resolveMacros($matches['args']);

            $name = $matches['name'];
            $args = magicSplit(
                '(?:' . PARAMS . '|' . ARGS . ')(*SKIP)(*FAIL)|,',
                $matches['args']
            );

            if ('error' == $name) {
                assertArgs(1, $args, $name);

                return 'throw new PHPParser_Error(' . $args[0] . ')';
            }

            if ('init' == $name) {
                return '$$ = array(' . implode(', ', $args) . ')';
            }

            if ('push' == $name) {
                assertArgs(2, $args, $name);

                return $args[0] . '[] = ' . $args[1] . '; $$ = ' . $args[0];
            }

            if ('pushNormalizing' == $name) {
                assertArgs(2, $args, $name);

                return 'if (is_array(' . $args[1] . ')) { $$ = array_merge(' . $args[0] . ', ' . $args[1] . '); } else { ' . $args[0] . '[] = ' . $args[1] . '; $$ = ' . $args[0] . '; }';
            }

            if ('toArray' == $name) {
                assertArgs(1, $args, $name);

                return 'is_array(' . $args[0] . ') ? ' . $args[0] . ' : array(' . $args[0] . ')';
            }

            if ('parseVar' == $name) {
                assertArgs(1, $args, $name);

                return 'substr(' . $args[0] . ', 1)';
            }

            if ('parseEncapsed' == $name) {
                assertArgs(2, $args, $name);

                return 'foreach (' . $args[0] . ' as &$s) { if (is_string($s)) { $s = PHPParser_Node_Scalar_String::parseEscapeSequences($s, ' . $args[1] . '); } }';
            }

            if ('parseEncapsedDoc' == $name) {
                assertArgs(1, $args, $name);

                return 'foreach (' . $args[0] . ' as &$s) { if (is_string($s)) { $s = PHPParser_Node_Scalar_String::parseEscapeSequences($s, null); } } $s = preg_replace(\'~(\r\n|\n|\r)$~\', \'\', $s); if (\'\' === $s) array_pop(' . $args[0] . ');';
            }

            throw new Exception(sprintf('Unknown macro "%s"', $name));
        },
        $code
    );
}

function assertArgs($num, $args, $name) {
    if ($num != count($args)) {
        die('Wrong argument count for ' . $name . '().');
    }
}

function resolveArrays($code) {
    return preg_replace_callback(
        '~' . PARAMS . '~',
        function ($matches) {
            $elements = magicSplit(
                '(?:' . PARAMS . '|' . ARGS . ')(*SKIP)(*FAIL)|,',
                $matches['params']
            );

            // don't convert [] to array, it might have different meaning
            if (empty($elements)) {
                return $matches[0];
            }

            $elementCodes = array();
            foreach ($elements as $element) {
                // convert only arrays where all elements have keys
                if (false === strpos($element, ':')) {
                    return $matches[0];
                }

                list($key, $value) = explode(':', $element, 2);
                $elementCodes[] = "'" . $key . "' =>" . $value;
            }

            return 'array(' . implode(', ', $elementCodes) . ')';
        },
        $code
    );
}

function moveFileWithDirCheck($fromPath, $toPath) {
    $dir = dirname($toPath);
    if (!is_dir($dir)) {
        mkdir($dir, 0777, true);
    }
    rename($fromPath, $toPath);
}

//////////////////////////////
/// Regex helper functions ///
//////////////////////////////

function regex($regex) {
    return '~' . LIB . '(?:' . str_replace('~', '\~', $regex) . ')~';
}

function magicSplit($regex, $string) {
    $pieces = preg_split(regex('(?:(?&string)|(?&comment)|(?&code))(*SKIP)(*FAIL)|' . $regex), $string);

    foreach ($pieces as &$piece) {
        $piece = trim($piece);
    }

    return array_filter($pieces);
}<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="false"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="./lib/bootstrap.php">
    <testsuites>
        <testsuite name="PHPParser Test Suite">
            <directory>./test/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory suffix=".php">./lib/PHPParser/</directory>
        </whitelist>
    </filter>
</phpunit><?php

interface PHPParser_NodeVisitor
{
    /**
     * Called once before traversal.
     *
     * Return value semantics:
     *  * null:      $nodes stays as-is
     *  * otherwise: $nodes is set to the return value
     *
     * @param PHPParser_Node[] $nodes Array of nodes
     *
     * @return null|PHPParser_Node[] Array of nodes
     */
    public function beforeTraverse(array $nodes);

    /**
     * Called when entering a node.
     *
     * Return value semantics:
     *  * null:      $node stays as-is
     *  * otherwise: $node is set to the return value
     *
     * @param PHPParser_Node $node Node
     *
     * @return null|PHPParser_Node Node
     */
    public function enterNode(PHPParser_Node $node);

    /**
     * Called when leaving a node.
     *
     * Return value semantics:
     *  * null:      $node stays as-is
     *  * false:     $node is removed from the parent array
     *  * array:     The return value is merged into the parent array (at the position of the $node)
     *  * otherwise: $node is set to the return value
     *
     * @param PHPParser_Node $node Node
     *
     * @return null|PHPParser_Node|false|PHPParser_Node[] Node
     */
    public function leaveNode(PHPParser_Node $node);

    /**
     * Called once after traversal.
     *
     * Return value semantics:
     *  * null:      $nodes stays as-is
     *  * otherwise: $nodes is set to the return value
     *
     * @param PHPParser_Node[] $nodes Array of nodes
     *
     * @return null|PHPParser_Node[] Array of nodes
     */
    public function afterTraverse(array $nodes);
}<?php

/* This is an automatically GENERATED file, which should not be manually edited.
 * Instead edit one of the following:
 *  * the grammar file grammar/zend_language_parser.phpy
 *  * the parser skeleton grammar/kymacc.php.parser
 *  * the preprocessing script grammar/rebuildParser.php
 *
 * The skeleton for this parser was written by Moriyoshi Koizumi and is based on
 * the work by Masato Bito and is in the PUBLIC DOMAIN.
 */
class PHPParser_Parser
{
    const TOKEN_NONE    = -1;
    const TOKEN_INVALID = 151;

    const TOKEN_MAP_SIZE = 386;

    const YYLAST       = 1008;
    const YY2TBLSTATE  = 316;
    const YYGLAST      = 444;
    const YYNLSTATES   = 531;
    const YYUNEXPECTED = 32767;
    const YYDEFAULT    = -32766;

    // {{{ Tokens
    const YYERRTOK = 256;
    const T_INCLUDE = 257;
    const T_INCLUDE_ONCE = 258;
    const T_EVAL = 259;
    const T_REQUIRE = 260;
    const T_REQUIRE_ONCE = 261;
    const T_LOGICAL_OR = 262;
    const T_LOGICAL_XOR = 263;
    const T_LOGICAL_AND = 264;
    const T_PRINT = 265;
    const T_YIELD = 266;
    const T_PLUS_EQUAL = 267;
    const T_MINUS_EQUAL = 268;
    const T_MUL_EQUAL = 269;
    const T_DIV_EQUAL = 270;
    const T_CONCAT_EQUAL = 271;
    const T_MOD_EQUAL = 272;
    const T_AND_EQUAL = 273;
    const T_OR_EQUAL = 274;
    const T_XOR_EQUAL = 275;
    const T_SL_EQUAL = 276;
    const T_SR_EQUAL = 277;
    const T_BOOLEAN_OR = 278;
    const T_BOOLEAN_AND = 279;
    const T_IS_EQUAL = 280;
    const T_IS_NOT_EQUAL = 281;
    const T_IS_IDENTICAL = 282;
    const T_IS_NOT_IDENTICAL = 283;
    const T_IS_SMALLER_OR_EQUAL = 284;
    const T_IS_GREATER_OR_EQUAL = 285;
    const T_SL = 286;
    const T_SR = 287;
    const T_INSTANCEOF = 288;
    const T_INC = 289;
    const T_DEC = 290;
    const T_INT_CAST = 291;
    const T_DOUBLE_CAST = 292;
    const T_STRING_CAST = 293;
    const T_ARRAY_CAST = 294;
    const T_OBJECT_CAST = 295;
    const T_BOOL_CAST = 296;
    const T_UNSET_CAST = 297;
    const T_NEW = 298;
    const T_CLONE = 299;
    const T_EXIT = 300;
    const T_IF = 301;
    const T_ELSEIF = 302;
    const T_ELSE = 303;
    const T_ENDIF = 304;
    const T_LNUMBER = 305;
    const T_DNUMBER = 306;
    const T_STRING = 307;
    const T_STRING_VARNAME = 308;
    const T_VARIABLE = 309;
    const T_NUM_STRING = 310;
    const T_INLINE_HTML = 311;
    const T_CHARACTER = 312;
    const T_BAD_CHARACTER = 313;
    const T_ENCAPSED_AND_WHITESPACE = 314;
    const T_CONSTANT_ENCAPSED_STRING = 315;
    const T_ECHO = 316;
    const T_DO = 317;
    const T_WHILE = 318;
    const T_ENDWHILE = 319;
    const T_FOR = 320;
    const T_ENDFOR = 321;
    const T_FOREACH = 322;
    const T_ENDFOREACH = 323;
    const T_DECLARE = 324;
    const T_ENDDECLARE = 325;
    const T_AS = 326;
    const T_SWITCH = 327;
    const T_ENDSWITCH = 328;
    const T_CASE = 329;
    const T_DEFAULT = 330;
    const T_BREAK = 331;
    const T_CONTINUE = 332;
    const T_GOTO = 333;
    const T_FUNCTION = 334;
    const T_CONST = 335;
    const T_RETURN = 336;
    const T_TRY = 337;
    const T_CATCH = 338;
    const T_FINALLY = 339;
    const T_THROW = 340;
    const T_USE = 341;
    const T_INSTEADOF = 342;
    const T_GLOBAL = 343;
    const T_STATIC = 344;
    const T_ABSTRACT = 345;
    const T_FINAL = 346;
    const T_PRIVATE = 347;
    const T_PROTECTED = 348;
    const T_PUBLIC = 349;
    const T_VAR = 350;
    const T_UNSET = 351;
    const T_ISSET = 352;
    const T_EMPTY = 353;
    const T_HALT_COMPILER = 354;
    const T_CLASS = 355;
    const T_TRAIT = 356;
    const T_INTERFACE = 357;
    const T_EXTENDS = 358;
    const T_IMPLEMENTS = 359;
    const T_OBJECT_OPERATOR = 360;
    const T_DOUBLE_ARROW = 361;
    const T_LIST = 362;
    const T_ARRAY = 363;
    const T_CALLABLE = 364;
    const T_CLASS_C = 365;
    const T_TRAIT_C = 366;
    const T_METHOD_C = 367;
    const T_FUNC_C = 368;
    const T_LINE = 369;
    const T_FILE = 370;
    const T_COMMENT = 371;
    const T_DOC_COMMENT = 372;
    const T_OPEN_TAG = 373;
    const T_OPEN_TAG_WITH_ECHO = 374;
    const T_CLOSE_TAG = 375;
    const T_WHITESPACE = 376;
    const T_START_HEREDOC = 377;
    const T_END_HEREDOC = 378;
    const T_DOLLAR_OPEN_CURLY_BRACES = 379;
    const T_CURLY_OPEN = 380;
    const T_PAAMAYIM_NEKUDOTAYIM = 381;
    const T_NAMESPACE = 382;
    const T_NS_C = 383;
    const T_DIR = 384;
    const T_NS_SEPARATOR = 385;
    // }}}

    /* @var array Map of token ids to their respective names */
    protected static $terminals = array(
        "EOF",
        "error",
        "T_INCLUDE",
        "T_INCLUDE_ONCE",
        "T_EVAL",
        "T_REQUIRE",
        "T_REQUIRE_ONCE",
        "','",
        "T_LOGICAL_OR",
        "T_LOGICAL_XOR",
        "T_LOGICAL_AND",
        "T_PRINT",
        "T_YIELD",
        "'='",
        "T_PLUS_EQUAL",
        "T_MINUS_EQUAL",
        "T_MUL_EQUAL",
        "T_DIV_EQUAL",
        "T_CONCAT_EQUAL",
        "T_MOD_EQUAL",
        "T_AND_EQUAL",
        "T_OR_EQUAL",
        "T_XOR_EQUAL",
        "T_SL_EQUAL",
        "T_SR_EQUAL",
        "'?'",
        "':'",
        "T_BOOLEAN_OR",
        "T_BOOLEAN_AND",
        "'|'",
        "'^'",
        "'&'",
        "T_IS_EQUAL",
        "T_IS_NOT_EQUAL",
        "T_IS_IDENTICAL",
        "T_IS_NOT_IDENTICAL",
        "'<'",
        "T_IS_SMALLER_OR_EQUAL",
        "'>'",
        "T_IS_GREATER_OR_EQUAL",
        "T_SL",
        "T_SR",
        "'+'",
        "'-'",
        "'.'",
        "'*'",
        "'/'",
        "'%'",
        "'!'",
        "T_INSTANCEOF",
        "'~'",
        "T_INC",
        "T_DEC",
        "T_INT_CAST",
        "T_DOUBLE_CAST",
        "T_STRING_CAST",
        "T_ARRAY_CAST",
        "T_OBJECT_CAST",
        "T_BOOL_CAST",
        "T_UNSET_CAST",
        "'@'",
        "'['",
        "T_NEW",
        "T_CLONE",
        "T_EXIT",
        "T_IF",
        "T_ELSEIF",
        "T_ELSE",
        "T_ENDIF",
        "T_LNUMBER",
        "T_DNUMBER",
        "T_STRING",
        "T_STRING_VARNAME",
        "T_VARIABLE",
        "T_NUM_STRING",
        "T_INLINE_HTML",
        "T_ENCAPSED_AND_WHITESPACE",
        "T_CONSTANT_ENCAPSED_STRING",
        "T_ECHO",
        "T_DO",
        "T_WHILE",
        "T_ENDWHILE",
        "T_FOR",
        "T_ENDFOR",
        "T_FOREACH",
        "T_ENDFOREACH",
        "T_DECLARE",
        "T_ENDDECLARE",
        "T_AS",
        "T_SWITCH",
        "T_ENDSWITCH",
        "T_CASE",
        "T_DEFAULT",
        "T_BREAK",
        "T_CONTINUE",
        "T_GOTO",
        "T_FUNCTION",
        "T_CONST",
        "T_RETURN",
        "T_TRY",
        "T_CATCH",
        "T_FINALLY",
        "T_THROW",
        "T_USE",
        "T_INSTEADOF",
        "T_GLOBAL",
        "T_STATIC",
        "T_ABSTRACT",
        "T_FINAL",
        "T_PRIVATE",
        "T_PROTECTED",
        "T_PUBLIC",
        "T_VAR",
        "T_UNSET",
        "T_ISSET",
        "T_EMPTY",
        "T_HALT_COMPILER",
        "T_CLASS",
        "T_TRAIT",
        "T_INTERFACE",
        "T_EXTENDS",
        "T_IMPLEMENTS",
        "T_OBJECT_OPERATOR",
        "T_DOUBLE_ARROW",
        "T_LIST",
        "T_ARRAY",
        "T_CALLABLE",
        "T_CLASS_C",
        "T_TRAIT_C",
        "T_METHOD_C",
        "T_FUNC_C",
        "T_LINE",
        "T_FILE",
        "T_START_HEREDOC",
        "T_END_HEREDOC",
        "T_DOLLAR_OPEN_CURLY_BRACES",
        "T_CURLY_OPEN",
        "T_PAAMAYIM_NEKUDOTAYIM",
        "T_NAMESPACE",
        "T_NS_C",
        "T_DIR",
        "T_NS_SEPARATOR",
        "';'",
        "'{'",
        "'}'",
        "'('",
        "')'",
        "'$'",
        "'`'",
        "']'",
        "'\"'"
        , "???"
    );

    /* @var array Map which translates lexer tokens to internal tokens */
    protected static $translate = array(
            0,  151,  151,  151,  151,  151,  151,  151,  151,  151,
          151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
          151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
          151,  151,  151,   48,  150,  151,  147,   47,   31,  151,
          145,  146,   45,   42,    7,   43,   44,   46,  151,  151,
          151,  151,  151,  151,  151,  151,  151,  151,   26,  142,
           36,   13,   38,   25,   60,  151,  151,  151,  151,  151,
          151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
          151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
          151,   61,  151,  149,   30,  151,  148,  151,  151,  151,
          151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
          151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
          151,  151,  151,  143,   29,  144,   50,  151,  151,  151,
          151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
          151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
          151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
          151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
          151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
          151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
          151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
          151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
          151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
          151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
          151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
          151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
          151,  151,  151,  151,  151,  151,    1,    2,    3,    4,
            5,    6,    8,    9,   10,   11,   12,   14,   15,   16,
           17,   18,   19,   20,   21,   22,   23,   24,   27,   28,
           32,   33,   34,   35,   37,   39,   40,   41,   49,   51,
           52,   53,   54,   55,   56,   57,   58,   59,   62,   63,
           64,   65,   66,   67,   68,   69,   70,   71,   72,   73,
           74,   75,  151,  151,   76,   77,   78,   79,   80,   81,
           82,   83,   84,   85,   86,   87,   88,   89,   90,   91,
           92,   93,   94,   95,   96,   97,   98,   99,  100,  101,
          102,  103,  104,  105,  106,  107,  108,  109,  110,  111,
          112,  113,  114,  115,  116,  117,  118,  119,  120,  121,
          122,  123,  124,  125,  126,  127,  128,  129,  130,  131,
          132,  151,  151,  151,  151,  151,  151,  133,  134,  135,
          136,  137,  138,  139,  140,  141
    );

    protected static $yyaction = array(
           59,   60,  325,   61,   62,-32766,-32766,-32766,  324,   63,
           64,-32767,-32767,-32767,-32767,   98,   99,  100,  101,  102,
           57,  917,-32766,  298,-32766,-32766,   41,  106,  107,  108,
          109,  110,  111,  112,  113,  114,  115,  116,  267,  346,
           65,   66,  927,  249,  929,  928,   67,  535,   68,  220,
          221,   69,   70,   71,   72,   73,   74,   75,   76,   31,
          232,   77,  318,  326,  730,  732,  462,  836,  837,  362,
          348,  895,  238,  578,  280,  363,   46,   27,  327,  859,
          364,  246,  365,  454,  366,   39,  223,  328,-32766,-32766,
        -32766,   36,   37,  367,  333,  360,   38,  368,  329,  423,
           78,  848,  122,  278,  279,-32766,  286,-32766,   35,  369,
          370,  371,  372,  373,  389,  343,  861,  330,  560,  602,
          374,  375,  376,  377,  848,  842,  843,  844,  845,  839,
          840,  239,   82,   83,   84, -350,  389,  846,  841,  330,
          584,  504,  126,   47,  227,  259,  244,  802,  248,   40,
          351,   85,   86,   87,   88,   89,   90,   91,   92,   93,
           94,   95,   96,   97,   98,   99,  100,  101,  102,  103,
          104,  105,  788,  233,  576,-32766,-32766,-32766,  701,  702,
          703,  700,  699,  698,  630,    0,-32766,-32766,-32766,  655,
          656,  216,-32766,  215,-32766,-32766,-32766,-32766,-32766,-32767,
        -32767,-32767,-32767,-32766,  788,  322,  329,  319,  899,  544,
         -117,  257,  128,  277,-32766,-32766,-32766,  369,  370,  889,
          693,  261,  895,  225,  226,-32766,  540,  602,  374,  375,
          675,  535,  344,-32766,  535,-32766,  895,  376,-32766,-32766,
        -32766,  575,-32766,   53,-32766,  322,-32766,  658,  263,-32766,
          187,  257,  600,-32766,-32766,-32766,  788,-32766,-32766,-32766,
          693,   34,-32766,  535,  350,-32766,  388,-32766,  860,  812,
        -32766,-32766,-32766,-32766,-32766,  222,-32766,   54,-32766,   56,
          127,-32766,  100,  101,  102,-32766,-32766,-32766,  788,   22,
        -32766,-32766,  601,  268,-32766,  924,  259,-32766,  388,  666,
          631,  389,-32766,-32766,  330,-32766,  322,  224,  334,-32766,
          259,  917,  257,  503,  861,  535,  103,  104,  105,-32766,
          233,  693,-32766,-32766,-32766,  118,-32766,  494,-32766,  340,
        -32766,  506,  902,-32766,-32766,-32766,  126,-32766,-32766,-32766,
          345,-32766,-32766,-32766,  213,  123,-32766,  535,  130,-32766,
          388,-32766,  452,  599,-32766,-32766,-32766,-32766,-32766,  119,
        -32766,  120,-32766,  788,  233,-32766,  189, -113,  190,-32766,
        -32766,-32766,  194,  217,-32766,-32766,  195,  125,-32766,-32766,
        -32766,-32766,  388,  188,  685,  858,-32766,-32766,  117,-32766,
          329,  319,  353,   28,  509,  788,  597,  277,  357,  468,
          680,  369,  370,  516,-32766,-32766,-32766,  131,  287,   49,
          540,  602,  374,  375,  477,  478,-32766,  520,-32766,-32766,
          528,-32766,  535,-32766,-32766,-32766,-32766,  655,  656,-32766,
        -32766,-32766,  263,-32766,  519,-32766,  507,-32766,  542,  129,
        -32766,  679,  525,  588,-32766,-32766,-32766,  526,-32766,-32766,
        -32766,  690,  530,-32766,  535,  306,-32766,  388,-32766,  541,
          511,-32766,-32766,-32766,-32766,-32766,  224,-32766,   50,-32766,
           58,  482,-32766,   55,  805,   51,-32766,-32766,-32766,  788,
           52,-32766,-32766,  416,  232,-32766,  502,  687,-32766,  388,
          445,  491,  229,-32766,-32766,  551,-32766,  922,  549,  415,
        -32766,  339,  341,  535,  536,  399,  535,  400,  402,  414,
        -32766, -158,  401,-32766,-32766,-32766,  493,-32766,  479,-32766,
          475,-32766, -161,  604,-32766,-32766,-32766,  265,-32766,-32766,
        -32766,  788,-32766,-32766,-32766,  266,  917,-32766,  535,  256,
        -32766,  388,-32766,  342,  212,-32766,-32766,-32766,-32766,-32766,
          338,-32766,  471,-32766,  457,  473,-32766,  359,  603,  258,
        -32766,-32766,-32766,  788,  255,-32766,-32766,  577,  260,-32766,
          376,  579,-32766,  388,  847,  247,    0,-32766,-32766, -350,
        -32766,  657,    0,  337,-32766,    0,    0, -351,  245,    0,
          535,  121,  193,   42,-32766, -282,  791,-32766,-32766,-32766,
            0,-32766,    0,-32766,    0,-32766,    0,    0,-32766,  570,
        -32766, -290,-32766,-32766,-32766,  788,-32766,-32766,-32766, -291,
          499,-32766,  535,  300,-32766,  388,-32766,  288,  251,-32766,
        -32766,-32766,-32766,-32766,  242,-32766,  407,-32766,  684,  340,
        -32766,  686,  614,  616,-32766,-32766,-32766,  618,  563,-32766,
        -32766,  625,  624,-32766,  633,  580,-32766,  388,  565,  587,
          574,  572,-32766,  513,-32766,  512,   45,   44,-32766,  569,
          571,  573,  586,  545,  535,  683,  676,  234,-32766,  510,
          515,-32766,-32766,-32766,  517,-32766,  522,-32766,   81,-32766,
          124,  523,-32766,-32766,-32766,  524,-32766,-32766,-32766,  527,
        -32766,-32766,-32766,  505,  529,-32766,  535,  890,-32766,  388,
        -32766,  900,  668,-32766,-32766,-32766,-32766,-32766,  827,-32766,
          892,-32766,  880,  894,-32766,  191,  192,  896,-32766,-32766,
        -32766,  923,  356,-32766,-32766,  623,  926,-32766,  622,  925,
        -32766,  388,   32,   33,  185,  568,-32766,  321,-32766,  317,
           43,  262,  836,  837,  237,-32766,-32766,  236,   48,-32766,
          838,  535,  235,   30,  219,-32766,  218,  214,-32766,-32766,
        -32766,  186,-32766,   80,-32766,   79,-32766,-32766,-32766,-32766,
          768,  829,  767,-32766,-32766,-32766,  446, -114,-32766,-32766,
          854,  659,-32766,  795,  792,-32766,  388,  498,  472,  437,
          358,  354,  307,-32766,  289,   25,   24,   23,  442, -113,
          842,  843,  844,  845,  839,  840,  309,  786,    0,  480,
          874,  855,  846,  841,  329,  319,  921,  826,-32766,  329,
        -32766,  277,-32766,-32766,  891,  369,  370,-32766,-32766,-32766,
          369,  370,  875,  879,  540,  602,  374,  375,  893,  560,
          602,  374,  375,  329,-32766,  811,-32766,-32766,-32766,-32766,
        -32766,  799,  797,  798,  369,  370,  263,  329,  796,    0,
            0,  329,  543,  560,  602,  374,  375,  598,  369,  370,
            0,    0,  369,  370,  329,    0,    0,  560,  602,  374,
          375,  560,  602,  374,  375,  369,  370,    0,    0,    0,
          329,  691,    0,    0,  560,  602,  374,  375,    0,    0,
            0,  369,  370,  329,    0,  790,    0,  329,  501,  591,
          560,  602,  374,  375,  369,  370,    0,    0,  369,  370,
            0,  329,  593,  560,  602,  374,  375,  560,  602,  374,
          375,    0,  369,  370,  492,    0,    0,    0,  514,    0,
          486,  560,  602,  374,  375,  329,    0,    0,    0,  329,
            0,  561,    0,    0,    0,  789,  369,  370,    0,    0,
          369,  370,-32766,-32766,-32766,  560,  602,  374,  375,  560,
          602,  374,  375,    0,  329,    0,    0,    0,    0,-32766,
            0,-32766,-32766,-32766,-32766,  369,  370,    0,    0,    0,
            0,    0,    0,    0,  560,  602,  374,  375
    );

    protected static $yycheck = array(
            2,    3,    4,    5,    6,    8,    9,   10,    7,   11,
           12,   36,   37,   38,   39,   40,   41,   42,   43,   44,
           61,   76,   25,   73,   27,   28,   13,   14,   15,   16,
           17,   18,   19,   20,   21,   22,   23,   24,   61,    7,
           42,   43,   71,   76,   73,   74,   48,   71,   50,   51,
           52,   53,   54,   55,   56,   57,   58,   59,   60,   61,
           62,   63,   64,   65,   51,   52,   76,   69,   70,   71,
           71,   73,    7,   75,    7,   77,   78,   79,   80,  134,
           82,  122,   84,   81,   86,  135,  136,   89,    8,    9,
           10,   93,   94,   95,   96,    7,   98,   99,   96,  122,
          102,  134,  143,  105,  106,   25,    7,   27,    7,  107,
          108,  113,  114,  115,  138,   26,  117,  141,  116,  117,
          118,  119,  124,  125,  134,  127,  128,  129,  130,  131,
          132,  133,    8,    9,   10,  122,  138,  139,  140,  141,
          142,  143,  143,  145,   31,  147,  148,  146,  150,   25,
            7,   27,   28,   29,   30,   31,   32,   33,   34,   35,
           36,   37,   38,   39,   40,   41,   42,   43,   44,   45,
           46,   47,   12,   49,  142,    8,    9,   10,  106,  107,
          108,  109,  110,  111,   26,    0,    8,    9,   10,  125,
          126,   31,   25,    7,   27,   28,   29,   30,   31,   32,
           33,   34,   35,   25,   12,   97,   96,   97,   71,  142,
          146,  103,   61,  103,    8,    9,   10,  107,  108,   73,
          112,    7,   73,   31,    7,   65,  116,  117,  118,  119,
          142,   71,  143,    8,   71,   75,   73,  124,   78,   79,
           80,  142,   82,   61,   84,   97,   86,  146,  138,   89,
            7,  103,  144,   93,   94,   95,   12,   65,   98,   99,
          112,    7,  102,   71,   71,  105,  106,   75,   71,  106,
           78,   79,   80,  113,   82,   31,   84,   61,   86,   61,
          143,   89,   42,   43,   44,   93,   94,   95,   12,  146,
           98,   99,  144,  147,  102,  144,  147,  105,  106,   73,
          142,  138,  142,  143,  141,  113,   97,   31,  145,   65,
          147,   76,  103,   71,  117,   71,   45,   46,   47,   75,
           49,  112,   78,   79,   80,  143,   82,   71,   84,  141,
           86,  143,  146,   89,  142,  143,  143,   93,   94,   95,
            7,   65,   98,   99,  123,    7,  102,   71,  143,  105,
          106,   75,  147,  144,   78,   79,   80,  113,   82,  143,
           84,  143,   86,   12,   49,   89,   13,  146,   13,   93,
           94,   95,   13,  147,   98,   99,   13,   26,  102,    8,
            9,  105,  106,   13,  142,  150,  142,  143,   13,  113,
           96,   97,   66,   67,   26,   12,   31,  103,   66,   67,
          144,  107,  108,   26,    8,    9,   10,   91,   92,   61,
          116,  117,  118,  119,  100,  101,   65,   26,  142,  143,
           26,   25,   71,   27,   28,   29,   75,  125,  126,   78,
           79,   80,  138,   82,   26,   84,   26,   86,  144,   26,
           89,  142,  143,   26,   93,   94,   95,   26,   65,   98,
           99,  142,  143,  102,   71,   72,  105,  106,   75,  142,
          143,   78,   79,   80,  113,   82,   31,   84,   61,   86,
           61,   68,   89,   61,   73,   61,   93,   94,   95,   12,
           61,   98,   99,   88,   62,  102,   71,   71,  105,  106,
           88,   71,   88,  142,  143,   71,  113,   71,   71,   71,
           65,   71,   71,   71,   71,   71,   71,   71,   71,   71,
           75,   88,   73,   78,   79,   80,   73,   82,   73,   84,
           73,   86,   73,  117,   89,  142,  143,   76,   93,   94,
           95,   12,   65,   98,   99,   76,   76,  102,   71,  121,
          105,  106,   75,   80,   88,   78,   79,   80,  113,   82,
           96,   84,   90,   86,   90,  103,   89,   96,  117,  104,
           93,   94,   95,   12,  120,   98,   99,  142,  120,  102,
          124,  142,  105,  106,  134,  122,   -1,  142,  143,  122,
          113,  146,   -1,  141,   65,   -1,   -1,  122,  122,   -1,
           71,  123,  123,  123,   75,  137,  146,   78,   79,   80,
           -1,   82,   -1,   84,   -1,   86,   -1,   -1,   89,  142,
          143,  137,   93,   94,   95,   12,   65,   98,   99,  137,
          137,  102,   71,  137,  105,  106,   75,  137,  137,   78,
           79,   80,  113,   82,  137,   84,  141,   86,  142,  141,
           89,  142,  142,  142,   93,   94,   95,  142,  142,   98,
           99,  142,  142,  102,  142,  142,  105,  106,  142,  142,
          142,  142,  143,  142,  113,  142,  142,  142,   65,  142,
          142,  142,  142,  142,   71,  142,  142,  145,   75,  143,
          143,   78,   79,   80,  143,   82,  143,   84,  143,   86,
          143,  143,   89,  142,  143,  143,   93,   94,   95,  143,
           65,   98,   99,  143,  143,  102,   71,  144,  105,  106,
           75,  144,  144,   78,   79,   80,  113,   82,  144,   84,
          144,   86,  144,  144,   89,   42,   43,  144,   93,   94,
           95,  144,  144,   98,   99,  144,  144,  102,  144,  144,
          105,  106,  145,  145,   61,  142,  143,  145,  113,  145,
          145,  145,   69,   70,  145,   65,   73,  145,  145,  145,
           77,   71,  145,  145,  145,   75,  145,  145,   78,   79,
           80,  145,   82,  145,   84,  145,   86,  142,  143,   89,
          146,  146,  146,   93,   94,   95,  146,  146,   98,   99,
          146,  146,  102,  146,  146,  105,  106,  146,  146,  146,
          146,  146,  146,  113,  146,  146,  146,  146,  125,  146,
          127,  128,  129,  130,  131,  132,  133,  148,   -1,  149,
          149,  149,  139,  140,   96,   97,  149,  149,  145,   96,
          147,  103,  142,  143,  149,  107,  108,    8,    9,   10,
          107,  108,  149,  149,  116,  117,  118,  119,  149,  116,
          117,  118,  119,   96,   25,  149,   27,   28,   29,   30,
           31,  149,  149,  149,  107,  108,  138,   96,  149,   -1,
           -1,   96,  144,  116,  117,  118,  119,  144,  107,  108,
           -1,   -1,  107,  108,   96,   -1,   -1,  116,  117,  118,
          119,  116,  117,  118,  119,  107,  108,   -1,   -1,   -1,
           96,  144,   -1,   -1,  116,  117,  118,  119,   -1,   -1,
           -1,  107,  108,   96,   -1,  144,   -1,   96,   83,  144,
          116,  117,  118,  119,  107,  108,   -1,   -1,  107,  108,
           -1,   96,  144,  116,  117,  118,  119,  116,  117,  118,
          119,   -1,  107,  108,   85,   -1,   -1,   -1,  144,   -1,
           87,  116,  117,  118,  119,   96,   -1,   -1,   -1,   96,
           -1,  144,   -1,   -1,   -1,  144,  107,  108,   -1,   -1,
          107,  108,    8,    9,   10,  116,  117,  118,  119,  116,
          117,  118,  119,   -1,   96,   -1,   -1,   -1,   -1,   25,
           -1,   27,   28,   29,   30,  107,  108,   -1,   -1,   -1,
           -1,   -1,   -1,   -1,  116,  117,  118,  119
    );

    protected static $yybase = array(
            0,  728,  294,  110,  817,  804,    2,  863,  859,  733,
          821,  788,  771,  835,  775,  757,  888,  888,  888,  888,
          888,  368,  377,  391,  394,  391,  410,   -2,   -2,   -2,
          435,  244,  244,  635,  244,  276,  603,  467,  519,  383,
          351,  160,  192,  551,  551,  551,  551,  690,  690,  551,
          551,  551,  551,  551,  551,  551,  551,  551,  551,  551,
          551,  551,  551,  551,  551,  551,  551,  551,  551,  551,
          551,  551,  551,  551,  551,  551,  551,  551,  551,  551,
          551,  551,  551,  551,  551,  551,  551,  551,  551,  551,
          551,  551,  551,  551,  551,  551,  551,  551,  551,  551,
          551,  551,  551,  551,  551,  551,  551,  551,  551,  551,
          551,  551,  551,  551,  551,  551,  551,  551,  551,  551,
          551,  551,  551,  551,  551,  551,  551,  551,  551,  551,
          551,  551,  158,  429,  468,  470,  527,  528,  529,  530,
          450,  456,  634,  587,  583,  413,  579,  578,  576,  574,
          568,  588,  567,  670,  563,  124,  124,  124,  124,  124,
          124,  124,  124,  124,  124,  225,  371,  206,  206,  206,
          206,  206,  206,  206,  206,  206,  206,  206,  206,  206,
          206,  206,  178,  178,   80,  683,  683,  683,  683,  683,
          683,  683,  683,  683,  683,  683,   -3,  396,  964,  829,
          167,  167,  167,  167,   13,  -25,  -25,  -25,  -25,  148,
          108,  209,  113,  113,  446,  446,  422,  547,  163,  163,
          163,  163,  163,  163,  163,  163,  163,  163,  449,  415,
          240,  240,  614,  614,   64,   64,   64,   64,  302,  -33,
          -55,  235,   -1,  256,  451,  137,  137,  137,  459,  440,
          460,  193,  271,  271,  271,  -24,  -24,  -24,  -24,  545,
          -24,  -24,  -24,  188,  216,  -50,  -50,  -29,  205,  464,
          594,  462,  591,  299,  482,  -41,  317,  442,  226,  454,
          442,  326,  332,  314,  458,   89,  226,  158,  197,  309,
          218,  425,  428,  531,  395,   67,   99,   32,  -23,  182,
          146,  143,  402,  640,  636,  186,  151,  465,  101,  -10,
          182,  221,  534,   88,    1,  533,  242,  365,  598,  436,
          618,  438,  436,  445,  365,  613,  613,  613,  613,  365,
          432,  618,  618,  365,  422,  618,  254,  432,  365,  444,
          432,  448,  613,  523,  521,  436,  439,  418,  618,  618,
          618,  438,  365,  613,  452,  243,  618,  613,  452,  365,
          445,  185,  417,  348,  605,  630,  602,  434,  560,  441,
          406,  621,  619,  628,  437,  430,  622,  597,  495,  518,
          431,  375,  407,  414,  419,  497,  412,  466,  454,  498,
          315,  457,  491,  457,  719,  486,  474,  453,  463,  517,
          370,  353,  536,  495,  648,  656,  669,  433,  532,  653,
          457,  714,  525,  338,  355,  617,  427,  457,  612,  457,
          537,  457,  647,  426,  592,  495,  315,  315,  315,  645,
          713,  712,  706,  699,  694,  693,  685,  409,  678,  516,
          655,   65,  626,  458,  490,  424,  513,  214,  677,  457,
          457,  541,  545,  457,  512,  524,  661,  510,  652,  447,
          469,  672,  440,  654,  457,  461,  671,  214,  408,  403,
          641,  509,  543,  604,  548,  359,  644,  606,  552,  363,
          595,  421,  506,  660,  659,  663,  505,  556,  420,  401,
          443,  609,  501,  651,  423,  483,  455,  404,  561,  416,
          658,  500,  499,  496,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,
           -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,
           -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,    0,    0,
            0,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,
           -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,
           -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,
           -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,
           -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,
           -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,
           -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,
           -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,
           -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,
           -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,   -2,
           -2,   -2,   -2,  124,  124,  124,  124,  124,  124,  124,
          124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
          124,  124,  124,  124,  124,  124,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,  124,  124,  124,  124,
          124,  124,  124,  124,  124,  124,  124,  124,  124,  124,
          124,  124,  124,  124,  124,  124,  163,  163,  163,  163,
          163,  163,  163,  163,  163,  163,  163,  124,  124,  124,
          124,  124,  124,  124,  124,    0,  271,  271,  271,  271,
           72,   72,   72,  163,  163,  163,  163,  163,  163,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,   72,
           72,  271,  271,  163,  163,  -24,  -24,  -24,  -24,  -24,
          -50,  -50,  -50,  146,  -24,  -50,  149,  149,  149,  -50,
          -50,  -50,  146,    0,    0,    0,    0,    0,    0,    0,
          149,    0,    0,    0,  432,  618,    0,    0,    0,  149,
          316,  316,  316,  316,  214,  182,    0,  495,  432,    0,
          439,  432,    0,    0,    0,  618,    0,    0,    0,    0,
            0,    0,  338,  532,  333,  495,    0,    0,    0,    0,
            0,    0,    0,  495,  217,  217,    0,    0,  409,    0,
            0,    0,    0,  333,    0,    0,  214
    );

    protected static $yydefault = array(
            3,32767,32767,    1,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,  106,   98,  112,   97,
          108,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,  377,  377,32767,  334,32767,32767,32767,32767,32767,
        32767,32767,32767,  179,  179,  179,32767,32767,32767,  366,
          366,  366,  366,  366,  366,  366,  366,  366,  366,32767,
        32767,32767,32767,32767,  257,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,  262,  382,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,  238,  239,  241,  242,  178,
          367,  131,  263,  381,  177,  205,  207,  256,  206,  183,
          188,  189,  190,  191,  192,  193,  194,  195,  196,  197,
          198,  182,  235,  234,  203,  331,  331,  334,32767,32767,
        32767,32767,32767,32767,32767,32767,  204,  208,  210,  209,
          225,  226,  223,  224,  181,  227,  228,  229,  230,  163,
          163,  163,32767,32767,  376,  376,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,  164,32767,
          217,  218,  292,  292,  122,  122,  122,  122,  122,32767,
        32767,32767,32767,32767,  300,32767,32767,32767,32767,32767,
          302,32767,  212,  213,  211,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,  339,  301,32767,32767,32767,32767,
        32767,32767,32767,32767,  352,  288,32767,32767,32767,  281,
        32767,  109,  111,   61,  318,32767,32767,32767,32767,32767,
          357,32767,32767,32767,   17,32767,32767,32767,  389,  352,
        32767,32767,   19,32767,32767,32767,32767,  233,32767,32767,
          356,  350,32767,32767,32767,32767,32767,   65,  297,32767,
          303,32767,32767,32767,   65,32767,32767,32767,32767,   65,
        32767,  355,  354,   65,32767,  282,  333,32767,   65,   76,
        32767,   74,32767,   95,   95,32767,32767,   78,  329,  345,
        32767,32767,   65,32767,  270,  333,32767,32767,  270,   65,
        32767,32767,    4,  307,32767,32767,32767,32767,32767,32767,
        32767,32767,32767,32767,32767,32767,32767,32767,  283,32767,
        32767,32767,  253,  254,  341,32767,  342,32767,  281,32767,
          221,  200,32767,  202,32767,32767,  286,  289,32767,32767,
        32767,  140,32767,  284,32767,  186,32767,32767,32767,32767,
          384,32767,32767,  180,32767,32767,32767,  136,32767,   63,
        32767,  374,32767,32767,  350,  285,  214,  215,  216,32767,
        32767,32767,32767,32767,32767,32767,32767,  351,32767,32767,
        32767,  116,32767,  318,32767,32767,32767,   77,32767,  184,
          132,32767,32767,  383,32767,32767,32767,32767,32767,32767,
          338,32767,32767,32767,   64,32767,32767,   79,32767,32767,
          350,32767,32767,32767,32767,  120,32767,32767,32767,  175,
        32767,32767,32767,32767,32767,  350,32767,32767,32767,32767,
        32767,32767,32767,32767,    4,32767,  157,32767,32767,32767,
        32767,32767,32767,32767,   25,   25,    3,   25,  103,   25,
          143,    3,   95,   95,   58,  143,   25,  143,   25,   25,
           25,   25,   25,   25,   25,  150,   25,   25,   25,   25,
           25
    );

    protected static $yygoto = array(
          161,  135,  135,  140,  135,  161,  136,  137,  138,  143,
          145,  169,  163,  159,  159,  159,  159,  140,  140,  160,
          160,  160,  160,  160,  160,  160,  160,  160,  160,  155,
          156,  157,  158,  167,  134,  750,  751,  390,  753,  774,
          775,  776,  777,  778,  779,  780,  782,  718,  139,  141,
          142,  144,  165,  166,  168,  184,  196,  197,  198,  199,
          200,  201,  202,  203,  205,  206,  207,  208,  230,  231,
          252,  253,  254,  426,  427,  428,  170,  171,  172,  173,
          174,  175,  176,  177,  178,  179,  180,  181,  146,  147,
          148,  162,  149,  164,  150,  182,  151,  152,  153,  183,
          154,  132,  443,  443,  443,  443,  443,  443,  443,  443,
          443,  443,  443,  311,  485,  421,  421,  449,  417,  419,
          419,  391,  393,  410,  424,  450,  453,  464,  470,  335,
          335,  335,  335,  335,  335,  335,  335,  335,  335,  335,
          335,  335,  335,  335,  335,  646,  646,  906,  906,  813,
          813,  654,  654,  654,  654,  654,  405,  538,  538,  538,
          495,  444,  444,  444,  444,  444,  444,  444,  444,  444,
          444,  444,  611,  611,  611,  611,  270,  606,  612,  490,
          392,  392,  392,  392,  392,  392,  392,  392,  392,  392,
          392,  392,  392,  392,  392,  392,  539,  539,  539,  582,
          395,  395,    5,  878,   16,  210,    6,  211,  396,  396,
          537,  537,  537,    7,  422,   17,   18,    8,   19,    9,
           10,   11,  910,   20,   12,   13,   14,   15,  455,  483,
          632,  617,  615,  613,  615,  508,  398,  641,  636,  850,
          850,  850,  850,  850,  850,  850,  850,  850,  850,  850,
          430,  431,  432,  433,  434,  435,  436,  438,  466,  835,
          458,  463,  500,  467,  273,  315,  830,    1,  697,  316,
          809,  810,    2,  771,   26,   21,  285,  554,  672,  621,
          852,  853,  868,  652,  707,  276,  661,  807,  877,  807,
          439,  291,  250,  885,  885,  808,  241,  886,  886,  294,
          476,   29,  294,  916,  916,  481,  901,  901,  901,  866,
          292,  484,  919,  916,  408,  903,  299,  299,  299,  418,
          884,  304,  397,  397,  429,  716,  762,  404,  919,  919,
          299,  825,  824,  459,  650,  546,  664,  851,  518,  310,
          488,  404,  404,  312,  271,  272,  552,  804,  669,  620,
          863,  487,  403,    0,  705,    0,    0,    0,    0,  302,
            0,    0,  425,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,    0,  409
    );

    protected static $yygcheck = array(
           24,   24,   24,   24,   24,   24,   24,   24,   24,   24,
           24,   24,   24,   24,   24,   24,   24,   24,   24,   24,
           24,   24,   24,   24,   24,   24,   24,   24,   24,   24,
           24,   24,   24,   24,   24,   24,   24,   24,   24,   24,
           24,   24,   24,   24,   24,   24,   24,   24,   24,   24,
           24,   24,   24,   24,   24,   24,   24,   24,   24,   24,
           24,   24,   24,   24,   24,   24,   24,   24,   24,   24,
           24,   24,   24,   24,   24,   24,   24,   24,   24,   24,
           24,   24,   24,   24,   24,   24,   24,   24,   24,   24,
           24,   24,   24,   24,   24,   24,   24,   24,   24,   24,
           24,   24,   38,   38,   38,   38,   38,   38,   38,   38,
           38,   38,   38,   32,   32,   32,   32,   32,   32,   32,
           32,   32,   32,   32,   32,   32,   32,   32,   32,   38,
           38,   38,   38,   38,   38,   38,   38,   38,   38,   38,
           38,   38,   38,   38,   38,   53,   53,   53,   53,   38,
           38,   38,   38,   38,   38,   38,   75,    6,    6,    6,
           38,   92,   92,   92,   92,   92,   92,   92,   92,   92,
           92,   92,   38,   38,   38,   38,   48,   38,   38,   38,
           89,   89,   89,   89,   89,   89,   89,   89,   89,   89,
           89,   89,   89,   89,   89,   89,    7,    7,    7,   31,
           89,   89,   13,   57,   13,   44,   13,   44,   92,   92,
            5,    5,    5,   13,   83,   13,   13,   13,   13,   13,
           13,   13,  112,   13,   13,   13,   13,   13,   21,   21,
            5,    5,    5,    5,    5,    5,    5,    5,    5,   99,
           99,   99,   99,   99,   99,   99,   99,   99,   99,   99,
           84,   84,   84,   84,   84,   84,   84,   84,   84,   57,
           40,   40,   40,   46,   46,   46,   15,    2,   72,   72,
           57,   57,    2,   15,   15,   15,   15,   12,   12,   12,
           12,   12,   12,   12,   12,    4,   59,   57,   57,   57,
           15,   28,   98,   91,   91,   57,   98,   90,   90,    4,
          101,   15,    4,  113,  113,   15,   91,   91,   91,  104,
           39,   30,  113,  113,   39,  110,   96,   96,   96,   39,
           91,   29,   95,   95,   25,   75,   76,   25,  113,  113,
           96,   97,   97,   39,   55,   10,   60,  100,   50,   96,
           39,   25,   25,    9,   48,   48,   11,   87,   61,   47,
          103,   82,    4,   -1,   74,   -1,   -1,   -1,   -1,    4,
           -1,   -1,    4,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
           -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
           -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
           -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
           -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
           -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
           -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
           -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
           -1,   -1,   -1,   75
    );

    protected static $yygbase = array(
            0,    0, -239,    0,   22,  209,  156,  195,    0,   21,
           55,    1,   89, -303,    0,  -52,    0,    0,    0,    0,
            0,  184,    0,    0,  -30,  294,    0,    0,  245,  102,
           98,  174,  -99,    0,    0,    0,    0,    0,  -83,  -19,
           25,    0,    0,    0, -310,    0,    7,   -2, -168,    0,
           51,    0,    0,  -67,    0,   96,    0,  -61,    0,  251,
           50,    2,    0,    0,    0,    0,    0,    0,    0,    0,
            0,    0,   40,    0,   -6,  109,   93,    0,    0,    0,
            0,    0,   -7,  182,  200,    0,    0,   23,    0,  -32,
           65,   61,  -24,    0,    0,   90,   71,   85,   48,   54,
           49,  114,    0,   -5,  122,    0,    0,    0,    0,    0,
          100,    0,  188,   63,    0
    );

    protected static $yygdefault = array(
        -32768,  361,    3,  533,  378,  557,  558,  559,  295,  293,
          547,  553,  460,    4,  555,  763,  281,  562,  282,  469,
          564,  412,  566,  567,  133,  379,  296,  297,  413,  303,
          456,  581,  204,  301,  583,  283,  585,  590,  284,  489,
          440,  380,  347,  451,  209,  420,  447,  619,  269,  627,
          521,  635,  638,  381,  441,  649,  352,  806,  308,  660,
          665,  670,  673,  323,  313,  465,  677,  678,  243,  682,
          496,  497,  696,  228,  704,  717,  320,  781,  783,  382,
          383,  406,  474,  394,  411,  800,  314,  803,  384,  385,
          331,  332,  821,  818,  275,  871,  274,  349,  240,  856,
          857,  461,  355,  909,  867,  264,  386,  387,  290,  305,
          904,  336,  911,  918,  448
    );

    protected static $yylhs = array(
            0,    1,    2,    2,    4,    4,    3,    3,    3,    3,
            3,    3,    3,    3,    3,    8,    8,   10,   10,   10,
           10,    9,    9,   11,   13,   13,   14,   14,   14,   14,
            5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
            5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
            5,    5,    5,    5,    5,    5,    5,    5,   35,   35,
           37,   36,   36,   29,   29,   39,   39,    6,    7,    7,
            7,   41,   41,   41,   42,   42,   45,   45,   43,   43,
           46,   46,   22,   22,   31,   31,   34,   34,   33,   33,
           47,   23,   23,   23,   23,   48,   48,   49,   49,   50,
           50,   20,   20,   16,   16,   51,   18,   18,   52,   17,
           17,   19,   19,   30,   30,   30,   40,   40,   54,   54,
           55,   55,   56,   56,   56,   56,   57,   57,   57,   58,
           58,   59,   59,   26,   26,   60,   60,   60,   27,   27,
           61,   61,   44,   44,   62,   62,   62,   62,   67,   67,
           68,   68,   69,   69,   69,   69,   70,   71,   71,   66,
           66,   63,   63,   65,   65,   73,   73,   72,   72,   72,
           72,   72,   72,   64,   64,   74,   74,   28,   28,   21,
           21,   24,   24,   24,   24,   24,   24,   24,   24,   24,
           24,   24,   24,   24,   24,   24,   24,   24,   24,   24,
           24,   24,   24,   24,   24,   24,   24,   24,   24,   24,
           24,   24,   24,   24,   24,   24,   24,   24,   24,   24,
           24,   24,   24,   24,   24,   24,   24,   24,   24,   24,
           24,   24,   24,   24,   24,   24,   24,   24,   24,   24,
           24,   24,   24,   24,   24,   24,   24,   24,   24,   24,
           24,   24,   24,   24,   24,   24,   24,   24,   24,   24,
           15,   15,   25,   25,   79,   79,   80,   80,   80,   75,
           82,   82,   86,   86,   87,   88,   88,   88,   88,   88,
           88,   92,   92,   38,   38,   38,   76,   76,   93,   93,
           89,   89,   94,   94,   94,   94,   94,   77,   77,   77,
           81,   81,   81,   85,   85,   99,   99,   99,   99,   99,
           99,   99,   99,   99,   99,   99,   99,   99,   99,   12,
           12,   12,   12,   12,   12,   78,   78,   78,   78,  100,
          100,  101,  101,  103,  103,  102,  102,  104,  104,   32,
           32,   32,   32,  106,  106,  105,  105,  105,  105,  105,
          107,  107,   91,   91,   95,   95,   90,   90,  108,  108,
          108,  108,   96,   96,   96,   96,   84,   84,   97,   97,
           97,   53,  109,  109,  110,  110,  110,   83,   83,  111,
          111,  112,  112,  112,  112,   98,   98,   98,   98,  113,
          113,  113,  113,  113,  113,  113,  114,  114,  114
    );

    protected static $yylen = array(
            1,    1,    2,    0,    1,    3,    1,    1,    1,    1,
            3,    5,    4,    3,    3,    3,    1,    1,    3,    2,
            4,    3,    1,    3,    2,    0,    1,    1,    1,    1,
            3,    5,    8,    3,    5,    9,    3,    2,    3,    2,
            3,    2,    3,    2,    3,    3,    3,    1,    2,    5,
            7,    9,    5,    1,    6,    3,    3,    2,    0,    2,
            8,    0,    4,    1,    3,    0,    1,    9,    7,    6,
            5,    1,    2,    2,    0,    2,    0,    2,    0,    2,
            1,    3,    1,    4,    1,    4,    1,    4,    1,    3,
            3,    3,    4,    4,    5,    0,    2,    4,    3,    1,
            1,    1,    4,    0,    2,    3,    0,    2,    4,    0,
            2,    0,    3,    1,    2,    1,    1,    0,    1,    3,
            3,    5,    0,    1,    1,    1,    2,    3,    3,    1,
            3,    1,    2,    3,    1,    1,    2,    4,    3,    1,
            1,    3,    2,    0,    3,    3,    8,    3,    1,    3,
            0,    2,    4,    5,    4,    4,    3,    1,    1,    1,
            3,    1,    1,    0,    1,    1,    2,    1,    1,    1,
            1,    1,    1,    1,    3,    1,    3,    3,    1,    0,
            1,    1,    3,    3,    4,    4,    1,    2,    3,    3,
            3,    3,    3,    3,    3,    3,    3,    3,    3,    2,
            2,    2,    2,    3,    3,    3,    3,    3,    3,    3,
            3,    3,    3,    3,    3,    3,    3,    3,    3,    2,
            2,    2,    2,    3,    3,    3,    3,    3,    3,    3,
            3,    3,    1,    3,    5,    4,    4,    4,    2,    2,
            2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
            2,    2,    1,    1,    1,    3,    2,    1,    9,   10,
            3,    3,    2,    4,    4,    3,    4,    4,    4,    3,
            0,    4,    1,    3,    2,    2,    4,    6,    2,    2,
            4,    1,    1,    1,    2,    3,    1,    1,    1,    1,
            1,    1,    0,    3,    3,    4,    4,    0,    2,    1,
            0,    1,    1,    0,    1,    1,    1,    1,    1,    1,
            1,    1,    1,    1,    1,    1,    3,    2,    1,    1,
            3,    2,    2,    4,    3,    1,    3,    3,    3,    1,
            1,    0,    2,    0,    1,    3,    1,    3,    1,    1,
            1,    1,    1,    6,    4,    3,    4,    2,    4,    4,
            1,    3,    1,    2,    1,    1,    4,    1,    3,    6,
            4,    4,    4,    4,    1,    4,    0,    1,    1,    3,
            1,    4,    3,    1,    1,    1,    0,    0,    2,    3,
            1,    3,    1,    4,    2,    2,    2,    1,    2,    1,
            4,    3,    3,    3,    6,    3,    1,    1,    1
    );

    protected $yyval;
    protected $yyastk;
    protected $stackPos;
    protected $lexer;

    /**
     * Creates a parser instance.
     *
     * @param PHPParser_Lexer $lexer A lexer
     */
    public function __construct(PHPParser_Lexer $lexer) {
        $this->lexer = $lexer;
    }

    /**
     * Parses PHP code into a node tree.
     *
     * @param string $code The source code to parse
     *
     * @return PHPParser_Node[] Array of statements
     */
    public function parse($code) {
        $this->lexer->startLexing($code);

        // We start off with no lookahead-token
        $tokenId = self::TOKEN_NONE;

        // The attributes for a node are taken from the first and last token of the node.
        // From the first token only the startAttributes are taken and from the last only
        // the endAttributes. Both are merged using the array union operator (+).
        $startAttributes = array('startLine' => 1);
        $endAttributes   = array();

        // In order to figure out the attributes for the starting token, we have to keep
        // them in a stack
        $attributeStack = array($startAttributes);

        // Start off in the initial state and keep a stack of previous states
        $state = 0;
        $stateStack = array($state);

        // AST stack (?)
        $this->yyastk = array();

        // Current position in the stack(s)
        $this->stackPos = 0;

        for (;;) {
            if (self::$yybase[$state] == 0) {
                $yyn = self::$yydefault[$state];
            } else {
                if ($tokenId === self::TOKEN_NONE) {
                    // Fetch the next token id from the lexer and fetch additional info by-ref.
                    // The end attributes are fetched into a temporary variable and only set once the token is really
                    // shifted (not during read). Otherwise you would sometimes get off-by-one errors, when a rule is
                    // reduced after a token was read but not yet shifted.
                    $origTokenId = $this->lexer->getNextToken($tokenValue, $startAttributes, $nextEndAttributes);

                    // map the lexer token id to the internally used token id's
                    $tokenId = $origTokenId >= 0 && $origTokenId < self::TOKEN_MAP_SIZE
                        ? self::$translate[$origTokenId]
                        : self::TOKEN_INVALID;

                    if ($tokenId === self::TOKEN_INVALID) {
                        throw new RangeException(sprintf(
                            'The lexer returned an invalid token (id=%d, value=%s)',
                            $origTokenId, $tokenValue
                        ));
                    }

                    $attributeStack[$this->stackPos] = $startAttributes;
                }

                if ((($yyn = self::$yybase[$state] + $tokenId) >= 0
                     && $yyn < self::YYLAST && self::$yycheck[$yyn] == $tokenId
                     || ($state < self::YY2TBLSTATE
                        && ($yyn = self::$yybase[$state + self::YYNLSTATES] + $tokenId) >= 0
                        && $yyn < self::YYLAST
                        && self::$yycheck[$yyn] == $tokenId))
                    && ($yyn = self::$yyaction[$yyn]) != self::YYDEFAULT) {
                    /*
                     * >= YYNLSTATE: shift and reduce
                     * > 0: shift
                     * = 0: accept
                     * < 0: reduce
                     * = -YYUNEXPECTED: error
                     */
                    if ($yyn > 0) {
                        /* shift */
                        ++$this->stackPos;

                        $stateStack[$this->stackPos]     = $state = $yyn;
                        $this->yyastk[$this->stackPos]   = $tokenValue;
                        $attributeStack[$this->stackPos] = $startAttributes;
                        $endAttributes = $nextEndAttributes;
                        $tokenId = self::TOKEN_NONE;

                        if ($yyn < self::YYNLSTATES)
                            continue;

                        /* $yyn >= YYNLSTATES means shift-and-reduce */
                        $yyn -= self::YYNLSTATES;
                    } else {
                        $yyn = -$yyn;
                    }
                } else {
                    $yyn = self::$yydefault[$state];
                }
            }

            for (;;) {
                /* reduce/error */
                if ($yyn == 0) {
                    /* accept */
                    return $this->yyval;
                } elseif ($yyn != self::YYUNEXPECTED) {
                    /* reduce */
                    try {
                        $this->{'yyn' . $yyn}(
                            $attributeStack[$this->stackPos - self::$yylen[$yyn]]
                            + $endAttributes
                        );
                    } catch (PHPParser_Error $e) {
                        if (-1 === $e->getRawLine()) {
                            $e->setRawLine($startAttributes['startLine']);
                        }

                        throw $e;
                    }

                    /* Goto - shift nonterminal */
                    $this->stackPos -= self::$yylen[$yyn];
                    $yyn = self::$yylhs[$yyn];
                    if (($yyp = self::$yygbase[$yyn] + $stateStack[$this->stackPos]) >= 0
                         && $yyp < self::YYGLAST
                         && self::$yygcheck[$yyp] == $yyn) {
                        $state = self::$yygoto[$yyp];
                    } else {
                        $state = self::$yygdefault[$yyn];
                    }

                    ++$this->stackPos;

                    $stateStack[$this->stackPos]     = $state;
                    $this->yyastk[$this->stackPos]   = $this->yyval;
                    $attributeStack[$this->stackPos] = $startAttributes;
                } else {
                    /* error */
                    $expected = array();

                    $base = self::$yybase[$state];
                    for ($i = 0; $i < self::TOKEN_MAP_SIZE; ++$i) {
                        $n = $base + $i;
                        if ($n >= 0 && $n < self::YYLAST && self::$yycheck[$n] == $i
                         || $state < self::YY2TBLSTATE
                            && ($n = self::$yybase[$state + self::YYNLSTATES] + $i) >= 0
                            && $n < self::YYLAST && self::$yycheck[$n] == $i
                        ) {
                            if (self::$yyaction[$n] != self::YYUNEXPECTED) {
                                if (count($expected) == 4) {
                                    /* Too many expected tokens */
                                    $expected = array();
                                    break;
                                }

                                $expected[] = self::$terminals[$i];
                            }
                        }
                    }

                    $expectedString = '';
                    if ($expected) {
                        $expectedString = ', expecting ' . implode(' or ', $expected);
                    }

                    throw new PHPParser_Error(
                        'Syntax error, unexpected ' . self::$terminals[$tokenId] . $expectedString,
                        $startAttributes['startLine']
                    );
                }

                if ($state < self::YYNLSTATES)
                    break;
                /* >= YYNLSTATES means shift-and-reduce */
                $yyn = $state - self::YYNLSTATES;
            }
        }
    }

    protected function yyn0() {
        $this->yyval = $this->yyastk[$this->stackPos];
    }

    protected function yyn1($attributes) {
         $this->yyval = PHPParser_Node_Stmt_Namespace::postprocess($this->yyastk[$this->stackPos-(1-1)]); 
    }

    protected function yyn2($attributes) {
         if (is_array($this->yyastk[$this->stackPos-(2-2)])) { $this->yyval = array_merge($this->yyastk[$this->stackPos-(2-1)], $this->yyastk[$this->stackPos-(2-2)]); } else { $this->yyastk[$this->stackPos-(2-1)][] = $this->yyastk[$this->stackPos-(2-2)]; $this->yyval = $this->yyastk[$this->stackPos-(2-1)]; }; 
    }

    protected function yyn3($attributes) {
         $this->yyval = array(); 
    }

    protected function yyn4($attributes) {
         $this->yyval = array($this->yyastk[$this->stackPos-(1-1)]); 
    }

    protected function yyn5($attributes) {
         $this->yyastk[$this->stackPos-(3-1)][] = $this->yyastk[$this->stackPos-(3-3)]; $this->yyval = $this->yyastk[$this->stackPos-(3-1)]; 
    }

    protected function yyn6($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn7($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn8($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn9($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_HaltCompiler($this->lexer->handleHaltCompiler(), $attributes); 
    }

    protected function yyn10($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Namespace(new PHPParser_Node_Name($this->yyastk[$this->stackPos-(3-2)], $attributes), null, $attributes); 
    }

    protected function yyn11($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Namespace(new PHPParser_Node_Name($this->yyastk[$this->stackPos-(5-2)], $attributes), $this->yyastk[$this->stackPos-(5-4)], $attributes); 
    }

    protected function yyn12($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Namespace(null, $this->yyastk[$this->stackPos-(4-3)], $attributes); 
    }

    protected function yyn13($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Use($this->yyastk[$this->stackPos-(3-2)], $attributes); 
    }

    protected function yyn14($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Const($this->yyastk[$this->stackPos-(3-2)], $attributes); 
    }

    protected function yyn15($attributes) {
         $this->yyastk[$this->stackPos-(3-1)][] = $this->yyastk[$this->stackPos-(3-3)]; $this->yyval = $this->yyastk[$this->stackPos-(3-1)]; 
    }

    protected function yyn16($attributes) {
         $this->yyval = array($this->yyastk[$this->stackPos-(1-1)]); 
    }

    protected function yyn17($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_UseUse(new PHPParser_Node_Name($this->yyastk[$this->stackPos-(1-1)], $attributes), null, $attributes); 
    }

    protected function yyn18($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_UseUse(new PHPParser_Node_Name($this->yyastk[$this->stackPos-(3-1)], $attributes), $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn19($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_UseUse(new PHPParser_Node_Name($this->yyastk[$this->stackPos-(2-2)], $attributes), null, $attributes); 
    }

    protected function yyn20($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_UseUse(new PHPParser_Node_Name($this->yyastk[$this->stackPos-(4-2)], $attributes), $this->yyastk[$this->stackPos-(4-4)], $attributes); 
    }

    protected function yyn21($attributes) {
         $this->yyastk[$this->stackPos-(3-1)][] = $this->yyastk[$this->stackPos-(3-3)]; $this->yyval = $this->yyastk[$this->stackPos-(3-1)]; 
    }

    protected function yyn22($attributes) {
         $this->yyval = array($this->yyastk[$this->stackPos-(1-1)]); 
    }

    protected function yyn23($attributes) {
         $this->yyval = new PHPParser_Node_Const($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn24($attributes) {
         if (is_array($this->yyastk[$this->stackPos-(2-2)])) { $this->yyval = array_merge($this->yyastk[$this->stackPos-(2-1)], $this->yyastk[$this->stackPos-(2-2)]); } else { $this->yyastk[$this->stackPos-(2-1)][] = $this->yyastk[$this->stackPos-(2-2)]; $this->yyval = $this->yyastk[$this->stackPos-(2-1)]; }; 
    }

    protected function yyn25($attributes) {
         $this->yyval = array(); 
    }

    protected function yyn26($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn27($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn28($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn29($attributes) {
         throw new PHPParser_Error('__halt_compiler() can only be used from the outermost scope'); 
    }

    protected function yyn30($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(3-2)]; 
    }

    protected function yyn31($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_If($this->yyastk[$this->stackPos-(5-2)], array('stmts' => is_array($this->yyastk[$this->stackPos-(5-3)]) ? $this->yyastk[$this->stackPos-(5-3)] : array($this->yyastk[$this->stackPos-(5-3)]), 'elseifs' => $this->yyastk[$this->stackPos-(5-4)], 'else' => $this->yyastk[$this->stackPos-(5-5)]), $attributes); 
    }

    protected function yyn32($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_If($this->yyastk[$this->stackPos-(8-2)], array('stmts' => $this->yyastk[$this->stackPos-(8-4)], 'elseifs' => $this->yyastk[$this->stackPos-(8-5)], 'else' => $this->yyastk[$this->stackPos-(8-6)]), $attributes); 
    }

    protected function yyn33($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_While($this->yyastk[$this->stackPos-(3-2)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn34($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Do($this->yyastk[$this->stackPos-(5-4)], is_array($this->yyastk[$this->stackPos-(5-2)]) ? $this->yyastk[$this->stackPos-(5-2)] : array($this->yyastk[$this->stackPos-(5-2)]), $attributes); 
    }

    protected function yyn35($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_For(array('init' => $this->yyastk[$this->stackPos-(9-3)], 'cond' => $this->yyastk[$this->stackPos-(9-5)], 'loop' => $this->yyastk[$this->stackPos-(9-7)], 'stmts' => $this->yyastk[$this->stackPos-(9-9)]), $attributes); 
    }

    protected function yyn36($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Switch($this->yyastk[$this->stackPos-(3-2)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn37($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Break(null, $attributes); 
    }

    protected function yyn38($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Break($this->yyastk[$this->stackPos-(3-2)], $attributes); 
    }

    protected function yyn39($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Continue(null, $attributes); 
    }

    protected function yyn40($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Continue($this->yyastk[$this->stackPos-(3-2)], $attributes); 
    }

    protected function yyn41($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Return(null, $attributes); 
    }

    protected function yyn42($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Return($this->yyastk[$this->stackPos-(3-2)], $attributes); 
    }

    protected function yyn43($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(2-1)]; 
    }

    protected function yyn44($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Global($this->yyastk[$this->stackPos-(3-2)], $attributes); 
    }

    protected function yyn45($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Static($this->yyastk[$this->stackPos-(3-2)], $attributes); 
    }

    protected function yyn46($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Echo($this->yyastk[$this->stackPos-(3-2)], $attributes); 
    }

    protected function yyn47($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_InlineHTML($this->yyastk[$this->stackPos-(1-1)], $attributes); 
    }

    protected function yyn48($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(2-1)]; 
    }

    protected function yyn49($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Unset($this->yyastk[$this->stackPos-(5-3)], $attributes); 
    }

    protected function yyn50($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Foreach($this->yyastk[$this->stackPos-(7-3)], $this->yyastk[$this->stackPos-(7-5)][0], array('keyVar' => null, 'byRef' => $this->yyastk[$this->stackPos-(7-5)][1], 'stmts' => $this->yyastk[$this->stackPos-(7-7)]), $attributes); 
    }

    protected function yyn51($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Foreach($this->yyastk[$this->stackPos-(9-3)], $this->yyastk[$this->stackPos-(9-7)][0], array('keyVar' => $this->yyastk[$this->stackPos-(9-5)], 'byRef' => $this->yyastk[$this->stackPos-(9-7)][1], 'stmts' => $this->yyastk[$this->stackPos-(9-9)]), $attributes); 
    }

    protected function yyn52($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Declare($this->yyastk[$this->stackPos-(5-3)], $this->yyastk[$this->stackPos-(5-5)], $attributes); 
    }

    protected function yyn53($attributes) {
         $this->yyval = array(); /* means: no statement */ 
    }

    protected function yyn54($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_TryCatch($this->yyastk[$this->stackPos-(6-3)], $this->yyastk[$this->stackPos-(6-5)], $this->yyastk[$this->stackPos-(6-6)], $attributes); 
    }

    protected function yyn55($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Throw($this->yyastk[$this->stackPos-(3-2)], $attributes); 
    }

    protected function yyn56($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Goto($this->yyastk[$this->stackPos-(3-2)], $attributes); 
    }

    protected function yyn57($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Label($this->yyastk[$this->stackPos-(2-1)], $attributes); 
    }

    protected function yyn58($attributes) {
         $this->yyval = array(); 
    }

    protected function yyn59($attributes) {
         $this->yyastk[$this->stackPos-(2-1)][] = $this->yyastk[$this->stackPos-(2-2)]; $this->yyval = $this->yyastk[$this->stackPos-(2-1)]; 
    }

    protected function yyn60($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Catch($this->yyastk[$this->stackPos-(8-3)], substr($this->yyastk[$this->stackPos-(8-4)], 1), $this->yyastk[$this->stackPos-(8-7)], $attributes); 
    }

    protected function yyn61($attributes) {
         $this->yyval = null; 
    }

    protected function yyn62($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(4-3)]; 
    }

    protected function yyn63($attributes) {
         $this->yyval = array($this->yyastk[$this->stackPos-(1-1)]); 
    }

    protected function yyn64($attributes) {
         $this->yyastk[$this->stackPos-(3-1)][] = $this->yyastk[$this->stackPos-(3-3)]; $this->yyval = $this->yyastk[$this->stackPos-(3-1)]; 
    }

    protected function yyn65($attributes) {
         $this->yyval = false; 
    }

    protected function yyn66($attributes) {
         $this->yyval = true; 
    }

    protected function yyn67($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Function($this->yyastk[$this->stackPos-(9-3)], array('byRef' => $this->yyastk[$this->stackPos-(9-2)], 'params' => $this->yyastk[$this->stackPos-(9-5)], 'stmts' => $this->yyastk[$this->stackPos-(9-8)]), $attributes); 
    }

    protected function yyn68($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Class($this->yyastk[$this->stackPos-(7-2)], array('type' => $this->yyastk[$this->stackPos-(7-1)], 'extends' => $this->yyastk[$this->stackPos-(7-3)], 'implements' => $this->yyastk[$this->stackPos-(7-4)], 'stmts' => $this->yyastk[$this->stackPos-(7-6)]), $attributes); 
    }

    protected function yyn69($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Interface($this->yyastk[$this->stackPos-(6-2)], array('extends' => $this->yyastk[$this->stackPos-(6-3)], 'stmts' => $this->yyastk[$this->stackPos-(6-5)]), $attributes); 
    }

    protected function yyn70($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Trait($this->yyastk[$this->stackPos-(5-2)], $this->yyastk[$this->stackPos-(5-4)], $attributes); 
    }

    protected function yyn71($attributes) {
         $this->yyval = 0; 
    }

    protected function yyn72($attributes) {
         $this->yyval = PHPParser_Node_Stmt_Class::MODIFIER_ABSTRACT; 
    }

    protected function yyn73($attributes) {
         $this->yyval = PHPParser_Node_Stmt_Class::MODIFIER_FINAL; 
    }

    protected function yyn74($attributes) {
         $this->yyval = null; 
    }

    protected function yyn75($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(2-2)]; 
    }

    protected function yyn76($attributes) {
         $this->yyval = array(); 
    }

    protected function yyn77($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(2-2)]; 
    }

    protected function yyn78($attributes) {
         $this->yyval = array(); 
    }

    protected function yyn79($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(2-2)]; 
    }

    protected function yyn80($attributes) {
         $this->yyval = array($this->yyastk[$this->stackPos-(1-1)]); 
    }

    protected function yyn81($attributes) {
         $this->yyastk[$this->stackPos-(3-1)][] = $this->yyastk[$this->stackPos-(3-3)]; $this->yyval = $this->yyastk[$this->stackPos-(3-1)]; 
    }

    protected function yyn82($attributes) {
         $this->yyval = is_array($this->yyastk[$this->stackPos-(1-1)]) ? $this->yyastk[$this->stackPos-(1-1)] : array($this->yyastk[$this->stackPos-(1-1)]); 
    }

    protected function yyn83($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(4-2)]; 
    }

    protected function yyn84($attributes) {
         $this->yyval = is_array($this->yyastk[$this->stackPos-(1-1)]) ? $this->yyastk[$this->stackPos-(1-1)] : array($this->yyastk[$this->stackPos-(1-1)]); 
    }

    protected function yyn85($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(4-2)]; 
    }

    protected function yyn86($attributes) {
         $this->yyval = is_array($this->yyastk[$this->stackPos-(1-1)]) ? $this->yyastk[$this->stackPos-(1-1)] : array($this->yyastk[$this->stackPos-(1-1)]); 
    }

    protected function yyn87($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(4-2)]; 
    }

    protected function yyn88($attributes) {
         $this->yyval = array($this->yyastk[$this->stackPos-(1-1)]); 
    }

    protected function yyn89($attributes) {
         $this->yyastk[$this->stackPos-(3-1)][] = $this->yyastk[$this->stackPos-(3-3)]; $this->yyval = $this->yyastk[$this->stackPos-(3-1)]; 
    }

    protected function yyn90($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_DeclareDeclare($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn91($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(3-2)]; 
    }

    protected function yyn92($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(4-3)]; 
    }

    protected function yyn93($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(4-2)]; 
    }

    protected function yyn94($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(5-3)]; 
    }

    protected function yyn95($attributes) {
         $this->yyval = array(); 
    }

    protected function yyn96($attributes) {
         $this->yyastk[$this->stackPos-(2-1)][] = $this->yyastk[$this->stackPos-(2-2)]; $this->yyval = $this->yyastk[$this->stackPos-(2-1)]; 
    }

    protected function yyn97($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Case($this->yyastk[$this->stackPos-(4-2)], $this->yyastk[$this->stackPos-(4-4)], $attributes); 
    }

    protected function yyn98($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Case(null, $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn99() {
        $this->yyval = $this->yyastk[$this->stackPos];
    }

    protected function yyn100() {
        $this->yyval = $this->yyastk[$this->stackPos];
    }

    protected function yyn101($attributes) {
         $this->yyval = is_array($this->yyastk[$this->stackPos-(1-1)]) ? $this->yyastk[$this->stackPos-(1-1)] : array($this->yyastk[$this->stackPos-(1-1)]); 
    }

    protected function yyn102($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(4-2)]; 
    }

    protected function yyn103($attributes) {
         $this->yyval = array(); 
    }

    protected function yyn104($attributes) {
         $this->yyastk[$this->stackPos-(2-1)][] = $this->yyastk[$this->stackPos-(2-2)]; $this->yyval = $this->yyastk[$this->stackPos-(2-1)]; 
    }

    protected function yyn105($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_ElseIf($this->yyastk[$this->stackPos-(3-2)], is_array($this->yyastk[$this->stackPos-(3-3)]) ? $this->yyastk[$this->stackPos-(3-3)] : array($this->yyastk[$this->stackPos-(3-3)]), $attributes); 
    }

    protected function yyn106($attributes) {
         $this->yyval = array(); 
    }

    protected function yyn107($attributes) {
         $this->yyastk[$this->stackPos-(2-1)][] = $this->yyastk[$this->stackPos-(2-2)]; $this->yyval = $this->yyastk[$this->stackPos-(2-1)]; 
    }

    protected function yyn108($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_ElseIf($this->yyastk[$this->stackPos-(4-2)], $this->yyastk[$this->stackPos-(4-4)], $attributes); 
    }

    protected function yyn109($attributes) {
         $this->yyval = null; 
    }

    protected function yyn110($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Else(is_array($this->yyastk[$this->stackPos-(2-2)]) ? $this->yyastk[$this->stackPos-(2-2)] : array($this->yyastk[$this->stackPos-(2-2)]), $attributes); 
    }

    protected function yyn111($attributes) {
         $this->yyval = null; 
    }

    protected function yyn112($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Else($this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn113($attributes) {
         $this->yyval = array($this->yyastk[$this->stackPos-(1-1)], false); 
    }

    protected function yyn114($attributes) {
         $this->yyval = array($this->yyastk[$this->stackPos-(2-2)], true); 
    }

    protected function yyn115($attributes) {
         $this->yyval = array($this->yyastk[$this->stackPos-(1-1)], false); 
    }

    protected function yyn116($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn117($attributes) {
         $this->yyval = array(); 
    }

    protected function yyn118($attributes) {
         $this->yyval = array($this->yyastk[$this->stackPos-(1-1)]); 
    }

    protected function yyn119($attributes) {
         $this->yyastk[$this->stackPos-(3-1)][] = $this->yyastk[$this->stackPos-(3-3)]; $this->yyval = $this->yyastk[$this->stackPos-(3-1)]; 
    }

    protected function yyn120($attributes) {
         $this->yyval = new PHPParser_Node_Param(substr($this->yyastk[$this->stackPos-(3-3)], 1), null, $this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-2)], $attributes); 
    }

    protected function yyn121($attributes) {
         $this->yyval = new PHPParser_Node_Param(substr($this->yyastk[$this->stackPos-(5-3)], 1), $this->yyastk[$this->stackPos-(5-5)], $this->yyastk[$this->stackPos-(5-1)], $this->yyastk[$this->stackPos-(5-2)], $attributes); 
    }

    protected function yyn122($attributes) {
         $this->yyval = null; 
    }

    protected function yyn123($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn124($attributes) {
         $this->yyval = 'array'; 
    }

    protected function yyn125($attributes) {
         $this->yyval = 'callable'; 
    }

    protected function yyn126($attributes) {
         $this->yyval = array(); 
    }

    protected function yyn127($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(3-2)]; 
    }

    protected function yyn128($attributes) {
         $this->yyval = array(new PHPParser_Node_Arg($this->yyastk[$this->stackPos-(3-2)], false, $attributes)); 
    }

    protected function yyn129($attributes) {
         $this->yyval = array($this->yyastk[$this->stackPos-(1-1)]); 
    }

    protected function yyn130($attributes) {
         $this->yyastk[$this->stackPos-(3-1)][] = $this->yyastk[$this->stackPos-(3-3)]; $this->yyval = $this->yyastk[$this->stackPos-(3-1)]; 
    }

    protected function yyn131($attributes) {
         $this->yyval = new PHPParser_Node_Arg($this->yyastk[$this->stackPos-(1-1)], false, $attributes); 
    }

    protected function yyn132($attributes) {
         $this->yyval = new PHPParser_Node_Arg($this->yyastk[$this->stackPos-(2-2)], true, $attributes); 
    }

    protected function yyn133($attributes) {
         $this->yyastk[$this->stackPos-(3-1)][] = $this->yyastk[$this->stackPos-(3-3)]; $this->yyval = $this->yyastk[$this->stackPos-(3-1)]; 
    }

    protected function yyn134($attributes) {
         $this->yyval = array($this->yyastk[$this->stackPos-(1-1)]); 
    }

    protected function yyn135($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Variable(substr($this->yyastk[$this->stackPos-(1-1)], 1), $attributes); 
    }

    protected function yyn136($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Variable($this->yyastk[$this->stackPos-(2-2)], $attributes); 
    }

    protected function yyn137($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Variable($this->yyastk[$this->stackPos-(4-3)], $attributes); 
    }

    protected function yyn138($attributes) {
         $this->yyastk[$this->stackPos-(3-1)][] = $this->yyastk[$this->stackPos-(3-3)]; $this->yyval = $this->yyastk[$this->stackPos-(3-1)]; 
    }

    protected function yyn139($attributes) {
         $this->yyval = array($this->yyastk[$this->stackPos-(1-1)]); 
    }

    protected function yyn140($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_StaticVar(substr($this->yyastk[$this->stackPos-(1-1)], 1), null, $attributes); 
    }

    protected function yyn141($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_StaticVar(substr($this->yyastk[$this->stackPos-(3-1)], 1), $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn142($attributes) {
         $this->yyastk[$this->stackPos-(2-1)][] = $this->yyastk[$this->stackPos-(2-2)]; $this->yyval = $this->yyastk[$this->stackPos-(2-1)]; 
    }

    protected function yyn143($attributes) {
         $this->yyval = array(); 
    }

    protected function yyn144($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_Property($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-2)], $attributes); 
    }

    protected function yyn145($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_ClassConst($this->yyastk[$this->stackPos-(3-2)], $attributes); 
    }

    protected function yyn146($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_ClassMethod($this->yyastk[$this->stackPos-(8-4)], array('type' => $this->yyastk[$this->stackPos-(8-1)], 'byRef' => $this->yyastk[$this->stackPos-(8-3)], 'params' => $this->yyastk[$this->stackPos-(8-6)], 'stmts' => $this->yyastk[$this->stackPos-(8-8)]), $attributes); 
    }

    protected function yyn147($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_TraitUse($this->yyastk[$this->stackPos-(3-2)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn148($attributes) {
         $this->yyval = array(); 
    }

    protected function yyn149($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(3-2)]; 
    }

    protected function yyn150($attributes) {
         $this->yyval = array(); 
    }

    protected function yyn151($attributes) {
         $this->yyastk[$this->stackPos-(2-1)][] = $this->yyastk[$this->stackPos-(2-2)]; $this->yyval = $this->yyastk[$this->stackPos-(2-1)]; 
    }

    protected function yyn152($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_TraitUseAdaptation_Precedence($this->yyastk[$this->stackPos-(4-1)][0], $this->yyastk[$this->stackPos-(4-1)][1], $this->yyastk[$this->stackPos-(4-3)], $attributes); 
    }

    protected function yyn153($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_TraitUseAdaptation_Alias($this->yyastk[$this->stackPos-(5-1)][0], $this->yyastk[$this->stackPos-(5-1)][1], $this->yyastk[$this->stackPos-(5-3)], $this->yyastk[$this->stackPos-(5-4)], $attributes); 
    }

    protected function yyn154($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_TraitUseAdaptation_Alias($this->yyastk[$this->stackPos-(4-1)][0], $this->yyastk[$this->stackPos-(4-1)][1], $this->yyastk[$this->stackPos-(4-3)], null, $attributes); 
    }

    protected function yyn155($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_TraitUseAdaptation_Alias($this->yyastk[$this->stackPos-(4-1)][0], $this->yyastk[$this->stackPos-(4-1)][1], null, $this->yyastk[$this->stackPos-(4-3)], $attributes); 
    }

    protected function yyn156($attributes) {
         $this->yyval = array($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)]); 
    }

    protected function yyn157($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn158($attributes) {
         $this->yyval = array(null, $this->yyastk[$this->stackPos-(1-1)]); 
    }

    protected function yyn159($attributes) {
         $this->yyval = null; 
    }

    protected function yyn160($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(3-2)]; 
    }

    protected function yyn161($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn162($attributes) {
         $this->yyval = PHPParser_Node_Stmt_Class::MODIFIER_PUBLIC; 
    }

    protected function yyn163($attributes) {
         $this->yyval = PHPParser_Node_Stmt_Class::MODIFIER_PUBLIC; 
    }

    protected function yyn164($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn165($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn166($attributes) {
         PHPParser_Node_Stmt_Class::verifyModifier($this->yyastk[$this->stackPos-(2-1)], $this->yyastk[$this->stackPos-(2-2)]); $this->yyval = $this->yyastk[$this->stackPos-(2-1)] | $this->yyastk[$this->stackPos-(2-2)]; 
    }

    protected function yyn167($attributes) {
         $this->yyval = PHPParser_Node_Stmt_Class::MODIFIER_PUBLIC; 
    }

    protected function yyn168($attributes) {
         $this->yyval = PHPParser_Node_Stmt_Class::MODIFIER_PROTECTED; 
    }

    protected function yyn169($attributes) {
         $this->yyval = PHPParser_Node_Stmt_Class::MODIFIER_PRIVATE; 
    }

    protected function yyn170($attributes) {
         $this->yyval = PHPParser_Node_Stmt_Class::MODIFIER_STATIC; 
    }

    protected function yyn171($attributes) {
         $this->yyval = PHPParser_Node_Stmt_Class::MODIFIER_ABSTRACT; 
    }

    protected function yyn172($attributes) {
         $this->yyval = PHPParser_Node_Stmt_Class::MODIFIER_FINAL; 
    }

    protected function yyn173($attributes) {
         $this->yyval = array($this->yyastk[$this->stackPos-(1-1)]); 
    }

    protected function yyn174($attributes) {
         $this->yyastk[$this->stackPos-(3-1)][] = $this->yyastk[$this->stackPos-(3-3)]; $this->yyval = $this->yyastk[$this->stackPos-(3-1)]; 
    }

    protected function yyn175($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_PropertyProperty(substr($this->yyastk[$this->stackPos-(1-1)], 1), null, $attributes); 
    }

    protected function yyn176($attributes) {
         $this->yyval = new PHPParser_Node_Stmt_PropertyProperty(substr($this->yyastk[$this->stackPos-(3-1)], 1), $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn177($attributes) {
         $this->yyastk[$this->stackPos-(3-1)][] = $this->yyastk[$this->stackPos-(3-3)]; $this->yyval = $this->yyastk[$this->stackPos-(3-1)]; 
    }

    protected function yyn178($attributes) {
         $this->yyval = array($this->yyastk[$this->stackPos-(1-1)]); 
    }

    protected function yyn179($attributes) {
         $this->yyval = array(); 
    }

    protected function yyn180($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn181($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn182($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Assign($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn183($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Assign($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn184($attributes) {
         $this->yyval = new PHPParser_Node_Expr_AssignRef($this->yyastk[$this->stackPos-(4-1)], $this->yyastk[$this->stackPos-(4-4)], $attributes); 
    }

    protected function yyn185($attributes) {
         $this->yyval = new PHPParser_Node_Expr_AssignRef($this->yyastk[$this->stackPos-(4-1)], $this->yyastk[$this->stackPos-(4-4)], $attributes); 
    }

    protected function yyn186($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn187($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Clone($this->yyastk[$this->stackPos-(2-2)], $attributes); 
    }

    protected function yyn188($attributes) {
         $this->yyval = new PHPParser_Node_Expr_AssignPlus($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn189($attributes) {
         $this->yyval = new PHPParser_Node_Expr_AssignMinus($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn190($attributes) {
         $this->yyval = new PHPParser_Node_Expr_AssignMul($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn191($attributes) {
         $this->yyval = new PHPParser_Node_Expr_AssignDiv($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn192($attributes) {
         $this->yyval = new PHPParser_Node_Expr_AssignConcat($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn193($attributes) {
         $this->yyval = new PHPParser_Node_Expr_AssignMod($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn194($attributes) {
         $this->yyval = new PHPParser_Node_Expr_AssignBitwiseAnd($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn195($attributes) {
         $this->yyval = new PHPParser_Node_Expr_AssignBitwiseOr($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn196($attributes) {
         $this->yyval = new PHPParser_Node_Expr_AssignBitwiseXor($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn197($attributes) {
         $this->yyval = new PHPParser_Node_Expr_AssignShiftLeft($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn198($attributes) {
         $this->yyval = new PHPParser_Node_Expr_AssignShiftRight($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn199($attributes) {
         $this->yyval = new PHPParser_Node_Expr_PostInc($this->yyastk[$this->stackPos-(2-1)], $attributes); 
    }

    protected function yyn200($attributes) {
         $this->yyval = new PHPParser_Node_Expr_PreInc($this->yyastk[$this->stackPos-(2-2)], $attributes); 
    }

    protected function yyn201($attributes) {
         $this->yyval = new PHPParser_Node_Expr_PostDec($this->yyastk[$this->stackPos-(2-1)], $attributes); 
    }

    protected function yyn202($attributes) {
         $this->yyval = new PHPParser_Node_Expr_PreDec($this->yyastk[$this->stackPos-(2-2)], $attributes); 
    }

    protected function yyn203($attributes) {
         $this->yyval = new PHPParser_Node_Expr_BooleanOr($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn204($attributes) {
         $this->yyval = new PHPParser_Node_Expr_BooleanAnd($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn205($attributes) {
         $this->yyval = new PHPParser_Node_Expr_LogicalOr($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn206($attributes) {
         $this->yyval = new PHPParser_Node_Expr_LogicalAnd($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn207($attributes) {
         $this->yyval = new PHPParser_Node_Expr_LogicalXor($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn208($attributes) {
         $this->yyval = new PHPParser_Node_Expr_BitwiseOr($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn209($attributes) {
         $this->yyval = new PHPParser_Node_Expr_BitwiseAnd($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn210($attributes) {
         $this->yyval = new PHPParser_Node_Expr_BitwiseXor($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn211($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Concat($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn212($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Plus($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn213($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Minus($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn214($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Mul($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn215($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Div($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn216($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Mod($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn217($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ShiftLeft($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn218($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ShiftRight($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn219($attributes) {
         $this->yyval = new PHPParser_Node_Expr_UnaryPlus($this->yyastk[$this->stackPos-(2-2)], $attributes); 
    }

    protected function yyn220($attributes) {
         $this->yyval = new PHPParser_Node_Expr_UnaryMinus($this->yyastk[$this->stackPos-(2-2)], $attributes); 
    }

    protected function yyn221($attributes) {
         $this->yyval = new PHPParser_Node_Expr_BooleanNot($this->yyastk[$this->stackPos-(2-2)], $attributes); 
    }

    protected function yyn222($attributes) {
         $this->yyval = new PHPParser_Node_Expr_BitwiseNot($this->yyastk[$this->stackPos-(2-2)], $attributes); 
    }

    protected function yyn223($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Identical($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn224($attributes) {
         $this->yyval = new PHPParser_Node_Expr_NotIdentical($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn225($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Equal($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn226($attributes) {
         $this->yyval = new PHPParser_Node_Expr_NotEqual($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn227($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Smaller($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn228($attributes) {
         $this->yyval = new PHPParser_Node_Expr_SmallerOrEqual($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn229($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Greater($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn230($attributes) {
         $this->yyval = new PHPParser_Node_Expr_GreaterOrEqual($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn231($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Instanceof($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn232($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn233($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(3-2)]; 
    }

    protected function yyn234($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Ternary($this->yyastk[$this->stackPos-(5-1)], $this->yyastk[$this->stackPos-(5-3)], $this->yyastk[$this->stackPos-(5-5)], $attributes); 
    }

    protected function yyn235($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Ternary($this->yyastk[$this->stackPos-(4-1)], null, $this->yyastk[$this->stackPos-(4-4)], $attributes); 
    }

    protected function yyn236($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Isset($this->yyastk[$this->stackPos-(4-3)], $attributes); 
    }

    protected function yyn237($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Empty($this->yyastk[$this->stackPos-(4-3)], $attributes); 
    }

    protected function yyn238($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Include($this->yyastk[$this->stackPos-(2-2)], PHPParser_Node_Expr_Include::TYPE_INCLUDE, $attributes); 
    }

    protected function yyn239($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Include($this->yyastk[$this->stackPos-(2-2)], PHPParser_Node_Expr_Include::TYPE_INCLUDE_ONCE, $attributes); 
    }

    protected function yyn240($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Eval($this->yyastk[$this->stackPos-(2-2)], $attributes); 
    }

    protected function yyn241($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Include($this->yyastk[$this->stackPos-(2-2)], PHPParser_Node_Expr_Include::TYPE_REQUIRE, $attributes); 
    }

    protected function yyn242($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Include($this->yyastk[$this->stackPos-(2-2)], PHPParser_Node_Expr_Include::TYPE_REQUIRE_ONCE, $attributes); 
    }

    protected function yyn243($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Cast_Int($this->yyastk[$this->stackPos-(2-2)], $attributes); 
    }

    protected function yyn244($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Cast_Double($this->yyastk[$this->stackPos-(2-2)], $attributes); 
    }

    protected function yyn245($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Cast_String($this->yyastk[$this->stackPos-(2-2)], $attributes); 
    }

    protected function yyn246($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Cast_Array($this->yyastk[$this->stackPos-(2-2)], $attributes); 
    }

    protected function yyn247($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Cast_Object($this->yyastk[$this->stackPos-(2-2)], $attributes); 
    }

    protected function yyn248($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Cast_Bool($this->yyastk[$this->stackPos-(2-2)], $attributes); 
    }

    protected function yyn249($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Cast_Unset($this->yyastk[$this->stackPos-(2-2)], $attributes); 
    }

    protected function yyn250($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Exit($this->yyastk[$this->stackPos-(2-2)], $attributes); 
    }

    protected function yyn251($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ErrorSuppress($this->yyastk[$this->stackPos-(2-2)], $attributes); 
    }

    protected function yyn252($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn253($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn254($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn255($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ShellExec($this->yyastk[$this->stackPos-(3-2)], $attributes); 
    }

    protected function yyn256($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Print($this->yyastk[$this->stackPos-(2-2)], $attributes); 
    }

    protected function yyn257($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Yield(null, null, $attributes); 
    }

    protected function yyn258($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Closure(array('static' => false, 'byRef' => $this->yyastk[$this->stackPos-(9-2)], 'params' => $this->yyastk[$this->stackPos-(9-4)], 'uses' => $this->yyastk[$this->stackPos-(9-6)], 'stmts' => $this->yyastk[$this->stackPos-(9-8)]), $attributes); 
    }

    protected function yyn259($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Closure(array('static' => true, 'byRef' => $this->yyastk[$this->stackPos-(10-3)], 'params' => $this->yyastk[$this->stackPos-(10-5)], 'uses' => $this->yyastk[$this->stackPos-(10-7)], 'stmts' => $this->yyastk[$this->stackPos-(10-9)]), $attributes); 
    }

    protected function yyn260($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(3-2)]; 
    }

    protected function yyn261($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(3-2)]; 
    }

    protected function yyn262($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Yield($this->yyastk[$this->stackPos-(2-2)], null, $attributes); 
    }

    protected function yyn263($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Yield($this->yyastk[$this->stackPos-(4-4)], $this->yyastk[$this->stackPos-(4-2)], $attributes); 
    }

    protected function yyn264($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Array($this->yyastk[$this->stackPos-(4-3)], $attributes); 
    }

    protected function yyn265($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Array($this->yyastk[$this->stackPos-(3-2)], $attributes); 
    }

    protected function yyn266($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ArrayDimFetch($this->yyastk[$this->stackPos-(4-1)], $this->yyastk[$this->stackPos-(4-3)], $attributes); 
    }

    protected function yyn267($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ArrayDimFetch(new PHPParser_Node_Scalar_String(PHPParser_Node_Scalar_String::parse($this->yyastk[$this->stackPos-(4-1)]), $attributes), $this->yyastk[$this->stackPos-(4-3)], $attributes); 
    }

    protected function yyn268($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ArrayDimFetch($this->yyastk[$this->stackPos-(4-1)], $this->yyastk[$this->stackPos-(4-3)], $attributes); 
    }

    protected function yyn269($attributes) {
         $this->yyval = new PHPParser_Node_Expr_New($this->yyastk[$this->stackPos-(3-2)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn270($attributes) {
         $this->yyval = array(); 
    }

    protected function yyn271($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(4-3)]; 
    }

    protected function yyn272($attributes) {
         $this->yyval = array($this->yyastk[$this->stackPos-(1-1)]); 
    }

    protected function yyn273($attributes) {
         $this->yyastk[$this->stackPos-(3-1)][] = $this->yyastk[$this->stackPos-(3-3)]; $this->yyval = $this->yyastk[$this->stackPos-(3-1)]; 
    }

    protected function yyn274($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ClosureUse(substr($this->yyastk[$this->stackPos-(2-2)], 1), $this->yyastk[$this->stackPos-(2-1)], $attributes); 
    }

    protected function yyn275($attributes) {
         $this->yyval = new PHPParser_Node_Expr_FuncCall($this->yyastk[$this->stackPos-(2-1)], $this->yyastk[$this->stackPos-(2-2)], $attributes); 
    }

    protected function yyn276($attributes) {
         $this->yyval = new PHPParser_Node_Expr_StaticCall($this->yyastk[$this->stackPos-(4-1)], $this->yyastk[$this->stackPos-(4-3)], $this->yyastk[$this->stackPos-(4-4)], $attributes); 
    }

    protected function yyn277($attributes) {
         $this->yyval = new PHPParser_Node_Expr_StaticCall($this->yyastk[$this->stackPos-(6-1)], $this->yyastk[$this->stackPos-(6-4)], $this->yyastk[$this->stackPos-(6-6)], $attributes); 
    }

    protected function yyn278($attributes) {
        
            if ($this->yyastk[$this->stackPos-(2-1)] instanceof PHPParser_Node_Expr_StaticPropertyFetch) {
                $this->yyval = new PHPParser_Node_Expr_StaticCall($this->yyastk[$this->stackPos-(2-1)]->class, new PHPParser_Node_Expr_Variable($this->yyastk[$this->stackPos-(2-1)]->name, $attributes), $this->yyastk[$this->stackPos-(2-2)], $attributes);
            } elseif ($this->yyastk[$this->stackPos-(2-1)] instanceof PHPParser_Node_Expr_ArrayDimFetch) {
                $tmp = $this->yyastk[$this->stackPos-(2-1)];
                while ($tmp->var instanceof PHPParser_Node_Expr_ArrayDimFetch) {
                    $tmp = $tmp->var;
                }

                $this->yyval = new PHPParser_Node_Expr_StaticCall($tmp->var->class, $this->yyastk[$this->stackPos-(2-1)], $this->yyastk[$this->stackPos-(2-2)], $attributes);
                $tmp->var = new PHPParser_Node_Expr_Variable($tmp->var->name, $attributes);
            } else {
                throw new Exception;
            }
          
    }

    protected function yyn279($attributes) {
         $this->yyval = new PHPParser_Node_Expr_FuncCall($this->yyastk[$this->stackPos-(2-1)], $this->yyastk[$this->stackPos-(2-2)], $attributes); 
    }

    protected function yyn280($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ArrayDimFetch($this->yyastk[$this->stackPos-(4-1)], $this->yyastk[$this->stackPos-(4-3)], $attributes); 
    }

    protected function yyn281($attributes) {
         $this->yyval = new PHPParser_Node_Name('static', $attributes); 
    }

    protected function yyn282($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn283($attributes) {
         $this->yyval = new PHPParser_Node_Name($this->yyastk[$this->stackPos-(1-1)], $attributes); 
    }

    protected function yyn284($attributes) {
         $this->yyval = new PHPParser_Node_Name_FullyQualified($this->yyastk[$this->stackPos-(2-2)], $attributes); 
    }

    protected function yyn285($attributes) {
         $this->yyval = new PHPParser_Node_Name_Relative($this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn286($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn287($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn288($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn289($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn290($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn291($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn292() {
        $this->yyval = $this->yyastk[$this->stackPos];
    }

    protected function yyn293($attributes) {
         $this->yyval = new PHPParser_Node_Expr_PropertyFetch($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn294($attributes) {
         $this->yyval = new PHPParser_Node_Expr_PropertyFetch($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn295($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ArrayDimFetch($this->yyastk[$this->stackPos-(4-1)], $this->yyastk[$this->stackPos-(4-3)], $attributes); 
    }

    protected function yyn296($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ArrayDimFetch($this->yyastk[$this->stackPos-(4-1)], $this->yyastk[$this->stackPos-(4-3)], $attributes); 
    }

    protected function yyn297($attributes) {
         $this->yyval = null; 
    }

    protected function yyn298($attributes) {
         $this->yyval = null; 
    }

    protected function yyn299($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn300($attributes) {
         $this->yyval = array(); 
    }

    protected function yyn301($attributes) {
         $this->yyval = array(PHPParser_Node_Scalar_String::parseEscapeSequences($this->yyastk[$this->stackPos-(1-1)], '`')); 
    }

    protected function yyn302($attributes) {
         foreach ($this->yyastk[$this->stackPos-(1-1)] as &$s) { if (is_string($s)) { $s = PHPParser_Node_Scalar_String::parseEscapeSequences($s, '`'); } }; $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn303($attributes) {
         $this->yyval = array(); 
    }

    protected function yyn304($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn305($attributes) {
         $this->yyval = new PHPParser_Node_Scalar_LNumber(PHPParser_Node_Scalar_LNumber::parse($this->yyastk[$this->stackPos-(1-1)]), $attributes); 
    }

    protected function yyn306($attributes) {
         $this->yyval = new PHPParser_Node_Scalar_DNumber(PHPParser_Node_Scalar_DNumber::parse($this->yyastk[$this->stackPos-(1-1)]), $attributes); 
    }

    protected function yyn307($attributes) {
         $this->yyval = new PHPParser_Node_Scalar_String(PHPParser_Node_Scalar_String::parse($this->yyastk[$this->stackPos-(1-1)]), $attributes); 
    }

    protected function yyn308($attributes) {
         $this->yyval = new PHPParser_Node_Scalar_LineConst($attributes); 
    }

    protected function yyn309($attributes) {
         $this->yyval = new PHPParser_Node_Scalar_FileConst($attributes); 
    }

    protected function yyn310($attributes) {
         $this->yyval = new PHPParser_Node_Scalar_DirConst($attributes); 
    }

    protected function yyn311($attributes) {
         $this->yyval = new PHPParser_Node_Scalar_ClassConst($attributes); 
    }

    protected function yyn312($attributes) {
         $this->yyval = new PHPParser_Node_Scalar_TraitConst($attributes); 
    }

    protected function yyn313($attributes) {
         $this->yyval = new PHPParser_Node_Scalar_MethodConst($attributes); 
    }

    protected function yyn314($attributes) {
         $this->yyval = new PHPParser_Node_Scalar_FuncConst($attributes); 
    }

    protected function yyn315($attributes) {
         $this->yyval = new PHPParser_Node_Scalar_NSConst($attributes); 
    }

    protected function yyn316($attributes) {
         $this->yyval = new PHPParser_Node_Scalar_String(PHPParser_Node_Scalar_String::parseDocString($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-2)]), $attributes); 
    }

    protected function yyn317($attributes) {
         $this->yyval = new PHPParser_Node_Scalar_String('', $attributes); 
    }

    protected function yyn318($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ConstFetch($this->yyastk[$this->stackPos-(1-1)], $attributes); 
    }

    protected function yyn319($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn320($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ClassConstFetch($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn321($attributes) {
         $this->yyval = new PHPParser_Node_Expr_UnaryPlus($this->yyastk[$this->stackPos-(2-2)], $attributes); 
    }

    protected function yyn322($attributes) {
         $this->yyval = new PHPParser_Node_Expr_UnaryMinus($this->yyastk[$this->stackPos-(2-2)], $attributes); 
    }

    protected function yyn323($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Array($this->yyastk[$this->stackPos-(4-3)], $attributes); 
    }

    protected function yyn324($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Array($this->yyastk[$this->stackPos-(3-2)], $attributes); 
    }

    protected function yyn325($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn326($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ClassConstFetch($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn327($attributes) {
         foreach ($this->yyastk[$this->stackPos-(3-2)] as &$s) { if (is_string($s)) { $s = PHPParser_Node_Scalar_String::parseEscapeSequences($s, '"'); } }; $this->yyval = new PHPParser_Node_Scalar_Encapsed($this->yyastk[$this->stackPos-(3-2)], $attributes); 
    }

    protected function yyn328($attributes) {
         foreach ($this->yyastk[$this->stackPos-(3-2)] as &$s) { if (is_string($s)) { $s = PHPParser_Node_Scalar_String::parseEscapeSequences($s, null); } } $s = preg_replace('~(\r\n|\n|\r)$~', '', $s); if ('' === $s) array_pop($this->yyastk[$this->stackPos-(3-2)]);; $this->yyval = new PHPParser_Node_Scalar_Encapsed($this->yyastk[$this->stackPos-(3-2)], $attributes); 
    }

    protected function yyn329($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn330($attributes) {
         $this->yyval = 'class'; 
    }

    protected function yyn331($attributes) {
         $this->yyval = array(); 
    }

    protected function yyn332($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(2-1)]; 
    }

    protected function yyn333() {
        $this->yyval = $this->yyastk[$this->stackPos];
    }

    protected function yyn334() {
        $this->yyval = $this->yyastk[$this->stackPos];
    }

    protected function yyn335($attributes) {
         $this->yyastk[$this->stackPos-(3-1)][] = $this->yyastk[$this->stackPos-(3-3)]; $this->yyval = $this->yyastk[$this->stackPos-(3-1)]; 
    }

    protected function yyn336($attributes) {
         $this->yyval = array($this->yyastk[$this->stackPos-(1-1)]); 
    }

    protected function yyn337($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ArrayItem($this->yyastk[$this->stackPos-(3-3)], $this->yyastk[$this->stackPos-(3-1)], false, $attributes); 
    }

    protected function yyn338($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ArrayItem($this->yyastk[$this->stackPos-(1-1)], null, false, $attributes); 
    }

    protected function yyn339($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn340($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn341($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn342($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn343($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ArrayDimFetch($this->yyastk[$this->stackPos-(6-2)], $this->yyastk[$this->stackPos-(6-5)], $attributes); 
    }

    protected function yyn344($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ArrayDimFetch($this->yyastk[$this->stackPos-(4-1)], $this->yyastk[$this->stackPos-(4-3)], $attributes); 
    }

    protected function yyn345($attributes) {
         $this->yyval = new PHPParser_Node_Expr_PropertyFetch($this->yyastk[$this->stackPos-(3-1)], $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn346($attributes) {
         $this->yyval = new PHPParser_Node_Expr_MethodCall($this->yyastk[$this->stackPos-(4-1)], $this->yyastk[$this->stackPos-(4-3)], $this->yyastk[$this->stackPos-(4-4)], $attributes); 
    }

    protected function yyn347($attributes) {
         $this->yyval = new PHPParser_Node_Expr_FuncCall($this->yyastk[$this->stackPos-(2-1)], $this->yyastk[$this->stackPos-(2-2)], $attributes); 
    }

    protected function yyn348($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ArrayDimFetch($this->yyastk[$this->stackPos-(4-1)], $this->yyastk[$this->stackPos-(4-3)], $attributes); 
    }

    protected function yyn349($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ArrayDimFetch($this->yyastk[$this->stackPos-(4-1)], $this->yyastk[$this->stackPos-(4-3)], $attributes); 
    }

    protected function yyn350($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn351($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(3-2)]; 
    }

    protected function yyn352($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn353($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Variable($this->yyastk[$this->stackPos-(2-2)], $attributes); 
    }

    protected function yyn354($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn355($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn356($attributes) {
         $this->yyval = new PHPParser_Node_Expr_StaticPropertyFetch($this->yyastk[$this->stackPos-(4-1)], $this->yyastk[$this->stackPos-(4-4)], $attributes); 
    }

    protected function yyn357($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn358($attributes) {
         $this->yyval = new PHPParser_Node_Expr_StaticPropertyFetch($this->yyastk[$this->stackPos-(3-1)], substr($this->yyastk[$this->stackPos-(3-3)], 1), $attributes); 
    }

    protected function yyn359($attributes) {
         $this->yyval = new PHPParser_Node_Expr_StaticPropertyFetch($this->yyastk[$this->stackPos-(6-1)], $this->yyastk[$this->stackPos-(6-5)], $attributes); 
    }

    protected function yyn360($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ArrayDimFetch($this->yyastk[$this->stackPos-(4-1)], $this->yyastk[$this->stackPos-(4-3)], $attributes); 
    }

    protected function yyn361($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ArrayDimFetch($this->yyastk[$this->stackPos-(4-1)], $this->yyastk[$this->stackPos-(4-3)], $attributes); 
    }

    protected function yyn362($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ArrayDimFetch($this->yyastk[$this->stackPos-(4-1)], $this->yyastk[$this->stackPos-(4-3)], $attributes); 
    }

    protected function yyn363($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ArrayDimFetch($this->yyastk[$this->stackPos-(4-1)], $this->yyastk[$this->stackPos-(4-3)], $attributes); 
    }

    protected function yyn364($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Variable(substr($this->yyastk[$this->stackPos-(1-1)], 1), $attributes); 
    }

    protected function yyn365($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Variable($this->yyastk[$this->stackPos-(4-3)], $attributes); 
    }

    protected function yyn366($attributes) {
         $this->yyval = null; 
    }

    protected function yyn367($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn368($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn369($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(3-2)]; 
    }

    protected function yyn370($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn371($attributes) {
         $this->yyval = new PHPParser_Node_Expr_List($this->yyastk[$this->stackPos-(4-3)], $attributes); 
    }

    protected function yyn372($attributes) {
         $this->yyastk[$this->stackPos-(3-1)][] = $this->yyastk[$this->stackPos-(3-3)]; $this->yyval = $this->yyastk[$this->stackPos-(3-1)]; 
    }

    protected function yyn373($attributes) {
         $this->yyval = array($this->yyastk[$this->stackPos-(1-1)]); 
    }

    protected function yyn374($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn375($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(1-1)]; 
    }

    protected function yyn376($attributes) {
         $this->yyval = null; 
    }

    protected function yyn377($attributes) {
         $this->yyval = array(); 
    }

    protected function yyn378($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(2-1)]; 
    }

    protected function yyn379($attributes) {
         $this->yyastk[$this->stackPos-(3-1)][] = $this->yyastk[$this->stackPos-(3-3)]; $this->yyval = $this->yyastk[$this->stackPos-(3-1)]; 
    }

    protected function yyn380($attributes) {
         $this->yyval = array($this->yyastk[$this->stackPos-(1-1)]); 
    }

    protected function yyn381($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ArrayItem($this->yyastk[$this->stackPos-(3-3)], $this->yyastk[$this->stackPos-(3-1)], false, $attributes); 
    }

    protected function yyn382($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ArrayItem($this->yyastk[$this->stackPos-(1-1)], null, false, $attributes); 
    }

    protected function yyn383($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ArrayItem($this->yyastk[$this->stackPos-(4-4)], $this->yyastk[$this->stackPos-(4-1)], true, $attributes); 
    }

    protected function yyn384($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ArrayItem($this->yyastk[$this->stackPos-(2-2)], null, true, $attributes); 
    }

    protected function yyn385($attributes) {
         $this->yyastk[$this->stackPos-(2-1)][] = $this->yyastk[$this->stackPos-(2-2)]; $this->yyval = $this->yyastk[$this->stackPos-(2-1)]; 
    }

    protected function yyn386($attributes) {
         $this->yyastk[$this->stackPos-(2-1)][] = $this->yyastk[$this->stackPos-(2-2)]; $this->yyval = $this->yyastk[$this->stackPos-(2-1)]; 
    }

    protected function yyn387($attributes) {
         $this->yyval = array($this->yyastk[$this->stackPos-(1-1)]); 
    }

    protected function yyn388($attributes) {
         $this->yyval = array($this->yyastk[$this->stackPos-(2-1)], $this->yyastk[$this->stackPos-(2-2)]); 
    }

    protected function yyn389($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Variable(substr($this->yyastk[$this->stackPos-(1-1)], 1), $attributes); 
    }

    protected function yyn390($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ArrayDimFetch(new PHPParser_Node_Expr_Variable(substr($this->yyastk[$this->stackPos-(4-1)], 1), $attributes), $this->yyastk[$this->stackPos-(4-3)], $attributes); 
    }

    protected function yyn391($attributes) {
         $this->yyval = new PHPParser_Node_Expr_PropertyFetch(new PHPParser_Node_Expr_Variable(substr($this->yyastk[$this->stackPos-(3-1)], 1), $attributes), $this->yyastk[$this->stackPos-(3-3)], $attributes); 
    }

    protected function yyn392($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Variable($this->yyastk[$this->stackPos-(3-2)], $attributes); 
    }

    protected function yyn393($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Variable($this->yyastk[$this->stackPos-(3-2)], $attributes); 
    }

    protected function yyn394($attributes) {
         $this->yyval = new PHPParser_Node_Expr_ArrayDimFetch(new PHPParser_Node_Expr_Variable($this->yyastk[$this->stackPos-(6-2)], $attributes), $this->yyastk[$this->stackPos-(6-4)], $attributes); 
    }

    protected function yyn395($attributes) {
         $this->yyval = $this->yyastk[$this->stackPos-(3-2)]; 
    }

    protected function yyn396($attributes) {
         $this->yyval = new PHPParser_Node_Scalar_String($this->yyastk[$this->stackPos-(1-1)], $attributes); 
    }

    protected function yyn397($attributes) {
         $this->yyval = new PHPParser_Node_Scalar_String($this->yyastk[$this->stackPos-(1-1)], $attributes); 
    }

    protected function yyn398($attributes) {
         $this->yyval = new PHPParser_Node_Expr_Variable(substr($this->yyastk[$this->stackPos-(1-1)], 1), $attributes); 
    }
}
<?php

abstract class PHPParser_PrettyPrinterAbstract
{
    protected $precedenceMap = array(
        // [precedence, associativity] where for the latter -1 is %left, 0 is %nonassoc and 1 is %right
        'Expr_BitwiseNot'       => array( 1,  1),
        'Expr_PreInc'           => array( 1,  1),
        'Expr_PreDec'           => array( 1,  1),
        'Expr_PostInc'          => array( 1, -1),
        'Expr_PostDec'          => array( 1, -1),
        'Expr_UnaryPlus'        => array( 1,  1),
        'Expr_UnaryMinus'       => array( 1,  1),
        'Expr_Cast_Int'         => array( 1,  1),
        'Expr_Cast_Double'      => array( 1,  1),
        'Expr_Cast_String'      => array( 1,  1),
        'Expr_Cast_Array'       => array( 1,  1),
        'Expr_Cast_Object'      => array( 1,  1),
        'Expr_Cast_Bool'        => array( 1,  1),
        'Expr_Cast_Unset'       => array( 1,  1),
        'Expr_ErrorSuppress'    => array( 1,  1),
        'Expr_Instanceof'       => array( 2,  0),
        'Expr_BooleanNot'       => array( 3,  1),
        'Expr_Mul'              => array( 4, -1),
        'Expr_Div'              => array( 4, -1),
        'Expr_Mod'              => array( 4, -1),
        'Expr_Plus'             => array( 5, -1),
        'Expr_Minus'            => array( 5, -1),
        'Expr_Concat'           => array( 5, -1),
        'Expr_ShiftLeft'        => array( 6, -1),
        'Expr_ShiftRight'       => array( 6, -1),
        'Expr_Smaller'          => array( 7,  0),
        'Expr_SmallerOrEqual'   => array( 7,  0),
        'Expr_Greater'          => array( 7,  0),
        'Expr_GreaterOrEqual'   => array( 7,  0),
        'Expr_Equal'            => array( 8,  0),
        'Expr_NotEqual'         => array( 8,  0),
        'Expr_Identical'        => array( 8,  0),
        'Expr_NotIdentical'     => array( 8,  0),
        'Expr_BitwiseAnd'       => array( 9, -1),
        'Expr_BitwiseXor'       => array(10, -1),
        'Expr_BitwiseOr'        => array(11, -1),
        'Expr_BooleanAnd'       => array(12, -1),
        'Expr_BooleanOr'        => array(13, -1),
        'Expr_Ternary'          => array(14, -1),
        // parser uses %left for assignments, but they really behave as %right
        'Expr_Assign'           => array(15,  1),
        'Expr_AssignRef'        => array(15,  1),
        'Expr_AssignPlus'       => array(15,  1),
        'Expr_AssignMinus'      => array(15,  1),
        'Expr_AssignMul'        => array(15,  1),
        'Expr_AssignDiv'        => array(15,  1),
        'Expr_AssignConcat'     => array(15,  1),
        'Expr_AssignMod'        => array(15,  1),
        'Expr_AssignBitwiseAnd' => array(15,  1),
        'Expr_AssignBitwiseOr'  => array(15,  1),
        'Expr_AssignBitwiseXor' => array(15,  1),
        'Expr_AssignShiftLeft'  => array(15,  1),
        'Expr_AssignShiftRight' => array(15,  1),
        'Expr_LogicalAnd'       => array(16, -1),
        'Expr_LogicalXor'       => array(17, -1),
        'Expr_LogicalOr'        => array(18, -1),
        'Expr_Include'          => array(19, -1),
    );

    protected $noIndentToken;
    protected $canUseSemicolonNamespaces;

    public function __construct() {
        $this->noIndentToken = '_NO_INDENT_' . mt_rand();
    }

    /**
     * Pretty prints an array of statements.
     *
     * @param PHPParser_Node[] $stmts Array of statements
     *
     * @return string Pretty printed statements
     */
    public function prettyPrint(array $stmts) {
        $this->preprocessNodes($stmts);

        return str_replace("\n" . $this->noIndentToken, "\n", $this->pStmts($stmts, false));
    }

    /**
     * Pretty prints an expression.
     *
     * @param PHPParser_Node_Expr $node Expression node
     *
     * @return string Pretty printed node
     */
    public function prettyPrintExpr(PHPParser_Node_Expr $node) {
        return str_replace("\n" . $this->noIndentToken, "\n", $this->p($node));
    }

    /**
     * Pretty prints a file of statements (includes the opening <?php tag if it is required).
     *
     * @param PHPParser_Node[] $stmts Array of statements
     *
     * @return string Pretty printed statements
     */
    public function prettyPrintFile(array $stmts) {
        $p = trim($this->prettyPrint($stmts));

        $p = preg_replace('/^\?>\n?/', '', $p, -1, $count);
        $p = preg_replace('/<\?php$/', '', $p);

        if (!$count) {
            $p = "<?php\n\n" . $p;
        }

        return $p;
    }

    /**
     * Preprocesses the top-level nodes to initialize pretty printer state.
     *
     * @param PHPParser_Node[] $nodes Array of nodes
     */
    protected function preprocessNodes(array $nodes) {
        /* We can use semicolon-namespaces unless there is a global namespace declaration */
        $this->canUseSemicolonNamespaces = true;
        foreach ($nodes as $node) {
            if ($node instanceof PHPParser_Node_Stmt_Namespace && null === $node->name) {
                $this->canUseSemicolonNamespaces = false;
            }
        }
    }

    /**
     * Pretty prints an array of nodes (statements) and indents them optionally.
     *
     * @param PHPParser_Node[] $nodes  Array of nodes
     * @param bool             $indent Whether to indent the printed nodes
     *
     * @return string Pretty printed statements
     */
    protected function pStmts(array $nodes, $indent = true) {
        $pNodes = array();
        foreach ($nodes as $node) {
            $pNodes[] = $this->pComments($node->getAttribute('comments', array()))
                      . $this->p($node)
                      . ($node instanceof PHPParser_Node_Expr ? ';' : '');
        }

        if ($indent) {
            return '    ' . preg_replace(
                '~\n(?!$|' . $this->noIndentToken . ')~',
                "\n" . '    ',
                implode("\n", $pNodes)
            );
        } else {
            return implode("\n", $pNodes);
        }
    }

    /**
     * Pretty prints a node.
     *
     * @param PHPParser_Node $node Node to be pretty printed
     *
     * @return string Pretty printed node
     */
    protected function p(PHPParser_Node $node) {
        return $this->{'p' . $node->getType()}($node);
    }

    protected function pInfixOp($type, PHPParser_Node $leftNode, $operatorString, PHPParser_Node $rightNode) {
        list($precedence, $associativity) = $this->precedenceMap[$type];

        return $this->pPrec($leftNode, $precedence, $associativity, -1)
             . $operatorString
             . $this->pPrec($rightNode, $precedence, $associativity, 1);
    }

    protected function pPrefixOp($type, $operatorString, PHPParser_Node $node) {
        list($precedence, $associativity) = $this->precedenceMap[$type];
        return $operatorString . $this->pPrec($node, $precedence, $associativity, 1);
    }

    protected function pPostfixOp($type, PHPParser_Node $node, $operatorString) {
        list($precedence, $associativity) = $this->precedenceMap[$type];
        return $this->pPrec($node, $precedence, $associativity, -1) . $operatorString;
    }

    /**
     * Prints an expression node with the least amount of parentheses necessary to preserve the meaning.
     *
     * @param PHPParser_Node $node                Node to pretty print
     * @param int            $parentPrecedence    Precedence of the parent operator
     * @param int            $parentAssociativity Associativity of parent operator
     *                                            (-1 is left, 0 is nonassoc, 1 is right)
     * @param int            $childPosition       Position of the node relative to the operator
     *                                            (-1 is left, 1 is right)
     *
     * @return string The pretty printed node
     */
    protected function pPrec(PHPParser_Node $node, $parentPrecedence, $parentAssociativity, $childPosition) {
        $type = $node->getType();
        if (isset($this->precedenceMap[$type])) {
            $childPrecedence = $this->precedenceMap[$type][0];
            if ($childPrecedence > $parentPrecedence
                || ($parentPrecedence == $childPrecedence && $parentAssociativity != $childPosition)
            ) {
                return '(' . $this->{'p' . $type}($node) . ')';
            }
        }

        return $this->{'p' . $type}($node);
    }

    /**
     * Pretty prints an array of nodes and implodes the printed values.
     *
     * @param PHPParser_Node[] $nodes Array of Nodes to be printed
     * @param string           $glue  Character to implode with
     *
     * @return string Imploded pretty printed nodes
     */
    protected function pImplode(array $nodes, $glue = '') {
        $pNodes = array();
        foreach ($nodes as $node) {
            $pNodes[] = $this->p($node);
        }

        return implode($glue, $pNodes);
    }

    /**
     * Pretty prints an array of nodes and implodes the printed values with commas.
     *
     * @param PHPParser_Node[] $nodes Array of Nodes to be printed
     *
     * @return string Comma separated pretty printed nodes
     */
    protected function pCommaSeparated(array $nodes) {
        return $this->pImplode($nodes, ', ');
    }

    /**
     * Signals the pretty printer that a string shall not be indented.
     *
     * @param string $string Not to be indented string
     *
     * @return mixed String marked with $this->noIndentToken's.
     */
    protected function pNoIndent($string) {
        return str_replace("\n", "\n" . $this->noIndentToken, $string);
    }

    protected function pComments(array $comments) {
        $result = '';

        foreach ($comments as $comment) {
            $result .= $comment->getReformattedText() . "\n";
        }

        return $result;
    }
}<?php

class PHPParser_Error extends RuntimeException
{
    protected $rawMessage;
    protected $rawLine;

    /**
     * Creates an Exception signifying a parse error.
     *
     * @param string $message Error message
     * @param int    $line    Error line in PHP file
     */
    public function __construct($message, $line = -1) {
        $this->rawMessage = (string) $message;
        $this->rawLine    = (int) $line;
        $this->updateMessage();
    }

    /**
     * Gets the error message
     *
     * @return string Error message
     */
    public function getRawMessage() {
        return $this->rawMessage;
    }

    /**
     * Sets the line of the PHP file the error occurred in.
     *
     * @param string $message Error message
     */
    public function setRawMessage($message) {
        $this->rawMessage = (string) $message;
        $this->updateMessage();
    }

    /**
     * Gets the error line in the PHP file.
     *
     * @return int Error line in the PHP file
     */
    public function getRawLine() {
        return $this->rawLine;
    }

    /**
     * Sets the line of the PHP file the error occurred in.
     *
     * @param int $line Error line in the PHP file
     */
    public function setRawLine($line) {
        $this->rawLine = (int) $line;
        $this->updateMessage();
    }

    /**
     * Updates the exception message after a change to rawMessage or rawLine.
     */
    protected function updateMessage() {
        $this->message = $this->rawMessage;

        if (-1 === $this->rawLine) {
            $this->message .= ' on unknown line';
        } else {
            $this->message .= ' on line ' . $this->rawLine;
        }
    }
}<?php

/**
 * @codeCoverageIgnore
 */
class PHPParser_Autoloader
{
    /**
    * Registers PHPParser_Autoloader as an SPL autoloader.
    */
    static public function register()
    {
        ini_set('unserialize_callback_func', 'spl_autoload_call');
        spl_autoload_register(array(__CLASS__, 'autoload'));
    }

    /**
    * Handles autoloading of classes.
    *
    * @param string $class A class name.
    */
    static public function autoload($class)
    {
        if (0 !== strpos($class, 'PHPParser')) {
            return;
        }

        $file = dirname(dirname(__FILE__)) . '/' . strtr($class, '_', '/') . '.php';
        if (is_file($file)) {
            require $file;
        }
    }
}<?php

interface PHPParser_Node
{
    /**
     * Gets the type of the node.
     *
     * @return string Type of the node
     */
    public function getType();

    /**
     * Gets the names of the sub nodes.
     *
     * @return array Names of sub nodes
     */
    public function getSubNodeNames();

    /**
     * Gets line the node started in.
     *
     * @return int Line
     */
    public function getLine();

    /**
     * Sets line the node started in.
     *
     * @param int $line Line
     */
    public function setLine($line);

    /**
     * Gets the doc comment of the node.
     *
     * The doc comment has to be the last comment associated with the node.
     *
     * @return null|PHPParser_Comment_Doc Doc comment object or null
     */
    public function getDocComment();

    /**
     * Sets an attribute on a node.
     *
     * @param string $key
     * @param mixed  $value
     */
    public function setAttribute($key, $value);

    /**
     * Returns whether an attribute exists.
     *
     * @param string $key
     *
     * @return bool
     */
    public function hasAttribute($key);

    /**
     * Returns the value of an attribute.
     *
     * @param string $key
     * @param mixed  $default
     *
     * @return mixed
     */
    public function &getAttribute($key, $default = null);

    /**
     * Returns all attributes for the given node.
     *
     * @return array
     */
    public function getAttributes();
}<?php

abstract class PHPParser_BuilderAbstract implements PHPParser_Builder {
    /**
     * Normalizes a node: Converts builder objects to nodes.
     *
     * @param PHPParser_Node|PHPParser_Builder $node The node to normalize
     *
     * @return PHPParser_Node The normalized node
     */
    protected function normalizeNode($node) {
        if ($node instanceof PHPParser_Builder) {
            return $node->getNode();
        } elseif ($node instanceof PHPParser_Node) {
            return $node;
        }

        throw new LogicException('Expected node or builder object');
    }

    /**
     * Normalizes a name: Converts plain string names to PHPParser_Node_Name.
     *
     * @param PHPParser_Node_Name|string $name The name to normalize
     *
     * @return PHPParser_Node_Name The normalized name
     */
    protected function normalizeName($name) {
        if ($name instanceof PHPParser_Node_Name) {
            return $name;
        } else {
            return new PHPParser_Node_Name($name);
        }
    }

    /**
     * Normalizes a value: Converts nulls, booleans, integers,
     * floats, strings and arrays into their respective nodes
     *
     * @param mixed $value The value to normalize
     *
     * @return PHPParser_Node_Expr The normalized value
     */
    protected function normalizeValue($value) {
        if ($value instanceof PHPParser_Node) {
            return $value;
        } elseif (is_null($value)) {
            return new PHPParser_Node_Expr_ConstFetch(
                new PHPParser_Node_Name('null')
            );
        } elseif (is_bool($value)) {
            return new PHPParser_Node_Expr_ConstFetch(
                new PHPParser_Node_Name($value ? 'true' : 'false')
            );
        } elseif (is_int($value)) {
            return new PHPParser_Node_Scalar_LNumber($value);
        } elseif (is_float($value)) {
            return new PHPParser_Node_Scalar_DNumber($value);
        } elseif (is_string($value)) {
            return new PHPParser_Node_Scalar_String($value);
        } elseif (is_array($value)) {
            $items = array();
            $lastKey = -1;
            foreach ($value as $itemKey => $itemValue) {
                // for consecutive, numeric keys don't generate keys
                if (null !== $lastKey && ++$lastKey === $itemKey) {
                    $items[] = new PHPParser_Node_Expr_ArrayItem(
                        $this->normalizeValue($itemValue)
                    );
                } else {
                    $lastKey = null;
                    $items[] = new PHPParser_Node_Expr_ArrayItem(
                        $this->normalizeValue($itemValue),
                        $this->normalizeValue($itemKey)
                    );
                }
            }

            return new PHPParser_Node_Expr_Array($items);
        } else {
            throw new LogicException('Invalid value');
        }
    }

    /**
     * Sets a modifier in the $this->type property.
     *
     * @param int $modifier Modifier to set
     */
    protected function setModifier($modifier) {
        PHPParser_Node_Stmt_Class::verifyModifier($this->type, $modifier);
        $this->type |= $modifier;
    }
}<?php

class PHPParser_Builder_Property extends PHPParser_BuilderAbstract
{
    protected $name;

    protected $type;
    protected $default;

    /**
     * Creates a property builder.
     *
     * @param string $name Name of the property
     */
    public function __construct($name) {
        $this->name = $name;

        $this->type = 0;
        $this->default = null;
    }

    /**
     * Makes the property public.
     *
     * @return PHPParser_Builder_Property The builder instance (for fluid interface)
     */
    public function makePublic() {
        $this->setModifier(PHPParser_Node_Stmt_Class::MODIFIER_PUBLIC);

        return $this;
    }

    /**
     * Makes the property protected.
     *
     * @return PHPParser_Builder_Property The builder instance (for fluid interface)
     */
    public function makeProtected() {
        $this->setModifier(PHPParser_Node_Stmt_Class::MODIFIER_PROTECTED);

        return $this;
    }

    /**
     * Makes the property private.
     *
     * @return PHPParser_Builder_Property The builder instance (for fluid interface)
     */
    public function makePrivate() {
        $this->setModifier(PHPParser_Node_Stmt_Class::MODIFIER_PRIVATE);

        return $this;
    }

    /**
     * Makes the property static.
     *
     * @return PHPParser_Builder_Property The builder instance (for fluid interface)
     */
    public function makeStatic() {
        $this->setModifier(PHPParser_Node_Stmt_Class::MODIFIER_STATIC);

        return $this;
    }

    /**
     * Sets default value for the property.
     *
     * @param mixed $value Default value to use
     *
     * @return PHPParser_Builder_Property The builder instance (for fluid interface)
     */
    public function setDefault($value) {
        $this->default = $this->normalizeValue($value);

        return $this;
    }

    /**
     * Returns the built class node.
     *
     * @return PHPParser_Node_Stmt_Property The built property node
     */
    public function getNode() {
        return new PHPParser_Node_Stmt_Property(
            $this->type !== 0 ? $this->type : PHPParser_Node_Stmt_Class::MODIFIER_PUBLIC,
            array(
                new PHPParser_Node_Stmt_PropertyProperty($this->name, $this->default)
            )
        );
    }
}<?php

class PHPParser_Builder_Class extends PHPParser_BuilderAbstract
{
    protected $name;

    protected $extends;
    protected $implements;
    protected $type;

    protected $uses;
    protected $constants;
    protected $properties;
    protected $methods;

    /**
     * Creates a class builder.
     *
     * @param string $name Name of the class
     */
    public function __construct($name) {
        $this->name = $name;

        $this->type = 0;
        $this->extends = null;
        $this->implements = array();

        $this->uses = $this->constants = $this->properties = $this->methods = array();
    }

    /**
     * Extends a class.
     *
     * @param PHPParser_Node_Name|string $class Name of class to extend
     *
     * @return PHPParser_Builder_Class The builder instance (for fluid interface)
     */
    public function extend($class) {
        $this->extends = $this->normalizeName($class);

        return $this;
    }

    /**
     * Implements one or more interfaces.
     *
     * @param PHPParser_Node_Name|string $interface Name of interface to implement
     * @param PHPParser_Node_Name|string $...       More interfaces to implement
     *
     * @return PHPParser_Builder_Class The builder instance (for fluid interface)
     */
    public function implement() {
        foreach (func_get_args() as $interface) {
            $this->implements[] = $this->normalizeName($interface);
        }

        return $this;
    }

    /**
     * Makes the class abstract.
     *
     * @return PHPParser_Builder_Class The builder instance (for fluid interface)
     */
    public function makeAbstract() {
        $this->setModifier(PHPParser_Node_Stmt_Class::MODIFIER_ABSTRACT);

        return $this;
    }

    /**
     * Makes the class final.
     *
     * @return PHPParser_Builder_Class The builder instance (for fluid interface)
     */
    public function makeFinal() {
        $this->setModifier(PHPParser_Node_Stmt_Class::MODIFIER_FINAL);

        return $this;
    }

    /**
     * Adds a statement.
     *
     * @param PHPParser_Node_Stmt|PHPParser_Builder $stmt The statement to add
     *
     * @return PHPParser_Builder_Class The builder instance (for fluid interface)
     */
    public function addStmt($stmt) {
        $stmt = $this->normalizeNode($stmt);

        $targets = array(
            'Stmt_TraitUse'    => &$this->uses,
            'Stmt_ClassConst'  => &$this->constants,
            'Stmt_Property'    => &$this->properties,
            'Stmt_ClassMethod' => &$this->methods,
        );

        $type = $stmt->getType();
        if (!isset($targets[$type])) {
            throw new LogicException(sprintf('Unexpected node of type "%s"', $type));
        }

        $targets[$type][] = $stmt;

        return $this;
    }

    /**
     * Adds multiple statements.
     *
     * @param array $stmts The statements to add
     *
     * @return PHPParser_Builder_Class The builder instance (for fluid interface)
     */
    public function addStmts(array $stmts) {
        foreach ($stmts as $stmt) {
            $this->addStmt($stmt);
        }

        return $this;
    }

    /**
     * Returns the built class node.
     *
     * @return PHPParser_Node_Stmt_Class The built class node
     */
    public function getNode() {
        return new PHPParser_Node_Stmt_Class($this->name, array(
            'type' => $this->type,
            'extends' => $this->extends,
            'implements' => $this->implements,
            'stmts' => array_merge($this->uses, $this->constants, $this->properties, $this->methods),
        ));
    }
}<?php

class PHPParser_Builder_Function extends PHPParser_BuilderAbstract
{
    protected $name;

    protected $returnByRef;
    protected $params;
    protected $stmts;

    /**
     * Creates a function builder.
     *
     * @param string $name Name of the function
     */
    public function __construct($name) {
        $this->name = $name;

        $this->returnByRef = false;
        $this->params = array();
        $this->stmts = array();
    }

    /**
     * Make the function return by reference.
     *
     * @return PHPParser_Builder_Function The builder instance (for fluid interface)
     */
    public function makeReturnByRef() {
        $this->returnByRef = true;

        return $this;
    }

    /**
     * Adds a parameter.
     *
     * @param PHPParser_Node_Param|PHPParser_Builder_Param $param The parameter to add
     *
     * @return PHPParser_Builder_Function The builder instance (for fluid interface)
     */
    public function addParam($param) {
        $param = $this->normalizeNode($param);

        if (!$param instanceof PHPParser_Node_Param) {
            throw new LogicException(sprintf('Expected parameter node, got "%s"', $param->getType()));
        }

        $this->params[] = $param;

        return $this;
    }

    /**
     * Adds multiple parameters.
     *
     * @param array $params The parameters to add
     *
     * @return PHPParser_Builder_Function The builder instance (for fluid interface)
     */
    public function addParams(array $params) {
        foreach ($params as $param) {
            $this->addParam($param);
        }

        return $this;
    }

    /**
     * Adds a statement.
     *
     * @param PHPParser_Node|PHPParser_Builder $stmt The statement to add
     *
     * @return PHPParser_Builder_Function The builder instance (for fluid interface)
     */
    public function addStmt($stmt) {
        $this->stmts[] = $this->normalizeNode($stmt);

        return $this;
    }

    /**
     * Adds multiple statements.
     *
     * @param array $stmts The statements to add
     *
     * @return PHPParser_Builder_Function The builder instance (for fluid interface)
     */
    public function addStmts(array $stmts) {
        foreach ($stmts as $stmt) {
            $this->addStmt($stmt);
        }

        return $this;
    }

    /**
     * Returns the built function node.
     *
     * @return PHPParser_Node_Stmt_Function The built function node
     */
    public function getNode() {
        return new PHPParser_Node_Stmt_Function($this->name, array(
            'byRef'  => $this->returnByRef,
            'params' => $this->params,
            'stmts'  => $this->stmts,
        ));
    }
}<?php

class PHPParser_Builder_Method extends PHPParser_BuilderAbstract
{
    protected $name;

    protected $type;
    protected $returnByRef;
    protected $params;
    protected $stmts;

    /**
     * Creates a method builder.
     *
     * @param string $name Name of the method
     */
    public function __construct($name) {
        $this->name = $name;

        $this->type = 0;
        $this->returnByRef = false;
        $this->params = array();
        $this->stmts = array();
    }

    /**
     * Makes the method public.
     *
     * @return PHPParser_Builder_Method The builder instance (for fluid interface)
     */
    public function makePublic() {
        $this->setModifier(PHPParser_Node_Stmt_Class::MODIFIER_PUBLIC);

        return $this;
    }

    /**
     * Makes the method protected.
     *
     * @return PHPParser_Builder_Method The builder instance (for fluid interface)
     */
    public function makeProtected() {
        $this->setModifier(PHPParser_Node_Stmt_Class::MODIFIER_PROTECTED);

        return $this;
    }

    /**
     * Makes the method private.
     *
     * @return PHPParser_Builder_Method The builder instance (for fluid interface)
     */
    public function makePrivate() {
        $this->setModifier(PHPParser_Node_Stmt_Class::MODIFIER_PRIVATE);

        return $this;
    }

    /**
     * Makes the method static.
     *
     * @return PHPParser_Builder_Method The builder instance (for fluid interface)
     */
    public function makeStatic() {
        $this->setModifier(PHPParser_Node_Stmt_Class::MODIFIER_STATIC);

        return $this;
    }

    /**
     * Makes the method abstract.
     *
     * @return PHPParser_Builder_Method The builder instance (for fluid interface)
     */
    public function makeAbstract() {
        if (!empty($this->stmts)) {
            throw new LogicException('Cannot make method with statements abstract');
        }

        $this->setModifier(PHPParser_Node_Stmt_Class::MODIFIER_ABSTRACT);
        $this->stmts = null; // abstract methods don't have statements

        return $this;
    }

    /**
     * Makes the method final.
     *
     * @return PHPParser_Builder_Method The builder instance (for fluid interface)
     */
    public function makeFinal() {
        $this->setModifier(PHPParser_Node_Stmt_Class::MODIFIER_FINAL);

        return $this;
    }

    /**
     * Make the method return by reference.
     *
     * @return PHPParser_Builder_Method The builder instance (for fluid interface)
     */
    public function makeReturnByRef() {
        $this->returnByRef = true;

        return $this;
    }

    /**
     * Adds a parameter.
     *
     * @param PHPParser_Node_Param|PHPParser_Builder_Param $param The parameter to add
     *
     * @return PHPParser_Builder_Method The builder instance (for fluid interface)
     */
    public function addParam($param) {
        $param = $this->normalizeNode($param);

        if (!$param instanceof PHPParser_Node_Param) {
            throw new LogicException(sprintf('Expected parameter node, got "%s"', $param->getType()));
        }

        $this->params[] = $param;

        return $this;
    }

    /**
     * Adds multiple parameters.
     *
     * @param array $params The parameters to add
     *
     * @return PHPParser_Builder_Method The builder instance (for fluid interface)
     */
    public function addParams(array $params) {
        foreach ($params as $param) {
            $this->addParam($param);
        }

        return $this;
    }

    /**
     * Adds a statement.
     *
     * @param PHPParser_Node|PHPParser_Builder $stmt The statement to add
     *
     * @return PHPParser_Builder_Method The builder instance (for fluid interface)
     */
    public function addStmt($stmt) {
        if (null === $this->stmts) {
            throw new LogicException('Cannot add statements to an abstract method');
        }

        $this->stmts[] = $this->normalizeNode($stmt);

        return $this;
    }

    /**
     * Adds multiple statements.
     *
     * @param array $stmts The statements to add
     *
     * @return PHPParser_Builder_Method The builder instance (for fluid interface)
     */
    public function addStmts(array $stmts) {
        foreach ($stmts as $stmt) {
            $this->addStmt($stmt);
        }

        return $this;
    }

    /**
     * Returns the built method node.
     *
     * @return PHPParser_Node_Stmt_ClassMethod The built method node
     */
    public function getNode() {
        return new PHPParser_Node_Stmt_ClassMethod($this->name, array(
            'type'   => $this->type !== 0 ? $this->type : PHPParser_Node_Stmt_Class::MODIFIER_PUBLIC,
            'byRef'  => $this->returnByRef,
            'params' => $this->params,
            'stmts'  => $this->stmts,
        ));
    }
}<?php

class PHPParser_Builder_Param extends PHPParser_BuilderAbstract
{
    protected $name;

    protected $default;
    protected $type;
    protected $byRef;

    /**
     * Creates a parameter builder.
     *
     * @param string $name Name of the parameter
     */
    public function __construct($name) {
        $this->name = $name;

        $this->default = null;
        $this->type = null;
        $this->byRef = false;
    }

    /**
     * Sets default value for the parameter.
     *
     * @param mixed $value Default value to use
     *
     * @return PHPParser_Builder_Param The builder instance (for fluid interface)
     */
    public function setDefault($value) {
        $this->default = $this->normalizeValue($value);

        return $this;
    }

    /**
     * Sets type hint for the parameter.
     *
     * @param string|PHPParser_Node_Name $type Type hint to use
     *
     * @return PHPParser_Builder_Param The builder instance (for fluid interface)
     */
    public function setTypeHint($type) {
        if ($type === 'array' || $type === 'callable') {
            $this->type = $type;
        } else {
            $this->type = $this->normalizeName($type);
        }

        return $this;
    }

    /**
     * Make the parameter accept the value by reference.
     *
     * @return PHPParser_Builder_Param The builder instance (for fluid interface)
     */
    public function makeByRef() {
        $this->byRef = true;

        return $this;
    }

    /**
     * Returns the built parameter node.
     *
     * @return PHPParser_Node_Param The built parameter node
     */
    public function getNode() {
        return new PHPParser_Node_Param(
            $this->name, $this->default, $this->type, $this->byRef
        );
    }
}<?php

class PHPParser_Builder_Interface extends PHPParser_BuilderAbstract
{
    protected $name;
    protected $extends;
    protected $constants;
    protected $methods;

    /**
     * Creates an interface builder.
     *
     * @param string $name Name of the interface
     */
    public function __construct($name) {
        $this->name = $name;
        $this->extends = array();
        $this->constants = $this->methods = array();
    }

    /**
     * Extends one or more interfaces.
     *
     * @param PHPParser_Node_Name|string $interface Name of interface to extend
     * @param PHPParser_Node_Name|string $...       More interfaces to extend
     *
     * @return PHPParser_Builder_Interface The builder instance (for fluid interface)
     */
    public function extend() {
        foreach (func_get_args() as $interface) {
            $this->extends[] = $this->normalizeName($interface);
        }

        return $this;
    }

    /**
     * Adds a statement.
     *
     * @param PHPParser_Node_Stmt|PHPParser_Builder $stmt The statement to add
     *
     * @return PHPParser_Builder_Interface The builder instance (for fluid interface)
     */
    public function addStmt($stmt) {
        $stmt = $this->normalizeNode($stmt);

        $type = $stmt->getType();
        switch ($type) {
            case 'Stmt_ClassConst':
                $this->constants[] = $stmt;
                break;

            case 'Stmt_ClassMethod':
                // we erase all statements in the body of an interface method
                $stmt->stmts = null;
                $this->methods[] = $stmt;
                break;

            default:
                throw new LogicException(sprintf('Unexpected node of type "%s"', $type));
        }

        return $this;
    }

    /**
     * Adds multiple statements.
     *
     * @param array $stmts The statements to add
     *
     * @return PHPParser_Builder_Class The builder instance (for fluid interface)
     */
    public function addStmts(array $stmts) {
        foreach ($stmts as $stmt) {
            $this->addStmt($stmt);
        }

        return $this;
    }

    /**
     * Returns the built class node.
     *
     * @return PHPParser_Node_Stmt_Interface The built interface node
     */
    public function getNode() {
        return new PHPParser_Node_Stmt_Interface($this->name, array(
            'extends' => $this->extends,
            'stmts' => array_merge($this->constants, $this->methods),
        ));
    }
}<?php

interface PHPParser_NodeTraverserInterface
{
    /**
     * Adds a visitor.
     *
     * @param PHPParser_NodeVisitor $visitor Visitor to add
     */
    function addVisitor(PHPParser_NodeVisitor $visitor);

    /**
     * Traverses an array of nodes using the registered visitors.
     *
     * @param PHPParser_Node[] $nodes Array of nodes
     *
     * @return PHPParser_Node[] Traversed array of nodes
     */
    function traverse(array $nodes);
}

<?php

class PHPParser_NodeVisitor_NameResolver extends PHPParser_NodeVisitorAbstract
{
    /**
     * @var null|PHPParser_Node_Name Current namespace
     */
    protected $namespace;

    /**
     * @var array Currently defined namespace and class aliases
     */
    protected $aliases;

    public function beforeTraverse(array $nodes) {
        $this->namespace = null;
        $this->aliases   = array();
    }

    public function enterNode(PHPParser_Node $node) {
        if ($node instanceof PHPParser_Node_Stmt_Namespace) {
            $this->namespace = $node->name;
            $this->aliases   = array();
        } elseif ($node instanceof PHPParser_Node_Stmt_UseUse) {
            if (isset($this->aliases[$node->alias])) {
                throw new PHPParser_Error(
                    sprintf(
                        'Cannot use "%s" as "%s" because the name is already in use',
                        $node->name, $node->alias
                    ),
                    $node->getLine()
                );
            }

            $this->aliases[$node->alias] = $node->name;
        } elseif ($node instanceof PHPParser_Node_Stmt_Class) {
            if (null !== $node->extends) {
                $node->extends = $this->resolveClassName($node->extends);
            }

            foreach ($node->implements as &$interface) {
                $interface = $this->resolveClassName($interface);
            }

            $this->addNamespacedName($node);
        } elseif ($node instanceof PHPParser_Node_Stmt_Interface) {
            foreach ($node->extends as &$interface) {
                $interface = $this->resolveClassName($interface);
            }

            $this->addNamespacedName($node);
        } elseif ($node instanceof PHPParser_Node_Stmt_Trait) {
            $this->addNamespacedName($node);
        } elseif ($node instanceof PHPParser_Node_Stmt_Function) {
            $this->addNamespacedName($node);
        } elseif ($node instanceof PHPParser_Node_Stmt_Const) {
            foreach ($node->consts as $const) {
                $this->addNamespacedName($const);
            }
        } elseif ($node instanceof PHPParser_Node_Expr_StaticCall
                  || $node instanceof PHPParser_Node_Expr_StaticPropertyFetch
                  || $node instanceof PHPParser_Node_Expr_ClassConstFetch
                  || $node instanceof PHPParser_Node_Expr_New
                  || $node instanceof PHPParser_Node_Expr_Instanceof
        ) {
            if ($node->class instanceof PHPParser_Node_Name) {
                $node->class = $this->resolveClassName($node->class);
            }
        } elseif ($node instanceof PHPParser_Node_Stmt_Catch) {
            $node->type = $this->resolveClassName($node->type);
        } elseif ($node instanceof PHPParser_Node_Expr_FuncCall
                  || $node instanceof PHPParser_Node_Expr_ConstFetch
        ) {
            if ($node->name instanceof PHPParser_Node_Name) {
                $node->name = $this->resolveOtherName($node->name);
            }
        } elseif ($node instanceof PHPParser_Node_Stmt_TraitUse) {
            foreach ($node->traits as &$trait) {
                $trait = $this->resolveClassName($trait);
            }
        } elseif ($node instanceof PHPParser_Node_Param
                  && $node->type instanceof PHPParser_Node_Name
        ) {
            $node->type = $this->resolveClassName($node->type);
        }
    }

    protected function resolveClassName(PHPParser_Node_Name $name) {
        // don't resolve special class names
        if (in_array((string) $name, array('self', 'parent', 'static'))) {
            return $name;
        }

        // fully qualified names are already resolved
        if ($name->isFullyQualified()) {
            return $name;
        }

        // resolve aliases (for non-relative names)
        if (!$name->isRelative() && isset($this->aliases[$name->getFirst()])) {
            $name->setFirst($this->aliases[$name->getFirst()]);
        // if no alias exists prepend current namespace
        } elseif (null !== $this->namespace) {
            $name->prepend($this->namespace);
        }

        return new PHPParser_Node_Name_FullyQualified($name->parts, $name->getAttributes());
    }

    protected function resolveOtherName(PHPParser_Node_Name $name) {
        // fully qualified names are already resolved and we can't do anything about unqualified
        // ones at compiler-time
        if ($name->isFullyQualified() || $name->isUnqualified()) {
            return $name;
        }

        // resolve aliases for qualified names
        if ($name->isQualified() && isset($this->aliases[$name->getFirst()])) {
            $name->setFirst($this->aliases[$name->getFirst()]);
        // prepend namespace for relative names
        } elseif (null !== $this->namespace) {
            $name->prepend($this->namespace);
        }

        return new PHPParser_Node_Name_FullyQualified($name->parts, $name->getAttributes());
    }

    protected function addNamespacedName(PHPParser_Node $node) {
        if (null !== $this->namespace) {
            $node->namespacedName = clone $this->namespace;
            $node->namespacedName->append($node->name);
        } else {
            $node->namespacedName = new PHPParser_Node_Name($node->name, $node->getAttributes());
        }
    }
}<?php

class PHPParser_Comment_Doc extends PHPParser_Comment
{
}<?php

/**
 * "class", "interface" and "function" are reserved keywords, so the methods are defined as _class(),
 * _interface() and _function() in the class and are made available as class(), interface() and function()
 * through __call() magic.
 *
 * @method PHPParser_Builder_Class     class(string $name)     Creates a class builder.
 * @method PHPParser_Builder_Function  function(string $name)  Creates a function builder
 * @method PHPParser_Builder_Interface interface(string $name) Creates an interface builder.
 */
class PHPParser_BuilderFactory
{
    /**
     * Creates a class builder.
     *
     * @param string $name Name of the class
     *
     * @return PHPParser_Builder_Class The created class builder
     */
    protected function _class($name) {
        return new PHPParser_Builder_Class($name);
    }

    /**
     * Creates a interface builder.
     *
     * @param string $name Name of the interface
     *
     * @return PHPParser_Builder_Class The created interface builder
     */
    protected function _interface($name) {
        return new PHPParser_Builder_Interface($name);
    }

    /**
     * Creates a method builder.
     *
     * @param string $name Name of the method
     *
     * @return PHPParser_Builder_Method The created method builder
     */
    public function method($name) {
        return new PHPParser_Builder_Method($name);
    }

    /**
     * Creates a parameter builder.
     *
     * @param string $name Name of the parameter
     *
     * @return PHPParser_Builder_Param The created parameter builder
     */
    public function param($name) {
        return new PHPParser_Builder_Param($name);
    }

    /**
     * Creates a property builder.
     *
     * @param string $name Name of the property
     *
     * @return PHPParser_Builder_Property The created property builder
     */
    public function property($name) {
        return new PHPParser_Builder_Property($name);
    }

    /**
     * Creates a function builder.
     *
     * @param string $name Name of the function
     *
     * @return PHPParser_Builder_Property The created function builder
     */
    protected function _function($name) {
        return new PHPParser_Builder_Function($name);
    }

    public function __call($name, array $args) {
        if (method_exists($this, '_' . $name)) {
            return call_user_func_array(array($this, '_' . $name), $args);
        }

        throw new LogicException(sprintf('Method "%s" does not exist', $name));
    }
}<?php

class PHPParser_NodeDumper
{
    /**
     * Dumps a node or array.
     *
     * @param array|PHPParser_Node $node Node or array to dump
     *
     * @return string Dumped value
     */
    public function dump($node) {
        if ($node instanceof PHPParser_Node) {
            $r = $node->getType() . '(';
        } elseif (is_array($node)) {
            $r = 'array(';
        } else {
            throw new InvalidArgumentException('Can only dump nodes and arrays.');
        }

        foreach ($node as $key => $value) {
            $r .= "\n" . '    ' . $key . ': ';

            if (null === $value) {
                $r .= 'null';
            } elseif (false === $value) {
                $r .= 'false';
            } elseif (true === $value) {
                $r .= 'true';
            } elseif (is_scalar($value)) {
                $r .= $value;
            } else {
                $r .= str_replace("\n", "\n" . '    ', $this->dump($value));
            }
        }

        return $r . "\n" . ')';
    }
}<?php

class PHPParser_Comment
{
    protected $text;
    protected $line;

    /**
     * Constructs a comment node.
     *
     * @param string $text Comment text (including comment delimiters like /*)
     * @param int    $line Line number the comment started on
     */
    public function __construct($text, $line = -1) {
        $this->text = $text;
        $this->line = $line;
    }

    /**
     * Gets the comment text.
     *
     * @return string The comment text (including comment delimiters like /*)
     */
    public function getText() {
        return $this->text;
    }

    /**
     * Sets the comment text.
     *
     * @param string $text The comment text (including comment delimiters like /*)
     */
    public function setText($text) {
        $this->text = $text;
    }

    /**
     * Gets the line number the comment started on.
     *
     * @return int Line number
     */
    public function getLine() {
        return $this->line;
    }

    /**
     * Sets the line number the comment started on.
     *
     * @param int $line Line number
     */
    public function setLine($line) {
        $this->line = $line;
    }

    /**
     * Gets the comment text.
     *
     * @return string The comment text (including comment delimiters like /*)
     */
    public function __toString() {
        return $this->text;
    }

    /**
     * Gets the reformatted comment text.
     *
     * "Reformatted" here means that we try to clean up the whitespace at the
     * starts of the lines. This is necessary because we receive the comments
     * without trailing whitespace on the first line, but with trailing whitespace
     * on all subsequent lines.
     *
     * @return mixed|string
     */
    public function getReformattedText() {
        $text = trim($this->text);
        if (false === strpos($text, "\n")) {
            // Single line comments don't need further processing
            return $text;
        } elseif (preg_match('((*BSR_ANYCRLF)(*ANYCRLF)^.*(?:\R\s+\*.*)+$)', $text)) {
            // Multi line comment of the type
            //
            //     /*
            //      * Some text.
            //      * Some more text.
            //      */
            //
            // is handled by replacing the whitespace sequences before the * by a single space
            return preg_replace('(^\s+\*)m', ' *', $this->text);
        } elseif (preg_match('(^/\*\*?\s*[\r\n])', $text) && preg_match('(\n(\s*)\*/$)', $text, $matches)) {
            // Multi line comment of the type
            //
            //    /*
            //        Some text.
            //        Some more text.
            //    */
            //
            // is handled by removing the whitespace sequence on the line before the closing
            // */ on all lines. So if the last line is "    */", then "    " is removed at the
            // start of all lines.
            return preg_replace('(^' . preg_quote($matches[1]) . ')m', '', $text);
        } elseif (preg_match('(^/\*\*?\s*(?!\s))', $text, $matches)) {
            // Multi line comment of the type
            //
            //     /* Some text.
            //        Some more text.
            //        Even more text. */
            //
            // is handled by taking the length of the "/* " segment and leaving only that
            // many space characters before the lines. Thus in the above example only three
            // space characters are left at the start of every line.
            return preg_replace('(^\s*(?= {' . strlen($matches[0]) . '}(?!\s)))m', '', $text);
        }

        // No idea how to format this comment, so simply return as is
        return $text;
    }
}<?php

interface PHPParser_Builder
{
    /**
     * Returns the built node.
     *
     * @return PHPParser_Node The built node
     */
    public function getNode();
}<?php

/**
 * @codeCoverageIgnore
 */
class PHPParser_NodeVisitorAbstract implements PHPParser_NodeVisitor
{
    public function beforeTraverse(array $nodes)    { }
    public function enterNode(PHPParser_Node $node) { }
    public function leaveNode(PHPParser_Node $node) { }
    public function afterTraverse(array $nodes)     { }
}<?php

class PHPParser_Template
{
    protected $parser;
    protected $template;

    /**
     * Creates a new code template from a template string.
     *
     * @param PHPParser_Parser $parser   A parser instance
     * @param string           $template The template string
     */
    public function __construct(PHPParser_Parser $parser, $template) {
        $this->parser   = $parser;
        $this->template = $template;
    }

    /**
     * Get the statements of the template with the passed in placeholders
     * replaced.
     *
     * @param array $placeholders Placeholders
     *
     * @return PHPParser_Node[] Statements
     */
    public function getStmts(array $placeholders) {
        return $this->parser->parse(
            $this->getTemplateWithPlaceholdersReplaced($placeholders)
        );
    }

    protected function getTemplateWithPlaceholdersReplaced(array $placeholders) {
        if (empty($placeholders)) {
            return $this->template;
        }

        return strtr($this->template, $this->preparePlaceholders($placeholders));
    }

    /*
     * Prepare the placeholders for replacement. This means that
     * a) all placeholders will be surrounded with __.
     * b) ucfirst/lcfirst variations of the placeholders are generated.
     *
     * E.g. for an input array of ['foo' => 'bar'] the result will be
     * ['__foo__' => 'bar', '__Foo__' => 'Bar'].
     */
    protected function preparePlaceholders(array $placeholders) {
        $preparedPlaceholders = array();

        foreach ($placeholders as $name => $value) {
            $preparedPlaceholders['__' . $name . '__'] = $value;

            if (ctype_lower($name[0])) {
                $ucfirstName = ucfirst($name);
                if (!isset($placeholders[$ucfirstName])) {
                    $preparedPlaceholders['__' . $ucfirstName . '__'] = ucfirst($value);
                }
            }

            if (ctype_upper($name[0])) {
                $lcfirstName = lcfirst($name);
                if (!isset($placeholders[$lcfirstName])) {
                    $preparedPlaceholders['__' . $lcfirstName . '__'] = lcfirst($value);
                }
            }
        }

        return $preparedPlaceholders;
    }
}<?php

abstract class PHPParser_NodeAbstract implements PHPParser_Node, IteratorAggregate
{
    protected $subNodes;
    protected $attributes;

    /**
     * Creates a Node.
     *
     * @param array $subNodes   Array of sub nodes
     * @param array $attributes Array of attributes
     */
    public function __construct(array $subNodes = array(), array $attributes = array()) {
        $this->subNodes   = $subNodes;
        $this->attributes = $attributes;
    }

    /**
     * Gets the type of the node.
     *
     * @return string Type of the node
     */
    public function getType() {
        return substr(get_class($this), 15);
    }

    /**
     * Gets the names of the sub nodes.
     *
     * @return array Names of sub nodes
     */
    public function getSubNodeNames() {
        return array_keys($this->subNodes);
    }

    /**
     * Gets line the node started in.
     *
     * @return int Line
     */
    public function getLine() {
        return $this->getAttribute('startLine', -1);
    }

    /**
     * Sets line the node started in.
     *
     * @param int $line Line
     */
    public function setLine($line) {
        $this->setAttribute('startLine', (int) $line);
    }

    /**
     * Gets the doc comment of the node.
     *
     * The doc comment has to be the last comment associated with the node.
     *
     * @return null|PHPParser_Comment_Doc Doc comment object or null
     */
    public function getDocComment() {
        $comments = $this->getAttribute('comments');
        if (!$comments) {
            return null;
        }

        $lastComment = $comments[count($comments) - 1];
        if (!$lastComment instanceof PHPParser_Comment_Doc) {
            return null;
        }

        return $lastComment;
    }

    /**
     * {@inheritDoc}
     */
    public function setAttribute($key, $value) {
        $this->attributes[$key] = $value;
    }

    /**
     * {@inheritDoc}
     */
    public function hasAttribute($key) {
        return array_key_exists($key, $this->attributes);
    }

    /**
     * {@inheritDoc}
     */
    public function &getAttribute($key, $default = null) {
        if (!array_key_exists($key, $this->attributes)) {
            return $default;
        } else {
            return $this->attributes[$key];
        }
    }

    /**
     * {@inheritDoc}
     */
    public function getAttributes() {
        return $this->attributes;
    }

    /* Magic interfaces */

    public function &__get($name) {
        return $this->subNodes[$name];
    }
    public function __set($name, $value) {
        $this->subNodes[$name] = $value;
    }
    public function __isset($name) {
        return isset($this->subNodes[$name]);
    }
    public function __unset($name) {
        unset($this->subNodes[$name]);
    }
    public function getIterator() {
        return new ArrayIterator($this->subNodes);
    }
}<?php

class PHPParser_Unserializer_XML implements PHPParser_Unserializer
{
    protected $reader;

    public function __construct() {
        $this->reader = new XMLReader;
    }

    public function unserialize($string) {
        $this->reader->XML($string);

        $this->reader->read();
        if ('AST' !== $this->reader->name) {
            throw new DomainException('AST root element not found');
        }

        return $this->read($this->reader->depth);
    }

    protected function read($depthLimit, $throw = true, &$nodeFound = null) {
        $nodeFound = true;
        while ($this->reader->read() && $depthLimit < $this->reader->depth) {
            if (XMLReader::ELEMENT !== $this->reader->nodeType) {
                continue;
            }

            if ('node' === $this->reader->prefix) {
                return $this->readNode();
            } elseif ('scalar' === $this->reader->prefix) {
                return $this->readScalar();
            } elseif ('comment' === $this->reader->name) {
                return $this->readComment();
            } else {
                throw new DomainException(sprintf('Unexpected node of type "%s"', $this->reader->name));
            }
        }

        $nodeFound = false;
        if ($throw) {
            throw new DomainException('Expected node or scalar');
        }
    }

    protected function readNode()
    {
        $className = 'PHPParser_Node_' . $this->reader->localName;

        // create the node without calling it's constructor
        $node = unserialize(
            sprintf(
                "O:%d:\"%s\":2:{s:11:\"\0*\0subNodes\";a:0:{}s:13:\"\0*\0attributes\";a:0:{}}",
                strlen($className), $className
            )
        );

        $depthLimit = $this->reader->depth;
        while ($this->reader->read() && $depthLimit < $this->reader->depth) {
            if (XMLReader::ELEMENT !== $this->reader->nodeType) {
                continue;
            }

            $type = $this->reader->prefix;
            if ('subNode' !== $type && 'attribute' !== $type) {
                throw new DomainException(
                    sprintf('Expected sub node or attribute, got node of type "%s"', $this->reader->name)
                );
            }

            $name = $this->reader->localName;
            $value = $this->read($this->reader->depth);

            if ('subNode' === $type) {
                $node->$name = $value;
            } else {
                $node->setAttribute($name, $value);
            }
        }

        return $node;
    }

    protected function readScalar() {
        switch ($name = $this->reader->localName) {
            case 'array':
                $depth = $this->reader->depth;
                $array = array();
                while (true) {
                    $node = $this->read($depth, false, $nodeFound);
                    if (!$nodeFound) {
                        break;
                    }
                    $array[] = $node;
                }
                return $array;
            case 'string':
                return $this->reader->readString();
            case 'int':
                $text = $this->reader->readString();
                if (false === $int = filter_var($text, FILTER_VALIDATE_INT)) {
                    throw new DomainException(sprintf('"%s" is not a valid integer', $text));
                }
                return $int;
            case 'float':
                $text = $this->reader->readString();
                if (false === $float = filter_var($text, FILTER_VALIDATE_FLOAT)) {
                    throw new DomainException(sprintf('"%s" is not a valid float', $text));
                }
                return $float;
            case 'true':
            case 'false':
            case 'null':
                if (!$this->reader->isEmptyElement) {
                    throw new DomainException(sprintf('"%s" scalar must be empty', $name));
                }
                return constant($name);
            default:
                throw new DomainException(sprintf('Unknown scalar type "%s"', $name));
        }
    }

    protected function readComment() {
        $className = $this->reader->getAttribute('isDocComment') === 'true'
            ? 'PHPParser_Comment_Doc'
            : 'PHPParser_Comment'
        ;
        return new $className(
            $this->reader->readString(),
            $this->reader->getAttribute('line')
        );
    }
}
<?php

interface PHPParser_Serializer
{
    /**
     * Serializes statements into some string format.
     *
     * @param array $nodes Statements
     *
     * @return string Serialized string
     */
    public function serialize(array $nodes);
}<?php

class PHPParser_NodeTraverser implements PHPParser_NodeTraverserInterface
{
    /**
     * @var PHPParser_NodeVisitor[] Visitors
     */
    protected $visitors;

    /**
     * Constructs a node traverser.
     */
    public function __construct() {
        $this->visitors = array();
    }

    /**
     * Adds a visitor.
     *
     * @param PHPParser_NodeVisitor $visitor Visitor to add
     */
    public function addVisitor(PHPParser_NodeVisitor $visitor) {
        $this->visitors[] = $visitor;
    }

    /**
     * Traverses an array of nodes using the registered visitors.
     *
     * @param PHPParser_Node[] $nodes Array of nodes
     *
     * @return PHPParser_Node[] Traversed array of nodes
     */
    public function traverse(array $nodes) {
        foreach ($this->visitors as $visitor) {
            if (null !== $return = $visitor->beforeTraverse($nodes)) {
                $nodes = $return;
            }
        }

        $nodes = $this->traverseArray($nodes);

        foreach ($this->visitors as $visitor) {
            if (null !== $return = $visitor->afterTraverse($nodes)) {
                $nodes = $return;
            }
        }

        return $nodes;
    }

    protected function traverseNode(PHPParser_Node $node) {
        $node = clone $node;

        foreach ($node->getSubNodeNames() as $name) {
            $subNode =& $node->$name;

            if (is_array($subNode)) {
                $subNode = $this->traverseArray($subNode);
            } elseif ($subNode instanceof PHPParser_Node) {
                foreach ($this->visitors as $visitor) {
                    if (null !== $return = $visitor->enterNode($subNode)) {
                        $subNode = $return;
                    }
                }

                $subNode = $this->traverseNode($subNode);

                foreach ($this->visitors as $visitor) {
                    if (null !== $return = $visitor->leaveNode($subNode)) {
                        $subNode = $return;
                    }
                }
            }
        }

        return $node;
    }

    protected function traverseArray(array $nodes) {
        $doNodes = array();

        foreach ($nodes as $i => &$node) {
            if (is_array($node)) {
                $node = $this->traverseArray($node);
            } elseif ($node instanceof PHPParser_Node) {
                foreach ($this->visitors as $visitor) {
                    if (null !== $return = $visitor->enterNode($node)) {
                        $node = $return;
                    }
                }

                $node = $this->traverseNode($node);

                foreach ($this->visitors as $visitor) {
                    $return = $visitor->leaveNode($node);

                    if (false === $return) {
                        $doNodes[] = array($i, array());
                        break;
                    } elseif (is_array($return)) {
                        $doNodes[] = array($i, $return);
                        break;
                    } elseif (null !== $return) {
                        $node = $return;
                    }
                }
            }
        }

        if (!empty($doNodes)) {
            while (list($i, $replace) = array_pop($doNodes)) {
                array_splice($nodes, $i, 1, $replace);
            }
        }

        return $nodes;
    }
}<?php

/**
 * ATTENTION: This code is WRITE-ONLY. Do not try to read it.
 */
class PHPParser_Lexer_Emulative extends PHPParser_Lexer
{
    protected $newKeywords;
    protected $inObjectAccess;

    public function __construct() {
        parent::__construct();

        $newKeywordsPerVersion = array(
            '5.5.0-dev' => array(
                'finally'       => PHPParser_Parser::T_FINALLY,
                'yield'         => PHPParser_Parser::T_YIELD,
            ),
            '5.4.0-dev' => array(
                'callable'      => PHPParser_Parser::T_CALLABLE,
                'insteadof'     => PHPParser_Parser::T_INSTEADOF,
                'trait'         => PHPParser_Parser::T_TRAIT,
                '__trait__'     => PHPParser_Parser::T_TRAIT_C,
            ),
            '5.3.0-dev' => array(
                '__dir__'       => PHPParser_Parser::T_DIR,
                'goto'          => PHPParser_Parser::T_GOTO,
                'namespace'     => PHPParser_Parser::T_NAMESPACE,
                '__namespace__' => PHPParser_Parser::T_NS_C,
            ),
        );

        $this->newKeywords = array();
        foreach ($newKeywordsPerVersion as $version => $newKeywords) {
            if (version_compare(PHP_VERSION, $version, '>=')) {
                break;
            }

            $this->newKeywords += $newKeywords;
        }
    }

    public function startLexing($code) {
        $this->inObjectAccess = false;

        // on PHP 5.4 don't do anything
        if (version_compare(PHP_VERSION, '5.4.0RC1', '>=')) {
            parent::startLexing($code);
        } else {
            $code = $this->preprocessCode($code);
            parent::startLexing($code);
            $this->postprocessTokens();
        }
    }

    /*
     * Replaces new features in the code by ~__EMU__{NAME}__{DATA}__~ sequences.
     * ~LABEL~ is never valid PHP code, that's why we can (to some degree) safely
     * use it here.
     * Later when preprocessing the tokens these sequences will either be replaced
     * by real tokens or replaced with their original content (e.g. if they occured
     * inside a string, i.e. a place where they don't have a special meaning).
     */
    protected function preprocessCode($code) {
        // binary notation (0b010101101001...)
        $code = preg_replace('(\b0b[01]+\b)', '~__EMU__BINARY__$0__~', $code);

        if (version_compare(PHP_VERSION, '5.3.0', '<')) {
            // namespace separator (backslash not followed by some special characters,
            // which are not valid after a NS separator, but would cause problems with
            // escape sequence parsing if one would replace the backslash there)
            $code = preg_replace('(\\\\(?!["\'`${\\\\]))', '~__EMU__NS__~', $code);

            // nowdoc (<<<'ABC'\ncontent\nABC;)
            $code = preg_replace_callback(
                '((*BSR_ANYCRLF)        # set \R to (?>\r\n|\r|\n)
                  (b?<<<[\t ]*\'([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\'\R) # opening token
                  ((?:(?!\2;?\R).*\R)*) # content
                  (\2)                  # closing token
                  (?=;?\R)              # must be followed by newline (with optional semicolon)
                 )x',
                array($this, 'encodeNowdocCallback'),
                $code
            );
        }

        return $code;
    }

    /*
     * As nowdocs can have arbitrary content but LABELs can only contain a certain
     * range of characters, the nowdoc content is encoded as hex and separated by
     * 'x' tokens. So the result of the encoding will look like this:
     * ~__EMU__NOWDOC__{HEX(START_TOKEN)}x{HEX(CONTENT)}x{HEX(END_TOKEN)}~
     */
    public function encodeNowdocCallback(array $matches) {
        return '~__EMU__NOWDOC__'
                . bin2hex($matches[1]) . 'x' . bin2hex($matches[3]) . 'x' . bin2hex($matches[4])
                . '__~';
    }

    /*
     * Replaces the ~__EMU__...~ sequences with real tokens or their original
     * value.
     */
    protected function postprocessTokens() {
        // we need to manually iterate and manage a count because we'll change
        // the tokens array on the way
        for ($i = 0, $c = count($this->tokens); $i < $c; ++$i) {
            // first check that the following tokens are form ~LABEL~,
            // then match the __EMU__... sequence.
            if ('~' === $this->tokens[$i]
                && isset($this->tokens[$i + 2])
                && '~' === $this->tokens[$i + 2]
                && T_STRING === $this->tokens[$i + 1][0]
                && preg_match('(^__EMU__([A-Z]++)__(?:([A-Za-z0-9]++)__)?$)', $this->tokens[$i + 1][1], $matches)
            ) {
                if ('BINARY' === $matches[1]) {
                    // the binary number can either be an integer or a double, so return a LNUMBER
                    // or DNUMBER respectively
                    $replace = array(
                        array(is_int(bindec($matches[2])) ? T_LNUMBER : T_DNUMBER, $matches[2], $this->tokens[$i + 1][2])
                    );
                } elseif ('NS' === $matches[1]) {
                    // a \ single char token is returned here and replaced by a
                    // PHPParser_Parser::T_NS_SEPARATOR token in ->getNextToken(). This hacks around
                    // the limitations arising from T_NS_SEPARATOR not being defined on 5.3
                    $replace = array('\\');
                } elseif ('NOWDOC' === $matches[1]) {
                    // decode the encoded nowdoc payload; pack('H*' is bin2hex( for 5.3
                    list($start, $content, $end) = explode('x', $matches[2]);
                    list($start, $content, $end) = array(pack('H*', $start), pack('H*', $content), pack('H*', $end));

                    $replace = array();
                    $replace[] = array(T_START_HEREDOC, $start, $this->tokens[$i + 1][2]);
                    if ('' !== $content) {
                        $replace[] = array(T_ENCAPSED_AND_WHITESPACE, $content, -1);
                    }
                    $replace[] = array(T_END_HEREDOC, $end, -1);
                } else {
                    // just ignore all other __EMU__ sequences
                    continue;
                }

                array_splice($this->tokens, $i, 3, $replace);
                $c -= 3 - count($replace);
            // for multichar tokens (e.g. strings) replace any ~__EMU__...~ sequences
            // in their content with the original character sequence
            } elseif (is_array($this->tokens[$i])
                      && 0 !== strpos($this->tokens[$i][1], '__EMU__')
            ) {
                $this->tokens[$i][1] = preg_replace_callback(
                    '(~__EMU__([A-Z]++)__(?:([A-Za-z0-9]++)__)?~)',
                    array($this, 'restoreContentCallback'),
                    $this->tokens[$i][1]
                );
            }
        }
    }

    /*
     * This method is a callback for restoring EMU sequences in
     * multichar tokens (like strings) to their original value.
     */
    public function restoreContentCallback(array $matches) {
        if ('BINARY' === $matches[1]) {
            return $matches[2];
        } elseif ('NS' === $matches[1]) {
            return '\\';
        } elseif ('NOWDOC' === $matches[1]) {
            list($start, $content, $end) = explode('x', $matches[2]);
            return pack('H*', $start) . pack('H*', $content) . pack('H*', $end);
        } else {
            return $matches[0];
        }
    }

    public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) {
        $token = parent::getNextToken($value, $startAttributes, $endAttributes);

        // replace new keywords by their respective tokens. This is not done
        // if we currently are in an object access (e.g. in $obj->namespace
        // "namespace" stays a T_STRING tokens and isn't converted to T_NAMESPACE)
        if (PHPParser_Parser::T_STRING === $token && !$this->inObjectAccess) {
            if (isset($this->newKeywords[strtolower($value)])) {
                return $this->newKeywords[strtolower($value)];
            }
        // backslashes are replaced by T_NS_SEPARATOR tokens
        } elseif (92 === $token) { // ord('\\')
            return PHPParser_Parser::T_NS_SEPARATOR;
        // keep track of whether we currently are in an object access (after ->)
        } elseif (PHPParser_Parser::T_OBJECT_OPERATOR === $token) {
            $this->inObjectAccess = true;
        } else {
            $this->inObjectAccess = false;
        }

        return $token;
    }
}<?php

/**
 * @property string              $name  Name
 * @property PHPParser_Node_Expr $value Value
 */
class PHPParser_Node_Const extends PHPParser_NodeAbstract
{
    /**
     * Constructs a const node for use in class const and const statements.
     *
     * @param string              $name       Name
     * @param PHPParser_Node_Expr $value      Value
     * @param array               $attributes Additional attributes
     */
    public function __construct($name, PHPParser_Node_Expr $value, array $attributes = array()) {
        parent::__construct(
            array(
                'name'  => $name,
                'value' => $value,
            ),
            $attributes
        );
    }
}<?php

abstract class PHPParser_Node_Stmt extends PHPParser_NodeAbstract
{
}<?php

/**
 * @property PHPParser_Node_Expr $value Value to pass
 * @property bool                $byRef Whether to pass by ref
 */
class PHPParser_Node_Arg extends PHPParser_NodeAbstract
{
    /**
     * Constructs a function call argument node.
     *
     * @param PHPParser_Node_Expr $value      Value to pass
     * @param bool                $byRef      Whether to pass by ref
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $value, $byRef = false, array $attributes = array()) {
        parent::__construct(
            array(
                'value' => $value,
                'byRef' => $byRef
            ),
            $attributes
        );
    }
}<?php

abstract class PHPParser_Node_Scalar extends PHPParser_Node_Expr
{
}<?php

/**
 * @property PHPParser_Node_Const[] $consts Constant declarations
 */
class PHPParser_Node_Stmt_Const extends PHPParser_Node_Stmt
{
    /**
     * Constructs a const list node.
     *
     * @param PHPParser_Node_Const[] $consts     Constant declarations
     * @param array                  $attributes Additional attributes
     */
    public function __construct(array $consts, array $attributes = array()) {
        parent::__construct(
            array(
                'consts' => $consts,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $cond  Condition
 * @property PHPParser_Node[]    $stmts Statements
 */
class PHPParser_Node_Stmt_ElseIf extends PHPParser_Node_Stmt
{
    /**
     * Constructs an elseif node.
     *
     * @param PHPParser_Node_Expr $cond       Condition
     * @param PHPParser_Node[]    $stmts      Statements
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $cond, array $stmts = array(), array $attributes = array()) {
        parent::__construct(
            array(
                'cond'  => $cond,
                'stmts' => $stmts,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property null|PHPParser_Node_Expr $num Number of loops to continue
 */
class PHPParser_Node_Stmt_Continue extends PHPParser_Node_Stmt
{
    /**
     * Constructs a continue node.
     *
     * @param null|PHPParser_Node_Expr $num        Number of loops to continue
     * @param array                    $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $num = null, array $attributes = array()) {
        parent::__construct(
            array(
                'num' => $num,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr[] $vars Variables
 */
class PHPParser_Node_Stmt_Global extends PHPParser_Node_Stmt
{
    /**
     * Constructs a global variables list node.
     *
     * @param PHPParser_Node_Expr[] $vars       Variables to unset
     * @param array                 $attributes Additional attributes
     */
    public function __construct(array $vars, array $attributes = array()) {
        parent::__construct(
            array(
                'vars' => $vars,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $cond  Condition
 * @property PHPParser_Node[]    $stmts Statements
 */
class PHPParser_Node_Stmt_While extends PHPParser_Node_Stmt
{
    /**
     * Constructs a while node.
     *
     * @param PHPParser_Node_Expr $cond       Condition
     * @param PHPParser_Node[]    $stmts      Statements
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $cond, array $stmts = array(), array $attributes = array()) {
        parent::__construct(
            array(
                'cond'  => $cond,
                'stmts' => $stmts,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property int                    $type   Type
 * @property bool                   $byRef  Whether to return by reference
 * @property string                 $name   Name
 * @property PHPParser_Node_Param[] $params Parameters
 * @property PHPParser_Node[]       $stmts  Statements
 */
class PHPParser_Node_Stmt_ClassMethod extends PHPParser_Node_Stmt
{

    /**
     * Constructs a class method node.
     *
     * @param string      $name       Name
     * @param array       $subNodes   Array of the following optional subnodes:
     *                                'type'   => MODIFIER_PUBLIC: Type
     *                                'byRef'  => false          : Whether to return by reference
     *                                'params' => array()        : Parameters
     *                                'stmts'  => array()        : Statements
     * @param array       $attributes Additional attributes
     */
    public function __construct($name, array $subNodes = array(), array $attributes = array()) {
        parent::__construct(
            $subNodes + array(
                'type'   => PHPParser_Node_Stmt_Class::MODIFIER_PUBLIC,
                'byRef'  => false,
                'params' => array(),
                'stmts'  => array(),
            ),
            $attributes
        );
        $this->name = $name;

        if (($this->type & PHPParser_Node_Stmt_Class::MODIFIER_STATIC)
            && ('__construct' == $this->name || '__destruct' == $this->name || '__clone' == $this->name)
        ) {
            throw new PHPParser_Error(sprintf('"%s" method cannot be static', $this->name));
        }
    }

    public function isPublic() {
        return (bool) ($this->type & PHPParser_Node_Stmt_Class::MODIFIER_PUBLIC);
    }

    public function isProtected() {
        return (bool) ($this->type & PHPParser_Node_Stmt_Class::MODIFIER_PROTECTED);
    }

    public function isPrivate() {
        return (bool) ($this->type & PHPParser_Node_Stmt_Class::MODIFIER_PRIVATE);
    }

    public function isAbstract() {
        return (bool) ($this->type & PHPParser_Node_Stmt_Class::MODIFIER_ABSTRACT);
    }

    public function isFinal() {
        return (bool) ($this->type & PHPParser_Node_Stmt_Class::MODIFIER_FINAL);
    }

    public function isStatic() {
        return (bool) ($this->type & PHPParser_Node_Stmt_Class::MODIFIER_STATIC);
    }
}<?php

/**
 * @property int                                    $type  Modifiers
 * @property PHPParser_Node_Stmt_PropertyProperty[] $props Properties
 */
class PHPParser_Node_Stmt_Property extends PHPParser_Node_Stmt
{
    /**
     * Constructs a class property list node.
     *
     * @param int                                    $type       Modifiers
     * @param PHPParser_Node_Stmt_PropertyProperty[] $props      Properties
     * @param array                                  $attributes Additional attributes
     */
    public function __construct($type, array $props, array $attributes = array()) {
        parent::__construct(
            array(
                'type'  => $type,
                'props' => $props,
            ),
            $attributes
        );
    }

    public function isPublic() {
        return (bool) ($this->type & PHPParser_Node_Stmt_Class::MODIFIER_PUBLIC);
    }

    public function isProtected() {
        return (bool) ($this->type & PHPParser_Node_Stmt_Class::MODIFIER_PROTECTED);
    }

    public function isPrivate() {
        return (bool) ($this->type & PHPParser_Node_Stmt_Class::MODIFIER_PRIVATE);
    }

    public function isStatic() {
        return (bool) ($this->type & PHPParser_Node_Stmt_Class::MODIFIER_STATIC);
    }
}<?php

/**
 * @property PHPParser_Node_Expr[] $exprs Expressions
 */
class PHPParser_Node_Stmt_Echo extends PHPParser_Node_Stmt
{
    /**
     * Constructs an echo node.
     *
     * @param PHPParser_Node_Expr[] $exprs      Expressions
     * @param array                 $attributes Additional attributes
     */
    public function __construct(array $exprs, array $attributes = array()) {
        parent::__construct(
            array(
                'exprs' => $exprs,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Name $name  Namespace/Class to alias
 * @property string              $alias Alias
 */
class PHPParser_Node_Stmt_UseUse extends PHPParser_Node_Stmt
{
    /**
     * Constructs an alias (use) node.
     *
     * @param PHPParser_Node_Name $name       Namespace/Class to alias
     * @param null|string         $alias      Alias
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Name $name, $alias = null, array $attributes = array()) {
        if (null === $alias) {
            $alias = $name->getLast();
        }

        if ('self' == $alias || 'parent' == $alias) {
            throw new PHPParser_Error(sprintf(
                'Cannot use "%s" as "%s" because "%2$s" is a special class name',
                $name, $alias
            ));
        }

        parent::__construct(
            array(
                'name'  => $name,
                'alias' => $alias,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Const[] $consts Constant declarations
 */
class PHPParser_Node_Stmt_ClassConst extends PHPParser_Node_Stmt
{
    /**
     * Constructs a class const list node.
     *
     * @param PHPParser_Node_Const[] $consts     Constant declarations
     * @param array                  $attributes Additional attributes
     */
    public function __construct(array $consts, array $attributes = array()) {
        parent::__construct(
            array(
                'consts' => $consts,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property string              $key   Key
 * @property PHPParser_Node_Expr $value Value
 */
class PHPParser_Node_Stmt_DeclareDeclare extends PHPParser_Node_Stmt
{
    /**
     * Constructs a declare key=>value pair node.
     *
     * @param string              $key        Key
     * @param PHPParser_Node_Expr $value      Value
     * @param array               $attributes Additional attributes
     */
    public function __construct($key, PHPParser_Node_Expr $value, array $attributes = array()) {
        parent::__construct(
            array(
                'key'   => $key,
                'value' => $value,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node[]            $stmts        Statements
 * @property PHPParser_Node_Stmt_Catch[] $catches      Catches
 * @property PHPParser_Node[]            $finallyStmts Finally statements
 */
class PHPParser_Node_Stmt_TryCatch extends PHPParser_Node_Stmt
{
    /**
     * Constructs a try catch node.
     *
     * @param PHPParser_Node[]            $stmts        Statements
     * @param PHPParser_Node_Stmt_Catch[] $catches      Catches
     * @param PHPParser_Node[]            $finallyStmts Finally statements (null means no finally clause)
     * @param array|null                  $attributes   Additional attributes
     */
    public function __construct(array $stmts, array $catches, array $finallyStmts = null, array $attributes = array()) {
        if (empty($catches) && null === $finallyStmts) {
            throw new PHPParser_Error('Cannot use try without catch or finally');
        }

        parent::__construct(
            array(
                'stmts'        => $stmts,
                'catches'      => $catches,
                'finallyStmts' => $finallyStmts,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr           $cond    Condition expression
 * @property PHPParser_Node[]              $stmts   Statements
 * @property PHPParser_Node_Stmt_ElseIf[]  $elseifs Elseif clauses
 * @property null|PHPParser_Node_Stmt_Else $else    Else clause
 */
class PHPParser_Node_Stmt_If extends PHPParser_Node_Stmt
{

    /**
     * Constructs an if node.
     *
     * @param PHPParser_Node_Expr $cond       Condition
     * @param array               $subNodes   Array of the following optional subnodes:
     *                                        'stmts'   => array(): Statements
     *                                        'elseifs' => array(): Elseif clauses
     *                                        'else'    => null   : Else clause
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $cond, array $subNodes = array(), array $attributes = array()) {
        parent::__construct(
            $subNodes + array(
                'stmts'   => array(),
                'elseifs' => array(),
                'else'    => null,
            ),
            $attributes
        );
        $this->cond = $cond;
    }
}<?php

/**
 * @property PHPParser_Node_Expr        $cond  Condition
 * @property PHPParser_Node_Stmt_Case[] $cases Case list
 */
class PHPParser_Node_Stmt_Switch extends PHPParser_Node_Stmt
{
    /**
     * Constructs a case node.
     *
     * @param PHPParser_Node_Expr        $cond       Condition
     * @param PHPParser_Node_Stmt_Case[] $cases      Case list
     * @param array                      $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $cond, array $cases, array $attributes = array()) {
        parent::__construct(
            array(
                'cond'  => $cond,
                'cases' => $cases,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property null|PHPParser_Node_Expr $cond  Condition (null for default)
 * @property PHPParser_Node[]         $stmts Statements
 */
class PHPParser_Node_Stmt_Case extends PHPParser_Node_Stmt
{
    /**
     * Constructs a case node.
     *
     * @param null|PHPParser_Node_Expr $cond       Condition (null for default)
     * @param PHPParser_Node[]         $stmts      Statements
     * @param array                    $attributes Additional attributes
     */
    public function __construct($cond, array $stmts = array(), array $attributes = array()) {
        parent::__construct(
            array(
                'cond'  => $cond,
                'stmts' => $stmts,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Name[]                    $traits      Traits
 * @property PHPParser_Node_Stmt_TraitUseAdaptation[] $adaptations Adaptations
 */
class PHPParser_Node_Stmt_TraitUse extends PHPParser_Node_Stmt
{
    /**
     * Constructs a trait use node.
     *
     * @param PHPParser_Node_Name[]                    $traits      Traits
     * @param PHPParser_Node_Stmt_TraitUseAdaptation[] $adaptations Adaptations
     * @param array                                    $attributes  Additional attributes
     */
    public function __construct(array $traits, array $adaptations = array(), array $attributes = array()) {
        parent::__construct(
            array(
                'traits'      => $traits,
                'adaptations' => $adaptations,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property string $value String
 */
class PHPParser_Node_Stmt_InlineHTML extends PHPParser_Node_Stmt
{
    /**
     * Constructs an inline HTML node.
     *
     * @param string $value      String
     * @param array  $attributes Additional attributes
     */
    public function __construct($value, array $attributes = array()) {
        parent::__construct(
            array(
                'value' => $value,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property null|PHPParser_Node_Name $name  Name
 * @property PHPParser_Node[]         $stmts Statements
 */
class PHPParser_Node_Stmt_Namespace extends PHPParser_Node_Stmt
{
    protected static $specialNames = array(
        'self'   => true,
        'parent' => true,
        'static' => true,
    );

    /**
     * Constructs a namespace node.
     *
     * @param null|PHPParser_Node_Name $name       Name
     * @param PHPParser_Node[]         $stmts      Statements
     * @param array                    $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Name $name = null, $stmts = array(), array $attributes = array()) {
        parent::__construct(
            array(
                'name'  => $name,
                'stmts' => $stmts,
            ),
            $attributes
        );

        if (isset(self::$specialNames[(string) $this->name])) {
            throw new PHPParser_Error(sprintf('Cannot use "%s" as namespace name as it is reserved', $this->name));
        }

        if (null !== $this->stmts) {
            foreach ($this->stmts as $stmt) {
                if ($stmt instanceof PHPParser_Node_Stmt_Namespace) {
                    throw new PHPParser_Error('Namespace declarations cannot be nested', $stmt->getLine());
                }
            }
        }
    }

    public static function postprocess(array $stmts) {
        // null = not in namespace, false = semicolon style, true = bracket style
        $bracketed = null;

        // whether any statements that aren't allowed before a namespace declaration are encountered
        // (the only valid statement currently is a declare)
        $hasNotAllowedStmts = false;

        // offsets for semicolon style namespaces
        // (required for transplanting the following statements into their ->stmts property)
        $nsOffsets = array();

        foreach ($stmts as $i => $stmt) {
            if ($stmt instanceof PHPParser_Node_Stmt_Namespace) {
                // ->stmts is null if semicolon style is used
                $currentBracketed = null !== $stmt->stmts;

                // if no namespace statement has been encountered yet
                if (!isset($bracketed)) {
                    // set the namespacing style
                    $bracketed = $currentBracketed;

                    // and ensure that it isn't preceded by a not allowed statement
                    if ($hasNotAllowedStmts) {
                        throw new PHPParser_Error('Namespace declaration statement has to be the very first statement in the script', $stmt->getLine());
                    }
                // otherwise ensure that the style of the current namespace matches the style of
                // namespaceing used before in this document
                } elseif ($bracketed !== $currentBracketed) {
                    throw new PHPParser_Error('Cannot mix bracketed namespace declarations with unbracketed namespace declarations', $stmt->getLine());
                }

                // for semicolon style namespaces remember the offset
                if (!$bracketed) {
                    $nsOffsets[] = $i;
                }
            // declare() and __halt_compiler() are the only valid statements outside of namespace declarations
            } elseif (!$stmt instanceof PHPParser_Node_Stmt_Declare
                      && !$stmt instanceof PHPParser_Node_Stmt_HaltCompiler
            ) {
                if (true === $bracketed) {
                    throw new PHPParser_Error('No code may exist outside of namespace {}', $stmt->getLine());
                }

                $hasNotAllowedStmts = true;
            }
        }

        // if bracketed namespaces were used or no namespaces were used at all just return the
        // original statements
        if (!isset($bracketed) || true === $bracketed) {
            return $stmts;
        // for semicolon style transplant statements
        } else {
            // take all statements preceding the first namespace
            $newStmts = array_slice($stmts, 0, $nsOffsets[0]);

            // iterate over all following namespaces
            for ($i = 0, $c = count($nsOffsets); $i < $c; ++$i) {
                $newStmts[] = $nsStmt = $stmts[$nsOffsets[$i]];

                // the last namespace takes all statements after it
                if ($c === $i + 1) {
                    $nsStmt->stmts = array_slice($stmts, $nsOffsets[$i] + 1);

                    // if the last statement is __halt_compiler() put it outside the namespace
                    if (end($nsStmt->stmts) instanceof PHPParser_Node_Stmt_HaltCompiler) {
                        $newStmts[] = array_pop($nsStmt->stmts);
                    }
                // and all the others take all statements between the current and the following one
                } else {
                    $nsStmt->stmts = array_slice($stmts, $nsOffsets[$i] + 1, $nsOffsets[$i + 1] - $nsOffsets[$i] - 1);
                }
            }

            return $newStmts;
        }
    }
}<?php

/**
 * @property PHPParser_Node_Stmt_UseUse[] $uses Aliases
 */
class PHPParser_Node_Stmt_Use extends PHPParser_Node_Stmt
{
    /**
     * Constructs an alias (use) list node.
     *
     * @param PHPParser_Node_Stmt_UseUse[] $uses       Aliases
     * @param array                        $attributes Additional attributes
     */
    public function __construct(array $uses, array $attributes = array()) {
        parent::__construct(
            array(
                'uses' => $uses,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property null|PHPParser_Node_Expr $num Number of loops to break
 */
class PHPParser_Node_Stmt_Break extends PHPParser_Node_Stmt
{
    /**
     * Constructs a break node.
     *
     * @param null|PHPParser_Node_Expr $num        Number of loops to break
     * @param array                    $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $num = null, array $attributes = array()) {
        parent::__construct(
            array(
                'num' => $num,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr[] $init  Init expressions
 * @property PHPParser_Node_Expr[] $cond  Loop conditions
 * @property PHPParser_Node_Expr[] $loop  Loop expressions
 * @property PHPParser_Node[]      $stmts Statements
 */
class PHPParser_Node_Stmt_For extends PHPParser_Node_Stmt
{
    /**
     * Constructs a for loop node.
     *
     * @param array $subNodes   Array of the following optional subnodes:
     *                          'init'  => array(): Init expressions
     *                          'cond'  => array(): Loop conditions
     *                          'loop'  => array(): Loop expressions
     *                          'stmts' => array(): Statements
     * @param array $attributes Additional attributes
     */
    public function __construct(array $subNodes = array(), array $attributes = array()) {
        parent::__construct(
            $subNodes + array(
                'init'  => array(),
                'cond'  => array(),
                'loop'  => array(),
                'stmts' => array(),
            ),
            $attributes
        );
    }
}<?php

/**
 * @property string $name Name
 */
class PHPParser_Node_Stmt_Label extends PHPParser_Node_Stmt
{
    /**
     * Constructs a label node.
     *
     * @param string $name       Name
     * @param array  $attributes Additional attributes
     */
    public function __construct($name, array $attributes = array()) {
        parent::__construct(
            array(
                'name' => $name,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node[] $stmts Statements
 */
class PHPParser_Node_Stmt_Else extends PHPParser_Node_Stmt
{
    /**
     * Constructs an else node.
     *
     * @param PHPParser_Node[] $stmts      Statements
     * @param array            $attributes Additional attributes
     */
    public function __construct(array $stmts = array(), array $attributes = array()) {
        parent::__construct(
            array(
                'stmts' => $stmts,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr      $expr     Expression to iterate
 * @property null|PHPParser_Node_Expr $keyVar   Variable to assign key to
 * @property bool                     $byRef    Whether to assign value by reference
 * @property PHPParser_Node_Expr      $valueVar Variable to assign value to
 * @property PHPParser_Node[]         $stmts    Statements
 */
class PHPParser_Node_Stmt_Foreach extends PHPParser_Node_Stmt
{
    /**
     * Constructs a foreach node.
     *
     * @param PHPParser_Node_Expr $expr       Expression to iterate
     * @param PHPParser_Node_Expr $valueVar   Variable to assign value to
     * @param array               $subNodes   Array of the following optional subnodes:
     *                                        'keyVar' => null   : Variable to assign key to
     *                                        'byRef'  => false  : Whether to assign value by reference
     *                                        'stmts'  => array(): Statements
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $expr, PHPParser_Node_Expr $valueVar, array $subNodes = array(), array $attributes = array()) {
        parent::__construct(
            $subNodes + array(
                'keyVar' => null,
                'byRef'  => false,
                'stmts'  => array(),
            ),
            $attributes
        );
        $this->expr     = $expr;
        $this->valueVar = $valueVar;
    }
}<?php

/**
 * @property null|PHPParser_Node_Name $trait       Trait name
 * @property string                   $method      Method name
 * @property null|int                 $newModifier New modifier
 * @property null|string              $newName     New name
 */
class PHPParser_Node_Stmt_TraitUseAdaptation_Alias extends PHPParser_Node_Stmt_TraitUseAdaptation
{
    /**
     * Constructs a trait use precedence adaptation node.
     *
     * @param null|PHPParser_Node_Name $trait       Trait name
     * @param string                   $method      Method name
     * @param null|int                 $newModifier New modifier
     * @param null|string              $newName     New name
     * @param array                    $attributes  Additional attributes
     */
    public function __construct($trait, $method, $newModifier, $newName, array $attributes = array()) {
        parent::__construct(
            array(
                'trait'       => $trait,
                'method'      => $method,
                'newModifier' => $newModifier,
                'newName'     => $newName,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Name   $trait     Trait name
 * @property string                $method    Method name
 * @property PHPParser_Node_Name[] $insteadof Overwritten traits
 */
class PHPParser_Node_Stmt_TraitUseAdaptation_Precedence extends PHPParser_Node_Stmt_TraitUseAdaptation
{
    /**
     * Constructs a trait use precedence adaptation node.
     *
     * @param PHPParser_Node_Name   $trait       Trait name
     * @param string                $method      Method name
     * @param PHPParser_Node_Name[] $insteadof   Overwritten traits
     * @param array                 $attributes  Additional attributes
     */
    public function __construct(PHPParser_Node_Name $trait, $method, array $insteadof, array $attributes = array()) {
        parent::__construct(
            array(
                'trait'     => $trait,
                'method'    => $method,
                'insteadof' => $insteadof,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property int                      $type       Type
 * @property string                   $name       Name
 * @property null|PHPParser_Node_Name $extends    Name of extended class
 * @property PHPParser_Node_Name[]    $implements Names of implemented interfaces
 * @property PHPParser_Node[]         $stmts      Statements
 */
class PHPParser_Node_Stmt_Class extends PHPParser_Node_Stmt
{
    const MODIFIER_PUBLIC    =  1;
    const MODIFIER_PROTECTED =  2;
    const MODIFIER_PRIVATE   =  4;
    const MODIFIER_STATIC    =  8;
    const MODIFIER_ABSTRACT  = 16;
    const MODIFIER_FINAL     = 32;

    protected static $specialNames = array(
        'self'   => true,
        'parent' => true,
        'static' => true,
    );

    /**
     * Constructs a class node.
     *
     * @param string      $name       Name
     * @param array       $subNodes   Array of the following optional subnodes:
     *                                'type'       => 0      : Type
     *                                'extends'    => null   : Name of extended class
     *                                'implements' => array(): Names of implemented interfaces
     *                                'stmts'      => array(): Statements
     * @param array       $attributes Additional attributes
     */
    public function __construct($name, array $subNodes = array(), array $attributes = array()) {
        parent::__construct(
            $subNodes + array(
                'type'       => 0,
                'extends'    => null,
                'implements' => array(),
                'stmts'      => array(),
            ),
            $attributes
        );
        $this->name = $name;

        if (isset(self::$specialNames[(string) $this->name])) {
            throw new PHPParser_Error(sprintf('Cannot use "%s" as class name as it is reserved', $this->name));
        }

        if (isset(self::$specialNames[(string) $this->extends])) {
            throw new PHPParser_Error(sprintf('Cannot use "%s" as class name as it is reserved', $this->extends));
        }

        foreach ($this->implements as $interface) {
            if (isset(self::$specialNames[(string) $interface])) {
                throw new PHPParser_Error(sprintf('Cannot use "%s" as interface name as it is reserved', $interface));
            }
        }
    }

    public function isAbstract() {
        return (bool) ($this->type & self::MODIFIER_ABSTRACT);
    }

    public function isFinal() {
        return (bool) ($this->type & self::MODIFIER_FINAL);
    }

    public function getMethods() {
        $methods = array();
        foreach ($this->stmts as $stmt) {
            if ($stmt instanceof PHPParser_Node_Stmt_ClassMethod) {
                $methods[] = $stmt;
            }
        }
        return $methods;
    }

    public static function verifyModifier($a, $b) {
        if ($a & 7 && $b & 7) {
            throw new PHPParser_Error('Multiple access type modifiers are not allowed');
        }

        if ($a & self::MODIFIER_ABSTRACT && $b & self::MODIFIER_ABSTRACT) {
            throw new PHPParser_Error('Multiple abstract modifiers are not allowed');
        }

        if ($a & self::MODIFIER_STATIC && $b & self::MODIFIER_STATIC) {
            throw new PHPParser_Error('Multiple static modifiers are not allowed');
        }

        if ($a & self::MODIFIER_FINAL && $b & self::MODIFIER_FINAL) {
            throw new PHPParser_Error('Multiple final modifiers are not allowed');
        }

        if ($a & 48 && $b & 48) {
            throw new PHPParser_Error('Cannot use the final and abstract modifier at the same time');
        }
    }
}<?php

/**
 * @property bool                   $byRef  Whether returns by reference
 * @property string                 $name   Name
 * @property PHPParser_Node_Param[] $params Parameters
 * @property PHPParser_Node[]       $stmts  Statements
 */
class PHPParser_Node_Stmt_Function extends PHPParser_Node_Stmt
{
    /**
     * Constructs a function node.
     *
     * @param string $name       Name
     * @param array  $subNodes   Array of the following optional subnodes:
     *                           'byRef'  => false  : Whether to return by reference
     *                           'params' => array(): Parameters
     *                           'stmts'  => array(): Statements
     * @param array  $attributes Additional attributes
     */
    public function __construct($name, array $subNodes = array(), array $attributes = array()) {
        parent::__construct(
            $subNodes + array(
                'byRef'  => false,
                'params' => array(),
                'stmts'  => array(),
            ),
            $attributes
        );
        $this->name = $name;
    }
}<?php

/**
 * @property string $name Name of label to jump to
 */
class PHPParser_Node_Stmt_Goto extends PHPParser_Node_Stmt
{
    /**
     * Constructs a goto node.
     *
     * @param string $name       Name of label to jump to
     * @param array  $attributes Additional attributes
     */
    public function __construct($name, array $attributes = array()) {
        parent::__construct(
            array(
                'name' => $name,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $expr Expression
 */
class PHPParser_Node_Stmt_Throw extends PHPParser_Node_Stmt
{
    /**
     * Constructs a throw node.
     *
     * @param PHPParser_Node_Expr $expr       Expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $expr, array $attributes = array()) {
        parent::__construct(
            array(
                'expr' => $expr,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $cond  Condition
 * @property PHPParser_Node[]    $stmts Statements
 */
class PHPParser_Node_Stmt_Do extends PHPParser_Node_Stmt
{
    /**
     * Constructs a do while node.
     *
     * @param PHPParser_Node_Expr $cond       Condition
     * @param PHPParser_Node[]    $stmts      Statements
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $cond, array $stmts = array(), array $attributes = array()) {
        parent::__construct(
            array(
                'cond'  => $cond,
                'stmts' => $stmts,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Name $type  Class of exception
 * @property string              $var   Variable for exception
 * @property PHPParser_Node[]    $stmts Statements
 */
class PHPParser_Node_Stmt_Catch extends PHPParser_Node_Stmt
{
    /**
     * Constructs a catch node.
     *
     * @param PHPParser_Node_Name $type       Class of exception
     * @param string              $var        Variable for exception
     * @param PHPParser_Node[]    $stmts      Statements
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Name $type, $var, array $stmts = array(), array $attributes = array()) {
        parent::__construct(
            array(
                'type'  => $type,
                'var'   => $var,
                'stmts' => $stmts,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property string                   $name    Name
 * @property null|PHPParser_Node_Expr $default Default value
 */
class PHPParser_Node_Stmt_StaticVar extends PHPParser_Node_Stmt
{
    /**
     * Constructs a static variable node.
     *
     * @param string                   $name       Name
     * @param null|PHPParser_Node_Expr $default    Default value
     * @param array                    $attributes Additional attributes
     */
    public function __construct($name, PHPParser_Node_Expr $default = null, array $attributes = array()) {
        parent::__construct(
            array(
                'name'    => $name,
                'default' => $default,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property string                   $name    Name
 * @property null|PHPParser_Node_Expr $default Default
 */
class PHPParser_Node_Stmt_PropertyProperty extends PHPParser_Node_Stmt
{
    /**
     * Constructs a class property node.
     *
     * @param string                   $name       Name
     * @param null|PHPParser_Node_Expr $default    Default value
     * @param array                    $attributes Additional attributes
     */
    public function __construct($name, PHPParser_Node_Expr $default = null, array $attributes = array()) {
        parent::__construct(
            array(
                'name'    => $name,
                'default' => $default,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Stmt_StaticVar[] $vars Variable definitions
 */
class PHPParser_Node_Stmt_Static extends PHPParser_Node_Stmt
{
    /**
     * Constructs a static variables list node.
     *
     * @param PHPParser_Node_Stmt_StaticVar[] $vars       Variable definitions
     * @param array                           $attributes Additional attributes
     */
    public function __construct(array $vars, array $attributes = array()) {
        parent::__construct(
            array(
                'vars' => $vars,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property string $remaining Remaining text after halt compiler statement.
 */
class PHPParser_Node_Stmt_HaltCompiler extends PHPParser_Node_Stmt
{
    /**
     * Constructs a __halt_compiler node.
     *
     * @param string $remaining  Remaining text after halt compiler statement.
     * @param array  $attributes Additional attributes
     */
    public function __construct($remaining, array $attributes = array()) {
        parent::__construct(
            array(
                'remaining' => $remaining,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr[] $vars Variables to unset
 */
class PHPParser_Node_Stmt_Unset extends PHPParser_Node_Stmt
{
    /**
     * Constructs an unset node.
     *
     * @param PHPParser_Node_Expr[] $vars       Variables to unset
     * @param array                 $attributes Additional attributes
     */
    public function __construct(array $vars, array $attributes = array()) {
        parent::__construct(
            array(
                'vars' => $vars,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property string           $name  Name
 * @property PHPParser_Node[] $stmts Statements
 */
class PHPParser_Node_Stmt_Trait extends PHPParser_Node_Stmt
{
    /**
     * Constructs a trait node.
     *
     * @param string           $name       Name
     * @param PHPParser_Node[] $stmts      Statements
     * @param array            $attributes Additional attributes
     */
    public function __construct($name, array $stmts = array(), array $attributes = array()) {
        parent::__construct(
            array(
                'name'  => $name,
                'stmts' => $stmts,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property null|PHPParser_Node_Expr $expr Expression
 */
class PHPParser_Node_Stmt_Return extends PHPParser_Node_Stmt
{
    /**
     * Constructs a return node.
     *
     * @param null|PHPParser_Node_Expr $expr       Expression
     * @param array                    $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $expr = null, array $attributes = array()) {
        parent::__construct(
            array(
                'expr' => $expr,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Stmt_DeclareDeclare[] $declares List of declares
 * @property PHPParser_Node[]                     $stmts    Statements
 */
class PHPParser_Node_Stmt_Declare extends PHPParser_Node_Stmt
{
    /**
     * Constructs a declare node.
     *
     * @param PHPParser_Node_Stmt_DeclareDeclare[] $declares   List of declares
     * @param PHPParser_Node[]                     $stmts      Statements
     * @param array                                $attributes Additional attributes
     */
    public function __construct(array $declares, array $stmts, array $attributes = array()) {
        parent::__construct(
            array(
                'declares' => $declares,
                'stmts'    => $stmts,
            ),
            $attributes
        );
    }
}<?php

abstract class PHPParser_Node_Stmt_TraitUseAdaptation extends PHPParser_Node_Stmt
{
}<?php

/**
 * @property string                $name    Name
 * @property PHPParser_Node_Name[] $extends Extended interfaces
 * @property PHPParser_Node[]      $stmts   Statements
 */
class PHPParser_Node_Stmt_Interface extends PHPParser_Node_Stmt
{
    protected static $specialNames = array(
        'self'   => true,
        'parent' => true,
        'static' => true,
    );

    /**
     * Constructs a class node.
     *
     * @param string $name       Name
     * @param array  $subNodes   Array of the following optional subnodes:
     *                           'extends' => array(): Name of extended interfaces
     *                           'stmts'   => array(): Statements
     * @param array  $attributes Additional attributes
     */
    public function __construct($name, array $subNodes = array(), array $attributes = array()) {
        parent::__construct(
            $subNodes + array(
                'extends' => array(),
                'stmts'   => array(),
            ),
            $attributes
        );
        $this->name = $name;

        if (isset(self::$specialNames[(string) $this->name])) {
            throw new PHPParser_Error(sprintf('Cannot use "%s" as interface name as it is reserved', $this->name));
        }

        foreach ($this->extends as $interface) {
            if (isset(self::$specialNames[(string) $interface])) {
                throw new PHPParser_Error(sprintf('Cannot use "%s" as interface name as it is reserved', $interface));
            }
        }
    }
}<?php

/**
 * @property array $parts Parts of the name
 */
class PHPParser_Node_Name extends PHPParser_NodeAbstract
{
    /**
     * Constructs a name node.
     *
     * @param string|array $parts      Parts of the name (or name as string)
     * @param array        $attributes Additional attributes
     */
    public function __construct($parts, array $attributes = array()) {
        if (!is_array($parts)) {
            $parts = explode('\\', $parts);
        }

        parent::__construct(
            array(
                'parts' => $parts,
            ),
            $attributes
        );
    }

    /**
     * Gets the first part of the name, i.e. everything before the first namespace separator.
     *
     * @return string First part of the name
     */
    public function getFirst() {
        return $this->parts[0];
    }

    /**
     * Gets the last part of the name, i.e. everything after the last namespace separator.
     *
     * @return string Last part of the name
     */
    public function getLast() {
        return $this->parts[count($this->parts) - 1];
    }

    /**
     * Checks whether the name is unqualified. (E.g. Name)
     *
     * @return bool Whether the name is unqualified
     */
    public function isUnqualified() {
        return 1 == count($this->parts);
    }

    /**
     * Checks whether the name is qualified. (E.g. Name\Name)
     *
     * @return bool Whether the name is qualified
     */
    public function isQualified() {
        return 1 < count($this->parts);
    }

    /**
     * Checks whether the name is fully qualified. (E.g. \Name)
     *
     * @return bool Whether the name is fully qualified
     */
    public function isFullyQualified() {
        return false;
    }

    /**
     * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name)
     *
     * @return bool Whether the name is relative
     */
    public function isRelative() {
        return false;
    }

    /**
     * Returns a string representation of the name by imploding the namespace parts with a separator.
     *
     * @param string $separator The separator to use (defaults to the namespace separator \)
     *
     * @return string String representation
     */
    public function toString($separator = '\\') {
        return implode($separator, $this->parts);
    }

    /**
     * Returns a string representation of the name by imploding the namespace parts with the
     * namespace separator.
     *
     * @return string String representation
     */
    public function __toString() {
        return implode('\\', $this->parts);
    }

    /**
     * Sets the whole name.
     *
     * @param string|array|self $name The name to set the whole name to
     */
    public function set($name) {
        $this->parts = $this->prepareName($name);
    }

    /**
     * Prepends a name to this name.
     *
     * @param string|array|self $name Name to prepend
     */
    public function prepend($name) {
        $this->parts = array_merge($this->prepareName($name), $this->parts);
    }

    /**
     * Appends a name to this name.
     *
     * @param string|array|self $name Name to append
     */
    public function append($name) {
        $this->parts = array_merge($this->parts, $this->prepareName($name));
    }

    /**
     * Sets the first part of the name.
     *
     * @param string|array|self $name The name to set the first part to
     */
    public function setFirst($name) {
        array_splice($this->parts, 0, 1, $this->prepareName($name));
    }

    /**
     * Sets the last part of the name.
     *
     * @param string|array|self $name The name to set the last part to
     */
    public function setLast($name) {
        array_splice($this->parts, -1, 1, $this->prepareName($name));
    }

    /**
     * Prepares a (string, array or Name node) name for use in name changing methods by converting
     * it to an array.
     *
     * @param string|array|self $name Name to prepare
     *
     * @return array Prepared name
     */
    protected function prepareName($name) {
        if (is_string($name)) {
            return explode('\\', $name);
        } elseif (is_array($name)) {
            return $name;
        } elseif ($name instanceof self) {
            return $name->parts;
        }

        throw new InvalidArgumentException(
            'When changing a name you need to pass either a string, an array or a Name node'
        );
    }
}<?php

abstract class PHPParser_Node_Expr extends PHPParser_NodeAbstract
{
}<?php

/**
 * @property string                          $name    Name
 * @property null|PHPParser_Node_Expr        $default Default value
 * @property null|string|PHPParser_Node_Name $type    Typehint
 * @property bool                            $byRef   Whether is passed by reference
 */
class PHPParser_Node_Param extends PHPParser_NodeAbstract
{
    /**
     * Constructs a parameter node.
     *
     * @param string                          $name       Name
     * @param null|PHPParser_Node_Expr        $default    Default value
     * @param null|string|PHPParser_Node_Name $type       Typehint
     * @param bool                            $byRef      Whether is passed by reference
     * @param array                           $attributes Additional attributes
     */
    public function __construct($name, $default = null, $type = null, $byRef = false, array $attributes = array()) {
        parent::__construct(
            array(
                'name'    => $name,
                'default' => $default,
                'type'    => $type,
                'byRef'   => $byRef
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $left  The left hand side expression
 * @property PHPParser_Node_Expr $right The right hand side expression
 */
class PHPParser_Node_Expr_BitwiseXor extends PHPParser_Node_Expr
{
    /**
     * Constructs a bitwise xor node.
     *
     * @param PHPParser_Node_Expr $left       The left hand side expression
     * @param PHPParser_Node_Expr $right      The right hand side expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, array $attributes = array()) {
        parent::__construct(
            array(
                'left'  => $left,
                'right' => $right
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr        $var  Variable holding object
 * @property string|PHPParser_Node_Expr $name Property Name
 */
class PHPParser_Node_Expr_PropertyFetch extends PHPParser_Node_Expr
{
    /**
     * Constructs a function call node.
     *
     * @param PHPParser_Node_Expr        $var        Variable holding object
     * @param string|PHPParser_Node_Expr $name       Property name
     * @param array                      $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $var, $name, array $attributes = array()) {
        parent::__construct(
            array(
                'var'  => $var,
                'name' => $name
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $var  Variable
 * @property PHPParser_Node_Expr $expr Expression
 */
class PHPParser_Node_Expr_AssignMod extends PHPParser_Node_Expr
{
    /**
     * Constructs an assignment with modulo node.
     *
     * @param PHPParser_Node_Expr $var        Variable
     * @param PHPParser_Node_Expr $expr       Expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $expr, array $attributes = array()) {
        parent::__construct(
            array(
                'var'  => $var,
                'expr' => $expr
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr_ArrayItem[] $items Items
 */
class PHPParser_Node_Expr_Array extends PHPParser_Node_Expr
{
    /**
     * Constructs an array node.
     *
     * @param PHPParser_Node_Expr_ArrayItem[] $items      Items of the array
     * @param array                           $attributes Additional attributes
     */
    public function __construct(array $items = array(), array $attributes = array()) {
        parent::__construct(
            array(
                'items' => $items
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr      $var Variable
 * @property null|PHPParser_Node_Expr $dim Array index / dim
 */
class PHPParser_Node_Expr_ArrayDimFetch extends PHPParser_Node_Expr
{
    /**
     * Constructs an array index fetch node.
     *
     * @param PHPParser_Node_Expr      $var        Variable
     * @param null|PHPParser_Node_Expr $dim        Array index / dim
     * @param array                    $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $dim = null, array $attributes = array()) {
        parent::__construct(
            array(
                'var' => $var,
                'dim' => $dim
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr      $cond Condition
 * @property null|PHPParser_Node_Expr $if   Expression for true
 * @property PHPParser_Node_Expr      $else Expression for false
 */
class PHPParser_Node_Expr_Ternary extends PHPParser_Node_Expr
{
    /**
     * Constructs a ternary operator node.
     *
     * @param PHPParser_Node_Expr      $cond       Condition
     * @param null|PHPParser_Node_Expr $if         Expression for true
     * @param PHPParser_Node_Expr      $else       Expression for false
     * @param array                    $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $cond, $if, PHPParser_Node_Expr $else, array $attributes = array()) {
        parent::__construct(
            array(
                'cond' => $cond,
                'if'   => $if,
                'else' => $else
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Name|PHPParser_Node_Expr $class Class name
 * @property string|PHPParser_Node_Expr              $name  Method name
 * @property PHPParser_Node_Arg[]                    $args  Arguments
 */
class PHPParser_Node_Expr_StaticCall extends PHPParser_Node_Expr
{
    /**
     * Constructs a static method call node.
     *
     * @param PHPParser_Node_Name|PHPParser_Node_Expr $class      Class name
     * @param string|PHPParser_Node_Expr              $name       Method name
     * @param PHPParser_Node_Arg[]                    $args       Arguments
     * @param array                                   $attributes Additional attributes
     */
    public function __construct($class, $name, array $args = array(), array $attributes = array()) {
        parent::__construct(
            array(
                'class' => $class,
                'name'  => $name,
                'args'  => $args
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr[] $vars Variables
 */
class PHPParser_Node_Expr_Isset extends PHPParser_Node_Expr
{
    /**
     * Constructs an array node.
     *
     * @param PHPParser_Node_Expr[] $vars       Variables
     * @param array                 $attributes Additional attributes
     */
    public function __construct(array $vars, array $attributes = array()) {
        parent::__construct(
            array(
                'vars' => $vars
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Name|PHPParser_Node_Expr $class Class name
 * @property string                                  $name  Constant name
 */
class PHPParser_Node_Expr_ClassConstFetch extends PHPParser_Node_Expr
{
    /**
     * Constructs a class const fetch node.
     *
     * @param PHPParser_Node_Name|PHPParser_Node_Expr $class      Class name
     * @param string                                  $name       Constant name
     * @param array                                   $attributes Additional attributes
     */
    public function __construct($class, $name, array $attributes = array()) {
        parent::__construct(
            array(
                'class' => $class,
                'name'  => $name
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $left  The left hand side expression
 * @property PHPParser_Node_Expr $right The right hand side expression
 */
class PHPParser_Node_Expr_Mod extends PHPParser_Node_Expr
{
    /**
     * Constructs a modulo node.
     *
     * @param PHPParser_Node_Expr $left       The left hand side expression
     * @param PHPParser_Node_Expr $right      The right hand side expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, array $attributes = array()) {
        parent::__construct(
            array(
                'left'  => $left,
                'right' => $right
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $expr Expression
 */
class PHPParser_Node_Expr_Empty extends PHPParser_Node_Expr
{
    /**
     * Constructs an empty() node.
     *
     * @param PHPParser_Node_Expr $expr       Expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $expr, array $attributes = array()) {
        parent::__construct(
            array(
                'expr' => $expr
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $var  Variable
 * @property PHPParser_Node_Expr $expr Expression
 */
class PHPParser_Node_Expr_AssignMul extends PHPParser_Node_Expr
{
    /**
     * Constructs an assignment with multiplication node.
     *
     * @param PHPParser_Node_Expr $var        Variable
     * @param PHPParser_Node_Expr $expr       Expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $expr, array $attributes = array()) {
        parent::__construct(
            array(
                'var'  => $var,
                'expr' => $expr
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Name|PHPParser_Node_Expr $class Class name
 * @property PHPParser_Node_Arg[]                    $args  Arguments
 */
class PHPParser_Node_Expr_New extends PHPParser_Node_Expr
{
    /**
     * Constructs a function call node.
     *
     * @param PHPParser_Node_Name|PHPParser_Node_Expr $class      Class name
     * @param PHPParser_Node_Arg[]                    $args       Arguments
     * @param array                                   $attributes Additional attributes
     */
    public function __construct($class, array $args = array(), array $attributes = array()) {
        parent::__construct(
            array(
                'class' => $class,
                'args'  => $args
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $var  Variable
 * @property PHPParser_Node_Expr $expr Expression
 */
class PHPParser_Node_Expr_Assign extends PHPParser_Node_Expr
{
    /**
     * Constructs an assignment node.
     *
     * @param PHPParser_Node_Expr $var        Variable
     * @param PHPParser_Node_Expr $expr       Expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $expr, array $attributes = array()) {
        parent::__construct(
            array(
                'var'  => $var,
                'expr' => $expr
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr      $value Value
 * @property null|PHPParser_Node_Expr $key   Key
 * @property bool                     $byRef Whether to assign by reference
 */
class PHPParser_Node_Expr_ArrayItem extends PHPParser_Node_Expr
{
    /**
     * Constructs an array item node.
     *
     * @param PHPParser_Node_Expr      $value      Value
     * @param null|PHPParser_Node_Expr $key        Key
     * @param bool                     $byRef      Whether to assign by reference
     * @param array                    $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $value, PHPParser_Node_Expr $key = null, $byRef = false, array $attributes = array()) {
        parent::__construct(
            array(
                'key'   => $key,
                'value' => $value,
                'byRef' => $byRef
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $var Variable
 */
class PHPParser_Node_Expr_PostDec extends PHPParser_Node_Expr
{
    /**
     * Constructs a post decrement node.
     *
     * @param PHPParser_Node_Expr $var        Variable
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $var, array $attributes = array()) {
        parent::__construct(
            array(
                'var' => $var
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $left  The left hand side expression
 * @property PHPParser_Node_Expr $right The right hand side expression
 */
class PHPParser_Node_Expr_Minus extends PHPParser_Node_Expr
{
    /**
     * Constructs a substraction node.
     *
     * @param PHPParser_Node_Expr $left       The left hand side expression
     * @param PHPParser_Node_Expr $right      The right hand side expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, array $attributes = array()) {
        parent::__construct(
            array(
                'left'  => $left,
                'right' => $right
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $left  The left hand side expression
 * @property PHPParser_Node_Expr $right The right hand side expression
 */
class PHPParser_Node_Expr_Identical extends PHPParser_Node_Expr
{
    /**
     * Constructs an identicality comparison node.
     *
     * @param PHPParser_Node_Expr $left       The left hand side expression
     * @param PHPParser_Node_Expr $right      The right hand side expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, array $attributes = array()) {
        parent::__construct(
            array(
                'left'  => $left,
                'right' => $right
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $expr Expression
 */
class PHPParser_Node_Expr_UnaryPlus extends PHPParser_Node_Expr
{
    /**
     * Constructs a unary plus node.
     *
     * @param PHPParser_Node_Expr $expr       Expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $expr, array $attributes = array()) {
        parent::__construct(
            array(
                'expr' => $expr
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $var Variable
 */
class PHPParser_Node_Expr_PreDec extends PHPParser_Node_Expr
{
    /**
     * Constructs a pre decrement node.
     *
     * @param PHPParser_Node_Expr $var        Variable
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $var, array $attributes = array()) {
        parent::__construct(
            array(
                'var' => $var
            ),
            $attributes
        );
    }
}<?php

/**
 * @property string|PHPParser_Node_Expr $name Name
 */
class PHPParser_Node_Expr_Variable extends PHPParser_Node_Expr
{
    /**
     * Constructs a variable node.
     *
     * @param string|PHPParser_Node_Expr $name       Name
     * @param array                      $attributes Additional attributes
     */
    public function __construct($name, array $attributes = array()) {
        parent::__construct(
            array(
                 'name' => $name
            ),
            $attributes
        );
    }
}<?php

/**
 * @property null|PHPParser_Node_Expr $value Value expression
 * @property null|PHPParser_Node_Expr $key   Key expression
 */
class PHPParser_Node_Expr_Yield extends PHPParser_Node_Expr
{
    /**
     * Constructs a yield expression node.
     *
     * @param null|PHPParser_Node_Expr $value ´    Value expression
     * @param null|PHPParser_Node_Expr $key        Key expression
     * @param array                    $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $value = null, PHPParser_Node_Expr $key = null, array $attributes = array()) {
        parent::__construct(
            array(
                'key'   => $key,
                'value' => $value,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $var  Variable
 * @property PHPParser_Node_Expr $expr Expression
 */
class PHPParser_Node_Expr_AssignMinus extends PHPParser_Node_Expr
{
    /**
     * Constructs an assignment with minus node.
     *
     * @param PHPParser_Node_Expr $var        Variable
     * @param PHPParser_Node_Expr $expr       Expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $expr, array $attributes = array()) {
        parent::__construct(
            array(
                'var'  => $var,
                'expr' => $expr
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $var  Variable
 * @property PHPParser_Node_Expr $expr Expression
 */
class PHPParser_Node_Expr_AssignPlus extends PHPParser_Node_Expr
{
    /**
     * Constructs an assignment with addition node.
     *
     * @param PHPParser_Node_Expr $var        Variable
     * @param PHPParser_Node_Expr $expr       Expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $expr, array $attributes = array()) {
        parent::__construct(
            array(
                'var'  => $var,
                'expr' => $expr
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $var  Variable
 * @property PHPParser_Node_Expr $expr Expression
 */
class PHPParser_Node_Expr_AssignConcat extends PHPParser_Node_Expr
{
    /**
     * Constructs an assignment with concat node.
     *
     * @param PHPParser_Node_Expr $var        Variable
     * @param PHPParser_Node_Expr $expr       Expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $expr, array $attributes = array()) {
        parent::__construct(
            array(
                'var'  => $var,
                'expr' => $expr
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $expr Expression
 */
class PHPParser_Node_Expr_Print extends PHPParser_Node_Expr
{
    /**
     * Constructs an print() node.
     *
     * @param PHPParser_Node_Expr $expr       Expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $expr, array $attributes = array()) {
        parent::__construct(
            array(
                'expr' => $expr
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $left  The left hand side expression
 * @property PHPParser_Node_Expr $right The right hand side expression
 */
class PHPParser_Node_Expr_SmallerOrEqual extends PHPParser_Node_Expr
{
    /**
     * Constructs a smaller than or equal comparison node.
     *
     * @param PHPParser_Node_Expr $left       The left hand side expression
     * @param PHPParser_Node_Expr $right      The right hand side expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, array $attributes = array()) {
        parent::__construct(
            array(
                'left'  => $left,
                'right' => $right
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $left  The left hand side expression
 * @property PHPParser_Node_Expr $right The right hand side expression
 */
class PHPParser_Node_Expr_Div extends PHPParser_Node_Expr
{
    /**
     * Constructs a division node.
     *
     * @param PHPParser_Node_Expr $left       The left hand side expression
     * @param PHPParser_Node_Expr $right      The right hand side expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, array $attributes = array()) {
        parent::__construct(
            array(
                'left'  => $left,
                'right' => $right
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Name $name Constant name
 */
class PHPParser_Node_Expr_ConstFetch extends PHPParser_Node_Expr
{
    /**
     * Constructs a const fetch node.
     *
     * @param PHPParser_Node_Name $name       Constant name
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Name $name, array $attributes = array()) {
        parent::__construct(
            array(
                'name'  => $name
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $left  The left hand side expression
 * @property PHPParser_Node_Expr $right The right hand side expression
 */
class PHPParser_Node_Expr_Mul extends PHPParser_Node_Expr
{
    /**
     * Constructs a multiplication node.
     *
     * @param PHPParser_Node_Expr $left       The left hand side expression
     * @param PHPParser_Node_Expr $right      The right hand side expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, array $attributes = array()) {
        parent::__construct(
            array(
                'left'  => $left,
                'right' => $right
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $expr Expression
 */
class PHPParser_Node_Expr_UnaryMinus extends PHPParser_Node_Expr
{
    /**
     * Constructs a unary minus node.
     *
     * @param PHPParser_Node_Expr $expr       Expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $expr, array $attributes = array()) {
        parent::__construct(
            array(
                'expr' => $expr
            ),
            $attributes
        );
    }
}<?php

/**
 * @property string $var   Name of variable
 * @property bool   $byRef Whether to use by reference
 */
class PHPParser_Node_Expr_ClosureUse extends PHPParser_Node_Expr
{
    /**
     * Constructs a closure use node.
     *
     * @param string      $var        Name of variable
     * @param bool        $byRef      Whether to use by reference
     * @param array       $attributes Additional attributes
     */
    public function __construct($var, $byRef = false, array $attributes = array()) {
        parent::__construct(
            array(
                'var'   => $var,
                'byRef' => $byRef
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $left  The left hand side expression
 * @property PHPParser_Node_Expr $right The right hand side expression
 */
class PHPParser_Node_Expr_Equal extends PHPParser_Node_Expr
{
    /**
     * Constructs a equality comparison node.
     *
     * @param PHPParser_Node_Expr $left       The left hand side expression
     * @param PHPParser_Node_Expr $right      The right hand side expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, array $attributes = array()) {
        parent::__construct(
            array(
                'left'  => $left,
                'right' => $right
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $var  Variable
 * @property PHPParser_Node_Expr $expr Expression
 */
class PHPParser_Node_Expr_AssignBitwiseXor extends PHPParser_Node_Expr
{
    /**
     * Constructs an assignment with bitwise xor node.
     *
     * @param PHPParser_Node_Expr $var        Variable
     * @param PHPParser_Node_Expr $expr       Expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $expr, array $attributes = array()) {
        parent::__construct(
            array(
                'var'  => $var,
                'expr' => $expr
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $var Variable
 */
class PHPParser_Node_Expr_PostInc extends PHPParser_Node_Expr
{
    /**
     * Constructs a post increment node.
     *
     * @param PHPParser_Node_Expr $var        Variable
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $var, array $attributes = array()) {
        parent::__construct(
            array(
                'var' => $var
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $expr Expression
 */
abstract class PHPParser_Node_Expr_Cast extends PHPParser_Node_Expr
{
    /**
     * Constructs a cast node.
     *
     * @param PHPParser_Node_Expr $expr       Expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $expr, array $attributes = array()) {
        parent::__construct(
            array(
                'expr' => $expr
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $expr Expression
 * @property int                 $type Type of include
 */
class PHPParser_Node_Expr_Include extends PHPParser_Node_Expr
{
    const TYPE_INCLUDE      = 1;
    const TYPE_INCLUDE_ONCE = 2;
    const TYPE_REQUIRE      = 3;
    const TYPE_REQUIRE_ONCE = 4;

    /**
     * Constructs an include node.
     *
     * @param PHPParser_Node_Expr $expr       Expression
     * @param int                 $type       Type of include
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $expr, $type, array $attributes = array()) {
        parent::__construct(
            array(
                'expr' => $expr,
                'type' => $type
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $var  Variable
 * @property PHPParser_Node_Expr $expr Expression
 */
class PHPParser_Node_Expr_AssignShiftLeft extends PHPParser_Node_Expr
{
    /**
     * Constructs an assignment with left shift node.
     *
     * @param PHPParser_Node_Expr $var        Variable
     * @param PHPParser_Node_Expr $expr       Expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $expr, array $attributes = array()) {
        parent::__construct(
            array(
                'var'  => $var,
                'expr' => $expr
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $expr Expression
 */
class PHPParser_Node_Expr_BooleanNot extends PHPParser_Node_Expr
{
    /**
     * Constructs a boolean not node.
     *
     * @param PHPParser_Node_Expr $expr       Expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $expr, array $attributes = array()) {
        parent::__construct(
            array(
                'expr' => $expr
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $var  Variable
 * @property PHPParser_Node_Expr $expr Expression
 */
class PHPParser_Node_Expr_AssignBitwiseAnd extends PHPParser_Node_Expr
{
    /**
     * Constructs an assignment with bitwise and node.
     *
     * @param PHPParser_Node_Expr $var        Variable
     * @param PHPParser_Node_Expr $expr       Expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $expr, array $attributes = array()) {
        parent::__construct(
            array(
                'var'  => $var,
                'expr' => $expr
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $left  The left hand side expression
 * @property PHPParser_Node_Expr $right The right hand side expression
 */
class PHPParser_Node_Expr_Smaller extends PHPParser_Node_Expr
{
    /**
     * Constructs a smaller than comparison node.
     *
     * @param PHPParser_Node_Expr $left       The left hand side expression
     * @param PHPParser_Node_Expr $right      The right hand side expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, array $attributes = array()) {
        parent::__construct(
            array(
                'left'  => $left,
                'right' => $right
            ),
            $attributes
        );
    }
}<?php

/**
 * @property array $vars List of variables to assign to
 */
class PHPParser_Node_Expr_List extends PHPParser_Node_Expr
{
    /**
     * Constructs a list() destructuring node.
     *
     * @param array $vars       List of variables to assign to
     * @param array $attributes Additional attributes
     */
    public function __construct(array $vars, array $attributes = array()) {
        parent::__construct(
            array(
                'vars' => $vars,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $left  The left hand side expression
 * @property PHPParser_Node_Expr $right The right hand side expression
 */
class PHPParser_Node_Expr_Plus extends PHPParser_Node_Expr
{
    /**
     * Constructs an addition node.
     *
     * @param PHPParser_Node_Expr $left       The left hand side expression
     * @param PHPParser_Node_Expr $right      The right hand side expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, array $attributes = array()) {
        parent::__construct(
            array(
                'left'  => $left,
                'right' => $right
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Name|PHPParser_Node_Expr $name Function name
 * @property PHPParser_Node_Arg[]                    $args Arguments
 */
class PHPParser_Node_Expr_FuncCall extends PHPParser_Node_Expr
{
    /**
     * Constructs a function call node.
     *
     * @param PHPParser_Node_Name|PHPParser_Node_Expr $name       Function name
     * @param PHPParser_Node_Arg[]                    $args       Arguments
     * @param array                                   $attributes Additional attributes
     */
    public function __construct($name, array $args = array(), array $attributes = array()) {
        parent::__construct(
            array(
                'name' => $name,
                'args' => $args
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $var Variable
 */
class PHPParser_Node_Expr_PreInc extends PHPParser_Node_Expr
{
    /**
     * Constructs a pre increment node.
     *
     * @param PHPParser_Node_Expr $var        Variable
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $var, array $attributes = array()) {
        parent::__construct(
            array(
                'var' => $var
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $expr Expression
 */
class PHPParser_Node_Expr_ErrorSuppress extends PHPParser_Node_Expr
{
    /**
     * Constructs an error suppress node.
     *
     * @param PHPParser_Node_Expr $expr       Expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $expr, array $attributes = array()) {
        parent::__construct(
            array(
                'expr' => $expr
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $var  Variable
 * @property PHPParser_Node_Expr $expr Expression
 */
class PHPParser_Node_Expr_AssignBitwiseOr extends PHPParser_Node_Expr
{
    /**
     * Constructs an assignment with bitwise or node.
     *
     * @param PHPParser_Node_Expr $var        Variable
     * @param PHPParser_Node_Expr $expr       Expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $expr, array $attributes = array()) {
        parent::__construct(
            array(
                'var'  => $var,
                'expr' => $expr
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $left  The left hand side expression
 * @property PHPParser_Node_Expr $right The right hand side expression
 */
class PHPParser_Node_Expr_Greater extends PHPParser_Node_Expr
{
    /**
     * Constructs a greater than comparison node.
     *
     * @param PHPParser_Node_Expr $left       The left hand side expression
     * @param PHPParser_Node_Expr $right      The right hand side expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, array $attributes = array()) {
        parent::__construct(
            array(
                'left'  => $left,
                'right' => $right
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $expr  Expression
 * @property PHPParser_Node_Name|PHPParser_Node_Expr $class Class name
 */
class PHPParser_Node_Expr_Instanceof extends PHPParser_Node_Expr
{
    /**
     * Constructs an instanceof check node.
     *
     * @param PHPParser_Node_Expr                     $expr       Expression
     * @param PHPParser_Node_Name|PHPParser_Node_Expr $class      Class name
     * @param array                                   $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $expr, $class, array $attributes = array()) {
        parent::__construct(
            array(
                'expr'  => $expr,
                'class' => $class
            ),
            $attributes
        );
    }
}<?php

class PHPParser_Node_Expr_Cast_String extends PHPParser_Node_Expr_Cast
{
}<?php

class PHPParser_Node_Expr_Cast_Array extends PHPParser_Node_Expr_Cast
{
}<?php

class PHPParser_Node_Expr_Cast_Double extends PHPParser_Node_Expr_Cast
{
}<?php

class PHPParser_Node_Expr_Cast_Int extends PHPParser_Node_Expr_Cast
{
}<?php

class PHPParser_Node_Expr_Cast_Object extends PHPParser_Node_Expr_Cast
{
}<?php

class PHPParser_Node_Expr_Cast_Bool extends PHPParser_Node_Expr_Cast
{
}<?php

class PHPParser_Node_Expr_Cast_Unset extends PHPParser_Node_Expr_Cast
{
}<?php

/**
 * @property PHPParser_Node_Expr $left  The left hand side expression
 * @property PHPParser_Node_Expr $right The right hand side expression
 */
class PHPParser_Node_Expr_Concat extends PHPParser_Node_Expr
{
    /**
     * Constructs a concat node.
     *
     * @param PHPParser_Node_Expr $left       The left hand side expression
     * @param PHPParser_Node_Expr $right      The right hand side expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, array $attributes = array()) {
        parent::__construct(
            array(
                'left'  => $left,
                'right' => $right
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Name|PHPParser_Node_Expr $class Class name
 * @property string|PHPParser_Node_Expr              $name  Property name
 */
class PHPParser_Node_Expr_StaticPropertyFetch extends PHPParser_Node_Expr
{
    /**
     * Constructs a static property fetch node.
     *
     * @param PHPParser_Node_Name|PHPParser_Node_Expr $class      Class name
     * @param string|PHPParser_Node_Expr              $name       Property name
     * @param array                                   $attributes Additional attributes
     */
    public function __construct($class, $name, array $attributes = array()) {
        parent::__construct(
            array(
                'class' => $class,
                'name'  => $name
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $left  The left hand side expression
 * @property PHPParser_Node_Expr $right The right hand side expression
 */
class PHPParser_Node_Expr_BitwiseOr extends PHPParser_Node_Expr
{
    /**
     * Constructs a bitwise or node.
     *
     * @param PHPParser_Node_Expr $left       The left hand side expression
     * @param PHPParser_Node_Expr $right      The right hand side expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, array $attributes = array()) {
        parent::__construct(
            array(
                'left'  => $left,
                'right' => $right
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $var  Variable
 * @property PHPParser_Node_Expr $expr Expression
 */
class PHPParser_Node_Expr_AssignShiftRight extends PHPParser_Node_Expr
{
    /**
     * Constructs an assignment with right shift node.
     *
     * @param PHPParser_Node_Expr $var        Variable
     * @param PHPParser_Node_Expr $expr       Expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $expr, array $attributes = array()) {
        parent::__construct(
            array(
                'var'  => $var,
                'expr' => $expr
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $expr Expression
 */
class PHPParser_Node_Expr_Clone extends PHPParser_Node_Expr
{
    /**
     * Constructs a clone node.
     *
     * @param PHPParser_Node_Expr $expr       Expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $expr, array $attributes = array()) {
        parent::__construct(
            array(
                'expr' => $expr
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $left  The left hand side expression
 * @property PHPParser_Node_Expr $right The right hand side expression
 */
class PHPParser_Node_Expr_BooleanOr extends PHPParser_Node_Expr
{
    /**
     * Constructs a boolean or node.
     *
     * @param PHPParser_Node_Expr $left       The left hand side expression
     * @param PHPParser_Node_Expr $right      The right hand side expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, array $attributes = array()) {
        parent::__construct(
            array(
                'left'  => $left,
                'right' => $right
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node[]                 $stmts  Statements
 * @property PHPParser_Node_Param[]           $params Parameters
 * @property PHPParser_Node_Expr_ClosureUse[] $uses   use()s
 * @property bool                             $byRef  Whether to return by reference
 * @property bool                             $static Whether the closure is static
 */
class PHPParser_Node_Expr_Closure extends PHPParser_Node_Expr
{
    /**
     * Constructs a lambda function node.
     *
     * @param array $subNodes   Array of the following optional subnodes:
     *                          'stmts'  => array(): Statements
     *                          'params' => array(): Parameters
     *                          'uses'   => array(): use()s
     *                          'byRef'  => false  : Whether to return by reference
     *                          'static' => false  : Whether the closure is static
     * @param array $attributes Additional attributes
     */
    public function __construct(array $subNodes = array(), array $attributes = array()) {
        parent::__construct(
            $subNodes + array(
                'stmts'  => array(),
                'params' => array(),
                'uses'   => array(),
                'byRef'  => false,
                'static' => false,
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $left  The left hand side expression
 * @property PHPParser_Node_Expr $right The right hand side expression
 */
class PHPParser_Node_Expr_BitwiseAnd extends PHPParser_Node_Expr
{
    /**
     * Constructs a bitwise and node.
     *
     * @param PHPParser_Node_Expr $left       The left hand side expression
     * @param PHPParser_Node_Expr $right      The right hand side expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, array $attributes = array()) {
        parent::__construct(
            array(
                'left'  => $left,
                'right' => $right
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $left  The left hand side expression
 * @property PHPParser_Node_Expr $right The right hand side expression
 */
class PHPParser_Node_Expr_ShiftLeft extends PHPParser_Node_Expr
{
    /**
     * Constructs a shift left node.
     *
     * @param PHPParser_Node_Expr $left       The left hand side expression
     * @param PHPParser_Node_Expr $right      The right hand side expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, array $attributes = array()) {
        parent::__construct(
            array(
                'left'  => $left,
                'right' => $right
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $left  The left hand side expression
 * @property PHPParser_Node_Expr $right The right hand side expression
 */
class PHPParser_Node_Expr_BooleanAnd extends PHPParser_Node_Expr
{
    /**
     * Constructs a boolean and node.
     *
     * @param PHPParser_Node_Expr $left       The left hand side expression
     * @param PHPParser_Node_Expr $right      The right hand side expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, array $attributes = array()) {
        parent::__construct(
            array(
                'left'  => $left,
                'right' => $right
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $left  The left hand side expression
 * @property PHPParser_Node_Expr $right The right hand side expression
 */
class PHPParser_Node_Expr_LogicalAnd extends PHPParser_Node_Expr
{
    /**
     * Constructs a logical and node.
     *
     * @param PHPParser_Node_Expr $left       The left hand side expression
     * @param PHPParser_Node_Expr $right      The right hand side expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, array $attributes = array()) {
        parent::__construct(
            array(
                'left'  => $left,
                'right' => $right
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $expr Expression
 */
class PHPParser_Node_Expr_BitwiseNot extends PHPParser_Node_Expr
{
    /**
     * Constructs a bitwise not node.
     *
     * @param PHPParser_Node_Expr $expr       Expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $expr, array $attributes = array()) {
        parent::__construct(
            array(
                'expr' => $expr
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $left  The left hand side expression
 * @property PHPParser_Node_Expr $right The right hand side expression
 */
class PHPParser_Node_Expr_ShiftRight extends PHPParser_Node_Expr
{
    /**
     * Constructs a shift right node.
     *
     * @param PHPParser_Node_Expr $left       The left hand side expression
     * @param PHPParser_Node_Expr $right      The right hand side expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, array $attributes = array()) {
        parent::__construct(
            array(
                'left'  => $left,
                'right' => $right
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $left  The left hand side expression
 * @property PHPParser_Node_Expr $right The right hand side expression
 */
class PHPParser_Node_Expr_NotIdentical extends PHPParser_Node_Expr
{
    /**
     * Constructs a not identical comparison node.
     *
     * @param PHPParser_Node_Expr $left       The left hand side expression
     * @param PHPParser_Node_Expr $right      The right hand side expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, array $attributes = array()) {
        parent::__construct(
            array(
                'left'  => $left,
                'right' => $right
            ),
            $attributes
        );
    }
}<?php

/**
 * @property null|PHPParser_Node_Expr $expr Expression
 */
class PHPParser_Node_Expr_Exit extends PHPParser_Node_Expr
{
    /**
     * Constructs an exit() node.
     *
     * @param null|PHPParser_Node_Expr $expr       Expression
     * @param array                    $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $expr = null, array $attributes = array()) {
        parent::__construct(
            array(
                'expr' => $expr
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $left  The left hand side expression
 * @property PHPParser_Node_Expr $right The right hand side expression
 */
class PHPParser_Node_Expr_LogicalOr extends PHPParser_Node_Expr
{
    /**
     * Constructs a logical or node.
     *
     * @param PHPParser_Node_Expr $left       The left hand side expression
     * @param PHPParser_Node_Expr $right      The right hand side expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, array $attributes = array()) {
        parent::__construct(
            array(
                'left'  => $left,
                'right' => $right
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $var  Variable
 * @property PHPParser_Node_Expr $expr Expression
 */
class PHPParser_Node_Expr_AssignDiv extends PHPParser_Node_Expr
{
    /**
     * Constructs an assignment with division node.
     *
     * @param PHPParser_Node_Expr $var        Variable
     * @param PHPParser_Node_Expr $expr       Expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $expr, array $attributes = array()) {
        parent::__construct(
            array(
                'var'  => $var,
                'expr' => $expr
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $left  The left hand side expression
 * @property PHPParser_Node_Expr $right The right hand side expression
 */
class PHPParser_Node_Expr_GreaterOrEqual extends PHPParser_Node_Expr
{
    /**
     * Constructs a greater than or equal node.
     *
     * @param PHPParser_Node_Expr $left       The left hand side expression
     * @param PHPParser_Node_Expr $right      The right hand side expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, array $attributes = array()) {
        parent::__construct(
            array(
                'left'  => $left,
                'right' => $right
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $left  The left hand side expression
 * @property PHPParser_Node_Expr $right The right hand side expression
 */
class PHPParser_Node_Expr_LogicalXor extends PHPParser_Node_Expr
{
    /**
     * Constructs a logical xor node.
     *
     * @param PHPParser_Node_Expr $left       The left hand side expression
     * @param PHPParser_Node_Expr $right      The right hand side expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, array $attributes = array()) {
        parent::__construct(
            array(
                'left'  => $left,
                'right' => $right
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $left  The left hand side expression
 * @property PHPParser_Node_Expr $right The right hand side expression
 */
class PHPParser_Node_Expr_NotEqual extends PHPParser_Node_Expr
{
    /**
     * Constructs a not equal comparison node.
     *
     * @param PHPParser_Node_Expr $left       The left hand side expression
     * @param PHPParser_Node_Expr $right      The right hand side expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $left, PHPParser_Node_Expr $right, array $attributes = array()) {
        parent::__construct(
            array(
                'left'  => $left,
                'right' => $right
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $var  Variable reference is assigned to
 * @property PHPParser_Node_Expr $expr Variable which is referenced
 */
class PHPParser_Node_Expr_AssignRef extends PHPParser_Node_Expr
{
    /**
     * Constructs an assignment node.
     *
     * @param PHPParser_Node_Expr $var        Variable
     * @param PHPParser_Node_Expr $expr       Expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $var, PHPParser_Node_Expr $expr, array $attributes = array()) {
        parent::__construct(
            array(
                'var'  => $var,
                'expr' => $expr
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr $expr Expression
 */
class PHPParser_Node_Expr_Eval extends PHPParser_Node_Expr
{
    /**
     * Constructs an eval() node.
     *
     * @param PHPParser_Node_Expr $expr       Expression
     * @param array               $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $expr, array $attributes = array()) {
        parent::__construct(
            array(
                'expr' => $expr
            ),
            $attributes
        );
    }
}<?php

/**
 * @property PHPParser_Node_Expr        $var  Variable holding object
 * @property string|PHPParser_Node_Expr $name Method name
 * @property PHPParser_Node_Arg[]       $args Arguments
 */
class PHPParser_Node_Expr_MethodCall extends PHPParser_Node_Expr
{
    /**
     * Constructs a function call node.
     *
     * @param PHPParser_Node_Expr        $var        Variable holding object
     * @param string|PHPParser_Node_Expr $name       Method name
     * @param PHPParser_Node_Arg[]       $args       Arguments
     * @param array                      $attributes Additional attributes
     */
    public function __construct(PHPParser_Node_Expr $var, $name, array $args = array(), array $attributes = array()) {
        parent::__construct(
            array(
                'var'  => $var,
                'name' => $name,
                'args' => $args
            ),
            $attributes
        );
    }
}<?php

/**
 * @property array $parts Encapsed string array
 */
class PHPParser_Node_Expr_ShellExec extends PHPParser_Node_Expr
{
    /**
     * Constructs a shell exec (backtick) node.
     *
     * @param array       $parts      Encapsed string array
     * @param array       $attributes Additional attributes
     */
    public function __construct($parts, array $attributes = array()) {
        parent::__construct(
            array(
                'parts' => $parts
            ),
            $attributes
        );
    }
}<?php

class PHPParser_Node_Name_FullyQualified extends PHPParser_Node_Name
{
    /**
     * Checks whether the name is unqualified. (E.g. Name)
     *
     * @return bool Whether the name is unqualified
     */
    public function isUnqualified() {
        return false;
    }

    /**
     * Checks whether the name is qualified. (E.g. Name\Name)
     *
     * @return bool Whether the name is qualified
     */
    public function isQualified() {
        return false;
    }

    /**
     * Checks whether the name is fully qualified. (E.g. \Name)
     *
     * @return bool Whether the name is fully qualified
     */
    public function isFullyQualified() {
        return true;
    }

    /**
     * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name)
     *
     * @return bool Whether the name is relative
     */
    public function isRelative() {
        return false;
    }
}<?php

class PHPParser_Node_Name_Relative extends PHPParser_Node_Name
{
    /**
     * Checks whether the name is unqualified. (E.g. Name)
     *
     * @return bool Whether the name is unqualified
     */
    public function isUnqualified() {
        return false;
    }

    /**
     * Checks whether the name is qualified. (E.g. Name\Name)
     *
     * @return bool Whether the name is qualified
     */
    public function isQualified() {
        return false;
    }

    /**
     * Checks whether the name is fully qualified. (E.g. \Name)
     *
     * @return bool Whether the name is fully qualified
     */
    public function isFullyQualified() {
        return false;
    }

    /**
     * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name)
     *
     * @return bool Whether the name is relative
     */
    public function isRelative() {
        return true;
    }
}<?php

/**
 * @property string $value String value
 */
class PHPParser_Node_Scalar_String extends PHPParser_Node_Scalar
{
    protected static $replacements = array(
        '\\' => '\\',
        '$'  =>  '$',
        'n'  => "\n",
        'r'  => "\r",
        't'  => "\t",
        'f'  => "\f",
        'v'  => "\v",
        'e'  => "\x1B",
    );

    /**
     * Constructs a string scalar node.
     *
     * @param string $value      Value of the string
     * @param array  $attributes Additional attributes
     */
    public function __construct($value = '', array $attributes = array()) {
        parent::__construct(
            array(
                'value' => $value
            ),
            $attributes
        );
    }

    /**
     * Parses a string token.
     *
     * @param string $str String token content
     *
     * @return string The parsed string
     */
    public static function parse($str) {
        $bLength = 0;
        if ('b' === $str[0]) {
            $bLength = 1;
        }

        if ('\'' === $str[$bLength]) {
            return str_replace(
                array('\\\\', '\\\''),
                array(  '\\',   '\''),
                substr($str, $bLength + 1, -1)
            );
        } else {
            return self::parseEscapeSequences(substr($str, $bLength + 1, -1), '"');
        }
    }

    /**
     * Parses escape sequences in strings (all string types apart from single quoted).
     *
     * @param string      $str   String without quotes
     * @param null|string $quote Quote type
     *
     * @return string String with escape sequences parsed
     */
    public static function parseEscapeSequences($str, $quote) {
        if (null !== $quote) {
            $str = str_replace('\\' . $quote, $quote, $str);
        }

        return preg_replace_callback(
            '~\\\\([\\\\$nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3})~',
            array(__CLASS__, 'parseCallback'),
            $str
        );
    }

    public static function parseCallback($matches) {
        $str = $matches[1];

        if (isset(self::$replacements[$str])) {
            return self::$replacements[$str];
        } elseif ('x' === $str[0] || 'X' === $str[0]) {
            return chr(hexdec($str));
        } else {
            return chr(octdec($str));
        }
    }

    /**
     * Parses a constant doc string.
     *
     * @param string $startToken Doc string start token content (<<<SMTHG)
     * @param string $str        String token content
     *
     * @return string Parsed string
     */
    public static function parseDocString($startToken, $str) {
        // strip last newline (thanks tokenizer for sticking it into the string!)
        $str = preg_replace('~(\r\n|\n|\r)$~', '', $str);

        // nowdoc string
        if (false !== strpos($startToken, '\'')) {
            return $str;
        }

        return self::parseEscapeSequences($str, null);
    }
}<?php

/**
 * @property array $parts Encaps list
 */
class PHPParser_Node_Scalar_Encapsed extends PHPParser_Node_Scalar
{
    /**
     * Constructs an encapsed string node.
     *
     * @param array $parts      Encaps list
     * @param array $attributes Additional attributes
     */
    public function __construct(array $parts = array(), array $attributes = array()) {
        parent::__construct(
            array(
                'parts' => $parts
            ),
            $attributes
        );
    }
}<?php

class PHPParser_Node_Scalar_ClassConst extends PHPParser_Node_Scalar
{
    /**
     * Constructs a __CLASS__ const node
     *
     * @param array $attributes Additional attributes
     */
    public function __construct(array $attributes = array()) {
        parent::__construct(array(), $attributes);
    }
}<?php

class PHPParser_Node_Scalar_LineConst extends PHPParser_Node_Scalar
{
    /**
     * Constructs a __LINE__ const node
     *
     * @param array $attributes Additional attributes
     */
    public function __construct(array $attributes = array()) {
        parent::__construct(array(), $attributes);
    }
}<?php

/**
 * @property float $value Number value
 */
class PHPParser_Node_Scalar_DNumber extends PHPParser_Node_Scalar
{
    /**
     * Constructs a float number scalar node.
     *
     * @param float $value      Value of the number
     * @param array $attributes Additional attributes
     */
    public function __construct($value = 0.0, array $attributes = array()) {
        parent::__construct(
            array(
                'value' => $value
            ),
            $attributes
        );
    }

    /**
     * Parses a DNUMBER token like PHP would.
     *
     * @param string $str A string number
     *
     * @return float The parsed number
     */
    public static function parse($str) {
        // if string contains any of .eE just cast it to float
        if (false !== strpbrk($str, '.eE')) {
            return (float) $str;
        }

        // otherwise it's an integer notation that overflowed into a float
        // if it starts with 0 it's one of the special integer notations
        if ('0' === $str[0]) {
            // hex
            if ('x' === $str[1] || 'X' === $str[1]) {
                return hexdec($str);
            }

            // bin
            if ('b' === $str[1] || 'B' === $str[1]) {
                return bindec($str);
            }

            // oct
            // substr($str, 0, strcspn($str, '89')) cuts the string at the first invalid digit (8 or 9)
            // so that only the digits before that are used
            return octdec(substr($str, 0, strcspn($str, '89')));
        }

        // dec
        return (float) $str;
    }
}<?php

/**
 * @property int $value Number value
 */
class PHPParser_Node_Scalar_LNumber extends PHPParser_Node_Scalar
{
    /**
     * Constructs an integer number scalar node.
     *
     * @param int   $value      Value of the number
     * @param array $attributes Additional attributes
     */
    public function __construct($value = 0, array $attributes = array()) {
        parent::__construct(
            array(
                'value' => $value
            ),
            $attributes
        );
    }

    /**
     * Parses an LNUMBER token (dec, hex, oct and bin notations) like PHP would.
     *
     * @param string $str A string number
     *
     * @return int The parsed number
     */
    public static function parse($str) {
        // handle plain 0 specially
        if ('0' === $str) {
            return 0;
        }

        // if first char is 0 (and number isn't 0) it's a special syntax
        if ('0' === $str[0]) {
            // hex
            if ('x' === $str[1] || 'X' === $str[1]) {
                return hexdec($str);
            }

            // bin
            if ('b' === $str[1] || 'B' === $str[1]) {
                return bindec($str);
            }

            // oct (intval instead of octdec to get proper cutting behavior with malformed numbers)
            return intval($str, 8);
        }

        // dec
        return (int) $str;
    }
}<?php

class PHPParser_Node_Scalar_FuncConst extends PHPParser_Node_Scalar
{
    /**
     * Constructs a __FUNCTION__ const node
     *
     * @param array $attributes Additional attributes
     */
    public function __construct(array $attributes = array()) {
        parent::__construct(array(), $attributes);
    }
}<?php

class PHPParser_Node_Scalar_FileConst extends PHPParser_Node_Scalar
{
    /**
     * Constructs a __FILE__ const node
     *
     * @param array $attributes Additional attributes
     */
    public function __construct(array $attributes = array()) {
        parent::__construct(array(), $attributes);
    }
}<?php

class PHPParser_Node_Scalar_DirConst extends PHPParser_Node_Scalar
{
    /**
     * Constructs a __DIR__ const node
     *
     * @param array $attributes Additional attributes
     */
    public function __construct(array $attributes = array()) {
        parent::__construct(array(), $attributes);
    }
}<?php

class PHPParser_Node_Scalar_TraitConst extends PHPParser_Node_Scalar
{
    /**
     * Constructs a __TRAIT__ const node
     *
     * @param array $attributes Additional attributes
     */
    public function __construct(array $attributes = array()) {
        parent::__construct(array(), $attributes);
    }
}<?php

class PHPParser_Node_Scalar_NSConst extends PHPParser_Node_Scalar
{
    /**
     * Constructs a __NAMESPACE__ const node
     *
     * @param array $attributes Additional attributes
     */
    public function __construct(array $attributes = array()) {
        parent::__construct(array(), $attributes);
    }
}<?php

class PHPParser_Node_Scalar_MethodConst extends PHPParser_Node_Scalar
{
    /**
     * Constructs a __METHOD__ const node
     *
     * @param array $attributes Additional attributes
     */
    public function __construct(array $attributes = array()) {
        parent::__construct(array(), $attributes);
    }
}<?php

interface PHPParser_Unserializer
{
    /**
     * Unserializes a string in some format into a node tree.
     *
     * @param string $string Serialized string
     *
     * @return array Statements
     */
    public function unserialize($string);
}
<?php

class PHPParser_Serializer_XML implements PHPParser_Serializer
{
    protected $writer;

    /**
     * Constructs a XML serializer.
     */
    public function __construct() {
        $this->writer = new XMLWriter;
        $this->writer->openMemory();
        $this->writer->setIndent(true);
    }

    public function serialize(array $nodes) {
        $this->writer->flush();
        $this->writer->startDocument('1.0', 'UTF-8');

        $this->writer->startElement('AST');
        $this->writer->writeAttribute('xmlns:node',      'http://nikic.github.com/PHPParser/XML/node');
        $this->writer->writeAttribute('xmlns:subNode',   'http://nikic.github.com/PHPParser/XML/subNode');
        $this->writer->writeAttribute('xmlns:attribute', 'http://nikic.github.com/PHPParser/XML/attribute');
        $this->writer->writeAttribute('xmlns:scalar',    'http://nikic.github.com/PHPParser/XML/scalar');

        $this->_serialize($nodes);

        $this->writer->endElement();

        return $this->writer->outputMemory();
    }

    protected function _serialize($node) {
        if ($node instanceof PHPParser_Node) {
            $this->writer->startElement('node:' . $node->getType());

            foreach ($node->getAttributes() as $name => $value) {
                $this->writer->startElement('attribute:' . $name);
                $this->_serialize($value);
                $this->writer->endElement();
            }

            foreach ($node as $name => $subNode) {
                $this->writer->startElement('subNode:' . $name);
                $this->_serialize($subNode);
                $this->writer->endElement();
            }

            $this->writer->endElement();
        } elseif ($node instanceof PHPParser_Comment) {
            $this->writer->startElement('comment');
            $this->writer->writeAttribute('isDocComment', $node instanceof PHPParser_Comment_Doc ? 'true' : 'false');
            $this->writer->writeAttribute('line', $node->getLine());
            $this->writer->text($node->getText());
            $this->writer->endElement();
        } elseif (is_array($node)) {
            $this->writer->startElement('scalar:array');
            foreach ($node as $subNode) {
                $this->_serialize($subNode);
            }
            $this->writer->endElement();
        } elseif (is_string($node)) {
            $this->writer->writeElement('scalar:string', $node);
        } elseif (is_int($node)) {
            $this->writer->writeElement('scalar:int', $node);
        } elseif (is_float($node)) {
            $this->writer->writeElement('scalar:float', $node);
        } elseif (true === $node) {
            $this->writer->writeElement('scalar:true');
        } elseif (false === $node) {
            $this->writer->writeElement('scalar:false');
        } elseif (null === $node) {
            $this->writer->writeElement('scalar:null');
        } else {
            throw new InvalidArgumentException('Unexpected node type');
        }
    }
}<?php

class PHPParser_Lexer
{
    protected $code;
    protected $tokens;
    protected $pos;
    protected $line;

    protected $tokenMap;
    protected $dropTokens;

    /**
     * Creates a Lexer.
     */
    public function __construct() {
        // map from internal tokens to PHPParser tokens
        $this->tokenMap = $this->createTokenMap();

        // map of tokens to drop while lexing (the map is only used for isset lookup,
        // that's why the value is simply set to 1; the value is never actually used.)
        $this->dropTokens = array_fill_keys(array(T_WHITESPACE, T_OPEN_TAG), 1);
    }

    /**
     * Initializes the lexer for lexing the provided source code.
     *
     * @param string $code The source code to lex
     *
     * @throws PHPParser_Error on lexing errors (unterminated comment or unexpected character)
     */
    public function startLexing($code) {
        $this->resetErrors();
        $this->tokens = @token_get_all($code);
        $this->handleErrors();

        $this->code = $code; // keep the code around for __halt_compiler() handling
        $this->pos  = -1;
        $this->line =  1;
    }

    protected function resetErrors() {
        // clear error_get_last() by forcing an undefined variable error
        @$undefinedVariable;
    }

    protected function handleErrors() {
        $error = error_get_last();

        if (preg_match(
            '~^Unterminated comment starting line ([0-9]+)$~',
            $error['message'], $matches
        )) {
            throw new PHPParser_Error('Unterminated comment', $matches[1]);
        }

        if (preg_match(
            '~^Unexpected character in input:  \'(.)\' \(ASCII=([0-9]+)\)~s',
            $error['message'], $matches
        )) {
            throw new PHPParser_Error(sprintf(
                'Unexpected character "%s" (ASCII %d)',
                $matches[1], $matches[2]
            ));
        }

        // PHP cuts error message after null byte, so need special case
        if (preg_match('~^Unexpected character in input:  \'$~', $error['message'])) {
            throw new PHPParser_Error('Unexpected null byte');
        }
    }

    /**
     * Fetches the next token.
     *
     * @param mixed $value           Variable to store token content in
     * @param mixed $startAttributes Variable to store start attributes in
     * @param mixed $endAttributes   Variable to store end attributes in
     *
     * @return int Token id
     */
    public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) {
        $startAttributes = array();
        $endAttributes   = array();

        while (isset($this->tokens[++$this->pos])) {
            $token = $this->tokens[$this->pos];

            if (is_string($token)) {
                $startAttributes['startLine'] = $this->line;
                $endAttributes['endLine']     = $this->line;

                // bug in token_get_all
                if ('b"' === $token) {
                    $value = 'b"';
                    return ord('"');
                } else {
                    $value = $token;
                    return ord($token);
                }
            } else {
                $this->line += substr_count($token[1], "\n");

                if (T_COMMENT === $token[0]) {
                    $startAttributes['comments'][] = new PHPParser_Comment($token[1], $token[2]);
                } elseif (T_DOC_COMMENT === $token[0]) {
                    $startAttributes['comments'][] = new PHPParser_Comment_Doc($token[1], $token[2]);
                } elseif (!isset($this->dropTokens[$token[0]])) {
                    $value = $token[1];
                    $startAttributes['startLine'] = $token[2];
                    $endAttributes['endLine']     = $this->line;

                    return $this->tokenMap[$token[0]];
                }
            }
        }

        $startAttributes['startLine'] = $this->line;

        // 0 is the EOF token
        return 0;
    }

    /**
     * Handles __halt_compiler() by returning the text after it.
     *
     * @return string Remaining text
     */
    public function handleHaltCompiler() {
        // get the length of the text before the T_HALT_COMPILER token
        $textBefore = '';
        for ($i = 0; $i <= $this->pos; ++$i) {
            if (is_string($this->tokens[$i])) {
                $textBefore .= $this->tokens[$i];
            } else {
                $textBefore .= $this->tokens[$i][1];
            }
        }

        // text after T_HALT_COMPILER, still including ();
        $textAfter = substr($this->code, strlen($textBefore));

        // ensure that it is followed by ();
        // this simplifies the situation, by not allowing any comments
        // in between of the tokens.
        if (!preg_match('~\s*\(\s*\)\s*(?:;|\?>\r?\n?)~', $textAfter, $matches)) {
            throw new PHPParser_Error('__halt_compiler must be followed by "();"');
        }

        // prevent the lexer from returning any further tokens
        $this->pos = count($this->tokens);

        // return with (); removed
        return (string) substr($textAfter, strlen($matches[0])); // (string) converts false to ''
    }

    /**
     * Creates the token map.
     *
     * The token map maps the PHP internal token identifiers
     * to the identifiers used by the Parser. Additionally it
     * maps T_OPEN_TAG_WITH_ECHO to T_ECHO and T_CLOSE_TAG to ';'.
     *
     * @return array The token map
     */
    protected function createTokenMap() {
        $tokenMap = array();

        // 256 is the minimum possible token number, as everything below
        // it is an ASCII value
        for ($i = 256; $i < 1000; ++$i) {
            // T_DOUBLE_COLON is equivalent to T_PAAMAYIM_NEKUDOTAYIM
            if (T_DOUBLE_COLON === $i) {
                $tokenMap[$i] = PHPParser_Parser::T_PAAMAYIM_NEKUDOTAYIM;
            // T_OPEN_TAG_WITH_ECHO with dropped T_OPEN_TAG results in T_ECHO
            } elseif(T_OPEN_TAG_WITH_ECHO === $i) {
                $tokenMap[$i] = PHPParser_Parser::T_ECHO;
            // T_CLOSE_TAG is equivalent to ';'
            } elseif(T_CLOSE_TAG === $i) {
                $tokenMap[$i] = ord(';');
            // and the others can be mapped directly
            } elseif ('UNKNOWN' !== ($name = token_name($i))
                      && defined($name = 'PHPParser_Parser::' . $name)
            ) {
                $tokenMap[$i] = constant($name);
            }
        }

        return $tokenMap;
    }
}<?php

class PHPParser_TemplateLoader
{
    protected $parser;
    protected $baseDir;
    protected $suffix;

    /**
     * Constructs a filesystem template loader.
     *
     * The templates are loaded from {baseDir}/{name}{suffix}.
     *
     * @param PHPParser_Parser $parser  A PHP parser instance
     * @param string           $baseDir The base directory to load templates from
     * @param string           $suffix  An optional suffix to append after the template name
     */
    public function __construct(PHPParser_Parser $parser, $baseDir, $suffix = '') {
        if (!is_dir($baseDir)) {
            throw new InvalidArgumentException(
                sprintf('The specified base directory "%s" does not exist', $baseDir)
            );
        }

        $this->parser  = $parser;
        $this->baseDir = $baseDir;
        $this->suffix  = $suffix;
    }

    /**
     * Loads the template with the specified name.
     *
     * @param string $name The name of template
     *
     * @return PHPParser_Template The loaded template
     */
    public function load($name) {
        $file = $this->baseDir . '/' . $name . $this->suffix;

        if (!is_file($file)) {
            throw new InvalidArgumentException(
                sprintf('The file "%s" does not exist', $file)
            );
        }

        return new PHPParser_Template($this->parser, file_get_contents($file));
    }
}<?php

class PHPParser_PrettyPrinter_Default extends PHPParser_PrettyPrinterAbstract
{
    // Special nodes

    public function pParam(PHPParser_Node_Param $node) {
        return ($node->type ? (is_string($node->type) ? $node->type : $this->p($node->type)) . ' ' : '')
             . ($node->byRef ? '&' : '')
             . '$' . $node->name
             . ($node->default ? ' = ' . $this->p($node->default) : '');
    }

    public function pArg(PHPParser_Node_Arg $node) {
        return ($node->byRef ? '&' : '') . $this->p($node->value);
    }

    public function pConst(PHPParser_Node_Const $node) {
        return $node->name . ' = ' . $this->p($node->value);
    }

    // Names

    public function pName(PHPParser_Node_Name $node) {
        return implode('\\', $node->parts);
    }

    public function pName_FullyQualified(PHPParser_Node_Name_FullyQualified $node) {
        return '\\' . implode('\\', $node->parts);
    }

    public function pName_Relative(PHPParser_Node_Name_Relative $node) {
        return 'namespace\\' . implode('\\', $node->parts);
    }

    // Magic Constants

    public function pScalar_ClassConst(PHPParser_Node_Scalar_ClassConst $node) {
        return '__CLASS__';
    }

    public function pScalar_TraitConst(PHPParser_Node_Scalar_TraitConst $node) {
        return '__TRAIT__';
    }

    public function pScalar_DirConst(PHPParser_Node_Scalar_DirConst $node) {
        return '__DIR__';
    }

    public function pScalar_FileConst(PHPParser_Node_Scalar_FileConst $node) {
        return '__FILE__';
    }

    public function pScalar_FuncConst(PHPParser_Node_Scalar_FuncConst $node) {
        return '__FUNCTION__';
    }

    public function pScalar_LineConst(PHPParser_Node_Scalar_LineConst $node) {
        return '__LINE__';
    }

    public function pScalar_MethodConst(PHPParser_Node_Scalar_MethodConst $node) {
        return '__METHOD__';
    }

    public function pScalar_NSConst(PHPParser_Node_Scalar_NSConst $node) {
        return '__NAMESPACE__';
    }

    // Scalars

    public function pScalar_String(PHPParser_Node_Scalar_String $node) {
        return '\'' . $this->pNoIndent(addcslashes($node->value, '\'\\')) . '\'';
    }

    public function pScalar_Encapsed(PHPParser_Node_Scalar_Encapsed $node) {
        return '"' . $this->pEncapsList($node->parts, '"') . '"';
    }

    public function pScalar_LNumber(PHPParser_Node_Scalar_LNumber $node) {
        return (string) $node->value;
    }

    public function pScalar_DNumber(PHPParser_Node_Scalar_DNumber $node) {
        $stringValue = (string) $node->value;

        // ensure that number is really printed as float
        return ctype_digit($stringValue) ? $stringValue . '.0' : $stringValue;
    }

    // Assignments

    public function pExpr_Assign(PHPParser_Node_Expr_Assign $node) {
        return $this->pInfixOp('Expr_Assign', $node->var, ' = ', $node->expr);
    }

    public function pExpr_AssignRef(PHPParser_Node_Expr_AssignRef $node) {
        return $this->pInfixOp('Expr_AssignRef', $node->var, ' =& ', $node->expr);
    }

    public function pExpr_AssignPlus(PHPParser_Node_Expr_AssignPlus $node) {
        return $this->pInfixOp('Expr_AssignPlus', $node->var, ' += ', $node->expr);
    }

    public function pExpr_AssignMinus(PHPParser_Node_Expr_AssignMinus $node) {
        return $this->pInfixOp('Expr_AssignMinus', $node->var, ' -= ', $node->expr);
    }

    public function pExpr_AssignMul(PHPParser_Node_Expr_AssignMul $node) {
        return $this->pInfixOp('Expr_AssignMul', $node->var, ' *= ', $node->expr);
    }

    public function pExpr_AssignDiv(PHPParser_Node_Expr_AssignDiv $node) {
        return $this->pInfixOp('Expr_AssignDiv', $node->var, ' /= ', $node->expr);
    }

    public function pExpr_AssignConcat(PHPParser_Node_Expr_AssignConcat $node) {
        return $this->pInfixOp('Expr_AssignConcat', $node->var, ' .= ', $node->expr);
    }

    public function pExpr_AssignMod(PHPParser_Node_Expr_AssignMod $node) {
        return $this->pInfixOp('Expr_AssignMod', $node->var, ' %= ', $node->expr);
    }

    public function pExpr_AssignBitwiseAnd(PHPParser_Node_Expr_AssignBitwiseAnd $node) {
        return $this->pInfixOp('Expr_AssignBitwiseAnd', $node->var, ' &= ', $node->expr);
    }

    public function pExpr_AssignBitwiseOr(PHPParser_Node_Expr_AssignBitwiseOr $node) {
        return $this->pInfixOp('Expr_AssignBitwiseOr', $node->var, ' |= ', $node->expr);
    }

    public function pExpr_AssignBitwiseXor(PHPParser_Node_Expr_AssignBitwiseXor $node) {
        return $this->pInfixOp('Expr_AssignBitwiseXor', $node->var, ' ^= ', $node->expr);
    }

    public function pExpr_AssignShiftLeft(PHPParser_Node_Expr_AssignShiftLeft $node) {
        return $this->pInfixOp('Expr_AssignShiftLeft', $node->var, ' <<= ', $node->expr);
    }

    public function pExpr_AssignShiftRight(PHPParser_Node_Expr_AssignShiftRight $node) {
        return $this->pInfixOp('Expr_AssignShiftRight', $node->var, ' >>= ', $node->expr);
    }

    // Binary expressions

    public function pExpr_Plus(PHPParser_Node_Expr_Plus $node) {
        return $this->pInfixOp('Expr_Plus', $node->left, ' + ', $node->right);
    }

    public function pExpr_Minus(PHPParser_Node_Expr_Minus $node) {
        return $this->pInfixOp('Expr_Minus', $node->left, ' - ', $node->right);
    }

    public function pExpr_Mul(PHPParser_Node_Expr_Mul $node) {
        return $this->pInfixOp('Expr_Mul', $node->left, ' * ', $node->right);
    }

    public function pExpr_Div(PHPParser_Node_Expr_Div $node) {
        return $this->pInfixOp('Expr_Div', $node->left, ' / ', $node->right);
    }

    public function pExpr_Concat(PHPParser_Node_Expr_Concat $node) {
        return $this->pInfixOp('Expr_Concat', $node->left, ' . ', $node->right);
    }

    public function pExpr_Mod(PHPParser_Node_Expr_Mod $node) {
        return $this->pInfixOp('Expr_Mod', $node->left, ' % ', $node->right);
    }

    public function pExpr_BooleanAnd(PHPParser_Node_Expr_BooleanAnd $node) {
        return $this->pInfixOp('Expr_BooleanAnd', $node->left, ' && ', $node->right);
    }

    public function pExpr_BooleanOr(PHPParser_Node_Expr_BooleanOr $node) {
        return $this->pInfixOp('Expr_BooleanOr', $node->left, ' || ', $node->right);
    }

    public function pExpr_BitwiseAnd(PHPParser_Node_Expr_BitwiseAnd $node) {
        return $this->pInfixOp('Expr_BitwiseAnd', $node->left, ' & ', $node->right);
    }

    public function pExpr_BitwiseOr(PHPParser_Node_Expr_BitwiseOr $node) {
        return $this->pInfixOp('Expr_BitwiseOr', $node->left, ' | ', $node->right);
    }

    public function pExpr_BitwiseXor(PHPParser_Node_Expr_BitwiseXor $node) {
        return $this->pInfixOp('Expr_BitwiseXor', $node->left, ' ^ ', $node->right);
    }

    public function pExpr_ShiftLeft(PHPParser_Node_Expr_ShiftLeft $node) {
        return $this->pInfixOp('Expr_ShiftLeft', $node->left, ' << ', $node->right);
    }

    public function pExpr_ShiftRight(PHPParser_Node_Expr_ShiftRight $node) {
        return $this->pInfixOp('Expr_ShiftRight', $node->left, ' >> ', $node->right);
    }

    public function pExpr_LogicalAnd(PHPParser_Node_Expr_LogicalAnd $node) {
        return $this->pInfixOp('Expr_LogicalAnd', $node->left, ' and ', $node->right);
    }

    public function pExpr_LogicalOr(PHPParser_Node_Expr_LogicalOr $node) {
        return $this->pInfixOp('Expr_LogicalOr', $node->left, ' or ', $node->right);
    }

    public function pExpr_LogicalXor(PHPParser_Node_Expr_LogicalXor $node) {
        return $this->pInfixOp('Expr_LogicalXor', $node->left, ' xor ', $node->right);
    }

    public function pExpr_Equal(PHPParser_Node_Expr_Equal $node) {
        return $this->pInfixOp('Expr_Equal', $node->left, ' == ', $node->right);
    }

    public function pExpr_NotEqual(PHPParser_Node_Expr_NotEqual $node) {
        return $this->pInfixOp('Expr_NotEqual', $node->left, ' != ', $node->right);
    }

    public function pExpr_Identical(PHPParser_Node_Expr_Identical $node) {
        return $this->pInfixOp('Expr_Identical', $node->left, ' === ', $node->right);
    }

    public function pExpr_NotIdentical(PHPParser_Node_Expr_NotIdentical $node) {
        return $this->pInfixOp('Expr_NotIdentical', $node->left, ' !== ', $node->right);
    }

    public function pExpr_Greater(PHPParser_Node_Expr_Greater $node) {
        return $this->pInfixOp('Expr_Greater', $node->left, ' > ', $node->right);
    }

    public function pExpr_GreaterOrEqual(PHPParser_Node_Expr_GreaterOrEqual $node) {
        return $this->pInfixOp('Expr_GreaterOrEqual', $node->left, ' >= ', $node->right);
    }

    public function pExpr_Smaller(PHPParser_Node_Expr_Smaller $node) {
        return $this->pInfixOp('Expr_Smaller', $node->left, ' < ', $node->right);
    }

    public function pExpr_SmallerOrEqual(PHPParser_Node_Expr_SmallerOrEqual $node) {
        return $this->pInfixOp('Expr_SmallerOrEqual', $node->left, ' <= ', $node->right);
    }

    public function pExpr_Instanceof(PHPParser_Node_Expr_Instanceof $node) {
        return $this->pInfixOp('Expr_Instanceof', $node->expr, ' instanceof ', $node->class);
    }

    // Unary expressions

    public function pExpr_BooleanNot(PHPParser_Node_Expr_BooleanNot $node) {
        return $this->pPrefixOp('Expr_BooleanNot', '!', $node->expr);
    }

    public function pExpr_BitwiseNot(PHPParser_Node_Expr_BitwiseNot $node) {
        return $this->pPrefixOp('Expr_BitwiseNot', '~', $node->expr);
    }

    public function pExpr_UnaryMinus(PHPParser_Node_Expr_UnaryMinus $node) {
        return $this->pPrefixOp('Expr_UnaryMinus', '-', $node->expr);
    }

    public function pExpr_UnaryPlus(PHPParser_Node_Expr_UnaryPlus $node) {
        return $this->pPrefixOp('Expr_UnaryPlus', '+', $node->expr);
    }

    public function pExpr_PreInc(PHPParser_Node_Expr_PreInc $node) {
        return $this->pPrefixOp('Expr_PreInc', '++', $node->var);
    }

    public function pExpr_PreDec(PHPParser_Node_Expr_PreDec $node) {
        return $this->pPrefixOp('Expr_PreDec', '--', $node->var);
    }

    public function pExpr_PostInc(PHPParser_Node_Expr_PostInc $node) {
        return $this->pPostfixOp('Expr_PostInc', $node->var, '++');
    }

    public function pExpr_PostDec(PHPParser_Node_Expr_PostDec $node) {
        return $this->pPostfixOp('Expr_PostDec', $node->var, '--');
    }

    public function pExpr_ErrorSuppress(PHPParser_Node_Expr_ErrorSuppress $node) {
        return $this->pPrefixOp('Expr_ErrorSuppress', '@', $node->expr);
    }

    // Casts

    public function pExpr_Cast_Int(PHPParser_Node_Expr_Cast_Int $node) {
        return $this->pPrefixOp('Expr_Cast_Int', '(int) ', $node->expr);
    }

    public function pExpr_Cast_Double(PHPParser_Node_Expr_Cast_Double $node) {
        return $this->pPrefixOp('Expr_Cast_Double', '(double) ', $node->expr);
    }

    public function pExpr_Cast_String(PHPParser_Node_Expr_Cast_String $node) {
        return $this->pPrefixOp('Expr_Cast_String', '(string) ', $node->expr);
    }

    public function pExpr_Cast_Array(PHPParser_Node_Expr_Cast_Array $node) {
        return $this->pPrefixOp('Expr_Cast_Array', '(array) ', $node->expr);
    }

    public function pExpr_Cast_Object(PHPParser_Node_Expr_Cast_Object $node) {
        return $this->pPrefixOp('Expr_Cast_Object', '(object) ', $node->expr);
    }

    public function pExpr_Cast_Bool(PHPParser_Node_Expr_Cast_Bool $node) {
        return $this->pPrefixOp('Expr_Cast_Bool', '(bool) ', $node->expr);
    }

    public function pExpr_Cast_Unset(PHPParser_Node_Expr_Cast_Unset $node) {
        return $this->pPrefixOp('Expr_Cast_Unset', '(unset) ', $node->expr);
    }

    // Function calls and similar constructs

    public function pExpr_FuncCall(PHPParser_Node_Expr_FuncCall $node) {
        return $this->p($node->name) . '(' . $this->pCommaSeparated($node->args) . ')';
    }

    public function pExpr_MethodCall(PHPParser_Node_Expr_MethodCall $node) {
        return $this->pVarOrNewExpr($node->var) . '->' . $this->pObjectProperty($node->name)
             . '(' . $this->pCommaSeparated($node->args) . ')';
    }

    public function pExpr_StaticCall(PHPParser_Node_Expr_StaticCall $node) {
        return $this->p($node->class) . '::'
             . ($node->name instanceof PHPParser_Node_Expr
                ? ($node->name instanceof PHPParser_Node_Expr_Variable
                   || $node->name instanceof PHPParser_Node_Expr_ArrayDimFetch
                   ? $this->p($node->name)
                   : '{' . $this->p($node->name) . '}')
                : $node->name)
             . '(' . $this->pCommaSeparated($node->args) . ')';
    }

    public function pExpr_Empty(PHPParser_Node_Expr_Empty $node) {
        return 'empty(' . $this->p($node->expr) . ')';
    }

    public function pExpr_Isset(PHPParser_Node_Expr_Isset $node) {
        return 'isset(' . $this->pCommaSeparated($node->vars) . ')';
    }

    public function pExpr_Print(PHPParser_Node_Expr_Print $node) {
        return 'print ' . $this->p($node->expr);
    }

    public function pExpr_Eval(PHPParser_Node_Expr_Eval $node) {
        return 'eval(' . $this->p($node->expr) . ')';
    }

    public function pExpr_Include(PHPParser_Node_Expr_Include $node) {
        static $map = array(
            PHPParser_Node_Expr_Include::TYPE_INCLUDE      => 'include',
            PHPParser_Node_Expr_Include::TYPE_INCLUDE_ONCE => 'include_once',
            PHPParser_Node_Expr_Include::TYPE_REQUIRE      => 'require',
            PHPParser_Node_Expr_Include::TYPE_REQUIRE_ONCE => 'require_once',
        );

        return $map[$node->type] . ' ' . $this->p($node->expr);
    }

    public function pExpr_List(PHPParser_Node_Expr_List $node) {
        $pList = array();
        foreach ($node->vars as $var) {
            if (null === $var) {
                $pList[] = '';
            } else {
                $pList[] = $this->p($var);
            }
        }

        return 'list(' . implode(', ', $pList) . ')';
    }

    // Other

    public function pExpr_Variable(PHPParser_Node_Expr_Variable $node) {
        if ($node->name instanceof PHPParser_Node_Expr) {
            return '${' . $this->p($node->name) . '}';
        } else {
            return '$' . $node->name;
        }
    }

    public function pExpr_Array(PHPParser_Node_Expr_Array $node) {
        return 'array(' . $this->pCommaSeparated($node->items) . ')';
    }

    public function pExpr_ArrayItem(PHPParser_Node_Expr_ArrayItem $node) {
        return (null !== $node->key ? $this->p($node->key) . ' => ' : '')
             . ($node->byRef ? '&' : '') . $this->p($node->value);
    }

    public function pExpr_ArrayDimFetch(PHPParser_Node_Expr_ArrayDimFetch $node) {
        return $this->pVarOrNewExpr($node->var)
             . '[' . (null !== $node->dim ? $this->p($node->dim) : '') . ']';
    }

    public function pExpr_ConstFetch(PHPParser_Node_Expr_ConstFetch $node) {
        return $this->p($node->name);
    }

    public function pExpr_ClassConstFetch(PHPParser_Node_Expr_ClassConstFetch $node) {
        return $this->p($node->class) . '::' . $node->name;
    }

    public function pExpr_PropertyFetch(PHPParser_Node_Expr_PropertyFetch $node) {
        return $this->pVarOrNewExpr($node->var) . '->' . $this->pObjectProperty($node->name);
    }

    public function pExpr_StaticPropertyFetch(PHPParser_Node_Expr_StaticPropertyFetch $node) {
        return $this->p($node->class) . '::$' . $this->pObjectProperty($node->name);
    }

    public function pExpr_ShellExec(PHPParser_Node_Expr_ShellExec $node) {
        return '`' . $this->pEncapsList($node->parts, '`') . '`';
    }

    public function pExpr_Closure(PHPParser_Node_Expr_Closure $node) {
        return ($node->static ? 'static ' : '')
             . 'function ' . ($node->byRef ? '&' : '')
             . '(' . $this->pCommaSeparated($node->params) . ')'
             . (!empty($node->uses) ? ' use(' . $this->pCommaSeparated($node->uses) . ')': '')
             . ' {' . "\n" . $this->pStmts($node->stmts) . "\n" . '}';
    }

    public function pExpr_ClosureUse(PHPParser_Node_Expr_ClosureUse $node) {
        return ($node->byRef ? '&' : '') . '$' . $node->var;
    }

    public function pExpr_New(PHPParser_Node_Expr_New $node) {
        return 'new ' . $this->p($node->class) . '(' . $this->pCommaSeparated($node->args) . ')';
    }

    public function pExpr_Clone(PHPParser_Node_Expr_Clone $node) {
        return 'clone ' . $this->p($node->expr);
    }

    public function pExpr_Ternary(PHPParser_Node_Expr_Ternary $node) {
        // a bit of cheating: we treat the ternary as a binary op where the ?...: part is the operator.
        // this is okay because the part between ? and : never needs parentheses.
        return $this->pInfixOp('Expr_Ternary',
            $node->cond, ' ?' . (null !== $node->if ? ' ' . $this->p($node->if) . ' ' : '') . ': ', $node->else
        );
    }

    public function pExpr_Exit(PHPParser_Node_Expr_Exit $node) {
        return 'die' . (null !== $node->expr ? '(' . $this->p($node->expr) . ')' : '');
    }

    public function pExpr_Yield(PHPParser_Node_Expr_Yield $node) {
        if ($node->value === null) {
            return 'yield';
        } else {
            // this is a bit ugly, but currently there is no way to detect whether the parentheses are necessary
            return '(yield '
                 . ($node->key !== null ? $this->p($node->key) . ' => ' : '')
                 . $this->p($node->value)
                 . ')';
        }
    }

    // Declarations

    public function pStmt_Namespace(PHPParser_Node_Stmt_Namespace $node) {
        if ($this->canUseSemicolonNamespaces) {
            return 'namespace ' . $this->p($node->name) . ';' . "\n\n" . $this->pStmts($node->stmts, false);
        } else {
            return 'namespace' . (null !== $node->name ? ' ' . $this->p($node->name) : '')
                 . ' {' . "\n" . $this->pStmts($node->stmts) . "\n" . '}';
        }
    }

    public function pStmt_Use(PHPParser_Node_Stmt_Use $node) {
        return 'use ' . $this->pCommaSeparated($node->uses) . ';';
    }

    public function pStmt_UseUse(PHPParser_Node_Stmt_UseUse $node) {
        return $this->p($node->name)
             . ($node->name->getLast() !== $node->alias ? ' as ' . $node->alias : '');
    }

    public function pStmt_Interface(PHPParser_Node_Stmt_Interface $node) {
        return 'interface ' . $node->name
             . (!empty($node->extends) ? ' extends ' . $this->pCommaSeparated($node->extends) : '')
             . "\n" . '{' . "\n" . $this->pStmts($node->stmts) . "\n" . '}';
    }

    public function pStmt_Class(PHPParser_Node_Stmt_Class $node) {
        return $this->pModifiers($node->type)
             . 'class ' . $node->name
             . (null !== $node->extends ? ' extends ' . $this->p($node->extends) : '')
             . (!empty($node->implements) ? ' implements ' . $this->pCommaSeparated($node->implements) : '')
             . "\n" . '{' . "\n" . $this->pStmts($node->stmts) . "\n" . '}';
    }

    public function pStmt_Trait(PHPParser_Node_Stmt_Trait $node) {
        return 'trait ' . $node->name
             . "\n" . '{' . "\n" . $this->pStmts($node->stmts) . "\n" . '}';
    }

    public function pStmt_TraitUse(PHPParser_Node_Stmt_TraitUse $node) {
        return 'use ' . $this->pCommaSeparated($node->traits)
             . (empty($node->adaptations)
                ? ';'
                : ' {' . "\n" . $this->pStmts($node->adaptations) . "\n" . '}');
    }

    public function pStmt_TraitUseAdaptation_Precedence(PHPParser_Node_Stmt_TraitUseAdaptation_Precedence $node) {
        return $this->p($node->trait) . '::' . $node->method
             . ' insteadof ' . $this->pCommaSeparated($node->insteadof) . ';';
    }

    public function pStmt_TraitUseAdaptation_Alias(PHPParser_Node_Stmt_TraitUseAdaptation_Alias $node) {
        return (null !== $node->trait ? $this->p($node->trait) . '::' : '')
             . $node->method . ' as'
             . (null !== $node->newModifier ? ' ' . $this->pModifiers($node->newModifier) : '')
             . (null !== $node->newName     ? ' ' . $node->newName                        : '')
             . ';';
    }

    public function pStmt_Property(PHPParser_Node_Stmt_Property $node) {
        return $this->pModifiers($node->type) . $this->pCommaSeparated($node->props) . ';';
    }

    public function pStmt_PropertyProperty(PHPParser_Node_Stmt_PropertyProperty $node) {
        return '$' . $node->name
             . (null !== $node->default ? ' = ' . $this->p($node->default) : '');
    }

    public function pStmt_ClassMethod(PHPParser_Node_Stmt_ClassMethod $node) {
        return $this->pModifiers($node->type)
             . 'function ' . ($node->byRef ? '&' : '') . $node->name
             . '(' . $this->pCommaSeparated($node->params) . ')'
             . (null !== $node->stmts
                ? "\n" . '{' . "\n" . $this->pStmts($node->stmts) . "\n" . '}'
                : ';');
    }

    public function pStmt_ClassConst(PHPParser_Node_Stmt_ClassConst $node) {
        return 'const ' . $this->pCommaSeparated($node->consts) . ';';
    }

    public function pStmt_Function(PHPParser_Node_Stmt_Function $node) {
        return 'function ' . ($node->byRef ? '&' : '') . $node->name
             . '(' . $this->pCommaSeparated($node->params) . ')'
             . "\n" . '{' . "\n" . $this->pStmts($node->stmts) . "\n" . '}';
    }

    public function pStmt_Const(PHPParser_Node_Stmt_Const $node) {
        return 'const ' . $this->pCommaSeparated($node->consts) . ';';
    }

    public function pStmt_Declare(PHPParser_Node_Stmt_Declare $node) {
        return 'declare (' . $this->pCommaSeparated($node->declares) . ') {'
             . "\n" . $this->pStmts($node->stmts) . "\n" . '}';
    }

    public function pStmt_DeclareDeclare(PHPParser_Node_Stmt_DeclareDeclare $node) {
        return $node->key . ' = ' . $this->p($node->value);
    }

    // Control flow

    public function pStmt_If(PHPParser_Node_Stmt_If $node) {
        return 'if (' . $this->p($node->cond) . ') {'
             . "\n" . $this->pStmts($node->stmts) . "\n" . '}'
             . $this->pImplode($node->elseifs)
             . (null !== $node->else ? $this->p($node->else) : '');
    }

    public function pStmt_Elseif(PHPParser_Node_Stmt_Elseif $node) {
        return ' elseif (' . $this->p($node->cond) . ') {'
             . "\n" . $this->pStmts($node->stmts) . "\n" . '}';
    }

    public function pStmt_Else(PHPParser_Node_Stmt_Else $node) {
        return ' else {' . "\n" . $this->pStmts($node->stmts) . "\n" . '}';
    }

    public function pStmt_For(PHPParser_Node_Stmt_For $node) {
        return 'for ('
             . $this->pCommaSeparated($node->init) . ';' . (!empty($node->cond) ? ' ' : '')
             . $this->pCommaSeparated($node->cond) . ';' . (!empty($node->loop) ? ' ' : '')
             . $this->pCommaSeparated($node->loop)
             . ') {' . "\n" . $this->pStmts($node->stmts) . "\n" . '}';
    }

    public function pStmt_Foreach(PHPParser_Node_Stmt_Foreach $node) {
        return 'foreach (' . $this->p($node->expr) . ' as '
             . (null !== $node->keyVar ? $this->p($node->keyVar) . ' => ' : '')
             . ($node->byRef ? '&' : '') . $this->p($node->valueVar) . ') {'
             . "\n" . $this->pStmts($node->stmts) . "\n" . '}';
    }

    public function pStmt_While(PHPParser_Node_Stmt_While $node) {
        return 'while (' . $this->p($node->cond) . ') {'
             . "\n" . $this->pStmts($node->stmts) . "\n" . '}';
    }

    public function pStmt_Do(PHPParser_Node_Stmt_Do $node) {
        return 'do {' . "\n" . $this->pStmts($node->stmts) . "\n"
             . '} while (' . $this->p($node->cond) . ');';
    }

    public function pStmt_Switch(PHPParser_Node_Stmt_Switch $node) {
        return 'switch (' . $this->p($node->cond) . ') {'
             . "\n" . $this->pStmts($node->cases) . "\n" . '}';
    }

    public function pStmt_Case(PHPParser_Node_Stmt_Case $node) {
        return (null !== $node->cond ? 'case ' . $this->p($node->cond) : 'default') . ':'
             . ($node->stmts ? "\n" . $this->pStmts($node->stmts) : '');
    }

    public function pStmt_TryCatch(PHPParser_Node_Stmt_TryCatch $node) {
        return 'try {' . "\n" . $this->pStmts($node->stmts) . "\n" . '}'
             . $this->pImplode($node->catches)
             . ($node->finallyStmts !== null
                ? ' finally {' . "\n" . $this->pStmts($node->finallyStmts) . "\n" . '}'
                : '');
    }

    public function pStmt_Catch(PHPParser_Node_Stmt_Catch $node) {
        return ' catch (' . $this->p($node->type) . ' $' . $node->var . ') {'
             . "\n" . $this->pStmts($node->stmts) . "\n" . '}';
    }

    public function pStmt_Break(PHPParser_Node_Stmt_Break $node) {
        return 'break' . ($node->num !== null ? ' ' . $this->p($node->num) : '') . ';';
    }

    public function pStmt_Continue(PHPParser_Node_Stmt_Continue $node) {
        return 'continue' . ($node->num !== null ? ' ' . $this->p($node->num) : '') . ';';
    }

    public function pStmt_Return(PHPParser_Node_Stmt_Return $node) {
        return 'return' . (null !== $node->expr ? ' ' . $this->p($node->expr) : '') . ';';
    }

    public function pStmt_Throw(PHPParser_Node_Stmt_Throw $node) {
        return 'throw ' . $this->p($node->expr) . ';';
    }

    public function pStmt_Label(PHPParser_Node_Stmt_Label $node) {
        return $node->name . ':';
    }

    public function pStmt_Goto(PHPParser_Node_Stmt_Goto $node) {
        return 'goto ' . $node->name . ';';
    }

    // Other

    public function pStmt_Echo(PHPParser_Node_Stmt_Echo $node) {
        return 'echo ' . $this->pCommaSeparated($node->exprs) . ';';
    }

    public function pStmt_Static(PHPParser_Node_Stmt_Static $node) {
        return 'static ' . $this->pCommaSeparated($node->vars) . ';';
    }

    public function pStmt_Global(PHPParser_Node_Stmt_Global $node) {
        return 'global ' . $this->pCommaSeparated($node->vars) . ';';
    }

    public function pStmt_StaticVar(PHPParser_Node_Stmt_StaticVar $node) {
        return '$' . $node->name
             . (null !== $node->default ? ' = ' . $this->p($node->default) : '');
    }

    public function pStmt_Unset(PHPParser_Node_Stmt_Unset $node) {
        return 'unset(' . $this->pCommaSeparated($node->vars) . ');';
    }

    public function pStmt_InlineHTML(PHPParser_Node_Stmt_InlineHTML $node) {
        return '?>' . $this->pNoIndent("\n" . $node->value) . '<?php ';
    }

    public function pStmt_HaltCompiler(PHPParser_Node_Stmt_HaltCompiler $node) {
        return '__halt_compiler();' . $node->remaining;
    }

    // Helpers

    public function pObjectProperty($node) {
        if ($node instanceof PHPParser_Node_Expr) {
            return '{' . $this->p($node) . '}';
        } else {
            return $node;
        }
    }

    public function pModifiers($modifiers) {
        return ($modifiers & PHPParser_Node_Stmt_Class::MODIFIER_PUBLIC    ? 'public '    : '')
             . ($modifiers & PHPParser_Node_Stmt_Class::MODIFIER_PROTECTED ? 'protected ' : '')
             . ($modifiers & PHPParser_Node_Stmt_Class::MODIFIER_PRIVATE   ? 'private '   : '')
             . ($modifiers & PHPParser_Node_Stmt_Class::MODIFIER_STATIC    ? 'static '    : '')
             . ($modifiers & PHPParser_Node_Stmt_Class::MODIFIER_ABSTRACT  ? 'abstract '  : '')
             . ($modifiers & PHPParser_Node_Stmt_Class::MODIFIER_FINAL     ? 'final '     : '');
    }

    public function pEncapsList(array $encapsList, $quote) {
        $return = '';
        foreach ($encapsList as $element) {
            if (is_string($element)) {
                $return .= addcslashes($element, "\n\r\t\f\v$" . $quote . "\\");
            } else {
                $return .= '{' . $this->p($element) . '}';
            }
        }

        return $return;
    }

    public function pVarOrNewExpr(PHPParser_Node $node) {
        if ($node instanceof PHPParser_Node_Expr_New) {
            return '(' . $this->p($node) . ')';
        } else {
            return $this->p($node);
        }
    }
}<?php

/**
 * This class is only retained for backwards compatibility. Use PHPParser_PrettyPrinter_Default instead.
 *
 * @deprecated
 */
class PHPParser_PrettyPrinter_Zend extends PHPParser_PrettyPrinter_Default
{
}<?php

require dirname(__FILE__) . '/PHPParser/Autoloader.php';
PHPParser_Autoloader::register();

/*
 * lcfirst() was added in PHP 5.3, so we have to emulate it for PHP 5.2.
 */
if (!function_exists('lcfirst')) {
    function lcfirst($string) {
        $string[0] = strtolower($string[0]);
        return $string;
    }
}
<?php

// autoload_classmap.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'File_Iterator' => $vendorDir . '/phpunit/php-file-iterator/File/Iterator.php',
    'File_Iterator_Facade' => $vendorDir . '/phpunit/php-file-iterator/File/Iterator/Facade.php',
    'File_Iterator_Factory' => $vendorDir . '/phpunit/php-file-iterator/File/Iterator/Factory.php',
    'Generic_Sniffs_Classes_DuplicateClassNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Classes/DuplicateClassNameSniff.php',
    'Generic_Sniffs_CodeAnalysis_EmptyStatementSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/EmptyStatementSniff.php',
    'Generic_Sniffs_CodeAnalysis_ForLoopShouldBeWhileLoopSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/ForLoopShouldBeWhileLoopSniff.php',
    'Generic_Sniffs_CodeAnalysis_ForLoopWithTestFunctionCallSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/ForLoopWithTestFunctionCallSniff.php',
    'Generic_Sniffs_CodeAnalysis_JumbledIncrementerSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/JumbledIncrementerSniff.php',
    'Generic_Sniffs_CodeAnalysis_UnconditionalIfStatementSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/UnconditionalIfStatementSniff.php',
    'Generic_Sniffs_CodeAnalysis_UnnecessaryFinalModifierSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/UnnecessaryFinalModifierSniff.php',
    'Generic_Sniffs_CodeAnalysis_UnusedFunctionParameterSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/UnusedFunctionParameterSniff.php',
    'Generic_Sniffs_CodeAnalysis_UselessOverridingMethodSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/CodeAnalysis/UselessOverridingMethodSniff.php',
    'Generic_Sniffs_Commenting_FixmeSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Commenting/FixmeSniff.php',
    'Generic_Sniffs_Commenting_TodoSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Commenting/TodoSniff.php',
    'Generic_Sniffs_ControlStructures_InlineControlStructureSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/ControlStructures/InlineControlStructureSniff.php',
    'Generic_Sniffs_Debug_CSSLintSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Debug/CSSLintSniff.php',
    'Generic_Sniffs_Debug_ClosureLinterSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Debug/ClosureLinterSniff.php',
    'Generic_Sniffs_Debug_JSHintSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Debug/JSHintSniff.php',
    'Generic_Sniffs_Files_ByteOrderMarkSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/ByteOrderMarkSniff.php',
    'Generic_Sniffs_Files_EndFileNewlineSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/EndFileNewlineSniff.php',
    'Generic_Sniffs_Files_EndFileNoNewlineSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/EndFileNoNewlineSniff.php',
    'Generic_Sniffs_Files_InlineHTMLSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/InlineHTMLSniff.php',
    'Generic_Sniffs_Files_LineEndingsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/LineEndingsSniff.php',
    'Generic_Sniffs_Files_LineLengthSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/LineLengthSniff.php',
    'Generic_Sniffs_Files_LowercasedFilenameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/LowercasedFilenameSniff.php',
    'Generic_Sniffs_Files_OneClassPerFileSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/OneClassPerFileSniff.php',
    'Generic_Sniffs_Files_OneInterfacePerFileSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Files/OneInterfacePerFileSniff.php',
    'Generic_Sniffs_Formatting_DisallowMultipleStatementsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Formatting/DisallowMultipleStatementsSniff.php',
    'Generic_Sniffs_Formatting_MultipleStatementAlignmentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Formatting/MultipleStatementAlignmentSniff.php',
    'Generic_Sniffs_Formatting_NoSpaceAfterCastSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Formatting/NoSpaceAfterCastSniff.php',
    'Generic_Sniffs_Formatting_SpaceAfterCastSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Formatting/SpaceAfterCastSniff.php',
    'Generic_Sniffs_Functions_CallTimePassByReferenceSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Functions/CallTimePassByReferenceSniff.php',
    'Generic_Sniffs_Functions_FunctionCallArgumentSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Functions/FunctionCallArgumentSpacingSniff.php',
    'Generic_Sniffs_Functions_OpeningFunctionBraceBsdAllmanSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceBsdAllmanSniff.php',
    'Generic_Sniffs_Functions_OpeningFunctionBraceKernighanRitchieSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Functions/OpeningFunctionBraceKernighanRitchieSniff.php',
    'Generic_Sniffs_Metrics_CyclomaticComplexitySniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Metrics/CyclomaticComplexitySniff.php',
    'Generic_Sniffs_Metrics_NestingLevelSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Metrics/NestingLevelSniff.php',
    'Generic_Sniffs_NamingConventions_CamelCapsFunctionNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/NamingConventions/CamelCapsFunctionNameSniff.php',
    'Generic_Sniffs_NamingConventions_ConstructorNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/NamingConventions/ConstructorNameSniff.php',
    'Generic_Sniffs_NamingConventions_UpperCaseConstantNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/NamingConventions/UpperCaseConstantNameSniff.php',
    'Generic_Sniffs_PHP_CharacterBeforePHPOpeningTagSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/CharacterBeforePHPOpeningTagSniff.php',
    'Generic_Sniffs_PHP_ClosingPHPTagSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/ClosingPHPTagSniff.php',
    'Generic_Sniffs_PHP_DeprecatedFunctionsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/DeprecatedFunctionsSniff.php',
    'Generic_Sniffs_PHP_DisallowShortOpenTagSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/DisallowShortOpenTagSniff.php',
    'Generic_Sniffs_PHP_ForbiddenFunctionsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/ForbiddenFunctionsSniff.php',
    'Generic_Sniffs_PHP_LowerCaseConstantSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/LowerCaseConstantSniff.php',
    'Generic_Sniffs_PHP_LowerCaseKeywordSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/LowerCaseKeywordSniff.php',
    'Generic_Sniffs_PHP_NoSilencedErrorsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/NoSilencedErrorsSniff.php',
    'Generic_Sniffs_PHP_SAPIUsageSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/SAPIUsageSniff.php',
    'Generic_Sniffs_PHP_UpperCaseConstantSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/PHP/UpperCaseConstantSniff.php',
    'Generic_Sniffs_Strings_UnnecessaryStringConcatSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/Strings/UnnecessaryStringConcatSniff.php',
    'Generic_Sniffs_VersionControl_SubversionPropertiesSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/VersionControl/SubversionPropertiesSniff.php',
    'Generic_Sniffs_WhiteSpace_DisallowSpaceIndentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/WhiteSpace/DisallowSpaceIndentSniff.php',
    'Generic_Sniffs_WhiteSpace_DisallowTabIndentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/WhiteSpace/DisallowTabIndentSniff.php',
    'Generic_Sniffs_WhiteSpace_ScopeIndentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Generic/Sniffs/WhiteSpace/ScopeIndentSniff.php',
    'MySource_Sniffs_CSS_BrowserSpecificStylesSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/CSS/BrowserSpecificStylesSniff.php',
    'MySource_Sniffs_Channels_ChannelExceptionSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Channels/ChannelExceptionSniff.php',
    'MySource_Sniffs_Channels_DisallowSelfActionsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Channels/DisallowSelfActionsSniff.php',
    'MySource_Sniffs_Channels_IncludeOwnSystemSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Channels/IncludeOwnSystemSniff.php',
    'MySource_Sniffs_Channels_IncludeSystemSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Channels/IncludeSystemSniff.php',
    'MySource_Sniffs_Channels_UnusedSystemSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Channels/UnusedSystemSniff.php',
    'MySource_Sniffs_Commenting_FunctionCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Commenting/FunctionCommentSniff.php',
    'MySource_Sniffs_Debug_DebugCodeSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Debug/DebugCodeSniff.php',
    'MySource_Sniffs_Debug_FirebugConsoleSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Debug/FirebugConsoleSniff.php',
    'MySource_Sniffs_Objects_AssignThisSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Objects/AssignThisSniff.php',
    'MySource_Sniffs_Objects_CreateWidgetTypeCallbackSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Objects/CreateWidgetTypeCallbackSniff.php',
    'MySource_Sniffs_Objects_DisallowNewWidgetSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Objects/DisallowNewWidgetSniff.php',
    'MySource_Sniffs_PHP_AjaxNullComparisonSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/PHP/AjaxNullComparisonSniff.php',
    'MySource_Sniffs_PHP_EvalObjectFactorySniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/PHP/EvalObjectFactorySniff.php',
    'MySource_Sniffs_PHP_GetRequestDataSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/PHP/GetRequestDataSniff.php',
    'MySource_Sniffs_PHP_ReturnFunctionValueSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/PHP/ReturnFunctionValueSniff.php',
    'MySource_Sniffs_Strings_JoinStringsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/MySource/Sniffs/Strings/JoinStringsSniff.php',
    'PEAR_Sniffs_Classes_ClassDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Classes/ClassDeclarationSniff.php',
    'PEAR_Sniffs_Commenting_ClassCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Commenting/ClassCommentSniff.php',
    'PEAR_Sniffs_Commenting_FileCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Commenting/FileCommentSniff.php',
    'PEAR_Sniffs_Commenting_FunctionCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Commenting/FunctionCommentSniff.php',
    'PEAR_Sniffs_Commenting_InlineCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Commenting/InlineCommentSniff.php',
    'PEAR_Sniffs_ControlStructures_ControlSignatureSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/ControlStructures/ControlSignatureSniff.php',
    'PEAR_Sniffs_ControlStructures_MultiLineConditionSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/ControlStructures/MultiLineConditionSniff.php',
    'PEAR_Sniffs_Files_IncludingFileSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Files/IncludingFileSniff.php',
    'PEAR_Sniffs_Formatting_MultiLineAssignmentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Formatting/MultiLineAssignmentSniff.php',
    'PEAR_Sniffs_Functions_FunctionCallSignatureSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Functions/FunctionCallSignatureSniff.php',
    'PEAR_Sniffs_Functions_FunctionDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Functions/FunctionDeclarationSniff.php',
    'PEAR_Sniffs_Functions_ValidDefaultValueSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/Functions/ValidDefaultValueSniff.php',
    'PEAR_Sniffs_NamingConventions_ValidClassNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/NamingConventions/ValidClassNameSniff.php',
    'PEAR_Sniffs_NamingConventions_ValidFunctionNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/NamingConventions/ValidFunctionNameSniff.php',
    'PEAR_Sniffs_NamingConventions_ValidVariableNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/NamingConventions/ValidVariableNameSniff.php',
    'PEAR_Sniffs_WhiteSpace_ObjectOperatorIndentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/WhiteSpace/ObjectOperatorIndentSniff.php',
    'PEAR_Sniffs_WhiteSpace_ScopeClosingBraceSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php',
    'PEAR_Sniffs_WhiteSpace_ScopeIndentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PEAR/Sniffs/WhiteSpace/ScopeIndentSniff.php',
    'PHPUnit_Extensions_GroupTestSuite' => $vendorDir . '/phpunit/phpunit/PHPUnit/Extensions/GroupTestSuite.php',
    'PHPUnit_Extensions_PhptTestCase' => $vendorDir . '/phpunit/phpunit/PHPUnit/Extensions/PhptTestCase.php',
    'PHPUnit_Extensions_PhptTestCase_Logger' => $vendorDir . '/phpunit/phpunit/PHPUnit/Extensions/PhptTestCase/Logger.php',
    'PHPUnit_Extensions_PhptTestSuite' => $vendorDir . '/phpunit/phpunit/PHPUnit/Extensions/PhptTestSuite.php',
    'PHPUnit_Extensions_RepeatedTest' => $vendorDir . '/phpunit/phpunit/PHPUnit/Extensions/RepeatedTest.php',
    'PHPUnit_Extensions_TestDecorator' => $vendorDir . '/phpunit/phpunit/PHPUnit/Extensions/TestDecorator.php',
    'PHPUnit_Extensions_TicketListener' => $vendorDir . '/phpunit/phpunit/PHPUnit/Extensions/TicketListener.php',
    'PHPUnit_Framework_Assert' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Assert.php',
    'PHPUnit_Framework_AssertionFailedError' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/AssertionFailedError.php',
    'PHPUnit_Framework_Comparator' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Comparator.php',
    'PHPUnit_Framework_ComparatorFactory' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/ComparatorFactory.php',
    'PHPUnit_Framework_Comparator_Array' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Comparator/Array.php',
    'PHPUnit_Framework_Comparator_DOMDocument' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Comparator/DOMDocument.php',
    'PHPUnit_Framework_Comparator_Double' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Comparator/Double.php',
    'PHPUnit_Framework_Comparator_Exception' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Comparator/Exception.php',
    'PHPUnit_Framework_Comparator_MockObject' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Comparator/MockObject.php',
    'PHPUnit_Framework_Comparator_Numeric' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Comparator/Numeric.php',
    'PHPUnit_Framework_Comparator_Object' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Comparator/Object.php',
    'PHPUnit_Framework_Comparator_Resource' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Comparator/Resource.php',
    'PHPUnit_Framework_Comparator_Scalar' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Comparator/Scalar.php',
    'PHPUnit_Framework_Comparator_SplObjectStorage' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Comparator/SplObjectStorage.php',
    'PHPUnit_Framework_Comparator_Type' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Comparator/Type.php',
    'PHPUnit_Framework_ComparisonFailure' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/ComparisonFailure.php',
    'PHPUnit_Framework_Constraint' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint.php',
    'PHPUnit_Framework_Constraint_And' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/And.php',
    'PHPUnit_Framework_Constraint_ArrayHasKey' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/ArrayHasKey.php',
    'PHPUnit_Framework_Constraint_Attribute' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/Attribute.php',
    'PHPUnit_Framework_Constraint_Callback' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/Callback.php',
    'PHPUnit_Framework_Constraint_ClassHasAttribute' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/ClassHasAttribute.php',
    'PHPUnit_Framework_Constraint_ClassHasStaticAttribute' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/ClassHasStaticAttribute.php',
    'PHPUnit_Framework_Constraint_Composite' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/Composite.php',
    'PHPUnit_Framework_Constraint_Count' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/Count.php',
    'PHPUnit_Framework_Constraint_Exception' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/Exception.php',
    'PHPUnit_Framework_Constraint_ExceptionCode' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/ExceptionCode.php',
    'PHPUnit_Framework_Constraint_ExceptionMessage' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/ExceptionMessage.php',
    'PHPUnit_Framework_Constraint_FileExists' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/FileExists.php',
    'PHPUnit_Framework_Constraint_GreaterThan' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/GreaterThan.php',
    'PHPUnit_Framework_Constraint_IsAnything' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/IsAnything.php',
    'PHPUnit_Framework_Constraint_IsEmpty' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/IsEmpty.php',
    'PHPUnit_Framework_Constraint_IsEqual' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/IsEqual.php',
    'PHPUnit_Framework_Constraint_IsFalse' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/IsFalse.php',
    'PHPUnit_Framework_Constraint_IsIdentical' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/IsIdentical.php',
    'PHPUnit_Framework_Constraint_IsInstanceOf' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/IsInstanceOf.php',
    'PHPUnit_Framework_Constraint_IsJson' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/IsJson.php',
    'PHPUnit_Framework_Constraint_IsNull' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/IsNull.php',
    'PHPUnit_Framework_Constraint_IsTrue' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/IsTrue.php',
    'PHPUnit_Framework_Constraint_IsType' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/IsType.php',
    'PHPUnit_Framework_Constraint_JsonMatches' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/JsonMatches.php',
    'PHPUnit_Framework_Constraint_JsonMatches_ErrorMessageProvider' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/JsonMatches/ErrorMessageProvider.php',
    'PHPUnit_Framework_Constraint_LessThan' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/LessThan.php',
    'PHPUnit_Framework_Constraint_Not' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/Not.php',
    'PHPUnit_Framework_Constraint_ObjectHasAttribute' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/ObjectHasAttribute.php',
    'PHPUnit_Framework_Constraint_Or' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/Or.php',
    'PHPUnit_Framework_Constraint_PCREMatch' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/PCREMatch.php',
    'PHPUnit_Framework_Constraint_SameSize' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/SameSize.php',
    'PHPUnit_Framework_Constraint_StringContains' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/StringContains.php',
    'PHPUnit_Framework_Constraint_StringEndsWith' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/StringEndsWith.php',
    'PHPUnit_Framework_Constraint_StringMatches' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/StringMatches.php',
    'PHPUnit_Framework_Constraint_StringStartsWith' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/StringStartsWith.php',
    'PHPUnit_Framework_Constraint_TraversableContains' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/TraversableContains.php',
    'PHPUnit_Framework_Constraint_TraversableContainsOnly' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/TraversableContainsOnly.php',
    'PHPUnit_Framework_Constraint_Xor' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Constraint/Xor.php',
    'PHPUnit_Framework_Error' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Error.php',
    'PHPUnit_Framework_Error_Deprecated' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Error/Deprecated.php',
    'PHPUnit_Framework_Error_Notice' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Error/Notice.php',
    'PHPUnit_Framework_Error_Warning' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Error/Warning.php',
    'PHPUnit_Framework_Exception' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Exception.php',
    'PHPUnit_Framework_ExpectationFailedException' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/ExpectationFailedException.php',
    'PHPUnit_Framework_IncompleteTest' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/IncompleteTest.php',
    'PHPUnit_Framework_IncompleteTestError' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/IncompleteTestError.php',
    'PHPUnit_Framework_MockObject_Builder_Identity' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Builder/Identity.php',
    'PHPUnit_Framework_MockObject_Builder_InvocationMocker' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Builder/InvocationMocker.php',
    'PHPUnit_Framework_MockObject_Builder_Match' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Builder/Match.php',
    'PHPUnit_Framework_MockObject_Builder_MethodNameMatch' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Builder/MethodNameMatch.php',
    'PHPUnit_Framework_MockObject_Builder_Namespace' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Builder/Namespace.php',
    'PHPUnit_Framework_MockObject_Builder_ParametersMatch' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Builder/ParametersMatch.php',
    'PHPUnit_Framework_MockObject_Builder_Stub' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Builder/Stub.php',
    'PHPUnit_Framework_MockObject_Generator' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Generator.php',
    'PHPUnit_Framework_MockObject_Invocation' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Invocation.php',
    'PHPUnit_Framework_MockObject_InvocationMocker' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/InvocationMocker.php',
    'PHPUnit_Framework_MockObject_Invocation_Object' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Invocation/Object.php',
    'PHPUnit_Framework_MockObject_Invocation_Static' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Invocation/Static.php',
    'PHPUnit_Framework_MockObject_Invokable' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Invokable.php',
    'PHPUnit_Framework_MockObject_Matcher' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Matcher.php',
    'PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Matcher/AnyInvokedCount.php',
    'PHPUnit_Framework_MockObject_Matcher_AnyParameters' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Matcher/AnyParameters.php',
    'PHPUnit_Framework_MockObject_Matcher_Invocation' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Matcher/Invocation.php',
    'PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Matcher/InvokedAtIndex.php',
    'PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastOnce' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Matcher/InvokedAtLeastOnce.php',
    'PHPUnit_Framework_MockObject_Matcher_InvokedCount' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Matcher/InvokedCount.php',
    'PHPUnit_Framework_MockObject_Matcher_InvokedRecorder' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Matcher/InvokedRecorder.php',
    'PHPUnit_Framework_MockObject_Matcher_MethodName' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Matcher/MethodName.php',
    'PHPUnit_Framework_MockObject_Matcher_Parameters' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Matcher/Parameters.php',
    'PHPUnit_Framework_MockObject_Matcher_StatelessInvocation' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Matcher/StatelessInvocation.php',
    'PHPUnit_Framework_MockObject_MockBuilder' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/MockBuilder.php',
    'PHPUnit_Framework_MockObject_MockObject' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/MockObject.php',
    'PHPUnit_Framework_MockObject_Stub' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Stub.php',
    'PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Stub/ConsecutiveCalls.php',
    'PHPUnit_Framework_MockObject_Stub_Exception' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Stub/Exception.php',
    'PHPUnit_Framework_MockObject_Stub_MatcherCollection' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Stub/MatcherCollection.php',
    'PHPUnit_Framework_MockObject_Stub_Return' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Stub/Return.php',
    'PHPUnit_Framework_MockObject_Stub_ReturnArgument' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Stub/ReturnArgument.php',
    'PHPUnit_Framework_MockObject_Stub_ReturnCallback' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Stub/ReturnCallback.php',
    'PHPUnit_Framework_MockObject_Stub_ReturnSelf' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Stub/ReturnSelf.php',
    'PHPUnit_Framework_MockObject_Stub_ReturnValueMap' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Stub/ReturnValueMap.php',
    'PHPUnit_Framework_MockObject_Verifiable' => $vendorDir . '/phpunit/phpunit-mock-objects/PHPUnit/Framework/MockObject/Verifiable.php',
    'PHPUnit_Framework_OutputError' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/OutputError.php',
    'PHPUnit_Framework_SelfDescribing' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/SelfDescribing.php',
    'PHPUnit_Framework_SkippedTest' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/SkippedTest.php',
    'PHPUnit_Framework_SkippedTestError' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/SkippedTestError.php',
    'PHPUnit_Framework_SkippedTestSuiteError' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/SkippedTestSuiteError.php',
    'PHPUnit_Framework_SyntheticError' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/SyntheticError.php',
    'PHPUnit_Framework_Test' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Test.php',
    'PHPUnit_Framework_TestCase' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/TestCase.php',
    'PHPUnit_Framework_TestFailure' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/TestFailure.php',
    'PHPUnit_Framework_TestListener' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/TestListener.php',
    'PHPUnit_Framework_TestResult' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/TestResult.php',
    'PHPUnit_Framework_TestSuite' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/TestSuite.php',
    'PHPUnit_Framework_TestSuite_DataProvider' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/TestSuite/DataProvider.php',
    'PHPUnit_Framework_Warning' => $vendorDir . '/phpunit/phpunit/PHPUnit/Framework/Warning.php',
    'PHPUnit_Runner_BaseTestRunner' => $vendorDir . '/phpunit/phpunit/PHPUnit/Runner/BaseTestRunner.php',
    'PHPUnit_Runner_StandardTestSuiteLoader' => $vendorDir . '/phpunit/phpunit/PHPUnit/Runner/StandardTestSuiteLoader.php',
    'PHPUnit_Runner_TestSuiteLoader' => $vendorDir . '/phpunit/phpunit/PHPUnit/Runner/TestSuiteLoader.php',
    'PHPUnit_Runner_Version' => $vendorDir . '/phpunit/phpunit/PHPUnit/Runner/Version.php',
    'PHPUnit_TextUI_Command' => $vendorDir . '/phpunit/phpunit/PHPUnit/TextUI/Command.php',
    'PHPUnit_TextUI_ResultPrinter' => $vendorDir . '/phpunit/phpunit/PHPUnit/TextUI/ResultPrinter.php',
    'PHPUnit_TextUI_TestRunner' => $vendorDir . '/phpunit/phpunit/PHPUnit/TextUI/TestRunner.php',
    'PHPUnit_Util_Class' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/Class.php',
    'PHPUnit_Util_Configuration' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/Configuration.php',
    'PHPUnit_Util_DeprecatedFeature' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/DeprecatedFeature.php',
    'PHPUnit_Util_DeprecatedFeature_Logger' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/DeprecatedFeature/Logger.php',
    'PHPUnit_Util_Diff' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/Diff.php',
    'PHPUnit_Util_ErrorHandler' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/ErrorHandler.php',
    'PHPUnit_Util_Fileloader' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/Fileloader.php',
    'PHPUnit_Util_Filesystem' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/Filesystem.php',
    'PHPUnit_Util_Filter' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/Filter.php',
    'PHPUnit_Util_Getopt' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/Getopt.php',
    'PHPUnit_Util_GlobalState' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/GlobalState.php',
    'PHPUnit_Util_InvalidArgumentHelper' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/InvalidArgumentHelper.php',
    'PHPUnit_Util_Log_JSON' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/Log/JSON.php',
    'PHPUnit_Util_Log_JUnit' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/Log/JUnit.php',
    'PHPUnit_Util_Log_TAP' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/Log/TAP.php',
    'PHPUnit_Util_PHP' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/PHP.php',
    'PHPUnit_Util_PHP_Default' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/PHP/Default.php',
    'PHPUnit_Util_PHP_Windows' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/PHP/Windows.php',
    'PHPUnit_Util_Printer' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/Printer.php',
    'PHPUnit_Util_String' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/String.php',
    'PHPUnit_Util_Test' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/Test.php',
    'PHPUnit_Util_TestDox_NamePrettifier' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/TestDox/NamePrettifier.php',
    'PHPUnit_Util_TestDox_ResultPrinter' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/TestDox/ResultPrinter.php',
    'PHPUnit_Util_TestDox_ResultPrinter_HTML' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/TestDox/ResultPrinter/HTML.php',
    'PHPUnit_Util_TestDox_ResultPrinter_Text' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/TestDox/ResultPrinter/Text.php',
    'PHPUnit_Util_TestSuiteIterator' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/TestSuiteIterator.php',
    'PHPUnit_Util_Type' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/Type.php',
    'PHPUnit_Util_XML' => $vendorDir . '/phpunit/phpunit/PHPUnit/Util/XML.php',
    'PHP_CodeCoverage' => $vendorDir . '/phpunit/php-code-coverage/PHP/CodeCoverage.php',
    'PHP_CodeCoverage_Driver' => $vendorDir . '/phpunit/php-code-coverage/PHP/CodeCoverage/Driver.php',
    'PHP_CodeCoverage_Driver_Xdebug' => $vendorDir . '/phpunit/php-code-coverage/PHP/CodeCoverage/Driver/Xdebug.php',
    'PHP_CodeCoverage_Exception' => $vendorDir . '/phpunit/php-code-coverage/PHP/CodeCoverage/Exception.php',
    'PHP_CodeCoverage_Filter' => $vendorDir . '/phpunit/php-code-coverage/PHP/CodeCoverage/Filter.php',
    'PHP_CodeCoverage_Report_Clover' => $vendorDir . '/phpunit/php-code-coverage/PHP/CodeCoverage/Report/Clover.php',
    'PHP_CodeCoverage_Report_Factory' => $vendorDir . '/phpunit/php-code-coverage/PHP/CodeCoverage/Report/Factory.php',
    'PHP_CodeCoverage_Report_HTML' => $vendorDir . '/phpunit/php-code-coverage/PHP/CodeCoverage/Report/HTML.php',
    'PHP_CodeCoverage_Report_HTML_Renderer' => $vendorDir . '/phpunit/php-code-coverage/PHP/CodeCoverage/Report/HTML/Renderer.php',
    'PHP_CodeCoverage_Report_HTML_Renderer_Dashboard' => $vendorDir . '/phpunit/php-code-coverage/PHP/CodeCoverage/Report/HTML/Renderer/Dashboard.php',
    'PHP_CodeCoverage_Report_HTML_Renderer_Directory' => $vendorDir . '/phpunit/php-code-coverage/PHP/CodeCoverage/Report/HTML/Renderer/Directory.php',
    'PHP_CodeCoverage_Report_HTML_Renderer_File' => $vendorDir . '/phpunit/php-code-coverage/PHP/CodeCoverage/Report/HTML/Renderer/File.php',
    'PHP_CodeCoverage_Report_Node' => $vendorDir . '/phpunit/php-code-coverage/PHP/CodeCoverage/Report/Node.php',
    'PHP_CodeCoverage_Report_Node_Directory' => $vendorDir . '/phpunit/php-code-coverage/PHP/CodeCoverage/Report/Node/Directory.php',
    'PHP_CodeCoverage_Report_Node_File' => $vendorDir . '/phpunit/php-code-coverage/PHP/CodeCoverage/Report/Node/File.php',
    'PHP_CodeCoverage_Report_Node_Iterator' => $vendorDir . '/phpunit/php-code-coverage/PHP/CodeCoverage/Report/Node/Iterator.php',
    'PHP_CodeCoverage_Report_PHP' => $vendorDir . '/phpunit/php-code-coverage/PHP/CodeCoverage/Report/PHP.php',
    'PHP_CodeCoverage_Report_Text' => $vendorDir . '/phpunit/php-code-coverage/PHP/CodeCoverage/Report/Text.php',
    'PHP_CodeCoverage_Util' => $vendorDir . '/phpunit/php-code-coverage/PHP/CodeCoverage/Util.php',
    'PHP_CodeCoverage_Util_InvalidArgumentHelper' => $vendorDir . '/phpunit/php-code-coverage/PHP/CodeCoverage/Util/InvalidArgumentHelper.php',
    'PHP_CodeCoverage_Version' => $vendorDir . '/phpunit/php-code-coverage/PHP/CodeCoverage/Version.php',
    'PHP_CodeSniffer' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer.php',
    'PHP_CodeSniffer_CLI' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/CLI.php',
    'PHP_CodeSniffer_CommentParser_AbstractDocElement' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/CommentParser/AbstractDocElement.php',
    'PHP_CodeSniffer_CommentParser_AbstractParser' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/CommentParser/AbstractParser.php',
    'PHP_CodeSniffer_CommentParser_ClassCommentParser' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/CommentParser/ClassCommentParser.php',
    'PHP_CodeSniffer_CommentParser_CommentElement' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/CommentParser/CommentElement.php',
    'PHP_CodeSniffer_CommentParser_DocElement' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/CommentParser/DocElement.php',
    'PHP_CodeSniffer_CommentParser_FunctionCommentParser' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/CommentParser/FunctionCommentParser.php',
    'PHP_CodeSniffer_CommentParser_MemberCommentParser' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/CommentParser/MemberCommentParser.php',
    'PHP_CodeSniffer_CommentParser_PairElement' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/CommentParser/PairElement.php',
    'PHP_CodeSniffer_CommentParser_ParameterElement' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/CommentParser/ParameterElement.php',
    'PHP_CodeSniffer_CommentParser_ParserException' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/CommentParser/ParserException.php',
    'PHP_CodeSniffer_CommentParser_SingleElement' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/CommentParser/SingleElement.php',
    'PHP_CodeSniffer_DocGenerators_Generator' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/DocGenerators/Generator.php',
    'PHP_CodeSniffer_DocGenerators_HTML' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/DocGenerators/HTML.php',
    'PHP_CodeSniffer_DocGenerators_Text' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/DocGenerators/Text.php',
    'PHP_CodeSniffer_Exception' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Exception.php',
    'PHP_CodeSniffer_File' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/File.php',
    'PHP_CodeSniffer_Report' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Report.php',
    'PHP_CodeSniffer_Reporting' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reporting.php',
    'PHP_CodeSniffer_Reports_Checkstyle' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/Checkstyle.php',
    'PHP_CodeSniffer_Reports_Csv' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/Csv.php',
    'PHP_CodeSniffer_Reports_Emacs' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/Emacs.php',
    'PHP_CodeSniffer_Reports_Full' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/Full.php',
    'PHP_CodeSniffer_Reports_Gitblame' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/Gitblame.php',
    'PHP_CodeSniffer_Reports_Hgblame' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/Hgblame.php',
    'PHP_CodeSniffer_Reports_Json' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/Json.php',
    'PHP_CodeSniffer_Reports_Junit' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/Junit.php',
    'PHP_CodeSniffer_Reports_Notifysend' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/Notifysend.php',
    'PHP_CodeSniffer_Reports_Source' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/Source.php',
    'PHP_CodeSniffer_Reports_Summary' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/Summary.php',
    'PHP_CodeSniffer_Reports_Svnblame' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/Svnblame.php',
    'PHP_CodeSniffer_Reports_VersionControl' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/VersionControl.php',
    'PHP_CodeSniffer_Reports_Xml' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Reports/Xml.php',
    'PHP_CodeSniffer_Sniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Sniff.php',
    'PHP_CodeSniffer_Standards_AbstractPatternSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/AbstractPatternSniff.php',
    'PHP_CodeSniffer_Standards_AbstractScopeSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/AbstractScopeSniff.php',
    'PHP_CodeSniffer_Standards_AbstractVariableSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/AbstractVariableSniff.php',
    'PHP_CodeSniffer_Standards_IncorrectPatternException' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/IncorrectPatternException.php',
    'PHP_CodeSniffer_Tokenizers_CSS' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Tokenizers/CSS.php',
    'PHP_CodeSniffer_Tokenizers_JS' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Tokenizers/JS.php',
    'PHP_CodeSniffer_Tokenizers_PHP' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Tokenizers/PHP.php',
    'PHP_CodeSniffer_Tokens' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Tokens.php',
    'PHP_Timer' => $vendorDir . '/phpunit/php-timer/PHP/Timer.php',
    'PHP_Token' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_TokenWithScope' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_TokenWithScopeAndVisibility' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_ABSTRACT' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_AMPERSAND' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_AND_EQUAL' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_ARRAY' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_ARRAY_CAST' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_AS' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_AT' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_BACKTICK' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_BAD_CHARACTER' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_BOOLEAN_AND' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_BOOLEAN_OR' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_BOOL_CAST' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_BREAK' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_CALLABLE' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_CARET' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_CASE' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_CATCH' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_CHARACTER' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_CLASS' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_CLASS_C' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_CLASS_NAME_CONSTANT' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_CLONE' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_CLOSE_BRACKET' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_CLOSE_CURLY' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_CLOSE_SQUARE' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_CLOSE_TAG' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_COLON' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_COMMA' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_COMMENT' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_CONCAT_EQUAL' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_CONST' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_CONSTANT_ENCAPSED_STRING' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_CONTINUE' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_CURLY_OPEN' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_DEC' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_DECLARE' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_DEFAULT' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_DIR' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_DIV' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_DIV_EQUAL' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_DNUMBER' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_DO' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_DOC_COMMENT' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_DOLLAR' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_DOLLAR_OPEN_CURLY_BRACES' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_DOT' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_DOUBLE_ARROW' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_DOUBLE_CAST' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_DOUBLE_COLON' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_DOUBLE_QUOTES' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_ECHO' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_ELSE' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_ELSEIF' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_EMPTY' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_ENCAPSED_AND_WHITESPACE' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_ENDDECLARE' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_ENDFOR' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_ENDFOREACH' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_ENDIF' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_ENDSWITCH' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_ENDWHILE' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_END_HEREDOC' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_EQUAL' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_EVAL' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_EXCLAMATION_MARK' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_EXIT' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_EXTENDS' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_FILE' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_FINAL' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_FINALLY' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_FOR' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_FOREACH' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_FUNCTION' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_FUNC_C' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_GLOBAL' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_GOTO' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_GT' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_HALT_COMPILER' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_IF' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_IMPLEMENTS' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_INC' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_INCLUDE' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_INCLUDE_ONCE' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_INLINE_HTML' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_INSTANCEOF' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_INSTEADOF' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_INTERFACE' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_INT_CAST' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_ISSET' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_IS_EQUAL' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_IS_GREATER_OR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_IS_IDENTICAL' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_IS_NOT_EQUAL' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_IS_NOT_IDENTICAL' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_IS_SMALLER_OR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_Includes' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_LINE' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_LIST' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_LNUMBER' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_LOGICAL_AND' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_LOGICAL_OR' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_LOGICAL_XOR' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_LT' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_METHOD_C' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_MINUS' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_MINUS_EQUAL' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_MOD_EQUAL' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_MULT' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_MUL_EQUAL' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_NAMESPACE' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_NEW' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_NS_C' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_NS_SEPARATOR' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_NUM_STRING' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_OBJECT_CAST' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_OBJECT_OPERATOR' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_OPEN_BRACKET' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_OPEN_CURLY' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_OPEN_SQUARE' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_OPEN_TAG' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_OPEN_TAG_WITH_ECHO' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_OR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_PAAMAYIM_NEKUDOTAYIM' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_PERCENT' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_PIPE' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_PLUS' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_PLUS_EQUAL' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_PRINT' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_PRIVATE' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_PROTECTED' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_PUBLIC' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_QUESTION_MARK' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_REQUIRE' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_REQUIRE_ONCE' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_RETURN' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_SEMICOLON' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_SL' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_SL_EQUAL' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_SR' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_SR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_START_HEREDOC' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_STATIC' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_STRING' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_STRING_CAST' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_STRING_VARNAME' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_SWITCH' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_Stream' => $vendorDir . '/phpunit/php-token-stream/PHP/Token/Stream.php',
    'PHP_Token_Stream_CachingFactory' => $vendorDir . '/phpunit/php-token-stream/PHP/Token/Stream/CachingFactory.php',
    'PHP_Token_THROW' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_TILDE' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_TRAIT' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_TRAIT_C' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_TRY' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_UNSET' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_UNSET_CAST' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_USE' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_VAR' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_VARIABLE' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_WHILE' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_WHITESPACE' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_XOR_EQUAL' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PHP_Token_YIELD' => $vendorDir . '/phpunit/php-token-stream/PHP/Token.php',
    'PSR1_Sniffs_Classes_ClassDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR1/Sniffs/Classes/ClassDeclarationSniff.php',
    'PSR1_Sniffs_Files_SideEffectsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR1/Sniffs/Files/SideEffectsSniff.php',
    'PSR1_Sniffs_Methods_CamelCapsMethodNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR1/Sniffs/Methods/CamelCapsMethodNameSniff.php',
    'PSR2_Sniffs_Classes_ClassDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Classes/ClassDeclarationSniff.php',
    'PSR2_Sniffs_Classes_PropertyDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Classes/PropertyDeclarationSniff.php',
    'PSR2_Sniffs_ControlStructures_ControlStructureSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/ControlStructures/ControlStructureSpacingSniff.php',
    'PSR2_Sniffs_ControlStructures_ElseIfDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/ControlStructures/ElseIfDeclarationSniff.php',
    'PSR2_Sniffs_ControlStructures_SwitchDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/ControlStructures/SwitchDeclarationSniff.php',
    'PSR2_Sniffs_Files_EndFileNewlineSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Files/EndFileNewlineSniff.php',
    'PSR2_Sniffs_Methods_FunctionCallSignatureSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Methods/FunctionCallSignatureSniff.php',
    'PSR2_Sniffs_Methods_MethodDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Methods/MethodDeclarationSniff.php',
    'PSR2_Sniffs_Namespaces_NamespaceDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Namespaces/NamespaceDeclarationSniff.php',
    'PSR2_Sniffs_Namespaces_UseDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/PSR2/Sniffs/Namespaces/UseDeclarationSniff.php',
    'Squiz_Sniffs_Arrays_ArrayBracketSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Arrays/ArrayBracketSpacingSniff.php',
    'Squiz_Sniffs_Arrays_ArrayDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Arrays/ArrayDeclarationSniff.php',
    'Squiz_Sniffs_CSS_ClassDefinitionClosingBraceSpaceSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/ClassDefinitionClosingBraceSpaceSniff.php',
    'Squiz_Sniffs_CSS_ClassDefinitionNameSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/ClassDefinitionNameSpacingSniff.php',
    'Squiz_Sniffs_CSS_ClassDefinitionOpeningBraceSpaceSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/ClassDefinitionOpeningBraceSpaceSniff.php',
    'Squiz_Sniffs_CSS_ColonSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/ColonSpacingSniff.php',
    'Squiz_Sniffs_CSS_ColourDefinitionSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/ColourDefinitionSniff.php',
    'Squiz_Sniffs_CSS_DisallowMultipleStyleDefinitionsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/DisallowMultipleStyleDefinitionsSniff.php',
    'Squiz_Sniffs_CSS_DuplicateClassDefinitionSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/DuplicateClassDefinitionSniff.php',
    'Squiz_Sniffs_CSS_DuplicateStyleDefinitionSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/DuplicateStyleDefinitionSniff.php',
    'Squiz_Sniffs_CSS_EmptyClassDefinitionSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/EmptyClassDefinitionSniff.php',
    'Squiz_Sniffs_CSS_EmptyStyleDefinitionSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/EmptyStyleDefinitionSniff.php',
    'Squiz_Sniffs_CSS_ForbiddenStylesSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/ForbiddenStylesSniff.php',
    'Squiz_Sniffs_CSS_IndentationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/IndentationSniff.php',
    'Squiz_Sniffs_CSS_LowercaseStyleDefinitionSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/LowercaseStyleDefinitionSniff.php',
    'Squiz_Sniffs_CSS_MissingColonSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/MissingColonSniff.php',
    'Squiz_Sniffs_CSS_NamedColoursSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/NamedColoursSniff.php',
    'Squiz_Sniffs_CSS_OpacitySniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/OpacitySniff.php',
    'Squiz_Sniffs_CSS_SemicolonSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/SemicolonSpacingSniff.php',
    'Squiz_Sniffs_CSS_ShorthandSizeSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CSS/ShorthandSizeSniff.php',
    'Squiz_Sniffs_Classes_ClassDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Classes/ClassDeclarationSniff.php',
    'Squiz_Sniffs_Classes_ClassFileNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Classes/ClassFileNameSniff.php',
    'Squiz_Sniffs_Classes_DuplicatePropertySniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Classes/DuplicatePropertySniff.php',
    'Squiz_Sniffs_Classes_LowercaseClassKeywordsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Classes/LowercaseClassKeywordsSniff.php',
    'Squiz_Sniffs_Classes_SelfMemberReferenceSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Classes/SelfMemberReferenceSniff.php',
    'Squiz_Sniffs_Classes_ValidClassNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Classes/ValidClassNameSniff.php',
    'Squiz_Sniffs_CodeAnalysis_EmptyStatementSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/CodeAnalysis/EmptyStatementSniff.php',
    'Squiz_Sniffs_Commenting_BlockCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/BlockCommentSniff.php',
    'Squiz_Sniffs_Commenting_ClassCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/ClassCommentSniff.php',
    'Squiz_Sniffs_Commenting_ClosingDeclarationCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/ClosingDeclarationCommentSniff.php',
    'Squiz_Sniffs_Commenting_DocCommentAlignmentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/DocCommentAlignmentSniff.php',
    'Squiz_Sniffs_Commenting_EmptyCatchCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/EmptyCatchCommentSniff.php',
    'Squiz_Sniffs_Commenting_FileCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/FileCommentSniff.php',
    'Squiz_Sniffs_Commenting_FunctionCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/FunctionCommentSniff.php',
    'Squiz_Sniffs_Commenting_FunctionCommentThrowTagSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/FunctionCommentThrowTagSniff.php',
    'Squiz_Sniffs_Commenting_InlineCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/InlineCommentSniff.php',
    'Squiz_Sniffs_Commenting_LongConditionClosingCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/LongConditionClosingCommentSniff.php',
    'Squiz_Sniffs_Commenting_PostStatementCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/PostStatementCommentSniff.php',
    'Squiz_Sniffs_Commenting_VariableCommentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Commenting/VariableCommentSniff.php',
    'Squiz_Sniffs_ControlStructures_ControlSignatureSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/ControlStructures/ControlSignatureSniff.php',
    'Squiz_Sniffs_ControlStructures_ElseIfDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/ControlStructures/ElseIfDeclarationSniff.php',
    'Squiz_Sniffs_ControlStructures_ForEachLoopDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/ControlStructures/ForEachLoopDeclarationSniff.php',
    'Squiz_Sniffs_ControlStructures_ForLoopDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/ControlStructures/ForLoopDeclarationSniff.php',
    'Squiz_Sniffs_ControlStructures_InlineIfDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/ControlStructures/InlineIfDeclarationSniff.php',
    'Squiz_Sniffs_ControlStructures_LowercaseDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/ControlStructures/LowercaseDeclarationSniff.php',
    'Squiz_Sniffs_ControlStructures_SwitchDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/ControlStructures/SwitchDeclarationSniff.php',
    'Squiz_Sniffs_Debug_JSLintSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Debug/JSLintSniff.php',
    'Squiz_Sniffs_Debug_JavaScriptLintSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Debug/JavaScriptLintSniff.php',
    'Squiz_Sniffs_Files_FileExtensionSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Files/FileExtensionSniff.php',
    'Squiz_Sniffs_Formatting_OperatorBracketSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Formatting/OperatorBracketSniff.php',
    'Squiz_Sniffs_Functions_FunctionDeclarationArgumentSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Functions/FunctionDeclarationArgumentSpacingSniff.php',
    'Squiz_Sniffs_Functions_FunctionDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Functions/FunctionDeclarationSniff.php',
    'Squiz_Sniffs_Functions_FunctionDuplicateArgumentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Functions/FunctionDuplicateArgumentSniff.php',
    'Squiz_Sniffs_Functions_GlobalFunctionSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Functions/GlobalFunctionSniff.php',
    'Squiz_Sniffs_Functions_LowercaseFunctionKeywordsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Functions/LowercaseFunctionKeywordsSniff.php',
    'Squiz_Sniffs_Functions_MultiLineFunctionDeclarationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Functions/MultiLineFunctionDeclarationSniff.php',
    'Squiz_Sniffs_NamingConventions_ConstantCaseSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/NamingConventions/ConstantCaseSniff.php',
    'Squiz_Sniffs_NamingConventions_ValidFunctionNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/NamingConventions/ValidFunctionNameSniff.php',
    'Squiz_Sniffs_NamingConventions_ValidVariableNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/NamingConventions/ValidVariableNameSniff.php',
    'Squiz_Sniffs_Objects_DisallowObjectStringIndexSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Objects/DisallowObjectStringIndexSniff.php',
    'Squiz_Sniffs_Objects_ObjectInstantiationSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Objects/ObjectInstantiationSniff.php',
    'Squiz_Sniffs_Objects_ObjectMemberCommaSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Objects/ObjectMemberCommaSniff.php',
    'Squiz_Sniffs_Operators_ComparisonOperatorUsageSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Operators/ComparisonOperatorUsageSniff.php',
    'Squiz_Sniffs_Operators_IncrementDecrementUsageSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Operators/IncrementDecrementUsageSniff.php',
    'Squiz_Sniffs_Operators_ValidLogicalOperatorsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Operators/ValidLogicalOperatorsSniff.php',
    'Squiz_Sniffs_PHP_CommentedOutCodeSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/CommentedOutCodeSniff.php',
    'Squiz_Sniffs_PHP_DisallowBooleanStatementSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/DisallowBooleanStatementSniff.php',
    'Squiz_Sniffs_PHP_DisallowComparisonAssignmentSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/DisallowComparisonAssignmentSniff.php',
    'Squiz_Sniffs_PHP_DisallowInlineIfSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/DisallowInlineIfSniff.php',
    'Squiz_Sniffs_PHP_DisallowMultipleAssignmentsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/DisallowMultipleAssignmentsSniff.php',
    'Squiz_Sniffs_PHP_DisallowObEndFlushSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/DisallowObEndFlushSniff.php',
    'Squiz_Sniffs_PHP_DisallowSizeFunctionsInLoopsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/DisallowSizeFunctionsInLoopsSniff.php',
    'Squiz_Sniffs_PHP_DiscouragedFunctionsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/DiscouragedFunctionsSniff.php',
    'Squiz_Sniffs_PHP_EmbeddedPhpSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/EmbeddedPhpSniff.php',
    'Squiz_Sniffs_PHP_EvalSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/EvalSniff.php',
    'Squiz_Sniffs_PHP_ForbiddenFunctionsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/ForbiddenFunctionsSniff.php',
    'Squiz_Sniffs_PHP_GlobalKeywordSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/GlobalKeywordSniff.php',
    'Squiz_Sniffs_PHP_HeredocSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/HeredocSniff.php',
    'Squiz_Sniffs_PHP_InnerFunctionsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/InnerFunctionsSniff.php',
    'Squiz_Sniffs_PHP_LowercasePHPFunctionsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/LowercasePHPFunctionsSniff.php',
    'Squiz_Sniffs_PHP_NonExecutableCodeSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/PHP/NonExecutableCodeSniff.php',
    'Squiz_Sniffs_Scope_MemberVarScopeSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Scope/MemberVarScopeSniff.php',
    'Squiz_Sniffs_Scope_MethodScopeSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Scope/MethodScopeSniff.php',
    'Squiz_Sniffs_Scope_StaticThisUsageSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Scope/StaticThisUsageSniff.php',
    'Squiz_Sniffs_Strings_ConcatenationSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Strings/ConcatenationSpacingSniff.php',
    'Squiz_Sniffs_Strings_DoubleQuoteUsageSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Strings/DoubleQuoteUsageSniff.php',
    'Squiz_Sniffs_Strings_EchoedStringsSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/Strings/EchoedStringsSniff.php',
    'Squiz_Sniffs_WhiteSpace_CastSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/CastSpacingSniff.php',
    'Squiz_Sniffs_WhiteSpace_ControlStructureSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/ControlStructureSpacingSniff.php',
    'Squiz_Sniffs_WhiteSpace_FunctionClosingBraceSpaceSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/FunctionClosingBraceSpaceSniff.php',
    'Squiz_Sniffs_WhiteSpace_FunctionOpeningBraceSpaceSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/FunctionOpeningBraceSpaceSniff.php',
    'Squiz_Sniffs_WhiteSpace_FunctionSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/FunctionSpacingSniff.php',
    'Squiz_Sniffs_WhiteSpace_LanguageConstructSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/LanguageConstructSpacingSniff.php',
    'Squiz_Sniffs_WhiteSpace_LogicalOperatorSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/LogicalOperatorSpacingSniff.php',
    'Squiz_Sniffs_WhiteSpace_MemberVarSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/MemberVarSpacingSniff.php',
    'Squiz_Sniffs_WhiteSpace_ObjectOperatorSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/ObjectOperatorSpacingSniff.php',
    'Squiz_Sniffs_WhiteSpace_OperatorSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/OperatorSpacingSniff.php',
    'Squiz_Sniffs_WhiteSpace_PropertyLabelSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/PropertyLabelSpacingSniff.php',
    'Squiz_Sniffs_WhiteSpace_ScopeClosingBraceSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php',
    'Squiz_Sniffs_WhiteSpace_ScopeKeywordSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/ScopeKeywordSpacingSniff.php',
    'Squiz_Sniffs_WhiteSpace_SemicolonSpacingSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/SemicolonSpacingSniff.php',
    'Squiz_Sniffs_WhiteSpace_SuperfluousWhitespaceSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Squiz/Sniffs/WhiteSpace/SuperfluousWhitespaceSniff.php',
    'Text_Template' => $vendorDir . '/phpunit/php-text-template/Text/Template.php',
    'Zend_Sniffs_Debug_CodeAnalyzerSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Zend/Sniffs/Debug/CodeAnalyzerSniff.php',
    'Zend_Sniffs_Files_ClosingTagSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Zend/Sniffs/Files/ClosingTagSniff.php',
    'Zend_Sniffs_NamingConventions_ValidVariableNameSniff' => $vendorDir . '/squizlabs/php_codesniffer/CodeSniffer/Standards/Zend/Sniffs/NamingConventions/ValidVariableNameSniff.php',
);
<?php

// autoload_real.php @generated by Composer

class ComposerAutoloaderInit687aaa93da4df781853324a5163d1fd6
{
    private static $loader;

    public static function loadClassLoader($class)
    {
        if ('Composer\Autoload\ClassLoader' === $class) {
            require __DIR__ . '/ClassLoader.php';
        }
    }

    public static function getLoader()
    {
        if (null !== self::$loader) {
            return self::$loader;
        }

        spl_autoload_register(array('ComposerAutoloaderInit687aaa93da4df781853324a5163d1fd6', 'loadClassLoader'), true, true);
        self::$loader = $loader = new \Composer\Autoload\ClassLoader();
        spl_autoload_unregister(array('ComposerAutoloaderInit687aaa93da4df781853324a5163d1fd6', 'loadClassLoader'));

        $vendorDir = dirname(__DIR__);
        $baseDir = dirname($vendorDir);

        $includePaths = require __DIR__ . '/include_paths.php';
        array_push($includePaths, get_include_path());
        set_include_path(join(PATH_SEPARATOR, $includePaths));

        $map = require __DIR__ . '/autoload_namespaces.php';
        foreach ($map as $namespace => $path) {
            $loader->set($namespace, $path);
        }

        $classMap = require __DIR__ . '/autoload_classmap.php';
        if ($classMap) {
            $loader->addClassMap($classMap);
        }

        $loader->register(true);

        return $loader;
    }
}
<?php

/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Composer\Autoload;

/**
 * ClassLoader implements a PSR-0 class loader
 *
 * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
 *
 *     $loader = new \Composer\Autoload\ClassLoader();
 *
 *     // register classes with namespaces
 *     $loader->add('Symfony\Component', __DIR__.'/component');
 *     $loader->add('Symfony',           __DIR__.'/framework');
 *
 *     // activate the autoloader
 *     $loader->register();
 *
 *     // to enable searching the include path (eg. for PEAR packages)
 *     $loader->setUseIncludePath(true);
 *
 * In this example, if you try to use a class in the Symfony\Component
 * namespace or one of its children (Symfony\Component\Console for instance),
 * the autoloader will first look for the class under the component/
 * directory, and it will then fallback to the framework/ directory if not
 * found before giving up.
 *
 * This class is loosely based on the Symfony UniversalClassLoader.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class ClassLoader
{
    private $prefixes = array();
    private $fallbackDirs = array();
    private $useIncludePath = false;
    private $classMap = array();

    public function getPrefixes()
    {
        return call_user_func_array('array_merge', $this->prefixes);
    }

    public function getFallbackDirs()
    {
        return $this->fallbackDirs;
    }

    public function getClassMap()
    {
        return $this->classMap;
    }

    /**
     * @param array $classMap Class to filename map
     */
    public function addClassMap(array $classMap)
    {
        if ($this->classMap) {
            $this->classMap = array_merge($this->classMap, $classMap);
        } else {
            $this->classMap = $classMap;
        }
    }

    /**
     * Registers a set of classes, merging with any others previously set.
     *
     * @param string       $prefix  The classes prefix
     * @param array|string $paths   The location(s) of the classes
     * @param bool         $prepend Prepend the location(s)
     */
    public function add($prefix, $paths, $prepend = false)
    {
        if (!$prefix) {
            if ($prepend) {
                $this->fallbackDirs = array_merge(
                    (array) $paths,
                    $this->fallbackDirs
                );
            } else {
                $this->fallbackDirs = array_merge(
                    $this->fallbackDirs,
                    (array) $paths
                );
            }

            return;
        }

        $first = $prefix[0];
        if (!isset($this->prefixes[$first][$prefix])) {
            $this->prefixes[$first][$prefix] = (array) $paths;

            return;
        }
        if ($prepend) {
            $this->prefixes[$first][$prefix] = array_merge(
                (array) $paths,
                $this->prefixes[$first][$prefix]
            );
        } else {
            $this->prefixes[$first][$prefix] = array_merge(
                $this->prefixes[$first][$prefix],
                (array) $paths
            );
        }
    }

    /**
     * Registers a set of classes, replacing any others previously set.
     *
     * @param string       $prefix The classes prefix
     * @param array|string $paths  The location(s) of the classes
     */
    public function set($prefix, $paths)
    {
        if (!$prefix) {
            $this->fallbackDirs = (array) $paths;

            return;
        }
        $this->prefixes[substr($prefix, 0, 1)][$prefix] = (array) $paths;
    }

    /**
     * Turns on searching the include path for class files.
     *
     * @param bool $useIncludePath
     */
    public function setUseIncludePath($useIncludePath)
    {
        $this->useIncludePath = $useIncludePath;
    }

    /**
     * Can be used to check if the autoloader uses the include path to check
     * for classes.
     *
     * @return bool
     */
    public function getUseIncludePath()
    {
        return $this->useIncludePath;
    }

    /**
     * Registers this instance as an autoloader.
     *
     * @param bool $prepend Whether to prepend the autoloader or not
     */
    public function register($prepend = false)
    {
        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
    }

    /**
     * Unregisters this instance as an autoloader.
     */
    public function unregister()
    {
        spl_autoload_unregister(array($this, 'loadClass'));
    }

    /**
     * Loads the given class or interface.
     *
     * @param  string    $class The name of the class
     * @return bool|null True if loaded, null otherwise
     */
    public function loadClass($class)
    {
        if ($file = $this->findFile($class)) {
            include $file;

            return true;
        }
    }

    /**
     * Finds the path to the file where the class is defined.
     *
     * @param string $class The name of the class
     *
     * @return string|false The path if found, false otherwise
     */
    public function findFile($class)
    {
        // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
        if ('\\' == $class[0]) {
            $class = substr($class, 1);
        }

        if (isset($this->classMap[$class])) {
            return $this->classMap[$class];
        }

        if (false !== $pos = strrpos($class, '\\')) {
            // namespaced class name
            $classPath = strtr(substr($class, 0, $pos), '\\', DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
            $className = substr($class, $pos + 1);
        } else {
            // PEAR-like class name
            $classPath = null;
            $className = $class;
        }

        $classPath .= strtr($className, '_', DIRECTORY_SEPARATOR) . '.php';

        $first = $class[0];
        if (isset($this->prefixes[$first])) {
            foreach ($this->prefixes[$first] as $prefix => $dirs) {
                if (0 === strpos($class, $prefix)) {
                    foreach ($dirs as $dir) {
                        if (file_exists($dir . DIRECTORY_SEPARATOR . $classPath)) {
                            return $dir . DIRECTORY_SEPARATOR . $classPath;
                        }
                    }
                }
            }
        }

        foreach ($this->fallbackDirs as $dir) {
            if (file_exists($dir . DIRECTORY_SEPARATOR . $classPath)) {
                return $dir . DIRECTORY_SEPARATOR . $classPath;
            }
        }

        if ($this->useIncludePath && $file = stream_resolve_include_path($classPath)) {
            return $file;
        }

        return $this->classMap[$class] = false;
    }
}
<?php

// include_paths.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    $vendorDir . '/phpunit/php-text-template',
    $vendorDir . '/phpunit/phpunit-mock-objects',
    $vendorDir . '/phpunit/php-timer',
    $vendorDir . '/phpunit/php-token-stream',
    $vendorDir . '/phpunit/php-code-coverage',
    $vendorDir . '/phpunit/php-file-iterator',
    $vendorDir . '/phpunit/phpunit',
    $vendorDir . '/symfony/yaml',
);
[
    {
        "name": "doctrine/annotations",
        "version": "v1.1.2",
        "version_normalized": "1.1.2.0",
        "source": {
            "type": "git",
            "url": "https://github.com/doctrine/annotations.git",
            "reference": "v1.1.2"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/doctrine/annotations/zipball/v1.1.2",
            "reference": "v1.1.2",
            "shasum": ""
        },
        "require": {
            "doctrine/lexer": "1.*",
            "php": ">=5.3.2"
        },
        "require-dev": {
            "doctrine/cache": "1.*"
        },
        "time": "2013-06-16 21:33:03",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "1.0.x-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Doctrine\\Common\\Annotations\\": "lib/"
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Jonathan Wage",
                "email": "jonwage@gmail.com",
                "homepage": "http://www.jwage.com/"
            },
            {
                "name": "Guilherme Blanco",
                "email": "guilhermeblanco@gmail.com",
                "homepage": "http://www.instaclick.com"
            },
            {
                "name": "Roman Borschel",
                "email": "roman@code-factory.org"
            },
            {
                "name": "Benjamin Eberlei",
                "email": "kontakt@beberlei.de"
            },
            {
                "name": "Johannes Schmitt",
                "email": "schmittjoh@gmail.com",
                "homepage": "http://jmsyst.com",
                "role": "Developer of wrapped JMSSerializerBundle"
            }
        ],
        "description": "Docblock Annotations Parser",
        "homepage": "http://www.doctrine-project.org",
        "keywords": [
            "annotations",
            "docblock",
            "parser"
        ]
    },
    {
        "name": "psr/log",
        "version": "1.0.0",
        "version_normalized": "1.0.0.0",
        "source": {
            "type": "git",
            "url": "https://github.com/php-fig/log",
            "reference": "1.0.0"
        },
        "dist": {
            "type": "zip",
            "url": "https://github.com/php-fig/log/archive/1.0.0.zip",
            "reference": "1.0.0",
            "shasum": ""
        },
        "time": "2012-12-21 11:40:51",
        "type": "library",
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Psr\\Log\\": ""
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "PHP-FIG",
                "homepage": "http://www.php-fig.org/"
            }
        ],
        "description": "Common interface for logging libraries",
        "keywords": [
            "log",
            "psr",
            "psr-3"
        ]
    },
    {
        "name": "mockery/mockery",
        "version": "0.8.0",
        "version_normalized": "0.8.0.0",
        "source": {
            "type": "git",
            "url": "https://github.com/padraic/mockery.git",
            "reference": "0.8.0"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/padraic/mockery/zipball/0.8.0",
            "reference": "0.8.0",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.2"
        },
        "require-dev": {
            "hamcrest/hamcrest": "1.1.0"
        },
        "time": "2013-04-01 12:13:17",
        "type": "library",
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Mockery": "library/"
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "BSD-3-Clause"
        ],
        "authors": [
            {
                "name": "Pádraic Brady",
                "email": "padraic.brady@gmail.com",
                "homepage": "http://blog.astrumfutura.com"
            }
        ],
        "description": "Mockery is a simple yet flexible PHP mock object framework for use in unit testing with PHPUnit, PHPSpec or any other testing framework. Its core goal is to offer a test double framework with a succint API capable of clearly defining all possible object operations and interactions using a human readable Domain Specific Language (DSL). Designed as a drop in alternative to PHPUnit's phpunit-mock-objects library, Mockery is easy to integrate with PHPUnit and can operate alongside phpunit-mock-objects without the World ending.",
        "homepage": "http://github.com/padraic/mockery",
        "keywords": [
            "BDD",
            "TDD",
            "library",
            "mock",
            "mock objects",
            "mockery",
            "stub",
            "test",
            "test double",
            "testing"
        ]
    },
    {
        "name": "pimple/pimple",
        "version": "v1.0.2",
        "version_normalized": "1.0.2.0",
        "source": {
            "type": "git",
            "url": "https://github.com/fabpot/Pimple.git",
            "reference": "v1.0.2"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/fabpot/Pimple/zipball/v1.0.2",
            "reference": "v1.0.2",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.0"
        },
        "time": "2013-03-08 08:21:40",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "1.0.x-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Pimple": "lib/"
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Fabien Potencier",
                "email": "fabien@symfony.com"
            }
        ],
        "description": "Pimple is a simple Dependency Injection Container for PHP 5.3",
        "homepage": "http://pimple.sensiolabs.org",
        "keywords": [
            "container",
            "dependency injection"
        ]
    },
    {
        "name": "cilex/console-service-provider",
        "version": "1.0.0",
        "version_normalized": "1.0.0.0",
        "source": {
            "type": "git",
            "url": "https://github.com/Cilex/console-service-provider.git",
            "reference": "1.0.0"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/Cilex/console-service-provider/zipball/1.0.0",
            "reference": "1.0.0",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3",
            "pimple/pimple": "1.*@dev",
            "symfony/console": "~2.1"
        },
        "require-dev": {
            "cilex/cilex": "1.*@dev",
            "silex/silex": "1.*@dev"
        },
        "time": "2012-12-19 10:50:58",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "1.0-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Cilex\\Provider\\Console": "src"
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Beau Simensen",
                "email": "beau@dflydev.com",
                "homepage": "http://beausimensen.com"
            },
            {
                "name": "Mike van Riel",
                "email": "mike.vanriel@naenius.com"
            }
        ],
        "description": "Console Service Provider",
        "keywords": [
            "cilex",
            "console",
            "pimple",
            "service-provider",
            "silex"
        ]
    },
    {
        "name": "cilex/cilex",
        "version": "1.0.1",
        "version_normalized": "1.0.1.0",
        "source": {
            "type": "git",
            "url": "https://github.com/Cilex/Cilex.git",
            "reference": "1.0.1"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/Cilex/Cilex/zipball/1.0.1",
            "reference": "1.0.1",
            "shasum": ""
        },
        "require": {
            "cilex/console-service-provider": "1.*",
            "php": ">=5.3.3",
            "pimple/pimple": "1.0.*",
            "symfony/finder": "~2.1",
            "symfony/process": "~2.1"
        },
        "require-dev": {
            "phpunit/phpunit": "3.7.*",
            "symfony/validator": "~2.1"
        },
        "suggest": {
            "monolog/monolog": ">=1.0.0",
            "symfony/validator": ">=1.0.0",
            "symfony/yaml": ">=1.0.0"
        },
        "time": "2013-08-01 15:19:34",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "1.0-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Cilex": "src/"
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Mike van Riel",
                "email": "mike.vanriel@naenius.com"
            }
        ],
        "description": "The PHP micro-framework for Command line tools based on the Symfony2 Components",
        "homepage": "http://cilex.github.com",
        "keywords": [
            "cli",
            "microframework"
        ]
    },
    {
        "name": "jms/parser-lib",
        "version": "1.0.0",
        "version_normalized": "1.0.0.0",
        "source": {
            "type": "git",
            "url": "git://github.com/schmittjoh/parser-lib",
            "reference": "1.0.0"
        },
        "dist": {
            "type": "zip",
            "url": "https://github.com/schmittjoh/parser-lib/archive/1.0.0.zip",
            "reference": "1.0.0",
            "shasum": ""
        },
        "require": {
            "phpoption/phpoption": ">=0.9,<2.0-dev"
        },
        "time": "2012-11-18 18:08:43",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "1.0-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "JMS\\": "src/"
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "Apache2"
        ],
        "description": "A library for easily creating recursive-descent parsers."
    },
    {
        "name": "doctrine/lexer",
        "version": "v1.0",
        "version_normalized": "1.0.0.0",
        "source": {
            "type": "git",
            "url": "https://github.com/doctrine/lexer.git",
            "reference": "v1.0"
        },
        "dist": {
            "type": "zip",
            "url": "https://github.com/doctrine/lexer/archive/v1.0.zip",
            "reference": "v1.0",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.2"
        },
        "time": "2013-01-12 18:59:04",
        "type": "library",
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Doctrine\\Common\\Lexer\\": "lib/"
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Guilherme Blanco",
                "email": "guilhermeblanco@gmail.com",
                "homepage": "http://www.instaclick.com"
            },
            {
                "name": "Roman Borschel",
                "email": "roman@code-factory.org"
            },
            {
                "name": "Johannes Schmitt",
                "email": "schmittjoh@gmail.com",
                "homepage": "http://jmsyst.com",
                "role": "Developer of wrapped JMSSerializerBundle"
            }
        ],
        "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.",
        "homepage": "http://www.doctrine-project.org",
        "keywords": [
            "lexer",
            "parser"
        ]
    },
    {
        "name": "phpcollection/phpcollection",
        "version": "0.2.0",
        "version_normalized": "0.2.0.0",
        "source": {
            "type": "git",
            "url": "https://github.com/schmittjoh/php-collection.git",
            "reference": "0.2.0"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/schmittjoh/php-collection/zipball/0.2.0",
            "reference": "0.2.0",
            "shasum": ""
        },
        "require": {
            "phpoption/phpoption": "1.*"
        },
        "time": "2013-01-23 15:16:14",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "0.2-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "PhpCollection": "src/"
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "Apache2"
        ],
        "authors": [
            {
                "name": "Johannes M. Schmitt",
                "email": "schmittjoh@gmail.com",
                "homepage": "http://jmsyst.com",
                "role": "Developer of wrapped JMSSerializerBundle"
            }
        ],
        "description": "General-Purpose Collection Library for PHP",
        "keywords": [
            "collection",
            "list",
            "map",
            "sequence",
            "set"
        ]
    },
    {
        "name": "phpunit/php-text-template",
        "version": "1.1.4",
        "version_normalized": "1.1.4.0",
        "source": {
            "type": "git",
            "url": "git://github.com/sebastianbergmann/php-text-template.git",
            "reference": "1.1.4"
        },
        "dist": {
            "type": "zip",
            "url": "https://github.com/sebastianbergmann/php-text-template/zipball/1.1.4",
            "reference": "1.1.4",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3"
        },
        "time": "2012-10-31 11:15:28",
        "type": "library",
        "installation-source": "source",
        "autoload": {
            "classmap": [
                "Text/"
            ]
        },
        "notification-url": "https://packagist.org/downloads/",
        "include-path": [
            ""
        ],
        "license": [
            "BSD-3-Clause"
        ],
        "authors": [
            {
                "name": "Sebastian Bergmann",
                "email": "sb@sebastian-bergmann.de",
                "role": "lead"
            }
        ],
        "description": "Simple template engine.",
        "homepage": "https://github.com/sebastianbergmann/php-text-template/",
        "keywords": [
            "template"
        ]
    },
    {
        "name": "phpunit/phpunit-mock-objects",
        "version": "1.2.3",
        "version_normalized": "1.2.3.0",
        "source": {
            "type": "git",
            "url": "git://github.com/sebastianbergmann/phpunit-mock-objects.git",
            "reference": "1.2.3"
        },
        "dist": {
            "type": "zip",
            "url": "https://github.com/sebastianbergmann/phpunit-mock-objects/archive/1.2.3.zip",
            "reference": "1.2.3",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3",
            "phpunit/php-text-template": ">=1.1.1@stable"
        },
        "suggest": {
            "ext-soap": "*"
        },
        "time": "2013-01-13 10:24:48",
        "type": "library",
        "installation-source": "source",
        "autoload": {
            "classmap": [
                "PHPUnit/"
            ]
        },
        "notification-url": "https://packagist.org/downloads/",
        "include-path": [
            ""
        ],
        "license": [
            "BSD-3-Clause"
        ],
        "authors": [
            {
                "name": "Sebastian Bergmann",
                "email": "sb@sebastian-bergmann.de",
                "role": "lead"
            }
        ],
        "description": "Mock Object library for PHPUnit",
        "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
        "keywords": [
            "mock",
            "xunit"
        ]
    },
    {
        "name": "phpdocumentor/graphviz",
        "version": "1.0.0",
        "version_normalized": "1.0.0.0",
        "source": {
            "type": "git",
            "url": "https://github.com/phpDocumentor/GraphViz.git",
            "reference": "1.0.0"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/phpDocumentor/GraphViz/zipball/1.0.0",
            "reference": "1.0.0",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3"
        },
        "require-dev": {
            "phpunit/phpunit": "~3.7"
        },
        "time": "2013-08-06 20:57:15",
        "type": "library",
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "phpDocumentor": [
                    "src/",
                    "tests/unit"
                ]
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Mike van Riel",
                "email": "mike.vanriel@naenius.com"
            }
        ]
    },
    {
        "name": "phpdocumentor/fileset",
        "version": "1.0.0",
        "version_normalized": "1.0.0.0",
        "source": {
            "type": "git",
            "url": "https://github.com/phpDocumentor/Fileset.git",
            "reference": "1.0.0"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/phpDocumentor/Fileset/zipball/1.0.0",
            "reference": "1.0.0",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3",
            "symfony/finder": "~2.1"
        },
        "require-dev": {
            "phpunit/phpunit": "~3.7"
        },
        "time": "2013-08-06 21:07:42",
        "type": "library",
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "phpDocumentor": [
                    "src/",
                    "tests/unit/"
                ]
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "description": "Fileset component for collecting a set of files given directories and file paths",
        "homepage": "http://www.phpdoc.org",
        "keywords": [
            "files",
            "fileset",
            "phpdoc"
        ]
    },
    {
        "name": "phpunit/php-timer",
        "version": "1.0.5",
        "version_normalized": "1.0.5.0",
        "source": {
            "type": "git",
            "url": "https://github.com/sebastianbergmann/php-timer.git",
            "reference": "1.0.5"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/1.0.5",
            "reference": "1.0.5",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3"
        },
        "time": "2013-08-02 07:42:54",
        "type": "library",
        "installation-source": "source",
        "autoload": {
            "classmap": [
                "PHP/"
            ]
        },
        "notification-url": "https://packagist.org/downloads/",
        "include-path": [
            ""
        ],
        "license": [
            "BSD-3-Clause"
        ],
        "authors": [
            {
                "name": "Sebastian Bergmann",
                "email": "sb@sebastian-bergmann.de",
                "role": "lead"
            }
        ],
        "description": "Utility class for timing",
        "homepage": "https://github.com/sebastianbergmann/php-timer/",
        "keywords": [
            "timer"
        ]
    },
    {
        "name": "phpdocumentor/unified-asset-installer",
        "version": "1.1.2",
        "version_normalized": "1.1.2.0",
        "source": {
            "type": "git",
            "url": "https://github.com/phpDocumentor/UnifiedAssetInstaller.git",
            "reference": "241fb036268cd9da7d76da3db66e3eda66259c52"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/phpDocumentor/UnifiedAssetInstaller/zipball/241fb036268cd9da7d76da3db66e3eda66259c52",
            "reference": "241fb036268cd9da7d76da3db66e3eda66259c52",
            "shasum": ""
        },
        "require": {
            "composer-plugin-api": "1.0.0"
        },
        "require-dev": {
            "composer/composer": "~1.0@dev",
            "phpunit/phpunit": "~3.7"
        },
        "time": "2013-09-09 06:13:02",
        "type": "composer-installer",
        "extra": {
            "class": "\\phpDocumentor\\Composer\\UnifiedAssetInstaller"
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "phpDocumentor\\Composer": [
                    "src/",
                    "test/unit/"
                ]
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "description": "Asset installer for phpDocumentor",
        "homepage": "http://www.phpdoc.org",
        "keywords": [
            "assets",
            "installer",
            "plugins",
            "templates"
        ]
    },
    {
        "name": "phpdocumentor/template-checkstyle",
        "version": "1.2.0",
        "version_normalized": "1.2.0.0",
        "source": {
            "type": "git",
            "url": "https://github.com/phpDocumentor/template.checkstyle.git",
            "reference": "1.2.0"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/phpDocumentor/template.checkstyle/zipball/1.2.0",
            "reference": "1.2.0",
            "shasum": ""
        },
        "require": {
            "ext-xsl": "*",
            "phpdocumentor/unified-asset-installer": "~1.1"
        },
        "time": "2013-08-01 19:43:19",
        "type": "phpdocumentor-template",
        "installation-source": "dist",
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "description": "Checkstyle XML output template for phpDocumentor2",
        "homepage": "http://www.phpdoc.org",
        "keywords": [
            "documentation",
            "phpdoc",
            "template"
        ]
    },
    {
        "name": "phpdocumentor/template-abstract",
        "version": "1.2.1",
        "version_normalized": "1.2.1.0",
        "source": {
            "type": "git",
            "url": "https://github.com/phpDocumentor/template.abstract.git",
            "reference": "1.2.1"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/phpDocumentor/template.abstract/zipball/1.2.1",
            "reference": "1.2.1",
            "shasum": ""
        },
        "require": {
            "ext-xsl": "*",
            "phpdocumentor/unified-asset-installer": "~1.1"
        },
        "time": "2013-08-02 06:11:13",
        "type": "phpdocumentor-template",
        "installation-source": "dist",
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "description": "Simple bright template for phpDocumentor",
        "homepage": "http://www.phpdoc.org",
        "keywords": [
            "documentation",
            "phpdoc",
            "template"
        ]
    },
    {
        "name": "phpdocumentor/template-new-black",
        "version": "1.3.1",
        "version_normalized": "1.3.1.0",
        "source": {
            "type": "git",
            "url": "https://github.com/phpDocumentor/template.new_black.git",
            "reference": "1.3.1"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/phpDocumentor/template.new_black/zipball/1.3.1",
            "reference": "1.3.1",
            "shasum": ""
        },
        "require": {
            "ext-xsl": "*",
            "phpdocumentor/template-abstract": "1.*",
            "phpdocumentor/unified-asset-installer": "~1.1"
        },
        "time": "2013-08-02 06:16:30",
        "type": "phpdocumentor-template",
        "installation-source": "dist",
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "description": "Web 2.0 template with dark sidebar for phpDocumentor",
        "homepage": "http://www.phpdoc.org",
        "keywords": [
            "documentation",
            "phpdoc",
            "template"
        ]
    },
    {
        "name": "phpdocumentor/template-old-ocean",
        "version": "1.3.1",
        "version_normalized": "1.3.1.0",
        "source": {
            "type": "git",
            "url": "https://github.com/phpDocumentor/template.old_ocean.git",
            "reference": "1.3.1"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/phpDocumentor/template.old_ocean/zipball/1.3.1",
            "reference": "1.3.1",
            "shasum": ""
        },
        "require": {
            "ext-xsl": "*",
            "phpdocumentor/unified-asset-installer": "~1.1"
        },
        "time": "2013-08-02 06:21:07",
        "type": "phpdocumentor-template",
        "installation-source": "dist",
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "description": "Blue template with high contrast for the foreground",
        "homepage": "http://www.phpdoc.org",
        "keywords": [
            "documentation",
            "phpdoc",
            "template"
        ]
    },
    {
        "name": "phpdocumentor/template-xml",
        "version": "1.2.0",
        "version_normalized": "1.2.0.0",
        "source": {
            "type": "git",
            "url": "https://github.com/mvriel/template.xml.git",
            "reference": "1.2.0"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/mvriel/template.xml/zipball/1.2.0",
            "reference": "1.2.0",
            "shasum": ""
        },
        "require": {
            "phpdocumentor/unified-asset-installer": "~1.1"
        },
        "time": "2013-08-01 20:23:32",
        "type": "phpdocumentor-template",
        "installation-source": "dist",
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "description": "Generates an XML representation of the project's structure",
        "homepage": "http://www.phpdoc.org",
        "keywords": [
            "documentation",
            "phpdoc",
            "template"
        ]
    },
    {
        "name": "mikey179/vfsStream",
        "version": "v1.2.0",
        "version_normalized": "1.2.0.0",
        "source": {
            "type": "git",
            "url": "https://github.com/mikey179/vfsStream.git",
            "reference": "063fb10633f10c5ccbcac26227e94f46d9336f90"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/mikey179/vfsStream/zipball/063fb10633f10c5ccbcac26227e94f46d9336f90",
            "reference": "063fb10633f10c5ccbcac26227e94f46d9336f90",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.0"
        },
        "time": "2013-04-01 10:41:02",
        "type": "library",
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "org\\bovigo\\vfs\\": "src/main/php"
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "BSD"
        ],
        "homepage": "http://vfs.bovigo.org/"
    },
    {
        "name": "phpoption/phpoption",
        "version": "1.3.0",
        "version_normalized": "1.3.0.0",
        "source": {
            "type": "git",
            "url": "https://github.com/schmittjoh/php-option.git",
            "reference": "1c7e8016289d17d83ced49c56d0f266fd0568941"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/1c7e8016289d17d83ced49c56d0f266fd0568941",
            "reference": "1c7e8016289d17d83ced49c56d0f266fd0568941",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.0"
        },
        "time": "2013-05-19 11:09:35",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "1.3-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "PhpOption\\": "src/"
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "Apache2"
        ],
        "authors": [
            {
                "name": "Johannes M. Schmitt",
                "email": "schmittjoh@gmail.com",
                "homepage": "http://jmsyst.com",
                "role": "Developer of wrapped JMSSerializerBundle"
            }
        ],
        "description": "Option Type for PHP",
        "keywords": [
            "language",
            "option",
            "php",
            "type"
        ]
    },
    {
        "name": "jms/serializer",
        "version": "0.13.0",
        "version_normalized": "0.13.0.0",
        "source": {
            "type": "git",
            "url": "https://github.com/schmittjoh/serializer.git",
            "reference": "9e0fcd00a374e9ad484687628c6c25ab1083ea5a"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/9e0fcd00a374e9ad484687628c6c25ab1083ea5a",
            "reference": "9e0fcd00a374e9ad484687628c6c25ab1083ea5a",
            "shasum": ""
        },
        "require": {
            "doctrine/annotations": "1.*",
            "jms/metadata": "~1.1",
            "jms/parser-lib": "1.*",
            "php": ">=5.3.2",
            "phpcollection/phpcollection": ">=0.1,<0.3-dev"
        },
        "require-dev": {
            "doctrine/orm": ">=2.1,<2.4-dev",
            "symfony/filesystem": "2.*",
            "symfony/form": ">=2.1,<2.2-dev",
            "symfony/translation": ">=2.0,<2.2-dev",
            "symfony/validator": ">=2.0,<2.2-dev",
            "symfony/yaml": "2.*",
            "twig/twig": ">=1.8,<2.0-dev"
        },
        "suggest": {
            "symfony/yaml": "Required if you'd like to serialize data to YAML format."
        },
        "time": "2013-07-29 13:39:49",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "0.13-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "JMS\\Serializer": "src/"
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "Apache2"
        ],
        "authors": [
            {
                "name": "Johannes M. Schmitt",
                "email": "schmittjoh@gmail.com",
                "homepage": "https://github.com/schmittjoh",
                "role": "Developer of wrapped JMSSerializerBundle"
            }
        ],
        "description": "Library for (de-)serializing data of any complexity; supports XML, JSON, and YAML.",
        "homepage": "http://jmsyst.com/libs/serializer",
        "keywords": [
            "deserialization",
            "jaxb",
            "json",
            "serialization",
            "xml"
        ]
    },
    {
        "name": "nikic/php-parser",
        "version": "v0.9.4",
        "version_normalized": "0.9.4.0",
        "source": {
            "type": "git",
            "url": "https://github.com/nikic/PHP-Parser.git",
            "reference": "1e5e280ae88a27effa2ae4aa2bd088494ed8594f"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1e5e280ae88a27effa2ae4aa2bd088494ed8594f",
            "reference": "1e5e280ae88a27effa2ae4aa2bd088494ed8594f",
            "shasum": ""
        },
        "require": {
            "php": ">=5.2"
        },
        "time": "2013-08-25 17:11:40",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "0.9-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "PHPParser": "lib/"
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "BSD-3-Clause"
        ],
        "authors": [
            {
                "name": "Nikita Popov"
            }
        ],
        "description": "A PHP parser written in PHP",
        "keywords": [
            "parser",
            "php"
        ]
    },
    {
        "name": "phpunit/php-token-stream",
        "version": "1.2.1",
        "version_normalized": "1.2.1.0",
        "source": {
            "type": "git",
            "url": "https://github.com/sebastianbergmann/php-token-stream.git",
            "reference": "5220af2a7929aa35cf663d97c89ad3d50cf5fa3e"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/5220af2a7929aa35cf663d97c89ad3d50cf5fa3e",
            "reference": "5220af2a7929aa35cf663d97c89ad3d50cf5fa3e",
            "shasum": ""
        },
        "require": {
            "ext-tokenizer": "*",
            "php": ">=5.3.3"
        },
        "time": "2013-09-13 04:58:23",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "1.2-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "classmap": [
                "PHP/"
            ]
        },
        "notification-url": "https://packagist.org/downloads/",
        "include-path": [
            ""
        ],
        "license": [
            "BSD-3-Clause"
        ],
        "authors": [
            {
                "name": "Sebastian Bergmann",
                "email": "sb@sebastian-bergmann.de",
                "role": "lead"
            }
        ],
        "description": "Wrapper around PHP's tokenizer extension.",
        "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
        "keywords": [
            "tokenizer"
        ]
    },
    {
        "name": "phpunit/php-code-coverage",
        "version": "1.2.13",
        "version_normalized": "1.2.13.0",
        "source": {
            "type": "git",
            "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
            "reference": "466e7cd2554b4e264c9e3f31216d25ac0e5f3d94"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/466e7cd2554b4e264c9e3f31216d25ac0e5f3d94",
            "reference": "466e7cd2554b4e264c9e3f31216d25ac0e5f3d94",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3",
            "phpunit/php-file-iterator": ">=1.3.0@stable",
            "phpunit/php-text-template": ">=1.1.1@stable",
            "phpunit/php-token-stream": ">=1.1.3@stable"
        },
        "require-dev": {
            "phpunit/phpunit": "3.7.*@dev"
        },
        "suggest": {
            "ext-dom": "*",
            "ext-xdebug": ">=2.0.5"
        },
        "time": "2013-09-10 08:14:32",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "1.2.x-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "classmap": [
                "PHP/"
            ]
        },
        "notification-url": "https://packagist.org/downloads/",
        "include-path": [
            ""
        ],
        "license": [
            "BSD-3-Clause"
        ],
        "authors": [
            {
                "name": "Sebastian Bergmann",
                "email": "sb@sebastian-bergmann.de",
                "role": "lead"
            }
        ],
        "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
        "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
        "keywords": [
            "coverage",
            "testing",
            "xunit"
        ]
    },
    {
        "name": "twig/twig",
        "version": "v1.14.2",
        "version_normalized": "1.14.2.0",
        "source": {
            "type": "git",
            "url": "https://github.com/fabpot/Twig.git",
            "reference": "ca445842fcea4f844d68203ffa2d00f5e3cdea64"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/fabpot/Twig/zipball/ca445842fcea4f844d68203ffa2d00f5e3cdea64",
            "reference": "ca445842fcea4f844d68203ffa2d00f5e3cdea64",
            "shasum": ""
        },
        "require": {
            "php": ">=5.2.4"
        },
        "time": "2013-10-30 08:20:53",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "1.14-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Twig_": "lib/"
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "BSD-3-Clause"
        ],
        "authors": [
            {
                "name": "Fabien Potencier",
                "email": "fabien@symfony.com"
            },
            {
                "name": "Armin Ronacher",
                "email": "armin.ronacher@active-4.com"
            }
        ],
        "description": "Twig, the flexible, fast, and secure template language for PHP",
        "homepage": "http://twig.sensiolabs.org",
        "keywords": [
            "templating"
        ]
    },
    {
        "name": "monolog/monolog",
        "version": "1.7.0",
        "version_normalized": "1.7.0.0",
        "source": {
            "type": "git",
            "url": "https://github.com/Seldaek/monolog.git",
            "reference": "6225b22de9dcf36546be3a0b2fa8e3d986153f57"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/Seldaek/monolog/zipball/6225b22de9dcf36546be3a0b2fa8e3d986153f57",
            "reference": "6225b22de9dcf36546be3a0b2fa8e3d986153f57",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.0",
            "psr/log": "~1.0"
        },
        "require-dev": {
            "aws/aws-sdk-php": "~2.4.8",
            "doctrine/couchdb": "dev-master",
            "mlehner/gelf-php": "1.0.*",
            "phpunit/phpunit": "~3.7.0",
            "raven/raven": "0.5.*",
            "ruflin/elastica": "0.90.*"
        },
        "suggest": {
            "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
            "doctrine/couchdb": "Allow sending log messages to a CouchDB server",
            "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
            "ext-mongo": "Allow sending log messages to a MongoDB server",
            "mlehner/gelf-php": "Allow sending log messages to a GrayLog2 server",
            "raven/raven": "Allow sending log messages to a Sentry server",
            "ruflin/elastica": "Allow sending log messages to an Elastic Search server"
        },
        "time": "2013-11-14 19:48:31",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "1.7.x-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Monolog": "src/"
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Jordi Boggiano",
                "email": "j.boggiano@seld.be",
                "homepage": "http://seld.be",
                "role": "Developer"
            }
        ],
        "description": "Sends your logs to files, sockets, inboxes, databases and various web services",
        "homepage": "http://github.com/Seldaek/monolog",
        "keywords": [
            "log",
            "logging",
            "psr-3"
        ]
    },
    {
        "name": "zendframework/zend-stdlib",
        "version": "2.2.5",
        "version_normalized": "2.2.5.0",
        "target-dir": "Zend/Stdlib",
        "source": {
            "type": "git",
            "url": "https://github.com/zendframework/Component_ZendStdlib.git",
            "reference": "f440ecfc828d61d620662a03987c8287e1e4801e"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/zendframework/Component_ZendStdlib/zipball/f440ecfc828d61d620662a03987c8287e1e4801e",
            "reference": "f440ecfc828d61d620662a03987c8287e1e4801e",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3"
        },
        "suggest": {
            "zendframework/zend-eventmanager": "To support aggregate hydrator usage",
            "zendframework/zend-servicemanager": "To support hydrator plugin manager usage"
        },
        "time": "2013-10-20 06:00:20",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.2-dev",
                "dev-develop": "2.3-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Zend\\Stdlib\\": ""
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "BSD-3-Clause"
        ],
        "keywords": [
            "stdlib",
            "zf2"
        ]
    },
    {
        "name": "zendframework/zend-i18n",
        "version": "2.2.5",
        "version_normalized": "2.2.5.0",
        "target-dir": "Zend/I18n",
        "source": {
            "type": "git",
            "url": "https://github.com/zendframework/Component_ZendI18n.git",
            "reference": "d69eda2fc0e137412eeca3340952eb94345a5c25"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/zendframework/Component_ZendI18n/zipball/d69eda2fc0e137412eeca3340952eb94345a5c25",
            "reference": "d69eda2fc0e137412eeca3340952eb94345a5c25",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3",
            "zendframework/zend-stdlib": "self.version"
        },
        "suggest": {
            "ext-intl": "Required for most features of Zend\\I18n; included in default builds of PHP",
            "zendframework/zend-eventmanager": "You should install this package to use the events in the translator",
            "zendframework/zend-filter": "You should install this package to use the provided filters",
            "zendframework/zend-resources": "Translation resources",
            "zendframework/zend-validator": "You should install this package to use the provided validators",
            "zendframework/zend-view": "You should install this package to use the provided view helpers"
        },
        "time": "2013-10-23 20:00:09",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.2-dev",
                "dev-develop": "2.3-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Zend\\I18n\\": ""
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "BSD-3-Clause"
        ],
        "keywords": [
            "i18n",
            "zf2"
        ]
    },
    {
        "name": "zendframework/zend-eventmanager",
        "version": "2.2.5",
        "version_normalized": "2.2.5.0",
        "target-dir": "Zend/EventManager",
        "source": {
            "type": "git",
            "url": "https://github.com/zendframework/Component_ZendEventManager.git",
            "reference": "f325feef4e1a19b873936e5b116980fbe88dd176"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/zendframework/Component_ZendEventManager/zipball/f325feef4e1a19b873936e5b116980fbe88dd176",
            "reference": "f325feef4e1a19b873936e5b116980fbe88dd176",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3",
            "zendframework/zend-stdlib": "self.version"
        },
        "time": "2013-06-12 19:45:10",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.2-dev",
                "dev-develop": "2.3-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Zend\\EventManager\\": ""
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "BSD-3-Clause"
        ],
        "keywords": [
            "eventmanager",
            "zf2"
        ]
    },
    {
        "name": "zendframework/zend-servicemanager",
        "version": "2.2.5",
        "version_normalized": "2.2.5.0",
        "target-dir": "Zend/ServiceManager",
        "source": {
            "type": "git",
            "url": "https://github.com/zendframework/Component_ZendServiceManager.git",
            "reference": "064bb1d0441529aded2f213a10002cc4523f328c"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/zendframework/Component_ZendServiceManager/zipball/064bb1d0441529aded2f213a10002cc4523f328c",
            "reference": "064bb1d0441529aded2f213a10002cc4523f328c",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3"
        },
        "suggest": {
            "zendframework/zend-di": "Zend\\Di component"
        },
        "time": "2013-10-23 20:00:05",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.2-dev",
                "dev-develop": "2.3-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Zend\\ServiceManager\\": ""
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "BSD-3-Clause"
        ],
        "keywords": [
            "servicemanager",
            "zf2"
        ]
    },
    {
        "name": "zendframework/zend-cache",
        "version": "2.2.5",
        "version_normalized": "2.2.5.0",
        "target-dir": "Zend/Cache",
        "source": {
            "type": "git",
            "url": "https://github.com/zendframework/Component_ZendCache.git",
            "reference": "49e5c3a59c4acb3e3e0a5b251f31b274889b1f97"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/zendframework/Component_ZendCache/zipball/49e5c3a59c4acb3e3e0a5b251f31b274889b1f97",
            "reference": "49e5c3a59c4acb3e3e0a5b251f31b274889b1f97",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3",
            "zendframework/zend-eventmanager": "self.version",
            "zendframework/zend-servicemanager": "self.version",
            "zendframework/zend-stdlib": "self.version"
        },
        "require-dev": {
            "zendframework/zend-serializer": "self.version"
        },
        "suggest": {
            "ext-apc": "APC >= 3.1.6 to use the APC storage adapter",
            "ext-dba": "DBA, to use the DBA storage adapter",
            "ext-memcached": "Memcached >= 1.0.0 to use the Memcached storage adapter",
            "ext-wincache": "WinCache, to use the WinCache storage adapter",
            "zendframework/zend-serializer": "Zend\\Serializer component",
            "zendframework/zend-session": "Zend\\Session component"
        },
        "time": "2013-10-26 10:00:05",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.2-dev",
                "dev-develop": "2.3-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Zend\\Cache\\": ""
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "BSD-3-Clause"
        ],
        "description": "provides a generic way to cache any data",
        "keywords": [
            "cache",
            "zf2"
        ]
    },
    {
        "name": "zendframework/zend-math",
        "version": "2.2.5",
        "version_normalized": "2.2.5.0",
        "target-dir": "Zend/Math",
        "source": {
            "type": "git",
            "url": "https://github.com/zendframework/Component_ZendMath.git",
            "reference": "7cba0957e916b705ba280f31919e6acfa3d983fd"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/zendframework/Component_ZendMath/zipball/7cba0957e916b705ba280f31919e6acfa3d983fd",
            "reference": "7cba0957e916b705ba280f31919e6acfa3d983fd",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3"
        },
        "suggest": {
            "ircmaxell/random-lib": "Fallback random byte generator for Zend\\Math\\Rand if OpenSSL/Mcrypt extensions are unavailable"
        },
        "time": "2013-10-02 08:00:14",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.2-dev",
                "dev-develop": "2.3-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Zend\\Math\\": ""
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "BSD-3-Clause"
        ],
        "keywords": [
            "math",
            "zf2"
        ]
    },
    {
        "name": "zendframework/zend-json",
        "version": "2.2.5",
        "version_normalized": "2.2.5.0",
        "target-dir": "Zend/Json",
        "source": {
            "type": "git",
            "url": "https://github.com/zendframework/Component_ZendJson.git",
            "reference": "f4394103c3db6052de75bbfcf6613888b0a63d9b"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/zendframework/Component_ZendJson/zipball/f4394103c3db6052de75bbfcf6613888b0a63d9b",
            "reference": "f4394103c3db6052de75bbfcf6613888b0a63d9b",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3",
            "zendframework/zend-stdlib": "self.version"
        },
        "suggest": {
            "zendframework/zend-server": "Zend\\Server component"
        },
        "time": "2013-10-20 06:00:16",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.2-dev",
                "dev-develop": "2.3-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Zend\\Json\\": ""
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "BSD-3-Clause"
        ],
        "description": "provides convenience methods for serializing native PHP to JSON and decoding JSON to native PHP",
        "keywords": [
            "json",
            "zf2"
        ]
    },
    {
        "name": "zendframework/zend-serializer",
        "version": "2.2.5",
        "version_normalized": "2.2.5.0",
        "target-dir": "Zend/Serializer",
        "source": {
            "type": "git",
            "url": "https://github.com/zendframework/Component_ZendSerializer.git",
            "reference": "ba5a28e04c6f933f01248357021486042a7d5fb7"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/zendframework/Component_ZendSerializer/zipball/ba5a28e04c6f933f01248357021486042a7d5fb7",
            "reference": "ba5a28e04c6f933f01248357021486042a7d5fb7",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3",
            "zendframework/zend-json": "self.version",
            "zendframework/zend-math": "self.version",
            "zendframework/zend-stdlib": "self.version"
        },
        "suggest": {
            "zendframework/zend-servicemanager": "To support plugin manager support"
        },
        "time": "2013-10-02 08:00:15",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.2-dev",
                "dev-develop": "2.3-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Zend\\Serializer\\": ""
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "BSD-3-Clause"
        ],
        "description": "provides an adapter based interface to simply generate storable representation of PHP types by different facilities, and recover",
        "keywords": [
            "serializer",
            "zf2"
        ]
    },
    {
        "name": "zendframework/zend-config",
        "version": "2.2.5",
        "version_normalized": "2.2.5.0",
        "target-dir": "Zend/Config",
        "source": {
            "type": "git",
            "url": "https://github.com/zendframework/Component_ZendConfig.git",
            "reference": "e3457e088f641bfd5b02d9985c1ef504a571bc62"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/zendframework/Component_ZendConfig/zipball/e3457e088f641bfd5b02d9985c1ef504a571bc62",
            "reference": "e3457e088f641bfd5b02d9985c1ef504a571bc62",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3",
            "zendframework/zend-stdlib": "self.version"
        },
        "suggest": {
            "zendframework/zend-json": "Zend\\Json to use the Json reader or writer classes",
            "zendframework/zend-servicemanager": "Zend\\ServiceManager for use with the Config Factory to retrieve reader and writer instances"
        },
        "time": "2013-10-02 08:00:13",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.2-dev",
                "dev-develop": "2.3-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Zend\\Config\\": ""
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "BSD-3-Clause"
        ],
        "description": "provides a nested object property based user interface for accessing this configuration data within application code",
        "keywords": [
            "config",
            "zf2"
        ]
    },
    {
        "name": "zendframework/zend-filter",
        "version": "2.2.5",
        "version_normalized": "2.2.5.0",
        "target-dir": "Zend/Filter",
        "source": {
            "type": "git",
            "url": "https://github.com/zendframework/Component_ZendFilter.git",
            "reference": "0dbe1c10822a340a253a99147bb004978915f641"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/zendframework/Component_ZendFilter/zipball/0dbe1c10822a340a253a99147bb004978915f641",
            "reference": "0dbe1c10822a340a253a99147bb004978915f641",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3",
            "zendframework/zend-stdlib": "self.version"
        },
        "require-dev": {
            "zendframework/zend-crypt": "self.version"
        },
        "suggest": {
            "zendframework/zend-crypt": "Zend\\Crypt component",
            "zendframework/zend-i18n": "Zend\\I18n component",
            "zendframework/zend-stdlib": "Zend\\Stdlib component",
            "zendframework/zend-uri": "Zend\\Uri component for UriNormalize filter",
            "zendframework/zend-validator": "Zend\\Validator component"
        },
        "time": "2013-10-20 06:00:14",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.2-dev",
                "dev-develop": "2.3-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Zend\\Filter\\": ""
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "BSD-3-Clause"
        ],
        "description": "provides a set of commonly needed data filters",
        "keywords": [
            "filter",
            "zf2"
        ]
    },
    {
        "name": "phpunit/php-file-iterator",
        "version": "1.3.4",
        "version_normalized": "1.3.4.0",
        "source": {
            "type": "git",
            "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
            "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb",
            "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3"
        },
        "time": "2013-10-10 15:34:57",
        "type": "library",
        "installation-source": "source",
        "autoload": {
            "classmap": [
                "File/"
            ]
        },
        "notification-url": "https://packagist.org/downloads/",
        "include-path": [
            ""
        ],
        "license": [
            "BSD-3-Clause"
        ],
        "authors": [
            {
                "name": "Sebastian Bergmann",
                "email": "sb@sebastian-bergmann.de",
                "role": "lead"
            }
        ],
        "description": "FilterIterator implementation that filters files based on a list of suffixes.",
        "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
        "keywords": [
            "filesystem",
            "iterator"
        ]
    },
    {
        "name": "phpunit/phpunit",
        "version": "3.7.28",
        "version_normalized": "3.7.28.0",
        "source": {
            "type": "git",
            "url": "https://github.com/sebastianbergmann/phpunit.git",
            "reference": "3b97c8492bcafbabe6b6fbd2ab35f2f04d932a8d"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3b97c8492bcafbabe6b6fbd2ab35f2f04d932a8d",
            "reference": "3b97c8492bcafbabe6b6fbd2ab35f2f04d932a8d",
            "shasum": ""
        },
        "require": {
            "ext-dom": "*",
            "ext-pcre": "*",
            "ext-reflection": "*",
            "ext-spl": "*",
            "php": ">=5.3.3",
            "phpunit/php-code-coverage": "~1.2.1",
            "phpunit/php-file-iterator": ">=1.3.1",
            "phpunit/php-text-template": ">=1.1.1",
            "phpunit/php-timer": ">=1.0.4",
            "phpunit/phpunit-mock-objects": "~1.2.0",
            "symfony/yaml": "~2.0"
        },
        "require-dev": {
            "pear-pear/pear": "1.9.4"
        },
        "suggest": {
            "ext-json": "*",
            "ext-simplexml": "*",
            "ext-tokenizer": "*",
            "phpunit/php-invoker": ">=1.1.0,<1.2.0"
        },
        "time": "2013-10-17 07:27:40",
        "bin": [
            "composer/bin/phpunit"
        ],
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "3.7.x-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "classmap": [
                "PHPUnit/"
            ]
        },
        "notification-url": "https://packagist.org/downloads/",
        "include-path": [
            "",
            "../../symfony/yaml/"
        ],
        "license": [
            "BSD-3-Clause"
        ],
        "authors": [
            {
                "name": "Sebastian Bergmann",
                "email": "sebastian@phpunit.de",
                "role": "lead"
            }
        ],
        "description": "The PHP Unit Testing framework.",
        "homepage": "http://www.phpunit.de/",
        "keywords": [
            "phpunit",
            "testing",
            "xunit"
        ]
    },
    {
        "name": "squizlabs/php_codesniffer",
        "version": "1.5.0",
        "version_normalized": "1.5.0.0",
        "source": {
            "type": "git",
            "url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
            "reference": "0191c4f193a62915227ac7946b1600c82cc3c253"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/0191c4f193a62915227ac7946b1600c82cc3c253",
            "reference": "0191c4f193a62915227ac7946b1600c82cc3c253",
            "shasum": ""
        },
        "require": {
            "ext-tokenizer": "*",
            "php": ">=5.1.2"
        },
        "suggest": {
            "phpunit/php-timer": "dev-master"
        },
        "time": "2013-11-27 22:22:42",
        "bin": [
            "scripts/phpcs"
        ],
        "type": "library",
        "installation-source": "source",
        "autoload": {
            "classmap": [
                "CodeSniffer.php",
                "CodeSniffer/CLI.php",
                "CodeSniffer/Exception.php",
                "CodeSniffer/File.php",
                "CodeSniffer/Report.php",
                "CodeSniffer/Reporting.php",
                "CodeSniffer/Sniff.php",
                "CodeSniffer/Tokens.php",
                "CodeSniffer/Reports/",
                "CodeSniffer/CommentParser/",
                "CodeSniffer/Tokenizers/",
                "CodeSniffer/DocGenerators/",
                "CodeSniffer/Standards/AbstractPatternSniff.php",
                "CodeSniffer/Standards/AbstractScopeSniff.php",
                "CodeSniffer/Standards/AbstractVariableSniff.php",
                "CodeSniffer/Standards/IncorrectPatternException.php",
                "CodeSniffer/Standards/Generic/Sniffs/",
                "CodeSniffer/Standards/MySource/Sniffs/",
                "CodeSniffer/Standards/PEAR/Sniffs/",
                "CodeSniffer/Standards/PSR1/Sniffs/",
                "CodeSniffer/Standards/PSR2/Sniffs/",
                "CodeSniffer/Standards/Squiz/Sniffs/",
                "CodeSniffer/Standards/Zend/Sniffs/"
            ]
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "BSD-3-Clause"
        ],
        "authors": [
            {
                "name": "Greg Sherwood",
                "role": "lead"
            }
        ],
        "description": "PHP_CodeSniffer tokenises PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
        "homepage": "http://www.squizlabs.com/php-codesniffer",
        "keywords": [
            "phpcs",
            "standards"
        ]
    },
    {
        "name": "jms/metadata",
        "version": "1.5.0",
        "version_normalized": "1.5.0.0",
        "source": {
            "type": "git",
            "url": "https://github.com/schmittjoh/metadata.git",
            "reference": "88ffa28bc987e4c26229fc84a2e541b6ed4e1459"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/schmittjoh/metadata/zipball/88ffa28bc987e4c26229fc84a2e541b6ed4e1459",
            "reference": "88ffa28bc987e4c26229fc84a2e541b6ed4e1459",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.0"
        },
        "require-dev": {
            "doctrine/cache": "~1.0"
        },
        "time": "2013-11-05 23:02:36",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "1.5.x-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Metadata\\": "src/"
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "Apache"
        ],
        "authors": [
            {
                "name": "Johannes M. Schmitt",
                "email": "schmittjoh@gmail.com",
                "homepage": "http://jmsyst.com",
                "role": "Developer of wrapped JMSSerializerBundle"
            }
        ],
        "description": "Class/method/property metadata management in PHP",
        "keywords": [
            "annotations",
            "metadata",
            "xml",
            "yaml"
        ]
    },
    {
        "name": "symfony/property-access",
        "version": "v2.4.0",
        "version_normalized": "2.4.0.0",
        "target-dir": "Symfony/Component/PropertyAccess",
        "source": {
            "type": "git",
            "url": "https://github.com/symfony/PropertyAccess.git",
            "reference": "274951234150e303c83099a2429be6be35629fe9"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/symfony/PropertyAccess/zipball/274951234150e303c83099a2429be6be35629fe9",
            "reference": "274951234150e303c83099a2429be6be35629fe9",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3"
        },
        "time": "2013-11-13 21:30:16",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.4-dev"
            }
        },
        "installation-source": "dist",
        "autoload": {
            "psr-0": {
                "Symfony\\Component\\PropertyAccess\\": ""
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Fabien Potencier",
                "email": "fabien@symfony.com"
            },
            {
                "name": "Symfony Community",
                "homepage": "http://symfony.com/contributors"
            }
        ],
        "description": "Symfony PropertyAccess Component",
        "homepage": "http://symfony.com",
        "keywords": [
            "access",
            "array",
            "extraction",
            "index",
            "injection",
            "object",
            "property",
            "property path",
            "reflection"
        ]
    },
    {
        "name": "symfony/translation",
        "version": "v2.4.0",
        "version_normalized": "2.4.0.0",
        "target-dir": "Symfony/Component/Translation",
        "source": {
            "type": "git",
            "url": "https://github.com/symfony/Translation.git",
            "reference": "0919e0fc709217f8c9e5049f2603419fdd4a34ff"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/symfony/Translation/zipball/0919e0fc709217f8c9e5049f2603419fdd4a34ff",
            "reference": "0919e0fc709217f8c9e5049f2603419fdd4a34ff",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3"
        },
        "require-dev": {
            "symfony/config": "~2.0",
            "symfony/yaml": "~2.2"
        },
        "suggest": {
            "symfony/config": "",
            "symfony/yaml": ""
        },
        "time": "2013-11-28 10:27:26",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.4-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Symfony\\Component\\Translation\\": ""
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Fabien Potencier",
                "email": "fabien@symfony.com"
            },
            {
                "name": "Symfony Community",
                "homepage": "http://symfony.com/contributors"
            }
        ],
        "description": "Symfony Translation Component",
        "homepage": "http://symfony.com"
    },
    {
        "name": "symfony/validator",
        "version": "v2.4.0",
        "version_normalized": "2.4.0.0",
        "target-dir": "Symfony/Component/Validator",
        "source": {
            "type": "git",
            "url": "https://github.com/symfony/Validator.git",
            "reference": "12d1f1e64a43ce9cc35151ca89dae1ae8882d991"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/symfony/Validator/zipball/12d1f1e64a43ce9cc35151ca89dae1ae8882d991",
            "reference": "12d1f1e64a43ce9cc35151ca89dae1ae8882d991",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3",
            "symfony/property-access": "~2.2",
            "symfony/translation": "~2.0"
        },
        "require-dev": {
            "doctrine/annotations": "~1.0",
            "doctrine/cache": "~1.0",
            "symfony/config": "~2.2",
            "symfony/http-foundation": "~2.1",
            "symfony/intl": "~2.3",
            "symfony/yaml": "~2.0"
        },
        "suggest": {
            "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.",
            "doctrine/cache": "For using the default cached annotation reader",
            "symfony/config": "",
            "symfony/http-foundation": "",
            "symfony/intl": "",
            "symfony/yaml": ""
        },
        "time": "2013-11-28 10:27:26",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.4-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Symfony\\Component\\Validator\\": ""
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Fabien Potencier",
                "email": "fabien@symfony.com"
            },
            {
                "name": "Symfony Community",
                "homepage": "http://symfony.com/contributors"
            }
        ],
        "description": "Symfony Validator Component",
        "homepage": "http://symfony.com"
    },
    {
        "name": "erusev/parsedown",
        "version": "0.7.4",
        "version_normalized": "0.7.4.0",
        "source": {
            "type": "git",
            "url": "https://github.com/erusev/parsedown.git",
            "reference": "8baf537c122c9ec863a044a1f10b140aeaf9fa7a"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/erusev/parsedown/zipball/8baf537c122c9ec863a044a1f10b140aeaf9fa7a",
            "reference": "8baf537c122c9ec863a044a1f10b140aeaf9fa7a",
            "shasum": ""
        },
        "time": "2013-12-02 21:26:43",
        "type": "library",
        "installation-source": "dist",
        "autoload": {
            "psr-0": {
                "Parsedown": ""
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Emanuil Rusev",
                "email": "hello@erusev.com",
                "homepage": "http://erusev.com"
            }
        ],
        "description": "Parser for Markdown.",
        "homepage": "http://parsedown.org",
        "keywords": [
            "markdown",
            "parser"
        ]
    },
    {
        "name": "symfony/stopwatch",
        "version": "v2.4.0",
        "version_normalized": "2.4.0.0",
        "target-dir": "Symfony/Component/Stopwatch",
        "source": {
            "type": "git",
            "url": "https://github.com/symfony/Stopwatch.git",
            "reference": "b43d5cc4e6405ee5aab692f991048ec18d598785"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/b43d5cc4e6405ee5aab692f991048ec18d598785",
            "reference": "b43d5cc4e6405ee5aab692f991048ec18d598785",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3"
        },
        "time": "2013-11-11 18:40:07",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.4-dev"
            }
        },
        "installation-source": "dist",
        "autoload": {
            "psr-0": {
                "Symfony\\Component\\Stopwatch\\": ""
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Fabien Potencier",
                "email": "fabien@symfony.com"
            },
            {
                "name": "Symfony Community",
                "homepage": "http://symfony.com/contributors"
            }
        ],
        "description": "Symfony Stopwatch Component",
        "homepage": "http://symfony.com"
    },
    {
        "name": "phpdocumentor/reflection-docblock",
        "version": "2.0.1",
        "version_normalized": "2.0.1.0",
        "source": {
            "type": "git",
            "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
            "reference": "cfb3ebea556b24df8f8f3745d61478293cb5a166"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/cfb3ebea556b24df8f8f3745d61478293cb5a166",
            "reference": "cfb3ebea556b24df8f8f3745d61478293cb5a166",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3"
        },
        "require-dev": {
            "phpunit/phpunit": "3.7.*@stable"
        },
        "suggest": {
            "dflydev/markdown": "1.0.*",
            "erusev/parsedown": "~0.7"
        },
        "time": "2013-12-05 08:16:55",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.0.x-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "phpDocumentor": [
                    "src/"
                ]
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Mike van Riel",
                "email": "mike.vanriel@naenius.com"
            }
        ]
    },
    {
        "name": "phpdocumentor/reflection",
        "version": "1.0.2",
        "version_normalized": "1.0.2.0",
        "source": {
            "type": "git",
            "url": "https://github.com/phpDocumentor/Reflection.git",
            "reference": "ac90c626dc11005e31a166a5cb97fe54b0931378"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/phpDocumentor/Reflection/zipball/ac90c626dc11005e31a166a5cb97fe54b0931378",
            "reference": "ac90c626dc11005e31a166a5cb97fe54b0931378",
            "shasum": ""
        },
        "require": {
            "nikic/php-parser": ">=0.9",
            "php": ">=5.3.3",
            "phpdocumentor/reflection-docblock": "2.*@dev",
            "psr/log": "~1.0"
        },
        "require-dev": {
            "behat/behat": "~2.4",
            "mockery/mockery": ">=0.7.0",
            "phpunit/phpunit": "~3.7"
        },
        "time": "2013-11-29 20:34:41",
        "type": "library",
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "phpDocumentor": [
                    "src/",
                    "tests/unit/",
                    "tests/mocks/"
                ]
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "description": "Reflection library to do Static Analysis for PHP Projects",
        "homepage": "http://www.phpdoc.org",
        "keywords": [
            "phpDocumentor",
            "phpdoc",
            "reflection",
            "static analysis"
        ]
    },
    {
        "name": "phpdocumentor/template-clean",
        "version": "1.0.2",
        "version_normalized": "1.0.2.0",
        "source": {
            "type": "git",
            "url": "https://github.com/phpDocumentor/template.clean.git",
            "reference": "9b7db5988447f901bfd04b1e2ff1adba951d4374"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/phpDocumentor/template.clean/zipball/9b7db5988447f901bfd04b1e2ff1adba951d4374",
            "reference": "9b7db5988447f901bfd04b1e2ff1adba951d4374",
            "shasum": ""
        },
        "require": {
            "phpdocumentor/unified-asset-installer": "~1.1"
        },
        "time": "2013-11-06 21:30:35",
        "type": "phpdocumentor-template",
        "installation-source": "dist",
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "description": "A clean, responsive modern template for phpDocumentor for Twig aimed at usability",
        "homepage": "http://www.phpdoc.org",
        "keywords": [
            "documentation",
            "phpdoc",
            "responsive",
            "template"
        ]
    },
    {
        "name": "phpdocumentor/template-responsive-twig",
        "version": "1.2.2",
        "version_normalized": "1.2.2.0",
        "source": {
            "type": "git",
            "url": "https://github.com/phpDocumentor/template.responsive-twig.git",
            "reference": "1f2a3ef331594fe463f698bca6c474634a127cd6"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/phpDocumentor/template.responsive-twig/zipball/1f2a3ef331594fe463f698bca6c474634a127cd6",
            "reference": "1f2a3ef331594fe463f698bca6c474634a127cd6",
            "shasum": ""
        },
        "require": {
            "phpdocumentor/unified-asset-installer": "~1.1"
        },
        "time": "2013-11-02 08:25:22",
        "type": "phpdocumentor-template",
        "installation-source": "dist",
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "description": "Responsive modern template for phpDocumentor for Twig",
        "homepage": "http://www.phpdoc.org",
        "keywords": [
            "documentation",
            "phpdoc",
            "template"
        ]
    },
    {
        "name": "phpdocumentor/template-responsive",
        "version": "1.3.2",
        "version_normalized": "1.3.2.0",
        "source": {
            "type": "git",
            "url": "https://github.com/phpDocumentor/template.responsive.git",
            "reference": "5cc453d7946ca76eb3f1b0a9ceff775d4a40f093"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/phpDocumentor/template.responsive/zipball/5cc453d7946ca76eb3f1b0a9ceff775d4a40f093",
            "reference": "5cc453d7946ca76eb3f1b0a9ceff775d4a40f093",
            "shasum": ""
        },
        "require": {
            "ext-xsl": "*",
            "phpdocumentor/unified-asset-installer": "~1.1"
        },
        "time": "2013-12-05 08:50:30",
        "type": "phpdocumentor-template",
        "installation-source": "dist",
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "description": "Responsive modern template for phpDocumentor",
        "homepage": "http://www.phpdoc.org",
        "keywords": [
            "documentation",
            "phpdoc",
            "template"
        ]
    },
    {
        "name": "phpdocumentor/template-zend",
        "version": "1.3.2",
        "version_normalized": "1.3.2.0",
        "source": {
            "type": "git",
            "url": "https://github.com/phpDocumentor/template.zend.git",
            "reference": "75913288bfd73d3bf4c1b1179c3963f3431e7a9d"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/phpDocumentor/template.zend/zipball/75913288bfd73d3bf4c1b1179c3963f3431e7a9d",
            "reference": "75913288bfd73d3bf4c1b1179c3963f3431e7a9d",
            "shasum": ""
        },
        "require": {
            "ext-xsl": "*",
            "phpdocumentor/template-abstract": "1.*",
            "phpdocumentor/unified-asset-installer": "~1.1"
        },
        "time": "2013-12-05 08:51:57",
        "type": "phpdocumentor-template",
        "installation-source": "dist",
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "description": "Official Zend Framework Template for phpDocumentor2",
        "homepage": "http://www.phpdoc.org",
        "keywords": [
            "ZendFramework",
            "documentation",
            "phpdoc",
            "template",
            "zend",
            "zf"
        ]
    },
    {
        "name": "symfony/finder",
        "version": "v2.4.0",
        "version_normalized": "2.4.0.0",
        "target-dir": "Symfony/Component/Finder",
        "source": {
            "type": "git",
            "url": "https://github.com/symfony/Finder.git",
            "reference": "72356bf0646b11af1bae666c28a639bd8ede459f"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/symfony/Finder/zipball/72356bf0646b11af1bae666c28a639bd8ede459f",
            "reference": "72356bf0646b11af1bae666c28a639bd8ede459f",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3"
        },
        "time": "2013-11-26 16:40:27",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.4-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Symfony\\Component\\Finder\\": ""
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Fabien Potencier",
                "email": "fabien@symfony.com"
            },
            {
                "name": "Symfony Community",
                "homepage": "http://symfony.com/contributors"
            }
        ],
        "description": "Symfony Finder Component",
        "homepage": "http://symfony.com"
    },
    {
        "name": "symfony/yaml",
        "version": "v2.4.0",
        "version_normalized": "2.4.0.0",
        "target-dir": "Symfony/Component/Yaml",
        "source": {
            "type": "git",
            "url": "https://github.com/symfony/Yaml.git",
            "reference": "1ae235a1b9d3ad3d9f3860ff20acc072df95b7f5"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/symfony/Yaml/zipball/1ae235a1b9d3ad3d9f3860ff20acc072df95b7f5",
            "reference": "1ae235a1b9d3ad3d9f3860ff20acc072df95b7f5",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3"
        },
        "time": "2013-11-26 16:40:27",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.4-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Symfony\\Component\\Yaml\\": ""
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Fabien Potencier",
                "email": "fabien@symfony.com"
            },
            {
                "name": "Symfony Community",
                "homepage": "http://symfony.com/contributors"
            }
        ],
        "description": "Symfony Yaml Component",
        "homepage": "http://symfony.com"
    },
    {
        "name": "symfony/event-dispatcher",
        "version": "v2.4.0",
        "version_normalized": "2.4.0.0",
        "target-dir": "Symfony/Component/EventDispatcher",
        "source": {
            "type": "git",
            "url": "https://github.com/symfony/EventDispatcher.git",
            "reference": "acd1707236f6eb96fbb8d58f63d289b72ebc2f6e"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/acd1707236f6eb96fbb8d58f63d289b72ebc2f6e",
            "reference": "acd1707236f6eb96fbb8d58f63d289b72ebc2f6e",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3"
        },
        "require-dev": {
            "symfony/dependency-injection": "~2.0"
        },
        "suggest": {
            "symfony/dependency-injection": "",
            "symfony/http-kernel": ""
        },
        "time": "2013-12-03 14:52:22",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.4-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Symfony\\Component\\EventDispatcher\\": ""
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Fabien Potencier",
                "email": "fabien@symfony.com"
            },
            {
                "name": "Symfony Community",
                "homepage": "http://symfony.com/contributors"
            }
        ],
        "description": "Symfony EventDispatcher Component",
        "homepage": "http://symfony.com"
    },
    {
        "name": "symfony/dependency-injection",
        "version": "v2.4.0",
        "version_normalized": "2.4.0.0",
        "target-dir": "Symfony/Component/DependencyInjection",
        "source": {
            "type": "git",
            "url": "https://github.com/symfony/DependencyInjection.git",
            "reference": "66c1eb29c6b6b0d3631d29c85c6d3f00f83f6a6f"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/66c1eb29c6b6b0d3631d29c85c6d3f00f83f6a6f",
            "reference": "66c1eb29c6b6b0d3631d29c85c6d3f00f83f6a6f",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3"
        },
        "require-dev": {
            "symfony/config": "~2.2",
            "symfony/expression-language": "~2.4",
            "symfony/yaml": "~2.0"
        },
        "suggest": {
            "symfony/config": "",
            "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them",
            "symfony/yaml": ""
        },
        "time": "2013-12-03 14:52:22",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.4-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Symfony\\Component\\DependencyInjection\\": ""
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Fabien Potencier",
                "email": "fabien@symfony.com"
            },
            {
                "name": "Symfony Community",
                "homepage": "http://symfony.com/contributors"
            }
        ],
        "description": "Symfony DependencyInjection Component",
        "homepage": "http://symfony.com"
    },
    {
        "name": "symfony/filesystem",
        "version": "v2.4.0",
        "version_normalized": "2.4.0.0",
        "target-dir": "Symfony/Component/Filesystem",
        "source": {
            "type": "git",
            "url": "https://github.com/symfony/Filesystem.git",
            "reference": "79acd777762e81d0f3414ca25a602deeeb48240d"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/symfony/Filesystem/zipball/79acd777762e81d0f3414ca25a602deeeb48240d",
            "reference": "79acd777762e81d0f3414ca25a602deeeb48240d",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3"
        },
        "time": "2013-11-16 15:13:54",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.4-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Symfony\\Component\\Filesystem\\": ""
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Fabien Potencier",
                "email": "fabien@symfony.com"
            },
            {
                "name": "Symfony Community",
                "homepage": "http://symfony.com/contributors"
            }
        ],
        "description": "Symfony Filesystem Component",
        "homepage": "http://symfony.com"
    },
    {
        "name": "symfony/config",
        "version": "v2.4.0",
        "version_normalized": "2.4.0.0",
        "target-dir": "Symfony/Component/Config",
        "source": {
            "type": "git",
            "url": "https://github.com/symfony/Config.git",
            "reference": "16068f76c0af74968f3ad8fcec3eb90df1fde394"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/symfony/Config/zipball/16068f76c0af74968f3ad8fcec3eb90df1fde394",
            "reference": "16068f76c0af74968f3ad8fcec3eb90df1fde394",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3",
            "symfony/filesystem": "~2.3"
        },
        "time": "2013-11-26 16:40:27",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.4-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Symfony\\Component\\Config\\": ""
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Fabien Potencier",
                "email": "fabien@symfony.com"
            },
            {
                "name": "Symfony Community",
                "homepage": "http://symfony.com/contributors"
            }
        ],
        "description": "Symfony Config Component",
        "homepage": "http://symfony.com"
    },
    {
        "name": "symfony/console",
        "version": "v2.4.0",
        "version_normalized": "2.4.0.0",
        "target-dir": "Symfony/Component/Console",
        "source": {
            "type": "git",
            "url": "https://github.com/symfony/Console.git",
            "reference": "3c1496ae96d24ccc6c340fcc25f71d7a1ab4c12c"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/symfony/Console/zipball/3c1496ae96d24ccc6c340fcc25f71d7a1ab4c12c",
            "reference": "3c1496ae96d24ccc6c340fcc25f71d7a1ab4c12c",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3"
        },
        "require-dev": {
            "symfony/event-dispatcher": "~2.1"
        },
        "suggest": {
            "symfony/event-dispatcher": ""
        },
        "time": "2013-11-27 09:10:40",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.4-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Symfony\\Component\\Console\\": ""
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Fabien Potencier",
                "email": "fabien@symfony.com"
            },
            {
                "name": "Symfony Community",
                "homepage": "http://symfony.com/contributors"
            }
        ],
        "description": "Symfony Console Component",
        "homepage": "http://symfony.com"
    },
    {
        "name": "behat/gherkin",
        "version": "v2.3.5",
        "version_normalized": "2.3.5.0",
        "source": {
            "type": "git",
            "url": "https://github.com/Behat/Gherkin.git",
            "reference": "2b33963da5525400573560c173ab5c9c057e1852"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/Behat/Gherkin/zipball/2b33963da5525400573560c173ab5c9c057e1852",
            "reference": "2b33963da5525400573560c173ab5c9c057e1852",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.1",
            "symfony/finder": "~2.0"
        },
        "require-dev": {
            "symfony/config": "~2.0",
            "symfony/translation": "~2.0",
            "symfony/yaml": "~2.0"
        },
        "suggest": {
            "symfony/config": "If you want to use Config component to manage resources",
            "symfony/translation": "If you want to use Symfony2 translations adapter",
            "symfony/yaml": "If you want to parse features, represented in YAML files"
        },
        "time": "2013-10-15 11:22:17",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-develop": "2.2-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Behat\\Gherkin": "src/"
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Konstantin Kudryashov",
                "email": "ever.zet@gmail.com",
                "homepage": "http://everzet.com"
            }
        ],
        "description": "Gherkin DSL parser for PHP 5.3",
        "homepage": "http://behat.org/",
        "keywords": [
            "BDD",
            "Behat",
            "DSL",
            "Symfony2",
            "parser"
        ]
    },
    {
        "name": "behat/behat",
        "version": "v2.5.1",
        "version_normalized": "2.5.1.0",
        "source": {
            "type": "git",
            "url": "https://github.com/Behat/Behat.git",
            "reference": "b688e3c4bd65ef867d2ec0a0cf8e621c166e259b"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/Behat/Behat/zipball/b688e3c4bd65ef867d2ec0a0cf8e621c166e259b",
            "reference": "b688e3c4bd65ef867d2ec0a0cf8e621c166e259b",
            "shasum": ""
        },
        "require": {
            "behat/gherkin": "~2.3.0",
            "php": ">=5.3.1",
            "symfony/config": "~2.0",
            "symfony/console": "~2.0",
            "symfony/dependency-injection": "~2.0",
            "symfony/event-dispatcher": "~2.0",
            "symfony/finder": "~2.0",
            "symfony/translation": "~2.0",
            "symfony/yaml": "~2.0"
        },
        "require-dev": {
            "phpunit/phpunit": "~3.7.19"
        },
        "suggest": {
            "behat/mink-extension": "for integration with Mink testing framework",
            "behat/symfony2-extension": "for integration with Symfony2 web framework",
            "behat/yii-extension": "for integration with Yii web framework"
        },
        "time": "2013-11-24 10:17:18",
        "bin": [
            "bin/behat"
        ],
        "type": "library",
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Behat\\Behat": "src/"
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Konstantin Kudryashov",
                "email": "ever.zet@gmail.com",
                "homepage": "http://everzet.com"
            }
        ],
        "description": "Scenario-oriented BDD framework for PHP 5.3",
        "homepage": "http://behat.org/",
        "keywords": [
            "BDD",
            "Behat",
            "Symfony2"
        ]
    },
    {
        "name": "symfony/process",
        "version": "v2.4.0",
        "version_normalized": "2.4.0.0",
        "target-dir": "Symfony/Component/Process",
        "source": {
            "type": "git",
            "url": "https://github.com/symfony/Process.git",
            "reference": "87738ff42e2467730ed74d941866e95513844b70"
        },
        "dist": {
            "type": "zip",
            "url": "https://api.github.com/repos/symfony/Process/zipball/87738ff42e2467730ed74d941866e95513844b70",
            "reference": "87738ff42e2467730ed74d941866e95513844b70",
            "shasum": ""
        },
        "require": {
            "php": ">=5.3.3"
        },
        "time": "2013-11-26 16:40:27",
        "type": "library",
        "extra": {
            "branch-alias": {
                "dev-master": "2.4-dev"
            }
        },
        "installation-source": "source",
        "autoload": {
            "psr-0": {
                "Symfony\\Component\\Process\\": ""
            }
        },
        "notification-url": "https://packagist.org/downloads/",
        "license": [
            "MIT"
        ],
        "authors": [
            {
                "name": "Fabien Potencier",
                "email": "fabien@symfony.com"
            },
            {
                "name": "Symfony Community",
                "homepage": "http://symfony.com/contributors"
            }
        ],
        "description": "Symfony Process Component",
        "homepage": "http://symfony.com"
    }
]
<?php

// autoload_namespaces.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'phpDocumentor\\Composer' => array($vendorDir . '/phpdocumentor/unified-asset-installer/src', $vendorDir . '/phpdocumentor/unified-asset-installer/test/unit'),
    'phpDocumentor' => array($baseDir . '/src', $baseDir . '/tests/unit', $vendorDir . '/phpdocumentor/graphviz/src', $vendorDir . '/phpdocumentor/graphviz/tests/unit', $vendorDir . '/phpdocumentor/fileset/src', $vendorDir . '/phpdocumentor/fileset/tests/unit', $vendorDir . '/phpdocumentor/reflection-docblock/src', $vendorDir . '/phpdocumentor/reflection/src', $vendorDir . '/phpdocumentor/reflection/tests/unit', $vendorDir . '/phpdocumentor/reflection/tests/mocks'),
    'org\\bovigo\\vfs\\' => array($vendorDir . '/mikey179/vfsStream/src/main/php'),
    'Zend\\Stdlib\\' => array($vendorDir . '/zendframework/zend-stdlib'),
    'Zend\\ServiceManager\\' => array($vendorDir . '/zendframework/zend-servicemanager'),
    'Zend\\Serializer\\' => array($vendorDir . '/zendframework/zend-serializer'),
    'Zend\\Math\\' => array($vendorDir . '/zendframework/zend-math'),
    'Zend\\Json\\' => array($vendorDir . '/zendframework/zend-json'),
    'Zend\\I18n\\' => array($vendorDir . '/zendframework/zend-i18n'),
    'Zend\\Filter\\' => array($vendorDir . '/zendframework/zend-filter'),
    'Zend\\EventManager\\' => array($vendorDir . '/zendframework/zend-eventmanager'),
    'Zend\\Config\\' => array($vendorDir . '/zendframework/zend-config'),
    'Zend\\Cache\\' => array($vendorDir . '/zendframework/zend-cache'),
    'Twig_' => array($vendorDir . '/twig/twig/lib'),
    'Symfony\\Component\\Yaml\\' => array($vendorDir . '/symfony/yaml'),
    'Symfony\\Component\\Validator\\' => array($vendorDir . '/symfony/validator'),
    'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'),
    'Symfony\\Component\\Stopwatch\\' => array($vendorDir . '/symfony/stopwatch'),
    'Symfony\\Component\\PropertyAccess\\' => array($vendorDir . '/symfony/property-access'),
    'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
    'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
    'Symfony\\Component\\Filesystem\\' => array($vendorDir . '/symfony/filesystem'),
    'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'),
    'Symfony\\Component\\DependencyInjection\\' => array($vendorDir . '/symfony/dependency-injection'),
    'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
    'Symfony\\Component\\Config\\' => array($vendorDir . '/symfony/config'),
    'Psr\\Log\\' => array($vendorDir . '/psr/log'),
    'Pimple' => array($vendorDir . '/pimple/pimple/lib'),
    'PhpOption\\' => array($vendorDir . '/phpoption/phpoption/src'),
    'PhpCollection' => array($vendorDir . '/phpcollection/phpcollection/src'),
    'Parsedown' => array($vendorDir . '/erusev/parsedown'),
    'PHPParser' => array($vendorDir . '/nikic/php-parser/lib'),
    'Monolog' => array($vendorDir . '/monolog/monolog/src'),
    'Mockery' => array($vendorDir . '/mockery/mockery/library'),
    'Metadata\\' => array($vendorDir . '/jms/metadata/src'),
    'JMS\\Serializer' => array($vendorDir . '/jms/serializer/src'),
    'JMS\\' => array($vendorDir . '/jms/parser-lib/src'),
    'Doctrine\\Common\\Lexer\\' => array($vendorDir . '/doctrine/lexer/lib'),
    'Doctrine\\Common\\Annotations\\' => array($vendorDir . '/doctrine/annotations/lib'),
    'Cilex\\Provider\\Console' => array($vendorDir . '/cilex/console-service-provider/src'),
    'Cilex' => array($vendorDir . '/cilex/cilex/src'),
    'Behat\\Gherkin' => array($vendorDir . '/behat/gherkin/src'),
    'Behat\\Behat' => array($vendorDir . '/behat/behat/src'),
);
{
    "name": "monolog/monolog",
    "description": "Sends your logs to files, sockets, inboxes, databases and various web services",
    "keywords": ["log", "logging", "psr-3"],
    "homepage": "http://github.com/Seldaek/monolog",
    "type": "library",
    "license": "MIT",
    "authors": [
        {
            "name": "Jordi Boggiano",
            "email": "j.boggiano@seld.be",
            "homepage": "http://seld.be"
        }
    ],
    "require": {
        "php": ">=5.3.0",
        "psr/log": "~1.0"
    },
    "require-dev": {
        "phpunit/phpunit": "~3.7.0",
        "mlehner/gelf-php": "1.0.*",
        "raven/raven": "0.5.*",
        "ruflin/elastica": "0.90.*",
        "doctrine/couchdb": "dev-master",
        "aws/aws-sdk-php": "~2.4.8"
    },
    "suggest": {
        "mlehner/gelf-php": "Allow sending log messages to a GrayLog2 server",
        "raven/raven": "Allow sending log messages to a Sentry server",
        "doctrine/couchdb": "Allow sending log messages to a CouchDB server",
        "ruflin/elastica": "Allow sending log messages to an Elastic Search server",
        "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
        "ext-mongo": "Allow sending log messages to a MongoDB server",
        "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB"
    },
    "autoload": {
        "psr-0": {"Monolog": "src/"}
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.7.x-dev"
        }
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog;

use Monolog\Handler\HandlerInterface;
use Monolog\Handler\StreamHandler;
use Psr\Log\LoggerInterface;
use Psr\Log\InvalidArgumentException;

/**
 * Monolog log channel
 *
 * It contains a stack of Handlers and a stack of Processors,
 * and uses them to store records that are added to it.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class Logger implements LoggerInterface
{
    /**
     * Detailed debug information
     */
    const DEBUG = 100;

    /**
     * Interesting events
     *
     * Examples: User logs in, SQL logs.
     */
    const INFO = 200;

    /**
     * Uncommon events
     */
    const NOTICE = 250;

    /**
     * Exceptional occurrences that are not errors
     *
     * Examples: Use of deprecated APIs, poor use of an API,
     * undesirable things that are not necessarily wrong.
     */
    const WARNING = 300;

    /**
     * Runtime errors
     */
    const ERROR = 400;

    /**
     * Critical conditions
     *
     * Example: Application component unavailable, unexpected exception.
     */
    const CRITICAL = 500;

    /**
     * Action must be taken immediately
     *
     * Example: Entire website down, database unavailable, etc.
     * This should trigger the SMS alerts and wake you up.
     */
    const ALERT = 550;

    /**
     * Urgent alert.
     */
    const EMERGENCY = 600;

    /**
     * Monolog API version
     *
     * This is only bumped when API breaks are done and should
     * follow the major version of the library
     *
     * @var int
     */
    const API = 1;

    /**
     * Logging levels from syslog protocol defined in RFC 5424
     *
     * @var array $levels Logging levels
     */
    protected static $levels = array(
        100 => 'DEBUG',
        200 => 'INFO',
        250 => 'NOTICE',
        300 => 'WARNING',
        400 => 'ERROR',
        500 => 'CRITICAL',
        550 => 'ALERT',
        600 => 'EMERGENCY',
    );

    /**
     * @var DateTimeZone
     */
    protected static $timezone;

    protected $name;

    /**
     * The handler stack
     *
     * @var array of Monolog\Handler\HandlerInterface
     */
    protected $handlers;

    /**
     * Processors that will process all log records
     *
     * To process records of a single handler instead, add the processor on that specific handler
     *
     * @var array of callables
     */
    protected $processors;

    /**
     * @param string $name       The logging channel
     * @param array  $handlers   Optional stack of handlers, the first one in the array is called first, etc.
     * @param array  $processors Optional array of processors
     */
    public function __construct($name, array $handlers = array(), array $processors = array())
    {
        $this->name = $name;
        $this->handlers = $handlers;
        $this->processors = $processors;
    }

    /**
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Pushes a handler on to the stack.
     *
     * @param HandlerInterface $handler
     */
    public function pushHandler(HandlerInterface $handler)
    {
        array_unshift($this->handlers, $handler);
    }

    /**
     * Pops a handler from the stack
     *
     * @return HandlerInterface
     */
    public function popHandler()
    {
        if (!$this->handlers) {
            throw new \LogicException('You tried to pop from an empty handler stack.');
        }

        return array_shift($this->handlers);
    }

    /**
     * Adds a processor on to the stack.
     *
     * @param callable $callback
     */
    public function pushProcessor($callback)
    {
        if (!is_callable($callback)) {
            throw new \InvalidArgumentException('Processors must be valid callables (callback or object with an __invoke method), '.var_export($callback, true).' given');
        }
        array_unshift($this->processors, $callback);
    }

    /**
     * Removes the processor on top of the stack and returns it.
     *
     * @return callable
     */
    public function popProcessor()
    {
        if (!$this->processors) {
            throw new \LogicException('You tried to pop from an empty processor stack.');
        }

        return array_shift($this->processors);
    }

    /**
     * Adds a log record.
     *
     * @param  integer $level   The logging level
     * @param  string  $message The log message
     * @param  array   $context The log context
     * @return Boolean Whether the record has been processed
     */
    public function addRecord($level, $message, array $context = array())
    {
        if (!$this->handlers) {
            $this->pushHandler(new StreamHandler('php://stderr', static::DEBUG));
        }

        if (!static::$timezone) {
            static::$timezone = new \DateTimeZone(date_default_timezone_get() ?: 'UTC');
        }

        $record = array(
            'message' => (string) $message,
            'context' => $context,
            'level' => $level,
            'level_name' => static::getLevelName($level),
            'channel' => $this->name,
            'datetime' => \DateTime::createFromFormat('U.u', sprintf('%.6F', microtime(true)), static::$timezone)->setTimezone(static::$timezone),
            'extra' => array(),
        );
        // check if any handler will handle this message
        $handlerKey = null;
        foreach ($this->handlers as $key => $handler) {
            if ($handler->isHandling($record)) {
                $handlerKey = $key;
                break;
            }
        }
        // none found
        if (null === $handlerKey) {
            return false;
        }

        // found at least one, process message and dispatch it
        foreach ($this->processors as $processor) {
            $record = call_user_func($processor, $record);
        }
        while (isset($this->handlers[$handlerKey]) &&
            false === $this->handlers[$handlerKey]->handle($record)) {
            $handlerKey++;
        }

        return true;
    }

    /**
     * Adds a log record at the DEBUG level.
     *
     * @param  string  $message The log message
     * @param  array   $context The log context
     * @return Boolean Whether the record has been processed
     */
    public function addDebug($message, array $context = array())
    {
        return $this->addRecord(static::DEBUG, $message, $context);
    }

    /**
     * Adds a log record at the INFO level.
     *
     * @param  string  $message The log message
     * @param  array   $context The log context
     * @return Boolean Whether the record has been processed
     */
    public function addInfo($message, array $context = array())
    {
        return $this->addRecord(static::INFO, $message, $context);
    }

    /**
     * Adds a log record at the NOTICE level.
     *
     * @param  string  $message The log message
     * @param  array   $context The log context
     * @return Boolean Whether the record has been processed
     */
    public function addNotice($message, array $context = array())
    {
        return $this->addRecord(static::NOTICE, $message, $context);
    }

    /**
     * Adds a log record at the WARNING level.
     *
     * @param  string  $message The log message
     * @param  array   $context The log context
     * @return Boolean Whether the record has been processed
     */
    public function addWarning($message, array $context = array())
    {
        return $this->addRecord(static::WARNING, $message, $context);
    }

    /**
     * Adds a log record at the ERROR level.
     *
     * @param  string  $message The log message
     * @param  array   $context The log context
     * @return Boolean Whether the record has been processed
     */
    public function addError($message, array $context = array())
    {
        return $this->addRecord(static::ERROR, $message, $context);
    }

    /**
     * Adds a log record at the CRITICAL level.
     *
     * @param  string  $message The log message
     * @param  array   $context The log context
     * @return Boolean Whether the record has been processed
     */
    public function addCritical($message, array $context = array())
    {
        return $this->addRecord(static::CRITICAL, $message, $context);
    }

    /**
     * Adds a log record at the ALERT level.
     *
     * @param  string  $message The log message
     * @param  array   $context The log context
     * @return Boolean Whether the record has been processed
     */
    public function addAlert($message, array $context = array())
    {
        return $this->addRecord(static::ALERT, $message, $context);
    }

    /**
     * Adds a log record at the EMERGENCY level.
     *
     * @param  string  $message The log message
     * @param  array   $context The log context
     * @return Boolean Whether the record has been processed
     */
    public function addEmergency($message, array $context = array())
    {
      return $this->addRecord(static::EMERGENCY, $message, $context);
    }

    /**
     * Gets all supported logging levels.
     *
     * @return array Assoc array with human-readable level names => level codes.
     */
    public static function getLevels()
    {
        return array_flip(static::$levels);
    }

    /**
     * Gets the name of the logging level.
     *
     * @param  integer $level
     * @return string
     */
    public static function getLevelName($level)
    {
        if (!isset(static::$levels[$level])) {
            throw new InvalidArgumentException('Level "'.$level.'" is not defined, use one of: '.implode(', ', array_keys(static::$levels)));
        }

        return static::$levels[$level];
    }

    /**
     * Checks whether the Logger has a handler that listens on the given level
     *
     * @param  integer $level
     * @return Boolean
     */
    public function isHandling($level)
    {
        $record = array(
            'level' => $level,
        );

        foreach ($this->handlers as $handler) {
            if ($handler->isHandling($record)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Adds a log record at an arbitrary level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param  mixed   $level   The log level
     * @param  string  $message The log message
     * @param  array   $context The log context
     * @return Boolean Whether the record has been processed
     */
    public function log($level, $message, array $context = array())
    {
        if (is_string($level) && defined(__CLASS__.'::'.strtoupper($level))) {
            $level = constant(__CLASS__.'::'.strtoupper($level));
        }

        return $this->addRecord($level, $message, $context);
    }

    /**
     * Adds a log record at the DEBUG level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param  string  $message The log message
     * @param  array   $context The log context
     * @return Boolean Whether the record has been processed
     */
    public function debug($message, array $context = array())
    {
        return $this->addRecord(static::DEBUG, $message, $context);
    }

    /**
     * Adds a log record at the INFO level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param  string  $message The log message
     * @param  array   $context The log context
     * @return Boolean Whether the record has been processed
     */
    public function info($message, array $context = array())
    {
        return $this->addRecord(static::INFO, $message, $context);
    }

    /**
     * Adds a log record at the INFO level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param  string  $message The log message
     * @param  array   $context The log context
     * @return Boolean Whether the record has been processed
     */
    public function notice($message, array $context = array())
    {
        return $this->addRecord(static::NOTICE, $message, $context);
    }

    /**
     * Adds a log record at the WARNING level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param  string  $message The log message
     * @param  array   $context The log context
     * @return Boolean Whether the record has been processed
     */
    public function warn($message, array $context = array())
    {
        return $this->addRecord(static::WARNING, $message, $context);
    }

    /**
     * Adds a log record at the WARNING level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param  string  $message The log message
     * @param  array   $context The log context
     * @return Boolean Whether the record has been processed
     */
    public function warning($message, array $context = array())
    {
        return $this->addRecord(static::WARNING, $message, $context);
    }

    /**
     * Adds a log record at the ERROR level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param  string  $message The log message
     * @param  array   $context The log context
     * @return Boolean Whether the record has been processed
     */
    public function err($message, array $context = array())
    {
        return $this->addRecord(static::ERROR, $message, $context);
    }

    /**
     * Adds a log record at the ERROR level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param  string  $message The log message
     * @param  array   $context The log context
     * @return Boolean Whether the record has been processed
     */
    public function error($message, array $context = array())
    {
        return $this->addRecord(static::ERROR, $message, $context);
    }

    /**
     * Adds a log record at the CRITICAL level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param  string  $message The log message
     * @param  array   $context The log context
     * @return Boolean Whether the record has been processed
     */
    public function crit($message, array $context = array())
    {
        return $this->addRecord(static::CRITICAL, $message, $context);
    }

    /**
     * Adds a log record at the CRITICAL level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param  string  $message The log message
     * @param  array   $context The log context
     * @return Boolean Whether the record has been processed
     */
    public function critical($message, array $context = array())
    {
        return $this->addRecord(static::CRITICAL, $message, $context);
    }

    /**
     * Adds a log record at the ALERT level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param  string  $message The log message
     * @param  array   $context The log context
     * @return Boolean Whether the record has been processed
     */
    public function alert($message, array $context = array())
    {
        return $this->addRecord(static::ALERT, $message, $context);
    }

    /**
     * Adds a log record at the EMERGENCY level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param  string  $message The log message
     * @param  array   $context The log context
     * @return Boolean Whether the record has been processed
     */
    public function emerg($message, array $context = array())
    {
        return $this->addRecord(static::EMERGENCY, $message, $context);
    }

    /**
     * Adds a log record at the EMERGENCY level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param  string  $message The log message
     * @param  array   $context The log context
     * @return Boolean Whether the record has been processed
     */
    public function emergency($message, array $context = array())
    {
        return $this->addRecord(static::EMERGENCY, $message, $context);
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Processor;

/**
 * Injects url/method and remote IP of the current web request in all records
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class WebProcessor
{
    protected $serverData;

    /**
     * @param mixed $serverData array or object w/ ArrayAccess that provides access to the $_SERVER data
     */
    public function __construct($serverData = null)
    {
        if (null === $serverData) {
            $this->serverData =& $_SERVER;
        } elseif (is_array($serverData) || $serverData instanceof \ArrayAccess) {
            $this->serverData = $serverData;
        } else {
            throw new \UnexpectedValueException('$serverData must be an array or object implementing ArrayAccess.');
        }
    }

    /**
     * @param  array $record
     * @return array
     */
    public function __invoke(array $record)
    {
        // skip processing if for some reason request data
        // is not present (CLI or wonky SAPIs)
        if (!isset($this->serverData['REQUEST_URI'])) {
            return $record;
        }

        $record['extra'] = array_merge(
            $record['extra'],
            array(
                'url'         => $this->serverData['REQUEST_URI'],
                'ip'          => isset($this->serverData['REMOTE_ADDR']) ? $this->serverData['REMOTE_ADDR'] : null,
                'http_method' => isset($this->serverData['REQUEST_METHOD']) ? $this->serverData['REQUEST_METHOD'] : null,
                'server'      => isset($this->serverData['SERVER_NAME']) ? $this->serverData['SERVER_NAME'] : null,
                'referrer'    => isset($this->serverData['HTTP_REFERER']) ? $this->serverData['HTTP_REFERER'] : null,
            )
        );

        if (isset($this->serverData['UNIQUE_ID'])) {
            $record['extra']['unique_id'] = $this->serverData['UNIQUE_ID'];
        }

        return $record;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Processor;

/**
 * Processes a record's message according to PSR-3 rules
 *
 * It replaces {foo} with the value from $context['foo']
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class PsrLogMessageProcessor
{
    /**
     * @param  array $record
     * @return array
     */
    public function __invoke(array $record)
    {
        if (false === strpos($record['message'], '{')) {
            return $record;
        }

        $replacements = array();
        foreach ($record['context'] as $key => $val) {
            $replacements['{'.$key.'}'] = $val;
        }

        $record['message'] = strtr($record['message'], $replacements);

        return $record;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Processor;

/**
 * Injects memory_get_usage in all records
 *
 * @see Monolog\Processor\MemoryProcessor::__construct() for options
 * @author Rob Jensen
 */
class MemoryUsageProcessor extends MemoryProcessor
{
    /**
     * @param  array $record
     * @return array
     */
    public function __invoke(array $record)
    {
        $bytes = memory_get_usage($this->realUsage);
        $formatted = self::formatBytes($bytes);

        $record['extra'] = array_merge(
            $record['extra'],
            array(
                'memory_usage' => $formatted,
            )
        );

        return $record;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Processor;

/**
 * Adds a unique identifier into records
 *
 * @author Simon Mönch <sm@webfactory.de>
 */
class UidProcessor
{
    private $uid;

    public function __construct($length = 7)
    {
        if (!is_int($length) || $length > 32 || $length < 1) {
            throw new \InvalidArgumentException('The uid length must be an integer between 1 and 32');
        }

        $this->uid = substr(hash('md5', uniqid('', true)), 0, $length);
    }

    public function __invoke(array $record)
    {
        $record['extra']['uid'] = $this->uid;

        return $record;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Processor;

/**
 * Injects memory_get_peak_usage in all records
 *
 * @see Monolog\Processor\MemoryProcessor::__construct() for options
 * @author Rob Jensen
 */
class MemoryPeakUsageProcessor extends MemoryProcessor
{
    /**
     * @param  array $record
     * @return array
     */
    public function __invoke(array $record)
    {
        $bytes = memory_get_peak_usage($this->realUsage);
        $formatted = self::formatBytes($bytes);

        $record['extra'] = array_merge(
            $record['extra'],
            array(
                'memory_peak_usage' => $formatted,
            )
        );

        return $record;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Processor;

use Monolog\Logger;

/**
 * Injects line/file:class/function where the log message came from
 *
 * Warning: This only works if the handler processes the logs directly.
 * If you put the processor on a handler that is behind a FingersCrossedHandler
 * for example, the processor will only be called once the trigger level is reached,
 * and all the log records will have the same file/line/.. data from the call that
 * triggered the FingersCrossedHandler.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class IntrospectionProcessor
{
    private $level;

    public function __construct($level = Logger::DEBUG)
    {
        $this->level = $level;
    }

    /**
     * @param  array $record
     * @return array
     */
    public function __invoke(array $record)
    {
        // return if the level is not high enough
        if ($record['level'] < $this->level) {
            return $record;
        }

        $trace = debug_backtrace();

        // skip first since it's always the current method
        array_shift($trace);
        // the call_user_func call is also skipped
        array_shift($trace);

        $i = 0;
        while (isset($trace[$i]['class']) && false !== strpos($trace[$i]['class'], 'Monolog\\')) {
            $i++;
        }

        // we should have the call source now
        $record['extra'] = array_merge(
            $record['extra'],
            array(
                'file'      => isset($trace[$i-1]['file']) ? $trace[$i-1]['file'] : null,
                'line'      => isset($trace[$i-1]['line']) ? $trace[$i-1]['line'] : null,
                'class'     => isset($trace[$i]['class']) ? $trace[$i]['class'] : null,
                'function'  => isset($trace[$i]['function']) ? $trace[$i]['function'] : null,
            )
        );

        return $record;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Processor;

/**
 * Some methods that are common for all memory processors
 *
 * @author Rob Jensen
 */
abstract class MemoryProcessor
{
    protected $realUsage;

    /**
     * @param boolean $realUsage
     */
    public function __construct($realUsage = true)
    {
        $this->realUsage = (boolean) $realUsage;
    }

    /**
     * Formats bytes into a human readable string
     *
     * @param  int    $bytes
     * @return string
     */
    protected static function formatBytes($bytes)
    {
        $bytes = (int) $bytes;

        if ($bytes > 1024*1024) {
            return round($bytes/1024/1024, 2).' MB';
        } elseif ($bytes > 1024) {
            return round($bytes/1024, 2).' KB';
        }

        return $bytes . ' B';
    }

}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Processor;

/**
 * Adds value of getmypid into records
 *
 * @author Andreas Hörnicke
 */
class ProcessIdProcessor
{
    /**
     * @param  array $record
     * @return array
     */
    public function __invoke(array $record)
    {
        $record['extra']['process_id'] = getmypid();

        return $record;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog;

use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;

/**
 * Monolog error handler
 *
 * A facility to enable logging of runtime errors, exceptions and fatal errors.
 *
 * Quick setup: <code>ErrorHandler::register($logger);</code>
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class ErrorHandler
{
    private $logger;

    private $previousExceptionHandler;
    private $uncaughtExceptionLevel;

    private $previousErrorHandler;
    private $errorLevelMap;

    private $fatalLevel;
    private $reservedMemory;
    private static $fatalErrors = array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR);

    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }

    /**
     * Registers a new ErrorHandler for a given Logger
     *
     * By default it will handle errors, exceptions and fatal errors
     *
     * @param  LoggerInterface $logger
     * @param  array|false     $errorLevelMap  an array of E_* constant to LogLevel::* constant mapping, or false to disable error handling
     * @param  int|false       $exceptionLevel a LogLevel::* constant, or false to disable exception handling
     * @param  int|false       $fatalLevel     a LogLevel::* constant, or false to disable fatal error handling
     * @return ErrorHandler
     */
    public static function register(LoggerInterface $logger, $errorLevelMap = array(), $exceptionLevel = null, $fatalLevel = null)
    {
        $handler = new static($logger);
        if ($errorLevelMap !== false) {
            $handler->registerErrorHandler($errorLevelMap);
        }
        if ($exceptionLevel !== false) {
            $handler->registerExceptionHandler($exceptionLevel);
        }
        if ($fatalLevel !== false) {
            $handler->registerFatalHandler($fatalLevel);
        }

        return $handler;
    }

    public function registerExceptionHandler($level = null, $callPrevious = true)
    {
        $prev = set_exception_handler(array($this, 'handleException'));
        $this->uncaughtExceptionLevel = $level;
        if ($callPrevious && $prev) {
            $this->previousExceptionHandler = $prev;
        }
    }

    public function registerErrorHandler(array $levelMap = array(), $callPrevious = true, $errorTypes = -1)
    {
        $prev = set_error_handler(array($this, 'handleError'), $errorTypes);
        $this->errorLevelMap = array_replace($this->defaultErrorLevelMap(), $levelMap);
        if ($callPrevious) {
            $this->previousErrorHandler = $prev ?: true;
        }
    }

    public function registerFatalHandler($level = null, $reservedMemorySize = 20)
    {
        register_shutdown_function(array($this, 'handleFatalError'));

        $this->reservedMemory = str_repeat(' ', 1024 * $reservedMemorySize);
        $this->fatalLevel = $level;
    }

    protected function defaultErrorLevelMap()
    {
        return array(
            E_ERROR             => LogLevel::CRITICAL,
            E_WARNING           => LogLevel::WARNING,
            E_PARSE             => LogLevel::ALERT,
            E_NOTICE            => LogLevel::NOTICE,
            E_CORE_ERROR        => LogLevel::CRITICAL,
            E_CORE_WARNING      => LogLevel::WARNING,
            E_COMPILE_ERROR     => LogLevel::ALERT,
            E_COMPILE_WARNING   => LogLevel::WARNING,
            E_USER_ERROR        => LogLevel::ERROR,
            E_USER_WARNING      => LogLevel::WARNING,
            E_USER_NOTICE       => LogLevel::NOTICE,
            E_STRICT            => LogLevel::NOTICE,
            E_RECOVERABLE_ERROR => LogLevel::ERROR,
            E_DEPRECATED        => LogLevel::NOTICE,
            E_USER_DEPRECATED   => LogLevel::NOTICE,
        );
    }

    /**
     * @private
     */
    public function handleException(\Exception $e)
    {
        $this->logger->log(
            $this->uncaughtExceptionLevel === null ? LogLevel::ERROR : $this->uncaughtExceptionLevel,
            'Uncaught exception',
            array('exception' => $e)
        );

        if ($this->previousExceptionHandler) {
            call_user_func($this->previousExceptionHandler, $e);
        }
    }

    /**
     * @private
     */
    public function handleError($code, $message, $file = '', $line = 0, $context = array())
    {
        if (!(error_reporting() & $code)) {
            return;
        }

        $level = isset($this->errorLevelMap[$code]) ? $this->errorLevelMap[$code] : LogLevel::CRITICAL;
        $this->logger->log($level, self::codeToString($code).': '.$message, array('file' => $file, 'line' => $line));

        if ($this->previousErrorHandler === true) {
            return false;
        } elseif ($this->previousErrorHandler) {
            return call_user_func($this->previousErrorHandler, $code, $message, $file, $line, $context);
        }
    }

    /**
     * @private
     */
    public function handleFatalError()
    {
        $this->reservedMemory = null;

        $lastError = error_get_last();
        if ($lastError && in_array($lastError['type'], self::$fatalErrors)) {
            $this->logger->log(
                $this->fatalLevel === null ? LogLevel::ALERT : $this->fatalLevel,
                'Fatal Error ('.self::codeToString($lastError['type']).'): '.$lastError['message'],
                array('file' => $lastError['file'], 'line' => $lastError['line'])
            );
        }
    }

    private static function codeToString($code)
    {
        switch ($code) {
            case E_ERROR:
                return 'E_ERROR';
            case E_WARNING:
                return 'E_WARNING';
            case E_PARSE:
                return 'E_PARSE';
            case E_NOTICE:
                return 'E_NOTICE';
            case E_CORE_ERROR:
                return 'E_CORE_ERROR';
            case E_CORE_WARNING:
                return 'E_CORE_WARNING';
            case E_COMPILE_ERROR:
                return 'E_COMPILE_ERROR';
            case E_COMPILE_WARNING:
                return 'E_COMPILE_WARNING';
            case E_USER_ERROR:
                return 'E_USER_ERROR';
            case E_USER_WARNING:
                return 'E_USER_WARNING';
            case E_USER_NOTICE:
                return 'E_USER_NOTICE';
            case E_STRICT:
                return 'E_STRICT';
            case E_RECOVERABLE_ERROR:
                return 'E_RECOVERABLE_ERROR';
            case E_DEPRECATED:
                return 'E_DEPRECATED';
            case E_USER_DEPRECATED:
                return 'E_USER_DEPRECATED';
        }

        return 'Unknown PHP error';
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Formatter;

/**
 * Serializes a log message to Logstash Event Format
 *
 * @see http://logstash.net/
 * @see https://github.com/logstash/logstash/blob/master/lib/logstash/event.rb
 *
 * @author Tim Mower <timothy.mower@gmail.com>
 */
class LogstashFormatter extends NormalizerFormatter
{
    const V0 = 0;
    const V1 = 1;

    /**
     * @var string the name of the system for the Logstash log message, used to fill the @source field
     */
    protected $systemName;

    /**
     * @var string an application name for the Logstash log message, used to fill the @type field
     */
    protected $applicationName;

    /**
     * @var string a prefix for 'extra' fields from the Monolog record (optional)
     */
    protected $extraPrefix;

    /**
     * @var string a prefix for 'context' fields from the Monolog record (optional)
     */
    protected $contextPrefix;

    /**
     * @var integer logstash format version to use
     */
    protected $version;

    /**
     * @param string $applicationName the application that sends the data, used as the "type" field of logstash
     * @param string $systemName      the system/machine name, used as the "source" field of logstash, defaults to the hostname of the machine
     * @param string $extraPrefix     prefix for extra keys inside logstash "fields"
     * @param string $contextPrefix   prefix for context keys inside logstash "fields", defaults to ctxt_
     */
    public function __construct($applicationName, $systemName = null, $extraPrefix = null, $contextPrefix = 'ctxt_', $version = self::V0)
    {
        // logstash requires a ISO 8601 format date with optional millisecond precision.
        parent::__construct('Y-m-d\TH:i:s.uP');

        $this->systemName = $systemName ?: gethostname();
        $this->applicationName = $applicationName;
        $this->extraPrefix = $extraPrefix;
        $this->contextPrefix = $contextPrefix;
        $this->version = $version;
    }

    /**
     * {@inheritdoc}
     */
    public function format(array $record)
    {
        $record = parent::format($record);

        if ($this->version === self::V1) {
            $message = $this->formatV1($record);
        } else {
            $message = $this->formatV0($record);
        }

        return $this->toJson($message) . "\n";
    }

    protected function formatV0(array $record)
    {
        $message = array(
            '@timestamp' => $record['datetime'],
            '@message' => $record['message'],
            '@tags' => array($record['channel']),
            '@source' => $this->systemName,
            '@fields' => array(
                'channel' => $record['channel'],
                'level' => $record['level']
            )
        );

        if ($this->applicationName) {
            $message['@type'] = $this->applicationName;
        }

        if (isset($record['extra']['server'])) {
            $message['@source_host'] = $record['extra']['server'];
        }
        if (isset($record['extra']['url'])) {
            $message['@source_path'] = $record['extra']['url'];
        }
        foreach ($record['extra'] as $key => $val) {
            $message['@fields'][$this->extraPrefix . $key] = $val;
        }

        foreach ($record['context'] as $key => $val) {
            $message['@fields'][$this->contextPrefix . $key] = $val;
        }

        return $message;
    }

    protected function formatV1(array $record)
    {
        $message = array(
            '@timestamp' => $record['datetime'],
            '@version' => 1,
            'message' => $record['message'],
            'host' => $this->systemName,
            'type' => $record['channel'],
            'channel' => $record['channel'],
            'level' => $record['level_name']
        );

        if ($this->applicationName) {
            $message['type'] = $this->applicationName;
        }

        foreach ($record['extra'] as $key => $val) {
            $message[$this->extraPrefix . $key] = $val;
        }

        foreach ($record['context'] as $key => $val) {
            $message[$this->contextPrefix . $key] = $val;
        }

        return $message;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Formatter;

use Monolog\Logger;
use Gelf\Message;

/**
 * Serializes a log message to GELF
 * @see http://www.graylog2.org/about/gelf
 *
 * @author Matt Lehner <mlehner@gmail.com>
 */
class GelfMessageFormatter extends NormalizerFormatter
{
    /**
     * @var string the name of the system for the Gelf log message
     */
    protected $systemName;

    /**
     * @var string a prefix for 'extra' fields from the Monolog record (optional)
     */
    protected $extraPrefix;

    /**
     * @var string a prefix for 'context' fields from the Monolog record (optional)
     */
    protected $contextPrefix;

    /**
     * Translates Monolog log levels to Graylog2 log priorities.
     */
    private $logLevels = array(
        Logger::DEBUG     => 7,
        Logger::INFO      => 6,
        Logger::NOTICE    => 5,
        Logger::WARNING   => 4,
        Logger::ERROR     => 3,
        Logger::CRITICAL  => 2,
        Logger::ALERT     => 1,
        Logger::EMERGENCY => 0,
    );

    public function __construct($systemName = null, $extraPrefix = null, $contextPrefix = 'ctxt_')
    {
        parent::__construct('U.u');

        $this->systemName = $systemName ?: gethostname();

        $this->extraPrefix = $extraPrefix;
        $this->contextPrefix = $contextPrefix;
    }

    /**
     * {@inheritdoc}
     */
    public function format(array $record)
    {
        $record = parent::format($record);
        $message = new Message();
        $message
            ->setTimestamp($record['datetime'])
            ->setShortMessage((string) $record['message'])
            ->setFacility($record['channel'])
            ->setHost($this->systemName)
            ->setLine(isset($record['extra']['line']) ? $record['extra']['line'] : null)
            ->setFile(isset($record['extra']['file']) ? $record['extra']['file'] : null)
            ->setLevel($this->logLevels[$record['level']]);

        // Do not duplicate these values in the additional fields
        unset($record['extra']['line']);
        unset($record['extra']['file']);

        foreach ($record['extra'] as $key => $val) {
            $message->setAdditional($this->extraPrefix . $key, is_scalar($val) ? $val : $this->toJson($val));
        }

        foreach ($record['context'] as $key => $val) {
            $message->setAdditional($this->contextPrefix . $key, is_scalar($val) ? $val : $this->toJson($val));
        }

        if (null === $message->getFile() && isset($record['context']['exception'])) {
            if (preg_match("/^(.+):([0-9]+)$/", $record['context']['exception']['file'], $matches)) {
                $message->setFile($matches[1]);
                $message->setLine($matches[2]);
            }
        }

        return $message;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Formatter;

use Exception;

/**
 * Normalizes incoming records to remove objects/resources so it's easier to dump to various targets
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class NormalizerFormatter implements FormatterInterface
{
    const SIMPLE_DATE = "Y-m-d H:i:s";

    protected $dateFormat;

    /**
     * @param string $dateFormat The format of the timestamp: one supported by DateTime::format
     */
    public function __construct($dateFormat = null)
    {
        $this->dateFormat = $dateFormat ?: static::SIMPLE_DATE;
    }

    /**
     * {@inheritdoc}
     */
    public function format(array $record)
    {
        return $this->normalize($record);
    }

    /**
     * {@inheritdoc}
     */
    public function formatBatch(array $records)
    {
        foreach ($records as $key => $record) {
            $records[$key] = $this->format($record);
        }

        return $records;
    }

    protected function normalize($data)
    {
        if (null === $data || is_scalar($data)) {
            return $data;
        }

        if (is_array($data) || $data instanceof \Traversable) {
            $normalized = array();

            $count = 1;
            foreach ($data as $key => $value) {
                if ($count++ >= 1000) {
                    $normalized['...'] = 'Over 1000 items, aborting normalization';
                    break;
                }
                $normalized[$key] = $this->normalize($value);
            }

            return $normalized;
        }

        if ($data instanceof \DateTime) {
            return $data->format($this->dateFormat);
        }

        if (is_object($data)) {
            if ($data instanceof Exception) {
                return $this->normalizeException($data);
            }

            return sprintf("[object] (%s: %s)", get_class($data), $this->toJson($data, true));
        }

        if (is_resource($data)) {
            return '[resource]';
        }

        return '[unknown('.gettype($data).')]';
    }

    protected function normalizeException(Exception $e)
    {
        $data = array(
            'class' => get_class($e),
            'message' => $e->getMessage(),
            'file' => $e->getFile().':'.$e->getLine(),
        );

        $trace = $e->getTrace();
        array_shift($trace);
        foreach ($trace as $frame) {
            if (isset($frame['file'])) {
                $data['trace'][] = $frame['file'].':'.$frame['line'];
            } else {
                $data['trace'][] = json_encode($frame);
            }
        }

        if ($previous = $e->getPrevious()) {
            $data['previous'] = $this->normalizeException($previous);
        }

        return $data;
    }

    protected function toJson($data, $ignoreErrors = false)
    {
        // suppress json_encode errors since it's twitchy with some inputs
        if ($ignoreErrors) {
            if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
                return @json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
            }

            return @json_encode($data);
        }

        if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
            return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        }

        return json_encode($data);
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Formatter;

/**
 * Interface for formatters
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface FormatterInterface
{
    /**
     * Formats a log record.
     *
     * @param  array $record A record to format
     * @return mixed The formatted record
     */
    public function format(array $record);

    /**
     * Formats a set of log records.
     *
     * @param  array $records A set of records to format
     * @return mixed The formatted set of records
     */
    public function formatBatch(array $records);
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Formatter;

use Monolog\Logger;

/**
 * Serializes a log message according to Wildfire's header requirements
 *
 * @author Eric Clemmons (@ericclemmons) <eric@uxdriven.com>
 * @author Christophe Coevoet <stof@notk.org>
 * @author Kirill chEbba Chebunin <iam@chebba.org>
 */
class WildfireFormatter extends NormalizerFormatter
{
    /**
     * Translates Monolog log levels to Wildfire levels.
     */
    private $logLevels = array(
        Logger::DEBUG     => 'LOG',
        Logger::INFO      => 'INFO',
        Logger::NOTICE    => 'INFO',
        Logger::WARNING   => 'WARN',
        Logger::ERROR     => 'ERROR',
        Logger::CRITICAL  => 'ERROR',
        Logger::ALERT     => 'ERROR',
        Logger::EMERGENCY => 'ERROR',
    );

    /**
     * {@inheritdoc}
     */
    public function format(array $record)
    {
        // Retrieve the line and file if set and remove them from the formatted extra
        $file = $line = '';
        if (isset($record['extra']['file'])) {
            $file = $record['extra']['file'];
            unset($record['extra']['file']);
        }
        if (isset($record['extra']['line'])) {
            $line = $record['extra']['line'];
            unset($record['extra']['line']);
        }

        $record = $this->normalize($record);
        $message = array('message' => $record['message']);
        $handleError = false;
        if ($record['context']) {
            $message['context'] = $record['context'];
            $handleError = true;
        }
        if ($record['extra']) {
            $message['extra'] = $record['extra'];
            $handleError = true;
        }
        if (count($message) === 1) {
            $message = reset($message);
        }

        // Create JSON object describing the appearance of the message in the console
        $json = $this->toJson(array(
            array(
                'Type'  => $this->logLevels[$record['level']],
                'File'  => $file,
                'Line'  => $line,
                'Label' => $record['channel'],
            ),
            $message,
        ), $handleError);

        // The message itself is a serialization of the above JSON object + it's length
        return sprintf(
            '%s|%s|',
            strlen($json),
            $json
        );
    }

    public function formatBatch(array $records)
    {
        throw new \BadMethodCallException('Batch formatting does not make sense for the WildfireFormatter');
    }

    protected function normalize($data)
    {
        if (is_object($data) && !$data instanceof \DateTime) {
            return $data;
        }

        return parent::normalize($data);
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Formatter;

use Monolog\Logger;

/**
 * Formats a log message according to the ChromePHP array format
 *
 * @author Christophe Coevoet <stof@notk.org>
 */
class ChromePHPFormatter implements FormatterInterface
{
    /**
     * Translates Monolog log levels to Wildfire levels.
     */
    private $logLevels = array(
        Logger::DEBUG     => 'log',
        Logger::INFO      => 'info',
        Logger::NOTICE    => 'info',
        Logger::WARNING   => 'warn',
        Logger::ERROR     => 'error',
        Logger::CRITICAL  => 'error',
        Logger::ALERT     => 'error',
        Logger::EMERGENCY => 'error',
    );

    /**
     * {@inheritdoc}
     */
    public function format(array $record)
    {
        // Retrieve the line and file if set and remove them from the formatted extra
        $backtrace = 'unknown';
        if (isset($record['extra']['file']) && isset($record['extra']['line'])) {
            $backtrace = $record['extra']['file'].' : '.$record['extra']['line'];
            unset($record['extra']['file']);
            unset($record['extra']['line']);
        }

        $message = array('message' => $record['message']);
        if ($record['context']) {
            $message['context'] = $record['context'];
        }
        if ($record['extra']) {
            $message['extra'] = $record['extra'];
        }
        if (count($message) === 1) {
            $message = reset($message);
        }

        return array(
            $record['channel'],
            $message,
            $backtrace,
            $this->logLevels[$record['level']],
        );
    }

    public function formatBatch(array $records)
    {
        $formatted = array();

        foreach ($records as $record) {
            $formatted[] = $this->format($record);
        }

        return $formatted;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Formatter;

use Monolog\Formatter\NormalizerFormatter;

/**
 * Formats data into an associative array of scalar values.
 * Objects and arrays will be JSON encoded.
 *
 * @author Andrew Lawson <adlawson@gmail.com>
 */
class ScalarFormatter extends NormalizerFormatter
{
    /**
     * {@inheritdoc}
     */
    public function format(array $record)
    {
        foreach ($record as $key => $value) {
            $record[$key] = $this->normalizeValue($value);
        }

        return $record;
    }

    /**
     * @param mixed $value
     * @return mixed
     */
    protected function normalizeValue($value)
    {
        $normalized = $this->normalize($value);

        if (is_array($normalized) || is_object($normalized)) {
            return $this->toJson($normalized, true);
        }

        return $normalized;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Formatter;

use Elastica\Document;

/**
 * Format a log message into an Elastica Document
 *
 * @author Jelle Vink <jelle.vink@gmail.com>
 */
class ElasticaFormatter extends NormalizerFormatter
{
    /**
     * @var string Elastic search index name
     */
    protected $index;

    /**
     * @var string Elastic search document type
     */
    protected $type;

    /**
     * @param string $index Elastic Search index name
     * @param string $type  Elastic Search document type
     */
    public function __construct($index, $type)
    {
        parent::__construct(\DateTime::ISO8601);
        $this->index = $index;
        $this->type = $type;
    }

    /**
     * {@inheritdoc}
     */
    public function format(array $record)
    {
        $record = parent::format($record);
        return $this->getDocument($record);
    }

    /**
     * Getter index
     * @return string
     */
    public function getIndex()
    {
        return $this->index;
    }

    /**
     * Getter type
     * @return string
     */
    public function getType()
    {
        return $this->type;
    }

    /**
     * Convert a log message into an Elastica Document
     *
     * @param array  $record Log message
     * @return Document
     */
    protected function getDocument($record)
    {
        $document = new Document();
        $document->setData($record);
        $document->setType($this->type);
        $document->setIndex($this->index);
        return $document;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Formatter;

/**
 * Formats incoming records into a one-line string
 *
 * This is especially useful for logging to files
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Christophe Coevoet <stof@notk.org>
 */
class LineFormatter extends NormalizerFormatter
{
    const SIMPLE_FORMAT = "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n";

    protected $format;

    /**
     * @param string $format     The format of the message
     * @param string $dateFormat The format of the timestamp: one supported by DateTime::format
     */
    public function __construct($format = null, $dateFormat = null)
    {
        $this->format = $format ?: static::SIMPLE_FORMAT;
        parent::__construct($dateFormat);
    }

    /**
     * {@inheritdoc}
     */
    public function format(array $record)
    {
        $vars = parent::format($record);

        $output = $this->format;
        foreach ($vars['extra'] as $var => $val) {
            if (false !== strpos($output, '%extra.'.$var.'%')) {
                $output = str_replace('%extra.'.$var.'%', $this->convertToString($val), $output);
                unset($vars['extra'][$var]);
            }
        }
        foreach ($vars as $var => $val) {
            if (false !== strpos($output, '%'.$var.'%')) {
                $output = str_replace('%'.$var.'%', $this->convertToString($val), $output);
            }
        }

        return $output;
    }

    public function formatBatch(array $records)
    {
        $message = '';
        foreach ($records as $record) {
            $message .= $this->format($record);
        }

        return $message;
    }

    protected function normalize($data)
    {
        if (is_bool($data) || is_null($data)) {
            return var_export($data, true);
        }

        if ($data instanceof \Exception) {
            $previousText = '';
            if ($previous = $data->getPrevious()) {
                do {
                    $previousText .= ', '.get_class($previous).': '.$previous->getMessage().' at '.$previous->getFile().':'.$previous->getLine();
                } while ($previous = $previous->getPrevious());
            }

            return '[object] ('.get_class($data).': '.$data->getMessage().' at '.$data->getFile().':'.$data->getLine().$previousText.')';
        }

        return parent::normalize($data);
    }

    protected function convertToString($data)
    {
        if (null === $data || is_scalar($data)) {
            return (string) $data;
        }

        $data = $this->normalize($data);
        if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
            return $this->toJson($data, true);
        }

        return str_replace('\\/', '/', @json_encode($data));
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Formatter;

/**
 * Encodes whatever record data is passed to it as json
 *
 * This can be useful to log to databases or remote APIs
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class JsonFormatter implements FormatterInterface
{
    /**
     * {@inheritdoc}
     */
    public function format(array $record)
    {
        return json_encode($record);
    }

    /**
     * {@inheritdoc}
     */
    public function formatBatch(array $records)
    {
        return json_encode($records);
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Formatter\NormalizerFormatter;

/**
 * Logs to a MongoDB database.
 *
 * usage example:
 *
 *   $log = new Logger('application');
 *   $mongodb = new MongoDBHandler(new \Mongo("mongodb://localhost:27017"), "logs", "prod");
 *   $log->pushHandler($mongodb);
 *
 * @author Thomas Tourlourat <thomas@tourlourat.com>
 */
class MongoDBHandler extends AbstractProcessingHandler
{
    protected $mongoCollection;

    public function __construct($mongo, $database, $collection, $level = Logger::DEBUG, $bubble = true)
    {
        if (!($mongo instanceof \MongoClient || $mongo instanceof \Mongo)) {
            throw new \InvalidArgumentException('MongoClient or Mongo instance required');
        }

        $this->mongoCollection = $mongo->selectCollection($database, $collection);

        parent::__construct($level, $bubble);
    }

    protected function write(array $record)
    {
        $this->mongoCollection->save($record["formatted"]);
    }

    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter()
    {
        return new NormalizerFormatter();
    }
}
<?php
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Formatter\NormalizerFormatter;
use Monolog\Logger;

/**
 * Handler sending logs to Zend Monitor
 *
 * @author  Christian Bergau <cbergau86@gmail.com>
 */
class ZendMonitorHandler extends AbstractProcessingHandler
{
    /**
     * Monolog level / ZendMonitor Custom Event priority map
     *
     * @var array
     */
    protected $levelMap = array(
        Logger::DEBUG     => 1,
        Logger::INFO      => 2,
        Logger::NOTICE    => 3,
        Logger::WARNING   => 4,
        Logger::ERROR     => 5,
        Logger::CRITICAL  => 6,
        Logger::ALERT     => 7,
        Logger::EMERGENCY => 0,
    );

    /**
     * Construct
     *
     * @param  int                       $level
     * @param  bool                      $bubble
     * @throws MissingExtensionException
     */
    public function __construct($level = Logger::DEBUG, $bubble = true)
    {
        if (!function_exists('zend_monitor_custom_event')) {
            throw new MissingExtensionException('You must have Zend Server installed in order to use this handler');
        }
        parent::__construct($level, $bubble);
    }

    /**
     * {@inheritdoc}
     */
    protected function write(array $record)
    {
        $this->writeZendMonitorCustomEvent(
            $this->levelMap[$record['level']],
            $record['message'],
            $record['formatted']
        );
    }

    /**
     * Write a record to Zend Monitor
     *
     * @param int    $level
     * @param string $message
     * @param array  $formatted
     */
    protected function writeZendMonitorCustomEvent($level, $message, $formatted)
    {
        zend_monitor_custom_event($level, $message, $formatted);
    }

    /**
     * {@inheritdoc}
     */
    public function getDefaultFormatter()
    {
        return new NormalizerFormatter();
    }

    /**
     * Get the level map
     *
     * @return array
     */
    public function getLevelMap()
    {
        return $this->levelMap;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Logger;

/**
 * Blackhole
 *
 * Any record it can handle will be thrown away. This can be used
 * to put on top of an existing stack to override it temporarily.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class NullHandler extends AbstractHandler
{
    /**
     * @param integer $level The minimum logging level at which this handler will be triggered
     */
    public function __construct($level = Logger::DEBUG)
    {
        parent::__construct($level, false);
    }

    /**
     * {@inheritdoc}
     */
    public function handle(array $record)
    {
        if ($record['level'] < $this->level) {
            return false;
        }

        return true;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Formatter\LineFormatter;
use Monolog\Formatter\FormatterInterface;
use Monolog\Logger;
use Monolog\Handler\AbstractProcessingHandler;
use Raven_Client;

/**
 * Handler to send messages to a Sentry (https://github.com/dcramer/sentry) server
 * using raven-php (https://github.com/getsentry/raven-php)
 *
 * @author Marc Abramowitz <marc@marc-abramowitz.com>
 */
class RavenHandler extends AbstractProcessingHandler
{
    /**
     * Translates Monolog log levels to Raven log levels.
     */
    private $logLevels = array(
        Logger::DEBUG     => Raven_Client::DEBUG,
        Logger::INFO      => Raven_Client::INFO,
        Logger::NOTICE    => Raven_Client::INFO,
        Logger::WARNING   => Raven_Client::WARNING,
        Logger::ERROR     => Raven_Client::ERROR,
        Logger::CRITICAL  => Raven_Client::FATAL,
        Logger::ALERT     => Raven_Client::FATAL,
        Logger::EMERGENCY => Raven_Client::FATAL,
    );

    /**
     * @var Raven_Client the client object that sends the message to the server
     */
    protected $ravenClient;

    /**
     * @var LineFormatter The formatter to use for the logs generated via handleBatch()
     */
    protected $batchFormatter;

    /**
     * @param Raven_Client $ravenClient
     * @param integer      $level       The minimum logging level at which this handler will be triggered
     * @param Boolean      $bubble      Whether the messages that are handled can bubble up the stack or not
     */
    public function __construct(Raven_Client $ravenClient, $level = Logger::DEBUG, $bubble = true)
    {
        parent::__construct($level, $bubble);

        $this->ravenClient = $ravenClient;
    }

    /**
     * {@inheritdoc}
     */
    public function handleBatch(array $records)
    {
        $level = $this->level;

        // filter records based on their level
        $records = array_filter($records, function($record) use ($level) {
            return $record['level'] >= $level;
        });

        if (!$records) {
            return;
        }

        // the record with the highest severity is the "main" one
        $record = array_reduce($records, function($highest, $record) {
            if ($record['level'] >= $highest['level']) {
                return $record;
            }

            return $highest;
        });

        // the other ones are added as a context item
        $logs = array();
        foreach ($records as $r) {
            $logs[] = $this->processRecord($r);
        }

        if ($logs) {
            $record['context']['logs'] = (string) $this->getBatchFormatter()->formatBatch($logs);
        }

        $this->handle($record);
    }

    /**
     * Sets the formatter for the logs generated by handleBatch().
     *
     * @param FormatterInterface $formatter
     */
    public function setBatchFormatter(FormatterInterface $formatter)
    {
        $this->batchFormatter = $formatter;
    }

    /**
     * Gets the formatter for the logs generated by handleBatch().
     *
     * @return FormatterInterface
     */
    public function getBatchFormatter()
    {
        if (!$this->batchFormatter) {
            $this->batchFormatter = $this->getDefaultBatchFormatter();
        }

        return $this->batchFormatter;
    }

    /**
     * {@inheritdoc}
     */
    protected function write(array $record)
    {
        $options = array();
        $options['level'] = $this->logLevels[$record['level']];
        if (!empty($record['context'])) {
            $options['extra']['context'] = $record['context'];
        }
        if (!empty($record['extra'])) {
            $options['extra']['extra'] = $record['extra'];
        }

        if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Exception) {
            $options['extra']['message'] = $record['formatted'];
            $this->ravenClient->captureException($record['context']['exception'], $options);

            return;
        }

        $this->ravenClient->captureMessage($record['formatted'], array(), $options);
    }

    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter()
    {
        return new LineFormatter('[%channel%] %message%');
    }

    /**
     * Gets the default formatter for the logs generated by handleBatch().
     *
     * @return FormatterInterface
     */
    protected function getDefaultBatchFormatter()
    {
        return new LineFormatter();
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Logger;

/**
 * Used for testing purposes.
 *
 * It records all records and gives you access to them for verification.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class TestHandler extends AbstractProcessingHandler
{
    protected $records = array();
    protected $recordsByLevel = array();

    public function getRecords()
    {
        return $this->records;
    }

    public function hasEmergency($record)
    {
        return $this->hasRecord($record, Logger::EMERGENCY);
    }

    public function hasAlert($record)
    {
        return $this->hasRecord($record, Logger::ALERT);
    }

    public function hasCritical($record)
    {
        return $this->hasRecord($record, Logger::CRITICAL);
    }

    public function hasError($record)
    {
        return $this->hasRecord($record, Logger::ERROR);
    }

    public function hasWarning($record)
    {
        return $this->hasRecord($record, Logger::WARNING);
    }

    public function hasNotice($record)
    {
        return $this->hasRecord($record, Logger::NOTICE);
    }

    public function hasInfo($record)
    {
        return $this->hasRecord($record, Logger::INFO);
    }

    public function hasDebug($record)
    {
        return $this->hasRecord($record, Logger::DEBUG);
    }

    public function hasEmergencyRecords()
    {
        return isset($this->recordsByLevel[Logger::EMERGENCY]);
    }

    public function hasAlertRecords()
    {
        return isset($this->recordsByLevel[Logger::ALERT]);
    }

    public function hasCriticalRecords()
    {
        return isset($this->recordsByLevel[Logger::CRITICAL]);
    }

    public function hasErrorRecords()
    {
        return isset($this->recordsByLevel[Logger::ERROR]);
    }

    public function hasWarningRecords()
    {
        return isset($this->recordsByLevel[Logger::WARNING]);
    }

    public function hasNoticeRecords()
    {
        return isset($this->recordsByLevel[Logger::NOTICE]);
    }

    public function hasInfoRecords()
    {
        return isset($this->recordsByLevel[Logger::INFO]);
    }

    public function hasDebugRecords()
    {
        return isset($this->recordsByLevel[Logger::DEBUG]);
    }

    protected function hasRecord($record, $level)
    {
        if (!isset($this->recordsByLevel[$level])) {
            return false;
        }

        if (is_array($record)) {
            $record = $record['message'];
        }

        foreach ($this->recordsByLevel[$level] as $rec) {
            if ($rec['message'] === $record) {
                return true;
            }
        }

        return false;
    }

    /**
     * {@inheritdoc}
     */
    protected function write(array $record)
    {
        $this->recordsByLevel[$record['level']][] = $record;
        $this->records[] = $record;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Formatter\ChromePHPFormatter;
use Monolog\Logger;

/**
 * Handler sending logs to the ChromePHP extension (http://www.chromephp.com/)
 *
 * @author Christophe Coevoet <stof@notk.org>
 */
class ChromePHPHandler extends AbstractProcessingHandler
{
    /**
     * Version of the extension
     */
    const VERSION = '4.0';

    /**
     * Header name
     */
    const HEADER_NAME = 'X-ChromeLogger-Data';

    protected static $initialized = false;

    /**
     * Tracks whether we sent too much data
     *
     * Chrome limits the headers to 256KB, so when we sent 240KB we stop sending
     *
     * @var Boolean
     */
    protected static $overflowed = false;

    protected static $json = array(
        'version' => self::VERSION,
        'columns' => array('label', 'log', 'backtrace', 'type'),
        'rows' => array(),
    );

    protected static $sendHeaders = true;

    /**
     * {@inheritdoc}
     */
    public function handleBatch(array $records)
    {
        $messages = array();

        foreach ($records as $record) {
            if ($record['level'] < $this->level) {
                continue;
            }
            $messages[] = $this->processRecord($record);
        }

        if (!empty($messages)) {
            $messages = $this->getFormatter()->formatBatch($messages);
            self::$json['rows'] = array_merge(self::$json['rows'], $messages);
            $this->send();
        }
    }

    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter()
    {
        return new ChromePHPFormatter();
    }

    /**
     * Creates & sends header for a record
     *
     * @see sendHeader()
     * @see send()
     * @param array $record
     */
    protected function write(array $record)
    {
        self::$json['rows'][] = $record['formatted'];

        $this->send();
    }

    /**
     * Sends the log header
     *
     * @see sendHeader()
     */
    protected function send()
    {
        if (self::$overflowed) {
            return;
        }

        if (!self::$initialized) {
            self::$sendHeaders = $this->headersAccepted();
            self::$json['request_uri'] = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';

            self::$initialized = true;
        }

        $json = @json_encode(self::$json);
        $data = base64_encode(utf8_encode($json));
        if (strlen($data) > 240*1024) {
            self::$overflowed = true;

            $record = array(
                'message' => 'Incomplete logs, chrome header size limit reached',
                'context' => array(),
                'level' => Logger::WARNING,
                'level_name' => Logger::getLevelName(Logger::WARNING),
                'channel' => 'monolog',
                'datetime' => new \DateTime(),
                'extra' => array(),
            );
            self::$json['rows'][count(self::$json['rows']) - 1] = $this->getFormatter()->format($record);
            $json = @json_encode(self::$json);
            $data = base64_encode(utf8_encode($json));
        }

        $this->sendHeader(self::HEADER_NAME, $data);
    }

    /**
     * Send header string to the client
     *
     * @param string $header
     * @param string $content
     */
    protected function sendHeader($header, $content)
    {
        if (!headers_sent() && self::$sendHeaders) {
            header(sprintf('%s: %s', $header, $content));
        }
    }

    /**
     * Verifies if the headers are accepted by the current user agent
     *
     * @return Boolean
     */
    protected function headersAccepted()
    {
        return !isset($_SERVER['HTTP_USER_AGENT'])
               || preg_match('{\bChrome/\d+[\.\d+]*\b}', $_SERVER['HTTP_USER_AGENT']);
    }

    /**
     * BC getter for the sendHeaders property that has been made static
     */
    public function __get($property)
    {
        if ('sendHeaders' !== $property) {
            throw new \InvalidArgumentException('Undefined property '.$property);
        }

        return static::$sendHeaders;
    }

    /**
     * BC setter for the sendHeaders property that has been made static
     */
    public function __set($property, $value)
    {
        if ('sendHeaders' !== $property) {
            throw new \InvalidArgumentException('Undefined property '.$property);
        }

        static::$sendHeaders = $value;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Aws\Common\Aws;
use Aws\DynamoDb\DynamoDbClient;
use Monolog\Formatter\ScalarFormatter;
use Monolog\Handler\AbstractProcessingHandler;
use Monolog\Logger;

/**
 * Amazon DynamoDB handler (http://aws.amazon.com/dynamodb/)
 *
 * @link https://github.com/aws/aws-sdk-php/
 * @author Andrew Lawson <adlawson@gmail.com>
 */
class DynamoDbHandler extends AbstractProcessingHandler
{
    const DATE_FORMAT = 'Y-m-d\TH:i:s.uO';

    /**
     * @var DynamoDbClient
     */
    protected $client;

    /**
     * @var string
     */
    protected $table;

    /**
     * @param DynamoDbClient $client
     * @param string $table
     * @param integer $level
     * @param boolean $bubble
     */
    public function __construct(DynamoDbClient $client, $table, $level = Logger::DEBUG, $bubble = true)
    {
        if (!defined('Aws\Common\Aws::VERSION') || version_compare('3.0', Aws::VERSION, '<=')) {
            throw new \RuntimeException('The DynamoDbHandler is only known to work with the AWS SDK 2.x releases');
        }

        $this->client = $client;
        $this->table = $table;

        parent::__construct($level, $bubble);
    }

    /**
     * {@inheritdoc}
     */
    protected function write(array $record)
    {
        $filtered = $this->filterEmptyFields($record['formatted']);
        $formatted = $this->client->formatAttributes($filtered);

        $this->client->putItem(array(
            'TableName' => $this->table,
            'Item' => $formatted
        ));
    }

    /**
     * @param array $record
     * @return array
     */
    protected function filterEmptyFields(array $record)
    {
        return array_filter($record, function($value) {
            return !empty($value) || false === $value || 0 === $value;
        });
    }

    /**
     * {@inheritdoc}
     */
    protected function getDefaultFormatter()
    {
        return new ScalarFormatter(self::DATE_FORMAT);
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Formatter\FormatterInterface;

/**
 * Interface that all Monolog Handlers must implement
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface HandlerInterface
{
    /**
     * Checks whether the given record will be handled by this handler.
     *
     * This is mostly done for performance reasons, to avoid calling processors for nothing.
     *
     * Handlers should still check the record levels within handle(), returning false in isHandling()
     * is no guarantee that handle() will not be called, and isHandling() might not be called
     * for a given record.
     *
     * @param array $record
     *
     * @return Boolean
     */
    public function isHandling(array $record);

    /**
     * Handles a record.
     *
     * All records may be passed to this method, and the handler should discard
     * those that it does not want to handle.
     *
     * The return value of this function controls the bubbling process of the handler stack.
     * Unless the bubbling is interrupted (by returning true), the Logger class will keep on
     * calling further handlers in the stack with a given log record.
     *
     * @param  array   $record The record to handle
     * @return Boolean true means that this handler handled the record, and that bubbling is not permitted.
     *                 false means the record was either not processed or that this handler allows bubbling.
     */
    public function handle(array $record);

    /**
     * Handles a set of records at once.
     *
     * @param array $records The records to handle (an array of record arrays)
     */
    public function handleBatch(array $records);

    /**
     * Adds a processor in the stack.
     *
     * @param  callable $callback
     * @return self
     */
    public function pushProcessor($callback);

    /**
     * Removes the processor on top of the stack and returns it.
     *
     * @return callable
     */
    public function popProcessor();

    /**
     * Sets the formatter.
     *
     * @param  FormatterInterface $formatter
     * @return self
     */
    public function setFormatter(FormatterInterface $formatter);

    /**
     * Gets the formatter.
     *
     * @return FormatterInterface
     */
    public function getFormatter();
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LineFormatter;

/**
 * Base Handler class providing the Handler structure
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
abstract class AbstractHandler implements HandlerInterface
{
    protected $level = Logger::DEBUG;
    protected $bubble = true;

    /**
     * @var FormatterInterface
     */
    protected $formatter;
    protected $processors = array();

    /**
     * @param integer $level  The minimum logging level at which this handler will be triggered
     * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
     */
    public function __construct($level = Logger::DEBUG, $bubble = true)
    {
        $this->level = $level;
        $this->bubble = $bubble;
    }

    /**
     * {@inheritdoc}
     */
    public function isHandling(array $record)
    {
        return $record['level'] >= $this->level;
    }

    /**
     * {@inheritdoc}
     */
    public function handleBatch(array $records)
    {
        foreach ($records as $record) {
            $this->handle($record);
        }
    }

    /**
     * Closes the handler.
     *
     * This will be called automatically when the object is destroyed
     */
    public function close()
    {
    }

    /**
     * {@inheritdoc}
     */
    public function pushProcessor($callback)
    {
        if (!is_callable($callback)) {
            throw new \InvalidArgumentException('Processors must be valid callables (callback or object with an __invoke method), '.var_export($callback, true).' given');
        }
        array_unshift($this->processors, $callback);

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function popProcessor()
    {
        if (!$this->processors) {
            throw new \LogicException('You tried to pop from an empty processor stack.');
        }

        return array_shift($this->processors);
    }

    /**
     * {@inheritdoc}
     */
    public function setFormatter(FormatterInterface $formatter)
    {
        $this->formatter = $formatter;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function getFormatter()
    {
        if (!$this->formatter) {
            $this->formatter = $this->getDefaultFormatter();
        }

        return $this->formatter;
    }

    /**
     * Sets minimum logging level at which this handler will be triggered.
     *
     * @param  integer $level
     * @return self
     */
    public function setLevel($level)
    {
        $this->level = $level;

        return $this;
    }

    /**
     * Gets minimum logging level at which this handler will be triggered.
     *
     * @return integer
     */
    public function getLevel()
    {
        return $this->level;
    }

    /**
     * Sets the bubbling behavior.
     *
     * @param Boolean $bubble true means that this handler allows bubbling.
     *                        false means that bubbling is not permitted.
     * @return self
     */
    public function setBubble($bubble)
    {
        $this->bubble = $bubble;

        return $this;
    }

    /**
     * Gets the bubbling behavior.
     *
     * @return Boolean true means that this handler allows bubbling.
     *                 false means that bubbling is not permitted.
     */
    public function getBubble()
    {
        return $this->bubble;
    }

    public function __destruct()
    {
        try {
            $this->close();
        } catch (\Exception $e) {
            // do nothing
        }
    }

    /**
     * Gets the default formatter.
     *
     * @return FormatterInterface
     */
    protected function getDefaultFormatter()
    {
        return new LineFormatter();
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Formatter\JsonFormatter;

/**
 * Sends errors to Loggly.
 *
 * @author Przemek Sobstel <przemek@sobstel.org>
 */
class LogglyHandler extends AbstractProcessingHandler
{
    const HOST = 'logs-01.loggly.com';

    protected $token;

    protected $tag;

    public function __construct($token, $level = Logger::DEBUG, $bubble = true)
    {
        if (!extension_loaded('curl')) {
            throw new \LogicException('The curl extension is needed to use the LogglyHandler');
        }

        $this->token = $token;

        parent::__construct($level, $bubble);
    }

    public function setTag($tag)
    {
        $this->tag = $tag;
    }

    protected function write(array $record)
    {
        $url = sprintf("http://%s/inputs/%s/", self::HOST, $this->token);
        if ($this->tag) {
            $url .= sprintf("tag/%s/", $this->tag);
        }

        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $record["formatted"]);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        curl_exec($ch);
        curl_close($ch);
    }

    protected function getDefaultFormatter()
    {
        return new JsonFormatter();
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Logger;

/**
 * Stores to PHP error_log() handler.
 *
 * @author Elan Ruusamäe <glen@delfi.ee>
 */
class ErrorLogHandler extends AbstractProcessingHandler
{
    const OPERATING_SYSTEM = 0;
    const SAPI = 4;

    protected $messageType;

    /**
     * @param integer $messageType Says where the error should go.
     * @param integer $level       The minimum logging level at which this handler will be triggered
     * @param Boolean $bubble      Whether the messages that are handled can bubble up the stack or not
     */
    public function __construct($messageType = self::OPERATING_SYSTEM, $level = Logger::DEBUG, $bubble = true)
    {
        parent::__construct($level, $bubble);

        if (false === in_array($messageType, self::getAvailableTypes())) {
            $message = sprintf('The given message type "%s" is not supported', print_r($messageType, true));
            throw new \InvalidArgumentException($message);
        }

        $this->messageType = $messageType;
    }

    /**
     * @return array With all available types
     */
    public static function getAvailableTypes()
    {
        return array(
            self::OPERATING_SYSTEM,
            self::SAPI,
        );
    }

    /**
     * {@inheritdoc}
     */
    protected function write(array $record)
    {
        error_log((string) $record['formatted'], $this->messageType);
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler\SyslogUdp;

class UdpSocket
{
    const DATAGRAM_MAX_LENGTH = 2048;

    public function __construct($ip, $port = 514)
    {
        $this->ip = $ip;
        $this->port = $port;
        $this->socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
    }

    public function write($line, $header = "")
    {
        $remaining = $line;
        while (!is_null($remaining)) {
            list($chunk, $remaining) = $this->splitLineIfNessesary($remaining, $header);
            $this->send($chunk);
        }
    }

    public function close()
    {
        socket_close($this->socket);
    }

    protected function send($chunk)
    {
        socket_sendto($this->socket, $chunk, strlen($chunk), $flags = 0, $this->ip, $this->port);
    }

    protected function splitLineIfNessesary($line, $header)
    {
        if ($this->shouldSplitLine($line, $header)) {
            $chunkSize = self::DATAGRAM_MAX_LENGTH - strlen($header);
            $chunk = $header . substr($line, 0, $chunkSize);
            $remaining = substr($line, $chunkSize);
        } else {
            $chunk = $header . $line;
            $remaining = null;
        }

        return array($chunk, $remaining);
    }

    protected function shouldSplitLine($remaining, $header)
    {
        return strlen($header.$remaining) > self::DATAGRAM_MAX_LENGTH;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Logger;

/**
 * Sends notifications through the pushover api to mobile phones
 *
 * @author Sebastian Göttschkes <sebastian.goettschkes@googlemail.com>
 * @see    https://www.pushover.net/api
 */
class PushoverHandler extends SocketHandler
{
    private $token;
    private $users;
    private $title;
    private $user;
    private $retry;
    private $expire;

    private $highPriorityLevel;
    private $emergencyLevel;

    /**
     * @param string       $token  Pushover api token
     * @param string|array $users  Pushover user id or array of ids the message will be sent to
     * @param string       $title  Title sent to the Pushover API
     * @param integer      $level  The minimum logging level at which this handler will be triggered
     * @param Boolean      $bubble Whether the messages that are handled can bubble up the stack or not
     * @param Boolean      $useSSL Whether to connect via SSL. Required when pushing messages to users that are not
     *                        the pushover.net app owner. OpenSSL is required for this option.
     * @param integer $highPriorityLevel The minimum logging level at which this handler will start
     *                                   sending "high priority" requests to the Pushover API
     * @param integer $emergencyLevel The minimum logging level at which this handler will start
     *                                sending "emergency" requests to the Pushover API
     * @param integer $retry  The retry parameter specifies how often (in seconds) the Pushover servers will send the same notification to the user.
     * @param integer $expire The expire parameter specifies how many seconds your notification will continue to be retried for (every retry seconds).
     */
    public function __construct($token, $users, $title = null, $level = Logger::CRITICAL, $bubble = true, $useSSL = true, $highPriorityLevel = Logger::CRITICAL, $emergencyLevel = Logger::EMERGENCY, $retry = 30, $expire = 25200)
    {
        $connectionString = $useSSL ? 'ssl://api.pushover.net:443' : 'api.pushover.net:80';
        parent::__construct($connectionString, $level, $bubble);

        $this->token = $token;
        $this->users = (array) $users;
        $this->title = $title ?: gethostname();
        $this->highPriorityLevel = $highPriorityLevel;
        $this->emergencyLevel = $emergencyLevel;
        $this->retry = $retry;
        $this->expire = $expire;
    }

    protected function generateDataStream($record)
    {
        $content = $this->buildContent($record);

        return $this->buildHeader($content) . $content;
    }

    private function buildContent($record)
    {
        // Pushover has a limit of 512 characters on title and message combined.
        $maxMessageLength = 512 - strlen($this->title);
        $message = substr($record['message'], 0, $maxMessageLength);
        $timestamp = $record['datetime']->getTimestamp();

        $dataArray = array(
            'token' => $this->token,
            'user' => $this->user,
            'message' => $message,
            'title' => $this->title,
            'timestamp' => $timestamp
        );

        if ($record['level'] >= $this->emergencyLevel) {
            $dataArray['priority'] = 2;
            $dataArray['retry'] = $this->retry;
            $dataArray['expire'] = $this->expire;
        } elseif ($record['level'] >= $this->highPriorityLevel) {
            $dataArray['priority'] = 1;
        }

        return http_build_query($dataArray);
    }

    private function buildHeader($content)
    {
        $header = "POST /1/messages.json HTTP/1.1\r\n";
        $header .= "Host: api.pushover.net\r\n";
        $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
        $header .= "Content-Length: " . strlen($content) . "\r\n";
        $header .= "\r\n";

        return $header;
    }

    public function write(array $record)
    {
        foreach ($this->users as $user) {
            $this->user = $user;

            parent::write($record);
            $this->closeSocket();
        }

        $this->user = null;
    }

    public function setHighPriorityLevel($value)
    {
        $this->highPriorityLevel = $value;
    }

    public function setEmergencyLevel($value)
    {
        $this->emergencyLevel = $value;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Formatter\LineFormatter;

/**
 * Logs to a Redis key using rpush
 *
 * usage example:
 *
 *   $log = new Logger('application');
 *   $redis = new RedisHandler(new Predis\Client("tcp://localhost:6379"), "logs", "prod");
 *   $log->pushHandler($redis);
 *
 * @author Thomas Tourlourat <thomas@tourlourat.com>
 */
class RedisHandler extends AbstractProcessingHandler
{
    private $redisClient;
    private $redisKey;

    # redis instance, key to use
    public function __construct($redis, $key, $level = Logger::DEBUG, $bubble = true)
    {
        if (!(($redis instanceof \Predis\Client) || ($redis instanceof \Redis))) {
            throw new \InvalidArgumentException('Predis\Client or Redis instance required');
        }

        $this->redisClient = $redis;
        $this->redisKey = $key;

        parent::__construct($level, $bubble);
    }

    protected function write(array $record)
    {
        $this->redisClient->rpush($this->redisKey, $record["formatted"]);
    }

    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter()
    {
        return new LineFormatter();
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Formatter\LineFormatter;

/**
 * Common syslog functionality
 */
abstract class AbstractSyslogHandler extends AbstractProcessingHandler
{
    protected $facility;

    /**
     * Translates Monolog log levels to syslog log priorities.
     */
    protected $logLevels = array(
        Logger::DEBUG     => LOG_DEBUG,
        Logger::INFO      => LOG_INFO,
        Logger::NOTICE    => LOG_NOTICE,
        Logger::WARNING   => LOG_WARNING,
        Logger::ERROR     => LOG_ERR,
        Logger::CRITICAL  => LOG_CRIT,
        Logger::ALERT     => LOG_ALERT,
        Logger::EMERGENCY => LOG_EMERG,
    );

    /**
     * List of valid log facility names.
     */
    protected $facilities = array(
        'auth'     => LOG_AUTH,
        'authpriv' => LOG_AUTHPRIV,
        'cron'     => LOG_CRON,
        'daemon'   => LOG_DAEMON,
        'kern'     => LOG_KERN,
        'lpr'      => LOG_LPR,
        'mail'     => LOG_MAIL,
        'news'     => LOG_NEWS,
        'syslog'   => LOG_SYSLOG,
        'user'     => LOG_USER,
        'uucp'     => LOG_UUCP,
    );

    /**
     * @param mixed   $facility
     * @param integer $level    The minimum logging level at which this handler will be triggered
     * @param Boolean $bubble   Whether the messages that are handled can bubble up the stack or not
     */
    public function __construct($facility = LOG_USER, $level = Logger::DEBUG, $bubble = true)
    {
        parent::__construct($level, $bubble);

        if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->facilities['local0'] = LOG_LOCAL0;
            $this->facilities['local1'] = LOG_LOCAL1;
            $this->facilities['local2'] = LOG_LOCAL2;
            $this->facilities['local3'] = LOG_LOCAL3;
            $this->facilities['local4'] = LOG_LOCAL4;
            $this->facilities['local5'] = LOG_LOCAL5;
            $this->facilities['local6'] = LOG_LOCAL6;
            $this->facilities['local7'] = LOG_LOCAL7;
        }

        // convert textual description of facility to syslog constant
        if (array_key_exists(strtolower($facility), $this->facilities)) {
            $facility = $this->facilities[strtolower($facility)];
        } elseif (!in_array($facility, array_values($this->facilities), true)) {
            throw new \UnexpectedValueException('Unknown facility value "'.$facility.'" given');
        }

        $this->facility = $facility;
    }

    /**
     * {@inheritdoc}
     */
    protected function getDefaultFormatter()
    {
        return new LineFormatter('%channel%.%level_name%: %message% %context% %extra%');
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Logger;

/**
 * Sends notifications through the hipchat api to a hipchat room
 *
 * Notes:
 * API token - HipChat API token
 * Room      - HipChat Room Id or name, where messages are sent
 * Name      - Name used to send the message (from)
 * notify    - Should the message trigger a notification in the clients
 *
 * @author Rafael Dohms <rafael@doh.ms>
 * @see    https://www.hipchat.com/docs/api
 */
class HipChatHandler extends SocketHandler
{
    /**
     * @var string
     */
    private $token;

    /**
     * @var array
     */
    private $room;

    /**
     * @var string
     */
    private $name;

    /**
     * @var boolean
     */
    private $notify;

    /**
     * @param string  $token  HipChat API Token
     * @param string  $room   The room that should be alerted of the message (Id or Name)
     * @param string  $name   Name used in the "from" field
     * @param bool    $notify Trigger a notification in clients or not
     * @param int     $level  The minimum logging level at which this handler will be triggered
     * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
     * @param Boolean $useSSL Whether to connect via SSL.
     */
    public function __construct($token, $room, $name = 'Monolog', $notify = false, $level = Logger::CRITICAL, $bubble = true, $useSSL = true)
    {
        $connectionString = $useSSL ? 'ssl://api.hipchat.com:443' : 'api.hipchat.com:80';
        parent::__construct($connectionString, $level, $bubble);

        $this->token = $token;
        $this->name = $name;
        $this->notify = $notify;
        $this->room = $room;
    }

    /**
     * {@inheritdoc}
     *
     * @param  array  $record
     * @return string
     */
    protected function generateDataStream($record)
    {
        $content = $this->buildContent($record);

        return $this->buildHeader($content) . $content;
    }

    /**
     * Builds the body of API call
     *
     * @param  array  $record
     * @return string
     */
    private function buildContent($record)
    {
        $dataArray = array(
            'from' => $this->name,
            'room_id' => $this->room,
            'notify' => $this->notify,
            'message' => $record['formatted'],
            'message_format' => 'text',
            'color' => $this->getAlertColor($record['level']),
        );

        return http_build_query($dataArray);
    }

    /**
     * Builds the header of the API Call
     *
     * @param  string $content
     * @return string
     */
    private function buildHeader($content)
    {
        $header = "POST /v1/rooms/message?format=json&auth_token=".$this->token." HTTP/1.1\r\n";
        $header .= "Host: api.hipchat.com\r\n";
        $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
        $header .= "Content-Length: " . strlen($content) . "\r\n";
        $header .= "\r\n";

        return $header;
    }

    /**
     * Assigns a color to each level of log records.
     *
     * @param  integer $level
     * @return string
     */
    protected function getAlertColor($level)
    {
        switch (true) {
            case $level >= Logger::ERROR:
                return 'red';
            case $level >= Logger::WARNING:
                return 'yellow';
            case $level >= Logger::INFO:
                return 'green';
            case $level == Logger::DEBUG:
                return 'gray';
            default:
                return 'yellow';
        }
    }

    /**
     * {@inheritdoc}
     *
     * @param array $record
     */
    public function write(array $record)
    {
        parent::write($record);
        $this->closeSocket();
    }

    /**
     * {@inheritdoc}
     */
    public function handleBatch(array $records)
    {
        if (count($records) == 0) {
            return true;
        }

        $batchRecord = $this->combineRecords($records);

        if (!$this->isHandling($batchRecord)) {
            return false;
        }

        $this->write($batchRecord);

        return false === $this->bubble;
    }

    /**
     * Combines multiple records into one. Error level of the combined record
     * will be the highest level from the given records. Datetime will be taken
     * from the first record.
     *
     * @param $records
     * @return array
     */
    private function combineRecords($records)
    {
        $messages = array();
        $formattedMessages = array();
        $level = 0;
        $levelName = null;
        $datetime = null;

        foreach ($records as $record) {

            $record = $this->processRecord($record);
            $record['formatted'] = $this->getFormatter()->format($record);

            $messages[] = $record['message'];
            $formattedMessages[] = $record['formatted'];

            if ($record['level'] > $level) {
                $level = $record['level'];
                $levelName = $record['level_name'];
            }

            if (null === $datetime) {
                $datetime = $record['datetime'];
            }
        }

        $batchRecord = array(
            'message' => implode(PHP_EOL, $messages),
            'formatted' => implode('', $formattedMessages),
            'level' => $level,
            'level_name' => $levelName,
            'datetime' => $datetime,
            'context' => array(),
            'extra' => array(),
        );

        return $batchRecord;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Logger;

/**
 * Class to record a log on a NewRelic application
 *
 * @see https://newrelic.com/docs/php/new-relic-for-php
 */
class NewRelicHandler extends AbstractProcessingHandler
{
    /**
     * Name of the New Relic application that will receive logs from this handler.
     *
     * @var string
     */
    protected $appName;

    /**
     * {@inheritDoc}
     *
     * @param string $appName
     */
    public function __construct($level = Logger::ERROR, $bubble = true, $appName = null)
    {
        parent::__construct($level, $bubble);

        $this->appName = $appName;
    }

    /**
     * {@inheritDoc}
     */
    protected function write(array $record)
    {
        if (!$this->isNewRelicEnabled()) {
            throw new MissingExtensionException('The newrelic PHP extension is required to use the NewRelicHandler');
        }

        if ($appName = $this->getAppName($record['context'])) {
            $this->setNewRelicAppName($appName);
        }

        if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Exception) {
            newrelic_notice_error($record['message'], $record['context']['exception']);
            unset($record['context']['exception']);
        } else {
            newrelic_notice_error($record['message']);
        }

        foreach ($record['context'] as $key => $parameter) {
            newrelic_add_custom_parameter($key, $parameter);
        }
    }

    /**
     * Checks whether the NewRelic extension is enabled in the system.
     *
     * @return bool
     */
    protected function isNewRelicEnabled()
    {
        return extension_loaded('newrelic');
    }

    /**
     * Returns the appname where this log should be sent. Each log can override the default appname, set in this
     * handler's constructor, by providing the appname in its context.
     *
     * @param  array       $context
     * @return null|string
     */
    protected function getAppName(array $context)
    {
        if (isset($context['appname'])) {
            return $context['appname'];
        }

        return $this->appName;
    }

    /**
     * Sets the NewRelic application that should receive this log.
     *
     * @param string $appName
     */
    protected function setNewRelicAppName($appName)
    {
        newrelic_set_appname($appName);
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Handler\SyslogUdp\UdpSocket;

/**
 * A Handler for logging to a remote syslogd server.
 *
 * @author Jesper Skovgaard Nielsen <nulpunkt@gmail.com>
 */
class SyslogUdpHandler extends AbstractSyslogHandler
{
    /**
     * @param string  $host
     * @param int     $port
     * @param mixed   $facility
     * @param integer $level    The minimum logging level at which this handler will be triggered
     * @param Boolean $bubble   Whether the messages that are handled can bubble up the stack or not
     */
    public function __construct($host, $port = 514, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true)
    {
        parent::__construct($facility, $level, $bubble);

        $this->socket = new UdpSocket($host, $port ?: 514);
    }

    protected function write(array $record)
    {
        $lines = $this->splitMessageIntoLines($record['formatted']);

        $header = $this->makeCommonSyslogHeader($this->logLevels[$record['level']]);

        foreach ($lines as $line) {
            $this->socket->write($line, $header);
        }
    }

    public function close()
    {
        $this->socket->close();
    }

    private function splitMessageIntoLines($message)
    {
        if (is_array($message)) {
            $message = implode("\n", $message);
        }

        return preg_split('/$\R?^/m', $message);
    }

    /**
     * Make common syslog header (see rfc5424)
     */
    private function makeCommonSyslogHeader($severity)
    {
        $priority = $severity + $this->facility;

        return "<$priority>: ";
    }

    /**
     * Inject your own socket, mainly used for testing
     */
    public function setSocket($socket)
    {
        $this->socket = $socket;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

/**
 * Base class for all mail handlers
 *
 * @author Gyula Sallai
 */
abstract class MailHandler extends AbstractProcessingHandler
{
    /**
     * {@inheritdoc}
     */
    public function handleBatch(array $records)
    {
        $messages = array();

        foreach ($records as $record) {
            if ($record['level'] < $this->level) {
                continue;
            }
            $messages[] = $this->processRecord($record);
        }

        if (!empty($messages)) {
            $this->send((string) $this->getFormatter()->formatBatch($messages), $messages);
        }
    }

    /**
     * Send a mail with the given content
     *
     * @param string $content
     * @param array  $records the array of log records that formed this content
     */
    abstract protected function send($content, array $records);

    /**
     * {@inheritdoc}
     */
    protected function write(array $record)
    {
        $this->send((string) $record['formatted'], array($record));
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Logger;

/**
 * Stores logs to files that are rotated every day and a limited number of files are kept.
 *
 * This rotation is only intended to be used as a workaround. Using logrotate to
 * handle the rotation is strongly encouraged when you can use it.
 *
 * @author Christophe Coevoet <stof@notk.org>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class RotatingFileHandler extends StreamHandler
{
    protected $filename;
    protected $maxFiles;
    protected $mustRotate;
    protected $nextRotation;
    protected $filenameFormat;
    protected $dateFormat;

    /**
     * @param string  $filename
     * @param integer $maxFiles The maximal amount of files to keep (0 means unlimited)
     * @param integer $level    The minimum logging level at which this handler will be triggered
     * @param Boolean $bubble   Whether the messages that are handled can bubble up the stack or not
     */
    public function __construct($filename, $maxFiles = 0, $level = Logger::DEBUG, $bubble = true)
    {
        $this->filename = $filename;
        $this->maxFiles = (int) $maxFiles;
        $this->nextRotation = new \DateTime('tomorrow');
        $this->filenameFormat = '{filename}-{date}';
        $this->dateFormat = 'Y-m-d';

        parent::__construct($this->getTimedFilename(), $level, $bubble);
    }

    /**
     * {@inheritdoc}
     */
    public function close()
    {
        parent::close();

        if (true === $this->mustRotate) {
            $this->rotate();
        }
    }

    public function setFilenameFormat($filenameFormat, $dateFormat)
    {
        $this->filenameFormat = $filenameFormat;
        $this->dateFormat = $dateFormat;
    }

    /**
     * {@inheritdoc}
     */
    protected function write(array $record)
    {
        // on the first record written, if the log is new, we should rotate (once per day)
        if (null === $this->mustRotate) {
            $this->mustRotate = !file_exists($this->url);
        }

        if ($this->nextRotation < $record['datetime']) {
            $this->mustRotate = true;
            $this->close();
        }

        parent::write($record);
    }

    /**
     * Rotates the files.
     */
    protected function rotate()
    {
        // update filename
        $this->url = $this->getTimedFilename();
        $this->nextRotation = new \DateTime('tomorrow');

        // skip GC of old logs if files are unlimited
        if (0 === $this->maxFiles) {
            return;
        }

        $logFiles = glob($this->getGlobPattern());
        if ($this->maxFiles >= count($logFiles)) {
            // no files to remove
            return;
        }

        // Sorting the files by name to remove the older ones
        usort($logFiles, function($a, $b) {
            return strcmp($b, $a);
        });

        foreach (array_slice($logFiles, $this->maxFiles) as $file) {
            if (is_writable($file)) {
                unlink($file);
            }
        }
    }

    protected function getTimedFilename()
    {
        $fileInfo = pathinfo($this->filename);
        $timedFilename = str_replace(
            array('{filename}', '{date}'),
            array($fileInfo['filename'], date($this->dateFormat)),
            $fileInfo['dirname'] . '/' . $this->filenameFormat
        );

        if (!empty($fileInfo['extension'])) {
            $timedFilename .= '.'.$fileInfo['extension'];
        }

        return $timedFilename;
    }

    protected function getGlobPattern()
    {
        $fileInfo = pathinfo($this->filename);
        $glob = str_replace(
            array('{filename}', '{date}'),
            array($fileInfo['filename'], '*'),
            $fileInfo['dirname'] . '/' . $this->filenameFormat
        );
        if (!empty($fileInfo['extension'])) {
            $glob .= '.'.$fileInfo['extension'];
        }

        return $glob;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
use Monolog\Handler\FingersCrossed\ActivationStrategyInterface;
use Monolog\Logger;

/**
 * Buffers all records until a certain level is reached
 *
 * The advantage of this approach is that you don't get any clutter in your log files.
 * Only requests which actually trigger an error (or whatever your actionLevel is) will be
 * in the logs, but they will contain all records, not only those above the level threshold.
 *
 * You can find the various activation strategies in the
 * Monolog\Handler\FingersCrossed\ namespace.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class FingersCrossedHandler extends AbstractHandler
{
    protected $handler;
    protected $activationStrategy;
    protected $buffering = true;
    protected $bufferSize;
    protected $buffer = array();
    protected $stopBuffering;

    /**
     * @param callable|HandlerInterface       $handler            Handler or factory callable($record, $fingersCrossedHandler).
     * @param int|ActivationStrategyInterface $activationStrategy Strategy which determines when this handler takes action
     * @param int                             $bufferSize         How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
     * @param Boolean                         $bubble             Whether the messages that are handled can bubble up the stack or not
     * @param Boolean                         $stopBuffering      Whether the handler should stop buffering after being triggered (default true)
     */
    public function __construct($handler, $activationStrategy = null, $bufferSize = 0, $bubble = true, $stopBuffering = true)
    {
        if (null === $activationStrategy) {
            $activationStrategy = new ErrorLevelActivationStrategy(Logger::WARNING);
        }

        // convert simple int activationStrategy to an object
        if (!$activationStrategy instanceof ActivationStrategyInterface) {
            $activationStrategy = new ErrorLevelActivationStrategy($activationStrategy);
        }

        $this->handler = $handler;
        $this->activationStrategy = $activationStrategy;
        $this->bufferSize = $bufferSize;
        $this->bubble = $bubble;
        $this->stopBuffering = $stopBuffering;
    }

    /**
     * {@inheritdoc}
     */
    public function isHandling(array $record)
    {
        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function handle(array $record)
    {
        if ($this->processors) {
            foreach ($this->processors as $processor) {
                $record = call_user_func($processor, $record);
            }
        }

        if ($this->buffering) {
            $this->buffer[] = $record;
            if ($this->bufferSize > 0 && count($this->buffer) > $this->bufferSize) {
                array_shift($this->buffer);
            }
            if ($this->activationStrategy->isHandlerActivated($record)) {
                if ($this->stopBuffering) {
                    $this->buffering = false;
                }
                if (!$this->handler instanceof HandlerInterface) {
                    if (!is_callable($this->handler)) {
                        throw new \RuntimeException("The given handler (".json_encode($this->handler).") is not a callable nor a Monolog\Handler\HandlerInterface object");
                    }
                    $this->handler = call_user_func($this->handler, $record, $this);
                    if (!$this->handler instanceof HandlerInterface) {
                        throw new \RuntimeException("The factory callable should return a HandlerInterface");
                    }
                }
                $this->handler->handleBatch($this->buffer);
                $this->buffer = array();
            }
        } else {
            $this->handler->handle($record);
        }

        return false === $this->bubble;
    }

    /**
     * Resets the state of the handler. Stops forwarding records to the wrapped handler.
     */
    public function reset()
    {
        $this->buffering = true;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Formatter\NormalizerFormatter;
use Doctrine\CouchDB\CouchDBClient;

/**
 * CouchDB handler for Doctrine CouchDB ODM
 *
 * @author Markus Bachmann <markus.bachmann@bachi.biz>
 */
class DoctrineCouchDBHandler extends AbstractProcessingHandler
{
    private $client;

    public function __construct(CouchDBClient $client, $level = Logger::DEBUG, $bubble = true)
    {
        $this->client = $client;
        parent::__construct($level, $bubble);
    }

    /**
     * {@inheritDoc}
     */
    protected function write(array $record)
    {
        $this->client->postDocument($record['formatted']);
    }

    protected function getDefaultFormatter()
    {
        return new NormalizerFormatter;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler\FingersCrossed;

/**
 * Interface for activation strategies for the FingersCrossedHandler.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface ActivationStrategyInterface
{
    /**
     * Returns whether the given record activates the handler.
     *
     * @param  array   $record
     * @return Boolean
     */
    public function isHandlerActivated(array $record);
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler\FingersCrossed;

/**
 * Error level based activation strategy.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ErrorLevelActivationStrategy implements ActivationStrategyInterface
{
    private $actionLevel;

    public function __construct($actionLevel)
    {
        $this->actionLevel = $actionLevel;
    }

    public function isHandlerActivated(array $record)
    {
        return $record['level'] >= $this->actionLevel;
    }
}
<?php

/*
 * This file is part of the Monolog package.
*
* (c) Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Monolog\Handler\FingersCrossed;

/**
 * Channel and Error level based monolog activation strategy. Allows to trigger activation
 * based on level per channel. e.g. trigger activation on level 'ERROR' by default, except
 * for records of the 'sql' channel; those should trigger activation on level 'WARN'.
 *
 * Example:
 *
 * <code>
 *   $activationStrategy = new ChannelLevelActivationStrategy(
 *       Logger::CRITICAL,
 *       array(
 *           'request' => Logger::ALERT,
 *           'sensitive' => Logger::ERROR,
 *       )
 *   );
 *   $handler = new FingersCrossedHandler(new StreamHandler('php://stderr'), $activationStrategy);
 * </code>
 *
 * @author Mike Meessen <netmikey@gmail.com>
 */
class ChannelLevelActivationStrategy implements ActivationStrategyInterface
{
    private $defaultActionLevel;
    private $channelToActionLevel;

    /**
     * @param int   $defaultActionLevel    The default action level to be used if the record's category doesn't match any
     * @param array $categoryToActionLevel An array that maps channel names to action levels.
     */
    public function __construct($defaultActionLevel, $channelToActionLevel = array())
    {
        $this->defaultActionLevel = $defaultActionLevel;
        $this->channelToActionLevel = $channelToActionLevel;
    }

    public function isHandlerActivated(array $record)
    {
        if (isset($this->channelToActionLevel[$record['channel']])) {
            return $record['level'] >= $this->channelToActionLevel[$record['channel']];
        }

        return $record['level'] >= $this->defaultActionLevel;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Formatter\JsonFormatter;

class AmqpHandler extends AbstractProcessingHandler
{
    /**
     * @var \AMQPExchange $exchange
     */
    protected $exchange;

    /**
     * @param \AMQPExchange $exchange     AMQP exchange, ready for use
     * @param string        $exchangeName
     * @param int           $level
     * @param bool          $bubble       Whether the messages that are handled can bubble up the stack or not
     */
    public function __construct(\AMQPExchange $exchange, $exchangeName = 'log', $level = Logger::DEBUG, $bubble = true)
    {
        $this->exchange = $exchange;
        $this->exchange->setName($exchangeName);

        parent::__construct($level, $bubble);
    }

    /**
     * {@inheritDoc}
     */
    protected function write(array $record)
    {
        $data = $record["formatted"];

        $routingKey = sprintf(
            '%s.%s',
            substr($record['level_name'], 0, 4),
            $record['channel']
        );

        $this->exchange->publish(
            $data,
            strtolower($routingKey),
            0,
            array(
                'delivery_mode' => 2,
                'Content-type' => 'application/json'
            )
        );
    }

    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter()
    {
        return new JsonFormatter();
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

/**
 * Base Handler class providing the Handler structure
 *
 * Classes extending it should (in most cases) only implement write($record)
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Christophe Coevoet <stof@notk.org>
 */
abstract class AbstractProcessingHandler extends AbstractHandler
{
    /**
     * {@inheritdoc}
     */
    public function handle(array $record)
    {
        if (!$this->isHandling($record)) {
            return false;
        }

        $record = $this->processRecord($record);

        $record['formatted'] = $this->getFormatter()->format($record);

        $this->write($record);

        return false === $this->bubble;
    }

    /**
     * Writes the record down to the log of the implementing handler
     *
     * @param  array $record
     * @return void
     */
    abstract protected function write(array $record);

    /**
     * Processes a record.
     *
     * @param  array $record
     * @return array
     */
    protected function processRecord(array $record)
    {
        if ($this->processors) {
            foreach ($this->processors as $processor) {
                $record = call_user_func($processor, $record);
            }
        }

        return $record;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Logger;

/**
 * Stores to any socket - uses fsockopen() or pfsockopen().
 *
 * @author Pablo de Leon Belloc <pablolb@gmail.com>
 * @see    http://php.net/manual/en/function.fsockopen.php
 */
class SocketHandler extends AbstractProcessingHandler
{
    private $connectionString;
    private $connectionTimeout;
    private $resource;
    private $timeout = 0;
    private $persistent = false;
    private $errno;
    private $errstr;

    /**
     * @param string  $connectionString Socket connection string
     * @param integer $level            The minimum logging level at which this handler will be triggered
     * @param Boolean $bubble           Whether the messages that are handled can bubble up the stack or not
     */
    public function __construct($connectionString, $level = Logger::DEBUG, $bubble = true)
    {
        parent::__construct($level, $bubble);
        $this->connectionString = $connectionString;
        $this->connectionTimeout = (float) ini_get('default_socket_timeout');
    }

    /**
     * Connect (if necessary) and write to the socket
     *
     * @param array $record
     *
     * @throws \UnexpectedValueException
     * @throws \RuntimeException
     */
    public function write(array $record)
    {
        $this->connectIfNotConnected();
        $data = $this->generateDataStream($record);
        $this->writeToSocket($data);
    }

    /**
     * We will not close a PersistentSocket instance so it can be reused in other requests.
     */
    public function close()
    {
        if (!$this->isPersistent()) {
            $this->closeSocket();
        }
    }

    /**
     * Close socket, if open
     */
    public function closeSocket()
    {
        if (is_resource($this->resource)) {
            fclose($this->resource);
            $this->resource = null;
        }
    }

    /**
     * Set socket connection to nbe persistent. It only has effect before the connection is initiated.
     *
     * @param type $boolean
     */
    public function setPersistent($boolean)
    {
        $this->persistent = (boolean) $boolean;
    }

    /**
     * Set connection timeout.  Only has effect before we connect.
     *
     * @param float $seconds
     *
     * @see http://php.net/manual/en/function.fsockopen.php
     */
    public function setConnectionTimeout($seconds)
    {
        $this->validateTimeout($seconds);
        $this->connectionTimeout = (float) $seconds;
    }

    /**
     * Set write timeout. Only has effect before we connect.
     *
     * @param float $seconds
     *
     * @see http://php.net/manual/en/function.stream-set-timeout.php
     */
    public function setTimeout($seconds)
    {
        $this->validateTimeout($seconds);
        $this->timeout = (float) $seconds;
    }

    /**
     * Get current connection string
     *
     * @return string
     */
    public function getConnectionString()
    {
        return $this->connectionString;
    }

    /**
     * Get persistent setting
     *
     * @return boolean
     */
    public function isPersistent()
    {
        return $this->persistent;
    }

    /**
     * Get current connection timeout setting
     *
     * @return float
     */
    public function getConnectionTimeout()
    {
        return $this->connectionTimeout;
    }

    /**
     * Get current in-transfer timeout
     *
     * @return float
     */
    public function getTimeout()
    {
        return $this->timeout;
    }

    /**
     * Check to see if the socket is currently available.
     *
     * UDP might appear to be connected but might fail when writing.  See http://php.net/fsockopen for details.
     *
     * @return boolean
     */
    public function isConnected()
    {
        return is_resource($this->resource)
            && !feof($this->resource);  // on TCP - other party can close connection.
    }

    /**
     * Wrapper to allow mocking
     */
    protected function pfsockopen()
    {
        return @pfsockopen($this->connectionString, -1, $this->errno, $this->errstr, $this->connectionTimeout);
    }

    /**
     * Wrapper to allow mocking
     */
    protected function fsockopen()
    {
        return @fsockopen($this->connectionString, -1, $this->errno, $this->errstr, $this->connectionTimeout);
    }

    /**
     * Wrapper to allow mocking
     *
     * @see http://php.net/manual/en/function.stream-set-timeout.php
     */
    protected function streamSetTimeout()
    {
        $seconds = floor($this->timeout);
        $microseconds = round(($this->timeout - $seconds)*1e6);

        return stream_set_timeout($this->resource, $seconds, $microseconds);
    }

    /**
     * Wrapper to allow mocking
     */
    protected function fwrite($data)
    {
        return @fwrite($this->resource, $data);
    }

    /**
     * Wrapper to allow mocking
     */
    protected function streamGetMetadata()
    {
        return stream_get_meta_data($this->resource);
    }

    private function validateTimeout($value)
    {
        $ok = filter_var($value, FILTER_VALIDATE_FLOAT);
        if ($ok === false || $value < 0) {
            throw new \InvalidArgumentException("Timeout must be 0 or a positive float (got $value)");
        }
    }

    private function connectIfNotConnected()
    {
        if ($this->isConnected()) {
            return;
        }
        $this->connect();
    }

    protected function generateDataStream($record)
    {
        return (string) $record['formatted'];
    }

    private function connect()
    {
        $this->createSocketResource();
        $this->setSocketTimeout();
    }

    private function createSocketResource()
    {
        if ($this->isPersistent()) {
            $resource = $this->pfsockopen();
        } else {
            $resource = $this->fsockopen();
        }
        if (!$resource) {
            throw new \UnexpectedValueException("Failed connecting to $this->connectionString ($this->errno: $this->errstr)");
        }
        $this->resource = $resource;
    }

    private function setSocketTimeout()
    {
        if (!$this->streamSetTimeout()) {
            throw new \UnexpectedValueException("Failed setting timeout with stream_set_timeout()");
        }
    }

    private function writeToSocket($data)
    {
        $length = strlen($data);
        $sent = 0;
        while ($this->isConnected() && $sent < $length) {
            if (0 == $sent) {
                $chunk = $this->fwrite($data);
            } else {
                $chunk = $this->fwrite(substr($data, $sent));
            }
            if ($chunk === false) {
                throw new \RuntimeException("Could not write to socket");
            }
            $sent += $chunk;
            $socketInfo = $this->streamGetMetadata();
            if ($socketInfo['timed_out']) {
                throw new \RuntimeException("Write timed-out");
            }
        }
        if (!$this->isConnected() && $sent < $length) {
            throw new \RuntimeException("End-of-file reached, probably we got disconnected (sent $sent of $length)");
        }
    }

}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Logger;

/**
 * Logs to Cube.
 *
 * @link http://square.github.com/cube/
 * @author Wan Chen <kami@kamisama.me>
 */
class CubeHandler extends AbstractProcessingHandler
{
    private $udpConnection = null;
    private $httpConnection = null;
    private $scheme = null;
    private $host = null;
    private $port = null;
    private $acceptedSchemes = array('http', 'udp');

    /**
     * Create a Cube handler
     *
     * @throws UnexpectedValueException when given url is not a valid url.
     * A valid url must consists of three parts : protocol://host:port
     * Only valid protocol used by Cube are http and udp
     */
    public function __construct($url, $level = Logger::DEBUG, $bubble = true)
    {
        $urlInfos = parse_url($url);

        if (!isset($urlInfos['scheme']) || !isset($urlInfos['host']) || !isset($urlInfos['port'])) {
            throw new \UnexpectedValueException('URL "'.$url.'" is not valid');
        }

        if (!in_array($urlInfos['scheme'], $this->acceptedSchemes)) {
            throw new \UnexpectedValueException(
                'Invalid protocol (' . $urlInfos['scheme']  . ').'
                . ' Valid options are ' . implode(', ', $this->acceptedSchemes));
        }

        $this->scheme = $urlInfos['scheme'];
        $this->host = $urlInfos['host'];
        $this->port = $urlInfos['port'];

        parent::__construct($level, $bubble);
    }

    /**
     * Establish a connection to an UDP socket
     *
     * @throws LogicException when unable to connect to the socket
     */
    protected function connectUdp()
    {
        if (!extension_loaded('sockets')) {
            throw new MissingExtensionException('The sockets extension is required to use udp URLs with the CubeHandler');
        }

        $this->udpConnection = socket_create(AF_INET, SOCK_DGRAM, 0);
        if (!$this->udpConnection) {
            throw new \LogicException('Unable to create a socket');
        }

        if (!socket_connect($this->udpConnection, $this->host, $this->port)) {
            throw new \LogicException('Unable to connect to the socket at ' . $this->host . ':' . $this->port);
        }
    }

    /**
     * Establish a connection to a http server
     */
    protected function connectHttp()
    {
        if (!extension_loaded('curl')) {
            throw new \LogicException('The curl extension is needed to use http URLs with the CubeHandler');
        }

        $this->httpConnection = curl_init('http://'.$this->host.':'.$this->port.'/1.0/event/put');

        if (!$this->httpConnection) {
            throw new \LogicException('Unable to connect to ' . $this->host . ':' . $this->port);
        }

        curl_setopt($this->httpConnection, CURLOPT_CUSTOMREQUEST, "POST");
        curl_setopt($this->httpConnection, CURLOPT_RETURNTRANSFER, true);
    }

    /**
     * {@inheritdoc}
     */
    protected function write(array $record)
    {
        $date = $record['datetime'];

        $data = array('time' => $date->format('Y-m-d\TH:i:s.uO'));
        unset($record['datetime']);

        if (isset($record['context']['type'])) {
            $data['type'] = $record['context']['type'];
            unset($record['context']['type']);
        } else {
            $data['type'] = $record['channel'];
        }

        $data['data'] = $record['context'];
        $data['data']['level'] = $record['level'];

        $this->{'write'.$this->scheme}(json_encode($data));
    }

    private function writeUdp($data)
    {
        if (!$this->udpConnection) {
            $this->connectUdp();
        }

        socket_send($this->udpConnection, $data, strlen($data), 0);
    }

    private function writeHttp($data)
    {
        if (!$this->httpConnection) {
            $this->connectHttp();
        }

        curl_setopt($this->httpConnection, CURLOPT_POSTFIELDS, '['.$data.']');
        curl_setopt($this->httpConnection, CURLOPT_HTTPHEADER, array(
                'Content-Type: application/json',
                'Content-Length: ' . strlen('['.$data.']'))
        );

        return curl_exec($this->httpConnection);
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Logger;

/**
 * Stores to any stream resource
 *
 * Can be used to store into php://stderr, remote and local files, etc.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class StreamHandler extends AbstractProcessingHandler
{
    protected $stream;
    protected $url;
    private $errorMessage;

    /**
     * @param string  $stream
     * @param integer $level  The minimum logging level at which this handler will be triggered
     * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
     */
    public function __construct($stream, $level = Logger::DEBUG, $bubble = true)
    {
        parent::__construct($level, $bubble);
        if (is_resource($stream)) {
            $this->stream = $stream;
        } else {
            $this->url = $stream;
        }
    }

    /**
     * {@inheritdoc}
     */
    public function close()
    {
        if (is_resource($this->stream)) {
            fclose($this->stream);
        }
        $this->stream = null;
    }

    /**
     * {@inheritdoc}
     */
    protected function write(array $record)
    {
        if (null === $this->stream) {
            if (!$this->url) {
                throw new \LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().');
            }
            $this->errorMessage = null;
            set_error_handler(array($this, 'customErrorHandler'));
            $this->stream = fopen($this->url, 'a');
            restore_error_handler();
            if (!is_resource($this->stream)) {
                $this->stream = null;
                throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened: '.$this->errorMessage, $this->url));
            }
        }
        fwrite($this->stream, (string) $record['formatted']);
    }

    private function customErrorHandler($code, $msg) {
        $this->errorMessage = preg_replace('{^fopen\(.*?\): }', '', $msg);
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Logger;

/**
 * Logs to syslog service.
 *
 * usage example:
 *
 *   $log = new Logger('application');
 *   $syslog = new SyslogHandler('myfacility', 'local6');
 *   $formatter = new LineFormatter("%channel%.%level_name%: %message% %extra%");
 *   $syslog->setFormatter($formatter);
 *   $log->pushHandler($syslog);
 *
 * @author Sven Paulus <sven@karlsruhe.org>
 */
class SyslogHandler extends AbstractSyslogHandler
{
    protected $ident;
    protected $logopts;

    /**
     * @param string  $ident
     * @param mixed   $facility
     * @param integer $level    The minimum logging level at which this handler will be triggered
     * @param Boolean $bubble   Whether the messages that are handled can bubble up the stack or not
     * @param int     $logopts  Option flags for the openlog() call, defaults to LOG_PID
     */
    public function __construct($ident, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true, $logopts = LOG_PID)
    {
        parent::__construct($facility, $level, $bubble);

        $this->ident = $ident;
        $this->logopts = $logopts;
    }

    /**
     * {@inheritdoc}
     */
    public function close()
    {
        closelog();
    }

    /**
     * {@inheritdoc}
     */
    protected function write(array $record)
    {
        if (!openlog($this->ident, $this->logopts, $this->facility)) {
            throw new \LogicException('Can\'t open syslog for ident "'.$this->ident.'" and facility "'.$this->facility.'"');
        }
        syslog($this->logLevels[$record['level']], (string) $record['formatted']);
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Formatter\JsonFormatter;
use Monolog\Logger;

/**
 * CouchDB handler
 *
 * @author Markus Bachmann <markus.bachmann@bachi.biz>
 */
class CouchDBHandler extends AbstractProcessingHandler
{
    private $options;

    public function __construct(array $options = array(), $level = Logger::DEBUG, $bubble = true)
    {
        $this->options = array_merge(array(
            'host'     => 'localhost',
            'port'     => 5984,
            'dbname'   => 'logger',
            'username' => null,
            'password' => null,
        ), $options);

        parent::__construct($level, $bubble);
    }

    /**
     * {@inheritDoc}
     */
    protected function write(array $record)
    {
        $basicAuth = null;
        if ($this->options['username']) {
            $basicAuth = sprintf('%s:%s@', $this->options['username'], $this->options['password']);
        }

        $url = 'http://'.$basicAuth.$this->options['host'].':'.$this->options['port'].'/'.$this->options['dbname'];
        $context = stream_context_create(array(
            'http' => array(
                'method'        => 'POST',
                'content'       => $record['formatted'],
                'ignore_errors' => true,
                'max_redirects' => 0,
                'header'        => 'Content-type: application/json',
            )
        ));

        if (false === @file_get_contents($url, null, $context)) {
            throw new \RuntimeException(sprintf('Could not connect to %s', $url));
        }
    }

    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter()
    {
        return new JsonFormatter();
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Logger;

/**
 * Buffers all records until closing the handler and then pass them as batch.
 *
 * This is useful for a MailHandler to send only one mail per request instead of
 * sending one per log message.
 *
 * @author Christophe Coevoet <stof@notk.org>
 */
class BufferHandler extends AbstractHandler
{
    protected $handler;
    protected $bufferSize = 0;
    protected $bufferLimit;
    protected $flushOnOverflow;
    protected $buffer = array();

    /**
     * @param HandlerInterface $handler         Handler.
     * @param integer          $bufferLimit     How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
     * @param integer          $level           The minimum logging level at which this handler will be triggered
     * @param Boolean          $bubble          Whether the messages that are handled can bubble up the stack or not
     * @param Boolean          $flushOnOverflow If true, the buffer is flushed when the max size has been reached, by default oldest entries are discarded
     */
    public function __construct(HandlerInterface $handler, $bufferLimit = 0, $level = Logger::DEBUG, $bubble = true, $flushOnOverflow = false)
    {
        parent::__construct($level, $bubble);
        $this->handler = $handler;
        $this->bufferLimit = (int) $bufferLimit;
        $this->flushOnOverflow = $flushOnOverflow;

        // __destructor() doesn't get called on Fatal errors
        register_shutdown_function(array($this, 'close'));
    }

    /**
     * {@inheritdoc}
     */
    public function handle(array $record)
    {
        if ($record['level'] < $this->level) {
            return false;
        }

        if ($this->bufferLimit > 0 && $this->bufferSize === $this->bufferLimit) {
            if ($this->flushOnOverflow) {
                $this->flush();
            } else {
                array_shift($this->buffer);
                $this->bufferSize--;
            }
        }

        if ($this->processors) {
            foreach ($this->processors as $processor) {
                $record = call_user_func($processor, $record);
            }
        }

        $this->buffer[] = $record;
        $this->bufferSize++;

        return false === $this->bubble;
    }

    public function flush()
    {
        if ($this->bufferSize === 0) {
            return;
        }

        $this->handler->handleBatch($this->buffer);
        $this->bufferSize = 0;
        $this->buffer = array();
    }

    /**
     * {@inheritdoc}
     */
    public function close()
    {
        $this->flush();
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Logger;

/**
 * NativeMailerHandler uses the mail() function to send the emails
 *
 * @author Christophe Coevoet <stof@notk.org>
 */
class NativeMailerHandler extends MailHandler
{
    protected $to;
    protected $subject;
    protected $headers = array(
        'Content-type: text/plain; charset=utf-8'
    );
    protected $maxColumnWidth;

    /**
     * @param string|array $to             The receiver of the mail
     * @param string       $subject        The subject of the mail
     * @param string       $from           The sender of the mail
     * @param integer      $level          The minimum logging level at which this handler will be triggered
     * @param boolean      $bubble         Whether the messages that are handled can bubble up the stack or not
     * @param int          $maxColumnWidth The maximum column width that the message lines will have
     */
    public function __construct($to, $subject, $from, $level = Logger::ERROR, $bubble = true, $maxColumnWidth = 70)
    {
        parent::__construct($level, $bubble);
        $this->to = is_array($to) ? $to : array($to);
        $this->subject = $subject;
        $this->addHeader(sprintf('From: %s', $from));
        $this->maxColumnWidth = $maxColumnWidth;
    }

    /**
     * @param string|array $headers Custom added headers
     */
    public function addHeader($headers)
    {
        foreach ((array) $headers as $header) {
            if (strpos($header, "\n") !== false || strpos($header, "\r") !== false) {
                throw new \InvalidArgumentException('Headers can not contain newline characters for security reasons');
            }
            $this->headers[] = $header;
        }
    }

    /**
     * {@inheritdoc}
     */
    protected function send($content, array $records)
    {
        $content = wordwrap($content, $this->maxColumnWidth);
        $headers = implode("\r\n", $this->headers) . "\r\n";
        foreach ($this->to as $to) {
            mail($to, $this->subject, $content, $headers);
        }
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\ElasticaFormatter;
use Monolog\Logger;
use Elastica\Client;
use Elastica\Exception\ExceptionInterface;

/**
 * Elastic Search handler
 *
 * Usage example:
 *
 *    $client = new \Elastica\Client();
 *    $options = array(
 *        'index' => 'elastic_index_name',
 *        'type' => 'elastic_doc_type',
 *    );
 *    $handler = new ElasticSearchHandler($client, $options);
 *    $log = new Logger('application');
 *    $log->pushHandler($handler);
 *
 * @author Jelle Vink <jelle.vink@gmail.com>
 */
class ElasticSearchHandler extends AbstractProcessingHandler
{
    /**
     * @var Client
     */
    protected $client;

    /**
     * @var array Handler config options
     */
    protected $options = array();

    /**
     * @param Client  $client   Elastica Client object
     * @param array   $options  Handler configuration
     * @param integer $level    The minimum logging level at which this handler will be triggered
     * @param Boolean $bubble   Whether the messages that are handled can bubble up the stack or not
     */
    public function __construct(Client $client, array $options = array(), $level = Logger::DEBUG, $bubble = true)
    {
        parent::__construct($level, $bubble);
        $this->client = $client;
        $this->options = array_merge(
            array(
                'index'          => 'monolog',      // Elastic index name
                'type'           => 'record',       // Elastic document type
                'ignore_error'   => false,          // Suppress Elastica exceptions
            ),
            $options
        );
    }

    /**
     * {@inheritDoc}
     */
    protected function write(array $record)
    {
        $this->bulkSend(array($record['formatted']));
    }

    /**
     * {@inheritdoc}
     */
    public function setFormatter(FormatterInterface $formatter)
    {
        if ($formatter instanceof ElasticaFormatter) {
            return parent::setFormatter($formatter);
        }
        throw new \InvalidArgumentException('ElasticSearchHandler is only compatible with ElasticaFormatter');
    }

    /**
     * Getter options
     * @return array
     */
    public function getOptions()
    {
        return $this->options;
    }

    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter()
    {
        return new ElasticaFormatter($this->options['index'], $this->options['type']);
    }

    /**
     * {@inheritdoc}
     */
    public function handleBatch(array $records)
    {
        $documents = $this->getFormatter()->formatBatch($records);
        $this->bulkSend($documents);
    }

    /**
     * Use Elasticsearch bulk API to send list of documents
     * @param array $documents
     * @throws \RuntimeException
     */
    protected function bulkSend(array $documents)
    {
        try {
            $this->client->addDocuments($documents);
        } catch (ExceptionInterface $e) {
            if (!$this->options['ignore_error']) {
                throw new \RuntimeException("Error sending messages to Elasticsearch", 0, $e);
            }
        }
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Logger;

/**
 * SwiftMailerHandler uses Swift_Mailer to send the emails
 *
 * @author Gyula Sallai
 */
class SwiftMailerHandler extends MailHandler
{
    protected $mailer;
    protected $message;

    /**
     * @param \Swift_Mailer           $mailer  The mailer to use
     * @param callable|\Swift_Message $message An example message for real messages, only the body will be replaced
     * @param integer                 $level   The minimum logging level at which this handler will be triggered
     * @param Boolean                 $bubble  Whether the messages that are handled can bubble up the stack or not
     */
    public function __construct(\Swift_Mailer $mailer, $message, $level = Logger::ERROR, $bubble = true)
    {
        parent::__construct($level, $bubble);
        $this->mailer  = $mailer;
        if (!$message instanceof \Swift_Message && is_callable($message)) {
            $message = call_user_func($message);
        }
        if (!$message instanceof \Swift_Message) {
            throw new \InvalidArgumentException('You must provide either a Swift_Message instance or a callable returning it');
        }
        $this->message = $message;
    }

    /**
     * {@inheritdoc}
     */
    protected function send($content, array $records)
    {
        $message = clone $this->message;
        $message->setBody($content);

        $this->mailer->send($message);
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

/**
 * Exception can be thrown if an extension for an handler is missing
 *
 * @author  Christian Bergau <cbergau86@gmail.com>
 */
class MissingExtensionException extends \Exception
{

}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Formatter\WildfireFormatter;

/**
 * Simple FirePHP Handler (http://www.firephp.org/), which uses the Wildfire protocol.
 *
 * @author Eric Clemmons (@ericclemmons) <eric@uxdriven.com>
 */
class FirePHPHandler extends AbstractProcessingHandler
{
    /**
     * WildFire JSON header message format
     */
    const PROTOCOL_URI = 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2';

    /**
     * FirePHP structure for parsing messages & their presentation
     */
    const STRUCTURE_URI = 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1';

    /**
     * Must reference a "known" plugin, otherwise headers won't display in FirePHP
     */
    const PLUGIN_URI = 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3';

    /**
     * Header prefix for Wildfire to recognize & parse headers
     */
    const HEADER_PREFIX = 'X-Wf';

    /**
     * Whether or not Wildfire vendor-specific headers have been generated & sent yet
     */
    protected static $initialized = false;

    /**
     * Shared static message index between potentially multiple handlers
     * @var int
     */
    protected static $messageIndex = 1;

    protected static $sendHeaders = true;

    /**
     * Base header creation function used by init headers & record headers
     *
     * @param  array  $meta    Wildfire Plugin, Protocol & Structure Indexes
     * @param  string $message Log message
     * @return array  Complete header string ready for the client as key and message as value
     */
    protected function createHeader(array $meta, $message)
    {
        $header = sprintf('%s-%s', self::HEADER_PREFIX, join('-', $meta));

        return array($header => $message);
    }

    /**
     * Creates message header from record
     *
     * @see createHeader()
     * @param  array  $record
     * @return string
     */
    protected function createRecordHeader(array $record)
    {
        // Wildfire is extensible to support multiple protocols & plugins in a single request,
        // but we're not taking advantage of that (yet), so we're using "1" for simplicity's sake.
        return $this->createHeader(
            array(1, 1, 1, self::$messageIndex++),
            $record['formatted']
        );
    }

    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter()
    {
        return new WildfireFormatter();
    }

    /**
     * Wildfire initialization headers to enable message parsing
     *
     * @see createHeader()
     * @see sendHeader()
     * @return array
     */
    protected function getInitHeaders()
    {
        // Initial payload consists of required headers for Wildfire
        return array_merge(
            $this->createHeader(array('Protocol', 1), self::PROTOCOL_URI),
            $this->createHeader(array(1, 'Structure', 1), self::STRUCTURE_URI),
            $this->createHeader(array(1, 'Plugin', 1), self::PLUGIN_URI)
        );
    }

    /**
     * Send header string to the client
     *
     * @param string $header
     * @param string $content
     */
    protected function sendHeader($header, $content)
    {
        if (!headers_sent() && self::$sendHeaders) {
            header(sprintf('%s: %s', $header, $content));
        }
    }

    /**
     * Creates & sends header for a record, ensuring init headers have been sent prior
     *
     * @see sendHeader()
     * @see sendInitHeaders()
     * @param array $record
     */
    protected function write(array $record)
    {
        // WildFire-specific headers must be sent prior to any messages
        if (!self::$initialized) {
            self::$sendHeaders = $this->headersAccepted();

            foreach ($this->getInitHeaders() as $header => $content) {
                $this->sendHeader($header, $content);
            }

            self::$initialized = true;
        }

        $header = $this->createRecordHeader($record);
        $this->sendHeader(key($header), current($header));
    }

    /**
     * Verifies if the headers are accepted by the current user agent
     *
     * @return Boolean
     */
    protected function headersAccepted()
    {
        return !isset($_SERVER['HTTP_USER_AGENT'])
               || preg_match('{\bFirePHP/\d+\.\d+\b}', $_SERVER['HTTP_USER_AGENT'])
               || isset($_SERVER['HTTP_X_FIREPHP_VERSION']);
    }

    /**
     * BC getter for the sendHeaders property that has been made static
     */
    public function __get($property)
    {
        if ('sendHeaders' !== $property) {
            throw new \InvalidArgumentException('Undefined property '.$property);
        }

        return static::$sendHeaders;
    }

    /**
     * BC setter for the sendHeaders property that has been made static
     */
    public function __set($property, $value)
    {
        if ('sendHeaders' !== $property) {
            throw new \InvalidArgumentException('Undefined property '.$property);
        }

        static::$sendHeaders = $value;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

/**
 * Forwards records to multiple handlers
 *
 * @author Lenar Lõhmus <lenar@city.ee>
 */
class GroupHandler extends AbstractHandler
{
    protected $handlers;

    /**
     * @param array   $handlers Array of Handlers.
     * @param Boolean $bubble   Whether the messages that are handled can bubble up the stack or not
     */
    public function __construct(array $handlers, $bubble = true)
    {
        foreach ($handlers as $handler) {
            if (!$handler instanceof HandlerInterface) {
                throw new \InvalidArgumentException('The first argument of the GroupHandler must be an array of HandlerInterface instances.');
            }
        }

        $this->handlers = $handlers;
        $this->bubble = $bubble;
    }

    /**
     * {@inheritdoc}
     */
    public function isHandling(array $record)
    {
        foreach ($this->handlers as $handler) {
            if ($handler->isHandling($record)) {
                return true;
            }
        }

        return false;
    }

    /**
     * {@inheritdoc}
     */
    public function handle(array $record)
    {
        if ($this->processors) {
            foreach ($this->processors as $processor) {
                $record = call_user_func($processor, $record);
            }
        }

        foreach ($this->handlers as $handler) {
            $handler->handle($record);
        }

        return false === $this->bubble;
    }

    /**
     * {@inheritdoc}
     */
    public function handleBatch(array $records)
    {
        foreach ($this->handlers as $handler) {
            $handler->handleBatch($records);
        }
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Gelf\IMessagePublisher;
use Monolog\Logger;
use Monolog\Handler\AbstractProcessingHandler;
use Monolog\Formatter\GelfMessageFormatter;

/**
 * Handler to send messages to a Graylog2 (http://www.graylog2.org) server
 *
 * @author Matt Lehner <mlehner@gmail.com>
 */
class GelfHandler extends AbstractProcessingHandler
{
    /**
     * @var Gelf\IMessagePublisher the publisher object that sends the message to the server
     */
    protected $publisher;

    /**
     * @param Gelf\IMessagePublisher $publisher a publisher object
     * @param integer                $level     The minimum logging level at which this handler will be triggered
     * @param Boolean                $bubble    Whether the messages that are handled can bubble up the stack or not
     */
    public function __construct(IMessagePublisher $publisher, $level = Logger::DEBUG, $bubble = true)
    {
        parent::__construct($level, $bubble);

        $this->publisher = $publisher;
    }

    /**
     * {@inheritdoc}
     */
    public function close()
    {
        $this->publisher = null;
    }

    /**
     * {@inheritdoc}
     */
    protected function write(array $record)
    {
        $this->publisher->publish($record['formatted']);
    }

    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter()
    {
        return new GelfMessageFormatter();
    }
}
Copyright (c) Jordi Boggiano

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog;

class TestCase extends \PHPUnit_Framework_TestCase
{
    /**
     * @return array Record
     */
    protected function getRecord($level = Logger::WARNING, $message = 'test', $context = array())
    {
        return array(
            'message' => $message,
            'context' => $context,
            'level' => $level,
            'level_name' => Logger::getLevelName($level),
            'channel' => 'test',
            'datetime' => \DateTime::createFromFormat('U.u', sprintf('%.6F', microtime(true))),
            'extra' => array(),
        );
    }

    /**
     * @return array
     */
    protected function getMultipleRecords()
    {
        return array(
            $this->getRecord(Logger::DEBUG, 'debug message 1'),
            $this->getRecord(Logger::DEBUG, 'debug message 2'),
            $this->getRecord(Logger::INFO, 'information'),
            $this->getRecord(Logger::WARNING, 'warning'),
            $this->getRecord(Logger::ERROR, 'error')
        );
    }

    /**
     * @return Monolog\Formatter\FormatterInterface
     */
    protected function getIdentityFormatter()
    {
        $formatter = $this->getMock('Monolog\\Formatter\\FormatterInterface');
        $formatter->expects($this->any())
            ->method('format')
            ->will($this->returnCallback(function($record) { return $record['message']; }));

        return $formatter;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog;

use Monolog\Handler\TestHandler;

class ErrorHandlerTest extends \PHPUnit_Framework_TestCase
{
    public function testHandleError()
    {
        $logger = new Logger('test', array($handler = new TestHandler));
        $errHandler = new ErrorHandler($logger);

        $errHandler->registerErrorHandler(array(E_USER_NOTICE => Logger::EMERGENCY), false);
        trigger_error('Foo', E_USER_ERROR);
        $this->assertCount(1, $handler->getRecords());
        $this->assertTrue($handler->hasErrorRecords());
        trigger_error('Foo', E_USER_NOTICE);
        $this->assertCount(2, $handler->getRecords());
        $this->assertTrue($handler->hasEmergencyRecords());
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog;

use Monolog\Handler\TestHandler;
use Monolog\Formatter\LineFormatter;
use Monolog\Processor\PsrLogMessageProcessor;
use Psr\Log\Test\LoggerInterfaceTest;

class PsrLogCompatTest extends LoggerInterfaceTest
{
    private $handler;

    public function getLogger()
    {
        $logger = new Logger('foo');
        $logger->pushHandler($handler = new TestHandler);
        $logger->pushProcessor(new PsrLogMessageProcessor);
        $handler->setFormatter(new LineFormatter('%level_name% %message%'));

        $this->handler = $handler;

        return $logger;
    }

    public function getLogs()
    {
        $convert = function ($record) {
            $lower = function ($match) {
                return strtolower($match[0]);
            };

            return preg_replace_callback('{^[A-Z]+}', $lower, $record['formatted']);
        };

        return array_map($convert, $this->handler->getRecords());
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog;

use Monolog\Processor\WebProcessor;
use Monolog\Handler\TestHandler;

class LoggerTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Monolog\Logger::getName
     */
    public function testGetName()
    {
        $logger = new Logger('foo');
        $this->assertEquals('foo', $logger->getName());
    }

    /**
     * @covers Monolog\Logger::getLevelName
     */
    public function testGetLevelName()
    {
        $this->assertEquals('ERROR', Logger::getLevelName(Logger::ERROR));
    }

    /**
     * @covers Monolog\Logger::getLevelName
     * @expectedException InvalidArgumentException
     */
    public function testGetLevelNameThrows()
    {
        Logger::getLevelName(5);
    }

    /**
     * @covers Monolog\Logger::__construct
     */
    public function testChannel()
    {
        $logger = new Logger('foo');
        $handler = new TestHandler;
        $logger->pushHandler($handler);
        $logger->addWarning('test');
        list($record) = $handler->getRecords();
        $this->assertEquals('foo', $record['channel']);
    }

    /**
     * @covers Monolog\Logger::addRecord
     */
    public function testLog()
    {
        $logger = new Logger(__METHOD__);

        $handler = $this->getMock('Monolog\Handler\NullHandler', array('handle'));
        $handler->expects($this->once())
            ->method('handle');
        $logger->pushHandler($handler);

        $this->assertTrue($logger->addWarning('test'));
    }

    /**
     * @covers Monolog\Logger::addRecord
     */
    public function testLogNotHandled()
    {
        $logger = new Logger(__METHOD__);

        $handler = $this->getMock('Monolog\Handler\NullHandler', array('handle'), array(Logger::ERROR));
        $handler->expects($this->never())
            ->method('handle');
        $logger->pushHandler($handler);

        $this->assertFalse($logger->addWarning('test'));
    }

    public function testHandlersInCtor()
    {
        $handler1 = new TestHandler;
        $handler2 = new TestHandler;
        $logger = new Logger(__METHOD__, array($handler1, $handler2));

        $this->assertEquals($handler1, $logger->popHandler());
        $this->assertEquals($handler2, $logger->popHandler());
    }

    public function testProcessorsInCtor()
    {
        $processor1 = new WebProcessor;
        $processor2 = new WebProcessor;
        $logger = new Logger(__METHOD__, array(), array($processor1, $processor2));

        $this->assertEquals($processor1, $logger->popProcessor());
        $this->assertEquals($processor2, $logger->popProcessor());
    }

    /**
     * @covers Monolog\Logger::pushHandler
     * @covers Monolog\Logger::popHandler
     * @expectedException LogicException
     */
    public function testPushPopHandler()
    {
        $logger = new Logger(__METHOD__);
        $handler1 = new TestHandler;
        $handler2 = new TestHandler;

        $logger->pushHandler($handler1);
        $logger->pushHandler($handler2);

        $this->assertEquals($handler2, $logger->popHandler());
        $this->assertEquals($handler1, $logger->popHandler());
        $logger->popHandler();
    }

    /**
     * @covers Monolog\Logger::pushProcessor
     * @covers Monolog\Logger::popProcessor
     * @expectedException LogicException
     */
    public function testPushPopProcessor()
    {
        $logger = new Logger(__METHOD__);
        $processor1 = new WebProcessor;
        $processor2 = new WebProcessor;

        $logger->pushProcessor($processor1);
        $logger->pushProcessor($processor2);

        $this->assertEquals($processor2, $logger->popProcessor());
        $this->assertEquals($processor1, $logger->popProcessor());
        $logger->popProcessor();
    }

    /**
     * @covers Monolog\Logger::pushProcessor
     * @expectedException InvalidArgumentException
     */
    public function testPushProcessorWithNonCallable()
    {
        $logger = new Logger(__METHOD__);

        $logger->pushProcessor(new \stdClass());
    }

    /**
     * @covers Monolog\Logger::addRecord
     */
    public function testProcessorsAreExecuted()
    {
        $logger = new Logger(__METHOD__);
        $handler = new TestHandler;
        $logger->pushHandler($handler);
        $logger->pushProcessor(function($record) {
            $record['extra']['win'] = true;

            return $record;
        });
        $logger->addError('test');
        list($record) = $handler->getRecords();
        $this->assertTrue($record['extra']['win']);
    }

    /**
     * @covers Monolog\Logger::addRecord
     */
    public function testProcessorsAreCalledOnlyOnce()
    {
        $logger = new Logger(__METHOD__);
        $handler = $this->getMock('Monolog\Handler\HandlerInterface');
        $handler->expects($this->any())
            ->method('isHandling')
            ->will($this->returnValue(true))
        ;
        $handler->expects($this->any())
            ->method('handle')
            ->will($this->returnValue(true))
        ;
        $logger->pushHandler($handler);

        $processor = $this->getMockBuilder('Monolog\Processor\WebProcessor')
            ->disableOriginalConstructor()
            ->setMethods(array('__invoke'))
            ->getMock()
        ;
        $processor->expects($this->once())
            ->method('__invoke')
            ->will($this->returnArgument(0))
        ;
        $logger->pushProcessor($processor);

        $logger->addError('test');
    }

    /**
     * @covers Monolog\Logger::addRecord
     */
    public function testProcessorsNotCalledWhenNotHandled()
    {
        $logger = new Logger(__METHOD__);
        $handler = $this->getMock('Monolog\Handler\HandlerInterface');
        $handler->expects($this->once())
            ->method('isHandling')
            ->will($this->returnValue(false))
        ;
        $logger->pushHandler($handler);
        $that = $this;
        $logger->pushProcessor(function($record) use ($that) {
            $that->fail('The processor should not be called');
        });
        $logger->addAlert('test');
    }

    /**
     * @covers Monolog\Logger::addRecord
     */
    public function testHandlersNotCalledBeforeFirstHandling()
    {
        $logger = new Logger(__METHOD__);

        $handler1 = $this->getMock('Monolog\Handler\HandlerInterface');
        $handler1->expects($this->never())
            ->method('isHandling')
            ->will($this->returnValue(false))
        ;
        $handler1->expects($this->once())
            ->method('handle')
            ->will($this->returnValue(false))
        ;
        $logger->pushHandler($handler1);

        $handler2 = $this->getMock('Monolog\Handler\HandlerInterface');
        $handler2->expects($this->once())
            ->method('isHandling')
            ->will($this->returnValue(true))
        ;
        $handler2->expects($this->once())
            ->method('handle')
            ->will($this->returnValue(false))
        ;
        $logger->pushHandler($handler2);

        $handler3 = $this->getMock('Monolog\Handler\HandlerInterface');
        $handler3->expects($this->once())
            ->method('isHandling')
            ->will($this->returnValue(false))
        ;
        $handler3->expects($this->never())
            ->method('handle')
        ;
        $logger->pushHandler($handler3);

        $logger->debug('test');
    }

    /**
     * @covers Monolog\Logger::addRecord
     */
    public function testBubblingWhenTheHandlerReturnsFalse()
    {
        $logger = new Logger(__METHOD__);

        $handler1 = $this->getMock('Monolog\Handler\HandlerInterface');
        $handler1->expects($this->any())
            ->method('isHandling')
            ->will($this->returnValue(true))
        ;
        $handler1->expects($this->once())
            ->method('handle')
            ->will($this->returnValue(false))
        ;
        $logger->pushHandler($handler1);

        $handler2 = $this->getMock('Monolog\Handler\HandlerInterface');
        $handler2->expects($this->any())
            ->method('isHandling')
            ->will($this->returnValue(true))
        ;
        $handler2->expects($this->once())
            ->method('handle')
            ->will($this->returnValue(false))
        ;
        $logger->pushHandler($handler2);

        $logger->debug('test');
    }

    /**
     * @covers Monolog\Logger::addRecord
     */
    public function testNotBubblingWhenTheHandlerReturnsTrue()
    {
        $logger = new Logger(__METHOD__);

        $handler1 = $this->getMock('Monolog\Handler\HandlerInterface');
        $handler1->expects($this->any())
            ->method('isHandling')
            ->will($this->returnValue(true))
        ;
        $handler1->expects($this->never())
            ->method('handle')
        ;
        $logger->pushHandler($handler1);

        $handler2 = $this->getMock('Monolog\Handler\HandlerInterface');
        $handler2->expects($this->any())
            ->method('isHandling')
            ->will($this->returnValue(true))
        ;
        $handler2->expects($this->once())
            ->method('handle')
            ->will($this->returnValue(true))
        ;
        $logger->pushHandler($handler2);

        $logger->debug('test');
    }

    /**
     * @covers Monolog\Logger::isHandling
     */
    public function testIsHandling()
    {
        $logger = new Logger(__METHOD__);

        $handler1 = $this->getMock('Monolog\Handler\HandlerInterface');
        $handler1->expects($this->any())
            ->method('isHandling')
            ->will($this->returnValue(false))
        ;

        $logger->pushHandler($handler1);
        $this->assertFalse($logger->isHandling(Logger::DEBUG));

        $handler2 = $this->getMock('Monolog\Handler\HandlerInterface');
        $handler2->expects($this->any())
            ->method('isHandling')
            ->will($this->returnValue(true))
        ;

        $logger->pushHandler($handler2);
        $this->assertTrue($logger->isHandling(Logger::DEBUG));
    }

    /**
     * @dataProvider logMethodProvider
     * @covers Monolog\Logger::addDebug
     * @covers Monolog\Logger::addInfo
     * @covers Monolog\Logger::addNotice
     * @covers Monolog\Logger::addWarning
     * @covers Monolog\Logger::addError
     * @covers Monolog\Logger::addCritical
     * @covers Monolog\Logger::addAlert
     * @covers Monolog\Logger::addEmergency
     * @covers Monolog\Logger::debug
     * @covers Monolog\Logger::info
     * @covers Monolog\Logger::notice
     * @covers Monolog\Logger::warn
     * @covers Monolog\Logger::err
     * @covers Monolog\Logger::crit
     * @covers Monolog\Logger::alert
     * @covers Monolog\Logger::emerg
     */
    public function testLogMethods($method, $expectedLevel)
    {
        $logger = new Logger('foo');
        $handler = new TestHandler;
        $logger->pushHandler($handler);
        $logger->{$method}('test');
        list($record) = $handler->getRecords();
        $this->assertEquals($expectedLevel, $record['level']);
    }

    public function logMethodProvider()
    {
        return array(
            // monolog methods
            array('addDebug',     Logger::DEBUG),
            array('addInfo',      Logger::INFO),
            array('addNotice',    Logger::NOTICE),
            array('addWarning',   Logger::WARNING),
            array('addError',     Logger::ERROR),
            array('addCritical',  Logger::CRITICAL),
            array('addAlert',     Logger::ALERT),
            array('addEmergency', Logger::EMERGENCY),

            // ZF/Sf2 compat methods
            array('debug',  Logger::DEBUG),
            array('info',   Logger::INFO),
            array('notice', Logger::NOTICE),
            array('warn',   Logger::WARNING),
            array('err',    Logger::ERROR),
            array('crit',   Logger::CRITICAL),
            array('alert',  Logger::ALERT),
            array('emerg',  Logger::EMERGENCY),
        );
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Processor;

use Monolog\TestCase;

class ProcessIdProcessorTest extends TestCase
{
    /**
     * @covers Monolog\Processor\ProcessIdProcessor::__invoke
     */
    public function testProcessor()
    {
        $processor = new ProcessIdProcessor();
        $record = $processor($this->getRecord());
        $this->assertArrayHasKey('process_id', $record['extra']);
        $this->assertInternalType('int', $record['extra']['process_id']);
        $this->assertGreaterThan(0, $record['extra']['process_id']);
        $this->assertEquals(getmypid(), $record['extra']['process_id']);
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Processor;

use Monolog\TestCase;

class WebProcessorTest extends TestCase
{
    public function testProcessor()
    {
        $server = array(
            'REQUEST_URI'    => 'A',
            'REMOTE_ADDR'    => 'B',
            'REQUEST_METHOD' => 'C',
            'HTTP_REFERER'   => 'D',
            'SERVER_NAME'    => 'F',
            'UNIQUE_ID'      => 'G',
        );

        $processor = new WebProcessor($server);
        $record = $processor($this->getRecord());
        $this->assertEquals($server['REQUEST_URI'], $record['extra']['url']);
        $this->assertEquals($server['REMOTE_ADDR'], $record['extra']['ip']);
        $this->assertEquals($server['REQUEST_METHOD'], $record['extra']['http_method']);
        $this->assertEquals($server['HTTP_REFERER'], $record['extra']['referrer']);
        $this->assertEquals($server['SERVER_NAME'], $record['extra']['server']);
        $this->assertEquals($server['UNIQUE_ID'], $record['extra']['unique_id']);
    }

    public function testProcessorDoNothingIfNoRequestUri()
    {
        $server = array(
            'REMOTE_ADDR'    => 'B',
            'REQUEST_METHOD' => 'C',
        );
        $processor = new WebProcessor($server);
        $record = $processor($this->getRecord());
        $this->assertEmpty($record['extra']);
    }

    public function testProcessorReturnNullIfNoHttpReferer()
    {
        $server = array(
            'REQUEST_URI'    => 'A',
            'REMOTE_ADDR'    => 'B',
            'REQUEST_METHOD' => 'C',
            'SERVER_NAME'    => 'F',
        );
        $processor = new WebProcessor($server);
        $record = $processor($this->getRecord());
        $this->assertNull($record['extra']['referrer']);
    }

    public function testProcessorDoesNotAddUniqueIdIfNotPresent()
    {
        $server = array(
            'REQUEST_URI'    => 'A',
            'REMOTE_ADDR'    => 'B',
            'REQUEST_METHOD' => 'C',
            'SERVER_NAME'    => 'F',
        );
        $processor = new WebProcessor($server);
        $record = $processor($this->getRecord());
        $this->assertFalse(isset($record['extra']['unique_id']));
    }

    /**
     * @expectedException UnexpectedValueException
     */
    public function testInvalidData()
    {
        new WebProcessor(new \stdClass);
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Processor;

use Monolog\TestCase;

class UidProcessorTest extends TestCase
{
    /**
     * @covers Monolog\Processor\UidProcessor::__invoke
     */
    public function testProcessor()
    {
        $processor = new UidProcessor();
        $record = $processor($this->getRecord());
        $this->assertArrayHasKey('uid', $record['extra']);
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Processor;

use Monolog\TestCase;

class MemoryUsageProcessorTest extends TestCase
{
    /**
     * @covers Monolog\Processor\MemoryUsageProcessor::__invoke
     * @covers Monolog\Processor\MemoryProcessor::formatBytes
     */
    public function testProcessor()
    {
        $processor = new MemoryUsageProcessor();
        $record = $processor($this->getRecord());
        $this->assertArrayHasKey('memory_usage', $record['extra']);
        $this->assertRegExp('#[0-9.]+ (M|K)?B$#', $record['extra']['memory_usage']);
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Processor;

use Monolog\TestCase;

class MemoryPeakUsageProcessorTest extends TestCase
{
    /**
     * @covers Monolog\Processor\MemoryPeakUsageProcessor::__invoke
     * @covers Monolog\Processor\MemoryProcessor::formatBytes
     */
    public function testProcessor()
    {
        $processor = new MemoryPeakUsageProcessor();
        $record = $processor($this->getRecord());
        $this->assertArrayHasKey('memory_peak_usage', $record['extra']);
        $this->assertRegExp('#[0-9.]+ (M|K)?B$#', $record['extra']['memory_peak_usage']);
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Acme;

class Tester
{
    public function test($handler, $record)
    {
        $handler->handle($record);
    }
}

function tester($handler, $record)
{
    $handler->handle($record);
}

namespace Monolog\Processor;

use Monolog\Logger;
use Monolog\TestCase;
use Monolog\Handler\TestHandler;

class IntrospectionProcessorTest extends TestCase
{
    public function getHandler()
    {
        $processor = new IntrospectionProcessor();
        $handler = new TestHandler();
        $handler->pushProcessor($processor);

        return $handler;
    }

    public function testProcessorFromClass()
    {
        $handler = $this->getHandler();
        $tester = new \Acme\Tester;
        $tester->test($handler, $this->getRecord());
        list($record) = $handler->getRecords();
        $this->assertEquals(__FILE__, $record['extra']['file']);
        $this->assertEquals(18, $record['extra']['line']);
        $this->assertEquals('Acme\Tester', $record['extra']['class']);
        $this->assertEquals('test', $record['extra']['function']);
    }

    public function testProcessorFromFunc()
    {
        $handler = $this->getHandler();
        \Acme\tester($handler, $this->getRecord());
        list($record) = $handler->getRecords();
        $this->assertEquals(__FILE__, $record['extra']['file']);
        $this->assertEquals(24, $record['extra']['line']);
        $this->assertEquals(null, $record['extra']['class']);
        $this->assertEquals('Acme\tester', $record['extra']['function']);
    }

    public function testLevelTooLow()
    {
        $input = array(
            'level' => Logger::DEBUG,
            'extra' => array(),
        );

        $expected = $input;

        $processor = new IntrospectionProcessor(Logger::CRITICAL);
        $actual = $processor($input);

        $this->assertEquals($expected, $actual);
    }

    public function testLevelEqual()
    {
        $input = array(
            'level' => Logger::CRITICAL,
            'extra' => array(),
        );

        $expected = $input;
        $expected['extra'] = array(
            'file' => null,
            'line' => null,
            'class' => 'ReflectionMethod',
            'function' => 'invokeArgs',
        );

        $processor = new IntrospectionProcessor(Logger::CRITICAL);
        $actual = $processor($input);

        $this->assertEquals($expected, $actual);
    }

    public function testLevelHigher()
    {
        $input = array(
            'level' => Logger::EMERGENCY,
            'extra' => array(),
        );

        $expected = $input;
        $expected['extra'] = array(
            'file' => null,
            'line' => null,
            'class' => 'ReflectionMethod',
            'function' => 'invokeArgs',
        );

        $processor = new IntrospectionProcessor(Logger::CRITICAL);
        $actual = $processor($input);

        $this->assertEquals($expected, $actual);
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Formatter;

/**
 * @covers Monolog\Formatter\LineFormatter
 */
class LineFormatterTest extends \PHPUnit_Framework_TestCase
{
    public function testDefFormatWithString()
    {
        $formatter = new LineFormatter(null, 'Y-m-d');
        $message = $formatter->format(array(
            'level_name' => 'WARNING',
            'channel' => 'log',
            'context' => array(),
            'message' => 'foo',
            'datetime' => new \DateTime,
            'extra' => array(),
        ));
        $this->assertEquals('['.date('Y-m-d').'] log.WARNING: foo [] []'."\n", $message);
    }

    public function testDefFormatWithArrayContext()
    {
        $formatter = new LineFormatter(null, 'Y-m-d');
        $message = $formatter->format(array(
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'message' => 'foo',
            'datetime' => new \DateTime,
            'extra' => array(),
            'context' => array(
                'foo' => 'bar',
                'baz' => 'qux',
            )
        ));
        $this->assertEquals('['.date('Y-m-d').'] meh.ERROR: foo {"foo":"bar","baz":"qux"} []'."\n", $message);
    }

    public function testDefFormatExtras()
    {
        $formatter = new LineFormatter(null, 'Y-m-d');
        $message = $formatter->format(array(
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'context' => array(),
            'datetime' => new \DateTime,
            'extra' => array('ip' => '127.0.0.1'),
            'message' => 'log',
        ));
        $this->assertEquals('['.date('Y-m-d').'] meh.ERROR: log [] {"ip":"127.0.0.1"}'."\n", $message);
    }

    public function testFormatExtras()
    {
        $formatter = new LineFormatter("[%datetime%] %channel%.%level_name%: %message% %context% %extra.file% %extra%\n", 'Y-m-d');
        $message = $formatter->format(array(
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'context' => array(),
            'datetime' => new \DateTime,
            'extra' => array('ip' => '127.0.0.1', 'file' => 'test'),
            'message' => 'log',
        ));
        $this->assertEquals('['.date('Y-m-d').'] meh.ERROR: log [] test {"ip":"127.0.0.1"}'."\n", $message);
    }

    public function testDefFormatWithObject()
    {
        $formatter = new LineFormatter(null, 'Y-m-d');
        $message = $formatter->format(array(
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'context' => array(),
            'datetime' => new \DateTime,
            'extra' => array('foo' => new TestFoo, 'bar' => new TestBar, 'baz' => array(), 'res' => fopen('php://memory', 'rb')),
            'message' => 'foobar',
        ));

        $this->assertEquals('['.date('Y-m-d').'] meh.ERROR: foobar [] {"foo":"[object] (Monolog\\\\Formatter\\\\TestFoo: {\\"foo\\":\\"foo\\"})","bar":"[object] (Monolog\\\\Formatter\\\\TestBar: {})","baz":[],"res":"[resource]"}'."\n", $message);
    }

    public function testDefFormatWithException()
    {
        $formatter = new LineFormatter(null, 'Y-m-d');
        $message = $formatter->format(array(
            'level_name' => 'CRITICAL',
            'channel' => 'core',
            'context' => array('exception' => new \RuntimeException('Foo')),
            'datetime' => new \DateTime,
            'extra' => array(),
            'message' => 'foobar',
        ));

        $path = str_replace('\\/', '/', json_encode(__FILE__));

        $this->assertEquals('['.date('Y-m-d').'] core.CRITICAL: foobar {"exception":"[object] (RuntimeException: Foo at '.substr($path, 1, -1).':'.(__LINE__-8).')"} []'."\n", $message);
    }

    public function testDefFormatWithPreviousException()
    {
        $formatter = new LineFormatter(null, 'Y-m-d');
        $previous = new \LogicException('Wut?');
        $message = $formatter->format(array(
            'level_name' => 'CRITICAL',
            'channel' => 'core',
            'context' => array('exception' => new \RuntimeException('Foo', 0, $previous)),
            'datetime' => new \DateTime,
            'extra' => array(),
            'message' => 'foobar',
        ));

        $path = str_replace('\\/', '/', json_encode(__FILE__));

        $this->assertEquals('['.date('Y-m-d').'] core.CRITICAL: foobar {"exception":"[object] (RuntimeException: Foo at '.substr($path, 1, -1).':'.(__LINE__-8).', LogicException: Wut? at '.substr($path, 1, -1).':'.(__LINE__-12).')"} []'."\n", $message);
    }

    public function testBatchFormat()
    {
        $formatter = new LineFormatter(null, 'Y-m-d');
        $message = $formatter->formatBatch(array(
            array(
                'level_name' => 'CRITICAL',
                'channel' => 'test',
                'message' => 'bar',
                'context' => array(),
                'datetime' => new \DateTime,
                'extra' => array(),
            ),
            array(
                'level_name' => 'WARNING',
                'channel' => 'log',
                'message' => 'foo',
                'context' => array(),
                'datetime' => new \DateTime,
                'extra' => array(),
            ),
        ));
        $this->assertEquals('['.date('Y-m-d').'] test.CRITICAL: bar [] []'."\n".'['.date('Y-m-d').'] log.WARNING: foo [] []'."\n", $message);
    }
}

class TestFoo
{
    public $foo = 'foo';
}

class TestBar
{
    public function __toString()
    {
        return 'bar';
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Formatter;

use Monolog\Logger;
use Monolog\TestCase;

class JsonFormatterTest extends TestCase
{
    /**
     * @covers Monolog\Formatter\JsonFormatter::format
     */
    public function testFormat()
    {
        $formatter = new JsonFormatter();
        $record = $this->getRecord();
        $this->assertEquals(json_encode($record), $formatter->format($record));
    }

    /**
     * @covers Monolog\Formatter\JsonFormatter::formatBatch
     */
    public function testFormatBatch()
    {
        $formatter = new JsonFormatter();
        $records = array(
            $this->getRecord(Logger::WARNING),
            $this->getRecord(Logger::DEBUG),
        );
        $this->assertEquals(json_encode($records), $formatter->formatBatch($records));
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Formatter;

use Monolog\Logger;
use Monolog\Formatter\LogstashFormatter;

class LogstashFormatterTest extends \PHPUnit_Framework_TestCase
{

    /**
     * @covers Monolog\Formatter\LogstashFormatter::format
     */
    public function testDefaultFormatter()
    {
        $formatter = new LogstashFormatter('test', 'hostname');
        $record = array(
            'level' => Logger::ERROR,
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'context' => array(),
            'datetime' => new \DateTime("@0"),
            'extra' => array(),
            'message' => 'log',
        );

        $message = json_decode($formatter->format($record), true);

        $this->assertEquals("1970-01-01T00:00:00.000000+00:00", $message['@timestamp']);
        $this->assertEquals('log', $message['@message']);
        $this->assertEquals('meh', $message['@fields']['channel']);
        $this->assertContains('meh', $message['@tags']);
        $this->assertEquals(Logger::ERROR, $message['@fields']['level']);
        $this->assertEquals('test', $message['@type']);
        $this->assertEquals('hostname', $message['@source']);

        $formatter = new LogstashFormatter('mysystem');

        $message = json_decode($formatter->format($record), true);

        $this->assertEquals('mysystem', $message['@type']);
    }

    /**
     * @covers Monolog\Formatter\LogstashFormatter::format
     */
    public function testFormatWithFileAndLine()
    {
        $formatter = new LogstashFormatter('test');
        $record = array(
            'level' => Logger::ERROR,
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'context' => array('from' => 'logger'),
            'datetime' => new \DateTime("@0"),
            'extra' => array('file' => 'test', 'line' => 14),
            'message' => 'log',
        );

        $message = json_decode($formatter->format($record), true);

        $this->assertEquals('test', $message['@fields']['file']);
        $this->assertEquals(14, $message['@fields']['line']);
    }

    /**
     * @covers Monolog\Formatter\LogstashFormatter::format
     */
    public function testFormatWithContext()
    {
        $formatter = new LogstashFormatter('test');
        $record = array(
            'level' => Logger::ERROR,
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'context' => array('from' => 'logger'),
            'datetime' => new \DateTime("@0"),
            'extra' => array('key' => 'pair'),
            'message' => 'log'
        );

        $message = json_decode($formatter->format($record), true);

        $message_array = $message['@fields'];

        $this->assertArrayHasKey('ctxt_from', $message_array);
        $this->assertEquals('logger', $message_array['ctxt_from']);

        // Test with extraPrefix
        $formatter = new LogstashFormatter('test', null, null, 'CTX');
        $message = json_decode($formatter->format($record), true);

        $message_array = $message['@fields'];

        $this->assertArrayHasKey('CTXfrom', $message_array);
        $this->assertEquals('logger', $message_array['CTXfrom']);

    }

    /**
     * @covers Monolog\Formatter\LogstashFormatter::format
     */
    public function testFormatWithExtra()
    {
        $formatter = new LogstashFormatter('test');
        $record = array(
            'level' => Logger::ERROR,
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'context' => array('from' => 'logger'),
            'datetime' => new \DateTime("@0"),
            'extra' => array('key' => 'pair'),
            'message' => 'log'
        );

        $message = json_decode($formatter->format($record), true);

        $message_array = $message['@fields'];

        $this->assertArrayHasKey('key', $message_array);
        $this->assertEquals('pair', $message_array['key']);

        // Test with extraPrefix
        $formatter = new LogstashFormatter('test', null, 'EXT');
        $message = json_decode($formatter->format($record), true);

        $message_array = $message['@fields'];

        $this->assertArrayHasKey('EXTkey', $message_array);
        $this->assertEquals('pair', $message_array['EXTkey']);
    }

    public function testFormatWithApplicationName()
    {
        $formatter = new LogstashFormatter('app', 'test');
        $record = array(
            'level' => Logger::ERROR,
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'context' => array('from' => 'logger'),
            'datetime' => new \DateTime("@0"),
            'extra' => array('key' => 'pair'),
            'message' => 'log'
        );

        $message = json_decode($formatter->format($record), true);

        $this->assertArrayHasKey('@type', $message);
        $this->assertEquals('app', $message['@type']);
    }

    /**
     * @covers Monolog\Formatter\LogstashFormatter::format
     */
    public function testDefaultFormatterV1()
    {
        $formatter = new LogstashFormatter('test', 'hostname', null, 'ctxt_', LogstashFormatter::V1);
        $record = array(
            'level' => Logger::ERROR,
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'context' => array(),
            'datetime' => new \DateTime("@0"),
            'extra' => array(),
            'message' => 'log',
        );

        $message = json_decode($formatter->format($record), true);

        $this->assertEquals("1970-01-01T00:00:00.000000+00:00", $message['@timestamp']);
        $this->assertEquals("1", $message['@version']);
        $this->assertEquals('log', $message['message']);
        $this->assertEquals('meh', $message['channel']);
        $this->assertEquals('ERROR', $message['level']);
        $this->assertEquals('test', $message['type']);
        $this->assertEquals('hostname', $message['host']);

        $formatter = new LogstashFormatter('mysystem', null, null, 'ctxt_', LogstashFormatter::V1);

        $message = json_decode($formatter->format($record), true);

        $this->assertEquals('mysystem', $message['type']);
    }

    /**
     * @covers Monolog\Formatter\LogstashFormatter::format
     */
    public function testFormatWithFileAndLineV1()
    {
        $formatter = new LogstashFormatter('test', null, null, 'ctxt_', LogstashFormatter::V1);
        $record = array(
            'level' => Logger::ERROR,
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'context' => array('from' => 'logger'),
            'datetime' => new \DateTime("@0"),
            'extra' => array('file' => 'test', 'line' => 14),
            'message' => 'log',
        );

        $message = json_decode($formatter->format($record), true);

        $this->assertEquals('test', $message['file']);
        $this->assertEquals(14, $message['line']);
    }

    /**
     * @covers Monolog\Formatter\LogstashFormatter::format
     */
    public function testFormatWithContextV1()
    {
        $formatter = new LogstashFormatter('test', null, null, 'ctxt_', LogstashFormatter::V1);
        $record = array(
            'level' => Logger::ERROR,
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'context' => array('from' => 'logger'),
            'datetime' => new \DateTime("@0"),
            'extra' => array('key' => 'pair'),
            'message' => 'log'
        );

        $message = json_decode($formatter->format($record), true);

        $this->assertArrayHasKey('ctxt_from', $message);
        $this->assertEquals('logger', $message['ctxt_from']);

        // Test with extraPrefix
        $formatter = new LogstashFormatter('test', null, null, 'CTX', LogstashFormatter::V1);
        $message = json_decode($formatter->format($record), true);

        $this->assertArrayHasKey('CTXfrom', $message);
        $this->assertEquals('logger', $message['CTXfrom']);

    }

    /**
     * @covers Monolog\Formatter\LogstashFormatter::format
     */
    public function testFormatWithExtraV1()
    {
        $formatter = new LogstashFormatter('test', null, null, 'ctxt_', LogstashFormatter::V1);
        $record = array(
            'level' => Logger::ERROR,
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'context' => array('from' => 'logger'),
            'datetime' => new \DateTime("@0"),
            'extra' => array('key' => 'pair'),
            'message' => 'log'
        );

        $message = json_decode($formatter->format($record), true);

        $this->assertArrayHasKey('key', $message);
        $this->assertEquals('pair', $message['key']);

        // Test with extraPrefix
        $formatter = new LogstashFormatter('test', null, 'EXT', 'ctxt_', LogstashFormatter::V1);
        $message = json_decode($formatter->format($record), true);

        $this->assertArrayHasKey('EXTkey', $message);
        $this->assertEquals('pair', $message['EXTkey']);
    }

    public function testFormatWithApplicationNameV1()
    {
        $formatter = new LogstashFormatter('app', 'test', null, 'ctxt_', LogstashFormatter::V1);
        $record = array(
            'level' => Logger::ERROR,
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'context' => array('from' => 'logger'),
            'datetime' => new \DateTime("@0"),
            'extra' => array('key' => 'pair'),
            'message' => 'log'
        );

        $message = json_decode($formatter->format($record), true);

        $this->assertArrayHasKey('type', $message);
        $this->assertEquals('app', $message['type']);
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Formatter;

use Monolog\Logger;
use Monolog\Formatter\GelfMessageFormatter;

class GelfMessageFormatterTest extends \PHPUnit_Framework_TestCase
{
    public function setUp()
    {
        if (!class_exists("Gelf\Message")) {
            $this->markTestSkipped("mlehner/gelf-php not installed");
        }
    }

    /**
     * @covers Monolog\Formatter\GelfMessageFormatter::format
     */
    public function testDefaultFormatter()
    {
        $formatter = new GelfMessageFormatter();
        $record = array(
            'level' => Logger::ERROR,
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'context' => array(),
            'datetime' => new \DateTime("@0"),
            'extra' => array(),
            'message' => 'log',
        );

        $message = $formatter->format($record);

        $this->assertInstanceOf('Gelf\Message', $message);
        $this->assertEquals(0, $message->getTimestamp());
        $this->assertEquals('log', $message->getShortMessage());
        $this->assertEquals('meh', $message->getFacility());
        $this->assertEquals(null, $message->getLine());
        $this->assertEquals(null, $message->getFile());
        $this->assertEquals(3, $message->getLevel());
        $this->assertNotEmpty($message->getHost());

        $formatter = new GelfMessageFormatter('mysystem');

        $message = $formatter->format($record);

        $this->assertInstanceOf('Gelf\Message', $message);
        $this->assertEquals('mysystem', $message->getHost());
    }

    /**
     * @covers Monolog\Formatter\GelfMessageFormatter::format
     */
    public function testFormatWithFileAndLine()
    {
        $formatter = new GelfMessageFormatter();
        $record = array(
            'level' => Logger::ERROR,
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'context' => array('from' => 'logger'),
            'datetime' => new \DateTime("@0"),
            'extra' => array('file' => 'test', 'line' => 14),
            'message' => 'log',
        );

        $message = $formatter->format($record);

        $this->assertInstanceOf('Gelf\Message', $message);
        $this->assertEquals('test', $message->getFile());
        $this->assertEquals(14, $message->getLine());
    }

    /**
     * @covers Monolog\Formatter\GelfMessageFormatter::format
     */
    public function testFormatWithContext()
    {
        $formatter = new GelfMessageFormatter();
        $record = array(
            'level' => Logger::ERROR,
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'context' => array('from' => 'logger'),
            'datetime' => new \DateTime("@0"),
            'extra' => array('key' => 'pair'),
            'message' => 'log'
        );

        $message = $formatter->format($record);

        $this->assertInstanceOf('Gelf\Message', $message);

        $message_array = $message->toArray();

        $this->assertArrayHasKey('_ctxt_from', $message_array);
        $this->assertEquals('logger', $message_array['_ctxt_from']);

        // Test with extraPrefix
        $formatter = new GelfMessageFormatter(null, null, 'CTX');
        $message = $formatter->format($record);

        $this->assertInstanceOf('Gelf\Message', $message);

        $message_array = $message->toArray();

        $this->assertArrayHasKey('_CTXfrom', $message_array);
        $this->assertEquals('logger', $message_array['_CTXfrom']);

    }

    /**
     * @covers Monolog\Formatter\GelfMessageFormatter::format
     */
    public function testFormatWithContextContainingException()
    {
        $formatter = new GelfMessageFormatter();
        $record = array(
            'level' => Logger::ERROR,
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'context' => array('from' => 'logger', 'exception' => array(
                'class' => '\Exception',
                'file'  => '/some/file/in/dir.php:56',
                'trace' => array('/some/file/1.php:23', '/some/file/2.php:3')
            )),
            'datetime' => new \DateTime("@0"),
            'extra' => array(),
            'message' => 'log'
        );

        $message = $formatter->format($record);

        $this->assertInstanceOf('Gelf\Message', $message);

        $this->assertEquals("/some/file/in/dir.php", $message->getFile());
        $this->assertEquals("56", $message->getLine());

    }

    /**
     * @covers Monolog\Formatter\GelfMessageFormatter::format
     */
    public function testFormatWithExtra()
    {
        $formatter = new GelfMessageFormatter();
        $record = array(
            'level' => Logger::ERROR,
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'context' => array('from' => 'logger'),
            'datetime' => new \DateTime("@0"),
            'extra' => array('key' => 'pair'),
            'message' => 'log'
        );

        $message = $formatter->format($record);

        $this->assertInstanceOf('Gelf\Message', $message);

        $message_array = $message->toArray();

        $this->assertArrayHasKey('_key', $message_array);
        $this->assertEquals('pair', $message_array['_key']);

        // Test with extraPrefix
        $formatter = new GelfMessageFormatter(null, 'EXT');
        $message = $formatter->format($record);

        $this->assertInstanceOf('Gelf\Message', $message);

        $message_array = $message->toArray();

        $this->assertArrayHasKey('_EXTkey', $message_array);
        $this->assertEquals('pair', $message_array['_EXTkey']);
    }
}
<?php
namespace Monolog\Formatter;

class ScalarFormatterTest extends \PHPUnit_Framework_TestCase
{
    public function setUp()
    {
        $this->formatter = new ScalarFormatter();
    }

    public function buildTrace(\Exception $e)
    {
        $data = array();
        $trace = $e->getTrace();
        array_shift($trace);
        foreach ($trace as $frame) {
            if (isset($frame['file'])) {
                $data[] = $frame['file'].':'.$frame['line'];
            } else {
                $data[] = json_encode($frame);
            }
        }

        return $data;
    }

    public function encodeJson($data)
    {
        if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
            return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        }

        return json_encode($data);
    }

    public function testFormat()
    {
        $exception = new \Exception('foo');
        $formatted = $this->formatter->format(array(
            'foo' => 'string',
            'bar' => 1,
            'baz' => false,
            'bam' => array(1,2,3),
            'bat' => array('foo' => 'bar'),
            'bap' => \DateTime::createFromFormat(\DateTime::ISO8601, '1970-01-01T00:00:00+0000'),
            'ban' => $exception
        ));

        $this->assertSame(array(
            'foo' => 'string',
            'bar' => 1,
            'baz' => false,
            'bam' => $this->encodeJson(array(1,2,3)),
            'bat' => $this->encodeJson(array('foo' => 'bar')),
            'bap' => '1970-01-01 00:00:00',
            'ban' => $this->encodeJson(array(
                'class'   => get_class($exception),
                'message' => $exception->getMessage(),
                'file'    => $exception->getFile() . ':' . $exception->getLine(),
                'trace'   => $this->buildTrace($exception)
            ))
        ), $formatted);
    }

    public function testFormatWithErrorContext()
    {
        $context = array('file' => 'foo', 'line' => 1);
        $formatted = $this->formatter->format(array(
            'context' => $context
        ));

        $this->assertSame(array(
            'context' => $this->encodeJson($context)
        ), $formatted);
    }

    public function testFormatWithExceptionContext()
    {
        $exception = new \Exception('foo');
        $formatted = $this->formatter->format(array(
            'context' => array(
                'exception' => $exception
            )
        ));

        $this->assertSame(array(
            'context' => $this->encodeJson(array(
                'exception' => array(
                    'class'   => get_class($exception),
                    'message' => $exception->getMessage(),
                    'file'    => $exception->getFile() . ':' . $exception->getLine(),
                    'trace'   => $this->buildTrace($exception)
                )
            ))
        ), $formatted);
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Formatter;

/**
 * @covers Monolog\Formatter\NormalizerFormatter
 */
class NormalizerFormatterTest extends \PHPUnit_Framework_TestCase
{
    public function testFormat()
    {
        $formatter = new NormalizerFormatter('Y-m-d');
        $formatted = $formatter->format(array(
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'message' => 'foo',
            'datetime' => new \DateTime,
            'extra' => array('foo' => new TestFooNorm, 'bar' => new TestBarNorm, 'baz' => array(), 'res' => fopen('php://memory', 'rb')),
            'context' => array(
                'foo' => 'bar',
                'baz' => 'qux',
            ),
        ));

        $this->assertEquals(array(
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'message' => 'foo',
            'datetime' => date('Y-m-d'),
            'extra' => array(
                'foo' => '[object] (Monolog\\Formatter\\TestFooNorm: {"foo":"foo"})',
                'bar' => '[object] (Monolog\\Formatter\\TestBarNorm: {})',
                'baz' => array(),
                'res' => '[resource]',
            ),
            'context' => array(
                'foo' => 'bar',
                'baz' => 'qux',
            )
        ), $formatted);
    }

    public function testFormatExceptions()
    {
        $formatter = new NormalizerFormatter('Y-m-d');
        $e = new \LogicException('bar');
        $e2 = new \RuntimeException('foo', 0, $e);
        $formatted = $formatter->format(array(
            'exception' => $e2,
        ));

        $this->assertGreaterThan(5, count($formatted['exception']['trace']));
        $this->assertTrue(isset($formatted['exception']['previous']));
        unset($formatted['exception']['trace'], $formatted['exception']['previous']);

        $this->assertEquals(array(
            'exception' => array(
                'class'   => get_class($e2),
                'message' => $e2->getMessage(),
                'file'   => $e2->getFile().':'.$e2->getLine(),
            )
        ), $formatted);
    }

    public function testBatchFormat()
    {
        $formatter = new NormalizerFormatter('Y-m-d');
        $formatted = $formatter->formatBatch(array(
            array(
                'level_name' => 'CRITICAL',
                'channel' => 'test',
                'message' => 'bar',
                'context' => array(),
                'datetime' => new \DateTime,
                'extra' => array(),
            ),
            array(
                'level_name' => 'WARNING',
                'channel' => 'log',
                'message' => 'foo',
                'context' => array(),
                'datetime' => new \DateTime,
                'extra' => array(),
            ),
        ));
        $this->assertEquals(array(
            array(
                'level_name' => 'CRITICAL',
                'channel' => 'test',
                'message' => 'bar',
                'context' => array(),
                'datetime' => date('Y-m-d'),
                'extra' => array(),
            ),
            array(
                'level_name' => 'WARNING',
                'channel' => 'log',
                'message' => 'foo',
                'context' => array(),
                'datetime' => date('Y-m-d'),
                'extra' => array(),
            ),
        ), $formatted);
    }

    /**
     * Test issue #137
     */
    public function testIgnoresRecursiveObjectReferences()
    {
        // set up the recursion
        $foo = new \stdClass();
        $bar = new \stdClass();

        $foo->bar = $bar;
        $bar->foo = $foo;

        // set an error handler to assert that the error is not raised anymore
        $that = $this;
        set_error_handler(function ($level, $message, $file, $line, $context) use ($that) {
            if (error_reporting() & $level) {
                restore_error_handler();
                $that->fail("$message should not be raised");
            }
        });

        $formatter = new NormalizerFormatter();
        $reflMethod = new \ReflectionMethod($formatter, 'toJson');
        $reflMethod->setAccessible(true);
        $res = $reflMethod->invoke($formatter, array($foo, $bar), true);

        restore_error_handler();

        $this->assertEquals(@json_encode(array($foo, $bar)), $res);
    }

    public function testIgnoresInvalidTypes()
    {
        // set up the recursion
        $resource = fopen(__FILE__, 'r');

        // set an error handler to assert that the error is not raised anymore
        $that = $this;
        set_error_handler(function ($level, $message, $file, $line, $context) use ($that) {
            if (error_reporting() & $level) {
                restore_error_handler();
                $that->fail("$message should not be raised");
            }
        });

        $formatter = new NormalizerFormatter();
        $reflMethod = new \ReflectionMethod($formatter, 'toJson');
        $reflMethod->setAccessible(true);
        $res = $reflMethod->invoke($formatter, array($resource), true);

        restore_error_handler();

        $this->assertEquals(@json_encode(array($resource)), $res);
    }
}

class TestFooNorm
{
    public $foo = 'foo';
}

class TestBarNorm
{
    public function __toString()
    {
        return 'bar';
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Formatter;

use Monolog\Logger;

class WildfireFormatterTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Monolog\Formatter\WildfireFormatter::format
     */
    public function testDefaultFormat()
    {
        $wildfire = new WildfireFormatter();
        $record = array(
            'level' => Logger::ERROR,
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'context' => array('from' => 'logger'),
            'datetime' => new \DateTime("@0"),
            'extra' => array('ip' => '127.0.0.1'),
            'message' => 'log',
        );

        $message = $wildfire->format($record);

        $this->assertEquals(
            '125|[{"Type":"ERROR","File":"","Line":"","Label":"meh"},'
                .'{"message":"log","context":{"from":"logger"},"extra":{"ip":"127.0.0.1"}}]|',
            $message
        );
    }

    /**
     * @covers Monolog\Formatter\WildfireFormatter::format
     */
    public function testFormatWithFileAndLine()
    {
        $wildfire = new WildfireFormatter();
        $record = array(
            'level' => Logger::ERROR,
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'context' => array('from' => 'logger'),
            'datetime' => new \DateTime("@0"),
            'extra' => array('ip' => '127.0.0.1', 'file' => 'test', 'line' => 14),
            'message' => 'log',
        );

        $message = $wildfire->format($record);

        $this->assertEquals(
            '129|[{"Type":"ERROR","File":"test","Line":14,"Label":"meh"},'
                .'{"message":"log","context":{"from":"logger"},"extra":{"ip":"127.0.0.1"}}]|',
            $message
        );
    }

    /**
     * @covers Monolog\Formatter\WildfireFormatter::format
     */
    public function testFormatWithoutContext()
    {
        $wildfire = new WildfireFormatter();
        $record = array(
            'level' => Logger::ERROR,
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'context' => array(),
            'datetime' => new \DateTime("@0"),
            'extra' => array(),
            'message' => 'log',
        );

        $message = $wildfire->format($record);

        $this->assertEquals(
            '58|[{"Type":"ERROR","File":"","Line":"","Label":"meh"},"log"]|',
            $message
        );
    }

    /**
     * @covers Monolog\Formatter\WildfireFormatter::formatBatch
     * @expectedException BadMethodCallException
     */
    public function testBatchFormatThrowException()
    {
        $wildfire = new WildfireFormatter();
        $record = array(
            'level' => Logger::ERROR,
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'context' => array(),
            'datetime' => new \DateTime("@0"),
            'extra' => array(),
            'message' => 'log',
        );

        $wildfire->formatBatch(array($record));
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Formatter;

use Monolog\Logger;
use Monolog\Formatter\ElasticaFormatter;

class ElasticaFormatterTest extends \PHPUnit_Framework_TestCase
{
    public function setUp()
    {
        if (!class_exists("Elastica\Document")) {
            $this->markTestSkipped("ruflin/elastica not installed");
        }
    }

    /**
     * @covers Monolog\Formatter\ElasticaFormatter::__construct
     * @covers Monolog\Formatter\ElasticaFormatter::format
     * @covers Monolog\Formatter\ElasticaFormatter::getDocument
     */
    public function testFormat()
    {
        // test log message
        $msg = array(
            'level' => Logger::ERROR,
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'context' => array('foo' => 7, 'bar', 'class' => new \stdClass),
            'datetime' => new \DateTime("@0"),
            'extra' => array(),
            'message' => 'log',
        );

        // expected values
        $expected = $msg;
        $expected['datetime'] = '1970-01-01T00:00:00+0000';
        $expected['context'] = array(
            'class' => '[object] (stdClass: {})',
            'foo' => 7,
            0 => 'bar',
        );

        // format log message
        $formatter = new ElasticaFormatter('my_index', 'doc_type');
        $doc = $formatter->format($msg);
        $this->assertInstanceOf('Elastica\Document', $doc);

        // Document parameters
        $params = $doc->getParams();
        $this->assertEquals('my_index', $params['_index']);
        $this->assertEquals('doc_type', $params['_type']);

        // Document data values
        $data = $doc->getData();
        foreach (array_keys($expected) as $key) {
            $this->assertEquals($expected[$key], $data[$key]);
        }
    }

    /**
     * @covers Monolog\Formatter\ElasticaFormatter::getIndex
     * @covers Monolog\Formatter\ElasticaFormatter::getType
     */
    public function testGetters()
    {
        $formatter = new ElasticaFormatter('my_index', 'doc_type');
        $this->assertEquals('my_index', $formatter->getIndex());
        $this->assertEquals('doc_type', $formatter->getType());
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Formatter;

use Monolog\Logger;

class ChromePHPFormatterTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Monolog\Formatter\ChromePHPFormatter::format
     */
    public function testDefaultFormat()
    {
        $formatter = new ChromePHPFormatter();
        $record = array(
            'level' => Logger::ERROR,
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'context' => array('from' => 'logger'),
            'datetime' => new \DateTime("@0"),
            'extra' => array('ip' => '127.0.0.1'),
            'message' => 'log',
        );

        $message = $formatter->format($record);

        $this->assertEquals(
            array(
                'meh',
                array(
                    'message' => 'log',
                    'context' => array('from' => 'logger'),
                    'extra' => array('ip' => '127.0.0.1'),
                ),
                'unknown',
                'error'
            ),
            $message
        );
    }

    /**
     * @covers Monolog\Formatter\ChromePHPFormatter::format
     */
    public function testFormatWithFileAndLine()
    {
        $formatter = new ChromePHPFormatter();
        $record = array(
            'level' => Logger::CRITICAL,
            'level_name' => 'CRITICAL',
            'channel' => 'meh',
            'context' => array('from' => 'logger'),
            'datetime' => new \DateTime("@0"),
            'extra' => array('ip' => '127.0.0.1', 'file' => 'test', 'line' => 14),
            'message' => 'log',
        );

        $message = $formatter->format($record);

        $this->assertEquals(
            array(
                'meh',
                array(
                    'message' => 'log',
                    'context' => array('from' => 'logger'),
                    'extra' => array('ip' => '127.0.0.1'),
                ),
                'test : 14',
                'error'
            ),
            $message
        );
    }

    /**
     * @covers Monolog\Formatter\ChromePHPFormatter::format
     */
    public function testFormatWithoutContext()
    {
        $formatter = new ChromePHPFormatter();
        $record = array(
            'level' => Logger::DEBUG,
            'level_name' => 'DEBUG',
            'channel' => 'meh',
            'context' => array(),
            'datetime' => new \DateTime("@0"),
            'extra' => array(),
            'message' => 'log',
        );

        $message = $formatter->format($record);

        $this->assertEquals(
            array(
                'meh',
                'log',
                'unknown',
                'log'
            ),
            $message
        );
    }

    /**
     * @covers Monolog\Formatter\ChromePHPFormatter::formatBatch
     */
    public function testBatchFormatThrowException()
    {
        $formatter = new ChromePHPFormatter();
        $records = array(
            array(
                'level' => Logger::INFO,
                'level_name' => 'INFO',
                'channel' => 'meh',
                'context' => array(),
                'datetime' => new \DateTime("@0"),
                'extra' => array(),
                'message' => 'log',
            ),
            array(
                'level' => Logger::WARNING,
                'level_name' => 'WARNING',
                'channel' => 'foo',
                'context' => array(),
                'datetime' => new \DateTime("@0"),
                'extra' => array(),
                'message' => 'log2',
            ),
        );

        $this->assertEquals(
            array(
                array(
                    'meh',
                    'log',
                    'unknown',
                    'info'
                ),
                array(
                    'foo',
                    'log2',
                    'unknown',
                    'warn'
                ),
            ),
            $formatter->formatBatch($records)
        );
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

spl_autoload_register(function($class) {
    $file = __DIR__.'/../../../../src/'.strtr($class, '\\', '/').'.php';
    if (file_exists($file)) {
        require $file;

        return true;
    }
});

use Monolog\Logger;
use Monolog\Handler\FirePHPHandler;
use Monolog\Handler\ChromePHPHandler;

$logger = new Logger('firephp');
$logger->pushHandler(new FirePHPHandler);
$logger->pushHandler(new ChromePHPHandler());

$logger->addDebug('Debug');
$logger->addInfo('Info');
$logger->addWarning('Warning');
$logger->addError('Error');
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\TestCase;
use Monolog\Logger;

class DoctrineCouchDBHandlerTest extends TestCase
{
    protected function setup()
    {
        if (!class_exists('Doctrine\CouchDB\CouchDBClient')) {
            $this->markTestSkipped('The "doctrine/couchdb" package is not installed');
        }
    }

    public function testHandle()
    {
        $client = $this->getMockBuilder('Doctrine\\CouchDB\\CouchDBClient')
            ->setMethods(array('postDocument'))
            ->disableOriginalConstructor()
            ->getMock();

        $record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34));

        $expected = array(
            'message' => 'test',
            'context' => array('data' => '[object] (stdClass: {})', 'foo' => 34),
            'level' => Logger::WARNING,
            'level_name' => 'WARNING',
            'channel' => 'test',
            'datetime' => $record['datetime']->format('Y-m-d H:i:s'),
            'extra' => array(),
        );

        $client->expects($this->once())
            ->method('postDocument')
            ->with($expected);

        $handler = new DoctrineCouchDBHandler($client);
        $handler->handle($record);
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\TestCase;

class NativeMailerHandlerTest extends TestCase
{
    /**
     * @expectedException InvalidArgumentException
     */
    public function testConstructorHeaderInjection()
    {
        $mailer = new NativeMailerHandler('spammer@example.org', 'dear victim', "receiver@example.org\r\nFrom: faked@attacker.org");
    }

    /**
     * @expectedException InvalidArgumentException
     */
    public function testSetterHeaderInjection()
    {
        $mailer = new NativeMailerHandler('spammer@example.org', 'dear victim', 'receiver@example.org');
        $mailer->addHeader("Content-Type: text/html\r\nFrom: faked@attacker.org");
    }

    /**
     * @expectedException InvalidArgumentException
     */
    public function testSetterArrayHeaderInjection()
    {
        $mailer = new NativeMailerHandler('spammer@example.org', 'dear victim', 'receiver@example.org');
        $mailer->addHeader(array("Content-Type: text/html\r\nFrom: faked@attacker.org"));
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Gelf\MessagePublisher;
use Gelf\Message;

class MockMessagePublisher extends MessagePublisher
{
    public function publish(Message $message)
    {
        $this->lastMessage = $message;
    }

    public $lastMessage = null;
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\TestCase;
use Monolog\Logger;

/**
 * @covers Monolog\Handler\ChromePHPHandler
 */
class ChromePHPHandlerTest extends TestCase
{
    protected function setUp()
    {
        TestChromePHPHandler::reset();
    }

    public function testHeaders()
    {
        $handler = new TestChromePHPHandler();
        $handler->setFormatter($this->getIdentityFormatter());
        $handler->handle($this->getRecord(Logger::DEBUG));
        $handler->handle($this->getRecord(Logger::WARNING));

        $expected = array(
            'X-ChromeLogger-Data'   => base64_encode(utf8_encode(json_encode(array(
                'version' => ChromePHPHandler::VERSION,
                'columns' => array('label', 'log', 'backtrace', 'type'),
                'rows' => array(
                    'test',
                    'test',
                ),
                'request_uri' => '',
            ))))
        );

        $this->assertEquals($expected, $handler->getHeaders());
    }

    public function testHeadersOverflow()
    {
        $handler = new TestChromePHPHandler();
        $handler->handle($this->getRecord(Logger::DEBUG));
        $handler->handle($this->getRecord(Logger::WARNING, str_repeat('a', 150*1024)));

        // overflow chrome headers limit
        $handler->handle($this->getRecord(Logger::WARNING, str_repeat('a', 100*1024)));

        $expected = array(
            'X-ChromeLogger-Data'   => base64_encode(utf8_encode(json_encode(array(
                'version' => ChromePHPHandler::VERSION,
                'columns' => array('label', 'log', 'backtrace', 'type'),
                'rows' => array(
                    array(
                        'test',
                        'test',
                        'unknown',
                        'log',
                    ),
                    array(
                        'test',
                        str_repeat('a', 150*1024),
                        'unknown',
                        'warn',
                    ),
                    array(
                        'monolog',
                        'Incomplete logs, chrome header size limit reached',
                        'unknown',
                        'warn',
                    ),
                ),
                'request_uri' => '',
            ))))
        );

        $this->assertEquals($expected, $handler->getHeaders());
    }

    public function testConcurrentHandlers()
    {
        $handler = new TestChromePHPHandler();
        $handler->setFormatter($this->getIdentityFormatter());
        $handler->handle($this->getRecord(Logger::DEBUG));
        $handler->handle($this->getRecord(Logger::WARNING));

        $handler2 = new TestChromePHPHandler();
        $handler2->setFormatter($this->getIdentityFormatter());
        $handler2->handle($this->getRecord(Logger::DEBUG));
        $handler2->handle($this->getRecord(Logger::WARNING));

        $expected = array(
            'X-ChromeLogger-Data'   => base64_encode(utf8_encode(json_encode(array(
                'version' => ChromePHPHandler::VERSION,
                'columns' => array('label', 'log', 'backtrace', 'type'),
                'rows' => array(
                    'test',
                    'test',
                    'test',
                    'test',
                ),
                'request_uri' => '',
            ))))
        );

        $this->assertEquals($expected, $handler2->getHeaders());
    }
}

class TestChromePHPHandler extends ChromePHPHandler
{
    protected $headers = array();

    public static function reset()
    {
        self::$initialized = false;
        self::$overflowed = false;
        self::$json['rows'] = array();
    }

    protected function sendHeader($header, $content)
    {
        $this->headers[$header] = $content;
    }

    public function getHeaders()
    {
        return $this->headers;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\TestCase;
use Monolog\Logger;

/**
 * @covers Monolog\Handler\TestHandler
 */
class TestHandlerTest extends TestCase
{
    /**
     * @dataProvider methodProvider
     */
    public function testHandler($method, $level)
    {
        $handler = new TestHandler;
        $record = $this->getRecord($level, 'test'.$method);
        $this->assertFalse($handler->{'has'.$method}($record));
        $this->assertFalse($handler->{'has'.$method.'Records'}());
        $handler->handle($record);

        $this->assertFalse($handler->{'has'.$method}('bar'));
        $this->assertTrue($handler->{'has'.$method}($record));
        $this->assertTrue($handler->{'has'.$method}('test'.$method));
        $this->assertTrue($handler->{'has'.$method.'Records'}());

        $records = $handler->getRecords();
        unset($records[0]['formatted']);
        $this->assertEquals(array($record), $records);
    }

    public function methodProvider()
    {
        return array(
            array('Emergency', Logger::EMERGENCY),
            array('Alert'    , Logger::ALERT),
            array('Critical' , Logger::CRITICAL),
            array('Error'    , Logger::ERROR),
            array('Warning'  , Logger::WARNING),
            array('Info'     , Logger::INFO),
            array('Notice'   , Logger::NOTICE),
            array('Debug'    , Logger::DEBUG),
        );
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\TestCase;
use Monolog\Logger;

/**
 * @covers Monolog\Handler\RotatingFileHandler
 */
class AmqpHandlerTest extends TestCase
{
    public function setUp()
    {
        if (!class_exists('AMQPConnection') || !class_exists('AMQPExchange')) {
            $this->markTestSkipped("amqp-php not installed");
        }

        if (!class_exists('AMQPChannel')) {
            $this->markTestSkipped("Please update AMQP to version >= 1.0");
        }
    }

    public function testHandle()
    {
        $exchange = $this->getExchange();

        $handler = new AmqpHandler($exchange, 'log');

        $record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34));

        $expected = array(
            array(
                'message' => 'test',
                'context' => array(
                    'data' => array(),
                    'foo' => 34,
                ),
                'level' => 300,
                'level_name' => 'WARNING',
                'channel' => 'test',
                'extra' => array(),
            ),
            'warn.test',
            0,
            array(
                'delivery_mode' => 2,
                'Content-type' => 'application/json'
            )
        );

        $handler->handle($record);

        $messages = $exchange->getMessages();
        $this->assertCount(1, $messages);
        $messages[0][0] = json_decode($messages[0][0], true);
        unset($messages[0][0]['datetime']);
        $this->assertEquals($expected, $messages[0]);
    }

    protected function getExchange()
    {
        return new AmqpExchangeMock();
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Raven_Client;

class MockRavenClient extends Raven_Client
{
    public function capture($data, $stack, $vars = null)
    {
        $this->lastData = $data;
        $this->lastStack = $stack;
    }

    public $lastData;
    public $lastStack;
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;
use Monolog\Logger;

class SyslogHandlerTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @covers Monolog\Handler\SyslogHandler::__construct
     */
    public function testConstruct()
    {
        $handler = new SyslogHandler('test');
        $this->assertInstanceOf('Monolog\Handler\SyslogHandler', $handler);

        $handler = new SyslogHandler('test', LOG_USER);
        $this->assertInstanceOf('Monolog\Handler\SyslogHandler', $handler);

        $handler = new SyslogHandler('test', 'user');
        $this->assertInstanceOf('Monolog\Handler\SyslogHandler', $handler);

        $handler = new SyslogHandler('test', LOG_USER, Logger::DEBUG, true, LOG_PERROR);
        $this->assertInstanceOf('Monolog\Handler\SyslogHandler', $handler);
    }

    /**
     * @covers Monolog\Handler\SyslogHandler::__construct
     */
    public function testConstructInvalidFacility()
    {
        $this->setExpectedException('UnexpectedValueException');
        $handler = new SyslogHandler('test', 'unknown');
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\TestCase;
use Monolog\Logger;

class CouchDBHandlerTest extends TestCase
{
    public function testHandle()
    {
        $record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34));

        $expected = array(
            'message' => 'test',
            'context' => array('data' => '[object] (stdClass: {})', 'foo' => 34),
            'level' => Logger::WARNING,
            'level_name' => 'WARNING',
            'channel' => 'test',
            'datetime' => $record['datetime']->format('Y-m-d H:i:s'),
            'extra' => array(),
        );

        $handler = new CouchDBHandler();

        try {
            $handler->handle($record);
        } catch (\RuntimeException $e) {
            $this->markTestSkipped('Could not connect to couchdb server on http://localhost:5984');
        }
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\TestCase;
use Monolog\Logger;

class BufferHandlerTest extends TestCase
{
    /**
     * @covers Monolog\Handler\BufferHandler::__construct
     * @covers Monolog\Handler\BufferHandler::handle
     * @covers Monolog\Handler\BufferHandler::close
     */
    public function testHandleBuffers()
    {
        $test = new TestHandler();
        $handler = new BufferHandler($test);
        $handler->handle($this->getRecord(Logger::DEBUG));
        $handler->handle($this->getRecord(Logger::INFO));
        $this->assertFalse($test->hasDebugRecords());
        $this->assertFalse($test->hasInfoRecords());
        $handler->close();
        $this->assertTrue($test->hasInfoRecords());
        $this->assertTrue(count($test->getRecords()) === 2);
    }

    /**
     * @covers Monolog\Handler\BufferHandler::close
     * @covers Monolog\Handler\BufferHandler::flush
     */
    public function testDestructPropagatesRecords()
    {
        $test = new TestHandler();
        $handler = new BufferHandler($test);
        $handler->handle($this->getRecord(Logger::WARNING));
        $handler->handle($this->getRecord(Logger::DEBUG));
        $handler->__destruct();
        $this->assertTrue($test->hasWarningRecords());
        $this->assertTrue($test->hasDebugRecords());
    }

    /**
     * @covers Monolog\Handler\BufferHandler::handle
     */
    public function testHandleBufferLimit()
    {
        $test = new TestHandler();
        $handler = new BufferHandler($test, 2);
        $handler->handle($this->getRecord(Logger::DEBUG));
        $handler->handle($this->getRecord(Logger::DEBUG));
        $handler->handle($this->getRecord(Logger::INFO));
        $handler->handle($this->getRecord(Logger::WARNING));
        $handler->close();
        $this->assertTrue($test->hasWarningRecords());
        $this->assertTrue($test->hasInfoRecords());
        $this->assertFalse($test->hasDebugRecords());
    }

    /**
     * @covers Monolog\Handler\BufferHandler::handle
     */
    public function testHandleBufferLimitWithFlushOnOverflow()
    {
        $test = new TestHandler();
        $handler = new BufferHandler($test, 3, Logger::DEBUG, true, true);

        // send two records
        $handler->handle($this->getRecord(Logger::DEBUG));
        $handler->handle($this->getRecord(Logger::DEBUG));
        $handler->handle($this->getRecord(Logger::DEBUG));
        $this->assertFalse($test->hasDebugRecords());
        $this->assertCount(0, $test->getRecords());

        // overflow
        $handler->handle($this->getRecord(Logger::INFO));
        $this->assertTrue($test->hasDebugRecords());
        $this->assertCount(3, $test->getRecords());

        // should buffer again
        $handler->handle($this->getRecord(Logger::WARNING));
        $this->assertCount(3, $test->getRecords());

        $handler->close();
        $this->assertCount(5, $test->getRecords());
        $this->assertTrue($test->hasWarningRecords());
        $this->assertTrue($test->hasInfoRecords());
    }

    /**
     * @covers Monolog\Handler\BufferHandler::handle
     */
    public function testHandleLevel()
    {
        $test = new TestHandler();
        $handler = new BufferHandler($test, 0, Logger::INFO);
        $handler->handle($this->getRecord(Logger::DEBUG));
        $handler->handle($this->getRecord(Logger::INFO));
        $handler->handle($this->getRecord(Logger::WARNING));
        $handler->handle($this->getRecord(Logger::DEBUG));
        $handler->close();
        $this->assertTrue($test->hasWarningRecords());
        $this->assertTrue($test->hasInfoRecords());
        $this->assertFalse($test->hasDebugRecords());
    }

    /**
     * @covers Monolog\Handler\BufferHandler::flush
     */
    public function testFlush()
    {
        $test = new TestHandler();
        $handler = new BufferHandler($test, 0);
        $handler->handle($this->getRecord(Logger::DEBUG));
        $handler->handle($this->getRecord(Logger::INFO));
        $handler->flush();
        $this->assertTrue($test->hasInfoRecords());
        $this->assertTrue($test->hasDebugRecords());
        $this->assertFalse($test->hasWarningRecords());
    }

    /**
     * @covers Monolog\Handler\BufferHandler::handle
     */
    public function testHandleUsesProcessors()
    {
        $test = new TestHandler();
        $handler = new BufferHandler($test);
        $handler->pushProcessor(function ($record) {
            $record['extra']['foo'] = true;

            return $record;
        });
        $handler->handle($this->getRecord(Logger::WARNING));
        $handler->flush();
        $this->assertTrue($test->hasWarningRecords());
        $records = $test->getRecords();
        $this->assertTrue($records[0]['extra']['foo']);
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\TestCase;
use Monolog\Logger;

/**
 * @author Pablo de Leon Belloc <pablolb@gmail.com>
 */
class SocketHandlerTest extends TestCase
{
    /**
     * @var Monolog\Handler\SocketHandler
     */
    private $handler;

    /**
     * @var resource
     */
    private $res;

    /**
     * @expectedException UnexpectedValueException
     */
    public function testInvalidHostname()
    {
        $this->createHandler('garbage://here');
        $this->writeRecord('data');
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testBadConnectionTimeout()
    {
        $this->createHandler('localhost:1234');
        $this->handler->setConnectionTimeout(-1);
    }

    public function testSetConnectionTimeout()
    {
        $this->createHandler('localhost:1234');
        $this->handler->setConnectionTimeout(10.1);
        $this->assertEquals(10.1, $this->handler->getConnectionTimeout());
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testBadTimeout()
    {
        $this->createHandler('localhost:1234');
        $this->handler->setTimeout(-1);
    }

    public function testSetTimeout()
    {
        $this->createHandler('localhost:1234');
        $this->handler->setTimeout(10.25);
        $this->assertEquals(10.25, $this->handler->getTimeout());
    }

    public function testSetConnectionString()
    {
        $this->createHandler('tcp://localhost:9090');
        $this->assertEquals('tcp://localhost:9090', $this->handler->getConnectionString());
    }

    /**
     * @expectedException UnexpectedValueException
     */
    public function testExceptionIsThrownOnFsockopenError()
    {
        $this->setMockHandler(array('fsockopen'));
        $this->handler->expects($this->once())
            ->method('fsockopen')
            ->will($this->returnValue(false));
        $this->writeRecord('Hello world');
    }

    /**
     * @expectedException UnexpectedValueException
     */
    public function testExceptionIsThrownOnPfsockopenError()
    {
        $this->setMockHandler(array('pfsockopen'));
        $this->handler->expects($this->once())
            ->method('pfsockopen')
            ->will($this->returnValue(false));
        $this->handler->setPersistent(true);
        $this->writeRecord('Hello world');
    }

    /**
     * @expectedException UnexpectedValueException
     */
    public function testExceptionIsThrownIfCannotSetTimeout()
    {
        $this->setMockHandler(array('streamSetTimeout'));
        $this->handler->expects($this->once())
            ->method('streamSetTimeout')
            ->will($this->returnValue(false));
        $this->writeRecord('Hello world');
    }

    /**
     * @expectedException RuntimeException
     */
    public function testWriteFailsOnIfFwriteReturnsFalse()
    {
        $this->setMockHandler(array('fwrite'));

        $callback = function($arg) {
            $map = array(
                'Hello world' => 6,
                'world' => false,
            );

            return $map[$arg];
        };

        $this->handler->expects($this->exactly(2))
            ->method('fwrite')
            ->will($this->returnCallback($callback));

        $this->writeRecord('Hello world');
    }

    /**
     * @expectedException RuntimeException
     */
    public function testWriteFailsIfStreamTimesOut()
    {
        $this->setMockHandler(array('fwrite', 'streamGetMetadata'));

        $callback = function($arg) {
            $map = array(
                'Hello world' => 6,
                'world' => 5,
            );

            return $map[$arg];
        };

        $this->handler->expects($this->exactly(1))
            ->method('fwrite')
            ->will($this->returnCallback($callback));
        $this->handler->expects($this->exactly(1))
            ->method('streamGetMetadata')
            ->will($this->returnValue(array('timed_out' => true)));

        $this->writeRecord('Hello world');
    }

    /**
     * @expectedException RuntimeException
     */
    public function testWriteFailsOnIncompleteWrite()
    {
        $this->setMockHandler(array('fwrite', 'streamGetMetadata'));

        $res = $this->res;
        $callback = function($string) use ($res) {
            fclose($res);

            return strlen('Hello');
        };

        $this->handler->expects($this->exactly(1))
            ->method('fwrite')
            ->will($this->returnCallback($callback));
        $this->handler->expects($this->exactly(1))
            ->method('streamGetMetadata')
            ->will($this->returnValue(array('timed_out' => false)));

        $this->writeRecord('Hello world');
    }

    public function testWriteWithMemoryFile()
    {
        $this->setMockHandler();
        $this->writeRecord('test1');
        $this->writeRecord('test2');
        $this->writeRecord('test3');
        fseek($this->res, 0);
        $this->assertEquals('test1test2test3', fread($this->res, 1024));
    }

    public function testWriteWithMock()
    {
        $this->setMockHandler(array('fwrite'));

        $callback = function($arg) {
            $map = array(
                'Hello world' => 6,
                'world' => 5,
            );

            return $map[$arg];
        };

        $this->handler->expects($this->exactly(2))
            ->method('fwrite')
            ->will($this->returnCallback($callback));

        $this->writeRecord('Hello world');
    }

    public function testClose()
    {
        $this->setMockHandler();
        $this->writeRecord('Hello world');
        $this->assertInternalType('resource', $this->res);
        $this->handler->close();
        $this->assertFalse(is_resource($this->res), "Expected resource to be closed after closing handler");
    }

    public function testCloseDoesNotClosePersistentSocket()
    {
        $this->setMockHandler();
        $this->handler->setPersistent(true);
        $this->writeRecord('Hello world');
        $this->assertTrue(is_resource($this->res));
        $this->handler->close();
        $this->assertTrue(is_resource($this->res));
    }

    private function createHandler($connectionString)
    {
        $this->handler = new SocketHandler($connectionString);
        $this->handler->setFormatter($this->getIdentityFormatter());
    }

    private function writeRecord($string)
    {
        $this->handler->handle($this->getRecord(Logger::WARNING, $string));
    }

    private function setMockHandler(array $methods = array())
    {
        $this->res = fopen('php://memory', 'a');

        $defaultMethods = array('fsockopen', 'pfsockopen', 'streamSetTimeout');
        $newMethods = array_diff($methods, $defaultMethods);

        $finalMethods = array_merge($defaultMethods, $newMethods);

        $this->handler = $this->getMock(
            '\Monolog\Handler\SocketHandler', $finalMethods, array('localhost:1234')
        );

        if (!in_array('fsockopen', $methods)) {
            $this->handler->expects($this->any())
                ->method('fsockopen')
                ->will($this->returnValue($this->res));
        }

        if (!in_array('pfsockopen', $methods)) {
            $this->handler->expects($this->any())
                ->method('pfsockopen')
                ->will($this->returnValue($this->res));
        }

        if (!in_array('streamSetTimeout', $methods)) {
            $this->handler->expects($this->any())
                ->method('streamSetTimeout')
                ->will($this->returnValue(true));
        }

        $this->handler->setFormatter($this->getIdentityFormatter());
    }

}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\TestCase;
use Monolog\Logger;
use Monolog\Formatter\LineFormatter;
use Monolog\Processor\WebProcessor;

class AbstractHandlerTest extends TestCase
{
    /**
     * @covers Monolog\Handler\AbstractHandler::__construct
     * @covers Monolog\Handler\AbstractHandler::getLevel
     * @covers Monolog\Handler\AbstractHandler::setLevel
     * @covers Monolog\Handler\AbstractHandler::getBubble
     * @covers Monolog\Handler\AbstractHandler::setBubble
     * @covers Monolog\Handler\AbstractHandler::getFormatter
     * @covers Monolog\Handler\AbstractHandler::setFormatter
     */
    public function testConstructAndGetSet()
    {
        $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler', array(Logger::WARNING, false));
        $this->assertEquals(Logger::WARNING, $handler->getLevel());
        $this->assertEquals(false, $handler->getBubble());

        $handler->setLevel(Logger::ERROR);
        $handler->setBubble(true);
        $handler->setFormatter($formatter = new LineFormatter);
        $this->assertEquals(Logger::ERROR, $handler->getLevel());
        $this->assertEquals(true, $handler->getBubble());
        $this->assertSame($formatter, $handler->getFormatter());
    }

    /**
     * @covers Monolog\Handler\AbstractHandler::handleBatch
     */
    public function testHandleBatch()
    {
        $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler');
        $handler->expects($this->exactly(2))
            ->method('handle');
        $handler->handleBatch(array($this->getRecord(), $this->getRecord()));
    }

    /**
     * @covers Monolog\Handler\AbstractHandler::isHandling
     */
    public function testIsHandling()
    {
        $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler', array(Logger::WARNING, false));
        $this->assertTrue($handler->isHandling($this->getRecord()));
        $this->assertFalse($handler->isHandling($this->getRecord(Logger::DEBUG)));
    }

    /**
     * @covers Monolog\Handler\AbstractHandler::getFormatter
     * @covers Monolog\Handler\AbstractHandler::getDefaultFormatter
     */
    public function testGetFormatterInitializesDefault()
    {
        $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler');
        $this->assertInstanceOf('Monolog\Formatter\LineFormatter', $handler->getFormatter());
    }

    /**
     * @covers Monolog\Handler\AbstractHandler::pushProcessor
     * @covers Monolog\Handler\AbstractHandler::popProcessor
     * @expectedException LogicException
     */
    public function testPushPopProcessor()
    {
        $logger = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler');
        $processor1 = new WebProcessor;
        $processor2 = new WebProcessor;

        $logger->pushProcessor($processor1);
        $logger->pushProcessor($processor2);

        $this->assertEquals($processor2, $logger->popProcessor());
        $this->assertEquals($processor1, $logger->popProcessor());
        $logger->popProcessor();
    }

    /**
     * @covers Monolog\Handler\AbstractHandler::pushProcessor
     * @expectedException InvalidArgumentException
     */
    public function testPushProcessorWithNonCallable()
    {
        $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractHandler');

        $handler->pushProcessor(new \stdClass());
    }
}
<?php
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\TestCase;

class ZendMonitorHandlerTest extends TestCase
{
    protected $zendMonitorHandler;

    public function setUp()
    {
        if (!function_exists('zend_monitor_custom_event')) {
            $this->markTestSkipped('ZendServer is not installed');
        }
    }

    /**
     * @covers  Monolog\Handler\ZendMonitorHandler::write
     */
    public function testWrite()
    {
        $record = $this->getRecord();
        $formatterResult = array(
            'message' => $record['message']
        );

        $zendMonitor = $this->getMockBuilder('Monolog\Handler\ZendMonitorHandler')
            ->setMethods(array('writeZendMonitorCustomEvent', 'getDefaultFormatter'))
            ->getMock();

        $formatterMock = $this->getMockBuilder('Monolog\Formatter\NormalizerFormatter')
            ->disableOriginalConstructor()
            ->getMock();

        $formatterMock->expects($this->once())
            ->method('format')
            ->will($this->returnValue($formatterResult));

        $zendMonitor->expects($this->once())
            ->method('getDefaultFormatter')
            ->will($this->returnValue($formatterMock));

        $levelMap = $zendMonitor->getLevelMap();

        $zendMonitor->expects($this->once())
            ->method('writeZendMonitorCustomEvent')
            ->with($levelMap[$record['level']], $record['message'], $formatterResult);

        $zendMonitor->handle($record);
    }

    /**
     * @covers Monolog\Handler\ZendMonitorHandler::getDefaultFormatter
     */
    public function testGetDefaultFormatterReturnsNormalizerFormatter()
    {
        $zendMonitor = new ZendMonitorHandler();
        $this->assertInstanceOf('Monolog\Formatter\NormalizerFormatter', $zendMonitor->getDefaultFormatter());
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\TestCase;
use Monolog\Logger;

class MongoDBHandlerTest extends TestCase
{
    /**
     * @expectedException InvalidArgumentException
     */
    public function testConstructorShouldThrowExceptionForInvalidMongo()
    {
        new MongoDBHandler(new \stdClass(), 'DB', 'Collection');
    }

    public function testHandle()
    {
        $mongo = $this->getMock('Mongo', array('selectCollection'));
        $collection = $this->getMock('stdClass', array('save'));

        $mongo->expects($this->once())
            ->method('selectCollection')
            ->with('DB', 'Collection')
            ->will($this->returnValue($collection));

        $record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34));

        $expected = array(
            'message' => 'test',
            'context' => array('data' => '[object] (stdClass: {})', 'foo' => 34),
            'level' => Logger::WARNING,
            'level_name' => 'WARNING',
            'channel' => 'test',
            'datetime' => $record['datetime']->format('Y-m-d H:i:s'),
            'extra' => array(),
        );

        $collection->expects($this->once())
            ->method('save')
            ->with($expected);

        $handler = new MongoDBHandler($mongo, 'DB', 'Collection');
        $handler->handle($record);
    }
}

if (!class_exists('Mongo')) {
    class Mongo
    {
        public function selectCollection() {}
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

class AmqpExchangeMock extends \AMQPExchange
{
    protected $messages = array();

    public function __construct()
    {
    }

    public function publish($message, $routing_key, $params = 0, $attributes = array())
    {
        $this->messages[] = array($message, $routing_key, $params, $attributes);

        return true;
    }

    public function getMessages()
    {
        return $this->messages;
    }

    public function setName($name)
    {
        return true;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\TestCase;
use Monolog\Logger;
use Monolog\Formatter\LineFormatter;

class RedisHandlerTest extends TestCase
{
    /**
     * @expectedException InvalidArgumentException
     */
    public function testConstructorShouldThrowExceptionForInvalidRedis()
    {
        new RedisHandler(new \stdClass(), 'key');
    }

    public function testConstructorShouldWorkWithPredis()
    {
        $redis = $this->getMock('Predis\Client');
        $this->assertInstanceof('Monolog\Handler\RedisHandler', new RedisHandler($redis, 'key'));
    }

    public function testConstructorShouldWorkWithRedis()
    {
        $redis = $this->getMock('Redis');
        $this->assertInstanceof('Monolog\Handler\RedisHandler', new RedisHandler($redis, 'key'));
    }

    public function testPredisHandle()
    {
        $redis = $this->getMock('Predis\Client', array('rpush'));

        // Predis\Client uses rpush
        $redis->expects($this->once())
            ->method('rpush')
            ->with('key', 'test');

        $record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34));

        $handler = new RedisHandler($redis, 'key');
        $handler->setFormatter(new LineFormatter("%message%"));
        $handler->handle($record);
    }

    public function testRedisHandle()
    {
        $redis = $this->getMock('Redis', array('rpush'));

        // Redis uses rPush
        $redis->expects($this->once())
            ->method('rPush')
            ->with('key', 'test');

        $record = $this->getRecord(Logger::WARNING, 'test', array('data' => new \stdClass, 'foo' => 34));

        $handler = new RedisHandler($redis, 'key');
        $handler->setFormatter(new LineFormatter("%message%"));
        $handler->handle($record);
    }
}
<?php

namespace Monolog\Handler;

use Monolog\TestCase;

class UdpSocketTest extends TestCase
{
    public function testWeDoNotSplitShortMessages()
    {
        $socket = $this->getMock('\Monolog\Handler\SyslogUdp\UdpSocket', array('send'), array('lol', 'lol'));

        $socket->expects($this->at(0))
            ->method('send')
            ->with("HEADER: The quick brown fox jumps over the lazy dog");

        $socket->write("The quick brown fox jumps over the lazy dog", "HEADER: ");
    }

    public function testWeSplitLongMessages()
    {
        $socket = $this->getMock('\Monolog\Handler\SyslogUdp\UdpSocket', array('send'), array('lol', 'lol'));

        $socket->expects($this->at(1))
            ->method('send')
            ->with("The quick brown fox jumps over the lazy dog");

        $aStringOfLength2048 = str_repeat("derp", 2048/4);

        $socket->write($aStringOfLength2048."The quick brown fox jumps over the lazy dog");
    }

    public function testAllSplitMessagesHasAHeader()
    {
        $socket = $this->getMock('\Monolog\Handler\SyslogUdp\UdpSocket', array('send'), array('lol', 'lol'));

        $socket->expects($this->exactly(5))
            ->method('send')
            ->with($this->stringStartsWith("HEADER"));

        $aStringOfLength8192 = str_repeat("derp", 2048);

        $socket->write($aStringOfLength8192, "HEADER");
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\TestCase;
use Monolog\Logger;

/**
 * @covers Monolog\Handler\FirePHPHandler
 */
class FirePHPHandlerTest extends TestCase
{
    public function setUp()
    {
        TestFirePHPHandler::reset();
    }

    public function testHeaders()
    {
        $handler = new TestFirePHPHandler;
        $handler->setFormatter($this->getIdentityFormatter());
        $handler->handle($this->getRecord(Logger::DEBUG));
        $handler->handle($this->getRecord(Logger::WARNING));

        $expected = array(
            'X-Wf-Protocol-1'    => 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2',
            'X-Wf-1-Structure-1' => 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1',
            'X-Wf-1-Plugin-1'    => 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3',
            'X-Wf-1-1-1-1'       => 'test',
            'X-Wf-1-1-1-2'       => 'test',
        );

        $this->assertEquals($expected, $handler->getHeaders());
    }

    public function testConcurrentHandlers()
    {
        $handler = new TestFirePHPHandler;
        $handler->setFormatter($this->getIdentityFormatter());
        $handler->handle($this->getRecord(Logger::DEBUG));
        $handler->handle($this->getRecord(Logger::WARNING));

        $handler2 = new TestFirePHPHandler;
        $handler2->setFormatter($this->getIdentityFormatter());
        $handler2->handle($this->getRecord(Logger::DEBUG));
        $handler2->handle($this->getRecord(Logger::WARNING));

        $expected = array(
            'X-Wf-Protocol-1'    => 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2',
            'X-Wf-1-Structure-1' => 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1',
            'X-Wf-1-Plugin-1'    => 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3',
            'X-Wf-1-1-1-1'       => 'test',
            'X-Wf-1-1-1-2'       => 'test',
        );

        $expected2 = array(
            'X-Wf-1-1-1-3'       => 'test',
            'X-Wf-1-1-1-4'       => 'test',
        );

        $this->assertEquals($expected, $handler->getHeaders());
        $this->assertEquals($expected2, $handler2->getHeaders());
    }
}

class TestFirePHPHandler extends FirePHPHandler
{
    protected $headers = array();

    public static function reset()
    {
        self::$initialized = false;
        self::$messageIndex = 1;
    }

    protected function sendHeader($header, $content)
    {
        $this->headers[$header] = $content;
    }

    public function getHeaders()
    {
        return $this->headers;
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\TestCase;
use Monolog\Logger;

class GroupHandlerTest extends TestCase
{
    /**
     * @covers Monolog\Handler\GroupHandler::__construct
     * @expectedException InvalidArgumentException
     */
    public function testConstructorOnlyTakesHandler()
    {
        new GroupHandler(array(new TestHandler(), "foo"));
    }

    /**
     * @covers Monolog\Handler\GroupHandler::__construct
     * @covers Monolog\Handler\GroupHandler::handle
     */
    public function testHandle()
    {
        $testHandlers = array(new TestHandler(), new TestHandler());
        $handler = new GroupHandler($testHandlers);
        $handler->handle($this->getRecord(Logger::DEBUG));
        $handler->handle($this->getRecord(Logger::INFO));
        foreach ($testHandlers as $test) {
            $this->assertTrue($test->hasDebugRecords());
            $this->assertTrue($test->hasInfoRecords());
            $this->assertTrue(count($test->getRecords()) === 2);
        }
    }

    /**
     * @covers Monolog\Handler\GroupHandler::handleBatch
     */
    public function testHandleBatch()
    {
        $testHandlers = array(new TestHandler(), new TestHandler());
        $handler = new GroupHandler($testHandlers);
        $handler->handleBatch(array($this->getRecord(Logger::DEBUG), $this->getRecord(Logger::INFO)));
        foreach ($testHandlers as $test) {
            $this->assertTrue($test->hasDebugRecords());
            $this->assertTrue($test->hasInfoRecords());
            $this->assertTrue(count($test->getRecords()) === 2);
        }
    }

    /**
     * @covers Monolog\Handler\GroupHandler::isHandling
     */
    public function testIsHandling()
    {
        $testHandlers = array(new TestHandler(Logger::ERROR), new TestHandler(Logger::WARNING));
        $handler = new GroupHandler($testHandlers);
        $this->assertTrue($handler->isHandling($this->getRecord(Logger::ERROR)));
        $this->assertTrue($handler->isHandling($this->getRecord(Logger::WARNING)));
        $this->assertFalse($handler->isHandling($this->getRecord(Logger::DEBUG)));
    }

    /**
     * @covers Monolog\Handler\GroupHandler::handle
     */
    public function testHandleUsesProcessors()
    {
        $test = new TestHandler();
        $handler = new GroupHandler(array($test));
        $handler->pushProcessor(function ($record) {
            $record['extra']['foo'] = true;

            return $record;
        });
        $handler->handle($this->getRecord(Logger::WARNING));
        $this->assertTrue($test->hasWarningRecords());
        $records = $test->getRecords();
        $this->assertTrue($records[0]['extra']['foo']);
    }
}
<?php

namespace Monolog\Handler;

use Monolog\TestCase;

class SyslogUdpHandlerTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @expectedException UnexpectedValueException
     */
    public function testWeValidateFacilities()
    {
        $handler = new SyslogUdpHandler("ip", null, "invalidFacility");
    }

    public function testWeSplitIntoLines()
    {
        $handler = new SyslogUdpHandler("127.0.0.1", 514, "local5");
        $handler->setFormatter(new \Monolog\Formatter\ChromePHPFormatter());

        $socket = $this->getMock('\Monolog\Handler\SyslogUdp\UdpSocket', array('write'), array('lol', 'lol'));
        $socket->expects($this->at(0))
            ->method('write')
            ->with("lol", "<172>: ");
        $socket->expects($this->at(1))
            ->method('write')
            ->with("hej", "<172>: ");

        $handler->setSocket($socket);

        $handler->handle($this->getRecordWithMessage("hej\nlol"));
    }

    protected function getRecordWithMessage($msg)
    {
        return array('message' => $msg, 'level' => \Monolog\Logger::WARNING, 'context' => null, 'extra' => array(), 'channel' => 'lol');
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\TestCase;
use Monolog\Logger;
use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
use Monolog\Handler\FingersCrossed\ChannelLevelActivationStrategy;

class FingersCrossedHandlerTest extends TestCase
{
    /**
     * @covers Monolog\Handler\FingersCrossedHandler::__construct
     * @covers Monolog\Handler\FingersCrossedHandler::handle
     */
    public function testHandleBuffers()
    {
        $test = new TestHandler();
        $handler = new FingersCrossedHandler($test);
        $handler->handle($this->getRecord(Logger::DEBUG));
        $handler->handle($this->getRecord(Logger::INFO));
        $this->assertFalse($test->hasDebugRecords());
        $this->assertFalse($test->hasInfoRecords());
        $handler->handle($this->getRecord(Logger::WARNING));
        $this->assertTrue($test->hasInfoRecords());
        $this->assertTrue(count($test->getRecords()) === 3);
    }

    /**
     * @covers Monolog\Handler\FingersCrossedHandler::handle
     */
    public function testHandleStopsBufferingAfterTrigger()
    {
        $test = new TestHandler();
        $handler = new FingersCrossedHandler($test);
        $handler->handle($this->getRecord(Logger::WARNING));
        $handler->handle($this->getRecord(Logger::DEBUG));
        $this->assertTrue($test->hasWarningRecords());
        $this->assertTrue($test->hasDebugRecords());
    }

    /**
     * @covers Monolog\Handler\FingersCrossedHandler::handle
     * @covers Monolog\Handler\FingersCrossedHandler::reset
     */
    public function testHandleRestartBufferingAfterReset()
    {
        $test = new TestHandler();
        $handler = new FingersCrossedHandler($test);
        $handler->handle($this->getRecord(Logger::WARNING));
        $handler->handle($this->getRecord(Logger::DEBUG));
        $handler->reset();
        $handler->handle($this->getRecord(Logger::INFO));
        $this->assertTrue($test->hasWarningRecords());
        $this->assertTrue($test->hasDebugRecords());
        $this->assertFalse($test->hasInfoRecords());
    }

    /**
     * @covers Monolog\Handler\FingersCrossedHandler::handle
     */
    public function testHandleRestartBufferingAfterBeingTriggeredWhenStopBufferingIsDisabled()
    {
        $test = new TestHandler();
        $handler = new FingersCrossedHandler($test, Logger::WARNING, 0, false, false);
        $handler->handle($this->getRecord(Logger::DEBUG));
        $handler->handle($this->getRecord(Logger::WARNING));
        $handler->handle($this->getRecord(Logger::INFO));
        $this->assertTrue($test->hasWarningRecords());
        $this->assertTrue($test->hasDebugRecords());
        $this->assertFalse($test->hasInfoRecords());
    }

    /**
     * @covers Monolog\Handler\FingersCrossedHandler::handle
     */
    public function testHandleBufferLimit()
    {
        $test = new TestHandler();
        $handler = new FingersCrossedHandler($test, Logger::WARNING, 2);
        $handler->handle($this->getRecord(Logger::DEBUG));
        $handler->handle($this->getRecord(Logger::DEBUG));
        $handler->handle($this->getRecord(Logger::INFO));
        $handler->handle($this->getRecord(Logger::WARNING));
        $this->assertTrue($test->hasWarningRecords());
        $this->assertTrue($test->hasInfoRecords());
        $this->assertFalse($test->hasDebugRecords());
    }

    /**
     * @covers Monolog\Handler\FingersCrossedHandler::handle
     */
    public function testHandleWithCallback()
    {
        $test = new TestHandler();
        $handler = new FingersCrossedHandler(function($record, $handler) use ($test) {
                    return $test;
                });
        $handler->handle($this->getRecord(Logger::DEBUG));
        $handler->handle($this->getRecord(Logger::INFO));
        $this->assertFalse($test->hasDebugRecords());
        $this->assertFalse($test->hasInfoRecords());
        $handler->handle($this->getRecord(Logger::WARNING));
        $this->assertTrue($test->hasInfoRecords());
        $this->assertTrue(count($test->getRecords()) === 3);
    }

    /**
     * @covers Monolog\Handler\FingersCrossedHandler::handle
     * @expectedException RuntimeException
     */
    public function testHandleWithBadCallbackThrowsException()
    {
        $handler = new FingersCrossedHandler(function($record, $handler) {
                    return 'foo';
                });
        $handler->handle($this->getRecord(Logger::WARNING));
    }

    /**
     * @covers Monolog\Handler\FingersCrossedHandler::isHandling
     */
    public function testIsHandlingAlways()
    {
        $test = new TestHandler();
        $handler = new FingersCrossedHandler($test, Logger::ERROR);
        $this->assertTrue($handler->isHandling($this->getRecord(Logger::DEBUG)));
    }

    /**
     * @covers Monolog\Handler\FingersCrossedHandler::__construct
     * @covers Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy::__construct
     * @covers Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy::isHandlerActivated
     */
    public function testErrorLevelActivationStrategy()
    {
        $test = new TestHandler();
        $handler = new FingersCrossedHandler($test, new ErrorLevelActivationStrategy(Logger::WARNING));
        $handler->handle($this->getRecord(Logger::DEBUG));
        $this->assertFalse($test->hasDebugRecords());
        $handler->handle($this->getRecord(Logger::WARNING));
        $this->assertTrue($test->hasDebugRecords());
        $this->assertTrue($test->hasWarningRecords());
    }

    /**
     * @covers Monolog\Handler\FingersCrossed\ChannelLevelActivationStrategy::__construct
     * @covers Monolog\Handler\FingersCrossed\ChannelLevelActivationStrategy::isHandlerActivated
     */
    public function testChannelLevelActivationStrategy()
    {
        $test = new TestHandler();
        $handler = new FingersCrossedHandler($test, new ChannelLevelActivationStrategy(Logger::ERROR, array('othertest' => Logger::DEBUG)));
        $handler->handle($this->getRecord(Logger::WARNING));
        $this->assertFalse($test->hasWarningRecords());
        $record = $this->getRecord(Logger::DEBUG);
        $record['channel'] = 'othertest';
        $handler->handle($record);
        $this->assertTrue($test->hasDebugRecords());
        $this->assertTrue($test->hasWarningRecords());
    }

    /**
     * @covers Monolog\Handler\FingersCrossedHandler::handle
     */
    public function testHandleUsesProcessors()
    {
        $test = new TestHandler();
        $handler = new FingersCrossedHandler($test, Logger::INFO);
        $handler->pushProcessor(function ($record) {
            $record['extra']['foo'] = true;

            return $record;
        });
        $handler->handle($this->getRecord(Logger::WARNING));
        $this->assertTrue($test->hasWarningRecords());
        $records = $test->getRecords();
        $this->assertTrue($records[0]['extra']['foo']);
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\TestCase;
use Monolog\Logger;

/**
 * @author Rafael Dohms <rafael@doh.ms>
 * @see    https://www.hipchat.com/docs/api
 */
class HipChatHandlerTest extends TestCase
{

    private $res;
    private $handler;

    public function testWriteHeader()
    {
        $this->createHandler();
        $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
        fseek($this->res, 0);
        $content = fread($this->res, 1024);

        $this->assertRegexp('/POST \/v1\/rooms\/message\?format=json&auth_token=.* HTTP\/1.1\\r\\nHost: api.hipchat.com\\r\\nContent-Type: application\/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content);

        return $content;
    }

    /**
     * @depends testWriteHeader
     */
    public function testWriteContent($content)
    {
        $this->assertRegexp('/from=Monolog&room_id=room1&notify=0&message=test1&message_format=text&color=red$/', $content);
    }

    public function testWriteWithComplexMessage()
    {
        $this->createHandler();
        $this->handler->handle($this->getRecord(Logger::CRITICAL, 'Backup of database "example" finished in 16 minutes.'));
        fseek($this->res, 0);
        $content = fread($this->res, 1024);

        $this->assertRegexp('/message=Backup\+of\+database\+%22example%22\+finished\+in\+16\+minutes\./', $content);
    }

    /**
     * @dataProvider provideLevelColors
     */
    public function testWriteWithErrorLevelsAndColors($level, $expectedColor)
    {
        $this->createHandler();
        $this->handler->handle($this->getRecord($level, 'Backup of database "example" finished in 16 minutes.'));
        fseek($this->res, 0);
        $content = fread($this->res, 1024);

        $this->assertRegexp('/color='.$expectedColor.'/', $content);
    }

    public function provideLevelColors()
    {
        return array(
            array(Logger::DEBUG,    'gray'),
            array(Logger::INFO,     'green'),
            array(Logger::WARNING,  'yellow'),
            array(Logger::ERROR,    'red'),
            array(Logger::CRITICAL, 'red'),
            array(Logger::ALERT,    'red'),
            array(Logger::EMERGENCY,'red'),
            array(Logger::NOTICE,   'green'),
        );
    }

    /**
     * @dataProvider provideBatchRecords
     */
    public function testHandleBatch($records, $expectedColor)
    {
        $this->createHandler();

        $this->handler->handleBatch($records);

        fseek($this->res, 0);
        $content = fread($this->res, 1024);

        $this->assertRegexp('/color='.$expectedColor.'/', $content);
    }

    public function provideBatchRecords()
    {
        return array(
            array(
                array(
                    array('level' => Logger::WARNING, 'message' => 'Oh bugger!', 'level_name' => 'warning', 'datetime' => new \DateTime()),
                    array('level' => Logger::NOTICE, 'message' => 'Something noticeable happened.', 'level_name' => 'notice', 'datetime' => new \DateTime()),
                    array('level' => Logger::CRITICAL, 'message' => 'Everything is broken!', 'level_name' => 'critical', 'datetime' => new \DateTime())
                ),
                'red',
            ),
            array(
                array(
                    array('level' => Logger::WARNING, 'message' => 'Oh bugger!', 'level_name' => 'warning', 'datetime' => new \DateTime()),
                    array('level' => Logger::NOTICE, 'message' => 'Something noticeable happened.', 'level_name' => 'notice', 'datetime' => new \DateTime()),
                ),
                'yellow',
            ),
            array(
                array(
                    array('level' => Logger::DEBUG, 'message' => 'Just debugging.', 'level_name' => 'debug', 'datetime' => new \DateTime()),
                    array('level' => Logger::NOTICE, 'message' => 'Something noticeable happened.', 'level_name' => 'notice', 'datetime' => new \DateTime()),
                ),
                'green',
            ),
            array(
                array(
                    array('level' => Logger::DEBUG, 'message' => 'Just debugging.', 'level_name' => 'debug', 'datetime' => new \DateTime()),
                ),
                'gray',
            ),
        );
    }

    private function createHandler($token = 'myToken', $room = 'room1', $name = 'Monolog', $notify = false)
    {
        $constructorArgs = array($token, $room, $name, $notify, Logger::DEBUG);
        $this->res = fopen('php://memory', 'a');
        $this->handler = $this->getMock(
            '\Monolog\Handler\HipChatHandler',
            array('fsockopen', 'streamSetTimeout', 'closeSocket'),
            $constructorArgs
        );

        $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString');
        $reflectionProperty->setAccessible(true);
        $reflectionProperty->setValue($this->handler, 'localhost:1234');

        $this->handler->expects($this->any())
            ->method('fsockopen')
            ->will($this->returnValue($this->res));
        $this->handler->expects($this->any())
            ->method('streamSetTimeout')
            ->will($this->returnValue(true));
        $this->handler->expects($this->any())
            ->method('closeSocket')
            ->will($this->returnValue(true));

        $this->handler->setFormatter($this->getIdentityFormatter());
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\TestCase;
use Monolog\Logger;
use Monolog\Formatter\GelfMessageFormatter;

class GelfHandlerTest extends TestCase
{
    public function setUp()
    {
        if (!class_exists("Gelf\MessagePublisher") || !class_exists("Gelf\Message")) {
            $this->markTestSkipped("mlehner/gelf-php not installed");
        }

        require_once __DIR__ . '/GelfMocks.php';
    }

    /**
     * @covers Monolog\Handler\GelfHandler::__construct
     */
    public function testConstruct()
    {
        $handler = new GelfHandler($this->getMessagePublisher());
        $this->assertInstanceOf('Monolog\Handler\GelfHandler', $handler);
    }

    protected function getHandler($messagePublisher)
    {
        $handler = new GelfHandler($messagePublisher);

        return $handler;
    }

    protected function getMessagePublisher()
    {
        return new MockMessagePublisher('localhost');
    }

    public function testDebug()
    {
        $messagePublisher = $this->getMessagePublisher();
        $handler = $this->getHandler($messagePublisher);

        $record = $this->getRecord(Logger::DEBUG, "A test debug message");
        $handler->handle($record);

        $this->assertEquals(7, $messagePublisher->lastMessage->getLevel());
        $this->assertEquals('test', $messagePublisher->lastMessage->getFacility());
        $this->assertEquals($record['message'], $messagePublisher->lastMessage->getShortMessage());
        $this->assertEquals(null, $messagePublisher->lastMessage->getFullMessage());
    }

    public function testWarning()
    {
        $messagePublisher = $this->getMessagePublisher();
        $handler = $this->getHandler($messagePublisher);

        $record = $this->getRecord(Logger::WARNING, "A test warning message");
        $handler->handle($record);

        $this->assertEquals(4, $messagePublisher->lastMessage->getLevel());
        $this->assertEquals('test', $messagePublisher->lastMessage->getFacility());
        $this->assertEquals($record['message'], $messagePublisher->lastMessage->getShortMessage());
        $this->assertEquals(null, $messagePublisher->lastMessage->getFullMessage());
    }

    public function testInjectedGelfMessageFormatter()
    {
        $messagePublisher = $this->getMessagePublisher();
        $handler = $this->getHandler($messagePublisher);

        $handler->setFormatter(new GelfMessageFormatter('mysystem', 'EXT', 'CTX'));

        $record = $this->getRecord(Logger::WARNING, "A test warning message");
        $record['extra']['blarg'] = 'yep';
        $record['context']['from'] = 'logger';
        $handler->handle($record);

        $this->assertEquals('mysystem', $messagePublisher->lastMessage->getHost());
        $this->assertArrayHasKey('_EXTblarg', $messagePublisher->lastMessage->toArray());
        $this->assertArrayHasKey('_CTXfrom', $messagePublisher->lastMessage->toArray());
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Handler\ElasticSearchHandler;
use Monolog\Formatter\ElasticaFormatter;
use Monolog\Formatter\NormalizerFormatter;
use Monolog\TestCase;
use Monolog\Logger;
use Elastica\Client;
use Elastica\Request;
use Elastica\Response;

class ElasticSearchHandlerTest extends TestCase
{
    /**
     * @var Client mock
     */
    protected $client;

    /**
     * @var array Default handler options
     */
    protected $options = array(
        'index' => 'my_index',
        'type'  => 'doc_type',
    );

    public function setUp()
    {
        // Elastica lib required
        if (!class_exists("Elastica\Client")) {
            $this->markTestSkipped("ruflin/elastica not installed");
        }

        // base mock Elastica Client object
        $this->client = $this->getMockBuilder('Elastica\Client')
            ->setMethods(array('addDocuments'))
            ->disableOriginalConstructor()
            ->getMock();
    }

    /**
     * @covers Monolog\Handler\ElasticSearchHandler::write
     * @covers Monolog\Handler\ElasticSearchHandler::handleBatch
     * @covers Monolog\Handler\ElasticSearchHandler::bulkSend
     * @covers Monolog\Handler\ElasticSearchHandler::getDefaultFormatter
     */
    public function testHandle()
    {
        // log message
        $msg = array(
            'level' => Logger::ERROR,
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'context' => array('foo' => 7, 'bar', 'class' => new \stdClass),
            'datetime' => new \DateTime("@0"),
            'extra' => array(),
            'message' => 'log',
        );

        // format expected result
        $formatter = new ElasticaFormatter($this->options['index'], $this->options['type']);
        $expected = array($formatter->format($msg));

        // setup ES client mock
        $this->client->expects($this->any())
            ->method('addDocuments')
            ->with($expected);

        // perform tests
        $handler = new ElasticSearchHandler($this->client, $this->options);
        $handler->handle($msg);
        $handler->handleBatch(array($msg));
    }

    /**
     * @covers Monolog\Handler\ElasticSearchHandler::setFormatter
     */
    public function testSetFormatter()
    {
        $handler = new ElasticSearchHandler($this->client);
        $formatter = new ElasticaFormatter('index_new', 'type_new');
        $handler->setFormatter($formatter);
        $this->assertInstanceOf('Monolog\Formatter\ElasticaFormatter', $handler->getFormatter());
        $this->assertEquals('index_new', $handler->getFormatter()->getIndex());
        $this->assertEquals('type_new', $handler->getFormatter()->getType());
    }

    /**
     * @covers                   Monolog\Handler\ElasticSearchHandler::setFormatter
     * @expectedException        InvalidArgumentException
     * @expectedExceptionMessage ElasticSearchHandler is only compatible with ElasticaFormatter
     */
    public function testSetFormatterInvalid()
    {
        $handler = new ElasticSearchHandler($this->client);
        $formatter = new NormalizerFormatter();
        $handler->setFormatter($formatter);
    }

    /**
     * @covers Monolog\Handler\ElasticSearchHandler::__construct
     * @covers Monolog\Handler\ElasticSearchHandler::getOptions
     */
    public function testOptions()
    {
        $expected = array(
            'index' => $this->options['index'],
            'type' => $this->options['type'],
            'ignore_error' => false,
        );
        $handler = new ElasticSearchHandler($this->client, $this->options);
        $this->assertEquals($expected, $handler->getOptions());
    }

    /**
     * @covers       Monolog\Handler\ElasticSearchHandler::bulkSend
     * @dataProvider providerTestConnectionErrors
     */
    public function testConnectionErrors($ignore, $expectedError)
    {
        $clientOpts = array('host' => '127.0.0.1', 'port' => 1);
        $client = new Client($clientOpts);
        $handlerOpts = array('ignore_error' => $ignore);
        $handler = new ElasticSearchHandler($client, $handlerOpts);

        if ($expectedError) {
            $this->setExpectedException($expectedError[0], $expectedError[1]);
            $handler->handle($this->getRecord());
        } else {
            $this->assertFalse($handler->handle($this->getRecord()));
        }
    }

    /**
     * @return array
     */
    public function providerTestConnectionErrors()
    {
        return array(
            array(false, array('RuntimeException', 'Error sending messages to Elasticsearch')),
            array(true, false),
        );
    }

    /**
     * Integration test using localhost Elastic Search server
     *
     * @covers Monolog\Handler\ElasticSearchHandler::__construct
     * @covers Monolog\Handler\ElasticSearchHandler::handleBatch
     * @covers Monolog\Handler\ElasticSearchHandler::bulkSend
     * @covers Monolog\Handler\ElasticSearchHandler::getDefaultFormatter
     */
    public function testHandleIntegration()
    {
        $msg = array(
            'level' => Logger::ERROR,
            'level_name' => 'ERROR',
            'channel' => 'meh',
            'context' => array('foo' => 7, 'bar', 'class' => new \stdClass),
            'datetime' => new \DateTime("@0"),
            'extra' => array(),
            'message' => 'log',
        );

        $expected = $msg;
        $expected['datetime'] = $msg['datetime']->format(\DateTime::ISO8601);
        $expected['context'] = array(
            'class' => '[object] (stdClass: {})',
            'foo' => 7,
            0 => 'bar',
        );

        $client = new Client();
        $handler = new ElasticSearchHandler($client, $this->options);
        try {
            $handler->handleBatch(array($msg));
        } catch(\RuntimeException $e) {
            $this->markTestSkipped("Cannot connect to Elastic Search server on localhost");
        }

        // check document id from ES server response
        $documentId = $this->getCreatedDocId($client->getLastResponse());
        $this->assertNotEmpty($documentId, 'No elastic document id received');

        // retrieve document source from ES and validate
        $document = $this->getDocSourceFromElastic(
            $client,
            $this->options['index'],
            $this->options['type'],
            $documentId
        );
        $this->assertEquals($expected, $document);

        // remove test index from ES
        $client->request("/{$this->options['index']}", Request::DELETE);
    }

    /**
     * Return last created document id from ES response
     * @param Response $response Elastica Response object
     * @return string|null
     */
    protected function getCreatedDocId(Response $response)
    {
        $data = $response->getData();
        if (!empty($data['items'][0]['create']['_id'])) {
            return $data['items'][0]['create']['_id'];
        }
    }

    /**
     * Retrieve document by id from Elasticsearch
     * @param Client $client Elastica client
     * @param string $index
     * @param string $type
     * @param string $documentId
     * @return array
     */
    protected function getDocSourceFromElastic(Client $client, $index, $type, $documentId)
    {
        $resp = $client->request("/{$index}/{$type}/{$documentId}", Request::GET);
        $data = $resp->getData();
        if (!empty($data['_source'])) {
            return $data['_source'];
        }
        return array();
    }
}
<?php

namespace Monolog\Handler;

use Monolog\TestCase;
use Monolog\Logger;

function error_log()
{
    $GLOBALS['error_log'] = func_get_args();
}

class ErrorLogHandlerTest extends TestCase
{

    protected function setUp()
    {
        $GLOBALS['error_log'] = array();
    }

    /**
     * @covers Monolog\Handler\ErrorLogHandler::__construct
     * @expectedException InvalidArgumentException
     * @expectedExceptionMessage The given message type "42" is not supported
     */
    public function testShouldNotAcceptAnInvalidTypeOnContructor()
    {
        new ErrorLogHandler(42);
    }

    /**
     * @covers Monolog\Handler\ErrorLogHandler::write
     */
    public function testShouldLogMessagesUsingErrorLogFuncion()
    {
        $type = ErrorLogHandler::OPERATING_SYSTEM;
        $handler = new ErrorLogHandler($type);
        $handler->handle($this->getRecord(Logger::ERROR));

        $this->assertStringMatchesFormat('[%s] test.ERROR: test [] []', $GLOBALS['error_log'][0]);
        $this->assertSame($GLOBALS['error_log'][1], $type);
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\TestCase;
use Monolog\Logger;
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\RavenHandler;

class RavenHandlerTest extends TestCase
{
    public function setUp()
    {
        if (!class_exists("Raven_Client")) {
            $this->markTestSkipped("raven/raven not installed");
        }

        require_once __DIR__ . '/MockRavenClient.php';
    }

    /**
     * @covers Monolog\Handler\RavenHandler::__construct
     */
    public function testConstruct()
    {
        $handler = new RavenHandler($this->getRavenClient());
        $this->assertInstanceOf('Monolog\Handler\RavenHandler', $handler);
    }

    protected function getHandler($ravenClient)
    {
        $handler = new RavenHandler($ravenClient);

        return $handler;
    }

    protected function getRavenClient()
    {
        $dsn = 'http://43f6017361224d098402974103bfc53d:a6a0538fc2934ba2bed32e08741b2cd3@marca.python.live.cheggnet.com:9000/1';

        return new MockRavenClient($dsn);
    }

    public function testDebug()
    {
        $ravenClient = $this->getRavenClient();
        $handler = $this->getHandler($ravenClient);

        $record = $this->getRecord(Logger::DEBUG, "A test debug message");
        $handler->handle($record);

        $this->assertEquals($ravenClient::DEBUG, $ravenClient->lastData['level']);
        $this->assertContains($record['message'], $ravenClient->lastData['message']);
    }

    public function testWarning()
    {
        $ravenClient = $this->getRavenClient();
        $handler = $this->getHandler($ravenClient);

        $record = $this->getRecord(Logger::WARNING, "A test warning message");
        $handler->handle($record);

        $this->assertEquals($ravenClient::WARNING, $ravenClient->lastData['level']);
        $this->assertContains($record['message'], $ravenClient->lastData['message']);
    }

    public function testException()
    {
        $ravenClient = $this->getRavenClient();
        $handler = $this->getHandler($ravenClient);

        try {
            $this->methodThatThrowsAnException();
        } catch (\Exception $e) {
            $record = $this->getRecord(Logger::ERROR, $e->getMessage(), array('exception' => $e));
            $handler->handle($record);
        }

        $this->assertEquals($record['message'], $ravenClient->lastData['message']);
    }

    public function testHandleBatch()
    {
        $records = $this->getMultipleRecords();
        $records[] = $this->getRecord(Logger::WARNING, 'warning');
        $records[] = $this->getRecord(Logger::WARNING, 'warning');

        $logFormatter = $this->getMock('Monolog\\Formatter\\FormatterInterface');
        $logFormatter->expects($this->once())->method('formatBatch');

        $formatter = $this->getMock('Monolog\\Formatter\\FormatterInterface');
        $formatter->expects($this->once())->method('format')->with($this->callback(function($record) {
            return $record['level'] == 400;
        }));

        $handler = $this->getHandler($this->getRavenClient());
        $handler->setBatchFormatter($logFormatter);
        $handler->setFormatter($formatter);
        $handler->handleBatch($records);
    }

    public function testHandleBatchDoNothingIfRecordsAreBelowLevel()
    {
        $records = array(
            $this->getRecord(Logger::DEBUG, 'debug message 1'),
            $this->getRecord(Logger::DEBUG, 'debug message 2'),
            $this->getRecord(Logger::INFO, 'information'),
        );

        $handler = $this->getMock('Monolog\Handler\RavenHandler', null, array($this->getRavenClient()));
        $handler->expects($this->never())->method('handle');
        $handler->setLevel(Logger::ERROR);
        $handler->handleBatch($records);
    }

    public function testGetSetBatchFormatter()
    {
        $ravenClient = $this->getRavenClient();
        $handler = $this->getHandler($ravenClient);

        $handler->setBatchFormatter($formatter = new LineFormatter());
        $this->assertSame($formatter, $handler->getBatchFormatter());
    }

    private function methodThatThrowsAnException()
    {
        throw new \Exception('This is an exception');
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\TestCase;
use Monolog\Logger;

/**
 * @covers Monolog\Handler\NullHandler::handle
 */
class NullHandlerTest extends TestCase
{
    public function testHandle()
    {
        $handler = new NullHandler();
        $this->assertTrue($handler->handle($this->getRecord()));
    }

    public function testHandleLowerLevelRecord()
    {
        $handler = new NullHandler(Logger::WARNING);
        $this->assertFalse($handler->handle($this->getRecord(Logger::DEBUG)));
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\TestCase;

/**
 * @covers Monolog\Handler\RotatingFileHandler
 */
class RotatingFileHandlerTest extends TestCase
{
    public function setUp()
    {
        $dir = __DIR__.'/Fixtures';
        chmod($dir, 0777);
        if (!is_writable($dir)) {
            $this->markTestSkipped($dir.' must be writeable to test the RotatingFileHandler.');
        }
    }

    public function testRotationCreatesNewFile()
    {
        touch(__DIR__.'/Fixtures/foo-'.date('Y-m-d', time() - 86400).'.rot');

        $handler = new RotatingFileHandler(__DIR__.'/Fixtures/foo.rot');
        $handler->setFormatter($this->getIdentityFormatter());
        $handler->handle($this->getRecord());

        $log = __DIR__.'/Fixtures/foo-'.date('Y-m-d').'.rot';
        $this->assertTrue(file_exists($log));
        $this->assertEquals('test', file_get_contents($log));
    }

    /**
     * @dataProvider rotationTests
     */
    public function testRotation($createFile)
    {
        touch($old1 = __DIR__.'/Fixtures/foo-'.date('Y-m-d', time() - 86400).'.rot');
        touch($old2 = __DIR__.'/Fixtures/foo-'.date('Y-m-d', time() - 86400 * 2).'.rot');
        touch($old3 = __DIR__.'/Fixtures/foo-'.date('Y-m-d', time() - 86400 * 3).'.rot');
        touch($old4 = __DIR__.'/Fixtures/foo-'.date('Y-m-d', time() - 86400 * 4).'.rot');

        $log = __DIR__.'/Fixtures/foo-'.date('Y-m-d').'.rot';

        if ($createFile) {
            touch($log);
        }

        $handler = new RotatingFileHandler(__DIR__.'/Fixtures/foo.rot', 2);
        $handler->setFormatter($this->getIdentityFormatter());
        $handler->handle($this->getRecord());

        $handler->close();

        $this->assertTrue(file_exists($log));
        $this->assertTrue(file_exists($old1));
        $this->assertEquals($createFile, file_exists($old2));
        $this->assertEquals($createFile, file_exists($old3));
        $this->assertEquals($createFile, file_exists($old4));
        $this->assertEquals('test', file_get_contents($log));
    }

    public function rotationTests()
    {
        return array(
            'Rotation is triggered when the file of the current day is not present'
                => array(true),
            'Rotation is not triggered when the file is already present'
                => array(false),
        );
    }

    public function testReuseCurrentFile()
    {
        $log = __DIR__.'/Fixtures/foo-'.date('Y-m-d').'.rot';
        file_put_contents($log, "foo");
        $handler = new RotatingFileHandler(__DIR__.'/Fixtures/foo.rot');
        $handler->setFormatter($this->getIdentityFormatter());
        $handler->handle($this->getRecord());
        $this->assertEquals('footest', file_get_contents($log));
    }

    public function tearDown()
    {
        foreach (glob(__DIR__.'/Fixtures/*.rot') as $file) {
            unlink($file);
        }
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\TestCase;

class MailHandlerTest extends TestCase
{
    /**
     * @covers Monolog\Handler\MailHandler::handleBatch
     */
    public function testHandleBatch()
    {
        $formatter = $this->getMock('Monolog\\Formatter\\FormatterInterface');
        $formatter->expects($this->once())
            ->method('formatBatch'); // Each record is formatted

        $handler = $this->getMockForAbstractClass('Monolog\\Handler\\MailHandler');
        $handler->expects($this->once())
            ->method('send');
        $handler->expects($this->never())
            ->method('write'); // write is for individual records

        $handler->setFormatter($formatter);

        $handler->handleBatch($this->getMultipleRecords());
    }

    /**
     * @covers Monolog\Handler\MailHandler::handleBatch
     */
    public function testHandleBatchNotSendsMailIfMessagesAreBelowLevel()
    {
        $records = array(
            $this->getRecord(Logger::DEBUG, 'debug message 1'),
            $this->getRecord(Logger::DEBUG, 'debug message 2'),
            $this->getRecord(Logger::INFO, 'information'),
        );

        $handler = $this->getMockForAbstractClass('Monolog\\Handler\\MailHandler');
        $handler->expects($this->never())
            ->method('send');
        $handler->setLevel(Logger::ERROR);

        $handler->handleBatch($records);
    }

    /**
     * @covers Monolog\Handler\MailHandler::write
     */
    public function testHandle()
    {
        $handler = $this->getMockForAbstractClass('Monolog\\Handler\\MailHandler');

        $record = $this->getRecord();
        $records = array($record);
        $records[0]['formatted'] = '['.$record['datetime']->format('Y-m-d H:i:s').'] test.WARNING: test [] []'."\n";

        $handler->expects($this->once())
            ->method('send')
            ->with($records[0]['formatted'], $records);

        $handler->handle($record);
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\TestCase;
use Monolog\Logger;
use Psr\Log\LogLevel;

class NewRelicHandlerTest extends TestCase
{
    public static $appname;

    public function setUp()
    {
        $this::$appname = null;
    }

    /**
     * @expectedException Monolog\Handler\MissingExtensionException
     */
    public function testThehandlerThrowsAnExceptionIfTheNRExtensionIsNotLoaded()
    {
        $handler = new StubNewRelicHandlerWithoutExtension();
        $handler->handle($this->getRecord(Logger::ERROR));
    }

    public function testThehandlerCanHandleTheRecord()
    {
        $handler = new StubNewRelicHandler();
        $handler->handle($this->getRecord(Logger::ERROR));
    }

    public function testThehandlerCanAddParamsToTheNewRelicTrace()
    {
        $handler = new StubNewRelicHandler();
        $handler->handle($this->getRecord(Logger::ERROR, 'log message', array('a' => 'b')));
    }

    public function testTheAppNameIsNullByDefault()
    {
        $handler = new StubNewRelicHandler();
        $handler->handle($this->getRecord(Logger::ERROR, 'log message'));

        $this->assertEquals(null, $this::$appname);
    }

    public function testTheAppNameCanBeInjectedFromtheConstructor()
    {
        $handler = new StubNewRelicHandler(LogLevel::ALERT, false, 'myAppName');
        $handler->handle($this->getRecord(Logger::ERROR, 'log message'));

        $this->assertEquals('myAppName', $this::$appname);
    }

    public function testTheAppNameCanBeOverriddenFromEachLog()
    {
        $handler = new StubNewRelicHandler(LogLevel::ALERT, false, 'myAppName');
        $handler->handle($this->getRecord(Logger::ERROR, 'log message', array('appname' => 'logAppName')));

        $this->assertEquals('logAppName', $this::$appname);
    }
}

class StubNewRelicHandlerWithoutExtension extends NewRelicHandler
{
    protected function isNewRelicEnabled()
    {
        return false;
    }
}

class StubNewRelicHandler extends NewRelicHandler
{
    protected function isNewRelicEnabled()
    {
        return true;
    }
}

function newrelic_notice_error()
{
    return true;
}

function newrelic_set_appname($appname)
{
    return NewRelicHandlerTest::$appname = $appname;
}

function newrelic_add_custom_parameter()
{
    return true;
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\TestCase;

class DynamoDbHandlerTest extends TestCase
{
    public function setUp()
    {
        if (!class_exists('Aws\DynamoDb\DynamoDbClient')) {
            $this->markTestSkipped('aws/aws-sdk-php not installed');
        }

        $this->client = $this->getMockBuilder('Aws\DynamoDb\DynamoDbClient')->disableOriginalConstructor()->getMock();
    }

    public function testConstruct()
    {
        $this->assertInstanceOf('Monolog\Handler\DynamoDbHandler', new DynamoDbHandler($this->client, 'foo'));
    }

    public function testInterface()
    {
        $this->assertInstanceOf('Monolog\Handler\HandlerInterface', new DynamoDbHandler($this->client, 'foo'));
    }

    public function testGetFormatter()
    {
        $handler = new DynamoDbHandler($this->client, 'foo');
        $this->assertInstanceOf('Monolog\Formatter\ScalarFormatter', $handler->getFormatter());
    }

    public function testHandle()
    {
        $record = $this->getRecord();
        $formatter = $this->getMock('Monolog\Formatter\FormatterInterface');
        $formatted = array('foo' => 1, 'bar' => 2);
        $handler = new DynamoDbHandler($this->client, 'foo');
        $handler->setFormatter($formatter);

        $formatter
             ->expects($this->once())
             ->method('format')
             ->with($record)
             ->will($this->returnValue($formatted));
        $this->client
             ->expects($this->once())
             ->method('formatAttributes')
             ->with($this->isType('array'))
             ->will($this->returnValue($formatted));
        $this->client
             ->expects($this->once())
             ->method('__call')
             ->with('putItem', array(array(
                 'TableName' => 'foo',
                 'Item' => $formatted
             )));

        $handler->handle($record);
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\TestCase;
use Monolog\Logger;
use Monolog\Processor\WebProcessor;

class AbstractProcessingHandlerTest extends TestCase
{
    /**
     * @covers Monolog\Handler\AbstractProcessingHandler::handle
     */
    public function testHandleLowerLevelMessage()
    {
        $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractProcessingHandler', array(Logger::WARNING, true));
        $this->assertFalse($handler->handle($this->getRecord(Logger::DEBUG)));
    }

    /**
     * @covers Monolog\Handler\AbstractProcessingHandler::handle
     */
    public function testHandleBubbling()
    {
        $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractProcessingHandler', array(Logger::DEBUG, true));
        $this->assertFalse($handler->handle($this->getRecord()));
    }

    /**
     * @covers Monolog\Handler\AbstractProcessingHandler::handle
     */
    public function testHandleNotBubbling()
    {
        $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractProcessingHandler', array(Logger::DEBUG, false));
        $this->assertTrue($handler->handle($this->getRecord()));
    }

    /**
     * @covers Monolog\Handler\AbstractProcessingHandler::handle
     */
    public function testHandleIsFalseWhenNotHandled()
    {
        $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractProcessingHandler', array(Logger::WARNING, false));
        $this->assertTrue($handler->handle($this->getRecord()));
        $this->assertFalse($handler->handle($this->getRecord(Logger::DEBUG)));
    }

    /**
     * @covers Monolog\Handler\AbstractProcessingHandler::processRecord
     */
    public function testProcessRecord()
    {
        $handler = $this->getMockForAbstractClass('Monolog\Handler\AbstractProcessingHandler');
        $handler->pushProcessor(new WebProcessor(array(
            'REQUEST_URI' => '',
            'REQUEST_METHOD' => '',
            'REMOTE_ADDR' => '',
            'SERVER_NAME' => '',
            'UNIQUE_ID' => '',
        )));
        $handledRecord = null;
        $handler->expects($this->once())
            ->method('write')
            ->will($this->returnCallback(function($record) use (&$handledRecord) {
                $handledRecord = $record;
            }))
        ;
        $handler->handle($this->getRecord());
        $this->assertEquals(6, count($handledRecord['extra']));
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\TestCase;
use Monolog\Logger;

/**
 * Almost all examples (expected header, titles, messages) taken from
 * https://www.pushover.net/api
 * @author Sebastian Göttschkes <sebastian.goettschkes@googlemail.com>
 * @see https://www.pushover.net/api
 */
class PushoverHandlerTest extends TestCase
{

    private $res;
    private $handler;

    public function testWriteHeader()
    {
        $this->createHandler();
        $this->handler->setHighPriorityLevel(Logger::EMERGENCY); // skip priority notifications
        $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
        fseek($this->res, 0);
        $content = fread($this->res, 1024);

        $this->assertRegexp('/POST \/1\/messages.json HTTP\/1.1\\r\\nHost: api.pushover.net\\r\\nContent-Type: application\/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content);

        return $content;
    }

    /**
     * @depends testWriteHeader
     */
    public function testWriteContent($content)
    {
        $this->assertRegexp('/token=myToken&user=myUser&message=test1&title=Monolog&timestamp=\d{10}$/', $content);
    }

    public function testWriteWithComplexTitle()
    {
        $this->createHandler('myToken', 'myUser', 'Backup finished - SQL1', Logger::EMERGENCY);
        $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
        fseek($this->res, 0);
        $content = fread($this->res, 1024);

        $this->assertRegexp('/title=Backup\+finished\+-\+SQL1/', $content);
    }

    public function testWriteWithComplexMessage()
    {
        $this->createHandler();
        $this->handler->setHighPriorityLevel(Logger::EMERGENCY); // skip priority notifications
        $this->handler->handle($this->getRecord(Logger::CRITICAL, 'Backup of database "example" finished in 16 minutes.'));
        fseek($this->res, 0);
        $content = fread($this->res, 1024);

        $this->assertRegexp('/message=Backup\+of\+database\+%22example%22\+finished\+in\+16\+minutes\./', $content);
    }

    public function testWriteWithTooLongMessage()
    {
        $message = str_pad('test', 520, 'a');
        $this->createHandler();
        $this->handler->setHighPriorityLevel(Logger::EMERGENCY); // skip priority notifications
        $this->handler->handle($this->getRecord(Logger::CRITICAL, $message));
        fseek($this->res, 0);
        $content = fread($this->res, 1024);

        $expectedMessage = substr($message, 0, 505);

        $this->assertRegexp('/message=' . $expectedMessage . '&title/', $content);
    }

    public function testWriteWithHighPriority()
    {
        $this->createHandler();
        $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1'));
        fseek($this->res, 0);
        $content = fread($this->res, 1024);

        $this->assertRegexp('/token=myToken&user=myUser&message=test1&title=Monolog&timestamp=\d{10}&priority=1$/', $content);
    }

    public function testWriteWithEmergencyPriority()
    {
        $this->createHandler();
        $this->handler->handle($this->getRecord(Logger::EMERGENCY, 'test1'));
        fseek($this->res, 0);
        $content = fread($this->res, 1024);

        $this->assertRegexp('/token=myToken&user=myUser&message=test1&title=Monolog&timestamp=\d{10}&priority=2&retry=30&expire=25200$/', $content);
    }

    public function testWriteToMultipleUsers()
    {
        $this->createHandler('myToken', array('userA', 'userB'));
        $this->handler->handle($this->getRecord(Logger::EMERGENCY, 'test1'));
        fseek($this->res, 0);
        $content = fread($this->res, 1024);

        $this->assertRegexp('/token=myToken&user=userA&message=test1&title=Monolog&timestamp=\d{10}&priority=2&retry=30&expire=25200POST/', $content);
        $this->assertRegexp('/token=myToken&user=userB&message=test1&title=Monolog&timestamp=\d{10}&priority=2&retry=30&expire=25200$/', $content);
    }

    private function createHandler($token = 'myToken', $user = 'myUser', $title = 'Monolog')
    {
        $constructorArgs = array($token, $user, $title);
        $this->res = fopen('php://memory', 'a');
        $this->handler = $this->getMock(
            '\Monolog\Handler\PushoverHandler',
            array('fsockopen', 'streamSetTimeout', 'closeSocket'),
            $constructorArgs
        );

        $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString');
        $reflectionProperty->setAccessible(true);
        $reflectionProperty->setValue($this->handler, 'localhost:1234');

        $this->handler->expects($this->any())
            ->method('fsockopen')
            ->will($this->returnValue($this->res));
        $this->handler->expects($this->any())
            ->method('streamSetTimeout')
            ->will($this->returnValue(true));
        $this->handler->expects($this->any())
            ->method('closeSocket')
            ->will($this->returnValue(true));

        $this->handler->setFormatter($this->getIdentityFormatter());
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Monolog\Handler;

use Monolog\TestCase;
use Monolog\Logger;

class StreamHandlerTest extends TestCase
{
    /**
     * @covers Monolog\Handler\StreamHandler::__construct
     * @covers Monolog\Handler\StreamHandler::write
     */
    public function testWrite()
    {
        $handle = fopen('php://memory', 'a+');
        $handler = new StreamHandler($handle);
        $handler->setFormatter($this->getIdentityFormatter());
        $handler->handle($this->getRecord(Logger::WARNING, 'test'));
        $handler->handle($this->getRecord(Logger::WARNING, 'test2'));
        $handler->handle($this->getRecord(Logger::WARNING, 'test3'));
        fseek($handle, 0);
        $this->assertEquals('testtest2test3', fread($handle, 100));
    }

    /**
     * @covers Monolog\Handler\StreamHandler::close
     */
    public function testClose()
    {
        $handle = fopen('php://memory', 'a+');
        $handler = new StreamHandler($handle);
        $this->assertTrue(is_resource($handle));
        $handler->close();
        $this->assertFalse(is_resource($handle));
    }

    /**
     * @covers Monolog\Handler\StreamHandler::write
     */
    public function testWriteCreatesTheStreamResource()
    {
        $handler = new StreamHandler('php://memory');
        $handler->handle($this->getRecord());
    }

    /**
     * @expectedException LogicException
     * @covers Monolog\Handler\StreamHandler::__construct
     * @covers Monolog\Handler\StreamHandler::write
     */
    public function testWriteMissingResource()
    {
        $handler = new StreamHandler(null);
        $handler->handle($this->getRecord());
    }

    /**
     * @expectedException UnexpectedValueException
     * @covers Monolog\Handler\StreamHandler::__construct
     * @covers Monolog\Handler\StreamHandler::write
     */
    public function testWriteInvalidResource()
    {
        $handler = new StreamHandler('bogus://url');
        $handler->handle($this->getRecord());
    }

    /**
     * @expectedException UnexpectedValueException
     * @covers Monolog\Handler\StreamHandler::__construct
     * @covers Monolog\Handler\StreamHandler::write
     */
    public function testWriteNonExistingResource()
    {
        $handler = new StreamHandler('/foo/bar/baz/'.rand(0, 10000));
        $handler->handle($this->getRecord());
    }
}
<?php

/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

$loader = require __DIR__ . "/../vendor/autoload.php";
$loader->add('Monolog\\', __DIR__);
<?xml version="1.0" encoding="UTF-8"?>

<phpunit bootstrap="tests/bootstrap.php" colors="true">
    <testsuites>
        <testsuite name="Monolog Test Suite">
            <directory>tests/Monolog/</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory suffix=".php">src/Monolog/</directory>
        </whitelist>
    </filter>
</phpunit>
Monolog - Logging for PHP 5.3+ [![Build Status](https://secure.travis-ci.org/Seldaek/monolog.png)](http://travis-ci.org/Seldaek/monolog)
==============================

[![Total Downloads](https://poser.pugx.org/monolog/monolog/downloads.png)](https://packagist.org/packages/monolog/monolog)
[![Latest Stable Version](https://poser.pugx.org/monolog/monolog/v/stable.png)](https://packagist.org/packages/monolog/monolog)


Monolog sends your logs to files, sockets, inboxes, databases and various
web services. See the complete list of handlers below. Special handlers
allow you to build advanced logging strategies.

This library implements the [PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md)
interface that you can type-hint against in your own libraries to keep
a maximum of interoperability. You can also use it in your applications to
make sure you can always use another compatible logger at a later time.

Usage
-----

```php
<?php

use Monolog\Logger;
use Monolog\Handler\StreamHandler;

// create a log channel
$log = new Logger('name');
$log->pushHandler(new StreamHandler('path/to/your.log', Logger::WARNING));

// add records to the log
$log->addWarning('Foo');
$log->addError('Bar');
```

Core Concepts
-------------

Every `Logger` instance has a channel (name) and a stack of handlers. Whenever
you add a record to the logger, it traverses the handler stack. Each handler
decides whether it handled fully the record, and if so, the propagation of the
record ends there.

This allows for flexible logging setups, for example having a `StreamHandler` at
the bottom of the stack that will log anything to disk, and on top of that add
a `MailHandler` that will send emails only when an error message is logged.
Handlers also have a `$bubble` property which defines whether they block the
record or not if they handled it. In this example, setting the `MailHandler`'s
`$bubble` argument to false means that records handled by the `MailHandler` will
not propagate to the `StreamHandler` anymore.

You can create many `Logger`s, each defining a channel (e.g.: db, request,
router, ..) and each of them combining various handlers, which can be shared
or not. The channel is reflected in the logs and allows you to easily see or
filter records.

Each Handler also has a Formatter, a default one with settings that make sense
will be created if you don't set one. The formatters normalize and format
incoming records so that they can be used by the handlers to output useful
information.

Custom severity levels are not available. Only the eight
[RFC 5424](http://tools.ietf.org/html/rfc5424) levels (debug, info, notice,
warning, error, critical, alert, emergency) are present for basic filtering
purposes, but for sorting and other use cases that would require
flexibility, you should add Processors to the Logger that can add extra
information (tags, user ip, ..) to the records before they are handled.

Log Levels
----------

Monolog supports the logging levels described by [RFC 5424](http://tools.ietf.org/html/rfc5424).

- **DEBUG** (100): Detailed debug information.

- **INFO** (200): Interesting events. Examples: User logs in, SQL logs.

- **NOTICE** (250): Normal but significant events.

- **WARNING** (300): Exceptional occurrences that are not errors. Examples:
  Use of deprecated APIs, poor use of an API, undesirable things that are not
  necessarily wrong.

- **ERROR** (400): Runtime errors that do not require immediate action but
  should typically be logged and monitored.

- **CRITICAL** (500): Critical conditions. Example: Application component
  unavailable, unexpected exception.

- **ALERT** (550): Action must be taken immediately. Example: Entire website
  down, database unavailable, etc. This should trigger the SMS alerts and wake
  you up.

- **EMERGENCY** (600): Emergency: system is unusable.

Docs
====

**See the `doc` directory for more detailed documentation.
The following is only a list of all parts that come with Monolog.**

Handlers
--------

### Log to files and syslog

- _StreamHandler_: Logs records into any PHP stream, use this for log files.
- _RotatingFileHandler_: Logs records to a file and creates one logfile per day.
  It will also delete files older than `$maxFiles`. You should use
  [logrotate](http://linuxcommand.org/man_pages/logrotate8.html) for high profile
  setups though, this is just meant as a quick and dirty solution.
- _SyslogHandler_: Logs records to the syslog.
- _ErrorLogHandler_: Logs records to PHP's
  [`error_log()`](http://docs.php.net/manual/en/function.error-log.php) function.

### Send alerts and emails

- _NativeMailerHandler_: Sends emails using PHP's
  [`mail()`](http://php.net/manual/en/function.mail.php) function.
- _SwiftMailerHandler_: Sends emails using a [`Swift_Mailer`](http://swiftmailer.org/) instance.
- _PushoverHandler_: Sends mobile notifications via the [Pushover](https://www.pushover.net/) API.
- _HipChatHandler_: Logs records to a [HipChat](http://hipchat.com) chat room using its API.

### Log specific servers and networked logging

- _SocketHandler_: Logs records to [sockets](http://php.net/fsockopen), use this
  for UNIX and TCP sockets. See an [example](https://github.com/Seldaek/monolog/blob/master/doc/sockets.md).
- _AmqpHandler_: Logs records to an [amqp](http://www.amqp.org/) compatible
  server. Requires the [php-amqp](http://pecl.php.net/package/amqp) extension (1.0+).
- _GelfHandler_: Logs records to a [Graylog2](http://www.graylog2.org) server.
- _CubeHandler_: Logs records to a [Cube](http://square.github.com/cube/) server.
- _RavenHandler_: Logs records to a [Sentry](http://getsentry.com/) server using
  [raven](https://packagist.org/packages/raven/raven).
- _ZendMonitorHandler_: Logs records to the Zend Monitor present in Zend Server.
- _NewRelicHandler_: Logs records to a [NewRelic](http://newrelic.com/) application.
- _LogglyHandler_: Logs records to a [Loggly](http://www.loggly.com/) account.
- _SyslogUdpHandler_: Logs records to a remote [Syslogd](http://www.rsyslog.com/) server.

### Logging in development

- _FirePHPHandler_: Handler for [FirePHP](http://www.firephp.org/), providing
  inline `console` messages within [FireBug](http://getfirebug.com/).
- _ChromePHPHandler_: Handler for [ChromePHP](http://www.chromephp.com/), providing
  inline `console` messages within Chrome.

### Log to databases

- _RedisHandler_: Logs records to a [redis](http://redis.io) server.
- _MongoDBHandler_: Handler to write records in MongoDB via a
  [Mongo](http://pecl.php.net/package/mongo) extension connection.
- _CouchDBHandler_: Logs records to a CouchDB server.
- _DoctrineCouchDBHandler_: Logs records to a CouchDB server via the Doctrine CouchDB ODM.
- _ElasticSearchHandler_: Logs records to an Elastic Search server.
- _DynamoDbHandler_: Logs records to a DynamoDB table with the [AWS SDK](https://github.com/aws/aws-sdk-php).

### Wrappers / Special Handlers

- _FingersCrossedHandler_: A very interesting wrapper. It takes a logger as
  parameter and will accumulate log records of all levels until a record
  exceeds the defined severity level. At which point it delivers all records,
  including those of lower severity, to the handler it wraps. This means that
  until an error actually happens you will not see anything in your logs, but
  when it happens you will have the full information, including debug and info
  records. This provides you with all the information you need, but only when
  you need it.
- _NullHandler_: Any record it can handle will be thrown away. This can be used
  to put on top of an existing handler stack to disable it temporarily.
- _BufferHandler_: This handler will buffer all the log records it receives
  until `close()` is called at which point it will call `handleBatch()` on the
  handler it wraps with all the log messages at once. This is very useful to
  send an email with all records at once for example instead of having one mail
  for every log record.
- _GroupHandler_: This handler groups other handlers. Every record received is
  sent to all the handlers it is configured with.
- _TestHandler_: Used for testing, it records everything that is sent to it and
  has accessors to read out the information.

Formatters
----------

- _LineFormatter_: Formats a log record into a one-line string.
- _NormalizerFormatter_: Normalizes objects/resources down to strings so a record can easily be serialized/encoded.
- _ScalarFormatter_: Used to format log records into an associative array of scalar values.
- _JsonFormatter_: Encodes a log record into json.
- _WildfireFormatter_: Used to format log records into the Wildfire/FirePHP protocol, only useful for the FirePHPHandler.
- _ChromePHPFormatter_: Used to format log records into the ChromePHP format, only useful for the ChromePHPHandler.
- _GelfFormatter_: Used to format log records into Gelf message instances, only useful for the GelfHandler.
- _LogstashFormatter_: Used to format log records into [logstash](http://logstash.net/) event json, useful for any handler listed under inputs [here](http://logstash.net/docs/1.1.5/).
- _ElasticaFormatter_: Used to format log records into an Elastica\Document object, only useful for the ElasticSearchHandler.

Processors
----------

- _IntrospectionProcessor_: Adds the line/file/class/method from which the log call originated.
- _WebProcessor_: Adds the current request URI, request method and client IP to a log record.
- _MemoryUsageProcessor_: Adds the current memory usage to a log record.
- _MemoryPeakUsageProcessor_: Adds the peak memory usage to a log record.
- _ProcessIdProcessor_: Adds the process id to a log record.
- _UidProcessor_: Adds a unique identifier to a log record.

Utilities
---------

- _ErrorHandler_: The `Monolog\ErrorHandler` class allows you to easily register
  a Logger instance as an exception handler, error handler or fatal error handler.
- _ErrorLevelActivationStrategy_: Activates a FingersCrossedHandler when a certain log
  level is reached.
- _ChannelLevelActivationStrategy_: Activates a FingersCrossedHandler when a certain
  log level is reached, depending on which channel received the log record.

About
=====

Requirements
------------

- Any flavor of PHP 5.3 or above should do
- [optional] PHPUnit 3.5+ to execute the test suite (phpunit --version)

Submitting bugs and feature requests
------------------------------------

Bugs and feature request are tracked on [GitHub](https://github.com/Seldaek/monolog/issues)

Frameworks Integration
----------------------

- Frameworks and libraries using [PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md)
  can be used very easily with Monolog since it implements the interface.
- [Symfony2](http://symfony.com) comes out of the box with Monolog.
- [Silex](http://silex.sensiolabs.org/) comes out of the box with Monolog.
- [Laravel 4](http://laravel.com/) comes out of the box with Monolog.
- [PPI](http://www.ppi.io/) comes out of the box with Monolog.
- [CakePHP](http://cakephp.org/) is usable with Monolog via the [cakephp-monolog](https://github.com/jadb/cakephp-monolog) plugin.
- [Slim](http://www.slimframework.com/) is usable with Monolog via the [Slim-Monolog](https://github.com/Flynsarmy/Slim-Monolog) log writer.
- [XOOPS 2.6](http://xoops.org/) comes out of the box with Monolog.

Author
------

Jordi Boggiano - <j.boggiano@seld.be> - <http://twitter.com/seldaek><br />
See also the list of [contributors](https://github.com/Seldaek/monolog/contributors) which participated in this project.

License
-------

Monolog is licensed under the MIT License - see the `LICENSE` file for details

Acknowledgements
----------------

This library is heavily inspired by Python's [Logbook](http://packages.python.org/Logbook/)
library, although most concepts have been adjusted to fit to the PHP world.
### 1.7.0 (2013-11-14)

  * Added ElasticSearchHandler to send logs to an Elastic Search server
  * Added DynamoDbHandler and ScalarFormatter to send logs to Amazon's Dynamo DB
  * Added SyslogUdpHandler to send logs to a remote syslogd server
  * Added LogglyHandler to send logs to a Loggly account
  * Added $level to IntrospectionProcessor so it only adds backtraces when needed
  * Added $version to LogstashFormatter to allow using the new v1 Logstash format
  * Added $appName to NewRelicHandler
  * Added configuration of Pushover notification retries/expiry
  * Added $maxColumnWidth to NativeMailerHandler to change the 70 chars default
  * Added chainability to most setters for all handlers
  * Fixed RavenHandler batch processing so it takes the message from the record with highest priority
  * Fixed HipChatHandler batch processing so it sends all messages at once
  * Fixed issues with eAccelerator
  * Fixed and improved many small things

### 1.6.0 (2013-07-29)

  * Added HipChatHandler to send logs to a HipChat chat room
  * Added ErrorLogHandler to send logs to PHP's error_log function
  * Added NewRelicHandler to send logs to NewRelic's service
  * Added Monolog\ErrorHandler helper class to register a Logger as exception/error/fatal handler
  * Added ChannelLevelActivationStrategy for the FingersCrossedHandler to customize levels by channel
  * Added stack traces output when normalizing exceptions (json output & co)
  * Added Monolog\Logger::API constant (currently 1)
  * Added support for ChromePHP's v4.0 extension
  * Added support for message priorities in PushoverHandler, see $highPriorityLevel and $emergencyLevel
  * Added support for sending messages to multiple users at once with the PushoverHandler
  * Fixed RavenHandler's support for batch sending of messages (when behind a Buffer or FingersCrossedHandler)
  * Fixed normalization of Traversables with very large data sets, only the first 1000 items are shown now
  * Fixed issue in RotatingFileHandler when an open_basedir restriction is active
  * Fixed minor issues in RavenHandler and bumped the API to Raven 0.5.0
  * Fixed SyslogHandler issue when many were used concurrently with different facilities

### 1.5.0 (2013-04-23)

  * Added ProcessIdProcessor to inject the PID in log records
  * Added UidProcessor to inject a unique identifier to all log records of one request/run
  * Added support for previous exceptions in the LineFormatter exception serialization
  * Added Monolog\Logger::getLevels() to get all available levels
  * Fixed ChromePHPHandler so it avoids sending headers larger than Chrome can handle

### 1.4.1 (2013-04-01)

  * Fixed exception formatting in the LineFormatter to be more minimalistic
  * Fixed RavenHandler's handling of context/extra data, requires Raven client >0.1.0
  * Fixed log rotation in RotatingFileHandler to work with long running scripts spanning multiple days
  * Fixed WebProcessor array access so it checks for data presence
  * Fixed Buffer, Group and FingersCrossed handlers to make use of their processors

### 1.4.0 (2013-02-13)

  * Added RedisHandler to log to Redis via the Predis library or the phpredis extension
  * Added ZendMonitorHandler to log to the Zend Server monitor
  * Added the possibility to pass arrays of handlers and processors directly in the Logger constructor
  * Added `$useSSL` option to the PushoverHandler which is enabled by default
  * Fixed ChromePHPHandler and FirePHPHandler issue when multiple instances are used simultaneously
  * Fixed header injection capability in the NativeMailHandler

### 1.3.1 (2013-01-11)

  * Fixed LogstashFormatter to be usable with stream handlers
  * Fixed GelfMessageFormatter levels on Windows

### 1.3.0 (2013-01-08)

  * Added PSR-3 compliance, the `Monolog\Logger` class is now an instance of `Psr\Log\LoggerInterface`
  * Added PsrLogMessageProcessor that you can selectively enable for full PSR-3 compliance
  * Added LogstashFormatter (combine with SocketHandler or StreamHandler to send logs to Logstash)
  * Added PushoverHandler to send mobile notifications
  * Added CouchDBHandler and DoctrineCouchDBHandler
  * Added RavenHandler to send data to Sentry servers
  * Added support for the new MongoClient class in MongoDBHandler
  * Added microsecond precision to log records' timestamps
  * Added `$flushOnOverflow` param to BufferHandler to flush by batches instead of losing
    the oldest entries
  * Fixed normalization of objects with cyclic references

### 1.2.1 (2012-08-29)

  * Added new $logopts arg to SyslogHandler to provide custom openlog options
  * Fixed fatal error in SyslogHandler

### 1.2.0 (2012-08-18)

  * Added AmqpHandler (for use with AMQP servers)
  * Added CubeHandler
  * Added NativeMailerHandler::addHeader() to send custom headers in mails
  * Added the possibility to specify more than one recipient in NativeMailerHandler
  * Added the possibility to specify float timeouts in SocketHandler
  * Added NOTICE and EMERGENCY levels to conform with RFC 5424
  * Fixed the log records to use the php default timezone instead of UTC
  * Fixed BufferHandler not being flushed properly on PHP fatal errors
  * Fixed normalization of exotic resource types
  * Fixed the default format of the SyslogHandler to avoid duplicating datetimes in syslog

### 1.1.0 (2012-04-23)

  * Added Monolog\Logger::isHandling() to check if a handler will
    handle the given log level
  * Added ChromePHPHandler
  * Added MongoDBHandler
  * Added GelfHandler (for use with Graylog2 servers)
  * Added SocketHandler (for use with syslog-ng for example)
  * Added NormalizerFormatter
  * Added the possibility to change the activation strategy of the FingersCrossedHandler
  * Added possibility to show microseconds in logs
  * Added `server` and `referer` to WebProcessor output

### 1.0.2 (2011-10-24)

  * Fixed bug in IE with large response headers and FirePHPHandler

### 1.0.1 (2011-08-25)

  * Added MemoryPeakUsageProcessor and MemoryUsageProcessor
  * Added Monolog\Logger::getName() to get a logger's channel name

### 1.0.0 (2011-07-06)

  * Added IntrospectionProcessor to get info from where the logger was called
  * Fixed WebProcessor in CLI

### 1.0.0-RC1 (2011-07-01)

  * Initial release
{
    "name": "pimple/pimple",
    "type": "library",
    "description": "Pimple is a simple Dependency Injection Container for PHP 5.3",
    "keywords": ["dependency injection", "container"],
    "homepage": "http://pimple.sensiolabs.org",
    "license": "MIT",
    "authors": [
        {
            "name": "Fabien Potencier",
            "email": "fabien@symfony.com"
        }
    ],
    "require": {
        "php": ">=5.3.0"
    },
    "autoload": {
        "psr-0": { "Pimple": "lib/" }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.0.x-dev"
        }
    }
}Copyright (c) 2009-2013 Fabien Potencier

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="tests/bootstrap.php"
>
    <testsuites>
        <testsuite name="Pimple Test Suite">
            <directory>./tests/Pimple/</directory>
        </testsuite>
    </testsuites>
</phpunit>
<?php

/*
 * This file is part of Pimple.
 *
 * Copyright (c) 2009 Fabien Potencier
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is furnished
 * to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

/**
 * Pimple main class.
 *
 * @package pimple
 * @author  Fabien Potencier
 */
class Pimple implements ArrayAccess
{
    protected $values = array();

    /**
     * Instantiate the container.
     *
     * Objects and parameters can be passed as argument to the constructor.
     *
     * @param array $values The parameters or objects.
     */
    public function __construct (array $values = array())
    {
        $this->values = $values;
    }

    /**
     * Sets a parameter or an object.
     *
     * Objects must be defined as Closures.
     *
     * Allowing any PHP callable leads to difficult to debug problems
     * as function names (strings) are callable (creating a function with
     * the same a name as an existing parameter would break your container).
     *
     * @param string $id    The unique identifier for the parameter or object
     * @param mixed  $value The value of the parameter or a closure to defined an object
     */
    public function offsetSet($id, $value)
    {
        $this->values[$id] = $value;
    }

    /**
     * Gets a parameter or an object.
     *
     * @param string $id The unique identifier for the parameter or object
     *
     * @return mixed The value of the parameter or an object
     *
     * @throws InvalidArgumentException if the identifier is not defined
     */
    public function offsetGet($id)
    {
        if (!array_key_exists($id, $this->values)) {
            throw new InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id));
        }

        $isFactory = is_object($this->values[$id]) && method_exists($this->values[$id], '__invoke');

        return $isFactory ? $this->values[$id]($this) : $this->values[$id];
    }

    /**
     * Checks if a parameter or an object is set.
     *
     * @param string $id The unique identifier for the parameter or object
     *
     * @return Boolean
     */
    public function offsetExists($id)
    {
        return array_key_exists($id, $this->values);
    }

    /**
     * Unsets a parameter or an object.
     *
     * @param string $id The unique identifier for the parameter or object
     */
    public function offsetUnset($id)
    {
        unset($this->values[$id]);
    }

    /**
     * Returns a closure that stores the result of the given closure for
     * uniqueness in the scope of this instance of Pimple.
     *
     * @param Closure $callable A closure to wrap for uniqueness
     *
     * @return Closure The wrapped closure
     */
    public static function share(Closure $callable)
    {
        return function ($c) use ($callable) {
            static $object;

            if (null === $object) {
                $object = $callable($c);
            }

            return $object;
        };
    }

    /**
     * Protects a callable from being interpreted as a service.
     *
     * This is useful when you want to store a callable as a parameter.
     *
     * @param Closure $callable A closure to protect from being evaluated
     *
     * @return Closure The protected closure
     */
    public static function protect(Closure $callable)
    {
        return function ($c) use ($callable) {
            return $callable;
        };
    }

    /**
     * Gets a parameter or the closure defining an object.
     *
     * @param string $id The unique identifier for the parameter or object
     *
     * @return mixed The value of the parameter or the closure defining an object
     *
     * @throws InvalidArgumentException if the identifier is not defined
     */
    public function raw($id)
    {
        if (!array_key_exists($id, $this->values)) {
            throw new InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id));
        }

        return $this->values[$id];
    }

    /**
     * Extends an object definition.
     *
     * Useful when you want to extend an existing object definition,
     * without necessarily loading that object.
     *
     * @param string  $id       The unique identifier for the object
     * @param Closure $callable A closure to extend the original
     *
     * @return Closure The wrapped closure
     *
     * @throws InvalidArgumentException if the identifier is not defined
     */
    public function extend($id, Closure $callable)
    {
        if (!array_key_exists($id, $this->values)) {
            throw new InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id));
        }

        $factory = $this->values[$id];

        if (!($factory instanceof Closure)) {
            throw new InvalidArgumentException(sprintf('Identifier "%s" does not contain an object definition.', $id));
        }

        return $this->values[$id] = function ($c) use ($callable, $factory) {
            return $callable($factory($c), $c);
        };
    }

    /**
     * Returns all defined value names.
     *
     * @return array An array of value names
     */
    public function keys()
    {
        return array_keys($this->values);
    }
}
{
    "name": "mockery/mockery",
    "description": "Mockery is a simple yet flexible PHP mock object framework for use in unit testing with PHPUnit, PHPSpec or any other testing framework. Its core goal is to offer a test double framework with a succint API capable of clearly defining all possible object operations and interactions using a human readable Domain Specific Language (DSL). Designed as a drop in alternative to PHPUnit's phpunit-mock-objects library, Mockery is easy to integrate with PHPUnit and can operate alongside phpunit-mock-objects without the World ending.",
    "keywords": ["library", "testing", "test", "stub", "mock", "mockery", "test double", "tdd", "bdd", "mock objects"],
    "homepage": "http://github.com/padraic/mockery",
    "license": "BSD-3-Clause",
    "authors": [
        {
            "name": "Pádraic Brady",
            "email": "padraic.brady@gmail.com",
            "homepage": "http://blog.astrumfutura.com"
        }
    ],
    "require": {
        "php": ">=5.3.2"
    },
    "require-dev": {
        "hamcrest/hamcrest": "1.1.0"
    },
    "autoload": {
        "psr-0": { "Mockery": "library/" }
    },
    "repositories": [
        {
            "type": "package",
            "package": {
                "name": "hamcrest/hamcrest",
                "version": "1.1.0",
                "dist": {
                    "type": "zip",
                    "url": "https://hamcrest.googlecode.com/files/hamcrest-php-1.1.0.zip"
                },
                "include-path": ["Hamcrest-1.1.0/"],
                "autoload": {
                    "psr-0": { "Hamcrest_": "Hamcrest-1.1.0/" },
                    "files": ["Hamcrest-1.1.0/Hamcrest/Hamcrest.php"]
                }
            }
        }
    ]
}<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */
 
namespace Mockery;

class ExpectationDirector
{

    /**
     * Method name the director is directing
     *
     * @var string
     */
    protected $_name = null;
    
    /**
     * Mock object the director is attached to
     *
     * @var \Mockery\MockInterface
     */
    protected $_mock = null;
    
    /**
     * Stores an array of all expectations for this mock
     *
     * @var array
     */
    protected $_expectations = array();
    
    /**
     * The expected order of next call
     *
     * @var int
     */
    protected $_expectedOrder = null;
    
    /**
     * Stores an array of all default expectations for this mock
     *
     * @var array
     */
    protected $_defaults = array();
    
    /**
     * Constructor
     *
     * @param string $name
     * @param \Mockery\MockInterface $mock
     */
    public function __construct($name, \Mockery\MockInterface $mock)
    {
        $this->_name = $name;
        $this->_mock = $mock;
    }
    
    /**
     * Add a new expectation to the director
     *
     * @param Mutateme\Expectation $expectation
     */
    public function addExpectation(\Mockery\Expectation $expectation)
    {
        $this->_expectations[] = $expectation;
    }
    
    /**
     * Handle a method call being directed by this instance
     *
     * @param array $args
     * @return mixed
     */
    public function call(array $args)
    {
        $expectation = $this->findExpectation($args);
        if (is_null($expectation)) {
            $exception = new \Mockery\Exception\NoMatchingExpectationException(
                'No matching handler found for '
                . $this->_mock->mockery_getName() . '::'
                . \Mockery::formatArgs($this->_name, $args)
                . '. Either the method was unexpected or its arguments matched'
                . ' no expected argument list for this method'
                . PHP_EOL . PHP_EOL
                . \Mockery::formatObjects($args)
            );
            $exception->setMock($this->_mock)
                ->setMethodName($this->_name)
                ->setActualArguments($args);
            throw $exception;
        }
        return $expectation->verifyCall($args);
    }
    
    /**
     * Verify all expectations of the director
     *
     * @throws \Mockery\CountValidator\Exception
     * @return void
     */
    public function verify()
    {
        if (!empty($this->_expectations)) {
            foreach ($this->_expectations as $exp) {
                $exp->verify();
            }
        } else {
            foreach ($this->_defaults as $exp) {
                $exp->verify();
            }
        }
    }
    
    /**
     * Attempt to locate an expecatation matching the provided args
     *
     * @param array $args
     * @return mixed
     */
    public function findExpectation(array $args)
    {
        if (!empty($this->_expectations)) {
            return $this->_findExpectationIn($this->_expectations, $args);
        } else {
            return $this->_findExpectationIn($this->_defaults, $args);
        }
    }
    
    /**
     * Make the given expectation a default for all others assuming it was
     * correctly created last
     *
     * @param \Mockery\Expectation
     */
    public function makeExpectationDefault(\Mockery\Expectation $expectation)
    {
        $last = end($this->_expectations);
        if ($last === $expectation) {
            array_pop($this->_expectations);
            array_unshift($this->_defaults, $expectation);
        } else {
            throw new \Mockery\Exception(
                'Cannot turn a previously defined expectation into a default'
            );
        }
    }
    
    /**
     * Search current array of expectations for a match
     *
     * @param array $expectations
     * @param array $args
     * @return mixed
     */
    protected function _findExpectationIn(array $expectations, array $args)
    {
        foreach ($expectations as $exp) {
            if ($exp->matchArgs($args) && $exp->isEligible()) {
                return $exp;
            }
        }
        foreach ($expectations as $exp) {
            if ($exp->matchArgs($args)) {
                return $exp;
            }
        }
    }
    
    /**
     * Return all expectations assigned to this director
     *
     * @return array
     */
    public function getExpectations()
    {
        return $this->_expectations;
    }
    
    /**
     * Return the number of expectations assigned to this director.
     *
     * @return int
     */
    public function getExpectationCount()
    {
        return count($this->getExpectations());    
    }

}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */
 
namespace Mockery;

interface MockInterface
{
    
    /**
     * Alternative setup method to constructor
     *
     * @param string $name
     * @param \Mockery\Container $container
     * @param object $partialObject
     * @return void
     */
    public function mockery_init($name, \Mockery\Container $container = null, $partialObject = null);
    
    /**
     * Set expected method calls
     *
     * @param mixed
     * @return \Mockery\Expectation
     */
    public function shouldReceive();
    
    /**
     * Set mock to ignore unexpected methods and return Undefined class
     *
     * @return Mock
     */
    public function shouldIgnoreMissing();
    
    /**
     * Set mock to defer unexpected methods to it's parent if possible
     *
     * @return Mock
     */
    public function shouldDeferMissing();

    /**
     * In the event shouldReceive() accepting an array of methods/returns
     * this method will switch them from normal expectations to default
     * expectations
     *
     * @return self
     */
    public function byDefault();
    
    /**
     * Capture calls to this mock and check against expectations
     *
     * @param string $method
     * @param array $args
     * @return mixed
     */
        /**
         * Unfortunately we need to allow type hinting agnostic __call()
         * definitions since any interface/class being mocked can go either
         * way.
         */
    //public function __call($method, array $args);
    
    /**
     * Iterate across all expectation directors and validate each
     *
     * @throws \Mockery\CountValidator\Exception
     * @return void
     */
    public function mockery_verify();
    
    /**
     * Tear down tasks for this mock
     *
     * @return void
     */
    public function mockery_teardown();
    
    /**
     * Fetch the next available allocation order number
     *
     * @return int
     */
    public function mockery_allocateOrder();
    
    /**
     * Set ordering for a group
     *
     * @param mixed $group
     * @param int $order
     */
    public function mockery_setGroup($group, $order);
    
    /**
     * Fetch array of ordered groups
     *
     * @return array
     */
    public function mockery_getGroups();
    
    /**
     * Set current ordered number
     *
     * @param int $order
     */
    public function mockery_setCurrentOrder($order);
    
    /**
     * Get current ordered number
     *
     * @return int
     */
    public function mockery_getCurrentOrder();
    
    /**
     * Validate the current mock's ordering
     *
     * @param string $method
     * @param int $order
     * @throws \Mockery\Exception
     * @return void
     */
    public function mockery_validateOrder($method, $order);
    
    /**
     * Gets the count of expectations for this mock
     *
     * @return int
     */
    public function mockery_getExpectationCount();
    
    /**
     * Return the expectations director for the given method
     *
     * @var string $method
     * @return \Mockery\ExpectationDirector|null
     */
    public function mockery_setExpectationsFor($method, \Mockery\ExpectationDirector $director);
    
    /**
     * Return the expectations director for the given method
     *
     * @var string $method
     * @return \Mockery\ExpectationDirector|null
     */
    public function mockery_getExpectationsFor($method);
    
    /**
     * Find an expectation matching the given method and arguments
     *
     * @var string $method
     * @var array $args
     * @return \Mockery\Expectation|null
     */
    public function mockery_findExpectation($method, array $args);
    
    /**
     * Return the container for this mock
     *
     * @return \Mockery\Container
     */
    public function mockery_getContainer();
    
    /**
     * Return the name for this mock
     *
     * @return string
     */
    public function mockery_getName();

}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Matcher;

class Not extends MatcherAbstract
{
    
    /**
     * Check if the actual value does not match the expected (in this
     * case it's specifically NOT expected).
     *
     * @param mixed $actual
     * @return bool
     */
    public function match(&$actual)
    {
        return $actual !== $this->_expected;
    }
    
    /**
     * Return a string representation of this Matcher
     *
     * @return string
     */
    public function __toString()
    {
        return '<Not>';
    }
    
}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Matcher;

class HasKey extends MatcherAbstract
{
    
    /**
     * Check if the actual value matches the expected.
     *
     * @param mixed $actual
     * @return bool
     */
    public function match(&$actual)
    {
        return in_array($this->_expected, array_keys($actual));
    }
    
    /**
     * Return a string representation of this Matcher
     *
     * @return string
     */
    public function __toString()
    {
        $return = '<HasKey[' . (string) $this->_expected . ']>';
        return $return;
    }
    
}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Matcher;

class Contains extends MatcherAbstract
{
    
    /**
     * Check if the actual value matches the expected.
     *
     * @param mixed $actual
     * @return bool
     */
    public function match(&$actual)
    {
        $values = array_values($actual);
        foreach ($this->_expected as $exp) {
            $match = false;
            foreach ($values as $val) {
                if ($exp === $val || $exp == $val) {
                    $match = true;
                    break;
                }   
            }
            if ($match === false) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * Return a string representation of this Matcher
     *
     * @return string
     */
    public function __toString()
    {
        $return = '<Contains[';
        $elements = array();
        foreach ($this->_expected as $v) {
            $elements[] = (string) $v;
        }
        $return .= implode(', ', $elements) . ']>';
        return $return;
    }
    
}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Matcher;

class Any extends MatcherAbstract
{
    
    /**
     * Check if the actual value matches the expected.
     *
     * @param mixed $actual
     * @return bool
     */
    public function match(&$actual)
    {
        return true;
    }
    
    /**
     * Return a string representation of this Matcher
     *
     * @return string
     */
    public function __toString()
    {
        return '<Any>';
    }
    
}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Matcher;

abstract class MatcherAbstract
{

    /**
     * The expected value (or part thereof)
     *
     * @var mixed
     */
    protected $_expected = null;
    
    /**
     * Set the expected value
     *
     * @param mixed $expected
     */
    public function __construct($expected = null)
    {
        $this->_expected = $expected;
    }
    
    /**
     * Check if the actual value matches the expected.
     * Actual passed by reference to preserve reference trail (where applicable)
     * back to the original method parameter.
     *
     * @param mixed $actual
     * @return bool
     */
    public abstract function match(&$actual);
    
    /**
     * Return a string representation of this Matcher
     *
     * @return string
     */
    public abstract function __toString();

}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Matcher;

class Type extends MatcherAbstract
{
    
    /**
     * Check if the actual value matches the expected.
     *
     * @param mixed $actual
     * @return bool
     */
    public function match(&$actual)
    {
        $function = 'is_' . strtolower($this->_expected);
        if (function_exists($function)) {
            return $function($actual);
        } elseif (is_string($this->_expected)
        && (class_exists($this->_expected) || interface_exists($this->_expected))) {
            return $actual instanceof $this->_expected;
        }
        return false;
    }
    
    /**
     * Return a string representation of this Matcher
     *
     * @return string
     */
    public function __toString()
    {
        return '<' . ucfirst($this->_expected) . '>';
    }
    
}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Matcher;

class AnyOf extends MatcherAbstract
{
    
    /**
     * Set the expected value
     *
     * @param mixed $expected
     */
    public function __construct($expected = null)
    {
        $this->_expected = $expected;
    }
    
    /**
     * Check if the actual value does not match the expected (in this
     * case it's specifically NOT expected).
     *
     * @param mixed $actual
     * @return bool
     */
    public function match(&$actual)
    {
        foreach ($this->_expected as $exp) {
            if ($actual === $exp || $actual == $exp) {
                return true;
            }
        }
        return false;
    }
    
    /**
     * Return a string representation of this Matcher
     *
     * @return string
     */
    public function __toString()
    {
        return '<AnyOf>';
    }
    
}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Matcher;

class Subset extends MatcherAbstract
{
    
    /**
     * Check if the actual value matches the expected.
     *
     * @param mixed $actual
     * @return bool
     */
    public function match(&$actual)
    {
        foreach ($this->_expected as $k=>$v) {
            if (!array_key_exists($k, $actual)) {
                return false;
            }
            if ($actual[$k] !== $v) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * Return a string representation of this Matcher
     *
     * @return string
     */
    public function __toString()
    {
        $return = '<Subset[';
        $elements = array();
        foreach ($this->_expected as $k=>$v) {
            $elements[] = $k . '=' . (string) $v;
        }
        $return .= implode(', ', $elements) . ']>';
        return $return;
    }
    
}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Matcher;

class Closure extends MatcherAbstract
{
    
    /**
     * Check if the actual value matches the expected.
     *
     * @param mixed $actual
     * @return bool
     */
    public function match(&$actual)
    {
        $closure = $this->_expected;
        $result = $closure($actual);
        return $result === true;
    }
    
    /**
     * Return a string representation of this Matcher
     *
     * @return string
     */
    public function __toString()
    {
        return '<Closure===TRUE>';
    }
    
}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Matcher;

class HasValue extends MatcherAbstract
{
    
    /**
     * Check if the actual value matches the expected.
     *
     * @param mixed $actual
     * @return bool
     */
    public function match(&$actual)
    {
        return in_array($this->_expected, $actual);
    }
    
    /**
     * Return a string representation of this Matcher
     *
     * @return string
     */
    public function __toString()
    {
        $return = '<HasValue[' . (string) $this->_expected . ']>';
        return $return;
    }
    
}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Matcher;

class MustBe extends MatcherAbstract
{
    
    /**
     * Check if the actual value matches the expected.
     *
     * @param mixed $actual
     * @return bool
     */
    public function match(&$actual)
    {
        if (!is_object($actual)) {
            return $this->_expected === $actual;
        } else {
            return $this->_expected == $actual;
        }
    }
    
    /**
     * Return a string representation of this Matcher
     *
     * @return string
     */
    public function __toString()
    {
        return '<MustBe>';
    }
    
}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Matcher;

class NotAnyOf extends MatcherAbstract
{
    
    /**
     * Set the expected value
     *
     * @param mixed $expected
     */
    public function __construct($expected = null)
    {
        $this->_expected = $expected;
    }
    
    /**
     * Check if the actual value does not match the expected (in this
     * case it's specifically NOT expected).
     *
     * @param mixed $actual
     * @return bool
     */
    public function match(&$actual)
    {
        foreach ($this->_expected as $exp) {
            if ($actual === $exp || $actual == $exp) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * Return a string representation of this Matcher
     *
     * @return string
     */
    public function __toString()
    {
        return '<AnyOf>';
    }
    
}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery\Matcher;

class Ducktype extends MatcherAbstract
{
    
    /**
     * Check if the actual value matches the expected.
     *
     * @param mixed $actual
     * @return bool
     */
    public function match(&$actual)
    {
        if (!is_object($actual)) {
            return false;
        }
        foreach ($this->_expected as $method) {
            if (!method_exists($actual, $method)) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * Return a string representation of this Matcher
     *
     * @return string
     */
    public function __toString()
    {
        return '<Ducktype[' . implode(', ', $this->_expected) . ']>';
    }
    
}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */
 
namespace Mockery;

class Undefined
{

    /**
     * Call capturing to merely return this same object.
     *
     * @param string $method
     * @param array $args
     * @return self
     */
    public function __call($method, array $args)
    {
        return $this;
    }  

    /**
     * Return a string, avoiding E_RECOVERABLE_ERROR 
     *
     * @return string
     */
    public function __toString()
    {
        return __CLASS__ . ":" . spl_object_hash($this);
    }

}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */
 
namespace Mockery;

class Exception extends \UnexpectedValueException
{

}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */
 
namespace Mockery\CountValidator;
use Mockery;

class AtMost extends CountValidatorAbstract
{

    /**
     * Validate the call count against this validator
     *
     * @param int $n
     * @return bool
     */
    public function validate($n)
    {
        if ($this->_limit < $n) {
            $exception = new Mockery\Exception\InvalidCountException(
                'Method ' . (string) $this->_expectation
                . ' from ' . $this->_expectation->getMock()->mockery_getName()
                . ' should be called' . PHP_EOL
                . ' at most ' . $this->_limit . ' times but called ' . $n
                . ' times.'
            );
            $exception->setMock($this->_expectation->getMock())
                ->setMethodName((string) $this->_expectation)
                ->setExpectedCountComparative('<=')
                ->setExpectedCount($this->_limit)
                ->setActualCount($n);
            throw $exception;
        }
    }

}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */
 
namespace Mockery\CountValidator;

class Exception extends \OutOfBoundsException
{

}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */
 
namespace Mockery\CountValidator;
use Mockery;

class AtLeast extends CountValidatorAbstract
{

    /**
     * Checks if the validator can accept an additional nth call
     *
     * @param int $n
     * @return bool
     */
    public function isEligible($n)
    {
        return true;
    }

    /**
     * Validate the call count against this validator
     *
     * @param int $n
     * @return bool
     */
    public function validate($n)
    {
        if ($this->_limit > $n) {
            $exception = new Mockery\Exception\InvalidCountException(
                'Method ' . (string) $this->_expectation
                . ' from ' . $this->_expectation->getMock()->mockery_getName()
                . ' should be called' . PHP_EOL
                . ' at least ' . $this->_limit . ' times but called ' . $n
                . ' times.'
            );
            $exception->setMock($this->_expectation->getMock())
                ->setMethodName((string) $this->_expectation)
                ->setExpectedCountComparative('>=')
                ->setExpectedCount($this->_limit)
                ->setActualCount($n);
            throw $exception;
        }
    }

}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */
 
namespace Mockery\CountValidator;

abstract class CountValidatorAbstract
{

    /**
     * Expectation for which this validator is assigned
     *
     * @var \Mockery\Expectation
     */
    protected $_expectation = null;
    
    /**
     * Call count limit
     *
     * @var int
     */
    protected $_limit = null;

    /**
     * Set Expectation object and upper call limit
     *
     * @param \Mockery\Expectation $expectation
     * @param int $limit
     */
    public function __construct(\Mockery\Expectation $expectation, $limit)
    {
        $this->_expectation = $expectation;
        $this->_limit = $limit;
    }
    
    /**
     * Checks if the validator can accept an additional nth call
     *
     * @param int $n
     * @return bool
     */
    public function isEligible($n)
    {
        return ($n < $this->_limit);
    }
    
    /**
     * Validate the call count against this validator
     *
     * @param int $n
     * @return bool
     */
    public abstract function validate($n);

}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */
 
namespace Mockery\CountValidator;
use Mockery;

class Exact extends CountValidatorAbstract
{

    /**
     * Validate the call count against this validator
     *
     * @param int $n
     * @return bool
     */
    public function validate($n)
    {
        if ($this->_limit !== $n) {
            $exception = new Mockery\Exception\InvalidCountException(
                'Method ' . (string) $this->_expectation
                . ' from ' . $this->_expectation->getMock()->mockery_getName()
                . ' should be called' . PHP_EOL
                . ' exactly ' . $this->_limit . ' times but called ' . $n
                . ' times.'
            );
            $exception->setMock($this->_expectation->getMock())
                ->setMethodName((string) $this->_expectation)
                ->setExpectedCountComparative('=')
                ->setExpectedCount($this->_limit)
                ->setActualCount($n);
            throw $exception;

        }
    }

}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */
 
namespace Mockery;

class CompositeExpectation
{

    /**
     * Stores an array of all expectations for this composite
     *
     * @var array
     */
    protected $_expectations = array();
    
    /**
     * Add an expectation to the composite
     *
     * @param \Mockery\Expectation|\Mockery\CompositeExpectation $expectation
     * @return void
     */
    public function add($expectation)
    {
        $this->_expectations[] = $expectation;
    }
    
    /**
     * Intercept any expectation calls and direct against all expectations
     *
     * @param string $method
     * @param array $args
     * @return self
     */
    public function __call($method, array $args)
    {
        foreach ($this->_expectations as $expectation) {
            call_user_func_array(array($expectation, $method), $args);
        }
        return $this;
    }
    
    /**
     * Return order number of the first expectation
     *
     * @return int
     */
    public function getOrderNumber()
    {
        reset($this->_expectations);
        $first = current($this->_expectations);
        return $first->getOrderNumber();
    }
    
    /**
     * Return the parent mock of the first expectation
     *
     * @return \Mockery\MockInterface
     */
    public function getMock()
    {
        reset($this->_expectations);
        $first = current($this->_expectations);
        return $first->getMock();
    }
    
    /**
     * Mockery API alias to getMock
     *
     * @return \Mockery\MockInterface
     */
    public function mock()
    {
        return $this->getMock();
    }
    
    /**
     * Starts a new expectation addition on the first mock which is the primary
     * target outside of a demeter chain
     *
     * @return \Mockery\Expectation
     */
    public function shouldReceive()
    {
        $args = func_get_args();
        reset($this->_expectations);
        $first = current($this->_expectations);
        return call_user_func_array(array($first->getMock(), 'shouldReceive'), $args);
    }
    
    /**
     * Return the string summary of this composite expectation
     *
     * @return string
     */
    public function __toString()
    {
        $return = '[';
        $parts = array();
        foreach ($this->_expectations as $exp) {
            $parts[] = (string) $exp;
        }
        $return .= implode(', ', $parts) . ']';
        return $return;
    }

}
<?php
/**
 * SplClassLoader implementation that implements the technical interoperability
 * standards for PHP 5.3 namespaces and class names.
 *
 * http://groups.google.com/group/php-standards/web/final-proposal
 *
 *     // Example which loads classes for the Doctrine Common package in the
 *     // Doctrine\Common namespace.
 *     $classLoader = new SplClassLoader('Doctrine\Common', '/path/to/doctrine');
 *     $classLoader->register();
 *
 * @author Jonathan H. Wage <jonwage@gmail.com>
 * @author Roman S. Borschel <roman@code-factory.org>
 * @author Matthew Weier O'Phinney <matthew@zend.com>
 * @author Kris Wallsmith <kris.wallsmith@gmail.com>
 * @author Fabien Potencier <fabien.potencier@symfony-project.org>
 */

namespace Mockery;

class Loader
{
    private $_fileExtension = '.php';
    private $_namespace;
    private $_includePath;
    private $_namespaceSeparator = '\\';

    /**
     * Creates a new <tt>Loader</tt> that loads classes of the
     * specified namespace.
     * 
     * @param string $ns The namespace to use.
     */
    public function __construct($ns = 'Mockery', $includePath = null)
    {
        $this->_namespace = $ns;
        $this->_includePath = $includePath;
    }

    /**
     * Sets the namespace separator used by classes in the namespace of this class loader.
     * 
     * @param string $sep The separator to use.
     */
    public function setNamespaceSeparator($sep)
    {
        $this->_namespaceSeparator = $sep;
    }

    /**
     * Gets the namespace seperator used by classes in the namespace of this class loader.
     *
     * @return void
     */
    public function getNamespaceSeparator()
    {
        return $this->_namespaceSeparator;
    }

    /**
     * Sets the base include path for all class files in the namespace of this class loader.
     * 
     * @param string $includePath
     */
    public function setIncludePath($includePath)
    {
        $this->_includePath = $includePath;
    }

    /**
     * Gets the base include path for all class files in the namespace of this class loader.
     *
     * @return string $includePath
     */
    public function getIncludePath()
    {
        return $this->_includePath;
    }

    /**
     * Sets the file extension of class files in the namespace of this class loader.
     * 
     * @param string $fileExtension
     */
    public function setFileExtension($fileExtension)
    {
        $this->_fileExtension = $fileExtension;
    }

    /**
     * Gets the file extension of class files in the namespace of this class loader.
     *
     * @return string $fileExtension
     */
    public function getFileExtension()
    {
        return $this->_fileExtension;
    }

    /**
     * Installs this class loader on the SPL autoload stack.
	 *
	 * @param bool $prepend If true, prepend autoloader on the autoload stack
     */
    public function register($prepend = false)
    {
        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
    }

    /**
     * Uninstalls this class loader from the SPL autoloader stack.
     */
    public function unregister()
    {
        spl_autoload_unregister(array($this, 'loadClass'));
    }

    /**
     * Loads the given class or interface.
     *
     * @param string $className The name of the class to load.
     * @return void
     */
    public function loadClass($className)
    {
        if ($className === 'Mockery') {
            require $this->getFullPath('Mockery.php');
            return;
        }
        if (null === $this->_namespace
        || $this->_namespace.$this->_namespaceSeparator === substr($className, 0, strlen($this->_namespace.$this->_namespaceSeparator))) {
            $fileName = '';
            $namespace = '';
            if (false !== ($lastNsPos = strripos($className, $this->_namespaceSeparator))) {
                $namespace = substr($className, 0, $lastNsPos);
                $className = substr($className, $lastNsPos + 1);
                $fileName = str_replace($this->_namespaceSeparator, DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
            }
            $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . $this->_fileExtension;
            require $this->getFullPath($fileName);
        }
    }

	/**
	 * Returns full path for $fileName if _includePath is set, or leaves as-is for PHP's internal search in 'require'.
	 *
	 * @param string $fileName relative to include path.
	 * @return string
	 */
	private function getFullPath($fileName)
	{
		return ($this->_includePath !== null ? $this->_includePath . DIRECTORY_SEPARATOR : '') . $fileName;
	}
}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */
 
namespace Mockery;

class Expectation
{

    /**
     * Mock object to which this expectation belongs
     *
     * @var object
     */
    protected $_mock = null;
    
    /**
     * Method name 
     *
     * @var string
     */
    protected $_name = null;
    
    /**
     * Arguments expected by this expectation
     *
     * @var array
     */
    protected $_expectedArgs = array();
    
    /**
     * Count validator store
     *
     * @var array
     */
    protected $_countValidators = array();
    
    /**
     * The count validator class to use
     *
     * @var string
     */
    protected $_countValidatorClass = 'Mockery\CountValidator\Exact';
    
    /**
     * Actual count of calls to this expectation
     *
     * @var int
     */
    protected $_actualCount = 0;
    
    /**
     * Value to return from this expectation
     *
     * @var mixed
     */
    protected $_returnValue = null;
    
    /**
     * Array of return values as a queue for multiple return sequence
     *
     * @var array
     */
    protected $_returnQueue = array();
    
    /**
     * Array of closures executed with given arguments to generate a result
     * to be returned
     *
     * @var array
     */
    protected $_closureQueue = array();
    
    /**
     * Integer representing the call order of this expectation
     *
     * @var int
     */
    protected $_orderNumber = null;
    
    /**
     * Integer representing the call order of this expectation on a global basis
     *
     * @var int
     */
    protected $_globalOrderNumber = null;
    
    /**
     * Flag indicating that an exception is expected to be throw (not returned)
     *
     * @var bool
     */
    protected $_throw = false;
    
    /**
     * Flag indicating whether the order of calling is determined locally or
     * globally
     *
     * @var bool
     */
    protected $_globally = false;
    
    /**
     * Flag indicating we expect no arguments
     *
     * @var bool
     */
    protected $_noArgsExpectation = false;
    
    /**
     * Constructor
     *
     * @param \Mockery\MockInterface $mock
     * @param string $name
     */
    public function __construct(\Mockery\MockInterface $mock, $name)
    {
        $this->_mock = $mock;
        $this->_name = $name;
    }
    
    /**
     * Return a string with the method name and arguments formatted
     *
     * @param string $name Name of the expected method
     * @param array $args List of arguments to the method
     * @return string
     */
    public function __toString()
    {
        return \Mockery::formatArgs($this->_name, $this->_expectedArgs);
    }
    
    /**
     * Verify the current call, i.e. that the given arguments match those
     * of this expectation
     *
     * @param array $args
     * @return mixed
     */
    public function verifyCall(array $args)
    {
        $this->validateOrder();
        $this->_actualCount++;
        $return = $this->_getReturnValue($args);
        if ($return instanceof \Exception && $this->_throw === true) {
            throw $return;
        }
        return $return; 
    }
    
    /**
     * Fetch the return value for the matching args
     *
     * @param array $args
     * @return mixed
     */
    protected function _getReturnValue(array $args)
    {
        if (count($this->_closureQueue) > 1) {
            return call_user_func_array(array_shift($this->_closureQueue), $args);
        } elseif (count($this->_closureQueue) > 0) {
            return call_user_func_array(current($this->_closureQueue), $args);
        } elseif (count($this->_returnQueue) > 1) {
            return array_shift($this->_returnQueue);
        } elseif (count($this->_returnQueue) > 0) {
            return current($this->_returnQueue);
        }
    }

    /**
     * Checks if this expectation is eligible for additional calls
     *
     * @return bool
     */
    public function isEligible()
    {
        foreach ($this->_countValidators as $validator) {
            if (!$validator->isEligible($this->_actualCount)) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * Check if there is a constraint on call count
     *
     * @return bool
     */
    public function isCallCountConstrained()
    {
        return (count($this->_countValidators) > 0);
    }
    
    /**
     * Verify call order
     *
     * @return void
     */
    public function validateOrder()
    {
        if ($this->_orderNumber) {
            $this->_mock->mockery_validateOrder((string) $this, $this->_orderNumber, $this->_mock);
        }
        if ($this->_globalOrderNumber) {
            $this->_mock->mockery_getContainer()
                ->mockery_validateOrder((string) $this, $this->_globalOrderNumber, $this->_mock);
        }
    }
    
    /**
     * Verify this expectation
     *
     * @return bool
     */
    public function verify()
    {
        foreach ($this->_countValidators as $validator) {
            $validator->validate($this->_actualCount);
        }
    }
    
    /**
     * Check if passed arguments match an argument expectation
     *
     * @param array $args
     * @return bool
     */
    public function matchArgs(array $args)
    {
        if(empty($this->_expectedArgs) && !$this->_noArgsExpectation) {
            return true;
        }
        if(count($args) !== count($this->_expectedArgs)) {
            return false;
        }
        for ($i=0; $i<count($args); $i++) {
            $param =& $args[$i];
            if (!$this->_matchArg($this->_expectedArgs[$i], $param)) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * Check if passed argument matches an argument expectation
     *
     * @param array $args
     * @return bool
     */
    protected function _matchArg($expected, &$actual)
    {
        if ($expected === $actual) {
            return true;
        }
        if (!is_object($expected) && !is_object($actual) && $expected == $actual) {
            return true;
        }
        if (is_string($expected) && !is_array($actual) && !is_object($actual)) {
            $result = @preg_match($expected, (string) $actual);
            if($result) {
                return true;
            }
        }
        if (is_string($expected) && is_object($actual)) {
            $result = $actual instanceof $expected;
            if($result) {
                return true;
            }
        }
        if ($expected instanceof \Mockery\Matcher\MatcherAbstract) {
            return $expected->match($actual);
        }
        if ($expected instanceof \Hamcrest_Matcher) {
            return $expected->matches($actual);
        }
        return false;
    }
    
    /**
     * Expected argument setter for the expectation
     *
     * @param mixed
     * @return self
     */
    public function with()
    {
        $this->_expectedArgs = func_get_args();
        return $this;
    }
    
    /**
     * Set with() as no arguments expected
     *
     * @return self
     */
    public function withNoArgs()
    {
        $this->_noArgsExpectation = true;
        return $this->with();
    }
    
    /**
     * Set expectation that any arguments are acceptable
     *
     * @return self
     */
    public function withAnyArgs()
    {
        $this->_expectedArgs = array();
        return $this;
    }
    
    /**
     * Set a return value, or sequential queue of return values
     *
     * @return self
     */
    public function andReturn()
    {
        $this->_returnQueue = func_get_args();
        return $this;
    }

    /**
     * Set a sequential queue of return values with an array
     *
     * @return self
     */
    public function andReturnValues(array $values)
    {
        call_user_func_array(array($this, 'andReturn'), $values);
        return $this;
    }
    
    /**
     * Set a closure or sequence of closures with which to generate return
     * values. The arguments passed to the expected method are passed to the
     * closures as parameters.
     *
     * @return self
     */
    public function andReturnUsing()
    {
        $this->_closureQueue = func_get_args();
        return $this;
    }
    
    /**
     * Return a self-returning black hole object.
     *
     * @return self
     */
    public function andReturnUndefined()
    {
        $this->andReturn(new \Mockery\Undefined);
        return $this;
    }

    /**
     * Return null. This is merely a language construct for Mock describing.
     *
     * @return self
     */
    public function andReturnNull()
    {
        return $this;
    }
    
    /**
     * Set Exception class and arguments to that class to be thrown
     *
     * @param string $exception
     * @param string $message
     * @param int $code
     * @param Exception $previous
     * @return self
     */
    public function andThrow($exception, $message = '', $code = 0, \Exception $previous = null)
    {
        $this->_throw = true;
        if (is_object($exception)) {
            $this->andReturn($exception);
        } else {
            $this->andReturn(new $exception($message, $code, $previous));
        }
        return $this;
    }
    
    /**
     * Set a public property on the mock
     *
     * @param string $name
     * @param mixed $value
     * @return self
     */
    public function andSet($name, $value)
    {
        $this->_mock->{$name} = $value;
        return $this;
    }
    
    /**
     * Set a public property on the mock (alias to andSet()). Allows the natural
     * English construct - set('foo', 'bar')->andReturn('bar')
     *
     * @param string $name
     * @param mixed $value
     * @return self
     */
    public function set($name, $value)
    {
        return $this->andSet($name, $value);
    }
    
    /**
     * Indicates this expectation should occur zero or more times
     *
     * @return self
     */
    public function zeroOrMoreTimes()
    {
        $this->atLeast()->never();
    }
    
    /**
     * Indicates the number of times this expectation should occur
     *
     * @param int $limit
     */
    public function times($limit = null)
    {
        if (is_null($limit)) return $this;
        $this->_countValidators[] = new $this->_countValidatorClass($this, $limit);
        $this->_countValidatorClass = 'Mockery\CountValidator\Exact';
        return $this;
    }
    
    /**
     * Indicates that this expectation is never expected to be called
     *
     * @return self
     */
    public function never()
    {
        return $this->times(0);
    }
    
    /**
     * Indicates that this expectation is expected exactly once
     *
     * @return self
     */
    public function once()
    {
        return $this->times(1);
    }
    
    /**
     * Indicates that this expectation is expected exactly twice
     *
     * @return self
     */
    public function twice()
    {
        return $this->times(2);
    }
    
    /**
     * Sets next count validator to the AtLeast instance
     *
     * @return self
     */
    public function atLeast()
    {
        $this->_countValidatorClass = 'Mockery\CountValidator\AtLeast';
        return $this;
    }
    
    /**
     * Sets next count validator to the AtMost instance
     *
     * @return self
     */
    public function atMost()
    {
        $this->_countValidatorClass = 'Mockery\CountValidator\AtMost';
        return $this;
    }
    
    /**
     * Shorthand for setting minimum and maximum constraints on call counts
     *
     * @param int $minimum
     * @param int $maximum
     */
    public function between($minimum, $maximum)
    {
        return $this->atLeast()->times($minimum)->atMost()->times($maximum);
    }
    
    /**
     * Indicates that this expectation must be called in a specific given order
     *
     * @param string $group Name of the ordered group
     * @return self
     */
    public function ordered($group = null)
    {
        if ($this->_globally) {
            $this->_globalOrderNumber = $this->_defineOrdered($group, $this->_mock->mockery_getContainer());
        } else {
            $this->_orderNumber = $this->_defineOrdered($group, $this->_mock);
        }
        $this->_globally = false;
        return $this;
    }
    
    /**
     * Indicates call order should apply globally
     *
     * @return self
     */
    public function globally()
    {
        $this->_globally = true;
        return $this;
    }
    
    /**
     * Setup the ordering tracking on the mock or mock container
     *
     * @param string $group
     * @param object $ordering
     * @return int
     */
    protected function _defineOrdered($group, $ordering)
    {
        $groups = $ordering->mockery_getGroups();
        if (is_null($group)) {
            $result = $ordering->mockery_allocateOrder();
        } elseif (isset($groups[$group])) {
            $result = $groups[$group];
        } else {
            $result = $ordering->mockery_allocateOrder();
            $ordering->mockery_setGroup($group, $result);
        }
        return $result;
    }
    
    /**
     * Return order number
     *
     * @return int
     */
    public function getOrderNumber()
    {
        return $this->_orderNumber;
    }
    
    /**
     * Mark this expectation as being a default
     *
     * @return self
     */
    public function byDefault()
    {
        $director = $this->_mock->mockery_getExpectationsFor($this->_name);
        if(!empty($director)) {
            $director->makeExpectationDefault($this);
        }
        return $this;
    }
    
    /**
     * Return the parent mock of the expectation
     *
     * @return \Mockery\MockInterface
     */
    public function getMock()
    {
        return $this->_mock;
    }
    
    /**
     * Cloning logic
     *
     */
    public function __clone()
    {
        $newValidators = array();
        $countValidators = $this->_countValidators;
        foreach ($countValidators as $validator) {
            $newValidators[] = clone $validator;
        } 
        $this->_countValidators = $newValidators;
    }

}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */
 
namespace Mockery;

class Container
{
    const BLOCKS = \Mockery::BLOCKS;

    /**
     * Store of mock objects
     *
     * @var array
     */
    protected $_mocks = array();
    
    /**
     * Order number of allocation
     *
     * @var int
     */
    protected $_allocatedOrder = 0;
    
    /**
     * Current ordered number
     *
     * @var int
     */
    protected $_currentOrder = 0;
    
    /**
     * Ordered groups
     *
     * @var array
     */
    protected $_groups = array();
    
    /**
     * Generates a new mock object for this container
     *
     * I apologies in advance for this. A God Method just fits the API which
     * doesn't require differentiating between classes, interfaces, abstracts,
     * names or partials - just so long as it's something that can be mocked.
     * I'll refactor it one day so it's easier to follow.
     *
     * @return \Mockery\Mock
     */
    public function mock()
    {
        $class = null;
        $name = null;
        $partial = null;
        $expectationClosure = null;
        $quickdefs = array();
        $constructorArgs = null;
        $blocks = array();
        $makeInstanceMock = false;
        $args = func_get_args();
        $partialMethods = array();
        if (count($args) > 1) {
            $finalArg = end($args);
            reset($args);
            if (is_callable($finalArg) && !is_array($finalArg)) {
                $expectationClosure = array_pop($args);
            }
        }
        while (count($args) > 0) {
            $arg = current($args);
            // check for multiple interfaces
            if (is_string($arg) && strpos($arg, ',') && !strpos($arg, ']')) {
                $interfaces = explode(',', str_replace(' ', '', $arg));
                foreach ($interfaces as $i) {
                    if (!interface_exists($i, true) && !class_exists($i, true)) {
                        throw new \Mockery\Exception(
                            'Class name follows the format for defining multiple'
                            . ' interfaces, however one or more of the interfaces'
                            . ' do not exist or are not included, or the base class'
                            . ' (which you may omit from the mock definition) does not exist'
                        );
                    }
                }
                $class = $interfaces;
                array_shift($args);
            } elseif (is_string($arg) && substr($arg, 0, 6) == 'alias:') {
                $class = 'stdClass';
                $name = array_shift($args);
                $name = str_replace('alias:', '', $name);
            } elseif (is_string($arg) && substr($arg, 0, 9) == 'overload:') {
                $class = 'stdClass';
                $name = array_shift($args);
                $name = str_replace('overload:', '', $name);
                $makeInstanceMock = true;
            } elseif (is_string($arg) && substr($arg, strlen($arg)-1, 1) == ']') {
                $parts = explode('[', $arg);
                if (!class_exists($parts[0], true) && !interface_exists($parts[0], true)) {
                    throw new \Mockery\Exception('Can only create a partial mock from'
                    . ' an existing class or interface');
                }
                $class = $parts[0];
                $parts[1] = str_replace(' ','', $parts[1]);
                $partialMethods = explode(',', strtolower(rtrim($parts[1], ']')));
                array_shift($args);
            } elseif (is_string($arg) && (class_exists($arg, true) || interface_exists($arg, true))) {
                $class = array_shift($args);
            } elseif (is_string($arg)) {
                $class = array_shift($args);
                $this->declareClass($class);
            } elseif (is_object($arg)) {
                $partial = array_shift($args);
            } elseif (is_array($arg) && array_keys($arg) !== range(0, count($arg) - 1)) {
                // if associative array
                if(array_key_exists(self::BLOCKS, $arg)) $blocks = $arg[self::BLOCKS]; unset($arg[self::BLOCKS]);
                $quickdefs = array_shift($args);
            } elseif (is_array($arg)) {
                $constructorArgs = array_shift($args);
                $blocks[] = "__construct"; // Assume they want to use the actual constructor regardless of other requirements
            } else {
                throw new \Mockery\Exception(
                    'Unable to parse arguments sent to '
                    . get_class($this) . '::mock()'
                );
            }
        }
        if (!is_null($name) && !is_null($class)) {
            if (!$makeInstanceMock) {
                $mockName = \Mockery\Generator::createClassMock($class, null, null, $blocks);
            } else {
                $mockName = \Mockery\Generator::createClassMock($class, null, null, $blocks, true);
            }
            $result = class_alias($mockName, $name);
            $mock = $this->_getInstance($name, $constructorArgs);
            $mock->mockery_init($class, $this);
        } elseif (!is_null($name)) {
            $mock = new \Mockery\Mock();
            $mock->mockery_init($name, $this);
        } elseif(!is_null($class)) {
            $mockName = \Mockery\Generator::createClassMock($class, null, null, $blocks, false, $partialMethods);
            $mock = $this->_getInstance($mockName, $constructorArgs);
            $mock->mockery_init($class, $this);
        } elseif(!is_null($partial)) {
            $mockName = \Mockery\Generator::createClassMock(get_class($partial), null, true, $blocks);
            $mock = $this->_getInstance($mockName, $constructorArgs);
            $mock->mockery_init(get_class($partial), $this, $partial);
        } else {
            $mock = new \Mockery\Mock();
            $mock->mockery_init('unknown', $this);
        }
        if (!empty($quickdefs)) {
            $mock->shouldReceive($quickdefs);
        }
        if (!empty($expectationClosure)) {
            $expectationClosure($mock);
        }
        $this->rememberMock($mock);
        return $mock;
    }
    
    public function instanceMock()
    {
        
    }
    
    /**
     *  Tear down tasks for this container
     *
     * @return void
     */
    public function mockery_teardown()
    {
        try {
            $this->mockery_verify();
        } catch (\Exception $e) {
            $this->mockery_close();
            throw $e;
        }
    }
    
    /**
     * Verify the container mocks
     *
     * @return void
     */
    public function mockery_verify()
    {
        foreach($this->_mocks as $mock) {
            $mock->mockery_verify();
        }
    }
    
    /**
     * Reset the container to its original state
     *
     * @return void
     */
    public function mockery_close()
    {
        foreach($this->_mocks as $mock) {
            $mock->mockery_teardown();
        }
        $this->_mocks = array();
    }
    
    /**
     * Fetch the next available allocation order number
     *
     * @return int
     */
    public function mockery_allocateOrder()
    {
        $this->_allocatedOrder += 1;
        return $this->_allocatedOrder;
    }
    
    /**
     * Set ordering for a group
     *
     * @param mixed $group
     * @param int $order
     */
    public function mockery_setGroup($group, $order)
    {
        $this->_groups[$group] = $order;
    }
    
    /**
     * Fetch array of ordered groups
     *
     * @return array
     */
    public function mockery_getGroups()
    {
        return $this->_groups;
    }
    
    /**
     * Set current ordered number
     *
     * @param int $order
     * @return int The current order number that was set
     */
    public function mockery_setCurrentOrder($order)
    {
        $this->_currentOrder = $order;
        return $this->_currentOrder;
    }
    
    /**
     * Get current ordered number
     *
     * @return int
     */
    public function mockery_getCurrentOrder()
    {
        return $this->_currentOrder;
    }
    
    /**
     * Validate the current mock's ordering
     *
     * @param string $method
     * @param int $order
     * @throws \Mockery\Exception
     * @return void
     */
    public function mockery_validateOrder($method, $order, \Mockery\MockInterface $mock)
    {
        if ($order < $this->_currentOrder) {
            $exception = new \Mockery\Exception\InvalidOrderException(
                'Method ' . $method . ' called out of order: expected order '
                . $order . ', was ' . $this->_currentOrder
            );
            $exception->setMock($mock)
                ->setMethodName($method)
                ->setExpectedOrder($order)
                ->setActualOrder($this->_currentOrder);
            throw $exception;
        }
        $this->mockery_setCurrentOrder($order);
    }
    
    /**
     * Gets the count of expectations on the mocks
     *
     * @return int
     */
    public function mockery_getExpectationCount()
    {
        $count = 0;
        foreach($this->_mocks as $mock) {
            $count += $mock->mockery_getExpectationCount();
        }
        return $count;
    }
    
    /**
     * Store a mock and set its container reference
     *
     * @param \Mockery\Mock
     * @return \Mockery\Mock
     */
    public function rememberMock(\Mockery\MockInterface $mock)
    {
        if (!isset($this->_mocks[get_class($mock)])) {
            $this->_mocks[get_class($mock)] = $mock;
        } else {
            /**
             * This condition triggers for an instance mock where origin mock
             * is already remembered
             */
            $this->_mocks[] = $mock;
        }
        return $mock;
    }

    /**
     * Retrieve the last remembered mock object, which is the same as saying
     * retrieve the current mock being programmed where you have yet to call
     * mock() to change it - thus why the method name is "self" since it will be
     * be used during the programming of the same mock.
     *
     * @return \Mockery\Mock
     */
    public function self()
    {
        $mocks = array_values($this->_mocks);
        $index = count($mocks) - 1;
        return $mocks[$index];
    }
    
    /**
     * Return a specific remembered mock according to the array index it
     * was stored to in this container instance
     *
     * @return \Mockery\Mock
     */
    public function fetchMock($reference)
    {
        if (isset($this->_mocks[$reference])) return $this->_mocks[$reference];
    }
    
    protected function _getInstance($mockName, $constructorArgs = null)
    {
        if (!method_exists($mockName, '__construct')) {
            $return = new $mockName;
            return $return;
        }

        if ($constructorArgs !== null) {
            $r = new \ReflectionClass($mockName);
            return $r->newInstanceArgs($constructorArgs);
        }

        $return = unserialize(sprintf('O:%d:"%s":0:{}', strlen($mockName), $mockName));
        return $return;
    }

    /**
     * Takes a class name and declares it
     *
     * @param string $fqcn
     */
    public function declareClass($fqcn)
    {
        if (false !== strpos($fqcn, '/')) {
            throw new \Mockery\Exception(
                'Class name contains a forward slash instead of backslash needed '
                . 'when employing namespaces'
            );
        }
        if (false !== strpos($fqcn, "\\")) {
            $parts = array_filter(explode("\\", $fqcn), function($part) {
                return $part !== "";
            });
            $cl = array_pop($parts);
            $ns = implode("\\", $parts);
            eval(" namespace $ns { class $cl {} }");
        } else {
            eval(" class $fqcn {} ");
        }
    }

}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */
 
namespace Mockery;

class Recorder
{

    /**
     * Mock object on which all recorded interactions will be set as
     * expectations
     *
     * @var object
     */
    protected $_mock = null;
    
    /**
     * The subject object whose interactions are being recorded
     *
     * @var object
     */
    protected $_subject = null;
    
    /**
     * Flag indicating whether the recording should maintain a strict adherence
     * to the recorded interactions, i.e. the usual Mockery flexibility is
     * suspended, ordering is enforced, and arguments received are set as
     * exact requirements.
     *
     * @var bool
     */
    protected $_strict = false;
    
    /**
     * Construct accepting the mock object on which expectations are to be
     * recorded. The second parameter is the subject object, passed into
     * a \Mockery::mock() call in the same way as a partial mock requires.
     *
     * @param \Mockery\MockInterface $mock
     * @param object $subject
     * @return void
     */
    public function __construct(\Mockery\MockInterface $mock, $subject)
    {
        $this->_mock = $mock;
        $this->_subject = $subject;
    }
    
    /**
     * Sets the recorded into strict mode where method calls are more strictly
     * matched against the argument and call count and ordering is also
     * set as enforceable.
     *
     * @return void
     */
    public function shouldBeStrict()
    {
        $this->_strict = true;
    }

    /**
     * Intercept all calls on the subject, and use the call details to create
     * a new expectation. The actual return value is then returned after being
     * recorded.
     *
     * @param string $method
     * @param array $args
     * @return mixed
     */
    public function __call($method, array $args)
    {
        $return = call_user_func_array(array($this->_subject, $method), $args);
        $expectation = $this->_mock->shouldReceive($method)->andReturn($return);
        if ($this->_strict) {
            $exactArgs = array();
            foreach ($args as $arg) {
                $exactArgs[] = \Mockery::mustBe($arg);
            }
            $expectation->once()->ordered();
            call_user_func_array(array($expectation, 'with'), $exactArgs);
        } else {
            call_user_func_array(array($expectation, 'with'), $args);
        }
        return $return;
    }
}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */
 
namespace Mockery;

class Mock implements MockInterface
{

    /**
     * Stores an array of all expectation directors for this mock
     *
     * @var array
     */
    protected $_mockery_expectations = array();
    
    /**
     * Last expectation that was set
     *
     * @var object
     */
    protected $_mockery_lastExpectation = null;
    
    /**
     * Flag to indicate whether we can ignore method calls missing from our
     * expectations
     *
     * @var bool
     */
    protected $_mockery_ignoreMissing = false;

    protected $_mockery_ignoreMissingAsUndefined = false;
    
    /**
     * Flag to indicate whether we can defer method calls missing from our
     * expectations
     *
     * @var bool
     */
    protected $_mockery_deferMissing = false;

    /**
     * Flag to indicate whether this mock was verified
     *
     * @var bool
     */
    protected $_mockery_verified = false;
    
    /**
     * Given name of the mock
     *
     * @var string
     */
    protected $_mockery_name = null;
    
    /**
     * Order number of allocation
     *
     * @var int
     */
    protected $_mockery_allocatedOrder = 0;
    
    /**
     * Current ordered number
     *
     * @var int
     */
    protected $_mockery_currentOrder = 0;
    
    /**
     * Ordered groups
     *
     * @var array
     */
    protected $_mockery_groups = array();
    
    /**
     * Mock container containing this mock object
     *
     * @var \Mockery\Container
     */
    protected $_mockery_container = null;
    
    /**
     * Instance of a core object on which methods are called in the event
     * it has been set, and an expectation for one of the object's methods
     * does not exist. This implements a simple partial mock proxy system.
     *
     * @var object
     */
    protected $_mockery_partial = null;
    
    /**
     * Flag to indicate we should ignore all expectations temporarily. Used
     * mainly to prevent expectation matching when in the middle of a mock
     * object recording session.
     *
     * @var bool
     */
    protected $_mockery_disableExpectationMatching = false;
    
    /**
     * Stores all stubbed public methods separate from any on-object public
     * properties that may exist.
     *
     * @var array
     */
    protected $_mockery_mockableProperties = array();
    
    /**
     * We want to avoid constructors since class is copied to Generator.php
     * for inclusion on extending class definitions.
     *
     * @param string $name
     * @param \Mockery\Container $container
     * @param object $partialObject
     * @return void
     */
    public function mockery_init($name, \Mockery\Container $container = null, $partialObject = null)
    {
        $this->_mockery_name = $name;
        if(is_null($container)) {
            $container = new \Mockery\Container;
        }
        $this->_mockery_container = $container;
        if (!is_null($partialObject)) {
            $this->_mockery_partial = $partialObject;
        }
    }
    
    /**
     * Set expected method calls
     *
     * @param mixed
     * @return \Mockery\Expectation
     */
    public function shouldReceive()
    {
        $self = $this;
        $lastExpectation = \Mockery::parseShouldReturnArgs(
            $this, func_get_args(), function($method) use ($self) {
                $director = $self->mockery_getExpectationsFor($method);
                if (!$director) {
                    $director = new \Mockery\ExpectationDirector($method, $self);
                    $self->mockery_setExpectationsFor($method, $director);
                }
                $expectation = new \Mockery\Expectation($self, $method);
                $director->addExpectation($expectation);
                return $expectation;
            }
        );
        return $lastExpectation;
    }
    
    /**
     * Set mock to ignore unexpected methods and return Undefined class
     *
     * @return Mock
     */
    public function shouldIgnoreMissing()
    {
        $this->_mockery_ignoreMissing = true;
        return $this;
    }

    public function asUndefined()
    {
        $this->_mockery_ignoreMissingAsUndefined = true;
        return $this;
    }
    
    /**
     * Set mock to defer unexpected methods to it's parent
     *
     * This is particularly useless for this class, as it doesn't have a parent, 
     * but included for completeness
     *
     * @return Mock
     */
    public function shouldDeferMissing()
    {
        $this->_mockery_deferMissing = true;
        return $this;
    }

    /**
     * Create an obviously worded alias to shouldDeferMissing()
     *
     * @return Mock
     */
    public function makePartial()
    {
        return $this->shouldDeferMissing();
    }

    /**
     * Accepts a closure which is executed with an object recorder which proxies
     * to the partial source object. The intent being to record the
     * interactions of a concrete object as a set of expectations on the
     * current mock object. The partial may then be passed to a second process
     * to see if it fulfils the same (or exact same) contract as the original.
     *
     * @param Closure $closure
     */
    public function shouldExpect(\Closure $closure)
    {
        $recorder = new \Mockery\Recorder($this, $this->_mockery_partial);
        $this->_mockery_disableExpectationMatching = true;
        $closure($recorder);
        $this->_mockery_disableExpectationMatching = false;
        return $this;
    }
    
    /**
     * In the event shouldReceive() accepting one or more methods/returns,
     * this method will switch them from normal expectations to default
     * expectations
     *
     * @return self
     */
    public function byDefault()
    {
        foreach ($this->_mockery_expectations as $director) {
            $exps = $director->getExpectations();
            foreach ($exps as $exp) {
                $exp->byDefault();
            }
        }
        return $this;
    }

    /**
     * Capture calls to this mock
     */
    public function __call($method, array $args)
    {
        if (isset($this->_mockery_expectations[$method])
        && !$this->_mockery_disableExpectationMatching) {
            $handler = $this->_mockery_expectations[$method];
            return $handler->call($args);
        } elseif (!is_null($this->_mockery_partial) && method_exists($this->_mockery_partial, $method)) {
            return call_user_func_array(array($this->_mockery_partial, $method), $args);
        } elseif ($this->_mockery_deferMissing && is_callable("parent::$method")) {
            return call_user_func_array("parent::$method", $args);
        } elseif ($this->_mockery_ignoreMissing) {
            if ($this->_mockery_ignoreMissingAsUndefined === true) {
                $undef = new \Mockery\Undefined;
                return call_user_func_array(array($undef, $method), $args);
            } else {
                return null;
            }
        }
        throw new \BadMethodCallException(
            'Method ' . $this->_mockery_name . '::' . $method . '() does not exist on this mock object'
        );
    }
    
    /**
     * Forward calls to this magic method to the __call method
     */
    public function __toString()
    {
        return $this->__call('__toString', array());
    }
    
    /**public function __set($name, $value)
    {
        $this->_mockery_mockableProperties[$name] = $value;
        return $this;
    }
            	            
    public function __get($name)
    {
        if (isset($this->_mockery_mockableProperties[$name])) {
            return $this->_mockery_mockableProperties[$name];
        } elseif(isset($this->{$name})) {
            return $this->{$name};
        }   	                			    
        throw new \InvalidArgumentException (
            'Property ' . $this->_mockery_name . '::' . $name . ' does not exist on this mock object'
        );
    }**/
    
    /**
     * Iterate across all expectation directors and validate each
     *
     * @throws \Mockery\CountValidator\Exception
     * @return void
     */
    public function mockery_verify()
    {
        if ($this->_mockery_verified) return true;
        $this->_mockery_verified = true;
        foreach($this->_mockery_expectations as $director) {
            $director->verify();
        }
    }
    
    /**
     * Tear down tasks for this mock
     *
     * @return void
     */
    public function mockery_teardown()
    {
        
    }
    
    /**
     * Fetch the next available allocation order number
     *
     * @return int
     */
    public function mockery_allocateOrder()
    {
        $this->_mockery_allocatedOrder += 1;
        return $this->_mockery_allocatedOrder;
    }
    
    /**
     * Set ordering for a group
     *
     * @param mixed $group
     * @param int $order
     */
    public function mockery_setGroup($group, $order)
    {
        $this->_mockery_groups[$group] = $order;
    }
    
    /**
     * Fetch array of ordered groups
     *
     * @return array
     */
    public function mockery_getGroups()
    {
        return $this->_mockery_groups;
    }
    
    /**
     * Set current ordered number
     *
     * @param int $order
     */
    public function mockery_setCurrentOrder($order)
    {
        $this->_mockery_currentOrder = $order;
        return $this->_mockery_currentOrder;
    }
    
    /**
     * Get current ordered number
     *
     * @return int
     */
    public function mockery_getCurrentOrder()
    {
        return $this->_mockery_currentOrder;
    }
    
    /**
     * Validate the current mock's ordering
     *
     * @param string $method
     * @param int $order
     * @throws \Mockery\Exception
     * @return void
     */
    public function mockery_validateOrder($method, $order)
    {
        if ($order < $this->_mockery_currentOrder) {
            $exception = new \Mockery\Exception\InvalidOrderException(
                'Method ' . $this->_mockery_name . '::' . $method . '()'
                . ' called out of order: expected order '
                . $order . ', was ' . $this->_mockery_currentOrder
            );
            $exception->setMock($this)
                ->setMethodName($method)
                ->setExpectedOrder($order)
                ->setActualOrder($this->_mockery_currentOrder);
            throw $exception;
        }
        $this->mockery_setCurrentOrder($order);
    }
    
    /**
     * Gets the count of expectations for this mock
     *
     * @return int
     */
    public function mockery_getExpectationCount()
    {
        $count = 0;
        foreach($this->_mockery_expectations as $director) {
            $count += $director->getExpectationCount();
        }
        return $count;
    }
    
    /**
     * Return the expectations director for the given method
     *
     * @var string $method
     * @return \Mockery\ExpectationDirector|null
     */
    public function mockery_setExpectationsFor($method, \Mockery\ExpectationDirector $director)
    {
        $this->_mockery_expectations[$method] = $director;
    }
    
    /**
     * Return the expectations director for the given method
     *
     * @var string $method
     * @return \Mockery\ExpectationDirector|null
     */
    public function mockery_getExpectationsFor($method)
    {
        if (isset($this->_mockery_expectations[$method])) {
            return $this->_mockery_expectations[$method];
        }
    }
    
    /**
     * Find an expectation matching the given method and arguments
     *
     * @var string $method
     * @var array $args
     * @return \Mockery\Expectation|null
     */
    public function mockery_findExpectation($method, array $args)
    {
        if (!isset($this->_mockery_expectations[$method])) {
            return null;
        }
        $director = $this->_mockery_expectations[$method];
        return $director->findExpectation($args);
    }
    
    /**
     * Return the container for this mock
     *
     * @return \Mockery\Container
     */
    public function mockery_getContainer()
    {
        return $this->_mockery_container;
    }
    
    /**
     * Return the name for this mock
     *
     * @return string
     */
    public function mockery_getName()
    {
        return $this->_mockery_name;
    }
    
    public function mockery_getMockableProperties()
    {
        return $this->_mockery_mockableProperties;
    }

}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */
 
namespace Mockery;

class Configuration
{

    /**
     * Boolean assertion of whether we can mock methods which do not actually
     * exist for the given class or object (ignored for unreal mocks)
     *
     * @var bool
     */
    protected $_allowMockingNonExistentMethod = true;
    
    /**
     * Boolean assertion of whether we ignore unnecessary mocking of methods,
     * i.e. when method expectations are made, set using a zeroOrMoreTimes()
     * constraint, and then never called. Essentially such expectations are
     * not required and are just taking up test space.
     *
     * @var bool
     */
    protected $_allowMockingMethodsUnnecessarily = true;
    
    /**
     * Parameter map for use with PHP internal classes.
     *
     * @var array
     */
    protected $_internalClassParamMap = array();
    
    /**
     * Set boolean to allow/prevent mocking of non-existent methods
     *
     * @param bool
     */
    public function allowMockingNonExistentMethods($flag = true)
    {
        $this->_allowMockingNonExistentMethod = (bool) $flag;
    }
    
    /**
     * Return flag indicating whether mocking non-existent methods allowed
     *
     * @return bool
     */
    public function mockingNonExistentMethodsAllowed()
    {
        return $this->_allowMockingNonExistentMethod;
    }
    
    /**
     * Set boolean to allow/prevent unnecessary mocking of methods
     *
     * @param bool
     */
    public function allowMockingMethodsUnnecessarily($flag = true)
    {
        $this->_allowMockingMethodsUnnecessarily = (bool) $flag;
    }
    
    /**
     * Return flag indicating whether mocking non-existent methods allowed
     *
     * @return bool
     */
    public function mockingMethodsUnnecessarilyAllowed()
    {
        return $this->_allowMockingMethodsUnnecessarily;
    }
    
    /**
     * Set a parameter map (array of param signature strings) for the method
     * of an internal PHP class.
     *
     * @param string $class
     * @param string $method
     * @param array $map
     */
    public function setInternalClassMethodParamMap($class, $method, array $map)
    {
        if (!isset($this->_internalClassParamMap[strtolower($class)])) {
            $this->_internalClassParamMap[strtolower($class)] = array();
        }
        $this->_internalClassParamMap[strtolower($class)][strtolower($method)] = $map;
    }
    
    /**
     * Get the parameter map of an internal PHP class method
     *
     * @return array
     */
    public function getInternalClassMethodParamMap($class, $method)
    {
        if (isset($this->_internalClassParamMap[strtolower($class)][strtolower($method)])) {
            return $this->_internalClassParamMap[strtolower($class)][strtolower($method)];
        }
    }

}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

namespace Mockery;

class Generator
{
    protected static $reservedWords = array(
        "__halt_compiler", "abstract", "and", "array", "as",
        "break", "callable", "case", "catch", "class",
        "clone", "const", "continue", "declare", "default",
        "die", "do", "echo", "else", "elseif",
        "empty", "enddeclare", "endfor", "endforeach", "endif",
        "endswitch", "endwhile", "eval", "exit", "extends",
        "final", "for", "foreach", "function", "global",
        "goto", "if", "implements", "include", "include_once",
        "instanceof", "insteadof", "interface", "isset", "list",
        "namespace", "new", "or", "print", "private",
        "protected", "public", "require", "require_once", "return",
        "static", "switch", "throw", "trait", "try",
        "unset", "use", "var", "while", "xor"
    );

   /**
    * Generates a Mock Object class with all Mockery methods whose
    * intent is basically to provide the mock object with the same
    * class type hierarchy as a typical instance of the class being
    * mocked.
    *
    * @param string $className
    * @param string $mockName
    * @param string $allowFinal
    * @return string Classname of the mock class created
    */
    public static function createClassMock($className, $mockName = null,
        $allowFinal = false, $block = array(), $makeInstanceMock = false,
        $partialMethods = array())
    {
        if (is_null($mockName)) $mockName = uniqid('Mockery_');
        $definition = '';
        $inheritance = '';
        $interfaceInheritance = array();
        $classData = array();
        $classNameInherited = '';
        $classIsFinal = false;
        $callTypehinting = false;
        $useStandardMethods = true;
        if (is_array($className)) {
            foreach ($className as $interface) {
                $class = new \ReflectionClass($interface);
                $classData[] = self::_analyseClass($class, $interface, $allowFinal);
            }
        } else {
            $class = new \ReflectionClass($className);
            $classData[] = self::_analyseClass($class, $className, $allowFinal);
        }
        foreach ($classData as $i=>$data) {
            if ($data['class']->isInterface() && preg_match("/^Traversable$/i", $data['class']->getName())) {
                $classData[] = $iterator = self::_analyseClass(
                    new \ReflectionClass('Iterator'), // can't use Traversable directly so substitute
                    '\Iterator',
                    $allowFinal
                );
                array_unshift($interfaceInheritance, $iterator['className']);
                unset($classData[$i]); // throw away Traversable or we'll get fatal error
            } elseif ($data['class']->isInterface()) {
                $interfaceInheritance[] = $data['className'];
            } elseif ($data['class']->isFinal()) {
                $inheritance = ' extends ' . $data['className'];
                $classNameInherited = $data['className'];
                $classIsFinal = true;
            } else {
                $inheritance = ' extends ' . $data['className'] . ' implements \Mockery\MockInterface';
                $classNameInherited = $data['className'];
            }
        }
        if (count($interfaceInheritance) > 0) {
            foreach ($classData as $i => $data) {
                if ($data['class']->isInterface()) {
                    $extendedInterfaces = $data['class']->getInterfaces();
                    $traversables = preg_grep("/^Traversable$/i", array_keys($extendedInterfaces));
                    if (!empty($traversables) && !in_array('\Iterator', $interfaceInheritance)
                    && !array_key_exists('IteratorAggregate', $extendedInterfaces)
                    && !preg_match("/^Iterator|IteratorAggregate$/i", $data['class']->getName())) {
                        array_unshift($interfaceInheritance, '\Iterator'); // must declare prior to Traversable
                        $classData[] = $iterator = self::_analyseClass(
                            new \ReflectionClass('Iterator'),
                            '\Iterator',
                            $allowFinal
                        );
                    }
                }
            }
            if (!$classIsFinal) $interfaceInheritance[] = '\Mockery\MockInterface';
            if (strlen($classNameInherited) > 0) $inheritance = ' extends ' . $classNameInherited;
            $inheritance .= ' implements ' . implode(', ', $interfaceInheritance);
        }

        $definition .= 'class ' . $mockName . $inheritance . PHP_EOL . '{' . PHP_EOL;
        foreach ($classData as $data) {
            if (!$data['class']->isFinal()) {
                $result = self::applyMockeryTo($data['class'], $data['publicMethods'], $block, $partialMethods);
                if ($result['callTypehinting']) $callTypehinting = true;
                $definition .= $result['definition'];
                $definition .= self::stubAbstractProtected($data['protectedMethods']);
            }  else {
                $useStandardMethods = false;
            }
        }
        if ($useStandardMethods) $definition .= self::_getStandardMethods($callTypehinting, $makeInstanceMock);
        $definition .= PHP_EOL . '}';
        eval($definition);
        return $mockName;
    }

    protected static function _analyseClass($class, $className, $allowFinal = false)
    {
        if ($class->isFinal() && !$allowFinal) {
            throw new \Mockery\Exception(
                'The class ' . $className . ' is marked final and its methods'
                . ' cannot be replaced. Classes marked final can be passed in'
                . ' to \Mockery::mock() as instantiated objects to create a'
                . ' partial mock, but only if the mock is not subject to type'
                . ' hinting checks.'
            );
        } elseif ($class->isFinal()) {
            $className = '\\Mockery\\Mock';
        }
        $hasFinalMethods = false;
        $methods = $class->getMethods(\ReflectionMethod::IS_PUBLIC);
        $protected = $class->getMethods(\ReflectionMethod::IS_PROTECTED);
        foreach ($methods as $method) {
            if ($method->isFinal()) {
                $hasFinalMethods = true;
            }
        }
        return array(
            'class' => $class,
            'className' => $className,
            'hasFinalMethods' => $hasFinalMethods,
            'publicMethods' => $methods,
            'protectedMethods' => $protected
        );
    }

    /**
     * Add all Mockery methods for mocks to the class being defined
     *
     *
     */
    public static function applyMockeryTo(\ReflectionClass $class,
        array $methods, array $block, $partialMethods = array())
    {
        $definition = '';
        $callTypehinting = false;
        /**
         * TODO: Worry about all these other method types later.
         */
        foreach ($methods as $method) {
            if(in_array($method->getName(), $block)) continue;
            if (count($partialMethods) > 0 && !in_array(strtolower($method->getName()), $partialMethods)) {
                continue;
            }
            // Skip final methods, i.e. we end up with a partial with final methods untouched
            if ($method->isFinal()) {
                continue;
            }
            if (!$method->isDestructor()
            //&& !$method->isStatic()
            && $method->getName() !== '__call'
            && $method->getName() !== '__clone'
            && $method->getName() !== '__wakeup'
            && $method->getName() !== '__set'
            && $method->getName() !== '__get'
            && $method->getName() !== '__toString'
            && $method->getName() !== '__isset'
            && $method->getName() !== '__callStatic') {
                $definition .= self::_replacePublicMethod($method);
            }
            if ($method->getName() == '__call') {
                $params = $method->getParameters();
                if ($params[1]->isArray()) {
                    $callTypehinting = true;
                }
            }
        }
        return array('definition'=>$definition, 'callTypehinting'=>$callTypehinting);
    }

    public static function stubAbstractProtected(array $methods)
    {
        $definition = '';
        foreach ($methods as $method) {
            if ($method->isAbstract()) {
                $definition .= self::_replaceProtectedAbstractMethod($method);
            }
        }
        return $definition;
    }

    /**
     * Attempts to replace defined public (non-static) methods so they all
     * redirect to the Mock Object's __call() interceptor
     *
     * TODO: Add exclusions for partial mock support
     */
    protected static function _replacePublicMethod(\ReflectionMethod $method)
    {
        $name = $method->getName();

        if (static::_isReservedWord($name)) {
            return " /* Could not replace $name() as it is a reserved word */ ";
        }

        $body = '';
        if ($name !== '__construct' && $method->isPublic()) {
            /**
             * Purpose of this block is to create an argument array where
             * references are preserved (func_get_args() does not preserve
             * references)
             */
            $body = <<<BODY
\$stack = debug_backtrace();
\$args = array();
if (isset(\$stack[0]['args'])) {
    for(\$i=0; \$i<count(\$stack[0]['args']); \$i++) {
        \$args[\$i] =& \$stack[0]['args'][\$i];
    }
}
\$ret = \$this->__call('$name', \$args);
return \$ret;
BODY;
        }
        $methodParams = self::_renderPublicMethodParameters($method);
        $paramDef = implode(',', $methodParams);
        if ($method->isPublic()) {
            $access = 'public';
        } elseif($method->isProtected()) {
            $access = 'protected';
        } else {
            $access = 'private';
        }
        if ($method->isStatic()) {
            $access .= ' static';
        }
        $returnByRef = $method->returnsReference() ? ' & ' : '';
        return $access . ' function ' . $returnByRef . $name . '(' . $paramDef . ')'
                      . '{' . $body . '}';
    }

    protected static function _renderPublicMethodParameters(\ReflectionMethod $method)
    {
        $class = $method->getDeclaringClass();
        if ($class->isInternal()) { // check for parameter overrides for internal PHP classes
            $paramMap = \Mockery::getConfiguration()
                ->getInternalClassMethodParamMap($class->getName(), $method->getName());
            if (!is_null($paramMap)) return $paramMap;
        }
        $methodParams = array();
        $params = $method->getParameters();
		$typehintMatch = array();
        foreach ($params as $i => $param) {
            $paramDef = '';
            if ($param->isArray()) {
                $paramDef .= 'array ';
            } elseif ($param->getClass()) {
                $paramDef .= $param->getClass()->getName() . ' ';
            }  elseif (preg_match('/^Parameter #[0-9]+ \[ \<(required|optional)\> (?<typehint>\S+ )?.*\$' . $param->getName() . ' .*\]$/', $param->__toString(), $typehintMatch)) {
                if (!empty($typehintMatch['typehint'])) {
                    $paramDef .= $typehintMatch['typehint'] . ' ';
                }
            }
            $paramName = $param->getName();
            if (empty($paramName) || $paramName === '...') {
                $paramName = 'arg' . $i;
            }
            $paramDef .= ($param->isPassedByReference() ? '&' : '') . '$' . $paramName;
            if ($param->isOptional()) {
                if ($param->isDefaultValueAvailable()) {
                    $default = var_export($param->getDefaultValue(), true);
                } else {
                    $default = 'null';
                }
                $paramDef .= ' = ' . $default;
            }

            $methodParams[] = $paramDef;
        }
        return $methodParams;
    }

    /**
     * Replace abstract protected methods (the only enforceable type outside
     * of public methods). The replacement is just a stub that does nothing.
     */
    protected static function _replaceProtectedAbstractMethod(\ReflectionMethod $method)
    {
        $name = $method->getName();

        if (static::_isReservedWord($name)) {
            return " /* Could not replace $name() as it is a reserved word */ ";
        }

        $body = '';
        $methodParams = array();
        $params = $method->getParameters();
        foreach ($params as $param) {
            $paramDef = '';
            if ($param->isArray()) {
                $paramDef .= 'array ';
            } elseif ($param->getClass()) {
                $paramDef .= $param->getClass()->getName() . ' ';
            }
            $paramDef .= ($param->isPassedByReference() ? '&' : '') . '$' . $param->getName();
            if ($param->isDefaultValueAvailable()) {
                $default = var_export($param->getDefaultValue(), true);
                if ($default == '') {
                  $default = 'null';
                }
                $paramDef .= ' = ' . $default;
            } else if ($param->isOptional()) {
                $paramDef .= ' = null';
            }
            $methodParams[] = $paramDef;
        }
        $paramDef = implode(',', $methodParams);
        $access = 'protected';
        $returnByRef = $method->returnsReference() ? ' & ' : '';
        return $access . ' function ' . $returnByRef . $name . '(' . $paramDef . ')'
                      . '{' . $body . '}';
    }

    public static function _isReservedWord($word)
    {
        static $flippedReservedWords;

        if (null === $flippedReservedWords) {
            $flippedReservedWords = array_fill_keys(static::$reservedWords, true);
        }

        return isset($flippedReservedWords[$word]);
    }

    /**
     * NOTE: The code below is taken from Mockery\Mock and should
     * be an exact copy with only one difference - we define the Mockery\Mock
     * constructor as a public init method (since the original class
     * constructor is often not replaceable, e.g. for interface adherance)
     *
     * Return a string def of the standard Mock Object API needed for all mocks
     *
     */
    public static function _getStandardMethods($callTypehint = true, $makeInstanceMock = false)
    {
        $typehint = $callTypehint ? 'array' : '';
        $std = <<<MOCK
    protected static \$_mockery_staticClassName = '';

    protected \$_mockery_expectations = array();

    protected \$_mockery_lastExpectation = null;

    protected \$_mockery_ignoreMissing = false;

    protected \$_mockery_ignoreMissingAsUndefined = false;

    protected \$_mockery_deferMissing = false;

    protected \$_mockery_verified = false;

    protected \$_mockery_name = null;

    protected \$_mockery_allocatedOrder = 0;

    protected \$_mockery_currentOrder = 0;

    protected \$_mockery_groups = array();

    protected \$_mockery_container = null;

    protected \$_mockery_partial = null;

    protected \$_mockery_disableExpectationMatching = false;

    protected \$_mockery_mockableMethods = array();

    protected \$_mockery_mockableProperties = array();

    public function mockery_init(\$name, \Mockery\Container \$container = null, \$partialObject = null)
    {
        \$this->_mockery_name = \$name;
        if(is_null(\$container)) {
            \$container = new \Mockery\Container;
        }
        \$this->_mockery_container = \$container;
        if (!is_null(\$partialObject)) {
            \$this->_mockery_partial = \$partialObject;
        }
        if (!\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed()) {
            if (isset(\$this->_mockery_partial)) {
                \$reflected = new \ReflectionObject(\$this->_mockery_partial);
            } else {
                \$reflected = new \ReflectionClass(\$this->_mockery_name);
            }
            \$methods = \$reflected->getMethods(\ReflectionMethod::IS_PUBLIC);
            foreach (\$methods as \$method) {
                if (!\$method->isStatic()) \$this->_mockery_mockableMethods[] = \$method->getName();
            }
        }
    }

    public function shouldReceive()
    {
        \$self = \$this;
        \$lastExpectation = \Mockery::parseShouldReturnArgs(
            \$this, func_get_args(), function(\$method) use (\$self) {
                \$director = \$self->mockery_getExpectationsFor(\$method);
                if (!\$director) {
                    \$director = new \Mockery\ExpectationDirector(\$method, \$self);
                    \$self->mockery_setExpectationsFor(\$method, \$director);
                }
                \$expectation = new \Mockery\Expectation(\$self, \$method);
                \$director->addExpectation(\$expectation);
                return \$expectation;
            }
        );
        return \$lastExpectation;
    }

    public function shouldDeferMissing()
    {
        \$this->_mockery_deferMissing = true;
        return \$this;
    }

    public function makePartial()
    {
        return \$this->shouldDeferMissing();
    }

    public function shouldIgnoreMissing()
    {
        \$this->_mockery_ignoreMissing = true;
        return \$this;
    }

    public function asUndefined()
    {
        \$this->_mockery_ignoreMissingAsUndefined = true;
        return \$this;
    }

    public function shouldExpect(Closure \$closure)
    {
        \$recorder = new \Mockery\Recorder(\$this, \$this->_mockery_partial);
        \$this->_mockery_disableExpectationMatching = true;
        \$closure(\$recorder);
        \$this->_mockery_disableExpectationMatching = false;
        return \$this;
    }

    public function byDefault()
    {
        foreach (\$this->_mockery_expectations as \$director) {
            \$exps = \$director->getExpectations();
            foreach (\$exps as \$exp) {
                \$exp->byDefault();
            }
        }
        return \$this;
    }

    public function __call(\$method, $typehint \$args)
    {
        if (isset(\$this->_mockery_expectations[\$method])
        && !\$this->_mockery_disableExpectationMatching) {
            \$handler = \$this->_mockery_expectations[\$method];
            return \$handler->call(\$args);
        } elseif (!is_null(\$this->_mockery_partial) && method_exists(\$this->_mockery_partial, \$method)) {
            return call_user_func_array(array(\$this->_mockery_partial, \$method), \$args);
        } elseif (\$this->_mockery_deferMissing && is_callable("parent::\$method")) {
            return call_user_func_array("parent::\$method", \$args);
        } elseif (\$this->_mockery_ignoreMissing) {
            if (\$this->_mockery_ignoreMissingAsUndefined === true) {
                \$undef = new \Mockery\Undefined;
                return call_user_func_array(array(\$undef, \$method), \$args);
            } else {
                return null;
            }
        }
        throw new \BadMethodCallException(
            'Method ' . \$this->_mockery_name . '::' . \$method . '() does not exist on this mock object'
        );
    }

    /**
     * Forward calls to this magic method to the __call method
     */
    public function __toString()
    {
        return \$this->__call('__toString', array());
    }

    public function mockery_verify()
    {
        if (\$this->_mockery_verified) return true;
        if (isset(\$this->_mockery_ignoreVerification)
        && \$this->_mockery_ignoreVerification == true) {
            return true;
        }
        \$this->_mockery_verified = true;
        foreach(\$this->_mockery_expectations as \$director) {
            \$director->verify();
        }
    }

    public function mockery_teardown()
    {

    }

    public function mockery_allocateOrder()
    {
        \$this->_mockery_allocatedOrder += 1;
        return \$this->_mockery_allocatedOrder;
    }

    public function mockery_setGroup(\$group, \$order)
    {
        \$this->_mockery_groups[\$group] = \$order;
    }

    public function mockery_getGroups()
    {
        return \$this->_mockery_groups;
    }

    public function mockery_setCurrentOrder(\$order)
    {
        \$this->_mockery_currentOrder = \$order;
        return \$this->_mockery_currentOrder;
    }

    public function mockery_getCurrentOrder()
    {
        return \$this->_mockery_currentOrder;
    }

    public function mockery_validateOrder(\$method, \$order)
    {
        if (isset(\$this->_mockery_ignoreVerification)
        && \$this->_mockery_ignoreVerification === false) {
            return;
        }
        if (\$order < \$this->_mockery_currentOrder) {
            \$exception = new \Mockery\Exception\InvalidOrderException(
                'Method ' . \$this->_mockery_name . '::' . \$method . '()'
                . ' called out of order: expected order '
                . \$order . ', was ' . \$this->_mockery_currentOrder
            );
            \$exception->setMock(\$this)
                ->setMethodName(\$method)
                ->setExpectedOrder(\$order)
                ->setActualOrder(\$this->_mockery_currentOrder);
            throw \$exception;
        }
        \$this->mockery_setCurrentOrder(\$order);
    }

    public function mockery_getExpectationCount()
    {
        \$count = 0;
        foreach(\$this->_mockery_expectations as \$director) {
            \$count += \$director->getExpectationCount();
        }
        return \$count;
    }

    public function mockery_setExpectationsFor(\$method, \Mockery\ExpectationDirector \$director)
    {
        \$this->_mockery_expectations[\$method] = \$director;
    }

    public function mockery_getExpectationsFor(\$method)
    {
        if (isset(\$this->_mockery_expectations[\$method])) {
            return \$this->_mockery_expectations[\$method];
        }
    }

    public function mockery_findExpectation(\$method, array \$args)
    {
        if (!isset(\$this->_mockery_expectations[\$method])) {
            return null;
        }
        \$director = \$this->_mockery_expectations[\$method];
        return \$director->findExpectation(\$args);
    }

    public function mockery_getContainer()
    {
        return \$this->_mockery_container;
    }

    public function mockery_getName()
    {
        return \$this->_mockery_name;
    }

    public function mockery_getMockableMethods()
    {
        return \$this->_mockery_mockableMethods;
    }

    public function mockery_getMockableProperties()
    {
        return \$this->_mockery_mockableProperties;
    }

    //** Everything below this line is not copied from/needed for Mockery/Mock **//

    public function __wakeup()
    {
        /**
         * This does not add __wakeup method support. It's a blind method and any
         * expected __wakeup work will NOT be performed. It merely cuts off
         * annoying errors where a __wakeup exists but is not essential when
         * mocking
         */
    }

    public static function __callStatic(\$method, $typehint \$args)
    {
        try {
            \$associatedRealObject = \Mockery::fetchMock(__CLASS__);
            return \$associatedRealObject->__call(\$method, \$args);
        } catch (\BadMethodCallException \$e) {
            throw new \BadMethodCallException(
                'Static method ' . \$associatedRealObject->mockery_getName() . '::' . \$method
                . '() does not exist on this mock object'
            );
        }
    }

    public function mockery_getExpectations()
    {
        return \$this->_mockery_expectations;
    }

    public function __isset(\$name)
    {
        if (false === stripos(\$name, '_mockery_') && method_exists(get_parent_class(\$this), '__isset')) {
            return parent::__isset(\$name);
        }
    }

MOCK;
        /**
         * Note: An instance mock allows the declaration of an instantiable class
         * which imports cloned expectations from an existing mock object. In effect
         * it enables pseudo-overloading of the "new" operator.
         */
        if ($makeInstanceMock) {
            $mim = <<<MOCK

    protected \$_mockery_ignoreVerification = true;

    public function __construct()
    {
        \$this->_mockery_ignoreVerification = false;
        \$associatedRealObject = \Mockery::fetchMock(__CLASS__);
        \$directors = \$associatedRealObject->mockery_getExpectations();
        foreach (\$directors as \$method=>\$director) {
            \$expectations = \$director->getExpectations();
            // get the director method needed
            \$existingDirector = \$this->mockery_getExpectationsFor(\$method);
            if (!\$existingDirector) {
                \$existingDirector = new \Mockery\ExpectationDirector(\$method, \$this);
                \$this->mockery_setExpectationsFor(\$method, \$existingDirector);
            }
            foreach (\$expectations as \$expectation) {
                \$clonedExpectation = clone \$expectation;
                \$existingDirector->addExpectation(\$clonedExpectation);
            }
        }
        \Mockery::getContainer()->rememberMock(\$this);
    }
MOCK;
            $std .= $mim;
        }
        return $std;
    }


}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */
 
namespace Mockery\Exception;
use Mockery;

class NoMatchingExpectationException extends Mockery\Exception
{

    protected $method = null;

    protected $actual = array();

    protected $mockObject = null;

    public function setMock(Mockery\MockInterface $mock)
    {
        $this->mockObject = $mock;
        return $this;
    }

    public function setMethodName($name)
    {
        $this->method = $name;
        return $this;
    }

    public function setActualArguments($count)
    {
        $this->actual = $count;
        return $this;
    }

    public function getMock()
    {
        return $this->mockObject;
    }

    public function getMethodName()
    {
        return $this->method;
    }

    public function getActualArguments()
    {
        return $this->actual;
    }

    public function getMockName()
    {
        return $this->getMock()->mockery_getName();
    }

}<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */
 
namespace Mockery\Exception;
use Mockery;

class InvalidCountException extends Mockery\CountValidator\Exception
{

    protected $method = null;

    protected $expected = 0;

    protected $expectedComparative = '<=';

    protected $actual = null;

    protected $mockObject = null;

    public function setMock(Mockery\MockInterface $mock)
    {
        $this->mockObject = $mock;
        return $this;
    }

    public function setMethodName($name)
    {
        $this->method = $name;
        return $this;
    }

    public function setActualCount($count)
    {
        $this->actual = $count;
        return $this;
    }

    public function setExpectedCount($count)
    {
        $this->expected = $count;
        return $this;
    }

    public function setExpectedCountComparative($comp)
    {
        if (!in_array($comp, array('=', '>', '<', '>=', '<='))) {
            throw new Exception(
                'Illegal comparative for expected call counts set: ' . $comp
            );
        }
        $this->expectedComparative = $comp;
        return $this;
    }

    public function getMock()
    {
        return $this->mockObject;
    }

    public function getMethodName()
    {
        return $this->method;
    }

    public function getActualCount()
    {
        return $this->actual;
    }

    public function getExpectedCount()
    {
        return $this->expected;
    }

    public function getMockName()
    {
        return $this->getMock()->mockery_getName();
    }

    public function getExpectedCountComparative()
    {
        return $this->expectedComparative;
    }

}<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */
 
namespace Mockery\Exception;
use Mockery;

class InvalidOrderException extends Mockery\Exception
{

    protected $method = null;

    protected $expected = 0;

    protected $actual = null;

    protected $mockObject = null;

    public function setMock(Mockery\MockInterface $mock)
    {
        $this->mockObject = $mock;
        return $this;
    }

    public function setMethodName($name)
    {
        $this->method = $name;
        return $this;
    }

    public function setActualOrder($count)
    {
        $this->actual = $count;
        return $this;
    }

    public function setExpectedOrder($count)
    {
        $this->expected = $count;
        return $this;
    }

    public function getMock()
    {
        return $this->mockObject;
    }

    public function getMethodName()
    {
        return $this->method;
    }

    public function getActualOrder()
    {
        return $this->actual;
    }

    public function getExpectedOrder()
    {
        return $this->expected;
    }

    public function getMockName()
    {
        return $this->getMock()->mockery_getName();
    }

}<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */
 
namespace Mockery\Adapter\Phpunit;

class TestListener implements \PHPUnit_Framework_TestListener
{
    
    /**
     * After each test, perform Mockery verification tasks and cleanup the
     * statically stored Mockery container for the next test.
     *
     * @param  PHPUnit_Framework_Test $test
     * @param  float                  $time
     */
    public function endTest(\PHPUnit_Framework_Test $test, $time)
    {
        try
        {
            $container = \Mockery::getContainer();
            if ($container != null) {
                $expectation_count = $container->mockery_getExpectationCount();
                $test->addToAssertionCount($expectation_count);
            }
            \Mockery::close();
        } catch (\Exception $e) {
            $result = $test->getTestResultObject();
            $result->addError($test, $e, $time);
        }
    }
    
	/**
	 * Add Mockery files to PHPUnit's blacklist so they don't showup on coverage reports 
	 */
    public function startTestSuite(\PHPUnit_Framework_TestSuite $suite) {
		
        if (class_exists('\\PHP_CodeCoverage_Filter')
        && method_exists('\\PHP_CodeCoverage_Filter', 'getInstance')) {
            \PHP_CodeCoverage_Filter::getInstance()->addDirectoryToBlacklist(
                 __DIR__.'/../../../Mockery/', '.php', '', 'PHPUNIT'
            );

            \PHP_CodeCoverage_Filter::getInstance()->addFileToBlacklist(__DIR__.'/../../../Mockery.php', 'PHPUNIT');
        }
    }
    /**
     *  The Listening methods below are not required for Mockery
     */
    public function addError(\PHPUnit_Framework_Test $test, \Exception $e, $time) {}

    public function addFailure(\PHPUnit_Framework_Test $test, \PHPUnit_Framework_AssertionFailedError $e, $time) {}

    public function addIncompleteTest(\PHPUnit_Framework_Test $test, \Exception $e, $time) {}

    public function addSkippedTest(\PHPUnit_Framework_Test $test, \Exception $e, $time) {}


    public function endTestSuite(\PHPUnit_Framework_TestSuite $suite) {}

    public function startTest(\PHPUnit_Framework_Test $test) {}

}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/blob/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

class Mockery
{
    const BLOCKS = 'Mockery_Forward_Blocks';

    /**
     * Global container to hold all mocks for the current unit test running
     *
     * @var \Mockery\Container
     */
    protected static $_container = null;

    /**
     * Global configuration handler containing configuration options
     *
     * @var \Mockery\Configuration
     */
    protected static $_config = null;

    /**
     * Static shortcut to \Mockery\Container::mock()
     *
     * @return \Mockery\MockInterface
     */
    public static function mock()
    {
        if (is_null(self::$_container)) {
            self::$_container = new \Mockery\Container;
        }
        $args = func_get_args();
        return call_user_func_array(array(self::$_container, 'mock'), $args);
    }

    public static function instanceMock()
    {
        if (is_null(self::$_container)) {
            self::$_container = new \Mockery\Container;
        }
        $args = func_get_args();
        return call_user_func_array(array(self::$_container, 'instanceMock'), $args);
    }

    /**
     * Static shortcut to \Mockery\Container::self()
     *
     * @return \Mockery\MockInterface
     */
    public static function self()
    {
        if (is_null(self::$_container)) {
            throw new \LogicException("You have not declared any mocks yet");
        }

        return self::$_container->self();
    }
    
    /**
     * Static shortcut to closing up and verifying all mocks in the global
     * container, and resetting the container static variable to null
     *
     * @return void
     */
    public static function close()
    {
        if (is_null(self::$_container)) return;
        self::$_container->mockery_teardown();
        self::$_container->mockery_close();
        self::$_container = null;
    }

    /**
     * Static fetching of a mock associated with a name or explicit class poser
     */
    public static function fetchMock($name)
    {
        return self::$_container->fetchMock($name);
    }

    /**
     * Get the container
     */
    public static function getContainer()
    {
        return self::$_container;
    }

    /**
     * Set the container
     */
    public static function setContainer(Mockery\Container $container)
    {
        return self::$_container = $container;
    }

    /**
     * Reset the container to NULL
     */
    public static function resetContainer()
    {
        self::$_container = null;
    }

    /**
     * Return instance of ANY matcher
     *
     * @return
     */
    public static function any()
    {
        $return = new \Mockery\Matcher\Any();
        return $return;
    }

    /**
     * Return instance of TYPE matcher
     *
     * @return
     */
    public static function type($expected)
    {
        $return = new \Mockery\Matcher\Type($expected);
        return $return;
    }

    /**
     * Return instance of DUCKTYPE matcher
     *
     * @return
     */
    public static function ducktype()
    {
        $return = new \Mockery\Matcher\Ducktype(func_get_args());
        return $return;
    }

    /**
     * Return instance of SUBSET matcher
     *
     * @return
     */
    public static function subset(array $part)
    {
        $return = new \Mockery\Matcher\Subset($part);
        return $return;
    }

    /**
     * Return instance of CONTAINS matcher
     *
     * @return
     */
    public static function contains()
    {
        $return = new \Mockery\Matcher\Contains(func_get_args());
        return $return;
    }

    /**
     * Return instance of HASKEY matcher
     *
     * @return
     */
    public static function hasKey($key)
    {
        $return = new \Mockery\Matcher\HasKey($key);
        return $return;
    }

    /**
     * Return instance of HASVALUE matcher
     *
     * @return
     */
    public static function hasValue($val)
    {
        $return = new \Mockery\Matcher\HasValue($val);
        return $return;
    }

    /**
     * Return instance of CLOSURE matcher
     *
     * @return
     */
    public static function on($closure)
    {
        $return = new \Mockery\Matcher\Closure($closure);
        return $return;
    }

    /**
     * Return instance of MUSTBE matcher
     *
     * @return
     */
    public static function mustBe($expected)
    {
        $return = new \Mockery\Matcher\MustBe($expected);
        return $return;
    }

    /**
     * Return instance of NOT matcher
     *
     * @return
     */
    public static function not($expected)
    {
        $return = new \Mockery\Matcher\Not($expected);
        return $return;
    }

    /**
     * Return instance of ANYOF matcher
     *
     * @return
     */
    public static function anyOf()
    {
        $return = new \Mockery\Matcher\AnyOf(func_get_args());
        return $return;
    }

    /**
     * Return instance of NOTANYOF matcher
     *
     * @return
     */
    public static function notAnyOf()
    {
        $return = new \Mockery\Matcher\NotAnyOf(func_get_args());
        return $return;
    }

    /**
     * Get the global configuration container
     */
    public static function getConfiguration()
    {
        if (is_null(self::$_config)) {
            self::$_config = new \Mockery\Configuration;
        }
        return self::$_config;
    }

    /**
     * Utility method to format method name and args into a string
     *
     * @param string $method
     * @param array $args
     * @return string
     */
    public static function formatArgs($method, array $args = null)
    {
        $return = $method . '(';
        if ($args && !empty($args)) {
            $parts = array();
            foreach($args as $arg) {
                if (is_object($arg)) {
                    $parts[] = get_class($arg);
                } elseif (is_int($arg) || is_float($arg)) {
                    $parts[] = $arg;
                } elseif (is_array($arg)) {
                    $parts[] = 'Array';
                } else {
                    $parts[] = '"' . (string) $arg . '"';
                }
            }
            $return .= implode(', ', $parts); // TODO: improve format

        }
        $return .= ')';
        return $return;
    }

    /**
     * Utility function to format objects to printable arrays
     *
     * @param array $args
     * @return string
     */
    public static function formatObjects(array $args = null)
    {
        $hasObjects = false;
        $parts = array();
        $return = 'Objects: (';
        if ($args && !empty($args)) {
            foreach($args as $arg) {
                if (is_object($arg)) {
                    $hasObjects = true;
                    $parts[get_class($arg)] = self::_objectToArray($arg);
                }
            }
        }
        $return .= var_export($parts, true);
        $return .= ')';
        $return = $hasObjects ? $return : '';
        return $return;
    }

    /**
     * Utility function to turn public properties
     * and public get* and is* method values into an array
     *
     * @param object $object
     * @return string
     */
    private static function _objectToArray($object, $nesting = 3)
    {
        if ($nesting == 0) {
            return array('...');
        }
        $reflection = new \ReflectionClass($object);
        $properties = array();
        foreach ($reflection->getProperties(\ReflectionProperty::IS_PUBLIC) as $publicProperty)
        {
            if ($publicProperty->isStatic()) continue;
            $properties[$name] = self::_cleanupNesting($object->$name, $nesting);
        }

        $getters = array();
        foreach ($reflection->getMethods(\ReflectionProperty::IS_PUBLIC) as $publicMethod)
        {
            if ($publicMethod->isStatic()) continue;
            $name = $publicMethod->getName();
            $numberOfParameters = $publicMethod->getNumberOfParameters();
            if ((substr($name, 0, 3) === 'get' || substr($name, 0, 2) === 'is') && $numberOfParameters == 0) {
                $getters[$name] = self::_cleanupNesting($object->$name(), $nesting);
            }
        }
        return array('class' => get_class($object), 'properties' => $properties, 'getters' => $getters);
    }

    private static function _cleanupNesting($arg, $nesting) {
        if (is_object($arg)) {
            $object = self::_objectToArray($arg, $nesting - 1);
            $object['class'] = get_class($arg);
            return $object;
        } elseif (is_array($arg)) {
            return self::_cleanupArray($arg, $nesting -1 );
        }
        return $arg;
    }

    private static function _cleanupArray($arg, $nesting = 3) {
        if ($nesting == 0) {
            return '...';
        }
        foreach ($arg as $key => $value) {
            if (is_array($value)) {
                $arg[$key] = self::_cleanupArray($value, $nesting -1);
            } elseif (is_object($value)) {
                $arg[$key] = self::_objectToArray($value, $nesting - 1);
            }
        }
        return $arg;
    }

    /**
     * Utility function to parse shouldReceive() arguments and generate
     * expectations from such as needed.
     *
     * @param \Mockery\MockInterface
     * @param array $args
     * @return \Mockery\CompositeExpectation
     */
    public static function parseShouldReturnArgs(\Mockery\MockInterface $mock, $args, $add)
    {
        $composite = new \Mockery\CompositeExpectation;
        foreach ($args as $arg) {
            if (is_array($arg)) {
                foreach($arg as $k=>$v) {
                    $expectation = self::_buildDemeterChain($mock, $k, $add)->andReturn($v);
                    $composite->add($expectation);
                }
            } elseif (is_string($arg)) {
                $expectation = self::_buildDemeterChain($mock, $arg, $add);
                $composite->add($expectation);
            }
        }
        return $composite;
    }

    /**
     * Sets up expectations on the members of the CompositeExpectation and
     * builds up any demeter chain that was passed to shouldReceive
     *
     * @param \Mockery\MockInterface $mock
     * @param string $arg
     * @param Closure $add
     * @return \Mockery\ExpectationDirector
     */
    protected static function _buildDemeterChain(\Mockery\MockInterface $mock, $arg, $add)
    {
        $container = $mock->mockery_getContainer();
        $names = explode('->', $arg);
        reset($names);
        if (!\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed()
        && method_exists($mock, "mockery_getMockableMethods")
        && !in_array(current($names), $mock->mockery_getMockableMethods())) {
            throw new \Mockery\Exception(
                'Mockery\'s configuration currently forbids mocking the method '
                . current($names) . ' as it does not exist on the class or object '
                . 'being mocked'
            );
        }
        $exp = null;
        $nextExp = function ($n) use ($add) {return $add($n);};
        while (true) {
            $method = array_shift($names);
            $exp = $mock->mockery_getExpectationsFor($method);
            $needNew = false;
            if (is_null($exp) || empty($names)) {
                $needNew = true;
            }
            if ($needNew) $exp = $nextExp($method);
            if (empty($names)) break;
            if ($needNew) {
                $mock = $container->mock('demeter_' . $method);
                $exp->andReturn($mock);
            }
            $nextExp = function ($n) use ($mock) {return $mock->shouldReceive($n);};
        }
        return $exp;
    }
}
<?xml version="1.0"?>
<package xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0         http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd" version="2.0">
  <name>Mockery</name>
  <channel>pear.survivethedeepend.com</channel>
  <summary>Mockery is a simple yet flexible mock object framework for use in unit testing.</summary>
  <description>Mockery is a simple yet flexible mock object framework for use in unit testing.</description>
  <lead>
    <name>Padraic Brady</name>
    <user>padraic</user>
    <email>padraic.brady@yahoo.com</email>
    <active>yes</active>
  </lead>
  <date>2012-01-24</date>
  <time>20:00:00</time>
  <version>
    <release>0.7.2</release>
    <api>0.7.2</api>
  </version>
  <stability>
    <release>stable</release>
    <api>stable</api>
  </stability>
  <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD</license>
  <notes>http://github.com/padraic/mockery#readme</notes>
  <contents>
    <dir name="/" baseinstalldir="/">
      <dir name="library">
        <file name="Mockery.php" role="php"/>
        <dir name="Mockery">
          <dir name="Adapter">
            <dir name="Phpunit">
              <file name="TestListener.php" role="php"/>
            </dir>
          </dir>
          <file name="CompositeExpectation.php" role="php"/>
          <file name="Configuration.php" role="php"/>
          <file name="Container.php" role="php"/>
          <dir name="CountValidator">
            <file name="AtLeast.php" role="php"/>
            <file name="AtMost.php" role="php"/>
            <file name="CountValidatorAbstract.php" role="php"/>
            <file name="Exact.php" role="php"/>
            <file name="Exception.php" role="php"/>
          </dir>
          <file name="Exception.php" role="php"/>
          <file name="Expectation.php" role="php"/>
          <file name="ExpectationDirector.php" role="php"/>
          <file name="Generator.php" role="php"/>
          <file name="Loader.php" role="php"/>
          <dir name="Matcher">
            <file name="Any.php" role="php"/>
            <file name="AnyOf.php" role="php"/>
            <file name="Closure.php" role="php"/>
            <file name="Contains.php" role="php"/>
            <file name="Ducktype.php" role="php"/>
            <file name="HasKey.php" role="php"/>
            <file name="HasValue.php" role="php"/>
            <file name="MatcherAbstract.php" role="php"/>
            <file name="MustBe.php" role="php"/>
            <file name="Not.php" role="php"/>
            <file name="NotAnyOf.php" role="php"/>
            <file name="Subset.php" role="php"/>
            <file name="Type.php" role="php"/>
          </dir>
          <file name="Mock.php" role="php"/>
          <file name="MockInterface.php" role="php"/>
          <file name="Recorder.php" role="php"/>
          <file name="Undefined.php" role="php"/>
        </dir>
      </dir>
    </dir>
  </contents>
  <dependencies>
    <required>
      <php>
        <min>5.3.0</min>
      </php>
      <pearinstaller>
        <min>1.4.0</min>
      </pearinstaller>
    </required>
    <optional>
        <package>
            <name>Hamcrest</name>
            <channel>hamcrest.googlecode.com/svn/pear</channel>
        </package>
    </optional>
  </dependencies>
  <phprelease>
    <filelist>
      <install name="library/Mockery.php" as="Mockery.php"/>
      <install name="library/Mockery/Adapter/Phpunit/TestListener.php" as="Mockery/Adapter/Phpunit/TestListener.php"/>
      <install name="library/Mockery/CompositeExpectation.php" as="Mockery/CompositeExpectation.php"/>
      <install name="library/Mockery/Configuration.php" as="Mockery/Configuration.php"/>
      <install name="library/Mockery/Container.php" as="Mockery/Container.php"/>
      <install name="library/Mockery/CountValidator/AtLeast.php" as="Mockery/CountValidator/AtLeast.php"/>
      <install name="library/Mockery/CountValidator/AtMost.php" as="Mockery/CountValidator/AtMost.php"/>
      <install name="library/Mockery/CountValidator/CountValidatorAbstract.php" as="Mockery/CountValidator/CountValidatorAbstract.php"/>
      <install name="library/Mockery/CountValidator/Exact.php" as="Mockery/CountValidator/Exact.php"/>
      <install name="library/Mockery/CountValidator/Exception.php" as="Mockery/CountValidator/Exception.php"/>
      <install name="library/Mockery/Exception.php" as="Mockery/Exception.php"/>
      <install name="library/Mockery/Expectation.php" as="Mockery/Expectation.php"/>
      <install name="library/Mockery/ExpectationDirector.php" as="Mockery/ExpectationDirector.php"/>
      <install name="library/Mockery/Generator.php" as="Mockery/Generator.php"/>
      <install name="library/Mockery/Loader.php" as="Mockery/Loader.php"/>
      <install name="library/Mockery/Matcher/Any.php" as="Mockery/Matcher/Any.php"/>
      <install name="library/Mockery/Matcher/AnyOf.php" as="Mockery/Matcher/AnyOf.php"/>
      <install name="library/Mockery/Matcher/Closure.php" as="Mockery/Matcher/Closure.php"/>
      <install name="library/Mockery/Matcher/Contains.php" as="Mockery/Matcher/Contains.php"/>
      <install name="library/Mockery/Matcher/Ducktype.php" as="Mockery/Matcher/Ducktype.php"/>
      <install name="library/Mockery/Matcher/HasKey.php" as="Mockery/Matcher/HasKey.php"/>
      <install name="library/Mockery/Matcher/HasValue.php" as="Mockery/Matcher/HasValue.php"/>
      <install name="library/Mockery/Matcher/MatcherAbstract.php" as="Mockery/Matcher/MatcherAbstract.php"/>
      <install name="library/Mockery/Matcher/MustBe.php" as="Mockery/Matcher/MustBe.php"/>
      <install name="library/Mockery/Matcher/Not.php" as="Mockery/Matcher/Not.php"/>
      <install name="library/Mockery/Matcher/NotAnyOf.php" as="Mockery/Matcher/NotAnyOf.php"/>
      <install name="library/Mockery/Matcher/Subset.php" as="Mockery/Matcher/Subset.php"/>
      <install name="library/Mockery/Matcher/Type.php" as="Mockery/Matcher/Type.php"/>
      <install name="library/Mockery/Mock.php" as="Mockery/Mock.php"/>
      <install name="library/Mockery/MockInterface.php" as="Mockery/MockInterface.php"/>
      <install name="library/Mockery/Recorder.php" as="Mockery/Recorder.php"/>
      <install name="library/Mockery/Undefined.php" as="Mockery/Undefined.php"/>
    </filelist>
  </phprelease>
</package>
Copyright (c) 2010-2013, Pádraic Brady
All rights reserved.
 
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
 
    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.
 
    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
 
    * The name of Pádraic Brady may not be used to endorse or promote
      products derived from this software without specific prior written
      permission.
 
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Mockery
========

Mockery is a simple yet flexible PHP mock object framework for use in unit testing
with PHPUnit, PHPSpec or any other testing framework. Its core goal is to offer a
test double framework with a succinct API capable of clearly defining all possible
object operations and interactions using a human readable Domain Specific Language
(DSL). Designed as a drop in alternative to PHPUnit's phpunit-mock-objects library,
Mockery is easy to integrate with PHPUnit and can operate alongside
phpunit-mock-objects without the World ending.

Mockery is released under a New BSD License.

The current released version for PEAR is 0.8.0. Composer users may instead opt to use
the current master branch in lieu of using the more static 0.8.0 git tag.
The build status of the current master branch is tracked by Travis CI:
[![Build Status](https://travis-ci.org/padraic/mockery.png?branch=master)](http://travis-ci.org/padraic/mockery)

Mock Objects
------------

In unit tests, mock objects simulate the behaviour of real objects. They are
commonly utilised to offer test isolation, to stand in for objects which do not
yet exist, or to allow for the exploratory design of class APIs without
requiring actual implementation up front.

The benefits of a mock object framework are to allow for the flexible generation
of such mock objects (and stubs). They allow the setting of expected method calls
and return values using a flexible API which is capable of capturing every
possible real object behaviour in way that is stated as close as possible to a
natural language description.

Prerequisites
-------------

Mockery requires PHP 5.3.2 or greater. In addition, it is recommended to install
the Hamcrest library (see below for instructions) which contains additional
matchers used when defining expected method arguments.

Installation
------------

Mockery may be installed using Composer, PEAR or by cloning it from its GitHub repository. These
three options are outlined below.

**Composer**

You can read more about Composer and its main repository at
[http://packagist.org](http://packagist.org "Packagist"). To install
Mockery using Composer, first install Composer for your project using the instructions on the
Packagist home page. You can then define your development dependency on Mockery using the
suggested parameters below. While every effort is made to keep the master branch
stable, you may prefer to use the current stable version tag instead.

    {
        "require-dev": {
            "mockery/mockery": "dev-master@dev"
        }
    }

To install, you then may call:
    
    composer.phar install --dev
    
This will install Mockery as a development dependency but will not install it
for regular non-development installs.

**PEAR**

Mockery is hosted on the [survivethedeepend.com](http://pear.survivethedeepend.com) PEAR channel and
can be installed using the following commands:

    sudo pear channel-discover pear.survivethedeepend.com
    sudo pear channel-discover hamcrest.googlecode.com/svn/pear
    sudo pear install --alldeps deepend/Mockery

**Git / GitHub**

The git repository hosts the development version in its master branch. You can
install this using Composer by referencing dev-master as your preferred version
in your project's composer.json file as the earlier example shows.

You may also install this development version using PEAR:

    git clone git://github.com/padraic/mockery.git
    cd mockery
    sudo pear channel-discover hamcrest.googlecode.com/svn/pear
    sudo pear install --alldeps package.xml

The above processes will install both Mockery and Hamcrest.
While omitting Hamcrest will not break Mockery, Hamcrest is recommended
as it adds a wider variety of functionality for argument matching.

**Unit Testing**

To run the unit tests for Mockery, clone the git repository, download Composer (i.e. composer.phar) using the instructions at [http://getcomposer.org/download/](http://getcomposer.org/download/) and run the following Composer command from the root directory of Mockery:

    php /path/to/composer.phar install --dev

This will install the required Hamcrest dev dependency and create the autoload files required by the unit tests. Navigate to the "tests" directory and run the phpunit command as normal. With a wee bit of luck, there will be no failed tests!

Upgrading to 0.8.*
------------------

Since the release of 0.8.0 the following behaviours were altered:

1. The shouldIgnoreMissing() behaviour optionally applied to mock objects returned an instance of
\Mockery\Undefined when methods called did not match a known expectation. Since 0.8.0, this behaviour
was switched to returning NULL instead. You can restore the 0.7.2 behavour by using the following:

    $mock = \Mockery::mock('stdClass')->shouldIgnoreMissing()->asUndefined();

Simple Example
--------------

Imagine we have a Temperature class which samples the temperature of a locale
before reporting an average temperature. The data could come from a web service
or any other data source, but we do not have such a class at present. We can,
however, assume some basic interactions with such a class based on its interaction
with the Temperature class.

    class Temperature
    {

        public function __construct($service)
        {
            $this->_service = $service;
        }

        public function average()
        {
            $total = 0;
            for ($i=0;$i<3;$i++) {
                $total += $this->_service->readTemp();
            }
            return $total/3;
        }

    }

Even without an actual service class, we can see how we expect it to operate.
When writing a test for the Temperature class, we can now substitute a mock
object for the real service which allows us to test the behaviour of the
Temperature class without actually needing a concrete service instance.

Note: PHPUnit integration (see below) can remove the need for a tearDown() method.

    use \Mockery as m;

    class TemperatureTest extends PHPUnit_Framework_TestCase
    {

        public function tearDown()
        {
            m::close();
        }

        public function testGetsAverageTemperatureFromThreeServiceReadings()
        {
            $service = m::mock('service');
            $service->shouldReceive('readTemp')->times(3)->andReturn(10, 12, 14);
            $temperature = new Temperature($service);
            $this->assertEquals(12, $temperature->average());
        }

    }

We'll cover the API in greater detail below.

PHPUnit Integration
-------------------

Mockery was designed as a simple to use standalone mock object framework, so
its need for integration with any testing framework is entirely optional.
To integrate Mockery, you just need to define a tearDown() method for your
tests containing the following (you may use a shorter \Mockery namespace alias):

    public function tearDown() {
        \Mockery::close();
    }

This static call cleans up the Mockery container used by the current test, and
run any verification tasks needed for your expectations.

For some added brevity when it comes to using Mockery, you can also explicitly
use the Mockery namespace with a shorter alias. For example:

    use \Mockery as m;

    class SimpleTest extends PHPUnit_Framework_TestCase
    {
        public function testSimpleMock() {
            $mock = m::mock('simple mock');
            $mock->shouldReceive('foo')->with(5, m::any())->once()->andReturn(10);
            $this->assertEquals(10, $mock->foo(5));
        }

        public function tearDown() {
            m::close();
        }
    }

Mockery ships with an autoloader so you don't need to litter your tests with
require_once() calls. To use it, ensure Mockery is on your include_path and add
the following to your test suite's Bootstrap.php or TestHelper.php file:

    
    require_once 'Mockery/Loader.php';
    require_once 'Hamcrest/Hamcrest.php';
    $loader = new \Mockery\Loader;
    $loader->register();

If you are using Composer, you can simiplify this to just including the Composer generated autoloader file:

    require __DIR__ . '/../vendor/autoload.php'; // assuming vendor is one directory up

(Note: Prior to Hamcrest 1.0.0, the Hamcrest.php file name had a small "h", i.e. hamcrest.php. If upgrading Hamcrest to 1.0.0 remember to check the file name is updated for all your projects.)

To integrate Mockery into PHPUnit and avoid having to call the close method and
have Mockery remove itself from code coverage reports, use this in you suite:

    //Create Suite
    $suite = new PHPUnit_Framework_TestSuite();

    //Create a result listener or add it
    $result = new PHPUnit_Framework_TestResult();
    $result->addListener(new \Mockery\Adapter\Phpunit\TestListener());

    // Run the tests.
    $suite->run($result);

If you are using PHPUnit's XML configuration approach, you can include the following to load the TestListener:

    <listeners>
        <listener class="\Mockery\Adapter\Phpunit\TestListener"></listener>
    </listeners>

Make sure Composer's or Mockery's autoloader is present in the bootstrap file or you will need to also define a
"file" attribute pointing to the file of the above TestListener class.

Quick Reference
---------------

Mockery implements a shorthand API when creating a mock. Here's a sampling
of the possible startup methods.

    $mock = \Mockery::mock('foo');

Creates a mock object named foo. In this case, foo is a name (not necessarily
a class name) used as a simple identifier when raising exceptions. This creates
a mock object of type \Mockery\Mock and is the loosest form of mock possible.

    $mock = \Mockery::mock(array('foo'=>1,'bar'=>2));

Creates an mock object named unknown since we passed no name. However we did
pass an expectation array, a quick method of setting up methods to expect with
their return values.

    $mock = \Mockery::mock('foo', array('foo'=>1,'bar'=>2));

Similar to the previous examples and all examples going forward, expectation arrays
can be passed for all mock objects as the second parameter to mock().

    $mock = \Mockery::mock('foo', function($mock) {
        $mock->shouldReceive(method_name);
    });

In addition to expectation arrays, you can also pass in a closure which contains
reusable expectations. This can be passed as the second parameter, or as the third
parameter if partnered with an expectation array. This is one method for creating
reusable mock expectations.

    $mock = \Mockery::mock('stdClass');

Creates a mock identical to a named mock, except the name is an actual class
name. Creates a simple mock as previous examples show, except the mock
object will inherit the class type (via inheritance), i.e. it will pass type hints
or instanceof evaluations for stdClass. Useful where a mock object must be of a specific
type.

    $mock = \Mockery::mock('FooInterface');

You can create mock objects based on any concrete class, abstract class or
even an interface. Again, the primary purpose is to ensure the mock object
inherits a specific type for type hinting. There is an exception in that classes
marked final, or with methods marked final, cannot be mocked fully. In these cases
a partial mock (explained later) must be utilised.

    $mock = \Mockery::mock('alias:MyNamespace\MyClass');

Prefixing the valid name of a class (which is NOT currently loaded) with "alias:"
will generate an "alias mock". Alias mocks create a class alias with the given
classname to stdClass and are generally used to enable the mocking of public
static methods. Expectations set on the new mock object which refer to static
methods will be used by all static calls to this class.

    $mock = \Mockery::mock('overload:MyNamespace\MyClass');

Prefixing the valid name of a class (which is NOT currently loaded) with "overload:" will
generate an alias mock (as with "alias:") except that created new instances of that
class will import any expectations set on the origin mock ($mock). The origin
mock is never verified since it's used an expectation store for new instances. For this
purpose I used the term "instance mock" to differentiate it from the simpler "alias mock".

Note: Using alias/instance mocks across more than one test will generate a fatal error since
you can't have two classes of the same name. To avoid this, run each test of this
kind in a separate PHP process (which is supported out of the box by both
PHPUnit and PHPT).

    $mock = \Mockery::mock('stdClass, MyInterface1, MyInterface2');

The first argument can also accept a list of interfaces that the mock object must
implement, optionally including no more than one existing class to be based on. The
class name doesn't need to be the first member of the list but it's a friendly
convention to use for readability. All subsequent arguments remain unchanged from
previous examples.

If the given class does not exist, you must define and include it beforehand or a
\Mockery\Exception will be thrown.

    $mock = \Mockery::mock('MyNamespace\MyClass[foo,bar]');

The syntax above tells Mockery to partially mock the MyNamespace\MyClass class,
by mocking the foo() and bar() methods only. Any other method will be not be
overridden by Mockery. This traditional form of "partial mock" can be applied to any class
or abstract class (e.g. mocking abstract methods where a concrete implementation
does not exist yet). If you attempt to partial mock a method marked final, it will
actually be ignored in that instance leaving the final method untouched. This is
necessary since mocking of final methods is, by definition in PHP, impossible.

Please refer to [Creating Partial Mocks](#creating-partial-mocks) for a detailed
explanation on how to create Partial Mocks in Mockery.

    $mock = \Mockery::mock("MyNamespace\MyClass[foo]", array($arg1, $arg2));

If Mockery encounters an indexed array as the second or third argument, it will
assume they are constructor parameters and pass them when constructing the mock
object. The syntax above will create a new partial mock, particularly useful if
method `bar` calls method `foo` internally with `$this->foo()`.

    $mock = \Mockery::mock(new Foo);

Passing any real object into Mockery will create a Proxied Partial Mock. This
can be useful if real partials are impossible, e.g. a final class or class where
you absolutely must override a method marked final. Since you can already create
a concrete object, so all we need to do is selectively
override a subset of existing methods (or add non-existing methods!) for
our expectations.

A little revision: All mock methods accept the class, object or alias name to be
mocked as the first parameter. The second parameter can be an expectation array
of methods and their return values, or an expectation closure (which can be the
third param if used in conjunction with an expectation array).

    \Mockery::self()

At times, you will discover that expectations on a mock include methods which need
to return the same mock object (e.g. a common case when designing a Domain Specific
Language (DSL) such as the one Mockery itself uses!). To facilitate this, calling
\Mockery::self() will always return the last Mock Object created by calling
\Mockery::mock(). For example:

    $mock = \Mockery::mock('BazIterator')
        ->shouldReceive('next')
        ->andReturn(\Mockery::self())
        ->mock();

The above class being mocked, as the next() method suggests, is an iterator. In
many cases, you can replace all the iterated elements (since they are the same type
many times) with just the one mock object which is programmed to act as discrete
iterated elements.

### Behaviour Modifiers

When creating a mock object, you may wish to use some commonly preferred behaviours
that are not the default in Mockery.

    \Mockery:mock('MyClass')->shouldIgnoreMissing()
    
The use of the shouldIgnoreMissing() behaviour modifier will label this mock object
as a Passive Mock. In such a mock object, calls to methods which are not covered by
expectations will return NULL
instead of the usual complaining about there being no expectation matching the call.

You can optionally prefer to return an object of type \Mockery\Undefined (i.e.
a null object) (which was the 0.7.2 behaviour) by using an additional modifier:

    \Mockery:mock('MyClass')->shouldIgnoreMissing()->asUndefined()

The returned object is nothing more than a placeholder so if, by some act of fate,
it's erroneously used somewhere it shouldn't it will likely not pass a logic check.

    \Mockery::mock('MyClass')->makePartial()

also

    \Mockery::mock('MyClass')->shouldDeferMissing()
    
Known as a Passive Partial Mock (not to be confused with real partial mock objects
discussed later), this form of mock object will defer all methods not subject to
an expectation to the parent class of the mock, i.e. MyClass. Whereas the previous
shouldIgnoreMissing() returned NULL, this behaviour simply
calls the parent's matching method.

Expectation Declarations
------------------------

Once you have created a mock object, you'll often want to start defining how
exactly it should behave (and how it should be called). This is where the
Mockery expectation declarations take over.

    shouldReceive(method_name)

Declares that the mock expects a call to the given method name. This is the
starting expectation upon which all other expectations and constraints are
appended.

    shouldReceive(method1, method2, ...)

Declares a number of expected method calls, all of which will adopt any chained
expectations or constraints.

    shouldReceive(array('method1'=>1, 'method2'=>2, ...))

Declares a number of expected calls but also their return values. All will
adopt any additional chained expectations or constraints.

    shouldReceive(closure)

Creates a mock object (only from a partial mock) which is used to create a mock
object recorder. The recorder is a simple proxy to the original object passed
in for mocking. This is passed to the closure, which may run it through a set of
operations which are recorded as expectations on the partial mock. A simple
use case is automatically recording expectations based on an existing usage
(e.g. during refactoring). See examples in a later section.

    with(arg1, arg2, ...)

Adds a constraint that this expectation only applies to method calls which
match the expected argument list. You can add a lot more flexibility to argument
matching using the built in matcher classes (see later). For example,
\Mockery::any() matches any argument passed to that position in the with()
parameter list. Mockery also allows Hamcrest library matchers - for example, the
Hamcrest function anything() is equivalent to \Mockery:any().

It's important to note that this means all expectations attached only apply
to the given method when it is called with these exact arguments. This allows for
setting up differing expectations based on the arguments provided to expected calls.

    withAnyArgs()

Declares that this expectation matches a method call regardless of what arguments
are passed. This is set by default unless otherwise specified.

    withNoArgs()

Declares this expectation matches method calls with zero arguments.

    andReturn(value)

Sets a value to be returned from the expected method call.

    andReturn(value1, value2, ...)

Sets up a sequence of return values or closures. For example, the first call will return
value1 and the second value2. Note that all subsequent calls to a mocked method
will always return the final value (or the only value) given to this declaration.

    andReturnNull() / andReturn([NULL])

Both of the above options are primarily for communication to test readers. They mark the
mock object method call as returning NULL or nothing.

    andReturnValues(array)

Alternative syntax for andReturn() that accepts a simple array instead of a list of parameters.
The order of return is determined by the numerical index of the given array with the last array
member being return on all calls once previous return values are exhausted.

    andReturnUsing(closure, ...)

Sets a closure (anonymous function) to be called with the arguments passed to
the method. The return value from the closure is then returned. Useful for some
dynamic processing of arguments into related concrete results. Closures can
queued by passing them as extra parameters as for andReturn(). Note that you
cannot currently mix andReturnUsing() with andReturn().

    andThrow(Exception)

Declares that this method will throw the given Exception object when called.

    andThrow(exception_name, message)

Rather than an object, you can pass in the Exception class and message to
use when throwing an Exception from the mocked method.

    andSet(name, value1) / set(name, value1)

Used with an expectation so that when a matching method is called, one
can also cause a mock object's public property to be set to a specified value.

    zeroOrMoreTimes()

Declares that the expected method may be called zero or more times. This is
the default for all methods unless otherwise set.

    once()

Declares that the expected method may only be called once. Like all other
call count constraints, it will throw a \Mockery\CountValidator\Exception
if breached and can be modified by the atLeast() and atMost() constraints.

    twice()

Declares that the expected method may only be called twice.

    times(n)

Declares that the expected method may only be called n times.

    never()

Declares that the expected method may never be called. Ever!

    atLeast()

Adds a minimum modifier to the next call count expectation. Thus
atLeast()->times(3) means the call must be called at least three times (given
matching method args) but never less than three times.

    atMost()

Adds a maximum modifier to the next call count expectation. Thus
atMost()->times(3) means the call must be called no more than three times. This
also means no calls are acceptable.

    between(min, max)

Sets an expected range of call counts. This is actually identical to using
atLeast()->times(min)->atMost()->times(max) but is provided as a shorthand.
It may be followed by a times() call with no parameter to preserve the
APIs natural language readability.

    ordered()

Declares that this method is expected to be called in a specific order in
relation to similarly marked methods. The order is dictated by the order in
which this modifier is actually used when setting up mocks.

    ordered(group)

Declares the method as belonging to an order group (which can be named or
numbered). Methods within a group can be called in any order, but the ordered
calls from outside the group are ordered in relation to the group, i.e. you can
set up so that method1 is called before group1 which is in turn called before
method 2.

    globally()

When called prior to ordered() or ordered(group), it declares this ordering to
apply across all mock objects (not just the current mock). This allows for dictating
order expectations across multiple mocks.

    byDefault()

Marks an expectation as a default. Default expectations are applied unless
a non-default expectation is created. These later expectations immediately
replace the previously defined default. This is useful so you can setup default
mocks in your unit test setup() and later tweak them in specific tests as
needed.

    getMock()

Returns the current mock object from an expectation chain. Useful where
you prefer to keep mock setups as a single statement, e.g.

    $mock = \Mockery::mock('foo')->shouldReceive('foo')->andReturn(1)->getMock();


Argument Validation
-------------------

The arguments passed to the with() declaration when setting up an expectation
determine the criteria for matching method calls to expectations. Thus, you
can setup up many expectations for a single method, each differentiated by
the expected arguments. Such argument matching is done on a "best fit" basis.
This ensures explicit matches take precedence over generalised matches.

An explicit match is merely where the expected argument and the actual argument
are easily equated (i.e. using === or ==). More generalised matches are possible
using regular expressions, class hinting and the available generic matchers. The
purpose of generalised matchers is to allow arguments be defined in non-explicit
terms, e.g. Mockery::any() passed to with() will match ANY argument in that
position.

Mockery's generic matchers do not cover all possibilities but offers optional
support for the Hamcrest library of matchers. Hamcrest is a PHP port of the
similarly named Java library (which has been ported also to Python, Erlang, etc).
I strongly recommend using Hamcrest since Mockery simply does not need to duplicate
Hamcrest's already impressive utility which itself promotes a natural English DSL.

The example below show Mockery matchers and their Hamcrest equivalent. Hamcrest uses
functions (no namespacing).

Here's a sample of the possibilities.

    with(1)

Matches the integer 1. This passes the === test (identical). It does facilitate
a less strict == check (equals) where the string '1' would also match the
argument.

    with(\Mockery::any()) OR with(anything())

Matches any argument. Basically, anything and everything passed in this argument
slot is passed unconstrained.

    with(\Mockery::type('resource')) OR with(resourceValue()) OR with(typeOf('resource'))

Matches any resource, i.e. returns true from an is_resource() call. The Type
matcher accepts any string which can be attached to "is_" to form a valid
type check. For example, \Mockery::type('float') or Hamcrest's floatValue() and
typeOf('float') checks using is_float(), and \Mockery::type('callable') or Hamcrest's
callable() uses is_callable().

The Type matcher also accepts a class or interface name to be used in an instanceof
evaluation of the actual argument (similarly Hamcrest uses anInstanceOf()).

You may find a full list of the available type checkers at
http://www.php.net/manual/en/ref.var.php or browse Hamcrest's function list at
http://code.google.com/p/hamcrest/source/browse/trunk/hamcrest-php/hamcrest/Hamcrest.php.

    with(\Mockery::on(closure))

The On matcher accepts a closure (anonymous function) to which the actual argument
will be passed. If the closure evaluates to (i.e. returns) boolean TRUE then
the argument is assumed to have matched the expectation. This is invaluable
where your argument expectation is a bit too complex for or simply not
implemented in the current default matchers.

There is no Hamcrest version of this functionality.

    with('/^foo/') OR with(matchesPattern('/^foo/'))

The argument declarator also assumes any given string may be a regular
expression to be used against actual arguments when matching. The regex option
is only used when a) there is no === or == match and b) when the regex
is verified to be a valid regex (i.e. does not return false from preg_match()).
If the regex detection doesn't suit your tastes, Hamcrest offers the more
explicit matchesPattern() function.

    with(\Mockery::ducktype('foo', 'bar'))

The Ducktype matcher is an alternative to matching by class type. It simply
matches any argument which is an object containing the provided list
of methods to call.

There is no Hamcrest version of this functionality.

    with(\Mockery::mustBe(2)) OR with(identicalTo(2))

The MustBe matcher is more strict than the default argument matcher. The default
matcher allows for PHP type casting, but the MustBe matcher also verifies that
the argument must be of the same type as the expected value. Thus by default,
the argument '2' matches the actual argument 2 (integer) but the MustBe matcher
would fail in the same situation since the expected argument was a string and
instead we got an integer.

Note: Objects are not subject to an identical comparison using this matcher
since PHP would fail the comparison if both objects were not the exact same
instance. This is a hindrance when objects are generated prior to being
returned, since an identical match just would never be possible.

    with(\Mockery::not(2)) OR with(not(2))

The Not matcher matches any argument which is not equal or identical to the
matcher's parameter.

    with(\Mockery::anyOf(1, 2)) OR with(anyOf(1,2))

Matches any argument which equals any one of the given parameters.

    with(\Mockery::notAnyOf(1, 2))

Matches any argument which is not equal or identical to any of the given
parameters.

There is no Hamcrest version of this functionality.

    with(\Mockery::subset(array(0=>'foo')))

Matches any argument which is any array containing the given array subset. This
enforces both key naming and values, i.e. both the key and value of each
actual element is compared.

There is no Hamcrest version of this functionality, though Hamcrest can check a
single entry using hasEntry() or hasKeyValuePair().

    with(\Mockery::contains(value1, value2))

Matches any argument which is an array containing the listed values. The naming
of keys is ignored.

    with(\Mockery::hasKey(key));

Matches any argument which is an array containing the given key name.

    with(\Mockery::hasValue(value));

Matches any argument which is an array containing the given value.


Creating Partial Mocks
----------------------

Partial mocks are useful when you only need to mock several methods of 
an object leaving the remainder free to respond to calls normally (i.e.
as implemented). Mockery implements three distinct strategies for creating
partials. Each has specific advantages and disadvantages so which strategy
you use will depend on your own preferences and the source code in need
of mocking.

1. Traditional Partial Mock
2. Passive Partial Mock
3. Proxied Partial Mock

### Traditional Partial Mock

A traditional partial mock defined ahead of time which methods of a class
are to be mocked and which are to left unmocked (i.e. callable as normal).
The syntax for creating traditional mocks is:

    $mock = \Mockery::mock('MyClass[foo,bar]');

In the above example, the foo() and bar() methods of MyClass will be
mocked but no other MyClass methods are touched. You will need to define
expectations for the foo() and bar() methods to dictate their mocked behaviour.

Don't forget that you can pass in constructor arguments since unmocked
methods may rely on those!

    $mock = \Mockery::mock("MyNamespace\MyClass[foo]", array($arg1, $arg2));

### Passive Partial Mock

A passive partial mock is more of a default state of being.

    $mock = \Mockery::mock('MyClass')->makePartial();

In a passive partial, we assume that all methods will simply defer to
the parent class (MyClass) original methods unless a method call
matches a known expectation. If you have no matching expectation for
a specific method call, that call is deferred to the class being
mocked. Since the division between mocked and unmocked calls depends
entirely on the expectations you define, there is no need to define
which methods to mock in advance. The makePartial() method is identical to the
original shouldDeferMissing() method which first introduced this Partial Mock
type.

### Proxied Partial Mock

A proxied partial mock is a partial of last resort. You may encounter
a class which is simply not capable of being mocked because it has
been marked as final. Similarly, you may find a class with methods
marked as final. In such a scenario, we cannot simply extend the
class and override methods to mock - we need to get creative.

    $mock = \Mockery::mock(new MyClass);

Yes, the new mock is a Proxy. It intercepts calls and reroutes them to
the proxied object (which you construct and pass in) for methods which
are not subject to any expectations. Indirectly, this allows you to
mock methods marked final since the Proxy is not subject to those 
limitations. The tradeoff should be obvious - a proxied partial will
fail any typehint checks for the class being mocked since it cannot
extend that class.

#### Special Internal Case

There is a fourth kind of partial mock reserved for internal use. This is automatically
generated when you attempt to mock a class containing methods marked final. Since we
cannot override such methods, they are simply left unmocked. Typically, you don't need
to worry about this but if you really really must mock a final method, the only possible
means is through a Proxied Partial Mock. SplFileInfo, for example, is a common class subject
to this form of automatic internal partial since it contains public final methods used
internally.

Detecting Mock Objects
----------------------

Users may find it useful to check whether a given object is a real object or a simulated
Mock Object. All Mockery mocks implement the \Mockery\MockInterface interface which can
be used in a type check.

    assert($mightBeMocked instanceof \Mockery\MockInterface);

Default Mock Expectations
-------------------------

Often in unit testing, we end up with sets of tests which use the same object
dependency over and over again. Rather than mocking this class/object within
every single unit test (requiring a mountain of duplicate code), we can instead
define reusable default mocks within the test case's setup() method. This even
works where unit tests use varying expectations on the same or similar mock
object.

How this works, is that you can define mocks with default expectations. Then,
in a later unit test, you can add or fine-tune expectations for that
specific test. Any expectation can be set as a default using the byDefault()
declaration.

Mocking Public Properties
-------------------------

Mockery allows you to mock properties in several ways. The simplest is that
you can simply set a public property and value on any mock object. The second
is that you can use the expectation methods set() and andSet() to set property
values if that expectation is ever met.

You should note that, in general, Mockery does not support mocking any magic
methods since these are generally not considered a public API (and besides they
are a PITA to differentiate when you badly need them for mocking!). So please
mock virtual properties (those relying on __get and __set) as if they were
actually declared on the class.

Mocking Public Static Methods
-----------------------------

Static methods are not called on real objects, so normal mock objects can't mock
them. Mockery supports class aliased mocks, mocks representing a class name which
would normally be loaded (via autoloading or a require statement) in the system
under test. These aliases block that loading (unless via a require statement - so please
use autoloading!) and allow Mockery to intercept static method calls and add
expectations for them.

Generating Mock Objects Upon Instantiation (Instance Mocking)
-------------------------------------------------------------

Instance mocking means that a statement like:

$obj = new \MyNamespace\Foo;

...will actually generate a mock object. This is done by replacing the real class
with an instance mock (similar to an alias mock), as with mocking public methods.
The alias will import its
expectations from the original mock of that type (note that the original is never
verified and should be ignored after its expectations are setup). This lets you
intercept instantiation where you can't simply inject a replacement object.

As before, this does not prevent a require statement from including the real
class and triggering a fatal PHP error. It's intended for use where autoloading
is the primary class loading mechanism.

Preserving Pass-By-Reference Method Parameter Behaviour
-------------------------------------------------------

PHP Class method may accept parameters by reference. In this case, changes made
to the parameter (a reference to the original variable passed to the method) are
reflected in the original variable. A simple example:

    class Foo {
        public function bar(&$a) {
            $a++;
        }
    }

    $baz = 1;
    $foo = new Foo;
    $foo->bar($baz);

    echo $baz; // will echo the integer 2

In the example above, the variable $baz is passed by reference to Foo::bar()
(notice the "&" symbol in front of the parameter?).
Any change bar() makes to the parameter reference is reflected in the original
variable, $baz.

Mockery 0.7+ handles references correctly for all methods where it can analyse the
parameter (using Reflection) to see if it is passed by reference. To mock how a
reference is manipulated by the class method, you can use a closure argument
matcher to manipulate it, i.e. \Mockery::on() - see Argument Validation section
above.

There is an exception for internal PHP classes where Mockery cannot analyse
method parameters using Reflection (a limitation in PHP). To work around this,
you can explicitly declare method parameters for an internal class using
/Mockery/Configuration::setInternalClassMethodParamMap().

Here's an example using MongoCollection::insert(). MongoCollection is an internal
class offered by the mongo extension from PECL. Its insert() method accepts an array
of data as the first parameter, and an optional options array as the second
parameter. The original data array is updated (i.e. when a insert() pass-by-reference
parameter) to include a new "_id" field. We can mock this behaviour using
a configured parameter map (to tell Mockery to expect a pass by reference parameter)
and a Closure attached to the expected method parameter to be updated.

Here's a PHPUnit unit test verifying that this pass-by-reference behaviour is preserved:

    public function testCanOverrideExpectedParametersOfInternalPHPClassesToPreserveRefs()
    {
        \Mockery::getConfiguration()->setInternalClassMethodParamMap(
            'MongoCollection',
            'insert',
            array('&$data', '$options = array()')
        );
        $m = \Mockery::mock('MongoCollection');
        $m->shouldReceive('insert')->with(
            \Mockery::on(function(&$data) {
                if (!is_array($data)) return false;
                $data['_id'] = 123;
                return true;
            }),
            \Mockery::any()
        );
        $data = array('a'=>1,'b'=>2);
        $m->insert($data);
        $this->assertTrue(isset($data['_id']));
        $this->assertEquals(123, $data['_id']);
        \Mockery::resetContainer();
    }

Mocking Demeter Chains And Fluent Interfaces
--------------------------------------------

Both of these terms refer to the growing practice of invoking statements
similar to:

    $object->foo()->bar()->zebra()->alpha()->selfDestruct();

The long chain of method calls isn't necessarily a bad thing, assuming they
each link back to a local object the calling class knows. Just as a fun example,
Mockery's long chains (after the first shouldReceive() method) all call to the
same instance of \Mockery\Expectation. However, sometimes this is not the case
and the chain is constantly crossing object boundaries.

In either case, mocking such a chain can be a horrible task. To make it easier
Mockery support demeter chain mocking. Essentially, we shortcut through the
chain and return a defined value from the final call. For example, let's
assume selfDestruct() returns the string "Ten!" to $object (an instance of
CaptainsConsole). Here's how we could mock it.

    $mock = \Mockery::mock('CaptainsConsole');
    $mock->shouldReceive('foo->bar->zebra->alpha->selfDestruct')->andReturn('Ten!');

The above expectation can follow any previously seen format or expectation, except
that the method name is simply the string of all expected chain calls separated
by "->". Mockery will automatically setup the chain of expected calls with
its final return values, regardless of whatever intermediary object might be
used in the real implementation.

Arguments to all members of the chain (except the final call) are ignored in
this process.

Mockery Exceptions
------------------

Mockery throws three types of exceptions when it cannot verify a mock object.

1. \Mockery\Exception\InvalidCountException
2. \Mockery\Exception\InvalidOrderException
3. \Mockery\Exception\NoMatchingExpectationException

You can capture any of these exceptions in a try...catch block to query them for
specific information which is also passed along in the exception message but is provided
separately from getters should they
be useful when logging or reformatting output.

### \Mockery\Exception\InvalidCountException

The exception class is used when a method is called too many (or too few) times
and offers the following methods:

+ getMock() - return actual mock object
+ getMockName() - return the name of the mock object
+ getMethodName() - return the name of the method the failing expectation is attached to
+ getExpectedCount() - return expected calls
+ getExpectedCountComparative() - returns a string, e.g. "<=" used to compare to actual count
+ getActualCount() - return actual calls made with given argument constraints

### \Mockery\Exception\InvalidOrderException

The exception class is used when a method is called outside the expected order set using the
ordered() and globally() expectation modifiers. It offers the following methods:

+ getMock() - return actual mock object
+ getMockName() - return the name of the mock object
+ getMethodName() - return the name of the method the failing expectation is attached to
+ getExpectedOrder() - returns an integer represented the expected index for which this call was expected
+ getActualOrder() - return the actual index at which this method call occured.

### \Mockery\Exception\NoMatchingExpectationException

The exception class is used when a method call does not match any known expectation.
All expectations are uniquely identified in a mock object by the method name and the list
of expected arguments. You can disable this exception and opt for returning NULL from all
unexpected method calls by using the earlier mentioned shouldIgnoreMissing() behaviour
modifier.
This exception class offers the following methods:

+ getMock() - return actual mock object
+ getMockName() - return the name of the mock object
+ getMethodName() - return the name of the method the failing expectation is attached to
+ getActualArguments() - return actual arguments used to search for a matching expectation

Mock Object Recording
---------------------

In certain cases, you may find that you are testing against an already
established pattern of behaviour, perhaps during refactoring. Rather then hand
crafting mock object expectations for this behaviour, you could instead use
the existing source code to record the interactions a real object undergoes
onto a mock object as expectations - expectations you can then verify against
an alternative or refactored version of the source code.

To record expectations, you need a concrete instance of the class to be mocked.
This can then be used to create a partial mock to which is given the necessary
code to execute the object interactions to be recorded. A simple example is
outline below (we use a closure for passing instructions to the mock).

Here we have a very simple setup, a class (SubjectUser) which uses another class
(Subject) to retrieve some value. We want to record as expectations on our
mock (which will replace Subject later) all the calls and return values of
a Subject instance when interacting with SubjectUser.

    class Subject {

        public function execute() {
            return 'executed!';
        }
    }

    class SubjectUser {

        public function use(Subject $subject) {
            return $subject->execute();
        }
    }

Here's the test case showing the recording:

    class SubjectUserTest extends PHPUnit_Framework_TestCase
    {

        public function tearDown()
        {
            \Mockery::close();
        }

        public function testSomething()
        {
            $mock = \Mockery::mock(new Subject);
            $mock->shouldExpect(function ($subject) {
                $user = new SubjectUser;
                $user->use($subject);
            });

            /**
             * Assume we have a replacement SubjectUser called NewSubjectUser.
             * We want to verify it behaves identically to SubjectUser, i.e.
             * it uses Subject in the exact same way
             */
            $newSubject = new NewSubjectUser;
            $newSubject->use($mock);
        }

    }

After the \Mockery::close() call in tearDown() validates the mock object, we
should have zero exceptions if NewSubjectUser acted on Subject in a similar way
to SubjectUser. By default the order of calls are not enforced, and loose argument
matching is enabled, i.e. arguments may be equal (==) but not necessarily identical
(===).

If you wished to be more strict, for example ensuring the order of calls
and the final call counts were identical, or ensuring arguments are completely
identical, you can invoke the recorder's strict mode from the closure block, e.g.

    $mock->shouldExpect(function ($subject) {
        $subject->shouldBeStrict();
        $user = new SubjectUser;
        $user->use($subject);
    });

Dealing with Final Classes/Methods
----------------------------------

One of the primary restrictions of mock objects in PHP, is that mocking classes
or methods marked final is hard. The final keyword prevents methods so marked
from being replaced in subclasses (subclassing is how mock objects can inherit
the type of the class or object being mocked.

The simplest solution is not to mark classes or methods as final!

However, in a compromise between mocking functionality and type safety, Mockery
does allow creating "proxy mocks" from classes marked final, or from classes with
methods marked final. This offers all the usual mock object goodness but the
resulting mock will not inherit the class type of the object being mocked, i.e.
it will not pass any instanceof comparison.

You can create a proxy mock by passing the instantiated object you wish to mock
into \Mockery::mock(), i.e. Mockery will then generate a Proxy to the real object
and selectively intercept method calls for the purposes of setting and
meeting expectations.

Mockery Global Configuration
----------------------------

To allow for a degree of fine-tuning, Mockery utilises a singleton configuration
object to store a small subset of core behaviours. The three currently present
include:

* Option to allow/disallow the mocking of methods which do not actually exist
* Option to allow/disallow the existence of expectations which are never fulfilled (i.e. unused)
* Setter/Getter for added a parameter map for internal PHP class methods (Reflection cannot detect these automatically)

By default, the first two behaviours are enabled. Of course, there are situations where
this can lead to unintended consequences. The mocking of non-existent methods
may allow mocks based on real classes/objects to fall out of sync with the
actual implementations, especially when some degree of integration testing (testing
of object wiring) is not being performed. Allowing unfulfilled expectations means
unnecessary mock expectations go unnoticed, cluttering up test code, and
potentially confusing test readers.

You may allow or disallow these behaviours (whether for whole test suites or just
select tests) by using one or both of the following two calls:

    \Mockery::getConfiguration()->allowMockingNonExistentMethods(bool);
    \Mockery::getConfiguration()->allowMockingMethodsUnnecessarily(bool);

Passing a true allows the behaviour, false disallows it. Both take effect
immediately until switched back. In both cases, if either
behaviour is detected when not allowed, it will result in an Exception being
thrown at that point. Note that disallowing these behaviours should be carefully
considered since they necessarily remove at least some of Mockery's flexibility.

The other two methods are:

    \Mockery::getConfiguration()->setInternalClassMethodParamMap($class, $method, array $paramMap)
    \Mockery::getConfiguration()->getInternalClassMethodParamMap($class, $method)

These are used to define parameters (i.e. the signature string of each) for the
methods of internal PHP classes (e.g. SPL, or PECL extension classes like
ext/mongo's MongoCollection. Reflection cannot analyse the parameters of internal
classes. Most of the time, you never need to do this. It's mainly needed where an
internal class method uses pass-by-reference for a parameter - you MUST in such
cases ensure the parameter signature includes the "&" symbol correctly as Mockery
won't correctly add it automatically for internal classes.

Reserved Method Names
---------------------

As you may have noticed, Mockery uses a number of methods called directly on
all mock objects, for example shouldReceive(). Such methods are necessary
in order to setup expectations on the given mock, and so they cannot be
implemented on the classes or objects being mocked without creating a method
name collision (reported as a PHP fatal error). The methods reserved by Mockery are:

* shouldReceive()
* shouldBeStrict()

In addition, all mocks utilise a set of added methods and protected properties
which cannot exist on the class or object being mocked. These are far less likely
to cause collisions. All properties are prefixed with "_mockery" and all method
names with "mockery_".

PHP Magic Methods
-----------------

PHP magic methods which are prefixed with a double underscore, e.g. _set(), pose
a particular problem in mocking and unit testing in general. It is strongly
recommended that unit tests and mock objects do not directly refer to magic
methods. Instead, refer only to the virtual methods and properties these magic
methods simulate.

Following this piece of advice will ensure you are testing the real API of classes
and also ensures there is no conflict should Mockery override these magic methods,
which it will inevitably do in order to support its role in intercepting method
calls and properties.

Gotchas!
--------

Mocking objects in PHP has its limitations and gotchas. Some functionality can't
be mocked or can't be mocked YET! If you locate such a circumstance, please please
(pretty please with sugar on top) create a new issue on GitHub so it can be
documented and resolved where possible. Here is a list to note:

1. Classes containing public __wakeup methods can be mocked but the mocked __wakeup
method will perform no actions and cannot have expectations set for it. This is
necessary since Mockery must serialize and unserialize objects to avoid some
__construct() insanity and attempting to mock a __wakeup method as normal leads
to a BadMethodCallException been thrown.

2. Classes using non-real methods, i.e. where a method call triggers a __call
method, will throw an exception that the non-real method does not exist unless
you first define at least one expectation (a simple shouldReceive() call would
suffice). This is necessary since there is no other way for Mockery to be
aware of the method name.

3. Mockery has two scenarios where real classes are replaced: Instance mocks and
alias mocks. Both will generate PHP fatal errors if the real class is loaded,
usually via a require or include statement. Only use these two mock types where
autoloading is in place and where classes are not explicitly loaded on a per-file
basis using require(), require_once(), etc.

4. Internal PHP classes are not entirely capable of being fully analysed using
Reflection. For example, Reflection cannot reveal details of expected parameters
to the methods of such internal classes. As a result, there will be problems
where a method parameter is defined to accept a value by reference (Mockery
cannot detect this condition and will assume a pass by value on scalars and
arrays). If references as internal class method parameters are needed, you
should use the \Mockery\Configuration::setInternalClassMethodParamMap() method.

The gotchas noted above are largely down to PHP's architecture and are assumed
to be unavoidable. But - if you figure out a solution (or a better one than what
may exist), let me know!

Quick Examples
--------------

Create a mock object to return a sequence of values from a set of method calls.

    class SimpleTest extends PHPUnit_Framework_TestCase
    {

        public function tearDown()
        {
            \Mockery::close();
        }

        public function testSimpleMock()
        {
            $mock = \Mockery::mock(array('pi' => 3.1416, 'e' => 2.71));
            $this->assertEquals(3.1416, $mock->pi());
            $this->assertEquals(2.71, $mock->e());
        }

    }

Create a mock object which returns a self-chaining Undefined object for a method
call.

    use \Mockery as m;

    class UndefinedTest extends PHPUnit_Framework_TestCase
    {

        public function tearDown()
        {
            m::close();
        }

        public function testUndefinedValues()
        {
            $mock = m::mock('my mock');
            $mock->shouldReceive('divideBy')->with(0)->andReturnUndefined();
            $this->assertTrue($mock->divideBy(0) instanceof \Mockery\Undefined);
        }

    }

Creates a mock object which multiple query calls and a single update call

    use \Mockery as m;

    class DbTest extends PHPUnit_Framework_TestCase
    {

        public function tearDown()
        {
            m::close();
        }

        public function testDbAdapter()
        {
            $mock = m::mock('db');
            $mock->shouldReceive('query')->andReturn(1, 2, 3);
            $mock->shouldReceive('update')->with(5)->andReturn(NULL)->once();

            // test code here using the mock
        }

    }

Expect all queries to be executed before any updates.

    use \Mockery as m;

    class DbTest extends PHPUnit_Framework_TestCase
    {

        public function tearDown()
        {
            m::close();
        }

        public function testQueryAndUpdateOrder()
        {
            $mock = m::mock('db');
            $mock->shouldReceive('query')->andReturn(1, 2, 3)->ordered();
            $mock->shouldReceive('update')->andReturn(NULL)->once()->ordered();

            // test code here using the mock
        }

    }

Create a mock object where all queries occur after startup, but before finish, and
where queries are expected with several different params.

    use \Mockery as m;

    class DbTest extends PHPUnit_Framework_TestCase
    {

        public function tearDown()
        {
            m::close();
        }

        public function testOrderedQueries()
        {
            $db = m::mock('db');
            $db->shouldReceive('startup')->once()->ordered();
            $db->shouldReceive('query')->with('CPWR')->andReturn(12.3)->once()->ordered('queries');
            $db->shouldReceive('query')->with('MSFT')->andReturn(10.0)->once()->ordered('queries');
            $db->shouldReceive('query')->with("/^....$/")->andReturn(3.3)->atLeast()->once()->ordered('queries');
            $db->shouldReceive('finish')->once()->ordered();

            // test code here using the mock
        }

    }
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mutateme/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2012 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

/**
 */
class Mockery_MockTest extends PHPUnit_Framework_TestCase
{

    public function setup ()
    {
        $this->container = new \Mockery\Container;
    }
    
    public function teardown()
    {
        $this->container->mockery_close();
    }

    public function testAnonymousMockWorksWithNotAllowingMockingOfNonExistantMethods()
    {
        $before = \Mockery::getConfiguration()->mockingNonExistentMethodsAllowed();
        \Mockery::getConfiguration()->allowMockingNonExistentMethods(false);
        $m = $this->container->mock();
        $m->shouldReceive("test123")->andReturn(true);
        assertThat($m->test123(), equalTo(true));
        \Mockery::getConfiguration()->allowMockingNonExistentMethods(true);
    }

}

<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mutateme/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2012 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

/**
 * Ad-hoc unit tests for various scenarios reported by users
 */
class Mockery_AdhocTest extends PHPUnit_Framework_TestCase
{

    public function setup ()
    {
        $this->container = new \Mockery\Container;
    }
    
    public function teardown()
    {
        $this->container->mockery_close();
    }

    public function testSimplestMockCreation()
    {
        $m = $this->container->mock('MockeryTest_NameOfExistingClass');
        $this->assertTrue($m instanceof MockeryTest_NameOfExistingClass);
    }

    public function testMockeryInterfaceForClass()
    {
        $m = $this->container->mock('SplFileInfo');
        $this->assertTrue($m instanceof \Mockery\MockInterface);
    }

    public function testMockeryInterfaceForNonExistingClass()
    {
        $m = $this->container->mock('ABC_IDontExist');
        $this->assertTrue($m instanceof \Mockery\MockInterface);
    }

    public function testMockeryInterfaceForInterface()
    {
        $m = $this->container->mock('MockeryTest_NameOfInterface');
        $this->assertTrue($m instanceof \Mockery\MockInterface);
    }

    public function testMockeryInterfaceForAbstract()
    {
        $m = $this->container->mock('MockeryTest_NameOfAbstract');
        $this->assertTrue($m instanceof \Mockery\MockInterface);
    }


}

class MockeryTest_NameOfExistingClass {}

interface MockeryTest_NameOfInterface {
    public function foo();
}

abstract class MockeryTest_NameOfAbstract {
    abstract public function foo();
}<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

class RecorderTest extends PHPUnit_Framework_TestCase
{

    public function setup ()
    {
        $this->container = new \Mockery\Container;
    }
    
    public function teardown()
    {
        $this->container->mockery_close();
    }

    public function testRecorderWithSimpleObject()
    {
        $mock = $this->container->mock(new MockeryTestSubject);
        $mock->shouldExpect(function ($subject) {
            $user = new MockeryTestSubjectUser($subject);
            $user->doFoo();
        });
        
        $this->assertEquals(1, $mock->foo());
        $mock->mockery_verify();
    }
    
    public function testArgumentsArePassedAsMethodExpectations()
    {
        $mock = $this->container->mock(new MockeryTestSubject);
        $mock->shouldExpect(function ($subject) {
            $user = new MockeryTestSubjectUser($subject);
            $user->doBar();
        });
        
        $this->assertEquals(4, $mock->bar(2));
        $mock->mockery_verify();
    }
    
    public function testArgumentsLooselyMatchedByDefault()
    {
        $mock = $this->container->mock(new MockeryTestSubject);
        $mock->shouldExpect(function ($subject) {
            $user = new MockeryTestSubjectUser($subject);
            $user->doBar();
        });
        
        $this->assertEquals(4, $mock->bar('2'));
        $mock->mockery_verify();
    }
    
    public function testMultipleMethodExpectations()
    {
        $mock = $this->container->mock(new MockeryTestSubject);
        $mock->shouldExpect(function ($subject) {
            $user = new MockeryTestSubjectUser($subject);
            $user->doFoo();
            $user->doBar();
        });
        
        $this->assertEquals(1, $mock->foo());
        $this->assertEquals(4, $mock->bar(2));
        $mock->mockery_verify();
    }
    
    public function testRecordingDoesNotSpecifyExactOrderByDefault()
    {
        $mock = $this->container->mock(new MockeryTestSubject);
        $mock->shouldExpect(function ($subject) {
            $user = new MockeryTestSubjectUser($subject);
            $user->doFoo();
            $user->doBar();
        });
        
        $this->assertEquals(4, $mock->bar(2));
        $this->assertEquals(1, $mock->foo());
        $mock->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testRecordingDoesSpecifyExactOrderInStrictMode()
    {
        $mock = $this->container->mock(new MockeryTestSubject);
        $mock->shouldExpect(function ($subject) {
            $subject->shouldBeStrict();
            $user = new MockeryTestSubjectUser($subject);
            $user->doFoo();
            $user->doBar();
        });
        
        $mock->bar(2);
        $mock->foo();
        $mock->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testArgumentsAreMatchedExactlyUnderStrictMode()
    {
        $mock = $this->container->mock(new MockeryTestSubject);
        $mock->shouldExpect(function ($subject) {
            $subject->shouldBeStrict();
            $user = new MockeryTestSubjectUser($subject);
            $user->doBar();
        });
        
        $mock->bar('2');
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testThrowsExceptionWhenArgumentsNotExpected()
    {
        $mock = $this->container->mock(new MockeryTestSubject);
        $mock->shouldExpect(function ($subject) {
            $user = new MockeryTestSubjectUser($subject);
            $user->doBar();
        });
        
        $mock->bar(4);
    }
    
    public function testCallCountUnconstrainedByDefault()
    {
        $mock = $this->container->mock(new MockeryTestSubject);
        $mock->shouldExpect(function ($subject) {
            $user = new MockeryTestSubjectUser($subject);
            $user->doBar();
        });
        
        $mock->bar(2);
        $this->assertEquals(4, $mock->bar(2));
        $mock->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testCallCountConstrainedInStrictMode()
    {
        $mock = $this->container->mock(new MockeryTestSubject);
        $mock->shouldExpect(function ($subject) {
            $subject->shouldBeStrict();
            $user = new MockeryTestSubjectUser($subject);
            $user->doBar();
        });
        
        $mock->bar(2);
        $mock->bar(2);
        $mock->mockery_verify();
    }
    
}

class MockeryTestSubject {
    function foo() { return 1; }
    function bar($i) { return $i * 2; }
}

class MockeryTestSubjectUser {
    public $subject = null;
    function __construct($subject) { $this->subject = $subject; }
    function doFoo () { return $this->subject->foo(); }
    function doBar () { return $this->subject->bar(2); }
}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mutateme/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

class Mockery_LoaderTest extends PHPUnit_Framework_TestCase
{

    public function setUp()
    {
        spl_autoload_unregister('\Mockery\Loader::loadClass');
    }

    public function testCallingRegisterRegistersSelfAsSplAutoloaderFunction()
    {
        require_once 'Mockery/Loader.php';
        $loader = new \Mockery\Loader;
        $loader->register();
        $expected = array($loader, 'loadClass');
        $this->assertTrue(in_array($expected, spl_autoload_functions()));
    }

    public function tearDown()
    {
        spl_autoload_unregister('\Mockery\Loader::loadClass');
        $loader = new \Mockery\Loader;
        $loader->register();
    }

}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

class ExpectationTest extends PHPUnit_Framework_TestCase
{

    public function setup ()
    {
        $this->container = new \Mockery\Container;
        $this->mock = $this->container->mock('foo');
    }
    
    public function teardown()
    {
        \Mockery::getConfiguration()->allowMockingNonExistentMethods(true);
        $this->container->mockery_close();
    }

    public function testReturnsNullWhenNoArgs()
    {
        $this->mock->shouldReceive('foo');
        $this->assertNull($this->mock->foo());
    }
    
    public function testReturnsNullWhenSingleArg()
    {
        $this->mock->shouldReceive('foo');
        $this->assertNull($this->mock->foo(1));
    }
    
    public function testReturnsNullWhenManyArgs()
    {
        $this->mock->shouldReceive('foo');
        $this->assertNull($this->mock->foo('foo', array(), new stdClass));
    }

    public function testReturnsNullIfNullIsReturnValue()
    {
        $this->mock->shouldReceive('foo')->andReturn(null);
        $this->assertNull($this->mock->foo());
    }

    public function testReturnsNullForMockedExistingClassIfAndreturnnullCalled()
    {
        $mock = $this->container->mock('MockeryTest_Foo');
        $mock->shouldReceive('foo')->andReturn(null);
        $this->assertNull($mock->foo());
    }

    public function testReturnsNullForMockedExistingClassIfNullIsReturnValue()
    {
        $mock = $this->container->mock('MockeryTest_Foo');
        $mock->shouldReceive('foo')->andReturnNull();
        $this->assertNull($mock->foo());
    }
    
    public function testReturnsSameValueForAllIfNoArgsExpectationAndNoneGiven()
    {
        $this->mock->shouldReceive('foo')->andReturn(1);
        $this->assertEquals(1, $this->mock->foo());
    }
    
    public function testSetsPublicPropertyWhenRequested()
    {
        $this->mock->shouldReceive('foo')->andSet('bar', 'baz');
        $this->mock->foo();
        $this->assertEquals('baz', $this->mock->bar);
    }
    
    public function testSetsPublicPropertyWhenRequestedUsingAlias()
    {
        $this->mock->shouldReceive('foo')->set('bar', 'baz');
        $this->mock->foo();
        $this->assertEquals('baz', $this->mock->bar);
    }
    
    public function testReturnsSameValueForAllIfNoArgsExpectationAndSomeGiven()
    {
        $this->mock->shouldReceive('foo')->andReturn(1);
        $this->assertEquals(1, $this->mock->foo('foo'));
    }
    
    public function testReturnsValueFromSequenceSequentially()
    {
        $this->mock->shouldReceive('foo')->andReturn(1, 2, 3);
        $this->mock->foo('foo');
        $this->assertEquals(2, $this->mock->foo('foo'));
    }
    
    public function testReturnsValueFromSequenceSequentiallyAndRepeatedlyReturnsFinalValueOnExtraCalls()
    {
        $this->mock->shouldReceive('foo')->andReturn(1, 2, 3);
        $this->mock->foo('foo');
        $this->mock->foo('foo');
        $this->assertEquals(3, $this->mock->foo('foo'));
        $this->assertEquals(3, $this->mock->foo('foo'));
    }
    
    public function testReturnsValueFromSequenceSequentiallyAndRepeatedlyReturnsFinalValueOnExtraCallsWithManyAndReturnCalls()
    {
        $this->mock->shouldReceive('foo')->andReturn(1)->andReturn(2, 3);
        $this->mock->foo('foo');
        $this->mock->foo('foo');
        $this->assertEquals(3, $this->mock->foo('foo'));
        $this->assertEquals(3, $this->mock->foo('foo'));
    }

    public function testReturnsValueOfClosure()
    {
        $this->mock->shouldReceive('foo')->with(5)->andReturnUsing(function($v){return $v+1;});
        $this->assertEquals(6, $this->mock->foo(5));
    }
    
    public function testReturnsUndefined()
    {
        $this->mock->shouldReceive('foo')->andReturnUndefined();
        $this->assertTrue($this->mock->foo() instanceof \Mockery\Undefined);
    }

    public function testReturnsValuesSetAsArray()
    {
        $this->mock->shouldReceive('foo')->andReturnValues(array(1,2,3));
        $this->assertEquals(1, $this->mock->foo());
        $this->assertEquals(2, $this->mock->foo());
        $this->assertEquals(3, $this->mock->foo());
    }

    /**
     * @expectedException OutOfBoundsException
     */
    public function testThrowsException()
    {
        $this->mock->shouldReceive('foo')->andThrow(new OutOfBoundsException);
        $this->mock->foo();
    }
    
    /**
     * @expectedException OutOfBoundsException
     */
    public function testThrowsExceptionBasedOnArgs()
    {
        $this->mock->shouldReceive('foo')->andThrow('OutOfBoundsException');
        $this->mock->foo();
    }
    
    public function testThrowsExceptionBasedOnArgsWithMessage()
    {
        $this->mock->shouldReceive('foo')->andThrow('OutOfBoundsException', 'foo');
        try {
            $this->mock->foo();
        } catch (OutOfBoundsException $e) {
            $this->assertEquals('foo', $e->getMessage());
        }
    }
    
    /**
     * @expectedException OutOfBoundsException
     */
    public function testThrowsExceptionSequentially()
    {
        $this->mock->shouldReceive('foo')->andThrow(new Exception)->andThrow(new OutOfBoundsException);
        try {
            $this->mock->foo();
        } catch (Exception $e) {}
        $this->mock->foo();
    }
    
    public function testMultipleExpectationsWithReturns()
    {
        $this->mock->shouldReceive('foo')->with(1)->andReturn(10);
        $this->mock->shouldReceive('bar')->with(2)->andReturn(20);
        $this->assertEquals(10, $this->mock->foo(1));
        $this->assertEquals(20, $this->mock->bar(2));
    }
    
    public function testExpectsNoArguments()
    {
        $this->mock->shouldReceive('foo')->withNoArgs();
        $this->mock->foo();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testExpectsNoArgumentsThrowsExceptionIfAnyPassed()
    {
        $this->mock->shouldReceive('foo')->withNoArgs();
        $this->mock->foo(1);
    }
    
    public function testExpectsAnyArguments()
    {
        $this->mock->shouldReceive('foo')->withAnyArgs();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 'k', new stdClass);
    }
    
    public function testExpectsArgumentMatchingRegularExpression()
    {
        $this->mock->shouldReceive('foo')->with('/bar/i');
        $this->mock->foo('xxBARxx');
    }
    
    public function testExpectsArgumentMatchingObjectType()
    {
        $this->mock->shouldReceive('foo')->with('\stdClass');
        $this->mock->foo(new stdClass);
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testThrowsExceptionOnNoArgumentMatch()
    {
        $this->mock->shouldReceive('foo')->with(1);
        $this->mock->foo(2);
    }
    
    public function testNeverCalled()
    {
        $this->mock->shouldReceive('foo')->never();
    }
    
    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testNeverCalledThrowsExceptionOnCall()
    {
        $this->mock->shouldReceive('foo')->never();
        $this->mock->foo();
        $this->container->mockery_verify();
    }
    
    public function testCalledOnce()
    {
        $this->mock->shouldReceive('foo')->once();
        $this->mock->foo();
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testCalledOnceThrowsExceptionIfNotCalled()
    {
        $this->mock->shouldReceive('foo')->once();
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testCalledOnceThrowsExceptionIfCalledTwice()
    {
        $this->mock->shouldReceive('foo')->once();
        $this->mock->foo();
        $this->mock->foo();
        $this->container->mockery_verify();
    }
    
    public function testCalledTwice()
    {
        $this->mock->shouldReceive('foo')->twice();
        $this->mock->foo();
        $this->mock->foo();
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testCalledTwiceThrowsExceptionIfNotCalled()
    {
        $this->mock->shouldReceive('foo')->twice();
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testCalledOnceThrowsExceptionIfCalledThreeTimes()
    {
        $this->mock->shouldReceive('foo')->twice();
        $this->mock->foo();
        $this->mock->foo();
        $this->mock->foo();
        $this->container->mockery_verify();
    }
    
    public function testCalledZeroOrMoreTimesAtZeroCalls()
    {
        $this->mock->shouldReceive('foo')->zeroOrMoreTimes();
        $this->container->mockery_verify();
    }
    
    public function testCalledZeroOrMoreTimesAtThreeCalls()
    {
        $this->mock->shouldReceive('foo')->zeroOrMoreTimes();
        $this->mock->foo();
        $this->mock->foo();
        $this->mock->foo();
        $this->container->mockery_verify();
    }
    
    public function testTimesCountCalls()
    {
        $this->mock->shouldReceive('foo')->times(4);
        $this->mock->foo();
        $this->mock->foo();
        $this->mock->foo();
        $this->mock->foo();
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testTimesCountCallThrowsExceptionOnTooFewCalls()
    {
        $this->mock->shouldReceive('foo')->times(2);
        $this->mock->foo();
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testTimesCountCallThrowsExceptionOnTooManyCalls()
    {
        $this->mock->shouldReceive('foo')->times(2);
        $this->mock->foo();
        $this->mock->foo();
        $this->mock->foo();
        $this->container->mockery_verify();
    }
    
    public function testCalledAtLeastOnceAtExactlyOneCall()
    {
        $this->mock->shouldReceive('foo')->atLeast()->once();
        $this->mock->foo();
        $this->container->mockery_verify();
    }
    
    public function testCalledAtLeastOnceAtExactlyThreeCalls()
    {
        $this->mock->shouldReceive('foo')->atLeast()->times(3);
        $this->mock->foo();
        $this->mock->foo();
        $this->mock->foo();
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testCalledAtLeastThrowsExceptionOnTooFewCalls()
    {
        $this->mock->shouldReceive('foo')->atLeast()->twice();
        $this->mock->foo();
        $this->container->mockery_verify();
    }
    
    public function testCalledAtMostOnceAtExactlyOneCall()
    {
        $this->mock->shouldReceive('foo')->atMost()->once();
        $this->mock->foo();
        $this->container->mockery_verify();
    }
    
    public function testCalledAtMostAtExactlyThreeCalls()
    {
        $this->mock->shouldReceive('foo')->atMost()->times(3);
        $this->mock->foo();
        $this->mock->foo();
        $this->mock->foo();
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testCalledAtLeastThrowsExceptionOnTooManyCalls()
    {
        $this->mock->shouldReceive('foo')->atMost()->twice();
        $this->mock->foo();
        $this->mock->foo();
        $this->mock->foo();
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testExactCountersOverrideAnyPriorSetNonExactCounters()
    {
        $this->mock->shouldReceive('foo')->atLeast()->once()->once();
        $this->mock->foo();
        $this->mock->foo();
        $this->container->mockery_verify();
    }
    
    public function testComboOfLeastAndMostCallsWithOneCall()
    {
        $this->mock->shouldReceive('foo')->atleast()->once()->atMost()->twice();
        $this->mock->foo();
        $this->container->mockery_verify(); 
    }
    
    public function testComboOfLeastAndMostCallsWithTwoCalls()
    {
        $this->mock->shouldReceive('foo')->atleast()->once()->atMost()->twice();
        $this->mock->foo();
        $this->mock->foo();
        $this->container->mockery_verify(); 
    }
    
    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testComboOfLeastAndMostCallsThrowsExceptionAtTooFewCalls()
    {
        $this->mock->shouldReceive('foo')->atleast()->once()->atMost()->twice();
        $this->container->mockery_verify(); 
    }
    
    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testComboOfLeastAndMostCallsThrowsExceptionAtTooManyCalls()
    {
        $this->mock->shouldReceive('foo')->atleast()->once()->atMost()->twice();
        $this->mock->foo();
        $this->mock->foo();
        $this->mock->foo();
        $this->container->mockery_verify(); 
    }
    
    public function testCallCountingOnlyAppliesToMatchedExpectations()
    {
        $this->mock->shouldReceive('foo')->with(1)->once();
        $this->mock->shouldReceive('foo')->with(2)->twice();
        $this->mock->shouldReceive('foo')->with(3);
        $this->mock->foo(1);
        $this->mock->foo(2);
        $this->mock->foo(2);
        $this->mock->foo(3);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testCallCountingThrowsExceptionOnAnyMismatch()
    {
        $this->mock->shouldReceive('foo')->with(1)->once();
        $this->mock->shouldReceive('foo')->with(2)->twice();
        $this->mock->shouldReceive('foo')->with(3);
        $this->mock->shouldReceive('bar');
        $this->mock->foo(1);
        $this->mock->foo(2);
        $this->mock->foo(3);
        $this->mock->bar();
        $this->container->mockery_verify();
    }
    
    public function testOrderedCallsWithoutError()
    {
        $this->mock->shouldReceive('foo')->ordered();
        $this->mock->shouldReceive('bar')->ordered();
        $this->mock->foo();
        $this->mock->bar();
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testOrderedCallsWithOutOfOrderError()
    {
        $this->mock->shouldReceive('foo')->ordered();
        $this->mock->shouldReceive('bar')->ordered();
        $this->mock->bar();
        $this->mock->foo();
        $this->container->mockery_verify();
    }
    
    public function testDifferentArgumentsAndOrderingsPassWithoutException()
    {
        $this->mock->shouldReceive('foo')->with(1)->ordered();
        $this->mock->shouldReceive('foo')->with(2)->ordered();
        $this->mock->foo(1);
        $this->mock->foo(2);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testDifferentArgumentsAndOrderingsThrowExceptionWhenInWrongOrder()
    {
        $this->mock->shouldReceive('foo')->with(1)->ordered();
        $this->mock->shouldReceive('foo')->with(2)->ordered();
        $this->mock->foo(2);
        $this->mock->foo(1);
        $this->container->mockery_verify();
    }
    
    public function testUnorderedCallsIgnoredForOrdering()
    {
        $this->mock->shouldReceive('foo')->with(1)->ordered();
        $this->mock->shouldReceive('foo')->with(2);
        $this->mock->shouldReceive('foo')->with(3)->ordered();
        $this->mock->foo(2);
        $this->mock->foo(1);
        $this->mock->foo(2);
        $this->mock->foo(3);
        $this->mock->foo(2);
        $this->container->mockery_verify();
    }
    
    public function testOrderingOfDefaultGrouping()
    {
        $this->mock->shouldReceive('foo')->ordered();
        $this->mock->shouldReceive('bar')->ordered();
        $this->mock->foo();
        $this->mock->bar();
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testOrderingOfDefaultGroupingThrowsExceptionOnWrongOrder()
    {
        $this->mock->shouldReceive('foo')->ordered();
        $this->mock->shouldReceive('bar')->ordered();
        $this->mock->bar();
        $this->mock->foo();
        $this->container->mockery_verify();
    }
    
    public function testOrderingUsingNumberedGroups()
    {
        $this->mock->shouldReceive('start')->ordered(1);
        $this->mock->shouldReceive('foo')->ordered(2);
        $this->mock->shouldReceive('bar')->ordered(2);
        $this->mock->shouldReceive('final')->ordered();
        $this->mock->start();
        $this->mock->bar();
        $this->mock->foo();
        $this->mock->bar();
        $this->mock->final();
        $this->container->mockery_verify();
    }
    
    public function testOrderingUsingNamedGroups()
    {
        $this->mock->shouldReceive('start')->ordered('start');
        $this->mock->shouldReceive('foo')->ordered('foobar');
        $this->mock->shouldReceive('bar')->ordered('foobar');
        $this->mock->shouldReceive('final')->ordered();
        $this->mock->start();
        $this->mock->bar();
        $this->mock->foo();
        $this->mock->bar();
        $this->mock->final();
        $this->container->mockery_verify();
    }
    
    /**
     * @group 2A
     */
    public function testGroupedUngroupedOrderingDoNotOverlap()
    {
        $s = $this->mock->shouldReceive('start')->ordered();
        $m = $this->mock->shouldReceive('mid')->ordered('foobar');
        $e = $this->mock->shouldReceive('end')->ordered();
        $this->assertTrue($s->getOrderNumber() < $m->getOrderNumber());
        $this->assertTrue($m->getOrderNumber() < $e->getOrderNumber());
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testGroupedOrderingThrowsExceptionWhenCallsDisordered()
    {
        $this->mock->shouldReceive('foo')->ordered('first');
        $this->mock->shouldReceive('bar')->ordered('second');
        $this->mock->bar();
        $this->mock->foo();
        $this->container->mockery_verify();
    }
    
    public function testExpectationMatchingWithNoArgsOrderings()
    {
        $this->mock->shouldReceive('foo')->withNoArgs()->once()->ordered();
        $this->mock->shouldReceive('bar')->withNoArgs()->once()->ordered();
        $this->mock->shouldReceive('foo')->withNoArgs()->once()->ordered();
        $this->mock->foo();
        $this->mock->bar();
        $this->mock->foo();
        $this->container->mockery_verify();
    }
    
    public function testExpectationMatchingWithAnyArgsOrderings()
    {
        $this->mock->shouldReceive('foo')->withAnyArgs()->once()->ordered();
        $this->mock->shouldReceive('bar')->withAnyArgs()->once()->ordered();
        $this->mock->shouldReceive('foo')->withAnyArgs()->once()->ordered();
        $this->mock->foo();
        $this->mock->bar();
        $this->mock->foo();
        $this->container->mockery_verify();
    }
    
    public function testEnsuresOrderingIsNotCrossMockByDefault()
    {
        $this->mock->shouldReceive('foo')->ordered();
        $mock2 = $this->container->mock('bar');
        $mock2->shouldReceive('bar')->ordered();
        $mock2->bar();
        $this->mock->foo();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testEnsuresOrderingIsCrossMockWhenGloballyFlagSet()
    {
        $this->mock->shouldReceive('foo')->globally()->ordered();
        $mock2 = $this->container->mock('bar');
        $mock2->shouldReceive('bar')->globally()->ordered();
        $mock2->bar();
        $this->mock->foo();
    }
    
    public function testExpectationCastToStringFormatting()
    {
        $exp = $this->mock->shouldReceive('foo')->with(1, 'bar', new stdClass, array());
        $this->assertEquals('[foo(1, "bar", stdClass, Array)]', (string) $exp);
    }
    
    public function testMultipleExpectationCastToStringFormatting()
    {
        $exp = $this->mock->shouldReceive('foo', 'bar')->with(1);
        $this->assertEquals('[foo(1), bar(1)]', (string) $exp);
    }
    
    public function testGroupedOrderingWithLimitsAllowsMultipleReturnValues()
    {
        $this->mock->shouldReceive('foo')->with(2)->once()->andReturn('first');
        $this->mock->shouldReceive('foo')->with(2)->twice()->andReturn('second/third');
        $this->mock->shouldReceive('foo')->with(2)->andReturn('infinity');
        $this->assertEquals('first', $this->mock->foo(2));
        $this->assertEquals('second/third', $this->mock->foo(2));
        $this->assertEquals('second/third', $this->mock->foo(2));
        $this->assertEquals('infinity', $this->mock->foo(2));
        $this->assertEquals('infinity', $this->mock->foo(2));
        $this->assertEquals('infinity', $this->mock->foo(2));
        $this->container->mockery_verify();
    }
    
    public function testExpectationsCanBeMarkedAsDefaults()
    {
        $this->mock->shouldReceive('foo')->andReturn('bar')->byDefault();
        $this->assertEquals('bar', $this->mock->foo());
        $this->container->mockery_verify();
    }
    
    public function testDefaultExpectationsValidatedInCorrectOrder()
    {
        $this->mock->shouldReceive('foo')->with(1)->once()->andReturn('first')->byDefault();
        $this->mock->shouldReceive('foo')->with(2)->once()->andReturn('second')->byDefault();
        $this->assertEquals('first', $this->mock->foo(1));
        $this->assertEquals('second', $this->mock->foo(2));
        $this->container->mockery_verify();
    }
    
    public function testDefaultExpectationsAreReplacedByLaterConcreteExpectations()
    {
        $this->mock->shouldReceive('foo')->andReturn('bar')->once()->byDefault();
        $this->mock->shouldReceive('foo')->andReturn('bar')->twice();
        $this->mock->foo();
        $this->mock->foo();
        $this->container->mockery_verify();
    }
    
    public function testDefaultExpectationsCanBeChangedByLaterExpectations()
    {
        $this->mock->shouldReceive('foo')->with(1)->andReturn('bar')->once()->byDefault();
        $this->mock->shouldReceive('foo')->with(2)->andReturn('baz')->once();
        try {
            $this->mock->foo(1);
            $this->fail('Expected exception not thrown');
        } catch (\Mockery\Exception $e) {}
        $this->mock->foo(2);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testDefaultExpectationsCanBeOrdered()
    {
        $this->mock->shouldReceive('foo')->ordered()->byDefault();
        $this->mock->shouldReceive('bar')->ordered()->byDefault();
        $this->mock->bar();
        $this->mock->foo();
        $this->container->mockery_verify();
    }
    
    public function testDefaultExpectationsCanBeOrderedAndReplaced()
    {
        $this->mock->shouldReceive('foo')->ordered()->byDefault();
        $this->mock->shouldReceive('bar')->ordered()->byDefault();
        $this->mock->shouldReceive('bar')->ordered();
        $this->mock->shouldReceive('foo')->ordered();
        $this->mock->bar();
        $this->mock->foo();
        $this->container->mockery_verify();
    }
    
    public function testByDefaultOperatesFromMockConstruction()
    {
        $container = new \Mockery\Container;
        $mock = $container->mock('f', array('foo'=>'rfoo','bar'=>'rbar','baz'=>'rbaz'))->byDefault();
        $mock->shouldReceive('foo')->andReturn('foobar');
        $this->assertEquals('foobar', $mock->foo());
        $this->assertEquals('rbar', $mock->bar());
        $this->assertEquals('rbaz', $mock->baz());
        $mock->mockery_verify();
    }
    
    public function testByDefaultOnAMockDoesSquatWithoutExpectations()
    {
        $container = new \Mockery\Container;
        $mock = $container->mock('f')->byDefault();
    }

    public function testDefaultExpectationsCanBeOverridden()
    {
        $this->mock->shouldReceive('foo')->with('test')->andReturn('bar')->byDefault();
        $this->mock->shouldReceive('foo')->with('test')->andReturn('newbar')->byDefault();
        $this->mock->foo('test');
        $this->assertEquals('newbar', $this->mock->foo('test'));
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testByDefaultPreventedFromSettingDefaultWhenDefaultingExpectationWasReplaced()
    {
        $exp = $this->mock->shouldReceive('foo')->andReturn(1);
        $this->mock->shouldReceive('foo')->andReturn(2);
        $exp->byDefault();
    }
    
    /**
     * Argument Constraint Tests
     */
    
    public function testAnyConstraintMatchesAnyArg()
    {
        $this->mock->shouldReceive('foo')->with(1, Mockery::any())->twice();
        $this->mock->foo(1, 2);
        $this->mock->foo(1, 'str');
        $this->container->mockery_verify();
    }
    
    public function testAnyConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::any())->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }
    
    public function testArrayConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('array'))->once();
        $this->mock->foo(array());
        $this->container->mockery_verify();
    }
    
    public function testArrayConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('array'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testArrayConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('array'))->once();
        $this->mock->foo(1);
        $this->container->mockery_verify();
    }
    
    public function testBoolConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('bool'))->once();
        $this->mock->foo(true);
        $this->container->mockery_verify();
    }
    
    public function testBoolConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('bool'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testBoolConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('bool'))->once();
        $this->mock->foo(1);
        $this->container->mockery_verify();
    }
    
    public function testCallableConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('callable'))->once();
        $this->mock->foo(function(){return 'f';});
        $this->container->mockery_verify();
    }
    
    public function testCallableConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('callable'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testCallableConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('callable'))->once();
        $this->mock->foo(1);
        $this->container->mockery_verify();
    }
    
    public function testDoubleConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('double'))->once();
        $this->mock->foo(2.25);
        $this->container->mockery_verify();
    }
    
    public function testDoubleConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('double'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testDoubleConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('double'))->once();
        $this->mock->foo(1);
        $this->container->mockery_verify();
    }
    
    public function testFloatConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('float'))->once();
        $this->mock->foo(2.25);
        $this->container->mockery_verify();
    }
    
    public function testFloatConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('float'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testFloatConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('float'))->once();
        $this->mock->foo(1);
        $this->container->mockery_verify();
    }
    
    public function testIntConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('int'))->once();
        $this->mock->foo(2);
        $this->container->mockery_verify();
    }
    
    public function testIntConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('int'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testIntConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('int'))->once();
        $this->mock->foo('f');
        $this->container->mockery_verify();
    }
    
    public function testLongConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('long'))->once();
        $this->mock->foo(2);
        $this->container->mockery_verify();
    }
    
    public function testLongConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('long'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testLongConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('long'))->once();
        $this->mock->foo('f');
        $this->container->mockery_verify();
    }
    
    public function testNullConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('null'))->once();
        $this->mock->foo(null);
        $this->container->mockery_verify();
    }
    
    public function testNullConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('null'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testNullConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('null'))->once();
        $this->mock->foo('f');
        $this->container->mockery_verify();
    }
    
    public function testNumericConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('numeric'))->once();
        $this->mock->foo('2');
        $this->container->mockery_verify();
    }
    
    public function testNumericConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('numeric'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testNumericConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('numeric'))->once();
        $this->mock->foo('f');
        $this->container->mockery_verify();
    }
    
    public function testObjectConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('object'))->once();
        $this->mock->foo(new stdClass);
        $this->container->mockery_verify();
    }
    
    public function testObjectConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('object`'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testObjectConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('object'))->once();
        $this->mock->foo('f');
        $this->container->mockery_verify();
    }
    
    public function testRealConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('real'))->once();
        $this->mock->foo(2.25);
        $this->container->mockery_verify();
    }
    
    public function testRealConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('real'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testRealConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('real'))->once();
        $this->mock->foo('f');
        $this->container->mockery_verify();
    }
    
    public function testResourceConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('resource'))->once();
        $r = fopen(dirname(__FILE__) . '/_files/file.txt', 'r');
        $this->mock->foo($r);
        $this->container->mockery_verify();
    }
    
    public function testResourceConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('resource'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testResourceConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('resource'))->once();
        $this->mock->foo('f');
        $this->container->mockery_verify();
    }
    
    public function testScalarConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('scalar'))->once();
        $this->mock->foo(2);
        $this->container->mockery_verify();
    }
    
    public function testScalarConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('scalar'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testScalarConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('scalar'))->once();
        $this->mock->foo(array());
        $this->container->mockery_verify();
    }
    
    public function testStringConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('string'))->once();
        $this->mock->foo('2');
        $this->container->mockery_verify();
    }
    
    public function testStringConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('string'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testStringConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('string'))->once();
        $this->mock->foo(1);
        $this->container->mockery_verify();
    }
    
    public function testClassConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('stdClass'))->once();
        $this->mock->foo(new stdClass);
        $this->container->mockery_verify();
    }
    
    public function testClassConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::type('stdClass'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testClassConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::type('stdClass'))->once();
        $this->mock->foo(new Exception);
        $this->container->mockery_verify();
    }
    
    public function testDucktypeConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::ducktype('quack', 'swim'))->once();
        $this->mock->foo(new Mockery_Duck);
        $this->container->mockery_verify();
    }
    
    public function testDucktypeConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::ducktype('quack', 'swim'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testDucktypeConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::ducktype('quack', 'swim'))->once();
        $this->mock->foo(new Mockery_Duck_Nonswimmer);
        $this->container->mockery_verify();
    }
    
    public function testArrayContentConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::subset(array('a'=>1,'b'=>2)))->once();
        $this->mock->foo(array('a'=>1,'b'=>2,'c'=>3));
        $this->container->mockery_verify();
    }
    
    public function testArrayContentConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::subset(array('a'=>1,'b'=>2)))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testArrayContentConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::subset(array('a'=>1,'b'=>2)))->once();
        $this->mock->foo(array('a'=>1,'c'=>3));
        $this->container->mockery_verify();
    }
    
    public function testContainsConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::contains(1, 2))->once();
        $this->mock->foo(array('a'=>1,'b'=>2,'c'=>3));
        $this->container->mockery_verify();
    }
    
    public function testContainsConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::contains(1, 2))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testContainsConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::contains(1, 2))->once();
        $this->mock->foo(array('a'=>1,'c'=>3));
        $this->container->mockery_verify();
    }
    
    public function testHasKeyConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::hasKey('c'))->once();
        $this->mock->foo(array('a'=>1,'b'=>2,'c'=>3));
        $this->container->mockery_verify();
    }
    
    public function testHasKeyConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::hasKey('a'))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, array('a'=>1), 3);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testHasKeyConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::hasKey('c'))->once();
        $this->mock->foo(array('a'=>1,'b'=>3));
        $this->container->mockery_verify();
    }
    
    public function testHasValueConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::hasValue(1))->once();
        $this->mock->foo(array('a'=>1,'b'=>2,'c'=>3));
        $this->container->mockery_verify();
    }
    
    public function testHasValueConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::hasValue(1))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, array('a'=>1), 3);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testHasValueConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::hasValue(2))->once();
        $this->mock->foo(array('a'=>1,'b'=>3));
        $this->container->mockery_verify();
    }
    
    public function testOnConstraintMatchesArgument_ClosureEvaluatesToTrue()
    {
        $function = function($arg){return $arg % 2 == 0;};
        $this->mock->shouldReceive('foo')->with(Mockery::on($function))->once();
        $this->mock->foo(4);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testOnConstraintThrowsExceptionWhenConstraintUnmatched_ClosureEvaluatesToFalse()
    {
        $function = function($arg){return $arg % 2 == 0;};
        $this->mock->shouldReceive('foo')->with(Mockery::on($function))->once();
        $this->mock->foo(5);
        $this->container->mockery_verify();
    }
    
    public function testMustBeConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::mustBe(2))->once();
        $this->mock->foo(2);
        $this->container->mockery_verify();
    }
    
    public function testMustBeConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::mustBe(2))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testMustBeConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::mustBe(2))->once();
        $this->mock->foo('2');
        $this->container->mockery_verify();
    }
    
    public function testMustBeConstraintMatchesObjectArgumentWithEqualsComparisonNotIdentical()
    {
        $a = new stdClass; $a->foo = 1;
        $b = new stdClass; $b->foo = 1;
        $this->mock->shouldReceive('foo')->with(Mockery::mustBe($a))->once();
        $this->mock->foo($b);
        $this->container->mockery_verify();
    }
    
    public function testMustBeConstraintNonMatchingCaseWithObject()
    {
        $a = new stdClass; $a->foo = 1;
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::mustBe($a))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, $a, 3);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testMustBeConstraintThrowsExceptionWhenConstraintUnmatchedWithObject()
    {
        $a = new stdClass; $a->foo = 1;
        $b = new stdClass; $b->foo = 2;
        $this->mock->shouldReceive('foo')->with(Mockery::mustBe($a))->once();
        $this->mock->foo($b);
        $this->container->mockery_verify();
    }
    
    public function testMatchPrecedenceBasedOnExpectedCallsFavouringExplicitMatch()
    {
        $this->mock->shouldReceive('foo')->with(1)->once();
        $this->mock->shouldReceive('foo')->with(Mockery::any())->never();
        $this->mock->foo(1);
        $this->container->mockery_verify();
    }
    
    public function testMatchPrecedenceBasedOnExpectedCallsFavouringAnyMatch()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::any())->once();
        $this->mock->shouldReceive('foo')->with(1)->never();
        $this->mock->foo(1);
        $this->container->mockery_verify();
    }
    
    public function testReturnNullIfIgnoreMissingMethodsSet()
    {
        $this->mock->shouldIgnoreMissing();
        $this->assertNull($this->mock->g(1,2));
    }

    public function testReturnUndefinedIfIgnoreMissingMethodsSet()
    {
        $this->mock->shouldIgnoreMissing()->asUndefined();
        $this->assertTrue($this->mock->g(1,2) instanceof \Mockery\Undefined);
    }
    
    public function testReturnAsUndefinedAllowsForInfiniteSelfReturningChain()
    {
        $this->mock->shouldIgnoreMissing()->asUndefined();
        $this->assertTrue($this->mock->g(1,2)->a()->b()->c() instanceof \Mockery\Undefined);
    }

    public function testShouldIgnoreMissingFluentInterface()
    {
        $this->assertTrue($this->mock->shouldIgnoreMissing() instanceof \Mockery\MockInterface);
    }

    public function testShouldIgnoreMissingAsUndefinedFluentInterface()
    {
        $this->assertTrue($this->mock->shouldIgnoreMissing()->asUndefined() instanceof \Mockery\MockInterface);
    }

    public function testShouldIgnoreMissingAsDefinedProxiesToUndefinedAllowingToString()
    {
        $this->mock->shouldIgnoreMissing()->asUndefined();
        $string = "Method call: {$this->mock->g()}";
        $string = "Mock: {$this->mock}";
    }

    public function testToStringMagicMethodCanBeMocked()
    {
        $this->mock->shouldReceive("__toString")->andReturn('dave');
        $this->assertEquals("{$this->mock}", "dave");
    }

    public function testOptionalMockRetrieval()
    {
        $m = $this->container->mock('f')->shouldReceive('foo')->with(1)->andReturn(3)->mock();
        $this->assertTrue($m instanceof \Mockery\MockInterface);
    }
    
    public function testNotConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::not(1))->once();
        $this->mock->foo(2);
        $this->container->mockery_verify();
    }
    
    public function testNotConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::not(2))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testNotConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::not(2))->once();
        $this->mock->foo(2);
        $this->container->mockery_verify();
    }

    public function testAnyOfConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::anyOf(1, 2))->twice();
        $this->mock->foo(2);
        $this->mock->foo(1);
        $this->container->mockery_verify();
    }
    
    public function testAnyOfConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::anyOf(1, 2))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 2, 3);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testAnyOfConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::anyOf(1, 2))->once();
        $this->mock->foo(3);
        $this->container->mockery_verify();
    }
    
    public function testNotAnyOfConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::notAnyOf(1, 2))->once();
        $this->mock->foo(3);
        $this->container->mockery_verify();
    }
    
    public function testNotAnyOfConstraintNonMatchingCase()
    {
        $this->mock->shouldReceive('foo')->times(3);
        $this->mock->shouldReceive('foo')->with(1, Mockery::notAnyOf(1, 2))->never();
        $this->mock->foo();
        $this->mock->foo(1);
        $this->mock->foo(1, 4, 3);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testNotAnyOfConstraintThrowsExceptionWhenConstraintUnmatched()
    {
        $this->mock->shouldReceive('foo')->with(Mockery::notAnyOf(1, 2))->once();
        $this->mock->foo(2);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException \Mockery\Exception
     */
    public function testGlobalConfigMayForbidMockingNonExistentMethodsOnClasses()
    {
        \Mockery::getConfiguration()->allowMockingNonExistentMethods(false);
        $mock = $this->container->mock('stdClass');
        $mock->shouldReceive('foo');
    }
    
    /**
     * @expectedException \Mockery\Exception
     * @expectedExceptionMessage Mockery's configuration currently forbids mocking 
     */
    public function testGlobalConfigMayForbidMockingNonExistentMethodsOnAutoDeclaredClasses()
    {
        \Mockery::getConfiguration()->allowMockingNonExistentMethods(false);
        $mock = $this->container->mock('SomeMadeUpClass');
        $mock->shouldReceive('foo');
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testGlobalConfigMayForbidMockingNonExistentMethodsOnObjects()
    {
        \Mockery::getConfiguration()->allowMockingNonExistentMethods(false);
        $mock = $this->container->mock(new stdClass);
        $mock->shouldReceive('foo');
    }
    
    public function testAnExampleWithSomeExpectationAmends()
    {
        $service = $this->container->mock('MyService');
        $service->shouldReceive('login')->with('user', 'pass')->once()->andReturn(true);
        $service->shouldReceive('hasBookmarksTagged')->with('php')->once()->andReturn(false);
        $service->shouldReceive('addBookmark')->with('/^http:/', \Mockery::type('string'))->times(3)->andReturn(true);
        $service->shouldReceive('hasBookmarksTagged')->with('php')->once()->andReturn(true);
        
        $this->assertTrue($service->login('user', 'pass'));
        $this->assertFalse($service->hasBookmarksTagged('php'));
        $this->assertTrue($service->addBookmark('http://example.com/1', 'some_tag1'));
        $this->assertTrue($service->addBookmark('http://example.com/2', 'some_tag2'));
        $this->assertTrue($service->addBookmark('http://example.com/3', 'some_tag3'));
        $this->assertTrue($service->hasBookmarksTagged('php'));
        
        $this->container->mockery_verify();
    }
    
    public function testAnExampleWithSomeExpectationAmendsOnCallCounts()
    {
        $service = $this->container->mock('MyService');
        $service->shouldReceive('login')->with('user', 'pass')->once()->andReturn(true);
        $service->shouldReceive('hasBookmarksTagged')->with('php')->once()->andReturn(false);
        $service->shouldReceive('addBookmark')->with('/^http:/', \Mockery::type('string'))->times(3)->andReturn(true);
        $service->shouldReceive('hasBookmarksTagged')->with('php')->twice()->andReturn(true);
        
        $this->assertTrue($service->login('user', 'pass'));
        $this->assertFalse($service->hasBookmarksTagged('php'));
        $this->assertTrue($service->addBookmark('http://example.com/1', 'some_tag1'));
        $this->assertTrue($service->addBookmark('http://example.com/2', 'some_tag2'));
        $this->assertTrue($service->addBookmark('http://example.com/3', 'some_tag3'));
        $this->assertTrue($service->hasBookmarksTagged('php'));
        $this->assertTrue($service->hasBookmarksTagged('php'));
        
        $this->container->mockery_verify();
    }
    
    public function testAnExampleWithSomeExpectationAmendsOnCallCounts_PHPUnitTest()
    {
        $service = $this->getMock('MyService2');
        $service->expects($this->once())->method('login')->with('user', 'pass')->will($this->returnValue(true));
        $service->expects($this->exactly(3))->method('hasBookmarksTagged')->with('php')
            ->will($this->onConsecutiveCalls(false, true, true));
        $service->expects($this->exactly(3))->method('addBookmark')
            ->with($this->matchesRegularExpression('/^http:/'), $this->isType('string'))
            ->will($this->returnValue(true));
        
        $this->assertTrue($service->login('user', 'pass'));
        $this->assertFalse($service->hasBookmarksTagged('php'));
        $this->assertTrue($service->addBookmark('http://example.com/1', 'some_tag1'));
        $this->assertTrue($service->addBookmark('http://example.com/2', 'some_tag2'));
        $this->assertTrue($service->addBookmark('http://example.com/3', 'some_tag3'));
        $this->assertTrue($service->hasBookmarksTagged('php'));
        $this->assertTrue($service->hasBookmarksTagged('php'));
    }

    public function testMockedMethodsCallableFromWithinOriginalClass()
    {
        $mock = $this->container->mock('MockeryTest_InterMethod1[doThird]');
        $mock->shouldReceive('doThird')->andReturn(true);
        $this->assertTrue($mock->doFirst());
    }

    /**
     * @group issue #20
     */
    public function testMockingDemeterChainsPassesMockeryExpectationToCompositeExpectation()
    {
        $mock = $this->container->mock('Mockery_Demeterowski');
        $mock->shouldReceive('foo->bar->baz')->andReturn('Spam!');
        $demeter = new Mockery_UseDemeter($mock);
        $this->assertSame('Spam!', $demeter->doit());
    }

    /**
     * @group issue #20 - with args in demeter chain
     */
    public function testMockingDemeterChainsPassesMockeryExpectationToCompositeExpectationWithArgs()
    {
        $mock = $this->container->mock('Mockery_Demeterowski');
        $mock->shouldReceive('foo->bar->baz')->andReturn('Spam!');
        $demeter = new Mockery_UseDemeter($mock);
        $this->assertSame('Spam!', $demeter->doitWithArgs());
    }

    /**
    * @expectedException PHPUnit_Framework_Error_Warning
    */
    public function testPregMatchThrowsDelimiterWarningWithXdebugScreamTurnedOn()
    {
        if (!extension_loaded('xdebug')) {
            $this->markTestSkipped('ext/xdebug not installed');
        }
        
        if (ini_get('xdebug.scream') == 0) {
            $this->markTestSkipped('xdebug.scream turned off');
        }
        
        $mock = $this->container->mock('foo');
        $mock->shouldReceive('foo')->with('bar', 'baz');
        
        $mock->foo('spam', 'ham');
    }

}

class MockeryTest_InterMethod1
{
    public function doFirst() {
        return $this->doSecond();
    }

    private function doSecond() {
        return $this->doThird();
    }

    public function doThird() {
        return false;
    }
}

class MyService2
{
    public function login($user, $pass){}
    public function hasBookmarksTagged($tag){}
    public function addBookmark($uri, $tag){}
}

class Mockery_Duck {
    function quack(){}
    function swim(){}
}

class Mockery_Duck_Nonswimmer {
    function quack(){}
}

class Mockery_Demeterowski {
    public function foo() {
        return $this;
    }
    public function bar() {
        return $this;
    }
    public function baz() {
        return 'Ham!';
    }
}

class Mockery_UseDemeter {
    public function __construct($demeter) {
        $this->demeter = $demeter;
    }
    public function doit() {
        return $this->demeter->foo()->bar()->baz();
    }
    public function doitWithArgs() {
        return $this->demeter->foo("foo")->bar("bar")->baz("baz");
    }
}

class MockeryTest_Foo {
    public function foo() {}
}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

class ContainerTest extends PHPUnit_Framework_TestCase
{

    public function setup ()
    {
        $this->container = new \Mockery\Container;
    }

    public function teardown()
    {
        $this->container->mockery_close();
    }

    public function testSimplestMockCreation()
    {
        $m = $this->container->mock();
        $m->shouldReceive('foo')->andReturn('bar');
        $this->assertEquals('bar', $m->foo());
    }

    public function testNamedMocksAddNameToExceptions()
    {
        $m = $this->container->mock('Foo');
        $m->shouldReceive('foo')->with(1)->andReturn('bar');
        try {
            $m->foo();
        } catch (\Mockery\Exception $e) {
            $this->assertTrue((bool) preg_match("/Foo/", $e->getMessage()));
        }
    }

    public function testSimpleMockWithArrayDefs()
    {
        $m = $this->container->mock(array('foo'=>1,'bar'=>2));
        $this->assertEquals(1, $m->foo());
        $this->assertEquals(2, $m->bar());
    }

    public function testNamedMockWithArrayDefs()
    {
        $m = $this->container->mock('Foo', array('foo'=>1,'bar'=>2));
        $this->assertEquals(1, $m->foo());
        $this->assertEquals(2, $m->bar());
        try {
            $m->f();
        } catch (BadMethodCallException $e) {
            $this->assertTrue((bool) preg_match("/Foo/", $e->getMessage()));
        }
    }

    public function testNamedMockWithConstructorArgs()
    {
        $m = $this->container->mock("MockeryTest_ClassConstructor2[foo]", array($param1 = new stdClass()));
        $m->shouldReceive("foo")->andReturn(123);
        $this->assertEquals(123, $m->foo());
        $this->assertEquals($param1, $m->getParam1());
    }

    public function testNamedMockWithConstructorArgsAndArrayDefs()
    {
        $m = $this->container->mock(
            "MockeryTest_ClassConstructor2[foo]",
            array($param1 = new stdClass()),
            array("foo" => 123)
        );
        $this->assertEquals(123, $m->foo());
        $this->assertEquals($param1, $m->getParam1());
    }

    public function testNamedMockWithConstructorArgsWithInternalCallToMockedMethod()
    {
        $m = $this->container->mock("MockeryTest_ClassConstructor2[foo]", array($param1 = new stdClass()));
        $m->shouldReceive("foo")->andReturn(123);
        $this->assertEquals(123, $m->bar());
    }

    public function testNamedMockWithConstructorArgsButNoQuickDefsShouldLeaveConstructorIntact()
    {
        $m = $this->container->mock("MockeryTest_ClassConstructor2", array($param1 = new stdClass()));
        $m->shouldDeferMissing();
        $this->assertEquals($param1, $m->getParam1());
    }

    public function testNamedMockWithShouldDeferMissing()
    {
        $m = $this->container->mock("MockeryTest_ClassConstructor2", array($param1 = new stdClass()));
        $m->shouldDeferMissing();
        $this->assertEquals('foo', $m->bar());
        $m->shouldReceive("bar")->andReturn(123);
        $this->assertEquals(123, $m->bar());
    }

    /**
     * @expectedException BadMethodCallException
     */
    public function testNamedMockWithShouldDeferMissingThrowsIfNotAvailable()
    {
        $m = $this->container->mock("MockeryTest_ClassConstructor2", array($param1 = new stdClass()));
        $m->shouldDeferMissing();
        $m->foorbar123();
    }

    public function testMockingAKnownConcreteClassSoMockInheritsClassType()
    {
        $m = $this->container->mock('stdClass');
        $m->shouldReceive('foo')->andReturn('bar');
        $this->assertEquals('bar', $m->foo());
        $this->assertTrue($m instanceof stdClass);
    }

    public function testMockingAKnownUserClassSoMockInheritsClassType()
    {
        $m = $this->container->mock('MockeryTest_TestInheritedType');
        $this->assertTrue($m instanceof MockeryTest_TestInheritedType);
    }

    public function testMockingAConcreteObjectCreatesAPartialWithoutError()
    {
        $m = $this->container->mock(new stdClass);
        $m->shouldReceive('foo')->andReturn('bar');
        $this->assertEquals('bar', $m->foo());
        $this->assertTrue($m instanceof stdClass);
    }

    public function testCreatingAPartialAllowsDynamicExpectationsAndPassesThroughUnexpectedMethods()
    {
        $m = $this->container->mock(new MockeryTestFoo);
        $m->shouldReceive('bar')->andReturn('bar');
        $this->assertEquals('bar', $m->bar());
        $this->assertEquals('foo', $m->foo());
        $this->assertTrue($m instanceof MockeryTestFoo);
    }

    public function testCreatingAPartialAllowsExpectationsToInterceptCallsToImplementedMethods()
    {
        $m = $this->container->mock(new MockeryTestFoo2);
        $m->shouldReceive('bar')->andReturn('baz');
        $this->assertEquals('baz', $m->bar());
        $this->assertEquals('foo', $m->foo());
        $this->assertTrue($m instanceof MockeryTestFoo2);
    }

    public function testBlockForwardingToPartialObject()
    {
        $m = $this->container->mock(new MockeryTestBar1, array('foo'=>1, \Mockery\Container::BLOCKS => array('method1')));
        $this->assertSame($m, $m->method1());
    }

    public function testPartialWithArrayDefs()
    {
        $m = $this->container->mock(new MockeryTestBar1, array('foo'=>1, \Mockery\Container::BLOCKS => array('method1')));
        $this->assertEquals(1, $m->foo());
    }

    public function testPassingClosureAsFinalParameterUsedToDefineExpectations()
    {
        $m = $this->container->mock('foo', function($m) {
            $m->shouldReceive('foo')->once()->andReturn('bar');
        });
        $this->assertEquals('bar', $m->foo());
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testMockingAKnownConcreteFinalClassThrowsErrors_OnlyPartialMocksCanMockFinalElements()
    {
        $m = $this->container->mock('MockeryFoo3');
    }

    public function testMockingAKnownConcreteClassWithFinalMethodsThrowsNoException()
    {
        $m = $this->container->mock('MockeryFoo4');
    }

    /**
     * @group finalclass
     */
    public function testFinalClassesCanBePartialMocks()
    {
        $m = $this->container->mock(new MockeryFoo3);
        $m->shouldReceive('foo')->andReturn('baz');
        $this->assertEquals('baz', $m->foo());
        $this->assertFalse($m instanceof MockeryFoo3);
    }

    public function testSplClassWithFinalMethodsCanBeMocked()
    {
        $m = $this->container->mock('SplFileInfo');
        $m->shouldReceive('foo')->andReturn('baz');
        $this->assertEquals('baz', $m->foo());
        $this->assertTrue($m instanceof SplFileInfo);

    }

    public function testClassesWithFinalMethodsCanBeProxyPartialMocks()
    {
        $m = $this->container->mock(new MockeryFoo4);
        $m->shouldReceive('foo')->andReturn('baz');
        $this->assertEquals('baz', $m->foo());
        $this->assertEquals('bar', $m->bar());
        $this->assertTrue($m instanceof MockeryFoo4);
    }

    public function testClassesWithFinalMethodsCanBeProperPartialMocks()
    {
        $m = $this->container->mock('MockeryFoo4[bar]');
        $m->shouldReceive('bar')->andReturn('baz');
        $this->assertEquals('baz', $m->foo());
        $this->assertEquals('baz', $m->bar());
        $this->assertTrue($m instanceof MockeryFoo4);
    }

    public function testClassesWithFinalMethodsCanBeProperPartialMocksButFinalMethodsNotPartialed()
    {
        $m = $this->container->mock('MockeryFoo4[foo]');
        $m->shouldReceive('foo')->andReturn('foo');
        $this->assertEquals('baz', $m->foo()); // partial expectation ignored - will fail callcount assertion
        $this->assertTrue($m instanceof MockeryFoo4);
    }

    public function testSplfileinfoClassMockPassesUserExpectations()
    {
        $file = $this->container->mock('SplFileInfo[getFilename,getPathname,getExtension,getMTime]');
        $file->shouldReceive('getFilename')->once()->andReturn('foo');
        $file->shouldReceive('getPathname')->once()->andReturn('path/to/foo');
        $file->shouldReceive('getExtension')->once()->andReturn('css');
        $file->shouldReceive('getMTime')->once()->andReturn(time());
    }

    public function testCanMockInterface()
    {
        $m = $this->container->mock('MockeryTest_Interface');
        $this->assertTrue($m instanceof MockeryTest_Interface);
    }

    public function testCanMockSpl()
    {
        $m = $this->container->mock('\\SplFixedArray');
        $this->assertTrue($m instanceof \SplFixedArray);
    }

    public function testCanMockInterfaceWithAbstractMethod()
    {
        $m = $this->container->mock('MockeryTest_InterfaceWithAbstractMethod');
        $this->assertTrue($m instanceof MockeryTest_InterfaceWithAbstractMethod);
        $m->shouldReceive('foo')->andReturn(1);
        $this->assertEquals(1, $m->foo());
    }

    public function testCanMockAbstractWithAbstractProtectedMethod()
    {
        $m = $this->container->mock('MockeryTest_AbstractWithAbstractMethod');
        $this->assertTrue($m instanceof MockeryTest_AbstractWithAbstractMethod);
    }

    public function testCanMockInterfaceWithPublicStaticMethod()
    {
        $m = $this->container->mock('MockeryTest_InterfaceWithPublicStaticMethod');
        $this->assertTrue($m instanceof MockeryTest_InterfaceWithPublicStaticMethod);
    }

    public function testCanMockClassWithConstructor()
    {
        $m = $this->container->mock('MockeryTest_ClassConstructor');
        $this->assertTrue($m instanceof MockeryTest_ClassConstructor);
    }

    public function testCanMockClassWithConstructorNeedingClassArgs()
    {
        $m = $this->container->mock('MockeryTest_ClassConstructor2');
        $this->assertTrue($m instanceof MockeryTest_ClassConstructor2);
    }

    /**
     * @group partial
     */
    public function testCanPartiallyMockANormalClass()
    {
        $m = $this->container->mock('MockeryTest_PartialNormalClass[foo]');
        $this->assertTrue($m instanceof MockeryTest_PartialNormalClass);
        $m->shouldReceive('foo')->andReturn('cba');
        $this->assertEquals('abc', $m->bar());
        $this->assertEquals('cba', $m->foo());
    }

    /**
     * @group partial
     */
    public function testCanPartiallyMockAnAbstractClass()
    {
        $m = $this->container->mock('MockeryTest_PartialAbstractClass[foo]');
        $this->assertTrue($m instanceof MockeryTest_PartialAbstractClass);
        $m->shouldReceive('foo')->andReturn('cba');
        $this->assertEquals('abc', $m->bar());
        $this->assertEquals('cba', $m->foo());
    }

    /**
     * @group partial
     */
    public function testCanPartiallyMockANormalClassWith2Methods()
    {
        $m = $this->container->mock('MockeryTest_PartialNormalClass2[foo, baz]');
        $this->assertTrue($m instanceof MockeryTest_PartialNormalClass2);
        $m->shouldReceive('foo')->andReturn('cba');
        $m->shouldReceive('baz')->andReturn('cba');
        $this->assertEquals('abc', $m->bar());
        $this->assertEquals('cba', $m->foo());
        $this->assertEquals('cba', $m->baz());
    }

    /**
     * @group partial
     */
    public function testCanPartiallyMockAnAbstractClassWith2Methods()
    {
        $m = $this->container->mock('MockeryTest_PartialAbstractClass2[foo,baz]');
        $this->assertTrue($m instanceof MockeryTest_PartialAbstractClass2);
        $m->shouldReceive('foo')->andReturn('cba');
        $m->shouldReceive('baz')->andReturn('cba');
        $this->assertEquals('abc', $m->bar());
        $this->assertEquals('cba', $m->foo());
        $this->assertEquals('cba', $m->baz());
    }

    /**
     * @expectedException \Mockery\Exception
     * @group partial
     */
    public function testThrowsExceptionIfSettingExpectationForNonMockedMethodOfPartialMock()
    {
        $this->markTestSkipped('For now...');
        $m = $this->container->mock('MockeryTest_PartialNormalClass[foo]');
        $this->assertTrue($m instanceof MockeryTest_PartialNormalClass);
        $m->shouldReceive('bar')->andReturn('cba');
    }

    /**
     * @expectedException \Mockery\Exception
     * @group partial
     */
    public function testThrowsExceptionIfClassOrInterfaceForPartialMockDoesNotExist()
    {
        $m = $this->container->mock('MockeryTest_PartialNormalClassXYZ[foo]');
    }

    /**
     * @group issue/4
     */
    public function testCanMockClassContainingMagicCallMethod()
    {
        $m = $this->container->mock('MockeryTest_Call1');
        $this->assertTrue($m instanceof MockeryTest_Call1);
    }

    /**
     * @group issue/4
     */
    public function testCanMockClassContainingMagicCallMethodWithoutTypeHinting()
    {
        $m = $this->container->mock('MockeryTest_Call2');
        $this->assertTrue($m instanceof MockeryTest_Call2);
    }

    /**
     * @group issue/14
     */
    public function testCanMockClassContainingAPublicWakeupMethod()
    {
        $m = $this->container->mock('MockeryTest_Wakeup1');
        $this->assertTrue($m instanceof MockeryTest_Wakeup1);
    }

    /**
     * @group issue/18
     */
    public function testCanMockClassUsingMagicCallMethodsInPlaceOfNormalMethods()
    {
        $m = \Mockery::mock('Gateway');
        $m->shouldReceive('iDoSomethingReallyCoolHere');
        $m->iDoSomethingReallyCoolHere();
    }

    /**
     * @group issue/18
     */
    public function testCanPartialMockObjectUsingMagicCallMethodsInPlaceOfNormalMethods()
    {
        $m = \Mockery::mock(new Gateway);
        $m->shouldReceive('iDoSomethingReallyCoolHere');
        $m->iDoSomethingReallyCoolHere();
    }

    /**
     * @group issue/13
     */
    public function testCanMockClassWhereMethodHasReferencedParameter()
    {
        $m = \Mockery::mock(new MockeryTest_MethodParamRef);
    }

    /**
     * @group issue/13
     */
    public function testCanPartiallyMockObjectWhereMethodHasReferencedParameter()
    {
        $m = \Mockery::mock(new MockeryTest_MethodParamRef2);
    }

    /**
     * @group issue/11
     */
    public function testMockingAKnownConcreteClassCanBeGrantedAnArbitraryClassType()
    {
        $m = $this->container->mock('alias:MyNamespace\MyClass');
        $m->shouldReceive('foo')->andReturn('bar');
        $this->assertEquals('bar', $m->foo());
        $this->assertTrue($m instanceof MyNamespace\MyClass);
    }

    /**
     * @group issue/15
     */
    public function testCanMockMultipleInterfaces()
    {
        $m = $this->container->mock('MockeryTest_Interface1, MockeryTest_Interface2');
        $this->assertTrue($m instanceof MockeryTest_Interface1);
        $this->assertTrue($m instanceof MockeryTest_Interface2);
    }

    /**
     * @expectedException \Mockery\Exception
     */
    public function testMockingMultipleInterfacesThrowsExceptionWhenGivenNonExistingClassOrInterface()
    {
        $m = $this->container->mock('DoesNotExist, MockeryTest_Interface2');
        $this->assertTrue($m instanceof MockeryTest_Interface1);
        $this->assertTrue($m instanceof MockeryTest_Interface2);
    }

    /**
     * @group issue/15
     */
    public function testCanMockClassAndApplyMultipleInterfaces()
    {
        $m = $this->container->mock('MockeryTestFoo, MockeryTest_Interface1, MockeryTest_Interface2');
        $this->assertTrue($m instanceof MockeryTestFoo);
        $this->assertTrue($m instanceof MockeryTest_Interface1);
        $this->assertTrue($m instanceof MockeryTest_Interface2);
    }

    /**
     * @group issue/7
     *
     * Noted: We could complicate internally, but a blind class is better built
     * with a real class noted up front (stdClass is a perfect choice it is
     * behaviourless). Fine, it's a muddle - but we need to draw a line somewhere.
     */
    public function testCanMockStaticMethods()
    {
        \Mockery::setContainer($this->container);
        $m = $this->container->mock('alias:MyNamespace\MyClass2');
        $m->shouldReceive('staticFoo')->andReturn('bar');
        $this->assertEquals('bar', \MyNameSpace\MyClass2::staticFoo());
        \Mockery::resetContainer();
    }

    /**
     * @group issue/7
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testMockedStaticMethodsObeyMethodCounting()
    {
        \Mockery::setContainer($this->container);
        $m = $this->container->mock('alias:MyNamespace\MyClass3');
        $m->shouldReceive('staticFoo')->once()->andReturn('bar');
        $this->container->mockery_verify();
        \Mockery::resetContainer();
    }

    /**
     * @expectedException BadMethodCallException
     */
    public function testMockedStaticThrowsExceptionWhenMethodDoesNotExist(){
    	\Mockery::setContainer($this->container);
        $m = $this->container->mock('alias:MyNamespace\StaticNoMethod');
        $this->assertEquals('bar', \MyNameSpace\StaticNoMethod::staticFoo());
        \Mockery::resetContainer();
    }

    /**
     * @group issue/17
     */
    public function testMockingAllowsPublicPropertyStubbingOnRealClass()
    {
        $m = $this->container->mock('MockeryTestFoo');
        $m->foo = 'bar';
        $this->assertEquals('bar', $m->foo);
        //$this->assertTrue(array_key_exists('foo', $m->mockery_getMockableProperties()));
    }

    /**
     * @group issue/17
     */
    public function testMockingAllowsPublicPropertyStubbingOnNamedMock()
    {
        $m = $this->container->mock('Foo');
        $m->foo = 'bar';
        $this->assertEquals('bar', $m->foo);
        //$this->assertTrue(array_key_exists('foo', $m->mockery_getMockableProperties()));
    }

    /**
     * @group issue/17
     */
    public function testMockingAllowsPublicPropertyStubbingOnPartials()
    {
        $m = $this->container->mock(new stdClass);
        $m->foo = 'bar';
        $this->assertEquals('bar', $m->foo);
        //$this->assertTrue(array_key_exists('foo', $m->mockery_getMockableProperties()));
    }

    /**
     * @group issue/17
     */
    public function testMockingDoesNotStubNonStubbedPropertiesOnPartials()
    {
        $m = $this->container->mock(new MockeryTest_ExistingProperty);
        $this->assertEquals('bar', $m->foo);
        $this->assertFalse(array_key_exists('foo', $m->mockery_getMockableProperties()));
    }

    public function testCreationOfInstanceMock()
    {
        $m = $this->container->mock('overload:MyNamespace\MyClass4');
        $this->assertTrue($m instanceof \MyNamespace\MyClass4);
    }

    public function testInstantiationOfInstanceMock()
    {
        \Mockery::setContainer($this->container);
        $m = $this->container->mock('overload:MyNamespace\MyClass5');
        $instance = new \MyNamespace\MyClass5;
        $this->assertTrue($instance instanceof \MyNamespace\MyClass5);
        \Mockery::resetContainer();
    }

    public function testInstantiationOfInstanceMockImportsExpectations()
    {
        \Mockery::setContainer($this->container);
        $m = $this->container->mock('overload:MyNamespace\MyClass6');
        $m->shouldReceive('foo')->andReturn('bar');
        $instance = new \MyNamespace\MyClass6;
        $this->assertEquals('bar', $instance->foo());
        \Mockery::resetContainer();
    }

    public function testInstantiationOfInstanceMocksIgnoresVerificationOfOriginMock()
    {
        \Mockery::setContainer($this->container);
        $m = $this->container->mock('overload:MyNamespace\MyClass7');
        $m->shouldReceive('foo')->once()->andReturn('bar');
        $this->container->mockery_verify();
        \Mockery::resetContainer(); //should not throw an exception
    }

    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testInstantiationOfInstanceMocksAddsThemToContainerForVerification()
    {
        \Mockery::setContainer($this->container);
        $m = $this->container->mock('overload:MyNamespace\MyClass8');
        $m->shouldReceive('foo')->once();
        $instance = new \MyNamespace\MyClass8;
        $this->container->mockery_verify();
        \Mockery::resetContainer();
    }

    public function testInstantiationOfInstanceMocksDoesNotHaveCountValidatorCrossover()
    {
        \Mockery::setContainer($this->container);
        $m = $this->container->mock('overload:MyNamespace\MyClass9');
        $m->shouldReceive('foo')->once();
        $instance1 = new \MyNamespace\MyClass9;
        $instance2 = new \MyNamespace\MyClass9;
        $instance1->foo();
        $instance2->foo();
        $this->container->mockery_verify();
        \Mockery::resetContainer();
    }

    /**
     * @expectedException \Mockery\CountValidator\Exception
     */
    public function testInstantiationOfInstanceMocksDoesNotHaveCountValidatorCrossover2()
    {
        \Mockery::setContainer($this->container);
        $m = $this->container->mock('overload:MyNamespace\MyClass10');
        $m->shouldReceive('foo')->once();
        $instance1 = new \MyNamespace\MyClass10;
        $instance2 = new \MyNamespace\MyClass10;
        $instance1->foo();
        $this->container->mockery_verify();
        \Mockery::resetContainer();
    }

    public function testMethodParamsPassedByReferenceHaveReferencePreserved()
    {
        $m = $this->container->mock('MockeryTestRef1');
        $m->shouldReceive('foo')->with(
            \Mockery::on(function(&$a) {$a += 1;return true;}),
            \Mockery::any()
        );
        $a = 1;
        $b = 1;
        $m->foo($a, $b);
        $this->assertEquals(2, $a);
        $this->assertEquals(1, $b);
    }

    public function testCanOverrideExpectedParametersOfInternalPHPClassesToPreserveRefs()
    {
        if (!class_exists('MongoCollection', false)) $this->markTestSkipped('ext/mongo not installed');
        \Mockery::getConfiguration()->setInternalClassMethodParamMap(
            'MongoCollection', 'insert', array('&$data', '$options')
        );
        $m = $this->container->mock('MongoCollection');
        $m->shouldReceive('insert')->with(
            \Mockery::on(function(&$data) {$data['_id'] = 123; return true;}),
            \Mockery::type('array')
        );
        $data = array('a'=>1,'b'=>2);
        $m->insert($data, array());
        $this->assertTrue(isset($data['_id']));
        $this->assertEquals(123, $data['_id']);
        $this->container->mockery_verify();
        \Mockery::resetContainer();
    }

    /**
     * @group abstract
     */
    public function testCanMockAbstractClassWithAbstractPublicMethod()
    {
        $m = $this->container->mock('MockeryTest_AbstractWithAbstractPublicMethod');
        $this->assertTrue($m instanceof MockeryTest_AbstractWithAbstractPublicMethod);
    }

    /**
     * @issue issue/21
     */
    public function testClassDeclaringIssetDoesNotThrowException()
    {
        \Mockery::setContainer($this->container);
        $m = $this->container->mock('MockeryTest_IssetMethod');
        $this->container->mockery_verify();
        \Mockery::resetContainer();
    }

    /**
     * @issue issue/21
     */
    public function testClassDeclaringUnsetDoesNotThrowException()
    {
        \Mockery::setContainer($this->container);
        $m = $this->container->mock('MockeryTest_UnsetMethod');
        $this->container->mockery_verify();
        \Mockery::resetContainer();
    }

    /**
     * @issue issue/35
     */
    public function testCallingSelfOnlyReturnsLastMockCreatedOrCurrentMockBeingProgrammedSinceTheyAreOneAndTheSame()
    {
        \Mockery::setContainer($this->container);
        $m = $this->container->mock('MockeryTestFoo');
        $this->assertFalse($this->container->self() instanceof MockeryTestFoo2);
        //$m = $this->container->mock('MockeryTestFoo2');
        //$this->assertTrue($this->container->self() instanceof MockeryTestFoo2);
        //$m = $this->container->mock('MockeryTestFoo');
        //$this->assertFalse(\Mockery::self() instanceof MockeryTestFoo2);
        //$this->assertTrue(\Mockery::self() instanceof MockeryTestFoo);
        \Mockery::resetContainer();
    }

    /**
     * @issue issue/89
     */
    public function testCreatingMockOfClassWithExistingToStringMethodDoesntCreateClassWithTwoToStringMethods()
    {
        \Mockery::setContainer($this->container);
        $m = $this->container->mock('MockeryTest_WithToString'); // this would fatal
        $m->shouldReceive("__toString")->andReturn('dave');
        $this->assertEquals("dave", "$m");
    }

    public function testGetExpectationCount_freshContainer()
    {
        $this->assertEquals(0, $this->container->mockery_getExpectationCount());
    }

    public function testGetExpectationCount_simplestMock()
    {
        $m = $this->container->mock();
        $m->shouldReceive('foo')->andReturn('bar');
        $this->assertEquals(1, $this->container->mockery_getExpectationCount());
    }

    public function testMethodsReturningParamsByReferenceDoesNotErrorOut()
    {
        $this->container->mock('MockeryTest_ReturnByRef');
        $mock = $this->container->mock('MockeryTest_ReturnByRef');
        $mock->shouldReceive("get")->andReturn($var = 123);
        $this->assertSame($var, $mock->get());
    }

    public function testMockCallableTypeHint()
    {
		if(PHP_VERSION_ID >= 50400) {
        	$this->container->mock('MockeryTest_MockCallableTypeHint');
		}
    }

    public function testCanMockClassWithReservedWordMethod()
    {
        if (!extension_loaded("redis")) {
            $this->markTestSkipped(
                "phpredis not installed"
            );;
        }

        $this->container->mock("Redis");
    }

    public function testUndeclaredClassIsDeclared()
    {
        $this->assertFalse(class_exists("BlahBlah"));
        $mock = $this->container->mock("BlahBlah");
        $this->assertInstanceOf("BlahBlah", $mock);
    }

    public function testUndeclaredClassWithNamespaceIsDeclared()
    {
        $this->assertFalse(class_exists("MyClasses\Blah\BlahBlah"));
        $mock = $this->container->mock("MyClasses\Blah\BlahBlah");
        $this->assertInstanceOf("MyClasses\Blah\BlahBlah", $mock);
    }

    public function testUndeclaredClassWithNamespaceIncludingLeadingOperatorIsDeclared()
    {
        $this->assertFalse(class_exists("\MyClasses\DaveBlah\BlahBlah"));
        $mock = $this->container->mock("\MyClasses\DaveBlah\BlahBlah");
        $this->assertInstanceOf("\MyClasses\DaveBlah\BlahBlah", $mock);
    }

    public function testMockingPhpredisExtensionClassWorks()
    {
        if (!class_exists('Redis')) {
            $this->markTestSkipped('PHPRedis extension required for this test');
        }
        $m = $this->container->mock('Redis');
    }

    public function testIssetMappingUsingProxiedPartials_CheckNoExceptionThrown()
    {
        $var = $this->container->mock(new MockeryTestIsset_Bar());
        $mock = $this->container->mock(new MockeryTestIsset_Foo($var));
        $mock->shouldReceive('bar')->once();
        $mock->bar();
        $this->container->mockery_teardown(); // closed by teardown()
    }

    /**
     * @group traversable1
     */
    public function testCanMockInterfacesExtendingTraversable()
    {
        $mock = $this->container->mock('MockeryTest_InterfaceWithTraversable');
        $this->assertInstanceOf('MockeryTest_InterfaceWithTraversable', $mock);
        $this->assertInstanceOf('ArrayAccess', $mock);
        $this->assertInstanceOf('Countable', $mock);
        $this->assertInstanceOf('Traversable', $mock);
    }

    /**
     * @group traversable2
     */
    public function testCanMockInterfacesAlongsideTraversable()
    {
        $mock = $this->container->mock('stdClass, ArrayAccess, Countable, Traversable');
        $this->assertInstanceOf('stdClass', $mock);
        $this->assertInstanceOf('ArrayAccess', $mock);
        $this->assertInstanceOf('Countable', $mock);
        $this->assertInstanceOf('Traversable', $mock);
    }

    public function testMockingIteratorAggregateDoesNotImplementIterator()
    {
        $mock = $this->container->mock('MockeryTest_ImplementsIteratorAggregate');
        $this->assertInstanceOf('IteratorAggregate', $mock);
        $this->assertInstanceOf('Traversable', $mock);
        $this->assertNotInstanceOf('Iterator', $mock);
    }

    public function testMockingIteratorAggregateDoesNotImplementIteratorAlongside()
    {
        $mock = $this->container->mock('IteratorAggregate');
        $this->assertInstanceOf('IteratorAggregate', $mock);
        $this->assertInstanceOf('Traversable', $mock);
        $this->assertNotInstanceOf('Iterator', $mock);
    }

    public function testMockingIteratorDoesNotImplementIteratorAlongside()
    {
        $mock = $this->container->mock('Iterator');
        $this->assertInstanceOf('Iterator', $mock);
        $this->assertInstanceOf('Traversable', $mock);
    }

    public function testMockingIteratorDoesNotImplementIterator()
    {
        $mock = $this->container->mock('MockeryTest_ImplementsIterator');
        $this->assertInstanceOf('Iterator', $mock);
        $this->assertInstanceOf('Traversable', $mock);
    }

    public function testMockeryCloseForIllegalIssetFileInclude()
    {
        $m = \Mockery::mock('StdClass')
            ->shouldReceive('get')
            ->andReturn(false)
            ->getMock();
        $m->get();
        \Mockery::close();
    }

    public function testMockeryShouldDistinguishBetweenConstructorParamsAndClosures()
    {
        $mock = $this->container->mock('MockeryTest_ClassMultipleConstructorParams[dave]',
            array(new stdClass, 'bar'));
    }

    /** @group nette */
    public function testMockeryShouldNotMockCallstaticMagicMethod()
    {
        $mock = $this->container->mock('MockeryTest_CallStatic');
    }
}

class MockeryTest_CallStatic {
    public static function __callStatic($method, $args){}
}

class MockeryTest_ClassMultipleConstructorParams {
    public function __construct($a, $b) {}
    public function dave() {}
}

interface MockeryTest_InterfaceWithTraversable extends \ArrayAccess, \Traversable, \Countable {
    public function self();
}

class MockeryTestIsset_Bar {

    public function doSomething() {}
}

class MockeryTestIsset_Foo {

    private $var;

    public function __construct($var) {
        $this->var = $var;
    }

    public function __get($name) {
        $this->var->doSomething();
    }

    public function __isset($name) {
        return (bool) strlen($this->__get($name));
    }
}

class MockeryTest_IssetMethod
{
    protected $_properties = array();
    public function __construct() {}
    public function __isset($property) {
        return isset($this->_properties[$property]);
    }
}

class MockeryTest_UnsetMethod
{
    protected $_properties = array();
    public function __construct() {}
    public function __unset($property) {
        unset($this->_properties[$property]);
    }
}

class MockeryTestFoo {
    public function foo() { return 'foo'; }
}

class MockeryTestFoo2 {
    public function foo() { return 'foo'; }
    public function bar() { return 'bar'; }
}

final class MockeryFoo3 {
    public function foo() { return 'baz'; }
}

class MockeryFoo4 {
    final public function foo() { return 'baz'; }
    public function bar() { return 'bar'; }
}

interface MockeryTest_Interface {}
interface MockeryTest_Interface1 {}
interface MockeryTest_Interface2 {}

interface MockeryTest_InterfaceWithAbstractMethod
{
    public function set();
}

interface MockeryTest_InterfaceWithPublicStaticMethod
{
    public static function self();
}

abstract class MockeryTest_AbstractWithAbstractMethod
{
    abstract protected function set();
}

class MockeryTest_ClassConstructor {
    public function __construct($param1) {}
}

class MockeryTest_ClassConstructor2 {
    protected $param1;
    public function __construct(stdClass $param1) { $this->param1 = $param1; }
    public function getParam1() { return $this->param1; }
    public function foo() { return 'foo'; }
    public function bar() { return $this->foo(); }
}

class MockeryTest_Call1 {
    public function __call($method, array $params) {}
}

class MockeryTest_Call2 {
    public function __call($method, $params) {}
}

class MockeryTest_Wakeup1 {
    public function __construct() {}
    public function __wakeup() {}
}

class MockeryTest_ExistingProperty {
    public $foo = 'bar';
}
abstract class MockeryTest_AbstractWithAbstractPublicMethod{
    abstract public function foo($a, $b);
}

// issue/18
class SoCool
{
    public function iDoSomethingReallyCoolHere()
    {
        return 3;
    }
}
class Gateway
{
    public function __call($method, $args)
    {
        $m = new SoCool();
        return call_user_func_array(array($m, $method), $args);
    }
}

class MockeryTestBar1 {
    public function method1()
    {
        return $this;
    }
}

class MockeryTest_ReturnByRef {
    public $i = 0;
    public function &get()
    {
        return $this->$i;
    }
}

class MockeryTest_MethodParamRef {
    public function method1(&$foo){return true;}
}
class MockeryTest_MethodParamRef2 {
    public function method1(&$foo){return true;}
}
class MockeryTestRef1 {
    public function foo(&$a, $b) {}
}

class MockeryTest_PartialNormalClass {
    public function foo() {return 'abc';}
    public function bar() {return 'abc';}
}

abstract class MockeryTest_PartialAbstractClass {
    abstract public function foo();
    public function bar() {return 'abc';}
}

class MockeryTest_PartialNormalClass2 {
    public function foo() {return 'abc';}
    public function bar() {return 'abc';}
    public function baz() {return 'abc';}
}

abstract class MockeryTest_PartialAbstractClass2 {
    abstract public function foo();
    public function bar() {return 'abc';}
    abstract public function baz();
}

class MockeryTest_TestInheritedType {}

if(PHP_VERSION_ID >= 50400) {
    class MockeryTest_MockCallableTypeHint {
        public function foo(callable $baz) {$baz();}
        public function bar(callable $callback = null) {$callback();}
    }
}

class MockeryTest_WithToString {
    public function __toString() {}
}

class MockeryTest_ImplementsIteratorAggregate implements \IteratorAggregate {
    public function getIterator()
    {
        return new \ArrayIterator(array());
    }
}

class MockeryTest_ImplementsIterator implements \Iterator {
    public function rewind(){}
    public function current(){}
    public function key(){}
    public function next(){}
    public function valid(){}
}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2011 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

class HamcrestExpectationTest extends PHPUnit_Framework_TestCase
{

    public function setup ()
    {
        $this->container = new \Mockery\Container;
        $this->mock = $this->container->mock('foo');
    }
    
    public function teardown()
    {
        \Mockery::getConfiguration()->allowMockingNonExistentMethods(true);
        $this->container->mockery_close();
    }
    
    /** Just a quickie roundup of a few Hamcrest matchers to check nothing obvious out of place **/
    
    public function testAnythingConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(anything())->once();
        $this->mock->foo(2);
        $this->container->mockery_verify();
    }
    
    public function testGreaterThanConstraintMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(greaterThan(1))->once();
        $this->mock->foo(2);
        $this->container->mockery_verify();
    }
    
    /**
     * @expectedException Mockery\Exception
     */
    public function testGreaterThanConstraintNotMatchesArgument()
    {
        $this->mock->shouldReceive('foo')->with(greaterThan(1))->once();
        $this->mock->foo(1);
        $this->container->mockery_verify();
    }
    
}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
 */

class WithFormatterExpectationTest extends PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider formatObjectsDataProvider
     */
    public function testFormatObjects($args, $expected)
    {
        $this->assertEquals(
            $expected,
            Mockery::formatObjects($args)
        );
    }

    public function formatObjectsDataProvider()
    {
        return array(
            array(
                array(null),
                ''
            ),
            array(
                array('a string', 98768, array('a', 'nother', 'array')),
                ''
            )
        );
    }

}
<?php
/**
 * Mockery
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://github.com/padraic/mockery/master/LICENSE
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to padraic@php.net so we can send you a copy immediately.
 *
 * @category   Mockery
 * @package    Mockery
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
 * @license    http://github.com/padraic/mutateme/master/LICENSE New BSD License
 */

/*
 * Set error reporting to the level to which Mockery code must comply.
 */
error_reporting(E_ALL);

/*
 * Determine the root, library, and tests directories of the framework
 * distribution.
 */
$root    = realpath(dirname(dirname(__FILE__)));
$library = "$root/library";
$tests   = "$root/tests";

/**
 * Check that --dev composer installation was done
 */
if (!file_exists($root . '/vendor/autoload.php')) {
    throw new Exception(
        'Please run "php composer.phar install --dev" in root directory '
        . 'to setup unit test dependencies before running the tests'
    );
}

/*
 * Prepend the Mutateme library/ and tests/ directories to the
 * include_path. This allows the tests to run out of the box and helps prevent
 * loading other copies of the code and tests that would supercede
 * this copy.
 */
$path = array(
    $library,
    $tests,
    get_include_path(),
);
set_include_path(implode(PATH_SEPARATOR, $path));

if (defined('TESTS_GENERATE_REPORT') && TESTS_GENERATE_REPORT === true &&
    version_compare(PHPUnit_Runner_Version::id(), '3.1.6', '>=')) {

    /*
     * Add Mutateme library/ directory to the PHPUnit code coverage
     * whitelist. This has the effect that only production code source files
     * appear in the code coverage report and that all production code source
     * files, even those that are not covered by a test yet, are processed.
     */
    PHPUnit_Util_Filter::addDirectoryToWhitelist($library);

    /*
     * Omit from code coverage reports the contents of the tests directory
     */
    foreach (array('.php', '.phtml', '.csv', '.inc') as $suffix) {
        PHPUnit_Util_Filter::addDirectoryToFilter($tests, $suffix);
    }
    PHPUnit_Util_Filter::addDirectoryToFilter(PEAR_INSTALL_DIR);
    PHPUnit_Util_Filter::addDirectoryToFilter(PHP_LIBDIR);
}

require __DIR__.'/../vendor/autoload.php';

/*
 * Unset global variables that are no longer needed.
 */
unset($root, $library, $tests, $path);

<phpunit bootstrap="./Bootstrap.php">
    <testsuite name="Mockery Test Suite">
        <directory>./</directory>
    </testsuite>

    <groups>
        <exclude>
            <group>disable</group>
        </exclude>
    </groups>

    <filter>
        <whitelist>
            <directory suffix=".php">../library/</directory>
        </whitelist>
    </filter>
    <listeners>
        <listener
            class='Mockery\Adapter\Phpunit\TestListener'
            file='../library/Mockery/Adapter/Phpunit/TestListener.php'/>
    </listeners>
</phpunit>

<?php

use \Mockery as M;

require_once 'Starship.php';

class StarshipTest extends PHPUnit_Framework_TestCase
{
    public function testEngineeringResponseToEnteringOrbit()
    {
        $mock = M::mock('Engineering');
        $mock->shouldReceive('disengageWarp')->once()->ordered();
        $mock->shouldReceive('divertPower')->with(0.40, 'sensors')->once()->ordered();
        $mock->shouldReceive('divertPower')->with(0.30, 'auxengines')->once()->ordered();
        $mock->shouldReceive('runDiagnosticLevel')->with(1)->once()->ordered();
        $mock->shouldReceive('runDiagnosticLevel')->with(M::type('int'))->zeroOrMoreTimes();
        
        $starship = new Starship($mock);
        $starship->enterOrbit();
    }
    
}
<?php

set_include_path(
    dirname(__FILE__) . '/../../library'
    . PATH_SEPARATOR . get_include_path()
);

require_once 'Mockery/Loader.php';

$loader = new \Mockery\Loader;
$loader->register();
<phpunit bootstrap="./Bootstrap.php">
    <testsuite name="Starship Test Suite">
        <directory>./</directory>
    </testsuite>
    <listeners>
        <listener class="\Mockery\Adapter\Phpunit\TestListener"
            file="Mockery/Adapter/Phpunit/TestListener.php">
        </listener>
    </listeners>
</phpunit>
<?php

class Starship
{

    protected $_engineering = null;

    public function __construct($engineering)
    {
        $this->_engineering = $engineering;
    }

    public function enterOrbit()
    {
        $this->_engineering->disengageWarp();
        $this->_engineering->runDiagnosticLevel(5);
        $this->_engineering->divertPower(0.40, 'sensors');
        $this->_engineering->divertPower(0.30, 'auxengines');
        $this->_engineering->runDiagnosticLevel(1);
        
        // We can add more runDiagnosticLevel() calls without failing the test
        // anywhere above since they are unordered.
    }

}
#!/usr/bin/env php
<?php
require_once __DIR__.'/bin/phpdoc.php'; __HALT_COMPILER();#!/usr/bin/env php
"<?php
throw new \LogicException('This PHAR file can only be used from the CLI.');
__HALT_COMPILER();ZxXє}f~],   GBMB